1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "media/gpu/v4l2/v4l2_device.h"
6 
7 #include <fcntl.h>
8 #include <poll.h>
9 #include <linux/media.h>
10 #include <sys/ioctl.h>
11 
12 #include <algorithm>
13 #include <set>
14 
15 #include <libdrm/drm_fourcc.h>
16 #include <linux/videodev2.h>
17 #include <string.h>
18 #include <sys/mman.h>
19 #include <sstream>
20 
21 #include "base/bind.h"
22 #include "base/logging.h"
23 #include "base/numerics/safe_conversions.h"
24 #include "base/posix/eintr_wrapper.h"
25 #include "build/build_config.h"
26 #include "media/base/bind_to_current_loop.h"
27 #include "media/base/color_plane_layout.h"
28 #include "media/base/video_types.h"
29 #include "media/gpu/chromeos/fourcc.h"
30 #include "media/gpu/macros.h"
31 #include "media/gpu/v4l2/generic_v4l2_device.h"
32 #include "ui/gfx/native_pixmap_handle.h"
33 
34 #if defined(ARCH_CPU_ARMEL)
35 #include "media/gpu/v4l2/tegra_v4l2_device.h"
36 #endif
37 #if defined(AML_V4L2)
38 #include "media/gpu/v4l2/aml_v4l2_device.h"
39 #endif
40 
41 #define REQUEST_DEVICE "/dev/media-dec0"
42 
43 namespace media {
44 
45 namespace {
46 
47 // Maximum number of requests that can be created.
48 constexpr size_t kMaxNumRequests = 32;
49 
50 }  // namespace
51 
V4L2ExtCtrl(uint32_t id)52 V4L2ExtCtrl::V4L2ExtCtrl(uint32_t id) {
53   memset(&ctrl, 0, sizeof(ctrl));
54   ctrl.id = id;
55 }
56 
V4L2ExtCtrl(uint32_t id,int32_t val)57 V4L2ExtCtrl::V4L2ExtCtrl(uint32_t id, int32_t val) : V4L2ExtCtrl(id) {
58   ctrl.value = val;
59 }
60 
61 // Class used to store the state of a buffer that should persist between
62 // reference creations. This includes:
63 // * Result of initial VIDIOC_QUERYBUF ioctl,
64 // * Plane mappings.
65 //
66 // Also provides helper functions.
67 class V4L2Buffer {
68  public:
69   static std::unique_ptr<V4L2Buffer> Create(scoped_refptr<V4L2Device> device,
70                                             enum v4l2_buf_type type,
71                                             enum v4l2_memory memory,
72                                             const struct v4l2_format& format,
73                                             size_t buffer_id);
74   ~V4L2Buffer();
75 
76   void* GetPlaneMapping(const size_t plane);
77   size_t GetMemoryUsage() const;
v4l2_buffer() const78   const struct v4l2_buffer& v4l2_buffer() const { return v4l2_buffer_; }
79   scoped_refptr<VideoFrame> GetVideoFrame();
80 
81  private:
82   V4L2Buffer(scoped_refptr<V4L2Device> device,
83              enum v4l2_buf_type type,
84              enum v4l2_memory memory,
85              const struct v4l2_format& format,
86              size_t buffer_id);
87   bool Query();
88   scoped_refptr<VideoFrame> CreateVideoFrame();
89 
90   scoped_refptr<V4L2Device> device_;
91   std::vector<void*> plane_mappings_;
92 
93   // V4L2 data as queried by QUERYBUF.
94   struct v4l2_buffer v4l2_buffer_ = {};
95   // WARNING: do not change this to a vector or something smaller than
96   // VIDEO_MAX_PLANES, otherwise the Tegra libv4l2 will write data beyond
97   // the number of allocated planes, resulting in memory corruption.
98   struct v4l2_plane v4l2_planes_[VIDEO_MAX_PLANES] = {{}};
99 
100   struct v4l2_format format_;
101   scoped_refptr<VideoFrame> video_frame_;
102 
103   DISALLOW_COPY_AND_ASSIGN(V4L2Buffer);
104 };
105 
Create(scoped_refptr<V4L2Device> device,enum v4l2_buf_type type,enum v4l2_memory memory,const struct v4l2_format & format,size_t buffer_id)106 std::unique_ptr<V4L2Buffer> V4L2Buffer::Create(scoped_refptr<V4L2Device> device,
107                                                enum v4l2_buf_type type,
108                                                enum v4l2_memory memory,
109                                                const struct v4l2_format& format,
110                                                size_t buffer_id) {
111   // Not using std::make_unique because constructor is private.
112   std::unique_ptr<V4L2Buffer> buffer(
113       new V4L2Buffer(device, type, memory, format, buffer_id));
114 
115   if (!buffer->Query())
116     return nullptr;
117 
118   return buffer;
119 }
120 
V4L2Buffer(scoped_refptr<V4L2Device> device,enum v4l2_buf_type type,enum v4l2_memory memory,const struct v4l2_format & format,size_t buffer_id)121 V4L2Buffer::V4L2Buffer(scoped_refptr<V4L2Device> device,
122                        enum v4l2_buf_type type,
123                        enum v4l2_memory memory,
124                        const struct v4l2_format& format,
125                        size_t buffer_id)
126     : device_(device), format_(format) {
127   DCHECK(V4L2_TYPE_IS_MULTIPLANAR(type));
128   DCHECK_LE(format.fmt.pix_mp.num_planes, base::size(v4l2_planes_));
129   v4l2_buffer_.m.planes = v4l2_planes_;
130   // Just in case we got more planes than we want.
131   v4l2_buffer_.length =
132       std::min(static_cast<size_t>(format.fmt.pix_mp.num_planes),
133                base::size(v4l2_planes_));
134   v4l2_buffer_.index = buffer_id;
135   v4l2_buffer_.type = type;
136   v4l2_buffer_.memory = memory;
137   plane_mappings_.resize(v4l2_buffer_.length);
138 }
139 
~V4L2Buffer()140 V4L2Buffer::~V4L2Buffer() {
141   if (v4l2_buffer_.memory == V4L2_MEMORY_MMAP) {
142     for (size_t i = 0; i < plane_mappings_.size(); i++)
143       if (plane_mappings_[i] != nullptr)
144         device_->Munmap(plane_mappings_[i], v4l2_buffer_.m.planes[i].length);
145   }
146 }
147 
Query()148 bool V4L2Buffer::Query() {
149   int ret = device_->Ioctl(VIDIOC_QUERYBUF, &v4l2_buffer_);
150   if (ret) {
151     VPLOGF(1) << "VIDIOC_QUERYBUF failed: ";
152     return false;
153   }
154 
155   DCHECK(plane_mappings_.size() == v4l2_buffer_.length);
156 
157   return true;
158 }
159 
GetPlaneMapping(const size_t plane)160 void* V4L2Buffer::GetPlaneMapping(const size_t plane) {
161   if (plane >= plane_mappings_.size()) {
162     VLOGF(1) << "Invalid plane " << plane << " requested.";
163     return nullptr;
164   }
165 
166   void* p = plane_mappings_[plane];
167   if (p)
168     return p;
169 
170   // Do this check here to avoid repeating it after a buffer has been
171   // successfully mapped (we know we are of MMAP type by then).
172   if (v4l2_buffer_.memory != V4L2_MEMORY_MMAP) {
173     VLOGF(1) << "Cannot create mapping on non-MMAP buffer";
174     return nullptr;
175   }
176 
177   p = device_->Mmap(NULL, v4l2_buffer_.m.planes[plane].length,
178                     PROT_READ | PROT_WRITE, MAP_SHARED,
179                     v4l2_buffer_.m.planes[plane].m.mem_offset);
180   if (p == MAP_FAILED) {
181     VPLOGF(1) << "mmap() failed: ";
182     return nullptr;
183   }
184 
185   plane_mappings_[plane] = p;
186   return p;
187 }
188 
GetMemoryUsage() const189 size_t V4L2Buffer::GetMemoryUsage() const {
190   size_t usage = 0;
191   for (size_t i = 0; i < v4l2_buffer_.length; i++) {
192     usage += v4l2_buffer_.m.planes[i].length;
193   }
194   return usage;
195 }
196 
CreateVideoFrame()197 scoped_refptr<VideoFrame> V4L2Buffer::CreateVideoFrame() {
198   auto layout = V4L2Device::V4L2FormatToVideoFrameLayout(format_);
199   if (!layout) {
200     VLOGF(1) << "Cannot create frame layout for V4L2 buffers";
201     return nullptr;
202   }
203 
204   std::vector<base::ScopedFD> dmabuf_fds = device_->GetDmabufsForV4L2Buffer(
205       v4l2_buffer_.index, v4l2_buffer_.length,
206       static_cast<enum v4l2_buf_type>(v4l2_buffer_.type));
207   if (dmabuf_fds.empty()) {
208     VLOGF(1) << "Failed to get DMABUFs of V4L2 buffer";
209     return nullptr;
210   }
211 
212   // Duplicate the fd of the last v4l2 plane until the number of fds are the
213   // same as the number of color planes.
214   while (dmabuf_fds.size() != layout->planes().size()) {
215     int duped_fd = -1;
216     // Fd in dmabuf_fds is invalid with TegraV4L2Device. An invalid fd is added
217     // in the case.
218     if (dmabuf_fds.back().is_valid()) {
219       duped_fd = HANDLE_EINTR(dup(dmabuf_fds.back().get()));
220       if (duped_fd == -1) {
221         DLOG(ERROR) << "Failed duplicating dmabuf fd";
222         return nullptr;
223       }
224     }
225 
226     dmabuf_fds.emplace_back(duped_fd);
227   }
228 
229   gfx::Size size(format_.fmt.pix_mp.width, format_.fmt.pix_mp.height);
230 
231   return VideoFrame::WrapExternalDmabufs(
232       *layout, gfx::Rect(size), size, std::move(dmabuf_fds), base::TimeDelta());
233 }
234 
GetVideoFrame()235 scoped_refptr<VideoFrame> V4L2Buffer::GetVideoFrame() {
236   // We can create the VideoFrame only when using MMAP buffers.
237   if (v4l2_buffer_.memory != V4L2_MEMORY_MMAP) {
238     VLOGF(1) << "Cannot create video frame from non-MMAP buffer";
239     // video_frame_ should be null since that's its default value.
240     DCHECK_EQ(video_frame_, nullptr);
241     return video_frame_;
242   }
243 
244   // Create the video frame instance if requiring it for the first time.
245   if (!video_frame_)
246     video_frame_ = CreateVideoFrame();
247 
248   return video_frame_;
249 }
250 
251 // A thread-safe pool of buffer indexes, allowing buffers to be obtained and
252 // returned from different threads. All the methods of this class are
253 // thread-safe. Users should keep a scoped_refptr to instances of this class
254 // in order to ensure the list remains alive as long as they need it.
255 class V4L2BuffersList : public base::RefCountedThreadSafe<V4L2BuffersList> {
256  public:
257   V4L2BuffersList() = default;
258   // Return a buffer to this list. Also can be called to set the initial pool
259   // of buffers.
260   // Note that it is illegal to return the same buffer twice.
261   void ReturnBuffer(size_t buffer_id);
262   // Get any of the buffers in the list. There is no order guarantee whatsoever.
263   base::Optional<size_t> GetFreeBuffer();
264   // Number of buffers currently in this list.
265   size_t size() const;
266 
267  private:
268   friend class base::RefCountedThreadSafe<V4L2BuffersList>;
269   ~V4L2BuffersList() = default;
270 
271   mutable base::Lock lock_;
272   std::set<size_t> free_buffers_ GUARDED_BY(lock_);
273   DISALLOW_COPY_AND_ASSIGN(V4L2BuffersList);
274 };
275 
ReturnBuffer(size_t buffer_id)276 void V4L2BuffersList::ReturnBuffer(size_t buffer_id) {
277   base::AutoLock auto_lock(lock_);
278 
279   auto inserted = free_buffers_.emplace(buffer_id);
280   DCHECK(inserted.second);
281 }
282 
GetFreeBuffer()283 base::Optional<size_t> V4L2BuffersList::GetFreeBuffer() {
284   base::AutoLock auto_lock(lock_);
285 
286   auto iter = free_buffers_.begin();
287   if (iter == free_buffers_.end()) {
288     DVLOGF(4) << "No free buffer available!";
289     return base::nullopt;
290   }
291 
292   size_t buffer_id = *iter;
293   free_buffers_.erase(iter);
294 
295   return buffer_id;
296 }
297 
size() const298 size_t V4L2BuffersList::size() const {
299   base::AutoLock auto_lock(lock_);
300 
301   return free_buffers_.size();
302 }
303 
304 // Module-private class that let users query/write V4L2 buffer information.
305 // It also makes some private V4L2Queue methods available to this module only.
306 class V4L2BufferRefBase {
307  public:
308   V4L2BufferRefBase(const struct v4l2_buffer& v4l2_buffer,
309                     base::WeakPtr<V4L2Queue> queue);
310   ~V4L2BufferRefBase();
311 
312   bool QueueBuffer();
313   void* GetPlaneMapping(const size_t plane);
314 
315   scoped_refptr<VideoFrame> GetVideoFrame();
316   // Checks that the number of passed FDs is adequate for the current format
317   // and buffer configuration. Only useful for DMABUF buffers.
318   bool CheckNumFDsForFormat(const size_t num_fds) const;
319 
320   // Data from the buffer, that users can query and/or write.
321   struct v4l2_buffer v4l2_buffer_;
322   // WARNING: do not change this to a vector or something smaller than
323   // VIDEO_MAX_PLANES, otherwise the Tegra libv4l2 will write data beyond
324   // the number of allocated planes, resulting in memory corruption.
325   struct v4l2_plane v4l2_planes_[VIDEO_MAX_PLANES];
326 
327  private:
BufferId() const328   size_t BufferId() const { return v4l2_buffer_.index; }
329 
330   friend class V4L2WritableBufferRef;
331   // A weak pointer to the queue this buffer belongs to. Will remain valid as
332   // long as the underlying V4L2 buffer is valid too.
333   // This can only be accessed from the sequence protected by sequence_checker_.
334   // Thread-safe methods (like ~V4L2BufferRefBase) must *never* access this.
335   base::WeakPtr<V4L2Queue> queue_;
336   // Where to return this buffer if it goes out of scope without being queued.
337   scoped_refptr<V4L2BuffersList> return_to_;
338   bool queued = false;
339 
340   SEQUENCE_CHECKER(sequence_checker_);
341   DISALLOW_COPY_AND_ASSIGN(V4L2BufferRefBase);
342 };
343 
V4L2BufferRefBase(const struct v4l2_buffer & v4l2_buffer,base::WeakPtr<V4L2Queue> queue)344 V4L2BufferRefBase::V4L2BufferRefBase(const struct v4l2_buffer& v4l2_buffer,
345                                      base::WeakPtr<V4L2Queue> queue)
346     : queue_(std::move(queue)), return_to_(queue_->free_buffers_) {
347   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
348   DCHECK(V4L2_TYPE_IS_MULTIPLANAR(v4l2_buffer.type));
349   DCHECK_LE(v4l2_buffer.length, base::size(v4l2_planes_));
350   DCHECK(return_to_);
351 
352   memcpy(&v4l2_buffer_, &v4l2_buffer, sizeof(v4l2_buffer_));
353   memcpy(v4l2_planes_, v4l2_buffer.m.planes,
354          sizeof(struct v4l2_plane) * v4l2_buffer.length);
355   v4l2_buffer_.m.planes = v4l2_planes_;
356 }
357 
~V4L2BufferRefBase()358 V4L2BufferRefBase::~V4L2BufferRefBase() {
359   // We are the last reference and are only accessing the thread-safe
360   // return_to_, so we are safe to call from any sequence.
361   // If we have been queued, then the queue is our owner so we don't need to
362   // return to the free buffers list.
363   if (!queued)
364     return_to_->ReturnBuffer(BufferId());
365 }
366 
QueueBuffer()367 bool V4L2BufferRefBase::QueueBuffer() {
368   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
369 
370   if (!queue_)
371     return false;
372 
373   queued = queue_->QueueBuffer(&v4l2_buffer_);
374 
375   return queued;
376 }
377 
GetPlaneMapping(const size_t plane)378 void* V4L2BufferRefBase::GetPlaneMapping(const size_t plane) {
379   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
380 
381   if (!queue_)
382     return nullptr;
383 
384   return queue_->buffers_[BufferId()]->GetPlaneMapping(plane);
385 }
386 
GetVideoFrame()387 scoped_refptr<VideoFrame> V4L2BufferRefBase::GetVideoFrame() {
388   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
389 
390   // Used so we can return a const scoped_refptr& in all cases.
391   static const scoped_refptr<VideoFrame> null_videoframe;
392 
393   if (!queue_)
394     return null_videoframe;
395 
396   DCHECK_LE(BufferId(), queue_->buffers_.size());
397 
398   return queue_->buffers_[BufferId()]->GetVideoFrame();
399 }
400 
CheckNumFDsForFormat(const size_t num_fds) const401 bool V4L2BufferRefBase::CheckNumFDsForFormat(const size_t num_fds) const {
402   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
403 
404   if (!queue_)
405     return false;
406 
407   // We have not used SetFormat(), assume this is ok.
408   // Hopefully we standardize SetFormat() in the future.
409   if (!queue_->current_format_)
410     return true;
411 
412   const size_t required_fds = queue_->current_format_->fmt.pix_mp.num_planes;
413   // Sanity check.
414   DCHECK_EQ(v4l2_buffer_.length, required_fds);
415   if (num_fds < required_fds) {
416     VLOGF(1) << "Insufficient number of FDs given for the current format. "
417              << num_fds << " provided, " << required_fds << " required.";
418     return false;
419   }
420 
421   const auto* planes = v4l2_buffer_.m.planes;
422   for (size_t i = v4l2_buffer_.length - 1; i >= num_fds; --i) {
423     // Assume that an fd is a duplicate of a previous plane's fd if offset != 0.
424     // Otherwise, if offset == 0, return error as it is likely pointing to
425     // a new plane.
426     if (planes[i].data_offset == 0) {
427       VLOGF(1) << "Additional dmabuf fds point to a new buffer.";
428       return false;
429     }
430   }
431 
432   return true;
433 }
434 
V4L2WritableBufferRef(const struct v4l2_buffer & v4l2_buffer,base::WeakPtr<V4L2Queue> queue)435 V4L2WritableBufferRef::V4L2WritableBufferRef(
436     const struct v4l2_buffer& v4l2_buffer,
437     base::WeakPtr<V4L2Queue> queue)
438     : buffer_data_(
439           std::make_unique<V4L2BufferRefBase>(v4l2_buffer, std::move(queue))) {
440   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
441 }
442 
V4L2WritableBufferRef(V4L2WritableBufferRef && other)443 V4L2WritableBufferRef::V4L2WritableBufferRef(V4L2WritableBufferRef&& other)
444     : buffer_data_(std::move(other.buffer_data_)) {
445   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
446   DCHECK_CALLED_ON_VALID_SEQUENCE(other.sequence_checker_);
447 }
448 
~V4L2WritableBufferRef()449 V4L2WritableBufferRef::~V4L2WritableBufferRef() {
450   // Only valid references should be sequence-checked
451   if (buffer_data_) {
452     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
453   }
454 }
455 
operator =(V4L2WritableBufferRef && other)456 V4L2WritableBufferRef& V4L2WritableBufferRef::operator=(
457     V4L2WritableBufferRef&& other) {
458   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
459   DCHECK_CALLED_ON_VALID_SEQUENCE(other.sequence_checker_);
460 
461   if (this == &other)
462     return *this;
463 
464   buffer_data_ = std::move(other.buffer_data_);
465 
466   return *this;
467 }
468 
GetVideoFrame()469 scoped_refptr<VideoFrame> V4L2WritableBufferRef::GetVideoFrame() {
470   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
471   DCHECK(buffer_data_);
472 
473   return buffer_data_->GetVideoFrame();
474 }
475 
Memory() const476 enum v4l2_memory V4L2WritableBufferRef::Memory() const {
477   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
478   DCHECK(buffer_data_);
479 
480   return static_cast<enum v4l2_memory>(buffer_data_->v4l2_buffer_.memory);
481 }
482 
DoQueue(V4L2RequestRef * request_ref)483 bool V4L2WritableBufferRef::DoQueue(V4L2RequestRef* request_ref) && {
484   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
485   DCHECK(buffer_data_);
486 
487   if (request_ref && buffer_data_->queue_->SupportsRequests())
488     request_ref->ApplyQueueBuffer(&(buffer_data_->v4l2_buffer_));
489 
490   bool queued = buffer_data_->QueueBuffer();
491 
492   // Clear our own reference.
493   buffer_data_.reset();
494 
495   return queued;
496 }
497 
QueueMMap(V4L2RequestRef * request_ref)498 bool V4L2WritableBufferRef::QueueMMap(
499     V4L2RequestRef* request_ref) && {
500   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
501   DCHECK(buffer_data_);
502 
503   // Move ourselves so our data gets freed no matter when we return
504   V4L2WritableBufferRef self(std::move(*this));
505 
506   if (self.Memory() != V4L2_MEMORY_MMAP) {
507     VLOGF(1) << "Called on invalid buffer type!";
508     return false;
509   }
510 
511   return std::move(self).DoQueue(request_ref);
512 }
513 
QueueUserPtr(const std::vector<void * > & ptrs,V4L2RequestRef * request_ref)514 bool V4L2WritableBufferRef::QueueUserPtr(
515     const std::vector<void*>& ptrs,
516     V4L2RequestRef* request_ref) && {
517   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
518   DCHECK(buffer_data_);
519 
520   // Move ourselves so our data gets freed no matter when we return
521   V4L2WritableBufferRef self(std::move(*this));
522 
523   if (self.Memory() != V4L2_MEMORY_USERPTR) {
524     VLOGF(1) << "Called on invalid buffer type!";
525     return false;
526   }
527 
528   if (ptrs.size() != self.PlanesCount()) {
529     VLOGF(1) << "Provided " << ptrs.size() << " pointers while we require "
530              << self.buffer_data_->v4l2_buffer_.length << ".";
531     return false;
532   }
533 
534   for (size_t i = 0; i < ptrs.size(); i++)
535     self.buffer_data_->v4l2_buffer_.m.planes[i].m.userptr =
536         reinterpret_cast<unsigned long>(ptrs[i]);
537 
538   return std::move(self).DoQueue(request_ref);
539 }
540 
QueueDMABuf(const std::vector<base::ScopedFD> & fds,V4L2RequestRef * request_ref)541 bool V4L2WritableBufferRef::QueueDMABuf(
542     const std::vector<base::ScopedFD>& fds,
543     V4L2RequestRef* request_ref) && {
544   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
545   DCHECK(buffer_data_);
546 
547   // Move ourselves so our data gets freed no matter when we return
548   V4L2WritableBufferRef self(std::move(*this));
549 
550   if (self.Memory() != V4L2_MEMORY_DMABUF) {
551     VLOGF(1) << "Called on invalid buffer type!";
552     return false;
553   }
554 
555   if (!self.buffer_data_->CheckNumFDsForFormat(fds.size()))
556     return false;
557 
558   size_t num_planes = self.PlanesCount();
559   for (size_t i = 0; i < num_planes; i++)
560     self.buffer_data_->v4l2_buffer_.m.planes[i].m.fd = fds[i].get();
561 
562   return std::move(self).DoQueue(request_ref);
563 }
564 
QueueDMABuf(const std::vector<gfx::NativePixmapPlane> & planes,V4L2RequestRef * request_ref)565 bool V4L2WritableBufferRef::QueueDMABuf(
566     const std::vector<gfx::NativePixmapPlane>& planes,
567     V4L2RequestRef* request_ref) && {
568   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
569   DCHECK(buffer_data_);
570 
571   // Move ourselves so our data gets freed no matter when we return
572   V4L2WritableBufferRef self(std::move(*this));
573 
574   if (self.Memory() != V4L2_MEMORY_DMABUF) {
575     VLOGF(1) << "Called on invalid buffer type!";
576     return false;
577   }
578 
579   if (!self.buffer_data_->CheckNumFDsForFormat(planes.size()))
580     return false;
581 
582   size_t num_planes = self.PlanesCount();
583   for (size_t i = 0; i < num_planes; i++)
584     self.buffer_data_->v4l2_buffer_.m.planes[i].m.fd = planes[i].fd.get();
585 
586   return std::move(self).DoQueue(request_ref);
587 }
588 
PlanesCount() const589 size_t V4L2WritableBufferRef::PlanesCount() const {
590   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
591   DCHECK(buffer_data_);
592 
593   return buffer_data_->v4l2_buffer_.length;
594 }
595 
GetPlaneSize(const size_t plane) const596 size_t V4L2WritableBufferRef::GetPlaneSize(const size_t plane) const {
597   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
598   DCHECK(buffer_data_);
599 
600   if (plane >= PlanesCount()) {
601     VLOGF(1) << "Invalid plane " << plane << " requested.";
602     return 0;
603   }
604 
605   return buffer_data_->v4l2_buffer_.m.planes[plane].length;
606 }
607 
SetPlaneSize(const size_t plane,const size_t size)608 void V4L2WritableBufferRef::SetPlaneSize(const size_t plane,
609                                          const size_t size) {
610   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
611   DCHECK(buffer_data_);
612 
613   enum v4l2_memory memory = Memory();
614   if (memory == V4L2_MEMORY_MMAP) {
615     DCHECK_EQ(buffer_data_->v4l2_buffer_.m.planes[plane].length, size);
616     return;
617   }
618   DCHECK(memory == V4L2_MEMORY_USERPTR || memory == V4L2_MEMORY_DMABUF);
619 
620   if (plane >= PlanesCount()) {
621     VLOGF(1) << "Invalid plane " << plane << " requested.";
622     return;
623   }
624 
625   buffer_data_->v4l2_buffer_.m.planes[plane].length = size;
626 }
627 
GetPlaneMapping(const size_t plane)628 void* V4L2WritableBufferRef::GetPlaneMapping(const size_t plane) {
629   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
630   DCHECK(buffer_data_);
631 
632   return buffer_data_->GetPlaneMapping(plane);
633 }
634 
SetTimeStamp(const struct timeval & timestamp)635 void V4L2WritableBufferRef::SetTimeStamp(const struct timeval& timestamp) {
636   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
637   DCHECK(buffer_data_);
638 
639   buffer_data_->v4l2_buffer_.timestamp = timestamp;
640 }
641 
GetTimeStamp() const642 const struct timeval& V4L2WritableBufferRef::GetTimeStamp() const {
643   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
644   DCHECK(buffer_data_);
645 
646   return buffer_data_->v4l2_buffer_.timestamp;
647 }
648 
SetPlaneBytesUsed(const size_t plane,const size_t bytes_used)649 void V4L2WritableBufferRef::SetPlaneBytesUsed(const size_t plane,
650                                               const size_t bytes_used) {
651   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
652   DCHECK(buffer_data_);
653 
654   if (plane >= PlanesCount()) {
655     VLOGF(1) << "Invalid plane " << plane << " requested.";
656     return;
657   }
658 
659   if (bytes_used > GetPlaneSize(plane)) {
660     VLOGF(1) << "Set bytes used " << bytes_used << " larger than plane size "
661              << GetPlaneSize(plane) << ".";
662     return;
663   }
664 
665   buffer_data_->v4l2_buffer_.m.planes[plane].bytesused = bytes_used;
666 }
667 
GetPlaneBytesUsed(const size_t plane) const668 size_t V4L2WritableBufferRef::GetPlaneBytesUsed(const size_t plane) const {
669   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
670   DCHECK(buffer_data_);
671 
672   if (plane >= PlanesCount()) {
673     VLOGF(1) << "Invalid plane " << plane << " requested.";
674     return 0;
675   }
676 
677   return buffer_data_->v4l2_buffer_.m.planes[plane].bytesused;
678 }
679 
SetPlaneDataOffset(const size_t plane,const size_t data_offset)680 void V4L2WritableBufferRef::SetPlaneDataOffset(const size_t plane,
681                                                const size_t data_offset) {
682   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
683   DCHECK(buffer_data_);
684 
685   if (plane >= PlanesCount()) {
686     VLOGF(1) << "Invalid plane " << plane << " requested.";
687     return;
688   }
689 
690   buffer_data_->v4l2_buffer_.m.planes[plane].data_offset = data_offset;
691 }
692 
BufferId() const693 size_t V4L2WritableBufferRef::BufferId() const {
694   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
695   DCHECK(buffer_data_);
696 
697   return buffer_data_->v4l2_buffer_.index;
698 }
699 
SetConfigStore(uint32_t config_store)700 void V4L2WritableBufferRef::SetConfigStore(uint32_t config_store) {
701   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
702   DCHECK(buffer_data_);
703 
704   buffer_data_->v4l2_buffer_.config_store = config_store;
705 }
706 
V4L2ReadableBuffer(const struct v4l2_buffer & v4l2_buffer,base::WeakPtr<V4L2Queue> queue)707 V4L2ReadableBuffer::V4L2ReadableBuffer(const struct v4l2_buffer& v4l2_buffer,
708                                        base::WeakPtr<V4L2Queue> queue)
709     : buffer_data_(
710           std::make_unique<V4L2BufferRefBase>(v4l2_buffer, std::move(queue))) {
711   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
712 }
713 
GetVideoFrame()714 scoped_refptr<VideoFrame> V4L2ReadableBuffer::GetVideoFrame() {
715   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
716 
717   return buffer_data_->GetVideoFrame();
718 }
719 
~V4L2ReadableBuffer()720 V4L2ReadableBuffer::~V4L2ReadableBuffer() {
721   // This method is thread-safe. Since we are the destructor, we are guaranteed
722   // to be called from the only remaining reference to us. Also, we are just
723   // calling the destructor of buffer_data_, which is also thread-safe.
724   DCHECK(buffer_data_);
725 }
726 
IsLast() const727 bool V4L2ReadableBuffer::IsLast() const {
728   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
729   DCHECK(buffer_data_);
730 
731   return buffer_data_->v4l2_buffer_.flags & V4L2_BUF_FLAG_LAST;
732 }
733 
IsKeyframe() const734 bool V4L2ReadableBuffer::IsKeyframe() const {
735   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
736   DCHECK(buffer_data_);
737 
738   return buffer_data_->v4l2_buffer_.flags & V4L2_BUF_FLAG_KEYFRAME;
739 }
740 
GetTimeStamp() const741 struct timeval V4L2ReadableBuffer::GetTimeStamp() const {
742   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
743   DCHECK(buffer_data_);
744 
745   return buffer_data_->v4l2_buffer_.timestamp;
746 }
747 
PlanesCount() const748 size_t V4L2ReadableBuffer::PlanesCount() const {
749   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
750   DCHECK(buffer_data_);
751 
752   return buffer_data_->v4l2_buffer_.length;
753 }
754 
GetPlaneMapping(const size_t plane) const755 const void* V4L2ReadableBuffer::GetPlaneMapping(const size_t plane) const {
756   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
757   DCHECK(buffer_data_);
758 
759   return buffer_data_->GetPlaneMapping(plane);
760 }
761 
GetPlaneBytesUsed(const size_t plane) const762 size_t V4L2ReadableBuffer::GetPlaneBytesUsed(const size_t plane) const {
763   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
764   DCHECK(buffer_data_);
765 
766   if (plane >= PlanesCount()) {
767     VLOGF(1) << "Invalid plane " << plane << " requested.";
768     return 0;
769   }
770 
771   return buffer_data_->v4l2_planes_[plane].bytesused;
772 }
773 
GetPlaneDataOffset(const size_t plane) const774 size_t V4L2ReadableBuffer::GetPlaneDataOffset(const size_t plane) const {
775   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
776   DCHECK(buffer_data_);
777 
778   if (plane >= PlanesCount()) {
779     VLOGF(1) << "Invalid plane " << plane << " requested.";
780     return 0;
781   }
782 
783   return buffer_data_->v4l2_planes_[plane].data_offset;
784 }
785 
BufferId() const786 size_t V4L2ReadableBuffer::BufferId() const {
787   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
788   DCHECK(buffer_data_);
789 
790   return buffer_data_->v4l2_buffer_.index;
791 }
792 
793 // This class is used to expose buffer reference classes constructors to
794 // this module. This is to ensure that nobody else can create buffer references.
795 class V4L2BufferRefFactory {
796  public:
CreateWritableRef(const struct v4l2_buffer & v4l2_buffer,base::WeakPtr<V4L2Queue> queue)797   static V4L2WritableBufferRef CreateWritableRef(
798       const struct v4l2_buffer& v4l2_buffer,
799       base::WeakPtr<V4L2Queue> queue) {
800     return V4L2WritableBufferRef(v4l2_buffer, std::move(queue));
801   }
802 
CreateReadableRef(const struct v4l2_buffer & v4l2_buffer,base::WeakPtr<V4L2Queue> queue)803   static V4L2ReadableBufferRef CreateReadableRef(
804       const struct v4l2_buffer& v4l2_buffer,
805       base::WeakPtr<V4L2Queue> queue) {
806     return new V4L2ReadableBuffer(v4l2_buffer, std::move(queue));
807   }
808 };
809 
810 // Helper macros that print the queue type with logs.
811 #define VPQLOGF(level) \
812   VPLOGF(level) << "(" << V4L2Device::V4L2BufferTypeToString(type_) << ") "
813 #define VQLOGF(level) \
814   VLOGF(level) << "(" << V4L2Device::V4L2BufferTypeToString(type_) << ") "
815 #define DVQLOGF(level) \
816   DVLOGF(level) << "(" << V4L2Device::V4L2BufferTypeToString(type_) << ") "
817 
V4L2Queue(scoped_refptr<V4L2Device> dev,enum v4l2_buf_type type,base::OnceClosure destroy_cb)818 V4L2Queue::V4L2Queue(scoped_refptr<V4L2Device> dev,
819                      enum v4l2_buf_type type,
820                      base::OnceClosure destroy_cb)
821     : type_(type),
822       device_(dev),
823       destroy_cb_(std::move(destroy_cb)),
824       weak_this_factory_(this) {
825   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
826 
827   // Check if this queue support requests.
828   struct v4l2_requestbuffers reqbufs;
829   memset(&reqbufs, 0, sizeof(reqbufs));
830   reqbufs.count = 0;
831   reqbufs.type = type;
832   reqbufs.memory = V4L2_MEMORY_MMAP;
833   if (device_->Ioctl(VIDIOC_REQBUFS, &reqbufs) != 0) {
834     VPLOGF(1) << "Request support checks's VIDIOC_REQBUFS ioctl failed.";
835     return;
836   }
837 
838   if (reqbufs.capabilities & V4L2_BUF_CAP_SUPPORTS_REQUESTS) {
839     supports_requests_ = true;
840     DVLOGF(4) << "Queue supports request API.";
841   }
842 }
843 
~V4L2Queue()844 V4L2Queue::~V4L2Queue() {
845   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
846 
847   if (is_streaming_) {
848     VQLOGF(1) << "Queue is still streaming, trying to stop it...";
849     Streamoff();
850   }
851 
852   DCHECK(queued_buffers_.empty());
853   DCHECK(!free_buffers_);
854 
855   if (!buffers_.empty()) {
856     VQLOGF(1) << "Buffers are still allocated, trying to deallocate them...";
857     DeallocateBuffers();
858   }
859 
860   std::move(destroy_cb_).Run();
861 }
862 
SetFormat(uint32_t fourcc,const gfx::Size & size,size_t buffer_size)863 base::Optional<struct v4l2_format> V4L2Queue::SetFormat(uint32_t fourcc,
864                                                         const gfx::Size& size,
865                                                         size_t buffer_size) {
866   struct v4l2_format format = {};
867   format.type = type_;
868   format.fmt.pix_mp.pixelformat = fourcc;
869   format.fmt.pix_mp.width = size.width();
870   format.fmt.pix_mp.height = size.height();
871   format.fmt.pix_mp.num_planes = V4L2Device::GetNumPlanesOfV4L2PixFmt(fourcc);
872   format.fmt.pix_mp.plane_fmt[0].sizeimage = buffer_size;
873   if (device_->Ioctl(VIDIOC_S_FMT, &format) != 0 ||
874       format.fmt.pix_mp.pixelformat != fourcc) {
875     VPQLOGF(2) << "Failed to set format (format_fourcc=0x" << std::hex << fourcc
876                << ")";
877     return base::nullopt;
878   }
879 
880   current_format_ = format;
881   return current_format_;
882 }
883 
AllocateBuffers(size_t count,enum v4l2_memory memory)884 size_t V4L2Queue::AllocateBuffers(size_t count, enum v4l2_memory memory) {
885   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
886   DCHECK(!free_buffers_);
887   DCHECK_EQ(queued_buffers_.size(), 0u);
888 
889   if (IsStreaming()) {
890     VQLOGF(1) << "Cannot allocate buffers while streaming.";
891     return 0;
892   }
893 
894   if (buffers_.size() != 0) {
895     VQLOGF(1)
896         << "Cannot allocate new buffers while others are still allocated.";
897     return 0;
898   }
899 
900   if (count == 0) {
901     VQLOGF(1) << "Attempting to allocate 0 buffers.";
902     return 0;
903   }
904 
905   // First query the number of planes in the buffers we are about to request.
906   // This should not be required, but Tegra's VIDIOC_QUERYBUF will fail on
907   // output buffers if the number of specified planes does not exactly match the
908   // format.
909   struct v4l2_format format = {.type = type_};
910   int ret = device_->Ioctl(VIDIOC_G_FMT, &format);
911   if (ret) {
912     VPQLOGF(1) << "VIDIOC_G_FMT failed";
913     return 0;
914   }
915   planes_count_ = format.fmt.pix_mp.num_planes;
916   DCHECK_LE(planes_count_, static_cast<size_t>(VIDEO_MAX_PLANES));
917 
918   struct v4l2_requestbuffers reqbufs = {};
919   reqbufs.count = count;
920   reqbufs.type = type_;
921   reqbufs.memory = memory;
922   DVQLOGF(3) << "Requesting " << count << " buffers.";
923 
924   ret = device_->Ioctl(VIDIOC_REQBUFS, &reqbufs);
925   if (ret) {
926     VPQLOGF(1) << "VIDIOC_REQBUFS failed";
927     return 0;
928   }
929   DVQLOGF(3) << "queue " << type_ << ": got " << reqbufs.count << " buffers.";
930 
931   memory_ = memory;
932 
933   free_buffers_ = new V4L2BuffersList();
934 
935   // Now query all buffer information.
936   for (size_t i = 0; i < reqbufs.count; i++) {
937     auto buffer = V4L2Buffer::Create(device_, type_, memory_, format, i);
938 
939     if (!buffer) {
940       DeallocateBuffers();
941 
942       return 0;
943     }
944 
945     buffers_.emplace_back(std::move(buffer));
946     free_buffers_->ReturnBuffer(i);
947   }
948 
949   DCHECK(free_buffers_);
950   DCHECK_EQ(free_buffers_->size(), buffers_.size());
951   DCHECK_EQ(queued_buffers_.size(), 0u);
952 
953   return buffers_.size();
954 }
955 
DeallocateBuffers()956 bool V4L2Queue::DeallocateBuffers() {
957   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
958 
959   if (IsStreaming()) {
960     VQLOGF(1) << "Cannot deallocate buffers while streaming.";
961     return false;
962   }
963 
964   if (buffers_.size() == 0)
965     return true;
966 
967   weak_this_factory_.InvalidateWeakPtrs();
968   buffers_.clear();
969   free_buffers_ = nullptr;
970 
971   // Free all buffers.
972   struct v4l2_requestbuffers reqbufs = {};
973   reqbufs.count = 0;
974   reqbufs.type = type_;
975   reqbufs.memory = memory_;
976 
977   int ret = device_->Ioctl(VIDIOC_REQBUFS, &reqbufs);
978   if (ret) {
979     VPQLOGF(1) << "VIDIOC_REQBUFS failed";
980     return false;
981   }
982 
983   DCHECK(!free_buffers_);
984   DCHECK_EQ(queued_buffers_.size(), 0u);
985 
986   return true;
987 }
988 
GetMemoryUsage() const989 size_t V4L2Queue::GetMemoryUsage() const {
990   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
991   size_t usage = 0;
992   for (const auto& buf : buffers_) {
993     usage += buf->GetMemoryUsage();
994   }
995   return usage;
996 }
997 
GetMemoryType() const998 v4l2_memory V4L2Queue::GetMemoryType() const {
999   return memory_;
1000 }
1001 
GetFreeBuffer()1002 base::Optional<V4L2WritableBufferRef> V4L2Queue::GetFreeBuffer() {
1003   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1004 
1005   // No buffers allocated at the moment?
1006   if (!free_buffers_)
1007     return base::nullopt;
1008 
1009   auto buffer_id = free_buffers_->GetFreeBuffer();
1010   if (!buffer_id.has_value())
1011     return base::nullopt;
1012 
1013   return V4L2BufferRefFactory::CreateWritableRef(
1014       buffers_[buffer_id.value()]->v4l2_buffer(),
1015       weak_this_factory_.GetWeakPtr());
1016 }
1017 
QueueBuffer(struct v4l2_buffer * v4l2_buffer)1018 bool V4L2Queue::QueueBuffer(struct v4l2_buffer* v4l2_buffer) {
1019   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1020 
1021   int ret = device_->Ioctl(VIDIOC_QBUF, v4l2_buffer);
1022   if (ret) {
1023     VPQLOGF(1) << "VIDIOC_QBUF failed";
1024     return false;
1025   }
1026 
1027   auto inserted = queued_buffers_.emplace(v4l2_buffer->index);
1028   DCHECK_EQ(inserted.second, true);
1029 
1030   device_->SchedulePoll();
1031 
1032   return true;
1033 }
1034 
DequeueBuffer()1035 std::pair<bool, V4L2ReadableBufferRef> V4L2Queue::DequeueBuffer() {
1036   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1037 
1038   // No need to dequeue if no buffers queued.
1039   if (QueuedBuffersCount() == 0)
1040     return std::make_pair(true, nullptr);
1041 
1042   if (!IsStreaming()) {
1043     VQLOGF(1) << "Attempting to dequeue a buffer while not streaming.";
1044     return std::make_pair(true, nullptr);
1045   }
1046 
1047   struct v4l2_buffer v4l2_buffer = {};
1048   // WARNING: do not change this to a vector or something smaller than
1049   // VIDEO_MAX_PLANES, otherwise the Tegra libv4l2 will write data beyond
1050   // the number of allocated planes, resulting in memory corruption.
1051   struct v4l2_plane planes[VIDEO_MAX_PLANES] = {{}};
1052   v4l2_buffer.type = type_;
1053   v4l2_buffer.memory = memory_;
1054   v4l2_buffer.m.planes = planes;
1055   v4l2_buffer.length = planes_count_;
1056   int ret = device_->Ioctl(VIDIOC_DQBUF, &v4l2_buffer);
1057   if (ret) {
1058     // TODO(acourbot): we should not have to check for EPIPE as codec clients
1059     // should not call this method after the last buffer is dequeued.
1060     switch (errno) {
1061       case EAGAIN:
1062       case EPIPE:
1063         // This is not an error so we'll need to continue polling but won't
1064         // provide a buffer.
1065         device_->SchedulePoll();
1066         return std::make_pair(true, nullptr);
1067       default:
1068         VPQLOGF(1) << "VIDIOC_DQBUF failed";
1069         return std::make_pair(false, nullptr);
1070     }
1071   }
1072 
1073   auto it = queued_buffers_.find(v4l2_buffer.index);
1074   DCHECK(it != queued_buffers_.end());
1075   queued_buffers_.erase(*it);
1076 
1077   if (QueuedBuffersCount() > 0)
1078     device_->SchedulePoll();
1079 
1080   DCHECK(free_buffers_);
1081   return std::make_pair(true,
1082                         V4L2BufferRefFactory::CreateReadableRef(
1083                             v4l2_buffer, weak_this_factory_.GetWeakPtr()));
1084 }
1085 
IsStreaming() const1086 bool V4L2Queue::IsStreaming() const {
1087   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1088 
1089   return is_streaming_;
1090 }
1091 
Streamon()1092 bool V4L2Queue::Streamon() {
1093   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1094 
1095   if (is_streaming_)
1096     return true;
1097 
1098   int arg = static_cast<int>(type_);
1099   int ret = device_->Ioctl(VIDIOC_STREAMON, &arg);
1100   if (ret) {
1101     VPQLOGF(1) << "VIDIOC_STREAMON failed";
1102     return false;
1103   }
1104 
1105   is_streaming_ = true;
1106 
1107   return true;
1108 }
1109 
Streamoff()1110 bool V4L2Queue::Streamoff() {
1111   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1112 
1113   // We do not check the value of IsStreaming(), because we may have queued
1114   // buffers to the queue and wish to get them back - in such as case, we may
1115   // need to do a VIDIOC_STREAMOFF on a stopped queue.
1116 
1117   int arg = static_cast<int>(type_);
1118   int ret = device_->Ioctl(VIDIOC_STREAMOFF, &arg);
1119   if (ret) {
1120     VPQLOGF(1) << "VIDIOC_STREAMOFF failed";
1121     return false;
1122   }
1123 
1124   for (const auto& buffer_id : queued_buffers_) {
1125     DCHECK(free_buffers_);
1126     free_buffers_->ReturnBuffer(buffer_id);
1127   }
1128 
1129   queued_buffers_.clear();
1130 
1131   is_streaming_ = false;
1132 
1133   return true;
1134 }
1135 
AllocatedBuffersCount() const1136 size_t V4L2Queue::AllocatedBuffersCount() const {
1137   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1138 
1139   return buffers_.size();
1140 }
1141 
FreeBuffersCount() const1142 size_t V4L2Queue::FreeBuffersCount() const {
1143   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1144 
1145   return free_buffers_ ? free_buffers_->size() : 0;
1146 }
1147 
QueuedBuffersCount() const1148 size_t V4L2Queue::QueuedBuffersCount() const {
1149   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1150 
1151   return queued_buffers_.size();
1152 }
1153 
1154 #undef VDQLOGF
1155 #undef VPQLOGF
1156 #undef VQLOGF
1157 
SupportsRequests()1158 bool V4L2Queue::SupportsRequests() {
1159   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1160 
1161   return supports_requests_;
1162 }
1163 
1164 // This class is used to expose V4L2Queue's constructor to this module. This is
1165 // to ensure that nobody else can create instances of it.
1166 class V4L2QueueFactory {
1167  public:
CreateQueue(scoped_refptr<V4L2Device> dev,enum v4l2_buf_type type,base::OnceClosure destroy_cb)1168   static scoped_refptr<V4L2Queue> CreateQueue(scoped_refptr<V4L2Device> dev,
1169                                               enum v4l2_buf_type type,
1170                                               base::OnceClosure destroy_cb) {
1171     return new V4L2Queue(std::move(dev), type, std::move(destroy_cb));
1172   }
1173 };
1174 
V4L2Device()1175 V4L2Device::V4L2Device() {
1176   DETACH_FROM_SEQUENCE(client_sequence_checker_);
1177 }
1178 
~V4L2Device()1179 V4L2Device::~V4L2Device() {}
1180 
GetQueue(enum v4l2_buf_type type)1181 scoped_refptr<V4L2Queue> V4L2Device::GetQueue(enum v4l2_buf_type type) {
1182   DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
1183 
1184   switch (type) {
1185     // Supported queue types.
1186     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1187     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1188       break;
1189     default:
1190       VLOGF(1) << "Unsupported V4L2 queue type: " << type;
1191       return nullptr;
1192   }
1193 
1194   // TODO(acourbot): we should instead query the device for available queues,
1195   // and allocate them accordingly. This will do for now though.
1196   auto it = queues_.find(type);
1197   if (it != queues_.end())
1198     return scoped_refptr<V4L2Queue>(it->second);
1199 
1200   scoped_refptr<V4L2Queue> queue = V4L2QueueFactory::CreateQueue(
1201       this, type, base::BindOnce(&V4L2Device::OnQueueDestroyed, this, type));
1202 
1203   queues_[type] = queue.get();
1204   return queue;
1205 }
1206 
OnQueueDestroyed(v4l2_buf_type buf_type)1207 void V4L2Device::OnQueueDestroyed(v4l2_buf_type buf_type) {
1208   DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
1209 
1210   auto it = queues_.find(buf_type);
1211   DCHECK(it != queues_.end());
1212   queues_.erase(it);
1213 }
1214 
1215 // static
Create()1216 scoped_refptr<V4L2Device> V4L2Device::Create() {
1217   DVLOGF(3);
1218 
1219   scoped_refptr<V4L2Device> device;
1220 
1221 #if defined(ARCH_CPU_ARMEL)
1222   device = new TegraV4L2Device();
1223   if (device->Initialize())
1224     return device;
1225 #endif
1226 
1227 #if defined(AML_V4L2)
1228   device = new AmlV4L2Device();
1229   if (device->Initialize())
1230     return device;
1231 #endif
1232 
1233   device = new GenericV4L2Device();
1234   if (device->Initialize())
1235     return device;
1236 
1237   VLOGF(1) << "Failed to create a V4L2Device";
1238   return nullptr;
1239 }
1240 
1241 // static
VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile,bool slice_based)1242 uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile,
1243                                                    bool slice_based) {
1244   if (profile >= H264PROFILE_MIN && profile <= H264PROFILE_MAX) {
1245     if (slice_based)
1246       return V4L2_PIX_FMT_H264_SLICE;
1247     else
1248       return V4L2_PIX_FMT_H264;
1249   } else if (profile >= VP8PROFILE_MIN && profile <= VP8PROFILE_MAX) {
1250     if (slice_based)
1251       return V4L2_PIX_FMT_VP8_FRAME;
1252     else
1253       return V4L2_PIX_FMT_VP8;
1254   } else if (profile >= VP9PROFILE_MIN && profile <= VP9PROFILE_MAX) {
1255     if (slice_based)
1256       return V4L2_PIX_FMT_VP9_FRAME;
1257     else
1258       return V4L2_PIX_FMT_VP9;
1259   } else {
1260     LOG(ERROR) << "Unknown profile: " << GetProfileName(profile);
1261     return 0;
1262   }
1263 }
1264 
1265 // static
V4L2ProfileToVideoCodecProfile(VideoCodec codec,uint32_t profile)1266 VideoCodecProfile V4L2Device::V4L2ProfileToVideoCodecProfile(VideoCodec codec,
1267                                                              uint32_t profile) {
1268   switch (codec) {
1269     case kCodecH264:
1270       switch (profile) {
1271         case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
1272         case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
1273           return H264PROFILE_BASELINE;
1274         case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
1275           return H264PROFILE_MAIN;
1276         case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
1277           return H264PROFILE_EXTENDED;
1278         case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
1279           return H264PROFILE_HIGH;
1280       }
1281       break;
1282     case kCodecVP8:
1283       switch (profile) {
1284         case V4L2_MPEG_VIDEO_VP8_PROFILE_0:
1285         case V4L2_MPEG_VIDEO_VP8_PROFILE_1:
1286         case V4L2_MPEG_VIDEO_VP8_PROFILE_2:
1287         case V4L2_MPEG_VIDEO_VP8_PROFILE_3:
1288           return VP8PROFILE_ANY;
1289       }
1290       break;
1291     case kCodecVP9:
1292       switch (profile) {
1293         case V4L2_MPEG_VIDEO_VP9_PROFILE_0:
1294           return VP9PROFILE_PROFILE0;
1295         case V4L2_MPEG_VIDEO_VP9_PROFILE_1:
1296           return VP9PROFILE_PROFILE1;
1297         case V4L2_MPEG_VIDEO_VP9_PROFILE_2:
1298           return VP9PROFILE_PROFILE2;
1299         case V4L2_MPEG_VIDEO_VP9_PROFILE_3:
1300           return VP9PROFILE_PROFILE3;
1301       }
1302       break;
1303     default:
1304       VLOGF(2) << "Unknown codec: " << codec;
1305   }
1306   VLOGF(2) << "Unknown profile: " << profile;
1307   return VIDEO_CODEC_PROFILE_UNKNOWN;
1308 }
1309 
V4L2PixFmtToVideoCodecProfiles(uint32_t pix_fmt,bool is_encoder)1310 std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles(
1311     uint32_t pix_fmt,
1312     bool is_encoder) {
1313   auto get_supported_profiles = [this](
1314                                     VideoCodec codec,
1315                                     std::vector<VideoCodecProfile>* profiles) {
1316     uint32_t query_id = 0;
1317     switch (codec) {
1318       case kCodecH264:
1319         query_id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
1320         break;
1321       case kCodecVP8:
1322         query_id = V4L2_CID_MPEG_VIDEO_VP8_PROFILE;
1323         break;
1324       case kCodecVP9:
1325         query_id = V4L2_CID_MPEG_VIDEO_VP9_PROFILE;
1326         break;
1327       default:
1328         return false;
1329     }
1330 
1331     v4l2_queryctrl query_ctrl = {};
1332     query_ctrl.id = query_id;
1333     if (Ioctl(VIDIOC_QUERYCTRL, &query_ctrl) != 0) {
1334       return false;
1335     }
1336     v4l2_querymenu query_menu = {};
1337     query_menu.id = query_ctrl.id;
1338     for (query_menu.index = query_ctrl.minimum;
1339          static_cast<int>(query_menu.index) <= query_ctrl.maximum;
1340          query_menu.index++) {
1341       if (Ioctl(VIDIOC_QUERYMENU, &query_menu) == 0) {
1342         const VideoCodecProfile profile =
1343             V4L2Device::V4L2ProfileToVideoCodecProfile(codec, query_menu.index);
1344         if (profile != VIDEO_CODEC_PROFILE_UNKNOWN)
1345           profiles->push_back(profile);
1346       }
1347     }
1348     return true;
1349   };
1350 
1351   std::vector<VideoCodecProfile> profiles;
1352   switch (pix_fmt) {
1353     case V4L2_PIX_FMT_H264:
1354     case V4L2_PIX_FMT_H264_SLICE:
1355       if (!get_supported_profiles(kCodecH264, &profiles)) {
1356         DLOG(WARNING) << "Driver doesn't support QUERY H264 profiles, "
1357                       << "use default values, Base, Main, High";
1358         profiles = {
1359             H264PROFILE_BASELINE,
1360             H264PROFILE_MAIN,
1361             H264PROFILE_HIGH,
1362         };
1363       }
1364       break;
1365     case V4L2_PIX_FMT_VP8:
1366     case V4L2_PIX_FMT_VP8_FRAME:
1367       profiles = {VP8PROFILE_ANY};
1368       break;
1369     case V4L2_PIX_FMT_VP9:
1370     case V4L2_PIX_FMT_VP9_FRAME:
1371       if (!get_supported_profiles(kCodecVP9, &profiles)) {
1372         DLOG(WARNING) << "Driver doesn't support QUERY VP9 profiles, "
1373                       << "use default values, Profile0";
1374         profiles = {VP9PROFILE_PROFILE0};
1375       }
1376       break;
1377     default:
1378       VLOGF(1) << "Unhandled pixelformat " << FourccToString(pix_fmt);
1379       return {};
1380   }
1381 
1382   // Erase duplicated profiles.
1383   std::sort(profiles.begin(), profiles.end());
1384   profiles.erase(std::unique(profiles.begin(), profiles.end()), profiles.end());
1385   return profiles;
1386 }
1387 
1388 // static
V4L2PixFmtToDrmFormat(uint32_t format)1389 uint32_t V4L2Device::V4L2PixFmtToDrmFormat(uint32_t format) {
1390   switch (format) {
1391     case V4L2_PIX_FMT_NV12:
1392     case V4L2_PIX_FMT_NV12M:
1393       return DRM_FORMAT_NV12;
1394 
1395     case V4L2_PIX_FMT_YUV420:
1396     case V4L2_PIX_FMT_YUV420M:
1397       return DRM_FORMAT_YUV420;
1398 
1399     case V4L2_PIX_FMT_YVU420:
1400       return DRM_FORMAT_YVU420;
1401 
1402     case V4L2_PIX_FMT_RGB32:
1403       return DRM_FORMAT_ARGB8888;
1404 
1405     default:
1406       DVLOGF(1) << "Unrecognized format " << FourccToString(format);
1407       return 0;
1408   }
1409 }
1410 
1411 // static
VideoCodecProfileToV4L2H264Profile(VideoCodecProfile profile)1412 int32_t V4L2Device::VideoCodecProfileToV4L2H264Profile(
1413     VideoCodecProfile profile) {
1414   switch (profile) {
1415     case H264PROFILE_BASELINE:
1416       return V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
1417     case H264PROFILE_MAIN:
1418       return V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
1419     case H264PROFILE_EXTENDED:
1420       return V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED;
1421     case H264PROFILE_HIGH:
1422       return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
1423     case H264PROFILE_HIGH10PROFILE:
1424       return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10;
1425     case H264PROFILE_HIGH422PROFILE:
1426       return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422;
1427     case H264PROFILE_HIGH444PREDICTIVEPROFILE:
1428       return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE;
1429     case H264PROFILE_SCALABLEBASELINE:
1430       return V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE;
1431     case H264PROFILE_SCALABLEHIGH:
1432       return V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH;
1433     case H264PROFILE_STEREOHIGH:
1434       return V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH;
1435     case H264PROFILE_MULTIVIEWHIGH:
1436       return V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH;
1437     default:
1438       DVLOGF(1) << "Add more cases as needed";
1439       return -1;
1440   }
1441 }
1442 
1443 // static
H264LevelIdcToV4L2H264Level(uint8_t level_idc)1444 int32_t V4L2Device::H264LevelIdcToV4L2H264Level(uint8_t level_idc) {
1445   switch (level_idc) {
1446     case 10:
1447       return V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
1448     case 9:
1449       return V4L2_MPEG_VIDEO_H264_LEVEL_1B;
1450     case 11:
1451       return V4L2_MPEG_VIDEO_H264_LEVEL_1_1;
1452     case 12:
1453       return V4L2_MPEG_VIDEO_H264_LEVEL_1_2;
1454     case 13:
1455       return V4L2_MPEG_VIDEO_H264_LEVEL_1_3;
1456     case 20:
1457       return V4L2_MPEG_VIDEO_H264_LEVEL_2_0;
1458     case 21:
1459       return V4L2_MPEG_VIDEO_H264_LEVEL_2_1;
1460     case 22:
1461       return V4L2_MPEG_VIDEO_H264_LEVEL_2_2;
1462     case 30:
1463       return V4L2_MPEG_VIDEO_H264_LEVEL_3_0;
1464     case 31:
1465       return V4L2_MPEG_VIDEO_H264_LEVEL_3_1;
1466     case 32:
1467       return V4L2_MPEG_VIDEO_H264_LEVEL_3_2;
1468     case 40:
1469       return V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
1470     case 41:
1471       return V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
1472     case 42:
1473       return V4L2_MPEG_VIDEO_H264_LEVEL_4_2;
1474     case 50:
1475       return V4L2_MPEG_VIDEO_H264_LEVEL_5_0;
1476     case 51:
1477       return V4L2_MPEG_VIDEO_H264_LEVEL_5_1;
1478     default:
1479       DVLOGF(1) << "Unrecognized level_idc: " << static_cast<int>(level_idc);
1480       return -1;
1481   }
1482 }
1483 
1484 // static
AllocatedSizeFromV4L2Format(const struct v4l2_format & format)1485 gfx::Size V4L2Device::AllocatedSizeFromV4L2Format(
1486     const struct v4l2_format& format) {
1487   gfx::Size coded_size;
1488   gfx::Size visible_size;
1489   VideoPixelFormat frame_format = PIXEL_FORMAT_UNKNOWN;
1490   size_t bytesperline = 0;
1491   // Total bytes in the frame.
1492   size_t sizeimage = 0;
1493 
1494   if (V4L2_TYPE_IS_MULTIPLANAR(format.type)) {
1495     DCHECK_GT(format.fmt.pix_mp.num_planes, 0);
1496     bytesperline =
1497         base::checked_cast<int>(format.fmt.pix_mp.plane_fmt[0].bytesperline);
1498     for (size_t i = 0; i < format.fmt.pix_mp.num_planes; ++i) {
1499       sizeimage +=
1500           base::checked_cast<int>(format.fmt.pix_mp.plane_fmt[i].sizeimage);
1501     }
1502     visible_size.SetSize(base::checked_cast<int>(format.fmt.pix_mp.width),
1503                          base::checked_cast<int>(format.fmt.pix_mp.height));
1504     const uint32_t pix_fmt = format.fmt.pix_mp.pixelformat;
1505     const auto frame_fourcc = Fourcc::FromV4L2PixFmt(pix_fmt);
1506     if (!frame_fourcc) {
1507       VLOGF(1) << "Unsupported format " << FourccToString(pix_fmt);
1508       return coded_size;
1509     }
1510     frame_format = frame_fourcc->ToVideoPixelFormat();
1511   } else {
1512     bytesperline = base::checked_cast<int>(format.fmt.pix.bytesperline);
1513     sizeimage = base::checked_cast<int>(format.fmt.pix.sizeimage);
1514     visible_size.SetSize(base::checked_cast<int>(format.fmt.pix.width),
1515                          base::checked_cast<int>(format.fmt.pix.height));
1516     const uint32_t fourcc = format.fmt.pix.pixelformat;
1517     const auto frame_fourcc = Fourcc::FromV4L2PixFmt(fourcc);
1518     if (!frame_fourcc) {
1519       VLOGF(1) << "Unsupported format " << FourccToString(fourcc);
1520       return coded_size;
1521     }
1522     frame_format = frame_fourcc ? frame_fourcc->ToVideoPixelFormat()
1523                                 : PIXEL_FORMAT_UNKNOWN;
1524   }
1525 
1526   // V4L2 does not provide per-plane bytesperline (bpl) when different
1527   // components are sharing one physical plane buffer. In this case, it only
1528   // provides bpl for the first component in the plane. So we can't depend on it
1529   // for calculating height, because bpl may vary within one physical plane
1530   // buffer. For example, YUV420 contains 3 components in one physical plane,
1531   // with Y at 8 bits per pixel, and Cb/Cr at 4 bits per pixel per component,
1532   // but we only get 8 pits per pixel from bytesperline in physical plane 0.
1533   // So we need to get total frame bpp from elsewhere to calculate coded height.
1534 
1535   // We need bits per pixel for one component only to calculate
1536   // coded_width from bytesperline.
1537   int plane_horiz_bits_per_pixel =
1538       VideoFrame::PlaneHorizontalBitsPerPixel(frame_format, 0);
1539 
1540   // Adding up bpp for each component will give us total bpp for all components.
1541   int total_bpp = 0;
1542   for (size_t i = 0; i < VideoFrame::NumPlanes(frame_format); ++i)
1543     total_bpp += VideoFrame::PlaneBitsPerPixel(frame_format, i);
1544 
1545   if (sizeimage == 0 || bytesperline == 0 || plane_horiz_bits_per_pixel == 0 ||
1546       total_bpp == 0 || (bytesperline * 8) % plane_horiz_bits_per_pixel != 0) {
1547     VLOGF(1) << "Invalid format provided";
1548     return coded_size;
1549   }
1550 
1551   // Coded width can be calculated by taking the first component's bytesperline,
1552   // which in V4L2 always applies to the first component in physical plane
1553   // buffer.
1554   int coded_width = bytesperline * 8 / plane_horiz_bits_per_pixel;
1555   // Sizeimage is coded_width * coded_height * total_bpp. In the case that we
1556   // don't have exact alignment due to padding in the driver, round up so that
1557   // the buffer is large enough.
1558   std::div_t res = std::div(sizeimage * 8, coded_width * total_bpp);
1559   int coded_height = res.quot + std::min(res.rem, 1);
1560 
1561   coded_size.SetSize(coded_width, coded_height);
1562   DVLOGF(3) << "coded_size=" << coded_size.ToString();
1563 
1564   // Sanity checks. Calculated coded size has to contain given visible size
1565   // and fulfill buffer byte size requirements.
1566   DCHECK(gfx::Rect(coded_size).Contains(gfx::Rect(visible_size)));
1567   DCHECK_LE(sizeimage, VideoFrame::AllocationSize(frame_format, coded_size));
1568 
1569   return coded_size;
1570 }
1571 
1572 // static
V4L2MemoryToString(const v4l2_memory memory)1573 const char* V4L2Device::V4L2MemoryToString(const v4l2_memory memory) {
1574   switch (memory) {
1575     case V4L2_MEMORY_MMAP:
1576       return "V4L2_MEMORY_MMAP";
1577     case V4L2_MEMORY_USERPTR:
1578       return "V4L2_MEMORY_USERPTR";
1579     case V4L2_MEMORY_DMABUF:
1580       return "V4L2_MEMORY_DMABUF";
1581     case V4L2_MEMORY_OVERLAY:
1582       return "V4L2_MEMORY_OVERLAY";
1583     default:
1584       return "UNKNOWN";
1585   }
1586 }
1587 
1588 // static
V4L2BufferTypeToString(const enum v4l2_buf_type buf_type)1589 const char* V4L2Device::V4L2BufferTypeToString(
1590     const enum v4l2_buf_type buf_type) {
1591   switch (buf_type) {
1592     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1593       return "OUTPUT";
1594     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1595       return "CAPTURE";
1596     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1597       return "OUTPUT_MPLANE";
1598     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1599       return "CAPTURE_MPLANE";
1600     default:
1601       return "UNKNOWN";
1602   }
1603 }
1604 
1605 // static
V4L2FormatToString(const struct v4l2_format & format)1606 std::string V4L2Device::V4L2FormatToString(const struct v4l2_format& format) {
1607   std::ostringstream s;
1608   s << "v4l2_format type: " << format.type;
1609   if (format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
1610       format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1611     //  single-planar
1612     const struct v4l2_pix_format& pix = format.fmt.pix;
1613     s << ", width_height: " << gfx::Size(pix.width, pix.height).ToString()
1614       << ", pixelformat: " << FourccToString(pix.pixelformat)
1615       << ", field: " << pix.field << ", bytesperline: " << pix.bytesperline
1616       << ", sizeimage: " << pix.sizeimage;
1617   } else if (V4L2_TYPE_IS_MULTIPLANAR(format.type)) {
1618     const struct v4l2_pix_format_mplane& pix_mp = format.fmt.pix_mp;
1619     // As long as num_planes's type is uint8_t, ostringstream treats it as a
1620     // char instead of an integer, which is not what we want. Casting
1621     // pix_mp.num_planes unsigned int solves the issue.
1622     s << ", width_height: " << gfx::Size(pix_mp.width, pix_mp.height).ToString()
1623       << ", pixelformat: " << FourccToString(pix_mp.pixelformat)
1624       << ", field: " << pix_mp.field
1625       << ", num_planes: " << static_cast<unsigned int>(pix_mp.num_planes);
1626     for (size_t i = 0; i < pix_mp.num_planes; ++i) {
1627       const struct v4l2_plane_pix_format& plane_fmt = pix_mp.plane_fmt[i];
1628       s << ", plane_fmt[" << i << "].sizeimage: " << plane_fmt.sizeimage
1629         << ", plane_fmt[" << i << "].bytesperline: " << plane_fmt.bytesperline;
1630     }
1631   } else {
1632     s << " unsupported yet.";
1633   }
1634   return s.str();
1635 }
1636 
1637 // static
V4L2BufferToString(const struct v4l2_buffer & buffer)1638 std::string V4L2Device::V4L2BufferToString(const struct v4l2_buffer& buffer) {
1639   std::ostringstream s;
1640   s << "v4l2_buffer type: " << buffer.type << ", memory: " << buffer.memory
1641     << ", index: " << buffer.index << " bytesused: " << buffer.bytesused
1642     << ", length: " << buffer.length;
1643   if (buffer.type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
1644       buffer.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1645     //  single-planar
1646     if (buffer.memory == V4L2_MEMORY_MMAP) {
1647       s << ", m.offset: " << buffer.m.offset;
1648     } else if (buffer.memory == V4L2_MEMORY_USERPTR) {
1649       s << ", m.userptr: " << buffer.m.userptr;
1650     } else if (buffer.memory == V4L2_MEMORY_DMABUF) {
1651       s << ", m.fd: " << buffer.m.fd;
1652     }
1653   } else if (V4L2_TYPE_IS_MULTIPLANAR(buffer.type)) {
1654     for (size_t i = 0; i < buffer.length; ++i) {
1655       const struct v4l2_plane& plane = buffer.m.planes[i];
1656       s << ", m.planes[" << i << "](bytesused: " << plane.bytesused
1657         << ", length: " << plane.length
1658         << ", data_offset: " << plane.data_offset;
1659       if (buffer.memory == V4L2_MEMORY_MMAP) {
1660         s << ", m.mem_offset: " << plane.m.mem_offset;
1661       } else if (buffer.memory == V4L2_MEMORY_USERPTR) {
1662         s << ", m.userptr: " << plane.m.userptr;
1663       } else if (buffer.memory == V4L2_MEMORY_DMABUF) {
1664         s << ", m.fd: " << plane.m.fd;
1665       }
1666       s << ")";
1667     }
1668   } else {
1669     s << " unsupported yet.";
1670   }
1671   return s.str();
1672 }
1673 
1674 // static
V4L2FormatToVideoFrameLayout(const struct v4l2_format & format)1675 base::Optional<VideoFrameLayout> V4L2Device::V4L2FormatToVideoFrameLayout(
1676     const struct v4l2_format& format) {
1677   if (!V4L2_TYPE_IS_MULTIPLANAR(format.type)) {
1678     VLOGF(1) << "v4l2_buf_type is not multiplanar: " << std::hex << "0x"
1679              << format.type;
1680     return base::nullopt;
1681   }
1682   const v4l2_pix_format_mplane& pix_mp = format.fmt.pix_mp;
1683   const uint32_t& pix_fmt = pix_mp.pixelformat;
1684   const auto video_fourcc = Fourcc::FromV4L2PixFmt(pix_fmt);
1685   if (!video_fourcc) {
1686     VLOGF(1) << "Failed to convert pixel format to VideoPixelFormat: "
1687              << FourccToString(pix_fmt);
1688     return base::nullopt;
1689   }
1690   const VideoPixelFormat video_format = video_fourcc->ToVideoPixelFormat();
1691   const size_t num_buffers = pix_mp.num_planes;
1692   const size_t num_color_planes = VideoFrame::NumPlanes(video_format);
1693   if (num_color_planes == 0) {
1694     VLOGF(1) << "Unsupported video format for NumPlanes(): "
1695              << VideoPixelFormatToString(video_format);
1696     return base::nullopt;
1697   }
1698   if (num_buffers > num_color_planes) {
1699     VLOGF(1) << "pix_mp.num_planes: " << num_buffers
1700              << " should not be larger than NumPlanes("
1701              << VideoPixelFormatToString(video_format)
1702              << "): " << num_color_planes;
1703     return base::nullopt;
1704   }
1705   // Reserve capacity in advance to prevent unnecessary vector reallocation.
1706   std::vector<ColorPlaneLayout> planes;
1707   planes.reserve(num_color_planes);
1708   for (size_t i = 0; i < num_buffers; ++i) {
1709     const v4l2_plane_pix_format& plane_format = pix_mp.plane_fmt[i];
1710     planes.emplace_back(static_cast<int32_t>(plane_format.bytesperline), 0u,
1711                         plane_format.sizeimage);
1712   }
1713   // For the case that #color planes > #buffers, it fills stride of color
1714   // plane which does not map to buffer.
1715   // Right now only some pixel formats are supported: NV12, YUV420, YVU420.
1716   if (num_color_planes > num_buffers) {
1717     const int32_t y_stride = planes[0].stride;
1718     // Note that y_stride is from v4l2 bytesperline and its type is uint32_t.
1719     // It is safe to cast to size_t.
1720     const size_t y_stride_abs = static_cast<size_t>(y_stride);
1721     switch (pix_fmt) {
1722       case V4L2_PIX_FMT_NV12:
1723         // The stride of UV is the same as Y in NV12.
1724         // The height is half of Y plane.
1725         planes.emplace_back(y_stride, y_stride_abs * pix_mp.height,
1726                             y_stride_abs * pix_mp.height / 2);
1727         DCHECK_EQ(2u, planes.size());
1728         break;
1729       case V4L2_PIX_FMT_YUV420:
1730       case V4L2_PIX_FMT_YVU420: {
1731         // The spec claims that two Cx rows (including padding) is exactly as
1732         // long as one Y row (including padding). So stride of Y must be even
1733         // number.
1734         if (y_stride % 2 != 0 || pix_mp.height % 2 != 0) {
1735           VLOGF(1) << "Plane-Y stride and height should be even; stride: "
1736                    << y_stride << ", height: " << pix_mp.height;
1737           return base::nullopt;
1738         }
1739         const int32_t half_stride = y_stride / 2;
1740         const size_t plane_0_area = y_stride_abs * pix_mp.height;
1741         const size_t plane_1_area = plane_0_area / 4;
1742         planes.emplace_back(half_stride, plane_0_area, plane_1_area);
1743         planes.emplace_back(half_stride, plane_0_area + plane_1_area,
1744                             plane_1_area);
1745         DCHECK_EQ(3u, planes.size());
1746         break;
1747       }
1748       default:
1749         VLOGF(1) << "Cannot derive stride for each plane for pixel format "
1750                  << FourccToString(pix_fmt);
1751         return base::nullopt;
1752     }
1753   }
1754 
1755   // Some V4L2 devices expect buffers to be page-aligned. We cannot detect
1756   // such devices individually, so set this as a video frame layout property.
1757   constexpr size_t buffer_alignment = 0x1000;
1758   if (num_buffers == 1) {
1759     return VideoFrameLayout::CreateWithPlanes(
1760         video_format, gfx::Size(pix_mp.width, pix_mp.height), std::move(planes),
1761         buffer_alignment);
1762   } else {
1763     return VideoFrameLayout::CreateMultiPlanar(
1764         video_format, gfx::Size(pix_mp.width, pix_mp.height), std::move(planes),
1765         buffer_alignment);
1766   }
1767 }
1768 
1769 // static
GetNumPlanesOfV4L2PixFmt(uint32_t pix_fmt)1770 size_t V4L2Device::GetNumPlanesOfV4L2PixFmt(uint32_t pix_fmt) {
1771   base::Optional<Fourcc> fourcc = Fourcc::FromV4L2PixFmt(pix_fmt);
1772   if (fourcc && fourcc->IsMultiPlanar()) {
1773     return VideoFrame::NumPlanes(fourcc->ToVideoPixelFormat());
1774   }
1775   return 1u;
1776 }
1777 
GetSupportedResolution(uint32_t pixelformat,gfx::Size * min_resolution,gfx::Size * max_resolution)1778 void V4L2Device::GetSupportedResolution(uint32_t pixelformat,
1779                                         gfx::Size* min_resolution,
1780                                         gfx::Size* max_resolution) {
1781   max_resolution->SetSize(0, 0);
1782   min_resolution->SetSize(0, 0);
1783   v4l2_frmsizeenum frame_size;
1784   memset(&frame_size, 0, sizeof(frame_size));
1785   frame_size.pixel_format = pixelformat;
1786   for (; Ioctl(VIDIOC_ENUM_FRAMESIZES, &frame_size) == 0; ++frame_size.index) {
1787     if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
1788       if (frame_size.discrete.width >=
1789               base::checked_cast<uint32_t>(max_resolution->width()) &&
1790           frame_size.discrete.height >=
1791               base::checked_cast<uint32_t>(max_resolution->height())) {
1792         max_resolution->SetSize(frame_size.discrete.width,
1793                                 frame_size.discrete.height);
1794       }
1795       if (min_resolution->IsEmpty() ||
1796           (frame_size.discrete.width <=
1797                base::checked_cast<uint32_t>(min_resolution->width()) &&
1798            frame_size.discrete.height <=
1799                base::checked_cast<uint32_t>(min_resolution->height()))) {
1800         min_resolution->SetSize(frame_size.discrete.width,
1801                                 frame_size.discrete.height);
1802       }
1803     } else if (frame_size.type == V4L2_FRMSIZE_TYPE_STEPWISE ||
1804                frame_size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
1805       max_resolution->SetSize(frame_size.stepwise.max_width,
1806                               frame_size.stepwise.max_height);
1807       min_resolution->SetSize(frame_size.stepwise.min_width,
1808                               frame_size.stepwise.min_height);
1809       break;
1810     }
1811   }
1812   if (max_resolution->IsEmpty()) {
1813     max_resolution->SetSize(1920, 1088);
1814     VLOGF(1) << "GetSupportedResolution failed to get maximum resolution for "
1815              << "fourcc " << FourccToString(pixelformat) << ", fall back to "
1816              << max_resolution->ToString();
1817   }
1818   if (min_resolution->IsEmpty()) {
1819     min_resolution->SetSize(16, 16);
1820     VLOGF(1) << "GetSupportedResolution failed to get minimum resolution for "
1821              << "fourcc " << FourccToString(pixelformat) << ", fall back to "
1822              << min_resolution->ToString();
1823   }
1824 }
1825 
EnumerateSupportedPixelformats(v4l2_buf_type buf_type)1826 std::vector<uint32_t> V4L2Device::EnumerateSupportedPixelformats(
1827     v4l2_buf_type buf_type) {
1828   std::vector<uint32_t> pixelformats;
1829 
1830   v4l2_fmtdesc fmtdesc;
1831   memset(&fmtdesc, 0, sizeof(fmtdesc));
1832   fmtdesc.type = buf_type;
1833 
1834   for (; Ioctl(VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) {
1835     DVLOGF(3) << "Found " << fmtdesc.description << std::hex << " (0x"
1836               << fmtdesc.pixelformat << ")";
1837     pixelformats.push_back(fmtdesc.pixelformat);
1838   }
1839 
1840   return pixelformats;
1841 }
1842 
1843 VideoDecodeAccelerator::SupportedProfiles
EnumerateSupportedDecodeProfiles(const size_t num_formats,const uint32_t pixelformats[])1844 V4L2Device::EnumerateSupportedDecodeProfiles(const size_t num_formats,
1845                                              const uint32_t pixelformats[]) {
1846   VideoDecodeAccelerator::SupportedProfiles profiles;
1847 
1848   const auto& supported_pixelformats =
1849       EnumerateSupportedPixelformats(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
1850 
1851   for (uint32_t pixelformat : supported_pixelformats) {
1852     if (std::find(pixelformats, pixelformats + num_formats, pixelformat) ==
1853         pixelformats + num_formats)
1854       continue;
1855 
1856     VideoDecodeAccelerator::SupportedProfile profile;
1857     GetSupportedResolution(pixelformat, &profile.min_resolution,
1858                            &profile.max_resolution);
1859 
1860     const auto video_codec_profiles =
1861         V4L2PixFmtToVideoCodecProfiles(pixelformat, false);
1862 
1863     for (const auto& video_codec_profile : video_codec_profiles) {
1864       profile.profile = video_codec_profile;
1865       profiles.push_back(profile);
1866 
1867       DVLOGF(3) << "Found decoder profile " << GetProfileName(profile.profile)
1868                 << ", resolutions: " << profile.min_resolution.ToString() << " "
1869                 << profile.max_resolution.ToString();
1870     }
1871   }
1872 
1873   return profiles;
1874 }
1875 
1876 VideoEncodeAccelerator::SupportedProfiles
EnumerateSupportedEncodeProfiles()1877 V4L2Device::EnumerateSupportedEncodeProfiles() {
1878   VideoEncodeAccelerator::SupportedProfiles profiles;
1879 
1880   const auto& supported_pixelformats =
1881       EnumerateSupportedPixelformats(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
1882 
1883   for (const auto& pixelformat : supported_pixelformats) {
1884     VideoEncodeAccelerator::SupportedProfile profile;
1885     profile.max_framerate_numerator = 30;
1886     profile.max_framerate_denominator = 1;
1887     gfx::Size min_resolution;
1888     GetSupportedResolution(pixelformat, &min_resolution,
1889                            &profile.max_resolution);
1890 
1891     const auto video_codec_profiles =
1892         V4L2PixFmtToVideoCodecProfiles(pixelformat, true);
1893 
1894     for (const auto& video_codec_profile : video_codec_profiles) {
1895       profile.profile = video_codec_profile;
1896       profiles.push_back(profile);
1897 
1898       DVLOGF(3) << "Found encoder profile " << GetProfileName(profile.profile)
1899                 << ", max resolution: " << profile.max_resolution.ToString();
1900     }
1901   }
1902 
1903   return profiles;
1904 }
1905 
StartPolling(V4L2DevicePoller::EventCallback event_callback,base::RepeatingClosure error_callback)1906 bool V4L2Device::StartPolling(V4L2DevicePoller::EventCallback event_callback,
1907                               base::RepeatingClosure error_callback) {
1908   DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
1909 
1910   if (!device_poller_) {
1911     device_poller_ =
1912         std::make_unique<V4L2DevicePoller>(this, "V4L2DeviceThreadPoller");
1913   }
1914 
1915   bool ret = device_poller_->StartPolling(std::move(event_callback),
1916                                           std::move(error_callback));
1917 
1918   if (!ret)
1919     device_poller_ = nullptr;
1920 
1921   return ret;
1922 }
1923 
StopPolling()1924 bool V4L2Device::StopPolling() {
1925   DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
1926 
1927   return !device_poller_ || device_poller_->StopPolling();
1928 }
1929 
SchedulePoll()1930 void V4L2Device::SchedulePoll() {
1931   DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
1932 
1933   if (!device_poller_ || !device_poller_->IsPolling())
1934     return;
1935 
1936   device_poller_->SchedulePoll();
1937 }
1938 
GetRequestsQueue()1939 V4L2RequestsQueue* V4L2Device::GetRequestsQueue() {
1940   DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
1941 
1942   if (requests_queue_creation_called_)
1943     return requests_queue_.get();
1944 
1945   requests_queue_creation_called_ = true;
1946   int media_fd = open(REQUEST_DEVICE, O_RDWR, 0);
1947   if (media_fd < 0) {
1948     VPLOGF(1) << "Failed to open media device.";
1949     return nullptr;
1950   }
1951 
1952   // Not using std::make_unique because constructor is private.
1953   std::unique_ptr<V4L2RequestsQueue> requests_queue(new V4L2RequestsQueue(
1954       base::ScopedFD(media_fd)));
1955   requests_queue_ = std::move(requests_queue);
1956 
1957   return requests_queue_.get();
1958 }
1959 
IsCtrlExposed(uint32_t ctrl_id)1960 bool V4L2Device::IsCtrlExposed(uint32_t ctrl_id) {
1961   DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
1962 
1963   struct v4l2_queryctrl query_ctrl {};
1964   query_ctrl.id = ctrl_id;
1965 
1966   return Ioctl(VIDIOC_QUERYCTRL, &query_ctrl) == 0;
1967 }
1968 
SetExtCtrls(uint32_t ctrl_class,std::vector<V4L2ExtCtrl> ctrls)1969 bool V4L2Device::SetExtCtrls(uint32_t ctrl_class,
1970                              std::vector<V4L2ExtCtrl> ctrls) {
1971   DCHECK_CALLED_ON_VALID_SEQUENCE(client_sequence_checker_);
1972 
1973   if (ctrls.empty())
1974     return true;
1975 
1976   struct v4l2_ext_controls ext_ctrls {};
1977   ext_ctrls.ctrl_class = ctrl_class;
1978   ext_ctrls.count = ctrls.size();
1979   ext_ctrls.controls = &ctrls[0].ctrl;
1980   return Ioctl(VIDIOC_S_EXT_CTRLS, &ext_ctrls) == 0;
1981 }
1982 
1983 class V4L2Request {
1984  public:
1985   // Apply the passed controls to the request.
1986   bool ApplyCtrls(struct v4l2_ext_controls* ctrls);
1987   // Apply the passed buffer to the request..
1988   bool ApplyQueueBuffer(struct v4l2_buffer* buffer);
1989   // Submits the request to the driver.
1990   bool Submit();
1991   // Indicates if the request has completed.
1992   bool IsCompleted();
1993   // Waits for the request to complete for a determined timeout. Returns false
1994   // if the request is not ready or other error. Default timeout is 500ms.
1995   bool WaitForCompletion(int poll_timeout_ms = 500);
1996   // Resets the request.
1997   bool Reset();
1998 
1999  private:
2000   V4L2RequestsQueue* request_queue_;
2001   int ref_counter_ = 0;
2002   base::ScopedFD request_fd_;
2003 
2004   friend class V4L2RequestsQueue;
V4L2Request(base::ScopedFD && request_fd,V4L2RequestsQueue * request_queue)2005   V4L2Request(base::ScopedFD&& request_fd, V4L2RequestsQueue* request_queue) :
2006    request_queue_(request_queue), request_fd_(std::move(request_fd)) {}
2007 
2008   friend class V4L2RequestRefBase;
2009   // Increases the number of request references.
2010   void IncRefCounter();
2011   // Decreases the number of request references.
2012   // When the counters reaches zero, the request is returned to the queue.
2013   int DecRefCounter();
2014 
2015   SEQUENCE_CHECKER(sequence_checker_);
2016   DISALLOW_COPY_AND_ASSIGN(V4L2Request);
2017 };
2018 
IncRefCounter()2019 void V4L2Request::IncRefCounter() {
2020   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2021 
2022   ref_counter_++;
2023 }
2024 
DecRefCounter()2025 int V4L2Request::DecRefCounter() {
2026   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2027 
2028   ref_counter_--;
2029 
2030   if (ref_counter_< 1)
2031     request_queue_->ReturnRequest(this);
2032 
2033   return ref_counter_;
2034 }
2035 
ApplyCtrls(struct v4l2_ext_controls * ctrls)2036 bool V4L2Request::ApplyCtrls(struct v4l2_ext_controls* ctrls) {
2037   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2038   DCHECK_NE(ctrls, nullptr);
2039 
2040   if (!request_fd_.is_valid()) {
2041     VPLOGF(1) << "Invalid request";
2042     return false;
2043   }
2044 
2045   ctrls->which = V4L2_CTRL_WHICH_REQUEST_VAL;
2046   ctrls->request_fd = request_fd_.get();
2047 
2048   return true;
2049 }
2050 
ApplyQueueBuffer(struct v4l2_buffer * buffer)2051 bool V4L2Request::ApplyQueueBuffer(struct v4l2_buffer* buffer) {
2052   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2053   DCHECK_NE(buffer, nullptr);
2054 
2055   if (!request_fd_.is_valid()) {
2056     VPLOGF(1) << "Invalid request";
2057     return false;
2058   }
2059 
2060   buffer->flags |= V4L2_BUF_FLAG_REQUEST_FD;
2061   buffer->request_fd = request_fd_.get();
2062 
2063   return true;
2064 }
2065 
Submit()2066 bool V4L2Request::Submit() {
2067   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2068 
2069   if (!request_fd_.is_valid()) {
2070     VPLOGF(1) << "No valid request file descriptor to submit request.";
2071     return false;
2072   }
2073 
2074   return HANDLE_EINTR(ioctl(request_fd_.get(), MEDIA_REQUEST_IOC_QUEUE)) == 0;
2075 }
2076 
IsCompleted()2077 bool V4L2Request::IsCompleted() {
2078   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2079 
2080   return WaitForCompletion(0);
2081 }
2082 
WaitForCompletion(int poll_timeout_ms)2083 bool V4L2Request::WaitForCompletion(int poll_timeout_ms) {
2084   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2085   if (!request_fd_.is_valid()) {
2086     VPLOGF(1) << "Invalid request";
2087     return false;
2088   }
2089 
2090   struct pollfd poll_fd = {request_fd_.get(), POLLPRI, 0};
2091 
2092   // Poll the request to ensure its previous task is done
2093   switch (poll(&poll_fd, 1, poll_timeout_ms)) {
2094     case 1:
2095       return true;
2096     case 0:
2097       // Not an error - we just timed out.
2098       DVLOGF(4) << "Request poll(" << poll_timeout_ms << ") timed out";
2099       return false;
2100     case -1:
2101       VPLOGF(1) << "Failed to poll request";
2102       return false;
2103     default:
2104       NOTREACHED();
2105       return false;
2106   }
2107 }
2108 
Reset()2109 bool V4L2Request::Reset() {
2110   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2111 
2112   if (!request_fd_.is_valid()) {
2113     VPLOGF(1) << "Invalid request";
2114     return false;
2115   }
2116 
2117   // Reinit the request to make sure we can use it for a new submission.
2118   if (HANDLE_EINTR(ioctl(request_fd_.get(), MEDIA_REQUEST_IOC_REINIT)) < 0) {
2119     VPLOGF(1) << "Failed to reinit request.";
2120     return false;
2121   }
2122 
2123   return true;
2124 }
2125 
V4L2RequestRefBase(V4L2RequestRefBase && req_base)2126 V4L2RequestRefBase::V4L2RequestRefBase(V4L2RequestRefBase&& req_base) {
2127   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2128 
2129   request_ = req_base.request_;
2130   req_base.request_ = nullptr;
2131 }
2132 
V4L2RequestRefBase(V4L2Request * request)2133 V4L2RequestRefBase::V4L2RequestRefBase(V4L2Request* request) {
2134   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2135 
2136   if (request) {
2137     request_ = request;
2138     request_->IncRefCounter();
2139   }
2140 }
2141 
~V4L2RequestRefBase()2142 V4L2RequestRefBase::~V4L2RequestRefBase() {
2143   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2144 
2145   if (request_)
2146     request_->DecRefCounter();
2147 }
2148 
ApplyCtrls(struct v4l2_ext_controls * ctrls) const2149 bool V4L2RequestRef::ApplyCtrls(struct v4l2_ext_controls* ctrls) const {
2150   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2151   DCHECK_NE(request_, nullptr);
2152 
2153   return request_->ApplyCtrls(ctrls);
2154 }
2155 
ApplyQueueBuffer(struct v4l2_buffer * buffer) const2156 bool V4L2RequestRef::ApplyQueueBuffer(struct v4l2_buffer* buffer) const {
2157   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2158   DCHECK_NE(request_, nullptr);
2159 
2160   return request_->ApplyQueueBuffer(buffer);
2161 }
2162 
Submit()2163 base::Optional<V4L2SubmittedRequestRef> V4L2RequestRef::Submit() && {
2164   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2165   DCHECK_NE(request_, nullptr);
2166 
2167   V4L2RequestRef self(std::move(*this));
2168 
2169   if (!self.request_->Submit())
2170     return base::nullopt;
2171 
2172   return V4L2SubmittedRequestRef(self.request_);
2173 }
2174 
IsCompleted()2175 bool V4L2SubmittedRequestRef::IsCompleted() {
2176   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2177   DCHECK_NE(request_, nullptr);
2178 
2179   return request_->IsCompleted();
2180 }
2181 
V4L2RequestsQueue(base::ScopedFD && media_fd)2182 V4L2RequestsQueue::V4L2RequestsQueue(base::ScopedFD&& media_fd) {
2183   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2184 
2185   media_fd_ = std::move(media_fd);
2186 }
2187 
~V4L2RequestsQueue()2188 V4L2RequestsQueue::~V4L2RequestsQueue() {
2189   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2190 
2191   requests_.clear();
2192   media_fd_.reset();
2193 }
2194 
CreateRequestFD()2195 base::Optional<base::ScopedFD> V4L2RequestsQueue::CreateRequestFD() {
2196   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2197 
2198   int request_fd;
2199   int ret = HANDLE_EINTR(
2200         ioctl(media_fd_.get(), MEDIA_IOC_REQUEST_ALLOC, &request_fd));
2201   if (ret < 0) {
2202     VPLOGF(1) << "Failed to create request";
2203     return base::nullopt;
2204   }
2205 
2206   return base::ScopedFD(request_fd);
2207 }
2208 
GetFreeRequest()2209 base::Optional<V4L2RequestRef> V4L2RequestsQueue::GetFreeRequest() {
2210   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2211 
2212   V4L2Request* request_ptr =
2213       free_requests_.empty() ? nullptr : free_requests_.front();
2214   if (request_ptr && request_ptr->IsCompleted()) {
2215     // Previous request is already completed, just recycle it.
2216     free_requests_.pop();
2217   } else if (requests_.size() < kMaxNumRequests) {
2218     // No request yet, or not completed, but we can allocate a new one.
2219     auto request_fd = CreateRequestFD();
2220     if (!request_fd.has_value()) {
2221       VLOGF(1) << "Error while creating a new request FD!";
2222       return base::nullopt;
2223     }
2224     // Not using std::make_unique because constructor is private.
2225     std::unique_ptr<V4L2Request> request(
2226         new V4L2Request(std::move(*request_fd), this));
2227     request_ptr = request.get();
2228     requests_.push_back(std::move(request));
2229     VLOGF(4) << "Allocated new request, total number: " << requests_.size();
2230   } else {
2231     // Request is not completed and we have reached the maximum number.
2232     // Wait for it to complete.
2233     VLOGF(1) << "Waiting for request completion. This probably means a "
2234              << "request is blocking.";
2235     if (!request_ptr->WaitForCompletion()) {
2236       VLOG(1) << "Timeout while waiting for request to complete.";
2237       return base::nullopt;
2238     }
2239     free_requests_.pop();
2240   }
2241 
2242   DCHECK(request_ptr);
2243   if (!request_ptr->Reset()) {
2244     VPLOGF(1) << "Failed to reset request";
2245     return base::nullopt;
2246   }
2247 
2248   return V4L2RequestRef(request_ptr);
2249 }
2250 
ReturnRequest(V4L2Request * request)2251 void V4L2RequestsQueue::ReturnRequest(V4L2Request* request) {
2252   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
2253   DCHECK(request);
2254 
2255   if (request)
2256     free_requests_.push(request);
2257 }
2258 
2259 }  //  namespace media
2260