/* GstShark - A Front End for GstTracer * Copyright (C) 2016-2018 RidgeRun Engineering * * This file is part of GstShark. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION:gstqueuelevel * @short_description: log current queue level * * A tracing module that takes queue's current level */ #include "gstqueuelevel.h" #include "gstctf.h" GST_DEBUG_CATEGORY_STATIC (gst_queue_level_debug); #define GST_CAT_DEFAULT gst_queue_level_debug struct _GstQueueLevelTracer { GstSharkTracer parent; }; #define _do_init \ GST_DEBUG_CATEGORY_INIT (gst_queue_level_debug, "queuelevel", 0, "queuelevel tracer"); G_DEFINE_TYPE_WITH_CODE (GstQueueLevelTracer, gst_queue_level_tracer, GST_SHARK_TYPE_TRACER, _do_init); static void do_queue_level (GstTracer * tracer, guint64 ts, GstPad * pad); static void do_queue_level_list (GstTracer * tracer, guint64 ts, GstPad * pad, GstBufferList * list); static gboolean is_queue (GstElement * element); static GstTracerRecord *tr_qlevel; static const gchar queue_level_metadata_event[] = "event {\n\ name = queuelevel;\n\ id = %d;\n\ stream_id = %d;\n\ fields := struct {\n\ string queue;\n\ integer { size = 32; align = 8; signed = 0; encoding = none; base = 10; } size_bytes;\n\ integer { size = 32; align = 8; signed = 0; encoding = none; base = 10; } max_size_bytes;\n \ integer { size = 32; align = 8; signed = 0; encoding = none; base = 10; } size_buffers;\n\ integer { size = 32; align = 8; signed = 0; encoding = none; base = 10; } max_size_buffers;\n\ integer { size = 64; align = 8; signed = 0; encoding = none; base = 10; } size_time;\n\ integer { size = 64; align = 8; signed = 0; encoding = none; base = 10; } max_size_time;\n\ };\n\ };\n\ \n"; static GstElement * get_parent_element (GstPad * pad) { GstElement *element; GstObject *parent; GstObject *child = GST_OBJECT (pad); do { parent = GST_OBJECT_PARENT (child); if (GST_IS_ELEMENT (parent)) break; child = parent; } while (GST_IS_OBJECT (child)); element = gst_pad_get_parent_element (GST_PAD (child)); return element; } static void do_queue_level (GstTracer * self, guint64 ts, GstPad * pad) { GstElement *element; guint32 size_bytes; guint32 max_size_bytes; guint32 size_buffers; guint32 max_size_buffers; guint64 size_time; guint64 max_size_time; gchar *size_time_string; gchar *max_size_time_string; const gchar *element_name; element = get_parent_element (pad); if (!is_queue (element)) { goto out; } element_name = GST_OBJECT_NAME (element); g_object_get (element, "current-level-bytes", &size_bytes, "current-level-buffers", &size_buffers, "current-level-time", &size_time, "max-size-bytes", &max_size_bytes, "max-size-buffers", &max_size_buffers, "max-size-time", &max_size_time, NULL); size_time_string = g_strdup_printf ("%" GST_TIME_FORMAT, GST_TIME_ARGS (size_time)); max_size_time_string = g_strdup_printf ("%" GST_TIME_FORMAT, GST_TIME_ARGS (max_size_time)); gst_tracer_record_log (tr_qlevel, element_name, size_bytes, max_size_bytes, size_buffers, max_size_buffers, size_time_string, max_size_time_string); g_free (size_time_string); g_free (max_size_time_string); do_print_queue_level_event (QUEUE_LEVEL_EVENT_ID, element_name, size_bytes, max_size_bytes, size_buffers, max_size_buffers, size_time, max_size_time); out: { gst_object_unref (element); } } static void do_queue_level_list (GstTracer * tracer, guint64 ts, GstPad * pad, GstBufferList * list) { guint idx; for (idx = 0; idx < gst_buffer_list_length (list); ++idx) { do_queue_level (tracer, ts, pad); } } static gboolean is_queue (GstElement * element) { static GstElementFactory *qfactory = NULL; GstElementFactory *efactory; g_return_val_if_fail (element, FALSE); /* Find the queue factory that is going to be compared against the element under inspection to see if it is a queue */ if (NULL == qfactory) { qfactory = gst_element_factory_find ("queue"); } efactory = gst_element_get_factory (element); return efactory == qfactory; } /* tracer class */ static void gst_queue_level_tracer_class_init (GstQueueLevelTracerClass * klass) { tr_qlevel = gst_tracer_record_new ("queuelevel.class", "queue", GST_TYPE_STRUCTURE, gst_structure_new ("scope", "type", G_TYPE_GTYPE, G_TYPE_STRING, "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, NULL), "size_bytes", GST_TYPE_STRUCTURE, gst_structure_new ("scope", "type", G_TYPE_GTYPE, G_TYPE_UINT, "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, NULL), "max_size_bytes", GST_TYPE_STRUCTURE, gst_structure_new ("scope", "type", G_TYPE_GTYPE, G_TYPE_UINT, "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, NULL), "size_buffers", GST_TYPE_STRUCTURE, gst_structure_new ("scope", "type", G_TYPE_GTYPE, G_TYPE_UINT, "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, NULL), "max_size_buffers", GST_TYPE_STRUCTURE, gst_structure_new ("scope", "type", G_TYPE_GTYPE, G_TYPE_UINT, "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, NULL), "size_time", GST_TYPE_STRUCTURE, gst_structure_new ("scope", "type", G_TYPE_GTYPE, G_TYPE_STRING, "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, NULL), "max_size_time", GST_TYPE_STRUCTURE, gst_structure_new ("scope", "type", G_TYPE_GTYPE, G_TYPE_STRING, "related-to", GST_TYPE_TRACER_VALUE_SCOPE, GST_TRACER_VALUE_SCOPE_ELEMENT, NULL), NULL); } static void gst_queue_level_tracer_init (GstQueueLevelTracer * self) { GstSharkTracer *tracer = GST_SHARK_TRACER (self); gchar *metadata_event = NULL; gst_shark_tracer_register_hook (tracer, "pad-push-pre", G_CALLBACK (do_queue_level)); gst_shark_tracer_register_hook (tracer, "pad-push-list-pre", G_CALLBACK (do_queue_level_list)); gst_shark_tracer_register_hook (tracer, "pad-pull-range-pre", G_CALLBACK (do_queue_level)); metadata_event = g_strdup_printf (queue_level_metadata_event, QUEUE_LEVEL_EVENT_ID, 0); add_metadata_event_struct (metadata_event); g_free (metadata_event); }