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 // Linux USB camera devices have names like "UVC Camera (1234:fdcb)"
     49 static const char kUsbSuffixStart[] = " (";
     50 static const size_t kUsbModelSize = 9;
     51 static const char kUsbSuffixEnd[] = ")";
     52 
     53 static VideoCaptureCapability::Format V4l2ColorToVideoCaptureColorFormat(
     54     int32 v4l2_fourcc) {
     55   VideoCaptureCapability::Format result = VideoCaptureCapability::kColorUnknown;
     56   switch (v4l2_fourcc) {
     57     case V4L2_PIX_FMT_YUV420:
     58       result = VideoCaptureCapability::kI420;
     59       break;
     60     case V4L2_PIX_FMT_YUYV:
     61       result = VideoCaptureCapability::kYUY2;
     62       break;
     63     case V4L2_PIX_FMT_MJPEG:
     64     case V4L2_PIX_FMT_JPEG:
     65       result = VideoCaptureCapability::kMJPEG;
     66       break;
     67   }
     68   DCHECK_NE(result, VideoCaptureCapability::kColorUnknown);
     69   return result;
     70 }
     71 
     72 static void GetListOfUsableFourCCs(bool favour_mjpeg, std::list<int>* fourccs) {
     73   for (size_t i = 0; i < arraysize(kV4l2RawFmts); ++i)
     74     fourccs->push_back(kV4l2RawFmts[i]);
     75   if (favour_mjpeg)
     76     fourccs->push_front(V4L2_PIX_FMT_MJPEG);
     77   else
     78     fourccs->push_back(V4L2_PIX_FMT_MJPEG);
     79 
     80   // JPEG works as MJPEG on some gspca webcams from field reports.
     81   // Put it as the least preferred format.
     82   fourccs->push_back(V4L2_PIX_FMT_JPEG);
     83 }
     84 
     85 static bool HasUsableFormats(int fd) {
     86   v4l2_fmtdesc fmtdesc;
     87   std::list<int> usable_fourccs;
     88 
     89   GetListOfUsableFourCCs(false, &usable_fourccs);
     90 
     91   memset(&fmtdesc, 0, sizeof(v4l2_fmtdesc));
     92   fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     93 
     94   while (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
     95     if (std::find(usable_fourccs.begin(), usable_fourccs.end(),
     96                   fmtdesc.pixelformat) != usable_fourccs.end())
     97       return true;
     98 
     99     fmtdesc.index++;
    100   }
    101   return false;
    102 }
    103 
    104 void VideoCaptureDevice::GetDeviceNames(Names* device_names) {
    105   int fd = -1;
    106 
    107   // Empty the name list.
    108   device_names->clear();
    109 
    110   base::FilePath path("/dev/");
    111   base::FileEnumerator enumerator(
    112       path, false, base::FileEnumerator::FILES, "video*");
    113 
    114   while (!enumerator.Next().empty()) {
    115     base::FileEnumerator::FileInfo info = enumerator.GetInfo();
    116 
    117     std::string unique_id = path.value() + info.GetName().value();
    118     if ((fd = open(unique_id.c_str() , O_RDONLY)) < 0) {
    119       // Failed to open this device.
    120       continue;
    121     }
    122     // Test if this is a V4L2 capture device.
    123     v4l2_capability cap;
    124     if ((ioctl(fd, VIDIOC_QUERYCAP, &cap) == 0) &&
    125         (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
    126         !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)) {
    127       // This is a V4L2 video capture device
    128       if (HasUsableFormats(fd)) {
    129         Name device_name(base::StringPrintf("%s", cap.card), unique_id);
    130         device_names->push_back(device_name);
    131       } else {
    132         DVLOG(1) << "No usable formats reported by " << info.GetName().value();
    133       }
    134     }
    135     close(fd);
    136   }
    137 }
    138 
    139 const std::string VideoCaptureDevice::Name::GetModel() const {
    140   const size_t usb_suffix_start_size = sizeof(kUsbSuffixStart) - 1;
    141   const size_t usb_suffix_end_size = sizeof(kUsbSuffixEnd) - 1;
    142   const size_t suffix_size =
    143       usb_suffix_start_size + kUsbModelSize + usb_suffix_end_size;
    144   if (device_name_.length() < suffix_size)
    145     return "";
    146   const std::string suffix = device_name_.substr(
    147       device_name_.length() - suffix_size, suffix_size);
    148 
    149   int start_compare =
    150       suffix.compare(0, usb_suffix_start_size, kUsbSuffixStart);
    151   int end_compare = suffix.compare(suffix_size - usb_suffix_end_size,
    152       usb_suffix_end_size, kUsbSuffixEnd);
    153   if (start_compare != 0 || end_compare != 0)
    154     return "";
    155 
    156   return suffix.substr(usb_suffix_start_size, kUsbModelSize);
    157 }
    158 
    159 VideoCaptureDevice* VideoCaptureDevice::Create(const Name& device_name) {
    160   VideoCaptureDeviceLinux* self = new VideoCaptureDeviceLinux(device_name);
    161   if (!self)
    162     return NULL;
    163   // Test opening the device driver. This is to make sure it is available.
    164   // We will reopen it again in our worker thread when someone
    165   // allocates the camera.
    166   int fd = open(device_name.id().c_str(), O_RDONLY);
    167   if (fd < 0) {
    168     DVLOG(1) << "Cannot open device";
    169     delete self;
    170     return NULL;
    171   }
    172   close(fd);
    173 
    174   return self;
    175 }
    176 
    177 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name)
    178     : state_(kIdle),
    179       observer_(NULL),
    180       device_name_(device_name),
    181       device_fd_(-1),
    182       v4l2_thread_("V4L2Thread"),
    183       buffer_pool_(NULL),
    184       buffer_pool_size_(0),
    185       timeout_count_(0) {
    186 }
    187 
    188 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() {
    189   state_ = kIdle;
    190   // Check if the thread is running.
    191   // This means that the device have not been DeAllocated properly.
    192   DCHECK(!v4l2_thread_.IsRunning());
    193 
    194   v4l2_thread_.Stop();
    195   if (device_fd_ >= 0) {
    196     close(device_fd_);
    197   }
    198 }
    199 
    200 void VideoCaptureDeviceLinux::Allocate(
    201     const VideoCaptureCapability& capture_format,
    202     EventHandler* observer) {
    203   if (v4l2_thread_.IsRunning()) {
    204     return;  // Wrong state.
    205   }
    206   v4l2_thread_.Start();
    207   v4l2_thread_.message_loop()
    208       ->PostTask(FROM_HERE,
    209                  base::Bind(&VideoCaptureDeviceLinux::OnAllocate,
    210                             base::Unretained(this),
    211                             capture_format.width,
    212                             capture_format.height,
    213                             capture_format.frame_rate,
    214                             observer));
    215 }
    216 
    217 void VideoCaptureDeviceLinux::Start() {
    218   if (!v4l2_thread_.IsRunning()) {
    219     return;  // Wrong state.
    220   }
    221   v4l2_thread_.message_loop()->PostTask(
    222       FROM_HERE,
    223       base::Bind(&VideoCaptureDeviceLinux::OnStart, base::Unretained(this)));
    224 }
    225 
    226 void VideoCaptureDeviceLinux::Stop() {
    227   if (!v4l2_thread_.IsRunning()) {
    228     return;  // Wrong state.
    229   }
    230   v4l2_thread_.message_loop()->PostTask(
    231       FROM_HERE,
    232       base::Bind(&VideoCaptureDeviceLinux::OnStop, base::Unretained(this)));
    233 }
    234 
    235 void VideoCaptureDeviceLinux::DeAllocate() {
    236   if (!v4l2_thread_.IsRunning()) {
    237     return;  // Wrong state.
    238   }
    239   v4l2_thread_.message_loop()->PostTask(
    240       FROM_HERE,
    241       base::Bind(&VideoCaptureDeviceLinux::OnDeAllocate,
    242                  base::Unretained(this)));
    243   v4l2_thread_.Stop();
    244 
    245   // Make sure no buffers are still allocated.
    246   // This can happen (theoretically) if an error occurs when trying to stop
    247   // the camera.
    248   DeAllocateVideoBuffers();
    249 }
    250 
    251 const VideoCaptureDevice::Name& VideoCaptureDeviceLinux::device_name() {
    252   return device_name_;
    253 }
    254 
    255 void VideoCaptureDeviceLinux::OnAllocate(int width,
    256                                          int height,
    257                                          int frame_rate,
    258                                          EventHandler* observer) {
    259   DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
    260 
    261   observer_ = observer;
    262 
    263   // Need to open camera with O_RDWR after Linux kernel 3.3.
    264   if ((device_fd_ = open(device_name_.id().c_str(), O_RDWR)) < 0) {
    265     SetErrorState("Failed to open V4L2 device driver.");
    266     return;
    267   }
    268 
    269   // Test if this is a V4L2 capture device.
    270   v4l2_capability cap;
    271   if (!((ioctl(device_fd_, VIDIOC_QUERYCAP, &cap) == 0) &&
    272       (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
    273       !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT))) {
    274     // This is not a V4L2 video capture device.
    275     close(device_fd_);
    276     device_fd_ = -1;
    277     SetErrorState("This is not a V4L2 video capture device");
    278     return;
    279   }
    280 
    281   // Get supported video formats in preferred order.
    282   // For large resolutions, favour mjpeg over raw formats.
    283   std::list<int> v4l2_formats;
    284   GetListOfUsableFourCCs(width > kMjpegWidth || height > kMjpegHeight,
    285                          &v4l2_formats);
    286 
    287   v4l2_fmtdesc fmtdesc;
    288   memset(&fmtdesc, 0, sizeof(v4l2_fmtdesc));
    289   fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    290 
    291   // Enumerate image formats.
    292   std::list<int>::iterator best = v4l2_formats.end();
    293   while (ioctl(device_fd_, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
    294     best = std::find(v4l2_formats.begin(), best, fmtdesc.pixelformat);
    295     fmtdesc.index++;
    296   }
    297 
    298   if (best == v4l2_formats.end()) {
    299     SetErrorState("Failed to find a supported camera format.");
    300     return;
    301   }
    302 
    303   // Set format and frame size now.
    304   v4l2_format video_fmt;
    305   memset(&video_fmt, 0, sizeof(video_fmt));
    306   video_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    307   video_fmt.fmt.pix.sizeimage = 0;
    308   video_fmt.fmt.pix.width = width;
    309   video_fmt.fmt.pix.height = height;
    310   video_fmt.fmt.pix.pixelformat = *best;
    311 
    312   if (ioctl(device_fd_, VIDIOC_S_FMT, &video_fmt) < 0) {
    313     SetErrorState("Failed to set camera format");
    314     return;
    315   }
    316 
    317   // Set capture framerate in the form of capture interval.
    318   v4l2_streamparm streamparm;
    319   memset(&streamparm, 0, sizeof(v4l2_streamparm));
    320   streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    321   // The following line checks that the driver knows about framerate get/set.
    322   if (ioctl(device_fd_, VIDIOC_G_PARM, &streamparm) >= 0) {
    323     // Now check if the device is able to accept a capture framerate set.
    324     if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
    325       streamparm.parm.capture.timeperframe.numerator = 1;
    326       streamparm.parm.capture.timeperframe.denominator =
    327           (frame_rate) ? frame_rate : kTypicalFramerate;
    328 
    329       if (ioctl(device_fd_, VIDIOC_S_PARM, &streamparm) < 0) {
    330         SetErrorState("Failed to set camera framerate");
    331         return;
    332       }
    333       DVLOG(2) << "Actual camera driverframerate: "
    334                << streamparm.parm.capture.timeperframe.denominator << "/"
    335                << streamparm.parm.capture.timeperframe.numerator;
    336     }
    337   }
    338   // TODO(mcasas): what should be done if the camera driver does not allow
    339   // framerate configuration, or the actual one is different from the desired?
    340 
    341   // Store our current width and height.
    342   VideoCaptureCapability current_settings;
    343   current_settings.color = V4l2ColorToVideoCaptureColorFormat(
    344       video_fmt.fmt.pix.pixelformat);
    345   current_settings.width  = video_fmt.fmt.pix.width;
    346   current_settings.height = video_fmt.fmt.pix.height;
    347   current_settings.frame_rate = frame_rate;
    348   current_settings.expected_capture_delay = 0;
    349   current_settings.interlaced = false;
    350 
    351   state_ = kAllocated;
    352   // Report the resulting frame size to the observer.
    353   observer_->OnFrameInfo(current_settings);
    354 }
    355 
    356 void VideoCaptureDeviceLinux::OnDeAllocate() {
    357   DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
    358 
    359   // If we are in error state or capturing
    360   // try to stop the camera.
    361   if (state_ == kCapturing) {
    362     OnStop();
    363   }
    364   if (state_ == kAllocated) {
    365     state_ = kIdle;
    366   }
    367 
    368   // We need to close and open the device if we want to change the settings
    369   // Otherwise VIDIOC_S_FMT will return error
    370   // Sad but true.
    371   close(device_fd_);
    372   device_fd_ = -1;
    373 }
    374 
    375 void VideoCaptureDeviceLinux::OnStart() {
    376   DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
    377 
    378   if (state_ != kAllocated) {
    379     return;
    380   }
    381 
    382   if (!AllocateVideoBuffers()) {
    383     // Error, We can not recover.
    384     SetErrorState("Allocate buffer failed");
    385     return;
    386   }
    387 
    388   // Start UVC camera.
    389   v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    390   if (ioctl(device_fd_, VIDIOC_STREAMON, &type) == -1) {
    391     SetErrorState("VIDIOC_STREAMON failed");
    392     return;
    393   }
    394 
    395   state_ = kCapturing;
    396   // Post task to start fetching frames from v4l2.
    397   v4l2_thread_.message_loop()->PostTask(
    398       FROM_HERE,
    399       base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
    400                  base::Unretained(this)));
    401 }
    402 
    403 void VideoCaptureDeviceLinux::OnStop() {
    404   DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
    405 
    406   state_ = kAllocated;
    407 
    408   v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    409   if (ioctl(device_fd_, VIDIOC_STREAMOFF, &type) < 0) {
    410     SetErrorState("VIDIOC_STREAMOFF failed");
    411     return;
    412   }
    413   // We don't dare to deallocate the buffers if we can't stop
    414   // the capture device.
    415   DeAllocateVideoBuffers();
    416 }
    417 
    418 void VideoCaptureDeviceLinux::OnCaptureTask() {
    419   DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
    420 
    421   if (state_ != kCapturing) {
    422     return;
    423   }
    424 
    425   fd_set r_set;
    426   FD_ZERO(&r_set);
    427   FD_SET(device_fd_, &r_set);
    428   timeval timeout;
    429 
    430   timeout.tv_sec = 0;
    431   timeout.tv_usec = kCaptureTimeoutUs;
    432 
    433   // First argument to select is the highest numbered file descriptor +1.
    434   // Refer to http://linux.die.net/man/2/select for more information.
    435   int result = select(device_fd_ + 1, &r_set, NULL, NULL, &timeout);
    436   // Check if select have failed.
    437   if (result < 0) {
    438     // EINTR is a signal. This is not really an error.
    439     if (errno != EINTR) {
    440       SetErrorState("Select failed");
    441       return;
    442     }
    443     v4l2_thread_.message_loop()->PostDelayedTask(
    444         FROM_HERE,
    445         base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
    446                    base::Unretained(this)),
    447         base::TimeDelta::FromMilliseconds(kCaptureSelectWaitMs));
    448   }
    449 
    450   // Check if select timeout.
    451   if (result == 0) {
    452     timeout_count_++;
    453     if (timeout_count_ >= kContinuousTimeoutLimit) {
    454       SetErrorState(base::StringPrintf(
    455           "Continuous timeout %d times", timeout_count_));
    456       timeout_count_ = 0;
    457       return;
    458     }
    459   } else {
    460     timeout_count_ = 0;
    461   }
    462 
    463   // Check if the driver have filled a buffer.
    464   if (FD_ISSET(device_fd_, &r_set)) {
    465     v4l2_buffer buffer;
    466     memset(&buffer, 0, sizeof(buffer));
    467     buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    468     buffer.memory = V4L2_MEMORY_MMAP;
    469     // Dequeue a buffer.
    470     if (ioctl(device_fd_, VIDIOC_DQBUF, &buffer) == 0) {
    471       observer_->OnIncomingCapturedFrame(
    472           static_cast<uint8*> (buffer_pool_[buffer.index].start),
    473           buffer.bytesused, base::Time::Now(), 0, false, false);
    474 
    475       // Enqueue the buffer again.
    476       if (ioctl(device_fd_, VIDIOC_QBUF, &buffer) == -1) {
    477         SetErrorState(base::StringPrintf(
    478             "Failed to enqueue capture buffer errno %d", errno));
    479       }
    480     } else {
    481       SetErrorState(base::StringPrintf(
    482           "Failed to dequeue capture buffer errno %d", errno));
    483       return;
    484     }
    485   }
    486 
    487   v4l2_thread_.message_loop()->PostTask(
    488       FROM_HERE,
    489       base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
    490                  base::Unretained(this)));
    491 }
    492 
    493 bool VideoCaptureDeviceLinux::AllocateVideoBuffers() {
    494   v4l2_requestbuffers r_buffer;
    495   memset(&r_buffer, 0, sizeof(r_buffer));
    496 
    497   r_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    498   r_buffer.memory = V4L2_MEMORY_MMAP;
    499   r_buffer.count = kMaxVideoBuffers;
    500 
    501   if (ioctl(device_fd_, VIDIOC_REQBUFS, &r_buffer) < 0) {
    502     return false;
    503   }
    504 
    505   if (r_buffer.count > kMaxVideoBuffers) {
    506     r_buffer.count = kMaxVideoBuffers;
    507   }
    508 
    509   buffer_pool_size_ = r_buffer.count;
    510 
    511   // Map the buffers.
    512   buffer_pool_ = new Buffer[r_buffer.count];
    513   for (unsigned int i = 0; i < r_buffer.count; i++) {
    514     v4l2_buffer buffer;
    515     memset(&buffer, 0, sizeof(buffer));
    516     buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    517     buffer.memory = V4L2_MEMORY_MMAP;
    518     buffer.index = i;
    519 
    520     if (ioctl(device_fd_, VIDIOC_QUERYBUF, &buffer) < 0) {
    521       return false;
    522     }
    523 
    524     // Some devices require mmap() to be called with both READ and WRITE.
    525     // See crbug.com/178582.
    526     buffer_pool_[i].start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE,
    527                                  MAP_SHARED, device_fd_, buffer.m.offset);
    528     if (buffer_pool_[i].start == MAP_FAILED) {
    529       return false;
    530     }
    531     buffer_pool_[i].length = buffer.length;
    532     // Enqueue the buffer in the drivers incoming queue.
    533     if (ioctl(device_fd_, VIDIOC_QBUF, &buffer) < 0) {
    534       return false;
    535     }
    536   }
    537   return true;
    538 }
    539 
    540 void VideoCaptureDeviceLinux::DeAllocateVideoBuffers() {
    541   if (!buffer_pool_)
    542     return;
    543 
    544   // Unmaps buffers.
    545   for (int i = 0; i < buffer_pool_size_; i++) {
    546     munmap(buffer_pool_[i].start, buffer_pool_[i].length);
    547   }
    548   v4l2_requestbuffers r_buffer;
    549   memset(&r_buffer, 0, sizeof(r_buffer));
    550   r_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    551   r_buffer.memory = V4L2_MEMORY_MMAP;
    552   r_buffer.count = 0;
    553 
    554   if (ioctl(device_fd_, VIDIOC_REQBUFS, &r_buffer) < 0) {
    555     SetErrorState("Failed to reset buf.");
    556   }
    557 
    558   delete [] buffer_pool_;
    559   buffer_pool_ = NULL;
    560   buffer_pool_size_ = 0;
    561 }
    562 
    563 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) {
    564   DVLOG(1) << reason;
    565   state_ = kError;
    566   observer_->OnError();
    567 }
    568 
    569 }  // namespace media
    570