add gstreamer plugin

This commit is contained in:
Oleg Shishlyannikov 2025-12-09 16:29:40 +03:00
parent d77253e058
commit 8fe11a0a07
4 changed files with 250 additions and 0 deletions

3
.clang-format Normal file
View File

@ -0,0 +1,3 @@
Language: Cpp
ColumnLimit: 180
IndentPPDirectives: AfterHash

2
.clangd Normal file
View File

@ -0,0 +1,2 @@
CompileFlags:
Add: ['-I/usr/include/gstreamer-1.0', '-I/usr/lib/glib-2.0/include', '-I/usr/include/glib-2.0']

209
clients/gstwestonimagesrc.c Normal file
View File

@ -0,0 +1,209 @@
#include "gstwestonimagesrc.h"
#include "gst/gstinfo.h"
#include <string.h>
GST_DEBUG_CATEGORY_STATIC(gst_westonimagesrc_debug);
#define GST_CAT_DEFAULT gst_westonimagesrc_debug
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS("text/plain; charset=utf-8"));
enum { PROP_0, PROP_FRAMERATE, N_PROPERTIES };
static gboolean gst_westonimagesrc_start(GstBaseSrc *basesrc);
static gboolean gst_westonimagesrc_stop(GstBaseSrc *basesrc);
static GstFlowReturn gst_westonimagesrc_create(GstBaseSrc *basesrc, guint64 offset, guint size, GstBuffer **buf);
static gboolean gst_westonimagesrc_unlock(GstBaseSrc *basesrc);
static gboolean gst_westonimagesrc_unlock_stop(GstBaseSrc *basesrc);
static void gst_westonimagesrc_class_init(GstWestonImageSrcClass *klass);
static void gst_westonimagesrc_init(GstWestonImageSrc *westonimagesrc);
static void gst_westonimagesrc_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
static void gst_westonimagesrc_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
G_DEFINE_TYPE(GstWestonImageSrc, gst_westonimagesrc, GST_TYPE_BASE_SRC);
static void gst_westonimagesrc_class_init(GstWestonImageSrcClass *klass) {
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
GstElementClass *gstelement_class = GST_ELEMENT_CLASS(klass);
GstBaseSrcClass *gstbasesrc_class = GST_BASE_SRC_CLASS(klass);
gobject_class->set_property = gst_westonimagesrc_set_property;
gobject_class->get_property = gst_westonimagesrc_get_property;
gstbasesrc_class->start = GST_DEBUG_FUNCPTR(gst_westonimagesrc_start);
gstbasesrc_class->stop = GST_DEBUG_FUNCPTR(gst_westonimagesrc_stop);
gstbasesrc_class->create = GST_DEBUG_FUNCPTR(gst_westonimagesrc_create);
gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR(gst_westonimagesrc_unlock);
gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR(gst_westonimagesrc_unlock_stop);
// Регистрация свойств
g_object_class_install_property(
gobject_class, PROP_FRAMERATE,
g_param_spec_double("framerate", "Frame rate", "Number of hello world messages per second", 0.f, 24.f, 1.f, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gst_element_class_set_static_metadata(gstelement_class, "WestonImageSrc World Source", "Source", "Generates westonimagesrc world messages", "Your Name <your.email@example.com>");
gst_element_class_add_static_pad_template(gstelement_class, &src_template);
GST_DEBUG_CATEGORY_INIT(gst_westonimagesrc_debug, "westonimagesrc", 0, "WestonImageSrc World Plugin");
}
static void gst_westonimagesrc_init(GstWestonImageSrc *westonimagesrc) {
gst_base_src_set_live(GST_BASE_SRC(westonimagesrc), TRUE);
gst_base_src_set_format(GST_BASE_SRC(westonimagesrc), GST_FORMAT_TIME);
gst_base_src_set_blocksize(GST_BASE_SRC(westonimagesrc), 0);
westonimagesrc->running = FALSE;
westonimagesrc->timeout_id = 0;
westonimagesrc->offset = 0;
westonimagesrc->framerate = 1.f;
g_mutex_init(&westonimagesrc->lock);
g_cond_init(&westonimagesrc->cond);
}
static void gst_westonimagesrc_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) {
GstWestonImageSrc *westonimagesrc = GST_WESTONIMAGESRC(object);
GST_OBJECT_LOCK(westonimagesrc);
switch (prop_id) {
case PROP_FRAMERATE: {
gdouble new_framerate = g_value_get_double(value);
if (new_framerate != westonimagesrc->framerate) {
westonimagesrc->framerate = new_framerate;
g_object_notify(object, "framerate");
}
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
GST_OBJECT_UNLOCK(westonimagesrc);
}
static void gst_westonimagesrc_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) {
GstWestonImageSrc *westonimagesrc = GST_WESTONIMAGESRC(object);
GST_OBJECT_LOCK(westonimagesrc);
switch (prop_id) {
case PROP_FRAMERATE:
g_value_set_double(value, westonimagesrc->framerate);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
GST_OBJECT_UNLOCK(westonimagesrc);
}
static gboolean gst_westonimagesrc_start(GstBaseSrc *basesrc) {
GstWestonImageSrc *westonimagesrc = GST_WESTONIMAGESRC(basesrc);
g_mutex_lock(&westonimagesrc->lock);
westonimagesrc->running = TRUE;
westonimagesrc->offset = 0;
g_mutex_unlock(&westonimagesrc->lock);
GST_DEBUG_OBJECT(westonimagesrc, "started");
return TRUE;
}
static gboolean gst_westonimagesrc_stop(GstBaseSrc *basesrc) {
GstWestonImageSrc *westonimagesrc = GST_WESTONIMAGESRC(basesrc);
g_mutex_lock(&westonimagesrc->lock);
westonimagesrc->running = FALSE;
g_cond_signal(&westonimagesrc->cond);
g_mutex_unlock(&westonimagesrc->lock);
GST_DEBUG_OBJECT(westonimagesrc, "stopped");
return TRUE;
}
static GstFlowReturn gst_westonimagesrc_create(GstBaseSrc *basesrc, guint64 offset, guint size, GstBuffer **buf) {
GstWestonImageSrc *westonimagesrc = GST_WESTONIMAGESRC(basesrc);
GstMapInfo map;
gchar *message;
gint message_len;
GstClockTime timestamp;
GstBuffer *buffer;
g_mutex_lock(&westonimagesrc->lock);
while (westonimagesrc->running) {
GstClockTime wait_until = g_get_monotonic_time() + (1 / westonimagesrc->framerate) * G_TIME_SPAN_SECOND;
if (g_cond_wait_until(&westonimagesrc->cond, &westonimagesrc->lock, wait_until)) {
if (!westonimagesrc->running) {
g_mutex_unlock(&westonimagesrc->lock);
return GST_FLOW_FLUSHING;
}
}
if (!westonimagesrc->running) {
g_mutex_unlock(&westonimagesrc->lock);
return GST_FLOW_FLUSHING;
}
message = g_strdup_printf("westonimagesrc world #%lu\n", (gulong)westonimagesrc->offset);
message_len = strlen(message);
buffer = gst_buffer_new_allocate(NULL, message_len, NULL);
gst_buffer_map(buffer, &map, GST_MAP_WRITE);
memcpy(map.data, message, message_len);
gst_buffer_unmap(buffer, &map);
g_free(message);
timestamp = westonimagesrc->offset * GST_SECOND;
GST_BUFFER_PTS(buffer) = timestamp;
GST_BUFFER_DURATION(buffer) = GST_SECOND;
GST_BUFFER_OFFSET(buffer) = westonimagesrc->offset;
GST_BUFFER_OFFSET_END(buffer) = westonimagesrc->offset + 1;
westonimagesrc->offset++;
*buf = buffer;
g_mutex_unlock(&westonimagesrc->lock);
GST_DEBUG_OBJECT(westonimagesrc, "created buffer %" G_GUINT64_FORMAT, westonimagesrc->offset - 1);
return GST_FLOW_OK;
}
g_mutex_unlock(&westonimagesrc->lock);
return GST_FLOW_FLUSHING;
}
static gboolean gst_westonimagesrc_unlock(GstBaseSrc *basesrc) {
GstWestonImageSrc *westonimagesrc = GST_WESTONIMAGESRC(basesrc);
GST_DEBUG_OBJECT(westonimagesrc, "unlock");
g_mutex_lock(&westonimagesrc->lock);
westonimagesrc->running = FALSE;
g_cond_signal(&westonimagesrc->cond);
g_mutex_unlock(&westonimagesrc->lock);
return TRUE;
}
static gboolean gst_westonimagesrc_unlock_stop(GstBaseSrc *basesrc) {
GstWestonImageSrc *westonimagesrc = GST_WESTONIMAGESRC(basesrc);
GST_DEBUG_OBJECT(westonimagesrc, "unlock stop");
g_mutex_lock(&westonimagesrc->lock);
westonimagesrc->running = TRUE;
g_mutex_unlock(&westonimagesrc->lock);
return TRUE;
}
static gboolean plugin_init(GstPlugin *plugin) { return gst_element_register(plugin, "westonimagesrc", GST_RANK_NONE, GST_TYPE_WESTONIMAGESRC); }
#ifndef PACKAGE
# define PACKAGE "westonimagesrc"
#endif
GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, GST_VERSION_MINOR, westonimagesrc, "WestonImageSrc World source plugin", plugin_init, "1.0", "LGPL", "GStreamer", "http://gstreamer.net/")

View File

@ -0,0 +1,36 @@
#ifndef __GST_WESTONIMAGESRC_H__
#define __GST_WESTONIMAGESRC_H__
#include <gst/base/gstbasesrc.h>
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_WESTONIMAGESRC (gst_westonimagesrc_get_type())
#define GST_WESTONIMAGESRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_WESTONIMAGESRC, GstWestonImageSrc))
#define GST_WESTONIMAGESRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_WESTONIMAGESRC, GstWestonImageSrcClass))
#define GST_IS_WESTONIMAGESRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_WESTONIMAGESRC))
#define GST_IS_WESTONIMAGESRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_WESTONIMAGESRC))
typedef struct _GstWestonImageSrc GstWestonImageSrc;
typedef struct _GstWestonImageSrcClass GstWestonImageSrcClass;
struct _GstWestonImageSrc {
GstBaseSrc element;
GMutex lock;
GCond cond;
gboolean running;
guint timeout_id;
guint64 offset; // Счетчик отправленных сообщений
gdouble framerate;
};
struct _GstWestonImageSrcClass {
GstBaseSrcClass parent_class;
};
GType gst_westonimagesrc_get_type(void);
G_END_DECLS
#endif /* __GST_WESTONIMAGESRC_H__ */