4412 使用usb摄像头拍照YUYV格式
阅读原文时间:2023年07月15日阅读:1

一、内核设置

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架构的程序来操作摄像头

二、编写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 ;  

}

三、使用软件打开

不过要选择对应的格式:

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章