Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f5943271 authored by Gopalakrishnan Nallasamy's avatar Gopalakrishnan Nallasamy
Browse files

MPEG4Writer: Large CodecSpecificData in MP4 ESDS box

Some external media files have CodecSpecificData greater than 128 bytes. Currently, that size
isn't fitting in one byte. Hence, added support to store large CodecSpecificDataSize, as per
ISO standard, by extending to more than one byte as required.

Bug: 127878894

Test: CtsMediaTestCases --compatibility:module-arg CtsMediaTestCases:include-annotation:
      android.platform.test.annotations.RequiresDevice

Change-Id: I2923adbecbef0aed034b3ccccf04084a7c6a34e4
parent 5635b7d1
Loading
Loading
Loading
Loading
+49 −11
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ static const uint8_t kNalUnitTypePicParamSet = 0x08;
static const int64_t kInitialDelayTimeUs     = 700000LL;
static const int64_t kMaxMetadataSize = 0x4000000LL;   // 64MB max per-frame metadata size
static const int64_t kMaxCttsOffsetTimeUs = 30 * 60 * 1000000LL;  // 30 minutes
static const size_t kESDSScratchBufferSize = 10;  // kMaxAtomSize in Mpeg4Extractor 64MB

static const char kMetaKey_Version[]    = "com.android.version";
static const char kMetaKey_Manufacturer[]      = "com.android.manufacturer";
@@ -3882,22 +3883,52 @@ void MPEG4Writer::Track::writeAudioFourCCBox() {
    mOwner->endBox();
}

static void generateEsdsSize(size_t dataLength, size_t* sizeGenerated, uint8_t* buffer) {
    size_t offset = 0, cur = 0;
    size_t more = 0x00;
    *sizeGenerated = 0;
    /* Start with the LSB(7 bits) of dataLength and build the byte sequence upto MSB.
     * Continuation flag(most significant bit) will be set on the first N-1 bytes.
     */
    do {
        buffer[cur++] = (dataLength & 0x7f) | more;
        dataLength >>= 7;
        more = 0x80;
        ++(*sizeGenerated);
    } while (dataLength > 0u);
    --cur;
    // Reverse the newly formed byte sequence.
    while (cur > offset) {
        uint8_t tmp = buffer[cur];
        buffer[cur--] = buffer[offset];
        buffer[offset++] = tmp;
    }
}

void MPEG4Writer::Track::writeMp4aEsdsBox() {
    mOwner->beginBox("esds");
    CHECK(mCodecSpecificData);
    CHECK_GT(mCodecSpecificDataSize, 0u);

    // Make sure all sizes encode to a single byte.
    CHECK_LT(mCodecSpecificDataSize + 23, 128u);
    uint8_t sizeESDBuffer[kESDSScratchBufferSize];
    uint8_t sizeDCDBuffer[kESDSScratchBufferSize];
    uint8_t sizeDSIBuffer[kESDSScratchBufferSize];
    size_t sizeESD = 0;
    size_t sizeDCD = 0;
    size_t sizeDSI = 0;
    generateEsdsSize(mCodecSpecificDataSize, &sizeDSI, sizeDSIBuffer);
    generateEsdsSize(mCodecSpecificDataSize + sizeDSI + 14, &sizeDCD, sizeDCDBuffer);
    generateEsdsSize(mCodecSpecificDataSize + sizeDSI + sizeDCD + 21, &sizeESD, sizeESDBuffer);

    mOwner->beginBox("esds");

    mOwner->writeInt32(0);     // version=0, flags=0
    mOwner->writeInt8(0x03);   // ES_DescrTag
    mOwner->writeInt8(23 + mCodecSpecificDataSize);
    mOwner->write(sizeESDBuffer, sizeESD);
    mOwner->writeInt16(0x0000);// ES_ID
    mOwner->writeInt8(0x00);

    mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
    mOwner->writeInt8(15 + mCodecSpecificDataSize);
    mOwner->write(sizeDCDBuffer, sizeDCD);
    mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
    mOwner->writeInt8(0x15);   // streamType AudioStream

@@ -3912,7 +3943,7 @@ void MPEG4Writer::Track::writeMp4aEsdsBox() {
    mOwner->writeInt32(avgBitrate);

    mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
    mOwner->writeInt8(mCodecSpecificDataSize);
    mOwner->write(sizeDSIBuffer, sizeDSI);
    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);

    static const uint8_t kData2[] = {
@@ -3929,20 +3960,27 @@ void MPEG4Writer::Track::writeMp4vEsdsBox() {
    CHECK(mCodecSpecificData);
    CHECK_GT(mCodecSpecificDataSize, 0u);

    // Make sure all sizes encode to a single byte.
    CHECK_LT(23 + mCodecSpecificDataSize, 128u);
    uint8_t sizeESDBuffer[kESDSScratchBufferSize];
    uint8_t sizeDCDBuffer[kESDSScratchBufferSize];
    uint8_t sizeDSIBuffer[kESDSScratchBufferSize];
    size_t sizeESD = 0;
    size_t sizeDCD = 0;
    size_t sizeDSI = 0;
    generateEsdsSize(mCodecSpecificDataSize, &sizeDSI, sizeDSIBuffer);
    generateEsdsSize(mCodecSpecificDataSize + sizeDSI + 14, &sizeDCD, sizeDCDBuffer);
    generateEsdsSize(mCodecSpecificDataSize + sizeDSI + sizeDCD + 21, &sizeESD, sizeESDBuffer);

    mOwner->beginBox("esds");

    mOwner->writeInt32(0);    // version=0, flags=0

    mOwner->writeInt8(0x03);  // ES_DescrTag
    mOwner->writeInt8(23 + mCodecSpecificDataSize);
    mOwner->write(sizeESDBuffer, sizeESD);
    mOwner->writeInt16(0x0000);  // ES_ID
    mOwner->writeInt8(0x1f);

    mOwner->writeInt8(0x04);  // DecoderConfigDescrTag
    mOwner->writeInt8(15 + mCodecSpecificDataSize);
    mOwner->write(sizeDCDBuffer, sizeDCD);
    mOwner->writeInt8(0x20);  // objectTypeIndication ISO/IEC 14492-2
    mOwner->writeInt8(0x11);  // streamType VisualStream

@@ -3960,7 +3998,7 @@ void MPEG4Writer::Track::writeMp4vEsdsBox() {

    mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag

    mOwner->writeInt8(mCodecSpecificDataSize);
    mOwner->write(sizeDSIBuffer, sizeDSI);
    mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);

    static const uint8_t kData2[] = {