在Raspberry Pi上从USB摄像头获取原始h264数据包

时间:2018-06-12 22:18:00

标签: ffmpeg raspberry-pi video-streaming h.264

我正在尝试从连接到我的Raspberry PI的USB网络摄像头接收H264帧

使用RPi相机模块我可以运行以下命令来获取stdin输出的H264数据:raspivid -t 0 -w 640 -h 320 -fps 15 -o - 接近零延迟

使用USB相机是否有相同的功能?我有两个USB摄像头,我想这样做。

使用ffprobe /dev/videoX我得到以下输出:(缩写为重要细节):

$ ffprobe /dev/video0
...
Input #0, video4linux2,v4l2, from '/dev/video0':
Duration: N/A, start: 18876.273861, bitrate: 147456 kb/s
Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 1280x720, 147456 kb/s, 10 fps, 10 tbr, 1000k tbn, 1000k tbc

$ ffprobe /dev/video1
...
Input #0, video4linux2,v4l2, from '/dev/video1':
Duration: N/A, start: 18980.783228, bitrate: 115200 kb/s
Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 800x600, 115200 kb/s, 15 fps, 15 tbr, 1000k tbn, 1000k tbc


$ ffprobe /dev/video2
...
Input #0, video4linux2,v4l2, from '/dev/video2':
Duration: N/A, start: 18998.984143, bitrate: N/A
Stream #0:0: Video: h264 (Main), yuv420p(progressive), 1920x1080, -5 kb/s, 30 fps, 30 tbr, 1000k tbn, 2000k tbc

据我所知,其中两个不是H264,需要“解码”到H264,所以我知道那里增加了一点延迟。但第三个(video2)是H264,所以我应该可以从中获取数据?我试图用CAT来解决它,但它说我得到了无效的论据。

我到目前为止,使用FFMPEG可能是唯一的选择。想使用易于所有RPi(apt安装)的软件。

有关H264数据包的额外问题:当我将数据从raspivid命令流式传输到我的解码器时,它可以正常工作。但是,如果我决定丢弃10个第一个数据包,那么它永远不会初始化解码过程,只显示黑色背景。任何人都知道我可以在我的软件中重新创建的第一个数据包中可能缺少什么,所以我不必为每个新连接的用户重新启动流?

编辑:奖金问题答案:谷歌搜索后,我看到前两帧raspivid发给我的是。因此,通过忽略两个第一帧,我的解码器将无法正确“解码”。因此,如果我保存这些帧并将它们首先发送给所有新用户,它就能完美运行。似乎这些用于某种初始过程。

0x27 = 01 00111 = type 7    Sequence parameter set (B-frame)
0x28 = 01 01000 = type 8    Picture parameter set (B-frame)

1 个答案:

答案 0 :(得分:0)

首先,让我们获得数据流。对于Raspi cam:

  1. Raspi camera通过CSI(相机串行接口)连接到Raspi。此链接包含未压缩的原始图像数据。

  2. raspivid与Raspi的嵌入式GPU进行对话以访问图像数据,并要求GPU执行H.264编码,这总是会增加一些延迟(您可以使用raspiyuv获取原始未压缩数据,可能延迟较少)。

  3. USB网络摄像头通常会传输未压缩的原始图像数据。但有些还传输H.264或jpeg编码数据。

    接下来, Video for Linux API version 2 不是针对shell管道的,因此您无法使用cat从 / dev / videoX 中获取数据。您需要一些代码来执行IOCTL调用以协商从设备读取数据的内容和方式。 ffmpeg正是如此。

    关于您的奖金问题,您可以尝试使用raspivid的--inline option,这会强制流在每个I帧上包含PPS和SPS标头。

    接下来,使用 -f rawvideo 从ffmpeg输出H.264数据对我来说是错误的,因为 rawvideo 表示未压缩的视频。您可以尝试 -f h264 来强制使用原始H.264视频输出格式:

    ffmpeg -i /dev/video2 -c copy -f h264 pipe:1
    

    最后,您确实希望从USB网络摄像头获取 H.264流。由于图像数据未从相机中解压缩,因此首先必须将其编码为H.264。 Raspi的明智选择是使用硬件编码器,因为使用像x264这样的软件编码器会占用过多的CPU资源。

    如果你有一个使用 - enable-mmal 和/或 - enable-omx-rpi 配置的ffmpeg,你可以使用ffmpeg与硬件H.264编码器。

    否则,请查看gstreamer及其omxh264enc元素,例如。 here。 gstreamer也可以talk to v4l2 devices