diff --git a/demo/src/main/java/com/google/android/exoplayer/demo/player/DemoPlayer.java b/demo/src/main/java/com/google/android/exoplayer/demo/player/DemoPlayer.java index f72c8d44f1..bf9c44290a 100644 --- a/demo/src/main/java/com/google/android/exoplayer/demo/player/DemoPlayer.java +++ b/demo/src/main/java/com/google/android/exoplayer/demo/player/DemoPlayer.java @@ -17,6 +17,7 @@ package com.google.android.exoplayer.demo.player; import com.google.android.exoplayer.C; import com.google.android.exoplayer.CodecCounters; +import com.google.android.exoplayer.DefaultTrackSelectionPolicy; import com.google.android.exoplayer.DefaultTrackSelector; import com.google.android.exoplayer.DefaultTrackSelector.TrackInfo; import com.google.android.exoplayer.ExoPlaybackException; @@ -170,7 +171,7 @@ public class DemoPlayer implements ExoPlayer.Listener, DefaultTrackSelector.Even renderers = renderersList.toArray(new TrackRenderer[renderersList.size()]); // Build the player and associated objects. - trackSelector = new DefaultTrackSelector(mainHandler, this); + trackSelector = new DefaultTrackSelector(mainHandler, this, new DefaultTrackSelectionPolicy()); player = ExoPlayer.Factory.newInstance(renderers, trackSelector, 1000, 5000); player.addListener(this); playerControl = new PlayerControl(player); diff --git a/extensions/flac/src/androidTest/java/com/google/android/exoplayer/ext/flac/FlacPlaybackTest.java b/extensions/flac/src/androidTest/java/com/google/android/exoplayer/ext/flac/FlacPlaybackTest.java index 0768a4f143..70c9049b1b 100644 --- a/extensions/flac/src/androidTest/java/com/google/android/exoplayer/ext/flac/FlacPlaybackTest.java +++ b/extensions/flac/src/androidTest/java/com/google/android/exoplayer/ext/flac/FlacPlaybackTest.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer.ext.flac; +import com.google.android.exoplayer.DefaultTrackSelectionPolicy; import com.google.android.exoplayer.DefaultTrackSelector; import com.google.android.exoplayer.ExoPlaybackException; import com.google.android.exoplayer.ExoPlayer; @@ -76,7 +77,8 @@ public class FlacPlaybackTest extends InstrumentationTestCase { public void run() { Looper.prepare(); LibflacAudioTrackRenderer audioRenderer = new LibflacAudioTrackRenderer(); - DefaultTrackSelector trackSelector = new DefaultTrackSelector(null, null); + DefaultTrackSelector trackSelector = new DefaultTrackSelector(null, null, + new DefaultTrackSelectionPolicy()); player = ExoPlayer.Factory.newInstance(new TrackRenderer[] {audioRenderer}, trackSelector); player.addListener(this); ExtractorSampleSource sampleSource = new ExtractorSampleSource( diff --git a/extensions/opus/src/androidTest/java/com/google/android/exoplayer/ext/opus/OpusPlaybackTest.java b/extensions/opus/src/androidTest/java/com/google/android/exoplayer/ext/opus/OpusPlaybackTest.java index 32b9b55c8b..5a05ba98db 100644 --- a/extensions/opus/src/androidTest/java/com/google/android/exoplayer/ext/opus/OpusPlaybackTest.java +++ b/extensions/opus/src/androidTest/java/com/google/android/exoplayer/ext/opus/OpusPlaybackTest.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer.ext.opus; +import com.google.android.exoplayer.DefaultTrackSelectionPolicy; import com.google.android.exoplayer.DefaultTrackSelector; import com.google.android.exoplayer.ExoPlaybackException; import com.google.android.exoplayer.ExoPlayer; @@ -76,7 +77,8 @@ public class OpusPlaybackTest extends InstrumentationTestCase { public void run() { Looper.prepare(); LibopusAudioTrackRenderer audioRenderer = new LibopusAudioTrackRenderer(); - DefaultTrackSelector trackSelector = new DefaultTrackSelector(null, null); + DefaultTrackSelector trackSelector = new DefaultTrackSelector(null, null, + new DefaultTrackSelectionPolicy()); player = ExoPlayer.Factory.newInstance(new TrackRenderer[] {audioRenderer}, trackSelector); player.addListener(this); ExtractorSampleSource sampleSource = new ExtractorSampleSource( diff --git a/extensions/vp9/src/androidTest/java/com/google/android/exoplayer/ext/vp9/VpxPlaybackTest.java b/extensions/vp9/src/androidTest/java/com/google/android/exoplayer/ext/vp9/VpxPlaybackTest.java index d395887eda..292b60a517 100644 --- a/extensions/vp9/src/androidTest/java/com/google/android/exoplayer/ext/vp9/VpxPlaybackTest.java +++ b/extensions/vp9/src/androidTest/java/com/google/android/exoplayer/ext/vp9/VpxPlaybackTest.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer.ext.vp9; +import com.google.android.exoplayer.DefaultTrackSelectionPolicy; import com.google.android.exoplayer.DefaultTrackSelector; import com.google.android.exoplayer.ExoPlaybackException; import com.google.android.exoplayer.ExoPlayer; @@ -92,7 +93,8 @@ public class VpxPlaybackTest extends InstrumentationTestCase { public void run() { Looper.prepare(); LibvpxVideoTrackRenderer videoRenderer = new LibvpxVideoTrackRenderer(true); - DefaultTrackSelector trackSelector = new DefaultTrackSelector(null, null); + DefaultTrackSelector trackSelector = new DefaultTrackSelector(null, null, + new DefaultTrackSelectionPolicy()); player = ExoPlayer.Factory.newInstance(new TrackRenderer[] {videoRenderer}, trackSelector); player.addListener(this); ExtractorSampleSource sampleSource = new ExtractorSampleSource( diff --git a/library/src/main/java/com/google/android/exoplayer/DefaultTrackSelectionPolicy.java b/library/src/main/java/com/google/android/exoplayer/DefaultTrackSelectionPolicy.java new file mode 100644 index 0000000000..91ccab89ee --- /dev/null +++ b/library/src/main/java/com/google/android/exoplayer/DefaultTrackSelectionPolicy.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer; + +/** + * A {@link TrackSelectionPolicy} that allows configuration of common parameters. + */ +public class DefaultTrackSelectionPolicy extends TrackSelectionPolicy { + + @Override + public TrackSelection[] selectTracks(TrackRenderer[] renderers, + TrackGroupArray[] rendererTrackGroupArrays, int[][][] rendererFormatSupports) { + // Make a track selection for each renderer. + TrackSelection[] rendererTrackSelections = new TrackSelection[renderers.length]; + for (int i = 0; i < renderers.length; i++) { + rendererTrackSelections[i] = selectTracksForRenderer(rendererTrackGroupArrays[i], + rendererFormatSupports[i]); + } + return rendererTrackSelections; + } + + private static TrackSelection selectTracksForRenderer(TrackGroupArray trackGroups, + int[][] formatSupport) { + // TODO: Allow more specific track selection parameters. + for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) { + TrackGroup trackGroup = trackGroups.get(groupIndex); + int[] trackFormatSupport = formatSupport[groupIndex]; + for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) { + if ((trackFormatSupport[trackIndex] & TrackRenderer.FORMAT_SUPPORT_MASK) + == TrackRenderer.FORMAT_HANDLED) { + return new TrackSelection(groupIndex, trackIndex); + } + } + } + return null; + } + +} + diff --git a/library/src/main/java/com/google/android/exoplayer/DefaultTrackSelector.java b/library/src/main/java/com/google/android/exoplayer/DefaultTrackSelector.java index 21632d15b4..93495a68a8 100644 --- a/library/src/main/java/com/google/android/exoplayer/DefaultTrackSelector.java +++ b/library/src/main/java/com/google/android/exoplayer/DefaultTrackSelector.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer; +import com.google.android.exoplayer.util.Assertions; import com.google.android.exoplayer.util.Util; import android.os.Handler; @@ -29,7 +30,8 @@ import java.util.Map; /** * A {@link TrackSelector} suitable for a wide range of use cases. */ -public class DefaultTrackSelector extends TrackSelector { +public class DefaultTrackSelector extends TrackSelector implements + TrackSelectionPolicy.InvalidationListener{ /** * Interface definition for a callback to be notified of {@link DefaultTrackSelector} events. @@ -49,6 +51,7 @@ public class DefaultTrackSelector extends TrackSelector { private final EventListener eventListener; private final SparseArray> trackSelectionOverrides; private final SparseBooleanArray rendererDisabledFlags; + private final TrackSelectionPolicy trackSelectionPolicy; private TrackInfo activeTrackInfo; @@ -56,12 +59,16 @@ public class DefaultTrackSelector extends TrackSelector { * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be * null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required. + * @param trackSelectionPolicy Defines the policy for track selection. */ - public DefaultTrackSelector(Handler eventHandler, EventListener eventListener) { + public DefaultTrackSelector(Handler eventHandler, EventListener eventListener, + TrackSelectionPolicy trackSelectionPolicy) { this.eventHandler = eventHandler; this.eventListener = eventListener; trackSelectionOverrides = new SparseArray<>(); rendererDisabledFlags = new SparseBooleanArray(); + this.trackSelectionPolicy = Assertions.checkNotNull(trackSelectionPolicy); + this.trackSelectionPolicy.init(this); } /** @@ -189,6 +196,14 @@ public class DefaultTrackSelector extends TrackSelector { invalidate(); } + /** + * Invoked when the {@link TrackSelectionPolicy} has changed. + */ + @Override + public void invalidatePolicySelections() { + invalidate(); + } + // TrackSelector implementation. @Override @@ -244,12 +259,21 @@ public class DefaultTrackSelector extends TrackSelector { TrackGroupArray unassociatedTrackGroupArray = new TrackGroupArray( Arrays.copyOf(rendererTrackGroups[renderers.length], unassociatedTrackGroupCount)); - // Make a track selection for each renderer. - TrackSelection[] rendererTrackSelections = new TrackSelection[renderers.length]; + TrackSelection[] rendererTrackSelections = trackSelectionPolicy.selectTracks(renderers, + rendererTrackGroupArrays, rendererFormatSupports); + + // Apply track disabling and overriding. for (int i = 0; i < renderers.length; i++) { - rendererTrackSelections[i] = rendererDisabledFlags.get(i) ? null - : selectTracksForRenderer(rendererTrackGroupArrays[i], rendererFormatSupports[i], - trackSelectionOverrides.get(i)); + if (rendererDisabledFlags.get(i)) { + rendererTrackSelections[i] = null; + } else { + Map override = trackSelectionOverrides.get(i); + TrackSelection overrideSelection = override == null ? null + : override.get(rendererTrackGroupArrays[i]); + if (overrideSelection != null) { + rendererTrackSelections[i] = overrideSelection; + } + } } // The track selections above index into the track group arrays associated to each renderer, @@ -349,27 +373,6 @@ public class DefaultTrackSelector extends TrackSelector { return mixedMimeTypeAdaptationSupport; } - private static TrackSelection selectTracksForRenderer(TrackGroupArray trackGroups, - int[][] formatSupport, Map overrides) { - if (overrides != null && overrides.containsKey(trackGroups)) { - return overrides.get(trackGroups); - } - - // TODO[REFACTOR]: Implement real default selection logic here. - for (int groupIndex = 0; groupIndex < trackGroups.length; groupIndex++) { - TrackGroup trackGroup = trackGroups.get(groupIndex); - int[] trackFormatSupport = formatSupport[groupIndex]; - for (int trackIndex = 0; trackIndex < trackGroup.length; trackIndex++) { - if ((trackFormatSupport[trackIndex] & TrackRenderer.FORMAT_SUPPORT_MASK) - == TrackRenderer.FORMAT_HANDLED) { - return new TrackSelection(groupIndex, trackIndex); - } - } - } - - return null; - } - /** * Finds the specified group in a group array, using referential equality. * diff --git a/library/src/main/java/com/google/android/exoplayer/TrackSelectionPolicy.java b/library/src/main/java/com/google/android/exoplayer/TrackSelectionPolicy.java new file mode 100644 index 0000000000..068679cdb4 --- /dev/null +++ b/library/src/main/java/com/google/android/exoplayer/TrackSelectionPolicy.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer; + +/** + * Defines a policy for selecting the track rendered by each {@link TrackRenderer}. + */ +public abstract class TrackSelectionPolicy { + + /** + * Notified when selection parameters have changed. + */ + /* package */ interface InvalidationListener { + + /** + * Invoked by a {@link TrackSelectionPolicy} when previous selections are invalidated. + */ + void invalidatePolicySelections(); + + } + + private InvalidationListener listener; + + /** + * Must be invoked by subclasses when a selection parameter has changed, invalidating previous + * selections. + */ + protected void invalidate() { + listener.invalidatePolicySelections(); + } + + /** + * Given an array of {@link TrackRenderer}s and a set of {@link TrackGroup}s assigned to each of + * them, provides a {@link TrackSelection} per renderer. + * + * @param renderers The available {@link TrackRenderer}s. + * @param rendererTrackGroupArrays An array of {@link TrackGroupArray}s where each entry + * corresponds to the {@link TrackRenderer} of equal index in {@code renderers}. + * @param rendererFormatSupports Maps every available track to a specific level of support as + * defined by the {@link TrackRenderer} FORMAT_* constants. + */ + /* package */ abstract TrackSelection[] selectTracks(TrackRenderer[] renderers, + TrackGroupArray[] rendererTrackGroupArrays, int[][][] rendererFormatSupports); + + /* package */ void init(InvalidationListener listener) { + this.listener = listener; + } + +} +