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