[vlc-commits] codec: mpg123: really fix multiple output per block (fix #18943)
Francois Cartegnie
git at videolan.org
Tue Oct 24 11:56:02 CEST 2017
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Tue Oct 24 11:41:37 2017 +0200| [6a77d75453e1c20edcbcb85d5ca618154408f1a7] | committer: Francois Cartegnie
codec: mpg123: really fix multiple output per block (fix #18943)
fixes stuttering/dropped audio on non packetized input
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=6a77d75453e1c20edcbcb85d5ca618154408f1a7
---
modules/codec/mpg123.c | 143 +++++++++++++++++++++++++++----------------------
1 file changed, 80 insertions(+), 63 deletions(-)
diff --git a/modules/codec/mpg123.c b/modules/codec/mpg123.c
index 171254f707..a4f9ac9b7b 100644
--- a/modules/codec/mpg123.c
+++ b/modules/codec/mpg123.c
@@ -141,7 +141,7 @@ static void Flush( decoder_t *p_dec )
{
decoder_sys_t *p_sys = p_dec->p_sys;
- date_Set( &p_sys->end_date, 0 );
+ date_Set( &p_sys->end_date, VLC_TS_INVALID );
mpg123_close( p_sys->p_handle );
mpg123_delete( p_sys->p_handle );
@@ -203,7 +203,7 @@ static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
{
int i_err;
decoder_sys_t *p_sys = p_dec->p_sys;
- block_t *p_out = NULL;
+ mtime_t i_pts = VLC_TS_INVALID;
if( !p_sys->b_opened )
{
@@ -215,51 +215,58 @@ static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
/* Feed input block */
if( p_block != NULL )
{
- if( !date_Get( &p_sys->end_date ) && p_block->i_pts <= VLC_TS_INVALID )
- {
- /* We've just started the stream, wait for the first PTS. */
- msg_Dbg( p_dec, "waiting for PTS" );
- goto end;
- }
+ i_pts = p_block->i_pts > VLC_TS_INVALID ? p_block->i_pts : p_block->i_dts;
if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
{
Flush( p_dec );
if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
- goto end;
+ {
+ block_Release( p_block );
+ return VLCDEC_SUCCESS;
+ }
+ }
+
+ if( !date_Get( &p_sys->end_date ) && i_pts <= VLC_TS_INVALID )
+ {
+ /* We've just started the stream, wait for the first PTS. */
+ msg_Dbg( p_dec, "waiting for PTS" );
+ block_Release( p_block );
+ return VLCDEC_SUCCESS;
}
/* Feed mpg123 with raw data */
- i_err = mpg123_feed( p_sys->p_handle, p_block->p_buffer,
- p_block->i_buffer );
+ i_err = mpg123_feed( p_sys->p_handle, p_block->p_buffer, p_block->i_buffer );
+ block_Release( p_block );
if( i_err != MPG123_OK )
{
msg_Err( p_dec, "mpg123_feed failed: %s",
mpg123_plain_strerror( i_err ) );
- goto end;
+ return VLCDEC_SUCCESS;
}
}
- /* Fetch a new output block (if possible) */
- if( !p_sys->p_out
- || p_sys->p_out->i_buffer != mpg123_outblock( p_sys->p_handle ) )
+ while( true )
{
- if( p_sys->p_out )
- block_Release( p_sys->p_out );
+ /* Fetch a new output block (if possible) */
+ if( !p_sys->p_out
+ || p_sys->p_out->i_buffer != mpg123_outblock( p_sys->p_handle ) )
+ {
+ if( p_sys->p_out )
+ block_Release( p_sys->p_out );
- /* Keep the output buffer for next calls in case it's not used (in case
- * of MPG123_NEED_MORE status) */
- p_sys->p_out = block_Alloc( mpg123_outblock( p_sys->p_handle ) );
+ /* Keep the output buffer for next calls in case it's not used (in case
+ * of MPG123_NEED_MORE status) */
+ p_sys->p_out = block_Alloc( mpg123_outblock( p_sys->p_handle ) );
- if( unlikely( !p_sys->p_out ) )
- return VLCDEC_SUCCESS;
- }
+ if( unlikely( !p_sys->p_out ) )
+ return VLCDEC_SUCCESS;
+ }
+
+ /* Do the actual decoding now */
+ size_t i_bytes = 0;
- /* Do the actual decoding now */
- size_t i_bytes = 0;
- while( true )
- {
/* Make mpg123 write directly into the VLC output buffer */
i_err = mpg123_replace_buffer( p_sys->p_handle, p_sys->p_out->p_buffer,
p_sys->p_out->i_buffer );
@@ -269,59 +276,69 @@ static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
mpg123_plain_strerror( i_err ) );
block_Release( p_sys->p_out );
p_sys->p_out = NULL;
- return VLCDEC_SUCCESS;
+ break;
}
i_err = mpg123_decode_frame( p_sys->p_handle, NULL, NULL, &i_bytes );
- if( i_err != MPG123_OK )
+ if( i_err != MPG123_OK && i_err != MPG123_NEED_MORE )
{
if( i_err == MPG123_NEW_FORMAT )
{
- if( UpdateAudioFormat( p_dec ) != VLC_SUCCESS )
- goto end;
- else
- continue;
+ p_dec->fmt_out.audio.i_rate = 0;
}
- else if( i_err != MPG123_NEED_MORE )
+ else
+ {
msg_Err( p_dec, "mpg123_decode_frame error: %s",
mpg123_plain_strerror( i_err ) );
+ date_Set( &p_sys->end_date, VLC_TS_INVALID );
+ break;
+ }
}
- else if( p_dec->fmt_out.audio.i_rate == 0 )
+
+ if( i_bytes == 0 )
+ break;
+
+ if( p_dec->fmt_out.audio.i_rate == 0 )
{
- msg_Warn( p_dec, "mpg123_decode_frame returned valid frame without "
- "updating the format" );
if( UpdateAudioFormat( p_dec ) != VLC_SUCCESS )
- goto end;
+ {
+ date_Set( &p_sys->end_date, VLC_TS_INVALID );
+ break;
+ }
}
- break;
- }
- if( p_block && p_block->i_pts > VLC_TS_INVALID &&
- p_block->i_pts != date_Get( &p_sys->end_date ) )
- date_Set( &p_sys->end_date, p_block->i_pts );
+ block_t *p_out = p_sys->p_out;
+ p_sys->p_out = NULL;
- if( i_bytes == 0 )
- goto end;
-
- assert( p_dec->fmt_out.audio.i_rate != 0 );
+ if( date_Get( &p_sys->end_date ) == VLC_TS_INVALID )
+ {
+ if( i_pts != VLC_TS_INVALID )
+ {
+ date_Set( &p_sys->end_date, i_pts );
+ }
+ else if( p_out ) /* we need a valid date and that's not guaranteed on flush/error */
+ {
+ block_Release( p_out );
+ break;
+ }
+ }
- p_out = p_sys->p_out;
- p_sys->p_out = NULL;
+ if( p_out )
+ {
+ assert( p_dec->fmt_out.audio.i_rate != 0 );
+ assert( p_out->i_buffer >= i_bytes );
+ p_out->i_buffer = i_bytes;
+ p_out->i_nb_samples = p_out->i_buffer * p_dec->fmt_out.audio.i_frame_length
+ / p_dec->fmt_out.audio.i_bytes_per_frame;
+
+ /* Configure the buffer */
+ p_out->i_dts = p_out->i_pts = date_Get( &p_sys->end_date );
+ p_out->i_length = date_Increment( &p_sys->end_date, p_out->i_nb_samples )
+ - p_out->i_pts;
+ decoder_QueueAudio( p_dec, p_out );
+ }
+ }
- assert( p_out->i_buffer >= i_bytes );
- p_out->i_buffer = i_bytes;
- p_out->i_nb_samples = p_out->i_buffer * p_dec->fmt_out.audio.i_frame_length
- / p_dec->fmt_out.audio.i_bytes_per_frame;
-
- /* Configure the buffer */
- p_out->i_dts = p_out->i_pts = date_Get( &p_sys->end_date );
- p_out->i_length = date_Increment( &p_sys->end_date, p_out->i_nb_samples )
- - p_out->i_pts;
-end:
- if( p_block )
- block_Release( p_block );
- if( p_out != NULL )
- decoder_QueueAudio( p_dec, p_out );
return VLCDEC_SUCCESS;
}
More information about the vlc-commits
mailing list