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

Jan Sebechlebsky sebechlebskyjan at gmail.com
Tue Jun 28 17:11:25 CEST 2016


Hello Nicolas,

On 06/28/2016 03:42 PM, Nicolas George wrote:
> +The fifo pseudo-muxer allows to separate encoding from any other muxer
> +by using first-in-first-out queue and running the actual muxer in separate
> +thread. This is especially useful in combination with tee muxer
> +and output to several destinations with different reliability/writing speed/latency.
> +
> +The fifo muxer can operate in regular or fully non-blocking mode. This determines
> Not true: the current code is non-blocking for packets, but not for the
> trailer. It can not be really non-blocking but as is it can block
> indefinitely.
>
>> +the behaviour in case the queue fills up. In regular mode the encoding is blocked
>> +until muxer processes some of the packets from queue, in non-blocking mode the packets
>> +are thrown away rather than blocking the encoder (this might be useful in real-time
>> +streaming scenario).
Would it be ok to call it "asynchronous"?
>> + at item fifo_format
>> +Specify the format name. Useful if it cannot be guessed from the
>> +output name suffix.
> This option is defined but never used.
I don't understand this note - the fifo_format option is used (and seems 
to work)?
>> +
>> + at item queue_size
>> +Specify size of the queue (number of packets)
>> +
>> + at item format_opts
>> +Specify format options for the underlying muxer. Muxer options can be specified
>> +as a list of @var{key}=@var{value} pairs separated by ':'.
> Yay, another trip to escaping hell!
Unfortunately :( Do you think cmd muxer initialization could be easily 
modified in a way that muxer would also get access to option dictionary?
>
>> +    if (!(avf2->oformat->flags & AVFMT_NOFILE)) {
>> +        ret = avf2->io_open(avf2, &avf2->pb, avf->filename, AVIO_FLAG_WRITE, &format_options);
>> +        if (ret < 0) {
>> +            av_log(avf, AV_LOG_ERROR, "Error opening %s: %s\n",
>> +                   avf->filename, av_err2str(ret));
>> +            goto end;
>> +        }
>> +    }
> Why do we not have a utility function for that?
>
I'll create ff_format_io_open and, this can be refactored in other 
muxer, too.

>> +    s_idx = pkt->stream_index;
>> +    src_tb = avf->streams[s_idx]->time_base;
>> +    dst_tb = avf2->streams[s_idx]->time_base;
>> +
>> +    pkt->pts = av_rescale_q(pkt->pts, src_tb, dst_tb);
>> +    pkt->dts = av_rescale_q(pkt->dts, src_tb, dst_tb);
>> +    pkt->duration = av_rescale_q(pkt->duration, src_tb, dst_tb);
> This looks suspicious.
>
> For starters, it does not handle the NOPTS value, but that is an easy fix.
>
> More worryingly, it looks that the application does not see the time base
> selected by the real muxer. It could be a problem.
I'll change it to handle NOPTS (the same should be done for tee muxer, 
so I'll patch that too). Can you specify what could be the problem when 
the application does not see the time base of real muxer? If it was 
really neccessary, I can make write_header call before actually 
executing the thread (so only write_packet calls would be non-blocking) 
and copy the selected timebase, however, I prefer write_header to be 
executed in consumer thread. Also, this situation is impossible to 
handle in tee muxer, since every slave muxer can select different time base.
>
>> +        /* Check and solve overflow */
>> +        pthread_mutex_lock(&fifo->overflow_flag_lock);
>> +        if (fifo->overflow_flag) {
>> +            av_thread_message_flush(queue);
>> +            if (fifo->restart_with_keyframe)
>> +                fifo->drop_until_keyframe = 1;
>> +            fifo->overflow_flag = 0;
>> +            just_flushed = 1;
>> +        }
>> +        pthread_mutex_unlock(&fifo->overflow_flag_lock);
> I think the communication logic here needs an extensive comment here.
>
> And I am a bit worried about the extra lock: mixing several communication
> mechanisms between threads is a recipe for headache.
I'll add the comment. I've tried to do this without the extra lock at 
first by setting error to the thread message queue and adding 
threadmessage queue flag which allows the error to be returned 
immediately, but I think using this single extra lock is really cleaner 
solution, I would prefer that.
>
>> +    avf2->io_close = avf->io_close;
>> +    avf2->io_open = avf->io_open;
> This could be dangerous too, I am not sure these functions are guaranteed to
> be thread-safe. It needs at least documentation.
I'll try to check existing functions for dangerous operations - I guess 
we could add a note to documentation saying that the io_{open,close} 
should be thread-safe.
>> +        st2->r_frame_rate        = st->r_frame_rate;
>> +        st2->time_base           = st->time_base;
>> +        st2->start_time          = st->start_time;
>> +        st2->duration            = st->duration;
>> +        st2->nb_frames           = st->nb_frames;
>> +        st2->disposition         = st->disposition;
>> +        st2->sample_aspect_ratio = st->sample_aspect_ratio;
>> +        st2->avg_frame_rate      = st->avg_frame_rate;
> Why do we not have an utility function for that (bis)?
I've actually created the function av_stream_encode_params_copy:

https://github.com/jsebechlebsky/FFmpeg/commit/c46a35b19daa0f58efb70254e30bbd767f5d62ef

but not submitted the patch yet. I was not completely sure what fields 
actually have to be copied. In segment muxer some of them are ommited. 
Tee muxer copies all of those, but've I checked documentation for all 
the fields which might be used during encoding and there is one more - 
AVPacketSideData* side_data field (together with nb_side_data) which 
might be used during muxing. So I guess I'll stick to documentation and 
copy everything which might be set during encoding according to 
documentation.

I agree with all other suggested changes and will implement them.

Thanks for feedback!

Regards,
Jan


More information about the ffmpeg-devel mailing list