[vlc-devel] [PATCH] Allow the ES block fifo to store PCR

Rémi Denis-Courmont remi at remlab.net
Sun Mar 1 17:54:59 CET 2020


Hi,

1) I'd split into 3 patches, for the FIFO, using the FIFO and setting the PCR.

2) If we expose the struct layout anyway, we could just have cannoy-fail init functions instead of using malloc.

No objections on the design.

Le 1 mars 2020 16:00:23 GMT+01:00, Denis Charmet <typx at dinauz.org> a écrit :
>---
> src/Makefile.am     |   2 +
> src/input/decoder.c | 170 ++++++++++++++++++++++++++----------------
> src/input/decoder.h |   3 +
> src/input/es_fifo.c | 177 ++++++++++++++++++++++++++++++++++++++++++++
> src/input/es_fifo.h | 102 +++++++++++++++++++++++++
> src/input/es_out.c  |  18 +++++
> 6 files changed, 409 insertions(+), 63 deletions(-)
> create mode 100644 src/input/es_fifo.c
> create mode 100644 src/input/es_fifo.h
>
>diff --git a/src/Makefile.am b/src/Makefile.am
>index 2b4dfcb7dd..e3f4308e23 100644
>--- a/src/Makefile.am
>+++ b/src/Makefile.am
>@@ -256,6 +256,8 @@ libvlccore_la_SOURCES = \
> 	input/decoder_helpers.c \
> 	input/demux.c \
> 	input/demux_chained.c \
>+	input/es_fifo.c \
>+	input/es_fifo.h \
> 	input/es_out.c \
> 	input/es_out_source.c \
> 	input/es_out_timeshift.c \
>diff --git a/src/input/decoder.c b/src/input/decoder.c
>index d868c21f23..70ab06d2d8 100644
>--- a/src/input/decoder.c
>+++ b/src/input/decoder.c
>@@ -93,7 +93,8 @@ struct decoder_owner
>     atomic_int     reload;
> 
>     /* fifo */
>-    block_fifo_t *p_fifo;
>+    struct vlc_es_fifo_t *p_fifo;
>+    vlc_tick_t i_pcr;
> 
>     /* Lock for communication with decoder thread */
>     vlc_mutex_t lock;
>@@ -396,9 +397,9 @@ static int ModuleThread_UpdateAudioFormat(
>decoder_t *p_dec )
>         p_dec->fmt_out.audio.i_frame_length =
>             p_owner->fmt.audio.i_frame_length;
> 
>-        vlc_fifo_Lock( p_owner->p_fifo );
>+        vlc_es_fifo_Lock( p_owner->p_fifo );
>         p_owner->reset_out_state = true;
>-        vlc_fifo_Unlock( p_owner->p_fifo );
>+        vlc_es_fifo_Unlock( p_owner->p_fifo );
>     }
>     return 0;
> }
>@@ -590,9 +591,9 @@ static int CreateVoutIfNeeded(struct decoder_owner
>*p_owner,
>         return -1;
>     }
> 
>-    vlc_fifo_Lock( p_owner->p_fifo );
>+    vlc_es_fifo_Lock( p_owner->p_fifo );
>     p_owner->reset_out_state = true;
>-    vlc_fifo_Unlock( p_owner->p_fifo );
>+    vlc_es_fifo_Unlock( p_owner->p_fifo );
> 
>     return 1; // new vout was created
> }
>@@ -1001,11 +1002,11 @@ static void DecoderPlayCc( struct decoder_owner
>*p_owner, block_t *p_cc,
> 
>         if( i_bitmap > 1 )
>         {
>-            block_FifoPut( p_ccowner->p_fifo, block_Duplicate(p_cc) );
>+            vlc_es_fifo_FifoPut( p_ccowner->p_fifo,
>block_Duplicate(p_cc) );
>         }
>         else
>         {
>-            block_FifoPut( p_ccowner->p_fifo, p_cc );
>+            vlc_es_fifo_FifoPut( p_ccowner->p_fifo, p_cc );
>             p_cc = NULL; /* was last dec */
>         }
>     }
>@@ -1100,10 +1101,10 @@ static int ModuleThread_PlayVideo( struct
>decoder_owner *p_owner, picture_t *p_p
> 
>/* FIXME: The *input* FIFO should not be locked here. This will not
>work
>      * properly if/when pictures are queued asynchronously. */
>-    vlc_fifo_Lock( p_owner->p_fifo );
>+    vlc_es_fifo_Lock( p_owner->p_fifo );
>if( unlikely(p_owner->paused) && likely(p_owner->frames_countdown > 0)
>)
>         p_owner->frames_countdown--;
>-    vlc_fifo_Unlock( p_owner->p_fifo );
>+    vlc_es_fifo_Unlock( p_owner->p_fifo );
> 
>     /* */
>     if( p_vout == NULL )
>@@ -1633,19 +1634,19 @@ static void *DecoderThread( void *p_data )
>     bool paused = false;
> 
>     /* The decoder's main loop */
>-    vlc_fifo_Lock( p_owner->p_fifo );
>+    vlc_es_fifo_Lock( p_owner->p_fifo );
> 
>     while( !p_owner->aborting )
>     {
>         if( p_owner->flushing )
> {   /* Flush before/regardless of pause. We do not want to resume just
>       * for the sake of flushing (glitches could otherwise happen). */
>-            vlc_fifo_Unlock( p_owner->p_fifo );
>+            vlc_es_fifo_Unlock( p_owner->p_fifo );
> 
>             /* Flush the decoder (and the output) */
>             DecoderThread_Flush( p_owner );
> 
>-            vlc_fifo_Lock( p_owner->p_fifo );
>+            vlc_es_fifo_Lock( p_owner->p_fifo );
> 
>/* Reset flushing after DecoderThread_ProcessInput in case
>input_DecoderFlush
>         * is called again. This will avoid a second useless flush (but
>@@ -1671,33 +1672,33 @@ static void *DecoderThread( void *p_data )
>             vlc_tick_t date = p_owner->pause_date;
> 
>             paused = p_owner->paused;
>-            vlc_fifo_Unlock( p_owner->p_fifo );
>+            vlc_es_fifo_Unlock( p_owner->p_fifo );
> 
>             DecoderThread_ChangePause( p_owner, paused, date );
> 
>-            vlc_fifo_Lock( p_owner->p_fifo );
>+            vlc_es_fifo_Lock( p_owner->p_fifo );
>             continue;
>         }
> 
>         if( rate != p_owner->request_rate )
>         {
>             rate = p_owner->request_rate;
>-            vlc_fifo_Unlock( p_owner->p_fifo );
>+            vlc_es_fifo_Unlock( p_owner->p_fifo );
> 
>             DecoderThread_ChangeRate( p_owner, rate );
> 
>-            vlc_fifo_Lock( p_owner->p_fifo );
>+            vlc_es_fifo_Lock( p_owner->p_fifo );
>             continue;
>         }
> 
>         if( delay != p_owner->delay )
>         {
>             delay = p_owner->delay;
>-            vlc_fifo_Unlock( p_owner->p_fifo );
>+            vlc_es_fifo_Unlock( p_owner->p_fifo );
> 
>             DecoderThread_ChangeDelay( p_owner, delay );
> 
>-            vlc_fifo_Lock( p_owner->p_fifo );
>+            vlc_es_fifo_Lock( p_owner->p_fifo );
>             continue;
>         }
> 
>@@ -1705,29 +1706,35 @@ static void *DecoderThread( void *p_data )
>         {   /* Wait for resumption from pause */
>             p_owner->b_idle = true;
>             vlc_cond_signal( &p_owner->wait_acknowledge );
>-            vlc_fifo_Wait( p_owner->p_fifo );
>+            vlc_es_fifo_Wait( p_owner->p_fifo );
>             p_owner->b_idle = false;
>             continue;
>         }
> 
>         vlc_cond_signal( &p_owner->wait_fifo );
> 
>-        block_t *p_block = vlc_fifo_DequeueUnlocked( p_owner->p_fifo
>);
>+        vlc_tick_t pcr;
>+        block_t *p_block = vlc_es_fifo_DequeueUnlocked(
>p_owner->p_fifo, &pcr );
>         if( p_block == NULL )
>         {
>             if( likely(!p_owner->b_draining) )
>           {   /* Wait for a block to decode (or a request to drain) */
>                 p_owner->b_idle = true;
>                 vlc_cond_signal( &p_owner->wait_acknowledge );
>-                vlc_fifo_Wait( p_owner->p_fifo );
>+                vlc_es_fifo_Wait( p_owner->p_fifo );
>                 p_owner->b_idle = false;
>                 continue;
>             }
>          /* We have emptied the FIFO and there is a pending request to
>              * drain. Pass p_block = NULL to decoder just once. */
>         }
>+        if (pcr != p_owner->i_pcr)
>+        {
>+            p_owner->i_pcr = pcr;
>+            /* TODO notify pcr to decoder/packetizer */
>+        }
> 
>-        vlc_fifo_Unlock( p_owner->p_fifo );
>+        vlc_es_fifo_Unlock( p_owner->p_fifo );
> 
>         DecoderThread_ProcessInput( p_owner, p_block );
> 
>@@ -1740,7 +1747,7 @@ static void *DecoderThread( void *p_data )
> 
>         /* TODO? Wait for draining instead of polling. */
>         vlc_mutex_lock( &p_owner->lock );
>-        vlc_fifo_Lock( p_owner->p_fifo );
>+        vlc_es_fifo_Lock( p_owner->p_fifo );
>         if( p_owner->b_draining && (p_block == NULL) )
>         {
>             p_owner->b_draining = false;
>@@ -1750,7 +1757,7 @@ static void *DecoderThread( void *p_data )
>         vlc_mutex_unlock( &p_owner->lock );
>     }
> 
>-    vlc_fifo_Unlock( p_owner->p_fifo );
>+    vlc_es_fifo_Unlock( p_owner->p_fifo );
>     return NULL;
> }
> 
>@@ -1861,12 +1868,13 @@ static struct decoder_owner * CreateDecoder(
>vlc_object_t *p_parent,
>     es_format_Init( &p_owner->fmt, fmt->i_cat, 0 );
> 
>     /* decoder fifo */
>-    p_owner->p_fifo = block_FifoNew();
>+    p_owner->p_fifo = vlc_es_fifo_New();
>     if( unlikely(p_owner->p_fifo == NULL) )
>     {
>         vlc_object_delete(p_dec);
>         return NULL;
>     }
>+    p_owner->i_pcr = VLC_TICK_INVALID;
> 
>     vlc_mutex_init( &p_owner->lock );
>     vlc_mutex_init( &p_owner->mouse_lock );
>@@ -1974,7 +1982,7 @@ static void DeleteDecoder( decoder_t * p_dec )
>         vlc_video_context_Release( p_owner->vctx );
> 
>     /* Free all packets still in the decoder fifo. */
>-    block_FifoRelease( p_owner->p_fifo );
>+    vlc_es_fifo_Release( p_owner->p_fifo );
> 
>     /* Cleanup */
> #ifdef ENABLE_SOUT
>@@ -2163,11 +2171,11 @@ void input_DecoderDelete( decoder_t *p_dec )
> {
>     struct decoder_owner *p_owner = dec_get_owner( p_dec );
> 
>-    vlc_fifo_Lock( p_owner->p_fifo );
>+    vlc_es_fifo_Lock( p_owner->p_fifo );
>     p_owner->aborting = true;
>     p_owner->flushing = true;
>-    vlc_fifo_Signal( p_owner->p_fifo );
>-    vlc_fifo_Unlock( p_owner->p_fifo );
>+    vlc_es_fifo_Signal( p_owner->p_fifo );
>+    vlc_es_fifo_Unlock( p_owner->p_fifo );
> 
>     /* Make sure we aren't waiting/decoding anymore */
>     vlc_mutex_lock( &p_owner->lock );
>@@ -2212,17 +2220,17 @@ void input_DecoderDecode( decoder_t *p_dec,
>block_t *p_block, bool b_do_pace )
> {
>     struct decoder_owner *p_owner = dec_get_owner( p_dec );
> 
>-    vlc_fifo_Lock( p_owner->p_fifo );
>+    vlc_es_fifo_Lock( p_owner->p_fifo );
>     if( !b_do_pace )
>     {
>         /* FIXME: ideally we would check the time amount of data
>          * in the FIFO instead of its size. */
>         /* 400 MiB, i.e. ~ 50mb/s for 60s */
>-        if( vlc_fifo_GetBytes( p_owner->p_fifo ) > 400*1024*1024 )
>+        if( vlc_es_fifo_GetBytes( p_owner->p_fifo ) > 400*1024*1024 )
>         {
>             msg_Warn( p_dec, "decoder/packetizer fifo full (data not "
>                       "consumed quickly enough), resetting fifo!" );
>-            block_ChainRelease( vlc_fifo_DequeueAllUnlocked(
>p_owner->p_fifo ) );
>+            vlc_es_fifo_FlushUnlocked(p_owner->p_fifo);
>             p_block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
>         }
>     }
>@@ -2231,12 +2239,12 @@ void input_DecoderDecode( decoder_t *p_dec,
>block_t *p_block, bool b_do_pace )
>{   /* The FIFO is not consumed when waiting, so pacing would deadlock
>VLC.
>   * Locking is not necessary as b_waiting is only read, not written by
>          * the decoder thread. */
>-        while( vlc_fifo_GetCount( p_owner->p_fifo ) >= 10 )
>-            vlc_fifo_WaitCond( p_owner->p_fifo, &p_owner->wait_fifo );
>+        while( vlc_es_fifo_GetCount( p_owner->p_fifo ) >= 10 )
>+            vlc_es_fifo_WaitCond( p_owner->p_fifo, &p_owner->wait_fifo
>);
>     }
> 
>-    vlc_fifo_QueueUnlocked( p_owner->p_fifo, p_block );
>-    vlc_fifo_Unlock( p_owner->p_fifo );
>+    vlc_es_fifo_QueueUnlocked( p_owner->p_fifo, p_block );
>+    vlc_es_fifo_Unlock( p_owner->p_fifo );
> }
> 
> bool input_DecoderIsEmpty( decoder_t * p_dec )
>@@ -2245,13 +2253,13 @@ bool input_DecoderIsEmpty( decoder_t * p_dec )
> 
>     assert( !p_owner->b_waiting );
> 
>-    vlc_fifo_Lock( p_owner->p_fifo );
>-    if( !vlc_fifo_IsEmpty( p_owner->p_fifo ) || p_owner->b_draining )
>+    vlc_es_fifo_Lock( p_owner->p_fifo );
>+    if( !vlc_es_fifo_IsEmpty( p_owner->p_fifo ) || p_owner->b_draining
>)
>     {
>-        vlc_fifo_Unlock( p_owner->p_fifo );
>+        vlc_es_fifo_Unlock( p_owner->p_fifo );
>         return false;
>     }
>-    vlc_fifo_Unlock( p_owner->p_fifo );
>+    vlc_es_fifo_Unlock( p_owner->p_fifo );
> 
>     bool b_empty;
> 
>@@ -2284,10 +2292,10 @@ void input_DecoderDrain( decoder_t *p_dec )
> {
>     struct decoder_owner *p_owner = dec_get_owner( p_dec );
> 
>-    vlc_fifo_Lock( p_owner->p_fifo );
>+    vlc_es_fifo_Lock( p_owner->p_fifo );
>     p_owner->b_draining = true;
>-    vlc_fifo_Signal( p_owner->p_fifo );
>-    vlc_fifo_Unlock( p_owner->p_fifo );
>+    vlc_es_fifo_Signal( p_owner->p_fifo );
>+    vlc_es_fifo_Unlock( p_owner->p_fifo );
> }
> 
> /**
>@@ -2298,10 +2306,10 @@ void input_DecoderFlush( decoder_t *p_dec )
> {
>     struct decoder_owner *p_owner = dec_get_owner( p_dec );
> 
>-    vlc_fifo_Lock( p_owner->p_fifo );
>+    vlc_es_fifo_Lock( p_owner->p_fifo );
> 
>     /* Empty the fifo */
>-    block_ChainRelease( vlc_fifo_DequeueAllUnlocked( p_owner->p_fifo )
>);
>+    vlc_es_fifo_FlushUnlocked(p_owner->p_fifo);
> 
>/* Don't need to wait for the DecoderThread to flush. Indeed, if called
>a
>* second time, this function will clear the FIFO again before anything
>was
>@@ -2316,9 +2324,9 @@ void input_DecoderFlush( decoder_t *p_dec )
>      && p_owner->frames_countdown == 0 )
>         p_owner->frames_countdown++;
> 
>-    vlc_fifo_Signal( p_owner->p_fifo );
>+    vlc_es_fifo_Signal( p_owner->p_fifo );
> 
>-    vlc_fifo_Unlock( p_owner->p_fifo );
>+    vlc_es_fifo_Unlock( p_owner->p_fifo );
> 
>     if( p_owner->paused )
>     {
>@@ -2449,30 +2457,30 @@ void input_DecoderChangePause( decoder_t
>*p_dec, bool b_paused, vlc_tick_t i_dat
>/* Normally, p_owner->b_paused != b_paused here. But if a track is
>added
>      * while the input is paused (e.g. add sub file), then b_paused is
>   * (incorrectly) false. FIXME: This is a bug in the decoder owner. */
>-    vlc_fifo_Lock( p_owner->p_fifo );
>+    vlc_es_fifo_Lock( p_owner->p_fifo );
>     p_owner->paused = b_paused;
>     p_owner->pause_date = i_date;
>     p_owner->frames_countdown = 0;
>-    vlc_fifo_Signal( p_owner->p_fifo );
>-    vlc_fifo_Unlock( p_owner->p_fifo );
>+    vlc_es_fifo_Signal( p_owner->p_fifo );
>+    vlc_es_fifo_Unlock( p_owner->p_fifo );
> }
> 
> void input_DecoderChangeRate( decoder_t *dec, float rate )
> {
>     struct decoder_owner *owner = dec_get_owner( dec );
> 
>-    vlc_fifo_Lock( owner->p_fifo );
>+    vlc_es_fifo_Lock( owner->p_fifo );
>     owner->request_rate = rate;
>-    vlc_fifo_Unlock( owner->p_fifo );
>+    vlc_es_fifo_Unlock( owner->p_fifo );
> }
> 
> void input_DecoderChangeDelay( decoder_t *dec, vlc_tick_t delay )
> {
>     struct decoder_owner *owner = dec_get_owner( dec );
> 
>-    vlc_fifo_Lock( owner->p_fifo );
>+    vlc_es_fifo_Lock( owner->p_fifo );
>     owner->delay = delay;
>-    vlc_fifo_Unlock( owner->p_fifo );
>+    vlc_es_fifo_Unlock( owner->p_fifo );
> }
> 
> void input_DecoderStartWait( decoder_t *p_dec )
>@@ -2514,14 +2522,14 @@ void input_DecoderWait( decoder_t *p_dec )
>          * owner */
>         if( p_owner->paused )
>             break;
>-        vlc_fifo_Lock( p_owner->p_fifo );
>-        if( p_owner->b_idle && vlc_fifo_IsEmpty( p_owner->p_fifo ) )
>+        vlc_es_fifo_Lock( p_owner->p_fifo );
>+        if( p_owner->b_idle && vlc_es_fifo_IsEmpty( p_owner->p_fifo )
>)
>         {
>             msg_Err( p_dec, "buffer deadlock prevented" );
>-            vlc_fifo_Unlock( p_owner->p_fifo );
>+            vlc_es_fifo_Unlock( p_owner->p_fifo );
>             break;
>         }
>-        vlc_fifo_Unlock( p_owner->p_fifo );
>+        vlc_es_fifo_Unlock( p_owner->p_fifo );
>         vlc_cond_wait( &p_owner->wait_acknowledge, &p_owner->lock );
>     }
>     vlc_mutex_unlock( &p_owner->lock );
>@@ -2534,10 +2542,10 @@ void input_DecoderFrameNext( decoder_t *p_dec,
>vlc_tick_t *pi_duration )
>     assert( p_owner->paused );
>     *pi_duration = 0;
> 
>-    vlc_fifo_Lock( p_owner->p_fifo );
>+    vlc_es_fifo_Lock( p_owner->p_fifo );
>     p_owner->frames_countdown++;
>-    vlc_fifo_Signal( p_owner->p_fifo );
>-    vlc_fifo_Unlock( p_owner->p_fifo );
>+    vlc_es_fifo_Signal( p_owner->p_fifo );
>+    vlc_es_fifo_Unlock( p_owner->p_fifo );
> 
>     vlc_mutex_lock( &p_owner->lock );
>     if( p_owner->fmt.i_cat == VIDEO_ES )
>@@ -2577,8 +2585,10 @@ bool input_DecoderHasFormatChanged( decoder_t
>*p_dec, es_format_t *p_fmt, vlc_me
> size_t input_DecoderGetFifoSize( decoder_t *p_dec )
> {
>     struct decoder_owner *p_owner = dec_get_owner( p_dec );
>-
>-    return block_FifoSize( p_owner->p_fifo );
>+    vlc_es_fifo_Lock(p_owner->p_fifo);
>+    size_t bytes = vlc_es_fifo_GetBytes( p_owner->p_fifo );
>+    vlc_es_fifo_Unlock(p_owner->p_fifo);
>+    return bytes;
> }
> 
>void input_DecoderSetVoutMouseEvent( decoder_t *dec, vlc_mouse_event
>mouse_event,
>@@ -2667,3 +2677,37 @@ int input_DecoderSetSpuHighlight( decoder_t
>*dec,
>     vlc_mutex_unlock( &p_owner->lock );
>     return VLC_SUCCESS;
> }
>+
>+int input_DecoderSetPcr(decoder_t * dec, vlc_tick_t pcr)
>+{
>+    struct decoder_owner *p_owner = dec_get_owner( dec );
>+
>+    vlc_mutex_lock( &p_owner->lock );
>+
>+    if (vlc_es_fifo_SetPcr(p_owner->p_fifo, pcr))
>+    {
>+        vlc_mutex_unlock( &p_owner->lock );
>+        return 1;
>+    }
>+
>+    /* Fanout data to all decoders. We do not know if es_out
>+       selected 608 or 708. */
>+    uint64_t i_bitmap = p_owner->cc.desc.i_608_channels |
>+                        p_owner->cc.desc.i_708_channels;
>+
>+    for( int i=0; i_bitmap > 0; i_bitmap >>= 1, i++ )
>+    {
>+        decoder_t *p_ccdec = p_owner->cc.pp_decoder[i];
>+        struct decoder_owner *p_ccowner = dec_get_owner( p_ccdec );
>+        if( !p_ccdec )
>+            continue;
>+        if (vlc_es_fifo_SetPcr(p_ccowner->p_fifo, pcr))
>+        {
>+            vlc_mutex_unlock( &p_owner->lock );
>+            return 1;
>+        }
>+    }
>+
>+    vlc_mutex_unlock( &p_owner->lock );
>+    return 0;
>+}
>diff --git a/src/input/decoder.h b/src/input/decoder.h
>index af9f7c7bdb..2fe9b8cf44 100644
>--- a/src/input/decoder.h
>+++ b/src/input/decoder.h
>@@ -27,6 +27,7 @@
> #include <vlc_common.h>
> #include <vlc_codec.h>
> #include <vlc_mouse.h>
>+#include "es_fifo.h"
> 
> struct input_decoder_callbacks {
>     /* notifications */
>@@ -138,4 +139,6 @@ void input_DecoderSetVoutMouseEvent( decoder_t *,
>vlc_mouse_event, void * );
>int  input_DecoderAddVoutOverlay( decoder_t *, subpicture_t *, size_t *
>);
> int  input_DecoderDelVoutOverlay( decoder_t *, size_t );
> 
>+int input_DecoderSetPcr(decoder_t *, vlc_tick_t);
>+
> #endif
>diff --git a/src/input/es_fifo.c b/src/input/es_fifo.c
>new file mode 100644
>index 0000000000..97404d2cf1
>--- /dev/null
>+++ b/src/input/es_fifo.c
>@@ -0,0 +1,177 @@
>+/*****************************************************************************
>+ * es_fifo.c: Input es_out fifo functions
>+
>*****************************************************************************
>+ * Copyright (C) 2020 VLC authors and VideoLAN
>+ *
>+ * This program is free software; you can redistribute it and/or
>modify it
>+ * under the terms of the GNU Lesser General Public License as
>published by
>+ * the Free Software Foundation; either version 2.1 of the License, or
>+ * (at your option) any later version.
>+ *
>+ * This program is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>+ * GNU Lesser General Public License for more details.
>+ *
>+ * You should have received a copy of the GNU Lesser General Public
>License
>+ * along with this program; if not, write to the Free Software
>Foundation,
>+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
>+
>*****************************************************************************/
>+#ifdef HAVE_CONFIG_H
>+# include "config.h"
>+#endif
>+
>+#include <assert.h>
>+#include <vlc_common.h>
>+#include <vlc_block.h>
>+
>+#include "es_fifo.h"
>+
>+static struct vlc_pcr_block_fifo_t *pcr_fifo_New(vlc_tick_t pcr)
>+{
>+    struct vlc_pcr_block_fifo_t *p_fifo = malloc(sizeof(struct
>vlc_pcr_block_fifo_t));
>+    if (p_fifo == NULL)
>+        return NULL;
>+    p_fifo->i_pcr = pcr;
>+    p_fifo->p_first = NULL;
>+    p_fifo->pp_last = &p_fifo->p_first;
>+    p_fifo->p_next = NULL;
>+    return p_fifo;
>+}
>+
>+struct vlc_es_fifo_t *vlc_es_fifo_New()
>+{
>+    struct vlc_es_fifo_t *p_fifo = malloc(sizeof(struct
>vlc_es_fifo_t));
>+
>+    if (p_fifo == NULL)
>+        return NULL;
>+
>+    p_fifo->p_first = pcr_fifo_New(VLC_TICK_INVALID);
>+
>+    if (p_fifo->p_first == NULL)
>+    {
>+        free(p_fifo);
>+        return NULL;
>+    }
>+
>+    vlc_mutex_init(&p_fifo->lock);
>+    vlc_cond_init(&p_fifo->wait);
>+    p_fifo->p_last = p_fifo->p_first;
>+    p_fifo->i_depth = p_fifo->i_size = 0;
>+
>+    return p_fifo;
>+}
>+
>+int vlc_es_fifo_SetPcr(struct vlc_es_fifo_t *fifo, vlc_tick_t pcr)
>+{
>+    vlc_mutex_lock(&fifo->lock);
>+
>+    struct vlc_pcr_block_fifo_t *p_pcr_fifo = fifo->p_last;
>+    if (p_pcr_fifo->p_first == NULL || p_pcr_fifo->i_pcr == pcr)
>+        p_pcr_fifo->i_pcr = pcr; /* Reuse empty or same pcr_block fifo
>*/
>+    else
>+    {
>+        p_pcr_fifo = pcr_fifo_New(pcr);
>+        if (p_pcr_fifo == NULL)
>+        {
>+            vlc_mutex_unlock(&fifo->lock);
>+            return 1;
>+        }
>+        fifo->p_last->p_next = p_pcr_fifo;
>+        fifo->p_last = p_pcr_fifo;
>+    }
>+    vlc_mutex_unlock(&fifo->lock);
>+    return 0;
>+}
>+
>+void vlc_es_fifo_Release(struct vlc_es_fifo_t *fifo)
>+{
>+    vlc_mutex_lock(&fifo->lock);
>+    struct vlc_pcr_block_fifo_t *tmp;
>+    while ((tmp = fifo->p_first) != NULL)
>+    {
>+        block_ChainRelease(tmp->p_first);
>+        fifo->p_first = tmp->p_next;
>+        free(tmp);
>+    }
>+    vlc_mutex_unlock(&fifo->lock);
>+    free(fifo);
>+}
>+
>+void vlc_es_fifo_FlushUnlocked(struct vlc_es_fifo_t *fifo)
>+{
>+    vlc_mutex_assert(&fifo->lock);
>+    struct vlc_pcr_block_fifo_t *tmp, *first = fifo->p_first;
>+
>+    /* Reset the first element */
>+    block_ChainRelease(first->p_first);
>+    first->p_first = NULL;
>+    first->pp_last = &first->p_first;
>+    first->i_pcr = VLC_TICK_INVALID;
>+
>+    fifo->p_first = first->p_next;
>+    first->p_next = NULL;
>+
>+    while ((tmp = fifo->p_first) != NULL)
>+    {
>+        block_ChainRelease(tmp->p_first);
>+        fifo->p_first = tmp->p_next;
>+        free(tmp);
>+    }
>+
>+    fifo->p_first = fifo->p_last = first;
>+    fifo->i_depth = 0;
>+    fifo->i_size = 0;
>+}
>+
>+block_t *vlc_es_fifo_DequeueUnlocked(struct vlc_es_fifo_t *fifo,
>vlc_tick_t * pcr)
>+{
>+    vlc_mutex_assert(&fifo->lock);
>+
>+    struct vlc_pcr_block_fifo_t * restrict first = fifo->p_first;
>+    block_t * restrict block = first->p_first;
>+
>+    if (block == NULL)
>+        return NULL;
>+
>+    *pcr = first->i_pcr;
>+    first->p_first = block->p_next;
>+    if (block->p_next == NULL)
>+    {
>+        if (first->p_next != NULL)
>+        {
>+            fifo->p_first = first->p_next;
>+            free(first);
>+        }
>+        else
>+        {
>+            first->pp_last = &first->p_first;
>+            //printf("%lld - %p - %p\n", first->i_pcr, first->p_first,
>first->pp_last);
>+        }
>+    }
>+
>+    assert(fifo->i_depth > 0);
>+    fifo->i_depth--;
>+    assert(fifo->i_size >= block->i_buffer);
>+    fifo->i_size -= block->i_buffer;
>+
>+    return block;
>+}
>+
>+void vlc_es_fifo_QueueUnlocked(struct vlc_es_fifo_t *fifo, block_t
>*block)
>+{
>+    vlc_mutex_assert(&fifo->lock);
>+    struct vlc_pcr_block_fifo_t * restrict last = fifo->p_last;
>+    assert(*last->pp_last == NULL);
>+
>+    *last->pp_last = block;
>+
>+    while (block != NULL)
>+    {
>+        last->pp_last = &block->p_next;
>+        fifo->i_depth++;
>+        fifo->i_size += block->i_buffer;
>+        block = block->p_next;
>+    }
>+    vlc_cond_signal(&fifo->wait);
>+}
>diff --git a/src/input/es_fifo.h b/src/input/es_fifo.h
>new file mode 100644
>index 0000000000..38f8e6c414
>--- /dev/null
>+++ b/src/input/es_fifo.h
>@@ -0,0 +1,102 @@
>+/*****************************************************************************
>+ * es_fifo.h: Input es_out fifo functions
>+
>*****************************************************************************
>+ * Copyright (C) 2020 VLC authors and VideoLAN
>+ *
>+ * This program is free software; you can redistribute it and/or
>modify it
>+ * under the terms of the GNU Lesser General Public License as
>published by
>+ * the Free Software Foundation; either version 2.1 of the License, or
>+ * (at your option) any later version.
>+ *
>+ * This program is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>+ * GNU Lesser General Public License for more details.
>+ *
>+ * You should have received a copy of the GNU Lesser General Public
>License
>+ * along with this program; if not, write to the Free Software
>Foundation,
>+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
>+
>*****************************************************************************/
>+
>+#ifndef LIBVLC_INPUT_ES_FIFO_H
>+#define LIBVLC_INPUT_ES_FIFO_H 1
>+
>+struct vlc_pcr_block_fifo_t
>+{
>+    vlc_tick_t i_pcr;
>+    block_t *p_first;
>+    block_t **pp_last;
>+    struct vlc_pcr_block_fifo_t *p_next;
>+};
>+
>+struct vlc_es_fifo_t
>+{
>+    vlc_mutex_t lock;
>+    vlc_cond_t wait;
>+    struct vlc_pcr_block_fifo_t *p_first;
>+    struct vlc_pcr_block_fifo_t *p_last;
>+    size_t i_depth;
>+    size_t i_size;
>+};
>+
>+struct vlc_es_fifo_t *vlc_es_fifo_New(void);
>+
>+void vlc_es_fifo_Release(struct vlc_es_fifo_t *fifo);
>+
>+void vlc_es_fifo_FlushUnlocked(struct vlc_es_fifo_t *fifo);
>+
>+block_t *vlc_es_fifo_DequeueUnlocked(struct vlc_es_fifo_t *fifo,
>vlc_tick_t * pcr);
>+
>+void vlc_es_fifo_QueueUnlocked(struct vlc_es_fifo_t *fifo, block_t
>*block);
>+
>+int vlc_es_fifo_SetPcr(struct vlc_es_fifo_t *fifo, vlc_tick_t pcr);
>+
>+static inline void vlc_es_fifo_FifoPut(struct vlc_es_fifo_t *fifo,
>block_t *block)
>+{
>+    vlc_mutex_lock(&fifo->lock);
>+    vlc_es_fifo_QueueUnlocked(fifo, block);
>+    vlc_mutex_unlock(&fifo->lock);
>+}
>+
>+static inline void vlc_es_fifo_Lock(struct vlc_es_fifo_t *fifo)
>+{
>+    vlc_mutex_lock(&fifo->lock);
>+}
>+
>+static inline void vlc_es_fifo_Unlock(struct vlc_es_fifo_t *fifo)
>+{
>+    vlc_mutex_unlock(&fifo->lock);
>+}
>+
>+static inline void vlc_es_fifo_Signal(struct vlc_es_fifo_t *fifo)
>+{
>+    vlc_cond_signal(&fifo->wait);
>+}
>+
>+static inline void vlc_es_fifo_Wait(struct vlc_es_fifo_t *fifo)
>+{
>+    vlc_cond_wait(&fifo->wait, &fifo->lock);
>+}
>+
>+static inline void vlc_es_fifo_WaitCond(struct vlc_es_fifo_t *fifo,
>vlc_cond_t * wait)
>+{
>+    vlc_cond_wait(wait, &fifo->lock);
>+}
>+
>+static inline size_t vlc_es_fifo_GetCount(const struct vlc_es_fifo_t
>*fifo)
>+{
>+    vlc_mutex_assert(&fifo->lock);
>+    return fifo->i_depth;
>+}
>+
>+static inline size_t vlc_es_fifo_GetBytes(const struct vlc_es_fifo_t
>*fifo)
>+{
>+    vlc_mutex_assert(&fifo->lock);
>+    return fifo->i_size;
>+}
>+
>+static inline bool vlc_es_fifo_IsEmpty(struct vlc_es_fifo_t *fifo)
>+{
>+    return vlc_es_fifo_GetCount(fifo) == 0;
>+}
>+#endif
>diff --git a/src/input/es_out.c b/src/input/es_out.c
>index 118c780c95..2c1953ecb7 100644
>--- a/src/input/es_out.c
>+++ b/src/input/es_out.c
>@@ -3143,6 +3143,24 @@ static int EsOutVaControlLocked( es_out_t *out,
>input_source_t *source,
>             return VLC_EGENERIC;
>         }
> 
>+        es_out_id_t *es;
>+        foreach_es_then_es_slaves( es )
>+        {
>+            if ( es->p_pgrm == p_pgrm )
>+            {
>+                if ( es->p_dec != NULL && input_DecoderSetPcr(
>es->p_dec, i_pcr ) )
>+                {
>+                    EsOutControlLocked( out, source, ES_OUT_RESET_PCR
>);
>+                    return VLC_ENOMEM;
>+                }
>+                if ( es->p_dec_record != NULL && input_DecoderSetPcr(
>es->p_dec, i_pcr ) )
>+                {
>+                    EsOutControlLocked( out, source, ES_OUT_RESET_PCR
>);
>+                    return VLC_ENOMEM;
>+                }
>+            }
>+        }
>+
>/* TODO do not use vlc_tick_now() but proper stream acquisition date */
>      const bool b_low_delay = input_priv(p_sys->p_input)->b_low_delay;
>bool b_extra_buffering_allowed = !b_low_delay &&
>EsOutIsExtraBufferingAllowed( out );
>-- 
>2.24.1
>
>_______________________________________________
>vlc-devel mailing list
>To unsubscribe or modify your subscription options:
>https://mailman.videolan.org/listinfo/vlc-devel

-- 
Envoyé de mon appareil Android avec Courriel K-9 Mail. Veuillez excuser ma brièveté.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20200301/cea7f6c3/attachment-0001.html>


More information about the vlc-devel mailing list