1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 //#define LOG_NDEBUG 0
6 #define LOG_TAG "V4L2Decoder"
7
8 #include <v4l2_codec2/components/V4L2Decoder.h>
9
10 #include <stdint.h>
11
12 #include <vector>
13
14 #include <base/bind.h>
15 #include <base/files/scoped_file.h>
16 #include <base/memory/ptr_util.h>
17 #include <log/log.h>
18
19 namespace android {
20 namespace {
21
22 constexpr size_t kNumInputBuffers = 16;
23 // Extra buffers for transmitting in the whole video pipeline.
24 constexpr size_t kNumExtraOutputBuffers = 4;
25
VideoCodecToV4L2PixFmt(VideoCodec codec)26 uint32_t VideoCodecToV4L2PixFmt(VideoCodec codec) {
27 switch (codec) {
28 case VideoCodec::H264:
29 return V4L2_PIX_FMT_H264;
30 case VideoCodec::VP8:
31 return V4L2_PIX_FMT_VP8;
32 case VideoCodec::VP9:
33 return V4L2_PIX_FMT_VP9;
34 }
35 }
36
37 } // namespace
38
39 // static
Create(const VideoCodec & codec,const size_t inputBufferSize,GetPoolCB getPoolCb,OutputCB outputCb,ErrorCB errorCb,scoped_refptr<::base::SequencedTaskRunner> taskRunner)40 std::unique_ptr<VideoDecoder> V4L2Decoder::Create(
41 const VideoCodec& codec, const size_t inputBufferSize, GetPoolCB getPoolCb,
42 OutputCB outputCb, ErrorCB errorCb, scoped_refptr<::base::SequencedTaskRunner> taskRunner) {
43 std::unique_ptr<V4L2Decoder> decoder =
44 ::base::WrapUnique<V4L2Decoder>(new V4L2Decoder(taskRunner));
45 if (!decoder->start(codec, inputBufferSize, std::move(getPoolCb), std::move(outputCb),
46 std::move(errorCb))) {
47 return nullptr;
48 }
49 return decoder;
50 }
51
V4L2Decoder(scoped_refptr<::base::SequencedTaskRunner> taskRunner)52 V4L2Decoder::V4L2Decoder(scoped_refptr<::base::SequencedTaskRunner> taskRunner)
53 : mTaskRunner(std::move(taskRunner)) {
54 ALOGV("%s()", __func__);
55
56 mWeakThis = mWeakThisFactory.GetWeakPtr();
57 }
58
~V4L2Decoder()59 V4L2Decoder::~V4L2Decoder() {
60 ALOGV("%s()", __func__);
61 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
62
63 mWeakThisFactory.InvalidateWeakPtrs();
64
65 // Streamoff input and output queue.
66 if (mOutputQueue) {
67 mOutputQueue->Streamoff();
68 mOutputQueue->DeallocateBuffers();
69 mOutputQueue = nullptr;
70 }
71 if (mInputQueue) {
72 mInputQueue->Streamoff();
73 mInputQueue->DeallocateBuffers();
74 mInputQueue = nullptr;
75 }
76 if (mDevice) {
77 mDevice->StopPolling();
78 mDevice = nullptr;
79 }
80 }
81
start(const VideoCodec & codec,const size_t inputBufferSize,GetPoolCB getPoolCb,OutputCB outputCb,ErrorCB errorCb)82 bool V4L2Decoder::start(const VideoCodec& codec, const size_t inputBufferSize, GetPoolCB getPoolCb,
83 OutputCB outputCb, ErrorCB errorCb) {
84 ALOGV("%s(codec=%s, inputBufferSize=%zu)", __func__, VideoCodecToString(codec),
85 inputBufferSize);
86 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
87
88 mGetPoolCb = std::move(getPoolCb);
89 mOutputCb = std::move(outputCb);
90 mErrorCb = std::move(errorCb);
91
92 if (mState == State::Error) {
93 ALOGE("Ignore due to error state.");
94 return false;
95 }
96
97 mDevice = media::V4L2Device::Create();
98
99 const uint32_t inputPixelFormat = VideoCodecToV4L2PixFmt(codec);
100 if (!mDevice->Open(media::V4L2Device::Type::kDecoder, inputPixelFormat)) {
101 ALOGE("Failed to open device for %s", VideoCodecToString(codec));
102 return false;
103 }
104
105 if (!mDevice->HasCapabilities(V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING)) {
106 ALOGE("Device does not have VIDEO_M2M_MPLANE and STREAMING capabilities.");
107 return false;
108 }
109
110 struct v4l2_decoder_cmd cmd;
111 memset(&cmd, 0, sizeof(cmd));
112 cmd.cmd = V4L2_DEC_CMD_STOP;
113 if (mDevice->Ioctl(VIDIOC_TRY_DECODER_CMD, &cmd) != 0) {
114 ALOGE("Device does not support flushing (V4L2_DEC_CMD_STOP)");
115 return false;
116 }
117
118 // Subscribe to the resolution change event.
119 struct v4l2_event_subscription sub;
120 memset(&sub, 0, sizeof(sub));
121 sub.type = V4L2_EVENT_SOURCE_CHANGE;
122 if (mDevice->Ioctl(VIDIOC_SUBSCRIBE_EVENT, &sub) != 0) {
123 ALOGE("ioctl() failed: VIDIOC_SUBSCRIBE_EVENT: V4L2_EVENT_SOURCE_CHANGE");
124 return false;
125 }
126
127 // Create Input/Output V4L2Queue, and setup input queue.
128 mInputQueue = mDevice->GetQueue(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
129 mOutputQueue = mDevice->GetQueue(V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
130 if (!mInputQueue || !mOutputQueue) {
131 ALOGE("Failed to create V4L2 queue.");
132 return false;
133 }
134 if (!setupInputFormat(inputPixelFormat, inputBufferSize)) {
135 ALOGE("Failed to setup input format.");
136 return false;
137 }
138
139 if (!mDevice->StartPolling(::base::BindRepeating(&V4L2Decoder::serviceDeviceTask, mWeakThis),
140 ::base::BindRepeating(&V4L2Decoder::onError, mWeakThis))) {
141 ALOGE("Failed to start polling V4L2 device.");
142 return false;
143 }
144
145 setState(State::Idle);
146 return true;
147 }
148
setupInputFormat(const uint32_t inputPixelFormat,const size_t inputBufferSize)149 bool V4L2Decoder::setupInputFormat(const uint32_t inputPixelFormat, const size_t inputBufferSize) {
150 ALOGV("%s(inputPixelFormat=%u, inputBufferSize=%zu)", __func__, inputPixelFormat,
151 inputBufferSize);
152 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
153
154 // Check if the format is supported.
155 std::vector<uint32_t> formats =
156 mDevice->EnumerateSupportedPixelformats(V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
157 if (std::find(formats.begin(), formats.end(), inputPixelFormat) == formats.end()) {
158 ALOGE("Input codec s not supported by device.");
159 return false;
160 }
161
162 // Setup the input format.
163 auto format = mInputQueue->SetFormat(inputPixelFormat, media::Size(), inputBufferSize);
164 if (!format) {
165 ALOGE("Failed to call IOCTL to set input format.");
166 return false;
167 }
168 ALOG_ASSERT(format->fmt.pix_mp.pixelformat == inputPixelFormat);
169
170 if (mInputQueue->AllocateBuffers(kNumInputBuffers, V4L2_MEMORY_DMABUF) == 0) {
171 ALOGE("Failed to allocate input buffer.");
172 return false;
173 }
174 if (!mInputQueue->Streamon()) {
175 ALOGE("Failed to streamon input queue.");
176 return false;
177 }
178 return true;
179 }
180
decode(std::unique_ptr<BitstreamBuffer> buffer,DecodeCB decodeCb)181 void V4L2Decoder::decode(std::unique_ptr<BitstreamBuffer> buffer, DecodeCB decodeCb) {
182 ALOGV("%s(id=%d)", __func__, buffer->id);
183 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
184
185 if (mState == State::Error) {
186 ALOGE("Ignore due to error state.");
187 mTaskRunner->PostTask(FROM_HERE, ::base::BindOnce(std::move(decodeCb),
188 VideoDecoder::DecodeStatus::kError));
189 return;
190 }
191
192 if (mState == State::Idle) {
193 setState(State::Decoding);
194 }
195
196 mDecodeRequests.push(DecodeRequest(std::move(buffer), std::move(decodeCb)));
197 pumpDecodeRequest();
198 }
199
drain(DecodeCB drainCb)200 void V4L2Decoder::drain(DecodeCB drainCb) {
201 ALOGV("%s()", __func__);
202 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
203
204 switch (mState) {
205 case State::Idle:
206 ALOGD("Nothing need to drain, ignore.");
207 mTaskRunner->PostTask(
208 FROM_HERE, ::base::BindOnce(std::move(drainCb), VideoDecoder::DecodeStatus::kOk));
209 return;
210
211 case State::Decoding:
212 mDecodeRequests.push(DecodeRequest(nullptr, std::move(drainCb)));
213 pumpDecodeRequest();
214 return;
215
216 case State::Draining:
217 case State::Error:
218 ALOGE("Ignore due to wrong state: %s", StateToString(mState));
219 mTaskRunner->PostTask(FROM_HERE, ::base::BindOnce(std::move(drainCb),
220 VideoDecoder::DecodeStatus::kError));
221 return;
222 }
223 }
224
pumpDecodeRequest()225 void V4L2Decoder::pumpDecodeRequest() {
226 ALOGV("%s()", __func__);
227 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
228
229 if (mState != State::Decoding) return;
230
231 while (!mDecodeRequests.empty()) {
232 // Drain the decoder.
233 if (mDecodeRequests.front().buffer == nullptr) {
234 ALOGV("Get drain request.");
235 // Send the flush command after all input buffers are dequeued. This makes
236 // sure all previous resolution changes have been handled because the
237 // driver must hold the input buffer that triggers resolution change. The
238 // driver cannot decode data in it without new output buffers. If we send
239 // the flush now and a queued input buffer triggers resolution change
240 // later, the driver will send an output buffer that has
241 // V4L2_BUF_FLAG_LAST. But some queued input buffer have not been decoded
242 // yet. Also, V4L2VDA calls STREAMOFF and STREAMON after resolution
243 // change. They implicitly send a V4L2_DEC_CMD_STOP and V4L2_DEC_CMD_START
244 // to the decoder.
245 if (mInputQueue->QueuedBuffersCount() > 0) {
246 ALOGD("Wait for all input buffers dequeued.");
247 return;
248 }
249
250 auto request = std::move(mDecodeRequests.front());
251 mDecodeRequests.pop();
252
253 if (!sendV4L2DecoderCmd(false)) {
254 std::move(request.decodeCb).Run(VideoDecoder::DecodeStatus::kError);
255 onError();
256 return;
257 }
258 mDrainCb = std::move(request.decodeCb);
259 setState(State::Draining);
260 return;
261 }
262
263 // Pause if no free input buffer. We resume decoding after dequeueing input buffers.
264 auto inputBuffer = mInputQueue->GetFreeBuffer();
265 if (!inputBuffer) {
266 ALOGV("There is no free input buffer.");
267 return;
268 }
269
270 auto request = std::move(mDecodeRequests.front());
271 mDecodeRequests.pop();
272
273 const int32_t bitstreamId = request.buffer->id;
274 ALOGV("QBUF to input queue, bitstreadId=%d", bitstreamId);
275 inputBuffer->SetTimeStamp({.tv_sec = bitstreamId});
276 size_t planeSize = inputBuffer->GetPlaneSize(0);
277 if (request.buffer->size > planeSize) {
278 ALOGE("The input size (%zu) is not enough, we need %zu", planeSize,
279 request.buffer->size);
280 onError();
281 return;
282 }
283
284 ALOGV("Set bytes_used=%zu, offset=%zu", request.buffer->offset + request.buffer->size,
285 request.buffer->offset);
286 inputBuffer->SetPlaneDataOffset(0, request.buffer->offset);
287 inputBuffer->SetPlaneBytesUsed(0, request.buffer->offset + request.buffer->size);
288 std::vector<int> fds;
289 fds.push_back(std::move(request.buffer->dmabuf_fd));
290 if (!std::move(*inputBuffer).QueueDMABuf(fds)) {
291 ALOGE("%s(): Failed to QBUF to input queue, bitstreamId=%d", __func__, bitstreamId);
292 onError();
293 return;
294 }
295
296 mPendingDecodeCbs.insert(std::make_pair(bitstreamId, std::move(request.decodeCb)));
297 }
298 }
299
flush()300 void V4L2Decoder::flush() {
301 ALOGV("%s()", __func__);
302 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
303
304 if (mState == State::Idle) {
305 ALOGD("Nothing need to flush, ignore.");
306 return;
307 }
308 if (mState == State::Error) {
309 ALOGE("Ignore due to error state.");
310 return;
311 }
312
313 // Call all pending callbacks.
314 for (auto& item : mPendingDecodeCbs) {
315 std::move(item.second).Run(VideoDecoder::DecodeStatus::kAborted);
316 }
317 mPendingDecodeCbs.clear();
318 if (mDrainCb) {
319 std::move(mDrainCb).Run(VideoDecoder::DecodeStatus::kAborted);
320 }
321
322 // Streamoff both V4L2 queues to drop input and output buffers.
323 mDevice->StopPolling();
324 mOutputQueue->Streamoff();
325 mFrameAtDevice.clear();
326 mInputQueue->Streamoff();
327
328 // Streamon both V4L2 queues.
329 mInputQueue->Streamon();
330 mOutputQueue->Streamon();
331
332 if (!mDevice->StartPolling(::base::BindRepeating(&V4L2Decoder::serviceDeviceTask, mWeakThis),
333 ::base::BindRepeating(&V4L2Decoder::onError, mWeakThis))) {
334 ALOGE("Failed to start polling V4L2 device.");
335 onError();
336 return;
337 }
338
339 setState(State::Idle);
340 }
341
serviceDeviceTask(bool event)342 void V4L2Decoder::serviceDeviceTask(bool event) {
343 ALOGV("%s(event=%d) state=%s InputQueue(%s):%zu+%zu/%zu, OutputQueue(%s):%zu+%zu/%zu", __func__,
344 event, StateToString(mState), (mInputQueue->IsStreaming() ? "streamon" : "streamoff"),
345 mInputQueue->FreeBuffersCount(), mInputQueue->QueuedBuffersCount(),
346 mInputQueue->AllocatedBuffersCount(),
347 (mOutputQueue->IsStreaming() ? "streamon" : "streamoff"),
348 mOutputQueue->FreeBuffersCount(), mOutputQueue->QueuedBuffersCount(),
349 mOutputQueue->AllocatedBuffersCount());
350 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
351
352 if (mState == State::Error) return;
353
354 // Dequeue output and input queue.
355 bool inputDequeued = false;
356 while (mInputQueue->QueuedBuffersCount() > 0) {
357 bool success;
358 media::V4L2ReadableBufferRef dequeuedBuffer;
359 std::tie(success, dequeuedBuffer) = mInputQueue->DequeueBuffer();
360 if (!success) {
361 ALOGE("Failed to dequeue buffer from input queue.");
362 onError();
363 return;
364 }
365 if (!dequeuedBuffer) break;
366
367 inputDequeued = true;
368
369 // Run the corresponding decode callback.
370 int32_t id = dequeuedBuffer->GetTimeStamp().tv_sec;
371 ALOGV("DQBUF from input queue, bitstreamId=%d", id);
372 auto it = mPendingDecodeCbs.find(id);
373 if (it == mPendingDecodeCbs.end()) {
374 ALOGW("Callback is already abandoned.");
375 continue;
376 }
377 std::move(it->second).Run(VideoDecoder::DecodeStatus::kOk);
378 mPendingDecodeCbs.erase(it);
379 }
380
381 bool outputDequeued = false;
382 while (mOutputQueue->QueuedBuffersCount() > 0) {
383 bool success;
384 media::V4L2ReadableBufferRef dequeuedBuffer;
385 std::tie(success, dequeuedBuffer) = mOutputQueue->DequeueBuffer();
386 if (!success) {
387 ALOGE("Failed to dequeue buffer from output queue.");
388 onError();
389 return;
390 }
391 if (!dequeuedBuffer) break;
392
393 outputDequeued = true;
394
395 const size_t bufferId = dequeuedBuffer->BufferId();
396 const int32_t bitstreamId = static_cast<int32_t>(dequeuedBuffer->GetTimeStamp().tv_sec);
397 const size_t bytesUsed = dequeuedBuffer->GetPlaneBytesUsed(0);
398 const bool isLast = dequeuedBuffer->IsLast();
399 ALOGV("DQBUF from output queue, bufferId=%zu, corresponding bitstreamId=%d, bytesused=%zu",
400 bufferId, bitstreamId, bytesUsed);
401
402 // Get the corresponding VideoFrame of the dequeued buffer.
403 auto it = mFrameAtDevice.find(bufferId);
404 ALOG_ASSERT(it != mFrameAtDevice.end(), "buffer %zu is not found at mFrameAtDevice",
405 bufferId);
406 auto frame = std::move(it->second);
407 mFrameAtDevice.erase(it);
408
409 if (bytesUsed > 0) {
410 ALOGV("Send output frame(bitstreamId=%d) to client", bitstreamId);
411 frame->setBitstreamId(bitstreamId);
412 frame->setVisibleRect(mVisibleRect);
413 mOutputCb.Run(std::move(frame));
414 } else {
415 // Workaround(b/168750131): If the buffer is not enqueued before the next drain is done,
416 // then the driver will fail to notify EOS. So we recycle the buffer immediately.
417 ALOGV("Recycle empty buffer %zu back to V4L2 output queue.", bufferId);
418 dequeuedBuffer.reset();
419 auto outputBuffer = mOutputQueue->GetFreeBuffer(bufferId);
420 ALOG_ASSERT(outputBuffer, "V4L2 output queue slot %zu is not freed.", bufferId);
421
422 if (!std::move(*outputBuffer).QueueDMABuf(frame->getFDs())) {
423 ALOGE("%s(): Failed to recycle empty buffer to output queue.", __func__);
424 onError();
425 return;
426 }
427 mFrameAtDevice.insert(std::make_pair(bufferId, std::move(frame)));
428 }
429
430 if (mDrainCb && isLast) {
431 ALOGV("All buffers are drained.");
432 sendV4L2DecoderCmd(true);
433 std::move(mDrainCb).Run(VideoDecoder::DecodeStatus::kOk);
434 setState(State::Idle);
435 }
436 }
437
438 // Handle resolution change event.
439 if (event && dequeueResolutionChangeEvent()) {
440 if (!changeResolution()) {
441 onError();
442 return;
443 }
444 }
445
446 // We freed some input buffers, continue handling decode requests.
447 if (inputDequeued) {
448 mTaskRunner->PostTask(FROM_HERE,
449 ::base::BindOnce(&V4L2Decoder::pumpDecodeRequest, mWeakThis));
450 }
451 // We free some output buffers, try to get VideoFrame.
452 if (outputDequeued) {
453 mTaskRunner->PostTask(FROM_HERE,
454 ::base::BindOnce(&V4L2Decoder::tryFetchVideoFrame, mWeakThis));
455 }
456 }
457
dequeueResolutionChangeEvent()458 bool V4L2Decoder::dequeueResolutionChangeEvent() {
459 ALOGV("%s()", __func__);
460 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
461
462 struct v4l2_event ev;
463 memset(&ev, 0, sizeof(ev));
464 while (mDevice->Ioctl(VIDIOC_DQEVENT, &ev) == 0) {
465 if (ev.type == V4L2_EVENT_SOURCE_CHANGE &&
466 ev.u.src_change.changes & V4L2_EVENT_SRC_CH_RESOLUTION) {
467 return true;
468 }
469 }
470 return false;
471 }
472
changeResolution()473 bool V4L2Decoder::changeResolution() {
474 ALOGV("%s()", __func__);
475 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
476
477 std::optional<struct v4l2_format> format = getFormatInfo();
478 std::optional<size_t> numOutputBuffers = getNumOutputBuffers();
479 if (!format || !numOutputBuffers) {
480 return false;
481 }
482
483 mCodedSize.SetSize(format->fmt.pix_mp.width, format->fmt.pix_mp.height);
484 mVisibleRect = getVisibleRect(mCodedSize);
485
486 ALOGI("Need %zu output buffers. coded size: %s, visible rect: %s", *numOutputBuffers,
487 mCodedSize.ToString().c_str(), mVisibleRect.ToString().c_str());
488 if (mCodedSize.IsEmpty()) {
489 ALOGE("Failed to get resolution from V4L2 driver.");
490 return false;
491 }
492
493 mOutputQueue->Streamoff();
494 mOutputQueue->DeallocateBuffers();
495 mFrameAtDevice.clear();
496 mBlockIdToV4L2Id.clear();
497
498 if (mOutputQueue->AllocateBuffers(*numOutputBuffers, V4L2_MEMORY_DMABUF) == 0) {
499 ALOGE("Failed to allocate output buffer.");
500 return false;
501 }
502 if (!mOutputQueue->Streamon()) {
503 ALOGE("Failed to streamon output queue.");
504 return false;
505 }
506
507 // Always use fexible pixel 420 format YCBCR_420_888 in Android.
508 mGetPoolCb.Run(&mVideoFramePool, mCodedSize, HalPixelFormat::YCBCR_420_888, *numOutputBuffers);
509 if (!mVideoFramePool) {
510 ALOGE("Failed to get block pool with size: %s", mCodedSize.ToString().c_str());
511 return false;
512 }
513
514 tryFetchVideoFrame();
515 return true;
516 }
517
tryFetchVideoFrame()518 void V4L2Decoder::tryFetchVideoFrame() {
519 ALOGV("%s()", __func__);
520 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
521 ALOG_ASSERT(mVideoFramePool, "mVideoFramePool is null, haven't get the instance yet?");
522
523 if (mOutputQueue->FreeBuffersCount() == 0) {
524 ALOGD("No free V4L2 output buffers, ignore.");
525 return;
526 }
527
528 if (!mVideoFramePool->getVideoFrame(
529 ::base::BindOnce(&V4L2Decoder::onVideoFrameReady, mWeakThis))) {
530 ALOGV("%s(): Previous callback is running, ignore.", __func__);
531 }
532 }
533
onVideoFrameReady(std::optional<VideoFramePool::FrameWithBlockId> frameWithBlockId)534 void V4L2Decoder::onVideoFrameReady(
535 std::optional<VideoFramePool::FrameWithBlockId> frameWithBlockId) {
536 ALOGV("%s()", __func__);
537 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
538
539 if (!frameWithBlockId) {
540 ALOGE("Got nullptr VideoFrame.");
541 onError();
542 return;
543 }
544
545 // Unwrap our arguments.
546 std::unique_ptr<VideoFrame> frame;
547 uint32_t blockId;
548 std::tie(frame, blockId) = std::move(*frameWithBlockId);
549
550 ::base::Optional<media::V4L2WritableBufferRef> outputBuffer;
551 // Find the V4L2 buffer that is associated with this block.
552 auto iter = mBlockIdToV4L2Id.find(blockId);
553 if (iter != mBlockIdToV4L2Id.end()) {
554 // If we have met this block in the past, reuse the same V4L2 buffer.
555 outputBuffer = mOutputQueue->GetFreeBuffer(iter->second);
556 } else if (mBlockIdToV4L2Id.size() < mOutputQueue->AllocatedBuffersCount()) {
557 // If this is the first time we see this block, give it the next
558 // available V4L2 buffer.
559 const size_t v4l2BufferId = mBlockIdToV4L2Id.size();
560 mBlockIdToV4L2Id.emplace(blockId, v4l2BufferId);
561 outputBuffer = mOutputQueue->GetFreeBuffer(v4l2BufferId);
562 } else {
563 // If this happens, this is a bug in VideoFramePool. It should never
564 // provide more blocks than we have V4L2 buffers.
565 ALOGE("Got more different blocks than we have V4L2 buffers for.");
566 }
567
568 if (!outputBuffer) {
569 ALOGE("V4L2 buffer not available.");
570 onError();
571 return;
572 }
573
574 uint32_t v4l2Id = outputBuffer->BufferId();
575 ALOGV("QBUF to output queue, blockId=%u, V4L2Id=%u", blockId, v4l2Id);
576
577 if (!std::move(*outputBuffer).QueueDMABuf(frame->getFDs())) {
578 ALOGE("%s(): Failed to QBUF to output queue, blockId=%u, V4L2Id=%u", __func__, blockId,
579 v4l2Id);
580 onError();
581 return;
582 }
583 if (mFrameAtDevice.find(v4l2Id) != mFrameAtDevice.end()) {
584 ALOGE("%s(): V4L2 buffer %d already enqueued.", __func__, v4l2Id);
585 onError();
586 return;
587 }
588 mFrameAtDevice.insert(std::make_pair(v4l2Id, std::move(frame)));
589
590 tryFetchVideoFrame();
591 }
592
getNumOutputBuffers()593 std::optional<size_t> V4L2Decoder::getNumOutputBuffers() {
594 ALOGV("%s()", __func__);
595 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
596
597 struct v4l2_control ctrl;
598 memset(&ctrl, 0, sizeof(ctrl));
599 ctrl.id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE;
600 if (mDevice->Ioctl(VIDIOC_G_CTRL, &ctrl) != 0) {
601 ALOGE("ioctl() failed: VIDIOC_G_CTRL");
602 return std::nullopt;
603 }
604 ALOGV("%s() V4L2_CID_MIN_BUFFERS_FOR_CAPTURE returns %u", __func__, ctrl.value);
605
606 return ctrl.value + kNumExtraOutputBuffers;
607 }
608
getFormatInfo()609 std::optional<struct v4l2_format> V4L2Decoder::getFormatInfo() {
610 ALOGV("%s()", __func__);
611 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
612
613 struct v4l2_format format;
614 memset(&format, 0, sizeof(format));
615 format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
616 if (mDevice->Ioctl(VIDIOC_G_FMT, &format) != 0) {
617 ALOGE("ioctl() failed: VIDIOC_G_FMT");
618 return std::nullopt;
619 }
620
621 return format;
622 }
623
getVisibleRect(const media::Size & codedSize)624 media::Rect V4L2Decoder::getVisibleRect(const media::Size& codedSize) {
625 ALOGV("%s()", __func__);
626 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
627
628 struct v4l2_rect* visible_rect = nullptr;
629 struct v4l2_selection selection_arg;
630 memset(&selection_arg, 0, sizeof(selection_arg));
631 selection_arg.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
632 selection_arg.target = V4L2_SEL_TGT_COMPOSE;
633
634 if (mDevice->Ioctl(VIDIOC_G_SELECTION, &selection_arg) == 0) {
635 ALOGV("VIDIOC_G_SELECTION is supported");
636 visible_rect = &selection_arg.r;
637 } else {
638 ALOGV("Fallback to VIDIOC_G_CROP");
639 struct v4l2_crop crop_arg;
640 memset(&crop_arg, 0, sizeof(crop_arg));
641 crop_arg.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
642
643 if (mDevice->Ioctl(VIDIOC_G_CROP, &crop_arg) != 0) {
644 ALOGW("ioctl() VIDIOC_G_CROP failed");
645 return media::Rect(codedSize);
646 }
647 visible_rect = &crop_arg.c;
648 }
649
650 media::Rect rect(visible_rect->left, visible_rect->top, visible_rect->width,
651 visible_rect->height);
652 ALOGD("visible rectangle is %s", rect.ToString().c_str());
653 if (!media::Rect(codedSize).Contains(rect)) {
654 ALOGW("visible rectangle %s is not inside coded size %s", rect.ToString().c_str(),
655 codedSize.ToString().c_str());
656 return media::Rect(codedSize);
657 }
658 if (rect.IsEmpty()) {
659 ALOGW("visible size is empty");
660 return media::Rect(codedSize);
661 }
662
663 return rect;
664 }
665
sendV4L2DecoderCmd(bool start)666 bool V4L2Decoder::sendV4L2DecoderCmd(bool start) {
667 ALOGV("%s(start=%d)", __func__, start);
668 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
669
670 struct v4l2_decoder_cmd cmd;
671 memset(&cmd, 0, sizeof(cmd));
672 cmd.cmd = start ? V4L2_DEC_CMD_START : V4L2_DEC_CMD_STOP;
673 if (mDevice->Ioctl(VIDIOC_DECODER_CMD, &cmd) != 0) {
674 ALOGE("ioctl() VIDIOC_DECODER_CMD failed: start=%d", start);
675 return false;
676 }
677
678 return true;
679 }
680
onError()681 void V4L2Decoder::onError() {
682 ALOGV("%s()", __func__);
683 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
684
685 setState(State::Error);
686 mErrorCb.Run();
687 }
688
setState(State newState)689 void V4L2Decoder::setState(State newState) {
690 ALOGV("%s(%s)", __func__, StateToString(newState));
691 ALOG_ASSERT(mTaskRunner->RunsTasksInCurrentSequence());
692
693 if (mState == newState) return;
694 if (mState == State::Error) {
695 ALOGV("Already in Error state.");
696 return;
697 }
698
699 switch (newState) {
700 case State::Idle:
701 break;
702 case State::Decoding:
703 break;
704 case State::Draining:
705 if (mState != State::Decoding) newState = State::Error;
706 break;
707 case State::Error:
708 break;
709 }
710
711 ALOGI("Set state %s => %s", StateToString(mState), StateToString(newState));
712 mState = newState;
713 }
714
715 // static
StateToString(State state)716 const char* V4L2Decoder::StateToString(State state) {
717 switch (state) {
718 case State::Idle:
719 return "Idle";
720 case State::Decoding:
721 return "Decoding";
722 case State::Draining:
723 return "Draining";
724 case State::Error:
725 return "Error";
726 }
727 }
728
729 } // namespace android
730