Add FilterableMediaPeriod interface and SmoothStreaming implementation.

This interface allows to put the mapping from tracks to StreamKeys in the same place
where we map manifest to tracks.

PiperOrigin-RevId: 225377033
This commit is contained in:
tonihei 2018-12-13 16:40:42 +00:00 committed by Oliver Woodman
parent 9c4258fef9
commit 9ed2a393b0
3 changed files with 41 additions and 11 deletions

View File

@ -19,11 +19,11 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
/** /**
* Identifies a stream in a {@link FilterableManifest} by the index of the containing period, the * A key for a subset of media which can be separately loaded (a "stream").
* index of the containing group within the period, and the index of the track within the group.
* *
* <p>Note that the interpretation of period, group and index depends on the type of manifest being * <p>The stream key consists of a period index, a group index within the period and a track index
* filtered. * within the group. The interpretation of these indices depends on the type of media for which the
* stream key is used.
*/ */
public final class StreamKey implements Comparable<StreamKey> { public final class StreamKey implements Comparable<StreamKey> {

View File

@ -19,8 +19,11 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.SeekParameters; import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType; import org.checkerframework.checker.nullness.compatqual.NullableType;
/** /**
@ -83,6 +86,22 @@ public interface MediaPeriod extends SequenceableLoader {
*/ */
TrackGroupArray getTrackGroups(); TrackGroupArray getTrackGroups();
/**
* Returns a list of {@link StreamKey stream keys} which allow to filter the media in this period
* to load only the parts needed to play the provided {@link TrackSelection}.
*
* <p>This method is only called after the period has been prepared.
*
* @param trackSelection The {@link TrackSelection} describing the tracks for which stream keys
* are requested.
* @return The corresponding {@link StreamKey stream keys} for the selected tracks, or an empty
* list if filtering is not possible and the entire media needs to be loaded to play the
* selected tracks.
*/
default List<StreamKey> getStreamKeys(TrackSelection trackSelection) {
return Collections.emptyList();
}
/** /**
* Performs a track selection. * Performs a track selection.
* *

View File

@ -20,6 +20,7 @@ import android.util.Base64;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.SeekParameters; import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.extractor.mp4.TrackEncryptionBox; import com.google.android.exoplayer2.extractor.mp4.TrackEncryptionBox;
import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory; import com.google.android.exoplayer2.source.CompositeSequenceableLoaderFactory;
import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
@ -37,12 +38,11 @@ import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.upstream.TransferListener;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
/** /** A SmoothStreaming {@link MediaPeriod}. */
* A SmoothStreaming {@link MediaPeriod}. /* package */ final class SsMediaPeriod
*/ implements MediaPeriod, SequenceableLoader.Callback<ChunkSampleStream<SsChunkSource>> {
/* package */ final class SsMediaPeriod implements MediaPeriod,
SequenceableLoader.Callback<ChunkSampleStream<SsChunkSource>> {
private static final int INITIALIZATION_VECTOR_SIZE = 8; private static final int INITIALIZATION_VECTOR_SIZE = 8;
@ -112,6 +112,8 @@ import java.util.ArrayList;
eventDispatcher.mediaPeriodReleased(); eventDispatcher.mediaPeriodReleased();
} }
// MediaPeriod implementation.
@Override @Override
public void prepare(Callback callback, long positionUs) { public void prepare(Callback callback, long positionUs) {
this.callback = callback; this.callback = callback;
@ -157,6 +159,16 @@ import java.util.ArrayList;
return positionUs; return positionUs;
} }
@Override
public List<StreamKey> getStreamKeys(TrackSelection trackSelection) {
List<StreamKey> streamKeys = new ArrayList<>(trackSelection.length());
int streamElementIndex = trackGroups.indexOf(trackSelection.getTrackGroup());
for (int i = 0; i < trackSelection.length(); i++) {
streamKeys.add(new StreamKey(streamElementIndex, trackSelection.getIndexInTrackGroup(i)));
}
return streamKeys;
}
@Override @Override
public void discardBuffer(long positionUs, boolean toKeyframe) { public void discardBuffer(long positionUs, boolean toKeyframe) {
for (ChunkSampleStream<SsChunkSource> sampleStream : sampleStreams) { for (ChunkSampleStream<SsChunkSource> sampleStream : sampleStreams) {
@ -211,7 +223,7 @@ import java.util.ArrayList;
return positionUs; return positionUs;
} }
// SequenceableLoader.Callback implementation // SequenceableLoader.Callback implementation.
@Override @Override
public void onContinueLoadingRequested(ChunkSampleStream<SsChunkSource> sampleStream) { public void onContinueLoadingRequested(ChunkSampleStream<SsChunkSource> sampleStream) {
@ -277,5 +289,4 @@ import java.util.ArrayList;
data[firstPosition] = data[secondPosition]; data[firstPosition] = data[secondPosition];
data[secondPosition] = temp; data[secondPosition] = temp;
} }
} }