1

我正在尝试使用 jni 下的 v4l2 在 android 上捕获视频。我找到了一些指南并按照以下步骤操作:

fd = open("/dev/video0", O_RDWR);

/* init part */
ioctl(fd, VIDIOC_QUERYCAP, &caps);
ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc);
ioctl(fd, VIDIOC_S_FMT, &fmt);
ioctl(fd, VIDIOC_REQBUFS, &req);
ioctl(fd, VIDIOC_QUERYBUF, &buf);
ioctl(fd, VIDIOC_QBUF, &buf);

/* capture part */
FILE *fp = fopen("/sdcard/img.yuv", "wb");
for (i = 0; i < 20; i++)
{
    ioctl(fd, VIDIOC_DQBUF, &buf);
    fwrite(buffers[buf.index].start, 1, buf.bytesused, fp);
    ioctl(fd, VIDIOC_QBUF, &buf);
}
fclose(fp);

这是我的代码的主要结构。所有函数都正确运行并返回 0。但是,当我用二进制查看器打开输出文件时,我发现所有数据都是 0。

我的代码有问题吗?我很困惑,因为所有函数都返回 0。

谢谢!!

4

1 回答 1

0

您正在使用一个名为 buffers[] 的数组。但我看不到它在哪里声明或它代表什么。如果上面没有缺少代码,您将始终得到零,因为您正在将 buffer[] 写入文件而不是从 v4l2 获得的内容。此外,在 ioctl 命令之前的 caps、fmtdesc、fmt、req 和 buf 的初始值也会很有趣。根据它们的初始值,您将拥有不同的通信接口。问题可能隐藏在这些部分中。

正如您在问题中所写,所有 ioctl 命令都将返回 0,应该没有错误。如果一切都按预期运行。检查问题的另一种方法是致电

perror("<your comment or hint to line above>");

在每个 ioctl 命令之后。这将在您的标准输出上打印有关错误的更多信息。(有关 perror 的更多详细信息可以在此线程中找到我应该何时使用 perror("...") 和 fprintf(stderr, "...")?

您是否尝试从相机中获取图像?(在某些手机上,您上面使用的 video0 是后置摄像头)在某些 android 设备上,必须使用除 videoXY 之外的其他设备驱动程序通过复杂的程序启动摄像头。在官方相机应用程序运行时尝试从 video0 获取图像可能很困难。官方 v4l2 api 说:

V4L2 驱动程序不应支持多个应用程序通过复制缓冲区、时间复用或类似方式在设备上读取或写入相同的数据流。这最好由用户空间中的代理应用程序处理。

来自: http: //linuxtv.org/downloads/v4l-dvb-apis/common.html#idp18553208

您可以发布更多(详细)代码吗?我可能会提供帮助,因为我正在做非常相似的事情。

为了能够重现它,您正在使用哪个 android 设备(类型/型号/android 版本)会非常有趣。

于 2014-05-01T12:09:58.603 回答