Add missing equals to MergingMediaPeriod.ForwardingTrackSelection

This causes a bug where the forwarded selections are no longer
assumed equal and the child MediaPeriods will think they need
to reset streams even though the selection stayed the same.

Issue: Issue: google/ExoPlayer#10248
PiperOrigin-RevId: 449454038
This commit is contained in:
tonihei 2022-05-18 13:01:55 +01:00 committed by Ian Baker
parent dcb58c767c
commit 1a171a004a
3 changed files with 78 additions and 7 deletions

View File

@ -12,6 +12,10 @@
by the user of the device. Apps can opt-out of contributing to platform by the user of the device. Apps can opt-out of contributing to platform
diagnostics for ExoPlayer with diagnostics for ExoPlayer with
`ExoPlayer.Builder.setUsePlatformDiagnostics(false)`. `ExoPlayer.Builder.setUsePlatformDiagnostics(false)`.
* Fix bug that tracks are reset too often when using `MergingMediaSource`,
for example when side-loading subtitles and changing the selected
subtitle mid-playback
([#10248](https://github.com/google/ExoPlayer/issues/10248)).
* Track selection: * Track selection:
* Flatten `TrackSelectionOverrides` class into `TrackSelectionParameters`, * Flatten `TrackSelectionOverrides` class into `TrackSelectionParameters`,
and promote `TrackSelectionOverride` to a top level class. and promote `TrackSelectionOverride` to a top level class.

View File

@ -608,5 +608,25 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
public boolean isBlacklisted(int index, long nowMs) { public boolean isBlacklisted(int index, long nowMs) {
return trackSelection.isBlacklisted(index, nowMs); return trackSelection.isBlacklisted(index, nowMs);
} }
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ForwardingTrackSelection)) {
return false;
}
ForwardingTrackSelection that = (ForwardingTrackSelection) o;
return trackSelection.equals(that.trackSelection) && trackGroup.equals(that.trackGroup);
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + trackGroup.hashCode();
result = 31 * result + trackSelection.hashCode();
return result;
}
} }
} }

View File

@ -35,6 +35,7 @@ import androidx.media3.exoplayer.upstream.DefaultAllocator;
import androidx.media3.test.utils.FakeMediaPeriod; import androidx.media3.test.utils.FakeMediaPeriod;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import org.checkerframework.checker.nullness.compatqual.NullableType; import org.checkerframework.checker.nullness.compatqual.NullableType;
import org.junit.Test; import org.junit.Test;
@ -139,21 +140,64 @@ public final class MergingMediaPeriodTest {
streams[0].readData(formatHolder, inputBuffer, FLAG_REQUIRE_FORMAT); streams[0].readData(formatHolder, inputBuffer, FLAG_REQUIRE_FORMAT);
streams[1].readData(formatHolder, inputBuffer, FLAG_REQUIRE_FORMAT); streams[1].readData(formatHolder, inputBuffer, FLAG_REQUIRE_FORMAT);
FakeMediaPeriodWithSelectTracksPosition childMediaPeriod1 = FakeMediaPeriodWithSelectionParameters childMediaPeriod1 =
(FakeMediaPeriodWithSelectTracksPosition) mergingMediaPeriod.getChildPeriod(0); (FakeMediaPeriodWithSelectionParameters) mergingMediaPeriod.getChildPeriod(0);
assertThat(childMediaPeriod1.selectTracksPositionUs).isEqualTo(0); assertThat(childMediaPeriod1.selectTracksPositionUs).isEqualTo(0);
assertThat(streams[0].readData(formatHolder, inputBuffer, /* readFlags= */ 0)) assertThat(streams[0].readData(formatHolder, inputBuffer, /* readFlags= */ 0))
.isEqualTo(C.RESULT_BUFFER_READ); .isEqualTo(C.RESULT_BUFFER_READ);
assertThat(inputBuffer.timeUs).isEqualTo(123_000L); assertThat(inputBuffer.timeUs).isEqualTo(123_000L);
FakeMediaPeriodWithSelectTracksPosition childMediaPeriod2 = FakeMediaPeriodWithSelectionParameters childMediaPeriod2 =
(FakeMediaPeriodWithSelectTracksPosition) mergingMediaPeriod.getChildPeriod(1); (FakeMediaPeriodWithSelectionParameters) mergingMediaPeriod.getChildPeriod(1);
assertThat(childMediaPeriod2.selectTracksPositionUs).isEqualTo(3000L); assertThat(childMediaPeriod2.selectTracksPositionUs).isEqualTo(3000L);
assertThat(streams[1].readData(formatHolder, inputBuffer, /* readFlags= */ 0)) assertThat(streams[1].readData(formatHolder, inputBuffer, /* readFlags= */ 0))
.isEqualTo(C.RESULT_BUFFER_READ); .isEqualTo(C.RESULT_BUFFER_READ);
assertThat(inputBuffer.timeUs).isEqualTo(456_000 - 3000); assertThat(inputBuffer.timeUs).isEqualTo(456_000 - 3000);
} }
@Test
public void selectTracks_withSameArguments_forwardsEqualSelectionsToChildSources()
throws Exception {
MergingMediaPeriod mergingMediaPeriod =
prepareMergingPeriod(
new MergingPeriodDefinition(
/* timeOffsetUs= */ 0, /* singleSampleTimeUs= */ 0, childFormat11),
new MergingPeriodDefinition(
/* timeOffsetUs= */ 0, /* singleSampleTimeUs= */ 0, childFormat22));
FakeMediaPeriodWithSelectionParameters childMediaPeriod1 =
(FakeMediaPeriodWithSelectionParameters) mergingMediaPeriod.getChildPeriod(0);
FakeMediaPeriodWithSelectionParameters childMediaPeriod2 =
(FakeMediaPeriodWithSelectionParameters) mergingMediaPeriod.getChildPeriod(1);
TrackGroupArray mergedTrackGroups = mergingMediaPeriod.getTrackGroups();
ExoTrackSelection[] selectionArray =
new ExoTrackSelection[] {
new FixedTrackSelection(mergedTrackGroups.get(0), /* track= */ 0),
new FixedTrackSelection(mergedTrackGroups.get(1), /* track= */ 0)
};
mergingMediaPeriod.selectTracks(
selectionArray,
/* mayRetainStreamFlags= */ new boolean[2],
/* streams= */ new SampleStream[2],
/* streamResetFlags= */ new boolean[2],
/* positionUs= */ 0);
ExoTrackSelection firstSelectionChild1 = childMediaPeriod1.selectTracksSelections[0];
ExoTrackSelection firstSelectionChild2 = childMediaPeriod2.selectTracksSelections[1];
mergingMediaPeriod.selectTracks(
selectionArray,
/* mayRetainStreamFlags= */ new boolean[2],
/* streams= */ new SampleStream[2],
/* streamResetFlags= */ new boolean[2],
/* positionUs= */ 0);
ExoTrackSelection secondSelectionChild1 = childMediaPeriod1.selectTracksSelections[0];
ExoTrackSelection secondSelectionChild2 = childMediaPeriod2.selectTracksSelections[1];
assertThat(firstSelectionChild1).isEqualTo(secondSelectionChild1);
assertThat(firstSelectionChild2).isEqualTo(secondSelectionChild2);
}
private MergingMediaPeriod prepareMergingPeriod(MergingPeriodDefinition... definitions) private MergingMediaPeriod prepareMergingPeriod(MergingPeriodDefinition... definitions)
throws Exception { throws Exception {
MediaPeriod[] mediaPeriods = new MediaPeriod[definitions.length]; MediaPeriod[] mediaPeriods = new MediaPeriod[definitions.length];
@ -166,7 +210,7 @@ public final class MergingMediaPeriodTest {
trackGroups[j] = new TrackGroup(definition.formats[j]); trackGroups[j] = new TrackGroup(definition.formats[j]);
} }
mediaPeriods[i] = mediaPeriods[i] =
new FakeMediaPeriodWithSelectTracksPosition( new FakeMediaPeriodWithSelectionParameters(
new TrackGroupArray(trackGroups), new TrackGroupArray(trackGroups),
new EventDispatcher() new EventDispatcher()
.withParameters( .withParameters(
@ -201,11 +245,12 @@ public final class MergingMediaPeriodTest {
return mergingMediaPeriod; return mergingMediaPeriod;
} }
private static final class FakeMediaPeriodWithSelectTracksPosition extends FakeMediaPeriod { private static final class FakeMediaPeriodWithSelectionParameters extends FakeMediaPeriod {
public @NullableType ExoTrackSelection[] selectTracksSelections;
public long selectTracksPositionUs; public long selectTracksPositionUs;
public FakeMediaPeriodWithSelectTracksPosition( public FakeMediaPeriodWithSelectionParameters(
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
EventDispatcher mediaSourceEventDispatcher, EventDispatcher mediaSourceEventDispatcher,
TrackDataFactory trackDataFactory) { TrackDataFactory trackDataFactory) {
@ -217,6 +262,7 @@ public final class MergingMediaPeriodTest {
DrmSessionManager.DRM_UNSUPPORTED, DrmSessionManager.DRM_UNSUPPORTED,
new DrmSessionEventListener.EventDispatcher(), new DrmSessionEventListener.EventDispatcher(),
/* deferOnPrepared= */ false); /* deferOnPrepared= */ false);
selectTracksSelections = new ExoTrackSelection[trackGroupArray.length];
selectTracksPositionUs = C.TIME_UNSET; selectTracksPositionUs = C.TIME_UNSET;
} }
@ -227,6 +273,7 @@ public final class MergingMediaPeriodTest {
@NullableType SampleStream[] streams, @NullableType SampleStream[] streams,
boolean[] streamResetFlags, boolean[] streamResetFlags,
long positionUs) { long positionUs) {
selectTracksSelections = Arrays.copyOf(selections, selections.length);
selectTracksPositionUs = positionUs; selectTracksPositionUs = positionUs;
return super.selectTracks( return super.selectTracks(
selections, mayRetainStreamFlags, streams, streamResetFlags, positionUs); selections, mayRetainStreamFlags, streams, streamResetFlags, positionUs);