diff mbox series

[FFmpeg-devel] lavfi/vf_fieldmatch: keep fields as-is if not matched properly

Message ID 399842a707482604827e62860e98cb37@nodoa.me
State Accepted
Commit e8850bc2a8590ac66346de7a6d4831d1778746d1
Headers show
Series [FFmpeg-devel] lavfi/vf_fieldmatch: keep fields as-is if not matched properly | expand

Checks

Context Check Description
yinshiyou/commit_msg_loongarch64 warning Please wrap lines in the body of the commit message between 60 and 72 characters.
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 fail Make fate failed

Commit Message

mail@nodoa.me Nov. 3, 2022, 2:40 p.m. UTC
Makes it possible to use deinterlacers which output one frame for each field as fallback if field
matching fails (combmatch=full).

Currently, the documented example with fallback on a post-deinterlacer will only work in case the
deinterlacer outputs one frame per first field (as yadif=mode=0). The reason for that is that
fieldmatch will attempt to match the second field regardless of whether it recognizes the end
result is still interlaced. This produces garbled output with for example mixed telecined 24fps and
60i content combined with a field-based deinterlaced such as yadif=mode=1.
This patch orders fieldmatch to revert to using the second field of the current frame in case the
end result is still interlaced and a post-deinterlacer is assumed to be used.

Signed-off-by: lovesyk <lovesyk@users.noreply.github.com>
---
 libavfilter/vf_fieldmatch.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

Comments

Paul B Mahol Nov. 4, 2022, 1:24 p.m. UTC | #1
On 11/3/22, mail@nodoa.me <mail@nodoa.me> wrote:
> Makes it possible to use deinterlacers which output one frame for each field
> as fallback if field
> matching fails (combmatch=full).
>
> Currently, the documented example with fallback on a post-deinterlacer will
> only work in case the
> deinterlacer outputs one frame per first field (as yadif=mode=0). The reason
> for that is that
> fieldmatch will attempt to match the second field regardless of whether it
> recognizes the end
> result is still interlaced. This produces garbled output with for example
> mixed telecined 24fps and
> 60i content combined with a field-based deinterlaced such as yadif=mode=1.
> This patch orders fieldmatch to revert to using the second field of the
> current frame in case the
> end result is still interlaced and a post-deinterlacer is assumed to be
> used.
>

Are there samples, ways to reproduce this?

> Signed-off-by: lovesyk <lovesyk@users.noreply.github.com>
> ---
>  libavfilter/vf_fieldmatch.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/libavfilter/vf_fieldmatch.c b/libavfilter/vf_fieldmatch.c
> index 40e559df9e..bf946beec9 100644
> --- a/libavfilter/vf_fieldmatch.c
> +++ b/libavfilter/vf_fieldmatch.c
> @@ -680,7 +680,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame
> *in)
>      AVFilterLink *outlink = ctx->outputs[0];
>      FieldMatchContext *fm = ctx->priv;
>      int combs[] = { -1, -1, -1, -1, -1 };
> -    int order, field, i, match, sc = 0, ret = 0;
> +    int order, field, i, match, interlaced_frame, sc = 0, ret = 0;
>      const int *fxo;
>      AVFrame *gen_frames[] = { NULL, NULL, NULL, NULL, NULL };
>      AVFrame *dst = NULL;
> @@ -793,6 +793,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame
> *in)
>          }
>      }
>
> +    /* keep fields as-is if not matched properly */
> +    interlaced_frame = combs[match] >= fm->combpel;
> +    if (interlaced_frame && fm->combmatch == COMBMATCH_FULL) {
> +        match = mC;
> +    }
> +
>      /* get output frame and drop the others */
>      if (fm->ppsrc) {
>          /* field matching was based on a filtered/post-processed input, we
> now
> @@ -813,7 +819,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame
> *in)
>
>      /* mark the frame we are unable to match properly as interlaced so a
> proper
>       * de-interlacer can take the relay */
> -    dst->interlaced_frame = combs[match] >= fm->combpel;
> +    dst->interlaced_frame = interlaced_frame;
>      if (dst->interlaced_frame) {
>          av_log(ctx, AV_LOG_WARNING, "Frame #%"PRId64" at %s is still
> interlaced\n",
>                 outlink->frame_count_in, av_ts2timestr(in->pts,
> &inlink->time_base));
> --
> 2.34.2
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
>
diff mbox series

Patch

diff --git a/libavfilter/vf_fieldmatch.c b/libavfilter/vf_fieldmatch.c
index 40e559df9e..bf946beec9 100644
--- a/libavfilter/vf_fieldmatch.c
+++ b/libavfilter/vf_fieldmatch.c
@@ -680,7 +680,7 @@  static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     AVFilterLink *outlink = ctx->outputs[0];
     FieldMatchContext *fm = ctx->priv;
     int combs[] = { -1, -1, -1, -1, -1 };
-    int order, field, i, match, sc = 0, ret = 0;
+    int order, field, i, match, interlaced_frame, sc = 0, ret = 0;
     const int *fxo;
     AVFrame *gen_frames[] = { NULL, NULL, NULL, NULL, NULL };
     AVFrame *dst = NULL;
@@ -793,6 +793,12 @@  static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         }
     }
 
+    /* keep fields as-is if not matched properly */
+    interlaced_frame = combs[match] >= fm->combpel;
+    if (interlaced_frame && fm->combmatch == COMBMATCH_FULL) {
+        match = mC;
+    }
+
     /* get output frame and drop the others */
     if (fm->ppsrc) {
         /* field matching was based on a filtered/post-processed input, we now
@@ -813,7 +819,7 @@  static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 
     /* mark the frame we are unable to match properly as interlaced so a proper
      * de-interlacer can take the relay */
-    dst->interlaced_frame = combs[match] >= fm->combpel;
+    dst->interlaced_frame = interlaced_frame;
     if (dst->interlaced_frame) {
         av_log(ctx, AV_LOG_WARNING, "Frame #%"PRId64" at %s is still interlaced\n",
                outlink->frame_count_in, av_ts2timestr(in->pts, &inlink->time_base));