static void do_query_post (GstStatsTracer * self, guint64 ts, GstPad * this_pad, GstQuery * qry, gboolean res) { GstPadStats *this_pad_stats = get_pad_stats (self, this_pad); GstPad *that_pad = GST_PAD_PEER (this_pad); GstPadStats *that_pad_stats = get_pad_stats (self, that_pad); do_query_stats (self, this_pad, this_pad_stats, that_pad, that_pad_stats, qry, ts, TRUE, res); }
static void do_push_buffer_pre (GstStatsTracer * self, guint64 ts, GstPad * this_pad, GstBuffer * buffer) { GstPadStats *this_pad_stats = get_pad_stats (self, this_pad); GstPad *that_pad = GST_PAD_PEER (this_pad); GstPadStats *that_pad_stats = get_pad_stats (self, that_pad); do_buffer_stats (self, this_pad, this_pad_stats, that_pad, that_pad_stats, buffer, ts); }
static void do_query_pre (GstStatsTracer * self, guint64 ts, GstPad * this_pad, GstQuery * qry) { GstPadStats *this_pad_stats = get_pad_stats (self, this_pad); GstPad *that_pad = GST_PAD_PEER (this_pad); GstPadStats *that_pad_stats = get_pad_stats (self, that_pad); do_query_stats (self, this_pad, this_pad_stats, that_pad, that_pad_stats, qry, ts, FALSE, FALSE); }
static void do_push_buffer_list_pre (GstStatsTracer * self, guint64 ts, GstPad * this_pad, GstBufferList * list) { GstPadStats *this_pad_stats = get_pad_stats (self, this_pad); GstPad *that_pad = GST_PAD_PEER (this_pad); GstPadStats *that_pad_stats = get_pad_stats (self, that_pad); DoPushBufferListArgs args = { self, this_pad, this_pad_stats, that_pad, that_pad_stats, ts }; gst_buffer_list_foreach (list, do_push_buffer_list_item, &args); }
static void do_pull_range_post (GstStatsTracer * self, guint64 ts, GstPad * this_pad, GstBuffer * buffer) { GstPadStats *this_pad_stats = get_pad_stats (self, this_pad); guint64 last_ts = this_pad_stats->last_ts; GstPad *that_pad = GST_PAD_PEER (this_pad); GstPadStats *that_pad_stats = get_pad_stats (self, that_pad); if (buffer != NULL) { do_buffer_stats (self, this_pad, this_pad_stats, that_pad, that_pad_stats, buffer, ts); } do_element_stats (self, this_pad, last_ts, ts); }
static void do_push_buffer_list_post (GstStatsTracer * self, guint64 ts, GstPad * pad, GstFlowReturn res) { GstPadStats *stats = get_pad_stats (self, pad); do_element_stats (self, pad, stats->last_ts, ts); }
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)); }
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)); }
static void do_pull_range_pre (GstStatsTracer * self, guint64 ts, GstPad * pad) { GstPadStats *stats = get_pad_stats (self, pad); stats->last_ts = ts; }
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 }