From eebe990d2059a04c645cf1c0fd254764ddb4c0bc Mon Sep 17 00:00:00 2001 From: olly Date: Tue, 24 Mar 2020 11:31:19 +0000 Subject: [PATCH] MP4 edit lists: Use floor rather than ceil to find first sample If the start time of the edit falls within a sample, start from that sample rather than the next one. This ensures playback can start from the correct point if the sample is a keyframe, rather than having to start from the next one. Issue: #7133 PiperOrigin-RevId: 302639115 --- .../android/exoplayer2/extractor/mp4/AtomParsers.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java index 0c03795b8a..3cf858558a 100644 --- a/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java +++ b/library/extractor/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java @@ -446,10 +446,15 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; long editDuration = Util.scaleLargeTimestamp( track.editListDurations[i], track.timescale, track.movieTimescale); - startIndices[i] = Util.binarySearchCeil(timestamps, editMediaTime, true, true); + startIndices[i] = + Util.binarySearchFloor( + timestamps, editMediaTime, /* inclusive= */ true, /* stayInBounds= */ true); endIndices[i] = Util.binarySearchCeil( - timestamps, editMediaTime + editDuration, omitClippedSample, false); + timestamps, + editMediaTime + editDuration, + /* inclusive= */ omitClippedSample, + /* stayInBounds= */ false); while (startIndices[i] < endIndices[i] && (flags[startIndices[i]] & C.BUFFER_FLAG_KEY_FRAME) == 0) { // Applying the edit correctly would require prerolling from the previous sync sample. In @@ -487,7 +492,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; long ptsUs = Util.scaleLargeTimestamp(pts, C.MICROS_PER_SECOND, track.movieTimescale); long timeInSegmentUs = Util.scaleLargeTimestamp( - timestamps[j] - editMediaTime, C.MICROS_PER_SECOND, track.timescale); + Math.max(0, timestamps[j] - editMediaTime), C.MICROS_PER_SECOND, track.timescale); editedTimestamps[sampleIndex] = ptsUs + timeInSegmentUs; if (copyMetadata && editedSizes[sampleIndex] > editedMaximumSize) { editedMaximumSize = sizes[j];