本文转载自许野平的博客
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
GStreamer 是一款非常优秀的媒体流构建工具。由于相关参考资料缺乏,官网介绍不够详尽,初学者往往费尽周折,也搞不定一个定制的管道架构,最后只好从网络上东拼西凑,摸着别人的例子过河。
如果您有类似的困惑,本文将带领您走出这个困境,迈出正确构建 GStreamer 管道的第一步。
1. 最简单的视频管道
由于一个管道至少有一个起点和一个终点,因此最简单的管道至少有两个元素,一个用来做 src(流的起点),另一个做 sink(流的终点)。
- videotestsrc:提供测试视频信号源。它绝对不会出错,可以提供可靠、稳定的信号源。
- autovideosink:可以把为压缩编码的视频信号显示在屏幕上。我用的是 Jetson Nano 硬件平台,这个元素直接把画面全屏显示了。
我们把它两个连接起来,用下面的命令测试一下。
$ gst-launch-1.0 videotestsrc ! autovideosink
- 1
屏幕显示如下信号:
这个让我想起三十多年前当电视机维修工的时候,用的那个视频信号发生器,输出的就是类似这样的信号。人生如梦,当年手拿烙铁和万用表的时候,老子怎么也没想到将来有一天会靠敲键盘在机器视觉行业混饭。
2. 自己创建一个问题
我打算做个简单的实验,在 videotestsrc 后面加上一个 h.264 编码器,然后再紧跟一个 h.264 解码器。我觉得这个效果应该和上面的例子一样——因为图像编码后再解码,等于啥也没做。
输入下面的命令后,一大堆错误信息,让我瞬间崩溃了:
$ gst-launch-1.0 videotestsrc ! omxh264enc ! omxh264dec ! autovideosink
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
Framerate set to : 30 at NvxVideoEncoderSetParameterNvMMLiteOpen : Block : BlockType = 4
===== NVMEDIA: NVENC =====
NvMMLiteBlockCreate : Block : BlockType = 4
H264: Profile = 66, Level = 40
ERROR: from element /GstPipeline:pipeline0/GstOMXH264Enc-omxh264enc:omxh264enc-omxh264enc0: Internal data stream error.
Additional debug info:
/dvs/git/dirty/git-master_linux/3rdparty/gst/gst-omx/omx/gstomxvideoenc.c(1383): gst_omx_video_enc_loop (): /GstPipeline:pipeline0/GstOMXH264Enc-omxh264enc:omxh264enc-omxh264enc0:
stream stopped, reason not-negotiated
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
3. 有用的 fakesink
GStreamer 提供了一个万能的管道终点元素 fakesink。这个元素对输入数据没有任何要求,来者不拒,同时,它啥工作也不做,感觉就是个黑洞,任何数据到它这里都接受,也不做任何处理,然后就没有然后了。因此,它前面可以对接任何合理的元素。
fakesink 的作用在于,可以在任何位置让你正在构建的管道合法地结束。这可以让我们采用增量方式,步步为营,慢慢增加管道长度,直到完整地构建出管道。
例如,为了正确构建上面的例子,我输入下面这两行命令,都是可以正常执行的。这说明管道的 videotestsrc ! omxh264enc
这一部分是可以正常工作的。
$ gst-launch-1.0 videotestsrc ! fakesink
$ gst-launch-1.0 videotestsrc ! omxh264enc ! fakesink
- 1
- 2
但是下面这一行就不行了:
$ gst-launch-1.0 videotestsrc ! omxh264enc ! omxh264dec ! fakesink
- 1
这说明,元素 omxh264dec 与管道前面的那个部分不能衔接。接下来我们分析一下原因。
4. gst-inspect-1.0:随手可得的元素/插件说明书
我们用下面两行命令查看 omxh264enc 和 omxh264dec 的说明,重点查看 omxh264enc 的输出数据(src pad caps)和 omxh264dec 的输入数据 (sink pad caps) 的兼容性。为了便于理解,下面的屏幕输出内容我做了删减。
$ gst-inspect-1.0 omxh264enc
...
Pad Templates:
SRC template: 'src'
Availability: Always
Capabilities:
video/x-h264
width: [ 16, 4096 ]
height: [ 16, 4096 ]
stream-format: { (string)byte-stream, (string)avc }
alignment: au
...
$ gst-inspect-1.0 omxh264dec
...
Pad Templates:
SINK template: 'sink'
Availability: Always
Capabilities:
video/x-h264
parsed: true
alignment: au
stream-format: byte-stream
width: [ 1, 2147483647 ]
height: [ 1, 2147483647 ]
...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
看出区别了吗?omxh264dec 要求输入数据必须满足 parsed=true
,而元素 omxh264enc 却不提供这个保障。
顾名思义,这说明 omxh264enc 的输出结果需要进一步解析后,才能发送给 omxh264dec 解码。查找一些 h.264 数据解析插件,发现 h265parse 符合要求。于是我们构造下面的命令:
$ gst-launch-1.0 videotestsrc ! omxh264enc ! h264parse ! omxh264dec ! autovideosink
- 1
运行后,非常完美。忽然又突发奇想,再长一些行不行?输入下面的命令:
$ gst-launch-1.0 videotestsrc ! omxh264enc ! h264parse ! omxh264dec ! omxh264enc ! h264parse ! omxh264dec ! autovideosink
- 1
依旧完美!OK,从今天起,我们可以借助 gst-inspect-1.0 和 fakesink 这两个工具,逐步排查管道连接中存在的 caps 协商异常问题,建立可靠的媒体流管道。如果本文对您有帮助,请点赞、收藏,谢谢!
标签:1.0,gst,omxh264enc,GStreamer,omxh264dec,有把握,管道,videotestsrc,必然王国 From: https://www.cnblogs.com/thammer/p/17202603.html