[FFmpeg-devel] [PATCH] libavformat: Add FIFO pseudo-muxer

Marton Balint cus at passwd.hu
Fri Jul 8 23:39:37 EEST 2016

On Fri, 8 Jul 2016, Nicolas George wrote:

> Le primidi 21 messidor, an CCXXIV, Jan Sebechlebsky a écrit :
>> I actually thought about this and maybe I am still missing something, but
>> how is this different from the situation without FIFO muxer?
> It is not, which is exactly the answer you do not want when people ask what
> your program is good for.
>> When the FIFO is not used, let's say an I/O operation somewhere inside
>> write_packet call blocks for a long time - actually it means it is spinning
>> in a cycle "wait for io with short timeout"<->"check return value of
>> interrupt callback". When the application decides to interrupt the
>> operation, it sets some interrupt condition (ffmpeg increments
>> received_nb_signals when receives SIGINT). The next call to interrupt
>> callback will cause the IO function to return AVERROR_EXIT causing
>> write_packet to fail with same error.
>> When the FIFO is used the write_packet call will return immediately. The I/O
>> blocking will happen in consumer thread, in some of the
>> fifo_thread_write_packet calls. Let's say that during that time all packets
>> are send to queue and write_trailer is called. The main thread
>> is blocked by pthread_join(). However when the interrupt condition is set
>> (for example by receiving SIGINT as in ffmpeg), this is still handled by the
>> blocking IO function which will return AVERROR_EXIT causing
>> fifo_thread_write_packet to fail with the same error, causing the thread to
>> terminate which unblocks write_trailer.
>> My point is that the same asynchronous mechanism which is supposed to work
>> in case of blocking I/O operation should work also in case pthread_join is
>> blocking, so the I/O operation should be terminated the same way returning
>> AVERROR_EXIT which will cause consumer thread to terminate and unblock
>> pthread_join call...
>> Am I missing something?
> I think you are missing (not in the sense of your question) a clear mission
> statement for the FIFO muxer. Or, to put another way, a detailed explanation
> of what it is useful for and more importantly, how to benefit from it.

The basic goals are the ones which are set in the GSOC trac page under the 
tee muxer improvement project:

Description: FFmpeg contains a tee muxer, which is capable of writing the 
same coded packets to multiple outputs. However, if one of the outputs 
blocks or fails for any reason, the other outputs will block or fail too. 
Also there is no built-in support for gracefully restarting an output in 
case of a failure. Lacking these two features makes the tee muxer 
unsuitable for redundancy or high availability purposes especially on 
networked outputs.

Expected results:
•Add a non-blocking mode with a configurable maximum packet queue size 
where one output does not block the others
•Add a graceful restart mode where a failed output can transparently 
automatically restart its operation

We decided to implement these features in a separate muxer, instead of 
hard coding it to tee, but the goals are the same. In order to reach 
them, one will have to specify fifo muxers in the output of the tee muxer, 
or Jan can work on some syntactic sugar which makes this more convenient 
for the user, but the result is the same.

> If I understand things correctly, it is meant to be used by applications (or
> libraries, including the tee muxer), not directly by users. But how are the
> applications supposed to do exactly, and what can they expect.

It also can be used by users. For example in blocking mode the fifo 
muxer can work as a pipeline between the encoder and the output, hiding 
disk latencies. In this scenario the user don't need to use the tee muxer 
to grab the benefits of the fifo muxer. In this case, it works similarly 
as the async protocol for input, only for output.

> One of the features seems to be to turn a blocking muxer into a non-blocking
> muxer, which is indeed useful. But if the muxer falls back to blocking on
> close and the application needs to set up a thread-synchronized interrupt
> callback to handle it, then I feel we are missing a serious opportunity.

The reason why neither me (and I guess nor Jan) sees this as an issue, is 
that this is not needed for the goals set in the project. We simply don't 
care if closeing a stream blocks, that is not what we are aiming for here.

> The way I see it, in non-blocking mode, the most logical approach would be
> something like this: the first call to write_header() causes the closing
> process to start an returns EAGAIN immediately, subsequent calls return
> EAGAIN until the closing process is done, then 0 for success, or an error
> code after a configurable timeout.

Sure, this can be implemented (although an API change, so dificcult to 
pull through), but in GSOC this was simply not a goal of ours.


More information about the ffmpeg-devel mailing list