Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qgstvideobuffer.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6#include <private/qvideotexturehelper_p.h>
7#include <qpa/qplatformnativeinterface.h>
8#include <qguiapplication.h>
9#include <QtCore/qloggingcategory.h>
10
11#include <gst/video/video.h>
12#include <gst/video/video-frame.h>
13#include <gst/video/gstvideometa.h>
14#include <gst/pbutils/gstpluginsbaseversion.h>
15
16#include <common/qgstutils_p.h>
17
18#if QT_CONFIG(gstreamer_gl)
19# include <QtGui/rhi/qrhi.h>
20# include <QtGui/qopenglcontext.h>
21# include <QtGui/qopenglfunctions.h>
22# include <QtGui/qopengl.h>
23
24# include <gst/gl/gstglconfig.h>
25# include <gst/gl/gstglmemory.h>
26# include <gst/gl/gstglsyncmeta.h>
27
28# if QT_CONFIG(gstreamer_gl_egl)
29# include <EGL/egl.h>
30# include <EGL/eglext.h>
31# endif
32
33# if QT_CONFIG(gstreamer_gl_egl) && QT_CONFIG(linux_dmabuf)
34# include <gst/allocators/gstdmabuf.h>
35# endif
36#endif
37
39
40Q_STATIC_LOGGING_CATEGORY(qLcGstVideoBuffer, "qt.multimedia.gstreamer.videobuffer");
41
42// keep things building without drm_fourcc.h
43#define fourcc_code(a, b, c, d) ((uint32_t)(a) | ((uint32_t)(b) << 8) |
44 ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
45#define DRM_FORMAT_RGBA8888 fourcc_code('R', 'A', '2', '4') /* [31:0] R:G:B:A 8:8:8:8 little endian */
46#define DRM_FORMAT_BGRA8888 fourcc_code('B', 'A', '2', '4') /* [31:0] B:G:R:A 8:8:8:8 little endian */
47#define DRM_FORMAT_RGB888 fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */
48#define DRM_FORMAT_RG88 fourcc_code('R', 'G', '8', '8') /* [15:0] R:G 8:8 little endian */
49#define DRM_FORMAT_ARGB8888 fourcc_code('A', 'R', '2', '4') /* [31:0] A:R:G:B 8:8:8:8 little endian */
50#define DRM_FORMAT_ABGR8888 fourcc_code('A', 'B', '2', '4') /* [31:0] A:B:G:R 8:8:8:8 little endian */
51#define DRM_FORMAT_BGR888 fourcc_code('B', 'G', '2', '4') /* [23:0] B:G:R little endian */
52#define DRM_FORMAT_GR88 fourcc_code('G', 'R', '8', '8') /* [15:0] G:R 8:8 little endian */
53#define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ') /* [7:0] R */
54#define DRM_FORMAT_R16 fourcc_code('R', '1', '6', ' ') /* [15:0] R little endian */
55#define DRM_FORMAT_RGB565 fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */
56#define DRM_FORMAT_RG1616 fourcc_code('R', 'G', '3', '2') /* [31:0] R:G 16:16 little endian */
57#define DRM_FORMAT_GR1616 fourcc_code('G', 'R', '3', '2') /* [31:0] G:R 16:16 little endian */
58#define DRM_FORMAT_BGRA1010102 fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */
59#define DRM_FORMAT_YUYV fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */
60#define DRM_FORMAT_UYVY fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */
61#define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */
62#define DRM_FORMAT_NV12 fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb plane */
63#define DRM_FORMAT_NV21 fourcc_code('N', 'V', '2', '1') /* 2x2 subsampled Cb:Cr plane */
64#define DRM_FORMAT_P010 fourcc_code('P', '0', '1', '0') /* 2x2 subsampled Cr:Cb plane 10 bits per channel */
65#define DRM_FORMAT_YUV411 fourcc_code('Y', 'U', '1', '1') /* 4x1 subsampled Cb (1) and Cr (2) planes */
66#define DRM_FORMAT_YUV420 fourcc_code('Y', 'U', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */
67#define DRM_FORMAT_YVU420 fourcc_code('Y', 'V', '1', '2') /* 2x2 subsampled Cr (1) and Cb (2) planes */
68#define DRM_FORMAT_YUV422 fourcc_code('Y', 'U', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes */
69#define DRM_FORMAT_YUV444 fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */
70
71QGstVideoBuffer::QGstVideoBuffer(QGstBufferHandle buffer, const GstVideoInfo &info,
72 QGstreamerRelayVideoSink *sink, const QVideoFrameFormat &frameFormat,
73 QGstCaps::MemoryFormat memoryFormat)
77 sink ? sink->rhi() : nullptr),
78 m_memoryFormat(memoryFormat),
82{
83#if QT_CONFIG(gstreamer_gl_egl)
84 if (sink) {
85 eglDisplay = sink->eglDisplay();
86 eglImageTargetTexture2D = sink->eglImageTargetTexture2D();
87 }
88#endif
89 Q_UNUSED(m_memoryFormat);
90 Q_UNUSED(eglDisplay);
91 Q_UNUSED(eglImageTargetTexture2D);
92}
93
94QGstVideoBuffer::~QGstVideoBuffer()
95{
96 Q_ASSERT(m_mode == QVideoFrame::NotMapped);
97}
98
99QAbstractVideoBuffer::MapData QGstVideoBuffer::map(QVideoFrame::MapMode mode)
100{
101 const GstMapFlags flags = GstMapFlags(((mode & QVideoFrame::ReadOnly) ? GST_MAP_READ : 0)
102 | ((mode & QVideoFrame::WriteOnly) ? GST_MAP_WRITE : 0));
103
104 MapData mapData;
105 if (mode == QVideoFrame::NotMapped || m_mode != QVideoFrame::NotMapped)
106 return mapData;
107
108 if (m_videoInfo.finfo->n_planes == 0) { // Encoded
109 if (gst_buffer_map(m_buffer.get(), &m_frame.map[0], flags)) {
110 mapData.planeCount = 1;
111 mapData.bytesPerLine[0] = -1;
112 mapData.dataSize[0] = m_frame.map[0].size;
113 mapData.data[0] = static_cast<uchar *>(m_frame.map[0].data);
114
115 m_mode = mode;
116 }
117 } else if (gst_video_frame_map(&m_frame, &m_videoInfo, m_buffer.get(), flags)) {
118 mapData.planeCount = GST_VIDEO_FRAME_N_PLANES(&m_frame);
119
120 for (guint i = 0; i < GST_VIDEO_FRAME_N_PLANES(&m_frame); ++i) {
121 mapData.bytesPerLine[i] = GST_VIDEO_FRAME_PLANE_STRIDE(&m_frame, i);
122 mapData.data[i] = static_cast<uchar *>(GST_VIDEO_FRAME_PLANE_DATA(&m_frame, i));
123 mapData.dataSize[i] = mapData.bytesPerLine[i]*GST_VIDEO_FRAME_COMP_HEIGHT(&m_frame, i);
124 }
125
126 m_mode = mode;
127 }
128 return mapData;
129}
130
131void QGstVideoBuffer::unmap()
132{
133 if (m_mode != QVideoFrame::NotMapped) {
134 if (m_videoInfo.finfo->n_planes == 0)
135 gst_buffer_unmap(m_buffer.get(), &m_frame.map[0]);
136 else
137 gst_video_frame_unmap(&m_frame);
138 }
139 m_mode = QVideoFrame::NotMapped;
140}
141
142bool QGstVideoBuffer::isDmaBuf() const
143{
144 return m_memoryFormat == QGstCaps::DMABuf;
145}
146
147#if QT_CONFIG(gstreamer_gl_egl) && QT_CONFIG(linux_dmabuf)
148
149static int
150fourccFromVideoInfo(const GstVideoInfo * info, int plane, bool singleEGLImage)
151{
152 GstVideoFormat format = GST_VIDEO_INFO_FORMAT (info);
153#if G_BYTE_ORDER == G_LITTLE_ENDIAN
154 const gint argb_fourcc = DRM_FORMAT_ARGB8888;
155 const gint rgba_fourcc = DRM_FORMAT_ABGR8888;
156 const gint rgb_fourcc = DRM_FORMAT_BGR888;
157 const gint rg_fourcc = DRM_FORMAT_GR88;
158#else
159 const gint argb_fourcc = DRM_FORMAT_BGRA8888;
160 const gint rgba_fourcc = DRM_FORMAT_RGBA8888;
161 const gint rgb_fourcc = DRM_FORMAT_RGB888;
162 const gint rg_fourcc = DRM_FORMAT_RG88;
163#endif
164
165 qCDebug(qLcGstVideoBuffer) << "Getting DRM fourcc for"
166 << gst_video_format_to_string(format)
167 << "plane" << plane;
168
169 switch (format) {
170 case GST_VIDEO_FORMAT_RGB16:
171 case GST_VIDEO_FORMAT_BGR16:
172 return DRM_FORMAT_RGB565;
173
174 case GST_VIDEO_FORMAT_RGB:
175 case GST_VIDEO_FORMAT_BGR:
176 return rgb_fourcc;
177
178 case GST_VIDEO_FORMAT_BGRx:
179 case GST_VIDEO_FORMAT_BGRA:
180 return argb_fourcc;
181
182 case GST_VIDEO_FORMAT_AYUV:
183 if (singleEGLImage) return DRM_FORMAT_AYUV;
184 [[fallthrough]];
185 case GST_VIDEO_FORMAT_RGBx:
186 case GST_VIDEO_FORMAT_RGBA:
187 case GST_VIDEO_FORMAT_ARGB:
188 case GST_VIDEO_FORMAT_xRGB:
189 case GST_VIDEO_FORMAT_ABGR:
190 case GST_VIDEO_FORMAT_xBGR:
191 return rgba_fourcc;
192
193 case GST_VIDEO_FORMAT_GRAY8:
194 return DRM_FORMAT_R8;
195
196 case GST_VIDEO_FORMAT_YUY2:
197 return DRM_FORMAT_YUYV;
198
199 case GST_VIDEO_FORMAT_UYVY:
200 return DRM_FORMAT_UYVY;
201
202 case GST_VIDEO_FORMAT_GRAY16_LE:
203 case GST_VIDEO_FORMAT_GRAY16_BE:
204 if (singleEGLImage) return DRM_FORMAT_R16;
205 return rg_fourcc;
206
207 case GST_VIDEO_FORMAT_NV12:
208 if (singleEGLImage) return DRM_FORMAT_NV12;
209 [[fallthrough]];
210 case GST_VIDEO_FORMAT_NV21:
211 if (singleEGLImage) return DRM_FORMAT_NV21;
212 return plane == 0 ? DRM_FORMAT_R8 : rg_fourcc;
213
214 case GST_VIDEO_FORMAT_I420:
215 if (singleEGLImage) return DRM_FORMAT_YUV420;
216 [[fallthrough]];
217 case GST_VIDEO_FORMAT_YV12:
218 if (singleEGLImage) return DRM_FORMAT_YVU420;
219 [[fallthrough]];
220 case GST_VIDEO_FORMAT_Y41B:
221 if (singleEGLImage) return DRM_FORMAT_YUV411;
222 [[fallthrough]];
223 case GST_VIDEO_FORMAT_Y42B:
224 if (singleEGLImage) return DRM_FORMAT_YUV422;
225 [[fallthrough]];
226 case GST_VIDEO_FORMAT_Y444:
227 if (singleEGLImage) return DRM_FORMAT_YUV444;
228 return DRM_FORMAT_R8;
229
230#if GST_CHECK_PLUGINS_BASE_VERSION(1,16,0)
231 case GST_VIDEO_FORMAT_BGR10A2_LE:
232 return DRM_FORMAT_BGRA1010102;
233#endif
234
235 case GST_VIDEO_FORMAT_P010_10LE:
236 case GST_VIDEO_FORMAT_P010_10BE:
237 if (singleEGLImage) return DRM_FORMAT_P010;
238 return plane == 0 ? DRM_FORMAT_R16 : DRM_FORMAT_RG1616;
239
240 default:
241 qWarning() << "Unsupported format for DMABuf:" << gst_video_format_to_string(format);
242 return -1;
243 }
244}
245#endif
246
247#if QT_CONFIG(gstreamer_gl)
248struct GlTextures
249{
250 uint count = 0;
251 bool owned = false;
252 std::array<guint32, QVideoTextureHelper::TextureDescription::maxPlanes> names{};
253};
254
255class QGstQVideoFrameTextures : public QVideoFrameTextures
256{
257public:
258 QGstQVideoFrameTextures(QRhi *rhi,
259 QSize size,
260 QVideoFrameFormat::PixelFormat format,
261 GlTextures &textures,
262 QGstCaps::MemoryFormat memoryFormat)
263 : m_rhi(rhi)
264 , m_glTextures(textures)
265 {
266 QRhiTexture::Flags textureFlags = {};
267 if (QVideoTextureHelper::forceGlTextureExternalOesIsSet()
268 && m_rhi && rhi->backend() == QRhi::OpenGLES2)
269 textureFlags = {QRhiTexture::ExternalOES};
270
271 bool isDmaBuf = memoryFormat == QGstCaps::DMABuf;
272 auto fallbackPolicy = isDmaBuf
273 ? QVideoTextureHelper::TextureDescription::FallbackPolicy::Disable
274 : QVideoTextureHelper::TextureDescription::FallbackPolicy::Enable;
275
276 auto desc = QVideoTextureHelper::textureDescription(format);
277 for (uint i = 0; i < textures.count; ++i) {
278 // Pass nullptr to rhiPlaneSize to disable fallback in its call to rhiTextureFormat
279 QSize planeSize = desc->rhiPlaneSize(size, i, isDmaBuf ? nullptr : m_rhi);
280 QRhiTexture::Format format = desc->rhiTextureFormat(i, m_rhi, fallbackPolicy);
281 m_textures[i].reset(rhi->newTexture(format, planeSize, 1, textureFlags));
282 m_textures[i]->createFrom({textures.names[i], 0});
283 }
284 }
285
286 ~QGstQVideoFrameTextures() override
287 {
288 m_rhi->makeThreadLocalNativeContextCurrent();
289 auto ctx = QOpenGLContext::currentContext();
290 if (m_glTextures.owned && ctx)
291 ctx->functions()->glDeleteTextures(int(m_glTextures.count), m_glTextures.names.data());
292 }
293
294 QRhiTexture *texture(uint plane) const override
295 {
296 return plane < m_glTextures.count ? m_textures[plane].get() : nullptr;
297 }
298
299private:
300 QRhi *m_rhi = nullptr;
301 GlTextures m_glTextures;
302 std::unique_ptr<QRhiTexture> m_textures[QVideoTextureHelper::TextureDescription::maxPlanes];
303};
304
305static GlTextures mapFromGlTexture(const QGstBufferHandle &bufferHandle, GstVideoFrame &frame,
306 GstVideoInfo &videoInfo)
307{
308 qCDebug(qLcGstVideoBuffer) << "mapFromGlTexture";
309
310 GstBuffer *buffer = bufferHandle.get();
311 auto *mem = GST_GL_BASE_MEMORY_CAST(gst_buffer_peek_memory(buffer, 0));
312 if (!mem)
313 return {};
314
315 if (!gst_video_frame_map(&frame, &videoInfo, buffer, GstMapFlags(GST_MAP_READ|GST_MAP_GL))) {
316 qWarning() << "Could not map GL textures";
317 return {};
318 }
319
320 auto *sync_meta = gst_buffer_get_gl_sync_meta(buffer);
321 GstBuffer *sync_buffer = nullptr;
322 if (!sync_meta) {
323 sync_buffer = gst_buffer_new();
324 sync_meta = gst_buffer_add_gl_sync_meta(mem->context, sync_buffer);
325 }
326 gst_gl_sync_meta_set_sync_point (sync_meta, mem->context);
327 gst_gl_sync_meta_wait (sync_meta, mem->context);
328 if (sync_buffer)
329 gst_buffer_unref(sync_buffer);
330
331 GlTextures textures;
332 textures.count = frame.info.finfo->n_planes;
333
334 for (uint i = 0; i < textures.count; ++i)
335 textures.names[i] = *(guint32 *)frame.data[i];
336
337 gst_video_frame_unmap(&frame);
338
339 return textures;
340}
341
342# if QT_CONFIG(gstreamer_gl_egl) && QT_CONFIG(linux_dmabuf)
343static GlTextures mapFromDmaBuffer(QRhi *rhi, const QGstBufferHandle &bufferHandle,
344 GstVideoFrame &frame, GstVideoInfo &videoInfo,
345 Qt::HANDLE eglDisplay, QFunctionPointer eglImageTargetTexture2D)
346{
347 qCDebug(qLcGstVideoBuffer) << "mapFromDmaBuffer, glGetError returns" << Qt::hex << glGetError()
348 << ", eglGetError() returns" << eglGetError();
349
350 GstBuffer *buffer = bufferHandle.get();
351
352 Q_ASSERT(gst_is_dmabuf_memory(gst_buffer_peek_memory(buffer, 0)));
353 Q_ASSERT(eglDisplay);
354 Q_ASSERT(eglImageTargetTexture2D);
355 Q_ASSERT(QGuiApplication::platformName() == QLatin1String("eglfs"));
356 Q_ASSERT(rhi);
357
358 auto *nativeHandles = static_cast<const QRhiGles2NativeHandles *>(rhi->nativeHandles());
359 auto glContext = nativeHandles->context;
360 if (!glContext) {
361 qWarning() << "no GL context";
362 return {};
363 }
364
365 if (!gst_video_frame_map(&frame, &videoInfo, buffer, GstMapFlags(GST_MAP_READ))) {
366 qWarning() << "gst_video_frame_map failed, couldn't map DMA video frame";
367 return {};
368 }
369
370 constexpr int maxPlanes = 4;
371 const int nPlanes = GST_VIDEO_FRAME_N_PLANES(&frame);
372 const int nMemoryBlocks = gst_buffer_n_memory(buffer);
373 const bool externalOes =
374 QVideoTextureHelper::forceGlTextureExternalOesIsSet();
375 static const bool singleEGLImage =
376 externalOes || qEnvironmentVariableIsSet("QT_GSTREAMER_FORCE_SINGLE_EGLIMAGE");
377
378 qCDebug(qLcGstVideoBuffer) << "nPlanes:" << nPlanes
379 << "nMemoryBlocks:" << nMemoryBlocks
380 << "externalOes:" << externalOes
381 << "singleEGLImage:" << singleEGLImage;
382 Q_ASSERT(nPlanes >= 1
383 && nPlanes <= maxPlanes
384 && (nMemoryBlocks == 1 || nMemoryBlocks == nPlanes));
385
386 GlTextures textures = {};
387 textures.owned = true;
388 textures.count = singleEGLImage ? 1 : nPlanes;
389
390 QOpenGLFunctions functions(glContext);
391 functions.glGenTextures(int(textures.count), textures.names.data());
392 qCDebug(qLcGstVideoBuffer) << "called glGenTextures, glGetError returns"
393 << Qt::hex << glGetError();
394
395 std::array<int, maxPlanes> fds{-1, -1, -1, -1};
396 for (int i = 0; i < nMemoryBlocks && i < maxPlanes; ++i) {
397 fds[i] = gst_dmabuf_memory_get_fd(gst_buffer_peek_memory(buffer, i));
398 }
399 auto fdForPlane = [&](int plane) {
400 if (plane < 0 || plane >= maxPlanes || plane >= nMemoryBlocks)
401 return fds[0];
402 return (fds[plane] >= 0) ? fds[plane] : fds[0];
403 };
404
405 int nEGLImages = singleEGLImage ? 1 : nPlanes;
406 for (int plane = 0; plane < nEGLImages; ++plane) {
407 constexpr int maxAttrCount = 31;
408 std::array<EGLAttrib, maxAttrCount> attr;
409 int i = 0;
410
411 gint width = singleEGLImage ? GST_VIDEO_FRAME_WIDTH(&frame)
412 : GST_VIDEO_FRAME_COMP_WIDTH(&frame, plane);
413 gint height = singleEGLImage ? GST_VIDEO_FRAME_HEIGHT(&frame)
414 : GST_VIDEO_FRAME_COMP_HEIGHT(&frame, plane);
415 attr[i++] = EGL_WIDTH;
416 attr[i++] = width;
417 attr[i++] = EGL_HEIGHT;
418 attr[i++] = height;
419 attr[i++] = EGL_LINUX_DRM_FOURCC_EXT;
420 attr[i++] = fourccFromVideoInfo(&videoInfo, plane, singleEGLImage);
421
422 attr[i++] = EGL_DMA_BUF_PLANE0_FD_EXT;
423 attr[i++] = fdForPlane(plane);
424 attr[i++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
425 attr[i++] = (EGLAttrib)(GST_VIDEO_FRAME_PLANE_OFFSET(&frame, plane));
426 attr[i++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
427 attr[i++] = (EGLAttrib)(GST_VIDEO_FRAME_PLANE_STRIDE(&frame, plane));
428
429 if (singleEGLImage && nPlanes > 1) {
430 attr[i++] = EGL_DMA_BUF_PLANE1_FD_EXT;
431 attr[i++] = fdForPlane(1);
432 attr[i++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
433 attr[i++] = (EGLAttrib)(GST_VIDEO_FRAME_PLANE_OFFSET(&frame, 1));
434 attr[i++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
435 attr[i++] = (EGLAttrib)(GST_VIDEO_FRAME_PLANE_STRIDE(&frame, 1));
436 }
437
438 if (singleEGLImage && nPlanes > 2) {
439 attr[i++] = EGL_DMA_BUF_PLANE2_FD_EXT;
440 attr[i++] = fdForPlane(2);
441 attr[i++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
442 attr[i++] = (EGLAttrib)(GST_VIDEO_FRAME_PLANE_OFFSET(&frame, 2));
443 attr[i++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
444 attr[i++] = (EGLAttrib)(GST_VIDEO_FRAME_PLANE_STRIDE(&frame, 2));
445 }
446
447 if (singleEGLImage && nPlanes > 3) {
448 attr[i++] = EGL_DMA_BUF_PLANE3_FD_EXT;
449 attr[i++] = fdForPlane(3);
450 attr[i++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT;
451 attr[i++] = (EGLAttrib)(GST_VIDEO_FRAME_PLANE_OFFSET(&frame, 3));
452 attr[i++] = EGL_DMA_BUF_PLANE3_PITCH_EXT;
453 attr[i++] = (EGLAttrib)(GST_VIDEO_FRAME_PLANE_STRIDE(&frame, 3));
454 }
455
456 attr[i++] = EGL_NONE;
457 Q_ASSERT(i <= maxAttrCount);
458
459 EGLImage image = eglCreateImage(eglDisplay,
460 EGL_NO_CONTEXT,
461 EGL_LINUX_DMA_BUF_EXT,
462 nullptr,
463 attr.data());
464 if (image == EGL_NO_IMAGE_KHR) {
465 qWarning() << "could not create EGL image for plane" << plane
466 << ", eglError"<< Qt::hex << eglGetError();
467 continue;
468 }
469 qCDebug(qLcGstVideoBuffer) << "called eglCreateImage, glGetError returns"
470 << Qt::hex << glGetError()
471 << ", eglGetError() returns" << eglGetError();
472
473 #ifdef GL_OES_EGL_image_external
474 GLenum target = externalOes ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
475 #else
476 GLenum target = GL_TEXTURE_2D;
477 #endif
478 functions.glBindTexture(target, textures.names[plane]);
479
480 auto EGLImageTargetTexture2D = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglImageTargetTexture2D;
481 EGLImageTargetTexture2D(target, image);
482 qCDebug(qLcGstVideoBuffer) << "called glEGLImageTargetTexture2DOES, glGetError returns"
483 << Qt::hex << glGetError()
484 << ", eglGetError() returns" << eglGetError();
485
486 eglDestroyImage(eglDisplay, image);
487 }
488
489 gst_video_frame_unmap(&frame);
490
491 return textures;
492}
493#endif
494#endif
495
496QVideoFrameTexturesUPtr QGstVideoBuffer::mapTextures(QRhi &rhi, QVideoFrameTexturesUPtr& /*oldTextures*/)
497{
498#if QT_CONFIG(gstreamer_gl)
499# if QT_CONFIG(gstreamer_gl_egl) && QT_CONFIG(linux_dmabuf)
500 static const bool isEglfsQPA = QGuiApplication::platformName() == QLatin1String("eglfs");
501# endif
502 GlTextures textures = {};
503 if (m_memoryFormat == QGstCaps::GLTexture)
504 textures = mapFromGlTexture(m_buffer, m_frame, m_videoInfo);
505
506# if QT_CONFIG(gstreamer_gl_egl) && QT_CONFIG(linux_dmabuf)
507 else if (m_memoryFormat == QGstCaps::DMABuf && eglDisplay && isEglfsQPA)
508 textures = mapFromDmaBuffer(&rhi, m_buffer, m_frame, m_videoInfo, eglDisplay,
509 eglImageTargetTexture2D);
510
511# endif
512 if (textures.count > 0)
513 return std::make_unique<QGstQVideoFrameTextures>(&rhi, QSize{m_videoInfo.width, m_videoInfo.height},
514 m_frameFormat.pixelFormat(), textures, m_memoryFormat);
515#endif
516 return {};
517}
518
519QT_END_NAMESPACE
MemoryFormat
Definition qgst_p.h:343
@ DMABuf
Definition qgst_p.h:343
~QGstVideoBuffer() override
QGstVideoBuffer(QGstBufferHandle buffer, const GstVideoInfo &info, QGstreamerRelayVideoSink *sink, const QVideoFrameFormat &frameFormat, QGstCaps::MemoryFormat format)
bool isDmaBuf() const override
QVideoFrameTexturesUPtr mapTextures(QRhi &, QVideoFrameTexturesUPtr &) override
void unmap() override
Releases the memory mapped by the map() function.
MapData map(QVideoFrame::MapMode mode) override
Maps the planes of a video buffer to memory.
Combined button and popup list for selecting options.
#define fourcc_code(a, b, c, d)