Skip to content

Commit

Permalink
Extract HlsPlaylistTracker interface
Browse files Browse the repository at this point in the history
This allows injection of custom implementations and configuration of
DefaultHlsPlaylistTracker without modifying the HlsMediaSource interface.

Issue:#2844

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=198846607
  • Loading branch information
AquilesCanta authored and ojw28 committed Jun 25, 2018
1 parent 798b29e commit f1fe1c4
Show file tree
Hide file tree
Showing 4 changed files with 696 additions and 544 deletions.
4 changes: 3 additions & 1 deletion RELEASENOTES.md
Expand Up @@ -6,7 +6,9 @@
extractor for this ([#4297](https://github.com/google/ExoPlayer/issues/4297)).
* DASH: Fix playback getting stuck when playing representations that have both
sidx atoms and non-zero presentationTimeOffset values.
* HLS: Fix adaptation in live playlists with EXT-X-PROGRAM-DATE-TIME tags.
* HLS:
* Allow injection of custom playlist trackers.
* Fix adaptation in live playlists with EXT-X-PROGRAM-DATE-TIME tags.
* Mitigate memory leaks when `MediaSource` loads are slow to cancel
([#4249](https://github.com/google/ExoPlayer/issues/4249)).
* Fix inconsistent `Player.EventListener` invocations for recursive player state
Expand Down
Expand Up @@ -32,6 +32,7 @@
import com.google.android.exoplayer2.source.SequenceableLoader;
import com.google.android.exoplayer2.source.SinglePeriodTimeline;
import com.google.android.exoplayer2.source.ads.AdsMediaSource;
import com.google.android.exoplayer2.source.hls.playlist.DefaultHlsPlaylistTracker;
import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist;
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylist;
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParser;
Expand All @@ -58,6 +59,7 @@ public static final class Factory implements AdsMediaSource.MediaSourceFactory {

private HlsExtractorFactory extractorFactory;
private @Nullable ParsingLoadable.Parser<HlsPlaylist> playlistParser;
private @Nullable HlsPlaylistTracker playlistTracker;
private CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory;
private int minLoadableRetryCount;
private boolean allowChunklessPreparation;
Expand Down Expand Up @@ -136,16 +138,37 @@ public Factory setMinLoadableRetryCount(int minLoadableRetryCount) {
* Sets the parser to parse HLS playlists. The default is an instance of {@link
* HlsPlaylistParser}.
*
* <p>Must not be called after calling {@link #setPlaylistTracker} on the same builder.
*
* @param playlistParser A {@link ParsingLoadable.Parser} for HLS playlists.
* @return This factory, for convenience.
* @throws IllegalStateException If one of the {@code create} methods has already been called.
*/
public Factory setPlaylistParser(ParsingLoadable.Parser<HlsPlaylist> playlistParser) {
Assertions.checkState(!isCreateCalled);
Assertions.checkState(playlistTracker == null, "A playlist tracker has already been set.");
this.playlistParser = Assertions.checkNotNull(playlistParser);
return this;
}

/**
* Sets the HLS playlist tracker. The default is an instance of {@link
* DefaultHlsPlaylistTracker}. Playlist trackers must not be shared by {@link HlsMediaSource}
* instances.
*
* <p>Must not be called after calling {@link #setPlaylistParser} on the same builder.
*
* @param playlistTracker A tracker for HLS playlists.
* @return This factory, for convenience.
* @throws IllegalStateException If one of the {@code create} methods has already been called.
*/
public Factory setPlaylistTracker(HlsPlaylistTracker playlistTracker) {
Assertions.checkState(!isCreateCalled);
Assertions.checkState(playlistParser == null, "A playlist parser has already been set.");
this.playlistTracker = Assertions.checkNotNull(playlistTracker);
return this;
}

/**
* Sets the factory to create composite {@link SequenceableLoader}s for when this media source
* loads data from multiple streams (video, audio etc...). The default is an instance of {@link
Expand Down Expand Up @@ -187,16 +210,20 @@ public Factory setAllowChunklessPreparation(boolean allowChunklessPreparation) {
@Override
public HlsMediaSource createMediaSource(Uri playlistUri) {
isCreateCalled = true;
if (playlistParser == null) {
playlistParser = new HlsPlaylistParser();
if (playlistTracker == null) {
playlistTracker =
new DefaultHlsPlaylistTracker(
hlsDataSourceFactory,
minLoadableRetryCount,
playlistParser != null ? playlistParser : new HlsPlaylistParser());
}
return new HlsMediaSource(
playlistUri,
hlsDataSourceFactory,
extractorFactory,
compositeSequenceableLoaderFactory,
minLoadableRetryCount,
playlistParser,
playlistTracker,
allowChunklessPreparation,
tag);
}
Expand Down Expand Up @@ -233,12 +260,10 @@ public int[] getSupportedTypes() {
private final HlsDataSourceFactory dataSourceFactory;
private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory;
private final int minLoadableRetryCount;
private final ParsingLoadable.Parser<HlsPlaylist> playlistParser;
private final boolean allowChunklessPreparation;
private final HlsPlaylistTracker playlistTracker;
private final @Nullable Object tag;

private HlsPlaylistTracker playlistTracker;

/**
* @param manifestUri The {@link Uri} of the HLS manifest.
* @param dataSourceFactory An {@link HlsDataSourceFactory} for {@link DataSource}s for manifests,
Expand Down Expand Up @@ -276,8 +301,13 @@ public HlsMediaSource(
int minLoadableRetryCount,
Handler eventHandler,
MediaSourceEventListener eventListener) {
this(manifestUri, new DefaultHlsDataSourceFactory(dataSourceFactory),
HlsExtractorFactory.DEFAULT, minLoadableRetryCount, eventHandler, eventListener,
this(
manifestUri,
new DefaultHlsDataSourceFactory(dataSourceFactory),
HlsExtractorFactory.DEFAULT,
minLoadableRetryCount,
eventHandler,
eventListener,
new HlsPlaylistParser());
}

Expand Down Expand Up @@ -309,7 +339,8 @@ public HlsMediaSource(
extractorFactory,
new DefaultCompositeSequenceableLoaderFactory(),
minLoadableRetryCount,
playlistParser,
new DefaultHlsPlaylistTracker(
dataSourceFactory, minLoadableRetryCount, new HlsPlaylistParser()),
/* allowChunklessPreparation= */ false,
/* tag= */ null);
if (eventHandler != null && eventListener != null) {
Expand All @@ -323,25 +354,23 @@ private HlsMediaSource(
HlsExtractorFactory extractorFactory,
CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory,
int minLoadableRetryCount,
ParsingLoadable.Parser<HlsPlaylist> playlistParser,
HlsPlaylistTracker playlistTracker,
boolean allowChunklessPreparation,
@Nullable Object tag) {
this.manifestUri = manifestUri;
this.dataSourceFactory = dataSourceFactory;
this.extractorFactory = extractorFactory;
this.compositeSequenceableLoaderFactory = compositeSequenceableLoaderFactory;
this.minLoadableRetryCount = minLoadableRetryCount;
this.playlistParser = playlistParser;
this.playlistTracker = playlistTracker;
this.allowChunklessPreparation = allowChunklessPreparation;
this.tag = tag;
}

@Override
public void prepareSourceInternal(ExoPlayer player, boolean isTopLevelSource) {
EventDispatcher eventDispatcher = createEventDispatcher(/* mediaPeriodId= */ null);
playlistTracker = new HlsPlaylistTracker(manifestUri, dataSourceFactory, eventDispatcher,
minLoadableRetryCount, this, playlistParser);
playlistTracker.start();
playlistTracker.start(manifestUri, eventDispatcher, /* listener= */ this);
}

@Override
Expand Down Expand Up @@ -373,7 +402,6 @@ public void releasePeriod(MediaPeriod mediaPeriod) {
public void releaseSourceInternal() {
if (playlistTracker != null) {
playlistTracker.release();
playlistTracker = null;
}
}

Expand Down

0 comments on commit f1fe1c4

Please sign in to comment.