diff options
author | Andreas Huber <andih@google.com> | 2011-09-28 12:37:36 -0700 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2011-09-28 12:37:36 -0700 |
commit | 729de186450f78c099637e1fce743fe531862c52 (patch) | |
tree | bf05611a1943104189abce2f9b09514f2ec2adeb | |
parent | ac4d4d3698e920b9f5c648a781df5b6af8bcfdf0 (diff) |
Support AMR, G.711 and vorbis audio in ACodec and friends.
Change-Id: I08c03219bf2d60fc5c6e89957bd4b4c615570983
-rw-r--r-- | cmds/stagefright/sf2.cpp | 51 | ||||
-rw-r--r-- | include/media/stagefright/ACodec.h | 6 | ||||
-rw-r--r-- | media/libstagefright/ACodec.cpp | 96 | ||||
-rwxr-xr-x | media/libstagefright/OMXCodec.cpp | 2 |
4 files changed, 147 insertions, 8 deletions
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp index 263ecd14..f547e019 100644 --- a/cmds/stagefright/sf2.cpp +++ b/cmds/stagefright/sf2.cpp @@ -46,7 +46,8 @@ struct Controller : public AHandler { mDecodeAudio(decodeAudio), mSurface(surface), mRenderToSurface(renderToSurface), - mCodec(new ACodec) { + mCodec(new ACodec), + mIsVorbis(false) { CHECK(!mDecodeAudio || mSurface == NULL); } @@ -85,6 +86,12 @@ protected: if (!strncasecmp(mDecodeAudio ? "audio/" : "video/", mime, 6)) { mSource = extractor->getTrack(i); + + if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) { + mIsVorbis = true; + } else { + mIsVorbis = false; + } break; } } @@ -227,6 +234,7 @@ private: bool mRenderToSurface; sp<ACodec> mCodec; sp<MediaSource> mSource; + bool mIsVorbis; Vector<sp<ABuffer> > mCSD; size_t mCSDIndex; @@ -369,6 +377,20 @@ private: buffer->meta()->setInt32("csd", true); mCSD.push(buffer); + } else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) { + sp<ABuffer> buffer = new ABuffer(size); + memcpy(buffer->data(), data, size); + + buffer->meta()->setInt32("csd", true); + mCSD.push(buffer); + + CHECK(meta->findData(kKeyVorbisBooks, &type, &data, &size)); + + buffer = new ABuffer(size); + memcpy(buffer->data(), data, size); + + buffer->meta()->setInt32("csd", true); + mCSD.push(buffer); } int32_t maxInputSize; @@ -423,10 +445,17 @@ private: } } - if (inBuffer->range_length() > sizeLeft) { + size_t sizeNeeded = inBuffer->range_length(); + if (mIsVorbis) { + // Vorbis data is suffixed with the number of + // valid samples on the page. + sizeNeeded += sizeof(int32_t); + } + + if (sizeNeeded > sizeLeft) { if (outBuffer->size() == 0) { LOGE("Unable to fit even a single input buffer of size %d.", - inBuffer->range_length()); + sizeNeeded); } CHECK_GT(outBuffer->size(), 0u); @@ -448,10 +477,22 @@ private: + inBuffer->range_offset(), inBuffer->range_length()); + if (mIsVorbis) { + int32_t numPageSamples; + if (!inBuffer->meta_data()->findInt32( + kKeyValidSamples, &numPageSamples)) { + numPageSamples = -1; + } + + memcpy(outBuffer->data() + + outBuffer->size() + inBuffer->range_length(), + &numPageSamples, sizeof(numPageSamples)); + } + outBuffer->setRange( - 0, outBuffer->size() + inBuffer->range_length()); + 0, outBuffer->size() + sizeNeeded); - sizeLeft -= inBuffer->range_length(); + sizeLeft -= sizeNeeded; inBuffer->release(); inBuffer = NULL; diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h index 9da99077..58228772 100644 --- a/include/media/stagefright/ACodec.h +++ b/include/media/stagefright/ACodec.h @@ -151,6 +151,12 @@ private: OMX_VIDEO_CODINGTYPE compressionFormat); status_t setupAACDecoder(int32_t numChannels, int32_t sampleRate); + status_t setupAMRDecoder(bool isWAMR); + status_t setupG711Decoder(int32_t numChannels); + + status_t setupRawAudioFormat( + OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels); + status_t setMinBufferSize(OMX_U32 portIndex, size_t size); status_t initNativeWindow(); diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index a3746cdc..9cb18de2 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -687,6 +687,8 @@ void ACodec::setComponentRole( "audio_decoder.amrwb", "audio_encoder.amrwb" }, { MEDIA_MIMETYPE_AUDIO_AAC, "audio_decoder.aac", "audio_encoder.aac" }, + { MEDIA_MIMETYPE_AUDIO_VORBIS, + "audio_decoder.vorbis", "audio_encoder.vorbis" }, { MEDIA_MIMETYPE_VIDEO_AVC, "video_decoder.avc", "video_encoder.avc" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, @@ -750,9 +752,19 @@ void ACodec::configureCodec( CHECK(msg->findInt32("sample-rate", &sampleRate)); CHECK_EQ(setupAACDecoder(numChannels, sampleRate), (status_t)OK); - } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { - } else { - TRESPASS(); + } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) { + CHECK_EQ(setupAMRDecoder(false /* isWAMR */), (status_t)OK); + } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { + CHECK_EQ(setupAMRDecoder(true /* isWAMR */), (status_t)OK); + } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW) + || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) { + // These are PCM-like formats with a fixed sample rate but + // a variable number of channels. + + int32_t numChannels; + CHECK(msg->findInt32("channel-count", &numChannels)); + + CHECK_EQ(setupG711Decoder(numChannels), (status_t)OK); } int32_t maxInputSize; @@ -824,6 +836,84 @@ status_t ACodec::setupAACDecoder(int32_t numChannels, int32_t sampleRate) { return err; } +status_t ACodec::setupAMRDecoder(bool isWAMR) { + OMX_AUDIO_PARAM_AMRTYPE def; + InitOMXParams(&def); + def.nPortIndex = kPortIndexInput; + + status_t err = + mOMX->getParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); + + if (err != OK) { + return err; + } + + def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; + + def.eAMRBandMode = + isWAMR ? OMX_AUDIO_AMRBandModeWB0 : OMX_AUDIO_AMRBandModeNB0; + + return mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def)); +} + +status_t ACodec::setupG711Decoder(int32_t numChannels) { + return setupRawAudioFormat( + kPortIndexInput, 8000 /* sampleRate */, numChannels); +} + +status_t ACodec::setupRawAudioFormat( + OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { + OMX_PARAM_PORTDEFINITIONTYPE def; + InitOMXParams(&def); + def.nPortIndex = portIndex; + + status_t err = mOMX->getParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + + if (err != OK) { + return err; + } + + def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; + + err = mOMX->setParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + + if (err != OK) { + return err; + } + + OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; + InitOMXParams(&pcmParams); + pcmParams.nPortIndex = portIndex; + + err = mOMX->getParameter( + mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); + + if (err != OK) { + return err; + } + + pcmParams.nChannels = numChannels; + pcmParams.eNumData = OMX_NumericalDataSigned; + pcmParams.bInterleaved = OMX_TRUE; + pcmParams.nBitPerSample = 16; + pcmParams.nSamplingRate = sampleRate; + pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear; + + if (numChannels == 1) { + pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF; + } else { + CHECK_EQ(numChannels, 2); + + pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF; + pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF; + } + + return mOMX->setParameter( + mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); +} + status_t ACodec::setVideoPortFormatType( OMX_U32 portIndex, OMX_VIDEO_CODINGTYPE compressionFormat, diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 9eb1469c..e94a8d71 100755 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -1485,6 +1485,8 @@ void OMXCodec::setComponentRole( "audio_decoder.amrwb", "audio_encoder.amrwb" }, { MEDIA_MIMETYPE_AUDIO_AAC, "audio_decoder.aac", "audio_encoder.aac" }, + { MEDIA_MIMETYPE_AUDIO_VORBIS, + "audio_decoder.vorbis", "audio_encoder.vorbis" }, { MEDIA_MIMETYPE_VIDEO_AVC, "video_decoder.avc", "video_encoder.avc" }, { MEDIA_MIMETYPE_VIDEO_MPEG4, |