[FFmpeg-soc] Help needed with new concatenate filter

Brandon Mintern bmintern at gmail.com
Thu Apr 1 02:06:17 CEST 2010


Thanks a lot for the feedback. A new, much cleaner (and actually
similar to what I wrote on my first try before changing it to what you
saw) patch is at the bottom of this post. I still can't see why the
2nd input is not being output; it seems like everything should be
getting properly propagated.

On Wed, Mar 31, 2010 at 6:23 PM, Stefano Sabatini
<stefano.sabatini-lala at poste.it> wrote:
> On date Wednesday 2010-03-31 18:00:46 -0400, Brandon Mintern encoded:
[snip]
>> sample usage:
>>
>> ./ffmpeg_g -y -i input1.wmv -vfilters "movie=0:wmv3:input2.wmv [in2];
>> [in][in2] concatenate" -r 15 out.wmv
>>
>> Where input1.wmv and input2.wmv are both 15 fps and 800x600. As
>> written now, out.wmv seems to only be input1.wmv. I would appreciate
>> any insight into what I'm doing wrong. The patch is located at
>> http://bmintern.homeunix.com/~brandon/vf_concatenate.patch and is
>> included below.
>>
>> Thanks,
>> Brandon
[snip]
>> +static av_cold void uninit(AVFilterContext *ctx)
>> +{
>> +    ConcatenateContext *con = ctx->priv;
>> +    if (con->pic)
>> +        avfilter_unref_pic(con->pic);
>
> This is not the way picref are supposed to be unref-fed. They should
> be unref-ed during processing, so this is not needed.

I was thinking it might be possible for the filter to be uninit-ed in
the middle of processing; that's all this was for. I've removed it.

>> +static int config_props(AVFilterLink *link)
>> +{
>> +    if (link->src->inputs[0]->w > link->src->inputs[1]->w)
>> +        link->w = link->src->inputs[0]->w;
>> +    else
>> +        link->w = link->src->inputs[1]->w;
>> +    if (link->src->inputs[1]->h > link->src->inputs[1]->h)
>> +        link->h = link->src->inputs[0]->h;
>> +    else
>> +        link->h = link->src->inputs[1]->h;
>> +    return 0;
>> +}
>
> Variable video frame size is not supported, that means that something
> bad will likely happen when the size of the video will change from the
> first to the second source.

It's not intended to work with variable sizes anyways, so I've removed
this. I assume the default will match it with inputs[0]? Should I be
making sure that inputs[1]->w and ->h match inputs[0] and indicating
an error if they don't?

>> +static void start_frame(AVFilterLink *link, AVFilterPicRef *picref)
>> +{
>> +    ConcatenateContext *con = link->dst->priv;
>> +    con->pic = picref;
>> +}
>
> You need to propagate the start_frame to the next filter. Also I
> suppose your filter is not changing the passed in video frame, so a
> simple avfilter_null_start_frame should be enough.

I was thinking the propagation is happening in request_frame instead
of here. At any rate, I've removed this altogether and simply changed
.start_frame to avfilter_null_start_frame

>> +static int request_frame(AVFilterLink *link)
>> +{
>> +    ConcatenateContext *con = link->src->priv;
>> +    if(!con->first_input_consumed &&
>> +       avfilter_request_frame(link->src->inputs[0]))
>> +        con->first_input_consumed = 1;
>> +    if(con->first_input_consumed &&
>> +       avfilter_request_frame(link->src->inputs[1]))
>> +        return AVERROR_EOF;
>
>> +    avfilter_start_frame(link, con->pic);
>> +    avfilter_draw_slice(link, 0, con->pic->h, 1);
>> +    avfilter_end_frame(link);
>> +    con->pic = NULL;
>
> This can't work, suppose request_frame() is called, it is propagated
> to the source, finally the source calls start_frame() but it is not
> propagated, then draw_slice() is called, which is propagated (see
> avfilter_default_slice()), this will result in a crash.

I'm not entirely sure why it wasn't crashing, either :-\. I'm
propagating start_frame here, but like you said I'm doing something
strange with _draw_slice. I was modeling this component after the
wrong one, clearly.

> In other words the rule is:
>
> avfilter_start_frame(), _draw_slice() and _end_frame() must be
> propagated in this order from the source to the destination filter.
>
> Check the vf_null.c filter, this filter is very similar as it only
> *propagates* frames from a selected source, in the case of the null
> filter you have only one source, in this case you need to select the
> right source in the request_frame() callback.

Thanks a lot, these insights/explanations made things a lot clearer
for me. Unfortunately it's still not working as I'm expecting it to.
My new patch is below.

Thanks again,
Brandon

Index: allfilters.c
===================================================================
--- allfilters.c	(revision 5726)
+++ allfilters.c	(working copy)
@@ -35,6 +35,7 @@
     initialized = 1;

     REGISTER_FILTER (ASPECT,      aspect,      vf);
+    REGISTER_FILTER (CONCATENATE, concatenate, vf);
     REGISTER_FILTER (CROP,        crop,        vf);
     REGISTER_FILTER (DRAWBOX,     drawbox,     vf);
     REGISTER_FILTER (FIFO,        fifo,        vf);
Index: vf_concatenate.c
===================================================================
--- vf_concatenate.c	(revision 0)
+++ vf_concatenate.c	(revision 0)
@@ -0,0 +1,71 @@
+/*
+ * video concatenate filter
+ * copyright (c) 2007 Bobby Bingham
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avfilter.h"
+
+typedef struct {
+    int first_input_consumed;
+} ConcatenateContext;
+
+static int poll_frame(AVFilterLink *link)
+{
+    ConcatenateContext *con = link->src->priv;
+    if (con->first_input_consumed)
+        return avfilter_poll_frame(link->src->inputs[1]);
+    return avfilter_poll_frame(link->src->inputs[0]);
+}
+
+static int request_frame(AVFilterLink *link)
+{
+    ConcatenateContext *con = link->src->priv;
+    if (!con->first_input_consumed) {
+        if (avfilter_request_frame(link->src->inputs[0]))
+            con->first_input_consumed = 1;
+        else
+            return 0;
+    }
+    return avfilter_request_frame(link->src->inputs[1]);
+}
+
+AVFilter avfilter_vf_concatenate =
+{
+    .name      = "concatenate",
+
+    .priv_size = sizeof(ConcatenateContext),
+
+    .inputs    = (AVFilterPad[]) {{ .name            = "default",
+                                    .type            = CODEC_TYPE_VIDEO,
+                                    .start_frame     =
avfilter_null_start_frame,
+                                    .end_frame       = avfilter_null_end_frame,
+                                    .get_video_buffer=
avfilter_null_get_video_buffer, },
+                                  { .name            = "default2",
+                                    .type            = CODEC_TYPE_VIDEO,
+                                    .start_frame     =
avfilter_null_start_frame,
+                                    .end_frame       = avfilter_null_end_frame,
+                                    .get_video_buffer=
avfilter_null_get_video_buffer, },
+                                  { .name = NULL}},
+    .outputs   = (AVFilterPad[]) {{ .name            = "default",
+                                    .type            = CODEC_TYPE_VIDEO,
+                                    .poll_frame      = poll_frame,
+                                    .request_frame   = request_frame, },
+                                  { .name = NULL}},
+};
+
Index: Makefile
===================================================================
--- Makefile	(revision 5726)
+++ Makefile	(working copy)
@@ -16,6 +16,7 @@
        parseutils.o                                                     \

 OBJS-$(CONFIG_ASPECT_FILTER)                 += vf_aspect.o
+OBJS-$(CONFIG_CONCATENATE_FILTER)            += vf_concatenate.o
 OBJS-$(CONFIG_CROP_FILTER)                   += vf_crop.o
 OBJS-$(CONFIG_DRAWBOX_FILTER)                += vf_drawbox.o
 OBJS-$(CONFIG_FIFO_FILTER)                   += vf_fifo.o


More information about the FFmpeg-soc mailing list