Loading...
Searching...
No Matches
GStreamerLoader.hpp
1#pragma once
2#include <score/tools/DynamicLibrary.hpp>
3
4#include <ossia/detail/dylib_loader.hpp>
5
6#include <cstddef>
7#include <cstdint>
8#include <initializer_list>
9#include <optional>
10#include <string>
11#include <string_view>
12#include <vector>
13
14// Forward declarations of GStreamer types (all opaque)
15extern "C"
16{
17typedef struct _GstElement GstElement;
18typedef struct _GstBus GstBus;
19typedef struct _GstMessage GstMessage;
20typedef struct _GstCaps GstCaps;
21typedef struct _GstStructure GstStructure;
22typedef struct _GstSample GstSample;
23typedef struct _GstBuffer GstBuffer;
24typedef struct _GstPad GstPad;
25typedef struct _GstIterator GstIterator;
26
27// Enums that are passed by value
28typedef enum
29{
30 GST_STATE_VOID_PENDING = 0,
31 GST_STATE_NULL = 1,
32 GST_STATE_READY = 2,
33 GST_STATE_PAUSED = 3,
34 GST_STATE_PLAYING = 4
35} GstState;
36
37typedef enum
38{
39 GST_STATE_CHANGE_FAILURE = 0,
40 GST_STATE_CHANGE_SUCCESS = 1,
41 GST_STATE_CHANGE_ASYNC = 2,
42 GST_STATE_CHANGE_NO_PREROLL = 3
43} GstStateChangeReturn;
44
45typedef enum
46{
47 GST_MESSAGE_UNKNOWN = 0,
48 GST_MESSAGE_EOS = (1 << 0),
49 GST_MESSAGE_ERROR = (1 << 1),
50 GST_MESSAGE_WARNING = (1 << 2),
51 GST_MESSAGE_INFO = (1 << 3),
52 GST_MESSAGE_STATE_CHANGED = (1 << 5),
53} GstMessageType;
54
55typedef enum
56{
57 GST_MAP_READ = (1 << 0),
58 GST_MAP_WRITE = (1 << 1),
59} GstMapFlags;
60
61typedef enum
62{
63 GST_FORMAT_UNDEFINED = 0,
64 GST_FORMAT_DEFAULT = 1,
65 GST_FORMAT_BYTES = 2,
66 GST_FORMAT_TIME = 3,
67} GstFormat;
68
69typedef enum
70{
71 GST_SEEK_FLAG_NONE = 0,
72 GST_SEEK_FLAG_FLUSH = (1 << 0),
73 GST_SEEK_FLAG_ACCURATE = (1 << 1),
74 GST_SEEK_FLAG_KEY_UNIT = (1 << 2),
75} GstSeekFlags;
76
77typedef enum
78{
79 GST_FLOW_OK = 0,
80 GST_FLOW_EOS = -3,
81 GST_FLOW_ERROR = -5,
82} GstFlowReturn;
83
84// GstMapInfo must be fully defined since it's stack-allocated
85typedef struct _GstMapInfo
86{
87 void* memory;
88 GstMapFlags flags;
89 uint8_t* data;
90 size_t size;
91 size_t maxsize;
92 void* user_data[4];
93 void* _gst_reserved[4];
95
96// GstVideoMeta, from gst/video/gstvideometa.h. Read-only and only up to
97// stride[]: the map/unmap callbacks and the GstVideoAlignment that follow are
98// deliberately not declared, so nothing here depends on their layout.
99// GST_VIDEO_MAX_PLANES has been 4 since the API was introduced.
100#define GST_VIDEO_MAX_PLANES 4
101typedef struct _GstVideoMeta
102{
103 // GstMeta meta;
104 int meta_flags;
105 const void* meta_info;
106
107 struct _GstBuffer* buffer;
108 int flags; // GstVideoFrameFlags
109 int format; // GstVideoFormat
110 unsigned int id;
111 unsigned int width;
112 unsigned int height;
113 unsigned int n_planes;
114 size_t offset[GST_VIDEO_MAX_PLANES];
115 int stride[GST_VIDEO_MAX_PLANES];
117
118// GError for error handling
119typedef struct _GError
120{
121 uint32_t domain;
122 int code;
123 char* message;
124} GError;
125
126// gboolean is an int in GLib
127typedef int gboolean;
128typedef uint64_t GstClockTime;
129#define GST_CLOCK_TIME_NONE ((GstClockTime)-1)
130#define GST_SECOND ((GstClockTime)1000000000)
131
132// GType is gsize, which is pointer-sized: eight bytes on the LP64 platforms
133// and on Windows, where unsigned long is four. Getting this wrong shifts every
134// field that follows a GType in the structures below.
135typedef std::size_t GType;
136
137// GLib type constants for gst_caps_new_simple varargs
138// GLib/GObject fundamental type IDs
139#define G_TYPE_BOOLEAN ((GType)5 << 2)
140#define G_TYPE_INT ((GType)6 << 2)
141#define G_TYPE_UINT ((GType)7 << 2)
142#define G_TYPE_LONG ((GType)8 << 2)
143#define G_TYPE_ULONG ((GType)9 << 2)
144#define G_TYPE_INT64 ((GType)10 << 2)
145#define G_TYPE_UINT64 ((GType)11 << 2)
146#define G_TYPE_FLOAT ((GType)14 << 2)
147#define G_TYPE_DOUBLE ((GType)15 << 2)
148#define G_TYPE_STRING ((GType)16 << 2)
149#define G_TYPE_ENUM ((GType)12 << 2)
150#define G_TYPE_FLAGS ((GType)13 << 2)
151
152// GParamSpec: property metadata
153typedef struct _GParamSpec
154{
155 void* g_type_instance; // GTypeInstance
156 const char* name;
157 unsigned int flags; // GParamFlags
158 GType value_type;
159 GType owner_type;
160 // Private fields follow — we only access name, flags, value_type
161 char* _nick;
162 char* _blurb;
163 void* qdata;
164 unsigned int ref_count;
165 unsigned int param_id;
166} GParamSpec;
167
168// Typed GParamSpec subtypes for range access
169typedef struct { GParamSpec parent; int minimum; int maximum; int default_value; } GParamSpecInt;
170typedef struct { GParamSpec parent; unsigned int minimum; unsigned int maximum; unsigned int default_value; } GParamSpecUInt;
171typedef struct { GParamSpec parent; long minimum; long maximum; long default_value; } GParamSpecLong;
172typedef struct { GParamSpec parent; unsigned long minimum; unsigned long maximum; unsigned long default_value; } GParamSpecULong;
173typedef struct { GParamSpec parent; int64_t minimum; int64_t maximum; int64_t default_value; } GParamSpecInt64;
174typedef struct { GParamSpec parent; uint64_t minimum; uint64_t maximum; uint64_t default_value; } GParamSpecUInt64;
175typedef struct { GParamSpec parent; float minimum; float maximum; float default_value; float epsilon; } GParamSpecFloat;
176typedef struct { GParamSpec parent; double minimum; double maximum; double default_value; double epsilon; } GParamSpecDouble;
177
178// GValue: generic value container (must match ABI — 24 bytes on 64-bit)
179typedef struct _GValue
180{
181 GType g_type;
182 union { int v_int; unsigned int v_uint; long v_long; unsigned long v_ulong;
183 int64_t v_int64; uint64_t v_uint64; float v_float; double v_double;
184 void* v_pointer; } data[2];
185} GValue;
186
187// GParamFlags
188#define G_PARAM_READABLE (1 << 0)
189#define G_PARAM_WRITABLE (1 << 1)
190#define G_PARAM_READWRITE (G_PARAM_READABLE | G_PARAM_WRITABLE)
191
192// Function signatures for dlsym
193
194// Core
195gboolean gst_init_check(int* argc, char*** argv, GError** error);
196GstElement* gst_parse_launch(const char* pipeline_description, GError** error);
197GstStateChangeReturn
198gst_element_set_state(GstElement* element, GstState state);
199GstStateChangeReturn gst_element_get_state(
200 GstElement* element, GstState* state, GstState* pending,
201 GstClockTime timeout);
202GstBus* gst_element_get_bus(GstElement* element);
203gboolean gst_element_seek_simple(
204 GstElement* element, GstFormat format, GstSeekFlags seek_flags,
205 int64_t seek_pos);
206GstElement* gst_bin_get_by_name(GstElement* bin, const char* name);
207GstPad* gst_element_get_static_pad(GstElement* element, const char* name);
208char* gst_element_get_name(GstElement* element);
209
210// Pads
211GstPad* gst_pad_get_peer(GstPad* pad);
212GstCaps* gst_pad_get_allowed_caps(GstPad* pad);
213GstElement* gst_pad_get_parent_element(GstPad* pad);
214
215// Caps
216GstCaps* gst_pad_get_current_caps(GstPad* pad);
217GstCaps* gst_caps_new_simple(const char* media_type, const char* fieldname, ...);
218GstCaps* gst_caps_from_string(const char* string);
219void gst_caps_unref(GstCaps* caps);
220GstStructure* gst_caps_get_structure(const GstCaps* caps, unsigned int index);
221const char* gst_structure_get_name(const GstStructure* structure);
222gboolean gst_structure_get_int(
223 const GstStructure* structure, const char* fieldname, int* value);
224const char* gst_structure_get_string(
225 const GstStructure* structure, const char* fieldname);
226
227// Bus/messages
228GstMessage* gst_bus_timed_pop_filtered(
229 GstBus* bus, GstClockTime timeout, GstMessageType types);
230
231// Lifecycle
232void gst_object_unref(void* object);
233void gst_message_unref(GstMessage* msg);
234void gst_mini_object_unref(void* mini_object);
235void g_free(void* mem);
236void g_error_free(GError* error);
237
238// AppSink (input)
239GstSample* gst_app_sink_try_pull_sample(void* appsink, GstClockTime timeout);
240gboolean gst_app_sink_is_eos(void* appsink);
241
242// AppSrc (output)
243GstFlowReturn gst_app_src_push_buffer(void* appsrc, GstBuffer* buffer);
244GstFlowReturn gst_app_src_end_of_stream(void* appsrc);
245void gst_app_src_set_caps(void* appsrc, const GstCaps* caps);
246
247// Sample/Buffer
248GstBuffer* gst_sample_get_buffer(GstSample* sample);
249GstCaps* gst_sample_get_caps(GstSample* sample);
250GstBuffer* gst_buffer_new_allocate(void* allocator, size_t size, void* params);
251GstBuffer* gst_buffer_new_wrapped_full(
252 int flags, void* data, size_t maxsize, size_t offset, size_t size,
253 void* user_data, void (*notify)(void*));
254gboolean gst_buffer_map(GstBuffer* buffer, GstMapInfo* info, GstMapFlags flags);
255void gst_buffer_unmap(GstBuffer* buffer, GstMapInfo* info);
256
257// Video meta (from libgstvideo-1.0): the stride and plane offsets an upstream
258// element actually negotiated, when they are not the default for the caps.
259GstVideoMeta* gst_buffer_get_video_meta(GstBuffer* buffer);
260
261// GObject property introspection (from libgobject-2.0)
262GParamSpec** g_object_class_list_properties(void* oclass, unsigned int* n_properties);
263void* g_type_class_ref(GType type);
264void g_type_class_unref(void* g_class);
265gboolean g_type_is_a(GType type, GType is_a_type); // Check type inheritance
266
267// GObject property access
268void g_object_set(void* object, const char* first_property_name, ...);
269void g_object_get(void* object, const char* first_property_name, ...);
270
271// GValue operations
272void g_value_init(GValue* value, GType g_type);
273void g_value_unset(GValue* value);
274void g_object_get_property(void* object, const char* property_name, GValue* value);
275void g_object_set_property(void* object, const char* property_name, const GValue* value);
276int g_value_get_int(const GValue* value);
277unsigned int g_value_get_uint(const GValue* value);
278float g_value_get_float(const GValue* value);
279double g_value_get_double(const GValue* value);
280gboolean g_value_get_boolean(const GValue* value);
281const char* g_value_get_string(const GValue* value);
282int64_t g_value_get_int64(const GValue* value);
283uint64_t g_value_get_uint64(const GValue* value);
284long g_value_get_long(const GValue* value);
285unsigned long g_value_get_ulong(const GValue* value);
286int g_value_get_enum(const GValue* value);
287void g_value_set_int(GValue* value, int v_int);
288void g_value_set_uint(GValue* value, unsigned int v_uint);
289void g_value_set_float(GValue* value, float v_float);
290void g_value_set_double(GValue* value, double v_double);
291void g_value_set_boolean(GValue* value, gboolean v_boolean);
292void g_value_set_string(GValue* value, const char* v_string);
293void g_value_set_int64(GValue* value, int64_t v_int64);
294void g_value_set_uint64(GValue* value, uint64_t v_uint64);
295void g_value_set_long(GValue* value, long v_long);
296void g_value_set_ulong(GValue* value, unsigned long v_ulong);
297void g_value_set_enum(GValue* value, int v_enum);
298}
299
300namespace Gfx::GStreamer
301{
302
303// Unified dynamic loader for libgstreamer-1.0, libgstapp-1.0, libglib-2.0
305{
306 // Core functions
307 decltype(&::gst_init_check) init_check{};
308 decltype(&::gst_parse_launch) parse_launch{};
309 decltype(&::gst_element_set_state) element_set_state{};
310 decltype(&::gst_element_get_state) element_get_state{};
311 decltype(&::gst_element_get_bus) element_get_bus{};
312 decltype(&::gst_element_seek_simple) element_seek_simple{};
313 decltype(&::gst_bin_get_by_name) bin_get_by_name{};
314 decltype(&::gst_element_get_static_pad) element_get_static_pad{};
315 decltype(&::gst_element_get_name) element_get_name{};
316
317 // Pads
318 decltype(&::gst_pad_get_peer) pad_get_peer{};
319 decltype(&::gst_pad_get_allowed_caps) pad_get_allowed_caps{};
320 decltype(&::gst_pad_get_parent_element) pad_get_parent_element{};
321
322 // Caps
323 decltype(&::gst_pad_get_current_caps) pad_get_current_caps{};
324 decltype(&::gst_caps_new_simple) caps_new_simple{};
325 decltype(&::gst_caps_from_string) caps_from_string{};
326 decltype(&::gst_caps_unref) caps_unref{};
327 decltype(&::gst_caps_get_structure) caps_get_structure{};
328 decltype(&::gst_structure_get_name) structure_get_name{};
329 decltype(&::gst_structure_get_int) structure_get_int{};
330 decltype(&::gst_structure_get_string) structure_get_string{};
331
332 // Bus/messages
333 decltype(&::gst_bus_timed_pop_filtered) bus_timed_pop_filtered{};
334
335 // Lifecycle
336 decltype(&::gst_object_unref) object_unref{};
337 decltype(&::gst_message_unref) message_unref{};
338 decltype(&::gst_mini_object_unref) mini_object_unref{};
339 decltype(&::g_free) g_free{};
340 decltype(&::g_error_free) g_error_free{};
341
342 // AppSink (input)
343 decltype(&::gst_app_sink_try_pull_sample) app_sink_try_pull_sample{};
344 decltype(&::gst_app_sink_is_eos) app_sink_is_eos{};
345
346 // AppSrc (output)
347 decltype(&::gst_app_src_push_buffer) app_src_push_buffer{};
348 decltype(&::gst_app_src_end_of_stream) app_src_end_of_stream{};
349 decltype(&::gst_app_src_set_caps) app_src_set_caps{};
350
351 // Sample/Buffer
352 decltype(&::gst_sample_get_buffer) sample_get_buffer{};
353 decltype(&::gst_sample_get_caps) sample_get_caps{};
354 decltype(&::gst_buffer_new_allocate) buffer_new_allocate{};
355 decltype(&::gst_buffer_new_wrapped_full) buffer_new_wrapped_full{};
356 decltype(&::gst_buffer_map) buffer_map{};
357 decltype(&::gst_buffer_unmap) buffer_unmap{};
358
359 // Optional: absent when libgstvideo-1.0 is not installed. Every use falls
360 // back to the default layout for the caps.
361 decltype(&::gst_buffer_get_video_meta) buffer_get_video_meta{};
362
363 // GObject property introspection (from libgobject-2.0)
364 decltype(&::g_object_class_list_properties) object_class_list_properties{};
365 decltype(&::g_type_class_ref) type_class_ref{};
366 decltype(&::g_type_class_unref) type_class_unref{};
367 decltype(&::g_type_is_a) type_is_a{};
368 decltype(&::g_object_set_property) object_set_property{};
369 decltype(&::g_object_get_property) object_get_property{};
370 decltype(&::g_value_init) value_init{};
371 decltype(&::g_value_unset) value_unset{};
372 decltype(&::g_value_get_int) value_get_int{};
373 decltype(&::g_value_get_uint) value_get_uint{};
374 decltype(&::g_value_get_float) value_get_float{};
375 decltype(&::g_value_get_double) value_get_double{};
376 decltype(&::g_value_get_boolean) value_get_boolean{};
377 decltype(&::g_value_get_string) value_get_string{};
378 decltype(&::g_value_get_int64) value_get_int64{};
379 decltype(&::g_value_get_uint64) value_get_uint64{};
380 decltype(&::g_value_get_long) value_get_long{};
381 decltype(&::g_value_get_ulong) value_get_ulong{};
382 decltype(&::g_value_get_enum) value_get_enum{};
383 decltype(&::g_value_set_int) value_set_int{};
384 decltype(&::g_value_set_uint) value_set_uint{};
385 decltype(&::g_value_set_float) value_set_float{};
386 decltype(&::g_value_set_double) value_set_double{};
387 decltype(&::g_value_set_boolean) value_set_boolean{};
388 decltype(&::g_value_set_string) value_set_string{};
389 decltype(&::g_value_set_int64) value_set_int64{};
390 decltype(&::g_value_set_uint64) value_set_uint64{};
391 decltype(&::g_value_set_long) value_set_long{};
392 decltype(&::g_value_set_ulong) value_set_ulong{};
393 decltype(&::g_value_set_enum) value_set_enum{};
394
395 bool available{};
396
397 static const libgstreamer& instance() noexcept
398 {
399 static const libgstreamer self;
400 return self;
401 }
402
403private:
404#if defined(__APPLE__)
405 // dlopen searches DYLD_FALLBACK_LIBRARY_PATH, which covers neither the
406 // Homebrew nor the MacPorts prefix, so the install roots are named outright.
407 static std::optional<ossia::dylib_loader>
408 load_apple_library(std::initializer_list<std::string_view> sonames)
409 {
410 static constexpr std::string_view prefixes[]{
411 "", "/opt/homebrew/lib/", "/usr/local/lib/", "/opt/local/lib/",
412 "/Library/Frameworks/GStreamer.framework/Versions/1.0/lib/"};
413
414 std::vector<std::string> owned;
415 owned.reserve(sonames.size() * std::size(prefixes));
416 for(auto prefix : prefixes)
417 for(auto soname : sonames)
418 owned.emplace_back(std::string(prefix) + std::string(soname));
419
420 std::vector<std::string_view> names;
421 names.reserve(owned.size());
422 for(auto& candidate : owned)
423 names.emplace_back(candidate);
424 return score::try_load_library(std::move(names));
425 }
426#endif
427
428 static std::optional<ossia::dylib_loader> load_core_library()
429 {
430#if defined(_WIN32)
431 return score::try_load_library({"gstreamer-1.0-0.dll", "libgstreamer-1.0-0.dll"});
432#elif defined(__APPLE__)
433 return load_apple_library({"libgstreamer-1.0.0.dylib", "libgstreamer-1.0.dylib"});
434#else
436 "libgstreamer-1.0.so.0", "libgstreamer-1.0.so"});
437#endif
438 }
439
440 static std::optional<ossia::dylib_loader> load_app_library()
441 {
442#if defined(_WIN32)
443 return score::try_load_library({"gstapp-1.0-0.dll", "libgstapp-1.0-0.dll"});
444#elif defined(__APPLE__)
445 return load_apple_library({"libgstapp-1.0.0.dylib", "libgstapp-1.0.dylib"});
446#else
448 "libgstapp-1.0.so.0", "libgstapp-1.0.so"});
449#endif
450 }
451
452 static std::optional<ossia::dylib_loader> load_video_library()
453 {
454#if defined(_WIN32)
455 return score::try_load_library({"gstvideo-1.0-0.dll", "libgstvideo-1.0-0.dll"});
456#elif defined(__APPLE__)
457 return load_apple_library({"libgstvideo-1.0.0.dylib", "libgstvideo-1.0.dylib"});
458#else
460 "libgstvideo-1.0.so.0", "libgstvideo-1.0.so"});
461#endif
462 }
463
464 static std::optional<ossia::dylib_loader> load_gobject_library()
465 {
466#if defined(_WIN32)
467 return score::try_load_library({"gobject-2.0-0.dll", "libgobject-2.0-0.dll"});
468#elif defined(__APPLE__)
469 return load_apple_library({"libgobject-2.0.0.dylib", "libgobject-2.0.dylib"});
470#else
472 "libgobject-2.0.so.0", "libgobject-2.0.so"});
473#endif
474 }
475
476 static std::optional<ossia::dylib_loader> load_glib_library()
477 {
478#if defined(_WIN32)
479 return score::try_load_library({"glib-2.0-0.dll", "libglib-2.0-0.dll"});
480#elif defined(__APPLE__)
481 return load_apple_library({"libglib-2.0.0.dylib", "libglib-2.0.dylib"});
482#else
484 "libglib-2.0.so.0", "libglib-2.0.so"});
485#endif
486 }
487
488#define GST_LOAD(lib, name) \
489 name = lib->symbol<decltype(&::gst_##name)>("gst_" #name)
490
492 {
493 m_core = load_core_library();
494 m_app = load_app_library();
495 m_gobject = load_gobject_library();
496 m_glib = load_glib_library();
497 m_video = load_video_library();
498
499 // Not installed: available stays false and every entry point bails out
500 if(!m_core || !m_app || !m_gobject || !m_glib)
501 return;
502
503 // Core
504 GST_LOAD(m_core, init_check);
505 GST_LOAD(m_core, parse_launch);
506 GST_LOAD(m_core, element_set_state);
507 GST_LOAD(m_core, element_get_state);
508 GST_LOAD(m_core, element_get_bus);
509 GST_LOAD(m_core, element_seek_simple);
510 GST_LOAD(m_core, bin_get_by_name);
511 GST_LOAD(m_core, element_get_static_pad);
512 GST_LOAD(m_core, element_get_name);
513
514 // Pads
515 GST_LOAD(m_core, pad_get_peer);
516 GST_LOAD(m_core, pad_get_allowed_caps);
517 GST_LOAD(m_core, pad_get_parent_element);
518
519 // Caps
520 GST_LOAD(m_core, pad_get_current_caps);
521 GST_LOAD(m_core, caps_new_simple);
522 GST_LOAD(m_core, caps_from_string);
523 GST_LOAD(m_core, caps_unref);
524 GST_LOAD(m_core, caps_get_structure);
525 GST_LOAD(m_core, structure_get_name);
526 GST_LOAD(m_core, structure_get_int);
527 GST_LOAD(m_core, structure_get_string);
528
529 // Bus
530 GST_LOAD(m_core, bus_timed_pop_filtered);
531
532 // Lifecycle
533 GST_LOAD(m_core, object_unref);
534 GST_LOAD(m_core, message_unref);
535 GST_LOAD(m_core, mini_object_unref);
536 g_free = m_glib->symbol<decltype(&::g_free)>("g_free");
537 g_error_free = m_glib->symbol<decltype(&::g_error_free)>("g_error_free");
538
539 // AppSink
540 GST_LOAD(m_app, app_sink_try_pull_sample);
541 GST_LOAD(m_app, app_sink_is_eos);
542
543 // AppSrc
544 GST_LOAD(m_app, app_src_push_buffer);
545 GST_LOAD(m_app, app_src_end_of_stream);
546 GST_LOAD(m_app, app_src_set_caps);
547
548 // Sample/Buffer
549 GST_LOAD(m_core, sample_get_buffer);
550 GST_LOAD(m_core, sample_get_caps);
551 GST_LOAD(m_core, buffer_new_allocate);
552 GST_LOAD(m_core, buffer_new_wrapped_full);
553 GST_LOAD(m_core, buffer_map);
554 GST_LOAD(m_core, buffer_unmap);
555
556 if(m_video)
557 GST_LOAD(m_video, buffer_get_video_meta);
558
559 // GObject property introspection
560#define GOBJ_LOAD(name) \
561 name = m_gobject->symbol<decltype(&::g_##name)>("g_" #name)
562
563 GOBJ_LOAD(object_class_list_properties);
564 GOBJ_LOAD(type_class_ref);
565 GOBJ_LOAD(type_class_unref);
566 GOBJ_LOAD(type_is_a);
567 GOBJ_LOAD(object_set_property);
568 GOBJ_LOAD(object_get_property);
569 GOBJ_LOAD(value_init);
570 GOBJ_LOAD(value_unset);
571 GOBJ_LOAD(value_get_int);
572 GOBJ_LOAD(value_get_uint);
573 GOBJ_LOAD(value_get_float);
574 GOBJ_LOAD(value_get_double);
575 GOBJ_LOAD(value_get_boolean);
576 GOBJ_LOAD(value_get_string);
577 GOBJ_LOAD(value_get_int64);
578 GOBJ_LOAD(value_get_uint64);
579 GOBJ_LOAD(value_get_long);
580 GOBJ_LOAD(value_get_ulong);
581 GOBJ_LOAD(value_get_enum);
582 GOBJ_LOAD(value_set_int);
583 GOBJ_LOAD(value_set_uint);
584 GOBJ_LOAD(value_set_float);
585 GOBJ_LOAD(value_set_double);
586 GOBJ_LOAD(value_set_boolean);
587 GOBJ_LOAD(value_set_string);
588 GOBJ_LOAD(value_set_int64);
589 GOBJ_LOAD(value_set_uint64);
590 GOBJ_LOAD(value_set_long);
591 GOBJ_LOAD(value_set_ulong);
592 GOBJ_LOAD(value_set_enum);
593
594#undef GOBJ_LOAD
595
596 // Verify critical symbols
597 available = init_check && parse_launch && element_set_state && element_get_state
598 && bin_get_by_name && object_unref && buffer_map && buffer_unmap;
599 }
600
601#undef GST_LOAD
602
603 std::optional<ossia::dylib_loader> m_core;
604 std::optional<ossia::dylib_loader> m_app;
605 std::optional<ossia::dylib_loader> m_gobject;
606 std::optional<ossia::dylib_loader> m_glib;
607 std::optional<ossia::dylib_loader> m_video;
608};
609
610// Call once from any code that needs GStreamer
611inline bool gstreamer_init()
612{
613 static bool initialized = [] {
614 auto& g = libgstreamer::instance();
615 if(!g.available || !g.init_check)
616 return false;
617 GError* err = nullptr;
618 gboolean ok = g.init_check(nullptr, nullptr, &err);
619 if(err)
620 {
621 if(g.g_error_free)
622 g.g_error_free(err);
623 }
624 return ok != 0;
625 }();
626 return initialized;
627}
628
629}
std::optional< ossia::dylib_loader > try_load_library(const char *name) noexcept
dlopen a library, reporting absence instead of throwing.
Definition DynamicLibrary.hpp:22
Definition GStreamerLoader.hpp:120
Definition GStreamerLoader.hpp:154
Definition GStreamerLoader.hpp:180
Definition GStreamerLoader.hpp:86
Definition GStreamerLoader.hpp:102
Definition GStreamerLoader.hpp:176
Definition GStreamerLoader.hpp:175
Definition GStreamerLoader.hpp:173
Definition GStreamerLoader.hpp:169
Definition GStreamerLoader.hpp:171
Definition GStreamerLoader.hpp:174
Definition GStreamerLoader.hpp:170
Definition GStreamerLoader.hpp:172
Definition GStreamerLoader.hpp:305