diff options
-rw-r--r-- | media/libavextensions/Android.mk | 8 | ||||
-rw-r--r-- | media/libavextensions/media/AVMediaExtensions.h | 5 | ||||
-rw-r--r-- | media/libavextensions/mediaplayerservice/AVNuUtils.cpp | 257 | ||||
-rw-r--r-- | media/libavextensions/stagefright/AVUtils.cpp | 267 | ||||
-rw-r--r-- | media/libmediaplayerservice/Android.mk | 3 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/Android.mk | 2 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 63 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayer.h | 10 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp | 12 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h | 1 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp | 214 |
11 files changed, 693 insertions, 149 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; } diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk index 7c4aa3d..6575625 100644 --- a/media/libmediaplayerservice/Android.mk +++ b/media/libmediaplayerservice/Android.mk @@ -40,6 +40,7 @@ LOCAL_SHARED_LIBRARIES := \ libstagefright_wfd \ libutils \ libvorbisidec \ + libaudioutils \ LOCAL_STATIC_LIBRARIES := \ libstagefright_nuplayer \ @@ -57,7 +58,7 @@ LOCAL_C_INCLUDES := \ $(TOP)/external/tremolo/Tremolo \ $(TOP)/frameworks/av/media/libavextensions \ -LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall +LOCAL_CFLAGS += -Werror -Wno-error=deprecated-declarations -Wall #-DLOG_NDEBUG=0 LOCAL_CLANG := true LOCAL_MODULE:= libmediaplayerservice diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk index cc1bdb4..fbb1276 100644 --- a/media/libmediaplayerservice/nuplayer/Android.mk +++ b/media/libmediaplayerservice/nuplayer/Android.mk @@ -27,7 +27,7 @@ LOCAL_C_INCLUDES := \ $(TOP)/frameworks/av/media/libavextensions \ $(TOP)/frameworks/av/include/media \ -LOCAL_CFLAGS += -Werror -Wall +LOCAL_CFLAGS += -Werror -Wall #-DLOG_NDEBUG=0 # enable experiments only in userdebug and eng builds ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT))) diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index de507f1..678db8e 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -189,6 +189,7 @@ NuPlayer::NuPlayer(pid_t pid) mPID(pid), mSourceFlags(0), mOffloadAudio(false), + mOffloadDecodedPCM(false), mAudioDecoderGeneration(0), mVideoDecoderGeneration(0), mRendererGeneration(0), @@ -1133,10 +1134,12 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { mResetting = true; - mDeferredActions.push_back( - new FlushDecoderAction( - FLUSH_CMD_SHUTDOWN /* audio */, - FLUSH_CMD_SHUTDOWN /* video */)); + if (mAudioDecoder != NULL && mFlushingAudio == NONE) { + mDeferredActions.push_back( + new FlushDecoderAction( + FLUSH_CMD_SHUTDOWN /* audio */, + FLUSH_CMD_SHUTDOWN /* video */)); + } mDeferredActions.push_back( new SimpleAction(&NuPlayer::closeAudioSink)); @@ -1228,9 +1231,16 @@ void NuPlayer::onResume() { } else { ALOGW("resume called when source is gone or not set"); } + if (mOffloadAudio && !mOffloadDecodedPCM) { + // Resuming after a pause timed out event, check if can continue with offload + sp<AMessage> videoFormat = mSource->getFormat(false /* audio */); + sp<AMessage> format = mSource->getFormat(true /*audio*/); + const bool hasVideo = (videoFormat != NULL); + tryOpenAudioSinkForOffload(format, hasVideo); + } // |mAudioDecoder| may have been released due to the pause timeout, so re-create it if // needed. - if (audioDecoderStillNeeded() && mAudioDecoder == NULL) { + if (audioDecoderStillNeeded() && mAudioDecoder == NULL && !mOffloadDecodedPCM) { instantiateDecoder(true /* audio */, &mAudioDecoder); } if (mRenderer != NULL) { @@ -1282,6 +1292,7 @@ void NuPlayer::onStart(int64_t startPositionUs) { } mOffloadAudio = false; + mOffloadDecodedPCM = false; mAudioEOS = false; mVideoEOS = false; mStarted = true; @@ -1292,8 +1303,10 @@ void NuPlayer::onStart(int64_t startPositionUs) { flags |= Renderer::FLAG_REAL_TIME; } + ALOGV("onStart"); sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */); AVNuUtils::get()->setSourcePCMFormat(audioMeta); + audioMeta->dumpToLog(); audio_stream_type_t streamType = AUDIO_STREAM_MUSIC; if (mAudioSink != NULL) { streamType = mAudioSink->getAudioStreamType(); @@ -1690,6 +1703,18 @@ void NuPlayer::flushDecoder(bool audio, bool needShutdown) { return; } + FlushStatus *state = audio ? &mFlushingAudio : &mFlushingVideo; + + bool inShutdown = *state != NONE && + *state != FLUSHING_DECODER && + *state != FLUSHED; + + // Reject flush if the decoder state is not one of the above + if (inShutdown) { + ALOGI("flush %s called while in shutdown", audio ? "audio" : "video"); + return; + } + // Make sure we don't continue to scan sources until we finish flushing. ++mScanSourcesGeneration; if (mScanSourcesPending) { @@ -2433,4 +2458,32 @@ void NuPlayer::performTearDown(const sp<AMessage> &msg) { processDeferredActions(); } +bool NuPlayer::ifDecodedPCMOffload() { + return mOffloadDecodedPCM; +} + +void NuPlayer::setDecodedPcmOffload(bool decodePcmOffload) { + mOffloadDecodedPCM = decodePcmOffload; +} + +bool NuPlayer::canOffloadDecodedPCMStream(const sp<MetaData> audioMeta, + bool hasVideo, bool isStreaming, audio_stream_type_t streamType) { + const char *mime = NULL; + + //For offloading decoded content + if (!mOffloadAudio && (audioMeta != NULL)) { + audioMeta->findCString(kKeyMIMEType, &mime); + sp<MetaData> audioPCMMeta = + AVNuUtils::get()->createPCMMetaFromSource(audioMeta); + + ALOGI("canOffloadDecodedPCMStream"); + audioMeta->dumpToLog(); + mOffloadDecodedPCM = + ((mime && !AVNuUtils::get()->pcmOffloadException(audioMeta)) && + canOffloadStream(audioPCMMeta, hasVideo, isStreaming, streamType)); + ALOGI("PCM offload decided: %d", mOffloadDecodedPCM); + } + return mOffloadDecodedPCM; +} + } // namespace android diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h index ee0f3e6..c093b0f 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h @@ -86,11 +86,12 @@ protected: virtual ~NuPlayer(); virtual void onMessageReceived(const sp<AMessage> &msg); - virtual bool ifDecodedPCMOffload() {return false;} - virtual void setDecodedPcmOffload(bool /*decodePcmOffload*/) {} - virtual bool canOffloadDecodedPCMStream(const sp<MetaData> /*meta*/, - bool /*hasVideo*/, bool /*isStreaming*/, audio_stream_type_t /*streamType*/) {return false;} + virtual bool ifDecodedPCMOffload(); + virtual void setDecodedPcmOffload(bool decodePcmOffload); + virtual bool canOffloadDecodedPCMStream(const sp<MetaData> meta, + bool hasVideo, bool isStreaming, audio_stream_type_t streamType); static bool IsHTTPLiveURL(const char *url); + public: struct NuPlayerStreamListener; struct Source; @@ -151,6 +152,7 @@ protected: sp<MediaPlayerBase::AudioSink> mAudioSink; sp<DecoderBase> mVideoDecoder; bool mOffloadAudio; + bool mOffloadDecodedPCM; sp<DecoderBase> mAudioDecoder; sp<CCDecoder> mCCDecoder; sp<Renderer> mRenderer; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp index 937936d..0b50d0d 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp @@ -53,7 +53,8 @@ NuPlayer::DecoderPassThrough::DecoderPassThrough( mPendingAudioErr(OK), mPendingBuffersToDrain(0), mCachedBytes(0), - mComponentName("pass through decoder") { + mComponentName("pass through decoder"), + mPCMFormat(AUDIO_FORMAT_INVALID) { ALOGW_IF(renderer == NULL, "expect a non-NULL renderer"); } @@ -75,6 +76,15 @@ void NuPlayer::DecoderPassThrough::onConfigure(const sp<AMessage> &format) { // The audio sink is already opened before the PassThrough decoder is created. // Opening again might be relevant if decoder is instantiated after shutdown and // format is different. + sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */); + if (AVNuUtils::get()->isRAWFormat(audioMeta)) { + mPCMFormat = AVNuUtils::get()->getKeyPCMFormat(audioMeta); + if (mPCMFormat != AUDIO_FORMAT_INVALID) { + AVNuUtils::get()->setPCMFormat(format, mPCMFormat); + AVNuUtils::get()->updateAudioBitWidth(mPCMFormat, format); + } + } + status_t err = mRenderer->openAudioSink( format, true /* offloadOnly */, hasVideo, AUDIO_OUTPUT_FLAG_NONE /* flags */, NULL /* isOffloaded */, mSource->isStreaming()); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h index 629e266..fbc4087 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.h @@ -69,6 +69,7 @@ private: size_t mPendingBuffersToDrain; size_t mCachedBytes; AString mComponentName; + audio_format_t mPCMFormat; bool isStaleReply(const sp<AMessage> &msg); bool isDoneFetching() const; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp index 049b79d..9cf6b62 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp @@ -1250,6 +1250,30 @@ void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) { if (audio) { Mutex::Autolock autoLock(mLock); +#if 1 + sp<ABuffer> newBuffer; + status_t err = AVNuUtils::get()->convertToSinkFormatIfNeeded( + buffer, newBuffer, + (offloadingAudio() ? mCurrentOffloadInfo.format : mCurrentPcmInfo.mFormat), + offloadingAudio()); + switch (err) { + case NO_INIT: + // passthru decoder pushes some buffers before the audio sink + // is opened. Since the offload format is known only when the sink + // is opened, pcm conversions cannot take place. So, retry. + ALOGI("init pending, retrying in 10ms, this shouldn't happen"); + msg->post(10000LL); + return; + case OK: + break; + default: + ALOGW("error 0x%x in converting to sink format, drop buffer", err); + notifyConsumed->post(); + return; + } + CHECK(newBuffer != NULL); + entry.mBuffer = newBuffer; +#endif mAudioQueue.push_back(entry); postDrainAudioQueue_l(); } else { @@ -1727,108 +1751,106 @@ status_t NuPlayer::Renderer::onOpenAudioSink( AString mime; CHECK(format->findString("mime", &mime)); - if (offloadingAudio()) { - audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT; - status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str()); + audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT; + status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str()); - if (err != OK) { - ALOGE("Couldn't map mime \"%s\" to a valid " - "audio_format", mime.c_str()); - onDisableOffloadAudio(); - } else { - audioFormat = AVUtils::get()->updateAudioFormat(audioFormat, format); - - bitWidth = AVUtils::get()->getAudioSampleBits(format); - int avgBitRate = -1; - format->findInt32("bitrate", &avgBitRate); - - int32_t aacProfile = -1; - if (audioFormat == AUDIO_FORMAT_AAC - && format->findInt32("aac-profile", &aacProfile)) { - // Redefine AAC format as per aac profile - int32_t isADTSSupported; - isADTSSupported = AVUtils::get()->mapAACProfileToAudioFormat(format, - audioFormat, - aacProfile); - if (!isADTSSupported) { - mapAACProfileToAudioFormat(audioFormat, - aacProfile); - } else { - ALOGV("Format is AAC ADTS\n"); - } + if (err != OK) { + ALOGE("Couldn't map mime \"%s\" to a valid " + "audio_format", mime.c_str()); + onDisableOffloadAudio(); + } else { + audioFormat = AVUtils::get()->updateAudioFormat(audioFormat, format); + + bitWidth = AVUtils::get()->getAudioSampleBits(format); + int avgBitRate = -1; + format->findInt32("bitrate", &avgBitRate); + + int32_t aacProfile = -1; + if (audioFormat == AUDIO_FORMAT_AAC + && format->findInt32("aac-profile", &aacProfile)) { + // Redefine AAC format as per aac profile + int32_t isADTSSupported; + isADTSSupported = AVUtils::get()->mapAACProfileToAudioFormat(format, + audioFormat, + aacProfile); + if (!isADTSSupported) { + mapAACProfileToAudioFormat(audioFormat, + aacProfile); + } else { + ALOGV("Format is AAC ADTS\n"); } + } - int32_t offloadBufferSize = - AVUtils::get()->getAudioMaxInputBufferSize( - audioFormat, - format); - audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER; - - offloadInfo.duration_us = -1; - format->findInt64( - "durationUs", &offloadInfo.duration_us); - offloadInfo.sample_rate = sampleRate; - offloadInfo.channel_mask = channelMask; - offloadInfo.format = audioFormat; - offloadInfo.stream_type = AUDIO_STREAM_MUSIC; - offloadInfo.bit_rate = avgBitRate; - offloadInfo.has_video = hasVideo; - offloadInfo.is_streaming = isStreaming; - offloadInfo.bit_width = bitWidth; - offloadInfo.offload_buffer_size = offloadBufferSize; - - if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) { - ALOGV("openAudioSink: no change in offload mode"); - // no change from previous configuration, everything ok. - return OK; - } - mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER; + int32_t offloadBufferSize = + AVUtils::get()->getAudioMaxInputBufferSize( + audioFormat, + format); + audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER; + + offloadInfo.duration_us = -1; + format->findInt64( + "durationUs", &offloadInfo.duration_us); + offloadInfo.sample_rate = sampleRate; + offloadInfo.channel_mask = channelMask; + offloadInfo.format = audioFormat; + offloadInfo.stream_type = AUDIO_STREAM_MUSIC; + offloadInfo.bit_rate = avgBitRate; + offloadInfo.has_video = hasVideo; + offloadInfo.is_streaming = isStreaming; + offloadInfo.bit_width = bitWidth; + offloadInfo.offload_buffer_size = offloadBufferSize; + + if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) { + ALOGV("openAudioSink: no change in offload mode"); + // no change from previous configuration, everything ok. + return OK; + } + mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER; - ALOGV("openAudioSink: try to open AudioSink in offload mode"); - uint32_t offloadFlags = flags; - offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; - offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER; - audioSinkChanged = true; - mAudioSink->close(); + ALOGV("openAudioSink: try to open AudioSink in offload mode"); + uint32_t offloadFlags = flags; + offloadFlags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; + offloadFlags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER; + audioSinkChanged = true; + mAudioSink->close(); - err = mAudioSink->open( - sampleRate, - numChannels, - (audio_channel_mask_t)channelMask, - audioFormat, - 0 /* bufferCount - unused */, - &NuPlayer::Renderer::AudioSinkCallback, - this, - (audio_output_flags_t)offloadFlags, - &offloadInfo); + err = mAudioSink->open( + sampleRate, + numChannels, + (audio_channel_mask_t)channelMask, + audioFormat, + 0 /* bufferCount - unused */, + &NuPlayer::Renderer::AudioSinkCallback, + this, + (audio_output_flags_t)offloadFlags, + &offloadInfo); - if (err == OK) { - err = mAudioSink->setPlaybackRate(mPlaybackSettings); - } + if (err == OK) { + err = mAudioSink->setPlaybackRate(mPlaybackSettings); + } - if (err == OK) { - // If the playback is offloaded to h/w, we pass - // the HAL some metadata information. - // We don't want to do this for PCM because it - // will be going through the AudioFlinger mixer - // before reaching the hardware. - // TODO - mCurrentOffloadInfo = offloadInfo; - if (!mPaused) { // for preview mode, don't start if paused - err = mAudioSink->start(); - } - ALOGV_IF(err == OK, "openAudioSink: offload succeeded"); - } - if (err != OK) { - // Clean up, fall back to non offload mode. - mAudioSink->close(); - onDisableOffloadAudio(); - mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER; - ALOGV("openAudioSink: offload failed"); - } else { - mUseAudioCallback = true; // offload mode transfers data through callback - ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message. + if (err == OK) { + // If the playback is offloaded to h/w, we pass + // the HAL some metadata information. + // We don't want to do this for PCM because it + // will be going through the AudioFlinger mixer + // before reaching the hardware. + // TODO + mCurrentOffloadInfo = offloadInfo; + if (!mPaused) { // for preview mode, don't start if paused + err = mAudioSink->start(); } + ALOGV_IF(err == OK, "openAudioSink: offload succeeded"); + } + if (err != OK) { + // Clean up, fall back to non offload mode. + mAudioSink->close(); + onDisableOffloadAudio(); + mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER; + ALOGV("openAudioSink: offload failed"); + } else { + mUseAudioCallback = true; // offload mode transfers data through callback + ++mAudioDrainGeneration; // discard pending kWhatDrainAudioQueue message. } } if (!offloadOnly && !offloadingAudio()) { @@ -1839,7 +1861,7 @@ status_t NuPlayer::Renderer::onOpenAudioSink( const PcmInfo info = { (audio_channel_mask_t)channelMask, (audio_output_flags_t)pcmFlags, - getPCMFormat(format), + AVNuUtils::get()->getPCMFormat(format), numChannels, sampleRate }; @@ -1874,7 +1896,7 @@ status_t NuPlayer::Renderer::onOpenAudioSink( sampleRate, numChannels, (audio_channel_mask_t)channelMask, - getPCMFormat(format), + AVNuUtils::get()->getPCMFormat(format), 0 /* bufferCount - unused */, mUseAudioCallback ? &NuPlayer::Renderer::AudioSinkCallback : NULL, mUseAudioCallback ? this : NULL, |