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; }
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。