Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / media / video / capture / linux / video_capture_device_linux.cc
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 preferred 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   V4L2_PIX_FMT_UYVY
48 };
49
50 // USB VID and PID are both 4 bytes long.
51 static const size_t kVidPidSize = 4;
52
53 // /sys/class/video4linux/video{N}/device is a symlink to the corresponding
54 // USB device info directory.
55 static const char kVidPathTemplate[] =
56     "/sys/class/video4linux/%s/device/../idVendor";
57 static const char kPidPathTemplate[] =
58     "/sys/class/video4linux/%s/device/../idProduct";
59
60 bool 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
76 VideoPixelFormat 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
100 void 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
114 const 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
136 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name)
137     : is_capturing_(false),
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
146 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() {
147   // Check if the thread is running.
148   // This means that the device have not been DeAllocated properly.
149   DCHECK(!v4l2_thread_.IsRunning());
150   v4l2_thread_.Stop();
151 }
152
153 void VideoCaptureDeviceLinux::AllocateAndStart(
154     const VideoCaptureParams& params,
155     scoped_ptr<VideoCaptureDevice::Client> client) {
156   if (v4l2_thread_.IsRunning()) {
157     return;  // Wrong state.
158   }
159   v4l2_thread_.Start();
160   v4l2_thread_.message_loop()->PostTask(
161       FROM_HERE,
162       base::Bind(&VideoCaptureDeviceLinux::OnAllocateAndStart,
163                  base::Unretained(this),
164                  params.requested_format.frame_size.width(),
165                  params.requested_format.frame_size.height(),
166                  params.requested_format.frame_rate,
167                  base::Passed(&client)));
168 }
169
170 void VideoCaptureDeviceLinux::StopAndDeAllocate() {
171   if (!v4l2_thread_.IsRunning()) {
172     return;  // Wrong state.
173   }
174   v4l2_thread_.message_loop()->PostTask(
175       FROM_HERE,
176       base::Bind(&VideoCaptureDeviceLinux::OnStopAndDeAllocate,
177                  base::Unretained(this)));
178   v4l2_thread_.Stop();
179   // Make sure no buffers are still allocated.
180   // This can happen (theoretically) if an error occurs when trying to stop
181   // the camera.
182   DeAllocateVideoBuffers();
183 }
184
185 void VideoCaptureDeviceLinux::SetRotation(int rotation) {
186   if (v4l2_thread_.IsRunning()) {
187     v4l2_thread_.message_loop()->PostTask(
188         FROM_HERE,
189         base::Bind(&VideoCaptureDeviceLinux::SetRotationOnV4L2Thread,
190                    base::Unretained(this), rotation));
191   } else {
192     // If the |v4l2_thread_| is not running, there's no race condition and
193     // |rotation_| can be set directly.
194     rotation_ = rotation;
195   }
196 }
197
198 void VideoCaptureDeviceLinux::SetRotationOnV4L2Thread(int rotation) {
199   DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
200   DCHECK(rotation >= 0 && rotation < 360 && rotation % 90 == 0);
201   rotation_ = rotation;
202 }
203
204 void VideoCaptureDeviceLinux::OnAllocateAndStart(int width,
205                                                  int height,
206                                                  float frame_rate,
207                                                  scoped_ptr<Client> client) {
208   DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
209
210   client_ = client.Pass();
211
212   // Need to open camera with O_RDWR after Linux kernel 3.3.
213   device_fd_.reset(HANDLE_EINTR(open(device_name_.id().c_str(), O_RDWR)));
214   if (!device_fd_.is_valid()) {
215     SetErrorState("Failed to open V4L2 device driver.");
216     return;
217   }
218
219   // Test if this is a V4L2 capture device.
220   v4l2_capability cap;
221   if (!((HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYCAP, &cap)) == 0) &&
222         (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
223         !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT))) {
224     // This is not a V4L2 video capture device.
225     device_fd_.reset();
226     SetErrorState("This is not a V4L2 video capture device");
227     return;
228   }
229
230   // Get supported video formats in preferred order.
231   // For large resolutions, favour mjpeg over raw formats.
232   std::list<int> v4l2_formats;
233   GetListOfUsableFourCCs(width > kMjpegWidth || height > kMjpegHeight,
234                          &v4l2_formats);
235
236   v4l2_fmtdesc fmtdesc = {0};
237   fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
238
239   // Enumerate image formats.
240   std::list<int>::iterator best = v4l2_formats.end();
241   while (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_ENUM_FMT, &fmtdesc)) ==
242          0) {
243     best = std::find(v4l2_formats.begin(), best, fmtdesc.pixelformat);
244     fmtdesc.index++;
245   }
246
247   if (best == v4l2_formats.end()) {
248     SetErrorState("Failed to find a supported camera format.");
249     return;
250   }
251
252   // Set format and frame size now.
253   v4l2_format video_fmt;
254   memset(&video_fmt, 0, sizeof(v4l2_format));
255   video_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
256   video_fmt.fmt.pix.sizeimage = 0;
257   video_fmt.fmt.pix.width = width;
258   video_fmt.fmt.pix.height = height;
259   video_fmt.fmt.pix.pixelformat = *best;
260
261   if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_FMT, &video_fmt)) < 0) {
262     SetErrorState(
263         base::StringPrintf("Failed to set camera format: %s", strerror(errno)));
264     return;
265   }
266
267   // Set capture framerate in the form of capture interval.
268   v4l2_streamparm streamparm;
269   memset(&streamparm, 0, sizeof(v4l2_streamparm));
270   streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
271   // The following line checks that the driver knows about framerate get/set.
272   if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_G_PARM, &streamparm)) >= 0) {
273     // Now check if the device is able to accept a capture framerate set.
274     if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
275       // |frame_rate| is float, approximate by a fraction.
276       streamparm.parm.capture.timeperframe.numerator =
277           media::kFrameRatePrecision;
278       streamparm.parm.capture.timeperframe.denominator = (frame_rate) ?
279           (frame_rate * media::kFrameRatePrecision) :
280           (kTypicalFramerate * media::kFrameRatePrecision);
281
282       if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_PARM, &streamparm)) <
283           0) {
284         SetErrorState("Failed to set camera framerate");
285         return;
286       }
287       DVLOG(2) << "Actual camera driverframerate: "
288                << streamparm.parm.capture.timeperframe.denominator << "/"
289                << streamparm.parm.capture.timeperframe.numerator;
290     }
291   }
292   // TODO(mcasas): what should be done if the camera driver does not allow
293   // framerate configuration, or the actual one is different from the desired?
294
295   // Set anti-banding/anti-flicker to 50/60Hz. May fail due to not supported
296   // operation (|errno| == EINVAL in this case) or plain failure.
297   const int power_line_frequency = GetPowerLineFrequencyForLocation();
298   if ((power_line_frequency == kPowerLine50Hz) ||
299       (power_line_frequency == kPowerLine60Hz)) {
300     struct v4l2_control control = {};
301     control.id = V4L2_CID_POWER_LINE_FREQUENCY;
302     control.value = (power_line_frequency == kPowerLine50Hz) ?
303                         V4L2_CID_POWER_LINE_FREQUENCY_50HZ :
304                         V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
305     HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_CTRL, &control));
306   }
307
308   // Store our current width and height.
309   capture_format_.frame_size.SetSize(video_fmt.fmt.pix.width,
310                                      video_fmt.fmt.pix.height);
311   capture_format_.frame_rate = frame_rate;
312   capture_format_.pixel_format =
313       V4l2ColorToVideoCaptureColorFormat(video_fmt.fmt.pix.pixelformat);
314
315   // Start capturing.
316   if (!AllocateVideoBuffers()) {
317     // Error, We can not recover.
318     SetErrorState("Allocate buffer failed");
319     return;
320   }
321
322   // Start UVC camera.
323   v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
324   if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMON, &type)) == -1) {
325     SetErrorState("VIDIOC_STREAMON failed");
326     return;
327   }
328
329   is_capturing_ = true;
330   // Post task to start fetching frames from v4l2.
331   v4l2_thread_.message_loop()->PostTask(
332       FROM_HERE,
333       base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
334                  base::Unretained(this)));
335 }
336
337 void VideoCaptureDeviceLinux::OnStopAndDeAllocate() {
338   DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
339
340   v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
341   if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMOFF, &type)) < 0) {
342     SetErrorState("VIDIOC_STREAMOFF failed");
343     return;
344   }
345   // We don't dare to deallocate the buffers if we can't stop
346   // the capture device.
347   DeAllocateVideoBuffers();
348
349   // We need to close and open the device if we want to change the settings
350   // Otherwise VIDIOC_S_FMT will return error
351   // Sad but true.
352   device_fd_.reset();
353   is_capturing_ = false;
354   client_.reset();
355 }
356
357 void VideoCaptureDeviceLinux::OnCaptureTask() {
358   DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
359   if (!is_capturing_)
360     return;
361
362   fd_set r_set;
363   FD_ZERO(&r_set);
364   FD_SET(device_fd_.get(), &r_set);
365   timeval timeout;
366
367   timeout.tv_sec = 0;
368   timeout.tv_usec = kCaptureTimeoutUs;
369
370   // First argument to select is the highest numbered file descriptor +1.
371   // Refer to http://linux.die.net/man/2/select for more information.
372   int result =
373       HANDLE_EINTR(select(device_fd_.get() + 1, &r_set, NULL, NULL, &timeout));
374   // Check if select have failed.
375   if (result < 0) {
376     // EINTR is a signal. This is not really an error.
377     if (errno != EINTR) {
378       SetErrorState("Select failed");
379       return;
380     }
381     v4l2_thread_.message_loop()->PostDelayedTask(
382         FROM_HERE,
383         base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
384                    base::Unretained(this)),
385         base::TimeDelta::FromMilliseconds(kCaptureSelectWaitMs));
386   }
387
388   // Check if select timeout.
389   if (result == 0) {
390     timeout_count_++;
391     if (timeout_count_ >= kContinuousTimeoutLimit) {
392       SetErrorState(base::StringPrintf(
393           "Continuous timeout %d times", timeout_count_));
394       timeout_count_ = 0;
395       return;
396     }
397   } else {
398     timeout_count_ = 0;
399   }
400
401   // Check if the driver have filled a buffer.
402   if (FD_ISSET(device_fd_.get(), &r_set)) {
403     v4l2_buffer buffer;
404     memset(&buffer, 0, sizeof(buffer));
405     buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
406     buffer.memory = V4L2_MEMORY_MMAP;
407     // Dequeue a buffer.
408     if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) == 0) {
409       client_->OnIncomingCapturedData(
410           static_cast<uint8*>(buffer_pool_[buffer.index].start),
411           buffer.bytesused,
412           capture_format_,
413           rotation_,
414           base::TimeTicks::Now());
415
416       // Enqueue the buffer again.
417       if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) == -1) {
418         SetErrorState(base::StringPrintf(
419             "Failed to enqueue capture buffer errno %d", errno));
420       }
421     } else {
422       SetErrorState(base::StringPrintf(
423           "Failed to dequeue capture buffer errno %d", errno));
424       return;
425     }
426   }
427
428   v4l2_thread_.message_loop()->PostTask(
429       FROM_HERE,
430       base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
431                  base::Unretained(this)));
432 }
433
434 bool VideoCaptureDeviceLinux::AllocateVideoBuffers() {
435   v4l2_requestbuffers r_buffer;
436   memset(&r_buffer, 0, sizeof(r_buffer));
437
438   r_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
439   r_buffer.memory = V4L2_MEMORY_MMAP;
440   r_buffer.count = kMaxVideoBuffers;
441
442   if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) {
443     return false;
444   }
445
446   if (r_buffer.count > kMaxVideoBuffers) {
447     r_buffer.count = kMaxVideoBuffers;
448   }
449
450   buffer_pool_size_ = r_buffer.count;
451
452   // Map the buffers.
453   buffer_pool_ = new Buffer[r_buffer.count];
454   for (unsigned int i = 0; i < r_buffer.count; i++) {
455     v4l2_buffer buffer;
456     memset(&buffer, 0, sizeof(buffer));
457     buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
458     buffer.memory = V4L2_MEMORY_MMAP;
459     buffer.index = i;
460
461     if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYBUF, &buffer)) < 0) {
462       return false;
463     }
464
465     // Some devices require mmap() to be called with both READ and WRITE.
466     // See crbug.com/178582.
467     buffer_pool_[i].start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE,
468                                  MAP_SHARED, device_fd_.get(), buffer.m.offset);
469     if (buffer_pool_[i].start == MAP_FAILED) {
470       return false;
471     }
472     buffer_pool_[i].length = buffer.length;
473     // Enqueue the buffer in the drivers incoming queue.
474     if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) {
475       return false;
476     }
477   }
478   return true;
479 }
480
481 void VideoCaptureDeviceLinux::DeAllocateVideoBuffers() {
482   if (!buffer_pool_)
483     return;
484
485   // Unmaps buffers.
486   for (int i = 0; i < buffer_pool_size_; i++) {
487     munmap(buffer_pool_[i].start, buffer_pool_[i].length);
488   }
489   v4l2_requestbuffers r_buffer;
490   memset(&r_buffer, 0, sizeof(r_buffer));
491   r_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
492   r_buffer.memory = V4L2_MEMORY_MMAP;
493   r_buffer.count = 0;
494
495   if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) {
496     SetErrorState("Failed to reset buf.");
497   }
498
499   delete [] buffer_pool_;
500   buffer_pool_ = NULL;
501   buffer_pool_size_ = 0;
502 }
503
504 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) {
505   DCHECK(!v4l2_thread_.IsRunning() ||
506          v4l2_thread_.message_loop() == base::MessageLoop::current());
507   is_capturing_ = false;
508   client_->OnError(reason);
509 }
510
511 }  // namespace media