mirror of
https://github.com/androidx/media.git
synced 2025-05-07 15:40:37 +08:00
Allow passing BandwidthMeter to TrackSelector and TrackSelection.Factory.
This enabled the player to specify the bandwidth meter after the track selector and the track selection factory have been created. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=199286400
This commit is contained in:
parent
23afdd6f66
commit
1773708fe4
@ -15,6 +15,8 @@
|
||||
* Add support for lazy preparation of playlist media sources in
|
||||
`ConcatenatingMediaSource`
|
||||
([#3972](https://github.com/google/ExoPlayer/issues/3972)).
|
||||
* Pass `BandwidthMeter` to `TrackSelection.Factory` which can be used to obtain
|
||||
bandwidth estimates in the future. Always null at the moment.
|
||||
* HLS:
|
||||
* Allow injection of custom playlist trackers.
|
||||
* Add method to `BandwidthMeter` to return the `TransferListener` used to gather
|
||||
|
@ -162,7 +162,7 @@ import java.util.Collections;
|
||||
enabledRenderers = new Renderer[0];
|
||||
window = new Timeline.Window();
|
||||
period = new Timeline.Period();
|
||||
trackSelector.init(this);
|
||||
trackSelector.init(/* listener= */ this, /* bandwidthMeter= */ null);
|
||||
|
||||
// Note: The documentation for Process.THREAD_PRIORITY_AUDIO that states "Applications can
|
||||
// not normally change to this priority" is incorrect.
|
||||
|
@ -21,6 +21,7 @@ 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;
|
||||
@ -137,11 +138,15 @@ public class AdaptiveTrackSelection extends BaseTrackSelection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdaptiveTrackSelection createTrackSelection(TrackGroup group, int... tracks) {
|
||||
public AdaptiveTrackSelection createTrackSelection(
|
||||
TrackGroup group, @Nullable BandwidthMeter bandwidthMeter, int... tracks) {
|
||||
if (this.bandwidthMeter != null) {
|
||||
bandwidthMeter = this.bandwidthMeter;
|
||||
}
|
||||
return new AdaptiveTrackSelection(
|
||||
group,
|
||||
tracks,
|
||||
bandwidthMeter,
|
||||
Assertions.checkNotNull(bandwidthMeter),
|
||||
minDurationForQualityIncreaseMs,
|
||||
maxDurationForQualityDecreaseMs,
|
||||
minDurationToRetainAfterDiscardMs,
|
||||
|
@ -1206,7 +1206,9 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
||||
rendererTrackSelections[i] =
|
||||
Assertions.checkNotNull(adaptiveTrackSelectionFactory)
|
||||
.createTrackSelection(
|
||||
rendererTrackGroups.get(override.groupIndex), override.tracks);
|
||||
rendererTrackGroups.get(override.groupIndex),
|
||||
getBandwidthMeter(),
|
||||
override.tracks);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1352,7 +1354,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
||||
formatSupports,
|
||||
mixedMimeTypeAdaptationSupports,
|
||||
params,
|
||||
adaptiveTrackSelectionFactory);
|
||||
adaptiveTrackSelectionFactory,
|
||||
getBandwidthMeter());
|
||||
}
|
||||
if (selection == null) {
|
||||
selection = selectFixedVideoTrack(groups, formatSupports, params);
|
||||
@ -1365,7 +1368,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
||||
int[][] formatSupport,
|
||||
int mixedMimeTypeAdaptationSupports,
|
||||
Parameters params,
|
||||
TrackSelection.Factory adaptiveTrackSelectionFactory)
|
||||
TrackSelection.Factory adaptiveTrackSelectionFactory,
|
||||
@Nullable BandwidthMeter bandwidthMeter)
|
||||
throws ExoPlaybackException {
|
||||
int requiredAdaptiveSupport = params.allowNonSeamlessAdaptiveness
|
||||
? (RendererCapabilities.ADAPTIVE_NOT_SEAMLESS | RendererCapabilities.ADAPTIVE_SEAMLESS)
|
||||
@ -1381,7 +1385,7 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
||||
params.viewportOrientationMayChange);
|
||||
if (adaptiveTracks.length > 0) {
|
||||
return Assertions.checkNotNull(adaptiveTrackSelectionFactory)
|
||||
.createTrackSelection(group, adaptiveTracks);
|
||||
.createTrackSelection(group, bandwidthMeter, adaptiveTracks);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -1600,8 +1604,8 @@ public class DefaultTrackSelector extends MappingTrackSelector {
|
||||
getAdaptiveAudioTracks(
|
||||
selectedGroup, formatSupports[selectedGroupIndex], params.allowMixedMimeAdaptiveness);
|
||||
if (adaptiveTracks.length > 0) {
|
||||
return adaptiveTrackSelectionFactory.createTrackSelection(selectedGroup,
|
||||
adaptiveTracks);
|
||||
return adaptiveTrackSelectionFactory
|
||||
.createTrackSelection(selectedGroup, getBandwidthMeter(), adaptiveTracks);
|
||||
}
|
||||
}
|
||||
return new FixedTrackSelection(selectedGroup, selectedTrackIndex);
|
||||
|
@ -18,6 +18,7 @@ package com.google.android.exoplayer2.trackselection;
|
||||
import android.support.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.source.TrackGroup;
|
||||
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
|
||||
/**
|
||||
@ -48,7 +49,8 @@ public final class FixedTrackSelection extends BaseTrackSelection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FixedTrackSelection createTrackSelection(TrackGroup group, int... tracks) {
|
||||
public FixedTrackSelection createTrackSelection(
|
||||
TrackGroup group, @Nullable BandwidthMeter bandwidthMeter, int... tracks) {
|
||||
Assertions.checkArgument(tracks.length == 1);
|
||||
return new FixedTrackSelection(group, tracks[0], reason, data);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import android.os.SystemClock;
|
||||
import android.support.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.source.TrackGroup;
|
||||
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
@ -45,7 +46,8 @@ public final class RandomTrackSelection extends BaseTrackSelection {
|
||||
}
|
||||
|
||||
@Override
|
||||
public RandomTrackSelection createTrackSelection(TrackGroup group, int... tracks) {
|
||||
public RandomTrackSelection createTrackSelection(
|
||||
TrackGroup group, @Nullable BandwidthMeter bandwidthMeter, int... tracks) {
|
||||
return new RandomTrackSelection(group, tracks, random);
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import com.google.android.exoplayer2.C;
|
||||
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 java.util.List;
|
||||
|
||||
/**
|
||||
@ -36,16 +37,29 @@ 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 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.
|
||||
*/
|
||||
TrackSelection createTrackSelection(TrackGroup group, int... tracks);
|
||||
|
||||
default TrackSelection createTrackSelection(
|
||||
TrackGroup group, @Nullable BandwidthMeter bandwidthMeter, int... tracks) {
|
||||
return createTrackSelection(group, tracks);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,6 +22,7 @@ import com.google.android.exoplayer2.Renderer;
|
||||
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;
|
||||
|
||||
/**
|
||||
* The component of an {@link ExoPlayer} responsible for selecting tracks to be consumed by each of
|
||||
@ -29,48 +30,52 @@ import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||
* suitable for most use cases.
|
||||
*
|
||||
* <h3>Interactions with the player</h3>
|
||||
*
|
||||
* The following interactions occur between the player and its track selector during playback.
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>When the player is created it will initialize the track selector by calling
|
||||
* {@link #init(InvalidationListener)}.</li>
|
||||
* <li>When the player needs to make a track selection it will call
|
||||
* {@link #selectTracks(RendererCapabilities[], TrackGroupArray)}. This typically occurs at the
|
||||
* start of playback, when the player starts to buffer a new period of the media being played,
|
||||
* and when the track selector invalidates its previous selections.</li>
|
||||
* <li>The player may perform a track selection well in advance of the selected tracks becoming
|
||||
* active, where active is defined to mean that the renderers are actually consuming media
|
||||
* corresponding to the selection that was made. For example when playing media containing
|
||||
* multiple periods, the track selection for a period is made when the player starts to buffer
|
||||
* that period. Hence if the player's buffering policy is to maintain a 30 second buffer, the
|
||||
* selection will occur approximately 30 seconds in advance of it becoming active. In fact the
|
||||
* selection may never become active, for example if the user seeks to some other period of the
|
||||
* media during the 30 second gap. The player indicates to the track selector when a selection
|
||||
* it has previously made becomes active by calling {@link #onSelectionActivated(Object)}.</li>
|
||||
* <li>If the track selector wishes to indicate to the player that selections it has previously
|
||||
* made are invalid, it can do so by calling
|
||||
* {@link InvalidationListener#onTrackSelectionsInvalidated()} on the
|
||||
* {@link InvalidationListener} that was passed to {@link #init(InvalidationListener)}. A
|
||||
* track selector may wish to do this if its configuration has changed, for example if it now
|
||||
* wishes to prefer audio tracks in a particular language. This will trigger the player to make
|
||||
* new track selections. Note that the player will have to re-buffer in the case that the new
|
||||
* track selection for the currently playing period differs from the one that was invalidated.
|
||||
* </li>
|
||||
* <li>When the player is created it will initialize the track selector by calling {@link
|
||||
* #init(InvalidationListener, BandwidthMeter)}.
|
||||
* <li>When the player needs to make a track selection it will call {@link
|
||||
* #selectTracks(RendererCapabilities[], TrackGroupArray)}. This typically occurs at the start
|
||||
* of playback, when the player starts to buffer a new period of the media being played, and
|
||||
* when the track selector invalidates its previous selections.
|
||||
* <li>The player may perform a track selection well in advance of the selected tracks becoming
|
||||
* active, where active is defined to mean that the renderers are actually consuming media
|
||||
* corresponding to the selection that was made. For example when playing media containing
|
||||
* multiple periods, the track selection for a period is made when the player starts to buffer
|
||||
* that period. Hence if the player's buffering policy is to maintain a 30 second buffer, the
|
||||
* selection will occur approximately 30 seconds in advance of it becoming active. In fact the
|
||||
* selection may never become active, for example if the user seeks to some other period of
|
||||
* the media during the 30 second gap. The player indicates to the track selector when a
|
||||
* selection it has previously made becomes active by calling {@link
|
||||
* #onSelectionActivated(Object)}.
|
||||
* <li>If the track selector wishes to indicate to the player that selections it has previously
|
||||
* made are invalid, it can do so by calling {@link
|
||||
* InvalidationListener#onTrackSelectionsInvalidated()} on the {@link InvalidationListener}
|
||||
* that was passed to {@link #init(InvalidationListener, BandwidthMeter)}. A track selector
|
||||
* may wish to do this if its configuration has changed, for example if it now wishes to
|
||||
* prefer audio tracks in a particular language. This will trigger the player to make new
|
||||
* track selections. Note that the player will have to re-buffer in the case that the new
|
||||
* track selection for the currently playing period differs from the one that was invalidated.
|
||||
* </ul>
|
||||
*
|
||||
* <h3>Renderer configuration</h3>
|
||||
* The {@link TrackSelectorResult} returned by
|
||||
* {@link #selectTracks(RendererCapabilities[], TrackGroupArray)} contains not only
|
||||
* {@link TrackSelection}s for each renderer, but also {@link RendererConfiguration}s defining
|
||||
* configuration parameters that the renderers should apply when consuming the corresponding media.
|
||||
* Whilst it may seem counter-intuitive for a track selector to also specify renderer configuration
|
||||
* information, in practice the two are tightly bound together. It may only be possible to play a
|
||||
* certain combination tracks if the renderers are configured in a particular way. Equally, it may
|
||||
* only be possible to configure renderers in a particular way if certain tracks are selected. Hence
|
||||
* it makes sense to determined the track selection and corresponding renderer configurations in a
|
||||
* single step.
|
||||
*
|
||||
* The {@link TrackSelectorResult} returned by {@link #selectTracks(RendererCapabilities[],
|
||||
* TrackGroupArray)} contains not only {@link TrackSelection}s for each renderer, but also {@link
|
||||
* RendererConfiguration}s defining configuration parameters that the renderers should apply when
|
||||
* consuming the corresponding media. Whilst it may seem counter-intuitive for a track selector to
|
||||
* also specify renderer configuration information, in practice the two are tightly bound together.
|
||||
* It may only be possible to play a certain combination tracks if the renderers are configured in a
|
||||
* particular way. Equally, it may only be possible to configure renderers in a particular way if
|
||||
* certain tracks are selected. Hence it makes sense to determined the track selection and
|
||||
* corresponding renderer configurations in a single step.
|
||||
*
|
||||
* <h3>Threading model</h3>
|
||||
*
|
||||
* All calls made by the player into the track selector are on the player's internal playback
|
||||
* thread. The track selector may call {@link InvalidationListener#onTrackSelectionsInvalidated()}
|
||||
* from any thread.
|
||||
@ -91,15 +96,19 @@ public abstract class TrackSelector {
|
||||
}
|
||||
|
||||
private @Nullable InvalidationListener listener;
|
||||
private @Nullable BandwidthMeter bandwidthMeter;
|
||||
|
||||
/**
|
||||
* Called by the player to initialize the selector.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
public final void init(InvalidationListener listener) {
|
||||
public final void init(InvalidationListener listener, @Nullable BandwidthMeter bandwidthMeter) {
|
||||
this.listener = listener;
|
||||
this.bandwidthMeter = bandwidthMeter;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -132,4 +141,11 @@ 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.
|
||||
*/
|
||||
protected final @Nullable BandwidthMeter getBandwidthMeter() {
|
||||
return bandwidthMeter;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,10 @@
|
||||
package com.google.android.exoplayer2.trackselection;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
@ -54,6 +58,23 @@ public final class AdaptiveTrackSelectionTest {
|
||||
fakeClock = new FakeClock(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFactoryUsesInitiallyProvidedBandwidthMeter() {
|
||||
BandwidthMeter initialBandwidthMeter = mock(BandwidthMeter.class);
|
||||
BandwidthMeter injectedBandwidthMeter = mock(BandwidthMeter.class);
|
||||
Format format = videoFormat(/* bitrate= */ 500, /* width= */ 320, /* height= */ 240);
|
||||
AdaptiveTrackSelection adaptiveTrackSelection =
|
||||
new AdaptiveTrackSelection.Factory(initialBandwidthMeter)
|
||||
.createTrackSelection(new TrackGroup(format), injectedBandwidthMeter, /* tracks= */ 0);
|
||||
adaptiveTrackSelection.updateSelectedTrack(
|
||||
/* playbackPositionUs= */ 0,
|
||||
/* bufferedDurationUs= */ 0,
|
||||
/* availableDurationUs= */ C.TIME_UNSET);
|
||||
|
||||
verify(initialBandwidthMeter, atLeastOnce()).getBitrateEstimate();
|
||||
verifyZeroInteractions(injectedBandwidthMeter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectInitialIndexUseMaxInitialBitrateIfNoBandwidthEstimate() {
|
||||
Format format1 = videoFormat(/* bitrate= */ 500, /* width= */ 320, /* height= */ 240);
|
||||
|
@ -19,9 +19,13 @@ import static com.google.android.exoplayer2.RendererCapabilities.FORMAT_EXCEEDS_
|
||||
import static com.google.android.exoplayer2.RendererCapabilities.FORMAT_HANDLED;
|
||||
import static com.google.android.exoplayer2.RendererConfiguration.DEFAULT;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyVararg;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
import android.os.Parcel;
|
||||
@ -38,6 +42,7 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.Paramet
|
||||
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.ParametersBuilder;
|
||||
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector.SelectionOverride;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelector.InvalidationListener;
|
||||
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||
import com.google.android.exoplayer2.util.MimeTypes;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -71,33 +76,33 @@ public final class DefaultTrackSelectorTest {
|
||||
private static final RendererCapabilities[] RENDERER_CAPABILITIES_WITH_NO_SAMPLE_RENDERER =
|
||||
new RendererCapabilities[] {VIDEO_CAPABILITIES, NO_SAMPLE_CAPABILITIES};
|
||||
|
||||
private static final TrackGroup VIDEO_TRACK_GROUP =
|
||||
new TrackGroup(
|
||||
Format.createVideoSampleFormat(
|
||||
"video",
|
||||
MimeTypes.VIDEO_H264,
|
||||
null,
|
||||
Format.NO_VALUE,
|
||||
Format.NO_VALUE,
|
||||
1024,
|
||||
768,
|
||||
Format.NO_VALUE,
|
||||
null,
|
||||
null));
|
||||
private static final TrackGroup AUDIO_TRACK_GROUP =
|
||||
new TrackGroup(
|
||||
Format.createAudioSampleFormat(
|
||||
"audio",
|
||||
MimeTypes.AUDIO_AAC,
|
||||
null,
|
||||
Format.NO_VALUE,
|
||||
Format.NO_VALUE,
|
||||
2,
|
||||
44100,
|
||||
null,
|
||||
null,
|
||||
0,
|
||||
null));
|
||||
private static final Format VIDEO_FORMAT =
|
||||
Format.createVideoSampleFormat(
|
||||
"video",
|
||||
MimeTypes.VIDEO_H264,
|
||||
null,
|
||||
Format.NO_VALUE,
|
||||
Format.NO_VALUE,
|
||||
1024,
|
||||
768,
|
||||
Format.NO_VALUE,
|
||||
null,
|
||||
null);
|
||||
private static final Format AUDIO_FORMAT =
|
||||
Format.createAudioSampleFormat(
|
||||
"audio",
|
||||
MimeTypes.AUDIO_AAC,
|
||||
null,
|
||||
Format.NO_VALUE,
|
||||
Format.NO_VALUE,
|
||||
2,
|
||||
44100,
|
||||
null,
|
||||
null,
|
||||
0,
|
||||
null);
|
||||
private static final TrackGroup VIDEO_TRACK_GROUP = new TrackGroup(VIDEO_FORMAT);
|
||||
private static final TrackGroup AUDIO_TRACK_GROUP = new TrackGroup(AUDIO_FORMAT);
|
||||
private static final TrackGroupArray TRACK_GROUPS =
|
||||
new TrackGroupArray(VIDEO_TRACK_GROUP, AUDIO_TRACK_GROUP);
|
||||
|
||||
@ -282,7 +287,7 @@ public final class DefaultTrackSelectorTest {
|
||||
@Test
|
||||
public void testSetParameterWithDefaultParametersDoesNotNotifyInvalidationListener()
|
||||
throws Exception {
|
||||
trackSelector.init(invalidationListener);
|
||||
trackSelector.init(invalidationListener, /* bandwidthMeter= */ null);
|
||||
|
||||
verify(invalidationListener, never()).onTrackSelectionsInvalidated();
|
||||
}
|
||||
@ -295,7 +300,7 @@ public final class DefaultTrackSelectorTest {
|
||||
public void testSetParameterWithNonDefaultParameterNotifyInvalidationListener()
|
||||
throws Exception {
|
||||
Parameters parameters = new ParametersBuilder().setPreferredAudioLanguage("eng").build();
|
||||
trackSelector.init(invalidationListener);
|
||||
trackSelector.init(invalidationListener, /* bandwidthMeter= */ null);
|
||||
trackSelector.setParameters(parameters);
|
||||
|
||||
verify(invalidationListener).onTrackSelectionsInvalidated();
|
||||
@ -310,7 +315,7 @@ public final class DefaultTrackSelectorTest {
|
||||
public void testSetParameterWithSameParametersDoesNotNotifyInvalidationListenerAgain()
|
||||
throws Exception {
|
||||
ParametersBuilder builder = new ParametersBuilder().setPreferredAudioLanguage("eng");
|
||||
trackSelector.init(invalidationListener);
|
||||
trackSelector.init(invalidationListener, /* bandwidthMeter= */ null);
|
||||
trackSelector.setParameters(builder.build());
|
||||
trackSelector.setParameters(builder.build());
|
||||
|
||||
@ -956,6 +961,116 @@ public final class DefaultTrackSelectorTest {
|
||||
assertThat(result.selections.get(0).getSelectedFormat()).isEqualTo(lowerBitrateFormat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectTracksWithMultipleAudioTracksReturnsAdaptiveTrackSelection()
|
||||
throws Exception {
|
||||
TrackSelection adaptiveTrackSelection = mock(TrackSelection.class);
|
||||
TrackSelection.Factory adaptiveTrackSelectionFactory = mock(TrackSelection.Factory.class);
|
||||
when(adaptiveTrackSelectionFactory.createTrackSelection(any(), any(), anyVararg()))
|
||||
.thenReturn(adaptiveTrackSelection);
|
||||
|
||||
trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory);
|
||||
|
||||
BandwidthMeter bandwidthMeter = mock(BandwidthMeter.class);
|
||||
trackSelector.init(invalidationListener, bandwidthMeter);
|
||||
|
||||
TrackGroupArray trackGroupArray = singleTrackGroup(AUDIO_FORMAT, AUDIO_FORMAT);
|
||||
TrackSelectorResult result =
|
||||
trackSelector.selectTracks(
|
||||
new RendererCapabilities[] {AUDIO_CAPABILITIES}, trackGroupArray);
|
||||
|
||||
assertThat(result.length).isEqualTo(1);
|
||||
assertThat(result.selections.get(0)).isEqualTo(adaptiveTrackSelection);
|
||||
verify(adaptiveTrackSelectionFactory)
|
||||
.createTrackSelection(trackGroupArray.get(0), bandwidthMeter, 0, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectTracksWithMultipleAudioTracksOverrideReturnsAdaptiveTrackSelection()
|
||||
throws Exception {
|
||||
TrackSelection adaptiveTrackSelection = mock(TrackSelection.class);
|
||||
TrackSelection.Factory adaptiveTrackSelectionFactory = mock(TrackSelection.Factory.class);
|
||||
when(adaptiveTrackSelectionFactory.createTrackSelection(any(), any(), anyVararg()))
|
||||
.thenReturn(adaptiveTrackSelection);
|
||||
|
||||
trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory);
|
||||
|
||||
BandwidthMeter bandwidthMeter = mock(BandwidthMeter.class);
|
||||
trackSelector.init(invalidationListener, bandwidthMeter);
|
||||
|
||||
TrackGroupArray trackGroupArray = singleTrackGroup(AUDIO_FORMAT, AUDIO_FORMAT, AUDIO_FORMAT);
|
||||
trackSelector.setParameters(
|
||||
trackSelector
|
||||
.buildUponParameters()
|
||||
.setSelectionOverride(
|
||||
/* rendererIndex= */ 0,
|
||||
trackGroupArray,
|
||||
new SelectionOverride(/* groupIndex= */ 0, /* tracks= */ 1, 2)));
|
||||
TrackSelectorResult result =
|
||||
trackSelector.selectTracks(
|
||||
new RendererCapabilities[] {AUDIO_CAPABILITIES}, trackGroupArray);
|
||||
|
||||
assertThat(result.length).isEqualTo(1);
|
||||
assertThat(result.selections.get(0)).isEqualTo(adaptiveTrackSelection);
|
||||
verify(adaptiveTrackSelectionFactory)
|
||||
.createTrackSelection(trackGroupArray.get(0), bandwidthMeter, 1, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectTracksWithMultipleVideoTracksReturnsAdaptiveTrackSelection()
|
||||
throws Exception {
|
||||
TrackSelection adaptiveTrackSelection = mock(TrackSelection.class);
|
||||
TrackSelection.Factory adaptiveTrackSelectionFactory = mock(TrackSelection.Factory.class);
|
||||
when(adaptiveTrackSelectionFactory.createTrackSelection(any(), any(), anyVararg()))
|
||||
.thenReturn(adaptiveTrackSelection);
|
||||
|
||||
trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory);
|
||||
|
||||
BandwidthMeter bandwidthMeter = mock(BandwidthMeter.class);
|
||||
trackSelector.init(invalidationListener, bandwidthMeter);
|
||||
|
||||
TrackGroupArray trackGroupArray = singleTrackGroup(VIDEO_FORMAT, VIDEO_FORMAT);
|
||||
TrackSelectorResult result =
|
||||
trackSelector.selectTracks(
|
||||
new RendererCapabilities[] {VIDEO_CAPABILITIES}, trackGroupArray);
|
||||
|
||||
assertThat(result.length).isEqualTo(1);
|
||||
assertThat(result.selections.get(0)).isEqualTo(adaptiveTrackSelection);
|
||||
verify(adaptiveTrackSelectionFactory)
|
||||
.createTrackSelection(trackGroupArray.get(0), bandwidthMeter, 0, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelectTracksWithMultipleVideoTracksOverrideReturnsAdaptiveTrackSelection()
|
||||
throws Exception {
|
||||
TrackSelection adaptiveTrackSelection = mock(TrackSelection.class);
|
||||
TrackSelection.Factory adaptiveTrackSelectionFactory = mock(TrackSelection.Factory.class);
|
||||
when(adaptiveTrackSelectionFactory.createTrackSelection(any(), any(), anyVararg()))
|
||||
.thenReturn(adaptiveTrackSelection);
|
||||
|
||||
trackSelector = new DefaultTrackSelector(adaptiveTrackSelectionFactory);
|
||||
|
||||
BandwidthMeter bandwidthMeter = mock(BandwidthMeter.class);
|
||||
trackSelector.init(invalidationListener, bandwidthMeter);
|
||||
|
||||
TrackGroupArray trackGroupArray = singleTrackGroup(VIDEO_FORMAT, VIDEO_FORMAT, VIDEO_FORMAT);
|
||||
trackSelector.setParameters(
|
||||
trackSelector
|
||||
.buildUponParameters()
|
||||
.setSelectionOverride(
|
||||
/* rendererIndex= */ 0,
|
||||
trackGroupArray,
|
||||
new SelectionOverride(/* groupIndex= */ 0, /* tracks= */ 1, 2)));
|
||||
TrackSelectorResult result =
|
||||
trackSelector.selectTracks(
|
||||
new RendererCapabilities[] {VIDEO_CAPABILITIES}, trackGroupArray);
|
||||
|
||||
assertThat(result.length).isEqualTo(1);
|
||||
assertThat(result.selections.get(0)).isEqualTo(adaptiveTrackSelection);
|
||||
verify(adaptiveTrackSelectionFactory)
|
||||
.createTrackSelection(trackGroupArray.get(0), bandwidthMeter, 1, 2);
|
||||
}
|
||||
|
||||
private static void assertTrackSelections(TrackSelectorResult result, TrackSelection[] expected) {
|
||||
assertThat(result.length).isEqualTo(expected.length);
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.exoplayer2.trackselection;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||
import com.google.android.exoplayer2.RendererCapabilities;
|
||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||
import com.google.android.exoplayer2.trackselection.TrackSelector.InvalidationListener;
|
||||
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
/** Unit test for {@link TrackSelector}. */
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class TrackSelectorTest {
|
||||
|
||||
private TrackSelector trackSelector;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
trackSelector = new TrackSelector() {
|
||||
@Override
|
||||
public TrackSelectorResult selectTracks(RendererCapabilities[] rendererCapabilities,
|
||||
TrackGroupArray trackGroups) throws ExoPlaybackException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectionActivated(Object info) {}
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBandwidthMeter_beforeInitialization_returnsNull() {
|
||||
assertThat(trackSelector.getBandwidthMeter()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBandwidthMeter_afterInitialization_returnsProvidedBandwidthMeter() {
|
||||
InvalidationListener invalidationListener = Mockito.mock(InvalidationListener.class);
|
||||
BandwidthMeter bandwidthMeter = Mockito.mock(BandwidthMeter.class);
|
||||
trackSelector.init(invalidationListener, bandwidthMeter);
|
||||
|
||||
assertThat(trackSelector.getBandwidthMeter()).isEqualTo(bandwidthMeter);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user