h264裸流解析

H.264标准中,视频流是由NAL(Network Abstraction Layer)单元组成的(简称NALU),每个NALU中可能是IDR图像、SPS、PPS、non-IDR图像等。

1 AVCC与Annex-B

H.264码流分为AVCC与Annex-B两种组织格式。

AVCC格式 也叫AVC1格式,MPEG-4格式,字节对齐,因此也叫Byte-Stream Format。用于mp4/flv/mkv等封装中。

Annex-B格式 也叫MPEG-2 transport stream format格式(ts格式), ElementaryStream格式。用于TS流中(以及使用TS作为切片的hls格式中)。

这两种格式的区别有两点:

(1)NALU的分割方式不同;

(2)SPS/PPS的数据结构不同。

AVCC格式使用NALU长度(固定字节,字节数由extradata中的信息给定)进行分割,在封装文件或者直播流的头部包含extradata信息(非NALU),extradata中包含NALU长度的字节数以及SPS/PPS信息。

Annex-B格式使用start code进行分割,start code为0x000001或0x00000001,SPS/PPS作为一般NALU单元以start code作为分隔符的方式放在文件或者直播流的头部。

AVCC格式的extradata格式定义在“ISO_IEC_14496-15"文档中,Annex-B格式的SPS/PPS定义可以在"ISO_IEC_14496-10"文档中找到。

 图 Annex-B格式h264码流

 

图  NAL构成

本文福利, C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部点击领取↓↓

MediaCodec与VideoToolBox使用的数据格式

Android的硬解码接口MediaCodec只能接收Annex-B格式的H.264数据,而iOS平台的VideoToolBox则相反,只支持AVCC格式。这就导致:

在Android平台硬解播放flv/mp4/mkv等封装的视频时,需要将AVCC格式的extradata以及NALU数据转为Annex-B格式;

在iOS平台播放ts或ts切片的hls视频时,需要将Annex-B格式的SPS/PPS NALU转为AVCC格式的extradata,以及将其他以size方式分割的NALU转为start code方式。

2 slice

视频由frame组成,frame由slice组成。每一个Slice分为Slice header(用于保存Slice的总体信息)和Slice body组成(通常是一组连续的宏块结构或者宏块跳过信息),如下图所示:

SI和SP:即Switch I和Switch P,是一种特殊的编解码条带,可以保证在视频流之间进行有效的切换,并且解码器可以任意的访问。比如,同一个视频源被编码成各种码率的码流,在传输的过程中可以根据网络环境进行实时的切换;

2.1 slice header

  • first_mb_in_slice: 当前slice中包含的第一个宏块在整帧中的位置;
  • slice_type:当前slice的类型;

slice_type的值5到9表示除了当前条带的编码类型,所有当前编码图像的其他条带的slice_type的值应与当前条带的slice_type的值一样,或者等于当前条带的slice_type的值减5。对于IDR图像,slice_type的值应为2、4、7或者9。

pic_parameter_set_id:当前slice所依赖的pps的id;范围 0 到 255。

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

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应保持一致。该值的取值范围为[0,65535]。

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

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

slice_qp_delta:用于计算当前slice内所使用的初始qp值。

3 工具解析文件h264

示例1

 

profile_idc = 66 → baseline profile;

profile_idc = 77 → main profile;

profile_idc = 88 → extended profile;

(profile_idc = 99 → high profile;)

constraint_set0_flag ~ constraint_set5_flag是在编码的档次方面对码流增加的其他一些额外限制性条件。

level_idc,除以10,码流级别=5.2

seq_parameter_set_id表示当前的序列参数集的id。通过该id值,图像参数集pps可以引用其代表的sps中的参数。

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

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

pic_width_in_mbs_minus1,用于计算图像的宽度,单位为宏块个数-1。

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

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

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

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

pic_parameter_set_id,表示当前PPS的id。某个PPS在码流中会被相应的slice引用,slice引用PPS的方式就是在Slice header中保存PPS的id值。该值的取值范围为[0,255]。

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

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

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

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

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

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

 

 

示例2

 

 

 

 示例3

 

 

 

原文链接:h264裸流解析 - 资料 - 我爱音视频网 - 构建全国最权威的音视频技术交流分享论坛 

 本文福利, C++音视频学习资料包、技术视频,内容包括(音视频开发,面试题,FFmpeg webRTC rtmp hls rtsp ffplay srs↓↓↓↓↓↓见下面↓↓文章底部点击领取↓↓

猜你喜欢

转载自blog.csdn.net/m0_60259116/article/details/126074511