mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-30 07:42:23 +02:00
Add "clappergluploader" module which uses "glupload" and "glcolorconvert" internally, allowing either uploading RAW system memory into GPU with GL colorspace conversion or importing DMABufs into GL memory and making a GdkTexture out of them at one go.
233 lines
7.3 KiB
C
Vendored
233 lines
7.3 KiB
C
Vendored
/*
|
|
* Copyright (C) 2022 Rafał Dzięgiel <rafostar.github@gmail.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "gstclappergluploader.h"
|
|
|
|
#define GST_CAT_DEFAULT gst_clapper_gl_uploader_debug
|
|
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
|
|
|
#define parent_class gst_clapper_gl_uploader_parent_class
|
|
GST_CLAPPER_IMPORTER_DEFINE (GstClapperGLUploader, gst_clapper_gl_uploader, GST_TYPE_CLAPPER_GL_BASE_IMPORTER);
|
|
|
|
static void
|
|
_update_elements_caps_locked (GstClapperGLUploader *self, GstCaps *upload_sink_caps)
|
|
{
|
|
GstClapperGLBaseImporter *gl_bi = GST_CLAPPER_GL_BASE_IMPORTER_CAST (self);
|
|
GstCaps *upload_src_caps, *color_sink_caps, *color_src_caps, *gdk_sink_caps;
|
|
|
|
GST_INFO_OBJECT (self, "Input caps: %" GST_PTR_FORMAT, upload_sink_caps);
|
|
|
|
upload_src_caps = gst_gl_upload_transform_caps (self->upload, gl_bi->gst_context,
|
|
GST_PAD_SINK, upload_sink_caps, NULL);
|
|
upload_src_caps = gst_caps_fixate (upload_src_caps);
|
|
|
|
GST_INFO_OBJECT (self, "GLUpload caps: %" GST_PTR_FORMAT, upload_src_caps);
|
|
gst_gl_upload_set_caps (self->upload, upload_sink_caps, upload_src_caps);
|
|
|
|
gdk_sink_caps = gst_clapper_gl_base_importer_make_supported_gdk_gl_caps ();
|
|
color_sink_caps = gst_gl_color_convert_transform_caps (gl_bi->gst_context,
|
|
GST_PAD_SRC, upload_src_caps, gdk_sink_caps);
|
|
gst_caps_unref (gdk_sink_caps);
|
|
|
|
/* Second caps arg is transfer-full */
|
|
color_src_caps = gst_gl_color_convert_fixate_caps (gl_bi->gst_context,
|
|
GST_PAD_SINK, upload_src_caps, color_sink_caps);
|
|
|
|
GST_INFO_OBJECT (self, "GLColorConvert caps: %" GST_PTR_FORMAT, color_src_caps);
|
|
gst_gl_color_convert_set_caps (self->color_convert, upload_src_caps, color_src_caps);
|
|
|
|
self->has_pending_v_info = gst_video_info_from_caps (&self->pending_v_info, color_src_caps);
|
|
|
|
gst_caps_unref (upload_src_caps);
|
|
gst_caps_unref (color_src_caps);
|
|
}
|
|
|
|
static void
|
|
gst_clapper_gl_uploader_set_caps (GstClapperImporter *importer, GstCaps *caps)
|
|
{
|
|
GstClapperGLUploader *self = GST_CLAPPER_GL_UPLOADER_CAST (importer);
|
|
|
|
GST_OBJECT_LOCK (self);
|
|
_update_elements_caps_locked (self, caps);
|
|
GST_OBJECT_UNLOCK (self);
|
|
}
|
|
|
|
static void
|
|
_uploader_reconfigure_locked (GstClapperGLUploader *self)
|
|
{
|
|
GstCaps *in_caps = NULL;
|
|
|
|
GST_DEBUG_OBJECT (self, "Reconfiguring upload");
|
|
|
|
gst_gl_upload_get_caps (self->upload, &in_caps, NULL);
|
|
|
|
if (G_LIKELY (in_caps)) {
|
|
_update_elements_caps_locked (self, in_caps);
|
|
gst_caps_unref (in_caps);
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
gst_clapper_gl_uploader_prepare (GstClapperImporter *importer)
|
|
{
|
|
gboolean res = GST_CLAPPER_IMPORTER_CLASS (parent_class)->prepare (importer);
|
|
|
|
if (res) {
|
|
GstClapperGLUploader *self = GST_CLAPPER_GL_UPLOADER_CAST (importer);
|
|
GstClapperGLBaseImporter *gl_bi = GST_CLAPPER_GL_BASE_IMPORTER_CAST (importer);
|
|
|
|
GST_OBJECT_LOCK (self);
|
|
|
|
if (!self->upload)
|
|
self->upload = gst_gl_upload_new (gl_bi->gst_context);
|
|
if (!self->color_convert)
|
|
self->color_convert = gst_gl_color_convert_new (gl_bi->gst_context);
|
|
|
|
GST_OBJECT_UNLOCK (self);
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static GstBuffer *
|
|
_upload_perform_locked (GstClapperGLUploader *self, GstBuffer *buffer)
|
|
{
|
|
GstBuffer *upload_buf = NULL;
|
|
GstGLUploadReturn ret;
|
|
|
|
ret = gst_gl_upload_perform_with_buffer (self->upload, buffer, &upload_buf);
|
|
|
|
if (G_UNLIKELY (ret != GST_GL_UPLOAD_DONE)) {
|
|
switch (ret) {
|
|
case GST_GL_UPLOAD_RECONFIGURE:
|
|
_uploader_reconfigure_locked (self);
|
|
/* Retry with the same buffer after reconfiguring */
|
|
return _upload_perform_locked (self, buffer);
|
|
default:
|
|
GST_ERROR_OBJECT (self, "Could not upload input buffer, returned: %i", ret);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return upload_buf;
|
|
}
|
|
|
|
static GdkTexture *
|
|
gst_clapper_gl_uploader_generate_texture (GstClapperImporter *importer,
|
|
GstBuffer *buffer, GstVideoInfo *v_info)
|
|
{
|
|
GstClapperGLUploader *self = GST_CLAPPER_GL_UPLOADER_CAST (importer);
|
|
GstClapperGLBaseImporter *gl_bi = GST_CLAPPER_GL_BASE_IMPORTER_CAST (importer);
|
|
GstBuffer *upload_buf, *color_buf;
|
|
GdkTexture *texture;
|
|
|
|
/* XXX: We both upload and perform color conversion here, thus we skip
|
|
* upload for buffers that are not going to be shown and gain more free
|
|
* CPU time to prepare the next one. Improves performance on weak HW. */
|
|
|
|
GST_LOG_OBJECT (self, "Uploading %" GST_PTR_FORMAT, buffer);
|
|
|
|
GST_OBJECT_LOCK (self);
|
|
|
|
upload_buf = _upload_perform_locked (self, buffer);
|
|
|
|
if (G_UNLIKELY (!upload_buf)) {
|
|
GST_ERROR_OBJECT (self, "Could not perform upload on input buffer");
|
|
GST_OBJECT_UNLOCK (self);
|
|
|
|
return NULL;
|
|
}
|
|
GST_LOG_OBJECT (self, "Uploaded into %" GST_PTR_FORMAT, upload_buf);
|
|
|
|
color_buf = gst_gl_color_convert_perform (self->color_convert, upload_buf);
|
|
gst_buffer_unref (upload_buf);
|
|
|
|
/* Use video info associated with converted buffer */
|
|
if (self->has_pending_v_info) {
|
|
self->v_info = self->pending_v_info;
|
|
self->has_pending_v_info = FALSE;
|
|
}
|
|
|
|
GST_OBJECT_UNLOCK (self);
|
|
|
|
if (G_UNLIKELY (!color_buf)) {
|
|
GST_ERROR_OBJECT (self, "Could not perform color conversion on input buffer");
|
|
return NULL;
|
|
}
|
|
GST_LOG_OBJECT (self, "Color converted into %" GST_PTR_FORMAT, color_buf);
|
|
|
|
texture = gst_clapper_gl_base_importer_make_gl_texture (gl_bi, color_buf, &self->v_info);
|
|
gst_buffer_unref (color_buf);
|
|
|
|
return texture;
|
|
}
|
|
|
|
static void
|
|
gst_clapper_gl_uploader_init (GstClapperGLUploader *self)
|
|
{
|
|
gst_video_info_init (&self->pending_v_info);
|
|
gst_video_info_init (&self->v_info);
|
|
}
|
|
|
|
static void
|
|
gst_clapper_gl_uploader_finalize (GObject *object)
|
|
{
|
|
GstClapperGLUploader *self = GST_CLAPPER_GL_UPLOADER_CAST (object);
|
|
|
|
gst_clear_object (&self->upload);
|
|
gst_clear_object (&self->color_convert);
|
|
|
|
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
|
|
}
|
|
|
|
static void
|
|
gst_clapper_gl_uploader_class_init (GstClapperGLUploaderClass *klass)
|
|
{
|
|
GObjectClass *gobject_class = (GObjectClass *) klass;
|
|
GstClapperImporterClass *importer_class = (GstClapperImporterClass *) klass;
|
|
|
|
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clappergluploader", 0,
|
|
"Clapper GL Uploader");
|
|
|
|
gobject_class->finalize = gst_clapper_gl_uploader_finalize;
|
|
|
|
importer_class->prepare = gst_clapper_gl_uploader_prepare;
|
|
importer_class->set_caps = gst_clapper_gl_uploader_set_caps;
|
|
importer_class->generate_texture = gst_clapper_gl_uploader_generate_texture;
|
|
}
|
|
|
|
GstClapperImporter *
|
|
make_importer (void)
|
|
{
|
|
return g_object_new (GST_TYPE_CLAPPER_GL_UPLOADER, NULL);
|
|
}
|
|
|
|
GstCaps *
|
|
make_caps (GstRank *rank, GStrv *context_types)
|
|
{
|
|
*rank = GST_RANK_MARGINAL + 1;
|
|
*context_types = gst_clapper_gl_base_importer_make_gl_context_types ();
|
|
|
|
return gst_gl_upload_get_input_template_caps ();
|
|
}
|