Blame gst/gsttracerutils.c

Packit Service 963350
/* GStreamer
Packit Service 963350
 * Copyright (C) 2013 Stefan Sauer <ensonic@users.sf.net>
Packit Service 963350
 *
Packit Service 963350
 * gsttracerutils.c: tracing subsystem
Packit Service 963350
 *
Packit Service 963350
 * This library is free software; you can redistribute it and/or
Packit Service 963350
 * modify it under the terms of the GNU Library General Public
Packit Service 963350
 * License as published by the Free Software Foundation; either
Packit Service 963350
 * version 2 of the License, or (at your option) any later version.
Packit Service 963350
 *
Packit Service 963350
 * This library is distributed in the hope that it will be useful,
Packit Service 963350
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 963350
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 963350
 * Library General Public License for more details.
Packit Service 963350
 *
Packit Service 963350
 * You should have received a copy of the GNU Library General Public
Packit Service 963350
 * License along with this library; if not, write to the
Packit Service 963350
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Packit Service 963350
 * Boston, MA 02110-1301, USA.
Packit Service 963350
 */
Packit Service 963350
Packit Service 963350
/* Tracing subsystem:
Packit Service 963350
 *
Packit Service 963350
 * The tracing subsystem provides hooks in the core library and API for modules
Packit Service 963350
 * to attach to them.
Packit Service 963350
 *
Packit Service 963350
 * The user can activate tracers by setting the environment variable GST_TRACE
Packit Service 963350
 * to a ';' separated list of tracers.
Packit Service 963350
 *
Packit Service 963350
 * Note that instanciating tracers at runtime is possible but is not thread safe
Packit Service 963350
 * and needs to be done before any pipeline state is set to PAUSED.
Packit Service 963350
 */
Packit Service 963350
Packit Service 963350
#define GST_USE_UNSTABLE_API
Packit Service 963350
Packit Service 963350
#include "gst_private.h"
Packit Service 963350
#include "gsttracer.h"
Packit Service 963350
#include "gsttracerfactory.h"
Packit Service 963350
#include "gsttracerutils.h"
Packit Service 963350
Packit Service 963350
#ifndef GST_DISABLE_GST_TRACER_HOOKS
Packit Service 963350
Packit Service 963350
/* tracer quarks */
Packit Service 963350
Packit Service 963350
/* These strings must match order and number declared in the GstTracerQuarkId
Packit Service 963350
 * enum in gsttracerutils.h! */
Packit Service 963350
static const gchar *_quark_strings[] = {
Packit Service 963350
  "pad-push-pre", "pad-push-post", "pad-push-list-pre", "pad-push-list-post",
Packit Service 963350
  "pad-pull-range-pre", "pad-pull-range-post", "pad-push-event-pre",
Packit Service 963350
  "pad-push-event-post", "pad-query-pre", "pad-query-post",
Packit Service 963350
  "element-post-message-pre",
Packit Service 963350
  "element-post-message-post", "element-query-pre", "element-query-post",
Packit Service 963350
  "element-new", "element-add-pad", "element-remove-pad",
Packit Service 963350
  "bin-add-pre", "bin-add-post", "bin-remove-pre", "bin-remove-post",
Packit Service 963350
  "pad-link-pre", "pad-link-post", "pad-unlink-pre", "pad-unlink-post",
Packit Service 963350
  "element-change-state-pre", "element-change-state-post",
Packit Service 963350
  "mini-object-created", "mini-object-destroyed", "object-created",
Packit Service 963350
  "object-destroyed", "mini-object-reffed", "mini-object-unreffed",
Packit Service 963350
  "object-reffed", "object-unreffed",
Packit Service 963350
};
Packit Service 963350
Packit Service 963350
GQuark _priv_gst_tracer_quark_table[GST_TRACER_QUARK_MAX];
Packit Service 963350
Packit Service 963350
/* tracing helpers */
Packit Service 963350
Packit Service 963350
gboolean _priv_tracer_enabled = FALSE;
Packit Service 963350
GHashTable *_priv_tracers = NULL;
Packit Service 963350
Packit Service 963350
/* Initialize the tracing system */
Packit Service 963350
void
Packit Service 963350
_priv_gst_tracing_init (void)
Packit Service 963350
{
Packit Service 963350
  gint i = 0;
Packit Service 963350
  const gchar *env = g_getenv ("GST_TRACERS");
Packit Service 963350
Packit Service 963350
  /* We initialize the tracer sub system even if the end
Packit Service 963350
   * user did not activate it through the env variable
Packit Service 963350
   * so that external tools can use it anyway */
Packit Service 963350
  GST_DEBUG ("Initializing GstTracer");
Packit Service 963350
  _priv_tracers = g_hash_table_new (NULL, NULL);
Packit Service 963350
Packit Service 963350
  if (G_N_ELEMENTS (_quark_strings) != GST_TRACER_QUARK_MAX)
Packit Service 963350
    g_warning ("the quark table is not consistent! %d != %d",
Packit Service 963350
        (gint) G_N_ELEMENTS (_quark_strings), GST_TRACER_QUARK_MAX);
Packit Service 963350
Packit Service 963350
  for (i = 0; i < GST_TRACER_QUARK_MAX; i++) {
Packit Service 963350
    _priv_gst_tracer_quark_table[i] =
Packit Service 963350
        g_quark_from_static_string (_quark_strings[i]);
Packit Service 963350
  }
Packit Service 963350
Packit Service 963350
  if (env != NULL && *env != '\0') {
Packit Service 963350
    GstRegistry *registry = gst_registry_get ();
Packit Service 963350
    GstPluginFeature *feature;
Packit Service 963350
    GstTracerFactory *factory;
Packit Service 963350
    gchar **t = g_strsplit_set (env, ";", 0);
Packit Service 963350
    gchar *params;
Packit Service 963350
Packit Service 963350
    GST_INFO ("enabling tracers: '%s'", env);
Packit Service 963350
    i = 0;
Packit Service 963350
    while (t[i]) {
Packit Service 963350
      // check t[i] for params
Packit Service 963350
      if ((params = strchr (t[i], '('))) {
Packit Service 963350
        gchar *end = strchr (&params[1], ')');
Packit Service 963350
        *params = '\0';
Packit Service 963350
        params++;
Packit Service 963350
        if (end)
Packit Service 963350
          *end = '\0';
Packit Service 963350
      } else {
Packit Service 963350
        params = NULL;
Packit Service 963350
      }
Packit Service 963350
Packit Service 963350
      GST_INFO ("checking tracer: '%s'", t[i]);
Packit Service 963350
Packit Service 963350
      if ((feature = gst_registry_lookup_feature (registry, t[i]))) {
Packit Service 963350
        factory = GST_TRACER_FACTORY (gst_plugin_feature_load (feature));
Packit Service 963350
        if (factory) {
Packit Service 963350
          GstTracer *tracer;
Packit Service 963350
Packit Service 963350
          GST_INFO_OBJECT (factory, "creating tracer: type-id=%u",
Packit Service 963350
              (guint) factory->type);
Packit Service 963350
Packit Service 963350
          tracer = g_object_new (factory->type, "params", params, NULL);
Packit Service 963350
Packit Service 963350
          /* Clear floating flag */
Packit Service 963350
          gst_object_ref_sink (tracer);
Packit Service 963350
Packit Service 963350
          /* tracers register them self to the hooks */
Packit Service 963350
          gst_object_unref (tracer);
Packit Service 963350
        } else {
Packit Service 963350
          GST_WARNING_OBJECT (feature,
Packit Service 963350
              "loading plugin containing feature %s failed!", t[i]);
Packit Service 963350
        }
Packit Service 963350
      } else {
Packit Service 963350
        GST_WARNING ("no tracer named '%s'", t[i]);
Packit Service 963350
      }
Packit Service 963350
      i++;
Packit Service 963350
    }
Packit Service 963350
    g_strfreev (t);
Packit Service 963350
  }
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
void
Packit Service 963350
_priv_gst_tracing_deinit (void)
Packit Service 963350
{
Packit Service 963350
  GList *h_list, *h_node, *t_node;
Packit Service 963350
  GstTracerHook *hook;
Packit Service 963350
Packit Service 963350
  _priv_tracer_enabled = FALSE;
Packit Service 963350
  if (!_priv_tracers)
Packit Service 963350
    return;
Packit Service 963350
Packit Service 963350
  /* shutdown tracers for final reports */
Packit Service 963350
  h_list = g_hash_table_get_values (_priv_tracers);
Packit Service 963350
  for (h_node = h_list; h_node; h_node = g_list_next (h_node)) {
Packit Service 963350
    for (t_node = h_node->data; t_node; t_node = g_list_next (t_node)) {
Packit Service 963350
      hook = (GstTracerHook *) t_node->data;
Packit Service 963350
      gst_object_unref (hook->tracer);
Packit Service 963350
      g_slice_free (GstTracerHook, hook);
Packit Service 963350
    }
Packit Service 963350
    g_list_free (h_node->data);
Packit Service 963350
  }
Packit Service 963350
  g_list_free (h_list);
Packit Service 963350
  g_hash_table_destroy (_priv_tracers);
Packit Service 963350
  _priv_tracers = NULL;
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
static void
Packit Service 963350
gst_tracing_register_hook_id (GstTracer * tracer, GQuark detail, GCallback func)
Packit Service 963350
{
Packit Service 963350
  gpointer key = GINT_TO_POINTER (detail);
Packit Service 963350
  GList *list = g_hash_table_lookup (_priv_tracers, key);
Packit Service 963350
  GstTracerHook *hook = g_slice_new0 (GstTracerHook);
Packit Service 963350
  hook->tracer = gst_object_ref (tracer);
Packit Service 963350
  hook->func = func;
Packit Service 963350
Packit Service 963350
  list = g_list_prepend (list, hook);
Packit Service 963350
  g_hash_table_replace (_priv_tracers, key, list);
Packit Service 963350
  GST_DEBUG ("registering tracer for '%s', list.len=%d",
Packit Service 963350
      (detail ? g_quark_to_string (detail) : "*"), g_list_length (list));
Packit Service 963350
  _priv_tracer_enabled = TRUE;
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
/**
Packit Service 963350
 * gst_tracing_register_hook:
Packit Service 963350
 * @tracer: the tracer
Packit Service 963350
 * @detail: the detailed hook
Packit Service 963350
 * @func: (scope async): the callback
Packit Service 963350
 *
Packit Service 963350
 * Register @func to be called when the trace hook @detail is getting invoked.
Packit Service 963350
 * Use %NULL for @detail to register to all hooks.
Packit Service 963350
 */
Packit Service 963350
void
Packit Service 963350
gst_tracing_register_hook (GstTracer * tracer, const gchar * detail,
Packit Service 963350
    GCallback func)
Packit Service 963350
{
Packit Service 963350
  gst_tracing_register_hook_id (tracer, g_quark_try_string (detail), func);
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
#else /* !GST_DISABLE_GST_TRACER_HOOKS */
Packit Service 963350
Packit Service 963350
void
Packit Service 963350
gst_tracing_register_hook (GstTracer * tracer, const gchar * detail,
Packit Service 963350
    GCallback func)
Packit Service 963350
{
Packit Service 963350
}
Packit Service 963350
Packit Service 963350
#endif /* GST_DISABLE_GST_TRACER_HOOKS */