diff options
author | Steve Kondik <shade@chemlab.org> | 2014-10-07 23:14:32 -0700 |
---|---|---|
committer | Steve Kondik <shade@chemlab.org> | 2014-10-08 17:56:27 -0700 |
commit | bf1690beb04508b079cb255a13c8fb0b9e098e29 (patch) | |
tree | 335cc8201adf597c93618dfbeec89c846593754e | |
parent | 0ea7bfd6ae3dd587a4981969edf74361fc469a4d (diff) | |
download | frameworks_av-bf1690beb04508b079cb255a13c8fb0b9e098e29.tar.gz frameworks_av-bf1690beb04508b079cb255a13c8fb0b9e098e29.tar.bz2 frameworks_av-bf1690beb04508b079cb255a13c8fb0b9e098e29.zip |
stagefright: More high-resolution audio support
* Clean up the "error driven" fallback code we had before and
reconfigure components if the output bit width needs to change
(a2dp/usb fallback).
* Decode various formats (AC3/DTS/EAC3) which output floating point
samples using FFMPEG, which will output 24-bit PCM for us.
Change-Id: I94f5fa59f5f737be8969df4c5ad4295c45cb8657
-rw-r--r-- | include/media/stagefright/ExtendedCodec.h | 6 | ||||
-rw-r--r-- | media/libstagefright/AudioPlayer.cpp | 10 | ||||
-rw-r--r-- | media/libstagefright/AwesomePlayer.cpp | 3 | ||||
-rw-r--r-- | media/libstagefright/ExtendedCodec.cpp | 41 | ||||
-rw-r--r-- | media/libstagefright/OMXCodec.cpp | 50 | ||||
-rw-r--r-- | media/libstagefright/Utils.cpp | 16 |
6 files changed, 97 insertions, 29 deletions
diff --git a/include/media/stagefright/ExtendedCodec.h b/include/media/stagefright/ExtendedCodec.h index eaca72c859..5ec73a78ac 100644 --- a/include/media/stagefright/ExtendedCodec.h +++ b/include/media/stagefright/ExtendedCodec.h @@ -147,6 +147,12 @@ struct ExtendedCodec { static bool isSourcePauseRequired(const char *componentName); +#if defined(ENABLE_AV_ENHANCEMENTS) || defined(ENABLE_OFFLOAD_ENHANCEMENTS) + static status_t updatePcmOutputFormat(const sp<MetaData> &meta, + sp<IOMX> OMXhandle, IOMX::node_id nodeID, + const char* componentName); +#endif + private: static const char* getMsgKey(int key ); diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp index 6b8399bdf6..0a00161924 100644 --- a/media/libstagefright/AudioPlayer.cpp +++ b/media/libstagefright/AudioPlayer.cpp @@ -182,13 +182,13 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) { if (mapMimeToAudioFormat(audioFormat, mime) != OK) { ALOGE("Couldn't map mime type \"%s\" to a valid AudioSystem::audio_format", mime); audioFormat = AUDIO_FORMAT_INVALID; - } else { + } else if (audio_is_linear_pcm(audioFormat) || audio_is_offload_pcm(audioFormat)) { #if defined(QCOM_HARDWARE) || defined(ENABLE_OFFLOAD_ENHANCEMENTS) // Override audio format for PCM offload - if (audioFormat == AUDIO_FORMAT_PCM_24_BIT || bitWidth == 24) { - ALOGI("24-bit PCM offload enabled"); + if (bitWidth >= 24) { + ALOGD("24-bit PCM offload enabled format=%d", audioFormat); audioFormat = AUDIO_FORMAT_PCM_24_BIT_OFFLOAD; - } else if (audioFormat == AUDIO_FORMAT_PCM_16_BIT) { + } else { audioFormat = AUDIO_FORMAT_PCM_16_BIT_OFFLOAD; } #endif @@ -225,7 +225,7 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) { offloadInfo.has_video = ((mCreateFlags & HAS_VIDEO) != 0); offloadInfo.is_streaming = ((mCreateFlags & IS_STREAMING) != 0); #if defined(ENABLE_AV_ENHANCEMENTS) || defined(ENABLE_OFFLOAD_ENHANCEMENTS) - offloadInfo.bit_width = bitWidth; + offloadInfo.bit_width = bitWidth >= 24 ? 24 : bitWidth; #endif } diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 7fc4512add..cc152d8385 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -1931,6 +1931,7 @@ status_t AwesomePlayer::initAudioDecoder() { mAudioSource = mAudioTrack; #ifndef QCOM_DIRECTTRACK } else { + mOmxSource->getFormat()->setInt32(kKeySampleBits, 16); mAudioSource = mOmxSource; #endif } @@ -1942,7 +1943,7 @@ status_t AwesomePlayer::initAudioDecoder() { mAudioTrack->getFormat()->findInt32(kKeySampleBits, &bitsPerSample); if (!mOffloadAudio && mAudioSource != NULL) { - ALOGI("Could not offload audio decode, try pcm offload"); + ALOGI("Could not offload audio decode, try pcm offload (%d-bit)", bitsPerSample); sp<MetaData> format = mAudioSource->getFormat(); if (durationUs >= 0) { format->setInt64(kKeyDuration, durationUs); diff --git a/media/libstagefright/ExtendedCodec.cpp b/media/libstagefright/ExtendedCodec.cpp index 9a048d73e0..bb87490bae 100644 --- a/media/libstagefright/ExtendedCodec.cpp +++ b/media/libstagefright/ExtendedCodec.cpp @@ -323,7 +323,7 @@ status_t ExtendedCodec::setAudioFormat( const sp<AMessage> &msg, const char* mime, sp<IOMX> OMXhandle, IOMX::node_id nodeID, bool isEncoder ) { ALOGV("setAudioFormat called"); - status_t err = OK; + status_t err = ERROR_UNSUPPORTED; if ((!strcasecmp(MEDIA_MIMETYPE_AUDIO_AC3, mime)) || (!strcasecmp(MEDIA_MIMETYPE_AUDIO_EAC3, mime))){ @@ -333,16 +333,19 @@ status_t ExtendedCodec::setAudioFormat( //setAC3Format(numChannels, sampleRate, OMXhandle, nodeID); CHECK(msg->findInt32("channel-count", &numChannels)); CHECK(msg->findInt32("sample-rate", &sampleRate)); + err = OK; } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_EVRC, mime)) { int32_t numChannels, sampleRate; CHECK(msg->findInt32("channel-count", &numChannels)); CHECK(msg->findInt32("sample-rate", &sampleRate)); setEVRCFormat(numChannels, sampleRate, OMXhandle, nodeID, isEncoder ); + err = OK; } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_QCELP, mime)) { int32_t numChannels, sampleRate; CHECK(msg->findInt32("channel-count", &numChannels)); CHECK(msg->findInt32("sample-rate", &sampleRate)); setQCELPFormat(numChannels, sampleRate, OMXhandle, nodeID, isEncoder); + err = OK; } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_WMA, mime)) { err = setWMAFormat(msg, OMXhandle, nodeID, isEncoder); } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS, mime)) { @@ -418,8 +421,10 @@ status_t ExtendedCodec::setSupportedRole( "video_decoder.divx", NULL }, { MEDIA_MIMETYPE_VIDEO_WMV, "video_decoder.vc1", NULL }, +#if 0 // handled by FFMPEG { MEDIA_MIMETYPE_AUDIO_AC3, "audio_decoder.ac3", NULL }, +#endif { MEDIA_MIMETYPE_AUDIO_WMA, "audio_decoder.wma" , NULL }, { MEDIA_MIMETYPE_VIDEO_HEVC, @@ -1399,3 +1404,37 @@ namespace android { } //namespace android #endif //ENABLE_AV_ENHANCEMENTS + +#if defined(ENABLE_AV_ENHANCEMENTS) || defined(ENABLE_OFFLOAD_ENHANCEMENTS) +namespace android { + + status_t ExtendedCodec::updatePcmOutputFormat( + const sp<MetaData> &meta, sp<IOMX> OMXhandle, IOMX::node_id nodeID, + const char* componentName) { + + OMX_AUDIO_PARAM_PCMMODETYPE param; + int32_t bits_per_sample = 16; + int32_t sample_rate; + int32_t channels; + status_t err = OK; + + CHECK(meta->findInt32(kKeyChannelCount, &channels)); + CHECK(meta->findInt32(kKeySampleRate, &sample_rate)); + + if (!meta->findInt32(kKeySampleBits, &bits_per_sample)) { + ALOGD("Bits per sample not specified, using default 16"); + } + ALOGD("Update output bit width = %d", bits_per_sample); + + InitOMXParams(¶m); + param.nPortIndex = kPortIndexOutput; + param.nChannels = channels; + param.nSamplingRate = sample_rate; + param.nBitPerSample = bits_per_sample; + + return OMXhandle->setParameter(nodeID, OMX_IndexParamAudioPcm, + ¶m, sizeof(param)); + } + +} // namespace android +#endif diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 0ac0d2a02e..8646fbe492 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -850,12 +850,19 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) { CODEC_LOGE("setMP2Format() failed (err = %d)", err); return err; } - } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AC3, mMIME)) { + } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AC3, mMIME) || + !strcasecmp(MEDIA_MIMETYPE_AUDIO_EAC3, mMIME)) { status_t err = setAC3Format(meta); if (err != OK) { CODEC_LOGE("setAC3Format() failed (err = %d)", err); return err; } +#ifdef ENABLE_AV_ENHANCEMENTS + // FFMPEG will convert floating point to 24-bit PCM + if (ExtendedUtils::isHiresAudioEnabled()) { + meta->setInt32(kKeySampleBits, 24); + } +#endif } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_APE, mMIME)) { status_t err = setAPEFormat(meta); if (err != OK) { @@ -882,16 +889,18 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) { } #ifdef QCOM_HARDWARE } else { - if (mIsEncoder && !mIsVideo) { - int32_t numChannels, sampleRate; - CHECK(meta->findInt32(kKeyChannelCount, &numChannels)); - CHECK(meta->findInt32(kKeySampleRate, &sampleRate)); - setRawAudioFormat(kPortIndexInput, sampleRate, numChannels); - } - status_t err = ExtendedCodec::setAudioFormat( - meta, mMIME, mOMX, mNode, mIsEncoder); - if(OK != err) { - return err; + if (!mIsVideo) { + if (mIsEncoder) { + int32_t numChannels, sampleRate; + CHECK(meta->findInt32(kKeyChannelCount, &numChannels)); + CHECK(meta->findInt32(kKeySampleRate, &sampleRate)); + setRawAudioFormat(kPortIndexInput, sampleRate, numChannels); + } + status_t err = ExtendedCodec::setAudioFormat( + meta, mMIME, mOMX, mNode, mIsEncoder); + if(OK != err) { + return err; + } } #endif } @@ -2097,6 +2106,13 @@ status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) { } } +#if defined(ENABLE_AV_ENHANCEMENTS) || defined(ENABLE_OFFLOAD_ENHANCEMENTS) + if (!mIsVideo && portIndex == kPortIndexOutput && + !strncmp(mComponentName, "OMX.ffmpeg.", 11)) { + ExtendedCodec::updatePcmOutputFormat(mOutputFormat, mOMX, mNode, NULL); + } +#endif + OMX_PARAM_PORTDEFINITIONTYPE def; InitOMXParams(&def); def.nPortIndex = portIndex; @@ -4514,7 +4530,7 @@ status_t OMXCodec::setFLACFormat(const sp<MetaData> &meta) { int32_t numChannels = 0; int32_t sampleRate = 0; - int32_t bitsPerSample = 0; + int32_t bitsPerSample = 16; OMX_AUDIO_PARAM_FLACTYPE param; if (mIsEncoder) { @@ -4524,10 +4540,12 @@ status_t OMXCodec::setFLACFormat(const sp<MetaData> &meta) CHECK(meta->findInt32(kKeyChannelCount, &numChannels)); CHECK(meta->findInt32(kKeySampleRate, &sampleRate)); - CHECK(meta->findInt32(kKeySampleBits, &bitsPerSample)); + if (!meta->findInt32(kKeySampleBits, &bitsPerSample)) { + CODEC_LOGV("BitsPerSample not set, using default"); + } - CODEC_LOGV("Channels: %d, SampleRate: %d", - numChannels, sampleRate); + CODEC_LOGV("Channels: %d, SampleRate: %d, BitsPerSample: %d", + numChannels, sampleRate, bitsPerSample); InitOMXParams(¶m); param.nPortIndex = kPortIndexInput; @@ -4539,7 +4557,7 @@ status_t OMXCodec::setFLACFormat(const sp<MetaData> &meta) param.nChannels = numChannels; param.nSampleRate = sampleRate; - //param.nBitsPerSample = bitsPerSample; + param.nBitsPerSample = bitsPerSample; err = mOMX->setParameter( mNode, OMX_IndexParamAudioFlac, ¶m, sizeof(param)); diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp index 5187b63914..2313a16161 100644 --- a/media/libstagefright/Utils.cpp +++ b/media/libstagefright/Utils.cpp @@ -603,20 +603,20 @@ bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo, const sp<MetaData if (!meta->findInt32(kKeySampleBits, &bitWidth)) { ALOGV("bits per sample not set, using default %d", bitWidth); } - info.bit_width = bitWidth; + info.bit_width = bitWidth >= 24 ? 24 : bitWidth; #endif info.format = AUDIO_FORMAT_INVALID; if (mapMimeToAudioFormat(info.format, mime) != OK) { ALOGE(" Couldn't map mime type \"%s\" to a valid AudioSystem::audio_format !", mime); return false; - } else { + } else if (audio_is_linear_pcm(info.format) || audio_is_offload_pcm(info.format)) { #if defined(QCOM_HARDWARE) || defined(ENABLE_OFFLOAD_ENHANCEMENTS) // Override audio format for PCM offload - if (bitWidth == 24) { + if (bitWidth >= 24) { ALOGD("24-bit PCM offload enabled"); info.format = AUDIO_FORMAT_PCM_24_BIT_OFFLOAD; - } else if (info.format == AUDIO_FORMAT_PCM_16_BIT) { + } else { info.format = AUDIO_FORMAT_PCM_16_BIT_OFFLOAD; } #endif @@ -628,7 +628,7 @@ bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo, const sp<MetaData return false; } - ALOGV("Mime type \"%s\" mapped to audio_format %d", mime, info.format); + ALOGV("Mime type \"%s\" mapped to audio_format 0x%x", mime, info.format); // check whether it is ELD/LD/main content -> no offloading // FIXME: this should depend on audio DSP capabilities. mapMimeToAudioFormat() should use the @@ -682,7 +682,11 @@ bool canOffloadStream(const sp<MetaData>& meta, bool hasVideo, const sp<MetaData bool canOffload = AudioSystem::isOffloadSupported(info); #if defined(ENABLE_AV_ENHANCEMENTS) || defined(ENABLE_OFFLOAD_ENHANCEMENTS) - ExtendedUtils::updateOutputBitWidth(meta, canOffload); + // If we can't offload a 24-bit stream, we need to downgrade + // it to 16-bits. Codec will reconfigure for new bit width. + if (audio_is_offload_pcm(info.format)) { + ExtendedUtils::updateOutputBitWidth(meta, canOffload); + } #endif return canOffload; |