在V4l2框架下采集UVC摄像头的YUV与JPEG数据

#include <errno.h> #include <fcntl.h> #include <linux/videodev2.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <sys/prctl.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h>

#define VIDEO_NAME "/dev/video0" #define TEST_STREAM_SAVE_PATH "/customer/nfs" #define BUFFER_NUM (4) #define V4L2_BUF_TYPE (V4L2_BUF_TYPE_VIDEO_CAPTURE) static int g_video_fd;
typedef struct { void *start; int length; } BUFTYPE;
BUFTYPE *usr_buf; static unsigned int n_buffer = 0;
static int camera_Open(void) { struct v4l2_input inp; int i = 0; int ret = -1; g_video_fd = open(VIDEO_NAME, O_RDWR | O_NONBLOCK, 0); if (g_video_fd < 0) { printf("%s open failed ! \n", VIDEO_NAME); return ret; };
for (i = 0; i < 16; i++) { inp.index = i; if (-1 == ioctl(g_video_fd, VIDIOC_S_INPUT, &inp)) { printf("VIDIOC_S_INPUT failed %d !\n", i); } else { printf("VIDIOC_S_INPUT success %d !\n", i); ret = 0; break; } }
return ret; }
// close void camera_Close(int video_fd) { unsigned int i;
for (i = 0; i < n_buffer; i++) { if (-1 == munmap(usr_buf[i].start, usr_buf[i].length)) { exit(-1); } }
if (NULL != usr_buf) free(usr_buf);
if (video_fd > 0) close(video_fd);
return; }
/*set video capture ways(mmap)*/ int init_mmap(int fd) { /*to request frame cache, contain requested counts*/ struct v4l2_requestbuffers reqbufs;
memset(&reqbufs, 0, sizeof(reqbufs)); reqbufs.count = BUFFER_NUM; /*the number of buffer*/ reqbufs.type = V4L2_BUF_TYPE; reqbufs.memory = V4L2_MEMORY_MMAP;
if (-1 == ioctl(fd, VIDIOC_REQBUFS, &reqbufs)) { perror("Fail to ioctl 'VIDIOC_REQBUFS'"); return -1; }
n_buffer = reqbufs.count; printf("n_buffer = %d\n", n_buffer); usr_buf = calloc(reqbufs.count, sizeof(BUFTYPE)); if (usr_buf == NULL) { printf("Out of memory\n"); return -1; }
/*map kernel cache to user process*/ for (n_buffer = 0; n_buffer < reqbufs.count; n_buffer++) { // stand for a frame struct v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE; buf.memory = V4L2_MEMORY_MMAP; buf.index = n_buffer;
/*check the information of the kernel cache requested*/ if (-1 == ioctl(fd, VIDIOC_QUERYBUF, &buf)) { perror("Fail to ioctl : VIDIOC_QUERYBUF"); return -1; } printf("buf length = %d",buf.length);
usr_buf[n_buffer].length = buf.length; usr_buf[n_buffer].start = (char *)mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
if (MAP_FAILED == usr_buf[n_buffer].start) { perror("Fail to mmap"); return -1; } }
return 0; }
static int set_Format(int video_fd) { struct v4l2_format tv_fmt; /* frame format */
/*set the form of camera capture data*/ tv_fmt.type = V4L2_BUF_TYPE; /*v4l2_buf_typea,camera must use V4L2_BUF_TYPE_VIDEO_CAPTURE*/ tv_fmt.fmt.pix.width = 1280; tv_fmt.fmt.pix.height = 720; tv_fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG; tv_fmt.fmt.pix.field = V4L2_FIELD_NONE; /*V4L2_FIELD_NONE*/ if (ioctl(video_fd, VIDIOC_S_FMT, &tv_fmt) < 0) { fprintf(stderr, "VIDIOC_S_FMT set err\n"); return -1; } return 0; } static int init_Camera(int video_fd) { struct v4l2_capability cap; /* decive fuction, such as video input */ struct v4l2_fmtdesc fmtdesc; /* detail control value */
int ret = 0; if (video_fd <= 0) return -1;
/*show all the support format*/ memset(&fmtdesc, 0, sizeof(fmtdesc)); fmtdesc.index = 0; /* the number to check */ fmtdesc.type = V4L2_BUF_TYPE;
/* check video decive driver capability */ if (ret = ioctl(video_fd, VIDIOC_QUERYCAP, &cap) < 0) { fprintf(stderr, "fail to ioctl VIDEO_QUERYCAP \n"); return -1; }
/*judge wherher or not to be a video-get device*/ if (!(cap.capabilities & V4L2_BUF_TYPE)) { fprintf(stderr, "The Current device is not a video capture device \n"); return -1; }
/*judge whether or not to supply the form of video stream*/ if (!(cap.capabilities & V4L2_CAP_STREAMING)) { printf("The Current device does not support streaming i/o\n"); return -1; }
printf("\ncamera driver name is : %s\n", cap.driver); printf("camera device name is : %s\n", cap.card); printf("camera bus information: %s\n", cap.bus_info);
/*display the format device support*/ printf("\n"); while (ioctl(video_fd, VIDIOC_ENUM_FMT, &fmtdesc) != -1) { printf("support device %d.%s\n", fmtdesc.index + 1, fmtdesc.description); fmtdesc.index++; } printf("\n");
return 0; }
int start_capture(int fd) { unsigned int i; enum v4l2_buf_type type;
/*place the kernel cache to a queue*/ for (i = 0; i < n_buffer; i++) { struct v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE; buf.memory = V4L2_MEMORY_MMAP; buf.index = i;
if (-1 == ioctl(fd, VIDIOC_QBUF, &buf)) { perror("Fail to ioctl 'VIDIOC_QBUF'"); exit(EXIT_FAILURE); } }
type = V4L2_BUF_TYPE; if (-1 == ioctl(fd, VIDIOC_STREAMON, &type)) { printf("i=%d.\n", i); perror("VIDIOC_STREAMON"); close(fd); exit(EXIT_FAILURE); }
return 0; }
int process_image(void *addr, int length) { FILE *fp; static int num = 0; char image_name[64] = {0};
sprintf(image_name, TEST_STREAM_SAVE_PATH "/%d.jpeg", num++); if ((fp = fopen(image_name, "w")) == NULL) { perror("Fail to fopen \n"); exit(EXIT_FAILURE); } fwrite(addr, length, 1, fp); usleep(500); fclose(fp);
return 0; }
int read_frame(int fd) { struct v4l2_buffer buf;
memset(&buf, 0, sizeof(buf)); buf.type = V4L2_BUF_TYPE; buf.memory = V4L2_MEMORY_MMAP;
// put cache from queue if (-1 == ioctl(fd, VIDIOC_DQBUF, &buf)) { perror("Fail to ioctl 'VIDIOC_DQBUF'"); return -1; } if (buf.index >= n_buffer) return -1; // printf("length=%d", usr_buf[buf.index].length); printf("bytesused=%d", buf.bytesused); usr_buf[buf.index].length = buf.bytesused; // read process space's data to a file process_image(usr_buf[buf.index].start, usr_buf[buf.index].length);
if (-1 == ioctl(fd, VIDIOC_QBUF, &buf)) { perror("Fail to ioctl 'VIDIOC_QBUF'"); return -1; }
return 0; }
static int stop_Capture(int fd) { enum v4l2_buf_type type; type = V4L2_BUF_TYPE; if (-1 == ioctl(fd, VIDIOC_STREAMOFF, &type)) { perror("Fail to ioctl 'VIDIOC_STREAMOFF' \n"); return -1; } return 0; }
int mainloop(int fd) { int count = 10; while (count-- > 0) { while (1) { fd_set fds; struct timeval tv; int r;
FD_ZERO(&fds); FD_SET(fd, &fds);
/*Timeout*/ tv.tv_sec = 2; tv.tv_usec = 0; r = select(fd + 1, &fds, NULL, NULL, &tv);
if (-1 == r) { if (EINTR == errno) continue; perror("Fail to select \n"); return -1; } if (0 == r) { fprintf(stderr, "select Timeout \n"); return -1; }
if (read_frame(fd) == 0) break; } } return 0; }
int UVC_Init(void) { int s32Ret = 0;
// 1 open device s32Ret = camera_Open(); if (s32Ret < 0) { printf("HI_PDT_Camera_Open failed ! \n"); return -1; }
// Check and set device properties set frame s32Ret = init_Camera(g_video_fd); if (s32Ret < 0) { printf("HI_PDT_Camera_Open failed ! \n"); camera_Close(g_video_fd); return -1; }
set_Format(g_video_fd);
// Apply for a video buffer init_mmap(g_video_fd); start_capture(g_video_fd); mainloop(g_video_fd); return 0; }
int UVC_DeInit(void) { stop_Capture(g_video_fd); camera_Close(g_video_fd); return 0; }
int main() { UVC_Init(); UVC_DeInit(); return 0; }

上一篇:影像算法解析——JPEG 压缩算法


下一篇:JS图片切换,焦点对齐,自定义索引的使用