From fee46dee28abfda49151847dc7e9415e094b70e8 Mon Sep 17 00:00:00 2001 From: Jochen Henneberg Date: Wed, 10 Apr 2024 08:19:01 +0200 Subject: [PATCH] qt6: Added support for NV12 input format to qml6glsink Part-of: --- .../ext/qt6/YUV_BIPLANAR.frag | 36 +++++++++++++++++++ .../gst-plugins-good/ext/qt6/gstqml6glsink.cc | 2 +- .../ext/qt6/gstqsg6material.cc | 20 +++++++++++ .../gst-plugins-good/ext/qt6/meson.build | 1 + .../gst-plugins-good/ext/qt6/resources.qrc | 1 + 5 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 subprojects/gst-plugins-good/ext/qt6/YUV_BIPLANAR.frag diff --git a/subprojects/gst-plugins-good/ext/qt6/YUV_BIPLANAR.frag b/subprojects/gst-plugins-good/ext/qt6/YUV_BIPLANAR.frag new file mode 100644 index 0000000000..226076f710 --- /dev/null +++ b/subprojects/gst-plugins-good/ext/qt6/YUV_BIPLANAR.frag @@ -0,0 +1,36 @@ +#version 440 + +layout(location = 0) in vec2 vTexCoord; + +layout(location = 0) out vec4 fragColor; + +layout(std140, binding = 0) uniform buf { + mat4 qt_Matrix; + ivec4 swizzle; + mat4 color_matrix; + float qt_Opacity; +} ubuf; + +layout(binding = 1) uniform sampler2D Ytex; +layout(binding = 2) uniform sampler2D UVtex; + +vec4 swizzle(in vec4 texel, in ivec4 swizzle) { + return vec4(texel[swizzle[0]], texel[swizzle[1]], texel[swizzle[2]], texel[swizzle[3]]); +} + +vec4 yuva_to_rgba(in vec4 yuva, in mat4 color_matrix) { + return yuva * color_matrix; +} + +void main() +{ + vec4 yuva; + yuva.x = texture(Ytex, vTexCoord).r; + yuva.y = texture(UVtex, vTexCoord).r; + yuva.z = texture(UVtex, vTexCoord).g; + yuva.a = 1.0; + yuva = swizzle(yuva, ubuf.swizzle); + vec4 rgba = yuva_to_rgba (yuva, ubuf.color_matrix); + fragColor = rgba * ubuf.qt_Opacity; +} + diff --git a/subprojects/gst-plugins-good/ext/qt6/gstqml6glsink.cc b/subprojects/gst-plugins-good/ext/qt6/gstqml6glsink.cc index 068d343a33..0057df631f 100644 --- a/subprojects/gst-plugins-good/ext/qt6/gstqml6glsink.cc +++ b/subprojects/gst-plugins-good/ext/qt6/gstqml6glsink.cc @@ -109,7 +109,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) { RGBA, BGRA, RGB, YV12 }, " + "format = (string) { RGBA, BGRA, RGB, YV12, NV12 }, " "width = " GST_VIDEO_SIZE_RANGE ", " "height = " GST_VIDEO_SIZE_RANGE ", " "framerate = " GST_VIDEO_FPS_RANGE ", " diff --git a/subprojects/gst-plugins-good/ext/qt6/gstqsg6material.cc b/subprojects/gst-plugins-good/ext/qt6/gstqsg6material.cc index 34587d69e1..b2aa8823a7 100644 --- a/subprojects/gst-plugins-good/ext/qt6/gstqsg6material.cc +++ b/subprojects/gst-plugins-good/ext/qt6/gstqsg6material.cc @@ -283,6 +283,9 @@ GstQSGMaterialShader::GstQSGMaterialShader(GstVideoFormat v_format) case GST_VIDEO_FORMAT_YV12: setShaderFileName(FragmentStage, ":/org/freedesktop/gstreamer/qml6/YUV_TRIPLANAR.frag.qsb"); break; + case GST_VIDEO_FORMAT_NV12: + setShaderFileName(FragmentStage, ":/org/freedesktop/gstreamer/qml6/YUV_BIPLANAR.frag.qsb"); + break; default: g_assert_not_reached (); } @@ -365,6 +368,7 @@ G_PASTE(GstQSGMaterial_,format)::~G_PASTE(GstQSGMaterial_,format)() {} DEFINE_MATERIAL(RGBA_SWIZZLE); DEFINE_MATERIAL(YUV_TRIPLANAR); +DEFINE_MATERIAL(YUV_BIPLANAR); GstQSGMaterial * GstQSGMaterial::new_for_format(GstVideoFormat format) @@ -378,6 +382,8 @@ GstQSGMaterial::new_for_format(GstVideoFormat format) switch (format) { case GST_VIDEO_FORMAT_YV12: return static_cast(new GstQSGMaterial_YUV_TRIPLANAR()); + case GST_VIDEO_FORMAT_NV12: + return static_cast(new GstQSGMaterial_YUV_BIPLANAR()); default: g_assert_not_reached (); } @@ -513,6 +519,8 @@ video_format_to_rhi_format (GstVideoFormat format, guint plane) return QRhiTexture::RGBA8; case GST_VIDEO_FORMAT_YV12: return QRhiTexture::R8; + case GST_VIDEO_FORMAT_NV12: + return (plane == 0 ? QRhiTexture::R8 : QRhiTexture::RG8); default: g_assert_not_reached (); } @@ -527,6 +535,8 @@ video_format_to_texel_size (GstVideoFormat format, guint plane) return 4; case GST_VIDEO_FORMAT_YV12: return 1; + case GST_VIDEO_FORMAT_NV12: + return (plane == 0 ? 1 : 2); default: g_assert_not_reached (); } @@ -619,6 +629,16 @@ out: } } break; + case GST_VIDEO_FORMAT_NV12: + if (plane == 1) { + for (gsize j = 0; j < tex_sidelength; j++) { + for (gsize k = 0; k < tex_sidelength; k++) { + data[(j * tex_sidelength + k) * ts + 0] = 0x7F; + data[(j * tex_sidelength + k) * ts + 1] = 0x7F; + } + } + } + break; default: g_assert_not_reached (); break; diff --git a/subprojects/gst-plugins-good/ext/qt6/meson.build b/subprojects/gst-plugins-good/ext/qt6/meson.build index 2b1ab1d871..5e2e87b934 100644 --- a/subprojects/gst-plugins-good/ext/qt6/meson.build +++ b/subprojects/gst-plugins-good/ext/qt6/meson.build @@ -21,6 +21,7 @@ moc_headers = [ shader_sources = [ 'vertex.vert', 'RGBA.frag', + 'YUV_BIPLANAR.frag', 'YUV_TRIPLANAR.frag', ] diff --git a/subprojects/gst-plugins-good/ext/qt6/resources.qrc b/subprojects/gst-plugins-good/ext/qt6/resources.qrc index 7a01e20f68..e20f5f809c 100644 --- a/subprojects/gst-plugins-good/ext/qt6/resources.qrc +++ b/subprojects/gst-plugins-good/ext/qt6/resources.qrc @@ -2,6 +2,7 @@ vertex.vert.qsb RGBA.frag.qsb + YUV_BIPLANAR.frag.qsb YUV_TRIPLANAR.frag.qsb