[H264从序列参数集(SPS)NAL单元获取帧的高度和宽度

问题描述 投票:3回答:2

您好,我一直在尝试找出如何从SPS最终单位计算宽度和高度的宽度。我有具有这些参数的H264视频

h264 (High), yuvj420p(pc), 1280x720 [SAR 1:1 DAR 16:9], 20 fps, 20 tbr, 1200k tbn, 40 tbc

我一直在寻找一个可以计算宽度(1280)和高度(720)的公式,但是没有找到可以帮助我的公式。现在,我正在使用this formula,它适用于大多数H264流,但在这种情况下,高度和宽度为80x48

if(frame_cropping_flag) {
    width = ((pic_width_in_mbs_minus1 +1)*16) - frame_crop_left_offset*2 - frame_crop_right_offset*2;
    height= ((2 - frame_mbs_only_flag)* (pic_height_in_map_units_minus1 +1) * 16) - (frame_crop_top_offset * 2) - (frame_crop_bottom_offset * 2);
}
else {
    width = ((pic_width_in_mbs_minus1 +1)*16);
    height= ((2 - frame_mbs_only_flag)* (pic_height_in_map_units_minus1 +1) * 16);
}

这里是SPS作为base64

Z2QAKa2EBUViuKxUdCAqKxXFYqOhAVFYrisVHQgKisVxWKjoQFRWK4rFR0ICorFcVio6ECSFITk8nyfk/k/J8nm5s00IEkKQnJ5Pk/J/J+T5PNzZprQCgC3YCqQAAAMB4AAASwGBAAH0AAADAjKAve+F4RCNQA==

这里是我解析的SPS:

======= SPS =======
 profile_idc : 100
 constraint_set0_flag : 0
 constraint_set1_flag : 0
 constraint_set2_flag : 0
 constraint_set3_flag : 0
 constraint_set4_flag : 0
 constraint_set5_flag : 0
 reserved_zero_2bits : 0
 level_idc : 41
 seq_parameter_set_id : 0
 chroma_format_idc : 1
 separate_colour_plane_flag : 0
 bit_depth_luma_minus8 : 0
 bit_depth_chroma_minus8 : 0
 qpprime_y_zero_transform_bypass_flag : 0
 seq_scaling_matrix_present_flag : 1
 log2_max_frame_num_minus4 : 41
 pic_order_cnt_type : 4
   log2_max_pic_order_cnt_lsb_minus4 : 0
   delta_pic_order_always_zero_flag : 0
   offset_for_non_ref_pic : 0
   offset_for_top_to_bottom_field : 0
   num_ref_frames_in_pic_order_cnt_cycle : 0
 num_ref_frames : 2
 gaps_in_frame_num_value_allowed_flag : 0
 pic_width_in_mbs_minus1 : 4
 pic_height_in_map_units_minus1 : 2
 frame_mbs_only_flag : 1
 mb_adaptive_frame_field_flag : 0
 direct_8x8_inference_flag : 0
 frame_cropping_flag : 0
   frame_crop_left_offset : 0
   frame_crop_right_offset : 0
   frame_crop_top_offset : 0
   frame_crop_bottom_offset : 0
 vui_parameters_present_flag : 0
=== VUI ===
 aspect_ratio_info_present_flag : 0
   aspect_ratio_idc : 0
     sar_width : 0
     sar_height : 0
 overscan_info_present_flag : 0
   overscan_appropriate_flag : 0
 video_signal_type_present_flag : 0
   video_format : 0
   video_full_range_flag : 0
   colour_description_present_flag : 0
     colour_primaries : 0
   transfer_characteristics : 0
   matrix_coefficients : 0
 chroma_loc_info_present_flag : 0
   chroma_sample_loc_type_top_field : 0
   chroma_sample_loc_type_bottom_field : 0
 timing_info_present_flag : 0
   num_units_in_tick : 0
   time_scale : 0
   fixed_frame_rate_flag : 0
 nal_hrd_parameters_present_flag : 0
 vcl_hrd_parameters_present_flag : 0
   low_delay_hrd_flag : 0
 pic_struct_present_flag : 0
 bitstream_restriction_flag : 0
   motion_vectors_over_pic_boundaries_flag : 0
   max_bytes_per_pic_denom : 0
   max_bits_per_mb_denom : 0
   log2_max_mv_length_horizontal : 0
   log2_max_mv_length_vertical : 0
   num_reorder_frames : 0
   max_dec_frame_buffering : 0
=== HRD ===
 cpb_cnt_minus1 : 0
 bit_rate_scale : 0
 cpb_size_scale : 0
   bit_rate_value_minus1[0] : 0
   cpb_size_value_minus1[0] : 0
   cbr_flag[0] : 0
 initial_cpb_removal_delay_length_minus1 : 0
 cpb_removal_delay_length_minus1 : 0
 dpb_output_delay_length_minus1 : 0
 time_offset_length : 0

我想这与亮度和切尔玛macrblocks大小有关,我已经能够计算SubWidthC \ SubHeightC和MbWidthC \ MbHeightC。但是我仍然很困惑下一步该怎么做。

谢谢您的任何帮助或指导此致teamol

height width frame resolution h.264
2个回答
7
投票

您好,首先您错误地解析了SPS,因此您需要解决该问题。如果您正确解析它,那么您将有

pic_width_in_mbs_minus1 : 79
pic_height_in_map_units_minus1 : 44
frame_mbs_only_flag : 1
frame_cropping_flag : 0

如果使用公式计算宽度和高度,则实际上将为1280x720

无论如何,应使用SubWidth和SubHeight如下计算高度和宽度:

int SubWidthC;
int SubHeightC;

if (sps->chroma_format_idc == 0 && sps->separate_colour_plane_flag == 0) { //monochrome
    SubWidthC = SubHeightC = 0;
}
else if (sps->chroma_format_idc == 1 && sps->separate_colour_plane_flag == 0) { //4:2:0 
    SubWidthC = SubHeightC = 2;
}
else if (sps->chroma_format_idc == 2 && sps->separate_colour_plane_flag == 0) { //4:2:2 
    SubWidthC = 2;
    SubHeightC = 1;
}
else if (sps->chroma_format_idc == 3) { //4:4:4
    if (sps->separate_colour_plane_flag == 0) {
        SubWidthC = SubHeightC = 1;
    }
    else if (sps->separate_colour_plane_flag == 1) {
        SubWidthC = SubHeightC = 0;
    }
}

int PicWidthInMbs = sps->pic_width_in_mbs_minus1 + 1;

int PicHeightInMapUnits = sps->pic_height_in_map_units_minus1 + 1;
int FrameHeightInMbs = (2 - sps->frame_mbs_only_flag) * PicHeightInMapUnits;

int crop_left = 0;
int crop_right = 0;
int crop_top = 0;
int crop_bottom = 0;

if (sps->frame_cropping_flag) {
    crop_left = sps->frame_crop_left_offset;
    crop_right = sps->frame_crop_right_offset;
    crop_top = sps->frame_crop_top_offset;
    crop_bottom = sps->frame_crop_bottom_offset;
}

int width = PicWidthInMbs * 16 - SubWidthC * (crop_left + crop_right);
int height = FrameHeightInMbs * 16 - SubHeightC * (2 - sps->frame_mbs_only_flag) * (crop_top + crop_bottom);

0
投票

我们现在在librem中具有H.264 SPS解析器:

https://github.com/creytiv/rem/blob/master/include/rem_h264.h#L52

可以这样使用,以提取分辨率:

    struct h264_sps sps;
    struct vidsz vidsz;

    h264_sps_decode(&sps, buf, len);

    h264_sps_resolution(&sps, vidsz);

    printf("resolution: %u x %u\n", vidsz.w, vidsz.h);
© www.soinside.com 2019 - 2024. All rights reserved.