@Override public int onLoadError(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error) { boolean isFatal = error instanceof ParserException; eventDispatcher.loadError(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded(), error, isFatal); if (isFatal) { return Loader.DONT_RETRY_FATAL; } boolean shouldRetry = true; if (ChunkedTrackBlacklistUtil.shouldBlacklist(error)) { blacklistUntilMs = SystemClock.elapsedRealtime() + ChunkedTrackBlacklistUtil.DEFAULT_TRACK_BLACKLIST_MS; notifyPlaylistBlacklisting(playlistUrl, ChunkedTrackBlacklistUtil.DEFAULT_TRACK_BLACKLIST_MS); shouldRetry = primaryHlsUrl == playlistUrl && !maybeSelectNewPrimaryUrl(); } return shouldRetry ? Loader.RETRY : Loader.DONT_RETRY; }
/** * @param initialPlaylistUri Uri for the initial playlist of the stream. Can refer a media * playlist or a master playlist. * @param dataSourceFactory A factory for {@link DataSource} instances. * @param eventDispatcher A dispatcher to notify of events. * @param minRetryCount The minimum number of times loads must be retried before * {@link #maybeThrowPlaylistRefreshError(HlsUrl)} and * {@link #maybeThrowPrimaryPlaylistRefreshError()} propagate any loading errors. * @param primaryPlaylistListener A callback for the primary playlist change events. */ public HlsPlaylistTracker(Uri initialPlaylistUri, HlsDataSourceFactory dataSourceFactory, EventDispatcher eventDispatcher, int minRetryCount, PrimaryPlaylistListener primaryPlaylistListener, ParsingLoadable.Parser<HlsPlaylist> playlistParser) { this.initialPlaylistUri = initialPlaylistUri; this.dataSourceFactory = dataSourceFactory; this.eventDispatcher = eventDispatcher; this.minRetryCount = minRetryCount; this.primaryPlaylistListener = primaryPlaylistListener; this.playlistParser = playlistParser; listeners = new ArrayList<>(); initialPlaylistLoader = new Loader("HlsPlaylistTracker:MasterPlaylist"); playlistBundles = new IdentityHashMap<>(); playlistRefreshHandler = new Handler(); }
private SsMediaSource(SsManifest manifest, Uri manifestUri, DataSource.Factory manifestDataSourceFactory, ParsingLoadable.Parser<? extends SsManifest> manifestParser, SsChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount, long livePresentationDelayMs, Handler eventHandler, MediaSourceEventListener eventListener) { Assertions.checkState(manifest == null || !manifest.isLive); this.manifest = manifest; this.manifestUri = manifestUri == null ? null : Util.toLowerInvariant(manifestUri.getLastPathSegment()).matches("manifest(\\(.+\\))?") ? manifestUri : Uri.withAppendedPath(manifestUri, "Manifest"); this.manifestDataSourceFactory = manifestDataSourceFactory; this.manifestParser = manifestParser; this.chunkSourceFactory = chunkSourceFactory; this.minLoadableRetryCount = minLoadableRetryCount; this.livePresentationDelayMs = livePresentationDelayMs; this.eventDispatcher = new EventDispatcher(eventHandler, eventListener); mediaPeriods = new ArrayList<>(); }
/** * Starts tracking all the playlists related to the provided Uri. */ public void start() { ParsingLoadable<HlsPlaylist> masterPlaylistLoadable = new ParsingLoadable<>( dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST), initialPlaylistUri, C.DATA_TYPE_MANIFEST, playlistParser); initialPlaylistLoader.startLoading(masterPlaylistLoadable, this, minRetryCount); }
@Override public void onLoadCompleted(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs, long loadDurationMs) { HlsPlaylist result = loadable.getResult(); HlsMasterPlaylist masterPlaylist; boolean isMediaPlaylist = result instanceof HlsMediaPlaylist; if (isMediaPlaylist) { masterPlaylist = HlsMasterPlaylist.createSingleVariantMasterPlaylist(result.baseUri); } else /* result instanceof HlsMasterPlaylist */ { masterPlaylist = (HlsMasterPlaylist) result; } this.masterPlaylist = masterPlaylist; primaryHlsUrl = masterPlaylist.variants.get(0); ArrayList<HlsUrl> urls = new ArrayList<>(); urls.addAll(masterPlaylist.variants); urls.addAll(masterPlaylist.audios); urls.addAll(masterPlaylist.subtitles); createBundles(urls); MediaPlaylistBundle primaryBundle = playlistBundles.get(primaryHlsUrl); if (isMediaPlaylist) { // We don't need to load the playlist again. We can use the same result. primaryBundle.processLoadedPlaylist((HlsMediaPlaylist) result); } else { primaryBundle.loadPlaylist(); } eventDispatcher.loadCompleted(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); }
@Override public int onLoadError(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error) { boolean isFatal = error instanceof ParserException; eventDispatcher.loadError(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded(), error, isFatal); return isFatal ? Loader.DONT_RETRY_FATAL : Loader.RETRY; }
public MediaPlaylistBundle(HlsUrl playlistUrl, long initialLastSnapshotAccessTimeMs) { this.playlistUrl = playlistUrl; lastSnapshotAccessTimeMs = initialLastSnapshotAccessTimeMs; mediaPlaylistLoader = new Loader("HlsPlaylistTracker:MediaPlaylist"); mediaPlaylistLoadable = new ParsingLoadable<>( dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST), UriUtil.resolveToUri(masterPlaylist.baseUri, playlistUrl.url), C.DATA_TYPE_MANIFEST, playlistParser); }
@Override public void onLoadCompleted(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs, long loadDurationMs) { HlsPlaylist result = loadable.getResult(); if (result instanceof HlsMediaPlaylist) { processLoadedPlaylist((HlsMediaPlaylist) result); eventDispatcher.loadCompleted(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); } else { onLoadError(loadable, elapsedRealtimeMs, loadDurationMs, new ParserException("Loaded playlist has unexpected type.")); } }
@Override public void onLoadCompleted(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs, long loadDurationMs) { processLoadedPlaylist((HlsMediaPlaylist) loadable.getResult()); eventDispatcher.loadCompleted(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); }
int onManifestLoadError(ParsingLoadable<DashManifest> loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error) { boolean isFatal = error instanceof ParserException; eventDispatcher.loadError(loadable.dataSpec, loadable.type, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded(), error, isFatal); return isFatal ? Loader.DONT_RETRY_FATAL : Loader.RETRY; }
int onUtcTimestampLoadError(ParsingLoadable<Long> loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error) { eventDispatcher.loadError(loadable.dataSpec, loadable.type, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded(), error, true); onUtcTimestampResolutionError(error); return Loader.DONT_RETRY; }
private void startLoadingManifest() { Uri manifestUri; synchronized (manifestUriLock) { manifestUri = this.manifestUri; } startLoading(new ParsingLoadable<>(dataSource, manifestUri, C.DATA_TYPE_MANIFEST, manifestParser), manifestCallback, minLoadableRetryCount); }
@Override public void onLoadCompleted(ParsingLoadable<SsManifest> loadable, long elapsedRealtimeMs, long loadDurationMs) { eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); manifest = loadable.getResult(); manifestLoadStartTimestamp = elapsedRealtimeMs - loadDurationMs; processManifest(); scheduleManifestRefresh(); }
@Override public int onLoadError(ParsingLoadable<SsManifest> loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error) { boolean isFatal = error instanceof ParserException; eventDispatcher.loadError(loadable.dataSpec, loadable.type, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded(), error, isFatal); return isFatal ? Loader.DONT_RETRY_FATAL : Loader.RETRY; }
@Override public void prepare(Callback callback) { this.callback = callback; ParsingLoadable<HlsPlaylist> loadable = new ParsingLoadable<>( dataSourceFactory.createDataSource(), manifestUri, C.DATA_TYPE_MANIFEST, manifestParser); long elapsedRealtimeMs = manifestFetcher.startLoading(loadable, this, minLoadableRetryCount); eventDispatcher.loadStarted(loadable.dataSpec, loadable.type, elapsedRealtimeMs); }
@Override public void onLoadCompleted(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs, long loadDurationMs) { eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); playlist = loadable.getResult(); buildAndPrepareSampleStreamWrappers(); }
@Override public int onLoadError(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error) { boolean isFatal = error instanceof ParserException; eventDispatcher.loadError(loadable.dataSpec, loadable.type, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded(), error, isFatal); return isFatal ? Loader.DONT_RETRY_FATAL : Loader.RETRY; }
public MediaPlaylistBundle(HlsUrl playlistUrl) { this.playlistUrl = playlistUrl; mediaPlaylistLoader = new Loader("HlsPlaylistTracker:MediaPlaylist"); mediaPlaylistLoadable = new ParsingLoadable<>( dataSourceFactory.createDataSource(C.DATA_TYPE_MANIFEST), UriUtil.resolveToUri(masterPlaylist.baseUri, playlistUrl.url), C.DATA_TYPE_MANIFEST, playlistParser); }
@Override public void onLoadCompleted(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs, long loadDurationMs) { HlsPlaylist result = loadable.getResult(); if (result instanceof HlsMediaPlaylist) { processLoadedPlaylist((HlsMediaPlaylist) result); eventDispatcher.loadCompleted(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); } else { playlistError = new ParserException("Loaded playlist has unexpected type."); } }
@Override public int onLoadError(ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs, long loadDurationMs, IOException error) { boolean isFatal = error instanceof ParserException; eventDispatcher.loadError(loadable.dataSpec, C.DATA_TYPE_MANIFEST, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded(), error, isFatal); if (isFatal) { return Loader.DONT_RETRY_FATAL; } boolean shouldRetry = true; if (ChunkedTrackBlacklistUtil.shouldBlacklist(error)) { shouldRetry = blacklistPlaylist(); } return shouldRetry ? Loader.RETRY : Loader.DONT_RETRY; }
private HlsPlaylist loadManifest(DataSource dataSource, Uri uri) throws IOException { DataSpec dataSpec = new DataSpec(uri, DataSpec.FLAG_ALLOW_CACHING_UNKNOWN_LENGTH | DataSpec.FLAG_ALLOW_GZIP); ParsingLoadable<HlsPlaylist> loadable = new ParsingLoadable<>(dataSource, dataSpec, C.DATA_TYPE_MANIFEST, new HlsPlaylistParser()); loadable.load(); return loadable.getResult(); }
/** * Loads a DASH manifest. * * @param dataSource The {@link HttpDataSource} from which the manifest should be read. * @param uri The {@link Uri} of the manifest to be read. * @return An instance of {@link DashManifest}. * @throws IOException Thrown when there is an error while loading. */ public static DashManifest loadManifest(DataSource dataSource, Uri uri) throws IOException { DataSpec dataSpec = new DataSpec(uri, DataSpec.FLAG_ALLOW_CACHING_UNKNOWN_LENGTH | DataSpec.FLAG_ALLOW_GZIP); ParsingLoadable<DashManifest> loadable = new ParsingLoadable<>(dataSource, dataSpec, C.DATA_TYPE_MANIFEST, new DashManifestParser()); loadable.load(); return loadable.getResult(); }
private DashMediaSource(DashManifest manifest, Uri manifestUri, DataSource.Factory manifestDataSourceFactory, ParsingLoadable.Parser<? extends DashManifest> manifestParser, DashChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount, long livePresentationDelayMs, Handler eventHandler, MediaSourceEventListener eventListener) { this.manifest = manifest; this.manifestUri = manifestUri; this.manifestDataSourceFactory = manifestDataSourceFactory; this.manifestParser = manifestParser; this.chunkSourceFactory = chunkSourceFactory; this.minLoadableRetryCount = minLoadableRetryCount; this.livePresentationDelayMs = livePresentationDelayMs; sideloadedManifest = manifest != null; eventDispatcher = new EventDispatcher(eventHandler, eventListener); manifestUriLock = new Object(); periodsById = new SparseArray<>(); if (sideloadedManifest) { Assertions.checkState(!manifest.dynamic); manifestCallback = null; refreshManifestRunnable = null; simulateManifestRefreshRunnable = null; } else { manifestCallback = new ManifestCallback(); refreshManifestRunnable = new Runnable() { @Override public void run() { startLoadingManifest(); } }; simulateManifestRefreshRunnable = new Runnable() { @Override public void run() { processManifest(false); } }; } }