[vlc-commits] [Git][videolan/vlc][3.0.x] 5 commits: packetizer: h264: write avcC with HIGH extended info
Jean-Baptiste Kempf (@jbk)
gitlab at videolan.org
Sat Jul 3 08:19:50 UTC 2021
Jean-Baptiste Kempf pushed to branch 3.0.x at VideoLAN / VLC
Commits:
ff632589 by Francois Cartegnie at 2021-07-03T07:50:52+00:00
packetizer: h264: write avcC with HIGH extended info
(cherry picked from commit 8d5dd5ead3340db5591ef09b703432723aaa1886)
- - - - -
7f85a5ad by Francois Cartegnie at 2021-07-03T07:50:52+00:00
packetizer: h264: add basic decoding for sequence set extension
(cherry picked from commit a9d002e84b49fe395f5564f0fcee57a1f7f25229)
- - - - -
8530682d by Francois Cartegnie at 2021-07-03T07:50:52+00:00
hxxx_helper: process SPS_EXT
(cherry picked from commit 33a34ae731ce03aa4910c680cae1eb6bfd3a56f3)
- - - - -
a3df90aa by Francois Cartegnie at 2021-07-03T07:50:52+00:00
packetizer: h264: remove scan lookup
(cherry picked from commit 8404b8c6b79d4e94ed9f1170b089620614cb7a7f)
- - - - -
cd18bd16 by Francois Cartegnie at 2021-07-03T07:50:52+00:00
packetizer: h264: gather and store SPSEXT
(cherry picked from commit 35251232e281be37ecb994ae8714c32dc2e40c30)
- - - - -
5 changed files:
- modules/codec/hxxx_helper.c
- modules/codec/hxxx_helper.h
- modules/packetizer/h264.c
- modules/packetizer/h264_nal.c
- modules/packetizer/h264_nal.h
Changes:
=====================================
modules/codec/hxxx_helper.c
=====================================
@@ -88,6 +88,8 @@ hxxx_helper_clean(struct hxxx_helper *hh)
h264_release_sps(hnal->h264_sps));
RELEASE_NALS(hh->h264.pps_list, H264_PPS_ID_MAX,
h264_release_pps(hnal->h264_pps));
+ RELEASE_NALS(hh->h264.spsext_list, H264_SPSEXT_ID_MAX,
+ h264_release_sps_extension(hnal->h264_spsext));
memset(&hh->h264, 0, sizeof(hh->h264));
break;
case VLC_CODEC_HEVC:
@@ -229,6 +231,15 @@ h264_helper_parse_nal(struct hxxx_helper *hh, const uint8_t *p_buf, size_t i_buf
h264_release_pps);
msg_Dbg(hh->p_obj, "new PPS parsed: %u", ((h264_picture_parameter_set_t*)p_xps)->i_id);
}
+ else if(i_nal_type == H264_NAL_SPS_EXT)
+ {
+ LOAD_xPS(hh->h264.spsext_list, hh->h264.i_spsext_count,
+ p_xps->i_sps_id, H264_SPSEXT_ID_MAX,
+ h264_sequence_parameter_set_extension_t,
+ h264_decode_sps_extension,
+ h264_release_sps_extension);
+ msg_Dbg(hh->p_obj, "new SPSEXT parsed: %u", ((h264_sequence_parameter_set_extension_t*)p_xps)->i_sps_id);
+ }
else if (i_nal_type <= H264_NAL_SLICE_IDR
&& i_nal_type != H264_NAL_UNKNOWN)
{
@@ -738,11 +749,11 @@ h264_helper_get_annexb_config(const struct hxxx_helper *hh)
return NULL;
const struct hxxx_helper_nal *pp_nal_lists[] = {
- hh->h264.sps_list, hh->h264.pps_list };
- const size_t p_nal_counts[] = { hh->h264.i_sps_count, hh->h264.i_pps_count };
- const size_t p_nal_maxs[] = { H264_SPS_ID_MAX+1, H264_PPS_ID_MAX+1 };
+ hh->h264.sps_list, hh->h264.pps_list, hh->h264.spsext_list };
+ const size_t p_nal_counts[] = { hh->h264.i_sps_count, hh->h264.i_pps_count, hh->h264.i_spsext_count };
+ const size_t p_nal_maxs[] = { H264_SPS_ID_MAX+1, H264_PPS_ID_MAX+1, H264_SPSEXT_ID_MAX+1 };
- return hxxx_helper_get_annexb_config( pp_nal_lists, p_nal_counts, p_nal_maxs, 2 );
+ return hxxx_helper_get_annexb_config( pp_nal_lists, p_nal_counts, p_nal_maxs, 3 );
}
block_t *
@@ -782,8 +793,19 @@ h264_helper_get_avcc_config(const struct hxxx_helper *hh)
pp_pps_bufs[i_nal_found - 1] = p_nal->b->p_buffer;
p_pps_sizes[i_nal_found - 1] = p_nal->b->i_buffer;
}
+
+ const uint8_t *pp_spsext_bufs[hh->h264.i_spsext_count];
+ size_t p_spsext_sizes[hh->h264.i_spsext_count];
+ HELPER_FOREACH_NAL(p_nal, hh->h264.spsext_list, hh->h264.i_spsext_count,
+ H264_SPSEXT_ID_MAX+1)
+ {
+ pp_spsext_bufs[i_nal_found - 1] = p_nal->b->p_buffer;
+ p_spsext_sizes[i_nal_found - 1] = p_nal->b->i_buffer;
+ }
+
return h264_NAL_to_avcC(4, pp_sps_bufs, p_sps_sizes, hh->h264.i_sps_count,
- pp_pps_bufs, p_pps_sizes, hh->h264.i_pps_count);
+ pp_pps_bufs, p_pps_sizes, hh->h264.i_pps_count,
+ pp_spsext_bufs, p_spsext_sizes, hh->h264.i_spsext_count);
}
block_t *
=====================================
modules/codec/hxxx_helper.h
=====================================
@@ -35,6 +35,7 @@ struct hxxx_helper_nal
void *xps;
h264_sequence_parameter_set_t *h264_sps;
h264_picture_parameter_set_t *h264_pps;
+ h264_sequence_parameter_set_extension_t *h264_spsext;
hevc_sequence_parameter_set_t *hevc_sps;
hevc_picture_parameter_set_t *hevc_pps;
hevc_video_parameter_set_t *hevc_vps;
@@ -55,9 +56,11 @@ struct hxxx_helper
struct {
struct hxxx_helper_nal sps_list[H264_SPS_ID_MAX + 1];
struct hxxx_helper_nal pps_list[H264_PPS_ID_MAX + 1];
+ struct hxxx_helper_nal spsext_list[H264_SPS_ID_MAX + 1];
uint8_t i_current_sps;
uint8_t i_sps_count;
uint8_t i_pps_count;
+ uint8_t i_spsext_count;
} h264;
struct {
struct hxxx_helper_nal sps_list[HEVC_SPS_ID_MAX + 1];
=====================================
modules/packetizer/h264.c
=====================================
@@ -96,6 +96,10 @@ struct decoder_sys_t
block_t *p_block;
h264_picture_parameter_set_t *p_pps;
} pps[H264_PPS_ID_MAX + 1];
+ struct
+ {
+ block_t *p_block;
+ } spsext[H264_SPSEXT_ID_MAX + 1];
const h264_sequence_parameter_set_t *p_active_sps;
const h264_picture_parameter_set_t *p_active_pps;
@@ -152,6 +156,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 void PutSPSEXT( decoder_t *p_dec, block_t *p_frag );
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 * );
@@ -188,6 +193,13 @@ static void StorePPS( decoder_sys_t *p_sys, uint8_t i_id,
p_sys->pps[i_id].p_pps = p_pps;
}
+static void StoreSPSEXT( decoder_sys_t *p_sys, uint8_t i_id, block_t *p_block )
+{
+ if( p_sys->spsext[i_id].p_block )
+ block_Release( p_sys->spsext[i_id].p_block );
+ p_sys->spsext[i_id].p_block = p_block;
+}
+
static void ActivateSets( decoder_t *p_dec, const h264_sequence_parameter_set_t *p_sps,
const h264_picture_parameter_set_t *p_pps )
{
@@ -237,27 +249,28 @@ static void ActivateSets( decoder_t *p_dec, const h264_sequence_parameter_set_t
if( p_dec->fmt_out.i_extra == 0 && p_pps )
{
- const block_t *p_spsblock = NULL;
- const block_t *p_ppsblock = NULL;
- for( size_t i=0; i<=H264_SPS_ID_MAX && !p_spsblock; i++ )
- if( p_sps == p_sys->sps[i].p_sps )
- p_spsblock = p_sys->sps[i].p_block;
-
- for( size_t i=0; i<=H264_PPS_ID_MAX && !p_ppsblock; i++ )
- if( p_pps == p_sys->pps[i].p_pps )
- p_ppsblock = p_sys->pps[i].p_block;
+ const block_t *p_spsblock = p_sys->sps[p_sps->i_id].p_block;
+ const block_t *p_ppsblock = p_sys->pps[p_pps->i_id].p_block;
+ const block_t *p_spsextblock = p_sys->spsext[p_sps->i_id].p_block;
if( p_spsblock && p_ppsblock )
{
size_t i_alloc = p_ppsblock->i_buffer + p_spsblock->i_buffer;
+ if( p_spsextblock )
+ i_alloc += p_spsextblock->i_buffer;
p_dec->fmt_out.p_extra = malloc( i_alloc );
if( p_dec->fmt_out.p_extra )
{
uint8_t*p_buf = p_dec->fmt_out.p_extra;
p_dec->fmt_out.i_extra = i_alloc;
- memcpy( &p_buf[0], p_spsblock->p_buffer, p_spsblock->i_buffer );
- memcpy( &p_buf[p_spsblock->i_buffer], p_ppsblock->p_buffer,
- p_ppsblock->i_buffer );
+ memcpy( p_buf, p_spsblock->p_buffer, p_spsblock->i_buffer );
+ p_buf += p_spsblock->i_buffer;
+ if( p_spsextblock )
+ {
+ memcpy( p_buf, p_spsextblock->p_buffer, p_spsextblock->i_buffer );
+ p_buf += p_spsextblock->i_buffer;
+ }
+ memcpy( p_buf, p_ppsblock->p_buffer, p_ppsblock->i_buffer );
}
}
}
@@ -359,6 +372,8 @@ static int Open( vlc_object_t *p_this )
p_sys->pps[i].p_block = NULL;
}
p_sys->p_active_pps = NULL;
+ for( i = 0; i <= H264_SPSEXT_ID_MAX; i++ )
+ p_sys->spsext[i].p_block = NULL;
p_sys->i_recovery_frame_cnt = UINT_MAX;
h264_slice_init( &p_sys->slice );
@@ -477,6 +492,8 @@ static void Close( vlc_object_t *p_this )
StoreSPS( p_sys, i, NULL, NULL );
for( i = 0; i <= H264_PPS_ID_MAX; i++ )
StorePPS( p_sys, i, NULL, NULL );
+ for( i = 0; i <= H264_SPSEXT_ID_MAX; i++ )
+ StoreSPSEXT( p_sys, i, NULL );
packetizer_Clean( &p_sys->packetizer );
@@ -714,6 +731,11 @@ static block_t *ParseNALBlock( decoder_t *p_dec, bool *pb_ts_used, block_t *p_fr
break;
case H264_NAL_SPS_EXT:
+ PutSPSEXT( p_dec, p_frag );
+ if( p_sys->b_slice )
+ p_pic = OutputPicture( p_dec );
+ break;
+
case H264_NAL_PREFIX: /* first slice/VCL associated data */
case H264_NAL_SUBSET_SPS:
case H264_NAL_DEPTH_PS:
@@ -853,6 +875,10 @@ static block_t *OutputPicture( decoder_t *p_dec )
{
if( p_sys->sps[i].p_block )
block_ChainLastAppend( &pp_xpsnal_tail, block_Duplicate( p_sys->sps[i].p_block ) );
+ /* 7.4.1.2.3, shall be the next NAL unit after a sequence parameter set NAL unit
+ * having the same value of seq_parameter_set_id */
+ if( p_sys->spsext[i].p_block )
+ block_ChainLastAppend( &pp_xpsnal_tail, block_Duplicate( p_sys->spsext[i].p_block ) );
}
for( int i = 0; i < H264_PPS_ID_MAX && (b_need_sps_pps || p_sys->b_new_pps); i++ )
{
@@ -1110,6 +1136,37 @@ static void PutPPS( decoder_t *p_dec, block_t *p_frag )
StorePPS( p_sys, p_pps->i_id, p_frag, p_pps );
}
+static void PutSPSEXT( decoder_t *p_dec, block_t *p_frag )
+{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+ const uint8_t *p_buffer = p_frag->p_buffer;
+ size_t i_buffer = p_frag->i_buffer;
+
+ if( !hxxx_strip_AnnexB_startcode( &p_buffer, &i_buffer ) )
+ {
+ block_Release( p_frag );
+ return;
+ }
+
+ h264_sequence_parameter_set_extension_t *p_spsext =
+ h264_decode_sps_extension( p_buffer, i_buffer, true );
+ if( !p_spsext )
+ {
+ msg_Warn( p_dec, "invalid SPSEXT" );
+ block_Release( p_frag );
+ return;
+ }
+
+ /* We have a new SPSEXT */
+ if( !p_sys->spsext[p_spsext->i_sps_id].p_block )
+ msg_Dbg( p_dec, "found NAL_SPSEXT (sps_id=%d)", p_spsext->i_sps_id );
+
+ StoreSPSEXT( p_sys, p_spsext->i_sps_id, p_frag );
+
+ /* we don't need a decoded one */
+ h264_release_sps_extension( p_spsext );
+}
+
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 )
=====================================
modules/packetizer/h264_nal.c
=====================================
@@ -607,6 +607,20 @@ static bool h264_parse_picture_parameter_set_rbsp( bs_t *p_bs,
return true;
}
+static bool h264_parse_sequence_parameter_set_extension_rbsp( bs_t *p_bs,
+ h264_sequence_parameter_set_extension_t *p_sps_ext )
+{
+ p_sps_ext->i_sps_id = bs_read_ue( p_bs );
+ if( p_sps_ext->i_sps_id > H264_SPSEXT_ID_MAX )
+ return false;
+ return true;
+}
+
+void h264_release_sps_extension( h264_sequence_parameter_set_extension_t *p_sps_ext )
+{
+ free( p_sps_ext );
+}
+
#define IMPL_h264_generic_decode( name, h264type, decode, release ) \
h264type * name( const uint8_t *p_buf, size_t i_buf, bool b_escaped ) \
{ \
@@ -638,11 +652,16 @@ IMPL_h264_generic_decode( h264_decode_sps, h264_sequence_parameter_set_t,
IMPL_h264_generic_decode( h264_decode_pps, h264_picture_parameter_set_t,
h264_parse_picture_parameter_set_rbsp, h264_release_pps )
+IMPL_h264_generic_decode( h264_decode_sps_extension, h264_sequence_parameter_set_extension_t,
+ h264_parse_sequence_parameter_set_extension_rbsp, h264_release_sps_extension )
+
block_t *h264_NAL_to_avcC( uint8_t i_nal_length_size,
const uint8_t **pp_sps_buf,
const size_t *p_sps_size, uint8_t i_sps_count,
const uint8_t **pp_pps_buf,
- const size_t *p_pps_size, uint8_t i_pps_count )
+ const size_t *p_pps_size, uint8_t i_pps_count,
+ const uint8_t **pp_sps_ext_buf,
+ const size_t *p_sps_ext_size, uint8_t i_sps_ext_count )
{
/* The length of the NAL size is encoded using 1, 2 or 4 bytes */
if( i_nal_length_size != 1 && i_nal_length_size != 2
@@ -691,6 +710,26 @@ block_t *h264_NAL_to_avcC( uint8_t i_nal_length_size,
bo_add_mem( &bo, p_pps_size[i], pp_pps_buf[i] );
}
+ const uint8_t i_profile = pp_sps_buf[0][1];
+ if( i_profile == PROFILE_H264_HIGH ||
+ i_profile == PROFILE_H264_HIGH_10 ||
+ i_profile == PROFILE_H264_HIGH_422 ||
+ i_profile == PROFILE_H264_HIGH_444 )
+ {
+ h264_sequence_parameter_set_t *p_sps = h264_decode_sps( pp_sps_buf[0], p_sps_size[0], true );
+ bo_add_8( &bo, 0xfc | (p_sps ? p_sps->i_chroma_idc : 0) );
+ bo_add_8( &bo, 0xf8 | (p_sps ? (p_sps->i_bit_depth_luma - 8) : 0) );
+ bo_add_8( &bo, 0xf8 | (p_sps ? (p_sps->i_bit_depth_chroma - 8) : 0) );
+ if( p_sps )
+ h264_release_sps( p_sps );
+ bo_add_8( &bo, i_sps_ext_count );
+ for( size_t i = 0; i < i_sps_ext_count; ++i )
+ {
+ bo_add_16be( &bo, p_sps_ext_size[i] );
+ bo_add_mem( &bo, p_sps_ext_size[i], pp_sps_ext_buf[i] );
+ }
+ }
+
return bo.b;
}
=====================================
modules/packetizer/h264_nal.h
=====================================
@@ -44,6 +44,7 @@
#define H264_SPS_ID_MAX (31)
#define H264_PPS_ID_MAX (255)
+#define H264_SPSEXT_ID_MAX H264_SPS_ID_MAX
enum h264_nal_unit_type_e
{
@@ -76,12 +77,15 @@ enum h264_nal_unit_type_e
typedef struct h264_sequence_parameter_set_t h264_sequence_parameter_set_t;
typedef struct h264_picture_parameter_set_t h264_picture_parameter_set_t;
+typedef struct h264_sequence_parameter_set_extension_t h264_sequence_parameter_set_extension_t;
h264_sequence_parameter_set_t * h264_decode_sps( const uint8_t *, size_t, bool );
h264_picture_parameter_set_t * h264_decode_pps( const uint8_t *, size_t, bool );
+h264_sequence_parameter_set_extension_t * h264_decode_sps_extension( const uint8_t *, size_t, bool );
void h264_release_sps( h264_sequence_parameter_set_t * );
void h264_release_pps( h264_picture_parameter_set_t * );
+void h264_release_sps_extension( h264_sequence_parameter_set_extension_t * );
struct h264_sequence_parameter_set_t
{
@@ -148,6 +152,11 @@ struct h264_picture_parameter_set_t
uint8_t weighted_bipred_idc;
};
+struct h264_sequence_parameter_set_extension_t
+{
+ uint8_t i_sps_id;
+};
+
/*
AnnexB : [\x00] \x00 \x00 \x01 Prefixed NAL
AVC Sample format : NalLengthSize encoded size prefixed NAL
@@ -175,7 +184,9 @@ block_t *h264_NAL_to_avcC( uint8_t i_nal_length_size,
const uint8_t **pp_sps_buf,
const size_t *p_sps_size, uint8_t i_sps_count,
const uint8_t **pp_pps_buf,
- const size_t *p_pps_size, uint8_t i_pps_count );
+ const size_t *p_pps_size, uint8_t i_pps_count,
+ const uint8_t **pp_sps_ext_buf,
+ const size_t *p_sps_ext_size, uint8_t i_sps_ext_count);
/* Convert AVCDecoderConfigurationRecord SPS/PPS to Annex B format */
uint8_t * h264_avcC_to_AnnexB_NAL( const uint8_t *p_buf, size_t i_buf,
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/4c537f29b0ca27377badf7b7ed77bc4b0b4a9f32...cd18bd167d221412576d974673cd3f0718a80b36
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/4c537f29b0ca27377badf7b7ed77bc4b0b4a9f32...cd18bd167d221412576d974673cd3f0718a80b36
You're receiving this email because of your account on code.videolan.org.
More information about the vlc-commits
mailing list