diff options
author | James Dong <jdong@google.com> | 2010-04-22 17:27:04 -0700 |
---|---|---|
committer | James Dong <jdong@google.com> | 2010-05-03 15:47:41 -0700 |
commit | 050b28a593350047845a45a14cc5026221ac1620 (patch) | |
tree | 118de60bec960d36dd3784439f84e2bc1bba6d9f /media/libstagefright/MPEG4Writer.cpp | |
parent | 86f69c1f41dcf4e0826b17ecf7fd71eb353b0782 (diff) | |
download | frameworks_av-050b28a593350047845a45a14cc5026221ac1620.zip frameworks_av-050b28a593350047845a45a14cc5026221ac1620.tar.gz frameworks_av-050b28a593350047845a45a14cc5026221ac1620.tar.bz2 |
Support AAC recording
- Extend the audio recording to AAC format
- Add support for setting some recording parameters
- Add stss box to the meta data in the recorded file
Change-Id: I41167bfd9d70ef9cd33906f8437b39c232b6d3b7
Diffstat (limited to 'media/libstagefright/MPEG4Writer.cpp')
-rw-r--r-- | media/libstagefright/MPEG4Writer.cpp | 107 |
1 files changed, 85 insertions, 22 deletions
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 |