Quoting James Almer (2016-10-03 21:40:06)
> Arguments for bitstream filters weren't being parsed at all, and instead
> checked by av_bsf_get_by_name() as if they were part of the filter's name
> 
> Signed-off-by: James Almer <jamr...@gmail.com>
> ---
> This should also go into Libav 12, but i'm not CCing libav-sta...@libav.org
> since i assume it's still for Libav 11 and older for now.

This is not exactly a "fix", but a new feature -- parameters for
bitstream filters were never supported before. So it probably should not
go into the stable versions.

> 
>  avconv.c     | 15 ++-------------
>  avconv.h     |  1 -
>  avconv_opt.c | 45 ++++++++++++++++++++++++++++++++++++---------
>  3 files changed, 38 insertions(+), 23 deletions(-)
> 
> diff --git a/avconv.c b/avconv.c
> index 0b75cbe..4bd28e6 100644
> --- a/avconv.c
> +++ b/avconv.c
> @@ -190,7 +190,6 @@ static void avconv_cleanup(int ret)
>          for (j = 0; j < ost->nb_bitstream_filters; j++)
>              av_bsf_free(&ost->bsf_ctx[j]);
>          av_freep(&ost->bsf_ctx);
> -        av_freep(&ost->bitstream_filters);
>  
>          av_frame_free(&ost->filtered_frame);
>  
> @@ -1798,17 +1797,8 @@ static int init_output_bsfs(OutputStream *ost)
>      if (!ost->nb_bitstream_filters)
>          return 0;
>  
> -    ost->bsf_ctx = av_mallocz_array(ost->nb_bitstream_filters, 
> sizeof(*ost->bsf_ctx));
> -    if (!ost->bsf_ctx)
> -        return AVERROR(ENOMEM);
> -
>      for (i = 0; i < ost->nb_bitstream_filters; i++) {
> -        ret = av_bsf_alloc(ost->bitstream_filters[i], &ctx);
> -        if (ret < 0) {
> -            av_log(NULL, AV_LOG_ERROR, "Error allocating a bitstream filter 
> context\n");
> -            return ret;
> -        }
> -        ost->bsf_ctx[i] = ctx;
> +        ctx = ost->bsf_ctx[i];
>  
>          ret = avcodec_parameters_copy(ctx->par_in,
>                                        i ? ost->bsf_ctx[i - 1]->par_out : 
> ost->st->codecpar);
> @@ -1820,12 +1810,11 @@ static int init_output_bsfs(OutputStream *ost)
>          ret = av_bsf_init(ctx);
>          if (ret < 0) {
>              av_log(NULL, AV_LOG_ERROR, "Error initializing bitstream filter: 
> %s\n",
> -                   ost->bitstream_filters[i]->name);
> +                   ctx->filter->name);
>              return ret;
>          }
>      }
>  
> -    ctx = ost->bsf_ctx[ost->nb_bitstream_filters - 1];
>      ret = avcodec_parameters_copy(ost->st->codecpar, ctx->par_out);
>      if (ret < 0)
>          return ret;
> diff --git a/avconv.h b/avconv.h
> index fcdf3d0..6360f76 100644
> --- a/avconv.h
> +++ b/avconv.h
> @@ -360,7 +360,6 @@ typedef struct OutputStream {
>      AVRational mux_timebase;
>  
>      int                    nb_bitstream_filters;
> -    const AVBitStreamFilter **bitstream_filters;
>      AVBSFContext            **bsf_ctx;
>  
>      AVCodecContext *enc_ctx;
> diff --git a/avconv_opt.c b/avconv_opt.c
> index 362a5b7..931c35d 100644
> --- a/avconv_opt.c
> +++ b/avconv_opt.c
> @@ -1025,26 +1025,53 @@ static OutputStream *new_output_stream(OptionsContext 
> *o, AVFormatContext *oc, e
>      MATCH_PER_STREAM_OPT(bitstream_filters, str, bsfs, oc, st);
>      while (bsfs && *bsfs) {
>          const AVBitStreamFilter *filter;
> -        char *bsf;
> +        const char *bsf, *bsf_options_str, *bsf_name;
> +        AVDictionary *bsf_options = NULL;
>  
> -        bsf = av_get_token(&bsfs, ",");
> +        bsf = bsf_options_str = av_get_token(&bsfs, ",");
>          if (!bsf)
>              exit_program(1);
> +        bsf_name = av_get_token(&bsf_options_str, "=");
> +        if (!bsf_name)
> +            exit_program(1);
>  
> -        filter = av_bsf_get_by_name(bsf);
> +        filter = av_bsf_get_by_name(bsf_name);
>          if (!filter) {
> -            av_log(NULL, AV_LOG_FATAL, "Unknown bitstream filter %s\n", bsf);
> +            av_log(NULL, AV_LOG_FATAL, "Unknown bitstream filter %s\n", 
> bsf_name);
>              exit_program(1);
>          }
> +        if (*++bsf_options_str) {
> +            ret = av_dict_parse_string(&bsf_options, bsf_options_str, "=", 
> ":", 0);
> +            if (ret < 0) {
> +                av_log(NULL, AV_LOG_ERROR, "Error parsing options for 
> bitstream filter %s\n", bsf_name);
> +                exit_program(1);
> +            }
> +        }
>          av_freep(&bsf);
>  
> -        ost->bitstream_filters = av_realloc_array(ost->bitstream_filters,
> -                                                  ost->nb_bitstream_filters 
> + 1,
> -                                                  
> sizeof(*ost->bitstream_filters));
> -        if (!ost->bitstream_filters)
> +        ost->bsf_ctx = av_realloc_array(ost->bsf_ctx,
> +                                        ost->nb_bitstream_filters + 1,
> +                                        sizeof(*ost->bsf_ctx));
> +        if (!ost->bsf_ctx)
> +            exit_program(1);
> +
> +        ret = av_bsf_alloc(filter, &ost->bsf_ctx[ost->nb_bitstream_filters]);
> +        if (ret < 0) {
> +            av_log(NULL, AV_LOG_ERROR, "Error allocating a bistream filter 
> context\n");
>              exit_program(1);
> +        }
> +        ost->nb_bitstream_filters++;
> +
> +        if (bsf_options && filter->priv_class) {
> +            ret = 
> av_opt_set_dict(ost->bsf_ctx[ost->nb_bitstream_filters-1]->priv_data, 
> &bsf_options);
> +            if (ret < 0) {
> +                av_log(NULL, AV_LOG_ERROR, "Error setting options for 
> bitstream filter %s\n", bsf_name);
> +                exit_program(1);
> +            }

It should complain loudly if
- options were provided but the filter does not accept any
- some options were not consumed
otherwise we'll again get the old problem of users cargo culting random
options from the internet with no indication that they don't do
anything.

Also, it might be better to use av_opt_set_dict() directly on the filter
context itself, so that this will also work on options that are shared
among all filters (if we add any later).

-- 
Anton Khirnov
_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to