1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/video/capture/linux/video_capture_device_linux.h"
6
7 #include <errno.h>
8 #include <fcntl.h>
9 #if defined(OS_OPENBSD)
10 #include <sys/videoio.h>
11 #else
12 #include <linux/videodev2.h>
13 #endif
14 #include <sys/ioctl.h>
15 #include <sys/mman.h>
16
17 #include <list>
18 #include <string>
19
20 #include "base/bind.h"
21 #include "base/files/file_enumerator.h"
22 #include "base/files/scoped_file.h"
23 #include "base/posix/eintr_wrapper.h"
24 #include "base/strings/stringprintf.h"
25
26 namespace media {
27
28 // Max number of video buffers VideoCaptureDeviceLinux can allocate.
29 enum { kMaxVideoBuffers = 2 };
30 // Timeout in microseconds v4l2_thread_ blocks waiting for a frame from the hw.
31 enum { kCaptureTimeoutUs = 200000 };
32 // The number of continuous timeouts tolerated before treated as error.
33 enum { kContinuousTimeoutLimit = 10 };
34 // Time to wait in milliseconds before v4l2_thread_ reschedules OnCaptureTask
35 // if an event is triggered (select) but no video frame is read.
36 enum { kCaptureSelectWaitMs = 10 };
37 // MJPEG is prefered if the width or height is larger than this.
38 enum { kMjpegWidth = 640 };
39 enum { kMjpegHeight = 480 };
40 // Typical framerate, in fps
41 enum { kTypicalFramerate = 30 };
42
43 // V4L2 color formats VideoCaptureDeviceLinux support.
44 static const int32 kV4l2RawFmts[] = {
45 V4L2_PIX_FMT_YUV420,
46 V4L2_PIX_FMT_YUYV
47 };
48
49 // USB VID and PID are both 4 bytes long.
50 static const size_t kVidPidSize = 4;
51
52 // /sys/class/video4linux/video{N}/device is a symlink to the corresponding
53 // USB device info directory.
54 static const char kVidPathTemplate[] =
55 "/sys/class/video4linux/%s/device/../idVendor";
56 static const char kPidPathTemplate[] =
57 "/sys/class/video4linux/%s/device/../idProduct";
58
ReadIdFile(const std::string path,std::string * id)59 bool ReadIdFile(const std::string path, std::string* id) {
60 char id_buf[kVidPidSize];
61 FILE* file = fopen(path.c_str(), "rb");
62 if (!file)
63 return false;
64 const bool success = fread(id_buf, kVidPidSize, 1, file) == 1;
65 fclose(file);
66 if (!success)
67 return false;
68 id->append(id_buf, kVidPidSize);
69 return true;
70 }
71
72 // This function translates Video4Linux pixel formats to Chromium pixel formats,
73 // should only support those listed in GetListOfUsableFourCCs.
74 // static
V4l2ColorToVideoCaptureColorFormat(int32 v4l2_fourcc)75 VideoPixelFormat VideoCaptureDeviceLinux::V4l2ColorToVideoCaptureColorFormat(
76 int32 v4l2_fourcc) {
77 VideoPixelFormat result = PIXEL_FORMAT_UNKNOWN;
78 switch (v4l2_fourcc) {
79 case V4L2_PIX_FMT_YUV420:
80 result = PIXEL_FORMAT_I420;
81 break;
82 case V4L2_PIX_FMT_YUYV:
83 result = PIXEL_FORMAT_YUY2;
84 break;
85 case V4L2_PIX_FMT_MJPEG:
86 case V4L2_PIX_FMT_JPEG:
87 result = PIXEL_FORMAT_MJPEG;
88 break;
89 default:
90 DVLOG(1) << "Unsupported pixel format " << std::hex << v4l2_fourcc;
91 }
92 return result;
93 }
94
95 // static
GetListOfUsableFourCCs(bool favour_mjpeg,std::list<int> * fourccs)96 void VideoCaptureDeviceLinux::GetListOfUsableFourCCs(bool favour_mjpeg,
97 std::list<int>* fourccs) {
98 for (size_t i = 0; i < arraysize(kV4l2RawFmts); ++i)
99 fourccs->push_back(kV4l2RawFmts[i]);
100 if (favour_mjpeg)
101 fourccs->push_front(V4L2_PIX_FMT_MJPEG);
102 else
103 fourccs->push_back(V4L2_PIX_FMT_MJPEG);
104
105 // JPEG works as MJPEG on some gspca webcams from field reports.
106 // Put it as the least preferred format.
107 fourccs->push_back(V4L2_PIX_FMT_JPEG);
108 }
109
GetModel() const110 const std::string VideoCaptureDevice::Name::GetModel() const {
111 // |unique_id| is of the form "/dev/video2". |file_name| is "video2".
112 const std::string dev_dir = "/dev/";
113 DCHECK_EQ(0, unique_id_.compare(0, dev_dir.length(), dev_dir));
114 const std::string file_name =
115 unique_id_.substr(dev_dir.length(), unique_id_.length());
116
117 const std::string vidPath =
118 base::StringPrintf(kVidPathTemplate, file_name.c_str());
119 const std::string pidPath =
120 base::StringPrintf(kPidPathTemplate, file_name.c_str());
121
122 std::string usb_id;
123 if (!ReadIdFile(vidPath, &usb_id))
124 return "";
125 usb_id.append(":");
126 if (!ReadIdFile(pidPath, &usb_id))
127 return "";
128
129 return usb_id;
130 }
131
VideoCaptureDeviceLinux(const Name & device_name)132 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name)
133 : state_(kIdle),
134 device_name_(device_name),
135 v4l2_thread_("V4L2Thread"),
136 buffer_pool_(NULL),
137 buffer_pool_size_(0),
138 timeout_count_(0),
139 rotation_(0) {
140 }
141
~VideoCaptureDeviceLinux()142 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() {
143 state_ = kIdle;
144 // Check if the thread is running.
145 // This means that the device have not been DeAllocated properly.
146 DCHECK(!v4l2_thread_.IsRunning());
147 v4l2_thread_.Stop();
148 }
149
AllocateAndStart(const VideoCaptureParams & params,scoped_ptr<VideoCaptureDevice::Client> client)150 void VideoCaptureDeviceLinux::AllocateAndStart(
151 const VideoCaptureParams& params,
152 scoped_ptr<VideoCaptureDevice::Client> client) {
153 if (v4l2_thread_.IsRunning()) {
154 return; // Wrong state.
155 }
156 v4l2_thread_.Start();
157 v4l2_thread_.message_loop()->PostTask(
158 FROM_HERE,
159 base::Bind(&VideoCaptureDeviceLinux::OnAllocateAndStart,
160 base::Unretained(this),
161 params.requested_format.frame_size.width(),
162 params.requested_format.frame_size.height(),
163 params.requested_format.frame_rate,
164 base::Passed(&client)));
165 }
166
StopAndDeAllocate()167 void VideoCaptureDeviceLinux::StopAndDeAllocate() {
168 if (!v4l2_thread_.IsRunning()) {
169 return; // Wrong state.
170 }
171 v4l2_thread_.message_loop()->PostTask(
172 FROM_HERE,
173 base::Bind(&VideoCaptureDeviceLinux::OnStopAndDeAllocate,
174 base::Unretained(this)));
175 v4l2_thread_.Stop();
176 // Make sure no buffers are still allocated.
177 // This can happen (theoretically) if an error occurs when trying to stop
178 // the camera.
179 DeAllocateVideoBuffers();
180 }
181
SetRotation(int rotation)182 void VideoCaptureDeviceLinux::SetRotation(int rotation) {
183 if (v4l2_thread_.IsRunning()) {
184 v4l2_thread_.message_loop()->PostTask(
185 FROM_HERE,
186 base::Bind(&VideoCaptureDeviceLinux::SetRotationOnV4L2Thread,
187 base::Unretained(this), rotation));
188 } else {
189 // If the |v4l2_thread_| is not running, there's no race condition and
190 // |rotation_| can be set directly.
191 rotation_ = rotation;
192 }
193 }
194
SetRotationOnV4L2Thread(int rotation)195 void VideoCaptureDeviceLinux::SetRotationOnV4L2Thread(int rotation) {
196 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
197 DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0);
198 rotation_ = rotation;
199 }
200
OnAllocateAndStart(int width,int height,int frame_rate,scoped_ptr<Client> client)201 void VideoCaptureDeviceLinux::OnAllocateAndStart(int width,
202 int height,
203 int frame_rate,
204 scoped_ptr<Client> client) {
205 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
206
207 client_ = client.Pass();
208
209 // Need to open camera with O_RDWR after Linux kernel 3.3.
210 device_fd_.reset(HANDLE_EINTR(open(device_name_.id().c_str(), O_RDWR)));
211 if (!device_fd_.is_valid()) {
212 SetErrorState("Failed to open V4L2 device driver.");
213 return;
214 }
215
216 // Test if this is a V4L2 capture device.
217 v4l2_capability cap;
218 if (!((HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYCAP, &cap)) == 0) &&
219 (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
220 !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT))) {
221 // This is not a V4L2 video capture device.
222 device_fd_.reset();
223 SetErrorState("This is not a V4L2 video capture device");
224 return;
225 }
226
227 // Get supported video formats in preferred order.
228 // For large resolutions, favour mjpeg over raw formats.
229 std::list<int> v4l2_formats;
230 GetListOfUsableFourCCs(width > kMjpegWidth || height > kMjpegHeight,
231 &v4l2_formats);
232
233 v4l2_fmtdesc fmtdesc = {0};
234 fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
235
236 // Enumerate image formats.
237 std::list<int>::iterator best = v4l2_formats.end();
238 while (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_ENUM_FMT, &fmtdesc)) ==
239 0) {
240 best = std::find(v4l2_formats.begin(), best, fmtdesc.pixelformat);
241 fmtdesc.index++;
242 }
243
244 if (best == v4l2_formats.end()) {
245 SetErrorState("Failed to find a supported camera format.");
246 return;
247 }
248
249 // Set format and frame size now.
250 v4l2_format video_fmt;
251 memset(&video_fmt, 0, sizeof(v4l2_format));
252 video_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
253 video_fmt.fmt.pix.sizeimage = 0;
254 video_fmt.fmt.pix.width = width;
255 video_fmt.fmt.pix.height = height;
256 video_fmt.fmt.pix.pixelformat = *best;
257
258 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_FMT, &video_fmt)) < 0) {
259 SetErrorState("Failed to set camera format");
260 return;
261 }
262
263 // Set capture framerate in the form of capture interval.
264 v4l2_streamparm streamparm;
265 memset(&streamparm, 0, sizeof(v4l2_streamparm));
266 streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
267 // The following line checks that the driver knows about framerate get/set.
268 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_G_PARM, &streamparm)) >= 0) {
269 // Now check if the device is able to accept a capture framerate set.
270 if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
271 // |frame_rate| is float, approximate by a fraction.
272 streamparm.parm.capture.timeperframe.numerator =
273 media::kFrameRatePrecision;
274 streamparm.parm.capture.timeperframe.denominator = (frame_rate) ?
275 (frame_rate * media::kFrameRatePrecision) :
276 (kTypicalFramerate * media::kFrameRatePrecision);
277
278 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_PARM, &streamparm)) <
279 0) {
280 SetErrorState("Failed to set camera framerate");
281 return;
282 }
283 DVLOG(2) << "Actual camera driverframerate: "
284 << streamparm.parm.capture.timeperframe.denominator << "/"
285 << streamparm.parm.capture.timeperframe.numerator;
286 }
287 }
288 // TODO(mcasas): what should be done if the camera driver does not allow
289 // framerate configuration, or the actual one is different from the desired?
290
291 // Set anti-banding/anti-flicker to 50/60Hz. May fail due to not supported
292 // operation (|errno| == EINVAL in this case) or plain failure.
293 const int power_line_frequency = GetPowerLineFrequencyForLocation();
294 if ((power_line_frequency == kPowerLine50Hz) ||
295 (power_line_frequency == kPowerLine60Hz)) {
296 struct v4l2_control control = {};
297 control.id = V4L2_CID_POWER_LINE_FREQUENCY;
298 control.value = (power_line_frequency == kPowerLine50Hz) ?
299 V4L2_CID_POWER_LINE_FREQUENCY_50HZ :
300 V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
301 HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, &control));
302 }
303
304 // Store our current width and height.
305 capture_format_.frame_size.SetSize(video_fmt.fmt.pix.width,
306 video_fmt.fmt.pix.height);
307 capture_format_.frame_rate = frame_rate;
308 capture_format_.pixel_format =
309 V4l2ColorToVideoCaptureColorFormat(video_fmt.fmt.pix.pixelformat);
310
311 // Start capturing.
312 if (!AllocateVideoBuffers()) {
313 // Error, We can not recover.
314 SetErrorState("Allocate buffer failed");
315 return;
316 }
317
318 // Start UVC camera.
319 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
320 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMON, &type)) == -1) {
321 SetErrorState("VIDIOC_STREAMON failed");
322 return;
323 }
324
325 state_ = kCapturing;
326 // Post task to start fetching frames from v4l2.
327 v4l2_thread_.message_loop()->PostTask(
328 FROM_HERE,
329 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
330 base::Unretained(this)));
331 }
332
OnStopAndDeAllocate()333 void VideoCaptureDeviceLinux::OnStopAndDeAllocate() {
334 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
335
336 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
337 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMOFF, &type)) < 0) {
338 SetErrorState("VIDIOC_STREAMOFF failed");
339 return;
340 }
341 // We don't dare to deallocate the buffers if we can't stop
342 // the capture device.
343 DeAllocateVideoBuffers();
344
345 // We need to close and open the device if we want to change the settings
346 // Otherwise VIDIOC_S_FMT will return error
347 // Sad but true.
348 device_fd_.reset();
349 state_ = kIdle;
350 client_.reset();
351 }
352
OnCaptureTask()353 void VideoCaptureDeviceLinux::OnCaptureTask() {
354 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
355
356 if (state_ != kCapturing) {
357 return;
358 }
359
360 fd_set r_set;
361 FD_ZERO(&r_set);
362 FD_SET(device_fd_.get(), &r_set);
363 timeval timeout;
364
365 timeout.tv_sec = 0;
366 timeout.tv_usec = kCaptureTimeoutUs;
367
368 // First argument to select is the highest numbered file descriptor +1.
369 // Refer to http://linux.die.net/man/2/select for more information.
370 int result =
371 HANDLE_EINTR(select(device_fd_.get() + 1, &r_set, NULL, NULL, &timeout));
372 // Check if select have failed.
373 if (result < 0) {
374 // EINTR is a signal. This is not really an error.
375 if (errno != EINTR) {
376 SetErrorState("Select failed");
377 return;
378 }
379 v4l2_thread_.message_loop()->PostDelayedTask(
380 FROM_HERE,
381 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
382 base::Unretained(this)),
383 base::TimeDelta::FromMilliseconds(kCaptureSelectWaitMs));
384 }
385
386 // Check if select timeout.
387 if (result == 0) {
388 timeout_count_++;
389 if (timeout_count_ >= kContinuousTimeoutLimit) {
390 SetErrorState(base::StringPrintf(
391 "Continuous timeout %d times", timeout_count_));
392 timeout_count_ = 0;
393 return;
394 }
395 } else {
396 timeout_count_ = 0;
397 }
398
399 // Check if the driver have filled a buffer.
400 if (FD_ISSET(device_fd_.get(), &r_set)) {
401 v4l2_buffer buffer;
402 memset(&buffer, 0, sizeof(buffer));
403 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
404 buffer.memory = V4L2_MEMORY_MMAP;
405 // Dequeue a buffer.
406 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) == 0) {
407 client_->OnIncomingCapturedData(
408 static_cast<uint8*>(buffer_pool_[buffer.index].start),
409 buffer.bytesused,
410 capture_format_,
411 rotation_,
412 base::TimeTicks::Now());
413
414 // Enqueue the buffer again.
415 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) == -1) {
416 SetErrorState(base::StringPrintf(
417 "Failed to enqueue capture buffer errno %d", errno));
418 }
419 } else {
420 SetErrorState(base::StringPrintf(
421 "Failed to dequeue capture buffer errno %d", errno));
422 return;
423 }
424 }
425
426 v4l2_thread_.message_loop()->PostTask(
427 FROM_HERE,
428 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
429 base::Unretained(this)));
430 }
431
AllocateVideoBuffers()432 bool VideoCaptureDeviceLinux::AllocateVideoBuffers() {
433 v4l2_requestbuffers r_buffer;
434 memset(&r_buffer, 0, sizeof(r_buffer));
435
436 r_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
437 r_buffer.memory = V4L2_MEMORY_MMAP;
438 r_buffer.count = kMaxVideoBuffers;
439
440 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) {
441 return false;
442 }
443
444 if (r_buffer.count > kMaxVideoBuffers) {
445 r_buffer.count = kMaxVideoBuffers;
446 }
447
448 buffer_pool_size_ = r_buffer.count;
449
450 // Map the buffers.
451 buffer_pool_ = new Buffer[r_buffer.count];
452 for (unsigned int i = 0; i < r_buffer.count; i++) {
453 v4l2_buffer buffer;
454 memset(&buffer, 0, sizeof(buffer));
455 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
456 buffer.memory = V4L2_MEMORY_MMAP;
457 buffer.index = i;
458
459 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYBUF, &buffer)) < 0) {
460 return false;
461 }
462
463 // Some devices require mmap() to be called with both READ and WRITE.
464 // See crbug.com/178582.
465 buffer_pool_[i].start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE,
466 MAP_SHARED, device_fd_.get(), buffer.m.offset);
467 if (buffer_pool_[i].start == MAP_FAILED) {
468 return false;
469 }
470 buffer_pool_[i].length = buffer.length;
471 // Enqueue the buffer in the drivers incoming queue.
472 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) {
473 return false;
474 }
475 }
476 return true;
477 }
478
DeAllocateVideoBuffers()479 void VideoCaptureDeviceLinux::DeAllocateVideoBuffers() {
480 if (!buffer_pool_)
481 return;
482
483 // Unmaps buffers.
484 for (int i = 0; i < buffer_pool_size_; i++) {
485 munmap(buffer_pool_[i].start, buffer_pool_[i].length);
486 }
487 v4l2_requestbuffers r_buffer;
488 memset(&r_buffer, 0, sizeof(r_buffer));
489 r_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
490 r_buffer.memory = V4L2_MEMORY_MMAP;
491 r_buffer.count = 0;
492
493 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) {
494 SetErrorState("Failed to reset buf.");
495 }
496
497 delete [] buffer_pool_;
498 buffer_pool_ = NULL;
499 buffer_pool_size_ = 0;
500 }
501
SetErrorState(const std::string & reason)502 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) {
503 DCHECK(!v4l2_thread_.IsRunning() ||
504 v4l2_thread_.message_loop() == base::MessageLoop::current());
505 DVLOG(1) << reason;
506 state_ = kError;
507 client_->OnError(reason);
508 }
509
510 } // namespace media
511