[FFmpeg-devel] lavfi/buffersrc: push the frame deeper if requested.

Submitted by Paul B Mahol on July 11, 2017, 7:12 p.m.

Details

Message ID CAPYw7P4uX9wBHq7NCdzkiGKYJ1sxG6Cq7Rj6osMUeTnmGssOQg@mail.gmail.com
State New
Headers show

Commit Message

Paul B Mahol July 11, 2017, 7:12 p.m.
On 7/11/17, Nicolas George <george@nsup.org> wrote:
> Le tridi 23 messidor, an CCXXV, Paul B Mahol a ecrit :
>> Nothing can get rid of that issue, except tootal lavfi rewrite.
>
> Why do you say that? My plan gets rid of them quite easily, since now
> all links have a dynamically-sized FIFO built-in.
>
>> I tried this and it did not work at all. And I even contacted Nicolas
>> privately and never got reply.
>
> I found your mail in my inbox, and I vaguely remember reading them at
> the time, but no more. It was a very busy week. Sorry for missing them.
>
> Unfortunately, you neglected to include your code, so I cannot tell why
> it did not work.

You never asked for one.

Here it is attached just for you.

Comments

Nicolas George July 17, 2017, 12:58 p.m.
Le tridi 23 messidor, an CCXXV, Paul B Mahol a écrit :
> You never asked for one.

Indeed, since I forgot to answer your mail. But you know what is
necessary in a bug report.

> Here it is attached just for you.

I think you sent it to the mailing-list, not just to me.

Anyway, I have a working version now, I need to clean it up before
sending. In the meantime, instead of duelling while riding office
chairs, I can point what did not work in this patch:

> From 20d00cead1e47b2e389fde99a3c0f9c36b6587ec Mon Sep 17 00:00:00 2001
> From: Paul B Mahol <onemda@gmail.com>
> Date: Tue, 20 Jun 2017 19:44:54 +0200
> Subject: [PATCH] shit
> 
> Signed-off-by: Paul B Mahol <onemda@gmail.com>
> ---
>  libavfilter/framesync.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
>  libavfilter/framesync.h |  4 ++++
>  libavfilter/vf_stack.c  |  9 ++++-----
>  3 files changed, 55 insertions(+), 5 deletions(-)
> 
> diff --git a/libavfilter/framesync.c b/libavfilter/framesync.c
> index eb05d66..f2a4450 100644
> --- a/libavfilter/framesync.c
> +++ b/libavfilter/framesync.c
> @@ -23,6 +23,7 @@
>  
>  #include "libavutil/avassert.h"
>  #include "avfilter.h"
> +#include "filters.h"
>  #include "bufferqueue.h"
>  #include "framesync.h"
>  #include "internal.h"
> @@ -224,6 +225,22 @@ void ff_framesync_next(FFFrameSync *fs)
>      framesync_advance(fs);
>  }
>  
> +void ff_framesync_next2(FFFrameSync *fs)
> +{
> +    AVFilterContext *ctx = fs->parent;
> +    unsigned i;
> +
> +    av_assert0(!fs->frame_ready);
> +    for (i = 0; i < fs->nb_in; i++)

> +        if (!fs->in[i].have_next && ff_framequeue_queued_frames(&ctx->inputs[i]->fifo)) {
> +            framesync_inject_frame(fs, i, ff_framequeue_take(&ctx->inputs[i]->fifo));

Do not access link->fifo directly.

> +            ctx->inputs[i]->frame_wanted_out = 1;

This must not be done unconditionally, it must only be done if (1)
frame_wanted_out is set on the output or (2) there are frame queued in
other inputs and a frame is necessary to process them.

> +            ff_filter_set_ready(ctx->inputs[i]->src, 100);

Use ff_inlink_request_frame().

> +        }
> +    fs->frame_ready = 0;
> +    framesync_advance(fs);
> +}
> +
>  void ff_framesync_drop(FFFrameSync *fs)
>  {
>      fs->frame_ready = 0;
> @@ -300,6 +317,27 @@ int ff_framesync_process_frame(FFFrameSync *fs, unsigned all)
>      return count;
>  }
>  
> +int ff_framesync_process_frame2(FFFrameSync *fs, unsigned all)
> +{
> +    int ret, count = 0;
> +
> +    av_assert0(fs->on_event);
> +    while (1) {
> +        ff_framesync_next2(fs);
> +        if (fs->eof || !fs->frame_ready)
> +            break;
> +        if ((ret = fs->on_event(fs)) < 0)
> +            return ret;
> +        ff_framesync_drop(fs);
> +        count++;
> +        if (!all)
> +            break;
> +    }
> +    if (!count && fs->eof)
> +        return AVERROR_EOF;
> +    return count;
> +}
> +
>  int ff_framesync_filter_frame(FFFrameSync *fs, AVFilterLink *inlink,
>                                AVFrame *in)
>  {
> @@ -314,6 +352,15 @@ int ff_framesync_filter_frame(FFFrameSync *fs, AVFilterLink *inlink,
>      return 0;
>  }
>  
> +int ff_framesync_activate(FFFrameSync *fs, AVFilterContext *ctx)
> +{
> +    int ret;
> +

> +    if ((ret = ff_framesync_process_frame2(fs, 1)) < 0)
> +        return ret;

At no point your code calls ff_inlink_acknowledge_status(). Therefore,
it can not detect EOF.

> +    return 0;
> +}
> +
>  int ff_framesync_request_frame(FFFrameSync *fs, AVFilterLink *outlink)
>  {
>      AVFilterContext *ctx = outlink->src;
> diff --git a/libavfilter/framesync.h b/libavfilter/framesync.h
> index 7ba99d5..0f381e3 100644
> --- a/libavfilter/framesync.h
> +++ b/libavfilter/framesync.h
> @@ -250,6 +250,7 @@ int ff_framesync_add_frame(FFFrameSync *fs, unsigned in, AVFrame *frame);
>   * The status of the operation can be found in fs->frame_ready and fs->eof.
>   */
>  void ff_framesync_next(FFFrameSync *fs);
> +void ff_framesync_next2(FFFrameSync *fs);
>  
>  /**
>   * Drop the current frame event.
> @@ -275,6 +276,7 @@ int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe,
>   * @return  number of frames processed or negative error code
>   */
>  int ff_framesync_process_frame(FFFrameSync *fs, unsigned all);
> +int ff_framesync_process_frame2(FFFrameSync *fs, unsigned all);
>  
>  
>  /**
> @@ -286,6 +288,8 @@ int ff_framesync_process_frame(FFFrameSync *fs, unsigned all);
>  int ff_framesync_filter_frame(FFFrameSync *fs, AVFilterLink *inlink,
>                                AVFrame *in);
>  
> +int ff_framesync_activate(FFFrameSync *fs, AVFilterContext *ctx);
> +
>  /**
>   * Request a frame on the filter output.
>   *
> diff --git a/libavfilter/vf_stack.c b/libavfilter/vf_stack.c
> index 03643b6..0e45952 100644
> --- a/libavfilter/vf_stack.c
> +++ b/libavfilter/vf_stack.c
> @@ -58,10 +58,10 @@ static int query_formats(AVFilterContext *ctx)
>      return ff_set_common_formats(ctx, pix_fmts);
>  }
>  
> -static int filter_frame(AVFilterLink *inlink, AVFrame *in)
> +static int activate(AVFilterContext *ctx)
>  {
> -    StackContext *s = inlink->dst->priv;
> -    return ff_framesync_filter_frame(&s->fs, inlink, in);
> +    StackContext *s = ctx->priv;
> +    return ff_framesync_activate(&s->fs, ctx);
>  }
>  
>  static av_cold int init(AVFilterContext *ctx)
> @@ -83,7 +83,6 @@ static av_cold int init(AVFilterContext *ctx)
>          pad.name = av_asprintf("input%d", i);
>          if (!pad.name)
>              return AVERROR(ENOMEM);
> -        pad.filter_frame = filter_frame;
>  
>          if ((ret = ff_insert_inpad(ctx, i, &pad)) < 0) {
>              av_freep(&pad.name);
> @@ -237,7 +236,6 @@ static const AVFilterPad outputs[] = {
>          .name          = "default",
>          .type          = AVMEDIA_TYPE_VIDEO,
>          .config_props  = config_output,
> -        .request_frame = request_frame,
>      },
>      { NULL }
>  };
> @@ -274,6 +272,7 @@ AVFilter ff_vf_vstack = {
>      .query_formats = query_formats,
>      .outputs       = outputs,
>      .init          = init,
> +    .activate      = activate,
>      .uninit        = uninit,
>      .flags         = AVFILTER_FLAG_DYNAMIC_INPUTS,
>  };

Regards,

Patch hide | download patch | download mbox

From 20d00cead1e47b2e389fde99a3c0f9c36b6587ec Mon Sep 17 00:00:00 2001
From: Paul B Mahol <onemda@gmail.com>
Date: Tue, 20 Jun 2017 19:44:54 +0200
Subject: [PATCH] shit

Signed-off-by: Paul B Mahol <onemda@gmail.com>
---
 libavfilter/framesync.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 libavfilter/framesync.h |  4 ++++
 libavfilter/vf_stack.c  |  9 ++++-----
 3 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/libavfilter/framesync.c b/libavfilter/framesync.c
index eb05d66..f2a4450 100644
--- a/libavfilter/framesync.c
+++ b/libavfilter/framesync.c
@@ -23,6 +23,7 @@ 
 
 #include "libavutil/avassert.h"
 #include "avfilter.h"
+#include "filters.h"
 #include "bufferqueue.h"
 #include "framesync.h"
 #include "internal.h"
@@ -224,6 +225,22 @@  void ff_framesync_next(FFFrameSync *fs)
     framesync_advance(fs);
 }
 
+void ff_framesync_next2(FFFrameSync *fs)
+{
+    AVFilterContext *ctx = fs->parent;
+    unsigned i;
+
+    av_assert0(!fs->frame_ready);
+    for (i = 0; i < fs->nb_in; i++)
+        if (!fs->in[i].have_next && ff_framequeue_queued_frames(&ctx->inputs[i]->fifo)) {
+            framesync_inject_frame(fs, i, ff_framequeue_take(&ctx->inputs[i]->fifo));
+            ctx->inputs[i]->frame_wanted_out = 1;
+            ff_filter_set_ready(ctx->inputs[i]->src, 100);
+        }
+    fs->frame_ready = 0;
+    framesync_advance(fs);
+}
+
 void ff_framesync_drop(FFFrameSync *fs)
 {
     fs->frame_ready = 0;
@@ -300,6 +317,27 @@  int ff_framesync_process_frame(FFFrameSync *fs, unsigned all)
     return count;
 }
 
+int ff_framesync_process_frame2(FFFrameSync *fs, unsigned all)
+{
+    int ret, count = 0;
+
+    av_assert0(fs->on_event);
+    while (1) {
+        ff_framesync_next2(fs);
+        if (fs->eof || !fs->frame_ready)
+            break;
+        if ((ret = fs->on_event(fs)) < 0)
+            return ret;
+        ff_framesync_drop(fs);
+        count++;
+        if (!all)
+            break;
+    }
+    if (!count && fs->eof)
+        return AVERROR_EOF;
+    return count;
+}
+
 int ff_framesync_filter_frame(FFFrameSync *fs, AVFilterLink *inlink,
                               AVFrame *in)
 {
@@ -314,6 +352,15 @@  int ff_framesync_filter_frame(FFFrameSync *fs, AVFilterLink *inlink,
     return 0;
 }
 
+int ff_framesync_activate(FFFrameSync *fs, AVFilterContext *ctx)
+{
+    int ret;
+
+    if ((ret = ff_framesync_process_frame2(fs, 1)) < 0)
+        return ret;
+    return 0;
+}
+
 int ff_framesync_request_frame(FFFrameSync *fs, AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
diff --git a/libavfilter/framesync.h b/libavfilter/framesync.h
index 7ba99d5..0f381e3 100644
--- a/libavfilter/framesync.h
+++ b/libavfilter/framesync.h
@@ -250,6 +250,7 @@  int ff_framesync_add_frame(FFFrameSync *fs, unsigned in, AVFrame *frame);
  * The status of the operation can be found in fs->frame_ready and fs->eof.
  */
 void ff_framesync_next(FFFrameSync *fs);
+void ff_framesync_next2(FFFrameSync *fs);
 
 /**
  * Drop the current frame event.
@@ -275,6 +276,7 @@  int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe,
  * @return  number of frames processed or negative error code
  */
 int ff_framesync_process_frame(FFFrameSync *fs, unsigned all);
+int ff_framesync_process_frame2(FFFrameSync *fs, unsigned all);
 
 
 /**
@@ -286,6 +288,8 @@  int ff_framesync_process_frame(FFFrameSync *fs, unsigned all);
 int ff_framesync_filter_frame(FFFrameSync *fs, AVFilterLink *inlink,
                               AVFrame *in);
 
+int ff_framesync_activate(FFFrameSync *fs, AVFilterContext *ctx);
+
 /**
  * Request a frame on the filter output.
  *
diff --git a/libavfilter/vf_stack.c b/libavfilter/vf_stack.c
index 03643b6..0e45952 100644
--- a/libavfilter/vf_stack.c
+++ b/libavfilter/vf_stack.c
@@ -58,10 +58,10 @@  static int query_formats(AVFilterContext *ctx)
     return ff_set_common_formats(ctx, pix_fmts);
 }
 
-static int filter_frame(AVFilterLink *inlink, AVFrame *in)
+static int activate(AVFilterContext *ctx)
 {
-    StackContext *s = inlink->dst->priv;
-    return ff_framesync_filter_frame(&s->fs, inlink, in);
+    StackContext *s = ctx->priv;
+    return ff_framesync_activate(&s->fs, ctx);
 }
 
 static av_cold int init(AVFilterContext *ctx)
@@ -83,7 +83,6 @@  static av_cold int init(AVFilterContext *ctx)
         pad.name = av_asprintf("input%d", i);
         if (!pad.name)
             return AVERROR(ENOMEM);
-        pad.filter_frame = filter_frame;
 
         if ((ret = ff_insert_inpad(ctx, i, &pad)) < 0) {
             av_freep(&pad.name);
@@ -237,7 +236,6 @@  static const AVFilterPad outputs[] = {
         .name          = "default",
         .type          = AVMEDIA_TYPE_VIDEO,
         .config_props  = config_output,
-        .request_frame = request_frame,
     },
     { NULL }
 };
@@ -274,6 +272,7 @@  AVFilter ff_vf_vstack = {
     .query_formats = query_formats,
     .outputs       = outputs,
     .init          = init,
+    .activate      = activate,
     .uninit        = uninit,
     .flags         = AVFILTER_FLAG_DYNAMIC_INPUTS,
 };
-- 
2.9.3