parent
516d4ce1fd
commit
fad3257072
@ -82,6 +82,10 @@
|
|||||||
if playback is ongoing or stops the service otherwise.
|
if playback is ongoing or stops the service otherwise.
|
||||||
* UI:
|
* UI:
|
||||||
* Downloads:
|
* Downloads:
|
||||||
|
* Ensure that `DownloadHelper` doesn't leak unreleased `Renderer`
|
||||||
|
instances, which can eventually result in an app crashing with
|
||||||
|
`IllegalStateException: Too many receivers, total of 1000, registered
|
||||||
|
for pid` ([#1224](https://github.com/androidx/media/issues/1224)).
|
||||||
* OkHttp Extension:
|
* OkHttp Extension:
|
||||||
* Cronet Extension:
|
* Cronet Extension:
|
||||||
* RTMP Extension:
|
* RTMP Extension:
|
||||||
|
@ -57,7 +57,7 @@ public final class DefaultRendererCapabilitiesList implements RendererCapabiliti
|
|||||||
public DefaultRendererCapabilitiesList createRendererCapabilitiesList() {
|
public DefaultRendererCapabilitiesList createRendererCapabilitiesList() {
|
||||||
Renderer[] renderers =
|
Renderer[] renderers =
|
||||||
renderersFactory.createRenderers(
|
renderersFactory.createRenderers(
|
||||||
Util.createHandlerForCurrentLooper(),
|
Util.createHandlerForCurrentOrMainLooper(),
|
||||||
new VideoRendererEventListener() {},
|
new VideoRendererEventListener() {},
|
||||||
new AudioRendererEventListener() {},
|
new AudioRendererEventListener() {},
|
||||||
cueGroup -> {},
|
cueGroup -> {},
|
||||||
@ -84,6 +84,11 @@ public final class DefaultRendererCapabilitiesList implements RendererCapabiliti
|
|||||||
return rendererCapabilities;
|
return rendererCapabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return renderers.length;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void release() {
|
public void release() {
|
||||||
for (Renderer renderer : renderers) {
|
for (Renderer renderer : renderers) {
|
||||||
|
@ -31,6 +31,9 @@ public interface RendererCapabilitiesList {
|
|||||||
/** Returns an array of {@link RendererCapabilities}. */
|
/** Returns an array of {@link RendererCapabilities}. */
|
||||||
RendererCapabilities[] getRendererCapabilities();
|
RendererCapabilities[] getRendererCapabilities();
|
||||||
|
|
||||||
|
/** Returns the number of {@link RendererCapabilities}. */
|
||||||
|
int size();
|
||||||
|
|
||||||
/** Releases any resources associated with this {@link RendererCapabilitiesList}. */
|
/** Releases any resources associated with this {@link RendererCapabilitiesList}. */
|
||||||
void release();
|
void release();
|
||||||
}
|
}
|
||||||
|
@ -38,10 +38,12 @@ import androidx.media3.common.util.UnstableApi;
|
|||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.datasource.DataSource;
|
import androidx.media3.datasource.DataSource;
|
||||||
import androidx.media3.datasource.TransferListener;
|
import androidx.media3.datasource.TransferListener;
|
||||||
|
import androidx.media3.exoplayer.DefaultRendererCapabilitiesList;
|
||||||
import androidx.media3.exoplayer.ExoPlaybackException;
|
import androidx.media3.exoplayer.ExoPlaybackException;
|
||||||
import androidx.media3.exoplayer.LoadingInfo;
|
import androidx.media3.exoplayer.LoadingInfo;
|
||||||
import androidx.media3.exoplayer.Renderer;
|
import androidx.media3.exoplayer.Renderer;
|
||||||
import androidx.media3.exoplayer.RendererCapabilities;
|
import androidx.media3.exoplayer.RendererCapabilities;
|
||||||
|
import androidx.media3.exoplayer.RendererCapabilitiesList;
|
||||||
import androidx.media3.exoplayer.RenderersFactory;
|
import androidx.media3.exoplayer.RenderersFactory;
|
||||||
import androidx.media3.exoplayer.analytics.PlayerId;
|
import androidx.media3.exoplayer.analytics.PlayerId;
|
||||||
import androidx.media3.exoplayer.audio.AudioRendererEventListener;
|
import androidx.media3.exoplayer.audio.AudioRendererEventListener;
|
||||||
@ -144,12 +146,12 @@ public final class DownloadHelper {
|
|||||||
public static class LiveContentUnsupportedException extends IOException {}
|
public static class LiveContentUnsupportedException extends IOException {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts renderer capabilities for the renderers created by the provided renderers factory.
|
* @deprecated This method leaks un-released {@link Renderer} instances. There is no direct
|
||||||
*
|
* replacement. Equivalent functionality can be implemented by constructing the renderer
|
||||||
* @param renderersFactory A {@link RenderersFactory}.
|
* instances, calling {@link Renderer#getCapabilities()} on each one, then releasing the
|
||||||
* @return The {@link RendererCapabilities} for each renderer created by the {@code
|
* renderers when the capabilities are no longer required.
|
||||||
* renderersFactory}.
|
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static RendererCapabilities[] getRendererCapabilities(RenderersFactory renderersFactory) {
|
public static RendererCapabilities[] getRendererCapabilities(RenderersFactory renderersFactory) {
|
||||||
Renderer[] renderers =
|
Renderer[] renderers =
|
||||||
renderersFactory.createRenderers(
|
renderersFactory.createRenderers(
|
||||||
@ -274,8 +276,9 @@ public final class DownloadHelper {
|
|||||||
mediaItem, castNonNull(dataSourceFactory), drmSessionManager),
|
mediaItem, castNonNull(dataSourceFactory), drmSessionManager),
|
||||||
trackSelectionParameters,
|
trackSelectionParameters,
|
||||||
renderersFactory != null
|
renderersFactory != null
|
||||||
? getRendererCapabilities(renderersFactory)
|
? new DefaultRendererCapabilitiesList.Factory(renderersFactory)
|
||||||
: new RendererCapabilities[0]);
|
.createRendererCapabilitiesList()
|
||||||
|
: new UnreleaseableRendererCapabilitiesList(new RendererCapabilities[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -308,7 +311,7 @@ public final class DownloadHelper {
|
|||||||
private final MediaItem.LocalConfiguration localConfiguration;
|
private final MediaItem.LocalConfiguration localConfiguration;
|
||||||
@Nullable private final MediaSource mediaSource;
|
@Nullable private final MediaSource mediaSource;
|
||||||
private final DefaultTrackSelector trackSelector;
|
private final DefaultTrackSelector trackSelector;
|
||||||
private final RendererCapabilities[] rendererCapabilities;
|
private final RendererCapabilitiesList rendererCapabilities;
|
||||||
private final SparseIntArray scratchSet;
|
private final SparseIntArray scratchSet;
|
||||||
private final Handler callbackHandler;
|
private final Handler callbackHandler;
|
||||||
private final Timeline.Window window;
|
private final Timeline.Window window;
|
||||||
@ -322,6 +325,26 @@ public final class DownloadHelper {
|
|||||||
private List<ExoTrackSelection> @MonotonicNonNull [][]
|
private List<ExoTrackSelection> @MonotonicNonNull [][]
|
||||||
immutableTrackSelectionsByPeriodAndRenderer;
|
immutableTrackSelectionsByPeriodAndRenderer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated The {@link Renderer} instances used to produce {@code rendererCapabilities} must be
|
||||||
|
* kept alive for the lifetime of this {@code DownloadHelper} instance and then released (to
|
||||||
|
* avoid a resource leak). Use {@link DownloadHelper#DownloadHelper(MediaItem, MediaSource,
|
||||||
|
* TrackSelectionParameters, RendererCapabilitiesList)} instead to avoid needing to manually
|
||||||
|
* manage this bookkeeping.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public DownloadHelper(
|
||||||
|
MediaItem mediaItem,
|
||||||
|
@Nullable MediaSource mediaSource,
|
||||||
|
TrackSelectionParameters trackSelectionParameters,
|
||||||
|
RendererCapabilities[] rendererCapabilities) {
|
||||||
|
this(
|
||||||
|
mediaItem,
|
||||||
|
mediaSource,
|
||||||
|
trackSelectionParameters,
|
||||||
|
new UnreleaseableRendererCapabilitiesList(rendererCapabilities));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates download helper.
|
* Creates download helper.
|
||||||
*
|
*
|
||||||
@ -330,14 +353,14 @@ public final class DownloadHelper {
|
|||||||
* selection needs to be made.
|
* selection needs to be made.
|
||||||
* @param trackSelectionParameters {@link TrackSelectionParameters} for selecting tracks for
|
* @param trackSelectionParameters {@link TrackSelectionParameters} for selecting tracks for
|
||||||
* downloading.
|
* downloading.
|
||||||
* @param rendererCapabilities The {@link RendererCapabilities} of the renderers for which tracks
|
* @param rendererCapabilities The {@link RendererCapabilitiesList} of the renderers for which
|
||||||
* are selected.
|
* tracks are selected.
|
||||||
*/
|
*/
|
||||||
public DownloadHelper(
|
public DownloadHelper(
|
||||||
MediaItem mediaItem,
|
MediaItem mediaItem,
|
||||||
@Nullable MediaSource mediaSource,
|
@Nullable MediaSource mediaSource,
|
||||||
TrackSelectionParameters trackSelectionParameters,
|
TrackSelectionParameters trackSelectionParameters,
|
||||||
RendererCapabilities[] rendererCapabilities) {
|
RendererCapabilitiesList rendererCapabilities) {
|
||||||
this.localConfiguration = checkNotNull(mediaItem.localConfiguration);
|
this.localConfiguration = checkNotNull(mediaItem.localConfiguration);
|
||||||
this.mediaSource = mediaSource;
|
this.mediaSource = mediaSource;
|
||||||
this.trackSelector =
|
this.trackSelector =
|
||||||
@ -371,6 +394,7 @@ public final class DownloadHelper {
|
|||||||
mediaPreparer.release();
|
mediaPreparer.release();
|
||||||
}
|
}
|
||||||
trackSelector.release();
|
trackSelector.release();
|
||||||
|
rendererCapabilities.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -462,7 +486,7 @@ public final class DownloadHelper {
|
|||||||
*/
|
*/
|
||||||
public void clearTrackSelections(int periodIndex) {
|
public void clearTrackSelections(int periodIndex) {
|
||||||
assertPreparedWithMedia();
|
assertPreparedWithMedia();
|
||||||
for (int i = 0; i < rendererCapabilities.length; i++) {
|
for (int i = 0; i < rendererCapabilities.size(); i++) {
|
||||||
trackSelectionsByPeriodAndRenderer[periodIndex][i].clear();
|
trackSelectionsByPeriodAndRenderer[periodIndex][i].clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -521,7 +545,7 @@ public final class DownloadHelper {
|
|||||||
// Prefer highest supported bitrate for downloads.
|
// Prefer highest supported bitrate for downloads.
|
||||||
parametersBuilder.setForceHighestSupportedBitrate(true);
|
parametersBuilder.setForceHighestSupportedBitrate(true);
|
||||||
// Disable all non-audio track types supported by the renderers.
|
// Disable all non-audio track types supported by the renderers.
|
||||||
for (RendererCapabilities capabilities : rendererCapabilities) {
|
for (RendererCapabilities capabilities : rendererCapabilities.getRendererCapabilities()) {
|
||||||
@C.TrackType int trackType = capabilities.getTrackType();
|
@C.TrackType int trackType = capabilities.getTrackType();
|
||||||
parametersBuilder.setTrackTypeDisabled(
|
parametersBuilder.setTrackTypeDisabled(
|
||||||
trackType, /* disabled= */ trackType != C.TRACK_TYPE_AUDIO);
|
trackType, /* disabled= */ trackType != C.TRACK_TYPE_AUDIO);
|
||||||
@ -562,7 +586,7 @@ public final class DownloadHelper {
|
|||||||
// Prefer highest supported bitrate for downloads.
|
// Prefer highest supported bitrate for downloads.
|
||||||
parametersBuilder.setForceHighestSupportedBitrate(true);
|
parametersBuilder.setForceHighestSupportedBitrate(true);
|
||||||
// Disable all non-text track types supported by the renderers.
|
// Disable all non-text track types supported by the renderers.
|
||||||
for (RendererCapabilities capabilities : rendererCapabilities) {
|
for (RendererCapabilities capabilities : rendererCapabilities.getRendererCapabilities()) {
|
||||||
@C.TrackType int trackType = capabilities.getTrackType();
|
@C.TrackType int trackType = capabilities.getTrackType();
|
||||||
parametersBuilder.setTrackTypeDisabled(
|
parametersBuilder.setTrackTypeDisabled(
|
||||||
trackType, /* disabled= */ trackType != C.TRACK_TYPE_TEXT);
|
trackType, /* disabled= */ trackType != C.TRACK_TYPE_TEXT);
|
||||||
@ -694,7 +718,7 @@ public final class DownloadHelper {
|
|||||||
checkNotNull(mediaPreparer.mediaPeriods);
|
checkNotNull(mediaPreparer.mediaPeriods);
|
||||||
checkNotNull(mediaPreparer.timeline);
|
checkNotNull(mediaPreparer.timeline);
|
||||||
int periodCount = mediaPreparer.mediaPeriods.length;
|
int periodCount = mediaPreparer.mediaPeriods.length;
|
||||||
int rendererCount = rendererCapabilities.length;
|
int rendererCount = rendererCapabilities.size();
|
||||||
trackSelectionsByPeriodAndRenderer =
|
trackSelectionsByPeriodAndRenderer =
|
||||||
(List<ExoTrackSelection>[][]) new List<?>[periodCount][rendererCount];
|
(List<ExoTrackSelection>[][]) new List<?>[periodCount][rendererCount];
|
||||||
immutableTrackSelectionsByPeriodAndRenderer =
|
immutableTrackSelectionsByPeriodAndRenderer =
|
||||||
@ -762,7 +786,7 @@ public final class DownloadHelper {
|
|||||||
private TrackSelectorResult runTrackSelection(int periodIndex) throws ExoPlaybackException {
|
private TrackSelectorResult runTrackSelection(int periodIndex) throws ExoPlaybackException {
|
||||||
TrackSelectorResult trackSelectorResult =
|
TrackSelectorResult trackSelectorResult =
|
||||||
trackSelector.selectTracks(
|
trackSelector.selectTracks(
|
||||||
rendererCapabilities,
|
rendererCapabilities.getRendererCapabilities(),
|
||||||
trackGroupArrays[periodIndex],
|
trackGroupArrays[periodIndex],
|
||||||
new MediaPeriodId(mediaPreparer.timeline.getUidOfPeriod(periodIndex)),
|
new MediaPeriodId(mediaPreparer.timeline.getUidOfPeriod(periodIndex)),
|
||||||
mediaPreparer.timeline);
|
mediaPreparer.timeline);
|
||||||
@ -1066,4 +1090,27 @@ public final class DownloadHelper {
|
|||||||
// Do nothing.
|
// Do nothing.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final class UnreleaseableRendererCapabilitiesList
|
||||||
|
implements RendererCapabilitiesList {
|
||||||
|
|
||||||
|
private final RendererCapabilities[] rendererCapabilities;
|
||||||
|
|
||||||
|
private UnreleaseableRendererCapabilitiesList(RendererCapabilities[] rendererCapabilities) {
|
||||||
|
this.rendererCapabilities = rendererCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RendererCapabilities[] getRendererCapabilities() {
|
||||||
|
return rendererCapabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return rendererCapabilities.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void release() {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,14 @@ import androidx.media3.common.Timeline;
|
|||||||
import androidx.media3.common.TrackGroup;
|
import androidx.media3.common.TrackGroup;
|
||||||
import androidx.media3.common.TrackSelectionOverride;
|
import androidx.media3.common.TrackSelectionOverride;
|
||||||
import androidx.media3.common.TrackSelectionParameters;
|
import androidx.media3.common.TrackSelectionParameters;
|
||||||
|
import androidx.media3.datasource.DefaultDataSource;
|
||||||
|
import androidx.media3.exoplayer.DefaultRendererCapabilitiesList;
|
||||||
import androidx.media3.exoplayer.Renderer;
|
import androidx.media3.exoplayer.Renderer;
|
||||||
|
import androidx.media3.exoplayer.RendererCapabilities;
|
||||||
|
import androidx.media3.exoplayer.RendererCapabilitiesList;
|
||||||
import androidx.media3.exoplayer.RenderersFactory;
|
import androidx.media3.exoplayer.RenderersFactory;
|
||||||
|
import androidx.media3.exoplayer.drm.DefaultDrmSessionManager;
|
||||||
|
import androidx.media3.exoplayer.drm.HttpMediaDrmCallback;
|
||||||
import androidx.media3.exoplayer.offline.DownloadHelper.Callback;
|
import androidx.media3.exoplayer.offline.DownloadHelper.Callback;
|
||||||
import androidx.media3.exoplayer.source.MediaPeriod;
|
import androidx.media3.exoplayer.source.MediaPeriod;
|
||||||
import androidx.media3.exoplayer.source.MediaSourceEventListener.EventDispatcher;
|
import androidx.media3.exoplayer.source.MediaSourceEventListener.EventDispatcher;
|
||||||
@ -39,6 +45,7 @@ import androidx.media3.exoplayer.trackselection.DefaultTrackSelector;
|
|||||||
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
||||||
import androidx.media3.exoplayer.trackselection.MappingTrackSelector.MappedTrackInfo;
|
import androidx.media3.exoplayer.trackselection.MappingTrackSelector.MappedTrackInfo;
|
||||||
import androidx.media3.exoplayer.upstream.Allocator;
|
import androidx.media3.exoplayer.upstream.Allocator;
|
||||||
|
import androidx.media3.test.utils.FakeDataSource;
|
||||||
import androidx.media3.test.utils.FakeMediaPeriod;
|
import androidx.media3.test.utils.FakeMediaPeriod;
|
||||||
import androidx.media3.test.utils.FakeMediaSource;
|
import androidx.media3.test.utils.FakeMediaSource;
|
||||||
import androidx.media3.test.utils.FakeRenderer;
|
import androidx.media3.test.utils.FakeRenderer;
|
||||||
@ -123,7 +130,8 @@ public class DownloadHelperTest {
|
|||||||
testMediaItem,
|
testMediaItem,
|
||||||
new TestMediaSource(),
|
new TestMediaSource(),
|
||||||
DownloadHelper.DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_CONTEXT,
|
DownloadHelper.DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_CONTEXT,
|
||||||
DownloadHelper.getRendererCapabilities(renderersFactory));
|
new DefaultRendererCapabilitiesList.Factory(renderersFactory)
|
||||||
|
.createRendererCapabilitiesList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -439,6 +447,191 @@ public class DownloadHelperTest {
|
|||||||
new StreamKey(/* periodIndex= */ 0, /* groupIndex= */ 2, /* streamIndex= */ 0));
|
new StreamKey(/* periodIndex= */ 0, /* groupIndex= */ 2, /* streamIndex= */ 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/androidx/media/issues/1224
|
||||||
|
@Test
|
||||||
|
public void prepareThenRelease_renderersReleased() throws Exception {
|
||||||
|
// We can't use this.downloadHelper because we need access to the FakeRenderer instances for
|
||||||
|
// later assertions, so we recreate a local DownloadHelper.
|
||||||
|
FakeRenderer videoRenderer = new FakeRenderer(C.TRACK_TYPE_VIDEO);
|
||||||
|
FakeRenderer audioRenderer = new FakeRenderer(C.TRACK_TYPE_AUDIO);
|
||||||
|
FakeRenderer textRenderer = new FakeRenderer(C.TRACK_TYPE_TEXT);
|
||||||
|
RenderersFactory renderersFactory =
|
||||||
|
(handler, videoListener, audioListener, metadata, text) ->
|
||||||
|
new Renderer[] {textRenderer, audioRenderer, videoRenderer};
|
||||||
|
DownloadHelper downloadHelper =
|
||||||
|
DownloadHelper.forMediaItem(
|
||||||
|
testMediaItem,
|
||||||
|
DownloadHelper.DEFAULT_TRACK_SELECTOR_PARAMETERS_WITHOUT_CONTEXT,
|
||||||
|
renderersFactory,
|
||||||
|
new FakeDataSource.Factory());
|
||||||
|
|
||||||
|
prepareDownloadHelper(downloadHelper);
|
||||||
|
downloadHelper.release();
|
||||||
|
|
||||||
|
assertThat(videoRenderer.isReleased).isTrue();
|
||||||
|
assertThat(audioRenderer.isReleased).isTrue();
|
||||||
|
assertThat(textRenderer.isReleased).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void forMediaItem_mediaItemOnly_worksWithoutLooperThread() throws Exception {
|
||||||
|
AtomicReference<Throwable> exception = new AtomicReference<>();
|
||||||
|
AtomicReference<DownloadHelper> downloadHelper = new AtomicReference<>();
|
||||||
|
Thread thread =
|
||||||
|
new Thread(
|
||||||
|
() -> {
|
||||||
|
try {
|
||||||
|
downloadHelper.set(
|
||||||
|
DownloadHelper.forMediaItem(getApplicationContext(), testMediaItem));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
exception.set(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
thread.start();
|
||||||
|
thread.join();
|
||||||
|
|
||||||
|
assertThat(exception.get()).isNull();
|
||||||
|
assertThat(downloadHelper.get()).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal b/333089854
|
||||||
|
@Test
|
||||||
|
public void forMediaItem_withContext_worksWithoutLooperThread() throws Exception {
|
||||||
|
AtomicReference<Throwable> exception = new AtomicReference<>();
|
||||||
|
AtomicReference<DownloadHelper> downloadHelper = new AtomicReference<>();
|
||||||
|
Thread thread =
|
||||||
|
new Thread(
|
||||||
|
() -> {
|
||||||
|
try {
|
||||||
|
FakeRenderer videoRenderer = new FakeRenderer(C.TRACK_TYPE_VIDEO);
|
||||||
|
RenderersFactory renderersFactory =
|
||||||
|
(handler, videoListener, audioListener, metadata, text) ->
|
||||||
|
new Renderer[] {videoRenderer};
|
||||||
|
downloadHelper.set(
|
||||||
|
DownloadHelper.forMediaItem(
|
||||||
|
getApplicationContext(),
|
||||||
|
testMediaItem,
|
||||||
|
renderersFactory,
|
||||||
|
new FakeDataSource.Factory()));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
exception.set(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
thread.start();
|
||||||
|
thread.join();
|
||||||
|
|
||||||
|
assertThat(exception.get()).isNull();
|
||||||
|
assertThat(downloadHelper.get()).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void forMediaItem_withTrackSelectionParams_worksWithoutLooperThread() throws Exception {
|
||||||
|
AtomicReference<Throwable> exception = new AtomicReference<>();
|
||||||
|
AtomicReference<DownloadHelper> downloadHelper = new AtomicReference<>();
|
||||||
|
Thread thread =
|
||||||
|
new Thread(
|
||||||
|
() -> {
|
||||||
|
try {
|
||||||
|
FakeRenderer videoRenderer = new FakeRenderer(C.TRACK_TYPE_VIDEO);
|
||||||
|
RenderersFactory renderersFactory =
|
||||||
|
(handler, videoListener, audioListener, metadata, text) ->
|
||||||
|
new Renderer[] {videoRenderer};
|
||||||
|
downloadHelper.set(
|
||||||
|
DownloadHelper.forMediaItem(
|
||||||
|
testMediaItem,
|
||||||
|
TrackSelectionParameters.getDefaults(getApplicationContext()),
|
||||||
|
renderersFactory,
|
||||||
|
new FakeDataSource.Factory()));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
exception.set(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
thread.start();
|
||||||
|
thread.join();
|
||||||
|
|
||||||
|
assertThat(exception.get()).isNull();
|
||||||
|
assertThat(downloadHelper.get()).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void forMediaItem_withTrackSelectionParamsAndDrm_worksWithoutLooperThread()
|
||||||
|
throws Exception {
|
||||||
|
AtomicReference<Throwable> exception = new AtomicReference<>();
|
||||||
|
AtomicReference<DownloadHelper> downloadHelper = new AtomicReference<>();
|
||||||
|
Thread thread =
|
||||||
|
new Thread(
|
||||||
|
() -> {
|
||||||
|
try {
|
||||||
|
FakeRenderer videoRenderer = new FakeRenderer(C.TRACK_TYPE_VIDEO);
|
||||||
|
RenderersFactory renderersFactory =
|
||||||
|
(handler, videoListener, audioListener, metadata, text) ->
|
||||||
|
new Renderer[] {videoRenderer};
|
||||||
|
downloadHelper.set(
|
||||||
|
DownloadHelper.forMediaItem(
|
||||||
|
testMediaItem,
|
||||||
|
TrackSelectionParameters.getDefaults(getApplicationContext()),
|
||||||
|
renderersFactory,
|
||||||
|
new FakeDataSource.Factory(),
|
||||||
|
new DefaultDrmSessionManager.Builder()
|
||||||
|
.build(
|
||||||
|
new HttpMediaDrmCallback(
|
||||||
|
/* defaultLicenseUrl= */ null,
|
||||||
|
new DefaultDataSource.Factory(getApplicationContext())))));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
exception.set(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
thread.start();
|
||||||
|
thread.join();
|
||||||
|
|
||||||
|
assertThat(exception.get()).isNull();
|
||||||
|
assertThat(downloadHelper.get()).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void constructor_worksWithoutLooperThread() throws Exception {
|
||||||
|
AtomicReference<Throwable> exception = new AtomicReference<>();
|
||||||
|
AtomicReference<DownloadHelper> downloadHelper = new AtomicReference<>();
|
||||||
|
Thread thread =
|
||||||
|
new Thread(
|
||||||
|
() -> {
|
||||||
|
try {
|
||||||
|
RendererCapabilitiesList emptyRendererCapabilitiesList =
|
||||||
|
new RendererCapabilitiesList() {
|
||||||
|
@Override
|
||||||
|
public RendererCapabilities[] getRendererCapabilities() {
|
||||||
|
return new RendererCapabilities[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void release() {}
|
||||||
|
};
|
||||||
|
downloadHelper.set(
|
||||||
|
new DownloadHelper(
|
||||||
|
testMediaItem,
|
||||||
|
new FakeMediaSource(),
|
||||||
|
TrackSelectionParameters.getDefaults(getApplicationContext()),
|
||||||
|
emptyRendererCapabilitiesList));
|
||||||
|
} catch (Throwable e) {
|
||||||
|
exception.set(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
thread.start();
|
||||||
|
thread.join();
|
||||||
|
|
||||||
|
assertThat(exception.get()).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
private static void prepareDownloadHelper(DownloadHelper downloadHelper) throws Exception {
|
private static void prepareDownloadHelper(DownloadHelper downloadHelper) throws Exception {
|
||||||
AtomicReference<Exception> prepareException = new AtomicReference<>(null);
|
AtomicReference<Exception> prepareException = new AtomicReference<>(null);
|
||||||
CountDownLatch preparedLatch = new CountDownLatch(1);
|
CountDownLatch preparedLatch = new CountDownLatch(1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user