使用Gstreamer从摄像头捕获h.264流

12

我正在尝试使用Gstreamer 1.0的v4l2src元素从本地安装的Logitech C920相机的/dev/video0捕获H264流。

v4l2-ctl --list-formats显示相机能够提供H264视频格式:

# v4l2-ctl --list-formats
ioctl: VIDIOC_ENUM_FMT
        ...

        Index       : 1
        Type        : Video Capture
        Pixel Format: 'H264' (compressed)
        Name        : H.264

        ...

但是管道一直给我not-negotiated (-4)错误:

# gst-launch-1.0 -vvv v4l2src device=/dev/video0 ! video/x-h264, width=800, height=448, framerate=30/1 ! fakesink

/GstPipeline:pipeline0/GstV4l2Src:v4l2src0.GstPad:src: caps = video/x-h264, width=(int)800, height=(int)448, interlace-mode=(string)progressive, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)30/1
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:src: caps = video/x-h264, width=(int)800, height=(int)448, interlace-mode=(string)progressive, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)30/1
/GstPipeline:pipeline0/GstFakeSink:fakesink0.GstPad:sink: caps = video/x-h264, width=(int)800, height=(int)448, interlace-mode=(string)progressive, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)30/1
/GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:sink: caps = video/x-h264, width=(int)800, height=(int)448, interlace-mode=(string)progressive, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)30/1
ERROR: from element /GstPipeline:pipeline0/GstV4l2Src:v4l2src0: Internal data flow error.
Additional debug info:
gstbasesrc.c(2809): gst_base_src_loop (): /GstPipeline:pipeline0/GstV4l2Src:v4l2src0:
streaming task paused, reason not-negotiated (-4)
Execution ended after 67687169 ns.

需要帮助!

5个回答

13

您的需求是否必须使用gstreamer?我在使用Logitech C920的H264模式和gstreamer时也遇到了很多问题。但是,我成功地使用VLC作为RTSP服务器,以便使用C920进行H264:

$ cvlc -v v4l2:///dev/video0:chroma="H264":width=1024:height=570:fps=30 \
       --sout="#rtp{sdp=rtsp://:8554/live}"

如果您想使用VLC,那么我可以通过URI rtsp://localhost:8554/live 与另一个VLC 进行连接。

如果您必须使用GStreamer,则我只能使用一个捕获实用程序来使用它,您可以在此处找到该实用程序:https://github.com/csete/bonecam - 目录 "capture"。

您需要编译它,但如果您具备一些编程技能,这应该很容易,因为只有一个C文件和一个脚本可帮助您。只需将“host”作为参数传递给脚本:

# Get the bonecam/capture content or git clone the directory, and then
$ cd bonecam/capture
$ ./build host
你可以使用"capture"工具,例如:
$ v4l2-ctl -d /dev/video0 --set-fmt-video=width=1024,height=570,pixelformat=1
$ v4l2-ctl -d /dev/video0 --set-parm=30
$ ./bonecam/capture/capture -d /dev/video0 -c 100000 -o | \
      gst-launch -e filesrc location=/dev/fd/0 ! legacyh264parse ! rtph264pay ! udpsink host=10.0.0.42 port=5000
如果你不想指定获取帧的数量(使用"capture"的"-c"参数),那么这个实用程序有一个分支可以在这里找到:https://github.com/DeLaGuardo/bonecam 我知道有一个被归类为“坏”的插件,名为uvch264适用于gstreamer 0.10,应该可以与C920一起使用。但是我不知道对于gstreamer 1.0是否可行,并且我无法进行测试。 更新: 不要忘记将--rtsp-timeout=-1添加到cvlc命令行中,例如:
$ cvlc -v v4l2:///dev/video0:chroma="H264":width=1024:height=570:fps=30 \
       --sout="#rtp{sdp=rtsp://:8554/live}" --rtsp-timeout=-1

如果没有这个选项,默认情况下流式传输只会持续60秒。


非常感谢!cvlc运行得非常好!我正在Rasperry Pi上使用它。 - s.webbandit
C920 处于 H264 模式下?你确定吗?我在树莓派上启用相机的 H264 模式时遇到了很多问题,由于树莓派上的 USB 问题,导致一些 H264 帧丢失,因此视频看起来很奇怪。实际上,正是因为这个原因,我正在 Beaglebone 上使用 C920。 无论如何,如果它对你有用,我想固件更新解决了这个问题。 - Vincent Hiribarren
我之前遇到过USB丢帧的问题。我按照这里描述的方式安装了新的Rapbian内核(https://github.com/raspberrypi/linux/issues/238)。丢帧问题消失了。现在H264视频流非常流畅。 - s.webbandit
谢谢提供这些信息。我会使用这个更新重新进行测试。 - Vincent Hiribarren

4
我一直在尝试做同样的事情,但出现了相同的错误。我想我当时使用的是GStreamer 1.0.6。
我找到了以下页面,可能还要感谢Fergal Butler的回答:

http://kakaroto.homelinux.net/2012/09/uvc-h264-encoding-cameras-support-in-gstreamer/

在这里,Youness Alaoui描述了他创建的uvch264_src元素,以支持GStreamer中的H264摄像机。

他在文章中提到了将其移植到GStreamer 1.0的计划。所以在过去的一周里,我一直在研究这个问题。结果发现,它已经被移植到了GStreamer 1.0,但只在开发者版本(版本1.1.2)中发布。

你可以在这里获取1.1.2版本:

http://gstreamer.freedesktop.org/src/

现在它被称为“uvch264src”,是gst-plugins-bad的一部分。我认为它也存在于1.1.1版本中,但我没有真正研究过。
我安装它时遇到了一些困难,我认为主要是由于我PC上安装的GST 1.0软件包冲突(所以是我的错)。但请注意,它依赖于libgudev-1.0-dev和libusb-1.0-0-dev,因此首先安装这些软件包-我花了一段时间才弄清楚我缺少了这两个软件包。
这是一个使用uvch264工作的管道: gst-launch-1.0 uvch264src device=/dev/video0 name=src auto-start=true src.vfsrc ! video/x-raw, format=YUY2, width=160, height=90, framerate=5/1 ! xvimagesink src.vidsrc ! queue ! video/x-h264, width=800, height=448, framerate=30/1 ! h264parse ! avdec_h264 ! xvimagesink 如果您不想使用预览视频(来自vfsrc pad),只需将src.vfsrc直接连接到fakesink即可。我还应该提到,即使这个管道对我有用,我也会收到很多关于“在段事件之前获得数据流”的警告。显然,我做错了什么,但我不确定是什么。
无论如何,在折腾了1.1.2和uvch264src的完全安装和工作后,我决定再次快速尝试v4l2src。结果发现v4l2src确实支持H264:/。(请参见简短的答案。)

简短回答:

所以,如果你愿意从源代码安装1.1.2版本,你就可以像之前尝试的那样做到你想要的。你不需要uvch264src。我已经测试过你的管道,在我的安装中它可以正常工作。我还尝试了这个简单的管道,在屏幕上显示视频,对我来说也很好用:

gst-launch-1.0 -e v4l2src device=/dev/video0 ! video/x-h264, width=800, height=448, framerate=30/1 ! avdec_h264 ! xvimagesink sync=false


1
尝试使用videoconvert自动将视频转换为视频接收器可理解的格式。
gst-launch-1.0 -vvv v4l2src device=/dev/video0 ! videoconvert ! ...

1

我还有一台Logitech C920相机,使用以下管道录制来自相机的H.264视频:

gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-h264,width=1280,height=720,framerate=30/1 ! mpegtsmux ! filesink location=output.ts

这段代码请求相机生成H.264数据,然后将其混合到MPEG传输流容器中,并写入磁盘。我可以用Totem成功播放生成的文件。
上述管道以720p记录。如果您更改所请求的格式为width=1920,height=1080,相机也可以以1080p录制。

1

1
想象一下,如果这些链接有一天失效了。因此,请解释一下你引用的链接。 - Freakyuser
1
h264现在已被v4l2src支持。 - Ross

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接