aboutsummaryrefslogtreecommitdiff
path: root/src/com/android/tv/dvr/ui/playback/DvrPlayer.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/tv/dvr/ui/playback/DvrPlayer.java')
-rw-r--r--src/com/android/tv/dvr/ui/playback/DvrPlayer.java361
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
+}