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. */
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 dataSourceFactory A factory for {@link DataSource}s to read the media.
@ -349,6 +348,7 @@ public final class ExtractorMediaSource extends BaseMediaSource
ExoPlayer player,
boolean isTopLevelSource,
@Nullable TransferListener<? super DataSource> mediaTransferListener) {
transferListener = mediaTransferListener;
notifySourceInfoRefreshed(timelineDurationUs, /* isSeekable= */ false);
}
@ -360,9 +360,13 @@ public final class ExtractorMediaSource extends BaseMediaSource
@Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
Assertions.checkArgument(id.periodIndex == 0);
DataSource dataSource = dataSourceFactory.createDataSource();
if (transferListener != null) {
dataSource.addTransferListener(transferListener);
}
return new ExtractorMediaPeriod(
uri,
dataSourceFactory.createDataSource(),
dataSource,
extractorsFactory.createExtractors(),
minLoadableRetryCount,
createEventDispatcher(id),

View File

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

View File

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

View File

@ -581,7 +581,8 @@ public final class ExoPlayerTest {
MediaPeriodId id,
TrackGroupArray trackGroupArray,
Allocator allocator,
EventDispatcher eventDispatcher) {
EventDispatcher eventDispatcher,
@Nullable TransferListener<? super DataSource> transferListener) {
FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray, eventDispatcher);
mediaPeriod.setSeekToUsOffset(10);
return mediaPeriod;
@ -615,7 +616,8 @@ public final class ExoPlayerTest {
MediaPeriodId id,
TrackGroupArray trackGroupArray,
Allocator allocator,
EventDispatcher eventDispatcher) {
EventDispatcher eventDispatcher,
@Nullable TransferListener<? super DataSource> transferListener) {
FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray, eventDispatcher);
mediaPeriod.setDiscontinuityPositionUs(10);
return mediaPeriod;
@ -640,7 +642,8 @@ public final class ExoPlayerTest {
MediaPeriodId id,
TrackGroupArray trackGroupArray,
Allocator allocator,
EventDispatcher eventDispatcher) {
EventDispatcher eventDispatcher,
@Nullable TransferListener<? super DataSource> transferListener) {
FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray, eventDispatcher);
mediaPeriod.setDiscontinuityPositionUs(0);
return mediaPeriod;
@ -876,7 +879,8 @@ public final class ExoPlayerTest {
MediaPeriodId id,
TrackGroupArray trackGroupArray,
Allocator allocator,
EventDispatcher eventDispatcher) {
EventDispatcher eventDispatcher,
@Nullable TransferListener<? super DataSource> transferListener) {
// Defer completing preparation of the period until playback parameters have been set.
fakeMediaPeriodHolder[0] =
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.TimelineAsserts;
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 org.junit.Before;
import org.junit.Test;
@ -478,7 +480,8 @@ public final class ClippingMediaSourceTest {
MediaPeriodId id,
TrackGroupArray trackGroupArray,
Allocator allocator,
EventDispatcher eventDispatcher) {
EventDispatcher eventDispatcher,
@Nullable TransferListener<? super DataSource> transferListener) {
eventDispatcher.downstreamFormatChanged(
new MediaLoadData(
C.DATA_TYPE_MEDIA,
@ -488,7 +491,8 @@ public final class ClippingMediaSourceTest {
/* trackSelectionData= */ null,
C.usToMs(eventStartUs),
C.usToMs(eventEndUs)));
return super.createFakeMediaPeriod(id, trackGroupArray, allocator, eventDispatcher);
return super.createFakeMediaPeriod(
id, trackGroupArray, allocator, eventDispatcher, transferListener);
}
};
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.manifest.DashManifest;
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.TransferListener;
/**
* An {@link ChunkSource} for DASH streams.
@ -44,6 +46,8 @@ public interface DashChunkSource extends ChunkSource {
* message track.
* @param enableCea608Track Whether the chunks generated by the source may output a CEA-608
* 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}.
*/
DashChunkSource createDashChunkSource(
@ -56,7 +60,8 @@ public interface DashChunkSource extends ChunkSource {
long elapsedRealtimeOffsetMs,
boolean enableEventMessageTrack,
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.trackselection.TrackSelection;
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.TransferListener;
import com.google.android.exoplayer2.util.MimeTypes;
import java.io.IOException;
import java.lang.annotation.Retention;
@ -61,6 +63,7 @@ import java.util.List;
/* package */ final int id;
private final DashChunkSource.Factory chunkSourceFactory;
private final @Nullable TransferListener<? super DataSource> transferListener;
private final int minLoadableRetryCount;
private final EventDispatcher eventDispatcher;
private final long elapsedRealtimeOffset;
@ -87,6 +90,7 @@ import java.util.List;
DashManifest manifest,
int periodIndex,
DashChunkSource.Factory chunkSourceFactory,
@Nullable TransferListener<? super DataSource> transferListener,
int minLoadableRetryCount,
EventDispatcher eventDispatcher,
long elapsedRealtimeOffset,
@ -98,6 +102,7 @@ import java.util.List;
this.manifest = manifest;
this.periodIndex = periodIndex;
this.chunkSourceFactory = chunkSourceFactory;
this.transferListener = transferListener;
this.minLoadableRetryCount = minLoadableRetryCount;
this.eventDispatcher = eventDispatcher;
this.elapsedRealtimeOffset = elapsedRealtimeOffset;
@ -562,7 +567,8 @@ import java.util.List;
elapsedRealtimeOffset,
enableEventMessageTrack,
enableCea608Track,
trackPlayerEmsgHandler);
trackPlayerEmsgHandler,
transferListener);
ChunkSampleStream<DashChunkSource> stream =
new ChunkSampleStream<>(
trackGroupInfo.trackType,

View File

@ -315,6 +315,7 @@ public final class DashMediaSource extends BaseMediaSource {
private DataSource dataSource;
private Loader loader;
private @Nullable TransferListener<? super DataSource> mediaTransferListener;
private IOException manifestFatalError;
private Handler handler;
@ -550,6 +551,7 @@ public final class DashMediaSource extends BaseMediaSource {
ExoPlayer player,
boolean isTopLevelSource,
@Nullable TransferListener<? super DataSource> mediaTransferListener) {
this.mediaTransferListener = mediaTransferListener;
if (sideloadedManifest) {
processManifest(false);
} else {
@ -576,6 +578,7 @@ public final class DashMediaSource extends BaseMediaSource {
manifest,
periodIndex,
chunkSourceFactory,
mediaTransferListener,
minLoadableRetryCount,
periodEventDispatcher,
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.HttpDataSource.InvalidResponseCodeException;
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.Util;
import java.io.IOException;
@ -87,8 +88,12 @@ public class DefaultDashChunkSource implements DashChunkSource {
long elapsedRealtimeOffsetMs,
boolean enableEventMessageTrack,
boolean enableCea608Track,
@Nullable PlayerTrackEmsgHandler playerEmsgHandler) {
@Nullable PlayerTrackEmsgHandler playerEmsgHandler,
@Nullable TransferListener<? super DataSource> transferListener) {
DataSource dataSource = dataSourceFactory.createDataSource();
if (transferListener != null) {
dataSource.addTransferListener(transferListener);
}
return new DefaultDashChunkSource(
manifestLoaderErrorThrower,
manifest,

View File

@ -17,6 +17,7 @@ package com.google.android.exoplayer2.source.hls;
import android.net.Uri;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
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.upstream.DataSource;
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.UriUtil;
import com.google.android.exoplayer2.util.Util;
@ -114,15 +116,22 @@ import java.util.List;
* @param variants The available variants.
* @param dataSourceFactory An {@link HlsDataSourceFactory} to create {@link DataSource}s for the
* chunks.
* @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 mediaTransferListener The transfer listener which should be informed of any media data
* transfers. May be null if no listener is available.
* @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
* information is available in the master playlist.
*/
public HlsChunkSource(HlsExtractorFactory extractorFactory, HlsPlaylistTracker playlistTracker,
HlsUrl[] variants, HlsDataSourceFactory dataSourceFactory,
TimestampAdjusterProvider timestampAdjusterProvider, List<Format> muxedCaptionFormats) {
public HlsChunkSource(
HlsExtractorFactory extractorFactory,
HlsPlaylistTracker playlistTracker,
HlsUrl[] variants,
HlsDataSourceFactory dataSourceFactory,
@Nullable TransferListener<? super DataSource> mediaTransferListener,
TimestampAdjusterProvider timestampAdjusterProvider,
List<Format> muxedCaptionFormats) {
this.extractorFactory = extractorFactory;
this.playlistTracker = playlistTracker;
this.variants = variants;
@ -136,6 +145,9 @@ import java.util.List;
initialTrackSelection[i] = i;
}
mediaDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_MEDIA);
if (mediaTransferListener != null) {
mediaDataSource.addTransferListener(mediaTransferListener);
}
encryptionDataSource = dataSourceFactory.createDataSource(C.DATA_TYPE_DRM);
trackGroup = new TrackGroup(variantFormats);
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.trackselection.TrackSelection;
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.MimeTypes;
import com.google.android.exoplayer2.util.Util;
@ -50,6 +52,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
private final HlsExtractorFactory extractorFactory;
private final HlsPlaylistTracker playlistTracker;
private final HlsDataSourceFactory dataSourceFactory;
private final @Nullable TransferListener<? super DataSource> mediaTransferListener;
private final int minLoadableRetryCount;
private final EventDispatcher eventDispatcher;
private final Allocator allocator;
@ -70,6 +73,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
HlsExtractorFactory extractorFactory,
HlsPlaylistTracker playlistTracker,
HlsDataSourceFactory dataSourceFactory,
@Nullable TransferListener<? super DataSource> mediaTransferListener,
int minLoadableRetryCount,
EventDispatcher eventDispatcher,
Allocator allocator,
@ -78,6 +82,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
this.extractorFactory = extractorFactory;
this.playlistTracker = playlistTracker;
this.dataSourceFactory = dataSourceFactory;
this.mediaTransferListener = mediaTransferListener;
this.minLoadableRetryCount = minLoadableRetryCount;
this.eventDispatcher = eventDispatcher;
this.allocator = allocator;
@ -488,8 +493,15 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
private HlsSampleStreamWrapper buildSampleStreamWrapper(int trackType, HlsUrl[] variants,
Format muxedAudioFormat, List<Format> muxedCaptionFormats, long positionUs) {
HlsChunkSource defaultChunkSource = new HlsChunkSource(extractorFactory, playlistTracker,
variants, dataSourceFactory, timestampAdjusterProvider, muxedCaptionFormats);
HlsChunkSource defaultChunkSource =
new HlsChunkSource(
extractorFactory,
playlistTracker,
variants,
dataSourceFactory,
mediaTransferListener,
timestampAdjusterProvider,
muxedCaptionFormats);
return new HlsSampleStreamWrapper(trackType, this, defaultChunkSource, allocator, positionUs,
muxedAudioFormat, minLoadableRetryCount, eventDispatcher);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.testutil;
import android.os.Handler;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period;
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.TrackGroupArray;
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
@ -49,10 +52,16 @@ public class FakeAdaptiveMediaSource extends FakeMediaSource {
MediaPeriodId id,
TrackGroupArray trackGroupArray,
Allocator allocator,
EventDispatcher eventDispatcher) {
EventDispatcher eventDispatcher,
@Nullable TransferListener<? super DataSource> transferListener) {
Period period = timeline.getPeriod(id.periodIndex, new Period());
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;
import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
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.upstream.DataSource;
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.Util;
import java.io.IOException;
@ -52,11 +54,17 @@ public final class FakeChunkSource implements ChunkSource {
this.dataSourceFactory = dataSourceFactory;
}
public FakeChunkSource createChunkSource(TrackSelection trackSelection, long durationUs) {
public FakeChunkSource createChunkSource(
TrackSelection trackSelection,
long durationUs,
@Nullable TransferListener<? super DataSource> transferListener) {
FakeAdaptiveDataSet dataSet =
dataSetFactory.createDataSet(trackSelection.getTrackGroup(), durationUs);
dataSourceFactory.setFakeDataSet(dataSet);
DataSource dataSource = dataSourceFactory.createDataSource();
if (transferListener != null) {
dataSource.addTransferListener(transferListener);
}
return new FakeChunkSource(trackSelection, dataSource, dataSet);
}

View File

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