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
171abddd9f6225298066094e20a6c29061b6af4590Nick Chalkopackage com.android.usbtuner.exoplayer;
181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
191abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.media.AudioFormat;
201abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.media.MediaCodec.CryptoException;
211abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.media.MediaDataSource;
221abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.os.Handler;
231abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.os.Looper;
241abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.support.annotation.IntDef;
251abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport android.view.Surface;
261abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
271abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.google.android.exoplayer.DummyTrackRenderer;
281abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.google.android.exoplayer.ExoPlaybackException;
291abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.google.android.exoplayer.ExoPlayer;
301abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.google.android.exoplayer.MediaCodecAudioTrackRenderer;
311abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.google.android.exoplayer.MediaCodecTrackRenderer.DecoderInitializationException;
3248dadb49248271b01997862e1335912a4f2e189fYoungsang Choimport com.google.android.exoplayer.MediaCodecVideoTrackRenderer;
331abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.google.android.exoplayer.TrackRenderer;
341abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.google.android.exoplayer.audio.AudioCapabilities;
351abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.google.android.exoplayer.audio.AudioTrack;
361abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.usbtuner.data.Cea708Data;
371abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.usbtuner.data.Cea708Data.CaptionEvent;
381abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.usbtuner.exoplayer.Cea708TextTrackRenderer.CcListener;
391abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport com.android.usbtuner.exoplayer.ac3.Ac3TrackRenderer;
401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
411abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport java.lang.annotation.Retention;
421abddd9f6225298066094e20a6c29061b6af4590Nick Chalkoimport java.lang.annotation.RetentionPolicy;
431abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
441abddd9f6225298066094e20a6c29061b6af4590Nick Chalko/**
451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko * MPEG-2 TS stream player implementation using ExoPlayer.
461abddd9f6225298066094e20a6c29061b6af4590Nick Chalko */
471abddd9f6225298066094e20a6c29061b6af4590Nick Chalkopublic class MpegTsPlayer implements ExoPlayer.Listener,
4848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        MediaCodecVideoTrackRenderer.EventListener, Ac3TrackRenderer.EventListener {
491abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private int mCaptionServiceNumber = Cea708Data.EMPTY_SERVICE_NUMBER;
501abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    /**
521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko     * Interface definition for building specific track renderers.
531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko     */
541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public interface RendererBuilder {
551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        void buildRenderers(MpegTsPlayer mpegTsPlayer, MediaDataSource dataSource,
561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                RendererBuilderCallback callback);
571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
591abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    /**
601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko     * Interface definition for {@link RendererBuilder#buildRenderers} to notify the result.
611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko     */
621abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public interface RendererBuilderCallback {
6348dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        void onRenderers(String[][] trackNames, TrackRenderer[] renderers);
641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        void onRenderersError(Exception e);
651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    /**
681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko     * Interface definition for a callback to be notified of changes in player state.
691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko     */
701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public interface Listener {
711abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        void onStateChanged(int generation, boolean playWhenReady, int playbackState);
721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        void onError(int generation, Exception e);
731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        void onVideoSizeChanged(int generation, int width, int height,
741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                float pixelWidthHeightRatio);
751abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        void onDrawnToSurface(MpegTsPlayer player, Surface surface);
761abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        void onAudioUnplayable(int generation);
771abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
781abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    /**
801abddd9f6225298066094e20a6c29061b6af4590Nick Chalko     * Interface definition for a callback to be notified of changes on video display.
811abddd9f6225298066094e20a6c29061b6af4590Nick Chalko     */
821abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public interface VideoEventListener {
831abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        /**
841abddd9f6225298066094e20a6c29061b6af4590Nick Chalko         * Notifies the caption event.
851abddd9f6225298066094e20a6c29061b6af4590Nick Chalko         */
861abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        void onEmitCaptionEvent(CaptionEvent event);
871abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
881abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        /**
891abddd9f6225298066094e20a6c29061b6af4590Nick Chalko         * Notifies the discovered caption service number.
901abddd9f6225298066094e20a6c29061b6af4590Nick Chalko         */
911abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        void onDiscoverCaptionServiceNumber(int serviceNumber);
921abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
931abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
941abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    // Constants pulled into this class for convenience.
951abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @IntDef({STATE_IDLE, STATE_PREPARING, STATE_BUFFERING, STATE_READY, STATE_ENDED})
961abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Retention(RetentionPolicy.SOURCE)
971abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public @interface PlaybackState {}
981abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public static final int STATE_IDLE = ExoPlayer.STATE_IDLE;
991abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public static final int STATE_PREPARING = ExoPlayer.STATE_PREPARING;
1001abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public static final int STATE_BUFFERING = ExoPlayer.STATE_BUFFERING;
1011abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public static final int STATE_READY = ExoPlayer.STATE_READY;
1021abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public static final int STATE_ENDED = ExoPlayer.STATE_ENDED;
1031abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1041abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public static final int RENDERER_COUNT = 3;
1051abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public static final int MIN_BUFFER_MS = 200;
1061abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public static final int MIN_REBUFFER_MS = 500;
1071abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1081abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @IntDef({TRACK_TYPE_VIDEO, TRACK_TYPE_AUDIO, TRACK_TYPE_TEXT})
1091abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Retention(RetentionPolicy.SOURCE)
1101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public @interface TrackType {}
1111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public static final int TRACK_TYPE_VIDEO = 0;
1121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public static final int TRACK_TYPE_AUDIO = 1;
1131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public static final int TRACK_TYPE_TEXT = 2;
1141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @IntDef({RENDERER_BUILDING_STATE_IDLE, RENDERER_BUILDING_STATE_BUILDING,
1161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        RENDERER_BUILDING_STATE_BUILT})
1171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Retention(RetentionPolicy.SOURCE)
1181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public @interface RendererBuildingState {}
1191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private static final int RENDERER_BUILDING_STATE_IDLE = 1;
1201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private static final int RENDERER_BUILDING_STATE_BUILDING = 2;
1211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private static final int RENDERER_BUILDING_STATE_BUILT = 3;
1221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1231abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private final RendererBuilder mRendererBuilder;
1241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private final ExoPlayer mPlayer;
1251abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private final Handler mMainHandler;
1261abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private final int mPlayerGeneration;
1271abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private final AudioCapabilities mAudioCapabilities;
1281abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1291abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private Listener mListener;
1301abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @RendererBuildingState private int mRendererBuildingState;
1311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @PlaybackState private int mLastReportedPlaybackState;
1321abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private boolean mLastReportedPlayWhenReady;
1331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1341abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private Surface mSurface;
1351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private InternalRendererBuilderCallback mBuilderCallback;
1361abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private TrackRenderer mVideoRenderer;
1371abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private TrackRenderer mAudioRenderer;
1381abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private String[][] mTrackNames;
1401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private int[] mSelectedTracks;
1411abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1421abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private Cea708TextTrackRenderer mTextRenderer;
1431abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private CcListener mCcListener;
1441abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private VideoEventListener mVideoEventListener;
1451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1461abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public MpegTsPlayer(int playerGeneration, RendererBuilder rendererBuilder, Handler handler,
14748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            AudioCapabilities capabilities, Listener listener) {
1481abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mRendererBuilder = rendererBuilder;
1491abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mPlayer = ExoPlayer.Factory.newInstance(RENDERER_COUNT, MIN_BUFFER_MS, MIN_REBUFFER_MS);
1501abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mPlayer.addListener(this);
1511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mMainHandler = handler;
1521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mPlayerGeneration = playerGeneration;
1531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mAudioCapabilities = capabilities;
1541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mLastReportedPlaybackState = STATE_IDLE;
1551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mRendererBuildingState = RENDERER_BUILDING_STATE_IDLE;
1561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mSelectedTracks = new int[RENDERER_COUNT];
1571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mCcListener = new MpegTsCcListener();
1581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mListener = listener;
1591abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void setVideoEventListener(VideoEventListener videoEventListener) {
1621abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mVideoEventListener = videoEventListener;
1631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void setCaptionServiceNumber(int captionServiceNumber) {
1661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mCaptionServiceNumber = captionServiceNumber;
1671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mTextRenderer != null) {
1681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mPlayer.sendMessage(mTextRenderer,
1691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                    Cea708TextTrackRenderer.MSG_SERVICE_NUMBER, mCaptionServiceNumber);
1701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1711abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void setSurface(Surface surface) {
1741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mSurface = surface;
1751abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        pushSurface(false);
1761abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1771abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1781abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public Surface getSurface() {
1791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return mSurface;
1801abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1811abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1821abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void blockingClearSurface() {
1831abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mSurface = null;
1841abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        pushSurface(true);
1851abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1861abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1871abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public String[] getTracks(int type) {
1881abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return mTrackNames == null ? null : mTrackNames[type];
1891abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1901abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1911abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public int getSelectedTrackIndex(int type) {
1921abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return mSelectedTracks[type];
1931abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
1941abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
1951abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void selectTrack(int type, int index) {
1961abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mSelectedTracks[type] == index) {
1971abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            return;
1981abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
1991abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mSelectedTracks[type] = index;
2001abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        pushTrackSelection(type, true);
2011abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2021abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
203ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko    public void prepare(MediaDataSource source) {
2041abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mRendererBuildingState == RENDERER_BUILDING_STATE_BUILT) {
2051abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mPlayer.stop();
2061abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2071abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mBuilderCallback != null) {
2081abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mBuilderCallback.cancel();
2091abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mRendererBuildingState = RENDERER_BUILDING_STATE_BUILDING;
2111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        maybeReportPlayerState();
2121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mBuilderCallback = new InternalRendererBuilderCallback();
213ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        mRendererBuilder.buildRenderers(this, source, mBuilderCallback);
2141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
21648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    /* package */ void onRenderers(String[][] trackNames, TrackRenderer[] renderers) {
2171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mBuilderCallback = null;
2181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        // Normalize the results.
2201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (trackNames == null) {
2211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            trackNames = new String[RENDERER_COUNT][];
2221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2231abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        for (int i = 0; i < RENDERER_COUNT; i++) {
2241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            if (renderers[i] == null) {
2251abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                // Convert a null renderer to a dummy renderer.
2261abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                renderers[i] = new DummyTrackRenderer();
2271abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
2281abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2291abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mVideoRenderer = renderers[TRACK_TYPE_VIDEO];
2301abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mAudioRenderer = renderers[TRACK_TYPE_AUDIO];
2311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mTextRenderer = (Cea708TextTrackRenderer) renderers[TRACK_TYPE_TEXT];
2321abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mTextRenderer.setCcListener(mCcListener);
2331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mPlayer.sendMessage(
2341abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                mTextRenderer, Cea708TextTrackRenderer.MSG_SERVICE_NUMBER, mCaptionServiceNumber);
2351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mTrackNames = trackNames;
2361abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mRendererBuildingState = RENDERER_BUILDING_STATE_BUILT;
2371abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        pushSurface(false);
23848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        mPlayer.prepare(renderers);
2391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        pushTrackSelection(TRACK_TYPE_VIDEO, true);
2401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        pushTrackSelection(TRACK_TYPE_AUDIO, true);
2411abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        pushTrackSelection(TRACK_TYPE_TEXT, true);
2421abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2431abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2441abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    /* package */ void onRenderersError(Exception e) {
2451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mBuilderCallback = null;
2461abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mListener != null) {
2471abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mListener.onError(mPlayerGeneration, e);
2481abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2491abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mRendererBuildingState = RENDERER_BUILDING_STATE_IDLE;
2501abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        maybeReportPlayerState();
2511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void setPlayWhenReady(boolean playWhenReady) {
2541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mPlayer.setPlayWhenReady(playWhenReady);
2551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void seekTo(long positionMs) {
2581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mPlayer.seekTo(positionMs);
2591abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void release() {
2621abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mBuilderCallback != null) {
2631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mBuilderCallback.cancel();
2641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mBuilderCallback = null;
2651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mRendererBuildingState = RENDERER_BUILDING_STATE_IDLE;
2671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mSurface = null;
26848dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        mListener = null;
2691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mPlayer.release();
2701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2711abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @PlaybackState public int getPlaybackState() {
2731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mRendererBuildingState == RENDERER_BUILDING_STATE_BUILDING) {
2741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            return STATE_PREPARING;
2751abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
2761abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return mPlayer.getPlaybackState();
2771abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2781abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public boolean isPlaying() {
2801abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        @PlaybackState int state = getPlaybackState();
2811abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return (state == STATE_READY || state == STATE_BUFFERING)
2821abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                && mPlayer.getPlayWhenReady();
2831abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2841abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2851abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public boolean isBuffering() {
2861abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return getPlaybackState() == STATE_BUFFERING;
2871abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2881abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2891abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public long getCurrentPosition() {
2901abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return mPlayer.getCurrentPosition();
2911abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2921abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2931abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public long getDuration() {
2941abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return mPlayer.getDuration();
2951abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
2961abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
2971abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public int getBufferedPercentage() {
2981abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return mPlayer.getBufferedPercentage();
2991abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3001abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3011abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public boolean getPlayWhenReady() {
3021abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return mPlayer.getPlayWhenReady();
3031abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3041abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3051abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void setVolume(float volume) {
3061abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mPlayer.sendMessage(mAudioRenderer, MediaCodecAudioTrackRenderer.MSG_SET_VOLUME, volume);
3071abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3081abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3091abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void setAudioTrack(boolean enable) {
3101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mPlayer.sendMessage(mAudioRenderer, Ac3TrackRenderer.MSG_SET_AUDIO_TRACK, enable ? 1 : 0);
3111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public boolean isAc3Playable() {
314ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko        return mAudioCapabilities != null
315ba5845f23b8fbc985890f892961abc8b39886611Nick Chalko                && mAudioCapabilities.supportsEncoding(AudioFormat.ENCODING_AC3);
3161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void onAudioUnplayable() {
3191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mListener != null) {
3201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mListener.onAudioUnplayable(mPlayerGeneration);
3211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
3221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3231abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    /* package */ Looper getPlaybackLooper() {
3251abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return mPlayer.getPlaybackLooper();
3261abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3271abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3281abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    /* package */ Handler getMainHandler() {
3291abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        return mMainHandler;
3301abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3321abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
3331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void onPlayerStateChanged(boolean playWhenReady, int state) {
3341abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        maybeReportPlayerState();
3351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3361abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3371abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
3381abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void onPlayerError(ExoPlaybackException exception) {
3391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        mRendererBuildingState = RENDERER_BUILDING_STATE_IDLE;
3401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mListener != null) {
3411abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mListener.onError(mPlayerGeneration, exception);
3421abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
3431abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3441abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
34648dadb49248271b01997862e1335912a4f2e189fYoungsang Cho    public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees,
34748dadb49248271b01997862e1335912a4f2e189fYoungsang Cho            float pixelWidthHeightRatio) {
3481abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mListener != null) {
3491abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mListener.onVideoSizeChanged(mPlayerGeneration, width, height, pixelWidthHeightRatio);
3501abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
3511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
3541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void onDecoderInitialized(String decoderName, long elapsedRealtimeMs,
3551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            long initializationDurationMs) {
3561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        // TODO
3571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3591abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
3601abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void onDecoderInitializationError(DecoderInitializationException e) {
3611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        // Do nothing.
3621abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
3651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void onAudioTrackInitializationError(AudioTrack.InitializationException e) {
3661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        onAudioUnplayable();
3671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
3701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void onAudioTrackWriteError(AudioTrack.WriteException e) {
3711abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        // Do nothing.
3721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3741abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
3751abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void onCryptoError(CryptoException e) {
3761abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        // Do nothing.
3771abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3781abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3791abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
3801abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void onPlayWhenReadyCommitted() {
3811abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        // Do nothing.
3821abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3831abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3841abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
3851abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void onDrawnToSurface(Surface surface) {
3861abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mListener != null) {
3871abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mListener.onDrawnToSurface(this, surface);
3881abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
3891abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3901abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3911abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    @Override
3921abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    public void onDroppedFrames(int count, long elapsed) {
3931abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        // Do nothing.
3941abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
3951abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
3961abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private void maybeReportPlayerState() {
3971abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        boolean playWhenReady = mPlayer.getPlayWhenReady();
3981abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        @PlaybackState int playbackState = getPlaybackState();
3991abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mLastReportedPlayWhenReady != playWhenReady
4001abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                || mLastReportedPlaybackState != playbackState) {
4011abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            if (mListener != null) {
4021abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                if (playbackState == STATE_ENDED) {
4031abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                    mListener.onStateChanged(mPlayerGeneration, playWhenReady, STATE_ENDED);
4041abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                }
4051abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                else if (playbackState == STATE_READY) {
4061abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                    mListener.onStateChanged(mPlayerGeneration, playWhenReady, STATE_READY);
4071abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                }
4081abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
4091abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mLastReportedPlayWhenReady = playWhenReady;
4101abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mLastReportedPlaybackState = playbackState;
4111abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
4121abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
4131abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
4141abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private void pushSurface(boolean blockForSurfacePush) {
4151abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mRendererBuildingState != RENDERER_BUILDING_STATE_BUILT) {
4161abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            return;
4171abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
4181abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
4191abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (blockForSurfacePush) {
4201abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mPlayer.blockingSendMessage(
4211abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                    mVideoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, mSurface);
4221abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        } else {
4231abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            mPlayer.sendMessage(
4241abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                    mVideoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, mSurface);
4251abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
4261abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
4271abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
4281abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private void pushTrackSelection(@TrackType int type, boolean allowRendererEnable) {
4291abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        if (mRendererBuildingState != RENDERER_BUILDING_STATE_BUILT) {
4301abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            return;
4311abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
43248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        mPlayer.setSelectedTrack(type, allowRendererEnable ? 0 : -1);
4331abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
4341abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
4351abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private class MpegTsCcListener implements CcListener {
4361abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
4371abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        @Override
4381abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        public void emitEvent(CaptionEvent captionEvent) {
4391abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            if (mVideoEventListener != null) {
4401abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                mVideoEventListener.onEmitCaptionEvent(captionEvent);
4411abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
4421abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
4431abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
4441abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        @Override
4451abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        public void discoverServiceNumber(int serviceNumber) {
4461abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            if (mVideoEventListener != null) {
4471abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                mVideoEventListener.onDiscoverCaptionServiceNumber(serviceNumber);
4481abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
4491abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
4501abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
4511abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
4521abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    private class InternalRendererBuilderCallback implements RendererBuilderCallback {
4531abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        private boolean canceled;
4541abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
4551abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        public void cancel() {
4561abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            canceled = true;
4571abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
4581abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
4591abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        @Override
46048dadb49248271b01997862e1335912a4f2e189fYoungsang Cho        public void onRenderers(String[][] trackNames, TrackRenderer[] renderers) {
4611abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            if (!canceled) {
46248dadb49248271b01997862e1335912a4f2e189fYoungsang Cho                MpegTsPlayer.this.onRenderers(trackNames, renderers);
4631abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
4641abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
4651abddd9f6225298066094e20a6c29061b6af4590Nick Chalko
4661abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        @Override
4671abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        public void onRenderersError(Exception e) {
4681abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            if (!canceled) {
4691abddd9f6225298066094e20a6c29061b6af4590Nick Chalko                MpegTsPlayer.this.onRenderersError(e);
4701abddd9f6225298066094e20a6c29061b6af4590Nick Chalko            }
4711abddd9f6225298066094e20a6c29061b6af4590Nick Chalko        }
4721abddd9f6225298066094e20a6c29061b6af4590Nick Chalko    }
4731abddd9f6225298066094e20a6c29061b6af4590Nick Chalko}
474