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
This commit is contained in:
tonihei 2020-11-20 10:24:22 +00:00 committed by Ian Baker
parent db48a68456
commit 1d2cf6f270
2 changed files with 52 additions and 0 deletions

View File

@ -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) {

View File

@ -861,6 +861,53 @@ public final class SampleQueueTest {
assertAllocationCount(1);
}
@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();