Forward TransferListener from MediaSources to DataSources.

This wires up recent changes of passing a transfer listener to the MediaSource and
allowing DataSources to accept new listeners.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=203280818
This commit is contained in:
tonihei 2018-07-04 07:59:03 -07:00 committed by Oliver Woodman
parent abb4d6ff70
commit acbe52d0d7
20 changed files with 212 additions and 74 deletions

View File

@ -68,40 +68,6 @@ public final class ExtractorMediaSource extends BaseMediaSource
} }
/**
* The default minimum number of times to retry loading prior to failing for on-demand streams.
*/
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT_ON_DEMAND = 3;
/**
* The default minimum number of times to retry loading prior to failing for live streams.
*/
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT_LIVE = 6;
/**
* Value for {@code minLoadableRetryCount} that causes the loader to retry
* {@link #DEFAULT_MIN_LOADABLE_RETRY_COUNT_LIVE} times for live streams and
* {@link #DEFAULT_MIN_LOADABLE_RETRY_COUNT_ON_DEMAND} for on-demand streams.
*/
public static final int MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA = -1;
/**
* The default number of bytes that should be loaded between each each invocation of
* {@link MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}.
*/
public static final int DEFAULT_LOADING_CHECK_INTERVAL_BYTES = 1024 * 1024;
private final Uri uri;
private final DataSource.Factory dataSourceFactory;
private final ExtractorsFactory extractorsFactory;
private final int minLoadableRetryCount;
private final String customCacheKey;
private final int continueLoadingCheckIntervalBytes;
private final @Nullable Object tag;
private long timelineDurationUs;
private boolean timelineIsSeekable;
/** Factory for {@link ExtractorMediaSource}s. */ /** Factory for {@link ExtractorMediaSource}s. */
public static final class Factory implements AdsMediaSource.MediaSourceFactory { public static final class Factory implements AdsMediaSource.MediaSourceFactory {
@ -244,6 +210,39 @@ public final class ExtractorMediaSource extends BaseMediaSource
} }
} }
/**
* The default minimum number of times to retry loading prior to failing for on-demand streams.
*/
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT_ON_DEMAND = 3;
/** The default minimum number of times to retry loading prior to failing for live streams. */
public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT_LIVE = 6;
/**
* Value for {@code minLoadableRetryCount} that causes the loader to retry {@link
* #DEFAULT_MIN_LOADABLE_RETRY_COUNT_LIVE} times for live streams and {@link
* #DEFAULT_MIN_LOADABLE_RETRY_COUNT_ON_DEMAND} for on-demand streams.
*/
public static final int MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA = -1;
/**
* The default number of bytes that should be loaded between each each invocation of {@link
* MediaPeriod.Callback#onContinueLoadingRequested(SequenceableLoader)}.
*/
public static final int DEFAULT_LOADING_CHECK_INTERVAL_BYTES = 1024 * 1024;
private final Uri uri;
private final DataSource.Factory dataSourceFactory;
private final ExtractorsFactory extractorsFactory;
private final int minLoadableRetryCount;
private final String customCacheKey;
private final int continueLoadingCheckIntervalBytes;
private final @Nullable Object tag;
private long timelineDurationUs;
private boolean timelineIsSeekable;
private @Nullable TransferListener<? super DataSource> transferListener;
/** /**
* @param uri The {@link Uri} of the media stream. * @param uri The {@link Uri} of the media stream.
* @param dataSourceFactory A factory for {@link DataSource}s to read the media. * @param dataSourceFactory A factory for {@link DataSource}s to read the media.
@ -349,6 +348,7 @@ public final class ExtractorMediaSource extends BaseMediaSource
ExoPlayer player, ExoPlayer player,
boolean isTopLevelSource, boolean isTopLevelSource,
@Nullable TransferListener<? super DataSource> mediaTransferListener) { @Nullable TransferListener<? super DataSource> mediaTransferListener) {
transferListener = mediaTransferListener;
notifySourceInfoRefreshed(timelineDurationUs, /* isSeekable= */ false); notifySourceInfoRefreshed(timelineDurationUs, /* isSeekable= */ false);
} }
@ -360,9 +360,13 @@ public final class ExtractorMediaSource extends BaseMediaSource
@Override @Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) { public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
Assertions.checkArgument(id.periodIndex == 0); Assertions.checkArgument(id.periodIndex == 0);
DataSource dataSource = dataSourceFactory.createDataSource();
if (transferListener != null) {
dataSource.addTransferListener(transferListener);
}
return new ExtractorMediaPeriod( return new ExtractorMediaPeriod(
uri, uri,
dataSourceFactory.createDataSource(), dataSource,
extractorsFactory.createExtractors(), extractorsFactory.createExtractors(),
minLoadableRetryCount, minLoadableRetryCount,
createEventDispatcher(id), createEventDispatcher(id),

View File

@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.source; package com.google.android.exoplayer2.source;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder; import com.google.android.exoplayer2.FormatHolder;
@ -28,6 +29,7 @@ import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction; import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction;
import com.google.android.exoplayer2.upstream.Loader.Loadable; import com.google.android.exoplayer2.upstream.Loader.Loadable;
import com.google.android.exoplayer2.upstream.StatsDataSource; import com.google.android.exoplayer2.upstream.StatsDataSource;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
@ -47,6 +49,7 @@ import java.util.Arrays;
private final DataSpec dataSpec; private final DataSpec dataSpec;
private final DataSource.Factory dataSourceFactory; private final DataSource.Factory dataSourceFactory;
private final @Nullable TransferListener<? super DataSource> transferListener;
private final int minLoadableRetryCount; private final int minLoadableRetryCount;
private final EventDispatcher eventDispatcher; private final EventDispatcher eventDispatcher;
private final TrackGroupArray tracks; private final TrackGroupArray tracks;
@ -67,6 +70,7 @@ import java.util.Arrays;
public SingleSampleMediaPeriod( public SingleSampleMediaPeriod(
DataSpec dataSpec, DataSpec dataSpec,
DataSource.Factory dataSourceFactory, DataSource.Factory dataSourceFactory,
@Nullable TransferListener<? super DataSource> transferListener,
Format format, Format format,
long durationUs, long durationUs,
int minLoadableRetryCount, int minLoadableRetryCount,
@ -74,6 +78,7 @@ import java.util.Arrays;
boolean treatLoadErrorsAsEndOfStream) { boolean treatLoadErrorsAsEndOfStream) {
this.dataSpec = dataSpec; this.dataSpec = dataSpec;
this.dataSourceFactory = dataSourceFactory; this.dataSourceFactory = dataSourceFactory;
this.transferListener = transferListener;
this.format = format; this.format = format;
this.durationUs = durationUs; this.durationUs = durationUs;
this.minLoadableRetryCount = minLoadableRetryCount; this.minLoadableRetryCount = minLoadableRetryCount;
@ -138,11 +143,13 @@ import java.util.Arrays;
if (loadingFinished || loader.isLoading()) { if (loadingFinished || loader.isLoading()) {
return false; return false;
} }
DataSource dataSource = dataSourceFactory.createDataSource();
if (transferListener != null) {
dataSource.addTransferListener(transferListener);
}
long elapsedRealtimeMs = long elapsedRealtimeMs =
loader.startLoading( loader.startLoading(
new SourceLoadable(dataSpec, dataSourceFactory.createDataSource()), new SourceLoadable(dataSpec, dataSource), /* callback= */ this, minLoadableRetryCount);
this,
minLoadableRetryCount);
eventDispatcher.loadStarted( eventDispatcher.loadStarted(
dataSpec, dataSpec,
dataSpec.uri, dataSpec.uri,

View File

@ -169,6 +169,8 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
private final boolean treatLoadErrorsAsEndOfStream; private final boolean treatLoadErrorsAsEndOfStream;
private final Timeline timeline; private final Timeline timeline;
private @Nullable TransferListener<? super DataSource> transferListener;
/** /**
* @param uri The {@link Uri} of the media stream. * @param uri The {@link Uri} of the media stream.
* @param dataSourceFactory The factory from which the {@link DataSource} to read the media will * @param dataSourceFactory The factory from which the {@link DataSource} to read the media will
@ -273,6 +275,7 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
ExoPlayer player, ExoPlayer player,
boolean isTopLevelSource, boolean isTopLevelSource,
@Nullable TransferListener<? super DataSource> mediaTransferListener) { @Nullable TransferListener<? super DataSource> mediaTransferListener) {
transferListener = mediaTransferListener;
refreshSourceInfo(timeline, /* manifest= */ null); refreshSourceInfo(timeline, /* manifest= */ null);
} }
@ -287,6 +290,7 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
return new SingleSampleMediaPeriod( return new SingleSampleMediaPeriod(
dataSpec, dataSpec,
dataSourceFactory, dataSourceFactory,
transferListener,
format, format,
durationUs, durationUs,
minLoadableRetryCount, minLoadableRetryCount,

View File

@ -581,7 +581,8 @@ public final class ExoPlayerTest {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
EventDispatcher eventDispatcher) { EventDispatcher eventDispatcher,
@Nullable TransferListener<? super DataSource> transferListener) {
FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray, eventDispatcher); FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray, eventDispatcher);
mediaPeriod.setSeekToUsOffset(10); mediaPeriod.setSeekToUsOffset(10);
return mediaPeriod; return mediaPeriod;
@ -615,7 +616,8 @@ public final class ExoPlayerTest {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
EventDispatcher eventDispatcher) { EventDispatcher eventDispatcher,
@Nullable TransferListener<? super DataSource> transferListener) {
FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray, eventDispatcher); FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray, eventDispatcher);
mediaPeriod.setDiscontinuityPositionUs(10); mediaPeriod.setDiscontinuityPositionUs(10);
return mediaPeriod; return mediaPeriod;
@ -640,7 +642,8 @@ public final class ExoPlayerTest {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
EventDispatcher eventDispatcher) { EventDispatcher eventDispatcher,
@Nullable TransferListener<? super DataSource> transferListener) {
FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray, eventDispatcher); FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray, eventDispatcher);
mediaPeriod.setDiscontinuityPositionUs(0); mediaPeriod.setDiscontinuityPositionUs(0);
return mediaPeriod; return mediaPeriod;
@ -876,7 +879,8 @@ public final class ExoPlayerTest {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
EventDispatcher eventDispatcher) { EventDispatcher eventDispatcher,
@Nullable TransferListener<? super DataSource> transferListener) {
// Defer completing preparation of the period until playback parameters have been set. // Defer completing preparation of the period until playback parameters have been set.
fakeMediaPeriodHolder[0] = fakeMediaPeriodHolder[0] =
new FakeMediaPeriod(trackGroupArray, eventDispatcher, /* deferOnPrepared= */ true); new FakeMediaPeriod(trackGroupArray, eventDispatcher, /* deferOnPrepared= */ true);

View File

@ -37,6 +37,8 @@ import com.google.android.exoplayer2.testutil.MediaSourceTestRunner;
import com.google.android.exoplayer2.testutil.RobolectricUtil; import com.google.android.exoplayer2.testutil.RobolectricUtil;
import com.google.android.exoplayer2.testutil.TimelineAsserts; import com.google.android.exoplayer2.testutil.TimelineAsserts;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.TransferListener;
import java.io.IOException; import java.io.IOException;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -478,7 +480,8 @@ public final class ClippingMediaSourceTest {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
EventDispatcher eventDispatcher) { EventDispatcher eventDispatcher,
@Nullable TransferListener<? super DataSource> transferListener) {
eventDispatcher.downstreamFormatChanged( eventDispatcher.downstreamFormatChanged(
new MediaLoadData( new MediaLoadData(
C.DATA_TYPE_MEDIA, C.DATA_TYPE_MEDIA,
@ -488,7 +491,8 @@ public final class ClippingMediaSourceTest {
/* trackSelectionData= */ null, /* trackSelectionData= */ null,
C.usToMs(eventStartUs), C.usToMs(eventStartUs),
C.usToMs(eventEndUs))); C.usToMs(eventEndUs)));
return super.createFakeMediaPeriod(id, trackGroupArray, allocator, eventDispatcher); return super.createFakeMediaPeriod(
id, trackGroupArray, allocator, eventDispatcher, transferListener);
} }
}; };
final ClippingMediaSource clippingMediaSource = final ClippingMediaSource clippingMediaSource =

View File

@ -21,7 +21,9 @@ import com.google.android.exoplayer2.source.chunk.ChunkSource;
import com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerTrackEmsgHandler; import com.google.android.exoplayer2.source.dash.PlayerEmsgHandler.PlayerTrackEmsgHandler;
import com.google.android.exoplayer2.source.dash.manifest.DashManifest; import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower; import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
import com.google.android.exoplayer2.upstream.TransferListener;
/** /**
* An {@link ChunkSource} for DASH streams. * An {@link ChunkSource} for DASH streams.
@ -44,6 +46,8 @@ public interface DashChunkSource extends ChunkSource {
* message track. * message track.
* @param enableCea608Track Whether the chunks generated by the source may output a CEA-608 * @param enableCea608Track Whether the chunks generated by the source may output a CEA-608
* track. * track.
* @param transferListener The transfer listener which should be informed of any data transfers.
* May be null if no listener is available.
* @return The created {@link DashChunkSource}. * @return The created {@link DashChunkSource}.
*/ */
DashChunkSource createDashChunkSource( DashChunkSource createDashChunkSource(
@ -56,7 +60,8 @@ public interface DashChunkSource extends ChunkSource {
long elapsedRealtimeOffsetMs, long elapsedRealtimeOffsetMs,
boolean enableEventMessageTrack, boolean enableEventMessageTrack,
boolean enableCea608Track, boolean enableCea608Track,
@Nullable PlayerTrackEmsgHandler playerEmsgHandler); @Nullable PlayerTrackEmsgHandler playerEmsgHandler,
@Nullable TransferListener<? super DataSource> transferListener);
} }
/** /**

View File

@ -43,7 +43,9 @@ import com.google.android.exoplayer2.source.dash.manifest.Period;
import com.google.android.exoplayer2.source.dash.manifest.Representation; import com.google.android.exoplayer2.source.dash.manifest.Representation;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower; import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@ -61,6 +63,7 @@ import java.util.List;
/* package */ final int id; /* package */ final int id;
private final DashChunkSource.Factory chunkSourceFactory; private final DashChunkSource.Factory chunkSourceFactory;
private final @Nullable TransferListener<? super DataSource> transferListener;
private final int minLoadableRetryCount; private final int minLoadableRetryCount;
private final EventDispatcher eventDispatcher; private final EventDispatcher eventDispatcher;
private final long elapsedRealtimeOffset; private final long elapsedRealtimeOffset;
@ -87,6 +90,7 @@ import java.util.List;
DashManifest manifest, DashManifest manifest,
int periodIndex, int periodIndex,
DashChunkSource.Factory chunkSourceFactory, DashChunkSource.Factory chunkSourceFactory,
@Nullable TransferListener<? super DataSource> transferListener,
int minLoadableRetryCount, int minLoadableRetryCount,
EventDispatcher eventDispatcher, EventDispatcher eventDispatcher,
long elapsedRealtimeOffset, long elapsedRealtimeOffset,
@ -98,6 +102,7 @@ import java.util.List;
this.manifest = manifest; this.manifest = manifest;
this.periodIndex = periodIndex; this.periodIndex = periodIndex;
this.chunkSourceFactory = chunkSourceFactory; this.chunkSourceFactory = chunkSourceFactory;
this.transferListener = transferListener;
this.minLoadableRetryCount = minLoadableRetryCount; this.minLoadableRetryCount = minLoadableRetryCount;
this.eventDispatcher = eventDispatcher; this.eventDispatcher = eventDispatcher;
this.elapsedRealtimeOffset = elapsedRealtimeOffset; this.elapsedRealtimeOffset = elapsedRealtimeOffset;
@ -562,7 +567,8 @@ import java.util.List;
elapsedRealtimeOffset, elapsedRealtimeOffset,
enableEventMessageTrack, enableEventMessageTrack,
enableCea608Track, enableCea608Track,
trackPlayerEmsgHandler); trackPlayerEmsgHandler,
transferListener);
ChunkSampleStream<DashChunkSource> stream = ChunkSampleStream<DashChunkSource> stream =
new ChunkSampleStream<>( new ChunkSampleStream<>(
trackGroupInfo.trackType, trackGroupInfo.trackType,

View File

@ -315,6 +315,7 @@ public final class DashMediaSource extends BaseMediaSource {
private DataSource dataSource; private DataSource dataSource;
private Loader loader; private Loader loader;
private @Nullable TransferListener<? super DataSource> mediaTransferListener;
private IOException manifestFatalError; private IOException manifestFatalError;
private Handler handler; private Handler handler;
@ -550,6 +551,7 @@ public final class DashMediaSource extends BaseMediaSource {
ExoPlayer player, ExoPlayer player,
boolean isTopLevelSource, boolean isTopLevelSource,
@Nullable TransferListener<? super DataSource> mediaTransferListener) { @Nullable TransferListener<? super DataSource> mediaTransferListener) {
this.mediaTransferListener = mediaTransferListener;
if (sideloadedManifest) { if (sideloadedManifest) {
processManifest(false); processManifest(false);
} else { } else {
@ -576,6 +578,7 @@ public final class DashMediaSource extends BaseMediaSource {
manifest, manifest,
periodIndex, periodIndex,
chunkSourceFactory, chunkSourceFactory,
mediaTransferListener,
minLoadableRetryCount, minLoadableRetryCount,
periodEventDispatcher, periodEventDispatcher,
elapsedRealtimeOffsetMs, elapsedRealtimeOffsetMs,

View File

@ -50,6 +50,7 @@ import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.HttpDataSource.InvalidResponseCodeException; import com.google.android.exoplayer2.upstream.HttpDataSource.InvalidResponseCodeException;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower; import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
@ -87,8 +88,12 @@ public class DefaultDashChunkSource implements DashChunkSource {
long elapsedRealtimeOffsetMs, long elapsedRealtimeOffsetMs,
boolean enableEventMessageTrack, boolean enableEventMessageTrack,
boolean enableCea608Track, boolean enableCea608Track,
@Nullable PlayerTrackEmsgHandler playerEmsgHandler) { @Nullable PlayerTrackEmsgHandler playerEmsgHandler,
@Nullable TransferListener<? super DataSource> transferListener) {
DataSource dataSource = dataSourceFactory.createDataSource(); DataSource dataSource = dataSourceFactory.createDataSource();
if (transferListener != null) {
dataSource.addTransferListener(transferListener);
}
return new DefaultDashChunkSource( return new DefaultDashChunkSource(
manifestLoaderErrorThrower, manifestLoaderErrorThrower,
manifest, manifest,

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2.source.hls;
import android.net.Uri; import android.net.Uri;
import android.os.SystemClock; import android.os.SystemClock;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.source.BehindLiveWindowException; import com.google.android.exoplayer2.source.BehindLiveWindowException;
@ -32,6 +33,7 @@ import com.google.android.exoplayer2.trackselection.BaseTrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.TimestampAdjuster; import com.google.android.exoplayer2.util.TimestampAdjuster;
import com.google.android.exoplayer2.util.UriUtil; import com.google.android.exoplayer2.util.UriUtil;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
@ -114,15 +116,22 @@ import java.util.List;
* @param variants The available variants. * @param variants The available variants.
* @param dataSourceFactory An {@link HlsDataSourceFactory} to create {@link DataSource}s for the * @param dataSourceFactory An {@link HlsDataSourceFactory} to create {@link DataSource}s for the
* chunks. * chunks.
* @param timestampAdjusterProvider A provider of {@link TimestampAdjuster} instances. If * @param mediaTransferListener The transfer listener which should be informed of any media data
* multiple {@link HlsChunkSource}s are used for a single playback, they should all share the * transfers. May be null if no listener is available.
* same provider. * @param timestampAdjusterProvider A provider of {@link TimestampAdjuster} instances. If multiple
* {@link HlsChunkSource}s are used for a single playback, they should all share the same
* provider.
* @param muxedCaptionFormats List of muxed caption {@link Format}s. Null if no closed caption * @param muxedCaptionFormats List of muxed caption {@link Format}s. Null if no closed caption
* information is available in the master playlist. * information is available in the master playlist.
*/ */
public HlsChunkSource(HlsExtractorFactory extractorFactory, HlsPlaylistTracker playlistTracker, public HlsChunkSource(
HlsUrl[] variants, HlsDataSourceFactory dataSourceFactory, HlsExtractorFactory extractorFactory,
TimestampAdjusterProvider timestampAdjusterProvider, List<Format> muxedCaptionFormats) { HlsPlaylistTracker playlistTracker,
HlsUrl[] variants,
HlsDataSourceFactory dataSourceFactory,
@Nullable TransferListener<? super DataSource> mediaTransferListener,
TimestampAdjusterProvider timestampAdjusterProvider,
List<Format> muxedCaptionFormats) {
this.extractorFactory = extractorFactory; this.extractorFactory = extractorFactory;
this.playlistTracker = playlistTracker; this.playlistTracker = playlistTracker;
this.variants = variants; this.variants = variants;
@ -136,6 +145,9 @@ import java.util.List;
initialTrackSelection[i] = i; initialTrackSelection[i] = i;
} }
mediaDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_MEDIA); mediaDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_MEDIA);
if (mediaTransferListener != null) {
mediaDataSource.addTransferListener(mediaTransferListener);
}
encryptionDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_DRM); encryptionDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_DRM);
trackGroup = new TrackGroup(variantFormats); trackGroup = new TrackGroup(variantFormats);
trackSelection = new InitializationTrackSelection(trackGroup, initialTrackSelection); trackSelection = new InitializationTrackSelection(trackGroup, initialTrackSelection);

View File

@ -31,6 +31,8 @@ import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.HlsUr
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker; import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
@ -50,6 +52,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
private final HlsExtractorFactory extractorFactory; private final HlsExtractorFactory extractorFactory;
private final HlsPlaylistTracker playlistTracker; private final HlsPlaylistTracker playlistTracker;
private final HlsDataSourceFactory dataSourceFactory; private final HlsDataSourceFactory dataSourceFactory;
private final @Nullable TransferListener<? super DataSource> mediaTransferListener;
private final int minLoadableRetryCount; private final int minLoadableRetryCount;
private final EventDispatcher eventDispatcher; private final EventDispatcher eventDispatcher;
private final Allocator allocator; private final Allocator allocator;
@ -70,6 +73,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
HlsExtractorFactory extractorFactory, HlsExtractorFactory extractorFactory,
HlsPlaylistTracker playlistTracker, HlsPlaylistTracker playlistTracker,
HlsDataSourceFactory dataSourceFactory, HlsDataSourceFactory dataSourceFactory,
@Nullable TransferListener<? super DataSource> mediaTransferListener,
int minLoadableRetryCount, int minLoadableRetryCount,
EventDispatcher eventDispatcher, EventDispatcher eventDispatcher,
Allocator allocator, Allocator allocator,
@ -78,6 +82,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
this.extractorFactory = extractorFactory; this.extractorFactory = extractorFactory;
this.playlistTracker = playlistTracker; this.playlistTracker = playlistTracker;
this.dataSourceFactory = dataSourceFactory; this.dataSourceFactory = dataSourceFactory;
this.mediaTransferListener = mediaTransferListener;
this.minLoadableRetryCount = minLoadableRetryCount; this.minLoadableRetryCount = minLoadableRetryCount;
this.eventDispatcher = eventDispatcher; this.eventDispatcher = eventDispatcher;
this.allocator = allocator; this.allocator = allocator;
@ -488,8 +493,15 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
private HlsSampleStreamWrapper buildSampleStreamWrapper(int trackType, HlsUrl[] variants, private HlsSampleStreamWrapper buildSampleStreamWrapper(int trackType, HlsUrl[] variants,
Format muxedAudioFormat, List<Format> muxedCaptionFormats, long positionUs) { Format muxedAudioFormat, List<Format> muxedCaptionFormats, long positionUs) {
HlsChunkSource defaultChunkSource = new HlsChunkSource(extractorFactory, playlistTracker, HlsChunkSource defaultChunkSource =
variants, dataSourceFactory, timestampAdjusterProvider, muxedCaptionFormats); new HlsChunkSource(
extractorFactory,
playlistTracker,
variants,
dataSourceFactory,
mediaTransferListener,
timestampAdjusterProvider,
muxedCaptionFormats);
return new HlsSampleStreamWrapper(trackType, this, defaultChunkSource, allocator, positionUs, return new HlsSampleStreamWrapper(trackType, this, defaultChunkSource, allocator, positionUs,
muxedAudioFormat, minLoadableRetryCount, eventDispatcher); muxedAudioFormat, minLoadableRetryCount, eventDispatcher);
} }

View File

@ -265,6 +265,8 @@ public final class HlsMediaSource extends BaseMediaSource
private final HlsPlaylistTracker playlistTracker; private final HlsPlaylistTracker playlistTracker;
private final @Nullable Object tag; private final @Nullable Object tag;
private @Nullable TransferListener<? super DataSource> mediaTransferListener;
/** /**
* @param manifestUri The {@link Uri} of the HLS manifest. * @param manifestUri The {@link Uri} of the HLS manifest.
* @param dataSourceFactory An {@link HlsDataSourceFactory} for {@link DataSource}s for manifests, * @param dataSourceFactory An {@link HlsDataSourceFactory} for {@link DataSource}s for manifests,
@ -372,6 +374,7 @@ public final class HlsMediaSource extends BaseMediaSource
ExoPlayer player, ExoPlayer player,
boolean isTopLevelSource, boolean isTopLevelSource,
@Nullable TransferListener<? super DataSource> mediaTransferListener) { @Nullable TransferListener<? super DataSource> mediaTransferListener) {
this.mediaTransferListener = mediaTransferListener;
EventDispatcher eventDispatcher = createEventDispatcher(/* mediaPeriodId= */ null); EventDispatcher eventDispatcher = createEventDispatcher(/* mediaPeriodId= */ null);
playlistTracker.start(manifestUri, eventDispatcher, /* listener= */ this); playlistTracker.start(manifestUri, eventDispatcher, /* listener= */ this);
} }
@ -389,6 +392,7 @@ public final class HlsMediaSource extends BaseMediaSource
extractorFactory, extractorFactory,
playlistTracker, playlistTracker,
dataSourceFactory, dataSourceFactory,
mediaTransferListener,
minLoadableRetryCount, minLoadableRetryCount,
eventDispatcher, eventDispatcher,
allocator, allocator,

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.source.smoothstreaming; package com.google.android.exoplayer2.source.smoothstreaming;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.SeekParameters; import com.google.android.exoplayer2.SeekParameters;
@ -35,6 +36,7 @@ import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower; import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@ -53,10 +55,17 @@ public class DefaultSsChunkSource implements SsChunkSource {
} }
@Override @Override
public SsChunkSource createChunkSource(LoaderErrorThrower manifestLoaderErrorThrower, public SsChunkSource createChunkSource(
SsManifest manifest, int elementIndex, TrackSelection trackSelection, LoaderErrorThrower manifestLoaderErrorThrower,
TrackEncryptionBox[] trackEncryptionBoxes) { SsManifest manifest,
int elementIndex,
TrackSelection trackSelection,
TrackEncryptionBox[] trackEncryptionBoxes,
@Nullable TransferListener<? super DataSource> transferListener) {
DataSource dataSource = dataSourceFactory.createDataSource(); DataSource dataSource = dataSourceFactory.createDataSource();
if (transferListener != null) {
dataSource.addTransferListener(transferListener);
}
return new DefaultSsChunkSource(manifestLoaderErrorThrower, manifest, elementIndex, return new DefaultSsChunkSource(manifestLoaderErrorThrower, manifest, elementIndex,
trackSelection, dataSource, trackEncryptionBoxes); trackSelection, dataSource, trackEncryptionBoxes);
} }

View File

@ -15,11 +15,14 @@
*/ */
package com.google.android.exoplayer2.source.smoothstreaming; package com.google.android.exoplayer2.source.smoothstreaming;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.extractor.mp4.TrackEncryptionBox; import com.google.android.exoplayer2.extractor.mp4.TrackEncryptionBox;
import com.google.android.exoplayer2.source.chunk.ChunkSource; import com.google.android.exoplayer2.source.chunk.ChunkSource;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest; import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower; import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
import com.google.android.exoplayer2.upstream.TransferListener;
/** /**
* A {@link ChunkSource} for SmoothStreaming. * A {@link ChunkSource} for SmoothStreaming.
@ -37,6 +40,8 @@ public interface SsChunkSource extends ChunkSource {
* @param streamElementIndex The index of the corresponding stream element in the manifest. * @param streamElementIndex The index of the corresponding stream element in the manifest.
* @param trackSelection The track selection. * @param trackSelection The track selection.
* @param trackEncryptionBoxes Track encryption boxes for the stream. * @param trackEncryptionBoxes Track encryption boxes for the stream.
* @param transferListener The transfer listener which should be informed of any data transfers.
* May be null if no listener is available.
* @return The created {@link SsChunkSource}. * @return The created {@link SsChunkSource}.
*/ */
SsChunkSource createChunkSource( SsChunkSource createChunkSource(
@ -44,7 +49,8 @@ public interface SsChunkSource extends ChunkSource {
SsManifest manifest, SsManifest manifest,
int streamElementIndex, int streamElementIndex,
TrackSelection trackSelection, TrackSelection trackSelection,
TrackEncryptionBox[] trackEncryptionBoxes); TrackEncryptionBox[] trackEncryptionBoxes,
@Nullable TransferListener<? super DataSource> transferListener);
} }
/** /**

View File

@ -32,7 +32,9 @@ import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.ProtectionElement; import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.ProtectionElement;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower; import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
import com.google.android.exoplayer2.upstream.TransferListener;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -45,6 +47,7 @@ import java.util.ArrayList;
private static final int INITIALIZATION_VECTOR_SIZE = 8; private static final int INITIALIZATION_VECTOR_SIZE = 8;
private final SsChunkSource.Factory chunkSourceFactory; private final SsChunkSource.Factory chunkSourceFactory;
private final @Nullable TransferListener<? super DataSource> transferListener;
private final LoaderErrorThrower manifestLoaderErrorThrower; private final LoaderErrorThrower manifestLoaderErrorThrower;
private final int minLoadableRetryCount; private final int minLoadableRetryCount;
private final EventDispatcher eventDispatcher; private final EventDispatcher eventDispatcher;
@ -59,11 +62,17 @@ import java.util.ArrayList;
private SequenceableLoader compositeSequenceableLoader; private SequenceableLoader compositeSequenceableLoader;
private boolean notifiedReadingStarted; private boolean notifiedReadingStarted;
public SsMediaPeriod(SsManifest manifest, SsChunkSource.Factory chunkSourceFactory, public SsMediaPeriod(
SsManifest manifest,
SsChunkSource.Factory chunkSourceFactory,
@Nullable TransferListener<? super DataSource> transferListener,
CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory, CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory,
int minLoadableRetryCount, EventDispatcher eventDispatcher, int minLoadableRetryCount,
LoaderErrorThrower manifestLoaderErrorThrower, Allocator allocator) { EventDispatcher eventDispatcher,
LoaderErrorThrower manifestLoaderErrorThrower,
Allocator allocator) {
this.chunkSourceFactory = chunkSourceFactory; this.chunkSourceFactory = chunkSourceFactory;
this.transferListener = transferListener;
this.manifestLoaderErrorThrower = manifestLoaderErrorThrower; this.manifestLoaderErrorThrower = manifestLoaderErrorThrower;
this.minLoadableRetryCount = minLoadableRetryCount; this.minLoadableRetryCount = minLoadableRetryCount;
this.eventDispatcher = eventDispatcher; this.eventDispatcher = eventDispatcher;
@ -214,8 +223,14 @@ import java.util.ArrayList;
private ChunkSampleStream<SsChunkSource> buildSampleStream(TrackSelection selection, private ChunkSampleStream<SsChunkSource> buildSampleStream(TrackSelection selection,
long positionUs) { long positionUs) {
int streamElementIndex = trackGroups.indexOf(selection.getTrackGroup()); int streamElementIndex = trackGroups.indexOf(selection.getTrackGroup());
SsChunkSource chunkSource = chunkSourceFactory.createChunkSource(manifestLoaderErrorThrower, SsChunkSource chunkSource =
manifest, streamElementIndex, selection, trackEncryptionBoxes); chunkSourceFactory.createChunkSource(
manifestLoaderErrorThrower,
manifest,
streamElementIndex,
selection,
trackEncryptionBoxes,
transferListener);
return new ChunkSampleStream<>( return new ChunkSampleStream<>(
manifest.streamElements[streamElementIndex].type, manifest.streamElements[streamElementIndex].type,
null, null,

View File

@ -285,6 +285,7 @@ public final class SsMediaSource extends BaseMediaSource
private DataSource manifestDataSource; private DataSource manifestDataSource;
private Loader manifestLoader; private Loader manifestLoader;
private LoaderErrorThrower manifestLoaderErrorThrower; private LoaderErrorThrower manifestLoaderErrorThrower;
private @Nullable TransferListener<? super DataSource> mediaTransferListener;
private long manifestLoadStartTimestamp; private long manifestLoadStartTimestamp;
private SsManifest manifest; private SsManifest manifest;
@ -467,6 +468,7 @@ public final class SsMediaSource extends BaseMediaSource
ExoPlayer player, ExoPlayer player,
boolean isTopLevelSource, boolean isTopLevelSource,
@Nullable TransferListener<? super DataSource> mediaTransferListener) { @Nullable TransferListener<? super DataSource> mediaTransferListener) {
this.mediaTransferListener = mediaTransferListener;
if (sideloadedManifest) { if (sideloadedManifest) {
manifestLoaderErrorThrower = new LoaderErrorThrower.Dummy(); manifestLoaderErrorThrower = new LoaderErrorThrower.Dummy();
processManifest(); processManifest();
@ -488,9 +490,16 @@ public final class SsMediaSource extends BaseMediaSource
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) { public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
Assertions.checkArgument(id.periodIndex == 0); Assertions.checkArgument(id.periodIndex == 0);
EventDispatcher eventDispatcher = createEventDispatcher(id); EventDispatcher eventDispatcher = createEventDispatcher(id);
SsMediaPeriod period = new SsMediaPeriod(manifest, chunkSourceFactory, SsMediaPeriod period =
compositeSequenceableLoaderFactory, minLoadableRetryCount, eventDispatcher, new SsMediaPeriod(
manifestLoaderErrorThrower, allocator); manifest,
chunkSourceFactory,
mediaTransferListener,
compositeSequenceableLoaderFactory,
minLoadableRetryCount,
eventDispatcher,
manifestLoaderErrorThrower,
allocator);
mediaPeriods.add(period); mediaPeriods.add(period);
return period; return period;
} }

View File

@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.testutil; package com.google.android.exoplayer2.testutil;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.source.CompositeSequenceableLoader; import com.google.android.exoplayer2.source.CompositeSequenceableLoader;
import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
@ -24,6 +25,8 @@ import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.chunk.ChunkSampleStream; import com.google.android.exoplayer2.source.chunk.ChunkSampleStream;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -37,6 +40,7 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
private final Allocator allocator; private final Allocator allocator;
private final FakeChunkSource.Factory chunkSourceFactory; private final FakeChunkSource.Factory chunkSourceFactory;
private final @Nullable TransferListener<? super DataSource> transferListener;
private final long durationUs; private final long durationUs;
private Callback callback; private Callback callback;
@ -48,10 +52,12 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
EventDispatcher eventDispatcher, EventDispatcher eventDispatcher,
Allocator allocator, Allocator allocator,
FakeChunkSource.Factory chunkSourceFactory, FakeChunkSource.Factory chunkSourceFactory,
long durationUs) { long durationUs,
@Nullable TransferListener<? super DataSource> transferListener) {
super(trackGroupArray, eventDispatcher); super(trackGroupArray, eventDispatcher);
this.allocator = allocator; this.allocator = allocator;
this.chunkSourceFactory = chunkSourceFactory; this.chunkSourceFactory = chunkSourceFactory;
this.transferListener = transferListener;
this.durationUs = durationUs; this.durationUs = durationUs;
this.sampleStreams = newSampleStreamArray(0); this.sampleStreams = newSampleStreamArray(0);
} }
@ -128,7 +134,8 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
@Override @Override
protected SampleStream createSampleStream(TrackSelection trackSelection) { protected SampleStream createSampleStream(TrackSelection trackSelection) {
FakeChunkSource chunkSource = chunkSourceFactory.createChunkSource(trackSelection, durationUs); FakeChunkSource chunkSource =
chunkSourceFactory.createChunkSource(trackSelection, durationUs, transferListener);
return new ChunkSampleStream<>( return new ChunkSampleStream<>(
MimeTypes.getTrackType(trackSelection.getSelectedFormat().sampleMimeType), MimeTypes.getTrackType(trackSelection.getSelectedFormat().sampleMimeType),
null, null,

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.testutil; package com.google.android.exoplayer2.testutil;
import android.os.Handler; import android.os.Handler;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period; import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
@ -23,6 +24,8 @@ import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.TransferListener;
/** /**
* Fake {@link MediaSource} that provides a given timeline. Creating the period returns a * Fake {@link MediaSource} that provides a given timeline. Creating the period returns a
@ -49,10 +52,16 @@ public class FakeAdaptiveMediaSource extends FakeMediaSource {
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
EventDispatcher eventDispatcher) { EventDispatcher eventDispatcher,
@Nullable TransferListener<? super DataSource> transferListener) {
Period period = timeline.getPeriod(id.periodIndex, new Period()); Period period = timeline.getPeriod(id.periodIndex, new Period());
return new FakeAdaptiveMediaPeriod( return new FakeAdaptiveMediaPeriod(
trackGroupArray, eventDispatcher, allocator, chunkSourceFactory, period.durationUs); trackGroupArray,
eventDispatcher,
allocator,
chunkSourceFactory,
period.durationUs,
transferListener);
} }
} }

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.testutil; package com.google.android.exoplayer2.testutil;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.SeekParameters; import com.google.android.exoplayer2.SeekParameters;
@ -28,6 +29,7 @@ import com.google.android.exoplayer2.testutil.FakeDataSet.FakeData.Segment;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.io.IOException; import java.io.IOException;
@ -52,11 +54,17 @@ public final class FakeChunkSource implements ChunkSource {
this.dataSourceFactory = dataSourceFactory; this.dataSourceFactory = dataSourceFactory;
} }
public FakeChunkSource createChunkSource(TrackSelection trackSelection, long durationUs) { public FakeChunkSource createChunkSource(
TrackSelection trackSelection,
long durationUs,
@Nullable TransferListener<? super DataSource> transferListener) {
FakeAdaptiveDataSet dataSet = FakeAdaptiveDataSet dataSet =
dataSetFactory.createDataSet(trackSelection.getTrackGroup(), durationUs); dataSetFactory.createDataSet(trackSelection.getTrackGroup(), durationUs);
dataSourceFactory.setFakeDataSet(dataSet); dataSourceFactory.setFakeDataSet(dataSet);
DataSource dataSource = dataSourceFactory.createDataSource(); DataSource dataSource = dataSourceFactory.createDataSource();
if (transferListener != null) {
dataSource.addTransferListener(transferListener);
}
return new FakeChunkSource(trackSelection, dataSource, dataSet); return new FakeChunkSource(trackSelection, dataSource, dataSet);
} }

View File

@ -61,6 +61,7 @@ public class FakeMediaSource extends BaseMediaSource {
private boolean preparedSource; private boolean preparedSource;
private boolean releasedSource; private boolean releasedSource;
private Handler sourceInfoRefreshHandler; private Handler sourceInfoRefreshHandler;
private @Nullable TransferListener<? super DataSource> transferListener;
/** /**
* Creates a {@link FakeMediaSource}. This media source creates {@link FakeMediaPeriod}s with a * Creates a {@link FakeMediaSource}. This media source creates {@link FakeMediaPeriod}s with a
@ -93,6 +94,7 @@ public class FakeMediaSource extends BaseMediaSource {
boolean isTopLevelSource, boolean isTopLevelSource,
@Nullable TransferListener<? super DataSource> mediaTransferListener) { @Nullable TransferListener<? super DataSource> mediaTransferListener) {
assertThat(preparedSource).isFalse(); assertThat(preparedSource).isFalse();
transferListener = mediaTransferListener;
preparedSource = true; preparedSource = true;
releasedSource = false; releasedSource = false;
sourceInfoRefreshHandler = new Handler(); sourceInfoRefreshHandler = new Handler();
@ -115,7 +117,7 @@ public class FakeMediaSource extends BaseMediaSource {
EventDispatcher eventDispatcher = EventDispatcher eventDispatcher =
createEventDispatcher(period.windowIndex, id, period.getPositionInWindowMs()); createEventDispatcher(period.windowIndex, id, period.getPositionInWindowMs());
FakeMediaPeriod mediaPeriod = FakeMediaPeriod mediaPeriod =
createFakeMediaPeriod(id, trackGroupArray, allocator, eventDispatcher); createFakeMediaPeriod(id, trackGroupArray, allocator, eventDispatcher, transferListener);
activeMediaPeriods.add(mediaPeriod); activeMediaPeriods.add(mediaPeriod);
createdMediaPeriods.add(id); createdMediaPeriods.add(id);
return mediaPeriod; return mediaPeriod;
@ -195,13 +197,16 @@ public class FakeMediaSource extends BaseMediaSource {
* @param trackGroupArray The {@link TrackGroupArray} supported by the media period. * @param trackGroupArray The {@link TrackGroupArray} supported by the media period.
* @param allocator An {@link Allocator} from which to obtain media buffer allocations. * @param allocator An {@link Allocator} from which to obtain media buffer allocations.
* @param eventDispatcher An {@link EventDispatcher} to dispatch media source events. * @param eventDispatcher An {@link EventDispatcher} to dispatch media source events.
* @param transferListener The transfer listener which should be informed of any data transfers.
* May be null if no listener is available.
* @return A new {@link FakeMediaPeriod}. * @return A new {@link FakeMediaPeriod}.
*/ */
protected FakeMediaPeriod createFakeMediaPeriod( protected FakeMediaPeriod createFakeMediaPeriod(
MediaPeriodId id, MediaPeriodId id,
TrackGroupArray trackGroupArray, TrackGroupArray trackGroupArray,
Allocator allocator, Allocator allocator,
EventDispatcher eventDispatcher) { EventDispatcher eventDispatcher,
@Nullable TransferListener<? super DataSource> transferListener) {
return new FakeMediaPeriod(trackGroupArray, eventDispatcher); return new FakeMediaPeriod(trackGroupArray, eventDispatcher);
} }