在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 }
原文地址:https://www.cnblogs.com/y4247464/p/15722722.html