[FFmpeg-devel] [RFC] lavf/tee per-output stream selection

Stefano Sabatini stefasab at gmail.com
Wed Aug 21 17:17:22 CEST 2013


On date Wednesday 2013-08-21 15:01:44 +0200, Nicolas George encoded:
> Le duodi 2 fructidor, an CCXXI, Stefano Sabatini a écrit :
> > Updated and rebased.
> > -- 
> > FFmpeg = Faithless Fast Majestic Perennial Extravagant Ghost
> 
> > >From b49874d5420cc2c0d8c6b3933ae74b8bebb9fb8d Mon Sep 17 00:00:00 2001
> > From: Stefano Sabatini <stefasab at gmail.com>
> > Date: Thu, 8 Aug 2013 12:11:59 +0200
> > Subject: [PATCH] lavf/tee: add special select option
> > 
> > TODO: bump micro
> > ---
> >  doc/muxers.texi   |  5 +++++
> >  libavformat/tee.c | 57 +++++++++++++++++++++++++++++++++++++++++++------------
> >  2 files changed, 50 insertions(+), 12 deletions(-)
> > 
> > diff --git a/doc/muxers.texi b/doc/muxers.texi
> > index 52da73e..c9c4416 100644
> > --- a/doc/muxers.texi
> > +++ b/doc/muxers.texi
> > @@ -871,6 +871,11 @@ separated by @code{/}. If the stream specifier is not specified, the
> >  bistream filters will be applied to all streams in the output.
> >  
> >  Several bitstream filters can be specified, separated by ",".
> > +
> > + at item select
> > +Select the streams that should be mapped to the slave output,
> > +specified by a stream specifier. If not specified, this defaults to
> > +all the input streams.
> >  @end table
> >  
> >  Example: encode something and both archive it in a WebM file and stream it
> > diff --git a/libavformat/tee.c b/libavformat/tee.c
> > index f7a8f41..a04c7ef 100644
> > --- a/libavformat/tee.c
> > +++ b/libavformat/tee.c
> > @@ -30,6 +30,9 @@
> >  typedef struct {
> >      AVFormatContext *avf;
> >      AVBitStreamFilterContext **bsfs; ///< bitstream filters per stream
> > +
> 
> > +    /** map from input to output streams indexes, disabled output streams are set to -1 */
> 
> Minor nit: please split this line.
> 
> > +    int *stream_map;
> >  } TeeSlave;
> >  
> >  typedef struct TeeContext {
> > @@ -134,24 +137,52 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
> >      AVDictionary *options = NULL;
> >      AVDictionaryEntry *entry;
> >      char *filename;
> > -    char *format = NULL;
> > +    char *format = NULL, *select = NULL;
> >      AVFormatContext *avf2 = NULL;
> >      AVStream *st, *st2;
> > +    int stream_count;
> >  
> >      if ((ret = parse_slave_options(avf, slave, &options, &filename)) < 0)
> >          return ret;
> > -    if ((entry = av_dict_get(options, "f", NULL, 0))) {
> > -        format = entry->value;
> > -        entry->value = NULL; /* prevent it from being freed */
> > -        av_dict_set(&options, "f", NULL, 0);
> > +
> > +#define STEAL_OPTION(option, field)                             \
> > +    if ((entry = av_dict_get(options, option, NULL, 0))) {      \
> > +        field = entry->value;                                   \
> > +        entry->value = NULL; /* prevent it from being freed */  \
> > +        av_dict_set(&options, option, NULL, 0);                 \
> >      }
> > +    STEAL_OPTION("f", format);
> > +    STEAL_OPTION("select", select);
> >  
> >      ret = avformat_alloc_output_context2(&avf2, NULL, format, filename);
> >      if (ret < 0)
> >          goto end;
> >  
> > +    tee_slave->stream_map = av_calloc(avf->nb_streams, sizeof(*tee_slave->stream_map));
> > +    if (!tee_slave->stream_map) {
> > +        ret = AVERROR(ENOMEM);
> > +        goto end;
> > +    }
> > +
> > +    stream_count = 0;
> >      for (i = 0; i < avf->nb_streams; i++) {
> >          st = avf->streams[i];
> > +        if (select) {
> > +            ret = avformat_match_stream_specifier(avf, avf->streams[i], select);
> > +            if (ret < 0) {
> > +                av_log(avf, AV_LOG_ERROR,
> > +                       "Invalid stream specifier '%s' for output '%s'\n",
> > +                       select, slave);
> > +                goto end;
> > +            }
> > +
> > +            if (ret == 0) { /* no match */
> > +                tee_slave->stream_map[i] = -1;
> > +                continue;
> > +            }
> > +        }
> > +        tee_slave->stream_map[i] = stream_count++;
> 
> Nit: add a warning if some input streams are not mapped at all.

Not sure what you mean. Most containers will refuse no input stream,
so this should not be strictly required. I'll provide a further patch
if you can clarify.

[...]
> Apart from that, LGTM. Sorry for the delay.
>
> > >From 3cf0413b8b660b46a4b21eac2992dd68ceced51d Mon Sep 17 00:00:00 2001
> > From: Stefano Sabatini <stefasab at gmail.com>
> > Date: Sat, 3 Aug 2013 14:05:13 +0200
> > Subject: [PATCH] doc/muxers: add elaborated example for the tee muxer
> > 
> > The example shows how to combine bsfs and select options.
> 
> LGTM too.

Will push both patches soon, thanks.
-- 
FFmpeg = Free Fantastic Monstrous Political Empowered Gospel


More information about the ffmpeg-devel mailing list