From 8647bbe4420ca487467318404127f52c567e346b Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Thu, 17 May 2012 12:12:39 -0700 Subject: Prefix MPEG4-generic audio data with ADTS headers to work around limitations of the new AAC decoder. Change-Id: I4988c7c39fedb7d04eb1ae2ba2d618aa6cb14e77 related-to-bug: 6488547 --- media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp | 22 +------ .../rtsp/AMPEG4ElementaryAssembler.cpp | 52 ++++++++++----- .../rtsp/AMPEG4ElementaryAssembler.h | 5 ++ media/libstagefright/rtsp/APacketSource.cpp | 1 + media/libstagefright/rtsp/ARTPAssembler.cpp | 73 ++++++++++++++++++++++ media/libstagefright/rtsp/ARTPAssembler.h | 10 +++ 6 files changed, 128 insertions(+), 35 deletions(-) diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp index 24c2f30..f9a44f0 100644 --- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp +++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp @@ -534,27 +534,7 @@ void AMPEG4AudioAssembler::submitAccessUnit() { LOG(VERBOSE) << "Access unit complete (" << mPackets.size() << " packets)"; #endif - size_t totalSize = 0; - List >::iterator it = mPackets.begin(); - while (it != mPackets.end()) { - const sp &unit = *it; - - totalSize += unit->size(); - ++it; - } - - sp accessUnit = new ABuffer(totalSize); - size_t offset = 0; - it = mPackets.begin(); - while (it != mPackets.end()) { - const sp &unit = *it; - - memcpy((uint8_t *)accessUnit->data() + offset, - unit->data(), unit->size()); - - ++it; - } - + sp accessUnit = MakeCompoundFromPackets(mPackets); accessUnit = removeLATMFraming(accessUnit); CopyTimes(accessUnit, *mPackets.begin()); diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp index 687d72b..eefceba 100644 --- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp +++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.cpp @@ -21,6 +21,7 @@ #include "AMPEG4ElementaryAssembler.h" #include "ARTPSource.h" +#include "ASessionDescription.h" #include #include @@ -85,6 +86,25 @@ static bool GetIntegerAttribute( return true; } +static bool GetSampleRateIndex(int32_t sampleRate, size_t *tableIndex) { + static const int32_t kSampleRateTable[] = { + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000 + }; + const size_t kNumSampleRates = + sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]); + + *tableIndex = 0; + for (size_t index = 0; index < kNumSampleRates; ++index) { + if (sampleRate == kSampleRateTable[index]) { + *tableIndex = index; + return true; + } + } + + return false; +} + // static AMPEG4ElementaryAssembler::AMPEG4ElementaryAssembler( const sp ¬ify, const AString &desc, const AString ¶ms) @@ -100,6 +120,8 @@ AMPEG4ElementaryAssembler::AMPEG4ElementaryAssembler( mStreamStateIndication(0), mAuxiliaryDataSizeLength(0), mHasAUHeader(false), + mChannelConfig(0), + mSampleRateIndex(0), mAccessUnitRTPTime(0), mNextExpectedSeqNoValid(false), mNextExpectedSeqNo(0), @@ -163,6 +185,13 @@ AMPEG4ElementaryAssembler::AMPEG4ElementaryAssembler( || mDTSDeltaLength > 0 || mRandomAccessIndication || mStreamStateIndication > 0; + + int32_t sampleRate, numChannels; + ASessionDescription::ParseFormatDesc( + desc.c_str(), &sampleRate, &numChannels); + + mChannelConfig = numChannels; + CHECK(GetSampleRateIndex(sampleRate, &mSampleRateIndex)); } } @@ -338,23 +367,18 @@ void AMPEG4ElementaryAssembler::submitAccessUnit() { ALOGV("Access unit complete (%d nal units)", mPackets.size()); - size_t totalSize = 0; - for (List >::iterator it = mPackets.begin(); - it != mPackets.end(); ++it) { - totalSize += (*it)->size(); - } + sp accessUnit; - sp accessUnit = new ABuffer(totalSize); - size_t offset = 0; - for (List >::iterator it = mPackets.begin(); - it != mPackets.end(); ++it) { - sp nal = *it; - memcpy(accessUnit->data() + offset, nal->data(), nal->size()); - offset += nal->size(); + if (mIsGeneric) { + accessUnit = MakeADTSCompoundFromAACFrames( + OMX_AUDIO_AACObjectLC - 1, + mSampleRateIndex, + mChannelConfig, + mPackets); + } else { + accessUnit = MakeCompoundFromPackets(mPackets); } - CopyTimes(accessUnit, *mPackets.begin()); - #if 0 printf(mAccessUnitDamaged ? "X" : "."); fflush(stdout); diff --git a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h index 794bbcc..693fca5 100644 --- a/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h +++ b/media/libstagefright/rtsp/AMPEG4ElementaryAssembler.h @@ -25,6 +25,8 @@ #include #include +#include + namespace android { struct ABuffer; @@ -57,6 +59,9 @@ private: unsigned mAuxiliaryDataSizeLength; bool mHasAUHeader; + int32_t mChannelConfig; + size_t mSampleRateIndex; + uint32_t mAccessUnitRTPTime; bool mNextExpectedSeqNoValid; uint32_t mNextExpectedSeqNo; diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp index 6cf1301..fc177d2 100644 --- a/media/libstagefright/rtsp/APacketSource.cpp +++ b/media/libstagefright/rtsp/APacketSource.cpp @@ -551,6 +551,7 @@ APacketSource::APacketSource( mFormat->setInt32(kKeySampleRate, sampleRate); mFormat->setInt32(kKeyChannelCount, numChannels); + mFormat->setInt32(kKeyIsADTS, true); sp codecSpecificData = MakeAACCodecSpecificData2(params.c_str()); diff --git a/media/libstagefright/rtsp/ARTPAssembler.cpp b/media/libstagefright/rtsp/ARTPAssembler.cpp index a897c10..1844bc5 100644 --- a/media/libstagefright/rtsp/ARTPAssembler.cpp +++ b/media/libstagefright/rtsp/ARTPAssembler.cpp @@ -74,4 +74,77 @@ void ARTPAssembler::CopyTimes(const sp &to, const sp &from) { to->setInt32Data(from->int32Data()); } +// static +sp ARTPAssembler::MakeADTSCompoundFromAACFrames( + unsigned profile, + unsigned samplingFreqIndex, + unsigned channelConfig, + const List > &frames) { + size_t totalSize = 0; + for (List >::const_iterator it = frames.begin(); + it != frames.end(); ++it) { + // Each frame is prefixed by a 7 byte ADTS header + totalSize += (*it)->size() + 7; + } + + sp accessUnit = new ABuffer(totalSize); + size_t offset = 0; + for (List >::const_iterator it = frames.begin(); + it != frames.end(); ++it) { + sp nal = *it; + uint8_t *dst = accessUnit->data() + offset; + + static const unsigned kADTSId = 0; + static const unsigned kADTSLayer = 0; + static const unsigned kADTSProtectionAbsent = 1; + + unsigned frameLength = nal->size() + 7; + + dst[0] = 0xff; + + dst[1] = + 0xf0 | (kADTSId << 3) | (kADTSLayer << 1) | kADTSProtectionAbsent; + + dst[2] = (profile << 6) + | (samplingFreqIndex << 2) + | (channelConfig >> 2); + + dst[3] = ((channelConfig & 3) << 6) | (frameLength >> 11); + + dst[4] = (frameLength >> 3) & 0xff; + dst[5] = (frameLength & 7) << 5; + dst[6] = 0x00; + + memcpy(dst + 7, nal->data(), nal->size()); + offset += nal->size() + 7; + } + + CopyTimes(accessUnit, *frames.begin()); + + return accessUnit; +} + +// static +sp ARTPAssembler::MakeCompoundFromPackets( + const List > &packets) { + size_t totalSize = 0; + for (List >::const_iterator it = packets.begin(); + it != packets.end(); ++it) { + totalSize += (*it)->size(); + } + + sp accessUnit = new ABuffer(totalSize); + size_t offset = 0; + for (List >::const_iterator it = packets.begin(); + it != packets.end(); ++it) { + sp nal = *it; + memcpy(accessUnit->data() + offset, nal->data(), nal->size()); + offset += nal->size(); + } + + CopyTimes(accessUnit, *packets.begin()); + + return accessUnit; +} + } // namespace android diff --git a/media/libstagefright/rtsp/ARTPAssembler.h b/media/libstagefright/rtsp/ARTPAssembler.h index 70ea186..7c147be 100644 --- a/media/libstagefright/rtsp/ARTPAssembler.h +++ b/media/libstagefright/rtsp/ARTPAssembler.h @@ -19,6 +19,7 @@ #define A_RTP_ASSEMBLER_H_ #include +#include #include namespace android { @@ -45,6 +46,15 @@ protected: static void CopyTimes(const sp &to, const sp &from); + static sp MakeADTSCompoundFromAACFrames( + unsigned profile, + unsigned samplingFreqIndex, + unsigned channelConfig, + const List > &frames); + + static sp MakeCompoundFromPackets( + const List > &frames); + private: int64_t mFirstFailureTimeUs; -- cgit v1.1