diff options
author | Alexandre Courbot <acourbot@google.com> | 2020-08-03 14:13:08 +0900 |
---|---|---|
committer | Alexandre Courbot <acourbot@google.com> | 2020-08-05 11:58:01 +0900 |
commit | b8b9791ca729e15ac40b534c1b63f1e54a8ce586 (patch) | |
tree | 5f0cecadf87f3ddbbc7a6a11e6a909cbb7993e2f /components | |
parent | f14abffcf37057345506d3b7d861f2e0b9070fb4 (diff) | |
download | v4l2_codec2-b8b9791ca729e15ac40b534c1b63f1e54a8ce586.tar.gz |
V4L2Decoder: use map to associate block IDs to V4L2 buffers
Block IDs can be arbitrarily large, but we only have a limited number of
V4L2 buffers. Keep an association between the block IDs received from
VideoFramePool and a V4L2 buffer slot to use with them instead of
assuming that block IDs can be used as valid V4L2 buffer indices.
Bug: 161323057
Test: arc.VideoDecodeAccel.h264_vm fully passes on Kukui.
Change-Id: Id6a1013795d85cc08e3dca9308442db4921ddae0
Diffstat (limited to 'components')
-rw-r--r-- | components/V4L2Decoder.cpp | 29 | ||||
-rw-r--r-- | components/include/v4l2_codec2/components/V4L2Decoder.h | 5 |
2 files changed, 29 insertions, 5 deletions
diff --git a/components/V4L2Decoder.cpp b/components/V4L2Decoder.cpp index 71e3dc4..4301813 100644 --- a/components/V4L2Decoder.cpp +++ b/components/V4L2Decoder.cpp @@ -470,6 +470,7 @@ bool V4L2Decoder::changeResolution() { mOutputQueue->Streamoff(); mOutputQueue->DeallocateBuffers(); + mBlockIdToV4L2Id.clear(); if (mOutputQueue->AllocateBuffers(*numOutputBuffers, V4L2_MEMORY_DMABUF) == 0) { ALOGE("Failed to allocate output buffer."); @@ -522,17 +523,35 @@ void V4L2Decoder::onVideoFrameReady( uint32_t blockId; std::tie(frame, blockId) = std::move(*frameWithBlockId); - ::base::Optional<media::V4L2WritableBufferRef> outputBuffer = - mOutputQueue->GetFreeBuffer(blockId); + ::base::Optional<media::V4L2WritableBufferRef> outputBuffer; + // Find the V4L2 buffer that is associated with this block. + auto iter = mBlockIdToV4L2Id.find(blockId); + if (iter != mBlockIdToV4L2Id.end()) { + // If we have met this block in the past, reuse the same V4L2 buffer. + outputBuffer = mOutputQueue->GetFreeBuffer(iter->second); + } else if (mBlockIdToV4L2Id.size() < mOutputQueue->AllocatedBuffersCount()) { + // If this is the first time we see this block, give it the next + // available V4L2 buffer. + const size_t v4l2BufferId = mBlockIdToV4L2Id.size(); + mBlockIdToV4L2Id.emplace(blockId, v4l2BufferId); + outputBuffer = mOutputQueue->GetFreeBuffer(v4l2BufferId); + } else { + // If this happens, this is a bug in VideoFramePool. It should never + // provide more blocks than we have V4L2 buffers. + ALOGE("Got more different blocks than we have V4L2 buffers for."); + } + if (!outputBuffer) { - ALOGE("No free output buffer."); + ALOGE("V4L2 buffer not available."); onError(); return; } - ALOGV("QBUF to output queue, blockId=%u, fd: %d", blockId, frame->getFDs()[0].get()); + uint32_t v4l2Id = outputBuffer->BufferId(); + ALOGV("QBUF to output queue, blockId=%u, V4L2Id=%u", blockId, v4l2Id); + std::move(*outputBuffer).QueueDMABuf(frame->getFDs()); - mFrameAtDevice.insert(std::make_pair(blockId, std::move(frame))); + mFrameAtDevice.insert(std::make_pair(v4l2Id, std::move(frame))); tryFetchVideoFrame(); } diff --git a/components/include/v4l2_codec2/components/V4L2Decoder.h b/components/include/v4l2_codec2/components/V4L2Decoder.h index b7843c7..6476bb6 100644 --- a/components/include/v4l2_codec2/components/V4L2Decoder.h +++ b/components/include/v4l2_codec2/components/V4L2Decoder.h @@ -97,6 +97,11 @@ private: std::map<size_t, std::unique_ptr<VideoFrame>> mFrameAtDevice; + // Block IDs can be arbitrarily large, but we only have a limited number of + // buffers. This maintains an association between a block ID and a specific + // V4L2 buffer index. + std::map<size_t, size_t> mBlockIdToV4L2Id; + State mState = State::Idle; scoped_refptr<::base::SequencedTaskRunner> mTaskRunner; |