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 android.os.SystemClock; 20 import com.android.tv.common.SoftPreconditions; 21 22 /** 23 * Copy of {@link com.google.android.exoplayer.MediaClock}. 24 * 25 * <p>A simple clock for tracking the progression of media time. The clock can be started, stopped 26 * and its time can be set and retrieved. When started, this clock is based on {@link 27 * SystemClock#elapsedRealtime()}. 28 */ 29 /* package */ class AudioClock { 30 private boolean mStarted; 31 32 /** The media time when the clock was last set or stopped. */ 33 private long mPositionUs; 34 35 /** 36 * The difference between {@link SystemClock#elapsedRealtime()} and {@link #mPositionUs} when 37 * the clock was last set or mStarted. 38 */ 39 private long mDeltaUs; 40 41 private float mPlaybackSpeed = 1.0f; 42 private long mDeltaUpdatedTimeUs; 43 44 /** Starts the clock. Does nothing if the clock is already started. */ start()45 public void start() { 46 if (!mStarted) { 47 mStarted = true; 48 mDeltaUs = elapsedRealtimeMinus(mPositionUs); 49 mDeltaUpdatedTimeUs = SystemClock.elapsedRealtime() * 1000; 50 } 51 } 52 53 /** Stops the clock. Does nothing if the clock is already stopped. */ stop()54 public void stop() { 55 if (mStarted) { 56 mPositionUs = elapsedRealtimeMinus(mDeltaUs); 57 mStarted = false; 58 } 59 } 60 61 /** @param timeUs The position to set in microseconds. */ setPositionUs(long timeUs)62 public void setPositionUs(long timeUs) { 63 this.mPositionUs = timeUs; 64 mDeltaUs = elapsedRealtimeMinus(timeUs); 65 mDeltaUpdatedTimeUs = SystemClock.elapsedRealtime() * 1000; 66 } 67 68 /** @return The current position in microseconds. */ getPositionUs()69 public long getPositionUs() { 70 if (!mStarted) { 71 return mPositionUs; 72 } 73 if (mPlaybackSpeed != 1.0f) { 74 long elapsedTimeFromPlaybackSpeedChanged = 75 SystemClock.elapsedRealtime() * 1000 - mDeltaUpdatedTimeUs; 76 return elapsedRealtimeMinus(mDeltaUs) 77 + (long) ((mPlaybackSpeed - 1.0f) * elapsedTimeFromPlaybackSpeedChanged); 78 } else { 79 return elapsedRealtimeMinus(mDeltaUs); 80 } 81 } 82 83 /** Sets playback speed. {@code speed} should be positive. */ setPlaybackSpeed(float speed)84 public void setPlaybackSpeed(float speed) { 85 SoftPreconditions.checkState(speed > 0); 86 mDeltaUs = elapsedRealtimeMinus(getPositionUs()); 87 mDeltaUpdatedTimeUs = SystemClock.elapsedRealtime() * 1000; 88 mPlaybackSpeed = speed; 89 } 90 elapsedRealtimeMinus(long toSubtractUs)91 private long elapsedRealtimeMinus(long toSubtractUs) { 92 return SystemClock.elapsedRealtime() * 1000 - toSubtractUs; 93 } 94 } 95