1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1187c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include <errno.h> 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <fcntl.h> 13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <linux/videodev2.h> 14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <stdio.h> 15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <string.h> 1687c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include <sys/ioctl.h> 1787c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include <sys/mman.h> 1887c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include <sys/stat.h> 1987c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include <unistd.h> 20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <iostream> 22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <new> 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2487c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/modules/video_capture/linux/video_capture_linux.h" 2587c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 2687c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/system_wrappers/interface/ref_count.h" 2787c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/system_wrappers/interface/thread_wrapper.h" 2887c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/system_wrappers/interface/trace.h" 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace videocapturemodule 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 34f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgVideoCaptureModule* VideoCaptureImpl::Create(const int32_t id, 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const char* deviceUniqueId) 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RefCountImpl<videocapturemodule::VideoCaptureModuleV4L2>* implementation = 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org new RefCountImpl<videocapturemodule::VideoCaptureModuleV4L2>(id); 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!implementation || implementation->Init(deviceUniqueId) != 0) 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete implementation; 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org implementation = NULL; 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return implementation; 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 49f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgVideoCaptureModuleV4L2::VideoCaptureModuleV4L2(const int32_t id) 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org : VideoCaptureImpl(id), 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureThread(NULL), 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureCritSect(CriticalSectionWrapper::CreateCriticalSection()), 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _deviceId(-1), 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _deviceFd(-1), 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _buffersAllocatedByDevice(-1), 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentWidth(-1), 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentHeight(-1), 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentFrameRate(-1), 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureStarted(false), 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureVideoType(kVideoI420), 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _pool(NULL) 62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 65f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureModuleV4L2::Init(const char* deviceUniqueIdUTF8) 66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int len = strlen((const char*) deviceUniqueIdUTF8); 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _deviceUniqueId = new (std::nothrow) char[len + 1]; 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_deviceUniqueId) 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memcpy(_deviceUniqueId, deviceUniqueIdUTF8, len + 1); 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int fd; 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char device[32]; 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool found = false; 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org /* detect /dev/video [0-63] entries */ 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int n; 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (n = 0; n < 64; n++) 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org sprintf(device, "/dev/video%d", n); 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((fd = open(device, O_RDONLY)) != -1) 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // query device capabilities 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct v4l2_capability cap; 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0) 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (cap.bus_info[0] != 0) 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (strncmp((const char*) cap.bus_info, 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (const char*) deviceUniqueIdUTF8, 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org strlen((const char*) deviceUniqueIdUTF8)) == 0) //match with device id 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org close(fd); 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org found = true; 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org break; // fd matches with device unique id supplied 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org close(fd); // close since this is not the matching device 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!found) 105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, "no matching device found"); 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _deviceId = n; //store the device id 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVideoCaptureModuleV4L2::~VideoCaptureModuleV4L2() 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StopCapture(); 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_captureCritSect) 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete _captureCritSect; 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_deviceFd != -1) 121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org close(_deviceFd); 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 124f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureModuleV4L2::StartCapture( 125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const VideoCaptureCapability& capability) 126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_captureStarted) 128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (capability.width == _currentWidth && 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org capability.height == _currentHeight && 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureVideoType == capability.rawType) 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org StopCapture(); 138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_captureCritSect); 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //first open /dev/video device 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org char device[20]; 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org sprintf(device, "/dev/video%d", (int) _deviceId); 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((_deviceFd = open(device, O_RDWR | O_NONBLOCK, 0)) < 0) 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "error in opening %s errono = %d", device, errno); 150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Supported video formats in preferred order. 154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // If the requested resolution is larger than VGA, we prefer MJPEG. Go for 155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // I420 otherwise. 1560e686e60563fe47299846d2900658fb545667aafbraveyao@webrtc.org const int nFormats = 4; 157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org unsigned int fmts[nFormats]; 158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (capability.width > 640 || capability.height > 480) { 159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org fmts[0] = V4L2_PIX_FMT_MJPEG; 160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org fmts[1] = V4L2_PIX_FMT_YUV420; 161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org fmts[2] = V4L2_PIX_FMT_YUYV; 1620e686e60563fe47299846d2900658fb545667aafbraveyao@webrtc.org fmts[3] = V4L2_PIX_FMT_JPEG; 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org fmts[0] = V4L2_PIX_FMT_YUV420; 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org fmts[1] = V4L2_PIX_FMT_YUYV; 166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org fmts[2] = V4L2_PIX_FMT_MJPEG; 1670e686e60563fe47299846d2900658fb545667aafbraveyao@webrtc.org fmts[3] = V4L2_PIX_FMT_JPEG; 168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 170f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org // Enumerate image formats. 171f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org struct v4l2_fmtdesc fmt; 172f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org int fmtsIdx = nFormats; 173f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org memset(&fmt, 0, sizeof(fmt)); 174f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org fmt.index = 0; 175f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 176f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id, 177f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org "Video Capture enumerats supported image formats:"); 178f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org while (ioctl(_deviceFd, VIDIOC_ENUM_FMT, &fmt) == 0) { 179f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id, 180f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org " { pixelformat = %c%c%c%c, description = '%s' }", 181f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org fmt.pixelformat & 0xFF, (fmt.pixelformat>>8) & 0xFF, 182f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org (fmt.pixelformat>>16) & 0xFF, (fmt.pixelformat>>24) & 0xFF, 183f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org fmt.description); 184f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org // Match the preferred order. 185f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org for (int i = 0; i < nFormats; i++) { 186f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org if (fmt.pixelformat == fmts[i] && i < fmtsIdx) 187f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org fmtsIdx = i; 188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 189f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org // Keep enumerating. 190f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org fmt.index++; 191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 192f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org 193f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org if (fmtsIdx == nFormats) 194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 196f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org "no supporting video formats found"); 197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 198f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org } else { 199f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id, 200f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org "We prefer format %c%c%c%c", 201f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org fmts[fmtsIdx] & 0xFF, (fmts[fmtsIdx]>>8) & 0xFF, 202f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org (fmts[fmtsIdx]>>16) & 0xFF, (fmts[fmtsIdx]>>24) & 0xFF); 203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 205f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org struct v4l2_format video_fmt; 206f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org memset(&video_fmt, 0, sizeof(struct v4l2_format)); 207f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org video_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 208f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org video_fmt.fmt.pix.sizeimage = 0; 209f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org video_fmt.fmt.pix.width = capability.width; 210f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org video_fmt.fmt.pix.height = capability.height; 211f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org video_fmt.fmt.pix.pixelformat = fmts[fmtsIdx]; 212f548bdbe8ad4edf1a23361d92f6ef0dbc23d2a3cbraveyao@webrtc.org 213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) 214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureVideoType = kVideoYUY2; 215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) 216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureVideoType = kVideoI420; 2170e686e60563fe47299846d2900658fb545667aafbraveyao@webrtc.org else if (video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG || 2180e686e60563fe47299846d2900658fb545667aafbraveyao@webrtc.org video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG) 219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureVideoType = kVideoMJPEG; 220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //set format and frame size now 222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ioctl(_deviceFd, VIDIOC_S_FMT, &video_fmt) < 0) 223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "error in VIDIOC_S_FMT, errno = %d", errno); 226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // initialize current width and height 230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentWidth = video_fmt.fmt.pix.width; 231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentHeight = video_fmt.fmt.pix.height; 232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureDelay = 120; 233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Trying to set frame rate, before check driver capability. 235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool driver_framerate_support = true; 236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct v4l2_streamparm streamparms; 237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(&streamparms, 0, sizeof(streamparms)); 238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org streamparms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ioctl(_deviceFd, VIDIOC_G_PARM, &streamparms) < 0) { 240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "error in VIDIOC_G_PARM errno = %d", errno); 242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org driver_framerate_support = false; 243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // continue 244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // check the capability flag is set to V4L2_CAP_TIMEPERFRAME. 246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (streamparms.parm.capture.capability == V4L2_CAP_TIMEPERFRAME) { 247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // driver supports the feature. Set required framerate. 248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(&streamparms, 0, sizeof(streamparms)); 249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org streamparms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org streamparms.parm.capture.timeperframe.numerator = 1; 251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org streamparms.parm.capture.timeperframe.denominator = capability.maxFPS; 252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ioctl(_deviceFd, VIDIOC_S_PARM, &streamparms) < 0) { 253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to set the framerate. errno=%d", errno); 255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org driver_framerate_support = false; 256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentFrameRate = capability.maxFPS; 258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // If driver doesn't support framerate control, need to hardcode. 262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Hardcoding the value based on the frame size. 263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!driver_framerate_support) { 264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if(_currentWidth >= 800 && _captureVideoType != kVideoMJPEG) { 265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentFrameRate = 15; 266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _currentFrameRate = 30; 268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!AllocateVideoBuffers()) 272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "failed to allocate video capture buffers"); 275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //start capture thread; 279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_captureThread) 280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureThread = ThreadWrapper::CreateThread( 282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VideoCaptureModuleV4L2::CaptureThread, this, kHighPriority); 283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org unsigned int id; 284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureThread->Start(id); 285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Needed to start UVC camera - from the uvcview application 288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enum v4l2_buf_type type; 289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ioctl(_deviceFd, VIDIOC_STREAMON, &type) == -1) 291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to turn on stream"); 294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureStarted = true; 298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 301f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureModuleV4L2::StopCapture() 302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_captureThread) { 304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Make sure the capture thread stop stop using the critsect. 305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureThread->SetNotAlive(); 306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_captureThread->Stop()) { 307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete _captureThread; 308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureThread = NULL; 309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Couldn't stop the thread, leak instead of crash. 312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1, 313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "%s: could not stop capture thread", __FUNCTION__); 3140f2782fcee5cef8dd302eb841254303e16e5bb07wu@webrtc.org assert(false); 315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(_captureCritSect); 319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_captureStarted) 320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureStarted = false; 322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureThread = NULL; 323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DeAllocateVideoBuffers(); 325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org close(_deviceFd); 326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _deviceFd = -1; 327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org//critical section protected by the caller 333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VideoCaptureModuleV4L2::AllocateVideoBuffers() 335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct v4l2_requestbuffers rbuffer; 337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(&rbuffer, 0, sizeof(v4l2_requestbuffers)); 338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org rbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org rbuffer.memory = V4L2_MEMORY_MMAP; 341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org rbuffer.count = kNoOfV4L2Bufffers; 342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ioctl(_deviceFd, VIDIOC_REQBUFS, &rbuffer) < 0) 344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Could not get buffers from device. errno = %d", errno); 347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (rbuffer.count > kNoOfV4L2Bufffers) 351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org rbuffer.count = kNoOfV4L2Bufffers; 352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _buffersAllocatedByDevice = rbuffer.count; 354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //Map the buffers 356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _pool = new Buffer[rbuffer.count]; 357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (unsigned int i = 0; i < rbuffer.count; i++) 359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct v4l2_buffer buffer; 361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(&buffer, 0, sizeof(v4l2_buffer)); 362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org buffer.memory = V4L2_MEMORY_MMAP; 364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org buffer.index = i; 365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ioctl(_deviceFd, VIDIOC_QUERYBUF, &buffer) < 0) 367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _pool[i].start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, 372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _deviceFd, buffer.m.offset); 373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (MAP_FAILED == _pool[i].start) 375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (unsigned int j = 0; j < i; j++) 377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org munmap(_pool[j].start, _pool[j].length); 378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _pool[i].length = buffer.length; 382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ioctl(_deviceFd, VIDIOC_QBUF, &buffer) < 0) 384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VideoCaptureModuleV4L2::DeAllocateVideoBuffers() 392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // unmap buffers 394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (int i = 0; i < _buffersAllocatedByDevice; i++) 395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org munmap(_pool[i].start, _pool[i].length); 396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org delete[] _pool; 398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // turn off stream 400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org enum v4l2_buf_type type; 401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ioctl(_deviceFd, VIDIOC_STREAMOFF, &type) < 0) 403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "VIDIOC_STREAMOFF error. errno: %d", errno); 406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VideoCaptureModuleV4L2::CaptureStarted() 412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return _captureStarted; 414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VideoCaptureModuleV4L2::CaptureThread(void* obj) 417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return static_cast<VideoCaptureModuleV4L2*> (obj)->CaptureProcess(); 419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VideoCaptureModuleV4L2::CaptureProcess() 421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int retVal = 0; 423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org fd_set rSet; 424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct timeval timeout; 425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureCritSect->Enter(); 427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org FD_ZERO(&rSet); 429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org FD_SET(_deviceFd, &rSet); 430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org timeout.tv_sec = 1; 431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org timeout.tv_usec = 0; 432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org retVal = select(_deviceFd + 1, &rSet, NULL, NULL, &timeout); 434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (retVal < 0 && errno != EINTR) // continue if interrupted 435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // select failed 437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureCritSect->Leave(); 438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return false; 439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (retVal == 0) 441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // select timed out 443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureCritSect->Leave(); 444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else if (!FD_ISSET(_deviceFd, &rSet)) 447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // not event on camera handle 449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureCritSect->Leave(); 450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_captureStarted) 454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org struct v4l2_buffer buf; 456b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memset(&buf, 0, sizeof(struct v4l2_buffer)); 457b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 458b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org buf.memory = V4L2_MEMORY_MMAP; 459b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // dequeue a buffer - repeat until dequeued properly! 460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (ioctl(_deviceFd, VIDIOC_DQBUF, &buf) < 0) 461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 462b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (errno != EINTR) 463b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 464b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 465b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "could not sync on a buffer on device %s", strerror(errno)); 466b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureCritSect->Leave(); 467b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 468b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 469b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 470b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VideoCaptureCapability frameInfo; 471b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frameInfo.width = _currentWidth; 472b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frameInfo.height = _currentHeight; 473b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frameInfo.rawType = _captureVideoType; 474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // convert to to I420 if needed 476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IncomingFrame((unsigned char*) _pool[buf.index].start, 477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org buf.bytesused, frameInfo); 478b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // enqueue the buffer again 479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (ioctl(_deviceFd, VIDIOC_QBUF, &buf) == -1) 480b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 481b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, _id, 482b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to enqueue capture buffer"); 483b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 484b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureCritSect->Leave(); 486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org usleep(0); 487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return true; 488b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 490f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureModuleV4L2::CaptureSettings(VideoCaptureCapability& settings) 491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org settings.width = _currentWidth; 493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org settings.height = _currentHeight; 494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org settings.maxFPS = _currentFrameRate; 495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org settings.rawType=_captureVideoType; 496b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 498b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4993b89e10f31160da35b408fd00cb8f89d2b08862dpbos@webrtc.org} // namespace videocapturemodule 5003b89e10f31160da35b408fd00cb8f89d2b08862dpbos@webrtc.org} // namespace webrtc 501