如何使用支持H264的网络摄像头在raspberry Pi和客户端上设置gstreamer?

时间:2016-12-01 23:00:48

标签: udp raspberry-pi gstreamer

在水下ROV项目的背景下,我正在尝试从Raspberry Pi模型2流式传输(通过rtp)高清视频通量。网络摄像头是 Logitech C920 网络摄像头,我前一段时间买的,因为它是当时唯一具有H264功能的摄像头。 由于视频将用于驾驶ROV,因此我必须获得尽可能低的延迟。

所以我使用C920(戴尔站,运行Ubuntu 14.04)在我的桌面计算机上完善了一些gstreamer-1.0管道,这种方法运行良好,但是当我尝试使用Raspberry而不是它时遇到一些问题。

首先,我尝试(在RPi上)捕获H264相机流到matroska文件:

#this sets the C920 cam to H264 encoding, framerate 30/1:
v4l2-ctl --set-fmt-video=width=1920,height=1080,pixelformat=1 

gst-launch-1.0 -vvv v4l2src \
! video/x-h264, width=1920, height=1080, framerate=30/1 \
! queue max-size-buffers=1 \
! matroskamux \
! filesink location=/tmp/video.mkv

这完美无缺。有点不稳定,我想由于缓冲区的大小,但确定。

然后,我尝试将流量放在指向我的笔记本电脑的rtp流(MacBook Pro,Yosemite,通过brew安装的gstreamer)。

# on the server (RPi):
gst-launch-1.0 -vvv v4l2src \
! video/x-h264,width=1920,height=1080,framerate=30/1 \
! rtph264pay \
! udpsink host=192.168.0.168 port=5000

# on the client (MacBookPro)
gst-launch-1.0 -vvv udpsrc port=5000 \
   caps="application/x-rtp, media=(string)video, \
   clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96" \
! rtpjitterbuffer drop-on-latency=true latency=300 \
! rtph264depay \
! queue max-size-buffers=1 \
! matroskamux \
! filesink location=/tmp/video.mkv

在那里,我一无所获。我在sudo tcpdump (port 5000 and udp)的客户端检查它是否有效地在端口5000上接收udp数据包,但这就是全部。 video.mkv中没有记录任何内容,“触摸”但保持0字节。

在阅读了一些相关问题之后,我尝试了很多变化,包括:

  • 将流式传输到pi本身。在这种情况下,我有时会在客户端窗口上获得一些奇怪的输出,如果我增加缓冲区的大小,它会“消失”:
  

**(gst-launch-1.0:2832):CRITICAL **:gst_rtp_buffer_map:断言'GST_IS_BUFFER(缓冲区)'失败   **(gst-launch-1.0:2832):CRITICAL **:gst_rtp_buffer_unmap:断言'rtp->缓冲区!= NULL'失败

但仍然没有任何输出。

  • 其他接收器:xvimagesink,autovideosink
  • rtpjitterbuffer:切换drop-on-latency,更改了延迟值
  • queue:更改缓冲区大小

这是客户端的输出:

gst-launch-1.0 -vvv udpsrc port=5000 caps="application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96" ! rtpjitterbuffer drop-on-latency=true latency=300 ! rtph264depay ! queue max-size-buffers=10 ! matroskamux ! filesink location=/tmp/movie.mkv
Définition du pipeline à PAUSED...
Le pipeline est actif et n’a pas besoin de phase PREROLL…
/GstPipeline:pipeline0/GstUDPSrc:udpsrc0.GstPad:src: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96
/GstPipeline:pipeline0/GstRtpJitterBuffer:rtpjitterbuffer0.GstPad:sink: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96
Passage du pipeline à la phase PLAYING…
New clock: GstSystemClock
/GstPipeline:pipeline0/GstRtpJitterBuffer:rtpjitterbuffer0.GstPad:src: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96
/GstPipeline:pipeline0/GstRtpH264Depay:rtph264depay0.GstPad:sink: caps = application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96

^Chandling interrupt.
Interruption : arrêt du pipeline…
Execution ended after 0:16:23.292637000
Définition du pipeline à PAUSED...
Définition du pipeline à READY (prêt)…
Définition du pipeline à NULL…
Libération du pipeline…

我希望这里有人可以给我一些关于这个问题的线索:我应该指出(如果需要的话)我仍然是gstreamer的初学者......

编辑(12/11/16) 遵循ensonic的建议我使用了GST_DEBUG="*:3"。客户端现在告诉它的问题:它找不到视频的类型:

0:00:35.185377000 12349 0x7f878904bb20 WARN typefind
gsttypefindelement.c:983:GstFlowReturn
gst_type_find_element_chain_do_typefinding(GstTypeFindElement *, gboolean, gboolean):<typefind> error: Le flux ne contient pas assez de données.

0:00:35.185416000 12349 0x7f878904bb20 WARN typefind
gsttypefindelement.c:983:GstFlowReturn 
gst_type_find_element_chain_do_typefinding(GstTypeFindElement *, gboolean, gboolean):<typefind> error: Can't typefind stream

ERREUR : de l’élément /GstPipeline:pipeline0/GstDecodeBin:decodebin0   
/GstTypeFindElement:typefind : Le flux ne contient pas assez de données.

Information de débogage supplémentaire :
gsttypefindelement.c(983): GstFlowReturn     
gst_type_find_element_chain_do_typefinding(GstTypeFindElement *, gboolean, gboolean) (): /GstPipeline:pipeline0/GstDecodeBin:decodebin0  
/GstTypeFindElement:typefind:

Can't typefind stream

因此,客户端在流中没有足够的数据来确定其类型...... 我该怎么改变?我不明白缺少什么!

2 个答案:

答案 0 :(得分:0)

一些评论:

1)在客户端上使用“gst-launch-1.0 -e ...”使ctrl-c发送一个eos,以便文件最终确定。

2)在raspi上,在udpsink之前添加“gdppay”,在客户端上添加udpsrc之后的“gdpdepay”。这将传输事件和查询,因为您不使用rtsp。

3)在客户端尝试使用GST_DEBUG =“*:3”运行以查看是否有任何方法。另请尝试使用“!decodebin!autovideosink”运行,看看是否有任何图像。

答案 1 :(得分:0)

按照ensonic的评论(见下文),我终于设法让两个管道工作。 诀窍是使用gdppay / gdpdepay元素而不是rtph264pay / rtph264depay。

在服务器端(Raspberry Pi)

#set the Logitech C920 cam properly (1920x1080, 30 fps)
v4l2-ctl --set-fmt-video=width=1920,height=1080,pixelformat=1 --set-parm=30

# exec the following pipeline (only after gstreamer runs on the client!):
gst-launch-1.0 -vvv -e v4l2src \
 ! video/x-h264,width=1920,height=1080,framerate=30/1 \
 ! gdppay \
 ! udpsink host=192.168.0.168 port=5000

在客户端(MacBookPro)

# launch the following command before executing server pipeline:
gst-launch-1.0 -e -vvv udpsrc port=5000 \
   caps="application/x-gdp, streamheader=(buffer)< [insert long header here] >" \
 ! gdpdepay \
 ! video/x-h264, width=1920, height=1080, pixel-aspect-ratio=1/1, framerate=30/1 \
 ! decodebin \
 ! queue max-size-buffers=10 \
 ! autovideosink sync=false async=false

<强>结果

  • CPU负载

C920在Raspberry Pi上的表现非常出色。对于1920x1080分辨率,30 fps,总cpu负载小于3%。为了比较,当我在Raspberry上编码等效的原始YUV流时,负载上升到96%。客户端(对于我的2011英特尔i5 MacBookPro)的负载约为25%。

  • 视频延迟

我连续20分钟测试了之前的管道,整体测试超过10次。每当我获得可重现的〜250 ms 的延迟时,无论是通过LAN还是WLAN。改变队列的大小&#39;缓冲区并没有多大帮助。考虑到网络上有关流媒体延迟的内容,我认为这是可以接受的。足以低速驾驶车辆。

  • 开始使用

有时,在服务器端启动管道之后,由于以下错误导致许多数据包丢失:

gst_h264_parse_handle_frame:<h264parse0> broken/invalid nal Type: 1 Slice, Size: xxxx will be dropped  

但这些错误很快消失,可能是在收到下一个关键帧后(一个问题是,我不能轻易地改变摄像机的编码参数)?

其他提示和备注

  • 启动订单

如上所述,请务必在客户端之后启动服务器的管道。否则协商失败。

  • 获取标头缓冲区

要获取服务器流的(非常长)标头缓冲区,使用-vvv选项执行服务器管道一次,将其删除,然后将其复制/粘贴到客户端的大写字母中#39;管道。

  • 使用gstreamer和操作系统版本

Raspberry Pi 2,Raspbian,4.1.19-v7 +,gstreamer 1.2.0(http://packages.qa.debian.org/gstreamer1.0

客户: MacBook Pro 2011,i5,Apple OSX Yosemite,gstreamer 1.10.1(通过brew安装)

再次感谢那些想要切换到gdp的想法!