| Index: media/video/capture/linux/v4l2_capture_delegate.cc
|
| diff --git a/media/video/capture/linux/v4l2_capture_delegate.cc b/media/video/capture/linux/v4l2_capture_delegate.cc
|
| index bca49e68540d4e4ecca0e9f0c7922340a9ea050c..c42fbdd8cf94d9dab76877f5a7132838b3df0136 100644
|
| --- a/media/video/capture/linux/v4l2_capture_delegate.cc
|
| +++ b/media/video/capture/linux/v4l2_capture_delegate.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "media/video/capture/linux/v4l2_capture_delegate.h"
|
|
|
| +#include <linux/version.h>
|
| #include <poll.h>
|
| #include <sys/fcntl.h>
|
| #include <sys/ioctl.h>
|
| @@ -60,16 +61,44 @@ static struct{
|
| {V4L2_PIX_FMT_JPEG, PIXEL_FORMAT_MJPEG, 1},
|
| };
|
|
|
| +// This function investigates if the driver supports Dma-Buf. Such capacity is
|
| +// not present in non-Ozone platforms nor for certain kernel versions.
|
| +static bool IsDmaBufCaptureSupported(const std::string& device_name,
|
| + v4l2_buf_type buf_type) {
|
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) || !defined(USE_OZONE)
|
| + return false;
|
| +#else
|
| + const base::ScopedFD fd(HANDLE_EINTR(open(device_name.c_str(), O_RDONLY)));
|
| + if (!fd.is_valid()) {
|
| + return false;
|
| + }
|
| + // Check if the V4L2 device supports Dma Buf capture.
|
| + v4l2_requestbuffers r_buffer = {};
|
| + r_buffer.type = buf_type;
|
| + r_buffer.memory = V4L2_MEMORY_DMABUF;
|
| + r_buffer.count = 1u;
|
| + if (HANDLE_EINTR(ioctl(fd.get(), VIDIOC_REQBUFS, &r_buffer)) < 0)
|
| + return false;
|
| + return true;
|
| +#endif
|
| +}
|
| +
|
| // static
|
| scoped_refptr<V4L2CaptureDelegate>
|
| V4L2CaptureDelegate::CreateV4L2CaptureDelegate(
|
| const VideoCaptureDevice::Name& device_name,
|
| const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner,
|
| + VideoCaptureDevice::Client* client,
|
| + bool allow_using_dma_bufs,
|
| int power_line_frequency) {
|
| switch (device_name.capture_api_type()) {
|
| case VideoCaptureDevice::Name::V4L2_SINGLE_PLANE:
|
| return make_scoped_refptr(new V4L2CaptureDelegateSinglePlane(
|
| - device_name, v4l2_task_runner, power_line_frequency));
|
| + device_name, v4l2_task_runner,
|
| + power_line_frequency,
|
| + allow_using_dma_bufs &&
|
| + IsDmaBufCaptureSupported(device_name.id(),
|
| + V4L2_BUF_TYPE_VIDEO_CAPTURE)));
|
| case VideoCaptureDevice::Name::V4L2_MULTI_PLANE:
|
| #if !defined(OS_OPENBSD)
|
| return make_scoped_refptr(new V4L2CaptureDelegateMultiPlane(
|
| @@ -138,16 +167,24 @@ V4L2CaptureDelegate::BufferTracker::~BufferTracker() {
|
|
|
| void V4L2CaptureDelegate::BufferTracker::AddMmapedPlane(uint8_t* const start,
|
| size_t length) {
|
| - Plane plane;
|
| + Plane plane = {};
|
| plane.start = start;
|
| plane.length = length;
|
| plane.payload_size = 0;
|
| + plane.fd = -1;
|
| + planes_.push_back(plane);
|
| +}
|
| +
|
| +void V4L2CaptureDelegate::BufferTracker::AddNonMmapedPlane(int fd) {
|
| + Plane plane = {};
|
| + plane.fd = fd;
|
| planes_.push_back(plane);
|
| }
|
|
|
| V4L2CaptureDelegate::V4L2CaptureDelegate(
|
| const VideoCaptureDevice::Name& device_name,
|
| const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner,
|
| + v4l2_memory memory_type,
|
| int power_line_frequency)
|
| : capture_type_((device_name.capture_api_type() ==
|
| VideoCaptureDevice::Name::V4L2_SINGLE_PLANE)
|
| @@ -156,6 +193,7 @@ V4L2CaptureDelegate::V4L2CaptureDelegate(
|
| v4l2_task_runner_(v4l2_task_runner),
|
| device_name_(device_name),
|
| power_line_frequency_(power_line_frequency),
|
| + memory_type_(memory_type),
|
| is_capturing_(false),
|
| timeout_count_(0),
|
| rotation_(0) {
|
| @@ -275,10 +313,10 @@ void V4L2CaptureDelegate::AllocateAndStart(
|
|
|
| v4l2_requestbuffers r_buffer = {};
|
| r_buffer.type = capture_type_;
|
| - r_buffer.memory = V4L2_MEMORY_MMAP;
|
| r_buffer.count = kNumVideoBuffers;
|
| + r_buffer.memory = memory_type();
|
| if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) {
|
| - SetErrorState("Error requesting MMAP buffers from V4L2");
|
| + SetErrorState("Error requesting buffers from V4L2");
|
| return;
|
| }
|
| for (unsigned int i = 0; i < r_buffer.count; ++i) {
|
| @@ -314,8 +352,8 @@ void V4L2CaptureDelegate::StopAndDeAllocate() {
|
|
|
| v4l2_requestbuffers r_buffer = {};
|
| r_buffer.type = capture_type_;
|
| - r_buffer.memory = V4L2_MEMORY_MMAP;
|
| r_buffer.count = 0;
|
| + r_buffer.memory = memory_type();
|
| if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0)
|
| SetErrorState("Failed to VIDIOC_REQBUFS with count = 0");
|
|
|
| @@ -334,7 +372,7 @@ void V4L2CaptureDelegate::SetRotation(int rotation) {
|
|
|
| bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) {
|
| v4l2_buffer buffer;
|
| - FillV4L2Buffer(&buffer, index);
|
| + FillV4L2Buffer(&buffer, index, true /* for_enqueue */);
|
|
|
| if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYBUF, &buffer)) < 0) {
|
| DLOG(ERROR) << "Error querying status of a MMAP V4L2 buffer";
|
| @@ -357,11 +395,12 @@ bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) {
|
| }
|
|
|
| void V4L2CaptureDelegate::FillV4L2Buffer(v4l2_buffer* buffer,
|
| - int i) const {
|
| + int i,
|
| + bool for_enqueue) const {
|
| memset(buffer, 0, sizeof(*buffer));
|
| - buffer->memory = V4L2_MEMORY_MMAP;
|
| buffer->index = i;
|
| - FinishFillingV4L2Buffer(buffer);
|
| + buffer->memory = memory_type();
|
| + FinishFillingV4L2Buffer(buffer, for_enqueue);
|
| }
|
|
|
| void V4L2CaptureDelegate::DoCapture() {
|
| @@ -393,7 +432,7 @@ void V4L2CaptureDelegate::DoCapture() {
|
| // Deenqueue, send and reenqueue a buffer if the driver has filled one in.
|
| if (device_pfd.revents & POLLIN) {
|
| v4l2_buffer buffer;
|
| - FillV4L2Buffer(&buffer, 0);
|
| + FillV4L2Buffer(&buffer, 0, false /* for_enqueue */);
|
|
|
| if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) < 0) {
|
| SetErrorState("Failed to dequeue capture buffer");
|
|
|