[FFmpeg-cvslog] avconv: decouple configuring filtergraphs and setting input parameters

Anton Khirnov git at videolan.org
Thu Nov 3 15:54:43 EET 2016


ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Mon May 23 14:09:08 2016 +0200| [722ec3eb35bc152ce91d0a4502eca0df1c0086d0] | committer: Anton Khirnov

avconv: decouple configuring filtergraphs and setting input parameters

Currently, calling configure_filtergraph() will pull in the input
parameters from the corresponding decoder context. This has the
following disadvantages:
- the decoded frame is a more proper source for this information
- a filter accessing decoder data breaks proper layering

Add functions for explicitly sending the input stream parameters to a
filtergraph input - currently from a frame and a decoder. The decoder
one will be dropped in future commits after some more restructuring.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=722ec3eb35bc152ce91d0a4502eca0df1c0086d0
---

 avconv.c        | 30 +++++++++++++++++++++++++
 avconv.h        | 14 ++++++++++++
 avconv_filter.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++----------
 avconv_opt.c    | 24 ++++++++++++++++----
 4 files changed, 122 insertions(+), 16 deletions(-)

diff --git a/avconv.c b/avconv.c
index 6401760..4e19813 100644
--- a/avconv.c
+++ b/avconv.c
@@ -147,6 +147,7 @@ static void avconv_cleanup(int ret)
         FilterGraph *fg = filtergraphs[i];
         avfilter_graph_free(&fg->graph);
         for (j = 0; j < fg->nb_inputs; j++) {
+            av_buffer_unref(&fg->inputs[j]->hw_frames_ctx);
             av_freep(&fg->inputs[j]->name);
             av_freep(&fg->inputs[j]);
         }
@@ -1252,6 +1253,16 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
         ist->resample_channel_layout = decoded_frame->channel_layout;
         ist->resample_channels       = avctx->channels;
 
+        for (i = 0; i < ist->nb_filters; i++) {
+            err = ifilter_parameters_from_frame(ist->filters[i], decoded_frame);
+            if (err < 0) {
+                av_log(NULL, AV_LOG_ERROR,
+                       "Error reconfiguring input stream %d:%d filter %d\n",
+                       ist->file_index, ist->st->index, i);
+                goto fail;
+            }
+        }
+
         for (i = 0; i < nb_filtergraphs; i++)
             if (ist_in_filtergraph(filtergraphs[i], ist) &&
                 configure_filtergraph(filtergraphs[i]) < 0) {
@@ -1279,6 +1290,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output)
             break;
     }
 
+fail:
     av_frame_unref(ist->filter_frame);
     av_frame_unref(decoded_frame);
     return err < 0 ? err : ret;
@@ -1336,6 +1348,16 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output)
         ist->resample_height  = decoded_frame->height;
         ist->resample_pix_fmt = decoded_frame->format;
 
+        for (i = 0; i < ist->nb_filters; i++) {
+            err = ifilter_parameters_from_frame(ist->filters[i], decoded_frame);
+            if (err < 0) {
+                av_log(NULL, AV_LOG_ERROR,
+                       "Error reconfiguring input stream %d:%d filter %d\n",
+                       ist->file_index, ist->st->index, i);
+                goto fail;
+            }
+        }
+
         for (i = 0; i < nb_filtergraphs; i++)
             if (ist_in_filtergraph(filtergraphs[i], ist) &&
                 configure_filtergraph(filtergraphs[i]) < 0) {
@@ -2061,6 +2083,14 @@ static int transcode_init(void)
                  enc_ctx->codec_type == AVMEDIA_TYPE_AUDIO) &&
                  filtergraph_is_simple(ost->filter->graph)) {
                     FilterGraph *fg = ost->filter->graph;
+
+                    ret = ifilter_parameters_from_decoder(fg->inputs[0],
+                                                          dec_ctx);
+                    if (ret < 0) {
+                        av_log(NULL, AV_LOG_FATAL, "Error initializing filter input\n");
+                        exit_program(1);
+                    }
+
                     if (configure_filtergraph(fg)) {
                         av_log(NULL, AV_LOG_FATAL, "Error opening filters!\n");
                         exit_program(1);
diff --git a/avconv.h b/avconv.h
index 60729c3..e201b92 100644
--- a/avconv.h
+++ b/avconv.h
@@ -199,6 +199,17 @@ typedef struct InputFilter {
     struct InputStream *ist;
     struct FilterGraph *graph;
     uint8_t            *name;
+
+    // parameters configured for this input
+    int format;
+
+    int width, height;
+    AVRational sample_aspect_ratio;
+
+    int sample_rate;
+    uint64_t channel_layout;
+
+    AVBufferRef *hw_frames_ctx;
 } InputFilter;
 
 typedef struct OutputFilter {
@@ -468,6 +479,9 @@ int filtergraph_is_simple(FilterGraph *fg);
 int init_simple_filtergraph(InputStream *ist, OutputStream *ost);
 int init_complex_filtergraph(FilterGraph *fg);
 
+int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame);
+int ifilter_parameters_from_decoder(InputFilter *ifilter, const AVCodecContext *avctx);
+
 int avconv_parse_options(int argc, char **argv);
 
 int vdpau_init(AVCodecContext *s);
diff --git a/avconv_filter.c b/avconv_filter.c
index 875ce10..2332f99 100644
--- a/avconv_filter.c
+++ b/avconv_filter.c
@@ -97,6 +97,7 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost)
         exit(1);
     fg->inputs[0]->ist   = ist;
     fg->inputs[0]->graph = fg;
+    fg->inputs[0]->format = -1;
 
     GROW_ARRAY(ist->filters, ist->nb_filters);
     ist->filters[ist->nb_filters - 1] = fg->inputs[0];
@@ -172,6 +173,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
         exit(1);
     fg->inputs[fg->nb_inputs - 1]->ist   = ist;
     fg->inputs[fg->nb_inputs - 1]->graph = fg;
+    fg->inputs[fg->nb_inputs - 1]->format = -1;
 
     GROW_ARRAY(ist->filters, ist->nb_filters);
     ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1];
@@ -505,15 +507,12 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
     if (!par)
         return AVERROR(ENOMEM);
 
-    par->sample_aspect_ratio = ist->st->sample_aspect_ratio.num ?
-                               ist->st->sample_aspect_ratio :
-                               ist->dec_ctx->sample_aspect_ratio;
-    par->width               = ist->dec_ctx->width;
-    par->height              = ist->dec_ctx->height;
-    par->format              = ist->hwaccel_retrieve_data ?
-                               ist->hwaccel_retrieved_pix_fmt : ist->dec_ctx->pix_fmt;
+    par->sample_aspect_ratio = ifilter->sample_aspect_ratio;
+    par->width               = ifilter->width;
+    par->height              = ifilter->height;
+    par->format              = ifilter->format;
     par->time_base           = tb;
-    par->hw_frames_ctx       = ist->hw_frames_ctx;
+    par->hw_frames_ctx       = ifilter->hw_frames_ctx;
 
     ret = av_buffersrc_parameters_set(ifilter->filter, par);
     av_freep(&par);
@@ -597,10 +596,10 @@ static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter,
     if (!par)
         return AVERROR(ENOMEM);
 
-    par->time_base      = (AVRational){ 1, ist->dec_ctx->sample_rate };
-    par->sample_rate    = ist->dec_ctx->sample_rate;
-    par->format         = ist->dec_ctx->sample_fmt;
-    par->channel_layout = ist->dec_ctx->channel_layout;
+    par->time_base      = (AVRational){ 1, ifilter->sample_rate };
+    par->sample_rate    = ifilter->sample_rate;
+    par->format         = ifilter->format;
+    par->channel_layout = ifilter->channel_layout;
 
     ret = av_buffersrc_parameters_set(ifilter->filter, par);
     av_freep(&par);
@@ -751,6 +750,53 @@ int configure_filtergraph(FilterGraph *fg)
     return 0;
 }
 
+int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame)
+{
+    av_buffer_unref(&ifilter->hw_frames_ctx);
+
+    ifilter->format = frame->format;
+
+    ifilter->width               = frame->width;
+    ifilter->height              = frame->height;
+    ifilter->sample_aspect_ratio = frame->sample_aspect_ratio;
+
+    ifilter->sample_rate         = frame->sample_rate;
+    ifilter->channel_layout      = frame->channel_layout;
+
+    if (frame->hw_frames_ctx) {
+        ifilter->hw_frames_ctx = av_buffer_ref(frame->hw_frames_ctx);
+        if (!ifilter->hw_frames_ctx)
+            return AVERROR(ENOMEM);
+    }
+
+    return 0;
+}
+
+int ifilter_parameters_from_decoder(InputFilter *ifilter, const AVCodecContext *avctx)
+{
+    av_buffer_unref(&ifilter->hw_frames_ctx);
+
+    if (avctx->codec_type == AVMEDIA_TYPE_VIDEO)
+        ifilter->format = avctx->pix_fmt;
+    else
+        ifilter->format = avctx->sample_fmt;
+
+    ifilter->width               = avctx->width;
+    ifilter->height              = avctx->height;
+    ifilter->sample_aspect_ratio = avctx->sample_aspect_ratio;
+
+    ifilter->sample_rate         = avctx->sample_rate;
+    ifilter->channel_layout      = avctx->channel_layout;
+
+    if (avctx->hw_frames_ctx) {
+        ifilter->hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx);
+        if (!ifilter->hw_frames_ctx)
+            return AVERROR(ENOMEM);
+    }
+
+    return 0;
+}
+
 int ist_in_filtergraph(FilterGraph *fg, InputStream *ist)
 {
     int i;
diff --git a/avconv_opt.c b/avconv_opt.c
index a1729c3..ce58f2b 100644
--- a/avconv_opt.c
+++ b/avconv_opt.c
@@ -1498,12 +1498,28 @@ static int init_complex_filters(void)
 
 static int configure_complex_filters(void)
 {
-    int i, ret = 0;
+    int i, j, ret = 0;
+
+    for (i = 0; i < nb_filtergraphs; i++) {
+        FilterGraph *fg = filtergraphs[i];
+
+        if (filtergraph_is_simple(fg))
+            continue;
 
-    for (i = 0; i < nb_filtergraphs; i++)
-        if (!filtergraph_is_simple(filtergraphs[i]) &&
-            (ret = configure_filtergraph(filtergraphs[i])) < 0)
+        for (j = 0; j < fg->nb_inputs; j++) {
+            ret = ifilter_parameters_from_decoder(fg->inputs[j],
+                                                  fg->inputs[j]->ist->dec_ctx);
+            if (ret < 0) {
+                av_log(NULL, AV_LOG_ERROR,
+                       "Error initializing filtergraph %d input %d\n", i, j);
+                return ret;
+            }
+        }
+
+        ret = configure_filtergraph(filtergraphs[i]);
+        if (ret < 0)
             return ret;
+    }
     return 0;
 }
 



More information about the ffmpeg-cvslog mailing list