diff options
author | Steve Kondik <steve@cyngn.com> | 2015-12-09 20:44:26 -0800 |
---|---|---|
committer | Steve Kondik <steve@cyngn.com> | 2015-12-13 13:16:01 -0800 |
commit | 6dde130280d6ead297170211b005cc809e7f7bde (patch) | |
tree | a2053b10d736cadc85ce1adfe18d6256875da325 /media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp | |
parent | fb9765480b10aaf39ac82149abe28d1805e1fe92 (diff) | |
download | frameworks_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/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp')
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp | 214 |
1 files changed, 118 insertions, 96 deletions
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, |