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


    采集YUYV422/ jpeg 数据

    jpeg是编码压缩后的格式,在获取buf中的数据时,一定要是实际的大小:

    v4l2_buffer --> buf.bytesused
      1 #include <errno.h>
      2 #include <fcntl.h>
      3 #include <linux/videodev2.h>
      4 #include <pthread.h>
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 #include <string.h>
      8 #include <sys/ioctl.h>
      9 #include <sys/mman.h>
     10 #include <sys/prctl.h>
     11 #include <sys/stat.h>
     12 #include <sys/types.h>
     13 #include <unistd.h>
     14 
     15 
     16 #define VIDEO_NAME "/dev/video0"
     17 #define TEST_STREAM_SAVE_PATH "/customer/nfs"
     18 #define BUFFER_NUM (4)
     19 #define V4L2_BUF_TYPE (V4L2_BUF_TYPE_VIDEO_CAPTURE)
     20 #define V4L2_PIX_FORMAT (V4L2_PIX_FMT_MJPEG)  //or V4L2_PIX_FMT_YUYV
     21 static int g_video_fd;
     22 
     23 typedef struct {
     24     void *start;
     25     int length;
     26 } BUFTYPE;
     27 
     28 BUFTYPE *usr_buf;
     29 static unsigned int n_buffer = 0;
     30 
     31 static int camera_Open(void) {
     32     struct v4l2_input inp;
     33     int i = 0;
     34     int ret = -1;
     35     g_video_fd = open(VIDEO_NAME, O_RDWR | O_NONBLOCK, 0);
     36     if (g_video_fd < 0) {
     37         printf("%s open failed ! \n", VIDEO_NAME);
     38         return ret;
     39     };
     40 
     41     for (i = 0; i < 16; i++) {
     42         inp.index = i;
     43         if (-1 == ioctl(g_video_fd, VIDIOC_S_INPUT, &inp)) {
     44             printf("VIDIOC_S_INPUT  failed %d !\n", i);
     45         } else {
     46             printf("VIDIOC_S_INPUT  success %d !\n", i);
     47             ret = 0;
     48             break;
     49         }
     50     }
     51 
     52     return ret;
     53 }
     54 
     55 // close
     56 void camera_Close(int video_fd) {
     57     unsigned int i;
     58 
     59     for (i = 0; i < n_buffer; i++) {
     60         if (-1 == munmap(usr_buf[i].start, usr_buf[i].length)) {
     61             exit(-1);
     62         }
     63     }
     64 
     65     if (NULL != usr_buf) free(usr_buf);
     66 
     67     if (video_fd > 0) close(video_fd);
     68 
     69     return;
     70 }
     71 
     72 /*set video capture ways(mmap)*/
     73 int init_mmap(int fd) {
     74     /*to request frame cache, contain requested counts*/
     75     struct v4l2_requestbuffers reqbufs;
     76 
     77     memset(&reqbufs, 0, sizeof(reqbufs));
     78     reqbufs.count = BUFFER_NUM; /*the number of buffer*/
     79     reqbufs.type = V4L2_BUF_TYPE;
     80     reqbufs.memory = V4L2_MEMORY_MMAP;
     81 
     82     if (-1 == ioctl(fd, VIDIOC_REQBUFS, &reqbufs)) {
     83         perror("Fail to ioctl 'VIDIOC_REQBUFS'");
     84         return -1;
     85     }
     86 
     87     n_buffer = reqbufs.count;
     88     printf("n_buffer = %d\n", n_buffer);
     89     usr_buf = calloc(reqbufs.count, sizeof(BUFTYPE));
     90     if (usr_buf == NULL) {
     91         printf("Out of memory\n");
     92         return -1;
     93     }
     94 
     95     /*map kernel cache to user process*/
     96     for (n_buffer = 0; n_buffer < reqbufs.count; n_buffer++) {
     97         // stand for a frame
     98         struct v4l2_buffer buf;
     99         memset(&buf, 0, sizeof(buf));
    100         buf.type = V4L2_BUF_TYPE;
    101         buf.memory = V4L2_MEMORY_MMAP;
    102         buf.index = n_buffer;
    103 
    104         /*check the information of the kernel cache requested*/
    105         if (-1 == ioctl(fd, VIDIOC_QUERYBUF, &buf)) {
    106             perror("Fail to ioctl : VIDIOC_QUERYBUF");
    107             return -1;
    108         }
    109         printf("buf length = %d",buf.length);
    110 
    111         usr_buf[n_buffer].length = buf.length;
    112         usr_buf[n_buffer].start =
    113             (char *)mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED,
    114                          fd, buf.m.offset);
    115 
    116         if (MAP_FAILED == usr_buf[n_buffer].start) {
    117             perror("Fail to mmap");
    118             return -1;
    119         }
    120     }
    121 
    122     return 0;
    123 }
    124 
    125 static int set_Format(int video_fd) {
    126     struct v4l2_format tv_fmt; /* frame format */
    127 
    128     /*set the form of camera capture data*/
    129     tv_fmt.type = V4L2_BUF_TYPE; /*v4l2_buf_typea,camera must use
    130                                     V4L2_BUF_TYPE_VIDEO_CAPTURE*/
    131     tv_fmt.fmt.pix.width = 1280;
    132     tv_fmt.fmt.pix.height = 720;
    133     tv_fmt.fmt.pix.pixelformat = V4L2_PIX_FORMAT;
    134     tv_fmt.fmt.pix.field = V4L2_FIELD_NONE; /*V4L2_FIELD_NONE*/
    135     if (ioctl(video_fd, VIDIOC_S_FMT, &tv_fmt) < 0) {
    136         fprintf(stderr, "VIDIOC_S_FMT set err\n");
    137         return -1;
    138     }
    139     return 0;
    140 }
    141 static int init_Camera(int video_fd) {
    142     struct v4l2_capability cap;  /* decive fuction, such as video input */
    143     struct v4l2_fmtdesc fmtdesc; /* detail control value */
    144 
    145     int ret = 0;
    146     if (video_fd <= 0) return -1;
    147 
    148     /*show all the support format*/
    149     memset(&fmtdesc, 0, sizeof(fmtdesc));
    150     fmtdesc.index = 0; /* the number to check */
    151     fmtdesc.type = V4L2_BUF_TYPE;
    152 
    153     /* check video decive driver capability */
    154     if (ret = ioctl(video_fd, VIDIOC_QUERYCAP, &cap) < 0) {
    155         fprintf(stderr, "fail to ioctl VIDEO_QUERYCAP \n");
    156         return -1;
    157     }
    158 
    159     /*judge wherher or not to be a video-get device*/
    160     if (!(cap.capabilities & V4L2_BUF_TYPE)) {
    161         fprintf(stderr, "The Current device is not a video capture device \n");
    162         return -1;
    163     }
    164 
    165     /*judge whether or not to supply the form of video stream*/
    166     if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
    167         printf("The Current device does not support streaming i/o\n");
    168         return -1;
    169     }
    170 
    171     printf("\ncamera driver name is : %s\n", cap.driver);
    172     printf("camera device name is : %s\n", cap.card);
    173     printf("camera bus information: %s\n", cap.bus_info);
    174 
    175     /*display the format device support*/
    176     printf("\n");
    177     while (ioctl(video_fd, VIDIOC_ENUM_FMT, &fmtdesc) != -1) {
    178         printf("support device %d.%s\n", fmtdesc.index + 1,
    179                fmtdesc.description);
    180         fmtdesc.index++;
    181     }
    182     printf("\n");
    183 
    184     return 0;
    185 }
    186 
    187 int start_capture(int fd) {
    188     unsigned int i;
    189     enum v4l2_buf_type type;
    190 
    191     /*place the kernel cache to a queue*/
    192     for (i = 0; i < n_buffer; i++) {
    193         struct v4l2_buffer buf;
    194         memset(&buf, 0, sizeof(buf));
    195         buf.type = V4L2_BUF_TYPE;
    196         buf.memory = V4L2_MEMORY_MMAP;
    197         buf.index = i;
    198 
    199         if (-1 == ioctl(fd, VIDIOC_QBUF, &buf)) {
    200             perror("Fail to ioctl 'VIDIOC_QBUF'");
    201             exit(EXIT_FAILURE);
    202         }
    203     }
    204 
    205     type = V4L2_BUF_TYPE;
    206     if (-1 == ioctl(fd, VIDIOC_STREAMON, &type)) {
    207         printf("i=%d.\n", i);
    208         perror("VIDIOC_STREAMON");
    209         close(fd);
    210         exit(EXIT_FAILURE);
    211     }
    212 
    213     return 0;
    214 }
    215 
    216 int process_image(void *addr, int length) {
    217     FILE *fp;
    218     static int num = 0;
    219     char image_name[64] = {0};
    220 
    221     sprintf(image_name, TEST_STREAM_SAVE_PATH "/%d.jpeg", num++);
    222     if ((fp = fopen(image_name, "w")) == NULL) {
    223         perror("Fail to fopen \n");
    224         exit(EXIT_FAILURE);
    225     }
    226     fwrite(addr, length, 1, fp);
    227     usleep(500);
    228     fclose(fp);
    229 
    230     return 0;
    231 }
    232 
    233 int read_frame(int fd) {
    234     struct v4l2_buffer buf;
    235 
    236     memset(&buf, 0, sizeof(buf));
    237     buf.type = V4L2_BUF_TYPE;
    238     buf.memory = V4L2_MEMORY_MMAP;
    239 
    240     // put cache from queue
    241     if (-1 == ioctl(fd, VIDIOC_DQBUF, &buf)) {
    242         perror("Fail to ioctl 'VIDIOC_DQBUF'");
    243         return -1;
    244     }
    245     if (buf.index >= n_buffer) return -1;
    246     // printf("length=%d", usr_buf[buf.index].length);
    247     printf("bytesused=%d, buf length=%d", buf.bytesused, buf.length);
    248     if(V4L2_PIX_FORMAT == V4L2_PIX_FMT_MJPEG){
    249         usr_buf[buf.index].length = buf.bytesused;
    250     }
    251     // read process space's data to a file
    252     process_image(usr_buf[buf.index].start, usr_buf[buf.index].length);
    253 
    254     if (-1 == ioctl(fd, VIDIOC_QBUF, &buf)) {
    255         perror("Fail to ioctl 'VIDIOC_QBUF'");
    256         return -1;
    257     }
    258 
    259     return 0;
    260 }
    261 
    262 static int stop_Capture(int fd) {
    263     enum v4l2_buf_type type;
    264     type = V4L2_BUF_TYPE;
    265     if (-1 == ioctl(fd, VIDIOC_STREAMOFF, &type)) {
    266         perror("Fail to ioctl 'VIDIOC_STREAMOFF' \n");
    267         return -1;
    268     }
    269     return 0;
    270 }
    271 
    272 int mainloop(int fd) {
    273     int count = 10;
    274     while (count-- > 0) {
    275         while (1) {
    276             fd_set fds;
    277             struct timeval tv;
    278             int r;
    279 
    280             FD_ZERO(&fds);
    281             FD_SET(fd, &fds);
    282 
    283             /*Timeout*/
    284             tv.tv_sec = 2;
    285             tv.tv_usec = 0;
    286             r = select(fd + 1, &fds, NULL, NULL, &tv);
    287 
    288             if (-1 == r) {
    289                 if (EINTR == errno) continue;
    290                 perror("Fail to select \n");
    291                 return -1;
    292             }
    293             if (0 == r) {
    294                 fprintf(stderr, "select Timeout \n");
    295                 return -1;
    296             }
    297 
    298             if (read_frame(fd) == 0) break;
    299         }
    300     }
    301     return 0;
    302 }
    303 
    304 int UVC_Init(void) {
    305     int s32Ret = 0;
    306 
    307     // 1 open device
    308     s32Ret = camera_Open();
    309     if (s32Ret < 0) {
    310         printf("HI_PDT_Camera_Open failed ! \n");
    311         return -1;
    312     }
    313 
    314     // Check and set device properties  set frame
    315     s32Ret = init_Camera(g_video_fd);
    316     if (s32Ret < 0) {
    317         printf("HI_PDT_Camera_Open failed ! \n");
    318         camera_Close(g_video_fd);
    319         return -1;
    320     }
    321 
    322     set_Format(g_video_fd);
    323 
    324     // Apply for a video buffer
    325     init_mmap(g_video_fd);
    326     start_capture(g_video_fd);
    327     mainloop(g_video_fd);
    328     return 0;
    329 }
    330 
    331 int UVC_DeInit(void) {
    332     stop_Capture(g_video_fd);
    333     camera_Close(g_video_fd);
    334     return 0;
    335 }
    336 
    337 int main() {
    338    UVC_Init();
    339    UVC_DeInit();
    340     return 0;
    341 }
  • 相关阅读:
    Attributes.Add用途与用法
    Reapter控件中更换Td背景色
    SQL SERVER查询时间条件式写法
    C# Cache何时使用及使用方法
    C#中Cache用法
    用sql语句将两个时间相减,得到时间距的DateDiff()函数
    HTML5 带进度条的异步文件上传原理
    Node环境Grunt开发流
    HTML5的Web SQL Databases(html5 本地数据库)API
    移动端范围拖动选择效果
  • 原文地址:https://www.cnblogs.com/y4247464/p/15722722.html
Copyright © 2020-2023  润新知