什么是H.264

  • H264 是 MPEG-4 标准所定义的最新编码格式,同时也是技术含量最高、代表最新技术水平的视频编码格式之一,标准写法应该是H.264
  • H264 视频格式是经过有损压缩的,但在技术上尽可能做的降低存储体积下获得较好图像质量和低带宽图像快速传输。
  • 总结:H.264是一种视频压缩算法,因为不压缩视频会变得巨大
    1280 * 720 *30 / 8(字节) /1024(KB)/1024(MB) = 3.11MB,这还是一个像素点只有一个bit的情况,实际情况会更加大。

视频压缩原理

  • 空间冗余: 图中TOM猫的皮肤毛色都是一样的数据,背景色都是同样的数据,可以对这部分数据进行压缩
  • 时间冗余:视频是连续的,按照我们的PFS是30的情况下,两帧数据之间的差距很小,那么后一帧的数据就可以记录与上一帧的差距而不是图像原本的数据。
  • 知识冗余(选看)
    有许多图像的理解与某些基础知识有相当大的相关性,
    例如:人脸的图像有固定的结构。比如,嘴的上方有鼻子。鼻子的上方有眼睛,鼻子位于正脸图像的中线上等等。这类规律性的结构可由先验知识相背景知识得到,我们称此类冗余为知识冗余。
  • 结构冗余(选看)
    有些图像从大域上看存在着非常强的纹理结构,例如布纹图像和草席图像,我们说它们在结构上存在冗余。
  • 视觉冗余(选看)
    人类视觉系统对于图像场的任何变化,并不是都能感知的。例如,对于图像的编码和解码处理时,由于压缩或量比截断引入了噪声而使图像发生了一些变化,如果这些变化不能为视觉所感知,则仍认为图像足够好。事实上人类视觉系统一般的分辨能力约为26灰度等级,而一般图像量化采用28灰度等级,这类冗余我们称为视觉冗余。
    通常情况下,人类视觉系统对亮度变化敏感,而对色度的变化相对不敏感;在高亮度区,人眼对亮度变化敏感度下降。

H264原始码流结构

  • 组成:H264功能分为两层,VCL(视频编码层)和 NAL(网络提取层).
  • VCL:包括核心压缩引擎和块,宏块和片的语法级别定义,设计目标是尽可能地独立于网络进行高效的编码。
  • NAL:负责将VCL产生的比特字符串适配到各种各样的网络和多元环境中,覆盖了所有片级以上的语法级别。
  • 现在有一个H.264文件,用H.264分析器打开。


    可以看出H.264文件是由一段一段的数据组成,这一段一段的数据就是NALU,如下图所示

NALU组成

  • VCL数据传输或者存储之前,会被映射到一个NALU中,H264数据包含一个个NALU
  • 一个NALU包含 START CODE、NALU HEADER、RBSP
  • START CODE :00 00 00 01 代表一个NALU的开始
  • NALU HEADER:紧跟在start code后面的一个字节 ,其各个bit的含义如下

    例如
    此处的00 00 00 01 67:其中0x67 0110 0111,从左往右开始数
    (forbidden bit)bit 0 : 0代表合法数据
    (nal_rel_idc)bit 2~3:代表了这个NALU的重要程度为3,最重要的级别
    (nal_unit_type)bit 4~8:7表示这是一个序列参数集(SPS)

NALU的分类

  • 从这张图中我们可以看出来 NALU分分为SPSPPSSEIIDR_SLICESLICE,并且这些NALU组成了一个序列

sequence(序列)

  • 一个H264视频由多个nal组成,
  • 多种不同类型的NAL组成sequence(序列),
  • 一个H264视频包含一个或者多个序列,
  • 在H3516EV200中一个序列代表的是一秒内采集到的视频数据的集合。在FPS为30的情况下,一个squence包含一个SPS、一个PPS、一个SEI、一个IDR(非参考帧,图像原本的数据)、30-1=29个PDR(参考帧,记录图像的变化)

SPS

  • 概述:即Sequence Paramater Set,又称作序列参数集。SPS中保存了一组编码视频序列(Coded video sequence)的全局参数。所谓的编码视频序列即原始视频的一帧一帧的像素数据经过编码之后的结构组成的序列。而每一帧的编码后数据所依赖的参数保存于图像参数集中。一般情况SPS和PPS的NAL Unit通常位于整个码流的起始位置。但在某些特殊情况下,在码流中间也可能出现这两种结构,主要原因可能为:

    • 解码器需要在码流中间开始解码;
    • 编码器在编码的过程中改变了码流的参数(如图像分辨率等);
    • 在做视频播放器时,为了让后续的解码过程可以使用SPS中包含的参数,必须对其中的数据进行解析。其中H.264标准协议中规定的SPS格式位于文档的7.3.2.1.1部分
  • 组成

  1. profile_idc:

    • 标识当前H.264码流的profile。我们知道,H.264中定义了三种常用的档次profile:
      基准档次:baseline profile;
      主要档次:main profile;
      扩展档次:extended profile;
    • 在H.264的SPS中,第一个字节表示profile_idc,根据profile_idc的值可以确定码流符合哪一种档次。判断规律为:
      profile_idc = 66 → baseline profile;
      profile_idc = 77 → main profile;
      profile_idc = 88 → extended profile;
    • 在新版的标准中,还包括了High、High 10、High 4:2:2、High 4:4:4、High 10 Intra、High 4:2:2 Intra、High 4:4:4 Intra、CAVLC 4:4:4 Intra等,每一种都由不同的profile_idc表示。
    • 另外,constraint_set0_flag ~ constraint_set5_flag是在编码的档次方面对码流增加的其他一些额外限制性条件。
    • 在我们实验码流中,profile_idc = 0x42 = 66,因此码流的档次为baseline profile。
  2. level_idc

    • 标识当前码流的Level。编码的Level定义了某种条件下的最大视频分辨率、最大视频帧率等参数,码流所遵从的level由level_idc指定。
    • 当前码流中,level_idc = 0x1e = 30,因此码流的级别为3。
  3. seq_parameter_set_id
    表示当前的序列参数集的id。通过该id值,图像参数集pps可以引用其代表的sps中的参数。

  4. log2_max_frame_num_minus4
    用于计算MaxFrameNum的值。计算公式为MaxFrameNum = 2^(log2_max_frame_num_minus4 + 4)。MaxFrameNum是frame_num的上限值,frame_num是图像序号的一种表示方法,在帧间编码中常用作一种参考帧标记的手段。

  5. pic_order_cnt_type
    表示解码picture order count(POC)的方法。POC是另一种计量图像序号的方式,与frame_num有着不同的计算方法。该语法元素的取值为0、1或2。

  6. log2_max_pic_order_cnt_lsb_minus4
    用于计算MaxPicOrderCntLsb的值,该值表示POC的上限。计算方法为MaxPicOrderCntLsb = 2^(log2_max_pic_order_cnt_lsb_minus4 + 4)。

  7. max_num_ref_frames
    用于表示参考帧的最大数目。

  8. gaps_in_frame_num_value_allowed_flag
    标识位,说明frame_num中是否允许不连续的值。

  9. pic_width_in_mbs_minus1
    用于计算图像的宽度。单位为宏块个数,因此图像的实际宽度为:
    frame_width = 16 × (pic_width_in_mbs_minus1 + 1);

  10. pic_height_in_map_units_minus1
    使用PicHeightInMapUnits来度量视频中一帧图像的高度。PicHeightInMapUnits并非图像明确的以像素或宏块为单位的高度,而需要考虑该宏块是帧编码或场编码。PicHeightInMapUnits的计算方式为:
    PicHeightInMapUnits = pic_height_in_map_units_minus1 + 1;

  11. frame_mbs_only_flag
    标识位,说明宏块的编码方式。当该标识位为0时,宏块可能为帧编码或场编码;该标识位为1时,所有宏块都采用帧编码。根据该标识位取值不同,PicHeightInMapUnits的含义也不同,为0时表示一场数据按宏块计算的高度,为1时表示一帧数据按宏块计算的高度。
    按照宏块计算的图像实际高度FrameHeightInMbs的计算方法为:
    FrameHeightInMbs = ( 2 − frame_mbs_only_flag ) * PicHeightInMapUnits

  12. mb_adaptive_frame_field_flag
    标识位,说明是否采用了宏块级的帧场自适应编码。当该标识位为0时,不存在帧编码和场编码之间的切换;当标识位为1时,宏块可能在帧编码和场编码模式之间进行选择。

  13. direct_8x8_inference_flag
    标识位,用于B_Skip、B_Direct模式运动矢量的推导计算。

  14. frame_cropping_flag
    标识位,说明是否需要对输出的图像帧进行裁剪。

  15. vui_parameters_present_flag
    标识位,说明SPS中是否存在VUI信息。

PPS

  • 概述: 除了序列参数集SPS之外,H.264中另一重要的参数集合为图像参数集Picture Paramater Set(PPS)。通常情况下,PPS类似于SPS,在H.264的裸码流中单独保存在一个NAL Unit中,只是PPS NAL Unit的nal_unit_type值为8;而在封装格式中,PPS通常与SPS一起,保存在视频文件的文件头中。
  • 组成
  1. pic_parameter_set_id
    表示当前PPS的id。某个PPS在码流中会被相应的slice引用,slice引用PPS的方式就是在Slice header中保存PPS的id值。该值的取值范围为[0,255]。

  2. seq_parameter_set_id
    表示当前PPS所引用的激活的SPS的id。通过这种方式,PPS中也可以取到对应SPS中的参数。该值的取值范围为[0,31]。

  3. entropy_coding_mode_flag
    熵编码模式标识,该标识位表示码流中熵编码/解码选择的算法。对于部分语法元素,在不同的编码配置下,选择的熵编码方式不同。例如在一个宏块语法元素中,宏块类型mb_type的语法元素描述符为“ue(v) | ae(v)”,在baseline profile等设置下采用指数哥伦布编码,在main profile等设置下采用CABAC编码。
    标识位entropy_coding_mode_flag的作用就是控制这种算法选择。当该值为0时,选择左边的算法,通常为指数哥伦布编码或者CAVLC;当该值为1时,选择右边的算法,通常为CABAC。

  4. bottom_field_pic_order_in_frame_present_flag
    标识位,用于表示另外条带头中的两个语法元素delta_pic_order_cnt_bottom和delta_pic_order_cn是否存在的标识。这两个语法元素表示了某一帧的底场的POC的计算方法。

  5. num_slice_groups_minus1
    表示某一帧中slice group的个数。当该值为0时,一帧中所有的slice都属于一个slice group。slice group是一帧中宏块的组合方式,定义在协议文档的3.141部分。

  6. num_ref_idx_l0_default_active_minus1、num_ref_idx_l0_default_active_minus1
    表示当Slice Header中的num_ref_idx_active_override_flag标识位为0时,P/SP/B slice的语法元素num_ref_idx_l0_active_minus1和num_ref_idx_l1_active_minus1的默认值。

  7. weighted_pred_flag
    标识位,表示在P/SP slice中是否开启加权预测。

  8. weighted_bipred_idc
    表示在B Slice中加权预测的方法,取值范围为[0,2]。0表示默认加权预测,1表示显式加权预测,2表示隐式加权预测。

  9. pic_init_qp_minus26和pic_init_qs_minus26
    表示初始的量化参数。实际的量化参数由该参数、slice header中的slice_qp_delta/slice_qs_delta计算得到。

  10. chroma_qp_index_offset
    用于计算色度分量的量化参数,取值范围为[-12,12]。

  11. deblocking_filter_control_present_flag
    标识位,用于表示Slice header中是否存在用于去块滤波器控制的信息。当该标志位为1时,slice header中包含去块滤波相应的信息;当该标识位为0时,slice header中没有相应的信息。

  12. constrained_intra_pred_flag
    若该标识为1,表示I宏块在进行帧内预测时只能使用来自I和SI类型宏块的信息;若该标识位0,表示I宏块可以使用来自Inter类型宏块的信息。

  13. redundant_pic_cnt_present_flag
    标识位,用于表示Slice header中是否存在redundant_pic_cnt语法元素。当该标志位为1时,slice header中包含redundant_pic_cnt;当该标识位为0时,slice header中没有相应的信息。

GOP(画面组)

  • GOP我个人也理解为跟序列差不多意思,就是一段时间内变化不大的图像集。GOP结构一般有两个数字,如M=3,N=12。M指定I帧和P帧之间的距离,N指定两个I帧之间的距离。上面的M=3,N=12,GOP结构为:IBBPBBPBBPBBI。在一个GOP内I frame解码不依赖任何的其它帧,p frame解码则依赖前面的I frame或P frame,B frame解码依赖前最近的一个I frame或P frame 及其后最近的一个P frame。

IDR

  • 在编码解码中为了方便,将GOP中首个I帧和其他帧分开,把第一个I帧称之为IDR,这样方便控制编码和解码流程,所以IDR帧一定是I帧,但是I帧不一定是IDR帧;IDR帧的作用是立刻刷新,使错误不致传播,从IDR帧开始算新的序列开始编码。I帧有被跨帧参考的可能,IDR不会。

  • I帧不用参考任何帧,但是之后的P帧和B帧是有可能参考这个I帧之前的帧的。IDR就不允许这样例如
    作用:
    H.264引入 IDR 图像是为了解码的重同步,当解码器解码到 IDR图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码。

SLICE

  • 概念:

    1. 表示视频图像数据的NAL Unit包含的语法元素
    2. IDR Slice NAL Type 5
    3. non-IDR Slice NAL Type:1
  • 意义:
    1. 一个Slice:包含某一帧的全部或者部分数据
    2. 防止误码的扩散
    3. 不同的slice之间去解码操作独立
    4. 某一个slice的解码过程锁参考的数据(例如预测编码)不能越过slice的便捷
  • 类型
    根据码流中不同的数据类型,H.264标准中共定义了5总Slice类型:
    I slice: 帧内编码的slice;
    P slice: 单向帧间编码的slice;
    B slice: 双向帧间编码的slice;
    SI slice: 切换Islice,用于扩展档次中码流切换使用;
    SP slice: 切换Pslice,用于扩展档次中码流切换使用;
  • 组成
    每一个Slice由两部分组成,一部分作为Slice header用于保存Slice的总体信息(例如当前Slice的类型),另一部分作为Slice body 通常是一组连续的宏块结构
  • 结构
  1. Slice header:中主要保存了当前slice的一些全局的信息,slice body中的宏块在进行解码时需依赖这些信息。其中比较常见的一些语法元素有:
    irst_mb_in_slice:片中的第一个宏块的地址, 片通过这个句法元素来标定它自己的地址。要注意的是在帧场自适应模式下,宏块都是成对出现,这时本句法元素表示的是第几个宏块对,对应的第一个宏块的真实地址应该是 2 * first_mb_in_slice

  2. slice_type:指明片的类型,IDR 图像时, slice_type 等于 2, 4, 7, 9。

pic_parameter_set_id:当前slice所依赖的pps的id;

colour_plane_id:当标识位separate_colour_plane_flag为true时,colour_plane_id表示当前的颜色分量,0、1、2分别表示Y、U、V分量。

frame_num: 每个参考帧都有一个依次连续的 frame_num 作为它们的标识,这指明了各图像的解码顺序。但事实上我们在表 中可以看到, frame_num 的出现没有 if 语句限定条件,这表明非参考帧的片头也会出现 frame_num。只是当该个图像是参考帧时,它所携带的这个句法元素在解码时才有意义。如表:

field_pic_flag:场编码标识位。当该标识位为1时表示当前slice按照场进行编码;该标识位为0时表示当前slice按照帧进行编码。

bottom_field_flag:底场标识位。该标志位为1表示当前slice是某一帧的底场;为0表示当前slice为某一帧的顶场。

idr_pic_id:表示IDR帧的序号。某一个IDR帧所属的所有slice,其idr_pic_id应保持一致。IDR 图像的标识。不同的 IDR 图像有不同的 idr_pic_id 值。值得注意的是, IDR 图像有不等价于 I 图像,只有在作为 IDR 图像的 I 帧才有这个句法元素,在场模式下, IDR 帧的两个场有相同的 idr_pic_id 值。 idr_pic_id 的取值范围是 [0, 65535],和 frame_num 类似,当它的值超出这个范围时,它会以循环的方式重新开始计数。

pic_order_cnt_lsb:表示当前帧序号的另一种计量方式。

delta_pic_order_cnt_bottom:表示顶场与底场POC差值的计算方法,不存在则默认为0;

slice_qp_delta:指出在用于当前片的所有宏块的量化参数的初始值。
SliceQPY = 26 + pic_init_qp_minus26 + slice_qp_delta
QPY 的范围是 0 to 51。
我们前文已经提到, H.264 中量化参数是分图像参数集、片头、宏块头三层给出的,前两层各自给出一个偏移值,这个句法元素就是片层的偏移。

整个slice header的结构如下表所示:

宏块

  • mb_type 确定该 MB 是帧内或帧间(P 或 B)编码模式,确定该 MB 分割的尺寸
  • mb_pred 确定帧内预测模式(帧内宏块)确定表 0 或表 1 参考图 像,和每一宏块分割的差分编码的运动矢量(帧间宏块,除 8×8 宏块分割的帧内 MB)
  • sub_mb_pred (只对 8×8MB 分割的帧内 MB)确定每一子宏块的子宏 块分割,每一宏块分割的表 0 和/或表 1 的参考图象;每一 宏块子分割的差分编码运动矢量。
  • coded_block_pattern 指出哪个 8×8 块(亮度和彩色)包 编码变换系数
  • mb_qp_delta 量化参数的改变值
  • esidual 预测后对应于残差图象取样的编码变换系数
  • 宏块数据:1宏块 = 16x16yuv数据

总结


H264的数据结构如上图所示
一个宏块 = 一个16*16的亮度像素 + 一个8×8Cb + 一个8×8Cr彩色像素块组成。(YCbCr 是属于 YUV 家族的一员,在YCbCr 中 Y 是指亮度分量,Cb 指蓝色色度分量,而 Cr 指红色色度分量)

参考

  1. https://www.jianshu.com/p/8edb448cf22e
  2. https://blog.csdn.net/qq_40732350/article/details/89605963
  3. https://blog.csdn.net/qq_40732350/category_8691404.html
  4. https://blog.csdn.net/qq_40732350/article/details/89606483
  5. 《H.264官方中文档.pdf》
  6. 安利一个流程图工具 https://app.diagrams.net/

H264数据格式解析相关推荐

  1. JSON 数据格式解析(转)

    JSON 即 JavaScript Object Natation,它是一种轻量级的数据交换格式,非常适合于服务器与 JavaScript 的交互.本文将快速讲解 JSON 格式,并通过代码示例演示如 ...

  2. Protobuf数据格式解析

    Protobuf数据格式解析 Protobuf是Google开源的一款类似于Json,XML数据交换格式,其内部数据是纯二进制格式,不依赖于语言和平台,具有简单,数据量小,快速等优点.目前用于序列化与 ...

  3. android gps磁偏角,GPS数据格式解析

    GPS数据格式解析 简介 GPS发送数据以行为单位,数据格式如下: $信息类型,x,x,x,x,x,x,x,x,x,x,x,x,x 每行以字符"$"开头,以为结尾,CR-Carri ...

  4. 流媒体专家(7)H264协议详解III H264文件解析C实现

    前面一节我们认识了H264的两层结构: VCL (VideoCoding Layer,视频编码层):负责高效的视频内容表示. NAL(NetworkAbstraction Layer,网络提取层):负 ...

  5. Linux下USB抓包工具UsbMon的使用和包数据格式解析

    Linux下USB抓包工具UsbMon的使用和包数据格式解析 一.UsbMon的使用步骤 1.挂载debugfs 2.加载usbmon模块 3.确认usbmon是否可用 4.确认usb设备挂在哪条总线 ...

  6. NTU-RGBD数据集下载及数据格式解析

    下载地址: 0-60:https://drive.google.com/open?id=1CUZnBtYwifVXS21yVg62T-vrPVayso5Hhttps://drive.google.co ...

  7. C语言 JSON数据格式解析

    C语言 JSON数据格式解析 一.如何用c语言编写与解析json数据格式,这篇主要是使用一个第三方的json库,本人已经上传至csdn,下载链接在下方. 二.json库代码文件下载地址(json.ra ...

  8. opendrive数据格式解析思维导图 , opendrive高精地图是自动驾驶领域使用最为广泛的开源高精地图标准级地图格式

    opendrive数据格式解析思维导图 , opendrive高精地图是自动驾驶领域使用最为广泛的开源高精地图标准级地图格式. 本思维导图将详细剖开高精路网地图内部的数据格式,涵盖:道路.车道.车道段 ...

  9. JSON数据格式解析库(cJSON、Jansson)的使用在STM32上移植和使用

    json | json-c使用入门 这篇讲的也不错,抽空看下(网络传输json数据) https://www.bilibili.com/video/av669454528?p=3&spm_id ...

  10. ffmpeg H264/mpegts 解析

    h264解析码流的流程 理解流程的几个问题: 如何找一个完整的帧 如何处理多slice的情况 一个完整的帧如何拷贝出去的 ffmpeg parse流程读数据怎么读的 如何找一个完整的帧 以0x00 0 ...

最新文章

  1. 云计算调查显示 希望与问题同在
  2. 供应商的余额,从哪个表里取
  3. python关键字匹配_python通过BF算法实现关键词匹配的方法
  4. Microsoft Dynamics CRM 前瑞开发
  5. 【算法分析与设计】内排序算法归纳
  6. android 应用开发(第70章)---二维码
  7. Python __str __()和__repr __()函数
  8. navicat 远程访问mariadb失败,修改配置如下
  9. qt实现百度首页(仅界面,功能未实现)
  10. 华为笔试题——分礼物
  11. 华为手机自带浏览器的显示问题
  12. 图片放大不失真 —— 矢量图
  13. vue文件在服务器上乱码,解决vue-pdf查看pdf文件及打印乱码的问题
  14. 解决windows连接Ubuntu向日葵不能操作
  15. 如何高效回复审稿意见?(附常用审稿意见回复模板)
  16. 使用欧镭2D雷达ROS驱动
  17. 【21天python打卡】第9天 基础技能(2)
  18. Linux命令窗口如何调节大小
  19. 数学与计算机科学奖视频马化腾,首届未来科学大奖揭晓 马化腾李彦宏都来颁奖了...
  20. 为什么现在的人越来越不怕老板了? 老板和员工都要看

热门文章

  1. QQ象棋java通用版下载_QQ中国象棋
  2. 数字化审图时代批量生成PDF或者DWF利器SmartBatchPlot
  3. 北斗导航 | BDS RTK高精度定位算法在形变检测中的应用(算法原理讲解)
  4. 长字符串的算术编码matlab,算术编码及MATLAB实现
  5. 苹果出现长方形透明框_看到我卧槽!这是苹果史上最疯狂的开发者大会
  6. PHICOMM(斐讯)N1盒子 - recovery模式救砖卡登录页LOGO卡1%卡4%卡26%
  7. 简单常用的10个excel公式
  8. Hilbert变换器
  9. Oracle 索引原理和种类
  10. 本特利3500软件组态指导