CPU 如何在没有完全解码的情况下从 h264 中提取运动矢量
How to extract motion vectors from h264 without a full decode on the CPU
我正在尝试将我的鼻子用作指示设备。计划是将来自指向我脸部的网络摄像头的视频流编码为 h264 或类似格式,获取运动矢量,稍微处理数字并将它们放入 /dev/uinput 中,使鼠标指针移动。 uinput 位很简单。
这必须在零可辨别的延迟下工作。例如:
#!/bin/bash
[ -p pipe.mkv ] || mkfifo pipe.mkv
ffmpeg -y -rtbufsize 1M -s 640x360 -vcodec mjpeg -i /dev/video0 -c h264_nvenc pipe.mkv &
ffplay -flags2 +export_mvs -vf codecview=mv=pf+bf+bb pipe.mkv
表明向量在那里,但有几秒钟的延迟,这在鼠标中是不可用的。我知道第一个 ffmpeg 步骤通过使用 GPU 工作得非常快,所以第二步中的管道或 h264 解码会引入延迟。
我在类似的管道布置中尝试了 MV Tractus(我认为与 mpegflow 相同),它也非常慢。他们在 CPU 上进行了完整的 h264 解码,我认为这是问题所在,因为我可以看到他们在一个 CPU 上施加了很多负载。如果管道因缓冲不良而导致延迟,则 CPU 不会被加载。我猜 ffplay 也在 CPU 上进行了解码,我无法说服它不这样做,但它只想画对我没有用的箭头。
我认为有几种方法,我想知道哪种方法最好,或者是否还有我不知道的更好的方法。我可以:
- 在硬件中解码并获得运动矢量。到目前为止,这已经失败了。我尝试组合 ffmpeg 的
extract_mvs.c
和 hw_decode.c
样本,但没有出现运动矢量。 vdpau 是我在 linux 盒子上工作的唯一解码器。我有一个 nvidia gpu。
- 对 h264 进行最少的解析以仅找出运动矢量,忽略所有其他数据。我认为这意味着在 libav 的解析器中加入某种“仅运动”选项,但我一点也不熟悉该代码。
- 找到其他一些具有上述选项的 h264 解析库,并解压容器。
- 忘掉硬件加速编码,使用精简的编码器只在 CPU 或 GPU 上制作运动矢量。我怀疑这会很慢,因为我认为计算运动矢量是算法中最难的部分。
我倾向于第二个选项,但我需要一些帮助来确定在 libav 代码中的哪个位置执行此操作。
非常有趣的项目!我不是 ffmpeg 专家,但在我看来,您的 ffmpeg 命令正在解码 /dev/video0 的 mjpeg 输出,然后将其编码为 h.264 以获得运动矢量。 h.264 编码步骤是计算密集型的,可能会导致您的延迟。您可以做一些事情来加快速度:(a)使用输出 h.264 而不是 mjpeg 的网络摄像头; (b) 运行 在更快的硬件上进行 h.264 编码和 (c) 在编码之前使用 ffmpeg 降低视频流的分辨率。例如,您可以在摄像机中定义一个小的“热区”,您的鼻子的运动可以在其中控制鼠标。
我正在尝试将我的鼻子用作指示设备。计划是将来自指向我脸部的网络摄像头的视频流编码为 h264 或类似格式,获取运动矢量,稍微处理数字并将它们放入 /dev/uinput 中,使鼠标指针移动。 uinput 位很简单。
这必须在零可辨别的延迟下工作。例如:
#!/bin/bash
[ -p pipe.mkv ] || mkfifo pipe.mkv
ffmpeg -y -rtbufsize 1M -s 640x360 -vcodec mjpeg -i /dev/video0 -c h264_nvenc pipe.mkv &
ffplay -flags2 +export_mvs -vf codecview=mv=pf+bf+bb pipe.mkv
表明向量在那里,但有几秒钟的延迟,这在鼠标中是不可用的。我知道第一个 ffmpeg 步骤通过使用 GPU 工作得非常快,所以第二步中的管道或 h264 解码会引入延迟。
我在类似的管道布置中尝试了 MV Tractus(我认为与 mpegflow 相同),它也非常慢。他们在 CPU 上进行了完整的 h264 解码,我认为这是问题所在,因为我可以看到他们在一个 CPU 上施加了很多负载。如果管道因缓冲不良而导致延迟,则 CPU 不会被加载。我猜 ffplay 也在 CPU 上进行了解码,我无法说服它不这样做,但它只想画对我没有用的箭头。
我认为有几种方法,我想知道哪种方法最好,或者是否还有我不知道的更好的方法。我可以:
- 在硬件中解码并获得运动矢量。到目前为止,这已经失败了。我尝试组合 ffmpeg 的
extract_mvs.c
和hw_decode.c
样本,但没有出现运动矢量。 vdpau 是我在 linux 盒子上工作的唯一解码器。我有一个 nvidia gpu。 - 对 h264 进行最少的解析以仅找出运动矢量,忽略所有其他数据。我认为这意味着在 libav 的解析器中加入某种“仅运动”选项,但我一点也不熟悉该代码。
- 找到其他一些具有上述选项的 h264 解析库,并解压容器。
- 忘掉硬件加速编码,使用精简的编码器只在 CPU 或 GPU 上制作运动矢量。我怀疑这会很慢,因为我认为计算运动矢量是算法中最难的部分。
我倾向于第二个选项,但我需要一些帮助来确定在 libav 代码中的哪个位置执行此操作。
非常有趣的项目!我不是 ffmpeg 专家,但在我看来,您的 ffmpeg 命令正在解码 /dev/video0 的 mjpeg 输出,然后将其编码为 h.264 以获得运动矢量。 h.264 编码步骤是计算密集型的,可能会导致您的延迟。您可以做一些事情来加快速度:(a)使用输出 h.264 而不是 mjpeg 的网络摄像头; (b) 运行 在更快的硬件上进行 h.264 编码和 (c) 在编码之前使用 ffmpeg 降低视频流的分辨率。例如,您可以在摄像机中定义一个小的“热区”,您的鼻子的运动可以在其中控制鼠标。