static bool hevc_parse_scaling_list_rbsp( bs_t *p_bs ) { if( bs_remain( p_bs ) < 16 ) return false; for( int i=0; i<4; i++ ) { for( int j=0; j<6; j += (i == 3) ? 3 : 1 ) { if( bs_read1( p_bs ) == 0 ) bs_read_ue( p_bs ); else { unsigned nextCoef = 8; unsigned coefNum = __MIN( 64, (1 << (4 + (i << 1)))); if( i > 1 ) { nextCoef = bs_read_se( p_bs ) + 8; } for( unsigned k=0; k<coefNum; k++ ) { nextCoef = ( nextCoef + bs_read_se( p_bs ) + 256 ) % 256; } } } } return true; }
//7.3.2.1.1 Scaling list syntax void read_scaling_list(bs_t* b, int* scalingList, int sizeOfScalingList, int useDefaultScalingMatrixFlag) { int j; if (scalingList == NULL) { return; } int lastScale = 8; int nextScale = 8; for (j = 0; j < sizeOfScalingList; j++) { if (nextScale != 0) { int delta_scale = bs_read_se(b); nextScale = (lastScale + delta_scale + 256) % 256; useDefaultScalingMatrixFlag = (j == 0 && nextScale == 0); } scalingList[j] = (nextScale == 0) ? lastScale : nextScale; lastScale = scalingList[j]; } }
int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size, struct nal_sps *p_sps ) { uint8_t *pb_dec = NULL; int i_dec = 0; bs_t s; int i_tmp; if (i_sps_size < 5 || (p_sps_buf[4] & 0x1f) != NAL_SPS) return -1; memset( p_sps, 0, sizeof(struct nal_sps) ); CreateRbspFromNAL( &pb_dec, &i_dec, &p_sps_buf[5], i_sps_size - 5 ); bs_init( &s, pb_dec, i_dec ); int i_profile_idc = bs_read( &s, 8 ); p_sps->i_profile = i_profile_idc; p_sps->i_profile_compatibility = bs_read( &s, 8 ); p_sps->i_level = bs_read( &s, 8 ); /* sps id */ p_sps->i_id = bs_read_ue( &s ); if( p_sps->i_id >= SPS_MAX || p_sps->i_id < 0 ) { free( pb_dec ); return -1; } if( i_profile_idc == PROFILE_H264_HIGH || i_profile_idc == PROFILE_H264_HIGH_10 || i_profile_idc == PROFILE_H264_HIGH_422 || i_profile_idc == PROFILE_H264_HIGH_444_PREDICTIVE || i_profile_idc == PROFILE_H264_CAVLC_INTRA || i_profile_idc == PROFILE_H264_SVC_BASELINE || i_profile_idc == PROFILE_H264_SVC_HIGH ) { /* chroma_format_idc */ const int i_chroma_format_idc = bs_read_ue( &s ); if( i_chroma_format_idc == 3 ) bs_skip( &s, 1 ); /* separate_colour_plane_flag */ /* bit_depth_luma_minus8 */ bs_read_ue( &s ); /* bit_depth_chroma_minus8 */ bs_read_ue( &s ); /* qpprime_y_zero_transform_bypass_flag */ bs_skip( &s, 1 ); /* seq_scaling_matrix_present_flag */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { for( int i = 0; i < ((3 != i_chroma_format_idc) ? 8 : 12); i++ ) { /* seq_scaling_list_present_flag[i] */ i_tmp = bs_read( &s, 1 ); if( !i_tmp ) continue; const int i_size_of_scaling_list = (i < 6 ) ? 16 : 64; /* scaling_list (...) */ int i_lastscale = 8; int i_nextscale = 8; for( int j = 0; j < i_size_of_scaling_list; j++ ) { if( i_nextscale != 0 ) { /* delta_scale */ i_tmp = bs_read_se( &s ); i_nextscale = ( i_lastscale + i_tmp + 256 ) % 256; /* useDefaultScalingMatrixFlag = ... */ } /* scalinglist[j] */ i_lastscale = ( i_nextscale == 0 ) ? i_lastscale : i_nextscale; } } } } /* Skip i_log2_max_frame_num */ p_sps->i_log2_max_frame_num = bs_read_ue( &s ); if( p_sps->i_log2_max_frame_num > 12) p_sps->i_log2_max_frame_num = 12; /* Read poc_type */ p_sps->i_pic_order_cnt_type = bs_read_ue( &s ); if( p_sps->i_pic_order_cnt_type == 0 ) { /* skip i_log2_max_poc_lsb */ p_sps->i_log2_max_pic_order_cnt_lsb = bs_read_ue( &s ); if( p_sps->i_log2_max_pic_order_cnt_lsb > 12 ) p_sps->i_log2_max_pic_order_cnt_lsb = 12; } else if( p_sps->i_pic_order_cnt_type == 1 ) { int i_cycle; /* skip b_delta_pic_order_always_zero */ p_sps->i_delta_pic_order_always_zero_flag = bs_read( &s, 1 ); /* skip i_offset_for_non_ref_pic */ bs_read_se( &s ); /* skip i_offset_for_top_to_bottom_field */ bs_read_se( &s ); /* read i_num_ref_frames_in_poc_cycle */ i_cycle = bs_read_ue( &s ); if( i_cycle > 256 ) i_cycle = 256; while( i_cycle > 0 ) { /* skip i_offset_for_ref_frame */ bs_read_se(&s ); i_cycle--; } } /* i_num_ref_frames */ bs_read_ue( &s ); /* b_gaps_in_frame_num_value_allowed */ bs_skip( &s, 1 ); /* Read size */ p_sps->i_width = 16 * ( bs_read_ue( &s ) + 1 ); p_sps->i_height = 16 * ( bs_read_ue( &s ) + 1 ); /* b_frame_mbs_only */ p_sps->b_frame_mbs_only = bs_read( &s, 1 ); p_sps->i_height *= ( 2 - p_sps->b_frame_mbs_only ); if( p_sps->b_frame_mbs_only == 0 ) { bs_skip( &s, 1 ); } /* b_direct8x8_inference */ bs_skip( &s, 1 ); /* crop */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { /* left */ bs_read_ue( &s ); /* right */ bs_read_ue( &s ); /* top */ bs_read_ue( &s ); /* bottom */ bs_read_ue( &s ); } /* vui */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { p_sps->vui.b_valid = true; /* read the aspect ratio part if any */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { static const struct { int w, h; } sar[17] = { { 0, 0 }, { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, { 160,99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, }; int i_sar = bs_read( &s, 8 ); int w, h; if( i_sar < 17 ) { w = sar[i_sar].w; h = sar[i_sar].h; } else if( i_sar == 255 ) { w = bs_read( &s, 16 ); h = bs_read( &s, 16 ); } else { w = 0; h = 0; } if( w != 0 && h != 0 ) { p_sps->vui.i_sar_num = w; p_sps->vui.i_sar_den = h; } else { p_sps->vui.i_sar_num = 1; p_sps->vui.i_sar_den = 1; } } /* overscan */ i_tmp = bs_read( &s, 1 ); if ( i_tmp ) bs_read( &s, 1 ); /* video signal type */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { bs_read( &s, 4 ); /* colour desc */ bs_read( &s, 1 ); if ( i_tmp ) bs_read( &s, 24 ); } /* chroma loc info */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { bs_read_ue( &s ); bs_read_ue( &s ); } /* timing info */ p_sps->vui.b_timing_info_present_flag = bs_read( &s, 1 ); if( p_sps->vui.b_timing_info_present_flag ) { p_sps->vui.i_num_units_in_tick = bs_read( &s, 32 ); p_sps->vui.i_time_scale = bs_read( &s, 32 ); p_sps->vui.b_fixed_frame_rate = bs_read( &s, 1 ); } /* Nal hrd & VC1 hrd parameters */ p_sps->vui.b_cpb_dpb_delays_present_flag = false; for ( int i=0; i<2; i++ ) { i_tmp = bs_read( &s, 1 ); if( i_tmp ) { p_sps->vui.b_cpb_dpb_delays_present_flag = true; uint32_t count = bs_read_ue( &s ) + 1; bs_read( &s, 4 ); bs_read( &s, 4 ); for( uint32_t i=0; i<count; i++ ) { bs_read_ue( &s ); bs_read_ue( &s ); bs_read( &s, 1 ); } bs_read( &s, 5 ); p_sps->vui.i_cpb_removal_delay_length_minus1 = bs_read( &s, 5 ); p_sps->vui.i_dpb_output_delay_length_minus1 = bs_read( &s, 5 ); bs_read( &s, 5 ); } } if( p_sps->vui.b_cpb_dpb_delays_present_flag ) bs_read( &s, 1 ); /* pic struct info */ p_sps->vui.b_pic_struct_present_flag = bs_read( &s, 1 ); /* + unparsed remains */ } free( pb_dec ); return 0; }
//7.3.2.1 Sequence parameter set RBSP syntax void read_seq_parameter_set_rbsp(sps_t *sps, bs_t* b) { int i; // NOTE can't read directly into sps because seq_parameter_set_id not yet known and so sps is not selected int profile_idc = bs_read(b, 8); int constraint_set0_flag = bs_read(b, 1); int constraint_set1_flag = bs_read(b, 1); int constraint_set2_flag = bs_read(b, 1); int constraint_set3_flag = bs_read(b, 1); int constraint_set4_flag = bs_read(b, 1); int constraint_set5_flag = bs_read(b, 1); int reserved_zero_2bits = bs_read(b, 2); /* all 0's */ int level_idc = bs_read(b, 8); int seq_parameter_set_id = bs_read_ue(b); memset(sps, 0, sizeof(sps_t)); sps->chroma_format_idc = 1; sps->profile_idc = profile_idc; // bs_read(b, 8); sps->constraint_set0_flag = constraint_set0_flag;//bs_read(b, 1); sps->constraint_set1_flag = constraint_set1_flag;//bs_read(b, 1); sps->constraint_set2_flag = constraint_set2_flag;//bs_read(b, 1); sps->constraint_set3_flag = constraint_set3_flag;//bs_read(b, 1); sps->constraint_set4_flag = constraint_set4_flag;//bs_read(b, 1); sps->constraint_set5_flag = constraint_set5_flag;//bs_read(b, 1); sps->reserved_zero_2bits = reserved_zero_2bits;//bs_read(b,2); sps->level_idc = level_idc; //bs_read(b, 8); sps->seq_parameter_set_id = seq_parameter_set_id; // bs_read_ue(b); if (sps->profile_idc == 100 || sps->profile_idc == 110 || sps->profile_idc == 122 || sps->profile_idc == 144) { sps->chroma_format_idc = bs_read_ue(b); if (sps->chroma_format_idc == 3) { sps->residual_colour_transform_flag = bs_read(b, 1); } sps->bit_depth_luma_minus8 = bs_read_ue(b); sps->bit_depth_chroma_minus8 = bs_read_ue(b); sps->qpprime_y_zero_transform_bypass_flag = bs_read(b, 1); sps->seq_scaling_matrix_present_flag = bs_read(b, 1); if (sps->seq_scaling_matrix_present_flag) { for (i = 0; i < 8; i++) { sps->seq_scaling_list_present_flag[i] = bs_read(b, 1); if (sps->seq_scaling_list_present_flag[i]) { if (i < 6) { read_scaling_list(b, sps->ScalingList4x4[i], 16, sps->UseDefaultScalingMatrix4x4Flag[i]); } else { read_scaling_list(b, sps->ScalingList8x8[i - 6], 64, sps->UseDefaultScalingMatrix8x8Flag[i - 6]); } } } } } sps->log2_max_frame_num_minus4 = bs_read_ue(b); sps->pic_order_cnt_type = bs_read_ue(b); if (sps->pic_order_cnt_type == 0) { sps->log2_max_pic_order_cnt_lsb_minus4 = bs_read_ue(b); } else if (sps->pic_order_cnt_type == 1) { sps->delta_pic_order_always_zero_flag = bs_read(b, 1); sps->offset_for_non_ref_pic = bs_read_se(b); sps->offset_for_top_to_bottom_field = bs_read_se(b); sps->num_ref_frames_in_pic_order_cnt_cycle = bs_read_ue(b); for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++) { sps->offset_for_ref_frame[i] = bs_read_se(b); } } sps->num_ref_frames = bs_read_ue(b); sps->gaps_in_frame_num_value_allowed_flag = bs_read(b, 1); sps->pic_width_in_mbs_minus1 = bs_read_ue(b); sps->pic_height_in_map_units_minus1 = bs_read_ue(b); sps->frame_mbs_only_flag = bs_read(b, 1); if (!sps->frame_mbs_only_flag) { sps->mb_adaptive_frame_field_flag = bs_read(b, 1); } sps->direct_8x8_inference_flag = bs_read(b, 1); sps->frame_cropping_flag = bs_read(b, 1); if (sps->frame_cropping_flag) { sps->frame_crop_left_offset = bs_read_ue(b); sps->frame_crop_right_offset = bs_read_ue(b); sps->frame_crop_top_offset = bs_read_ue(b); sps->frame_crop_bottom_offset = bs_read_ue(b); } sps->vui_parameters_present_flag = bs_read(b, 1); if (sps->vui_parameters_present_flag) { read_vui_parameters(sps, b); } //read_rbsp_trailing_bits(h, b); }
void Parser::parse(int *pb_nal_start) { h264_t *h = &h264; bs_t s; *pb_nal_start = 0; if( nal.i_type == NAL_SPS || nal.i_type == NAL_PPS ) *pb_nal_start = 1; bs_init( &s, nal.p_payload, nal.i_payload ); if( nal.i_type == NAL_SPS ) { int i_tmp; i_tmp = bs_read( &s, 8 ); bs_skip( &s, 1+1+1 + 5 + 8 ); /* sps id */ bs_read_ue( &s ); if( i_tmp >= 100 ) { b_hiprofile = 1; bs_read_ue( &s ); // chroma_format_idc bs_read_ue( &s ); // bit_depth_luma_minus8 bs_read_ue( &s ); // bit_depth_chroma_minus8 bs_skip( &s, 1 ); // qpprime_y_zero_transform_bypass_flag if( bs_read( &s, 1 ) ) // seq_scaling_matrix_present_flag { int i, j; for( i = 0; i < 8; i++ ) { if( bs_read( &s, 1 ) ) // seq_scaling_list_present_flag[i] { uint8 i_tmp = 8; for( j = 0; j < (i<6?16:64); j++ ) { i_tmp += bs_read_se( &s ); if( i_tmp == 0 ) break; } } } } } /* Skip i_log2_max_frame_num */ h->i_log2_max_frame_num = bs_read_ue( &s ) + 4; /* Read poc_type */ h->i_poc_type = bs_read_ue( &s ); if( h->i_poc_type == 0 ) { h->i_log2_max_poc_lsb = bs_read_ue( &s ) + 4; } else if( h->i_poc_type == 1 ) { int i_cycle; /* skip b_delta_pic_order_always_zero */ bs_skip( &s, 1 ); /* skip i_offset_for_non_ref_pic */ bs_read_se( &s ); /* skip i_offset_for_top_to_bottom_field */ bs_read_se( &s ); /* read i_num_ref_frames_in_poc_cycle */ i_cycle = bs_read_ue( &s ); if( i_cycle > 256 ) i_cycle = 256; while( i_cycle > 0 ) { /* skip i_offset_for_ref_frame */ bs_read_se(&s ); } } /* i_num_ref_frames */ bs_read_ue( &s ); /* b_gaps_in_frame_num_value_allowed */ bs_skip( &s, 1 ); /* Read size */ h->i_width = 16 * ( bs_read_ue( &s ) + 1 ); h->i_height = 32 * ( bs_read_ue( &s ) + 1 ); /* b_frame_mbs_only */ i_tmp = bs_read( &s, 1 ); if( i_tmp == 1 ) { // fix: progressive, half height h->i_height /= 2; } else { // mb_adaptive_frame_field_flag bs_skip( &s, 1 ); } /* b_direct8x8_inference */ bs_skip( &s, 1 ); /* crop ? */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { // fix: no cropping /* left */ //h->i_width -= 2 * bs_read_ue( &s ); /* right */ //h->i_width -= 2 * bs_read_ue( &s ); /* top */ //h->i_height -= 2 * bs_read_ue( &s ); /* bottom */ //h->i_height -= 2 * bs_read_ue( &s ); } /* vui: ignored */ } else if( nal.i_type >= NAL_SLICE && nal.i_type <= NAL_SLICE_IDR ) { int i_tmp; /* i_first_mb */ bs_read_ue( &s ); /* picture type */ switch( bs_read_ue( &s ) ) { case 0: case 5: /* P */ case 1: case 6: /* B */ case 3: case 8: /* SP */ h->b_key = 0; break; case 2: case 7: /* I */ case 4: case 9: /* SI */ // fix: key flags in high profile h->b_key = (nal.i_type == NAL_SLICE_IDR || (b_hiprofile && nal.i_type == NAL_SLICE)); break; } /* pps id */ bs_read_ue( &s ); /* frame num */ i_tmp = bs_read( &s, h->i_log2_max_frame_num ); if( i_tmp != h->i_frame_num ) *pb_nal_start = 1; h->i_frame_num = i_tmp; if( nal.i_type == NAL_SLICE_IDR ) { i_tmp = bs_read_ue( &s ); if( h->i_nal_type == NAL_SLICE_IDR && h->i_idr_pic_id != i_tmp ) *pb_nal_start = 1; h->i_idr_pic_id = i_tmp; } if( h->i_poc_type == 0 ) { i_tmp = bs_read( &s, h->i_log2_max_poc_lsb ); if( i_tmp != h->i_poc ) *pb_nal_start = 1; h->i_poc = i_tmp; } } h->i_nal_type = nal.i_type; h->i_ref_idc = nal.i_ref_idc; }
static bool h264_parse_sequence_parameter_set_rbsp( bs_t *p_bs, h264_sequence_parameter_set_t *p_sps ) { int i_tmp; int i_profile_idc = bs_read( p_bs, 8 ); p_sps->i_profile = i_profile_idc; p_sps->i_constraint_set_flags = bs_read( p_bs, 8 ); p_sps->i_level = bs_read( p_bs, 8 ); /* sps id */ uint32_t i_sps_id = bs_read_ue( p_bs ); if( i_sps_id > H264_SPS_ID_MAX ) return false; p_sps->i_id = i_sps_id; if( i_profile_idc == PROFILE_H264_HIGH || i_profile_idc == PROFILE_H264_HIGH_10 || i_profile_idc == PROFILE_H264_HIGH_422 || i_profile_idc == PROFILE_H264_HIGH_444 || /* Old one, no longer on spec */ i_profile_idc == PROFILE_H264_HIGH_444_PREDICTIVE || i_profile_idc == PROFILE_H264_CAVLC_INTRA || i_profile_idc == PROFILE_H264_SVC_BASELINE || i_profile_idc == PROFILE_H264_SVC_HIGH || i_profile_idc == PROFILE_H264_MVC_MULTIVIEW_HIGH || i_profile_idc == PROFILE_H264_MVC_STEREO_HIGH || i_profile_idc == PROFILE_H264_MVC_MULTIVIEW_DEPTH_HIGH || i_profile_idc == PROFILE_H264_MVC_ENHANCED_MULTIVIEW_DEPTH_HIGH || i_profile_idc == PROFILE_H264_MFC_HIGH ) { /* chroma_format_idc */ p_sps->i_chroma_idc = bs_read_ue( p_bs ); if( p_sps->i_chroma_idc == 3 ) bs_skip( p_bs, 1 ); /* separate_colour_plane_flag */ /* bit_depth_luma_minus8 */ p_sps->i_bit_depth_luma = bs_read_ue( p_bs ) + 8; /* bit_depth_chroma_minus8 */ p_sps->i_bit_depth_chroma = bs_read_ue( p_bs ) + 8; /* qpprime_y_zero_transform_bypass_flag */ bs_skip( p_bs, 1 ); /* seq_scaling_matrix_present_flag */ i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { for( int i = 0; i < ((3 != p_sps->i_chroma_idc) ? 8 : 12); i++ ) { /* seq_scaling_list_present_flag[i] */ i_tmp = bs_read( p_bs, 1 ); if( !i_tmp ) continue; const int i_size_of_scaling_list = (i < 6 ) ? 16 : 64; /* scaling_list (...) */ int i_lastscale = 8; int i_nextscale = 8; for( int j = 0; j < i_size_of_scaling_list; j++ ) { if( i_nextscale != 0 ) { /* delta_scale */ i_tmp = bs_read_se( p_bs ); i_nextscale = ( i_lastscale + i_tmp + 256 ) % 256; /* useDefaultScalingMatrixFlag = ... */ } /* scalinglist[j] */ i_lastscale = ( i_nextscale == 0 ) ? i_lastscale : i_nextscale; } } } } /* Skip i_log2_max_frame_num */ p_sps->i_log2_max_frame_num = bs_read_ue( p_bs ); if( p_sps->i_log2_max_frame_num > 12) p_sps->i_log2_max_frame_num = 12; /* Read poc_type */ p_sps->i_pic_order_cnt_type = bs_read_ue( p_bs ); if( p_sps->i_pic_order_cnt_type == 0 ) { /* skip i_log2_max_poc_lsb */ p_sps->i_log2_max_pic_order_cnt_lsb = bs_read_ue( p_bs ); if( p_sps->i_log2_max_pic_order_cnt_lsb > 12 ) p_sps->i_log2_max_pic_order_cnt_lsb = 12; } else if( p_sps->i_pic_order_cnt_type == 1 ) { int i_cycle; /* skip b_delta_pic_order_always_zero */ p_sps->i_delta_pic_order_always_zero_flag = bs_read( p_bs, 1 ); /* skip i_offset_for_non_ref_pic */ bs_read_se( p_bs ); /* skip i_offset_for_top_to_bottom_field */ bs_read_se( p_bs ); /* read i_num_ref_frames_in_poc_cycle */ i_cycle = bs_read_ue( p_bs ); if( i_cycle > 256 ) i_cycle = 256; while( i_cycle > 0 ) { /* skip i_offset_for_ref_frame */ bs_read_se(p_bs ); i_cycle--; } } /* i_num_ref_frames */ bs_read_ue( p_bs ); /* b_gaps_in_frame_num_value_allowed */ bs_skip( p_bs, 1 ); /* Read size */ p_sps->pic_width_in_mbs_minus1 = bs_read_ue( p_bs ); p_sps->pic_height_in_map_units_minus1 = bs_read_ue( p_bs ); /* b_frame_mbs_only */ p_sps->frame_mbs_only_flag = bs_read( p_bs, 1 ); if( !p_sps->frame_mbs_only_flag ) bs_skip( p_bs, 1 ); /* b_direct8x8_inference */ bs_skip( p_bs, 1 ); /* crop */ if( bs_read1( p_bs ) ) /* frame_cropping_flag */ { p_sps->frame_crop.left_offset = bs_read_ue( p_bs ); p_sps->frame_crop.right_offset = bs_read_ue( p_bs ); p_sps->frame_crop.right_offset = bs_read_ue( p_bs ); p_sps->frame_crop.bottom_offset = bs_read_ue( p_bs ); } /* vui */ i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { p_sps->vui.b_valid = true; /* read the aspect ratio part if any */ i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { static const struct { int w, h; } sar[17] = { { 0, 0 }, { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, { 160,99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, }; int i_sar = bs_read( p_bs, 8 ); int w, h; if( i_sar < 17 ) { w = sar[i_sar].w; h = sar[i_sar].h; } else if( i_sar == 255 ) { w = bs_read( p_bs, 16 ); h = bs_read( p_bs, 16 ); } else { w = 0; h = 0; } if( w != 0 && h != 0 ) { p_sps->vui.i_sar_num = w; p_sps->vui.i_sar_den = h; } else { p_sps->vui.i_sar_num = 1; p_sps->vui.i_sar_den = 1; } } /* overscan */ i_tmp = bs_read( p_bs, 1 ); if ( i_tmp ) bs_read( p_bs, 1 ); /* video signal type */ i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { bs_read( p_bs, 3 ); p_sps->vui.colour.b_full_range = bs_read( p_bs, 1 ); /* colour desc */ i_tmp = bs_read( p_bs, 1 ); if ( i_tmp ) { p_sps->vui.colour.i_colour_primaries = bs_read( p_bs, 8 ); p_sps->vui.colour.i_transfer_characteristics = bs_read( p_bs, 8 ); p_sps->vui.colour.i_matrix_coefficients = bs_read( p_bs, 8 ); } else { p_sps->vui.colour.i_colour_primaries = HXXX_PRIMARIES_UNSPECIFIED; p_sps->vui.colour.i_transfer_characteristics = HXXX_TRANSFER_UNSPECIFIED; p_sps->vui.colour.i_matrix_coefficients = HXXX_MATRIX_UNSPECIFIED; } } /* chroma loc info */ i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { bs_read_ue( p_bs ); bs_read_ue( p_bs ); } /* timing info */ p_sps->vui.b_timing_info_present_flag = bs_read( p_bs, 1 ); if( p_sps->vui.b_timing_info_present_flag ) { p_sps->vui.i_num_units_in_tick = bs_read( p_bs, 32 ); p_sps->vui.i_time_scale = bs_read( p_bs, 32 ); p_sps->vui.b_fixed_frame_rate = bs_read( p_bs, 1 ); } /* Nal hrd & VC1 hrd parameters */ p_sps->vui.b_hrd_parameters_present_flag = false; for ( int i=0; i<2; i++ ) { i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { p_sps->vui.b_hrd_parameters_present_flag = true; uint32_t count = bs_read_ue( p_bs ) + 1; if( count > 31 ) return false; bs_read( p_bs, 4 ); bs_read( p_bs, 4 ); for( uint32_t i=0; i<count; i++ ) { if( bs_remain( p_bs ) < 23 ) return false; bs_read_ue( p_bs ); bs_read_ue( p_bs ); bs_read( p_bs, 1 ); } bs_read( p_bs, 5 ); p_sps->vui.i_cpb_removal_delay_length_minus1 = bs_read( p_bs, 5 ); p_sps->vui.i_dpb_output_delay_length_minus1 = bs_read( p_bs, 5 ); bs_read( p_bs, 5 ); } } if( p_sps->vui.b_hrd_parameters_present_flag ) bs_read( p_bs, 1 ); /* pic struct info */ p_sps->vui.b_pic_struct_present_flag = bs_read( p_bs, 1 ); /* + unparsed remains */ } return true; }
/***************************************************************************** * ParseNALBlock: parses annexB type NALs * All p_frag blocks are required to start with 0 0 0 1 4-byte startcode *****************************************************************************/ static block_t *ParseNALBlock( decoder_t *p_dec, block_t *p_frag ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_pic = NULL; const int i_nal_ref_idc = (p_frag->p_buffer[4] >> 5)&0x03; const int i_nal_type = p_frag->p_buffer[4]&0x1f; #define OUTPUT \ do { \ if( !p_sys->b_header && p_sys->slice.i_frame_type != BLOCK_FLAG_TYPE_I) \ break; \ \ if( p_sys->slice.i_frame_type == BLOCK_FLAG_TYPE_I && p_sys->p_sps && p_sys->p_pps && !p_sys->b_header ) \ { \ block_t *p_sps = block_Duplicate( p_sys->p_sps ); \ block_t *p_pps = block_Duplicate( p_sys->p_pps ); \ p_sps->i_dts = p_sys->p_frame->i_dts; \ p_sps->i_pts = p_sys->p_frame->i_pts; \ block_ChainAppend( &p_sps, p_pps ); \ block_ChainAppend( &p_sps, p_sys->p_frame ); \ p_sys->b_header = VLC_TRUE; \ p_pic = block_ChainGather( p_sps ); \ } else { \ p_pic = block_ChainGather( p_sys->p_frame ); \ } \ p_pic->i_length = 0; /* FIXME */ \ p_pic->i_flags |= p_sys->slice.i_frame_type; \ \ p_sys->slice.i_frame_type = 0; \ p_sys->p_frame = NULL; \ p_sys->b_slice = VLC_FALSE; \ } while(0) if( p_sys->b_slice && ( !p_sys->b_sps || !p_sys->b_pps ) ) { block_ChainRelease( p_sys->p_frame ); msg_Warn( p_dec, "waiting for SPS/PPS" ); /* Reset context */ p_sys->slice.i_frame_type = 0; p_sys->p_frame = NULL; p_sys->b_slice = VLC_FALSE; } if( ( !p_sys->b_sps || !p_sys->b_pps ) && i_nal_type >= NAL_SLICE && i_nal_type <= NAL_SLICE_IDR ) { p_sys->b_slice = VLC_TRUE; /* Fragment will be discarded later on */ } else if( i_nal_type >= NAL_SLICE && i_nal_type <= NAL_SLICE_IDR ) { uint8_t *dec; int i_dec, i_first_mb, i_slice_type; slice_t slice; vlc_bool_t b_pic; bs_t s; /* do not convert the whole frame */ nal_get_decoded( &dec, &i_dec, &p_frag->p_buffer[5], __MIN( p_frag->i_buffer - 5, 60 ) ); bs_init( &s, dec, i_dec ); /* first_mb_in_slice */ i_first_mb = bs_read_ue( &s ); /* slice_type */ switch( (i_slice_type = bs_read_ue( &s )) ) { case 0: case 5: slice.i_frame_type = BLOCK_FLAG_TYPE_P; break; case 1: case 6: slice.i_frame_type = BLOCK_FLAG_TYPE_B; break; case 2: case 7: slice.i_frame_type = BLOCK_FLAG_TYPE_I; break; case 3: case 8: /* SP */ slice.i_frame_type = BLOCK_FLAG_TYPE_P; break; case 4: case 9: slice.i_frame_type = BLOCK_FLAG_TYPE_I; break; default: slice.i_frame_type = 0; break; } /* */ slice.i_nal_type = i_nal_type; slice.i_nal_ref_idc = i_nal_ref_idc; slice.i_pic_parameter_set_id = bs_read_ue( &s ); slice.i_frame_num = bs_read( &s, p_sys->i_log2_max_frame_num + 4 ); slice.i_field_pic_flag = 0; slice.i_bottom_field_flag = -1; if( !p_sys->b_frame_mbs_only ) { /* field_pic_flag */ slice.i_field_pic_flag = bs_read( &s, 1 ); if( slice.i_field_pic_flag ) slice.i_bottom_field_flag = bs_read( &s, 1 ); } slice.i_idr_pic_id = p_sys->slice.i_idr_pic_id; if( slice.i_nal_type == NAL_SLICE_IDR ) slice.i_idr_pic_id = bs_read_ue( &s ); slice.i_pic_order_cnt_lsb = -1; slice.i_delta_pic_order_cnt_bottom = -1; slice.i_delta_pic_order_cnt0 = 0; slice.i_delta_pic_order_cnt1 = 0; if( p_sys->i_pic_order_cnt_type == 0 ) { slice.i_pic_order_cnt_lsb = bs_read( &s, p_sys->i_log2_max_pic_order_cnt_lsb + 4 ); if( p_sys->i_pic_order_present_flag && !slice.i_field_pic_flag ) slice.i_delta_pic_order_cnt_bottom = bs_read_se( &s ); } else if( p_sys->i_pic_order_cnt_type == 1 && !p_sys->i_delta_pic_order_always_zero_flag ) { slice.i_delta_pic_order_cnt0 = bs_read_se( &s ); if( p_sys->i_pic_order_present_flag && !slice.i_field_pic_flag ) slice.i_delta_pic_order_cnt1 = bs_read_se( &s ); } /* Detection of the first VCL NAL unit of a primary coded picture * (cf. 7.4.1.2.4) */ b_pic = VLC_FALSE; if( slice.i_frame_num != p_sys->slice.i_frame_num || slice.i_pic_parameter_set_id != p_sys->slice.i_pic_parameter_set_id || slice.i_field_pic_flag != p_sys->slice.i_field_pic_flag || slice.i_nal_ref_idc != p_sys->slice.i_nal_ref_idc ) b_pic = VLC_TRUE; if( slice.i_bottom_field_flag != -1 && p_sys->slice.i_bottom_field_flag != -1 && slice.i_bottom_field_flag != p_sys->slice.i_bottom_field_flag ) b_pic = VLC_TRUE; if( p_sys->i_pic_order_cnt_type == 0 && ( slice.i_pic_order_cnt_lsb != p_sys->slice.i_pic_order_cnt_lsb || slice.i_delta_pic_order_cnt_bottom != p_sys->slice.i_delta_pic_order_cnt_bottom ) ) b_pic = VLC_TRUE; else if( p_sys->i_pic_order_cnt_type == 1 && ( slice.i_delta_pic_order_cnt0 != p_sys->slice.i_delta_pic_order_cnt0 || slice.i_delta_pic_order_cnt1 != p_sys->slice.i_delta_pic_order_cnt1 ) ) b_pic = VLC_TRUE; if( ( slice.i_nal_type == NAL_SLICE_IDR || p_sys->slice.i_nal_type == NAL_SLICE_IDR ) && ( slice.i_nal_type != p_sys->slice.i_nal_type || slice.i_idr_pic_id != p_sys->slice.i_idr_pic_id ) ) b_pic = VLC_TRUE; /* */ p_sys->slice = slice; if( b_pic && p_sys->b_slice ) OUTPUT; p_sys->b_slice = VLC_TRUE; free( dec ); } else if( i_nal_type == NAL_SPS ) { uint8_t *dec; int i_dec; bs_t s; int i_tmp; if( !p_sys->b_sps ) msg_Dbg( p_dec, "found NAL_SPS" ); p_sys->b_sps = VLC_TRUE; nal_get_decoded( &dec, &i_dec, &p_frag->p_buffer[5], p_frag->i_buffer - 5 ); bs_init( &s, dec, i_dec ); /* Skip profile(8), constraint_set012, reserver(5), level(8) */ bs_skip( &s, 8 + 1+1+1 + 5 + 8 ); /* sps id */ bs_read_ue( &s ); /* Skip i_log2_max_frame_num */ p_sys->i_log2_max_frame_num = bs_read_ue( &s ); if( p_sys->i_log2_max_frame_num > 12) p_sys->i_log2_max_frame_num = 12; /* Read poc_type */ p_sys->i_pic_order_cnt_type = bs_read_ue( &s ); if( p_sys->i_pic_order_cnt_type == 0 ) { /* skip i_log2_max_poc_lsb */ p_sys->i_log2_max_pic_order_cnt_lsb = bs_read_ue( &s ); if( p_sys->i_log2_max_pic_order_cnt_lsb > 12 ) p_sys->i_log2_max_pic_order_cnt_lsb = 12; } else if( p_sys->i_pic_order_cnt_type == 1 ) { int i_cycle; /* skip b_delta_pic_order_always_zero */ p_sys->i_delta_pic_order_always_zero_flag = bs_read( &s, 1 ); /* skip i_offset_for_non_ref_pic */ bs_read_se( &s ); /* skip i_offset_for_top_to_bottom_field */ bs_read_se( &s ); /* read i_num_ref_frames_in_poc_cycle */ i_cycle = bs_read_ue( &s ); if( i_cycle > 256 ) i_cycle = 256; while( i_cycle > 0 ) { /* skip i_offset_for_ref_frame */ bs_read_se(&s ); } } /* i_num_ref_frames */ bs_read_ue( &s ); /* b_gaps_in_frame_num_value_allowed */ bs_skip( &s, 1 ); /* Read size */ p_dec->fmt_out.video.i_width = 16 * ( bs_read_ue( &s ) + 1 ); p_dec->fmt_out.video.i_height = 16 * ( bs_read_ue( &s ) + 1 ); /* b_frame_mbs_only */ p_sys->b_frame_mbs_only = bs_read( &s, 1 ); if( p_sys->b_frame_mbs_only == 0 ) { bs_skip( &s, 1 ); } /* b_direct8x8_inference */ bs_skip( &s, 1 ); /* crop */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { /* left */ bs_read_ue( &s ); /* right */ bs_read_ue( &s ); /* top */ bs_read_ue( &s ); /* bottom */ bs_read_ue( &s ); } /* vui */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { /* read the aspect ratio part if any FIXME check it */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { static const struct { int w, h; } sar[14] = { { 0, 0 }, { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, { 160,99 }, }; int i_sar = bs_read( &s, 8 ); int w, h; if( i_sar < 14 ) { w = sar[i_sar].w; h = sar[i_sar].h; } else { w = bs_read( &s, 16 ); h = bs_read( &s, 16 ); } if( h != 0 ) p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * w / h * p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height; else p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR; } } free( dec ); if( p_sys->b_slice ) OUTPUT; /* We have a new SPS */ if( p_sys->p_sps ) block_Release( p_sys->p_sps ); p_sys->p_sps = p_frag; /* Do not append the SPS because we will insert it on keyframes */ return p_pic; } else if( i_nal_type == NAL_PPS ) { bs_t s; bs_init( &s, &p_frag->p_buffer[5], p_frag->i_buffer - 5 ); bs_read_ue( &s ); // pps id bs_read_ue( &s ); // sps id bs_skip( &s, 1 ); // entropy coding mode flag p_sys->i_pic_order_present_flag = bs_read( &s, 1 ); if( !p_sys->b_pps ) msg_Dbg( p_dec, "found NAL_PPS" ); p_sys->b_pps = VLC_TRUE; /* TODO */ if( p_sys->b_slice ) OUTPUT; /* We have a new PPS */ if( p_sys->p_pps ) block_Release( p_sys->p_pps ); p_sys->p_pps = p_frag; /* Do not append the PPS because we will insert it on keyframes */ return p_pic; } else if( i_nal_type == NAL_AU_DELIMITER || i_nal_type == NAL_SEI || ( i_nal_type >= 13 && i_nal_type <= 18 ) ) { if( p_sys->b_slice ) OUTPUT; } #undef OUTPUT /* Append the block */ block_ChainAppend( &p_sys->p_frame, p_frag ); return p_pic; }
static void PutSPS( decoder_t *p_dec, block_t *p_frag ) { decoder_sys_t *p_sys = p_dec->p_sys; uint8_t *pb_dec = NULL; int i_dec = 0; bs_t s; int i_tmp; int i_sps_id; CreateDecodedNAL( &pb_dec, &i_dec, &p_frag->p_buffer[5], p_frag->i_buffer - 5 ); bs_init( &s, pb_dec, i_dec ); int i_profile_idc = bs_read( &s, 8 ); p_dec->fmt_out.i_profile = i_profile_idc; /* Skip constraint_set0123, reserved(4) */ bs_skip( &s, 1+1+1+1 + 4 ); p_dec->fmt_out.i_level = bs_read( &s, 8 ); /* sps id */ i_sps_id = bs_read_ue( &s ); if( i_sps_id >= SPS_MAX || i_sps_id < 0 ) { msg_Warn( p_dec, "invalid SPS (sps_id=%d)", i_sps_id ); free( pb_dec ); block_Release( p_frag ); return; } if( i_profile_idc == 100 || i_profile_idc == 110 || i_profile_idc == 122 || i_profile_idc == 244 || i_profile_idc == 44 || i_profile_idc == 83 || i_profile_idc == 86 ) { /* chroma_format_idc */ const int i_chroma_format_idc = bs_read_ue( &s ); if( i_chroma_format_idc == 3 ) bs_skip( &s, 1 ); /* separate_colour_plane_flag */ /* bit_depth_luma_minus8 */ bs_read_ue( &s ); /* bit_depth_chroma_minus8 */ bs_read_ue( &s ); /* qpprime_y_zero_transform_bypass_flag */ bs_skip( &s, 1 ); /* seq_scaling_matrix_present_flag */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { for( int i = 0; i < ((3 != i_chroma_format_idc) ? 8 : 12); i++ ) { /* seq_scaling_list_present_flag[i] */ i_tmp = bs_read( &s, 1 ); if( !i_tmp ) continue; const int i_size_of_scaling_list = (i < 6 ) ? 16 : 64; /* scaling_list (...) */ int i_lastscale = 8; int i_nextscale = 8; for( int j = 0; j < i_size_of_scaling_list; j++ ) { if( i_nextscale != 0 ) { /* delta_scale */ i_tmp = bs_read_se( &s ); i_nextscale = ( i_lastscale + i_tmp + 256 ) % 256; /* useDefaultScalingMatrixFlag = ... */ } /* scalinglist[j] */ i_lastscale = ( i_nextscale == 0 ) ? i_lastscale : i_nextscale; } } } } /* Skip i_log2_max_frame_num */ p_sys->i_log2_max_frame_num = bs_read_ue( &s ); if( p_sys->i_log2_max_frame_num > 12) p_sys->i_log2_max_frame_num = 12; /* Read poc_type */ p_sys->i_pic_order_cnt_type = bs_read_ue( &s ); if( p_sys->i_pic_order_cnt_type == 0 ) { /* skip i_log2_max_poc_lsb */ p_sys->i_log2_max_pic_order_cnt_lsb = bs_read_ue( &s ); if( p_sys->i_log2_max_pic_order_cnt_lsb > 12 ) p_sys->i_log2_max_pic_order_cnt_lsb = 12; } else if( p_sys->i_pic_order_cnt_type == 1 ) { int i_cycle; /* skip b_delta_pic_order_always_zero */ p_sys->i_delta_pic_order_always_zero_flag = bs_read( &s, 1 ); /* skip i_offset_for_non_ref_pic */ bs_read_se( &s ); /* skip i_offset_for_top_to_bottom_field */ bs_read_se( &s ); /* read i_num_ref_frames_in_poc_cycle */ i_cycle = bs_read_ue( &s ); if( i_cycle > 256 ) i_cycle = 256; while( i_cycle > 0 ) { /* skip i_offset_for_ref_frame */ bs_read_se(&s ); i_cycle--; } } /* i_num_ref_frames */ bs_read_ue( &s ); /* b_gaps_in_frame_num_value_allowed */ bs_skip( &s, 1 ); /* Read size */ p_dec->fmt_out.video.i_width = 16 * ( bs_read_ue( &s ) + 1 ); p_dec->fmt_out.video.i_height = 16 * ( bs_read_ue( &s ) + 1 ); /* b_frame_mbs_only */ p_sys->b_frame_mbs_only = bs_read( &s, 1 ); p_dec->fmt_out.video.i_height *= ( 2 - p_sys->b_frame_mbs_only ); if( p_sys->b_frame_mbs_only == 0 ) { bs_skip( &s, 1 ); } /* b_direct8x8_inference */ bs_skip( &s, 1 ); /* crop */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { /* left */ bs_read_ue( &s ); /* right */ bs_read_ue( &s ); /* top */ bs_read_ue( &s ); /* bottom */ bs_read_ue( &s ); } /* vui */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { /* read the aspect ratio part if any */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { static const struct { int w, h; } sar[17] = { { 0, 0 }, { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, { 160,99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, }; int i_sar = bs_read( &s, 8 ); int w, h; if( i_sar < 17 ) { w = sar[i_sar].w; h = sar[i_sar].h; } else if( i_sar == 255 ) { w = bs_read( &s, 16 ); h = bs_read( &s, 16 ); } else { w = 0; h = 0; } if( w != 0 && h != 0 ) { p_dec->fmt_out.video.i_sar_num = w; p_dec->fmt_out.video.i_sar_den = h; } else { p_dec->fmt_out.video.i_sar_num = 1; p_dec->fmt_out.video.i_sar_den = 1; } } } free( pb_dec ); /* We have a new SPS */ if( !p_sys->b_sps ) msg_Dbg( p_dec, "found NAL_SPS (sps_id=%d)", i_sps_id ); p_sys->b_sps = true; if( p_sys->pp_sps[i_sps_id] ) block_Release( p_sys->pp_sps[i_sps_id] ); p_sys->pp_sps[i_sps_id] = p_frag; }
static void ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t *p_slice, int i_nal_ref_idc, int i_nal_type, const block_t *p_frag ) { decoder_sys_t *p_sys = p_dec->p_sys; uint8_t *pb_dec; int i_dec; int i_slice_type; slice_t slice; bs_t s; /* do not convert the whole frame */ CreateDecodedNAL( &pb_dec, &i_dec, &p_frag->p_buffer[5], __MIN( p_frag->i_buffer - 5, 60 ) ); bs_init( &s, pb_dec, i_dec ); /* first_mb_in_slice */ /* int i_first_mb = */ bs_read_ue( &s ); /* slice_type */ switch( (i_slice_type = bs_read_ue( &s )) ) { case 0: case 5: slice.i_frame_type = BLOCK_FLAG_TYPE_P; break; case 1: case 6: slice.i_frame_type = BLOCK_FLAG_TYPE_B; break; case 2: case 7: slice.i_frame_type = BLOCK_FLAG_TYPE_I; break; case 3: case 8: /* SP */ slice.i_frame_type = BLOCK_FLAG_TYPE_P; break; case 4: case 9: slice.i_frame_type = BLOCK_FLAG_TYPE_I; break; default: slice.i_frame_type = 0; break; } /* */ slice.i_nal_type = i_nal_type; slice.i_nal_ref_idc = i_nal_ref_idc; slice.i_pic_parameter_set_id = bs_read_ue( &s ); slice.i_frame_num = bs_read( &s, p_sys->i_log2_max_frame_num + 4 ); slice.i_field_pic_flag = 0; slice.i_bottom_field_flag = -1; if( !p_sys->b_frame_mbs_only ) { /* field_pic_flag */ slice.i_field_pic_flag = bs_read( &s, 1 ); if( slice.i_field_pic_flag ) slice.i_bottom_field_flag = bs_read( &s, 1 ); } slice.i_idr_pic_id = p_sys->slice.i_idr_pic_id; if( slice.i_nal_type == NAL_SLICE_IDR ) slice.i_idr_pic_id = bs_read_ue( &s ); slice.i_pic_order_cnt_lsb = -1; slice.i_delta_pic_order_cnt_bottom = -1; slice.i_delta_pic_order_cnt0 = 0; slice.i_delta_pic_order_cnt1 = 0; if( p_sys->i_pic_order_cnt_type == 0 ) { slice.i_pic_order_cnt_lsb = bs_read( &s, p_sys->i_log2_max_pic_order_cnt_lsb + 4 ); if( p_sys->i_pic_order_present_flag && !slice.i_field_pic_flag ) slice.i_delta_pic_order_cnt_bottom = bs_read_se( &s ); } else if( (p_sys->i_pic_order_cnt_type == 1) && (!p_sys->i_delta_pic_order_always_zero_flag) ) { slice.i_delta_pic_order_cnt0 = bs_read_se( &s ); if( p_sys->i_pic_order_present_flag && !slice.i_field_pic_flag ) slice.i_delta_pic_order_cnt1 = bs_read_se( &s ); } free( pb_dec ); /* Detection of the first VCL NAL unit of a primary coded picture * (cf. 7.4.1.2.4) */ bool b_pic = false; if( slice.i_frame_num != p_sys->slice.i_frame_num || slice.i_pic_parameter_set_id != p_sys->slice.i_pic_parameter_set_id || slice.i_field_pic_flag != p_sys->slice.i_field_pic_flag || slice.i_nal_ref_idc != p_sys->slice.i_nal_ref_idc ) b_pic = true; if( (slice.i_bottom_field_flag != -1) && (p_sys->slice.i_bottom_field_flag != -1) && (slice.i_bottom_field_flag != p_sys->slice.i_bottom_field_flag) ) b_pic = true; if( p_sys->i_pic_order_cnt_type == 0 && ( slice.i_pic_order_cnt_lsb != p_sys->slice.i_pic_order_cnt_lsb || slice.i_delta_pic_order_cnt_bottom != p_sys->slice.i_delta_pic_order_cnt_bottom ) ) b_pic = true; else if( p_sys->i_pic_order_cnt_type == 1 && ( slice.i_delta_pic_order_cnt0 != p_sys->slice.i_delta_pic_order_cnt0 || slice.i_delta_pic_order_cnt1 != p_sys->slice.i_delta_pic_order_cnt1 ) ) b_pic = true; if( ( slice.i_nal_type == NAL_SLICE_IDR || p_sys->slice.i_nal_type == NAL_SLICE_IDR ) && ( slice.i_nal_type != p_sys->slice.i_nal_type || slice.i_idr_pic_id != p_sys->slice.i_idr_pic_id ) ) b_pic = true; /* */ *pb_new_picture = b_pic; *p_slice = slice; }
static block_t *ParseNALBlock( decoder_t *p_dec, block_t *p_frag ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_pic = NULL; const int i_nal_ref_idc = (p_frag->p_buffer[3] >> 5)&0x03; const int i_nal_type = p_frag->p_buffer[3]&0x1f; if( p_sys->b_slice && !p_sys->b_sps ) { block_ChainRelease( p_sys->p_frame ); msg_Warn( p_dec, "waiting for SPS" ); /* Reset context */ p_sys->p_frame = NULL; p_sys->b_slice = VLC_FALSE; } if( !p_sys->b_sps && i_nal_type >= NAL_SLICE && i_nal_type <= NAL_SLICE_IDR ) { p_sys->b_slice = VLC_TRUE; /* Fragment will be discarded later on */ } else if( i_nal_type >= NAL_SLICE && i_nal_type <= NAL_SLICE_IDR ) { uint8_t *dec; int i_dec, i_first_mb, i_slice_type, i_frame_num, i_pic_flags = 0; vlc_bool_t b_pic = VLC_FALSE; bs_t s; /* do not convert the whole frame */ nal_get_decoded( &dec, &i_dec, &p_frag->p_buffer[4], __MIN( p_frag->i_buffer - 4, 60 ) ); bs_init( &s, dec, i_dec ); /* first_mb_in_slice */ i_first_mb = bs_read_ue( &s ); /* slice_type */ switch( (i_slice_type = bs_read_ue( &s )) ) { case 0: case 5: i_pic_flags = BLOCK_FLAG_TYPE_P; break; case 1: case 6: i_pic_flags = BLOCK_FLAG_TYPE_B; break; case 2: case 7: i_pic_flags = BLOCK_FLAG_TYPE_I; break; case 3: case 8: /* SP */ i_pic_flags = BLOCK_FLAG_TYPE_P; break; case 4: case 9: i_pic_flags = BLOCK_FLAG_TYPE_I; break; } /* pic_parameter_set_id */ bs_read_ue( &s ); /* frame_num */ i_frame_num = bs_read( &s, p_sys->i_log2_max_frame_num + 4 ); /* Detection of the first VCL NAL unit of a primary coded picture * (cf. 7.4.1.2.4) */ if( i_frame_num != p_sys->i_frame_num || ( (i_nal_ref_idc != p_sys->i_nal_ref_idc) && (!i_nal_ref_idc || !p_sys->i_nal_ref_idc) ) ) { b_pic = VLC_TRUE; } p_sys->i_frame_num = i_frame_num; p_sys->i_nal_ref_idc = i_nal_ref_idc; if( !p_sys->b_frame_mbs_only ) { /* field_pic_flag */ if( bs_read( &s, 1 ) ) { /* bottom_field_flag */ bs_read( &s, 1 ); } } if( i_nal_type == NAL_SLICE_IDR ) { /* id_pic_id */ int i_idr_pic_id = bs_read_ue( &s ); if( p_sys->i_nal_type != i_nal_type ) b_pic = VLC_TRUE; if( p_sys->i_idr_pic_id != i_idr_pic_id ) b_pic = VLC_TRUE; p_sys->i_idr_pic_id = i_idr_pic_id; } p_sys->i_nal_type = i_nal_type; if( b_pic && p_sys->b_slice ) { p_pic = block_ChainGather( p_sys->p_frame ); p_pic->i_dts = p_sys->i_dts; p_pic->i_pts = p_sys->i_pts; p_pic->i_length = 0; /* FIXME */ p_pic->i_flags = p_sys->i_flags; /* Reset context */ p_sys->p_frame = NULL; p_sys->b_slice = VLC_FALSE; } p_sys->b_slice = VLC_TRUE; p_sys->i_flags = i_pic_flags; p_sys->i_dts = p_frag->i_dts; p_sys->i_pts = p_frag->i_pts; free( dec ); } else if( i_nal_type == NAL_SPS ) { uint8_t *dec; int i_dec; bs_t s; int i_tmp; msg_Dbg( p_dec, "found NAL_SPS" ); p_sys->b_sps = VLC_TRUE; nal_get_decoded( &dec, &i_dec, &p_frag->p_buffer[4], p_frag->i_buffer - 4 ); bs_init( &s, dec, i_dec ); /* Skip profile(8), constraint_set012, reserver(5), level(8) */ bs_skip( &s, 8 + 1+1+1 + 5 + 8 ); /* sps id */ bs_read_ue( &s ); /* Skip i_log2_max_frame_num */ p_sys->i_log2_max_frame_num = bs_read_ue( &s ); /* Read poc_type */ i_tmp = bs_read_ue( &s ); if( i_tmp == 0 ) { /* skip i_log2_max_poc_lsb */ bs_read_ue( &s ); } else if( i_tmp == 1 ) { int i_cycle; /* skip b_delta_pic_order_always_zero */ bs_skip( &s, 1 ); /* skip i_offset_for_non_ref_pic */ bs_read_se( &s ); /* skip i_offset_for_top_to_bottom_field */ bs_read_se( &s ); /* read i_num_ref_frames_in_poc_cycle */ i_cycle = bs_read_ue( &s ); if( i_cycle > 256 ) i_cycle = 256; while( i_cycle > 0 ) { /* skip i_offset_for_ref_frame */ bs_read_se(&s ); } } /* i_num_ref_frames */ bs_read_ue( &s ); /* b_gaps_in_frame_num_value_allowed */ bs_skip( &s, 1 ); /* Read size */ p_dec->fmt_out.video.i_width = 16 * ( bs_read_ue( &s ) + 1 ); p_dec->fmt_out.video.i_height = 16 * ( bs_read_ue( &s ) + 1 ); /* b_frame_mbs_only */ p_sys->b_frame_mbs_only = bs_read( &s, 1 ); if( p_sys->b_frame_mbs_only == 0 ) { bs_skip( &s, 1 ); } /* b_direct8x8_inference */ bs_skip( &s, 1 ); /* crop */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { /* left */ bs_read_ue( &s ); /* right */ bs_read_ue( &s ); /* top */ bs_read_ue( &s ); /* bottom */ bs_read_ue( &s ); } /* vui */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { /* read the aspect ratio part if any FIXME check it */ i_tmp = bs_read( &s, 1 ); if( i_tmp ) { static const struct { int w, h; } sar[14] = { { 0, 0 }, { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, { 160,99 }, }; int i_sar = bs_read( &s, 8 ); int w, h; if( i_sar < 14 ) { w = sar[i_sar].w; h = sar[i_sar].h; } else { w = bs_read( &s, 16 ); h = bs_read( &s, 16 ); } p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * w / h * p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height; } } free( dec ); } else if( i_nal_type == NAL_PPS ) { bs_t s; bs_init( &s, &p_frag->p_buffer[4], p_frag->i_buffer - 4 ); /* TODO */ msg_Dbg( p_dec, "found NAL_PPS" ); } /* Append the block */ block_ChainAppend( &p_sys->p_frame, p_frag ); return p_pic; }
bool h264MediaStream::ParseSqs(const buf_share_ptr SqsNode) { assert(SqsNode); if (StreamSps == NULL) StreamSps = new h264_sps_t; uint8_t *pb_dec = NULL; int i_dec = 0; bs_t s; int i_sps_id; i_dec = SqsNode->GetSizeValue(); int nal_hrd_parameters_present_flag, vcl_hrd_parameters_present_flag; pb_dec = const_cast<uint8_t *>(SqsNode->GetBuffer()); //转化00 00 03为00 00 uint8_t *p_nal = new uint8_t[i_dec]; int pcount = 0; for (int tmp = 1; tmp < i_dec ; tmp++) { if (tmp < i_dec - 3 && *(pb_dec + tmp) == 0x00 && *(pb_dec + tmp + 1) == 0x00 && *(pb_dec + tmp + 2) == 0x03) { p_nal[pcount++] = 0x00; p_nal[pcount++] = 0x00; //printf("count = %d %2X\n",tmp, *(p_nal + tmp)); tmp += 2; continue; } p_nal[pcount++] = *(pb_dec + tmp); } pb_dec = p_nal; //以下内容根据H264协议解读,属于直接复制粘贴代码 同parseslice bs_init( &s, pb_dec, i_dec ); // profile(8) StreamSps->profile_idc = bs_read( &s, 8); /* constraint_set012, reserver(5), level(8) */ bs_skip( &s, 1+1+1 + 5 + 8 ); /* sps id */ i_sps_id = bs_read_ue( &s ); if( i_sps_id >= 32/*SPS_MAX*/ ) { printf("invalid SPS (sps_id=%d)", i_sps_id ); delete pb_dec; return false; } StreamSps->scaling_matrix_present = 0; if(StreamSps->profile_idc >= 100) //high profile { if(bs_read_ue(&s) == 3) //chroma_format_idc bs_read(&s, 1); //residual_color_transform_flag bs_read_ue(&s); //bit_depth_luma_minus8 bs_read_ue(&s); //bit_depth_chroma_minus8 StreamSps->transform_bypass = bs_read(&s, 1); bs_skip(&s, 1); //decode_scaling_matrices(h, sps, NULL, 1, sps->scaling_matrix4, sps->scaling_matrix8); } /* Skip i_log2_max_frame_num */ StreamSps->log2_max_frame_num = bs_read_ue( &s ); if( StreamSps->log2_max_frame_num > 12) StreamSps->log2_max_frame_num = 12; /* Read poc_type */ StreamSps->poc_type/*->i_pic_order_cnt_type*/ = bs_read_ue( &s ); if( StreamSps->poc_type == 0 ) { /* skip i_log2_max_poc_lsb */ StreamSps->log2_max_poc_lsb/*->i_log2_max_pic_order_cnt_lsb*/ = bs_read_ue( &s ); if( StreamSps->log2_max_poc_lsb > 12 ) StreamSps->log2_max_poc_lsb = 12; } else if( StreamSps->poc_type/*p_sys->i_pic_order_cnt_type*/ == 1 ) { int i_cycle; /* skip b_delta_pic_order_always_zero */ StreamSps->delta_pic_order_always_zero_flag/*->i_delta_pic_order_always_zero_flag*/ = bs_read( &s, 1 ); /* skip i_offset_for_non_ref_pic */ bs_read_se( &s ); /* skip i_offset_for_top_to_bottom_field */ bs_read_se( &s ); /* read i_num_ref_frames_in_poc_cycle */ i_cycle = bs_read_ue( &s ); if( i_cycle > 256 ) i_cycle = 256; while( i_cycle > 0 ) { /* skip i_offset_for_ref_frame */ bs_read_se(&s ); i_cycle--; } } /* i_num_ref_frames */ bs_read_ue( &s ); /* b_gaps_in_frame_num_value_allowed */ bs_skip( &s, 1 ); /* Read size */ StreamSps->mb_width/*->fmt_out.video.i_width*/ = 16 * ( bs_read_ue( &s ) + 1 ); StreamSps->mb_height/*fmt_out.video.i_height*/ = 16 * ( bs_read_ue( &s ) + 1 ); /* b_frame_mbs_only */ StreamSps->frame_mbs_only_flag/*->b_frame_mbs_only*/ = bs_read( &s, 1 ); if( StreamSps->frame_mbs_only_flag == 0 ) { bs_skip( &s, 1 ); } /* b_direct8x8_inference */ bs_skip( &s, 1 ); /* crop */ StreamSps->crop = bs_read( &s, 1 ); if( StreamSps->crop ) { /* left */ bs_read_ue( &s ); /* right */ bs_read_ue( &s ); /* top */ bs_read_ue( &s ); /* bottom */ bs_read_ue( &s ); } /* vui */ StreamSps->vui_parameters_present_flag = bs_read( &s, 1 ); if( StreamSps->vui_parameters_present_flag ) { int aspect_ratio_info_present_flag = bs_read( &s, 1 ); if( aspect_ratio_info_present_flag ) { static const struct { int num, den; } sar[17] = { { 0, 0 }, { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 }, { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 }, { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 }, { 160,99 }, { 4, 3 }, { 3, 2 }, { 2, 1 }, }; int i_sar = bs_read( &s, 8 ); if( i_sar < 17 ) { StreamSps->sar.num = sar[i_sar].num; StreamSps->sar.den = sar[i_sar].den; } else if( i_sar == 255 ) { StreamSps->sar.num = bs_read( &s, 16 ); StreamSps->sar.den = bs_read( &s, 16 ); } else { StreamSps->sar.num = 0; StreamSps->sar.den = 0; } //if( den != 0 ) // p_dec->fmt_out.video.i_aspect = (int64_t)VOUT_ASPECT_FACTOR * // ( num * p_dec->fmt_out.video.i_width ) / // ( den * p_dec->fmt_out.video.i_height); //else // p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR; } else { StreamSps->sar.num = 0; StreamSps->sar.den = 0; } if(bs_read(&s, 1)) /* overscan_info_present_flag */ { bs_read(&s, 1); /* overscan_appropriate_flag */ } if(bs_read(&s, 1)) /* video_signal_type_present_flag */ { bs_read(&s, 3); /* video_format */ bs_read(&s, 1); /* video_full_range_flag */ if(bs_read(&s, 1)) /* colour_description_present_flag */ { bs_read(&s, 8); /* colour_primaries */ bs_read(&s, 8); /* transfer_characteristics */ bs_read(&s, 8); /* matrix_coefficients */ } } if(bs_read(&s, 1)) /* chroma_location_info_present_flag */ { bs_read_ue(&s); /* chroma_sample_location_type_top_field */ bs_read_ue(&s); /* chroma_sample_location_type_bottom_field */ } StreamSps->timing_info_present_flag = bs_read(&s, 1); if(StreamSps->timing_info_present_flag) { StreamSps->num_units_in_tick = bs_read(&s, 32); StreamSps->time_scale = bs_read(&s, 32); StreamSps->fixed_frame_rate_flag = bs_read(&s, 1); } nal_hrd_parameters_present_flag = bs_read(&s, 1); if(nal_hrd_parameters_present_flag) h264_decode_hrd_parameters(s, StreamSps); vcl_hrd_parameters_present_flag = bs_read(&s, 1); if(vcl_hrd_parameters_present_flag) h264_decode_hrd_parameters(s, StreamSps); if(nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) bs_read(&s, 1); /* low_delay_hrd_flag */ bs_read(&s, 1); /* pic_struct_present_flag */ StreamSps->bitstream_restriction_flag = bs_read(&s, 1); if(StreamSps->bitstream_restriction_flag) { unsigned int num_reorder_frames; bs_read(&s, 1); /* motion_vectors_over_pic_boundaries_flag */ bs_read_ue(&s); /* max_bytes_per_pic_denom */ bs_read_ue(&s); /* max_bits_per_mb_denom */ bs_read_ue(&s); /* log2_max_mv_length_horizontal */ bs_read_ue(&s); /* log2_max_mv_length_vertical */ num_reorder_frames= bs_read_ue(&s); bs_read_ue(&s); /*max_dec_frame_buffering*/ if(num_reorder_frames > 16 /*max_dec_frame_buffering || max_dec_frame_buffering > 16*/){ printf("illegal num_reorder_frames %d\n", num_reorder_frames); delete pb_dec; return true; } StreamSps->num_reorder_frames= num_reorder_frames; } } delete pb_dec; return true; }
void h264MediaStream::ParseSlice(uint8_t* p_nal, int n_nal_size, int i_nal_type) { if(CurSlice == NULL) CurSlice = new h264_slice_t; //转化00 00 03为00 00 int icount = 0; uint8_t p_slice[64] = {0}; int parcount = (n_nal_size>64?64:n_nal_size); for (int t = 0; t < parcount; t++) { if (t < parcount-2 && p_nal[t] == 0x00 && p_nal[t + 1] == 0x00 && p_nal[t + 2] == 0x03) { p_slice[icount++] = 0x00; p_slice[icount++] = 0x00; t += 2; continue; } p_slice[icount++] = p_nal[t]; } bs_t s; bs_init(&s, p_slice, icount); bs_read_ue( &s ); // first_mb_in_slice CurSlice->i_slice_type = bs_read_ue( &s ); // slice type int i_pic_parameter_set_id = bs_read_ue( &s ); CurSlice->i_frame_num = bs_read( &s, StreamSps->log2_max_frame_num + 4 ); int i_field_pic_flag = 0; int i_bottom_field_flag = -1; if( !StreamSps->frame_mbs_only_flag) { /* field_pic_flag */ i_field_pic_flag = bs_read( &s, 1 ); if( i_field_pic_flag ) i_bottom_field_flag = bs_read( &s, 1 ); } int i_idr_pic_id; if( i_nal_type == 5/*NAL_SLICE_IDR*/ ) i_idr_pic_id = bs_read_ue( &s ); int i_delta_pic_order_cnt_bottom = -1; int i_delta_pic_order_cnt0 = 0; int i_delta_pic_order_cnt1 = 0; CurSlice->i_pic_order_cnt_lsb = 0; if( StreamSps->poc_type == 0 ) { CurSlice->i_pic_order_cnt_lsb = bs_read( &s, StreamSps->log2_max_poc_lsb + 4 ); //if( g_pic_order_present_flag && !i_field_pic_flag ) // i_delta_pic_order_cnt_bottom = bs_read_se( &s ); } else if( (StreamSps->poc_type == 1) && (!StreamSps->delta_pic_order_always_zero_flag) ) { i_delta_pic_order_cnt0 = bs_read_se( &s ); //if( g_pic_order_present_flag && !i_field_pic_flag ) // i_delta_pic_order_cnt1 = bs_read_se( &s ); } }