[vlc-commits] [Git][videolan/vlc][master] 9 commits: fourcc: add Y212

Felix Paul Kühne (@fkuehne) gitlab at videolan.org
Thu Apr 23 18:28:37 UTC 2026



Felix Paul Kühne pushed to branch master at VideoLAN / VLC


Commits:
1c1cc575 by Thomas Guillem at 2026-04-23T20:03:51+02:00
fourcc: add Y212

- - - - -
41d67207 by Thomas Guillem at 2026-04-23T20:03:51+02:00
fourcc: add VAAPI 422 chromas

- - - - -
1441ec4d by Thomas Guillem at 2026-04-23T20:03:51+02:00
vlc_vaapi: handle VLC_CODEC_VAAPI_422*

- - - - -
f9d5ac20 by Thomas Guillem at 2026-04-23T20:03:51+02:00
opengl: sampler: add Y210/Y212 packed shader

- - - - -
6714c1c9 by Thomas Guillem at 2026-04-23T20:03:51+02:00
interop_vaapi: use texs ratio instead of chroma ratios

And remove the P012/NV12 special case.

This will be needed for VLC_CODEC_VAAPI_422_*.

- - - - -
c8ae7aef by Thomas Guillem at 2026-04-23T20:03:51+02:00
interop_vaapi: handle Y210/Y212

- - - - -
0e75b935 by Thomas Guillem at 2026-04-23T20:03:51+02:00
avcodec: vaapi: support VAAPI 422 chromas

- - - - -
71dcea89 by Thomas Guillem at 2026-04-23T20:03:51+02:00
avcodec: chroma: add Y210/Y212 in chroma table

To enable swscale color conversion.

- - - - -
fd0fbaeb by Thomas Guillem at 2026-04-23T20:03:51+02:00
vaapi: chroma: add 422 10/12 bits conversion support

- - - - -


11 changed files:

- include/vlc_fourcc.h
- modules/codec/avcodec/chroma.c
- modules/codec/avcodec/vaapi.c
- modules/hw/vaapi/chroma.c
- modules/hw/vaapi/filters.c
- modules/hw/vaapi/vlc_vaapi.c
- modules/hw/vaapi/vlc_vaapi.h
- modules/video_output/opengl/interop_vaapi.c
- modules/video_output/opengl/sampler.c
- src/misc/fourcc.c
- src/misc/fourcc_list.h


Changes:

=====================================
include/vlc_fourcc.h
=====================================
@@ -330,6 +330,8 @@
 #define VLC_CODEC_R420            VLC_FOURCC('r','4','2','0')
 /* Packed YUV 4:2:2 10-bit V10:U10:Y10:A2 */
 #define VLC_CODEC_Y210            VLC_FOURCC('Y','2','1','0')
+/* Packed YUV 4:2:2 12-bit V12:U12:Y12:A2 */
+#define VLC_CODEC_Y212            VLC_FOURCC('Y','2','1','2')
 /* Packed YUV 4:4:4 10-bit V10:U10:Y10:A2 */
 #define VLC_CODEC_Y410            VLC_FOURCC('Y','4','1','0')
 /* Packed YUV 4:4:4 12-bit V12:U12:Y12:A2 */
@@ -462,6 +464,8 @@
 #define VLC_CODEC_VAAPI_420 VLC_FOURCC('V','A','O','P') /* 4:2:0  8 bpc */
 #define VLC_CODEC_VAAPI_420_10BPP VLC_FOURCC('V','A','O','0') /* 4:2:0 10 bpc */
 #define VLC_CODEC_VAAPI_420_12BPP VLC_FOURCC('V','A','O','2') /* 4:2:0 12 bpc */
+#define VLC_CODEC_VAAPI_422_10BPP VLC_FOURCC('V','A','2','0') /* 4:2:2 10 bpc */
+#define VLC_CODEC_VAAPI_422_12BPP VLC_FOURCC('V','A','2','2') /* 4:2:2 12 bpc */
 #define VLC_CODEC_VAAPI_444       VLC_FOURCC('V','A','4','P') /* 4:4:4 8 bpc */
 #define VLC_CODEC_VAAPI_444_10BPP VLC_FOURCC('V','A','4','0') /* 4:4:4 10 bpc */
 #define VLC_CODEC_VAAPI_444_12BPP VLC_FOURCC('V','A','4','2') /* 4:4:4 12 bpc */


=====================================
modules/codec/avcodec/chroma.c
=====================================
@@ -122,6 +122,8 @@ static const struct vlc_chroma_ffmpeg chroma_table[] =
     {VLC_CODEC_VUYX, AV_PIX_FMT_VUYX,     COLOR_RANGE_UNDEF },
 #endif
 #if LIBAVUTIL_VERSION_CHECK(57, 36, 100)
+    {VLC_CODEC_Y210, AV_PIX_FMT_Y210LE,   COLOR_RANGE_UNDEF },
+    {VLC_CODEC_Y212, AV_PIX_FMT_Y212LE,   COLOR_RANGE_UNDEF },
     {VLC_CODEC_Y410, AV_PIX_FMT_XV30LE,   COLOR_RANGE_UNDEF },
     {VLC_CODEC_Y412, AV_PIX_FMT_XV36LE,   COLOR_RANGE_UNDEF },
 #endif


=====================================
modules/codec/avcodec/vaapi.c
=====================================
@@ -375,6 +375,14 @@ static int Create(vlc_va_t *va, struct vlc_va_cfg *cfg)
             case AV_PIX_FMT_P012BE:
                 vlc_chroma = VLC_CODEC_VAAPI_420_12BPP;
                 break;
+            case AV_PIX_FMT_Y210BE:
+            case AV_PIX_FMT_Y210LE:
+                vlc_chroma = VLC_CODEC_VAAPI_422_10BPP;
+                break;
+            case AV_PIX_FMT_Y212BE:
+            case AV_PIX_FMT_Y212LE:
+                vlc_chroma = VLC_CODEC_VAAPI_422_12BPP;
+                break;
             case AV_PIX_FMT_XV30BE:
             case AV_PIX_FMT_XV30LE:
                 vlc_chroma = VLC_CODEC_VAAPI_444_10BPP;


=====================================
modules/hw/vaapi/chroma.c
=====================================
@@ -131,6 +131,8 @@ FillPictureFromVAImage(picture_t *dest,
                 vlc_assert_unreachable();
         }
         break;
+    case VA_FOURCC_Y210:
+    case VA_FOURCC_Y212:
     case VA_FOURCC_XYUV:
     case VA_FOURCC_Y410:
     case VA_FOURCC_Y412:
@@ -360,6 +362,20 @@ static int CheckFmt(const video_format_t *in, const video_format_t *out,
                 return VLC_SUCCESS;
             }
             break;
+        case VLC_CODEC_VAAPI_422_10BPP:
+            if (out->i_chroma == VLC_CODEC_Y210)
+            {
+                *pixel_bytes = 4;
+                return VLC_SUCCESS;
+            }
+            break;
+        case VLC_CODEC_VAAPI_422_12BPP:
+            if (out->i_chroma == VLC_CODEC_Y212)
+            {
+                *pixel_bytes = 4;
+                return VLC_SUCCESS;
+            }
+            break;
         case VLC_CODEC_VAAPI_444:
             if (out->i_chroma == VLC_CODEC_VUYX)
             {
@@ -406,6 +422,20 @@ static int CheckFmt(const video_format_t *in, const video_format_t *out,
                 return VLC_SUCCESS;
             }
             break;
+        case VLC_CODEC_VAAPI_422_10BPP:
+            if (in->i_chroma == VLC_CODEC_Y210)
+            {
+                *pixel_bytes = 4;
+                return VLC_SUCCESS;
+            }
+            break;
+        case VLC_CODEC_VAAPI_422_12BPP:
+            if (in->i_chroma == VLC_CODEC_Y212)
+            {
+                *pixel_bytes = 4;
+                return VLC_SUCCESS;
+            }
+            break;
         case VLC_CODEC_VAAPI_444:
             if (in->i_chroma == VLC_CODEC_VUYX)
             {


=====================================
modules/hw/vaapi/filters.c
=====================================
@@ -1127,6 +1127,8 @@ static void ProbeChroma(vlc_chroma_conv_vec *vec)
     vlc_chroma_conv_add(vec, 1.1, VLC_CODEC_VAAPI_420_10BPP, VLC_CODEC_I420_10L, true);
     vlc_chroma_conv_add(vec, 1.1, VLC_CODEC_VAAPI_420_12BPP, VLC_CODEC_P012, true);
     vlc_chroma_conv_add(vec, 1.1, VLC_CODEC_VAAPI_420_12BPP, VLC_CODEC_I420_12L, true);
+    vlc_chroma_conv_add(vec, 1.1, VLC_CODEC_VAAPI_422_10BPP, VLC_CODEC_Y210, true);
+    vlc_chroma_conv_add(vec, 1.1, VLC_CODEC_VAAPI_422_12BPP, VLC_CODEC_Y212, true);
     vlc_chroma_conv_add(vec, 1.1, VLC_CODEC_VAAPI_444, VLC_CODEC_VUYX, true);
     vlc_chroma_conv_add(vec, 1.1, VLC_CODEC_VAAPI_444_10BPP, VLC_CODEC_Y410, true);
     vlc_chroma_conv_add(vec, 1.1, VLC_CODEC_VAAPI_444_12BPP, VLC_CODEC_Y412, true);


=====================================
modules/hw/vaapi/vlc_vaapi.c
=====================================
@@ -59,6 +59,14 @@ vlc_chroma_to_vaapi(int i_vlc_chroma, unsigned *va_rt_format, int *va_fourcc)
             *va_rt_format = VA_RT_FORMAT_YUV420_12;
             *va_fourcc = VA_FOURCC_P012;
             break;
+        case VLC_CODEC_VAAPI_422_10BPP:
+            *va_rt_format = VA_RT_FORMAT_YUV422_10;
+            *va_fourcc = VA_FOURCC_Y210;
+            break;
+        case VLC_CODEC_VAAPI_422_12BPP:
+            *va_rt_format = VA_RT_FORMAT_YUV422_12;
+            *va_fourcc = VA_FOURCC_Y212;
+            break;
         case VLC_CODEC_VAAPI_444:
             *va_rt_format = VA_RT_FORMAT_YUV444;
             *va_fourcc = VA_FOURCC_XYUV;


=====================================
modules/hw/vaapi/vlc_vaapi.h
=====================================
@@ -198,6 +198,8 @@ vlc_vaapi_IsChromaOpaque(int i_vlc_chroma)
         case VLC_CODEC_VAAPI_420:
         case VLC_CODEC_VAAPI_420_10BPP:
         case VLC_CODEC_VAAPI_420_12BPP:
+        case VLC_CODEC_VAAPI_422_10BPP:
+        case VLC_CODEC_VAAPI_422_12BPP:
         case VLC_CODEC_VAAPI_444:
         case VLC_CODEC_VAAPI_444_10BPP:
         case VLC_CODEC_VAAPI_444_12BPP:


=====================================
modules/video_output/opengl/interop_vaapi.c
=====================================
@@ -154,6 +154,10 @@ vaegl_init_fourcc(struct priv *priv, unsigned va_fourcc)
             priv->drm_fourccs[0] = VLC_FOURCC('R', '1', '6', ' ');
             priv->drm_fourccs[1] = VLC_FOURCC('G', 'R', '3', '2');
             break;
+        case VA_FOURCC_Y210:
+        case VA_FOURCC_Y212:
+            priv->drm_fourccs[0] = VLC_FOURCC('A', 'B', '4', '8');
+            break;
         case VA_FOURCC_XYUV:
         case VA_FOURCC_Y410:
         case VA_FOURCC_Y412:
@@ -350,8 +354,7 @@ tc_va_check_interop_blacklist(const struct vlc_gl_interop *interop, VADisplay *v
 }
 
 static int
-tc_va_check_derive_image(const struct vlc_gl_interop *interop,
-                         vlc_fourcc_t sw_chroma)
+tc_va_check_derive_image(const struct vlc_gl_interop *interop)
 {
     vlc_object_t *o = VLC_OBJECT(interop->gl);
     struct priv *priv = interop->priv;
@@ -370,11 +373,6 @@ tc_va_check_derive_image(const struct vlc_gl_interop *interop,
         goto done;
     assert(va_image.format.fourcc == priv->fourcc);
 
-    const vlc_chroma_description_t *image_desc =
-        vlc_fourcc_GetChromaDescription(sw_chroma);
-    assert(image_desc != NULL);
-    assert(image_desc->plane_count == va_image.num_planes);
-
     VABufferInfo va_buffer_info = (VABufferInfo) {
         .mem_type = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME
     };
@@ -383,14 +381,10 @@ tc_va_check_derive_image(const struct vlc_gl_interop *interop,
     if (ret != VLC_SUCCESS)
         goto done;
 
-    for (unsigned i = 0; i < image_desc->plane_count; ++i)
+    for (unsigned i = 0; i < interop->tex_count; ++i)
     {
-        unsigned w_num = image_desc->p[i].w.num;
-        if (image_desc->plane_count == 2 && i == 1)
-            // for NV12/P010 the second plane uses GL_RG which has a double pitch
-            w_num /= 2;
-        EGLint w = (va_image.width * w_num) / image_desc->p[i].w.den;
-        EGLint h = (va_image.height * image_desc->p[i].h.num) / image_desc->p[i].h.den;
+        EGLint w = (va_image.width * interop->texs[i].w.num) / interop->texs[i].w.den;
+        EGLint h = (va_image.height * interop->texs[i].h.num) / interop->texs[i].h.den;
         EGLImageKHR egl_image =
             vaegl_image_create(interop, w, h, priv->drm_fourccs[i], va_buffer_info.handle,
                                va_image.offsets[i], va_image.pitches[i],
@@ -435,6 +429,14 @@ GetChromaVaFourcc(vlc_fourcc_t opaque_chroma, int *va_fourcc,
             *va_fourcc = VA_FOURCC_P012;
             *sw_chroma = VLC_CODEC_P012;
             break;
+        case VLC_CODEC_VAAPI_422_10BPP:
+            *va_fourcc = VA_FOURCC_Y210;
+            *sw_chroma = VLC_CODEC_Y210;
+            break;
+        case VLC_CODEC_VAAPI_422_12BPP:
+            *va_fourcc = VA_FOURCC_Y212;
+            *sw_chroma = VLC_CODEC_Y212;
+            break;
         case VLC_CODEC_VAAPI_444:
             *va_fourcc = VA_FOURCC_XYUV;
             *sw_chroma = VLC_CODEC_VUYX;
@@ -522,6 +524,17 @@ Open(struct vlc_gl_interop *interop)
                 .type = GL_UNSIGNED_SHORT,
             };
             break;
+        case VLC_CODEC_VAAPI_422_10BPP: /* VLC_CODEC_Y210 */
+        case VLC_CODEC_VAAPI_422_12BPP: /* VLC_CODEC_Y212 */
+            interop->tex_count = 1;
+            interop->texs[0] = (struct vlc_gl_tex_cfg) {
+                .w = {1, 2},
+                .h = {1, 1},
+                .internal = GL_RGBA16,
+                .format = GL_RGBA,
+                .type = GL_UNSIGNED_SHORT,
+            };
+            break;
         case VLC_CODEC_VAAPI_444: /* VLC_CODEC_VUYX */
             interop->tex_count = 1;
             interop->texs[0] = (struct vlc_gl_tex_cfg) {
@@ -602,7 +615,7 @@ Open(struct vlc_gl_interop *interop)
     if (tc_va_check_interop_blacklist(interop, priv->vadpy))
         goto error;
 
-    if (tc_va_check_derive_image(interop, vlc_sw_chroma))
+    if (tc_va_check_derive_image(interop))
         goto error;
 
     /* The pictures are uploaded upside-down */


=====================================
modules/video_output/opengl/sampler.c
=====================================
@@ -789,6 +789,9 @@ opengl_fragment_shader_init(struct vlc_gl_sampler *sampler, bool expose_planes)
         chroma == VLC_CODEC_XYZ_12B)
         return xyz12_shader_init(sampler);
 
+    const bool is_y21x_packed = chroma == VLC_CODEC_Y210
+                             || chroma == VLC_CODEC_Y212;
+
     if (is_yuv)
     {
         ret = sampler_yuv_base_init(sampler, desc, yuv_space);
@@ -797,11 +800,14 @@ opengl_fragment_shader_init(struct vlc_gl_sampler *sampler, bool expose_planes)
             msg_Dbg(priv->gl, "opengl sampler: could not initialize YUV shaders for %4.4s", (const char *)&chroma);
             return ret;
         }
-        ret = opengl_init_swizzle(sampler, swizzle_per_tex, desc);
-        if (ret != VLC_SUCCESS)
+        if (!is_y21x_packed)
         {
-            msg_Dbg(priv->gl, "opengl sampler: could not determine swizzle for %4.4s", (const char *)&chroma);
-            return ret;
+            ret = opengl_init_swizzle(sampler, swizzle_per_tex, desc);
+            if (ret != VLC_SUCCESS)
+            {
+                msg_Dbg(priv->gl, "opengl sampler: could not determine swizzle for %4.4s", (const char *)&chroma);
+                return ret;
+            }
         }
     }
 
@@ -932,8 +938,25 @@ opengl_fragment_shader_init(struct vlc_gl_sampler *sampler, bool expose_planes)
     ADD("vec4 vlc_texture(vec2 tex_coords) {\n");
 
     unsigned color_count;
-    if (is_yuv) {
-
+    if (is_y21x_packed)
+    {
+        assert(is_yuv);
+        assert(tex_count == 1);
+        /* Y210/Y212: packed 4:2:2, each 8-byte texel holds 2 pixels:
+         * [Y0:16][U:16][Y1:16][V:16] -> sampled as (R=Y0, G=U, B=Y1, A=V)
+         * A simple swizzle can't select the correct luma, so bypass the
+         * generic path and use texelFetch to pick Y0 or Y1 by pixel parity. */
+        ADD(" ivec2 _ts = textureSize(Textures[0], 0);\n"
+            " int _px = int(tex_coords.x * float(_ts.x) * 2.0);\n"
+            " int _py = int(tex_coords.y * float(_ts.y));\n"
+            " vec4 _t = texelFetch(Textures[0], ivec2(_px >> 1, _py), 0);\n"
+            " float _Y = ((_px & 1) == 0) ? _t.r : _t.b;\n"
+            " vec4 pixel = vec4(_Y, _t.g, _t.a, 1.0);\n"
+            " vec4 result = ConvMatrix * pixel;\n");
+        color_count = 3;
+    }
+    else if (is_yuv)
+    {
         if (priv->unsigned_sampler)
         {
             /* One extra integer -> float step will be needed */


=====================================
src/misc/fourcc.c
=====================================
@@ -401,6 +401,7 @@ static const vlc_chroma_description_t p_list_chroma_description[] = {
     { VLC_CODEC_VUYA,                  PACKED_FMT(YUV444, 4, 32, 8) },
     { VLC_CODEC_VUYX,                  PACKED_FMT(YUV444, 4, 32, 8) },
     { VLC_CODEC_Y210,                  PACKED_FMT(YUV422, 4, 32, 10) },
+    { VLC_CODEC_Y212,                  PACKED_FMT(YUV422, 4, 32, 12) },
     { VLC_CODEC_Y410,                  PACKED_FMT(YUV444, 4, 32, 10) },
     { VLC_CODEC_Y412,                  PACKED_FMT(YUV444, 8, 64, 12) },
     { VLC_CODEC_Y211, VLC_CHROMA_SUBTYPE_YUV211,1, { {{1,4}, {1,1}} }, 4, 32, 8 },
@@ -438,6 +439,8 @@ static const vlc_chroma_description_t p_list_chroma_description[] = {
     { VLC_CODEC_VAAPI_420,             GPU_FMT(YUV420, 8) },
     { VLC_CODEC_VAAPI_420_10BPP,       GPU_FMT(YUV420, 10) },
     { VLC_CODEC_VAAPI_420_12BPP,       GPU_FMT(YUV420, 12) },
+    { VLC_CODEC_VAAPI_422_10BPP,       GPU_FMT(YUV422, 10) },
+    { VLC_CODEC_VAAPI_422_12BPP,       GPU_FMT(YUV422, 12) },
     { VLC_CODEC_VAAPI_444,             GPU_FMT(YUV444, 8) },
     { VLC_CODEC_VAAPI_444_10BPP,       GPU_FMT(YUV444, 10) },
     { VLC_CODEC_VAAPI_444_12BPP,       GPU_FMT(YUV444, 12) },


=====================================
src/misc/fourcc_list.h
=====================================
@@ -913,6 +913,8 @@ static const staticentry_t p_list_video[] = {
 
     B(VLC_CODEC_Y210, "Packed 10-bit YUV 4:2:2"),
         A("Y210"),
+    B(VLC_CODEC_Y212, "Packed 12-bit YUV 4:2:2"),
+        A("Y212"),
     B(VLC_CODEC_VUYA, "Packed YUV 4:4:4, V:U:Y:A"),
         A("VUYA"),
     B(VLC_CODEC_VUYX, "Packed YUV 4:4:4, V:U:Y:X"),
@@ -1260,6 +1262,12 @@ static const staticentry_t p_list_video[] = {
     B(VLC_CODEC_VAAPI_420_12BPP, "4:2:0 12bits VAAPI opaque"),
         A("VAO2"),
 
+    B(VLC_CODEC_VAAPI_422_10BPP, "4:2:2 10bits VAAPI opaque"),
+        A("VA20"),
+
+    B(VLC_CODEC_VAAPI_422_12BPP, "4:2:2 12bits VAAPI opaque"),
+        A("VA22"),
+
     B(VLC_CODEC_VAAPI_444,       "4:4:4 8bits VAAPI opaque"),
         A("VA4P"),
 



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/959712afa971fe2b3fe578bfd42ee32505d5c095...fd0fbaeb77101577d3bc383f7f0282fbb347db31

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/959712afa971fe2b3fe578bfd42ee32505d5c095...fd0fbaeb77101577d3bc383f7f0282fbb347db31
You're receiving this email because of your account on code.videolan.org.




More information about the vlc-commits mailing list