Linux内核中已经带有很完善的USB摄像头驱动,支持几乎所有的USB摄像头,我们只需要配置内核,选择上相应的Sensor型号即可。
配置内核,支持USB摄像头:
Device Drivers --->
<\*> Multimedia support --->
<\*> Video For Linux
\[\*\] Enable Video For Linux API (DEPRECATED)
\[\*\] Video capture adapters --->
\[\*\] V4L USB devices --->
<\*> USB Video Class (UVC)
\[\*\] UVC input events device support
\[\*\] GSPCA based webcams --->
到这里,我们就可以选择所需要的USB摄像头驱动,当然也可以选择所有的USB摄像头驱动支持(这样编译出的内核会比较大)
GSPCA是一个万能摄像头驱动程序,进入GSPCA based webcams进行选择。
插入USB摄像头(我使用的UVC摄像头),会提示:
usb 1-1.1: new full speed USB device using s3c2410-ohci and address 3
usb 1-1.1: New USB device found, idVendor=0ac8, idProduct=3450
usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-1.1: Product: Deasy USB2.0 Camera
usb 1-1.1: Manufacturer: Vimicro Corp.
uvcvideo: Found UVC 1.00 device Deasy USB2.0 Camera (0ac8:3450)
input: Deasy USB2.0 Camera as
/devices/platform/s3c2410-ohci/usb1/1-1/1-1.1/1-1.1:1.0/input/input3
它的设备名称是:/dev/video0
USB摄像头一般都是基于V4L2架构的,需要编写V4L2架构的程序来操作摄像头
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define CAMERA_DEVICE "/dev/video0"
#define CAPTURE_FILE "frame.jpg"
#define VIDEO_WIDTH 640
#define VIDEO_HEIGHT 480
#define VIDEO_FORMAT V4L2_PIX_FMT_YUYV
#define BUFFER_COUNT 4
typedef struct VideoBuffer {
void *start;
size_t length;
}VideoBuffer;
int fd; //摄像头文件描述符
void open_camera(char *path);
void get_camera_info();
void get_vedio_info();
//打开设备
void open_camera(char *path)
{
fd = open(CAMERA_DEVICE, O_RDWR, );
if(fd < ) {
printf("Open %s failed\n", CAMERA_DEVICE);
exit(EXIT_FAILURE);
}
}
//获取驱动信息
void get_camera_info()
{
struct v4l2_capability cap;
ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
if(ret < ) {
printf("VIDIOC_QUERYCAP failed (%d)\n", ret);
return ret;
}
// Print capability informations
printf("Capbility Informations:\n");
printf("*\tdriver: %s\n", cap.driver);
printf("*\tcard: %s\n", cap.card);
printf("*\tbus_info: %s\n", cap.bus_info);
printf("*\tversion: %08X\n", cap.version);
printf("*\tcapabilities: %08X\n", cap.capabilities);
}
//获取视频格式
void get_vedio_info()
{
struct v4l2_format fmt;
memset(&fmt, , sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
ret = ioctl(fd, VIDIOC_G_FMT, &fmt);
if(ret < ) {
printf("VIDIOC_G_FMT failed (%d)\n", ret);
return ret;
}
// Print Stream Format
printf("Stream Format Informations:\n");
printf("*\ttype: %d\n", fmt.type);
printf("*\twidth: %d\n", fmt.fmt.pix.width);
printf("*\theight: %d\n", fmt.fmt.pix.height);
char fmtstr\[\];
memset(fmtstr, , );
memcpy(fmtstr, &fmt.fmt.pix.pixelformat, );
printf("\*\\tpixelformat: %s\\n", fmtstr);
printf("\*\\tfield: %d\\n", fmt.fmt.pix.field);
printf("\*\\tbytesperline: %d\\n", fmt.fmt.pix.bytesperline);
printf("\*\\tsizeimage: %d\\n", fmt.fmt.pix.sizeimage);
printf("\*\\tcolorspace: %d\\n", fmt.fmt.pix.colorspace);
printf("\*\\tpriv: %d\\n", fmt.fmt.pix.priv);
// printf("\*\\traw\_data: %s\\n", fmt.fmt.raw\_data);
/\* 显示所有支持的格式 \*/
struct v4l2\_fmtdesc fmtdesc;
fmtdesc.index = ;
fmtdesc.type = V4L2\_BUF\_TYPE\_VIDEO\_CAPTURE;
printf("Support format:\\n");
while(ioctl(fd, VIDIOC\_ENUM\_FMT, &fmtdesc) != -) {
printf("\\t%d.%s\\n", fmtdesc.index+, fmtdesc.description);
fmtdesc.index++;
}
}
int main()
{
int i, ret;
open_camera(CAMERA_DEVICE);
get\_camera\_info();
get\_vedio\_info();
//请求分配内存
struct v4l2\_requestbuffers reqbuf;
reqbuf.count = BUFFER\_COUNT;
reqbuf.type = V4L2\_BUF\_TYPE\_VIDEO\_CAPTURE;
reqbuf.memory = V4L2\_MEMORY\_MMAP;
ret = ioctl(fd, VIDIOC\_REQBUFS, &reqbuf);
if(ret < ) {
printf("VIDIOC\_REQBUFS failed (%d)\\n", ret);
return ret;
}
//获取空间
VideoBuffer \*buffers = calloc(reqbuf.count, sizeof(\*buffers));
if(!buffers) {
//映射
fprintf(stderr, "Out of memory\\n");
exit(EXIT\_FAILURE);
}
for(i=;i<reqbuf.count;i++) {
struct v4l2\_buffer buf;
memset(&buf, , sizeof(buf));
buf.index = i;
buf.type = V4L2\_BUF\_TYPE\_VIDEO\_CAPTURE;
buf.memory = V4L2\_MEMORY\_MMAP;
ret = ioctl(fd, VIDIOC\_QUERYBUF, &buf);
if(ret < ) {
printf("VIDIOC\_QUERYBUF (%d) failed (%d)\\n", i, ret);
return ret;
}
// mmap buffer
buffers\[i\].length = buf.length;
buffers\[i\].start = (char \*)mmap(, buf.length, PROT\_READ|PROT\_WRITE, MAP\_SHARED,
fd, buf.m.offset);
if(buffers\[i\].start == MAP\_FAILED) {
printf("mmap (%d) failed: %s\\n", i, strerror(errno));
return -;
}
// Queen buffer
ret = ioctl(fd, VIDIOC\_QBUF, &buf);
if(ret < ) {
printf("VIDIOC\_QBUF (%d) failed (%d)\\n", i, ret);
return -;
}
printf("Frame buffer: %d: address=0x%x, length=%d\\n", i,
(unsigned int)buffers\[i\].start, buffers\[i\].length);
}
// 开始录制
struct v4l2\_buffer buf;
enum v4l2\_buf\_type type = V4L2\_BUF\_TYPE\_VIDEO\_CAPTURE;
buf.index = ;
buf.type = V4L2\_BUF\_TYPE\_VIDEO\_CAPTURE;
buf.memory = V4L2\_MEMORY\_MMAP;
ret = ioctl(fd, VIDIOC\_STREAMON, &type);
if (ret < ) {
printf("VIDIOC\_STREAMON failed (%d)\\n", ret);
return ret;
}
// Get frame
ret = ioctl(fd, VIDIOC\_DQBUF, &buf);
if (ret < ) {
printf("VIDIOC\_DQBUF failed (%d)\\n", ret);
return ret;
}
// Process the frame
FILE \*fp = fopen(CAPTURE\_FILE, "wb");
if (fp < ) {
printf("open frame data file failed\\n");
return -;
}
fwrite(buffers\[buf.index\].start, , buf.length, fp);
fclose(fp);
printf("Capture one frame saved in %s\\n", CAPTURE\_FILE);
// Re-queen buffer
ret = ioctl(fd, VIDIOC\_QBUF, &buf);
if (ret < ) {
printf("VIDIOC\_QBUF failed (%d)\\n", ret);
return ret;
}
// Release the resource
for(i=;i<;i++) {
munmap(buffers\[i\].start, buffers\[i\].length);
}
close(fd);
printf("Camera test Done.\\n");
return ;
}
不过要选择对应的格式:
手机扫一扫
移动阅读更方便
你可能感兴趣的文章