Use TrackKey in place of RepresentetionKey, StreamKey, RenditionKey

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=199767518
This commit is contained in:
eguven 2018-06-08 02:11:37 -07:00 committed by Oliver Woodman
parent 8e65696f02
commit a406dc8bee
31 changed files with 255 additions and 400 deletions

View File

@ -37,6 +37,7 @@ import com.google.android.exoplayer2.offline.DownloadManager.TaskState;
import com.google.android.exoplayer2.offline.DownloadService;
import com.google.android.exoplayer2.offline.ProgressiveDownloadHelper;
import com.google.android.exoplayer2.offline.SegmentDownloadAction;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.offline.TrackKey;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
@ -111,7 +112,7 @@ public class DownloadTracker implements DownloadManager.Listener {
}
@SuppressWarnings("unchecked")
public <K> List<K> getOfflineStreamKeys(Uri uri) {
public List<StreamKey> getOfflineStreamKeys(Uri uri) {
if (!trackedDownloadStates.containsKey(uri)) {
return Collections.emptyList();
}
@ -282,6 +283,7 @@ public class DownloadTracker implements DownloadManager.Listener {
Toast.makeText(
context.getApplicationContext(), R.string.download_start_error, Toast.LENGTH_LONG)
.show();
Log.e(TAG, "Failed to start download", e);
}
@Override

View File

@ -49,6 +49,7 @@ import com.google.android.exoplayer2.drm.UnsupportedDrmException;
import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException;
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;
import com.google.android.exoplayer2.offline.FilteringManifestParser;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.BehindLiveWindowException;
import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
@ -59,14 +60,11 @@ import com.google.android.exoplayer2.source.ads.AdsMediaSource;
import com.google.android.exoplayer2.source.dash.DashMediaSource;
import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource;
import com.google.android.exoplayer2.source.dash.manifest.DashManifestParser;
import com.google.android.exoplayer2.source.dash.manifest.RepresentationKey;
import com.google.android.exoplayer2.source.hls.HlsMediaSource;
import com.google.android.exoplayer2.source.hls.playlist.HlsPlaylistParser;
import com.google.android.exoplayer2.source.hls.playlist.RenditionKey;
import com.google.android.exoplayer2.source.smoothstreaming.DefaultSsChunkSource;
import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifestParser;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.StreamKey;
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
@ -446,22 +444,19 @@ public class PlayerActivity extends Activity
new DefaultDashChunkSource.Factory(mediaDataSourceFactory),
buildDataSourceFactory(false))
.setManifestParser(
new FilteringManifestParser<>(
new DashManifestParser(), (List<RepresentationKey>) getOfflineStreamKeys(uri)))
new FilteringManifestParser<>(new DashManifestParser(), getOfflineStreamKeys(uri)))
.createMediaSource(uri);
case C.TYPE_SS:
return new SsMediaSource.Factory(
new DefaultSsChunkSource.Factory(mediaDataSourceFactory),
buildDataSourceFactory(false))
.setManifestParser(
new FilteringManifestParser<>(
new SsManifestParser(), (List<StreamKey>) getOfflineStreamKeys(uri)))
new FilteringManifestParser<>(new SsManifestParser(), getOfflineStreamKeys(uri)))
.createMediaSource(uri);
case C.TYPE_HLS:
return new HlsMediaSource.Factory(mediaDataSourceFactory)
.setPlaylistParser(
new FilteringManifestParser<>(
new HlsPlaylistParser(), (List<RenditionKey>) getOfflineStreamKeys(uri)))
new FilteringManifestParser<>(new HlsPlaylistParser(), getOfflineStreamKeys(uri)))
.createMediaSource(uri);
case C.TYPE_OTHER:
return new ExtractorMediaSource.Factory(mediaDataSourceFactory).createMediaSource(uri);
@ -471,7 +466,7 @@ public class PlayerActivity extends Activity
}
}
private List<?> getOfflineStreamKeys(Uri uri) {
private List<StreamKey> getOfflineStreamKeys(Uri uri) {
return ((DemoApplication) getApplication()).getDownloadTracker().getOfflineStreamKeys(uri);
}

View File

@ -22,9 +22,8 @@ import java.util.List;
* keys.
*
* @param <T> The manifest type.
* @param <K> The stream key type.
*/
public interface FilterableManifest<T, K> {
public interface FilterableManifest<T> {
/**
* Returns a copy of the manifest including only the streams specified by the given keys. If the
@ -33,5 +32,5 @@ public interface FilterableManifest<T, K> {
* @param streamKeys A non-empty list of stream keys.
* @return The filtered manifest.
*/
T copy(List<K> streamKeys);
T copy(List<StreamKey> streamKeys);
}

View File

@ -21,25 +21,24 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/** A manifest parser that includes only the tracks identified by the given track keys. */
public final class FilteringManifestParser<T extends FilterableManifest<T, K>, K>
implements Parser<T> {
/** A manifest parser that includes only the streams identified by the given stream keys. */
public final class FilteringManifestParser<T extends FilterableManifest<T>> implements Parser<T> {
private final Parser<T> parser;
private final List<K> trackKeys;
private final List<StreamKey> streamKeys;
/**
* @param parser A parser for the manifest that will be filtered.
* @param trackKeys The track keys. If null or empty then filtering will not occur.
* @param streamKeys The stream keys. If null or empty then filtering will not occur.
*/
public FilteringManifestParser(Parser<T> parser, List<K> trackKeys) {
public FilteringManifestParser(Parser<T> parser, List<StreamKey> streamKeys) {
this.parser = parser;
this.trackKeys = trackKeys;
this.streamKeys = streamKeys;
}
@Override
public T parse(Uri uri, InputStream inputStream) throws IOException {
T manifest = parser.parse(uri, inputStream);
return trackKeys == null || trackKeys.isEmpty() ? manifest : manifest.copy(trackKeys);
return streamKeys == null || streamKeys.isEmpty() ? manifest : manifest.copy(streamKeys);
}
}

View File

@ -25,19 +25,11 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* {@link DownloadAction} for {@link SegmentDownloader}s.
*
* @param <K> The type of the representation key object.
*/
public abstract class SegmentDownloadAction<K extends Comparable<K>> extends DownloadAction {
/** {@link DownloadAction} for {@link SegmentDownloader}s. */
public abstract class SegmentDownloadAction extends DownloadAction {
/**
* Base class for {@link SegmentDownloadAction} {@link Deserializer}s.
*
* @param <K> The type of the representation key object.
*/
protected abstract static class SegmentDownloadActionDeserializer<K> extends Deserializer {
/** Base class for {@link SegmentDownloadAction} {@link Deserializer}s. */
protected abstract static class SegmentDownloadActionDeserializer extends Deserializer {
public SegmentDownloadActionDeserializer(String type, int version) {
super(type, version);
@ -52,7 +44,7 @@ public abstract class SegmentDownloadAction<K extends Comparable<K>> extends Dow
byte[] data = new byte[dataLength];
input.readFully(data);
int keyCount = input.readInt();
List<K> keys = new ArrayList<>();
List<StreamKey> keys = new ArrayList<>();
for (int i = 0; i < keyCount; i++) {
keys.add(readKey(input));
}
@ -60,14 +52,14 @@ public abstract class SegmentDownloadAction<K extends Comparable<K>> extends Dow
}
/** Deserializes a key from the {@code input}. */
protected abstract K readKey(DataInputStream input) throws IOException;
protected abstract StreamKey readKey(DataInputStream input) throws IOException;
/** Returns a {@link DownloadAction}. */
protected abstract DownloadAction createDownloadAction(
Uri manifestUri, boolean isRemoveAction, byte[] data, List<K> keys);
Uri manifestUri, boolean isRemoveAction, byte[] data, List<StreamKey> keys);
}
public final List<K> keys;
public final List<StreamKey> keys;
/**
* @param type The type of the action.
@ -84,13 +76,13 @@ public abstract class SegmentDownloadAction<K extends Comparable<K>> extends Dow
Uri uri,
boolean isRemoveAction,
@Nullable byte[] data,
List<K> keys) {
List<StreamKey> keys) {
super(type, version, uri, isRemoveAction, data);
if (isRemoveAction) {
Assertions.checkArgument(keys.isEmpty());
this.keys = Collections.emptyList();
} else {
ArrayList<K> mutableKeys = new ArrayList<>(keys);
ArrayList<StreamKey> mutableKeys = new ArrayList<>(keys);
Collections.sort(mutableKeys);
this.keys = Collections.unmodifiableList(mutableKeys);
}
@ -109,7 +101,7 @@ public abstract class SegmentDownloadAction<K extends Comparable<K>> extends Dow
}
/** Serializes the {@code key} into the {@code output}. */
protected abstract void writeKey(DataOutputStream output, K key) throws IOException;
protected abstract void writeKey(DataOutputStream output, StreamKey key) throws IOException;
@Override
public boolean equals(@Nullable Object o) {
@ -119,7 +111,7 @@ public abstract class SegmentDownloadAction<K extends Comparable<K>> extends Dow
if (!super.equals(o)) {
return false;
}
SegmentDownloadAction<?> that = (SegmentDownloadAction<?>) o;
SegmentDownloadAction that = (SegmentDownloadAction) o;
return keys.equals(that.keys);
}

View File

@ -35,10 +35,8 @@ 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 streams key object.
*/
public abstract class SegmentDownloader<M extends FilterableManifest<M, K>, K>
implements Downloader {
public abstract class SegmentDownloader<M extends FilterableManifest<M>> implements Downloader {
/** Smallest unit of content to be downloaded. */
protected static class Segment implements Comparable<Segment> {
@ -68,7 +66,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> streamKeys;
private final ArrayList<StreamKey> streamKeys;
private final AtomicBoolean isCanceled;
private volatile int totalSegments;
@ -82,7 +80,7 @@ public abstract class SegmentDownloader<M extends FilterableManifest<M, K>, K>
* @param constructorHelper A {@link DownloaderConstructorHelper} instance.
*/
public SegmentDownloader(
Uri manifestUri, List<K> streamKeys, DownloaderConstructorHelper constructorHelper) {
Uri manifestUri, List<StreamKey> streamKeys, DownloaderConstructorHelper constructorHelper) {
this.manifestUri = manifestUri;
this.streamKeys = new ArrayList<>(streamKeys);
this.cache = constructorHelper.getCache();

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 The Android Open Source Project
* 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.
@ -13,25 +13,46 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.source.smoothstreaming.manifest;
package com.google.android.exoplayer2.offline;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
/** Uniquely identifies a track in a {@link SsManifest}. */
/**
* 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 final class StreamKey implements Comparable<StreamKey> {
public final int streamElementIndex;
/** The period index. */
public final int periodIndex;
/** The group index. */
public final int groupIndex;
/** The track index. */
public final int trackIndex;
public StreamKey(int streamElementIndex, int trackIndex) {
this.streamElementIndex = streamElementIndex;
/**
* @param groupIndex The group index.
* @param trackIndex The track index.
*/
public StreamKey(int groupIndex, int trackIndex) {
this(0, groupIndex, trackIndex);
}
/**
* @param periodIndex The period index.
* @param groupIndex The group index.
* @param trackIndex The track index.
*/
public StreamKey(int periodIndex, int groupIndex, int trackIndex) {
this.periodIndex = periodIndex;
this.groupIndex = groupIndex;
this.trackIndex = trackIndex;
}
@Override
public String toString() {
return streamElementIndex + "." + trackIndex;
return periodIndex + "." + groupIndex + "." + trackIndex;
}
@Override
@ -44,12 +65,15 @@ public final class StreamKey implements Comparable<StreamKey> {
}
StreamKey that = (StreamKey) o;
return streamElementIndex == that.streamElementIndex && trackIndex == that.trackIndex;
return periodIndex == that.periodIndex
&& groupIndex == that.groupIndex
&& trackIndex == that.trackIndex;
}
@Override
public int hashCode() {
int result = streamElementIndex;
int result = periodIndex;
result = 31 * result + groupIndex;
result = 31 * result + trackIndex;
return result;
}
@ -58,9 +82,12 @@ public final class StreamKey implements Comparable<StreamKey> {
@Override
public int compareTo(@NonNull StreamKey o) {
int result = streamElementIndex - o.streamElementIndex;
int result = periodIndex - o.periodIndex;
if (result == 0) {
result = trackIndex - o.trackIndex;
result = groupIndex - o.groupIndex;
if (result == 0) {
result = trackIndex - o.trackIndex;
}
}
return result;
}

View File

@ -18,6 +18,7 @@ package com.google.android.exoplayer2.source.dash.manifest;
import android.net.Uri;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.offline.FilterableManifest;
import com.google.android.exoplayer2.offline.StreamKey;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
@ -27,7 +28,7 @@ import java.util.List;
* Represents a DASH media presentation description (mpd), as defined by ISO/IEC 23009-1:2014
* Section 5.3.1.2.
*/
public class DashManifest implements FilterableManifest<DashManifest, RepresentationKey> {
public class DashManifest implements FilterableManifest<DashManifest> {
/**
* The {@code availabilityStartTime} value in milliseconds since epoch, or {@link C#TIME_UNSET} if
@ -123,10 +124,10 @@ public class DashManifest implements FilterableManifest<DashManifest, Representa
}
@Override
public final DashManifest copy(List<RepresentationKey> streamKeys) {
LinkedList<RepresentationKey> keys = new LinkedList<>(streamKeys);
public final DashManifest copy(List<StreamKey> streamKeys) {
LinkedList<StreamKey> keys = new LinkedList<>(streamKeys);
Collections.sort(keys);
keys.add(new RepresentationKey(-1, -1, -1)); // Add a stopper key to the end
keys.add(new StreamKey(-1, -1, -1)); // Add a stopper key to the end
ArrayList<Period> copyPeriods = new ArrayList<>();
long shiftMs = 0;
@ -153,21 +154,21 @@ public class DashManifest implements FilterableManifest<DashManifest, Representa
}
private static ArrayList<AdaptationSet> copyAdaptationSets(
List<AdaptationSet> adaptationSets, LinkedList<RepresentationKey> keys) {
RepresentationKey key = keys.poll();
List<AdaptationSet> adaptationSets, LinkedList<StreamKey> keys) {
StreamKey key = keys.poll();
int periodIndex = key.periodIndex;
ArrayList<AdaptationSet> copyAdaptationSets = new ArrayList<>();
do {
int adaptationSetIndex = key.adaptationSetIndex;
int adaptationSetIndex = key.groupIndex;
AdaptationSet adaptationSet = adaptationSets.get(adaptationSetIndex);
List<Representation> representations = adaptationSet.representations;
ArrayList<Representation> copyRepresentations = new ArrayList<>();
do {
Representation representation = representations.get(key.representationIndex);
Representation representation = representations.get(key.trackIndex);
copyRepresentations.add(representation);
key = keys.poll();
} while(key.periodIndex == periodIndex && key.adaptationSetIndex == adaptationSetIndex);
} while (key.periodIndex == periodIndex && key.groupIndex == adaptationSetIndex);
copyAdaptationSets.add(new AdaptationSet(adaptationSet.id, adaptationSet.type,
copyRepresentations, adaptationSet.accessibilityDescriptors,

View File

@ -1,76 +0,0 @@
/*
* Copyright (C) 2017 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.dash.manifest;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
/** Uniquely identifies a {@link Representation} in a {@link DashManifest}. */
public final class RepresentationKey implements Comparable<RepresentationKey> {
public final int periodIndex;
public final int adaptationSetIndex;
public final int representationIndex;
public RepresentationKey(int periodIndex, int adaptationSetIndex, int representationIndex) {
this.periodIndex = periodIndex;
this.adaptationSetIndex = adaptationSetIndex;
this.representationIndex = representationIndex;
}
@Override
public String toString() {
return periodIndex + "." + adaptationSetIndex + "." + representationIndex;
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
RepresentationKey that = (RepresentationKey) o;
return periodIndex == that.periodIndex
&& adaptationSetIndex == that.adaptationSetIndex
&& representationIndex == that.representationIndex;
}
@Override
public int hashCode() {
int result = periodIndex;
result = 31 * result + adaptationSetIndex;
result = 31 * result + representationIndex;
return result;
}
// Comparable implementation.
@Override
public int compareTo(@NonNull RepresentationKey o) {
int result = periodIndex - o.periodIndex;
if (result == 0) {
result = adaptationSetIndex - o.adaptationSetIndex;
if (result == 0) {
result = representationIndex - o.representationIndex;
}
}
return result;
}
}

View File

@ -20,29 +20,32 @@ import android.support.annotation.Nullable;
import com.google.android.exoplayer2.offline.DownloadAction;
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
import com.google.android.exoplayer2.offline.SegmentDownloadAction;
import com.google.android.exoplayer2.source.dash.manifest.RepresentationKey;
import com.google.android.exoplayer2.offline.StreamKey;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
/** An action to download or remove downloaded DASH streams. */
public final class DashDownloadAction extends SegmentDownloadAction<RepresentationKey> {
public final class DashDownloadAction extends SegmentDownloadAction {
private static final String TYPE = "dash";
private static final int VERSION = 0;
public static final Deserializer DESERIALIZER =
new SegmentDownloadActionDeserializer<RepresentationKey>(TYPE, VERSION) {
new SegmentDownloadActionDeserializer(TYPE, VERSION) {
@Override
protected RepresentationKey readKey(DataInputStream input) throws IOException {
return new RepresentationKey(input.readInt(), input.readInt(), input.readInt());
protected StreamKey readKey(DataInputStream input) throws IOException {
int periodIndex = input.readInt();
int groupIndex = input.readInt();
int trackIndex = input.readInt();
return new StreamKey(periodIndex, groupIndex, trackIndex);
}
@Override
protected DownloadAction createDownloadAction(
Uri uri, boolean isRemoveAction, byte[] data, List<RepresentationKey> keys) {
Uri uri, boolean isRemoveAction, byte[] data, List<StreamKey> keys) {
return new DashDownloadAction(uri, isRemoveAction, data, keys);
}
};
@ -55,7 +58,7 @@ public final class DashDownloadAction extends SegmentDownloadAction<Representati
* downloaded. If {@code removeAction} is true, {@code keys} must be empty.
*/
public DashDownloadAction(
Uri uri, boolean isRemoveAction, @Nullable byte[] data, List<RepresentationKey> keys) {
Uri uri, boolean isRemoveAction, @Nullable byte[] data, List<StreamKey> keys) {
super(TYPE, VERSION, uri, isRemoveAction, data, keys);
}
@ -65,10 +68,10 @@ public final class DashDownloadAction extends SegmentDownloadAction<Representati
}
@Override
protected void writeKey(DataOutputStream output, RepresentationKey key) throws IOException {
protected void writeKey(DataOutputStream output, StreamKey key) throws IOException {
output.writeInt(key.periodIndex);
output.writeInt(key.adaptationSetIndex);
output.writeInt(key.representationIndex);
output.writeInt(key.groupIndex);
output.writeInt(key.trackIndex);
}
}

View File

@ -19,6 +19,7 @@ import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.offline.DownloadHelper;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.offline.TrackKey;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
@ -26,7 +27,6 @@ import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet;
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
import com.google.android.exoplayer2.source.dash.manifest.DashManifestParser;
import com.google.android.exoplayer2.source.dash.manifest.Representation;
import com.google.android.exoplayer2.source.dash.manifest.RepresentationKey;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.ParsingLoadable;
import com.google.android.exoplayer2.util.Assertions;
@ -51,9 +51,8 @@ public final class DashDownloadHelper extends DownloadHelper {
@Override
protected void prepareInternal() throws IOException {
manifest =
ParsingLoadable.load(
manifestDataSourceFactory.createDataSource(), new DashManifestParser(), uri);
DataSource dataSource = manifestDataSourceFactory.createDataSource();
manifest = ParsingLoadable.load(dataSource, new DashManifestParser(), uri);
}
/** Returns the DASH manifest. Must not be called until after preparation completes. */
@ -87,23 +86,20 @@ public final class DashDownloadHelper extends DownloadHelper {
@Override
public DashDownloadAction getDownloadAction(@Nullable byte[] data, List<TrackKey> trackKeys) {
return new DashDownloadAction(
uri, /* isRemoveAction= */ false, data, toRepresentationKeys(trackKeys));
return new DashDownloadAction(uri, /* isRemoveAction= */ false, data, toStreamKeys(trackKeys));
}
@Override
public DashDownloadAction getRemoveAction(@Nullable byte[] data) {
return new DashDownloadAction(
uri, /* isRemoveAction= */ true, data, Collections.<RepresentationKey>emptyList());
return new DashDownloadAction(uri, /* isRemoveAction= */ true, data, Collections.emptyList());
}
private static List<RepresentationKey> toRepresentationKeys(List<TrackKey> trackKeys) {
List<RepresentationKey> representationKeys = new ArrayList<>(trackKeys.size());
private static List<StreamKey> toStreamKeys(List<TrackKey> trackKeys) {
List<StreamKey> streamKeys = new ArrayList<>(trackKeys.size());
for (int i = 0; i < trackKeys.size(); i++) {
TrackKey trackKey = trackKeys.get(i);
representationKeys.add(
new RepresentationKey(trackKey.periodIndex, trackKey.groupIndex, trackKey.trackIndex));
streamKeys.add(new StreamKey(trackKey.periodIndex, trackKey.groupIndex, trackKey.trackIndex));
}
return representationKeys;
return streamKeys;
}
}

View File

@ -22,6 +22,7 @@ import com.google.android.exoplayer2.extractor.ChunkIndex;
import com.google.android.exoplayer2.offline.DownloadException;
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
import com.google.android.exoplayer2.offline.SegmentDownloader;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.dash.DashSegmentIndex;
import com.google.android.exoplayer2.source.dash.DashUtil;
import com.google.android.exoplayer2.source.dash.DashWrappingSegmentIndex;
@ -30,7 +31,6 @@ import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
import com.google.android.exoplayer2.source.dash.manifest.Period;
import com.google.android.exoplayer2.source.dash.manifest.RangedUri;
import com.google.android.exoplayer2.source.dash.manifest.Representation;
import com.google.android.exoplayer2.source.dash.manifest.RepresentationKey;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import java.io.IOException;
@ -51,9 +51,7 @@ import java.util.List;
* // period.
* DashDownloader dashDownloader =
* new DashDownloader(
* manifestUrl,
* Collections.singletonList(new RepresentationKey(0, 0, 0)),
* constructorHelper);
* manifestUrl, Collections.singletonList(new StreamKey(0, 0, 0)), constructorHelper);
* // Perform the download.
* dashDownloader.download();
* // Access downloaded data using CacheDataSource
@ -61,19 +59,17 @@ import java.util.List;
* new CacheDataSource(cache, factory.createDataSource(), CacheDataSource.FLAG_BLOCK_ON_CACHE);
* }</pre>
*/
public final class DashDownloader extends SegmentDownloader<DashManifest, RepresentationKey> {
public final class DashDownloader extends SegmentDownloader<DashManifest> {
/**
* @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 streamKeys 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,
List<RepresentationKey> representationKeys,
DownloaderConstructorHelper constructorHelper) {
super(manifestUri, representationKeys, constructorHelper);
Uri manifestUri, List<StreamKey> streamKeys, DownloaderConstructorHelper constructorHelper) {
super(manifestUri, streamKeys, constructorHelper);
}
@Override

View File

@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat;
import android.net.Uri;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.dash.manifest.SegmentBase.SingleSegmentBase;
import java.util.Arrays;
import java.util.Collections;
@ -58,17 +59,17 @@ public class DashManifestTest {
newAdaptationSet(8, representations[2][0]),
newAdaptationSet(9, representations[2][1])));
List<RepresentationKey> keys =
List<StreamKey> keys =
Arrays.asList(
new RepresentationKey(0, 0, 0),
new RepresentationKey(0, 0, 1),
new RepresentationKey(0, 1, 2),
new RepresentationKey(1, 0, 1),
new RepresentationKey(1, 1, 0),
new RepresentationKey(1, 1, 2),
new RepresentationKey(2, 0, 1),
new RepresentationKey(2, 0, 2),
new RepresentationKey(2, 1, 0));
new StreamKey(0, 0, 0),
new StreamKey(0, 0, 1),
new StreamKey(0, 1, 2),
new StreamKey(1, 0, 1),
new StreamKey(1, 1, 0),
new StreamKey(1, 1, 2),
new StreamKey(2, 0, 1),
new StreamKey(2, 0, 2),
new StreamKey(2, 1, 0));
// Keys don't need to be in any particular order
Collections.shuffle(keys, new Random(0));
@ -105,8 +106,7 @@ public class DashManifestTest {
newPeriod("4", 4, newAdaptationSet(5, representations[1][0])));
DashManifest copyManifest =
sourceManifest.copy(
Arrays.asList(new RepresentationKey(0, 0, 0), new RepresentationKey(1, 0, 0)));
sourceManifest.copy(Arrays.asList(new StreamKey(0, 0, 0), new StreamKey(1, 0, 0)));
DashManifest expectedManifest =
newDashManifest(
@ -141,12 +141,12 @@ public class DashManifestTest {
DashManifest copyManifest =
sourceManifest.copy(
Arrays.asList(
new RepresentationKey(0, 0, 0),
new RepresentationKey(0, 0, 1),
new RepresentationKey(0, 1, 2),
new RepresentationKey(2, 0, 1),
new RepresentationKey(2, 0, 2),
new RepresentationKey(2, 1, 0)));
new StreamKey(0, 0, 0),
new StreamKey(0, 0, 1),
new StreamKey(0, 1, 2),
new StreamKey(2, 0, 1),
new StreamKey(2, 0, 2),
new StreamKey(2, 1, 0)));
DashManifest expectedManifest =
newDashManifest(

View File

@ -21,7 +21,7 @@ import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.offline.DownloadAction;
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
import com.google.android.exoplayer2.source.dash.manifest.RepresentationKey;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.upstream.DummyDataSource;
import com.google.android.exoplayer2.upstream.cache.Cache;
import java.io.ByteArrayInputStream;
@ -104,16 +104,13 @@ public class DashDownloadActionTest {
DashDownloadAction action6 = newAction(uri1, /* isRemoveAction= */ false, /* data= */ null);
DashDownloadAction action7 =
newAction(
uri1, /* isRemoveAction= */ false, /* data= */ null, new RepresentationKey(0, 0, 0));
newAction(uri1, /* isRemoveAction= */ false, /* data= */ null, new StreamKey(0, 0, 0));
assertNotEqual(action6, action7);
DashDownloadAction action8 =
newAction(
uri1, /* isRemoveAction= */ false, /* data= */ null, new RepresentationKey(1, 1, 1));
newAction(uri1, /* isRemoveAction= */ false, /* data= */ null, new StreamKey(1, 1, 1));
DashDownloadAction action9 =
newAction(
uri1, /* isRemoveAction= */ false, /* data= */ null, new RepresentationKey(0, 0, 0));
newAction(uri1, /* isRemoveAction= */ false, /* data= */ null, new StreamKey(0, 0, 0));
assertNotEqual(action8, action9);
DashDownloadAction action10 = newAction(uri1, /* isRemoveAction= */ true, /* data= */ null);
@ -125,27 +122,26 @@ public class DashDownloadActionTest {
uri1,
/* isRemoveAction= */ false,
/* data= */ null,
new RepresentationKey(0, 0, 0),
new RepresentationKey(1, 1, 1));
new StreamKey(0, 0, 0),
new StreamKey(1, 1, 1));
DashDownloadAction action13 =
newAction(
uri1,
/* isRemoveAction= */ false,
/* data= */ null,
new RepresentationKey(1, 1, 1),
new RepresentationKey(0, 0, 0));
new StreamKey(1, 1, 1),
new StreamKey(0, 0, 0));
assertEqual(action12, action13);
DashDownloadAction action14 =
newAction(
uri1, /* isRemoveAction= */ false, /* data= */ null, new RepresentationKey(0, 0, 0));
newAction(uri1, /* isRemoveAction= */ false, /* data= */ null, new StreamKey(0, 0, 0));
DashDownloadAction action15 =
newAction(
uri1,
/* isRemoveAction= */ false,
/* data= */ null,
new RepresentationKey(1, 1, 1),
new RepresentationKey(0, 0, 0));
new StreamKey(1, 1, 1),
new StreamKey(0, 0, 0));
assertNotEqual(action14, action15);
DashDownloadAction action16 = newAction(uri1, /* isRemoveAction= */ false, /* data= */ null);
@ -168,8 +164,8 @@ public class DashDownloadActionTest {
uri2,
/* isRemoveAction= */ false,
/* data= */ null,
new RepresentationKey(0, 0, 0),
new RepresentationKey(1, 1, 1)));
new StreamKey(0, 0, 0),
new StreamKey(1, 1, 1)));
}
private static void assertNotEqual(DashDownloadAction action1, DashDownloadAction action2) {
@ -197,8 +193,8 @@ public class DashDownloadActionTest {
}
private static DashDownloadAction newAction(
Uri uri, boolean isRemoveAction, @Nullable byte[] data, RepresentationKey... keys) {
ArrayList<RepresentationKey> keysList = new ArrayList<>();
Uri uri, boolean isRemoveAction, @Nullable byte[] data, StreamKey... keys) {
ArrayList<StreamKey> keysList = new ArrayList<>();
Collections.addAll(keysList, keys);
return new DashDownloadAction(uri, isRemoveAction, data, keysList);
}

View File

@ -27,7 +27,7 @@ import static org.mockito.Mockito.when;
import com.google.android.exoplayer2.offline.DownloadException;
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
import com.google.android.exoplayer2.source.dash.manifest.RepresentationKey;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.testutil.FakeDataSet;
import com.google.android.exoplayer2.testutil.FakeDataSource;
import com.google.android.exoplayer2.testutil.FakeDataSource.Factory;
@ -77,7 +77,7 @@ public class DashDownloaderTest {
.setRandomData("audio_segment_2", 5)
.setRandomData("audio_segment_3", 6);
DashDownloader dashDownloader = getDashDownloader(fakeDataSet, new RepresentationKey(0, 0, 0));
DashDownloader dashDownloader = getDashDownloader(fakeDataSet, new StreamKey(0, 0, 0));
dashDownloader.download();
assertCachedData(cache, fakeDataSet);
}
@ -96,7 +96,7 @@ public class DashDownloaderTest {
.setRandomData("audio_segment_2", 5)
.setRandomData("audio_segment_3", 6);
DashDownloader dashDownloader = getDashDownloader(fakeDataSet, new RepresentationKey(0, 0, 0));
DashDownloader dashDownloader = getDashDownloader(fakeDataSet, new StreamKey(0, 0, 0));
dashDownloader.download();
assertCachedData(cache, fakeDataSet);
}
@ -115,8 +115,7 @@ public class DashDownloaderTest {
.setRandomData("text_segment_3", 3);
DashDownloader dashDownloader =
getDashDownloader(
fakeDataSet, new RepresentationKey(0, 0, 0), new RepresentationKey(0, 1, 0));
getDashDownloader(fakeDataSet, new StreamKey(0, 0, 0), new StreamKey(0, 1, 0));
dashDownloader.download();
assertCachedData(cache, fakeDataSet);
}
@ -159,7 +158,7 @@ public class DashDownloaderTest {
when(factory.createDataSource()).thenReturn(fakeDataSource);
DashDownloader dashDownloader =
getDashDownloader(factory, new RepresentationKey(0, 0, 0), new RepresentationKey(0, 1, 0));
getDashDownloader(factory, new StreamKey(0, 0, 0), new StreamKey(0, 1, 0));
dashDownloader.download();
DataSpec[] openedDataSpecs = fakeDataSource.getAndClearOpenedDataSpecs();
@ -191,7 +190,7 @@ public class DashDownloaderTest {
when(factory.createDataSource()).thenReturn(fakeDataSource);
DashDownloader dashDownloader =
getDashDownloader(factory, new RepresentationKey(0, 0, 0), new RepresentationKey(1, 0, 0));
getDashDownloader(factory, new StreamKey(0, 0, 0), new StreamKey(1, 0, 0));
dashDownloader.download();
DataSpec[] openedDataSpecs = fakeDataSource.getAndClearOpenedDataSpecs();
@ -220,7 +219,7 @@ public class DashDownloaderTest {
.endData()
.setRandomData("audio_segment_3", 6);
DashDownloader dashDownloader = getDashDownloader(fakeDataSet, new RepresentationKey(0, 0, 0));
DashDownloader dashDownloader = getDashDownloader(fakeDataSet, new StreamKey(0, 0, 0));
try {
dashDownloader.download();
fail();
@ -245,7 +244,7 @@ public class DashDownloaderTest {
.endData()
.setRandomData("audio_segment_3", 6);
DashDownloader dashDownloader = getDashDownloader(fakeDataSet, new RepresentationKey(0, 0, 0));
DashDownloader dashDownloader = getDashDownloader(fakeDataSet, new StreamKey(0, 0, 0));
assertThat(dashDownloader.getDownloadedBytes()).isEqualTo(0);
try {
@ -274,8 +273,7 @@ public class DashDownloaderTest {
.setRandomData("text_segment_3", 3);
DashDownloader dashDownloader =
getDashDownloader(
fakeDataSet, new RepresentationKey(0, 0, 0), new RepresentationKey(0, 1, 0));
getDashDownloader(fakeDataSet, new StreamKey(0, 0, 0), new StreamKey(0, 1, 0));
dashDownloader.download();
dashDownloader.remove();
assertCacheEmpty(cache);
@ -288,7 +286,7 @@ public class DashDownloaderTest {
.setData(TEST_MPD_URI, TEST_MPD_NO_INDEX)
.setRandomData("test_segment_1", 4);
DashDownloader dashDownloader = getDashDownloader(fakeDataSet, new RepresentationKey(0, 0, 0));
DashDownloader dashDownloader = getDashDownloader(fakeDataSet, new StreamKey(0, 0, 0));
try {
dashDownloader.download();
fail();
@ -299,17 +297,17 @@ public class DashDownloaderTest {
assertCacheEmpty(cache);
}
private DashDownloader getDashDownloader(FakeDataSet fakeDataSet, RepresentationKey... keys) {
private DashDownloader getDashDownloader(FakeDataSet fakeDataSet, StreamKey... keys) {
return getDashDownloader(new Factory(null).setFakeDataSet(fakeDataSet), keys);
}
private DashDownloader getDashDownloader(Factory factory, RepresentationKey... keys) {
private DashDownloader getDashDownloader(Factory factory, StreamKey... keys) {
return new DashDownloader(
TEST_MPD_URI, keysList(keys), new DownloaderConstructorHelper(cache, factory));
}
private static ArrayList<RepresentationKey> keysList(RepresentationKey... keys) {
ArrayList<RepresentationKey> keysList = new ArrayList<>();
private static ArrayList<StreamKey> keysList(StreamKey... keys) {
ArrayList<StreamKey> keysList = new ArrayList<>();
Collections.addAll(keysList, keys);
return keysList;
}

View File

@ -27,7 +27,7 @@ import android.os.ConditionVariable;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.offline.DownloadManager;
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
import com.google.android.exoplayer2.source.dash.manifest.RepresentationKey;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.testutil.DummyMainThread;
import com.google.android.exoplayer2.testutil.FakeDataSet;
import com.google.android.exoplayer2.testutil.FakeDataSource;
@ -62,8 +62,8 @@ public class DownloadManagerDashTest {
private File tempFolder;
private FakeDataSet fakeDataSet;
private DownloadManager downloadManager;
private RepresentationKey fakeRepresentationKey1;
private RepresentationKey fakeRepresentationKey2;
private StreamKey fakeStreamKey1;
private StreamKey fakeStreamKey2;
private TestDownloadManagerListener downloadManagerListener;
private File actionFile;
private DummyMainThread dummyMainThread;
@ -88,8 +88,8 @@ public class DownloadManagerDashTest {
.setRandomData("text_segment_2", 2)
.setRandomData("text_segment_3", 3);
fakeRepresentationKey1 = new RepresentationKey(0, 0, 0);
fakeRepresentationKey2 = new RepresentationKey(0, 1, 0);
fakeStreamKey1 = new StreamKey(0, 0, 0);
fakeStreamKey2 = new StreamKey(0, 1, 0);
actionFile = new File(tempFolder, "actionFile");
createDownloadManager();
}
@ -133,7 +133,7 @@ public class DownloadManagerDashTest {
@Override
public void run() {
// Setup an Action and immediately release the DM.
handleDownloadAction(fakeRepresentationKey1, fakeRepresentationKey2);
handleDownloadAction(fakeStreamKey1, fakeStreamKey2);
downloadManager.release();
}
});
@ -160,15 +160,15 @@ public class DownloadManagerDashTest {
@Test
public void testHandleDownloadAction() throws Throwable {
handleDownloadAction(fakeRepresentationKey1, fakeRepresentationKey2);
handleDownloadAction(fakeStreamKey1, fakeStreamKey2);
blockUntilTasksCompleteAndThrowAnyDownloadError();
assertCachedData(cache, fakeDataSet);
}
@Test
public void testHandleMultipleDownloadAction() throws Throwable {
handleDownloadAction(fakeRepresentationKey1);
handleDownloadAction(fakeRepresentationKey2);
handleDownloadAction(fakeStreamKey1);
handleDownloadAction(fakeStreamKey2);
blockUntilTasksCompleteAndThrowAnyDownloadError();
assertCachedData(cache, fakeDataSet);
}
@ -181,13 +181,13 @@ public class DownloadManagerDashTest {
new Runnable() {
@Override
public void run() {
handleDownloadAction(fakeRepresentationKey2);
handleDownloadAction(fakeStreamKey2);
}
})
.appendReadData(TestUtil.buildTestData(5))
.endData();
handleDownloadAction(fakeRepresentationKey1);
handleDownloadAction(fakeStreamKey1);
blockUntilTasksCompleteAndThrowAnyDownloadError();
assertCachedData(cache, fakeDataSet);
@ -195,7 +195,7 @@ public class DownloadManagerDashTest {
@Test
public void testHandleRemoveAction() throws Throwable {
handleDownloadAction(fakeRepresentationKey1);
handleDownloadAction(fakeStreamKey1);
blockUntilTasksCompleteAndThrowAnyDownloadError();
@ -210,7 +210,7 @@ public class DownloadManagerDashTest {
@Ignore
@Test
public void testHandleRemoveActionBeforeDownloadFinish() throws Throwable {
handleDownloadAction(fakeRepresentationKey1);
handleDownloadAction(fakeStreamKey1);
handleRemoveAction();
blockUntilTasksCompleteAndThrowAnyDownloadError();
@ -233,7 +233,7 @@ public class DownloadManagerDashTest {
.appendReadData(TestUtil.buildTestData(5))
.endData();
handleDownloadAction(fakeRepresentationKey1);
handleDownloadAction(fakeStreamKey1);
assertThat(downloadInProgressCondition.block(ASSERT_TRUE_TIMEOUT)).isTrue();
@ -248,7 +248,7 @@ public class DownloadManagerDashTest {
downloadManagerListener.blockUntilTasksCompleteAndThrowAnyDownloadError();
}
private void handleDownloadAction(RepresentationKey... keys) {
private void handleDownloadAction(StreamKey... keys) {
downloadManager.handleAction(newAction(TEST_MPD_URI, false, null, keys));
}
@ -280,8 +280,8 @@ public class DownloadManagerDashTest {
}
private static DashDownloadAction newAction(
Uri uri, boolean isRemoveAction, @Nullable byte[] data, RepresentationKey... keys) {
ArrayList<RepresentationKey> keysList = new ArrayList<>();
Uri uri, boolean isRemoveAction, @Nullable byte[] data, StreamKey... keys) {
ArrayList<StreamKey> keysList = new ArrayList<>();
Collections.addAll(keysList, keys);
return new DashDownloadAction(uri, isRemoveAction, data, keysList);
}

View File

@ -29,9 +29,9 @@ import com.google.android.exoplayer2.offline.DownloadManager;
import com.google.android.exoplayer2.offline.DownloadManager.TaskState;
import com.google.android.exoplayer2.offline.DownloadService;
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.scheduler.Requirements;
import com.google.android.exoplayer2.scheduler.Scheduler;
import com.google.android.exoplayer2.source.dash.manifest.RepresentationKey;
import com.google.android.exoplayer2.testutil.DummyMainThread;
import com.google.android.exoplayer2.testutil.FakeDataSet;
import com.google.android.exoplayer2.testutil.FakeDataSource;
@ -65,8 +65,8 @@ public class DownloadServiceDashTest {
private SimpleCache cache;
private File tempFolder;
private FakeDataSet fakeDataSet;
private RepresentationKey fakeRepresentationKey1;
private RepresentationKey fakeRepresentationKey2;
private StreamKey fakeStreamKey1;
private StreamKey fakeStreamKey2;
private Context context;
private DownloadService dashDownloadService;
private ConditionVariable pauseDownloadCondition;
@ -108,8 +108,8 @@ public class DownloadServiceDashTest {
.setRandomData("text_segment_3", 3);
final DataSource.Factory fakeDataSourceFactory =
new FakeDataSource.Factory(null).setFakeDataSet(fakeDataSet);
fakeRepresentationKey1 = new RepresentationKey(0, 0, 0);
fakeRepresentationKey2 = new RepresentationKey(0, 1, 0);
fakeStreamKey1 = new StreamKey(0, 0, 0);
fakeStreamKey2 = new StreamKey(0, 1, 0);
dummyMainThread.runOnMainThread(
new Runnable() {
@ -180,8 +180,8 @@ public class DownloadServiceDashTest {
@Ignore // b/78877092
@Test
public void testMultipleDownloadAction() throws Throwable {
downloadKeys(fakeRepresentationKey1);
downloadKeys(fakeRepresentationKey2);
downloadKeys(fakeStreamKey1);
downloadKeys(fakeStreamKey2);
downloadManagerListener.blockUntilTasksCompleteAndThrowAnyDownloadError();
@ -191,7 +191,7 @@ public class DownloadServiceDashTest {
@Ignore // b/78877092
@Test
public void testRemoveAction() throws Throwable {
downloadKeys(fakeRepresentationKey1, fakeRepresentationKey2);
downloadKeys(fakeStreamKey1, fakeStreamKey2);
downloadManagerListener.blockUntilTasksCompleteAndThrowAnyDownloadError();
@ -206,7 +206,7 @@ public class DownloadServiceDashTest {
@Test
public void testRemoveBeforeDownloadComplete() throws Throwable {
pauseDownloadCondition = new ConditionVariable();
downloadKeys(fakeRepresentationKey1, fakeRepresentationKey2);
downloadKeys(fakeStreamKey1, fakeStreamKey2);
removeAll();
@ -219,7 +219,7 @@ public class DownloadServiceDashTest {
callDownloadServiceOnStart(newAction(TEST_MPD_URI, true, null));
}
private void downloadKeys(RepresentationKey... keys) {
private void downloadKeys(StreamKey... keys) {
callDownloadServiceOnStart(newAction(TEST_MPD_URI, false, null, keys));
}
@ -236,8 +236,8 @@ public class DownloadServiceDashTest {
}
private static DashDownloadAction newAction(
Uri uri, boolean isRemoveAction, @Nullable byte[] data, RepresentationKey... keys) {
ArrayList<RepresentationKey> keysList = new ArrayList<>();
Uri uri, boolean isRemoveAction, @Nullable byte[] data, StreamKey... keys) {
ArrayList<StreamKey> keysList = new ArrayList<>();
Collections.addAll(keysList, keys);
return new DashDownloadAction(uri, isRemoveAction, data, keysList);
}

View File

@ -20,31 +20,31 @@ import android.support.annotation.Nullable;
import com.google.android.exoplayer2.offline.DownloadAction;
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
import com.google.android.exoplayer2.offline.SegmentDownloadAction;
import com.google.android.exoplayer2.source.hls.playlist.RenditionKey;
import com.google.android.exoplayer2.offline.StreamKey;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
/** An action to download or remove downloaded HLS streams. */
public final class HlsDownloadAction extends SegmentDownloadAction<RenditionKey> {
public final class HlsDownloadAction extends SegmentDownloadAction {
private static final String TYPE = "hls";
private static final int VERSION = 0;
public static final Deserializer DESERIALIZER =
new SegmentDownloadActionDeserializer<RenditionKey>(TYPE, VERSION) {
new SegmentDownloadActionDeserializer(TYPE, VERSION) {
@Override
protected RenditionKey readKey(DataInputStream input) throws IOException {
protected StreamKey readKey(DataInputStream input) throws IOException {
int renditionGroup = input.readInt();
int trackIndex = input.readInt();
return new RenditionKey(renditionGroup, trackIndex);
return new StreamKey(renditionGroup, trackIndex);
}
@Override
protected DownloadAction createDownloadAction(
Uri uri, boolean isRemoveAction, byte[] data, List<RenditionKey> keys) {
Uri uri, boolean isRemoveAction, byte[] data, List<StreamKey> keys) {
return new HlsDownloadAction(uri, isRemoveAction, data, keys);
}
};
@ -57,7 +57,7 @@ public final class HlsDownloadAction extends SegmentDownloadAction<RenditionKey>
* {@code removeAction} is true, {@code keys} must empty.
*/
public HlsDownloadAction(
Uri uri, boolean isRemoveAction, @Nullable byte[] data, List<RenditionKey> keys) {
Uri uri, boolean isRemoveAction, @Nullable byte[] data, List<StreamKey> keys) {
super(TYPE, VERSION, uri, isRemoveAction, data, keys);
}
@ -67,8 +67,8 @@ public final class HlsDownloadAction extends SegmentDownloadAction<RenditionKey>
}
@Override
protected void writeKey(DataOutputStream output, RenditionKey key) throws IOException {
output.writeInt(key.type);
protected void writeKey(DataOutputStream output, StreamKey key) throws IOException {
output.writeInt(key.groupIndex);
output.writeInt(key.trackIndex);
}

View File

@ -19,6 +19,7 @@ import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.offline.DownloadHelper;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.offline.TrackKey;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
@ -26,7 +27,6 @@ import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist;
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;
import com.google.android.exoplayer2.source.hls.playlist.RenditionKey;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.ParsingLoadable;
import com.google.android.exoplayer2.util.Assertions;
@ -44,7 +44,7 @@ public final class HlsDownloadHelper extends DownloadHelper {
private final DataSource.Factory manifestDataSourceFactory;
private @MonotonicNonNull HlsPlaylist playlist;
private int[] renditionTypes;
private int[] renditionGroups;
public HlsDownloadHelper(Uri uri, DataSource.Factory manifestDataSourceFactory) {
this.uri = uri;
@ -78,18 +78,18 @@ public final class HlsDownloadHelper extends DownloadHelper {
// TODO: Generate track groups as in playback. Reverse the mapping in getDownloadAction.
HlsMasterPlaylist masterPlaylist = (HlsMasterPlaylist) playlist;
TrackGroup[] trackGroups = new TrackGroup[3];
renditionTypes = new int[3];
renditionGroups = new int[3];
int trackGroupIndex = 0;
if (!masterPlaylist.variants.isEmpty()) {
renditionTypes[trackGroupIndex] = RenditionKey.TYPE_VARIANT;
renditionGroups[trackGroupIndex] = HlsMasterPlaylist.GROUP_INDEX_VARIANT;
trackGroups[trackGroupIndex++] = new TrackGroup(toFormats(masterPlaylist.variants));
}
if (!masterPlaylist.audios.isEmpty()) {
renditionTypes[trackGroupIndex] = RenditionKey.TYPE_AUDIO;
renditionGroups[trackGroupIndex] = HlsMasterPlaylist.GROUP_INDEX_AUDIO;
trackGroups[trackGroupIndex++] = new TrackGroup(toFormats(masterPlaylist.audios));
}
if (!masterPlaylist.subtitles.isEmpty()) {
renditionTypes[trackGroupIndex] = RenditionKey.TYPE_SUBTITLE;
renditionGroups[trackGroupIndex] = HlsMasterPlaylist.GROUP_INDEX_SUBTITLE;
trackGroups[trackGroupIndex++] = new TrackGroup(toFormats(masterPlaylist.subtitles));
}
return new TrackGroupArray(Arrays.copyOf(trackGroups, trackGroupIndex));
@ -97,15 +97,14 @@ public final class HlsDownloadHelper extends DownloadHelper {
@Override
public HlsDownloadAction getDownloadAction(@Nullable byte[] data, List<TrackKey> trackKeys) {
Assertions.checkNotNull(renditionTypes);
Assertions.checkNotNull(renditionGroups);
return new HlsDownloadAction(
uri, /* isRemoveAction= */ false, data, toRenditionKeys(trackKeys, renditionTypes));
uri, /* isRemoveAction= */ false, data, toStreamKeys(trackKeys, renditionGroups));
}
@Override
public HlsDownloadAction getRemoveAction(@Nullable byte[] data) {
return new HlsDownloadAction(
uri, /* isRemoveAction= */ true, data, Collections.<RenditionKey>emptyList());
return new HlsDownloadAction(uri, /* isRemoveAction= */ true, data, Collections.emptyList());
}
private static Format[] toFormats(List<HlsMasterPlaylist.HlsUrl> hlsUrls) {
@ -116,11 +115,11 @@ public final class HlsDownloadHelper extends DownloadHelper {
return formats;
}
private static List<RenditionKey> toRenditionKeys(List<TrackKey> trackKeys, int[] groups) {
List<RenditionKey> representationKeys = new ArrayList<>(trackKeys.size());
private static List<StreamKey> toStreamKeys(List<TrackKey> trackKeys, int[] groups) {
List<StreamKey> representationKeys = new ArrayList<>(trackKeys.size());
for (int i = 0; i < trackKeys.size(); i++) {
TrackKey trackKey = trackKeys.get(i);
representationKeys.add(new RenditionKey(groups[trackKey.groupIndex], trackKey.trackIndex));
representationKeys.add(new StreamKey(groups[trackKey.groupIndex], trackKey.trackIndex));
}
return representationKeys;
}

View File

@ -19,12 +19,12 @@ import android.net.Uri;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
import com.google.android.exoplayer2.offline.SegmentDownloader;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist;
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist.HlsUrl;
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;
import com.google.android.exoplayer2.source.hls.playlist.RenditionKey;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.ParsingLoadable;
@ -48,7 +48,7 @@ import java.util.List;
* HlsDownloader hlsDownloader =
* new HlsDownloader(
* playlistUri,
* Collections.singletonList(new RenditionKey(RenditionKey.TYPE_VARIANT, 0)),
* Collections.singletonList(new StreamKey(HlsMasterPlaylist.GROUP_INDEX_VARIANT, 0)),
* constructorHelper);
* // Perform the download.
* hlsDownloader.download();
@ -57,19 +57,17 @@ import java.util.List;
* new CacheDataSource(cache, factory.createDataSource(), CacheDataSource.FLAG_BLOCK_ON_CACHE);
* }</pre>
*/
public final class HlsDownloader extends SegmentDownloader<HlsPlaylist, RenditionKey> {
public final class HlsDownloader extends SegmentDownloader<HlsPlaylist> {
/**
* @param playlistUri The {@link Uri} of the playlist to be downloaded.
* @param renditionKeys Keys defining which renditions in the playlist should be selected for
* @param streamKeys 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 playlistUri,
List<RenditionKey> renditionKeys,
DownloaderConstructorHelper constructorHelper) {
super(playlistUri, renditionKeys, constructorHelper);
Uri playlistUri, List<StreamKey> streamKeys, DownloaderConstructorHelper constructorHelper) {
super(playlistUri, streamKeys, constructorHelper);
}
@Override

View File

@ -16,6 +16,7 @@
package com.google.android.exoplayer2.source.hls.playlist;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.util.MimeTypes;
import java.util.ArrayList;
import java.util.Collections;
@ -24,6 +25,10 @@ import java.util.List;
/** Represents an HLS master playlist. */
public final class HlsMasterPlaylist extends HlsPlaylist {
public static final int GROUP_INDEX_VARIANT = 0;
public static final int GROUP_INDEX_AUDIO = 1;
public static final int GROUP_INDEX_SUBTITLE = 2;
/**
* Represents a url in an HLS master playlist.
*/
@ -108,13 +113,13 @@ public final class HlsMasterPlaylist extends HlsPlaylist {
}
@Override
public HlsMasterPlaylist copy(List<RenditionKey> renditionKeys) {
public HlsMasterPlaylist copy(List<StreamKey> streamKeys) {
return new HlsMasterPlaylist(
baseUri,
tags,
copyRenditionsList(variants, RenditionKey.TYPE_VARIANT, renditionKeys),
copyRenditionsList(audios, RenditionKey.TYPE_AUDIO, renditionKeys),
copyRenditionsList(subtitles, RenditionKey.TYPE_SUBTITLE, renditionKeys),
copyRenditionsList(variants, GROUP_INDEX_VARIANT, streamKeys),
copyRenditionsList(audios, GROUP_INDEX_AUDIO, streamKeys),
copyRenditionsList(subtitles, GROUP_INDEX_SUBTITLE, streamKeys),
muxedAudioFormat,
muxedCaptionFormats);
}
@ -133,13 +138,13 @@ public final class HlsMasterPlaylist extends HlsPlaylist {
}
private static List<HlsUrl> copyRenditionsList(
List<HlsUrl> renditions, int renditionType, List<RenditionKey> renditionKeys) {
List<HlsUrl> copiedRenditions = new ArrayList<>(renditionKeys.size());
List<HlsUrl> renditions, int groupIndex, List<StreamKey> streamKeys) {
List<HlsUrl> copiedRenditions = new ArrayList<>(streamKeys.size());
for (int i = 0; i < renditions.size(); i++) {
HlsUrl rendition = renditions.get(i);
for (int j = 0; j < renditionKeys.size(); j++) {
RenditionKey renditionKey = renditionKeys.get(j);
if (renditionKey.type == renditionType && renditionKey.trackIndex == i) {
for (int j = 0; j < streamKeys.size(); j++) {
StreamKey streamKey = streamKeys.get(j);
if (streamKey.groupIndex == groupIndex && streamKey.trackIndex == i) {
copiedRenditions.add(rendition);
break;
}

View File

@ -20,6 +20,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.drm.DrmInitData;
import com.google.android.exoplayer2.offline.StreamKey;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
@ -256,7 +257,7 @@ public final class HlsMediaPlaylist extends HlsPlaylist {
}
@Override
public HlsMediaPlaylist copy(List<RenditionKey> renditionKeys) {
public HlsMediaPlaylist copy(List<StreamKey> streamKeys) {
return this;
}

View File

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

View File

@ -1,79 +0,0 @@
/*
* 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 android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/** Uniquely identifies a rendition in an {@link HlsMasterPlaylist}. */
public final class RenditionKey implements Comparable<RenditionKey> {
/** Types of rendition. */
@Retention(RetentionPolicy.SOURCE)
@IntDef({TYPE_VARIANT, TYPE_AUDIO, TYPE_SUBTITLE})
public @interface Type {}
public static final int TYPE_VARIANT = 0;
public static final int TYPE_AUDIO = 1;
public static final int TYPE_SUBTITLE = 2;
public final @Type int type;
public final int trackIndex;
public RenditionKey(@Type int type, int trackIndex) {
this.type = type;
this.trackIndex = trackIndex;
}
@Override
public String toString() {
return type + "." + trackIndex;
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
RenditionKey that = (RenditionKey) o;
return type == that.type && trackIndex == that.trackIndex;
}
@Override
public int hashCode() {
int result = type;
result = 31 * result + trackIndex;
return result;
}
// Comparable implementation.
@Override
public int compareTo(@NonNull RenditionKey other) {
int result = type - other.type;
if (result == 0) {
result = trackIndex - other.trackIndex;
}
return result;
}
}

View File

@ -36,7 +36,8 @@ import static com.google.common.truth.Truth.assertThat;
import android.net.Uri;
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
import com.google.android.exoplayer2.source.hls.playlist.RenditionKey;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist;
import com.google.android.exoplayer2.testutil.FakeDataSet;
import com.google.android.exoplayer2.testutil.FakeDataSource.Factory;
import com.google.android.exoplayer2.upstream.cache.NoOpCacheEvictor;
@ -181,17 +182,18 @@ public class HlsDownloaderTest {
assertCachedData(cache, fakeDataSet);
}
private HlsDownloader getHlsDownloader(String mediaPlaylistUri, List<RenditionKey> keys) {
private HlsDownloader getHlsDownloader(String mediaPlaylistUri, List<StreamKey> keys) {
Factory factory = new Factory(null).setFakeDataSet(fakeDataSet);
return new HlsDownloader(
Uri.parse(mediaPlaylistUri), keys, new DownloaderConstructorHelper(cache, factory));
}
private static ArrayList<RenditionKey> getKeys(int... variantIndices) {
ArrayList<RenditionKey> renditionKeys = new ArrayList<>();
private static ArrayList<StreamKey> getKeys(int... variantIndices) {
ArrayList<StreamKey> streamKeys = new ArrayList<>();
for (int variantIndex : variantIndices) {
renditionKeys.add(new RenditionKey(RenditionKey.TYPE_VARIANT, variantIndex));
final int trackIndex = variantIndex;
streamKeys.add(new StreamKey(HlsMasterPlaylist.GROUP_INDEX_VARIANT, trackIndex));
}
return renditionKeys;
return streamKeys;
}
}

View File

@ -19,6 +19,7 @@ import android.net.Uri;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.offline.FilterableManifest;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.UriUtil;
import com.google.android.exoplayer2.util.Util;
@ -33,7 +34,7 @@ import java.util.UUID;
* @see <a href="http://msdn.microsoft.com/en-us/library/ee673436(v=vs.90).aspx">IIS Smooth
* Streaming Client Manifest Format</a>
*/
public class SsManifest implements FilterableManifest<SsManifest, StreamKey> {
public class SsManifest implements FilterableManifest<SsManifest> {
public static final int UNSET_LOOKAHEAD = -1;
@ -130,7 +131,7 @@ public class SsManifest implements FilterableManifest<SsManifest, StreamKey> {
List<Format> copiedFormats = new ArrayList<>();
for (int i = 0; i < sortedKeys.size(); i++) {
StreamKey key = sortedKeys.get(i);
StreamElement streamElement = streamElements[key.streamElementIndex];
StreamElement streamElement = streamElements[key.groupIndex];
if (streamElement != currentStreamElement && currentStreamElement != null) {
// We're advancing to a new stream element. Add the current one.
copiedStreamElements.add(currentStreamElement.copy(copiedFormats.toArray(new Format[0])));

View File

@ -20,24 +20,26 @@ import android.support.annotation.Nullable;
import com.google.android.exoplayer2.offline.DownloadAction;
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
import com.google.android.exoplayer2.offline.SegmentDownloadAction;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.StreamKey;
import com.google.android.exoplayer2.offline.StreamKey;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
/** An action to download or remove downloaded SmoothStreaming streams. */
public final class SsDownloadAction extends SegmentDownloadAction<StreamKey> {
public final class SsDownloadAction extends SegmentDownloadAction {
private static final String TYPE = "ss";
private static final int VERSION = 0;
public static final Deserializer DESERIALIZER =
new SegmentDownloadActionDeserializer<StreamKey>(TYPE, VERSION) {
new SegmentDownloadActionDeserializer(TYPE, VERSION) {
@Override
protected StreamKey readKey(DataInputStream input) throws IOException {
return new StreamKey(input.readInt(), input.readInt());
int groupIndex = input.readInt();
int trackIndex = input.readInt();
return new StreamKey(groupIndex, trackIndex);
}
@Override
@ -66,7 +68,7 @@ public final class SsDownloadAction extends SegmentDownloadAction<StreamKey> {
@Override
protected void writeKey(DataOutputStream output, StreamKey key) throws IOException {
output.writeInt(key.streamElementIndex);
output.writeInt(key.groupIndex);
output.writeInt(key.trackIndex);
}

View File

@ -18,12 +18,12 @@ package com.google.android.exoplayer2.source.smoothstreaming.offline;
import android.net.Uri;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.offline.DownloadHelper;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.offline.TrackKey;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifestParser;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.StreamKey;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.ParsingLoadable;
import com.google.android.exoplayer2.util.Assertions;
@ -82,8 +82,7 @@ public final class SsDownloadHelper extends DownloadHelper {
@Override
public SsDownloadAction getRemoveAction(@Nullable byte[] data) {
return new SsDownloadAction(
uri, /* isRemoveAction= */ true, data, Collections.<StreamKey>emptyList());
return new SsDownloadAction(uri, /* isRemoveAction= */ true, data, Collections.emptyList());
}
private static List<StreamKey> toStreamKeys(List<TrackKey> trackKeys) {

View File

@ -19,11 +19,11 @@ import android.net.Uri;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
import com.google.android.exoplayer2.offline.SegmentDownloader;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.StreamElement;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifestParser;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsUtil;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.StreamKey;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.ParsingLoadable;
@ -54,7 +54,7 @@ import java.util.List;
* new CacheDataSource(cache, factory.createDataSource(), CacheDataSource.FLAG_BLOCK_ON_CACHE);
* }</pre>
*/
public final class SsDownloader extends SegmentDownloader<SsManifest, StreamKey> {
public final class SsDownloader extends SegmentDownloader<SsManifest> {
/**
* @param manifestUri The {@link Uri} of the manifest to be downloaded.

View File

@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertThat;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.ProtectionElement;
import com.google.android.exoplayer2.source.smoothstreaming.manifest.SsManifest.StreamElement;
import com.google.android.exoplayer2.util.MimeTypes;

View File

@ -20,11 +20,11 @@ import static com.google.common.truth.Truth.assertWithMessage;
import android.net.Uri;
import android.test.ActivityInstrumentationTestCase2;
import com.google.android.exoplayer2.offline.DownloaderConstructorHelper;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.dash.DashUtil;
import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet;
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
import com.google.android.exoplayer2.source.dash.manifest.Representation;
import com.google.android.exoplayer2.source.dash.manifest.RepresentationKey;
import com.google.android.exoplayer2.source.dash.offline.DashDownloader;
import com.google.android.exoplayer2.testutil.HostActivity;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
@ -106,7 +106,7 @@ public final class DashDownloadTest extends ActivityInstrumentationTestCase2<Hos
private DashDownloader downloadContent() throws Exception {
DashManifest dashManifest =
DashUtil.loadManifest(httpDataSourceFactory.createDataSource(), MANIFEST_URI);
ArrayList<RepresentationKey> keys = new ArrayList<>();
ArrayList<StreamKey> keys = new ArrayList<>();
for (int pIndex = 0; pIndex < dashManifest.getPeriodCount(); pIndex++) {
List<AdaptationSet> adaptationSets = dashManifest.getPeriod(pIndex).adaptationSets;
for (int aIndex = 0; aIndex < adaptationSets.size(); aIndex++) {
@ -116,7 +116,7 @@ public final class DashDownloadTest extends ActivityInstrumentationTestCase2<Hos
String id = representations.get(rIndex).format.id;
if (DashTestData.AAC_AUDIO_REPRESENTATION_ID.equals(id)
|| DashTestData.H264_CDD_FIXED.equals(id)) {
keys.add(new RepresentationKey(pIndex, aIndex, rIndex));
keys.add(new StreamKey(pIndex, aIndex, rIndex));
}
}
}