MPEG4Extractor: read codecDelay from opus header
Instead of hard coding codecDelay, read it from opus header.
Also allow for variable sized opusheader to support multiple channels
Bug:129712302
Test: atest android.media.cts.DecoderTest
Change-Id: I5e134f688125d275163dfa496acd8133354b5617
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index e1bfb62..348ea49 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -45,6 +45,7 @@
#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/foundation/avc_utils.h>
#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/foundation/OpusHeader.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaDataBase.h>
@@ -1735,15 +1736,21 @@
AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, sample_rate);
if (chunk_type == FOURCC("Opus")) {
- uint8_t opusInfo[19];
+ uint8_t opusInfo[AOPUS_OPUSHEAD_MAXSIZE];
data_offset += sizeof(buffer);
+ size_t opusInfoSize = chunk_data_size - sizeof(buffer);
+
+ if (opusInfoSize < AOPUS_OPUSHEAD_MINSIZE ||
+ opusInfoSize > AOPUS_OPUSHEAD_MAXSIZE) {
+ return ERROR_MALFORMED;
+ }
// Read Opus Header
if (mDataSource->readAt(
- data_offset, opusInfo, sizeof(opusInfo)) < (ssize_t)sizeof(opusInfo)) {
+ data_offset, opusInfo, opusInfoSize) < opusInfoSize) {
return ERROR_IO;
}
- // OpusHeader must start with this magic sequence
+ // OpusHeader must start with this magic sequence, overwrite first 8 bytes
// http://wiki.xiph.org/OggOpus#ID_Header
strncpy((char *)opusInfo, "OpusHead", 8);
@@ -1760,17 +1767,18 @@
memcpy(&opusInfo[opusOffset + 2], &sample_rate, sizeof(sample_rate));
memcpy(&opusInfo[opusOffset + 6], &out_gain, sizeof(out_gain));
- int64_t codecDelay = 6500000;
- int64_t seekPreRollNs = 80000000; // Fixed 80 msec
+ static const int64_t kSeekPreRollNs = 80000000; // Fixed 80 msec
+ static const int32_t kOpusSampleRate = 48000;
+ int64_t codecDelay = pre_skip * 1000000000ll / kOpusSampleRate;
AMediaFormat_setBuffer(mLastTrack->meta,
AMEDIAFORMAT_KEY_CSD_0, opusInfo, sizeof(opusInfo));
AMediaFormat_setBuffer(mLastTrack->meta,
AMEDIAFORMAT_KEY_CSD_1, &codecDelay, sizeof(codecDelay));
AMediaFormat_setBuffer(mLastTrack->meta,
- AMEDIAFORMAT_KEY_CSD_2, &seekPreRollNs, sizeof(seekPreRollNs));
+ AMEDIAFORMAT_KEY_CSD_2, &kSeekPreRollNs, sizeof(kSeekPreRollNs));
- data_offset += sizeof(opusInfo);
+ data_offset += opusInfoSize;
*offset = data_offset;
CHECK_EQ(*offset, stop_offset);
}