系列文章目录
- GStreamer 简明教程(一):环境搭建,运行 Basic Tutorial 1 Hello world!
- GStreamer 简明教程(二):基本概念介绍,Element 和 Pipeline
- GStreamer 简明教程(三):动态调整 Pipeline
- GStreamer 简明教程(四):Seek 以及获取文件时长
- GStreamer 简明教程(五):Pad 相关概念介绍,Pad Capabilities/Templates
- GStreamer 简明教程(六):利用 Tee 复制流数据,巧用 Queue 实现多线程
- GStreamer 简明教程(七):实现管道的动态数据流
文章目录
前言
本章内容是对 GStreamer 官方教程中第九、十和十一三章的一个介绍。这几章涉及的代码不多,主要是介绍 GStreamer 中工具,包括 GstDiscoverer、gst-discoverer-1.0、gst-launch-1.0、gst-inspect-1.0 、日志工具等。这块可以扩展的内容比较少,但我又不想漏了这块,因此本文只是做一些粗粒度的总结。
一、GstDiscoverer
GstDiscoverer 是 pbutils 库(Plugin-Base 工具类)中的一个实用对象,它接受一个 URI 或 URI 列表,并返回有关它们的信息。它可以在同步或异步模式下工作。
它类似于 FFmpeg 中的 ffprobe 工具,用来获取媒体文件的信息,例如编解码器、视频分辨率、比特率等等
下面是 https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm 文件使用 GstDiscoverer 获取的结果
Duration: 0:00:52.250000000
Tags:
video codec: On2 VP8
language code: en
container format: Matroska
application name: ffmpeg2theora-0.24
encoder: Xiph.Org libVorbis I 20090709
encoder version: 0
audio codec: Vorbis
nominal bitrate: 80000
bitrate: 80000
Seekable: yes
Stream information:
container: WebM
audio: Vorbis
Tags:
language code: en
container format: Matroska
audio codec: Vorbis
application name: ffmpeg2theora-0.24
encoder: Xiph.Org libVorbis I 20090709
encoder version: 0
nominal bitrate: 80000
bitrate: 80000
video: VP8
Tags:
video codec: VP8 video
container format: Matroska
在代码中我们使用 GstDiscoverer 模块的相关 API 来获取信息,但 GStreamer 也提供了 gst-inspect-1.0 工具,与 ffprobe 类似,它是一个可执行程序,你可以运行它来获取信息(后面会再细说)。
GstDiscoverer API 使用请参考 basic-tutorial-9.c,我这边就不细说了,也没啥好说。
二、gst-launch-1.0、gst-discoverer-1.0、gst-inspect-1.0
这些工具位于 GStreamer 二进制文件的 bin 目录中。由于这个目录没有被添加到系统的 PATH 环境变量中(为了避免过度污染环境变量),你需要进入这个目录才能执行这些工具。
只需打开终端(或控制台窗口),进入 GStreamer 安装目录下的 bin 目录(重新阅读 GStreamer 安装部分以了解具体位置),就可以开始输入本教程中给出的命令了。
如果你是源码编译的,在运行这些工具之前,需要设置开发用的环境变量,关于开发环境变量我在 GStreamer 源码编译,在 Clion 下搭建调试环境 文中有提及。
2.1 gst-launch-1.0
gst-launch-1.0
是一个命令行工具,用于测试和调试GStreamer框架中的媒体管道。作为GStreamer项目的一部分,它允许用户通过命令行直接构建和运行媒体处理流水线,而无需编写完整的应用程序。这在开发和测试阶段特别有用,因为它能够快速验证GStreamer管道的正确性和性能。
以下是 gst-launch-1.0
的一些关键功能和特性:
-
管道创建:允许用户通过将不同的GStreamer元素连接起来描述一个多媒体管道。每个元素执行一个特定的功能,例如解码、编码、过滤及音视频同步等。
-
文本描述:用户通过文本形式描述管道,并且命令行解析器会实例化这些元素并创建实际的运行管道。
-
调试支持:作为一个调试工具,它可以帮助开发者快速发现和修复管道中的问题,比如元素不兼容或媒体格式不支持。
-
灵活性:由于GStreamer插件的模块化设计,
gst-launch-1.0
可以立即支持新添加的插件和功能,无需修改工具本身。 -
跨平台:可在多种操作系统上运行,包括Linux、Windows和macOS,适用于开发跨平台多媒体应用程序的环境。
-
管道动态管理:可以通过动态参数调整和事件响应控制管道的行为。
gst-launch-1.0
通常用于调试和原型构建阶段,而在生产应用中,开发者更倾向于使用GStreamer的C语言API来实现更复杂和优化的多媒体处理任务。
请注意,它只能创建简单的管道。特别是,它只能在一定程度上模拟管道与应用程序的交互。不过,它对于快速测试管道非常方便,世界各地的 GStreamer 开发者每天都在使用它。
请注意,gst-launch-1.0 主要是面向开发者的调试工具。你不应该基于它构建应用程序。相反,应该使用 GStreamer API 中的 gst_parse_launch() 函数,作为从管道描述构建管道的简单方法。
2.1.1 使用说明
创建并连接元素
在简单形式下,管道描述(PIPELINE-DESCRIPTION)是由感叹号(!)分隔的元素类型列表
gst-launch-1.0 videotestsrc ! videoconvert ! autovideosink
你应该能看到一个显示动画视频图案的窗口。在终端中使用 CTRL+C 可以停止程序。
设置属性
gst-launch-1.0 videotestsrc pattern=11 ! videoconvert ! autovideosink
属性可以附加到元素后,形式为property=value(可以指定多个属性,属性之间用空格分隔)。
pipeline 结构如下:
videotestsrc (pattern=11) --> videoconvert --> autovideosink
命名元素
可以使用 name 属性给元素命名,这样就可以创建包含分支的复杂管道。名称允许链接到在描述中较早创建的元素,对于使用具有多个输出端口的元素(如分离器或分流器)来说是必不可少的。
命名元素通过其名称后跟一个点来引用。
gst-launch-1.0 videotestsrc ! videoconvert ! tee name=t ! queue ! autovideosink t. ! queue ! autovideosink
pipeline 结构如下
videotestsrc --> videoconvert --> tee (name=t) -----> queue --> autovideosink
|
|
+-------> queue --> autovideosink
Pads
在链接两个元素时,与其让GStreamer自行选择要使用的Pad,您可以直接指定Pad。您可以通过在元素名称后加上一个点和Pad名称来做到这一点(元素必须是已命名的)。使用gst-inspect-1.0工具可以了解元素的Pad名称。
例如,当您想从解复用器中获取特定的流时,这将非常有用:
gst-launch-1.0 souphttpsrc location=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm ! matroskademux name=d d.video_0 ! matroskamux ! filesink location=sintel_video.mkv
这将使用souphttpsrc从网络中获取一个媒体文件,该文件为webm格式(一种特殊的Matroska容器,参见基本教程2:GStreamer概念)。然后我们使用matroskademux打开该容器。这个媒体包含音频和视频,所以matroskademux将创建两个输出Pad,分别命名为video_0和audio_0。我们将video_0链接到一个matroskamux元素,以将视频流重新打包到一个新容器中,最后链接到一个filesink,它会将流写入名为"sintel_video.mkv"的文件中(location属性指定文件名)。
pipeline 结构如下:
souphttpsrc --> matroskademux (name=d) --[video_0]--> matroskamux --> filesink
(webm file) (sintel_video.mkv)
如果我们只想保留音频:
gst-launch-1.0 souphttpsrc location=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm ! matroskademux name=d d.audio_0 ! vorbisparse ! matroskamux ! filesink location=sintel_audio.mka
Caps filters
当一个元素有多个输出Pad时,链接到下一个元素可能会出现歧义:下一个元素可能有多个兼容的输入Pad,或者其输入Pad可能与所有输出Pad的Pad Caps兼容。在这些情况下,GStreamer将使用第一个可用的Pad进行链接,这基本上意味着GStreamer会随机选择一个输出Pad。
考虑以下管道:
gst-launch-1.0 souphttpsrc location=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm ! matroskademux ! filesink location=test
这是与前一个示例中相同的媒体文件和解复用器。filesink的输入Pad Caps是ANY,这意味着它可以接受任何类型的媒体。那么matroskademux的两个输出Pad中的哪一个会链接到filesink呢?是video_0还是audio_0?你无法知道。
不过,您可以通过使用命名的Pad(如前一小节中所述)或使用Caps过滤器来消除这种歧义:
gst-launch-1.0 souphttpsrc location=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm ! matroskademux ! video/x-vp8 ! matroskamux ! filesink location=sintel_video.mkv
Caps过滤器表现得像一个通道元素,它不做任何事情,只接受具有给定Caps的媒体,有效地解决了歧义。在这个例子中,在matroskademux和matroskamux之间,我们添加了一个video/x-vp8的Caps过滤器,以指定我们感兴趣的是matroskademux的能够产生此类视频的输出Pad。
要找出一个元素接受和产生的Caps,请使用gst-inspect-1.0工具。要找出包含在特定文件中的Caps,请使用gst-discoverer-1.0工具。要找出一个元素在特定管道中产生的Caps,像平常一样运行gst-launch-1.0,并使用–v选项来打印Caps信息。
示例
使用playbin播放媒体文件(如基本教程1:Hello world! 中所示):
gst-launch-1.0 playbin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm
一个完整的播放管道,带有音频和视频(与playbin内部创建的管道大致相同):
gst-launch-1.0 souphttpsrc location=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm ! matroskademux name=d ! queue ! vp8dec ! videoconvert ! autovideosink d. ! queue ! vorbisdec ! audioconvert ! audioresample ! autoaudiosink
一个转码管道,它打开webm容器并解码两个流(通过uridecodebin),然后用不同的编解码器重新编码音频和视频分支,并将它们重新组合到一个Ogg容器中(仅为了演示)。
gst-launch-1.0 uridecodebin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm name=d ! queue ! theoraenc ! oggmux name=m ! filesink location=sintel.ogg d. ! queue ! audioconvert ! audioresample ! flacenc ! m.
一个重新缩放管道。当视频帧大小在输入和输出Caps中不同时,videoscale元素执行重新缩放操作。通过Caps过滤器将输出Caps设置为320x200。
gst-launch-1.0 uridecodebin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm ! queue ! videoscale ! video/x-raw-yuv,width=320,height=200 ! videoconvert ! autovideosink
这个关于gst-launch-1.0的简短描述应该足以让您入门。请记住,您可以在 Basic tutorial 10: GStreamer tools 获得完整的文档。
2.2 gst-inspect-1.0
gst-inspect-1.0 这个工具是常用的,在之前几章中我们使用它来查询元素的信息,该工具有三种操作模式:
- 如果不带参数,它会列出所有可用的元素类型,即可用于实例化新元素的类型。
- 如果带有文件名作为参数,它会将该文件视为一个GStreamer插件,尝试打开它,并列出其中描述的所有元素。
- 如果带有GStreamer元素名称作为参数,它会列出有关该元素的所有信息。
关于这个工具的更多内容参考 gst-inspect-1.0
2.3 gst-discoverer-1.0
这个工具是 GstDiscoverer 对象(在Basic tutorial 9: Media information gathering中有介绍)的一个包装器。它接受命令行中的 URI 并打印出 GStreamer 能够提取的所有媒体相关信息。它对于发现媒体使用了什么容器和编解码器很有用,从而帮助你确定在管道中需要放置哪些元素来播放它。
三、Debug 工具
3.1 日志等级
GStreamer 中有大量的日志,如果开放所有日志势必会影响性能,因此需要对日志进行分级,GStreamer 有 10 个日志等级
等级 | 名称 | 描述 |
---|---|---|
0 | none | 不输出任何调试信息 |
1 | ERROR | 记录所有致命错误。这些错误会导致核心或元素无法执行请求的操作。如果应用程序编程时处理了触发错误的条件,仍然可以恢复。 |
2 | WARNING | 记录所有警告。通常这些不是致命的,但预计会发生用户可见的问题。 |
3 | FIXME | 记录所有"待修复"消息。这些通常表示已知不完整的代码路径被触发。在大多数情况下可能正常工作,但在特定情况下可能会出现问题。 |
4 | INFO | 记录所有信息性消息。这些通常用于系统中只发生一次的事件,或重要且罕见到需要在此级别记录的事件。 |
5 | DEBUG | 记录所有调试消息。这些是在对象生命周期内仅发生有限次数的事件的一般调试消息,包括设置、清理、参数更改等。 |
6 | LOG | 记录所有日志消息。这些是对象生命周期内重复发生的事件消息,包括流媒体和稳定状态条件。例如用于记录元素中每个缓冲区的日志消息。 |
7 | TRACE | 记录所有跟踪消息。这些是非常频繁发生的消息。例如,每次修改 GstMiniObject(如 GstBuffer 或 GstEvent)的引用计数时。 |
9 | MEMDUMP | 记录所有内存转储消息。这是最重量级的日志记录,可能包括内存块内容的转储。 |
要启用调试输出,可以将环境变量 GST_DEBUG 设置为所需的调试级别。所有低于该级别的消息也将被显示(例如,如果设置 GST_DEBUG=2,您将获得 ERROR 和 WARNING 消息)。
此外,GStreamer 的每个插件或部分都定义了自己的分类,因此您可以为每个单独的分类指定调试级别。例如,GST_DEBUG=2,audiotestsrc:6 将为 audiotestsrc 元素使用调试级别 6,而其他所有元素使用级别 2。
因此,GST_DEBUG 环境变量是一个以逗号分隔的 category:level 对的列表,开头可选择一个级别,代表所有分类的默认调试级别。
还提供了 ‘’ 通配符。例如 GST_DEBUG=2,audio:6 将对所有以 audio 开头的类别使用调试级别 6。GST_DEBUG=*:2 相当于 GST_DEBUG=2。
还可以通过 GST_DEBUG_FILE 环境变量将日志重定向到文件中,然后再进行排查,例如:
export GST_DEBUG_FILE=debug.log
export GST_DEBUG=2
gst-launch-1.0 videotestsrc ! autovideosink
在我们排查 GStreamer 内存泄漏的时候,可以设置 GST_DEBUG=“GST_TRACER:7” 和 GST_TRACERS=“leaks” 一起使用。所以这个组合的意义是:
-
GST_TRACERS 告诉 GStreamer 要使用什么跟踪器
-
GST_DEBUG 确保跟踪器的输出信息能够被看到
这就像是: -
GST_TRACERS 是安装了监控摄像头
-
GST_DEBUG 是打开了显示器来查看监控画面
3.2 日志设置自己的 TAG
在 Android 日志中我们常设置一个 TAG 来标识不同的日志,这是很常见的用法,方面过滤掉其他我们不感兴趣的日志
- Android 日志写法:
// Android
private static final String TAG = "my_category";
Log.d(TAG, "debug message");
Log.e(TAG, "error message");
- GStreamer 日志写法:
// GStreamer
// 1. 首先定义你的 TAG
GST_DEBUG_CATEGORY_STATIC (my_category);
#define GST_CAT_DEFAULT my_category
// 2. 在初始化时注册这个 TAG
GST_DEBUG_CATEGORY_INIT (my_category, "my category", 0, "This is my very own");
// 3. 使用这个 TAG 输出日志
GST_DEBUG("debug message"); // 等同于 Log.d
GST_ERROR("error message"); // 等同于 Log.e
主要区别:
- Android 中直接使用字符串作为 TAG
- GStreamer 需要先注册 TAG,然后才能使用
- GStreamer 的方式可以更好地进行分类管理和级别控制
使用场景示例:
// 定义 TAG
GST_DEBUG_CATEGORY_STATIC (my_player);
#define GST_CAT_DEFAULT my_player
int main() {
// 初始化 GStreamer
gst_init(&argc, &argv);
// 注册 TAG
GST_DEBUG_CATEGORY_INIT (my_player, "MyPlayer", 0, "Custom player debug");
// 使用自定义 TAG 输出日志
GST_DEBUG("Player initializing...");
GST_ERROR("Failed to load media");
GST_INFO("Playback started");
}
这样的好处是:
- 可以更好地组织和过滤日志
- 可以针对特定 TAG 设置不同的日志级别
- 更容易定位和调试问题
3.3 导出 pipeline
GStreamer 支持导出 pipeline 结构为 .dot 文件,你可以使用 GraphViz 这样的工具来查看(这里推荐一个在线 GraphViz 网站:https://sketchviz.com/new)
这在使用像 playbin 或 uridecodebin 这样的多功能元素时特别有用,因为这些元素内部会实例化多个元素。你可以使用 .dot 文件来了解它们在内部创建了什么样的管道(同时也可以学习一些 GStreamer 的知识)。
3.1 基本设置
# 设置输出目录
export GST_DEBUG_DUMP_DOT_DIR=/path/to/your/folder
3.2在命令行中使用
# 运行 gst-launch-1.0,将自动在状态变化时生成 .dot 文件
gst-launch-1.0 videotestsrc ! autovideosink
3.3 在代码中使用
// 不带时间戳的版本
GST_DEBUG_BIN_TO_DOT_FILE(pipeline, GST_DEBUG_GRAPH_SHOW_ALL, "pipeline");
// 带时间戳的版本
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(pipeline, GST_DEBUG_GRAPH_SHOW_ALL, "pipeline");
3.4 查看生成的文件
# 转换 .dot 文件为图片
dot -Tpng pipeline.dot > pipeline.png
或者在 https://sketchviz.com/new 中在线查看
3.5 禁用此功能
# 取消环境变量设置
unset GST_DEBUG_DUMP_DOT_DIR