From aa324fea9962707e0f52b7cec5fc75ffb1df6e57 Mon Sep 17 00:00:00 2001 From: Francois Cartegnie Date: Mon, 20 Nov 2017 15:01:34 +0100 Subject: [PATCH] packetizer/mux: refactor hevc decoder config creation beause we'll need it for VT Signed-off-by: Thomas Guillem --- modules/packetizer/hevc_nal.c | 151 +++++++++++++++++++++++++++++++++++++++++- modules/packetizer/hevc_nal.h | 47 +++++++++++-- 2 files changed, 193 insertions(+), 5 deletions(-) diff --git a/modules/packetizer/hevc_nal.c b/modules/packetizer/hevc_nal.c index f7ad2a5406..c49359643d 100644 --- a/modules/packetizer/hevc_nal.c +++ b/modules/packetizer/hevc_nal.c @@ -1300,7 +1300,156 @@ bool hevc_get_profile_level(const es_format_t *p_fmt, uint8_t *pi_profile, return true; } -/* 8.3.1 Decoding process for POC */ +/* + * HEVCDecoderConfigurationRecord operations + */ + +static void hevc_dcr_params_from_vps( const uint8_t * p_buffer, size_t i_buffer, + struct hevc_dcr_values *p_values ) +{ + if( i_buffer < 19 ) + return; + + bs_t bs; + bs_init( &bs, p_buffer, i_buffer ); + unsigned i_bitflow = 0; + bs.p_fwpriv = &i_bitflow; + bs.pf_forward = hxxx_bsfw_ep3b_to_rbsp; /* Does the emulated 3bytes conversion to rbsp */ + + /* first two bytes are the NAL header, 3rd and 4th are: + vps_video_parameter_set_id(4) + vps_reserved_3_2bis(2) + vps_max_layers_minus1(6) + vps_max_sub_layers_minus1(3) + vps_temporal_id_nesting_flags + */ + bs_skip( &bs, 16 + 4 + 2 + 6 ); + p_values->i_numTemporalLayer = bs_read( &bs, 3 ) + 1; + p_values->b_temporalIdNested = bs_read1( &bs ); + + /* 5th & 6th are reserved 0xffff */ + bs_skip( &bs, 16 ); + /* copy the first 12 bytes of profile tier */ + for( unsigned i=0; i<12; i++ ) + p_values->general_configuration[i] = bs_read( &bs, 8 ); +} + +#define HEVC_DCR_ADD_NALS(type, count, buffers, sizes) \ +for (uint8_t i = 0; i < count; i++) \ +{ \ + if( i ==0 ) \ + { \ + *p++ = (type | (b_completeness ? 0x80 : 0)); \ + SetWBE( p, count ); p += 2; \ + } \ + SetWBE( p, sizes[i]); p += 2; \ + memcpy( p, buffers[i], sizes[i] ); p += sizes[i];\ +} + +#define HEVC_DCR_ADD_SIZES(count, sizes) \ +if(count > 0) \ +{\ + i_total_size += 3;\ + for(uint8_t i=0; ip_values != NULL ) + { + values = *p_params->p_values; + } + else + { + if( p_params->i_vps_count == 0 || p_params->i_sps_count == 0 ) + return NULL; /* required to extract info */ + + hevc_dcr_params_from_vps( p_params->p_vps[0], p_params->rgi_vps[0], &values ); + + hevc_sequence_parameter_set_t *p_sps = + hevc_decode_sps( p_params->p_sps[0], p_params->rgi_sps[0], true ); + if( p_sps ) + { + values.i_chroma_idc = p_sps->chroma_format_idc; + values.i_bit_depth_chroma_minus8 = p_sps->bit_depth_chroma_minus8; + values.i_bit_depth_luma_minus8 = p_sps->bit_depth_luma_minus8; + hevc_rbsp_release_sps( p_sps ); + } + } + + size_t i_total_size = 1+12+2+4+2+2; + HEVC_DCR_ADD_SIZES(p_params->i_vps_count, p_params->rgi_vps); + HEVC_DCR_ADD_SIZES(p_params->i_sps_count, p_params->rgi_sps); + HEVC_DCR_ADD_SIZES(p_params->i_pps_count, p_params->rgi_pps); + HEVC_DCR_ADD_SIZES(p_params->i_sei_count, p_params->rgi_sei); + + uint8_t *p_data = malloc( i_total_size ); + if( p_data == NULL ) + return NULL; + + *pi_size = i_total_size; + uint8_t *p = p_data; + + /* version */ + *p++ = 0x01; + memcpy( p, values.general_configuration, 12 ); p += 12; + /* Don't set min spatial segmentation */ + SetWBE( p, 0xF000 ); p += 2; + /* Don't set parallelism type since segmentation isn't set */ + *p++ = 0xFC; + *p++ = (0xFC | (values.i_chroma_idc & 0x03)); + *p++ = (0xF8 | (values.i_bit_depth_luma_minus8 & 0x07)); + *p++ = (0xF8 | (values.i_bit_depth_chroma_minus8 & 0x07)); + + /* Don't set framerate */ + SetWBE( p, 0x0000); p += 2; + /* Force NAL size of 4 bytes that replace the startcode */ + *p++ = ( ((values.i_numTemporalLayer & 0x07) << 3) | + (values.b_temporalIdNested << 2) | + (i_nal_length_size - 1) ); + /* total number of arrays */ + *p++ = !!p_params->i_vps_count + !!p_params->i_sps_count + + !!p_params->i_pps_count + !!p_params->i_sei_count; + + /* Write NAL arrays */ + HEVC_DCR_ADD_NALS(HEVC_NAL_VPS, p_params->i_vps_count, + p_params->p_vps, p_params->rgi_vps); + HEVC_DCR_ADD_NALS(HEVC_NAL_SPS, p_params->i_sps_count, + p_params->p_sps, p_params->rgi_sps); + HEVC_DCR_ADD_NALS(HEVC_NAL_PPS, p_params->i_pps_count, + p_params->p_pps, p_params->rgi_pps); + HEVC_DCR_ADD_NALS(HEVC_NAL_PREF_SEI, p_params->i_sei_count, + p_params->p_sei, p_params->rgi_sei); + + return p_data; +} + +#undef HEVC_DCR_ADD_NALS +#undef HEVC_DCR_ADD_SIZES + + +/* + * 8.3.1 Decoding process for POC + */ int hevc_compute_picture_order_count( const hevc_sequence_parameter_set_t *p_sps, const hevc_slice_segment_header_t *p_slice, hevc_poc_ctx_t *p_ctx ) diff --git a/modules/packetizer/hevc_nal.h b/modules/packetizer/hevc_nal.h index 047f554dd6..13e4deb6a2 100644 --- a/modules/packetizer/hevc_nal.h +++ b/modules/packetizer/hevc_nal.h @@ -175,10 +175,6 @@ uint8_t hevc_get_sps_vps_id( const hevc_sequence_parameter_set_t * ); uint8_t hevc_get_pps_sps_id( const hevc_picture_parameter_set_t * ); uint8_t hevc_get_slice_pps_id( const hevc_slice_segment_header_t * ); -/* Converts HEVCDecoderConfigurationRecord to Annex B format */ -uint8_t * hevc_hvcC_to_AnnexB_NAL( const uint8_t *p_buf, size_t i_buf, - size_t *pi_res, uint8_t *pi_nal_length_size ); - bool hevc_get_xps_id(const uint8_t *p_nalbuf, size_t i_nalbuf, uint8_t *pi_id); bool hevc_get_sps_profile_tier_level( const hevc_sequence_parameter_set_t *, uint8_t *pi_profile, uint8_t *pi_level ); @@ -201,6 +197,49 @@ bool hevc_get_slice_type( const hevc_slice_segment_header_t *, enum hevc_slice_t bool hevc_get_profile_level(const es_format_t *p_fmt, uint8_t *pi_profile, uint8_t *pi_level, uint8_t *pi_nal_length_size); +/* + * HEVCDecoderConfigurationRecord related + */ +struct hevc_dcr_values +{ + uint8_t general_configuration[12]; + uint8_t i_numTemporalLayer; + uint8_t i_chroma_idc; + uint8_t i_bit_depth_luma_minus8; + uint8_t i_bit_depth_chroma_minus8; + bool b_temporalIdNested; +}; + +#define HEVC_DCR_VPS_COUNT (HEVC_VPS_ID_MAX + 1) +#define HEVC_DCR_SPS_COUNT (HEVC_SPS_ID_MAX + 1) +#define HEVC_DCR_PPS_COUNT (HEVC_PPS_ID_MAX + 1) +#define HEVC_DCR_SEI_COUNT (16) + +struct hevc_dcr_params +{ + const uint8_t *p_vps[HEVC_DCR_VPS_COUNT], + *p_sps[HEVC_DCR_SPS_COUNT], + *p_pps[HEVC_DCR_VPS_COUNT], + *p_sei[HEVC_DCR_SEI_COUNT]; + uint8_t rgi_vps[HEVC_DCR_VPS_COUNT], + rgi_sps[HEVC_DCR_SPS_COUNT], + rgi_pps[HEVC_DCR_PPS_COUNT], + rgi_sei[HEVC_DCR_SEI_COUNT]; + uint8_t i_vps_count, i_sps_count, i_pps_count, i_sei_count; + struct hevc_dcr_values *p_values; +}; + +uint8_t * hevc_create_dcr( const struct hevc_dcr_params *p_params, + uint8_t i_nal_length_size, + bool b_completeness, size_t *pi_size ); + +/* Converts HEVCDecoderConfigurationRecord to Annex B format */ +uint8_t * hevc_hvcC_to_AnnexB_NAL( const uint8_t *p_buf, size_t i_buf, + size_t *pi_res, uint8_t *pi_nal_length_size ); + +/* + * POC computing + */ typedef struct { struct -- 2.11.4.GIT