diff options
author | Andreas Huber <andih@google.com> | 2010-01-29 15:05:08 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2010-01-29 15:05:09 -0800 |
commit | 0c9698ea9764c409d253635a255fa8b1ccbb7141 (patch) | |
tree | 0895c37b75ff88eac456681917841497471db617 /media | |
parent | 4a20061f341ffaa8531993a851a3dfbfcdc8e38d (diff) | |
parent | d2315967b4075875cd6681327ae3043fa2adfbcf (diff) | |
download | frameworks_base-0c9698ea9764c409d253635a255fa8b1ccbb7141.zip frameworks_base-0c9698ea9764c409d253635a255fa8b1ccbb7141.tar.gz frameworks_base-0c9698ea9764c409d253635a255fa8b1ccbb7141.tar.bz2 |
Merge "Apparently the generic mpeg4 file header does not describe the actual samplerate and channel count of the content in the case of mpeg4 audio, instead the 'ESDS' atom must be consulted."
Diffstat (limited to 'media')
-rw-r--r-- | media/libstagefright/MPEG4Extractor.cpp | 96 | ||||
-rw-r--r-- | media/libstagefright/include/MPEG4Extractor.h | 3 |
2 files changed, 99 insertions, 0 deletions
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index 5370c39..6274a6c 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -28,6 +28,7 @@ #include <string.h> #include <media/stagefright/DataSource.h> +#include "include/ESDS.h" #include <media/stagefright/MediaBuffer.h> #include <media/stagefright/MediaBufferGroup.h> #include <media/stagefright/MediaDebug.h> @@ -898,6 +899,21 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { mLastTrack->meta->setData( kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4); + if (mPath.size() >= 2 + && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) { + // Information from the ESDS must be relied on for proper + // setup of sample rate and channel count for MPEG4 Audio. + // The generic header appears to only contain generic + // information... + + status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio( + &buffer[4], chunk_data_size - 4); + + if (err != OK) { + return err; + } + } + *offset += chunk_size; break; } @@ -1121,6 +1137,86 @@ sp<MediaSource> MPEG4Extractor::getTrack(size_t index) { track->meta, mDataSource, track->timescale, track->sampleTable); } +status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( + const void *esds_data, size_t esds_size) { + ESDS esds(esds_data, esds_size); + const uint8_t *csd; + size_t csd_size; + if (esds.getCodecSpecificInfo( + (const void **)&csd, &csd_size) != OK) { + return ERROR_MALFORMED; + } + +#if 0 + printf("ESD of size %d\n", csd_size); + hexdump(csd, csd_size); +#endif + + if (csd_size < 2) { + return ERROR_MALFORMED; + } + + uint32_t objectType = csd[0] >> 3; + + if (objectType == 31) { + return ERROR_UNSUPPORTED; + } + + uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7); + int32_t sampleRate = 0; + int32_t numChannels = 0; + if (freqIndex == 15) { + if (csd_size < 5) { + return ERROR_MALFORMED; + } + + sampleRate = (csd[1] & 0x7f) << 17 + | csd[2] << 9 + | csd[3] << 1 + | (csd[4] >> 7); + + numChannels = (csd[4] >> 3) & 15; + } else { + static uint32_t kSamplingRate[] = { + 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, + 16000, 12000, 11025, 8000, 7350 + }; + + if (freqIndex == 13 || freqIndex == 14) { + return ERROR_MALFORMED; + } + + sampleRate = kSamplingRate[freqIndex]; + numChannels = (csd[1] >> 3) & 15; + } + + if (numChannels == 0) { + return ERROR_UNSUPPORTED; + } + + int32_t prevSampleRate; + CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate)); + + if (prevSampleRate != sampleRate) { + LOGW("mpeg4 audio sample rate different from previous setting. " + "was: %d, now: %d", prevSampleRate, sampleRate); + } + + mLastTrack->meta->setInt32(kKeySampleRate, sampleRate); + + int32_t prevChannelCount; + CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount)); + + if (prevChannelCount != numChannels) { + LOGW("mpeg4 audio channel count different from previous setting. " + "was: %d, now: %d", prevChannelCount, numChannels); + } + + mLastTrack->meta->setInt32(kKeyChannelCount, numChannels); + + return OK; +} + //////////////////////////////////////////////////////////////////////////////// MPEG4Source::MPEG4Source( diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h index 1a13446..3a63e88 100644 --- a/media/libstagefright/include/MPEG4Extractor.h +++ b/media/libstagefright/include/MPEG4Extractor.h @@ -65,6 +65,9 @@ private: status_t parseChunk(off_t *offset, int depth); status_t parseMetaData(off_t offset, size_t size); + status_t updateAudioTrackInfoFromESDS_MPEG4Audio( + const void *esds_data, size_t esds_size); + MPEG4Extractor(const MPEG4Extractor &); MPEG4Extractor &operator=(const MPEG4Extractor &); }; |