media/gpu/v4l2vd: use buffer affinity tracker
When using DMABUFs, it is preferable to use the same V4L2 buffer with
the same underlying buffer, as failure to do so results in memory
unmappings/remappings in the driver. Use the newly introduced buffer
affinity tracker and V4L2Queue::GetFreeBufferForFrame() method to
achieve this transparently in the video decoder.
Furthermore, it is a requirement of the V4L2 stateful decoder interface
that V4L2 buffers are always backed by the same underlying memory, lest
some reference frames lifetime tracking might be incorrect.
BUG=b:159688625
BUG=b:167412992
TEST=video.DecodeAccel.h264 passes on Trogdor.
(cherry picked from commit 2ca56c5955a7fd3acde86a492385e661e3cdaeb1)
Change-Id: I220a321d5584f50406480c105844a82dd96e63c6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2415909
Commit-Queue: Alexandre Courbot <[email protected]>
Reviewed-by: Fritz Koenig <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#813178}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2459405
Reviewed-by: Alexandre Courbot <[email protected]>
Cr-Commit-Position: refs/branch-heads/4280@{#131}
Cr-Branched-From: ea420fb963f9658c9969b6513c56b8f47efa1a2a-refs/heads/master@{#812852}
diff --git a/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.cc b/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.cc
index f959ec6..25f77a7 100644
--- a/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.cc
+++ b/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.cc
@@ -258,12 +258,19 @@
DVLOGF(3);
const v4l2_memory mem_type = output_queue_->GetMemoryType();
- while (base::Optional<V4L2WritableBufferRef> buffer =
- output_queue_->GetFreeBuffer()) {
+ while (true) {
bool ret = false;
+ bool no_buffer = false;
+ base::Optional<V4L2WritableBufferRef> buffer;
switch (mem_type) {
case V4L2_MEMORY_MMAP:
+ buffer = output_queue_->GetFreeBuffer();
+ if (!buffer) {
+ no_buffer = true;
+ break;
+ }
+
ret = std::move(*buffer).QueueMMap();
break;
case V4L2_MEMORY_DMABUF: {
@@ -272,6 +279,12 @@
// once frames are available.
if (!video_frame)
return;
+ buffer = output_queue_->GetFreeBufferForFrame(*video_frame);
+ if (!buffer) {
+ no_buffer = true;
+ break;
+ }
+
ret = std::move(*buffer).QueueDMABuf(std::move(video_frame));
break;
}
@@ -279,6 +292,11 @@
NOTREACHED();
}
+ // Running out of V4L2 buffers is not an error, so just exit the loop
+ // gracefully.
+ if (no_buffer)
+ break;
+
if (!ret)
client_->OnBackendError();
}