[vlc-commits] [Git][videolan/vlc][master] 23 commits: packetizer: vc1: avoid extra indirection
Steve Lhomme (@robUx4)
gitlab at videolan.org
Sun May 24 16:35:50 UTC 2026
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
060a05c6 by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer: vc1: avoid extra indirection
- - - - -
baecb2f1 by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizers: use the enum for packetizer state
It's easier to debug.
Not for dts.c as it uses more states.
- - - - -
d42c1245 by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: add comments
- - - - -
04c8b91b by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: fix documentation
When pp_block is NULL we are draining, not flushing.
Flushing is done via packetizer_Flush().
- - - - -
c36a28f8 by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: rename i_startcode to startcode_len and use as size_t
- - - - -
cb6ca767 by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: replace internal state by a boolean
We're either synchronized or not. Not other state is used.
No need for a switch case for 2 states. Especially as the first case
falls through the second one.
- - - - -
621526cf by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: fix indentation
- - - - -
8cb71b37 by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: continue loop early when we don't have minimum size
This is the same code as when p_pic is checked for NULL later.
We don't need the else anymore.
- - - - -
a9389c14 by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: don't allocate a block if we know the size is too small
Just ask for more data.
block_GetBytes() was consuming the bytes but we were not using them.
- - - - -
6895de59 by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: factorize sync flag reset
When reaching this state we reset the synched state so in the next loop we look
for 2 startcode and send the data between these 2 consecutive startcodes.
After this point we always exit or continue the loop with the synched flag
reset. That means even though we may know there's a second startcode we will
still look for it in the next call/loop.
- - - - -
fdfc57be by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: reorder tests to exit early
The synched flag won't change on error.
We won't skip the junk data before the startcode but since we didn't find one
we should not be skipping data as some of the data we have may be part of the
next startcode. If anything we should skip data except the startcode length
minus 1.
- - - - -
904f5515 by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: use local variables to read the startcode offsets
So it's clearer between the 2 calls what we're keeping.
The code strictly equivalent to the previous code.
- - - - -
9bf002d3 by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: keep the lookup offset when asking for more data
Since we don't have a startcode we don't know if the data we have may
or may not have part of the startcode.
- - - - -
646352de by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: keep the lookup offset when asking for more data on second startcode
p_pack->i_offset is positioned at the first startcode. We should stay there until
we have a second startcode. We are not draining.
- - - - -
3f1bac03 by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: keep the lookup offset when asking for more data on small output
- - - - -
f57e8e86 by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: start looking for the second startcode at start+code length
p_pack->i_offset always points to the location of the first startcode whether
we found it because b_synched was false or from a previous lookup.
We are going to look for the next one after the one we found.
No need to reuse the data of the startcode we found. Especially
if it finds a startcode in there, the same data will be used twice.
- - - - -
ed11d4bd by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: skip unused bytes when draining
If we are draining but there's is not enough data to feed we should ensure
we don't use these data in the future.
- - - - -
58b7c0e3 by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: always set lookup offset to 0 when draining
If there's no remaining data to drain it was 0 anyway.
If there is data to drain but not enough, we will return NULL and skip the
unused data.
If there is data to drain we will use it or there will be an error but we
should not use these data anyway.
- - - - -
12c4a8eb by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: skip bytes when the block created would be too small
We cannot return this block, we should start again starting at the second startcode.
- - - - -
1e833371 by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: skip bytes when the block allocation fail
We can't output this block, maybe it's too big, we should not try
to read it will we are fed more data.
- - - - -
05fad79b by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: keep the lookup offset when found the second startcode
In the normal case where we return the block between the 2 startcodes, it will
be reset to 0 at the end.
In some error cases we skip data and reset it to 0.
And after that block_GetBytes() will eat some of the data anyway.
- - - - -
7aaa0387 by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: remove always 0 i_offset
We always skip the the beginning of the (firs) startcode when we found one.
- - - - -
bd829f62 by Steve Lhomme at 2026-05-24T15:35:12+00:00
packetizer_helper: add FIXME on discontinuity
The bytestream may contain multiple packetized blocks but we only return one
when receiving a block with discontinuity/corrupted.
- - - - -
7 changed files:
- modules/packetizer/a52.c
- modules/packetizer/flac.c
- modules/packetizer/mlp.c
- modules/packetizer/mpeg4audio.c
- modules/packetizer/mpegaudio.c
- modules/packetizer/packetizer_helper.h
- modules/packetizer/vc1.c
Changes:
=====================================
modules/packetizer/a52.c
=====================================
@@ -58,7 +58,7 @@ typedef struct
/*
* Input properties
*/
- int i_state;
+ enum vlc_packetizer_state i_state;
block_bytestream_t bytestream;
@@ -332,6 +332,9 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
*pp_block = block_BytestreamPop( &p_sys->bytestream );
return p_out_buffer;
+
+ case STATE_CUSTOM_FIRST:
+ break; // do nothing
}
}
}
=====================================
modules/packetizer/flac.c
=====================================
@@ -58,7 +58,7 @@ typedef struct
/*
* Input properties
*/
- int i_state;
+ enum vlc_packetizer_state i_state;
block_bytestream_t bytestream;
size_t i_offset;
@@ -572,6 +572,9 @@ static block_t *Packetize(decoder_t *p_dec, block_t **pp_block)
*pp_block = block_BytestreamPop(&p_sys->bytestream);
return out;
+
+ case STATE_CUSTOM_FIRST:
+ break; // do nothing
}
return NULL;
=====================================
modules/packetizer/mlp.c
=====================================
@@ -73,7 +73,7 @@ typedef struct
/*
* Input properties
*/
- int i_state;
+ enum vlc_packetizer_state i_state;
block_bytestream_t bytestream;
@@ -457,6 +457,9 @@ static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
p_sys->i_state = STATE_NOSYNC;
return p_out_buffer;
+
+ case STATE_CUSTOM_FIRST:
+ break; // do nothing
}
}
=====================================
modules/packetizer/mpeg4audio.c
=====================================
@@ -63,7 +63,7 @@ typedef struct
/*
* Input properties
*/
- int i_state;
+ enum vlc_packetizer_state i_state;
int i_type;
block_bytestream_t bytestream;
@@ -857,6 +857,9 @@ static block_t *PacketizeStreamBlock(decoder_t *p_dec, block_t **pp_block)
p_sys->i_state = STATE_NOSYNC;
return p_out_buffer;
+
+ case STATE_CUSTOM_FIRST:
+ break; // do nothing
}
return NULL;
=====================================
modules/packetizer/mpegaudio.c
=====================================
@@ -50,7 +50,7 @@ typedef struct
/*
* Input properties
*/
- int i_state;
+ enum vlc_packetizer_state i_state;
block_bytestream_t bytestream;
@@ -437,6 +437,9 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
block_Release(p_block);
return p_out_buffer;
+
+ case STATE_CUSTOM_FIRST:
+ break; // do nothing
}
}
=====================================
modules/packetizer/packetizer_helper.h
=====================================
@@ -25,7 +25,7 @@
#include <vlc_block.h>
-enum
+enum vlc_packetizer_state
{
STATE_NOSYNC,
STATE_SYNC,
@@ -43,11 +43,10 @@ typedef int (*packetizer_validate_t)( void *p_private, block_t * );
typedef struct
{
- int i_state;
block_bytestream_t bytestream;
- size_t i_offset;
+ bool b_synched;
- int i_startcode;
+ size_t startcode_len;
const uint8_t *p_startcode;
block_startcode_helper_t pf_startcode_helper;
@@ -65,7 +64,7 @@ typedef struct
} packetizer_t;
static inline void packetizer_Init( packetizer_t *p_pack,
- const uint8_t *p_startcode, int i_startcode,
+ const uint8_t *p_startcode, size_t i_startcode,
block_startcode_helper_t pf_start_helper,
const uint8_t *p_au_prepend, int i_au_prepend,
unsigned i_au_min_size,
@@ -75,15 +74,14 @@ static inline void packetizer_Init( packetizer_t *p_pack,
packetizer_drain_t pf_drain,
void *p_private )
{
- p_pack->i_state = STATE_NOSYNC;
+ p_pack->b_synched = false;
block_BytestreamInit( &p_pack->bytestream );
- p_pack->i_offset = 0;
p_pack->i_au_prepend = i_au_prepend;
p_pack->p_au_prepend = p_au_prepend;
p_pack->i_au_min_size = i_au_min_size;
- p_pack->i_startcode = i_startcode;
+ p_pack->startcode_len = i_startcode;
p_pack->p_startcode = p_startcode;
p_pack->pf_startcode_helper = pf_start_helper;
p_pack->pf_reset = pf_reset;
@@ -100,12 +98,15 @@ static inline void packetizer_Clean( packetizer_t *p_pack )
static inline void packetizer_Flush( packetizer_t *p_pack )
{
- p_pack->i_state = STATE_NOSYNC;
+ p_pack->b_synched = false;
block_BytestreamEmpty( &p_pack->bytestream );
- p_pack->i_offset = 0;
p_pack->pf_reset( p_pack->p_private, true );
}
+/**
+ * Return a block of the data between 2 startcodes in the block stream.
+ * The block contains the startcode at the beginning.
+ */
static block_t *packetizer_PacketizeBlock( packetizer_t *p_pack, block_t **pp_block )
{
block_t *p_block = ( pp_block ) ? *pp_block : NULL;
@@ -117,11 +118,10 @@ static block_t *packetizer_PacketizeBlock( packetizer_t *p_pack, block_t **pp_bl
{
block_t *p_drained = packetizer_PacketizeBlock( p_pack, NULL );
if( p_drained )
- return p_drained;
+ return p_drained; // FIXME do we lose p_block ? Can we output more than one drain output ?
- p_pack->i_state = STATE_NOSYNC;
+ p_pack->b_synched = false;
block_BytestreamEmpty( &p_pack->bytestream );
- p_pack->i_offset = 0;
p_pack->pf_reset( p_pack->p_private, false );
}
@@ -133,112 +133,112 @@ static block_t *packetizer_PacketizeBlock( packetizer_t *p_pack, block_t **pp_bl
bool b_used_ts;
block_t *p_pic;
- switch( p_pack->i_state )
+ if( !p_pack->b_synched )
{
- case STATE_NOSYNC:
+ size_t block_startcode_offset = 0;
/* Find a startcode */
- if( !block_FindStartcodeFromOffset( &p_pack->bytestream, &p_pack->i_offset,
- p_pack->p_startcode, p_pack->i_startcode,
+ if( block_FindStartcodeFromOffset( &p_pack->bytestream, &block_startcode_offset,
+ p_pack->p_startcode, p_pack->startcode_len,
p_pack->pf_startcode_helper, NULL ) )
- p_pack->i_state = STATE_NEXT_SYNC;
-
- if( p_pack->i_offset )
{
- block_SkipBytes( &p_pack->bytestream, p_pack->i_offset );
- p_pack->i_offset = 0;
- block_BytestreamFlush( &p_pack->bytestream );
- }
-
- if( p_pack->i_state != STATE_NEXT_SYNC )
return NULL; /* Need more data */
+ }
- p_pack->i_offset = 1; /* To find next startcode */
- /* fallthrough */
+ p_pack->b_synched = true;
- case STATE_NEXT_SYNC:
- /* Find the next startcode */
- if( block_FindStartcodeFromOffset( &p_pack->bytestream, &p_pack->i_offset,
- p_pack->p_startcode, p_pack->i_startcode,
- p_pack->pf_startcode_helper, NULL ) )
+ if( block_startcode_offset )
{
- if( pp_block /* not flushing */ || !p_pack->bytestream.p_chain )
- return NULL; /* Need more data */
-
- /* When flushing and we don't find a startcode, suppose that
- * the data extend up to the end */
- p_pack->i_offset = block_BytestreamRemaining(&p_pack->bytestream);
- if( p_pack->i_offset == 0 )
- return NULL;
-
- if( p_pack->i_offset <= (size_t)p_pack->i_startcode &&
- (p_pack->bytestream.p_block->i_flags & BLOCK_FLAG_AU_END) == 0 )
- return NULL;
+ // remove junk data before the startcode
+ block_SkipBytes( &p_pack->bytestream, block_startcode_offset );
+ block_BytestreamFlush( &p_pack->bytestream );
}
+ }
- block_BytestreamFlush( &p_pack->bytestream );
+ size_t block_size = p_pack->startcode_len;
+ /* Find the next startcode */
+ if( block_FindStartcodeFromOffset( &p_pack->bytestream, &block_size,
+ p_pack->p_startcode, p_pack->startcode_len,
+ p_pack->pf_startcode_helper, NULL ) )
+ {
+ if( pp_block /* not draining */ || !p_pack->bytestream.p_chain )
+ {
+ return NULL; /* Need more data */
+ }
- /* Get the new fragment and set the pts/dts */
- block_t *p_block_bytestream = p_pack->bytestream.p_block;
+ /* When draining and we don't find a second startcode, suppose that
+ * the data extend up to the end of the bytestream */
+ block_size = block_BytestreamRemaining(&p_pack->bytestream);
+ if( block_size == 0 )
+ return NULL;
- p_pic = block_Alloc( p_pack->i_offset + p_pack->i_au_prepend );
- if( p_pic == NULL )
+ if( block_size <= p_pack->startcode_len &&
+ (p_pack->bytestream.p_block->i_flags & BLOCK_FLAG_AU_END) == 0 )
{
- p_pack->i_state = STATE_NOSYNC;
+ block_SkipBytes( &p_pack->bytestream, block_size );
return NULL;
}
- p_pic->i_pts = p_block_bytestream->i_pts;
- p_pic->i_dts = p_block_bytestream->i_dts;
+ }
- /* Do not wait for next sync code if notified block ends AU */
- if( (p_block_bytestream->i_flags & BLOCK_FLAG_AU_END) &&
- p_block_bytestream->i_buffer == p_pack->i_offset )
- {
- p_pic->i_flags |= BLOCK_FLAG_AU_END;
- }
+ block_BytestreamFlush( &p_pack->bytestream );
+ p_pack->b_synched = false; // look for 2 startcodes on next call/loop
- block_GetBytes( &p_pack->bytestream, &p_pic->p_buffer[p_pack->i_au_prepend],
- p_pic->i_buffer - p_pack->i_au_prepend );
- if( p_pack->i_au_prepend > 0 )
- memcpy( p_pic->p_buffer, p_pack->p_au_prepend, p_pack->i_au_prepend );
+ if ( block_size + p_pack->i_au_prepend < p_pack->i_au_min_size )
+ {
+ // we found 2 startcodes but the amount of data between them is too
+ // small, discard data until the second startcode
+ block_SkipBytes( &p_pack->bytestream, block_size );
+ return NULL;
+ }
- p_pack->i_offset = 0;
+ /* Get the new fragment and set the pts/dts */
+ block_t *p_block_bytestream = p_pack->bytestream.p_block;
- /* Parse the NAL */
- if( p_pic->i_buffer < p_pack->i_au_min_size )
- {
- block_Release( p_pic );
- p_pic = NULL;
- }
- else
- {
- p_pic = p_pack->pf_parse( p_pack->p_private, &b_used_ts, p_pic );
- if( b_used_ts )
- {
- p_block_bytestream->i_dts = VLC_TICK_INVALID;
- p_block_bytestream->i_pts = VLC_TICK_INVALID;
- }
- }
+ p_pic = block_Alloc( block_size + p_pack->i_au_prepend );
+ if( p_pic == NULL )
+ {
+ // we can't output this block, maybe it's too big, we should not try
+ // to read it will we are fed more data
+ block_SkipBytes( &p_pack->bytestream, block_size );
+ return NULL;
+ }
+ p_pic->i_pts = p_block_bytestream->i_pts;
+ p_pic->i_dts = p_block_bytestream->i_dts;
- if( !p_pic )
- {
- p_pack->i_state = STATE_NOSYNC;
- break;
- }
- if( p_pack->pf_validate( p_pack->p_private, p_pic ) )
- {
- p_pack->i_state = STATE_NOSYNC;
- block_Release( p_pic );
- break;
- }
+ /* Do not wait for next sync code if notified block ends AU */
+ if( (p_block_bytestream->i_flags & BLOCK_FLAG_AU_END) &&
+ p_block_bytestream->i_buffer == block_size )
+ {
+ p_pic->i_flags |= BLOCK_FLAG_AU_END;
+ }
- /* So p_block doesn't get re-added several times */
- if( pp_block )
- *pp_block = block_BytestreamPop( &p_pack->bytestream );
+ block_GetBytes( &p_pack->bytestream, &p_pic->p_buffer[p_pack->i_au_prepend],
+ p_pic->i_buffer - p_pack->i_au_prepend );
+ if( p_pack->i_au_prepend > 0 )
+ memcpy( p_pic->p_buffer, p_pack->p_au_prepend, p_pack->i_au_prepend );
- p_pack->i_state = STATE_NOSYNC;
+ /* Parse the NAL */
+ p_pic = p_pack->pf_parse( p_pack->p_private, &b_used_ts, p_pic );
+ if( b_used_ts )
+ {
+ p_block_bytestream->i_dts = VLC_TICK_INVALID;
+ p_block_bytestream->i_pts = VLC_TICK_INVALID;
+ }
- return p_pic;
+ if( !p_pic )
+ {
+ continue;
}
+ if( p_pack->pf_validate( p_pack->p_private, p_pic ) )
+ {
+ block_Release( p_pic );
+ continue;
+ }
+
+ /* So p_block doesn't get re-added several times */
+ if( pp_block )
+ *pp_block = block_BytestreamPop( &p_pack->bytestream );
+
+ return p_pic;
}
}
@@ -275,10 +275,8 @@ static inline void packetizer_Header( packetizer_t *p_pack,
while( ( p_pic = packetizer_Packetize( p_pack, NULL ) ) )
block_Release( p_pic );
- p_pack->i_state = STATE_NOSYNC;
+ p_pack->b_synched = false;
block_BytestreamEmpty( &p_pack->bytestream );
- p_pack->i_offset = 0;
}
#endif
-
=====================================
modules/packetizer/vc1.c
=====================================
@@ -125,12 +125,11 @@ static block_t *Packetize( decoder_t *p_dec, block_t **pp_block );
static void Flush( decoder_t * );
static void PacketizeReset( void *p_private, bool b_broken );
-static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t * );
static int PacketizeValidate( void *p_private, block_t * );
static block_t *PacketizeDrain( void *p_private );
static block_t *OutputFrame( decoder_t *p_dec );
-static block_t *ParseIDU( decoder_t *p_dec, bool *pb_ts_used, block_t *p_frag );
+static block_t *ParseIDU( void *, bool *pb_ts_used, block_t *p_frag );
static block_t *GetCc( decoder_t *p_dec, decoder_cc_desc_t * );
static const uint8_t p_vc1_startcode[3] = { 0x00, 0x00, 0x01 };
@@ -161,7 +160,7 @@ static int Open( vlc_object_t *p_this )
packetizer_Init( &p_sys->packetizer,
p_vc1_startcode, sizeof(p_vc1_startcode), startcode_FindAnnexB,
NULL, 0, 4,
- PacketizeReset, PacketizeParse, PacketizeValidate, PacketizeDrain,
+ PacketizeReset, ParseIDU, PacketizeValidate, PacketizeDrain,
p_dec );
p_sys->b_sequence_header = false;
@@ -297,12 +296,6 @@ static void PacketizeReset( void *p_private, bool b_flush )
p_sys->i_frame_pts = VLC_TICK_INVALID;
date_Set( &p_sys->dts, VLC_TICK_INVALID );
}
-static block_t *PacketizeParse( void *p_private, bool *pb_ts_used, block_t *p_block )
-{
- decoder_t *p_dec = p_private;
-
- return ParseIDU( p_dec, pb_ts_used, p_block );
-}
static int PacketizeValidate( void *p_private, block_t *p_au )
{
@@ -422,8 +415,9 @@ static block_t *OutputFrame( decoder_t *p_dec )
}
/* ParseIDU: parse an Independent Decoding Unit */
-static block_t *ParseIDU( decoder_t *p_dec, bool *pb_ts_used, block_t *p_frag )
+static block_t *ParseIDU( void *p_private, bool *pb_ts_used, block_t *p_frag )
{
+ decoder_t *p_dec = p_private;
decoder_sys_t *p_sys = p_dec->p_sys;
block_t *p_pic = NULL;
const idu_type_t idu = p_frag->p_buffer[3];
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/d781b84d59c89636f7150f6d5ced2e2304445d0f...bd829f62f1c6d9ab5a955d48e416a929418f5646
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/d781b84d59c89636f7150f6d5ced2e2304445d0f...bd829f62f1c6d9ab5a955d48e416a929418f5646
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help
More information about the vlc-commits
mailing list