From 8bfa2a274cf863ca433e3872d0b668e39b076fcf Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Thu, 19 Jan 2023 15:43:44 +0100 Subject: [PATCH] lavc: added uyvy_to_vuya+v210_to_xv30 possible input codecs of hevc_qsv --- src/hwaccel_videotoolbox.c | 4 +- src/libavcodec/from_lavc_vid_conv.c | 6 +-- src/libavcodec/lavc_common.h | 6 +-- src/libavcodec/to_lavc_vid_conv.c | 60 ++++++++++++++++++++++++++++- 4 files changed, 66 insertions(+), 10 deletions(-) diff --git a/src/hwaccel_videotoolbox.c b/src/hwaccel_videotoolbox.c index 0b910e2f5..e7bf821bc 100644 --- a/src/hwaccel_videotoolbox.c +++ b/src/hwaccel_videotoolbox.c @@ -90,9 +90,9 @@ int videotoolbox_init(struct AVCodecContext *s, return ret; enum AVPixelFormat probe_formats[] = { s->sw_pix_fmt, AV_PIX_FMT_UYVY422, -#ifdef HAVE_P210 +#if HAVE_P210 AV_PIX_FMT_P210LE, -#endif // defined HAVE_P210 +#endif // HAVE_P210 AV_PIX_FMT_AYUV64, }; sort_codecs(s->sw_pix_fmt, sizeof probe_formats / sizeof probe_formats[0] - 1, probe_formats + 1); diff --git a/src/libavcodec/from_lavc_vid_conv.c b/src/libavcodec/from_lavc_vid_conv.c index fe8030a8b..afe937812 100644 --- a/src/libavcodec/from_lavc_vid_conv.c +++ b/src/libavcodec/from_lavc_vid_conv.c @@ -1622,7 +1622,7 @@ static void yuv444p10le_to_rgb32(char * __restrict dst_buffer, AVFrame * __restr yuv444p10le_to_rgb(dst_buffer, in_frame, width, height, pitch, rgb_shift, true); } -#ifdef HAVE_P210 +#if HAVE_P210 static void p210le_to_v210(char * __restrict dst_buffer, AVFrame * __restrict in_frame, int width, int height, int pitch, const int * __restrict rgb_shift) { @@ -1763,7 +1763,7 @@ static void p010le_to_uyvy(char * __restrict dst_buffer, AVFrame * __restrict in } } -#ifdef HAVE_P210 +#if HAVE_P210 static void p210le_to_uyvy(char * __restrict dst_buffer, AVFrame * __restrict in_frame, int width, int height, int pitch, const int * __restrict rgb_shift) { @@ -1921,7 +1921,7 @@ const struct av_to_uv_conversion *get_av_to_uv_conversions() { {AV_PIX_FMT_YUV444P10LE, R12L, yuv444p10le_to_r12l, false}, {AV_PIX_FMT_YUV444P10LE, RG48, yuv444p10le_to_rg48, false}, {AV_PIX_FMT_YUV444P10LE, Y416, yuv444p10le_to_y416, true}, -#ifdef HAVE_P210 +#if HAVE_P210 {AV_PIX_FMT_P210LE, v210, p210le_to_v210, true}, {AV_PIX_FMT_P210LE, UYVY, p210le_to_uyvy, false}, #endif diff --git a/src/libavcodec/lavc_common.h b/src/libavcodec/lavc_common.h index 6325bb3d1..b6fec05c8 100644 --- a/src/libavcodec/lavc_common.h +++ b/src/libavcodec/lavc_common.h @@ -145,9 +145,9 @@ extern "C" { #define AV_PIX_FMT_GBRP12LE PIX_FMT_GBRP12LE #endif -#if LIBAVUTIL_VERSION_INT > AV_VERSION_INT(57, 9, 101) // FFMPEG commit b2cd1fb2ec6 -#define HAVE_P210 1 -#endif +#define HAVE_P210 LIBAVUTIL_VERSION_INT > AV_VERSION_INT(57, 9, 101) // FFMPEG commit b2cd1fb2ec6 +#define HAVE_VUYX LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 34, 100) // FFMPEG commit cc5a5c98604 +#define HAVE_XV30 LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 36, 100) // FFMPEG commit d75c4693fef #if defined FF_API_OLD_CHANNEL_LAYOUT || (LIBAVUTIL_VERSION_MAJOR >= 58) #define AVCODECCTX_CHANNELS(context) (context)->ch_layout.nb_channels diff --git a/src/libavcodec/to_lavc_vid_conv.c b/src/libavcodec/to_lavc_vid_conv.c index 3e386afa1..4b7f8d4da 100644 --- a/src/libavcodec/to_lavc_vid_conv.c +++ b/src/libavcodec/to_lavc_vid_conv.c @@ -140,6 +140,27 @@ static void uyvy_to_yuv422p(AVFrame * __restrict out_frame, const unsigned char } } +static void uyvy_to_vuya(AVFrame * __restrict out_frame, const unsigned char * __restrict src, int width, int height) + ATTRIBUTE(unused); +static void uyvy_to_vuya(AVFrame * __restrict out_frame, const unsigned char * __restrict src, int width, int height) +{ + for(int y = 0; y < (int) height; ++y) { + unsigned char *dst = out_frame->data[0] + out_frame->linesize[0] * y; + + OPTIMIZED_FOR (int x = 0; x < width; x += 2) { + *dst++ = src[2]; + *dst++ = src[0]; + *dst++ = src[1]; + *dst++ = 0xff; + *dst++ = src[2]; + *dst++ = src[0]; + *dst++ = src[3]; + *dst++ = 0xff; + src += 4; + } + } +} + static void uyvy_to_yuv444p(AVFrame * __restrict out_frame, const unsigned char * __restrict src, int width, int height) { for(int y = 0; y < height; ++y) { @@ -434,6 +455,34 @@ static void v210_to_yuv444p16le(AVFrame * __restrict out_frame, const unsigned c } } +static void v210_to_xv30(AVFrame * __restrict out_frame, const unsigned char * __restrict in_data, int width, int height) + ATTRIBUTE(unused); +static void v210_to_xv30(AVFrame * __restrict out_frame, const unsigned char * __restrict in_data, int width, int height) +{ + assert((uintptr_t) in_data % 4 == 0); + assert((uintptr_t) out_frame->linesize[0] % 4 == 0); + + for(int y = 0; y < height; y += 1) { + const uint32_t *src = (const void *) (in_data + y * vc_get_linesize(width, v210)); + uint32_t *dst = (uint32_t *)(void *) (out_frame->data[0] + out_frame->linesize[0] * y); + + OPTIMIZED_FOR (int x = 0; x < width / 6; ++x) { + uint32_t w0 = *src++; + uint32_t w1 = *src++; + uint32_t w2 = *src++; + uint32_t w3 = *src++; + *dst++ = w0; + *dst++ = (w0 & 0xFFF003FFU) | (w1 & 0x3FFU) << 10U; + + *dst++ = (w2 & 0x3FFU) << 20U | (w1 & 0x3FF00000U) >> 10U | (w1 & 0xFFC00U) >> 10U; + *dst++ = (w2 & 0x3FFU) << 20U | (w2 & 0xFFC00U) | (w1 & 0xFFC00U) >> 10U; + + *dst++ = (w3 & 0xFFC00U) << 10U | (w3 & 0x3FFU) << 10U | (w2 & 0x3FF00000U) >> 20; + *dst++ = (w3 & 0xFFC00U) << 10U | (w3 & 0x3FF00000U) >> 10 | (w2 & 0x3FF00000U) >> 20; + } + } +} + static void v210_to_p010le(AVFrame * __restrict out_frame, const unsigned char * __restrict in_data, int width, int height) { assert((uintptr_t) in_data % 4 == 0); @@ -498,7 +547,7 @@ static void v210_to_p010le(AVFrame * __restrict out_frame, const unsigned char * } } -#ifdef HAVE_P210 +#if HAVE_P210 static void v210_to_p210le(AVFrame * __restrict out_frame, const unsigned char * __restrict in_data, int width, int height) { assert((uintptr_t) in_data % 4 == 0); @@ -1141,6 +1190,9 @@ const struct uv_to_av_conversion *get_uv_to_av_conversions() { { v210, AV_PIX_FMT_YUV422P10LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, v210_to_yuv422p10le }, { v210, AV_PIX_FMT_YUV444P10LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, v210_to_yuv444p10le }, { v210, AV_PIX_FMT_YUV444P16LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, v210_to_yuv444p16le }, +#if HAVE_XV30 + { v210, AV_PIX_FMT_XV30, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, v210_to_xv30 }, +#endif { R10k, AV_PIX_FMT_YUV444P10LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r10k_to_yuv444p10le }, { R10k, AV_PIX_FMT_YUV444P12LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r10k_to_yuv444p12le }, { R10k, AV_PIX_FMT_YUV444P16LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r10k_to_yuv444p16le }, @@ -1153,11 +1205,15 @@ const struct uv_to_av_conversion *get_uv_to_av_conversions() { #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 15, 100) // FFMPEG commit c2869b4640f { v210, AV_PIX_FMT_P010LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, v210_to_p010le }, #endif -#ifdef HAVE_P210 +#if HAVE_P210 { v210, AV_PIX_FMT_P210LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, v210_to_p210le }, #endif { UYVY, AV_PIX_FMT_YUV422P, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, uyvy_to_yuv422p }, { UYVY, AV_PIX_FMT_YUVJ422P, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, uyvy_to_yuv422p }, +#if HAVE_VUYX + { UYVY, AV_PIX_FMT_VUYA, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, uyvy_to_vuya }, + { UYVY, AV_PIX_FMT_VUYX, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, uyvy_to_vuya }, +#endif { UYVY, AV_PIX_FMT_YUV420P, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, uyvy_to_yuv420p }, { UYVY, AV_PIX_FMT_YUVJ420P, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, uyvy_to_yuv420p }, { UYVY, AV_PIX_FMT_NV12, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, uyvy_to_nv12 },