static int32_t getFPS( demux_t *p_demux, block_t * p_block ) { demux_sys_t *p_sys = p_demux->p_sys; bs_t bs; uint8_t * p_decoded_nal; int i_decoded_nal; if( p_block->i_buffer < 5 ) return -1; p_decoded_nal = CreateDecodedNAL(&i_decoded_nal, p_block->p_buffer+4, p_block->i_buffer-4); if( !p_decoded_nal ) return -1; bs_init( &bs, p_decoded_nal, i_decoded_nal ); bs_skip( &bs, 12 ); int32_t max_sub_layer_minus1 = bs_read( &bs, 3 ); bs_skip( &bs, 17 ); hevc_skip_profile_tiers_level( &bs, max_sub_layer_minus1 ); int32_t vps_sub_layer_ordering_info_present_flag = bs_read1( &bs ); int32_t i = vps_sub_layer_ordering_info_present_flag? 0 : max_sub_layer_minus1; for( ; i <= max_sub_layer_minus1; i++ ) { bs_read_ue( &bs ); bs_read_ue( &bs ); bs_read_ue( &bs ); } uint32_t vps_max_layer_id = bs_read( &bs, 6); uint32_t vps_num_layer_sets_minus1 = bs_read_ue( &bs ); bs_skip( &bs, vps_max_layer_id * vps_num_layer_sets_minus1 ); if( bs_read1( &bs )) { uint32_t num_units_in_tick = bs_read( &bs, 32 ); uint32_t time_scale = bs_read( &bs, 32 ); if( num_units_in_tick ) { p_sys->f_fps = ( (float) time_scale )/( (float) num_units_in_tick ); msg_Dbg(p_demux,"Using framerate %f fps from VPS", (double) p_sys->f_fps); } else { msg_Err( p_demux, "vps_num_units_in_tick null defaulting to 25 fps"); p_sys->f_fps = 25.0f; } } else { msg_Err( p_demux, "No timing info in VPS defaulting to 25 fps"); p_sys->f_fps = 25.0f; } free(p_decoded_nal); return 0; }
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 void ParseSei( decoder_t *p_dec, block_t *p_frag ) { decoder_sys_t *p_sys = p_dec->p_sys; uint8_t *pb_dec; int i_dec; /* */ CreateDecodedNAL( &pb_dec, &i_dec, &p_frag->p_buffer[5], p_frag->i_buffer - 5 ); if( !pb_dec ) return; /* The +1 is for rbsp trailing bits */ for( int i_used = 0; i_used+1 < i_dec; ) { /* Read type */ int i_type = 0; while( i_used+1 < i_dec ) { const int i_byte = pb_dec[i_used++]; i_type += i_byte; if( i_byte != 0xff ) break; } /* Read size */ int i_size = 0; while( i_used+1 < i_dec ) { const int i_byte = pb_dec[i_used++]; i_size += i_byte; if( i_byte != 0xff ) break; } /* Check room */ if( i_used + i_size + 1 > i_dec ) break; /* Look for user_data_registered_itu_t_t35 */ if( i_type == 4 ) { static const uint8_t p_dvb1_data_start_code[] = { 0xb5, 0x00, 0x31, 0x47, 0x41, 0x39, 0x34 }; const int i_t35 = i_size; const uint8_t *p_t35 = &pb_dec[i_used]; /* Check for we have DVB1_data() */ if( i_t35 >= 5 && !memcmp( p_t35, p_dvb1_data_start_code, sizeof(p_dvb1_data_start_code) ) ) { cc_Extract( &p_sys->cc_next, true, &p_t35[3], i_t35 - 3 ); } } /* Look for SEI recovery point */ if( i_type == 6 ) { bs_t s; const int i_rec = i_size; const uint8_t *p_rec = &pb_dec[i_used]; bs_init( &s, p_rec, i_rec ); int i_recovery_frames = bs_read_ue( &s ); //bool b_exact_match = bs_read( &s, 1 ); //bool b_broken_link = bs_read( &s, 1 ); //int i_changing_slice_group = bs_read( &s, 2 ); if( !p_sys->b_header ) { msg_Dbg( p_dec, "Seen SEI recovery point, %d recovery frames", i_recovery_frames ); if ( p_sys->i_recovery_frames == -1 || i_recovery_frames < p_sys->i_recovery_frames ) p_sys->i_recovery_frames = i_recovery_frames; } } i_used += i_size; } free( pb_dec ); }
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) ); CreateDecodedNAL( &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; }