[vlc-commits] packetizer/mux: refactor hevc decoder config creation
Francois Cartegnie
git at videolan.org
Fri Nov 24 13:11:55 CET 2017
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Mon Nov 20 15:01:34 2017 +0100| [aa324fea9962707e0f52b7cec5fc75ffb1df6e57] | committer: Thomas Guillem
packetizer/mux: refactor hevc decoder config creation
beause we'll need it for VT
Signed-off-by: Thomas Guillem <thomas at gllm.fr>
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=aa324fea9962707e0f52b7cec5fc75ffb1df6e57
---
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; i<count; i++)\
+ i_total_size += 2 + sizes[i];\
+}
+
+/* Generate HEVCDecoderConfiguration iso/iec 14496-15 3rd edition */
+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 )
+{
+ *pi_size = 0;
+
+ if( i_nal_length_size != 1 && i_nal_length_size != 2 && i_nal_length_size != 4 )
+ return NULL;
+
+ struct hevc_dcr_values values =
+ {
+ .general_configuration = {0},
+ .i_numTemporalLayer = 0,
+ .i_chroma_idc = 1,
+ .i_bit_depth_luma_minus8 = 0,
+ .i_bit_depth_chroma_minus8 = 0,
+ .b_temporalIdNested = false,
+ };
+
+ if( p_params->p_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
More information about the vlc-commits
mailing list