diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 05e5cf6751..13d983285c 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -34,7 +34,7 @@ use the default bandwidth meter automatically. This change only works correctly if the following changes are adopted for custom `BandwidthMeter`s, `TrackSelection`s, `MediaSource`s and `DataSource`s. - * Pass `BandwidthMeter` to `TrackSelection.Factory` which can be used to + * Pass `BandwidthMeter` to `TrackSelection.Factory` which should be used to obtain bandwidth estimates. * Add method to `BandwidthMeter` to return the `TransferListener` used to gather bandwidth information. Also add methods to add and remove event diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelection.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelection.java index d13596d2d7..64b0da281c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelection.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/AdaptiveTrackSelection.java @@ -21,7 +21,6 @@ import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.chunk.MediaChunk; import com.google.android.exoplayer2.upstream.BandwidthMeter; -import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Clock; import com.google.android.exoplayer2.util.Util; import java.util.List; @@ -37,7 +36,7 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { */ public static final class Factory implements TrackSelection.Factory { - private final BandwidthMeter bandwidthMeter; + private final @Nullable BandwidthMeter bandwidthMeter; private final int minDurationForQualityIncreaseMs; private final int maxDurationForQualityDecreaseMs; private final int minDurationToRetainAfterDiscardMs; @@ -46,9 +45,24 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { private final long minTimeBetweenBufferReevaluationMs; private final Clock clock; + /** Creates an adaptive track selection factory with default parameters. */ + public Factory() { + this( + DEFAULT_MIN_DURATION_FOR_QUALITY_INCREASE_MS, + DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS, + DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS, + DEFAULT_BANDWIDTH_FRACTION, + DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE, + DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS, + Clock.DEFAULT); + } + /** - * @param bandwidthMeter Provides an estimate of the currently available bandwidth. + * @deprecated Use {@link #Factory()} instead. Custom bandwidth meter should be directly passed + * to the player in ExoPlayerFactory. */ + @Deprecated + @SuppressWarnings("deprecation") public Factory(BandwidthMeter bandwidthMeter) { this( bandwidthMeter, @@ -62,7 +76,8 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { } /** - * @param bandwidthMeter Provides an estimate of the currently available bandwidth. + * Creates an adaptive track selection factory. + * * @param minDurationForQualityIncreaseMs The minimum duration of buffered data required for the * selected track to switch to one of higher quality. * @param maxDurationForQualityDecreaseMs The maximum duration of buffered data required for the @@ -75,6 +90,27 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { * consider available for use. Setting to a value less than 1 is recommended to account for * inaccuracies in the bandwidth estimator. */ + public Factory( + int minDurationForQualityIncreaseMs, + int maxDurationForQualityDecreaseMs, + int minDurationToRetainAfterDiscardMs, + float bandwidthFraction) { + this( + minDurationForQualityIncreaseMs, + maxDurationForQualityDecreaseMs, + minDurationToRetainAfterDiscardMs, + bandwidthFraction, + DEFAULT_BUFFERED_FRACTION_TO_LIVE_EDGE_FOR_QUALITY_INCREASE, + DEFAULT_MIN_TIME_BETWEEN_BUFFER_REEVALUTATION_MS, + Clock.DEFAULT); + } + + /** + * @deprecated Use {@link #Factory(int, int, int, float)} instead. Custom bandwidth meter should + * be directly passed to the player in ExoPlayerFactory. + */ + @Deprecated + @SuppressWarnings("deprecation") public Factory( BandwidthMeter bandwidthMeter, int minDurationForQualityIncreaseMs, @@ -93,7 +129,8 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { } /** - * @param bandwidthMeter Provides an estimate of the currently available bandwidth.. + * Creates an adaptive track selection factory. + * * @param minDurationForQualityIncreaseMs The minimum duration of buffered data required for the * selected track to switch to one of higher quality. * @param maxDurationForQualityDecreaseMs The maximum duration of buffered data required for the @@ -117,8 +154,33 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { * buffer reevaluation calls. * @param clock A {@link Clock}. */ + @SuppressWarnings("deprecation") public Factory( - BandwidthMeter bandwidthMeter, + int minDurationForQualityIncreaseMs, + int maxDurationForQualityDecreaseMs, + int minDurationToRetainAfterDiscardMs, + float bandwidthFraction, + float bufferedFractionToLiveEdgeForQualityIncrease, + long minTimeBetweenBufferReevaluationMs, + Clock clock) { + this( + /* bandwidthMeter= */ null, + minDurationForQualityIncreaseMs, + maxDurationForQualityDecreaseMs, + minDurationToRetainAfterDiscardMs, + bandwidthFraction, + bufferedFractionToLiveEdgeForQualityIncrease, + minTimeBetweenBufferReevaluationMs, + clock); + } + + /** + * @deprecated Use {@link #Factory(int, int, int, float, float, long, Clock)} instead. Custom + * bandwidth meter should be directly passed to the player in ExoPlayerFactory. + */ + @Deprecated + public Factory( + @Nullable BandwidthMeter bandwidthMeter, int minDurationForQualityIncreaseMs, int maxDurationForQualityDecreaseMs, int minDurationToRetainAfterDiscardMs, @@ -139,14 +201,14 @@ public class AdaptiveTrackSelection extends BaseTrackSelection { @Override public AdaptiveTrackSelection createTrackSelection( - TrackGroup group, @Nullable BandwidthMeter bandwidthMeter, int... tracks) { + TrackGroup group, BandwidthMeter bandwidthMeter, int... tracks) { if (this.bandwidthMeter != null) { bandwidthMeter = this.bandwidthMeter; } return new AdaptiveTrackSelection( group, tracks, - Assertions.checkNotNull(bandwidthMeter), + bandwidthMeter, minDurationForQualityIncreaseMs, maxDurationForQualityDecreaseMs, minDurationToRetainAfterDiscardMs, diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java index bf8207839d..58784e4c5a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelector.java @@ -1056,23 +1056,19 @@ public class DefaultTrackSelector extends MappingTrackSelector { private static final int[] NO_TRACKS = new int[0]; private static final int WITHIN_RENDERER_CAPABILITIES_BONUS = 1000; - private final @Nullable TrackSelection.Factory adaptiveTrackSelectionFactory; + private final TrackSelection.Factory adaptiveTrackSelectionFactory; private final AtomicReference parametersReference; - /** - * Constructs an instance that does not support adaptive track selection. - */ + /** Constructs an instance that uses a default factory to create adaptive track selections. */ public DefaultTrackSelector() { - this((TrackSelection.Factory) null); + this(new AdaptiveTrackSelection.Factory()); } /** - * Constructs an instance that supports adaptive track selection. Adaptive track selections use - * the provided {@link BandwidthMeter} to determine which individual track should be used during - * playback. - * - * @param bandwidthMeter The {@link BandwidthMeter}. + * @deprecated Use {@link #DefaultTrackSelector()} instead. Custom bandwidth meter should be + * directly passed to the player in ExoPlayerFactory. */ + @Deprecated public DefaultTrackSelector(BandwidthMeter bandwidthMeter) { this(new AdaptiveTrackSelection.Factory(bandwidthMeter)); } @@ -1080,10 +1076,9 @@ public class DefaultTrackSelector extends MappingTrackSelector { /** * Constructs an instance that uses a factory to create adaptive track selections. * - * @param adaptiveTrackSelectionFactory A factory for adaptive {@link TrackSelection}s, or null if - * the selector should not support adaptive tracks. + * @param adaptiveTrackSelectionFactory A factory for adaptive {@link TrackSelection}s. */ - public DefaultTrackSelector(@Nullable TrackSelection.Factory adaptiveTrackSelectionFactory) { + public DefaultTrackSelector(TrackSelection.Factory adaptiveTrackSelectionFactory) { this.adaptiveTrackSelectionFactory = adaptiveTrackSelectionFactory; parametersReference = new AtomicReference<>(Parameters.DEFAULT); } @@ -1381,7 +1376,7 @@ public class DefaultTrackSelector extends MappingTrackSelector { int mixedMimeTypeAdaptationSupports, Parameters params, TrackSelection.Factory adaptiveTrackSelectionFactory, - @Nullable BandwidthMeter bandwidthMeter) + BandwidthMeter bandwidthMeter) throws ExoPlaybackException { int requiredAdaptiveSupport = params.allowNonSeamlessAdaptiveness ? (RendererCapabilities.ADAPTIVE_NOT_SEAMLESS | RendererCapabilities.ADAPTIVE_SEAMLESS) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/FixedTrackSelection.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/FixedTrackSelection.java index e378b4fcf5..b41698521f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/FixedTrackSelection.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/FixedTrackSelection.java @@ -50,7 +50,7 @@ public final class FixedTrackSelection extends BaseTrackSelection { @Override public FixedTrackSelection createTrackSelection( - TrackGroup group, @Nullable BandwidthMeter bandwidthMeter, int... tracks) { + TrackGroup group, BandwidthMeter bandwidthMeter, int... tracks) { Assertions.checkArgument(tracks.length == 1); return new FixedTrackSelection(group, tracks[0], reason, data); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/RandomTrackSelection.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/RandomTrackSelection.java index 4c908f3a7f..2ea90761af 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/RandomTrackSelection.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/RandomTrackSelection.java @@ -47,7 +47,7 @@ public final class RandomTrackSelection extends BaseTrackSelection { @Override public RandomTrackSelection createTrackSelection( - TrackGroup group, @Nullable BandwidthMeter bandwidthMeter, int... tracks) { + TrackGroup group, BandwidthMeter bandwidthMeter, int... tracks) { return new RandomTrackSelection(group, tracks, random); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelection.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelection.java index efa895a3a1..0650159cf4 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelection.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelection.java @@ -37,29 +37,17 @@ public interface TrackSelection { */ interface Factory { - /** - * @deprecated Use and implement {@link - * #createTrackSelection(TrackGroup, BandwidthMeter, int...)} instead. - */ - @Deprecated - default TrackSelection createTrackSelection(TrackGroup group, int... tracks) { - return createTrackSelection(group, /* bandwidthMeter= */ null, tracks); - } - /** * Creates a new selection. * * @param group The {@link TrackGroup}. Must not be null. - * @param bandwidthMeter A {@link BandwidthMeter} which can be used to select tracks, or null if - * no such bandwidth meter is available. + * @param bandwidthMeter A {@link BandwidthMeter} which can be used to select tracks. * @param tracks The indices of the selected tracks within the {@link TrackGroup}. Must not be * null or empty. May be in any order. * @return The created selection. */ - default TrackSelection createTrackSelection( - TrackGroup group, @Nullable BandwidthMeter bandwidthMeter, int... tracks) { - return createTrackSelection(group, tracks); - } + TrackSelection createTrackSelection( + TrackGroup group, BandwidthMeter bandwidthMeter, int... tracks); } /** diff --git a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelector.java b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelector.java index e2ac7fff2a..3bb603318f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelector.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/trackselection/TrackSelector.java @@ -23,6 +23,7 @@ import com.google.android.exoplayer2.RendererCapabilities; import com.google.android.exoplayer2.RendererConfiguration; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.upstream.BandwidthMeter; +import com.google.android.exoplayer2.util.Assertions; /** * The component of an {@link ExoPlayer} responsible for selecting tracks to be consumed by each of @@ -103,10 +104,9 @@ public abstract class TrackSelector { * * @param listener An invalidation listener that the selector can call to indicate that selections * it has previously made are no longer valid. - * @param bandwidthMeter A bandwidth meter which can be used by track selections to select tracks, - * or null if no such bandwidth meter is available. + * @param bandwidthMeter A bandwidth meter which can be used by track selections to select tracks. */ - public final void init(InvalidationListener listener, @Nullable BandwidthMeter bandwidthMeter) { + public final void init(InvalidationListener listener, BandwidthMeter bandwidthMeter) { this.listener = listener; this.bandwidthMeter = bandwidthMeter; } @@ -142,10 +142,10 @@ public abstract class TrackSelector { } /** - * Returns a bandwidth meter which can be used by track selections to select tracks, or null if no - * such bandwidth meter is available. + * Returns a bandwidth meter which can be used by track selections to select tracks. Must only be + * called after {@link #init(InvalidationListener, BandwidthMeter)} has been called. */ - protected final @Nullable BandwidthMeter getBandwidthMeter() { - return bandwidthMeter; + protected final BandwidthMeter getBandwidthMeter() { + return Assertions.checkNotNull(bandwidthMeter); } } diff --git a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelectorTest.java b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelectorTest.java index 0b949892af..13314dccf0 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelectorTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/DefaultTrackSelectorTest.java @@ -115,13 +115,16 @@ public final class DefaultTrackSelectorTest { @Mock private InvalidationListener invalidationListener; + @Mock private BandwidthMeter bandwidthMeter; private DefaultTrackSelector trackSelector; @Before public void setUp() { initMocks(this); + when(bandwidthMeter.getBitrateEstimate()).thenReturn(1000000L); trackSelector = new DefaultTrackSelector(); + trackSelector.init(invalidationListener, bandwidthMeter); } /** Tests {@link Parameters} {@link android.os.Parcelable} implementation. */ @@ -188,6 +191,7 @@ public final class DefaultTrackSelectorTest { @Test public void testSelectTracksWithNullOverride() throws ExoPlaybackException { DefaultTrackSelector trackSelector = new DefaultTrackSelector(); + trackSelector.init(invalidationListener, bandwidthMeter); trackSelector.setParameters( trackSelector .buildUponParameters() @@ -202,6 +206,7 @@ public final class DefaultTrackSelectorTest { @Test public void testSelectTracksWithClearedNullOverride() throws ExoPlaybackException { DefaultTrackSelector trackSelector = new DefaultTrackSelector(); + trackSelector.init(invalidationListener, bandwidthMeter); trackSelector.setParameters( trackSelector .buildUponParameters() @@ -217,6 +222,7 @@ public final class DefaultTrackSelectorTest { @Test public void testSelectTracksWithNullOverrideForDifferentTracks() throws ExoPlaybackException { DefaultTrackSelector trackSelector = new DefaultTrackSelector(); + trackSelector.init(invalidationListener, bandwidthMeter); trackSelector.setParameters( trackSelector .buildUponParameters() @@ -234,6 +240,7 @@ public final class DefaultTrackSelectorTest { @Test public void testSelectTracksWithDisabledRenderer() throws ExoPlaybackException { DefaultTrackSelector trackSelector = new DefaultTrackSelector(); + trackSelector.init(invalidationListener, bandwidthMeter); trackSelector.setParameters(trackSelector.buildUponParameters().setRendererDisabled(1, true)); TrackSelectorResult result = trackSelector.selectTracks(RENDERER_CAPABILITIES, TRACK_GROUPS); assertTrackSelections(result, new TrackSelection[] {TRACK_SELECTIONS[0], null}); @@ -245,6 +252,7 @@ public final class DefaultTrackSelectorTest { @Test public void testSelectTracksWithClearedDisabledRenderer() throws ExoPlaybackException { DefaultTrackSelector trackSelector = new DefaultTrackSelector(); + trackSelector.init(invalidationListener, bandwidthMeter); trackSelector.setParameters( trackSelector .buildUponParameters() @@ -260,6 +268,7 @@ public final class DefaultTrackSelectorTest { @Test public void testSelectTracksWithNoSampleRenderer() throws ExoPlaybackException { DefaultTrackSelector trackSelector = new DefaultTrackSelector(); + trackSelector.init(invalidationListener, bandwidthMeter); TrackSelectorResult result = trackSelector.selectTracks(RENDERER_CAPABILITIES_WITH_NO_SAMPLE_RENDERER, TRACK_GROUPS); assertTrackSelections(result, TRACK_SELECTIONS_WITH_NO_SAMPLE_RENDERER); @@ -271,6 +280,7 @@ public final class DefaultTrackSelectorTest { @Test public void testSelectTracksWithDisabledNoSampleRenderer() throws ExoPlaybackException { DefaultTrackSelector trackSelector = new DefaultTrackSelector(); + trackSelector.init(invalidationListener, bandwidthMeter); trackSelector.setParameters(trackSelector.buildUponParameters().setRendererDisabled(1, true)); TrackSelectorResult result = trackSelector.selectTracks(RENDERER_CAPABILITIES_WITH_NO_SAMPLE_RENDERER, TRACK_GROUPS); @@ -357,9 +367,10 @@ public final class DefaultTrackSelectorTest { Format.createAudioSampleFormat("audio", MimeTypes.AUDIO_AAC, null, Format.NO_VALUE, Format.NO_VALUE, 2, 44100, null, null, 0, "eng"); - TrackSelectorResult result = trackSelector.selectTracks( - new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES}, - singleTrackGroup(frAudioFormat, enAudioFormat)); + TrackSelectorResult result = + trackSelector.selectTracks( + new RendererCapabilities[] {ALL_AUDIO_FORMAT_SUPPORTED_RENDERER_CAPABILITIES}, + wrapFormats(frAudioFormat, enAudioFormat)); assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(enAudioFormat); } @@ -933,8 +944,6 @@ public final class DefaultTrackSelectorTest { .thenReturn(adaptiveTrackSelection); trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory); - - BandwidthMeter bandwidthMeter = mock(BandwidthMeter.class); trackSelector.init(invalidationListener, bandwidthMeter); TrackGroupArray trackGroupArray = singleTrackGroup(AUDIO_FORMAT, AUDIO_FORMAT); @@ -957,8 +966,6 @@ public final class DefaultTrackSelectorTest { .thenReturn(adaptiveTrackSelection); trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory); - - BandwidthMeter bandwidthMeter = mock(BandwidthMeter.class); trackSelector.init(invalidationListener, bandwidthMeter); TrackGroupArray trackGroupArray = singleTrackGroup(AUDIO_FORMAT, AUDIO_FORMAT, AUDIO_FORMAT); @@ -988,8 +995,6 @@ public final class DefaultTrackSelectorTest { .thenReturn(adaptiveTrackSelection); trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory); - - BandwidthMeter bandwidthMeter = mock(BandwidthMeter.class); trackSelector.init(invalidationListener, bandwidthMeter); TrackGroupArray trackGroupArray = singleTrackGroup(VIDEO_FORMAT, VIDEO_FORMAT); @@ -1012,8 +1017,6 @@ public final class DefaultTrackSelectorTest { .thenReturn(adaptiveTrackSelection); trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory); - - BandwidthMeter bandwidthMeter = mock(BandwidthMeter.class); trackSelector.init(invalidationListener, bandwidthMeter); TrackGroupArray trackGroupArray = singleTrackGroup(VIDEO_FORMAT, VIDEO_FORMAT, VIDEO_FORMAT); diff --git a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectorTest.java b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectorTest.java index 7fb910e18a..615f680bb5 100644 --- a/library/core/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectorTest.java +++ b/library/core/src/test/java/com/google/android/exoplayer2/trackselection/TrackSelectorTest.java @@ -16,6 +16,7 @@ package com.google.android.exoplayer2.trackselection; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.fail; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.RendererCapabilities; @@ -49,8 +50,13 @@ public class TrackSelectorTest { } @Test - public void getBandwidthMeter_beforeInitialization_returnsNull() { - assertThat(trackSelector.getBandwidthMeter()).isNull(); + public void getBandwidthMeter_beforeInitialization_throwsException() { + try { + trackSelector.getBandwidthMeter(); + fail(); + } catch (Exception e) { + // Expected. + } } @Test