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