[vlc-commits] [Git][videolan/vlc][master] 9 commits: core: add tracing API
Thomas Guillem (@tguillem)
gitlab at videolan.org
Tue Aug 31 14:38:15 UTC 2021
Thomas Guillem pushed to branch master at VideoLAN / VLC
Commits:
ee52a2e1 by Nicolas LeQuec at 2021-08-31T12:35:56+00:00
core: add tracing API
Tracing system is independant from the logging system and load modules with a "tracer" capability.
The tracer module is loaded at the initialisation of a libvlc instance.
- - - - -
fa32b560 by Nicolas LeQuec at 2021-08-31T12:35:56+00:00
src/object: add vlc_object_get_tracer function
- - - - -
d66f36af by Nicolas LeQuec at 2021-08-31T12:35:56+00:00
libvlc: integrate vlc_tracer API
- - - - -
0bf5330a by Nicolas LeQuec at 2021-08-31T12:35:56+00:00
src/clock: add a tracer field to the main clock
- - - - -
fcafe8a5 by Nicolas LeQuec at 2021-08-31T12:35:56+00:00
logger: add new trace module
Add a trace module that stores the traces in a file or displays them
in stdout with a json notation.
- - - - -
66fe08f3 by Nicolas LeQuec at 2021-08-31T12:35:56+00:00
libvlc-module: add the tracer module
- - - - -
a7edba07 by Nicolas LeQuec at 2021-08-31T12:35:56+00:00
src/decoder: add new field psz_id
In traces, it's useful to have the id of the decoder used.
- - - - -
8218c474 by Nicolas LeQuec at 2021-08-31T12:35:56+00:00
src/clock: add new field track_str_id
In traces, it's useful to have the str_id of the elementary stream read.
It can be obtained through the clock.
- - - - -
f55348fd by Nicolas LeQuec at 2021-08-31T12:35:56+00:00
logs: fit trace messages with the new trace API
Use of the previouly created trace API to collect data from demuxer, decoder and video_output.
Fields "type", "id", and "stream" are then used by a script to identify data and name curves to
display.
Here is the link of the script project: https://gitlab.com/videolabs/public/vlc-pa
- - - - -
16 changed files:
- include/vlc_objects.h
- + include/vlc_tracer.h
- modules/logger/Makefile.am
- + modules/logger/json.c
- src/Makefile.am
- src/clock/clock.c
- src/clock/clock.h
- src/input/decoder.c
- src/input/decoder.h
- src/input/es_out.c
- src/libvlc-module.c
- src/libvlc.c
- src/libvlc.h
- src/libvlccore.sym
- src/misc/objects.c
- + src/misc/tracer.c
Changes:
=====================================
include/vlc_objects.h
=====================================
@@ -29,6 +29,7 @@
*/
struct vlc_logger;
+struct vlc_tracer;
struct vlc_object_internals;
struct vlc_object_marker;
@@ -161,6 +162,13 @@ static inline struct vlc_logger *vlc_object_logger(vlc_object_t *obj)
}
#define vlc_object_logger(o) vlc_object_logger(VLC_OBJECT(o))
+ /**
+ * Get tracer of a vlc instance from an object.
+ *
+ * \return the tracer of a vlc instance from an object (NULL if none).
+ */
+VLC_API struct vlc_tracer *vlc_object_get_tracer(vlc_object_t *obj);
+
/**
* Tries to get the name of module bound to an object.
*
=====================================
include/vlc_tracer.h
=====================================
@@ -0,0 +1,188 @@
+/*****************************************************************************
+ * vlc_tracer.h: tracing interface
+ * This library provides basic functions for threads to interact with user
+ * interface, such as trace output.
+ *****************************************************************************
+ * Copyright (C) 2021 VLC authors and VideoLAN
+ *
+ * This program 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 program 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VLC_TRACES_H
+#define VLC_TRACES_H
+
+#include <stdarg.h>
+
+/**
+ * \defgroup traces Tracing
+ * \ingroup os
+ * \brief Message traces
+ *
+ * Functions for modules to emit traces.
+ *
+ * @{
+ * \file
+ * Tracing functions
+ */
+
+/**
+ * Trace message values
+ */
+enum vlc_tracer_value
+{
+ VLC_TRACER_INT,
+ VLC_TRACER_STRING
+};
+
+typedef union
+{
+ int64_t integer;
+ const char *string;
+} vlc_tracer_value_t;
+
+/**
+ * Trace message
+ */
+struct vlc_tracer_entry
+{
+ const char *key; /**< Key to identify the value */
+ vlc_tracer_value_t value; /**< Trace value */
+ enum vlc_tracer_value type; /**< Type of the value */
+};
+
+struct vlc_tracer;
+
+/**
+ * Trace logging callback signature.
+ *
+ * va-args can only be \ref vlc_tracer_entry and the va-args list
+ * should be ended by a \ref vlc_tracer_entry with a NULL key.
+ * \param data data pointer as provided to vlc_tracer_Trace().
+ */
+typedef void (*vlc_trace_cb) (void *data, va_list entries);
+
+struct vlc_tracer_operations
+{
+ vlc_trace_cb trace;
+ void (*destroy)(void *data);
+};
+
+/**
+ * Emit traces
+ *
+ * va-args are a list of key / value parameters.
+ * Key must be a not NULL string.
+ * Value has to be defined with one of the type defined
+ * in the \ref vlc_tracer_entry union.
+ * \param tracer tracer emitting the traces
+ */
+VLC_API void vlc_tracer_Trace(struct vlc_tracer *tracer, ...);
+
+/**
+ * \defgroup tracer Tracer
+ * \brief Tracing back-end.
+ *
+ * @{
+ */
+
+static inline struct vlc_tracer_entry vlc_tracer_entry_FromTick(const char *key, vlc_tick_t value)
+{
+ vlc_tracer_value_t tracer_value;
+ tracer_value.integer = value;
+ struct vlc_tracer_entry trace = { key, tracer_value, VLC_TRACER_INT };
+ return trace;
+}
+
+static inline struct vlc_tracer_entry vlc_tracer_entry_FromString(const char *key, const char *value)
+{
+ vlc_tracer_value_t tracer_value;
+ tracer_value.string = value;
+ struct vlc_tracer_entry trace = { key, tracer_value, VLC_TRACER_STRING };
+ return trace;
+}
+
+#ifndef __cplusplus
+#define VLC_TRACE_END \
+ vlc_tracer_entry_FromString(NULL, NULL)
+
+#define VLC_TRACE(key, value) \
+ _Generic((value), \
+ vlc_tick_t: vlc_tracer_entry_FromTick, \
+ char *: vlc_tracer_entry_FromString, \
+ const char *: vlc_tracer_entry_FromString) (key, value)
+#else
+#define VLC_TRACE_END \
+ vlc_tracer_entry_FromString(nullptr, nullptr)
+
+static inline struct vlc_tracer_entry VLC_TRACE(const char *key, vlc_tick_t value)
+{
+ return vlc_tracer_entry_FromTick(key, value);
+}
+
+static inline struct vlc_tracer_entry VLC_TRACE(const char *key, char *value)
+{
+ return vlc_tracer_entry_FromString(key, value);
+}
+
+static inline struct vlc_tracer_entry VLC_TRACE(const char *key, const char *value)
+{
+ return vlc_tracer_entry_FromString(key, value);
+}
+#endif
+
+/*
+ * Helper trace functions
+ */
+
+static inline void vlc_tracer_TraceStreamPTS(struct vlc_tracer *tracer, const char *type,
+ const char *id, const char* stream,
+ vlc_tick_t pts)
+{
+ vlc_tracer_Trace(tracer, VLC_TRACE("type", type), VLC_TRACE("id", id),
+ VLC_TRACE("stream", stream), VLC_TRACE("pts", NS_FROM_VLC_TICK(pts)),
+ VLC_TRACE_END);
+}
+
+static inline void vlc_tracer_TraceStreamDTS(struct vlc_tracer *tracer, const char *type,
+ const char *id, const char* stream,
+ vlc_tick_t pts, vlc_tick_t dts)
+{
+ vlc_tracer_Trace(tracer, VLC_TRACE("type", type), VLC_TRACE("id", id),
+ VLC_TRACE("stream", stream), VLC_TRACE("pts", NS_FROM_VLC_TICK(pts)),
+ VLC_TRACE("dts", NS_FROM_VLC_TICK(dts)), VLC_TRACE_END);
+}
+
+static inline void vlc_tracer_TraceRender(struct vlc_tracer *tracer, const char *type,
+ const char *id, vlc_tick_t pts, vlc_tick_t now)
+{
+ vlc_tracer_Trace(tracer, VLC_TRACE("type", type), VLC_TRACE("id", id),
+ VLC_TRACE("pts", NS_FROM_VLC_TICK(pts)),
+ VLC_TRACE("render_ts", NS_FROM_VLC_TICK(now)), VLC_TRACE_END);
+}
+
+static inline void vlc_tracer_TracePCR( struct vlc_tracer *tracer, const char *type,
+ const char *id, vlc_tick_t pcr)
+{
+ vlc_tracer_Trace(tracer, VLC_TRACE("type", type), VLC_TRACE("id", id),
+ VLC_TRACE("pcr", NS_FROM_VLC_TICK(pcr)), VLC_TRACE_END);
+}
+
+/**
+ * @}
+ */
+/**
+ * @}
+ */
+#endif
=====================================
modules/logger/Makefile.am
=====================================
@@ -22,3 +22,6 @@ libandroid_logger_plugin_la_LIBADD = -llog
if HAVE_ANDROID
logger_LTLIBRARIES += libandroid_logger_plugin.la
endif
+
+libjson_tracer_plugin_la_SOURCES = logger/json.c
+logger_LTLIBRARIES += libjson_tracer_plugin.la
=====================================
modules/logger/json.c
=====================================
@@ -0,0 +1,270 @@
+/*****************************************************************************
+ * json.c: JSON tracer plugin
+ *****************************************************************************
+ * Copyright © 2021 Videolabs
+ *
+ * Authors : Nicolas Le Quec
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_fs.h>
+#include <vlc_charset.h>
+#include <vlc_tracer.h>
+#include <vlc_memstream.h>
+
+#include <stdbool.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <assert.h>
+#include <ctype.h>
+
+#define JSON_FILENAME "vlc-log.json"
+
+typedef struct
+{
+ FILE *stream;
+} vlc_tracer_sys_t;
+
+static void PrintUTF8Char(FILE *stream, uint32_t character)
+{
+ /* If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF),
+ then it may be represented as a six-character sequence: \uxxxx */
+ if (character < 0x10000)
+ {
+ fprintf(stream, "\\u%04x", character);
+ }
+ /* To escape an extended character that is not in the Basic Multilingual
+ Plane, the character is represented as a 12-character sequence, encoding
+ the UTF-16 surrogate pair. */
+
+ else if (0x10000 <= character && character <= 0x10FFFF) {
+ unsigned int code;
+ uint16_t units[2];
+
+ code = (character - 0x10000);
+ units[0] = 0xD800 | (code >> 10);
+ units[1] = 0xDC00 | (code & 0x3FF);
+
+ fprintf(stream, "\\u%04x\\u%04x", units[0], units[1]);
+ }
+}
+
+static void JsonPrintString(FILE *stream, const char *str)
+{
+ if (!IsUTF8(str))
+ {
+ fputs("\"invalid string\"", stream);
+ return;
+ }
+
+ fputc('\"', stream);
+
+ unsigned char byte;
+ while (*str != '\0')
+ {
+ switch (*str)
+ {
+ case '/':
+ fputs("\\/", stream);
+ break;
+ case '\b':
+ fputs("\\b", stream);
+ break;
+ case '\f':
+ fputs("\\f", stream);
+ break;
+ case '\n':
+ fputs("\\n", stream);
+ break;
+ case '\r':
+ fputs("\\r", stream);
+ break;
+ case '\t':
+ fputs("\\t", stream);
+ break;
+ case '\\':
+ case '\"':
+ fprintf(stream, "\\%c", *str);
+ break;
+ default:
+ byte = *str;
+ if (byte <= 0x1F || byte == 0x7F)
+ {
+ fprintf(stream, "\\u%04x", byte);
+ }
+ else if (byte < 0x80)
+ {
+ fputc(byte, stream);
+ }
+ else
+ {
+ uint32_t bytes;
+ size_t len = vlc_towc(str, &bytes);
+ PrintUTF8Char(stream, bytes);
+ str += len - 1;
+ }
+ }
+ str++;
+ }
+ fputc('\"', stream);
+}
+
+static void JsonPrintKeyValueNumber(FILE *stream, const char *key, int64_t value)
+{
+ JsonPrintString(stream, key);
+ fprintf(stream, ": \"%"PRId64"\"", value);
+}
+
+static void JsonPrintKeyValueLabel(FILE *stream, const char *key, const char *value)
+{
+ JsonPrintString(stream, key);
+ fputs(": ", stream);
+ JsonPrintString(stream, value);
+}
+
+static void JsonStartObjectSection(FILE *stream, const char* name)
+{
+ if (name != NULL)
+ fprintf(stream, "\"%s\": {", name);
+ else
+ fputc('{', stream);
+}
+
+static void JsonEndObjectSection(FILE *stream)
+{
+ fputc('}', stream);
+}
+
+static void TraceJson(void *opaque, va_list entries)
+{
+ vlc_tracer_sys_t *sys = opaque;
+ FILE* stream = sys->stream;
+
+ flockfile(stream);
+ JsonStartObjectSection(stream, NULL);
+ JsonPrintKeyValueNumber(stream, "Timestamp", US_FROM_VLC_TICK(vlc_tick_now()));
+ fputc(',', stream);
+
+ JsonStartObjectSection(stream, "Body");
+
+ struct vlc_tracer_entry entry = va_arg(entries, struct vlc_tracer_entry);
+ while (entry.key != NULL)
+ {
+ switch (entry.type)
+ {
+ case VLC_TRACER_INT:
+ JsonPrintKeyValueNumber(stream, entry.key, entry.value.integer);
+ break;
+ case VLC_TRACER_STRING:
+ JsonPrintKeyValueLabel(stream, entry.key, entry.value.string);
+ break;
+ default:
+ vlc_assert_unreachable();
+ break;
+ }
+ entry = va_arg(entries, struct vlc_tracer_entry);
+ if (entry.key != NULL)
+ {
+ fputc(',', stream);
+ }
+ }
+ JsonEndObjectSection(stream);
+ JsonEndObjectSection(stream);
+ fputc('\n', stream);
+ funlockfile(stream);
+}
+
+static void Close(void *opaque)
+{
+ vlc_tracer_sys_t *sys = opaque;
+
+ free(sys);
+}
+
+static const struct vlc_tracer_operations json_ops =
+{
+ TraceJson,
+ Close
+};
+
+static const struct vlc_tracer_operations *Open(vlc_object_t *obj,
+ void **restrict sysp)
+{
+ vlc_tracer_sys_t *sys = malloc(sizeof (*sys));
+ if (unlikely(sys == NULL))
+ return NULL;
+
+ const struct vlc_tracer_operations *ops = &json_ops;
+
+ const char *filename = JSON_FILENAME;
+
+ char *path = var_InheritString(obj, "json-tracer-file");
+#ifdef __APPLE__
+ if (path == NULL)
+ {
+ char *home = config_GetUserDir(VLC_HOME_DIR);
+ if (home != NULL)
+ {
+ if (asprintf(&path, "%s/Library/Logs/"JSON_FILENAME, home) == -1)
+ path = NULL;
+ free(home);
+ }
+ }
+#endif
+ if (path != NULL)
+ filename = path;
+
+ /* Open the log file and remove any buffering for the stream */
+ msg_Dbg(obj, "opening logfile `%s'", filename);
+ sys->stream = vlc_fopen(filename, "at");
+ if (sys->stream == NULL)
+ {
+ msg_Err(obj, "error opening log file `%s': %s", filename,
+ vlc_strerror_c(errno) );
+ free(path);
+ free(sys);
+ return NULL;
+ }
+ free(path);
+
+ setvbuf(sys->stream, NULL, _IOLBF, 0);
+
+ *sysp = sys;
+ return ops;
+}
+
+#define FILE_LOG_TEXT N_("Log to file")
+#define FILE_LOG_LONGTEXT N_("Log all VLC traces to a json file.")
+
+#define LOGFILE_NAME_TEXT N_("Log filename")
+#define LOGFILE_NAME_LONGTEXT N_("Specify the log filename.")
+
+vlc_module_begin()
+ set_shortname(N_("Tracer"))
+ set_description(N_("JSON tracer"))
+ set_category(CAT_ADVANCED)
+ set_subcategory(SUBCAT_ADVANCED_MISC)
+ set_capability("tracer", 0)
+ set_callback(Open)
+
+ add_savefile("json-tracer-file", NULL, LOGFILE_NAME_TEXT, LOGFILE_NAME_LONGTEXT)
+vlc_module_end()
=====================================
src/Makefile.am
=====================================
@@ -70,6 +70,7 @@ pluginsinclude_HEADERS = \
../include/vlc_media_source.h \
../include/vlc_memstream.h \
../include/vlc_messages.h \
+ ../include/vlc_tracer.h \
../include/vlc_meta.h \
../include/vlc_meta_fetcher.h \
../include/vlc_mime.h \
@@ -378,6 +379,7 @@ libvlccore_la_SOURCES = \
misc/events.c \
misc/image.c \
misc/messages.c \
+ misc/tracer.c \
misc/mime.c \
misc/objects.c \
misc/objres.c \
=====================================
src/clock/clock.c
=====================================
@@ -25,12 +25,14 @@
#include <vlc_aout.h>
#include <assert.h>
#include <limits.h>
+#include <vlc_tracer.h>
#include "clock.h"
#include "clock_internal.h"
struct vlc_clock_main_t
{
struct vlc_logger *logger;
+ struct vlc_tracer *tracer;
vlc_mutex_t lock;
vlc_cond_t cond;
@@ -72,6 +74,7 @@ struct vlc_clock_t
vlc_clock_main_t *owner;
vlc_tick_t delay;
unsigned priority;
+ const char *track_str_id;
const struct vlc_clock_cbs *cbs;
void *cbs_data;
@@ -105,9 +108,15 @@ static inline void vlc_clock_on_update(vlc_clock_t *clock,
unsigned frame_rate,
unsigned frame_rate_base)
{
+ vlc_clock_main_t *main_clock = clock->owner;
if (clock->cbs)
clock->cbs->on_update(system_now, ts, rate, frame_rate, frame_rate_base,
clock->cbs_data);
+
+ if (main_clock->tracer != NULL && clock->track_str_id)
+ {
+ vlc_tracer_TraceRender(main_clock->tracer, "RENDER", clock->track_str_id, ts, system_now);
+ }
}
static vlc_tick_t vlc_clock_master_update(vlc_clock_t *clock,
@@ -385,7 +394,7 @@ void vlc_clock_Wake(vlc_clock_t *clock)
vlc_cond_broadcast(&main_clock->cond);
}
-vlc_clock_main_t *vlc_clock_main_New(struct vlc_logger *parent_logger)
+vlc_clock_main_t *vlc_clock_main_New(struct vlc_logger *parent_logger, struct vlc_tracer *parent_tracer)
{
vlc_clock_main_t *main_clock = malloc(sizeof(vlc_clock_main_t));
@@ -398,6 +407,7 @@ vlc_clock_main_t *vlc_clock_main_New(struct vlc_logger *parent_logger)
free(main_clock);
return NULL;
}
+ main_clock->tracer = parent_tracer;
vlc_mutex_init(&main_clock->lock);
vlc_cond_init(&main_clock->cond);
@@ -547,6 +557,7 @@ static void vlc_clock_set_slave_callbacks(vlc_clock_t *clock)
}
static vlc_clock_t *vlc_clock_main_Create(vlc_clock_main_t *main_clock,
+ const char* track_str_id,
unsigned priority,
const struct vlc_clock_cbs *cbs,
void *cbs_data)
@@ -556,6 +567,7 @@ static vlc_clock_t *vlc_clock_main_Create(vlc_clock_main_t *main_clock,
return NULL;
clock->owner = main_clock;
+ clock->track_str_id = track_str_id;
clock->delay = 0;
clock->cbs = cbs;
clock->cbs_data = cbs_data;
@@ -566,11 +578,12 @@ static vlc_clock_t *vlc_clock_main_Create(vlc_clock_main_t *main_clock,
}
vlc_clock_t *vlc_clock_main_CreateMaster(vlc_clock_main_t *main_clock,
+ const char *track_str_id,
const struct vlc_clock_cbs *cbs,
void *cbs_data)
{
/* The master has always the 0 priority */
- vlc_clock_t *clock = vlc_clock_main_Create(main_clock, 0, cbs, cbs_data);
+ vlc_clock_t *clock = vlc_clock_main_Create(main_clock, track_str_id, 0, cbs, cbs_data);
if (!clock)
return NULL;
@@ -592,7 +605,7 @@ vlc_clock_t *vlc_clock_main_CreateMaster(vlc_clock_main_t *main_clock,
vlc_clock_t *vlc_clock_main_CreateInputMaster(vlc_clock_main_t *main_clock)
{
/* The master has always the 0 priority */
- vlc_clock_t *clock = vlc_clock_main_Create(main_clock, 0, NULL, NULL);
+ vlc_clock_t *clock = vlc_clock_main_Create(main_clock, NULL, 0, NULL, NULL);
if (!clock)
return NULL;
@@ -616,6 +629,7 @@ vlc_clock_t *vlc_clock_main_CreateInputMaster(vlc_clock_main_t *main_clock)
}
vlc_clock_t *vlc_clock_main_CreateSlave(vlc_clock_main_t *main_clock,
+ const char* track_str_id,
enum es_format_category_e cat,
const struct vlc_clock_cbs *cbs,
void *cbs_data)
@@ -637,7 +651,7 @@ vlc_clock_t *vlc_clock_main_CreateSlave(vlc_clock_main_t *main_clock,
break;
}
- vlc_clock_t *clock = vlc_clock_main_Create(main_clock, priority, cbs,
+ vlc_clock_t *clock = vlc_clock_main_Create(main_clock, track_str_id, priority, cbs,
cbs_data);
if (!clock)
return NULL;
@@ -653,7 +667,7 @@ vlc_clock_t *vlc_clock_main_CreateSlave(vlc_clock_main_t *main_clock,
vlc_clock_t *vlc_clock_CreateSlave(const vlc_clock_t *clock,
enum es_format_category_e cat)
{
- return vlc_clock_main_CreateSlave(clock->owner, cat, NULL, NULL);
+ return vlc_clock_main_CreateSlave(clock->owner, clock->track_str_id, cat, NULL, NULL);
}
void vlc_clock_Delete(vlc_clock_t *clock)
=====================================
src/clock/clock.h
=====================================
@@ -58,7 +58,7 @@ struct vlc_clock_cbs
/**
* This function creates the vlc_clock_main_t of the program
*/
-vlc_clock_main_t *vlc_clock_main_New(struct vlc_logger *parent_logger);
+vlc_clock_main_t *vlc_clock_main_New(struct vlc_logger *parent_logger, struct vlc_tracer *parent_tracer);
/**
* Destroy the clock main
@@ -97,6 +97,7 @@ void vlc_clock_main_ChangePause(vlc_clock_main_t *clock, vlc_tick_t system_now,
* You must use vlc_clock_Delete to free it.
*/
vlc_clock_t *vlc_clock_main_CreateMaster(vlc_clock_main_t *main_clock,
+ const char *track_str_id,
const struct vlc_clock_cbs *cbs,
void *cbs_data);
@@ -118,6 +119,7 @@ vlc_clock_t *vlc_clock_main_CreateInputMaster(vlc_clock_main_t *main_clock);
* You must use vlc_clock_Delete to free it.
*/
vlc_clock_t *vlc_clock_main_CreateSlave(vlc_clock_main_t *main_clock,
+ const char *track_str_id,
enum es_format_category_e cat,
const struct vlc_clock_cbs *cbs,
void *cbs_data);
=====================================
src/input/decoder.c
=====================================
@@ -43,6 +43,7 @@
#include <vlc_modules.h>
#include <vlc_decoder.h>
#include <vlc_picture_pool.h>
+#include <vlc_tracer.h>
#include "audio_output/aout_internal.h"
#include "stream_output/stream_output.h"
@@ -68,6 +69,7 @@ struct vlc_input_decoder_t
decoder_t dec;
input_resource_t*p_resource;
vlc_clock_t *p_clock;
+ const char *psz_id;
const struct vlc_input_decoder_callbacks *cbs;
void *cbs_userdata;
@@ -1113,7 +1115,13 @@ static void ModuleThread_QueueVideo( decoder_t *p_dec, picture_t *p_pic )
{
assert( p_pic );
vlc_input_decoder_t *p_owner = dec_get_owner( p_dec );
+ struct vlc_tracer *tracer = vlc_object_get_tracer( &p_dec->obj );
+ if ( tracer != NULL )
+ {
+ vlc_tracer_TraceStreamPTS( tracer, "DEC", p_owner->psz_id,
+ "OUT", p_pic->date );
+ }
int success = ModuleThread_PlayVideo( p_owner, p_pic );
ModuleThread_UpdateStatVideo( p_owner, success != VLC_SUCCESS );
@@ -1242,7 +1250,13 @@ static void ModuleThread_UpdateStatAudio( vlc_input_decoder_t *p_owner,
static void ModuleThread_QueueAudio( decoder_t *p_dec, block_t *p_aout_buf )
{
vlc_input_decoder_t *p_owner = dec_get_owner( p_dec );
+ struct vlc_tracer *tracer = vlc_object_get_tracer( &p_dec->obj );
+ if ( tracer != NULL && p_aout_buf != NULL )
+ {
+ vlc_tracer_TraceStreamDTS( tracer, "DEC", p_owner->psz_id, "OUT",
+ p_aout_buf->i_pts, p_aout_buf->i_dts );
+ }
int success = ModuleThread_PlayAudio( p_owner, p_aout_buf );
ModuleThread_UpdateStatAudio( p_owner, success != VLC_SUCCESS );
@@ -1280,6 +1294,13 @@ static void ModuleThread_QueueSpu( decoder_t *p_dec, subpicture_t *p_spu )
{
assert( p_spu );
vlc_input_decoder_t *p_owner = dec_get_owner( p_dec );
+ struct vlc_tracer *tracer = vlc_object_get_tracer( &p_dec->obj );
+
+ if ( tracer != NULL && p_spu != NULL )
+ {
+ vlc_tracer_TraceStreamPTS( tracer, "DEC", p_owner->psz_id,
+ "OUT", p_spu->i_start );
+ }
/* The vout must be created from a previous decoder_NewSubpicture call. */
assert( p_owner->p_vout );
@@ -1304,6 +1325,13 @@ static void DecoderThread_ProcessInput( vlc_input_decoder_t *p_owner, block_t *p
static void DecoderThread_DecodeBlock( vlc_input_decoder_t *p_owner, block_t *p_block )
{
decoder_t *p_dec = &p_owner->dec;
+ struct vlc_tracer *tracer = vlc_object_get_tracer( &p_dec->obj );
+
+ if ( tracer != NULL && p_block != NULL )
+ {
+ vlc_tracer_TraceStreamDTS( tracer, "DEC", p_owner->psz_id, "IN",
+ p_block->i_pts, p_block->i_dts );
+ }
int ret = p_dec->pf_decode( p_dec, p_block );
switch( ret )
@@ -1769,8 +1797,8 @@ static const struct decoder_owner_callbacks dec_spu_cbs =
* \return the decoder object
*/
static vlc_input_decoder_t *
-CreateDecoder( vlc_object_t *p_parent,
- const es_format_t *fmt, vlc_clock_t *p_clock,
+CreateDecoder( vlc_object_t *p_parent, const es_format_t *fmt,
+ const char *psz_id, vlc_clock_t *p_clock,
input_resource_t *p_resource, sout_stream_t *p_sout,
bool b_thumbnailing, const struct vlc_input_decoder_callbacks *cbs,
void *cbs_userdata )
@@ -1785,6 +1813,7 @@ CreateDecoder( vlc_object_t *p_parent,
return NULL;
p_dec = &p_owner->dec;
+ p_owner->psz_id = psz_id;
p_owner->p_clock = p_clock;
p_owner->i_preroll_end = PREROLL_NONE;
p_owner->p_resource = p_resource;
@@ -2028,7 +2057,7 @@ static void DecoderUnsupportedCodec( decoder_t *p_dec, const es_format_t *fmt, b
/* TODO: pass p_sout through p_resource? -- Courmisch */
static vlc_input_decoder_t *
-decoder_New( vlc_object_t *p_parent, const es_format_t *fmt,
+decoder_New( vlc_object_t *p_parent, const es_format_t *fmt, const char *psz_id,
vlc_clock_t *p_clock, input_resource_t *p_resource,
sout_stream_t *p_sout, bool thumbnailing,
const struct vlc_input_decoder_callbacks *cbs, void *userdata)
@@ -2038,7 +2067,7 @@ decoder_New( vlc_object_t *p_parent, const es_format_t *fmt,
/* Create the decoder configuration structure */
vlc_input_decoder_t *p_owner =
- CreateDecoder( p_parent, fmt, p_clock, p_resource, p_sout,
+ CreateDecoder( p_parent, fmt, psz_id, p_clock, p_resource, p_sout,
thumbnailing, cbs, userdata );
if( p_owner == NULL )
{
@@ -2102,12 +2131,13 @@ decoder_New( vlc_object_t *p_parent, const es_format_t *fmt,
*/
vlc_input_decoder_t *
vlc_input_decoder_New( vlc_object_t *parent, es_format_t *fmt,
- vlc_clock_t *p_clock, input_resource_t *resource,
+ const char *psz_id, vlc_clock_t *p_clock,
+ input_resource_t *resource,
sout_stream_t *p_sout, bool thumbnailing,
const struct vlc_input_decoder_callbacks *cbs,
void *cbs_userdata)
{
- return decoder_New( parent, fmt, p_clock, resource, p_sout, thumbnailing,
+ return decoder_New( parent, fmt, psz_id, p_clock, resource, p_sout, thumbnailing,
cbs, cbs_userdata );
}
@@ -2118,7 +2148,7 @@ vlc_input_decoder_t *
vlc_input_decoder_Create( vlc_object_t *p_parent, const es_format_t *fmt,
input_resource_t *p_resource )
{
- return decoder_New( p_parent, fmt, NULL, p_resource, NULL, false, NULL,
+ return decoder_New( p_parent, fmt, NULL, NULL, p_resource, NULL, false, NULL,
NULL );
}
@@ -2371,9 +2401,9 @@ int vlc_input_decoder_SetCcState( vlc_input_decoder_t *p_owner, vlc_fourcc_t cod
es_format_Init( &fmt, SPU_ES, codec );
fmt.subs.cc.i_channel = i_channel;
fmt.subs.cc.i_reorder_depth = p_owner->cc.desc.i_reorder_depth;
- p_ccowner = vlc_input_decoder_New( VLC_OBJECT(p_dec), &fmt, p_owner->p_clock,
- p_owner->p_resource, p_owner->p_sout, false,
- NULL, NULL );
+ p_ccowner = vlc_input_decoder_New( VLC_OBJECT(p_dec), &fmt, p_owner->psz_id,
+ p_owner->p_clock, p_owner->p_resource, p_owner->p_sout,
+ false, NULL, NULL );
if( !p_ccowner )
{
msg_Err( p_dec, "could not create decoder" );
=====================================
src/input/decoder.h
=====================================
@@ -51,7 +51,7 @@ struct vlc_input_decoder_callbacks {
};
vlc_input_decoder_t *
-vlc_input_decoder_New( vlc_object_t *parent, es_format_t *, vlc_clock_t *,
+vlc_input_decoder_New( vlc_object_t *parent, es_format_t *, const char *psz_id, vlc_clock_t *,
input_resource_t *, sout_stream_t *, bool thumbnailing,
const struct vlc_input_decoder_callbacks *cbs,
void *userdata ) VLC_USED;
=====================================
src/input/es_out.c
=====================================
@@ -40,6 +40,7 @@
#include <vlc_list.h>
#include <vlc_decoder.h>
#include <vlc_memstream.h>
+#include <vlc_tracer.h>
#include "input_internal.h"
#include "../clock/input_clock.h"
@@ -845,7 +846,8 @@ static int EsOutSetRecord( es_out_t *out, bool b_record )
continue;
p_es->p_dec_record =
- vlc_input_decoder_New( VLC_OBJECT(p_input), &p_es->fmt, NULL,
+ vlc_input_decoder_New( VLC_OBJECT(p_input), &p_es->fmt,
+ p_es->id.str_id, NULL,
input_priv(p_input)->p_resource,
p_sys->p_sout_record, false,
&decoder_cbs, p_es );
@@ -1498,7 +1500,8 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, input_source_t *source, in
p_pgrm->p_master_es_clock = NULL;
p_pgrm->active_clock_source = VLC_CLOCK_MASTER_AUTO;
- p_pgrm->p_main_clock = vlc_clock_main_New( p_input->obj.logger );
+ struct vlc_tracer *tracer = vlc_object_get_tracer( &p_input->obj );
+ p_pgrm->p_main_clock = vlc_clock_main_New( p_input->obj.logger, tracer );
if( !p_pgrm->p_main_clock )
{
free( p_pgrm );
@@ -2313,12 +2316,14 @@ static void EsOutCreateDecoder( es_out_t *out, es_out_id_t *p_es )
p_es->master = true;
p_es->p_pgrm->p_master_es_clock = p_es->p_clock =
vlc_clock_main_CreateMaster( p_es->p_pgrm->p_main_clock,
+ p_es->id.str_id,
&clock_cbs, p_es );
}
else
{
p_es->master = false;
p_es->p_clock = vlc_clock_main_CreateSlave( p_es->p_pgrm->p_main_clock,
+ p_es->id.str_id,
p_es->fmt.i_cat,
&clock_cbs, p_es );
}
@@ -2330,7 +2335,8 @@ static void EsOutCreateDecoder( es_out_t *out, es_out_id_t *p_es )
}
input_thread_private_t *priv = input_priv(p_input);
- dec = vlc_input_decoder_New( VLC_OBJECT(p_input), &p_es->fmt, p_es->p_clock,
+ dec = vlc_input_decoder_New( VLC_OBJECT(p_input), &p_es->fmt,
+ p_es->id.str_id, p_es->p_clock,
priv->p_resource, priv->p_sout,
priv->b_thumbnailing, &decoder_cbs, p_es );
if( dec != NULL )
@@ -2343,7 +2349,8 @@ static void EsOutCreateDecoder( es_out_t *out, es_out_id_t *p_es )
if( !p_es->p_master && p_sys->p_sout_record )
{
p_es->p_dec_record =
- vlc_input_decoder_New( VLC_OBJECT(p_input), &p_es->fmt, NULL,
+ vlc_input_decoder_New( VLC_OBJECT(p_input), &p_es->fmt,
+ p_es->id.str_id, NULL,
priv->p_resource, p_sys->p_sout_record,
false, &decoder_cbs, p_es );
if( p_es->p_dec_record && p_sys->b_buffering )
@@ -2895,6 +2902,13 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
input_thread_t *p_input = p_sys->p_input;
assert( p_block->p_next == NULL );
+ struct vlc_tracer *tracer = vlc_object_get_tracer( &p_input->obj );
+
+ if ( tracer != NULL )
+ {
+ vlc_tracer_TraceStreamDTS( tracer, "DEMUX", es->id.str_id, "OUT",
+ p_block->i_pts, p_block->i_dts);
+ }
struct input_stats *stats = input_priv(p_input)->stats;
if( stats != NULL )
@@ -3342,6 +3356,11 @@ static int EsOutVaControlLocked( es_out_t *out, input_source_t *source,
p_pgrm->i_last_pcr = i_pcr;
+ struct vlc_tracer *tracer = vlc_object_get_tracer( &p_sys->p_input->obj );
+ if ( tracer != NULL )
+ {
+ vlc_tracer_TracePCR(tracer, "DEMUX", "PCR", i_pcr);
+ }
input_thread_private_t *priv = input_priv(p_sys->p_input);
/* TODO do not use vlc_tick_now() but proper stream acquisition date */
=====================================
src/libvlc-module.c
=====================================
@@ -1085,6 +1085,10 @@ static const char* const ppsz_restore_playback_desc[] = {
"You can select which VoD server module you want to use. Set this " \
"to 'vod_rtsp' to switch back to the old, legacy module." )
+#define TRACER_TEXT N_("Tracer module")
+#define TRACER_LONGTEXT N_( \
+ "This allow to select which tracer module you want to use." )
+
#define VLM_CONF_TEXT N_("VLM configuration file")
#define VLM_CONF_LONGTEXT N_( \
"Read a VLM configuration file as soon as VLM is started." )
@@ -2058,6 +2062,8 @@ vlc_module_begin ()
set_section( N_("Special modules"), NULL )
add_module("vod-server", "vod server", NULL,
VOD_SERVER_TEXT, VOD_SERVER_LONGTEXT)
+ add_module("tracer", "tracer", NULL,
+ TRACER_TEXT, TRACER_LONGTEXT)
set_section( N_("Plugins" ), NULL )
#ifdef HAVE_DYNAMIC_PLUGINS
=====================================
src/libvlc.c
=====================================
@@ -179,6 +179,7 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
goto error;
vlc_LogInit(p_libvlc);
+ vlc_tracer_Init(p_libvlc);
/*
* Support for gettext
@@ -389,6 +390,7 @@ void libvlc_InternalCleanup( libvlc_int_t *p_libvlc )
config_AutoSaveConfigFile( VLC_OBJECT(p_libvlc) );
vlc_LogDestroy(p_libvlc->obj.logger);
+ vlc_tracer_Destroy(p_libvlc);
/* Free module bank. It is refcounted, so we call this each time */
module_EndBank (true);
#if defined(_WIN32) || defined(__OS2__)
=====================================
src/libvlc.h
=====================================
@@ -59,6 +59,14 @@ typedef struct vlc_logger vlc_logger_t;
int vlc_LogPreinit(libvlc_int_t *) VLC_USED;
void vlc_LogInit(libvlc_int_t *);
+/*
+ * Tracing
+ */
+typedef struct vlc_tracer vlc_tracer_t;
+
+void vlc_tracer_Init(libvlc_int_t *);
+void vlc_tracer_Destroy(libvlc_int_t *);
+
/*
* LibVLC exit event handling
*/
@@ -185,6 +193,7 @@ typedef struct libvlc_priv_t
vlc_actions_t *actions; ///< Hotkeys handler
struct vlc_medialibrary_t *p_media_library; ///< Media library instance
struct vlc_thumbnailer_t *p_thumbnailer; ///< Lazily instantiated media thumbnailer
+ struct vlc_tracer *tracer; ///< Tracer callbacks
/* Exit callback */
vlc_exit_t exit;
=====================================
src/libvlccore.sym
=====================================
@@ -279,6 +279,7 @@ vlc_memstream_printf
vlc_Log
vlc_LogSet
vlc_vaLog
+vlc_tracer_Trace
vlc_LogHeaderCreate
vlc_LogDestroy
vlc_strerror
@@ -642,6 +643,7 @@ vlc_object_create
vlc_object_delete
vlc_object_typename
vlc_object_parent
+vlc_object_get_tracer
vlc_object_Log
vlc_object_vaLog
vlc_once
=====================================
src/misc/objects.c
=====================================
@@ -116,6 +116,13 @@ vlc_object_t *(vlc_object_parent)(vlc_object_t *obj)
return vlc_internals(obj)->parent;
}
+struct vlc_tracer *vlc_object_get_tracer(vlc_object_t *obj)
+{
+ libvlc_int_t *vlc = vlc_object_instance(obj);
+ libvlc_priv_t *vlc_priv = libvlc_priv(vlc);
+ return vlc_priv->tracer;
+}
+
void vlc_object_deinit(vlc_object_t *obj)
{
vlc_object_internals_t *priv = vlc_internals(obj);
=====================================
src/misc/tracer.c
=====================================
@@ -0,0 +1,118 @@
+/*****************************************************************************
+ * tracer.c: tracing interface
+ * This library provides an interface to the traces to be used by other
+ * modules. See vlc_config.h for output configuration.
+ *****************************************************************************
+ * Copyright (C) 2021 VLC authors and VideoLAN
+ *
+ * This program 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 program 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 program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#include <vlc_common.h>
+#include <vlc_modules.h>
+#include <vlc_tracer.h>
+#include "../libvlc.h"
+
+struct vlc_tracer {
+ const struct vlc_tracer_operations *ops;
+};
+
+/**
+ * Module-based message trace.
+ */
+struct vlc_tracer_module {
+ struct vlc_object_t obj;
+ struct vlc_tracer tracer;
+ void *opaque;
+};
+
+void vlc_tracer_Trace(struct vlc_tracer *tracer, ...)
+{
+ assert(tracer->ops->trace != NULL);
+ struct vlc_tracer_module *module =
+ container_of(tracer, struct vlc_tracer_module, tracer);
+
+ /* Pass message to the callback */
+ va_list entries;
+ va_start(entries, tracer);
+ tracer->ops->trace(module->opaque, entries);
+ va_end(entries);
+}
+
+static int vlc_tracer_load(void *func, bool forced, va_list ap)
+{
+ const struct vlc_tracer_operations *(*activate)(vlc_object_t *,
+ void **) = func;
+ struct vlc_tracer_module *module = va_arg(ap, struct vlc_tracer_module *);
+
+ (void) forced;
+ module->tracer.ops = activate(VLC_OBJECT(module), &module->opaque);
+ return (module->tracer.ops != NULL) ? VLC_SUCCESS : VLC_EGENERIC;
+}
+
+static struct vlc_tracer *vlc_TraceModuleCreate(vlc_object_t *parent)
+{
+ struct vlc_tracer_module *module;
+
+ module = vlc_custom_create(parent, sizeof (*module), "tracer");
+ if (unlikely(module == NULL))
+ return NULL;
+
+ char *module_name = var_InheritString(parent, "tracer");
+ if (vlc_module_load(VLC_OBJECT(module), "tracer", module_name, false,
+ vlc_tracer_load, module) == NULL) {
+ vlc_object_delete(VLC_OBJECT(module));
+ if (module_name)
+ free(module_name);
+ return NULL;
+ }
+ if (module_name)
+ free(module_name);
+
+ return &module->tracer;
+}
+
+/**
+ * Initializes the messages tracing system */
+void vlc_tracer_Init(libvlc_int_t *vlc)
+{
+ struct vlc_tracer *tracer = vlc_TraceModuleCreate(VLC_OBJECT(vlc));
+ libvlc_priv_t *vlc_priv = libvlc_priv(vlc);
+ vlc_priv->tracer = tracer;
+}
+
+void vlc_tracer_Destroy(libvlc_int_t *vlc)
+{
+ libvlc_priv_t *vlc_priv = libvlc_priv(vlc);
+
+ if (vlc_priv->tracer != NULL)
+ {
+ struct vlc_tracer_module *module =
+ container_of(vlc_priv->tracer, struct vlc_tracer_module, tracer);
+
+ if (module->tracer.ops->destroy != NULL)
+ module->tracer.ops->destroy(module->opaque);
+
+ vlc_object_delete(VLC_OBJECT(module));
+ }
+}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/50728ae64510294784371335fafe8f7d575251fb...f55348fd9b90335ae39669c77de493954fb763ce
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/50728ae64510294784371335fafe8f7d575251fb...f55348fd9b90335ae39669c77de493954fb763ce
You're receiving this email because of your account on code.videolan.org.
More information about the vlc-commits
mailing list