TrackStream -> source.SampleStream

Also addded result constants to C to remove the dependency
on TrackStream from extractor.DefaultTrackOutput.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=127192488
This commit is contained in:
olly 2016-07-12 06:11:39 -07:00 committed by Oliver Woodman
parent be9d77c59c
commit de27b2e043
24 changed files with 307 additions and 308 deletions

View file

@ -23,7 +23,6 @@ import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.TrackStream;
import com.google.android.exoplayer2.VideoRendererEventListener;
import com.google.android.exoplayer2.VideoRendererEventListener.EventDispatcher;
import com.google.android.exoplayer2.util.MimeTypes;
@ -289,10 +288,10 @@ public final class LibvpxVideoRenderer extends Renderer {
}
int result = readSource(formatHolder, inputBuffer);
if (result == TrackStream.NOTHING_READ) {
if (result == C.RESULT_NOTHING_READ) {
return false;
}
if (result == TrackStream.FORMAT_READ) {
if (result == C.RESULT_FORMAT_READ) {
onInputFormatChanged(formatHolder.format);
return true;
}
@ -396,7 +395,7 @@ public final class LibvpxVideoRenderer extends Renderer {
private boolean readFormat() {
int result = readSource(formatHolder, null);
if (result == TrackStream.FORMAT_READ) {
if (result == C.RESULT_FORMAT_READ) {
onInputFormatChanged(formatHolder.format);
return true;
}

View file

@ -152,6 +152,21 @@ public interface C {
*/
int RESULT_MAX_LENGTH_EXCEEDED = -2;
/**
* A return value for methods where nothing was read.
*/
int RESULT_NOTHING_READ = -3;
/**
* A return value for methods where a buffer was read.
*/
int RESULT_BUFFER_READ = -4;
/**
* A return value for methods where a format was read.
*/
int RESULT_FORMAT_READ = -5;
/**
* A data type constant for data of unknown or unspecified type.
*/

View file

@ -19,6 +19,7 @@ import com.google.android.exoplayer2.ExoPlayer.ExoPlayerMessage;
import com.google.android.exoplayer2.TrackSelector.InvalidationListener;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.util.PriorityHandlerThread;
import com.google.android.exoplayer2.util.TraceUtil;
@ -682,7 +683,7 @@ import java.util.ArrayList;
}
updateTimelineState();
if (readingPeriod == null) {
// The renderers have their final TrackStreams.
// The renderers have their final SampleStreams.
return;
}
for (Renderer renderer : enabledRenderers) {
@ -701,18 +702,18 @@ import java.util.ArrayList;
TrackSelection newSelection = newTrackSelections.get(i);
if (oldSelection != null) {
if (newSelection != null) {
// Replace the renderer's TrackStream so the transition to playing the next period can
// be seamless.
// Replace the renderer's SampleStream so the transition to playing the next period
// can be seamless.
Format[] formats = new Format[newSelection.length];
for (int j = 0; j < formats.length; j++) {
formats[j] = groups.get(newSelection.group).getFormat(newSelection.getTrack(j));
}
renderer.replaceTrackStream(formats, readingPeriod.trackStreams[i],
renderer.replaceSampleStream(formats, readingPeriod.sampleStreams[i],
readingPeriod.offsetUs);
} else {
// The renderer will be disabled when transitioning to playing the next period. Mark
// the TrackStream as final to play out any remaining data.
renderer.setCurrentTrackStreamIsFinal();
// the SampleStream as final to play out any remaining data.
renderer.setCurrentSampleStreamIsFinal();
}
}
}
@ -721,7 +722,7 @@ import java.util.ArrayList;
readingPeriod = null;
// This is the last period, so signal the renderers to read the end of the stream.
for (Renderer renderer : enabledRenderers) {
renderer.setCurrentTrackStreamIsFinal();
renderer.setCurrentSampleStreamIsFinal();
}
}
}
@ -964,7 +965,7 @@ import java.util.ArrayList;
formats[j] = trackGroups.get(newSelection.group).getFormat(newSelection.getTrack(j));
}
// Enable the renderer.
renderer.enable(formats, playingPeriod.trackStreams[i], internalPositionUs, joining,
renderer.enable(formats, playingPeriod.sampleStreams[i], internalPositionUs, joining,
playingPeriod.offsetUs);
MediaClock mediaClock = renderer.getMediaClock();
if (mediaClock != null) {
@ -996,7 +997,7 @@ import java.util.ArrayList;
public final MediaPeriod mediaPeriod;
public final int index;
public final TrackStream[] trackStreams;
public final SampleStream[] sampleStreams;
public boolean prepared;
public boolean hasEnabledTracks;
@ -1014,7 +1015,7 @@ import java.util.ArrayList;
this.trackSelector = trackSelector;
this.mediaPeriod = mediaPeriod;
this.index = index;
trackStreams = new TrackStream[renderers.length];
sampleStreams = new SampleStream[renderers.length];
}
public void setNextPeriod(Period nextPeriod) {
@ -1049,7 +1050,7 @@ import java.util.ArrayList;
public void updatePeriodTrackSelection(long positionUs, LoadControl loadControl,
boolean forceRecreateStreams) throws ExoPlaybackException {
// Populate lists of streams that are being disabled/newly enabled.
ArrayList<TrackStream> oldStreams = new ArrayList<>();
ArrayList<SampleStream> oldStreams = new ArrayList<>();
ArrayList<TrackSelection> newSelections = new ArrayList<>();
for (int i = 0; i < trackSelections.length; i++) {
TrackSelection oldSelection =
@ -1057,7 +1058,7 @@ import java.util.ArrayList;
TrackSelection newSelection = trackSelections.get(i);
if (forceRecreateStreams || !Util.areEqual(oldSelection, newSelection)) {
if (oldSelection != null) {
oldStreams.add(trackStreams[i]);
oldStreams.add(sampleStreams[i]);
}
if (newSelection != null) {
newSelections.add(newSelection);
@ -1066,7 +1067,7 @@ import java.util.ArrayList;
}
// Disable streams on the period and get new streams for updated/newly-enabled tracks.
TrackStream[] newStreams = mediaPeriod.selectTracks(oldStreams, newSelections, positionUs);
SampleStream[] newStreams = mediaPeriod.selectTracks(oldStreams, newSelections, positionUs);
periodTrackSelections = trackSelections;
hasEnabledTracks = false;
for (int i = 0; i < trackSelections.length; i++) {
@ -1075,12 +1076,12 @@ import java.util.ArrayList;
hasEnabledTracks = true;
int index = newSelections.indexOf(selection);
if (index != -1) {
trackStreams[i] = newStreams[index];
sampleStreams[i] = newStreams[index];
} else {
// This selection/stream is unchanged.
}
} else {
trackStreams[i] = null;
sampleStreams[i] = null;
}
}

View file

@ -461,7 +461,7 @@ public abstract class MediaCodecRenderer extends Renderer {
private void readFormat() throws ExoPlaybackException {
int result = readSource(formatHolder, null);
if (result == TrackStream.FORMAT_READ) {
if (result == C.RESULT_FORMAT_READ) {
onInputFormatChanged(formatHolder.format);
}
}
@ -544,7 +544,7 @@ public abstract class MediaCodecRenderer extends Renderer {
int adaptiveReconfigurationBytes = 0;
if (waitingForKeys) {
// We've already read an encrypted sample into buffer, and are waiting for keys.
result = TrackStream.BUFFER_READ;
result = C.RESULT_BUFFER_READ;
} else {
// For adaptive reconfiguration OMX decoders expect all reconfiguration data to be supplied
// at the start of the buffer that also contains the first frame in the new format.
@ -559,10 +559,10 @@ public abstract class MediaCodecRenderer extends Renderer {
result = readSource(formatHolder, buffer);
}
if (result == TrackStream.NOTHING_READ) {
if (result == C.RESULT_NOTHING_READ) {
return false;
}
if (result == TrackStream.FORMAT_READ) {
if (result == C.RESULT_FORMAT_READ) {
if (codecReconfigurationState == RECONFIGURATION_STATE_QUEUE_PENDING) {
// We received two formats in a row. Clear the current buffer of any reconfiguration data
// associated with the first format.

View file

@ -16,13 +16,14 @@
package com.google.android.exoplayer2;
import com.google.android.exoplayer2.ExoPlayer.ExoPlayerComponent;
import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes;
import java.io.IOException;
/**
* Renders a single component of media.
* Renders media samples read from a {@link SampleStream}.
* <p>
* Internally, a renderer's lifecycle is managed by the owning {@link ExoPlayer}. The player will
* transition its renderers through various states as the overall playback state changes. The valid
@ -107,7 +108,7 @@ public abstract class Renderer implements ExoPlayerComponent {
private int index;
private int state;
private TrackStream stream;
private SampleStream stream;
private long streamOffsetUs;
private boolean readEndOfStream;
private boolean streamIsFinal;
@ -169,22 +170,22 @@ public abstract class Renderer implements ExoPlayerComponent {
}
/**
* Enable the renderer to consume from the specified {@link TrackStream}.
* Enable the renderer to consume from the specified {@link SampleStream}.
*
* @param formats The enabled formats.
* @param stream The track stream from which the renderer should consume.
* @param stream The {@link SampleStream} from which the renderer should consume.
* @param positionUs The player's current position.
* @param joining Whether this renderer is being enabled to join an ongoing playback.
* @param offsetUs The offset to be added to timestamps of buffers read from {@code stream}
* before they are renderered.
* before they are rendered.
* @throws ExoPlaybackException If an error occurs.
*/
/* package */ final void enable(Format[] formats, TrackStream stream, long positionUs,
/* package */ final void enable(Format[] formats, SampleStream stream, long positionUs,
boolean joining, long offsetUs) throws ExoPlaybackException {
Assertions.checkState(state == STATE_DISABLED);
state = STATE_ENABLED;
onEnabled(joining);
replaceTrackStream(formats, stream, offsetUs);
replaceSampleStream(formats, stream, offsetUs);
onReset(positionUs, joining);
}
@ -201,15 +202,15 @@ public abstract class Renderer implements ExoPlayerComponent {
}
/**
* Sets the {@link TrackStream} from which samples will be consumed.
* Sets the {@link SampleStream} from which samples will be consumed.
*
* @param formats The enabled formats.
* @param stream The track stream from which the renderer should consume.
* @param stream The {@link SampleStream} from which the renderer should consume.
* @param offsetUs The offset to be added to timestamps of buffers read from {@code stream} before
* they are renderered.
* they are rendered.
* @throws ExoPlaybackException If an error occurs.
*/
/* package */ final void replaceTrackStream(Format[] formats, TrackStream stream, long offsetUs)
/* package */ final void replaceSampleStream(Format[] formats, SampleStream stream, long offsetUs)
throws ExoPlaybackException {
Assertions.checkState(!streamIsFinal);
this.stream = stream;
@ -256,17 +257,17 @@ public abstract class Renderer implements ExoPlayerComponent {
}
/**
* Returns whether the renderer has read the current {@link TrackStream} to the end.
* Returns whether the renderer has read the current {@link SampleStream} to the end.
*/
/* package */ final boolean hasReadStreamToEnd() {
return readEndOfStream;
}
/**
* Signals to the renderer that the current {@link TrackStream} will be the final one supplied
* Signals to the renderer that the current {@link SampleStream} will be the final one supplied
* before it is next disabled or reset.
*/
/* package */ final void setCurrentTrackStreamIsFinal() {
/* package */ final void setCurrentSampleStreamIsFinal() {
streamIsFinal = true;
}
@ -338,7 +339,7 @@ public abstract class Renderer implements ExoPlayerComponent {
// Methods to be called by subclasses.
/**
* Throws an error that's preventing the renderer from reading from its {@link TrackStream}. Does
* Throws an error that's preventing the renderer from reading from its {@link SampleStream}. Does
* nothing if no such error exists.
* <p>
* This method may be called when the renderer is in the following states:
@ -354,14 +355,14 @@ public abstract class Renderer implements ExoPlayerComponent {
/**
* Reads from the enabled upstream source.
*
* @see TrackStream#readData(FormatHolder, DecoderInputBuffer)
* @see SampleStream#readData(FormatHolder, DecoderInputBuffer)
*/
protected final int readSource(FormatHolder formatHolder, DecoderInputBuffer buffer) {
int result = stream.readData(formatHolder, buffer);
if (result == TrackStream.BUFFER_READ) {
if (result == C.RESULT_BUFFER_READ) {
if (buffer.isEndOfStream()) {
readEndOfStream = true;
return streamIsFinal ? TrackStream.BUFFER_READ : TrackStream.NOTHING_READ;
return streamIsFinal ? C.RESULT_BUFFER_READ : C.RESULT_NOTHING_READ;
}
buffer.timeUs += streamOffsetUs;
}
@ -410,7 +411,7 @@ public abstract class Renderer implements ExoPlayerComponent {
protected abstract int supportsFormat(Format format) throws ExoPlaybackException;
/**
* Incrementally renders the {@link TrackStream}.
* Incrementally renders the {@link SampleStream}.
* <p>
* This method should return quickly, and should not block if the renderer is unable to make
* useful progress.

View file

@ -20,9 +20,9 @@ import com.google.android.exoplayer2.DecoderInputBuffer;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.SequenceableLoader;
import com.google.android.exoplayer2.TrackStream;
import com.google.android.exoplayer2.extractor.DefaultTrackOutput;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.Loader;
import com.google.android.exoplayer2.util.Assertions;
@ -33,14 +33,14 @@ import java.util.LinkedList;
import java.util.List;
/**
* A {@link TrackStream} that loads media in {@link Chunk}s, obtained from a {@link ChunkSource}.
* A {@link SampleStream} that loads media in {@link Chunk}s, obtained from a {@link ChunkSource}.
*/
public class ChunkTrackStream<T extends ChunkSource> implements TrackStream, SequenceableLoader,
public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, SequenceableLoader,
Loader.Callback<Chunk> {
private final int trackType;
private final T chunkSource;
private final SequenceableLoader.Callback<ChunkTrackStream<T>> callback;
private final SequenceableLoader.Callback<ChunkSampleStream<T>> callback;
private final EventDispatcher eventDispatcher;
private final int minLoadableRetryCount;
private final LinkedList<BaseMediaChunk> mediaChunks;
@ -66,15 +66,15 @@ public class ChunkTrackStream<T extends ChunkSource> implements TrackStream, Seq
* before propagating an error.
* @param eventDispatcher A dispatcher to notify of events.
*/
public ChunkTrackStream(int trackType, T chunkSource,
SequenceableLoader.Callback<ChunkTrackStream<T>> callback, Allocator allocator,
public ChunkSampleStream(int trackType, T chunkSource,
SequenceableLoader.Callback<ChunkSampleStream<T>> callback, Allocator allocator,
long positionUs, int minLoadableRetryCount, EventDispatcher eventDispatcher) {
this.trackType = trackType;
this.chunkSource = chunkSource;
this.callback = callback;
this.eventDispatcher = eventDispatcher;
this.minLoadableRetryCount = minLoadableRetryCount;
loader = new Loader("Loader:ChunkTrackStream");
loader = new Loader("Loader:ChunkSampleStream");
nextChunkHolder = new ChunkHolder();
mediaChunks = new LinkedList<>();
readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks);
@ -155,7 +155,7 @@ public class ChunkTrackStream<T extends ChunkSource> implements TrackStream, Seq
loader.release();
}
// TrackStream implementation.
// SampleStream implementation.
@Override
public boolean isReady() {
@ -173,7 +173,7 @@ public class ChunkTrackStream<T extends ChunkSource> implements TrackStream, Seq
@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
if (isPendingReset()) {
return NOTHING_READ;
return C.RESULT_NOTHING_READ;
}
while (mediaChunks.size() > 1

View file

@ -19,7 +19,7 @@ import java.io.IOException;
import java.util.List;
/**
* A provider of {@link Chunk}s for a {@link ChunkTrackStream} to load.
* A provider of {@link Chunk}s for a {@link ChunkSampleStream} to load.
*/
public interface ChunkSource {
@ -62,7 +62,7 @@ public interface ChunkSource {
void getNextChunk(MediaChunk previous, long playbackPositionUs, ChunkHolder out);
/**
* Invoked when the {@link ChunkTrackStream} has finished loading a chunk obtained from this
* Invoked when the {@link ChunkSampleStream} has finished loading a chunk obtained from this
* source.
* <p>
* This method should only be called when the source is enabled.
@ -72,7 +72,7 @@ public interface ChunkSource {
void onChunkLoadCompleted(Chunk chunk);
/**
* Invoked when the {@link ChunkTrackStream} encounters an error loading a chunk obtained from
* Invoked when the {@link ChunkSampleStream} encounters an error loading a chunk obtained from
* this source.
* <p>
* This method should only be called when the source is enabled.

View file

@ -25,7 +25,6 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.MediaClock;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.TrackStream;
import com.google.android.exoplayer2.audio.AudioCapabilities;
import com.google.android.exoplayer2.audio.AudioTrack;
import com.google.android.exoplayer2.util.MimeTypes;
@ -241,10 +240,10 @@ public abstract class AudioDecoderRenderer extends Renderer implements MediaCloc
}
int result = readSource(formatHolder, inputBuffer);
if (result == TrackStream.NOTHING_READ) {
if (result == C.RESULT_NOTHING_READ) {
return false;
}
if (result == TrackStream.FORMAT_READ) {
if (result == C.RESULT_FORMAT_READ) {
onInputFormatChanged(formatHolder.format);
return true;
}
@ -354,7 +353,7 @@ public abstract class AudioDecoderRenderer extends Renderer implements MediaCloc
private boolean readFormat() {
int result = readSource(formatHolder, null);
if (result == TrackStream.FORMAT_READ) {
if (result == C.RESULT_FORMAT_READ) {
onInputFormatChanged(formatHolder.format);
return true;
}

View file

@ -19,7 +19,6 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DecoderInputBuffer;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.TrackStream;
import com.google.android.exoplayer2.upstream.Allocation;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.util.Assertions;
@ -252,22 +251,22 @@ public final class DefaultTrackOutput implements TrackOutput {
* @param loadingFinished True if an empty queue should be considered the end of the stream.
* @param decodeOnlyUntilUs If a buffer is read, the {@link C#BUFFER_FLAG_DECODE_ONLY} flag will
* be set if the buffer's timestamp is less than this value.
* @return The result, which can be {@link TrackStream#NOTHING_READ},
* {@link TrackStream#FORMAT_READ} or {@link TrackStream#BUFFER_READ}.
* @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or
* {@link C#RESULT_BUFFER_READ}.
*/
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean loadingFinished,
long decodeOnlyUntilUs) {
switch (infoQueue.readData(formatHolder, buffer, downstreamFormat, extrasHolder)) {
case TrackStream.NOTHING_READ:
case C.RESULT_NOTHING_READ:
if (loadingFinished) {
buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
return TrackStream.BUFFER_READ;
return C.RESULT_BUFFER_READ;
}
return TrackStream.NOTHING_READ;
case TrackStream.FORMAT_READ:
return C.RESULT_NOTHING_READ;
case C.RESULT_FORMAT_READ:
downstreamFormat = formatHolder.format;
return TrackStream.FORMAT_READ;
case TrackStream.BUFFER_READ:
return C.RESULT_FORMAT_READ;
case C.RESULT_BUFFER_READ:
if (buffer.timeUs < decodeOnlyUntilUs) {
buffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
}
@ -280,7 +279,7 @@ public final class DefaultTrackOutput implements TrackOutput {
readData(extrasHolder.offset, buffer.data, extrasHolder.size);
// Advance the read head.
dropDownstreamTo(extrasHolder.nextOffset);
return TrackStream.BUFFER_READ;
return C.RESULT_BUFFER_READ;
default:
throw new IllegalStateException();
}
@ -747,22 +746,22 @@ public final class DefaultTrackOutput implements TrackOutput {
* @param downstreamFormat The current downstream {@link Format}. If the format of the next
* sample is different to the current downstream format then a format will be read.
* @param extrasHolder The holder into which extra sample information should be written.
* @return The result, which can be {@link TrackStream#NOTHING_READ},
* {@link TrackStream#FORMAT_READ} or {@link TrackStream#BUFFER_READ}.
* @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ}
* or {@link C#RESULT_BUFFER_READ}.
*/
public synchronized int readData(FormatHolder formatHolder, DecoderInputBuffer buffer,
Format downstreamFormat, BufferExtrasHolder extrasHolder) {
if (queueSize == 0) {
if (upstreamFormat != null && upstreamFormat != downstreamFormat) {
formatHolder.format = upstreamFormat;
return TrackStream.FORMAT_READ;
return C.RESULT_FORMAT_READ;
}
return TrackStream.NOTHING_READ;
return C.RESULT_NOTHING_READ;
}
if (formats[relativeReadIndex] != downstreamFormat) {
formatHolder.format = formats[relativeReadIndex];
return TrackStream.FORMAT_READ;
return C.RESULT_FORMAT_READ;
}
buffer.timeUs = timesUs[relativeReadIndex];
@ -782,7 +781,7 @@ public final class DefaultTrackOutput implements TrackOutput {
extrasHolder.nextOffset = queueSize > 0 ? offsets[relativeReadIndex]
: extrasHolder.offset + extrasHolder.size;
return TrackStream.BUFFER_READ;
return C.RESULT_BUFFER_READ;
}
/**

View file

@ -21,7 +21,6 @@ import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.TrackStream;
import com.google.android.exoplayer2.util.Assertions;
import android.os.Handler;
@ -106,7 +105,7 @@ public final class MetadataRenderer<T> extends Renderer implements Callback {
if (!inputStreamEnded && pendingMetadata == null) {
buffer.clear();
int result = readSource(formatHolder, buffer);
if (result == TrackStream.BUFFER_READ) {
if (result == C.RESULT_BUFFER_READ) {
if (buffer.isEndOfStream()) {
inputStreamEnded = true;
} else {

View file

@ -17,7 +17,6 @@ package com.google.android.exoplayer2.source;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.TrackStream;
import com.google.android.exoplayer2.chunk.FormatEvaluator;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.util.Assertions;
@ -159,7 +158,7 @@ public interface AdaptiveMediaSourceEventListener {
/**
* Invoked when a downstream format change occurs (i.e. when the format of the media being read
* from one or more {@link TrackStream}s provided by the source changes).
* from one or more {@link SampleStream}s provided by the source changes).
*
* @param trackType The type of the media. One of the {@link C} {@code TRACK_TYPE_*} constants.
* @param format The new format.

View file

@ -22,7 +22,6 @@ import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.SequenceableLoader;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.TrackStream;
import com.google.android.exoplayer2.extractor.DefaultExtractorInput;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.DefaultTrackOutput;
@ -234,19 +233,19 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
}
@Override
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
public SampleStream[] selectTracks(List<SampleStream> oldStreams,
List<TrackSelection> newSelections, long positionUs) {
Assertions.checkState(prepared);
// Unselect old tracks.
for (int i = 0; i < oldStreams.size(); i++) {
int track = ((TrackStreamImpl) oldStreams.get(i)).track;
int track = ((SampleStreamImpl) oldStreams.get(i)).track;
Assertions.checkState(trackEnabledStates[track]);
enabledTrackCount--;
trackEnabledStates[track] = false;
sampleQueues[track].disable();
}
// Select new tracks.
TrackStream[] newStreams = new TrackStream[newSelections.size()];
SampleStream[] newStreams = new SampleStream[newSelections.size()];
for (int i = 0; i < newStreams.length; i++) {
TrackSelection selection = newSelections.get(i);
Assertions.checkState(selection.length == 1);
@ -255,7 +254,7 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
Assertions.checkState(!trackEnabledStates[track]);
enabledTrackCount++;
trackEnabledStates[track] = true;
newStreams[i] = new TrackStreamImpl(track);
newStreams[i] = new SampleStreamImpl(track);
}
// At the time of the first track selection all queues will be enabled, so we need to disable
// any that are no longer required.
@ -379,7 +378,7 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
loadingFinished = false;
}
// TrackStream methods.
// SampleStream methods.
/* package */ boolean isReady(int track) {
return loadingFinished || (!isPendingReset() && !sampleQueues[track].isEmpty());
@ -391,7 +390,7 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
/* package */ int readData(int track, FormatHolder formatHolder, DecoderInputBuffer buffer) {
if (notifyReset || isPendingReset()) {
return TrackStream.NOTHING_READ;
return C.RESULT_NOTHING_READ;
}
return sampleQueues[track].readData(formatHolder, buffer, loadingFinished, lastSeekPositionUs);
@ -580,11 +579,11 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
}
}
private final class TrackStreamImpl implements TrackStream {
private final class SampleStreamImpl implements SampleStream {
private final int track;
public TrackStreamImpl(int track) {
public SampleStreamImpl(int track) {
this.track = track;
}

View file

@ -18,7 +18,6 @@ package com.google.android.exoplayer2.source;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.SequenceableLoader;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.TrackStream;
import com.google.android.exoplayer2.upstream.Allocator;
import java.io.IOException;
@ -94,28 +93,28 @@ public interface MediaPeriod extends SequenceableLoader {
/**
* Modifies the selected tracks.
* <p>
* {@link TrackStream}s corresponding to tracks being unselected are passed in {@code oldStreams}.
* Tracks being selected are specified in {@code newSelections}. Each new {@link TrackSelection}
* must have a {@link TrackSelection#group} index distinct from those of currently enabled tracks,
* except for those being unselected.
* {@link SampleStream}s corresponding to tracks being unselected are passed in
* {@code oldStreams}. Tracks being selected are specified in {@code newSelections}. Each new
* {@link TrackSelection} must have a {@link TrackSelection#group} index distinct from those of
* currently enabled tracks, except for those being unselected.
* <p>
* This method should only be called after the period has been prepared.
*
* @param oldStreams {@link TrackStream}s corresponding to tracks being unselected. May be empty
* @param oldStreams {@link SampleStream}s corresponding to tracks being unselected. May be empty
* but must not be null.
* @param newSelections {@link TrackSelection}s that define tracks being selected. May be empty
* but must not be null.
* @param positionUs The current playback position in microseconds.
* @return The {@link TrackStream}s corresponding to each of the newly selected tracks.
* @return The {@link SampleStream}s corresponding to each of the newly selected tracks.
*/
TrackStream[] selectTracks(List<TrackStream> oldStreams, List<TrackSelection> newSelections,
SampleStream[] selectTracks(List<SampleStream> oldStreams, List<TrackSelection> newSelections,
long positionUs);
/**
* Attempts to read a discontinuity.
* <p>
* After this method has returned a value other than {@link C#UNSET_TIME_US}, all
* {@link TrackStream}s provided by the period are guaranteed to start from a key frame.
* {@link SampleStream}s provided by the period are guaranteed to start from a key frame.
*
* @return If a discontinuity was read then the playback position in microseconds after the
* discontinuity. Else {@link C#UNSET_TIME_US}.
@ -135,7 +134,7 @@ public interface MediaPeriod extends SequenceableLoader {
/**
* Attempts to seek to the specified position in microseconds.
* <p>
* After this method has been called, all {@link TrackStream}s provided by the period are
* After this method has been called, all {@link SampleStream}s provided by the period are
* guaranteed to start from a key frame.
* <p>
* This method should only be called when at least one track is selected.

View file

@ -19,7 +19,6 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.CompositeSequenceableLoader;
import com.google.android.exoplayer2.SequenceableLoader;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.TrackStream;
import com.google.android.exoplayer2.upstream.Allocator;
import android.util.Pair;
@ -35,7 +34,7 @@ import java.util.List;
public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callback {
private final MediaPeriod[] periods;
private final IdentityHashMap<TrackStream, MediaPeriod> trackStreamPeriods;
private final IdentityHashMap<SampleStream, MediaPeriod> sampleStreamPeriods;
private final int[] selectedTrackCounts;
private Callback callback;
@ -50,7 +49,7 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
public MergingMediaPeriod(MediaPeriod... periods) {
this.periods = periods;
pendingChildPrepareCount = periods.length;
trackStreamPeriods = new IdentityHashMap<>();
sampleStreamPeriods = new IdentityHashMap<>();
selectedTrackCounts = new int[periods.length];
}
@ -80,9 +79,9 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
}
@Override
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
public SampleStream[] selectTracks(List<SampleStream> oldStreams,
List<TrackSelection> newSelections, long positionUs) {
TrackStream[] newStreams = new TrackStream[newSelections.size()];
SampleStream[] newStreams = new SampleStream[newSelections.size()];
// Select tracks for each period.
int enabledPeriodCount = 0;
for (int i = 0; i < periods.length; i++) {
@ -206,15 +205,15 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
// Internal methods.
private int selectTracks(MediaPeriod period, List<TrackStream> allOldStreams,
List<TrackSelection> allNewSelections, long positionUs, TrackStream[] allNewStreams,
private int selectTracks(MediaPeriod period, List<SampleStream> allOldStreams,
List<TrackSelection> allNewSelections, long positionUs, SampleStream[] allNewStreams,
boolean seenFirstTrackSelection) {
// Get the subset of the old streams for the period.
ArrayList<TrackStream> oldStreams = new ArrayList<>();
ArrayList<SampleStream> oldStreams = new ArrayList<>();
for (int i = 0; i < allOldStreams.size(); i++) {
TrackStream stream = allOldStreams.get(i);
if (trackStreamPeriods.get(stream) == period) {
trackStreamPeriods.remove(stream);
SampleStream stream = allOldStreams.get(i);
if (sampleStreamPeriods.get(stream) == period) {
sampleStreamPeriods.remove(stream);
oldStreams.add(stream);
}
}
@ -234,10 +233,10 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
return 0;
}
// Perform the selection.
TrackStream[] newStreams = period.selectTracks(oldStreams, newSelections, positionUs);
SampleStream[] newStreams = period.selectTracks(oldStreams, newSelections, positionUs);
for (int j = 0; j < newStreams.length; j++) {
allNewStreams[newSelectionOriginalIndices[j]] = newStreams[j];
trackStreamPeriods.put(newStreams[j], period);
sampleStreamPeriods.put(newStreams[j], period);
}
return newSelections.size() - oldStreams.size();
}

View file

@ -13,27 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2;
package com.google.android.exoplayer2.source;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DecoderInputBuffer;
import com.google.android.exoplayer2.FormatHolder;
import java.io.IOException;
/**
* A stream of media data.
* A stream of media samples (and associated format information).
*/
public interface TrackStream {
/**
* Nothing was read.
*/
int NOTHING_READ = -1;
/**
* The buffer was populated.
*/
int BUFFER_READ = -2;
/**
* A format was read.
*/
int FORMAT_READ = -3;
public interface SampleStream {
/**
* Returns whether data is available to be read.
@ -59,8 +50,8 @@ public interface TrackStream {
* @param buffer A {@link DecoderInputBuffer} to populate in the case of reading a sample or the
* end of the stream. If the end of the stream has been reached, the
* {@link C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
* @return The result, which can be {@link #NOTHING_READ}, {@link #FORMAT_READ} or
* {@link #BUFFER_READ}.
* @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or
* {@link C#RESULT_BUFFER_READ}.
*/
int readData(FormatHolder formatHolder, DecoderInputBuffer buffer);

View file

@ -20,7 +20,6 @@ import com.google.android.exoplayer2.DecoderInputBuffer;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.TrackStream;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSourceFactory;
@ -39,7 +38,7 @@ import java.util.List;
/**
* Loads data at a given {@link Uri} as a single sample belonging to a single {@link MediaPeriod}.
*/
public final class SingleSampleMediaSource implements MediaPeriod, MediaSource, TrackStream,
public final class SingleSampleMediaSource implements MediaPeriod, MediaSource, SampleStream,
Loader.Callback<SingleSampleMediaSource.SourceLoadable> {
/**
@ -151,12 +150,12 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource,
}
@Override
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
public SampleStream[] selectTracks(List<SampleStream> oldStreams,
List<TrackSelection> newSelections, long positionUs) {
Assertions.checkState(oldStreams.size() <= 1);
Assertions.checkState(newSelections.size() <= 1);
// Select new tracks.
TrackStream[] newStreams = new TrackStream[newSelections.size()];
SampleStream[] newStreams = new SampleStream[newSelections.size()];
if (!newSelections.isEmpty()) {
newStreams[0] = this;
streamState = STREAM_STATE_SEND_FORMAT;
@ -204,7 +203,7 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource,
sampleSize = 0;
}
// TrackStream implementation.
// SampleStream implementation.
@Override
public boolean isReady() {
@ -225,23 +224,23 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource,
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
if (streamState == STREAM_STATE_END_OF_STREAM) {
buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
return BUFFER_READ;
return C.RESULT_BUFFER_READ;
} else if (streamState == STREAM_STATE_SEND_FORMAT) {
formatHolder.format = format;
streamState = STREAM_STATE_SEND_SAMPLE;
return FORMAT_READ;
return C.RESULT_FORMAT_READ;
}
Assertions.checkState(streamState == STREAM_STATE_SEND_SAMPLE);
if (!loadingFinished) {
return NOTHING_READ;
return C.RESULT_NOTHING_READ;
} else {
buffer.timeUs = 0;
buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
buffer.ensureSpaceForWrite(sampleSize);
buffer.data.put(sampleData, 0, sampleSize);
streamState = STREAM_STATE_END_OF_STREAM;
return BUFFER_READ;
return C.RESULT_BUFFER_READ;
}
}

View file

@ -16,7 +16,6 @@
package com.google.android.exoplayer2.source;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.TrackStream;
import com.google.android.exoplayer2.util.Assertions;
import java.util.Arrays;
@ -24,8 +23,8 @@ import java.util.Arrays;
/**
* Defines a group of tracks exposed by a {@link MediaPeriod}.
* <p>
* A {@link MediaPeriod} is only able to provide one {@link TrackStream} corresponding to a group
* at any given time. If {@link #adaptive} is true this {@link TrackStream} can adapt between
* A {@link MediaPeriod} is only able to provide one {@link SampleStream} corresponding to a group
* at any given time. If {@link #adaptive} is true this {@link SampleStream} can adapt between
* multiple tracks within the group. If {@link #adaptive} is false then it's only possible to
* consume one track from the group at a given time.
*/

View file

@ -21,14 +21,14 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.SequenceableLoader;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.TrackStream;
import com.google.android.exoplayer2.chunk.ChunkTrackStream;
import com.google.android.exoplayer2.chunk.ChunkSampleStream;
import com.google.android.exoplayer2.chunk.FormatEvaluator;
import com.google.android.exoplayer2.chunk.FormatEvaluator.AdaptiveEvaluator;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.dash.mpd.AdaptationSet;
@ -66,7 +66,7 @@ import java.util.TimeZone;
* A DASH {@link MediaSource}.
*/
public final class DashMediaSource implements MediaPeriod, MediaSource,
SequenceableLoader.Callback<ChunkTrackStream<DashChunkSource>> {
SequenceableLoader.Callback<ChunkSampleStream<DashChunkSource>> {
/**
* The default minimum number of times to retry loading data prior to failing.
@ -84,7 +84,7 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
private DataSource dataSource;
private Loader loader;
private ChunkTrackStream<DashChunkSource>[] trackStreams;
private ChunkSampleStream<DashChunkSource>[] sampleStreams;
private CompositeSequenceableLoader sequenceableLoader;
private Uri manifestUri;
@ -139,8 +139,8 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
public void prepare(Callback callback, Allocator allocator, long positionUs) {
this.callback = callback;
this.allocator = allocator;
trackStreams = newTrackStreamArray(0);
sequenceableLoader = new CompositeSequenceableLoader(trackStreams);
sampleStreams = newSampleStreamArray(0);
sequenceableLoader = new CompositeSequenceableLoader(sampleStreams);
dataSource = dataSourceFactory.createDataSource();
loader = new Loader("Loader:DashMediaSource");
manifestRefreshHandler = new Handler();
@ -163,32 +163,32 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
}
@Override
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
public SampleStream[] selectTracks(List<SampleStream> oldStreams,
List<TrackSelection> newSelections, long positionUs) {
int newEnabledSourceCount = trackStreams.length + newSelections.size() - oldStreams.size();
ChunkTrackStream<DashChunkSource>[] newTrackStreams =
newTrackStreamArray(newEnabledSourceCount);
int newEnabledSourceCount = sampleStreams.length + newSelections.size() - oldStreams.size();
ChunkSampleStream<DashChunkSource>[] newSampleStreams =
newSampleStreamArray(newEnabledSourceCount);
int newEnabledSourceIndex = 0;
// Iterate over currently enabled streams, either releasing them or adding them to the new list.
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
if (oldStreams.contains(trackStream)) {
trackStream.release();
for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) {
if (oldStreams.contains(sampleStream)) {
sampleStream.release();
} else {
newTrackStreams[newEnabledSourceIndex++] = trackStream;
newSampleStreams[newEnabledSourceIndex++] = sampleStream;
}
}
// Instantiate and return new streams.
TrackStream[] streamsToReturn = new TrackStream[newSelections.size()];
SampleStream[] streamsToReturn = new SampleStream[newSelections.size()];
for (int i = 0; i < newSelections.size(); i++) {
newTrackStreams[newEnabledSourceIndex] = buildTrackStream(newSelections.get(i), positionUs);
streamsToReturn[i] = newTrackStreams[newEnabledSourceIndex];
newSampleStreams[newEnabledSourceIndex] = buildSampleStream(newSelections.get(i), positionUs);
streamsToReturn[i] = newSampleStreams[newEnabledSourceIndex];
newEnabledSourceIndex++;
}
trackStreams = newTrackStreams;
sequenceableLoader = new CompositeSequenceableLoader(trackStreams);
sampleStreams = newSampleStreams;
sequenceableLoader = new CompositeSequenceableLoader(sampleStreams);
return streamsToReturn;
}
@ -210,8 +210,8 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
@Override
public long getBufferedPositionUs() {
long bufferedPositionUs = Long.MAX_VALUE;
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
long rendererBufferedPositionUs = trackStream.getBufferedPositionUs();
for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) {
long rendererBufferedPositionUs = sampleStream.getBufferedPositionUs();
if (rendererBufferedPositionUs != C.END_OF_SOURCE_US) {
bufferedPositionUs = Math.min(bufferedPositionUs, rendererBufferedPositionUs);
}
@ -221,8 +221,8 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
@Override
public long seekToUs(long positionUs) {
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
trackStream.seekToUs(positionUs);
for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) {
sampleStream.seekToUs(positionUs);
}
return positionUs;
}
@ -234,11 +234,11 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
loader.release();
loader = null;
}
if (trackStreams != null) {
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
trackStream.release();
if (sampleStreams != null) {
for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) {
sampleStream.release();
}
trackStreams = null;
sampleStreams = null;
}
sequenceableLoader = null;
manifestLoadStartTimestamp = 0;
@ -260,7 +260,7 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
// SequenceableLoader.Callback implementation.
@Override
public void onContinueLoadingRequested(ChunkTrackStream<DashChunkSource> trackStream) {
public void onContinueLoadingRequested(ChunkSampleStream<DashChunkSource> sampleStream) {
callback.onContinueLoadingRequested(this);
}
@ -285,8 +285,8 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
finishPrepare();
}
} else {
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
trackStream.getChunkSource().updateManifest(manifest);
for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) {
sampleStream.getChunkSource().updateManifest(manifest);
}
callback.onContinueLoadingRequested(this);
scheduleManifestRefresh();
@ -432,7 +432,7 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
trackGroups = new TrackGroupArray(trackGroupArray);
}
private ChunkTrackStream<DashChunkSource> buildTrackStream(TrackSelection selection,
private ChunkSampleStream<DashChunkSource> buildSampleStream(TrackSelection selection,
long positionUs) {
int[] selectedTracks = selection.getTracks();
FormatEvaluator adaptiveEvaluator = selectedTracks.length > 1
@ -445,13 +445,13 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
DashChunkSource chunkSource = new DashChunkSource(loader, manifest, adaptationSetIndex,
trackGroups.get(selection.group), selectedTracks, dataSource, adaptiveEvaluator,
elapsedRealtimeOffset);
return new ChunkTrackStream<>(adaptationSetType, chunkSource, this, allocator, positionUs,
return new ChunkSampleStream<>(adaptationSetType, chunkSource, this, allocator, positionUs,
minLoadableRetryCount, eventDispatcher);
}
@SuppressWarnings("unchecked")
private static ChunkTrackStream<DashChunkSource>[] newTrackStreamArray(int length) {
return new ChunkTrackStream[length];
private static ChunkSampleStream<DashChunkSource>[] newSampleStreamArray(int length) {
return new ChunkSampleStream[length];
}
private final class ManifestCallback implements

View file

@ -357,7 +357,7 @@ public class HlsChunkSource {
}
/**
* Invoked when the {@link HlsTrackStreamWrapper} has finished loading a chunk obtained from this
* Invoked when the {@link HlsSampleStreamWrapper} has finished loading a chunk obtained from this
* source.
*
* @param chunk The chunk whose load has been completed.
@ -376,7 +376,7 @@ public class HlsChunkSource {
}
/**
* Invoked when the {@link HlsTrackStreamWrapper} encounters an error loading a chunk obtained
* Invoked when the {@link HlsSampleStreamWrapper} encounters an error loading a chunk obtained
* from this source.
*
* @param chunk The chunk whose load encountered the error.

View file

@ -69,9 +69,9 @@ import java.util.concurrent.atomic.AtomicInteger;
* @param discontinuitySequenceNumber The discontinuity sequence number of the chunk.
* @param extractor The extractor to parse samples from the data.
* @param extractorNeedsInit Whether the extractor needs initializing with the target
* {@link HlsTrackStreamWrapper}.
* {@link HlsSampleStreamWrapper}.
* @param shouldSpliceIn Whether the samples parsed from this chunk should be spliced into any
* samples already queued to the {@link HlsTrackStreamWrapper}.
* samples already queued to the {@link HlsSampleStreamWrapper}.
* @param encryptionKey For AES encryption chunks, the encryption key.
* @param encryptionIv For AES encryption chunks, the encryption initialization vector.
*/
@ -92,12 +92,12 @@ import java.util.concurrent.atomic.AtomicInteger;
}
/**
* Initializes the chunk for loading, setting the {@link HlsTrackStreamWrapper} that will receive
* Initializes the chunk for loading, setting the {@link HlsSampleStreamWrapper} that will receive
* samples as they are loaded.
*
* @param output The output that will receive the loaded samples.
*/
public void init(HlsTrackStreamWrapper output) {
public void init(HlsSampleStreamWrapper output) {
output.init(uid, shouldSpliceIn);
if (extractorNeedsInit) {
extractor.init(output);

View file

@ -20,12 +20,12 @@ import com.google.android.exoplayer2.CompositeSequenceableLoader;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.TrackStream;
import com.google.android.exoplayer2.chunk.FormatEvaluator;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist;
@ -56,7 +56,7 @@ import java.util.List;
* An HLS {@link MediaSource}.
*/
public final class HlsMediaSource implements MediaPeriod, MediaSource,
Loader.Callback<ParsingLoadable<HlsPlaylist>>, HlsTrackStreamWrapper.Callback {
Loader.Callback<ParsingLoadable<HlsPlaylist>>, HlsSampleStreamWrapper.Callback {
/**
* The default minimum number of times to retry loading data prior to failing.
@ -68,7 +68,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
private final BandwidthMeter bandwidthMeter;
private final int minLoadableRetryCount;
private final EventDispatcher eventDispatcher;
private final IdentityHashMap<TrackStream, HlsTrackStreamWrapper> trackStreamSources;
private final IdentityHashMap<SampleStream, HlsSampleStreamWrapper> sampleStreamSources;
private final PtsTimestampAdjusterProvider timestampAdjusterProvider;
private final HlsPlaylistParser manifestParser;
@ -85,8 +85,8 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
private boolean isLive;
private TrackGroupArray trackGroups;
private int[] selectedTrackCounts;
private HlsTrackStreamWrapper[] trackStreamWrappers;
private HlsTrackStreamWrapper[] enabledTrackStreamWrappers;
private HlsSampleStreamWrapper[] sampleStreamWrappers;
private HlsSampleStreamWrapper[] enabledSampleStreamWrappers;
private CompositeSequenceableLoader sequenceableLoader;
public HlsMediaSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
@ -105,7 +105,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
this.minLoadableRetryCount = minLoadableRetryCount;
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
trackStreamSources = new IdentityHashMap<>();
sampleStreamSources = new IdentityHashMap<>();
timestampAdjusterProvider = new PtsTimestampAdjusterProvider();
manifestParser = new HlsPlaylistParser();
}
@ -140,11 +140,11 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
@Override
public void maybeThrowPrepareError() throws IOException {
if (trackStreamWrappers == null) {
if (sampleStreamWrappers == null) {
manifestFetcher.maybeThrowError();
} else {
for (HlsTrackStreamWrapper trackStreamWrapper : trackStreamWrappers) {
trackStreamWrapper.maybeThrowPrepareError();
for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) {
sampleStreamWrapper.maybeThrowPrepareError();
}
}
}
@ -160,28 +160,29 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
}
@Override
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
public SampleStream[] selectTracks(List<SampleStream> oldStreams,
List<TrackSelection> newSelections, long positionUs) {
TrackStream[] newStreams = new TrackStream[newSelections.size()];
SampleStream[] newStreams = new SampleStream[newSelections.size()];
// Select tracks for each wrapper.
int enabledTrackStreamWrapperCount = 0;
for (int i = 0; i < trackStreamWrappers.length; i++) {
selectedTrackCounts[i] += selectTracks(trackStreamWrappers[i], oldStreams, newSelections,
int enabledSampleStreamWrapperCount = 0;
for (int i = 0; i < sampleStreamWrappers.length; i++) {
selectedTrackCounts[i] += selectTracks(sampleStreamWrappers[i], oldStreams, newSelections,
newStreams);
if (selectedTrackCounts[i] > 0) {
enabledTrackStreamWrapperCount++;
enabledSampleStreamWrapperCount++;
}
}
// Update the enabled wrappers.
enabledTrackStreamWrappers = new HlsTrackStreamWrapper[enabledTrackStreamWrapperCount];
sequenceableLoader = new CompositeSequenceableLoader(enabledTrackStreamWrappers);
enabledTrackStreamWrapperCount = 0;
for (int i = 0; i < trackStreamWrappers.length; i++) {
enabledSampleStreamWrappers = new HlsSampleStreamWrapper[enabledSampleStreamWrapperCount];
sequenceableLoader = new CompositeSequenceableLoader(enabledSampleStreamWrappers);
enabledSampleStreamWrapperCount = 0;
for (int i = 0; i < sampleStreamWrappers.length; i++) {
if (selectedTrackCounts[i] > 0) {
enabledTrackStreamWrappers[enabledTrackStreamWrapperCount++] = trackStreamWrappers[i];
enabledSampleStreamWrappers[enabledSampleStreamWrapperCount++] = sampleStreamWrappers[i];
}
}
if (enabledTrackStreamWrapperCount > 0 && seenFirstTrackSelection && !newSelections.isEmpty()) {
if (enabledSampleStreamWrapperCount > 0 && seenFirstTrackSelection
&& !newSelections.isEmpty()) {
seekToUs(positionUs);
}
seenFirstTrackSelection = true;
@ -206,8 +207,8 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
@Override
public long getBufferedPositionUs() {
long bufferedPositionUs = Long.MAX_VALUE;
for (HlsTrackStreamWrapper trackStreamWrapper : enabledTrackStreamWrappers) {
long rendererBufferedPositionUs = trackStreamWrapper.getBufferedPositionUs();
for (HlsSampleStreamWrapper sampleStreamWrapper : enabledSampleStreamWrappers) {
long rendererBufferedPositionUs = sampleStreamWrapper.getBufferedPositionUs();
if (rendererBufferedPositionUs != C.END_OF_SOURCE_US) {
bufferedPositionUs = Math.min(bufferedPositionUs, rendererBufferedPositionUs);
}
@ -220,15 +221,15 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
// Treat all seeks into non-seekable media as being to t=0.
positionUs = isLive ? 0 : positionUs;
timestampAdjusterProvider.reset();
for (HlsTrackStreamWrapper trackStreamWrapper : enabledTrackStreamWrappers) {
trackStreamWrapper.seekTo(positionUs);
for (HlsSampleStreamWrapper sampleStreamWrapper : enabledSampleStreamWrappers) {
sampleStreamWrapper.seekTo(positionUs);
}
return positionUs;
}
@Override
public void release() {
trackStreamSources.clear();
sampleStreamSources.clear();
timestampAdjusterProvider.reset();
manifestDataSource = null;
if (manifestFetcher != null) {
@ -244,13 +245,13 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
isLive = false;
trackGroups = null;
selectedTrackCounts = null;
if (trackStreamWrappers != null) {
for (HlsTrackStreamWrapper trackStreamWrapper : trackStreamWrappers) {
trackStreamWrapper.release();
if (sampleStreamWrappers != null) {
for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) {
sampleStreamWrapper.release();
}
trackStreamWrappers = null;
sampleStreamWrappers = null;
}
enabledTrackStreamWrappers = null;
enabledSampleStreamWrappers = null;
sequenceableLoader = null;
}
@ -262,13 +263,13 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, elapsedRealtimeMs,
loadDurationMs, loadable.bytesLoaded());
HlsPlaylist playlist = loadable.getResult();
List<HlsTrackStreamWrapper> trackStreamWrapperList = buildTrackStreamWrappers(playlist);
trackStreamWrappers = new HlsTrackStreamWrapper[trackStreamWrapperList.size()];
trackStreamWrapperList.toArray(trackStreamWrappers);
selectedTrackCounts = new int[trackStreamWrappers.length];
pendingPrepareCount = trackStreamWrappers.length;
for (HlsTrackStreamWrapper trackStreamWrapper : trackStreamWrappers) {
trackStreamWrapper.prepare();
List<HlsSampleStreamWrapper> sampleStreamWrapperList = buildSampleStreamWrappers(playlist);
sampleStreamWrappers = new HlsSampleStreamWrapper[sampleStreamWrapperList.size()];
sampleStreamWrapperList.toArray(sampleStreamWrappers);
selectedTrackCounts = new int[sampleStreamWrappers.length];
pendingPrepareCount = sampleStreamWrappers.length;
for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) {
sampleStreamWrapper.prepare();
}
}
@ -288,7 +289,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
return isFatal ? Loader.DONT_RETRY_FATAL : Loader.RETRY;
}
// HlsTrackStreamWrapper.Callback implementation.
// HlsSampleStreamWrapper.Callback implementation.
@Override
public void onPrepared() {
@ -297,19 +298,19 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
}
// The wrapper at index 0 is the one of type TRACK_TYPE_DEFAULT.
durationUs = trackStreamWrappers[0].getDurationUs();
isLive = trackStreamWrappers[0].isLive();
durationUs = sampleStreamWrappers[0].getDurationUs();
isLive = sampleStreamWrappers[0].isLive();
int totalTrackGroupCount = 0;
for (HlsTrackStreamWrapper trackStreamWrapper : trackStreamWrappers) {
totalTrackGroupCount += trackStreamWrapper.getTrackGroups().length;
for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) {
totalTrackGroupCount += sampleStreamWrapper.getTrackGroups().length;
}
TrackGroup[] trackGroupArray = new TrackGroup[totalTrackGroupCount];
int trackGroupIndex = 0;
for (HlsTrackStreamWrapper trackStreamWrapper : trackStreamWrappers) {
int wrapperTrackGroupCount = trackStreamWrapper.getTrackGroups().length;
for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) {
int wrapperTrackGroupCount = sampleStreamWrapper.getTrackGroups().length;
for (int j = 0; j < wrapperTrackGroupCount; j++) {
trackGroupArray[trackGroupIndex++] = trackStreamWrapper.getTrackGroups().get(j);
trackGroupArray[trackGroupIndex++] = sampleStreamWrapper.getTrackGroups().get(j);
}
}
trackGroups = new TrackGroupArray(trackGroupArray);
@ -317,7 +318,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
}
@Override
public void onContinueLoadingRequested(HlsTrackStreamWrapper trackStreamWrapper) {
public void onContinueLoadingRequested(HlsSampleStreamWrapper sampleStreamWrapper) {
if (trackGroups == null) {
// Still preparing.
return;
@ -327,17 +328,17 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
// Internal methods.
private List<HlsTrackStreamWrapper> buildTrackStreamWrappers(HlsPlaylist playlist) {
ArrayList<HlsTrackStreamWrapper> trackStreamWrappers = new ArrayList<>();
private List<HlsSampleStreamWrapper> buildSampleStreamWrappers(HlsPlaylist playlist) {
ArrayList<HlsSampleStreamWrapper> sampleStreamWrappers = new ArrayList<>();
String baseUri = playlist.baseUri;
if (playlist instanceof HlsMediaPlaylist) {
Format format = Format.createContainerFormat("0", MimeTypes.APPLICATION_M3U8, null,
Format.NO_VALUE);
Variant[] variants = new Variant[] {new Variant(playlist.baseUri, format, null)};
trackStreamWrappers.add(buildTrackStreamWrapper(C.TRACK_TYPE_DEFAULT, baseUri, variants,
sampleStreamWrappers.add(buildSampleStreamWrapper(C.TRACK_TYPE_DEFAULT, baseUri, variants,
new FormatEvaluator.AdaptiveEvaluator(bandwidthMeter), null, null));
return trackStreamWrappers;
return sampleStreamWrappers;
}
HlsMasterPlaylist masterPlaylist = (HlsMasterPlaylist) playlist;
@ -369,7 +370,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
if (!selectedVariants.isEmpty()) {
Variant[] variants = new Variant[selectedVariants.size()];
selectedVariants.toArray(variants);
trackStreamWrappers.add(buildTrackStreamWrapper(C.TRACK_TYPE_DEFAULT, baseUri, variants,
sampleStreamWrappers.add(buildSampleStreamWrapper(C.TRACK_TYPE_DEFAULT, baseUri, variants,
new FormatEvaluator.AdaptiveEvaluator(bandwidthMeter), masterPlaylist.muxedAudioFormat,
masterPlaylist.muxedCaptionFormat));
}
@ -379,7 +380,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
if (!audioVariants.isEmpty()) {
Variant[] variants = new Variant[audioVariants.size()];
audioVariants.toArray(variants);
trackStreamWrappers.add(buildTrackStreamWrapper(C.TRACK_TYPE_AUDIO, baseUri, variants, null,
sampleStreamWrappers.add(buildSampleStreamWrapper(C.TRACK_TYPE_AUDIO, baseUri, variants, null,
null, null));
}
@ -388,33 +389,33 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
if (!subtitleVariants.isEmpty()) {
Variant[] variants = new Variant[subtitleVariants.size()];
subtitleVariants.toArray(variants);
trackStreamWrappers.add(buildTrackStreamWrapper(C.TRACK_TYPE_TEXT, baseUri, variants, null,
sampleStreamWrappers.add(buildSampleStreamWrapper(C.TRACK_TYPE_TEXT, baseUri, variants, null,
null, null));
}
return trackStreamWrappers;
return sampleStreamWrappers;
}
private HlsTrackStreamWrapper buildTrackStreamWrapper(int trackType, String baseUri,
private HlsSampleStreamWrapper buildSampleStreamWrapper(int trackType, String baseUri,
Variant[] variants, FormatEvaluator formatEvaluator, Format muxedAudioFormat,
Format muxedCaptionFormat) {
DataSource dataSource = dataSourceFactory.createDataSource(bandwidthMeter);
HlsChunkSource defaultChunkSource = new HlsChunkSource(baseUri, variants, dataSource,
timestampAdjusterProvider, formatEvaluator);
return new HlsTrackStreamWrapper(trackType, this, defaultChunkSource, allocator,
return new HlsSampleStreamWrapper(trackType, this, defaultChunkSource, allocator,
preparePositionUs, muxedAudioFormat, muxedCaptionFormat, minLoadableRetryCount,
eventDispatcher);
}
private int selectTracks(HlsTrackStreamWrapper trackStreamWrapper,
List<TrackStream> allOldStreams, List<TrackSelection> allNewSelections,
TrackStream[] allNewStreams) {
private int selectTracks(HlsSampleStreamWrapper sampleStreamWrapper,
List<SampleStream> allOldStreams, List<TrackSelection> allNewSelections,
SampleStream[] allNewStreams) {
// Get the subset of the old streams for the source.
ArrayList<TrackStream> oldStreams = new ArrayList<>();
ArrayList<SampleStream> oldStreams = new ArrayList<>();
for (int i = 0; i < allOldStreams.size(); i++) {
TrackStream stream = allOldStreams.get(i);
if (trackStreamSources.get(stream) == trackStreamWrapper) {
trackStreamSources.remove(stream);
SampleStream stream = allOldStreams.get(i);
if (sampleStreamSources.get(stream) == sampleStreamWrapper) {
sampleStreamSources.remove(stream);
oldStreams.add(stream);
}
}
@ -423,8 +424,8 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
int[] newSelectionOriginalIndices = new int[allNewSelections.size()];
for (int i = 0; i < allNewSelections.size(); i++) {
TrackSelection selection = allNewSelections.get(i);
Pair<HlsTrackStreamWrapper, Integer> sourceAndGroup = getSourceAndGroup(selection.group);
if (sourceAndGroup.first == trackStreamWrapper) {
Pair<HlsSampleStreamWrapper, Integer> sourceAndGroup = getSourceAndGroup(selection.group);
if (sourceAndGroup.first == sampleStreamWrapper) {
newSelectionOriginalIndices[newSelections.size()] = i;
newSelections.add(new TrackSelection(sourceAndGroup.second, selection.getTracks()));
}
@ -434,21 +435,21 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
return 0;
}
// Perform the selection.
TrackStream[] newStreams = trackStreamWrapper.selectTracks(oldStreams, newSelections,
SampleStream[] newStreams = sampleStreamWrapper.selectTracks(oldStreams, newSelections,
!seenFirstTrackSelection);
for (int j = 0; j < newStreams.length; j++) {
allNewStreams[newSelectionOriginalIndices[j]] = newStreams[j];
trackStreamSources.put(newStreams[j], trackStreamWrapper);
sampleStreamSources.put(newStreams[j], sampleStreamWrapper);
}
return newSelections.size() - oldStreams.size();
}
private Pair<HlsTrackStreamWrapper, Integer> getSourceAndGroup(int group) {
private Pair<HlsSampleStreamWrapper, Integer> getSourceAndGroup(int group) {
int totalTrackGroupCount = 0;
for (HlsTrackStreamWrapper trackStreamWrapper : trackStreamWrappers) {
int sourceTrackGroupCount = trackStreamWrapper.getTrackGroups().length;
for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) {
int sourceTrackGroupCount = sampleStreamWrapper.getTrackGroups().length;
if (group < totalTrackGroupCount + sourceTrackGroupCount) {
return Pair.create(trackStreamWrapper, group - totalTrackGroupCount);
return Pair.create(sampleStreamWrapper, group - totalTrackGroupCount);
}
totalTrackGroupCount += sourceTrackGroupCount;
}

View file

@ -21,7 +21,6 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.SequenceableLoader;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.TrackStream;
import com.google.android.exoplayer2.chunk.Chunk;
import com.google.android.exoplayer2.chunk.ChunkHolder;
import com.google.android.exoplayer2.extractor.DefaultTrackOutput;
@ -29,6 +28,7 @@ import com.google.android.exoplayer2.extractor.DefaultTrackOutput.UpstreamFormat
import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.upstream.Allocator;
@ -44,15 +44,15 @@ import java.util.List;
/**
* Loads {@link HlsMediaChunk}s obtained from a {@link HlsChunkSource}, and provides
* {@link TrackStream}s from which the loaded media can be consumed.
* {@link SampleStream}s from which the loaded media can be consumed.
*/
/* package */ final class HlsTrackStreamWrapper implements Loader.Callback<Chunk>,
/* package */ final class HlsSampleStreamWrapper implements Loader.Callback<Chunk>,
SequenceableLoader, ExtractorOutput, UpstreamFormatChangedListener {
/**
* A callback to be notified of events.
*/
public interface Callback extends SequenceableLoader.Callback<HlsTrackStreamWrapper> {
public interface Callback extends SequenceableLoader.Callback<HlsSampleStreamWrapper> {
/**
* Invoked when the wrapper has been prepared.
@ -112,7 +112,7 @@ import java.util.List;
* before propagating an error.
* @param eventDispatcher A dispatcher to notify of events.
*/
public HlsTrackStreamWrapper(int trackType, Callback callback, HlsChunkSource chunkSource,
public HlsSampleStreamWrapper(int trackType, Callback callback, HlsChunkSource chunkSource,
Allocator allocator, long positionUs, Format muxedAudioFormat, Format muxedCaptionFormat,
int minLoadableRetryCount, EventDispatcher eventDispatcher) {
this.trackType = trackType;
@ -123,7 +123,7 @@ import java.util.List;
this.muxedCaptionFormat = muxedCaptionFormat;
this.minLoadableRetryCount = minLoadableRetryCount;
this.eventDispatcher = eventDispatcher;
loader = new Loader("Loader:HlsTrackStreamWrapper");
loader = new Loader("Loader:HlsSampleStreamWrapper");
nextChunkHolder = new ChunkHolder();
sampleQueues = new SparseArray<>();
mediaChunks = new LinkedList<>();
@ -151,17 +151,17 @@ import java.util.List;
return trackGroups;
}
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
public SampleStream[] selectTracks(List<SampleStream> oldStreams,
List<TrackSelection> newSelections, boolean isFirstTrackSelection) {
Assertions.checkState(prepared);
// Unselect old tracks.
for (int i = 0; i < oldStreams.size(); i++) {
int group = ((TrackStreamImpl) oldStreams.get(i)).group;
int group = ((SampleStreamImpl) oldStreams.get(i)).group;
setTrackGroupEnabledState(group, false);
sampleQueues.valueAt(group).disable();
}
// Select new tracks.
TrackStream[] newStreams = new TrackStream[newSelections.size()];
SampleStream[] newStreams = new SampleStream[newSelections.size()];
for (int i = 0; i < newStreams.length; i++) {
TrackSelection selection = newSelections.get(i);
int group = selection.group;
@ -170,7 +170,7 @@ import java.util.List;
if (group == primaryTrackGroupIndex) {
chunkSource.selectTracks(tracks);
}
newStreams[i] = new TrackStreamImpl(group);
newStreams[i] = new SampleStreamImpl(group);
}
// At the time of the first track selection all queues will be enabled, so we need to disable
// any that are no longer required.
@ -239,7 +239,7 @@ import java.util.List;
loader.release();
}
// TrackStream implementation.
// SampleStream implementation.
/* package */ boolean isReady(int group) {
return loadingFinished || (!isPendingReset() && !sampleQueues.valueAt(group).isEmpty());
@ -252,7 +252,7 @@ import java.util.List;
/* package */ int readData(int group, FormatHolder formatHolder, DecoderInputBuffer buffer) {
if (isPendingReset()) {
return TrackStream.NOTHING_READ;
return C.RESULT_NOTHING_READ;
}
while (mediaChunks.size() > 1 && finishedReadingChunk(mediaChunks.getFirst())) {
@ -461,7 +461,7 @@ import java.util.List;
}
/**
* Builds tracks that are exposed by this {@link HlsTrackStreamWrapper} instance, as well as
* Builds tracks that are exposed by this {@link HlsSampleStreamWrapper} instance, as well as
* internal data-structures required for operation.
* <p>
* Tracks in HLS are complicated. A HLS master playlist contains a number of "variants". Each
@ -475,7 +475,7 @@ import java.util.List;
* adaptive track defined to span all variants and a track for each individual variant. The
* adaptive track is initially selected. The extractor is then prepared to discover the tracks
* inside of each variant stream. The two sets of tracks are then combined by this method to
* create a third set, which is the set exposed by this {@link HlsTrackStreamWrapper}:
* create a third set, which is the set exposed by this {@link HlsSampleStreamWrapper}:
* <ul>
* <li>The extractor tracks are inspected to infer a "primary" track type. If a video track is
* present then it is always the primary type. If not, audio is the primary type if present.
@ -587,27 +587,27 @@ import java.util.List;
return pendingResetPositionUs != C.UNSET_TIME_US;
}
private final class TrackStreamImpl implements TrackStream {
private final class SampleStreamImpl implements SampleStream {
private final int group;
public TrackStreamImpl(int group) {
public SampleStreamImpl(int group) {
this.group = group;
}
@Override
public boolean isReady() {
return HlsTrackStreamWrapper.this.isReady(group);
return HlsSampleStreamWrapper.this.isReady(group);
}
@Override
public void maybeThrowError() throws IOException {
HlsTrackStreamWrapper.this.maybeThrowError();
HlsSampleStreamWrapper.this.maybeThrowError();
}
@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
return HlsTrackStreamWrapper.this.readData(group, formatHolder, buffer);
return HlsSampleStreamWrapper.this.readData(group, formatHolder, buffer);
}
}

View file

@ -21,8 +21,7 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.SequenceableLoader;
import com.google.android.exoplayer2.TrackSelection;
import com.google.android.exoplayer2.TrackStream;
import com.google.android.exoplayer2.chunk.ChunkTrackStream;
import com.google.android.exoplayer2.chunk.ChunkSampleStream;
import com.google.android.exoplayer2.chunk.FormatEvaluator;
import com.google.android.exoplayer2.chunk.FormatEvaluator.AdaptiveEvaluator;
import com.google.android.exoplayer2.extractor.mp4.TrackEncryptionBox;
@ -30,6 +29,7 @@ import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.smoothstreaming.SmoothStreamingManifest.ProtectionElement;
@ -56,7 +56,7 @@ import java.util.List;
* A SmoothStreaming {@link MediaSource}.
*/
public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSource,
SequenceableLoader.Callback<ChunkTrackStream<SmoothStreamingChunkSource>>,
SequenceableLoader.Callback<ChunkSampleStream<SmoothStreamingChunkSource>>,
Loader.Callback<ParsingLoadable<SmoothStreamingManifest>> {
/**
@ -76,7 +76,7 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
private DataSource manifestDataSource;
private Loader manifestLoader;
private ChunkTrackStream<SmoothStreamingChunkSource>[] trackStreams;
private ChunkSampleStream<SmoothStreamingChunkSource>[] sampleStreams;
private CompositeSequenceableLoader sequenceableLoader;
private long manifestLoadStartTimestamp;
@ -129,8 +129,8 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
public void prepare(Callback callback, Allocator allocator, long positionUs) {
this.callback = callback;
this.allocator = allocator;
trackStreams = newTrackStreamArray(0);
sequenceableLoader = new CompositeSequenceableLoader(trackStreams);
sampleStreams = newSampleStreamArray(0);
sequenceableLoader = new CompositeSequenceableLoader(sampleStreams);
manifestDataSource = dataSourceFactory.createDataSource();
manifestLoader = new Loader("Loader:Manifest");
manifestRefreshHandler = new Handler();
@ -153,32 +153,32 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
}
@Override
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
public SampleStream[] selectTracks(List<SampleStream> oldStreams,
List<TrackSelection> newSelections, long positionUs) {
int newEnabledSourceCount = trackStreams.length + newSelections.size() - oldStreams.size();
ChunkTrackStream<SmoothStreamingChunkSource>[] newTrackStreams =
newTrackStreamArray(newEnabledSourceCount);
int newEnabledSourceCount = sampleStreams.length + newSelections.size() - oldStreams.size();
ChunkSampleStream<SmoothStreamingChunkSource>[] newSampleStreams =
newSampleStreamArray(newEnabledSourceCount);
int newEnabledSourceIndex = 0;
// Iterate over currently enabled streams, either releasing them or adding them to the new list.
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
if (oldStreams.contains(trackStream)) {
trackStream.release();
for (ChunkSampleStream<SmoothStreamingChunkSource> sampleStream : sampleStreams) {
if (oldStreams.contains(sampleStream)) {
sampleStream.release();
} else {
newTrackStreams[newEnabledSourceIndex++] = trackStream;
newSampleStreams[newEnabledSourceIndex++] = sampleStream;
}
}
// Instantiate and return new streams.
TrackStream[] streamsToReturn = new TrackStream[newSelections.size()];
SampleStream[] streamsToReturn = new SampleStream[newSelections.size()];
for (int i = 0; i < newSelections.size(); i++) {
newTrackStreams[newEnabledSourceIndex] = buildTrackStream(newSelections.get(i), positionUs);
streamsToReturn[i] = newTrackStreams[newEnabledSourceIndex];
newSampleStreams[newEnabledSourceIndex] = buildSampleStream(newSelections.get(i), positionUs);
streamsToReturn[i] = newSampleStreams[newEnabledSourceIndex];
newEnabledSourceIndex++;
}
trackStreams = newTrackStreams;
sequenceableLoader = new CompositeSequenceableLoader(trackStreams);
sampleStreams = newSampleStreams;
sequenceableLoader = new CompositeSequenceableLoader(sampleStreams);
return streamsToReturn;
}
@ -200,8 +200,8 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
@Override
public long getBufferedPositionUs() {
long bufferedPositionUs = Long.MAX_VALUE;
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
long rendererBufferedPositionUs = trackStream.getBufferedPositionUs();
for (ChunkSampleStream<SmoothStreamingChunkSource> sampleStream : sampleStreams) {
long rendererBufferedPositionUs = sampleStream.getBufferedPositionUs();
if (rendererBufferedPositionUs != C.END_OF_SOURCE_US) {
bufferedPositionUs = Math.min(bufferedPositionUs, rendererBufferedPositionUs);
}
@ -211,8 +211,8 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
@Override
public long seekToUs(long positionUs) {
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
trackStream.seekToUs(positionUs);
for (ChunkSampleStream<SmoothStreamingChunkSource> sampleStream : sampleStreams) {
sampleStream.seekToUs(positionUs);
}
return positionUs;
}
@ -224,11 +224,11 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
manifestLoader.release();
manifestLoader = null;
}
if (trackStreams != null) {
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
trackStream.release();
if (sampleStreams != null) {
for (ChunkSampleStream<SmoothStreamingChunkSource> sampleStream : sampleStreams) {
sampleStream.release();
}
trackStreams = null;
sampleStreams = null;
}
sequenceableLoader = null;
manifestLoadStartTimestamp = 0;
@ -249,7 +249,8 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
// SequenceableLoader.Callback implementation
@Override
public void onContinueLoadingRequested(ChunkTrackStream<SmoothStreamingChunkSource> trackStream) {
public void onContinueLoadingRequested(
ChunkSampleStream<SmoothStreamingChunkSource> sampleStream) {
callback.onContinueLoadingRequested(this);
}
@ -274,8 +275,8 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
prepared = true;
callback.onPeriodPrepared(this);
} else {
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
trackStream.getChunkSource().updateManifest(manifest);
for (ChunkSampleStream<SmoothStreamingChunkSource> sampleStream : sampleStreams) {
sampleStream.getChunkSource().updateManifest(manifest);
}
callback.onContinueLoadingRequested(this);
}
@ -343,7 +344,7 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
trackGroups = new TrackGroupArray(trackGroupArray);
}
private ChunkTrackStream<SmoothStreamingChunkSource> buildTrackStream(TrackSelection selection,
private ChunkSampleStream<SmoothStreamingChunkSource> buildSampleStream(TrackSelection selection,
long positionUs) {
int[] selectedTracks = selection.getTracks();
FormatEvaluator adaptiveEvaluator = selectedTracks.length > 1
@ -355,13 +356,13 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
SmoothStreamingChunkSource chunkSource = new SmoothStreamingChunkSource(manifestLoader,
manifest, streamElementIndex, trackGroups.get(selection.group), selectedTracks, dataSource,
adaptiveEvaluator, trackEncryptionBoxes);
return new ChunkTrackStream<>(streamElementType, chunkSource, this, allocator, positionUs,
return new ChunkSampleStream<>(streamElementType, chunkSource, this, allocator, positionUs,
minLoadableRetryCount, eventDispatcher);
}
@SuppressWarnings("unchecked")
private static ChunkTrackStream<SmoothStreamingChunkSource>[] newTrackStreamArray(int length) {
return new ChunkTrackStream[length];
private static ChunkSampleStream<SmoothStreamingChunkSource>[] newSampleStreamArray(int length) {
return new ChunkSampleStream[length];
}
private static byte[] getProtectionElementKeyId(byte[] initData) {

View file

@ -21,7 +21,6 @@ import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.ParserException;
import com.google.android.exoplayer2.Renderer;
import com.google.android.exoplayer2.TrackStream;
import com.google.android.exoplayer2.extensions.Decoder;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.MimeTypes;
@ -203,7 +202,7 @@ public final class TextRenderer extends Renderer implements Callback {
}
// Try and read the next subtitle from the source.
int result = readSource(formatHolder, nextInputBuffer);
if (result == TrackStream.BUFFER_READ) {
if (result == C.RESULT_BUFFER_READ) {
// Clear BUFFER_FLAG_DECODE_ONLY (see [Internal: b/27893809]) and queue the buffer.
nextInputBuffer.clearFlag(C.BUFFER_FLAG_DECODE_ONLY);
if (nextInputBuffer.isEndOfStream()) {
@ -214,7 +213,7 @@ public final class TextRenderer extends Renderer implements Callback {
}
parser.queueInputBuffer(nextInputBuffer);
nextInputBuffer = null;
} else if (result == TrackStream.NOTHING_READ) {
} else if (result == C.RESULT_NOTHING_READ) {
break;
}
}