avconv: support parsing bitstream filter options
authorJames Almer <jamrial@gmail.com>
Sat, 29 Oct 2016 00:44:51 +0000 (21:44 -0300)
committerAnton Khirnov <anton@khirnov.net>
Wed, 2 Nov 2016 09:08:28 +0000 (10:08 +0100)
Example usage:

avconv -i INPUT -bsf filter[=opt1=val1:opt2=val2] OUTPUT

Signed-off-by: James Almer <jamrial@gmail.com>
Signed-off-by: Anton Khirnov <anton@khirnov.net>
avconv.c
avconv.h
avconv_opt.c

index 0b75cbe21498f5601db28ed955b7315fca05a11a..4bd28e6e3b4191cc93cd11f1b99ef1611a461413 100644 (file)
--- 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;
index fcdf3d04613e21b1c065081d7200202017a0a074..6360f76c0bb5d1d768819dd358d5f3a76e765b1a 100644 (file)
--- 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;
index 362a5b7f5e9b4afb8f1ea35b4bf2c2278239611b..ba37a3a31d6811dcb8fa28a488904d8355a4a8f4 100644 (file)
@@ -1025,26 +1025,54 @@ 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) {
+            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);
+            }
+            assert_avoptions(bsf_options);
+            av_dict_free(&bsf_options);
+        }
+        av_freep(&bsf_name);
 
-        ost->bitstream_filters[ost->nb_bitstream_filters++] = filter;
         if (*bsfs)
             bsfs++;
     }