Ejemplo n.º 1
0
static void
do_query_stats (GstStatsTracer * self, GstPad * this_pad,
    GstPadStats * this_pad_stats, GstPad * that_pad,
    GstPadStats * that_pad_stats, GstQuery * qry, GstClockTime elapsed,
    gboolean res, gboolean is_post)
{
  GstElement *this_elem = get_real_pad_parent (this_pad);
  GstElementStats *this_elem_stats = get_element_stats (self, this_elem);
  GstElement *that_elem = get_real_pad_parent (that_pad);
  GstElementStats *that_elem_stats = get_element_stats (self, that_elem);
  GstStructure *s;

  s = gst_structure_new ("query",
      "thread-id", G_TYPE_UINT, GPOINTER_TO_UINT (g_thread_self ()),
      "ts", G_TYPE_UINT64, elapsed,
      "pad-ix", G_TYPE_UINT, this_pad_stats->index,
      "elem-ix", G_TYPE_UINT, this_elem_stats->index,
      "peer-pad-ix", G_TYPE_UINT, that_pad_stats->index,
      "peer-elem-ix", G_TYPE_UINT, that_elem_stats->index,
      "name", G_TYPE_STRING, GST_QUERY_TYPE_NAME (qry),
      "structure", GST_TYPE_STRUCTURE, gst_query_get_structure (qry), NULL);
  if (is_post) {
    gst_structure_set (s, "res", G_TYPE_BOOLEAN, res, NULL);
  }
  gst_tracer_log_trace (s);
}
Ejemplo n.º 2
0
static void
do_buffer_stats (GstStatsTracer * self, GstPad * this_pad,
    GstPadStats * this_pad_stats, GstPad * that_pad,
    GstPadStats * that_pad_stats, GstBuffer * buf, GstClockTime elapsed)
{
  GstElement *this_elem = get_real_pad_parent (this_pad);
  GstElementStats *this_elem_stats = get_element_stats (self, this_elem);
  GstElement *that_elem = get_real_pad_parent (that_pad);
  GstElementStats *that_elem_stats = get_element_stats (self, that_elem);

  /* TODO(ensonic): need a quark-table (shared with the tracer-front-ends?) */
  gst_tracer_log_trace (gst_structure_new ("buffer",
          "thread-id", G_TYPE_UINT, GPOINTER_TO_UINT (g_thread_self ()),
          "ts", G_TYPE_UINT64, elapsed,
          "pad-ix", G_TYPE_UINT, this_pad_stats->index,
          "elem-ix", G_TYPE_UINT, this_elem_stats->index,
          "peer-pad-ix", G_TYPE_UINT, that_pad_stats->index,
          "peer-elem-ix", G_TYPE_UINT, that_elem_stats->index,
          "buffer-size", G_TYPE_UINT, gst_buffer_get_size (buf),
          "buffer-pts", G_TYPE_UINT64, GST_BUFFER_PTS (buf),
          "buffer-dts", G_TYPE_UINT64, GST_BUFFER_DTS (buf),
          "buffer-duration", G_TYPE_UINT64, GST_BUFFER_DURATION (buf),
          "buffer-flags", GST_TYPE_BUFFER_FLAGS, GST_BUFFER_FLAGS (buf),
          /*
             scheduling-jitter: for this we need the last_ts on the pad
           */
          NULL));
}
Ejemplo n.º 3
0
static void
do_query_stats (GstStatsTracer * self, GstPad * this_pad,
    GstPadStats * this_pad_stats, GstPad * that_pad,
    GstPadStats * that_pad_stats, GstQuery * qry, GstClockTime elapsed,
    gboolean have_res, gboolean res)
{
  GstElement *this_elem = get_real_pad_parent (this_pad);
  GstElementStats *this_elem_stats = get_element_stats (self, this_elem);
  GstElement *that_elem = get_real_pad_parent (that_pad);
  GstElementStats *that_elem_stats = get_element_stats (self, that_elem);

  gst_tracer_record_log (tr_query, (guint64) (guintptr) g_thread_self (),
      elapsed, this_pad_stats->index, this_elem_stats->index,
      that_pad_stats->index, that_elem_stats->index, GST_QUERY_TYPE_NAME (qry),
      gst_query_get_structure (qry), have_res, res);
}
Ejemplo n.º 4
0
static GstPadStats *
get_pad_stats (GstStatsTracer * self, GstPad * pad)
{
  GstPadStats *stats;
  gboolean is_new = FALSE;

  if (!pad) {
    no_pad_stats.index = G_MAXUINT;
    return &no_pad_stats;
  }

  G_LOCK (_pad_stats);
  if (!(stats = g_object_get_qdata ((GObject *) pad, data_quark))) {
    stats = fill_pad_stats (self, pad);
    g_object_set_qdata_full ((GObject *) pad, data_quark, stats,
        free_pad_stats);
    is_new = TRUE;
  }
  G_UNLOCK (_pad_stats);
  if (G_UNLIKELY (stats->parent_ix == G_MAXUINT)) {
    GstElement *elem = get_real_pad_parent (pad);
    if (elem) {
      GstElementStats *elem_stats = get_element_stats (self, elem);

      stats->parent_ix = elem_stats->index;
    }
  }
  if (G_UNLIKELY (is_new)) {
    log_new_pad_stats (stats, pad);
  }
  return stats;
}
Ejemplo n.º 5
0
static inline GstElementStats *
get_element_stats (GstStatsTracer * self, GstElement * element)
{
  GstElementStats *stats;
  gboolean is_new = FALSE;

  if (!element) {
    no_elem_stats.index = G_MAXUINT;
    return &no_elem_stats;
  }

  G_LOCK (_elem_stats);
  if (!(stats = g_object_get_qdata ((GObject *) element, data_quark))) {
    stats = create_element_stats (self, element);
    is_new = TRUE;
  }
  G_UNLOCK (_elem_stats);
  if (G_UNLIKELY (stats->parent_ix == G_MAXUINT)) {
    GstElement *parent = GST_ELEMENT_PARENT (element);
    if (parent) {
      GstElementStats *parent_stats = get_element_stats (self, parent);
      stats->parent_ix = parent_stats->index;
    }
  }
  if (G_UNLIKELY (is_new)) {
    log_new_element_stats (stats, element, GST_CLOCK_TIME_NONE);
  }
  return stats;
}
Ejemplo n.º 6
0
static void
do_buffer_stats (GstStatsTracer * self, GstPad * this_pad,
    GstPadStats * this_pad_stats, GstPad * that_pad,
    GstPadStats * that_pad_stats, GstBuffer * buf, GstClockTime elapsed)
{
  GstElement *this_elem = get_real_pad_parent (this_pad);
  GstElementStats *this_elem_stats = get_element_stats (self, this_elem);
  GstElement *that_elem = get_real_pad_parent (that_pad);
  GstElementStats *that_elem_stats = get_element_stats (self, that_elem);
  GstClockTime pts = GST_BUFFER_PTS (buf);
  GstClockTime dts = GST_BUFFER_DTS (buf);
  GstClockTime dur = GST_BUFFER_DURATION (buf);

  gst_tracer_record_log (tr_buffer, (guint64) (guintptr) g_thread_self (),
      elapsed, this_pad_stats->index, this_elem_stats->index,
      that_pad_stats->index, that_elem_stats->index, gst_buffer_get_size (buf),
      GST_CLOCK_TIME_IS_VALID (pts), pts, GST_CLOCK_TIME_IS_VALID (dts), dts,
      GST_CLOCK_TIME_IS_VALID (dur), dur, GST_BUFFER_FLAGS (buf));
}
Ejemplo n.º 7
0
static void
do_element_query_pre (GstStatsTracer * self, guint64 ts, GstElement * elem,
    GstQuery * qry)
{
  GstElementStats *stats = get_element_stats (self, elem);

  stats->last_ts = ts;
  gst_tracer_record_log (tr_element_query,
      (guint64) (guintptr) g_thread_self (), ts, stats->index,
      GST_QUERY_TYPE_NAME (qry));
}
Ejemplo n.º 8
0
static void
do_push_event_pre (GstStatsTracer * self, guint64 ts, GstPad * pad,
    GstEvent * ev)
{
  GstElement *elem = get_real_pad_parent (pad);
  GstElementStats *elem_stats = get_element_stats (self, elem);
  GstPadStats *pad_stats = get_pad_stats (self, pad);

  elem_stats->last_ts = ts;
  gst_tracer_record_log (tr_event, (guint64) (guintptr) g_thread_self (), ts,
      pad_stats->index, elem_stats->index, GST_EVENT_TYPE_NAME (ev));
}
Ejemplo n.º 9
0
static void
do_element_query_pre (GstStatsTracer * self, guint64 ts, GstElement * elem,
    GstQuery * qry)
{
  GstElementStats *stats = get_element_stats (self, elem);

  stats->last_ts = ts;
  gst_tracer_log_trace (gst_structure_new ("element-query",
          "thread-id", G_TYPE_UINT, GPOINTER_TO_UINT (g_thread_self ()),
          "ts", G_TYPE_UINT64, ts,
          "elem-ix", G_TYPE_UINT, stats->index,
          "name", G_TYPE_STRING, GST_QUERY_TYPE_NAME (qry), NULL));
}
Ejemplo n.º 10
0
static void
do_post_message_pre (GstStatsTracer * self, guint64 ts, GstElement * elem,
    GstMessage * msg)
{
  GstElementStats *stats = get_element_stats (self, elem);
  const GstStructure *msg_s = gst_message_get_structure (msg);
  GstStructure *s =
      msg_s ? (GstStructure *) msg_s : gst_structure_new_empty ("dummy");

  stats->last_ts = ts;
  /* FIXME: work out whether using NULL instead of a dummy struct would work */
  gst_tracer_record_log (tr_message, (guint64) (guintptr) g_thread_self (), ts,
      stats->index, GST_MESSAGE_TYPE_NAME (msg), s);
  if (s != msg_s)
    gst_structure_free (s);
}
Ejemplo n.º 11
0
static void
do_push_event_pre (GstStatsTracer * self, guint64 ts, GstPad * pad,
    GstEvent * ev)
{
  GstElement *elem = get_real_pad_parent (pad);
  GstElementStats *elem_stats = get_element_stats (self, elem);
  GstPadStats *pad_stats = get_pad_stats (self, pad);

  elem_stats->last_ts = ts;
  gst_tracer_log_trace (gst_structure_new ("event",
          "thread-id", G_TYPE_UINT, GPOINTER_TO_UINT (g_thread_self ()),
          "ts", G_TYPE_UINT64, ts,
          "pad-ix", G_TYPE_UINT, pad_stats->index,
          "elem-ix", G_TYPE_UINT, elem_stats->index,
          "name", G_TYPE_STRING, GST_EVENT_TYPE_NAME (ev), NULL));
}
Ejemplo n.º 12
0
static void
do_post_message_pre (GstStatsTracer * self, guint64 ts, GstElement * elem,
    GstMessage * msg)
{
  GstElementStats *stats = get_element_stats (self, elem);
  const GstStructure *msg_s = gst_message_get_structure (msg);
  GstStructure *s;

  stats->last_ts = ts;

  s = gst_structure_new ("message",
      "thread-id", G_TYPE_UINT, GPOINTER_TO_UINT (g_thread_self ()),
      "ts", G_TYPE_UINT64, ts,
      "elem-ix", G_TYPE_UINT, stats->index,
      "name", G_TYPE_STRING, GST_MESSAGE_TYPE_NAME (msg), NULL);
  if (msg_s) {
    gst_structure_set (s, "structure", GST_TYPE_STRUCTURE, msg_s, NULL);
  }
  gst_tracer_log_trace (s);
}
Ejemplo n.º 13
0
static void
do_element_stats (GstStatsTracer * self, GstPad * pad, GstClockTime elapsed1,
    GstClockTime elapsed2)
{
  GstClockTimeDiff elapsed = GST_CLOCK_DIFF (elapsed1, elapsed2);
  GstObject *parent = GST_OBJECT_PARENT (pad);
  GstElement *this =
      GST_ELEMENT_CAST (GST_IS_PAD (parent) ? GST_OBJECT_PARENT (parent) :
      parent);
  GstElementStats *this_stats = get_element_stats (self, this);
  GstPad *peer_pad = GST_PAD_PEER (pad);
  GstElementStats *peer_stats;

  if (!peer_pad)
    return;

  /* walk the ghost pad chain downstream to get the real pad */
  /* if parent of peer_pad is a ghost-pad, then peer_pad is a proxy_pad */
  parent = GST_OBJECT_PARENT (peer_pad);
  if (parent && GST_IS_GHOST_PAD (parent)) {
    peer_pad = GST_PAD_CAST (parent);
    /* if this is now the ghost pad, get the peer of this */
    get_pad_stats (self, peer_pad);
    if ((parent = GST_OBJECT_PARENT (peer_pad))) {
      get_element_stats (self, GST_ELEMENT_CAST (parent));
    }
    peer_pad = GST_PAD_PEER (GST_GHOST_PAD_CAST (peer_pad));
    parent = peer_pad ? GST_OBJECT_PARENT (peer_pad) : NULL;
  }
  /* walk the ghost pad chain upstream to get the real pad */
  /* if peer_pad is a ghost-pad, then parent is a bin and it is the parent of
   * a proxy_pad */
  while (peer_pad && GST_IS_GHOST_PAD (peer_pad)) {
    get_pad_stats (self, peer_pad);
    get_element_stats (self, GST_ELEMENT_CAST (parent));
    peer_pad = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (peer_pad));
    parent = peer_pad ? GST_OBJECT_PARENT (peer_pad) : NULL;
  }

  if (!parent) {
    printf ("%" GST_TIME_FORMAT
        " transmission on unparented target pad %s_%s -> %s_%s\n",
        GST_TIME_ARGS (elapsed), GST_DEBUG_PAD_NAME (pad),
        GST_DEBUG_PAD_NAME (peer_pad));
    return;
  }
  peer_stats = get_element_stats (self, GST_ELEMENT_CAST (parent));

  /* we'd like to gather time spend in each element, but this does not make too
   * much sense yet
   * pure push/pull-based:
   *   - the time spend in the push/pull_range is accounted for the peer and
   *     removed from the current element
   *   - this works for chains
   *   - drawback is sink elements that block to sync have a high time usage
   *     - we could rerun the ests with sync=false
   * both:
   *   - a.g. demuxers both push and pull. thus we subtract time for the pull
   *     and the push operations, but never add anything.
   *   - can we start a counter after push/pull in such elements and add then
   *     time to the element upon next pad activity?
   */
#if 1
  /* this does not make sense for demuxers */
  this_stats->treal -= elapsed;
  peer_stats->treal += elapsed;
#else
  /* this creates several >100% figures */
  this_stats->treal += GST_CLOCK_DIFF (this_stats->last_ts, elapsed2) - elapsed;
  peer_stats->treal += elapsed;
  this_stats->last_ts = elapsed2;
  peer_stats->last_ts = elapsed2;
#endif
}