OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/capture/video/linux/v4l2_capture_delegate.h" | 5 #include "media/capture/video/linux/v4l2_capture_delegate.h" |
6 | 6 |
7 #include <poll.h> | 7 #include <poll.h> |
8 #include <sys/fcntl.h> | 8 #include <sys/fcntl.h> |
9 #include <sys/ioctl.h> | 9 #include <sys/ioctl.h> |
10 #include <sys/mman.h> | 10 #include <sys/mman.h> |
11 #include <utility> | 11 #include <utility> |
12 | 12 |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/files/file_enumerator.h" | 14 #include "base/files/file_enumerator.h" |
15 #include "base/posix/eintr_wrapper.h" | 15 #include "base/posix/eintr_wrapper.h" |
16 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
17 #include "build/build_config.h" | 17 #include "build/build_config.h" |
18 #include "media/base/bind_to_current_loop.h" | 18 #include "media/base/bind_to_current_loop.h" |
19 #include "media/capture/video/linux/video_capture_device_linux.h" | 19 #include "media/capture/video/linux/video_capture_device_linux.h" |
20 | 20 |
| 21 // Until include/uapi/linux/videodev2.h defines V4L2_PIX_FMT_Z16/INVZ, define |
| 22 // them here. |
| 23 #ifndef V4L2_PIX_FMT_Z16 |
| 24 // 16 bit depth, Realsense F200. |
| 25 #define V4L2_PIX_FMT_Z16 v4l2_fourcc('Z', '1', '6', ' ') |
| 26 #endif |
| 27 #ifndef V4L2_PIX_FMT_INVZ |
| 28 // 16 bit depth, Realsense SR300. |
| 29 #define V4L2_PIX_FMT_INVZ v4l2_fourcc('I', 'N', 'V', 'Z') |
| 30 #endif |
| 31 |
21 namespace media { | 32 namespace media { |
22 | 33 |
23 // Desired number of video buffers to allocate. The actual number of allocated | 34 // Desired number of video buffers to allocate. The actual number of allocated |
24 // buffers by v4l2 driver can be higher or lower than this number. | 35 // buffers by v4l2 driver can be higher or lower than this number. |
25 // kNumVideoBuffers should not be too small, or Chrome may not return enough | 36 // kNumVideoBuffers should not be too small, or Chrome may not return enough |
26 // buffers back to driver in time. | 37 // buffers back to driver in time. |
27 const uint32_t kNumVideoBuffers = 4; | 38 const uint32_t kNumVideoBuffers = 4; |
28 // Timeout in milliseconds v4l2_thread_ blocks waiting for a frame from the hw. | 39 // Timeout in milliseconds v4l2_thread_ blocks waiting for a frame from the hw. |
29 // This value has been fine tuned. Before changing or modifying it see | 40 // This value has been fine tuned. Before changing or modifying it see |
30 // https://crbug.com/470717 | 41 // https://crbug.com/470717 |
31 const int kCaptureTimeoutMs = 1000; | 42 const int kCaptureTimeoutMs = 1000; |
32 // The number of continuous timeouts tolerated before treated as error. | 43 // The number of continuous timeouts tolerated before treated as error. |
33 const int kContinuousTimeoutLimit = 10; | 44 const int kContinuousTimeoutLimit = 10; |
34 // MJPEG is preferred if the requested width or height is larger than this. | 45 // MJPEG is preferred if the requested width or height is larger than this. |
35 const int kMjpegWidth = 640; | 46 const int kMjpegWidth = 640; |
36 const int kMjpegHeight = 480; | 47 const int kMjpegHeight = 480; |
37 // Typical framerate, in fps | 48 // Typical framerate, in fps |
38 const int kTypicalFramerate = 30; | 49 const int kTypicalFramerate = 30; |
39 | 50 |
40 // V4L2 color formats supported by V4L2CaptureDelegate derived classes. | 51 // V4L2 color formats supported by V4L2CaptureDelegate derived classes. |
41 // This list is ordered by precedence of use -- but see caveats for MJPEG. | 52 // This list is ordered by precedence of use -- but see caveats for MJPEG. |
42 static struct { | 53 static struct { |
43 uint32_t fourcc; | 54 uint32_t fourcc; |
44 VideoPixelFormat pixel_format; | 55 VideoPixelFormat pixel_format; |
45 size_t num_planes; | 56 size_t num_planes; |
46 } const kSupportedFormatsAndPlanarity[] = { | 57 } const kSupportedFormatsAndPlanarity[] = { |
47 {V4L2_PIX_FMT_YUV420, PIXEL_FORMAT_I420, 1}, | 58 {V4L2_PIX_FMT_YUV420, PIXEL_FORMAT_I420, 1}, |
| 59 {V4L2_PIX_FMT_GREY, PIXEL_FORMAT_Y8, 1}, |
| 60 {V4L2_PIX_FMT_Y16, PIXEL_FORMAT_Y16, 1}, |
| 61 {V4L2_PIX_FMT_Z16, PIXEL_FORMAT_Y16, 1}, |
| 62 {V4L2_PIX_FMT_INVZ, PIXEL_FORMAT_Y16, 1}, |
48 {V4L2_PIX_FMT_YUYV, PIXEL_FORMAT_YUY2, 1}, | 63 {V4L2_PIX_FMT_YUYV, PIXEL_FORMAT_YUY2, 1}, |
49 {V4L2_PIX_FMT_UYVY, PIXEL_FORMAT_UYVY, 1}, | 64 {V4L2_PIX_FMT_UYVY, PIXEL_FORMAT_UYVY, 1}, |
50 {V4L2_PIX_FMT_RGB24, PIXEL_FORMAT_RGB24, 1}, | 65 {V4L2_PIX_FMT_RGB24, PIXEL_FORMAT_RGB24, 1}, |
51 // MJPEG is usually sitting fairly low since we don't want to have to | 66 // MJPEG is usually sitting fairly low since we don't want to have to |
52 // decode. However, it is needed for large resolutions due to USB bandwidth | 67 // decode. However, it is needed for large resolutions due to USB bandwidth |
53 // limitations, so GetListOfUsableFourCcs() can duplicate it on top, see | 68 // limitations, so GetListOfUsableFourCcs() can duplicate it on top, see |
54 // that method. | 69 // that method. |
55 {V4L2_PIX_FMT_MJPEG, PIXEL_FORMAT_MJPEG, 1}, | 70 {V4L2_PIX_FMT_MJPEG, PIXEL_FORMAT_MJPEG, 1}, |
56 // JPEG works as MJPEG on some gspca webcams from field reports, see | 71 // JPEG works as MJPEG on some gspca webcams from field reports, see |
57 // https://code.google.com/p/webrtc/issues/detail?id=529, put it as the | 72 // https://code.google.com/p/webrtc/issues/detail?id=529, put it as the |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 return; | 405 return; |
391 } | 406 } |
392 | 407 |
393 buffer_tracker_pool_[buffer.index]->set_payload_size(buffer.bytesused); | 408 buffer_tracker_pool_[buffer.index]->set_payload_size(buffer.bytesused); |
394 const scoped_refptr<BufferTracker>& buffer_tracker = | 409 const scoped_refptr<BufferTracker>& buffer_tracker = |
395 buffer_tracker_pool_[buffer.index]; | 410 buffer_tracker_pool_[buffer.index]; |
396 | 411 |
397 base::TimeDelta timestamp = | 412 base::TimeDelta timestamp = |
398 base::TimeDelta::FromSeconds(buffer.timestamp.tv_sec) + | 413 base::TimeDelta::FromSeconds(buffer.timestamp.tv_sec) + |
399 base::TimeDelta::FromMicroseconds(buffer.timestamp.tv_usec); | 414 base::TimeDelta::FromMicroseconds(buffer.timestamp.tv_usec); |
400 client_->OnIncomingCapturedData( | 415 #ifdef V4L2_BUF_FLAG_ERROR |
401 buffer_tracker->start(), buffer_tracker->payload_size(), | 416 if (buffer.flags & V4L2_BUF_FLAG_ERROR) { |
402 capture_format_, rotation_, base::TimeTicks::Now(), timestamp); | 417 LOG(ERROR) << "Dequeued v4l2 buffer contains corrupted data (" |
| 418 << buffer.bytesused << " bytes)."; |
| 419 buffer.bytesused = 0; |
| 420 } else |
| 421 #endif |
| 422 client_->OnIncomingCapturedData( |
| 423 buffer_tracker->start(), buffer_tracker->payload_size(), |
| 424 capture_format_, rotation_, base::TimeTicks::Now(), timestamp); |
403 | 425 |
404 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) { | 426 if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) { |
405 SetErrorState(FROM_HERE, "Failed to enqueue capture buffer"); | 427 SetErrorState(FROM_HERE, "Failed to enqueue capture buffer"); |
406 return; | 428 return; |
407 } | 429 } |
408 } | 430 } |
409 | 431 |
410 v4l2_task_runner_->PostTask( | 432 v4l2_task_runner_->PostTask( |
411 FROM_HERE, base::Bind(&V4L2CaptureDelegate::DoCapture, this)); | 433 FROM_HERE, base::Bind(&V4L2CaptureDelegate::DoCapture, this)); |
412 } | 434 } |
(...skipping 25 matching lines...) Expand all Loading... |
438 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace"; | 460 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace"; |
439 return false; | 461 return false; |
440 } | 462 } |
441 start_ = static_cast<uint8_t*>(start); | 463 start_ = static_cast<uint8_t*>(start); |
442 length_ = buffer.length; | 464 length_ = buffer.length; |
443 payload_size_ = 0; | 465 payload_size_ = 0; |
444 return true; | 466 return true; |
445 } | 467 } |
446 | 468 |
447 } // namespace media | 469 } // namespace media |
OLD | NEW |