mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Rework HlsPlaylist attribute inheritance
The reason for the change is that variable substititution requires master playlist variable definitions at the moment of parsing. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=208997963
This commit is contained in:
parent
7a34869f9a
commit
4530944ed7
7 changed files with 162 additions and 61 deletions
|
|
@ -36,6 +36,7 @@ import com.google.android.exoplayer2.source.hls.playlist.DefaultHlsPlaylistTrack
|
||||||
import com.google.android.exoplayer2.source.hls.playlist.HlsMediaPlaylist;
|
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.HlsPlaylist;
|
||||||
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParser;
|
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParser;
|
||||||
|
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParserFactory;
|
||||||
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker;
|
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistTracker;
|
||||||
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.DataSource;
|
||||||
|
|
@ -171,7 +172,11 @@ public final class HlsMediaSource extends BaseMediaSource
|
||||||
* @param playlistParser A {@link ParsingLoadable.Parser} for HLS playlists.
|
* @param playlistParser A {@link ParsingLoadable.Parser} for HLS playlists.
|
||||||
* @return This factory, for convenience.
|
* @return This factory, for convenience.
|
||||||
* @throws IllegalStateException If one of the {@code create} methods has already been called.
|
* @throws IllegalStateException If one of the {@code create} methods has already been called.
|
||||||
|
* @deprecated Use {@link #setPlaylistTracker(HlsPlaylistTracker)} instead. Using this method
|
||||||
|
* prevents support for attributes that are carried over from the master playlist to the
|
||||||
|
* media playlists.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public Factory setPlaylistParser(ParsingLoadable.Parser<HlsPlaylist> playlistParser) {
|
public Factory setPlaylistParser(ParsingLoadable.Parser<HlsPlaylist> playlistParser) {
|
||||||
Assertions.checkState(!isCreateCalled);
|
Assertions.checkState(!isCreateCalled);
|
||||||
Assertions.checkState(playlistTracker == null, "A playlist tracker has already been set.");
|
Assertions.checkState(playlistTracker == null, "A playlist tracker has already been set.");
|
||||||
|
|
@ -239,11 +244,15 @@ public final class HlsMediaSource extends BaseMediaSource
|
||||||
public HlsMediaSource createMediaSource(Uri playlistUri) {
|
public HlsMediaSource createMediaSource(Uri playlistUri) {
|
||||||
isCreateCalled = true;
|
isCreateCalled = true;
|
||||||
if (playlistTracker == null) {
|
if (playlistTracker == null) {
|
||||||
|
if (playlistParser == null) {
|
||||||
playlistTracker =
|
playlistTracker =
|
||||||
new DefaultHlsPlaylistTracker(
|
new DefaultHlsPlaylistTracker(
|
||||||
hlsDataSourceFactory,
|
hlsDataSourceFactory, loadErrorHandlingPolicy, HlsPlaylistParserFactory.DEFAULT);
|
||||||
loadErrorHandlingPolicy,
|
} else {
|
||||||
playlistParser != null ? playlistParser : new HlsPlaylistParser());
|
playlistTracker =
|
||||||
|
new DefaultHlsPlaylistTracker(
|
||||||
|
hlsDataSourceFactory, loadErrorHandlingPolicy, playlistParser);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return new HlsMediaSource(
|
return new HlsMediaSource(
|
||||||
playlistUri,
|
playlistUri,
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package com.google.android.exoplayer2.source.hls.playlist;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
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.ParserException;
|
import com.google.android.exoplayer2.ParserException;
|
||||||
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
|
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
|
||||||
|
|
@ -47,18 +48,19 @@ public final class DefaultHlsPlaylistTracker
|
||||||
private static final double PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT = 3.5;
|
private static final double PLAYLIST_STUCK_TARGET_DURATION_COEFFICIENT = 3.5;
|
||||||
|
|
||||||
private final HlsDataSourceFactory dataSourceFactory;
|
private final HlsDataSourceFactory dataSourceFactory;
|
||||||
private final ParsingLoadable.Parser<HlsPlaylist> playlistParser;
|
private final HlsPlaylistParserFactory playlistParserFactory;
|
||||||
private final LoadErrorHandlingPolicy loadErrorHandlingPolicy;
|
private final LoadErrorHandlingPolicy loadErrorHandlingPolicy;
|
||||||
private final IdentityHashMap<HlsUrl, MediaPlaylistBundle> playlistBundles;
|
private final IdentityHashMap<HlsUrl, MediaPlaylistBundle> playlistBundles;
|
||||||
private final List<PlaylistEventListener> listeners;
|
private final List<PlaylistEventListener> listeners;
|
||||||
|
|
||||||
private EventDispatcher eventDispatcher;
|
private @Nullable ParsingLoadable.Parser<HlsPlaylist> mediaPlaylistParser;
|
||||||
private Loader initialPlaylistLoader;
|
private @Nullable EventDispatcher eventDispatcher;
|
||||||
private Handler playlistRefreshHandler;
|
private @Nullable Loader initialPlaylistLoader;
|
||||||
private PrimaryPlaylistListener primaryPlaylistListener;
|
private @Nullable Handler playlistRefreshHandler;
|
||||||
private HlsMasterPlaylist masterPlaylist;
|
private @Nullable PrimaryPlaylistListener primaryPlaylistListener;
|
||||||
private HlsUrl primaryHlsUrl;
|
private @Nullable HlsMasterPlaylist masterPlaylist;
|
||||||
private HlsMediaPlaylist primaryUrlSnapshot;
|
private @Nullable HlsUrl primaryHlsUrl;
|
||||||
|
private @Nullable HlsMediaPlaylist primaryUrlSnapshot;
|
||||||
private boolean isLive;
|
private boolean isLive;
|
||||||
private long initialStartTimeUs;
|
private long initialStartTimeUs;
|
||||||
|
|
||||||
|
|
@ -66,13 +68,30 @@ public final class DefaultHlsPlaylistTracker
|
||||||
* @param dataSourceFactory A factory for {@link DataSource} instances.
|
* @param dataSourceFactory A factory for {@link DataSource} instances.
|
||||||
* @param loadErrorHandlingPolicy The {@link LoadErrorHandlingPolicy}.
|
* @param loadErrorHandlingPolicy The {@link LoadErrorHandlingPolicy}.
|
||||||
* @param playlistParser A {@link ParsingLoadable.Parser} for HLS playlists.
|
* @param playlistParser A {@link ParsingLoadable.Parser} for HLS playlists.
|
||||||
|
* @deprecated Use {@link #DefaultHlsPlaylistTracker(HlsDataSourceFactory,
|
||||||
|
* LoadErrorHandlingPolicy, HlsPlaylistParserFactory)} instead. Using this constructor
|
||||||
|
* prevents support for attributes that are carried over from the master playlist to the media
|
||||||
|
* playlists.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public DefaultHlsPlaylistTracker(
|
public DefaultHlsPlaylistTracker(
|
||||||
HlsDataSourceFactory dataSourceFactory,
|
HlsDataSourceFactory dataSourceFactory,
|
||||||
LoadErrorHandlingPolicy loadErrorHandlingPolicy,
|
LoadErrorHandlingPolicy loadErrorHandlingPolicy,
|
||||||
ParsingLoadable.Parser<HlsPlaylist> playlistParser) {
|
ParsingLoadable.Parser<HlsPlaylist> playlistParser) {
|
||||||
|
this(dataSourceFactory, loadErrorHandlingPolicy, createFixedFactory(playlistParser));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dataSourceFactory A factory for {@link DataSource} instances.
|
||||||
|
* @param loadErrorHandlingPolicy The {@link LoadErrorHandlingPolicy}.
|
||||||
|
* @param playlistParserFactory An {@link HlsPlaylistParserFactory}.
|
||||||
|
*/
|
||||||
|
public DefaultHlsPlaylistTracker(
|
||||||
|
HlsDataSourceFactory dataSourceFactory,
|
||||||
|
LoadErrorHandlingPolicy loadErrorHandlingPolicy,
|
||||||
|
HlsPlaylistParserFactory playlistParserFactory) {
|
||||||
this.dataSourceFactory = dataSourceFactory;
|
this.dataSourceFactory = dataSourceFactory;
|
||||||
this.playlistParser = playlistParser;
|
this.playlistParserFactory = playlistParserFactory;
|
||||||
this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
|
this.loadErrorHandlingPolicy = loadErrorHandlingPolicy;
|
||||||
listeners = new ArrayList<>();
|
listeners = new ArrayList<>();
|
||||||
playlistBundles = new IdentityHashMap<>();
|
playlistBundles = new IdentityHashMap<>();
|
||||||
|
|
@ -94,7 +113,7 @@ public final class DefaultHlsPlaylistTracker
|
||||||
dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST),
|
dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST),
|
||||||
initialPlaylistUri,
|
initialPlaylistUri,
|
||||||
C.DATA_TYPE_MANIFEST,
|
C.DATA_TYPE_MANIFEST,
|
||||||
playlistParser);
|
playlistParserFactory.createPlaylistParser());
|
||||||
Assertions.checkState(initialPlaylistLoader == null);
|
Assertions.checkState(initialPlaylistLoader == null);
|
||||||
initialPlaylistLoader = new Loader("DefaultHlsPlaylistTracker:MasterPlaylist");
|
initialPlaylistLoader = new Loader("DefaultHlsPlaylistTracker:MasterPlaylist");
|
||||||
long elapsedRealtime =
|
long elapsedRealtime =
|
||||||
|
|
@ -198,6 +217,7 @@ public final class DefaultHlsPlaylistTracker
|
||||||
masterPlaylist = (HlsMasterPlaylist) result;
|
masterPlaylist = (HlsMasterPlaylist) result;
|
||||||
}
|
}
|
||||||
this.masterPlaylist = masterPlaylist;
|
this.masterPlaylist = masterPlaylist;
|
||||||
|
mediaPlaylistParser = playlistParserFactory.createPlaylistParser(masterPlaylist);
|
||||||
primaryHlsUrl = masterPlaylist.variants.get(0);
|
primaryHlsUrl = masterPlaylist.variants.get(0);
|
||||||
ArrayList<HlsUrl> urls = new ArrayList<>();
|
ArrayList<HlsUrl> urls = new ArrayList<>();
|
||||||
urls.addAll(masterPlaylist.variants);
|
urls.addAll(masterPlaylist.variants);
|
||||||
|
|
@ -420,7 +440,7 @@ public final class DefaultHlsPlaylistTracker
|
||||||
dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST),
|
dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST),
|
||||||
UriUtil.resolveToUri(masterPlaylist.baseUri, playlistUrl.url),
|
UriUtil.resolveToUri(masterPlaylist.baseUri, playlistUrl.url),
|
||||||
C.DATA_TYPE_MANIFEST,
|
C.DATA_TYPE_MANIFEST,
|
||||||
playlistParser);
|
mediaPlaylistParser);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HlsMediaPlaylist getPlaylistSnapshot() {
|
public HlsMediaPlaylist getPlaylistSnapshot() {
|
||||||
|
|
@ -569,9 +589,6 @@ public final class DefaultHlsPlaylistTracker
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processLoadedPlaylist(HlsMediaPlaylist loadedPlaylist, long loadDurationMs) {
|
private void processLoadedPlaylist(HlsMediaPlaylist loadedPlaylist, long loadDurationMs) {
|
||||||
// Update the loaded playlist with any inheritable information from the master playlist.
|
|
||||||
loadedPlaylist = loadedPlaylist.copyWithMasterPlaylistInfo(masterPlaylist);
|
|
||||||
|
|
||||||
HlsMediaPlaylist oldPlaylist = playlistSnapshot;
|
HlsMediaPlaylist oldPlaylist = playlistSnapshot;
|
||||||
long currentTimeMs = SystemClock.elapsedRealtime();
|
long currentTimeMs = SystemClock.elapsedRealtime();
|
||||||
lastSnapshotLoadMs = currentTimeMs;
|
lastSnapshotLoadMs = currentTimeMs;
|
||||||
|
|
@ -630,4 +647,26 @@ public final class DefaultHlsPlaylistTracker
|
||||||
return primaryHlsUrl == playlistUrl && !maybeSelectNewPrimaryUrl();
|
return primaryHlsUrl == playlistUrl && !maybeSelectNewPrimaryUrl();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a factory which always returns the given playlist parser.
|
||||||
|
*
|
||||||
|
* @param playlistParser The parser to return.
|
||||||
|
* @return A factory which always returns the given playlist parser.
|
||||||
|
*/
|
||||||
|
private static HlsPlaylistParserFactory createFixedFactory(
|
||||||
|
ParsingLoadable.Parser<HlsPlaylist> playlistParser) {
|
||||||
|
return new HlsPlaylistParserFactory() {
|
||||||
|
@Override
|
||||||
|
public ParsingLoadable.Parser<HlsPlaylist> createPlaylistParser() {
|
||||||
|
return playlistParser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParsingLoadable.Parser<HlsPlaylist> createPlaylistParser(
|
||||||
|
HlsMasterPlaylist masterPlaylist) {
|
||||||
|
return playlistParser;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,18 @@ import java.util.List;
|
||||||
/** Represents an HLS master playlist. */
|
/** Represents an HLS master playlist. */
|
||||||
public final class HlsMasterPlaylist extends HlsPlaylist {
|
public final class HlsMasterPlaylist extends HlsPlaylist {
|
||||||
|
|
||||||
|
/** Represents an empty master playlist, from which no attributes can be inherited. */
|
||||||
|
public static final HlsMasterPlaylist EMPTY =
|
||||||
|
new HlsMasterPlaylist(
|
||||||
|
/* baseUri= */ "",
|
||||||
|
/* tags= */ Collections.emptyList(),
|
||||||
|
/* variants= */ Collections.emptyList(),
|
||||||
|
/* audios= */ Collections.emptyList(),
|
||||||
|
/* subtitles= */ Collections.emptyList(),
|
||||||
|
/* muxedAudioFormat= */ null,
|
||||||
|
/* muxedCaptionFormats= */ Collections.emptyList(),
|
||||||
|
/* hasIndependentSegments= */ false);
|
||||||
|
|
||||||
public static final int GROUP_INDEX_VARIANT = 0;
|
public static final int GROUP_INDEX_VARIANT = 0;
|
||||||
public static final int GROUP_INDEX_AUDIO = 1;
|
public static final int GROUP_INDEX_AUDIO = 1;
|
||||||
public static final int GROUP_INDEX_SUBTITLE = 2;
|
public static final int GROUP_INDEX_SUBTITLE = 2;
|
||||||
|
|
|
||||||
|
|
@ -336,40 +336,6 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||||
segments);
|
segments);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a playlist identical to this one, except for adding any inheritable attributes from the
|
|
||||||
* provided {@link HlsMasterPlaylist}.
|
|
||||||
*
|
|
||||||
* <p>The inheritable attributes are:
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li>{@link #hasIndependentSegments}.
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @return An identical playlist including the inheritable attributes from {@code masterPlaylist}.
|
|
||||||
*/
|
|
||||||
public HlsMediaPlaylist copyWithMasterPlaylistInfo(HlsMasterPlaylist masterPlaylist) {
|
|
||||||
if (hasIndependentSegments || !masterPlaylist.hasIndependentSegments) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
return new HlsMediaPlaylist(
|
|
||||||
playlistType,
|
|
||||||
baseUri,
|
|
||||||
tags,
|
|
||||||
startOffsetUs,
|
|
||||||
startTimeUs,
|
|
||||||
hasDiscontinuitySequence,
|
|
||||||
discontinuitySequence,
|
|
||||||
mediaSequence,
|
|
||||||
version,
|
|
||||||
targetDurationUs,
|
|
||||||
hasIndependentSegments || masterPlaylist.hasIndependentSegments,
|
|
||||||
hasEndTag,
|
|
||||||
hasProgramDateTime,
|
|
||||||
protectionSchemes,
|
|
||||||
segments);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a playlist identical to this one except that an end tag is added. If an end tag is
|
* Returns a playlist identical to this one except that an end tag is added. If an end tag is
|
||||||
* already present then the playlist will return itself.
|
* already present then the playlist will return itself.
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,26 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
private static final Pattern REGEX_DEFAULT = compileBooleanAttrPattern("DEFAULT");
|
private static final Pattern REGEX_DEFAULT = compileBooleanAttrPattern("DEFAULT");
|
||||||
private static final Pattern REGEX_FORCED = compileBooleanAttrPattern("FORCED");
|
private static final Pattern REGEX_FORCED = compileBooleanAttrPattern("FORCED");
|
||||||
|
|
||||||
|
private final HlsMasterPlaylist masterPlaylist;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance where media playlists are parsed without inheriting attributes from a
|
||||||
|
* master playlist.
|
||||||
|
*/
|
||||||
|
public HlsPlaylistParser() {
|
||||||
|
this(HlsMasterPlaylist.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance where parsed media playlists inherit attributes from the given master
|
||||||
|
* playlist.
|
||||||
|
*
|
||||||
|
* @param masterPlaylist The master playlist from which media playlists will inherit attributes.
|
||||||
|
*/
|
||||||
|
public HlsPlaylistParser(HlsMasterPlaylist masterPlaylist) {
|
||||||
|
this.masterPlaylist = masterPlaylist;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HlsPlaylist parse(Uri uri, InputStream inputStream) throws IOException {
|
public HlsPlaylist parse(Uri uri, InputStream inputStream) throws IOException {
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||||
|
|
@ -174,7 +194,8 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
|| line.equals(TAG_DISCONTINUITY_SEQUENCE)
|
|| line.equals(TAG_DISCONTINUITY_SEQUENCE)
|
||||||
|| line.equals(TAG_ENDLIST)) {
|
|| line.equals(TAG_ENDLIST)) {
|
||||||
extraLines.add(line);
|
extraLines.add(line);
|
||||||
return parseMediaPlaylist(new LineIterator(extraLines, reader), uri.toString());
|
return parseMediaPlaylist(
|
||||||
|
masterPlaylist, new LineIterator(extraLines, reader), uri.toString());
|
||||||
} else {
|
} else {
|
||||||
extraLines.add(line);
|
extraLines.add(line);
|
||||||
}
|
}
|
||||||
|
|
@ -402,14 +423,14 @@ public final class HlsPlaylistParser implements ParsingLoadable.Parser<HlsPlayli
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HlsMediaPlaylist parseMediaPlaylist(LineIterator iterator, String baseUri)
|
private static HlsMediaPlaylist parseMediaPlaylist(
|
||||||
throws IOException {
|
HlsMasterPlaylist masterPlaylist, LineIterator iterator, String baseUri) throws IOException {
|
||||||
@HlsMediaPlaylist.PlaylistType int playlistType = HlsMediaPlaylist.PLAYLIST_TYPE_UNKNOWN;
|
@HlsMediaPlaylist.PlaylistType int playlistType = HlsMediaPlaylist.PLAYLIST_TYPE_UNKNOWN;
|
||||||
long startOffsetUs = C.TIME_UNSET;
|
long startOffsetUs = C.TIME_UNSET;
|
||||||
long mediaSequence = 0;
|
long mediaSequence = 0;
|
||||||
int version = 1; // Default version == 1.
|
int version = 1; // Default version == 1.
|
||||||
long targetDurationUs = C.TIME_UNSET;
|
long targetDurationUs = C.TIME_UNSET;
|
||||||
boolean hasIndependentSegmentsTag = false;
|
boolean hasIndependentSegmentsTag = masterPlaylist.hasIndependentSegments;
|
||||||
boolean hasEndTag = false;
|
boolean hasEndTag = false;
|
||||||
Segment initializationSegment = null;
|
Segment initializationSegment = null;
|
||||||
List<Segment> segments = new ArrayList<>();
|
List<Segment> segments = new ArrayList<>();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.google.android.exoplayer2.source.hls.playlist;
|
||||||
|
|
||||||
|
import com.google.android.exoplayer2.upstream.ParsingLoadable;
|
||||||
|
|
||||||
|
/** Factory for {@link HlsPlaylist} parsers. */
|
||||||
|
public interface HlsPlaylistParserFactory {
|
||||||
|
|
||||||
|
HlsPlaylistParserFactory DEFAULT =
|
||||||
|
new HlsPlaylistParserFactory() {
|
||||||
|
@Override
|
||||||
|
public ParsingLoadable.Parser<HlsPlaylist> createPlaylistParser() {
|
||||||
|
return new HlsPlaylistParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParsingLoadable.Parser<HlsPlaylist> createPlaylistParser(
|
||||||
|
HlsMasterPlaylist masterPlaylist) {
|
||||||
|
return new HlsPlaylistParser(masterPlaylist);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a stand-alone playlist parser. Playlists parsed by the returned parser do not inherit
|
||||||
|
* any attributes from other playlists.
|
||||||
|
*/
|
||||||
|
ParsingLoadable.Parser<HlsPlaylist> createPlaylistParser();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a playlist parser for playlists that were referenced by the given {@link
|
||||||
|
* HlsMasterPlaylist}. Returned {@link HlsMediaPlaylist} instances may inherit attributes from
|
||||||
|
* {@code masterPlaylist}.
|
||||||
|
*
|
||||||
|
* @param masterPlaylist The master playlist that referenced any parsed media playlists.
|
||||||
|
* @return A parser for HLS playlists.
|
||||||
|
*/
|
||||||
|
ParsingLoadable.Parser<HlsPlaylist> createPlaylistParser(HlsMasterPlaylist masterPlaylist);
|
||||||
|
}
|
||||||
|
|
@ -383,10 +383,11 @@ public class HlsMediaPlaylistParserTest {
|
||||||
+ "#EXTINF:5.005,\n"
|
+ "#EXTINF:5.005,\n"
|
||||||
+ "02/00/47.ts\n";
|
+ "02/00/47.ts\n";
|
||||||
InputStream inputStream = new ByteArrayInputStream(Util.getUtf8Bytes(playlistString));
|
InputStream inputStream = new ByteArrayInputStream(Util.getUtf8Bytes(playlistString));
|
||||||
HlsMediaPlaylist playlist =
|
HlsMediaPlaylist standalonePlaylist =
|
||||||
(HlsMediaPlaylist) new HlsPlaylistParser().parse(playlistUri, inputStream);
|
(HlsMediaPlaylist) new HlsPlaylistParser().parse(playlistUri, inputStream);
|
||||||
assertThat(playlist.hasIndependentSegments).isFalse();
|
assertThat(standalonePlaylist.hasIndependentSegments).isFalse();
|
||||||
|
|
||||||
|
inputStream.reset();
|
||||||
HlsMasterPlaylist masterPlaylist =
|
HlsMasterPlaylist masterPlaylist =
|
||||||
new HlsMasterPlaylist(
|
new HlsMasterPlaylist(
|
||||||
/* baseUri= */ "https://example.com/",
|
/* baseUri= */ "https://example.com/",
|
||||||
|
|
@ -397,7 +398,8 @@ public class HlsMediaPlaylistParserTest {
|
||||||
/* muxedAudioFormat= */ null,
|
/* muxedAudioFormat= */ null,
|
||||||
/* muxedCaptionFormats= */ null,
|
/* muxedCaptionFormats= */ null,
|
||||||
/* hasIndependentSegments= */ true);
|
/* hasIndependentSegments= */ true);
|
||||||
|
HlsMediaPlaylist playlistWithInheritance =
|
||||||
assertThat(playlist.copyWithMasterPlaylistInfo(masterPlaylist).hasIndependentSegments).isTrue();
|
(HlsMediaPlaylist) new HlsPlaylistParser(masterPlaylist).parse(playlistUri, inputStream);
|
||||||
|
assertThat(playlistWithInheritance.hasIndependentSegments).isTrue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue