H.264的两个基本概念:IDR,dts/pts

IDR帧与I帧之间的区别

IDR:Instantaneous Decoding Refresh。

I帧与IDR帧之间的区别涉及到H.264中不同帧类型的视频解码过程。

  • 对于普通的I帧(及其IDR帧)而言,对其进行的视频解码不依赖于其他帧,对每一个I帧(及其IDR帧)解码都可以得到一张完整的图像。
  • 对于每一个P帧而言,对其进行解码需要参考其前面的I帧或者P帧,才能成功的解码出来一帧完整的图像;
  • B帧的解码则更复杂一些,对其进行解码不仅要参考前面的I帧或者P帧,还有可能要参考其后面的P帧解码后的图像;

为了能够支持以上解码过程,H.264的解码算法需要维护一个参考帧列表DPB(Decorded Picture Buffer),实际上就是一个普通的缓存空间,用于存放每一帧完成解码的图像数据,因此:

  • I帧的解码不需要依赖于DPB中的内容,直接独立进行解码就可以产生一张完整的图像,填入DPB中,此后就可以作为其他P帧和B帧解码的参考;
  • P帧和B帧的解码则需要依赖于DPB中已经解码好的图像帧,解码完成后同样放入DPB中,作为后面的P帧和B帧的解码参考帧。

注意:P帧和B帧的解码不仅可能依赖于其前面紧邻的那个I帧,还有可能要依赖于更前面的帧。这一点就导致了I帧和IDR帧的细微差别:

IDR帧是一种特殊的I帧,在IDR帧之后的所有P帧和B帧的解码都只会向前参考到这个IDR帧,而不会参考这个IDR帧之前的帧。因此在解码器在对一个IDR帧进行解码的时候,就可以直接把DPB中保存的所有缓存数据全部清空,这是很自然的道理:因为这个IDR帧后面的所有帧的解码都不会参考这个IDR帧之前的数据。

总结起来:

  • IDR帧一定是I帧,但I帧不一定是IDR帧。
  • IDR帧会导致DPB被清空,而普通的I帧不会,因为其后面的帧解码有可能要参考到普通I帧前面的帧。
  • 也正因为以上道理,在对视频流或者视频文件在播放过程中做seek操作的时候,一定要找到IDR帧开始进行解码播放,否则如果在I帧位置进行播放,有可能会因为其后面的帧解码时要依赖于这个I帧前面的帧而造成花屏。

dts与pts

dts、pts 的概念如下所述:

  • dts(Decoding Time Stamp):即解码时间戳,这个时间戳的意义在于告诉播放器该在什么时候解码这一帧的数据。
  • pts(Presentation Time Stamp):即显示时间戳,这个时间戳用来告诉播放器该在什么时候显示这一帧的数据。

实际上dts和pts的概念与B帧息息相关,当编解码器只有I帧和P帧的时候,视频解码和播放的顺序是完全一致的,因此dts与pts是相等的,这个时候讨论dts和pts就意义不大了,播放器只需要按照原来的顺序进行解码和显示就可以了。

但是如果引入了B帧,就会导致解码和显示的顺序不一样。这是因为:

  • B帧的解码需要依赖于其后面的帧,所以解码B帧的时候要先把其后面的帧解码才能对B帧成功解码,但是在播放的时候则需要按照原来的顺序进行播放,也就是说解码和播放显示的顺序不一致。

例如:

一个帧序列播放的顺序是:I B1 B2 P;

  • I帧可以独立解码,因此首先解码,I帧解码顺序为1,播放顺序为1;
  • B1和B2的解码需要依赖于I帧和后面的P帧,所以需要等P帧先解码;
  • P帧解码顺序为2,播放顺序为4;
  • B1的解码需要依赖于B2,因此B2先解码,B2的解码顺序为3,播放顺序为3;
  • B1的解码顺序为4,播放顺序为2。

也就是说:

Frame: I B1 B2 P;

dts:         1 4   3  2;

pts:         1 2   3  4;

参考资料

  1. 《音视频开发进阶指南》第一章;
  2. H264中I帧和IDR帧的区别
  3. 理解音视频PTS和DTS