Ensure silence skipping doesn't interfere with other discontinuities

The same doSomeWork iteration that triggers the silence skipping
discontinuity may already have another discontinuities (like
AUTO_TRANSITION), which should take precedence over the silence
skipping.

PiperOrigin-RevId: 632432851
This commit is contained in:
tonihei 2024-05-10 02:49:36 -07:00 committed by Copybara-Service
parent 1749726bc9
commit daa8750382
3 changed files with 61 additions and 1 deletions

View File

@ -24,6 +24,8 @@
`DefaultPreloadManager` and the custom
`PreloadMediaSource.PreloadControl` implementations to preload the next
source or take other actions.
* Fix bug where silence skipping at the end of items can trigger a
playback exception.
* Transformer:
* Work around a decoder bug where the number of audio channels was capped
at stereo when handling PCM input.

View File

@ -1038,13 +1038,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
long periodPositionUs = playingPeriodHolder.toPeriodTime(rendererPositionUs);
maybeTriggerPendingMessages(playbackInfo.positionUs, periodPositionUs);
if (mediaClock.hasSkippedSilenceSinceLastCall()) {
// Only report silence skipping if there isn't already another discontinuity.
boolean reportSilenceSkip = !playbackInfoUpdate.positionDiscontinuity;
playbackInfo =
handlePositionDiscontinuity(
playbackInfo.periodId,
/* positionUs= */ periodPositionUs,
playbackInfo.requestedContentPositionUs,
/* discontinuityStartPositionUs= */ periodPositionUs,
/* reportDiscontinuity= */ true,
/* reportDiscontinuity= */ reportSilenceSkip,
Player.DISCONTINUITY_REASON_SILENCE_SKIP);
} else {
playbackInfo.updatePositionUs(periodPositionUs);

View File

@ -14748,6 +14748,62 @@ public class ExoPlayerTest {
player.release();
}
@Test
public void silenceSkipped_atItemTransition_doesNotHideAutoTransitionDiscontinuity()
throws Exception {
FakeMediaClockRenderer audioRenderer =
new FakeMediaClockRenderer(C.TRACK_TYPE_AUDIO) {
private long positionUs;
@Override
protected void onStreamChanged(
Format[] formats, long startPositionUs, long offsetUs, MediaPeriodId mediaPeriodId) {
positionUs = offsetUs;
}
@Override
public long getPositionUs() {
// Advance position to make playback progress.
positionUs += 10_000;
return positionUs;
}
@Override
public boolean hasSkippedSilenceSinceLastCall() {
// Contuniuosly report skipped silences to ensure they will overlap with other
// discontinuities like AUTO_TRANSITION.
return true;
}
@Override
public void setPlaybackParameters(PlaybackParameters playbackParameters) {}
@Override
public PlaybackParameters getPlaybackParameters() {
return PlaybackParameters.DEFAULT;
}
};
ExoPlayer player =
parameterizeTestExoPlayerBuilder(
new TestExoPlayerBuilder(context).setRenderers(audioRenderer))
.build();
Player.Listener mockPlayerListener = mock(Player.Listener.class);
player.addListener(mockPlayerListener);
player.setMediaSources(
ImmutableList.of(
new FakeMediaSource(new FakeTimeline(), ExoPlayerTestRunner.AUDIO_FORMAT),
new FakeMediaSource(new FakeTimeline(), ExoPlayerTestRunner.AUDIO_FORMAT),
new FakeMediaSource(new FakeTimeline(), ExoPlayerTestRunner.AUDIO_FORMAT)));
player.prepare();
player.play();
runUntilPlaybackState(player, Player.STATE_ENDED);
player.release();
verify(mockPlayerListener, times(2))
.onPositionDiscontinuity(any(), any(), eq(Player.DISCONTINUITY_REASON_AUTO_TRANSITION));
}
@Test
public void seekToZeroAndTrackSelection_withNonZeroDefaultPosition_startsPlaybackAtZero()
throws Exception {