Commit 7d6b0e1f by olly Committed by Oliver Woodman

Move renderer flags, overrides and tunneling ID into Parameters

- This is needed to make DefaultTrackSelector properly thread
  safe, and enable atomic changes to the selector that, for
  example, disable a renderer and enable another one at the same
  time.

- This change also saves/restores parameters and the start
  position in PlayerActivity, resolving the ref'd issue.

Issue: #3915

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=193913350
parent 5926e201
......@@ -116,6 +116,12 @@ public class PlayerActivity extends Activity
// For backwards compatibility only.
private static final String DRM_SCHEME_UUID_EXTRA = "drm_scheme_uuid";
// Saved instance state keys.
private static final String KEY_TRACK_SELECTOR_PARAMETERS = "track_selector_parameters";
private static final String KEY_WINDOW = "window";
private static final String KEY_POSITION = "position";
private static final String KEY_AUTO_PLAY = "auto_play";
private static final DefaultBandwidthMeter BANDWIDTH_METER = new DefaultBandwidthMeter();
private static final CookieManager DEFAULT_COOKIE_MANAGER;
static {
......@@ -132,14 +138,15 @@ public class PlayerActivity extends Activity
private SimpleExoPlayer player;
private MediaSource mediaSource;
private DefaultTrackSelector trackSelector;
private DefaultTrackSelector.Parameters trackSelectorParameters;
private TrackSelectionHelper trackSelectionHelper;
private DebugTextViewHelper debugViewHelper;
private boolean inErrorState;
private TrackGroupArray lastSeenTrackGroupArray;
private boolean shouldAutoPlay;
private int resumeWindow;
private long resumePosition;
private boolean startAutoPlay;
private int startWindow;
private long startPosition;
// Fields used only for ad playback. The ads loader is loaded via reflection.
......@@ -152,8 +159,6 @@ public class PlayerActivity extends Activity
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
shouldAutoPlay = true;
clearResumePosition();
mediaDataSourceFactory = buildDataSourceFactory(true);
mainHandler = new Handler();
if (CookieHandler.getDefault() != DEFAULT_COOKIE_MANAGER) {
......@@ -169,13 +174,22 @@ public class PlayerActivity extends Activity
playerView = findViewById(R.id.player_view);
playerView.setControllerVisibilityListener(this);
playerView.requestFocus();
if (savedInstanceState != null) {
trackSelectorParameters = savedInstanceState.getParcelable(KEY_TRACK_SELECTOR_PARAMETERS);
startAutoPlay = savedInstanceState.getBoolean(KEY_AUTO_PLAY);
startWindow = savedInstanceState.getInt(KEY_WINDOW);
startPosition = savedInstanceState.getLong(KEY_POSITION);
} else {
trackSelectorParameters = new DefaultTrackSelector.ParametersBuilder().build();
clearStartPosition();
}
}
@Override
public void onNewIntent(Intent intent) {
releasePlayer();
shouldAutoPlay = true;
clearResumePosition();
clearStartPosition();
setIntent(intent);
}
......@@ -233,6 +247,16 @@ public class PlayerActivity extends Activity
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
updateTrackSelectorParameters();
updateStartPosition();
outState.putParcelable(KEY_TRACK_SELECTOR_PARAMETERS, trackSelectorParameters);
outState.putBoolean(KEY_AUTO_PLAY, startAutoPlay);
outState.putInt(KEY_WINDOW, startWindow);
outState.putLong(KEY_POSITION, startPosition);
}
// Activity input
@Override
......@@ -365,6 +389,7 @@ public class PlayerActivity extends Activity
new DefaultRenderersFactory(this, extensionRendererMode);
trackSelector = new DefaultTrackSelector(trackSelectionFactory);
trackSelector.setParameters(trackSelectorParameters);
trackSelectionHelper = new TrackSelectionHelper(trackSelector);
lastSeenTrackGroupArray = null;
......@@ -381,7 +406,7 @@ public class PlayerActivity extends Activity
drmSessionManager.addListener(mainHandler, eventLogger);
}
player.setPlayWhenReady(shouldAutoPlay);
player.setPlayWhenReady(startAutoPlay);
playerView.setPlayer(player);
playerView.setPlaybackPreparer(this);
debugViewHelper = new DebugTextViewHelper(player, debugTextView);
......@@ -421,11 +446,11 @@ public class PlayerActivity extends Activity
}
mediaSource.addEventListener(mainHandler, eventLogger);
}
boolean haveResumePosition = resumeWindow != C.INDEX_UNSET;
if (haveResumePosition) {
player.seekTo(resumeWindow, resumePosition);
boolean haveStartPosition = startWindow != C.INDEX_UNSET;
if (haveStartPosition) {
player.seekTo(startWindow, startPosition);
}
player.prepare(mediaSource, !haveResumePosition, false);
player.prepare(mediaSource, !haveStartPosition, false);
inErrorState = false;
updateButtonVisibilities();
}
......@@ -483,10 +508,10 @@ public class PlayerActivity extends Activity
private void releasePlayer() {
if (player != null) {
updateTrackSelectorParameters();
updateStartPosition();
debugViewHelper.stop();
debugViewHelper = null;
shouldAutoPlay = player.getPlayWhenReady();
updateResumePosition();
player.release();
player = null;
mediaSource = null;
......@@ -495,14 +520,24 @@ public class PlayerActivity extends Activity
}
}
private void updateResumePosition() {
resumeWindow = player.getCurrentWindowIndex();
resumePosition = Math.max(0, player.getContentPosition());
private void updateTrackSelectorParameters() {
if (trackSelector != null) {
trackSelectorParameters = trackSelector.getParameters();
}
}
private void updateStartPosition() {
if (player != null) {
startAutoPlay = player.getPlayWhenReady();
startWindow = player.getCurrentWindowIndex();
startPosition = Math.max(0, player.getContentPosition());
}
}
private void clearResumePosition() {
resumeWindow = C.INDEX_UNSET;
resumePosition = C.TIME_UNSET;
private void clearStartPosition() {
startAutoPlay = true;
startWindow = C.INDEX_UNSET;
startPosition = C.TIME_UNSET;
}
/**
......@@ -661,7 +696,7 @@ public class PlayerActivity extends Activity
// This will only occur if the user has performed a seek whilst in the error state. Update
// the resume position so that if the user then retries, playback will resume from the
// position to which they seeked.
updateResumePosition();
updateStartPosition();
}
}
......@@ -695,10 +730,10 @@ public class PlayerActivity extends Activity
}
inErrorState = true;
if (isBehindLiveWindow(e)) {
clearResumePosition();
clearStartPosition();
initializePlayer();
} else {
updateResumePosition();
updateStartPosition();
updateButtonVisibilities();
showControls();
}
......
......@@ -30,6 +30,8 @@ import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import java.util.Arrays;
......@@ -79,8 +81,9 @@ import java.util.Arrays;
!= RendererCapabilities.ADAPTIVE_NOT_SUPPORTED
&& trackGroups.get(i).length > 1;
}
isDisabled = selector.getRendererDisabled(rendererIndex);
override = selector.getSelectionOverride(rendererIndex, trackGroups);
Parameters parameters = selector.getParameters();
isDisabled = parameters.getRendererDisabled(rendererIndex);
override = parameters.getSelectionOverride(rendererIndex, trackGroups);
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(title)
......@@ -170,12 +173,14 @@ import java.util.Arrays;
@Override
public void onClick(DialogInterface dialog, int which) {
selector.setRendererDisabled(rendererIndex, isDisabled);
ParametersBuilder parametersBuilder = selector.buildUponParameters();
parametersBuilder.setRendererDisabled(rendererIndex, isDisabled);
if (override != null) {
selector.setSelectionOverride(rendererIndex, trackGroups, override);
parametersBuilder.setSelectionOverride(rendererIndex, trackGroups, override);
} else {
selector.clearSelectionOverrides(rendererIndex);
parametersBuilder.clearSelectionOverrides(rendererIndex);
}
selector.setParameters(parametersBuilder);
}
// View.OnClickListener
......
......@@ -25,6 +25,8 @@ import static org.mockito.Mockito.verify;
import static org.mockito.MockitoAnnotations.initMocks;
import android.os.Parcel;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format;
......@@ -120,8 +122,18 @@ public final class DefaultTrackSelectorTest {
/** Tests {@link Parameters} {@link android.os.Parcelable} implementation. */
@Test
public void testParametersParcelable() {
SparseArray<Map<TrackGroupArray, SelectionOverride>> selectionOverrides = new SparseArray<>();
Map<TrackGroupArray, SelectionOverride> videoOverrides = new HashMap<>();
videoOverrides.put(new TrackGroupArray(VIDEO_TRACK_GROUP), new SelectionOverride(0, 1));
selectionOverrides.put(2, videoOverrides);
SparseBooleanArray rendererDisabledFlags = new SparseBooleanArray();
rendererDisabledFlags.put(3, true);
Parameters parametersToParcel =
new Parameters(
selectionOverrides,
rendererDisabledFlags,
/* preferredAudioLanguage= */ "en",
/* preferredTextLanguage= */ "de",
/* selectUndeterminedTextLanguage= */ false,
......@@ -136,7 +148,8 @@ public final class DefaultTrackSelectorTest {
/* exceedRendererCapabilitiesIfNecessary= */ true,
/* viewportWidth= */ 4,
/* viewportHeight= */ 5,
/* viewportOrientationMayChange= */ false);
/* viewportOrientationMayChange= */ false,
/* tunnelingAudioSessionId= */ C.AUDIO_SESSION_ID_UNSET);
Parcel parcel = Parcel.obtain();
parametersToParcel.writeToParcel(parcel, 0);
......@@ -170,7 +183,10 @@ public final class DefaultTrackSelectorTest {
@Test
public void testSelectTracksWithNullOverride() throws ExoPlaybackException {
DefaultTrackSelector trackSelector = new DefaultTrackSelector();
trackSelector.setSelectionOverride(0, new TrackGroupArray(VIDEO_TRACK_GROUP), null);
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setSelectionOverride(0, new TrackGroupArray(VIDEO_TRACK_GROUP), null));
TrackSelectorResult result = trackSelector.selectTracks(RENDERER_CAPABILITIES, TRACK_GROUPS);
assertTrackSelections(result, new TrackSelection[] {null, TRACK_SELECTIONS[1]});
assertThat(result.rendererConfigurations)
......@@ -181,8 +197,11 @@ public final class DefaultTrackSelectorTest {
@Test
public void testSelectTracksWithClearedNullOverride() throws ExoPlaybackException {
DefaultTrackSelector trackSelector = new DefaultTrackSelector();
trackSelector.setSelectionOverride(0, new TrackGroupArray(VIDEO_TRACK_GROUP), null);
trackSelector.clearSelectionOverride(0, new TrackGroupArray(VIDEO_TRACK_GROUP));
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setSelectionOverride(0, new TrackGroupArray(VIDEO_TRACK_GROUP), null)
.clearSelectionOverride(0, new TrackGroupArray(VIDEO_TRACK_GROUP)));
TrackSelectorResult result = trackSelector.selectTracks(RENDERER_CAPABILITIES, TRACK_GROUPS);
assertTrackSelections(result, TRACK_SELECTIONS);
assertThat(result.rendererConfigurations)
......@@ -193,7 +212,10 @@ public final class DefaultTrackSelectorTest {
@Test
public void testSelectTracksWithNullOverrideForDifferentTracks() throws ExoPlaybackException {
DefaultTrackSelector trackSelector = new DefaultTrackSelector();
trackSelector.setSelectionOverride(0, new TrackGroupArray(VIDEO_TRACK_GROUP), null);
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setSelectionOverride(0, new TrackGroupArray(VIDEO_TRACK_GROUP), null));
TrackSelectorResult result =
trackSelector.selectTracks(
RENDERER_CAPABILITIES,
......@@ -207,7 +229,7 @@ public final class DefaultTrackSelectorTest {
@Test
public void testSelectTracksWithDisabledRenderer() throws ExoPlaybackException {
DefaultTrackSelector trackSelector = new DefaultTrackSelector();
trackSelector.setRendererDisabled(1, true);
trackSelector.setParameters(trackSelector.buildUponParameters().setRendererDisabled(1, true));
TrackSelectorResult result = trackSelector.selectTracks(RENDERER_CAPABILITIES, TRACK_GROUPS);
assertTrackSelections(result, new TrackSelection[] {TRACK_SELECTIONS[0], null});
assertThat(new RendererConfiguration[] {DEFAULT, null})
......@@ -218,8 +240,11 @@ public final class DefaultTrackSelectorTest {
@Test
public void testSelectTracksWithClearedDisabledRenderer() throws ExoPlaybackException {
DefaultTrackSelector trackSelector = new DefaultTrackSelector();
trackSelector.setRendererDisabled(1, true);
trackSelector.setRendererDisabled(1, false);
trackSelector.setParameters(
trackSelector
.buildUponParameters()
.setRendererDisabled(1, true)
.setRendererDisabled(1, false));
TrackSelectorResult result = trackSelector.selectTracks(RENDERER_CAPABILITIES, TRACK_GROUPS);
assertTrackSelections(result, TRACK_SELECTIONS);
assertThat(new RendererConfiguration[] {DEFAULT, DEFAULT})
......@@ -241,7 +266,7 @@ public final class DefaultTrackSelectorTest {
@Test
public void testSelectTracksWithDisabledNoSampleRenderer() throws ExoPlaybackException {
DefaultTrackSelector trackSelector = new DefaultTrackSelector();
trackSelector.setRendererDisabled(1, true);
trackSelector.setParameters(trackSelector.buildUponParameters().setRendererDisabled(1, true));
TrackSelectorResult result =
trackSelector.selectTracks(RENDERER_CAPABILITIES_WITH_NO_SAMPLE_RENDERER, TRACK_GROUPS);
assertTrackSelections(result, TRACK_SELECTIONS_WITH_NO_SAMPLE_RENDERER);
......
......@@ -397,7 +397,8 @@ public final class DashTestRunner {
protected TrackSelection[] selectAllTracks(
MappedTrackInfo mappedTrackInfo,
int[][][] rendererFormatSupports,
int[] rendererMixedMimeTypeAdaptationSupports)
int[] rendererMixedMimeTypeAdaptationSupports,
Parameters parameters)
throws ExoPlaybackException {
Assertions.checkState(
mappedTrackInfo.getRendererType(VIDEO_RENDERER_INDEX) == C.TRACK_TYPE_VIDEO);
......
......@@ -33,6 +33,7 @@ import com.google.android.exoplayer2.testutil.ActionSchedule.ActionNode;
import com.google.android.exoplayer2.testutil.ActionSchedule.PlayerRunnable;
import com.google.android.exoplayer2.testutil.ActionSchedule.PlayerTarget;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Parameters;
import com.google.android.exoplayer2.util.HandlerWrapper;
/**
......@@ -219,7 +220,10 @@ public abstract class Action {
}
/** Calls {@link DefaultTrackSelector#setRendererDisabled(int, boolean)}. */
/**
* Updates the {@link Parameters} of a {@link DefaultTrackSelector} to specify whether the
* renderer at a given index should be disabled.
*/
public static final class SetRendererDisabled extends Action {
private final int rendererIndex;
......@@ -239,7 +243,8 @@ public abstract class Action {
@Override
protected void doActionImpl(
SimpleExoPlayer player, DefaultTrackSelector trackSelector, Surface surface) {
trackSelector.setRendererDisabled(rendererIndex, disabled);
trackSelector.setParameters(
trackSelector.buildUponParameters().setRendererDisabled(rendererIndex, disabled));
}
}
......
......@@ -48,7 +48,8 @@ public class FakeTrackSelector extends DefaultTrackSelector {
protected TrackSelection[] selectAllTracks(
MappedTrackInfo mappedTrackInfo,
int[][][] rendererFormatSupports,
int[] rendererMixedMimeTypeAdaptationSupports)
int[] rendererMixedMimeTypeAdaptationSupports,
Parameters params)
throws ExoPlaybackException {
TrackSelection[] selections = new TrackSelection[mappedTrackInfo.length];
for (int i = 0; i < mappedTrackInfo.length; i++) {
......
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