I 帧和 IDR 帧的区别:
IDR 帧属于 I 帧。解码器收到 IDR frame 时,将所有的参考帧队列丢弃 (用x264_reference_reset 函数实现——在 encoder.c 文件中) 。这点是所有 I 帧共有的特性,但是收到 IDR 帧时,解码器另外需要做的工作就是:把所有的 PPS 和 SPS 参数进行更新。由此可见,在编码器端,每发一个 IDR ,就相应地发一个 PPS&SPS_nal_unit
这是网上搜索到的一个答案,有一定参考价值吧。
先说明:所有的 IDR 帧都是 I 帧,但是并不是所有 I 帧都是 IDR 帧。就是说, IDR 帧是 I 帧的子集。 (我们程序中设定的是每250帧出现一个 IDR 帧)
我们用的程序是这样的:
/* ------------------- Setup frame context ----------------------------- */
/* 5: Init da ta dependant of frame type */
if ( h->fenc->i_type == X264_TYPE_IDR )
{
/* reset ref pictures */
x264_reference_reset ( h );
i_nal_type = NAL_SLICE_IDR ;
i_nal_ref_idc = NAL_PRIORITY_ HIGHEST ;
i_slice_type = SLICE_TYPE_ I ;
}
else if ( h->fenc->i_type == X264_TYPE_I )
{
i_nal_type = NAL_SLICE ;
i_nal_ref_idc = NAL_PRIORITY_ HIGH ; /* Not completely true but for now it is (as all I/P are kept as ref)*/
i_slice_type = SLICE_TYPE_ I ;
}
else if ( h->fenc->i_type == X264_TYPE_P )
{
i_nal_type = NAL_SLICE;
i_nal_ref_idc = NAL_PRIORITY_HIGH; /* Not completely true but for now it is (as all I/P are kept as ref)*/
i_slice_type = SLICE_TYPE_P;
}
else if ( h->fenc->i_type == X264_TYPE_BREF )
{
i_nal_type = NAL_SLICE;
i_nal_ref_idc = NAL_PRIORITY_HIGH; /* maybe add MMCO to forget it? -> low */
i_slice_type = SLICE_TYPE_B;
}
else /* B frame */
{
i_nal_type = NAL_SLICE;
i_nal_ref_idc = NAL_PRIORITY_DISPOSABLE;
i_slice_type = SLICE_TYPE_B;
}
x264_reference_reset 函数的定义如下: (其实,因为这个代码是通用的,所以应该是参考帧队列。但是,我们只用一个参考帧,“队列”并没有意义。)
static inline void x264_reference_reset( x264_t *h )
{
int i;
/* reset ref pictures */
for ( i = 1; i < h->frames.i_max_dpb; i++ )
{
h->frames.reference[i]->i_poc = -1;
}
h->frames.reference[0]->i_poc = 0;
}
看来,好像是遇到 IDR 帧时才会 将所有的参考帧队列丢弃( x264_reference_reset ( h ); ) 。其实,我们的程序默认只用一个参考帧,这个问题就不是十分有意义了。
多参考帧情况下。
举个例子 :有如下帧序列: IPPPP I P PPP ……(我们程序没有 B 帧,所以帧序列简单些,但道理是一样的)。按照 3 个参考帧编码。
因为“按照 3 个参考帧编码”,所以参考帧队列长度为 3 。
遇到绿色的 I 时,并不清空参考帧队列,把这个 I 帧加入参考帧队列(当然 I 编码时不用参考帧。)。再检测到红色的 P 帧时,用到的就是 PPI 三帧做参考了。
不怕自己罗嗦(好记性不如烂笔头),再强调一个: 一个参考帧,就是参考当前帧的前面的那帧(因为没涉及到 B 帧,所以“前面的那帧”既是播放顺序的,也是编码顺序的)。多个参考帧是一个道理 。 ( 我以前一直误解为从前面的几帧中找到最合适的一个参考帧)
最后,“ 但是收到 IDR 帧时,解码器另外需要做的工作就是:把所有的 PPS 和 SPS 参数进行更新。由此可见,在编码器端,每发一个 IDR ,就相应地发一个 PPS&SPS_nal_unit ”应该是对的吧。先这样认为:)
还有:“ 因为 264 采用了多帧预测,就有可能在 display order 下 I 帧后的 P 会参考 I 帧前的帧,这样在 random access 时如果只找 I 帧,随后的帧的参考帧可能 unavailable , IDR 就是这样一种特殊的 I 帧,把它定义为确保后面的 P 一定不参考其前面的帧,可以放心地 random access 。