H.264中IDR帧和I帧区别
最后发布:2017-04-28 09:39:47 首次发布:2017-04-28 09:39:47I和IDR帧都是使用帧内预测的。它们都是同一个东西而已,在编码和解码中为了方便,要首个I帧和其他I帧区别开,所以才把第一个首个I帧叫IDR,这样就方便控制编码和解码流程。IDR帧的作用是立刻刷新,使错误不致传播,从IDR帧开始,重新算一个新的序列开始编码。而I帧不具有随机访问的能力,这个功能是由IDR承担。IDR会导致DPB(DecodedPictureBuffer参考帧列表——这是关键所在)清空,而I不会。IDR图像一定是I图像,但I图像不一定是IDR图像。一个序列中可以有很多的I图像,I图像之后的图像可以引用I图像之前的图像做运动参考。 对于IDR帧来说,在IDR帧之后的所有帧都不能引用任何IDR帧之前的帧的内容,与此相反,对于普通的I-帧来说,位于其之后的B-和P-帧可以引用位于普通I-帧之前的I-帧。从随机存取的视频流中,播放器永远可以从一个IDR帧播放,因为在它之后没有任何帧引用之前的帧。但是,不能在一个没有IDR帧的视频中从任意点开始播放,因为后面的帧总是会引用前面的帧。
普通I帧与IDR(Instantaneous Decoding Refresh,瞬时解码刷新)帧为均采用帧内预测技术的视频帧,同属于I帧。
区别是:采用IDR帧编码,会导致DPB(Decoded Picture Buffer,直译为解码图像缓冲区,即指参考帧列表)完成一次清空处理,而普通I帧不会。
那么,这样带来的直接结果是怎样的呢?
即,当前IDR帧后面的帧不会将当前IDR帧之前已经编码的帧作为参考帧;而当前普通I帧之后的帧有可能将当前I帧之前的帧作为参考帧。
那么,这样带来的直接效果是怎样的呢?
即,播放视频的时候,可以直接从IDR帧开始播放,因为IDR帧之前的帧与当前IDR帧和之后的帧再也没有直接地关联;而普通I帧则不行。
可以看到,一般来讲,一段视频的第0帧(也即首帧)是I帧,那么它算不算是IDR帧呢?答:算。
所以,IDR帧一定是I帧,反之不成立。
在H.264标准参考软件(JM)下,通过IDRIntraEnable来设置是否支持IDR帧。
在H.264编码中为了提高编码效率,采用了与传统MPEG-2编码不同的帧预测方式,在H.264编码中的B、P帧与MPEG-2中的B、P帧具有不同的帧间预测特性,H.264中的B、P帧能以多个视频帧做为参考帧,以获取更高的压缩比,正是这些新的特性进一步提高了H.264编码的压缩效率。为此,也在H.264编码中引入了一个关键帧的概念即IDR帧。
IDR帧是一个GOP(Group of Pictures)中的首个I帧,即从IDR帧开始,重新开始一个新的序列编码,它的作用是使解码器立即刷新,从而使预测错误不致传播,并提供随机访问的能力。一个GOP中可以有很多的I帧,但只能有一个IDR帧。IDR帧一定是I帧,但I帧不一定是IDR帧。对IDR帧的编码处理与I帧的处理相同:(1)进行帧内预测,决定所采用的帧内预测模式。(2)像素值减去预测值,得到残差。(3)对残差进行变换和量化。(4)变长编码和算术编码。(5)重构图像并滤波,得到的图像作为其它帧的参考帧。
H.264与MPEG-2编码的不同是,相对普通的I帧,位于其之后的B帧和P帧可以引用位于其之前的图像帧最为参考,而对于IDR帧来说,在IDR帧之后的所有帧都不能引用其之前的帧的内容。由此可以看出,从随机存取的视频流中,播放器永远可以从一个IDR帧播放,因为在它之后没有任何帧引用之前的帧。但是,不能在一个没有IDR帧的视频中从任意点开始播放,因为后面的帧总是会引用前面的帧进行帧间预测。
IDR就是这样一种特殊的I帧,它确保后面的任何帧一定不参考其前面的帧,可以放心地作为关键帧,而将快编后的重新编码计算量限定在编辑点前后2个GOP之内。
通过IDR帧的原理,我们可以看出,如果一个视频流的GOP的第一帧不是IDR帧而是普通I帧,会因为H.264采用了多帧预测,有可能I帧后的P、B会参考I帧前的帧,这样在编辑时如果以任意帧为编辑点,则随后的帧都应重新进行预测编码,这无疑会增加设备的运算量,降低编辑效率。
一幅图像根据概念来分可以分为两种:IDR图像和非IDR图像。一幅图像是否是IDR图像是由组成该图像的NALU值决定的,如果组成该图像的NALU如“图1”语法结构中nal_unit_type值为5,则该图像为IDR帧,否则为非IDR帧。由此我们可以得出这样的结论:
(1)nal_unit_type值为5的NALU只会出现在IDR帧中,而IDR帧中的所有NALU都是nal_unit_type 值为5的NALU;
(2)我们以组成一幅图像的帧的类型来区分该图像是否是IDR图像是不对的。一个图像序列中的所有帧都是I帧并不代表这个图像就是IDR图像。因为I帧也可以从属于nal_unit_type值为1的NALU。
可见,在编码器设置中进行参数设定,适时指定IDR帧十分重要。
H.264中普通I帧和IDR帧究竟有什么区别?(不要与MPEG2中的I帧搞混淆了)
分类: 视频相关研究
2012-11-16 16:12 1780人阅读 评论(0) 收藏 举报
纠结概念的人不少,这是个好事,但有时用实验的方法自己亲自分析一下会更好. 一次刻骨铭心的体验胜过千百次的说教, 闲话少扯,进入正题.
在MPEG2中,有个重要的概念叫GOP(group of pictures),假设编码的帧类型为:IBBPBBPBBPBBIBBPBBPBBPBBI…, 那么这个IBBPBBPBBPBB就叫一个GOP. 由于误差会积累,但MPEG2中的I帧可以阻断误差的积累,也就是说,在MPEG中I帧后面的帧永远不会参考I帧前面的帧,也就是说,一个GOP中的帧永远不会参考前一个GOP中的帧.(另外说句题外话:B帧可以参考下一个GOP的I帧,但在MPEG2中,B帧不会作为参考帧,所以B帧不会导致误差积累)
在H.264中就不同了.很多人说,在H.264中没有I帧这个概念了,当然这也是有道理的,标准中的确没有这么叫,但是,为了方便,也可以延续I帧这个概念,那么H.264中什么叫I帧呢?
定义:H.264中的I帧是指帧中的宏块都是采用帧内预测方式,在H.264中有两种I帧: 普通I帧和IDR帧(特殊I帧).
在H.264中,是IDR帧阻断了误差的积累, IDR帧后面的帧都不能参考该IDR帧前面的帧. 在H.264中,普通的I帧并没有阻断误差的积累,那就是说普通I帧后面的帧就可以参考该I帧之前的帧么?事实正是如此. 下面用H.264visa加以分析验证.
再次总结:在H.264中,I帧分为普通I帧和IDR帧(特殊I帧); 在H.264中,是IDR帧阻断了误差的积累, IDR帧后面的帧都不能参考该IDR帧前面的帧, 普通的I帧并没有阻断误差的积累,普通I帧后面的帧可以参考该I帧之前的帧. 在MPEG2中,I帧阻断了误差的积累,I帧后面的帧不可以参考该I帧之前的帧. 从这个意义上说,H.264中的IDR帧颇有MPEG2中I帧的味道.
I帧和IDR帧的区别
分类:H.264
2006-08-15 14:34
阅读(761)评论(0)
看代码看得头昏脑胀,有时会上网搜索一些自己比较困扰的问题,觉得大家好强啊。其实,任何成功的人都是一步步走到今天的,小贝也是每日苦练才踢出著名香蕉球的啊。可是,我常想我会有这样的一天吗?……好奇妙的感觉,怀着80%的担心和20%的欣喜。算了,不要胡思乱想了。
看一个问题:
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 data 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 );)。其实,我们的程序默认只用一个参考帧,这个问题就不是十分有意义了。
多参考帧情况下。
举个例子:有如下帧序列:IPPPPIPPPP……(我们程序没有B帧,所以帧序列简单些,但道理是一样的)。按照3个参考帧编码。
因为“按照3个参考帧编码”,所以参考帧队列长度为3。
遇到绿色的I时,并不清空参考帧队列,把这个I帧加入参考帧队列(当然I编码时不用参考帧。)。再检测到红色的P帧时,用到的就是PPI三帧做参考了。
不怕自己罗嗦(好记性不如烂笔头),再强调一个:一个参考帧,就是参考当前帧的前面的那帧(因为没涉及到B帧,所以“前面的那帧”既是播放顺序的,也是编码顺序的)。多个参考帧是一个道理。(我以前一直误解为从前面的几帧中找到最合适的一个参考帧)
最后,“但是收到IDR帧时,解码器另外需要做的工作就是:把所有的PPS和SPS参数进行更新。由此可见,在编码器端,每发一个IDR,就相应地发一个 PPS&SPS_nal_unit”应该是对的吧。先这样认为:)
偶然机会,查到:IDR-instantaneous decoding refresh (IDR)picture;
A coded picture in which all slices are I or SI slices that causes the decoding process to mark all reference pictures as “unused for reference” immediately after decoding the IDR picture. After the decoding of an IDR picture all following coded pictures in decoding order can be decoded without inter prediction from any picture decoded prior to the IDR picture. The first picture of each coded video sequence is an IDR picture.
“也就是说,IDR的出现其实是相当于向解码器发出了一个清理reference buffer的信号吧,上面说前于这一帧的所有已编码帧不能为inter做参考帧了。”
还有:“因为264采用了多帧预测,就有可能在display order下I帧后的P会参考I帧前的帧,这样在random access时如果只找I帧,随后的帧的参考帧可能unavailable,IDR就是这样一种特殊的I帧,把它定义为确保后面的P一定不参考其前面的帧,可以放心地random access。 ”