[vlc-devel] [PATCH 3/8] sout/core: handle drain

Thomas Guillem thomas at gllm.fr
Mon Jan 29 18:25:51 CET 2018


On most modules, draining consist of calling pf_send with the next sout with a
NULL buffer.

For standard: nothing to be done, just call sout_MuxSendBuffer() with a NULL
buffer, the muxer will take care of the draining.

For transcode, it was already implemented when the module was closing. So move
the drain code back to the Send callback.

I added a TODO on modules where I didn't know how to implement draining.
---
 include/vlc_sout.h                       |  4 ++--
 modules/stream_out/autodel.c             |  6 ++++++
 modules/stream_out/bridge.c              | 12 ++++++++++++
 modules/stream_out/chromaprint.c         |  6 ++++++
 modules/stream_out/chromecast/cast.cpp   |  7 +++++--
 modules/stream_out/cycle.c               |  6 ++++++
 modules/stream_out/description.c         |  3 ++-
 modules/stream_out/display.c             |  6 ++++++
 modules/stream_out/dummy.c               |  3 ++-
 modules/stream_out/duplicate.c           | 12 ++++++++++++
 modules/stream_out/gather.c              |  2 +-
 modules/stream_out/mosaic_bridge.c       |  3 ++-
 modules/stream_out/record.c              |  7 +++++++
 modules/stream_out/smem.c                |  5 +++++
 modules/stream_out/transcode/transcode.c | 10 ++++++----
 15 files changed, 80 insertions(+), 12 deletions(-)

diff --git a/include/vlc_sout.h b/include/vlc_sout.h
index 8ba55b75be..1ce1cc006b 100644
--- a/include/vlc_sout.h
+++ b/include/vlc_sout.h
@@ -217,8 +217,8 @@ struct sout_stream_t
     /* add, remove a stream */
     sout_stream_id_sys_t *(*pf_add)( sout_stream_t *, const es_format_t * );
     void              (*pf_del)( sout_stream_t *, sout_stream_id_sys_t * );
-    /* manage a packet */
-    int               (*pf_send)( sout_stream_t *, sout_stream_id_sys_t *, block_t* );
+    /* manage a packet. If p_block is NULL, the module should drain itself. */
+    int               (*pf_send)( sout_stream_t *, sout_stream_id_sys_t *, block_t*p_block );
     int               (*pf_control)( sout_stream_t *, int, va_list );
     void              (*pf_flush)( sout_stream_t *, sout_stream_id_sys_t * );
 
diff --git a/modules/stream_out/autodel.c b/modules/stream_out/autodel.c
index 91f95e3bb8..1a860c0db3 100644
--- a/modules/stream_out/autodel.c
+++ b/modules/stream_out/autodel.c
@@ -148,6 +148,12 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_sys_t *p_es,
     mtime_t i_current = mdate();
     int i;
 
+    if( unlikely( p_buffer == NULL ) )
+    {
+        /* TODO: Drain */
+        return VLC_SUCCESS;
+    }
+
     p_es->i_last = p_buffer->i_dts;
     if ( !p_es->id && !p_es->b_error )
     {
diff --git a/modules/stream_out/bridge.c b/modules/stream_out/bridge.c
index a26c6685e0..3da34546d8 100644
--- a/modules/stream_out/bridge.c
+++ b/modules/stream_out/bridge.c
@@ -324,6 +324,12 @@ static int SendOut( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
     out_sout_stream_sys_t *p_sys = (out_sout_stream_sys_t *)p_stream->p_sys;
     bridged_es_t *p_es;
 
+    if( unlikely( p_buffer == NULL ) )
+    {
+        /* TODO: Drain */
+        return VLC_SUCCESS;
+    }
+
     if ( (out_sout_stream_sys_t *)id != p_sys )
     {
         block_ChainRelease( p_buffer );
@@ -508,6 +514,12 @@ static int SendIn( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
     int i;
     int i_date = mdate();
 
+    if( unlikely( p_buffer == NULL ) )
+    {
+        /* TODO: Drain */
+        return VLC_SUCCESS;
+    }
+
     /* First forward the packet for our own ES */
     if( !p_sys->b_placeholder )
         p_stream->p_next->pf_send( p_stream->p_next, id->id, p_buffer );
diff --git a/modules/stream_out/chromaprint.c b/modules/stream_out/chromaprint.c
index 3a093a36ab..4d1886e86f 100644
--- a/modules/stream_out/chromaprint.c
+++ b/modules/stream_out/chromaprint.c
@@ -214,6 +214,12 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
 {
     sout_stream_sys_t *p_sys = p_stream->p_sys;
 
+    if( unlikely( p_buf == NULL ) )
+    {
+        /* TODO: Drain */
+        return VLC_SUCCESS;
+    }
+
     if ( p_sys->id != id )
     {
         /* drop the whole buffer at once */
diff --git a/modules/stream_out/chromecast/cast.cpp b/modules/stream_out/chromecast/cast.cpp
index 234944dc86..15f866b71c 100644
--- a/modules/stream_out/chromecast/cast.cpp
+++ b/modules/stream_out/chromecast/cast.cpp
@@ -781,9 +781,11 @@ static int Send(sout_stream_t *p_stream, sout_stream_id_sys_t *id,
     sout_stream_id_sys_t *next_id = p_sys->GetSubId( p_stream, id );
     if ( next_id == NULL )
     {
-        block_Release( p_buffer );
+        if( p_buffer )
+            block_Release( p_buffer );
         return VLC_EGENERIC;
     }
+
     States s = p_sys->p_intf->state();
     if ( p_sys->previous_state != s )
     {
@@ -792,7 +794,8 @@ static int Send(sout_stream_t *p_stream, sout_stream_id_sys_t *id,
             if ( p_sys->transcode_attempt_idx > MAX_TRANSCODE_PASS - 1 )
             {
                 msg_Err( p_stream, "All attempts failed. Giving up." );
-                block_Release( p_buffer );
+                if( p_buffer )
+                    block_Release( p_buffer );
                 return VLC_EGENERIC;
             }
             p_sys->transcode_attempt_idx++;
diff --git a/modules/stream_out/cycle.c b/modules/stream_out/cycle.c
index bb031f81ae..0b46fbe495 100644
--- a/modules/stream_out/cycle.c
+++ b/modules/stream_out/cycle.c
@@ -156,6 +156,12 @@ static int Send(sout_stream_t *stream, sout_stream_id_sys_t *id,
 {
     sout_stream_sys_t *sys = stream->p_sys;
 
+    if( unlikely( block == NULL ) )
+    {
+        /* TODO: Drain */
+        return VLC_SUCCESS;
+    }
+
     for (block_t *next = block->p_next; block != NULL; block = next)
     {
         block->p_next = NULL;
diff --git a/modules/stream_out/description.c b/modules/stream_out/description.c
index bf77ba3a33..8119ecc7f3 100644
--- a/modules/stream_out/description.c
+++ b/modules/stream_out/description.c
@@ -136,7 +136,8 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
     VLC_UNUSED(id);
     sout_stream_sys_t *p_sys = p_stream->p_sys;
 
-    block_ChainRelease( p_buffer );
+    if( p_buffer )
+        block_ChainRelease( p_buffer );
 
     if( p_sys->i_stream_start + 1500000 < mdate() )
         vlc_sem_post(p_sys->data->sem);
diff --git a/modules/stream_out/display.c b/modules/stream_out/display.c
index 246fd3ba8b..7bc2bd140a 100644
--- a/modules/stream_out/display.c
+++ b/modules/stream_out/display.c
@@ -168,6 +168,12 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
 {
     sout_stream_sys_t *p_sys = p_stream->p_sys;
 
+    if( unlikely( p_buffer == NULL ) )
+    {
+        input_DecoderDrain( (decoder_t *)id );
+        return VLC_SUCCESS;
+    }
+
     while( p_buffer )
     {
         block_t *p_next = p_buffer->p_next;
diff --git a/modules/stream_out/dummy.c b/modules/stream_out/dummy.c
index a4e105b978..efb9f3edd2 100644
--- a/modules/stream_out/dummy.c
+++ b/modules/stream_out/dummy.c
@@ -85,7 +85,8 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
                  block_t *p_buffer )
 {
     (void)p_stream; (void)id;
-    block_ChainRelease( p_buffer );
+    if( p_buffer )
+        block_ChainRelease( p_buffer );
     return VLC_SUCCESS;
 }
 
diff --git a/modules/stream_out/duplicate.c b/modules/stream_out/duplicate.c
index 983004d82f..b4630d734d 100644
--- a/modules/stream_out/duplicate.c
+++ b/modules/stream_out/duplicate.c
@@ -266,6 +266,18 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
     int               i_stream;
 
     /* Loop through the linked list of buffers */
+
+    if( unlikely( p_buffer == NULL ) )
+    {
+        /* Drain */
+        for( i_stream = 0; i_stream < p_sys->i_nb_streams; i_stream++ )
+        {
+            p_dup_stream = p_sys->pp_streams[i_stream];
+            sout_StreamIdSend( p_dup_stream, id->pp_ids[i_stream], NULL );
+        }
+        return VLC_SUCCESS;
+    }
+
     while( p_buffer )
     {
         block_t *p_next = p_buffer->p_next;
diff --git a/modules/stream_out/gather.c b/modules/stream_out/gather.c
index 2adfbab332..7f93241ba2 100644
--- a/modules/stream_out/gather.c
+++ b/modules/stream_out/gather.c
@@ -209,7 +209,7 @@ static void Del( sout_stream_t *p_stream, sout_stream_id_sys_t *id )
 static int Send( sout_stream_t *p_stream,
                  sout_stream_id_sys_t *id, block_t *p_buffer )
 {
-    if ( id->b_streamswap )
+    if ( id->b_streamswap && p_buffer != NULL )
     {
         id->b_streamswap = false;
         p_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY;
diff --git a/modules/stream_out/mosaic_bridge.c b/modules/stream_out/mosaic_bridge.c
index e0f9ff4c8f..6c520bfda2 100644
--- a/modules/stream_out/mosaic_bridge.c
+++ b/modules/stream_out/mosaic_bridge.c
@@ -573,7 +573,8 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
 
     if ( (sout_stream_sys_t *)id != p_sys )
     {
-        block_ChainRelease( p_buffer );
+        if( p_buffer != NULL )
+            block_ChainRelease( p_buffer );
         return VLC_SUCCESS;
     }
 
diff --git a/modules/stream_out/record.c b/modules/stream_out/record.c
index b8d6b94359..93cb119dc4 100644
--- a/modules/stream_out/record.c
+++ b/modules/stream_out/record.c
@@ -578,6 +578,13 @@ static void OutputSend( sout_stream_t *p_stream, sout_stream_id_sys_t *id, block
 
     if( id->id )
     {
+        if( unlikely( p_block == NULL ) )
+        {
+            /* Drain */
+            sout_StreamIdSend( p_sys->p_out, id->id, NULL );
+            return;
+        }
+
         /* We wait until the first key frame (if needed) and
          * to be beyong i_dts_start (for stream without key frame) */
         if( unlikely( id->b_wait_key ) )
diff --git a/modules/stream_out/smem.c b/modules/stream_out/smem.c
index 43ad651fd1..d779fdbc67 100644
--- a/modules/stream_out/smem.c
+++ b/modules/stream_out/smem.c
@@ -353,6 +353,11 @@ static void Del( sout_stream_t *p_stream, sout_stream_id_sys_t *id )
 static int Send( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
                  block_t *p_buffer )
 {
+    if ( unlikely( p_buffer == NULL ) )
+    {
+        /* TODO: Drain */
+        return VLC_SUCCESS;
+    }
     if ( id->format.i_cat == VIDEO_ES )
         return SendVideo( p_stream, id, p_buffer );
     else if ( id->format.i_cat == AUDIO_ES )
diff --git a/modules/stream_out/transcode/transcode.c b/modules/stream_out/transcode/transcode.c
index 9cd403f4f6..b4e82ac893 100644
--- a/modules/stream_out/transcode/transcode.c
+++ b/modules/stream_out/transcode/transcode.c
@@ -561,11 +561,9 @@ static void Del( sout_stream_t *p_stream, sout_stream_id_sys_t *id )
         switch( id->p_decoder->fmt_in.i_cat )
         {
         case AUDIO_ES:
-            Send( p_stream, id, NULL );
             transcode_audio_close( id );
             break;
         case VIDEO_ES:
-            Send( p_stream, id, NULL );
             transcode_video_close( p_stream, id );
             break;
         case SPU_ES:
@@ -627,9 +625,13 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
         goto error;
     }
 
+    int ret = VLC_SUCCESS;
     if( p_out )
-        return sout_StreamIdSend( p_stream->p_next, id->id, p_out );
-    return VLC_SUCCESS;
+        ret = sout_StreamIdSend( p_stream->p_next, id->id, p_out );
+
+    if( ret == VLC_SUCCESS && unlikely( p_buffer == NULL ) )
+        ret = sout_StreamIdSend( p_stream->p_next, id->id, NULL );
+    return ret;
 error:
     if( p_buffer )
         block_Release( p_buffer );
-- 
2.11.0



More information about the vlc-devel mailing list