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