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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
387 }
388
V4L2WritableBufferRef(V4L2WritableBufferRef && other)389 V4L2WritableBufferRef::V4L2WritableBufferRef(V4L2WritableBufferRef&& other)
390 : mBufferData(std::move(other.mBufferData)) {
391 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
399 }
400 }
401
operator =(V4L2WritableBufferRef && other)402 V4L2WritableBufferRef& V4L2WritableBufferRef::operator=(V4L2WritableBufferRef&& other) {
403 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
415 ALOG_ASSERT(mBufferData);
416
417 return static_cast<enum v4l2_memory>(mBufferData->mV4l2Buffer.memory);
418 }
419
doQueue()420 bool V4L2WritableBufferRef::doQueue() && {
421 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
540 ALOG_ASSERT(mBufferData);
541
542 mBufferData->mV4l2Buffer.timestamp = timestamp;
543 }
544
getTimeStamp() const545 const struct timeval& V4L2WritableBufferRef::getTimeStamp() const {
546 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
615 ALOG_ASSERT(mBufferData);
616
617 return mBufferData->mV4l2Buffer.flags & V4L2_BUF_FLAG_LAST;
618 }
619
isKeyframe() const620 bool V4L2ReadableBuffer::isKeyframe() const {
621 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
622 ALOG_ASSERT(mBufferData);
623
624 return mBufferData->mV4l2Buffer.flags & V4L2_BUF_FLAG_KEYFRAME;
625 }
626
getTimeStamp() const627 struct timeval V4L2ReadableBuffer::getTimeStamp() const {
628 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
629 ALOG_ASSERT(mBufferData);
630
631 return mBufferData->mV4l2Buffer.timestamp;
632 }
633
planesCount() const634 size_t V4L2ReadableBuffer::planesCount() const {
635 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
702 }
703
~V4L2Queue()704 V4L2Queue::~V4L2Queue() {
705 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
972
973 return mIsStreaming;
974 }
975
streamon()976 bool V4L2Queue::streamon() {
977 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
1021
1022 return mBuffers.size();
1023 }
1024
freeBuffersCount() const1025 size_t V4L2Queue::freeBuffersCount() const {
1026 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
1027
1028 return mFreeBuffers ? mFreeBuffers->size() : 0;
1029 }
1030
queuedBuffersCount() const1031 size_t V4L2Queue::queuedBuffersCount() const {
1032 ALOG_ASSERT(mSequenceChecker.CalledOnValidSequence());
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
allocatedSizeFromV4L2Format(const struct v4l2_format & format)1442 ui::Size V4L2Device::allocatedSizeFromV4L2Format(const struct v4l2_format& format) {
1443 ui::Size codedSize;
1444 ui::Size visibleSize;
1445 VideoPixelFormat frameFormat = VideoPixelFormat::UNKNOWN;
1446 size_t bytesPerLine = 0;
1447 // Total bytes in the frame.
1448 size_t sizeimage = 0;
1449
1450 if (V4L2_TYPE_IS_MULTIPLANAR(format.type)) {
1451 ALOG_ASSERT(format.fmt.pix_mp.num_planes > 0);
1452 bytesPerLine = base::checked_cast<int>(format.fmt.pix_mp.plane_fmt[0].bytesperline);
1453 for (size_t i = 0; i < format.fmt.pix_mp.num_planes; ++i) {
1454 sizeimage += base::checked_cast<int>(format.fmt.pix_mp.plane_fmt[i].sizeimage);
1455 }
1456 visibleSize.set(base::checked_cast<int>(format.fmt.pix_mp.width),
1457 base::checked_cast<int>(format.fmt.pix_mp.height));
1458 const uint32_t pixFmt = format.fmt.pix_mp.pixelformat;
1459 const auto frameFourcc = Fourcc::fromV4L2PixFmt(pixFmt);
1460 if (!frameFourcc) {
1461 ALOGE("Unsupported format %s", fourccToString(pixFmt).c_str());
1462 return codedSize;
1463 }
1464 frameFormat = frameFourcc->toVideoPixelFormat();
1465 } else {
1466 bytesPerLine = base::checked_cast<int>(format.fmt.pix.bytesperline);
1467 sizeimage = base::checked_cast<int>(format.fmt.pix.sizeimage);
1468 visibleSize.set(base::checked_cast<int>(format.fmt.pix.width),
1469 base::checked_cast<int>(format.fmt.pix.height));
1470 const uint32_t fourcc = format.fmt.pix.pixelformat;
1471 const auto frameFourcc = Fourcc::fromV4L2PixFmt(fourcc);
1472 if (!frameFourcc) {
1473 ALOGE("Unsupported format %s", fourccToString(fourcc).c_str());
1474 return codedSize;
1475 }
1476 frameFormat = frameFourcc ? frameFourcc->toVideoPixelFormat() : VideoPixelFormat::UNKNOWN;
1477 }
1478
1479 // V4L2 does not provide per-plane bytesperline (bpl) when different components are sharing one
1480 // physical plane buffer. In this case, it only provides bpl for the first component in the
1481 // plane. So we can't depend on it for calculating height, because bpl may vary within one
1482 // physical plane buffer. For example, YUV420 contains 3 components in one physical plane, with
1483 // Y at 8 bits per pixel, and Cb/Cr at 4 bits per pixel per component, but we only get 8 pits
1484 // per pixel from bytesperline in physical plane 0. So we need to get total frame bpp from
1485 // elsewhere to calculate coded height.
1486
1487 // We need bits per pixel for one component only to calculate the coded width from bytesperline.
1488 int planeHorizBitsPerPixel = planeHorizontalBitsPerPixel(frameFormat, 0);
1489
1490 // Adding up bpp for each component will give us total bpp for all components.
1491 int totalBpp = 0;
1492 for (size_t i = 0; i < numPlanes(frameFormat); ++i)
1493 totalBpp += planeBitsPerPixel(frameFormat, i);
1494
1495 if (sizeimage == 0 || bytesPerLine == 0 || planeHorizBitsPerPixel == 0 || totalBpp == 0 ||
1496 (bytesPerLine * 8) % planeHorizBitsPerPixel != 0) {
1497 ALOGE("Invalid format provided");
1498 return codedSize;
1499 }
1500
1501 // Coded width can be calculated by taking the first component's bytesperline, which in V4L2
1502 // always applies to the first component in physical plane buffer.
1503 int codedWidth = bytesPerLine * 8 / planeHorizBitsPerPixel;
1504 // Sizeimage is codedWidth * codedHeight * totalBpp.
1505 int codedHeight = sizeimage * 8 / codedWidth / totalBpp;
1506
1507 codedSize.set(codedWidth, codedHeight);
1508 ALOGV("codedSize=%s", toString(codedSize).c_str());
1509
1510 // Sanity checks. Calculated coded size has to contain given visible size and fulfill buffer
1511 // byte size requirements.
1512 ALOG_ASSERT(Rect(codedSize).Contains(Rect(visibleSize)));
1513 ALOG_ASSERT(sizeimage <= allocationSize(frameFormat, codedSize));
1514
1515 return codedSize;
1516 }
1517
1518 // static
v4L2MemoryToString(const v4l2_memory memory)1519 const char* V4L2Device::v4L2MemoryToString(const v4l2_memory memory) {
1520 switch (memory) {
1521 case V4L2_MEMORY_MMAP:
1522 return "V4L2_MEMORY_MMAP";
1523 case V4L2_MEMORY_USERPTR:
1524 return "V4L2_MEMORY_USERPTR";
1525 case V4L2_MEMORY_DMABUF:
1526 return "V4L2_MEMORY_DMABUF";
1527 case V4L2_MEMORY_OVERLAY:
1528 return "V4L2_MEMORY_OVERLAY";
1529 default:
1530 return "UNKNOWN";
1531 }
1532 }
1533
1534 // static
v4L2BufferTypeToString(const enum v4l2_buf_type bufType)1535 const char* V4L2Device::v4L2BufferTypeToString(const enum v4l2_buf_type bufType) {
1536 switch (bufType) {
1537 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1538 return "OUTPUT";
1539 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1540 return "CAPTURE";
1541 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1542 return "OUTPUT_MPLANE";
1543 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
1544 return "CAPTURE_MPLANE";
1545 default:
1546 return "UNKNOWN";
1547 }
1548 }
1549
1550 // static
v4L2FormatToString(const struct v4l2_format & format)1551 std::string V4L2Device::v4L2FormatToString(const struct v4l2_format& format) {
1552 std::ostringstream s;
1553 s << "v4l2_format type: " << format.type;
1554 if (format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE || format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1555 // single-planar
1556 const struct v4l2_pix_format& pix = format.fmt.pix;
1557 s << ", width_height: " << toString(ui::Size(pix.width, pix.height))
1558 << ", pixelformat: " << fourccToString(pix.pixelformat) << ", field: " << pix.field
1559 << ", bytesperline: " << pix.bytesperline << ", sizeimage: " << pix.sizeimage;
1560 } else if (V4L2_TYPE_IS_MULTIPLANAR(format.type)) {
1561 const struct v4l2_pix_format_mplane& pixMp = format.fmt.pix_mp;
1562 // As long as num_planes's type is uint8_t, ostringstream treats it as a char instead of an
1563 // integer, which is not what we want. Casting pix_mp.num_planes unsigned int solves the
1564 // issue.
1565 s << ", width_height: " << toString(ui::Size(pixMp.width, pixMp.height))
1566 << ", pixelformat: " << fourccToString(pixMp.pixelformat) << ", field: " << pixMp.field
1567 << ", num_planes: " << static_cast<unsigned int>(pixMp.num_planes);
1568 for (size_t i = 0; i < pixMp.num_planes; ++i) {
1569 const struct v4l2_plane_pix_format& plane_fmt = pixMp.plane_fmt[i];
1570 s << ", plane_fmt[" << i << "].sizeimage: " << plane_fmt.sizeimage << ", plane_fmt["
1571 << i << "].bytesperline: " << plane_fmt.bytesperline;
1572 }
1573 } else {
1574 s << " unsupported yet.";
1575 }
1576 return s.str();
1577 }
1578
1579 // static
v4L2BufferToString(const struct v4l2_buffer & buffer)1580 std::string V4L2Device::v4L2BufferToString(const struct v4l2_buffer& buffer) {
1581 std::ostringstream s;
1582 s << "v4l2_buffer type: " << buffer.type << ", memory: " << buffer.memory
1583 << ", index: " << buffer.index << " bytesused: " << buffer.bytesused
1584 << ", length: " << buffer.length;
1585 if (buffer.type == V4L2_BUF_TYPE_VIDEO_CAPTURE || buffer.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1586 // single-planar
1587 if (buffer.memory == V4L2_MEMORY_MMAP) {
1588 s << ", m.offset: " << buffer.m.offset;
1589 } else if (buffer.memory == V4L2_MEMORY_USERPTR) {
1590 s << ", m.userptr: " << buffer.m.userptr;
1591 } else if (buffer.memory == V4L2_MEMORY_DMABUF) {
1592 s << ", m.fd: " << buffer.m.fd;
1593 };
1594 } else if (V4L2_TYPE_IS_MULTIPLANAR(buffer.type)) {
1595 for (size_t i = 0; i < buffer.length; ++i) {
1596 const struct v4l2_plane& plane = buffer.m.planes[i];
1597 s << ", m.planes[" << i << "](bytesused: " << plane.bytesused
1598 << ", length: " << plane.length << ", data_offset: " << plane.data_offset;
1599 if (buffer.memory == V4L2_MEMORY_MMAP) {
1600 s << ", m.mem_offset: " << plane.m.mem_offset;
1601 } else if (buffer.memory == V4L2_MEMORY_USERPTR) {
1602 s << ", m.userptr: " << plane.m.userptr;
1603 } else if (buffer.memory == V4L2_MEMORY_DMABUF) {
1604 s << ", m.fd: " << plane.m.fd;
1605 }
1606 s << ")";
1607 }
1608 } else {
1609 s << " unsupported yet.";
1610 }
1611 return s.str();
1612 }
1613
1614 // static
v4L2FormatToVideoFrameLayout(const struct v4l2_format & format)1615 std::optional<VideoFrameLayout> V4L2Device::v4L2FormatToVideoFrameLayout(
1616 const struct v4l2_format& format) {
1617 if (!V4L2_TYPE_IS_MULTIPLANAR(format.type)) {
1618 ALOGE("v4l2_buf_type is not multiplanar: 0x%" PRIx32, format.type);
1619 return std::nullopt;
1620 }
1621 const v4l2_pix_format_mplane& pixMp = format.fmt.pix_mp;
1622 const uint32_t& pixFmt = pixMp.pixelformat;
1623 const auto videoFourcc = Fourcc::fromV4L2PixFmt(pixFmt);
1624 if (!videoFourcc) {
1625 ALOGE("Failed to convert pixel format to VideoPixelFormat: %s",
1626 fourccToString(pixFmt).c_str());
1627 return std::nullopt;
1628 }
1629 const VideoPixelFormat videoFormat = videoFourcc->toVideoPixelFormat();
1630 const size_t numBuffers = pixMp.num_planes;
1631 const size_t numColorPlanes = numPlanes(videoFormat);
1632 if (numColorPlanes == 0) {
1633 ALOGE("Unsupported video format for NumPlanes(): %s",
1634 videoPixelFormatToString(videoFormat).c_str());
1635 return std::nullopt;
1636 }
1637 if (numBuffers > numColorPlanes) {
1638 ALOGE("pix_mp.num_planes: %zu should not be larger than NumPlanes(%s): %zu", numBuffers,
1639 videoPixelFormatToString(videoFormat).c_str(), numColorPlanes);
1640 return std::nullopt;
1641 }
1642 // Reserve capacity in advance to prevent unnecessary vector reallocation.
1643 std::vector<VideoFramePlane> planes;
1644 planes.reserve(numColorPlanes);
1645 for (size_t i = 0; i < numBuffers; ++i) {
1646 const v4l2_plane_pix_format& planeFormat = pixMp.plane_fmt[i];
1647 planes.push_back(VideoFramePlane{planeFormat.bytesperline, 0u, planeFormat.sizeimage});
1648 }
1649 // For the case that #color planes > #buffers, it fills stride of color plane which does not map
1650 // to buffer. Right now only some pixel formats are supported: NV12, YUV420, YVU420.
1651 if (numColorPlanes > numBuffers) {
1652 const uint32_t yStride = planes[0].mStride;
1653 // Note that y_stride is from v4l2 bytesperline and its type is uint32_t. It is safe to cast
1654 // to size_t.
1655 const size_t yStrideAbs = static_cast<size_t>(yStride);
1656 switch (pixFmt) {
1657 case V4L2_PIX_FMT_NV12:
1658 // The stride of UV is the same as Y in NV12. The height is half of Y plane.
1659 planes.push_back(VideoFramePlane{yStride, yStrideAbs * pixMp.height,
1660 yStrideAbs * pixMp.height / 2});
1661 ALOG_ASSERT(2u == planes.size());
1662 break;
1663 case V4L2_PIX_FMT_YUV420:
1664 case V4L2_PIX_FMT_YVU420: {
1665 // The spec claims that two Cx rows (including padding) is exactly as long as one Y row
1666 // (including padding). So stride of Y must be even number.
1667 if (yStride % 2 != 0 || pixMp.height % 2 != 0) {
1668 ALOGE("Plane-Y stride and height should be even; stride: %u, height: %u", yStride,
1669 pixMp.height);
1670 return std::nullopt;
1671 }
1672 const uint32_t halfStride = yStride / 2;
1673 const size_t plane0Area = yStrideAbs * pixMp.height;
1674 const size_t plane1Area = plane0Area / 4;
1675 planes.push_back(VideoFramePlane{halfStride, plane0Area, plane1Area});
1676 planes.push_back(VideoFramePlane{halfStride, plane0Area + plane1Area, plane1Area});
1677 ALOG_ASSERT(3u == planes.size());
1678 break;
1679 }
1680 default:
1681 ALOGE("Cannot derive stride for each plane for pixel format %s",
1682 fourccToString(pixFmt).c_str());
1683 return std::nullopt;
1684 }
1685 }
1686
1687 return VideoFrameLayout{videoFormat, ui::Size(pixMp.width, pixMp.height), std::move(planes),
1688 (numBuffers > 1)};
1689 }
1690
1691 // static
getNumPlanesOfV4L2PixFmt(uint32_t pixFmt)1692 size_t V4L2Device::getNumPlanesOfV4L2PixFmt(uint32_t pixFmt) {
1693 std::optional<Fourcc> fourcc = Fourcc::fromV4L2PixFmt(pixFmt);
1694 if (fourcc && fourcc->isMultiPlanar()) {
1695 return numPlanes(fourcc->toVideoPixelFormat());
1696 }
1697 return 1u;
1698 }
1699
getSupportedResolution(uint32_t pixelFormat,ui::Size * minResolution,ui::Size * maxResolution)1700 void V4L2Device::getSupportedResolution(uint32_t pixelFormat, ui::Size* minResolution,
1701 ui::Size* maxResolution) {
1702 maxResolution->set(0, 0);
1703 minResolution->set(0, 0);
1704 v4l2_frmsizeenum frameSize;
1705 memset(&frameSize, 0, sizeof(frameSize));
1706 frameSize.pixel_format = pixelFormat;
1707 for (; ioctl(VIDIOC_ENUM_FRAMESIZES, &frameSize) == 0; ++frameSize.index) {
1708 if (frameSize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
1709 if (frameSize.discrete.width >= base::checked_cast<uint32_t>(maxResolution->width) &&
1710 frameSize.discrete.height >= base::checked_cast<uint32_t>(maxResolution->height)) {
1711 maxResolution->set(frameSize.discrete.width, frameSize.discrete.height);
1712 }
1713 if (isEmpty(*minResolution) ||
1714 (frameSize.discrete.width <= base::checked_cast<uint32_t>(minResolution->width) &&
1715 frameSize.discrete.height <=
1716 base::checked_cast<uint32_t>(minResolution->height))) {
1717 minResolution->set(frameSize.discrete.width, frameSize.discrete.height);
1718 }
1719 } else if (frameSize.type == V4L2_FRMSIZE_TYPE_STEPWISE ||
1720 frameSize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
1721 maxResolution->set(frameSize.stepwise.max_width, frameSize.stepwise.max_height);
1722 minResolution->set(frameSize.stepwise.min_width, frameSize.stepwise.min_height);
1723 break;
1724 }
1725 }
1726 if (isEmpty(*maxResolution)) {
1727 maxResolution->set(1920, 1088);
1728 ALOGE("GetSupportedResolution failed to get maximum resolution for fourcc %s, "
1729 "fall back to %s",
1730 fourccToString(pixelFormat).c_str(), toString(*maxResolution).c_str());
1731 }
1732 if (isEmpty(*minResolution)) {
1733 minResolution->set(16, 16);
1734 ALOGE("GetSupportedResolution failed to get minimum resolution for fourcc %s, "
1735 "fall back to %s",
1736 fourccToString(pixelFormat).c_str(), toString(*minResolution).c_str());
1737 }
1738 }
1739
enumerateSupportedPixelformats(v4l2_buf_type bufType)1740 std::vector<uint32_t> V4L2Device::enumerateSupportedPixelformats(v4l2_buf_type bufType) {
1741 std::vector<uint32_t> pixelFormats;
1742
1743 v4l2_fmtdesc fmtDesc;
1744 memset(&fmtDesc, 0, sizeof(fmtDesc));
1745 fmtDesc.type = bufType;
1746
1747 for (; ioctl(VIDIOC_ENUM_FMT, &fmtDesc) == 0; ++fmtDesc.index) {
1748 ALOGV("Found %s (0x%" PRIx32 ")", fmtDesc.description, fmtDesc.pixelformat);
1749 pixelFormats.push_back(fmtDesc.pixelformat);
1750 }
1751
1752 return pixelFormats;
1753 }
1754
getSupportedDecodeProfiles(const size_t numFormats,const uint32_t pixelFormats[])1755 V4L2Device::SupportedDecodeProfiles V4L2Device::getSupportedDecodeProfiles(
1756 const size_t numFormats, const uint32_t pixelFormats[]) {
1757 SupportedDecodeProfiles supportedProfiles;
1758
1759 Type type = Type::kDecoder;
1760 const auto& devices = getDevicesForType(type);
1761 for (const auto& device : devices) {
1762 if (!openDevicePath(device.first, type)) {
1763 ALOGV("Failed opening %s", device.first.c_str());
1764 continue;
1765 }
1766
1767 const auto& profiles = enumerateSupportedDecodeProfiles(numFormats, pixelFormats);
1768 supportedProfiles.insert(supportedProfiles.end(), profiles.begin(), profiles.end());
1769 closeDevice();
1770 }
1771
1772 return supportedProfiles;
1773 }
1774
getSupportedEncodeProfiles()1775 V4L2Device::SupportedEncodeProfiles V4L2Device::getSupportedEncodeProfiles() {
1776 SupportedEncodeProfiles supportedProfiles;
1777
1778 Type type = Type::kEncoder;
1779 const auto& devices = getDevicesForType(type);
1780 for (const auto& device : devices) {
1781 if (!openDevicePath(device.first, type)) {
1782 ALOGV("Failed opening %s", device.first.c_str());
1783 continue;
1784 }
1785
1786 const auto& profiles = enumerateSupportedEncodeProfiles();
1787 supportedProfiles.insert(supportedProfiles.end(), profiles.begin(), profiles.end());
1788 closeDevice();
1789 }
1790
1791 return supportedProfiles;
1792 }
1793
enumerateSupportedDecodeProfiles(const size_t numFormats,const uint32_t pixelFormats[])1794 V4L2Device::SupportedDecodeProfiles V4L2Device::enumerateSupportedDecodeProfiles(
1795 const size_t numFormats, const uint32_t pixelFormats[]) {
1796 SupportedDecodeProfiles profiles;
1797
1798 const auto& supportedPixelformats =
1799 enumerateSupportedPixelformats(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
1800
1801 for (uint32_t pixelFormat : supportedPixelformats) {
1802 if (std::find(pixelFormats, pixelFormats + numFormats, pixelFormat) ==
1803 pixelFormats + numFormats)
1804 continue;
1805
1806 SupportedDecodeProfile profile;
1807 getSupportedResolution(pixelFormat, &profile.min_resolution, &profile.max_resolution);
1808
1809 const auto videoCodecProfiles = v4L2PixFmtToC2Profiles(pixelFormat, false);
1810
1811 for (const auto& videoCodecProfile : videoCodecProfiles) {
1812 profile.profile = videoCodecProfile;
1813 profiles.push_back(profile);
1814
1815 ALOGV("Found decoder profile %s, resolutions: %s %s", profileToString(profile.profile),
1816 toString(profile.min_resolution).c_str(),
1817 toString(profile.max_resolution).c_str());
1818 }
1819 }
1820
1821 return profiles;
1822 }
1823
enumerateSupportedEncodeProfiles()1824 V4L2Device::SupportedEncodeProfiles V4L2Device::enumerateSupportedEncodeProfiles() {
1825 SupportedEncodeProfiles profiles;
1826
1827 const auto& supportedPixelformats =
1828 enumerateSupportedPixelformats(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
1829
1830 for (const auto& pixelformat : supportedPixelformats) {
1831 SupportedEncodeProfile profile;
1832 profile.max_framerate_numerator = 30;
1833 profile.max_framerate_denominator = 1;
1834 ui::Size minResolution;
1835 getSupportedResolution(pixelformat, &minResolution, &profile.max_resolution);
1836
1837 const auto videoCodecProfiles = v4L2PixFmtToC2Profiles(pixelformat, true);
1838
1839 for (const auto& videoCodecProfile : videoCodecProfiles) {
1840 profile.profile = videoCodecProfile;
1841 profiles.push_back(profile);
1842
1843 ALOGV("Found encoder profile %s, max resolution: %s", profileToString(profile.profile),
1844 toString(profile.max_resolution).c_str());
1845 }
1846 }
1847
1848 return profiles;
1849 }
1850
startPolling(android::V4L2DevicePoller::EventCallback eventCallback,base::RepeatingClosure errorCallback)1851 bool V4L2Device::startPolling(android::V4L2DevicePoller::EventCallback eventCallback,
1852 base::RepeatingClosure errorCallback) {
1853 DCHECK_CALLED_ON_VALID_SEQUENCE(mClientSequenceChecker);
1854
1855 if (!mDevicePoller) {
1856 mDevicePoller = std::make_unique<android::V4L2DevicePoller>(this, "V4L2DeviceThreadPoller");
1857 }
1858
1859 bool ret = mDevicePoller->startPolling(std::move(eventCallback), std::move(errorCallback));
1860
1861 if (!ret) mDevicePoller = nullptr;
1862
1863 return ret;
1864 }
1865
stopPolling()1866 bool V4L2Device::stopPolling() {
1867 DCHECK_CALLED_ON_VALID_SEQUENCE(mClientSequenceChecker);
1868
1869 return !mDevicePoller || mDevicePoller->stopPolling();
1870 }
1871
schedulePoll()1872 void V4L2Device::schedulePoll() {
1873 DCHECK_CALLED_ON_VALID_SEQUENCE(mClientSequenceChecker);
1874
1875 if (!mDevicePoller || !mDevicePoller->isPolling()) return;
1876
1877 mDevicePoller->schedulePoll();
1878 }
1879
isCtrlExposed(uint32_t ctrlId)1880 bool V4L2Device::isCtrlExposed(uint32_t ctrlId) {
1881 DCHECK_CALLED_ON_VALID_SEQUENCE(mClientSequenceChecker);
1882
1883 struct v4l2_queryctrl queryCtrl;
1884 memset(&queryCtrl, 0, sizeof(queryCtrl));
1885 queryCtrl.id = ctrlId;
1886
1887 return ioctl(VIDIOC_QUERYCTRL, &queryCtrl) == 0;
1888 }
1889
setExtCtrls(uint32_t ctrlClass,std::vector<V4L2ExtCtrl> ctrls)1890 bool V4L2Device::setExtCtrls(uint32_t ctrlClass, std::vector<V4L2ExtCtrl> ctrls) {
1891 DCHECK_CALLED_ON_VALID_SEQUENCE(mClientSequenceChecker);
1892
1893 if (ctrls.empty()) return true;
1894
1895 struct v4l2_ext_controls extCtrls;
1896 memset(&extCtrls, 0, sizeof(extCtrls));
1897 extCtrls.ctrl_class = ctrlClass;
1898 extCtrls.count = ctrls.size();
1899 extCtrls.controls = &ctrls[0].ctrl;
1900 return ioctl(VIDIOC_S_EXT_CTRLS, &extCtrls) == 0;
1901 }
1902
isCommandSupported(uint32_t commandId)1903 bool V4L2Device::isCommandSupported(uint32_t commandId) {
1904 DCHECK_CALLED_ON_VALID_SEQUENCE(mClientSequenceChecker);
1905
1906 struct v4l2_encoder_cmd cmd;
1907 memset(&cmd, 0, sizeof(cmd));
1908 cmd.cmd = commandId;
1909
1910 return ioctl(VIDIOC_TRY_ENCODER_CMD, &cmd) == 0;
1911 }
1912
hasCapabilities(uint32_t capabilities)1913 bool V4L2Device::hasCapabilities(uint32_t capabilities) {
1914 DCHECK_CALLED_ON_VALID_SEQUENCE(mClientSequenceChecker);
1915
1916 struct v4l2_capability caps;
1917 memset(&caps, 0, sizeof(caps));
1918 if (ioctl(VIDIOC_QUERYCAP, &caps) != 0) {
1919 ALOGE("Failed to query capabilities");
1920 return false;
1921 }
1922
1923 return (caps.capabilities & capabilities) == capabilities;
1924 }
1925
openDevicePath(const std::string & path,Type)1926 bool V4L2Device::openDevicePath(const std::string& path, Type /*type*/) {
1927 ALOG_ASSERT(!mDeviceFd.is_valid());
1928
1929 mDeviceFd.reset(HANDLE_EINTR(::open(path.c_str(), O_RDWR | O_NONBLOCK | O_CLOEXEC)));
1930 if (!mDeviceFd.is_valid()) return false;
1931
1932 return true;
1933 }
1934
closeDevice()1935 void V4L2Device::closeDevice() {
1936 ALOGV("%s()", __func__);
1937
1938 mDeviceFd.reset();
1939 }
1940
enumerateDevicesForType(Type type)1941 void V4L2Device::enumerateDevicesForType(Type type) {
1942 // video input/output devices are registered as /dev/videoX in V4L2.
1943 static const std::string kVideoDevicePattern = "/dev/video";
1944
1945 std::string devicePattern;
1946 v4l2_buf_type bufType;
1947 switch (type) {
1948 case Type::kDecoder:
1949 devicePattern = kVideoDevicePattern;
1950 bufType = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
1951 break;
1952 case Type::kEncoder:
1953 devicePattern = kVideoDevicePattern;
1954 bufType = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1955 break;
1956 default:
1957 ALOGE("Only decoder and encoder types are supported!!");
1958 return;
1959 }
1960
1961 std::vector<std::string> candidatePaths;
1962
1963 // TODO(posciak): Remove this legacy unnumbered device once all platforms are updated to use
1964 // numbered devices.
1965 candidatePaths.push_back(devicePattern);
1966
1967 // We are sandboxed, so we can't query directory contents to check which devices are actually
1968 // available. Try to open the first 10; if not present, we will just fail to open immediately.
1969 for (int i = 0; i < 10; ++i) {
1970 candidatePaths.push_back(base::StringPrintf("%s%d", devicePattern.c_str(), i));
1971 }
1972
1973 Devices devices;
1974 for (const auto& path : candidatePaths) {
1975 if (!openDevicePath(path, type)) {
1976 continue;
1977 }
1978
1979 const auto& supportedPixelformats = enumerateSupportedPixelformats(bufType);
1980 if (!supportedPixelformats.empty()) {
1981 ALOGV("Found device: %s", path.c_str());
1982 devices.push_back(std::make_pair(path, supportedPixelformats));
1983 }
1984
1985 closeDevice();
1986 }
1987
1988 ALOG_ASSERT(mDevicesByType.count(type) == 0u);
1989 mDevicesByType[type] = devices;
1990 }
1991
getDevicesForType(Type type)1992 const V4L2Device::Devices& V4L2Device::getDevicesForType(Type type) {
1993 if (mDevicesByType.count(type) == 0) enumerateDevicesForType(type);
1994
1995 ALOG_ASSERT(mDevicesByType.count(type) != 0u);
1996 return mDevicesByType[type];
1997 }
1998
getDevicePathFor(Type type,uint32_t pixFmt)1999 std::string V4L2Device::getDevicePathFor(Type type, uint32_t pixFmt) {
2000 const Devices& devices = getDevicesForType(type);
2001
2002 for (const auto& device : devices) {
2003 if (std::find(device.second.begin(), device.second.end(), pixFmt) != device.second.end())
2004 return device.first;
2005 }
2006
2007 return std::string();
2008 }
2009
2010 } // namespace android
2011