前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >FFmpeg_3.2.4+SDL_2.0.5学习(2)视频同步基础

FFmpeg_3.2.4+SDL_2.0.5学习(2)视频同步基础

作者头像
_gongluck
发布2018-03-08 14:37:47
8350
发布2018-03-08 14:37:47
举报

一般来说,视频同步指的是视频和音频同步,也就是说播放的声音要和当前显示的画面保持一致。想象以下,看一部电影的时候只看到人物嘴动没有声音传出;或者画面是激烈的战斗场景,而声音不是枪炮声却是人物说话的声音,这是非常差的一种体验。 在视频流和音频流中已包含了其以怎样的速度播放的相关数据,视频的帧率(Frame Rate)指示视频一秒显示的帧数(图像数);音频的采样率(Sample Rate)表示音频一秒播放的样本(Sample)的个数。可以使用以上数据通过简单的计算得到其在某一Frame(Sample)的播放时间,以这样的速度音频和视频各自播放互不影响,在理想条件下,其应该是同步的,不会出现偏差。但,理想条件是什么大家都懂得。如果用上面那种简单的计算方式,慢慢的就会出现音视频不同步的情况。要不是视频播放快了,要么是音频播放快了,很难准确的同步。这就需要一种随着时间会线性增长的量,视频和音频的播放速度都以该量为标准,播放快了就减慢播放速度;播放快了就加快播放的速度。所以呢,视频和音频的同步实际上是一个动态的过程,同步是暂时的,不同步则是常态。以选择的播放速度量为标准,快的等待慢的,慢的则加快速度,是一个你等我赶的过程。

播放速度标准量的的选择一般来说有以下三种:

  • 将视频同步到音频上,就是以音频的播放速度为基准来同步视频。视频比音频播放慢了,加快其播放速度;快了,则延迟播放。
  • 将音频同步到视频上,就是以视频的播放速度为基准来同步音频。
  • 将视频和音频同步外部的时钟上,选择一个外部时钟为基准,视频和音频的播放速度都以该时钟为标准。
代码语言:javascript
复制
			//extra_delay = repeat_pict / (2 * fps)
			//fps = 1 / time_base
			//uint64_t pts1 = pfe->pts;
			uint64_t pts2 = pfe->best_effort_timestamp;
			double extime = pfe->repeat_pict * av_q2d(pFmtCtx->streams[vindex]->time_base) * 0.5;//对齐
			double showtime = pts2 * av_q2d(pFmtCtx->streams[vindex]->time_base) + extime;

			static double time1 = timeGetTime();//0
			static double time2 = 0;
			static double preshow = 0;
			static double delay = showtime - preshow;

			time2 = timeGetTime();
			if (time1 > time2 || time1 == 0)
				time1 = time2;
			if (preshow >= showtime)
				preshow = showtime;
			if ((time2 - time1) < showtime*1000)//if(time2 - time1 < delay*1000)
				SDL_Delay(delay * 1000);

			delay = showtime - preshow;
			preshow = showtime;

			sws_scale(img_ctx, pfe->data, pfe->linesize, 0, vCodecCtx->height, YUV->data, YUV->linesize);
			SDL_UpdateTexture(texture, &rect, YUV->data[0], YUV->linesize[0]);
			SDL_RenderClear(renderer);
			SDL_RenderCopy(renderer, texture, NULL, NULL);
			SDL_RenderPresent(renderer);

			//time1 = timeGetTime();

如果把视频流看做一个数组,那么显示时间戳就像是数组下标,指示该图片帧应该显示的时间。

*pfe显示时间 = pfe->best_effort_timestamp * av_q2d(视频流的时基) + extra_delay

   extra_delay = pfe->repeat_pict / (2*fps)

   fps = 1 / av_q2d(视频流的时基)

extra_delay = pfe->repeat_pict * 0.5 * av_q2d(视频流的时基)

本例以第一帧的播放时间作为基准,适当延迟后续帧的播放时间,达到(动态)播放的效果。经测试,效果和用暴风影音的几乎一毛一样。

以后再考虑把音视频的解码播放封装成一个类,做一个真正的播放器(到时候应该以音频作为同步的基准)。

代码下载

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年04月27日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档