[FFmpeg-devel] [PATCH] libavformat/tee: Add fifo support for tee

Michael Niedermayer michael at niedermayer.cc
Fri Oct 7 23:25:35 EEST 2016


On Fri, Oct 07, 2016 at 01:03:03AM +0200, sebechlebskyjan at gmail.com wrote:
> From: Jan Sebechlebsky <sebechlebskyjan at gmail.com>
> 
> Signed-off-by: Jan Sebechlebsky <sebechlebskyjan at gmail.com>
> ---
> This commit makes use of fifo muxer together with tee muxer
> easier, fifo muxer does not have to be explicitly specified
> for each slave. For the most simple use case it is sufficient
> to turn fifo muxer on for all slaves by switching on use_fifo
> option. Same options can be passed to all fifo muxer instances of
> slaves by assigning them to fifo_options of tee. 
> Both use_fifo option and individual fifo_options can be 
> overriden per slave if needed.
> 
>  doc/muxers.texi   | 20 +++++++++++++
>  libavformat/tee.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 108 insertions(+), 1 deletion(-)
> 
> diff --git a/doc/muxers.texi b/doc/muxers.texi
> index 9ec2e31..b88b83c 100644
> --- a/doc/muxers.texi
> +++ b/doc/muxers.texi
> @@ -1473,6 +1473,7 @@ Specify whether to remove all fragments when finished. Default 0 (do not remove)
>  
>  @end table
>  
> + at anchor{fifo}
>  @section fifo
>  
>  The fifo pseudo-muxer allows the separation of encoding and muxing by using
> @@ -1580,6 +1581,18 @@ with the tee muxer; encoding can be a very expensive process. It is not
>  useful when using the libavformat API directly because it is then possible
>  to feed the same packets to several muxers directly.
>  
> + at table @option
> +
> + at item use_fifo @var{bool}
> +If set to 1, slave outputs will be processed in separate thread using @ref{fifo}
> +muxer. This allows to compensate for different speed/latency/reliability of
> +outputs and setup transparent recovery. By default this feature is turned off.
> +
> + at item fifo_options
> +Options to pass to fifo pseudo-muxer instances. See @ref{fifo}.
> +
> + at end table
> +
>  The slave outputs are specified in the file name given to the muxer,
>  separated by '|'. If any of the slave name contains the '|' separator,
>  leading or trailing spaces or any special character, it must be
> @@ -1601,6 +1614,13 @@ output name suffix.
>  Specify a list of bitstream filters to apply to the specified
>  output.
>  
> + at item use_fifo @var{bool}
> +This allows to override tee muxer use_fifo option for individual slave muxer.
> +
> + at item fifo_options
> +This allows to override tee muxer fifo_options for individual slave muxer.
> +See @ref{fifo}.
> +
>  It is possible to specify to which streams a given bitstream filter
>  applies, by appending a stream specifier to the option separated by
>  @code{/}. @var{spec} must be a stream specifier (see @ref{Format
> diff --git a/libavformat/tee.c b/libavformat/tee.c
> index d59ad4d..764135d 100644
> --- a/libavformat/tee.c
> +++ b/libavformat/tee.c
> @@ -40,6 +40,8 @@ typedef struct {
>      AVBSFContext **bsfs; ///< bitstream filters per stream
>  
>      SlaveFailurePolicy on_fail;
> +    int use_fifo;
> +    AVDictionary *fifo_options;
>  
>      /** map from input to output streams indexes,
>       * disabled output streams are set to -1 */
> @@ -52,15 +54,28 @@ typedef struct TeeContext {
>      unsigned nb_slaves;
>      unsigned nb_alive;
>      TeeSlave *slaves;
> +    int use_fifo;
> +    AVDictionary *fifo_options;
> +    char *fifo_options_str;
>  } TeeContext;
>  
>  static const char *const slave_delim     = "|";
>  static const char *const slave_bsfs_spec_sep = "/";
>  static const char *const slave_select_sep = ",";
>  
> +#define OFFSET(x) offsetof(TeeContext, x)
> +static const AVOption options[] = {
> +        {"use_fifo", "Use fifo pseudo-muxer to separate actual muxers from encoder",
> +         OFFSET(use_fifo), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
> +        {"fifo_options", "fifo pseudo-muxer options", OFFSET(fifo_options_str),
> +         AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM},
> +        {NULL}
> +};
> +
>  static const AVClass tee_muxer_class = {
>      .class_name = "Tee muxer",
>      .item_name  = av_default_item_name,
> +    .option = options,
>      .version    = LIBAVUTIL_VERSION_INT,
>  };
>  
> @@ -81,6 +96,27 @@ static inline int parse_slave_failure_policy_option(const char *opt, TeeSlave *t
>      return AVERROR(EINVAL);
>  }
>  
> +static int parse_slave_fifo_options(const char * use_fifo,
> +                                    const char * fifo_options, TeeSlave * tee_slave)
> +{
> +    int ret = 0;
> +
> +    if (use_fifo) {
> +        if (av_match_name(use_fifo, "true,y,yes,enable,enabled,on,1")) {
> +            tee_slave->use_fifo = 1;
> +        } else if (av_match_name(use_fifo, "false,n,no,disable,disabled,off,0")) {
> +            tee_slave->use_fifo = 0;
> +        } else {
> +            return AVERROR(EINVAL);
> +        }
> +    }
> +
> +    if (fifo_options)
> +        ret = av_dict_parse_string(&tee_slave->fifo_options, fifo_options, "=", ":", 0);
> +
> +    return ret;
> +}
> +
>  static int close_slave(TeeSlave *tee_slave)
>  {
>      AVFormatContext *avf;
> @@ -125,6 +161,7 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
>      AVDictionaryEntry *entry;
>      char *filename;
>      char *format = NULL, *select = NULL, *on_fail = NULL;
> +    char *use_fifo = NULL, *fifo_options_str = NULL;
>      AVFormatContext *avf2 = NULL;
>      AVStream *st, *st2;
>      int stream_count;
> @@ -145,6 +182,8 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
>      STEAL_OPTION("f", format);
>      STEAL_OPTION("select", select);
>      STEAL_OPTION("onfail", on_fail);
> +    STEAL_OPTION("use_fifo", use_fifo);
> +    STEAL_OPTION("fifo_options", fifo_options_str);
>  
>      ret = parse_slave_failure_policy_option(on_fail, tee_slave);
>      if (ret < 0) {
> @@ -153,7 +192,43 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
>          goto end;
>      }
>  
> -    ret = avformat_alloc_output_context2(&avf2, NULL, format, filename);
> +    ret = parse_slave_fifo_options( use_fifo, fifo_options_str, tee_slave);
> +    if (ret < 0) {
> +        av_log(avf, AV_LOG_ERROR, "Error parsing fifo options: %s\n", av_err2str(ret));
> +        goto end;
> +    }
> +
> +    if (tee_slave->use_fifo) {
> +
> +        if (options) {
> +            char *format_options_str = NULL;
> +            ret = av_dict_get_string(options, &format_options_str, '=', ':');
> +            if (ret < 0)
> +                goto end;
> +
> +            ret = av_dict_set(&tee_slave->fifo_options, "format_options", format_options_str,
> +                              AV_DICT_DONT_STRDUP_VAL);
> +            if (ret < 0) {
> +                av_free(format_options_str);

double free i think


> +                goto end;
> +            }
> +        }
> +
> +        if (format) {
> +            ret = av_dict_set(&tee_slave->fifo_options, "fifo_format", format,
> +                              AV_DICT_DONT_STRDUP_VAL);
> +            if (ret < 0)
> +                goto end;

here too

see: av_dist_set() doxy
 * Note: If AV_DICT_DONT_STRDUP_KEY or AV_DICT_DONT_STRDUP_VAL is set,
 * these arguments will be freed on error.
 
[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

The real ebay dictionary, page 2
"100% positive feedback" - "All either got their money back or didnt complain"
"Best seller ever, very honest" - "Seller refunded buyer after failed scam"
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20161007/1910d6ff/attachment.sig>


More information about the ffmpeg-devel mailing list