Files
clapper/lib/gst/plugin/importers/gstclappergluploader.c
Rafał Dzięgiel ae531db2b7 plugin: Have a separate mutex lock in GL base class
Make GL base importer class and all its subclasses that access parent props,
use a different mutex lock then the main importer class.

This way main importer class can continue processing buffers without waiting for
GL-based subclasses, as most GL operations (e.g. upload) are time consuming.
2022-05-11 22:00:49 +02:00

233 lines
7.4 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_CLAPPER_GL_BASE_IMPORTER_LOCK (self);
_update_elements_caps_locked (self, caps);
GST_CLAPPER_GL_BASE_IMPORTER_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_CLAPPER_GL_BASE_IMPORTER_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_CLAPPER_GL_BASE_IMPORTER_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_CLAPPER_GL_BASE_IMPORTER_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_CLAPPER_GL_BASE_IMPORTER_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_CLAPPER_GL_BASE_IMPORTER_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 ();
}