Commit 1d2cf6f2 by tonihei Committed by Ian Baker

Fix bug in SampleQueue.discardTo for duplicate timestamps.

When a stream has duplicate timestamps we currently discard to
the last sample with the specified discardTo timestamp, but
it should be the first one to adhere to the method doc and the
intended usage.

#minor-release

PiperOrigin-RevId: 343458870
parent db48a684
......@@ -894,6 +894,11 @@ public class SampleQueue implements TrackOutput {
if (!keyframe || (flags[searchIndex] & C.BUFFER_FLAG_KEY_FRAME) != 0) {
// We've found a suitable sample.
sampleCountToTarget = i;
if (timesUs[searchIndex] == timeUs) {
// Stop the search if we found a sample at the specified time to avoid returning a later
// sample with the same exactly matching timestamp.
break;
}
}
searchIndex++;
if (searchIndex == capacity) {
......
......@@ -862,6 +862,53 @@ public final class SampleQueueTest {
}
@Test
public void discardTo_withDuplicateTimestamps_discardsOnlyToFirstMatch() {
writeTestData(
DATA,
SAMPLE_SIZES,
SAMPLE_OFFSETS,
/* sampleTimestamps= */ new long[] {0, 1000, 1000, 1000, 2000, 2000, 2000, 2000},
SAMPLE_FORMATS,
/* sampleFlags= */ new int[] {
BUFFER_FLAG_KEY_FRAME,
0,
BUFFER_FLAG_KEY_FRAME,
BUFFER_FLAG_KEY_FRAME,
0,
0,
BUFFER_FLAG_KEY_FRAME,
BUFFER_FLAG_KEY_FRAME
});
// Discard to first keyframe exactly matching the specified time.
sampleQueue.discardTo(
/* timeUs= */ 1000, /* toKeyframe= */ true, /* stopAtReadPosition= */ false);
assertThat(sampleQueue.getFirstIndex()).isEqualTo(2);
// Do nothing when trying again.
sampleQueue.discardTo(
/* timeUs= */ 1000, /* toKeyframe= */ true, /* stopAtReadPosition= */ false);
sampleQueue.discardTo(
/* timeUs= */ 1000, /* toKeyframe= */ false, /* stopAtReadPosition= */ false);
assertThat(sampleQueue.getFirstIndex()).isEqualTo(2);
// Discard to first frame exactly matching the specified time.
sampleQueue.discardTo(
/* timeUs= */ 2000, /* toKeyframe= */ false, /* stopAtReadPosition= */ false);
assertThat(sampleQueue.getFirstIndex()).isEqualTo(4);
// Do nothing when trying again.
sampleQueue.discardTo(
/* timeUs= */ 2000, /* toKeyframe= */ false, /* stopAtReadPosition= */ false);
assertThat(sampleQueue.getFirstIndex()).isEqualTo(4);
// Discard to first keyframe at same timestamp.
sampleQueue.discardTo(
/* timeUs= */ 2000, /* toKeyframe= */ true, /* stopAtReadPosition= */ false);
assertThat(sampleQueue.getFirstIndex()).isEqualTo(6);
}
@Test
public void discardToDontStopAtReadPosition() {
writeTestData();
// Shouldn't discard anything.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment