Clean up enabled renderers + processing of resets.
- Made enabledRenderers an array to avoid loads of method calls. - Made if so that enabled renderers are always called in a consistent order, rather than their order changing if they're enabled/disabled over time. This is likely to make performance more predictable. - Split out reading of resets into a separate method. This method is now called directly after seeking on the source, so as to ensure instant propagation of the new position from source->renderers in the common case. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=117225639
This commit is contained in:
parent
9b467b7c1b
commit
9a40a4c77d
@ -36,7 +36,12 @@ public final class DummyTrackRenderer extends TrackRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doSomeWork(long positionUs, long elapsedRealtimeUs) {
|
protected void checkForReset() throws ExoPlaybackException {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void render(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,9 +32,7 @@ import android.util.Log;
|
|||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,7 +71,6 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
private final StandaloneMediaClock standaloneMediaClock;
|
private final StandaloneMediaClock standaloneMediaClock;
|
||||||
private final long minBufferUs;
|
private final long minBufferUs;
|
||||||
private final long minRebufferUs;
|
private final long minRebufferUs;
|
||||||
private final List<TrackRenderer> enabledRenderers;
|
|
||||||
private final TrackSelection[] trackSelections;
|
private final TrackSelection[] trackSelections;
|
||||||
private final Handler handler;
|
private final Handler handler;
|
||||||
private final HandlerThread internalPlaybackThread;
|
private final HandlerThread internalPlaybackThread;
|
||||||
@ -81,6 +78,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
private final AtomicInteger pendingSeekCount;
|
private final AtomicInteger pendingSeekCount;
|
||||||
|
|
||||||
private SampleSource source;
|
private SampleSource source;
|
||||||
|
private TrackRenderer[] enabledRenderers;
|
||||||
private boolean released;
|
private boolean released;
|
||||||
private boolean playWhenReady;
|
private boolean playWhenReady;
|
||||||
private boolean rebuffering;
|
private boolean rebuffering;
|
||||||
@ -123,8 +121,8 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
|
|
||||||
standaloneMediaClock = new StandaloneMediaClock();
|
standaloneMediaClock = new StandaloneMediaClock();
|
||||||
pendingSeekCount = new AtomicInteger();
|
pendingSeekCount = new AtomicInteger();
|
||||||
enabledRenderers = new ArrayList<>(renderers.length);
|
|
||||||
trackSelections = new TrackSelection[renderers.length];
|
trackSelections = new TrackSelection[renderers.length];
|
||||||
|
enabledRenderers = new TrackRenderer[0];
|
||||||
|
|
||||||
trackSelector.init(this);
|
trackSelector.init(this);
|
||||||
|
|
||||||
@ -361,21 +359,21 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
private void startRenderers() throws ExoPlaybackException {
|
private void startRenderers() throws ExoPlaybackException {
|
||||||
rebuffering = false;
|
rebuffering = false;
|
||||||
standaloneMediaClock.start();
|
standaloneMediaClock.start();
|
||||||
for (int i = 0; i < enabledRenderers.size(); i++) {
|
for (TrackRenderer renderer : enabledRenderers) {
|
||||||
enabledRenderers.get(i).start();
|
renderer.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopRenderers() throws ExoPlaybackException {
|
private void stopRenderers() throws ExoPlaybackException {
|
||||||
standaloneMediaClock.stop();
|
standaloneMediaClock.stop();
|
||||||
for (int i = 0; i < enabledRenderers.size(); i++) {
|
for (TrackRenderer renderer : enabledRenderers) {
|
||||||
ensureStopped(enabledRenderers.get(i));
|
ensureStopped(renderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePositionUs() {
|
private void updatePositionUs() {
|
||||||
if (rendererMediaClock != null && enabledRenderers.contains(rendererMediaClockSource)
|
if (rendererMediaClock != null
|
||||||
&& !rendererMediaClockSource.isEnded()) {
|
&& rendererMediaClockSource.getState() != TrackRenderer.STATE_DISABLED) {
|
||||||
positionUs = rendererMediaClock.getPositionUs();
|
positionUs = rendererMediaClock.getPositionUs();
|
||||||
standaloneMediaClock.setPositionUs(positionUs);
|
standaloneMediaClock.setPositionUs(positionUs);
|
||||||
} else {
|
} else {
|
||||||
@ -387,18 +385,23 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
private void doSomeWork() throws ExoPlaybackException, IOException {
|
private void doSomeWork() throws ExoPlaybackException, IOException {
|
||||||
TraceUtil.beginSection("doSomeWork");
|
TraceUtil.beginSection("doSomeWork");
|
||||||
long operationStartTimeMs = SystemClock.elapsedRealtime();
|
long operationStartTimeMs = SystemClock.elapsedRealtime();
|
||||||
|
|
||||||
|
// Process resets.
|
||||||
|
for (TrackRenderer renderer : enabledRenderers) {
|
||||||
|
renderer.checkForReset();
|
||||||
|
}
|
||||||
|
|
||||||
updatePositionUs();
|
updatePositionUs();
|
||||||
bufferedPositionUs = source.getBufferedPositionUs();
|
bufferedPositionUs = source.getBufferedPositionUs();
|
||||||
source.continueBuffering(positionUs);
|
source.continueBuffering(positionUs);
|
||||||
|
|
||||||
boolean allRenderersEnded = true;
|
boolean allRenderersEnded = true;
|
||||||
boolean allRenderersReadyOrEnded = true;
|
boolean allRenderersReadyOrEnded = true;
|
||||||
for (int i = 0; i < enabledRenderers.size(); i++) {
|
for (TrackRenderer renderer : enabledRenderers) {
|
||||||
TrackRenderer renderer = enabledRenderers.get(i);
|
|
||||||
// TODO: Each renderer should return the maximum delay before which it wishes to be
|
// TODO: Each renderer should return the maximum delay before which it wishes to be
|
||||||
// invoked again. The minimum of these values should then be used as the delay before the next
|
// invoked again. The minimum of these values should then be used as the delay before the next
|
||||||
// invocation of this method.
|
// invocation of this method.
|
||||||
renderer.doSomeWork(positionUs, elapsedRealtimeUs);
|
renderer.render(positionUs, elapsedRealtimeUs);
|
||||||
allRenderersEnded = allRenderersEnded && renderer.isEnded();
|
allRenderersEnded = allRenderersEnded && renderer.isEnded();
|
||||||
// Determine whether the renderer is ready (or ended). If it's not, throw an error that's
|
// Determine whether the renderer is ready (or ended). If it's not, throw an error that's
|
||||||
// preventing the renderer from making progress, if such an error exists.
|
// preventing the renderer from making progress, if such an error exists.
|
||||||
@ -427,7 +430,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
handler.removeMessages(MSG_DO_SOME_WORK);
|
handler.removeMessages(MSG_DO_SOME_WORK);
|
||||||
if ((playWhenReady && state == ExoPlayer.STATE_READY) || state == ExoPlayer.STATE_BUFFERING) {
|
if ((playWhenReady && state == ExoPlayer.STATE_READY) || state == ExoPlayer.STATE_BUFFERING) {
|
||||||
scheduleNextOperation(MSG_DO_SOME_WORK, operationStartTimeMs, RENDERING_INTERVAL_MS);
|
scheduleNextOperation(MSG_DO_SOME_WORK, operationStartTimeMs, RENDERING_INTERVAL_MS);
|
||||||
} else if (!enabledRenderers.isEmpty()) {
|
} else if (enabledRenderers.length != 0) {
|
||||||
scheduleNextOperation(MSG_DO_SOME_WORK, operationStartTimeMs, IDLE_INTERVAL_MS);
|
scheduleNextOperation(MSG_DO_SOME_WORK, operationStartTimeMs, IDLE_INTERVAL_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,12 +462,16 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
if (state == ExoPlayer.STATE_IDLE || state == ExoPlayer.STATE_PREPARING) {
|
if (state == ExoPlayer.STATE_IDLE || state == ExoPlayer.STATE_PREPARING) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < enabledRenderers.size(); i++) {
|
|
||||||
TrackRenderer renderer = enabledRenderers.get(i);
|
for (TrackRenderer renderer : enabledRenderers) {
|
||||||
ensureStopped(renderer);
|
ensureStopped(renderer);
|
||||||
}
|
}
|
||||||
setState(ExoPlayer.STATE_BUFFERING);
|
setState(ExoPlayer.STATE_BUFFERING);
|
||||||
source.seekToUs(positionUs);
|
source.seekToUs(positionUs);
|
||||||
|
for (TrackRenderer renderer : enabledRenderers) {
|
||||||
|
renderer.checkForReset();
|
||||||
|
}
|
||||||
|
|
||||||
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
|
handler.sendEmptyMessage(MSG_DO_SOME_WORK);
|
||||||
} finally {
|
} finally {
|
||||||
pendingSeekCount.decrementAndGet();
|
pendingSeekCount.decrementAndGet();
|
||||||
@ -493,10 +500,10 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
if (renderers == null) {
|
if (renderers == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < renderers.length; i++) {
|
for (TrackRenderer renderer : renderers) {
|
||||||
resetRendererInternal(renderers[i]);
|
resetRendererInternal(renderer);
|
||||||
}
|
}
|
||||||
enabledRenderers.clear();
|
enabledRenderers = new TrackRenderer[0];
|
||||||
Arrays.fill(trackSelections, null);
|
Arrays.fill(trackSelections, null);
|
||||||
source = null;
|
source = null;
|
||||||
}
|
}
|
||||||
@ -547,16 +554,19 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
|
|
||||||
// Disable renderers whose track selections have changed.
|
// Disable renderers whose track selections have changed.
|
||||||
boolean[] rendererWasEnabledFlags = new boolean[renderers.length];
|
boolean[] rendererWasEnabledFlags = new boolean[renderers.length];
|
||||||
|
int enabledRendererCount = 0;
|
||||||
for (int i = 0; i < renderers.length; i++) {
|
for (int i = 0; i < renderers.length; i++) {
|
||||||
TrackRenderer renderer = renderers[i];
|
TrackRenderer renderer = renderers[i];
|
||||||
TrackSelection previousTrackSelection = trackSelections[i];
|
TrackSelection previousTrackSelection = trackSelections[i];
|
||||||
trackSelections[i] = newTrackSelections.get(i);
|
trackSelections[i] = newTrackSelections.get(i);
|
||||||
|
if (trackSelections[i] != null) {
|
||||||
|
enabledRendererCount++;
|
||||||
|
}
|
||||||
|
rendererWasEnabledFlags[i] = renderer.getState() != TrackRenderer.STATE_DISABLED;
|
||||||
if (!Util.areEqual(previousTrackSelection, trackSelections[i])) {
|
if (!Util.areEqual(previousTrackSelection, trackSelections[i])) {
|
||||||
// The track selection has changed for this renderer.
|
// The track selection has changed for this renderer.
|
||||||
int rendererState = renderer.getState();
|
if (rendererWasEnabledFlags[i]) {
|
||||||
boolean isEnabled = rendererState == TrackRenderer.STATE_ENABLED
|
// We need to disable the renderer so that we can enable it with its new selection.
|
||||||
|| rendererState == TrackRenderer.STATE_STARTED;
|
|
||||||
if (isEnabled) {
|
|
||||||
if (trackSelections[i] == null && renderer == rendererMediaClockSource) {
|
if (trackSelections[i] == null && renderer == rendererMediaClockSource) {
|
||||||
// We've been using rendererMediaClockSource to advance the current position, but it's
|
// We've been using rendererMediaClockSource to advance the current position, but it's
|
||||||
// being disabled and won't be re-enabled. Sync standaloneMediaClock so that it can take
|
// being disabled and won't be re-enabled. Sync standaloneMediaClock so that it can take
|
||||||
@ -564,37 +574,37 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
standaloneMediaClock.setPositionUs(rendererMediaClock.getPositionUs());
|
standaloneMediaClock.setPositionUs(rendererMediaClock.getPositionUs());
|
||||||
}
|
}
|
||||||
ensureStopped(renderer);
|
ensureStopped(renderer);
|
||||||
enabledRenderers.remove(renderer);
|
|
||||||
renderer.disable();
|
renderer.disable();
|
||||||
}
|
}
|
||||||
rendererWasEnabledFlags[i] = isEnabled;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enabledRenderers = new TrackRenderer[enabledRendererCount];
|
||||||
|
enabledRendererCount = 0;
|
||||||
|
|
||||||
// Enable renderers with their new track selections.
|
// Enable renderers with their new track selections.
|
||||||
for (int i = 0; i < renderers.length; i++) {
|
for (int i = 0; i < renderers.length; i++) {
|
||||||
TrackRenderer renderer = renderers[i];
|
TrackRenderer renderer = renderers[i];
|
||||||
TrackSelection trackSelection = trackSelections[i];
|
TrackSelection trackSelection = trackSelections[i];
|
||||||
int rendererState = renderer.getState();
|
if (trackSelection != null) {
|
||||||
boolean isEnabled = rendererState == TrackRenderer.STATE_ENABLED
|
enabledRenderers[enabledRendererCount++] = renderer;
|
||||||
|| rendererState == TrackRenderer.STATE_STARTED;
|
if (renderer.getState() == TrackRenderer.STATE_DISABLED) {
|
||||||
if (!isEnabled && trackSelection != null) {
|
// The renderer needs enabling with its new track selection.
|
||||||
// The renderer needs enabling with its new track selection.
|
boolean playing = playWhenReady && state == ExoPlayer.STATE_READY;
|
||||||
boolean playing = playWhenReady && state == ExoPlayer.STATE_READY;
|
// Consider as joining only if the renderer was previously disabled.
|
||||||
// Consider as joining only if the renderer was previously disabled.
|
boolean joining = !rendererWasEnabledFlags[i] && playing;
|
||||||
boolean joining = !rendererWasEnabledFlags[i] && playing;
|
// Enable the source and obtain the stream for the renderer to consume.
|
||||||
// Enable the source and obtain the stream for the renderer to consume.
|
TrackStream trackStream = source.enable(trackSelection, positionUs);
|
||||||
TrackStream trackStream = source.enable(trackSelection, positionUs);
|
// Build an array of formats contained by the new selection.
|
||||||
// Build an array of formats contained by the new selection.
|
Format[] formats = new Format[trackSelection.length];
|
||||||
Format[] formats = new Format[trackSelection.length];
|
for (int j = 0; j < formats.length; j++) {
|
||||||
for (int j = 0; j < formats.length; j++) {
|
formats[j] = groups.get(trackSelections[i].group).getFormat(trackSelection.getTrack(j));
|
||||||
formats[j] = groups.get(trackSelections[i].group).getFormat(trackSelection.getTrack(j));
|
}
|
||||||
}
|
// Enable the renderer.
|
||||||
// Enable the renderer.
|
renderer.enable(formats, trackStream, positionUs, joining);
|
||||||
renderer.enable(formats, trackStream, positionUs, joining);
|
if (playing) {
|
||||||
enabledRenderers.add(renderer);
|
renderer.start();
|
||||||
if (playing) {
|
}
|
||||||
renderer.start();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -319,8 +319,8 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onReset(long positionUs) throws ExoPlaybackException {
|
protected void reset(long positionUs) throws ExoPlaybackException {
|
||||||
super.onReset(positionUs);
|
super.reset(positionUs);
|
||||||
audioTrack.reset();
|
audioTrack.reset();
|
||||||
currentPositionUs = positionUs;
|
currentPositionUs = positionUs;
|
||||||
allowPositionDiscontinuity = true;
|
allowPositionDiscontinuity = true;
|
||||||
|
@ -461,7 +461,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onReset(long positionUs) throws ExoPlaybackException {
|
protected void reset(long positionUs) throws ExoPlaybackException {
|
||||||
sourceState = SOURCE_STATE_NOT_READY;
|
sourceState = SOURCE_STATE_NOT_READY;
|
||||||
inputStreamEnded = false;
|
inputStreamEnded = false;
|
||||||
outputStreamEnded = false;
|
outputStreamEnded = false;
|
||||||
@ -481,7 +481,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doSomeWork(long positionUs, long elapsedRealtimeUs, boolean sourceIsReady)
|
protected void render(long positionUs, long elapsedRealtimeUs, boolean sourceIsReady)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
sourceState = sourceIsReady
|
sourceState = sourceIsReady
|
||||||
? (sourceState == SOURCE_STATE_NOT_READY ? SOURCE_STATE_READY : sourceState)
|
? (sourceState == SOURCE_STATE_NOT_READY ? SOURCE_STATE_READY : sourceState)
|
||||||
@ -537,7 +537,7 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param firstFeed True if this is the first call to this method from the current invocation of
|
* @param firstFeed True if this is the first call to this method from the current invocation of
|
||||||
* {@link #doSomeWork(long, long)}. False otherwise.
|
* {@link #render(long, long)}. False otherwise.
|
||||||
* @return True if it may be possible to feed more input data. False otherwise.
|
* @return True if it may be possible to feed more input data. False otherwise.
|
||||||
* @throws ExoPlaybackException If an error occurs feeding the input buffer.
|
* @throws ExoPlaybackException If an error occurs feeding the input buffer.
|
||||||
*/
|
*/
|
||||||
|
@ -284,8 +284,8 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onReset(long positionUs) throws ExoPlaybackException {
|
protected void reset(long positionUs) throws ExoPlaybackException {
|
||||||
super.onReset(positionUs);
|
super.reset(positionUs);
|
||||||
renderedFirstFrame = false;
|
renderedFirstFrame = false;
|
||||||
consecutiveDroppedFrameCount = 0;
|
consecutiveDroppedFrameCount = 0;
|
||||||
joiningDeadlineUs = -1;
|
joiningDeadlineUs = -1;
|
||||||
@ -293,8 +293,8 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isReady() {
|
protected boolean isReady() {
|
||||||
if (super.isReady() && (renderedFirstFrame || !codecInitialized()
|
if (super.isReady()
|
||||||
|| getSourceState() == SOURCE_STATE_READY_READ_MAY_FAIL)) {
|
&& (renderedFirstFrame || getSourceState() == SOURCE_STATE_READY_READ_MAY_FAIL)) {
|
||||||
// Ready. If we were joining then we've now joined, so clear the joining deadline.
|
// Ready. If we were joining then we've now joined, so clear the joining deadline.
|
||||||
joiningDeadlineUs = -1;
|
joiningDeadlineUs = -1;
|
||||||
return true;
|
return true;
|
||||||
|
@ -31,23 +31,26 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer {
|
|||||||
protected void onEnabled(Format[] formats, TrackStream trackStream, long positionUs,
|
protected void onEnabled(Format[] formats, TrackStream trackStream, long positionUs,
|
||||||
boolean joining) throws ExoPlaybackException {
|
boolean joining) throws ExoPlaybackException {
|
||||||
this.trackStream = Assertions.checkNotNull(trackStream);
|
this.trackStream = Assertions.checkNotNull(trackStream);
|
||||||
onReset(positionUs);
|
reset(positionUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final void doSomeWork(long positionUs, long elapsedRealtimeUs)
|
protected final void checkForReset() throws ExoPlaybackException {
|
||||||
throws ExoPlaybackException {
|
|
||||||
// TODO[REFACTOR]: Consider splitting reading of resets into a separate method?
|
|
||||||
long resetPositionUs = trackStream.readReset();
|
long resetPositionUs = trackStream.readReset();
|
||||||
if (resetPositionUs != TrackStream.NO_RESET) {
|
if (resetPositionUs != TrackStream.NO_RESET) {
|
||||||
onReset(resetPositionUs);
|
reset(resetPositionUs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
doSomeWork(positionUs, elapsedRealtimeUs, trackStream.isReady());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void maybeThrowError() throws IOException {
|
protected final void render(long positionUs, long elapsedRealtimeUs)
|
||||||
|
throws ExoPlaybackException {
|
||||||
|
render(positionUs, elapsedRealtimeUs, trackStream.isReady());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final void maybeThrowError() throws IOException {
|
||||||
trackStream.maybeThrowError();
|
trackStream.maybeThrowError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,15 +80,15 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer {
|
|||||||
// Abstract methods.
|
// Abstract methods.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked when a reset is encountered. Also invoked when the renderer is enabled.
|
* Invoked when a reset is encountered, and also when the renderer is enabled.
|
||||||
*
|
*
|
||||||
* @param positionUs The playback position in microseconds.
|
* @param positionUs The playback position in microseconds.
|
||||||
* @throws ExoPlaybackException If an error occurs handling the reset.
|
* @throws ExoPlaybackException If an error occurs handling the reset.
|
||||||
*/
|
*/
|
||||||
protected abstract void onReset(long positionUs) throws ExoPlaybackException;
|
protected abstract void reset(long positionUs) throws ExoPlaybackException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by {@link #doSomeWork(long, long)}.
|
* Called by {@link #render(long, long)}.
|
||||||
*
|
*
|
||||||
* @param positionUs The current media time in microseconds, measured at the start of the
|
* @param positionUs The current media time in microseconds, measured at the start of the
|
||||||
* current iteration of the rendering loop.
|
* current iteration of the rendering loop.
|
||||||
@ -93,9 +96,8 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer {
|
|||||||
* measured at the start of the current iteration of the rendering loop.
|
* measured at the start of the current iteration of the rendering loop.
|
||||||
* @param sourceIsReady The result of the most recent call to {@link TrackStream#isReady()}.
|
* @param sourceIsReady The result of the most recent call to {@link TrackStream#isReady()}.
|
||||||
* @throws ExoPlaybackException If an error occurs.
|
* @throws ExoPlaybackException If an error occurs.
|
||||||
* @throws ExoPlaybackException
|
|
||||||
*/
|
*/
|
||||||
protected abstract void doSomeWork(long positionUs, long elapsedRealtimeUs, boolean sourceIsReady)
|
protected abstract void render(long positionUs, long elapsedRealtimeUs, boolean sourceIsReady)
|
||||||
throws ExoPlaybackException;
|
throws ExoPlaybackException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -92,19 +92,16 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
|
|||||||
public static final int ADAPTIVE_NOT_SUPPORTED = 0b0000;
|
public static final int ADAPTIVE_NOT_SUPPORTED = 0b0000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The renderer is idle.
|
* The renderer is disabled.
|
||||||
*/
|
*/
|
||||||
protected static final int STATE_IDLE = 0;
|
protected static final int STATE_DISABLED = 0;
|
||||||
/**
|
/**
|
||||||
* The renderer is enabled. It should either be ready to be started, or be actively working
|
* The renderer is enabled but not started. A renderer in this state will typically hold any
|
||||||
* towards this state (e.g. a renderer in this state will typically hold any resources that it
|
* resources that it requires for rendering (e.g. media decoders).
|
||||||
* requires, such as media decoders, and will have buffered or be buffering any media data that
|
|
||||||
* is required to start playback).
|
|
||||||
*/
|
*/
|
||||||
protected static final int STATE_ENABLED = 1;
|
protected static final int STATE_ENABLED = 1;
|
||||||
/**
|
/**
|
||||||
* The renderer is started. Calls to {@link #doSomeWork(long, long)} should cause the media to be
|
* The renderer is started. Calls to {@link #render(long, long)} will cause media to be rendered.
|
||||||
* rendered.
|
|
||||||
*/
|
*/
|
||||||
protected static final int STATE_STARTED = 2;
|
protected static final int STATE_STARTED = 2;
|
||||||
|
|
||||||
@ -195,7 +192,7 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
|
|||||||
*/
|
*/
|
||||||
/* package */ final void enable(Format[] formats, TrackStream trackStream, long positionUs,
|
/* package */ final void enable(Format[] formats, TrackStream trackStream, long positionUs,
|
||||||
boolean joining) throws ExoPlaybackException {
|
boolean joining) throws ExoPlaybackException {
|
||||||
Assertions.checkState(state == STATE_IDLE);
|
Assertions.checkState(state == STATE_DISABLED);
|
||||||
state = STATE_ENABLED;
|
state = STATE_ENABLED;
|
||||||
onEnabled(formats, trackStream, positionUs, joining);
|
onEnabled(formats, trackStream, positionUs, joining);
|
||||||
}
|
}
|
||||||
@ -217,8 +214,8 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the renderer, meaning that calls to {@link #doSomeWork(long, long)} will cause the
|
* Starts the renderer, meaning that calls to {@link #render(long, long)} will cause media to be
|
||||||
* track to be rendered.
|
* rendered.
|
||||||
*
|
*
|
||||||
* @throws ExoPlaybackException If an error occurs.
|
* @throws ExoPlaybackException If an error occurs.
|
||||||
*/
|
*/
|
||||||
@ -268,7 +265,7 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
|
|||||||
*/
|
*/
|
||||||
/* package */ final void disable() throws ExoPlaybackException {
|
/* package */ final void disable() throws ExoPlaybackException {
|
||||||
Assertions.checkState(state == STATE_ENABLED);
|
Assertions.checkState(state == STATE_ENABLED);
|
||||||
state = STATE_IDLE;
|
state = STATE_DISABLED;
|
||||||
onDisabled();
|
onDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,7 +286,7 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
|
|||||||
* returned by all of its {@link TrackRenderer}s.
|
* returned by all of its {@link TrackRenderer}s.
|
||||||
* <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:
|
||||||
* {@link #STATE_ENABLED}, {@link #STATE_STARTED}
|
* {@link #STATE_ENABLED}, {@link #STATE_STARTED}.
|
||||||
*
|
*
|
||||||
* @return Whether the renderer is ready for the player to transition to the ended state.
|
* @return Whether the renderer is ready for the player to transition to the ended state.
|
||||||
*/
|
*/
|
||||||
@ -306,26 +303,30 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
|
|||||||
* renderer is ready for playback to be started. Returning false indicates that it is not.
|
* renderer is ready for playback to be started. Returning false indicates that it is not.
|
||||||
* <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:
|
||||||
* {@link #STATE_ENABLED}, {@link #STATE_STARTED}
|
* {@link #STATE_ENABLED}, {@link #STATE_STARTED}.
|
||||||
*
|
*
|
||||||
* @return True if the renderer is ready to render media. False otherwise.
|
* @return True if the renderer is ready to render media. False otherwise.
|
||||||
*/
|
*/
|
||||||
protected abstract boolean isReady();
|
protected abstract boolean isReady();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked to make progress when the renderer is in the {@link #STATE_ENABLED} or
|
* Attempts to read and process a pending reset from the {@link TrackStream}.
|
||||||
* {@link #STATE_STARTED} states.
|
|
||||||
* <p>
|
|
||||||
* If the renderer's state is {@link #STATE_STARTED}, then repeated calls to this method should
|
|
||||||
* cause the media track to be rendered. If the state is {@link #STATE_ENABLED}, then repeated
|
|
||||||
* calls should make progress towards getting the renderer into a position where it is ready to
|
|
||||||
* render the track.
|
|
||||||
* <p>
|
|
||||||
* This method should return quickly, and should not block if the renderer is currently unable to
|
|
||||||
* make any useful progress.
|
|
||||||
* <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:
|
||||||
* {@link #STATE_ENABLED}, {@link #STATE_STARTED}
|
* {@link #STATE_ENABLED}, {@link #STATE_STARTED}.
|
||||||
|
*
|
||||||
|
* @throws ExoPlaybackException If an error occurs.
|
||||||
|
*/
|
||||||
|
protected abstract void checkForReset() throws ExoPlaybackException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Incrementally renders the {@link TrackStream}.
|
||||||
|
* <p>
|
||||||
|
* This method should return quickly, and should not block if the renderer is unable to make
|
||||||
|
* useful progress.
|
||||||
|
* <p>
|
||||||
|
* This method may be called when the renderer is in the following states:
|
||||||
|
* {@link #STATE_ENABLED}, {@link #STATE_STARTED}.
|
||||||
*
|
*
|
||||||
* @param positionUs The current media time in microseconds, measured at the start of the
|
* @param positionUs The current media time in microseconds, measured at the start of the
|
||||||
* current iteration of the rendering loop.
|
* current iteration of the rendering loop.
|
||||||
@ -333,7 +334,7 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
|
|||||||
* measured at the start of the current iteration of the rendering loop.
|
* measured at the start of the current iteration of the rendering loop.
|
||||||
* @throws ExoPlaybackException If an error occurs.
|
* @throws ExoPlaybackException If an error occurs.
|
||||||
*/
|
*/
|
||||||
protected abstract void doSomeWork(long positionUs, long elapsedRealtimeUs)
|
protected abstract void render(long positionUs, long elapsedRealtimeUs)
|
||||||
throws ExoPlaybackException;
|
throws ExoPlaybackException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -341,7 +342,7 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
|
|||||||
* this point in time.
|
* this point in time.
|
||||||
* <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:
|
||||||
* {@link #STATE_ENABLED}
|
* {@link #STATE_ENABLED}.
|
||||||
*
|
*
|
||||||
* @throws IOException An error that's preventing the renderer from making progress or buffering
|
* @throws IOException An error that's preventing the renderer from making progress or buffering
|
||||||
* more data.
|
* more data.
|
||||||
|
@ -92,13 +92,13 @@ public final class MetadataTrackRenderer<T> extends SampleSourceTrackRenderer im
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onReset(long positionUs) {
|
protected void reset(long positionUs) {
|
||||||
pendingMetadata = null;
|
pendingMetadata = null;
|
||||||
inputStreamEnded = false;
|
inputStreamEnded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doSomeWork(long positionUs, long elapsedRealtimeUs, boolean sourceIsReady)
|
protected void render(long positionUs, long elapsedRealtimeUs, boolean sourceIsReady)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
if (!inputStreamEnded && pendingMetadata == null) {
|
if (!inputStreamEnded && pendingMetadata == null) {
|
||||||
sampleHolder.clearData();
|
sampleHolder.clearData();
|
||||||
|
@ -173,7 +173,7 @@ public final class TextTrackRenderer extends SampleSourceTrackRenderer implement
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onReset(long positionUs) {
|
protected void reset(long positionUs) {
|
||||||
inputStreamEnded = false;
|
inputStreamEnded = false;
|
||||||
subtitle = null;
|
subtitle = null;
|
||||||
nextSubtitle = null;
|
nextSubtitle = null;
|
||||||
@ -184,7 +184,7 @@ public final class TextTrackRenderer extends SampleSourceTrackRenderer implement
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doSomeWork(long positionUs, long elapsedRealtimeUs, boolean sourceIsReady)
|
protected void render(long positionUs, long elapsedRealtimeUs, boolean sourceIsReady)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
if (nextSubtitle == null) {
|
if (nextSubtitle == null) {
|
||||||
try {
|
try {
|
||||||
|
@ -93,7 +93,7 @@ public final class Eia608TrackRenderer extends SampleSourceTrackRenderer impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onReset(long positionUs) {
|
protected void reset(long positionUs) {
|
||||||
inputStreamEnded = false;
|
inputStreamEnded = false;
|
||||||
repeatableControl = null;
|
repeatableControl = null;
|
||||||
pendingCaptionLists.clear();
|
pendingCaptionLists.clear();
|
||||||
@ -104,7 +104,7 @@ public final class Eia608TrackRenderer extends SampleSourceTrackRenderer impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doSomeWork(long positionUs, long elapsedRealtimeUs, boolean sourceIsReady)
|
protected void render(long positionUs, long elapsedRealtimeUs, boolean sourceIsReady)
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
if (isSamplePending()) {
|
if (isSamplePending()) {
|
||||||
maybeParsePendingSample(positionUs);
|
maybeParsePendingSample(positionUs);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user