aboutsummaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorAlexandre Courbot <acourbot@google.com>2020-08-03 14:14:01 +0900
committerAlexandre Courbot <acourbot@google.com>2020-08-04 20:29:03 +0900
commit8138025080a9cca0167a6f32dc7058046f84b871 (patch)
tree98a8d0ab57dea8e0c577279b21ee17b1023c41e5 /components
parent6ced266b804391cc8617979af806eaa9a24353c1 (diff)
downloadv4l2_codec2-8138025080a9cca0167a6f32dc7058046f84b871.tar.gz
VideoFramePool: use exponential backoff for obtaining frames
The VideoFramePool needs to poll its backing block pool until a buffer becomes available. The current strategy is to sleep and repeat a number of times before giving up, but this carries the risk that some slower platforms will fail to receive buffers in the alloted time and introduce flakyness. Also the constant time between requests results in many requests to the block pool when it is empty, a situation that typically corresponds to the decoder having plenty of buffers at its disposal and thus not being in a particular hurry for a new buffer. Switch to an exponential backoff strategy for the block pool polling, and remove the time boundary. The exponential backoff limits the number of queries that are done to the block pool, and the absence of time makes the whole process safer. In case of a real error, the backing block pool is supposed to return a proper error code that we will propagate anyway. Bug: 161323057 Test: arc.VideoDecodeAccel.h264_vm does not time out waiting for buffers on Kukui. Change-Id: Ic3b9915926680cfd263352a7922658ec9a60b5cf
Diffstat (limited to 'components')
-rw-r--r--components/VideoFramePool.cpp28
-rw-r--r--components/include/v4l2_codec2/components/VideoFramePool.h4
2 files changed, 20 insertions, 12 deletions
diff --git a/components/VideoFramePool.cpp b/components/VideoFramePool.cpp
index 8703acf..c96fda7 100644
--- a/components/VideoFramePool.cpp
+++ b/components/VideoFramePool.cpp
@@ -24,11 +24,6 @@
using android::hardware::graphics::common::V1_0::BufferUsage;
namespace android {
-namespace {
-// The number of times and timeout used between subsequent calls when fetching graphic blocks.
-constexpr size_t kAllocateBufferMaxRetries = 32;
-constexpr size_t kFetchRetryDelayUs = 1000;
-} // namespace
// static
std::unique_ptr<VideoFramePool> VideoFramePool::Create(
@@ -82,6 +77,7 @@ VideoFramePool::~VideoFramePool() {
ALOG_ASSERT(mClientTaskRunner->RunsTasksInCurrentSequence());
mClientWeakThisFactory.InvalidateWeakPtrs();
+ mCancelGetFrame = true;
if (mFetchThread.IsRunning()) {
mFetchTaskRunner->PostTask(FROM_HERE,
@@ -116,11 +112,20 @@ bool VideoFramePool::hasPendingRequests() const {
void VideoFramePool::getVideoFrameTask(GetVideoFrameCB cb) {
ALOGV("%s()", __func__);
ALOG_ASSERT(mFetchTaskRunner->RunsTasksInCurrentSequence());
-
+ // Initial delay: 64us
+ constexpr size_t kFetchRetryDelayInit = 64;
+ // Max delay: 16ms (1 frame at 60fps)
+ constexpr size_t kFetchRetryDelayMax = 16384;
std::unique_ptr<VideoFrame> frame = nullptr;
size_t numRetries = 0;
- while (numRetries < kAllocateBufferMaxRetries) {
+ size_t delay = kFetchRetryDelayInit;
+ while (true) {
+ if (mCancelGetFrame) {
+ ALOGW("Request to get frame canceled after %zu retries", numRetries);
+ break;
+ }
+
std::shared_ptr<C2GraphicBlock> block;
c2_status_t err = mBlockPool->fetchGraphicBlock(mSize.width(), mSize.height(),
static_cast<uint32_t>(mPixelFormat),
@@ -135,13 +140,12 @@ void VideoFramePool::getVideoFrameTask(GetVideoFrameCB cb) {
break;
} else {
++numRetries;
- ALOGD("fetchGraphicBlock() timeout. retry %zu times", numRetries);
- usleep(kFetchRetryDelayUs);
+ ALOGD("fetchGraphicBlock() timeout, waiting %zuus (%zu retry)", delay, numRetries);
+ usleep(delay);
+ // Exponential backoff
+ delay = std::min(delay * 2, kFetchRetryDelayMax);
}
}
- if (numRetries == kAllocateBufferMaxRetries) {
- ALOGE("Timeout to fetch block, retry %zu times", numRetries);
- }
mClientTaskRunner->PostTask(
FROM_HERE, ::base::BindOnce(&VideoFramePool::onVideoFrameReady, mClientWeakThis,
diff --git a/components/include/v4l2_codec2/components/VideoFramePool.h b/components/include/v4l2_codec2/components/VideoFramePool.h
index 7097ad9..1de525e 100644
--- a/components/include/v4l2_codec2/components/VideoFramePool.h
+++ b/components/include/v4l2_codec2/components/VideoFramePool.h
@@ -5,6 +5,7 @@
#ifndef ANDROID_V4L2_CODEC2_COMPONENTS_VIDEO_FRAME_POOL_H
#define ANDROID_V4L2_CODEC2_COMPONENTS_VIDEO_FRAME_POOL_H
+#include <atomic>
#include <memory>
#include <queue>
@@ -66,6 +67,9 @@ private:
::base::Thread mFetchThread{"VideoFramePoolFetchThread"};
scoped_refptr<::base::SequencedTaskRunner> mFetchTaskRunner;
+ // Set to true to unconditionally interrupt pending frame requests.
+ std::atomic<bool> mCancelGetFrame = false;
+
::base::WeakPtr<VideoFramePool> mClientWeakThis;
::base::WeakPtr<VideoFramePool> mFetchWeakThis;
::base::WeakPtrFactory<VideoFramePool> mClientWeakThisFactory{this};