• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
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 "android/camera/camera-capture.h"
27  #include "android/camera/camera-format-converters.h"
28  
29  #define  E(...)    derror(__VA_ARGS__)
30  #define  W(...)    dwarning(__VA_ARGS__)
31  #define  D(...)    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  
45  /* 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   */
51  typedef 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  
60  /* Describes a framebuffer. */
61  typedef 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. */
69  typedef 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  
78  typedef struct LinuxCameraDevice LinuxCameraDevice;
79  /*
80   * Describes a connection to an actual camera device.
81   */
82  struct 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;
90  
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;
99      /* Actual pixel format reported by the device when capturing is started. */
100      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  
109  /* 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   */
123  static const uint32_t _preferred_formats[] =
124  {
125      /* Native format for the emulated camera: no conversion at all. */
126      V4L2_PIX_FMT_YUV420,
127      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. */
138  static const int _preferred_format_num =
139      sizeof(_preferred_formats)/sizeof(*_preferred_formats);
140  
141  /*******************************************************************************
142   *                     Helper routines
143   ******************************************************************************/
144  
145  /* IOCTL wrapper. */
146  static int
_xioctl(int fd,int request,void * arg)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  
155  /* Frees resource allocated for QemuPixelFormat instance, excluding the instance
156   * itself.
157   */
_qemu_pixel_format_free(QemuPixelFormat * fmt)158  static 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   */
182  static int
_get_format_index(uint32_t fmt,QemuPixelFormat * formats,int size)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  
190  /*******************************************************************************
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   */
201  static void
_free_framebuffers(CameraFrameBuffer * fb,int num,CameraIoType io_type)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:
232                  E("%s: Invalid I/O type %d", __FUNCTION__, io_type);
233                  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   */
248  static LinuxCameraDevice*
_camera_device_alloc(void)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   */
263  static void
_camera_device_free(LinuxCameraDevice * lcd)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 {
281          E("%s: No descriptor", __FUNCTION__);
282      }
283  }
284  
285  /* Resets camera device after capturing.
286   * Since new capture request may require different frame dimensions we must
287   * reset camera device by reopening its handle. Otherwise attempts to set up new
288   * frame properties (different from the previous one) may fail. */
289  static void
_camera_device_reset(LinuxCameraDevice * cd)290  _camera_device_reset(LinuxCameraDevice* cd)
291  {
292      struct v4l2_cropcap cropcap;
293      struct v4l2_crop crop;
294  
295      /* Free capturing framebuffers first. */
296      if (cd->framebuffers != NULL) {
297          _free_framebuffers(cd->framebuffers, cd->framebuffer_num, cd->io_type);
298          free(cd->framebuffers);
299          cd->framebuffers = NULL;
300          cd->framebuffer_num = 0;
301      }
302  
303      /* Reset device handle. */
304      close(cd->handle);
305      cd->handle = open(cd->device_name, O_RDWR | O_NONBLOCK, 0);
306  
307      if (cd->handle >= 0) {
308          /* Select video input, video standard and tune here. */
309          cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
310          _xioctl(cd->handle, VIDIOC_CROPCAP, &cropcap);
311          crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
312          crop.c = cropcap.defrect; /* reset to default */
313          _xioctl (cd->handle, VIDIOC_S_CROP, &crop);
314      }
315  }
316  
317  /* Memory maps buffers and shares mapped memory with the device.
318   * Return:
319   *  0 Framebuffers have been mapped.
320   *  -1 A critical error has ocurred.
321   *  1 Memory mapping is not available.
322   */
323  static int
_camera_device_mmap_framebuffer(LinuxCameraDevice * cd)324  _camera_device_mmap_framebuffer(LinuxCameraDevice* cd)
325  {
326      struct v4l2_requestbuffers req;
327      CLEAR(req);
328      req.count   = 4;
329      req.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
330      req.memory  = V4L2_MEMORY_MMAP;
331  
332      /* Request memory mapped buffers. Note that device can return less buffers
333       * than requested. */
334      if(_xioctl(cd->handle, VIDIOC_REQBUFS, &req)) {
335          if (EINVAL == errno) {
336              D("%s: Device '%s' does not support memory mapping",
337                __FUNCTION__, cd->device_name);
338              return 1;
339          } else {
340              E("%s: VIDIOC_REQBUFS has failed: %s",
341                __FUNCTION__, strerror(errno));
342              return -1;
343          }
344      }
345  
346      /* Allocate framebuffer array. */
347      cd->framebuffers = calloc(req.count, sizeof(CameraFrameBuffer));
348      if (cd->framebuffers == NULL) {
349          E("%s: Not enough memory to allocate framebuffer array", __FUNCTION__);
350          return -1;
351      }
352  
353      /* Map every framebuffer to the shared memory, and queue it
354       * with the device. */
355      for(cd->framebuffer_num = 0; cd->framebuffer_num < req.count;
356          cd->framebuffer_num++) {
357          /* Map framebuffer. */
358          struct v4l2_buffer buf;
359          CLEAR(buf);
360          buf.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
361          buf.memory  = V4L2_MEMORY_MMAP;
362          buf.index   = cd->framebuffer_num;
363          if(_xioctl(cd->handle, VIDIOC_QUERYBUF, &buf) < 0) {
364              E("%s: VIDIOC_QUERYBUF has failed: %s",
365                __FUNCTION__, strerror(errno));
366              return -1;
367          }
368          cd->framebuffers[cd->framebuffer_num].size = buf.length;
369          cd->framebuffers[cd->framebuffer_num].data =
370              mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED,
371                   cd->handle, buf.m.offset);
372          if (MAP_FAILED == cd->framebuffers[cd->framebuffer_num].data) {
373              E("%s: Memory mapping has failed: %s",
374                __FUNCTION__, strerror(errno));
375              return -1;
376          }
377  
378          /* Queue the mapped buffer. */
379          CLEAR(buf);
380          buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
381          buf.memory = V4L2_MEMORY_MMAP;
382          buf.index = cd->framebuffer_num;
383          if (_xioctl(cd->handle, VIDIOC_QBUF, &buf) < 0) {
384              E("%s: VIDIOC_QBUF has failed: %s", __FUNCTION__, strerror(errno));
385              return -1;
386          }
387      }
388  
389      cd->io_type = CAMERA_IO_MEMMAP;
390  
391      return 0;
392  }
393  
394  /* Allocates frame buffers and registers them with the device.
395   * Return:
396   *  0 Framebuffers have been mapped.
397   *  -1 A critical error has ocurred.
398   *  1 Device doesn't support user pointers.
399   */
400  static int
_camera_device_user_framebuffer(LinuxCameraDevice * cd)401  _camera_device_user_framebuffer(LinuxCameraDevice* cd)
402  {
403      struct v4l2_requestbuffers req;
404      CLEAR (req);
405      req.count   = 4;
406      req.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
407      req.memory  = V4L2_MEMORY_USERPTR;
408  
409      /* Request user buffers. Note that device can return less buffers
410       * than requested. */
411      if(_xioctl(cd->handle, VIDIOC_REQBUFS, &req)) {
412          if (EINVAL == errno) {
413              D("%s: Device '%s' does not support user pointers",
414                __FUNCTION__, cd->device_name);
415              return 1;
416          } else {
417              E("%s: VIDIOC_REQBUFS has failed: %s",
418                __FUNCTION__, strerror(errno));
419              return -1;
420          }
421      }
422  
423      /* Allocate framebuffer array. */
424      cd->framebuffers = calloc(req.count, sizeof(CameraFrameBuffer));
425      if (cd->framebuffers == NULL) {
426          E("%s: Not enough memory to allocate framebuffer array", __FUNCTION__);
427          return -1;
428      }
429  
430      /* Allocate buffers, queueing them wit the device at the same time */
431      for(cd->framebuffer_num = 0; cd->framebuffer_num < req.count;
432          cd->framebuffer_num++) {
433          cd->framebuffers[cd->framebuffer_num].size =
434              cd->actual_pixel_format.sizeimage;
435          cd->framebuffers[cd->framebuffer_num].data =
436              malloc(cd->framebuffers[cd->framebuffer_num].size);
437          if (cd->framebuffers[cd->framebuffer_num].data == NULL) {
438              E("%s: Not enough memory to allocate framebuffer", __FUNCTION__);
439              return -1;
440          }
441  
442          /* Queue the user buffer. */
443          struct v4l2_buffer buf;
444          CLEAR(buf);
445          buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
446          buf.memory = V4L2_MEMORY_USERPTR;
447          buf.m.userptr = (unsigned long)cd->framebuffers[cd->framebuffer_num].data;
448          buf.length = cd->framebuffers[cd->framebuffer_num].size;
449          if (_xioctl(cd->handle, VIDIOC_QBUF, &buf) < 0) {
450              E("%s: VIDIOC_QBUF has failed: %s", __FUNCTION__, strerror(errno));
451              return -1;
452          }
453      }
454  
455      cd->io_type = CAMERA_IO_USERPTR;
456  
457      return 0;
458  }
459  
460  /* Allocate frame buffer for direct read from the device.
461   * Return:
462   *  0 Framebuffers have been mapped.
463   *  -1 A critical error has ocurred.
464   *  1 Memory mapping is not available.
465   */
466  static int
_camera_device_direct_framebuffer(LinuxCameraDevice * cd)467  _camera_device_direct_framebuffer(LinuxCameraDevice* cd)
468  {
469      /* Allocate framebuffer array. */
470      cd->framebuffer_num = 1;
471      cd->framebuffers = malloc(sizeof(CameraFrameBuffer));
472      if (cd->framebuffers == NULL) {
473          E("%s: Not enough memory to allocate framebuffer array", __FUNCTION__);
474          return -1;
475      }
476  
477      cd->framebuffers[0].size = cd->actual_pixel_format.sizeimage;
478      cd->framebuffers[0].data = malloc(cd->framebuffers[0].size);
479      if (cd->framebuffers[0].data == NULL) {
480          E("%s: Not enough memory to allocate framebuffer", __FUNCTION__);
481          return -1;
482      }
483  
484      cd->io_type = CAMERA_IO_DIRECT;
485  
486      return 0;
487  }
488  
489  /* Opens camera device.
490   * Param:
491   *  cd - Camera device descriptor to open the camera for.
492   * Return:
493   *  0 on success, != 0 on failure.
494   */
495  static int
_camera_device_open(LinuxCameraDevice * cd)496  _camera_device_open(LinuxCameraDevice* cd)
497  {
498      struct stat st;
499  
500      if (stat(cd->device_name, &st)) {
501          return -1;
502      }
503  
504      if (!S_ISCHR(st.st_mode)) {
505          E("%s: '%s' is not a device", __FUNCTION__, cd->device_name);
506          return -1;
507      }
508  
509      /* Open handle to the device, and query device capabilities. */
510      cd->handle = open(cd->device_name, O_RDWR | O_NONBLOCK, 0);
511      if (cd->handle < 0) {
512          E("%s: Cannot open camera device '%s': %s",
513            __FUNCTION__, cd->device_name, strerror(errno));
514          return -1;
515      }
516      if (_xioctl(cd->handle, VIDIOC_QUERYCAP, &cd->caps) < 0) {
517          if (EINVAL == errno) {
518              E("%s: Camera '%s' is not a V4L2 device",
519                __FUNCTION__, cd->device_name);
520              close(cd->handle);
521              cd->handle = -1;
522              return -1;
523          } else {
524              E("%s: Unable to query capabilities for camera device '%s'",
525                __FUNCTION__, cd->device_name);
526              close(cd->handle);
527              cd->handle = -1;
528              return -1;
529          }
530      }
531  
532      /* Make sure that camera supports minimal requirements. */
533      if (!(cd->caps.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
534          E("%s: Camera '%s' is not a video capture device",
535            __FUNCTION__, cd->device_name);
536          close(cd->handle);
537          cd->handle = -1;
538          return -1;
539      }
540  
541      return 0;
542  }
543  
544  /* Enumerates frame sizes for the given pixel format.
545   * Param:
546   *  cd - Opened camera device descriptor.
547   *  fmt - Pixel format to enum frame sizes for.
548   *  sizes - Upon success contains an array of supported frame sizes. The size of
549   *      the array is defined by the value, returned from this routine. The caller
550   *      is responsible for freeing memory allocated for this array.
551   * Return:
552   *  On success returns number of entries in the 'sizes' array. On failure returns
553   *  a negative value.
554   */
555  static int
_camera_device_enum_format_sizes(LinuxCameraDevice * cd,uint32_t fmt,CameraFrameDim ** sizes)556  _camera_device_enum_format_sizes(LinuxCameraDevice* cd,
557                                   uint32_t fmt,
558                                   CameraFrameDim** sizes)
559  {
560      int n;
561      int sizes_num = 0;
562      int out_num = 0;
563      struct v4l2_frmsizeenum size_enum;
564      CameraFrameDim* arr;
565  
566      /* Calculate number of supported sizes for the given format. */
567      for (n = 0; ; n++) {
568          size_enum.index = n;
569          size_enum.pixel_format = fmt;
570          if(_xioctl(cd->handle, VIDIOC_ENUM_FRAMESIZES, &size_enum)) {
571              break;
572          }
573          if (size_enum.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
574              /* Size is in the simpe width, height form. */
575              sizes_num++;
576          } else if (size_enum.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
577              /* Sizes are represented as min/max width and height with a step for
578               * each dimension. Since at the end we want to list each supported
579               * size in the array (that's the only format supported by the guest
580               * camera framework), we need to calculate how many array entries
581               * this will generate. */
582              const uint32_t dif_widths =
583                  (size_enum.stepwise.max_width - size_enum.stepwise.min_width) /
584                  size_enum.stepwise.step_width + 1;
585              const uint32_t dif_heights =
586                  (size_enum.stepwise.max_height - size_enum.stepwise.min_height) /
587                  size_enum.stepwise.step_height + 1;
588              sizes_num += dif_widths * dif_heights;
589          } else if (size_enum.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
590              /* Special stepwise case, when steps are set to 1. We still need to
591               * flatten this for the guest, but the array may be too big.
592               * Fortunately, we don't need to be fancy, so three sizes would be
593               * sufficient here: min, max, and one in the middle. */
594              sizes_num += 3;
595          }
596  
597      }
598      if (sizes_num == 0) {
599          return 0;
600      }
601  
602      /* Allocate, and initialize the array of supported entries. */
603      *sizes = (CameraFrameDim*)malloc(sizes_num * sizeof(CameraFrameDim));
604      if (*sizes == NULL) {
605          E("%s: Memory allocation failure", __FUNCTION__);
606          return -1;
607      }
608      arr = *sizes;
609      for (n = 0; out_num < sizes_num; n++) {
610          size_enum.index = n;
611          size_enum.pixel_format = fmt;
612          if(_xioctl(cd->handle, VIDIOC_ENUM_FRAMESIZES, &size_enum)) {
613              /* Errors are not welcome here anymore. */
614              E("%s: Unexpected failure while getting pixel dimensions: %s",
615                strerror(errno));
616              free(arr);
617              return -1;
618          }
619  
620          if (size_enum.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
621              arr[out_num].width = size_enum.discrete.width;
622              arr[out_num].height = size_enum.discrete.height;
623              out_num++;
624          } else if (size_enum.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
625              uint32_t w;
626              for (w = size_enum.stepwise.min_width;
627                   w <= size_enum.stepwise.max_width;
628                   w += size_enum.stepwise.step_width) {
629                  uint32_t h;
630                  for (h = size_enum.stepwise.min_height;
631                       h <= size_enum.stepwise.max_height;
632                       h += size_enum.stepwise.step_height) {
633                      arr[out_num].width = w;
634                      arr[out_num].height = h;
635                      out_num++;
636                  }
637              }
638          } else if (size_enum.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
639              /* min */
640              arr[out_num].width = size_enum.stepwise.min_width;
641              arr[out_num].height = size_enum.stepwise.min_height;
642              out_num++;
643              /* one in the middle */
644              arr[out_num].width =
645                  (size_enum.stepwise.min_width + size_enum.stepwise.max_width) / 2;
646              arr[out_num].height =
647                  (size_enum.stepwise.min_height + size_enum.stepwise.max_height) / 2;
648              out_num++;
649              /* max */
650              arr[out_num].width = size_enum.stepwise.max_width;
651              arr[out_num].height = size_enum.stepwise.max_height;
652              out_num++;
653          }
654      }
655  
656      return out_num;
657  }
658  
659  /* Enumerates pixel formats, supported by the device.
660   * Note that this routine will enumerate only raw (uncompressed) formats.
661   * Param:
662   *  cd - Opened camera device descriptor.
663   *  fmts - Upon success contains an array of supported pixel formats. The size of
664   *      the array is defined by the value, returned from this routine. The caller
665   *      is responsible for freeing memory allocated for this array.
666   * Return:
667   *  On success returns number of entries in the 'fmts' array. On failure returns
668   *  a negative value.
669   */
670  static int
_camera_device_enum_pixel_formats(LinuxCameraDevice * cd,QemuPixelFormat ** fmts)671  _camera_device_enum_pixel_formats(LinuxCameraDevice* cd, QemuPixelFormat** fmts)
672  {
673      int n;
674      int fmt_num = 0;
675      int out_num = 0;
676      struct v4l2_fmtdesc fmt_enum;
677      QemuPixelFormat* arr;
678  
679      /* Calculate number of supported formats. */
680      for (n = 0; ; n++) {
681          fmt_enum.index = n;
682          fmt_enum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
683          if(_xioctl(cd->handle, VIDIOC_ENUM_FMT, &fmt_enum)) {
684              break;
685          }
686          /* Skip the compressed ones. */
687          if ((fmt_enum.flags & V4L2_FMT_FLAG_COMPRESSED) == 0) {
688              fmt_num++;
689          }
690      }
691      if (fmt_num == 0) {
692          return 0;
693      }
694  
695      /* Allocate, and initialize array for enumerated formats. */
696      *fmts = (QemuPixelFormat*)malloc(fmt_num * sizeof(QemuPixelFormat));
697      if (*fmts == NULL) {
698          E("%s: Memory allocation failure", __FUNCTION__);
699          return -1;
700      }
701      arr = *fmts;
702      memset(arr, 0, fmt_num * sizeof(QemuPixelFormat));
703      for (n = 0; out_num < fmt_num; n++) {
704          fmt_enum.index = n;
705          fmt_enum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
706          if(_xioctl(cd->handle, VIDIOC_ENUM_FMT, &fmt_enum)) {
707              int nn;
708              /* Errors are not welcome here anymore. */
709              E("%s: Unexpected failure while getting pixel format: %s",
710                strerror(errno));
711              for (nn = 0; nn < out_num; nn++) {
712                  _qemu_pixel_format_free(arr + nn);
713              }
714              free(arr);
715              return -1;
716          }
717          /* Skip the compressed ones. */
718          if ((fmt_enum.flags & V4L2_FMT_FLAG_COMPRESSED) == 0) {
719              arr[out_num].format = fmt_enum.pixelformat;
720              /* Enumerate frame dimensions supported for this format. */
721              arr[out_num].dim_num =
722                  _camera_device_enum_format_sizes(cd, fmt_enum.pixelformat,
723                                                   &arr[out_num].dims);
724              if (arr[out_num].dim_num > 0) {
725                  out_num++;
726              } else if (arr[out_num].dim_num < 0) {
727                  int nn;
728                  E("Unable to enumerate supported dimensions for pixel format %d",
729                    fmt_enum.pixelformat);
730                  for (nn = 0; nn < out_num; nn++) {
731                      _qemu_pixel_format_free(arr + nn);
732                  }
733                  free(arr);
734                  return -1;
735              }
736          }
737      }
738  
739      return out_num;
740  }
741  
742  /* Collects information about an opened camera device.
743   * The information collected in this routine contains list of pixel formats,
744   * supported by the device, and list of frame dimensions supported by the camera
745   * for each pixel format.
746   * Param:
747   *  cd - Opened camera device descriptor.
748   *  cis - Upon success contains information collected from the camera device.
749   * Return:
750   *  0 on success, != 0 on failure.
751   */
752  static int
_camera_device_get_info(LinuxCameraDevice * cd,CameraInfo * cis)753  _camera_device_get_info(LinuxCameraDevice* cd, CameraInfo* cis)
754  {
755      int f;
756      int chosen = -1;
757      QemuPixelFormat* formats = NULL;
758      int num_pix_fmts = _camera_device_enum_pixel_formats(cd, &formats);
759      if (num_pix_fmts <= 0) {
760          return num_pix_fmts;
761      }
762  
763      /* Lets see if camera supports preferred formats */
764      for (f = 0; f < _preferred_format_num; f++) {
765          chosen = _get_format_index(_preferred_formats[f], formats, num_pix_fmts);
766          if (chosen >= 0) {
767              break;
768          }
769      }
770      if (chosen < 0) {
771          /* Camera doesn't support any of the chosen formats. Then it doesn't
772           * matter which one we choose. Lets choose the first one. */
773          chosen = 0;
774      }
775  
776      cis->device_name = ASTRDUP(cd->device_name);
777      cis->inp_channel = cd->input_channel;
778      cis->pixel_format = formats[chosen].format;
779      cis->frame_sizes_num = formats[chosen].dim_num;
780      /* Swap instead of copy. */
781      cis->frame_sizes = formats[chosen].dims;
782      formats[chosen].dims = NULL;
783      cis->in_use = 0;
784  
785      for (f = 0; f < num_pix_fmts; f++) {
786          _qemu_pixel_format_free(formats + f);
787      }
788      free(formats);
789  
790      return 0;
791  }
792  
793  /*******************************************************************************
794   *                     CameraDevice API
795   ******************************************************************************/
796  
797  CameraDevice*
camera_device_open(const char * name,int inp_channel)798  camera_device_open(const char* name, int inp_channel)
799  {
800      struct v4l2_cropcap cropcap;
801      struct v4l2_crop crop;
802      LinuxCameraDevice* cd;
803  
804      /* Allocate and initialize the descriptor. */
805      cd = _camera_device_alloc();
806      cd->device_name = name != NULL ? ASTRDUP(name) : ASTRDUP("/dev/video0");
807      cd->input_channel = inp_channel;
808  
809      /* Open the device. */
810      if (_camera_device_open(cd)) {
811          _camera_device_free(cd);
812          return NULL;
813      }
814  
815      /* Select video input, video standard and tune here. */
816      cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
817      _xioctl(cd->handle, VIDIOC_CROPCAP, &cropcap);
818      crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
819      crop.c = cropcap.defrect; /* reset to default */
820      _xioctl (cd->handle, VIDIOC_S_CROP, &crop);
821  
822      return &cd->header;
823  }
824  
825  int
camera_device_start_capturing(CameraDevice * ccd,uint32_t pixel_format,int frame_width,int frame_height)826  camera_device_start_capturing(CameraDevice* ccd,
827                                uint32_t pixel_format,
828                                int frame_width,
829                                int frame_height)
830  {
831      struct v4l2_format fmt;
832      LinuxCameraDevice* cd;
833      char fmt_str[5];
834      int r;
835  
836      /* Sanity checks. */
837      if (ccd == NULL || ccd->opaque == NULL) {
838        E("%s: Invalid camera device descriptor", __FUNCTION__);
839        return -1;
840      }
841      cd = (LinuxCameraDevice*)ccd->opaque;
842      if (cd->handle < 0) {
843        E("%s: Camera device is not opened", __FUNCTION__);
844        return -1;
845      }
846  
847      /* Try to set pixel format with the given dimensions. */
848      CLEAR(fmt);
849      fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
850      fmt.fmt.pix.width       = frame_width;
851      fmt.fmt.pix.height      = frame_height;
852      fmt.fmt.pix.pixelformat = pixel_format;
853      if (_xioctl(cd->handle, VIDIOC_S_FMT, &fmt) < 0) {
854          memcpy(fmt_str, &pixel_format, 4);
855          fmt_str[4] = '\0';
856          E("%s: Camera '%s' does not support pixel format '%s' with dimensions %dx%d",
857            __FUNCTION__, cd->device_name, fmt_str, frame_width, frame_height);
858          _camera_device_reset(cd);
859          return -1;
860      }
861      /* VIDIOC_S_FMT may has changed some properties of the structure. Make sure
862       * that dimensions didn't change. */
863      if (fmt.fmt.pix.width != frame_width || fmt.fmt.pix.height != frame_height) {
864          memcpy(fmt_str, &pixel_format, 4);
865          fmt_str[4] = '\0';
866          E("%s: Dimensions %dx%d are wrong for pixel format '%s'",
867            __FUNCTION__, frame_width, frame_height, fmt_str);
868          _camera_device_reset(cd);
869          return -1;
870      }
871      memcpy(&cd->actual_pixel_format, &fmt.fmt.pix, sizeof(struct v4l2_pix_format));
872  
873      /*
874       * Lets initialize frame buffers, and see what kind of I/O we're going to
875       * use to retrieve frames.
876       */
877  
878      /* First, lets see if we can do mapped I/O (as most performant one). */
879      r = _camera_device_mmap_framebuffer(cd);
880      if (r < 0) {
881          /* Some critical error has ocurred. Bail out. */
882          _camera_device_reset(cd);
883          return -1;
884      } else if (r > 0) {
885          /* Device doesn't support memory mapping. Retrieve to the next performant
886           * one: preallocated user buffers. */
887          r = _camera_device_user_framebuffer(cd);
888          if (r < 0) {
889              /* Some critical error has ocurred. Bail out. */
890              _camera_device_reset(cd);
891              return -1;
892          } else if (r > 0) {
893              /* The only thing left for us is direct reading from the device. */
894              if (!(cd->caps.capabilities & V4L2_CAP_READWRITE)) {
895                  E("%s: Don't know how to access frames on device '%s'",
896                    __FUNCTION__, cd->device_name);
897                  _camera_device_reset(cd);
898                  return -1;
899              }
900              r = _camera_device_direct_framebuffer(cd);
901              if (r != 0) {
902                  /* Any error at this point is a critical one. */
903                  _camera_device_reset(cd);
904                  return -1;
905              }
906          }
907      }
908  
909      /* Start capturing from the device. */
910      if (cd->io_type != CAMERA_IO_DIRECT) {
911          enum v4l2_buf_type type;
912          type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
913          if (_xioctl (cd->handle, VIDIOC_STREAMON, &type) < 0) {
914              E("%s: VIDIOC_STREAMON on camera '%s' has failed: %s",
915                __FUNCTION__, cd->device_name, strerror(errno));
916              _camera_device_reset(cd);
917              return -1;
918          }
919      }
920      return 0;
921  }
922  
923  int
camera_device_stop_capturing(CameraDevice * ccd)924  camera_device_stop_capturing(CameraDevice* ccd)
925  {
926      enum v4l2_buf_type type;
927      LinuxCameraDevice* cd;
928  
929      /* Sanity checks. */
930      if (ccd == NULL || ccd->opaque == NULL) {
931        E("%s: Invalid camera device descriptor", __FUNCTION__);
932        return -1;
933      }
934      cd = (LinuxCameraDevice*)ccd->opaque;
935      if (cd->handle < 0) {
936        E("%s: Camera device is not opened", __FUNCTION__);
937        return -1;
938      }
939  
940      switch (cd->io_type) {
941          case CAMERA_IO_DIRECT:
942              /* Nothing to do. */
943              break;
944  
945          case CAMERA_IO_MEMMAP:
946          case CAMERA_IO_USERPTR:
947              type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
948              if (_xioctl(cd->handle, VIDIOC_STREAMOFF, &type) < 0) {
949  	            E("%s: VIDIOC_STREAMOFF on camera '%s' has failed: %s",
950                    __FUNCTION__, cd->device_name, strerror(errno));
951                  return -1;
952              }
953              break;
954          default:
955              E("%s: Unknown I/O method: %d", __FUNCTION__, cd->io_type);
956              return -1;
957      }
958  
959      /* Reopen the device to reset its internal state. It seems that if we don't
960       * do that, an attempt to reinit the device with different frame dimensions
961       * would fail. */
962      _camera_device_reset(cd);
963  
964      return 0;
965  }
966  
967  int
camera_device_read_frame(CameraDevice * ccd,ClientFrameBuffer * framebuffers,int fbs_num)968  camera_device_read_frame(CameraDevice* ccd,
969                           ClientFrameBuffer* framebuffers,
970                           int fbs_num)
971  {
972      LinuxCameraDevice* cd;
973  
974      /* Sanity checks. */
975      if (ccd == NULL || ccd->opaque == NULL) {
976        E("%s: Invalid camera device descriptor", __FUNCTION__);
977        return -1;
978      }
979      cd = (LinuxCameraDevice*)ccd->opaque;
980      if (cd->handle < 0) {
981        E("%s: Camera device is not opened", __FUNCTION__);
982        return -1;
983      }
984  
985      if (cd->io_type == CAMERA_IO_DIRECT) {
986          /* Read directly from the device. */
987          size_t total_read_bytes = 0;
988          /* There is one framebuffer allocated for direct read. */
989          void* buff = cd->framebuffers[0].data;
990          do {
991              int read_bytes =
992                  read(cd->handle, buff + total_read_bytes,
993                       cd->actual_pixel_format.sizeimage - total_read_bytes);
994              if (read_bytes < 0) {
995                  switch (errno) {
996                      case EIO:
997                      case EAGAIN:
998                          continue;
999                      default:
1000                          E("%s: Unable to read from the camera device '%s': %s",
1001                            __FUNCTION__, cd->device_name, strerror(errno));
1002                          return -1;
1003                  }
1004              }
1005              total_read_bytes += read_bytes;
1006          } while (total_read_bytes < cd->actual_pixel_format.sizeimage);
1007          /* Convert the read frame into the caller's framebuffers. */
1008          return convert_frame(buff, cd->actual_pixel_format.pixelformat,
1009                               cd->actual_pixel_format.sizeimage,
1010                               cd->actual_pixel_format.width,
1011                               cd->actual_pixel_format.height,
1012                               framebuffers, fbs_num);
1013      } else {
1014          /* Dequeue next buffer from the device. */
1015          struct v4l2_buffer buf;
1016          int res;
1017          CLEAR(buf);
1018          buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1019          buf.memory = cd->io_type == CAMERA_IO_MEMMAP ? V4L2_MEMORY_MMAP :
1020                                                         V4L2_MEMORY_USERPTR;
1021          for (;;) {
1022              const int res = _xioctl(cd->handle, VIDIOC_DQBUF, &buf);
1023              if (res >= 0) {
1024                  break;
1025              } else if (errno == EAGAIN) {
1026                  return 1;   // Tells the caller to repeat.
1027              } else if (errno != EINTR && errno != EIO) {
1028                  E("%s: VIDIOC_DQBUF on camera '%s' has failed: %s",
1029                    __FUNCTION__, cd->device_name, strerror(errno));
1030                  return -1;
1031              }
1032          }
1033  
1034          /* Convert frame to the receiving buffers. */
1035          res = convert_frame(cd->framebuffers[buf.index].data,
1036                              cd->actual_pixel_format.pixelformat,
1037                              cd->actual_pixel_format.sizeimage,
1038                              cd->actual_pixel_format.width,
1039                              cd->actual_pixel_format.height,
1040                              framebuffers, fbs_num);
1041  
1042          /* Requeue the buffer back to the device. */
1043          if (_xioctl(cd->handle, VIDIOC_QBUF, &buf) < 0) {
1044              W("%s: VIDIOC_QBUF on camera '%s' has failed: %s",
1045                __FUNCTION__, cd->device_name, strerror(errno));
1046          }
1047  
1048          return res;
1049      }
1050  }
1051  
1052  void
camera_device_close(CameraDevice * ccd)1053  camera_device_close(CameraDevice* ccd)
1054  {
1055      LinuxCameraDevice* cd;
1056  
1057      /* Sanity checks. */
1058      if (ccd != NULL && ccd->opaque != NULL) {
1059          cd = (LinuxCameraDevice*)ccd->opaque;
1060          _camera_device_free(cd);
1061      } else {
1062          E("%s: Invalid camera device descriptor", __FUNCTION__);
1063      }
1064  }
1065  
1066  int
enumerate_camera_devices(CameraInfo * cis,int max)1067  enumerate_camera_devices(CameraInfo* cis, int max)
1068  {
1069      char dev_name[24];
1070      int found = 0;
1071      int n;
1072  
1073      for (n = 0; n < max; n++) {
1074          CameraDevice* cd;
1075  
1076          sprintf(dev_name, "/dev/video%d", n);
1077          cd = camera_device_open(dev_name, 0);
1078          if (cd != NULL) {
1079              LinuxCameraDevice* lcd = (LinuxCameraDevice*)cd->opaque;
1080              if (!_camera_device_get_info(lcd, cis + found)) {
1081                  char user_name[24];
1082                  sprintf(user_name, "webcam%d", found);
1083                  cis[found].display_name = ASTRDUP(user_name);
1084                  cis[found].in_use = 0;
1085                  found++;
1086              }
1087              camera_device_close(cd);
1088          } else {
1089              break;
1090          }
1091      }
1092  
1093      return found;
1094  }
1095