From e4d896e90e2dbe82a2476743a00f95ca158dbc73 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Tue, 24 Jun 2025 08:15:11 +0200 Subject: [PATCH] from_lavc_vid_conv: add conv YCbCr 444->VUYA When supported by the display, this eliminates the conversion eg. to Y416 for video display because UYVY or v210 are 4:2:2. But the conversion went over UYVY anyways (there was no conv from Y444 keeping subsampling), eg: `$ uv -t testcard:c=vuya -d gl` was originally: ``` ./src/libavcodec/from_lavc_vid_conv.c: selected conversion from yuv444p to Y416 with UYVY intermediate. ``` now VUYA is selected --- src/libavcodec/from_lavc_vid_conv.c | 28 ++++++++++++++++++++++++++++ src/video_decompress/libavcodec.c | 1 + 2 files changed, 29 insertions(+) diff --git a/src/libavcodec/from_lavc_vid_conv.c b/src/libavcodec/from_lavc_vid_conv.c index 57c2a7ba3..634c4172d 100644 --- a/src/libavcodec/from_lavc_vid_conv.c +++ b/src/libavcodec/from_lavc_vid_conv.c @@ -54,6 +54,7 @@ #include // for alignof #endif #include +#include // for NULL, ptrdiff_t, size_t #include #include "color.h" @@ -1040,6 +1041,31 @@ yuv422p_to_v210(struct av_conv_data d) } } +static void +yuv444p_to_vuya(struct av_conv_data d) +{ + const int width = d.in_frame->width; + const int height = d.in_frame->height; + const AVFrame *in_frame = d.in_frame; + for (ptrdiff_t y = 0; y < height; ++y) { + unsigned char *src_y = (unsigned char *) in_frame->data[0] + + (in_frame->linesize[0] * y); + unsigned char *src_cb = (unsigned char *) in_frame->data[1] + + (in_frame->linesize[1] * y); + unsigned char *src_cr = (unsigned char *) in_frame->data[2] + + (in_frame->linesize[2] * y); + unsigned char *dst = + (unsigned char *) d.dst_buffer + (d.pitch * y); + OPTIMIZED_FOR (int x = 0; x < width; ++x) { + enum { ALPHA = 0xFF }; + *dst++ = *src_cr++; + *dst++ = *src_cb++; + *dst++ = *src_y++; + *dst++ = ALPHA; + } + } +} + static void yuv444p_to_uyvy(struct av_conv_data d) { @@ -2540,6 +2566,7 @@ static const struct av_to_uv_conversion av_to_uv_conversions[] = { {AV_PIX_FMT_YUV422P, RGBA, yuv422p_to_rgb32}, {AV_PIX_FMT_YUV444P, v210, yuv444p_to_v210}, {AV_PIX_FMT_YUV444P, UYVY, yuv444p_to_uyvy}, + {AV_PIX_FMT_YUV444P, VUYA, yuv444p_to_vuya}, {AV_PIX_FMT_YUV444P, RGB, yuv444p_to_rgb24}, {AV_PIX_FMT_YUV444P, RGBA, yuv444p_to_rgb32}, // 8-bit YUV - this should be supposedly full range JPEG but lavd decoder doesn't honor @@ -2554,6 +2581,7 @@ static const struct av_to_uv_conversion av_to_uv_conversions[] = { {AV_PIX_FMT_YUVJ422P, RGB, yuv422p_to_rgb24}, {AV_PIX_FMT_YUVJ422P, RGBA, yuv422p_to_rgb32}, {AV_PIX_FMT_YUVJ444P, v210, yuv444p_to_v210}, + {AV_PIX_FMT_YUVJ444P, VUYA, yuv444p_to_vuya}, {AV_PIX_FMT_YUVJ444P, UYVY, yuv444p_to_uyvy}, {AV_PIX_FMT_YUVJ444P, RGB, yuv444p_to_rgb24}, {AV_PIX_FMT_YUVJ444P, RGBA, yuv444p_to_rgb32}, diff --git a/src/video_decompress/libavcodec.c b/src/video_decompress/libavcodec.c index 1aa2f45bd..cb291554b 100644 --- a/src/video_decompress/libavcodec.c +++ b/src/video_decompress/libavcodec.c @@ -1224,6 +1224,7 @@ static int libavcodec_decompress_get_priority(codec_t compression, struct pixfmt case VIDEO_CODEC_NONE: return VDEC_PRIO_PROBE_LO; // for probe case UYVY: + case VUYA: case RG48: case RGB: case RGBA: