H264编码——DPB
DPB
全称 Decoded Picture Buffer,即解码图片缓存区。
在做视频解码时,需要将最近的若干幅参考帧
缓存起来,这个缓冲区就叫做DPB
。解码已经完成的图像被缓存在DPB中,供后续帧用作参考图像,因此,解码器需要按照一定的规则对DPB中的图像进行管理。
在H264中参考帧最多可以存储16帧
参考帧。
H.264中,已编码图像存储在编码器和解码器的参考缓冲区(DPB,解码图像缓冲区),并有相应的参考图像列表list0,以供帧间宏块的运动补偿预测使用。对B切片预测而言,参考帧包含当前图像的前面和后面两个方向的图像,保存在list0和list1;也可同时包含短期
和长期
参考图像。
参考帧——reference frame
目的:参考帧在帧间编码时,每个宏块(MB)的运动补偿预测使用,因此根据编码帧的不同主要分为两类。
P slice
: 在编解码P帧时,相应的参考帧全部保存在list0
中.B slice
: 在编解码B帧时,由于B帧存在前向和后向两个方向对图像的参考,因此参考帧分别保存在list0
和list1
中
P slice参考帧存储
P帧的参考帧存储比较简单,就是将当前帧后面的图像利用frame_num来进行索引,并按照降序
排列(即离当前图像最近的前向图像排在第0位)。
B slice参考帧存储
list0
:最近前向
图像(基于POC)标为index0,接着是其余前向图像( POC递增顺序),及后向
图像(从当前图像POC递增顺序)。list1
:最近后向
图像(基于POC)标为index0,接着是其余后向图像( POC递增顺序),及前向
图像(从当前图像POC递增顺序)。
举例:一个H.264解码器存储了6幅短期参考图像。其POC分别为:123,125,126,128,129和130。当前图像为127
。所有6幅短期参考图像在list0和list1中都标为“用作参考”。
1 | +-------------------------------+ |
IDR帧:会将list0和list1中的次序全部清零
短期参考帧——short term reference
短期参考帧:已编码图像由编码器重建的标为短期图像,并由其帧号标定。
长期参考帧——long term reference
长期参考帧是较早的图像,由LongTermPicNum
标定,保存在DPB中,直到被代替或删除。
DPB管理
当一幅图像在编码器被编码重建或在解码器被解码时,它存放在DPB并标定为以四种:
- “非参考”,不用于进一步的预测(Unused for reference)
- 短期参考图像(Used for short-term reference)
- 长期参考图像(Used for long-term reference)
- 直接输出显示(display)
4种状态之间的转化,是通过解码图像标记过程进行控制的,H.264/AVC 中采用了滑动窗
和MMCO
两种方式。
滑动窗
list0中短期参考帧是按PicNum
(由帧号推出的变量)从高到低的顺序排列,长期参考帧按LongTermPicNum
从低到高的顺序排列。
- 当新的图像加在短期列表的位置index0时,剩余的短期图像索引号依次增加。
- 当短期和长期图像号达到参考帧最大数时,最高索引号的图像被移出缓冲区,即实行
滑动窗内存控制
。该操作使得编码器和解码器保持N幅短期参考帧,包括一幅当前图像和(N-1)幅已编码图像。
简单来说就是,最多只缓存refs个数的参考帧,多了就扔掉。
MMCO
由编码器发送的自适应内存控制命令
用来管理短期和长期参考帧索引。这样,短期图像才可能被指定长期帧索引,短期或长期图像才可能标定为“非参考”。编码器从list0中选择参考图像,进行帧间宏块编码。而该参考图像的选择由索引号标志,索引0对应于短期部分的第一帧,长期帧索引开始于最后一个短期帧
。
参考图像缓冲区通常由编码器发送的IDR(瞬时解码器刷新)编码图像刷新,IDR图像一般为I片或SI片。当接受到IDR图像时,解码器立即将缓冲区中的图像标为“非参考”。后继的片进行无图像参考编码。通常,编码视频序列的第一幅图像都是IDR图像。
DPB大小
DPB一般以宏块
(MB)数为单位,计算公式为
1 | DpbInMbs = ref * PicWidthInMbs * FrameHeightInMbs |
- ref(参考帧数)
- PicWidthInMbs(水平宏块数)
- FrameHeightInMbs(垂直宏块数)
H.264协议规定,在不同的级别(Level)下,最大的解码图片缓存区宏块数(MaxDpbMbs)是不同的:
DPB的行为
清空机制
当解码器收到一个IDR帧时会立即将DPB清空
,因为H.264协议规定一个IDR帧之后的任何帧都不会引用该IDR之前的任何帧,所以DPB中的数据已失效,可以清空。这也是IDR帧名称的来源,即 Instantaneous Decoding Refresh – 解码立即重置。
内存分配过大
H.264 bitstream 语法结构(SPS)中定义了一个参数用于通知解码器最大参考帧数
。有些社会责任感不是特别强的编码器会随便报告一个安全余量很大的参数,实际上可能根本用不到。比如为了图方便在结构体中报告最大参考帧数=16,但实际上最多只用到2帧,如果解码器按照16分配内存则会造成大量的浪费。
对于资源紧张的场合,解码器的设计通常会要求最大参考帧数不能超过某个值,编码器输出的码流必须满足同样的限制才能顺利解码。显然,如果这个限制定为6帧,应该可以解大多数编码器的码流。但是如果定为2帧,则遇到不兼容码流的概率就会显著增加。
内存分配不足
如果编码器报告一个不恰当的level,在解码器解析出该level后,并依据该值进行内存的申请,可能会导致内存不足。
比如:
一帧4K分辨率的图像, 宏块数 = (3840/16)*(2160)/16 = 32400
- 按照level4.1准备DPB只能存一个参考帧。
一帧1000万像素分辨率的图像, 宏块数 = (3872/16)*(2592)/16 = 39204
- 按照 level 5.0 准备 DPB 能存2个参考帧,
- 按照 level 5.1 则可以存4个参考帧。
- 按照 level 4.1 则一帧也放不下
H.265中的DPB
HEVC 规定解一帧所需的参考帧数目不能超过8
。具体从DPB中哪些帧用来解当前帧,是由RPS定义的。
RPS也就是Reference Picture Set,即参考帧集。也就是可以选用的参考帧的集合。集合的每个元素是一种参考帧的排队方案。按照参考帧POC与当前帧POC的大小的相对关系排成一队。然后按照RPS的语法,来选出对应的reference_list_x。
对参考帧队列中的图像(即DPB中的图像帧)可分为三类:前向参考帧、后向参考帧和非参考帧。与H.264相似,前向、后向参考帧与list_0、list_1有关系,但不是对应关系。在构造参考帧列表时,会对DPB中的所有帧作遍历,将POC小于当前帧的作为前向参考帧备选,将POC大于当前帧的作为后向参考帧备选。这时,可以通过指定RPS中的ID值来选择用哪些帧来形成真正的参考帧列表。在即时RPS中,通过(与参考帧POC差,是否选入参考列表)两个参数对备选参考帧序列再作筛选,选出真正用于参考的参考帧序列。是不是其中标记为非参考帧的图像就可以被剔除出DPB了呢?当然不是,只是在当前RPS中的指定ID被选中时,这个图像不作为参考帧而已。
为了支持即时参考帧与长时参考帧,RPS分为两种,即时RPS与长时RPS
参考
- H.264 概念解析 - DPB
- H264 DPB管理
- H.264多参考帧管理