diff options
Diffstat (limited to 'src/com/android/tv/dvr/ui/playback/DvrPlayer.java')
-rw-r--r-- | src/com/android/tv/dvr/ui/playback/DvrPlayer.java | 361 |
1 files changed, 161 insertions, 200 deletions
diff --git a/src/com/android/tv/dvr/ui/playback/DvrPlayer.java b/src/com/android/tv/dvr/ui/playback/DvrPlayer.java index 7226c666..85bb31b2 100644 --- a/src/com/android/tv/dvr/ui/playback/DvrPlayer.java +++ b/src/com/android/tv/dvr/ui/playback/DvrPlayer.java @@ -24,9 +24,7 @@ import android.media.tv.TvTrackInfo; import android.media.tv.TvView; import android.text.TextUtils; import android.util.Log; - import com.android.tv.dvr.data.RecordedProgram; - import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; @@ -35,17 +33,13 @@ class DvrPlayer { private static final String TAG = "DvrPlayer"; private static final boolean DEBUG = false; - /** - * The max rewinding speed supported by DVR player. - */ + /** The max rewinding speed supported by DVR player. */ public static final int MAX_REWIND_SPEED = 256; - /** - * The max fast-forwarding speed supported by DVR player. - */ + /** The max fast-forwarding speed supported by DVR player. */ public static final int MAX_FAST_FORWARD_SPEED = 256; private static final long SEEK_POSITION_MARGIN_MS = TimeUnit.SECONDS.toMillis(2); - private static final long REWIND_POSITION_MARGIN_MS = 32; // Workaround value. b/29994826 + private static final long REWIND_POSITION_MARGIN_MS = 32; // Workaround value. b/29994826 private RecordedProgram mProgram; private long mInitialSeekPositionMs; @@ -71,49 +65,39 @@ class DvrPlayer { public static class DvrPlayerCallback { /** - * Called when the playback position is changed. The normal updating frequency is - * around 1 sec., which is restricted to the implementation of - * {@link android.media.tv.TvInputService}. + * Called when the playback position is changed. The normal updating frequency is around 1 + * sec., which is restricted to the implementation of {@link + * android.media.tv.TvInputService}. */ - public void onPlaybackPositionChanged(long positionMs) { } - /** - * Called when the playback state or the playback speed is changed. - */ - public void onPlaybackStateChanged(int playbackState, int playbackSpeed) { } - /** - * Called when the playback toward the end. - */ - public void onPlaybackEnded() { } + public void onPlaybackPositionChanged(long positionMs) {} + /** Called when the playback state or the playback speed is changed. */ + public void onPlaybackStateChanged(int playbackState, int playbackSpeed) {} + /** Called when the playback toward the end. */ + public void onPlaybackEnded() {} } public interface OnAspectRatioChangedListener { /** * Called when the Video's aspect ratio is changed. * - * @param videoAspectRatio The aspect ratio of video. 0 stands for unknown ratios. - * Listeners should handle it carefully. + * @param videoAspectRatio The aspect ratio of video. 0 stands for unknown ratios. Listeners + * should handle it carefully. */ void onAspectRatioChanged(float videoAspectRatio); } public interface OnContentBlockedListener { - /** - * Called when the Video's aspect ratio is changed. - */ + /** Called when the Video's aspect ratio is changed. */ void onContentBlocked(TvContentRating rating); } public interface OnTracksAvailabilityChangedListener { - /** - * Called when the Video's subtitle or audio tracks are changed. - */ + /** Called when the Video's subtitle or audio tracks are changed. */ void onTracksAvailabilityChanged(boolean hasClosedCaption, boolean hasMultiAudio); } public interface OnTrackSelectedListener { - /** - * Called when certain subtitle or audio track is selected. - */ + /** Called when certain subtitle or audio track is selected. */ void onTrackSelected(String selectedTrackId); } @@ -143,9 +127,7 @@ class DvrPlayer { mCallback.onPlaybackStateChanged(mPlaybackState, 1); } - /** - * Resumes playback. - */ + /** Resumes playback. */ public void play() throws IllegalStateException { if (DEBUG) Log.d(TAG, "play()"); if (!isPlaybackPrepared()) { @@ -163,9 +145,7 @@ class DvrPlayer { mCallback.onPlaybackStateChanged(mPlaybackState, 1); } - /** - * Pauses playback. - */ + /** Pauses playback. */ public void pause() throws IllegalStateException { if (DEBUG) Log.d(TAG, "pause()"); if (!isPlaybackPrepared()) { @@ -187,8 +167,8 @@ class DvrPlayer { } /** - * Fast-forwards playback with the given speed. If the given speed is larger than - * {@value #MAX_FAST_FORWARD_SPEED}, uses {@value #MAX_FAST_FORWARD_SPEED}. + * Fast-forwards playback with the given speed. If the given speed is larger than {@value + * #MAX_FAST_FORWARD_SPEED}, uses {@value #MAX_FAST_FORWARD_SPEED}. */ public void fastForward(int speed) throws IllegalStateException { if (DEBUG) Log.d(TAG, "fastForward()"); @@ -209,8 +189,8 @@ class DvrPlayer { } /** - * Rewinds playback with the given speed. If the given speed is larger than - * {@value #MAX_REWIND_SPEED}, uses {@value #MAX_REWIND_SPEED}. + * Rewinds playback with the given speed. If the given speed is larger than {@value + * #MAX_REWIND_SPEED}, uses {@value #MAX_REWIND_SPEED}. */ public void rewind(int speed) throws IllegalStateException { if (DEBUG) Log.d(TAG, "rewind()"); @@ -230,9 +210,7 @@ class DvrPlayer { mCallback.onPlaybackStateChanged(mPlaybackState, speed); } - /** - * Seeks playback to the specified position. - */ + /** Seeks playback to the specified position. */ public void seekTo(long positionMs) throws IllegalStateException { if (DEBUG) Log.d(TAG, "seekTo()"); if (!isPlaybackPrepared()) { @@ -244,17 +222,15 @@ class DvrPlayer { positionMs = getRealSeekPosition(positionMs, SEEK_POSITION_MARGIN_MS); if (DEBUG) Log.d(TAG, "Now: " + getPlaybackPosition() + ", shift to: " + positionMs); mTvView.timeShiftSeekTo(positionMs + mStartPositionMs); - if (mPlaybackState == PlaybackState.STATE_FAST_FORWARDING || - mPlaybackState == PlaybackState.STATE_REWINDING) { + if (mPlaybackState == PlaybackState.STATE_FAST_FORWARDING + || mPlaybackState == PlaybackState.STATE_REWINDING) { mPlaybackState = PlaybackState.STATE_PLAYING; mTvView.timeShiftResume(); mCallback.onPlaybackStateChanged(mPlaybackState, 1); } } - /** - * Resets playback. - */ + /** Resets playback. */ public void reset() { if (DEBUG) Log.d(TAG, "reset()"); mCallback.onPlaybackStateChanged(PlaybackState.STATE_NONE, 1); @@ -269,9 +245,7 @@ class DvrPlayer { mSelectedSubtitleTrackId = null; } - /** - * Sets callbacks for playback. - */ + /** Sets callbacks for playback. */ public void setCallback(DvrPlayerCallback callback) { if (callback != null) { mCallback = callback; @@ -280,23 +254,17 @@ class DvrPlayer { } } - /** - * Sets the listener to aspect ratio changing. - */ + /** Sets the listener to aspect ratio changing. */ public void setOnAspectRatioChangedListener(OnAspectRatioChangedListener listener) { mOnAspectRatioChangedListener = listener; } - /** - * Sets the listener to content blocking. - */ + /** Sets the listener to content blocking. */ public void setOnContentBlockedListener(OnContentBlockedListener listener) { mOnContentBlockedListener = listener; } - /** - * Sets the listener to tracks changing. - */ + /** Sets the listener to tracks changing. */ public void setOnTracksAvailabilityChangedListener( OnTracksAvailabilityChangedListener listener) { mOnTracksAvailabilityChangedListener = listener; @@ -305,8 +273,8 @@ class DvrPlayer { /** * Sets the listener to tracks of the given type being selected. * - * @param trackType should be either {@link TvTrackInfo#TYPE_AUDIO} - * or {@link TvTrackInfo#TYPE_SUBTITLE}. + * @param trackType should be either {@link TvTrackInfo#TYPE_AUDIO} or {@link + * TvTrackInfo#TYPE_SUBTITLE}. */ public void setOnTrackSelectedListener(int trackType, OnTrackSelectedListener listener) { if (trackType == TvTrackInfo.TYPE_AUDIO) { @@ -316,9 +284,7 @@ class DvrPlayer { } } - /** - * Gets the listener to tracks of the given type being selected. - */ + /** Gets the listener to tracks of the given type being selected. */ public OnTrackSelectedListener getOnTrackSelectedListener(int trackType) { if (trackType == TvTrackInfo.TYPE_AUDIO) { return mOnAudioTrackSelectedListener; @@ -328,9 +294,7 @@ class DvrPlayer { return null; } - /** - * Sets recorded programs for playback. If the player is playing another program, stops it. - */ + /** Sets recorded programs for playback. If the player is playing another program, stops it. */ public void setProgram(RecordedProgram program, long initialSeekPositionMs) { if (mProgram != null && mProgram.equals(program)) { return; @@ -342,51 +306,37 @@ class DvrPlayer { mProgram = program; } - /** - * Returns the recorded program now playing. - */ + /** Returns the recorded program now playing. */ public RecordedProgram getProgram() { return mProgram; } - /** - * Returns the currrent playback posistion in msecs. - */ + /** Returns the currrent playback posistion in msecs. */ public long getPlaybackPosition() { return mTimeShiftCurrentPositionMs; } - /** - * Returns the playback speed currently used. - */ + /** Returns the playback speed currently used. */ public int getPlaybackSpeed() { return (int) mPlaybackParams.getSpeed(); } - /** - * Returns the playback state defined in {@link android.media.session.PlaybackState}. - */ + /** Returns the playback state defined in {@link android.media.session.PlaybackState}. */ public int getPlaybackState() { return mPlaybackState; } - /** - * Returns the subtitle tracks of the current playback. - */ + /** Returns the subtitle tracks of the current playback. */ public ArrayList<TvTrackInfo> getSubtitleTracks() { return new ArrayList<>(mTvView.getTracks(TvTrackInfo.TYPE_SUBTITLE)); } - /** - * Returns the audio tracks of the current playback. - */ + /** Returns the audio tracks of the current playback. */ public ArrayList<TvTrackInfo> getAudioTracks() { return new ArrayList<>(mTvView.getTracks(TvTrackInfo.TYPE_AUDIO)); } - /** - * Returns the ID of the selected track of the given type. - */ + /** Returns the ID of the selected track of the given type. */ public String getSelectedTrackId(int trackType) { if (trackType == TvTrackInfo.TYPE_AUDIO) { return mSelectedAudioTrackId; @@ -396,9 +346,7 @@ class DvrPlayer { return null; } - /** - * Returns if playback of the recorded program is started. - */ + /** Returns if playback of the recorded program is started. */ public boolean isPlaybackPrepared() { return mPlaybackState != PlaybackState.STATE_NONE && mPlaybackState != PlaybackState.STATE_CONNECTING; @@ -449,125 +397,138 @@ class DvrPlayer { } private void setTvViewCallbacks() { - mTvView.setTimeShiftPositionCallback(new TvView.TimeShiftPositionCallback() { - @Override - public void onTimeShiftStartPositionChanged(String inputId, long timeMs) { - if (DEBUG) Log.d(TAG, "onTimeShiftStartPositionChanged:" + timeMs); - mStartPositionMs = timeMs; - if (mTimeShiftPlayAvailable) { - resumeToWatchedPositionIfNeeded(); - } - } + mTvView.setTimeShiftPositionCallback( + new TvView.TimeShiftPositionCallback() { + @Override + public void onTimeShiftStartPositionChanged(String inputId, long timeMs) { + if (DEBUG) Log.d(TAG, "onTimeShiftStartPositionChanged:" + timeMs); + mStartPositionMs = timeMs; + if (mTimeShiftPlayAvailable) { + resumeToWatchedPositionIfNeeded(); + } + } - @Override - public void onTimeShiftCurrentPositionChanged(String inputId, long timeMs) { - if (DEBUG) Log.d(TAG, "onTimeShiftCurrentPositionChanged: " + timeMs); - if (!mTimeShiftPlayAvailable) { - // Workaround of b/31436263 - return; - } - // Workaround of b/32211561, TIF won't report start position when TIS report - // its start position as 0. In that case, we have to do the prework of playback - // on the first time we get current position, and the start position should be 0 - // at that time. - if (mStartPositionMs == TvInputManager.TIME_SHIFT_INVALID_TIME) { - mStartPositionMs = 0; - resumeToWatchedPositionIfNeeded(); - } - timeMs -= mStartPositionMs; - if (mPlaybackState == PlaybackState.STATE_REWINDING - && timeMs <= REWIND_POSITION_MARGIN_MS) { - play(); - } else { - mTimeShiftCurrentPositionMs = getRealSeekPosition(timeMs, 0); - mCallback.onPlaybackPositionChanged(mTimeShiftCurrentPositionMs); - if (timeMs >= mProgram.getDurationMillis()) { - pause(); - mCallback.onPlaybackEnded(); + @Override + public void onTimeShiftCurrentPositionChanged(String inputId, long timeMs) { + if (DEBUG) Log.d(TAG, "onTimeShiftCurrentPositionChanged: " + timeMs); + if (!mTimeShiftPlayAvailable) { + // Workaround of b/31436263 + return; + } + // Workaround of b/32211561, TIF won't report start position when TIS report + // its start position as 0. In that case, we have to do the prework of + // playback + // on the first time we get current position, and the start position should + // be 0 + // at that time. + if (mStartPositionMs == TvInputManager.TIME_SHIFT_INVALID_TIME) { + mStartPositionMs = 0; + resumeToWatchedPositionIfNeeded(); + } + timeMs -= mStartPositionMs; + if (mPlaybackState == PlaybackState.STATE_REWINDING + && timeMs <= REWIND_POSITION_MARGIN_MS) { + play(); + } else { + mTimeShiftCurrentPositionMs = getRealSeekPosition(timeMs, 0); + mCallback.onPlaybackPositionChanged(mTimeShiftCurrentPositionMs); + if (timeMs >= mProgram.getDurationMillis()) { + pause(); + mCallback.onPlaybackEnded(); + } + } } - } - } - }); - mTvView.setCallback(new TvView.TvInputCallback() { - @Override - public void onTimeShiftStatusChanged(String inputId, int status) { - if (DEBUG) Log.d(TAG, "onTimeShiftStatusChanged:" + status); - if (status == TvInputManager.TIME_SHIFT_STATUS_AVAILABLE - && mPlaybackState == PlaybackState.STATE_CONNECTING) { - mTimeShiftPlayAvailable = true; - if (mStartPositionMs != TvInputManager.TIME_SHIFT_INVALID_TIME) { - // onTimeShiftStatusChanged is sometimes called after - // onTimeShiftStartPositionChanged is called. In this case, - // resumeToWatchedPositionIfNeeded needs to be called here. - resumeToWatchedPositionIfNeeded(); + }); + mTvView.setCallback( + new TvView.TvInputCallback() { + @Override + public void onTimeShiftStatusChanged(String inputId, int status) { + if (DEBUG) Log.d(TAG, "onTimeShiftStatusChanged:" + status); + if (status == TvInputManager.TIME_SHIFT_STATUS_AVAILABLE + && mPlaybackState == PlaybackState.STATE_CONNECTING) { + mTimeShiftPlayAvailable = true; + if (mStartPositionMs != TvInputManager.TIME_SHIFT_INVALID_TIME) { + // onTimeShiftStatusChanged is sometimes called after + // onTimeShiftStartPositionChanged is called. In this case, + // resumeToWatchedPositionIfNeeded needs to be called here. + resumeToWatchedPositionIfNeeded(); + } + } } - } - } - - @Override - public void onTracksChanged(String inputId, List<TvTrackInfo> tracks) { - boolean hasClosedCaption = - !mTvView.getTracks(TvTrackInfo.TYPE_SUBTITLE).isEmpty(); - boolean hasMultiAudio = mTvView.getTracks(TvTrackInfo.TYPE_AUDIO).size() > 1; - if ((hasClosedCaption != mHasClosedCaption || hasMultiAudio != mHasMultiAudio) - && mOnTracksAvailabilityChangedListener != null) { - mOnTracksAvailabilityChangedListener - .onTracksAvailabilityChanged(hasClosedCaption, hasMultiAudio); - } - mHasClosedCaption = hasClosedCaption; - mHasMultiAudio = hasMultiAudio; - } - @Override - public void onTrackSelected(String inputId, int type, String trackId) { - if (type == TvTrackInfo.TYPE_AUDIO || type == TvTrackInfo.TYPE_SUBTITLE) { - setSelectedTrackId(type, trackId); - OnTrackSelectedListener listener = getOnTrackSelectedListener(type); - if (listener != null) { - listener.onTrackSelected(trackId); + @Override + public void onTracksChanged(String inputId, List<TvTrackInfo> tracks) { + boolean hasClosedCaption = + !mTvView.getTracks(TvTrackInfo.TYPE_SUBTITLE).isEmpty(); + boolean hasMultiAudio = + mTvView.getTracks(TvTrackInfo.TYPE_AUDIO).size() > 1; + if ((hasClosedCaption != mHasClosedCaption + || hasMultiAudio != mHasMultiAudio) + && mOnTracksAvailabilityChangedListener != null) { + mOnTracksAvailabilityChangedListener.onTracksAvailabilityChanged( + hasClosedCaption, hasMultiAudio); + } + mHasClosedCaption = hasClosedCaption; + mHasMultiAudio = hasMultiAudio; } - } else if (type == TvTrackInfo.TYPE_VIDEO && trackId != null - && mOnAspectRatioChangedListener != null) { - List<TvTrackInfo> trackInfos = mTvView.getTracks(TvTrackInfo.TYPE_VIDEO); - if (trackInfos != null) { - for (TvTrackInfo trackInfo : trackInfos) { - if (trackInfo.getId().equals(trackId)) { - float videoAspectRatio; - int videoWidth = trackInfo.getVideoWidth(); - int videoHeight = trackInfo.getVideoHeight(); - if (videoWidth > 0 && videoHeight > 0) { - videoAspectRatio = trackInfo.getVideoPixelAspectRatio() - * trackInfo.getVideoWidth() / trackInfo.getVideoHeight(); - } else { - // Aspect ratio is unknown. Pass the message to listeners. - videoAspectRatio = 0; - } - if (DEBUG) Log.d(TAG, "Aspect Ratio: " + videoAspectRatio); - if (mAspectRatio != videoAspectRatio || videoAspectRatio == 0) { - mOnAspectRatioChangedListener - .onAspectRatioChanged(videoAspectRatio); - mAspectRatio = videoAspectRatio; - return; + + @Override + public void onTrackSelected(String inputId, int type, String trackId) { + if (type == TvTrackInfo.TYPE_AUDIO || type == TvTrackInfo.TYPE_SUBTITLE) { + setSelectedTrackId(type, trackId); + OnTrackSelectedListener listener = getOnTrackSelectedListener(type); + if (listener != null) { + listener.onTrackSelected(trackId); + } + } else if (type == TvTrackInfo.TYPE_VIDEO + && trackId != null + && mOnAspectRatioChangedListener != null) { + List<TvTrackInfo> trackInfos = + mTvView.getTracks(TvTrackInfo.TYPE_VIDEO); + if (trackInfos != null) { + for (TvTrackInfo trackInfo : trackInfos) { + if (trackInfo.getId().equals(trackId)) { + float videoAspectRatio; + int videoWidth = trackInfo.getVideoWidth(); + int videoHeight = trackInfo.getVideoHeight(); + if (videoWidth > 0 && videoHeight > 0) { + videoAspectRatio = + trackInfo.getVideoPixelAspectRatio() + * trackInfo.getVideoWidth() + / trackInfo.getVideoHeight(); + } else { + // Aspect ratio is unknown. Pass the message to + // listeners. + videoAspectRatio = 0; + } + if (DEBUG) Log.d(TAG, "Aspect Ratio: " + videoAspectRatio); + if (mAspectRatio != videoAspectRatio + || videoAspectRatio == 0) { + mOnAspectRatioChangedListener.onAspectRatioChanged( + videoAspectRatio); + mAspectRatio = videoAspectRatio; + return; + } + } } } } } - } - } - @Override - public void onContentBlocked(String inputId, TvContentRating rating) { - if (mOnContentBlockedListener != null) { - mOnContentBlockedListener.onContentBlocked(rating); - } - } - }); + @Override + public void onContentBlocked(String inputId, TvContentRating rating) { + if (mOnContentBlockedListener != null) { + mOnContentBlockedListener.onContentBlocked(rating); + } + } + }); } private void resumeToWatchedPositionIfNeeded() { if (mInitialSeekPositionMs != TvInputManager.TIME_SHIFT_INVALID_TIME) { - mTvView.timeShiftSeekTo(getRealSeekPosition(mInitialSeekPositionMs, - SEEK_POSITION_MARGIN_MS) + mStartPositionMs); + mTvView.timeShiftSeekTo( + getRealSeekPosition(mInitialSeekPositionMs, SEEK_POSITION_MARGIN_MS) + + mStartPositionMs); mInitialSeekPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME; } if (mPauseOnPrepared) { @@ -580,4 +541,4 @@ class DvrPlayer { } mCallback.onPlaybackStateChanged(mPlaybackState, 1); } -}
\ No newline at end of file +} |