aboutsummaryrefslogtreecommitdiff
path: root/src/com/android/tv/dvr/DvrPlayer.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/tv/dvr/DvrPlayer.java')
-rw-r--r--src/com/android/tv/dvr/DvrPlayer.java425
1 files changed, 0 insertions, 425 deletions
diff --git a/src/com/android/tv/dvr/DvrPlayer.java b/src/com/android/tv/dvr/DvrPlayer.java
deleted file mode 100644
index 5656655c..00000000
--- a/src/com/android/tv/dvr/DvrPlayer.java
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.tv.dvr;
-
-import android.media.PlaybackParams;
-import android.media.tv.TvContentRating;
-import android.media.tv.TvInputManager;
-import android.media.tv.TvTrackInfo;
-import android.media.tv.TvView;
-import android.media.session.PlaybackState;
-import android.util.Log;
-
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-public class DvrPlayer {
- private static final String TAG = "DvrPlayer";
- private static final boolean DEBUG = false;
-
- /**
- * 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.
- */
- 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 RecordedProgram mProgram;
- private long mInitialSeekPositionMs;
- private final TvView mTvView;
- private DvrPlayerCallback mCallback;
- private AspectRatioChangedListener mAspectRatioChangedListener;
- private ContentBlockedListener mContentBlockedListener;
- private float mAspectRatio = Float.NaN;
- private int mPlaybackState = PlaybackState.STATE_NONE;
- private long mTimeShiftCurrentPositionMs;
- private boolean mPauseOnPrepared;
- private final PlaybackParams mPlaybackParams = new PlaybackParams();
- private final DvrPlayerCallback mEmptyCallback = new DvrPlayerCallback();
- private long mStartPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
- private boolean mTimeShiftPlayAvailable;
-
- 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}.
- */
- 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 AspectRatioChangedListener {
- /**
- * Called when the Video's aspect ratio is changed.
- */
- void onAspectRatioChanged(float videoAspectRatio);
- }
-
- public interface ContentBlockedListener {
- /**
- * Called when the Video's aspect ratio is changed.
- */
- void onContentBlocked(TvContentRating rating);
- }
-
- public DvrPlayer(TvView tvView) {
- mTvView = tvView;
- mPlaybackParams.setSpeed(1.0f);
- setTvViewCallbacks();
- setCallback(null);
- }
-
- /**
- * Prepares playback.
- *
- * @param doPlay indicates DVR player do or do not start playback after media is prepared.
- */
- public void prepare(boolean doPlay) throws IllegalStateException {
- if (DEBUG) Log.d(TAG, "prepare()");
- if (mProgram == null) {
- throw new IllegalStateException("Recorded program not set");
- } else if (mPlaybackState != PlaybackState.STATE_NONE) {
- throw new IllegalStateException("Playback is already prepared");
- }
- mTvView.timeShiftPlay(mProgram.getInputId(), mProgram.getUri());
- mPlaybackState = PlaybackState.STATE_CONNECTING;
- mPauseOnPrepared = !doPlay;
- mCallback.onPlaybackStateChanged(mPlaybackState, 1);
- }
-
- /**
- * Resumes playback.
- */
- public void play() throws IllegalStateException {
- if (DEBUG) Log.d(TAG, "play()");
- if (!isPlaybackPrepared()) {
- throw new IllegalStateException("Recorded program not set or video not ready yet");
- }
- switch (mPlaybackState) {
- case PlaybackState.STATE_FAST_FORWARDING:
- case PlaybackState.STATE_REWINDING:
- setPlaybackSpeed(1);
- break;
- default:
- mTvView.timeShiftResume();
- }
- mPlaybackState = PlaybackState.STATE_PLAYING;
- mCallback.onPlaybackStateChanged(mPlaybackState, 1);
- }
-
- /**
- * Pauses playback.
- */
- public void pause() throws IllegalStateException {
- if (DEBUG) Log.d(TAG, "pause()");
- if (!isPlaybackPrepared()) {
- throw new IllegalStateException("Recorded program not set or playback not started yet");
- }
- switch (mPlaybackState) {
- case PlaybackState.STATE_FAST_FORWARDING:
- case PlaybackState.STATE_REWINDING:
- setPlaybackSpeed(1);
- // falls through
- case PlaybackState.STATE_PLAYING:
- mTvView.timeShiftPause();
- mPlaybackState = PlaybackState.STATE_PAUSED;
- break;
- default:
- break;
- }
- mCallback.onPlaybackStateChanged(mPlaybackState, 1);
- }
-
- /**
- * 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()");
- if (!isPlaybackPrepared()) {
- throw new IllegalStateException("Recorded program not set or playback not started yet");
- }
- if (speed <= 0) {
- throw new IllegalArgumentException("Speed cannot be negative or 0");
- }
- if (mTimeShiftCurrentPositionMs >= mProgram.getDurationMillis() - SEEK_POSITION_MARGIN_MS) {
- return;
- }
- speed = Math.min(speed, MAX_FAST_FORWARD_SPEED);
- if (DEBUG) Log.d(TAG, "Let's play with speed: " + speed);
- setPlaybackSpeed(speed);
- mPlaybackState = PlaybackState.STATE_FAST_FORWARDING;
- mCallback.onPlaybackStateChanged(mPlaybackState, 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()");
- if (!isPlaybackPrepared()) {
- throw new IllegalStateException("Recorded program not set or playback not started yet");
- }
- if (speed <= 0) {
- throw new IllegalArgumentException("Speed cannot be negative or 0");
- }
- if (mTimeShiftCurrentPositionMs <= REWIND_POSITION_MARGIN_MS) {
- return;
- }
- speed = Math.min(speed, MAX_REWIND_SPEED);
- if (DEBUG) Log.d(TAG, "Let's play with speed: " + speed);
- setPlaybackSpeed(-speed);
- mPlaybackState = PlaybackState.STATE_REWINDING;
- mCallback.onPlaybackStateChanged(mPlaybackState, speed);
- }
-
- /**
- * Seeks playback to the specified position.
- */
- public void seekTo(long positionMs) throws IllegalStateException {
- if (DEBUG) Log.d(TAG, "seekTo()");
- if (!isPlaybackPrepared()) {
- throw new IllegalStateException("Recorded program not set or playback not started yet");
- }
- if (mProgram == null || mPlaybackState == PlaybackState.STATE_NONE) {
- return;
- }
- 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) {
- mPlaybackState = PlaybackState.STATE_PLAYING;
- mTvView.timeShiftResume();
- mCallback.onPlaybackStateChanged(mPlaybackState, 1);
- }
- }
-
- /**
- * Resets playback.
- */
- public void reset() {
- if (DEBUG) Log.d(TAG, "reset()");
- mCallback.onPlaybackStateChanged(PlaybackState.STATE_NONE, 1);
- mPlaybackState = PlaybackState.STATE_NONE;
- mTvView.reset();
- mTimeShiftPlayAvailable = false;
- mStartPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
- mTimeShiftCurrentPositionMs = 0;
- mPlaybackParams.setSpeed(1.0f);
- mProgram = null;
- }
-
- /**
- * Sets callbacks for playback.
- */
- public void setCallback(DvrPlayerCallback callback) {
- if (callback != null) {
- mCallback = callback;
- } else {
- mCallback = mEmptyCallback;
- }
- }
-
- /**
- * Sets listener to aspect ratio changing.
- */
- public void setAspectRatioChangedListener(AspectRatioChangedListener listener) {
- mAspectRatioChangedListener = listener;
- }
-
- /**
- * Sets listener to content blocking.
- */
- public void setContentBlockedListener(ContentBlockedListener listener) {
- mContentBlockedListener = listener;
- }
-
- /**
- * 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;
- }
- if (mPlaybackState != PlaybackState.STATE_NONE) {
- reset();
- }
- mInitialSeekPositionMs = initialSeekPositionMs;
- mProgram = program;
- }
-
- /**
- * Returns the recorded program now playing.
- */
- public RecordedProgram getProgram() {
- return mProgram;
- }
-
- /**
- * Returns the currrent playback posistion in msecs.
- */
- public long getPlaybackPosition() {
- return mTimeShiftCurrentPositionMs;
- }
-
- /**
- * Returns the playback speed currently used.
- */
- public int getPlaybackSpeed() {
- return (int) mPlaybackParams.getSpeed();
- }
-
- /**
- * Returns the playback state defined in {@link android.media.session.PlaybackState}.
- */
- public int getPlaybackState() {
- return mPlaybackState;
- }
-
- /**
- * Returns if playback of the recorded program is started.
- */
- public boolean isPlaybackPrepared() {
- return mPlaybackState != PlaybackState.STATE_NONE
- && mPlaybackState != PlaybackState.STATE_CONNECTING;
- }
-
- private void setPlaybackSpeed(int speed) {
- mPlaybackParams.setSpeed(speed);
- mTvView.timeShiftSetPlaybackParams(mPlaybackParams);
- }
-
- private long getRealSeekPosition(long seekPositionMs, long endMarginMs) {
- return Math.max(0, Math.min(seekPositionMs, mProgram.getDurationMillis() - endMarginMs));
- }
-
- 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();
- }
- }
-
- @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;
- }
- }
-
- @Override
- public void onTrackSelected(String inputId, int type, String trackId) {
- if (trackId == null || type != TvTrackInfo.TYPE_VIDEO
- || mAspectRatioChangedListener == null) {
- return;
- }
- List<TvTrackInfo> trackInfos = mTvView.getTracks(TvTrackInfo.TYPE_VIDEO);
- if (trackInfos != null) {
- for (TvTrackInfo trackInfo : trackInfos) {
- if (trackInfo.getId().equals(trackId)) {
- float videoAspectRatio = trackInfo.getVideoPixelAspectRatio()
- * trackInfo.getVideoWidth() / trackInfo.getVideoHeight();
- if (DEBUG) Log.d(TAG, "Aspect Ratio: " + videoAspectRatio);
- if (!Float.isNaN(videoAspectRatio)
- && mAspectRatio != videoAspectRatio) {
- mAspectRatioChangedListener
- .onAspectRatioChanged(videoAspectRatio);
- mAspectRatio = videoAspectRatio;
- return;
- }
- }
- }
- }
- }
-
- @Override
- public void onContentBlocked(String inputId, TvContentRating rating) {
- if (mContentBlockedListener != null) {
- mContentBlockedListener.onContentBlocked(rating);
- }
- }
- });
- }
-
- private void resumeToWatchedPositionIfNeeded() {
- if (mInitialSeekPositionMs != TvInputManager.TIME_SHIFT_INVALID_TIME) {
- mTvView.timeShiftSeekTo(getRealSeekPosition(mInitialSeekPositionMs,
- SEEK_POSITION_MARGIN_MS) + mStartPositionMs);
- mInitialSeekPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
- }
- if (mPauseOnPrepared) {
- mTvView.timeShiftPause();
- mPlaybackState = PlaybackState.STATE_PAUSED;
- mPauseOnPrepared = false;
- } else {
- mTvView.timeShiftResume();
- mPlaybackState = PlaybackState.STATE_PLAYING;
- }
- mCallback.onPlaybackStateChanged(mPlaybackState, 1);
- }
-} \ No newline at end of file