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

Thomas Guillem thomas at gllm.fr
Tue Oct 16 10:26:19 CEST 2018


Merged !

On Mon, Oct 15, 2018, at 17:45, Olivier CrĂȘte wrote:
> From: Roman Diouskine <rdiouskine at haivision.com>
> 
> 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 | 71 ++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 59 insertions(+), 12 deletions(-)
> 
> diff --git a/modules/access/srt.c b/modules/access/srt.c
> index 5b7734310b..d8d8cbe659 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; /* Number of chunks to allocate in the next read */
>  } 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 the number of chunks to allocate as the bitrate of
> +     * the stream may have changed.
> +     */
> +    p_sys->i_chunks = SRT_MIN_CHUNKS_TRYREAD;
> +
>  out:
>      if (failed && p_sys->sock != SRT_INVALID_SOCK)
>      {
> @@ -221,7 +230,13 @@ static block_t *BlockSRT(stream_t *p_stream, bool 
> *restrict eof)
>          return NULL;
>      }
>  
> -    block_t *pkt = block_Alloc( i_chunk_size );
> +    if ( p_sys->i_chunks == 0 )
> +        p_sys->i_chunks = SRT_MIN_CHUNKS_TRYREAD;
> +
> +    size_t i_chunk_size_actual = ( i_chunk_size > 0 )
> +        ? i_chunk_size : SRT_DEFAULT_CHUNK_SIZE;
> +    size_t bufsize = i_chunk_size_actual * p_sys->i_chunks;
> +    block_t *pkt = block_Alloc( bufsize );
>      if ( unlikely( pkt == NULL ) )
>      {
>          return NULL;
> @@ -259,26 +274,58 @@ 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 get as much data as possible out of the lib, if there
> +         * is still some left, increase the number of chunks to read so that
> +         * it will read faster on the next iteration. This way the buffer will
> +         * grow until it reads fast enough to keep the library empty after
> +         * each iteration.
> +         */
> +        pkt->i_buffer = 0;
> +        while ( ( bufsize - pkt->i_buffer ) >= i_chunk_size_actual )
> +        {
> +            int stat = srt_recvmsg( p_sys->sock,
> +                (char *)( pkt->p_buffer + pkt->i_buffer ),
> +                bufsize - pkt->i_buffer );
> +            if ( stat <= 0 )
> +            {
> +                break;
> +            }
> +            pkt->i_buffer += (size_t)stat;
> +        }
> +
> +        msg_Dbg ( p_stream, "Read %zu bytes out of a max of %zu"
> +            " (%d chunks of %zu bytes)", pkt->i_buffer,
> +            p_sys->i_chunks * i_chunk_size_actual, p_sys->i_chunks,
> +                 i_chunk_size_actual );
> +
> +
> +        /* 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 - pkt->i_buffer;
> +        if ( rem < i_chunk_size_actual )
>          {
> -            pkt->i_buffer = stat;
> -            goto out;
> +            if ( p_sys->i_chunks < SRT_MAX_CHUNKS_TRYREAD )
> +            {
> +                p_sys->i_chunks++;
> +            }
>          }
>  
>          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);
> -    pkt = NULL;
> +    pkt->i_buffer = 0;
>  
>  out:
> +    if (pkt->i_buffer == 0) {
> +      block_Release(pkt);
> +      pkt = NULL;
> +    }
> +
>      vlc_interrupt_unregister();
>  
>      /* Re-add the socket to the poll if we were interrupted */
> -- 
> 2.17.2
> 
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list