Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

H264 getting frame height and width from sequence parameter set (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

like image 623
Teamol Avatar asked Aug 10 '15 12:08

Teamol


People also ask

What is the difference between SPS NAL and H264?

Recall that an H.264 bitstream contains a sequence of Network Abstraction Layer (NAL) units. The SPS and PPS are both types of NAL units. The SPS NAL unit contains parameters that apply to a series of consecutive coded video pictures, referred to as a “coded video sequence” in the H.264 standard.

What is sequenceparametersetlength in SPS NAL?

sequenceParameterSetLength: length in bytes of the SPS NAL unit as defined in H.264 Specification. sequenceParameterSetNALUnit: a SPS NAL unit, as specified in H.264 Specification. SPSs shall occur in order of ascending parameter set identifier with gaps being allowed.

What is the difference between SPS and PPS NAL?

The SPS NAL unit contains parameters that apply to a series of consecutive coded video pictures, referred to as a “coded video sequence” in the H.264 standard. The PPS NAL unit contains parameters that apply to the decoding of one or more individual pictures inside a coded video sequence.

What is the Profile-IOP in H264?

The profile-iop is a set of binary flags that change the meaning of the other two bytes. Their meaning are defined together with the different Profiles, and also in the H.264 Specification: Section 7.4.2.1.1 Sequence parameter set data semantics.


1 Answers

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_top + crop_bottom);
like image 76
Ivan Roubíček Avatar answered Sep 19 '22 16:09

Ivan Roubíček