• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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