x264学习笔记(一)

心已赠人 2022-06-08 07:57 221阅读 0赞

问题1:如何识别关键帧?

从x264的源代码中可以看到,如果某一帧为关键帧,这么这一帧的所携带的几个nalu中,必然有一个的type 必然为NAL_SLICE_IDR。

[cpp] view plain copy

  1. /* Set output picture properties */
  2. if( h->sh.i_type == SLICE_TYPE_I )
  3. pic_out->i_type = h->i_nal_type == NAL_SLICE_IDR ? X264_TYPE_IDR : X264_TYPE_I;
  4. else if( h->sh.i_type == SLICE_TYPE_P )
  5. pic_out->i_type = X264_TYPE_P;
  6. else
  7. pic_out->i_type = X264_TYPE_B;

我的理解就是如果nalu的type为NAL_SLICE_IDR的话,那么这帧肯定就是关键帧了。

因此只需要判断每一帧的nalu的type中是否包还有type为NAL_SLICE_IDR的,如果有则是关键帧。

判断nalu的type的可用如下的方法。

for(int i=0; i<i_nalu; i++)

{

  1. uint8\_t \*ptr = nalu\[i\];
  2. int type = ptr\[4\]&0x1F;
  3. if(type == NAL\_SLICE\_IDR)
  4. \{
  5. key\_frame = true;
  6. break;
  7. \}

}

判断nalu的type中用到int type = ptr[4]&0x1F; 为什么是0x1F呢,这得说说每个nalu的结构;

nalu有三部分组成。

起始码 nalu_header data

起始码: 分为longcode 和 shortcode ;

longcode :0x 00 00 00 01;

shortcode :0x 00 00 01;

nalu_header:有三个子域;

NALU 头由一个字节组成, 它的语法如下:

  1. +---------------+
  2. |0|1|2|3|4|5|6|7|
  3. +-+-+-+-+-+-+-+-+
  4. |F|NRI| Type |
  5. +---------------+

F: 1 个比特.
forbidden_zero_bit. 在 H.264 规范中规定了这一位必须为 0.

NRI: 2 个比特.
nal_ref_idc. 取 00 ~ 11, 似乎指示这个 NALU 的重要性, 如 00 的 NALU 解码器可以丢弃它而不影响图像的回放. 不过一般情

况下不太关心

这个属性.

Type: 5 个比特.
nal_unit_type. 这个 NALU 单元的类型. 简述如下:

0 没有定义
1-23 NAL单元 单个 NAL 单元包.
24 STAP-A 单一时间的组合包
24 STAP-B 单一时间的组合包
26 MTAP16 多个时间的组合包
27 MTAP24 多个时间的组合包
28 FU-A 分片的单元
29 FU-B 分片的单元
30-31 没有定义

大家可以看到,要获得type的话,就得将nalu起始码后面紧跟的第一个字节的内容与0x1F做与运算后得到。

问题2:如何判断每一帧的中nalu的起始和结束。

数据在经过int x264_nal_encode( void *, int *, int b_annexeb, x264_nal_t *nal )后,会将数据组装成nalu的标准格式,即按照上面的格式:

起始码 nalu_header data。

x264使用0x 00 00 00 01作为起始码(longcode)。int x264_nal_encode( void *, int *, int b_annexeb, x264_nal_t *nal )的作用就是使得数据流中不会再出现连续的两个以上的0。如果有的话就会插入一个0x03;

因此如果要还原一帧数据中的逻辑结构的话,可以遍历数据流,寻找0x00000001这样的特征代码。

这一点对于使用x264自带的mkv文件保存接口很是有用。因为我们接收到的网络数据可能没有没有带上详细的nalu分界信息和帧类型,需要自己重新还原。

发表评论

表情:
评论列表 (有 0 条评论,221人围观)

还没有评论,来说两句吧...

相关阅读

    相关 QT x264

    废了我4天总算在win平台下 QT上实现x264编码成功,对于那个bug 认为还是要先了解程序的原理才好排错,但是正是这个bug让我学到了很多,学会了如何可以将lib编译成可以

    相关 x264学习笔记

    问题1:如何识别关键帧? 从x264的源代码中可以看到,如果某一帧为关键帧,这么这一帧的所携带的几个nalu中,必然有一个的type 必然为NAL\_SLICE\_IDR。