From bc3028750d3438ebf108298e93f12de461f56430 Mon Sep 17 00:00:00 2001 From: vivek mehta Date: Thu, 16 Jul 2015 12:56:57 -0700 Subject: stagefright: Add support for custom size i/p buffer - handle non default input buffer size - fix issues associated with non-default buffer size Change-Id: Iad31f5c85601983b01e18e130b1c3eecb3988e30 --- media/libavextensions/stagefright/AVExtensions.h | 11 ++++++ media/libavextensions/stagefright/AVUtils.cpp | 14 ++++++++ .../nuplayer/NuPlayerRenderer.cpp | 19 ++++++++-- media/libstagefright/Utils.cpp | 7 +++- media/libstagefright/codecs/aacdec/SoftAAC2.cpp | 41 ++++++++++++++++++++-- media/libstagefright/codecs/aacdec/SoftAAC2.h | 3 ++ media/libstagefright/codecs/mp3dec/SoftMP3.cpp | 31 +++++++++++++--- media/libstagefright/codecs/mp3dec/SoftMP3.h | 3 ++ .../common/managerdefinitions/Android.mk | 3 ++ .../include/ConfigParsingUtils.h | 12 +++++++ 10 files changed, 134 insertions(+), 10 deletions(-) diff --git a/media/libavextensions/stagefright/AVExtensions.h b/media/libavextensions/stagefright/AVExtensions.h index e75499f..832fc28 100644 --- a/media/libavextensions/stagefright/AVExtensions.h +++ b/media/libavextensions/stagefright/AVExtensions.h @@ -128,6 +128,17 @@ struct AVUtils { virtual bool canOffloadAPE(const sp &meta); + virtual int32_t getAudioMaxInputBufferSize(audio_format_t audioFormat, + const sp &); + + virtual bool mapAACProfileToAudioFormat(const sp &, + audio_format_t &, + uint64_t /*eAacProfile*/); + + virtual bool mapAACProfileToAudioFormat(const sp &, + audio_format_t &, + uint64_t /*eAacProfile*/); + virtual void extractCustomCameraKeys( const CameraParameters& /*params*/, sp &/*meta*/) {} virtual void printFileName(int /*fd*/) {} diff --git a/media/libavextensions/stagefright/AVUtils.cpp b/media/libavextensions/stagefright/AVUtils.cpp index 5113446..9219fc2 100644 --- a/media/libavextensions/stagefright/AVUtils.cpp +++ b/media/libavextensions/stagefright/AVUtils.cpp @@ -105,6 +105,20 @@ bool AVUtils::canOffloadAPE(const sp &) { return true; } +int32_t AVUtils::getAudioMaxInputBufferSize(audio_format_t, const sp &) { + return 0; +} + +bool AVUtils::mapAACProfileToAudioFormat(const sp &, audio_format_t &, + uint64_t /*eAacProfile*/) { + return false ; +} + +bool AVUtils::mapAACProfileToAudioFormat(const sp &, audio_format_t &, + uint64_t /*eAacProfile*/) { + return false ; +} + bool AVUtils::isEnhancedExtension(const char *) { return false; } diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp index 87e49bd..aa993a9 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp @@ -1688,12 +1688,24 @@ status_t NuPlayer::Renderer::onOpenAudioSink( if (audioFormat == AUDIO_FORMAT_AAC && format->findInt32("aac-profile", &aacProfile)) { // Redefine AAC format as per aac profile - mapAACProfileToAudioFormat( - audioFormat, - aacProfile); + 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); @@ -1705,6 +1717,7 @@ status_t NuPlayer::Renderer::onOpenAudioSink( 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"); diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp index 935fbf7..e7d36dc 100644 --- a/media/libstagefright/Utils.cpp +++ b/media/libstagefright/Utils.cpp @@ -834,7 +834,12 @@ bool canOffloadStream(const sp& meta, bool hasVideo, // Offloading depends on audio DSP capabilities. int32_t aacaot = -1; if (meta->findInt32(kKeyAACAOT, &aacaot)) { - mapAACProfileToAudioFormat(info.format,(OMX_AUDIO_AACPROFILETYPE) aacaot); + bool isADTSSupported = false; + isADTSSupported = AVUtils::get()->mapAACProfileToAudioFormat(meta, info.format, + (OMX_AUDIO_AACPROFILETYPE) aacaot); + if (!isADTSSupported) { + mapAACProfileToAudioFormat(info.format,(OMX_AUDIO_AACPROFILETYPE) aacaot); + } } int32_t srate = -1; diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp index 965c55e..c945305 100644 --- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp +++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp @@ -68,6 +68,8 @@ SoftAAC2::SoftAAC2( mOutputBufferCount(0), mSignalledError(false), mLastInHeader(NULL), + mLastHeaderTimeUs(-1), + mNextOutBufferTimeUs(0), mOutputPortSettingsChange(NONE) { initPorts(); CHECK_EQ(initDecoder(), (status_t)OK); @@ -492,6 +494,27 @@ int32_t SoftAAC2::outputDelayRingBufferSpaceLeft() { return mOutputDelayRingBufferSize - outputDelayRingBufferSamplesAvailable(); } +void SoftAAC2::updateTimeStamp(int64_t inHeaderTimeUs) { + // use new input buffer timestamp as Anchor Time if its + // a) first buffer or + // b) first buffer post seek or + // c) different from last buffer timestamp + //If input buffer timestamp is same as last input buffer timestamp then + //treat this as a erroneous timestamp and ignore new input buffer + //timestamp and use last output buffer timestamp as Anchor Time. + int64_t anchorTimeUs = 0; + if ((mLastHeaderTimeUs != inHeaderTimeUs)) { + anchorTimeUs = inHeaderTimeUs; + mLastHeaderTimeUs = inHeaderTimeUs; + //Store current buffer's timestamp so that it can used as reference + //in cases where first frame/buffer is skipped/dropped. + //e.g to compensate decoder delay + mNextOutBufferTimeUs = inHeaderTimeUs; + } else { + anchorTimeUs = mNextOutBufferTimeUs; + } + mBufferTimestamps.add(anchorTimeUs); +} void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { if (mSignalledError || mOutputPortSettingsChange != NONE) { @@ -618,7 +641,7 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { // insert buffer size and time stamp mBufferSizes.add(inBufferLength[0]); if (mLastInHeader != inHeader) { - mBufferTimestamps.add(inHeader->nTimeStamp); + updateTimeStamp(inHeader->nTimeStamp); mLastInHeader = inHeader; } else { int64_t currentTime = mBufferTimestamps.top(); @@ -630,7 +653,7 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { inBuffer[0] = inHeader->pBuffer + inHeader->nOffset; inBufferLength[0] = inHeader->nFilledLen; mLastInHeader = inHeader; - mBufferTimestamps.add(inHeader->nTimeStamp); + updateTimeStamp(inHeader->nTimeStamp); mBufferSizes.add(inHeader->nFilledLen); } @@ -755,6 +778,14 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { if (inHeader && inHeader->nFilledLen == 0) { inInfo->mOwnedByUs = false; mInputBufferCount++; + + //During Port reconfiguration current frames is skipped and next frame + //is sent for decoding. + //Update mNextOutBufferTimeUs with current frame's timestamp if port reconfiguration is + //happening in last frame of current buffer otherwise LastOutBufferTimeUs + //will be zero(post seek). + mNextOutBufferTimeUs = mBufferTimestamps.top() + mStreamInfo->aacSamplesPerFrame * + 1000000ll / mStreamInfo->aacSampleRate; inQueue.erase(inQueue.begin()); mLastInHeader = NULL; inInfo = NULL; @@ -875,6 +906,7 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { *currentBufLeft -= decodedSize; *nextTimeStamp += mStreamInfo->aacSamplesPerFrame * 1000000ll / mStreamInfo->aacSampleRate; + mNextOutBufferTimeUs = *nextTimeStamp; ALOGV("adjusted nextTimeStamp/size to %lld/%d", (long long) *nextTimeStamp, *currentBufLeft); } else { @@ -882,6 +914,7 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { if (mBufferTimestamps.size() > 0) { mBufferTimestamps.removeAt(0); nextTimeStamp = &mBufferTimestamps.editItemAt(0); + mNextOutBufferTimeUs = *nextTimeStamp; mBufferSizes.removeAt(0); currentBufLeft = &mBufferSizes.editItemAt(0); ALOGV("moved to next time/size: %lld/%d", @@ -976,6 +1009,8 @@ void SoftAAC2::onPortFlushCompleted(OMX_U32 portIndex) { mDecodedSizes.clear(); mLastInHeader = NULL; mEndOfInput = false; + mLastHeaderTimeUs = -1; + mNextOutBufferTimeUs = 0; } else { int avail; while ((avail = outputDelayRingBufferSamplesAvailable()) > 0) { @@ -1038,6 +1073,8 @@ void SoftAAC2::onReset() { mBufferSizes.clear(); mDecodedSizes.clear(); mLastInHeader = NULL; + mLastHeaderTimeUs = -1; + mNextOutBufferTimeUs = 0; // To make the codec behave the same before and after a reset, we need to invalidate the // streaminfo struct. This does that: diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.h b/media/libstagefright/codecs/aacdec/SoftAAC2.h index c3e4459..3fe958e 100644 --- a/media/libstagefright/codecs/aacdec/SoftAAC2.h +++ b/media/libstagefright/codecs/aacdec/SoftAAC2.h @@ -59,6 +59,8 @@ private: size_t mOutputBufferCount; bool mSignalledError; OMX_BUFFERHEADERTYPE *mLastInHeader; + int64_t mLastHeaderTimeUs; + int64_t mNextOutBufferTimeUs; Vector mBufferSizes; Vector mDecodedSizes; Vector mBufferTimestamps; @@ -90,6 +92,7 @@ private: int32_t outputDelayRingBufferGetSamples(INT_PCM *samples, int numSamples); int32_t outputDelayRingBufferSamplesAvailable(); int32_t outputDelayRingBufferSpaceLeft(); + void updateTimeStamp(int64_t inHeaderTimesUs); DISALLOW_EVIL_CONSTRUCTORS(SoftAAC2); }; diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp index aeaea81..4c4da60 100644 --- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp +++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp @@ -51,7 +51,9 @@ SoftMP3::SoftMP3( mSignalledError(false), mSawInputEos(false), mSignalledOutputEos(false), - mOutputPortSettingsChange(NONE) { + mOutputPortSettingsChange(NONE), + mLastAnchorTimeUs(-1), + mNextOutBufferTimeUs(0) { initPorts(); initDecoder(); } @@ -212,7 +214,7 @@ void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) { List &inQueue = getPortQueue(0); List &outQueue = getPortQueue(1); - + int64_t tmpTime = 0; while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) { BufferInfo *inInfo = NULL; OMX_BUFFERHEADERTYPE *inHeader = NULL; @@ -227,7 +229,20 @@ void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) { if (inHeader) { if (inHeader->nOffset == 0 && inHeader->nFilledLen) { - mAnchorTimeUs = inHeader->nTimeStamp; + // use new input buffer timestamp as Anchor Time if its + // a) first buffer or + // b) first buffer post seek or + // c) different from last buffer timestamp + //If input buffer timestamp is same as last input buffer timestamp then + //treat this as a erroneous timestamp and ignore new input buffer + //timestamp and use last output buffer timestamp as Anchor Time. + if ((mLastAnchorTimeUs != inHeader->nTimeStamp)) { + mAnchorTimeUs = inHeader->nTimeStamp; + mLastAnchorTimeUs = inHeader->nTimeStamp; + } else { + mAnchorTimeUs = mNextOutBufferTimeUs; + } + mNumFramesOutput = 0; } @@ -326,7 +341,7 @@ void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) { outHeader->nTimeStamp = mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mSamplingRate; - + tmpTime = outHeader->nTimeStamp; if (inHeader) { CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength); @@ -351,6 +366,10 @@ void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) { notifyFillBufferDone(outHeader); outHeader = NULL; } + + if (tmpTime > 0) { + mNextOutBufferTimeUs = tmpTime; + } } void SoftMP3::onPortFlushCompleted(OMX_U32 portIndex) { @@ -362,6 +381,8 @@ void SoftMP3::onPortFlushCompleted(OMX_U32 portIndex) { mSignalledError = false; mSawInputEos = false; mSignalledOutputEos = false; + mLastAnchorTimeUs = -1; + mNextOutBufferTimeUs = 0; } } @@ -398,6 +419,8 @@ void SoftMP3::onReset() { mSawInputEos = false; mSignalledOutputEos = false; mOutputPortSettingsChange = NONE; + mLastAnchorTimeUs = -1; + mNextOutBufferTimeUs = 0; } } // namespace android diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.h b/media/libstagefright/codecs/mp3dec/SoftMP3.h index f9e7b53..c769795 100644 --- a/media/libstagefright/codecs/mp3dec/SoftMP3.h +++ b/media/libstagefright/codecs/mp3dec/SoftMP3.h @@ -70,6 +70,9 @@ private: AWAITING_ENABLED } mOutputPortSettingsChange; + int64_t mLastAnchorTimeUs; + int64_t mNextOutBufferTimeUs; + void initPorts(); void initDecoder(); diff --git a/services/audiopolicy/common/managerdefinitions/Android.mk b/services/audiopolicy/common/managerdefinitions/Android.mk index 10362f4..8c6a53c 100644 --- a/services/audiopolicy/common/managerdefinitions/Android.mk +++ b/services/audiopolicy/common/managerdefinitions/Android.mk @@ -47,6 +47,9 @@ endif ifeq ($(strip $(AUDIO_FEATURE_ENABLED_APE_OFFLOAD)),true) LOCAL_CFLAGS += -DAPE_OFFLOAD_ENABLED endif +ifeq ($(strip $(AUDIO_FEATURE_ENABLED_AAC_ADTS_OFFLOAD)),true) +LOCAL_CFLAGS += -DAAC_ADTS_OFFLOAD_ENABLED +endif endif LOCAL_MODULE := libaudiopolicycomponents diff --git a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h index cc91c63..4a394bb 100644 --- a/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h +++ b/services/audiopolicy/common/managerdefinitions/include/ConfigParsingUtils.h @@ -217,6 +217,18 @@ const StringToEnum sFormatNameToEnumTable[] = { #ifdef APE_OFFLOAD_ENABLED STRING_TO_ENUM(AUDIO_FORMAT_APE), #endif +#ifdef AAC_ADTS_OFFLOAD_ENABLED + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_MAIN), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_LC), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_SSR), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_LTP), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_HE_V1), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_SCALABLE), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_ERLC), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_LD), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_HE_V2), + STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADTS_ELD), +#endif }; const StringToEnum sOutChannelsNameToEnumTable[] = { -- cgit v1.1