diff --git a/extensions/opus/src/main/java/com/google/android/exoplayer/ext/opus/LibopusAudioTrackRenderer.java b/extensions/opus/src/main/java/com/google/android/exoplayer/ext/opus/LibopusAudioTrackRenderer.java
index 51b27cf7b1..bfdbcf50b0 100644
--- a/extensions/opus/src/main/java/com/google/android/exoplayer/ext/opus/LibopusAudioTrackRenderer.java
+++ b/extensions/opus/src/main/java/com/google/android/exoplayer/ext/opus/LibopusAudioTrackRenderer.java
@@ -131,8 +131,9 @@ public final class LibopusAudioTrackRenderer extends SampleSourceTrackRenderer
}
@Override
- protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException {
- super.onEnabled(positionUs, joining);
+ protected void onEnabled(int track, long positionUs, boolean joining)
+ throws ExoPlaybackException {
+ super.onEnabled(track, positionUs, joining);
seekToInternal(positionUs);
}
diff --git a/extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/LibvpxVideoTrackRenderer.java b/extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/LibvpxVideoTrackRenderer.java
index 71e59bafd7..1ea758b6a1 100644
--- a/extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/LibvpxVideoTrackRenderer.java
+++ b/extensions/vp9/src/main/java/com/google/android/exoplayer/ext/vp9/LibvpxVideoTrackRenderer.java
@@ -349,8 +349,9 @@ public final class LibvpxVideoTrackRenderer extends SampleSourceTrackRenderer {
}
@Override
- protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException {
- super.onEnabled(positionUs, joining);
+ protected void onEnabled(int track, long positionUs, boolean joining)
+ throws ExoPlaybackException {
+ super.onEnabled(track, positionUs, joining);
seekToInternal();
}
diff --git a/library/src/main/java/com/google/android/exoplayer/DummyTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/DummyTrackRenderer.java
index 1a1305898e..fd36939093 100644
--- a/library/src/main/java/com/google/android/exoplayer/DummyTrackRenderer.java
+++ b/library/src/main/java/com/google/android/exoplayer/DummyTrackRenderer.java
@@ -18,15 +18,25 @@ package com.google.android.exoplayer;
/**
* A {@link TrackRenderer} that does nothing.
*
- * This renderer returns {@link TrackRenderer#STATE_IGNORE} from {@link #doPrepare(long)} in order
- * to request that it should be ignored. {@link IllegalStateException} is thrown from all methods
- * that are documented to indicate that they should not be invoked unless the renderer is prepared.
+ * This renderer returns 0 from {@link #getTrackCount()} in order to request that it should be
+ * ignored. {@link IllegalStateException} is thrown from all other methods documented to indicate
+ * that they should not be invoked unless the renderer is prepared.
*/
public final class DummyTrackRenderer extends TrackRenderer {
@Override
- protected int doPrepare(long positionUs) {
- return STATE_IGNORE;
+ protected boolean doPrepare(long positionUs) throws ExoPlaybackException {
+ return true;
+ }
+
+ @Override
+ protected int getTrackCount() {
+ return 0;
+ }
+
+ @Override
+ protected TrackInfo getTrackInfo(int track) {
+ throw new IllegalStateException();
}
@Override
diff --git a/library/src/main/java/com/google/android/exoplayer/ExoPlayerImpl.java b/library/src/main/java/com/google/android/exoplayer/ExoPlayerImpl.java
index 6729bfddd8..2823cc7f31 100644
--- a/library/src/main/java/com/google/android/exoplayer/ExoPlayerImpl.java
+++ b/library/src/main/java/com/google/android/exoplayer/ExoPlayerImpl.java
@@ -34,8 +34,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
private final Handler eventHandler;
private final ExoPlayerImplInternal internalPlayer;
private final CopyOnWriteArraySet listeners;
- private final boolean[] rendererHasMediaFlags;
- private final boolean[] rendererEnabledFlags;
+ private final TrackInfo[][] trackInfos;
+ private final int[] selectedTrackIndices;
private boolean playWhenReady;
private int playbackState;
@@ -58,18 +58,15 @@ import java.util.concurrent.CopyOnWriteArraySet;
this.playWhenReady = false;
this.playbackState = STATE_IDLE;
this.listeners = new CopyOnWriteArraySet<>();
- this.rendererHasMediaFlags = new boolean[rendererCount];
- this.rendererEnabledFlags = new boolean[rendererCount];
- for (int i = 0; i < rendererEnabledFlags.length; i++) {
- rendererEnabledFlags[i] = true;
- }
+ this.trackInfos = new TrackInfo[rendererCount][];
+ this.selectedTrackIndices = new int[rendererCount];
eventHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
ExoPlayerImpl.this.handleEvent(msg);
}
};
- internalPlayer = new ExoPlayerImplInternal(eventHandler, playWhenReady, rendererEnabledFlags,
+ internalPlayer = new ExoPlayerImplInternal(eventHandler, playWhenReady, selectedTrackIndices,
minBufferMs, minRebufferMs);
}
@@ -95,26 +92,49 @@ import java.util.concurrent.CopyOnWriteArraySet;
@Override
public void prepare(TrackRenderer... renderers) {
- Arrays.fill(rendererHasMediaFlags, false);
+ Arrays.fill(trackInfos, null);
internalPlayer.prepare(renderers);
}
@Override
+ // TODO: Deprecate in ExoPlayer.
public boolean getRendererHasMedia(int rendererIndex) {
- return rendererHasMediaFlags[rendererIndex];
+ return getRendererTrackCount(rendererIndex) > 0;
}
@Override
+ // TODO: Deprecate in ExoPlayer.
public void setRendererEnabled(int rendererIndex, boolean enabled) {
- if (rendererEnabledFlags[rendererIndex] != enabled) {
- rendererEnabledFlags[rendererIndex] = enabled;
- internalPlayer.setRendererEnabled(rendererIndex, enabled);
+ setRendererSelectedTrack(rendererIndex, enabled ? 0 : -1);
+ }
+
+ @Override
+ // TODO: Deprecate in ExoPlayer.
+ public boolean getRendererEnabled(int rendererIndex) {
+ return getRendererSelectedTrack(rendererIndex) == 0;
+ }
+
+ // TODO: Expose in ExoPlayer.
+ public int getRendererTrackCount(int rendererIndex) {
+ return trackInfos[rendererIndex] != null ? trackInfos[rendererIndex].length : 0;
+ }
+
+ // TODO: Expose in ExoPlayer.
+ public TrackInfo getRendererTrackInfo(int rendererIndex, int trackIndex) {
+ return trackInfos[rendererIndex][trackIndex];
+ }
+
+ // TODO: Expose in ExoPlayer.
+ public void setRendererSelectedTrack(int rendererIndex, int trackIndex) {
+ if (selectedTrackIndices[rendererIndex] != trackIndex) {
+ selectedTrackIndices[rendererIndex] = trackIndex;
+ internalPlayer.setRendererSelectedTrack(rendererIndex, trackIndex);
}
}
- @Override
- public boolean getRendererEnabled(int rendererIndex) {
- return rendererEnabledFlags[rendererIndex];
+ // TODO: Expose in ExoPlayer.
+ public int getRendererSelectedTrack(int rendererIndex) {
+ return selectedTrackIndices[rendererIndex];
}
@Override
@@ -192,9 +212,8 @@ import java.util.concurrent.CopyOnWriteArraySet;
/* package */ void handleEvent(Message msg) {
switch (msg.what) {
case ExoPlayerImplInternal.MSG_PREPARED: {
- boolean[] rendererHasMediaFlags = (boolean[]) msg.obj;
- System.arraycopy(rendererHasMediaFlags, 0, this.rendererHasMediaFlags, 0,
- rendererHasMediaFlags.length);
+ TrackInfo[][] trackInfos = (TrackInfo[][]) msg.obj;
+ System.arraycopy(trackInfos, 0, this.trackInfos, 0, trackInfos.length);
playbackState = msg.arg1;
for (Listener listener : listeners) {
listener.onPlayerStateChanged(playWhenReady, playbackState);
diff --git a/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java b/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java
index 8e7690e04c..b87a16b165 100644
--- a/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java
+++ b/library/src/main/java/com/google/android/exoplayer/ExoPlayerImplInternal.java
@@ -31,6 +31,7 @@ import android.util.Log;
import android.util.Pair;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -54,7 +55,7 @@ import java.util.List;
private static final int MSG_RELEASE = 5;
private static final int MSG_SEEK_TO = 6;
private static final int MSG_DO_SOME_WORK = 7;
- private static final int MSG_SET_RENDERER_ENABLED = 8;
+ private static final int MSG_SET_RENDERER_SELECTED_TRACK = 8;
private static final int MSG_CUSTOM = 9;
private static final int PREPARE_INTERVAL_MS = 10;
@@ -65,11 +66,12 @@ import java.util.List;
private final HandlerThread internalPlaybackThread;
private final Handler eventHandler;
private final StandaloneMediaClock standaloneMediaClock;
- private final boolean[] rendererEnabledFlags;
+ private final List enabledRenderers;
+ private final TrackInfo[][] trackInfos;
+ private final int[] selectedTrackIndices;
private final long minBufferUs;
private final long minRebufferUs;
- private final List enabledRenderers;
private TrackRenderer[] renderers;
private TrackRenderer rendererMediaClockSource;
private MediaClock rendererMediaClock;
@@ -87,22 +89,19 @@ import java.util.List;
private volatile long bufferedPositionUs;
public ExoPlayerImplInternal(Handler eventHandler, boolean playWhenReady,
- boolean[] rendererEnabledFlags, int minBufferMs, int minRebufferMs) {
+ int[] selectedTrackIndices, int minBufferMs, int minRebufferMs) {
this.eventHandler = eventHandler;
this.playWhenReady = playWhenReady;
- this.rendererEnabledFlags = new boolean[rendererEnabledFlags.length];
this.minBufferUs = minBufferMs * 1000L;
this.minRebufferUs = minRebufferMs * 1000L;
- for (int i = 0; i < rendererEnabledFlags.length; i++) {
- this.rendererEnabledFlags[i] = rendererEnabledFlags[i];
- }
-
+ this.selectedTrackIndices = Arrays.copyOf(selectedTrackIndices, selectedTrackIndices.length);
this.state = ExoPlayer.STATE_IDLE;
this.durationUs = TrackRenderer.UNKNOWN_TIME_US;
this.bufferedPositionUs = TrackRenderer.UNKNOWN_TIME_US;
standaloneMediaClock = new StandaloneMediaClock();
- enabledRenderers = new ArrayList<>(rendererEnabledFlags.length);
+ enabledRenderers = new ArrayList<>(selectedTrackIndices.length);
+ trackInfos = new TrackInfo[selectedTrackIndices.length][];
// Note: The documentation for Process.THREAD_PRIORITY_AUDIO that states "Applications can
// not normally change to this priority" is incorrect.
internalPlaybackThread = new PriorityHandlerThread(getClass().getSimpleName() + ":Handler",
@@ -146,8 +145,9 @@ import java.util.List;
handler.sendEmptyMessage(MSG_STOP);
}
- public void setRendererEnabled(int index, boolean enabled) {
- handler.obtainMessage(MSG_SET_RENDERER_ENABLED, index, enabled ? 1 : 0).sendToTarget();
+ public void setRendererSelectedTrack(int rendererIndex, int trackIndex) {
+ handler.obtainMessage(MSG_SET_RENDERER_SELECTED_TRACK, rendererIndex, trackIndex)
+ .sendToTarget();
}
public void sendMessage(ExoPlayerComponent target, int messageType, Object message) {
@@ -223,8 +223,8 @@ import java.util.List;
sendMessageInternal(msg.arg1, msg.obj);
return true;
}
- case MSG_SET_RENDERER_ENABLED: {
- setRendererEnabledInternal(msg.arg1, msg.arg2 != 0);
+ case MSG_SET_RENDERER_SELECTED_TRACK: {
+ setRendererSelectedTrackInternal(msg.arg1, msg.arg2);
return true;
}
default:
@@ -253,6 +253,7 @@ import java.util.List;
private void prepareInternal(TrackRenderer[] renderers) throws ExoPlaybackException {
resetInternal();
this.renderers = renderers;
+ Arrays.fill(trackInfos, null);
for (int i = 0; i < renderers.length; i++) {
MediaClock mediaClock = renderers[i].getMediaClock();
if (mediaClock != null) {
@@ -288,11 +289,15 @@ import java.util.List;
long durationUs = 0;
boolean allRenderersEnded = true;
boolean allRenderersReadyOrEnded = true;
- boolean[] rendererHasMediaFlags = new boolean[renderers.length];
for (int rendererIndex = 0; rendererIndex < renderers.length; rendererIndex++) {
TrackRenderer renderer = renderers[rendererIndex];
- rendererHasMediaFlags[rendererIndex] = renderer.getState() == TrackRenderer.STATE_PREPARED;
- if (rendererHasMediaFlags[rendererIndex]) {
+ int rendererTrackCount = renderer.getTrackCount();
+ TrackInfo[] rendererTrackInfos = new TrackInfo[rendererTrackCount];
+ for (int trackIndex = 0; trackIndex < rendererTrackCount; trackIndex++) {
+ rendererTrackInfos[trackIndex] = renderer.getTrackInfo(trackIndex);
+ }
+ trackInfos[rendererIndex] = rendererTrackInfos;
+ if (rendererTrackCount > 0) {
if (durationUs == TrackRenderer.UNKNOWN_TIME_US) {
// We've already encountered a track for which the duration is unknown, so the media
// duration is unknown regardless of the duration of this track.
@@ -306,8 +311,9 @@ import java.util.List;
durationUs = Math.max(durationUs, trackDurationUs);
}
}
- if (rendererEnabledFlags[rendererIndex]) {
- renderer.enable(positionUs, false);
+ int trackIndex = selectedTrackIndices[rendererIndex];
+ if (0 <= trackIndex && trackIndex < rendererTrackInfos.length) {
+ renderer.enable(trackIndex, positionUs, false);
enabledRenderers.add(renderer);
allRenderersEnded = allRenderersEnded && renderer.isEnded();
allRenderersReadyOrEnded = allRenderersReadyOrEnded && rendererReadyOrEnded(renderer);
@@ -325,8 +331,8 @@ import java.util.List;
}
// Fire an event indicating that the player has been prepared, passing the initial state and
- // renderer media flags.
- eventHandler.obtainMessage(MSG_PREPARED, state, 0, rendererHasMediaFlags).sendToTarget();
+ // renderer track information.
+ eventHandler.obtainMessage(MSG_PREPARED, state, 0, trackInfos).sendToTarget();
// Start the renderers if required, and schedule the first piece of work.
if (playWhenReady && state == ExoPlayer.STATE_READY) {
@@ -583,43 +589,54 @@ import java.util.List;
}
}
- private void setRendererEnabledInternal(int rendererIndex, boolean enabled)
+ private void setRendererSelectedTrackInternal(int rendererIndex, int trackIndex)
throws ExoPlaybackException {
- if (rendererEnabledFlags[rendererIndex] == enabled) {
+ if (selectedTrackIndices[rendererIndex] == trackIndex) {
return;
}
- rendererEnabledFlags[rendererIndex] = enabled;
+ selectedTrackIndices[rendererIndex] = trackIndex;
if (state == ExoPlayer.STATE_IDLE || state == ExoPlayer.STATE_PREPARING) {
return;
}
TrackRenderer renderer = renderers[rendererIndex];
int rendererState = renderer.getState();
- if (rendererState != TrackRenderer.STATE_PREPARED &&
- rendererState != TrackRenderer.STATE_ENABLED &&
- rendererState != TrackRenderer.STATE_STARTED) {
+ if (rendererState == TrackRenderer.STATE_UNPREPARED
+ || rendererState == TrackRenderer.STATE_RELEASED
+ || renderer.getTrackCount() == 0) {
return;
}
- if (enabled) {
- boolean playing = playWhenReady && state == ExoPlayer.STATE_READY;
- renderer.enable(positionUs, playing);
- enabledRenderers.add(renderer);
- if (playing) {
- renderer.start();
- }
- handler.sendEmptyMessage(MSG_DO_SOME_WORK);
- } else {
- if (renderer == rendererMediaClockSource) {
+ boolean isEnabled = rendererState == TrackRenderer.STATE_ENABLED
+ || rendererState == TrackRenderer.STATE_STARTED;
+ boolean shouldEnable = 0 <= trackIndex && trackIndex < trackInfos[rendererIndex].length;
+
+ if (isEnabled) {
+ // The renderer is currently enabled. We need to disable it, so that we can either re-enable
+ // it with the newly selected track (if shouldEnable is true) or because we want to leave it
+ // disabled (if shouldEnable is false).
+ if (!shouldEnable && renderer == rendererMediaClockSource) {
// We've been using rendererMediaClockSource to advance the current position, but it's being
- // disabled. Sync standaloneMediaClock so that it can take over timing responsibilities.
+ // disabled and won't be re-enabled. Sync standaloneMediaClock so that it can take over
+ // timing responsibilities.
standaloneMediaClock.setPositionUs(rendererMediaClock.getPositionUs());
}
ensureStopped(renderer);
enabledRenderers.remove(renderer);
renderer.disable();
}
+
+ if (shouldEnable) {
+ // Re-enable the renderer with the newly selected track.
+ boolean playing = playWhenReady && state == ExoPlayer.STATE_READY;
+ renderer.enable(trackIndex, positionUs, playing);
+ enabledRenderers.add(renderer);
+ if (playing) {
+ renderer.start();
+ }
+ handler.sendEmptyMessage(MSG_DO_SOME_WORK);
+ }
}
private void ensureStopped(TrackRenderer renderer) throws ExoPlaybackException {
diff --git a/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java
index ecb99ac2ab..edacf72230 100644
--- a/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java
+++ b/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java
@@ -162,8 +162,9 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem
}
@Override
- protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException {
- super.onEnabled(positionUs, joining);
+ protected void onEnabled(int track, long positionUs, boolean joining)
+ throws ExoPlaybackException {
+ super.onEnabled(track, positionUs, joining);
seekToInternal(positionUs);
}
diff --git a/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java
index 13676b1c5e..3136ba4b9c 100644
--- a/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java
+++ b/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java
@@ -241,8 +241,9 @@ public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer
}
@Override
- protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException {
- super.onEnabled(positionUs, joining);
+ protected void onEnabled(int track, long positionUs, boolean joining)
+ throws ExoPlaybackException {
+ super.onEnabled(track, positionUs, joining);
seekToInternal();
}
diff --git a/library/src/main/java/com/google/android/exoplayer/MediaCodecVideoTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/MediaCodecVideoTrackRenderer.java
index 1187fd4286..db88d2906e 100644
--- a/library/src/main/java/com/google/android/exoplayer/MediaCodecVideoTrackRenderer.java
+++ b/library/src/main/java/com/google/android/exoplayer/MediaCodecVideoTrackRenderer.java
@@ -261,8 +261,9 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer {
}
@Override
- protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException {
- super.onEnabled(positionUs, joining);
+ protected void onEnabled(int track, long positionUs, boolean joining)
+ throws ExoPlaybackException {
+ super.onEnabled(track, positionUs, joining);
renderedFirstFrame = false;
if (joining && allowedJoiningTimeUs > 0) {
joiningDeadlineUs = SystemClock.elapsedRealtime() * 1000L + allowedJoiningTimeUs;
diff --git a/library/src/main/java/com/google/android/exoplayer/SampleSourceTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/SampleSourceTrackRenderer.java
index c5c69a830a..4ba94c07a5 100644
--- a/library/src/main/java/com/google/android/exoplayer/SampleSourceTrackRenderer.java
+++ b/library/src/main/java/com/google/android/exoplayer/SampleSourceTrackRenderer.java
@@ -18,6 +18,7 @@ package com.google.android.exoplayer;
import com.google.android.exoplayer.SampleSource.SampleSourceReader;
import java.io.IOException;
+import java.util.Arrays;
/**
* Base class for {@link TrackRenderer} implementations that render samples obtained from a
@@ -27,7 +28,9 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer {
private final SampleSourceReader source;
- private int trackIndex;
+ private int enabledSourceTrackIndex;
+ private int[] handledSourceTrackIndices;
+ private TrackInfo[] trackInfos;
/**
* @param source The upstream source from which the renderer obtains samples.
@@ -37,21 +40,26 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer {
}
@Override
- protected int doPrepare(long positionUs) throws ExoPlaybackException {
+ protected boolean doPrepare(long positionUs) throws ExoPlaybackException {
boolean sourcePrepared = source.prepare(positionUs);
if (!sourcePrepared) {
- return TrackRenderer.STATE_UNPREPARED;
+ return false;
}
- int trackCount = source.getTrackCount();
- for (int i = 0; i < trackCount; i++) {
- TrackInfo trackInfo = source.getTrackInfo(i);
+ int handledTrackCount = 0;
+ int sourceTrackCount = source.getTrackCount();
+ int[] trackIndices = new int[sourceTrackCount];
+ TrackInfo[] trackInfos = new TrackInfo[sourceTrackCount];
+ for (int trackIndex = 0; trackIndex < sourceTrackCount; trackIndex++) {
+ TrackInfo trackInfo = source.getTrackInfo(trackIndex);
if (handlesTrack(trackInfo)) {
- trackIndex = i;
- onTrackSelected(trackInfo);
- return TrackRenderer.STATE_PREPARED;
+ trackIndices[handledTrackCount] = trackIndex;
+ trackInfos[handledTrackCount] = trackInfo;
+ handledTrackCount++;
}
}
- return TrackRenderer.STATE_IGNORE;
+ this.handledSourceTrackIndices = Arrays.copyOf(trackIndices, handledTrackCount);
+ this.trackInfos = Arrays.copyOf(trackInfos, handledTrackCount);
+ return true;
}
/**
@@ -72,8 +80,10 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer {
}
@Override
- protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException {
- source.enable(trackIndex, positionUs);
+ protected void onEnabled(int track, long positionUs, boolean joining)
+ throws ExoPlaybackException {
+ this.enabledSourceTrackIndex = handledSourceTrackIndices[track];
+ source.enable(enabledSourceTrackIndex, positionUs);
}
@Override
@@ -88,7 +98,7 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer {
@Override
protected long getDurationUs() {
- return source.getTrackInfo(trackIndex).durationUs;
+ return source.getTrackInfo(enabledSourceTrackIndex).durationUs;
}
@Override
@@ -102,7 +112,7 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer {
@Override
protected void onDisabled() throws ExoPlaybackException {
- source.disable(trackIndex);
+ source.disable(enabledSourceTrackIndex);
}
@Override
@@ -111,13 +121,23 @@ public abstract class SampleSourceTrackRenderer extends TrackRenderer {
}
protected final boolean continueBufferingSource(long positionUs) {
- return source.continueBuffering(trackIndex, positionUs);
+ return source.continueBuffering(enabledSourceTrackIndex, positionUs);
}
protected final int readSource(long positionUs, MediaFormatHolder formatHolder,
SampleHolder sampleHolder, boolean onlyReadDiscontinuity) {
- return source.readData(trackIndex, positionUs, formatHolder, sampleHolder,
+ return source.readData(enabledSourceTrackIndex, positionUs, formatHolder, sampleHolder,
onlyReadDiscontinuity);
}
+ @Override
+ protected final int getTrackCount() {
+ return trackInfos.length;
+ }
+
+ @Override
+ protected final TrackInfo getTrackInfo(int track) {
+ return trackInfos[track];
+ }
+
}
diff --git a/library/src/main/java/com/google/android/exoplayer/TrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/TrackRenderer.java
index 408ac49982..00945d466d 100644
--- a/library/src/main/java/com/google/android/exoplayer/TrackRenderer.java
+++ b/library/src/main/java/com/google/android/exoplayer/TrackRenderer.java
@@ -31,14 +31,24 @@ import com.google.android.exoplayer.util.Assertions;
*/
public abstract class TrackRenderer implements ExoPlayerComponent {
+ /**
+ * Represents an unknown time or duration. Equal to {@link C#UNKNOWN_TIME_US}.
+ */
+ public static final long UNKNOWN_TIME_US = C.UNKNOWN_TIME_US; // -1
+ /**
+ * Represents a time or duration that should match the duration of the longest track whose
+ * duration is known. Equal to {@link C#MATCH_LONGEST_US}.
+ */
+ public static final long MATCH_LONGEST_US = C.MATCH_LONGEST_US; // -2
+ /**
+ * Represents the time of the end of the track.
+ */
+ public static final long END_OF_TRACK_US = -3;
+
/**
* The renderer has been released and should not be used.
*/
- protected static final int STATE_RELEASED = -2;
- /**
- * The renderer should be ignored by the player.
- */
- protected static final int STATE_IGNORE = -1;
+ protected static final int STATE_RELEASED = -1;
/**
* The renderer has not yet been prepared.
*/
@@ -64,20 +74,6 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
*/
protected static final int STATE_STARTED = 3;
- /**
- * Represents an unknown time or duration. Equal to {@link C#UNKNOWN_TIME_US}.
- */
- public static final long UNKNOWN_TIME_US = C.UNKNOWN_TIME_US; // -1
- /**
- * Represents a time or duration that should match the duration of the longest track whose
- * duration is known. Equal to {@link C#MATCH_LONGEST_US}.
- */
- public static final long MATCH_LONGEST_US = C.MATCH_LONGEST_US; // -2
- /**
- * Represents the time of the end of the track.
- */
- public static final long END_OF_TRACK_US = -3;
-
private int state;
/**
@@ -111,41 +107,65 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
*/
/* package */ final int prepare(long positionUs) throws ExoPlaybackException {
Assertions.checkState(state == STATE_UNPREPARED);
- state = doPrepare(positionUs);
- Assertions.checkState(state == STATE_UNPREPARED ||
- state == STATE_PREPARED ||
- state == STATE_IGNORE);
+ state = doPrepare(positionUs) ? STATE_PREPARED : STATE_UNPREPARED;
return state;
}
/**
* Invoked to make progress when the renderer is in the {@link #STATE_UNPREPARED} state. This
- * method will be called repeatedly until a value other than {@link #STATE_UNPREPARED} is
- * returned.
+ * method will be called repeatedly until {@code true} is returned.
*
* This method should return quickly, and should not block if the renderer is currently unable to
* make any useful progress.
*
* @param positionUs The player's current playback position.
- * @return The new state of the renderer. One of {@link #STATE_UNPREPARED},
- * {@link #STATE_PREPARED} and {@link #STATE_IGNORE}.
+ * @return True if the renderer is now prepared. False otherwise.
* @throws ExoPlaybackException If an error occurs.
*/
- protected abstract int doPrepare(long positionUs) throws ExoPlaybackException;
+ protected abstract boolean doPrepare(long positionUs) throws ExoPlaybackException;
/**
- * Enable the renderer.
+ * Returns the number of tracks exposed by the renderer.
+ *
+ * This method may be called when the renderer is in the following states:
+ * {@link #STATE_PREPARED}, {@link #STATE_ENABLED}, {@link #STATE_STARTED}
*
+ * @return The number of tracks.
+ */
+ // TODO: This method should be abstract. This implementation is provided as an interim step only.
+ protected int getTrackCount() {
+ return 1;
+ }
+
+ /**
+ * Returns information about the specified track.
+ *
+ * This method may be called when the renderer is in the following states:
+ * {@link #STATE_PREPARED}, {@link #STATE_ENABLED}, {@link #STATE_STARTED}
+ *
+ * @param track The track index.
+ * @return Information about the specified track.
+ */
+ // TODO: This method should be abstract. This implementation is provided as an interim step only.
+ protected TrackInfo getTrackInfo(int track) {
+ return new TrackInfo("application/octet-stream", getDurationUs());
+ }
+
+ /**
+ * Enable the renderer for a specified track.
+ *
+ * @param track The track for which the renderer is being enabled.
* @param positionUs The player's current position.
* @param joining Whether this renderer is being enabled to join an ongoing playback. If true
* then {@link #start} must be called immediately after this method returns (unless a
* {@link ExoPlaybackException} is thrown).
* @throws ExoPlaybackException If an error occurs.
*/
- /* package */ final void enable(long positionUs, boolean joining) throws ExoPlaybackException {
+ /* package */ final void enable(int track, long positionUs, boolean joining)
+ throws ExoPlaybackException {
Assertions.checkState(state == STATE_PREPARED);
state = STATE_ENABLED;
- onEnabled(positionUs, joining);
+ onEnabled(track, positionUs, joining);
}
/**
@@ -153,13 +173,15 @@ public abstract class TrackRenderer implements ExoPlayerComponent {
*
* The default implementation is a no-op.
*
+ * @param track The track for which the renderer is being enabled.
* @param positionUs The player's current position.
* @param joining Whether this renderer is being enabled to join an ongoing playback. If true
* then {@link #onStarted} is guaranteed to be called immediately after this method returns
* (unless a {@link ExoPlaybackException} is thrown).
* @throws ExoPlaybackException If an error occurs.
*/
- protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException {
+ protected void onEnabled(int track, long positionUs, boolean joining)
+ throws ExoPlaybackException {
// Do nothing.
}
diff --git a/library/src/main/java/com/google/android/exoplayer/metadata/MetadataTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/metadata/MetadataTrackRenderer.java
index 18521ca0c9..18d87c31f0 100644
--- a/library/src/main/java/com/google/android/exoplayer/metadata/MetadataTrackRenderer.java
+++ b/library/src/main/java/com/google/android/exoplayer/metadata/MetadataTrackRenderer.java
@@ -93,8 +93,9 @@ public final class MetadataTrackRenderer extends SampleSourceTrackRenderer im
}
@Override
- protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException {
- super.onEnabled(positionUs, joining);
+ protected void onEnabled(int track, long positionUs, boolean joining)
+ throws ExoPlaybackException {
+ super.onEnabled(track, positionUs, joining);
seekToInternal();
}
diff --git a/library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java
index 0c7f6c34ea..4c96587c39 100644
--- a/library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java
+++ b/library/src/main/java/com/google/android/exoplayer/text/TextTrackRenderer.java
@@ -171,8 +171,9 @@ public final class TextTrackRenderer extends SampleSourceTrackRenderer implement
}
@Override
- protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException {
- super.onEnabled(positionUs, joining);
+ protected void onEnabled(int track, long positionUs, boolean joining)
+ throws ExoPlaybackException {
+ super.onEnabled(track, positionUs, joining);
parserThread = new HandlerThread("textParser");
parserThread.start();
parserHelper = new SubtitleParserHelper(parserThread.getLooper(), subtitleParsers[parserIndex]);
diff --git a/library/src/main/java/com/google/android/exoplayer/text/eia608/Eia608TrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/text/eia608/Eia608TrackRenderer.java
index df8dc44911..f906396490 100644
--- a/library/src/main/java/com/google/android/exoplayer/text/eia608/Eia608TrackRenderer.java
+++ b/library/src/main/java/com/google/android/exoplayer/text/eia608/Eia608TrackRenderer.java
@@ -94,8 +94,9 @@ public final class Eia608TrackRenderer extends SampleSourceTrackRenderer impleme
}
@Override
- protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException {
- super.onEnabled(positionUs, joining);
+ protected void onEnabled(int track, long positionUs, boolean joining)
+ throws ExoPlaybackException {
+ super.onEnabled(track, positionUs, joining);
seekToInternal();
}