TunableTvView.java revision b47a0ad3227b940175fa4ecfe5c4113da72c8237
1d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leepackage com.android.tv.ui; 2900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 3900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.content.Context; 49035590d94d136a020e499ce720b9d2cf1f6f45cJae Seoimport android.media.tv.TvInputInfo; 59035590d94d136a020e499ce720b9d2cf1f6f45cJae Seoimport android.media.tv.TvView; 6900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.util.AttributeSet; 7900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.util.Log; 8900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Choimport android.view.SurfaceHolder; 9b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kangimport android.view.SurfaceView; 10900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 11d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.data.Channel; 1221abb13274f379e69c3c86d51e493122cccca345Dongwon Kangimport com.android.tv.data.StreamInfo; 13d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.util.TvInputManagerHelper; 14d422754c0cc8475d6e2c8c079ed2ee2e96213edbChulwoo Leeimport com.android.tv.util.Utils; 15900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 1621abb13274f379e69c3c86d51e493122cccca345Dongwon Kangpublic class TunableTvView extends TvView implements StreamInfo { 17900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho private static final boolean DEBUG = true; 18900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho private static final String TAG = "TunableTvView"; 19900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 20900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho private static final int DELAY_FOR_SURFACE_RELEASE = 300; 21900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 22900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho private float mVolume; 23900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho private long mChannelId = Channel.INVALID_ID; 24900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho private TvInputManagerHelper mInputManagerHelper; 25900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho private boolean mStarted; 26900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho private TvInputInfo mInputInfo; 27900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho private OnTuneListener mOnTuneListener; 2821abb13274f379e69c3c86d51e493122cccca345Dongwon Kang private int mVideoFormat = StreamInfo.VIDEO_DEFINITION_LEVEL_UNKNOWN; 29e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang private int mAudioChannelCount = StreamInfo.AUDIO_CHANNEL_COUNT_UNKNOWN; 30e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang private boolean mHasClosedCaption = false; 31b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang private SurfaceView mSurface; 32900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 33900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() { 34900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho @Override 35900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } 36900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 37900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho @Override 38900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public void surfaceCreated(SurfaceHolder holder) { } 39900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 40900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho @Override 41900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public void surfaceDestroyed(SurfaceHolder holder) { 42900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho // TODO: It is a hack to wait to release a surface at TIS. If there is a way to 43900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho // know when the surface is released at TIS, we don't need this hack. 44900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho try { 45900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho if (DEBUG) Log.d(TAG, "Sleep to wait destroying a surface"); 46900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho Thread.sleep(DELAY_FOR_SURFACE_RELEASE); 47900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho if (DEBUG) Log.d(TAG, "Wake up from sleeping"); 48900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } catch (InterruptedException e) { 49900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho e.printStackTrace(); 50900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 51900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 52900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho }; 53900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 549bb548ba08d7e222f276287fead545c6a11704d8Jae Seo private final TvInputListener mListener = 559bb548ba08d7e222f276287fead545c6a11704d8Jae Seo new TvInputListener() { 56900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho @Override 579bb548ba08d7e222f276287fead545c6a11704d8Jae Seo public void onError(String inputId, int errorCode) { 589bb548ba08d7e222f276287fead545c6a11704d8Jae Seo if (errorCode == TvView.ERROR_BUSY) { 599bb548ba08d7e222f276287fead545c6a11704d8Jae Seo Log.w(TAG, "Failed to bind an input"); 60900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho long channelId = mChannelId; 61900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mChannelId = Channel.INVALID_ID; 62900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mInputInfo = null; 63900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho if (mOnTuneListener != null) { 64900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mOnTuneListener.onTuned(false, channelId); 65900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mOnTuneListener = null; 66900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 679bb548ba08d7e222f276287fead545c6a11704d8Jae Seo } else if (errorCode == TvView.ERROR_TV_INPUT_DISCONNECTED) { 689bb548ba08d7e222f276287fead545c6a11704d8Jae Seo Log.w(TAG, "Session is released by crash"); 699bb548ba08d7e222f276287fead545c6a11704d8Jae Seo long channelId = mChannelId; 709bb548ba08d7e222f276287fead545c6a11704d8Jae Seo mChannelId = Channel.INVALID_ID; 719bb548ba08d7e222f276287fead545c6a11704d8Jae Seo mInputInfo = null; 729bb548ba08d7e222f276287fead545c6a11704d8Jae Seo if (mOnTuneListener != null) { 739bb548ba08d7e222f276287fead545c6a11704d8Jae Seo mOnTuneListener.onUnexpectedStop(channelId); 749bb548ba08d7e222f276287fead545c6a11704d8Jae Seo mOnTuneListener = null; 759bb548ba08d7e222f276287fead545c6a11704d8Jae Seo } 76900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 77900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 78900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 79900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho @Override 809bb548ba08d7e222f276287fead545c6a11704d8Jae Seo public void onVideoStreamChanged(String inputId, int width, int height, 81fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang boolean interlaced) { 8221abb13274f379e69c3c86d51e493122cccca345Dongwon Kang mVideoFormat = Utils.getVideoDefinitionLevelFromSize(width, height); 8321abb13274f379e69c3c86d51e493122cccca345Dongwon Kang if (mOnTuneListener != null) { 8421abb13274f379e69c3c86d51e493122cccca345Dongwon Kang mOnTuneListener.onStreamInfoChanged(TunableTvView.this); 8521abb13274f379e69c3c86d51e493122cccca345Dongwon Kang } 8621abb13274f379e69c3c86d51e493122cccca345Dongwon Kang } 87fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang 88fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang @Override 899bb548ba08d7e222f276287fead545c6a11704d8Jae Seo public void onAudioStreamChanged(String inputId, int channelCount) { 90fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang mAudioChannelCount = channelCount; 91fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang if (mOnTuneListener != null) { 92fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang mOnTuneListener.onStreamInfoChanged(TunableTvView.this); 93fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang } 94fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang } 95fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang 96fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang @Override 979bb548ba08d7e222f276287fead545c6a11704d8Jae Seo public void onClosedCaptionStreamChanged(String inputId, boolean hasClosedCaption) { 98fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang mHasClosedCaption = hasClosedCaption; 99fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang if (mOnTuneListener != null) { 100fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang mOnTuneListener.onStreamInfoChanged(TunableTvView.this); 101fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang } 102fc4ae3d84120d40af0d1ce5da7b0b1e40003e9aaDongwon Kang } 103900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho }; 104900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 105900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public TunableTvView(Context context) { 106900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho this(context, null, 0); 107900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 108900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 109900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public TunableTvView(Context context, AttributeSet attrs) { 110900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho this(context, attrs, 0); 111900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 112900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 113900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public TunableTvView(Context context, AttributeSet attrs, int defStyleAttr) { 114900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho super(context, attrs, defStyleAttr); 115b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang for (int i = 0; i < getChildCount(); ++i) { 116b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang if (getChildAt(i) instanceof SurfaceView) { 117b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang mSurface = (SurfaceView) getChildAt(i); 118b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang mSurface.getHolder().addCallback(mSurfaceHolderCallback); 119b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang return; 120b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang } 121b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang } 122b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang throw new RuntimeException("TvView does not have SurfaceView."); 123900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 124900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 125900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public void start(TvInputManagerHelper tvInputManagerHelper) { 126900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mInputManagerHelper = tvInputManagerHelper; 127900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho if (mStarted) { 128900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho return; 129900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 130900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mStarted = true; 131900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 132900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 133900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public void stop() { 134900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho if (!mStarted) { 135900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho return; 136900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 137900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mStarted = false; 1389bb548ba08d7e222f276287fead545c6a11704d8Jae Seo reset(); 139900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mChannelId = Channel.INVALID_ID; 140900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mInputInfo = null; 141900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mOnTuneListener = null; 142900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 143900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 144900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public boolean isPlaying() { 145900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho return mStarted; 146900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 147900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 148900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public boolean tuneTo(long channelId, OnTuneListener listener) { 149900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho if (!mStarted) { 150900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho throw new IllegalStateException("TvView isn't started"); 151900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 152900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho if (DEBUG) Log.d(TAG, "tuneTo " + channelId); 15321abb13274f379e69c3c86d51e493122cccca345Dongwon Kang mVideoFormat = StreamInfo.VIDEO_DEFINITION_LEVEL_UNKNOWN; 154e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang mAudioChannelCount = StreamInfo.AUDIO_CHANNEL_COUNT_UNKNOWN; 155e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang mHasClosedCaption = false; 156900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho String inputId = Utils.getInputIdForChannel(getContext(), channelId); 157900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho TvInputInfo inputInfo = mInputManagerHelper.getTvInputInfo(inputId); 158900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho if (inputInfo == null || !mInputManagerHelper.isAvailable(inputInfo)) { 159900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho return false; 160900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 161900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mOnTuneListener = listener; 162900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mChannelId = channelId; 163900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho if (!inputInfo.equals(mInputInfo)) { 1649bb548ba08d7e222f276287fead545c6a11704d8Jae Seo reset(); 165900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho // TODO: It is a hack to wait to release a surface at TIS. If there is a way to 166900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho // know when the surface is released at TIS, we don't need this hack. 167900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho try { 168900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho Thread.sleep(DELAY_FOR_SURFACE_RELEASE); 169900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } catch (InterruptedException e) { 170900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho e.printStackTrace(); 171900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 172900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mInputInfo = inputInfo; 1739bb548ba08d7e222f276287fead545c6a11704d8Jae Seo } 1749bb548ba08d7e222f276287fead545c6a11704d8Jae Seo setTvInputListener(mListener); 1759bb548ba08d7e222f276287fead545c6a11704d8Jae Seo tune(mInputInfo.getId(), Utils.getChannelUri(mChannelId)); 1769bb548ba08d7e222f276287fead545c6a11704d8Jae Seo if (mOnTuneListener != null) { 1779bb548ba08d7e222f276287fead545c6a11704d8Jae Seo // TODO: Add a callback for tune complete and call onTuned when it was successful. 1789bb548ba08d7e222f276287fead545c6a11704d8Jae Seo mOnTuneListener.onTuned(true, mChannelId); 179900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 180900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho return true; 181900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 182900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 183900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public TvInputInfo getCurrentTvInputInfo() { 184900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho return mInputInfo; 185900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 186900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 187900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public long getCurrentChannelId() { 188900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho return mChannelId; 189900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 190900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 191b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang public void setPip(boolean isPip) { 192b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang mSurface.setZOrderMediaOverlay(isPip); 193b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang } 194b47a0ad3227b940175fa4ecfe5c4113da72c8237Dongwon Kang 195561696c364ee330f4316544f1f85498393883526Jae Seo @Override 196561696c364ee330f4316544f1f85498393883526Jae Seo public void setStreamVolume(float volume) { 197900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho if (!mStarted) { 198900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho throw new IllegalStateException("TvView isn't started"); 199900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 200561696c364ee330f4316544f1f85498393883526Jae Seo if (DEBUG) 201561696c364ee330f4316544f1f85498393883526Jae Seo Log.d(TAG, "setStreamVolume " + volume); 202900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho mVolume = volume; 203561696c364ee330f4316544f1f85498393883526Jae Seo super.setStreamVolume(volume); 204900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 205900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho 206900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho public interface OnTuneListener { 207900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho void onTuned(boolean success, long channelId); 208900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho void onUnexpectedStop(long channelId); 20921abb13274f379e69c3c86d51e493122cccca345Dongwon Kang void onStreamInfoChanged(StreamInfo info); 21021abb13274f379e69c3c86d51e493122cccca345Dongwon Kang } 21121abb13274f379e69c3c86d51e493122cccca345Dongwon Kang 21221abb13274f379e69c3c86d51e493122cccca345Dongwon Kang @Override 21321abb13274f379e69c3c86d51e493122cccca345Dongwon Kang public int getVideoDefinitionLevel() { 21421abb13274f379e69c3c86d51e493122cccca345Dongwon Kang return mVideoFormat; 215900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho } 216e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang 217e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang @Override 218e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang public int getAudioChannelCount() { 219e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang return mAudioChannelCount; 220e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang } 221e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang 222e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang @Override 223e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang public boolean hasClosedCaption() { 224e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang return mHasClosedCaption; 225e51a084c2518f17cee43c86e2f9df907d1f2cafbDongwon Kang } 226900cc7509f1edf86db9ba1e4b71b7d1096769a0aYoungsang Cho} 227