blob: 895690d5b6ae30007a2df3413f7d1c1446c72436 [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>
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -070026#include "android/camera/camera-capture.h"
27#include "android/camera/camera-format-converters.h"
28
29#define D(...) VERBOSE_PRINT(camera,__VA_ARGS__)
30#define W(...) VERBOSE_PRINT(camera,__VA_ARGS__)
31#define E(...) VERBOSE_PRINT(camera,__VA_ARGS__)
32#define D_ACTIVE VERBOSE_CHECK(camera)
33
34/* the T(...) macro is used to dump traffic */
35#define T_ACTIVE 0
36
37#if T_ACTIVE
38#define T(...) VERBOSE_PRINT(camera,__VA_ARGS__)
39#else
40#define T(...) ((void)0)
41#endif
42
43#define CLEAR(x) memset (&(x), 0, sizeof(x))
44
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -070045/* Pixel format descriptor.
46 * Instances of this descriptor are created during camera device enumeration, and
47 * an instance of this structure describing pixel format chosen for the camera
48 * emulation is saved by the camera factory service to represent an emulating
49 * camera properties.
50 */
51typedef struct QemuPixelFormat {
52 /* Pixel format in V4L2_PIX_FMT_XXX form. */
53 uint32_t format;
54 /* Frame dimensions supported by this format. */
55 CameraFrameDim* dims;
56 /* Number of frame dimensions supported by this format. */
57 int dim_num;
58} QemuPixelFormat;
59
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -070060/* Describes a framebuffer. */
61typedef struct CameraFrameBuffer {
62 /* Framebuffer data. */
63 uint8_t* data;
64 /* Framebuffer data size. */
65 size_t size;
66} CameraFrameBuffer;
67
68/* Defines type of the I/O used to obtain frames from the device. */
69typedef enum CameraIoType {
70 /* Framebuffers are shared via memory mapping. */
71 CAMERA_IO_MEMMAP,
72 /* Framebuffers are available via user pointers. */
73 CAMERA_IO_USERPTR,
74 /* Framebuffers are to be read from the device. */
75 CAMERA_IO_DIRECT
76} CameraIoType;
77
78typedef struct LinuxCameraDevice LinuxCameraDevice;
79/*
80 * Describes a connection to an actual camera device.
81 */
82struct LinuxCameraDevice {
83 /* Common header. */
84 CameraDevice header;
85
86 /* Camera device name. (default is /dev/video0) */
87 char* device_name;
88 /* Input channel. (default is 0) */
89 int input_channel;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -070090
91 /*
92 * Set by the framework after initializing camera connection.
93 */
94
95 /* Handle to the opened camera device. */
96 int handle;
97 /* Device capabilities. */
98 struct v4l2_capability caps;
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -070099 /* Actual pixel format reported by the device when capturing is started. */
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700100 struct v4l2_pix_format actual_pixel_format;
101 /* Defines type of the I/O to use to retrieve frames from the device. */
102 CameraIoType io_type;
103 /* Allocated framebuffers. */
104 struct CameraFrameBuffer* framebuffers;
105 /* Actual number of allocated framebuffers. */
106 int framebuffer_num;
107};
108
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700109/* Preferred pixel formats arranged from the most to the least desired.
110 *
111 * More than anything else this array is defined by an existance of format
112 * conversion between the camera supported formats, and formats that are
113 * supported by camera framework in the guest system. Currently, guest supports
114 * only YV12 pixel format for data, and RGB32 for preview. So, this array should
115 * contain only those formats, for which converters are implemented. Generally
116 * speaking, the order in which entries should be arranged in this array matters
117 * only as far as conversion speed is concerned. So, formats with the fastest
118 * converters should be put closer to the top of the array, while slower ones
119 * should be put closer to the bottom. But as far as functionality is concerned,
120 * the orser doesn't matter, and any format can be placed anywhere in this array,
121 * as long as conversion for it exists.
122 */
123static const uint32_t _preferred_formats[] =
124{
125 /* Native format for the emulated camera: no conversion at all. */
Vladimir Chtchetkineddd59b12011-09-21 14:58:10 -0700126 V4L2_PIX_FMT_YUV420,
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700127 V4L2_PIX_FMT_YVU420,
128 /* Continue with YCbCr: less math than with RGB */
129 V4L2_PIX_FMT_NV12,
130 V4L2_PIX_FMT_NV21,
131 V4L2_PIX_FMT_YUYV,
132 /* End with RGB. */
133 V4L2_PIX_FMT_RGB32,
134 V4L2_PIX_FMT_RGB24,
135 V4L2_PIX_FMT_RGB565,
136};
137/* Number of entries in _preferred_formats array. */
138static const int _preferred_format_num =
139 sizeof(_preferred_formats)/sizeof(*_preferred_formats);
140
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700141/*******************************************************************************
142 * Helper routines
143 ******************************************************************************/
144
145/* IOCTL wrapper. */
146static int
147_xioctl(int fd, int request, void *arg) {
148 int r;
149 do {
150 r = ioctl(fd, request, arg);
151 } while (-1 == r && EINTR == errno);
152 return r;
153}
154
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700155/* Frees resource allocated for QemuPixelFormat instance, excluding the instance
156 * itself.
157 */
158static void _qemu_pixel_format_free(QemuPixelFormat* fmt)
159{
160 if (fmt != NULL) {
161 if (fmt->dims != NULL)
162 free(fmt->dims);
163 }
164}
165
166/* Returns an index of the given pixel format in an array containing pixel
167 * format descriptors.
168 * This routine is used to choose a pixel format for a camera device. The idea
169 * is that when the camera service enumerates all pixel formats for all cameras
170 * connected to the host, we need to choose just one, which would be most
171 * appropriate for camera emulation. To do that, the camera service will run
172 * formats, contained in _preferred_formats array against enumerated pixel
173 * formats to pick the first format that match.
174 * Param:
175 * fmt - Pixel format, for which to obtain the index.
176 * formats - Array containing list of pixel formats, supported by the camera
177 * device.
178 * size - Number of elements in the 'formats' array.
179 * Return:
180 * Index of the matched entry in the array, or -1 if no entry has been found.
181 */
182static int
183_get_format_index(uint32_t fmt, QemuPixelFormat* formats, int size)
184{
185 int f;
186 for (f = 0; f < size && formats[f].format != fmt; f++);
187 return f < size ? f : -1;
188}
189
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700190/*******************************************************************************
191 * CameraFrameBuffer routines
192 ******************************************************************************/
193
194/* Frees array of framebuffers, depending on the I/O method the array has been
195 * initialized for.
196 * Note that this routine doesn't frees the array itself.
197 * Param:
198 * fb, num - Array data, and its size.
199 * io_type - Type of the I/O the array has been initialized for.
200 */
201static void
202_free_framebuffers(CameraFrameBuffer* fb, int num, CameraIoType io_type)
203{
204 if (fb != NULL) {
205 int n;
206
207 switch (io_type) {
208 case CAMERA_IO_MEMMAP:
209 /* Unmap framebuffers. */
210 for (n = 0; n < num; n++) {
211 if (fb[n].data != NULL) {
212 munmap(fb[n].data, fb[n].size);
213 fb[n].data = NULL;
214 fb[n].size = 0;
215 }
216 }
217 break;
218
219 case CAMERA_IO_USERPTR:
220 case CAMERA_IO_DIRECT:
221 /* Free framebuffers. */
222 for (n = 0; n < num; n++) {
223 if (fb[n].data != NULL) {
224 free(fb[n].data);
225 fb[n].data = NULL;
226 fb[n].size = 0;
227 }
228 }
229 break;
230
231 default:
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700232 E("%s: Invalid I/O type %d", __FUNCTION__, io_type);
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700233 break;
234 }
235 }
236}
237
238/*******************************************************************************
239 * CameraDevice routines
240 ******************************************************************************/
241
242/* Allocates an instance of LinuxCameraDevice structure.
243 * Return:
244 * Allocated instance of LinuxCameraDevice structure. Note that this routine
245 * also sets 'opaque' field in the 'header' structure to point back to the
246 * containing LinuxCameraDevice instance.
247 */
248static LinuxCameraDevice*
249_camera_device_alloc(void)
250{
251 LinuxCameraDevice* cd;
252
253 ANEW0(cd);
254 memset(cd, 0, sizeof(*cd));
255 cd->header.opaque = cd;
256 cd->handle = -1;
257
258 return cd;
259}
260
261/* Uninitializes and frees CameraDevice structure.
262 */
263static void
264_camera_device_free(LinuxCameraDevice* lcd)
265{
266 if (lcd != NULL) {
267 /* Closing handle will also disconnect from the driver. */
268 if (lcd->handle >= 0) {
269 close(lcd->handle);
270 }
271 if (lcd->device_name != NULL) {
272 free(lcd->device_name);
273 }
274 if (lcd->framebuffers != NULL) {
275 _free_framebuffers(lcd->framebuffers, lcd->framebuffer_num,
276 lcd->io_type);
277 free(lcd->framebuffers);
278 }
279 AFREE(lcd);
280 } else {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700281 E("%s: No descriptor", __FUNCTION__);
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700282 }
283}
284
285/* Memory maps buffers and shares mapped memory with the device.
286 * Return:
287 * 0 Framebuffers have been mapped.
288 * -1 A critical error has ocurred.
289 * 1 Memory mapping is not available.
290 */
291static int
292_camera_device_mmap_framebuffer(LinuxCameraDevice* cd)
293{
294 struct v4l2_requestbuffers req;
295 CLEAR(req);
296 req.count = 4;
297 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
298 req.memory = V4L2_MEMORY_MMAP;
299
300 /* Request memory mapped buffers. Note that device can return less buffers
301 * than requested. */
302 if(_xioctl(cd->handle, VIDIOC_REQBUFS, &req)) {
303 if (EINVAL == errno) {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700304 D("%s: Device '%s' does not support memory mapping",
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700305 __FUNCTION__, cd->device_name);
306 return 1;
307 } else {
308 E("%s: VIDIOC_REQBUFS has failed: %s",
309 __FUNCTION__, strerror(errno));
310 return -1;
311 }
312 }
313
314 /* Allocate framebuffer array. */
315 cd->framebuffers = calloc(req.count, sizeof(CameraFrameBuffer));
316 if (cd->framebuffers == NULL) {
317 E("%s: Not enough memory to allocate framebuffer array", __FUNCTION__);
318 return -1;
319 }
320
321 /* Map every framebuffer to the shared memory, and queue it
322 * with the device. */
323 for(cd->framebuffer_num = 0; cd->framebuffer_num < req.count;
324 cd->framebuffer_num++) {
325 /* Map framebuffer. */
326 struct v4l2_buffer buf;
327 CLEAR(buf);
328 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
329 buf.memory = V4L2_MEMORY_MMAP;
330 buf.index = cd->framebuffer_num;
331 if(_xioctl(cd->handle, VIDIOC_QUERYBUF, &buf) < 0) {
332 E("%s: VIDIOC_QUERYBUF has failed: %s",
333 __FUNCTION__, strerror(errno));
334 return -1;
335 }
336 cd->framebuffers[cd->framebuffer_num].size = buf.length;
337 cd->framebuffers[cd->framebuffer_num].data =
338 mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED,
339 cd->handle, buf.m.offset);
340 if (MAP_FAILED == cd->framebuffers[cd->framebuffer_num].data) {
341 E("%s: Memory mapping has failed: %s",
342 __FUNCTION__, strerror(errno));
343 return -1;
344 }
345
346 /* Queue the mapped buffer. */
347 CLEAR(buf);
348 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
349 buf.memory = V4L2_MEMORY_MMAP;
350 buf.index = cd->framebuffer_num;
351 if (_xioctl(cd->handle, VIDIOC_QBUF, &buf) < 0) {
352 E("%s: VIDIOC_QBUF has failed: %s", __FUNCTION__, strerror(errno));
353 return -1;
354 }
355 }
356
357 cd->io_type = CAMERA_IO_MEMMAP;
358
359 return 0;
360}
361
362/* Allocates frame buffers and registers them with the device.
363 * Return:
364 * 0 Framebuffers have been mapped.
365 * -1 A critical error has ocurred.
366 * 1 Device doesn't support user pointers.
367 */
368static int
369_camera_device_user_framebuffer(LinuxCameraDevice* cd)
370{
371 struct v4l2_requestbuffers req;
372 CLEAR (req);
373 req.count = 4;
374 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
375 req.memory = V4L2_MEMORY_USERPTR;
376
377 /* Request user buffers. Note that device can return less buffers
378 * than requested. */
379 if(_xioctl(cd->handle, VIDIOC_REQBUFS, &req)) {
380 if (EINVAL == errno) {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700381 D("%s: Device '%s' does not support user pointers",
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700382 __FUNCTION__, cd->device_name);
383 return 1;
384 } else {
385 E("%s: VIDIOC_REQBUFS has failed: %s",
386 __FUNCTION__, strerror(errno));
387 return -1;
388 }
389 }
390
391 /* Allocate framebuffer array. */
392 cd->framebuffers = calloc(req.count, sizeof(CameraFrameBuffer));
393 if (cd->framebuffers == NULL) {
394 E("%s: Not enough memory to allocate framebuffer array", __FUNCTION__);
395 return -1;
396 }
397
398 /* Allocate buffers, queueing them wit the device at the same time */
399 for(cd->framebuffer_num = 0; cd->framebuffer_num < req.count;
400 cd->framebuffer_num++) {
401 cd->framebuffers[cd->framebuffer_num].size =
402 cd->actual_pixel_format.sizeimage;
403 cd->framebuffers[cd->framebuffer_num].data =
404 malloc(cd->framebuffers[cd->framebuffer_num].size);
405 if (cd->framebuffers[cd->framebuffer_num].data == NULL) {
406 E("%s: Not enough memory to allocate framebuffer", __FUNCTION__);
407 return -1;
408 }
409
410 /* Queue the user buffer. */
411 struct v4l2_buffer buf;
412 CLEAR(buf);
413 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
414 buf.memory = V4L2_MEMORY_USERPTR;
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700415 buf.m.userptr = (unsigned long)cd->framebuffers[cd->framebuffer_num].data;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700416 buf.length = cd->framebuffers[cd->framebuffer_num].size;
417 if (_xioctl(cd->handle, VIDIOC_QBUF, &buf) < 0) {
418 E("%s: VIDIOC_QBUF has failed: %s", __FUNCTION__, strerror(errno));
419 return -1;
420 }
421 }
422
423 cd->io_type = CAMERA_IO_USERPTR;
424
425 return 0;
426}
427
428/* Allocate frame buffer for direct read from the device.
429 * Return:
430 * 0 Framebuffers have been mapped.
431 * -1 A critical error has ocurred.
432 * 1 Memory mapping is not available.
433 */
434static int
435_camera_device_direct_framebuffer(LinuxCameraDevice* cd)
436{
437 /* Allocate framebuffer array. */
438 cd->framebuffer_num = 1;
439 cd->framebuffers = malloc(sizeof(CameraFrameBuffer));
440 if (cd->framebuffers == NULL) {
441 E("%s: Not enough memory to allocate framebuffer array", __FUNCTION__);
442 return -1;
443 }
444
445 cd->framebuffers[0].size = cd->actual_pixel_format.sizeimage;
446 cd->framebuffers[0].data = malloc(cd->framebuffers[0].size);
447 if (cd->framebuffers[0].data == NULL) {
448 E("%s: Not enough memory to allocate framebuffer", __FUNCTION__);
449 return -1;
450 }
451
452 cd->io_type = CAMERA_IO_DIRECT;
453
454 return 0;
455}
456
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700457/* Opens camera device.
458 * Param:
459 * cd - Camera device descriptor to open the camera for.
460 * Return:
461 * 0 on success, != 0 on failure.
462 */
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700463static int
464_camera_device_open(LinuxCameraDevice* cd)
465{
466 struct stat st;
467
468 if (stat(cd->device_name, &st)) {
469 E("%s: Cannot identify camera device '%s': %s",
470 __FUNCTION__, cd->device_name, strerror(errno));
471 return -1;
472 }
473
474 if (!S_ISCHR(st.st_mode)) {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700475 E("%s: '%s' is not a device", __FUNCTION__, cd->device_name);
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700476 return -1;
477 }
478
479 /* Open handle to the device, and query device capabilities. */
480 cd->handle = open(cd->device_name, O_RDWR | O_NONBLOCK, 0);
481 if (cd->handle < 0) {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700482 E("%s: Cannot open camera device '%s': %s",
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700483 __FUNCTION__, cd->device_name, strerror(errno));
484 return -1;
485 }
486 if (_xioctl(cd->handle, VIDIOC_QUERYCAP, &cd->caps) < 0) {
487 if (EINVAL == errno) {
488 E("%s: Camera '%s' is not a V4L2 device",
489 __FUNCTION__, cd->device_name);
490 close(cd->handle);
491 cd->handle = -1;
492 return -1;
493 } else {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700494 E("%s: Unable to query capabilities for camera device '%s'",
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700495 __FUNCTION__, cd->device_name);
496 close(cd->handle);
497 cd->handle = -1;
498 return -1;
499 }
500 }
501
502 /* Make sure that camera supports minimal requirements. */
503 if (!(cd->caps.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
504 E("%s: Camera '%s' is not a video capture device",
505 __FUNCTION__, cd->device_name);
506 close(cd->handle);
507 cd->handle = -1;
508 return -1;
509 }
510
511 return 0;
512}
513
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700514/* Enumerates frame sizes for the given pixel format.
515 * Param:
516 * cd - Opened camera device descriptor.
517 * fmt - Pixel format to enum frame sizes for.
518 * sizes - Upon success contains an array of supported frame sizes. The size of
519 * the array is defined by the value, returned from this routine. The caller
520 * is responsible for freeing memory allocated for this array.
521 * Return:
522 * On success returns number of entries in the 'sizes' array. On failure returns
523 * a negative value.
524 */
525static int
526_camera_device_enum_format_sizes(LinuxCameraDevice* cd,
527 uint32_t fmt,
528 CameraFrameDim** sizes)
529{
530 int n;
531 int sizes_num = 0;
532 int out_num = 0;
533 struct v4l2_frmsizeenum size_enum;
534 CameraFrameDim* arr;
535
536 /* Calculate number of supported sizes for the given format. */
537 for (n = 0; ; n++) {
538 size_enum.index = n;
539 size_enum.pixel_format = fmt;
540 if(_xioctl(cd->handle, VIDIOC_ENUM_FRAMESIZES, &size_enum)) {
541 break;
542 }
543 if (size_enum.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
544 /* Size is in the simpe width, height form. */
545 sizes_num++;
546 } else if (size_enum.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
547 /* Sizes are represented as min/max width and height with a step for
548 * each dimension. Since at the end we want to list each supported
549 * size in the array (that's the only format supported by the guest
550 * camera framework), we need to calculate how many array entries
551 * this will generate. */
552 const uint32_t dif_widths =
553 (size_enum.stepwise.max_width - size_enum.stepwise.min_width) /
554 size_enum.stepwise.step_width + 1;
555 const uint32_t dif_heights =
556 (size_enum.stepwise.max_height - size_enum.stepwise.min_height) /
557 size_enum.stepwise.step_height + 1;
558 sizes_num += dif_widths * dif_heights;
559 } else if (size_enum.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
560 /* Special stepwise case, when steps are set to 1. We still need to
561 * flatten this for the guest, but the array may be too big.
562 * Fortunately, we don't need to be fancy, so three sizes would be
563 * sufficient here: min, max, and one in the middle. */
564 sizes_num += 3;
565 }
566
567 }
568 if (sizes_num == 0) {
569 return 0;
570 }
571
572 /* Allocate, and initialize the array of supported entries. */
573 *sizes = (CameraFrameDim*)malloc(sizes_num * sizeof(CameraFrameDim));
574 if (*sizes == NULL) {
575 E("%s: Memory allocation failure", __FUNCTION__);
576 return -1;
577 }
578 arr = *sizes;
579 for (n = 0; out_num < sizes_num; n++) {
580 size_enum.index = n;
581 size_enum.pixel_format = fmt;
582 if(_xioctl(cd->handle, VIDIOC_ENUM_FRAMESIZES, &size_enum)) {
583 /* Errors are not welcome here anymore. */
584 E("%s: Unexpected failure while getting pixel dimensions: %s",
585 strerror(errno));
586 free(arr);
587 return -1;
588 }
589
590 if (size_enum.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
591 arr[out_num].width = size_enum.discrete.width;
592 arr[out_num].height = size_enum.discrete.height;
593 out_num++;
594 } else if (size_enum.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
595 uint32_t w;
596 for (w = size_enum.stepwise.min_width;
597 w <= size_enum.stepwise.max_width;
598 w += size_enum.stepwise.step_width) {
599 uint32_t h;
600 for (h = size_enum.stepwise.min_height;
601 h <= size_enum.stepwise.max_height;
602 h += size_enum.stepwise.step_height) {
603 arr[out_num].width = w;
604 arr[out_num].height = h;
605 out_num++;
606 }
607 }
608 } else if (size_enum.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
609 /* min */
610 arr[out_num].width = size_enum.stepwise.min_width;
611 arr[out_num].height = size_enum.stepwise.min_height;
612 out_num++;
613 /* one in the middle */
614 arr[out_num].width =
615 (size_enum.stepwise.min_width + size_enum.stepwise.max_width) / 2;
616 arr[out_num].height =
617 (size_enum.stepwise.min_height + size_enum.stepwise.max_height) / 2;
618 out_num++;
619 /* max */
620 arr[out_num].width = size_enum.stepwise.max_width;
621 arr[out_num].height = size_enum.stepwise.max_height;
622 out_num++;
623 }
624 }
625
626 return out_num;
627}
628
629/* Enumerates pixel formats, supported by the device.
630 * Note that this routine will enumerate only raw (uncompressed) formats.
631 * Param:
632 * cd - Opened camera device descriptor.
633 * fmts - Upon success contains an array of supported pixel formats. The size of
634 * the array is defined by the value, returned from this routine. The caller
635 * is responsible for freeing memory allocated for this array.
636 * Return:
637 * On success returns number of entries in the 'fmts' array. On failure returns
638 * a negative value.
639 */
640static int
641_camera_device_enum_pixel_formats(LinuxCameraDevice* cd, QemuPixelFormat** fmts)
642{
643 int n;
644 int fmt_num = 0;
645 int out_num = 0;
646 struct v4l2_fmtdesc fmt_enum;
647 QemuPixelFormat* arr;
648
649 /* Calculate number of supported formats. */
650 for (n = 0; ; n++) {
651 fmt_enum.index = n;
652 fmt_enum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
653 if(_xioctl(cd->handle, VIDIOC_ENUM_FMT, &fmt_enum)) {
654 break;
655 }
656 /* Skip the compressed ones. */
657 if ((fmt_enum.flags & V4L2_FMT_FLAG_COMPRESSED) == 0) {
658 fmt_num++;
659 }
660 }
661 if (fmt_num == 0) {
662 return 0;
663 }
664
665 /* Allocate, and initialize array for enumerated formats. */
666 *fmts = (QemuPixelFormat*)malloc(fmt_num * sizeof(QemuPixelFormat));
667 if (*fmts == NULL) {
668 E("%s: Memory allocation failure", __FUNCTION__);
669 return -1;
670 }
671 arr = *fmts;
672 memset(arr, 0, fmt_num * sizeof(QemuPixelFormat));
673 for (n = 0; out_num < fmt_num; n++) {
674 fmt_enum.index = n;
675 fmt_enum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
676 if(_xioctl(cd->handle, VIDIOC_ENUM_FMT, &fmt_enum)) {
677 int nn;
678 /* Errors are not welcome here anymore. */
679 E("%s: Unexpected failure while getting pixel format: %s",
680 strerror(errno));
681 for (nn = 0; nn < out_num; nn++) {
682 _qemu_pixel_format_free(arr + nn);
683 }
684 free(arr);
685 return -1;
686 }
687 /* Skip the compressed ones. */
688 if ((fmt_enum.flags & V4L2_FMT_FLAG_COMPRESSED) == 0) {
689 arr[out_num].format = fmt_enum.pixelformat;
690 /* Enumerate frame dimensions supported for this format. */
691 arr[out_num].dim_num =
692 _camera_device_enum_format_sizes(cd, fmt_enum.pixelformat,
693 &arr[out_num].dims);
694 if (arr[out_num].dim_num > 0) {
695 out_num++;
696 } else if (arr[out_num].dim_num < 0) {
697 int nn;
698 E("Unable to enumerate supported dimensions for pixel format %d",
699 fmt_enum.pixelformat);
700 for (nn = 0; nn < out_num; nn++) {
701 _qemu_pixel_format_free(arr + nn);
702 }
703 free(arr);
704 return -1;
705 }
706 }
707 }
708
709 return out_num;
710}
711
712/* Collects information about an opened camera device.
713 * The information collected in this routine contains list of pixel formats,
714 * supported by the device, and list of frame dimensions supported by the camera
715 * for each pixel format.
716 * Param:
717 * cd - Opened camera device descriptor.
718 * cis - Upon success contains information collected from the camera device.
719 * Return:
720 * 0 on success, != 0 on failure.
721 */
722static int
723_camera_device_get_info(LinuxCameraDevice* cd, CameraInfo* cis)
724{
725 int f;
726 int chosen = -1;
727 QemuPixelFormat* formats = NULL;
728 int num_pix_fmts = _camera_device_enum_pixel_formats(cd, &formats);
729 if (num_pix_fmts <= 0) {
730 return num_pix_fmts;
731 }
732
733 /* Lets see if camera supports preferred formats */
734 for (f = 0; f < _preferred_format_num; f++) {
735 chosen = _get_format_index(_preferred_formats[f], formats, num_pix_fmts);
736 if (chosen >= 0) {
737 break;
738 }
739 }
740 if (chosen < 0) {
741 /* Camera doesn't support any of the chosen formats. Then it doesn't
742 * matter which one we choose. Lets choose the first one. */
743 chosen = 0;
744 }
745
746 cis->device_name = ASTRDUP(cd->device_name);
747 cis->inp_channel = cd->input_channel;
748 cis->pixel_format = formats[chosen].format;
749 cis->frame_sizes_num = formats[chosen].dim_num;
750 /* Swap instead of copy. */
751 cis->frame_sizes = formats[chosen].dims;
752 formats[chosen].dims = NULL;
753 cis->in_use = 0;
754
755 for (f = 0; f < num_pix_fmts; f++) {
756 _qemu_pixel_format_free(formats + f);
757 }
758 free(formats);
759
760 return 0;
761}
762
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700763/*******************************************************************************
764 * CameraDevice API
765 ******************************************************************************/
766
767CameraDevice*
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700768camera_device_open(const char* name, int inp_channel)
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700769{
770 struct v4l2_cropcap cropcap;
771 struct v4l2_crop crop;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700772 LinuxCameraDevice* cd;
773
774 /* Allocate and initialize the descriptor. */
775 cd = _camera_device_alloc();
776 cd->device_name = name != NULL ? ASTRDUP(name) : ASTRDUP("/dev/video0");
777 cd->input_channel = inp_channel;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700778
779 /* Open the device. */
780 if (_camera_device_open(cd)) {
781 _camera_device_free(cd);
782 return NULL;
783 }
784
785 /* Select video input, video standard and tune here. */
786 cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
787 _xioctl(cd->handle, VIDIOC_CROPCAP, &cropcap);
788 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
789 crop.c = cropcap.defrect; /* reset to default */
790 _xioctl (cd->handle, VIDIOC_S_CROP, &crop);
791
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700792 return &cd->header;
793}
794
795int
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700796camera_device_start_capturing(CameraDevice* ccd,
797 uint32_t pixel_format,
798 int frame_width,
799 int frame_height)
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700800{
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700801 struct v4l2_format fmt;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700802 LinuxCameraDevice* cd;
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700803 char fmt_str[5];
804 int r;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700805
806 /* Sanity checks. */
807 if (ccd == NULL || ccd->opaque == NULL) {
808 E("%s: Invalid camera device descriptor", __FUNCTION__);
809 return -1;
810 }
811 cd = (LinuxCameraDevice*)ccd->opaque;
Vladimir Chtchetkinece31fbc2011-09-14 06:55:16 -0700812 if (cd->handle < 0) {
813 E("%s: Camera device is not opened", __FUNCTION__);
814 return -1;
815 }
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700816
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700817 /* Try to set pixel format with the given dimensions. */
818 CLEAR(fmt);
819 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
820 fmt.fmt.pix.width = frame_width;
821 fmt.fmt.pix.height = frame_height;
822 fmt.fmt.pix.pixelformat = pixel_format;
823 if (_xioctl(cd->handle, VIDIOC_S_FMT, &fmt) < 0) {
824 memcpy(fmt_str, &pixel_format, 4);
825 fmt_str[4] = '\0';
826 E("%s: Camera '%s' does not support pixel format '%s' with dimensions %dx%d",
827 __FUNCTION__, cd->device_name, fmt_str, frame_width, frame_height);
828 return -1;
829 }
830 /* VIDIOC_S_FMT may has changed some properties of the structure. Make sure
831 * that dimensions didn't change. */
832 if (fmt.fmt.pix.width != frame_width || fmt.fmt.pix.height != frame_height) {
833 memcpy(fmt_str, &pixel_format, 4);
834 fmt_str[4] = '\0';
835 E("%s: Dimensions %dx%d are wrong for pixel format '%s'",
836 __FUNCTION__, frame_width, frame_height, fmt_str);
837 return -1;
838 }
839 memcpy(&cd->actual_pixel_format, &fmt.fmt.pix, sizeof(struct v4l2_pix_format));
840
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700841 /*
842 * Lets initialize frame buffers, and see what kind of I/O we're going to
843 * use to retrieve frames.
844 */
845
846 /* First, lets see if we can do mapped I/O (as most performant one). */
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700847 r = _camera_device_mmap_framebuffer(cd);
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700848 if (r < 0) {
849 /* Some critical error has ocurred. Bail out. */
850 return -1;
851 } else if (r > 0) {
852 /* Device doesn't support memory mapping. Retrieve to the next performant
853 * one: preallocated user buffers. */
854 r = _camera_device_user_framebuffer(cd);
855 if (r < 0) {
856 /* Some critical error has ocurred. Bail out. */
857 return -1;
858 } else if (r > 0) {
859 /* The only thing left for us is direct reading from the device. */
860 if (!(cd->caps.capabilities & V4L2_CAP_READWRITE)) {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700861 E("%s: Don't know how to access frames on device '%s'",
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700862 __FUNCTION__, cd->device_name);
863 return -1;
864 }
865 r = _camera_device_direct_framebuffer(cd);
866 if (r != 0) {
867 /* Any error at this point is a critical one. */
868 return -1;
869 }
870 }
871 }
872
873 /* Start capturing from the device. */
874 if (cd->io_type != CAMERA_IO_DIRECT) {
875 enum v4l2_buf_type type;
876 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
877 if (_xioctl (cd->handle, VIDIOC_STREAMON, &type) < 0) {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700878 E("%s: VIDIOC_STREAMON on camera '%s' has failed: %s",
879 __FUNCTION__, cd->device_name, strerror(errno));
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700880 return -1;
881 }
882 }
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700883 return 0;
884}
885
886int
887camera_device_stop_capturing(CameraDevice* ccd)
888{
889 enum v4l2_buf_type type;
890 LinuxCameraDevice* cd;
891
892 /* Sanity checks. */
893 if (ccd == NULL || ccd->opaque == NULL) {
894 E("%s: Invalid camera device descriptor", __FUNCTION__);
895 return -1;
896 }
897 cd = (LinuxCameraDevice*)ccd->opaque;
Vladimir Chtchetkinece31fbc2011-09-14 06:55:16 -0700898 if (cd->handle < 0) {
899 E("%s: Camera device is not opened", __FUNCTION__);
900 return -1;
901 }
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700902
903 switch (cd->io_type) {
904 case CAMERA_IO_DIRECT:
905 /* Nothing to do. */
906 break;
907
908 case CAMERA_IO_MEMMAP:
909 case CAMERA_IO_USERPTR:
910 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
911 if (_xioctl(cd->handle, VIDIOC_STREAMOFF, &type) < 0) {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700912 E("%s: VIDIOC_STREAMOFF on camera '%s' has failed: %s",
913 __FUNCTION__, cd->device_name, strerror(errno));
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700914 return -1;
915 }
916 break;
917 default:
918 E("%s: Unknown I/O method: %d", __FUNCTION__, cd->io_type);
919 return -1;
920 }
921
922 if (cd->framebuffers != NULL) {
923 _free_framebuffers(cd->framebuffers, cd->framebuffer_num, cd->io_type);
924 free(cd->framebuffers);
925 cd->framebuffers = NULL;
926 cd->framebuffer_num = 0;
927 }
Vladimir Chtchetkinece31fbc2011-09-14 06:55:16 -0700928
929 /* Reopen the device to reset its internal state. It seems that if we don't
930 * do that, an attempt to reinit the device with different frame dimensions
931 * would fail. */
932 close(cd->handle);
933 cd->handle = open(cd->device_name, O_RDWR | O_NONBLOCK, 0);
934
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700935 return 0;
936}
937
938int
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700939camera_device_read_frame(CameraDevice* ccd,
940 ClientFrameBuffer* framebuffers,
941 int fbs_num)
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700942{
943 LinuxCameraDevice* cd;
944
945 /* Sanity checks. */
946 if (ccd == NULL || ccd->opaque == NULL) {
947 E("%s: Invalid camera device descriptor", __FUNCTION__);
948 return -1;
949 }
950 cd = (LinuxCameraDevice*)ccd->opaque;
Vladimir Chtchetkinece31fbc2011-09-14 06:55:16 -0700951 if (cd->handle < 0) {
952 E("%s: Camera device is not opened", __FUNCTION__);
953 return -1;
954 }
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700955
956 if (cd->io_type == CAMERA_IO_DIRECT) {
957 /* Read directly from the device. */
958 size_t total_read_bytes = 0;
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700959 /* There is one framebuffer allocated for direct read. */
960 void* buff = cd->framebuffers[0].data;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700961 do {
962 int read_bytes =
963 read(cd->handle, buff + total_read_bytes,
964 cd->actual_pixel_format.sizeimage - total_read_bytes);
965 if (read_bytes < 0) {
966 switch (errno) {
967 case EIO:
968 case EAGAIN:
969 continue;
970 default:
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700971 E("%s: Unable to read from the camera device '%s': %s",
972 __FUNCTION__, cd->device_name, strerror(errno));
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700973 return -1;
974 }
975 }
976 total_read_bytes += read_bytes;
977 } while (total_read_bytes < cd->actual_pixel_format.sizeimage);
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700978 /* Convert the read frame into the caller's framebuffers. */
979 return convert_frame(buff, cd->actual_pixel_format.pixelformat,
980 cd->actual_pixel_format.sizeimage,
981 cd->actual_pixel_format.width,
982 cd->actual_pixel_format.height,
983 framebuffers, fbs_num);
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700984 } else {
985 /* Dequeue next buffer from the device. */
986 struct v4l2_buffer buf;
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700987 int res;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700988 CLEAR(buf);
989 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
990 buf.memory = cd->io_type == CAMERA_IO_MEMMAP ? V4L2_MEMORY_MMAP :
991 V4L2_MEMORY_USERPTR;
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700992 for (;;) {
993 const int res = _xioctl(cd->handle, VIDIOC_DQBUF, &buf);
994 if (res >= 0) {
995 break;
996 } else if (errno == EAGAIN) {
997 return 1; // Tells the caller to repeat.
998 } else if (errno != EINTR && errno != EIO) {
999 E("%s: VIDIOC_DQBUF on camera '%s' has failed: %s",
1000 __FUNCTION__, cd->device_name, strerror(errno));
1001 return -1;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -07001002 }
1003 }
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -07001004
1005 /* Convert frame to the receiving buffers. */
1006 res = convert_frame(cd->framebuffers[buf.index].data,
1007 cd->actual_pixel_format.pixelformat,
1008 cd->actual_pixel_format.sizeimage,
1009 cd->actual_pixel_format.width,
1010 cd->actual_pixel_format.height,
1011 framebuffers, fbs_num);
1012
1013 /* Requeue the buffer back to the device. */
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -07001014 if (_xioctl(cd->handle, VIDIOC_QBUF, &buf) < 0) {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -07001015 W("%s: VIDIOC_QBUF on camera '%s' has failed: %s",
1016 __FUNCTION__, cd->device_name, strerror(errno));
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -07001017 }
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -07001018
1019 return res;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -07001020 }
1021}
1022
1023void
1024camera_device_close(CameraDevice* ccd)
1025{
1026 LinuxCameraDevice* cd;
1027
1028 /* Sanity checks. */
1029 if (ccd != NULL && ccd->opaque != NULL) {
1030 cd = (LinuxCameraDevice*)ccd->opaque;
1031 _camera_device_free(cd);
1032 } else {
1033 E("%s: Invalid camera device descriptor", __FUNCTION__);
1034 }
1035}
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -07001036
1037int
1038enumerate_camera_devices(CameraInfo* cis, int max)
1039{
1040 char dev_name[24];
1041 int found = 0;
1042 int n;
1043
1044 for (n = 0; n < max; n++) {
1045 CameraDevice* cd;
1046
1047 sprintf(dev_name, "/dev/video%d", n);
1048 cd = camera_device_open(dev_name, 0);
1049 if (cd != NULL) {
1050 LinuxCameraDevice* lcd = (LinuxCameraDevice*)cd->opaque;
1051 if (!_camera_device_get_info(lcd, cis + found)) {
Vladimir Chtchetkineb8dcaff2011-09-17 11:15:47 -07001052 char user_name[24];
1053 sprintf(user_name, "webcam%d", found);
1054 cis[found].display_name = ASTRDUP(user_name);
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -07001055 cis[found].in_use = 0;
1056 found++;
1057 }
1058 camera_device_close(cd);
1059 } else {
1060 break;
1061 }
1062 }
1063
1064 return found;
1065}