科普:视频的I、B、P帧和PTS、DTS的关系
详细科普:雷霄骅博客
- 需求:读取h264视频裸流文件、读取aac音频裸流文件,并发送出去
- 现象:播放器拿到数据播放的时候。ffplay和VLC兼容性好的播放器播放画面正常,容错性稍微差一点的如小程序的
live-player
标签,就会出现画面回跳- 原因:视频中有B帧,裸流文件中不带pts,需要自己手工生成
1、视频的PTS、DTS
- 没有B帧的时候PTS = DTS
- 有B帧的时候:
- 1、B帧PTS = B帧的DTS
- 2、I帧或者P帧PTS = DTS + 依赖此帧解码并在此帧前显示的B帧的数量 + 1
- 3、需要保证每一帧的 PTS >= DTS
- 思路
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
211、假设P帧之间的B帧数量为3个
2、
编码顺序:
I P1 B1 B2 B3 P2 ... ...
播放顺序:
I B1 B2 B3 P1 ...P2 ...
3、
实现的时候可以理解为将B帧用一个队列bframeQueue存起来,遇到下一个P帧或者I帧的时候,将bframeQueue全部出队列,并计算bframeQueue中B帧的PTS和前一个P或I帧的PTS
PTS与DTS
I P1 B1 B2 B3 P2 B4 B5 B6 P3//编码顺序
0 1 2 3 4 5 6 7 8 9//DTS
0 5 2 3 4 9 6 7 8 13 //PTS = DTS + bframeQueue.size() + 1
//这里可以看到,当不加后面1的时候,P帧会和一个B帧PTS重复了
4、
假如视频fps为30,一帧占用30分之1秒,就是1/fps秒
那么每编码出一帧的时候,DTS就是 n * 1/fps秒
根据上面的思路,PTS就可以根据DTS算出来了
2、音频的PTS、DTS
音频PTS = DTS,比较简单。
1 | F0 F1 F2 F3 ... //编码顺序 |
3、其他
了解了一下,在直播当中,很大一部分为了保证低延时、实现简单,都不会在视频流里面传送B帧。