H.264中NAL、Slice与frame意思及相互关系

H.264中NAL、Slice与frame意思及相互关系

NAL nal_unit_type中的1(非IDR图像的编码条带)、2(编码条带数据分割块A)、3(编码条带数据分割块B)、4(编码条带数据分割块C)、5(IDR图像的编码条带)种类型


Slice种的三种编码模式:I_slice、P_slice、B_slice

还有frame的3种类型:I frame、P frame、 B frame之间有什么映射关系么?

最后,NAL nal_unit_type中的6(SEI)、7(SPS)、8(PPS)属于什么帧呢?

不好意思,文档看得头晕晕的了,问题比较多~~~
PS:偶是新人 没多少分,要是哪位达人帮忙下的话  我就给我所有的分,好像只有十几分

1 frame的数据可以分为多个slice.
每个slice中的数据,在帧内预测只用到自己slice的数据, 与其他slice 数据没有依赖关系。
NAL 是用来将编码的数据进行大包的。 比如,每一个slice 数据可以放在NAL 包中。
I frame 是自己独立编码,不依赖于其他frame 数据。
P frame 依赖 I frame 数据。
B frame 依赖 I frame, P frame 或其他 B frame 数据。

建议楼主看一点视频编码的书吧, 自己看标准还是很难懂的。

那NAL nal_unit_type中的哪几种类型是I frame,现在只能确定nal_unit_type==5(IDR图像的编码条带)是I frame

sps、pps、SEI算不算I frame呢? 还有 属于编码条带分割的DPA、DPB、DPC呢?

能给个从视频流中提取I frame 和P frame的方法么?

谢谢楼上的回复,我也翻了两三本视频的书籍,感觉都是一个样的,都很少说到点的。楼主能推荐一两本好点的视频书籍么?

没人回答么??

直接给你代码吧 :)

//
// H.264 NAL type
enum H264NALTYPE{
H264NT_NAL = 0,
H264NT_SLICE,
H264NT_SLICE_DPA,
H264NT_SLICE_DPB,
H264NT_SLICE_DPC,
H264NT_SLICE_IDR,
H264NT_SEI,
H264NT_SPS,
H264NT_PPS,
};
int H264GetNALType(LPVOID pBSBuf, const LONG nBSLen)
{
if ( nBSLen < 5 )  // 不完整的NAL单元
return H264NT_NAL;

UINT8* pBS = (UINT8 *)pBSBuf;
ULONG nType = pBS[4] & 0×1F;  // NAL类型在固定的位置上 H.264中NAL、Slice与frame意思及相互关系_第1张图片
if ( nType <= H264NT_PPS )
return nType;

return 0;
}

其中 H264NT_SLICE_IDR 是关键帧,H264NT_SLICE 是P帧

一个frame是可以分割成多个Slice来编码的,而一个Slice编码之后被打包进一个NAL单元,不过NAL单元除了容纳Slice编码的码流外,还可以容纳其他数据,比如序列参数集SPS。

1、NAL、Slice与frame意思及相互关系

NAL指网络提取层,里面放一些与网络相关的信息
Slice是片的意思,264中把图像分成一帧(frame)或两场(field),而帧又可以分成一个或几个片(Slilce);片由宏块(MB)组成。宏块是编码处理的基本单元。

2、NAL nal_unit_type中的1(非IDR图像的编码条带)、2(编码条带数据分割块A)、3(编码条带数据分割块B)、4(编码条带数据分割块C)、5(IDR图像的编码条带)种类型
与 Slice种的三种编码模式:I_slice、P_slice、B_slice
NAL nal_unit_type 里的五种类型,代表接下来数据是表示啥信息的和具体如何分块。
I_slice、P_slice、B_slice 表示I类型的片、P类型的片,B类型的片.其中I_slice为帧内预测模式编码;P_slice为单向预测编码或帧内模式;B_slice 中为双向预测或帧内模式。

3、还有frame的3种类型:I frame、P frame、 B frame之间有什么映射关系么?
I frame、P frame、 B frame关系同 I_slice、P_slice、B_slice,slice和frame区别在问题1中已经讲明白。

4、最后,NAL nal_unit_type中的6(SEI)、7(SPS)、8(PPS)属于什么帧呢?
NAL nal_unit_type 为序列参数集(SPS)、图像参数集(PPS)、增强信息(SEI)不属于啥帧的概念。表示后面的数据信息为序列参数集(SPS)、图像参数集(PPS)、增强信息(SEI)。

能给个从视频流中提取I frame 和P frame的方法么?
可以看slice中的头信息。

查找NAL起始码,然后读取NAL类型不就可以了吗

pBS[4] & 0×1F 

怎么是第5个字节的第五位啊  前面4字节分别是什么(值)?

NAL单元的第1个字节的低五位吧?

然后在问个问题,怎么在一段视频流中检测 NAL的开始和结束?

引用 5 楼 hugeice 的回复:
直接给你代码吧 :)

//
// H.264 NAL type
enum H264NALTYPE{
H264NT_NAL = 0,
H264NT_SLICE,
H264NT_SLICE_DPA,
H264NT_SLICE_DPB,
H264NT_SLICE_DPC,
H264NT_SLICE_IDR,
H264NT_SEI,
H264NT_SPS,
H264NT_PPS,
};
int H264GetNALType(LPVOID pBSBuf, const LONG nBSLen)
{
if ( nBSLen < 5 )  // 不完整的NAL单元…

H.264视频流是以NAL单元传送的。。。但在一个NAL单元里面,可能既存放I-Slice(P-Slice或B-Slice),同事也可能存放图像的其他信息
那么 是不是说 I frame, P frame,B frame是把收到的NAL单元中的VCL的信息先提取出,然后按内容进行I、P、B frame分类?

而我们只能通过NAL nal_unit_type来判别NAL单元中数据的类型哈~~~

====================================================================
 
 
 

《如何结合H.264标准看JM代码》这个web文件,大家都应该有了吧。不过,那个web文档是“H.264乐园”群中聊天的内容,因此看的不是很方便......我在开学来的时候看的时候,做了一些总结,希望与大家分享!不对的地方请指正!

 

1、一个sps后,有若干个pps吗?
      这主要又编码器决定,但JM代码中只有一个

 

2、标准中第二栏的C是什么意思?
    请看标准7.2--分类(在表中以C标记)表明了片数据被划分为三类片数据分割的情况。片数据A类分割包含所有的2类语法元素。片数据B类分割包含所有的3类语法元素。片数据C类分割包含所有的4类语法元素。其他类语法元素取值的含义未做规定。对于某些语法元素,使用一个垂直竖线表示其包含两类语法元素。在这种情况下,该语法元素将使用的分类值将在文本中进一步确定。

3、一个NALU对应一个片吗?
    这种说法不太准确,NALU 包括一个片、SPS、PPS、SEI等等

 

4、decode_one_frame()包括I、P、B

 

5、 case NALU_TYPE_SLICE:
      case NALU_TYPE_IDR:
      case NALU_TYPE_DPA
      case NALU_TYPE_DPB:
      case NALU_TYPE_DPC
      case NALU_TYPE_SEI:
      case NALU_TYPE_PPS
      case NALU_TYPE_SPS
      case NALU_TYPE_AUD:
      case NALU_TYPE_EOSEQ:
      case NALU_TYPE_EOSTREAM:
      case NALU_TYPE_FILL
     问题:什么时候进入哪个,有什么说明的文章或书么?
        答 :进入哪个 case 是由从 NALU 头里解码出来的 nalu_type 决定的

 

6、解码器中的误码隐藏只对丢包有用,丢包之后,包的序号不连续,解码器一旦检测到包序号不连续就会将不连续地方的 ei_flag  置 1

 

7、字节流格式和RTP格式码流,具体的不同点有哪些?相关的资料哪里有?
      字节流格式主要用于文件存储,因此在该格式码流中 NALU 前面只有一个开始前缀,RTP格式码流因为需要进行网络传输, 因此 NALU 前面还有很多辅助信息

 

8、rtp格式就是在字节流前加包头吗?
      不是,字节流=开始前缀+NALU,而 RTP 中没有 开始前缀

 

9、RTP中没有开始前缀,为什么还是要插03?
       防止伪起始码、、RTP完全可以不用起始码,或许是为了与字节流格式统一吧

 

10、NALU是对RBSP的封装。而RTP之类的是对NALU的封装。

 

11、为什么要分ABC片?
        ——分ABC片主要目的是为了对重要程度不同的数据进行不同程度的保护

 

12、baseline没有数据分割吧?
      baseline只是如何产生RBSP,如何封装NALU。具体如何传输,RTP之类只是一种方式,文件copy也是一种方式,那一般 baseline最多有多少参考帧?任意个。

 

13、解码profile_idc之后解码器要做什么工作?比如baseline不支持CABAC那么后面相应的位entropy_coding_mode_flag是不是就不存在了,如果存在,相抵触怎么办?
      当然不会执行 CABAC 的代码,编码器如果是编码 baseline ,那么码流中自然就不存在与 CABAC 相关的语法元素,例如  entropy_coding_mode_flag ,解码器解码 SPS ,得知码流是 baseline 后,自然也就不会去调用与 CABAC 相关的解码程 序,也就不会出错了。profile_idc 为 baseline ,active_pps->entropy_coding_mode_flag 就不会为 CABAC,,码流是 否是 baseline 并不是由多少个参考帧决定的

 

14、JM 进行 CAVLC 编码时候,对于 level = 8 的情况是采用 escape suffix 处理的,我修改代码将 level = 8 的情况采用无符号数表示,结果编码出来的码流与未修改完全一样

附:RBSP、SODB、EBSP三者的区别和联系!
        SODB:最原始的编码数据,没有任何附加数据
        RBSP:在 SODB 的基础上加了rbsp_stop_ont_bit(bit 值为 1)并用 0 按字节补位对齐
        EBSP:在 RBSP 的基础上增加了防止伪起始码字节(0X03)

       1、1 frame的数据可以分为多个slice.
       2、每个slice中的数据,在帧内预测只用到自己slice的数据, 与其他slice 数据没有依赖关系。
       3、NAL 是用来将编码的数据进行大包的。 比如,每一个slice 数据可以放在NAL 包中。
       4、I frame. 是自己独立编码,不依赖于其他frame. 数据。
            P frame. 依赖 I frame. 数据。
            B frame. 依赖 I frame, P frame. 或其他 B frame. 数据。

     一个frame是可以分割成多个Slice来编码的,而一个Slice编码之后被打包进一个NAL单元,不过NAL单元除了容纳Slice编码的码流外,还可以容纳其他数据,比如序列参数集SPS。

 

15、NAL、Slice与frame意思及相互关系

NAL指网络提取层,里面放一些与网络相关的信息
Slice是片的意思,264中把图像分成一帧(frame)或两场(field),而帧又可以分成一个或几个片(Slilce);片由宏块(MB)组成。宏块是编码处理的基本单元。

 

16、NAL nal_unit_type中的1(非IDR图像的编码条带)、2(编码条带数据分割块A)、3(编码条带数据分割块B)、4(编码条带数据分割块C)、5(IDR图像的编码条带)种类型与 Slice种的三种编码模式:I_slice、P_slice、B_slice NAL nal_unit_type 里的五种类型,代表接下来数据是表示啥信息的和具体如何分块。I_slice、P_slice、B_slice 表示I类型的片、P类型的片,B类型的片.其中I_slice为帧内预测模式编码;P_slice为单向预测编码或帧内模式;B_slice 中为双向预测或帧内模式。

 

17、还有frame的3种类型:I frame、P frame、 B frame之间有什么映射关系么?
I frame、P frame、 B frame关系同 I_slice、P_slice、B_slice,slice和frame区别在问题1中已经讲明白。

 

18、最后,NAL nal_unit_type中的6(SEI)、7(SPS)、8(PPS)属于什么帧呢?
NAL nal_unit_type 为序列参数集(SPS)、图像参数集(PPS)、增强信息(SEI)不属于啥帧的概念。表示后面的数据信息为序列参数集(SPS)、图像参数集(PPS)、增强信息(SEI)。

========================================================
 
 
首先我觉得先要找相关书籍把基本原理搞懂,不要急于看标准和源代码。要知道什么是采样格式,什么是I、P、B,他们的原理是什么,了解CAVLC、CABAC熵编码的实现过程,一定要认认真真。这样各个主要模块攻克之后,你就可以结合标准和源代码一步一步的看下去。

 


    下面以解码过程为例说一下具体过程:


        1、 过程:码流→NALU→RBSP。





如果是字节流的码流当然就首先要对字节流进行解析,这就要看附录 B 了,如何查找起始码和去除伪起始码(为什么有伪起始码呢?);如果是 RTP 格式的码流,那就要按 RFC3984 来解析了(标准没有规定 RTP 格式码流的解析过程);字节流解析完后提取出来的就是 NALU 了,对 NALU 的解析就要看第七章了。黑色的粗体字都是在码流中可能出现的语法元素,解码器的首要任务就是要对这些语法元素进行解析。对于这些码流中的语法元素我们要进行解析必须知道三个问题:

(1)、什么时候存在于码流中?这样我们才能知道当前解析的是哪个语法元素;

  (2)、采用什么样的熵编码方式?这样我们才能知道如何解析;
  (3)、含义是什么?这样我们才知道解析出来之后用来干什么。

NALU 的前面三个语法元素所组成的一个字节我们称为 NALU 头,其余部分(也就是语法表 7.3.1 中的其余部分)我们称为 NALU 体。对 NALU 体的解析要看 7.3.2 小节。因为 NALU 有很多种类型,所以要针对 NALU 的不同类型去解析 NALU 体(表 7-1 说明了不同 NALU 对应的语法表)。例如,如果当前的 NALU 是 SPS,那么当然就要看 7.3.1 小节;如果当前的 NALU 是 DPA,那么当然就要看 7.3.2.9.1 小节了;
         2、对于属于 VCL 的 NALU(哪些 NALU 是 VCL NALU 呢?如果你看了 nal_unit_type 的语义,你就应该知道),例如表 7-1 中类型为 5 的 NALU,根据表 7-1 我们知道 NALU 体的语法表是 7.3.2.8。而从 7.3.2.8 我们可以看到,对这种 NALU 的 NALU 体解析实际就是对片级语法进行解析。语法表 7.3.2.8 显示片级语法解析首先要解析 slice_header()(这种带括号的表示是另一个语法结构),那么 slice_header() 怎么解析呢?往下看,7.3.3 的所有内容都被第一行的 slice_header() 包括在内,所以 7.3.3 就是对 slice_header() 这个语法层的码流规定;
        3、按照语法表 7.3.2.8 解析完了 slice_header() 就该解析 slice_data() 了。下面以最常见的 I 帧(CAVLC 熵编码、非 MBAFF)的解析过程为例简单描述怎么继续读标准。这时在码流中出现的第一个 slice_data() 层的语法元素是语法表 7.3.4 中的 macroblock_layer(),也就是说直接到了宏块层的语法解析,那就要又要看 7.3.5 小节了;
      4、基于我们对编解码流程的了解,我们知道解码是一个预测值加残差得到重建图像的过程,那么我们下面的解码过程就要分成两步走了:首先,得到预测值;其次,得到残差。基于我们对 H.264 关键技术的了解,我们知道 intra 宏块(提醒:我们举的例子是 I 帧,因此解析的是 intra 宏块)的预测值是需要使用到预测模式的,所以我们需要解析语法表 7.3.5 中的 mb_pred(mb_type) 语法层,那么又去看 7.3.5.1 小节。按照 7.3.5.1 小节解析出宏块或块的预测方式后我们怎么计算预测值呢?去看标准 8.3 小节;得到预测值后我们继续按照语法表 7.3.5 解析语法元素直到 residual() 语法层,这就又要去看 7.3.5.3 小节;按照 7.3.5.3 小节解析出残差系数后我们如何把它还原成真实的残差呢?去看标准 8.5 小节;
        5、预测值和残差都有了,加起来就是解码图像了。解码的主要工作到此也算基本完成了。当然,上面的过程中还会用到标准其他章节的相关内容(例如,8.5 小节会用到 5.7 小节中定义的 InverseRasterScan)总体过程也就如此吧,详细内容要大家自己去认真的学习


来源:http://blog.chinaunix.net/uid-20235103-id-1970924.html

你可能感兴趣的:(H264,流媒体协议)