diff mbox series

[FFmpeg-devel,11/16] lavfi/drawutils: reimplement ff_fill_rgba_map without hardcoding the list

Message ID 20211224030904.1196-12-rcombs@rcombs.me
State Accepted
Commit e24b71add534b44909519dcd0b5eaa0c9e9c9bbc
Headers show
Series [FFmpeg-devel,01/16] swscale/output: template-ize yuv2nv12cX 10-bit and 16-bit cases | expand

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished
andriy/make_ppc success Make finished
andriy/make_fate_ppc fail Make fate failed

Commit Message

rcombs Dec. 24, 2021, 3:08 a.m. UTC
Same outputs, but computed instead of statically known, so new formats will be
supported more easily. Asserts in place to ensure we update this if we add
anything incompatible with its logic.
---
 libavfilter/drawutils.c | 81 ++++++++++++++++++++---------------------
 1 file changed, 39 insertions(+), 42 deletions(-)
diff mbox series

Patch

diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c
index 0965afb03e..e4d6ddcf4c 100644
--- a/libavfilter/drawutils.c
+++ b/libavfilter/drawutils.c
@@ -21,6 +21,7 @@ 
 
 #include <string.h>
 
+#include "libavutil/avassert.h"
 #include "libavutil/avutil.h"
 #include "libavutil/colorspace.h"
 #include "libavutil/intreadwrite.h"
@@ -32,50 +33,46 @@  enum { RED = 0, GREEN, BLUE, ALPHA };
 
 int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt)
 {
-    switch (pix_fmt) {
-    case AV_PIX_FMT_0RGB:
-    case AV_PIX_FMT_ARGB:  rgba_map[ALPHA] = 0; rgba_map[RED  ] = 1; rgba_map[GREEN] = 2; rgba_map[BLUE ] = 3; break;
-    case AV_PIX_FMT_0BGR:
-    case AV_PIX_FMT_ABGR:  rgba_map[ALPHA] = 0; rgba_map[BLUE ] = 1; rgba_map[GREEN] = 2; rgba_map[RED  ] = 3; break;
-    case AV_PIX_FMT_RGB48LE:
-    case AV_PIX_FMT_RGB48BE:
-    case AV_PIX_FMT_RGBA64BE:
-    case AV_PIX_FMT_RGBA64LE:
-    case AV_PIX_FMT_RGB0:
-    case AV_PIX_FMT_RGBA:
-    case AV_PIX_FMT_RGB24: rgba_map[RED  ] = 0; rgba_map[GREEN] = 1; rgba_map[BLUE ] = 2; rgba_map[ALPHA] = 3; break;
-    case AV_PIX_FMT_BGR48LE:
-    case AV_PIX_FMT_BGR48BE:
-    case AV_PIX_FMT_BGRA64BE:
-    case AV_PIX_FMT_BGRA64LE:
-    case AV_PIX_FMT_BGRA:
-    case AV_PIX_FMT_BGR0:
-    case AV_PIX_FMT_BGR24: rgba_map[BLUE ] = 0; rgba_map[GREEN] = 1; rgba_map[RED  ] = 2; rgba_map[ALPHA] = 3; break;
-    case AV_PIX_FMT_GBRP9LE:
-    case AV_PIX_FMT_GBRP9BE:
-    case AV_PIX_FMT_GBRP10LE:
-    case AV_PIX_FMT_GBRP10BE:
-    case AV_PIX_FMT_GBRP12LE:
-    case AV_PIX_FMT_GBRP12BE:
-    case AV_PIX_FMT_GBRP14LE:
-    case AV_PIX_FMT_GBRP14BE:
-    case AV_PIX_FMT_GBRP16LE:
-    case AV_PIX_FMT_GBRP16BE:
-    case AV_PIX_FMT_GBRAP:
-    case AV_PIX_FMT_GBRAP10LE:
-    case AV_PIX_FMT_GBRAP10BE:
-    case AV_PIX_FMT_GBRAP12LE:
-    case AV_PIX_FMT_GBRAP12BE:
-    case AV_PIX_FMT_GBRAP16LE:
-    case AV_PIX_FMT_GBRAP16BE:
-    case AV_PIX_FMT_GBRPF32LE:
-    case AV_PIX_FMT_GBRPF32BE:
-    case AV_PIX_FMT_GBRAPF32LE:
-    case AV_PIX_FMT_GBRAPF32BE:
-    case AV_PIX_FMT_GBRP:  rgba_map[GREEN] = 0; rgba_map[BLUE ] = 1; rgba_map[RED  ] = 2; rgba_map[ALPHA] = 3; break;
-    default:                    /* unsupported */
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
+    if (!(desc->flags & AV_PIX_FMT_FLAG_RGB))
         return AVERROR(EINVAL);
+    if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM)
+        return AVERROR(EINVAL);
+    av_assert0(desc->nb_components == 3 + !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA));
+    if (desc->flags & AV_PIX_FMT_FLAG_PLANAR) {
+        rgba_map[RED]   = desc->comp[0].plane;
+        rgba_map[GREEN] = desc->comp[1].plane;
+        rgba_map[BLUE]  = desc->comp[2].plane;
+        rgba_map[ALPHA] = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) ? desc->comp[3].plane : 3;
+    } else {
+        int had0 = 0;
+        unsigned depthb = 0;
+        unsigned i;
+        for (i = 0; i < desc->nb_components; i++) {
+            /* all components must have same depth in bytes */
+            unsigned db = (desc->comp[i].depth + 7) / 8;
+            unsigned pos = desc->comp[i].offset / db;
+            if (depthb && (depthb != db))
+                return AVERROR(ENOSYS);
+
+            if (desc->comp[i].offset % db)
+                return AVERROR(ENOSYS);
+
+            had0 |= pos == 0;
+            rgba_map[i] = pos;
+        }
+
+        if (desc->nb_components == 3)
+            rgba_map[ALPHA] = had0 ? 3 : 0;
     }
+
+    av_assert0(rgba_map[RED]   != rgba_map[GREEN]);
+    av_assert0(rgba_map[GREEN] != rgba_map[BLUE]);
+    av_assert0(rgba_map[BLUE]  != rgba_map[RED]);
+    av_assert0(rgba_map[RED]   != rgba_map[ALPHA]);
+    av_assert0(rgba_map[GREEN] != rgba_map[ALPHA]);
+    av_assert0(rgba_map[BLUE]  != rgba_map[ALPHA]);
+
     return 0;
 }