14ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/* 24ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * Copyright (C) 2011 The Android Open Source Project 34ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * 44ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * Licensed under the Apache License, Version 2.0 (the "License"); 54ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * you may not use this file except in compliance with the License. 64ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * You may obtain a copy of the License at 74ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * 84ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * http://www.apache.org/licenses/LICENSE-2.0 94ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * 104ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * Unless required by applicable law or agreed to in writing, software 114ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * distributed under the License is distributed on an "AS IS" BASIS, 124ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * See the License for the specific language governing permissions and 144ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * limitations under the License. 154ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine */ 164ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 174ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/* 184ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * Contains code that is used to capture video frames from a camera device 194ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * on Linux. This code uses V4L2 API to work with camera devices, and requires 204ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * Linux kernel version at least 2.5 214ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine */ 224ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 234ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine#include <sys/mman.h> 244ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine#include <sys/stat.h> 254ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine#include <sys/ioctl.h> 264ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine#include "android/camera/camera-capture.h" 274ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine#include "android/camera/camera-format-converters.h" 284ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 29c68dbbef0118eab4256acfc0d9430f0e557a82a1Vladimir Chtchetkine#define E(...) derror(__VA_ARGS__) 30c68dbbef0118eab4256acfc0d9430f0e557a82a1Vladimir Chtchetkine#define W(...) dwarning(__VA_ARGS__) 314ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine#define D(...) VERBOSE_PRINT(camera,__VA_ARGS__) 324ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine#define D_ACTIVE VERBOSE_CHECK(camera) 334ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 344ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/* the T(...) macro is used to dump traffic */ 354ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine#define T_ACTIVE 0 364ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 374ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine#if T_ACTIVE 384ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine#define T(...) VERBOSE_PRINT(camera,__VA_ARGS__) 394ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine#else 404ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine#define T(...) ((void)0) 414ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine#endif 424ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 434ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine#define CLEAR(x) memset (&(x), 0, sizeof(x)) 444ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 45cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine/* Pixel format descriptor. 46cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * Instances of this descriptor are created during camera device enumeration, and 47cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * an instance of this structure describing pixel format chosen for the camera 48cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * emulation is saved by the camera factory service to represent an emulating 49cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * camera properties. 50cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine */ 51cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkinetypedef struct QemuPixelFormat { 52cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Pixel format in V4L2_PIX_FMT_XXX form. */ 53cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine uint32_t format; 54cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Frame dimensions supported by this format. */ 55cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine CameraFrameDim* dims; 56cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Number of frame dimensions supported by this format. */ 57cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int dim_num; 58cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine} QemuPixelFormat; 59cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 604ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/* Describes a framebuffer. */ 614ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkinetypedef struct CameraFrameBuffer { 624ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Framebuffer data. */ 634ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine uint8_t* data; 644ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Framebuffer data size. */ 654ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine size_t size; 664ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine} CameraFrameBuffer; 674ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 684ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/* Defines type of the I/O used to obtain frames from the device. */ 694ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkinetypedef enum CameraIoType { 704ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Framebuffers are shared via memory mapping. */ 714ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine CAMERA_IO_MEMMAP, 724ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Framebuffers are available via user pointers. */ 734ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine CAMERA_IO_USERPTR, 744ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Framebuffers are to be read from the device. */ 754ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine CAMERA_IO_DIRECT 764ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine} CameraIoType; 774ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 784ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkinetypedef struct LinuxCameraDevice LinuxCameraDevice; 794ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/* 804ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * Describes a connection to an actual camera device. 814ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine */ 824ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkinestruct LinuxCameraDevice { 834ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Common header. */ 844ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine CameraDevice header; 854ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 864ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Camera device name. (default is /dev/video0) */ 874ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine char* device_name; 884ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Input channel. (default is 0) */ 894ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine int input_channel; 904ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 914ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* 924ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * Set by the framework after initializing camera connection. 934ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine */ 944ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 954ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Handle to the opened camera device. */ 964ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine int handle; 974ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Device capabilities. */ 984ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine struct v4l2_capability caps; 99cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Actual pixel format reported by the device when capturing is started. */ 1004ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine struct v4l2_pix_format actual_pixel_format; 1014ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Defines type of the I/O to use to retrieve frames from the device. */ 1024ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine CameraIoType io_type; 1034ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Allocated framebuffers. */ 1044ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine struct CameraFrameBuffer* framebuffers; 1054ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Actual number of allocated framebuffers. */ 1064ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine int framebuffer_num; 1074ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine}; 1084ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 109cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine/* Preferred pixel formats arranged from the most to the least desired. 110cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * 111cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * More than anything else this array is defined by an existance of format 112cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * conversion between the camera supported formats, and formats that are 113cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * supported by camera framework in the guest system. Currently, guest supports 114cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * only YV12 pixel format for data, and RGB32 for preview. So, this array should 115cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * contain only those formats, for which converters are implemented. Generally 116cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * speaking, the order in which entries should be arranged in this array matters 117cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * only as far as conversion speed is concerned. So, formats with the fastest 118cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * converters should be put closer to the top of the array, while slower ones 119cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * should be put closer to the bottom. But as far as functionality is concerned, 120cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * the orser doesn't matter, and any format can be placed anywhere in this array, 121cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * as long as conversion for it exists. 122cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine */ 123cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkinestatic const uint32_t _preferred_formats[] = 124cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine{ 125cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Native format for the emulated camera: no conversion at all. */ 126ddd59b14583126d6282d2fab3142171934981e85Vladimir Chtchetkine V4L2_PIX_FMT_YUV420, 127cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine V4L2_PIX_FMT_YVU420, 128cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Continue with YCbCr: less math than with RGB */ 129cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine V4L2_PIX_FMT_NV12, 130cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine V4L2_PIX_FMT_NV21, 131cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine V4L2_PIX_FMT_YUYV, 132cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* End with RGB. */ 133cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine V4L2_PIX_FMT_RGB32, 134cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine V4L2_PIX_FMT_RGB24, 135cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine V4L2_PIX_FMT_RGB565, 136cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine}; 137cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine/* Number of entries in _preferred_formats array. */ 138cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkinestatic const int _preferred_format_num = 139cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine sizeof(_preferred_formats)/sizeof(*_preferred_formats); 140cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 1414ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/******************************************************************************* 1424ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * Helper routines 1434ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine ******************************************************************************/ 1444ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 1454ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/* IOCTL wrapper. */ 1464ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkinestatic int 1474ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine_xioctl(int fd, int request, void *arg) { 1484ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine int r; 1494ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine do { 1504ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine r = ioctl(fd, request, arg); 1514ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } while (-1 == r && EINTR == errno); 1524ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return r; 1534ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine} 1544ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 155cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine/* Frees resource allocated for QemuPixelFormat instance, excluding the instance 156cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * itself. 157cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine */ 158cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkinestatic void _qemu_pixel_format_free(QemuPixelFormat* fmt) 159cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine{ 160cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (fmt != NULL) { 161cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (fmt->dims != NULL) 162cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine free(fmt->dims); 163cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 164cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine} 165cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 166cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine/* Returns an index of the given pixel format in an array containing pixel 167cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * format descriptors. 168cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * This routine is used to choose a pixel format for a camera device. The idea 169cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * is that when the camera service enumerates all pixel formats for all cameras 170cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * connected to the host, we need to choose just one, which would be most 171cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * appropriate for camera emulation. To do that, the camera service will run 172cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * formats, contained in _preferred_formats array against enumerated pixel 173cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * formats to pick the first format that match. 174cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * Param: 175cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * fmt - Pixel format, for which to obtain the index. 176cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * formats - Array containing list of pixel formats, supported by the camera 177cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * device. 178cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * size - Number of elements in the 'formats' array. 179cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * Return: 180cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * Index of the matched entry in the array, or -1 if no entry has been found. 181cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine */ 182cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkinestatic int 183cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine_get_format_index(uint32_t fmt, QemuPixelFormat* formats, int size) 184cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine{ 185cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int f; 186cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine for (f = 0; f < size && formats[f].format != fmt; f++); 187cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return f < size ? f : -1; 188cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine} 189cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 1904ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/******************************************************************************* 1914ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * CameraFrameBuffer routines 1924ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine ******************************************************************************/ 1934ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 1944ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/* Frees array of framebuffers, depending on the I/O method the array has been 1954ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * initialized for. 1964ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * Note that this routine doesn't frees the array itself. 1974ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * Param: 1984ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * fb, num - Array data, and its size. 1994ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * io_type - Type of the I/O the array has been initialized for. 2004ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine */ 2014ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkinestatic void 2024ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine_free_framebuffers(CameraFrameBuffer* fb, int num, CameraIoType io_type) 2034ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine{ 2044ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (fb != NULL) { 2054ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine int n; 2064ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 2074ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine switch (io_type) { 2084ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine case CAMERA_IO_MEMMAP: 2094ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Unmap framebuffers. */ 2104ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine for (n = 0; n < num; n++) { 2114ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (fb[n].data != NULL) { 2124ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine munmap(fb[n].data, fb[n].size); 2134ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine fb[n].data = NULL; 2144ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine fb[n].size = 0; 2154ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 2164ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 2174ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine break; 2184ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 2194ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine case CAMERA_IO_USERPTR: 2204ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine case CAMERA_IO_DIRECT: 2214ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Free framebuffers. */ 2224ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine for (n = 0; n < num; n++) { 2234ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (fb[n].data != NULL) { 2244ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine free(fb[n].data); 2254ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine fb[n].data = NULL; 2264ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine fb[n].size = 0; 2274ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 2284ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 2294ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine break; 2304ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 2314ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine default: 232cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("%s: Invalid I/O type %d", __FUNCTION__, io_type); 2334ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine break; 2344ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 2354ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 2364ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine} 2374ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 2384ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/******************************************************************************* 2394ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * CameraDevice routines 2404ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine ******************************************************************************/ 2414ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 2424ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/* Allocates an instance of LinuxCameraDevice structure. 2434ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * Return: 2444ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * Allocated instance of LinuxCameraDevice structure. Note that this routine 2454ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * also sets 'opaque' field in the 'header' structure to point back to the 2464ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * containing LinuxCameraDevice instance. 2474ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine */ 2484ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkinestatic LinuxCameraDevice* 2494ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine_camera_device_alloc(void) 2504ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine{ 2514ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine LinuxCameraDevice* cd; 2524ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 2534ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine ANEW0(cd); 2544ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine memset(cd, 0, sizeof(*cd)); 2554ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->header.opaque = cd; 2564ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->handle = -1; 2574ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 2584ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return cd; 2594ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine} 2604ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 2614ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/* Uninitializes and frees CameraDevice structure. 2624ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine */ 2634ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkinestatic void 2644ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine_camera_device_free(LinuxCameraDevice* lcd) 2654ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine{ 2664ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (lcd != NULL) { 2674ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Closing handle will also disconnect from the driver. */ 2684ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (lcd->handle >= 0) { 2694ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine close(lcd->handle); 2704ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 2714ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (lcd->device_name != NULL) { 2724ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine free(lcd->device_name); 2734ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 2744ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (lcd->framebuffers != NULL) { 2754ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine _free_framebuffers(lcd->framebuffers, lcd->framebuffer_num, 2764ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine lcd->io_type); 2774ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine free(lcd->framebuffers); 2784ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 2794ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine AFREE(lcd); 2804ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } else { 281cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("%s: No descriptor", __FUNCTION__); 2824ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 2834ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine} 2844ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 285e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine/* Resets camera device after capturing. 286e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine * Since new capture request may require different frame dimensions we must 287e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine * reset camera device by reopening its handle. Otherwise attempts to set up new 288e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine * frame properties (different from the previous one) may fail. */ 289e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkinestatic void 290e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine_camera_device_reset(LinuxCameraDevice* cd) 291e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine{ 292e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine struct v4l2_cropcap cropcap; 293e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine struct v4l2_crop crop; 294e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine 295e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine /* Free capturing framebuffers first. */ 296e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine if (cd->framebuffers != NULL) { 297e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine _free_framebuffers(cd->framebuffers, cd->framebuffer_num, cd->io_type); 298e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine free(cd->framebuffers); 299e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine cd->framebuffers = NULL; 300e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine cd->framebuffer_num = 0; 301e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine } 302e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine 303e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine /* Reset device handle. */ 304e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine close(cd->handle); 305e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine cd->handle = open(cd->device_name, O_RDWR | O_NONBLOCK, 0); 306e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine 307e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine if (cd->handle >= 0) { 308e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine /* Select video input, video standard and tune here. */ 309e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 310e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine _xioctl(cd->handle, VIDIOC_CROPCAP, &cropcap); 311e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 312e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine crop.c = cropcap.defrect; /* reset to default */ 313e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine _xioctl (cd->handle, VIDIOC_S_CROP, &crop); 314e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine } 315e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine} 316e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine 3174ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/* Memory maps buffers and shares mapped memory with the device. 3184ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * Return: 3194ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * 0 Framebuffers have been mapped. 3204ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * -1 A critical error has ocurred. 3214ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * 1 Memory mapping is not available. 3224ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine */ 3234ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkinestatic int 3244ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine_camera_device_mmap_framebuffer(LinuxCameraDevice* cd) 3254ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine{ 3264ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine struct v4l2_requestbuffers req; 3274ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine CLEAR(req); 3284ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine req.count = 4; 3294ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 3304ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine req.memory = V4L2_MEMORY_MMAP; 3314ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 3324ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Request memory mapped buffers. Note that device can return less buffers 3334ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * than requested. */ 3344ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if(_xioctl(cd->handle, VIDIOC_REQBUFS, &req)) { 3354ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (EINVAL == errno) { 336cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine D("%s: Device '%s' does not support memory mapping", 3374ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine __FUNCTION__, cd->device_name); 3384ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return 1; 3394ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } else { 3404ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: VIDIOC_REQBUFS has failed: %s", 3414ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine __FUNCTION__, strerror(errno)); 3424ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 3434ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 3444ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 3454ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 3464ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Allocate framebuffer array. */ 3474ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->framebuffers = calloc(req.count, sizeof(CameraFrameBuffer)); 3484ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (cd->framebuffers == NULL) { 3494ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: Not enough memory to allocate framebuffer array", __FUNCTION__); 3504ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 3514ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 3524ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 3534ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Map every framebuffer to the shared memory, and queue it 3544ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * with the device. */ 3554ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine for(cd->framebuffer_num = 0; cd->framebuffer_num < req.count; 3564ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->framebuffer_num++) { 3574ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Map framebuffer. */ 3584ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine struct v4l2_buffer buf; 3594ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine CLEAR(buf); 3604ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 3614ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine buf.memory = V4L2_MEMORY_MMAP; 3624ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine buf.index = cd->framebuffer_num; 3634ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if(_xioctl(cd->handle, VIDIOC_QUERYBUF, &buf) < 0) { 3644ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: VIDIOC_QUERYBUF has failed: %s", 3654ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine __FUNCTION__, strerror(errno)); 3664ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 3674ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 3684ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->framebuffers[cd->framebuffer_num].size = buf.length; 3694ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->framebuffers[cd->framebuffer_num].data = 3704ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, 3714ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->handle, buf.m.offset); 3724ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (MAP_FAILED == cd->framebuffers[cd->framebuffer_num].data) { 3734ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: Memory mapping has failed: %s", 3744ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine __FUNCTION__, strerror(errno)); 3754ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 3764ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 3774ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 3784ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Queue the mapped buffer. */ 3794ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine CLEAR(buf); 3804ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 3814ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine buf.memory = V4L2_MEMORY_MMAP; 3824ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine buf.index = cd->framebuffer_num; 3834ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (_xioctl(cd->handle, VIDIOC_QBUF, &buf) < 0) { 3844ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: VIDIOC_QBUF has failed: %s", __FUNCTION__, strerror(errno)); 3854ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 3864ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 3874ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 3884ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 3894ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->io_type = CAMERA_IO_MEMMAP; 3904ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 3914ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return 0; 3924ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine} 3934ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 3944ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/* Allocates frame buffers and registers them with the device. 3954ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * Return: 3964ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * 0 Framebuffers have been mapped. 3974ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * -1 A critical error has ocurred. 3984ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * 1 Device doesn't support user pointers. 3994ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine */ 4004ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkinestatic int 4014ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine_camera_device_user_framebuffer(LinuxCameraDevice* cd) 4024ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine{ 4034ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine struct v4l2_requestbuffers req; 4044ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine CLEAR (req); 4054ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine req.count = 4; 4064ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 4074ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine req.memory = V4L2_MEMORY_USERPTR; 4084ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 4094ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Request user buffers. Note that device can return less buffers 4104ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * than requested. */ 4114ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if(_xioctl(cd->handle, VIDIOC_REQBUFS, &req)) { 4124ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (EINVAL == errno) { 413cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine D("%s: Device '%s' does not support user pointers", 4144ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine __FUNCTION__, cd->device_name); 4154ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return 1; 4164ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } else { 4174ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: VIDIOC_REQBUFS has failed: %s", 4184ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine __FUNCTION__, strerror(errno)); 4194ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 4204ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 4214ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 4224ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 4234ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Allocate framebuffer array. */ 4244ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->framebuffers = calloc(req.count, sizeof(CameraFrameBuffer)); 4254ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (cd->framebuffers == NULL) { 4264ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: Not enough memory to allocate framebuffer array", __FUNCTION__); 4274ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 4284ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 4294ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 4304ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Allocate buffers, queueing them wit the device at the same time */ 4314ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine for(cd->framebuffer_num = 0; cd->framebuffer_num < req.count; 4324ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->framebuffer_num++) { 4334ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->framebuffers[cd->framebuffer_num].size = 4344ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->actual_pixel_format.sizeimage; 4354ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->framebuffers[cd->framebuffer_num].data = 4364ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine malloc(cd->framebuffers[cd->framebuffer_num].size); 4374ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (cd->framebuffers[cd->framebuffer_num].data == NULL) { 4384ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: Not enough memory to allocate framebuffer", __FUNCTION__); 4394ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 4404ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 4414ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 4424ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Queue the user buffer. */ 4434ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine struct v4l2_buffer buf; 4444ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine CLEAR(buf); 4454ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 4464ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine buf.memory = V4L2_MEMORY_USERPTR; 447cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine buf.m.userptr = (unsigned long)cd->framebuffers[cd->framebuffer_num].data; 4484ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine buf.length = cd->framebuffers[cd->framebuffer_num].size; 4494ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (_xioctl(cd->handle, VIDIOC_QBUF, &buf) < 0) { 4504ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: VIDIOC_QBUF has failed: %s", __FUNCTION__, strerror(errno)); 4514ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 4524ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 4534ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 4544ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 4554ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->io_type = CAMERA_IO_USERPTR; 4564ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 4574ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return 0; 4584ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine} 4594ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 4604ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/* Allocate frame buffer for direct read from the device. 4614ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * Return: 4624ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * 0 Framebuffers have been mapped. 4634ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * -1 A critical error has ocurred. 4644ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * 1 Memory mapping is not available. 4654ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine */ 4664ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkinestatic int 4674ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine_camera_device_direct_framebuffer(LinuxCameraDevice* cd) 4684ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine{ 4694ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Allocate framebuffer array. */ 4704ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->framebuffer_num = 1; 4714ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->framebuffers = malloc(sizeof(CameraFrameBuffer)); 4724ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (cd->framebuffers == NULL) { 4734ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: Not enough memory to allocate framebuffer array", __FUNCTION__); 4744ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 4754ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 4764ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 4774ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->framebuffers[0].size = cd->actual_pixel_format.sizeimage; 4784ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->framebuffers[0].data = malloc(cd->framebuffers[0].size); 4794ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (cd->framebuffers[0].data == NULL) { 4804ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: Not enough memory to allocate framebuffer", __FUNCTION__); 4814ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 4824ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 4834ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 4844ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->io_type = CAMERA_IO_DIRECT; 4854ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 4864ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return 0; 4874ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine} 4884ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 489cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine/* Opens camera device. 490cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * Param: 491cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * cd - Camera device descriptor to open the camera for. 492cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * Return: 493cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * 0 on success, != 0 on failure. 494cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine */ 4954ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkinestatic int 4964ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine_camera_device_open(LinuxCameraDevice* cd) 4974ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine{ 4984ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine struct stat st; 4994ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 5004ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (stat(cd->device_name, &st)) { 5014ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 5024ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 5034ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 5044ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (!S_ISCHR(st.st_mode)) { 505cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("%s: '%s' is not a device", __FUNCTION__, cd->device_name); 5064ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 5074ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 5084ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 5094ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Open handle to the device, and query device capabilities. */ 5104ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->handle = open(cd->device_name, O_RDWR | O_NONBLOCK, 0); 5114ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (cd->handle < 0) { 512cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("%s: Cannot open camera device '%s': %s", 5134ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine __FUNCTION__, cd->device_name, strerror(errno)); 5144ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 5154ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 5164ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (_xioctl(cd->handle, VIDIOC_QUERYCAP, &cd->caps) < 0) { 5174ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (EINVAL == errno) { 5184ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: Camera '%s' is not a V4L2 device", 5194ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine __FUNCTION__, cd->device_name); 5204ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine close(cd->handle); 5214ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->handle = -1; 5224ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 5234ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } else { 524cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("%s: Unable to query capabilities for camera device '%s'", 5254ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine __FUNCTION__, cd->device_name); 5264ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine close(cd->handle); 5274ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->handle = -1; 5284ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 5294ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 5304ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 5314ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 5324ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Make sure that camera supports minimal requirements. */ 5334ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (!(cd->caps.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { 5344ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: Camera '%s' is not a video capture device", 5354ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine __FUNCTION__, cd->device_name); 5364ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine close(cd->handle); 5374ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->handle = -1; 5384ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 5394ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 5404ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 5414ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return 0; 5424ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine} 5434ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 544cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine/* Enumerates frame sizes for the given pixel format. 545cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * Param: 546cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * cd - Opened camera device descriptor. 547cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * fmt - Pixel format to enum frame sizes for. 548cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * sizes - Upon success contains an array of supported frame sizes. The size of 549cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * the array is defined by the value, returned from this routine. The caller 550cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * is responsible for freeing memory allocated for this array. 551cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * Return: 552cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * On success returns number of entries in the 'sizes' array. On failure returns 553cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * a negative value. 554cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine */ 555cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkinestatic int 556cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine_camera_device_enum_format_sizes(LinuxCameraDevice* cd, 557cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine uint32_t fmt, 558cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine CameraFrameDim** sizes) 559cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine{ 560cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int n; 561cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int sizes_num = 0; 562cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int out_num = 0; 563cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine struct v4l2_frmsizeenum size_enum; 564cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine CameraFrameDim* arr; 565cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 566cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Calculate number of supported sizes for the given format. */ 567cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine for (n = 0; ; n++) { 568cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine size_enum.index = n; 569cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine size_enum.pixel_format = fmt; 570cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if(_xioctl(cd->handle, VIDIOC_ENUM_FRAMESIZES, &size_enum)) { 571cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine break; 572cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 573cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (size_enum.type == V4L2_FRMSIZE_TYPE_DISCRETE) { 574cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Size is in the simpe width, height form. */ 575cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine sizes_num++; 576cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } else if (size_enum.type == V4L2_FRMSIZE_TYPE_STEPWISE) { 577cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Sizes are represented as min/max width and height with a step for 578cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * each dimension. Since at the end we want to list each supported 579cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * size in the array (that's the only format supported by the guest 580cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * camera framework), we need to calculate how many array entries 581cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * this will generate. */ 582cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine const uint32_t dif_widths = 583cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine (size_enum.stepwise.max_width - size_enum.stepwise.min_width) / 584cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine size_enum.stepwise.step_width + 1; 585cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine const uint32_t dif_heights = 586cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine (size_enum.stepwise.max_height - size_enum.stepwise.min_height) / 587cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine size_enum.stepwise.step_height + 1; 588cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine sizes_num += dif_widths * dif_heights; 589cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } else if (size_enum.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) { 590cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Special stepwise case, when steps are set to 1. We still need to 591cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * flatten this for the guest, but the array may be too big. 592cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * Fortunately, we don't need to be fancy, so three sizes would be 593cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * sufficient here: min, max, and one in the middle. */ 594cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine sizes_num += 3; 595cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 596cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 597cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 598cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (sizes_num == 0) { 599cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return 0; 600cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 601cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 602cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Allocate, and initialize the array of supported entries. */ 603cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine *sizes = (CameraFrameDim*)malloc(sizes_num * sizeof(CameraFrameDim)); 604cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (*sizes == NULL) { 605cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("%s: Memory allocation failure", __FUNCTION__); 606cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return -1; 607cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 608cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine arr = *sizes; 609cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine for (n = 0; out_num < sizes_num; n++) { 610cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine size_enum.index = n; 611cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine size_enum.pixel_format = fmt; 612cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if(_xioctl(cd->handle, VIDIOC_ENUM_FRAMESIZES, &size_enum)) { 613cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Errors are not welcome here anymore. */ 614cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("%s: Unexpected failure while getting pixel dimensions: %s", 615cdd8d78b202e005691467296b9be98816ed4d4a9Vladimir Chtchetkine __FUNCTION__, strerror(errno)); 616cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine free(arr); 617cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return -1; 618cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 619cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 620cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (size_enum.type == V4L2_FRMSIZE_TYPE_DISCRETE) { 621cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine arr[out_num].width = size_enum.discrete.width; 622cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine arr[out_num].height = size_enum.discrete.height; 623cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine out_num++; 624cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } else if (size_enum.type == V4L2_FRMSIZE_TYPE_STEPWISE) { 625cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine uint32_t w; 626cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine for (w = size_enum.stepwise.min_width; 627cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine w <= size_enum.stepwise.max_width; 628cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine w += size_enum.stepwise.step_width) { 629cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine uint32_t h; 630cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine for (h = size_enum.stepwise.min_height; 631cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine h <= size_enum.stepwise.max_height; 632cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine h += size_enum.stepwise.step_height) { 633cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine arr[out_num].width = w; 634cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine arr[out_num].height = h; 635cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine out_num++; 636cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 637cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 638cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } else if (size_enum.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) { 639cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* min */ 640cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine arr[out_num].width = size_enum.stepwise.min_width; 641cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine arr[out_num].height = size_enum.stepwise.min_height; 642cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine out_num++; 643cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* one in the middle */ 644cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine arr[out_num].width = 645cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine (size_enum.stepwise.min_width + size_enum.stepwise.max_width) / 2; 646cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine arr[out_num].height = 647cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine (size_enum.stepwise.min_height + size_enum.stepwise.max_height) / 2; 648cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine out_num++; 649cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* max */ 650cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine arr[out_num].width = size_enum.stepwise.max_width; 651cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine arr[out_num].height = size_enum.stepwise.max_height; 652cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine out_num++; 653cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 654cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 655cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 656cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return out_num; 657cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine} 658cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 659cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine/* Enumerates pixel formats, supported by the device. 660cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * Note that this routine will enumerate only raw (uncompressed) formats. 661cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * Param: 662cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * cd - Opened camera device descriptor. 663cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * fmts - Upon success contains an array of supported pixel formats. The size of 664cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * the array is defined by the value, returned from this routine. The caller 665cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * is responsible for freeing memory allocated for this array. 666cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * Return: 667cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * On success returns number of entries in the 'fmts' array. On failure returns 668cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * a negative value. 669cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine */ 670cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkinestatic int 671cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine_camera_device_enum_pixel_formats(LinuxCameraDevice* cd, QemuPixelFormat** fmts) 672cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine{ 67379570c3532503840855517494978082a99543a30Vladimir Chtchetkine int n, max_fmt; 674cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int fmt_num = 0; 675cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int out_num = 0; 676cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine struct v4l2_fmtdesc fmt_enum; 677cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine QemuPixelFormat* arr; 678cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 679cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Calculate number of supported formats. */ 68079570c3532503840855517494978082a99543a30Vladimir Chtchetkine for (max_fmt = 0; ; max_fmt++) { 68179570c3532503840855517494978082a99543a30Vladimir Chtchetkine memset(&fmt_enum, 0, sizeof(fmt_enum)); 68279570c3532503840855517494978082a99543a30Vladimir Chtchetkine fmt_enum.index = max_fmt; 683cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine fmt_enum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 684cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if(_xioctl(cd->handle, VIDIOC_ENUM_FMT, &fmt_enum)) { 685cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine break; 686cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 687cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Skip the compressed ones. */ 688cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if ((fmt_enum.flags & V4L2_FMT_FLAG_COMPRESSED) == 0) { 689cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine fmt_num++; 690cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 691cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 692cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (fmt_num == 0) { 693cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return 0; 694cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 695cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 696cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Allocate, and initialize array for enumerated formats. */ 697cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine *fmts = (QemuPixelFormat*)malloc(fmt_num * sizeof(QemuPixelFormat)); 698cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (*fmts == NULL) { 699cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("%s: Memory allocation failure", __FUNCTION__); 700cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return -1; 701cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 702cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine arr = *fmts; 703cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine memset(arr, 0, fmt_num * sizeof(QemuPixelFormat)); 70479570c3532503840855517494978082a99543a30Vladimir Chtchetkine for (n = 0; n < max_fmt && out_num < fmt_num; n++) { 70579570c3532503840855517494978082a99543a30Vladimir Chtchetkine memset(&fmt_enum, 0, sizeof(fmt_enum)); 706cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine fmt_enum.index = n; 707cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine fmt_enum.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 708cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if(_xioctl(cd->handle, VIDIOC_ENUM_FMT, &fmt_enum)) { 709cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int nn; 710cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Errors are not welcome here anymore. */ 711cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("%s: Unexpected failure while getting pixel format: %s", 712cdd8d78b202e005691467296b9be98816ed4d4a9Vladimir Chtchetkine __FUNCTION__, strerror(errno)); 713cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine for (nn = 0; nn < out_num; nn++) { 714cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine _qemu_pixel_format_free(arr + nn); 715cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 716cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine free(arr); 717cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return -1; 718cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 719cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Skip the compressed ones. */ 720cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if ((fmt_enum.flags & V4L2_FMT_FLAG_COMPRESSED) == 0) { 721cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine arr[out_num].format = fmt_enum.pixelformat; 722cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Enumerate frame dimensions supported for this format. */ 723cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine arr[out_num].dim_num = 724cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine _camera_device_enum_format_sizes(cd, fmt_enum.pixelformat, 725cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine &arr[out_num].dims); 726cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (arr[out_num].dim_num > 0) { 727cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine out_num++; 728cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } else if (arr[out_num].dim_num < 0) { 729cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int nn; 730cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("Unable to enumerate supported dimensions for pixel format %d", 731cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine fmt_enum.pixelformat); 732cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine for (nn = 0; nn < out_num; nn++) { 733cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine _qemu_pixel_format_free(arr + nn); 734cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 735cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine free(arr); 736cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return -1; 737cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 738cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 739cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 740cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 741cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return out_num; 742cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine} 743cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 744cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine/* Collects information about an opened camera device. 745cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * The information collected in this routine contains list of pixel formats, 746cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * supported by the device, and list of frame dimensions supported by the camera 747cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * for each pixel format. 748cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * Param: 749cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * cd - Opened camera device descriptor. 750cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * cis - Upon success contains information collected from the camera device. 751cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * Return: 752cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * 0 on success, != 0 on failure. 753cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine */ 754cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkinestatic int 755cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine_camera_device_get_info(LinuxCameraDevice* cd, CameraInfo* cis) 756cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine{ 757cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int f; 758cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int chosen = -1; 759cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine QemuPixelFormat* formats = NULL; 760cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int num_pix_fmts = _camera_device_enum_pixel_formats(cd, &formats); 761cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (num_pix_fmts <= 0) { 76279570c3532503840855517494978082a99543a30Vladimir Chtchetkine return -1; 763cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 764cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 765cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Lets see if camera supports preferred formats */ 766cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine for (f = 0; f < _preferred_format_num; f++) { 767cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine chosen = _get_format_index(_preferred_formats[f], formats, num_pix_fmts); 768cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (chosen >= 0) { 769cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine break; 770cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 771cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 772cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (chosen < 0) { 773cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Camera doesn't support any of the chosen formats. Then it doesn't 774cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * matter which one we choose. Lets choose the first one. */ 775cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine chosen = 0; 776cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 777cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 778cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine cis->device_name = ASTRDUP(cd->device_name); 779cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine cis->inp_channel = cd->input_channel; 780cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine cis->pixel_format = formats[chosen].format; 781cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine cis->frame_sizes_num = formats[chosen].dim_num; 782cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Swap instead of copy. */ 783cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine cis->frame_sizes = formats[chosen].dims; 784cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine formats[chosen].dims = NULL; 785cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine cis->in_use = 0; 786cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 787cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine for (f = 0; f < num_pix_fmts; f++) { 788cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine _qemu_pixel_format_free(formats + f); 789cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 790cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine free(formats); 791cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 792cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return 0; 793cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine} 794cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 7954ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine/******************************************************************************* 7964ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * CameraDevice API 7974ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine ******************************************************************************/ 7984ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 7994ed09fd35085c96ae8edbda87757187f75eeac8dVladimir ChtchetkineCameraDevice* 800cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkinecamera_device_open(const char* name, int inp_channel) 8014ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine{ 8024ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine struct v4l2_cropcap cropcap; 8034ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine struct v4l2_crop crop; 8044ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine LinuxCameraDevice* cd; 8054ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 8064ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Allocate and initialize the descriptor. */ 8074ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd = _camera_device_alloc(); 8084ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->device_name = name != NULL ? ASTRDUP(name) : ASTRDUP("/dev/video0"); 8094ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->input_channel = inp_channel; 8104ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 8114ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Open the device. */ 8124ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (_camera_device_open(cd)) { 8134ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine _camera_device_free(cd); 8144ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return NULL; 8154ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 8164ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 8174ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Select video input, video standard and tune here. */ 8184ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 8194ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine _xioctl(cd->handle, VIDIOC_CROPCAP, &cropcap); 8204ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 8214ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine crop.c = cropcap.defrect; /* reset to default */ 8224ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine _xioctl (cd->handle, VIDIOC_S_CROP, &crop); 8234ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 8244ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return &cd->header; 8254ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine} 8264ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 8274ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkineint 828cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkinecamera_device_start_capturing(CameraDevice* ccd, 829cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine uint32_t pixel_format, 830cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int frame_width, 831cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int frame_height) 8324ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine{ 833cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine struct v4l2_format fmt; 8344ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine LinuxCameraDevice* cd; 835cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine char fmt_str[5]; 836cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int r; 8374ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 8384ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Sanity checks. */ 8394ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (ccd == NULL || ccd->opaque == NULL) { 8404ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: Invalid camera device descriptor", __FUNCTION__); 8414ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 8424ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 8434ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd = (LinuxCameraDevice*)ccd->opaque; 844ce31fbc48a43ea4265be1d20f157e8749b3e11ddVladimir Chtchetkine if (cd->handle < 0) { 845ce31fbc48a43ea4265be1d20f157e8749b3e11ddVladimir Chtchetkine E("%s: Camera device is not opened", __FUNCTION__); 846ce31fbc48a43ea4265be1d20f157e8749b3e11ddVladimir Chtchetkine return -1; 847ce31fbc48a43ea4265be1d20f157e8749b3e11ddVladimir Chtchetkine } 8484ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 849cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Try to set pixel format with the given dimensions. */ 850cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine CLEAR(fmt); 851cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 852cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine fmt.fmt.pix.width = frame_width; 853cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine fmt.fmt.pix.height = frame_height; 854cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine fmt.fmt.pix.pixelformat = pixel_format; 855cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (_xioctl(cd->handle, VIDIOC_S_FMT, &fmt) < 0) { 856cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine memcpy(fmt_str, &pixel_format, 4); 857cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine fmt_str[4] = '\0'; 858cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("%s: Camera '%s' does not support pixel format '%s' with dimensions %dx%d", 859cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine __FUNCTION__, cd->device_name, fmt_str, frame_width, frame_height); 860e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine _camera_device_reset(cd); 861cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return -1; 862cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 863cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* VIDIOC_S_FMT may has changed some properties of the structure. Make sure 864cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine * that dimensions didn't change. */ 865cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (fmt.fmt.pix.width != frame_width || fmt.fmt.pix.height != frame_height) { 866cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine memcpy(fmt_str, &pixel_format, 4); 867cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine fmt_str[4] = '\0'; 868cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("%s: Dimensions %dx%d are wrong for pixel format '%s'", 869cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine __FUNCTION__, frame_width, frame_height, fmt_str); 870e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine _camera_device_reset(cd); 871cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return -1; 872cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 873cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine memcpy(&cd->actual_pixel_format, &fmt.fmt.pix, sizeof(struct v4l2_pix_format)); 874cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 8754ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* 8764ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * Lets initialize frame buffers, and see what kind of I/O we're going to 8774ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * use to retrieve frames. 8784ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine */ 8794ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 8804ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* First, lets see if we can do mapped I/O (as most performant one). */ 881cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine r = _camera_device_mmap_framebuffer(cd); 8824ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (r < 0) { 8834ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Some critical error has ocurred. Bail out. */ 884e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine _camera_device_reset(cd); 8854ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 8864ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } else if (r > 0) { 8874ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Device doesn't support memory mapping. Retrieve to the next performant 8884ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine * one: preallocated user buffers. */ 8894ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine r = _camera_device_user_framebuffer(cd); 8904ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (r < 0) { 8914ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Some critical error has ocurred. Bail out. */ 892e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine _camera_device_reset(cd); 8934ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 8944ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } else if (r > 0) { 8954ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* The only thing left for us is direct reading from the device. */ 8964ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (!(cd->caps.capabilities & V4L2_CAP_READWRITE)) { 897cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("%s: Don't know how to access frames on device '%s'", 8984ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine __FUNCTION__, cd->device_name); 899e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine _camera_device_reset(cd); 9004ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 9014ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 9024ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine r = _camera_device_direct_framebuffer(cd); 9034ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (r != 0) { 9044ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Any error at this point is a critical one. */ 905e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine _camera_device_reset(cd); 9064ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 9074ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 9084ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 9094ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 9104ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 9114ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Start capturing from the device. */ 9124ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (cd->io_type != CAMERA_IO_DIRECT) { 9134ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine enum v4l2_buf_type type; 9144ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 9154ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (_xioctl (cd->handle, VIDIOC_STREAMON, &type) < 0) { 916cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("%s: VIDIOC_STREAMON on camera '%s' has failed: %s", 917cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine __FUNCTION__, cd->device_name, strerror(errno)); 918e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine _camera_device_reset(cd); 9194ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 9204ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 9214ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 9224ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return 0; 9234ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine} 9244ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 9254ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkineint 9264ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkinecamera_device_stop_capturing(CameraDevice* ccd) 9274ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine{ 9284ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine enum v4l2_buf_type type; 9294ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine LinuxCameraDevice* cd; 9304ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 9314ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Sanity checks. */ 9324ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (ccd == NULL || ccd->opaque == NULL) { 9334ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: Invalid camera device descriptor", __FUNCTION__); 9344ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 9354ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 9364ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd = (LinuxCameraDevice*)ccd->opaque; 937ce31fbc48a43ea4265be1d20f157e8749b3e11ddVladimir Chtchetkine if (cd->handle < 0) { 938ce31fbc48a43ea4265be1d20f157e8749b3e11ddVladimir Chtchetkine E("%s: Camera device is not opened", __FUNCTION__); 939ce31fbc48a43ea4265be1d20f157e8749b3e11ddVladimir Chtchetkine return -1; 940ce31fbc48a43ea4265be1d20f157e8749b3e11ddVladimir Chtchetkine } 9414ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 9424ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine switch (cd->io_type) { 9434ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine case CAMERA_IO_DIRECT: 9444ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Nothing to do. */ 9454ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine break; 9464ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 9474ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine case CAMERA_IO_MEMMAP: 9484ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine case CAMERA_IO_USERPTR: 9494ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 9504ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (_xioctl(cd->handle, VIDIOC_STREAMOFF, &type) < 0) { 951cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("%s: VIDIOC_STREAMOFF on camera '%s' has failed: %s", 952cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine __FUNCTION__, cd->device_name, strerror(errno)); 9534ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 9544ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 9554ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine break; 9564ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine default: 9574ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: Unknown I/O method: %d", __FUNCTION__, cd->io_type); 9584ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 9594ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 9604ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 961ce31fbc48a43ea4265be1d20f157e8749b3e11ddVladimir Chtchetkine /* Reopen the device to reset its internal state. It seems that if we don't 962ce31fbc48a43ea4265be1d20f157e8749b3e11ddVladimir Chtchetkine * do that, an attempt to reinit the device with different frame dimensions 963ce31fbc48a43ea4265be1d20f157e8749b3e11ddVladimir Chtchetkine * would fail. */ 964e3b840cfa695c2f0b26625cf01149b9cc9079ce9Vladimir Chtchetkine _camera_device_reset(cd); 965ce31fbc48a43ea4265be1d20f157e8749b3e11ddVladimir Chtchetkine 9664ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return 0; 9674ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine} 9684ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 9694ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkineint 970cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkinecamera_device_read_frame(CameraDevice* ccd, 971cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine ClientFrameBuffer* framebuffers, 97237fb84f8b26e3061c1ccb404bf4c962eed5e6057Vladimir Chtchetkine int fbs_num, 97337fb84f8b26e3061c1ccb404bf4c962eed5e6057Vladimir Chtchetkine float r_scale, 97437fb84f8b26e3061c1ccb404bf4c962eed5e6057Vladimir Chtchetkine float g_scale, 97537fb84f8b26e3061c1ccb404bf4c962eed5e6057Vladimir Chtchetkine float b_scale, 97637fb84f8b26e3061c1ccb404bf4c962eed5e6057Vladimir Chtchetkine float exp_comp) 9774ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine{ 9784ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine LinuxCameraDevice* cd; 9794ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 9804ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Sanity checks. */ 9814ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (ccd == NULL || ccd->opaque == NULL) { 9824ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: Invalid camera device descriptor", __FUNCTION__); 9834ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 9844ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 9854ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd = (LinuxCameraDevice*)ccd->opaque; 986ce31fbc48a43ea4265be1d20f157e8749b3e11ddVladimir Chtchetkine if (cd->handle < 0) { 987ce31fbc48a43ea4265be1d20f157e8749b3e11ddVladimir Chtchetkine E("%s: Camera device is not opened", __FUNCTION__); 988ce31fbc48a43ea4265be1d20f157e8749b3e11ddVladimir Chtchetkine return -1; 989ce31fbc48a43ea4265be1d20f157e8749b3e11ddVladimir Chtchetkine } 9904ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 9914ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (cd->io_type == CAMERA_IO_DIRECT) { 9924ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Read directly from the device. */ 9934ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine size_t total_read_bytes = 0; 994cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* There is one framebuffer allocated for direct read. */ 995cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine void* buff = cd->framebuffers[0].data; 9964ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine do { 9974ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine int read_bytes = 9984ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine read(cd->handle, buff + total_read_bytes, 9994ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd->actual_pixel_format.sizeimage - total_read_bytes); 10004ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (read_bytes < 0) { 10014ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine switch (errno) { 10024ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine case EIO: 10034ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine case EAGAIN: 10044ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine continue; 10054ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine default: 1006cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("%s: Unable to read from the camera device '%s': %s", 1007cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine __FUNCTION__, cd->device_name, strerror(errno)); 10084ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine return -1; 10094ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 10104ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 10114ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine total_read_bytes += read_bytes; 10124ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } while (total_read_bytes < cd->actual_pixel_format.sizeimage); 1013cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Convert the read frame into the caller's framebuffers. */ 1014cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return convert_frame(buff, cd->actual_pixel_format.pixelformat, 1015cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine cd->actual_pixel_format.sizeimage, 1016cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine cd->actual_pixel_format.width, 1017cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine cd->actual_pixel_format.height, 101837fb84f8b26e3061c1ccb404bf4c962eed5e6057Vladimir Chtchetkine framebuffers, fbs_num, 101937fb84f8b26e3061c1ccb404bf4c962eed5e6057Vladimir Chtchetkine r_scale, g_scale, b_scale, exp_comp); 10204ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } else { 10214ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Dequeue next buffer from the device. */ 10224ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine struct v4l2_buffer buf; 1023cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int res; 10244ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine CLEAR(buf); 10254ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 10264ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine buf.memory = cd->io_type == CAMERA_IO_MEMMAP ? V4L2_MEMORY_MMAP : 10274ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine V4L2_MEMORY_USERPTR; 1028cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine for (;;) { 1029cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine const int res = _xioctl(cd->handle, VIDIOC_DQBUF, &buf); 1030cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (res >= 0) { 1031cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine break; 1032cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } else if (errno == EAGAIN) { 1033cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return 1; // Tells the caller to repeat. 1034cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } else if (errno != EINTR && errno != EIO) { 1035cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine E("%s: VIDIOC_DQBUF on camera '%s' has failed: %s", 1036cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine __FUNCTION__, cd->device_name, strerror(errno)); 1037cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return -1; 10384ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 10394ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 1040cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 1041cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Convert frame to the receiving buffers. */ 1042cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine res = convert_frame(cd->framebuffers[buf.index].data, 1043cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine cd->actual_pixel_format.pixelformat, 1044cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine cd->actual_pixel_format.sizeimage, 1045cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine cd->actual_pixel_format.width, 1046cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine cd->actual_pixel_format.height, 104737fb84f8b26e3061c1ccb404bf4c962eed5e6057Vladimir Chtchetkine framebuffers, fbs_num, 104837fb84f8b26e3061c1ccb404bf4c962eed5e6057Vladimir Chtchetkine r_scale, g_scale, b_scale, exp_comp); 1049cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 1050cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine /* Requeue the buffer back to the device. */ 10514ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (_xioctl(cd->handle, VIDIOC_QBUF, &buf) < 0) { 1052cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine W("%s: VIDIOC_QBUF on camera '%s' has failed: %s", 1053cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine __FUNCTION__, cd->device_name, strerror(errno)); 10544ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 1055cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 1056cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return res; 10574ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 10584ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine} 10594ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 10604ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkinevoid 10614ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkinecamera_device_close(CameraDevice* ccd) 10624ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine{ 10634ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine LinuxCameraDevice* cd; 10644ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine 10654ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine /* Sanity checks. */ 10664ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine if (ccd != NULL && ccd->opaque != NULL) { 10674ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine cd = (LinuxCameraDevice*)ccd->opaque; 10684ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine _camera_device_free(cd); 10694ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } else { 10704ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine E("%s: Invalid camera device descriptor", __FUNCTION__); 10714ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine } 10724ed09fd35085c96ae8edbda87757187f75eeac8dVladimir Chtchetkine} 1073cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 1074cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkineint 1075cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkineenumerate_camera_devices(CameraInfo* cis, int max) 1076cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine{ 1077cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine char dev_name[24]; 1078cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int found = 0; 1079cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine int n; 1080cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 1081cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine for (n = 0; n < max; n++) { 1082cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine CameraDevice* cd; 1083cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 1084cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine sprintf(dev_name, "/dev/video%d", n); 1085cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine cd = camera_device_open(dev_name, 0); 1086cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (cd != NULL) { 1087cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine LinuxCameraDevice* lcd = (LinuxCameraDevice*)cd->opaque; 1088cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine if (!_camera_device_get_info(lcd, cis + found)) { 1089b8dcaffaf7dcb0c795d2776abf3bb75196f8527cVladimir Chtchetkine char user_name[24]; 1090b8dcaffaf7dcb0c795d2776abf3bb75196f8527cVladimir Chtchetkine sprintf(user_name, "webcam%d", found); 1091b8dcaffaf7dcb0c795d2776abf3bb75196f8527cVladimir Chtchetkine cis[found].display_name = ASTRDUP(user_name); 1092cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine cis[found].in_use = 0; 1093cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine found++; 1094cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 1095cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine camera_device_close(cd); 1096cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } else { 1097cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine break; 1098cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 1099cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine } 1100cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine 1101cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine return found; 1102cf1c2c70dd99e7d78816ba9a558f9ed8c016862bVladimir Chtchetkine} 1103