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 <[email protected]> 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 _______________________________________________ FFmpeg-soc mailing list [email protected] https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc
