GStreamer基础教程13 - 调试Pipeline
摘要
在很多情况下,我们需要对GStreamer创建的Pipeline进行调试,来了解其运行机制以解决所遇到的问题。为此,GStreamer提供了相应的调试机制,方便我们快速定位问题。
查看调试日志
使用GST_DEBUG环境变量查看日志
GStreamer框架以及其插件提供了不同级别的日志信息,日志中包含时间戳,进程ID,线程ID,类型,源码行数,函数名,Element信息以及相应的日志消息。例如:
$ GST_DEBUG= gst-launch-1.0 playbin uri=file:///x.mp3
Setting pipeline to PAUSED ...
::00.014898047 0x2159d80 WARN filesrc gstfilesrc.c::gst_file_src_start:<source> error: No such file "/x.mp3"
...
我们可以发现,只需要在运行时指定GST_DEBUG环境变量,并设置日志级别,即可得到相应的日志。由于GStreamer提供了丰富的日志,如果我们打开所有的日志,必定会对程序的性能有所影响,所以我们需要对日志进行分级,GStreamer提供了8种级别,用于输出不同类型的日志。
- 级别0:不输出任何日志信息。
- 级别1:ERROR信息。
- 级别2:WARNING信息。
- 级别3:FIXME信息。
- 级别4:INFO信息。
- 级别5:DEBUG信息
- 级别6:LOG信息。
- 级别7:TRACE信息。
- 级别8:MEMDUMP信息,最高级别日志。
在使用时,我们只需将GST_DEBUG设置为相应级别,所有小于其级别的信息都会被输出,例如:设置GST_DEBUG=2,我们会得到ERROR及WARNING级别的日志。
上面的例子中,所有模块使用同一日志级别,除此之外,我们还可以针对某个插件设定其独有的日志级别,例如:GST_DEBUG=2,audiotestsrc:6 只会将audiotestsrc的日志级别设置为6,其他的模块仍然使用级别2。
这样,GST_DEBUG的值是以逗号分隔的”模块名:级别“的键值对,可以在最开始增加其他未指定模块的默认日志级别,多个模块名可以使用逗号隔开。同时,GST_DEBUG的值还支持”*“通配符。
例如:GST_DEBUG=2,audio*:6会将模块名以audio开始的模块的日志级别设置为6,其他的默认为2。
同样,GST_DEBUG=*:2 会匹配所有的模块,与GST_DEBUG=2等同。
我们可以通过gst-launch-1.0 --gst-debug-help 列出当前所注册的模块名,模块名由插件注册。在安装的插件改变时,此命令输出结果也会变化。
使用GST_DEBUG_FILE将日志输出到文件
在实际中,我们通常将日志保存在文件中,便于后续分析。我们可以使用GST_DEBUG_FILE环境变量,指定日志文件名,GStreamer会自动将日志写入文件中,由于GStreamer日志包含终端色彩代码,我们通常使用 GST_DEBUG_NO_COLOR=1 环境变量将其禁用,方便查看。使用方式如下:
$ GST_DEBUG_NO_COLOR= GST_DEBUG_FILE=pipeline.log GST_DEBUG= gst-launch-1.0 audiotestsrc ! autoaudiosink
使用自定义日志接口
在实际项目中,不同应用可能采用不同的日志接口,为此,GStreamer提供了相应的接口,应用程序可以在初始化时,通过gst_debug_add_log_function()增加自定义日志接口。相关接口如下:
//Add customized log function to GStreamer log system.
void gst_debug_add_log_function (GstLogFunction func,
gpointer user_data,
GDestroyNotify notify); // Function prototype for a logging function that can be registered with
// gst_debug_add_log_function()
// Use G_GNUC_NO_INSTRUMENT on that function.
typedef void (*GstLogFunction) (GstDebugCategory * category,
GstDebugLevel level,
const gchar * file,
const gchar * function,
gint line,
GObject * object,
GstDebugMessage * message,
gpointer user_data); // Enable log if set to true.
void gst_debug_set_active (gboolean active);
// Set the default log level.
void gst_debug_set_default_threshold (GstDebugLevel level);
示例代码如下:
#include <gst/gst.h>
#include <stdio.h> /* declare log function with the required attribute */
void my_log_func(GstDebugCategory * category,
GstDebugLevel level,
const gchar * file,
const gchar * function,
gint line,
GObject * object,
GstDebugMessage * message,
gpointer user_data) G_GNUC_NO_INSTRUMENT; void my_log_func(GstDebugCategory * category,
GstDebugLevel level,
const gchar * file,
const gchar * function,
gint line,
GObject * object,
GstDebugMessage * message,
gpointer user_data) { printf("MyLogFunc: [Level:%d] %s:%s:%d %s\n",
level, file, function, line,
gst_debug_message_get(message)); } int main(int argc, char *argv[]) {
GstPipeline *pipeline = NULL;
GMainLoop *main_loop = NULL; /* set log function and remove the default one */
gst_debug_add_log_function(my_log_func, NULL, NULL);
gst_debug_set_active(TRUE);
gst_debug_set_default_threshold(GST_LEVEL_INFO); /* Initialize GStreamer */
gst_init (&argc, &argv); /* default log function is added by gst_init, so we need remove it after that. */
gst_debug_remove_log_function(gst_debug_log_default); pipeline = (GstPipeline *)gst_parse_launch("audiotestsrc ! autoaudiosink", NULL); /* Start playing */
gst_element_set_state (GST_ELEMENT(pipeline), GST_STATE_PLAYING); main_loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (main_loop); /* Free resources */
g_main_loop_unref (main_loop);
gst_element_set_state (GST_ELEMENT(pipeline), GST_STATE_NULL);
gst_object_unref (pipeline); return ;
}
编译运行后,会得到指定函数输出的log。
$ gcc basic-tutorial-13a.c -o basic-tutorial-13a `pkg-config --cflags --libs gstreamer-1.0`
使用GStreamer日志系统
如果不想使用自定义接口,我们同样可以使用Gstreamer提供的日志系统来由Gstreamer框架统一管理日志。
使用GStreamer的日志系统时,我们需要首先定义我们的category,并定义GST_CAT_DEFAULT 宏为我们的category:
GST_DEBUG_CATEGORY_STATIC (my_category);
#define GST_CAT_DEFAULT my_category
然后在gst_init后初始化我们的category:
GST_DEBUG_CATEGORY_INIT (my_category, "my category", , "This is my very own");
最后使用GST_ERROR(), GST_WARNING(), GST_INFO(), GST_LOG() 或GST_DEBUG() 宏输出日志,这些宏所接受的参数类型与printf相同。
示例代码如下:
#include <gst/gst.h>
#include <stdio.h> GST_DEBUG_CATEGORY_STATIC (my_category);
#define GST_CAT_DEFAULT my_category int main(int argc, char *argv[]) {
/* Initialize GStreamer */
gst_init (&argc, &argv); GST_DEBUG_CATEGORY_INIT (my_category, "my category", , "This is my very own"); GST_ERROR("My msg: %d", );
GST_WARNING("My msg: %d", );
GST_INFO("My msg: %d", );
GST_DEBUG("My msg: %d", ); return ;
}
编译后,设置相应的log等级即可看到我们所添加的log。
$ gcc basic-tutorial-13b.c -o basic-tutorial-13b `pkg-config --cflags --libs gstreamer-1.0`
$ GST_DEBUG= ./basic-tutorial-13b
...
::00.135957434 0x21c4600 ERROR my category basic-tutorial-13b.c::main: My msg:
::00.135967528 0x21c4600 WARN my category basic-tutorial-13b.c::main: My msg:
::00.135976899 0x21c4600 INFO my category basic-tutorial-13b.c::main: My msg:
::00.135985622 0x21c4600 DEBUG my category basic-tutorial-13b.c::main: My msg:
获取Pipeline运行时的Element关系图
在Pipeline变得很复杂时,我们需要知道Pipeline是否按预期运行、使用到哪些Element,尤其是使用playbin 或uridecodebin时。为此,GStreamer提供了相应的功能,能够将Pipeline在当前状态下所有的Elements及其关系输出成dot文件,再通过 Graphviz等工具可以将其转换成图片文件。
为了得到.dot文件,我们只需通过GST_DEBUG_DUMP_DOT_DIR 环境变量,指定输出目录即可,gst-launch-1.0会在各状态分别生成一个.dot文件。 例如:通过下列命令,我们可以得到使用playbin播放网络文件时生成的Pipeline:
$ GST_DEBUG_DUMP_DOT_DIR=. gst-launch-1.0 playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm
$ ls *.dot
0.00.00.013715494-gst-launch.NULL_READY.dot
0.00.00.170999259-gst-launch.PAUSED_PLAYING.dot
0.00.07.642049256-gst-launch.PAUSED_READY.dot
0.00.00.162033239-gst-launch.READY_PAUSED.dot
0.00.07.606477348-gst-launch.PLAYING_PAUSED.dot $ dot 0.00.00.170999259-gst-launch.PAUSED_PLAYING.dot -Tpng -o play.png
生成的play.png如下(结果会根据安装的插件不同而不同):
需要注意的是,如果需要在自己的应用中加入此功能,那就需要在想要生成dot文件的时候显式地在相应事件发生时调用GST_DEBUG_BIN_TO_DOT_FILE() 或GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(),否则即使设置了GST_DEBUG_DUMP_DOT_DIR 环境变量也无法生成dot文件。
总结
通过本文,我们学习了:
- 如何通过GST_DEBUG环境变量获取GStreamer详细的日志信息。
- 如何使用自定义GStreamer的日志输出函数。
- 如何使用GStreamer日志系统。
- 如何获得GStreamer运行时的Element关系图。
GStreamer基础教程13 - 调试Pipeline的更多相关文章
- 【GStreamer开发】GStreamer基础教程13——播放速度
目标 快进,倒放和慢放是trick模式的共同技巧,它们有一个共同点就是它们都修改了播放的速度.本教程会展示如何来获得这些效果和如何进行逐帧的跳跃.主要内容是: 如何来变换播放的速度,变快或者变慢,前进 ...
- 【GStreamer开发】GStreamer基础教程03——动态pipeline
本教程介绍pipeline的一种新的创建方式--在运行中创建,而不是在运行前一次性的创建结束. 介绍 在这篇教程里的pipeline并非在运行前就全部创建结束的.放松一下,这样做没有任何问题.如果我们 ...
- 【GStreamer开发】GStreamer基础教程08——pipeline的快捷访问
目标 GStreamer建立的pipeline不需要完全关闭.有多种方法可以让数据在任何时候送到pipeline中或者从pipeline中取出.本教程会展示: 如何把外部数据送到pipeline中 如 ...
- 【GStreamer开发】GStreamer基础教程07——多线程和Pad的有效性
目标 GStreamer会自动处理多线程这部分,但在有些情况下,你需要手动对线程做解耦.本教程会教你怎样才能做到这一点,另外也展示了Pad的有效性.主要内容包括: 如何针对部分的pipeline建立一 ...
- GStreamer基础教程02 - 基本概念
摘要 在 Gstreamer基础教程01 - Hello World中,我们介绍了如何快速的通过一个字符串创建一个简单的pipeline.为了能够更好的控制pipline中的element,我们需要单 ...
- 【GStreamer开发】GStreamer基础教程14——常用的element
目标 本教程给出了一系列开发中常用的element.它们包括大杂烩般的eleemnt(比如playbin2)以及一些调试时很有用的element. 简单来说,下面用gst-launch这个工具给出一个 ...
- GStreamer基础教程09 - Appsrc及Appsink
摘要 在我们前面的文章中,我们的Pipline都是使用GStreamer自带的插件去产生/消费数据.在实际的情况中,我们的数据源可能没有相应的gstreamer插件,但我们又需要将数据发送到GStre ...
- GStreamer基础教程12 - 常用命令工具
摘要 GStreamer提供了不同的命令行工具用于快速的查看信息以及验证Pipeline的是否能够正确运行,在平时的开发过程中,我们也优先使用GStreamer的命令行工具验证,再将Pipeline集 ...
- 【GStreamer开发】GStreamer基础教程10——GStreamer工具
目标 GStreamer提供了一系列方便使用的工具.这篇教程里不牵涉任何代码,但还是会讲一些有用的内容: 如何在命令行下建立一个pipeline--完全不使用C 如何找出一个element的Capab ...
随机推荐
- H3C VLSM
- Linux中找不到ifconfig命令的解决方法
1.ifconfig命令是设置或显示网络接口的程序,可以显示出我们机器的网卡信息,可是有些时候最小化安装CentOS等Linux发行版的时候会默认不安装ifconfig等命令,这时候你进入终端,运行i ...
- 18.函数复习,文件处理b模式(二进制处理),文件处理其他高级玩法
1.函数复习 # map # l = [1,2,3,4,5] # print(list(map(str,l))) # reduce # l = [1,2,3,4,5] # from functools ...
- vue文章学习路线
vue学习笔记(一)入门 Vue实现简单的购物车功能 vue学习笔记(二)vue的生命周期和钩子函数 使用webstorm搭建vue-cli项目 vue-cli项目中引入第三方插件 vue-cli项目 ...
- java基础 -- 关键字final的用法
用法一(修饰变量): Final变量能被显式地初始化并且只能初始化一次.被声明为final的对象的引用不能指向不同的对象.但是final对象里的数据可以被改变.也就是说final对象的引用不能改变,但 ...
- SpringBoot入门简易教程
使用SpringBoot来开发一个简单的restful api网关功能,目标:实现对SpringBoot的简单入门. 1. 创建SpringBoot项目 可以通过spring官网(https://st ...
- ELK学习实验008:Kibana的介绍
一 简介 Kiana是一款开源的数据分析和可视化平台,它是 Elastic Stack成员之一,设计用于和 Elasticsearch协作.您可以使用 Kiana对 Elasticsearch索引中的 ...
- mysql主从之binlog日志
mysql的binlog说明 主从复制依赖于二进制日志文件,简称为binlog binlog里面有存放了偏移信息 mysql主库binlog信息查看命令 [root@master ~]# mysql ...
- SofaBoot使用Nacos进行服务注册发现
前提 最近创业公司的项目组基于业务需要,开发一套新的微服务,考虑到选用的组件必须是主流.社区活跃.生态完善以及方便迁移到云上等因素,引入了SOFAStack全家桶.微服务开发里面,一个很重要的功能就是 ...
- VC windows 多网卡情况下 获取当前网卡ip地址
参考 代码如下 记录下以后用得到或者能帮到有需要的朋友 #include <iostream> #include <WinSock2.h> #include <Iphlp ...