• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Note: ported from Chromium commit head: 2f13d62f0c0d
5 // Note: Added some missing defines that are only defined in newer kernel
6 //       versions (e.g. V4L2_PIX_FMT_VP8_FRAME)
7 
8 //#define LOG_NDEBUG 0
9 #define LOG_TAG "V4L2Device"
10 
11 #include <v4l2_codec2/common/V4L2Device.h>
12 
13 #include <fcntl.h>
14 #include <inttypes.h>
15 #include <linux/media.h>
16 #include <linux/videodev2.h>
17 #include <poll.h>
18 #include <string.h>
19 #include <sys/eventfd.h>
20 #include <sys/ioctl.h>
21 #include <sys/mman.h>
22 
23 #include <algorithm>
24 #include <mutex>
25 #include <set>
26 #include <sstream>
27 
28 #include <base/bind.h>
29 #include <base/numerics/safe_conversions.h>
30 #include <base/posix/eintr_wrapper.h>
31 #include <base/strings/stringprintf.h>
32 #include <base/thread_annotations.h>
33 #include <utils/Log.h>
34 
35 #include <v4l2_codec2/common/Fourcc.h>
36 #include <v4l2_codec2/common/VideoPixelFormat.h>
37 
38 // VP8 parsed frames
39 #ifndef V4L2_PIX_FMT_VP8_FRAME
40 #define V4L2_PIX_FMT_VP8_FRAME v4l2_fourcc('V', 'P', '8', 'F')
41 #endif
42 
43 // VP9 parsed frames
44 #ifndef V4L2_PIX_FMT_VP9_FRAME
45 #define V4L2_PIX_FMT_VP9_FRAME v4l2_fourcc('V', 'P', '9', 'F')
46 #endif
47 
48 // H264 parsed slices
49 #ifndef V4L2_PIX_FMT_H264_SLICE
50 #define V4L2_PIX_FMT_H264_SLICE v4l2_fourcc('S', '2', '6', '4')
51 #endif
52 
53 namespace android {
54 
buildV4L2Format(const enum v4l2_buf_type type,uint32_t fourcc,const ui::Size & size,size_t buffer_size,uint32_t stride)55 struct v4l2_format buildV4L2Format(const enum v4l2_buf_type type, uint32_t fourcc,
56                                    const ui::Size& size, size_t buffer_size, uint32_t stride) {
57     struct v4l2_format format;
58     memset(&format, 0, sizeof(format));
59     format.type = type;
60     format.fmt.pix_mp.pixelformat = fourcc;
61     format.fmt.pix_mp.width = size.width;
62     format.fmt.pix_mp.height = size.height;
63     format.fmt.pix_mp.num_planes = V4L2Device::getNumPlanesOfV4L2PixFmt(fourcc);
64     format.fmt.pix_mp.plane_fmt[0].sizeimage = buffer_size;
65 
66     // When the image format is planar the bytesperline value applies to the first plane and is
67     // divided by the same factor as the width field for the other planes.
68     format.fmt.pix_mp.plane_fmt[0].bytesperline = stride;
69 
70     return format;
71 }
72 
V4L2ExtCtrl(uint32_t id)73 V4L2ExtCtrl::V4L2ExtCtrl(uint32_t id) {
74     memset(&ctrl, 0, sizeof(ctrl));
75     ctrl.id = id;
76 }
77 
V4L2ExtCtrl(uint32_t id,int32_t val)78 V4L2ExtCtrl::V4L2ExtCtrl(uint32_t id, int32_t val) : V4L2ExtCtrl(id) {
79     ctrl.value = val;
80 }
81 
82 // Class used to store the state of a buffer that should persist between reference creations. This
83 // includes:
84 // * Result of initial VIDIOC_QUERYBUF ioctl,
85 // * Plane mappings.
86 //
87 // Also provides helper functions.
88 class V4L2Buffer {
89 public:
90     static std::unique_ptr<V4L2Buffer> create(scoped_refptr<V4L2Device> device,
91                                               enum v4l2_buf_type type, enum v4l2_memory memory,
92                                               const struct v4l2_format& format, size_t bufferId);
93     ~V4L2Buffer();
94 
95     V4L2Buffer(const V4L2Buffer&) = delete;
96     V4L2Buffer& operator=(const V4L2Buffer&) = delete;
97 
98     void* getPlaneMapping(const size_t plane);
99     size_t getMemoryUsage() const;
v4l2_buffer() const100     const struct v4l2_buffer& v4l2_buffer() const { return mV4l2Buffer; }
101 
102 private:
103     V4L2Buffer(scoped_refptr<V4L2Device> device, enum v4l2_buf_type type, enum v4l2_memory memory,
104                const struct v4l2_format& format, size_t bufferId);
105     bool query();
106 
107     scoped_refptr<V4L2Device> mDevice;
108     std::vector<void*> mPlaneMappings;
109 
110     // V4L2 data as queried by QUERYBUF.
111     struct v4l2_buffer mV4l2Buffer;
112     // WARNING: do not change this to a vector or something smaller than VIDEO_MAX_PLANES, otherwise
113     // the Tegra libv4l2 will write data beyond the number of allocated planes, resulting in memory
114     // corruption.
115     struct v4l2_plane mV4l2Planes[VIDEO_MAX_PLANES];
116 
117     struct v4l2_format mFormat __attribute__((unused));
118 };
119 
create(scoped_refptr<V4L2Device> device,enum v4l2_buf_type type,enum v4l2_memory memory,const struct v4l2_format & format,size_t bufferId)120 std::unique_ptr<V4L2Buffer> V4L2Buffer::create(scoped_refptr<V4L2Device> device,
121                                                enum v4l2_buf_type type, enum v4l2_memory memory,
122                                                const struct v4l2_format& format, size_t bufferId) {
123     // Not using std::make_unique because constructor is private.
124     std::unique_ptr<V4L2Buffer> buffer(new V4L2Buffer(device, type, memory, format, bufferId));
125 
126     if (!buffer->query()) return nullptr;
127 
128     return buffer;
129 }
130 
V4L2Buffer(scoped_refptr<V4L2Device> device,enum v4l2_buf_type type,enum v4l2_memory memory,const struct v4l2_format & format,size_t bufferId)131 V4L2Buffer::V4L2Buffer(scoped_refptr<V4L2Device> device, enum v4l2_buf_type type,
132                        enum v4l2_memory memory, const struct v4l2_format& format, size_t bufferId)
133       : mDevice(device), mFormat(format) {
134     ALOG_ASSERT(V4L2_TYPE_IS_MULTIPLANAR(type));
135     ALOG_ASSERT(format.fmt.pix_mp.num_planes <= base::size(mV4l2Planes));
136 
137     memset(mV4l2Planes, 0, sizeof(mV4l2Planes));
138     memset(&mV4l2Buffer, 0, sizeof(mV4l2Buffer));
139     mV4l2Buffer.m.planes = mV4l2Planes;
140     // Just in case we got more planes than we want.
141     mV4l2Buffer.length =
142             std::min(static_cast<size_t>(format.fmt.pix_mp.num_planes), base::size(mV4l2Planes));
143     mV4l2Buffer.index = bufferId;
144     mV4l2Buffer.type = type;
145     mV4l2Buffer.memory = memory;
146     mV4l2Buffer.memory = V4L2_MEMORY_DMABUF;
147     mPlaneMappings.resize(mV4l2Buffer.length);
148 }
149 
~V4L2Buffer()150 V4L2Buffer::~V4L2Buffer() {
151     if (mV4l2Buffer.memory == V4L2_MEMORY_MMAP) {
152         for (size_t i = 0; i < mPlaneMappings.size(); i++) {
153             if (mPlaneMappings[i] != nullptr) {
154                 mDevice->munmap(mPlaneMappings[i], mV4l2Buffer.m.planes[i].length);
155             }
156         }
157     }
158 }
159 
query()160 bool V4L2Buffer::query() {
161     int ret = mDevice->ioctl(VIDIOC_QUERYBUF, &mV4l2Buffer);
162     if (ret) {
163         ALOGE("VIDIOC_QUERYBUF failed");
164         return false;
165     }
166 
167     DCHECK(mPlaneMappings.size() == mV4l2Buffer.length);
168 
169     return true;
170 }
171 
getPlaneMapping(const size_t plane)172 void* V4L2Buffer::getPlaneMapping(const size_t plane) {
173     if (plane >= mPlaneMappings.size()) {
174         ALOGE("Invalid plane %zu requested.", plane);
175         return nullptr;
176     }
177 
178     void* p = mPlaneMappings[plane];
179     if (p) {
180         return p;
181     }
182 
183     // Do this check here to avoid repeating it after a buffer has been successfully mapped (we know
184     // we are of MMAP type by then).
185     if (mV4l2Buffer.memory != V4L2_MEMORY_MMAP) {
186         ALOGE("Cannot create mapping on non-MMAP buffer");
187         return nullptr;
188     }
189 
190     p = mDevice->mmap(NULL, mV4l2Buffer.m.planes[plane].length, PROT_READ | PROT_WRITE, MAP_SHARED,
191                       mV4l2Buffer.m.planes[plane].m.mem_offset);
192     if (p == MAP_FAILED) {
193         ALOGE("mmap() failed: ");
194         return nullptr;
195     }
196 
197     mPlaneMappings[plane] = p;
198     return p;
199 }
200 
getMemoryUsage() const201 size_t V4L2Buffer::getMemoryUsage() const {
202     size_t usage = 0;
203     for (size_t i = 0; i < mV4l2Buffer.length; i++) {
204         usage += mV4l2Buffer.m.planes[i].length;
205     }
206     return usage;
207 }
208 
209 // A thread-safe pool of buffer indexes, allowing buffers to be obtained and returned from different
210 // threads. All the methods of this class are thread-safe. Users should keep a scoped_refptr to
211 // instances of this class in order to ensure the list remains alive as long as they need it.
212 class V4L2BuffersList : public base::RefCountedThreadSafe<V4L2BuffersList> {
213 public:
214     V4L2BuffersList() = default;
215 
216     V4L2BuffersList(const V4L2BuffersList&) = delete;
217     V4L2BuffersList& operator=(const V4L2BuffersList&) = delete;
218 
219     // Return a buffer to this list. Also can be called to set the initial pool of buffers.
220     // Note that it is illegal to return the same buffer twice.
221     void returnBuffer(size_t bufferId);
222     // Get any of the buffers in the list. There is no order guarantee whatsoever.
223     std::optional<size_t> getFreeBuffer();
224     // Get the buffer with specified index.
225     std::optional<size_t> getFreeBuffer(size_t requestedBufferId);
226     // Number of buffers currently in this list.
227     size_t size() const;
228 
229 private:
230     friend class base::RefCountedThreadSafe<V4L2BuffersList>;
231     ~V4L2BuffersList() = default;
232 
233     mutable std::mutex mLock;
234     std::set<size_t> mFreeBuffers GUARDED_BY(mLock);
235 };
236 
returnBuffer(size_t bufferId)237 void V4L2BuffersList::returnBuffer(size_t bufferId) {
238     std::lock_guard<std::mutex> lock(mLock);
239 
240     auto inserted = mFreeBuffers.emplace(bufferId);
241     if (!inserted.second) {
242         ALOGE("Returning buffer failed");
243     }
244 }
245 
getFreeBuffer()246 std::optional<size_t> V4L2BuffersList::getFreeBuffer() {
247     std::lock_guard<std::mutex> lock(mLock);
248 
249     auto iter = mFreeBuffers.begin();
250     if (iter == mFreeBuffers.end()) {
251         ALOGV("No free buffer available!");
252         return std::nullopt;
253     }
254 
255     size_t bufferId = *iter;
256     mFreeBuffers.erase(iter);
257 
258     return bufferId;
259 }
260 
getFreeBuffer(size_t requestedBufferId)261 std::optional<size_t> V4L2BuffersList::getFreeBuffer(size_t requestedBufferId) {
262     std::lock_guard<std::mutex> lock(mLock);
263 
264     return (mFreeBuffers.erase(requestedBufferId) > 0) ? std::make_optional(requestedBufferId)
265                                                        : std::nullopt;
266 }
267 
size() const268 size_t V4L2BuffersList::size() const {
269     std::lock_guard<std::mutex> lock(mLock);
270 
271     return mFreeBuffers.size();
272 }
273 
274 // Module-private class that let users query/write V4L2 buffer information. It also makes some
275 // private V4L2Queue methods available to this module only.
276 class V4L2BufferRefBase {
277 public:
278     V4L2BufferRefBase(const struct v4l2_buffer& v4l2Buffer, base::WeakPtr<V4L2Queue> queue);
279     ~V4L2BufferRefBase();
280 
281     V4L2BufferRefBase(const V4L2BufferRefBase&) = delete;
282     V4L2BufferRefBase& operator=(const V4L2BufferRefBase&) = delete;
283 
284     bool queueBuffer();
285     void* getPlaneMapping(const size_t plane);
286 
287     // Checks that the number of passed FDs is adequate for the current format and buffer
288     // configuration. Only useful for DMABUF buffers.
289     bool checkNumFDsForFormat(const size_t numFds) const;
290 
291     // Data from the buffer, that users can query and/or write.
292     struct v4l2_buffer mV4l2Buffer;
293     // WARNING: do not change this to a vector or something smaller than VIDEO_MAX_PLANES, otherwise
294     // the Tegra libv4l2 will write data beyond the number of allocated planes, resulting in memory
295     // corruption.
296     struct v4l2_plane mV4l2Planes[VIDEO_MAX_PLANES];
297 
298 private:
bufferId() const299     size_t bufferId() const { return mV4l2Buffer.index; }
300 
301     friend class V4L2WritableBufferRef;
302     // A weak pointer to the queue this buffer belongs to. Will remain valid as long as the
303     // underlying V4L2 buffer is valid too. This can only be accessed from the sequence protected by
304     // sequence_checker_. Thread-safe methods (like ~V4L2BufferRefBase) must *never* access this.
305     base::WeakPtr<V4L2Queue> mQueue;
306     // Where to return this buffer if it goes out of scope without being queued.
307     scoped_refptr<V4L2BuffersList> mReturnTo;
308     bool queued = false;
309 
310     SEQUENCE_CHECKER(mSequenceChecker);
311 };
312 
V4L2BufferRefBase(const struct v4l2_buffer & v4l2Buffer,base::WeakPtr<V4L2Queue> queue)313 V4L2BufferRefBase::V4L2BufferRefBase(const struct v4l2_buffer& v4l2Buffer,
314                                      base::WeakPtr<V4L2Queue> queue)
315       : mQueue(std::move(queue)), mReturnTo(mQueue->mFreeBuffers) {
316     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
317     ALOG_ASSERT(V4L2_TYPE_IS_MULTIPLANAR(v4l2Buffer.type));
318     ALOG_ASSERT(v4l2Buffer.length <= base::size(mV4l2Planes));
319     ALOG_ASSERT(mReturnTo);
320 
321     memcpy(&mV4l2Buffer, &v4l2Buffer, sizeof(mV4l2Buffer));
322     memcpy(mV4l2Planes, v4l2Buffer.m.planes, sizeof(struct v4l2_plane) * v4l2Buffer.length);
323     mV4l2Buffer.m.planes = mV4l2Planes;
324 }
325 
~V4L2BufferRefBase()326 V4L2BufferRefBase::~V4L2BufferRefBase() {
327     // We are the last reference and are only accessing the thread-safe mReturnTo, so we are safe
328     // to call from any sequence. If we have been queued, then the queue is our owner so we don't
329     // need to return to the free buffers list.
330     if (!queued) mReturnTo->returnBuffer(bufferId());
331 }
332 
queueBuffer()333 bool V4L2BufferRefBase::queueBuffer() {
334     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
335 
336     if (!mQueue) return false;
337 
338     queued = mQueue->queueBuffer(&mV4l2Buffer);
339 
340     return queued;
341 }
342 
getPlaneMapping(const size_t plane)343 void* V4L2BufferRefBase::getPlaneMapping(const size_t plane) {
344     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
345 
346     if (!mQueue) return nullptr;
347 
348     return mQueue->mBuffers[bufferId()]->getPlaneMapping(plane);
349 }
350 
checkNumFDsForFormat(const size_t numFds) const351 bool V4L2BufferRefBase::checkNumFDsForFormat(const size_t numFds) const {
352     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
353 
354     if (!mQueue) return false;
355 
356     // We have not used SetFormat(), assume this is ok.
357     // Hopefully we standardize SetFormat() in the future.
358     if (!mQueue->mCurrentFormat) return true;
359 
360     const size_t requiredFds = mQueue->mCurrentFormat->fmt.pix_mp.num_planes;
361     // Sanity check.
362     ALOG_ASSERT(mV4l2Buffer.length == requiredFds);
363     if (numFds < requiredFds) {
364         ALOGE("Insufficient number of FDs given for the current format. "
365               "%zu provided, %zu required.",
366               numFds, requiredFds);
367         return false;
368     }
369 
370     const auto* planes = mV4l2Buffer.m.planes;
371     for (size_t i = mV4l2Buffer.length - 1; i >= numFds; --i) {
372         // Assume that an fd is a duplicate of a previous plane's fd if offset != 0. Otherwise, if
373         // offset == 0, return error as it is likely pointing to a new plane.
374         if (planes[i].data_offset == 0) {
375             ALOGE("Additional dmabuf fds point to a new buffer.");
376             return false;
377         }
378     }
379 
380     return true;
381 }
382 
V4L2WritableBufferRef(const struct v4l2_buffer & v4l2Buffer,base::WeakPtr<V4L2Queue> queue)383 V4L2WritableBufferRef::V4L2WritableBufferRef(const struct v4l2_buffer& v4l2Buffer,
384                                              base::WeakPtr<V4L2Queue> queue)
385       : mBufferData(std::make_unique<V4L2BufferRefBase>(v4l2Buffer, std::move(queue))) {
386     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
387 }
388 
V4L2WritableBufferRef(V4L2WritableBufferRef && other)389 V4L2WritableBufferRef::V4L2WritableBufferRef(V4L2WritableBufferRef&& other)
390       : mBufferData(std::move(other.mBufferData)) {
391     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
392     DCHECK_CALLED_ON_VALID_SEQUENCE(other.mSequenceChecker);
393 }
394 
~V4L2WritableBufferRef()395 V4L2WritableBufferRef::~V4L2WritableBufferRef() {
396     // Only valid references should be sequence-checked
397     if (mBufferData) {
398         DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
399     }
400 }
401 
operator =(V4L2WritableBufferRef && other)402 V4L2WritableBufferRef& V4L2WritableBufferRef::operator=(V4L2WritableBufferRef&& other) {
403     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
404     DCHECK_CALLED_ON_VALID_SEQUENCE(other.mSequenceChecker);
405 
406     if (this == &other) return *this;
407 
408     mBufferData = std::move(other.mBufferData);
409 
410     return *this;
411 }
412 
memory() const413 enum v4l2_memory V4L2WritableBufferRef::memory() const {
414     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
415     ALOG_ASSERT(mBufferData);
416 
417     return static_cast<enum v4l2_memory>(mBufferData->mV4l2Buffer.memory);
418 }
419 
doQueue()420 bool V4L2WritableBufferRef::doQueue() && {
421     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
422     ALOG_ASSERT(mBufferData);
423 
424     bool queued = mBufferData->queueBuffer();
425 
426     // Clear our own reference.
427     mBufferData.reset();
428 
429     return queued;
430 }
431 
queueMMap()432 bool V4L2WritableBufferRef::queueMMap() && {
433     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
434     ALOG_ASSERT(mBufferData);
435 
436     // Move ourselves so our data gets freed no matter when we return
437     V4L2WritableBufferRef self(std::move(*this));
438 
439     if (self.memory() != V4L2_MEMORY_MMAP) {
440         ALOGE("Called on invalid buffer type!");
441         return false;
442     }
443 
444     return std::move(self).doQueue();
445 }
446 
queueUserPtr(const std::vector<void * > & ptrs)447 bool V4L2WritableBufferRef::queueUserPtr(const std::vector<void*>& ptrs) && {
448     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
449     ALOG_ASSERT(mBufferData);
450 
451     // Move ourselves so our data gets freed no matter when we return
452     V4L2WritableBufferRef self(std::move(*this));
453 
454     if (self.memory() != V4L2_MEMORY_USERPTR) {
455         ALOGE("Called on invalid buffer type!");
456         return false;
457     }
458 
459     if (ptrs.size() != self.planesCount()) {
460         ALOGE("Provided %zu pointers while we require %u.", ptrs.size(),
461               self.mBufferData->mV4l2Buffer.length);
462         return false;
463     }
464 
465     for (size_t i = 0; i < ptrs.size(); i++) {
466         self.mBufferData->mV4l2Buffer.m.planes[i].m.userptr =
467                 reinterpret_cast<unsigned long>(ptrs[i]);
468     }
469 
470     return std::move(self).doQueue();
471 }
472 
queueDMABuf(const std::vector<int> & fds)473 bool V4L2WritableBufferRef::queueDMABuf(const std::vector<int>& fds) && {
474     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
475     ALOG_ASSERT(mBufferData);
476 
477     // Move ourselves so our data gets freed no matter when we return
478     V4L2WritableBufferRef self(std::move(*this));
479 
480     if (self.memory() != V4L2_MEMORY_DMABUF) {
481         ALOGE("Called on invalid buffer type!");
482         return false;
483     }
484 
485     if (!self.mBufferData->checkNumFDsForFormat(fds.size())) return false;
486 
487     size_t numPlanes = self.planesCount();
488     for (size_t i = 0; i < numPlanes; i++) self.mBufferData->mV4l2Buffer.m.planes[i].m.fd = fds[i];
489 
490     return std::move(self).doQueue();
491 }
492 
planesCount() const493 size_t V4L2WritableBufferRef::planesCount() const {
494     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
495     ALOG_ASSERT(mBufferData);
496 
497     return mBufferData->mV4l2Buffer.length;
498 }
499 
getPlaneSize(const size_t plane) const500 size_t V4L2WritableBufferRef::getPlaneSize(const size_t plane) const {
501     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
502     ALOG_ASSERT(mBufferData);
503 
504     if (plane >= planesCount()) {
505         ALOGE("Invalid plane %zu requested.", plane);
506         return 0;
507     }
508 
509     return mBufferData->mV4l2Buffer.m.planes[plane].length;
510 }
511 
setPlaneSize(const size_t plane,const size_t size)512 void V4L2WritableBufferRef::setPlaneSize(const size_t plane, const size_t size) {
513     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
514     ALOG_ASSERT(mBufferData);
515 
516     enum v4l2_memory mem = memory();
517     if (mem == V4L2_MEMORY_MMAP) {
518         ALOG_ASSERT(mBufferData->mV4l2Buffer.m.planes[plane].length == size);
519         return;
520     }
521     ALOG_ASSERT(mem == V4L2_MEMORY_USERPTR || mem == V4L2_MEMORY_DMABUF);
522 
523     if (plane >= planesCount()) {
524         ALOGE("Invalid plane %zu requested.", plane);
525         return;
526     }
527 
528     mBufferData->mV4l2Buffer.m.planes[plane].length = size;
529 }
530 
getPlaneMapping(const size_t plane)531 void* V4L2WritableBufferRef::getPlaneMapping(const size_t plane) {
532     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
533     ALOG_ASSERT(mBufferData);
534 
535     return mBufferData->getPlaneMapping(plane);
536 }
537 
setTimeStamp(const struct timeval & timestamp)538 void V4L2WritableBufferRef::setTimeStamp(const struct timeval& timestamp) {
539     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
540     ALOG_ASSERT(mBufferData);
541 
542     mBufferData->mV4l2Buffer.timestamp = timestamp;
543 }
544 
getTimeStamp() const545 const struct timeval& V4L2WritableBufferRef::getTimeStamp() const {
546     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
547     ALOG_ASSERT(mBufferData);
548 
549     return mBufferData->mV4l2Buffer.timestamp;
550 }
551 
setPlaneBytesUsed(const size_t plane,const size_t bytesUsed)552 void V4L2WritableBufferRef::setPlaneBytesUsed(const size_t plane, const size_t bytesUsed) {
553     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
554     ALOG_ASSERT(mBufferData);
555 
556     if (plane >= planesCount()) {
557         ALOGE("Invalid plane %zu requested.", plane);
558         return;
559     }
560 
561     if (bytesUsed > getPlaneSize(plane)) {
562         ALOGE("Set bytes used %zu larger than plane size %zu.", bytesUsed, getPlaneSize(plane));
563         return;
564     }
565 
566     mBufferData->mV4l2Buffer.m.planes[plane].bytesused = bytesUsed;
567 }
568 
getPlaneBytesUsed(const size_t plane) const569 size_t V4L2WritableBufferRef::getPlaneBytesUsed(const size_t plane) const {
570     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
571     ALOG_ASSERT(mBufferData);
572 
573     if (plane >= planesCount()) {
574         ALOGE("Invalid plane %zu requested.", plane);
575         return 0;
576     }
577 
578     return mBufferData->mV4l2Buffer.m.planes[plane].bytesused;
579 }
580 
setPlaneDataOffset(const size_t plane,const size_t dataOffset)581 void V4L2WritableBufferRef::setPlaneDataOffset(const size_t plane, const size_t dataOffset) {
582     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
583     ALOG_ASSERT(mBufferData);
584 
585     if (plane >= planesCount()) {
586         ALOGE("Invalid plane %zu requested.", plane);
587         return;
588     }
589 
590     mBufferData->mV4l2Buffer.m.planes[plane].data_offset = dataOffset;
591 }
592 
bufferId() const593 size_t V4L2WritableBufferRef::bufferId() const {
594     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
595     ALOG_ASSERT(mBufferData);
596 
597     return mBufferData->mV4l2Buffer.index;
598 }
599 
V4L2ReadableBuffer(const struct v4l2_buffer & v4l2Buffer,base::WeakPtr<V4L2Queue> queue)600 V4L2ReadableBuffer::V4L2ReadableBuffer(const struct v4l2_buffer& v4l2Buffer,
601                                        base::WeakPtr<V4L2Queue> queue)
602       : mBufferData(std::make_unique<V4L2BufferRefBase>(v4l2Buffer, std::move(queue))) {
603     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
604 }
605 
~V4L2ReadableBuffer()606 V4L2ReadableBuffer::~V4L2ReadableBuffer() {
607     // This method is thread-safe. Since we are the destructor, we are guaranteed to be called from
608     // the only remaining reference to us. Also, we are just calling the destructor of buffer_data_,
609     // which is also thread-safe.
610     ALOG_ASSERT(mBufferData);
611 }
612 
isLast() const613 bool V4L2ReadableBuffer::isLast() const {
614     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
615     ALOG_ASSERT(mBufferData);
616 
617     return mBufferData->mV4l2Buffer.flags & V4L2_BUF_FLAG_LAST;
618 }
619 
isKeyframe() const620 bool V4L2ReadableBuffer::isKeyframe() const {
621     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
622     ALOG_ASSERT(mBufferData);
623 
624     return mBufferData->mV4l2Buffer.flags & V4L2_BUF_FLAG_KEYFRAME;
625 }
626 
getTimeStamp() const627 struct timeval V4L2ReadableBuffer::getTimeStamp() const {
628     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
629     ALOG_ASSERT(mBufferData);
630 
631     return mBufferData->mV4l2Buffer.timestamp;
632 }
633 
planesCount() const634 size_t V4L2ReadableBuffer::planesCount() const {
635     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
636     ALOG_ASSERT(mBufferData);
637 
638     return mBufferData->mV4l2Buffer.length;
639 }
640 
getPlaneMapping(const size_t plane) const641 const void* V4L2ReadableBuffer::getPlaneMapping(const size_t plane) const {
642     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
643     DCHECK(mBufferData);
644 
645     return mBufferData->getPlaneMapping(plane);
646 }
647 
getPlaneBytesUsed(const size_t plane) const648 size_t V4L2ReadableBuffer::getPlaneBytesUsed(const size_t plane) const {
649     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
650     ALOG_ASSERT(mBufferData);
651 
652     if (plane >= planesCount()) {
653         ALOGE("Invalid plane %zu requested.", plane);
654         return 0;
655     }
656 
657     return mBufferData->mV4l2Planes[plane].bytesused;
658 }
659 
getPlaneDataOffset(const size_t plane) const660 size_t V4L2ReadableBuffer::getPlaneDataOffset(const size_t plane) const {
661     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
662     ALOG_ASSERT(mBufferData);
663 
664     if (plane >= planesCount()) {
665         ALOGE("Invalid plane %zu requested.", plane);
666         return 0;
667     }
668 
669     return mBufferData->mV4l2Planes[plane].data_offset;
670 }
671 
bufferId() const672 size_t V4L2ReadableBuffer::bufferId() const {
673     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
674     ALOG_ASSERT(mBufferData);
675 
676     return mBufferData->mV4l2Buffer.index;
677 }
678 
679 // This class is used to expose buffer reference classes constructors to this module. This is to
680 // ensure that nobody else can create buffer references.
681 class V4L2BufferRefFactory {
682 public:
CreateWritableRef(const struct v4l2_buffer & v4l2Buffer,base::WeakPtr<V4L2Queue> queue)683     static V4L2WritableBufferRef CreateWritableRef(const struct v4l2_buffer& v4l2Buffer,
684                                                    base::WeakPtr<V4L2Queue> queue) {
685         return V4L2WritableBufferRef(v4l2Buffer, std::move(queue));
686     }
687 
CreateReadableRef(const struct v4l2_buffer & v4l2Buffer,base::WeakPtr<V4L2Queue> queue)688     static V4L2ReadableBufferRef CreateReadableRef(const struct v4l2_buffer& v4l2Buffer,
689                                                    base::WeakPtr<V4L2Queue> queue) {
690         return new V4L2ReadableBuffer(v4l2Buffer, std::move(queue));
691     }
692 };
693 
694 //// Helper macros that print the queue type with logs.
695 #define ALOGEQ(fmt, ...) ALOGE("(%s)" fmt, V4L2Device::v4L2BufferTypeToString(mType), ##__VA_ARGS__)
696 #define ALOGVQ(fmt, ...) ALOGD("(%s)" fmt, V4L2Device::v4L2BufferTypeToString(mType), ##__VA_ARGS__)
697 
V4L2Queue(scoped_refptr<V4L2Device> dev,enum v4l2_buf_type type,base::OnceClosure destroyCb)698 V4L2Queue::V4L2Queue(scoped_refptr<V4L2Device> dev, enum v4l2_buf_type type,
699                      base::OnceClosure destroyCb)
700       : mType(type), mDevice(dev), mDestroyCb(std::move(destroyCb)) {
701     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
702 }
703 
~V4L2Queue()704 V4L2Queue::~V4L2Queue() {
705     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
706 
707     if (mIsStreaming) {
708         ALOGEQ("Queue is still streaming, trying to stop it...");
709         streamoff();
710     }
711 
712     ALOG_ASSERT(mQueuedBuffers.empty());
713     ALOG_ASSERT(!mFreeBuffers);
714 
715     if (!mBuffers.empty()) {
716         ALOGEQ("Buffers are still allocated, trying to deallocate them...");
717         deallocateBuffers();
718     }
719 
720     std::move(mDestroyCb).Run();
721 }
722 
setFormat(uint32_t fourcc,const ui::Size & size,size_t bufferSize,uint32_t stride)723 std::optional<struct v4l2_format> V4L2Queue::setFormat(uint32_t fourcc, const ui::Size& size,
724                                                        size_t bufferSize, uint32_t stride) {
725     struct v4l2_format format = buildV4L2Format(mType, fourcc, size, bufferSize, stride);
726     if (mDevice->ioctl(VIDIOC_S_FMT, &format) != 0 || format.fmt.pix_mp.pixelformat != fourcc) {
727         ALOGEQ("Failed to set format (format_fourcc=0x%" PRIx32 ")", fourcc);
728         return std::nullopt;
729     }
730 
731     mCurrentFormat = format;
732     return mCurrentFormat;
733 }
734 
tryFormat(uint32_t fourcc,const ui::Size & size,size_t bufferSize)735 std::optional<struct v4l2_format> V4L2Queue::tryFormat(uint32_t fourcc, const ui::Size& size,
736                                                        size_t bufferSize) {
737     struct v4l2_format format = buildV4L2Format(mType, fourcc, size, bufferSize, 0);
738     if (mDevice->ioctl(VIDIOC_TRY_FMT, &format) != 0 || format.fmt.pix_mp.pixelformat != fourcc) {
739         ALOGEQ("Tried format not supported (format_fourcc=0x%" PRIx32 ")", fourcc);
740         return std::nullopt;
741     }
742 
743     return format;
744 }
745 
getFormat()746 std::pair<std::optional<struct v4l2_format>, int> V4L2Queue::getFormat() {
747     struct v4l2_format format;
748     memset(&format, 0, sizeof(format));
749     format.type = mType;
750     if (mDevice->ioctl(VIDIOC_G_FMT, &format) != 0) {
751         ALOGEQ("Failed to get format");
752         return std::make_pair(std::nullopt, errno);
753     }
754 
755     return std::make_pair(format, 0);
756 }
757 
allocateBuffers(size_t count,enum v4l2_memory memory)758 size_t V4L2Queue::allocateBuffers(size_t count, enum v4l2_memory memory) {
759     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
760     ALOG_ASSERT(!mFreeBuffers);
761     ALOG_ASSERT(mQueuedBuffers.size() == 0u);
762 
763     if (isStreaming()) {
764         ALOGEQ("Cannot allocate buffers while streaming.");
765         return 0;
766     }
767 
768     if (mBuffers.size() != 0) {
769         ALOGEQ("Cannot allocate new buffers while others are still allocated.");
770         return 0;
771     }
772 
773     if (count == 0) {
774         ALOGEQ("Attempting to allocate 0 buffers.");
775         return 0;
776     }
777 
778     // First query the number of planes in the buffers we are about to request. This should not be
779     // required, but Tegra's VIDIOC_QUERYBUF will fail on output buffers if the number of specified
780     // planes does not exactly match the format.
781     struct v4l2_format format = {.type = mType};
782     int ret = mDevice->ioctl(VIDIOC_G_FMT, &format);
783     if (ret) {
784         ALOGEQ("VIDIOC_G_FMT failed");
785         return 0;
786     }
787     mPlanesCount = format.fmt.pix_mp.num_planes;
788     ALOG_ASSERT(mPlanesCount <= static_cast<size_t>(VIDEO_MAX_PLANES));
789 
790     struct v4l2_requestbuffers reqbufs;
791     memset(&reqbufs, 0, sizeof(reqbufs));
792     reqbufs.count = count;
793     reqbufs.type = mType;
794     reqbufs.memory = memory;
795     ALOGVQ("Requesting %zu buffers.", count);
796 
797     ret = mDevice->ioctl(VIDIOC_REQBUFS, &reqbufs);
798     if (ret) {
799         ALOGEQ("VIDIOC_REQBUFS failed");
800         return 0;
801     }
802     ALOGVQ("Queue %u: got %u buffers.", mType, reqbufs.count);
803 
804     mMemory = memory;
805 
806     mFreeBuffers = new V4L2BuffersList();
807 
808     // Now query all buffer information.
809     for (size_t i = 0; i < reqbufs.count; i++) {
810         auto buffer = V4L2Buffer::create(mDevice, mType, mMemory, format, i);
811 
812         if (!buffer) {
813             deallocateBuffers();
814 
815             return 0;
816         }
817 
818         mBuffers.emplace_back(std::move(buffer));
819         mFreeBuffers->returnBuffer(i);
820     }
821 
822     ALOG_ASSERT(mFreeBuffers);
823     ALOG_ASSERT(mFreeBuffers->size() == mBuffers.size());
824     ALOG_ASSERT(mQueuedBuffers.size() == 0u);
825 
826     return mBuffers.size();
827 }
828 
deallocateBuffers()829 bool V4L2Queue::deallocateBuffers() {
830     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
831 
832     if (isStreaming()) {
833         ALOGEQ("Cannot deallocate buffers while streaming.");
834         return false;
835     }
836 
837     if (mBuffers.size() == 0) return true;
838 
839     mWeakThisFactory.InvalidateWeakPtrs();
840     mBuffers.clear();
841     mFreeBuffers = nullptr;
842 
843     // Free all buffers.
844     struct v4l2_requestbuffers reqbufs;
845     memset(&reqbufs, 0, sizeof(reqbufs));
846     reqbufs.count = 0;
847     reqbufs.type = mType;
848     reqbufs.memory = mMemory;
849 
850     int ret = mDevice->ioctl(VIDIOC_REQBUFS, &reqbufs);
851     if (ret) {
852         ALOGEQ("VIDIOC_REQBUFS failed");
853         return false;
854     }
855 
856     ALOG_ASSERT(!mFreeBuffers);
857     ALOG_ASSERT(mQueuedBuffers.size() == 0u);
858 
859     return true;
860 }
861 
getMemoryUsage() const862 size_t V4L2Queue::getMemoryUsage() const {
863     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
864     size_t usage = 0;
865     for (const auto& buf : mBuffers) {
866         usage += buf->getMemoryUsage();
867     }
868     return usage;
869 }
870 
getMemoryType() const871 v4l2_memory V4L2Queue::getMemoryType() const {
872     return mMemory;
873 }
874 
getFreeBuffer()875 std::optional<V4L2WritableBufferRef> V4L2Queue::getFreeBuffer() {
876     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
877 
878     // No buffers allocated at the moment?
879     if (!mFreeBuffers) return std::nullopt;
880 
881     auto bufferId = mFreeBuffers->getFreeBuffer();
882     if (!bufferId.has_value()) return std::nullopt;
883 
884     return V4L2BufferRefFactory::CreateWritableRef(mBuffers[bufferId.value()]->v4l2_buffer(),
885                                                    mWeakThisFactory.GetWeakPtr());
886 }
887 
getFreeBuffer(size_t requestedBufferIid)888 std::optional<V4L2WritableBufferRef> V4L2Queue::getFreeBuffer(size_t requestedBufferIid) {
889     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
890 
891     // No buffers allocated at the moment?
892     if (!mFreeBuffers) return std::nullopt;
893 
894     auto bufferId = mFreeBuffers->getFreeBuffer(requestedBufferIid);
895     if (!bufferId.has_value()) return std::nullopt;
896 
897     return V4L2BufferRefFactory::CreateWritableRef(mBuffers[bufferId.value()]->v4l2_buffer(),
898                                                    mWeakThisFactory.GetWeakPtr());
899 }
900 
queueBuffer(struct v4l2_buffer * v4l2Buffer)901 bool V4L2Queue::queueBuffer(struct v4l2_buffer* v4l2Buffer) {
902     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
903 
904     int ret = mDevice->ioctl(VIDIOC_QBUF, v4l2Buffer);
905     if (ret) {
906         ALOGEQ("VIDIOC_QBUF failed");
907         return false;
908     }
909 
910     auto inserted = mQueuedBuffers.emplace(v4l2Buffer->index);
911     if (!inserted.second) {
912         ALOGE("Queuing buffer failed");
913         return false;
914     }
915 
916     mDevice->schedulePoll();
917 
918     return true;
919 }
920 
dequeueBuffer()921 std::pair<bool, V4L2ReadableBufferRef> V4L2Queue::dequeueBuffer() {
922     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
923 
924     // No need to dequeue if no buffers queued.
925     if (queuedBuffersCount() == 0) return std::make_pair(true, nullptr);
926 
927     if (!isStreaming()) {
928         ALOGEQ("Attempting to dequeue a buffer while not streaming.");
929         return std::make_pair(true, nullptr);
930     }
931 
932     struct v4l2_buffer v4l2Buffer;
933     memset(&v4l2Buffer, 0, sizeof(v4l2Buffer));
934     // WARNING: do not change this to a vector or something smaller than VIDEO_MAX_PLANES, otherwise
935     // the Tegra libv4l2 will write data beyond the number of allocated planes, resulting in memory
936     // corruption.
937     struct v4l2_plane planes[VIDEO_MAX_PLANES];
938     memset(planes, 0, sizeof(planes));
939     v4l2Buffer.type = mType;
940     v4l2Buffer.memory = mMemory;
941     v4l2Buffer.m.planes = planes;
942     v4l2Buffer.length = mPlanesCount;
943     int ret = mDevice->ioctl(VIDIOC_DQBUF, &v4l2Buffer);
944     if (ret) {
945         // TODO(acourbot): we should not have to check for EPIPE as codec clients should not call
946         // this method after the last buffer is dequeued.
947         switch (errno) {
948         case EAGAIN:
949         case EPIPE:
950             // This is not an error so we'll need to continue polling but won't provide a buffer.
951             mDevice->schedulePoll();
952             return std::make_pair(true, nullptr);
953         default:
954             ALOGEQ("VIDIOC_DQBUF failed");
955             return std::make_pair(false, nullptr);
956         }
957     }
958 
959     auto it = mQueuedBuffers.find(v4l2Buffer.index);
960     ALOG_ASSERT(it != mQueuedBuffers.end());
961     mQueuedBuffers.erase(*it);
962 
963     if (queuedBuffersCount() > 0) mDevice->schedulePoll();
964 
965     ALOG_ASSERT(mFreeBuffers);
966     return std::make_pair(true, V4L2BufferRefFactory::CreateReadableRef(
967                                         v4l2Buffer, mWeakThisFactory.GetWeakPtr()));
968 }
969 
isStreaming() const970 bool V4L2Queue::isStreaming() const {
971     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
972 
973     return mIsStreaming;
974 }
975 
streamon()976 bool V4L2Queue::streamon() {
977     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
978 
979     if (mIsStreaming) return true;
980 
981     int arg = static_cast<int>(mType);
982     int ret = mDevice->ioctl(VIDIOC_STREAMON, &arg);
983     if (ret) {
984         ALOGEQ("VIDIOC_STREAMON failed");
985         return false;
986     }
987 
988     mIsStreaming = true;
989 
990     return true;
991 }
992 
streamoff()993 bool V4L2Queue::streamoff() {
994     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
995 
996     // We do not check the value of IsStreaming(), because we may have queued buffers to the queue
997     // and wish to get them back - in such as case, we may need to do a VIDIOC_STREAMOFF on a
998     // stopped queue.
999 
1000     int arg = static_cast<int>(mType);
1001     int ret = mDevice->ioctl(VIDIOC_STREAMOFF, &arg);
1002     if (ret) {
1003         ALOGEQ("VIDIOC_STREAMOFF failed");
1004         return false;
1005     }
1006 
1007     for (const auto& bufferId : mQueuedBuffers) {
1008         ALOG_ASSERT(mFreeBuffers);
1009         mFreeBuffers->returnBuffer(bufferId);
1010     }
1011 
1012     mQueuedBuffers.clear();
1013 
1014     mIsStreaming = false;
1015 
1016     return true;
1017 }
1018 
allocatedBuffersCount() const1019 size_t V4L2Queue::allocatedBuffersCount() const {
1020     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
1021 
1022     return mBuffers.size();
1023 }
1024 
freeBuffersCount() const1025 size_t V4L2Queue::freeBuffersCount() const {
1026     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
1027 
1028     return mFreeBuffers ? mFreeBuffers->size() : 0;
1029 }
1030 
queuedBuffersCount() const1031 size_t V4L2Queue::queuedBuffersCount() const {
1032     DCHECK_CALLED_ON_VALID_SEQUENCE(mSequenceChecker);
1033 
1034     return mQueuedBuffers.size();
1035 }
1036 
1037 #undef ALOGEQ
1038 #undef ALOGVQ
1039 
1040 // This class is used to expose V4L2Queue's constructor to this module. This is to ensure that
1041 // nobody else can create instances of it.
1042 class V4L2QueueFactory {
1043 public:
createQueue(scoped_refptr<V4L2Device> dev,enum v4l2_buf_type type,base::OnceClosure destroyCb)1044     static scoped_refptr<V4L2Queue> createQueue(scoped_refptr<V4L2Device> dev,
1045                                                 enum v4l2_buf_type type,
1046                                                 base::OnceClosure destroyCb) {
1047         return new V4L2Queue(std::move(dev), type, std::move(destroyCb));
1048     }
1049 };
1050 
V4L2Device()1051 V4L2Device::V4L2Device() {
1052     DETACH_FROM_SEQUENCE(mClientSequenceChecker);
1053 }
1054 
~V4L2Device()1055 V4L2Device::~V4L2Device() {
1056     closeDevice();
1057 }
1058 
getQueue(enum v4l2_buf_type type)1059 scoped_refptr<V4L2Queue> V4L2Device::getQueue(enum v4l2_buf_type type) {
1060     DCHECK_CALLED_ON_VALID_SEQUENCE(mClientSequenceChecker);
1061 
1062     switch (type) {
1063     // Supported queue types.
1064     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1065     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1066         break;
1067     default:
1068         ALOGE("Unsupported V4L2 queue type: %u", type);
1069         return nullptr;
1070     }
1071 
1072     // TODO(acourbot): we should instead query the device for available queues, and allocate them
1073     // accordingly. This will do for now though.
1074     auto it = mQueues.find(type);
1075     if (it != mQueues.end()) return scoped_refptr<V4L2Queue>(it->second);
1076 
1077     scoped_refptr<V4L2Queue> queue = V4L2QueueFactory::createQueue(
1078             this, type, base::BindOnce(&V4L2Device::onQueueDestroyed, this, type));
1079 
1080     mQueues[type] = queue.get();
1081     return queue;
1082 }
1083 
onQueueDestroyed(v4l2_buf_type bufType)1084 void V4L2Device::onQueueDestroyed(v4l2_buf_type bufType) {
1085     DCHECK_CALLED_ON_VALID_SEQUENCE(mClientSequenceChecker);
1086 
1087     auto it = mQueues.find(bufType);
1088     ALOG_ASSERT(it != mQueues.end());
1089     mQueues.erase(it);
1090 }
1091 
1092 // static
create()1093 scoped_refptr<V4L2Device> V4L2Device::create() {
1094     ALOGV("%s()", __func__);
1095     return scoped_refptr<V4L2Device>(new V4L2Device());
1096 }
1097 
open(Type type,uint32_t v4l2PixFmt)1098 bool V4L2Device::open(Type type, uint32_t v4l2PixFmt) {
1099     ALOGV("%s()", __func__);
1100 
1101     std::string path = getDevicePathFor(type, v4l2PixFmt);
1102 
1103     if (path.empty()) {
1104         ALOGE("No devices supporting %s for type: %u", fourccToString(v4l2PixFmt).c_str(),
1105               static_cast<uint32_t>(type));
1106         return false;
1107     }
1108 
1109     if (!openDevicePath(path, type)) {
1110         ALOGE("Failed opening %s", path.c_str());
1111         return false;
1112     }
1113 
1114     mDevicePollInterruptFd.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));
1115     if (!mDevicePollInterruptFd.is_valid()) {
1116         ALOGE("Failed creating a poll interrupt fd");
1117         return false;
1118     }
1119 
1120     return true;
1121 }
1122 
ioctl(int request,void * arg)1123 int V4L2Device::ioctl(int request, void* arg) {
1124     ALOG_ASSERT(mDeviceFd.is_valid());
1125     return HANDLE_EINTR(::ioctl(mDeviceFd.get(), request, arg));
1126 }
1127 
poll(bool pollDevice,bool * eventPending)1128 bool V4L2Device::poll(bool pollDevice, bool* eventPending) {
1129     struct pollfd pollfds[2];
1130     nfds_t nfds;
1131     int pollfd = -1;
1132 
1133     pollfds[0].fd = mDevicePollInterruptFd.get();
1134     pollfds[0].events = POLLIN | POLLERR;
1135     nfds = 1;
1136 
1137     if (pollDevice) {
1138         ALOGV("adding device fd to poll() set");
1139         pollfds[nfds].fd = mDeviceFd.get();
1140         pollfds[nfds].events = POLLIN | POLLOUT | POLLERR | POLLPRI;
1141         pollfd = nfds;
1142         nfds++;
1143     }
1144 
1145     if (HANDLE_EINTR(::poll(pollfds, nfds, -1)) == -1) {
1146         ALOGE("poll() failed");
1147         return false;
1148     }
1149     *eventPending = (pollfd != -1 && pollfds[pollfd].revents & POLLPRI);
1150     return true;
1151 }
1152 
mmap(void * addr,unsigned int len,int prot,int flags,unsigned int offset)1153 void* V4L2Device::mmap(void* addr, unsigned int len, int prot, int flags, unsigned int offset) {
1154     DCHECK(mDeviceFd.is_valid());
1155     return ::mmap(addr, len, prot, flags, mDeviceFd.get(), offset);
1156 }
1157 
munmap(void * addr,unsigned int len)1158 void V4L2Device::munmap(void* addr, unsigned int len) {
1159     ::munmap(addr, len);
1160 }
1161 
setDevicePollInterrupt()1162 bool V4L2Device::setDevicePollInterrupt() {
1163     ALOGV("%s()", __func__);
1164 
1165     const uint64_t buf = 1;
1166     if (HANDLE_EINTR(write(mDevicePollInterruptFd.get(), &buf, sizeof(buf))) == -1) {
1167         ALOGE("write() failed");
1168         return false;
1169     }
1170     return true;
1171 }
1172 
clearDevicePollInterrupt()1173 bool V4L2Device::clearDevicePollInterrupt() {
1174     ALOGV("%s()", __func__);
1175 
1176     uint64_t buf;
1177     if (HANDLE_EINTR(read(mDevicePollInterruptFd.get(), &buf, sizeof(buf))) == -1) {
1178         if (errno == EAGAIN) {
1179             // No interrupt flag set, and we're reading nonblocking.  Not an error.
1180             return true;
1181         } else {
1182             ALOGE("read() failed");
1183             return false;
1184         }
1185     }
1186     return true;
1187 }
1188 
getDmabufsForV4L2Buffer(int index,size_t numPlanes,enum v4l2_buf_type bufType)1189 std::vector<base::ScopedFD> V4L2Device::getDmabufsForV4L2Buffer(int index, size_t numPlanes,
1190                                                                 enum v4l2_buf_type bufType) {
1191     ALOGV("%s()", __func__);
1192     ALOG_ASSERT(V4L2_TYPE_IS_MULTIPLANAR(bufType));
1193 
1194     std::vector<base::ScopedFD> dmabufFds;
1195     for (size_t i = 0; i < numPlanes; ++i) {
1196         struct v4l2_exportbuffer expbuf;
1197         memset(&expbuf, 0, sizeof(expbuf));
1198         expbuf.type = bufType;
1199         expbuf.index = index;
1200         expbuf.plane = i;
1201         expbuf.flags = O_CLOEXEC;
1202         if (ioctl(VIDIOC_EXPBUF, &expbuf) != 0) {
1203             dmabufFds.clear();
1204             break;
1205         }
1206 
1207         dmabufFds.push_back(base::ScopedFD(expbuf.fd));
1208     }
1209 
1210     return dmabufFds;
1211 }
1212 
preferredInputFormat(Type type)1213 std::vector<uint32_t> V4L2Device::preferredInputFormat(Type type) {
1214     if (type == Type::kEncoder) return {V4L2_PIX_FMT_NV12M, V4L2_PIX_FMT_NV12};
1215 
1216     return {};
1217 }
1218 
1219 // static
C2ProfileToV4L2PixFmt(C2Config::profile_t profile,bool sliceBased)1220 uint32_t V4L2Device::C2ProfileToV4L2PixFmt(C2Config::profile_t profile, bool sliceBased) {
1221     if (profile >= C2Config::PROFILE_AVC_BASELINE &&
1222         profile <= C2Config::PROFILE_AVC_ENHANCED_MULTIVIEW_DEPTH_HIGH) {
1223         if (sliceBased) {
1224             return V4L2_PIX_FMT_H264_SLICE;
1225         } else {
1226             return V4L2_PIX_FMT_H264;
1227         }
1228     } else if (profile >= C2Config::PROFILE_VP8_0 && profile <= C2Config::PROFILE_VP8_3) {
1229         if (sliceBased) {
1230             return V4L2_PIX_FMT_VP8_FRAME;
1231         } else {
1232             return V4L2_PIX_FMT_VP8;
1233         }
1234     } else if (profile >= C2Config::PROFILE_VP9_0 && profile <= C2Config::PROFILE_VP9_3) {
1235         if (sliceBased) {
1236             return V4L2_PIX_FMT_VP9_FRAME;
1237         } else {
1238             return V4L2_PIX_FMT_VP9;
1239         }
1240     } else {
1241         ALOGE("Unknown profile: %s", profileToString(profile));
1242         return 0;
1243     }
1244 }
1245 
1246 // static
v4L2ProfileToC2Profile(VideoCodec codec,uint32_t profile)1247 C2Config::profile_t V4L2Device::v4L2ProfileToC2Profile(VideoCodec codec, uint32_t profile) {
1248     switch (codec) {
1249     case VideoCodec::H264:
1250         switch (profile) {
1251         case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
1252         case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
1253             return C2Config::PROFILE_AVC_BASELINE;
1254         case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
1255             return C2Config::PROFILE_AVC_MAIN;
1256         case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
1257             return C2Config::PROFILE_AVC_EXTENDED;
1258         case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
1259             return C2Config::PROFILE_AVC_HIGH;
1260         }
1261         break;
1262     case VideoCodec::VP8:
1263         switch (profile) {
1264         case V4L2_MPEG_VIDEO_VP8_PROFILE_0:
1265             return C2Config::PROFILE_VP8_0;
1266         case V4L2_MPEG_VIDEO_VP8_PROFILE_1:
1267             return C2Config::PROFILE_VP8_1;
1268         case V4L2_MPEG_VIDEO_VP8_PROFILE_2:
1269             return C2Config::PROFILE_VP8_2;
1270         case V4L2_MPEG_VIDEO_VP8_PROFILE_3:
1271             return C2Config::PROFILE_VP8_3;
1272         }
1273         break;
1274     case VideoCodec::VP9:
1275         switch (profile) {
1276         case V4L2_MPEG_VIDEO_VP9_PROFILE_0:
1277             return C2Config::PROFILE_VP9_0;
1278         case V4L2_MPEG_VIDEO_VP9_PROFILE_1:
1279             return C2Config::PROFILE_VP9_1;
1280         case V4L2_MPEG_VIDEO_VP9_PROFILE_2:
1281             return C2Config::PROFILE_VP9_2;
1282         case V4L2_MPEG_VIDEO_VP9_PROFILE_3:
1283             return C2Config::PROFILE_VP9_3;
1284         }
1285         break;
1286     default:
1287         ALOGE("Unknown codec: %u", codec);
1288     }
1289     ALOGE("Unknown profile: %u", profile);
1290     return C2Config::PROFILE_UNUSED;
1291 }
1292 
v4L2PixFmtToC2Profiles(uint32_t pixFmt,bool)1293 std::vector<C2Config::profile_t> V4L2Device::v4L2PixFmtToC2Profiles(uint32_t pixFmt,
1294                                                                     bool /*isEncoder*/) {
1295     auto getSupportedProfiles = [this](VideoCodec codec,
1296                                        std::vector<C2Config::profile_t>* profiles) {
1297         uint32_t queryId = 0;
1298         switch (codec) {
1299         case VideoCodec::H264:
1300             queryId = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
1301             break;
1302         case VideoCodec::VP8:
1303             queryId = V4L2_CID_MPEG_VIDEO_VP8_PROFILE;
1304             break;
1305         case VideoCodec::VP9:
1306             queryId = V4L2_CID_MPEG_VIDEO_VP9_PROFILE;
1307             break;
1308         default:
1309             return false;
1310         }
1311 
1312         v4l2_queryctrl queryCtrl = {};
1313         queryCtrl.id = queryId;
1314         if (ioctl(VIDIOC_QUERYCTRL, &queryCtrl) != 0) {
1315             return false;
1316         }
1317         v4l2_querymenu queryMenu = {};
1318         queryMenu.id = queryCtrl.id;
1319         for (queryMenu.index = queryCtrl.minimum;
1320              static_cast<int>(queryMenu.index) <= queryCtrl.maximum; queryMenu.index++) {
1321             if (ioctl(VIDIOC_QUERYMENU, &queryMenu) == 0) {
1322                 const C2Config::profile_t profile =
1323                         V4L2Device::v4L2ProfileToC2Profile(codec, queryMenu.index);
1324                 if (profile != C2Config::PROFILE_UNUSED) profiles->push_back(profile);
1325             }
1326         }
1327         return true;
1328     };
1329 
1330     std::vector<C2Config::profile_t> profiles;
1331     switch (pixFmt) {
1332     case V4L2_PIX_FMT_H264:
1333     case V4L2_PIX_FMT_H264_SLICE:
1334         if (!getSupportedProfiles(VideoCodec::H264, &profiles)) {
1335             ALOGW("Driver doesn't support QUERY H264 profiles, "
1336                   "use default values, Base, Main, High");
1337             profiles = {
1338                     C2Config::PROFILE_AVC_BASELINE,
1339                     C2Config::PROFILE_AVC_MAIN,
1340                     C2Config::PROFILE_AVC_HIGH,
1341             };
1342         }
1343         break;
1344     case V4L2_PIX_FMT_VP8:
1345     case V4L2_PIX_FMT_VP8_FRAME:
1346         if (!getSupportedProfiles(VideoCodec::VP8, &profiles)) {
1347             ALOGW("Driver doesn't support QUERY VP8 profiles, use default values, Profile0");
1348             profiles = {C2Config::PROFILE_VP8_0};
1349         }
1350         break;
1351     case V4L2_PIX_FMT_VP9:
1352     case V4L2_PIX_FMT_VP9_FRAME:
1353         if (!getSupportedProfiles(VideoCodec::VP9, &profiles)) {
1354             ALOGW("Driver doesn't support QUERY VP9 profiles, use default values, Profile0");
1355             profiles = {C2Config::PROFILE_VP9_0};
1356         }
1357         break;
1358     default:
1359         ALOGE("Unhandled pixelformat %s", fourccToString(pixFmt).c_str());
1360         return {};
1361     }
1362 
1363     // Erase duplicated profiles.
1364     std::sort(profiles.begin(), profiles.end());
1365     profiles.erase(std::unique(profiles.begin(), profiles.end()), profiles.end());
1366     return profiles;
1367 }
1368 
1369 // static
c2ProfileToV4L2H264Profile(C2Config::profile_t profile)1370 int32_t V4L2Device::c2ProfileToV4L2H264Profile(C2Config::profile_t profile) {
1371     switch (profile) {
1372     case C2Config::PROFILE_AVC_BASELINE:
1373         return V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
1374     case C2Config::PROFILE_AVC_MAIN:
1375         return V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
1376     case C2Config::PROFILE_AVC_EXTENDED:
1377         return V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED;
1378     case C2Config::PROFILE_AVC_HIGH:
1379         return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
1380     case C2Config::PROFILE_AVC_HIGH_10:
1381         return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10;
1382     case C2Config::PROFILE_AVC_HIGH_422:
1383         return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422;
1384     case C2Config::PROFILE_AVC_HIGH_444_PREDICTIVE:
1385         return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE;
1386     case C2Config::PROFILE_AVC_SCALABLE_BASELINE:
1387         return V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE;
1388     case C2Config::PROFILE_AVC_SCALABLE_HIGH:
1389         return V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH;
1390     case C2Config::PROFILE_AVC_STEREO_HIGH:
1391         return V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH;
1392     case C2Config::PROFILE_AVC_MULTIVIEW_HIGH:
1393         return V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH;
1394     default:
1395         ALOGE("Add more cases as needed");
1396         return -1;
1397     }
1398 }
1399 
1400 // static
h264LevelIdcToV4L2H264Level(uint8_t levelIdc)1401 int32_t V4L2Device::h264LevelIdcToV4L2H264Level(uint8_t levelIdc) {
1402     switch (levelIdc) {
1403     case 10:
1404         return V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
1405     case 9:
1406         return V4L2_MPEG_VIDEO_H264_LEVEL_1B;
1407     case 11:
1408         return V4L2_MPEG_VIDEO_H264_LEVEL_1_1;
1409     case 12:
1410         return V4L2_MPEG_VIDEO_H264_LEVEL_1_2;
1411     case 13:
1412         return V4L2_MPEG_VIDEO_H264_LEVEL_1_3;
1413     case 20:
1414         return V4L2_MPEG_VIDEO_H264_LEVEL_2_0;
1415     case 21:
1416         return V4L2_MPEG_VIDEO_H264_LEVEL_2_1;
1417     case 22:
1418         return V4L2_MPEG_VIDEO_H264_LEVEL_2_2;
1419     case 30:
1420         return V4L2_MPEG_VIDEO_H264_LEVEL_3_0;
1421     case 31:
1422         return V4L2_MPEG_VIDEO_H264_LEVEL_3_1;
1423     case 32:
1424         return V4L2_MPEG_VIDEO_H264_LEVEL_3_2;
1425     case 40:
1426         return V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
1427     case 41:
1428         return V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
1429     case 42:
1430         return V4L2_MPEG_VIDEO_H264_LEVEL_4_2;
1431     case 50:
1432         return V4L2_MPEG_VIDEO_H264_LEVEL_5_0;
1433     case 51:
1434         return V4L2_MPEG_VIDEO_H264_LEVEL_5_1;
1435     default:
1436         ALOGE("Unrecognized levelIdc: %u", static_cast<uint32_t>(levelIdc));
1437         return -1;
1438     }
1439 }
1440 
1441 // static
C2BitrateModeToV4L2BitrateMode(C2Config::bitrate_mode_t bitrateMode)1442 v4l2_mpeg_video_bitrate_mode V4L2Device::C2BitrateModeToV4L2BitrateMode(
1443         C2Config::bitrate_mode_t bitrateMode) {
1444     switch (bitrateMode) {
1445     case C2Config::bitrate_mode_t::BITRATE_CONST_SKIP_ALLOWED:
1446         ALOGW("BITRATE_CONST_SKIP_ALLOWED not supported, defaulting to BITRATE_CONST");
1447         FALLTHROUGH;
1448     case C2Config::bitrate_mode_t::BITRATE_CONST:
1449         return V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
1450     case C2Config::bitrate_mode_t::BITRATE_VARIABLE_SKIP_ALLOWED:
1451         ALOGW("BITRATE_VARIABLE_SKIP_ALLOWED not supported, defaulting to BITRATE_VARIABLE");
1452         FALLTHROUGH;
1453     case C2Config::bitrate_mode_t::BITRATE_VARIABLE:
1454         return V4L2_MPEG_VIDEO_BITRATE_MODE_VBR;
1455     default:
1456         ALOGW("Unsupported bitrate mode %u, defaulting to BITRATE_VARIABLE",
1457               static_cast<uint32_t>(bitrateMode));
1458         return V4L2_MPEG_VIDEO_BITRATE_MODE_VBR;
1459     }
1460 }
1461 
1462 // static
allocatedSizeFromV4L2Format(const struct v4l2_format & format)1463 ui::Size V4L2Device::allocatedSizeFromV4L2Format(const struct v4l2_format& format) {
1464     ui::Size codedSize;
1465     ui::Size visibleSize;
1466     VideoPixelFormat frameFormat = VideoPixelFormat::UNKNOWN;
1467     size_t bytesPerLine = 0;
1468     // Total bytes in the frame.
1469     size_t sizeimage = 0;
1470 
1471     if (V4L2_TYPE_IS_MULTIPLANAR(format.type)) {
1472         ALOG_ASSERT(format.fmt.pix_mp.num_planes > 0);
1473         bytesPerLine = base::checked_cast<int>(format.fmt.pix_mp.plane_fmt[0].bytesperline);
1474         for (size_t i = 0; i < format.fmt.pix_mp.num_planes; ++i) {
1475             sizeimage += base::checked_cast<int>(format.fmt.pix_mp.plane_fmt[i].sizeimage);
1476         }
1477         visibleSize.set(base::checked_cast<int>(format.fmt.pix_mp.width),
1478                         base::checked_cast<int>(format.fmt.pix_mp.height));
1479         const uint32_t pixFmt = format.fmt.pix_mp.pixelformat;
1480         const auto frameFourcc = Fourcc::fromV4L2PixFmt(pixFmt);
1481         if (!frameFourcc) {
1482             ALOGE("Unsupported format %s", fourccToString(pixFmt).c_str());
1483             return codedSize;
1484         }
1485         frameFormat = frameFourcc->toVideoPixelFormat();
1486     } else {
1487         bytesPerLine = base::checked_cast<int>(format.fmt.pix.bytesperline);
1488         sizeimage = base::checked_cast<int>(format.fmt.pix.sizeimage);
1489         visibleSize.set(base::checked_cast<int>(format.fmt.pix.width),
1490                         base::checked_cast<int>(format.fmt.pix.height));
1491         const uint32_t fourcc = format.fmt.pix.pixelformat;
1492         const auto frameFourcc = Fourcc::fromV4L2PixFmt(fourcc);
1493         if (!frameFourcc) {
1494             ALOGE("Unsupported format %s", fourccToString(fourcc).c_str());
1495             return codedSize;
1496         }
1497         frameFormat = frameFourcc ? frameFourcc->toVideoPixelFormat() : VideoPixelFormat::UNKNOWN;
1498     }
1499 
1500     // V4L2 does not provide per-plane bytesperline (bpl) when different components are sharing one
1501     // physical plane buffer. In this case, it only provides bpl for the first component in the
1502     // plane. So we can't depend on it for calculating height, because bpl may vary within one
1503     // physical plane buffer. For example, YUV420 contains 3 components in one physical plane, with
1504     // Y at 8 bits per pixel, and Cb/Cr at 4 bits per pixel per component, but we only get 8 pits
1505     // per pixel from bytesperline in physical plane 0. So we need to get total frame bpp from
1506     // elsewhere to calculate coded height.
1507 
1508     // We need bits per pixel for one component only to calculate the coded width from bytesperline.
1509     int planeHorizBitsPerPixel = planeHorizontalBitsPerPixel(frameFormat, 0);
1510 
1511     // Adding up bpp for each component will give us total bpp for all components.
1512     int totalBpp = 0;
1513     for (size_t i = 0; i < numPlanes(frameFormat); ++i)
1514         totalBpp += planeBitsPerPixel(frameFormat, i);
1515 
1516     if (sizeimage == 0 || bytesPerLine == 0 || planeHorizBitsPerPixel == 0 || totalBpp == 0 ||
1517         (bytesPerLine * 8) % planeHorizBitsPerPixel != 0) {
1518         ALOGE("Invalid format provided");
1519         return codedSize;
1520     }
1521 
1522     // Coded width can be calculated by taking the first component's bytesperline, which in V4L2
1523     // always applies to the first component in physical plane buffer.
1524     int codedWidth = bytesPerLine * 8 / planeHorizBitsPerPixel;
1525     // Sizeimage is codedWidth * codedHeight * totalBpp.
1526     int codedHeight = sizeimage * 8 / codedWidth / totalBpp;
1527 
1528     codedSize.set(codedWidth, codedHeight);
1529     ALOGV("codedSize=%s", toString(codedSize).c_str());
1530 
1531     // Sanity checks. Calculated coded size has to contain given visible size and fulfill buffer
1532     // byte size requirements.
1533     ALOG_ASSERT(contains(Rect(codedSize), Rect(visibleSize)));
1534     ALOG_ASSERT(sizeimage <= allocationSize(frameFormat, codedSize));
1535 
1536     return codedSize;
1537 }
1538 
1539 // static
v4L2MemoryToString(const v4l2_memory memory)1540 const char* V4L2Device::v4L2MemoryToString(const v4l2_memory memory) {
1541     switch (memory) {
1542     case V4L2_MEMORY_MMAP:
1543         return "V4L2_MEMORY_MMAP";
1544     case V4L2_MEMORY_USERPTR:
1545         return "V4L2_MEMORY_USERPTR";
1546     case V4L2_MEMORY_DMABUF:
1547         return "V4L2_MEMORY_DMABUF";
1548     case V4L2_MEMORY_OVERLAY:
1549         return "V4L2_MEMORY_OVERLAY";
1550     default:
1551         return "UNKNOWN";
1552     }
1553 }
1554 
1555 // static
v4L2BufferTypeToString(const enum v4l2_buf_type bufType)1556 const char* V4L2Device::v4L2BufferTypeToString(const enum v4l2_buf_type bufType) {
1557     switch (bufType) {
1558     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1559         return "OUTPUT";
1560     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1561         return "CAPTURE";
1562     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1563         return "OUTPUT_MPLANE";
1564     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1565         return "CAPTURE_MPLANE";
1566     default:
1567         return "UNKNOWN";
1568     }
1569 }
1570 
1571 // static
v4L2FormatToString(const struct v4l2_format & format)1572 std::string V4L2Device::v4L2FormatToString(const struct v4l2_format& format) {
1573     std::ostringstream s;
1574     s << "v4l2_format type: " << format.type;
1575     if (format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE || format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1576         //  single-planar
1577         const struct v4l2_pix_format& pix = format.fmt.pix;
1578         s << ", width_height: " << toString(ui::Size(pix.width, pix.height))
1579           << ", pixelformat: " << fourccToString(pix.pixelformat) << ", field: " << pix.field
1580           << ", bytesperline: " << pix.bytesperline << ", sizeimage: " << pix.sizeimage;
1581     } else if (V4L2_TYPE_IS_MULTIPLANAR(format.type)) {
1582         const struct v4l2_pix_format_mplane& pixMp = format.fmt.pix_mp;
1583         // As long as num_planes's type is uint8_t, ostringstream treats it as a char instead of an
1584         // integer, which is not what we want. Casting pix_mp.num_planes unsigned int solves the
1585         // issue.
1586         s << ", width_height: " << toString(ui::Size(pixMp.width, pixMp.height))
1587           << ", pixelformat: " << fourccToString(pixMp.pixelformat) << ", field: " << pixMp.field
1588           << ", num_planes: " << static_cast<unsigned int>(pixMp.num_planes);
1589         for (size_t i = 0; i < pixMp.num_planes; ++i) {
1590             const struct v4l2_plane_pix_format& plane_fmt = pixMp.plane_fmt[i];
1591             s << ", plane_fmt[" << i << "].sizeimage: " << plane_fmt.sizeimage << ", plane_fmt["
1592               << i << "].bytesperline: " << plane_fmt.bytesperline;
1593         }
1594     } else {
1595         s << " unsupported yet.";
1596     }
1597     return s.str();
1598 }
1599 
1600 // static
v4L2BufferToString(const struct v4l2_buffer & buffer)1601 std::string V4L2Device::v4L2BufferToString(const struct v4l2_buffer& buffer) {
1602     std::ostringstream s;
1603     s << "v4l2_buffer type: " << buffer.type << ", memory: " << buffer.memory
1604       << ", index: " << buffer.index << " bytesused: " << buffer.bytesused
1605       << ", length: " << buffer.length;
1606     if (buffer.type == V4L2_BUF_TYPE_VIDEO_CAPTURE || buffer.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1607         //  single-planar
1608         if (buffer.memory == V4L2_MEMORY_MMAP) {
1609             s << ", m.offset: " << buffer.m.offset;
1610         } else if (buffer.memory == V4L2_MEMORY_USERPTR) {
1611             s << ", m.userptr: " << buffer.m.userptr;
1612         } else if (buffer.memory == V4L2_MEMORY_DMABUF) {
1613             s << ", m.fd: " << buffer.m.fd;
1614         };
1615     } else if (V4L2_TYPE_IS_MULTIPLANAR(buffer.type)) {
1616         for (size_t i = 0; i < buffer.length; ++i) {
1617             const struct v4l2_plane& plane = buffer.m.planes[i];
1618             s << ", m.planes[" << i << "](bytesused: " << plane.bytesused
1619               << ", length: " << plane.length << ", data_offset: " << plane.data_offset;
1620             if (buffer.memory == V4L2_MEMORY_MMAP) {
1621                 s << ", m.mem_offset: " << plane.m.mem_offset;
1622             } else if (buffer.memory == V4L2_MEMORY_USERPTR) {
1623                 s << ", m.userptr: " << plane.m.userptr;
1624             } else if (buffer.memory == V4L2_MEMORY_DMABUF) {
1625                 s << ", m.fd: " << plane.m.fd;
1626             }
1627             s << ")";
1628         }
1629     } else {
1630         s << " unsupported yet.";
1631     }
1632     return s.str();
1633 }
1634 
1635 // static
v4L2FormatToVideoFrameLayout(const struct v4l2_format & format)1636 std::optional<VideoFrameLayout> V4L2Device::v4L2FormatToVideoFrameLayout(
1637         const struct v4l2_format& format) {
1638     if (!V4L2_TYPE_IS_MULTIPLANAR(format.type)) {
1639         ALOGE("v4l2_buf_type is not multiplanar: 0x%" PRIx32, format.type);
1640         return std::nullopt;
1641     }
1642     const v4l2_pix_format_mplane& pixMp = format.fmt.pix_mp;
1643     const uint32_t& pixFmt = pixMp.pixelformat;
1644     const auto videoFourcc = Fourcc::fromV4L2PixFmt(pixFmt);
1645     if (!videoFourcc) {
1646         ALOGE("Failed to convert pixel format to VideoPixelFormat: %s",
1647               fourccToString(pixFmt).c_str());
1648         return std::nullopt;
1649     }
1650     const VideoPixelFormat videoFormat = videoFourcc->toVideoPixelFormat();
1651     const size_t numBuffers = pixMp.num_planes;
1652     const size_t numColorPlanes = numPlanes(videoFormat);
1653     if (numColorPlanes == 0) {
1654         ALOGE("Unsupported video format for NumPlanes(): %s",
1655               videoPixelFormatToString(videoFormat).c_str());
1656         return std::nullopt;
1657     }
1658     if (numBuffers > numColorPlanes) {
1659         ALOGE("pix_mp.num_planes: %zu should not be larger than NumPlanes(%s): %zu", numBuffers,
1660               videoPixelFormatToString(videoFormat).c_str(), numColorPlanes);
1661         return std::nullopt;
1662     }
1663     // Reserve capacity in advance to prevent unnecessary vector reallocation.
1664     std::vector<VideoFramePlane> planes;
1665     planes.reserve(numColorPlanes);
1666     for (size_t i = 0; i < numBuffers; ++i) {
1667         const v4l2_plane_pix_format& planeFormat = pixMp.plane_fmt[i];
1668         planes.push_back(VideoFramePlane{planeFormat.bytesperline, 0u, planeFormat.sizeimage});
1669     }
1670     // For the case that #color planes > #buffers, it fills stride of color plane which does not map
1671     // to buffer. Right now only some pixel formats are supported: NV12, YUV420, YVU420.
1672     if (numColorPlanes > numBuffers) {
1673         const uint32_t yStride = planes[0].mStride;
1674         // Note that y_stride is from v4l2 bytesperline and its type is uint32_t. It is safe to cast
1675         // to size_t.
1676         const size_t yStrideAbs = static_cast<size_t>(yStride);
1677         switch (pixFmt) {
1678         case V4L2_PIX_FMT_NV12:
1679             // The stride of UV is the same as Y in NV12. The height is half of Y plane.
1680             planes.push_back(VideoFramePlane{yStride, yStrideAbs * pixMp.height,
1681                                              yStrideAbs * pixMp.height / 2});
1682             ALOG_ASSERT(2u == planes.size());
1683             break;
1684         case V4L2_PIX_FMT_YUV420:
1685         case V4L2_PIX_FMT_YVU420: {
1686             // The spec claims that two Cx rows (including padding) is exactly as long as one Y row
1687             // (including padding). So stride of Y must be even number.
1688             if (yStride % 2 != 0 || pixMp.height % 2 != 0) {
1689                 ALOGE("Plane-Y stride and height should be even; stride: %u, height: %u", yStride,
1690                       pixMp.height);
1691                 return std::nullopt;
1692             }
1693             const uint32_t halfStride = yStride / 2;
1694             const size_t plane0Area = yStrideAbs * pixMp.height;
1695             const size_t plane1Area = plane0Area / 4;
1696             planes.push_back(VideoFramePlane{halfStride, plane0Area, plane1Area});
1697             planes.push_back(VideoFramePlane{halfStride, plane0Area + plane1Area, plane1Area});
1698             ALOG_ASSERT(3u == planes.size());
1699             break;
1700         }
1701         default:
1702             ALOGE("Cannot derive stride for each plane for pixel format %s",
1703                   fourccToString(pixFmt).c_str());
1704             return std::nullopt;
1705         }
1706     }
1707 
1708     return VideoFrameLayout{videoFormat, ui::Size(pixMp.width, pixMp.height), std::move(planes),
1709                             (numBuffers > 1)};
1710 }
1711 
1712 // static
getNumPlanesOfV4L2PixFmt(uint32_t pixFmt)1713 size_t V4L2Device::getNumPlanesOfV4L2PixFmt(uint32_t pixFmt) {
1714     std::optional<Fourcc> fourcc = Fourcc::fromV4L2PixFmt(pixFmt);
1715     if (fourcc && fourcc->isMultiPlanar()) {
1716         return numPlanes(fourcc->toVideoPixelFormat());
1717     }
1718     return 1u;
1719 }
1720 
getSupportedResolution(uint32_t pixelFormat,ui::Size * minResolution,ui::Size * maxResolution)1721 void V4L2Device::getSupportedResolution(uint32_t pixelFormat, ui::Size* minResolution,
1722                                         ui::Size* maxResolution) {
1723     maxResolution->set(0, 0);
1724     minResolution->set(0, 0);
1725     v4l2_frmsizeenum frameSize;
1726     memset(&frameSize, 0, sizeof(frameSize));
1727     frameSize.pixel_format = pixelFormat;
1728     for (; ioctl(VIDIOC_ENUM_FRAMESIZES, &frameSize) == 0; ++frameSize.index) {
1729         if (frameSize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
1730             if (frameSize.discrete.width >= base::checked_cast<uint32_t>(maxResolution->width) &&
1731                 frameSize.discrete.height >= base::checked_cast<uint32_t>(maxResolution->height)) {
1732                 maxResolution->set(frameSize.discrete.width, frameSize.discrete.height);
1733             }
1734             if (isEmpty(*minResolution) ||
1735                 (frameSize.discrete.width <= base::checked_cast<uint32_t>(minResolution->width) &&
1736                  frameSize.discrete.height <=
1737                          base::checked_cast<uint32_t>(minResolution->height))) {
1738                 minResolution->set(frameSize.discrete.width, frameSize.discrete.height);
1739             }
1740         } else if (frameSize.type == V4L2_FRMSIZE_TYPE_STEPWISE ||
1741                    frameSize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
1742             maxResolution->set(frameSize.stepwise.max_width, frameSize.stepwise.max_height);
1743             minResolution->set(frameSize.stepwise.min_width, frameSize.stepwise.min_height);
1744             break;
1745         }
1746     }
1747     if (isEmpty(*maxResolution)) {
1748         maxResolution->set(1920, 1088);
1749         ALOGE("GetSupportedResolution failed to get maximum resolution for fourcc %s, "
1750               "fall back to %s",
1751               fourccToString(pixelFormat).c_str(), toString(*maxResolution).c_str());
1752     }
1753     if (isEmpty(*minResolution)) {
1754         minResolution->set(16, 16);
1755         ALOGE("GetSupportedResolution failed to get minimum resolution for fourcc %s, "
1756               "fall back to %s",
1757               fourccToString(pixelFormat).c_str(), toString(*minResolution).c_str());
1758     }
1759 }
1760 
enumerateSupportedPixelformats(v4l2_buf_type bufType)1761 std::vector<uint32_t> V4L2Device::enumerateSupportedPixelformats(v4l2_buf_type bufType) {
1762     std::vector<uint32_t> pixelFormats;
1763 
1764     v4l2_fmtdesc fmtDesc;
1765     memset(&fmtDesc, 0, sizeof(fmtDesc));
1766     fmtDesc.type = bufType;
1767 
1768     for (; ioctl(VIDIOC_ENUM_FMT, &fmtDesc) == 0; ++fmtDesc.index) {
1769         ALOGV("Found %s (0x%" PRIx32 ")", fmtDesc.description, fmtDesc.pixelformat);
1770         pixelFormats.push_back(fmtDesc.pixelformat);
1771     }
1772 
1773     return pixelFormats;
1774 }
1775 
getSupportedDecodeProfiles(const size_t numFormats,const uint32_t pixelFormats[])1776 V4L2Device::SupportedDecodeProfiles V4L2Device::getSupportedDecodeProfiles(
1777         const size_t numFormats, const uint32_t pixelFormats[]) {
1778     SupportedDecodeProfiles supportedProfiles;
1779 
1780     Type type = Type::kDecoder;
1781     const auto& devices = getDevicesForType(type);
1782     for (const auto& device : devices) {
1783         if (!openDevicePath(device.first, type)) {
1784             ALOGV("Failed opening %s", device.first.c_str());
1785             continue;
1786         }
1787 
1788         const auto& profiles = enumerateSupportedDecodeProfiles(numFormats, pixelFormats);
1789         supportedProfiles.insert(supportedProfiles.end(), profiles.begin(), profiles.end());
1790         closeDevice();
1791     }
1792 
1793     return supportedProfiles;
1794 }
1795 
getSupportedEncodeProfiles()1796 V4L2Device::SupportedEncodeProfiles V4L2Device::getSupportedEncodeProfiles() {
1797     SupportedEncodeProfiles supportedProfiles;
1798 
1799     Type type = Type::kEncoder;
1800     const auto& devices = getDevicesForType(type);
1801     for (const auto& device : devices) {
1802         if (!openDevicePath(device.first, type)) {
1803             ALOGV("Failed opening %s", device.first.c_str());
1804             continue;
1805         }
1806 
1807         const auto& profiles = enumerateSupportedEncodeProfiles();
1808         supportedProfiles.insert(supportedProfiles.end(), profiles.begin(), profiles.end());
1809         closeDevice();
1810     }
1811 
1812     return supportedProfiles;
1813 }
1814 
enumerateSupportedDecodeProfiles(const size_t numFormats,const uint32_t pixelFormats[])1815 V4L2Device::SupportedDecodeProfiles V4L2Device::enumerateSupportedDecodeProfiles(
1816         const size_t numFormats, const uint32_t pixelFormats[]) {
1817     SupportedDecodeProfiles profiles;
1818 
1819     const auto& supportedPixelformats =
1820             enumerateSupportedPixelformats(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
1821 
1822     for (uint32_t pixelFormat : supportedPixelformats) {
1823         if (std::find(pixelFormats, pixelFormats + numFormats, pixelFormat) ==
1824             pixelFormats + numFormats)
1825             continue;
1826 
1827         SupportedDecodeProfile profile;
1828         getSupportedResolution(pixelFormat, &profile.min_resolution, &profile.max_resolution);
1829 
1830         const auto videoCodecProfiles = v4L2PixFmtToC2Profiles(pixelFormat, false);
1831 
1832         for (const auto& videoCodecProfile : videoCodecProfiles) {
1833             profile.profile = videoCodecProfile;
1834             profiles.push_back(profile);
1835 
1836             ALOGV("Found decoder profile %s, resolutions: %s %s", profileToString(profile.profile),
1837                   toString(profile.min_resolution).c_str(),
1838                   toString(profile.max_resolution).c_str());
1839         }
1840     }
1841 
1842     return profiles;
1843 }
1844 
enumerateSupportedEncodeProfiles()1845 V4L2Device::SupportedEncodeProfiles V4L2Device::enumerateSupportedEncodeProfiles() {
1846     SupportedEncodeProfiles profiles;
1847 
1848     const auto& supportedPixelformats =
1849             enumerateSupportedPixelformats(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
1850 
1851     for (const auto& pixelformat : supportedPixelformats) {
1852         SupportedEncodeProfile profile;
1853         profile.max_framerate_numerator = 30;
1854         profile.max_framerate_denominator = 1;
1855         ui::Size minResolution;
1856         getSupportedResolution(pixelformat, &minResolution, &profile.max_resolution);
1857 
1858         const auto videoCodecProfiles = v4L2PixFmtToC2Profiles(pixelformat, true);
1859 
1860         for (const auto& videoCodecProfile : videoCodecProfiles) {
1861             profile.profile = videoCodecProfile;
1862             profiles.push_back(profile);
1863 
1864             ALOGV("Found encoder profile %s, max resolution: %s", profileToString(profile.profile),
1865                   toString(profile.max_resolution).c_str());
1866         }
1867     }
1868 
1869     return profiles;
1870 }
1871 
startPolling(android::V4L2DevicePoller::EventCallback eventCallback,base::RepeatingClosure errorCallback)1872 bool V4L2Device::startPolling(android::V4L2DevicePoller::EventCallback eventCallback,
1873                               base::RepeatingClosure errorCallback) {
1874     DCHECK_CALLED_ON_VALID_SEQUENCE(mClientSequenceChecker);
1875 
1876     if (!mDevicePoller) {
1877         mDevicePoller = std::make_unique<android::V4L2DevicePoller>(this, "V4L2DeviceThreadPoller");
1878     }
1879 
1880     bool ret = mDevicePoller->startPolling(std::move(eventCallback), std::move(errorCallback));
1881 
1882     if (!ret) mDevicePoller = nullptr;
1883 
1884     return ret;
1885 }
1886 
stopPolling()1887 bool V4L2Device::stopPolling() {
1888     DCHECK_CALLED_ON_VALID_SEQUENCE(mClientSequenceChecker);
1889 
1890     return !mDevicePoller || mDevicePoller->stopPolling();
1891 }
1892 
schedulePoll()1893 void V4L2Device::schedulePoll() {
1894     DCHECK_CALLED_ON_VALID_SEQUENCE(mClientSequenceChecker);
1895 
1896     if (!mDevicePoller || !mDevicePoller->isPolling()) return;
1897 
1898     mDevicePoller->schedulePoll();
1899 }
1900 
isCtrlExposed(uint32_t ctrlId)1901 bool V4L2Device::isCtrlExposed(uint32_t ctrlId) {
1902     DCHECK_CALLED_ON_VALID_SEQUENCE(mClientSequenceChecker);
1903 
1904     struct v4l2_queryctrl queryCtrl;
1905     memset(&queryCtrl, 0, sizeof(queryCtrl));
1906     queryCtrl.id = ctrlId;
1907 
1908     return ioctl(VIDIOC_QUERYCTRL, &queryCtrl) == 0;
1909 }
1910 
setExtCtrls(uint32_t ctrlClass,std::vector<V4L2ExtCtrl> ctrls)1911 bool V4L2Device::setExtCtrls(uint32_t ctrlClass, std::vector<V4L2ExtCtrl> ctrls) {
1912     DCHECK_CALLED_ON_VALID_SEQUENCE(mClientSequenceChecker);
1913 
1914     if (ctrls.empty()) return true;
1915 
1916     struct v4l2_ext_controls extCtrls;
1917     memset(&extCtrls, 0, sizeof(extCtrls));
1918     extCtrls.ctrl_class = ctrlClass;
1919     extCtrls.count = ctrls.size();
1920     extCtrls.controls = &ctrls[0].ctrl;
1921     return ioctl(VIDIOC_S_EXT_CTRLS, &extCtrls) == 0;
1922 }
1923 
isCommandSupported(uint32_t commandId)1924 bool V4L2Device::isCommandSupported(uint32_t commandId) {
1925     DCHECK_CALLED_ON_VALID_SEQUENCE(mClientSequenceChecker);
1926 
1927     struct v4l2_encoder_cmd cmd;
1928     memset(&cmd, 0, sizeof(cmd));
1929     cmd.cmd = commandId;
1930 
1931     return ioctl(VIDIOC_TRY_ENCODER_CMD, &cmd) == 0;
1932 }
1933 
hasCapabilities(uint32_t capabilities)1934 bool V4L2Device::hasCapabilities(uint32_t capabilities) {
1935     DCHECK_CALLED_ON_VALID_SEQUENCE(mClientSequenceChecker);
1936 
1937     struct v4l2_capability caps;
1938     memset(&caps, 0, sizeof(caps));
1939     if (ioctl(VIDIOC_QUERYCAP, &caps) != 0) {
1940         ALOGE("Failed to query capabilities");
1941         return false;
1942     }
1943 
1944     return (caps.capabilities & capabilities) == capabilities;
1945 }
1946 
openDevicePath(const std::string & path,Type)1947 bool V4L2Device::openDevicePath(const std::string& path, Type /*type*/) {
1948     ALOG_ASSERT(!mDeviceFd.is_valid());
1949 
1950     mDeviceFd.reset(HANDLE_EINTR(::open(path.c_str(), O_RDWR | O_NONBLOCK | O_CLOEXEC)));
1951     if (!mDeviceFd.is_valid()) return false;
1952 
1953     return true;
1954 }
1955 
closeDevice()1956 void V4L2Device::closeDevice() {
1957     ALOGV("%s()", __func__);
1958 
1959     mDeviceFd.reset();
1960 }
1961 
enumerateDevicesForType(Type type)1962 void V4L2Device::enumerateDevicesForType(Type type) {
1963     // video input/output devices are registered as /dev/videoX in V4L2.
1964     static const std::string kVideoDevicePattern = "/dev/video";
1965 
1966     std::string devicePattern;
1967     v4l2_buf_type bufType;
1968     switch (type) {
1969     case Type::kDecoder:
1970         devicePattern = kVideoDevicePattern;
1971         bufType = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1972         break;
1973     case Type::kEncoder:
1974         devicePattern = kVideoDevicePattern;
1975         bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1976         break;
1977     default:
1978         ALOGE("Only decoder and encoder types are supported!!");
1979         return;
1980     }
1981 
1982     std::vector<std::string> candidatePaths;
1983 
1984     // TODO(posciak): Remove this legacy unnumbered device once all platforms are updated to use
1985     // numbered devices.
1986     candidatePaths.push_back(devicePattern);
1987 
1988     // We are sandboxed, so we can't query directory contents to check which devices are actually
1989     // available. Try to open the first 16; if not present, we will just fail to open immediately.
1990     for (int i = 0; i < 16; ++i) {
1991         candidatePaths.push_back(base::StringPrintf("%s%d", devicePattern.c_str(), i));
1992     }
1993 
1994     Devices devices;
1995     for (const auto& path : candidatePaths) {
1996         if (!openDevicePath(path, type)) {
1997             continue;
1998         }
1999 
2000         const auto& supportedPixelformats = enumerateSupportedPixelformats(bufType);
2001         if (!supportedPixelformats.empty()) {
2002             ALOGV("Found device: %s", path.c_str());
2003             devices.push_back(std::make_pair(path, supportedPixelformats));
2004         }
2005 
2006         closeDevice();
2007     }
2008 
2009     ALOG_ASSERT(mDevicesByType.count(type) == 0u);
2010     mDevicesByType[type] = devices;
2011 }
2012 
getDevicesForType(Type type)2013 const V4L2Device::Devices& V4L2Device::getDevicesForType(Type type) {
2014     if (mDevicesByType.count(type) == 0) enumerateDevicesForType(type);
2015 
2016     ALOG_ASSERT(mDevicesByType.count(type) != 0u);
2017     return mDevicesByType[type];
2018 }
2019 
getDevicePathFor(Type type,uint32_t pixFmt)2020 std::string V4L2Device::getDevicePathFor(Type type, uint32_t pixFmt) {
2021     const Devices& devices = getDevicesForType(type);
2022 
2023     for (const auto& device : devices) {
2024         if (std::find(device.second.begin(), device.second.end(), pixFmt) != device.second.end())
2025             return device.first;
2026     }
2027 
2028     return std::string();
2029 }
2030 
2031 }  // namespace android
2032