From 1d6bd0de15378c04c2fa624cb3d4c5c37f912ee1 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/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java index d19999e9e5..17c541ce07 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java @@ -433,10 +433,15 @@ import java.util.List; 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 @@ -474,7 +479,7 @@ import java.util.List; 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];