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