summaryrefslogtreecommitdiff
path: root/gst-libs
diff options
context:
space:
mode:
authorMatthew Waters <matthew@centricular.com>2016-01-11 17:22:26 +1100
committerMatthew Waters <matthew@centricular.com>2016-01-15 12:19:02 +1100
commit2ef124dac6d10439a27a076e17a4273af91cd1f7 (patch)
treefa60b82e12d797358e6f0926b620b37498ba4907 /gst-libs
parentad2f0cf619ce464d3226a890eac818383fb0251a (diff)
downloadgstreamer-plugins-bad-2ef124dac6d10439a27a076e17a4273af91cd1f7.tar.gz
gldebug: implement a delayed debug system
The messages are stored by gst_gl_async_debug_store_log_msg() and output later by a corresponding store(), output() or an unset()/free(). Some wrapper macros are provided to avoid callers explicitly using __FILE__, GST_FUNCTION and __LINE__
Diffstat (limited to 'gst-libs')
-rw-r--r--gst-libs/gst/gl/gstgldebug.c176
-rw-r--r--gst-libs/gst/gl/gstgldebug.h134
2 files changed, 307 insertions, 3 deletions
diff --git a/gst-libs/gst/gl/gstgldebug.c b/gst-libs/gst/gl/gstgldebug.c
index 46833a7fa..e0e8da7e1 100644
--- a/gst-libs/gst/gl/gstgldebug.c
+++ b/gst-libs/gst/gl/gstgldebug.c
@@ -25,7 +25,12 @@
#include "gl.h"
#include "gstgldebug.h"
#include <glib/gprintf.h>
+#include <string.h>
+#define ASYNC_DEBUG_FILLED (1 << 0)
+#define ASYNC_DEBUG_FROZEN (1 << 1)
+
+/* compatibility defines */
#ifndef GL_DEBUG_TYPE_ERROR
#define GL_DEBUG_TYPE_ERROR 0x824C
#endif
@@ -80,10 +85,10 @@
#define GL_DEBUG_SOURCE_OTHER 0x824B
#endif
-#if !defined(GST_DISABLE_GST_DEBUG)
GST_DEBUG_CATEGORY_STATIC (gst_performance);
#define GST_CAT_DEFAULT gst_gl_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+GST_DEBUG_CATEGORY_STATIC (default_debug);
static void
_init_debug (void)
@@ -93,10 +98,85 @@ _init_debug (void)
if (g_once_init_enter (&_init)) {
GST_DEBUG_CATEGORY_GET (gst_performance, "GST_PERFORMANCE");
GST_DEBUG_CATEGORY_INIT (gst_gl_debug, "gldebug", 0, "OpenGL Debugging");
+ GST_DEBUG_CATEGORY_GET (default_debug, "default");
g_once_init_leave (&_init, 1);
}
}
+static void
+_free_async_debug_data (GstGLAsyncDebug * ad)
+{
+ if (ad->debug_msg) {
+ g_free (ad->debug_msg);
+ ad->debug_msg = NULL;
+ if (ad->object)
+ g_object_unref (ad->object);
+ ad->object = NULL;
+ ad->state_flags &= ~ASYNC_DEBUG_FILLED;
+ }
+}
+
+void
+gst_gl_async_debug_init (GstGLAsyncDebug * ad)
+{
+ _init_debug ();
+
+ memset (ad, 0, sizeof (*ad));
+}
+
+void
+gst_gl_async_debug_unset (GstGLAsyncDebug * ad)
+{
+ gst_gl_async_debug_output_log_msg (ad);
+
+ _free_async_debug_data (ad);
+
+ if (ad->notify)
+ ad->notify (ad->user_data);
+}
+
+GstGLAsyncDebug *
+gst_gl_async_debug_new (void)
+{
+ return g_new0 (GstGLAsyncDebug, 1);
+}
+
+void
+gst_gl_async_debug_free (GstGLAsyncDebug * ad)
+{
+ gst_gl_async_debug_unset (ad);
+ g_free (ad);
+}
+
+/**
+ * gst_gl_async_debug_freeze:
+ * @ad: a #GstGLAsyncDebug
+ *
+ * freeze the debug output. While frozen, any call to
+ * gst_gl_async_debug_output_log_msg() will not output any messages but
+ * subsequent calls to gst_gl_async_debug_store_log_msg() will overwrite previous
+ * messages.
+ */
+void
+gst_gl_async_debug_freeze (GstGLAsyncDebug * ad)
+{
+ ad->state_flags |= ASYNC_DEBUG_FROZEN;
+}
+
+/**
+ * gst_gl_async_debug_thaw:
+ * @ad: a #GstGLAsyncDebug
+ *
+ * unfreeze the debug output. See gst_gl_async_debug_freeze() for what freezing means
+ */
+void
+gst_gl_async_debug_thaw (GstGLAsyncDebug * ad)
+{
+ ad->state_flags &= ~ASYNC_DEBUG_FROZEN;
+}
+
+#if !defined(GST_DISABLE_GST_DEBUG)
+
static inline const gchar *
_debug_severity_to_string (GLenum severity)
{
@@ -223,4 +303,98 @@ gst_gl_insert_debug_marker (GstGLContext * context, const gchar * format, ...)
g_free (string);
}
+
+/**
+ * gst_gl_async_debug_store_log_msg_valist:
+ * @ad: the #GstGLAsyncDebug to store the message in
+ * @cat: the #GstDebugCategory to output the message in
+ * @level: the #GstLevel
+ * @file: the file where the debug message originates from
+ * @function: the function where the debug message originates from
+ * @line: the line in @file where the debug message originates from
+ * @object: (allow-none): a #GObject to associate with the debug message
+ * @format: a printf style format string
+ * @varargs: the list of arguments for @format
+ *
+ * Stores a debug message for later output by gst_gl_async_debug_output_log_msg()
+ */
+void
+gst_gl_async_debug_store_log_msg_valist (GstGLAsyncDebug * ad,
+ GstDebugCategory * cat, GstDebugLevel level, const gchar * file,
+ const gchar * function, gint line, GObject * object, const gchar * format,
+ va_list varargs)
+{
+ gst_gl_async_debug_output_log_msg (ad);
+ _free_async_debug_data (ad);
+
+ if (G_UNLIKELY (level <= GST_LEVEL_MAX && level <= _gst_debug_min)) {
+ if (!cat)
+ cat = default_debug;
+
+ ad->cat = cat;
+ ad->level = level;
+ ad->file = file;
+ ad->function = function;
+ ad->line = line;
+ if (object)
+ ad->object = g_object_ref (object);
+ else
+ ad->object = NULL;
+
+ ad->debug_msg = gst_info_strdup_vprintf (format, varargs);
+ ad->state_flags |= ASYNC_DEBUG_FILLED;
+ }
+}
+
+/**
+ * gst_gl_async_debug_output_log_msg:
+ * @ad: the #GstGLAsyncDebug to store the message in
+ *
+ * Outputs a previously stored debug message.
+ */
+void
+gst_gl_async_debug_output_log_msg (GstGLAsyncDebug * ad)
+{
+ if ((ad->state_flags & ASYNC_DEBUG_FILLED) != 0
+ && (ad->state_flags & ASYNC_DEBUG_FROZEN) == 0) {
+ gchar *msg = NULL;
+
+ if (ad->callback)
+ msg = ad->callback (ad->user_data);
+
+ gst_debug_log (ad->cat, ad->level, ad->file, ad->function, ad->line,
+ ad->object, "%s %s", GST_STR_NULL (ad->debug_msg), msg ? msg : "");
+ g_free (msg);
+ _free_async_debug_data (ad);
+ }
+}
+
+/**
+ * gst_gl_async_debug_store_log_msg:
+ * @ad: the #GstGLAsyncDebug to store the message in
+ * @cat: the #GstDebugCategory to output the message in
+ * @level: the #GstLevel
+ * @file: the file where the debug message originates from
+ * @function: the function where the debug message originates from
+ * @line: the line in @file where the debug message originates from
+ * @object: (allow-none): a #GObject to associate with the debug message
+ * @format: a printf style format string
+ * @...: the list of arguments for @format
+ *
+ * Stores a debug message for later output by gst_gl_async_debug_output_log_msg()
+ */
+void
+gst_gl_async_debug_store_log_msg (GstGLAsyncDebug * ad, GstDebugCategory * cat,
+ GstDebugLevel level, const gchar * file, const gchar * function, gint line,
+ GObject * object, const gchar * format, ...)
+{
+ va_list varargs;
+
+ if (G_UNLIKELY (level <= GST_LEVEL_MAX && level <= _gst_debug_min)) {
+ va_start (varargs, format);
+ gst_gl_async_debug_store_log_msg_valist (ad, cat, level, file, function,
+ line, object, format, varargs);
+ va_end (varargs);
+ }
+}
#endif
diff --git a/gst-libs/gst/gl/gstgldebug.h b/gst-libs/gst/gl/gstgldebug.h
index c27782578..5b936d0ea 100644
--- a/gst-libs/gst/gl/gstgldebug.h
+++ b/gst-libs/gst/gl/gstgldebug.h
@@ -25,20 +25,150 @@
G_BEGIN_DECLS
+typedef struct _GstGLAsyncDebug GstGLAsyncDebug;
+
+typedef gchar * (*GstGLAsyncDebugLogGetMessage) (gpointer user_data);
+
+/**
+ * GstGLAsyncDebug:
+ *
+ * #GstGLAsyncDebug an opaque structure and should only be accessed through the
+ * provided API.
+ */
+struct _GstGLAsyncDebug
+{
+ /* <private> */
+ guint state_flags;
+ GstDebugCategory *cat;
+ GstDebugLevel level;
+ const gchar *file;
+ const gchar *function;
+ gint line;
+ GObject *object;
+ gchar *debug_msg;
+
+ /* <protected> */
+ GstGLAsyncDebugLogGetMessage callback;
+ gpointer user_data;
+ GDestroyNotify notify;
+};
+
+GstGLAsyncDebug * gst_gl_async_debug_new (void);
+void gst_gl_async_debug_free (GstGLAsyncDebug * ad);
+void gst_gl_async_debug_init (GstGLAsyncDebug * ad);
+void gst_gl_async_debug_unset (GstGLAsyncDebug * ad);
+void gst_gl_async_debug_freeze (GstGLAsyncDebug * ad);
+void gst_gl_async_debug_thaw (GstGLAsyncDebug * ad);
+
+/**
+ * GST_GL_ASYNC_CAT_LEVEL_LOG_valist:
+ * @ad: the #GstGLAsyncDebug to store the message in
+ * @cat: the #GstDebugCategory to output the message in
+ * @level: the #GstLevel
+ * @file: the file where the debug message originates from
+ * @function: the function where the debug message originates from
+ * @line: the line in @file where the debug message originates from
+ * @object: (allow-none): a #GObject to associate with the debug message
+ * @format: a printf style format string
+ * @varargs: the list of arguments for @format
+ *
+ * Stores a debug message in @ad for later output
+ */
+#define GST_GL_ASYNC_CAT_LEVEL_LOG_valist(ad,cat,level,object,format,varargs) \
+ gst_gl_async_debug_store_log_msg_valist (ad, cat, level, __FILE__, \
+ GST_FUNCTION, __LINE__, object, format, varargs)
+
+/**
+ * GST_GL_ASYNC_CAT_LEVEL_LOG:
+ * @ad: the #GstGLAsyncDebug to store the message in
+ * @cat: the #GstDebugCategory to output the message in
+ * @level: the #GstLevel
+ * @file: the file where the debug message originates from
+ * @function: the function where the debug message originates from
+ * @line: the line in @file where the debug message originates from
+ * @object: (allow-none): a #GObject to associate with the debug message
+ * @format: a printf style format string
+ * @...: the list of arguments for @format
+ *
+ * Stores a debug message in @ad for later output
+ */
+#if G_HAVE_ISO_VARARGS
+#define GST_GL_ASYNC_CAT_LEVEL_LOG(ad,cat,level,object,format,...) \
+ gst_gl_async_debug_store_log_msg (ad, cat, level, __FILE__, GST_FUNCTION, \
+ __LINE__, object, format, __VA_ARGS__)
+#else /* G_HAVE_ISO_VARARGS */
+#if G_HAVE_GNUC_VARARGS
+#define GST_GL_ASYNC_CAT_LEVEL_LOG(ad,cat,level,object,format,args...) \
+ gst_gl_async_debug_store_log_msg (ad, cat, level, __FILE__, GST_FUNCTION, \
+ __LINE__, object, format, ##args)
+#else /* G_HAVE_GNUC_VARARGS */
+static inline void
+GST_GL_ASYNC_CAT_LEVEL_LOG(GstGLAsyncDebug * ad, GstDebugCategory * cat,
+ GstDebugLevel level, GObject * object, const gchar * format, ...)
+{
+ va_list varargs;
+
+ va_start (varargs, format);
+ GST_GL_ASYNC_CAT_LEVEL_LOG_valist (ad, cat, level, object, format, varargs);
+ va_end (varargs);
+}
+#endif /* G_HAVE_GNUC_VARARGS */
+#endif /* G_HAVE_ISO_VARARGS */
+
#if !defined(GST_DISABLE_GST_DEBUG)
-void gst_gl_insert_debug_marker (GstGLContext * context,
- const gchar * format, ...) G_GNUC_PRINTF (2, 3);
+
+void gst_gl_insert_debug_marker (GstGLContext * context,
+ const gchar * format, ...) G_GNUC_PRINTF (2, 3);
+void gst_gl_async_debug_output_log_msg (GstGLAsyncDebug * ad);
+void gst_gl_async_debug_store_log_msg (GstGLAsyncDebug * ad,
+ GstDebugCategory * cat,
+ GstDebugLevel level,
+ const gchar * file,
+ const gchar * function,
+ gint line,
+ GObject * object,
+ const gchar * format, ...) G_GNUC_PRINTF (8, 9);
+void gst_gl_async_debug_store_log_msg_valist (GstGLAsyncDebug * ad,
+ GstDebugCategory * cat,
+ GstDebugLevel level,
+ const gchar * file,
+ const gchar * function,
+ gint line,
+ GObject * object,
+ const gchar * format,
+ va_list varargs) G_GNUC_PRINTF (8, 0);
+
#else /* GST_DISABLE_GST_DEBUG */
+
+#define gst_gl_async_debug_output_log_msg(ad) G_STMT_START{ }G_STMT_END
+#define gst_gl_async_debug_store_log_msg_valist(ad,cat,level,file,function,line,object,format,args) G_STMT_START{ }G_STMT_END
+
#if G_HAVE_ISO_VARARGS
+
#define gst_gl_insert_debug_marker(...) G_STMT_START{ }G_STMT_END
+#define gst_gl_async_debug_store_log_msg(...) G_STMT_START{ }G_STMT_END
+
#else /* G_HAVE_ISO_VARARGS */
#if G_HAVE_GNUC_VARARGS
+
#define gst_gl_insert_debug_marker(args...) G_STMT_START{ }G_STMT_END
+#define gst_gl_async_debug_store_log_msg(args...) G_STMT_START{ }G_STMT_END
+
#else /* G_HAVE_GNUC_VARARGS */
+
static inline void
gst_gl_insert_debug_marker (GstGLContext * context, const gchar * format, ...)
{
}
+
+static inline void
+gst_gl_async_debug_store_log_msg (GstGLAsyncDebug * ad,
+ GstDebugCategory * cat, GstDebugLevel level, const gchar * file,
+ const gchar * function, gint line, GstObject * object,
+ const gchar * format, ...)
+{
+}
+
#endif /* G_HAVE_GNUC_VARARGS */
#endif /* G_HAVE_ISO_VARARGS */
#endif /* GST_DISABLE_GST_DEBUG */