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 2ab807f899..51b27cf7b1 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 @@ -21,7 +21,8 @@ import com.google.android.exoplayer.MediaClock; import com.google.android.exoplayer.MediaFormat; import com.google.android.exoplayer.MediaFormatHolder; import com.google.android.exoplayer.SampleSource; -import com.google.android.exoplayer.SampleSource.SampleSourceReader; +import com.google.android.exoplayer.SampleSourceTrackRenderer; +import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.audio.AudioTrack; import com.google.android.exoplayer.ext.opus.OpusDecoderWrapper.InputBuffer; @@ -30,7 +31,6 @@ import com.google.android.exoplayer.util.MimeTypes; import android.os.Handler; -import java.io.IOException; import java.nio.ByteBuffer; import java.util.List; @@ -39,7 +39,8 @@ import java.util.List; * * @author vigneshv@google.com (Vignesh Venkatasubramanian) */ -public class LibopusAudioTrackRenderer extends TrackRenderer implements MediaClock { +public final class LibopusAudioTrackRenderer extends SampleSourceTrackRenderer + implements MediaClock { /** * Interface definition for a callback to be notified of {@link LibopusAudioTrackRenderer} events. @@ -76,7 +77,6 @@ public class LibopusAudioTrackRenderer extends TrackRenderer implements MediaClo */ public static final int MSG_SET_VOLUME = 1; - private final SampleSourceReader source; private final Handler eventHandler; private final EventListener eventListener; private final MediaFormatHolder formatHolder; @@ -86,7 +86,6 @@ public class LibopusAudioTrackRenderer extends TrackRenderer implements MediaClo private InputBuffer inputBuffer; private OutputBuffer outputBuffer; - private int trackIndex; private long currentPositionUs; private boolean allowPositionDiscontinuity; private boolean inputStreamEnded; @@ -112,7 +111,7 @@ public class LibopusAudioTrackRenderer extends TrackRenderer implements MediaClo */ public LibopusAudioTrackRenderer(SampleSource source, Handler eventHandler, EventListener eventListener) { - this.source = source.register(); + super(source); this.eventHandler = eventHandler; this.eventListener = eventListener; this.audioSessionId = AudioTrack.SESSION_ID_NOT_SET; @@ -126,20 +125,15 @@ public class LibopusAudioTrackRenderer extends TrackRenderer implements MediaClo } @Override - protected int doPrepare(long positionUs) { - boolean sourcePrepared = source.prepare(positionUs); - if (!sourcePrepared) { - return TrackRenderer.STATE_UNPREPARED; - } - int trackCount = source.getTrackCount(); - for (int i = 0; i < trackCount; i++) { - if (source.getTrackInfo(i).mimeType.equalsIgnoreCase(MimeTypes.AUDIO_OPUS) - || source.getTrackInfo(i).mimeType.equalsIgnoreCase(MimeTypes.AUDIO_WEBM)) { - trackIndex = i; - return TrackRenderer.STATE_PREPARED; - } - } - return TrackRenderer.STATE_IGNORE; + protected boolean handlesTrack(TrackInfo trackInfo) { + return MimeTypes.AUDIO_OPUS.equalsIgnoreCase(trackInfo.mimeType) + || MimeTypes.AUDIO_WEBM.equalsIgnoreCase(trackInfo.mimeType); + } + + @Override + protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException { + super.onEnabled(positionUs, joining); + seekToInternal(positionUs); } @Override @@ -147,8 +141,8 @@ public class LibopusAudioTrackRenderer extends TrackRenderer implements MediaClo if (outputStreamEnded) { return; } - sourceIsReady = source.continueBuffering(trackIndex, positionUs); - checkForDiscontinuity(); + sourceIsReady = continueBufferingSource(positionUs); + checkForDiscontinuity(positionUs); // Try and read a format if we don't have one already. if (format == null && !readFormat(positionUs)) { @@ -189,7 +183,7 @@ public class LibopusAudioTrackRenderer extends TrackRenderer implements MediaClo // Rendering loop. try { renderBuffer(); - while (feedInputBuffer()) {} + while (feedInputBuffer(positionUs)) {} } catch (AudioTrack.InitializationException e) { notifyAudioTrackInitializationError(e); throw new ExoPlaybackException(e); @@ -249,7 +243,7 @@ public class LibopusAudioTrackRenderer extends TrackRenderer implements MediaClo } } - private boolean feedInputBuffer() throws OpusDecoderException { + private boolean feedInputBuffer(long positionUs) throws OpusDecoderException { if (inputStreamEnded) { return false; } @@ -261,8 +255,7 @@ public class LibopusAudioTrackRenderer extends TrackRenderer implements MediaClo } } - int result = source.readData(trackIndex, currentPositionUs, formatHolder, - inputBuffer.sampleHolder, false); + int result = readSource(positionUs, formatHolder, inputBuffer.sampleHolder, false); if (result == SampleSource.NOTHING_READ) { return false; } @@ -291,11 +284,11 @@ public class LibopusAudioTrackRenderer extends TrackRenderer implements MediaClo return true; } - private void checkForDiscontinuity() { + private void checkForDiscontinuity(long positionUs) { if (decoder == null) { return; } - int result = source.readData(trackIndex, currentPositionUs, formatHolder, null, true); + int result = readSource(positionUs, formatHolder, null, true); if (result == SampleSource.DISCONTINUITY_READ) { flushDecoder(); } @@ -319,11 +312,6 @@ public class LibopusAudioTrackRenderer extends TrackRenderer implements MediaClo return audioTrack.hasPendingData() || (format != null && sourceIsReady); } - @Override - protected long getDurationUs() { - return source.getTrackInfo(trackIndex).durationUs; - } - @Override public long getPositionUs() { long newCurrentPositionUs = audioTrack.getCurrentPositionUs(isEnded()); @@ -335,14 +323,9 @@ public class LibopusAudioTrackRenderer extends TrackRenderer implements MediaClo return currentPositionUs; } - @Override - protected long getBufferedPositionUs() { - return source.getBufferedPositionUs(); - } - @Override protected void seekTo(long positionUs) throws ExoPlaybackException { - source.seekToUs(positionUs); + super.seekTo(positionUs); seekToInternal(positionUs); } @@ -350,18 +333,11 @@ public class LibopusAudioTrackRenderer extends TrackRenderer implements MediaClo audioTrack.reset(); currentPositionUs = positionUs; allowPositionDiscontinuity = true; - source.seekToUs(positionUs); inputStreamEnded = false; outputStreamEnded = false; sourceIsReady = false; } - @Override - protected void onEnabled(long positionUs, boolean joining) { - source.enable(trackIndex, positionUs); - seekToInternal(positionUs); - } - @Override protected void onStarted() { audioTrack.play(); @@ -373,38 +349,24 @@ public class LibopusAudioTrackRenderer extends TrackRenderer implements MediaClo } @Override - protected void onReleased() { - source.release(); - } - - @Override - protected void onDisabled() { - if (decoder != null) { - decoder.release(); - decoder = null; - } + protected void onDisabled() throws ExoPlaybackException { + inputBuffer = null; + outputBuffer = null; + format = null; audioSessionId = AudioTrack.SESSION_ID_NOT_SET; try { + if (decoder != null) { + decoder.release(); + decoder = null; + } audioTrack.release(); } finally { - inputBuffer = null; - outputBuffer = null; - format = null; - source.disable(trackIndex); - } - } - - @Override - protected void maybeThrowError() throws ExoPlaybackException { - try { - source.maybeThrowError(); - } catch (IOException e) { - throw new ExoPlaybackException(e); + super.onDisabled(); } } private boolean readFormat(long positionUs) { - int result = source.readData(trackIndex, positionUs, formatHolder, null, false); + int result = readSource(positionUs, formatHolder, null, false); if (result == SampleSource.FORMAT_READ) { format = formatHolder.format; audioTrack.reconfigure(format.getFrameworkMediaFormatV16()); 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 4c8745d006..71e59bafd7 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 @@ -20,7 +20,8 @@ import com.google.android.exoplayer.ExoPlayer; import com.google.android.exoplayer.MediaFormat; import com.google.android.exoplayer.MediaFormatHolder; import com.google.android.exoplayer.SampleSource; -import com.google.android.exoplayer.SampleSource.SampleSourceReader; +import com.google.android.exoplayer.SampleSourceTrackRenderer; +import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.ext.vp9.VpxDecoderWrapper.InputBuffer; import com.google.android.exoplayer.ext.vp9.VpxDecoderWrapper.OutputBuffer; @@ -32,12 +33,10 @@ import android.os.Handler; import android.os.SystemClock; import android.view.Surface; -import java.io.IOException; - /** * Decodes and renders video using the native VP9 decoder. */ -public class LibvpxVideoTrackRenderer extends TrackRenderer { +public final class LibvpxVideoTrackRenderer extends SampleSourceTrackRenderer { /** * Interface definition for a callback to be notified of {@link LibvpxVideoTrackRenderer} events. @@ -91,7 +90,6 @@ public class LibvpxVideoTrackRenderer extends TrackRenderer { public static final int MSG_SET_SURFACE = 1; public static final int MSG_SET_VPX_SURFACE_VIEW = 2; - private final SampleSourceReader source; private final boolean scaleToFit; private final Handler eventHandler; private final EventListener eventListener; @@ -110,7 +108,6 @@ public class LibvpxVideoTrackRenderer extends TrackRenderer { private VpxVideoSurfaceView vpxVideoSurfaceView; private boolean outputRgb; - private int trackIndex; private boolean inputStreamEnded; private boolean outputStreamEnded; private boolean sourceIsReady; @@ -141,7 +138,7 @@ public class LibvpxVideoTrackRenderer extends TrackRenderer { */ public LibvpxVideoTrackRenderer(SampleSource source, boolean scaleToFit, Handler eventHandler, EventListener eventListener, int maxDroppedFrameCountToNotify) { - this.source = source.register(); + super(source); this.scaleToFit = scaleToFit; this.eventHandler = eventHandler; this.eventListener = eventListener; @@ -152,20 +149,9 @@ public class LibvpxVideoTrackRenderer extends TrackRenderer { } @Override - protected int doPrepare(long positionUs) throws ExoPlaybackException { - boolean sourcePrepared = source.prepare(positionUs); - if (!sourcePrepared) { - return TrackRenderer.STATE_UNPREPARED; - } - int trackCount = source.getTrackCount(); - for (int i = 0; i < trackCount; i++) { - if (source.getTrackInfo(i).mimeType.equalsIgnoreCase(MimeTypes.VIDEO_VP9) - || source.getTrackInfo(i).mimeType.equalsIgnoreCase(MimeTypes.VIDEO_WEBM)) { - trackIndex = i; - return TrackRenderer.STATE_PREPARED; - } - } - return TrackRenderer.STATE_IGNORE; + protected boolean handlesTrack(TrackInfo trackInfo) { + return MimeTypes.VIDEO_VP9.equalsIgnoreCase(trackInfo.mimeType) + || MimeTypes.VIDEO_WEBM.equalsIgnoreCase(trackInfo.mimeType); } @Override @@ -173,7 +159,7 @@ public class LibvpxVideoTrackRenderer extends TrackRenderer { if (outputStreamEnded) { return; } - sourceIsReady = source.continueBuffering(trackIndex, positionUs); + sourceIsReady = continueBufferingSource(positionUs); checkForDiscontinuity(positionUs); // Try and read a format if we don't have one already. @@ -302,7 +288,7 @@ public class LibvpxVideoTrackRenderer extends TrackRenderer { } } - int result = source.readData(trackIndex, positionUs, formatHolder, inputBuffer.sampleHolder, + int result = readSource(positionUs, formatHolder, inputBuffer.sampleHolder, false); if (result == SampleSource.NOTHING_READ) { return false; @@ -334,7 +320,7 @@ public class LibvpxVideoTrackRenderer extends TrackRenderer { if (decoder == null) { return; } - int result = source.readData(trackIndex, positionUs, formatHolder, null, true); + int result = readSource(positionUs, formatHolder, null, true); if (result == SampleSource.DISCONTINUITY_READ) { flushDecoder(); } @@ -356,25 +342,15 @@ public class LibvpxVideoTrackRenderer extends TrackRenderer { return format != null && sourceIsReady; } - @Override - protected long getDurationUs() { - return source.getTrackInfo(trackIndex).durationUs; - } - - @Override - protected long getBufferedPositionUs() { - return source.getBufferedPositionUs(); - } - @Override protected void seekTo(long positionUs) throws ExoPlaybackException { - source.seekToUs(positionUs); + super.seekTo(positionUs); seekToInternal(); } @Override - protected void onEnabled(long positionUs, boolean joining) { - source.enable(trackIndex, positionUs); + protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException { + super.onEnabled(positionUs, joining); seekToInternal(); } @@ -397,33 +373,22 @@ public class LibvpxVideoTrackRenderer extends TrackRenderer { } @Override - protected void onReleased() { - source.release(); - } - - @Override - protected void onDisabled() { - if (decoder != null) { - decoder.release(); - decoder = null; - } + protected void onDisabled() throws ExoPlaybackException { inputBuffer = null; outputBuffer = null; format = null; - source.disable(trackIndex); - } - - @Override - protected void maybeThrowError() throws ExoPlaybackException { try { - source.maybeThrowError(); - } catch (IOException e) { - throw new ExoPlaybackException(e); + if (decoder != null) { + decoder.release(); + decoder = null; + } + } finally { + super.onDisabled(); } } private boolean readFormat(long positionUs) { - int result = source.readData(trackIndex, positionUs, formatHolder, null, false); + int result = readSource(positionUs, formatHolder, null, false); if (result == SampleSource.FORMAT_READ) { format = formatHolder.format; return true; 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 510313c787..ecb99ac2ab 100644 --- a/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/MediaCodecAudioTrackRenderer.java @@ -157,12 +157,12 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem } @Override - protected boolean handlesMimeType(String mimeType) { - return MimeTypes.isAudio(mimeType) && super.handlesMimeType(mimeType); + protected boolean handlesTrack(TrackInfo trackInfo) { + return MimeTypes.isAudio(trackInfo.mimeType); } @Override - protected void onEnabled(long positionUs, boolean joining) { + protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException { super.onEnabled(positionUs, joining); seekToInternal(positionUs); } @@ -231,7 +231,7 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem } @Override - protected void onDisabled() { + protected void onDisabled() throws ExoPlaybackException { audioSessionId = AudioTrack.SESSION_ID_NOT_SET; try { audioTrack.release(); 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 e9d21df57b..13676b1c5e 100644 --- a/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/MediaCodecTrackRenderer.java @@ -16,7 +16,6 @@ package com.google.android.exoplayer; import com.google.android.exoplayer.MediaCodecUtil.DecoderQueryException; -import com.google.android.exoplayer.SampleSource.SampleSourceReader; import com.google.android.exoplayer.drm.DrmInitData; import com.google.android.exoplayer.drm.DrmSessionManager; import com.google.android.exoplayer.util.Assertions; @@ -31,7 +30,6 @@ import android.media.MediaCrypto; import android.os.Handler; import android.os.SystemClock; -import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; @@ -40,7 +38,7 @@ import java.util.List; * An abstract {@link TrackRenderer} that uses {@link MediaCodec} to decode samples for rendering. */ @TargetApi(16) -public abstract class MediaCodecTrackRenderer extends TrackRenderer { +public abstract class MediaCodecTrackRenderer extends SampleSourceTrackRenderer { /** * Interface definition for a callback to be notified of {@link MediaCodecTrackRenderer} events. @@ -183,7 +181,6 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { private final DrmSessionManager drmSessionManager; private final boolean playClearSamplesWithoutKeys; - private final SampleSourceReader source; private final SampleHolder sampleHolder; private final MediaFormatHolder formatHolder; private final List decodeOnlyPresentationTimestamps; @@ -207,7 +204,6 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { private int codecReinitializationState; private boolean codecHasQueuedBuffers; - private int trackIndex; private int sourceState; private boolean inputStreamEnded; private boolean outputStreamEnded; @@ -229,8 +225,8 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { */ public MediaCodecTrackRenderer(SampleSource source, DrmSessionManager drmSessionManager, boolean playClearSamplesWithoutKeys, Handler eventHandler, EventListener eventListener) { + super(source); Assertions.checkState(Util.SDK_INT >= 16); - this.source = source.register(); this.drmSessionManager = drmSessionManager; this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; this.eventHandler = eventHandler; @@ -245,39 +241,8 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { } @Override - protected int doPrepare(long positionUs) { - boolean sourcePrepared = source.prepare(positionUs); - if (!sourcePrepared) { - return TrackRenderer.STATE_UNPREPARED; - } - int trackCount = source.getTrackCount(); - for (int i = 0; i < trackCount; i++) { - // TODO: Right now this is getting the mime types of the container format - // (e.g. audio/mp4 and video/mp4 for fragmented mp4). It needs to be getting the mime types - // of the actual samples (e.g. audio/mp4a-latm and video/avc). - if (handlesMimeType(source.getTrackInfo(i).mimeType)) { - trackIndex = i; - return TrackRenderer.STATE_PREPARED; - } - } - return TrackRenderer.STATE_IGNORE; - } - - /** - * Determines whether a mime type is handled by the renderer. - * - * @param mimeType The mime type to test. - * @return True if the renderer can handle the mime type. False otherwise. - */ - protected boolean handlesMimeType(String mimeType) { - return true; - // TODO: Uncomment once the TODO above is fixed. - // DecoderInfoUtil.getDecoder(mimeType) != null; - } - - @Override - protected void onEnabled(long positionUs, boolean joining) { - source.enable(trackIndex, positionUs); + protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException { + super.onEnabled(positionUs, joining); seekToInternal(); } @@ -400,7 +365,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { } @Override - protected void onDisabled() { + protected void onDisabled() throws ExoPlaybackException { format = null; drmInitData = null; try { @@ -412,7 +377,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { openedDrmSession = false; } } finally { - source.disable(trackIndex); + super.onDisabled(); } } } @@ -445,24 +410,9 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { } } - @Override - protected void onReleased() { - source.release(); - } - - @Override - protected long getDurationUs() { - return source.getTrackInfo(trackIndex).durationUs; - } - - @Override - protected long getBufferedPositionUs() { - return source.getBufferedPositionUs(); - } - @Override protected void seekTo(long positionUs) throws ExoPlaybackException { - source.seekToUs(positionUs); + super.seekTo(positionUs); seekToInternal(); } @@ -484,7 +434,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { @Override protected void doSomeWork(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException { - sourceState = source.continueBuffering(trackIndex, positionUs) + sourceState = continueBufferingSource(positionUs) ? (sourceState == SOURCE_STATE_NOT_READY ? SOURCE_STATE_READY : sourceState) : SOURCE_STATE_NOT_READY; checkForDiscontinuity(positionUs); @@ -506,7 +456,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { } private void readFormat(long positionUs) throws ExoPlaybackException { - int result = source.readData(trackIndex, positionUs, formatHolder, sampleHolder, false); + int result = readSource(positionUs, formatHolder, sampleHolder, false); if (result == SampleSource.FORMAT_READ) { onInputFormatChanged(formatHolder); } @@ -516,7 +466,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { if (codec == null) { return; } - int result = source.readData(trackIndex, positionUs, formatHolder, sampleHolder, true); + int result = readSource(positionUs, formatHolder, sampleHolder, true); if (result == SampleSource.DISCONTINUITY_READ) { flushCodec(); } @@ -597,7 +547,7 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { } codecReconfigurationState = RECONFIGURATION_STATE_QUEUE_PENDING; } - result = source.readData(trackIndex, positionUs, formatHolder, sampleHolder, false); + result = readSource(positionUs, formatHolder, sampleHolder, false); if (firstFeed && sourceState == SOURCE_STATE_READY && result == SampleSource.NOTHING_READ) { sourceState = SOURCE_STATE_READY_READ_MAY_FAIL; } @@ -774,15 +724,6 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { return false; } - @Override - protected void maybeThrowError() throws ExoPlaybackException { - try { - source.maybeThrowError(); - } catch (IOException e) { - throw new ExoPlaybackException(e); - } - } - @Override protected boolean isEnded() { return outputStreamEnded; @@ -950,11 +891,8 @@ public abstract class MediaCodecTrackRenderer extends TrackRenderer { * incorrectly on the host device. False otherwise. */ private static boolean codecNeedsEndOfStreamWorkaround(String name) { - return Util.SDK_INT <= 17 - && "OMX.rk.video_decoder.avc".equals(name) - && ("ht7s3".equals(Util.DEVICE) // Tesco HUDL - || "rk30sdk".equals(Util.DEVICE) // Rockchip rk30 - || "rk31sdk".equals(Util.DEVICE)); // Rockchip rk31 + return Util.SDK_INT <= 17 && "ht7s3".equals(Util.DEVICE) // Tesco HUDL + && "OMX.rk.video_decoder.avc".equals(name); } } 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 5970c7df63..1187fd4286 100644 --- a/library/src/main/java/com/google/android/exoplayer/MediaCodecVideoTrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/MediaCodecVideoTrackRenderer.java @@ -256,12 +256,12 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer { } @Override - protected boolean handlesMimeType(String mimeType) { - return MimeTypes.isVideo(mimeType) && super.handlesMimeType(mimeType); + protected boolean handlesTrack(TrackInfo trackInfo) { + return MimeTypes.isVideo(trackInfo.mimeType); } @Override - protected void onEnabled(long positionUs, boolean joining) { + protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException { super.onEnabled(positionUs, joining); renderedFirstFrame = false; if (joining && allowedJoiningTimeUs > 0) { @@ -314,7 +314,7 @@ public class MediaCodecVideoTrackRenderer extends MediaCodecTrackRenderer { } @Override - public void onDisabled() { + protected void onDisabled() throws ExoPlaybackException { currentWidth = -1; currentHeight = -1; currentPixelWidthHeightRatio = -1; diff --git a/library/src/main/java/com/google/android/exoplayer/SampleSourceTrackRenderer.java b/library/src/main/java/com/google/android/exoplayer/SampleSourceTrackRenderer.java new file mode 100644 index 0000000000..c5c69a830a --- /dev/null +++ b/library/src/main/java/com/google/android/exoplayer/SampleSourceTrackRenderer.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer; + +import com.google.android.exoplayer.SampleSource.SampleSourceReader; + +import java.io.IOException; + +/** + * Base class for {@link TrackRenderer} implementations that render samples obtained from a + * {@link SampleSource}. + */ +public abstract class SampleSourceTrackRenderer extends TrackRenderer { + + private final SampleSourceReader source; + + private int trackIndex; + + /** + * @param source The upstream source from which the renderer obtains samples. + */ + public SampleSourceTrackRenderer(SampleSource source) { + this.source = source.register(); + } + + @Override + protected int doPrepare(long positionUs) throws ExoPlaybackException { + boolean sourcePrepared = source.prepare(positionUs); + if (!sourcePrepared) { + return TrackRenderer.STATE_UNPREPARED; + } + int trackCount = source.getTrackCount(); + for (int i = 0; i < trackCount; i++) { + TrackInfo trackInfo = source.getTrackInfo(i); + if (handlesTrack(trackInfo)) { + trackIndex = i; + onTrackSelected(trackInfo); + return TrackRenderer.STATE_PREPARED; + } + } + return TrackRenderer.STATE_IGNORE; + } + + /** + * Returns whether this renderer is capable of handling the provided track. + * + * @param trackInfo The track. + * @return True if the renderer can handle the track, false otherwise. + */ + protected abstract boolean handlesTrack(TrackInfo trackInfo); + + /** + * Invoked when a track is selected. + * + * @param trackInfo The selected track. + */ + protected void onTrackSelected(TrackInfo trackInfo) { + // Do nothing. + } + + @Override + protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException { + source.enable(trackIndex, positionUs); + } + + @Override + protected void seekTo(long positionUs) throws ExoPlaybackException { + source.seekToUs(positionUs); + } + + @Override + protected long getBufferedPositionUs() { + return source.getBufferedPositionUs(); + } + + @Override + protected long getDurationUs() { + return source.getTrackInfo(trackIndex).durationUs; + } + + @Override + protected void maybeThrowError() throws ExoPlaybackException { + try { + source.maybeThrowError(); + } catch (IOException e) { + throw new ExoPlaybackException(e); + } + } + + @Override + protected void onDisabled() throws ExoPlaybackException { + source.disable(trackIndex); + } + + @Override + protected void onReleased() throws ExoPlaybackException { + source.release(); + } + + protected final boolean continueBufferingSource(long positionUs) { + return source.continueBuffering(trackIndex, positionUs); + } + + protected final int readSource(long positionUs, MediaFormatHolder formatHolder, + SampleHolder sampleHolder, boolean onlyReadDiscontinuity) { + return source.readData(trackIndex, positionUs, formatHolder, sampleHolder, + onlyReadDiscontinuity); + } + +} 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 ffc02caf4e..408ac49982 100644 --- a/library/src/main/java/com/google/android/exoplayer/TrackRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer/TrackRenderer.java @@ -110,11 +110,11 @@ public abstract class TrackRenderer implements ExoPlayerComponent { * @throws ExoPlaybackException If an error occurs. */ /* package */ final int prepare(long positionUs) throws ExoPlaybackException { - Assertions.checkState(state == TrackRenderer.STATE_UNPREPARED); + Assertions.checkState(state == STATE_UNPREPARED); state = doPrepare(positionUs); - Assertions.checkState(state == TrackRenderer.STATE_UNPREPARED || - state == TrackRenderer.STATE_PREPARED || - state == TrackRenderer.STATE_IGNORE); + Assertions.checkState(state == STATE_UNPREPARED || + state == STATE_PREPARED || + state == STATE_IGNORE); return state; } @@ -143,8 +143,8 @@ public abstract class TrackRenderer implements ExoPlayerComponent { * @throws ExoPlaybackException If an error occurs. */ /* package */ final void enable(long positionUs, boolean joining) throws ExoPlaybackException { - Assertions.checkState(state == TrackRenderer.STATE_PREPARED); - state = TrackRenderer.STATE_ENABLED; + Assertions.checkState(state == STATE_PREPARED); + state = STATE_ENABLED; onEnabled(positionUs, joining); } @@ -170,8 +170,8 @@ public abstract class TrackRenderer implements ExoPlayerComponent { * @throws ExoPlaybackException If an error occurs. */ /* package */ final void start() throws ExoPlaybackException { - Assertions.checkState(state == TrackRenderer.STATE_ENABLED); - state = TrackRenderer.STATE_STARTED; + Assertions.checkState(state == STATE_ENABLED); + state = STATE_STARTED; onStarted(); } @@ -192,8 +192,8 @@ public abstract class TrackRenderer implements ExoPlayerComponent { * @throws ExoPlaybackException If an error occurs. */ /* package */ final void stop() throws ExoPlaybackException { - Assertions.checkState(state == TrackRenderer.STATE_STARTED); - state = TrackRenderer.STATE_ENABLED; + Assertions.checkState(state == STATE_STARTED); + state = STATE_ENABLED; onStopped(); } @@ -214,8 +214,8 @@ public abstract class TrackRenderer implements ExoPlayerComponent { * @throws ExoPlaybackException If an error occurs. */ /* package */ final void disable() throws ExoPlaybackException { - Assertions.checkState(state == TrackRenderer.STATE_ENABLED); - state = TrackRenderer.STATE_PREPARED; + Assertions.checkState(state == STATE_ENABLED); + state = STATE_PREPARED; onDisabled(); } @@ -236,10 +236,10 @@ public abstract class TrackRenderer implements ExoPlayerComponent { * @throws ExoPlaybackException If an error occurs. */ /* package */ final void release() throws ExoPlaybackException { - Assertions.checkState(state != TrackRenderer.STATE_ENABLED - && state != TrackRenderer.STATE_STARTED - && state != TrackRenderer.STATE_RELEASED); - state = TrackRenderer.STATE_RELEASED; + Assertions.checkState(state != STATE_ENABLED + && state != STATE_STARTED + && state != STATE_RELEASED); + state = STATE_RELEASED; onReleased(); } diff --git a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java index 1e8cdaf9a6..4afd5ca565 100644 --- a/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/chunk/ChunkSampleSource.java @@ -58,7 +58,7 @@ public class ChunkSampleSource implements SampleSource, SampleSourceReader, Load private static final int STATE_PREPARED = 2; private static final int STATE_ENABLED = 3; - private static final int NO_RESET_PENDING = -1; + private static final long NO_RESET_PENDING = Long.MIN_VALUE; private final int eventSourceId; private final LoadControl loadControl; diff --git a/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java b/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java index 639c992b65..f50d9475b1 100644 --- a/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/extractor/ExtractorSampleSource.java @@ -93,7 +93,7 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourceRe public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT_LIVE = 6; private static final int MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA = -1; - private static final int NO_RESET_PENDING = -1; + private static final long NO_RESET_PENDING = Long.MIN_VALUE; /** * Default extractor classes in priority order. They are referred to indirectly so that it is @@ -326,10 +326,14 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourceRe enabledTrackCount++; trackEnabledStates[track] = true; pendingMediaFormat[track] = true; - if (enabledTrackCount == 1) { - seekToUs(positionUs); - } pendingDiscontinuities[track] = false; + if (enabledTrackCount == 1) { + // Treat all enables in non-seekable media as being from t=0. + positionUs = !seekMap.isSeekable() ? 0 : positionUs; + downstreamPositionUs = positionUs; + lastSeekPositionUs = positionUs; + restartFrom(positionUs); + } } @Override @@ -431,10 +435,8 @@ public final class ExtractorSampleSource implements SampleSource, SampleSourceRe public void seekToUs(long positionUs) { Assertions.checkState(prepared); Assertions.checkState(enabledTrackCount > 0); - if (!seekMap.isSeekable()) { - // Treat all seeks into non-seekable media as seeks to the start. - positionUs = 0; - } + // Treat all seeks into non-seekable media as being to t=0. + positionUs = !seekMap.isSeekable() ? 0 : positionUs; long currentPositionUs = isPendingReset() ? pendingResetPositionUs : downstreamPositionUs; downstreamPositionUs = positionUs; diff --git a/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java b/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java index 30eb9bb0a1..bf7f3981d5 100644 --- a/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java +++ b/library/src/main/java/com/google/android/exoplayer/hls/HlsSampleSource.java @@ -52,7 +52,7 @@ public final class HlsSampleSource implements SampleSource, SampleSourceReader, */ public static final int DEFAULT_MIN_LOADABLE_RETRY_COUNT = 3; - private static final int NO_RESET_PENDING = -1; + private static final long NO_RESET_PENDING = Long.MIN_VALUE; private final HlsChunkSource chunkSource; private final LinkedList extractors; @@ -182,15 +182,17 @@ public final class HlsSampleSource implements SampleSource, SampleSourceReader, enabledTrackCount++; trackEnabledStates[track] = true; downstreamMediaFormats[track] = null; + pendingDiscontinuities[track] = false; downstreamFormat = null; if (!loadControlRegistered) { loadControl.register(this, bufferSizeContribution); loadControlRegistered = true; } if (enabledTrackCount == 1) { - seekToUs(positionUs); + downstreamPositionUs = positionUs; + lastSeekPositionUs = positionUs; + restartFrom(positionUs); } - pendingDiscontinuities[track] = false; } @Override 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 767214482f..18521ca0c9 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 @@ -19,7 +19,8 @@ import com.google.android.exoplayer.ExoPlaybackException; import com.google.android.exoplayer.MediaFormatHolder; import com.google.android.exoplayer.SampleHolder; import com.google.android.exoplayer.SampleSource; -import com.google.android.exoplayer.SampleSource.SampleSourceReader; +import com.google.android.exoplayer.SampleSourceTrackRenderer; +import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.util.Assertions; @@ -35,7 +36,7 @@ import java.io.IOException; * * @param The type of the metadata. */ -public final class MetadataTrackRenderer extends TrackRenderer implements Callback { +public final class MetadataTrackRenderer extends SampleSourceTrackRenderer implements Callback { /** * An interface for components that process metadata. @@ -55,16 +56,13 @@ public final class MetadataTrackRenderer extends TrackRenderer implements Cal private static final int MSG_INVOKE_RENDERER = 0; - private final SampleSourceReader source; private final MetadataParser metadataParser; private final MetadataRenderer metadataRenderer; private final Handler metadataHandler; private final MediaFormatHolder formatHolder; private final SampleHolder sampleHolder; - private int trackIndex; private boolean inputStreamEnded; - private long pendingMetadataTimestamp; private T pendingMetadata; @@ -80,7 +78,7 @@ public final class MetadataTrackRenderer extends TrackRenderer implements Cal */ public MetadataTrackRenderer(SampleSource source, MetadataParser metadataParser, MetadataRenderer metadataRenderer, Looper metadataRendererLooper) { - this.source = source.register(); + super(source); this.metadataParser = Assertions.checkNotNull(metadataParser); this.metadataRenderer = Assertions.checkNotNull(metadataRenderer); this.metadataHandler = metadataRendererLooper == null ? null @@ -90,30 +88,19 @@ public final class MetadataTrackRenderer extends TrackRenderer implements Cal } @Override - protected int doPrepare(long positionUs) { - boolean sourcePrepared = source.prepare(positionUs); - if (!sourcePrepared) { - return TrackRenderer.STATE_UNPREPARED; - } - int trackCount = source.getTrackCount(); - for (int i = 0; i < trackCount; i++) { - if (metadataParser.canParse(source.getTrackInfo(i).mimeType)) { - trackIndex = i; - return TrackRenderer.STATE_PREPARED; - } - } - return TrackRenderer.STATE_IGNORE; + protected boolean handlesTrack(TrackInfo trackInfo) { + return metadataParser.canParse(trackInfo.mimeType); } @Override - protected void onEnabled(long positionUs, boolean joining) { - source.enable(trackIndex, positionUs); + protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException { + super.onEnabled(positionUs, joining); seekToInternal(); } @Override protected void seekTo(long positionUs) throws ExoPlaybackException { - source.seekToUs(positionUs); + super.seekTo(positionUs); seekToInternal(); } @@ -123,23 +110,21 @@ public final class MetadataTrackRenderer extends TrackRenderer implements Cal } @Override - protected void doSomeWork(long positionUs, long elapsedRealtimeUs) - throws ExoPlaybackException { - source.continueBuffering(trackIndex, positionUs); - + protected void doSomeWork(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException { + continueBufferingSource(positionUs); if (!inputStreamEnded && pendingMetadata == null) { - int result = source.readData(trackIndex, positionUs, formatHolder, sampleHolder, false); - if (result == SampleSource.SAMPLE_READ) { - pendingMetadataTimestamp = sampleHolder.timeUs; - try { - pendingMetadata = metadataParser.parse(sampleHolder.data.array(), sampleHolder.size); - } catch (IOException e) { - throw new ExoPlaybackException(e); - } - sampleHolder.data.clear(); - } else if (result == SampleSource.END_OF_STREAM) { - inputStreamEnded = true; + int result = readSource(positionUs, formatHolder, sampleHolder, false); + if (result == SampleSource.SAMPLE_READ) { + pendingMetadataTimestamp = sampleHolder.timeUs; + try { + pendingMetadata = metadataParser.parse(sampleHolder.data.array(), sampleHolder.size); + } catch (IOException e) { + throw new ExoPlaybackException(e); } + sampleHolder.data.clear(); + } else if (result == SampleSource.END_OF_STREAM) { + inputStreamEnded = true; + } } if (pendingMetadata != null && pendingMetadataTimestamp <= positionUs) { @@ -149,23 +134,9 @@ public final class MetadataTrackRenderer extends TrackRenderer implements Cal } @Override - protected void maybeThrowError() throws ExoPlaybackException { - try { - source.maybeThrowError(); - } catch (IOException e) { - throw new ExoPlaybackException(e); - } - } - - @Override - protected void onDisabled() { + protected void onDisabled() throws ExoPlaybackException { pendingMetadata = null; - source.disable(trackIndex); - } - - @Override - protected long getDurationUs() { - return source.getTrackInfo(trackIndex).durationUs; + super.onDisabled(); } @Override 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 dd9b7bd28f..0c7f6c34ea 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 @@ -19,7 +19,8 @@ import com.google.android.exoplayer.ExoPlaybackException; import com.google.android.exoplayer.MediaFormatHolder; import com.google.android.exoplayer.SampleHolder; import com.google.android.exoplayer.SampleSource; -import com.google.android.exoplayer.SampleSource.SampleSourceReader; +import com.google.android.exoplayer.SampleSourceTrackRenderer; +import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.util.Assertions; @@ -58,7 +59,7 @@ import java.util.List; * {@link SubtitleParser#canParse(String)} will be used. */ @TargetApi(16) -public final class TextTrackRenderer extends TrackRenderer implements Callback { +public final class TextTrackRenderer extends SampleSourceTrackRenderer implements Callback { private static final int MSG_UPDATE_OVERLAY = 0; @@ -104,15 +105,11 @@ public final class TextTrackRenderer extends TrackRenderer implements Callback { private final Handler textRendererHandler; private final TextRenderer textRenderer; - private final SampleSourceReader source; private final MediaFormatHolder formatHolder; private final SubtitleParser[] subtitleParsers; private int parserIndex; - private int trackIndex; - private boolean inputStreamEnded; - private Subtitle subtitle; private Subtitle nextSubtitle; private SubtitleParserHelper parserHelper; @@ -132,7 +129,7 @@ public final class TextTrackRenderer extends TrackRenderer implements Callback { */ public TextTrackRenderer(SampleSource source, TextRenderer textRenderer, Looper textRendererLooper, SubtitleParser... subtitleParsers) { - this.source = source.register(); + super(source); this.textRenderer = Assertions.checkNotNull(textRenderer); this.textRendererHandler = textRendererLooper == null ? null : new Handler(textRendererLooper, this); @@ -153,27 +150,29 @@ public final class TextTrackRenderer extends TrackRenderer implements Callback { } @Override - protected int doPrepare(long positionUs) { - boolean sourcePrepared = source.prepare(positionUs); - if (!sourcePrepared) { - return TrackRenderer.STATE_UNPREPARED; - } - int trackCount = source.getTrackCount(); + protected boolean handlesTrack(TrackInfo trackInfo) { for (int i = 0; i < subtitleParsers.length; i++) { - for (int j = 0; j < trackCount; j++) { - if (subtitleParsers[i].canParse(source.getTrackInfo(j).mimeType)) { - parserIndex = i; - trackIndex = j; - return TrackRenderer.STATE_PREPARED; - } + if (subtitleParsers[i].canParse(trackInfo.mimeType)) { + return true; } } - return TrackRenderer.STATE_IGNORE; + return false; } @Override - protected void onEnabled(long positionUs, boolean joining) { - source.enable(trackIndex, positionUs); + protected void onTrackSelected(TrackInfo trackInfo) { + for (int i = 0; i < subtitleParsers.length; i++) { + if (subtitleParsers[i].canParse(trackInfo.mimeType)) { + parserIndex = i; + return; + } + } + throw new IllegalStateException("Invalid track selected"); + } + + @Override + protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException { + super.onEnabled(positionUs, joining); parserThread = new HandlerThread("textParser"); parserThread.start(); parserHelper = new SubtitleParserHelper(parserThread.getLooper(), subtitleParsers[parserIndex]); @@ -181,8 +180,8 @@ public final class TextTrackRenderer extends TrackRenderer implements Callback { } @Override - protected void seekTo(long positionUs) { - source.seekToUs(positionUs); + protected void seekTo(long positionUs) throws ExoPlaybackException { + super.seekTo(positionUs); seekToInternal(); } @@ -196,8 +195,7 @@ public final class TextTrackRenderer extends TrackRenderer implements Callback { @Override protected void doSomeWork(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException { - source.continueBuffering(trackIndex, positionUs); - + continueBufferingSource(positionUs); if (nextSubtitle == null) { try { nextSubtitle = parserHelper.getAndClearResult(); @@ -241,7 +239,7 @@ public final class TextTrackRenderer extends TrackRenderer implements Callback { // Try and read the next subtitle from the source. SampleHolder sampleHolder = parserHelper.getSampleHolder(); sampleHolder.clearData(); - int result = source.readData(trackIndex, positionUs, formatHolder, sampleHolder, false); + int result = readSource(positionUs, formatHolder, sampleHolder, false); if (result == SampleSource.SAMPLE_READ) { parserHelper.startParseOperation(); } else if (result == SampleSource.END_OF_STREAM) { @@ -251,33 +249,14 @@ public final class TextTrackRenderer extends TrackRenderer implements Callback { } @Override - protected void onDisabled() { + protected void onDisabled() throws ExoPlaybackException { subtitle = null; nextSubtitle = null; parserThread.quit(); parserThread = null; parserHelper = null; clearTextRenderer(); - source.disable(trackIndex); - } - - @Override - protected void onReleased() { - source.release(); - } - - @Override - protected void maybeThrowError() throws ExoPlaybackException { - try { - source.maybeThrowError(); - } catch (IOException e) { - throw new ExoPlaybackException(e); - } - } - - @Override - protected long getDurationUs() { - return source.getTrackInfo(trackIndex).durationUs; + super.onDisabled(); } @Override 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 ffb9faddbb..df8dc44911 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 @@ -20,7 +20,8 @@ import com.google.android.exoplayer.ExoPlaybackException; import com.google.android.exoplayer.MediaFormatHolder; import com.google.android.exoplayer.SampleHolder; import com.google.android.exoplayer.SampleSource; -import com.google.android.exoplayer.SampleSource.SampleSourceReader; +import com.google.android.exoplayer.SampleSourceTrackRenderer; +import com.google.android.exoplayer.TrackInfo; import com.google.android.exoplayer.TrackRenderer; import com.google.android.exoplayer.text.Cue; import com.google.android.exoplayer.text.TextRenderer; @@ -32,14 +33,13 @@ import android.os.Handler.Callback; import android.os.Looper; import android.os.Message; -import java.io.IOException; import java.util.Collections; import java.util.TreeSet; /** * A {@link TrackRenderer} for EIA-608 closed captions in a media stream. */ -public final class Eia608TrackRenderer extends TrackRenderer implements Callback { +public final class Eia608TrackRenderer extends SampleSourceTrackRenderer implements Callback { private static final int MSG_INVOKE_RENDERER = 0; @@ -53,7 +53,6 @@ public final class Eia608TrackRenderer extends TrackRenderer implements Callback // The maximum duration that captions are parsed ahead of the current position. private static final int MAX_SAMPLE_READAHEAD_US = 5000000; - private final SampleSourceReader source; private final Eia608Parser eia608Parser; private final TextRenderer textRenderer; private final Handler textRendererHandler; @@ -62,9 +61,7 @@ public final class Eia608TrackRenderer extends TrackRenderer implements Callback private final StringBuilder captionStringBuilder; private final TreeSet pendingCaptionLists; - private int trackIndex; private boolean inputStreamEnded; - private int captionMode; private int captionRowCount; private String caption; @@ -81,7 +78,7 @@ public final class Eia608TrackRenderer extends TrackRenderer implements Callback */ public Eia608TrackRenderer(SampleSource source, TextRenderer textRenderer, Looper textRendererLooper) { - this.source = source.register(); + super(source); this.textRenderer = Assertions.checkNotNull(textRenderer); textRendererHandler = textRendererLooper == null ? null : new Handler(textRendererLooper, this); eia608Parser = new Eia608Parser(); @@ -92,30 +89,19 @@ public final class Eia608TrackRenderer extends TrackRenderer implements Callback } @Override - protected int doPrepare(long positionUs) { - boolean sourcePrepared = source.prepare(positionUs); - if (!sourcePrepared) { - return TrackRenderer.STATE_UNPREPARED; - } - int trackCount = source.getTrackCount(); - for (int i = 0; i < trackCount; i++) { - if (eia608Parser.canParse(source.getTrackInfo(i).mimeType)) { - trackIndex = i; - return TrackRenderer.STATE_PREPARED; - } - } - return TrackRenderer.STATE_IGNORE; + protected boolean handlesTrack(TrackInfo trackInfo) { + return eia608Parser.canParse(trackInfo.mimeType); } @Override - protected void onEnabled(long positionUs, boolean joining) { - source.enable(trackIndex, positionUs); + protected void onEnabled(long positionUs, boolean joining) throws ExoPlaybackException { + super.onEnabled(positionUs, joining); seekToInternal(); } @Override protected void seekTo(long positionUs) throws ExoPlaybackException { - source.seekToUs(positionUs); + super.seekTo(positionUs); seekToInternal(); } @@ -130,15 +116,14 @@ public final class Eia608TrackRenderer extends TrackRenderer implements Callback @Override protected void doSomeWork(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException { - source.continueBuffering(trackIndex, positionUs); - + continueBufferingSource(positionUs); if (isSamplePending()) { maybeParsePendingSample(positionUs); } int result = inputStreamEnded ? SampleSource.END_OF_STREAM : SampleSource.SAMPLE_READ; while (!isSamplePending() && result == SampleSource.SAMPLE_READ) { - result = source.readData(trackIndex, positionUs, formatHolder, sampleHolder, false); + result = readSource(positionUs, formatHolder, sampleHolder, false); if (result == SampleSource.SAMPLE_READ) { maybeParsePendingSample(positionUs); } else if (result == SampleSource.END_OF_STREAM) { @@ -161,25 +146,6 @@ public final class Eia608TrackRenderer extends TrackRenderer implements Callback } } - @Override - protected void onDisabled() { - source.disable(trackIndex); - } - - @Override - protected void maybeThrowError() throws ExoPlaybackException { - try { - source.maybeThrowError(); - } catch (IOException e) { - throw new ExoPlaybackException(e); - } - } - - @Override - protected long getDurationUs() { - return source.getTrackInfo(trackIndex).durationUs; - } - @Override protected long getBufferedPositionUs() { return TrackRenderer.END_OF_TRACK_US;