H.264中I帧和IDR帧

IDR帧的作用是立刻刷新, 使错误不致传播。从IDR帧开始, 重新算一个新的序列开始编码。而I帧不具有随机访问的能力,这个功能是由IDR承担。IDR帧会导致DPB (DecodedPictureBuffer 参考帧列表——这是关键所在)清空,而I不会。

在IDR帧之后的所有帧都不能引用任何IDR帧之前的帧的内容,而普通的I帧之后的B和P帧可以引用位于普通I帧之前的I帧。

从随机存取的视频流中,播放器永远可以从一个IDR帧播放,因为在它之后没有任何帧引用之前的帧。但是,不能在一个没有IDR帧的视频中从任意点开始播放,因为后面的帧总是会引用前面的帧。

x264的x264_encoder_encode()中有一段代码:

if( !IS_X264_TYPE_I( h->fenc->i_type ) )//su: 如果当前帧不是关键帧
    {
        int valid_refs_left = 0;
        for( int i = 0; h->frames.reference[i]; i++ )
            if( !h->frames.reference[i]->b_corrupt )
                valid_refs_left++;
        /* No valid reference frames left: force an IDR. */
        if( !valid_refs_left )
        {
            h->fenc->b_keyframe = 1;
            h->fenc->i_type = X264_TYPE_IDR;
        }
    }

这段代码的意思是,从当前帧位置向前寻找参考帧,如果当前帧不会参考前面的帧,那么就强制设成IDR帧。

if( h->fenc->i_type == X264_TYPE_IDR )
    {
        /* reset ref pictures */
        i_nal_type    = NAL_SLICE_IDR;
        i_nal_ref_idc = NAL_PRIORITY_HIGHEST;
        h->sh.i_type = SLICE_TYPE_I;//su: Slice header类型
        reference_reset( h );
        h->frames.i_poc_last_open_gop = -1;
    }

如果是IDR帧,在reference_reset函数中,会清空参考帧列表:

static inline void reference_reset( x264_t *h )
{
    while( h->frames.reference[0] )
        x264_frame_push_unused( h, x264_frame_pop( h->frames.reference ) );
    h->fdec->i_poc =
    h->fenc->i_poc = 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值