Nuplayer中音视频同步主要依靠MediaClock中记录的锚点时间,所以先看下MediaClock类

1,1

MediaClock::MediaClock()    : mAnchorTimeMediaUs(-1),      mAnchorTimeRealUs(-1),      mMaxTimeMediaUs(INT64_MAX),      mStartingTimeMediaUs(-1),      mPlaybackRate(1.0) {}

1.2锚点时间更新

void MediaClock::updateAnchor(int64_t anchorTimeMediaUs,int64_t anchorTimeRealUs,int64_t maxTimeMediaUs) {    Mutex::Autolock autoLock(mLock);    int64_t nowUs = ALooper::GetNowUs();    int64_t nowMediaUs =    anchorTimeMediaUs + (nowUs - anchorTimeRealUs) * (double)mPlaybackRate; //mPlaybackRate是播放倍速    //下面这段是超过阈值的保护       if (mAnchorTimeRealUs != -1) {    int64_t oldNowMediaUs =    mAnchorTimeMediaUs + (nowUs - mAnchorTimeRealUs) * (double)mPlaybackRate;    if (nowMediaUs < oldNowMediaUs    && nowMediaUs > oldNowMediaUs - kAnchorFluctuationAllowedUs) {    return;    }    }    //mAnchorTimeRealUs  当前系统时间,锚点real系统时间戳,可以理解为最后一帧播放的时间,对应到系统时钟后的时间。    //mAnchorTimeMediaUs   为锚点媒体时间戳,可以理解为从最开始播放时记录下来的第一个媒体时间戳,一直到当前正在播放这一帧的总时长,但是它主要将音频pts与系统时钟做了统一,即将音频同步到系统时钟上。    在这函数里面只是考虑到函数调用的耗时,将这个耗时加到mAnchorTimeMediaUs 而已,本质还是直接记录传入的2个入参时间    mAnchorTimeRealUs = nowUs;    mAnchorTimeMediaUs = nowMediaUs;}

  

 1.3从别人链接处摘录的解释

realTimeUs = PTS - nowMediaUs + nowUs      

getRealTimeFor

= PTS - (mAnchorTimeMediaUs + (nowUs - mAnchorTimeRealUs)) + nowUs

mAnchorTimeMediaUs + (nowUs - mAnchorTimeRealUs)  是在

getMediaTime_l中计算

mAnchorTimeMediaUs锚点媒体时间戳,可以理解为最开始播放的时候记录下来的第一个媒体时间戳

mAnchorTimeRealUs锚点real系统时间戳,

nowUs - mAnchorTimeRealUs即为从开始播放到现在,系统时间经过了多久。    

这个时间再加上mAnchorTimeMediaUs,即为“在当前系统时间下,对应的媒体时间戳”,

用PTS减去这个时间,表示“还有多久该播放这一帧”。

最后再加上一个系统时间,即为这一帧应该显示的时间。

--------------------- 

作者:zhanghui_cuc 

来源:CSDN 

原文:https://blog.csdn.net/nonmarking/article/details/78746671 

版权声明:本文为博主原创文章,转载请附上博文链接!


实际就是根据codec解出来的PTS, 然后比较音频的锚点值,计算出来当前这视频帧应当延迟多久post,锚点时间是在每个音频帧时都计算的,按我自己理解是

(nowUs - mAnchorTimeRealUs) 是距离上个音频帧播放有多久

mAnchorTimeMediaUs + (nowUs - mAnchorTimeRealUs)  是对应音频帧应该播放的视频帧时间戳
PTS - (mAnchorTimeMediaUs + (nowUs - mAnchorTimeRealUs)) + nowUs  这个是PTS-真正要播放的视频帧时间戳 计算出该视频帧要延迟多久 再加上当前时间得到绝对时间


mMediaClock->getRealTimeFor(mediaTimeUs, &realTimeUs) == OKdelayUs = realTimeUs - nowUs;msg->setWhat(kWhatPostDrainVideoQueue);msg->post(postDelayUs);

// targetMediaUs PTS   outRealUs 出参,实际要播放时刻status_t MediaClock::getRealTimeFor(int64_t targetMediaUs, int64_t *outRealUs) const {    int64_t nowUs = ALooper::GetNowUs();    int64_t nowMediaUs;    status_t status =    getMediaTime_l(nowUs, &nowMediaUs, true /* allowPastMaxTime */);    if (status != OK) {    return status;    }    *outRealUs = (targetMediaUs - nowMediaUs) / (double)mPlaybackRate + nowUs;    return OK;}status_t MediaClock::getMediaTime_l(int64_t realUs, int64_t *outMediaUs, bool allowPastMaxTime) const {    int64_t mediaUs = mAnchorTimeMediaUs    + (realUs - mAnchorTimeRealUs) * (double)mPlaybackRate;    if (mediaUs > mMaxTimeMediaUs && !allowPastMaxTime) {    mediaUs = mMaxTimeMediaUs;    }    if (mediaUs < mStartingTimeMediaUs) {    mediaUs = mStartingTimeMediaUs;    }    if (mediaUs < 0) {    mediaUs = 0;    }    *outMediaUs = mediaUs;    return OK;}