diff options
author | James Dong <jdong@google.com> | 2010-05-04 14:40:28 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-05-04 14:40:28 -0700 |
commit | 8d30b2d284fee002242dd412ddda39ce91845faf (patch) | |
tree | 0098cc5ea1403aaec6d2b835866bd0e8dd775bcd /media/libstagefright | |
parent | ce0bd71735532f53014cc299f684302f357c471a (diff) | |
parent | abed93a51b6b476ecb23a2c22faa43a219eb60a7 (diff) | |
download | frameworks_base-8d30b2d284fee002242dd412ddda39ce91845faf.zip frameworks_base-8d30b2d284fee002242dd412ddda39ce91845faf.tar.gz frameworks_base-8d30b2d284fee002242dd412ddda39ce91845faf.tar.bz2 |
Merge "Support AAC recording" into kraken
Diffstat (limited to 'media/libstagefright')
-rw-r--r-- | media/libstagefright/AudioSource.cpp | 4 | ||||
-rw-r--r-- | media/libstagefright/MPEG4Writer.cpp | 107 | ||||
-rw-r--r-- | media/libstagefright/OMXCodec.cpp | 80 |
3 files changed, 166 insertions, 25 deletions
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp index edabaf9..abd8abc 100644 --- a/media/libstagefright/AudioSource.cpp +++ b/media/libstagefright/AudioSource.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +//#define LOG_NDEBUG 0 +#define LOG_TAG "AudioSource" +#include <utils/Log.h> + #include <media/stagefright/AudioSource.h> #include <media/AudioRecord.h> diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index 5ff2abe..e6336e7 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +//#define LOG_NDEBUG 0 +#define LOG_TAG "MPEG4Writer" +#include <utils/Log.h> + #include <arpa/inet.h> #include <ctype.h> @@ -58,6 +62,8 @@ private: }; List<SampleInfo> mSampleInfos; + List<int32_t> mStssTableEntries; + void *mCodecSpecificData; size_t mCodecSpecificDataSize; bool mGotAllCodecSpecificData; @@ -522,7 +528,8 @@ void MPEG4Writer::Track::threadEntry() { sp<MetaData> meta = mSource->getFormat(); const char *mime; meta->findCString(kKeyMIMEType, &mime); - bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4); + bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) || + !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC); bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); int32_t count = 0; @@ -668,6 +675,9 @@ void MPEG4Writer::Track::threadEntry() { info.offset = offset; + + bool is_audio = !strncasecmp(mime, "audio/", 6); + int64_t timestampUs; CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); @@ -680,6 +690,12 @@ void MPEG4Writer::Track::threadEntry() { mSampleInfos.push_back(info); + int32_t isSync = false; + buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync); + if (isSync) { + mStssTableEntries.push_back(mSampleInfos.size()); + } + // Our timestamp is in ms. buffer->release(); buffer = NULL; } @@ -735,8 +751,8 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { success = success && mMeta->findInt32(kKeyHeight, &height); CHECK(success); - mOwner->writeInt32(width); - mOwner->writeInt32(height); + mOwner->writeInt32(width << 16); // 32-bit fixed-point value + mOwner->writeInt32(height << 16); // 32-bit fixed-point value } mOwner->endBox(); // tkhd @@ -754,26 +770,15 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { mOwner->beginBox("hdlr"); mOwner->writeInt32(0); // version=0, flags=0 - mOwner->writeInt32(0); // predefined - mOwner->writeFourcc(is_audio ? "soun" : "vide"); + mOwner->writeInt32(0); // component type: should be mhlr + mOwner->writeFourcc(is_audio ? "soun" : "vide"); // component subtype mOwner->writeInt32(0); // reserved mOwner->writeInt32(0); // reserved mOwner->writeInt32(0); // reserved - mOwner->writeCString(""); // name + mOwner->writeCString("SoundHandler"); // name mOwner->endBox(); mOwner->beginBox("minf"); - - mOwner->beginBox("dinf"); - mOwner->beginBox("dref"); - mOwner->writeInt32(0); // version=0, flags=0 - mOwner->writeInt32(1); - mOwner->beginBox("url "); - mOwner->writeInt32(1); // version=0, flags=1 - mOwner->endBox(); // url - mOwner->endBox(); // dref - mOwner->endBox(); // dinf - if (is_audio) { mOwner->beginBox("smhd"); mOwner->writeInt32(0); // version=0, flags=0 @@ -789,7 +794,18 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { mOwner->writeInt16(0); mOwner->endBox(); } - mOwner->endBox(); // minf + + mOwner->beginBox("dinf"); + mOwner->beginBox("dref"); + mOwner->writeInt32(0); // version=0, flags=0 + mOwner->writeInt32(1); + mOwner->beginBox("url "); + mOwner->writeInt32(1); // version=0, flags=1 + mOwner->endBox(); // url + mOwner->endBox(); // dref + mOwner->endBox(); // dinf + + mOwner->endBox(); // minf mOwner->beginBox("stbl"); @@ -802,6 +818,8 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { fourcc = "samr"; } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) { fourcc = "sawb"; + } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { + fourcc = "mp4a"; } else { LOGE("Unknown mime type '%s'.", mime); CHECK(!"should not be here, unknown mime type."); @@ -810,10 +828,12 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { mOwner->beginBox(fourcc); // audio format mOwner->writeInt32(0); // reserved mOwner->writeInt16(0); // reserved - mOwner->writeInt16(0); // data ref index + mOwner->writeInt16(0x1); // data ref index mOwner->writeInt32(0); // reserved mOwner->writeInt32(0); // reserved - mOwner->writeInt16(2); // channel count + int32_t nChannels; + CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels)); + mOwner->writeInt16(nChannels); // channel count mOwner->writeInt16(16); // sample size mOwner->writeInt16(0); // predefined mOwner->writeInt16(0); // reserved @@ -823,6 +843,38 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { CHECK(success); mOwner->writeInt32(samplerate << 16); + if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { + mOwner->beginBox("esds"); + + mOwner->writeInt32(0); // version=0, flags=0 + mOwner->writeInt8(0x03); // ES_DescrTag + mOwner->writeInt8(23 + mCodecSpecificDataSize); + mOwner->writeInt16(0x0000);// ES_ID + mOwner->writeInt8(0x00); + + mOwner->writeInt8(0x04); // DecoderConfigDescrTag + mOwner->writeInt8(15 + mCodecSpecificDataSize); + mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2 + mOwner->writeInt8(0x15); // streamType AudioStream + + mOwner->writeInt16(0x03); // XXX + mOwner->writeInt8(0x00); // buffer size 24-bit + mOwner->writeInt32(96000); // max bit rate + mOwner->writeInt32(96000); // avg bit rate + + mOwner->writeInt8(0x05); // DecoderSpecificInfoTag + mOwner->writeInt8(mCodecSpecificDataSize); + mOwner->write(mCodecSpecificData, mCodecSpecificDataSize); + + static const uint8_t kData2[] = { + 0x06, // SLConfigDescriptorTag + 0x01, + 0x02 + }; + mOwner->write(kData2, sizeof(kData2)); + + mOwner->endBox(); // esds + } mOwner->endBox(); } else { if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) { @@ -883,7 +935,7 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { 0x00, 0x03, 0xe8, 0x00 }; mOwner->write(kData, sizeof(kData)); - + mOwner->writeInt8(0x05); // DecoderSpecificInfoTag mOwner->writeInt8(mCodecSpecificDataSize); @@ -943,6 +995,17 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { mOwner->endBox(); // stts + if (!is_audio) { + mOwner->beginBox("stss"); + mOwner->writeInt32(0); // version=0, flags=0 + mOwner->writeInt32(mStssTableEntries.size()); // number of sync frames + for (List<int32_t>::iterator it = mStssTableEntries.begin(); + it != mStssTableEntries.end(); ++it) { + mOwner->writeInt32(*it); + } + mOwner->endBox(); // stss + } + mOwner->beginBox("stsz"); mOwner->writeInt32(0); // version=0, flags=0 mOwner->writeInt32(0); // default sample size @@ -969,7 +1032,7 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { mOwner->writeInt32(0); // version=0, flags=0 mOwner->writeInt32(mSampleInfos.size()); for (List<SampleInfo>::iterator it = mSampleInfos.begin(); - it != mSampleInfos.end(); ++it, ++n) { + it != mSampleInfos.end(); ++it) { mOwner->writeInt64((*it).offset); } mOwner->endBox(); // co64 diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp index 41be9ac..b7d6d42 100644 --- a/media/libstagefright/OMXCodec.cpp +++ b/media/libstagefright/OMXCodec.cpp @@ -520,6 +520,7 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) { setAACFormat(numChannels, sampleRate); } + if (!strncasecmp(mMIME, "video/", 6)) { int32_t width, height; bool success = meta->findInt32(kKeyWidth, &width); @@ -567,7 +568,8 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) { } if (!strcmp(mComponentName, "OMX.TI.AMR.encode") - || !strcmp(mComponentName, "OMX.TI.WBAMR.encode")) { + || !strcmp(mComponentName, "OMX.TI.WBAMR.encode") + || !strcmp(mComponentName, "OMX.TI.AAC.encode")) { setMinBufferSize(kPortIndexOutput, 8192); // XXX } @@ -708,7 +710,7 @@ void OMXCodec::setVideoInputFormat( OMX_COLOR_FORMATTYPE colorFormat = OMX_COLOR_FormatYUV420SemiPlanar; if (!strcasecmp("OMX.TI.Video.encoder", mComponentName)) { - colorFormat = OMX_COLOR_FormatYUV420Planar; + colorFormat = OMX_COLOR_FormatYCbYCr; } @@ -2127,11 +2129,24 @@ void OMXCodec::setState(State newState) { void OMXCodec::setRawAudioFormat( OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) { + + // port definition + OMX_PARAM_PORTDEFINITIONTYPE def; + InitOMXParams(&def); + def.nPortIndex = portIndex; + status_t err = mOMX->getParameter( + mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)); + CHECK_EQ(err, OK); + def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; + CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition, + &def, sizeof(def)), OK); + + // pcm param OMX_AUDIO_PARAM_PCMMODETYPE pcmParams; InitOMXParams(&pcmParams); pcmParams.nPortIndex = portIndex; - status_t err = mOMX->getParameter( + err = mOMX->getParameter( mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams)); CHECK_EQ(err, OK); @@ -2171,6 +2186,8 @@ void OMXCodec::setAMRFormat(bool isWAMR) { CHECK_EQ(err, OK); def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF; + + // XXX: Select bandmode based on bit rate def.eAMRBandMode = isWAMR ? OMX_AUDIO_AMRBandModeWB0 : OMX_AUDIO_AMRBandModeNB0; @@ -2191,8 +2208,60 @@ void OMXCodec::setAMRFormat(bool isWAMR) { } void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate) { + CHECK(numChannels == 1 || numChannels == 2); if (mIsEncoder) { + //////////////// input port //////////////////// setRawAudioFormat(kPortIndexInput, sampleRate, numChannels); + + //////////////// output port //////////////////// + // format + OMX_AUDIO_PARAM_PORTFORMATTYPE format; + format.nPortIndex = kPortIndexOutput; + format.nIndex = 0; + status_t err = OMX_ErrorNone; + while (OMX_ErrorNone == err) { + CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioPortFormat, + &format, sizeof(format)), OK); + if (format.eEncoding == OMX_AUDIO_CodingAAC) { + break; + } + format.nIndex++; + } + CHECK_EQ(OK, err); + CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioPortFormat, + &format, sizeof(format)), OK); + + // port definition + OMX_PARAM_PORTDEFINITIONTYPE def; + InitOMXParams(&def); + def.nPortIndex = kPortIndexOutput; + CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, + &def, sizeof(def)), OK); + def.format.audio.bFlagErrorConcealment = OMX_TRUE; + def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; + CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition, + &def, sizeof(def)), OK); + + // profile + OMX_AUDIO_PARAM_AACPROFILETYPE profile; + InitOMXParams(&profile); + profile.nPortIndex = kPortIndexOutput; + CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioAac, + &profile, sizeof(profile)), OK); + profile.nChannels = numChannels; + profile.eChannelMode = (numChannels == 1? + OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo); + profile.nSampleRate = sampleRate; + profile.nBitRate = 96000; // XXX + profile.nAudioBandWidth = 0; + profile.nFrameLength = 0; + profile.nAACtools = OMX_AUDIO_AACToolAll; + profile.nAACERtools = OMX_AUDIO_AACERNone; + profile.eAACProfile = OMX_AUDIO_AACObjectLC; + profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; + CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioAac, + &profile, sizeof(profile)), OK); + } else { OMX_AUDIO_PARAM_AACPROFILETYPE profile; InitOMXParams(&profile); @@ -2961,6 +3030,11 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) { } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) { mOutputFormat->setCString( kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); + int32_t numChannels, sampleRate; + inputFormat->findInt32(kKeyChannelCount, &numChannels); + inputFormat->findInt32(kKeySampleRate, &sampleRate); + mOutputFormat->setInt32(kKeyChannelCount, numChannels); + mOutputFormat->setInt32(kKeySampleRate, sampleRate); } else { CHECK(!"Should not be here. Unknown audio encoding."); } |