6#include <private/qvideotexturehelper_p.h>
7#include <qpa/qplatformnativeinterface.h>
10#include <gst/video/video.h>
11#include <gst/video/video-frame.h>
12#include <gst/video/gstvideometa.h>
13#include <gst/pbutils/gstpluginsbaseversion.h>
17#if QT_CONFIG(gstreamer_gl)
19#include <QtGui/qopenglcontext.h>
20#include <QtGui/qopenglfunctions.h>
21#include <QtGui/qopengl.h>
23#include <gst/gl/gstglconfig.h>
24#include <gst/gl/gstglmemory.h>
25#include <gst/gl/gstglsyncmeta.h>
26#if QT_CONFIG(linux_dmabuf)
27#include <gst/allocators/gstdmabuf.h>
31#include <EGL/eglext.h>
37#define fourcc_code(a, b, c, d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | \
38 ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
40#define DRM_FORMAT_RGBA8888 fourcc_code('R', 'A', '2', '4')
41#define DRM_FORMAT_RGB888 fourcc_code('R', 'G', '2', '4')
42#define DRM_FORMAT_RG88 fourcc_code('R', 'G', '8', '8')
43#define DRM_FORMAT_ABGR8888 fourcc_code('A', 'B', '2', '4')
44#define DRM_FORMAT_BGR888 fourcc_code('B', 'G', '2', '4')
45#define DRM_FORMAT_GR88 fourcc_code('G', 'R', '8', '8')
46#define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ')
47#define DRM_FORMAT_R16 fourcc_code('R', '1', '6', ' ')
48#define DRM_FORMAT_RGB565 fourcc_code('R', 'G', '1', '6')
49#define DRM_FORMAT_RG1616 fourcc_code('R', 'G', '3', '2')
50#define DRM_FORMAT_GR1616 fourcc_code('G', 'R', '3', '2')
51#define DRM_FORMAT_BGRA1010102 fourcc_code('B', 'A', '3', '0')
59 , m_frameFormat(frameFormat)
64 gst_buffer_ref(m_buffer);
66 eglDisplay =
sink->eglDisplay();
67 eglImageTargetTexture2D =
sink->eglImageTargetTexture2D();
75 gst_buffer_unref(m_buffer);
93 if (m_videoInfo.finfo->n_planes == 0) {
94 if (gst_buffer_map(m_buffer, &m_frame.map[0],
flags)) {
102 }
else if (gst_video_frame_map(&m_frame, &m_videoInfo, m_buffer,
flags)) {
105 for (guint
i = 0;
i < GST_VIDEO_FRAME_N_PLANES(&m_frame); ++
i) {
119 if (m_videoInfo.finfo->n_planes == 0)
120 gst_buffer_unmap(m_buffer, &m_frame.map[0]);
122 gst_video_frame_unmap(&m_frame);
127#if QT_CONFIG(gstreamer_gl) && QT_CONFIG(linux_dmabuf)
129fourccFromVideoInfo(
const GstVideoInfo *
info,
int plane)
131 GstVideoFormat
format = GST_VIDEO_INFO_FORMAT (
info);
132#if G_BYTE_ORDER == G_LITTLE_ENDIAN
142 GST_DEBUG (
"Getting DRM fourcc for %s plane %i",
143 gst_video_format_to_string (
format), plane);
146 case GST_VIDEO_FORMAT_RGB16:
147 case GST_VIDEO_FORMAT_BGR16:
150 case GST_VIDEO_FORMAT_RGB:
151 case GST_VIDEO_FORMAT_BGR:
154 case GST_VIDEO_FORMAT_RGBA:
155 case GST_VIDEO_FORMAT_RGBx:
156 case GST_VIDEO_FORMAT_BGRA:
157 case GST_VIDEO_FORMAT_BGRx:
158 case GST_VIDEO_FORMAT_ARGB:
159 case GST_VIDEO_FORMAT_xRGB:
160 case GST_VIDEO_FORMAT_ABGR:
161 case GST_VIDEO_FORMAT_xBGR:
162 case GST_VIDEO_FORMAT_AYUV:
163#if GST_CHECK_PLUGINS_BASE_VERSION(1,16,0)
164 case GST_VIDEO_FORMAT_VUYA:
168 case GST_VIDEO_FORMAT_GRAY8:
171 case GST_VIDEO_FORMAT_YUY2:
172 case GST_VIDEO_FORMAT_UYVY:
173 case GST_VIDEO_FORMAT_GRAY16_LE:
174 case GST_VIDEO_FORMAT_GRAY16_BE:
177 case GST_VIDEO_FORMAT_NV12:
178 case GST_VIDEO_FORMAT_NV21:
181 case GST_VIDEO_FORMAT_I420:
182 case GST_VIDEO_FORMAT_YV12:
183 case GST_VIDEO_FORMAT_Y41B:
184 case GST_VIDEO_FORMAT_Y42B:
185 case GST_VIDEO_FORMAT_Y444:
188#if GST_CHECK_PLUGINS_BASE_VERSION(1,16,0)
189 case GST_VIDEO_FORMAT_BGR10A2_LE:
196 case GST_VIDEO_FORMAT_P010_10LE:
201 case GST_VIDEO_FORMAT_P010_10BE:
207 GST_ERROR (
"Unsupported format for DMABuf.");
213#if QT_CONFIG(gstreamer_gl)
218 std::array<guint32, QVideoTextureHelper::TextureDescription::maxPlanes>
names;
231 desc->heightForPlane(
size.height(),
int(
i)));
232 m_textures[
i].reset(rhi->
newTexture(
desc->textureFormat[
i], planeSize, 1, {}));
233 m_textures[
i]->createFrom({
textures.names[
i], 0});
237 ~QGstQVideoFrameTextures()
239 m_rhi->makeThreadLocalNativeContextCurrent();
241 if (m_glTextures.owned &&
ctx)
242 ctx->functions()->glDeleteTextures(
int(m_glTextures.count), m_glTextures.names.data());
247 return plane < m_glTextures.count ? m_textures[plane].get() :
nullptr;
251 QRhi *m_rhi =
nullptr;
252 GlTextures m_glTextures;
257static GlTextures mapFromGlTexture(GstBuffer *
buffer, GstVideoFrame &
frame, GstVideoInfo &videoInfo)
259 auto *mem = GST_GL_BASE_MEMORY_CAST(gst_buffer_peek_memory(
buffer, 0));
263 if (!gst_video_frame_map(&
frame, &videoInfo,
buffer, GstMapFlags(GST_MAP_READ|GST_MAP_GL))) {
264 qWarning() <<
"Could not map GL textures";
268 auto *sync_meta = gst_buffer_get_gl_sync_meta(
buffer);
269 GstBuffer *sync_buffer =
nullptr;
271 sync_buffer = gst_buffer_new();
272 sync_meta = gst_buffer_add_gl_sync_meta(mem->context, sync_buffer);
274 gst_gl_sync_meta_set_sync_point (sync_meta, mem->context);
275 gst_gl_sync_meta_wait (sync_meta, mem->context);
277 gst_buffer_unref(sync_buffer);
285 gst_video_frame_unmap(&
frame);
290#if GST_GL_HAVE_PLATFORM_EGL && QT_CONFIG(linux_dmabuf)
291static GlTextures mapFromDmaBuffer(
QRhi *rhi, GstBuffer *
buffer, GstVideoFrame &
frame,
292 GstVideoInfo &videoInfo,
Qt::HANDLE eglDisplay,
293 QFunctionPointer eglImageTargetTexture2D)
295 Q_ASSERT(gst_is_dmabuf_memory(gst_buffer_peek_memory(
buffer, 0)));
300 auto glContext = nativeHandles->context;
306 if (!gst_video_frame_map(&
frame, &videoInfo,
buffer, GstMapFlags(GST_MAP_READ))) {
307 qDebug() <<
"Couldn't map DMA video frame";
327 int planeWidth = GST_VIDEO_FRAME_COMP_WIDTH(&
frame,
i);
328 int planeHeight = GST_VIDEO_FRAME_COMP_HEIGHT(&
frame,
i);
329 auto mem = gst_buffer_peek_memory(
buffer,
i);
330 int fd = gst_dmabuf_memory_get_fd(mem);
337 EGL_WIDTH, planeWidth,
338 EGL_HEIGHT, planeHeight,
339 EGL_LINUX_DRM_FOURCC_EXT, fourccFromVideoInfo(&videoInfo,
i),
340 EGL_DMA_BUF_PLANE0_FD_EXT,
fd,
342 EGL_DMA_BUF_PLANE0_PITCH_EXT,
stride,
345 EGLImage
image = eglCreateImage(eglDisplay,
347 EGL_LINUX_DMA_BUF_EXT,
350 if (
image == EGL_NO_IMAGE_KHR) {
351 qWarning() <<
"could not create EGL image for plane" <<
i <<
Qt::hex << eglGetError();
354 functions.glBindTexture(GL_TEXTURE_2D,
textures.names[
i]);
356 auto EGLImageTargetTexture2D = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglImageTargetTexture2D;
357 EGLImageTargetTexture2D(GL_TEXTURE_2D,
image);
359 eglDestroyImage(eglDisplay,
image);
361 gst_video_frame_unmap(&
frame);
373#if QT_CONFIG(gstreamer_gl)
376 textures = mapFromGlTexture(m_buffer, m_frame, m_videoInfo);
378#if GST_GL_HAVE_PLATFORM_EGL && QT_CONFIG(linux_dmabuf)
380 textures = mapFromDmaBuffer(m_rhi, m_buffer, m_frame, m_videoInfo, eglDisplay, eglImageTargetTexture2D);
384 return std::make_unique<QGstQVideoFrameTextures>(
rhi,
QSize{m_videoInfo.width, m_videoInfo.height},
The QAbstractVideoBuffer class is an abstraction for video data. \inmodule QtMultimedia.
QRhi * rhi() const
Returns the QRhi instance.
virtual std::unique_ptr< QVideoFrameTextures > mapTextures(QRhi *) override
QVideoFrame::MapMode mapMode() const override
QGstVideoBuffer(GstBuffer *buffer, const GstVideoInfo &info, QGstreamerVideoSink *sink, const QVideoFrameFormat &frameFormat, QGstCaps::MemoryFormat format)
void unmap() override
Releases the memory mapped by the map() function.
MapData map(QVideoFrame::MapMode mode) override
Independently maps the planes of a video buffer to memory.
static QOpenGLContext * currentContext()
Returns the last context which called makeCurrent in the current thread, or \nullptr,...
The QOpenGLFunctions class provides cross-platform access to the OpenGL ES 2.0 API.
\variable QRhiGles2InitParams::format
QRhiTexture * newTexture(QRhiTexture::Format format, const QSize &pixelSize, int sampleCount=1, QRhiTexture::Flags flags={})
const QRhiNativeHandles * nativeHandles()
The QVideoFrame class represents a frame of video data.
MapMode
Enumerates how a video buffer's data is mapped to system memory.
Combined button and popup list for selecting options.
const TextureDescription * textureDescription(QVideoFrameFormat::PixelFormat format)
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
#define DRM_FORMAT_BGR888
#define DRM_FORMAT_RGB565
#define DRM_FORMAT_RGB888
#define DRM_FORMAT_ABGR8888
#define DRM_FORMAT_BGRA1010102
#define DRM_FORMAT_GR1616
#define DRM_FORMAT_RGBA8888
#define DRM_FORMAT_RG1616
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint const GLuint GLuint const GLuint * textures
GLenum GLenum GLsizei count
const void GLsizei GLsizei stride
GLenum GLuint GLintptr offset
GLint GLsizei GLsizei GLenum format
GLsizei GLenum GLboolean sink
static QAbstractVideoBuffer::MapData mapData(const camera_frame_nv12_t &frame, unsigned char *baseAddress)
QFileInfo info(fileName)
[8]
static constexpr int maxPlanes