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

Commit 827c4656 authored by Venkatarama Avadhani's avatar Venkatarama Avadhani
Browse files

MP4: Use track header to get playback duration

When an MP4 file is trimmed, the samples may not be removed, but only
the playback duration for the track altered. So, to determine the
playback duration we must use track header's duration.

Add a new field in Track to store the mdhd header duration, which
contains the total duration of the samples contained in the track. This
can be use to determine the padding.

This reapplies aosp/2998978 with the change to store the mdhd duration.

Bug: 329121650
Test: atest MctsMediaExtractorTestCases
      atest MctsMediaV2TestCases:ExtractorTest
      atest MctsMediaV2TestCases:ExtractorUnitTest
      atest CtsMediaMuxerTestCases
      atest CtsMediaV2TestCases:MuxerTest
      atest CtsMediaV2TestCases:MuxerUnitTest

Change-Id: Idd4cbab8dec17fe8e1f815de9b1aa218baaa1fe7
parent 965655e0
Loading
Loading
Loading
Loading
+18 −6
Original line number Diff line number Diff line
@@ -523,11 +523,10 @@ media_status_t MPEG4Extractor::getTrackMetaData(
    }

    [this, &track] {
        int64_t duration;
        int64_t duration = track->mMdhdDurationUs;
        int32_t samplerate;
        // Only for audio track.
        if (track->elst_needs_processing && mHeaderTimescale != 0 &&
            AMediaFormat_getInt64(track->meta, AMEDIAFORMAT_KEY_DURATION, &duration) &&
        if (track->elst_needs_processing && mHeaderTimescale != 0 && duration != 0 &&
            AMediaFormat_getInt32(track->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, &samplerate)) {
            // Elst has to be processed only the first time this function is called.
            track->elst_needs_processing = false;
@@ -1645,7 +1644,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
                          (long long) duration, (long long) mLastTrack->timescale);
                    return ERROR_MALFORMED;
                }
                AMediaFormat_setInt64(mLastTrack->meta, AMEDIAFORMAT_KEY_DURATION, durationUs);
                // Store this track's mdhd duration to calculate the padding.
                mLastTrack->mMdhdDurationUs = (int64_t)durationUs;
            } else {
                mLastTrack->mMdhdDurationUs = 0;
            }

            uint8_t lang[2];
@@ -3907,17 +3909,18 @@ status_t MPEG4Extractor::parseTrackHeader(
    }

    int32_t id;
    int64_t duration;

    if (version == 1) {
        // we can get ctime value from U64_AT(&buffer[4])
        // we can get mtime value from U64_AT(&buffer[12])
        id = U32_AT(&buffer[20]);
        // we can get duration value from U64_AT(&buffer[28])
        duration = U64_AT(&buffer[28]);
    } else if (version == 0) {
        // we can get ctime value from U32_AT(&buffer[4])
        // we can get mtime value from U32_AT(&buffer[8])
        id = U32_AT(&buffer[12]);
        // we can get duration value from U32_AT(&buffer[20])
        duration = U32_AT(&buffer[20]);
    } else {
        return ERROR_UNSUPPORTED;
    }
@@ -3926,6 +3929,15 @@ status_t MPEG4Extractor::parseTrackHeader(
        return ERROR_MALFORMED;

    AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_TRACK_ID, id);
    if (duration != 0 && mHeaderTimescale != 0) {
        long double durationUs = ((long double)duration * 1000000) / mHeaderTimescale;
        if (durationUs < 0 || durationUs > INT64_MAX) {
            ALOGE("cannot represent %lld * 1000000 / %lld in 64 bits",
                  (long long) duration, (long long) mHeaderTimescale);
            return ERROR_MALFORMED;
        }
        AMediaFormat_setInt64(mLastTrack->meta, AMEDIAFORMAT_KEY_DURATION, durationUs);
    }

    size_t matrixOffset = dynSize + 16;
    int32_t a00 = U32_AT(&buffer[matrixOffset]);
+1 −1
Original line number Diff line number Diff line
@@ -96,7 +96,7 @@ private:

        uint8_t *mTx3gBuffer;
        size_t mTx3gSize, mTx3gFilled;

        int64_t mMdhdDurationUs;

        Track() {
            next = NULL;