浅谈音视频 pts dts基本概念及理解


Posted in 数码科技 onAugust 05, 2022

视频的播放过程可以简单理解为一帧一帧的画面按照时间顺序呈现出来的过程,就像在一个本子的每一页画上画,然后快速翻动的感觉。
但是在实际应用中,并不是每一帧都是完整的画面,因为如果每一帧画面都是完整的图片,那么一个视频的体积就会很大,这样对于网络传输或者视频数据存储来说成本太高,所以通常会对视频流中的一部分画面进行压缩(编码)处理。由于压缩处理的方式不同,视频中的画面帧就分为了不同的类别,其中包括:I 帧、P 帧、B 帧。

I、P、B 帧

I 帧、P 帧、B 帧的区别在于:

I 帧(Intra coded frames):I 帧图像采用帧内编码方式,即只利用了单帧图像内的空间相关性,而没有利用时间相关性。I 帧使用帧内压缩,不使用运动补偿,由于 I 帧不依赖其它帧,所以是随机存取的入点,同时是解码的基准帧。I 帧主要用于接收机的初始化和信道的获取,以及节目的切换和插入,I 帧图像的压缩倍数相对较低。I 帧图像是周期性出现在图像序列中的,出现频率可由编码器选择。
P 帧(Predicted frames):P 帧和 B 帧图像采用帧间编码方式,即同时利用了空间和时间上的相关性。P 帧图像只采用前向时间预测,可以提高压缩效率和图像质量。P 帧图像中可以包含帧内编码的部分,即 P 帧中的每一个宏块可以是前向预测,也可以是帧内编码。
B 帧(Bi-directional predicted frames):B 帧图像采用双向时间预测,可以大大提高压缩倍数。值得注意的是,由于 B 帧图像采用了未来帧作为参考,因此 MPEG-2 编码码流中图像帧的传输顺序和显示顺序是不同的。
也就是说,一个 I 帧可以不依赖其他帧就解码出一幅完整的图像,而 P 帧、B 帧不行。P 帧需要依赖视频流中排在它前面的帧才能解码出图像。B 帧则需要依赖视频流中排在它前面或后面的帧才能解码出图像。

这就带来一个问题:在视频流中,先到来的 B 帧无法立即解码,需要等待它依赖的后面的 I、P 帧先解码完成,这样一来播放时间与解码时间不一致了,顺序打乱了,那这些帧该如何播放呢?这时就需要我们来了解另外两个概念:DTS 和 PTS(详见下边说明)。

两个I frame之间形成一个GOP,在x264中同时可以通过参数来设定bf的大小,即:I 和p或者两个P之间B的数量。

通过上述基本可以说明如果有B frame 存在的情况下一个GOP的最后一个frame一定是P.

看x264代码,感觉GOP 就是IDR帧到另一个IDR帧之间 就是一个GOP.在视频编码序列中,GOP即Group of picture(图像组),指两个I帧之间的距离,Reference(参考周期)指两个P帧之间的距离(如下图)。一个I帧所占用的字节数大于一个P帧,一个P帧所占用的字节数大于一个B帧(如下图所示)。

所以在码率不变的前提下,GOP值越大,P、B帧的数量会越多,平均每个I、P、B帧所占用的字节数就越多,也就更容易获取较好的图像质量;Reference越大,B帧的数量越多,同理也更容易获得较好的图像质量。

需要说明的是,通过提高GOP值来提高图像质量是有限度的,在遇到场景切换的情况时,H.264编码器会自动强制插入一个I帧,此时实际的GOP值被缩短了。另一方面,在一个GOP中,P、B帧是由I帧预测得到的,当I帧的图像质量比较差时,会影响到一个GOP中后续P、B帧的图像质量,直到下一个GOP开始才有可能得以恢复,所以GOP值也不宜设置过大。

同时,由于P、B帧的复杂度大于I帧,所以过多的P、B帧会影响编码效率,使编码效率降低。另外,过长的GOP还会影响Seek操作的响应速度,由于P、B帧是由前面的I或P帧预测得到的,所以Seek操作需要直接定位,解码某一个P或B帧时,需要先解码得到本GOP内的I帧及之前的N个预测帧才可以,GOP值越长,需要解码的预测帧就越多,seek响应的时间也越长。

DTS、PTS 的概念

DTS、PTS 的概念如下所述:

DTS(Decoding Time Stamp):即解码时间戳,这个时间戳的意义在于告诉播放器该在什么时候解码这一帧的数据。
PTS(Presentation Time Stamp):即显示时间戳,这个时间戳用来告诉播放器该在什么时候显示这一帧的数据。
需要注意的是:虽然 DTS、PTS 是用于指导播放端的行为,但它们是在编码的时候由编码器生成的。

当视频流中没有 B 帧时,通常 DTS 和 PTS 的顺序是一致的。但如果有 B 帧时,就回到了我们前面说的问题:解码顺序和播放顺序不一致了。

比如一个视频中,帧的显示顺序是:I B B P,现在我们需要在解码 B 帧时知道 P 帧中信息,因此这几帧在视频流中的顺序可能是:I P B B,这时候就体现出每帧都有 DTS 和 PTS 的作用了。DTS 告诉我们该按什么顺序解码这几帧图像,PTS 告诉我们该按什么顺序显示这几帧图像。顺序大概如下:

PTS:   480   640  560  520  600  800  720  680  760  960 ...
DTS:   400   440  480  520  560  600  640  680  720  760 ...
Stream: I     P    B    B    B    P    B    B    B    P  ...
播放序: 1     5    3    2    4    9    7    6    8   10  ...               
PTS >= DTS

音视频的同步

上面说了视频帧、DTS、PTS 相关的概念。我们都知道在一个媒体流中,除了视频以外,通常还包括音频。音频的播放,也有 DTS、PTS 的概念,但是音频没有类似视频中 B 帧,不需要双向预测,所以音频帧的 DTS、PTS 顺序是一致的。

音频视频混合在一起播放,就呈现了我们常常看到的广义的视频。在音视频一起播放的时候,我们通常需要面临一个问题:怎么去同步它们,以免出现画不对声的情况。

要实现音视频同步,通常需要选择一个参考时钟,参考时钟上的时间是线性递增的,编码音视频流时依据参考时钟上的时间给每帧数据打上时间戳。在播放时,读取数据帧上的时间戳,同时参考当前参考时钟上的时间来安排播放。这里的说的时间戳就是我们前面说的 PTS。实践中,我们可以选择:同步视频到音频、同步音频到视频、同步音频和视频到外部时钟。

PTS和DTS的时间基

PST和DTS的单位是什么?

为了回答这个问题,先引入FFmpeg中时间基的概念,也就是time_base。它也是用来度量时间的。
如果把1秒分为25等份,你可以理解就是一把尺,那么每一格表示的就是1/25秒。此时的time_base={1,25}
如果你是把1秒分成90000份,每一个刻度就是1/90000秒,此时的time_base={1,90000}。
所谓时间基表示的就是每个刻度是多少秒
pts的值就是占多少个时间刻度(占多少个格子)。它的单位不是秒,而是时间刻度。只有pts加上time_base两者同时在一起,才能表达出时间是多少。
好比我只告诉你,某物体的长度占某一把尺上的20个刻度。但是我不告诉你,这把尺总共是多少厘米的,你就没办法计算每个刻度是多少厘米,你也就无法知道物体的长度。
pts=20个刻度
time_base={1,10} 每一个刻度是1/10厘米
所以物体的长度=ptstime_base=201/10 厘米

在ffmpeg中。av_q2d(time_base)=每个刻度是多少秒
此时你应该不难理解 pts*av_q2d(time_base)才是帧的显示时间戳。

下面理解时间基的转换,为什么要有时间基转换。
首先,不同的封装格式,timebase是不一样的。另外,整个转码过程,不同的数据状态对应的时间基也不一致。拿mpegts封装格式25fps来说(只说视频,音频大致一样,但也略有不同)。非压缩时候的数据(即YUV或者其它),在ffmpeg中对应的结构体为AVFrame,它的时间基为AVCodecContext 的time_base ,AVRational{1,25}。
压缩后的数据(对应的结构体为AVPacket)对应的时间基为AVStream的time_base,AVRational{1,90000}。
因为数据状态不同,时间基不一样,所以我们必须转换,在1/25时间刻度下占10格,在1/90000下是占多少格。这就是pts的转换。

根据pts来计算一桢在整个视频中的时间位置:
timestamp(秒) = pts * av_q2d(st->time_base)

duration和pts单位一样,duration表示当前帧的持续时间占多少格。或者理解是两帧的间隔时间是占多少格。一定要理解单位。
pts:格子数
av_q2d(st->time_base): 秒/格

计算视频长度:
time(秒) = st->duration * av_q2d(st->time_base)

ffmpeg内部的时间与标准的时间转换方法:
ffmpeg内部的时间戳 = AV_TIME_BASE * time(秒)
AV_TIME_BASE_Q=1/AV_TIME_BASE

av_rescale_q(int64_t a, AVRational bq, AVRational cq)函数
这个函数的作用是计算a*bq / cq来把时间戳从一个时间基调整到另外一个时间基。在进行时间基转换的时候,应该首先这个函数,因为它可以避免溢出的情况发生。
函数表示在bq下的占a个格子,在cq下是多少。

关于音频pts的计算:
音频sample_rate:samples per second,即采样率,表示每秒采集多少采样点。
比如44100HZ,就是一秒采集44100个sample.
即每个sample的时间是1/44100秒

一个音频帧的AVFrame有nb_samples个sample,所以一个AVFrame耗时是nb_samples*(1/44100)秒
即标准时间下duration_s=nb_samples*(1/44100)秒,
转换成AVStream时间基下
duration=duration_s / av_q2d(st->time_base)
基于st->time_base的num值一般等于采样率,所以duration=nb_samples.
pts=nduration=nnb_samples

到此这篇关于浅谈音视频 pts dts基本概念及理解的文章就介绍到这了,更多相关音视频 pts dts内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

数码科技 相关文章推荐
小米11和iphone12哪个值得买?小米11对比iphone12评测
Apr 21 数码科技
Win11局域网共享权限在哪里设置? Win11高级共享的设置技巧
Apr 05 数码科技
Win11黑色桌面背景怎么办?Win11黑色壁纸解决方法汇总
Apr 05 数码科技
如何设置多台电脑共享打印机?多台电脑共享打印机的方法
Apr 08 数码科技
苹果的回收机器人可以通过拆解iPhone获取大量的金和铜并外公布了环境保护最新进展
Apr 21 数码科技
Win10加载疑难解答时出错发生意外错误的解决方法
Jul 07 数码科技
Win11 PC上的Outlook搜索错误怎么办?
Jul 15 数码科技
win10如何开启ahci模式?win10开启ahci模式详细操作教程
Jul 23 数码科技
win10输入法不见了只能打出字母怎么解决?
Aug 05 数码科技
win10拖拽文件时崩溃怎么解决?win10文件不能拖拽问题解决方法
Aug 14 数码科技
鸿蒙3.0体验感怎么样? 鸿蒙3.0系统评测向
Aug 14 数码科技
Debian11 Xfce终端光标的颜色怎么设置?
Aug 14 数码科技
Win11远程连接不上怎么办?Win11远程桌面用不了的解决方法
Aug 05 #数码科技
win10识别不了U盘怎么办 win10系统读取U盘失败的解决办法
Aug 05 #数码科技
windows10声卡驱动怎么安装?win10声卡驱动安装操作步骤教程
Aug 05 #数码科技
win11怎么消除图标小盾牌?win11消除图标小盾牌解决方法
Aug 05 #数码科技
win10输入法不见了只能打出字母怎么解决?
Aug 05 #数码科技
win11开机发生死循环重启怎么办?win11开机发生死循环重启解决方法
Aug 05 #数码科技
win10蓝屏0xc0000001安全模式进不了怎么办?win10出现0xc0000001的解决方法
Aug 05 #数码科技
You might like
实用函数7
2007/11/08 PHP
mysql5的sql文件导入到mysql4的方法
2008/10/19 PHP
YII动态模型(动态表名)支持分析
2016/03/29 PHP
php使用pthreads v3多线程实现抓取新浪新闻信息操作示例
2020/02/21 PHP
图片格式的JavaScript和CSS速查手册
2007/08/20 Javascript
javascript 可以拖动的DIV(二)
2009/06/26 Javascript
自用js开发框架小成 学习js的朋友可以看看
2010/11/16 Javascript
用html+css+js实现的一个简单的图片切换特效
2014/05/28 Javascript
javascript使用正则控制input输入框允许输入的值方法大全
2014/06/19 Javascript
AngularJS语法详解(续)
2015/01/23 Javascript
jquery实现增加删除行的方法
2015/02/03 Javascript
bootstrapValidator bootstrap-select验证不可用的解决办法
2017/01/11 Javascript
VUE axios发送跨域请求需要注意的问题
2017/07/06 Javascript
js 开发之autocomplete="off"在chrom中失效的解决办法
2017/09/28 Javascript
详解javascript中的变量提升和函数提升
2018/05/24 Javascript
利用原生JavaScript实现造日历轮子实例代码
2019/05/08 Javascript
jquery实现的分页显示功能示例
2019/08/23 jQuery
vue 解决addRoutes多次添加路由重复的操作
2020/08/04 Javascript
[01:31](回顾)杀出重围,决战TI之巅
2014/07/01 DOTA
[03:21]辉夜杯主赛事 12月25日TOP5
2015/12/26 DOTA
Python正则表达式匹配HTML页面编码
2015/04/08 Python
老生常谈进程线程协程那些事儿
2017/07/24 Python
Sanic框架流式传输操作示例
2018/07/18 Python
解决pyinstaller打包运行程序时出现缺少plotly库问题
2020/06/02 Python
Python实现在线批量美颜功能过程解析
2020/06/10 Python
python开发一个解析protobuf文件的简单编译器
2020/11/17 Python
DJI大疆德国官方商城:大疆无人机
2018/09/01 全球购物
定义一结构体变量,用其表示点坐标,并输入两点坐标,求两点之间的距离
2015/08/17 面试题
医院竞聘演讲稿
2014/05/16 职场文书
中职毕业生自我鉴定范文(3篇)
2014/09/28 职场文书
大学生考试作弊检讨书1000字
2014/10/14 职场文书
2015年仓库管理员工作总结
2015/04/21 职场文书
2015年依法行政工作总结
2015/04/29 职场文书
背起爸爸上学观后感
2015/06/08 职场文书
Python数据清洗工具之Numpy的基本操作
2021/04/22 Python
80行代码写一个Webpack插件并发布到npm
2021/05/24 Javascript