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