1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tv.tuner.exoplayer.audio; 18 19 import com.android.tv.common.SoftPreconditions; 20 21 import android.os.SystemClock; 22 23 /** 24 * Copy of {@link com.google.android.exoplayer.MediaClock}. 25 * <p> 26 * A simple clock for tracking the progression of media time. The clock can be started, stopped and 27 * its time can be set and retrieved. When started, this clock is based on 28 * {@link SystemClock#elapsedRealtime()}. 29 */ 30 /* package */ class AudioClock { 31 private boolean mStarted; 32 33 /** 34 * The media time when the clock was last set or stopped. 35 */ 36 private long mPositionUs; 37 38 /** 39 * The difference between {@link SystemClock#elapsedRealtime()} and {@link #mPositionUs} 40 * when the clock was last set or mStarted. 41 */ 42 private long mDeltaUs; 43 44 private float mPlaybackSpeed = 1.0f; 45 private long mDeltaUpdatedTimeUs; 46 47 /** 48 * Starts the clock. Does nothing if the clock is already started. 49 */ start()50 public void start() { 51 if (!mStarted) { 52 mStarted = true; 53 mDeltaUs = elapsedRealtimeMinus(mPositionUs); 54 mDeltaUpdatedTimeUs = SystemClock.elapsedRealtime() * 1000; 55 } 56 } 57 58 /** 59 * Stops the clock. Does nothing if the clock is already stopped. 60 */ stop()61 public void stop() { 62 if (mStarted) { 63 mPositionUs = elapsedRealtimeMinus(mDeltaUs); 64 mStarted = false; 65 } 66 } 67 68 /** 69 * @param timeUs The position to set in microseconds. 70 */ setPositionUs(long timeUs)71 public void setPositionUs(long timeUs) { 72 this.mPositionUs = timeUs; 73 mDeltaUs = elapsedRealtimeMinus(timeUs); 74 mDeltaUpdatedTimeUs = SystemClock.elapsedRealtime() * 1000; 75 } 76 77 /** 78 * @return The current position in microseconds. 79 */ getPositionUs()80 public long getPositionUs() { 81 if (!mStarted) { 82 return mPositionUs; 83 } 84 if (mPlaybackSpeed != 1.0f) { 85 long elapsedTimeFromPlaybackSpeedChanged = SystemClock.elapsedRealtime() * 1000 86 - mDeltaUpdatedTimeUs; 87 return elapsedRealtimeMinus(mDeltaUs) 88 + (long) ((mPlaybackSpeed - 1.0f) * elapsedTimeFromPlaybackSpeedChanged); 89 } else { 90 return elapsedRealtimeMinus(mDeltaUs); 91 } 92 } 93 94 /** 95 * Sets playback speed. {@code speed} should be positive. 96 */ setPlaybackSpeed(float speed)97 public void setPlaybackSpeed(float speed) { 98 SoftPreconditions.checkState(speed > 0); 99 mDeltaUs = elapsedRealtimeMinus(getPositionUs()); 100 mDeltaUpdatedTimeUs = SystemClock.elapsedRealtime() * 1000; 101 mPlaybackSpeed = speed; 102 } 103 elapsedRealtimeMinus(long toSubtractUs)104 private long elapsedRealtimeMinus(long toSubtractUs) { 105 return SystemClock.elapsedRealtime() * 1000 - toSubtractUs; 106 } 107 } 108