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