音视频同步

原创 2018年04月17日 14:07:30

一、DTS、PTS 的概念

DTS(Decoding Time Stamp):即解码时间戳,这个时间戳的意义在于告诉播放器该在什么时候解码这一帧的数据。

PTS(Presentation Time Stamp):即显示时间戳,这个时间戳用来告诉播放器该在什么时候显示这一帧的数据。
需要注意的是:虽然 DTS、PTS 是用于指导播放端的行为,但它们是在编码的时候由编码器生成的。
当视频流中没有 B 帧时,通常 DTS 和 PTS 的顺序是一致的。但如果有 B 帧时,就回到了我们前面说的问题:解码顺序和播放顺序不一致了。

二、音视频同步原理:
根据音频的pts来控制视频的播放,也就是说在视频解码一帧后,是否显示以及显示多长时间是通过该帧的PTS与同时正在播放的音频的PTS比较而来的,如果音频的PTS较大,则视频显示完毕准备下一帧的解码显示,否则等待。

mplayer播放时的大循环过程为:
while(!mpctx->eof){
  fill_audio_out_buffers();//音频stream的读取,解码,播放
  update_video(&blit_frame);//视频stream的读取,解码,过滤处理
  sleep_until_update(&time_frame, &aq_sleep_time);//计算延迟时间并睡眠等待
  mpctx->video_out->flip_page();//视频的播放
  adjust_sync_and_print_status(frame_time_remaining, time_frame);//根据音视频的PTS做同步矫正处理
}

三、音视频同步方法为
1)音频播放playsize = mpctx->audio_out->play(sh_audio->a_out_buffer, playsize,  playflags);  后,根据数据大小算出时间并累计
mpctx->delay += playback_speed*playsize/(double)ao_data.bps;
2)视频解码前,用累计延迟时间剪掉本祯视频的时间mpctx->delay -= frame_time;
3)计算声音延迟时间*time_frame = delay - mpctx->delay / playback_speed;
其中float delay = mpctx->audio_out->get_delay();为距当前声音OUTPUT BUF里数据被全部播放完为止所需的时间。
4)播放视频同步完成,所以视频的播放是完全根据声卡最后的数据输出来同步的。
5)计算出当前音视频PTS差double AV_delay = a_pts - audio_delay - v_pts;再算出矫正值x = (AV_delay + timing_error * playback_speed) * 0.1f;最后把矫正的时间加到延迟累计中mpctx->delay+=x;。

四、音视频同步时遇到的问题

问题一:
没办法得到正在播放的音频帧的PTS,因为进行音频播放使用的DirectSound,而对于DirectSound我只能得到当前拷入DirectSound的缓存的帧的PTS,而无法得到正在播放的PTS,如果得不到正在播放的帧的PTS的话,那同步肯定是不可能的了。在网上找资料好象也没找到有用的,最后突然想到由于音频帧的大小与时间成正比,那么DirectSound的缓存中的数据所需要的播放时间就可以计算得出,再根据当前正在拷入的音频帧的PTS,就可以得到正在播放的帧的PTS,再用这个就可以正确同步视频帧的显示了。
问题二:
根据上面的方法处理后还是出现不同步的现象,为什么这样我也是百思不得其解,后来才发现是等待机制有问题,原来我是用Sleep()来做等待的,但实际上Sleep()的误差很大的,网上有说有15MS,做音视频同步肯定是不行的了,经过不断的google,找到一份代码:

void MySleep(int interval)
{
LARGE_INTEGER litmp; 
LONGLONG QPart1,QPart2;
double dfMinus, dfFreq, dfTim; 
QueryPerformanceFrequency(&litmp);
dfFreq = (double)litmp.QuadPart;// 获得计数器的时钟频率
QueryPerformanceCounter(&litmp);
QPart1 = litmp.QuadPart;// 获得初始值

do
{
   QueryPerformanceCounter(&litmp);
   QPart2 = litmp.QuadPart;//获得中止值
   dfMinus = (double)(QPart2-QPart1);
   dfTim = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
}while(dfTim<0.001 * interval);
}
可以达到精度比较高的等待,从效果看,也可以达到音视频同步。
       本以为问题到这就算结束了,但程序运行的时候怎么发现机器这么慢呀,看了下CPU占用率,达到100%。很显然使用这个做等待是不行的了。
       于是继续google,网上有说timesetevent什么的,我没有试。感觉麻烦了些。后来想到以前看过的一篇用WaitForSingleObject来做定时让某段代码执行的,于是试了试,一试之下立即发现效果明显,CPU占用率一下子回到了个位数。更改后的代码如下:
void MySleep(int interval)
{
HANDLE evt;
evt = CreateEvent(NULL, TRUE, FALSE, NULL);
WaitForSingleObject(evt, interval);
CloseHandle(evt);
}


ffmpeg+sdl教程----编写一个简单的播放器5(同步视频到音频)

视频 音频 时钟同步
  • mu399
  • mu399
  • 2010-08-16 21:06:00
  • 12875

音视频的同步原理

1.   音视频同步的原理  2.  音视频同步的较正方法  3.  音视频同步时遇到的问题 声明:以下所有内容均为转载  1.原文转自:http://bbs.chinavid...
  • Beyond_cn
  • Beyond_cn
  • 2014-03-02 21:36:27
  • 8107

音视频同步原理解析

音视频同步原理解析 2013-04-18 15:21:11 标签:音频视频 视频流中的DTS/PTS到底是什么? DTS(解码时间戳)和PTS(显示时间戳)分别是解码器进行解码...
  • titer1
  • titer1
  • 2014-09-27 17:12:47
  • 7842

音视频同步(播放)原理

1:音视频同步原理 每一帧音频或视频都有一个持续时间:duration: 采样频率是指将模拟声音波形进行数字化时,每秒钟抽取声波幅度样本的次数。 。正常人听觉的频率范围大约在20Hz~20kHz之间,...
  • zhuweigangzwg
  • zhuweigangzwg
  • 2014-05-14 18:05:00
  • 23152

音视频同步的简要总结

平台为嵌入式音视频解码器,使用linux作为操作系统,音频采用alsa架构。 一、STC(本地时钟作为一个基准) 如果是ts封装,可以使用PCR;如果为RTP封装,可以使用音频时间戳或者rtcp的...
  • gllilin
  • gllilin
  • 2015-09-09 17:11:11
  • 546

FFmpeg 音视频同步

原地址:http://www.jianshu.com/p/27279255f67e 音视频播放器的工作的具体流程如下图所示: 播放器工作流程 简单的来说包括:解协议,解封装,对音...
  • jiabailong
  • jiabailong
  • 2017-07-11 16:49:49
  • 303

音视频同步原理与代码

  • 2013年04月17日 14:42
  • 33KB
  • 下载

音视频同步原理

媒体内容在播放时,最令人头痛的就是音视频不同步。从技术上来说,解决音视频同步问题的最佳方案就是时间戳:首先选择一个参考时钟(要求参考时钟上的 时间是线性递增的);生成数据流时依据参考时钟上的时间给每...
  • coloriy
  • coloriy
  • 2015-03-17 10:28:33
  • 1822

Gstreamer的音视频同步

一 概述     Gstreamer的音频视频同步,概括起来是一个比较大的问题,因为在网上可以看到很多音视频同步的办法。这里我们只看最普通的一种。以音频时钟做为参考时钟(要求参考时钟上的时间...
  • jiangzhe1224
  • jiangzhe1224
  • 2014-11-13 15:02:45
  • 446

ffmpeg学习---7.音视频同步之视频同步音频

ffmpeg学习---7.音视频同步之视频同步音频
  • wangcong02345
  • wangcong02345
  • 2016-09-05 17:12:29
  • 475
收藏助手
不良信息举报
您举报文章:音视频同步
举报原因:
原因补充:

(最多只允许输入30个字)