视频流中的DTS/PTS到底是什么?
DTS
(解码时间戳)和
PTS
(显示时间戳)分别是×××进行解码和显示帧时相对于
SCR
(系统参考)的时间戳。
SCR
可以理解为×××应该开始从磁盘读取数据时的时间。
mpeg
文件中的每一个包都有一个
SCR
时间戳并且这个时间戳就是读取这个数据包时的系统时间。通常情况下,×××会在它开始读取
mpeg
流时启动系统时钟(系统时钟的初始值是第一个数据包的
SCR
值,通常为
0
但也可以不从
0
开始)。
DTS
时间戳决定了×××在
SCR
时间等于
DTS
时间时进行解码,
PTS
时间戳也是类似的。通常,
DTS/PTS
时间戳指示的是晚于音视频包中的
SCR
的一个时
间。例如,如果一个视频数据包的
SCR
是
100ms
(意味着此包是播放
100ms
以后从磁盘中读取的),那么
DTS/PTS
值就差不多是
200 /280ms
,表明当
SCR
到
200ms
时这个视频数据应该被解码并在
80ms
以后被显示出来(视频数据在一个
buffer
中一直保存到开始解码)下
溢通常发生在设置的视频数据流相关
mux
率太高。
如果
mux
率是
1000000bits/sec
(意味着×××要以
1000000bits/sec
的速率
读取文件),可是视频速率是
2000000bits/sec
(意味着需要以
2000000bits/sec
的速率显示视频数据),从磁盘中读取视频数据时
速度不够快以至于
1
秒钟内不能够读取足够的视频数据。这种情况下
DTS/PTS
时间戳就会指示视频在从硬盘中读出来之前进行解码或显示(
DTS/PTS
时间戳就要比包含它们的数据包中的
SCR
时间要早了)。
如今依靠×××,这基本已经不是什么问题了(尽管
MPEG
文件因为应该没有下溢而并不完全符合
MPEG
标准)。一些×××(很多著名的基于
PC
的播放器)尽可能快的读取文件以便显示视频,可以的话直接忽略
SCR
。
注意在你提供的列表中,平均的视频流速率为~
3Mbps
(
3000000bits/sec
)但是它的峰值达到了
14Mbps
(相当大,
DVD
限制在
9.8Mbps
内)。这意味着
mux
率需要调整足够大以处理
14Mbps
的部分,
bbMPEG
计算出来的
mux
率有时候太低而导致下溢。
你计划让视频流速率这么高么?这已经超过了
DVD
的说明了,而且很可能在大多数独立播放其中都不能播放。如果你不是这么计划,我会从
1
增加
mquant
的值并且在视频设置中将最大码流设置为
9Mbps
以保持一个小一点的码流。
如果你确实想让视频码率那么高,你需要增大
mux
率。从提供的列表可以得出
bbMPEG
使用
14706800bits/sec
或者
1838350bytes /sec
的
mux
率(总数据速率为:
1838350bytes/sec
(
14706800bits/sec
)行)。你在强制
mux
率字段设置的值应该是以
bytes/sec
为单位并被
50
整除。所以我会从
36767
(
1838350/50
)开始,一直增加直到不会再出现下溢错误为止。
音视频同步原理[ffmpeg]
ffmpeg
对视频文件进行解码的大致流程:
1.
注册所有容器格式和
CODEC: av_register_all()
2.
打开文件
: av_open_input_file()
3.
从文件中提取流信息
: av_find_stream_info()
4.
穷举所有的流,查找其中种类为
CODEC_TYPE_VIDEO
5.
查找对应的×××
: avcodec_find_decoder()
6.
打开编×××
: avcodec_open()
7.
为解码帧分配内存
: avcodec_alloc_frame()
8.
不停地从码流中提取中帧数据
: av_read_frame()
9.
判断帧的类型,对于视频帧调用
: avcodec_decode_video()
10.
解码完后,释放×××
: avcodec_close()
11.
关闭输入文件
:av_close_input_file()
output_example.c
中
AV
同步的代码如下
(
我的代码有些修改
)
,这个实现相当简单,不过挺说明问题。
音视频同步-时间戳
媒体内容在播放时,最令人头痛的就是音视频不同步。从技术上来说,解决音视频同步问题的最佳方案就是时间戳:首先选择一个参考时钟(要求参考时钟上的时间是线性递增的);生成数据流时依据参考时钟上的时间给每个数据块都打上时间戳(一般包括开始时间和结束时间);在播放时,读取数据块上的时间戳,同时参考当前参考时钟上的时间来安排播放(如果数据块的开始时间大于当前参考时钟上的时间,则不急于播放该数据块,直到参考时钟达到数据块的开始时间;如果数据块的开始时间小于当前参考时钟上的时间,则
“
尽快
”
播放这块数据或者索性将这块数据
“
丢弃
”
,以使播放进度追上参考时钟)。
可见,避免音视频不同步现象有两个关键
——
一是在生成数据流时要打上正确的时间戳。如果数据块上打的时间戳本身就有问题,那么播放时再怎么调整也于事无补。假如,视频流内容是从
0s
开始的,假设
10s
时有人开始说话,要求配上音频流,那么音频流的起始时间应该是
10s
,如果时间戳从
0s
或其它时间开始打,则这个混合的音视频流在时间同步上本身就出了问题。打时间戳时,视频流和音频流都是参考参考时钟的时间,而数据流之间不会发生参考关系;也就是说,视频流和音频流是通过一个中立的第三方(也就是参考时钟)来实现同步的。第二个关键的地方,就是在播放时基于时间戳对数据流的控制,也就是对数据块早到或晚到采取不同的处理方法。图
2.8
中,参考时钟时间在
0-10s
内播放视频流内容过程中,即使收到了音频流数据块也不能立即播放它,而必须等到参考时钟的时间达到
10s
之后才可以,否则就会引起音视频不同步问题。
基于时间戳的播放过程中,仅仅对早到的或晚到的数据块进行等待或快速处理,有时候是不够的。如果想要更加主动并且有效地调节播放性能,需要引入一个反馈机制,也就是要将当前数据流速度太快或太慢的状态反馈给
“
源
”
,让源去放慢或加快数据流的速度。熟悉
DirectShow
的读者一定知道,
DirectShow
中的质量控制(
Quality Control
)就是这么一个反馈机制。
DirectShow
对于音视频同步的解决方案是相当出色的。但
WMF SDK
在播放时只负责将
ASF
数据流读出并解码,而并不负责音视频内容的最终呈现,所以它也缺少这样的一个反馈机制。
音视频同步通讯
SDK
源码包分享:
Android
:
http://down.51cto.com/data/711001
Windows
:
http://down.51cto.com/data/715497
Linux
:
http://download.csdn.net/detail/weixiaowenrou/5169796
IOS
:
http://down.51cto.com/data/715486
WEB
:
http://down.51cto.com/data/710983