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;
}
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。