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

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

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

  • 将视频同步到音频上,就是以音频的播放速度为基准来同步视频。视频比音频播放慢了,加快其播放速度;快了,则延迟播放。
  • 将音频同步到视频上,就是以视频的播放速度为基准来同步音频。
  • 将视频和音频同步外部的时钟上,选择一个外部时钟为基准,视频和音频的播放速度都以该时钟为标准。
			//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(视频流的时基)

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

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

代码下载

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏前端小作坊

CSS硬件加速的好与坏

每个人都痴迷于60桢每秒的顺滑动画。为了实现这个顺滑体验现在用的最流行的一个做法就是使用『CSS硬件加速』。在一些极端例子中,强制使用translate3d意味...

712
来自专栏Coco的专栏

盒子端 CSS 动画性能提升研究

1236
来自专栏进步博客

创建高效media queries的七个好习惯

从最小屏幕开始,逐渐扩大窗口,当效果丑陋不堪(like shit)时,此处就是breakpoint。

592
来自专栏前端那些事

过渡与动画 - 逐帧动画&steps调速函数

上一篇中我们熟悉五种内置的缓动曲线和(三次)贝塞尔曲线,并且基于此完成了缓动效果.

580
来自专栏Coco的专栏

盒子端 CSS 动画性能提升研究

1636
来自专栏即时通讯技术

全面掌握移动端主流图片格式的特点、性能、调优等

图片通常是移动端应用流量耗费最多的部分,并且占据着重要的视觉空间。以大家最常用的即时通讯IM应用为例,应用中存在大量的图片数据往来(比如图片消息、用户相册、用户...

592
来自专栏Python中文社区

Python交互式数据分析报告框架:Dash

译者序 原文于2017年6月21日发布,时过半载,将这篇既不是教程,也不是新闻的产品发布稿做了一番翻译,为何?只因去年下半年的时候,用R语言的博哥和龙少有Sh...

5007
来自专栏hightopo

原 HT for Web中3D流动效果的实

1473
来自专栏数据小魔方

你想要的地图素材资源,我都帮你整理好了~

这一篇我会把自己所掌握的所有数据地图素材资源获取途径全部分享给大家。 可能有的小伙伴儿会有疑问,现在商务智能工具发展的这么火,像PowerBI、Tableau...

2663
来自专栏抠抠空间

haslib 模块

一、模块简介 Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。 什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任...

2958

扫描关注云+社区