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 。
IDR与GOP:
疑问:
在研究x264的参数的时候,接触到了很多概念,IDR和GOP的概念让我有点糊涂。
我知道H.264有I帧(完全的图像,体积也最大),P帧(记录相对于前面I和P的差异,体积变小),B帧(记录前后帧的差异,体积最小)。B帧还分为2种:不可被参考的,和可被参考的。B帧也可作为参考帧啊!!!!
我不太清楚GOP(Group of Pictures)到底是起什么作用,为什么会有GOP这个概念呢?
按照网上的说法,GOP是以I帧分割的图片序列,换句话说,GOP的值是指第一个I帧,到最后一个I帧之前的帧的数量。比如:IPPPPPI,GOP=6
关于GOP我看到2种说法,一种说法如上,1个GOP里面只有一个I帧,第二种说法是1个GOP里面可以有好几个I帧,所以我就糊涂了。
IDR帧也是让我糊涂的地方,据我查到的资料,IDR是强制刷新帧,因为P和B都不是记录完整信息,记录的是与其它帧的差异,所以如果I帧本身有错误,这个错误就会遗传到下面的帧,但碰到IDR帧的时候,播放器丢弃以前所以的信息,从新开始解码,错误也就到此为止。
但这不就是I帧本身固有的特点么,因为I帧就是记录全部信息的,不用参考任何其它帧,以全新的I帧开始遗传,错误也是到此为止啊,那何必弄出个IDR的概念呢?请赐教
解答:
IDR frame:I和IDR帧都使用帧内预测,在编码解码中为了方便,首个I帧要和其他I帧区别开,把第一个I帧叫IDR,这样方便控制编码和解码流程,所以IDR帧一定是I帧,但I帧不一定是IDR帧;IDR帧的作用是立刻刷新,使错误不致传播,从IDR帧开始算新的序列开始编码。I帧有被跨帧参考的可能,IDR不会。
第一种说法是针对Mpeg2的,这里面一个GOP只有且只有一个在组头的I帧;第二种说法是针对h264的新特性
I帧不用参考任何帧,但是之后的P帧和B帧是有可能参考这个I帧之前的帧的。IDR就不允许这样。
如:
IDR1 P4 B2 B3 P7 B5 B6 I10 B8 B9 P13 B11 B12 P16 B14 B15 这里的B8可以跨过I10去参考P7
而
IDR1 P4 B2 B3 P7 B5 B6 IDR8 P11 B9 B10 P14 B11 B12 这里的B9就只能参照IDR8和P11,不可以参考IDR8前面的帧。
结论:
每个GOP一定是以一个I帧开始的,但是却不一定指代的是两个I帧之间的距离。因为一个GOP内可能包含几个I帧,只有第一个I帧(也就是第一帧)才是关键帧。