[FFmpeg-devel] [PATCH v2 04/13] lavfi/vf_colorspace: support prim/trc/csp passthrough

Niklas Haas ffmpeg at haasn.xyz
Fri Oct 13 17:24:42 EEST 2023


From: Niklas Haas <git at haasn.dev>

Setting the output range/primaries/colorspace to unspecified now infers
the value from the input signal. If the input signal also has unknown
prim/trc, and no specific output is requested, enable passthrough mode.

As a technical implementation detail, define a static const sentinel
struct to represent "unknown" values. This is to avoid reconfiguring the
filter on every frame (which is guarded by s->out_primaries etc. being
NULL), as well as make the memcmp NOOP check succeed.
---
 libavfilter/vf_colorspace.c | 71 ++++++++++++++++---------------------
 1 file changed, 30 insertions(+), 41 deletions(-)

diff --git a/libavfilter/vf_colorspace.c b/libavfilter/vf_colorspace.c
index 2a30434401..5ab5266ef0 100644
--- a/libavfilter/vf_colorspace.c
+++ b/libavfilter/vf_colorspace.c
@@ -442,29 +442,23 @@ static int create_filtergraph(AVFilterContext *ctx,
         if (s->user_iprm != AVCOL_PRI_UNSPECIFIED)
             s->in_prm = s->user_iprm;
         s->in_primaries = av_csp_primaries_desc_from_id(s->in_prm);
-        if (!s->in_primaries) {
+        s->out_prm = out->color_primaries;
+        s->out_primaries = av_csp_primaries_desc_from_id(s->out_prm);
+        if (s->out_prm == AVCOL_PRI_UNSPECIFIED || s->fast_mode) {
+            static const AVColorPrimariesDesc unknown = {0};
+            s->in_primaries = s->out_primaries = &unknown; /* force passthrough */
+        } else if (!s->in_primaries) {
             av_log(ctx, AV_LOG_ERROR,
                    "Unsupported input primaries %d (%s)\n",
                    s->in_prm, av_color_primaries_name(s->in_prm));
             return AVERROR(EINVAL);
-        }
-        s->out_prm = out->color_primaries;
-        s->out_primaries = av_csp_primaries_desc_from_id(s->out_prm);
-        if (!s->out_primaries) {
-            if (s->out_prm == AVCOL_PRI_UNSPECIFIED) {
-                if (s->user_all == CS_UNSPECIFIED) {
-                    av_log(ctx, AV_LOG_ERROR, "Please specify output primaries\n");
-                } else {
-                    av_log(ctx, AV_LOG_ERROR,
-                           "Unsupported output color property %d\n", s->user_all);
-                }
-            } else {
-                av_log(ctx, AV_LOG_ERROR,
-                       "Unsupported output primaries %d (%s)\n",
-                       s->out_prm, av_color_primaries_name(s->out_prm));
-            }
+        } else if (!s->out_primaries) {
+            av_log(ctx, AV_LOG_ERROR,
+                   "Unsupported output primaries %d (%s)\n",
+                   s->out_prm, av_color_primaries_name(s->out_prm));
             return AVERROR(EINVAL);
         }
+
         s->lrgb2lrgb_passthrough = !memcmp(s->in_primaries, s->out_primaries,
                                            sizeof(*s->in_primaries));
         if (!s->lrgb2lrgb_passthrough) {
@@ -505,38 +499,33 @@ static int create_filtergraph(AVFilterContext *ctx,
         if (s->user_itrc != AVCOL_TRC_UNSPECIFIED)
             s->in_trc = s->user_itrc;
         s->in_txchr = get_transfer_characteristics(s->in_trc);
-        if (!s->in_txchr) {
-            av_log(ctx, AV_LOG_ERROR,
-                   "Unsupported input transfer characteristics %d (%s)\n",
-                   s->in_trc, av_color_transfer_name(s->in_trc));
-            return AVERROR(EINVAL);
-        }
     }
 
     if (!s->out_txchr) {
         av_freep(&s->lin_lut);
         s->out_trc = out->color_trc;
         s->out_txchr = get_transfer_characteristics(s->out_trc);
-        if (!s->out_txchr) {
-            if (s->out_trc == AVCOL_TRC_UNSPECIFIED) {
-                if (s->user_all == CS_UNSPECIFIED) {
-                    av_log(ctx, AV_LOG_ERROR,
-                           "Please specify output transfer characteristics\n");
-                } else {
-                    av_log(ctx, AV_LOG_ERROR,
-                           "Unsupported output color property %d\n", s->user_all);
-                }
-            } else {
-                av_log(ctx, AV_LOG_ERROR,
-                       "Unsupported output transfer characteristics %d (%s)\n",
-                       s->out_trc, av_color_transfer_name(s->out_trc));
-            }
-            return AVERROR(EINVAL);
-        }
     }
 
-    s->rgb2rgb_passthrough = s->fast_mode || (s->lrgb2lrgb_passthrough &&
-                             !memcmp(s->in_txchr, s->out_txchr, sizeof(*s->in_txchr)));
+    if ((s->out_trc == AVCOL_TRC_UNSPECIFIED && s->lrgb2lrgb_passthrough) || s->fast_mode) {
+        static const struct TransferCharacteristics unknown = {0};
+        s->in_txchr = s->out_txchr = &unknown; /* force passthrough */
+    } else if (!s->in_txchr) {
+        av_log(ctx, AV_LOG_ERROR,
+               "Unsupported input transfer characteristics %d (%s)\n",
+               s->in_trc, av_color_transfer_name(s->in_trc));
+        return AVERROR(EINVAL);
+    } else if (s->out_trc == AVCOL_TRC_UNSPECIFIED) {
+        s->out_txchr = s->in_txchr;
+    } else if (!s->out_txchr) {
+        av_log(ctx, AV_LOG_ERROR,
+               "Unsupported output transfer characteristics %d (%s)\n",
+               s->out_trc, av_color_transfer_name(s->out_trc));
+        return AVERROR(EINVAL);
+    }
+
+    s->rgb2rgb_passthrough = s->lrgb2lrgb_passthrough &&
+                             !memcmp(s->in_txchr, s->out_txchr, sizeof(*s->in_txchr));
     if (!s->rgb2rgb_passthrough && !s->lin_lut) {
         res = fill_gamma_table(s);
         if (res < 0)
-- 
2.42.0



More information about the ffmpeg-devel mailing list