[vlc-devel] [PATCH] srt: Read several chunks per blocking read call

Olivier Crête olivier.crete at collabora.com
Mon Jul 23 20:01:40 CEST 2018


Hi,

Re-ping for this patch? It makes a big difference for high bitrate
streams, it makes 4K streams usable on normal computers.

Olivier

On Fri, 2018-07-13 at 18:25 -0400, Olivier Crête wrote:
> From: Roman Diouskine <rdiouskine at haivision.com>
> 
> It is possible to get an empty read from libsrt and it should not be
> treated as EOF.
> 
> libsrt input is asynchonously buffered internally and it makes sense
> to empty those receive buffers as much as possible on every signaled
> receive event from epoll. Doing so reduces context
> switching/re-scheduling and improves performance.
> ---
>  modules/access/srt.c | 62 ++++++++++++++++++++++++++++++++++------
> ----
>  1 file changed, 48 insertions(+), 14 deletions(-)
> 
> diff --git a/modules/access/srt.c b/modules/access/srt.c
> index a1c9acca50..b21a9b64c7 100644
> --- a/modules/access/srt.c
> +++ b/modules/access/srt.c
> @@ -40,6 +40,9 @@
>  /* libsrt defines default packet size as 1316 internally
>   * so srt module takes same value. */
>  #define SRT_DEFAULT_CHUNK_SIZE 1316
> +/* Minimum/Maximum chunks to allow reading at a time from libsrt */
> +#define SRT_MIN_CHUNKS_TRYREAD 10
> +#define SRT_MAX_CHUNKS_TRYREAD 100
>  /* The default timeout is -1 (infinite) */
>  #define SRT_DEFAULT_POLL_TIMEOUT -1
>  /* The default latency is 125
> @@ -64,6 +67,7 @@ typedef struct
>      bool        b_interrupted;
>      char       *psz_host;
>      int         i_port;
> +    int         i_chunks;
>  } stream_sys_t;
>  
>  static void srt_wait_interrupted(void *p_data)
> @@ -193,6 +197,11 @@ static bool srt_schedule_reconnect(stream_t
> *p_stream)
>          failed = true;
>      }
>  
> +    /* Reset read chunks number because
> +     * the stream might have changed
> +     */
> +    p_sys->i_chunks = SRT_MIN_CHUNKS_TRYREAD;
> +
>  out:
>      if (failed && p_sys->sock != SRT_INVALID_SOCK)
>      {
> @@ -212,6 +221,8 @@ static block_t *BlockSRT(stream_t *p_stream, bool
> *restrict eof)
>      stream_sys_t *p_sys = p_stream->p_sys;
>      int i_chunk_size = var_InheritInteger( p_stream, "chunk-size" );
>      int i_poll_timeout = var_InheritInteger( p_stream, "poll-
> timeout" );
> +    /* SRT doesn't have a concept of EOF for live streams. */
> +    VLC_UNUSED(eof);
>  
>      if ( vlc_killed() )
>      {
> @@ -219,13 +230,18 @@ static block_t *BlockSRT(stream_t *p_stream,
> bool *restrict eof)
>          return NULL;
>      }
>  
> -    block_t *pkt = block_Alloc( i_chunk_size );
> +    size_t i_chunk_size_actual = ( i_chunk_size > 0 )
> +        ? i_chunk_size : SRT_DEFAULT_CHUNK_SIZE;
> +    int chunks = ( p_sys->i_chunks )
> +        ? p_sys->i_chunks : SRT_MIN_CHUNKS_TRYREAD;
> +    size_t bufsize = i_chunk_size_actual * chunks;
> +    block_t *pkt = block_Alloc( bufsize );
>      if ( unlikely( pkt == NULL ) )
>      {
>          return NULL;
>      }
>  
> -    vlc_interrupt_register( srt_wait_interrupted, p_stream);
> +    vlc_interrupt_register( srt_wait_interrupted, p_stream );
>  
>      SRTSOCKET ready[1];
>      int readycnt = 1;
> @@ -257,23 +273,41 @@ static block_t *BlockSRT(stream_t *p_stream,
> bool *restrict eof)
>                  continue;
>          }
>  
> -        int stat = srt_recvmsg( p_sys->sock,
> -            (char *)pkt->p_buffer, i_chunk_size );
> -        if ( stat > 0 )
> +        /* Try to read all available data from the lib up to
> +         * predefined buffer size. The buffer size can grow over
> time
> +         * up to predefined maximum.
> +         */
> +        size_t bytesread = 0;
> +        while ( (bufsize - bytesread) >= i_chunk_size_actual )
>          {
> -            pkt->i_buffer = stat;
> -            goto out;
> +            int stat = srt_recvmsg( p_sys->sock,
> +                (char *)( pkt->p_buffer + bytesread ), bufsize -
> bytesread );
> +            if ( stat <= 0 )
> +            {
> +                break;
> +            }
> +            bytesread += (size_t)stat;
>          }
>  
> -        msg_Err( p_stream, "failed to receive packet, set EOS
> (reason: %s)",
> -            srt_getlasterror_str() );
> -        *eof = true;
> -        break;
> +        /* Gradually adjust number of chunks we read at a time
> +        * up to a predefined maximum. The actual number we might
> +        * settle on depends on stream's bit rate.
> +        */
> +        size_t rem = bufsize - bytesread;
> +        if ( rem < i_chunk_size_actual )
> +        {
> +            if ( ++chunks <= SRT_MAX_CHUNKS_TRYREAD )
> +            {
> +                p_sys->i_chunks = chunks;
> +            }
> +        }
> +
> +        pkt->i_buffer = bytesread;
> +        goto out;
>      }
>  
> -    /* if the poll reports errors for any reason at all
> -     * including a timeout, or there is a read error,
> -     * we skip the turn.
> +    /* if the poll reports errors for any reason at all,
> +     * including a timeout, we skip the turn.
>       */
>  
>      block_Release(pkt);
-- 
Olivier Crête
olivier.crete at collabora.com


More information about the vlc-devel mailing list