Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1330)

Unified Diff: media/video/capture/linux/v4l2_capture_delegate.cc

Issue 1124723006: VideoCaptureDeviceLinux: Add support for SPLANE+DMABUF V4L2 type capture (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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");

Powered by Google App Engine
This is Rietveld 408576698