summaryrefslogtreecommitdiffstats
path: root/media/libavextensions/stagefright/AVUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libavextensions/stagefright/AVUtils.cpp')
-rw-r--r--media/libavextensions/stagefright/AVUtils.cpp267
1 files changed, 253 insertions, 14 deletions
diff --git a/media/libavextensions/stagefright/AVUtils.cpp b/media/libavextensions/stagefright/AVUtils.cpp
index 2d5208f..c36e0bb 100644
--- a/media/libavextensions/stagefright/AVUtils.cpp
+++ b/media/libavextensions/stagefright/AVUtils.cpp
@@ -39,52 +39,291 @@
#include <media/stagefright/ACodec.h>
#include <media/stagefright/MediaCodec.h>
+#ifdef QCOM_HARDWARE
+#include "QCMediaDefs.h"
+#include "QCMetaData.h"
+#endif
+
#include "common/ExtensionsLoader.hpp"
#include "stagefright/AVExtensions.h"
namespace android {
+enum MetaKeyType{
+ INT32, INT64, STRING, DATA, CSD
+};
+
+struct MetaKeyEntry{
+ int MetaKey;
+ const char* MsgKey;
+ MetaKeyType KeyType;
+};
+
+static const MetaKeyEntry MetaKeyTable[] {
+#ifdef QCOM_HARDWARE
+ {kKeyAacCodecSpecificData , "aac-codec-specific-data", CSD},
+ {kKeyDivXVersion , "divx-version" , INT32}, // int32_t
+ {kKeyDivXDrm , "divx-drm" , DATA}, // void *
+ {kKeyWMAEncodeOpt , "wma-encode-opt" , INT32}, // int32_t
+ {kKeyWMABlockAlign , "wma-block-align" , INT32}, // int32_t
+ {kKeyWMAAdvEncOpt1 , "wma-adv-enc-opt1" , INT32}, // int16_t
+ {kKeyWMAAdvEncOpt2 , "wma-adv-enc-opt2" , INT32}, // int32_t
+ {kKeyWMAFormatTag , "wma-format-tag" , INT32}, // int32_t
+ {kKeyWMABitspersample , "wma-bits-per-sample" , INT32}, // int32_t
+ {kKeyWMAVirPktSize , "wma-vir-pkt-size" , INT32}, // int32_t
+ {kKeyWMAChannelMask , "wma-channel-mask" , INT32}, // int32_t
+ {kKeyFileFormat , "file-format" , STRING}, // cstring
+
+ {kkeyAacFormatAdif , "aac-format-adif" , INT32}, // bool (int32_t)
+ {kkeyAacFormatLtp , "aac-format-ltp" , INT32},
+
+ //DTS subtype
+ {kKeyDTSSubtype , "dts-subtype" , INT32}, //int32_t
+
+ //Extractor sets this
+ {kKeyUseArbitraryMode , "use-arbitrary-mode" , INT32}, //bool (int32_t)
+ {kKeySmoothStreaming , "smooth-streaming" , INT32}, //bool (int32_t)
+ {kKeyHFR , "hfr" , INT32}, // int32_t
+#endif
+
+
+ {kKeyBitRate , "bitrate" , INT32},
+ {kKeySampleRate , "sample-rate" , INT32},
+ {kKeyChannelCount , "channel-count" , INT32},
+ {kKeyRawCodecSpecificData , "raw-codec-specific-data", CSD},
+
+ {kKeyBitsPerSample , "bits-per-sample" , INT32},
+ {kKeyCodecId , "codec-id" , INT32},
+ {kKeySampleFormat , "sample-format" , INT32},
+ {kKeyBlockAlign , "block-align" , INT32},
+ {kKeyCodedSampleBits , "coded-sample-bits" , INT32},
+ {kKeyAACAOT , "aac-profile" , INT32},
+ {kKeyRVVersion , "rv-version" , INT32},
+ {kKeyWMAVersion , "wma-version" , INT32}, // int32_t
+ {kKeyWMVVersion , "wmv-version" , INT32},
+};
+
status_t AVUtils::convertMetaDataToMessage(
- const sp<MetaData> &, sp<AMessage> *) {
+ const sp<MetaData> &meta, sp<AMessage> *format) {
+ const char * str_val;
+ int32_t int32_val;
+ int64_t int64_val;
+ uint32_t data_type;
+ const void * data;
+ size_t size;
+ static const size_t numMetaKeys =
+ sizeof(MetaKeyTable) / sizeof(MetaKeyTable[0]);
+ size_t i;
+ for (i = 0; i < numMetaKeys; ++i) {
+ if (MetaKeyTable[i].KeyType == INT32 &&
+ meta->findInt32(MetaKeyTable[i].MetaKey, &int32_val)) {
+ ALOGV("found metakey %s of type int32", MetaKeyTable[i].MsgKey);
+ format->get()->setInt32(MetaKeyTable[i].MsgKey, int32_val);
+ } else if (MetaKeyTable[i].KeyType == INT64 &&
+ meta->findInt64(MetaKeyTable[i].MetaKey, &int64_val)) {
+ ALOGV("found metakey %s of type int64", MetaKeyTable[i].MsgKey);
+ format->get()->setInt64(MetaKeyTable[i].MsgKey, int64_val);
+ } else if (MetaKeyTable[i].KeyType == STRING &&
+ meta->findCString(MetaKeyTable[i].MetaKey, &str_val)) {
+ ALOGV("found metakey %s of type string", MetaKeyTable[i].MsgKey);
+ format->get()->setString(MetaKeyTable[i].MsgKey, str_val);
+ } else if ( (MetaKeyTable[i].KeyType == DATA ||
+ MetaKeyTable[i].KeyType == CSD) &&
+ meta->findData(MetaKeyTable[i].MetaKey, &data_type, &data, &size)) {
+ ALOGV("found metakey %s of type data", MetaKeyTable[i].MsgKey);
+ if (MetaKeyTable[i].KeyType == CSD) {
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+ if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+ sp<ABuffer> buffer = new ABuffer(size);
+ memcpy(buffer->data(), data, size);
+ buffer->meta()->setInt32("csd", true);
+ buffer->meta()->setInt64("timeUs", 0);
+ format->get()->setBuffer("csd-0", buffer);
+ } else {
+ const uint8_t *ptr = (const uint8_t *)data;
+ CHECK(size >= 8);
+ int seqLength = 0, picLength = 0;
+ for (size_t i = 4; i < (size - 4); i++)
+ {
+ if ((*(ptr + i) == 0) && (*(ptr + i + 1) == 0) &&
+ (*(ptr + i + 2) == 0) && (*(ptr + i + 3) == 1))
+ seqLength = i;
+ }
+ sp<ABuffer> buffer = new ABuffer(seqLength);
+ memcpy(buffer->data(), data, seqLength);
+ buffer->meta()->setInt32("csd", true);
+ buffer->meta()->setInt64("timeUs", 0);
+ format->get()->setBuffer("csd-0", buffer);
+ picLength=size-seqLength;
+ sp<ABuffer> buffer1 = new ABuffer(picLength);
+ memcpy(buffer1->data(), (const uint8_t *)data + seqLength, picLength);
+ buffer1->meta()->setInt32("csd", true);
+ buffer1->meta()->setInt64("timeUs", 0);
+ format->get()->setBuffer("csd-1", buffer1);
+ }
+ } else {
+ sp<ABuffer> buffer = new ABuffer(size);
+ memcpy(buffer->data(), data, size);
+ format->get()->setBuffer(MetaKeyTable[i].MsgKey, buffer);
+ }
+ }
+ }
return OK;
}
+struct mime_conv_t {
+ const char* mime;
+ audio_format_t format;
+};
+
+static const struct mime_conv_t mimeLookup[] = {
+ { MEDIA_MIMETYPE_AUDIO_MPEG, AUDIO_FORMAT_MP3 },
+ { MEDIA_MIMETYPE_AUDIO_RAW, AUDIO_FORMAT_PCM_16_BIT },
+ { MEDIA_MIMETYPE_AUDIO_AMR_NB, AUDIO_FORMAT_AMR_NB },
+ { MEDIA_MIMETYPE_AUDIO_AMR_WB, AUDIO_FORMAT_AMR_WB },
+ { MEDIA_MIMETYPE_AUDIO_AAC, AUDIO_FORMAT_AAC },
+ { MEDIA_MIMETYPE_AUDIO_VORBIS, AUDIO_FORMAT_VORBIS },
+ { MEDIA_MIMETYPE_AUDIO_OPUS, AUDIO_FORMAT_OPUS},
+#ifdef QCOM_HARDWARE
+ { MEDIA_MIMETYPE_AUDIO_AC3, AUDIO_FORMAT_AC3 },
+ { MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS, AUDIO_FORMAT_AMR_WB_PLUS },
+ { MEDIA_MIMETYPE_AUDIO_DTS, AUDIO_FORMAT_DTS },
+ { MEDIA_MIMETYPE_AUDIO_EAC3, AUDIO_FORMAT_E_AC3 },
+ { MEDIA_MIMETYPE_AUDIO_EVRC, AUDIO_FORMAT_EVRC },
+ { MEDIA_MIMETYPE_AUDIO_QCELP, AUDIO_FORMAT_QCELP },
+ { MEDIA_MIMETYPE_AUDIO_WMA, AUDIO_FORMAT_WMA },
+ { MEDIA_MIMETYPE_AUDIO_FLAC, AUDIO_FORMAT_FLAC },
+ { MEDIA_MIMETYPE_CONTAINER_QTIFLAC, AUDIO_FORMAT_FLAC },
+#ifdef DOLBY_UDC
+ { MEDIA_MIMETYPE_AUDIO_EAC3_JOC, AUDIO_FORMAT_E_AC3_JOC },
+#endif
+#endif
+ { 0, AUDIO_FORMAT_INVALID }
+};
+
status_t AVUtils::mapMimeToAudioFormat(
- audio_format_t&, const char* ) {
- return OK;
+ audio_format_t& format, const char* mime) {
+ const struct mime_conv_t* p = &mimeLookup[0];
+ while (p->mime != NULL) {
+ if (0 == strcasecmp(mime, p->mime)) {
+ format = p->format;
+ return OK;
+ }
+ ++p;
+ }
+
+ return BAD_VALUE;
}
status_t AVUtils::sendMetaDataToHal(
- const sp<MetaData>&, AudioParameter *){
- return OK;
+ const sp<MetaData>& meta, AudioParameter *param){
+#ifdef FLAC_OFFLOAD_ENABLED
+ int32_t minBlkSize, maxBlkSize, minFrmSize, maxFrmSize; //FLAC params
+ if (meta->findInt32(kKeyMinBlkSize, &minBlkSize)) {
+ param.addInt(String8(AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE), minBlkSize);
+ }
+ if (meta->findInt32(kKeyMaxBlkSize, &maxBlkSize)) {
+ param.addInt(String8(AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE), maxBlkSize);
+ }
+ if (meta->findInt32(kKeyMinFrmSize, &minFrmSize)) {
+ param.addInt(String8(AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE), minFrmSize);
+ }
+ if (meta->findInt32(kKeyMaxFrmSize, &maxFrmSize)) {
+ param.addInt(String8(AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE), maxFrmSize);
+ }
+#else
+ (void)meta;
+ (void)param;
+#endif
+ return OK;
+}
+
+bool AVUtils::is24bitPCMOffloadEnabled() {
+ char propPCMOfload[PROPERTY_VALUE_MAX] = {0};
+ property_get("audio.offload.pcm.24bit.enable", propPCMOfload, "0");
+ if (!strncmp(propPCMOfload, "true", 4) || atoi(propPCMOfload))
+ return true;
+ else
+ return false;
+}
+
+bool AVUtils::is16bitPCMOffloadEnabled() {
+ char propPCMOfload[PROPERTY_VALUE_MAX] = {0};
+ property_get("audio.offload.pcm.16bit.enable", propPCMOfload, "0");
+ if (!strncmp(propPCMOfload, "true", 4) || atoi(propPCMOfload))
+ return true;
+ else
+ return false;
}
-bool AVUtils::is24bitPCMOffloadEnabled() {return false;}
-bool AVUtils::is16bitPCMOffloadEnabled() {return false;}
-int AVUtils::getAudioSampleBits(const sp<MetaData> &) {
- return 16;
+int AVUtils::getAudioSampleBits(const sp<MetaData> &meta) {
+ int32_t bits = 16;
+ audio_format_t audioFormat = AUDIO_FORMAT_INVALID;
+ if (meta->findInt32('pfmt', (int32_t *)&audioFormat)) {
+ bits = audio_bytes_per_sample(audioFormat) * 8;
+ } else if (meta->findInt32(kKeyBitsPerSample, &bits)) {
+ return bits;
+ }
+ return bits;
}
int AVUtils::getAudioSampleBits(const sp<AMessage> &format) {
int32_t bits = 16;
- format->findInt32("bits-per-sample", &bits);
+ audio_format_t audioFormat = AUDIO_FORMAT_INVALID;
+ if (format->findInt32("pcm-format", (int32_t *)&audioFormat)) {
+ bits = audio_bytes_per_sample(audioFormat) * 8;
+ } else if (format->findInt32("bits-per-sample", &bits)) {
+ return bits;
+ }
return bits;
}
-void AVUtils::setPcmSampleBits(const sp<AMessage> &, int32_t /*bitWidth*/) {
+void AVUtils::setPcmSampleBits(const sp<AMessage> &format, int32_t bitWidth) {
+ format->setInt32("bits-per-sample", bitWidth);
}
-void AVUtils::setPcmSampleBits(const sp<MetaData> &, int32_t /*bitWidth*/) {
+void AVUtils::setPcmSampleBits(const sp<MetaData> &meta, int32_t bitWidth) {
+ meta->setInt32(kKeyBitsPerSample, bitWidth);
}
audio_format_t AVUtils::updateAudioFormat(audio_format_t audioFormat,
- const sp<MetaData> &){
+ const sp<MetaData> &meta){
+ int32_t bits = getAudioSampleBits(meta);
+
+ ALOGV("updateAudioFormat %x %d", audioFormat, bits);
+ meta->dumpToLog();
+
+ // Override audio format for PCM offload
+ if (audio_is_linear_pcm(audioFormat)) {
+ if (bits > 16 && is24bitPCMOffloadEnabled()) {
+ audioFormat = AUDIO_FORMAT_PCM_24_BIT_OFFLOAD;
+ meta->setInt32(kKeyBitsPerSample, 24);
+ } else if (bits == 16 && is16bitPCMOffloadEnabled()) {
+ audioFormat = AUDIO_FORMAT_PCM_16_BIT_OFFLOAD;
+ }
+ }
+
return audioFormat;
}
audio_format_t AVUtils::updateAudioFormat(audio_format_t audioFormat,
- const sp<AMessage> &){
+ const sp<AMessage> &format){
+ int32_t bits = getAudioSampleBits(format);
+
+ ALOGV("updateAudioFormat %x %d %s", audioFormat, bits, format->debugString().c_str());
+
+ // Override audio format for PCM offload
+ if (audio_is_linear_pcm(audioFormat)) {
+ if (bits > 16 && is24bitPCMOffloadEnabled()) {
+ audioFormat = AUDIO_FORMAT_PCM_24_BIT_OFFLOAD;
+ format->setInt32("bits-per-sample", 24);
+ } else if (bits == 16 && is16bitPCMOffloadEnabled()) {
+ audioFormat = AUDIO_FORMAT_PCM_16_BIT_OFFLOAD;
+ }
+ }
+
return audioFormat;
}