[FFmpeg-devel] Blocking vs non-blocking modes in protocols

Nicolas George george at nsup.org
Mon Sep 2 18:21:22 EEST 2019


Andriy Gelman (12019-09-01):
> Below are my notes on blocking and non-blocking modes in protocols. Proposed
> changes that I'd like to make are at the end. 
> 
> Thanks, 
> Andriy
> 
> 
> ---General notes--
> -blocking mode-
>     - transfer_function deals with polling and timeout
>     - block inside transfer_function for max rw_timeout. 
>     - if rw_timeout expires the protocol designers have two options:  
>        (1) transfer_funciton returns AVERROR(ETIMEDOUT).  This will cause the
>            encoding/decoding to exit with timeout error.
>        (2) transfer_function returns AVERROR(EINTR).  Immediately retry the
>            transfer_function after checking interrupt callback.
>     
> -non-blocking mode-
>     - retry_transfer_wrapper deals with retries
>     - if read/writes are not available transfer_function should immediately
>       return with AVERROR(EAGAIN)

>     - retry transfer_function with 5 x fast_retry (no sleep). Then, retry with
>       1ms sleep.  
>     - If rw_timeout expires, exit encoding/decoding with AVERROR(EIO) (Probably
>       should be changed to AVERROR(ETIMEDOUT) to be consistent with blocking
>       mdoe.

This looks like one of the reasons the non-blocking mode does not work.

> But overall, the two modes seem similar to me: 
>     - "Blocking" - blocks at the transfer_function
>     - "Non-blocking" - blocks in retry_transfer_function

The expected behaviour is: non-blocking does not block.

> ----Potential advantage of non-blocking over blocking mode----
> I'm trying to figure what would be the advantage of non-blocking over blocking
> modes. The only reason I can think of: non-blocking mode gives more control to
> the user rather than protocol designer. In non-blocking mode the user can force
> an exit after rw_timeout expires. On the other hand, in blocking mode, the
> protocol designer can force a retry by returing AVERROR(EINTR) after rw_timeout
> expires instead of exiting the code (i.e. after AVERROR(ETIMEDOUT) is returned).
> 
> Any other reason someone would prefer non-blocking over blocking modes? 

I am not sure I read you correctly, I think you are saying that
blocking/non-blocking mode is a design decision for protocol
implementors. The difference between blocking and non-blocking mode is
not meant for the internal design of FFmpeg but for applications.

An application that has several live inputs (network, device, GUI (a GUI
is one big live input)) cannot be blocked reading on one of them,
because it needs to react to the others immediately. The application
design is then to have all live inputs in non-blocking mode, and walk
over them, like this:

while (1) {
    wait_for_any_input();
    for (input)
        process_input_non_blocking(input);
}

(If the application is CPU-bound rather than input-bound,
wait_for_any_input() will need to be rather
perform_a_slice_of_computation().)

(Some applications, including FFmpeg, will have wait_a_small_time()
instead of wait_for_any_input(), but that is terrible design and a waste
of energy that contributes to global warming.)

> ----Proposed changes----
>     (1) At the moment, non-blocking mode immediately exits after AVERROR(EAGAIN)
>     is returned without doing any retries. I'm quite sure there is a bug on
>     avio.c:379. It should be changed to: if (!(h->flags & AVIO_FLAG_NONBLOCK))

In non-blocking mode, if no data is available, the flow must return to
the application immediately with AVERROR(EAGAIN).

>     (3) Update avio.h/url.h to clarify difference between AVERROR(ETIMEDOUT) and
>     AVERROR(EINTR) in blocking mode.

The semantic of EINTR is "Unix sucks, signals are terribly badly
designed". It should never be used in our code except to deal with that
bad design.

>     (4) Add non-blocking option to the cli. Something like -avioflags
>     nonblocking. But add a note that this may not be supported by a specific
>     protocol 

Working in blocking or non-blocking mode means a completely different
design of the program, making it an option does not make sense.

>     (5) If rw_timeout expires in non-blocking mode, return AVERROR(ETIMEDOUT)
>     instead of AVERROR(EIO) to be consistent with blocking mode.

In non-blocking mode, there can be no timeout because there can be no
time. If there is, it is a bug.

Note: Currently, non-blocking mode works for a few cases but is
completely broken in most of FFmpeg's code base. In a subsequent mail I
will try to summarise the state of affairs and how it could be enhanced.

Regards,

-- 
  Nicolas George
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20190902/c9699e29/attachment.sig>


More information about the ffmpeg-devel mailing list