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