[FFmpeg-devel] [PATCH] lavf/tee: add support for bitstream filtering

Stefano Sabatini stefasab at gmail.com
Wed Jul 31 17:53:44 CEST 2013


On date Thursday 2013-07-18 12:30:23 +0200, Nicolas George encoded:
> L'octidi 18 messidor, an CCXXI, Stefano Sabatini a écrit :
> > TODO: add documentation, bump minor
> > ---
> >  libavformat/tee.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++---
> >  1 file changed, 221 insertions(+), 10 deletions(-)
> > 
> > diff --git a/libavformat/tee.c b/libavformat/tee.c
> > index 7b8b371..96ced3e 100644
> > --- a/libavformat/tee.c
> > +++ b/libavformat/tee.c
> > @@ -27,10 +27,16 @@
> >  
> >  #define MAX_SLAVES 16
> >  
> > +typedef struct {
> > +    AVFormatContext *fmt_ctx;
> > +    AVBitStreamFilterContext **bsf_ctxs; ///< bitstream filters per stream
> > +} TeeSlave;
> 

> Do you insist on the _ctx suffix? To me, they only make the lines of code
> longer.

Still kept, but I can change it if you insist (or you can change back
later if that saves time).

> 
> > +
> >  typedef struct TeeContext {
> >      const AVClass *class;
> >      unsigned nb_slaves;
> > -    AVFormatContext *slaves[MAX_SLAVES];
> > +    TeeSlave slaves[MAX_SLAVES];
> > +    char *bsfs;
> >  } TeeContext;
> >  
> >  static const char *const slave_delim     = "|";
> > @@ -38,10 +44,18 @@ static const char *const slave_opt_open  = "[";
> >  static const char *const slave_opt_close = "]";
> >  static const char *const slave_opt_delim = ":]"; /* must have the close too */
> >  
> 
> > +#define OFFSET(x) offsetof(TeeContext, x)
> > +#define E AV_OPT_FLAG_ENCODING_PARAM
> > +static const AVOption tee_options[] = {
> > +    { "tee_bsfs", "set bitstream filters for each slave", OFFSET(bsfs), AV_OPT_TYPE_STRING, {.str = NULL}, .flags=E },
> > +    { NULL },
> > +};
> 
> I believe you can make this feature much simpler and also more user-friendly
> by using the existing options system.
> 
> Your suggestion currently looks like that:
> 
> -f tee -tee_bsfs 'annexbtomp4|dump_extra' 'foo.mp4|foo.ts'
> 
> it would look like that:
> 
> -f tee '[bsfs=annexbtomp4]foo.mp4|[bsfs=dump_extra]foo.ts'
> 
> I like it better because the bsfs are nearer the corresponding file: if you
> change the order of the slaves, you do not risk to forget changing the order
> of the filters. It is also nicer when only one slave has filters and it is
> not the first.
> 
> You just have to imitate the av_dict_get(..."f") part.

Yes and true, it is now simpler and easier.

> Also, you could put the streams specifiers on the bsfs option rather than
> the bsfs names (which is strange when there are several filters, what does
> "dump_extra:a,mp4toannexb:v" mean?), that would make the parsing easier.

Changed to:
dumo_extra+a,mp4toannexb+v.

> 
> > +
> >  static const AVClass tee_muxer_class = {
> >      .class_name = "Tee muxer",
> >      .item_name  = av_default_item_name,
> >      .version    = LIBAVUTIL_VERSION_INT,
> > +    .option     = tee_options,
> >  };
> >  
> >  static int parse_slave_options(void *log, char *slave,
> > @@ -82,7 +96,93 @@ fail:
> >      return ret;
> >  }
> >  
> > -static int open_slave(AVFormatContext *avf, char *slave, AVFormatContext **ravf)
> > +/**
> > + * Parse bitstream filter, in the form:
> > + * BSF ::= BSF_NAME[:STREAM_SPECIFIER]
> > + */
> > +static int parse_bsf(void *log_ctx, char *bsf,
> > +                     AVFormatContext *fmt_ctx,
> > +                     AVBitStreamFilterContext **bsf_ctxs)
> > +{
> > +    int i, ret = 0;
> > +    char *bsf1 = av_strdup(bsf);
> > +    char *bsf_name, *spec;
> > +
> 
> > +    if (!bsf1)
> > +        return AVERROR(ENOMEM);
> 

> Maybe strdup the whole string once and for all, so you can butcher it all
> you want without bothering about it?

Not sure what you mean, I'm already duping it.

> 
> > +    bsf_name = av_strtok(bsf1, ":", &spec);
> > +
> > +    /* select the streams matched by the specifier */
> > +    for (i = 0; i < fmt_ctx->nb_streams; i++) {
> > +        AVBitStreamFilterContext *bsf_ctx;
> > +
> > +        if (spec && spec[0]) {
> > +            ret = avformat_match_stream_specifier(fmt_ctx, fmt_ctx->streams[i], spec);
> > +            if (ret < 0) {
> > +                av_log(log_ctx, AV_LOG_ERROR,
> > +                       "Invalid stream specifier for bitstream filter '%s'\n", bsf);
> > +                goto end;
> > +            }
> > +
> > +            if (ret == 0) /* no match */
> > +                continue;
> > +        }
> > +
> 
> > +        bsf_ctx = av_bitstream_filter_init(bsf_name);
> 
> Your parser does not allow to specify options if stream specifiers are in
> place ("dump_extra:v=a"). That is the reason I suggest to put streams
> specifiers on the option rather than the filter.
> 
[...]
> > +static void log_slave(TeeSlave *slave, void *log_ctx, int log_level)
> > +{
> > +    int i;
> > +    av_log(log_ctx, log_level, "filename:'%s' format:%s\n",
> > +           slave->fmt_ctx->filename, slave->fmt_ctx->oformat->name);
> > +    for (i = 0; i < slave->fmt_ctx->nb_streams; i++) {
> > +        AVStream *st = slave->fmt_ctx->streams[i];
> > +        AVBitStreamFilterContext *bsf_ctx = slave->bsf_ctxs[i];
> > +
> > +        av_log(log_ctx, log_level, "    stream:%d codec:%s type:%s",
> > +               i, avcodec_get_name(st->codec->codec_id),
> > +               st->codec->codec ?
> > +               av_get_media_type_string(st->codec->codec->type) : "copy");
> > +        if (bsf_ctx) {
> 
> > +            int first = 1;
> > +            av_log(log_ctx, log_level, " bsfs:");
> > +            while (bsf_ctx) {
> > +                av_log(log_ctx, log_level, "%s%s", first ? "" : ",",
> > +                       bsf_ctx->filter->name);
> > +                bsf_ctx = bsf_ctx->next;
> > +                first = 0;
> 
> 
> You could do slightly simpler with either these solutions:
> 
>   av_log(..., "%s%s", name, bsf_ctx->next ? "," : "");
> 
>   const char *delim = "";
>   av_log(..., "%s%s", delim, name);
>   delim = ",";

Done.

[...] 

Patch updated with documentation.
-- 
FFmpeg = Faithful Fancy Mastodontic Proud Elitarian Glue
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-lavf-tee-add-support-for-bitstream-filtering.patch
Type: text/x-diff
Size: 12077 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130731/5c2cb705/attachment.bin>


More information about the ffmpeg-devel mailing list