标签:同步 yun 基础 问题 log clear 入队 理解 github
用ffmpeg来做音视频同步,个人认为这个是ffmpeg基础处理中最难的一个,无数人就卡在这里,怎么也不准,本人也是尝试过网上各种demo,基本上都是渣渣,要么仅仅支持极其少量的视频文件比如收到的数据包是一帧视频一帧音频的,要么根本没法同步歪七八糟的,要么进度跳过去直接蹦蹦蹦崩溃的,其实最完美的音视频同步处理demo就是ffplay,我亲测过几十种各种各样的音视频本地文件,数十种视频流文件,都是非常完美,当然啦这是亲生的啦,不完美还玩个屁。
如果仅仅是播放视频流(不带音频流),可能不需要音视频同步,所以最开始只做rtsp视频流播放的时候根本没有考虑同步的问题,因为没遇到也不需要,等到后期发现各种rtmp、http、m3u8这种视频流的时候,问题大了去了,他是hls格式的视频流文件一次性过来的,一个个小视频文件过来的,如果没有同步的话,意味着突然之间刷刷刷的图片过去很多,下一次来的又是刷刷的,这就需要自己计算同步了,上次接收到的数据包放入队列,到了需要显示的时候就显示。
常用的音视频同步方法:
void FFmpegSync::run()
{
reset();
while (!stopped) {
//暂停状态或者队列中没有帧则不处理
if (!thread->isPause && packets.count() > 0) {
mutex.lock();
AVPacket *packet = packets.first();
mutex.unlock();
//h264的裸流文件同步有问题,获取不到pts和dts,暂时用最蠢的办法延时解决
if (thread->formatName == "h264") {
int sleepTime = (1000 / thread->videoFps) - 5;
msleep(sleepTime);
}
//计算当前帧显示时间 外部时钟同步
ptsTime = getPtsTime(thread->formatCtx, packet);
if (!this->checkPtsTime()) {
msleep(1);
continue;
}
//显示当前的播放进度
checkShowTime();
//0-表示音频 1-表示视频
if (type == 0) {
thread->decodeAudio(packet);
} else if (type == 1) {
thread->decodeVideo(packet);
}
//释放资源并移除
thread->free(packet);
mutex.lock();
packets.removeFirst();
mutex.unlock();
}
msleep(1);
}
clear();
stopped = false;
}
bool FFmpegSync::checkPtsTime()
{
bool ok = false;
if (ptsTime > 0) {
if (ptsTime > offsetTime + 100000) {
bufferTime = ptsTime - offsetTime + 100000;
}
int offset = (type == 0 ? 1000 : 5000);
offsetTime = av_gettime() - startTime + bufferTime;
if ((offsetTime <= ptsTime && ptsTime - offsetTime <= offset) || (offsetTime > ptsTime)) {
ok = true;
}
} else {
ok = true;
}
return ok;
}
标签:同步 yun 基础 问题 log clear 入队 理解 github
原文地址:https://www.cnblogs.com/feiyangqingyun/p/13723246.html