11abddd9f6225298066094e20a6c29061b6af4590Nick Chalko/* 21abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Copyright (C) 2015 The Android Open Source Project 31abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * 41abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Licensed under the Apache License, Version 2.0 (the "License"); 51abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * you may not use this file except in compliance with the License. 61abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * You may obtain a copy of the License at 71abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * 81abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * http://www.apache.org/licenses/LICENSE-2.0 91abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * 101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * Unless required by applicable law or agreed to in writing, software 111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * distributed under the License is distributed on an "AS IS" BASIS, 121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * See the License for the specific language governing permissions and 141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * limitations under the License. 151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */ 161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 1765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkopackage com.android.tv.tuner.exoplayer; 181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 191abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.util.Log; 201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 211abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.google.android.exoplayer.ExoPlaybackException; 222e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport com.google.android.exoplayer.MediaClock; 232e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport com.google.android.exoplayer.MediaFormat; 242e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport com.google.android.exoplayer.MediaFormatHolder; 251abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.google.android.exoplayer.SampleHolder; 261abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.google.android.exoplayer.SampleSource; 271abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.google.android.exoplayer.TrackRenderer; 282e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalkoimport com.google.android.exoplayer.util.Assertions; 2965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.tuner.cc.Cea708Parser; 3065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkoimport com.android.tv.tuner.data.Cea708Data.CaptionEvent; 311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 321abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport java.io.IOException; 331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 341abddd9f6225298066094e20a6c29061b6af4590Nick Chalko/** 351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * A {@link TrackRenderer} for CEA-708 textual subtitles. 361abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */ 3765fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalkopublic class Cea708TextTrackRenderer extends TrackRenderer implements 3865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko Cea708Parser.OnCea708ParserListener { 391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private static final String TAG = "Cea708TextTrackRenderer"; 401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private static final boolean DEBUG = false; 411abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 421abddd9f6225298066094e20a6c29061b6af4590Nick Chalko public static final int MSG_SERVICE_NUMBER = 1; 436ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko public static final int MSG_ENABLE_CLOSED_CAPTION = 2; 441abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko // According to CEA-708B, the maximum value of closed caption bandwidth is 9600bps. 461abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private static final int DEFAULT_INPUT_BUFFER_SIZE = 9600 / 8; 471abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 4865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private final SampleSource.SampleSourceReader mSource; 4965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private final SampleHolder mSampleHolder; 5065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko private final MediaFormatHolder mFormatHolder; 511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private int mServiceNumber; 521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private boolean mInputStreamEnded; 531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private long mCurrentPositionUs; 541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private long mPresentationTimeUs; 551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private int mTrackIndex; 566ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko private boolean mRenderingDisabled; 571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private Cea708Parser mCea708Parser; 581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private CcListener mCcListener; 591abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko public interface CcListener { 611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko void emitEvent(CaptionEvent captionEvent); 626ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko void clearCaption(); 631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko void discoverServiceNumber(int serviceNumber); 641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko public Cea708TextTrackRenderer(SampleSource source) { 672e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko mSource = source.register(); 682e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko mTrackIndex = -1; 691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mSampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_DIRECT); 702e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko mSampleHolder.ensureSpaceForWrite(DEFAULT_INPUT_BUFFER_SIZE); 712e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko mFormatHolder = new MediaFormatHolder(); 721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 752e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko protected MediaClock getMediaClock() { 762e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko return null; 771abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 781abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private boolean handlesMimeType(String mimeType) { 8065fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return mimeType.equals(MpegTsSampleExtractor.MIMETYPE_TEXT_CEA_708); 811abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 821abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 831abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 842e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko protected boolean doPrepare(long positionUs) throws ExoPlaybackException { 852e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko boolean sourcePrepared = mSource.prepare(positionUs); 862e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko if (!sourcePrepared) { 872e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko return false; 881abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 891abddd9f6225298066094e20a6c29061b6af4590Nick Chalko int trackCount = mSource.getTrackCount(); 901abddd9f6225298066094e20a6c29061b6af4590Nick Chalko for (int i = 0; i < trackCount; ++i) { 912e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko MediaFormat trackFormat = mSource.getFormat(i); 922e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko if (handlesMimeType(trackFormat.mimeType)) { 931abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mTrackIndex = i; 941abddd9f6225298066094e20a6c29061b6af4590Nick Chalko clearDecodeState(); 952e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko return true; 961abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 971abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 982e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko // TODO: Check this case. (Source do not have the proper mime type.) 992e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko return true; 1001abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1011abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 1021abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 1032e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko protected void onEnabled(int track, long positionUs, boolean joining) { 1042e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko Assertions.checkArgument(mTrackIndex != -1 && track == 0); 1051abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mSource.enable(mTrackIndex, positionUs); 1061abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mInputStreamEnded = false; 1071abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mPresentationTimeUs = positionUs; 1081abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mCurrentPositionUs = Long.MIN_VALUE; 1091abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 1111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 1121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko protected void onDisabled() { 1131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mSource.disable(mTrackIndex); 1141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 1161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 1171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko protected void onReleased() { 1181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mSource.release(); 1191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mCea708Parser = null; 1201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 1221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 1231abddd9f6225298066094e20a6c29061b6af4590Nick Chalko protected boolean isEnded() { 1241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko return mInputStreamEnded; 1251abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1261abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 1271abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 1281abddd9f6225298066094e20a6c29061b6af4590Nick Chalko protected boolean isReady() { 1292e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko // Since this track will be fed by {@link VideoTrackRenderer}, 1302e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko // it is not required to control transition between ready state and buffering state. 1312e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko return true; 1322e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 1332e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 1342e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko @Override 1352e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko protected int getTrackCount() { 1362e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko return mTrackIndex < 0 ? 0 : 1; 1372e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 1382e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 1392e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko @Override 1402e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko protected MediaFormat getFormat(int track) { 1412e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko Assertions.checkArgument(mTrackIndex != -1 && track == 0); 1422e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko return mSource.getFormat(mTrackIndex); 1432e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 1442e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 1452e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko @Override 1462e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko protected void maybeThrowError() throws ExoPlaybackException { 1472e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko try { 1482e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko mSource.maybeThrowError(); 1492e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } catch (IOException e) { 1502e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko throw new ExoPlaybackException(e); 1512e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 1521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 1541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 1551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko protected void doSomeWork(long positionUs, long elapsedRealtimeUs) throws ExoPlaybackException { 1561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko try { 1571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mPresentationTimeUs = positionUs; 1581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko if (!mInputStreamEnded) { 1591abddd9f6225298066094e20a6c29061b6af4590Nick Chalko processOutput(); 1601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko feedInputBuffer(); 1611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1621abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } catch (IOException e) { 1631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko throw new ExoPlaybackException(e); 1641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 1671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private boolean processOutput() { 16865fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko return !mInputStreamEnded && mCea708Parser != null && 16965fda1eaa94968bb55d5ded10dcb0b3f37fb05f2Nick Chalko mCea708Parser.processClosedCaptions(mPresentationTimeUs); 1701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1711abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 1721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private boolean feedInputBuffer() throws IOException, ExoPlaybackException { 1731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko if (mInputStreamEnded) { 1741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko return false; 1751abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1762e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko long discontinuity = mSource.readDiscontinuity(mTrackIndex); 1772e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko if (discontinuity != SampleSource.NO_DISCONTINUITY) { 1782e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko if (DEBUG) { 1792e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko Log.d(TAG, "Read discontinuity happened"); 1802e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 1812e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko 1822e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko // TODO: handle input discontinuity for trickplay. 1832e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko clearDecodeState(); 1842e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko mPresentationTimeUs = discontinuity; 1852e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko return false; 1862e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko } 1871abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mSampleHolder.data.clear(); 1881abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mSampleHolder.size = 0; 1892e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko int result = mSource.readData(mTrackIndex, mPresentationTimeUs, 1902e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko mFormatHolder, mSampleHolder); 1911abddd9f6225298066094e20a6c29061b6af4590Nick Chalko switch (result) { 1921abddd9f6225298066094e20a6c29061b6af4590Nick Chalko case SampleSource.NOTHING_READ: { 1931abddd9f6225298066094e20a6c29061b6af4590Nick Chalko return false; 1941abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1951abddd9f6225298066094e20a6c29061b6af4590Nick Chalko case SampleSource.FORMAT_READ: { 1961abddd9f6225298066094e20a6c29061b6af4590Nick Chalko if (DEBUG) { 1971abddd9f6225298066094e20a6c29061b6af4590Nick Chalko Log.i(TAG, "Format was read again"); 1981abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 1991abddd9f6225298066094e20a6c29061b6af4590Nick Chalko return true; 2001abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2011abddd9f6225298066094e20a6c29061b6af4590Nick Chalko case SampleSource.END_OF_STREAM: { 2021abddd9f6225298066094e20a6c29061b6af4590Nick Chalko if (DEBUG) { 2031abddd9f6225298066094e20a6c29061b6af4590Nick Chalko Log.i(TAG, "End of stream from SampleSource"); 2041abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2051abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mInputStreamEnded = true; 2061abddd9f6225298066094e20a6c29061b6af4590Nick Chalko return false; 2071abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2081abddd9f6225298066094e20a6c29061b6af4590Nick Chalko case SampleSource.SAMPLE_READ: { 2091abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mSampleHolder.data.flip(); 2106ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mCea708Parser != null && !mRenderingDisabled) { 2111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mCea708Parser.parseClosedCaption(mSampleHolder.data, mSampleHolder.timeUs); 2121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko return true; 2141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko return false; 2171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 2191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private void clearDecodeState() { 2201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mCea708Parser = new Cea708Parser(); 2211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mCea708Parser.setListener(this); 2221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mCea708Parser.setListenServiceNumber(mServiceNumber); 2231abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 2251abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 2261abddd9f6225298066094e20a6c29061b6af4590Nick Chalko protected long getDurationUs() { 2272e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko return mSource.getFormat(mTrackIndex).durationUs; 2281abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2291abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 2301abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 2311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko protected long getBufferedPositionUs() { 2322e1279b8bbe0603fb4399b25b73121bed5953c46Nick Chalko return mSource.getBufferedPositionUs(); 2331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2341abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 2351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 2361abddd9f6225298066094e20a6c29061b6af4590Nick Chalko protected void seekTo(long currentPositionUs) throws ExoPlaybackException { 2371abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mSource.seekToUs(currentPositionUs); 2381abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mInputStreamEnded = false; 2391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mPresentationTimeUs = currentPositionUs; 2401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mCurrentPositionUs = Long.MIN_VALUE; 2411abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2421abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 2431abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 2441abddd9f6225298066094e20a6c29061b6af4590Nick Chalko protected void onStarted() { 2451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko // do nothing. 2461abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2471abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 2481abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 2491abddd9f6225298066094e20a6c29061b6af4590Nick Chalko protected void onStopped() { 2501abddd9f6225298066094e20a6c29061b6af4590Nick Chalko // do nothing. 2511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 2531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko private void setServiceNumber(int serviceNumber) { 2541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mServiceNumber = serviceNumber; 2551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko if (mCea708Parser != null) { 2561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mCea708Parser.setListenServiceNumber(serviceNumber); 2571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2591abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 2601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 2611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko public void emitEvent(CaptionEvent event) { 2621abddd9f6225298066094e20a6c29061b6af4590Nick Chalko if (mCcListener != null) { 2631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mCcListener.emitEvent(event); 2641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 2671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 2681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko public void discoverServiceNumber(int serviceNumber) { 2691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko if (mCcListener != null) { 2701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mCcListener.discoverServiceNumber(serviceNumber); 2711abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 2741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko public void setCcListener(CcListener ccListener) { 2751abddd9f6225298066094e20a6c29061b6af4590Nick Chalko mCcListener = ccListener; 2761abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 2771abddd9f6225298066094e20a6c29061b6af4590Nick Chalko 2781abddd9f6225298066094e20a6c29061b6af4590Nick Chalko @Override 2791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko public void handleMessage(int messageType, Object message) throws ExoPlaybackException { 2806ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko switch (messageType) { 2816ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko case MSG_SERVICE_NUMBER: 2826ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko setServiceNumber((int) message); 2836ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko break; 2846ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko case MSG_ENABLE_CLOSED_CAPTION: 2856ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko boolean renderingDisabled = (Boolean) message == false; 2866ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mRenderingDisabled != renderingDisabled) { 2876ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mRenderingDisabled = renderingDisabled; 2886ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mRenderingDisabled) { 2896ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mCea708Parser != null) { 2906ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCea708Parser.clear(); 2916ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2926ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko if (mCcListener != null) { 2936ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko mCcListener.clearCaption(); 2946ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2956ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2966ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko } 2976ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko break; 2986ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko default: 2996ebde20b03db4c0d57f67acaac11832b610b966bNick Chalko super.handleMessage(messageType, message); 3001abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 3011abddd9f6225298066094e20a6c29061b6af4590Nick Chalko } 3021abddd9f6225298066094e20a6c29061b6af4590Nick Chalko} 303