mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Match with ExoPlayer seeking when using CompositionPlayer
In a image sequence, seek to after the image duration should render the final image frame. But currently it hangs as ConstantRateTimestampIterator doesn't output any timestamp in this case PiperOrigin-RevId: 724295475
This commit is contained in:
parent
5e6fb88372
commit
babc2dd416
@ -17,6 +17,7 @@ package androidx.media3.common.util;
|
||||
|
||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||
import static androidx.media3.common.util.Assertions.checkState;
|
||||
import static java.lang.Math.max;
|
||||
import static java.lang.Math.round;
|
||||
|
||||
import androidx.annotation.FloatRange;
|
||||
@ -70,7 +71,8 @@ public final class ConstantRateTimestampIterator implements TimestampIterator {
|
||||
this.endPositionUs = endPositionUs;
|
||||
this.frameRate = frameRate;
|
||||
float durationSecs = (endPositionUs - startPositionUs) / (float) C.MICROS_PER_SECOND;
|
||||
this.totalNumberOfFramesToAdd = round(frameRate * durationSecs);
|
||||
// Generate at least one timestamp so that at least one frame is produced when seeking.
|
||||
this.totalNumberOfFramesToAdd = max(round(frameRate * durationSecs), 1);
|
||||
framesDurationUs = C.MICROS_PER_SECOND / frameRate;
|
||||
}
|
||||
|
||||
|
@ -67,12 +67,12 @@ public class ConstantRateTimestampIteratorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timestampIterator_smallDuration_generatesEmptyIterator() {
|
||||
public void timestampIterator_smallDuration_generatesOneTimestamp() {
|
||||
ConstantRateTimestampIterator constantRateTimestampIterator =
|
||||
new ConstantRateTimestampIterator(/* durationUs= */ 1, /* frameRate= */ 2);
|
||||
|
||||
assertThat(generateList(constantRateTimestampIterator)).isEmpty();
|
||||
assertThat(constantRateTimestampIterator.getLastTimestampUs()).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(generateList(constantRateTimestampIterator)).containsExactly(0L);
|
||||
assertThat(constantRateTimestampIterator.getLastTimestampUs()).isEqualTo(0L);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -110,15 +110,15 @@ public class ConstantRateTimestampIteratorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void timestampIterator_withNoTimestampsWithinParameters_generatesNoTimestamp() {
|
||||
public void timestampIterator_withNoTimestampsWithinParameters_generatesOneTimestamp() {
|
||||
ConstantRateTimestampIterator constantRateTimestampIterator =
|
||||
new ConstantRateTimestampIterator(
|
||||
/* startPositionUs= */ 900_000L,
|
||||
/* endPositionUs= */ C.MICROS_PER_SECOND,
|
||||
/* frameRate= */ 3);
|
||||
|
||||
assertThat(generateList(constantRateTimestampIterator)).isEmpty();
|
||||
assertThat(constantRateTimestampIterator.getLastTimestampUs()).isEqualTo(C.TIME_UNSET);
|
||||
assertThat(generateList(constantRateTimestampIterator)).containsExactly(900_000L);
|
||||
assertThat(constantRateTimestampIterator.getLastTimestampUs()).isEqualTo(900_000L);
|
||||
}
|
||||
|
||||
private static List<Long> generateList(TimestampIterator iterator) {
|
||||
|
@ -355,6 +355,47 @@ public class CompositionPlayerSeekTest {
|
||||
.isEqualTo(sequenceTimestampsUs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void seekToEndOfSecondImage_afterPlayingSingleSequenceOfTwoImages() throws Exception {
|
||||
// Seeks to the end of the second image
|
||||
long seekTimeMs = usToMs(2 * IMAGE_DURATION_US);
|
||||
ImmutableList<Long> sequenceTimestampsUs =
|
||||
new ImmutableList.Builder<Long>()
|
||||
// Plays the first image
|
||||
.addAll(IMAGE_TIMESTAMPS_US)
|
||||
// Plays the second image
|
||||
.addAll(
|
||||
transform(IMAGE_TIMESTAMPS_US, timestampUs -> (IMAGE_DURATION_US + timestampUs)))
|
||||
// Plays the last image frame, which is one microsecond smaller than the total duration.
|
||||
.add(399_999L)
|
||||
.build();
|
||||
|
||||
assertThat(
|
||||
playSequenceUntilEndedAndSeekAndGetTimestampsUs(
|
||||
ImmutableList.of(IMAGE_MEDIA_ITEM, IMAGE_MEDIA_ITEM), seekTimeMs))
|
||||
.isEqualTo(sequenceTimestampsUs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void seekToAfterEndOfSecondImage_afterPlayingSingleSequenceOfTwoImages() throws Exception {
|
||||
long seekTimeMs = usToMs(3 * IMAGE_DURATION_US);
|
||||
ImmutableList<Long> sequenceTimestampsUs =
|
||||
new ImmutableList.Builder<Long>()
|
||||
// Plays the first image
|
||||
.addAll(IMAGE_TIMESTAMPS_US)
|
||||
// Plays the second image
|
||||
.addAll(
|
||||
transform(IMAGE_TIMESTAMPS_US, timestampUs -> (IMAGE_DURATION_US + timestampUs)))
|
||||
// Plays the last image frame, which is one microsecond smaller than the total duration.
|
||||
.add(399_999L)
|
||||
.build();
|
||||
|
||||
assertThat(
|
||||
playSequenceUntilEndedAndSeekAndGetTimestampsUs(
|
||||
ImmutableList.of(IMAGE_MEDIA_ITEM, IMAGE_MEDIA_ITEM), seekTimeMs))
|
||||
.isEqualTo(sequenceTimestampsUs);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void seekToZero_afterPlayingSingleSequenceOfVideoAndImage() throws Exception {
|
||||
maybeSkipTest();
|
||||
|
Loading…
x
Reference in New Issue
Block a user