From 3b1fecc4c8729fc4ef3983bbefa315d9db05f4af Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Thu, 11 Mar 2021 13:07:05 +0100 Subject: [PATCH] Lavc: added conversions for/to 16-bit FF YUV and RG48 AJA for eg. Kona 4 doesn't support 12-bit RGB natively. --- src/libavcodec_common.c | 93 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/src/libavcodec_common.c b/src/libavcodec_common.c index 207342beb..0c1521129 100644 --- a/src/libavcodec_common.c +++ b/src/libavcodec_common.c @@ -851,6 +851,46 @@ static void r12l_to_yuv444p16le(AVFrame * __restrict out_frame, unsigned char * r12l_to_yuv444pXXle(16, out_frame, in_data, width, height); } +/// @brief Converts RG48 to yuv444p 10/12/14 le +static inline void rg48_to_yuv444pXXle(int depth, AVFrame * __restrict out_frame, unsigned char * __restrict in_data, int width, int height) +{ + const int src_linesize = vc_get_linesize(width, RG48); + for(int y = 0; y < height; y++) { + uint16_t *dst_y = (uint16_t *) (out_frame->data[0] + out_frame->linesize[0] * y); + uint16_t *dst_cb = (uint16_t *) (out_frame->data[1] + out_frame->linesize[1] * y); + uint16_t *dst_cr = (uint16_t *) (out_frame->data[2] + out_frame->linesize[2] * y); + uint16_t *src = (uint16_t *) (in_data + y * src_linesize); + OPTIMIZED_FOR(int x = 0; x < width; x++){ + comp_type_t r = *src++; + comp_type_t g = *src++; + comp_type_t b = *src++; + + comp_type_t res_y = (RGB_TO_Y_709_SCALED(r, g, b) >> (COMP_BASE+16-depth)) + (1<<(depth-4)); + comp_type_t res_cb = (RGB_TO_CB_709_SCALED(r, g, b) >> (COMP_BASE+16-depth)) + (1<<(depth-1)); + comp_type_t res_cr = (RGB_TO_CR_709_SCALED(r, g, b) >> (COMP_BASE+16-depth)) + (1<<(depth-1)); + + *dst_y++ = MIN(MAX(res_y, 1<<(depth-4)), 235 * (1<<(depth-8))); + *dst_cb++ = MIN(MAX(res_cb, 1<<(depth-4)), 240 * (1<<(depth-8))); + *dst_cr++ = MIN(MAX(res_cr, 1<<(depth-4)), 240 * (1<<(depth-8))); + } + } +} + +static void rg48_to_yuv444p10le(AVFrame * __restrict out_frame, unsigned char * __restrict in_data, int width, int height) +{ + rg48_to_yuv444pXXle(10, out_frame, in_data, width, height); +} + +static void rg48_to_yuv444p12le(AVFrame * __restrict out_frame, unsigned char * __restrict in_data, int width, int height) +{ + rg48_to_yuv444pXXle(12, out_frame, in_data, width, height); +} + +static void rg48_to_yuv444p16le(AVFrame * __restrict out_frame, unsigned char * __restrict in_data, int width, int height) +{ + rg48_to_yuv444pXXle(16, out_frame, in_data, width, height); +} + static void y216_to_yuv444p16le(AVFrame * __restrict out_frame, unsigned char * __restrict in_data, int width, int height) { const int src_linesize = vc_get_linesize(width, Y216); @@ -1261,6 +1301,52 @@ static void yuv444p16le_to_r12l(char * __restrict dst_buffer, AVFrame * __restri yuv444pXXle_to_r12l(16, dst_buffer, frame, width, height, pitch, rgb_shift); } +static inline void yuv444pXXle_to_rg48(int depth, char * __restrict dst_buffer, AVFrame * __restrict frame, + int width, int height, int pitch, int * __restrict rgb_shift) +{ + UNUSED(rgb_shift); + for (int y = 0; y < height; ++y) { + uint16_t *src_y = (uint16_t *) (frame->data[0] + frame->linesize[0] * y); + uint16_t *src_cb = (uint16_t *) (frame->data[1] + frame->linesize[1] * y); + uint16_t *src_cr = (uint16_t *) (frame->data[2] + frame->linesize[2] * y); + uint16_t *dst = (uint16_t *) (dst_buffer + y * pitch); + + OPTIMIZED_FOR (int x = 0; x < width; ++x) { + comp_type_t y = (y_scale * (*src_y++ - (1<<(depth-4)))); + comp_type_t cr = *src_cr++ - (1<<(depth-1)); + comp_type_t cb = *src_cb++ - (1<<(depth-1)); + + comp_type_t r = YCBCR_TO_R_709_SCALED(y, cb, cr) >> (COMP_BASE-16+depth); + comp_type_t g = YCBCR_TO_G_709_SCALED(y, cb, cr) >> (COMP_BASE-16+depth); + comp_type_t b = YCBCR_TO_B_709_SCALED(y, cb, cr) >> (COMP_BASE-16+depth); + // r g b is now on 16 bit scale + + *dst++ = CLAMP_FULL(r, 16); + *dst++ = CLAMP_FULL(g, 16); + *dst++ = CLAMP_FULL(b, 16); + } + } +} + +static void yuv444p10le_to_rg48(char * __restrict dst_buffer, AVFrame * __restrict frame, + int width, int height, int pitch, int * __restrict rgb_shift) +{ + yuv444pXXle_to_rg48(10, dst_buffer, frame, width, height, pitch, rgb_shift); +} + +static void yuv444p12le_to_rg48(char * __restrict dst_buffer, AVFrame * __restrict frame, + int width, int height, int pitch, int * __restrict rgb_shift) +{ + yuv444pXXle_to_rg48(12, dst_buffer, frame, width, height, pitch, rgb_shift); +} + +static void yuv444p16le_to_rg48(char * __restrict dst_buffer, AVFrame * __restrict frame, + int width, int height, int pitch, int * __restrict rgb_shift) +{ + yuv444pXXle_to_rg48(16, dst_buffer, frame, width, height, pitch, rgb_shift); +} + + static void gbrp10le_to_rgb(char * __restrict dst_buffer, AVFrame * __restrict frame, int width, int height, int pitch, int * __restrict rgb_shift) { @@ -2418,6 +2504,9 @@ const struct uv_to_av_conversion *get_uv_to_av_conversions() { { R12L, AV_PIX_FMT_YUV444P10LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r12l_to_yuv444p10le }, { R12L, AV_PIX_FMT_YUV444P12LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r12l_to_yuv444p12le }, { R12L, AV_PIX_FMT_YUV444P16LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, r12l_to_yuv444p16le }, + { RG48, AV_PIX_FMT_YUV444P10LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, rg48_to_yuv444p10le }, + { RG48, AV_PIX_FMT_YUV444P12LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, rg48_to_yuv444p12le }, + { RG48, AV_PIX_FMT_YUV444P16LE, AVCOL_SPC_BT709, AVCOL_RANGE_MPEG, rg48_to_yuv444p16le }, #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 @@ -2488,6 +2577,7 @@ const struct av_to_uv_conversion *get_av_to_uv_conversions() { {AV_PIX_FMT_YUV444P10LE, RGB, yuv444p10le_to_rgb24, false}, {AV_PIX_FMT_YUV444P10LE, RGBA, yuv444p10le_to_rgb32, false}, {AV_PIX_FMT_YUV444P10LE, R12L, yuv444p10le_to_r12l, false}, + {AV_PIX_FMT_YUV444P10LE, RG48, yuv444p10le_to_rg48, false}, #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 15, 100) // FFMPEG commit c2869b4640f {AV_PIX_FMT_P010LE, v210, p010le_to_v210, true}, {AV_PIX_FMT_P010LE, UYVY, p010le_to_uyvy, true}, @@ -2527,9 +2617,11 @@ const struct av_to_uv_conversion *get_av_to_uv_conversions() { // 12-bit YUV {AV_PIX_FMT_YUV444P12LE, R10k, yuv444p12le_to_r10k, false}, {AV_PIX_FMT_YUV444P12LE, R12L, yuv444p12le_to_r12l, false}, + {AV_PIX_FMT_YUV444P12LE, RG48, yuv444p12le_to_rg48, false}, // 16-bit YUV {AV_PIX_FMT_YUV444P16LE, R10k, yuv444p16le_to_r10k, false}, {AV_PIX_FMT_YUV444P16LE, R12L, yuv444p16le_to_r12l, false}, + {AV_PIX_FMT_YUV444P16LE, RG48, yuv444p16le_to_rg48, false}, {AV_PIX_FMT_YUV444P16LE, UYVY, yuv444p16le_to_uyvy, false}, {AV_PIX_FMT_YUV444P16LE, v210, yuv444p16le_to_v210, false}, // RGB @@ -2610,3 +2702,4 @@ struct SwsContext *getSwsContext(unsigned int SrcW, unsigned int SrcH, enum AVPi } #endif // defined HAVE_SWSCALE +/* vi: set expandtab sw=8: */