| 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 <linux/version.h> |
| 7 #include <poll.h> | 8 #include <poll.h> |
| 8 #include <sys/fcntl.h> | 9 #include <sys/fcntl.h> |
| 9 #include <sys/ioctl.h> | 10 #include <sys/ioctl.h> |
| 10 #include <sys/mman.h> | 11 #include <sys/mman.h> |
| 11 #include <utility> | 12 #include <utility> |
| 12 | 13 |
| 13 #include "base/bind.h" | 14 #include "base/bind.h" |
| 14 #include "base/files/file_enumerator.h" | 15 #include "base/files/file_enumerator.h" |
| 15 #include "base/posix/eintr_wrapper.h" | 16 #include "base/posix/eintr_wrapper.h" |
| 16 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 17 #include "build/build_config.h" | 18 #include "build/build_config.h" |
| 18 #include "media/base/bind_to_current_loop.h" | 19 #include "media/base/bind_to_current_loop.h" |
| 19 #include "media/capture/video/blob_utils.h" | 20 #include "media/capture/video/blob_utils.h" |
| 20 #include "media/capture/video/linux/video_capture_device_linux.h" | 21 #include "media/capture/video/linux/video_capture_device_linux.h" |
| 21 | 22 |
| 23 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) |
| 24 // 16 bit depth, Realsense F200. |
| 25 #define V4L2_PIX_FMT_Z16 v4l2_fourcc('Z', '1', '6', ' ') |
| 26 // 16 bit depth, Realsense SR300. |
| 27 #define V4L2_PIX_FMT_INVZ v4l2_fourcc('I', 'N', 'V', 'Z') |
| 28 #endif |
| 29 |
| 22 namespace media { | 30 namespace media { |
| 23 | 31 |
| 24 // Desired number of video buffers to allocate. The actual number of allocated | 32 // Desired number of video buffers to allocate. The actual number of allocated |
| 25 // buffers by v4l2 driver can be higher or lower than this number. | 33 // buffers by v4l2 driver can be higher or lower than this number. |
| 26 // kNumVideoBuffers should not be too small, or Chrome may not return enough | 34 // kNumVideoBuffers should not be too small, or Chrome may not return enough |
| 27 // buffers back to driver in time. | 35 // buffers back to driver in time. |
| 28 const uint32_t kNumVideoBuffers = 4; | 36 const uint32_t kNumVideoBuffers = 4; |
| 29 // Timeout in milliseconds v4l2_thread_ blocks waiting for a frame from the hw. | 37 // Timeout in milliseconds v4l2_thread_ blocks waiting for a frame from the hw. |
| 30 // This value has been fine tuned. Before changing or modifying it see | 38 // This value has been fine tuned. Before changing or modifying it see |
| 31 // https://crbug.com/470717 | 39 // https://crbug.com/470717 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 43 const int kZoomMultiplier = 100; | 51 const int kZoomMultiplier = 100; |
| 44 | 52 |
| 45 // V4L2 color formats supported by V4L2CaptureDelegate derived classes. | 53 // V4L2 color formats supported by V4L2CaptureDelegate derived classes. |
| 46 // This list is ordered by precedence of use -- but see caveats for MJPEG. | 54 // This list is ordered by precedence of use -- but see caveats for MJPEG. |
| 47 static struct { | 55 static struct { |
| 48 uint32_t fourcc; | 56 uint32_t fourcc; |
| 49 VideoPixelFormat pixel_format; | 57 VideoPixelFormat pixel_format; |
| 50 size_t num_planes; | 58 size_t num_planes; |
| 51 } const kSupportedFormatsAndPlanarity[] = { | 59 } const kSupportedFormatsAndPlanarity[] = { |
| 52 {V4L2_PIX_FMT_YUV420, PIXEL_FORMAT_I420, 1}, | 60 {V4L2_PIX_FMT_YUV420, PIXEL_FORMAT_I420, 1}, |
| 61 {V4L2_PIX_FMT_Y16, PIXEL_FORMAT_Y16, 1}, |
| 62 {V4L2_PIX_FMT_Z16, PIXEL_FORMAT_Y16, 1}, |
| 63 {V4L2_PIX_FMT_INVZ, PIXEL_FORMAT_Y16, 1}, |
| 53 {V4L2_PIX_FMT_YUYV, PIXEL_FORMAT_YUY2, 1}, | 64 {V4L2_PIX_FMT_YUYV, PIXEL_FORMAT_YUY2, 1}, |
| 54 {V4L2_PIX_FMT_UYVY, PIXEL_FORMAT_UYVY, 1}, | 65 {V4L2_PIX_FMT_UYVY, PIXEL_FORMAT_UYVY, 1}, |
| 55 {V4L2_PIX_FMT_RGB24, PIXEL_FORMAT_RGB24, 1}, | 66 {V4L2_PIX_FMT_RGB24, PIXEL_FORMAT_RGB24, 1}, |
| 56 // MJPEG is usually sitting fairly low since we don't want to have to | 67 // MJPEG is usually sitting fairly low since we don't want to have to |
| 57 // decode. However, it is needed for large resolutions due to USB bandwidth | 68 // decode. However, it is needed for large resolutions due to USB bandwidth |
| 58 // limitations, so GetListOfUsableFourCcs() can duplicate it on top, see | 69 // limitations, so GetListOfUsableFourCcs() can duplicate it on top, see |
| 59 // that method. | 70 // that method. |
| 60 {V4L2_PIX_FMT_MJPEG, PIXEL_FORMAT_MJPEG, 1}, | 71 {V4L2_PIX_FMT_MJPEG, PIXEL_FORMAT_MJPEG, 1}, |
| 61 // JPEG works as MJPEG on some gspca webcams from field reports, see | 72 // JPEG works as MJPEG on some gspca webcams from field reports, see |
| 62 // https://code.google.com/p/webrtc/issues/detail?id=529, put it as the | 73 // https://code.google.com/p/webrtc/issues/detail?id=529, put it as the |
| (...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 return; | 571 return; |
| 561 } | 572 } |
| 562 | 573 |
| 563 buffer_tracker_pool_[buffer.index]->set_payload_size(buffer.bytesused); | 574 buffer_tracker_pool_[buffer.index]->set_payload_size(buffer.bytesused); |
| 564 const scoped_refptr<BufferTracker>& buffer_tracker = | 575 const scoped_refptr<BufferTracker>& buffer_tracker = |
| 565 buffer_tracker_pool_[buffer.index]; | 576 buffer_tracker_pool_[buffer.index]; |
| 566 | 577 |
| 567 base::TimeDelta timestamp = | 578 base::TimeDelta timestamp = |
| 568 base::TimeDelta::FromSeconds(buffer.timestamp.tv_sec) + | 579 base::TimeDelta::FromSeconds(buffer.timestamp.tv_sec) + |
| 569 base::TimeDelta::FromMicroseconds(buffer.timestamp.tv_usec); | 580 base::TimeDelta::FromMicroseconds(buffer.timestamp.tv_usec); |
| 570 client_->OnIncomingCapturedData( | 581 #ifdef V4L2_BUF_FLAG_ERROR |
| 571 buffer_tracker->start(), buffer_tracker->payload_size(), | 582 if (buffer.flags & V4L2_BUF_FLAG_ERROR) { |
| 572 capture_format_, rotation_, base::TimeTicks::Now(), timestamp); | 583 LOG(ERROR) << "Dequeued v4l2 buffer contains corrupted data (" |
| 584 << buffer.bytesused << " bytes)."; |
| 585 buffer.bytesused = 0; |
| 586 } else |
| 587 #endif |
| 588 client_->OnIncomingCapturedData( |
| 589 buffer_tracker->start(), buffer_tracker->payload_size(), |
| 590 capture_format_, rotation_, base::TimeTicks::Now(), timestamp); |
| 573 | 591 |
| 574 while (!take_photo_callbacks_.empty()) { | 592 while (!take_photo_callbacks_.empty()) { |
| 575 VideoCaptureDevice::TakePhotoCallback cb = | 593 VideoCaptureDevice::TakePhotoCallback cb = |
| 576 std::move(take_photo_callbacks_.front()); | 594 std::move(take_photo_callbacks_.front()); |
| 577 take_photo_callbacks_.pop(); | 595 take_photo_callbacks_.pop(); |
| 578 | 596 |
| 579 mojom::BlobPtr blob = | 597 mojom::BlobPtr blob = |
| 580 Blobify(buffer_tracker->start(), buffer.bytesused, capture_format_); | 598 Blobify(buffer_tracker->start(), buffer.bytesused, capture_format_); |
| 581 if (blob) | 599 if (blob) |
| 582 cb.Run(std::move(blob)); | 600 cb.Run(std::move(blob)); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 619 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace"; | 637 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace"; |
| 620 return false; | 638 return false; |
| 621 } | 639 } |
| 622 start_ = static_cast<uint8_t*>(start); | 640 start_ = static_cast<uint8_t*>(start); |
| 623 length_ = buffer.length; | 641 length_ = buffer.length; |
| 624 payload_size_ = 0; | 642 payload_size_ = 0; |
| 625 return true; | 643 return true; |
| 626 } | 644 } |
| 627 | 645 |
| 628 } // namespace media | 646 } // namespace media |
| OLD | NEW |