Misc cleanup
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=195552434
This commit is contained in:
parent
dbd768fbd7
commit
051da40dc3
@ -49,14 +49,17 @@ public final class DownloaderConstructorHelper {
|
|||||||
/**
|
/**
|
||||||
* @param cache Cache instance to be used to store downloaded data.
|
* @param cache Cache instance to be used to store downloaded data.
|
||||||
* @param upstreamDataSourceFactory A {@link Factory} for downloading data.
|
* @param upstreamDataSourceFactory A {@link Factory} for downloading data.
|
||||||
* @param cacheReadDataSourceFactory A {@link Factory} for reading data from the cache.
|
* @param cacheReadDataSourceFactory A {@link Factory} for reading data from the cache. If null
|
||||||
* If null, null is passed to {@link Downloader} constructor.
|
* then standard {@link FileDataSource} instances will be used.
|
||||||
* @param cacheWriteDataSinkFactory A {@link DataSink.Factory} for writing data to the cache. If
|
* @param cacheWriteDataSinkFactory A {@link DataSink.Factory} for writing data to the cache. If
|
||||||
* null, null is passed to {@link Downloader} constructor.
|
* null then standard {@link CacheDataSink} instances will be used.
|
||||||
* @param priorityTaskManager If one is given then the download priority is set lower than
|
* @param priorityTaskManager A {@link PriorityTaskManager} to use when downloading. If non-null,
|
||||||
* loading. If null, null is passed to {@link Downloader} constructor.
|
* downloaders will register as tasks with priority {@link C#PRIORITY_DOWNLOAD} whilst
|
||||||
|
* downloading.
|
||||||
*/
|
*/
|
||||||
public DownloaderConstructorHelper(Cache cache, Factory upstreamDataSourceFactory,
|
public DownloaderConstructorHelper(
|
||||||
|
Cache cache,
|
||||||
|
Factory upstreamDataSourceFactory,
|
||||||
@Nullable Factory cacheReadDataSourceFactory,
|
@Nullable Factory cacheReadDataSourceFactory,
|
||||||
@Nullable DataSink.Factory cacheWriteDataSinkFactory,
|
@Nullable DataSink.Factory cacheWriteDataSinkFactory,
|
||||||
@Nullable PriorityTaskManager priorityTaskManager) {
|
@Nullable PriorityTaskManager priorityTaskManager) {
|
||||||
|
@ -18,19 +18,20 @@ package com.google.android.exoplayer2.offline;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A manifest that can generate copies of itself including only the tracks specified by the given
|
* A manifest that can generate copies of itself including only the streams specified by the given
|
||||||
* track keys.
|
* keys.
|
||||||
*
|
*
|
||||||
* @param <T> The manifest type.
|
* @param <T> The manifest type.
|
||||||
* @param <K> The track key type.
|
* @param <K> The stream key type.
|
||||||
*/
|
*/
|
||||||
public interface FilterableManifest<T, K> {
|
public interface FilterableManifest<T, K> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a copy of the manifest including only the tracks specified by the given track keys.
|
* Returns a copy of the manifest including only the streams specified by the given keys. If the
|
||||||
|
* manifest is unchanged then the instance may return itself.
|
||||||
*
|
*
|
||||||
* @param trackKeys A non-empty list of track keys.
|
* @param streamKeys A non-empty list of stream keys.
|
||||||
* @return The filtered manifest.
|
* @return The filtered manifest.
|
||||||
*/
|
*/
|
||||||
T copy(List<K> trackKeys);
|
T copy(List<K> streamKeys);
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
* Base class for multi segment stream downloaders.
|
* Base class for multi segment stream downloaders.
|
||||||
*
|
*
|
||||||
* @param <M> The type of the manifest object.
|
* @param <M> The type of the manifest object.
|
||||||
* @param <K> The type of the track key object.
|
* @param <K> The type of the streams key object.
|
||||||
*/
|
*/
|
||||||
public abstract class SegmentDownloader<M extends FilterableManifest<M, K>, K>
|
public abstract class SegmentDownloader<M extends FilterableManifest<M, K>, K>
|
||||||
implements Downloader {
|
implements Downloader {
|
||||||
@ -68,7 +68,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M, K>, K>
|
|||||||
private final Cache cache;
|
private final Cache cache;
|
||||||
private final CacheDataSource dataSource;
|
private final CacheDataSource dataSource;
|
||||||
private final CacheDataSource offlineDataSource;
|
private final CacheDataSource offlineDataSource;
|
||||||
private final ArrayList<K> keys;
|
private final ArrayList<K> streamKeys;
|
||||||
private final AtomicBoolean isCanceled;
|
private final AtomicBoolean isCanceled;
|
||||||
|
|
||||||
private volatile int totalSegments;
|
private volatile int totalSegments;
|
||||||
@ -77,23 +77,24 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M, K>, K>
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param manifestUri The {@link Uri} of the manifest to be downloaded.
|
* @param manifestUri The {@link Uri} of the manifest to be downloaded.
|
||||||
|
* @param streamKeys Keys defining which streams in the manifest should be selected for download.
|
||||||
|
* If empty, all streams are downloaded.
|
||||||
* @param constructorHelper A {@link DownloaderConstructorHelper} instance.
|
* @param constructorHelper A {@link DownloaderConstructorHelper} instance.
|
||||||
* @param trackKeys Track keys to select when downloading. If empty, all tracks are downloaded.
|
|
||||||
*/
|
*/
|
||||||
public SegmentDownloader(
|
public SegmentDownloader(
|
||||||
Uri manifestUri, DownloaderConstructorHelper constructorHelper, List<K> trackKeys) {
|
Uri manifestUri, List<K> streamKeys, DownloaderConstructorHelper constructorHelper) {
|
||||||
this.manifestUri = manifestUri;
|
this.manifestUri = manifestUri;
|
||||||
|
this.streamKeys = new ArrayList<>(streamKeys);
|
||||||
this.cache = constructorHelper.getCache();
|
this.cache = constructorHelper.getCache();
|
||||||
this.dataSource = constructorHelper.buildCacheDataSource(false);
|
this.dataSource = constructorHelper.buildCacheDataSource(false);
|
||||||
this.offlineDataSource = constructorHelper.buildCacheDataSource(true);
|
this.offlineDataSource = constructorHelper.buildCacheDataSource(true);
|
||||||
this.priorityTaskManager = constructorHelper.getPriorityTaskManager();
|
this.priorityTaskManager = constructorHelper.getPriorityTaskManager();
|
||||||
keys = new ArrayList<>(trackKeys);
|
|
||||||
totalSegments = C.LENGTH_UNSET;
|
totalSegments = C.LENGTH_UNSET;
|
||||||
isCanceled = new AtomicBoolean();
|
isCanceled = new AtomicBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Downloads the selected tracks in the media. If multiple tracks are selected, they are
|
* Downloads the selected streams in the media. If multiple streams are selected, they are
|
||||||
* downloaded in sync with one another.
|
* downloaded in sync with one another.
|
||||||
*
|
*
|
||||||
* @throws IOException Thrown when there is an error downloading.
|
* @throws IOException Thrown when there is an error downloading.
|
||||||
@ -202,8 +203,8 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M, K>, K>
|
|||||||
/** Initializes the download, returning a list of {@link Segment}s that need to be downloaded. */
|
/** Initializes the download, returning a list of {@link Segment}s that need to be downloaded. */
|
||||||
private List<Segment> initDownload() throws IOException, InterruptedException {
|
private List<Segment> initDownload() throws IOException, InterruptedException {
|
||||||
M manifest = getManifest(dataSource, manifestUri);
|
M manifest = getManifest(dataSource, manifestUri);
|
||||||
if (!keys.isEmpty()) {
|
if (!streamKeys.isEmpty()) {
|
||||||
manifest = manifest.copy(keys);
|
manifest = manifest.copy(streamKeys);
|
||||||
}
|
}
|
||||||
List<Segment> segments = getSegments(dataSource, manifest, /* allowIncompleteList= */ false);
|
List<Segment> segments = getSegments(dataSource, manifest, /* allowIncompleteList= */ false);
|
||||||
CachingCounters cachingCounters = new CachingCounters();
|
CachingCounters cachingCounters = new CachingCounters();
|
||||||
|
@ -19,10 +19,13 @@ package com.google.android.exoplayer2.offline;
|
|||||||
* Identifies a given track by the index of the containing period, the index of the containing group
|
* Identifies a given track by the index of the containing period, the index of the containing group
|
||||||
* within the period, and the index of the track within the group.
|
* within the period, and the index of the track within the group.
|
||||||
*/
|
*/
|
||||||
public class TrackKey {
|
public final class TrackKey {
|
||||||
|
|
||||||
|
/** The period index. */
|
||||||
public final int periodIndex;
|
public final int periodIndex;
|
||||||
|
/** The group index. */
|
||||||
public final int groupIndex;
|
public final int groupIndex;
|
||||||
|
/** The track index. */
|
||||||
public final int trackIndex;
|
public final int trackIndex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -122,17 +122,9 @@ public class DashManifest implements FilterableManifest<DashManifest, Representa
|
|||||||
return C.msToUs(getPeriodDurationMs(index));
|
return C.msToUs(getPeriodDurationMs(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a copy of this manifest which includes only the representations identified by the given
|
|
||||||
* keys.
|
|
||||||
*
|
|
||||||
* @param representationKeys List of keys for the representations to be included in the copy.
|
|
||||||
* @return A copy of this manifest with the selected representations.
|
|
||||||
* @throws IndexOutOfBoundsException If a key has an invalid index.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public final DashManifest copy(List<RepresentationKey> representationKeys) {
|
public final DashManifest copy(List<RepresentationKey> streamKeys) {
|
||||||
LinkedList<RepresentationKey> keys = new LinkedList<>(representationKeys);
|
LinkedList<RepresentationKey> keys = new LinkedList<>(streamKeys);
|
||||||
Collections.sort(keys);
|
Collections.sort(keys);
|
||||||
keys.add(new RepresentationKey(-1, -1, -1)); // Add a stopper key to the end
|
keys.add(new RepresentationKey(-1, -1, -1)); // Add a stopper key to the end
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ public final class DashDownloadAction extends SegmentDownloadAction<Representati
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DashDownloader createDownloader(DownloaderConstructorHelper constructorHelper) {
|
protected DashDownloader createDownloader(DownloaderConstructorHelper constructorHelper) {
|
||||||
return new DashDownloader(uri, constructorHelper, keys);
|
return new DashDownloader(uri, keys, constructorHelper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -52,8 +52,8 @@ import java.util.List;
|
|||||||
* DashDownloader dashDownloader =
|
* DashDownloader dashDownloader =
|
||||||
* new DashDownloader(
|
* new DashDownloader(
|
||||||
* manifestUrl,
|
* manifestUrl,
|
||||||
* constructorHelper,
|
* Collections.singletonList(new RepresentationKey(0, 0, 0)),
|
||||||
* Collections.singletonList(new RepresentationKey(0, 0, 0)));
|
* constructorHelper);
|
||||||
* // Perform the download.
|
* // Perform the download.
|
||||||
* dashDownloader.download();
|
* dashDownloader.download();
|
||||||
* // Access downloaded data using CacheDataSource
|
* // Access downloaded data using CacheDataSource
|
||||||
@ -63,12 +63,17 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public final class DashDownloader extends SegmentDownloader<DashManifest, RepresentationKey> {
|
public final class DashDownloader extends SegmentDownloader<DashManifest, RepresentationKey> {
|
||||||
|
|
||||||
/** @see SegmentDownloader#SegmentDownloader(Uri, DownloaderConstructorHelper, List) */
|
/**
|
||||||
|
* @param manifestUri The {@link Uri} of the manifest to be downloaded.
|
||||||
|
* @param representationKeys Keys defining which representations in the manifest should be
|
||||||
|
* selected for download. If empty, all representations are downloaded.
|
||||||
|
* @param constructorHelper A {@link DownloaderConstructorHelper} instance.
|
||||||
|
*/
|
||||||
public DashDownloader(
|
public DashDownloader(
|
||||||
Uri manifestUri,
|
Uri manifestUri,
|
||||||
DownloaderConstructorHelper constructorHelper,
|
List<RepresentationKey> representationKeys,
|
||||||
List<RepresentationKey> trackKeys) {
|
DownloaderConstructorHelper constructorHelper) {
|
||||||
super(manifestUri, constructorHelper, trackKeys);
|
super(manifestUri, representationKeys, constructorHelper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -305,7 +305,7 @@ public class DashDownloaderTest {
|
|||||||
|
|
||||||
private DashDownloader getDashDownloader(Factory factory, RepresentationKey... keys) {
|
private DashDownloader getDashDownloader(Factory factory, RepresentationKey... keys) {
|
||||||
return new DashDownloader(
|
return new DashDownloader(
|
||||||
TEST_MPD_URI, new DownloaderConstructorHelper(cache, factory), keysList(keys));
|
TEST_MPD_URI, keysList(keys), new DownloaderConstructorHelper(cache, factory));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ArrayList<RepresentationKey> keysList(RepresentationKey... keys) {
|
private static ArrayList<RepresentationKey> keysList(RepresentationKey... keys) {
|
||||||
|
@ -63,7 +63,7 @@ public final class HlsDownloadAction extends SegmentDownloadAction<RenditionKey>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HlsDownloader createDownloader(DownloaderConstructorHelper constructorHelper) {
|
protected HlsDownloader createDownloader(DownloaderConstructorHelper constructorHelper) {
|
||||||
return new HlsDownloader(uri, constructorHelper, keys);
|
return new HlsDownloader(uri, keys, constructorHelper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -43,7 +43,7 @@ public final class HlsDownloadHelper extends DownloadHelper {
|
|||||||
private final Uri uri;
|
private final Uri uri;
|
||||||
private final DataSource.Factory manifestDataSourceFactory;
|
private final DataSource.Factory manifestDataSourceFactory;
|
||||||
|
|
||||||
private @MonotonicNonNull HlsPlaylist<?> playlist;
|
private @MonotonicNonNull HlsPlaylist playlist;
|
||||||
private int[] renditionTypes;
|
private int[] renditionTypes;
|
||||||
|
|
||||||
public HlsDownloadHelper(Uri uri, DataSource.Factory manifestDataSourceFactory) {
|
public HlsDownloadHelper(Uri uri, DataSource.Factory manifestDataSourceFactory) {
|
||||||
|
@ -34,54 +34,76 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** A downloader for HLS streams. */
|
/**
|
||||||
public final class HlsDownloader extends SegmentDownloader<HlsMasterPlaylist, RenditionKey> {
|
* A downloader for HLS streams.
|
||||||
|
*
|
||||||
|
* <p>Example usage:
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* SimpleCache cache = new SimpleCache(downloadFolder, new NoOpCacheEvictor());
|
||||||
|
* DefaultHttpDataSourceFactory factory = new DefaultHttpDataSourceFactory("ExoPlayer", null);
|
||||||
|
* DownloaderConstructorHelper constructorHelper =
|
||||||
|
* new DownloaderConstructorHelper(cache, factory);
|
||||||
|
* // Create a downloader for the first variant in a master playlist.
|
||||||
|
* HlsDownloader hlsDownloader =
|
||||||
|
* new HlsDownloader(
|
||||||
|
* playlistUri,
|
||||||
|
* Collections.singletonList(new RenditionKey(RenditionKey.TYPE_VARIANT, 0)),
|
||||||
|
* constructorHelper);
|
||||||
|
* // Perform the download.
|
||||||
|
* hlsDownloader.download();
|
||||||
|
* // Access downloaded data using CacheDataSource
|
||||||
|
* CacheDataSource cacheDataSource =
|
||||||
|
* new CacheDataSource(cache, factory.createDataSource(), CacheDataSource.FLAG_BLOCK_ON_CACHE);
|
||||||
|
* }</pre>
|
||||||
|
*/
|
||||||
|
public final class HlsDownloader extends SegmentDownloader<HlsPlaylist, RenditionKey> {
|
||||||
|
|
||||||
/** @see SegmentDownloader#SegmentDownloader(Uri, DownloaderConstructorHelper, List) */
|
/**
|
||||||
|
* @param playlistUri The {@link Uri} of the playlist to be downloaded.
|
||||||
|
* @param renditionKeys Keys defining which renditions in the playlist should be selected for
|
||||||
|
* download. If empty, all renditions are downloaded.
|
||||||
|
* @param constructorHelper A {@link DownloaderConstructorHelper} instance.
|
||||||
|
*/
|
||||||
public HlsDownloader(
|
public HlsDownloader(
|
||||||
Uri manifestUri,
|
Uri playlistUri,
|
||||||
DownloaderConstructorHelper constructorHelper,
|
List<RenditionKey> renditionKeys,
|
||||||
List<RenditionKey> trackKeys) {
|
DownloaderConstructorHelper constructorHelper) {
|
||||||
super(manifestUri, constructorHelper, trackKeys);
|
super(playlistUri, renditionKeys, constructorHelper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected HlsMasterPlaylist getManifest(DataSource dataSource, Uri uri) throws IOException {
|
protected HlsPlaylist getManifest(DataSource dataSource, Uri uri) throws IOException {
|
||||||
HlsPlaylist hlsPlaylist = loadManifest(dataSource, uri);
|
return loadManifest(dataSource, uri);
|
||||||
if (hlsPlaylist instanceof HlsMasterPlaylist) {
|
|
||||||
return (HlsMasterPlaylist) hlsPlaylist;
|
|
||||||
} else {
|
|
||||||
return HlsMasterPlaylist.createSingleVariantMasterPlaylist(hlsPlaylist.baseUri);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<Segment> getSegments(
|
protected List<Segment> getSegments(
|
||||||
DataSource dataSource, HlsMasterPlaylist manifest, boolean allowIncompleteList)
|
DataSource dataSource, HlsPlaylist playlist, boolean allowIncompleteList) throws IOException {
|
||||||
throws IOException {
|
ArrayList<Uri> mediaPlaylistUris = new ArrayList<>();
|
||||||
HashSet<Uri> encryptionKeyUris = new HashSet<>();
|
if (playlist instanceof HlsMasterPlaylist) {
|
||||||
ArrayList<HlsUrl> renditionUrls = new ArrayList<>();
|
HlsMasterPlaylist masterPlaylist = (HlsMasterPlaylist) playlist;
|
||||||
renditionUrls.addAll(manifest.variants);
|
addResolvedUris(masterPlaylist.baseUri, masterPlaylist.variants, mediaPlaylistUris);
|
||||||
renditionUrls.addAll(manifest.audios);
|
addResolvedUris(masterPlaylist.baseUri, masterPlaylist.audios, mediaPlaylistUris);
|
||||||
renditionUrls.addAll(manifest.subtitles);
|
addResolvedUris(masterPlaylist.baseUri, masterPlaylist.subtitles, mediaPlaylistUris);
|
||||||
|
} else {
|
||||||
|
mediaPlaylistUris.add(Uri.parse(playlist.baseUri));
|
||||||
|
}
|
||||||
ArrayList<Segment> segments = new ArrayList<>();
|
ArrayList<Segment> segments = new ArrayList<>();
|
||||||
|
|
||||||
for (HlsUrl renditionUrl : renditionUrls) {
|
HashSet<Uri> seenEncryptionKeyUris = new HashSet<>();
|
||||||
HlsMediaPlaylist mediaPlaylist = null;
|
for (Uri mediaPlaylistUri : mediaPlaylistUris) {
|
||||||
Uri uri = UriUtil.resolveToUri(manifest.baseUri, renditionUrl.url);
|
HlsMediaPlaylist mediaPlaylist;
|
||||||
try {
|
try {
|
||||||
mediaPlaylist = (HlsMediaPlaylist) loadManifest(dataSource, uri);
|
mediaPlaylist = (HlsMediaPlaylist) loadManifest(dataSource, mediaPlaylistUri);
|
||||||
|
segments.add(new Segment(mediaPlaylist.startTimeUs, new DataSpec(mediaPlaylistUri)));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (!allowIncompleteList) {
|
if (!allowIncompleteList) {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
segments.add(new Segment(0, new DataSpec(mediaPlaylistUri)));
|
||||||
segments.add(new Segment(mediaPlaylist != null ? mediaPlaylist.startTimeUs : Long.MIN_VALUE,
|
|
||||||
new DataSpec(uri)));
|
|
||||||
if (mediaPlaylist == null) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
HlsMediaPlaylist.Segment lastInitSegment = null;
|
HlsMediaPlaylist.Segment lastInitSegment = null;
|
||||||
List<HlsMediaPlaylist.Segment> hlsSegments = mediaPlaylist.segments;
|
List<HlsMediaPlaylist.Segment> hlsSegments = mediaPlaylist.segments;
|
||||||
for (int i = 0; i < hlsSegments.size(); i++) {
|
for (int i = 0; i < hlsSegments.size(); i++) {
|
||||||
@ -89,9 +111,9 @@ public final class HlsDownloader extends SegmentDownloader<HlsMasterPlaylist, Re
|
|||||||
HlsMediaPlaylist.Segment initSegment = segment.initializationSegment;
|
HlsMediaPlaylist.Segment initSegment = segment.initializationSegment;
|
||||||
if (initSegment != null && initSegment != lastInitSegment) {
|
if (initSegment != null && initSegment != lastInitSegment) {
|
||||||
lastInitSegment = initSegment;
|
lastInitSegment = initSegment;
|
||||||
addSegment(segments, mediaPlaylist, initSegment, encryptionKeyUris);
|
addSegment(segments, mediaPlaylist, initSegment, seenEncryptionKeyUris);
|
||||||
}
|
}
|
||||||
addSegment(segments, mediaPlaylist, segment, encryptionKeyUris);
|
addSegment(segments, mediaPlaylist, segment, seenEncryptionKeyUris);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return segments;
|
return segments;
|
||||||
@ -108,12 +130,12 @@ public final class HlsDownloader extends SegmentDownloader<HlsMasterPlaylist, Re
|
|||||||
ArrayList<Segment> segments,
|
ArrayList<Segment> segments,
|
||||||
HlsMediaPlaylist mediaPlaylist,
|
HlsMediaPlaylist mediaPlaylist,
|
||||||
HlsMediaPlaylist.Segment hlsSegment,
|
HlsMediaPlaylist.Segment hlsSegment,
|
||||||
HashSet<Uri> encryptionKeyUris) {
|
HashSet<Uri> seenEncryptionKeyUris) {
|
||||||
long startTimeUs = mediaPlaylist.startTimeUs + hlsSegment.relativeStartTimeUs;
|
long startTimeUs = mediaPlaylist.startTimeUs + hlsSegment.relativeStartTimeUs;
|
||||||
if (hlsSegment.fullSegmentEncryptionKeyUri != null) {
|
if (hlsSegment.fullSegmentEncryptionKeyUri != null) {
|
||||||
Uri keyUri = UriUtil.resolveToUri(mediaPlaylist.baseUri,
|
Uri keyUri = UriUtil.resolveToUri(mediaPlaylist.baseUri,
|
||||||
hlsSegment.fullSegmentEncryptionKeyUri);
|
hlsSegment.fullSegmentEncryptionKeyUri);
|
||||||
if (encryptionKeyUris.add(keyUri)) {
|
if (seenEncryptionKeyUris.add(keyUri)) {
|
||||||
segments.add(new Segment(startTimeUs, new DataSpec(keyUri)));
|
segments.add(new Segment(startTimeUs, new DataSpec(keyUri)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,4 +144,9 @@ public final class HlsDownloader extends SegmentDownloader<HlsMasterPlaylist, Re
|
|||||||
new DataSpec(resolvedUri, hlsSegment.byterangeOffset, hlsSegment.byterangeLength, null)));
|
new DataSpec(resolvedUri, hlsSegment.byterangeOffset, hlsSegment.byterangeLength, null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void addResolvedUris(String baseUri, List<HlsUrl> urls, List<Uri> out) {
|
||||||
|
for (int i = 0; i < urls.size(); i++) {
|
||||||
|
out.add(UriUtil.resolveToUri(baseUri, urls.get(i).url));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Represents an HLS master playlist. */
|
/** Represents an HLS master playlist. */
|
||||||
public final class HlsMasterPlaylist extends HlsPlaylist<HlsMasterPlaylist> {
|
public final class HlsMasterPlaylist extends HlsPlaylist {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a url in an HLS master playlist.
|
* Represents a url in an HLS master playlist.
|
||||||
@ -107,14 +107,6 @@ public final class HlsMasterPlaylist extends HlsPlaylist<HlsMasterPlaylist> {
|
|||||||
? Collections.unmodifiableList(muxedCaptionFormats) : null;
|
? Collections.unmodifiableList(muxedCaptionFormats) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a copy of this playlist which includes only the renditions identified by the given
|
|
||||||
* keys.
|
|
||||||
*
|
|
||||||
* @param renditionKeys List of rendition keys.
|
|
||||||
* @return A copy of this playlist which includes only the renditions identified by the given
|
|
||||||
* urls.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public HlsMasterPlaylist copy(List<RenditionKey> renditionKeys) {
|
public HlsMasterPlaylist copy(List<RenditionKey> renditionKeys) {
|
||||||
return new HlsMasterPlaylist(
|
return new HlsMasterPlaylist(
|
||||||
|
@ -26,7 +26,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Represents an HLS media playlist. */
|
/** Represents an HLS media playlist. */
|
||||||
public final class HlsMediaPlaylist extends HlsPlaylist<HlsMediaPlaylist> {
|
public final class HlsMediaPlaylist extends HlsPlaylist {
|
||||||
|
|
||||||
/** Media segment reference. */
|
/** Media segment reference. */
|
||||||
@SuppressWarnings("ComparableType")
|
@SuppressWarnings("ComparableType")
|
||||||
|
@ -20,8 +20,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Represents an HLS playlist. */
|
/** Represents an HLS playlist. */
|
||||||
public abstract class HlsPlaylist<T extends HlsPlaylist<T>>
|
public abstract class HlsPlaylist implements FilterableManifest<HlsPlaylist, RenditionKey> {
|
||||||
implements FilterableManifest<T, RenditionKey> {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base uri. Used to resolve relative paths.
|
* The base uri. Used to resolve relative paths.
|
||||||
|
@ -184,7 +184,7 @@ public class HlsDownloaderTest {
|
|||||||
private HlsDownloader getHlsDownloader(String mediaPlaylistUri, List<RenditionKey> keys) {
|
private HlsDownloader getHlsDownloader(String mediaPlaylistUri, List<RenditionKey> keys) {
|
||||||
Factory factory = new Factory(null).setFakeDataSet(fakeDataSet);
|
Factory factory = new Factory(null).setFakeDataSet(fakeDataSet);
|
||||||
return new HlsDownloader(
|
return new HlsDownloader(
|
||||||
Uri.parse(mediaPlaylistUri), new DownloaderConstructorHelper(cache, factory), keys);
|
Uri.parse(mediaPlaylistUri), keys, new DownloaderConstructorHelper(cache, factory));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ArrayList<RenditionKey> getKeys(int... variantIndices) {
|
private static ArrayList<RenditionKey> getKeys(int... variantIndices) {
|
||||||
|
@ -120,16 +120,9 @@ public class SsManifest implements FilterableManifest<SsManifest, StreamKey> {
|
|||||||
this.streamElements = streamElements;
|
this.streamElements = streamElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a copy of this manifest which includes only the tracks identified by the given keys.
|
|
||||||
*
|
|
||||||
* @param trackKeys List of keys for the tracks to be included in the copy.
|
|
||||||
* @return A copy of this manifest with the selected tracks.
|
|
||||||
* @throws IndexOutOfBoundsException If a key has an invalid index.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public final SsManifest copy(List<StreamKey> trackKeys) {
|
public final SsManifest copy(List<StreamKey> streamKeys) {
|
||||||
ArrayList<StreamKey> sortedKeys = new ArrayList<>(trackKeys);
|
ArrayList<StreamKey> sortedKeys = new ArrayList<>(streamKeys);
|
||||||
Collections.sort(sortedKeys);
|
Collections.sort(sortedKeys);
|
||||||
|
|
||||||
StreamElement currentStreamElement = null;
|
StreamElement currentStreamElement = null;
|
||||||
|
@ -51,7 +51,7 @@ public final class SsDownloadAction extends SegmentDownloadAction<StreamKey> {
|
|||||||
* @param uri The SmoothStreaming manifest URI.
|
* @param uri The SmoothStreaming manifest URI.
|
||||||
* @param isRemoveAction Whether the data will be removed. If {@code false} it will be downloaded.
|
* @param isRemoveAction Whether the data will be removed. If {@code false} it will be downloaded.
|
||||||
* @param data Optional custom data for this action.
|
* @param data Optional custom data for this action.
|
||||||
* @param keys Keys of tracks to be downloaded. If empty, all tracks are downloaded. If {@code
|
* @param keys Keys of streams to be downloaded. If empty, all streams are downloaded. If {@code
|
||||||
* removeAction} is true, {@code keys} must be empty.
|
* removeAction} is true, {@code keys} must be empty.
|
||||||
*/
|
*/
|
||||||
public SsDownloadAction(
|
public SsDownloadAction(
|
||||||
@ -61,7 +61,7 @@ public final class SsDownloadAction extends SegmentDownloadAction<StreamKey> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected SsDownloader createDownloader(DownloaderConstructorHelper constructorHelper) {
|
protected SsDownloader createDownloader(DownloaderConstructorHelper constructorHelper) {
|
||||||
return new SsDownloader(uri, constructorHelper, keys);
|
return new SsDownloader(uri, keys, constructorHelper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -45,8 +45,8 @@ import java.util.List;
|
|||||||
* SsDownloader ssDownloader =
|
* SsDownloader ssDownloader =
|
||||||
* new SsDownloader(
|
* new SsDownloader(
|
||||||
* manifestUrl,
|
* manifestUrl,
|
||||||
* constructorHelper,
|
* Collections.singletonList(new StreamKey(0, 0)),
|
||||||
* Collections.singletonList(new StreamKey(0, 0)));
|
* constructorHelper);
|
||||||
* // Perform the download.
|
* // Perform the download.
|
||||||
* ssDownloader.download();
|
* ssDownloader.download();
|
||||||
* // Access downloaded data using CacheDataSource
|
* // Access downloaded data using CacheDataSource
|
||||||
@ -56,10 +56,15 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public final class SsDownloader extends SegmentDownloader<SsManifest, StreamKey> {
|
public final class SsDownloader extends SegmentDownloader<SsManifest, StreamKey> {
|
||||||
|
|
||||||
/** @see SegmentDownloader#SegmentDownloader(Uri, DownloaderConstructorHelper, List) */
|
/**
|
||||||
|
* @param manifestUri The {@link Uri} of the manifest to be downloaded.
|
||||||
|
* @param streamKeys Keys defining which streams in the manifest should be selected for download.
|
||||||
|
* If empty, all streams are downloaded.
|
||||||
|
* @param constructorHelper A {@link DownloaderConstructorHelper} instance.
|
||||||
|
*/
|
||||||
public SsDownloader(
|
public SsDownloader(
|
||||||
Uri manifestUri, DownloaderConstructorHelper constructorHelper, List<StreamKey> trackKeys) {
|
Uri manifestUri, List<StreamKey> streamKeys, DownloaderConstructorHelper constructorHelper) {
|
||||||
super(SsUtil.fixManifestUri(manifestUri), constructorHelper, trackKeys);
|
super(SsUtil.fixManifestUri(manifestUri), streamKeys, constructorHelper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -123,7 +123,7 @@ public final class DashDownloadTest extends ActivityInstrumentationTestCase2<Hos
|
|||||||
}
|
}
|
||||||
DownloaderConstructorHelper constructorHelper =
|
DownloaderConstructorHelper constructorHelper =
|
||||||
new DownloaderConstructorHelper(cache, httpDataSourceFactory);
|
new DownloaderConstructorHelper(cache, httpDataSourceFactory);
|
||||||
return new DashDownloader(MANIFEST_URI, constructorHelper, keys);
|
return new DashDownloader(MANIFEST_URI, keys, constructorHelper);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user