[FFmpeg-cvslog] lavf/vf_deinterlace_vaapi: flush queued frame for field in DeinterlacingBob

Linjie Fu git at videolan.org
Wed Jan 12 05:00:49 EET 2022


ffmpeg | branch: master | Linjie Fu <linjie.fu at intel.com> | Wed Sep 18 16:19:58 2019 +0800| [9c58fd22269c9784f1f97d7e4a30daf4e06917f8] | committer: Haihao Xiang

lavf/vf_deinterlace_vaapi: flush queued frame for field in DeinterlacingBob

For DeinterlacingBob mode with rate=field, the frame number of output
should equal 2x input total since only intra deinterlace is used.

Currently for "backward_ref = 0, rate = field", extra_delay is
introduced. Due to the async without flush, frame number of output is
[expected_number - 2].

Specifically, if the input only has 1 frame, the output will be empty.

Add deint_vaapi_request_frame for deinterlace_vaapi, send NULL frame
to flush the queued frame.

For 1 frame input in Bob mode with rate=field,
before patch: 0 frame;
after  patch: 2 frames;

ffmpeg -hwaccel vaapi -hwaccel_device /dev/dri/renderD128
        -hwaccel_output_format vaapi -i input.h264 -an -vf
        deinterlace_vaapi=mode=bob:rate=field -f null -

Tested-by: Mark Thompson <sw at jkqxz.net>
Reviewed-by: Mark Thompson <sw at jkqxz.net>
Signed-off-by: Linjie Fu <linjie.fu at intel.com>
Signed-off-by: Haihao Xiang <haihao.xiang at intel.com>

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

 libavfilter/vf_deinterlace_vaapi.c | 44 ++++++++++++++++++++++++++++++++------
 1 file changed, 38 insertions(+), 6 deletions(-)

diff --git a/libavfilter/vf_deinterlace_vaapi.c b/libavfilter/vf_deinterlace_vaapi.c
index 65f319ba9a..1304561034 100644
--- a/libavfilter/vf_deinterlace_vaapi.c
+++ b/libavfilter/vf_deinterlace_vaapi.c
@@ -46,6 +46,9 @@ typedef struct DeintVAAPIContext {
     int                queue_count;
     AVFrame           *frame_queue[MAX_REFERENCES];
     int                extra_delay_for_timestamps;
+
+    int                eof;
+    int                prev_pts;
 } DeintVAAPIContext;
 
 static const char *deint_vaapi_mode_name(int mode)
@@ -188,9 +191,11 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame)
     void *filter_params_addr = NULL;
     int err, i, field, current_frame_index;
 
-    av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n",
-           av_get_pix_fmt_name(input_frame->format),
-           input_frame->width, input_frame->height, input_frame->pts);
+    // NULL frame is used to flush the queue in field mode
+    if (input_frame)
+        av_log(avctx, AV_LOG_DEBUG, "Filter input: %s, %ux%u (%"PRId64").\n",
+            av_get_pix_fmt_name(input_frame->format),
+            input_frame->width, input_frame->height, input_frame->pts);
 
     if (ctx->queue_count < ctx->queue_depth) {
         ctx->frame_queue[ctx->queue_count++] = input_frame;
@@ -208,6 +213,9 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame)
     current_frame_index = ctx->pipeline_caps.num_forward_references;
 
     input_frame = ctx->frame_queue[current_frame_index];
+    if (!input_frame)
+        return 0;
+
     input_surface = (VASurfaceID)(uintptr_t)input_frame->data[3];
     for (i = 0; i < ctx->pipeline_caps.num_forward_references; i++)
         forward_references[i] = (VASurfaceID)(uintptr_t)
@@ -289,6 +297,8 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame)
         if (ctx->field_rate == 2) {
             if (field == 0)
                 output_frame->pts = 2 * input_frame->pts;
+            else if (ctx->eof)
+                output_frame->pts = 3 * input_frame->pts - ctx->prev_pts;
             else
                 output_frame->pts = input_frame->pts +
                     ctx->frame_queue[current_frame_index + 1]->pts;
@@ -304,6 +314,8 @@ static int deint_vaapi_filter_frame(AVFilterLink *inlink, AVFrame *input_frame)
             break;
     }
 
+    ctx->prev_pts = input_frame->pts;
+
     return err;
 
 fail:
@@ -313,6 +325,25 @@ fail:
     return err;
 }
 
+static int deint_vaapi_request_frame(AVFilterLink *link)
+{
+    AVFilterContext *avctx = link->src;
+    DeintVAAPIContext *ctx   = avctx->priv;
+    int ret;
+
+    if (ctx->eof)
+        return AVERROR_EOF;
+
+    ret = ff_request_frame(link->src->inputs[0]);
+    if (ret == AVERROR_EOF && ctx->extra_delay_for_timestamps) {
+        ctx->eof = 1;
+        deint_vaapi_filter_frame(link->src->inputs[0], NULL);
+    } else if (ret < 0)
+        return ret;
+
+    return 0;
+}
+
 static av_cold int deint_vaapi_init(AVFilterContext *avctx)
 {
     VAAPIVPPContext *vpp_ctx = avctx->priv;
@@ -373,9 +404,10 @@ static const AVFilterPad deint_vaapi_inputs[] = {
 
 static const AVFilterPad deint_vaapi_outputs[] = {
     {
-        .name = "default",
-        .type = AVMEDIA_TYPE_VIDEO,
-        .config_props = &deint_vaapi_config_output,
+        .name           = "default",
+        .type           = AVMEDIA_TYPE_VIDEO,
+        .request_frame  = &deint_vaapi_request_frame,
+        .config_props   = &deint_vaapi_config_output,
     },
 };
 



More information about the ffmpeg-cvslog mailing list