[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