Commit 9ed2a393 by tonihei Committed by Oliver Woodman

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
parent 9c4258fe
...@@ -19,11 +19,11 @@ import android.support.annotation.NonNull; ...@@ -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> {
......
...@@ -19,8 +19,11 @@ import com.google.android.exoplayer2.C; ...@@ -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;
/** /**
...@@ -84,6 +87,22 @@ public interface MediaPeriod extends SequenceableLoader { ...@@ -84,6 +87,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.
* *
* <p>The call receives track {@code selections} for each renderer, {@code mayRetainStreamFlags} * <p>The call receives track {@code selections} for each renderer, {@code mayRetainStreamFlags}
......
...@@ -20,6 +20,7 @@ import android.util.Base64; ...@@ -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; ...@@ -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; ...@@ -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;
...@@ -158,6 +160,16 @@ import java.util.ArrayList; ...@@ -158,6 +160,16 @@ import java.util.ArrayList;
} }
@Override @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
public void discardBuffer(long positionUs, boolean toKeyframe) { public void discardBuffer(long positionUs, boolean toKeyframe) {
for (ChunkSampleStream<SsChunkSource> sampleStream : sampleStreams) { for (ChunkSampleStream<SsChunkSource> sampleStream : sampleStreams) {
sampleStream.discardBuffer(positionUs, toKeyframe); sampleStream.discardBuffer(positionUs, toKeyframe);
...@@ -211,7 +223,7 @@ import java.util.ArrayList; ...@@ -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; ...@@ -277,5 +289,4 @@ import java.util.ArrayList;
data[firstPosition] = data[secondPosition]; data[firstPosition] = data[secondPosition];
data[secondPosition] = temp; data[secondPosition] = temp;
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment