Home | History | Annotate | Download | only in libstagefright
      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