summaryrefslogtreecommitdiffstats
path: root/media/libavextensions
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2015-12-09 20:44:26 -0800
committerSteve Kondik <steve@cyngn.com>2015-12-13 13:16:01 -0800
commit6dde130280d6ead297170211b005cc809e7f7bde (patch)
treea2053b10d736cadc85ce1adfe18d6256875da325 /media/libavextensions
parentfb9765480b10aaf39ac82149abe28d1805e1fe92 (diff)
downloadframeworks_av-6dde130280d6ead297170211b005cc809e7f7bde.zip
frameworks_av-6dde130280d6ead297170211b005cc809e7f7bde.tar.gz
frameworks_av-6dde130280d6ead297170211b005cc809e7f7bde.tar.bz2
stagefright: Resurrect PCM offload
* Forward-port the open-source code from L which was moved to closed-source in M. This is being done out of necessity- the architecture chosen by Qualcomm is not optimal and doesn't work well with a singular codebase which attempts to service a large number of devices. * This patch brings in the code to support PCM offload (AudioFlinger bypass). This allows for playback of high resolution clips without decimation stages, and enables reduced power consumption for audio pipelines which take advantage of the Hexagon DSP (effects). Change-Id: I0ef15fc3df538ab723f3c12ce0ed71d0e607c99e
Diffstat (limited to 'media/libavextensions')
-rw-r--r--media/libavextensions/Android.mk8
-rw-r--r--media/libavextensions/media/AVMediaExtensions.h5
-rw-r--r--media/libavextensions/mediaplayerservice/AVNuUtils.cpp257
-rw-r--r--media/libavextensions/stagefright/AVUtils.cpp267
4 files changed, 496 insertions, 41 deletions
diff --git a/media/libavextensions/Android.mk b/media/libavextensions/Android.mk
index 0b01669..a39a76e 100644
--- a/media/libavextensions/Android.mk
+++ b/media/libavextensions/Android.mk
@@ -22,7 +22,7 @@ ifeq ($(TARGET_ENABLE_QC_AV_ENHANCEMENTS),true)
endif
LOCAL_MODULE:= libavextensions
-LOCAL_CLANG := false
+LOCAL_CFLAGS += -DLOG_NDEBUG=0
LOCAL_MODULE_TAGS := optional
@@ -41,6 +41,7 @@ LOCAL_C_INCLUDES:= \
$(TOP)/frameworks/native/include/media/hardware \
$(TOP)/frameworks/native/include/media/openmax \
$(TOP)/external/flac/include \
+ $(TOP)/system/media/audio_utils/include \
$(TOP)/$(call project-path-for,qcom-media)/mm-core/inc
LOCAL_CFLAGS += -Wno-multichar -Werror
@@ -50,7 +51,7 @@ ifeq ($(TARGET_ENABLE_QC_AV_ENHANCEMENTS),true)
endif
LOCAL_MODULE:= libavmediaextentions
-LOCAL_CLANG := false
+LOCAL_CFLAGS += -DLOG_NDEBUG=0
LOCAL_MODULE_TAGS := optional
@@ -75,6 +76,7 @@ LOCAL_C_INCLUDES:= \
$(TOP)/frameworks/native/include/media/hardware \
$(TOP)/frameworks/native/include/media/openmax \
$(TOP)/external/flac/include \
+ $(TOP)/system/media/audio_utils/include \
$(TOP)/$(call project-path-for,qcom-media)/mm-core/inc
LOCAL_CFLAGS += -Wno-multichar -Werror
@@ -88,7 +90,7 @@ ifeq ($(TARGET_BOARD_PLATFORM),msm8974)
endif
LOCAL_MODULE:= libavmediaserviceextensions
-LOCAL_CLANG := false
+LOCAL_CFLAGS += -DLOG_NDEBUG=0
LOCAL_MODULE_TAGS := optional
diff --git a/media/libavextensions/media/AVMediaExtensions.h b/media/libavextensions/media/AVMediaExtensions.h
index 9161fae..d48feec 100644
--- a/media/libavextensions/media/AVMediaExtensions.h
+++ b/media/libavextensions/media/AVMediaExtensions.h
@@ -33,6 +33,7 @@
#include <common/AVExtensionsCommon.h>
#include <hardware/audio.h>
#include <media/AudioTrack.h>
+#include <audio_utils/format.h>
namespace android {
@@ -43,8 +44,8 @@ class Parcel;
*/
struct AVMediaUtils {
- virtual bool AudioTrackIsPcmOffloaded(const audio_format_t /*format*/) {
- return false;
+ virtual bool AudioTrackIsPcmOffloaded(const audio_format_t format) {
+ return audio_is_offload_pcm(format);
}
virtual status_t AudioTrackGetPosition(AudioTrack* /*track*/,
uint32_t* /*position*/) {
diff --git a/media/libavextensions/mediaplayerservice/AVNuUtils.cpp b/media/libavextensions/mediaplayerservice/AVNuUtils.cpp
index a8defee..8a78767 100644
--- a/media/libavextensions/mediaplayerservice/AVNuUtils.cpp
+++ b/media/libavextensions/mediaplayerservice/AVNuUtils.cpp
@@ -30,10 +30,18 @@
#define LOG_TAG "AVNuUtils"
#include <utils/Log.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/foundation/ABitReader.h>
#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
+#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/OMXCodec.h>
+#include <cutils/properties.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/MediaProfiles.h>
+#include <media/stagefright/Utils.h>
+
+#include <audio_utils/format.h>
#include <nuplayer/NuPlayer.h>
#include <nuplayer/NuPlayerDecoderBase.h>
@@ -46,12 +54,116 @@
namespace android {
+static bool 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;
+}
+
+static bool 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;
+}
+
sp<MetaData> AVNuUtils::createPCMMetaFromSource(const sp<MetaData> &sMeta) {
- return sMeta;
+ sp<MetaData> tPCMMeta = new MetaData;
+ //hard code as RAW
+ tPCMMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
+
+ int32_t bits = 16;
+ sMeta->findInt32(kKeyBitsPerSample, &bits);
+ tPCMMeta->setInt32(kKeyBitsPerSample, bits > 24 ? 24 : bits);
+
+ if (sMeta == NULL) {
+ ALOGW("no meta returning dummy meta");
+ return tPCMMeta;
+ }
+
+ int32_t srate = -1;
+ if (!sMeta->findInt32(kKeySampleRate, &srate)) {
+ ALOGV("No sample rate");
+ }
+ tPCMMeta->setInt32(kKeySampleRate, srate);
+
+ int32_t cmask = 0;
+ if (!sMeta->findInt32(kKeyChannelMask, &cmask) || (cmask == 0)) {
+ ALOGI("No channel mask, try channel count");
+ }
+ int32_t channelCount = 0;
+ if (!sMeta->findInt32(kKeyChannelCount, &channelCount)) {
+ ALOGI("No channel count either");
+ } else {
+ //if channel mask is not set till now, use channel count
+ //to retrieve channel count
+ if (!cmask) {
+ cmask = audio_channel_out_mask_from_count(channelCount);
+ }
+ }
+ tPCMMeta->setInt32(kKeyChannelCount, channelCount);
+ tPCMMeta->setInt32(kKeyChannelMask, cmask);
+
+ int64_t duration = INT_MAX;
+ if (!sMeta->findInt64(kKeyDuration, &duration)) {
+ ALOGW("No duration in meta setting max duration");
+ }
+ tPCMMeta->setInt64(kKeyDuration, duration);
+
+ int32_t bitRate = -1;
+ if (!sMeta->findInt32(kKeyBitRate, &bitRate)) {
+ ALOGW("No bitrate info");
+ } else {
+ tPCMMeta->setInt32(kKeyBitRate, bitRate);
+ }
+
+ return tPCMMeta;
}
-bool AVNuUtils::pcmOffloadException(const sp<MetaData> &) {
- return true;
+bool AVNuUtils::pcmOffloadException(const sp<MetaData> &meta) {
+ bool decision = false;
+ const char *mime = {0};
+
+ if (meta == NULL) {
+ return true;
+ }
+ meta->findCString(kKeyMIMEType, &mime);
+
+ if (!mime) {
+ ALOGV("%s: no audio mime present, ignoring pcm offload", __func__);
+ return true;
+ }
+//#if defined (PCM_OFFLOAD_ENABLED) || defined (PCM_OFFLOAD_ENABLED_24)
+ const char * const ExceptionTable[] = {
+ MEDIA_MIMETYPE_AUDIO_AMR_NB,
+ MEDIA_MIMETYPE_AUDIO_AMR_WB,
+ MEDIA_MIMETYPE_AUDIO_QCELP,
+ MEDIA_MIMETYPE_AUDIO_G711_ALAW,
+ MEDIA_MIMETYPE_AUDIO_G711_MLAW,
+ MEDIA_MIMETYPE_AUDIO_EVRC
+ };
+ int countException = (sizeof(ExceptionTable) / sizeof(ExceptionTable[0]));
+
+ for(int i = 0; i < countException; i++) {
+ if (!strcasecmp(mime, ExceptionTable[i])) {
+ decision = true;
+ break;
+ }
+ }
+ ALOGI("decision %d mime %s", decision, mime);
+ return decision;
+#if 0
+ //if PCM offload flag is disabled, do not offload any sessions
+ //using pcm offload
+ decision = true;
+ ALOGI("decision %d mime %s", decision, mime);
+ return decision;
+#endif
}
bool AVNuUtils::isRAWFormat(const sp<MetaData> &meta) {
@@ -83,44 +195,145 @@ bool AVNuUtils::isVorbisFormat(const sp<MetaData> &) {
return false;
}
-int AVNuUtils::updateAudioBitWidth(audio_format_t /*audioFormat*/,
- const sp<AMessage> &){
- return 16;
+int AVNuUtils::updateAudioBitWidth(audio_format_t audioFormat,
+ const sp<AMessage> &format){
+ int bits = 16;
+ if (audio_is_linear_pcm(audioFormat) || audio_is_offload_pcm(audioFormat)) {
+ bits = audio_bytes_per_sample(audioFormat) * 8;
+ format->setInt32("bits-per-sample", bits);
+ }
+ return bits;
}
audio_format_t AVNuUtils::getKeyPCMFormat(const sp<MetaData> &meta) {
- int32_t pcmFormat = 0;
- if (meta->findInt32('pfmt', &pcmFormat))
- return (audio_format_t)pcmFormat;
-
- return AUDIO_FORMAT_PCM_16_BIT;
+ audio_format_t pcmFormat = AUDIO_FORMAT_INVALID;
+ meta->findInt32('pfmt', (int32_t *)&pcmFormat);
+ return pcmFormat;
}
void AVNuUtils::setKeyPCMFormat(const sp<MetaData> &meta, audio_format_t audioFormat) {
- if (audio_is_linear_pcm(audioFormat))
+ if (meta != NULL && audio_is_linear_pcm(audioFormat))
meta->setInt32('pfmt', audioFormat);
}
-audio_format_t AVNuUtils::getPCMFormat(const sp<AMessage> &/*format*/) {
- return AUDIO_FORMAT_PCM_16_BIT;
+audio_format_t AVNuUtils::getPCMFormat(const sp<AMessage> &format) {
+ audio_format_t pcmFormat = AUDIO_FORMAT_INVALID;
+ format->findInt32("pcm-format", (int32_t *)&pcmFormat);
+ return pcmFormat;
}
void AVNuUtils::setPCMFormat(const sp<AMessage> &format, audio_format_t audioFormat) {
- if (audio_is_linear_pcm(audioFormat))
+ if (audio_is_linear_pcm(audioFormat) || audio_is_offload_pcm(audioFormat))
format->setInt32("pcm-format", audioFormat);
}
-void AVNuUtils::setSourcePCMFormat(const sp<MetaData> &) {
-
+void AVNuUtils::setSourcePCMFormat(const sp<MetaData> &audioMeta) {
+ audio_format_t pcmFormat = getKeyPCMFormat(audioMeta);
+ ALOGI("setSourcePCMFormat fmt=%x", pcmFormat);
+ audioMeta->dumpToLog();
+ if (pcmFormat == AUDIO_FORMAT_INVALID) {
+ int32_t bits = 16;
+ if (audioMeta->findInt32(kKeyBitsPerSample, &bits)) {
+ if (bits == 8)
+ pcmFormat = AUDIO_FORMAT_PCM_8_BIT;
+ if (bits == 24)
+ pcmFormat = AUDIO_FORMAT_PCM_32_BIT;
+ if (bits == 32)
+ pcmFormat = AUDIO_FORMAT_PCM_FLOAT;
+ setKeyPCMFormat(audioMeta, pcmFormat);
+ }
+ }
}
void AVNuUtils::setDecodedPCMFormat(const sp<AMessage> &) {
}
-status_t AVNuUtils::convertToSinkFormatIfNeeded(const sp<ABuffer> &, sp<ABuffer> &,
- audio_format_t /*sinkFormat*/, bool /*isOffload*/) {
- return INVALID_OPERATION;
+status_t AVNuUtils::convertToSinkFormatIfNeeded(
+ const sp<ABuffer> &buffer, sp<ABuffer> &newBuffer,
+ audio_format_t sinkFormat, bool isOffload) {
+
+ audio_format_t srcFormat = AUDIO_FORMAT_INVALID;
+ if (!buffer->meta()->findInt32("pcm-format", (int32_t *)&srcFormat)) {
+ newBuffer = buffer;
+ return OK;
+ }
+
+ size_t bps = audio_bytes_per_sample(srcFormat);
+
+ if (bps <= 0) {
+ ALOGE("Invalid pcmformat %x given for conversion", srcFormat);
+ return INVALID_OPERATION;
+ }
+
+ size_t frames = buffer->size() / bps;
+
+ if (frames == 0) {
+ ALOGE("zero sized buffer, nothing to convert");
+ return BAD_VALUE;
+ }
+
+ ALOGV("convert %zu bytes (frames %d) of format %x",
+ buffer->size(), frames, srcFormat);
+
+ audio_format_t dstFormat;
+ if (isOffload) {
+ switch (sinkFormat) {
+ case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
+ dstFormat = AUDIO_FORMAT_PCM_16_BIT;
+ break;
+ case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
+ if (srcFormat != AUDIO_FORMAT_PCM_24_BIT_PACKED &&
+ srcFormat != AUDIO_FORMAT_PCM_8_24_BIT) {
+ ALOGE("Invalid src format for 24 bit conversion");
+ return INVALID_OPERATION;
+ }
+ dstFormat = AUDIO_FORMAT_PCM_24_BIT_OFFLOAD;
+ break;
+ case AUDIO_FORMAT_DEFAULT:
+ ALOGI("OffloadInfo not yet initialized, retry");
+ return NO_INIT;
+ default:
+ ALOGE("Invalid offload format %x given for conversion",
+ sinkFormat);
+ return INVALID_OPERATION;
+ }
+ } else {
+ if (sinkFormat == AUDIO_FORMAT_INVALID) {
+ ALOGD("PCM Info not yet initialized, drop buffer");
+ return INVALID_OPERATION;
+ }
+
+ dstFormat = sinkFormat;
+ }
+ if (srcFormat == dstFormat) {
+ ALOGV("same format");
+ newBuffer = buffer;
+ return OK;
+ }
+
+ size_t dstFrameSize = audio_bytes_per_sample(dstFormat);
+ size_t dstBytes = frames * dstFrameSize;
+
+ newBuffer = new ABuffer(dstBytes);
+
+ memcpy_by_audio_format(newBuffer->data(), dstFormat,
+ buffer->data(), srcFormat, frames);
+
+ ALOGV("convert to format %x newBuffer->size() %zu",
+ dstFormat, newBuffer->size());
+
+ // copy over some meta info
+ int64_t timeUs = 0;
+ buffer->meta()->findInt64("timeUs", &timeUs);
+ newBuffer->meta()->setInt64("timeUs", timeUs);
+
+ int32_t eos = false;
+ buffer->meta()->findInt32("eos", &eos);
+ newBuffer->meta()->setInt32("eos", eos);
+
+ newBuffer->meta()->setInt32("pcm-format", (int32_t)dstFormat);
+ return OK;
}
void AVNuUtils::printFileName(int) {}
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;
}