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

Side by Side Diff: media/video/capture/linux/v4l2_capture_delegate_single_plane.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 unified diff | Download patch
OLDNEW
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/video/capture/linux/v4l2_capture_delegate_single_plane.h" 5 #include "media/video/capture/linux/v4l2_capture_delegate_single_plane.h"
6 6
7 #include <linux/version.h>
7 #include <sys/mman.h> 8 #include <sys/mman.h>
8 9
9 namespace media { 10 namespace media {
10 11
12 V4L2CaptureDelegateSinglePlane::V4L2CaptureDelegateSinglePlane(
13 const VideoCaptureDevice::Name& device_name,
14 const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner,
15 int power_line_frequency,
16 bool try_to_use_dma_buf)
17 : V4L2CaptureDelegate(device_name, v4l2_task_runner, power_line_frequency) {
18 memory_type_ = V4L2_MEMORY_MMAP;
19 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
20 if (try_to_use_dma_buf)
21 memory_type_ = V4L2_MEMORY_DMABUF;
22 #endif
23 }
24
25 V4L2CaptureDelegateSinglePlane::~V4L2CaptureDelegateSinglePlane() {
26 }
27
11 scoped_refptr<V4L2CaptureDelegate::BufferTracker> 28 scoped_refptr<V4L2CaptureDelegate::BufferTracker>
12 V4L2CaptureDelegateSinglePlane::CreateBufferTracker() const { 29 V4L2CaptureDelegateSinglePlane::CreateBufferTracker() const {
13 return make_scoped_refptr(new BufferTrackerSPlane()); 30 return make_scoped_refptr(new BufferTrackerSPlane());
14 } 31 }
15 32
16 bool V4L2CaptureDelegateSinglePlane::FillV4L2Format( 33 bool V4L2CaptureDelegateSinglePlane::FillV4L2Format(
17 v4l2_format* format, 34 v4l2_format* format,
18 uint32_t width, 35 uint32_t width,
19 uint32_t height, 36 uint32_t height,
20 uint32_t pixelformat_fourcc) const { 37 uint32_t pixelformat_fourcc) const {
21 format->fmt.pix.width = width; 38 format->fmt.pix.width = width;
22 format->fmt.pix.height = height; 39 format->fmt.pix.height = height;
23 format->fmt.pix.pixelformat = pixelformat_fourcc; 40 format->fmt.pix.pixelformat = pixelformat_fourcc;
24 return true; 41 return true;
25 } 42 }
26 43
27 void V4L2CaptureDelegateSinglePlane::FinishFillingV4L2Buffer( 44 void V4L2CaptureDelegateSinglePlane::FinishFillingV4L2Buffer(
28 v4l2_buffer* buffer) const { 45 v4l2_buffer* buffer,
46 bool for_enqueue) const {
47 buffer->memory = memory_type_;
29 buffer->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 48 buffer->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
49
50 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
51 if (memory_type_ == V4L2_MEMORY_MMAP)
52 return;
53
54 if (!for_enqueue) {
55 DCHECK(buffer->m.fd); // For Dequeue, API should have filled |fd| in.
Pawel Osciak 2015/06/15 10:34:55 We call this before calling DQBUF, so it couldn't
mcasas 2015/06/17 01:30:53 First time this method is called, it's with |for_
56 return;
57 }
58 // For enqueueing, need to reserve an output buffer, keep it locally and pass
59 // its |fd| into the V4L2 API.
60 scoped_ptr<VideoCaptureDevice::Client::Buffer> capture_buffer =
Pawel Osciak 2015/06/15 10:34:55 Do we need to allocate buffers on each QBUF? Could
mcasas 2015/06/17 01:30:53 We don't allocate a Buffers on each QBUF, we Rese
61 client()->ReserveOutputBuffer(media::PIXEL_FORMAT_GPUMEMORYBUFFER,
62 capture_format().frame_size);
63 if (capture_buffer && capture_buffer->GetType() == gfx::OZONE_NATIVE_BUFFER) {
64 buffer->m.fd = capture_buffer->AsPlatformFile();
65
66 allocated_buffers_.push_back(capture_buffer.release());
67 DVLOG(1) << "Sizeof allocated_buffers_ " << allocated_buffers_.size();
68 } else {
69 DLOG(WARNING) << "Uh oh, platform does not support Dma-Buf allocation, "
Pawel Osciak 2015/06/15 10:34:55 We should propagate errors and SetErrorState() in
mcasas 2015/06/17 01:30:53 This is a Warning, and it was meant to be to help
70 << "or has run out of buffers :-?";
71 }
72 #endif
30 } 73 }
31 74
32 void V4L2CaptureDelegateSinglePlane::SetPayloadSize( 75 void V4L2CaptureDelegateSinglePlane::SetPayloadSize(
33 const scoped_refptr<BufferTracker>& buffer_tracker, 76 const scoped_refptr<BufferTracker>& buffer_tracker,
34 const v4l2_buffer& buffer) const { 77 const v4l2_buffer& buffer) const {
35 buffer_tracker->SetPlanePayloadSize(0, buffer.bytesused); 78 buffer_tracker->SetPlanePayloadSize(0, buffer.bytesused);
36 } 79 }
37 80
81 void V4L2CaptureDelegateSinglePlane::FinishFillingV4L2RequestBuffers(
82 v4l2_requestbuffers* request) const {
83 request->memory = memory_type_;
84 }
85
38 void V4L2CaptureDelegateSinglePlane::SendBuffer( 86 void V4L2CaptureDelegateSinglePlane::SendBuffer(
39 const scoped_refptr<BufferTracker>& buffer_tracker, 87 const scoped_refptr<BufferTracker>& buffer_tracker,
40 const v4l2_format& format) const { 88 const v4l2_format& format) const {
41 client()->OnIncomingCapturedData( 89 DVLOG(1) << __FUNCTION__;
42 buffer_tracker->GetPlaneStart(0), 90
91 if (memory_type_ == V4L2_MEMORY_MMAP) {
92 const size_t data_length = format.fmt.pix.sizeimage;
93 DCHECK_GE(data_length, capture_format().ImageAllocationSize());
94 client()->OnIncomingCapturedData(
95 buffer_tracker->GetPlaneStart(0),
43 buffer_tracker->GetPlanePayloadSize(0), 96 buffer_tracker->GetPlanePayloadSize(0),
44 capture_format(), 97 capture_format(),
45 rotation(), 98 rotation(),
46 base::TimeTicks::Now()); 99 base::TimeTicks::Now());
100 return;
101 }
102
103 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
104 // Search for the |fd| used for capture in |allocated_buffers_| and send it
105 // to client() if found. Otherwise is an error.
106 const int incoming_fd = buffer_tracker->GetFd(0);
107 ScopedVector<VideoCaptureDevice::Client::Buffer>::iterator used_buffer =
108 std::find_if(allocated_buffers_.begin(), allocated_buffers_.end(),
109 [incoming_fd](const VideoCaptureDevice::Client::Buffer* b) {
Pawel Osciak 2015/06/15 10:34:55 const Buffer& possible?
mcasas 2015/06/17 01:30:53 ScopedVector keeps pointers, from which you can ma
110 return incoming_fd == b->AsPlatformFile();
111 });
112 if (used_buffer == allocated_buffers_.end()) {
113 DLOG(ERROR) << "Uh oh, captured |fd| is not found in the list :?";
114 return;
Pawel Osciak 2015/06/15 10:34:55 Need to propagate the error.
mcasas 2015/06/17 01:30:53 Same as before, this was meant to be for helping
115 }
116 client()->OnIncomingCapturedBuffer(make_scoped_ptr(*used_buffer),
117 capture_format(), base::TimeTicks::Now());
118 allocated_buffers_.weak_erase(used_buffer);
Pawel Osciak 2015/06/15 10:34:55 Perhaps we could use std::vector<scoped_refptr<>>
mcasas 2015/06/17 01:30:53 I wish! ReserveOutputBuffer() returns a scoped_ptr
119 #endif
47 } 120 }
48 121
49 bool V4L2CaptureDelegateSinglePlane::BufferTrackerSPlane::Init( 122 bool V4L2CaptureDelegateSinglePlane::BufferTrackerSPlane::Init(
50 int fd, 123 int fd,
51 const v4l2_buffer& buffer) { 124 const v4l2_buffer& buffer) {
125 DVLOG(1) << __FUNCTION__;
126 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
127 if (buffer.memory == V4L2_MEMORY_DMABUF) {
128 AddNonMmapedPlane(buffer.m.fd);
Pawel Osciak 2015/06/15 10:34:55 Would it be possible to have one AddPlane() method
mcasas 2015/06/17 01:30:53 Wouldn't it move this ifdef somewhere else, and fo
129 return true;
130 }
131 #endif
132
52 // Some devices require mmap() to be called with both READ and WRITE. 133 // Some devices require mmap() to be called with both READ and WRITE.
53 // See http://crbug.com/178582. 134 // See http://crbug.com/178582.
54 void* const start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, 135 void* const start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE,
55 MAP_SHARED, fd, buffer.m.offset); 136 MAP_SHARED, fd, buffer.m.offset);
56 if (start == MAP_FAILED) { 137 if (start == MAP_FAILED) {
57 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace"; 138 DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace";
58 return false; 139 return false;
59 } 140 }
60 AddMmapedPlane(static_cast<uint8_t*>(start), buffer.length); 141 AddMmapedPlane(static_cast<uint8_t*>(start), buffer.length);
61 return true; 142 return true;
62 } 143 }
63 144
64 } // namespace media 145 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698