[vlc-commits] [Git][videolan/vlc][master] 6 commits: packetizer: h264: refactor sps/pps duplication
Jean-Baptiste Kempf (@jbk)
gitlab at videolan.org
Mon Apr 10 01:48:56 UTC 2023
Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC
Commits:
3ea4bcad by Francois Cartegnie at 2023-04-09T16:17:08+00:00
packetizer: h264: refactor sps/pps duplication
- - - - -
86393842 by Francois Cartegnie at 2023-04-09T16:17:08+00:00
packetizer: h264: compare sps/pps before replacement
- - - - -
c85581f4 by Francois Cartegnie at 2023-04-09T16:17:08+00:00
packetizer: h264: add h264_get_xps_id shortcut
- - - - -
21a329cc by Francois Cartegnie at 2023-04-09T16:17:08+00:00
packetizer: h264: refactor sps/pps handling
- - - - -
d8898afb by Francois Cartegnie at 2023-04-09T16:17:08+00:00
packetizer: h264: refactor gathering sps/pps
- - - - -
ed97dd9f by Francois Cartegnie at 2023-04-09T16:17:08+00:00
packetizer: h264: add all sps/pps sets to extradata
- - - - -
3 changed files:
- modules/packetizer/h264.c
- modules/packetizer/h264_nal.c
- modules/packetizer/h264_nal.h
Changes:
=====================================
modules/packetizer/h264.c
=====================================
@@ -152,9 +152,8 @@ static block_t * PacketizeDrain( void *p_private );
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 void ReleaseXPS( decoder_sys_t *p_sys );
+static bool PutXPS( decoder_t *p_dec, uint8_t i_nal_type, 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 * );
@@ -164,38 +163,33 @@ static const uint8_t p_h264_startcode[3] = { 0x00, 0x00, 0x01 };
/*****************************************************************************
* Helpers
*****************************************************************************/
-
-static void StoreSPS( decoder_sys_t *p_sys, uint8_t i_id,
- block_t *p_block, h264_sequence_parameter_set_t *p_sps )
-{
- if( p_sys->sps[i_id].p_block )
- block_Release( p_sys->sps[i_id].p_block );
- if( p_sys->sps[i_id].p_sps )
- h264_release_sps( p_sys->sps[i_id].p_sps );
- if( p_sys->sps[i_id].p_sps == p_sys->p_active_sps )
- p_sys->p_active_sps = NULL;
- p_sys->sps[i_id].p_block = p_block;
- p_sys->sps[i_id].p_sps = p_sps;
-}
-
-static void StorePPS( decoder_sys_t *p_sys, uint8_t i_id,
- block_t *p_block, h264_picture_parameter_set_t *p_pps )
+static void LastAppendXPSCopy( const block_t *p_block, block_t ***ppp_last )
{
- if( p_sys->pps[i_id].p_block )
- block_Release( p_sys->pps[i_id].p_block );
- if( p_sys->pps[i_id].p_pps )
- h264_release_pps( p_sys->pps[i_id].p_pps );
- if( p_sys->pps[i_id].p_pps == p_sys->p_active_pps )
- p_sys->p_active_pps = NULL;
- p_sys->pps[i_id].p_block = p_block;
- p_sys->pps[i_id].p_pps = p_pps;
+ if( !p_block )
+ return;
+ block_t *p_dup = block_Alloc( 4 + p_block->i_buffer );
+ if( p_dup )
+ {
+ memcpy( &p_dup->p_buffer[0], annexb_startcode4, 4 );
+ memcpy( &p_dup->p_buffer[4], p_block->p_buffer, p_block->i_buffer );
+ block_ChainLastAppend( ppp_last, p_dup );
+ }
}
-static void StoreSPSEXT( decoder_sys_t *p_sys, uint8_t i_id, block_t *p_block )
+static block_t * GatherSets( decoder_sys_t *p_sys, bool b_need_sps, bool b_need_pps )
{
- 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;
+ block_t *p_xpsnal = NULL;
+ block_t **pp_xpsnal_tail = &p_xpsnal;
+ for( int i = 0; i <= H264_SPS_ID_MAX && b_need_sps; i++ )
+ {
+ LastAppendXPSCopy( p_sys->sps[i].p_block, &pp_xpsnal_tail );
+ /* 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 */
+ LastAppendXPSCopy( p_sys->spsext[i].p_block, &pp_xpsnal_tail );
+ }
+ for( int i = 0; i < H264_PPS_ID_MAX && b_need_pps; i++ )
+ LastAppendXPSCopy( p_sys->pps[i].p_block, &pp_xpsnal_tail );
+ return p_xpsnal;
}
static void ActivateSets( decoder_t *p_dec, const h264_sequence_parameter_set_t *p_sps,
@@ -250,29 +244,18 @@ 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 = 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 )
+ block_t *p_xpsblocks = GatherSets( p_sys, true, true );
+ if( p_xpsblocks )
{
- 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 );
+ size_t i_total;
+ block_ChainProperties( p_xpsblocks, NULL, &i_total, NULL );
+ p_dec->fmt_out.p_extra = malloc( i_total );
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, 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 );
+ p_dec->fmt_out.i_extra = i_total;
+ block_ChainExtract( p_xpsblocks, p_dec->fmt_out.p_extra, i_total );
}
+ block_ChainRelease( p_xpsblocks );
}
}
}
@@ -485,15 +468,9 @@ static void Close( vlc_object_t *p_this )
{
decoder_t *p_dec = (decoder_t*)p_this;
decoder_sys_t *p_sys = p_dec->p_sys;
- int i;
DropStoredNAL( p_sys );
- for( i = 0; i <= H264_SPS_ID_MAX; i++ )
- 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 );
+ ReleaseXPS( p_sys );
packetizer_Clean( &p_sys->packetizer );
@@ -714,15 +691,9 @@ static block_t *ParseNALBlock( decoder_t *p_dec, bool *pb_ts_used, block_t *p_fr
/* Stored for insert on keyframes */
if( i_nal_type == H264_NAL_SPS )
- {
- PutSPS( p_dec, p_frag );
- p_sys->b_new_sps = true;
- }
+ p_sys->b_new_sps |= PutXPS( p_dec, i_nal_type, p_frag );
else
- {
- PutPPS( p_dec, p_frag );
- p_sys->b_new_pps = true;
- }
+ p_sys->b_new_pps |= PutXPS( p_dec, i_nal_type, p_frag );
break;
case H264_NAL_SEI:
@@ -734,7 +705,7 @@ 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 );
+ PutXPS( p_dec, i_nal_type, p_frag );
if( p_sys->b_slice )
p_pic = OutputPicture( p_dec );
break;
@@ -875,25 +846,8 @@ static block_t *OutputPicture( decoder_t *p_dec )
}
/* Gather PPS/SPS if required */
- block_t *p_xpsnal = NULL;
- block_t **pp_xpsnal_tail = &p_xpsnal;
- if( b_need_sps_pps || p_sys->b_new_sps || p_sys->b_new_pps )
- {
- for( int i = 0; i <= H264_SPS_ID_MAX && (b_need_sps_pps || p_sys->b_new_sps); i++ )
- {
- 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++ )
- {
- if( p_sys->pps[i].p_block )
- block_ChainLastAppend( &pp_xpsnal_tail, block_Duplicate( p_sys->pps[i].p_block ) );
- }
- }
+ block_t *p_xpsnal = GatherSets( p_sys, b_need_sps_pps|p_sys->b_new_sps,
+ b_need_sps_pps|p_sys->b_new_pps );
/* Now rebuild NAL Sequence, inserting PPS/SPS if any */
if( p_sys->leading.p_head &&
@@ -1089,90 +1043,130 @@ static block_t *OutputPicture( decoder_t *p_dec )
return p_pic;
}
-static void PutSPS( decoder_t *p_dec, block_t *p_frag )
+static int CmpXPS( const block_t *p_ref, const block_t *p_nal )
{
- decoder_sys_t *p_sys = p_dec->p_sys;
+ return p_ref == NULL ||
+ p_ref->i_buffer != p_nal->i_buffer ||
+ memcmp( p_ref->p_buffer, p_nal->p_buffer, p_nal->i_buffer );
+}
+
+#define wrap_h264_xps_decode(funcname ) \
+ static void *funcname ## _wrapper ( const uint8_t *a, size_t b, bool c ) \
+ { return funcname(a,b,c); }
- const uint8_t *p_buffer = p_frag->p_buffer;
- size_t i_buffer = p_frag->i_buffer;
+wrap_h264_xps_decode(h264_decode_sps)
+wrap_h264_xps_decode(h264_decode_pps)
- if( !hxxx_strip_AnnexB_startcode( &p_buffer, &i_buffer ) )
+#define wrap_h264_xps_release(funcname, typecast) \
+ static void funcname ## _wrapper ( void *a ) { funcname((typecast *)a); }
+
+wrap_h264_xps_release(h264_release_sps, h264_sequence_parameter_set_t)
+wrap_h264_xps_release(h264_release_pps, h264_picture_parameter_set_t)
+
+static void ReleaseXPS( decoder_sys_t *p_sys )
+{
+ for( int i = 0; i <= H264_SPS_ID_MAX; i++ )
{
- block_Release( p_frag );
- return;
+ if( !p_sys->sps[i].p_block )
+ continue;
+ block_Release( p_sys->sps[i].p_block );
+ h264_release_sps( p_sys->sps[i].p_sps );
}
-
- h264_sequence_parameter_set_t *p_sps = h264_decode_sps( p_buffer, i_buffer, true );
- if( !p_sps )
+ for( int i = 0; i <= H264_PPS_ID_MAX; i++ )
{
- msg_Warn( p_dec, "invalid SPS" );
- block_Release( p_frag );
- return;
+ if( !p_sys->pps[i].p_block )
+ continue;
+ block_Release( p_sys->pps[i].p_block );
+ h264_release_pps( p_sys->pps[i].p_pps );
}
-
- /* We have a new SPS */
- if( !p_sys->sps[p_sps->i_id].p_sps )
- msg_Dbg( p_dec, "found NAL_SPS (sps_id=%d)", p_sps->i_id );
-
- StoreSPS( p_sys, p_sps->i_id, p_frag, p_sps );
+ for( int i = 0; i <= H264_SPSEXT_ID_MAX; i++ )
+ {
+ if( p_sys->spsext[i].p_block )
+ block_Release( p_sys->spsext[i].p_block );
+ }
+ p_sys->p_active_sps = NULL;
+ p_sys->p_active_pps = NULL;
}
-static void PutPPS( decoder_t *p_dec, block_t *p_frag )
+static bool PutXPS( decoder_t *p_dec, uint8_t i_nal_type, 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 ) )
+ uint8_t i_id;
+ if( !hxxx_strip_AnnexB_startcode( (const uint8_t **)&p_frag->p_buffer,
+ &p_frag->i_buffer ) ||
+ !h264_get_xps_id( p_frag->p_buffer, p_frag->i_buffer, &i_id ) )
{
block_Release( p_frag );
- return;
+ return false;
}
- h264_picture_parameter_set_t *p_pps = h264_decode_pps( p_buffer, i_buffer, true );
- if( !p_pps )
+ const char * rgsz_types[3] = {"SPS", "PPS", "SPSEXT"};
+ const char *psz_type;
+ block_t **pp_block_dst;
+ /* all depend on pp_xps_dst */
+ void **pp_xps_dst = NULL;
+ const void **pp_active; /* optional */
+ void * (* pf_decode_xps)(const uint8_t *, size_t, bool);
+ void (* pf_release_xps)(void *);
+
+ switch( i_nal_type )
{
- msg_Warn( p_dec, "invalid PPS" );
- block_Release( p_frag );
- return;
+ case H264_NAL_SPS:
+ psz_type = rgsz_types[0];
+ pp_active = (const void **) &p_sys->p_active_sps;
+ pp_block_dst = &p_sys->sps[i_id].p_block;
+ pp_xps_dst = (void **) &p_sys->sps[i_id].p_sps;
+ pf_decode_xps = h264_decode_sps_wrapper;
+ pf_release_xps = h264_release_sps_wrapper;
+ break;
+ case H264_NAL_PPS:
+ psz_type = rgsz_types[1];
+ pp_active = (const void **) &p_sys->p_active_pps;
+ pp_block_dst = &p_sys->pps[i_id].p_block;
+ pp_xps_dst = (void **) &p_sys->pps[i_id].p_pps;
+ pf_decode_xps = h264_decode_pps_wrapper;
+ pf_release_xps = h264_release_pps_wrapper;
+ break;
+ case H264_NAL_SPS_EXT:
+ psz_type = rgsz_types[2];
+ pp_block_dst = &p_sys->spsext[i_id].p_block;
+ break;
+ default:
+ block_Release( p_frag );
+ return false;
}
- /* We have a new PPS */
- if( !p_sys->pps[p_pps->i_id].p_pps )
- msg_Dbg( p_dec, "found NAL_PPS (pps_id=%d sps_id=%d)", p_pps->i_id, p_pps->i_sps_id );
-
- 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 ) )
+ if( !CmpXPS( *pp_block_dst, p_frag ) )
{
block_Release( p_frag );
- return;
+ return false;
}
- h264_sequence_parameter_set_extension_t *p_spsext =
- h264_decode_sps_extension( p_buffer, i_buffer, true );
- if( !p_spsext )
+ msg_Dbg( p_dec, "found NAL_%s (id=%" PRIu8 ")", psz_type, i_id );
+
+ if( pp_xps_dst != NULL )
{
- msg_Warn( p_dec, "invalid SPSEXT" );
- block_Release( p_frag );
- return;
+ void *p_xps = pf_decode_xps( p_frag->p_buffer, p_frag->i_buffer, true );
+ if( !p_xps )
+ {
+ block_Release( p_frag );
+ return false;
+ }
+ if( *pp_xps_dst )
+ {
+ if( pp_active && *pp_active == *pp_xps_dst )
+ *pp_active = NULL;
+ pf_release_xps( *pp_xps_dst );
+ }
+ *pp_xps_dst = p_xps;
}
- /* 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 );
+ if( *pp_block_dst )
+ block_Release( *pp_block_dst );
+ *pp_block_dst = p_frag;
- StoreSPSEXT( p_sys, p_spsext->i_sps_id, p_frag );
-
- /* we don't need a decoded one */
- h264_release_sps_extension( p_spsext );
+ return true;
}
static void GetSPSPPS( uint8_t i_pps_id, void *priv,
=====================================
modules/packetizer/h264_nal.c
=====================================
@@ -740,6 +740,41 @@ block_t *h264_NAL_to_avcC( uint8_t i_nal_length_size,
return bo.b;
}
+bool h264_get_xps_id( const uint8_t *p_buf, size_t i_buf, uint8_t *pi_id )
+{
+ if( i_buf < 2 )
+ return false;
+
+ /* No need to lookup convert from emulation for that data */
+ uint8_t i_max, i_offset;
+ switch( h264_getNALType(p_buf) )
+ {
+ case H264_NAL_SPS:
+ i_offset = 1 + 3 /* profile constraint level */;
+ i_max = H264_SPS_ID_MAX;
+ break;
+ case H264_NAL_PPS:
+ i_offset = 1;
+ i_max = H264_PPS_ID_MAX;
+ break;
+ case H264_NAL_SPS_EXT:
+ i_offset = 1;
+ i_max = H264_SPSEXT_ID_MAX;
+ break;
+ default:
+ return false;
+ }
+
+ if( i_buf <= i_offset )
+ return false;
+
+ bs_t bs;
+ bs_init( &bs, &p_buf[i_offset], i_buf - i_offset );
+ *pi_id = bs_read_ue( &bs );
+
+ return !bs_error( &bs ) && *pi_id <= i_max;
+}
+
static const h264_level_limits_t * h264_get_level_limits( const h264_sequence_parameter_set_t *p_sps )
{
uint16_t i_level_number = p_sps->i_level;
=====================================
modules/packetizer/h264_nal.h
=====================================
@@ -89,6 +89,8 @@ 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;
+bool h264_get_xps_id(const uint8_t *p_nalbuf, size_t i_nalbuf, uint8_t *pi_id);
+
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 );
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/120ce6a393099f95e414785bf45b12cd84d67742...ed97dd9fb80a2d02de8c3b756aaeb263f8b807bb
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/120ce6a393099f95e414785bf45b12cd84d67742...ed97dd9fb80a2d02de8c3b756aaeb263f8b807bb
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list