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

Andriy Gelman andriy.gelman at gmail.com
Tue Sep 3 06:00:52 EEST 2019


Nicolas, thank you for clarifying  

On Mon, 02. Sep 17:21, Nicolas George wrote:
> 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).

I assumed that the set of retries in retry_transfer_wrapper were aimed at the
non-blocking mode. But these retries are not called at the moment when the
AVIO_FLAG_NONBLOCK flag is set. 
As I understand from your reply this is the correct behaviour. 

> 
> >     (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.

Thanks,
Andriy


More information about the ffmpeg-devel mailing list