From 3b9eb1f8629c6264d924ab7043f80d824cdd39e2 Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Wed, 15 Oct 2014 17:05:08 -0700 Subject: move audio sink open/close to NuPlayerRenderer Bug: 17675112 Change-Id: I7eb3d02380658f848baedafe2aea287586ccf016 --- media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 130 +------------- media/libmediaplayerservice/nuplayer/NuPlayer.h | 1 - .../nuplayer/NuPlayerRenderer.cpp | 199 ++++++++++++++++++++- .../nuplayer/NuPlayerRenderer.h | 16 ++ 4 files changed, 223 insertions(+), 123 deletions(-) (limited to 'media') diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index eb5821b..a63a940 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -153,7 +153,6 @@ NuPlayer::NuPlayer() mSourceFlags(0), mVideoIsAVC(false), mOffloadAudio(false), - mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER), mAudioDecoderGeneration(0), mVideoDecoderGeneration(0), mRendererGeneration(0), @@ -1112,30 +1111,15 @@ void NuPlayer::postScanSources() { } void NuPlayer::openAudioSink(const sp &format, bool offloadOnly) { - ALOGV("openAudioSink: offloadOnly(%d) mOffloadAudio(%d)", - offloadOnly, mOffloadAudio); - bool audioSinkChanged = false; - - int32_t numChannels; - CHECK(format->findInt32("channel-count", &numChannels)); - - int32_t channelMask; - if (!format->findInt32("channel-mask", &channelMask)) { - // signal to the AudioSink to derive the mask from count. - channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER; - } - - int32_t sampleRate; - CHECK(format->findInt32("sample-rate", &sampleRate)); - uint32_t flags; int64_t durationUs; + bool hasVideo = (mVideoDecoder != NULL); // FIXME: we should handle the case where the video decoder // is created after we receive the format change indication. // Current code will just make that we select deep buffer // with video which should not be a problem as it should // not prevent from keeping A/V sync. - if (mVideoDecoder == NULL && + if (hasVideo && mSource->getDuration(&durationUs) == OK && durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) { @@ -1144,114 +1128,18 @@ void NuPlayer::openAudioSink(const sp &format, bool offloadOnly) { flags = AUDIO_OUTPUT_FLAG_NONE; } - if (mOffloadAudio) { - audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT; - AString mime; - CHECK(format->findString("mime", &mime)); - status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str()); + mOffloadAudio = mRenderer->openAudioSink( + format, offloadOnly, hasVideo, flags); - if (err != OK) { - ALOGE("Couldn't map mime \"%s\" to a valid " - "audio_format", mime.c_str()); - mOffloadAudio = false; - } else { - ALOGV("Mime \"%s\" mapped to audio_format 0x%x", - mime.c_str(), audioFormat); - - int avgBitRate = -1; - format->findInt32("bit-rate", &avgBitRate); - - int32_t aacProfile = -1; - if (audioFormat == AUDIO_FORMAT_AAC - && format->findInt32("aac-profile", &aacProfile)) { - // Redefine AAC format as per aac profile - mapAACProfileToAudioFormat( - audioFormat, - aacProfile); - } - - 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 = (mVideoDecoder != NULL); - offloadInfo.is_streaming = true; - - if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) { - ALOGV("openAudioSink: no change in offload mode"); - return; // no change from previous configuration, everything ok. - } - ALOGV("openAudioSink: try to open AudioSink in offload mode"); - flags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; - flags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER; - audioSinkChanged = true; - mAudioSink->close(); - err = mAudioSink->open( - sampleRate, - numChannels, - (audio_channel_mask_t)channelMask, - audioFormat, - 8 /* bufferCount */, - &NuPlayer::Renderer::AudioSinkCallback, - mRenderer.get(), - (audio_output_flags_t)flags, - &offloadInfo); - - 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. - sp audioMeta = - mSource->getFormatMeta(true /* audio */); - sendMetaDataToHal(mAudioSink, audioMeta); - mCurrentOffloadInfo = offloadInfo; - err = mAudioSink->start(); - ALOGV_IF(err == OK, "openAudioSink: offload succeeded"); - } - if (err != OK) { - // Clean up, fall back to non offload mode. - mAudioSink->close(); - mRenderer->signalDisableOffloadAudio(); - mOffloadAudio = false; - mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER; - ALOGV("openAudioSink: offload failed"); - } - } - } - if (!offloadOnly && !mOffloadAudio) { - flags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; - ALOGV("openAudioSink: open AudioSink in NON-offload mode"); - - audioSinkChanged = true; - mAudioSink->close(); - mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER; - CHECK_EQ(mAudioSink->open( - sampleRate, - numChannels, - (audio_channel_mask_t)channelMask, - AUDIO_FORMAT_PCM_16_BIT, - 8 /* bufferCount */, - NULL, - NULL, - (audio_output_flags_t)flags), - (status_t)OK); - mAudioSink->start(); - } - if (audioSinkChanged) { - mRenderer->signalAudioSinkChanged(); + if (mOffloadAudio) { + sp audioMeta = + mSource->getFormatMeta(true /* audio */); + sendMetaDataToHal(mAudioSink, audioMeta); } } void NuPlayer::closeAudioSink() { - mAudioSink->close(); - mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER; + mRenderer->closeAudioSink(); } status_t NuPlayer::instantiateDecoder(bool audio, sp *decoder) { diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h index c61510c..d6120d2 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h @@ -132,7 +132,6 @@ private: sp mVideoDecoder; bool mVideoIsAVC; bool mOffloadAudio; - audio_offload_info_t mCurrentOffloadInfo; sp mAudioDecoder; sp mCCDecoder; sp mRenderer; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp index 7b9dbb7..e5c83dd 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -80,7 +81,8 @@ NuPlayer::Renderer::Renderer( mVideoRenderingStartGeneration(0), mAudioRenderingStartGeneration(0), mAudioOffloadPauseTimeoutGeneration(0), - mAudioOffloadTornDown(false) { + mAudioOffloadTornDown(false), + mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER) { readProperties(); } @@ -237,8 +239,72 @@ void NuPlayer::Renderer::setPauseStartedTimeRealUs(int64_t realUs) { mPauseStartedTimeRealUs = realUs; } +bool NuPlayer::Renderer::openAudioSink( + const sp &format, + bool offloadOnly, + bool hasVideo, + uint32_t flags) { + sp msg = new AMessage(kWhatOpenAudioSink, id()); + msg->setMessage("format", format); + msg->setInt32("offload-only", offloadOnly); + msg->setInt32("has-video", hasVideo); + msg->setInt32("flags", flags); + + sp response; + msg->postAndAwaitResponse(&response); + + int32_t offload; + CHECK(response->findInt32("offload", &offload)); + return (offload != 0); +} + +void NuPlayer::Renderer::closeAudioSink() { + sp msg = new AMessage(kWhatCloseAudioSink, id()); + + sp response; + msg->postAndAwaitResponse(&response); +} + void NuPlayer::Renderer::onMessageReceived(const sp &msg) { switch (msg->what()) { + case kWhatOpenAudioSink: + { + sp format; + CHECK(msg->findMessage("format", &format)); + + int32_t offloadOnly; + CHECK(msg->findInt32("offload-only", &offloadOnly)); + + int32_t hasVideo; + CHECK(msg->findInt32("has-video", &hasVideo)); + + uint32_t flags; + CHECK(msg->findInt32("flags", (int32_t *)&flags)); + + bool offload = onOpenAudioSink(format, offloadOnly, hasVideo, flags); + + sp response = new AMessage; + response->setInt32("offload", offload); + + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + response->postReply(replyID); + + break; + } + + case kWhatCloseAudioSink: + { + uint32_t replyID; + CHECK(msg->senderAwaitsResponse(&replyID)); + + onCloseAudioSink(); + + sp response = new AMessage; + response->postReply(replyID); + break; + } + case kWhatStopAudioSink: { mAudioSink->stop(); @@ -1162,5 +1228,136 @@ void NuPlayer::Renderer::cancelAudioOffloadPauseTimeout() { } } +bool NuPlayer::Renderer::onOpenAudioSink( + const sp &format, + bool offloadOnly, + bool hasVideo, + uint32_t flags) { + ALOGV("openAudioSink: offloadOnly(%d) offloadingAudio(%d)", + offloadOnly, offloadingAudio()); + bool audioSinkChanged = false; + + int32_t numChannels; + CHECK(format->findInt32("channel-count", &numChannels)); + + int32_t channelMask; + if (!format->findInt32("channel-mask", &channelMask)) { + // signal to the AudioSink to derive the mask from count. + channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER; + } + + int32_t sampleRate; + CHECK(format->findInt32("sample-rate", &sampleRate)); + + if (offloadingAudio()) { + audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT; + AString mime; + CHECK(format->findString("mime", &mime)); + 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 { + ALOGV("Mime \"%s\" mapped to audio_format 0x%x", + mime.c_str(), audioFormat); + + int avgBitRate = -1; + format->findInt32("bit-rate", &avgBitRate); + + int32_t aacProfile = -1; + if (audioFormat == AUDIO_FORMAT_AAC + && format->findInt32("aac-profile", &aacProfile)) { + // Redefine AAC format as per aac profile + mapAACProfileToAudioFormat( + audioFormat, + aacProfile); + } + + 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 = true; + + if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) { + ALOGV("openAudioSink: no change in offload mode"); + // no change from previous configuration, everything ok. + return offloadingAudio(); + } + ALOGV("openAudioSink: try to open AudioSink in offload mode"); + flags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; + flags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER; + audioSinkChanged = true; + mAudioSink->close(); + err = mAudioSink->open( + sampleRate, + numChannels, + (audio_channel_mask_t)channelMask, + audioFormat, + 8 /* bufferCount */, + &NuPlayer::Renderer::AudioSinkCallback, + this, + (audio_output_flags_t)flags, + &offloadInfo); + + 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; + 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"); + } + } + } + if (!offloadOnly && !offloadingAudio()) { + flags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; + ALOGV("openAudioSink: open AudioSink in NON-offload mode"); + + audioSinkChanged = true; + mAudioSink->close(); + mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER; + CHECK_EQ(mAudioSink->open( + sampleRate, + numChannels, + (audio_channel_mask_t)channelMask, + AUDIO_FORMAT_PCM_16_BIT, + 8 /* bufferCount */, + NULL, + NULL, + (audio_output_flags_t)flags), + (status_t)OK); + mAudioSink->start(); + } + if (audioSinkChanged) { + onAudioSinkChanged(); + } + + return offloadingAudio(); +} + +void NuPlayer::Renderer::onCloseAudioSink() { + mAudioSink->close(); + mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER; +} + } // namespace android diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h index db1dab6..3e30226 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h @@ -70,6 +70,13 @@ struct NuPlayer::Renderer : public AHandler { int64_t getVideoLateByUs(); void setPauseStartedTimeRealUs(int64_t realUs); + bool openAudioSink( + const sp &format, + bool offloadOnly, + bool hasVideo, + uint32_t flags); + void closeAudioSink(); + enum { kWhatEOS = 'eos ', kWhatFlushComplete = 'fluC', @@ -100,6 +107,8 @@ private: kWhatAudioSinkChanged = 'auSC', kWhatPause = 'paus', kWhatResume = 'resm', + kWhatOpenAudioSink = 'opnA', + kWhatCloseAudioSink = 'clsA', kWhatStopAudioSink = 'stpA', kWhatDisableOffloadAudio = 'noOA', kWhatSetVideoFrameRate = 'sVFR', @@ -158,6 +167,7 @@ private: int32_t mAudioOffloadPauseTimeoutGeneration; bool mAudioOffloadTornDown; + audio_offload_info_t mCurrentOffloadInfo; size_t fillAudioBuffer(void *buffer, size_t size); @@ -183,6 +193,12 @@ private: void onResume(); void onSetVideoFrameRate(float fps); void onAudioOffloadTearDown(AudioOffloadTearDownReason reason); + bool onOpenAudioSink( + const sp &format, + bool offloadOnly, + bool hasVideo, + uint32_t flags); + void onCloseAudioSink(); void notifyEOS(bool audio, status_t finalResult, int64_t delayUs = 0); void notifyFlushComplete(bool audio); -- cgit v1.1