From 64eb4b8d628423c2cbef6bf0c8ff55f061f5628a Mon Sep 17 00:00:00 2001 From: Seungha Yang <seungha@centricular.com> Date: Fri, 19 Nov 2021 21:46:43 +0900 Subject: [PATCH] compositor: Calculate background color only once ... instead of do that per fill_color() call in case of RGB format. Moreover, respect selected GstVideoColorRange Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1486> --- .../gst-plugins-base/gst/compositor/blend.c | 39 +++-------- .../gst/compositor/compositor.c | 66 +++++++++++-------- .../gst/compositor/compositor.h | 5 ++ 3 files changed, 54 insertions(+), 56 deletions(-) diff --git a/subprojects/gst-plugins-base/gst/compositor/blend.c b/subprojects/gst-plugins-base/gst/compositor/blend.c index 72a0de6f16..f350165419 100644 --- a/subprojects/gst-plugins-base/gst/compositor/blend.c +++ b/subprojects/gst-plugins-base/gst/compositor/blend.c @@ -219,15 +219,10 @@ A32_CHECKER_C (bgra, TRUE, 3, 2, 1, 0); A32_CHECKER_C (ayuv, FALSE, 0, 1, 2, 3); A32_CHECKER_C (vuya, FALSE, 3, 2, 1, 0); -#define YUV_TO_R(Y,U,V) (CLAMP (1.164 * (Y - 16) + 1.596 * (V - 128), 0, 255)) -#define YUV_TO_G(Y,U,V) (CLAMP (1.164 * (Y - 16) - 0.813 * (V - 128) - 0.391 * (U - 128), 0, 255)) -#define YUV_TO_B(Y,U,V) (CLAMP (1.164 * (Y - 16) + 2.018 * (U - 128), 0, 255)) - -#define A32_COLOR(name, RGB, A, C1, C2, C3) \ +#define A32_COLOR(name, A, C1, C2, C3) \ static void \ -fill_color_##name (GstVideoFrame * frame, guint y_start, guint y_end, gint Y, gint U, gint V) \ +fill_color_##name (GstVideoFrame * frame, guint y_start, guint y_end, gint c1, gint c2, gint c3) \ { \ - gint c1, c2, c3; \ guint32 val; \ gint stride; \ guint8 *dest; \ @@ -236,26 +231,17 @@ fill_color_##name (GstVideoFrame * frame, guint y_start, guint y_end, gint Y, gi stride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0); \ \ dest += y_start * stride; \ - if (RGB) { \ - c1 = YUV_TO_R (Y, U, V); \ - c2 = YUV_TO_G (Y, U, V); \ - c3 = YUV_TO_B (Y, U, V); \ - } else { \ - c1 = Y; \ - c2 = U; \ - c3 = V; \ - } \ val = GUINT32_FROM_BE ((0xff << A) | (c1 << C1) | (c2 << C2) | (c3 << C3)); \ \ compositor_orc_splat_u32 ((guint32 *) dest, val, (y_end - y_start) * (stride / 4)); \ } -A32_COLOR (argb, TRUE, 24, 16, 8, 0); -A32_COLOR (bgra, TRUE, 0, 8, 16, 24); -A32_COLOR (abgr, TRUE, 24, 0, 8, 16); -A32_COLOR (rgba, TRUE, 0, 24, 16, 8); -A32_COLOR (ayuv, FALSE, 24, 16, 8, 0); -A32_COLOR (vuya, FALSE, 0, 8, 16, 24); +A32_COLOR (argb, 24, 16, 8, 0); +A32_COLOR (bgra, 0, 8, 16, 24); +A32_COLOR (abgr, 24, 0, 8, 16); +A32_COLOR (rgba, 0, 24, 16, 8); +A32_COLOR (ayuv, 24, 16, 8, 0); +A32_COLOR (vuya, 0, 8, 16, 24); /* Y444, Y42B, I420, YV12, Y41B */ #define PLANAR_YUV_BLEND(format_name,format_enum,x_round,y_round,MEMCPY,BLENDLOOP) \ @@ -857,9 +843,8 @@ fill_checker_##name##_c (GstVideoFrame * frame, guint y_start, guint y_end) \ #define RGB_FILL_COLOR(name, bpp, MEMSET_RGB) \ static void \ fill_color_##name (GstVideoFrame * frame, \ - guint y_start, guint y_end, gint colY, gint colU, gint colV) \ + guint y_start, guint y_end, gint colR, gint colG, gint colB) \ { \ - gint red, green, blue; \ gint i; \ gint dest_stride; \ gint width, height; \ @@ -870,13 +855,9 @@ fill_color_##name (GstVideoFrame * frame, \ dest = GST_VIDEO_FRAME_PLANE_DATA (frame, 0); \ dest_stride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0); \ \ - red = YUV_TO_R (colY, colU, colV); \ - green = YUV_TO_G (colY, colU, colV); \ - blue = YUV_TO_B (colY, colU, colV); \ - \ dest += y_start * dest_stride; \ for (i = 0; i < height; i++) { \ - MEMSET_RGB (dest, red, green, blue, width); \ + MEMSET_RGB (dest, colR, colG, colB, width); \ dest += dest_stride; \ } \ } diff --git a/subprojects/gst-plugins-base/gst/compositor/compositor.c b/subprojects/gst-plugins-base/gst/compositor/compositor.c index 7dde46ba02..8d88230e9d 100644 --- a/subprojects/gst-plugins-base/gst/compositor/compositor.c +++ b/subprojects/gst-plugins-base/gst/compositor/compositor.c @@ -800,7 +800,9 @@ GST_ELEMENT_REGISTER_DEFINE (compositor, "compositor", GST_RANK_PRIMARY + 1, static gboolean set_functions (GstCompositor * self, const GstVideoInfo * info) { - gboolean ret = FALSE; + gint offset[GST_VIDEO_MAX_COMPONENTS] = { 0, }; + gint scale[GST_VIDEO_MAX_COMPONENTS] = { 0, }; + gint i; self->blend = NULL; self->overlay = NULL; @@ -813,160 +815,164 @@ set_functions (GstCompositor * self, const GstVideoInfo * info) self->overlay = gst_compositor_overlay_ayuv; self->fill_checker = gst_compositor_fill_checker_ayuv; self->fill_color = gst_compositor_fill_color_ayuv; - ret = TRUE; break; case GST_VIDEO_FORMAT_VUYA: self->blend = gst_compositor_blend_vuya; self->overlay = gst_compositor_overlay_vuya; self->fill_checker = gst_compositor_fill_checker_vuya; self->fill_color = gst_compositor_fill_color_vuya; - ret = TRUE; break; case GST_VIDEO_FORMAT_ARGB: self->blend = gst_compositor_blend_argb; self->overlay = gst_compositor_overlay_argb; self->fill_checker = gst_compositor_fill_checker_argb; self->fill_color = gst_compositor_fill_color_argb; - ret = TRUE; break; case GST_VIDEO_FORMAT_BGRA: self->blend = gst_compositor_blend_bgra; self->overlay = gst_compositor_overlay_bgra; self->fill_checker = gst_compositor_fill_checker_bgra; self->fill_color = gst_compositor_fill_color_bgra; - ret = TRUE; break; case GST_VIDEO_FORMAT_ABGR: self->blend = gst_compositor_blend_abgr; self->overlay = gst_compositor_overlay_abgr; self->fill_checker = gst_compositor_fill_checker_abgr; self->fill_color = gst_compositor_fill_color_abgr; - ret = TRUE; break; case GST_VIDEO_FORMAT_RGBA: self->blend = gst_compositor_blend_rgba; self->overlay = gst_compositor_overlay_rgba; self->fill_checker = gst_compositor_fill_checker_rgba; self->fill_color = gst_compositor_fill_color_rgba; - ret = TRUE; break; case GST_VIDEO_FORMAT_Y444: self->blend = gst_compositor_blend_y444; self->overlay = self->blend; self->fill_checker = gst_compositor_fill_checker_y444; self->fill_color = gst_compositor_fill_color_y444; - ret = TRUE; break; case GST_VIDEO_FORMAT_Y42B: self->blend = gst_compositor_blend_y42b; self->overlay = self->blend; self->fill_checker = gst_compositor_fill_checker_y42b; self->fill_color = gst_compositor_fill_color_y42b; - ret = TRUE; break; case GST_VIDEO_FORMAT_YUY2: self->blend = gst_compositor_blend_yuy2; self->overlay = self->blend; self->fill_checker = gst_compositor_fill_checker_yuy2; self->fill_color = gst_compositor_fill_color_yuy2; - ret = TRUE; break; case GST_VIDEO_FORMAT_UYVY: self->blend = gst_compositor_blend_uyvy; self->overlay = self->blend; self->fill_checker = gst_compositor_fill_checker_uyvy; self->fill_color = gst_compositor_fill_color_uyvy; - ret = TRUE; break; case GST_VIDEO_FORMAT_YVYU: self->blend = gst_compositor_blend_yvyu; self->overlay = self->blend; self->fill_checker = gst_compositor_fill_checker_yvyu; self->fill_color = gst_compositor_fill_color_yvyu; - ret = TRUE; break; case GST_VIDEO_FORMAT_I420: self->blend = gst_compositor_blend_i420; self->overlay = self->blend; self->fill_checker = gst_compositor_fill_checker_i420; self->fill_color = gst_compositor_fill_color_i420; - ret = TRUE; break; case GST_VIDEO_FORMAT_YV12: self->blend = gst_compositor_blend_yv12; self->overlay = self->blend; self->fill_checker = gst_compositor_fill_checker_yv12; self->fill_color = gst_compositor_fill_color_yv12; - ret = TRUE; break; case GST_VIDEO_FORMAT_NV12: self->blend = gst_compositor_blend_nv12; self->overlay = self->blend; self->fill_checker = gst_compositor_fill_checker_nv12; self->fill_color = gst_compositor_fill_color_nv12; - ret = TRUE; break; case GST_VIDEO_FORMAT_NV21: self->blend = gst_compositor_blend_nv21; self->overlay = self->blend; self->fill_checker = gst_compositor_fill_checker_nv21; self->fill_color = gst_compositor_fill_color_nv21; - ret = TRUE; break; case GST_VIDEO_FORMAT_Y41B: self->blend = gst_compositor_blend_y41b; self->overlay = self->blend; self->fill_checker = gst_compositor_fill_checker_y41b; self->fill_color = gst_compositor_fill_color_y41b; - ret = TRUE; break; case GST_VIDEO_FORMAT_RGB: self->blend = gst_compositor_blend_rgb; self->overlay = self->blend; self->fill_checker = gst_compositor_fill_checker_rgb; self->fill_color = gst_compositor_fill_color_rgb; - ret = TRUE; break; case GST_VIDEO_FORMAT_BGR: self->blend = gst_compositor_blend_bgr; self->overlay = self->blend; self->fill_checker = gst_compositor_fill_checker_bgr; self->fill_color = gst_compositor_fill_color_bgr; - ret = TRUE; break; case GST_VIDEO_FORMAT_xRGB: self->blend = gst_compositor_blend_xrgb; self->overlay = self->blend; self->fill_checker = gst_compositor_fill_checker_xrgb; self->fill_color = gst_compositor_fill_color_xrgb; - ret = TRUE; break; case GST_VIDEO_FORMAT_xBGR: self->blend = gst_compositor_blend_xbgr; self->overlay = self->blend; self->fill_checker = gst_compositor_fill_checker_xbgr; self->fill_color = gst_compositor_fill_color_xbgr; - ret = TRUE; break; case GST_VIDEO_FORMAT_RGBx: self->blend = gst_compositor_blend_rgbx; self->overlay = self->blend; self->fill_checker = gst_compositor_fill_checker_rgbx; self->fill_color = gst_compositor_fill_color_rgbx; - ret = TRUE; break; case GST_VIDEO_FORMAT_BGRx: self->blend = gst_compositor_blend_bgrx; self->overlay = self->blend; self->fill_checker = gst_compositor_fill_checker_bgrx; self->fill_color = gst_compositor_fill_color_bgrx; - ret = TRUE; break; default: - break; + GST_ERROR_OBJECT (self, "Unhandled format %s", + gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (info))); + return FALSE; } - return ret; + /* calculate black and white colors */ + gst_video_color_range_offsets (info->colorimetry.range, info->finfo, + offset, scale); + if (GST_VIDEO_INFO_IS_YUV (info)) { + /* black color [0.0, 0.0, 0.0] */ + self->black_color[0] = offset[0]; + + /* white color [1.0, 0.0, 0.0] */ + self->white_color[0] = scale[0] + offset[0]; + + for (i = 1; i < 3; i++) + self->black_color[i] = self->white_color[i] = offset[i]; + } else { + for (i = 0; i < 3; i++) { + self->black_color[i] = offset[i]; + self->white_color[i] = scale[i] + offset[i]; + } + } + + GST_DEBUG_OBJECT (self, + "Calculated background color block: [%d %d %d], white: [%d %d %d]", + self->black_color[0], self->black_color[1], self->black_color[2], + self->white_color[0], self->white_color[1], self->white_color[2]); + + return TRUE; } static GstCaps * @@ -1311,10 +1317,16 @@ _draw_background (GstCompositor * comp, GstVideoFrame * outframe, comp->fill_checker (outframe, y_start, y_end); break; case COMPOSITOR_BACKGROUND_BLACK: - comp->fill_color (outframe, y_start, y_end, 16, 128, 128); + comp->fill_color (outframe, y_start, y_end, + comp->black_color[GST_VIDEO_COMP_Y], + comp->black_color[GST_VIDEO_COMP_U], + comp->black_color[GST_VIDEO_COMP_V]); break; case COMPOSITOR_BACKGROUND_WHITE: - comp->fill_color (outframe, y_start, y_end, 240, 128, 128); + comp->fill_color (outframe, y_start, y_end, + comp->white_color[GST_VIDEO_COMP_Y], + comp->white_color[GST_VIDEO_COMP_U], + comp->white_color[GST_VIDEO_COMP_V]); break; case COMPOSITOR_BACKGROUND_TRANSPARENT: { diff --git a/subprojects/gst-plugins-base/gst/compositor/compositor.h b/subprojects/gst-plugins-base/gst/compositor/compositor.h index 863bb126c4..57f46f9e5c 100644 --- a/subprojects/gst-plugins-base/gst/compositor/compositor.h +++ b/subprojects/gst-plugins-base/gst/compositor/compositor.h @@ -144,6 +144,11 @@ struct _GstCompositor FillCheckerFunction fill_checker; FillColorFunction fill_color; + /* pre-calculated white/black level values, YUV or RGB order depending on + * selected output format */ + gint white_color[GST_VIDEO_MAX_COMPONENTS]; + gint black_color[GST_VIDEO_MAX_COMPONENTS]; + GstParallelizedTaskRunner *blend_runner; };