aboutsummaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorAlexandre Courbot <acourbot@google.com>2020-08-03 14:13:08 +0900
committerAlexandre Courbot <acourbot@google.com>2020-08-05 11:58:01 +0900
commitb8b9791ca729e15ac40b534c1b63f1e54a8ce586 (patch)
tree5f0cecadf87f3ddbbc7a6a11e6a909cbb7993e2f /components
parentf14abffcf37057345506d3b7d861f2e0b9070fb4 (diff)
downloadv4l2_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.cpp29
-rw-r--r--components/include/v4l2_codec2/components/V4L2Decoder.h5
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;