blob: 5be4272b0b365664eb3c50b885f036d21002c0af [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/video_capture/linux/video_capture_linux.h"
Sam Zackrisson2ed6e4f2017-08-16 13:39:25 +020012
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "media/base/videocommon.h"
Mirko Bonadei72c42502017-11-09 09:33:23 +010027#include "rtc_base/logging.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020028#include "rtc_base/refcount.h"
Niels Möller84255bb2017-10-06 13:43:23 +020029#include "rtc_base/refcountedobject.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020030#include "rtc_base/scoped_ref_ptr.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000031
Peter Boström1d194412016-03-21 16:44:31 +010032namespace webrtc {
33namespace videocapturemodule {
34rtc::scoped_refptr<VideoCaptureModule> VideoCaptureImpl::Create(
Peter Boström1d194412016-03-21 16:44:31 +010035 const char* deviceUniqueId) {
Mirko Bonadei72c42502017-11-09 09:33:23 +010036 rtc::scoped_refptr<VideoCaptureModuleV4L2> implementation(
37 new rtc::RefCountedObject<VideoCaptureModuleV4L2>());
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000038
Mirko Bonadei72c42502017-11-09 09:33:23 +010039 if (implementation->Init(deviceUniqueId) != 0)
40 return nullptr;
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000041
Mirko Bonadei72c42502017-11-09 09:33:23 +010042 return implementation;
perkj@webrtc.org0cc68dc2011-09-12 08:53:36 +000043}
44
nisseb29b9c82016-12-12 00:22:56 -080045VideoCaptureModuleV4L2::VideoCaptureModuleV4L2()
46 : VideoCaptureImpl(),
tommi@webrtc.org875c97e2015-02-04 11:11:53 +000047 _deviceId(-1),
mallinath@webrtc.org0d757b82012-02-21 16:47:55 +000048 _deviceFd(-1),
49 _buffersAllocatedByDevice(-1),
tommi@webrtc.org875c97e2015-02-04 11:11:53 +000050 _currentWidth(-1),
mallinath@webrtc.org0d757b82012-02-21 16:47:55 +000051 _currentHeight(-1),
tommi@webrtc.org875c97e2015-02-04 11:11:53 +000052 _currentFrameRate(-1),
mallinath@webrtc.org0d757b82012-02-21 16:47:55 +000053 _captureStarted(false),
nisseeb44b392017-04-28 07:18:05 -070054 _captureVideoType(VideoType::kI420),
55 _pool(NULL) {}
niklase@google.com470e71d2011-07-07 08:21:25 +000056
Mirko Bonadei72c42502017-11-09 09:33:23 +010057int32_t VideoCaptureModuleV4L2::Init(const char* deviceUniqueIdUTF8) {
58 int len = strlen((const char*)deviceUniqueIdUTF8);
59 _deviceUniqueId = new (std::nothrow) char[len + 1];
60 if (_deviceUniqueId) {
61 memcpy(_deviceUniqueId, deviceUniqueIdUTF8, len + 1);
62 }
niklase@google.com470e71d2011-07-07 08:21:25 +000063
Mirko Bonadei72c42502017-11-09 09:33:23 +010064 int fd;
65 char device[32];
66 bool found = false;
niklase@google.com470e71d2011-07-07 08:21:25 +000067
Mirko Bonadei72c42502017-11-09 09:33:23 +010068 /* detect /dev/video [0-63] entries */
69 int n;
70 for (n = 0; n < 64; n++) {
71 sprintf(device, "/dev/video%d", n);
72 if ((fd = open(device, O_RDONLY)) != -1) {
73 // query device capabilities
74 struct v4l2_capability cap;
75 if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0) {
76 if (cap.bus_info[0] != 0) {
77 if (strncmp((const char*)cap.bus_info,
78 (const char*)deviceUniqueIdUTF8,
79 strlen((const char*)deviceUniqueIdUTF8)) ==
80 0) // match with device id
81 {
82 close(fd);
83 found = true;
84 break; // fd matches with device unique id supplied
85 }
niklase@google.com470e71d2011-07-07 08:21:25 +000086 }
Mirko Bonadei72c42502017-11-09 09:33:23 +010087 }
88 close(fd); // close since this is not the matching device
niklase@google.com470e71d2011-07-07 08:21:25 +000089 }
Mirko Bonadei72c42502017-11-09 09:33:23 +010090 }
91 if (!found) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010092 RTC_LOG(LS_INFO) << "no matching device found";
Mirko Bonadei72c42502017-11-09 09:33:23 +010093 return -1;
94 }
95 _deviceId = n; // store the device id
96 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000097}
98
Mirko Bonadei72c42502017-11-09 09:33:23 +010099VideoCaptureModuleV4L2::~VideoCaptureModuleV4L2() {
100 StopCapture();
101 if (_deviceFd != -1)
102 close(_deviceFd);
niklase@google.com470e71d2011-07-07 08:21:25 +0000103}
104
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000105int32_t VideoCaptureModuleV4L2::StartCapture(
Mirko Bonadei72c42502017-11-09 09:33:23 +0100106 const VideoCaptureCapability& capability) {
107 if (_captureStarted) {
108 if (capability.width == _currentWidth &&
109 capability.height == _currentHeight &&
110 _captureVideoType == capability.videoType) {
111 return 0;
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000112 } else {
Mirko Bonadei72c42502017-11-09 09:33:23 +0100113 StopCapture();
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000114 }
Mirko Bonadei72c42502017-11-09 09:33:23 +0100115 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000116
Mirko Bonadei72c42502017-11-09 09:33:23 +0100117 rtc::CritScope cs(&_captureCritSect);
118 // first open /dev/video device
119 char device[20];
120 sprintf(device, "/dev/video%d", (int)_deviceId);
121
122 if ((_deviceFd = open(device, O_RDWR | O_NONBLOCK, 0)) < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100123 RTC_LOG(LS_INFO) << "error in opening " << device << " errono = " << errno;
Mirko Bonadei72c42502017-11-09 09:33:23 +0100124 return -1;
125 }
126
127 // Supported video formats in preferred order.
128 // If the requested resolution is larger than VGA, we prefer MJPEG. Go for
129 // I420 otherwise.
130 const int nFormats = 5;
131 unsigned int fmts[nFormats];
132 if (capability.width > 640 || capability.height > 480) {
133 fmts[0] = V4L2_PIX_FMT_MJPEG;
134 fmts[1] = V4L2_PIX_FMT_YUV420;
135 fmts[2] = V4L2_PIX_FMT_YUYV;
136 fmts[3] = V4L2_PIX_FMT_UYVY;
137 fmts[4] = V4L2_PIX_FMT_JPEG;
138 } else {
139 fmts[0] = V4L2_PIX_FMT_YUV420;
140 fmts[1] = V4L2_PIX_FMT_YUYV;
141 fmts[2] = V4L2_PIX_FMT_UYVY;
142 fmts[3] = V4L2_PIX_FMT_MJPEG;
143 fmts[4] = V4L2_PIX_FMT_JPEG;
144 }
145
146 // Enumerate image formats.
147 struct v4l2_fmtdesc fmt;
148 int fmtsIdx = nFormats;
149 memset(&fmt, 0, sizeof(fmt));
150 fmt.index = 0;
151 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
Mirko Bonadei675513b2017-11-09 11:09:25 +0100152 RTC_LOG(LS_INFO) << "Video Capture enumerats supported image formats:";
Mirko Bonadei72c42502017-11-09 09:33:23 +0100153 while (ioctl(_deviceFd, VIDIOC_ENUM_FMT, &fmt) == 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100154 RTC_LOG(LS_INFO) << " { pixelformat = "
155 << cricket::GetFourccName(fmt.pixelformat)
156 << ", description = '" << fmt.description << "' }";
Mirko Bonadei72c42502017-11-09 09:33:23 +0100157 // Match the preferred order.
158 for (int i = 0; i < nFormats; i++) {
159 if (fmt.pixelformat == fmts[i] && i < fmtsIdx)
160 fmtsIdx = i;
braveyao@webrtc.org254d85a2013-02-04 07:53:53 +0000161 }
Mirko Bonadei72c42502017-11-09 09:33:23 +0100162 // Keep enumerating.
163 fmt.index++;
164 }
braveyao@webrtc.org254d85a2013-02-04 07:53:53 +0000165
Mirko Bonadei72c42502017-11-09 09:33:23 +0100166 if (fmtsIdx == nFormats) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100167 RTC_LOG(LS_INFO) << "no supporting video formats found";
Mirko Bonadei72c42502017-11-09 09:33:23 +0100168 return -1;
169 } else {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100170 RTC_LOG(LS_INFO) << "We prefer format "
171 << cricket::GetFourccName(fmts[fmtsIdx]);
Mirko Bonadei72c42502017-11-09 09:33:23 +0100172 }
braveyao@webrtc.org254d85a2013-02-04 07:53:53 +0000173
Mirko Bonadei72c42502017-11-09 09:33:23 +0100174 struct v4l2_format video_fmt;
175 memset(&video_fmt, 0, sizeof(struct v4l2_format));
176 video_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
177 video_fmt.fmt.pix.sizeimage = 0;
178 video_fmt.fmt.pix.width = capability.width;
179 video_fmt.fmt.pix.height = capability.height;
180 video_fmt.fmt.pix.pixelformat = fmts[fmtsIdx];
mflodman@webrtc.org4f9e44f2012-02-23 09:00:26 +0000181
Mirko Bonadei72c42502017-11-09 09:33:23 +0100182 if (video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
183 _captureVideoType = VideoType::kYUY2;
184 else if (video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
185 _captureVideoType = VideoType::kI420;
186 else if (video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_UYVY)
187 _captureVideoType = VideoType::kUYVY;
188 else if (video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG ||
189 video_fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG)
190 _captureVideoType = VideoType::kMJPEG;
niklase@google.com470e71d2011-07-07 08:21:25 +0000191
Mirko Bonadei72c42502017-11-09 09:33:23 +0100192 // set format and frame size now
193 if (ioctl(_deviceFd, VIDIOC_S_FMT, &video_fmt) < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100194 RTC_LOG(LS_INFO) << "error in VIDIOC_S_FMT, errno = " << errno;
Mirko Bonadei72c42502017-11-09 09:33:23 +0100195 return -1;
196 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000197
Mirko Bonadei72c42502017-11-09 09:33:23 +0100198 // initialize current width and height
199 _currentWidth = video_fmt.fmt.pix.width;
200 _currentHeight = video_fmt.fmt.pix.height;
mallinath@webrtc.org42033b42012-08-01 06:31:34 +0000201
Mirko Bonadei72c42502017-11-09 09:33:23 +0100202 // Trying to set frame rate, before check driver capability.
203 bool driver_framerate_support = true;
204 struct v4l2_streamparm streamparms;
205 memset(&streamparms, 0, sizeof(streamparms));
206 streamparms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
207 if (ioctl(_deviceFd, VIDIOC_G_PARM, &streamparms) < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100208 RTC_LOG(LS_INFO) << "error in VIDIOC_G_PARM errno = " << errno;
Mirko Bonadei72c42502017-11-09 09:33:23 +0100209 driver_framerate_support = false;
210 // continue
211 } else {
212 // check the capability flag is set to V4L2_CAP_TIMEPERFRAME.
213 if (streamparms.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
214 // driver supports the feature. Set required framerate.
215 memset(&streamparms, 0, sizeof(streamparms));
216 streamparms.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
217 streamparms.parm.capture.timeperframe.numerator = 1;
218 streamparms.parm.capture.timeperframe.denominator = capability.maxFPS;
219 if (ioctl(_deviceFd, VIDIOC_S_PARM, &streamparms) < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100220 RTC_LOG(LS_INFO) << "Failed to set the framerate. errno=" << errno;
mallinath@webrtc.org42033b42012-08-01 06:31:34 +0000221 driver_framerate_support = false;
mallinath@webrtc.org42033b42012-08-01 06:31:34 +0000222 } else {
Mirko Bonadei72c42502017-11-09 09:33:23 +0100223 _currentFrameRate = capability.maxFPS;
mallinath@webrtc.org42033b42012-08-01 06:31:34 +0000224 }
225 }
Mirko Bonadei72c42502017-11-09 09:33:23 +0100226 }
227 // If driver doesn't support framerate control, need to hardcode.
228 // Hardcoding the value based on the frame size.
229 if (!driver_framerate_support) {
230 if (_currentWidth >= 800 && _captureVideoType != VideoType::kMJPEG) {
231 _currentFrameRate = 15;
232 } else {
233 _currentFrameRate = 30;
niklase@google.com470e71d2011-07-07 08:21:25 +0000234 }
Mirko Bonadei72c42502017-11-09 09:33:23 +0100235 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000236
Mirko Bonadei72c42502017-11-09 09:33:23 +0100237 if (!AllocateVideoBuffers()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100238 RTC_LOG(LS_INFO) << "failed to allocate video capture buffers";
Mirko Bonadei72c42502017-11-09 09:33:23 +0100239 return -1;
240 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000241
Mirko Bonadei72c42502017-11-09 09:33:23 +0100242 // start capture thread;
243 if (!_captureThread) {
244 _captureThread.reset(new rtc::PlatformThread(
245 VideoCaptureModuleV4L2::CaptureThread, this, "CaptureThread"));
246 _captureThread->Start();
247 _captureThread->SetPriority(rtc::kHighPriority);
248 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000249
Mirko Bonadei72c42502017-11-09 09:33:23 +0100250 // Needed to start UVC camera - from the uvcview application
251 enum v4l2_buf_type type;
252 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
253 if (ioctl(_deviceFd, VIDIOC_STREAMON, &type) == -1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100254 RTC_LOG(LS_INFO) << "Failed to turn on stream";
Mirko Bonadei72c42502017-11-09 09:33:23 +0100255 return -1;
256 }
257
258 _captureStarted = true;
259 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000260}
261
Mirko Bonadei72c42502017-11-09 09:33:23 +0100262int32_t VideoCaptureModuleV4L2::StopCapture() {
263 if (_captureThread) {
264 // Make sure the capture thread stop stop using the critsect.
265 _captureThread->Stop();
266 _captureThread.reset();
267 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000268
Mirko Bonadei72c42502017-11-09 09:33:23 +0100269 rtc::CritScope cs(&_captureCritSect);
270 if (_captureStarted) {
271 _captureStarted = false;
perkj@webrtc.orgc2fde802012-08-08 14:01:09 +0000272
Mirko Bonadei72c42502017-11-09 09:33:23 +0100273 DeAllocateVideoBuffers();
274 close(_deviceFd);
275 _deviceFd = -1;
276 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000277
Mirko Bonadei72c42502017-11-09 09:33:23 +0100278 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000279}
280
Mirko Bonadei72c42502017-11-09 09:33:23 +0100281// critical section protected by the caller
niklase@google.com470e71d2011-07-07 08:21:25 +0000282
Mirko Bonadei72c42502017-11-09 09:33:23 +0100283bool VideoCaptureModuleV4L2::AllocateVideoBuffers() {
284 struct v4l2_requestbuffers rbuffer;
285 memset(&rbuffer, 0, sizeof(v4l2_requestbuffers));
niklase@google.com470e71d2011-07-07 08:21:25 +0000286
Mirko Bonadei72c42502017-11-09 09:33:23 +0100287 rbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
288 rbuffer.memory = V4L2_MEMORY_MMAP;
289 rbuffer.count = kNoOfV4L2Bufffers;
290
291 if (ioctl(_deviceFd, VIDIOC_REQBUFS, &rbuffer) < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100292 RTC_LOG(LS_INFO) << "Could not get buffers from device. errno = " << errno;
Mirko Bonadei72c42502017-11-09 09:33:23 +0100293 return false;
294 }
295
296 if (rbuffer.count > kNoOfV4L2Bufffers)
niklase@google.com470e71d2011-07-07 08:21:25 +0000297 rbuffer.count = kNoOfV4L2Bufffers;
298
Mirko Bonadei72c42502017-11-09 09:33:23 +0100299 _buffersAllocatedByDevice = rbuffer.count;
300
301 // Map the buffers
302 _pool = new Buffer[rbuffer.count];
303
304 for (unsigned int i = 0; i < rbuffer.count; i++) {
305 struct v4l2_buffer buffer;
306 memset(&buffer, 0, sizeof(v4l2_buffer));
307 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
308 buffer.memory = V4L2_MEMORY_MMAP;
309 buffer.index = i;
310
311 if (ioctl(_deviceFd, VIDIOC_QUERYBUF, &buffer) < 0) {
312 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000313 }
314
Mirko Bonadei72c42502017-11-09 09:33:23 +0100315 _pool[i].start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE,
316 MAP_SHARED, _deviceFd, buffer.m.offset);
niklase@google.com470e71d2011-07-07 08:21:25 +0000317
Mirko Bonadei72c42502017-11-09 09:33:23 +0100318 if (MAP_FAILED == _pool[i].start) {
319 for (unsigned int j = 0; j < i; j++)
320 munmap(_pool[j].start, _pool[j].length);
321 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000322 }
Mirko Bonadei72c42502017-11-09 09:33:23 +0100323
324 _pool[i].length = buffer.length;
325
326 if (ioctl(_deviceFd, VIDIOC_QBUF, &buffer) < 0) {
327 return false;
328 }
329 }
330 return true;
331}
332
333bool VideoCaptureModuleV4L2::DeAllocateVideoBuffers() {
334 // unmap buffers
335 for (int i = 0; i < _buffersAllocatedByDevice; i++)
336 munmap(_pool[i].start, _pool[i].length);
337
338 delete[] _pool;
339
340 // turn off stream
341 enum v4l2_buf_type type;
342 type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
343 if (ioctl(_deviceFd, VIDIOC_STREAMOFF, &type) < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100344 RTC_LOG(LS_INFO) << "VIDIOC_STREAMOFF error. errno: " << errno;
Mirko Bonadei72c42502017-11-09 09:33:23 +0100345 }
346
347 return true;
348}
349
350bool VideoCaptureModuleV4L2::CaptureStarted() {
351 return _captureStarted;
352}
353
354bool VideoCaptureModuleV4L2::CaptureThread(void* obj) {
355 return static_cast<VideoCaptureModuleV4L2*>(obj)->CaptureProcess();
356}
357bool VideoCaptureModuleV4L2::CaptureProcess() {
358 int retVal = 0;
359 fd_set rSet;
360 struct timeval timeout;
361
362 rtc::CritScope cs(&_captureCritSect);
363
364 FD_ZERO(&rSet);
365 FD_SET(_deviceFd, &rSet);
366 timeout.tv_sec = 1;
367 timeout.tv_usec = 0;
368
369 retVal = select(_deviceFd + 1, &rSet, NULL, NULL, &timeout);
370 if (retVal < 0 && errno != EINTR) // continue if interrupted
371 {
372 // select failed
373 return false;
374 } else if (retVal == 0) {
375 // select timed out
niklase@google.com470e71d2011-07-07 08:21:25 +0000376 return true;
Mirko Bonadei72c42502017-11-09 09:33:23 +0100377 } else if (!FD_ISSET(_deviceFd, &rSet)) {
378 // not event on camera handle
niklase@google.com470e71d2011-07-07 08:21:25 +0000379 return true;
Mirko Bonadei72c42502017-11-09 09:33:23 +0100380 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000381
Mirko Bonadei72c42502017-11-09 09:33:23 +0100382 if (_captureStarted) {
383 struct v4l2_buffer buf;
384 memset(&buf, 0, sizeof(struct v4l2_buffer));
385 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
386 buf.memory = V4L2_MEMORY_MMAP;
387 // dequeue a buffer - repeat until dequeued properly!
388 while (ioctl(_deviceFd, VIDIOC_DQBUF, &buf) < 0) {
389 if (errno != EINTR) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100390 RTC_LOG(LS_INFO) << "could not sync on a buffer on device "
391 << strerror(errno);
niklase@google.com470e71d2011-07-07 08:21:25 +0000392 return true;
Mirko Bonadei72c42502017-11-09 09:33:23 +0100393 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000394 }
Mirko Bonadei72c42502017-11-09 09:33:23 +0100395 VideoCaptureCapability frameInfo;
396 frameInfo.width = _currentWidth;
397 frameInfo.height = _currentHeight;
398 frameInfo.videoType = _captureVideoType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000399
Mirko Bonadei72c42502017-11-09 09:33:23 +0100400 // convert to to I420 if needed
401 IncomingFrame((unsigned char*)_pool[buf.index].start, buf.bytesused,
402 frameInfo);
403 // enqueue the buffer again
404 if (ioctl(_deviceFd, VIDIOC_QBUF, &buf) == -1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100405 RTC_LOG(LS_INFO) << "Failed to enqueue capture buffer";
niklase@google.com470e71d2011-07-07 08:21:25 +0000406 }
Mirko Bonadei72c42502017-11-09 09:33:23 +0100407 }
408 usleep(0);
409 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000410}
411
Mirko Bonadei72c42502017-11-09 09:33:23 +0100412int32_t VideoCaptureModuleV4L2::CaptureSettings(
413 VideoCaptureCapability& settings) {
414 settings.width = _currentWidth;
415 settings.height = _currentHeight;
416 settings.maxFPS = _currentFrameRate;
417 settings.videoType = _captureVideoType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000418
Mirko Bonadei72c42502017-11-09 09:33:23 +0100419 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000420}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000421} // namespace videocapturemodule
422} // namespace webrtc