From 6dde130280d6ead297170211b005cc809e7f7bde Mon Sep 17 00:00:00 2001 From: Steve Kondik Date: Wed, 9 Dec 2015 20:44:26 -0800 Subject: 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 --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 63 +++++++++++++++++++++-- 1 file changed, 58 insertions(+), 5 deletions(-) (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp') 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 &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 videoFormat = mSource->getFormat(false /* audio */); + sp 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 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 &msg) { processDeferredActions(); } +bool NuPlayer::ifDecodedPCMOffload() { + return mOffloadDecodedPCM; +} + +void NuPlayer::setDecodedPcmOffload(bool decodePcmOffload) { + mOffloadDecodedPCM = decodePcmOffload; +} + +bool NuPlayer::canOffloadDecodedPCMStream(const sp 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 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 -- cgit v1.1