Trang chủ‎ > ‎IT‎ > ‎Video Processing‎ > ‎

H264 getting width height from SPS (NAL unit)

Hello guys I've been trying to find out how to calculate width a height from SPS nal unit. I have H264 video which has these parameters

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

I've been searching for a formula which would calculate width (1280) and height (720) but have't found any which would help me. Right now I'm using this formula and it works for most H264 streams but in this case height and width is 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);
}

here is SPS as base64

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

here is SPS that I've parsed:

======= 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

I guess it has something to do with luma and chorma macrblocks size I've been able to calculate SubWidthC\SubHeightC and MbWidthC\MbHeightC. But i'm still confused what to do next.

Thank you for any kind of help or direction Best regards teamol

--------------------------------------------------------------------------------------------------------------------

Hello first of all you are parsing SPS incorrectly so you need to fix that. If you parse it correctly then you will have

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

If you calculate width and height using your formula then you will actualy have 1280x720

Anyway you should calculate height and width using SubWidth and SubHeight as follows:

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_t
Comments