Chromium Code Reviews| 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..066f8b26a8061d9cb9de776c0d2a175b48e8d00d 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,58 @@ static struct{ |
| {V4L2_PIX_FMT_JPEG, PIXEL_FORMAT_MJPEG, 1}, |
| }; |
| +// This function investigates if the driver and the underlying platform support |
| +// Dma-Buf and both have the appropriate format |
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) |
| +bool IsDmaBufCaptureSupported(const std::string& device_fd, |
|
Pawel Osciak
2015/06/15 10:34:54
static
s/device_fd/device_name/
mcasas
2015/06/17 01:30:53
Done.
|
| + VideoCaptureDevice::Client* client, |
| + v4l2_buf_type buf_type) { |
| + const base::ScopedFD fd(HANDLE_EINTR(open(device_fd.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) |
|
Pawel Osciak
2015/06/15 10:34:55
Unfortunately, we check if the V4L2 capturer suppo
mcasas
2015/06/17 01:30:52
This is true, and I think just landing this code "
|
| + return false; |
| + |
| + // Check if the platform supports Dma-Buf capture. |
| + scoped_ptr<VideoCaptureDevice::Client::Buffer> capture_buffer = |
| + client->ReserveOutputBuffer(media::PIXEL_FORMAT_GPUMEMORYBUFFER, |
|
Pawel Osciak
2015/06/15 10:34:55
This is not really a detail of V4L2 capture, so I
mcasas
2015/06/17 01:30:53
That sounds reasonable. As you can see, at the lev
|
| + gfx::Size(0, 0)); |
| + if (capture_buffer->GetType() != gfx::OZONE_NATIVE_BUFFER) |
| + return false; |
| + |
| + // TODO(mcasas): Check |capture_buffer|'s underlying supported formats and |
| + // correlate with those we support. For the time being, just continue. |
| + |
| + // TODO(mcasas): Query VCM to see if we have failed in the past to |
| + // initialize |
| + 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, |
| 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, |
| +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) |
| + false |
| +#else |
| + IsDmaBufCaptureSupported(device_name.id(), client, |
| + V4L2_BUF_TYPE_VIDEO_CAPTURE) |
| +#endif |
| + )); |
| case VideoCaptureDevice::Name::V4L2_MULTI_PLANE: |
| #if !defined(OS_OPENBSD) |
| return make_scoped_refptr(new V4L2CaptureDelegateMultiPlane( |
| @@ -142,6 +185,16 @@ void V4L2CaptureDelegate::BufferTracker::AddMmapedPlane(uint8_t* const start, |
| 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.start = nullptr; |
|
Pawel Osciak
2015/06/15 10:34:55
Zero-initialization could be done in Plane::Plane(
mcasas
2015/06/17 01:30:52
Done.
|
| + plane.length = 0u; |
| + plane.payload_size = 0; |
| + plane.fd = fd; |
| planes_.push_back(plane); |
| } |
| @@ -275,10 +328,10 @@ void V4L2CaptureDelegate::AllocateAndStart( |
| v4l2_requestbuffers r_buffer = {}; |
| r_buffer.type = capture_type_; |
| - r_buffer.memory = V4L2_MEMORY_MMAP; |
| r_buffer.count = kNumVideoBuffers; |
| + FinishFillingV4L2RequestBuffers(&r_buffer); |
|
Pawel Osciak
2015/06/15 10:34:55
I'd suggest just r_buffer.memory = memory(); if we
mcasas
2015/06/17 01:30:53
Done.
|
| 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 +367,8 @@ void V4L2CaptureDelegate::StopAndDeAllocate() { |
| v4l2_requestbuffers r_buffer = {}; |
| r_buffer.type = capture_type_; |
| - r_buffer.memory = V4L2_MEMORY_MMAP; |
| r_buffer.count = 0; |
| + FinishFillingV4L2RequestBuffers(&r_buffer); |
| if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) |
| SetErrorState("Failed to VIDIOC_REQBUFS with count = 0"); |
| @@ -334,7 +387,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 +410,11 @@ 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); |
| + FinishFillingV4L2Buffer(buffer, for_enqueue); |
| } |
| void V4L2CaptureDelegate::DoCapture() { |
| @@ -393,7 +446,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"); |