vlc | branch: master | Francois Cartegnie <[email protected]> | Fri Mar 17 18:29:29 2017 +0100| [fde0b7b7fdef4df14fe8d136fce3fd91b02f97f9] | committer: Francois Cartegnie
packetizer: h264: split slice parsing > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=fde0b7b7fdef4df14fe8d136fce3fd91b02f97f9 --- modules/packetizer/Makefile.am | 1 + modules/packetizer/h264.c | 150 +++++++--------------------------------- modules/packetizer/h264_slice.c | 122 ++++++++++++++++++++++++++++++++ modules/packetizer/h264_slice.h | 69 ++++++++++++++++++ 4 files changed, 217 insertions(+), 125 deletions(-) diff --git a/modules/packetizer/Makefile.am b/modules/packetizer/Makefile.am index b873194..ad8dc21 100644 --- a/modules/packetizer/Makefile.am +++ b/modules/packetizer/Makefile.am @@ -7,6 +7,7 @@ libpacketizer_mpeg4audio_plugin_la_SOURCES = packetizer/mpeg4audio.c libpacketizer_mpegaudio_plugin_la_SOURCES = packetizer/mpegaudio.c libpacketizer_h264_plugin_la_SOURCES = \ packetizer/h264_nal.c packetizer/h264_nal.h \ + packetizer/h264_slice.c packetizer/h264_slice.h \ packetizer/h264.c packetizer/hxxx_nal.h \ packetizer/hxxx_sei.c packetizer/hxxx_sei.h \ packetizer/hxxx_common.c packetizer/hxxx_common.h diff --git a/modules/packetizer/h264.c b/modules/packetizer/h264.c index dd4cd0d..2849dea 100644 --- a/modules/packetizer/h264.c +++ b/modules/packetizer/h264.c @@ -41,6 +41,7 @@ #include <vlc_block_helper.h> #include <vlc_bits.h> #include "h264_nal.h" +#include "h264_slice.h" #include "hxxx_nal.h" #include "hxxx_sei.h" #include "hxxx_common.h" @@ -65,27 +66,6 @@ vlc_module_end () /**************************************************************************** * Local prototypes ****************************************************************************/ -typedef struct -{ - int i_nal_type; - int i_nal_ref_idc; - - int i_frame_type; - int i_pic_parameter_set_id; - int i_frame_num; - - int i_field_pic_flag; - int i_bottom_field_flag; - - int i_idr_pic_id; - - int i_pic_order_cnt_type; - int i_pic_order_cnt_lsb; - int i_delta_pic_order_cnt_bottom; - - int i_delta_pic_order_cnt0; - int i_delta_pic_order_cnt1; -} slice_t; struct decoder_sys_t { @@ -127,7 +107,7 @@ struct decoder_sys_t uint8_t i_dpb_output_delay; /* Useful values of the Slice Header */ - slice_t slice; + h264_slice_t slice; /* */ bool b_even_frame; @@ -159,7 +139,7 @@ static block_t *ParseNALBlock( decoder_t *, bool *pb_ts_used, block_t * ); static block_t *OutputPicture( decoder_t *p_dec ); static void PutSPS( decoder_t *p_dec, block_t *p_frag ); static void PutPPS( decoder_t *p_dec, block_t *p_frag ); -static bool ParseSliceHeader( decoder_t *p_dec, const block_t *p_frag, slice_t *p_slice ); +static bool ParseSliceHeader( decoder_t *p_dec, const block_t *p_frag, h264_slice_t *p_slice ); static bool ParseSeiCallback( const hxxx_sei_data_t *, void * ); @@ -242,24 +222,7 @@ static void ActivateSets( decoder_t *p_dec, const h264_sequence_parameter_set_t } } -static void SliceInit( slice_t *p_slice ) -{ - p_slice->i_nal_type = -1; - p_slice->i_nal_ref_idc = -1; - p_slice->i_idr_pic_id = -1; - p_slice->i_frame_num = -1; - p_slice->i_frame_type = 0; - p_slice->i_pic_parameter_set_id = -1; - p_slice->i_field_pic_flag = 0; - p_slice->i_bottom_field_flag = -1; - p_slice->i_pic_order_cnt_type = -1; - p_slice->i_pic_order_cnt_lsb = -1; - p_slice->i_delta_pic_order_cnt_bottom = -1; - p_slice->i_delta_pic_order_cnt0 = 0; - p_slice->i_delta_pic_order_cnt1 = 0; -} - -static bool IsFirstVCLNALUnit( const slice_t *p_prev, const slice_t *p_cur ) +static bool IsFirstVCLNALUnit( const h264_slice_t *p_prev, const h264_slice_t *p_cur ) { /* Detection of the first VCL NAL unit of a primary coded picture * (cf. 7.4.1.2.4) */ @@ -346,7 +309,7 @@ static int Open( vlc_object_t *p_this ) p_sys->p_active_pps = NULL; p_sys->i_recovery_frames = -1; - SliceInit( &p_sys->slice ); + h264_slice_init( &p_sys->slice ); p_sys->b_even_frame = false; p_sys->b_discontinuity = false; @@ -590,7 +553,7 @@ static block_t *ParseNALBlock( decoder_t *p_dec, bool *pb_ts_used, block_t *p_fr if( i_nal_type >= H264_NAL_SLICE && i_nal_type <= H264_NAL_SLICE_IDR ) { - slice_t newslice; + h264_slice_t newslice; if( ParseSliceHeader( p_dec, p_frag, &newslice ) ) { @@ -949,13 +912,22 @@ static void PutPPS( decoder_t *p_dec, block_t *p_frag ) StorePPS( p_sys, p_pps->i_id, p_frag, p_pps ); } -static bool ParseSliceHeader( decoder_t *p_dec, const block_t *p_frag, slice_t *p_slice ) +static void GetSPSPPS( uint8_t i_pps_id, void *priv, + const h264_sequence_parameter_set_t **pp_sps, + const h264_picture_parameter_set_t **pp_pps ) +{ + decoder_sys_t *p_sys = priv; + + *pp_pps = p_sys->pps[i_pps_id].p_pps; + if( *pp_pps == NULL ) + *pp_sps = NULL; + else + *pp_sps = p_sys->sps[(*pp_pps)->i_sps_id].p_sps; +} + +static bool ParseSliceHeader( decoder_t *p_dec, const block_t *p_frag, h264_slice_t *p_slice ) { decoder_sys_t *p_sys = p_dec->p_sys; - int i_slice_type; - SliceInit( p_slice ); - bs_t s; - unsigned i_bitflow = 0; const uint8_t *p_stripped = p_frag->p_buffer; size_t i_stripped = p_frag->i_buffer; @@ -963,89 +935,17 @@ static bool ParseSliceHeader( decoder_t *p_dec, const block_t *p_frag, slice_t * if( !hxxx_strip_AnnexB_startcode( &p_stripped, &i_stripped ) || i_stripped < 2 ) return false; - bs_init( &s, p_stripped, i_stripped ); - s.p_fwpriv = &i_bitflow; - s.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */ - /* nal unit header */ - bs_skip( &s, 1 ); - const uint8_t i_nal_ref_idc = bs_read( &s, 2 ); - const uint8_t i_nal_type = bs_read( &s, 5 ); - - /* 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: - p_slice->i_frame_type = BLOCK_FLAG_TYPE_P; - break; - case 1: case 6: - p_slice->i_frame_type = BLOCK_FLAG_TYPE_B; - break; - case 2: case 7: - p_slice->i_frame_type = BLOCK_FLAG_TYPE_I; - break; - case 3: case 8: /* SP */ - p_slice->i_frame_type = BLOCK_FLAG_TYPE_P; - break; - case 4: case 9: - p_slice->i_frame_type = BLOCK_FLAG_TYPE_I; - break; - default: - p_slice->i_frame_type = 0; - break; - } - - /* */ - p_slice->i_nal_type = i_nal_type; - p_slice->i_nal_ref_idc = i_nal_ref_idc; - - p_slice->i_pic_parameter_set_id = bs_read_ue( &s ); - if( p_slice->i_pic_parameter_set_id > H264_PPS_ID_MAX ) - return false; - - /* Bind matched/referred PPS and SPS */ - const h264_picture_parameter_set_t *p_pps = - p_sys->p_active_pps = p_sys->pps[p_slice->i_pic_parameter_set_id].p_pps; - if( p_pps == NULL ) + if( !h264_decode_slice( p_stripped, i_stripped, GetSPSPPS, p_sys, p_slice ) ) return false; - const h264_sequence_parameter_set_t *p_sps = - p_sys->p_active_sps = p_sys->sps[p_pps->i_sps_id].p_sps; - if( p_sps == NULL ) + const h264_sequence_parameter_set_t *p_sps; + const h264_picture_parameter_set_t *p_pps; + GetSPSPPS( p_slice->i_pic_parameter_set_id, p_sys, &p_sps, &p_pps ); + if( unlikely( !p_sps || !p_pps) ) return false; ActivateSets( p_dec, p_sps, p_pps ); - p_slice->i_frame_num = bs_read( &s, p_sps->i_log2_max_frame_num + 4 ); - - if( !p_sps->frame_mbs_only_flag ) - { - /* field_pic_flag */ - p_slice->i_field_pic_flag = bs_read( &s, 1 ); - if( p_slice->i_field_pic_flag ) - p_slice->i_bottom_field_flag = bs_read( &s, 1 ); - } - - if( p_slice->i_nal_type == H264_NAL_SLICE_IDR ) - p_slice->i_idr_pic_id = bs_read_ue( &s ); - - p_slice->i_pic_order_cnt_type = p_sps->i_pic_order_cnt_type; - if( p_sps->i_pic_order_cnt_type == 0 ) - { - p_slice->i_pic_order_cnt_lsb = bs_read( &s, p_sps->i_log2_max_pic_order_cnt_lsb + 4 ); - if( p_pps->i_pic_order_present_flag && !p_slice->i_field_pic_flag ) - p_slice->i_delta_pic_order_cnt_bottom = bs_read_se( &s ); - } - else if( (p_sps->i_pic_order_cnt_type == 1) && - (!p_sps->i_delta_pic_order_always_zero_flag) ) - { - p_slice->i_delta_pic_order_cnt0 = bs_read_se( &s ); - if( p_pps->i_pic_order_present_flag && !p_slice->i_field_pic_flag ) - p_slice->i_delta_pic_order_cnt1 = bs_read_se( &s ); - } - return true; } diff --git a/modules/packetizer/h264_slice.c b/modules/packetizer/h264_slice.c new file mode 100644 index 0000000..8c583f9 --- /dev/null +++ b/modules/packetizer/h264_slice.c @@ -0,0 +1,122 @@ +/***************************************************************************** + * h264_slice.c: h264 slice parser + ***************************************************************************** + * Copyright (C) 2001-17 VLC authors and VideoLAN + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <vlc_common.h> +#include <vlc_bits.h> +#include <vlc_block.h> + +#include "h264_nal.h" +#include "h264_slice.h" +#include "hxxx_nal.h" + +bool h264_decode_slice( const uint8_t *p_buffer, size_t i_buffer, + void (* get_sps_pps)(uint8_t, void *, + const h264_sequence_parameter_set_t **, + const h264_picture_parameter_set_t ** ), + void *priv, h264_slice_t *p_slice ) +{ + int i_slice_type; + h264_slice_init( p_slice ); + bs_t s; + unsigned i_bitflow = 0; + bs_init( &s, p_buffer, i_buffer ); + s.p_fwpriv = &i_bitflow; + s.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */ + + /* nal unit header */ + bs_skip( &s, 1 ); + const uint8_t i_nal_ref_idc = bs_read( &s, 2 ); + const uint8_t i_nal_type = bs_read( &s, 5 ); + + /* 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: + p_slice->i_frame_type = BLOCK_FLAG_TYPE_P; + break; + case 1: case 6: + p_slice->i_frame_type = BLOCK_FLAG_TYPE_B; + break; + case 2: case 7: + p_slice->i_frame_type = BLOCK_FLAG_TYPE_I; + break; + case 3: case 8: /* SP */ + p_slice->i_frame_type = BLOCK_FLAG_TYPE_P; + break; + case 4: case 9: + p_slice->i_frame_type = BLOCK_FLAG_TYPE_I; + break; + default: + p_slice->i_frame_type = 0; + break; + } + + /* */ + p_slice->i_nal_type = i_nal_type; + p_slice->i_nal_ref_idc = i_nal_ref_idc; + + p_slice->i_pic_parameter_set_id = bs_read_ue( &s ); + if( p_slice->i_pic_parameter_set_id > H264_PPS_ID_MAX ) + return false; + + const h264_sequence_parameter_set_t *p_sps; + const h264_picture_parameter_set_t *p_pps; + + /* Bind matched/referred PPS and SPS */ + get_sps_pps( p_slice->i_pic_parameter_set_id, priv, &p_sps, &p_pps ); + if( !p_sps || !p_pps ) + return false; + + p_slice->i_frame_num = bs_read( &s, p_sps->i_log2_max_frame_num + 4 ); + + if( !p_sps->frame_mbs_only_flag ) + { + /* field_pic_flag */ + p_slice->i_field_pic_flag = bs_read( &s, 1 ); + if( p_slice->i_field_pic_flag ) + p_slice->i_bottom_field_flag = bs_read( &s, 1 ); + } + + if( p_slice->i_nal_type == H264_NAL_SLICE_IDR ) + p_slice->i_idr_pic_id = bs_read_ue( &s ); + + p_slice->i_pic_order_cnt_type = p_sps->i_pic_order_cnt_type; + if( p_sps->i_pic_order_cnt_type == 0 ) + { + p_slice->i_pic_order_cnt_lsb = bs_read( &s, p_sps->i_log2_max_pic_order_cnt_lsb + 4 ); + if( p_pps->i_pic_order_present_flag && !p_slice->i_field_pic_flag ) + p_slice->i_delta_pic_order_cnt_bottom = bs_read_se( &s ); + } + else if( (p_sps->i_pic_order_cnt_type == 1) && + (!p_sps->i_delta_pic_order_always_zero_flag) ) + { + p_slice->i_delta_pic_order_cnt0 = bs_read_se( &s ); + if( p_pps->i_pic_order_present_flag && !p_slice->i_field_pic_flag ) + p_slice->i_delta_pic_order_cnt1 = bs_read_se( &s ); + } + + return true; +} diff --git a/modules/packetizer/h264_slice.h b/modules/packetizer/h264_slice.h new file mode 100644 index 0000000..0b665b5 --- /dev/null +++ b/modules/packetizer/h264_slice.h @@ -0,0 +1,69 @@ +/***************************************************************************** + * h264_slice.c: h264 slice parser + ***************************************************************************** + * Copyright (C) 2001-17 VLC authors and VideoLAN + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ +#ifndef VLC_H264_SLICE_H +#define VLC_H264_SLICE_H + +typedef struct +{ + int i_nal_type; + int i_nal_ref_idc; + + int i_frame_type; + int i_pic_parameter_set_id; + int i_frame_num; + + int i_field_pic_flag; + int i_bottom_field_flag; + + int i_idr_pic_id; + + int i_pic_order_cnt_type; + int i_pic_order_cnt_lsb; + int i_delta_pic_order_cnt_bottom; + + int i_delta_pic_order_cnt0; + int i_delta_pic_order_cnt1; + +} h264_slice_t; + +static inline void h264_slice_init( h264_slice_t *p_slice ) +{ + p_slice->i_nal_type = -1; + p_slice->i_nal_ref_idc = -1; + p_slice->i_idr_pic_id = -1; + p_slice->i_frame_num = -1; + p_slice->i_frame_type = 0; + p_slice->i_pic_parameter_set_id = -1; + p_slice->i_field_pic_flag = 0; + p_slice->i_bottom_field_flag = -1; + p_slice->i_pic_order_cnt_type = -1; + p_slice->i_pic_order_cnt_lsb = -1; + p_slice->i_delta_pic_order_cnt_bottom = -1; + p_slice->i_delta_pic_order_cnt0 = 0; + p_slice->i_delta_pic_order_cnt1 = 0; +} + +bool h264_decode_slice( const uint8_t *p_buffer, size_t i_buffer, + void (* get_sps_pps)(uint8_t pps_id, void *, + const h264_sequence_parameter_set_t **, + const h264_picture_parameter_set_t ** ), + void *, h264_slice_t *p_slice ); + +#endif _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
