diff mbox

[FFmpeg-devel,PATCHv3] avfilter/vf_framerate: always request input if no output is provided in request_frame

Message ID 20170408124905.2867-1-cus@passwd.hu
State Accepted
Commit 51948b9d9e97e9065296db1d04885c1b45a1b250
Headers show

Commit Message

Marton Balint April 8, 2017, 12:49 p.m. UTC
Fixes ticket #6285.

Signed-off-by: Marton Balint <cus@passwd.hu>
---
 libavfilter/vf_framerate.c | 42 ++++++++++++++++++++++++++----------------
 1 file changed, 26 insertions(+), 16 deletions(-)

Comments

Marton Balint April 12, 2017, 7:23 p.m. UTC | #1
On Sat, 8 Apr 2017, Marton Balint wrote:

> Fixes ticket #6285.
>
> Signed-off-by: Marton Balint <cus@passwd.hu>
> ---
> libavfilter/vf_framerate.c | 42 ++++++++++++++++++++++++++----------------
> 1 file changed, 26 insertions(+), 16 deletions(-)

Applied this as well.

> @@ -695,7 +689,23 @@ static int request_frame(AVFilterLink *outlink)
>     }
>
>     set_work_frame_pts(ctx);
> -    return process_work_frame(ctx, 0);
> +    ret = process_work_frame(ctx, 0);
> +    if (ret < 0)
> +        return ret;
> +    if (ret)
> +        return ff_filter_frame(ctx->outputs[0], s->work);
> +
> +request:
> +    ff_dlog(ctx, "request_frame() call source's request_frame()\n");
> +    ret = ff_request_frame(ctx->inputs[0]);
> +    if (ret < 0 && (ret != AVERROR_EOF)) {
> +        ff_dlog(ctx, "request_frame() source's request_frame() returned error:%d\n", ret);
> +        return ret;
> +    } else if (ret == AVERROR_EOF) {
> +        s->flush = 1;
> +    }
> +    ff_dlog(ctx, "request_frame() source's request_frame() returned:%d\n", ret);
> +    return 0;
> }

Note that the above code which I moved returns 0 if ff_request_frame 
returns AVERROR_EOF. As far as I see, this can only happen a few times, 
not infinitely, so I am not sure if this is an error or not, so I kept is 
as it was before.

Regards,
Marton
Nicolas George April 12, 2017, 7:58 p.m. UTC | #2
Le tridi 23 germinal, an CCXXV, Marton Balint a écrit :
> Note that the above code which I moved returns 0 if ff_request_frame returns
> AVERROR_EOF. As far as I see, this can only happen a few times, not
> infinitely, so I am not sure if this is an error or not, so I kept is as it
> was before.

There are exactly three acceptable behaviours for request_frame() and
all the functions it calls:

* it pushes a frame and returns 0;

* it issues a ff_request_frame() on the input and returns 0;

* it returns EOF or an error.

If the "few times" correspond to frames pushed, then it is ok.
Otherwise, it is not. lavfi will not activate filters saying "hey, you
told me last time you had nothing to do, but just in case I am taking
news". A filter should never do nothing.

Regards,
Marton Balint April 15, 2017, 12:06 p.m. UTC | #3
On Wed, 12 Apr 2017, Nicolas George wrote:

> Le tridi 23 germinal, an CCXXV, Marton Balint a écrit :
>> Note that the above code which I moved returns 0 if ff_request_frame returns
>> AVERROR_EOF. As far as I see, this can only happen a few times, not
>> infinitely, so I am not sure if this is an error or not, so I kept is as it
>> was before.
>
> There are exactly three acceptable behaviours for request_frame() and
> all the functions it calls:
>
> * it pushes a frame and returns 0;
>
> * it issues a ff_request_frame() on the input and returns 0;
>
> * it returns EOF or an error.
>
> If the "few times" correspond to frames pushed, then it is ok.
> Otherwise, it is not. lavfi will not activate filters saying "hey, you
> told me last time you had nothing to do, but just in case I am taking
> news". A filter should never do nothing.

Well, then I guess the doc/filtering_design.txt is outdated, because
it uses term "making progress towards producing a frame" when returning 0

There is also an example code snippet there:

         if (frames_queued) {
             push_one_frame();
             return 0;
         }
         input = input_where_a_frame_is_most_needed();
         ret = ff_request_frame(input);
         if (ret == AVERROR_EOF) {
             process_eof_on_input();
         } else if (ret < 0) {
             return ret;
         }
         return 0;

Am I getting this right, process_eof_on_input() should be extended to

process_eof_on_input();
if (!frames_queued)
     return AVERROR_EOF;
push_one_frame();

Regards,
Marton
diff mbox

Patch

diff --git a/libavfilter/vf_framerate.c b/libavfilter/vf_framerate.c
index b4a74f7..dc8b05f 100644
--- a/libavfilter/vf_framerate.c
+++ b/libavfilter/vf_framerate.c
@@ -440,7 +440,7 @@  copy_done:
         s->pending_end_frame = 0;
     s->last_dest_frame_pts = s->work->pts;
 
-    return ff_filter_frame(ctx->outputs[0], s->work);
+    return 1;
 }
 
 static void set_srce_frame_dest_pts(AVFilterContext *ctx)
@@ -586,6 +586,7 @@  static int config_input(AVFilterLink *inlink)
 
 static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
 {
+    int ret;
     AVFilterContext *ctx = inlink->dst;
     FrameRateContext *s = ctx->priv;
 
@@ -606,7 +607,10 @@  static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
         set_srce_frame_dest_pts(ctx);
     }
 
-    return process_work_frame(ctx, 1);
+    ret = process_work_frame(ctx, 1);
+    if (ret < 0)
+        return ret;
+    return ret ? ff_filter_frame(ctx->outputs[0], s->work) : 0;
 }
 
 static int config_output(AVFilterLink *outlink)
@@ -658,23 +662,13 @@  static int request_frame(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
     FrameRateContext *s = ctx->priv;
-    int val, i;
+    int ret, i;
 
     ff_dlog(ctx, "request_frame()\n");
 
     // if there is no "next" frame AND we are not in flush then get one from our input filter
-    if (!s->srce[s->frst] && !s->flush) {
-        ff_dlog(ctx, "request_frame() call source's request_frame()\n");
-        val = ff_request_frame(outlink->src->inputs[0]);
-        if (val < 0 && (val != AVERROR_EOF)) {
-            ff_dlog(ctx, "request_frame() source's request_frame() returned error:%d\n", val);
-            return val;
-        } else if (val == AVERROR_EOF) {
-            s->flush = 1;
-        }
-        ff_dlog(ctx, "request_frame() source's request_frame() returned:%d\n", val);
-        return 0;
-    }
+    if (!s->srce[s->frst] && !s->flush)
+        goto request;
 
     ff_dlog(ctx, "request_frame() REPEAT or FLUSH\n");
 
@@ -695,7 +689,23 @@  static int request_frame(AVFilterLink *outlink)
     }
 
     set_work_frame_pts(ctx);
-    return process_work_frame(ctx, 0);
+    ret = process_work_frame(ctx, 0);
+    if (ret < 0)
+        return ret;
+    if (ret)
+        return ff_filter_frame(ctx->outputs[0], s->work);
+
+request:
+    ff_dlog(ctx, "request_frame() call source's request_frame()\n");
+    ret = ff_request_frame(ctx->inputs[0]);
+    if (ret < 0 && (ret != AVERROR_EOF)) {
+        ff_dlog(ctx, "request_frame() source's request_frame() returned error:%d\n", ret);
+        return ret;
+    } else if (ret == AVERROR_EOF) {
+        s->flush = 1;
+    }
+    ff_dlog(ctx, "request_frame() source's request_frame() returned:%d\n", ret);
+    return 0;
 }
 
 static const AVFilterPad framerate_inputs[] = {