blob: f9efc7ba8d313a967d2210758cc9bec42f592a01 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
mallinath@webrtc.org12984f02012-02-16 18:18:21 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +020011#include "webrtc/modules/video_capture/linux/video_capture_linux.h"
12
pbos@webrtc.orga9b74ad2013-07-12 10:03:52 +000013#include <errno.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000014#include <fcntl.h>
15#include <linux/videodev2.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000016#include <stdio.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000017#include <string.h>
pbos@webrtc.orga9b74ad2013-07-12 10:03:52 +000018#include <sys/ioctl.h>
19#include <sys/mman.h>
20#include <sys/stat.h>
21#include <unistd.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000022
23#include <iostream>
24#include <new>
25
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +020026#include "webrtc/media/base/videocommon.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020027#include "webrtc/rtc_base/refcount.h"
28#include "webrtc/rtc_base/scoped_ref_ptr.h"
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +020029#include "webrtc/rtc_base/logging.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000030
Peter Boström1d194412016-03-21 16:44:31 +010031namespace webrtc {
32namespace videocapturemodule {
33rtc::scoped_refptr<VideoCaptureModule> VideoCaptureImpl::Create(
Peter Boström1d194412016-03-21 16:44:31 +010034 const char* deviceUniqueId) {
35 rtc::scoped_refptr<VideoCaptureModuleV4L2> implementation(
nisseb29b9c82016-12-12 00:22:56 -080036 new rtc::RefCountedObject<VideoCaptureModuleV4L2>());
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000037
Peter Boström1d194412016-03-21 16:44:31 +010038 if (implementation->Init(deviceUniqueId) != 0)
39 return nullptr;
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000040
41 return implementation;
42}
43
nisseb29b9c82016-12-12 00:22:56 -080044VideoCaptureModuleV4L2::VideoCaptureModuleV4L2()
45 : VideoCaptureImpl(),
tommi@webrtc.org875c97e2015-02-04 11:11:53 +000046 _deviceId(-1),
mallinath@webrtc.org0d757b82012-02-21 16:47:55 +000047 _deviceFd(-1),
48 _buffersAllocatedByDevice(-1),
tommi@webrtc.org875c97e2015-02-04 11:11:53 +000049 _currentWidth(-1),
mallinath@webrtc.org0d757b82012-02-21 16:47:55 +000050 _currentHeight(-1),
tommi@webrtc.org875c97e2015-02-04 11:11:53 +000051 _currentFrameRate(-1),
mallinath@webrtc.org0d757b82012-02-21 16:47:55 +000052 _captureStarted(false),
nisseeb44b392017-04-28 07:18:05 -070053 _captureVideoType(VideoType::kI420),
54 _pool(NULL) {}
niklase@google.com470e71d2011-07-07 08:21:25 +000055
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000056int32_t VideoCaptureModuleV4L2::Init(const char* deviceUniqueIdUTF8)
niklase@google.com470e71d2011-07-07 08:21:25 +000057{
58 int len = strlen((const char*) deviceUniqueIdUTF8);
leozwang@webrtc.org1745e932012-03-01 16:30:40 +000059 _deviceUniqueId = new (std::nothrow) char[len + 1];
niklase@google.com470e71d2011-07-07 08:21:25 +000060 if (_deviceUniqueId)
61 {
62 memcpy(_deviceUniqueId, deviceUniqueIdUTF8, len + 1);
63 }
64
65 int fd;
66 char device[32];
67 bool found = false;
68
69 /* detect /dev/video [0-63] entries */
70 int n;
71 for (n = 0; n < 64; n++)
72 {
niklase@google.com470e71d2011-07-07 08:21:25 +000073 sprintf(device, "/dev/video%d", n);
mallinath@webrtc.org12984f02012-02-16 18:18:21 +000074 if ((fd = open(device, O_RDONLY)) != -1)
niklase@google.com470e71d2011-07-07 08:21:25 +000075 {
mallinath@webrtc.org12984f02012-02-16 18:18:21 +000076 // query device capabilities
77 struct v4l2_capability cap;
78 if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0)
niklase@google.com470e71d2011-07-07 08:21:25 +000079 {
mallinath@webrtc.org12984f02012-02-16 18:18:21 +000080 if (cap.bus_info[0] != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +000081 {
mallinath@webrtc.org12984f02012-02-16 18:18:21 +000082 if (strncmp((const char*) cap.bus_info,
83 (const char*) deviceUniqueIdUTF8,
84 strlen((const char*) deviceUniqueIdUTF8)) == 0) //match with device id
niklase@google.com470e71d2011-07-07 08:21:25 +000085 {
mallinath@webrtc.org12984f02012-02-16 18:18:21 +000086 close(fd);
87 found = true;
88 break; // fd matches with device unique id supplied
niklase@google.com470e71d2011-07-07 08:21:25 +000089 }
90 }
niklase@google.com470e71d2011-07-07 08:21:25 +000091 }
mallinath@webrtc.org12984f02012-02-16 18:18:21 +000092 close(fd); // close since this is not the matching device
niklase@google.com470e71d2011-07-07 08:21:25 +000093 }
94 }
95 if (!found)
96 {
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +020097 LOG(LS_INFO) << "no matching device found";
niklase@google.com470e71d2011-07-07 08:21:25 +000098 return -1;
99 }
100 _deviceId = n; //store the device id
101 return 0;
102}
103
104VideoCaptureModuleV4L2::~VideoCaptureModuleV4L2()
105{
106 StopCapture();
perkj@webrtc.org8627adc2011-12-05 09:58:55 +0000107 if (_deviceFd != -1)
108 close(_deviceFd);
niklase@google.com470e71d2011-07-07 08:21:25 +0000109}
110
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000111int32_t VideoCaptureModuleV4L2::StartCapture(
mallinath@webrtc.org42033b42012-08-01 06:31:34 +0000112 const VideoCaptureCapability& capability)
niklase@google.com470e71d2011-07-07 08:21:25 +0000113{
114 if (_captureStarted)
115 {
nisseeb44b392017-04-28 07:18:05 -0700116 if (capability.width == _currentWidth &&
117 capability.height == _currentHeight &&
118 _captureVideoType == capability.videoType) {
119 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000120 }
121 else
122 {
123 StopCapture();
124 }
125 }
126
kthelgasonff046c72017-03-31 02:03:55 -0700127 rtc::CritScope cs(&_captureCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000128 //first open /dev/video device
129 char device[20];
130 sprintf(device, "/dev/video%d", (int) _deviceId);
131
132 if ((_deviceFd = open(device, O_RDWR | O_NONBLOCK, 0)) < 0)
133 {
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +0200134 LOG(LS_INFO) << "error in opening " << device << " errono = " << errno;
niklase@google.com470e71d2011-07-07 08:21:25 +0000135 return -1;
136 }
137
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000138 // Supported video formats in preferred order.
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000139 // If the requested resolution is larger than VGA, we prefer MJPEG. Go for
140 // I420 otherwise.
braveyao@webrtc.orgc502df52014-10-13 02:13:00 +0000141 const int nFormats = 5;
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000142 unsigned int fmts[nFormats];
143 if (capability.width > 640 || capability.height > 480) {
144 fmts[0] = V4L2_PIX_FMT_MJPEG;
145 fmts[1] = V4L2_PIX_FMT_YUV420;
146 fmts[2] = V4L2_PIX_FMT_YUYV;
braveyao@webrtc.orgc502df52014-10-13 02:13:00 +0000147 fmts[3] = V4L2_PIX_FMT_UYVY;
148 fmts[4] = V4L2_PIX_FMT_JPEG;
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000149 } else {
150 fmts[0] = V4L2_PIX_FMT_YUV420;
151 fmts[1] = V4L2_PIX_FMT_YUYV;
braveyao@webrtc.orgc502df52014-10-13 02:13:00 +0000152 fmts[2] = V4L2_PIX_FMT_UYVY;
153 fmts[3] = V4L2_PIX_FMT_MJPEG;
154 fmts[4] = V4L2_PIX_FMT_JPEG;
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000155 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000156
braveyao@webrtc.org254d85a2013-02-04 07:53:53 +0000157 // Enumerate image formats.
158 struct v4l2_fmtdesc fmt;
159 int fmtsIdx = nFormats;
160 memset(&fmt, 0, sizeof(fmt));
161 fmt.index = 0;
162 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +0200163 LOG(LS_INFO) << "Video Capture enumerats supported image formats:";
braveyao@webrtc.org254d85a2013-02-04 07:53:53 +0000164 while (ioctl(_deviceFd, VIDIOC_ENUM_FMT, &fmt) == 0) {
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +0200165 LOG(LS_INFO) << " { pixelformat = "
166 << cricket::GetFourccName(fmt.pixelformat)
167 << ", description = '" << fmt.description << "' }";
braveyao@webrtc.org254d85a2013-02-04 07:53:53 +0000168 // Match the preferred order.
169 for (int i = 0; i < nFormats; i++) {
170 if (fmt.pixelformat == fmts[i] && i < fmtsIdx)
171 fmtsIdx = i;
172 }
173 // Keep enumerating.
174 fmt.index++;
175 }
176
177 if (fmtsIdx == nFormats)
178 {
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +0200179 LOG(LS_INFO) << "no supporting video formats found";
braveyao@webrtc.org254d85a2013-02-04 07:53:53 +0000180 return -1;
181 } else {
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +0200182 LOG(LS_INFO) << "We prefer format "
183 << cricket::GetFourccName(fmts[fmtsIdx]);
braveyao@webrtc.org254d85a2013-02-04 07:53:53 +0000184 }
185
niklase@google.com470e71d2011-07-07 08:21:25 +0000186 struct v4l2_format video_fmt;
187 memset(&video_fmt, 0, sizeof(struct v4l2_format));
188 video_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
189 video_fmt.fmt.pix.sizeimage = 0;
190 video_fmt.fmt.pix.width = capability.width;
191 video_fmt.fmt.pix.height = capability.height;
braveyao@webrtc.org254d85a2013-02-04 07:53:53 +0000192 video_fmt.fmt.pix.pixelformat = fmts[fmtsIdx];
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000193
niklase@google.com470e71d2011-07-07 08:21:25 +0000194 if (video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
nisseeb44b392017-04-28 07:18:05 -0700195 _captureVideoType = VideoType::kYUY2;
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000196 else if (video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
nisseeb44b392017-04-28 07:18:05 -0700197 _captureVideoType = VideoType::kI420;
braveyao@webrtc.orgc502df52014-10-13 02:13:00 +0000198 else if (video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY)
nisseeb44b392017-04-28 07:18:05 -0700199 _captureVideoType = VideoType::kUYVY;
braveyao@webrtc.org6b6eb442013-02-28 10:08:02 +0000200 else if (video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG ||
201 video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG)
nisseeb44b392017-04-28 07:18:05 -0700202 _captureVideoType = VideoType::kMJPEG;
niklase@google.com470e71d2011-07-07 08:21:25 +0000203
204 //set format and frame size now
205 if (ioctl(_deviceFd, VIDIOC_S_FMT, &video_fmt) < 0)
206 {
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +0200207 LOG(LS_INFO) << "error in VIDIOC_S_FMT, errno = " << errno;
niklase@google.com470e71d2011-07-07 08:21:25 +0000208 return -1;
209 }
210
211 // initialize current width and height
212 _currentWidth = video_fmt.fmt.pix.width;
213 _currentHeight = video_fmt.fmt.pix.height;
mallinath@webrtc.org42033b42012-08-01 06:31:34 +0000214
215 // Trying to set frame rate, before check driver capability.
216 bool driver_framerate_support = true;
217 struct v4l2_streamparm streamparms;
218 memset(&streamparms, 0, sizeof(streamparms));
219 streamparms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
220 if (ioctl(_deviceFd, VIDIOC_G_PARM, &streamparms) < 0) {
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +0200221 LOG(LS_INFO) << "error in VIDIOC_G_PARM errno = " << errno;
mallinath@webrtc.org42033b42012-08-01 06:31:34 +0000222 driver_framerate_support = false;
223 // continue
224 } else {
225 // check the capability flag is set to V4L2_CAP_TIMEPERFRAME.
Weiyong Yaoe796f962016-02-05 17:06:17 -0800226 if (streamparms.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
mallinath@webrtc.org42033b42012-08-01 06:31:34 +0000227 // driver supports the feature. Set required framerate.
228 memset(&streamparms, 0, sizeof(streamparms));
229 streamparms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
230 streamparms.parm.capture.timeperframe.numerator = 1;
231 streamparms.parm.capture.timeperframe.denominator = capability.maxFPS;
232 if (ioctl(_deviceFd, VIDIOC_S_PARM, &streamparms) < 0) {
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +0200233 LOG(LS_INFO) << "Failed to set the framerate. errno=" << errno;
mallinath@webrtc.org42033b42012-08-01 06:31:34 +0000234 driver_framerate_support = false;
235 } else {
236 _currentFrameRate = capability.maxFPS;
237 }
238 }
239 }
240 // If driver doesn't support framerate control, need to hardcode.
241 // Hardcoding the value based on the frame size.
242 if (!driver_framerate_support) {
nisseeb44b392017-04-28 07:18:05 -0700243 if (_currentWidth >= 800 && _captureVideoType != VideoType::kMJPEG) {
mallinath@webrtc.org42033b42012-08-01 06:31:34 +0000244 _currentFrameRate = 15;
245 } else {
246 _currentFrameRate = 30;
247 }
248 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000249
250 if (!AllocateVideoBuffers())
251 {
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +0200252 LOG(LS_INFO) << "failed to allocate video capture buffers";
niklase@google.com470e71d2011-07-07 08:21:25 +0000253 return -1;
254 }
255
256 //start capture thread;
257 if (!_captureThread)
258 {
Peter Boström8c38e8b2015-11-26 17:45:47 +0100259 _captureThread.reset(new rtc::PlatformThread(
260 VideoCaptureModuleV4L2::CaptureThread, this, "CaptureThread"));
pbos@webrtc.org86639732015-03-13 00:06:21 +0000261 _captureThread->Start();
Peter Boström8c38e8b2015-11-26 17:45:47 +0100262 _captureThread->SetPriority(rtc::kHighPriority);
niklase@google.com470e71d2011-07-07 08:21:25 +0000263 }
264
265 // Needed to start UVC camera - from the uvcview application
266 enum v4l2_buf_type type;
267 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
268 if (ioctl(_deviceFd, VIDIOC_STREAMON, &type) == -1)
269 {
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +0200270 LOG(LS_INFO) << "Failed to turn on stream";
niklase@google.com470e71d2011-07-07 08:21:25 +0000271 return -1;
272 }
273
274 _captureStarted = true;
275 return 0;
276}
277
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000278int32_t VideoCaptureModuleV4L2::StopCapture()
niklase@google.com470e71d2011-07-07 08:21:25 +0000279{
perkj@webrtc.orgc2fde802012-08-08 14:01:09 +0000280 if (_captureThread) {
281 // Make sure the capture thread stop stop using the critsect.
tommi@webrtc.org361981f2015-03-19 14:44:18 +0000282 _captureThread->Stop();
283 _captureThread.reset();
niklase@google.com470e71d2011-07-07 08:21:25 +0000284 }
285
kthelgasonff046c72017-03-31 02:03:55 -0700286 rtc::CritScope cs(&_captureCritSect);
perkj@webrtc.orgc2fde802012-08-08 14:01:09 +0000287 if (_captureStarted)
288 {
289 _captureStarted = false;
perkj@webrtc.orgc2fde802012-08-08 14:01:09 +0000290
291 DeAllocateVideoBuffers();
292 close(_deviceFd);
293 _deviceFd = -1;
294 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000295
296 return 0;
297}
298
299//critical section protected by the caller
300
301bool VideoCaptureModuleV4L2::AllocateVideoBuffers()
302{
303 struct v4l2_requestbuffers rbuffer;
304 memset(&rbuffer, 0, sizeof(v4l2_requestbuffers));
305
306 rbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
307 rbuffer.memory = V4L2_MEMORY_MMAP;
308 rbuffer.count = kNoOfV4L2Bufffers;
309
310 if (ioctl(_deviceFd, VIDIOC_REQBUFS, &rbuffer) < 0)
311 {
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +0200312 LOG(LS_INFO) << "Could not get buffers from device. errno = " << errno;
niklase@google.com470e71d2011-07-07 08:21:25 +0000313 return false;
314 }
315
316 if (rbuffer.count > kNoOfV4L2Bufffers)
317 rbuffer.count = kNoOfV4L2Bufffers;
318
319 _buffersAllocatedByDevice = rbuffer.count;
320
321 //Map the buffers
mallinath@webrtc.org0d757b82012-02-21 16:47:55 +0000322 _pool = new Buffer[rbuffer.count];
niklase@google.com470e71d2011-07-07 08:21:25 +0000323
324 for (unsigned int i = 0; i < rbuffer.count; i++)
325 {
326 struct v4l2_buffer buffer;
327 memset(&buffer, 0, sizeof(v4l2_buffer));
328 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
329 buffer.memory = V4L2_MEMORY_MMAP;
330 buffer.index = i;
331
332 if (ioctl(_deviceFd, VIDIOC_QUERYBUF, &buffer) < 0)
333 {
334 return false;
335 }
336
mallinath@webrtc.org0d757b82012-02-21 16:47:55 +0000337 _pool[i].start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED,
338 _deviceFd, buffer.m.offset);
niklase@google.com470e71d2011-07-07 08:21:25 +0000339
mallinath@webrtc.org0d757b82012-02-21 16:47:55 +0000340 if (MAP_FAILED == _pool[i].start)
niklase@google.com470e71d2011-07-07 08:21:25 +0000341 {
mallinath@google.com16f1dfc2011-08-11 18:22:17 +0000342 for (unsigned int j = 0; j < i; j++)
mallinath@webrtc.org0d757b82012-02-21 16:47:55 +0000343 munmap(_pool[j].start, _pool[j].length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000344 return false;
345 }
346
mallinath@webrtc.org0d757b82012-02-21 16:47:55 +0000347 _pool[i].length = buffer.length;
niklase@google.com470e71d2011-07-07 08:21:25 +0000348
349 if (ioctl(_deviceFd, VIDIOC_QBUF, &buffer) < 0)
350 {
351 return false;
352 }
353 }
354 return true;
355}
356
357bool VideoCaptureModuleV4L2::DeAllocateVideoBuffers()
358{
359 // unmap buffers
360 for (int i = 0; i < _buffersAllocatedByDevice; i++)
mallinath@webrtc.org0d757b82012-02-21 16:47:55 +0000361 munmap(_pool[i].start, _pool[i].length);
niklase@google.com470e71d2011-07-07 08:21:25 +0000362
mallinath@webrtc.org0d757b82012-02-21 16:47:55 +0000363 delete[] _pool;
niklase@google.com470e71d2011-07-07 08:21:25 +0000364
365 // turn off stream
366 enum v4l2_buf_type type;
367 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
368 if (ioctl(_deviceFd, VIDIOC_STREAMOFF, &type) < 0)
369 {
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +0200370 LOG(LS_INFO) << "VIDIOC_STREAMOFF error. errno: " << errno;
niklase@google.com470e71d2011-07-07 08:21:25 +0000371 }
372
373 return true;
374}
375
376bool VideoCaptureModuleV4L2::CaptureStarted()
377{
378 return _captureStarted;
379}
380
381bool VideoCaptureModuleV4L2::CaptureThread(void* obj)
382{
383 return static_cast<VideoCaptureModuleV4L2*> (obj)->CaptureProcess();
384}
385bool VideoCaptureModuleV4L2::CaptureProcess()
386{
387 int retVal = 0;
388 fd_set rSet;
389 struct timeval timeout;
390
kthelgasonff046c72017-03-31 02:03:55 -0700391 rtc::CritScope cs(&_captureCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +0000392
393 FD_ZERO(&rSet);
394 FD_SET(_deviceFd, &rSet);
395 timeout.tv_sec = 1;
396 timeout.tv_usec = 0;
397
398 retVal = select(_deviceFd + 1, &rSet, NULL, NULL, &timeout);
399 if (retVal < 0 && errno != EINTR) // continue if interrupted
400 {
401 // select failed
niklase@google.com470e71d2011-07-07 08:21:25 +0000402 return false;
403 }
404 else if (retVal == 0)
405 {
406 // select timed out
niklase@google.com470e71d2011-07-07 08:21:25 +0000407 return true;
408 }
409 else if (!FD_ISSET(_deviceFd, &rSet))
410 {
411 // not event on camera handle
niklase@google.com470e71d2011-07-07 08:21:25 +0000412 return true;
413 }
414
415 if (_captureStarted)
416 {
417 struct v4l2_buffer buf;
418 memset(&buf, 0, sizeof(struct v4l2_buffer));
419 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
420 buf.memory = V4L2_MEMORY_MMAP;
421 // dequeue a buffer - repeat until dequeued properly!
422 while (ioctl(_deviceFd, VIDIOC_DQBUF, &buf) < 0)
423 {
424 if (errno != EINTR)
425 {
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +0200426 LOG(LS_INFO) << "could not sync on a buffer on device "
427 << strerror(errno);
niklase@google.com470e71d2011-07-07 08:21:25 +0000428 return true;
429 }
430 }
431 VideoCaptureCapability frameInfo;
432 frameInfo.width = _currentWidth;
433 frameInfo.height = _currentHeight;
nisseeb44b392017-04-28 07:18:05 -0700434 frameInfo.videoType = _captureVideoType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000435
436 // convert to to I420 if needed
mallinath@webrtc.org0d757b82012-02-21 16:47:55 +0000437 IncomingFrame((unsigned char*) _pool[buf.index].start,
niklase@google.com470e71d2011-07-07 08:21:25 +0000438 buf.bytesused, frameInfo);
439 // enqueue the buffer again
440 if (ioctl(_deviceFd, VIDIOC_QBUF, &buf) == -1)
441 {
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +0200442 LOG(LS_INFO) << "Failed to enqueue capture buffer";
niklase@google.com470e71d2011-07-07 08:21:25 +0000443 }
444 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000445 usleep(0);
446 return true;
447}
448
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000449int32_t VideoCaptureModuleV4L2::CaptureSettings(VideoCaptureCapability& settings)
niklase@google.com470e71d2011-07-07 08:21:25 +0000450{
451 settings.width = _currentWidth;
452 settings.height = _currentHeight;
453 settings.maxFPS = _currentFrameRate;
nisseeb44b392017-04-28 07:18:05 -0700454 settings.videoType = _captureVideoType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000455
456 return 0;
457}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000458} // namespace videocapturemodule
459} // namespace webrtc