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