【问题标题】:Getting raw h264 packets from USB camera on Raspberry Pi从 Raspberry Pi 上的 USB 摄像头获取原始 h264 数据包
【发布时间】:2018-11-22 09:47:33
【问题描述】:

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

使用 RPi 摄像头模块,我可以运行以下命令以获取在标准输入中输出的 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 install)。

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

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

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

【问题讨论】:

  • 你倒退了。 “生”=“生”。 H264 被编码。解码 h264 会产生原始帧。
  • @szatmary 非常感谢,编辑了主要帖子以反映这一点。 (去掉 H264 前面的“raw”)
  • 更新了主要问题,因为我找到了奖励问题的答案。我的研究也把我拖到了这个命令,它似乎从相机输出 H264 数据。 ffmpeg -i /dev/video2 -c copy -f rawvideo pipe: 1 问题似乎是我的解码器没有得到任何 0x27 0x28 帧,这似乎是必需的,因为 RPi 相机无法正常工作?另外,我无法使用该命令更改帧速率或分辨率? (像 raspivid 那样改变硬件?)

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


【解决方案1】:

首先,让我们正确处理数据流。对于 Raspi 摄像头:

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

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

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.

【讨论】:

  • 谢谢!所以我昨天实际上已经通过使用这个命令来实现它:ffmpeg -i /dev/video1 -r 30000/1001 -vcodec libx264 -pass 1 -coder 0 -bf 0 -flags -loop -wpredp 0 -f h264 pipe:1"libx264" 以 0.194 倍的速度编码并且解码得很好。 “复制”有 1x 但不会解码。 (百老汇 Javascript 解码器)。 libx264 和“复制”有什么区别?相机也是h264。 ffprobe 的输出:Input #0, video4linux2,v4l2, from '/dev/video1':Stream #0:0: Video: h264 (Main), yuv420p(progressive), 1920x1080, -5 kb/s, 30 fps, 30 tbr, 1000k tbn, 2000k tbc
  • libx264 是使用 x264 encoder 的 ffmpeg 名称,即软件,在 Raspberry 上非常慢。所以是的,没有解码错误,但是太慢了。
  • 编辑:确实保存了两个版本,libx264 是“基线”,副本是“主要”似乎百老汇只支持基线,所以我必须以某种方式将 h264 流近乎实时地转换为“基线” ”。这可能吗?
  • “改变”H.264 profile 从主要到基线需要解码 + 重新编码。这不是在 Raspberry Pi 上想要做的任何事情。
  • 哦,好吧,那么这台相机没用了 :) 可能需要查看 gstreamer 并拥有一个接收器,看看他们是否可以使它对 html 友好。但是相机有两个输入,一个是 h264 主输入,一个是原始视频。可能可以使用原始视频而不是仅使用 rpi hw 编码器进行编码(?)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-16
  • 2016-12-04
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多