Misc cleanup

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=195552434
This commit is contained in:
olly 2018-05-05 14:36:09 -07:00 committed by Oliver Woodman
parent dbd768fbd7
commit 051da40dc3
19 changed files with 127 additions and 106 deletions

View File

@ -49,14 +49,17 @@ public final class DownloaderConstructorHelper {
/**
* @param cache Cache instance to be used to store downloaded data.
* @param upstreamDataSourceFactory A {@link Factory} for downloading data.
* @param cacheReadDataSourceFactory A {@link Factory} for reading data from the cache.
* If null, null is passed to {@link Downloader} constructor.
* @param cacheReadDataSourceFactory A {@link Factory} for reading data from the cache. If null
* then standard {@link FileDataSource} instances will be used.
* @param cacheWriteDataSinkFactory A {@link DataSink.Factory} for writing data to the cache. If
* null, null is passed to {@link Downloader} constructor.
* @param priorityTaskManager If one is given then the download priority is set lower than
* loading. If null, null is passed to {@link Downloader} constructor.
* null then standard {@link CacheDataSink} instances will be used.
* @param priorityTaskManager A {@link PriorityTaskManager} to use when downloading. If non-null,
* 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 DataSink.Factory cacheWriteDataSinkFactory,
@Nullable PriorityTaskManager priorityTaskManager) {
@ -73,7 +76,7 @@ public final class DownloaderConstructorHelper {
return cache;
}
/** Returns a {@link PriorityTaskManager} instance.*/
/** Returns a {@link PriorityTaskManager} instance. */
public PriorityTaskManager getPriorityTaskManager() {
// Return a dummy PriorityTaskManager if none is provided. Create a new PriorityTaskManager
// each time so clients don't affect each other over the dummy PriorityTaskManager instance.

View File

@ -18,19 +18,20 @@ package com.google.android.exoplayer2.offline;
import java.util.List;
/**
* A manifest that can generate copies of itself including only the tracks specified by the given
* track keys.
* A manifest that can generate copies of itself including only the streams specified by the given
* keys.
*
* @param <T> The manifest type.
* @param <K> The track key type.
* @param <K> The stream key type.
*/
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.
*/
T copy(List<K> trackKeys);
T copy(List<K> streamKeys);
}

View File

@ -35,7 +35,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* Base class for multi segment stream downloaders.
*
* @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>
implements Downloader {
@ -68,7 +68,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M, K>, K>
private final Cache cache;
private final CacheDataSource dataSource;
private final CacheDataSource offlineDataSource;
private final ArrayList<K> keys;
private final ArrayList<K> streamKeys;
private final AtomicBoolean isCanceled;
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 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 trackKeys Track keys to select when downloading. If empty, all tracks are downloaded.
*/
public SegmentDownloader(
Uri manifestUri, DownloaderConstructorHelper constructorHelper, List<K> trackKeys) {
Uri manifestUri, List<K> streamKeys, DownloaderConstructorHelper constructorHelper) {
this.manifestUri = manifestUri;
this.streamKeys = new ArrayList<>(streamKeys);
this.cache = constructorHelper.getCache();
this.dataSource = constructorHelper.buildCacheDataSource(false);
this.offlineDataSource = constructorHelper.buildCacheDataSource(true);
this.priorityTaskManager = constructorHelper.getPriorityTaskManager();
keys = new ArrayList<>(trackKeys);
totalSegments = C.LENGTH_UNSET;
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.
*
* @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. */
private List<Segment> initDownload() throws IOException, InterruptedException {
M manifest = getManifest(dataSource, manifestUri);
if (!keys.isEmpty()) {
manifest = manifest.copy(keys);
if (!streamKeys.isEmpty()) {
manifest = manifest.copy(streamKeys);
}
List<Segment> segments = getSegments(dataSource, manifest, /* allowIncompleteList= */ false);
CachingCounters cachingCounters = new CachingCounters();

View File

@ -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
* 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;
/** The group index. */
public final int groupIndex;
/** The track index. */
public final int trackIndex;
/**

View File

@ -122,17 +122,9 @@ public class DashManifest implements FilterableManifest<DashManifest, Representa
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
public final DashManifest copy(List<RepresentationKey> representationKeys) {
LinkedList<RepresentationKey> keys = new LinkedList<>(representationKeys);
public final DashManifest copy(List<RepresentationKey> streamKeys) {
LinkedList<RepresentationKey> keys = new LinkedList<>(streamKeys);
Collections.sort(keys);
keys.add(new RepresentationKey(-1, -1, -1)); // Add a stopper key to the end

View File

@ -61,7 +61,7 @@ public final class DashDownloadAction extends SegmentDownloadAction<Representati
@Override
protected DashDownloader createDownloader(DownloaderConstructorHelper constructorHelper) {
return new DashDownloader(uri, constructorHelper, keys);
return new DashDownloader(uri, keys, constructorHelper);
}
@Override

View File

@ -52,8 +52,8 @@ import java.util.List;
* DashDownloader dashDownloader =
* new DashDownloader(
* manifestUrl,
* constructorHelper,
* Collections.singletonList(new RepresentationKey(0, 0, 0)));
* Collections.singletonList(new RepresentationKey(0, 0, 0)),
* constructorHelper);
* // Perform the download.
* dashDownloader.download();
* // Access downloaded data using CacheDataSource
@ -63,12 +63,17 @@ import java.util.List;
*/
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(
Uri manifestUri,
DownloaderConstructorHelper constructorHelper,
List<RepresentationKey> trackKeys) {
super(manifestUri, constructorHelper, trackKeys);
List<RepresentationKey> representationKeys,
DownloaderConstructorHelper constructorHelper) {
super(manifestUri, representationKeys, constructorHelper);
}
@Override

View File

@ -305,7 +305,7 @@ public class DashDownloaderTest {
private DashDownloader getDashDownloader(Factory factory, RepresentationKey... keys) {
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) {

View File

@ -63,7 +63,7 @@ public final class HlsDownloadAction extends SegmentDownloadAction<RenditionKey>
@Override
protected HlsDownloader createDownloader(DownloaderConstructorHelper constructorHelper) {
return new HlsDownloader(uri, constructorHelper, keys);
return new HlsDownloader(uri, keys, constructorHelper);
}
@Override

View File

@ -43,7 +43,7 @@ public final class HlsDownloadHelper extends DownloadHelper {
private final Uri uri;
private final DataSource.Factory manifestDataSourceFactory;
private @MonotonicNonNull HlsPlaylist<?> playlist;
private @MonotonicNonNull HlsPlaylist playlist;
private int[] renditionTypes;
public HlsDownloadHelper(Uri uri, DataSource.Factory manifestDataSourceFactory) {

View File

@ -34,54 +34,76 @@ import java.util.ArrayList;
import java.util.HashSet;
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(
Uri manifestUri,
DownloaderConstructorHelper constructorHelper,
List<RenditionKey> trackKeys) {
super(manifestUri, constructorHelper, trackKeys);
Uri playlistUri,
List<RenditionKey> renditionKeys,
DownloaderConstructorHelper constructorHelper) {
super(playlistUri, renditionKeys, constructorHelper);
}
@Override
protected HlsMasterPlaylist getManifest(DataSource dataSource, Uri uri) throws IOException {
HlsPlaylist hlsPlaylist = loadManifest(dataSource, uri);
if (hlsPlaylist instanceof HlsMasterPlaylist) {
return (HlsMasterPlaylist) hlsPlaylist;
} else {
return HlsMasterPlaylist.createSingleVariantMasterPlaylist(hlsPlaylist.baseUri);
}
protected HlsPlaylist getManifest(DataSource dataSource, Uri uri) throws IOException {
return loadManifest(dataSource, uri);
}
@Override
protected List<Segment> getSegments(
DataSource dataSource, HlsMasterPlaylist manifest, boolean allowIncompleteList)
throws IOException {
HashSet<Uri> encryptionKeyUris = new HashSet<>();
ArrayList<HlsUrl> renditionUrls = new ArrayList<>();
renditionUrls.addAll(manifest.variants);
renditionUrls.addAll(manifest.audios);
renditionUrls.addAll(manifest.subtitles);
DataSource dataSource, HlsPlaylist playlist, boolean allowIncompleteList) throws IOException {
ArrayList<Uri> mediaPlaylistUris = new ArrayList<>();
if (playlist instanceof HlsMasterPlaylist) {
HlsMasterPlaylist masterPlaylist = (HlsMasterPlaylist) playlist;
addResolvedUris(masterPlaylist.baseUri, masterPlaylist.variants, mediaPlaylistUris);
addResolvedUris(masterPlaylist.baseUri, masterPlaylist.audios, mediaPlaylistUris);
addResolvedUris(masterPlaylist.baseUri, masterPlaylist.subtitles, mediaPlaylistUris);
} else {
mediaPlaylistUris.add(Uri.parse(playlist.baseUri));
}
ArrayList<Segment> segments = new ArrayList<>();
for (HlsUrl renditionUrl : renditionUrls) {
HlsMediaPlaylist mediaPlaylist = null;
Uri uri = UriUtil.resolveToUri(manifest.baseUri, renditionUrl.url);
HashSet<Uri> seenEncryptionKeyUris = new HashSet<>();
for (Uri mediaPlaylistUri : mediaPlaylistUris) {
HlsMediaPlaylist mediaPlaylist;
try {
mediaPlaylist = (HlsMediaPlaylist) loadManifest(dataSource, uri);
mediaPlaylist = (HlsMediaPlaylist) loadManifest(dataSource, mediaPlaylistUri);
segments.add(new Segment(mediaPlaylist.startTimeUs, new DataSpec(mediaPlaylistUri)));
} catch (IOException e) {
if (!allowIncompleteList) {
throw e;
}
}
segments.add(new Segment(mediaPlaylist != null ? mediaPlaylist.startTimeUs : Long.MIN_VALUE,
new DataSpec(uri)));
if (mediaPlaylist == null) {
segments.add(new Segment(0, new DataSpec(mediaPlaylistUri)));
continue;
}
HlsMediaPlaylist.Segment lastInitSegment = null;
List<HlsMediaPlaylist.Segment> hlsSegments = mediaPlaylist.segments;
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;
if (initSegment != null && initSegment != lastInitSegment) {
lastInitSegment = initSegment;
addSegment(segments, mediaPlaylist, initSegment, encryptionKeyUris);
addSegment(segments, mediaPlaylist, initSegment, seenEncryptionKeyUris);
}
addSegment(segments, mediaPlaylist, segment, encryptionKeyUris);
addSegment(segments, mediaPlaylist, segment, seenEncryptionKeyUris);
}
}
return segments;
@ -108,12 +130,12 @@ public final class HlsDownloader extends SegmentDownloader<HlsMasterPlaylist, Re
ArrayList<Segment> segments,
HlsMediaPlaylist mediaPlaylist,
HlsMediaPlaylist.Segment hlsSegment,
HashSet<Uri> encryptionKeyUris) {
HashSet<Uri> seenEncryptionKeyUris) {
long startTimeUs = mediaPlaylist.startTimeUs + hlsSegment.relativeStartTimeUs;
if (hlsSegment.fullSegmentEncryptionKeyUri != null) {
Uri keyUri = UriUtil.resolveToUri(mediaPlaylist.baseUri,
hlsSegment.fullSegmentEncryptionKeyUri);
if (encryptionKeyUris.add(keyUri)) {
if (seenEncryptionKeyUris.add(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)));
}
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));
}
}
}

View File

@ -22,7 +22,7 @@ import java.util.Collections;
import java.util.List;
/** 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.
@ -107,14 +107,6 @@ public final class HlsMasterPlaylist extends HlsPlaylist<HlsMasterPlaylist> {
? 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
public HlsMasterPlaylist copy(List<RenditionKey> renditionKeys) {
return new HlsMasterPlaylist(

View File

@ -26,7 +26,7 @@ import java.util.Collections;
import java.util.List;
/** Represents an HLS media playlist. */
public final class HlsMediaPlaylist extends HlsPlaylist<HlsMediaPlaylist> {
public final class HlsMediaPlaylist extends HlsPlaylist {
/** Media segment reference. */
@SuppressWarnings("ComparableType")

View File

@ -20,8 +20,7 @@ import java.util.Collections;
import java.util.List;
/** Represents an HLS playlist. */
public abstract class HlsPlaylist<T extends HlsPlaylist<T>>
implements FilterableManifest<T, RenditionKey> {
public abstract class HlsPlaylist implements FilterableManifest<HlsPlaylist, RenditionKey> {
/**
* The base uri. Used to resolve relative paths.

View File

@ -184,7 +184,7 @@ public class HlsDownloaderTest {
private HlsDownloader getHlsDownloader(String mediaPlaylistUri, List<RenditionKey> keys) {
Factory factory = new Factory(null).setFakeDataSet(fakeDataSet);
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) {

View File

@ -120,16 +120,9 @@ public class SsManifest implements FilterableManifest<SsManifest, StreamKey> {
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
public final SsManifest copy(List<StreamKey> trackKeys) {
ArrayList<StreamKey> sortedKeys = new ArrayList<>(trackKeys);
public final SsManifest copy(List<StreamKey> streamKeys) {
ArrayList<StreamKey> sortedKeys = new ArrayList<>(streamKeys);
Collections.sort(sortedKeys);
StreamElement currentStreamElement = null;

View File

@ -51,7 +51,7 @@ public final class SsDownloadAction extends SegmentDownloadAction<StreamKey> {
* @param uri The SmoothStreaming manifest URI.
* @param isRemoveAction Whether the data will be removed. If {@code false} it will be downloaded.
* @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.
*/
public SsDownloadAction(
@ -61,7 +61,7 @@ public final class SsDownloadAction extends SegmentDownloadAction<StreamKey> {
@Override
protected SsDownloader createDownloader(DownloaderConstructorHelper constructorHelper) {
return new SsDownloader(uri, constructorHelper, keys);
return new SsDownloader(uri, keys, constructorHelper);
}
@Override

View File

@ -45,8 +45,8 @@ import java.util.List;
* SsDownloader ssDownloader =
* new SsDownloader(
* manifestUrl,
* constructorHelper,
* Collections.singletonList(new StreamKey(0, 0)));
* Collections.singletonList(new StreamKey(0, 0)),
* constructorHelper);
* // Perform the download.
* ssDownloader.download();
* // Access downloaded data using CacheDataSource
@ -56,10 +56,15 @@ import java.util.List;
*/
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(
Uri manifestUri, DownloaderConstructorHelper constructorHelper, List<StreamKey> trackKeys) {
super(SsUtil.fixManifestUri(manifestUri), constructorHelper, trackKeys);
Uri manifestUri, List<StreamKey> streamKeys, DownloaderConstructorHelper constructorHelper) {
super(SsUtil.fixManifestUri(manifestUri), streamKeys, constructorHelper);
}
@Override

View File

@ -123,7 +123,7 @@ public final class DashDownloadTest extends ActivityInstrumentationTestCase2<Hos
}
DownloaderConstructorHelper constructorHelper =
new DownloaderConstructorHelper(cache, httpDataSourceFactory);
return new DashDownloader(MANIFEST_URI, constructorHelper, keys);
return new DashDownloader(MANIFEST_URI, keys, constructorHelper);
}
}