michael@0: /* vim:set ts=2 sw=2 sts=2 et cindent: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "nsDebug.h" michael@0: #include "mozilla/NullPtr.h" michael@0: michael@0: #include "GStreamerLoader.h" michael@0: michael@0: #define LIBGSTREAMER 0 michael@0: #define LIBGSTAPP 1 michael@0: #define LIBGSTVIDEO 2 michael@0: michael@0: #ifdef __OpenBSD__ michael@0: #define LIB_GST_SUFFIX ".so" michael@0: #else michael@0: #define LIB_GST_SUFFIX ".so.0" michael@0: #endif michael@0: michael@0: namespace mozilla { michael@0: michael@0: /* michael@0: * Declare our function pointers using the types from the global gstreamer michael@0: * definitions. michael@0: */ michael@0: #define GST_FUNC(_, func) typeof(::func)* func; michael@0: #define REPLACE_FUNC(func) GST_FUNC(-1, func) michael@0: #include "GStreamerFunctionList.h" michael@0: #undef GST_FUNC michael@0: #undef REPLACE_FUNC michael@0: michael@0: /* michael@0: * Redefinitions of functions that have been defined in the gstreamer headers to michael@0: * stop them calling the gstreamer functions in global scope. michael@0: */ michael@0: GstBuffer * gst_buffer_ref_impl(GstBuffer *buf); michael@0: void gst_buffer_unref_impl(GstBuffer *buf); michael@0: void gst_message_unref_impl(GstMessage *msg); michael@0: void gst_caps_unref_impl(GstCaps *caps); michael@0: michael@0: #if GST_VERSION_MAJOR == 1 michael@0: void gst_sample_unref_impl(GstSample *sample); michael@0: #endif michael@0: michael@0: bool michael@0: load_gstreamer() michael@0: { michael@0: #ifdef __APPLE__ michael@0: return true; michael@0: #endif michael@0: static bool loaded = false; michael@0: michael@0: if (loaded) { michael@0: return true; michael@0: } michael@0: michael@0: void *gstreamerLib = nullptr; michael@0: guint major = 0; michael@0: guint minor = 0; michael@0: guint micro, nano; michael@0: michael@0: typedef typeof(::gst_version) VersionFuncType; michael@0: if (VersionFuncType *versionFunc = (VersionFuncType*)dlsym(RTLD_DEFAULT, "gst_version")) { michael@0: versionFunc(&major, &minor, µ, &nano); michael@0: } michael@0: michael@0: if (major == GST_VERSION_MAJOR && minor == GST_VERSION_MINOR) { michael@0: gstreamerLib = RTLD_DEFAULT; michael@0: } else { michael@0: gstreamerLib = dlopen("libgstreamer-" GST_API_VERSION LIB_GST_SUFFIX, RTLD_NOW | RTLD_LOCAL); michael@0: } michael@0: michael@0: void *handles[3] = { michael@0: gstreamerLib, michael@0: dlopen("libgstapp-" GST_API_VERSION LIB_GST_SUFFIX, RTLD_NOW | RTLD_LOCAL), michael@0: dlopen("libgstvideo-" GST_API_VERSION LIB_GST_SUFFIX, RTLD_NOW | RTLD_LOCAL) michael@0: }; michael@0: michael@0: for (size_t i = 0; i < sizeof(handles) / sizeof(handles[0]); i++) { michael@0: if (!handles[i]) { michael@0: NS_WARNING("Couldn't link gstreamer libraries"); michael@0: goto fail; michael@0: } michael@0: } michael@0: michael@0: #define GST_FUNC(lib, symbol) \ michael@0: if (!(symbol = (typeof(symbol))dlsym(handles[lib], #symbol))) { \ michael@0: NS_WARNING("Couldn't link symbol " #symbol); \ michael@0: goto fail; \ michael@0: } michael@0: #define REPLACE_FUNC(symbol) symbol = symbol##_impl; michael@0: #include "GStreamerFunctionList.h" michael@0: #undef GST_FUNC michael@0: #undef REPLACE_FUNC michael@0: michael@0: loaded = true; michael@0: return true; michael@0: michael@0: fail: michael@0: michael@0: for (size_t i = 0; i < sizeof(handles) / sizeof(handles[0]); i++) { michael@0: if (handles[i] && handles[i] != RTLD_DEFAULT) { michael@0: dlclose(handles[i]); michael@0: } michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: GstBuffer * michael@0: gst_buffer_ref_impl(GstBuffer *buf) michael@0: { michael@0: return (GstBuffer *)gst_mini_object_ref(GST_MINI_OBJECT_CAST(buf)); michael@0: } michael@0: michael@0: void michael@0: gst_buffer_unref_impl(GstBuffer *buf) michael@0: { michael@0: gst_mini_object_unref(GST_MINI_OBJECT_CAST(buf)); michael@0: } michael@0: michael@0: void michael@0: gst_message_unref_impl(GstMessage *msg) michael@0: { michael@0: gst_mini_object_unref(GST_MINI_OBJECT_CAST(msg)); michael@0: } michael@0: michael@0: #if GST_VERSION_MAJOR == 1 michael@0: void michael@0: gst_sample_unref_impl(GstSample *sample) michael@0: { michael@0: gst_mini_object_unref(GST_MINI_OBJECT_CAST(sample)); michael@0: } michael@0: #endif michael@0: michael@0: void michael@0: gst_caps_unref_impl(GstCaps *caps) michael@0: { michael@0: gst_mini_object_unref(GST_MINI_OBJECT_CAST(caps)); michael@0: } michael@0: michael@0: }