From c1adfb2e1a3305e4a96e5335073ed4c24acf25e0 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 24 Sep 2024 18:23:45 +0200 Subject: [PATCH] qt: Added support for RGB16/BGR16 input format to qmlglsink This allows input format to be 16-bit RGB565/BGR565, which is generated by various V4L2 devices. This format can be useful on hardware which is constrained by memory bandwidth. Part-of: --- .../docs/gst_plugins_cache.json | 2 +- .../gst-plugins-good/ext/qt/gstqsgmaterial.cc | 29 ++++++++++++++++--- .../gst-plugins-good/ext/qt/gstqtsink.cc | 2 +- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/subprojects/gst-plugins-good/docs/gst_plugins_cache.json b/subprojects/gst-plugins-good/docs/gst_plugins_cache.json index 4fb78ca246..5eae3ea5ab 100644 --- a/subprojects/gst-plugins-good/docs/gst_plugins_cache.json +++ b/subprojects/gst-plugins-good/docs/gst_plugins_cache.json @@ -12530,7 +12530,7 @@ "long-name": "Qt Video Sink", "pad-templates": { "sink": { - "caps": "video/x-raw(memory:GLMemory):\n format: { RGB, RGBA, BGRA, YV12, NV12 }\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\n framerate: [ 0/1, 2147483647/1 ]\n texture-target: { (string)2D, (string)external-oes }\n", + "caps": "video/x-raw(memory:GLMemory):\n format: { RGB, RGBA, RGB16, BGRA, BGR16, YV12, NV12 }\n width: [ 1, 2147483647 ]\n height: [ 1, 2147483647 ]\n framerate: [ 0/1, 2147483647/1 ]\n texture-target: { (string)2D, (string)external-oes }\n", "direction": "sink", "presence": "always" } diff --git a/subprojects/gst-plugins-good/ext/qt/gstqsgmaterial.cc b/subprojects/gst-plugins-good/ext/qt/gstqsgmaterial.cc index 67e4dc545a..3dfc325a90 100644 --- a/subprojects/gst-plugins-good/ext/qt/gstqsgmaterial.cc +++ b/subprojects/gst-plugins-good/ext/qt/gstqsgmaterial.cc @@ -110,6 +110,8 @@ public: case GST_VIDEO_FORMAT_RGB: case GST_VIDEO_FORMAT_RGBA: case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: tex_names[0] = UNIFORM_TEXTURE0_NAME; break; case GST_VIDEO_FORMAT_YV12: @@ -201,11 +203,13 @@ GstQSGMaterial::new_for_format_and_target(GstVideoFormat format, GstGLTextureTar switch (format) { case GST_VIDEO_FORMAT_RGB: case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_RGB16: if (target == GST_GL_TEXTURE_TARGET_EXTERNAL_OES) return static_cast(new GstQSGMaterial_RGBA_external()); return static_cast(new GstQSGMaterial_RGBA()); case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_BGR16: return static_cast(new GstQSGMaterial_RGBA_SWIZZLE()); case GST_VIDEO_FORMAT_YV12: return static_cast(new GstQSGMaterial_YUV_TRIPLANAR()); @@ -306,7 +310,8 @@ fragmentShaderForFormatAndTarget(GstVideoFormat v_format, GstGLTextureTarget tex switch (v_format) { case GST_VIDEO_FORMAT_RGB: - case GST_VIDEO_FORMAT_RGBA: { + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_RGB16: { char *swizzle = gst_gl_color_convert_swizzle_shader_string (context); char *ret = NULL; @@ -326,7 +331,8 @@ fragmentShaderForFormatAndTarget(GstVideoFormat v_format, GstGLTextureTarget tex g_clear_pointer (&swizzle, g_free); return ret; } - case GST_VIDEO_FORMAT_BGRA: { + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_BGR16: { char *swizzle = gst_gl_color_convert_swizzle_shader_string (context); char *ret = g_strdup_printf ("%s" texcoord_input single_texture_input uniform_swizzle uniform_opacity "%s\n" @@ -564,6 +570,9 @@ out: funcs->glActiveTexture(GL_TEXTURE0 + i); if (this->dummy_textures[i] == 0) { + /* Default GL formats for most supported input formats. */ + guint glformat = GL_RGBA; + guint gltype = GL_UNSIGNED_BYTE; /* Make this a black 64x64 pixel RGBA texture. * This size and format is supported pretty much everywhere, so these * are a safe pick. (64 pixel sidelength must be supported according @@ -584,6 +593,18 @@ out: } } break; + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + /* Override GL formats to support RGB565/BGR565 */ + glformat = GL_RGB; + gltype = GL_UNSIGNED_SHORT_5_6_5; + for (gsize j = 0; j < tex_sidelength; j++) { + for (gsize k = 0; k < tex_sidelength; k++) { + data[(j * tex_sidelength + k) * 2 + 0] = 0xFF; + data[(j * tex_sidelength + k) * 2 + 1] = 0xFF; + } + } + break; case GST_VIDEO_FORMAT_YV12: if (i == 1 || i == 2) { for (gsize j = 0; j < tex_sidelength; j++) { @@ -612,8 +633,8 @@ out: funcs->glBindTexture (GL_TEXTURE_2D, this->dummy_textures[i]); funcs->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); funcs->glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - funcs->glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, tex_sidelength, - tex_sidelength, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + funcs->glTexImage2D (GL_TEXTURE_2D, 0, glformat, tex_sidelength, + tex_sidelength, 0, glformat, gltype, data); } g_assert (this->dummy_textures[i] != 0); diff --git a/subprojects/gst-plugins-good/ext/qt/gstqtsink.cc b/subprojects/gst-plugins-good/ext/qt/gstqtsink.cc index c0e0cd2573..4633729e8c 100644 --- a/subprojects/gst-plugins-good/ext/qt/gstqtsink.cc +++ b/subprojects/gst-plugins-good/ext/qt/gstqtsink.cc @@ -108,7 +108,7 @@ GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("video/x-raw(" GST_CAPS_FEATURE_MEMORY_GL_MEMORY "), " - "format = (string) { RGB, RGBA, BGRA, YV12, NV12 }, " + "format = (string) { RGB, RGBA, RGB16, BGRA, BGR16, YV12, NV12 }, " "width = " GST_VIDEO_SIZE_RANGE ", " "height = " GST_VIDEO_SIZE_RANGE ", " "framerate = " GST_VIDEO_FPS_RANGE ", "