blob: 89442706c5ec092c4e8076e9a4fd6ad48b2e7da6 [file] [log] [blame]
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * Contains code that is used to capture video frames from a camera device
19 * on Linux. This code uses V4L2 API to work with camera devices, and requires
20 * Linux kernel version at least 2.5
21 */
22
23#include <sys/mman.h>
24#include <sys/stat.h>
25#include <sys/ioctl.h>
26#include <linux/videodev2.h>
27#include "qemu-common.h"
28#include "android/utils/debug.h"
29#include "android/utils/misc.h"
30#include "android/utils/system.h"
31#include "android/camera/camera-capture.h"
32#include "android/camera/camera-format-converters.h"
33
34#define D(...) VERBOSE_PRINT(camera,__VA_ARGS__)
35#define W(...) VERBOSE_PRINT(camera,__VA_ARGS__)
36#define E(...) VERBOSE_PRINT(camera,__VA_ARGS__)
37#define D_ACTIVE VERBOSE_CHECK(camera)
38
39/* the T(...) macro is used to dump traffic */
40#define T_ACTIVE 0
41
42#if T_ACTIVE
43#define T(...) VERBOSE_PRINT(camera,__VA_ARGS__)
44#else
45#define T(...) ((void)0)
46#endif
47
48#define CLEAR(x) memset (&(x), 0, sizeof(x))
49
50/* Describes a framebuffer. */
51typedef struct CameraFrameBuffer {
52 /* Framebuffer data. */
53 uint8_t* data;
54 /* Framebuffer data size. */
55 size_t size;
56} CameraFrameBuffer;
57
58/* Defines type of the I/O used to obtain frames from the device. */
59typedef enum CameraIoType {
60 /* Framebuffers are shared via memory mapping. */
61 CAMERA_IO_MEMMAP,
62 /* Framebuffers are available via user pointers. */
63 CAMERA_IO_USERPTR,
64 /* Framebuffers are to be read from the device. */
65 CAMERA_IO_DIRECT
66} CameraIoType;
67
68typedef struct LinuxCameraDevice LinuxCameraDevice;
69/*
70 * Describes a connection to an actual camera device.
71 */
72struct LinuxCameraDevice {
73 /* Common header. */
74 CameraDevice header;
75
76 /* Camera device name. (default is /dev/video0) */
77 char* device_name;
78 /* Input channel. (default is 0) */
79 int input_channel;
80 /* Requested pixel format. */
81 uint32_t req_pixel_format;
82
83 /*
84 * Set by the framework after initializing camera connection.
85 */
86
87 /* Handle to the opened camera device. */
88 int handle;
89 /* Device capabilities. */
90 struct v4l2_capability caps;
91 /* Actual pixel format reported by the device. */
92 struct v4l2_pix_format actual_pixel_format;
93 /* Defines type of the I/O to use to retrieve frames from the device. */
94 CameraIoType io_type;
95 /* Allocated framebuffers. */
96 struct CameraFrameBuffer* framebuffers;
97 /* Actual number of allocated framebuffers. */
98 int framebuffer_num;
99};
100
101/*******************************************************************************
102 * Helper routines
103 ******************************************************************************/
104
105/* IOCTL wrapper. */
106static int
107_xioctl(int fd, int request, void *arg) {
108 int r;
109 do {
110 r = ioctl(fd, request, arg);
111 } while (-1 == r && EINTR == errno);
112 return r;
113}
114
115/*******************************************************************************
116 * CameraFrameBuffer routines
117 ******************************************************************************/
118
119/* Frees array of framebuffers, depending on the I/O method the array has been
120 * initialized for.
121 * Note that this routine doesn't frees the array itself.
122 * Param:
123 * fb, num - Array data, and its size.
124 * io_type - Type of the I/O the array has been initialized for.
125 */
126static void
127_free_framebuffers(CameraFrameBuffer* fb, int num, CameraIoType io_type)
128{
129 if (fb != NULL) {
130 int n;
131
132 switch (io_type) {
133 case CAMERA_IO_MEMMAP:
134 /* Unmap framebuffers. */
135 for (n = 0; n < num; n++) {
136 if (fb[n].data != NULL) {
137 munmap(fb[n].data, fb[n].size);
138 fb[n].data = NULL;
139 fb[n].size = 0;
140 }
141 }
142 break;
143
144 case CAMERA_IO_USERPTR:
145 case CAMERA_IO_DIRECT:
146 /* Free framebuffers. */
147 for (n = 0; n < num; n++) {
148 if (fb[n].data != NULL) {
149 free(fb[n].data);
150 fb[n].data = NULL;
151 fb[n].size = 0;
152 }
153 }
154 break;
155
156 default:
157 E("Invalid I/O type %d", io_type);
158 break;
159 }
160 }
161}
162
163/*******************************************************************************
164 * CameraDevice routines
165 ******************************************************************************/
166
167/* Allocates an instance of LinuxCameraDevice structure.
168 * Return:
169 * Allocated instance of LinuxCameraDevice structure. Note that this routine
170 * also sets 'opaque' field in the 'header' structure to point back to the
171 * containing LinuxCameraDevice instance.
172 */
173static LinuxCameraDevice*
174_camera_device_alloc(void)
175{
176 LinuxCameraDevice* cd;
177
178 ANEW0(cd);
179 memset(cd, 0, sizeof(*cd));
180 cd->header.opaque = cd;
181 cd->handle = -1;
182
183 return cd;
184}
185
186/* Uninitializes and frees CameraDevice structure.
187 */
188static void
189_camera_device_free(LinuxCameraDevice* lcd)
190{
191 if (lcd != NULL) {
192 /* Closing handle will also disconnect from the driver. */
193 if (lcd->handle >= 0) {
194 close(lcd->handle);
195 }
196 if (lcd->device_name != NULL) {
197 free(lcd->device_name);
198 }
199 if (lcd->framebuffers != NULL) {
200 _free_framebuffers(lcd->framebuffers, lcd->framebuffer_num,
201 lcd->io_type);
202 free(lcd->framebuffers);
203 }
204 AFREE(lcd);
205 } else {
206 W("%s: No descriptor", __FUNCTION__);
207 }
208}
209
210/* Memory maps buffers and shares mapped memory with the device.
211 * Return:
212 * 0 Framebuffers have been mapped.
213 * -1 A critical error has ocurred.
214 * 1 Memory mapping is not available.
215 */
216static int
217_camera_device_mmap_framebuffer(LinuxCameraDevice* cd)
218{
219 struct v4l2_requestbuffers req;
220 CLEAR(req);
221 req.count = 4;
222 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
223 req.memory = V4L2_MEMORY_MMAP;
224
225 /* Request memory mapped buffers. Note that device can return less buffers
226 * than requested. */
227 if(_xioctl(cd->handle, VIDIOC_REQBUFS, &req)) {
228 if (EINVAL == errno) {
229 D("%s: %s does not support memory mapping",
230 __FUNCTION__, cd->device_name);
231 return 1;
232 } else {
233 E("%s: VIDIOC_REQBUFS has failed: %s",
234 __FUNCTION__, strerror(errno));
235 return -1;
236 }
237 }
238
239 /* Allocate framebuffer array. */
240 cd->framebuffers = calloc(req.count, sizeof(CameraFrameBuffer));
241 if (cd->framebuffers == NULL) {
242 E("%s: Not enough memory to allocate framebuffer array", __FUNCTION__);
243 return -1;
244 }
245
246 /* Map every framebuffer to the shared memory, and queue it
247 * with the device. */
248 for(cd->framebuffer_num = 0; cd->framebuffer_num < req.count;
249 cd->framebuffer_num++) {
250 /* Map framebuffer. */
251 struct v4l2_buffer buf;
252 CLEAR(buf);
253 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
254 buf.memory = V4L2_MEMORY_MMAP;
255 buf.index = cd->framebuffer_num;
256 if(_xioctl(cd->handle, VIDIOC_QUERYBUF, &buf) < 0) {
257 E("%s: VIDIOC_QUERYBUF has failed: %s",
258 __FUNCTION__, strerror(errno));
259 return -1;
260 }
261 cd->framebuffers[cd->framebuffer_num].size = buf.length;
262 cd->framebuffers[cd->framebuffer_num].data =
263 mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED,
264 cd->handle, buf.m.offset);
265 if (MAP_FAILED == cd->framebuffers[cd->framebuffer_num].data) {
266 E("%s: Memory mapping has failed: %s",
267 __FUNCTION__, strerror(errno));
268 return -1;
269 }
270
271 /* Queue the mapped buffer. */
272 CLEAR(buf);
273 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
274 buf.memory = V4L2_MEMORY_MMAP;
275 buf.index = cd->framebuffer_num;
276 if (_xioctl(cd->handle, VIDIOC_QBUF, &buf) < 0) {
277 E("%s: VIDIOC_QBUF has failed: %s", __FUNCTION__, strerror(errno));
278 return -1;
279 }
280 }
281
282 cd->io_type = CAMERA_IO_MEMMAP;
283
284 return 0;
285}
286
287/* Allocates frame buffers and registers them with the device.
288 * Return:
289 * 0 Framebuffers have been mapped.
290 * -1 A critical error has ocurred.
291 * 1 Device doesn't support user pointers.
292 */
293static int
294_camera_device_user_framebuffer(LinuxCameraDevice* cd)
295{
296 struct v4l2_requestbuffers req;
297 CLEAR (req);
298 req.count = 4;
299 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
300 req.memory = V4L2_MEMORY_USERPTR;
301
302 /* Request user buffers. Note that device can return less buffers
303 * than requested. */
304 if(_xioctl(cd->handle, VIDIOC_REQBUFS, &req)) {
305 if (EINVAL == errno) {
306 D("%s: %s does not support user pointers",
307 __FUNCTION__, cd->device_name);
308 return 1;
309 } else {
310 E("%s: VIDIOC_REQBUFS has failed: %s",
311 __FUNCTION__, strerror(errno));
312 return -1;
313 }
314 }
315
316 /* Allocate framebuffer array. */
317 cd->framebuffers = calloc(req.count, sizeof(CameraFrameBuffer));
318 if (cd->framebuffers == NULL) {
319 E("%s: Not enough memory to allocate framebuffer array", __FUNCTION__);
320 return -1;
321 }
322
323 /* Allocate buffers, queueing them wit the device at the same time */
324 for(cd->framebuffer_num = 0; cd->framebuffer_num < req.count;
325 cd->framebuffer_num++) {
326 cd->framebuffers[cd->framebuffer_num].size =
327 cd->actual_pixel_format.sizeimage;
328 cd->framebuffers[cd->framebuffer_num].data =
329 malloc(cd->framebuffers[cd->framebuffer_num].size);
330 if (cd->framebuffers[cd->framebuffer_num].data == NULL) {
331 E("%s: Not enough memory to allocate framebuffer", __FUNCTION__);
332 return -1;
333 }
334
335 /* Queue the user buffer. */
336 struct v4l2_buffer buf;
337 CLEAR(buf);
338 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
339 buf.memory = V4L2_MEMORY_USERPTR;
340 buf.m.userptr = cd->framebuffers[cd->framebuffer_num].data;
341 buf.length = cd->framebuffers[cd->framebuffer_num].size;
342 if (_xioctl(cd->handle, VIDIOC_QBUF, &buf) < 0) {
343 E("%s: VIDIOC_QBUF has failed: %s", __FUNCTION__, strerror(errno));
344 return -1;
345 }
346 }
347
348 cd->io_type = CAMERA_IO_USERPTR;
349
350 return 0;
351}
352
353/* Allocate frame buffer for direct read from the device.
354 * Return:
355 * 0 Framebuffers have been mapped.
356 * -1 A critical error has ocurred.
357 * 1 Memory mapping is not available.
358 */
359static int
360_camera_device_direct_framebuffer(LinuxCameraDevice* cd)
361{
362 /* Allocate framebuffer array. */
363 cd->framebuffer_num = 1;
364 cd->framebuffers = malloc(sizeof(CameraFrameBuffer));
365 if (cd->framebuffers == NULL) {
366 E("%s: Not enough memory to allocate framebuffer array", __FUNCTION__);
367 return -1;
368 }
369
370 cd->framebuffers[0].size = cd->actual_pixel_format.sizeimage;
371 cd->framebuffers[0].data = malloc(cd->framebuffers[0].size);
372 if (cd->framebuffers[0].data == NULL) {
373 E("%s: Not enough memory to allocate framebuffer", __FUNCTION__);
374 return -1;
375 }
376
377 cd->io_type = CAMERA_IO_DIRECT;
378
379 return 0;
380}
381
382static int
383_camera_device_open(LinuxCameraDevice* cd)
384{
385 struct stat st;
386
387 if (stat(cd->device_name, &st)) {
388 E("%s: Cannot identify camera device '%s': %s",
389 __FUNCTION__, cd->device_name, strerror(errno));
390 return -1;
391 }
392
393 if (!S_ISCHR(st.st_mode)) {
394 E("%s: %s is not a device", __FUNCTION__, cd->device_name);
395 return -1;
396 }
397
398 /* Open handle to the device, and query device capabilities. */
399 cd->handle = open(cd->device_name, O_RDWR | O_NONBLOCK, 0);
400 if (cd->handle < 0) {
401 E("%s: Cannot open camera device '%s': %s\n",
402 __FUNCTION__, cd->device_name, strerror(errno));
403 return -1;
404 }
405 if (_xioctl(cd->handle, VIDIOC_QUERYCAP, &cd->caps) < 0) {
406 if (EINVAL == errno) {
407 E("%s: Camera '%s' is not a V4L2 device",
408 __FUNCTION__, cd->device_name);
409 close(cd->handle);
410 cd->handle = -1;
411 return -1;
412 } else {
413 E("%s: Unable to query camera '%s' capabilities",
414 __FUNCTION__, cd->device_name);
415 close(cd->handle);
416 cd->handle = -1;
417 return -1;
418 }
419 }
420
421 /* Make sure that camera supports minimal requirements. */
422 if (!(cd->caps.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
423 E("%s: Camera '%s' is not a video capture device",
424 __FUNCTION__, cd->device_name);
425 close(cd->handle);
426 cd->handle = -1;
427 return -1;
428 }
429
430 return 0;
431}
432
433/*******************************************************************************
434 * CameraDevice API
435 ******************************************************************************/
436
437CameraDevice*
438camera_device_open(const char* name,
439 int inp_channel,
440 uint32_t pixel_format)
441{
442 struct v4l2_cropcap cropcap;
443 struct v4l2_crop crop;
444 struct v4l2_format fmt;
445 LinuxCameraDevice* cd;
446
447 /* Allocate and initialize the descriptor. */
448 cd = _camera_device_alloc();
449 cd->device_name = name != NULL ? ASTRDUP(name) : ASTRDUP("/dev/video0");
450 cd->input_channel = inp_channel;
451 cd->req_pixel_format = pixel_format;
452
453 /* Open the device. */
454 if (_camera_device_open(cd)) {
455 _camera_device_free(cd);
456 return NULL;
457 }
458
459 /* Select video input, video standard and tune here. */
460 cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
461 _xioctl(cd->handle, VIDIOC_CROPCAP, &cropcap);
462 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
463 crop.c = cropcap.defrect; /* reset to default */
464 _xioctl (cd->handle, VIDIOC_S_CROP, &crop);
465
466 /* Image settings. */
467 CLEAR(fmt);
468 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
469 fmt.fmt.pix.width = 0;
470 fmt.fmt.pix.height = 0;
471 fmt.fmt.pix.pixelformat = 0;
472 if (_xioctl(cd->handle, VIDIOC_G_FMT, &fmt) < 0) {
473 E("%s: Unable to obtain pixel format", __FUNCTION__);
474 _camera_device_free(cd);
475 return NULL;
476 }
477 if (_xioctl(cd->handle, VIDIOC_S_FMT, &fmt) < 0) {
478 char fmt_str[5];
479 memcpy(fmt_str, &cd->req_pixel_format, 4);
480 fmt_str[4] = '\0';
481 E("%s: Camera '%s' does not support requested pixel format '%s'",
482 __FUNCTION__, cd->device_name, fmt_str);
483 _camera_device_free(cd);
484 return NULL;
485 }
486 /* VIDIOC_S_FMT has changed some properties of the structure, adjusting them
487 * to the actual values, supported by the device. */
488 memcpy(&cd->actual_pixel_format, &fmt.fmt.pix,
489 sizeof(cd->actual_pixel_format));
490 {
491 char fmt_str[5];
492 memcpy(fmt_str, &cd->req_pixel_format, 4);
493 fmt_str[4] = '\0';
494 D("%s: Camera '%s' uses pixel format '%s'",
495 __FUNCTION__, cd->device_name, fmt_str);
496 }
497
498 return &cd->header;
499}
500
501int
502camera_device_start_capturing(CameraDevice* ccd)
503{
504 LinuxCameraDevice* cd;
505
506 /* Sanity checks. */
507 if (ccd == NULL || ccd->opaque == NULL) {
508 E("%s: Invalid camera device descriptor", __FUNCTION__);
509 return -1;
510 }
511 cd = (LinuxCameraDevice*)ccd->opaque;
512
513 /*
514 * Lets initialize frame buffers, and see what kind of I/O we're going to
515 * use to retrieve frames.
516 */
517
518 /* First, lets see if we can do mapped I/O (as most performant one). */
519 int r = _camera_device_mmap_framebuffer(cd);
520 if (r < 0) {
521 /* Some critical error has ocurred. Bail out. */
522 return -1;
523 } else if (r > 0) {
524 /* Device doesn't support memory mapping. Retrieve to the next performant
525 * one: preallocated user buffers. */
526 r = _camera_device_user_framebuffer(cd);
527 if (r < 0) {
528 /* Some critical error has ocurred. Bail out. */
529 return -1;
530 } else if (r > 0) {
531 /* The only thing left for us is direct reading from the device. */
532 if (!(cd->caps.capabilities & V4L2_CAP_READWRITE)) {
533 E("%s: Device '%s' doesn't support direct read",
534 __FUNCTION__, cd->device_name);
535 return -1;
536 }
537 r = _camera_device_direct_framebuffer(cd);
538 if (r != 0) {
539 /* Any error at this point is a critical one. */
540 return -1;
541 }
542 }
543 }
544
545 /* Start capturing from the device. */
546 if (cd->io_type != CAMERA_IO_DIRECT) {
547 enum v4l2_buf_type type;
548 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
549 if (_xioctl (cd->handle, VIDIOC_STREAMON, &type) < 0) {
550 E("%s: VIDIOC_STREAMON has failed: %s",
551 __FUNCTION__, strerror(errno));
552 return -1;
553 }
554 }
555
556 return 0;
557}
558
559int
560camera_device_stop_capturing(CameraDevice* ccd)
561{
562 enum v4l2_buf_type type;
563 LinuxCameraDevice* cd;
564
565 /* Sanity checks. */
566 if (ccd == NULL || ccd->opaque == NULL) {
567 E("%s: Invalid camera device descriptor", __FUNCTION__);
568 return -1;
569 }
570 cd = (LinuxCameraDevice*)ccd->opaque;
571
572 switch (cd->io_type) {
573 case CAMERA_IO_DIRECT:
574 /* Nothing to do. */
575 break;
576
577 case CAMERA_IO_MEMMAP:
578 case CAMERA_IO_USERPTR:
579 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
580 if (_xioctl(cd->handle, VIDIOC_STREAMOFF, &type) < 0) {
581 E("%s: VIDIOC_STREAMOFF has failed: %s",
582 __FUNCTION__, strerror(errno));
583 return -1;
584 }
585 break;
586 default:
587 E("%s: Unknown I/O method: %d", __FUNCTION__, cd->io_type);
588 return -1;
589 }
590
591 if (cd->framebuffers != NULL) {
592 _free_framebuffers(cd->framebuffers, cd->framebuffer_num, cd->io_type);
593 free(cd->framebuffers);
594 cd->framebuffers = NULL;
595 cd->framebuffer_num = 0;
596 }
597 return 0;
598}
599
600int
601camera_device_read_frame(CameraDevice* ccd, uint8_t* buff)
602{
603 LinuxCameraDevice* cd;
604
605 /* Sanity checks. */
606 if (ccd == NULL || ccd->opaque == NULL) {
607 E("%s: Invalid camera device descriptor", __FUNCTION__);
608 return -1;
609 }
610 cd = (LinuxCameraDevice*)ccd->opaque;
611
612 if (cd->io_type == CAMERA_IO_DIRECT) {
613 /* Read directly from the device. */
614 size_t total_read_bytes = 0;
615 do {
616 int read_bytes =
617 read(cd->handle, buff + total_read_bytes,
618 cd->actual_pixel_format.sizeimage - total_read_bytes);
619 if (read_bytes < 0) {
620 switch (errno) {
621 case EIO:
622 case EAGAIN:
623 continue;
624 default:
625 E("%s: Unable to read from the device: %s",
626 __FUNCTION__, strerror(errno));
627 return -1;
628 }
629 }
630 total_read_bytes += read_bytes;
631 } while (total_read_bytes < cd->actual_pixel_format.sizeimage);
632 return 0;
633 } else {
634 /* Dequeue next buffer from the device. */
635 struct v4l2_buffer buf;
636 CLEAR(buf);
637 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
638 buf.memory = cd->io_type == CAMERA_IO_MEMMAP ? V4L2_MEMORY_MMAP :
639 V4L2_MEMORY_USERPTR;
640 if (_xioctl(cd->handle, VIDIOC_DQBUF, &buf) < 0) {
641 switch (errno) {
642 case EAGAIN:
643 return 1;
644
645 case EIO:
646 /* Could ignore EIO, see spec. */
647 /* fall through */
648 default:
649 E("%s: VIDIOC_DQBUF has failed: %s",
650 __FUNCTION__, strerror(errno));
651 return 1;
652 }
653 }
654 /* Copy frame to the buffer. */
655 memcpy(buff, cd->framebuffers[buf.index].data,
656 cd->framebuffers[buf.index].size);
657 /* Requeue the buffer with the device. */
658 if (_xioctl(cd->handle, VIDIOC_QBUF, &buf) < 0) {
659 D("%s: VIDIOC_QBUF has failed: %s",
660 __FUNCTION__, strerror(errno));
661 }
662 return 0;
663 }
664}
665
666void
667camera_device_close(CameraDevice* ccd)
668{
669 LinuxCameraDevice* cd;
670
671 /* Sanity checks. */
672 if (ccd != NULL && ccd->opaque != NULL) {
673 cd = (LinuxCameraDevice*)ccd->opaque;
674 _camera_device_free(cd);
675 } else {
676 E("%s: Invalid camera device descriptor", __FUNCTION__);
677 }
678}