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