blob: 50324f003eed0a6961d793290ef094dad40c4acf [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. */
126 V4L2_PIX_FMT_YVU420,
127 /* Continue with YCbCr: less math than with RGB */
128 V4L2_PIX_FMT_NV12,
129 V4L2_PIX_FMT_NV21,
130 V4L2_PIX_FMT_YUYV,
131 /* End with RGB. */
132 V4L2_PIX_FMT_RGB32,
133 V4L2_PIX_FMT_RGB24,
134 V4L2_PIX_FMT_RGB565,
135};
136/* Number of entries in _preferred_formats array. */
137static const int _preferred_format_num =
138 sizeof(_preferred_formats)/sizeof(*_preferred_formats);
139
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700140/*******************************************************************************
141 * Helper routines
142 ******************************************************************************/
143
144/* IOCTL wrapper. */
145static int
146_xioctl(int fd, int request, void *arg) {
147 int r;
148 do {
149 r = ioctl(fd, request, arg);
150 } while (-1 == r && EINTR == errno);
151 return r;
152}
153
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700154/* Frees resource allocated for QemuPixelFormat instance, excluding the instance
155 * itself.
156 */
157static void _qemu_pixel_format_free(QemuPixelFormat* fmt)
158{
159 if (fmt != NULL) {
160 if (fmt->dims != NULL)
161 free(fmt->dims);
162 }
163}
164
165/* Returns an index of the given pixel format in an array containing pixel
166 * format descriptors.
167 * This routine is used to choose a pixel format for a camera device. The idea
168 * is that when the camera service enumerates all pixel formats for all cameras
169 * connected to the host, we need to choose just one, which would be most
170 * appropriate for camera emulation. To do that, the camera service will run
171 * formats, contained in _preferred_formats array against enumerated pixel
172 * formats to pick the first format that match.
173 * Param:
174 * fmt - Pixel format, for which to obtain the index.
175 * formats - Array containing list of pixel formats, supported by the camera
176 * device.
177 * size - Number of elements in the 'formats' array.
178 * Return:
179 * Index of the matched entry in the array, or -1 if no entry has been found.
180 */
181static int
182_get_format_index(uint32_t fmt, QemuPixelFormat* formats, int size)
183{
184 int f;
185 for (f = 0; f < size && formats[f].format != fmt; f++);
186 return f < size ? f : -1;
187}
188
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700189/*******************************************************************************
190 * CameraFrameBuffer routines
191 ******************************************************************************/
192
193/* Frees array of framebuffers, depending on the I/O method the array has been
194 * initialized for.
195 * Note that this routine doesn't frees the array itself.
196 * Param:
197 * fb, num - Array data, and its size.
198 * io_type - Type of the I/O the array has been initialized for.
199 */
200static void
201_free_framebuffers(CameraFrameBuffer* fb, int num, CameraIoType io_type)
202{
203 if (fb != NULL) {
204 int n;
205
206 switch (io_type) {
207 case CAMERA_IO_MEMMAP:
208 /* Unmap framebuffers. */
209 for (n = 0; n < num; n++) {
210 if (fb[n].data != NULL) {
211 munmap(fb[n].data, fb[n].size);
212 fb[n].data = NULL;
213 fb[n].size = 0;
214 }
215 }
216 break;
217
218 case CAMERA_IO_USERPTR:
219 case CAMERA_IO_DIRECT:
220 /* Free framebuffers. */
221 for (n = 0; n < num; n++) {
222 if (fb[n].data != NULL) {
223 free(fb[n].data);
224 fb[n].data = NULL;
225 fb[n].size = 0;
226 }
227 }
228 break;
229
230 default:
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700231 E("%s: Invalid I/O type %d", __FUNCTION__, io_type);
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700232 break;
233 }
234 }
235}
236
237/*******************************************************************************
238 * CameraDevice routines
239 ******************************************************************************/
240
241/* Allocates an instance of LinuxCameraDevice structure.
242 * Return:
243 * Allocated instance of LinuxCameraDevice structure. Note that this routine
244 * also sets 'opaque' field in the 'header' structure to point back to the
245 * containing LinuxCameraDevice instance.
246 */
247static LinuxCameraDevice*
248_camera_device_alloc(void)
249{
250 LinuxCameraDevice* cd;
251
252 ANEW0(cd);
253 memset(cd, 0, sizeof(*cd));
254 cd->header.opaque = cd;
255 cd->handle = -1;
256
257 return cd;
258}
259
260/* Uninitializes and frees CameraDevice structure.
261 */
262static void
263_camera_device_free(LinuxCameraDevice* lcd)
264{
265 if (lcd != NULL) {
266 /* Closing handle will also disconnect from the driver. */
267 if (lcd->handle >= 0) {
268 close(lcd->handle);
269 }
270 if (lcd->device_name != NULL) {
271 free(lcd->device_name);
272 }
273 if (lcd->framebuffers != NULL) {
274 _free_framebuffers(lcd->framebuffers, lcd->framebuffer_num,
275 lcd->io_type);
276 free(lcd->framebuffers);
277 }
278 AFREE(lcd);
279 } else {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700280 E("%s: No descriptor", __FUNCTION__);
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700281 }
282}
283
284/* Memory maps buffers and shares mapped memory with the device.
285 * Return:
286 * 0 Framebuffers have been mapped.
287 * -1 A critical error has ocurred.
288 * 1 Memory mapping is not available.
289 */
290static int
291_camera_device_mmap_framebuffer(LinuxCameraDevice* cd)
292{
293 struct v4l2_requestbuffers req;
294 CLEAR(req);
295 req.count = 4;
296 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
297 req.memory = V4L2_MEMORY_MMAP;
298
299 /* Request memory mapped buffers. Note that device can return less buffers
300 * than requested. */
301 if(_xioctl(cd->handle, VIDIOC_REQBUFS, &req)) {
302 if (EINVAL == errno) {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700303 D("%s: Device '%s' does not support memory mapping",
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700304 __FUNCTION__, cd->device_name);
305 return 1;
306 } else {
307 E("%s: VIDIOC_REQBUFS has failed: %s",
308 __FUNCTION__, strerror(errno));
309 return -1;
310 }
311 }
312
313 /* Allocate framebuffer array. */
314 cd->framebuffers = calloc(req.count, sizeof(CameraFrameBuffer));
315 if (cd->framebuffers == NULL) {
316 E("%s: Not enough memory to allocate framebuffer array", __FUNCTION__);
317 return -1;
318 }
319
320 /* Map every framebuffer to the shared memory, and queue it
321 * with the device. */
322 for(cd->framebuffer_num = 0; cd->framebuffer_num < req.count;
323 cd->framebuffer_num++) {
324 /* Map framebuffer. */
325 struct v4l2_buffer buf;
326 CLEAR(buf);
327 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
328 buf.memory = V4L2_MEMORY_MMAP;
329 buf.index = cd->framebuffer_num;
330 if(_xioctl(cd->handle, VIDIOC_QUERYBUF, &buf) < 0) {
331 E("%s: VIDIOC_QUERYBUF has failed: %s",
332 __FUNCTION__, strerror(errno));
333 return -1;
334 }
335 cd->framebuffers[cd->framebuffer_num].size = buf.length;
336 cd->framebuffers[cd->framebuffer_num].data =
337 mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED,
338 cd->handle, buf.m.offset);
339 if (MAP_FAILED == cd->framebuffers[cd->framebuffer_num].data) {
340 E("%s: Memory mapping has failed: %s",
341 __FUNCTION__, strerror(errno));
342 return -1;
343 }
344
345 /* Queue the mapped buffer. */
346 CLEAR(buf);
347 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
348 buf.memory = V4L2_MEMORY_MMAP;
349 buf.index = cd->framebuffer_num;
350 if (_xioctl(cd->handle, VIDIOC_QBUF, &buf) < 0) {
351 E("%s: VIDIOC_QBUF has failed: %s", __FUNCTION__, strerror(errno));
352 return -1;
353 }
354 }
355
356 cd->io_type = CAMERA_IO_MEMMAP;
357
358 return 0;
359}
360
361/* Allocates frame buffers and registers them with the device.
362 * Return:
363 * 0 Framebuffers have been mapped.
364 * -1 A critical error has ocurred.
365 * 1 Device doesn't support user pointers.
366 */
367static int
368_camera_device_user_framebuffer(LinuxCameraDevice* cd)
369{
370 struct v4l2_requestbuffers req;
371 CLEAR (req);
372 req.count = 4;
373 req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
374 req.memory = V4L2_MEMORY_USERPTR;
375
376 /* Request user buffers. Note that device can return less buffers
377 * than requested. */
378 if(_xioctl(cd->handle, VIDIOC_REQBUFS, &req)) {
379 if (EINVAL == errno) {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700380 D("%s: Device '%s' does not support user pointers",
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700381 __FUNCTION__, cd->device_name);
382 return 1;
383 } else {
384 E("%s: VIDIOC_REQBUFS has failed: %s",
385 __FUNCTION__, strerror(errno));
386 return -1;
387 }
388 }
389
390 /* Allocate framebuffer array. */
391 cd->framebuffers = calloc(req.count, sizeof(CameraFrameBuffer));
392 if (cd->framebuffers == NULL) {
393 E("%s: Not enough memory to allocate framebuffer array", __FUNCTION__);
394 return -1;
395 }
396
397 /* Allocate buffers, queueing them wit the device at the same time */
398 for(cd->framebuffer_num = 0; cd->framebuffer_num < req.count;
399 cd->framebuffer_num++) {
400 cd->framebuffers[cd->framebuffer_num].size =
401 cd->actual_pixel_format.sizeimage;
402 cd->framebuffers[cd->framebuffer_num].data =
403 malloc(cd->framebuffers[cd->framebuffer_num].size);
404 if (cd->framebuffers[cd->framebuffer_num].data == NULL) {
405 E("%s: Not enough memory to allocate framebuffer", __FUNCTION__);
406 return -1;
407 }
408
409 /* Queue the user buffer. */
410 struct v4l2_buffer buf;
411 CLEAR(buf);
412 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
413 buf.memory = V4L2_MEMORY_USERPTR;
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700414 buf.m.userptr = (unsigned long)cd->framebuffers[cd->framebuffer_num].data;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700415 buf.length = cd->framebuffers[cd->framebuffer_num].size;
416 if (_xioctl(cd->handle, VIDIOC_QBUF, &buf) < 0) {
417 E("%s: VIDIOC_QBUF has failed: %s", __FUNCTION__, strerror(errno));
418 return -1;
419 }
420 }
421
422 cd->io_type = CAMERA_IO_USERPTR;
423
424 return 0;
425}
426
427/* Allocate frame buffer for direct read from the device.
428 * Return:
429 * 0 Framebuffers have been mapped.
430 * -1 A critical error has ocurred.
431 * 1 Memory mapping is not available.
432 */
433static int
434_camera_device_direct_framebuffer(LinuxCameraDevice* cd)
435{
436 /* Allocate framebuffer array. */
437 cd->framebuffer_num = 1;
438 cd->framebuffers = malloc(sizeof(CameraFrameBuffer));
439 if (cd->framebuffers == NULL) {
440 E("%s: Not enough memory to allocate framebuffer array", __FUNCTION__);
441 return -1;
442 }
443
444 cd->framebuffers[0].size = cd->actual_pixel_format.sizeimage;
445 cd->framebuffers[0].data = malloc(cd->framebuffers[0].size);
446 if (cd->framebuffers[0].data == NULL) {
447 E("%s: Not enough memory to allocate framebuffer", __FUNCTION__);
448 return -1;
449 }
450
451 cd->io_type = CAMERA_IO_DIRECT;
452
453 return 0;
454}
455
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700456/* Opens camera device.
457 * Param:
458 * cd - Camera device descriptor to open the camera for.
459 * Return:
460 * 0 on success, != 0 on failure.
461 */
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700462static int
463_camera_device_open(LinuxCameraDevice* cd)
464{
465 struct stat st;
466
467 if (stat(cd->device_name, &st)) {
468 E("%s: Cannot identify camera device '%s': %s",
469 __FUNCTION__, cd->device_name, strerror(errno));
470 return -1;
471 }
472
473 if (!S_ISCHR(st.st_mode)) {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700474 E("%s: '%s' is not a device", __FUNCTION__, cd->device_name);
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700475 return -1;
476 }
477
478 /* Open handle to the device, and query device capabilities. */
479 cd->handle = open(cd->device_name, O_RDWR | O_NONBLOCK, 0);
480 if (cd->handle < 0) {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700481 E("%s: Cannot open camera device '%s': %s",
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700482 __FUNCTION__, cd->device_name, strerror(errno));
483 return -1;
484 }
485 if (_xioctl(cd->handle, VIDIOC_QUERYCAP, &cd->caps) < 0) {
486 if (EINVAL == errno) {
487 E("%s: Camera '%s' is not a V4L2 device",
488 __FUNCTION__, cd->device_name);
489 close(cd->handle);
490 cd->handle = -1;
491 return -1;
492 } else {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700493 E("%s: Unable to query capabilities for camera device '%s'",
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700494 __FUNCTION__, cd->device_name);
495 close(cd->handle);
496 cd->handle = -1;
497 return -1;
498 }
499 }
500
501 /* Make sure that camera supports minimal requirements. */
502 if (!(cd->caps.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
503 E("%s: Camera '%s' is not a video capture device",
504 __FUNCTION__, cd->device_name);
505 close(cd->handle);
506 cd->handle = -1;
507 return -1;
508 }
509
510 return 0;
511}
512
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700513/* Enumerates frame sizes for the given pixel format.
514 * Param:
515 * cd - Opened camera device descriptor.
516 * fmt - Pixel format to enum frame sizes for.
517 * sizes - Upon success contains an array of supported frame sizes. The size of
518 * the array is defined by the value, returned from this routine. The caller
519 * is responsible for freeing memory allocated for this array.
520 * Return:
521 * On success returns number of entries in the 'sizes' array. On failure returns
522 * a negative value.
523 */
524static int
525_camera_device_enum_format_sizes(LinuxCameraDevice* cd,
526 uint32_t fmt,
527 CameraFrameDim** sizes)
528{
529 int n;
530 int sizes_num = 0;
531 int out_num = 0;
532 struct v4l2_frmsizeenum size_enum;
533 CameraFrameDim* arr;
534
535 /* Calculate number of supported sizes for the given format. */
536 for (n = 0; ; n++) {
537 size_enum.index = n;
538 size_enum.pixel_format = fmt;
539 if(_xioctl(cd->handle, VIDIOC_ENUM_FRAMESIZES, &size_enum)) {
540 break;
541 }
542 if (size_enum.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
543 /* Size is in the simpe width, height form. */
544 sizes_num++;
545 } else if (size_enum.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
546 /* Sizes are represented as min/max width and height with a step for
547 * each dimension. Since at the end we want to list each supported
548 * size in the array (that's the only format supported by the guest
549 * camera framework), we need to calculate how many array entries
550 * this will generate. */
551 const uint32_t dif_widths =
552 (size_enum.stepwise.max_width - size_enum.stepwise.min_width) /
553 size_enum.stepwise.step_width + 1;
554 const uint32_t dif_heights =
555 (size_enum.stepwise.max_height - size_enum.stepwise.min_height) /
556 size_enum.stepwise.step_height + 1;
557 sizes_num += dif_widths * dif_heights;
558 } else if (size_enum.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
559 /* Special stepwise case, when steps are set to 1. We still need to
560 * flatten this for the guest, but the array may be too big.
561 * Fortunately, we don't need to be fancy, so three sizes would be
562 * sufficient here: min, max, and one in the middle. */
563 sizes_num += 3;
564 }
565
566 }
567 if (sizes_num == 0) {
568 return 0;
569 }
570
571 /* Allocate, and initialize the array of supported entries. */
572 *sizes = (CameraFrameDim*)malloc(sizes_num * sizeof(CameraFrameDim));
573 if (*sizes == NULL) {
574 E("%s: Memory allocation failure", __FUNCTION__);
575 return -1;
576 }
577 arr = *sizes;
578 for (n = 0; out_num < sizes_num; n++) {
579 size_enum.index = n;
580 size_enum.pixel_format = fmt;
581 if(_xioctl(cd->handle, VIDIOC_ENUM_FRAMESIZES, &size_enum)) {
582 /* Errors are not welcome here anymore. */
583 E("%s: Unexpected failure while getting pixel dimensions: %s",
584 strerror(errno));
585 free(arr);
586 return -1;
587 }
588
589 if (size_enum.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
590 arr[out_num].width = size_enum.discrete.width;
591 arr[out_num].height = size_enum.discrete.height;
592 out_num++;
593 } else if (size_enum.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
594 uint32_t w;
595 for (w = size_enum.stepwise.min_width;
596 w <= size_enum.stepwise.max_width;
597 w += size_enum.stepwise.step_width) {
598 uint32_t h;
599 for (h = size_enum.stepwise.min_height;
600 h <= size_enum.stepwise.max_height;
601 h += size_enum.stepwise.step_height) {
602 arr[out_num].width = w;
603 arr[out_num].height = h;
604 out_num++;
605 }
606 }
607 } else if (size_enum.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
608 /* min */
609 arr[out_num].width = size_enum.stepwise.min_width;
610 arr[out_num].height = size_enum.stepwise.min_height;
611 out_num++;
612 /* one in the middle */
613 arr[out_num].width =
614 (size_enum.stepwise.min_width + size_enum.stepwise.max_width) / 2;
615 arr[out_num].height =
616 (size_enum.stepwise.min_height + size_enum.stepwise.max_height) / 2;
617 out_num++;
618 /* max */
619 arr[out_num].width = size_enum.stepwise.max_width;
620 arr[out_num].height = size_enum.stepwise.max_height;
621 out_num++;
622 }
623 }
624
625 return out_num;
626}
627
628/* Enumerates pixel formats, supported by the device.
629 * Note that this routine will enumerate only raw (uncompressed) formats.
630 * Param:
631 * cd - Opened camera device descriptor.
632 * fmts - Upon success contains an array of supported pixel formats. The size of
633 * the array is defined by the value, returned from this routine. The caller
634 * is responsible for freeing memory allocated for this array.
635 * Return:
636 * On success returns number of entries in the 'fmts' array. On failure returns
637 * a negative value.
638 */
639static int
640_camera_device_enum_pixel_formats(LinuxCameraDevice* cd, QemuPixelFormat** fmts)
641{
642 int n;
643 int fmt_num = 0;
644 int out_num = 0;
645 struct v4l2_fmtdesc fmt_enum;
646 QemuPixelFormat* arr;
647
648 /* Calculate number of supported formats. */
649 for (n = 0; ; n++) {
650 fmt_enum.index = n;
651 fmt_enum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
652 if(_xioctl(cd->handle, VIDIOC_ENUM_FMT, &fmt_enum)) {
653 break;
654 }
655 /* Skip the compressed ones. */
656 if ((fmt_enum.flags & V4L2_FMT_FLAG_COMPRESSED) == 0) {
657 fmt_num++;
658 }
659 }
660 if (fmt_num == 0) {
661 return 0;
662 }
663
664 /* Allocate, and initialize array for enumerated formats. */
665 *fmts = (QemuPixelFormat*)malloc(fmt_num * sizeof(QemuPixelFormat));
666 if (*fmts == NULL) {
667 E("%s: Memory allocation failure", __FUNCTION__);
668 return -1;
669 }
670 arr = *fmts;
671 memset(arr, 0, fmt_num * sizeof(QemuPixelFormat));
672 for (n = 0; out_num < fmt_num; n++) {
673 fmt_enum.index = n;
674 fmt_enum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
675 if(_xioctl(cd->handle, VIDIOC_ENUM_FMT, &fmt_enum)) {
676 int nn;
677 /* Errors are not welcome here anymore. */
678 E("%s: Unexpected failure while getting pixel format: %s",
679 strerror(errno));
680 for (nn = 0; nn < out_num; nn++) {
681 _qemu_pixel_format_free(arr + nn);
682 }
683 free(arr);
684 return -1;
685 }
686 /* Skip the compressed ones. */
687 if ((fmt_enum.flags & V4L2_FMT_FLAG_COMPRESSED) == 0) {
688 arr[out_num].format = fmt_enum.pixelformat;
689 /* Enumerate frame dimensions supported for this format. */
690 arr[out_num].dim_num =
691 _camera_device_enum_format_sizes(cd, fmt_enum.pixelformat,
692 &arr[out_num].dims);
693 if (arr[out_num].dim_num > 0) {
694 out_num++;
695 } else if (arr[out_num].dim_num < 0) {
696 int nn;
697 E("Unable to enumerate supported dimensions for pixel format %d",
698 fmt_enum.pixelformat);
699 for (nn = 0; nn < out_num; nn++) {
700 _qemu_pixel_format_free(arr + nn);
701 }
702 free(arr);
703 return -1;
704 }
705 }
706 }
707
708 return out_num;
709}
710
711/* Collects information about an opened camera device.
712 * The information collected in this routine contains list of pixel formats,
713 * supported by the device, and list of frame dimensions supported by the camera
714 * for each pixel format.
715 * Param:
716 * cd - Opened camera device descriptor.
717 * cis - Upon success contains information collected from the camera device.
718 * Return:
719 * 0 on success, != 0 on failure.
720 */
721static int
722_camera_device_get_info(LinuxCameraDevice* cd, CameraInfo* cis)
723{
724 int f;
725 int chosen = -1;
726 QemuPixelFormat* formats = NULL;
727 int num_pix_fmts = _camera_device_enum_pixel_formats(cd, &formats);
728 if (num_pix_fmts <= 0) {
729 return num_pix_fmts;
730 }
731
732 /* Lets see if camera supports preferred formats */
733 for (f = 0; f < _preferred_format_num; f++) {
734 chosen = _get_format_index(_preferred_formats[f], formats, num_pix_fmts);
735 if (chosen >= 0) {
736 break;
737 }
738 }
739 if (chosen < 0) {
740 /* Camera doesn't support any of the chosen formats. Then it doesn't
741 * matter which one we choose. Lets choose the first one. */
742 chosen = 0;
743 }
744
745 cis->device_name = ASTRDUP(cd->device_name);
746 cis->inp_channel = cd->input_channel;
747 cis->pixel_format = formats[chosen].format;
748 cis->frame_sizes_num = formats[chosen].dim_num;
749 /* Swap instead of copy. */
750 cis->frame_sizes = formats[chosen].dims;
751 formats[chosen].dims = NULL;
752 cis->in_use = 0;
753
754 for (f = 0; f < num_pix_fmts; f++) {
755 _qemu_pixel_format_free(formats + f);
756 }
757 free(formats);
758
759 return 0;
760}
761
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700762/*******************************************************************************
763 * CameraDevice API
764 ******************************************************************************/
765
766CameraDevice*
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700767camera_device_open(const char* name, int inp_channel)
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700768{
769 struct v4l2_cropcap cropcap;
770 struct v4l2_crop crop;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700771 LinuxCameraDevice* cd;
772
773 /* Allocate and initialize the descriptor. */
774 cd = _camera_device_alloc();
775 cd->device_name = name != NULL ? ASTRDUP(name) : ASTRDUP("/dev/video0");
776 cd->input_channel = inp_channel;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700777
778 /* Open the device. */
779 if (_camera_device_open(cd)) {
780 _camera_device_free(cd);
781 return NULL;
782 }
783
784 /* Select video input, video standard and tune here. */
785 cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
786 _xioctl(cd->handle, VIDIOC_CROPCAP, &cropcap);
787 crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
788 crop.c = cropcap.defrect; /* reset to default */
789 _xioctl (cd->handle, VIDIOC_S_CROP, &crop);
790
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700791 return &cd->header;
792}
793
794int
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700795camera_device_start_capturing(CameraDevice* ccd,
796 uint32_t pixel_format,
797 int frame_width,
798 int frame_height)
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700799{
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700800 struct v4l2_format fmt;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700801 LinuxCameraDevice* cd;
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700802 char fmt_str[5];
803 int r;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700804
805 /* Sanity checks. */
806 if (ccd == NULL || ccd->opaque == NULL) {
807 E("%s: Invalid camera device descriptor", __FUNCTION__);
808 return -1;
809 }
810 cd = (LinuxCameraDevice*)ccd->opaque;
Vladimir Chtchetkinece31fbc2011-09-14 06:55:16 -0700811 if (cd->handle < 0) {
812 E("%s: Camera device is not opened", __FUNCTION__);
813 return -1;
814 }
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700815
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700816 /* Try to set pixel format with the given dimensions. */
817 CLEAR(fmt);
818 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
819 fmt.fmt.pix.width = frame_width;
820 fmt.fmt.pix.height = frame_height;
821 fmt.fmt.pix.pixelformat = pixel_format;
822 if (_xioctl(cd->handle, VIDIOC_S_FMT, &fmt) < 0) {
823 memcpy(fmt_str, &pixel_format, 4);
824 fmt_str[4] = '\0';
825 E("%s: Camera '%s' does not support pixel format '%s' with dimensions %dx%d",
826 __FUNCTION__, cd->device_name, fmt_str, frame_width, frame_height);
827 return -1;
828 }
829 /* VIDIOC_S_FMT may has changed some properties of the structure. Make sure
830 * that dimensions didn't change. */
831 if (fmt.fmt.pix.width != frame_width || fmt.fmt.pix.height != frame_height) {
832 memcpy(fmt_str, &pixel_format, 4);
833 fmt_str[4] = '\0';
834 E("%s: Dimensions %dx%d are wrong for pixel format '%s'",
835 __FUNCTION__, frame_width, frame_height, fmt_str);
836 return -1;
837 }
838 memcpy(&cd->actual_pixel_format, &fmt.fmt.pix, sizeof(struct v4l2_pix_format));
839
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700840 /*
841 * Lets initialize frame buffers, and see what kind of I/O we're going to
842 * use to retrieve frames.
843 */
844
845 /* First, lets see if we can do mapped I/O (as most performant one). */
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700846 r = _camera_device_mmap_framebuffer(cd);
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700847 if (r < 0) {
848 /* Some critical error has ocurred. Bail out. */
849 return -1;
850 } else if (r > 0) {
851 /* Device doesn't support memory mapping. Retrieve to the next performant
852 * one: preallocated user buffers. */
853 r = _camera_device_user_framebuffer(cd);
854 if (r < 0) {
855 /* Some critical error has ocurred. Bail out. */
856 return -1;
857 } else if (r > 0) {
858 /* The only thing left for us is direct reading from the device. */
859 if (!(cd->caps.capabilities & V4L2_CAP_READWRITE)) {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700860 E("%s: Don't know how to access frames on device '%s'",
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700861 __FUNCTION__, cd->device_name);
862 return -1;
863 }
864 r = _camera_device_direct_framebuffer(cd);
865 if (r != 0) {
866 /* Any error at this point is a critical one. */
867 return -1;
868 }
869 }
870 }
871
872 /* Start capturing from the device. */
873 if (cd->io_type != CAMERA_IO_DIRECT) {
874 enum v4l2_buf_type type;
875 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
876 if (_xioctl (cd->handle, VIDIOC_STREAMON, &type) < 0) {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700877 E("%s: VIDIOC_STREAMON on camera '%s' has failed: %s",
878 __FUNCTION__, cd->device_name, strerror(errno));
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700879 return -1;
880 }
881 }
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700882 return 0;
883}
884
885int
886camera_device_stop_capturing(CameraDevice* ccd)
887{
888 enum v4l2_buf_type type;
889 LinuxCameraDevice* cd;
890
891 /* Sanity checks. */
892 if (ccd == NULL || ccd->opaque == NULL) {
893 E("%s: Invalid camera device descriptor", __FUNCTION__);
894 return -1;
895 }
896 cd = (LinuxCameraDevice*)ccd->opaque;
Vladimir Chtchetkinece31fbc2011-09-14 06:55:16 -0700897 if (cd->handle < 0) {
898 E("%s: Camera device is not opened", __FUNCTION__);
899 return -1;
900 }
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700901
902 switch (cd->io_type) {
903 case CAMERA_IO_DIRECT:
904 /* Nothing to do. */
905 break;
906
907 case CAMERA_IO_MEMMAP:
908 case CAMERA_IO_USERPTR:
909 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
910 if (_xioctl(cd->handle, VIDIOC_STREAMOFF, &type) < 0) {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700911 E("%s: VIDIOC_STREAMOFF on camera '%s' has failed: %s",
912 __FUNCTION__, cd->device_name, strerror(errno));
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700913 return -1;
914 }
915 break;
916 default:
917 E("%s: Unknown I/O method: %d", __FUNCTION__, cd->io_type);
918 return -1;
919 }
920
921 if (cd->framebuffers != NULL) {
922 _free_framebuffers(cd->framebuffers, cd->framebuffer_num, cd->io_type);
923 free(cd->framebuffers);
924 cd->framebuffers = NULL;
925 cd->framebuffer_num = 0;
926 }
Vladimir Chtchetkinece31fbc2011-09-14 06:55:16 -0700927
928 /* Reopen the device to reset its internal state. It seems that if we don't
929 * do that, an attempt to reinit the device with different frame dimensions
930 * would fail. */
931 close(cd->handle);
932 cd->handle = open(cd->device_name, O_RDWR | O_NONBLOCK, 0);
933
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700934 return 0;
935}
936
937int
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700938camera_device_read_frame(CameraDevice* ccd,
939 ClientFrameBuffer* framebuffers,
940 int fbs_num)
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700941{
942 LinuxCameraDevice* cd;
943
944 /* Sanity checks. */
945 if (ccd == NULL || ccd->opaque == NULL) {
946 E("%s: Invalid camera device descriptor", __FUNCTION__);
947 return -1;
948 }
949 cd = (LinuxCameraDevice*)ccd->opaque;
Vladimir Chtchetkinece31fbc2011-09-14 06:55:16 -0700950 if (cd->handle < 0) {
951 E("%s: Camera device is not opened", __FUNCTION__);
952 return -1;
953 }
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700954
955 if (cd->io_type == CAMERA_IO_DIRECT) {
956 /* Read directly from the device. */
957 size_t total_read_bytes = 0;
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700958 /* There is one framebuffer allocated for direct read. */
959 void* buff = cd->framebuffers[0].data;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700960 do {
961 int read_bytes =
962 read(cd->handle, buff + total_read_bytes,
963 cd->actual_pixel_format.sizeimage - total_read_bytes);
964 if (read_bytes < 0) {
965 switch (errno) {
966 case EIO:
967 case EAGAIN:
968 continue;
969 default:
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700970 E("%s: Unable to read from the camera device '%s': %s",
971 __FUNCTION__, cd->device_name, strerror(errno));
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700972 return -1;
973 }
974 }
975 total_read_bytes += read_bytes;
976 } while (total_read_bytes < cd->actual_pixel_format.sizeimage);
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700977 /* Convert the read frame into the caller's framebuffers. */
978 return convert_frame(buff, cd->actual_pixel_format.pixelformat,
979 cd->actual_pixel_format.sizeimage,
980 cd->actual_pixel_format.width,
981 cd->actual_pixel_format.height,
982 framebuffers, fbs_num);
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700983 } else {
984 /* Dequeue next buffer from the device. */
985 struct v4l2_buffer buf;
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700986 int res;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -0700987 CLEAR(buf);
988 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
989 buf.memory = cd->io_type == CAMERA_IO_MEMMAP ? V4L2_MEMORY_MMAP :
990 V4L2_MEMORY_USERPTR;
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -0700991 for (;;) {
992 const int res = _xioctl(cd->handle, VIDIOC_DQBUF, &buf);
993 if (res >= 0) {
994 break;
995 } else if (errno == EAGAIN) {
996 return 1; // Tells the caller to repeat.
997 } else if (errno != EINTR && errno != EIO) {
998 E("%s: VIDIOC_DQBUF on camera '%s' has failed: %s",
999 __FUNCTION__, cd->device_name, strerror(errno));
1000 return -1;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -07001001 }
1002 }
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -07001003
1004 /* Convert frame to the receiving buffers. */
1005 res = convert_frame(cd->framebuffers[buf.index].data,
1006 cd->actual_pixel_format.pixelformat,
1007 cd->actual_pixel_format.sizeimage,
1008 cd->actual_pixel_format.width,
1009 cd->actual_pixel_format.height,
1010 framebuffers, fbs_num);
1011
1012 /* Requeue the buffer back to the device. */
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -07001013 if (_xioctl(cd->handle, VIDIOC_QBUF, &buf) < 0) {
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -07001014 W("%s: VIDIOC_QBUF on camera '%s' has failed: %s",
1015 __FUNCTION__, cd->device_name, strerror(errno));
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -07001016 }
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -07001017
1018 return res;
Vladimir Chtchetkine4ed09fd2011-08-18 09:42:40 -07001019 }
1020}
1021
1022void
1023camera_device_close(CameraDevice* ccd)
1024{
1025 LinuxCameraDevice* cd;
1026
1027 /* Sanity checks. */
1028 if (ccd != NULL && ccd->opaque != NULL) {
1029 cd = (LinuxCameraDevice*)ccd->opaque;
1030 _camera_device_free(cd);
1031 } else {
1032 E("%s: Invalid camera device descriptor", __FUNCTION__);
1033 }
1034}
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -07001035
1036int
1037enumerate_camera_devices(CameraInfo* cis, int max)
1038{
1039 char dev_name[24];
1040 int found = 0;
1041 int n;
1042
1043 for (n = 0; n < max; n++) {
1044 CameraDevice* cd;
1045
1046 sprintf(dev_name, "/dev/video%d", n);
1047 cd = camera_device_open(dev_name, 0);
1048 if (cd != NULL) {
1049 LinuxCameraDevice* lcd = (LinuxCameraDevice*)cd->opaque;
1050 if (!_camera_device_get_info(lcd, cis + found)) {
Vladimir Chtchetkineb8dcaff2011-09-17 11:15:47 -07001051 char user_name[24];
1052 sprintf(user_name, "webcam%d", found);
1053 cis[found].display_name = ASTRDUP(user_name);
Vladimir Chtchetkinecf1c2c72011-09-04 09:51:40 -07001054 cis[found].in_use = 0;
1055 found++;
1056 }
1057 camera_device_close(cd);
1058 } else {
1059 break;
1060 }
1061 }
1062
1063 return found;
1064}