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 // Maximum allowed time backwards from anchor change.
     29 // If larger than this threshold, it's treated as discontinuity.
     30 static const int64_t kAnchorFluctuationAllowedUs = 10000ll;
     31 
     32 MediaClock::MediaClock()
     33     : mAnchorTimeMediaUs(-1),
     34       mAnchorTimeRealUs(-1),
     35       mMaxTimeMediaUs(INT64_MAX),
     36       mStartingTimeMediaUs(-1),
     37       mPlaybackRate(1.0) {
     38 }
     39 
     40 MediaClock::~MediaClock() {
     41 }
     42 
     43 void MediaClock::setStartingTimeMedia(int64_t startingTimeMediaUs) {
     44     Mutex::Autolock autoLock(mLock);
     45     mStartingTimeMediaUs = startingTimeMediaUs;
     46 }
     47 
     48 void MediaClock::clearAnchor() {
     49     Mutex::Autolock autoLock(mLock);
     50     mAnchorTimeMediaUs = -1;
     51     mAnchorTimeRealUs = -1;
     52 }
     53 
     54 void MediaClock::updateAnchor(
     55         int64_t anchorTimeMediaUs,
     56         int64_t anchorTimeRealUs,
     57         int64_t maxTimeMediaUs) {
     58     if (anchorTimeMediaUs < 0 || anchorTimeRealUs < 0) {
     59         ALOGW("reject anchor time since it is negative.");
     60         return;
     61     }
     62 
     63     Mutex::Autolock autoLock(mLock);
     64     int64_t nowUs = ALooper::GetNowUs();
     65     int64_t nowMediaUs =
     66         anchorTimeMediaUs + (nowUs - anchorTimeRealUs) * (double)mPlaybackRate;
     67     if (nowMediaUs < 0) {
     68         ALOGW("reject anchor time since it leads to negative media time.");
     69         return;
     70     }
     71 
     72     if (maxTimeMediaUs != -1) {
     73         mMaxTimeMediaUs = maxTimeMediaUs;
     74     }
     75     if (mAnchorTimeRealUs != -1) {
     76         int64_t oldNowMediaUs =
     77             mAnchorTimeMediaUs + (nowUs - mAnchorTimeRealUs) * (double)mPlaybackRate;
     78         if (nowMediaUs < oldNowMediaUs
     79                 && nowMediaUs > oldNowMediaUs - kAnchorFluctuationAllowedUs) {
     80             return;
     81         }
     82     }
     83     mAnchorTimeRealUs = nowUs;
     84     mAnchorTimeMediaUs = nowMediaUs;
     85 }
     86 
     87 void MediaClock::updateMaxTimeMedia(int64_t maxTimeMediaUs) {
     88     Mutex::Autolock autoLock(mLock);
     89     mMaxTimeMediaUs = maxTimeMediaUs;
     90 }
     91 
     92 void MediaClock::setPlaybackRate(float rate) {
     93     CHECK_GE(rate, 0.0);
     94     Mutex::Autolock autoLock(mLock);
     95     if (mAnchorTimeRealUs == -1) {
     96         mPlaybackRate = rate;
     97         return;
     98     }
     99 
    100     int64_t nowUs = ALooper::GetNowUs();
    101     mAnchorTimeMediaUs += (nowUs - mAnchorTimeRealUs) * (double)mPlaybackRate;
    102     if (mAnchorTimeMediaUs < 0) {
    103         ALOGW("setRate: anchor time should not be negative, set to 0.");
    104         mAnchorTimeMediaUs = 0;
    105     }
    106     mAnchorTimeRealUs = nowUs;
    107     mPlaybackRate = rate;
    108 }
    109 
    110 float MediaClock::getPlaybackRate() const {
    111     Mutex::Autolock autoLock(mLock);
    112     return mPlaybackRate;
    113 }
    114 
    115 status_t MediaClock::getMediaTime(
    116         int64_t realUs, int64_t *outMediaUs, bool allowPastMaxTime) const {
    117     if (outMediaUs == NULL) {
    118         return BAD_VALUE;
    119     }
    120 
    121     Mutex::Autolock autoLock(mLock);
    122     return getMediaTime_l(realUs, outMediaUs, allowPastMaxTime);
    123 }
    124 
    125 status_t MediaClock::getMediaTime_l(
    126         int64_t realUs, int64_t *outMediaUs, bool allowPastMaxTime) const {
    127     if (mAnchorTimeRealUs == -1) {
    128         return NO_INIT;
    129     }
    130 
    131     int64_t mediaUs = mAnchorTimeMediaUs
    132             + (realUs - mAnchorTimeRealUs) * (double)mPlaybackRate;
    133     if (mediaUs > mMaxTimeMediaUs && !allowPastMaxTime) {
    134         mediaUs = mMaxTimeMediaUs;
    135     }
    136     if (mediaUs < mStartingTimeMediaUs) {
    137         mediaUs = mStartingTimeMediaUs;
    138     }
    139     if (mediaUs < 0) {
    140         mediaUs = 0;
    141     }
    142     *outMediaUs = mediaUs;
    143     return OK;
    144 }
    145 
    146 status_t MediaClock::getRealTimeFor(
    147         int64_t targetMediaUs, int64_t *outRealUs) const {
    148     if (outRealUs == NULL) {
    149         return BAD_VALUE;
    150     }
    151 
    152     Mutex::Autolock autoLock(mLock);
    153     if (mPlaybackRate == 0.0) {
    154         return NO_INIT;
    155     }
    156 
    157     int64_t nowUs = ALooper::GetNowUs();
    158     int64_t nowMediaUs;
    159     status_t status =
    160             getMediaTime_l(nowUs, &nowMediaUs, true /* allowPastMaxTime */);
    161     if (status != OK) {
    162         return status;
    163     }
    164     *outRealUs = (targetMediaUs - nowMediaUs) / (double)mPlaybackRate + nowUs;
    165     return OK;
    166 }
    167 
    168 }  // namespace android
    169