[vlc-commits] hevc_nal: add picture_parameter_set parser

Francois Cartegnie git at videolan.org
Tue Dec 15 17:23:47 CET 2015


vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | 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,



More information about the vlc-commits mailing list