mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
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:
parent
be9d77c59c
commit
de27b2e043
24 changed files with 307 additions and 308 deletions
|
|
@ -23,7 +23,6 @@ import com.google.android.exoplayer2.ExoPlayer;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.FormatHolder;
|
import com.google.android.exoplayer2.FormatHolder;
|
||||||
import com.google.android.exoplayer2.Renderer;
|
import com.google.android.exoplayer2.Renderer;
|
||||||
import com.google.android.exoplayer2.TrackStream;
|
|
||||||
import com.google.android.exoplayer2.VideoRendererEventListener;
|
import com.google.android.exoplayer2.VideoRendererEventListener;
|
||||||
import com.google.android.exoplayer2.VideoRendererEventListener.EventDispatcher;
|
import com.google.android.exoplayer2.VideoRendererEventListener.EventDispatcher;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
|
@ -289,10 +288,10 @@ public final class LibvpxVideoRenderer extends Renderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = readSource(formatHolder, inputBuffer);
|
int result = readSource(formatHolder, inputBuffer);
|
||||||
if (result == TrackStream.NOTHING_READ) {
|
if (result == C.RESULT_NOTHING_READ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (result == TrackStream.FORMAT_READ) {
|
if (result == C.RESULT_FORMAT_READ) {
|
||||||
onInputFormatChanged(formatHolder.format);
|
onInputFormatChanged(formatHolder.format);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -396,7 +395,7 @@ public final class LibvpxVideoRenderer extends Renderer {
|
||||||
|
|
||||||
private boolean readFormat() {
|
private boolean readFormat() {
|
||||||
int result = readSource(formatHolder, null);
|
int result = readSource(formatHolder, null);
|
||||||
if (result == TrackStream.FORMAT_READ) {
|
if (result == C.RESULT_FORMAT_READ) {
|
||||||
onInputFormatChanged(formatHolder.format);
|
onInputFormatChanged(formatHolder.format);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,21 @@ public interface C {
|
||||||
*/
|
*/
|
||||||
int RESULT_MAX_LENGTH_EXCEEDED = -2;
|
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.
|
* A data type constant for data of unknown or unspecified type.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import com.google.android.exoplayer2.ExoPlayer.ExoPlayerMessage;
|
||||||
import com.google.android.exoplayer2.TrackSelector.InvalidationListener;
|
import com.google.android.exoplayer2.TrackSelector.InvalidationListener;
|
||||||
import com.google.android.exoplayer2.source.MediaPeriod;
|
import com.google.android.exoplayer2.source.MediaPeriod;
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
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.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.util.PriorityHandlerThread;
|
import com.google.android.exoplayer2.util.PriorityHandlerThread;
|
||||||
import com.google.android.exoplayer2.util.TraceUtil;
|
import com.google.android.exoplayer2.util.TraceUtil;
|
||||||
|
|
@ -682,7 +683,7 @@ import java.util.ArrayList;
|
||||||
}
|
}
|
||||||
updateTimelineState();
|
updateTimelineState();
|
||||||
if (readingPeriod == null) {
|
if (readingPeriod == null) {
|
||||||
// The renderers have their final TrackStreams.
|
// The renderers have their final SampleStreams.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (Renderer renderer : enabledRenderers) {
|
for (Renderer renderer : enabledRenderers) {
|
||||||
|
|
@ -701,18 +702,18 @@ import java.util.ArrayList;
|
||||||
TrackSelection newSelection = newTrackSelections.get(i);
|
TrackSelection newSelection = newTrackSelections.get(i);
|
||||||
if (oldSelection != null) {
|
if (oldSelection != null) {
|
||||||
if (newSelection != null) {
|
if (newSelection != null) {
|
||||||
// Replace the renderer's TrackStream so the transition to playing the next period can
|
// Replace the renderer's SampleStream so the transition to playing the next period
|
||||||
// be seamless.
|
// can be seamless.
|
||||||
Format[] formats = new Format[newSelection.length];
|
Format[] formats = new Format[newSelection.length];
|
||||||
for (int j = 0; j < formats.length; j++) {
|
for (int j = 0; j < formats.length; j++) {
|
||||||
formats[j] = groups.get(newSelection.group).getFormat(newSelection.getTrack(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);
|
readingPeriod.offsetUs);
|
||||||
} else {
|
} else {
|
||||||
// The renderer will be disabled when transitioning to playing the next period. Mark
|
// The renderer will be disabled when transitioning to playing the next period. Mark
|
||||||
// the TrackStream as final to play out any remaining data.
|
// the SampleStream as final to play out any remaining data.
|
||||||
renderer.setCurrentTrackStreamIsFinal();
|
renderer.setCurrentSampleStreamIsFinal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -721,7 +722,7 @@ import java.util.ArrayList;
|
||||||
readingPeriod = null;
|
readingPeriod = null;
|
||||||
// This is the last period, so signal the renderers to read the end of the stream.
|
// This is the last period, so signal the renderers to read the end of the stream.
|
||||||
for (Renderer renderer : enabledRenderers) {
|
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));
|
formats[j] = trackGroups.get(newSelection.group).getFormat(newSelection.getTrack(j));
|
||||||
}
|
}
|
||||||
// Enable the renderer.
|
// Enable the renderer.
|
||||||
renderer.enable(formats, playingPeriod.trackStreams[i], internalPositionUs, joining,
|
renderer.enable(formats, playingPeriod.sampleStreams[i], internalPositionUs, joining,
|
||||||
playingPeriod.offsetUs);
|
playingPeriod.offsetUs);
|
||||||
MediaClock mediaClock = renderer.getMediaClock();
|
MediaClock mediaClock = renderer.getMediaClock();
|
||||||
if (mediaClock != null) {
|
if (mediaClock != null) {
|
||||||
|
|
@ -996,7 +997,7 @@ import java.util.ArrayList;
|
||||||
|
|
||||||
public final MediaPeriod mediaPeriod;
|
public final MediaPeriod mediaPeriod;
|
||||||
public final int index;
|
public final int index;
|
||||||
public final TrackStream[] trackStreams;
|
public final SampleStream[] sampleStreams;
|
||||||
|
|
||||||
public boolean prepared;
|
public boolean prepared;
|
||||||
public boolean hasEnabledTracks;
|
public boolean hasEnabledTracks;
|
||||||
|
|
@ -1014,7 +1015,7 @@ import java.util.ArrayList;
|
||||||
this.trackSelector = trackSelector;
|
this.trackSelector = trackSelector;
|
||||||
this.mediaPeriod = mediaPeriod;
|
this.mediaPeriod = mediaPeriod;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
trackStreams = new TrackStream[renderers.length];
|
sampleStreams = new SampleStream[renderers.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNextPeriod(Period nextPeriod) {
|
public void setNextPeriod(Period nextPeriod) {
|
||||||
|
|
@ -1049,7 +1050,7 @@ import java.util.ArrayList;
|
||||||
public void updatePeriodTrackSelection(long positionUs, LoadControl loadControl,
|
public void updatePeriodTrackSelection(long positionUs, LoadControl loadControl,
|
||||||
boolean forceRecreateStreams) throws ExoPlaybackException {
|
boolean forceRecreateStreams) throws ExoPlaybackException {
|
||||||
// Populate lists of streams that are being disabled/newly enabled.
|
// 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<>();
|
ArrayList<TrackSelection> newSelections = new ArrayList<>();
|
||||||
for (int i = 0; i < trackSelections.length; i++) {
|
for (int i = 0; i < trackSelections.length; i++) {
|
||||||
TrackSelection oldSelection =
|
TrackSelection oldSelection =
|
||||||
|
|
@ -1057,7 +1058,7 @@ import java.util.ArrayList;
|
||||||
TrackSelection newSelection = trackSelections.get(i);
|
TrackSelection newSelection = trackSelections.get(i);
|
||||||
if (forceRecreateStreams || !Util.areEqual(oldSelection, newSelection)) {
|
if (forceRecreateStreams || !Util.areEqual(oldSelection, newSelection)) {
|
||||||
if (oldSelection != null) {
|
if (oldSelection != null) {
|
||||||
oldStreams.add(trackStreams[i]);
|
oldStreams.add(sampleStreams[i]);
|
||||||
}
|
}
|
||||||
if (newSelection != null) {
|
if (newSelection != null) {
|
||||||
newSelections.add(newSelection);
|
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.
|
// 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;
|
periodTrackSelections = trackSelections;
|
||||||
hasEnabledTracks = false;
|
hasEnabledTracks = false;
|
||||||
for (int i = 0; i < trackSelections.length; i++) {
|
for (int i = 0; i < trackSelections.length; i++) {
|
||||||
|
|
@ -1075,12 +1076,12 @@ import java.util.ArrayList;
|
||||||
hasEnabledTracks = true;
|
hasEnabledTracks = true;
|
||||||
int index = newSelections.indexOf(selection);
|
int index = newSelections.indexOf(selection);
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
trackStreams[i] = newStreams[index];
|
sampleStreams[i] = newStreams[index];
|
||||||
} else {
|
} else {
|
||||||
// This selection/stream is unchanged.
|
// This selection/stream is unchanged.
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
trackStreams[i] = null;
|
sampleStreams[i] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -461,7 +461,7 @@ public abstract class MediaCodecRenderer extends Renderer {
|
||||||
|
|
||||||
private void readFormat() throws ExoPlaybackException {
|
private void readFormat() throws ExoPlaybackException {
|
||||||
int result = readSource(formatHolder, null);
|
int result = readSource(formatHolder, null);
|
||||||
if (result == TrackStream.FORMAT_READ) {
|
if (result == C.RESULT_FORMAT_READ) {
|
||||||
onInputFormatChanged(formatHolder.format);
|
onInputFormatChanged(formatHolder.format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -544,7 +544,7 @@ public abstract class MediaCodecRenderer extends Renderer {
|
||||||
int adaptiveReconfigurationBytes = 0;
|
int adaptiveReconfigurationBytes = 0;
|
||||||
if (waitingForKeys) {
|
if (waitingForKeys) {
|
||||||
// We've already read an encrypted sample into buffer, and are waiting for keys.
|
// We've already read an encrypted sample into buffer, and are waiting for keys.
|
||||||
result = TrackStream.BUFFER_READ;
|
result = C.RESULT_BUFFER_READ;
|
||||||
} else {
|
} else {
|
||||||
// For adaptive reconfiguration OMX decoders expect all reconfiguration data to be supplied
|
// 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.
|
// 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);
|
result = readSource(formatHolder, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == TrackStream.NOTHING_READ) {
|
if (result == C.RESULT_NOTHING_READ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (result == TrackStream.FORMAT_READ) {
|
if (result == C.RESULT_FORMAT_READ) {
|
||||||
if (codecReconfigurationState == RECONFIGURATION_STATE_QUEUE_PENDING) {
|
if (codecReconfigurationState == RECONFIGURATION_STATE_QUEUE_PENDING) {
|
||||||
// We received two formats in a row. Clear the current buffer of any reconfiguration data
|
// We received two formats in a row. Clear the current buffer of any reconfiguration data
|
||||||
// associated with the first format.
|
// associated with the first format.
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,14 @@
|
||||||
package com.google.android.exoplayer2;
|
package com.google.android.exoplayer2;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.ExoPlayer.ExoPlayerComponent;
|
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.Assertions;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders a single component of media.
|
* Renders media samples read from a {@link SampleStream}.
|
||||||
* <p>
|
* <p>
|
||||||
* Internally, a renderer's lifecycle is managed by the owning {@link ExoPlayer}. The player will
|
* 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
|
* 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 index;
|
||||||
private int state;
|
private int state;
|
||||||
private TrackStream stream;
|
private SampleStream stream;
|
||||||
private long streamOffsetUs;
|
private long streamOffsetUs;
|
||||||
private boolean readEndOfStream;
|
private boolean readEndOfStream;
|
||||||
private boolean streamIsFinal;
|
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 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 positionUs The player's current position.
|
||||||
* @param joining Whether this renderer is being enabled to join an ongoing playback.
|
* @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}
|
* @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.
|
* @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 {
|
boolean joining, long offsetUs) throws ExoPlaybackException {
|
||||||
Assertions.checkState(state == STATE_DISABLED);
|
Assertions.checkState(state == STATE_DISABLED);
|
||||||
state = STATE_ENABLED;
|
state = STATE_ENABLED;
|
||||||
onEnabled(joining);
|
onEnabled(joining);
|
||||||
replaceTrackStream(formats, stream, offsetUs);
|
replaceSampleStream(formats, stream, offsetUs);
|
||||||
onReset(positionUs, joining);
|
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 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
|
* @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.
|
* @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 {
|
throws ExoPlaybackException {
|
||||||
Assertions.checkState(!streamIsFinal);
|
Assertions.checkState(!streamIsFinal);
|
||||||
this.stream = stream;
|
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() {
|
/* package */ final boolean hasReadStreamToEnd() {
|
||||||
return readEndOfStream;
|
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.
|
* before it is next disabled or reset.
|
||||||
*/
|
*/
|
||||||
/* package */ final void setCurrentTrackStreamIsFinal() {
|
/* package */ final void setCurrentSampleStreamIsFinal() {
|
||||||
streamIsFinal = true;
|
streamIsFinal = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -338,7 +339,7 @@ public abstract class Renderer implements ExoPlayerComponent {
|
||||||
// Methods to be called by subclasses.
|
// 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.
|
* nothing if no such error exists.
|
||||||
* <p>
|
* <p>
|
||||||
* This method may be called when the renderer is in the following states:
|
* 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.
|
* Reads from the enabled upstream source.
|
||||||
*
|
*
|
||||||
* @see TrackStream#readData(FormatHolder, DecoderInputBuffer)
|
* @see SampleStream#readData(FormatHolder, DecoderInputBuffer)
|
||||||
*/
|
*/
|
||||||
protected final int readSource(FormatHolder formatHolder, DecoderInputBuffer buffer) {
|
protected final int readSource(FormatHolder formatHolder, DecoderInputBuffer buffer) {
|
||||||
int result = stream.readData(formatHolder, buffer);
|
int result = stream.readData(formatHolder, buffer);
|
||||||
if (result == TrackStream.BUFFER_READ) {
|
if (result == C.RESULT_BUFFER_READ) {
|
||||||
if (buffer.isEndOfStream()) {
|
if (buffer.isEndOfStream()) {
|
||||||
readEndOfStream = true;
|
readEndOfStream = true;
|
||||||
return streamIsFinal ? TrackStream.BUFFER_READ : TrackStream.NOTHING_READ;
|
return streamIsFinal ? C.RESULT_BUFFER_READ : C.RESULT_NOTHING_READ;
|
||||||
}
|
}
|
||||||
buffer.timeUs += streamOffsetUs;
|
buffer.timeUs += streamOffsetUs;
|
||||||
}
|
}
|
||||||
|
|
@ -410,7 +411,7 @@ public abstract class Renderer implements ExoPlayerComponent {
|
||||||
protected abstract int supportsFormat(Format format) throws ExoPlaybackException;
|
protected abstract int supportsFormat(Format format) throws ExoPlaybackException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Incrementally renders the {@link TrackStream}.
|
* Incrementally renders the {@link SampleStream}.
|
||||||
* <p>
|
* <p>
|
||||||
* This method should return quickly, and should not block if the renderer is unable to make
|
* This method should return quickly, and should not block if the renderer is unable to make
|
||||||
* useful progress.
|
* useful progress.
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,9 @@ import com.google.android.exoplayer2.DecoderInputBuffer;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.FormatHolder;
|
import com.google.android.exoplayer2.FormatHolder;
|
||||||
import com.google.android.exoplayer2.SequenceableLoader;
|
import com.google.android.exoplayer2.SequenceableLoader;
|
||||||
import com.google.android.exoplayer2.TrackStream;
|
|
||||||
import com.google.android.exoplayer2.extractor.DefaultTrackOutput;
|
import com.google.android.exoplayer2.extractor.DefaultTrackOutput;
|
||||||
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
|
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.Allocator;
|
||||||
import com.google.android.exoplayer2.upstream.Loader;
|
import com.google.android.exoplayer2.upstream.Loader;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
|
|
@ -33,14 +33,14 @@ import java.util.LinkedList;
|
||||||
import java.util.List;
|
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> {
|
Loader.Callback<Chunk> {
|
||||||
|
|
||||||
private final int trackType;
|
private final int trackType;
|
||||||
private final T chunkSource;
|
private final T chunkSource;
|
||||||
private final SequenceableLoader.Callback<ChunkTrackStream<T>> callback;
|
private final SequenceableLoader.Callback<ChunkSampleStream<T>> callback;
|
||||||
private final EventDispatcher eventDispatcher;
|
private final EventDispatcher eventDispatcher;
|
||||||
private final int minLoadableRetryCount;
|
private final int minLoadableRetryCount;
|
||||||
private final LinkedList<BaseMediaChunk> mediaChunks;
|
private final LinkedList<BaseMediaChunk> mediaChunks;
|
||||||
|
|
@ -66,15 +66,15 @@ public class ChunkTrackStream<T extends ChunkSource> implements TrackStream, Seq
|
||||||
* before propagating an error.
|
* before propagating an error.
|
||||||
* @param eventDispatcher A dispatcher to notify of events.
|
* @param eventDispatcher A dispatcher to notify of events.
|
||||||
*/
|
*/
|
||||||
public ChunkTrackStream(int trackType, T chunkSource,
|
public ChunkSampleStream(int trackType, T chunkSource,
|
||||||
SequenceableLoader.Callback<ChunkTrackStream<T>> callback, Allocator allocator,
|
SequenceableLoader.Callback<ChunkSampleStream<T>> callback, Allocator allocator,
|
||||||
long positionUs, int minLoadableRetryCount, EventDispatcher eventDispatcher) {
|
long positionUs, int minLoadableRetryCount, EventDispatcher eventDispatcher) {
|
||||||
this.trackType = trackType;
|
this.trackType = trackType;
|
||||||
this.chunkSource = chunkSource;
|
this.chunkSource = chunkSource;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.eventDispatcher = eventDispatcher;
|
this.eventDispatcher = eventDispatcher;
|
||||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||||
loader = new Loader("Loader:ChunkTrackStream");
|
loader = new Loader("Loader:ChunkSampleStream");
|
||||||
nextChunkHolder = new ChunkHolder();
|
nextChunkHolder = new ChunkHolder();
|
||||||
mediaChunks = new LinkedList<>();
|
mediaChunks = new LinkedList<>();
|
||||||
readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks);
|
readOnlyMediaChunks = Collections.unmodifiableList(mediaChunks);
|
||||||
|
|
@ -155,7 +155,7 @@ public class ChunkTrackStream<T extends ChunkSource> implements TrackStream, Seq
|
||||||
loader.release();
|
loader.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrackStream implementation.
|
// SampleStream implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isReady() {
|
public boolean isReady() {
|
||||||
|
|
@ -173,7 +173,7 @@ public class ChunkTrackStream<T extends ChunkSource> implements TrackStream, Seq
|
||||||
@Override
|
@Override
|
||||||
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
|
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
|
||||||
if (isPendingReset()) {
|
if (isPendingReset()) {
|
||||||
return NOTHING_READ;
|
return C.RESULT_NOTHING_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mediaChunks.size() > 1
|
while (mediaChunks.size() > 1
|
||||||
|
|
@ -19,7 +19,7 @@ import java.io.IOException;
|
||||||
import java.util.List;
|
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 {
|
public interface ChunkSource {
|
||||||
|
|
||||||
|
|
@ -62,7 +62,7 @@ public interface ChunkSource {
|
||||||
void getNextChunk(MediaChunk previous, long playbackPositionUs, ChunkHolder out);
|
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.
|
* source.
|
||||||
* <p>
|
* <p>
|
||||||
* This method should only be called when the source is enabled.
|
* This method should only be called when the source is enabled.
|
||||||
|
|
@ -72,7 +72,7 @@ public interface ChunkSource {
|
||||||
void onChunkLoadCompleted(Chunk chunk);
|
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.
|
* this source.
|
||||||
* <p>
|
* <p>
|
||||||
* This method should only be called when the source is enabled.
|
* This method should only be called when the source is enabled.
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.FormatHolder;
|
import com.google.android.exoplayer2.FormatHolder;
|
||||||
import com.google.android.exoplayer2.MediaClock;
|
import com.google.android.exoplayer2.MediaClock;
|
||||||
import com.google.android.exoplayer2.Renderer;
|
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.AudioCapabilities;
|
||||||
import com.google.android.exoplayer2.audio.AudioTrack;
|
import com.google.android.exoplayer2.audio.AudioTrack;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
|
@ -241,10 +240,10 @@ public abstract class AudioDecoderRenderer extends Renderer implements MediaCloc
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = readSource(formatHolder, inputBuffer);
|
int result = readSource(formatHolder, inputBuffer);
|
||||||
if (result == TrackStream.NOTHING_READ) {
|
if (result == C.RESULT_NOTHING_READ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (result == TrackStream.FORMAT_READ) {
|
if (result == C.RESULT_FORMAT_READ) {
|
||||||
onInputFormatChanged(formatHolder.format);
|
onInputFormatChanged(formatHolder.format);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -354,7 +353,7 @@ public abstract class AudioDecoderRenderer extends Renderer implements MediaCloc
|
||||||
|
|
||||||
private boolean readFormat() {
|
private boolean readFormat() {
|
||||||
int result = readSource(formatHolder, null);
|
int result = readSource(formatHolder, null);
|
||||||
if (result == TrackStream.FORMAT_READ) {
|
if (result == C.RESULT_FORMAT_READ) {
|
||||||
onInputFormatChanged(formatHolder.format);
|
onInputFormatChanged(formatHolder.format);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.DecoderInputBuffer;
|
import com.google.android.exoplayer2.DecoderInputBuffer;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.FormatHolder;
|
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.Allocation;
|
||||||
import com.google.android.exoplayer2.upstream.Allocator;
|
import com.google.android.exoplayer2.upstream.Allocator;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
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 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
|
* @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.
|
* be set if the buffer's timestamp is less than this value.
|
||||||
* @return The result, which can be {@link TrackStream#NOTHING_READ},
|
* @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or
|
||||||
* {@link TrackStream#FORMAT_READ} or {@link TrackStream#BUFFER_READ}.
|
* {@link C#RESULT_BUFFER_READ}.
|
||||||
*/
|
*/
|
||||||
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean loadingFinished,
|
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean loadingFinished,
|
||||||
long decodeOnlyUntilUs) {
|
long decodeOnlyUntilUs) {
|
||||||
switch (infoQueue.readData(formatHolder, buffer, downstreamFormat, extrasHolder)) {
|
switch (infoQueue.readData(formatHolder, buffer, downstreamFormat, extrasHolder)) {
|
||||||
case TrackStream.NOTHING_READ:
|
case C.RESULT_NOTHING_READ:
|
||||||
if (loadingFinished) {
|
if (loadingFinished) {
|
||||||
buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
|
buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
|
||||||
return TrackStream.BUFFER_READ;
|
return C.RESULT_BUFFER_READ;
|
||||||
}
|
}
|
||||||
return TrackStream.NOTHING_READ;
|
return C.RESULT_NOTHING_READ;
|
||||||
case TrackStream.FORMAT_READ:
|
case C.RESULT_FORMAT_READ:
|
||||||
downstreamFormat = formatHolder.format;
|
downstreamFormat = formatHolder.format;
|
||||||
return TrackStream.FORMAT_READ;
|
return C.RESULT_FORMAT_READ;
|
||||||
case TrackStream.BUFFER_READ:
|
case C.RESULT_BUFFER_READ:
|
||||||
if (buffer.timeUs < decodeOnlyUntilUs) {
|
if (buffer.timeUs < decodeOnlyUntilUs) {
|
||||||
buffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
|
buffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
|
||||||
}
|
}
|
||||||
|
|
@ -280,7 +279,7 @@ public final class DefaultTrackOutput implements TrackOutput {
|
||||||
readData(extrasHolder.offset, buffer.data, extrasHolder.size);
|
readData(extrasHolder.offset, buffer.data, extrasHolder.size);
|
||||||
// Advance the read head.
|
// Advance the read head.
|
||||||
dropDownstreamTo(extrasHolder.nextOffset);
|
dropDownstreamTo(extrasHolder.nextOffset);
|
||||||
return TrackStream.BUFFER_READ;
|
return C.RESULT_BUFFER_READ;
|
||||||
default:
|
default:
|
||||||
throw new IllegalStateException();
|
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
|
* @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.
|
* 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.
|
* @param extrasHolder The holder into which extra sample information should be written.
|
||||||
* @return The result, which can be {@link TrackStream#NOTHING_READ},
|
* @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ}
|
||||||
* {@link TrackStream#FORMAT_READ} or {@link TrackStream#BUFFER_READ}.
|
* or {@link C#RESULT_BUFFER_READ}.
|
||||||
*/
|
*/
|
||||||
public synchronized int readData(FormatHolder formatHolder, DecoderInputBuffer buffer,
|
public synchronized int readData(FormatHolder formatHolder, DecoderInputBuffer buffer,
|
||||||
Format downstreamFormat, BufferExtrasHolder extrasHolder) {
|
Format downstreamFormat, BufferExtrasHolder extrasHolder) {
|
||||||
if (queueSize == 0) {
|
if (queueSize == 0) {
|
||||||
if (upstreamFormat != null && upstreamFormat != downstreamFormat) {
|
if (upstreamFormat != null && upstreamFormat != downstreamFormat) {
|
||||||
formatHolder.format = upstreamFormat;
|
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) {
|
if (formats[relativeReadIndex] != downstreamFormat) {
|
||||||
formatHolder.format = formats[relativeReadIndex];
|
formatHolder.format = formats[relativeReadIndex];
|
||||||
return TrackStream.FORMAT_READ;
|
return C.RESULT_FORMAT_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.timeUs = timesUs[relativeReadIndex];
|
buffer.timeUs = timesUs[relativeReadIndex];
|
||||||
|
|
@ -782,7 +781,7 @@ public final class DefaultTrackOutput implements TrackOutput {
|
||||||
|
|
||||||
extrasHolder.nextOffset = queueSize > 0 ? offsets[relativeReadIndex]
|
extrasHolder.nextOffset = queueSize > 0 ? offsets[relativeReadIndex]
|
||||||
: extrasHolder.offset + extrasHolder.size;
|
: extrasHolder.offset + extrasHolder.size;
|
||||||
return TrackStream.BUFFER_READ;
|
return C.RESULT_BUFFER_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ import com.google.android.exoplayer2.ExoPlaybackException;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.FormatHolder;
|
import com.google.android.exoplayer2.FormatHolder;
|
||||||
import com.google.android.exoplayer2.Renderer;
|
import com.google.android.exoplayer2.Renderer;
|
||||||
import com.google.android.exoplayer2.TrackStream;
|
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
|
@ -106,7 +105,7 @@ public final class MetadataRenderer<T> extends Renderer implements Callback {
|
||||||
if (!inputStreamEnded && pendingMetadata == null) {
|
if (!inputStreamEnded && pendingMetadata == null) {
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
int result = readSource(formatHolder, buffer);
|
int result = readSource(formatHolder, buffer);
|
||||||
if (result == TrackStream.BUFFER_READ) {
|
if (result == C.RESULT_BUFFER_READ) {
|
||||||
if (buffer.isEndOfStream()) {
|
if (buffer.isEndOfStream()) {
|
||||||
inputStreamEnded = true;
|
inputStreamEnded = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ package com.google.android.exoplayer2.source;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.TrackStream;
|
|
||||||
import com.google.android.exoplayer2.chunk.FormatEvaluator;
|
import com.google.android.exoplayer2.chunk.FormatEvaluator;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
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
|
* 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 trackType The type of the media. One of the {@link C} {@code TRACK_TYPE_*} constants.
|
||||||
* @param format The new format.
|
* @param format The new format.
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ import com.google.android.exoplayer2.FormatHolder;
|
||||||
import com.google.android.exoplayer2.ParserException;
|
import com.google.android.exoplayer2.ParserException;
|
||||||
import com.google.android.exoplayer2.SequenceableLoader;
|
import com.google.android.exoplayer2.SequenceableLoader;
|
||||||
import com.google.android.exoplayer2.TrackSelection;
|
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.DefaultExtractorInput;
|
||||||
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
|
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
|
||||||
import com.google.android.exoplayer2.extractor.DefaultTrackOutput;
|
import com.google.android.exoplayer2.extractor.DefaultTrackOutput;
|
||||||
|
|
@ -234,19 +233,19 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
|
public SampleStream[] selectTracks(List<SampleStream> oldStreams,
|
||||||
List<TrackSelection> newSelections, long positionUs) {
|
List<TrackSelection> newSelections, long positionUs) {
|
||||||
Assertions.checkState(prepared);
|
Assertions.checkState(prepared);
|
||||||
// Unselect old tracks.
|
// Unselect old tracks.
|
||||||
for (int i = 0; i < oldStreams.size(); i++) {
|
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]);
|
Assertions.checkState(trackEnabledStates[track]);
|
||||||
enabledTrackCount--;
|
enabledTrackCount--;
|
||||||
trackEnabledStates[track] = false;
|
trackEnabledStates[track] = false;
|
||||||
sampleQueues[track].disable();
|
sampleQueues[track].disable();
|
||||||
}
|
}
|
||||||
// Select new tracks.
|
// Select new tracks.
|
||||||
TrackStream[] newStreams = new TrackStream[newSelections.size()];
|
SampleStream[] newStreams = new SampleStream[newSelections.size()];
|
||||||
for (int i = 0; i < newStreams.length; i++) {
|
for (int i = 0; i < newStreams.length; i++) {
|
||||||
TrackSelection selection = newSelections.get(i);
|
TrackSelection selection = newSelections.get(i);
|
||||||
Assertions.checkState(selection.length == 1);
|
Assertions.checkState(selection.length == 1);
|
||||||
|
|
@ -255,7 +254,7 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
|
||||||
Assertions.checkState(!trackEnabledStates[track]);
|
Assertions.checkState(!trackEnabledStates[track]);
|
||||||
enabledTrackCount++;
|
enabledTrackCount++;
|
||||||
trackEnabledStates[track] = true;
|
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
|
// At the time of the first track selection all queues will be enabled, so we need to disable
|
||||||
// any that are no longer required.
|
// any that are no longer required.
|
||||||
|
|
@ -379,7 +378,7 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
|
||||||
loadingFinished = false;
|
loadingFinished = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrackStream methods.
|
// SampleStream methods.
|
||||||
|
|
||||||
/* package */ boolean isReady(int track) {
|
/* package */ boolean isReady(int track) {
|
||||||
return loadingFinished || (!isPendingReset() && !sampleQueues[track].isEmpty());
|
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) {
|
/* package */ int readData(int track, FormatHolder formatHolder, DecoderInputBuffer buffer) {
|
||||||
if (notifyReset || isPendingReset()) {
|
if (notifyReset || isPendingReset()) {
|
||||||
return TrackStream.NOTHING_READ;
|
return C.RESULT_NOTHING_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sampleQueues[track].readData(formatHolder, buffer, loadingFinished, lastSeekPositionUs);
|
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;
|
private final int track;
|
||||||
|
|
||||||
public TrackStreamImpl(int track) {
|
public SampleStreamImpl(int track) {
|
||||||
this.track = track;
|
this.track = track;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ package com.google.android.exoplayer2.source;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.SequenceableLoader;
|
import com.google.android.exoplayer2.SequenceableLoader;
|
||||||
import com.google.android.exoplayer2.TrackSelection;
|
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.Allocator;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
@ -94,28 +93,28 @@ public interface MediaPeriod extends SequenceableLoader {
|
||||||
/**
|
/**
|
||||||
* Modifies the selected tracks.
|
* Modifies the selected tracks.
|
||||||
* <p>
|
* <p>
|
||||||
* {@link TrackStream}s corresponding to tracks being unselected are passed in {@code oldStreams}.
|
* {@link SampleStream}s corresponding to tracks being unselected are passed in
|
||||||
* Tracks being selected are specified in {@code newSelections}. Each new {@link TrackSelection}
|
* {@code oldStreams}. Tracks being selected are specified in {@code newSelections}. Each new
|
||||||
* must have a {@link TrackSelection#group} index distinct from those of currently enabled tracks,
|
* {@link TrackSelection} must have a {@link TrackSelection#group} index distinct from those of
|
||||||
* except for those being unselected.
|
* currently enabled tracks, except for those being unselected.
|
||||||
* <p>
|
* <p>
|
||||||
* This method should only be called after the period has been prepared.
|
* 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.
|
* but must not be null.
|
||||||
* @param newSelections {@link TrackSelection}s that define tracks being selected. May be empty
|
* @param newSelections {@link TrackSelection}s that define tracks being selected. May be empty
|
||||||
* but must not be null.
|
* but must not be null.
|
||||||
* @param positionUs The current playback position in microseconds.
|
* @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);
|
long positionUs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to read a discontinuity.
|
* Attempts to read a discontinuity.
|
||||||
* <p>
|
* <p>
|
||||||
* After this method has returned a value other than {@link C#UNSET_TIME_US}, all
|
* 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
|
* @return If a discontinuity was read then the playback position in microseconds after the
|
||||||
* discontinuity. Else {@link C#UNSET_TIME_US}.
|
* 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.
|
* Attempts to seek to the specified position in microseconds.
|
||||||
* <p>
|
* <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.
|
* guaranteed to start from a key frame.
|
||||||
* <p>
|
* <p>
|
||||||
* This method should only be called when at least one track is selected.
|
* This method should only be called when at least one track is selected.
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.CompositeSequenceableLoader;
|
import com.google.android.exoplayer2.CompositeSequenceableLoader;
|
||||||
import com.google.android.exoplayer2.SequenceableLoader;
|
import com.google.android.exoplayer2.SequenceableLoader;
|
||||||
import com.google.android.exoplayer2.TrackSelection;
|
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.Allocator;
|
||||||
|
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
@ -35,7 +34,7 @@ import java.util.List;
|
||||||
public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callback {
|
public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callback {
|
||||||
|
|
||||||
private final MediaPeriod[] periods;
|
private final MediaPeriod[] periods;
|
||||||
private final IdentityHashMap<TrackStream, MediaPeriod> trackStreamPeriods;
|
private final IdentityHashMap<SampleStream, MediaPeriod> sampleStreamPeriods;
|
||||||
private final int[] selectedTrackCounts;
|
private final int[] selectedTrackCounts;
|
||||||
|
|
||||||
private Callback callback;
|
private Callback callback;
|
||||||
|
|
@ -50,7 +49,7 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
|
||||||
public MergingMediaPeriod(MediaPeriod... periods) {
|
public MergingMediaPeriod(MediaPeriod... periods) {
|
||||||
this.periods = periods;
|
this.periods = periods;
|
||||||
pendingChildPrepareCount = periods.length;
|
pendingChildPrepareCount = periods.length;
|
||||||
trackStreamPeriods = new IdentityHashMap<>();
|
sampleStreamPeriods = new IdentityHashMap<>();
|
||||||
selectedTrackCounts = new int[periods.length];
|
selectedTrackCounts = new int[periods.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,9 +79,9 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
|
public SampleStream[] selectTracks(List<SampleStream> oldStreams,
|
||||||
List<TrackSelection> newSelections, long positionUs) {
|
List<TrackSelection> newSelections, long positionUs) {
|
||||||
TrackStream[] newStreams = new TrackStream[newSelections.size()];
|
SampleStream[] newStreams = new SampleStream[newSelections.size()];
|
||||||
// Select tracks for each period.
|
// Select tracks for each period.
|
||||||
int enabledPeriodCount = 0;
|
int enabledPeriodCount = 0;
|
||||||
for (int i = 0; i < periods.length; i++) {
|
for (int i = 0; i < periods.length; i++) {
|
||||||
|
|
@ -206,15 +205,15 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
|
||||||
|
|
||||||
// Internal methods.
|
// Internal methods.
|
||||||
|
|
||||||
private int selectTracks(MediaPeriod period, List<TrackStream> allOldStreams,
|
private int selectTracks(MediaPeriod period, List<SampleStream> allOldStreams,
|
||||||
List<TrackSelection> allNewSelections, long positionUs, TrackStream[] allNewStreams,
|
List<TrackSelection> allNewSelections, long positionUs, SampleStream[] allNewStreams,
|
||||||
boolean seenFirstTrackSelection) {
|
boolean seenFirstTrackSelection) {
|
||||||
// Get the subset of the old streams for the period.
|
// 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++) {
|
for (int i = 0; i < allOldStreams.size(); i++) {
|
||||||
TrackStream stream = allOldStreams.get(i);
|
SampleStream stream = allOldStreams.get(i);
|
||||||
if (trackStreamPeriods.get(stream) == period) {
|
if (sampleStreamPeriods.get(stream) == period) {
|
||||||
trackStreamPeriods.remove(stream);
|
sampleStreamPeriods.remove(stream);
|
||||||
oldStreams.add(stream);
|
oldStreams.add(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -234,10 +233,10 @@ public final class MergingMediaPeriod implements MediaPeriod, MediaPeriod.Callba
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// Perform the selection.
|
// 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++) {
|
for (int j = 0; j < newStreams.length; j++) {
|
||||||
allNewStreams[newSelectionOriginalIndices[j]] = newStreams[j];
|
allNewStreams[newSelectionOriginalIndices[j]] = newStreams[j];
|
||||||
trackStreamPeriods.put(newStreams[j], period);
|
sampleStreamPeriods.put(newStreams[j], period);
|
||||||
}
|
}
|
||||||
return newSelections.size() - oldStreams.size();
|
return newSelections.size() - oldStreams.size();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,27 +13,18 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* 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;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A stream of media data.
|
* A stream of media samples (and associated format information).
|
||||||
*/
|
*/
|
||||||
public interface TrackStream {
|
public interface SampleStream {
|
||||||
|
|
||||||
/**
|
|
||||||
* Nothing was read.
|
|
||||||
*/
|
|
||||||
int NOTHING_READ = -1;
|
|
||||||
/**
|
|
||||||
* The buffer was populated.
|
|
||||||
*/
|
|
||||||
int BUFFER_READ = -2;
|
|
||||||
/**
|
|
||||||
* A format was read.
|
|
||||||
*/
|
|
||||||
int FORMAT_READ = -3;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether data is available to be read.
|
* 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
|
* @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
|
* 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.
|
* {@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
|
* @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or
|
||||||
* {@link #BUFFER_READ}.
|
* {@link C#RESULT_BUFFER_READ}.
|
||||||
*/
|
*/
|
||||||
int readData(FormatHolder formatHolder, DecoderInputBuffer buffer);
|
int readData(FormatHolder formatHolder, DecoderInputBuffer buffer);
|
||||||
|
|
||||||
|
|
@ -20,7 +20,6 @@ import com.google.android.exoplayer2.DecoderInputBuffer;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.FormatHolder;
|
import com.google.android.exoplayer2.FormatHolder;
|
||||||
import com.google.android.exoplayer2.TrackSelection;
|
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.Allocator;
|
||||||
import com.google.android.exoplayer2.upstream.DataSource;
|
import com.google.android.exoplayer2.upstream.DataSource;
|
||||||
import com.google.android.exoplayer2.upstream.DataSourceFactory;
|
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}.
|
* 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> {
|
Loader.Callback<SingleSampleMediaSource.SourceLoadable> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -151,12 +150,12 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
|
public SampleStream[] selectTracks(List<SampleStream> oldStreams,
|
||||||
List<TrackSelection> newSelections, long positionUs) {
|
List<TrackSelection> newSelections, long positionUs) {
|
||||||
Assertions.checkState(oldStreams.size() <= 1);
|
Assertions.checkState(oldStreams.size() <= 1);
|
||||||
Assertions.checkState(newSelections.size() <= 1);
|
Assertions.checkState(newSelections.size() <= 1);
|
||||||
// Select new tracks.
|
// Select new tracks.
|
||||||
TrackStream[] newStreams = new TrackStream[newSelections.size()];
|
SampleStream[] newStreams = new SampleStream[newSelections.size()];
|
||||||
if (!newSelections.isEmpty()) {
|
if (!newSelections.isEmpty()) {
|
||||||
newStreams[0] = this;
|
newStreams[0] = this;
|
||||||
streamState = STREAM_STATE_SEND_FORMAT;
|
streamState = STREAM_STATE_SEND_FORMAT;
|
||||||
|
|
@ -204,7 +203,7 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource,
|
||||||
sampleSize = 0;
|
sampleSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrackStream implementation.
|
// SampleStream implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isReady() {
|
public boolean isReady() {
|
||||||
|
|
@ -225,23 +224,23 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource,
|
||||||
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
|
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
|
||||||
if (streamState == STREAM_STATE_END_OF_STREAM) {
|
if (streamState == STREAM_STATE_END_OF_STREAM) {
|
||||||
buffer.addFlag(C.BUFFER_FLAG_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) {
|
} else if (streamState == STREAM_STATE_SEND_FORMAT) {
|
||||||
formatHolder.format = format;
|
formatHolder.format = format;
|
||||||
streamState = STREAM_STATE_SEND_SAMPLE;
|
streamState = STREAM_STATE_SEND_SAMPLE;
|
||||||
return FORMAT_READ;
|
return C.RESULT_FORMAT_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
Assertions.checkState(streamState == STREAM_STATE_SEND_SAMPLE);
|
Assertions.checkState(streamState == STREAM_STATE_SEND_SAMPLE);
|
||||||
if (!loadingFinished) {
|
if (!loadingFinished) {
|
||||||
return NOTHING_READ;
|
return C.RESULT_NOTHING_READ;
|
||||||
} else {
|
} else {
|
||||||
buffer.timeUs = 0;
|
buffer.timeUs = 0;
|
||||||
buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
|
buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
|
||||||
buffer.ensureSpaceForWrite(sampleSize);
|
buffer.ensureSpaceForWrite(sampleSize);
|
||||||
buffer.data.put(sampleData, 0, sampleSize);
|
buffer.data.put(sampleData, 0, sampleSize);
|
||||||
streamState = STREAM_STATE_END_OF_STREAM;
|
streamState = STREAM_STATE_END_OF_STREAM;
|
||||||
return BUFFER_READ;
|
return C.RESULT_BUFFER_READ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
package com.google.android.exoplayer2.source;
|
package com.google.android.exoplayer2.source;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.TrackStream;
|
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
@ -24,8 +23,8 @@ import java.util.Arrays;
|
||||||
/**
|
/**
|
||||||
* Defines a group of tracks exposed by a {@link MediaPeriod}.
|
* Defines a group of tracks exposed by a {@link MediaPeriod}.
|
||||||
* <p>
|
* <p>
|
||||||
* A {@link MediaPeriod} is only able to provide one {@link TrackStream} corresponding to a group
|
* 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 TrackStream} can adapt between
|
* 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
|
* 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.
|
* consume one track from the group at a given time.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,14 @@ import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.ParserException;
|
import com.google.android.exoplayer2.ParserException;
|
||||||
import com.google.android.exoplayer2.SequenceableLoader;
|
import com.google.android.exoplayer2.SequenceableLoader;
|
||||||
import com.google.android.exoplayer2.TrackSelection;
|
import com.google.android.exoplayer2.TrackSelection;
|
||||||
import com.google.android.exoplayer2.TrackStream;
|
import com.google.android.exoplayer2.chunk.ChunkSampleStream;
|
||||||
import com.google.android.exoplayer2.chunk.ChunkTrackStream;
|
|
||||||
import com.google.android.exoplayer2.chunk.FormatEvaluator;
|
import com.google.android.exoplayer2.chunk.FormatEvaluator;
|
||||||
import com.google.android.exoplayer2.chunk.FormatEvaluator.AdaptiveEvaluator;
|
import com.google.android.exoplayer2.chunk.FormatEvaluator.AdaptiveEvaluator;
|
||||||
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
|
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
|
||||||
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
|
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
|
||||||
import com.google.android.exoplayer2.source.MediaPeriod;
|
import com.google.android.exoplayer2.source.MediaPeriod;
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
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.TrackGroup;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.source.dash.mpd.AdaptationSet;
|
import com.google.android.exoplayer2.source.dash.mpd.AdaptationSet;
|
||||||
|
|
@ -66,7 +66,7 @@ import java.util.TimeZone;
|
||||||
* A DASH {@link MediaSource}.
|
* A DASH {@link MediaSource}.
|
||||||
*/
|
*/
|
||||||
public final class DashMediaSource implements MediaPeriod, 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.
|
* 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 DataSource dataSource;
|
||||||
private Loader loader;
|
private Loader loader;
|
||||||
private ChunkTrackStream<DashChunkSource>[] trackStreams;
|
private ChunkSampleStream<DashChunkSource>[] sampleStreams;
|
||||||
private CompositeSequenceableLoader sequenceableLoader;
|
private CompositeSequenceableLoader sequenceableLoader;
|
||||||
|
|
||||||
private Uri manifestUri;
|
private Uri manifestUri;
|
||||||
|
|
@ -139,8 +139,8 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
|
||||||
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
trackStreams = newTrackStreamArray(0);
|
sampleStreams = newSampleStreamArray(0);
|
||||||
sequenceableLoader = new CompositeSequenceableLoader(trackStreams);
|
sequenceableLoader = new CompositeSequenceableLoader(sampleStreams);
|
||||||
dataSource = dataSourceFactory.createDataSource();
|
dataSource = dataSourceFactory.createDataSource();
|
||||||
loader = new Loader("Loader:DashMediaSource");
|
loader = new Loader("Loader:DashMediaSource");
|
||||||
manifestRefreshHandler = new Handler();
|
manifestRefreshHandler = new Handler();
|
||||||
|
|
@ -163,32 +163,32 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
|
public SampleStream[] selectTracks(List<SampleStream> oldStreams,
|
||||||
List<TrackSelection> newSelections, long positionUs) {
|
List<TrackSelection> newSelections, long positionUs) {
|
||||||
int newEnabledSourceCount = trackStreams.length + newSelections.size() - oldStreams.size();
|
int newEnabledSourceCount = sampleStreams.length + newSelections.size() - oldStreams.size();
|
||||||
ChunkTrackStream<DashChunkSource>[] newTrackStreams =
|
ChunkSampleStream<DashChunkSource>[] newSampleStreams =
|
||||||
newTrackStreamArray(newEnabledSourceCount);
|
newSampleStreamArray(newEnabledSourceCount);
|
||||||
int newEnabledSourceIndex = 0;
|
int newEnabledSourceIndex = 0;
|
||||||
|
|
||||||
// Iterate over currently enabled streams, either releasing them or adding them to the new list.
|
// Iterate over currently enabled streams, either releasing them or adding them to the new list.
|
||||||
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
|
for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) {
|
||||||
if (oldStreams.contains(trackStream)) {
|
if (oldStreams.contains(sampleStream)) {
|
||||||
trackStream.release();
|
sampleStream.release();
|
||||||
} else {
|
} else {
|
||||||
newTrackStreams[newEnabledSourceIndex++] = trackStream;
|
newSampleStreams[newEnabledSourceIndex++] = sampleStream;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instantiate and return new streams.
|
// 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++) {
|
for (int i = 0; i < newSelections.size(); i++) {
|
||||||
newTrackStreams[newEnabledSourceIndex] = buildTrackStream(newSelections.get(i), positionUs);
|
newSampleStreams[newEnabledSourceIndex] = buildSampleStream(newSelections.get(i), positionUs);
|
||||||
streamsToReturn[i] = newTrackStreams[newEnabledSourceIndex];
|
streamsToReturn[i] = newSampleStreams[newEnabledSourceIndex];
|
||||||
newEnabledSourceIndex++;
|
newEnabledSourceIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
trackStreams = newTrackStreams;
|
sampleStreams = newSampleStreams;
|
||||||
sequenceableLoader = new CompositeSequenceableLoader(trackStreams);
|
sequenceableLoader = new CompositeSequenceableLoader(sampleStreams);
|
||||||
return streamsToReturn;
|
return streamsToReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -210,8 +210,8 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
|
||||||
@Override
|
@Override
|
||||||
public long getBufferedPositionUs() {
|
public long getBufferedPositionUs() {
|
||||||
long bufferedPositionUs = Long.MAX_VALUE;
|
long bufferedPositionUs = Long.MAX_VALUE;
|
||||||
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
|
for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) {
|
||||||
long rendererBufferedPositionUs = trackStream.getBufferedPositionUs();
|
long rendererBufferedPositionUs = sampleStream.getBufferedPositionUs();
|
||||||
if (rendererBufferedPositionUs != C.END_OF_SOURCE_US) {
|
if (rendererBufferedPositionUs != C.END_OF_SOURCE_US) {
|
||||||
bufferedPositionUs = Math.min(bufferedPositionUs, rendererBufferedPositionUs);
|
bufferedPositionUs = Math.min(bufferedPositionUs, rendererBufferedPositionUs);
|
||||||
}
|
}
|
||||||
|
|
@ -221,8 +221,8 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long seekToUs(long positionUs) {
|
public long seekToUs(long positionUs) {
|
||||||
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
|
for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) {
|
||||||
trackStream.seekToUs(positionUs);
|
sampleStream.seekToUs(positionUs);
|
||||||
}
|
}
|
||||||
return positionUs;
|
return positionUs;
|
||||||
}
|
}
|
||||||
|
|
@ -234,11 +234,11 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
|
||||||
loader.release();
|
loader.release();
|
||||||
loader = null;
|
loader = null;
|
||||||
}
|
}
|
||||||
if (trackStreams != null) {
|
if (sampleStreams != null) {
|
||||||
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
|
for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) {
|
||||||
trackStream.release();
|
sampleStream.release();
|
||||||
}
|
}
|
||||||
trackStreams = null;
|
sampleStreams = null;
|
||||||
}
|
}
|
||||||
sequenceableLoader = null;
|
sequenceableLoader = null;
|
||||||
manifestLoadStartTimestamp = 0;
|
manifestLoadStartTimestamp = 0;
|
||||||
|
|
@ -260,7 +260,7 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
|
||||||
// SequenceableLoader.Callback implementation.
|
// SequenceableLoader.Callback implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(ChunkTrackStream<DashChunkSource> trackStream) {
|
public void onContinueLoadingRequested(ChunkSampleStream<DashChunkSource> sampleStream) {
|
||||||
callback.onContinueLoadingRequested(this);
|
callback.onContinueLoadingRequested(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,8 +285,8 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
|
||||||
finishPrepare();
|
finishPrepare();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (ChunkTrackStream<DashChunkSource> trackStream : trackStreams) {
|
for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) {
|
||||||
trackStream.getChunkSource().updateManifest(manifest);
|
sampleStream.getChunkSource().updateManifest(manifest);
|
||||||
}
|
}
|
||||||
callback.onContinueLoadingRequested(this);
|
callback.onContinueLoadingRequested(this);
|
||||||
scheduleManifestRefresh();
|
scheduleManifestRefresh();
|
||||||
|
|
@ -432,7 +432,7 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
|
||||||
trackGroups = new TrackGroupArray(trackGroupArray);
|
trackGroups = new TrackGroupArray(trackGroupArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChunkTrackStream<DashChunkSource> buildTrackStream(TrackSelection selection,
|
private ChunkSampleStream<DashChunkSource> buildSampleStream(TrackSelection selection,
|
||||||
long positionUs) {
|
long positionUs) {
|
||||||
int[] selectedTracks = selection.getTracks();
|
int[] selectedTracks = selection.getTracks();
|
||||||
FormatEvaluator adaptiveEvaluator = selectedTracks.length > 1
|
FormatEvaluator adaptiveEvaluator = selectedTracks.length > 1
|
||||||
|
|
@ -445,13 +445,13 @@ public final class DashMediaSource implements MediaPeriod, MediaSource,
|
||||||
DashChunkSource chunkSource = new DashChunkSource(loader, manifest, adaptationSetIndex,
|
DashChunkSource chunkSource = new DashChunkSource(loader, manifest, adaptationSetIndex,
|
||||||
trackGroups.get(selection.group), selectedTracks, dataSource, adaptiveEvaluator,
|
trackGroups.get(selection.group), selectedTracks, dataSource, adaptiveEvaluator,
|
||||||
elapsedRealtimeOffset);
|
elapsedRealtimeOffset);
|
||||||
return new ChunkTrackStream<>(adaptationSetType, chunkSource, this, allocator, positionUs,
|
return new ChunkSampleStream<>(adaptationSetType, chunkSource, this, allocator, positionUs,
|
||||||
minLoadableRetryCount, eventDispatcher);
|
minLoadableRetryCount, eventDispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static ChunkTrackStream<DashChunkSource>[] newTrackStreamArray(int length) {
|
private static ChunkSampleStream<DashChunkSource>[] newSampleStreamArray(int length) {
|
||||||
return new ChunkTrackStream[length];
|
return new ChunkSampleStream[length];
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class ManifestCallback implements
|
private final class ManifestCallback implements
|
||||||
|
|
|
||||||
|
|
@ -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.
|
* source.
|
||||||
*
|
*
|
||||||
* @param chunk The chunk whose load has been completed.
|
* @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.
|
* from this source.
|
||||||
*
|
*
|
||||||
* @param chunk The chunk whose load encountered the error.
|
* @param chunk The chunk whose load encountered the error.
|
||||||
|
|
|
||||||
|
|
@ -69,9 +69,9 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
* @param discontinuitySequenceNumber The discontinuity sequence number of the chunk.
|
* @param discontinuitySequenceNumber The discontinuity sequence number of the chunk.
|
||||||
* @param extractor The extractor to parse samples from the data.
|
* @param extractor The extractor to parse samples from the data.
|
||||||
* @param extractorNeedsInit Whether the extractor needs initializing with the target
|
* @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
|
* @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 encryptionKey For AES encryption chunks, the encryption key.
|
||||||
* @param encryptionIv For AES encryption chunks, the encryption initialization vector.
|
* @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.
|
* samples as they are loaded.
|
||||||
*
|
*
|
||||||
* @param output The output that will receive the loaded samples.
|
* @param output The output that will receive the loaded samples.
|
||||||
*/
|
*/
|
||||||
public void init(HlsTrackStreamWrapper output) {
|
public void init(HlsSampleStreamWrapper output) {
|
||||||
output.init(uid, shouldSpliceIn);
|
output.init(uid, shouldSpliceIn);
|
||||||
if (extractorNeedsInit) {
|
if (extractorNeedsInit) {
|
||||||
extractor.init(output);
|
extractor.init(output);
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,12 @@ import com.google.android.exoplayer2.CompositeSequenceableLoader;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.ParserException;
|
import com.google.android.exoplayer2.ParserException;
|
||||||
import com.google.android.exoplayer2.TrackSelection;
|
import com.google.android.exoplayer2.TrackSelection;
|
||||||
import com.google.android.exoplayer2.TrackStream;
|
|
||||||
import com.google.android.exoplayer2.chunk.FormatEvaluator;
|
import com.google.android.exoplayer2.chunk.FormatEvaluator;
|
||||||
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
|
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
|
||||||
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
|
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
|
||||||
import com.google.android.exoplayer2.source.MediaPeriod;
|
import com.google.android.exoplayer2.source.MediaPeriod;
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
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.TrackGroup;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist;
|
import com.google.android.exoplayer2.source.hls.playlist.HlsMasterPlaylist;
|
||||||
|
|
@ -56,7 +56,7 @@ import java.util.List;
|
||||||
* An HLS {@link MediaSource}.
|
* An HLS {@link MediaSource}.
|
||||||
*/
|
*/
|
||||||
public final class HlsMediaSource implements MediaPeriod, 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.
|
* 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 BandwidthMeter bandwidthMeter;
|
||||||
private final int minLoadableRetryCount;
|
private final int minLoadableRetryCount;
|
||||||
private final EventDispatcher eventDispatcher;
|
private final EventDispatcher eventDispatcher;
|
||||||
private final IdentityHashMap<TrackStream, HlsTrackStreamWrapper> trackStreamSources;
|
private final IdentityHashMap<SampleStream, HlsSampleStreamWrapper> sampleStreamSources;
|
||||||
private final PtsTimestampAdjusterProvider timestampAdjusterProvider;
|
private final PtsTimestampAdjusterProvider timestampAdjusterProvider;
|
||||||
private final HlsPlaylistParser manifestParser;
|
private final HlsPlaylistParser manifestParser;
|
||||||
|
|
||||||
|
|
@ -85,8 +85,8 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||||
private boolean isLive;
|
private boolean isLive;
|
||||||
private TrackGroupArray trackGroups;
|
private TrackGroupArray trackGroups;
|
||||||
private int[] selectedTrackCounts;
|
private int[] selectedTrackCounts;
|
||||||
private HlsTrackStreamWrapper[] trackStreamWrappers;
|
private HlsSampleStreamWrapper[] sampleStreamWrappers;
|
||||||
private HlsTrackStreamWrapper[] enabledTrackStreamWrappers;
|
private HlsSampleStreamWrapper[] enabledSampleStreamWrappers;
|
||||||
private CompositeSequenceableLoader sequenceableLoader;
|
private CompositeSequenceableLoader sequenceableLoader;
|
||||||
|
|
||||||
public HlsMediaSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
public HlsMediaSource(Uri manifestUri, DataSourceFactory dataSourceFactory,
|
||||||
|
|
@ -105,7 +105,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||||
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
|
||||||
|
|
||||||
trackStreamSources = new IdentityHashMap<>();
|
sampleStreamSources = new IdentityHashMap<>();
|
||||||
timestampAdjusterProvider = new PtsTimestampAdjusterProvider();
|
timestampAdjusterProvider = new PtsTimestampAdjusterProvider();
|
||||||
manifestParser = new HlsPlaylistParser();
|
manifestParser = new HlsPlaylistParser();
|
||||||
}
|
}
|
||||||
|
|
@ -140,11 +140,11 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void maybeThrowPrepareError() throws IOException {
|
public void maybeThrowPrepareError() throws IOException {
|
||||||
if (trackStreamWrappers == null) {
|
if (sampleStreamWrappers == null) {
|
||||||
manifestFetcher.maybeThrowError();
|
manifestFetcher.maybeThrowError();
|
||||||
} else {
|
} else {
|
||||||
for (HlsTrackStreamWrapper trackStreamWrapper : trackStreamWrappers) {
|
for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) {
|
||||||
trackStreamWrapper.maybeThrowPrepareError();
|
sampleStreamWrapper.maybeThrowPrepareError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -160,28 +160,29 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
|
public SampleStream[] selectTracks(List<SampleStream> oldStreams,
|
||||||
List<TrackSelection> newSelections, long positionUs) {
|
List<TrackSelection> newSelections, long positionUs) {
|
||||||
TrackStream[] newStreams = new TrackStream[newSelections.size()];
|
SampleStream[] newStreams = new SampleStream[newSelections.size()];
|
||||||
// Select tracks for each wrapper.
|
// Select tracks for each wrapper.
|
||||||
int enabledTrackStreamWrapperCount = 0;
|
int enabledSampleStreamWrapperCount = 0;
|
||||||
for (int i = 0; i < trackStreamWrappers.length; i++) {
|
for (int i = 0; i < sampleStreamWrappers.length; i++) {
|
||||||
selectedTrackCounts[i] += selectTracks(trackStreamWrappers[i], oldStreams, newSelections,
|
selectedTrackCounts[i] += selectTracks(sampleStreamWrappers[i], oldStreams, newSelections,
|
||||||
newStreams);
|
newStreams);
|
||||||
if (selectedTrackCounts[i] > 0) {
|
if (selectedTrackCounts[i] > 0) {
|
||||||
enabledTrackStreamWrapperCount++;
|
enabledSampleStreamWrapperCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Update the enabled wrappers.
|
// Update the enabled wrappers.
|
||||||
enabledTrackStreamWrappers = new HlsTrackStreamWrapper[enabledTrackStreamWrapperCount];
|
enabledSampleStreamWrappers = new HlsSampleStreamWrapper[enabledSampleStreamWrapperCount];
|
||||||
sequenceableLoader = new CompositeSequenceableLoader(enabledTrackStreamWrappers);
|
sequenceableLoader = new CompositeSequenceableLoader(enabledSampleStreamWrappers);
|
||||||
enabledTrackStreamWrapperCount = 0;
|
enabledSampleStreamWrapperCount = 0;
|
||||||
for (int i = 0; i < trackStreamWrappers.length; i++) {
|
for (int i = 0; i < sampleStreamWrappers.length; i++) {
|
||||||
if (selectedTrackCounts[i] > 0) {
|
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);
|
seekToUs(positionUs);
|
||||||
}
|
}
|
||||||
seenFirstTrackSelection = true;
|
seenFirstTrackSelection = true;
|
||||||
|
|
@ -206,8 +207,8 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||||
@Override
|
@Override
|
||||||
public long getBufferedPositionUs() {
|
public long getBufferedPositionUs() {
|
||||||
long bufferedPositionUs = Long.MAX_VALUE;
|
long bufferedPositionUs = Long.MAX_VALUE;
|
||||||
for (HlsTrackStreamWrapper trackStreamWrapper : enabledTrackStreamWrappers) {
|
for (HlsSampleStreamWrapper sampleStreamWrapper : enabledSampleStreamWrappers) {
|
||||||
long rendererBufferedPositionUs = trackStreamWrapper.getBufferedPositionUs();
|
long rendererBufferedPositionUs = sampleStreamWrapper.getBufferedPositionUs();
|
||||||
if (rendererBufferedPositionUs != C.END_OF_SOURCE_US) {
|
if (rendererBufferedPositionUs != C.END_OF_SOURCE_US) {
|
||||||
bufferedPositionUs = Math.min(bufferedPositionUs, rendererBufferedPositionUs);
|
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.
|
// Treat all seeks into non-seekable media as being to t=0.
|
||||||
positionUs = isLive ? 0 : positionUs;
|
positionUs = isLive ? 0 : positionUs;
|
||||||
timestampAdjusterProvider.reset();
|
timestampAdjusterProvider.reset();
|
||||||
for (HlsTrackStreamWrapper trackStreamWrapper : enabledTrackStreamWrappers) {
|
for (HlsSampleStreamWrapper sampleStreamWrapper : enabledSampleStreamWrappers) {
|
||||||
trackStreamWrapper.seekTo(positionUs);
|
sampleStreamWrapper.seekTo(positionUs);
|
||||||
}
|
}
|
||||||
return positionUs;
|
return positionUs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void release() {
|
public void release() {
|
||||||
trackStreamSources.clear();
|
sampleStreamSources.clear();
|
||||||
timestampAdjusterProvider.reset();
|
timestampAdjusterProvider.reset();
|
||||||
manifestDataSource = null;
|
manifestDataSource = null;
|
||||||
if (manifestFetcher != null) {
|
if (manifestFetcher != null) {
|
||||||
|
|
@ -244,13 +245,13 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||||
isLive = false;
|
isLive = false;
|
||||||
trackGroups = null;
|
trackGroups = null;
|
||||||
selectedTrackCounts = null;
|
selectedTrackCounts = null;
|
||||||
if (trackStreamWrappers != null) {
|
if (sampleStreamWrappers != null) {
|
||||||
for (HlsTrackStreamWrapper trackStreamWrapper : trackStreamWrappers) {
|
for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) {
|
||||||
trackStreamWrapper.release();
|
sampleStreamWrapper.release();
|
||||||
}
|
}
|
||||||
trackStreamWrappers = null;
|
sampleStreamWrappers = null;
|
||||||
}
|
}
|
||||||
enabledTrackStreamWrappers = null;
|
enabledSampleStreamWrappers = null;
|
||||||
sequenceableLoader = null;
|
sequenceableLoader = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -262,13 +263,13 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||||
eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, elapsedRealtimeMs,
|
eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, elapsedRealtimeMs,
|
||||||
loadDurationMs, loadable.bytesLoaded());
|
loadDurationMs, loadable.bytesLoaded());
|
||||||
HlsPlaylist playlist = loadable.getResult();
|
HlsPlaylist playlist = loadable.getResult();
|
||||||
List<HlsTrackStreamWrapper> trackStreamWrapperList = buildTrackStreamWrappers(playlist);
|
List<HlsSampleStreamWrapper> sampleStreamWrapperList = buildSampleStreamWrappers(playlist);
|
||||||
trackStreamWrappers = new HlsTrackStreamWrapper[trackStreamWrapperList.size()];
|
sampleStreamWrappers = new HlsSampleStreamWrapper[sampleStreamWrapperList.size()];
|
||||||
trackStreamWrapperList.toArray(trackStreamWrappers);
|
sampleStreamWrapperList.toArray(sampleStreamWrappers);
|
||||||
selectedTrackCounts = new int[trackStreamWrappers.length];
|
selectedTrackCounts = new int[sampleStreamWrappers.length];
|
||||||
pendingPrepareCount = trackStreamWrappers.length;
|
pendingPrepareCount = sampleStreamWrappers.length;
|
||||||
for (HlsTrackStreamWrapper trackStreamWrapper : trackStreamWrappers) {
|
for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) {
|
||||||
trackStreamWrapper.prepare();
|
sampleStreamWrapper.prepare();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -288,7 +289,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||||
return isFatal ? Loader.DONT_RETRY_FATAL : Loader.RETRY;
|
return isFatal ? Loader.DONT_RETRY_FATAL : Loader.RETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// HlsTrackStreamWrapper.Callback implementation.
|
// HlsSampleStreamWrapper.Callback implementation.
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPrepared() {
|
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.
|
// The wrapper at index 0 is the one of type TRACK_TYPE_DEFAULT.
|
||||||
durationUs = trackStreamWrappers[0].getDurationUs();
|
durationUs = sampleStreamWrappers[0].getDurationUs();
|
||||||
isLive = trackStreamWrappers[0].isLive();
|
isLive = sampleStreamWrappers[0].isLive();
|
||||||
|
|
||||||
int totalTrackGroupCount = 0;
|
int totalTrackGroupCount = 0;
|
||||||
for (HlsTrackStreamWrapper trackStreamWrapper : trackStreamWrappers) {
|
for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) {
|
||||||
totalTrackGroupCount += trackStreamWrapper.getTrackGroups().length;
|
totalTrackGroupCount += sampleStreamWrapper.getTrackGroups().length;
|
||||||
}
|
}
|
||||||
TrackGroup[] trackGroupArray = new TrackGroup[totalTrackGroupCount];
|
TrackGroup[] trackGroupArray = new TrackGroup[totalTrackGroupCount];
|
||||||
int trackGroupIndex = 0;
|
int trackGroupIndex = 0;
|
||||||
for (HlsTrackStreamWrapper trackStreamWrapper : trackStreamWrappers) {
|
for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) {
|
||||||
int wrapperTrackGroupCount = trackStreamWrapper.getTrackGroups().length;
|
int wrapperTrackGroupCount = sampleStreamWrapper.getTrackGroups().length;
|
||||||
for (int j = 0; j < wrapperTrackGroupCount; j++) {
|
for (int j = 0; j < wrapperTrackGroupCount; j++) {
|
||||||
trackGroupArray[trackGroupIndex++] = trackStreamWrapper.getTrackGroups().get(j);
|
trackGroupArray[trackGroupIndex++] = sampleStreamWrapper.getTrackGroups().get(j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trackGroups = new TrackGroupArray(trackGroupArray);
|
trackGroups = new TrackGroupArray(trackGroupArray);
|
||||||
|
|
@ -317,7 +318,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(HlsTrackStreamWrapper trackStreamWrapper) {
|
public void onContinueLoadingRequested(HlsSampleStreamWrapper sampleStreamWrapper) {
|
||||||
if (trackGroups == null) {
|
if (trackGroups == null) {
|
||||||
// Still preparing.
|
// Still preparing.
|
||||||
return;
|
return;
|
||||||
|
|
@ -327,17 +328,17 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||||
|
|
||||||
// Internal methods.
|
// Internal methods.
|
||||||
|
|
||||||
private List<HlsTrackStreamWrapper> buildTrackStreamWrappers(HlsPlaylist playlist) {
|
private List<HlsSampleStreamWrapper> buildSampleStreamWrappers(HlsPlaylist playlist) {
|
||||||
ArrayList<HlsTrackStreamWrapper> trackStreamWrappers = new ArrayList<>();
|
ArrayList<HlsSampleStreamWrapper> sampleStreamWrappers = new ArrayList<>();
|
||||||
String baseUri = playlist.baseUri;
|
String baseUri = playlist.baseUri;
|
||||||
|
|
||||||
if (playlist instanceof HlsMediaPlaylist) {
|
if (playlist instanceof HlsMediaPlaylist) {
|
||||||
Format format = Format.createContainerFormat("0", MimeTypes.APPLICATION_M3U8, null,
|
Format format = Format.createContainerFormat("0", MimeTypes.APPLICATION_M3U8, null,
|
||||||
Format.NO_VALUE);
|
Format.NO_VALUE);
|
||||||
Variant[] variants = new Variant[] {new Variant(playlist.baseUri, format, null)};
|
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));
|
new FormatEvaluator.AdaptiveEvaluator(bandwidthMeter), null, null));
|
||||||
return trackStreamWrappers;
|
return sampleStreamWrappers;
|
||||||
}
|
}
|
||||||
|
|
||||||
HlsMasterPlaylist masterPlaylist = (HlsMasterPlaylist) playlist;
|
HlsMasterPlaylist masterPlaylist = (HlsMasterPlaylist) playlist;
|
||||||
|
|
@ -369,7 +370,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||||
if (!selectedVariants.isEmpty()) {
|
if (!selectedVariants.isEmpty()) {
|
||||||
Variant[] variants = new Variant[selectedVariants.size()];
|
Variant[] variants = new Variant[selectedVariants.size()];
|
||||||
selectedVariants.toArray(variants);
|
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,
|
new FormatEvaluator.AdaptiveEvaluator(bandwidthMeter), masterPlaylist.muxedAudioFormat,
|
||||||
masterPlaylist.muxedCaptionFormat));
|
masterPlaylist.muxedCaptionFormat));
|
||||||
}
|
}
|
||||||
|
|
@ -379,7 +380,7 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||||
if (!audioVariants.isEmpty()) {
|
if (!audioVariants.isEmpty()) {
|
||||||
Variant[] variants = new Variant[audioVariants.size()];
|
Variant[] variants = new Variant[audioVariants.size()];
|
||||||
audioVariants.toArray(variants);
|
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));
|
null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -388,33 +389,33 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||||
if (!subtitleVariants.isEmpty()) {
|
if (!subtitleVariants.isEmpty()) {
|
||||||
Variant[] variants = new Variant[subtitleVariants.size()];
|
Variant[] variants = new Variant[subtitleVariants.size()];
|
||||||
subtitleVariants.toArray(variants);
|
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));
|
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,
|
Variant[] variants, FormatEvaluator formatEvaluator, Format muxedAudioFormat,
|
||||||
Format muxedCaptionFormat) {
|
Format muxedCaptionFormat) {
|
||||||
DataSource dataSource = dataSourceFactory.createDataSource(bandwidthMeter);
|
DataSource dataSource = dataSourceFactory.createDataSource(bandwidthMeter);
|
||||||
HlsChunkSource defaultChunkSource = new HlsChunkSource(baseUri, variants, dataSource,
|
HlsChunkSource defaultChunkSource = new HlsChunkSource(baseUri, variants, dataSource,
|
||||||
timestampAdjusterProvider, formatEvaluator);
|
timestampAdjusterProvider, formatEvaluator);
|
||||||
return new HlsTrackStreamWrapper(trackType, this, defaultChunkSource, allocator,
|
return new HlsSampleStreamWrapper(trackType, this, defaultChunkSource, allocator,
|
||||||
preparePositionUs, muxedAudioFormat, muxedCaptionFormat, minLoadableRetryCount,
|
preparePositionUs, muxedAudioFormat, muxedCaptionFormat, minLoadableRetryCount,
|
||||||
eventDispatcher);
|
eventDispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int selectTracks(HlsTrackStreamWrapper trackStreamWrapper,
|
private int selectTracks(HlsSampleStreamWrapper sampleStreamWrapper,
|
||||||
List<TrackStream> allOldStreams, List<TrackSelection> allNewSelections,
|
List<SampleStream> allOldStreams, List<TrackSelection> allNewSelections,
|
||||||
TrackStream[] allNewStreams) {
|
SampleStream[] allNewStreams) {
|
||||||
// Get the subset of the old streams for the source.
|
// 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++) {
|
for (int i = 0; i < allOldStreams.size(); i++) {
|
||||||
TrackStream stream = allOldStreams.get(i);
|
SampleStream stream = allOldStreams.get(i);
|
||||||
if (trackStreamSources.get(stream) == trackStreamWrapper) {
|
if (sampleStreamSources.get(stream) == sampleStreamWrapper) {
|
||||||
trackStreamSources.remove(stream);
|
sampleStreamSources.remove(stream);
|
||||||
oldStreams.add(stream);
|
oldStreams.add(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -423,8 +424,8 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||||
int[] newSelectionOriginalIndices = new int[allNewSelections.size()];
|
int[] newSelectionOriginalIndices = new int[allNewSelections.size()];
|
||||||
for (int i = 0; i < allNewSelections.size(); i++) {
|
for (int i = 0; i < allNewSelections.size(); i++) {
|
||||||
TrackSelection selection = allNewSelections.get(i);
|
TrackSelection selection = allNewSelections.get(i);
|
||||||
Pair<HlsTrackStreamWrapper, Integer> sourceAndGroup = getSourceAndGroup(selection.group);
|
Pair<HlsSampleStreamWrapper, Integer> sourceAndGroup = getSourceAndGroup(selection.group);
|
||||||
if (sourceAndGroup.first == trackStreamWrapper) {
|
if (sourceAndGroup.first == sampleStreamWrapper) {
|
||||||
newSelectionOriginalIndices[newSelections.size()] = i;
|
newSelectionOriginalIndices[newSelections.size()] = i;
|
||||||
newSelections.add(new TrackSelection(sourceAndGroup.second, selection.getTracks()));
|
newSelections.add(new TrackSelection(sourceAndGroup.second, selection.getTracks()));
|
||||||
}
|
}
|
||||||
|
|
@ -434,21 +435,21 @@ public final class HlsMediaSource implements MediaPeriod, MediaSource,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// Perform the selection.
|
// Perform the selection.
|
||||||
TrackStream[] newStreams = trackStreamWrapper.selectTracks(oldStreams, newSelections,
|
SampleStream[] newStreams = sampleStreamWrapper.selectTracks(oldStreams, newSelections,
|
||||||
!seenFirstTrackSelection);
|
!seenFirstTrackSelection);
|
||||||
for (int j = 0; j < newStreams.length; j++) {
|
for (int j = 0; j < newStreams.length; j++) {
|
||||||
allNewStreams[newSelectionOriginalIndices[j]] = newStreams[j];
|
allNewStreams[newSelectionOriginalIndices[j]] = newStreams[j];
|
||||||
trackStreamSources.put(newStreams[j], trackStreamWrapper);
|
sampleStreamSources.put(newStreams[j], sampleStreamWrapper);
|
||||||
}
|
}
|
||||||
return newSelections.size() - oldStreams.size();
|
return newSelections.size() - oldStreams.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Pair<HlsTrackStreamWrapper, Integer> getSourceAndGroup(int group) {
|
private Pair<HlsSampleStreamWrapper, Integer> getSourceAndGroup(int group) {
|
||||||
int totalTrackGroupCount = 0;
|
int totalTrackGroupCount = 0;
|
||||||
for (HlsTrackStreamWrapper trackStreamWrapper : trackStreamWrappers) {
|
for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) {
|
||||||
int sourceTrackGroupCount = trackStreamWrapper.getTrackGroups().length;
|
int sourceTrackGroupCount = sampleStreamWrapper.getTrackGroups().length;
|
||||||
if (group < totalTrackGroupCount + sourceTrackGroupCount) {
|
if (group < totalTrackGroupCount + sourceTrackGroupCount) {
|
||||||
return Pair.create(trackStreamWrapper, group - totalTrackGroupCount);
|
return Pair.create(sampleStreamWrapper, group - totalTrackGroupCount);
|
||||||
}
|
}
|
||||||
totalTrackGroupCount += sourceTrackGroupCount;
|
totalTrackGroupCount += sourceTrackGroupCount;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.FormatHolder;
|
import com.google.android.exoplayer2.FormatHolder;
|
||||||
import com.google.android.exoplayer2.SequenceableLoader;
|
import com.google.android.exoplayer2.SequenceableLoader;
|
||||||
import com.google.android.exoplayer2.TrackSelection;
|
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.Chunk;
|
||||||
import com.google.android.exoplayer2.chunk.ChunkHolder;
|
import com.google.android.exoplayer2.chunk.ChunkHolder;
|
||||||
import com.google.android.exoplayer2.extractor.DefaultTrackOutput;
|
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.ExtractorOutput;
|
||||||
import com.google.android.exoplayer2.extractor.SeekMap;
|
import com.google.android.exoplayer2.extractor.SeekMap;
|
||||||
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
|
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.TrackGroup;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.upstream.Allocator;
|
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
|
* 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 {
|
SequenceableLoader, ExtractorOutput, UpstreamFormatChangedListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A callback to be notified of events.
|
* 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.
|
* Invoked when the wrapper has been prepared.
|
||||||
|
|
@ -112,7 +112,7 @@ import java.util.List;
|
||||||
* before propagating an error.
|
* before propagating an error.
|
||||||
* @param eventDispatcher A dispatcher to notify of events.
|
* @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,
|
Allocator allocator, long positionUs, Format muxedAudioFormat, Format muxedCaptionFormat,
|
||||||
int minLoadableRetryCount, EventDispatcher eventDispatcher) {
|
int minLoadableRetryCount, EventDispatcher eventDispatcher) {
|
||||||
this.trackType = trackType;
|
this.trackType = trackType;
|
||||||
|
|
@ -123,7 +123,7 @@ import java.util.List;
|
||||||
this.muxedCaptionFormat = muxedCaptionFormat;
|
this.muxedCaptionFormat = muxedCaptionFormat;
|
||||||
this.minLoadableRetryCount = minLoadableRetryCount;
|
this.minLoadableRetryCount = minLoadableRetryCount;
|
||||||
this.eventDispatcher = eventDispatcher;
|
this.eventDispatcher = eventDispatcher;
|
||||||
loader = new Loader("Loader:HlsTrackStreamWrapper");
|
loader = new Loader("Loader:HlsSampleStreamWrapper");
|
||||||
nextChunkHolder = new ChunkHolder();
|
nextChunkHolder = new ChunkHolder();
|
||||||
sampleQueues = new SparseArray<>();
|
sampleQueues = new SparseArray<>();
|
||||||
mediaChunks = new LinkedList<>();
|
mediaChunks = new LinkedList<>();
|
||||||
|
|
@ -151,17 +151,17 @@ import java.util.List;
|
||||||
return trackGroups;
|
return trackGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
|
public SampleStream[] selectTracks(List<SampleStream> oldStreams,
|
||||||
List<TrackSelection> newSelections, boolean isFirstTrackSelection) {
|
List<TrackSelection> newSelections, boolean isFirstTrackSelection) {
|
||||||
Assertions.checkState(prepared);
|
Assertions.checkState(prepared);
|
||||||
// Unselect old tracks.
|
// Unselect old tracks.
|
||||||
for (int i = 0; i < oldStreams.size(); i++) {
|
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);
|
setTrackGroupEnabledState(group, false);
|
||||||
sampleQueues.valueAt(group).disable();
|
sampleQueues.valueAt(group).disable();
|
||||||
}
|
}
|
||||||
// Select new tracks.
|
// Select new tracks.
|
||||||
TrackStream[] newStreams = new TrackStream[newSelections.size()];
|
SampleStream[] newStreams = new SampleStream[newSelections.size()];
|
||||||
for (int i = 0; i < newStreams.length; i++) {
|
for (int i = 0; i < newStreams.length; i++) {
|
||||||
TrackSelection selection = newSelections.get(i);
|
TrackSelection selection = newSelections.get(i);
|
||||||
int group = selection.group;
|
int group = selection.group;
|
||||||
|
|
@ -170,7 +170,7 @@ import java.util.List;
|
||||||
if (group == primaryTrackGroupIndex) {
|
if (group == primaryTrackGroupIndex) {
|
||||||
chunkSource.selectTracks(tracks);
|
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
|
// At the time of the first track selection all queues will be enabled, so we need to disable
|
||||||
// any that are no longer required.
|
// any that are no longer required.
|
||||||
|
|
@ -239,7 +239,7 @@ import java.util.List;
|
||||||
loader.release();
|
loader.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrackStream implementation.
|
// SampleStream implementation.
|
||||||
|
|
||||||
/* package */ boolean isReady(int group) {
|
/* package */ boolean isReady(int group) {
|
||||||
return loadingFinished || (!isPendingReset() && !sampleQueues.valueAt(group).isEmpty());
|
return loadingFinished || (!isPendingReset() && !sampleQueues.valueAt(group).isEmpty());
|
||||||
|
|
@ -252,7 +252,7 @@ import java.util.List;
|
||||||
|
|
||||||
/* package */ int readData(int group, FormatHolder formatHolder, DecoderInputBuffer buffer) {
|
/* package */ int readData(int group, FormatHolder formatHolder, DecoderInputBuffer buffer) {
|
||||||
if (isPendingReset()) {
|
if (isPendingReset()) {
|
||||||
return TrackStream.NOTHING_READ;
|
return C.RESULT_NOTHING_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (mediaChunks.size() > 1 && finishedReadingChunk(mediaChunks.getFirst())) {
|
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.
|
* internal data-structures required for operation.
|
||||||
* <p>
|
* <p>
|
||||||
* Tracks in HLS are complicated. A HLS master playlist contains a number of "variants". Each
|
* 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 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
|
* 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
|
* 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>
|
* <ul>
|
||||||
* <li>The extractor tracks are inspected to infer a "primary" track type. If a video track is
|
* <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.
|
* 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;
|
return pendingResetPositionUs != C.UNSET_TIME_US;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class TrackStreamImpl implements TrackStream {
|
private final class SampleStreamImpl implements SampleStream {
|
||||||
|
|
||||||
private final int group;
|
private final int group;
|
||||||
|
|
||||||
public TrackStreamImpl(int group) {
|
public SampleStreamImpl(int group) {
|
||||||
this.group = group;
|
this.group = group;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isReady() {
|
public boolean isReady() {
|
||||||
return HlsTrackStreamWrapper.this.isReady(group);
|
return HlsSampleStreamWrapper.this.isReady(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void maybeThrowError() throws IOException {
|
public void maybeThrowError() throws IOException {
|
||||||
HlsTrackStreamWrapper.this.maybeThrowError();
|
HlsSampleStreamWrapper.this.maybeThrowError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
|
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
|
||||||
return HlsTrackStreamWrapper.this.readData(group, formatHolder, buffer);
|
return HlsSampleStreamWrapper.this.readData(group, formatHolder, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -21,8 +21,7 @@ import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.ParserException;
|
import com.google.android.exoplayer2.ParserException;
|
||||||
import com.google.android.exoplayer2.SequenceableLoader;
|
import com.google.android.exoplayer2.SequenceableLoader;
|
||||||
import com.google.android.exoplayer2.TrackSelection;
|
import com.google.android.exoplayer2.TrackSelection;
|
||||||
import com.google.android.exoplayer2.TrackStream;
|
import com.google.android.exoplayer2.chunk.ChunkSampleStream;
|
||||||
import com.google.android.exoplayer2.chunk.ChunkTrackStream;
|
|
||||||
import com.google.android.exoplayer2.chunk.FormatEvaluator;
|
import com.google.android.exoplayer2.chunk.FormatEvaluator;
|
||||||
import com.google.android.exoplayer2.chunk.FormatEvaluator.AdaptiveEvaluator;
|
import com.google.android.exoplayer2.chunk.FormatEvaluator.AdaptiveEvaluator;
|
||||||
import com.google.android.exoplayer2.extractor.mp4.TrackEncryptionBox;
|
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.AdaptiveMediaSourceEventListener.EventDispatcher;
|
||||||
import com.google.android.exoplayer2.source.MediaPeriod;
|
import com.google.android.exoplayer2.source.MediaPeriod;
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
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.TrackGroup;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
import com.google.android.exoplayer2.source.smoothstreaming.SmoothStreamingManifest.ProtectionElement;
|
import com.google.android.exoplayer2.source.smoothstreaming.SmoothStreamingManifest.ProtectionElement;
|
||||||
|
|
@ -56,7 +56,7 @@ import java.util.List;
|
||||||
* A SmoothStreaming {@link MediaSource}.
|
* A SmoothStreaming {@link MediaSource}.
|
||||||
*/
|
*/
|
||||||
public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSource,
|
public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSource,
|
||||||
SequenceableLoader.Callback<ChunkTrackStream<SmoothStreamingChunkSource>>,
|
SequenceableLoader.Callback<ChunkSampleStream<SmoothStreamingChunkSource>>,
|
||||||
Loader.Callback<ParsingLoadable<SmoothStreamingManifest>> {
|
Loader.Callback<ParsingLoadable<SmoothStreamingManifest>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -76,7 +76,7 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
||||||
|
|
||||||
private DataSource manifestDataSource;
|
private DataSource manifestDataSource;
|
||||||
private Loader manifestLoader;
|
private Loader manifestLoader;
|
||||||
private ChunkTrackStream<SmoothStreamingChunkSource>[] trackStreams;
|
private ChunkSampleStream<SmoothStreamingChunkSource>[] sampleStreams;
|
||||||
private CompositeSequenceableLoader sequenceableLoader;
|
private CompositeSequenceableLoader sequenceableLoader;
|
||||||
|
|
||||||
private long manifestLoadStartTimestamp;
|
private long manifestLoadStartTimestamp;
|
||||||
|
|
@ -129,8 +129,8 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
||||||
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
public void prepare(Callback callback, Allocator allocator, long positionUs) {
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
trackStreams = newTrackStreamArray(0);
|
sampleStreams = newSampleStreamArray(0);
|
||||||
sequenceableLoader = new CompositeSequenceableLoader(trackStreams);
|
sequenceableLoader = new CompositeSequenceableLoader(sampleStreams);
|
||||||
manifestDataSource = dataSourceFactory.createDataSource();
|
manifestDataSource = dataSourceFactory.createDataSource();
|
||||||
manifestLoader = new Loader("Loader:Manifest");
|
manifestLoader = new Loader("Loader:Manifest");
|
||||||
manifestRefreshHandler = new Handler();
|
manifestRefreshHandler = new Handler();
|
||||||
|
|
@ -153,32 +153,32 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TrackStream[] selectTracks(List<TrackStream> oldStreams,
|
public SampleStream[] selectTracks(List<SampleStream> oldStreams,
|
||||||
List<TrackSelection> newSelections, long positionUs) {
|
List<TrackSelection> newSelections, long positionUs) {
|
||||||
int newEnabledSourceCount = trackStreams.length + newSelections.size() - oldStreams.size();
|
int newEnabledSourceCount = sampleStreams.length + newSelections.size() - oldStreams.size();
|
||||||
ChunkTrackStream<SmoothStreamingChunkSource>[] newTrackStreams =
|
ChunkSampleStream<SmoothStreamingChunkSource>[] newSampleStreams =
|
||||||
newTrackStreamArray(newEnabledSourceCount);
|
newSampleStreamArray(newEnabledSourceCount);
|
||||||
int newEnabledSourceIndex = 0;
|
int newEnabledSourceIndex = 0;
|
||||||
|
|
||||||
// Iterate over currently enabled streams, either releasing them or adding them to the new list.
|
// Iterate over currently enabled streams, either releasing them or adding them to the new list.
|
||||||
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
|
for (ChunkSampleStream<SmoothStreamingChunkSource> sampleStream : sampleStreams) {
|
||||||
if (oldStreams.contains(trackStream)) {
|
if (oldStreams.contains(sampleStream)) {
|
||||||
trackStream.release();
|
sampleStream.release();
|
||||||
} else {
|
} else {
|
||||||
newTrackStreams[newEnabledSourceIndex++] = trackStream;
|
newSampleStreams[newEnabledSourceIndex++] = sampleStream;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instantiate and return new streams.
|
// 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++) {
|
for (int i = 0; i < newSelections.size(); i++) {
|
||||||
newTrackStreams[newEnabledSourceIndex] = buildTrackStream(newSelections.get(i), positionUs);
|
newSampleStreams[newEnabledSourceIndex] = buildSampleStream(newSelections.get(i), positionUs);
|
||||||
streamsToReturn[i] = newTrackStreams[newEnabledSourceIndex];
|
streamsToReturn[i] = newSampleStreams[newEnabledSourceIndex];
|
||||||
newEnabledSourceIndex++;
|
newEnabledSourceIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
trackStreams = newTrackStreams;
|
sampleStreams = newSampleStreams;
|
||||||
sequenceableLoader = new CompositeSequenceableLoader(trackStreams);
|
sequenceableLoader = new CompositeSequenceableLoader(sampleStreams);
|
||||||
return streamsToReturn;
|
return streamsToReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -200,8 +200,8 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
||||||
@Override
|
@Override
|
||||||
public long getBufferedPositionUs() {
|
public long getBufferedPositionUs() {
|
||||||
long bufferedPositionUs = Long.MAX_VALUE;
|
long bufferedPositionUs = Long.MAX_VALUE;
|
||||||
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
|
for (ChunkSampleStream<SmoothStreamingChunkSource> sampleStream : sampleStreams) {
|
||||||
long rendererBufferedPositionUs = trackStream.getBufferedPositionUs();
|
long rendererBufferedPositionUs = sampleStream.getBufferedPositionUs();
|
||||||
if (rendererBufferedPositionUs != C.END_OF_SOURCE_US) {
|
if (rendererBufferedPositionUs != C.END_OF_SOURCE_US) {
|
||||||
bufferedPositionUs = Math.min(bufferedPositionUs, rendererBufferedPositionUs);
|
bufferedPositionUs = Math.min(bufferedPositionUs, rendererBufferedPositionUs);
|
||||||
}
|
}
|
||||||
|
|
@ -211,8 +211,8 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long seekToUs(long positionUs) {
|
public long seekToUs(long positionUs) {
|
||||||
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
|
for (ChunkSampleStream<SmoothStreamingChunkSource> sampleStream : sampleStreams) {
|
||||||
trackStream.seekToUs(positionUs);
|
sampleStream.seekToUs(positionUs);
|
||||||
}
|
}
|
||||||
return positionUs;
|
return positionUs;
|
||||||
}
|
}
|
||||||
|
|
@ -224,11 +224,11 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
||||||
manifestLoader.release();
|
manifestLoader.release();
|
||||||
manifestLoader = null;
|
manifestLoader = null;
|
||||||
}
|
}
|
||||||
if (trackStreams != null) {
|
if (sampleStreams != null) {
|
||||||
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
|
for (ChunkSampleStream<SmoothStreamingChunkSource> sampleStream : sampleStreams) {
|
||||||
trackStream.release();
|
sampleStream.release();
|
||||||
}
|
}
|
||||||
trackStreams = null;
|
sampleStreams = null;
|
||||||
}
|
}
|
||||||
sequenceableLoader = null;
|
sequenceableLoader = null;
|
||||||
manifestLoadStartTimestamp = 0;
|
manifestLoadStartTimestamp = 0;
|
||||||
|
|
@ -249,7 +249,8 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
||||||
// SequenceableLoader.Callback implementation
|
// SequenceableLoader.Callback implementation
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContinueLoadingRequested(ChunkTrackStream<SmoothStreamingChunkSource> trackStream) {
|
public void onContinueLoadingRequested(
|
||||||
|
ChunkSampleStream<SmoothStreamingChunkSource> sampleStream) {
|
||||||
callback.onContinueLoadingRequested(this);
|
callback.onContinueLoadingRequested(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -274,8 +275,8 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
||||||
prepared = true;
|
prepared = true;
|
||||||
callback.onPeriodPrepared(this);
|
callback.onPeriodPrepared(this);
|
||||||
} else {
|
} else {
|
||||||
for (ChunkTrackStream<SmoothStreamingChunkSource> trackStream : trackStreams) {
|
for (ChunkSampleStream<SmoothStreamingChunkSource> sampleStream : sampleStreams) {
|
||||||
trackStream.getChunkSource().updateManifest(manifest);
|
sampleStream.getChunkSource().updateManifest(manifest);
|
||||||
}
|
}
|
||||||
callback.onContinueLoadingRequested(this);
|
callback.onContinueLoadingRequested(this);
|
||||||
}
|
}
|
||||||
|
|
@ -343,7 +344,7 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
||||||
trackGroups = new TrackGroupArray(trackGroupArray);
|
trackGroups = new TrackGroupArray(trackGroupArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChunkTrackStream<SmoothStreamingChunkSource> buildTrackStream(TrackSelection selection,
|
private ChunkSampleStream<SmoothStreamingChunkSource> buildSampleStream(TrackSelection selection,
|
||||||
long positionUs) {
|
long positionUs) {
|
||||||
int[] selectedTracks = selection.getTracks();
|
int[] selectedTracks = selection.getTracks();
|
||||||
FormatEvaluator adaptiveEvaluator = selectedTracks.length > 1
|
FormatEvaluator adaptiveEvaluator = selectedTracks.length > 1
|
||||||
|
|
@ -355,13 +356,13 @@ public final class SmoothStreamingMediaSource implements MediaPeriod, MediaSourc
|
||||||
SmoothStreamingChunkSource chunkSource = new SmoothStreamingChunkSource(manifestLoader,
|
SmoothStreamingChunkSource chunkSource = new SmoothStreamingChunkSource(manifestLoader,
|
||||||
manifest, streamElementIndex, trackGroups.get(selection.group), selectedTracks, dataSource,
|
manifest, streamElementIndex, trackGroups.get(selection.group), selectedTracks, dataSource,
|
||||||
adaptiveEvaluator, trackEncryptionBoxes);
|
adaptiveEvaluator, trackEncryptionBoxes);
|
||||||
return new ChunkTrackStream<>(streamElementType, chunkSource, this, allocator, positionUs,
|
return new ChunkSampleStream<>(streamElementType, chunkSource, this, allocator, positionUs,
|
||||||
minLoadableRetryCount, eventDispatcher);
|
minLoadableRetryCount, eventDispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static ChunkTrackStream<SmoothStreamingChunkSource>[] newTrackStreamArray(int length) {
|
private static ChunkSampleStream<SmoothStreamingChunkSource>[] newSampleStreamArray(int length) {
|
||||||
return new ChunkTrackStream[length];
|
return new ChunkSampleStream[length];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] getProtectionElementKeyId(byte[] initData) {
|
private static byte[] getProtectionElementKeyId(byte[] initData) {
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.FormatHolder;
|
import com.google.android.exoplayer2.FormatHolder;
|
||||||
import com.google.android.exoplayer2.ParserException;
|
import com.google.android.exoplayer2.ParserException;
|
||||||
import com.google.android.exoplayer2.Renderer;
|
import com.google.android.exoplayer2.Renderer;
|
||||||
import com.google.android.exoplayer2.TrackStream;
|
|
||||||
import com.google.android.exoplayer2.extensions.Decoder;
|
import com.google.android.exoplayer2.extensions.Decoder;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
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.
|
// Try and read the next subtitle from the source.
|
||||||
int result = readSource(formatHolder, nextInputBuffer);
|
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.
|
// Clear BUFFER_FLAG_DECODE_ONLY (see [Internal: b/27893809]) and queue the buffer.
|
||||||
nextInputBuffer.clearFlag(C.BUFFER_FLAG_DECODE_ONLY);
|
nextInputBuffer.clearFlag(C.BUFFER_FLAG_DECODE_ONLY);
|
||||||
if (nextInputBuffer.isEndOfStream()) {
|
if (nextInputBuffer.isEndOfStream()) {
|
||||||
|
|
@ -214,7 +213,7 @@ public final class TextRenderer extends Renderer implements Callback {
|
||||||
}
|
}
|
||||||
parser.queueInputBuffer(nextInputBuffer);
|
parser.queueInputBuffer(nextInputBuffer);
|
||||||
nextInputBuffer = null;
|
nextInputBuffer = null;
|
||||||
} else if (result == TrackStream.NOTHING_READ) {
|
} else if (result == C.RESULT_NOTHING_READ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue