您的位置:首页 > 其它

MediaClock及音视频同步

2019-05-12 23:01 573 查看

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) == OK
delayUs = 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;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: