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