Commit 0ca81b1a by olly Committed by Oliver Woodman

Make sure TrackSelections refer to the correct TrackGroups

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=130111048
parent fc5df631
......@@ -31,6 +31,7 @@ import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.FixedTrackSelection;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.SelectionOverride;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.TrackInfo;
import com.google.android.exoplayer2.trackselection.RandomTrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelection;
......@@ -44,6 +45,9 @@ import java.util.Locale;
/* package */ final class TrackSelectionHelper implements View.OnClickListener,
DialogInterface.OnClickListener {
private static final TrackSelection.Factory FIXED_FACTORY = new FixedTrackSelection.Factory();
private static final TrackSelection.Factory RANDOM_FACTORY = new RandomTrackSelection.Factory();
private final MappingTrackSelector selector;
private final TrackSelection.Factory adaptiveVideoTrackSelectionFactory;
......@@ -52,7 +56,7 @@ import java.util.Locale;
private TrackGroupArray trackGroups;
private boolean[] trackGroupsAdaptive;
private boolean isDisabled;
private TrackSelection override;
private SelectionOverride override;
private CheckedTextView disableView;
private CheckedTextView defaultView;
......@@ -92,8 +96,7 @@ import java.util.Locale;
&& trackGroups.get(i).length > 1;
}
isDisabled = selector.getRendererDisabled(rendererIndex);
override = selector.hasSelectionOverride(rendererIndex, trackGroups)
? trackInfo.getTrackSelection(rendererIndex) : null;
override = selector.getSelectionOverride(rendererIndex, trackGroups);
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(title)
......@@ -147,7 +150,7 @@ import java.util.Locale;
if (trackInfo.getTrackFormatSupport(rendererIndex, groupIndex, trackIndex)
== RendererCapabilities.FORMAT_HANDLED) {
trackView.setFocusable(true);
trackView.setTag(Pair.create(group, trackIndex));
trackView.setTag(Pair.create(groupIndex, trackIndex));
trackView.setOnClickListener(this);
haveSupportedTracks = true;
} else {
......@@ -180,19 +183,18 @@ import java.util.Locale;
disableView.setChecked(isDisabled);
defaultView.setChecked(!isDisabled && override == null);
for (int i = 0; i < trackViews.length; i++) {
TrackGroup trackGroup = trackGroups.get(i);
for (int j = 0; j < trackViews[i].length; j++) {
trackViews[i][j].setChecked(override != null && override.getTrackGroup() == trackGroup
&& override.indexOf(trackGroup.getFormat(j)) != -1);
trackViews[i][j].setChecked(override != null && override.groupIndex == i
&& override.containsTrack(j));
}
}
if (enableRandomAdaptationView != null) {
boolean enableView = !isDisabled && override != null && override.length() > 1;
boolean enableView = !isDisabled && override != null && override.length > 1;
enableRandomAdaptationView.setEnabled(enableView);
enableRandomAdaptationView.setFocusable(enableView);
if (enableView) {
enableRandomAdaptationView.setChecked(!isDisabled
&& override instanceof RandomTrackSelection);
&& override.factory instanceof RandomTrackSelection.Factory);
}
}
}
......@@ -224,20 +226,19 @@ import java.util.Locale;
isDisabled = false;
override = null;
} else if (view == enableRandomAdaptationView) {
setOverride(override.getTrackGroup(), getTracks(override),
!enableRandomAdaptationView.isChecked());
setOverride(override.groupIndex, override.tracks, !enableRandomAdaptationView.isChecked());
} else {
isDisabled = false;
@SuppressWarnings("unchecked")
Pair<TrackGroup, Integer> tag = (Pair<TrackGroup, Integer>) view.getTag();
TrackGroup group = tag.first;
Pair<Integer, Integer> tag = (Pair<Integer, Integer>) view.getTag();
int groupIndex = tag.first;
int trackIndex = tag.second;
if (!trackGroupsAdaptive[trackGroups.indexOf(group)] || override == null) {
override = new FixedTrackSelection(group, trackIndex);
if (!trackGroupsAdaptive[groupIndex] || override == null) {
override = new SelectionOverride(FIXED_FACTORY, groupIndex, trackIndex);
} else {
// The group being modified is adaptive and we already have a non-null override.
boolean isEnabled = ((CheckedTextView) view).isChecked();
int overrideLength = override.length();
int overrideLength = override.length;
if (isEnabled) {
// Remove the track from the override.
if (overrideLength == 1) {
......@@ -245,12 +246,12 @@ import java.util.Locale;
override = null;
isDisabled = true;
} else {
setOverride(group, getTracksRemoving(override, trackIndex),
setOverride(groupIndex, getTracksRemoving(override, trackIndex),
enableRandomAdaptationView.isChecked());
}
} else {
// Add the track to the override.
setOverride(group, getTracksAdding(override, trackIndex),
setOverride(groupIndex, getTracksAdding(override, trackIndex),
enableRandomAdaptationView.isChecked());
}
}
......@@ -259,34 +260,26 @@ import java.util.Locale;
updateViews();
}
private void setOverride(TrackGroup group, int[] tracks, boolean enableRandomAdaptation) {
override = tracks.length == 1 ? new FixedTrackSelection(group, tracks[0])
: (enableRandomAdaptation ? new RandomTrackSelection(group, tracks)
: adaptiveVideoTrackSelectionFactory.createTrackSelection(group, tracks));
private void setOverride(int group, int[] tracks, boolean enableRandomAdaptation) {
TrackSelection.Factory factory = tracks.length == 1 ? FIXED_FACTORY
: (enableRandomAdaptation ? RANDOM_FACTORY : adaptiveVideoTrackSelectionFactory);
override = new SelectionOverride(factory, group, tracks);
}
// Track array manipulation.
private static int[] getTracks(TrackSelection trackSelection) {
int[] tracks = new int[trackSelection.length()];
for (int i = 0; i < tracks.length; i++) {
tracks[i] = trackSelection.getIndexInTrackGroup(i);
}
return tracks;
}
private static int[] getTracksAdding(TrackSelection trackSelection, int addedTrack) {
int[] tracks = getTracks(trackSelection);
private static int[] getTracksAdding(SelectionOverride override, int addedTrack) {
int[] tracks = override.tracks;
tracks = Arrays.copyOf(tracks, tracks.length + 1);
tracks[tracks.length - 1] = addedTrack;
return tracks;
}
private static int[] getTracksRemoving(TrackSelection trackSelection, int removedTrack) {
int[] tracks = new int[trackSelection.length() - 1];
private static int[] getTracksRemoving(SelectionOverride override, int removedTrack) {
int[] tracks = new int[override.length - 1];
int trackCount = 0;
for (int i = 0; i < tracks.length + 1; i++) {
int track = trackSelection.getIndexInTrackGroup(i);
int track = override.tracks[i];
if (track != removedTrack) {
tracks[trackCount++] = track;
}
......
......@@ -475,7 +475,7 @@ public class HlsChunkSource {
/**
* A {@link TrackSelection} to use for initialization.
*/
public static final class InitializationTrackSelection extends BaseTrackSelection {
private static final class InitializationTrackSelection extends BaseTrackSelection {
private int selectedIndex;
......
......@@ -137,8 +137,8 @@ public class AdaptiveVideoTrackSelection extends BaseTrackSelection {
* for inaccuracies in the bandwidth estimator.
*/
public AdaptiveVideoTrackSelection(TrackGroup group, int[] tracks, BandwidthMeter bandwidthMeter,
int maxInitialBitrate, int minDurationForQualityIncreaseMs,
int maxDurationForQualityDecreaseMs, int minDurationToRetainAfterDiscardMs,
int maxInitialBitrate, long minDurationForQualityIncreaseMs,
long maxDurationForQualityDecreaseMs, long minDurationToRetainAfterDiscardMs,
float bandwidthFraction) {
super(group, tracks);
this.bandwidthMeter = bandwidthMeter;
......
......@@ -37,11 +37,11 @@ public abstract class BaseTrackSelection implements TrackSelection {
* The number of selected tracks within the {@link TrackGroup}. Always greater than zero.
*/
protected final int length;
/**
* The indices of the selected tracks in {@link #group}, in order of decreasing bandwidth.
*/
private final int[] tracks;
protected final int[] tracks;
/**
* The {@link Format}s of the selected tracks, in order of decreasing bandwidth.
*/
......
......@@ -17,12 +17,43 @@ package com.google.android.exoplayer2.trackselection;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.util.Assertions;
/**
* A {@link TrackSelection} consisting of a single track.
*/
public final class FixedTrackSelection extends BaseTrackSelection {
/**
* Factory for {@link FixedTrackSelection} instances.
*/
public static final class Factory implements TrackSelection.Factory {
private final int reason;
private final Object data;
public Factory() {
this.reason = C.SELECTION_REASON_UNKNOWN;
this.data = null;
}
/**
* @param reason A reason for the track selection.
* @param data Optional data associated with the track selection.
*/
public Factory(int reason, Object data) {
this.reason = reason;
this.data = data;
}
@Override
public FixedTrackSelection createTrackSelection(TrackGroup group, int... tracks) {
Assertions.checkArgument(tracks.length == 1);
return new FixedTrackSelection(group, tracks[0], reason, data);
}
}
private final int reason;
private final Object data;
......
......@@ -50,9 +50,55 @@ public abstract class MappingTrackSelector extends TrackSelector {
}
/**
* A track selection override.
*/
public static final class SelectionOverride {
public final TrackSelection.Factory factory;
public final int groupIndex;
public final int[] tracks;
public final int length;
/**
* @param factory A factory for creating selections from this override.
* @param groupIndex The overriding group index.
* @param tracks The overriding track indices within the group.
*/
public SelectionOverride(TrackSelection.Factory factory, int groupIndex, int... tracks) {
this.factory = factory;
this.groupIndex = groupIndex;
this.tracks = tracks;
this.length = tracks.length;
}
/**
* Creates an selection from this override.
*
* @param groups The groups whose selection is being overridden.
* @return The selection.
*/
public TrackSelection createTrackSelection(TrackGroupArray groups) {
return factory.createTrackSelection(groups.get(groupIndex), tracks);
}
/**
* Returns whether this override contains the specified track index.
*/
public boolean containsTrack(int track) {
for (int i = 0; i < tracks.length; i++) {
if (tracks[i] == track) {
return true;
}
}
return false;
}
}
private final Handler eventHandler;
private final CopyOnWriteArraySet<EventListener> listeners;
private final SparseArray<Map<TrackGroupArray, TrackSelection>> trackSelectionOverrides;
private final SparseArray<Map<TrackGroupArray, SelectionOverride>> selectionOverrides;
private final SparseBooleanArray rendererDisabledFlags;
private TrackInfo activeTrackInfo;
......@@ -64,7 +110,7 @@ public abstract class MappingTrackSelector extends TrackSelector {
public MappingTrackSelector(Handler eventHandler) {
this.eventHandler = eventHandler;
this.listeners = new CopyOnWriteArraySet<>();
trackSelectionOverrides = new SparseArray<>();
selectionOverrides = new SparseArray<>();
rendererDisabledFlags = new SparseBooleanArray();
}
......@@ -134,16 +180,16 @@ public abstract class MappingTrackSelector extends TrackSelector {
*
* @param rendererIndex The renderer index.
* @param groups The {@link TrackGroupArray} for which the override should be applied.
* @param override The overriding {@link TrackSelection}.
* @param override The override.
*/
// TODO - Don't allow overrides that select unsupported tracks, unless some flag has been
// explicitly set by the user to indicate that they want this.
public final void setSelectionOverride(int rendererIndex, TrackGroupArray groups,
TrackSelection override) {
Map<TrackGroupArray, TrackSelection> overrides = trackSelectionOverrides.get(rendererIndex);
SelectionOverride override) {
Map<TrackGroupArray, SelectionOverride> overrides = selectionOverrides.get(rendererIndex);
if (overrides == null) {
overrides = new HashMap<>();
trackSelectionOverrides.put(rendererIndex, overrides);
selectionOverrides.put(rendererIndex, overrides);
}
if (overrides.containsKey(groups) && Util.areEqual(overrides.get(groups), override)) {
// The override is unchanged.
......@@ -161,25 +207,37 @@ public abstract class MappingTrackSelector extends TrackSelector {
* @return Whether there is an override.
*/
public final boolean hasSelectionOverride(int rendererIndex, TrackGroupArray groups) {
Map<TrackGroupArray, TrackSelection> overrides = trackSelectionOverrides.get(rendererIndex);
Map<TrackGroupArray, SelectionOverride> overrides = selectionOverrides.get(rendererIndex);
return overrides != null && overrides.containsKey(groups);
}
/**
* Returns the override for the specified renderer and {@link TrackGroupArray}.
*
* @param rendererIndex The renderer index.
* @param groups The {@link TrackGroupArray}.
* @return The override, or null if no override exists.
*/
public final SelectionOverride getSelectionOverride(int rendererIndex, TrackGroupArray groups) {
Map<TrackGroupArray, SelectionOverride> overrides = selectionOverrides.get(rendererIndex);
return overrides != null ? overrides.get(groups) : null;
}
/**
* Clears a track selection override for the specified renderer and {@link TrackGroupArray}.
*
* @param rendererIndex The renderer index.
* @param groups The {@link TrackGroupArray} for which the override should be cleared.
*/
public final void clearSelectionOverride(int rendererIndex, TrackGroupArray groups) {
Map<TrackGroupArray, TrackSelection> overrides = trackSelectionOverrides.get(rendererIndex);
Map<TrackGroupArray, SelectionOverride> overrides = selectionOverrides.get(rendererIndex);
if (overrides == null || !overrides.containsKey(groups)) {
// Nothing to clear.
return;
}
overrides.remove(groups);
if (overrides.isEmpty()) {
trackSelectionOverrides.remove(rendererIndex);
selectionOverrides.remove(rendererIndex);
}
invalidate();
}
......@@ -190,12 +248,12 @@ public abstract class MappingTrackSelector extends TrackSelector {
* @param rendererIndex The renderer index.
*/
public final void clearSelectionOverrides(int rendererIndex) {
Map<TrackGroupArray, TrackSelection> overrides = trackSelectionOverrides.get(rendererIndex);
Map<TrackGroupArray, ?> overrides = selectionOverrides.get(rendererIndex);
if (overrides == null || overrides.isEmpty()) {
// Nothing to clear.
return;
}
trackSelectionOverrides.remove(rendererIndex);
selectionOverrides.remove(rendererIndex);
invalidate();
}
......@@ -203,11 +261,11 @@ public abstract class MappingTrackSelector extends TrackSelector {
* Clears all track selection overrides.
*/
public final void clearSelectionOverrides() {
if (trackSelectionOverrides.size() == 0) {
if (selectionOverrides.size() == 0) {
// Nothing to clear.
return;
}
trackSelectionOverrides.clear();
selectionOverrides.clear();
invalidate();
}
......@@ -277,11 +335,11 @@ public abstract class MappingTrackSelector extends TrackSelector {
if (rendererDisabledFlags.get(i)) {
trackSelections[i] = null;
} else {
Map<TrackGroupArray, TrackSelection> override = trackSelectionOverrides.get(i);
TrackSelection overrideSelection = override == null ? null
: override.get(rendererTrackGroupArrays[i]);
if (overrideSelection != null) {
trackSelections[i] = overrideSelection;
TrackGroupArray rendererTrackGroup = rendererTrackGroupArrays[i];
Map<TrackGroupArray, SelectionOverride> overrides = selectionOverrides.get(i);
SelectionOverride override = overrides == null ? null : overrides.get(rendererTrackGroup);
if (override != null) {
trackSelections[i] = override.createTrackSelection(rendererTrackGroup);
}
}
}
......
......@@ -25,6 +25,31 @@ import java.util.Random;
*/
public final class RandomTrackSelection extends BaseTrackSelection {
/**
* Factory for {@link RandomTrackSelection} instances.
*/
public static final class Factory implements TrackSelection.Factory {
private final Random random;
public Factory() {
random = new Random();
}
/**
* @param seed A seed for the {@link Random} instance used by the factory.
*/
public Factory(int seed) {
random = new Random(seed);
}
@Override
public RandomTrackSelection createTrackSelection(TrackGroup group, int... tracks) {
return new RandomTrackSelection(group, tracks, random);
}
}
private final Random random;
private int selectedIndex;
......@@ -47,8 +72,18 @@ public final class RandomTrackSelection extends BaseTrackSelection {
* @param seed A seed for the {@link Random} instance used to update the selected track.
*/
public RandomTrackSelection(TrackGroup group, int[] tracks, long seed) {
this(group, tracks, new Random(seed));
}
/**
* @param group The {@link TrackGroup}. Must not be null.
* @param tracks The indices of the selected tracks within the {@link TrackGroup}. Must not be
* null or empty. May be in any order.
* @param random A source of random numbers.
*/
public RandomTrackSelection(TrackGroup group, int[] tracks, Random random) {
super(group, tracks);
random = new Random(seed);
this.random = random;
selectedIndex = random.nextInt(length);
}
......
......@@ -50,7 +50,7 @@ public interface TrackSelection {
* Returns the {@link TrackGroup} to which the selected tracks belong.
*/
TrackGroup getTrackGroup();
// Static subset of selected tracks.
/**
......
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