[vlc-devel] [RFC PATCH 4/7] packetizer h264: refactor and expose sps/pps parsing

Thomas Guillem thomas at gllm.fr
Mon Apr 27 15:01:11 CEST 2015


Ok this with patch ?

I improved it a little by adding a more robust check at the beginning of
h264_parse_sps and h264_parse_pps.

if (i_sps_size < 5 || (p_sps_buf[4] & 0x1f) != NAL_SPS)
  return -1;

...

if (i_sps_size < 5 || (p_sps_buf[4] & 0x1f) != NAL_PPS)
  return -1;


On Thu, Apr 23, 2015, at 19:30, Thomas Guillem wrote:
> The goal is to expose h264_parse_sps and h264_parse_pps functions that
> can be
> used from decoders.
> ---
>  modules/packetizer/h264.c     | 306
>  +++++-------------------------------------
>  modules/packetizer/h264_nal.c | 275
>  +++++++++++++++++++++++++++++++++++++
>  modules/packetizer/h264_nal.h |  58 ++++++++
>  3 files changed, 369 insertions(+), 270 deletions(-)
> 
> diff --git a/modules/packetizer/h264.c b/modules/packetizer/h264.c
> index 778b439..f82168c 100644
> --- a/modules/packetizer/h264.c
> +++ b/modules/packetizer/h264.c
> @@ -84,8 +84,6 @@ typedef struct
>      int i_delta_pic_order_cnt1;
>  } slice_t;
>  
> -#define SPS_MAX (32)
> -#define PPS_MAX (256)
>  struct decoder_sys_t
>  {
>      /* */
> @@ -558,17 +556,6 @@ static block_t *CreateAnnexbNAL( decoder_t *p_dec,
> const uint8_t *p, int i_size
>      return p_nal;
>  }
>  
> -static void CreateDecodedNAL( uint8_t **pp_ret, int *pi_ret,
> -                              const uint8_t *src, int i_src )
> -{
> -    uint8_t *dst = malloc( i_src );
> -
> -    *pp_ret = dst;
> -
> -    if( dst )
> -        *pi_ret = nal_decode(src, dst, i_src);
> -}
> -
>  /*****************************************************************************
>   * ParseNALBlock: parses annexB type NALs
>   * All p_frag blocks are required to start with 0 0 0 1 4-byte startcode
> @@ -828,295 +815,74 @@ static block_t *OutputPicture( decoder_t *p_dec )
>  static void PutSPS( decoder_t *p_dec, block_t *p_frag )
>  {
>      decoder_sys_t *p_sys = p_dec->p_sys;
> +    struct nal_sps sps;
>  
> -    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 )
> +    if( h264_parse_sps( p_frag->p_buffer, p_frag->i_buffer, &sps ) != 0
> )
>      {
> -        msg_Warn( p_dec, "invalid SPS (sps_id=%d)", i_sps_id );
> -        free( pb_dec );
> +        msg_Warn( p_dec, "invalid SPS (sps_id=%d)", sps.i_id );
>          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 )
> +    p_dec->fmt_out.i_profile = sps.i_profile;
> +    p_dec->fmt_out.i_level = sps.i_level;
> +    p_dec->fmt_out.video.i_width  = sps.i_width;
> +    p_dec->fmt_out.video.i_height = sps.i_height;
> +    if( sps.vui.i_sar_num != 0 && sps.vui.i_sar_den != 0 )
>      {
> -        /* 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;
> -                }
> -            }
> -        }
> +        p_dec->fmt_out.video.i_sar_num = sps.vui.i_sar_num;
> +        p_dec->fmt_out.video.i_sar_den = sps.vui.i_sar_den;
>      }
>  
> -    /* 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 );
> +    p_sys->i_log2_max_frame_num = sps.i_log2_max_frame_num;
> +    p_sys->b_frame_mbs_only = sps.b_frame_mbs_only;
> +    p_sys->i_pic_order_cnt_type = sps.i_pic_order_cnt_type;
> +    p_sys->i_delta_pic_order_always_zero_flag =
> sps.i_delta_pic_order_always_zero_flag;
> +    p_sys->i_log2_max_pic_order_cnt_lsb =
> sps.i_log2_max_pic_order_cnt_lsb;
>  
> -    /* crop */
> -    i_tmp = bs_read( &s, 1 );
> -    if( i_tmp )
> +    if( sps.vui.b_valid )
>      {
> -        /* left */
> -        bs_read_ue( &s );
> -        /* right */
> -        bs_read_ue( &s );
> -        /* top */
> -        bs_read_ue( &s );
> -        /* bottom */
> -        bs_read_ue( &s );
> +        p_sys->b_timing_info_present_flag =
> sps.vui.b_timing_info_present_flag;
> +        p_sys->i_num_units_in_tick =  sps.vui.i_num_units_in_tick;
> +        p_sys->i_time_scale = sps.vui.i_time_scale;
> +        p_sys->b_fixed_frame_rate = sps.vui.b_fixed_frame_rate;
> +        p_sys->b_pic_struct_present_flag =
> sps.vui.b_pic_struct_present_flag;
> +        p_sys->b_cpb_dpb_delays_present_flag =
> sps.vui.b_cpb_dpb_delays_present_flag;
> +        p_sys->i_cpb_removal_delay_length_minus1 =
> sps.vui.i_cpb_removal_delay_length_minus1;
> +        p_sys->i_dpb_output_delay_length_minus1 =
> sps.vui.i_dpb_output_delay_length_minus1;
>      }
>  
> -    /* 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 );
> +        msg_Dbg( p_dec, "found NAL_SPS (sps_id=%d)", sps.i_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;
> +    if( p_sys->pp_sps[sps.i_id] )
> +        block_Release( p_sys->pp_sps[sps.i_id] );
> +    p_sys->pp_sps[sps.i_id] = p_frag;
>  }
>  
>  static void PutPPS( decoder_t *p_dec, block_t *p_frag )
>  {
>      decoder_sys_t *p_sys = p_dec->p_sys;
> -    bs_t s;
> -    int i_pps_id;
> -    int i_sps_id;
> +    struct nal_pps pps;
>  
> -    bs_init( &s, &p_frag->p_buffer[5], p_frag->i_buffer - 5 );
> -    i_pps_id = bs_read_ue( &s ); // pps id
> -    i_sps_id = bs_read_ue( &s ); // sps id
> -    if( i_pps_id >= PPS_MAX || i_sps_id >= SPS_MAX )
> +    if( h264_parse_pps( p_frag->p_buffer, p_frag->i_buffer, &pps ) != 0
> )
>      {
> -        msg_Warn( p_dec, "invalid PPS (pps_id=%d sps_id=%d)", i_pps_id,
> i_sps_id );
> +        msg_Warn( p_dec, "invalid PPS (pps_id=%d sps_id=%d)", pps.i_id,
> pps.i_sps_id );
>          block_Release( p_frag );
>          return;
>      }
> -    bs_skip( &s, 1 ); // entropy coding mode flag
> -    p_sys->i_pic_order_present_flag = bs_read( &s, 1 );
> -    /* TODO */
> +    p_sys->i_pic_order_present_flag = pps.i_pic_order_present_flag;
>  
>      /* We have a new PPS */
>      if( !p_sys->b_pps )
> -        msg_Dbg( p_dec, "found NAL_PPS (pps_id=%d sps_id=%d)", i_pps_id,
> i_sps_id );
> +        msg_Dbg( p_dec, "found NAL_PPS (pps_id=%d sps_id=%d)", pps.i_id,
> pps.i_sps_id );
>      p_sys->b_pps = true;
>  
> -    if( p_sys->pp_pps[i_pps_id] )
> -        block_Release( p_sys->pp_pps[i_pps_id] );
> -    p_sys->pp_pps[i_pps_id] = p_frag;
> +    if( p_sys->pp_pps[pps.i_id] )
> +        block_Release( p_sys->pp_pps[pps.i_id] );
> +    p_sys->pp_pps[pps.i_id] = p_frag;
>  }
>  
>  static void ParseSlice( decoder_t *p_dec, bool *pb_new_picture, slice_t
>  *p_slice,
> diff --git a/modules/packetizer/h264_nal.c
> b/modules/packetizer/h264_nal.c
> index de3ce6f..9a0f6c0 100644
> --- a/modules/packetizer/h264_nal.c
> +++ b/modules/packetizer/h264_nal.c
> @@ -212,6 +212,281 @@ int h264_get_spspps( uint8_t *p_buf, size_t i_buf,
>      return -1;
>  }
>  
> +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;
> +
> +    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;
> +    /* Skip constraint_set0123, reserved(4) */
> +    bs_skip( &s, 1+1+1+1 + 4 );
> +    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;
> +}
> +
> +int h264_parse_pps( const uint8_t *p_pps_buf, int i_pps_size,
> +                    struct nal_pps *p_pps )
> +{
> +    bs_t s;
> +
> +    memset( p_pps, 0, sizeof(struct nal_pps) );
> +    bs_init( &s, &p_pps_buf[5], i_pps_size - 5 );
> +    p_pps->i_id = bs_read_ue( &s ); // pps id
> +    p_pps->i_sps_id = bs_read_ue( &s ); // sps id
> +    if( p_pps->i_id >= PPS_MAX || p_pps->i_sps_id >= SPS_MAX )
> +    {
> +        return -1;
> +    }
> +    bs_skip( &s, 1 ); // entropy coding mode flag
> +    p_pps->i_pic_order_present_flag = bs_read( &s, 1 );
> +    /* TODO */
> +
> +    return 0;
> +}
> +
>  bool h264_get_profile_level(const es_format_t *p_fmt, size_t *p_profile,
>                              size_t *p_level, size_t *p_nal_size)
>  {
> diff --git a/modules/packetizer/h264_nal.h
> b/modules/packetizer/h264_nal.h
> index c991ddc..f307b64 100644
> --- a/modules/packetizer/h264_nal.h
> +++ b/modules/packetizer/h264_nal.h
> @@ -28,6 +28,8 @@
>  # include <vlc_common.h>
>  # include <vlc_codec.h>
>  
> +# include "../demux/mpeg/mpeg_parser_helpers.h"
> +
>  #define PROFILE_H264_BASELINE             66
>  #define PROFILE_H264_MAIN                 77
>  #define PROFILE_H264_EXTENDED             88
> @@ -43,6 +45,9 @@
>  #define PROFILE_H264_MVC_STEREO_HIGH      128
>  #define PROFILE_H264_MVC_MULTIVIEW_HIGH   118
>  
> +#define SPS_MAX (32)
> +#define PPS_MAX (256)
> +
>  enum nal_unit_type_e
>  {
>      NAL_UNKNOWN = 0,
> @@ -66,6 +71,49 @@ enum sei_type_e
>      SEI_RECOVERY_POINT = 6
>  };
>  
> +struct nal_sps
> +{
> +    int i_id;
> +    int i_profile, i_level;
> +    int i_width, i_height;
> +    int i_log2_max_frame_num;
> +    int b_frame_mbs_only;
> +    int i_pic_order_cnt_type;
> +    int i_delta_pic_order_always_zero_flag;
> +    int i_log2_max_pic_order_cnt_lsb;
> +
> +    struct {
> +        bool b_valid;
> +        int i_sar_num, i_sar_den;
> +        bool b_timing_info_present_flag;
> +        uint32_t i_num_units_in_tick;
> +        uint32_t i_time_scale;
> +        bool b_fixed_frame_rate;
> +        bool b_pic_struct_present_flag;
> +        bool b_cpb_dpb_delays_present_flag;
> +        uint8_t i_cpb_removal_delay_length_minus1;
> +        uint8_t i_dpb_output_delay_length_minus1;
> +    } vui;
> +};
> +
> +struct nal_pps
> +{
> +    int i_id;
> +    int i_sps_id;
> +    int i_pic_order_present_flag;
> +};
> +
> +static inline void CreateDecodedNAL( uint8_t **pp_ret, int *pi_ret,
> +                                     const uint8_t *src, int i_src )
> +{
> +    uint8_t *dst = malloc( i_src );
> +
> +    *pp_ret = dst;
> +
> +    if( dst )
> +        *pi_ret = nal_decode(src, dst, i_src);
> +}
> +
>  /* Parse the SPS/PPS Metadata and convert it to annex b format */
>  int convert_sps_pps( decoder_t *p_dec, const uint8_t *p_buf,
>                       uint32_t i_buf_size, uint8_t *p_out_buf,
> @@ -88,6 +136,16 @@ int h264_get_spspps( uint8_t *p_buf, size_t i_buf,
>                       uint8_t **pp_sps, size_t *p_sps_size,
>                       uint8_t **pp_pps, size_t *p_pps_size );
>  
> +/* Parse a SPS into the struct nal_sps
> + * Returns 0 in case of success */
> +int h264_parse_sps( const uint8_t *p_sps_buf, int i_sps_size,
> +                    struct nal_sps *p_sps );
> +
> +/* Parse a PPS into the struct nal_pps
> + * Returns 0 in case of success */
> +int h264_parse_pps( const uint8_t *p_pps_buf, int i_pps_size,
> +                    struct nal_pps *p_pps );
> +
>  /* Get level and Profile */
>  bool h264_get_profile_level(const es_format_t *p_fmt, size_t *p_profile,
>                              size_t *p_level, size_t *p_nal_size);
> -- 
> 2.1.3
> 



More information about the vlc-devel mailing list