vlc | branch: master | Francois Cartegnie <[email protected]> | Sat Dec 12 16:39:47 2015 +0100| [2db2212b615f595fb9cd082a7f05804935479161] | committer: Francois Cartegnie
hevc_nal: add picture_parameter_set parser > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=2db2212b615f595fb9cd082a7f05804935479161 --- modules/packetizer/hevc_nal.c | 202 +++++++++++++++++++++++++++++++++++++++++ modules/packetizer/hevc_nal.h | 3 + 2 files changed, 205 insertions(+) diff --git a/modules/packetizer/hevc_nal.c b/modules/packetizer/hevc_nal.c index 8300c96..5b83fc8 100644 --- a/modules/packetizer/hevc_nal.c +++ b/modules/packetizer/hevc_nal.c @@ -120,6 +120,64 @@ struct hevc_sequence_parameter_set_t /* incomplete */ }; +struct hevc_picture_parameter_set_t +{ + nal_ue_t pps_pic_parameter_set_id; + nal_ue_t pps_seq_parameter_set_id; + nal_u1_t dependent_slice_segments_enabled_flag; + nal_u1_t output_flag_present_flag; + nal_u3_t num_extra_slice_header_bits; + nal_u1_t sign_data_hiding_enabled_flag; + nal_u1_t cabac_init_present_flag; + nal_ue_t num_ref_idx_l0_default_active_minus1; + nal_ue_t num_ref_idx_l1_default_active_minus1; + nal_se_t init_qp_minus26; + nal_u1_t constrained_intra_pred_flag; + nal_u1_t transform_skip_enabled_flag; + + nal_u1_t cu_qp_delta_enabled_flag; + nal_ue_t diff_cu_qp_delta_depth; + + nal_se_t pps_cb_qp_offset; + nal_se_t pps_cr_qp_offset; + nal_u1_t pic_slice_level_chroma_qp_offsets_present_flag; + nal_u1_t weighted_pred_flag; + nal_u1_t weighted_bipred_flag; + nal_u1_t transquant_bypass_enable_flag; + + nal_u1_t tiles_enabled_flag; + nal_u1_t entropy_coding_sync_enabled_flag; + nal_ue_t num_tile_columns_minus1; + nal_ue_t num_tile_rows_minus1; + nal_u1_t uniform_spacing_flag; + // nal_ue_t *p_column_width_minus1; read but discarded + // nal_ue_t *p_row_height_minus1; read but discarded + nal_u1_t loop_filter_across_tiles_enabled_flag; + + nal_u1_t pps_loop_filter_across_slices_enabled_flag; + + nal_u1_t deblocking_filter_control_present_flag; + nal_u1_t deblocking_filter_override_enabled_flag; + nal_u1_t pps_deblocking_filter_disabled_flag; + nal_se_t pps_beta_offset_div2; + nal_se_t pps_tc_offset_div2; + + nal_u1_t scaling_list_data_present_flag; + // scaling_list_data; read but discarded + + nal_u1_t lists_modification_present_flag; + nal_ue_t log2_parallel_merge_level_minus2; + nal_u1_t slice_header_extension_present_flag; + + nal_u1_t pps_extension_present_flag; + nal_u1_t pps_range_extension_flag; + nal_u1_t pps_multilayer_extension_flag; + nal_u1_t pps_3d_extension_flag; + nal_u5_t pps_extension_5bits; + /* incomplete */ + +}; + /* Computes size and does check the whole struct integrity */ static size_t get_hvcC_to_AnnexB_NAL_size( const uint8_t *p_buf, size_t i_buf ) { @@ -202,6 +260,36 @@ uint8_t * hevc_hvcC_to_AnnexB_NAL( const uint8_t *p_buf, size_t i_buf, return p_ret; } +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; +} + static bool hevc_parse_inner_profile_tier_level_rbsp( bs_t *p_bs, hevc_inner_profile_tier_level_t *p_in ) { @@ -376,3 +464,117 @@ hevc_sequence_parameter_set_t * hevc_rbsp_decode_sps( const uint8_t *p_buf, size } return p_sps; } + +static bool hevc_parse_pic_parameter_set_rbsp( bs_t *p_bs, + hevc_picture_parameter_set_t *p_pps ) +{ + if( bs_remain( p_bs ) < 1 ) + return false; + p_pps->pps_pic_parameter_set_id = bs_read_ue( p_bs ); + if( p_pps->pps_pic_parameter_set_id >= HEVC_PPS_MAX || bs_remain( p_bs ) < 1 ) + return false; + p_pps->pps_seq_parameter_set_id = bs_read_ue( p_bs ); + if( p_pps->pps_seq_parameter_set_id >= HEVC_SPS_MAX ) + return false; + p_pps->dependent_slice_segments_enabled_flag = bs_read1( p_bs ); + p_pps->output_flag_present_flag = bs_read1( p_bs ); + p_pps->num_extra_slice_header_bits = bs_read( p_bs, 3 ); + p_pps->sign_data_hiding_enabled_flag = bs_read1( p_bs ); + p_pps->cabac_init_present_flag = bs_read1( p_bs ); + + p_pps->num_ref_idx_l0_default_active_minus1 = bs_read_ue( p_bs ); + p_pps->num_ref_idx_l1_default_active_minus1 = bs_read_ue( p_bs ); + + p_pps->init_qp_minus26 = bs_read_se( p_bs ); + p_pps->constrained_intra_pred_flag = bs_read1( p_bs ); + p_pps->transform_skip_enabled_flag = bs_read1( p_bs ); + p_pps->cu_qp_delta_enabled_flag = bs_read1( p_bs ); + if( p_pps->cu_qp_delta_enabled_flag ) + p_pps->diff_cu_qp_delta_depth = bs_read_ue( p_bs ); + + if( bs_remain( p_bs ) < 1 ) + return false; + + p_pps->pps_cb_qp_offset = bs_read_se( p_bs ); + p_pps->pps_cr_qp_offset = bs_read_se( p_bs ); + p_pps->pic_slice_level_chroma_qp_offsets_present_flag = bs_read1( p_bs ); + p_pps->weighted_pred_flag = bs_read1( p_bs ); + p_pps->weighted_bipred_flag = bs_read1( p_bs ); + p_pps->transquant_bypass_enable_flag = bs_read1( p_bs ); + p_pps->tiles_enabled_flag = bs_read1( p_bs ); + p_pps->entropy_coding_sync_enabled_flag = bs_read1( p_bs ); + + if( p_pps->tiles_enabled_flag ) + { + p_pps->num_tile_columns_minus1 = bs_read_ue( p_bs ); /* TODO: validate max col/row values */ + p_pps->num_tile_rows_minus1 = bs_read_ue( p_bs ); /* against sps PicWidthInCtbsY */ + p_pps->uniform_spacing_flag = bs_read1( p_bs ); + if( !p_pps->uniform_spacing_flag ) + { + for( unsigned i=0; i< p_pps->num_tile_columns_minus1; i++ ) + (void) bs_read_ue( p_bs ); + for( unsigned i=0; i< p_pps->num_tile_rows_minus1; i++ ) + (void) bs_read_ue( p_bs ); + } + p_pps->loop_filter_across_tiles_enabled_flag = bs_read1( p_bs ); + } + + p_pps->pps_loop_filter_across_slices_enabled_flag = bs_read1( p_bs ); + p_pps->deblocking_filter_control_present_flag = bs_read1( p_bs ); + if( p_pps->deblocking_filter_control_present_flag ) + { + p_pps->deblocking_filter_override_enabled_flag = bs_read1( p_bs ); + p_pps->pps_deblocking_filter_disabled_flag = bs_read1( p_bs ); + if( !p_pps->pps_deblocking_filter_disabled_flag ) + { + p_pps->pps_beta_offset_div2 = bs_read_se( p_bs ); + p_pps->pps_tc_offset_div2 = bs_read_se( p_bs ); + } + } + + p_pps->scaling_list_data_present_flag = bs_read1( p_bs ); + if( p_pps->scaling_list_data_present_flag && !hevc_parse_scaling_list_rbsp( p_bs ) ) + return false; + + p_pps->lists_modification_present_flag = bs_read1( p_bs ); + p_pps->log2_parallel_merge_level_minus2 = bs_read_ue( p_bs ); + p_pps->slice_header_extension_present_flag = bs_read1( p_bs ); + + if( bs_remain( p_bs ) < 1 ) + return false; + + p_pps->pps_extension_present_flag = bs_read1( p_bs ); + if( p_pps->pps_extension_present_flag ) + { + p_pps->pps_range_extension_flag = bs_read1( p_bs ); + p_pps->pps_multilayer_extension_flag = bs_read1( p_bs ); + p_pps->pps_3d_extension_flag = bs_read1( p_bs ); + if( bs_remain( p_bs ) < 5 ) + return false; + p_pps->pps_extension_5bits = bs_read( p_bs, 5 ); + } + + return true; +} + +void hevc_rbsp_release_pps( hevc_picture_parameter_set_t *p_pps ) +{ + free( p_pps ); +} + +hevc_picture_parameter_set_t * hevc_rbsp_decode_pps( const uint8_t *p_buf, size_t i_buf ) +{ + hevc_picture_parameter_set_t *p_pps = calloc(1, sizeof(hevc_picture_parameter_set_t)); + if(likely(p_pps)) + { + bs_t bs; + bs_init( &bs, p_buf, i_buf ); + bs_skip( &bs, 16 ); /* Skip nal_unit_header */ + if( !hevc_parse_pic_parameter_set_rbsp( &bs, p_pps ) ) + { + hevc_rbsp_release_pps( p_pps ); + p_pps = NULL; + } + } + return p_pps; +} diff --git a/modules/packetizer/hevc_nal.h b/modules/packetizer/hevc_nal.h index f4da751..8f91653 100644 --- a/modules/packetizer/hevc_nal.h +++ b/modules/packetizer/hevc_nal.h @@ -130,10 +130,13 @@ static inline bool hevc_ishvcC( const uint8_t *p_buf, size_t i_buf ) /* NAL decoding */ typedef struct hevc_sequence_parameter_set_t hevc_sequence_parameter_set_t; +typedef struct hevc_picture_parameter_set_t hevc_picture_parameter_set_t; hevc_sequence_parameter_set_t * hevc_rbsp_decode_sps( const uint8_t *, size_t ) VLC_USED; +hevc_picture_parameter_set_t * hevc_rbsp_decode_pps( const uint8_t *, size_t ) VLC_USED; void hevc_rbsp_release_sps( hevc_sequence_parameter_set_t * ); +void hevc_rbsp_release_pps( hevc_picture_parameter_set_t * ); /* Converts HEVCDecoderConfigurationRecord to Annex B format */ uint8_t * hevc_hvcC_to_AnnexB_NAL( const uint8_t *p_buf, size_t i_buf, _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
