Joh*_*ith 4 c video-capture mjpeg v4l2
作为V4L的新手,我决定开始使用video4linux2库,以便从C中捕捉相机中的帧(我正在使用带有Ricoh Co.相机的uvcvideo模块).我遵循了几个指南和教程,并设法获得一个正在运行的程序.我的问题主要是关于这个通常的代码行:
struct v4l2_format format = {0};
format.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
// ...
Run Code Online (Sandbox Code Playgroud)
这是我设置捕获时使用的实际视频格式的地方.如您所见,在此示例中,我使用的是MJPEG(http://lxr.free-electrons.com/source/include/uapi/linux/videodev2.h#L390).即使这可能是一个很好的格式,我的应用程序可能需要简单的RGB格式,我估计每像素像素.出于这个原因,我尝试使用RGB格式常量,如V4L2_PIX_FMT_RGB24.现在由于某种原因...... v4l2不喜欢它.我猜这与硬件有关,但我想尽可能避免MJPEG操作.出于测试目的,我尝试使用其他常量和格式,但无论我做什么,v4l2都不断改变pixelformat字段的值:
xioctl(fd, VIDIOC_S_FMT, &format); // This call succeeds with errno != EINTR.
if(format.fmt.pix.pixelformat != V4L2_PIX_FMT_RGB24){
// My program always enters this block when not using MJPEG.
fprintf(stderr, "Format wasn't accepted by v4l2.");
exit(4);
}
Run Code Online (Sandbox Code Playgroud)
现在我的问题是:有没有办法可以得到一个已接受的视频格式列表(我的意思是,我的相机/ v4l2接受),我可以从中找到除MJPEG以外的其他内容?如果你认为我必须坚持MJPEG,你会推荐我允许我操纵它的任何库,并最终在GUI框架中回退捕获吗?
我使用以下技巧测试我硬件上的所有可用格式.首先,一些shell脚本来获取所有格式的列表......
grep 'V4L2_PIX_FMT' /usr/include/linux/videodev2.h | grep define | tr '\t' ' ' | cut -d' ' -f2 | sed 's/$/,/g'
Run Code Online (Sandbox Code Playgroud)
...其输出在此C程序中使用:
int formats[] = {/* result of above command */};
int i = 0;
struct v4l2_format format = {0};
for(i = 0; i < /* number of lines in previous command output */; i++){
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.fmt.pix.width = 320;
format.fmt.pix.height = 240;
format.fmt.pix.pixelformat = formats[i];
format.fmt.pix.field = V4L2_FIELD_NONE;
if(xioctl(fd, VIDIOC_S_FMT, &format) != -1 && format.fmt.pix.pixelformat == formats[i])
fprintf(stderr, "Accepted : %d\n", i);
}
Run Code Online (Sandbox Code Playgroud)
该测试显示只有V4L2_PIX_FMT_YUYV并且V4L2_PIX_FMT_MJPEG功能正常.我可以用任何方式改进这个,还是与硬件有关?
在Linux中,命令行实用程序v4l2-ctl显示所有网络摄像头的本机支持格式 - 安装它sudo apt-get install v4l-utils,运行它与摄像机索引在v4l2-ctl -dX --list-formats-ext 哪里.这些格式通过模块报告给内核模块,网络摄像头芯片组本身支持这些格式.只有列出的格式所支持,什么都需要由用户进行编码,并且位RGB 非常很少提供,尽管几乎在拜耳RGGB工作的所有的CCD.迄今为止最常见的格式是YUV422(YUYV或YUY2)和MJPEG,具有一定的重叠:MJPEG为大分辨率实现更大的帧速率.X/dev/videoXv4l2uvcvideov4l2
用于列出相机格式的C++代码可以在Linux的Chromium GetDeviceSupportedFormats()实现中找到.
如果你必须插入代码将YUV转换为RGB我会推荐libyuv,它已针对大量架构进行了优化.
为了枚举可用的格式,您可以使用 ioctl VIDIOC_ENUM_FMT
要打印/dev/video0您支持的捕获格式的描述,可以像这样处理:
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/videodev2.h>
int main()
{
int fd = v4l2_open("/dev/video0", O_RDWR);
if (fd != -1)
{
struct v4l2_fmtdesc fmtdesc;
memset(&fmtdesc,0,sizeof(fmtdesc));
fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
while (ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc) == 0)
{
printf("%s\n", fmtdesc.description);
fmtdesc.index++;
}
v4l2_close(fd);
}
}
Run Code Online (Sandbox Code Playgroud)