ffmpeg h264解码器分析sps(一)

本文详细介绍了ffmpeg库中h264解码器如何解析序列参数集(sps),涉及关键参数如profile_idc、level_idc、sps_id、chroma_format_idc、bit_depth等的解析过程,以及解码过程中可能出现的错误检查和处理。

sps解码

int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx,

H264ParamSets *ps, int ignore_truncation)

{

AVBufferRef *sps_buf;

int profile_idc, level_idc, constraint_set_flags = 0;

unsigned int sps_id;

int i, log2_max_frame_num_minus4;

SPS *sps;

int ret;

 

sps_buf = av_buffer_allocz(sizeof(*sps));

if (!sps_buf)

return AVERROR(ENOMEM);

sps = (SPS*)sps_buf->data;

 

sps->data_size = gb->buffer_end - gb->buffer;

if (sps->data_size > sizeof(sps->data)) {

av_log(avctx, AV_LOG_DEBUG, "Truncating likely oversized SPS\n");

sps->data_size = sizeof(sps->data);

}

memcpy(sps->data, gb->buffer, sps->data_size);

 

profile_idc = get_bits(gb, 8); //编码参数 profile类型

constraint_set_flags |= get_bits1(gb) << 0; // constraint_set0_flag

constraint_set_flags |= get_bits1(gb) << 1; // constraint_set1_flag

constraint_set_flags |= get_bits1(gb) << 2; // constraint_set2_flag

constraint_set_flags |= get_bits1(gb) << 3; // constraint_set3_flag

constraint_set_flags |= get_bits1(gb) << 4; // constraint_set4_flag

constraint_set_flags |= get_bits1(gb) << 5; // constraint_set5_flag

//固定设置参数

skip_bits(gb, 2); // reserved_zero_2bits 保留2bits

level_idc = get_bits(gb, 8); // 编码level 8bits

sps_id = get_ue_golomb_31(gb); // ue无符号哥伦布编码读取, sps_id https://blog.youkuaiyun.com/fantasy_ARM9/article/details/105635317

 

if (sps_id >= MAX_SPS_COUNT) { //sps最大个数 32个

av_log(avctx, AV_LOG_ERROR, "sps_id %u out of range\n", sps_id);

goto fail;

}

 

sps->sps_id = sps_id;

sps->time_offset_length = 24;

sps->profile_idc = profile_idc;

sps->constraint_set_flags = constraint_set_flags;

sps->level_idc = level_idc;

sps->full_range = -1;

 

memset(sps->scaling_matrix4, 16, sizeof(sps->scaling_matrix4));

memset(sps->scaling_matrix8, 16, sizeof(sps->scaling_matrix8));

sps->scaling_matrix_present = 0;

sps->colorspace = 2; //AVCOL_SPC_UNSPECIFIED

 

if (sps->profile_idc == 100 || // High profile

sps->profile_idc == 110 || // High10 profile

sps->profile_idc == 122 || // High422 profile

sps->profile_idc == 244 || // High444 Predictive profile

sps->profile_idc == 44 || // Cavlc444 profile

sps->profile_idc == 83 || // Scalable Constrained High profile (SVC)

sps->profile_idc == 86 || // Scalable High Intra profile (SVC)

sps->profile_idc == 118 || // Stereo High profile (MVC)

sps->profile_idc == 128 || // Multiview High profile (MVC)

sps->profile_idc == 138 || // Multiview Depth High profile (MVCD)

sps->profile_idc == 144) { // old High444 profile

sps->chroma_format_idc = get_ue_golomb_31(gb); //色度采样格式

/*

enum chroma_format_e

{

CHROMA_400 = 0,

CHROMA_420 = 1,

CHROMA_422 = 2,

CHROMA_444 = 3,

};

*/

if (sps->chroma_format_idc > 3U) {

avpriv_request_sample(avctx, "chroma_format_idc %u",

sps->chroma_format_idc);

goto fail;

} else if (sps->chroma_format_idc == 3) {// 如果是YUV444

sps->residual_color_transform_flag = get_bits1(gb);// 等于0时,采用残余颜色转换

if (sps->residual_color_transform_flag) {

av_log(avctx, AV_LOG_ERROR, "separate color planes are not supported\n");

goto fail;

}

}

sps->bit_depth_luma = get_ue_golomb_31(gb) + 8;//亮度深度

sps->bit_depth_chroma = get_ue_golomb_31(gb) + 8;//色度深度

if (sps->bit_depth_chroma != sps->bit_depth_luma) {// 如果颜色深度和 亮度深度不等,认为时错误

avpriv_request_sample(avctx,

"Different chroma and luma bit depth");

goto fail;

}

if (sps->bit_depth_luma < 8 || sps->bit_depth_luma > 14 ||

sps->bit_depth_chroma < 8 || sps->bit_depth_chroma > 14) {

av_log(avctx, AV_LOG_ERROR, "illegal bit depth value (%d, %d)\n",

sps->bit_depth_luma, sps->bit_depth_chroma);

goto fail;

}

sps->transform_bypass = get_bits1(gb);

/*qpprime_y_zero_transform_bypass_flag 等于 1 是指当 QP'Y 等于 0 时变换系数解码过程的变换旁路操作和图

像构建过程将会在第 8.5 节给出的去块效应滤波过程之前执行。qpprime_y_zero_transform_bypass_flag 等于 0 是指

变 换 系 数 解 码过程和图像 构 建过程在 去 块 效 应 滤 波 过程之前 执 行而不使用 变 换 旁路操 作。当

qpprime_y_zero_transform_bypass_flag 没有特别指定时,应推定其值为 0。*/

ret = decode_scaling_matrices(gb, sps, NULL, 1,

sps->scaling_matrix4, sps->scaling_matrix8);

/*seq_scaling_matrix_present_flag 等 于 1 表示存在 i=0..7 的 标 志 seq_scaling_list_present_flag[ i ] 。

seq_scaling_matrix_present_flag 等于 0 则表示不存在这些标志并且由 Flat_4x4_16 表示的序列级别的缩放比例列表

应被推断出来(对应 i=0..5),由 Flat_8x8_16 表示的序列级别的缩放比例列表应被推断出来(对应 i=6..7)。当

seq_scaling_matrix_present_flag 没有特别指定时,应推定其值为 0。*/

if (ret < 0)

goto fail;

sps->scaling_matrix_present |= ret;

} else {

sps->chroma_format_idc = 1;

sps->bit_depth_luma = 8;

sps->bit_depth_chroma = 8;

}

 

log2_max_frame_num_minus4 = get_ue_golomb_31(gb);// log2_max_frame_num_minus4 最大frame_num -4 log2

if (log2_max_frame_num_minus4 < MIN_LOG2_MAX_FRAME_NUM - 4 ||

log2_max_frame_num_minus4 > MAX_LOG2_MAX_FRAME_NUM - 4) {

av_log(avctx, AV_LOG_ERROR,

"log2_max_frame_num_minus4 out of range (0-12): %d\n",

log2_max_frame_num_minus4);

goto fail;

}

sps->log2_max_frame_num = log2_max_frame_num_minus4 + 4;// log2 max_frame

 

sps->poc_type = get_ue_golomb_31(gb); // poc类型

/*pic_order_cnt_type 是指解码图像顺序的计数方法(如 8.2.1 节所述)。pic_order_cnt_type 的取值范围是 0 到 2(包括 0 和 2)。

包含下列任何情况的一个编码视频序列中 pic_order_cnt_type 都不能等于 2: -— 一个包含非参考图像的访问单元紧跟在一个包含非参考帧的访问单元之后; -— 一个包含非参考图像的访问单元紧跟在分别包含一个由两个场一起组成一个互补的非参考场对的两个

访问单元之后; -— 一个包含非参考场的访问单元之后紧跟在一个包含另一个非参考图像的访问单元(该访问单元没有与

两个访问单元中的第一个组成一个互补的非参考场对)*/

 

if (sps->poc_type == 0) { // FIXME #define

unsigned t = get_ue_golomb_31(gb);

/*log2_max_pic_order_cnt_lsb_minus4 表示用于 8.2.1 节规定的图像 顺 序 数 解 码过程中的 变 量

MaxPicOrderCntLsb 的值,公式如下:

MaxPicOrderCntLsb = 2( log2_max_pic_order_cnt_lsb_minus4 + 4 )*/

if (t>12) {

av_log(avctx, AV_LOG_ERROR, "log2_max_poc_lsb (%d) is out of range\n", t);

goto fail;

}

sps->log2_max_poc_lsb = t + 4;

} else if (sps->poc_type == 1) { // FIXME #define

sps->delta_pic_order_always_zero_flag = get_bits1(gb);

/*delta_pic_order_always_zero_flag 等 于 1 表示视频 序 列 的 条 带 头 中 没 有 delta_pic_order_cnt[ 0 ] 和

delta_pic_order_cnt[ 1 ] 两个字段,它们的值都默认为 0。delta_pic_order_always_zero_flag 等于 0 表示视频序列的

条带头中包含 delta_pic_order_cnt[ 0 ]字段,并可能包括 delta_pic_order_cnt[ 1]的字段(也可以不包括)。*/

sps->offset_for_non_ref_pic = get_se_golomb_long(gb);

sps->offset_for_top_to_bottom_field = get_se_golomb_long(gb);

/*offset_for_non_ref_pic 用于计算 8.2.1 节规定的一个非参考图像的图像顺序号。offset_for_non_ref_pic 的取值

范围是 – 231 到 231 – 1(包括-231 和 231 – 1)。

offset_for_top_to_bottom_field 用于计算 8.2.1 节规定的一个 帧 的 底 场的图像 顺序号 。

offset_for_top_to_bottom_field 的取值范围是 – 231 到 231 – 1(包括–231 和 231 – 1)。

num_ref_frames_in_pic_order_cnt_cycle 用 于 8.2.1 节规定的图像 顺序号 的 解 码过程。

num_ref_frames_in_pic_order_cnt_cycle 的取值范围是 0 到 255(包括 0 和 255)。*/

if ( sps->offset_for_non_ref_pic == INT32_MIN

|| sps->offset_for_top_to_bottom_field == INT32_MIN

) {

av_log(avctx, AV_LOG_ERROR,

"offset_for_non_ref_pic or offset_for_top_to_bottom_field is out of range\n");

goto fail;

}

 

sps->poc_cycle_length = get_ue_golomb(gb);

/*num_ref_frames_in_pic_order_cnt_cycle 用 于 8.2.1 节规定的图像 顺序号 的 解 码过程。

num_ref_frames_in_pic_order_cnt_cycle 的取值范围是 0 到 255(包括 0 和 255)。*/

if ((unsigned)sps->poc_cycle_length >=

FF_ARRAY_ELEMS(sps->offset_for_ref_frame)) {

av_log(avctx, AV_LOG_ERROR,

"poc_cycle_length overflow %d\n", sps->poc_cycle_length);

goto fail;

}

 

for (i = 0; i < sps->poc_cycle_length; i++) {//参考帧偏移

sps->offset_for_ref_frame[i] = get_se_golomb_long(gb);

if (sps->offset_for_ref_frame[i] == INT32_MIN) {

av_log(avctx, AV_LOG_ERROR,

"offset_for_ref_frame is out of range\n");

goto fail;

}

}

} else if (sps->poc_type != 2) {

av_log(avctx, AV_LOG_ERROR, "illegal POC type %d\n", sps->poc_type);

goto fail;

}

 

sps->ref_frame_count = get_ue_golomb_31(gb); //参考帧个数

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值