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

Commit 1b5e2cd1 authored by Gopalakrishnan Nallasamy's avatar Gopalakrishnan Nallasamy
Browse files

MPEG4Extractor:media timescale for audio delay/pad

segmentDuration elst entry ('edts') in mp4 file is based on timescale in movie header('mvhd').
But mediaTime is based on media header timescale ('mdhd').(Part 12:
ISO base media file format). Use media header timescale for mediaTime in delay/pad calculation.

Bug: 117681690
Bug: 80513071
Bug: 118053992
Bug: 118248950

Test: played failing clips from referenced bugs and gapless playback test files using mediaplayer
	and observed expected behavior. Verified calculated delay/padding samples with
	logcat messages manually.

CtsMediaTestCases passed:
	MediaExtractorTest
	MediaPlayerTest
	MediaRecorderTest
	MediaSyncTest
	MediaMuxerTest
	MediaRandomTest

Change-Id: I2c55fec365009c1580ed1967b1b0ba5db19928d2
parent 2d8a0e22
Loading
Loading
Loading
Loading
+43 −35
Original line number Original line Diff line number Diff line
@@ -465,6 +465,7 @@ media_status_t MPEG4Extractor::getTrackMetaData(
                AMediaFormat_getInt64(track->meta, AMEDIAFORMAT_KEY_DURATION, &duration) &&
                AMediaFormat_getInt64(track->meta, AMEDIAFORMAT_KEY_DURATION, &duration) &&
                AMediaFormat_getInt32(track->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, &samplerate)) {
                AMediaFormat_getInt32(track->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, &samplerate)) {


            // elst has to be processed only the first time this function is called
            track->has_elst = false;
            track->has_elst = false;


            if (track->elst_segment_duration > INT64_MAX) {
            if (track->elst_segment_duration > INT64_MAX) {
@@ -472,27 +473,24 @@ media_status_t MPEG4Extractor::getTrackMetaData(
            }
            }
            int64_t segment_duration = track->elst_segment_duration;
            int64_t segment_duration = track->elst_segment_duration;
            int64_t media_time = track->elst_media_time;
            int64_t media_time = track->elst_media_time;
            int64_t halfscale = mHeaderTimescale / 2;
            int64_t halfscale = track->timescale / 2;

            ALOGV("segment_duration = %" PRId64 ", media_time = %" PRId64
            ALOGV("segment_duration = %" PRId64 ", media_time = %" PRId64
                  ", halfscale = %" PRId64 ", timescale = %d",
                  ", halfscale = %" PRId64 ", mdhd_timescale = %d, track_timescale = %u",
                  segment_duration,
                  segment_duration, media_time,
                  media_time,
                  halfscale, mHeaderTimescale, track->timescale);
                  halfscale,

                  mHeaderTimescale);
            if (samplerate != track->timescale){
                ALOGV("samplerate:%d, track->timescale and samplerate are different!", samplerate);
            }


            int64_t delay;
            int64_t delay;
            // delay = ((media_time * samplerate) + halfscale) / mHeaderTimescale;
            // delay = ((media_time * samplerate) + halfscale) / track->timescale;
            if (__builtin_mul_overflow(media_time, samplerate, &delay) ||
            if (__builtin_mul_overflow(media_time, samplerate, &delay) ||
                    __builtin_add_overflow(delay, halfscale, &delay) ||
                    __builtin_add_overflow(delay, halfscale, &delay) ||
                    (delay /= mHeaderTimescale, false) ||
                    (delay /= track->timescale, false) ||
                    /* the calculated delay should be small, but some apps
                    delay > INT32_MAX ||
                     * appear to write a bogus edit list that causes a really
                    delay < INT32_MIN) {
                     * large delay, resulting in playback problems.
                     * Ignore such edit lists.
                     * (4096 is enough to drop 4 full samples)
                     */
                    delay > 4096 ||
                    delay < 0) {
                ALOGW("ignoring edit list with bogus values");
                ALOGW("ignoring edit list with bogus values");
                return;
                return;
            }
            }
@@ -508,22 +506,31 @@ media_status_t MPEG4Extractor::getTrackMetaData(


            int64_t segment_end;
            int64_t segment_end;
            int64_t padding;
            int64_t padding;
            // padding = scaled_duration - ((segment_duration + media_time) * 1000000);
            int64_t segment_duration_e6;
            if (__builtin_add_overflow(segment_duration, media_time, &segment_end) ||
            int64_t media_time_scaled_e6;
                    __builtin_mul_overflow(segment_end, 1000000, &segment_end) ||
            int64_t media_time_scaled;
            // padding = scaled_duration - ((segment_duration * 1000000) +
            //                  ((media_time * mHeaderTimeScale * 1000000)/track->timescale) )
            // segment_duration is based on timescale in movie header box(mdhd)
            // media_time is based on timescale track header/media timescale
            if (__builtin_mul_overflow(segment_duration, 1000000, &segment_duration_e6) ||
                __builtin_mul_overflow(media_time, mHeaderTimescale, &media_time_scaled) ||
                __builtin_mul_overflow(media_time_scaled, 1000000, &media_time_scaled_e6)) {
                return;
            }
            media_time_scaled_e6 /= track->timescale;
            if(__builtin_add_overflow(segment_duration_e6, media_time_scaled_e6, &segment_end) ||
                __builtin_sub_overflow(scaled_duration, segment_end, &padding)) {
                __builtin_sub_overflow(scaled_duration, segment_end, &padding)) {
                return;
                return;
            }
            }
            ALOGV("segment_end = %" PRId64 ", padding = %" PRId64, segment_end, padding);
            ALOGV("segment_end = %" PRId64 ", padding = %" PRId64, segment_end, padding);

            int64_t paddingsamples = 0;
            if (padding < 0) {
            if (padding < 0) {
                // track duration from media header (which is what AMEDIAFORMAT_KEY_DURATION is)
                // track duration from media header (which is what AMEDIAFORMAT_KEY_DURATION is)
                // might be slightly shorter than the segment duration, which would make the
                // might be slightly shorter than the segment duration, which would make the
                // padding negative. Clamp to zero.
                // padding negative. Clamp to zero.
                padding = 0;
                padding = 0;
            }
            } else {

            int64_t paddingsamples;
                int64_t halfscale_e6;
                int64_t halfscale_e6;
                int64_t timescale_e6;
                int64_t timescale_e6;
                // paddingsamples = ((padding * samplerate) + (halfscale * 1000000))
                // paddingsamples = ((padding * samplerate) + (halfscale * 1000000))
@@ -536,6 +543,7 @@ media_status_t MPEG4Extractor::getTrackMetaData(
                        paddingsamples > INT32_MAX) {
                        paddingsamples > INT32_MAX) {
                    return;
                    return;
                }
                }
            }
            ALOGV("paddingsamples = %" PRId64, paddingsamples);
            ALOGV("paddingsamples = %" PRId64, paddingsamples);
            AMediaFormat_setInt32(track->meta, AMEDIAFORMAT_KEY_ENCODER_PADDING, paddingsamples);
            AMediaFormat_setInt32(track->meta, AMEDIAFORMAT_KEY_ENCODER_PADDING, paddingsamples);
        }
        }