我正在尝试在 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。
谢谢!!
您正在使用一个名为 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 是后置摄像头)在某些安卓设备上,相机必须使用videoXY以外的其他设备驱动程序通过复杂的程序启动。在官方相机应用程序运行时尝试从 video0 获取图像可能很困难。官方 v4l2 API 说:
V4L2 驱动程序不应支持多个应用程序通过复制缓冲区、时间多路复用或类似方式在设备上读取或写入相同的数据流。这最好由用户空间中的代理应用程序处理。
寄件人: http://linuxtv.org/downloads/v4l-dvb-apis/common.html#idp18553208
你能发布更多(详细)代码吗?我也许能帮上忙,因为我正在做非常相似的事情。
为了能够重现它,您使用的安卓设备(类型/型号/安卓版本)会非常有趣。