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; }
/* MPLS */ void bd_mpls_stream_Parse( bd_mpls_stream_t *p_stream, bs_t *s, int i_class ) { /* Stream entry parsing */ const int i_entry_length = bs_read( s, 8 ); const int i_entry_start = bs_pos( s ) / 8; p_stream->i_type = bs_read( s, 8 ); p_stream->i_class = i_class; if( p_stream->i_type == BD_MPLS_STREAM_TYPE_PLAY_ITEM ) { p_stream->play_item.i_pid = bs_read( s, 16 ); } else if( p_stream->i_type == BD_MPLS_STREAM_TYPE_SUB_PATH ) { p_stream->sub_path.i_sub_path_id = bs_read( s, 8 ); p_stream->sub_path.i_sub_clip_id = bs_read( s, 8 ); p_stream->sub_path.i_pid = bs_read( s, 16 ); } else if( p_stream->i_type == BD_MPLS_STREAM_TYPE_IN_MUX_SUB_PATH ) { p_stream->in_mux_sub_path.i_sub_path_id = bs_read( s, 8 ); p_stream->in_mux_sub_path.i_pid = bs_read( s, 16 ); } bs_skip( s, 8 * ( i_entry_start + i_entry_length ) - bs_pos( s ) ); /* Stream attributes parsing */ const int i_attributes_length = bs_read( s, 8 ); const int i_attributes_start = bs_pos( s ) / 8; p_stream->i_stream_type = bs_read( s, 8 ); strcpy( p_stream->psz_language, "" ); p_stream->i_charset = -1; if( p_stream->i_stream_type == 0x02 || /* MPEG-I/II */ p_stream->i_stream_type == 0x1b || /* AVC */ p_stream->i_stream_type == 0xea ) /* VC-1 */ { /* Video */ } else if( ( p_stream->i_stream_type >= 0x80 && p_stream->i_stream_type <= 0x8f ) || ( p_stream->i_stream_type >= 0xa0 && p_stream->i_stream_type <= 0xaf ) ) { /* Audio */ bs_skip( s, 4 ); bs_skip( s, 4 ); for( int i = 0; i < 3; i++ ) p_stream->psz_language[i] = bs_read( s, 8 ); p_stream->psz_language[3] = '\0'; } else if( p_stream->i_stream_type == 0x90 || /* PG stream */ p_stream->i_stream_type == 0x91 ) /* IG stream */ { for( int i = 0; i < 3; i++ ) p_stream->psz_language[i] = bs_read( s, 8 ); p_stream->psz_language[3] = '\0'; } else if( p_stream->i_stream_type == 0x92 ) /* Text stream */ { p_stream->i_charset = bs_read( s, 8 ); for( int i = 0; i < 3; i++ ) p_stream->psz_language[i] = bs_read( s, 8 ); p_stream->psz_language[3] = '\0'; } bs_skip( s, 8 * ( i_attributes_start + i_attributes_length ) - bs_pos( s ) ); }
static int dirac_bool( bs_t *p_bs ) { return bs_read( p_bs, 1 ); }
void bd_mpls_play_item_Parse( bd_mpls_play_item_t *p_item, bs_t *s ) { const int i_length = bs_read( s, 16 ); const int i_start = bs_pos( s ) / 8; char psz_name[5+1]; for( int j = 0; j < 5; j++ ) psz_name[j] = bs_read( s, 8 ); psz_name[5] = '\0'; p_item->clpi.i_id = strtol( psz_name, NULL, 10 ); bs_skip( s, 32 ); bs_skip( s, 11 ); const bool b_angle = bs_read( s, 1 ); p_item->i_connection = bs_read( s, 4 ); p_item->clpi.i_stc_id = bs_read( s, 8 ); p_item->i_in_time = bs_read( s, 32 ); p_item->i_out_time = bs_read( s, 32 ); bs_skip( s, 64 ); bs_skip( s, 1 ); bs_skip( s, 7 ); p_item->i_still = bs_read( s, 8 ); p_item->i_still_time = bs_read( s, 16 ); if( p_item->i_still == BD_MPLS_PLAY_ITEM_STILL_NONE ) p_item->i_still_time = 0; else if( p_item->i_still == BD_MPLS_PLAY_ITEM_STILL_INFINITE ) p_item->i_still_time = INT_MAX; if( b_angle ) { const int i_angle = bs_read( s, 8 ); bs_skip( s, 6 ); p_item->b_angle_different_audio = bs_read( s, 1 ); p_item->b_angle_seamless = bs_read( s, 1 ); p_item->p_clpi = calloc( i_angle, sizeof(*p_item->p_clpi) ); for( p_item->i_clpi = 0; p_item->i_clpi < i_angle; p_item->i_clpi++ ) { if( !p_item->p_clpi ) break; bd_mpls_clpi_t *p_clpi = &p_item->p_clpi[p_item->i_clpi]; char psz_name[5+1]; for( int j = 0; j < 5; j++ ) psz_name[j] = bs_read( s, 8 ); psz_name[5] = '\0'; p_clpi->i_id = strtol( psz_name, NULL, 10 ); bs_skip( s, 32 ); p_clpi->i_stc_id = bs_read( s, 8 ); } } else { p_item->i_clpi = 0; p_item->p_clpi = NULL; p_item->b_angle_different_audio = false; p_item->b_angle_seamless = true; } /* STN Table */ bs_skip( s, 16 ); /* Length */ bs_skip( s, 16 ); const int i_video = bs_read( s, 8 ); const int i_audio = bs_read( s, 8 ); const int i_pg = bs_read( s, 8 ); const int i_ig = bs_read( s, 8 ); const int i_audio_2 = bs_read( s, 8 ); const int i_video_2 = bs_read( s, 8 ); const int i_pip_pg = bs_read( s, 8 ); bs_skip( s, 40 ); p_item->i_stream = 0; p_item->p_stream = calloc( i_video + i_audio + i_pg + i_ig, sizeof(*p_item->p_stream) ); for( int j = 0; j < i_video; j++, p_item->i_stream++ ) { if( !p_item->p_stream ) break; bd_mpls_stream_Parse( &p_item->p_stream[p_item->i_stream], s, BD_MPLS_STREAM_CLASS_PRIMARY_VIDEO ); } for( int j = 0; j < i_audio; j++, p_item->i_stream++ ) { if( !p_item->p_stream ) break; bd_mpls_stream_Parse( &p_item->p_stream[p_item->i_stream], s, BD_MPLS_STREAM_CLASS_PRIMARY_AUDIO ); } for( int j = 0; j < i_pg; j++, p_item->i_stream++ ) { if( !p_item->p_stream ) break; bd_mpls_stream_Parse( &p_item->p_stream[p_item->i_stream], s, BD_MPLS_STREAM_CLASS_PG ); } for( int j = 0; j < i_ig; j++, p_item->i_stream++ ) { if( !p_item->p_stream ) break; bd_mpls_stream_Parse( &p_item->p_stream[p_item->i_stream], s, BD_MPLS_STREAM_CLASS_IG ); } for( int j = 0; j < i_audio_2; j++ ) { /* TODO I need samples */ } for( int j = 0; j < i_video_2; j++ ) { /* TODO I need samples */ } for( int j = 0; j < i_pip_pg; j++ ) { /* TODO I need samples */ } bs_skip( s, 8 * ( i_start + i_length ) - bs_pos( s ) ); }
int bd_mpls_Parse( bd_mpls_t *p_mpls, bs_t *s, int i_id ) { const int i_start = bs_pos( s ) / 8; /* */ if( bs_read( s, 32 ) != 0x4d504c53 ) return VLC_EGENERIC; const uint32_t i_version = bs_read( s, 32 ); if( i_version != 0x30313030 && i_version != 0x30323030 ) return VLC_EGENERIC; const uint32_t i_play_item_start = bs_read( s, 32 ); const uint32_t i_mark_start = bs_read( s, 32 ); bs_skip( s, 32 ); /* Extension start */ /* */ p_mpls->i_id = i_id; /* Read AppInfo: ignored */ /* Read Playlist */ bs_t ps = *s; bs_skip( &ps, 8 * ( i_start + i_play_item_start ) - bs_pos( s ) ); bs_skip( &ps, 32 ); /* Length */ bs_skip( &ps, 16 ); const int i_play_item = bs_read( &ps, 16 ); const int i_sub_path = bs_read( &ps, 16 ); p_mpls->p_play_item = calloc( i_play_item, sizeof(*p_mpls->p_play_item) ); for( p_mpls->i_play_item = 0; p_mpls->i_play_item < i_play_item; p_mpls->i_play_item++ ) { if( !p_mpls->p_play_item ) break; bd_mpls_play_item_t *p_item = &p_mpls->p_play_item[p_mpls->i_play_item]; bd_mpls_play_item_Parse( p_item, &ps ); } p_mpls->p_sub_path = calloc( i_sub_path, sizeof(*p_mpls->p_sub_path) ); for( p_mpls->i_sub_path = 0; p_mpls->i_sub_path < i_sub_path; p_mpls->i_sub_path++ ) { if( !p_mpls->p_sub_path ) break; bd_mpls_sub_path_t *p_sub = &p_mpls->p_sub_path[p_mpls->i_sub_path]; bd_mpls_sub_path_Parse( p_sub, &ps ); } /* Read Mark */ bs_t ms = *s; bs_skip( &ms, 8 * ( i_start + i_mark_start ) - bs_pos( s ) ); bs_skip( &ms, 32 ); const int i_mark = bs_read( &ms, 16 ); p_mpls->p_mark = calloc( i_mark, sizeof(*p_mpls->p_mark) ); for( p_mpls->i_mark = 0; p_mpls->i_mark < i_mark; p_mpls->i_mark++ ) { if( !p_mpls->p_mark ) break; bd_mpls_mark_t *p_mark = &p_mpls->p_mark[p_mpls->i_mark]; bd_mpls_mark_Parse( p_mark, &ms ); } /* Read Extension: ignored */ return VLC_SUCCESS; }
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 pic timing */ if( i_type == SEI_PIC_TIMING ) { bs_t s; const int i_tim = i_size; const uint8_t *p_tim = &pb_dec[i_used]; bs_init( &s, p_tim, i_tim ); if( p_sys->b_cpb_dpb_delays_present_flag ) { bs_read( &s, p_sys->i_cpb_removal_delay_length_minus1 + 1 ); bs_read( &s, p_sys->i_dpb_output_delay_length_minus1 + 1 ); } if( p_sys->b_pic_struct_present_flag ) p_sys->i_pic_struct = bs_read( &s, 4 ); /* + unparsed remains */ } /* Look for user_data_registered_itu_t_t35 */ if( i_type == SEI_USER_DATA_REGISTERED ) { 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 == SEI_RECOVERY_POINT ) { 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 ); }
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 == 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_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; } } /* 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_sys->b_timing_info_present_flag = bs_read( &s, 1 ); if( p_sys->b_timing_info_present_flag ) { p_sys->i_num_units_in_tick = bs_read( &s, 32 ); p_sys->i_time_scale = bs_read( &s, 32 ); p_sys->b_fixed_frame_rate = bs_read( &s, 1 ); } /* Nal hrd & VC1 hrd parameters */ p_sys->b_cpb_dpb_delays_present_flag = false; for ( int i=0; i<2; i++ ) { i_tmp = bs_read( &s, 1 ); if( i_tmp ) { p_sys->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_sys->i_cpb_removal_delay_length_minus1 = bs_read( &s, 5 ); p_sys->i_dpb_output_delay_length_minus1 = bs_read( &s, 5 ); bs_read( &s, 5 ); } } if( p_sys->b_cpb_dpb_delays_present_flag ) bs_read( &s, 1 ); /* pic struct info */ p_sys->b_pic_struct_present_flag = bs_read( &s, 1 ); /* + unparsed remains */ } 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; }
int bd_clpi_ep_map_Parse( bd_clpi_ep_map_t *p_ep_map, bs_t *s, const int i_ep_map_start ) { p_ep_map->i_pid = bs_read( s, 16 ); bs_skip( s, 10 ); p_ep_map->i_type = bs_read( s, 4 ); const int i_coarse = bs_read( s, 16 ); const int i_fine = bs_read( s, 18 ); const uint32_t i_coarse_start = bs_read( s, 32 ); p_ep_map->i_ep = i_fine; p_ep_map->p_ep = (bd_clpi_ep_t *)calloc( i_fine, sizeof(*p_ep_map->p_ep) ); // sunqueen modify if( !p_ep_map->p_ep ) return VLC_EGENERIC; bs_t cs = *s; bs_skip( &cs, 8*(i_ep_map_start + i_coarse_start) - bs_pos( s ) ); const uint32_t i_fine_start = bs_read( &cs, 32 ); for( int i = 0; i < i_coarse; i++ ) { const int i_fine_id = bs_read( &cs, 18 ); const int i_pts = bs_read( &cs, 14 ); const uint32_t i_packet = bs_read( &cs, 32 ); for( int j = i_fine_id; j < p_ep_map->i_ep; j++ ) { p_ep_map->p_ep[j].i_pts = (int64_t)(i_pts & ~1) << 19; p_ep_map->p_ep[j].i_packet = i_packet & ~( (1 << 17) - 1 ); } } bs_t fs = *s; bs_skip( &fs, 8*(i_ep_map_start + i_coarse_start + i_fine_start) - bs_pos( s ) ); for( int i = 0; i < i_fine; i++ ) { const bool b_angle_point = bs_read( &fs, 1 ); bs_skip( &fs, 3 ); /* I end position offset */ const int i_pts = bs_read( &fs, 11 ); const int i_packet = bs_read( &fs, 17 ); p_ep_map->p_ep[i].b_angle_point = b_angle_point; p_ep_map->p_ep[i].i_pts |= i_pts << 9; p_ep_map->p_ep[i].i_packet |= i_packet; } return VLC_SUCCESS; }
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; }
int bd_clpi_Parse( bd_clpi_t *p_clpi, bs_t *s, int i_id ) { const int i_start = bs_pos( s ) / 8; /* */ if( bs_read( s, 32 ) != 0x48444D56 ) return VLC_EGENERIC; const uint32_t i_version = bs_read( s, 32 ); if( i_version != 0x30313030 && i_version != 0x30323030 ) return VLC_EGENERIC; /* */ const uint32_t i_sequence_start = bs_read( s, 32 ); const uint32_t i_program_start = bs_read( s, 32 ); const uint32_t i_cpi_start = bs_read( s, 32 ); bs_skip( s, 32 ); /* mark start */ bs_skip( s, 32 ); /* extension start */ /* */ p_clpi->i_id = i_id; /* Read sequence */ bs_t ss = *s; bs_skip( &ss, 8 * ( i_start + i_sequence_start ) - bs_pos( s ) ); bs_skip( &ss, 32 ); /* Length */ bs_skip( &ss, 8 ); bs_skip( &ss, 8 ); /* ATC sequence count (MUST be 1 ?) */ bs_skip( &ss, 32 ); /* ATC start (MUST be 0) */ const int i_stc = bs_read( &ss, 8 ); bs_skip( &ss, 8 ); /* STC ID offset (MUST be 0 ? */ p_clpi->p_stc = (bd_clpi_stc_t *)calloc( i_stc, sizeof(*p_clpi->p_stc) ); // sunqueen modify for( p_clpi->i_stc = 0; p_clpi->i_stc < i_stc; p_clpi->i_stc++ ) { if( !p_clpi->p_stc ) break; bd_clpi_stc_Parse( &p_clpi->p_stc[p_clpi->i_stc], &ss ); } /* Program */ bs_t ps = *s; bs_skip( &ps, 8 * ( i_start + i_program_start ) - bs_pos( s ) ); bs_skip( &ps, 32 ); /* Length */ bs_skip( &ps, 8 ); bs_skip( &ps, 8 ); /* Program count (MUST be 1 ?) */ bs_skip( &ps, 32 ); /* Program sequence start (MUST be 0) */ p_clpi->i_pmt_pid = bs_read( &ps, 16 ); const int i_stream = bs_read( &ps, 8 ); bs_skip( &ps, 8 ); /* Group count (MUST be 1 ?) */ p_clpi->p_stream = (bd_clpi_stream_t *)calloc( i_stream, sizeof(*p_clpi->p_stream) ); // sunqueen modify for( p_clpi->i_stream = 0; p_clpi->i_stream < i_stream; p_clpi->i_stream++ ) { if( !p_clpi->p_stream ) break; bd_clpi_stream_Parse( &p_clpi->p_stream[p_clpi->i_stream], &ps ); } /* Read CPI */ bs_t cs = *s; bs_skip( &cs, 8 * ( i_start + i_cpi_start ) - bs_pos( s ) ); const uint32_t i_cpi_length = bs_read( &cs, 32 ); if( i_cpi_length > 0 ) { bs_skip( &cs, 12 ); bs_skip( &cs, 4 ); /* Type (MUST be 1) */ /* EPMap */ const int i_epmap_start = bs_pos( &cs ) / 8; bs_skip( &cs, 8 ); const int i_ep_map = bs_read( &cs, 8 ); p_clpi->p_ep_map = (bd_clpi_ep_map_t *)calloc( i_ep_map, sizeof(*p_clpi->p_ep_map) ); // sunqueen modify for( p_clpi->i_ep_map = 0; p_clpi->i_ep_map < i_ep_map; p_clpi->i_ep_map++ ) { if( !p_clpi->p_ep_map ) break; if( bd_clpi_ep_map_Parse( &p_clpi->p_ep_map[p_clpi->i_ep_map], &cs, i_epmap_start ) ) break; } } else { p_clpi->i_ep_map = 0; p_clpi->p_ep_map = NULL; } return VLC_SUCCESS; }
/* ParseIDU: parse an Independent Decoding Unit */ static block_t *ParseIDU( decoder_t *p_dec, bool *pb_used_ts, block_t *p_frag ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_pic; const idu_type_t idu = p_frag->p_buffer[3]; *pb_used_ts = false; if( !p_sys->b_sequence_header && idu != IDU_TYPE_SEQUENCE_HEADER ) { msg_Warn( p_dec, "waiting for sequence header" ); block_Release( p_frag ); return NULL; } if( p_sys->b_sequence_header && !p_sys->b_entry_point && idu != IDU_TYPE_ENTRY_POINT ) { msg_Warn( p_dec, "waiting for entry point" ); block_Release( p_frag ); return NULL; } /* TODO we do not gather ENTRY_POINT and SEQUENCE_DATA user data * But It should not be a problem for decoder */ /* Do we have completed a frame */ p_pic = NULL; if( p_sys->b_frame && idu != IDU_TYPE_FRAME_USER_DATA && idu != IDU_TYPE_FIELD && idu != IDU_TYPE_FIELD_USER_DATA && idu != IDU_TYPE_SLICE && idu != IDU_TYPE_SLICE_USER_DATA && idu != IDU_TYPE_END_OF_SEQUENCE ) { /* Prepend SH and EP on I */ if( p_sys->p_frame->i_flags & BLOCK_FLAG_TYPE_I ) { block_t *p_list = block_Duplicate( p_sys->sh.p_sh ); block_ChainAppend( &p_list, block_Duplicate( p_sys->ep.p_ep ) ); block_ChainAppend( &p_list, p_sys->p_frame ); p_list->i_flags = p_sys->p_frame->i_flags; p_sys->p_frame = p_list; } /* */ p_pic = block_ChainGather( p_sys->p_frame ); p_pic->i_dts = p_sys->i_frame_dts; p_pic->i_pts = p_sys->i_frame_pts; /* */ if( p_pic->i_dts > VLC_TS_INVALID ) p_sys->i_interpolated_dts = p_pic->i_dts; /* We can interpolate dts/pts only if we have a frame rate */ if( p_dec->fmt_out.video.i_frame_rate != 0 && p_dec->fmt_out.video.i_frame_rate_base != 0 ) { if( p_sys->i_interpolated_dts > VLC_TS_INVALID ) p_sys->i_interpolated_dts += INT64_C(1000000) * p_dec->fmt_out.video.i_frame_rate_base / p_dec->fmt_out.video.i_frame_rate; //msg_Dbg( p_dec, "-------------- XXX0 dts=%"PRId64" pts=%"PRId64" interpolated=%"PRId64, // p_pic->i_dts, p_pic->i_pts, p_sys->i_interpolated_dts ); if( p_pic->i_dts <= VLC_TS_INVALID ) p_pic->i_dts = p_sys->i_interpolated_dts; if( p_pic->i_pts <= VLC_TS_INVALID ) { if( !p_sys->sh.b_has_bframe || (p_pic->i_flags & BLOCK_FLAG_TYPE_B ) ) p_pic->i_pts = p_pic->i_dts; /* TODO compute pts for other case */ } } //msg_Dbg( p_dec, "-------------- dts=%"PRId64" pts=%"PRId64, p_pic->i_dts, p_pic->i_pts ); /* Reset context */ p_sys->b_frame = false; p_sys->i_frame_dts = VLC_TS_INVALID; p_sys->i_frame_pts = VLC_TS_INVALID; p_sys->p_frame = NULL; p_sys->pp_last = &p_sys->p_frame; } /* */ if( p_sys->i_frame_dts <= VLC_TS_INVALID && p_sys->i_frame_pts <= VLC_TS_INVALID ) { p_sys->i_frame_dts = p_frag->i_dts; p_sys->i_frame_pts = p_frag->i_pts; *pb_used_ts = true; } /* We will add back SH and EP on I frames */ block_t *p_release = NULL; if( idu != IDU_TYPE_SEQUENCE_HEADER && idu != IDU_TYPE_ENTRY_POINT ) block_ChainLastAppend( &p_sys->pp_last, p_frag ); else p_release = p_frag; /* Parse IDU */ if( idu == IDU_TYPE_SEQUENCE_HEADER ) { es_format_t *p_es = &p_dec->fmt_out; bs_t s; int i_profile; uint8_t ridu[32]; int i_ridu = sizeof(ridu); /* */ if( p_sys->sh.p_sh ) block_Release( p_sys->sh.p_sh ); p_sys->sh.p_sh = block_Duplicate( p_frag ); /* Extract the raw IDU */ DecodeRIDU( ridu, &i_ridu, &p_frag->p_buffer[4], p_frag->i_buffer - 4 ); /* Auto detect VC-1_SPMP_PESpacket_PayloadFormatHeader (SMPTE RP 227) for simple/main profile * TODO find a test case and valid it */ if( i_ridu > 4 && (ridu[0]&0x80) == 0 ) /* for advanced profile, the first bit is 1 */ { video_format_t *p_v = &p_dec->fmt_in.video; const size_t i_potential_width = GetWBE( &ridu[0] ); const size_t i_potential_height = GetWBE( &ridu[2] ); if( i_potential_width >= 2 && i_potential_width <= 8192 && i_potential_height >= 2 && i_potential_height <= 8192 ) { if( ( p_v->i_width <= 0 && p_v->i_height <= 0 ) || ( p_v->i_width == i_potential_width && p_v->i_height == i_potential_height ) ) { static const uint8_t startcode[4] = { 0x00, 0x00, 0x01, IDU_TYPE_SEQUENCE_HEADER }; p_es->video.i_width = i_potential_width; p_es->video.i_height = i_potential_height; /* Remove it */ p_frag->p_buffer += 4; p_frag->i_buffer -= 4; memcpy( p_frag->p_buffer, startcode, sizeof(startcode) ); } } } /* Parse it */ bs_init( &s, ridu, i_ridu ); i_profile = bs_read( &s, 2 ); if( i_profile == 3 ) { const int i_level = bs_read( &s, 3 ); /* Advanced profile */ p_sys->sh.b_advanced_profile = true; p_sys->sh.b_range_reduction = false; p_sys->sh.b_has_bframe = true; bs_skip( &s, 2+3+5+1 ); // chroma format + frame rate Q + bit rate Q + postprocflag p_es->video.i_width = 2*bs_read( &s, 12 )+2; p_es->video.i_height = 2*bs_read( &s, 12 )+2; if( !p_sys->b_sequence_header ) msg_Dbg( p_dec, "found sequence header for advanced profile level L%d resolution %dx%d", i_level, p_es->video.i_width, p_es->video.i_height); bs_skip( &s, 1 );// pulldown p_sys->sh.b_interlaced = bs_read( &s, 1 ); bs_skip( &s, 1 );// frame counter p_sys->sh.b_frame_interpolation = bs_read( &s, 1 ); bs_skip( &s, 1 ); // Reserved bs_skip( &s, 1 ); // Psf if( bs_read( &s, 1 ) ) /* Display extension */ { const int i_display_width = bs_read( &s, 14 )+1; const int i_display_height = bs_read( &s, 14 )+1; p_es->video.i_aspect = VOUT_ASPECT_FACTOR * i_display_width / i_display_height; if( !p_sys->b_sequence_header ) msg_Dbg( p_dec, "display size %dx%d", i_display_width, i_display_height ); if( bs_read( &s, 1 ) ) /* Pixel aspect ratio (PAR/SAR) */ { static const int p_ar[16][2] = { { 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},{ 0, 0}, { 0, 0} }; int i_ar = bs_read( &s, 4 ); unsigned i_ar_w, i_ar_h; if( i_ar == 15 ) { i_ar_w = bs_read( &s, 8 ); i_ar_h = bs_read( &s, 8 ); } else { i_ar_w = p_ar[i_ar][0]; i_ar_h = p_ar[i_ar][1]; } vlc_ureduce( &i_ar_w, &i_ar_h, i_ar_w, i_ar_h, 0 ); if( !p_sys->b_sequence_header ) msg_Dbg( p_dec, "aspect ratio %d:%d", i_ar_w, i_ar_h ); } } if( bs_read( &s, 1 ) ) /* Frame rate */ { int i_fps_num = 0; int i_fps_den = 0; if( bs_read( &s, 1 ) ) { i_fps_num = bs_read( &s, 16 )+1; i_fps_den = 32; } else { const int i_nr = bs_read( &s, 8 ); const int i_dn = bs_read( &s, 4 ); switch( i_nr ) { case 1: i_fps_num = 24000; break; case 2: i_fps_num = 25000; break; case 3: i_fps_num = 30000; break; case 4: i_fps_num = 50000; break; case 5: i_fps_num = 60000; break; case 6: i_fps_num = 48000; break; case 7: i_fps_num = 72000; break; } switch( i_dn ) { case 1: i_fps_den = 1000; break; case 2: i_fps_den = 1001; break; } } if( i_fps_num != 0 && i_fps_den != 0 ) vlc_ureduce( &p_es->video.i_frame_rate, &p_es->video.i_frame_rate_base, i_fps_num, i_fps_den, 0 ); if( !p_sys->b_sequence_header ) msg_Dbg( p_dec, "frame rate %d/%d", p_es->video.i_frame_rate, p_es->video.i_frame_rate_base ); } } else { /* Simple and main profile */ p_sys->sh.b_advanced_profile = false; p_sys->sh.b_interlaced = false; if( !p_sys->b_sequence_header ) msg_Dbg( p_dec, "found sequence header for %s profile", i_profile == 0 ? "simple" : "main" ); bs_skip( &s, 2+3+5+1+1+ // reserved + frame rate Q + bit rate Q + loop filter + reserved 1+1+1+1+2+ // multiresolution + reserved + fast uv mc + extended mv + dquant 1+1+1+1 ); // variable size transform + reserved + overlap + sync marker p_sys->sh.b_range_reduction = bs_read( &s, 1 ); if( bs_read( &s, 3 ) > 0 ) p_sys->sh.b_has_bframe = true; else p_sys->sh.b_has_bframe = false; bs_skip( &s, 2 ); // quantizer p_sys->sh.b_frame_interpolation = bs_read( &s, 1 ); } p_sys->b_sequence_header = true; BuildExtraData( p_dec ); } else if( idu == IDU_TYPE_ENTRY_POINT ) { if( p_sys->ep.p_ep ) block_Release( p_sys->ep.p_ep ); p_sys->ep.p_ep = block_Duplicate( p_frag ); if( !p_sys->b_entry_point ) msg_Dbg( p_dec, "found entry point" ); p_sys->b_entry_point = true; BuildExtraData( p_dec ); } else if( idu == IDU_TYPE_FRAME ) { bs_t s; uint8_t ridu[8]; int i_ridu = sizeof(ridu); /* Extract the raw IDU */ DecodeRIDU( ridu, &i_ridu, &p_frag->p_buffer[4], p_frag->i_buffer - 4 ); /* Parse it + interpolate pts/dts if possible */ bs_init( &s, ridu, i_ridu ); if( p_sys->sh.b_advanced_profile ) { int i_fcm = 0; if( p_sys->sh.b_interlaced ) { if( bs_read( &s, 1 ) ) { if( bs_read( &s, 1 ) ) i_fcm = 1; /* interlaced field */ else i_fcm = 2; /* interlaced frame */ } } if( i_fcm == 1 ) /*interlaced field */ { /* XXX for mixed I/P we should check reference usage before marking them I (too much work) */ switch( bs_read( &s, 3 ) ) { case 0: /* II */ case 1: /* IP */ case 2: /* PI */ p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I; p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I; p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I; break; case 3: /* PP */ p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P; break; case 4: /* BB */ case 5: /* BBi */ case 6: /* BiB */ case 7: /* BiBi */ p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B; break; } } else { if( !bs_read( &s, 1 ) ) p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P; else if( !bs_read( &s, 1 ) ) p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B; else if( !bs_read( &s, 1 ) ) p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I; else if( !bs_read( &s, 1 ) ) p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B; /* Bi */ else p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P; /* P Skip */ } } else { if( p_sys->sh.b_frame_interpolation ) bs_skip( &s, 1 ); // interpolate bs_skip( &s, 2 ); // frame count if( p_sys->sh.b_range_reduction ) bs_skip( &s, 1 ); // range reduction if( bs_read( &s, 1 ) ) p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_P; else if( !p_sys->sh.b_has_bframe || bs_read( &s, 1 ) ) p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_I; else p_sys->p_frame->i_flags |= BLOCK_FLAG_TYPE_B; } p_sys->b_frame = true; } if( p_release ) block_Release( p_release ); 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 ); } }
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_profile_compatibility = bs_read( p_bs, 8 ); p_sps->i_level = bs_read( p_bs, 8 ); /* sps id */ p_sps->i_id = bs_read_ue( p_bs ); if( p_sps->i_id >= H264_SPS_MAX ) return false; 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 */ const int i_chroma_format_idc = bs_read_ue( p_bs ); if( i_chroma_format_idc == 3 ) bs_skip( p_bs, 1 ); /* separate_colour_plane_flag */ /* bit_depth_luma_minus8 */ bs_read_ue( p_bs ); /* bit_depth_chroma_minus8 */ bs_read_ue( p_bs ); /* 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 != i_chroma_format_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, 4 ); /* colour desc */ bs_read( p_bs, 1 ); if ( i_tmp ) bs_read( p_bs, 24 ); } /* 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_cpb_dpb_delays_present_flag = false; for ( int i=0; i<2; i++ ) { i_tmp = bs_read( p_bs, 1 ); if( i_tmp ) { p_sps->vui.b_cpb_dpb_delays_present_flag = true; uint32_t count = bs_read_ue( p_bs ) + 1; bs_read( p_bs, 4 ); bs_read( p_bs, 4 ); for( uint32_t i=0; i<count; i++ ) { 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_cpb_dpb_delays_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; }