diff mbox series

[FFmpeg-devel] avfilter/vf_pad: respect frame colorspace tag in RGB to YUV conversion

Message ID 20230827195115.105591-1-leo.izen@gmail.com
State New
Headers show
Series [FFmpeg-devel] avfilter/vf_pad: respect frame colorspace tag in RGB to YUV conversion | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 fail Make fate failed
andriy/make_x86 success Make finished
andriy/make_fate_x86 fail Make fate failed

Commit Message

Leo Izen Aug. 27, 2023, 7:51 p.m. UTC
vf_pad calls ff_draw_init, which assumes BT.709 and TV range for its
YUV matricies. Since the filter only accepts RGB inputs for the color
argument, it needs to convert them to YUV for YUV input video, and it
should respect the tagged colormatrix when doing such a conversion, but
it does not. It can do this by calling ff_draw_init2, and this patch
causes the filter to re-init when the first frame is received, as that
is when that colormatrix tag becomes available.

If the filter is not initialized before the first frame, then an
assertion will fail in avfilter.c when it does sanity checks on
input/output dimensions, so the original initialization cannot be
skipped.

Signed-off-by: Leo Izen <leo.izen@gmail.com>
---
 libavfilter/vf_pad.c | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

Comments

Leo Izen Sept. 4, 2023, 11:21 a.m. UTC | #1
On 8/27/23 15:51, Leo Izen wrote:
> vf_pad calls ff_draw_init, which assumes BT.709 and TV range for its
> YUV matricies. Since the filter only accepts RGB inputs for the color
> argument, it needs to convert them to YUV for YUV input video, and it
> should respect the tagged colormatrix when doing such a conversion, but
> it does not. It can do this by calling ff_draw_init2, and this patch
> causes the filter to re-init when the first frame is received, as that
> is when that colormatrix tag becomes available.
> 
> If the filter is not initialized before the first frame, then an
> assertion will fail in avfilter.c when it does sanity checks on
> input/output dimensions, so the original initialization cannot be
> skipped.
> 
> Signed-off-by: Leo Izen <leo.izen@gmail.com>
> ---
>   libavfilter/vf_pad.c | 21 ++++++++++++++++-----
>   1 file changed, 16 insertions(+), 5 deletions(-)
> 

Bumping, thanks.

- Leo Izen (Traneptora)
diff mbox series

Patch

diff --git a/libavfilter/vf_pad.c b/libavfilter/vf_pad.c
index e52f7284d4..01de896772 100644
--- a/libavfilter/vf_pad.c
+++ b/libavfilter/vf_pad.c
@@ -100,9 +100,10 @@  typedef struct PadContext {
     FFDrawColor color;
 
     int eval_mode;          ///< expression evaluation mode
+    int configured_input;   ///< if config_input has been called yet
 } PadContext;
 
-static int config_input(AVFilterLink *inlink)
+static int config_frame_input(AVFilterLink *inlink, const AVFrame *frame)
 {
     AVFilterContext *ctx = inlink->dst;
     PadContext *s = ctx->priv;
@@ -111,7 +112,10 @@  static int config_input(AVFilterLink *inlink)
     double var_values[VARS_NB], res;
     char *expr;
 
-    ff_draw_init(&s->draw, inlink->format, 0);
+    if (frame)
+        ff_draw_init2(&s->draw, inlink->format, frame->colorspace, frame->color_range, 0);
+    else
+        ff_draw_init(&s->draw, inlink->format, 0);
     ff_draw_color(&s->draw, &s->color, s->rgba_color);
 
     var_values[VAR_IN_W]  = var_values[VAR_IW] = inlink->w;
@@ -216,6 +220,11 @@  eval_fail:
 
 }
 
+static int config_input(AVFilterLink *inlink)
+{
+    return config_frame_input(inlink, NULL);
+}
+
 static int config_output(AVFilterLink *outlink)
 {
     PadContext *s = outlink->src->priv;
@@ -326,11 +335,11 @@  static int filter_frame(AVFilterLink *inlink, AVFrame *in)
     AVFilterLink *outlink = inlink->dst->outputs[0];
     AVFrame *out;
     int needs_copy;
-    if(s->eval_mode == EVAL_MODE_FRAME && (
+    if((s->eval_mode == EVAL_MODE_FRAME && (
            in->width  != s->inlink_w
         || in->height != s->inlink_h
         || in->format != outlink->format
-        || in->sample_aspect_ratio.den != outlink->sample_aspect_ratio.den || in->sample_aspect_ratio.num != outlink->sample_aspect_ratio.num)) {
+        || in->sample_aspect_ratio.den != outlink->sample_aspect_ratio.den || in->sample_aspect_ratio.num != outlink->sample_aspect_ratio.num)) || !s->configured_input) {
         int ret;
 
         inlink->dst->inputs[0]->format = in->format;
@@ -341,7 +350,7 @@  static int filter_frame(AVFilterLink *inlink, AVFrame *in)
         inlink->dst->inputs[0]->sample_aspect_ratio.num = in->sample_aspect_ratio.num;
 
 
-        if ((ret = config_input(inlink)) < 0) {
+        if ((ret = config_frame_input(inlink, in)) < 0) {
             s->inlink_w = -1;
             return ret;
         }
@@ -349,6 +358,8 @@  static int filter_frame(AVFilterLink *inlink, AVFrame *in)
             s->inlink_w = -1;
             return ret;
         }
+
+        s->configured_input = 1;
     }
 
     needs_copy = frame_needs_copy(s, in);