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 //#define LOG_NDEBUG 0 18 #define LOG_TAG "MediaClock" 19 #include <utils/Log.h> 20 21 #include <media/stagefright/MediaClock.h> 22 23 #include <media/stagefright/foundation/ADebug.h> 24 #include <media/stagefright/foundation/ALooper.h> 25 26 namespace android { 27 28 MediaClock::MediaClock() 29 : mAnchorTimeMediaUs(-1), 30 mAnchorTimeRealUs(-1), 31 mMaxTimeMediaUs(INT64_MAX), 32 mStartingTimeMediaUs(-1), 33 mPlaybackRate(1.0) { 34 } 35 36 MediaClock::~MediaClock() { 37 } 38 39 void MediaClock::setStartingTimeMedia(int64_t startingTimeMediaUs) { 40 Mutex::Autolock autoLock(mLock); 41 mStartingTimeMediaUs = startingTimeMediaUs; 42 } 43 44 void MediaClock::clearAnchor() { 45 Mutex::Autolock autoLock(mLock); 46 mAnchorTimeMediaUs = -1; 47 mAnchorTimeRealUs = -1; 48 } 49 50 void MediaClock::updateAnchor( 51 int64_t anchorTimeMediaUs, 52 int64_t anchorTimeRealUs, 53 int64_t maxTimeMediaUs) { 54 if (anchorTimeMediaUs < 0 || anchorTimeRealUs < 0) { 55 ALOGW("reject anchor time since it is negative."); 56 return; 57 } 58 59 Mutex::Autolock autoLock(mLock); 60 int64_t nowUs = ALooper::GetNowUs(); 61 int64_t nowMediaUs = 62 anchorTimeMediaUs + (nowUs - anchorTimeRealUs) * (double)mPlaybackRate; 63 if (nowMediaUs < 0) { 64 ALOGW("reject anchor time since it leads to negative media time."); 65 return; 66 } 67 mAnchorTimeRealUs = nowUs; 68 mAnchorTimeMediaUs = nowMediaUs; 69 mMaxTimeMediaUs = maxTimeMediaUs; 70 } 71 72 void MediaClock::updateMaxTimeMedia(int64_t maxTimeMediaUs) { 73 Mutex::Autolock autoLock(mLock); 74 mMaxTimeMediaUs = maxTimeMediaUs; 75 } 76 77 void MediaClock::setPlaybackRate(float rate) { 78 CHECK_GE(rate, 0.0); 79 Mutex::Autolock autoLock(mLock); 80 if (mAnchorTimeRealUs == -1) { 81 mPlaybackRate = rate; 82 return; 83 } 84 85 int64_t nowUs = ALooper::GetNowUs(); 86 mAnchorTimeMediaUs += (nowUs - mAnchorTimeRealUs) * (double)mPlaybackRate; 87 if (mAnchorTimeMediaUs < 0) { 88 ALOGW("setRate: anchor time should not be negative, set to 0."); 89 mAnchorTimeMediaUs = 0; 90 } 91 mAnchorTimeRealUs = nowUs; 92 mPlaybackRate = rate; 93 } 94 95 float MediaClock::getPlaybackRate() const { 96 Mutex::Autolock autoLock(mLock); 97 return mPlaybackRate; 98 } 99 100 status_t MediaClock::getMediaTime( 101 int64_t realUs, int64_t *outMediaUs, bool allowPastMaxTime) const { 102 if (outMediaUs == NULL) { 103 return BAD_VALUE; 104 } 105 106 Mutex::Autolock autoLock(mLock); 107 return getMediaTime_l(realUs, outMediaUs, allowPastMaxTime); 108 } 109 110 status_t MediaClock::getMediaTime_l( 111 int64_t realUs, int64_t *outMediaUs, bool allowPastMaxTime) const { 112 if (mAnchorTimeRealUs == -1) { 113 return NO_INIT; 114 } 115 116 int64_t mediaUs = mAnchorTimeMediaUs 117 + (realUs - mAnchorTimeRealUs) * (double)mPlaybackRate; 118 if (mediaUs > mMaxTimeMediaUs && !allowPastMaxTime) { 119 mediaUs = mMaxTimeMediaUs; 120 } 121 if (mediaUs < mStartingTimeMediaUs) { 122 mediaUs = mStartingTimeMediaUs; 123 } 124 if (mediaUs < 0) { 125 mediaUs = 0; 126 } 127 *outMediaUs = mediaUs; 128 return OK; 129 } 130 131 status_t MediaClock::getRealTimeFor( 132 int64_t targetMediaUs, int64_t *outRealUs) const { 133 if (outRealUs == NULL) { 134 return BAD_VALUE; 135 } 136 137 Mutex::Autolock autoLock(mLock); 138 if (mPlaybackRate == 0.0) { 139 return NO_INIT; 140 } 141 142 int64_t nowUs = ALooper::GetNowUs(); 143 int64_t nowMediaUs; 144 status_t status = 145 getMediaTime_l(nowUs, &nowMediaUs, true /* allowPastMaxTime */); 146 if (status != OK) { 147 return status; 148 } 149 *outRealUs = (targetMediaUs - nowMediaUs) / (double)mPlaybackRate + nowUs; 150 return OK; 151 } 152 153 } // namespace android 154