aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2024-03-06 09:29:57 -0800
committerXin Li <delphij@google.com>2024-03-06 09:29:57 -0800
commitb1539bd84beb1f5c54d8b5829eb74e7e04d82bb2 (patch)
treefe8ef1440268541e5f5b3b0bd0d4f3fc191dccdd
parent69678074833080eb0e4ec62b44240b3c7454d4da (diff)
parent3bde35bb879e4b628408ec6e126e7f124121f351 (diff)
downloadv4l2_codec2-main.tar.gz
Merge Android 14 QPR2 to AOSP mainHEADmastermain
Bug: 319669529 Merged-In: Id57ac546595fde736a32d17f61039b44107f413e Change-Id: I2f803594c587ed291e5f86f82779cadc5c1a77e4
-rw-r--r--common/include/v4l2_codec2/common/V4L2Device.h45
-rw-r--r--common/include/v4l2_codec2/common/V4L2DevicePoller.h12
-rw-r--r--components/V4L2DecodeComponent.cpp1
-rw-r--r--components/V4L2DecodeInterface.cpp4
-rw-r--r--components/V4L2EncodeComponent.cpp26
-rw-r--r--components/VideoFramePool.cpp181
-rw-r--r--components/include/v4l2_codec2/components/VideoDecoder.h8
-rw-r--r--components/include/v4l2_codec2/components/VideoEncoder.h10
-rw-r--r--components/include/v4l2_codec2/components/VideoFramePool.h23
-rw-r--r--plugin_store/Android.bp3
-rw-r--r--plugin_store/C2VdaBqBlockPool.cpp957
-rw-r--r--plugin_store/C2VdaPooledBlockPool.cpp86
-rw-r--r--plugin_store/H2BGraphicBufferProducer.cpp287
-rw-r--r--plugin_store/V4L2PluginStore.cpp11
-rw-r--r--plugin_store/include/v4l2_codec2/plugin_store/C2VdaBqBlockPool.h104
-rw-r--r--plugin_store/include/v4l2_codec2/plugin_store/C2VdaPooledBlockPool.h53
-rw-r--r--plugin_store/include/v4l2_codec2/plugin_store/H2BGraphicBufferProducer.h48
-rw-r--r--plugin_store/include/v4l2_codec2/plugin_store/V4L2AllocatorId.h4
-rw-r--r--service/Android.bp6
-rw-r--r--service/android.hardware.media.c2@1.2-service-v4l2-32.rc (renamed from service/android.hardware.media.c2@1.0-service-v4l2-32.rc)2
-rw-r--r--service/android.hardware.media.c2@1.2-service-v4l2-64.rc (renamed from service/android.hardware.media.c2@1.0-service-v4l2-64.rc)2
-rw-r--r--service/service.cpp6
22 files changed, 198 insertions, 1681 deletions
diff --git a/common/include/v4l2_codec2/common/V4L2Device.h b/common/include/v4l2_codec2/common/V4L2Device.h
index 77d7ddb..9824221 100644
--- a/common/include/v4l2_codec2/common/V4L2Device.h
+++ b/common/include/v4l2_codec2/common/V4L2Device.h
@@ -105,7 +105,7 @@ private:
// Do the actual queue operation once the v4l2_buffer structure is properly filled.
bool doQueue() &&;
- V4L2WritableBufferRef(const struct v4l2_buffer& v4l2Buffer, base::WeakPtr<V4L2Queue> queue);
+ V4L2WritableBufferRef(const struct v4l2_buffer& v4l2Buffer, ::base::WeakPtr<V4L2Queue> queue);
V4L2WritableBufferRef(const V4L2WritableBufferRef&) = delete;
V4L2WritableBufferRef& operator=(const V4L2WritableBufferRef&) = delete;
@@ -124,7 +124,7 @@ private:
// buffers they originate from. This flexibility is required because V4L2ReadableBufferRefs can be
// embedded into VideoFrames, which are then passed to other threads and not necessarily destroyed
// before the V4L2Queue buffers are freed.
-class V4L2ReadableBuffer : public base::RefCountedThreadSafe<V4L2ReadableBuffer> {
+class V4L2ReadableBuffer : public ::base::RefCountedThreadSafe<V4L2ReadableBuffer> {
public:
// Returns whether the V4L2_BUF_FLAG_LAST flag is set for this buffer.
bool isLast() const;
@@ -148,11 +148,11 @@ public:
private:
friend class V4L2BufferRefFactory;
- friend class base::RefCountedThreadSafe<V4L2ReadableBuffer>;
+ friend class ::base::RefCountedThreadSafe<V4L2ReadableBuffer>;
~V4L2ReadableBuffer();
- V4L2ReadableBuffer(const struct v4l2_buffer& v4l2Buffer, base::WeakPtr<V4L2Queue> queue);
+ V4L2ReadableBuffer(const struct v4l2_buffer& v4l2Buffer, ::base::WeakPtr<V4L2Queue> queue);
V4L2ReadableBuffer(const V4L2ReadableBuffer&) = delete;
V4L2ReadableBuffer& operator=(const V4L2ReadableBuffer&) = delete;
@@ -183,7 +183,7 @@ class V4L2Buffer;
// metadata, as well as making other references to it. The buffer will not be reused until all
// the references are dropped. Once this happens, the buffer goes back to the free list described
// in 1).
-class V4L2Queue : public base::RefCountedThreadSafe<V4L2Queue> {
+class V4L2Queue : public ::base::RefCountedThreadSafe<V4L2Queue> {
public:
// Set |fourcc| as the current format on this queue. |size| corresponds to the desired buffer's
// dimensions (i.e. width and height members of v4l2_pix_format_mplane (if not applicable, pass
@@ -206,10 +206,10 @@ public:
size_t bufferSize) WARN_UNUSED_RESULT;
// Returns the currently set format on the queue. The result is returned as a std::pair where
- // the first member is the format, or base::nullopt if the format could not be obtained due to
- // an ioctl error. The second member is only used in case of an error and contains the |errno|
- // set by the failing ioctl. If the first member is not base::nullopt, the second member will
- // always be zero.
+ // the first member is the format, or ::base::nullopt if the format could not be obtained due
+ // to an ioctl error. The second member is only used in case of an error and contains the
+ // |errno| set by the failing ioctl. If the first member is not ::base::nullopt, the second
+ // member will always be zero.
//
// If the second member is 0, then the first member is guaranteed to have a valid value. So
// clients that are not interested in the precise error message can just check that the first
@@ -304,19 +304,20 @@ private:
scoped_refptr<V4L2Device> mDevice;
// Callback to call in this queue's destructor.
- base::OnceClosure mDestroyCb;
+ ::base::OnceClosure mDestroyCb;
- V4L2Queue(scoped_refptr<V4L2Device> dev, enum v4l2_buf_type type, base::OnceClosure destroyCb);
+ V4L2Queue(scoped_refptr<V4L2Device> dev, enum v4l2_buf_type type,
+ ::base::OnceClosure destroyCb);
friend class V4L2QueueFactory;
friend class V4L2BufferRefBase;
- friend class base::RefCountedThreadSafe<V4L2Queue>;
+ friend class ::base::RefCountedThreadSafe<V4L2Queue>;
SEQUENCE_CHECKER(mSequenceChecker);
- base::WeakPtrFactory<V4L2Queue> mWeakThisFactory{this};
+ ::base::WeakPtrFactory<V4L2Queue> mWeakThisFactory{this};
};
-class V4L2Device : public base::RefCountedThreadSafe<V4L2Device> {
+class V4L2Device : public ::base::RefCountedThreadSafe<V4L2Device> {
public:
// Specification of an encoding profile supported by an encoder.
struct SupportedEncodeProfile {
@@ -364,7 +365,7 @@ public:
// Composes human readable string of v4l2_buffer.
static std::string v4L2BufferToString(const struct v4l2_buffer& buffer);
- // Composes VideoFrameLayout based on v4l2_format. If error occurs, it returns base::nullopt.
+ // Composes VideoFrameLayout based on v4l2_format. If error occurs, it returns ::base::nullopt.
static std::optional<VideoFrameLayout> v4L2FormatToVideoFrameLayout(
const struct v4l2_format& format);
@@ -411,8 +412,8 @@ public:
// Return a vector of dmabuf file descriptors, exported for V4L2 buffer with |index|, assuming
// the buffer contains |numPlanes| V4L2 planes and is of |bufType|. Return an empty vector on
// failure. The caller is responsible for closing the file descriptors after use.
- std::vector<base::ScopedFD> getDmabufsForV4L2Buffer(int index, size_t numPlanes,
- enum v4l2_buf_type bufType);
+ std::vector<::base::ScopedFD> getDmabufsForV4L2Buffer(int index, size_t numPlanes,
+ enum v4l2_buf_type bufType);
// Returns the preferred V4L2 input formats for |type| or empty if none.
std::vector<uint32_t> preferredInputFormat(Type type);
@@ -440,7 +441,7 @@ public:
// be posted to the client's
// sequence if a polling error has occurred.
bool startPolling(android::V4L2DevicePoller::EventCallback eventCallback,
- base::RepeatingClosure errorCallback);
+ ::base::RepeatingClosure errorCallback);
// Stop polling this V4L2Device if polling was active. No new events will be posted after this
// method has returned.
bool stopPolling();
@@ -463,7 +464,7 @@ private:
// Vector of video device node paths and corresponding pixelformats supported by each device node.
using Devices = std::vector<std::pair<std::string, std::vector<uint32_t>>>;
- friend class base::RefCountedThreadSafe<V4L2Device>;
+ friend class ::base::RefCountedThreadSafe<V4L2Device>;
V4L2Device();
~V4L2Device();
@@ -500,13 +501,13 @@ private:
std::map<V4L2Device::Type, Devices> mDevicesByType;
// The actual device fd.
- base::ScopedFD mDeviceFd;
+ ::base::ScopedFD mDeviceFd;
// eventfd fd to signal device poll thread when its poll() should be interrupted.
- base::ScopedFD mDevicePollInterruptFd;
+ ::base::ScopedFD mDevicePollInterruptFd;
// Associates a v4l2_buf_type to its queue.
- base::flat_map<enum v4l2_buf_type, V4L2Queue*> mQueues;
+ ::base::flat_map<enum v4l2_buf_type, V4L2Queue*> mQueues;
// Used if EnablePolling() is called to signal the user that an event happened or a buffer is
// ready to be dequeued.
diff --git a/common/include/v4l2_codec2/common/V4L2DevicePoller.h b/common/include/v4l2_codec2/common/V4L2DevicePoller.h
index ad256be..53b4b3f 100644
--- a/common/include/v4l2_codec2/common/V4L2DevicePoller.h
+++ b/common/include/v4l2_codec2/common/V4L2DevicePoller.h
@@ -32,7 +32,7 @@ class V4L2DevicePoller {
public:
// Callback to be called when buffer ready/V4L2 event has potentially been polled. |event| is
// set if a V4L2 event has been detected.
- using EventCallback = base::RepeatingCallback<void(bool event)>;
+ using EventCallback = ::base::RepeatingCallback<void(bool event)>;
// Create a poller for |device|, using a thread named |threadName|. Notification won't start
// until |startPolling()| is called.
@@ -45,7 +45,7 @@ public:
// again in order to be notified for them.
//
// If an error occurs during polling, |mErrorCallback| will be posted on the caller's sequence.
- bool startPolling(EventCallback eventCallback, base::RepeatingClosure errorCallback);
+ bool startPolling(EventCallback eventCallback, ::base::RepeatingClosure errorCallback);
// Stop polling and stop the thread. The poller won't post any new event to the caller's
// sequence after this method has returned.
bool stopPolling();
@@ -66,19 +66,19 @@ private:
// V4L2 device we are polling.
V4L2Device* const mDevice;
// Thread on which polling is done.
- base::Thread mPollThread;
+ ::base::Thread mPollThread;
// Callback to post to the client's sequence when an event occurs.
EventCallback mEventCallback;
// Closure to post to the client's sequence when an error occurs.
- base::RepeatingClosure mErrorCallback;
+ ::base::RepeatingClosure mErrorCallback;
// Client sequence's task runner, where closures are posted.
- scoped_refptr<base::SequencedTaskRunner> mClientTaskTunner;
+ scoped_refptr<::base::SequencedTaskRunner> mClientTaskTunner;
// Since poll() returns immediately if no buffers have been queued, we cannot rely on it to
// pause the polling thread until an event occurs. Instead,
// the polling thread will wait on this WaitableEvent (signaled by |schedulePoll| before calling
// poll(), so we only call it when we are actually waiting for an event.
- base::WaitableEvent mTriggerPoll;
+ ::base::WaitableEvent mTriggerPoll;
// Set to true when we wish to stop polling, instructing the poller thread to break its loop.
std::atomic_bool mStopPolling;
};
diff --git a/components/V4L2DecodeComponent.cpp b/components/V4L2DecodeComponent.cpp
index 456f3c4..2770b1e 100644
--- a/components/V4L2DecodeComponent.cpp
+++ b/components/V4L2DecodeComponent.cpp
@@ -30,7 +30,6 @@
#include <v4l2_codec2/components/BitstreamBuffer.h>
#include <v4l2_codec2/components/V4L2Decoder.h>
#include <v4l2_codec2/components/VideoFramePool.h>
-#include <v4l2_codec2/plugin_store/C2VdaBqBlockPool.h>
namespace android {
namespace {
diff --git a/components/V4L2DecodeInterface.cpp b/components/V4L2DecodeInterface.cpp
index d22f77b..32483be 100644
--- a/components/V4L2DecodeInterface.cpp
+++ b/components/V4L2DecodeInterface.cpp
@@ -267,9 +267,9 @@ V4L2DecodeInterface::V4L2DecodeInterface(const std::string& name,
const C2Allocator::id_t inputAllocators[] = {secureMode ? V4L2AllocatorId::SECURE_LINEAR
: C2AllocatorStore::DEFAULT_LINEAR};
- const C2Allocator::id_t outputAllocators[] = {V4L2AllocatorId::V4L2_BUFFERPOOL};
+ const C2Allocator::id_t outputAllocators[] = {C2PlatformAllocatorStore::GRALLOC};
const C2Allocator::id_t surfaceAllocator =
- secureMode ? V4L2AllocatorId::SECURE_GRAPHIC : V4L2AllocatorId::V4L2_BUFFERQUEUE;
+ secureMode ? V4L2AllocatorId::SECURE_GRAPHIC : C2PlatformAllocatorStore::BUFFERQUEUE;
const C2BlockPool::local_id_t outputBlockPools[] = {C2BlockPool::BASIC_GRAPHIC};
addParameter(
diff --git a/components/V4L2EncodeComponent.cpp b/components/V4L2EncodeComponent.cpp
index f9d735d..b266a6e 100644
--- a/components/V4L2EncodeComponent.cpp
+++ b/components/V4L2EncodeComponent.cpp
@@ -517,6 +517,32 @@ void V4L2EncodeComponent::queueTask(std::unique_ptr<C2Work> work) {
reportError(status);
return;
}
+ } else {
+ // Android encoder framework reuses the same gpu buffers as
+ // inputs and doesn't call lock/unlock explicitly between writes.
+ // If there is format conversion, this is fine since we will
+ // read back what we've written first and then put it in another
+ // buffer. Whenever there is no format conversion, this causes
+ // sync issue on ARCVM since host side buffers never get updated.
+ // Fix this by explicitly calling lock/unlock before sending buffer
+ // to encoder.
+ const C2Handle* handle = inputBlock.handle();
+ uint32_t width, height, format, stride, generation, igbpSlot;
+ uint64_t usage, igbpId;
+ _UnwrapNativeCodec2GrallocMetadata(handle, &width, &height, &format, &usage, &stride,
+ &generation, &igbpId, &igbpSlot);
+ do {
+ if (!(usage & GRALLOC_USAGE_SW_WRITE_MASK)) break;
+ native_handle_t* gralloc_handle = UnwrapNativeCodec2GrallocHandle(handle);
+ if (nullptr == gralloc_handle) break;
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(gralloc_handle, GraphicBuffer::CLONE_HANDLE, width,
+ height, format, 1, usage, stride);
+ native_handle_delete(gralloc_handle);
+ void* pixels;
+ if (buffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, &pixels)) break;
+ buffer->unlock();
+ } while (0);
}
if (!encode(inputBlock, index, timestamp)) {
return;
diff --git a/components/VideoFramePool.cpp b/components/VideoFramePool.cpp
index 665ff73..4bf45f3 100644
--- a/components/VideoFramePool.cpp
+++ b/components/VideoFramePool.cpp
@@ -10,6 +10,9 @@
#include <stdint.h>
#include <memory>
+#include <C2BlockInternal.h>
+#include <bufferpool/BufferPoolTypes.h>
+
#include <android/hardware/graphics/common/1.0/types.h>
#include <base/bind.h>
#include <base/memory/ptr_util.h>
@@ -17,11 +20,11 @@
#include <log/log.h>
#include <v4l2_codec2/common/VideoTypes.h>
-#include <v4l2_codec2/plugin_store/C2VdaBqBlockPool.h>
-#include <v4l2_codec2/plugin_store/C2VdaPooledBlockPool.h>
+#include <v4l2_codec2/plugin_store/DmabufHelpers.h>
#include <v4l2_codec2/plugin_store/V4L2AllocatorId.h>
using android::hardware::graphics::common::V1_0::BufferUsage;
+using android::hardware::media::bufferpool::BufferPoolData;
namespace android {
@@ -30,44 +33,36 @@ std::optional<uint32_t> VideoFramePool::getBufferIdFromGraphicBlock(C2BlockPool&
const C2Block2D& block) {
ALOGV("%s() blockPool.getAllocatorId() = %u", __func__, blockPool.getAllocatorId());
- if (blockPool.getAllocatorId() == android::V4L2AllocatorId::V4L2_BUFFERPOOL) {
- return C2VdaPooledBlockPool::getBufferIdFromGraphicBlock(block);
- } else if (blockPool.getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
- C2VdaBqBlockPool* bqPool = static_cast<C2VdaBqBlockPool*>(&blockPool);
- return bqPool->getBufferIdFromGraphicBlock(block);
+ switch (blockPool.getAllocatorId()) {
+ case V4L2AllocatorId::SECURE_GRAPHIC:
+ FALLTHROUGH;
+ case C2PlatformAllocatorStore::BUFFERQUEUE: {
+ auto dmabufId = android::getDmabufId(block.handle()->data[0]);
+ if (!dmabufId) {
+ return std::nullopt;
+ }
+ return dmabufId.value();
+ }
+ case C2PlatformAllocatorStore::GRALLOC:
+ FALLTHROUGH;
+ case V4L2AllocatorId::SECURE_LINEAR: {
+ std::shared_ptr<_C2BlockPoolData> blockPoolData =
+ _C2BlockFactory::GetGraphicBlockPoolData(block);
+ if (blockPoolData->getType() != _C2BlockPoolData::TYPE_BUFFERPOOL) {
+ ALOGE("Obtained C2GraphicBlock is not bufferpool-backed.");
+ return std::nullopt;
+ }
+ std::shared_ptr<BufferPoolData> bpData;
+ if (!_C2BlockFactory::GetBufferPoolData(blockPoolData, &bpData) || !bpData) {
+ ALOGE("BufferPoolData unavailable in block.");
+ return std::nullopt;
+ }
+ return bpData->mId;
}
-
- ALOGE("%s(): unknown allocator ID: %u", __func__, blockPool.getAllocatorId());
- return std::nullopt;
-}
-
-// static
-c2_status_t VideoFramePool::requestNewBufferSet(C2BlockPool& blockPool, int32_t bufferCount,
- const ui::Size& size, uint32_t format,
- C2MemoryUsage usage) {
- ALOGV("%s() blockPool.getAllocatorId() = %u", __func__, blockPool.getAllocatorId());
-
- if (blockPool.getAllocatorId() == android::V4L2AllocatorId::V4L2_BUFFERPOOL) {
- C2VdaPooledBlockPool* bpPool = static_cast<C2VdaPooledBlockPool*>(&blockPool);
- return bpPool->requestNewBufferSet(bufferCount);
- } else if (blockPool.getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
- C2VdaBqBlockPool* bqPool = static_cast<C2VdaBqBlockPool*>(&blockPool);
- return bqPool->requestNewBufferSet(bufferCount, size.width, size.height, format, usage);
}
ALOGE("%s(): unknown allocator ID: %u", __func__, blockPool.getAllocatorId());
- return C2_BAD_VALUE;
-}
-
-// static
-bool VideoFramePool::setNotifyBlockAvailableCb(C2BlockPool& blockPool, ::base::OnceClosure cb) {
- ALOGV("%s() blockPool.getAllocatorId() = %u", __func__, blockPool.getAllocatorId());
-
- if (blockPool.getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
- C2VdaBqBlockPool* bqPool = static_cast<C2VdaBqBlockPool*>(&blockPool);
- return bqPool->setNotifyBlockAvailableCb(std::move(cb));
- }
- return false;
+ return std::nullopt;
}
// static
@@ -80,27 +75,25 @@ std::unique_ptr<VideoFramePool> VideoFramePool::Create(
uint64_t usage = static_cast<uint64_t>(BufferUsage::VIDEO_DECODER);
if (isSecure) {
usage |= C2MemoryUsage::READ_PROTECTED;
- } else if (blockPool->getAllocatorId() == android::V4L2AllocatorId::V4L2_BUFFERPOOL) {
+ } else if (blockPool->getAllocatorId() == C2PlatformAllocatorStore::GRALLOC) {
// CPU access to buffers is only required in byte buffer mode.
usage |= C2MemoryUsage::CPU_READ;
}
const C2MemoryUsage memoryUsage(usage);
- if (requestNewBufferSet(*blockPool, numBuffers, size, static_cast<uint32_t>(pixelFormat),
- memoryUsage) != C2_OK) {
- return nullptr;
- }
-
- std::unique_ptr<VideoFramePool> pool = ::base::WrapUnique(new VideoFramePool(
- std::move(blockPool), size, pixelFormat, memoryUsage, std::move(taskRunner)));
+ std::unique_ptr<VideoFramePool> pool =
+ ::base::WrapUnique(new VideoFramePool(std::move(blockPool), numBuffers, size,
+ pixelFormat, memoryUsage, std::move(taskRunner)));
if (!pool->initialize()) return nullptr;
return pool;
}
-VideoFramePool::VideoFramePool(std::shared_ptr<C2BlockPool> blockPool, const ui::Size& size,
- HalPixelFormat pixelFormat, C2MemoryUsage memoryUsage,
+VideoFramePool::VideoFramePool(std::shared_ptr<C2BlockPool> blockPool, const size_t maxBufferCount,
+ const ui::Size& size, HalPixelFormat pixelFormat,
+ C2MemoryUsage memoryUsage,
scoped_refptr<::base::SequencedTaskRunner> taskRunner)
: mBlockPool(std::move(blockPool)),
+ mMaxBufferCount(maxBufferCount),
mSize(size),
mPixelFormat(pixelFormat),
mMemoryUsage(memoryUsage),
@@ -144,6 +137,18 @@ void VideoFramePool::destroyTask() {
mFetchWeakThisFactory.InvalidateWeakPtrs();
}
+bool VideoFramePool::shouldDropBuffer(uint32_t bufferId) {
+ if (mBuffers.size() < mMaxBufferCount) {
+ return false;
+ }
+
+ if (mBuffers.find(bufferId) != mBuffers.end()) {
+ return false;
+ }
+
+ return true;
+}
+
bool VideoFramePool::getVideoFrame(GetVideoFrameCB cb) {
ALOGV("%s()", __func__);
ALOG_ASSERT(mClientTaskRunner->RunsTasksInCurrentSequence());
@@ -176,28 +181,58 @@ void VideoFramePool::getVideoFrameTask() {
// Variables used to exponential backoff retry when buffer fetching times out.
constexpr size_t kFetchRetryDelayInit = 64; // Initial delay: 64us
constexpr size_t kFetchRetryDelayMax = 16384; // Max delay: 16ms (1 frame at 60fps)
+ constexpr size_t kFenceWaitTimeoutNs = 16000000; // 16ms (1 frame at 60fps)
static size_t sNumRetries = 0;
static size_t sDelay = kFetchRetryDelayInit;
+ C2Fence fence;
std::shared_ptr<C2GraphicBlock> block;
- c2_status_t err = mBlockPool->fetchGraphicBlock(
- mSize.width, mSize.height, static_cast<uint32_t>(mPixelFormat), mMemoryUsage, &block);
- if (err == C2_TIMED_OUT || err == C2_BLOCKING) {
- if (setNotifyBlockAvailableCb(*mBlockPool,
- ::base::BindOnce(&VideoFramePool::getVideoFrameTaskThunk,
- mFetchTaskRunner, mFetchWeakThis))) {
- ALOGV("%s(): fetchGraphicBlock() timeout, waiting for block available.", __func__);
- } else {
- ALOGV("%s(): fetchGraphicBlock() timeout, waiting %zuus (%zu retry)", __func__, sDelay,
- sNumRetries + 1);
- mFetchTaskRunner->PostDelayedTask(
- FROM_HERE, ::base::BindOnce(&VideoFramePool::getVideoFrameTask, mFetchWeakThis),
- ::base::TimeDelta::FromMicroseconds(sDelay));
-
- sDelay = std::min(sDelay * 2, kFetchRetryDelayMax); // Exponential backoff
- sNumRetries++;
+ c2_status_t err = mBlockPool->fetchGraphicBlock(mSize.width, mSize.height,
+ static_cast<uint32_t>(mPixelFormat),
+ mMemoryUsage, &block, &fence);
+ if (err == C2_BLOCKING) {
+ err = fence.wait(kFenceWaitTimeoutNs);
+ if (err == C2_OK) {
+ ALOGV("%s(): fence wait succeded, retrying now", __func__);
+ mFetchTaskRunner->PostTask(
+ FROM_HERE,
+ ::base::BindOnce(&VideoFramePool::getVideoFrameTask, mFetchWeakThis));
+ return;
}
+ ALOGV("%s(): fence wait unsucessful err=%d", __func__, err);
+ } else if (err == C2_OMITTED) {
+ // Fenced version is not supported, try legacy version.
+ err = mBlockPool->fetchGraphicBlock(mSize.width, mSize.height,
+ static_cast<uint32_t>(mPixelFormat), mMemoryUsage,
+ &block);
+ }
+ std::optional<uint32_t> bufferId;
+ if (err == C2_OK) {
+ bufferId = getBufferIdFromGraphicBlock(*mBlockPool, *block);
+
+ if (bufferId) {
+ ALOGV("%s(): Got buffer with id = %u", __func__, *bufferId);
+
+ if (shouldDropBuffer(*bufferId)) {
+ // We drop buffer, since we got more then needed.
+ ALOGV("%s(): Dropping allocated buffer with id = %u", __func__, *bufferId);
+ bufferId = std::nullopt;
+ block.reset();
+ err = C2_TIMED_OUT;
+ }
+ }
+ }
+
+ if (err == C2_TIMED_OUT || err == C2_BLOCKING) {
+ ALOGV("%s(): fetchGraphicBlock() timeout, waiting %zuus (%zu retry)", __func__, sDelay,
+ sNumRetries + 1);
+ mFetchTaskRunner->PostDelayedTask(
+ FROM_HERE, ::base::BindOnce(&VideoFramePool::getVideoFrameTask, mFetchWeakThis),
+ ::base::TimeDelta::FromMicroseconds(sDelay));
+
+ sDelay = std::min(sDelay * 2, kFetchRetryDelayMax); // Exponential backoff
+ sNumRetries++;
return;
}
@@ -205,20 +240,22 @@ void VideoFramePool::getVideoFrameTask() {
sNumRetries = 0;
sDelay = kFetchRetryDelayInit;
+ if (err != C2_OK) {
+ ALOGE("%s(): Failed to fetch block, err=%d", __func__, err);
+ return;
+ }
+
+ ALOG_ASSERT(block != nullptr);
+ std::unique_ptr<VideoFrame> frame = VideoFrame::Create(std::move(block));
std::optional<FrameWithBlockId> frameWithBlockId;
- if (err == C2_OK) {
- ALOG_ASSERT(block != nullptr);
- std::optional<uint32_t> bufferId = getBufferIdFromGraphicBlock(*mBlockPool, *block);
- std::unique_ptr<VideoFrame> frame = VideoFrame::Create(std::move(block));
+
+ if (bufferId && frame) {
// Only pass the frame + id pair if both have successfully been obtained.
// Otherwise exit the loop so a nullopt is passed to the client.
- if (bufferId && frame) {
- frameWithBlockId = std::make_pair(std::move(frame), *bufferId);
- } else {
- ALOGE("%s(): Failed to generate VideoFrame or get the buffer id.", __func__);
- }
+ frameWithBlockId = std::make_pair(std::move(frame), *bufferId);
+ mBuffers.insert(*bufferId);
} else {
- ALOGE("%s(): Failed to fetch block, err=%d", __func__, err);
+ ALOGE("%s(): Failed to generate VideoFrame or get the buffer id.", __func__);
}
mClientTaskRunner->PostTask(
diff --git a/components/include/v4l2_codec2/components/VideoDecoder.h b/components/include/v4l2_codec2/components/VideoDecoder.h
index 5b2da41..3e3fec4 100644
--- a/components/include/v4l2_codec2/components/VideoDecoder.h
+++ b/components/include/v4l2_codec2/components/VideoDecoder.h
@@ -26,11 +26,11 @@ public:
};
static const char* DecodeStatusToString(DecodeStatus status);
- using GetPoolCB = base::RepeatingCallback<std::unique_ptr<VideoFramePool>(
+ using GetPoolCB = ::base::RepeatingCallback<std::unique_ptr<VideoFramePool>(
const ui::Size& size, HalPixelFormat pixelFormat, size_t numOutputBuffers)>;
- using DecodeCB = base::OnceCallback<void(DecodeStatus)>;
- using OutputCB = base::RepeatingCallback<void(std::unique_ptr<VideoFrame>)>;
- using ErrorCB = base::RepeatingCallback<void()>;
+ using DecodeCB = ::base::OnceCallback<void(DecodeStatus)>;
+ using OutputCB = ::base::RepeatingCallback<void(std::unique_ptr<VideoFrame>)>;
+ using ErrorCB = ::base::RepeatingCallback<void()>;
virtual ~VideoDecoder();
diff --git a/components/include/v4l2_codec2/components/VideoEncoder.h b/components/include/v4l2_codec2/components/VideoEncoder.h
index 5f23541..7e5a3c2 100644
--- a/components/include/v4l2_codec2/components/VideoEncoder.h
+++ b/components/include/v4l2_codec2/components/VideoEncoder.h
@@ -47,13 +47,13 @@ public:
};
using FetchOutputBufferCB =
- base::RepeatingCallback<void(uint32_t, std::unique_ptr<BitstreamBuffer>* buffer)>;
+ ::base::RepeatingCallback<void(uint32_t, std::unique_ptr<BitstreamBuffer>* buffer)>;
// TODO(dstaessens): Change callbacks to OnceCallback provided when requesting encode/drain.
- using InputBufferDoneCB = base::RepeatingCallback<void(uint64_t)>;
- using OutputBufferDoneCB = base::RepeatingCallback<void(
+ using InputBufferDoneCB = ::base::RepeatingCallback<void(uint64_t)>;
+ using OutputBufferDoneCB = ::base::RepeatingCallback<void(
size_t, int64_t, bool, std::unique_ptr<BitstreamBuffer> buffer)>;
- using DrainDoneCB = base::RepeatingCallback<void(bool)>;
- using ErrorCB = base::RepeatingCallback<void()>;
+ using DrainDoneCB = ::base::RepeatingCallback<void(bool)>;
+ using ErrorCB = ::base::RepeatingCallback<void()>;
virtual ~VideoEncoder() = default;
diff --git a/components/include/v4l2_codec2/components/VideoFramePool.h b/components/include/v4l2_codec2/components/VideoFramePool.h
index 2978eed..6bebc37 100644
--- a/components/include/v4l2_codec2/components/VideoFramePool.h
+++ b/components/include/v4l2_codec2/components/VideoFramePool.h
@@ -44,12 +44,13 @@ public:
private:
// |blockPool| is the C2BlockPool that we fetch graphic blocks from.
+ // |maxBufferCount| maximum number of buffer that should should provide to client
// |size| is the resolution size of the required graphic blocks.
// |pixelFormat| is the pixel format of the required graphic blocks.
// |isSecure| indicates the video stream is encrypted or not.
// All public methods and the callbacks should be run on |taskRunner|.
- VideoFramePool(std::shared_ptr<C2BlockPool> blockPool, const ui::Size& size,
- HalPixelFormat pixelFormat, C2MemoryUsage memoryUsage,
+ VideoFramePool(std::shared_ptr<C2BlockPool> blockPool, const size_t maxBufferCount,
+ const ui::Size& size, HalPixelFormat pixelFormat, C2MemoryUsage memoryUsage,
scoped_refptr<::base::SequencedTaskRunner> taskRunner);
bool initialize();
void destroyTask();
@@ -59,20 +60,20 @@ private:
void getVideoFrameTask();
void onVideoFrameReady(std::optional<FrameWithBlockId> frameWithBlockId);
- // Ask |blockPool| to allocate the specified number of buffers.
- // |bufferCount| is the number of requested buffers.
- static c2_status_t requestNewBufferSet(C2BlockPool& blockPool, int32_t bufferCount,
- const ui::Size& size, uint32_t format,
- C2MemoryUsage usage);
+ // Returns true if a buffer shall not be handed to client.
+ bool shouldDropBuffer(uint32_t bufferId);
static std::optional<uint32_t> getBufferIdFromGraphicBlock(C2BlockPool& blockPool,
const C2Block2D& block);
- // Ask |blockPool| to notify when a block is available via |cb|.
- // Return true if |blockPool| supports notifying buffer available.
- static bool setNotifyBlockAvailableCb(C2BlockPool& blockPool, ::base::OnceClosure cb);
-
std::shared_ptr<C2BlockPool> mBlockPool;
+
+ // Holds the number of maximum amount of buffers that VideoFramePool
+ // should provide to client.
+ size_t mMaxBufferCount;
+ // Contains known buffer ids that are valid for the pool.
+ std::set<uint32_t> mBuffers;
+
const ui::Size mSize;
const HalPixelFormat mPixelFormat;
const C2MemoryUsage mMemoryUsage;
diff --git a/plugin_store/Android.bp b/plugin_store/Android.bp
index 621cbfc..6427512 100644
--- a/plugin_store/Android.bp
+++ b/plugin_store/Android.bp
@@ -16,10 +16,7 @@ cc_library_shared {
],
srcs: [
- "C2VdaBqBlockPool.cpp",
- "C2VdaPooledBlockPool.cpp",
"DmabufHelpers.cpp",
- "H2BGraphicBufferProducer.cpp",
"V4L2PluginStore.cpp",
"VendorAllocatorLoader.cpp",
],
diff --git a/plugin_store/C2VdaBqBlockPool.cpp b/plugin_store/C2VdaBqBlockPool.cpp
deleted file mode 100644
index d53f4a0..0000000
--- a/plugin_store/C2VdaBqBlockPool.cpp
+++ /dev/null
@@ -1,957 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "C2VdaBqBlockPool"
-
-#include <v4l2_codec2/plugin_store/C2VdaBqBlockPool.h>
-
-#include <errno.h>
-#include <string.h>
-
-#include <chrono>
-#include <mutex>
-#include <set>
-#include <sstream>
-#include <thread>
-
-#include <C2AllocatorGralloc.h>
-#include <C2BlockInternal.h>
-#include <C2SurfaceSyncObj.h>
-#include <android/hardware/graphics/bufferqueue/2.0/IProducerListener.h>
-#include <base/callback.h>
-#include <log/log.h>
-#include <ui/BufferQueueDefs.h>
-
-#include <v4l2_codec2/plugin_store/DmabufHelpers.h>
-#include <v4l2_codec2/plugin_store/H2BGraphicBufferProducer.h>
-#include <v4l2_codec2/plugin_store/V4L2AllocatorId.h>
-
-namespace android {
-namespace {
-
-// The wait time for acquire fence in milliseconds. The normal display is 60Hz,
-// which period is 16ms. We choose 2x period as timeout.
-constexpr int kFenceWaitTimeMs = 32;
-
-// The default maximum dequeued buffer count of IGBP. Currently we don't use
-// this value to restrict the count of allocated buffers, so we choose a huge
-// enough value here.
-constexpr int kMaxDequeuedBufferCount = 32u;
-
-} // namespace
-
-using namespace std::chrono_literals;
-
-// Type for IGBP slot index.
-using slot_t = int32_t;
-
-using ::android::BufferQueueDefs::BUFFER_NEEDS_REALLOCATION;
-using ::android::BufferQueueDefs::NUM_BUFFER_SLOTS;
-using ::android::hardware::Return;
-using HProducerListener = ::android::hardware::graphics::bufferqueue::V2_0::IProducerListener;
-
-static c2_status_t asC2Error(status_t err) {
- switch (err) {
- case OK:
- return C2_OK;
- case NO_INIT:
- return C2_NO_INIT;
- case BAD_VALUE:
- return C2_BAD_VALUE;
- case TIMED_OUT:
- return C2_TIMED_OUT;
- case WOULD_BLOCK:
- return C2_BLOCKING;
- case NO_MEMORY:
- return C2_NO_MEMORY;
- }
- return C2_CORRUPTED;
-}
-
-// Convert GraphicBuffer to C2GraphicAllocation and wrap producer id and slot index.
-std::shared_ptr<C2GraphicAllocation> ConvertGraphicBuffer2C2Allocation(
- sp<GraphicBuffer> graphicBuffer, const uint64_t igbpId, const slot_t slot,
- C2Allocator* const allocator) {
- ALOGV("%s(idbpId=0x%" PRIx64 ", slot=%d)", __func__, igbpId, slot);
-
- C2Handle* c2Handle = WrapNativeCodec2GrallocHandle(
- graphicBuffer->handle, graphicBuffer->width, graphicBuffer->height,
- graphicBuffer->format, graphicBuffer->usage, graphicBuffer->stride,
- graphicBuffer->getGenerationNumber(), igbpId, slot);
- if (!c2Handle) {
- ALOGE("WrapNativeCodec2GrallocHandle() failed");
- return nullptr;
- }
-
- std::shared_ptr<C2GraphicAllocation> allocation;
- const auto err = allocator->priorGraphicAllocation(c2Handle, &allocation);
- if (err != C2_OK) {
- ALOGE("C2Allocator::priorGraphicAllocation() failed: %d", err);
- native_handle_close(c2Handle);
- native_handle_delete(c2Handle);
- return nullptr;
- }
-
- return allocation;
-}
-
-// This class is used to notify the listener when a certain event happens.
-class EventNotifier : public virtual android::RefBase {
-public:
- class Listener {
- public:
- virtual ~Listener() = default;
-
- // Called by EventNotifier when a certain event happens.
- virtual void onEventNotified() = 0;
- };
-
- explicit EventNotifier(std::weak_ptr<Listener> listener) : mListener(std::move(listener)) {}
- virtual ~EventNotifier() = default;
-
-protected:
- void notify() {
- ALOGV("%s()", __func__);
- std::shared_ptr<Listener> listener = mListener.lock();
- if (listener) {
- listener->onEventNotified();
- }
- }
-
- std::weak_ptr<Listener> mListener;
-};
-
-// Notifies the listener when the connected IGBP releases buffers.
-class BufferReleasedNotifier : public EventNotifier, public HProducerListener {
-public:
- using EventNotifier::EventNotifier;
- ~BufferReleasedNotifier() override = default;
-
- // HProducerListener implementation
- Return<void> onBuffersReleased(uint32_t count) override {
- ALOGV("%s(%u)", __func__, count);
- if (count > 0) {
- notify();
- }
- return {};
- }
-};
-
-// IGBP expects its user (e.g. C2VdaBqBlockPool) to keep the mapping from dequeued slot index to
-// graphic buffers. Also, C2VdaBqBlockPool guaratees to fetch N fixed set of buffers with buffer
-// identifier. So this class stores the mapping from slot index to buffers and the mapping from
-// buffer unique ID to buffers.
-// This class also implements functionalities for buffer migration when surface switching. Buffers
-// are owned by either component (i.e. local buffers) or CCodec framework (i.e. remote buffers).
-// When switching surface, the ccodec framework migrates remote buffers to the new surfaces. Then
-// C2VdaBqBlockPool migrates local buffers. However, some buffers might be lost during migration.
-// We assume that there are enough buffers migrated to the new surface to continue the playback.
-// After |NUM_BUFFER_SLOTS| amount of buffers are dequeued from new surface, all buffers should
-// be dequeued at least once. Then we treat the missing buffer as lost, and attach these bufers to
-// the new surface.
-class TrackedGraphicBuffers {
-public:
- using value_type = std::tuple<slot_t, unique_id_t, std::shared_ptr<C2GraphicAllocation>>;
-
- TrackedGraphicBuffers() = default;
- ~TrackedGraphicBuffers() = default;
-
- void reset() {
- mSlotId2GraphicBuffer.clear();
- mSlotId2PoolData.clear();
- mAllocationsRegistered.clear();
- mAllocationsToBeMigrated.clear();
- mMigrateLostBufferCounter = 0;
- mGenerationToBeMigrated = 0;
- }
-
- void registerUniqueId(unique_id_t uniqueId, std::shared_ptr<C2GraphicAllocation> allocation) {
- ALOGV("%s(uniqueId=%u)", __func__, uniqueId);
- ALOG_ASSERT(allocation != nullptr);
-
- mAllocationsRegistered[uniqueId] = std::move(allocation);
- }
-
- std::shared_ptr<C2GraphicAllocation> getRegisteredAllocation(unique_id_t uniqueId) {
- const auto iter = mAllocationsRegistered.find(uniqueId);
- ALOG_ASSERT(iter != mAllocationsRegistered.end());
-
- return iter->second;
- }
-
- bool hasUniqueId(unique_id_t uniqueId) const {
- return mAllocationsRegistered.find(uniqueId) != mAllocationsRegistered.end() ||
- mAllocationsToBeMigrated.find(uniqueId) != mAllocationsToBeMigrated.end();
- }
-
- void updateSlotBuffer(slot_t slotId, unique_id_t uniqueId, sp<GraphicBuffer> slotBuffer) {
- ALOGV("%s(slotId=%d)", __func__, slotId);
- ALOG_ASSERT(slotBuffer != nullptr);
-
- mSlotId2GraphicBuffer[slotId] = std::make_pair(uniqueId, std::move(slotBuffer));
- }
-
- std::pair<unique_id_t, sp<GraphicBuffer>> getSlotBuffer(slot_t slotId) const {
- const auto iter = mSlotId2GraphicBuffer.find(slotId);
- ALOG_ASSERT(iter != mSlotId2GraphicBuffer.end());
-
- return iter->second;
- }
-
- bool hasSlotId(slot_t slotId) const {
- return mSlotId2GraphicBuffer.find(slotId) != mSlotId2GraphicBuffer.end();
- }
-
- void updatePoolData(slot_t slotId, std::weak_ptr<C2BufferQueueBlockPoolData> poolData) {
- ALOGV("%s(slotId=%d)", __func__, slotId);
- ALOG_ASSERT(hasSlotId(slotId));
-
- mSlotId2PoolData[slotId] = std::move(poolData);
- }
-
- bool migrateLocalBuffers(H2BGraphicBufferProducer* const producer, uint64_t producerId,
- uint32_t generation, uint64_t usage) {
- ALOGV("%s(producerId=%" PRIx64 ", generation=%u, usage=%" PRIx64 ")", __func__, producerId,
- generation, usage);
-
- mGenerationToBeMigrated = generation;
- mUsageToBeMigrated = usage;
-
- // Move all buffers to mAllocationsToBeMigrated.
- for (auto& pair : mAllocationsRegistered) {
- if (!mAllocationsToBeMigrated.insert(pair).second) {
- ALOGE("%s() duplicated uniqueId=%u", __func__, pair.first);
- return false;
- }
- }
- mAllocationsRegistered.clear();
-
- ALOGV("%s(producerId=%" PRIx64 ", generation=%u, usage=%" PRIx64 ") before %s", __func__,
- producerId, generation, usage, debugString().c_str());
-
- // Migrate local buffers.
- std::map<slot_t, std::pair<unique_id_t, sp<GraphicBuffer>>> newSlotId2GraphicBuffer;
- std::map<slot_t, std::weak_ptr<C2BufferQueueBlockPoolData>> newSlotId2PoolData;
- for (const auto& pair : mSlotId2PoolData) {
- auto oldSlot = pair.first;
- auto poolData = pair.second.lock();
- if (!poolData) {
- continue;
- }
-
- unique_id_t uniqueId;
- sp<GraphicBuffer> slotBuffer;
- std::shared_ptr<C2SurfaceSyncMemory> syncMem;
- std::tie(uniqueId, slotBuffer) = getSlotBuffer(oldSlot);
- slot_t newSlot = poolData->migrate(producer->getBase(), mGenerationToBeMigrated,
- mUsageToBeMigrated, producerId, slotBuffer,
- slotBuffer->getGenerationNumber(),
- syncMem);
- if (newSlot < 0) {
- ALOGW("%s() Failed to migrate local buffer: uniqueId=%u, oldSlot=%d", __func__,
- uniqueId, oldSlot);
- continue;
- }
-
- ALOGV("%s() migrated buffer: uniqueId=%u, oldSlot=%d, newSlot=%d", __func__, uniqueId,
- oldSlot, newSlot);
- newSlotId2GraphicBuffer[newSlot] = std::make_pair(uniqueId, std::move(slotBuffer));
- newSlotId2PoolData[newSlot] = std::move(poolData);
-
- if (!moveBufferToRegistered(uniqueId)) {
- ALOGE("%s() failed to move buffer to registered, uniqueId=%u", __func__, uniqueId);
- return false;
- }
- }
- mSlotId2GraphicBuffer = std::move(newSlotId2GraphicBuffer);
- mSlotId2PoolData = std::move(newSlotId2PoolData);
-
- // Choose a big enough number to ensure all buffer should be dequeued at least once.
- mMigrateLostBufferCounter = NUM_BUFFER_SLOTS;
- ALOGD("%s() migrated %zu local buffers", __func__, mAllocationsRegistered.size());
- return true;
- }
-
- bool needMigrateLostBuffers() const {
- return mMigrateLostBufferCounter == 0 && !mAllocationsToBeMigrated.empty();
- }
-
- status_t migrateLostBuffer(C2Allocator* const allocator,
- H2BGraphicBufferProducer* const producer, const uint64_t producerId,
- slot_t* newSlot) {
- ALOGV("%s() %s", __func__, debugString().c_str());
-
- if (!needMigrateLostBuffers()) {
- return NO_INIT;
- }
-
- auto iter = mAllocationsToBeMigrated.begin();
- const unique_id_t uniqueId = iter->first;
- const C2Handle* c2Handle = iter->second->handle();
-
- // Convert C2GraphicAllocation to GraphicBuffer, and update generation and usage.
- uint32_t width, height, format, stride, igbpSlot, generation;
- uint64_t usage, igbpId;
- _UnwrapNativeCodec2GrallocMetadata(c2Handle, &width, &height, &format, &usage, &stride,
- &generation, &igbpId, &igbpSlot);
- native_handle_t* grallocHandle = UnwrapNativeCodec2GrallocHandle(c2Handle);
- sp<GraphicBuffer> graphicBuffer =
- new GraphicBuffer(grallocHandle, GraphicBuffer::CLONE_HANDLE, width, height, format,
- 1, mUsageToBeMigrated, stride);
- native_handle_delete(grallocHandle);
- if (graphicBuffer->initCheck() != android::NO_ERROR) {
- ALOGE("Failed to create GraphicBuffer: %d", graphicBuffer->initCheck());
- return false;
- }
- graphicBuffer->setGenerationNumber(mGenerationToBeMigrated);
-
- // Attach GraphicBuffer to producer.
- const auto attachStatus = producer->attachBuffer(graphicBuffer, newSlot);
- if (attachStatus == TIMED_OUT || attachStatus == INVALID_OPERATION) {
- ALOGV("%s(): No free slot yet.", __func__);
- return TIMED_OUT;
- }
- if (attachStatus != OK) {
- ALOGE("%s(): Failed to attach buffer to new producer: %d", __func__, attachStatus);
- return attachStatus;
- }
- ALOGD("%s(), migrated lost buffer uniqueId=%u to slot=%d", __func__, uniqueId, *newSlot);
- updateSlotBuffer(*newSlot, uniqueId, graphicBuffer);
-
- // Wrap the new GraphicBuffer to C2GraphicAllocation and register it.
- std::shared_ptr<C2GraphicAllocation> allocation =
- ConvertGraphicBuffer2C2Allocation(graphicBuffer, producerId, *newSlot, allocator);
- if (!allocation) {
- return UNKNOWN_ERROR;
- }
- registerUniqueId(uniqueId, std::move(allocation));
-
- // Note: C2ArcProtectedGraphicAllocator releases the protected buffers if all the
- // corrresponding C2GraphicAllocations are released. To prevent the protected buffer is
- // released and then allocated again, we release the old C2GraphicAllocation after the new
- // one has been created.
- mAllocationsToBeMigrated.erase(iter);
-
- return OK;
- }
-
- void onBufferDequeued(slot_t slotId) {
- ALOGV("%s(slotId=%d)", __func__, slotId);
- unique_id_t uniqueId;
- std::tie(uniqueId, std::ignore) = getSlotBuffer(slotId);
-
- moveBufferToRegistered(uniqueId);
- if (mMigrateLostBufferCounter > 0) {
- --mMigrateLostBufferCounter;
- }
- }
-
- size_t size() const { return mAllocationsRegistered.size() + mAllocationsToBeMigrated.size(); }
-
- std::string debugString() const {
- std::stringstream ss;
- ss << "tracked size: " << size() << std::endl;
- ss << " registered uniqueIds: ";
- for (const auto& pair : mAllocationsRegistered) {
- ss << pair.first << ", ";
- }
- ss << std::endl;
- ss << " to-be-migrated uniqueIds: ";
- for (const auto& pair : mAllocationsToBeMigrated) {
- ss << pair.first << ", ";
- }
- ss << std::endl;
- ss << " Count down for lost buffer migration: " << mMigrateLostBufferCounter;
- return ss.str();
- }
-
-private:
- bool moveBufferToRegistered(unique_id_t uniqueId) {
- ALOGV("%s(uniqueId=%u)", __func__, uniqueId);
- auto iter = mAllocationsToBeMigrated.find(uniqueId);
- if (iter == mAllocationsToBeMigrated.end()) {
- return false;
- }
- if (!mAllocationsRegistered.insert(*iter).second) {
- ALOGE("%s() duplicated uniqueId=%u", __func__, uniqueId);
- return false;
- }
- mAllocationsToBeMigrated.erase(iter);
-
- return true;
- }
-
- // Mapping from IGBP slots to the corresponding graphic buffers.
- std::map<slot_t, std::pair<unique_id_t, sp<GraphicBuffer>>> mSlotId2GraphicBuffer;
-
- // Mapping from IGBP slots to the corresponding pool data.
- std::map<slot_t, std::weak_ptr<C2BufferQueueBlockPoolData>> mSlotId2PoolData;
-
- // Track the buffers registered at the current producer.
- std::map<unique_id_t, std::shared_ptr<C2GraphicAllocation>> mAllocationsRegistered;
-
- // Track the buffers that should be migrated to the current producer.
- std::map<unique_id_t, std::shared_ptr<C2GraphicAllocation>> mAllocationsToBeMigrated;
-
- // The counter for migrating lost buffers. Count down when a buffer is
- // dequeued from IGBP. When it goes to 0, then we treat the remaining
- // buffers at |mAllocationsToBeMigrated| lost, and migrate them to
- // current IGBP.
- size_t mMigrateLostBufferCounter = 0;
-
- // The generation and usage of the current IGBP, used to migrate buffers.
- uint32_t mGenerationToBeMigrated = 0;
- uint64_t mUsageToBeMigrated = 0;
-};
-
-class C2VdaBqBlockPool::Impl : public std::enable_shared_from_this<C2VdaBqBlockPool::Impl>,
- public EventNotifier::Listener {
-public:
- using HGraphicBufferProducer = C2VdaBqBlockPool::HGraphicBufferProducer;
-
- explicit Impl(const std::shared_ptr<C2Allocator>& allocator);
- // TODO: should we detach buffers on producer if any on destructor?
- ~Impl() = default;
-
- // EventNotifier::Listener implementation.
- void onEventNotified() override;
-
- c2_status_t fetchGraphicBlock(uint32_t width, uint32_t height, uint32_t format,
- C2MemoryUsage usage,
- std::shared_ptr<C2GraphicBlock>* block /* nonnull */);
- void setRenderCallback(const C2BufferQueueBlockPool::OnRenderCallback& renderCallback);
- void configureProducer(const sp<HGraphicBufferProducer>& producer);
- c2_status_t requestNewBufferSet(int32_t bufferCount, uint32_t width, uint32_t height,
- uint32_t format, C2MemoryUsage usage);
- bool setNotifyBlockAvailableCb(::base::OnceClosure cb);
- std::optional<unique_id_t> getBufferIdFromGraphicBlock(const C2Block2D& block);
-
-private:
- // Requested buffer formats.
- struct BufferFormat {
- BufferFormat(uint32_t width, uint32_t height, uint32_t pixelFormat,
- C2AndroidMemoryUsage androidUsage)
- : mWidth(width), mHeight(height), mPixelFormat(pixelFormat), mUsage(androidUsage) {}
- BufferFormat() = default;
-
- uint32_t mWidth = 0;
- uint32_t mHeight = 0;
- uint32_t mPixelFormat = 0;
- C2AndroidMemoryUsage mUsage = C2MemoryUsage(0);
- };
-
- status_t getFreeSlotLocked(uint32_t width, uint32_t height, uint32_t format,
- C2MemoryUsage usage, slot_t* slot, sp<Fence>* fence);
-
- // Queries the generation and usage flags from the given producer by dequeuing and requesting a
- // buffer (the buffer is then detached and freed).
- status_t queryGenerationAndUsageLocked(uint32_t width, uint32_t height, uint32_t pixelFormat,
- C2AndroidMemoryUsage androidUsage, uint32_t* generation,
- uint64_t* usage);
-
- // Wait the fence. If any error occurs, cancel the buffer back to the producer.
- status_t waitFence(slot_t slot, sp<Fence> fence);
-
- // Call mProducer's allowAllocation if needed.
- status_t allowAllocation(bool allow);
-
- const std::shared_ptr<C2Allocator> mAllocator;
-
- std::unique_ptr<H2BGraphicBufferProducer> mProducer;
- uint64_t mProducerId = 0;
- bool mAllowAllocation = false;
-
- C2BufferQueueBlockPool::OnRenderCallback mRenderCallback;
-
- // Function mutex to lock at the start of each API function call for protecting the
- // synchronization of all member variables.
- std::mutex mMutex;
-
- TrackedGraphicBuffers mTrackedGraphicBuffers;
-
- // Number of buffers requested on requestNewBufferSet() call.
- size_t mBuffersRequested = 0u;
- // Currently requested buffer formats.
- BufferFormat mBufferFormat;
-
- // Listener for buffer release events.
- sp<EventNotifier> mFetchBufferNotifier;
-
- std::mutex mBufferReleaseMutex;
- // Set to true when the buffer release event is triggered after dequeueing buffer from IGBP
- // times out. Reset when fetching new slot times out, or |mNotifyBlockAvailableCb| is executed.
- bool mBufferReleasedAfterTimedOut GUARDED_BY(mBufferReleaseMutex) = false;
- // The callback to notify the caller the buffer is available.
- ::base::OnceClosure mNotifyBlockAvailableCb GUARDED_BY(mBufferReleaseMutex);
-
- // Set to true if any error occurs at previous configureProducer().
- bool mConfigureProducerError = false;
-};
-
-C2VdaBqBlockPool::Impl::Impl(const std::shared_ptr<C2Allocator>& allocator)
- : mAllocator(allocator) {}
-
-c2_status_t C2VdaBqBlockPool::Impl::fetchGraphicBlock(
- uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
- std::shared_ptr<C2GraphicBlock>* block /* nonnull */) {
- ALOGV("%s(%ux%u)", __func__, width, height);
- std::lock_guard<std::mutex> lock(mMutex);
-
- if (width != mBufferFormat.mWidth || height != mBufferFormat.mHeight ||
- format != mBufferFormat.mPixelFormat || usage.expected != mBufferFormat.mUsage.expected) {
- ALOGE("%s(): buffer format (%ux%u, format=%u, usage=%" PRIx64
- ") is different from requested format (%ux%u, format=%u, usage=%" PRIx64 ")",
- __func__, width, height, format, usage.expected, mBufferFormat.mWidth,
- mBufferFormat.mHeight, mBufferFormat.mPixelFormat, mBufferFormat.mUsage.expected);
- return C2_BAD_VALUE;
- }
- if (mConfigureProducerError || !mProducer) {
- ALOGE("%s(): error occurred at previous configureProducer()", __func__);
- return C2_CORRUPTED;
- }
-
- slot_t slot;
- sp<Fence> fence = new Fence();
- const auto status = getFreeSlotLocked(width, height, format, usage, &slot, &fence);
- if (status != OK) {
- return asC2Error(status);
- }
-
- unique_id_t uniqueId;
- sp<GraphicBuffer> slotBuffer;
- std::tie(uniqueId, slotBuffer) = mTrackedGraphicBuffers.getSlotBuffer(slot);
- ALOGV("%s(): dequeued slot=%d uniqueId=%u", __func__, slot, uniqueId);
-
- if (!mTrackedGraphicBuffers.hasUniqueId(uniqueId)) {
- if (mTrackedGraphicBuffers.size() >= mBuffersRequested) {
- // The dequeued slot has a pre-allocated buffer whose size and format is as same as
- // currently requested (but was not dequeued during allocation cycle). Just detach it to
- // free this slot. And try dequeueBuffer again.
- ALOGD("dequeued a new slot %d but already allocated enough buffers. Detach it.", slot);
-
- if (mProducer->detachBuffer(slot) != OK) {
- return C2_CORRUPTED;
- }
-
- const auto allocationStatus = allowAllocation(false);
- if (allocationStatus != OK) {
- return asC2Error(allocationStatus);
- }
- return C2_TIMED_OUT;
- }
-
- std::shared_ptr<C2GraphicAllocation> allocation =
- ConvertGraphicBuffer2C2Allocation(slotBuffer, mProducerId, slot, mAllocator.get());
- if (!allocation) {
- return C2_CORRUPTED;
- }
- mTrackedGraphicBuffers.registerUniqueId(uniqueId, std::move(allocation));
-
- ALOGV("%s(): mTrackedGraphicBuffers.size=%zu", __func__, mTrackedGraphicBuffers.size());
- if (mTrackedGraphicBuffers.size() == mBuffersRequested) {
- ALOGV("Tracked IGBP slots: %s", mTrackedGraphicBuffers.debugString().c_str());
- // Already allocated enough buffers, set allowAllocation to false to restrict the
- // eligible slots to allocated ones for future dequeue.
- const auto allocationStatus = allowAllocation(false);
- if (allocationStatus != OK) {
- return asC2Error(allocationStatus);
- }
- }
- }
-
- std::shared_ptr<C2SurfaceSyncMemory> syncMem;
- // TODO: the |owner| argument should be set correctly.
- std::shared_ptr<C2GraphicAllocation> allocation =
- mTrackedGraphicBuffers.getRegisteredAllocation(uniqueId);
- auto poolData = std::make_shared<C2BufferQueueBlockPoolData>(
- slotBuffer->getGenerationNumber(), mProducerId, slot, std::make_shared<int>(0),
- mProducer->getBase(), syncMem);
- mTrackedGraphicBuffers.updatePoolData(slot, poolData);
- *block = _C2BlockFactory::CreateGraphicBlock(std::move(allocation), std::move(poolData));
- if (*block == nullptr) {
- ALOGE("failed to create GraphicBlock: no memory");
- return C2_NO_MEMORY;
- }
-
- // Wait for acquire fence at the last point of returning buffer.
- if (fence) {
- const auto fenceStatus = waitFence(slot, fence);
- if (fenceStatus != OK) {
- return asC2Error(fenceStatus);
- }
-
- if (mRenderCallback) {
- nsecs_t signalTime = fence->getSignalTime();
- if (signalTime >= 0 && signalTime < INT64_MAX) {
- mRenderCallback(mProducerId, slot, signalTime);
- } else {
- ALOGV("got fence signal time of %" PRId64 " nsec", signalTime);
- }
- }
- }
-
- return C2_OK;
-}
-
-status_t C2VdaBqBlockPool::Impl::getFreeSlotLocked(uint32_t width, uint32_t height, uint32_t format,
- C2MemoryUsage usage, slot_t* slot,
- sp<Fence>* fence) {
- if (mTrackedGraphicBuffers.needMigrateLostBuffers()) {
- slot_t newSlot;
- if (mTrackedGraphicBuffers.migrateLostBuffer(mAllocator.get(), mProducer.get(), mProducerId,
- &newSlot) == OK) {
- ALOGV("%s(): migrated buffer: slot=%d", __func__, newSlot);
- *slot = newSlot;
- return OK;
- }
- }
-
- // Dequeue a free slot from IGBP.
- ALOGV("%s(): try to dequeue free slot from IGBP.", __func__);
- const auto dequeueStatus = mProducer->dequeueBuffer(width, height, format, usage, slot, fence);
- if (dequeueStatus == TIMED_OUT) {
- std::lock_guard<std::mutex> lock(mBufferReleaseMutex);
- mBufferReleasedAfterTimedOut = false;
- }
- if (dequeueStatus != OK && dequeueStatus != BUFFER_NEEDS_REALLOCATION) {
- return dequeueStatus;
- }
-
- // Call requestBuffer to update GraphicBuffer for the slot and obtain the reference.
- if (!mTrackedGraphicBuffers.hasSlotId(*slot) || dequeueStatus == BUFFER_NEEDS_REALLOCATION) {
- sp<GraphicBuffer> slotBuffer = new GraphicBuffer();
- const auto requestStatus = mProducer->requestBuffer(*slot, &slotBuffer);
- if (requestStatus != OK) {
- mProducer->cancelBuffer(*slot, *fence);
- return requestStatus;
- }
-
- const auto uniqueId = getDmabufId(slotBuffer->handle->data[0]);
- if (!uniqueId) {
- ALOGE("%s(): failed to get uniqueId of GraphicBuffer from slot=%d", __func__, *slot);
- return UNKNOWN_ERROR;
- }
- mTrackedGraphicBuffers.updateSlotBuffer(*slot, *uniqueId, std::move(slotBuffer));
- }
-
- ALOGV("%s(%ux%u): dequeued slot=%d", __func__, mBufferFormat.mWidth, mBufferFormat.mHeight,
- *slot);
- mTrackedGraphicBuffers.onBufferDequeued(*slot);
- return OK;
-}
-
-void C2VdaBqBlockPool::Impl::onEventNotified() {
- ALOGV("%s()", __func__);
- ::base::OnceClosure outputCb;
- {
- std::lock_guard<std::mutex> lock(mBufferReleaseMutex);
-
- mBufferReleasedAfterTimedOut = true;
- if (mNotifyBlockAvailableCb) {
- mBufferReleasedAfterTimedOut = false;
- outputCb = std::move(mNotifyBlockAvailableCb);
- }
- }
-
- // Calling the callback outside the lock to avoid the deadlock.
- if (outputCb) {
- std::move(outputCb).Run();
- }
-}
-
-status_t C2VdaBqBlockPool::Impl::queryGenerationAndUsageLocked(uint32_t width, uint32_t height,
- uint32_t pixelFormat,
- C2AndroidMemoryUsage androidUsage,
- uint32_t* generation,
- uint64_t* usage) {
- ALOGV("%s()", __func__);
-
- sp<Fence> fence = new Fence();
- slot_t slot;
- const auto dequeueStatus =
- mProducer->dequeueBuffer(width, height, pixelFormat, androidUsage, &slot, &fence);
- if (dequeueStatus != OK && dequeueStatus != BUFFER_NEEDS_REALLOCATION) {
- return dequeueStatus;
- }
-
- // Call requestBuffer to allocate buffer for the slot and obtain the reference.
- // Get generation number here.
- sp<GraphicBuffer> slotBuffer = new GraphicBuffer();
- const auto requestStatus = mProducer->requestBuffer(slot, &slotBuffer);
-
- // Detach and delete the temporary buffer.
- const auto detachStatus = mProducer->detachBuffer(slot);
- if (detachStatus != OK) {
- return detachStatus;
- }
-
- // Check requestBuffer return flag.
- if (requestStatus != OK) {
- return requestStatus;
- }
-
- // Get generation number and usage from the slot buffer.
- *usage = slotBuffer->getUsage();
- *generation = slotBuffer->getGenerationNumber();
- ALOGV("Obtained from temp buffer: generation = %u, usage = %" PRIu64 "", *generation, *usage);
- return OK;
-}
-
-status_t C2VdaBqBlockPool::Impl::waitFence(slot_t slot, sp<Fence> fence) {
- const auto fenceStatus = fence->wait(kFenceWaitTimeMs);
- if (fenceStatus == OK) {
- return OK;
- }
-
- const auto cancelStatus = mProducer->cancelBuffer(slot, fence);
- if (cancelStatus != OK) {
- ALOGE("%s(): failed to cancelBuffer(slot=%d)", __func__, slot);
- return cancelStatus;
- }
-
- if (fenceStatus == -ETIME) { // fence wait timed out
- ALOGV("%s(): buffer (slot=%d) fence wait timed out", __func__, slot);
- return TIMED_OUT;
- }
- ALOGE("buffer fence wait error: %d", fenceStatus);
- return fenceStatus;
-}
-
-void C2VdaBqBlockPool::Impl::setRenderCallback(
- const C2BufferQueueBlockPool::OnRenderCallback& renderCallback) {
- ALOGV("setRenderCallback");
- std::lock_guard<std::mutex> lock(mMutex);
- mRenderCallback = renderCallback;
-}
-
-c2_status_t C2VdaBqBlockPool::Impl::requestNewBufferSet(int32_t bufferCount, uint32_t width,
- uint32_t height, uint32_t format,
- C2MemoryUsage usage) {
- ALOGV("%s(bufferCount=%d, size=%ux%u, format=0x%x, usage=%" PRIu64 ")", __func__, bufferCount,
- width, height, format, usage.expected);
-
- if (bufferCount <= 0) {
- ALOGE("Invalid requested buffer count = %d", bufferCount);
- return C2_BAD_VALUE;
- }
-
- std::lock_guard<std::mutex> lock(mMutex);
- if (!mProducer) {
- ALOGD("No HGraphicBufferProducer is configured...");
- return C2_NO_INIT;
- }
- if (mBuffersRequested == static_cast<size_t>(bufferCount) && mBufferFormat.mWidth == width &&
- mBufferFormat.mHeight == height && mBufferFormat.mPixelFormat == format &&
- mBufferFormat.mUsage.expected == usage.expected) {
- ALOGD("%s() Request the same format and amount of buffers, skip", __func__);
- return C2_OK;
- }
-
- const auto status = allowAllocation(true);
- if (status != OK) {
- return asC2Error(status);
- }
-
- // Release all remained slot buffer references here. CCodec should either cancel or queue its
- // owned buffers from this set before the next resolution change.
- mTrackedGraphicBuffers.reset();
-
- mBuffersRequested = static_cast<size_t>(bufferCount);
-
- // Store buffer formats for future usage.
- mBufferFormat = BufferFormat(width, height, format, C2AndroidMemoryUsage(usage));
-
- return C2_OK;
-}
-
-void C2VdaBqBlockPool::Impl::configureProducer(const sp<HGraphicBufferProducer>& producer) {
- ALOGV("%s(producer=%p)", __func__, producer.get());
-
- std::lock_guard<std::mutex> lock(mMutex);
- if (producer == nullptr) {
- ALOGI("input producer is nullptr...");
-
- mProducer = nullptr;
- mProducerId = 0;
- mTrackedGraphicBuffers.reset();
- return;
- }
-
- auto newProducer = std::make_unique<H2BGraphicBufferProducer>(producer);
- uint64_t newProducerId;
- if (newProducer->getUniqueId(&newProducerId) != OK) {
- ALOGE("%s(): failed to get IGBP ID", __func__);
- mConfigureProducerError = true;
- return;
- }
- if (newProducerId == mProducerId) {
- ALOGI("%s(): configure the same producer, ignore", __func__);
- return;
- }
-
- ALOGI("Producer (Surface) is going to switch... ( 0x%" PRIx64 " -> 0x%" PRIx64 " )",
- mProducerId, newProducerId);
- mProducer = std::move(newProducer);
- mProducerId = newProducerId;
- mConfigureProducerError = false;
- mAllowAllocation = false;
-
- // Set allowAllocation to new producer.
- if (allowAllocation(true) != OK) {
- ALOGE("%s(): failed to allowAllocation(true)", __func__);
- mConfigureProducerError = true;
- return;
- }
- if (mProducer->setDequeueTimeout(0) != OK) {
- ALOGE("%s(): failed to setDequeueTimeout(0)", __func__);
- mConfigureProducerError = true;
- return;
- }
- if (mProducer->setMaxDequeuedBufferCount(kMaxDequeuedBufferCount) != OK) {
- ALOGE("%s(): failed to setMaxDequeuedBufferCount(%d)", __func__, kMaxDequeuedBufferCount);
- mConfigureProducerError = true;
- return;
- }
-
- // Migrate existing buffers to the new producer.
- if (mTrackedGraphicBuffers.size() > 0) {
- uint32_t newGeneration = 0;
- uint64_t newUsage = 0;
- const status_t err = queryGenerationAndUsageLocked(
- mBufferFormat.mWidth, mBufferFormat.mHeight, mBufferFormat.mPixelFormat,
- mBufferFormat.mUsage, &newGeneration, &newUsage);
- if (err != OK) {
- ALOGE("failed to query generation and usage: %d", err);
- mConfigureProducerError = true;
- return;
- }
-
- if (!mTrackedGraphicBuffers.migrateLocalBuffers(mProducer.get(), mProducerId, newGeneration,
- newUsage)) {
- ALOGE("%s(): failed to migrateLocalBuffers()", __func__);
- mConfigureProducerError = true;
- return;
- }
-
- if (mTrackedGraphicBuffers.size() == mBuffersRequested) {
- if (allowAllocation(false) != OK) {
- ALOGE("%s(): failed to allowAllocation(false)", __func__);
- mConfigureProducerError = true;
- return;
- }
- }
- }
-
- // hack(b/146409777): Try to connect ARC-specific listener first.
- sp<BufferReleasedNotifier> listener = new BufferReleasedNotifier(weak_from_this());
- if (mProducer->connect(listener, 'ARC\0', false) == OK) {
- ALOGI("connected to ARC-specific IGBP listener.");
- mFetchBufferNotifier = listener;
- }
-
- // There might be free buffers at the new producer, notify the client if needed.
- onEventNotified();
-}
-
-bool C2VdaBqBlockPool::Impl::setNotifyBlockAvailableCb(::base::OnceClosure cb) {
- ALOGV("%s()", __func__);
- if (mFetchBufferNotifier == nullptr) {
- return false;
- }
-
- ::base::OnceClosure outputCb;
- {
- std::lock_guard<std::mutex> lock(mBufferReleaseMutex);
-
- // If there is any buffer released after dequeueBuffer() timed out, then we could notify the
- // caller directly.
- if (mBufferReleasedAfterTimedOut) {
- mBufferReleasedAfterTimedOut = false;
- outputCb = std::move(cb);
- } else {
- mNotifyBlockAvailableCb = std::move(cb);
- }
- }
-
- // Calling the callback outside the lock to avoid the deadlock.
- if (outputCb) {
- std::move(outputCb).Run();
- }
- return true;
-}
-
-std::optional<unique_id_t> C2VdaBqBlockPool::Impl::getBufferIdFromGraphicBlock(
- const C2Block2D& block) {
- return getDmabufId(block.handle()->data[0]);
-}
-
-status_t C2VdaBqBlockPool::Impl::allowAllocation(bool allow) {
- ALOGV("%s(%d)", __func__, allow);
-
- if (!mProducer) {
- ALOGW("%s() mProducer is not initiailzed", __func__);
- return NO_INIT;
- }
- if (mAllowAllocation == allow) {
- return OK;
- }
-
- const auto status = mProducer->allowAllocation(allow);
- if (status == OK) {
- mAllowAllocation = allow;
- }
- return status;
-}
-
-C2VdaBqBlockPool::C2VdaBqBlockPool(const std::shared_ptr<C2Allocator>& allocator,
- const local_id_t localId)
- : C2BufferQueueBlockPool(allocator, localId), mLocalId(localId), mImpl(new Impl(allocator)) {}
-
-c2_status_t C2VdaBqBlockPool::fetchGraphicBlock(
- uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
- std::shared_ptr<C2GraphicBlock>* block /* nonnull */) {
- if (mImpl) {
- return mImpl->fetchGraphicBlock(width, height, format, usage, block);
- }
- return C2_NO_INIT;
-}
-
-void C2VdaBqBlockPool::setRenderCallback(
- const C2BufferQueueBlockPool::OnRenderCallback& renderCallback) {
- if (mImpl) {
- mImpl->setRenderCallback(renderCallback);
- }
-}
-
-c2_status_t C2VdaBqBlockPool::requestNewBufferSet(int32_t bufferCount, uint32_t width,
- uint32_t height, uint32_t format,
- C2MemoryUsage usage) {
- if (mImpl) {
- return mImpl->requestNewBufferSet(bufferCount, width, height, format, usage);
- }
- return C2_NO_INIT;
-}
-
-void C2VdaBqBlockPool::configureProducer(const sp<HGraphicBufferProducer>& producer) {
- if (mImpl) {
- mImpl->configureProducer(producer);
- }
-}
-
-bool C2VdaBqBlockPool::setNotifyBlockAvailableCb(::base::OnceClosure cb) {
- if (mImpl) {
- return mImpl->setNotifyBlockAvailableCb(std::move(cb));
- }
- return false;
-}
-
-std::optional<unique_id_t> C2VdaBqBlockPool::getBufferIdFromGraphicBlock(const C2Block2D& block) {
- if (mImpl) {
- return mImpl->getBufferIdFromGraphicBlock(block);
- }
- return std::nullopt;
-}
-
-} // namespace android
diff --git a/plugin_store/C2VdaPooledBlockPool.cpp b/plugin_store/C2VdaPooledBlockPool.cpp
deleted file mode 100644
index 2b9104b..0000000
--- a/plugin_store/C2VdaPooledBlockPool.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "C2VdaPooledBlockPool"
-
-#include <v4l2_codec2/plugin_store/C2VdaPooledBlockPool.h>
-
-#include <time.h>
-
-#include <C2BlockInternal.h>
-#include <bufferpool/BufferPoolTypes.h>
-#include <log/log.h>
-
-namespace android {
-
-using android::hardware::media::bufferpool::BufferPoolData;
-
-// static
-std::optional<uint32_t> C2VdaPooledBlockPool::getBufferIdFromGraphicBlock(const C2Block2D& block) {
- std::shared_ptr<_C2BlockPoolData> blockPoolData =
- _C2BlockFactory::GetGraphicBlockPoolData(block);
- if (blockPoolData->getType() != _C2BlockPoolData::TYPE_BUFFERPOOL) {
- ALOGE("Obtained C2GraphicBlock is not bufferpool-backed.");
- return std::nullopt;
- }
- std::shared_ptr<BufferPoolData> bpData;
- if (!_C2BlockFactory::GetBufferPoolData(blockPoolData, &bpData) || !bpData) {
- ALOGE("BufferPoolData unavailable in block.");
- return std::nullopt;
- }
- return bpData->mId;
-}
-
-// Tries to fetch a buffer from bufferpool. When the size of |mBufferIds| is smaller than
-// |mBufferCount|, pass the obtained buffer to caller and record its ID in BufferPoolData to
-// |mBufferIds|. When the size of |mBufferIds| is equal to |mBufferCount|, pass the obtained
-// buffer only if its ID is included in |mBufferIds|. Otherwise, discard the buffer and
-// return C2_TIMED_OUT.
-c2_status_t C2VdaPooledBlockPool::fetchGraphicBlock(uint32_t width, uint32_t height,
- uint32_t format, C2MemoryUsage usage,
- std::shared_ptr<C2GraphicBlock>* block) {
- ALOG_ASSERT(block != nullptr);
- std::lock_guard<std::mutex> lock(mMutex);
-
- std::shared_ptr<C2GraphicBlock> fetchBlock;
- c2_status_t err =
- C2PooledBlockPool::fetchGraphicBlock(width, height, format, usage, &fetchBlock);
- if (err != C2_OK) {
- ALOGE("Failed at C2PooledBlockPool::fetchGraphicBlock: %d", err);
- return err;
- }
-
- std::optional<uint32_t> bufferId = getBufferIdFromGraphicBlock(*fetchBlock);
- if (!bufferId) {
- ALOGE("Failed to getBufferIdFromGraphicBlock");
- return C2_CORRUPTED;
- }
-
- if (mBufferIds.size() < mBufferCount) {
- mBufferIds.insert(*bufferId);
- }
-
- if (mBufferIds.find(*bufferId) != mBufferIds.end()) {
- ALOGV("Returned buffer id = %u", *bufferId);
- *block = std::move(fetchBlock);
- return C2_OK;
- }
- ALOGV("No buffer could be recycled now, wait for another try...");
- return C2_TIMED_OUT;
-}
-
-c2_status_t C2VdaPooledBlockPool::requestNewBufferSet(int32_t bufferCount) {
- if (bufferCount <= 0) {
- ALOGE("Invalid requested buffer count = %d", bufferCount);
- return C2_BAD_VALUE;
- }
-
- std::lock_guard<std::mutex> lock(mMutex);
- mBufferIds.clear();
- mBufferCount = bufferCount;
- return C2_OK;
-}
-
-} // namespace android
diff --git a/plugin_store/H2BGraphicBufferProducer.cpp b/plugin_store/H2BGraphicBufferProducer.cpp
deleted file mode 100644
index 95251de..0000000
--- a/plugin_store/H2BGraphicBufferProducer.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "H2BGraphicBuferProducer"
-
-#include <v4l2_codec2/plugin_store/H2BGraphicBufferProducer.h>
-
-#include <log/log.h>
-#include <types.h>
-#include <ui/BufferQueueDefs.h>
-
-namespace android {
-
-using ::android::BufferQueueDefs::BUFFER_NEEDS_REALLOCATION;
-using ::android::BufferQueueDefs::RELEASE_ALL_BUFFERS;
-using ::android::hardware::Return;
-
-using HBuffer = ::android::hardware::graphics::common::V1_2::HardwareBuffer;
-using HStatus = ::android::hardware::graphics::bufferqueue::V2_0::Status;
-using HConnectionType = hardware::graphics::bufferqueue::V2_0::ConnectionType;
-using HQueueBufferOutput =
- ::android::hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer::QueueBufferOutput;
-
-using ::android::hardware::graphics::bufferqueue::V2_0::utils::b2h;
-using ::android::hardware::graphics::bufferqueue::V2_0::utils::h2b;
-using ::android::hardware::graphics::bufferqueue::V2_0::utils::HFenceWrapper;
-
-H2BGraphicBufferProducer::H2BGraphicBufferProducer(sp<HGraphicBufferProducer> base) : mBase(base) {}
-
-status_t H2BGraphicBufferProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
- bool converted = false;
- status_t status = UNKNOWN_ERROR;
- Return<void> transResult = mBase->requestBuffer(
- slot, [&converted, &status, buf](HStatus hStatus, HBuffer const& hBuffer,
- uint32_t generationNumber) {
- converted = h2b(hStatus, &status) && h2b(hBuffer, buf);
- if (*buf) {
- (*buf)->setGenerationNumber(generationNumber);
- }
- });
-
- if (!transResult.isOk()) {
- ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
- return FAILED_TRANSACTION;
- }
- if (!converted) {
- ALOGE("%s(): corrupted transaction.", __func__);
- return FAILED_TRANSACTION;
- }
- if (status != OK) {
- ALOGD("%s() failed: %d", __func__, status);
- }
- return status;
-}
-
-status_t H2BGraphicBufferProducer::setMaxDequeuedBufferCount(int maxDequeuedBuffers) {
- status_t status = UNKNOWN_ERROR;
- Return<HStatus> transResult =
- mBase->setMaxDequeuedBufferCount(static_cast<int32_t>(maxDequeuedBuffers));
-
- if (!transResult.isOk()) {
- ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
- return FAILED_TRANSACTION;
- }
- if (!h2b(static_cast<HStatus>(transResult), &status)) {
- ALOGE("%s(): corrupted transaction.", __func__);
- return FAILED_TRANSACTION;
- }
- if (status != OK) {
- ALOGD("%s() failed: %d", __func__, status);
- }
- return status;
-}
-
-status_t H2BGraphicBufferProducer::dequeueBuffer(uint32_t width, uint32_t height,
- uint32_t pixelFormat,
- C2AndroidMemoryUsage androidUsage, int* slot,
- sp<Fence>* fence) {
- using Input = HGraphicBufferProducer::DequeueBufferInput;
- using Output = HGraphicBufferProducer::DequeueBufferOutput;
- Input input{width, height, pixelFormat, androidUsage.asGrallocUsage()};
-
- bool converted = false;
- status_t status = UNKNOWN_ERROR;
- Return<void> transResult = mBase->dequeueBuffer(
- input, [&converted, &status, &slot, &fence](HStatus hStatus, int32_t hSlot,
- Output const& hOutput) {
- converted = h2b(hStatus, &status);
- if (!converted || status != OK) {
- return;
- }
-
- *slot = hSlot;
- if (hOutput.bufferNeedsReallocation) {
- status = BUFFER_NEEDS_REALLOCATION;
- }
- converted = h2b(hOutput.fence, fence);
- });
-
- if (!transResult.isOk()) {
- ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
- return FAILED_TRANSACTION;
- }
- if (!converted) {
- ALOGE("%s(): corrupted transaction.", __func__);
- return FAILED_TRANSACTION;
- }
- // The C2VdaBqBlockPool does not fully own the bufferqueue. After buffers are dequeued here,
- // they are passed into the codec2 framework, processed, and eventually queued into the
- // bufferqueue. The C2VdaBqBlockPool cannot determine exactly when a buffer gets queued.
- // However, if every buffer is being processed by the codec2 framework, then dequeueBuffer()
- // will return INVALID_OPERATION because of an attempt to dequeue too many buffers.
- // The C2VdaBqBlockPool cannot prevent this from happening, so just map it to TIMED_OUT
- // and let the C2VdaBqBlockPool's caller's timeout retry logic handle the failure.
- if (status == INVALID_OPERATION) {
- status = TIMED_OUT;
- }
- if (status != OK && status != BUFFER_NEEDS_REALLOCATION && status != TIMED_OUT) {
- ALOGD("%s() failed: %d", __func__, status);
- }
- return status;
-}
-
-status_t H2BGraphicBufferProducer::detachBuffer(int slot) {
- status_t status = UNKNOWN_ERROR;
- Return<HStatus> transResult = mBase->detachBuffer(static_cast<int32_t>(slot));
-
- if (!transResult.isOk()) {
- ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
- return FAILED_TRANSACTION;
- }
- if (!h2b(static_cast<HStatus>(transResult), &status)) {
- ALOGE("%s(): corrupted transaction.", __func__);
- return FAILED_TRANSACTION;
- }
- if (status != OK) {
- ALOGD("%s() failed: %d", __func__, status);
- }
- return status;
-}
-
-status_t H2BGraphicBufferProducer::attachBuffer(const sp<GraphicBuffer>& buffer, int* outSlot) {
- HBuffer hBuffer;
- uint32_t hGenerationNumber;
- if (!b2h(buffer, &hBuffer, &hGenerationNumber)) {
- ALOGE("%s: invalid input buffer.", __func__);
- return BAD_VALUE;
- }
-
- bool converted = false;
- status_t status = UNKNOWN_ERROR;
- Return<void> transResult = mBase->attachBuffer(
- hBuffer, hGenerationNumber,
- [&converted, &status, outSlot](HStatus hStatus, int32_t hSlot, bool releaseAllBuffers) {
- converted = h2b(hStatus, &status);
- *outSlot = static_cast<int>(hSlot);
- if (converted && releaseAllBuffers && status == OK) {
- status = RELEASE_ALL_BUFFERS;
- }
- });
-
- if (!transResult.isOk()) {
- ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
- return FAILED_TRANSACTION;
- }
- if (!converted) {
- ALOGE("%s(): corrupted transaction.", __func__);
- return FAILED_TRANSACTION;
- }
- if (status != OK) {
- ALOGD("%s() failed: %d", __func__, status);
- }
- return status;
-}
-
-status_t H2BGraphicBufferProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
- HFenceWrapper hFenceWrapper;
- if (!b2h(fence, &hFenceWrapper)) {
- ALOGE("%s(): corrupted input fence.", __func__);
- return UNKNOWN_ERROR;
- }
-
- status_t status = UNKNOWN_ERROR;
- Return<HStatus> transResult =
- mBase->cancelBuffer(static_cast<int32_t>(slot), hFenceWrapper.getHandle());
-
- if (!transResult.isOk()) {
- ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
- return FAILED_TRANSACTION;
- }
- if (!h2b(static_cast<HStatus>(transResult), &status)) {
- ALOGE("%s(): corrupted transaction.", __func__);
- return FAILED_TRANSACTION;
- }
- if (status != OK) {
- ALOGD("%s() failed: %d", __func__, status);
- }
- return status;
-}
-
-int H2BGraphicBufferProducer::query(int what, int* value) {
- int result = 0;
- Return<void> transResult =
- mBase->query(static_cast<int32_t>(what), [&result, value](int32_t r, int32_t v) {
- result = static_cast<int>(r);
- *value = static_cast<int>(v);
- });
-
- if (!transResult.isOk()) {
- ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
- return FAILED_TRANSACTION;
- }
- return result;
-}
-
-status_t H2BGraphicBufferProducer::allowAllocation(bool allow) {
- status_t status = UNKNOWN_ERROR;
- Return<HStatus> transResult = mBase->allowAllocation(allow);
-
- if (!transResult.isOk()) {
- ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
- return FAILED_TRANSACTION;
- }
- if (!h2b(static_cast<HStatus>(transResult), &status)) {
- ALOGE("%s(): corrupted transaction.", __func__);
- return FAILED_TRANSACTION;
- }
- if (status != OK) {
- ALOGD("%s() failed: %d", __func__, status);
- }
- return status;
-}
-
-status_t H2BGraphicBufferProducer::getUniqueId(uint64_t* outId) const {
- Return<uint64_t> transResult = mBase->getUniqueId();
-
- if (!transResult.isOk()) {
- ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
- return FAILED_TRANSACTION;
- }
-
- *outId = static_cast<uint64_t>(transResult);
- return OK;
-}
-
-// android::IProducerListener cannot be depended by vendor library, so we use HProducerListener
-// directly.
-status_t H2BGraphicBufferProducer::connect(sp<HProducerListener> const& hListener, int32_t api,
- bool producerControlledByApp) {
- bool converted = false;
- status_t status = UNKNOWN_ERROR;
- // hack(b/146409777): We pass self-defined api, so we don't use b2h() here.
- Return<void> transResult = mBase->connect(
- hListener, static_cast<HConnectionType>(api), producerControlledByApp,
- [&converted, &status](HStatus hStatus, HQueueBufferOutput const& /* hOutput */) {
- converted = h2b(hStatus, &status);
- });
-
- if (!transResult.isOk()) {
- ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
- return FAILED_TRANSACTION;
- }
- if (!converted) {
- ALOGE("%s(): corrupted transaction.", __func__);
- return FAILED_TRANSACTION;
- }
- return status;
-}
-
-status_t H2BGraphicBufferProducer::setDequeueTimeout(nsecs_t timeout) {
- status_t status = UNKNOWN_ERROR;
- Return<HStatus> transResult = mBase->setDequeueTimeout(static_cast<int64_t>(timeout));
-
- if (!transResult.isOk()) {
- ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
- return FAILED_TRANSACTION;
- }
- if (!h2b(static_cast<HStatus>(transResult), &status)) {
- ALOGE("%s(): corrupted transaction.", __func__);
- return FAILED_TRANSACTION;
- }
- return status;
-}
-
-} // namespace android
diff --git a/plugin_store/V4L2PluginStore.cpp b/plugin_store/V4L2PluginStore.cpp
index 2d53c5f..9f9f262 100644
--- a/plugin_store/V4L2PluginStore.cpp
+++ b/plugin_store/V4L2PluginStore.cpp
@@ -12,11 +12,10 @@
#include <mutex>
#include <C2AllocatorGralloc.h>
+#include <C2BqBufferPriv.h>
#include <C2BufferPriv.h>
#include <log/log.h>
-#include <v4l2_codec2/plugin_store/C2VdaBqBlockPool.h>
-#include <v4l2_codec2/plugin_store/C2VdaPooledBlockPool.h>
#include <v4l2_codec2/plugin_store/V4L2AllocatorId.h>
#include <v4l2_codec2/plugin_store/VendorAllocatorLoader.h>
@@ -67,17 +66,11 @@ C2BlockPool* createBlockPool(C2Allocator::id_t allocatorId, C2BlockPool::local_i
}
switch (allocatorId) {
- case V4L2AllocatorId::V4L2_BUFFERPOOL:
- return new C2VdaPooledBlockPool(allocator, poolId);
-
- case V4L2AllocatorId::V4L2_BUFFERQUEUE:
- return new C2VdaBqBlockPool(allocator, poolId);
-
case V4L2AllocatorId::SECURE_LINEAR:
return new C2PooledBlockPool(allocator, poolId);
case V4L2AllocatorId::SECURE_GRAPHIC:
- return new C2VdaBqBlockPool(allocator, poolId);
+ return new C2BufferQueueBlockPool(allocator, poolId);
default:
ALOGE("%s(): Unknown allocator id=%u", __func__, allocatorId);
diff --git a/plugin_store/include/v4l2_codec2/plugin_store/C2VdaBqBlockPool.h b/plugin_store/include/v4l2_codec2/plugin_store/C2VdaBqBlockPool.h
deleted file mode 100644
index fde6299..0000000
--- a/plugin_store/include/v4l2_codec2/plugin_store/C2VdaBqBlockPool.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ANDROID_V4L2_CODEC2_PLUGIN_STORE_C2_VDA_BQ_BLOCK_POOL_H
-#define ANDROID_V4L2_CODEC2_PLUGIN_STORE_C2_VDA_BQ_BLOCK_POOL_H
-
-#include <functional>
-#include <map>
-#include <optional>
-
-#include <C2BqBufferPriv.h>
-#include <C2Buffer.h>
-#include <C2PlatformSupport.h>
-#include <base/callback_forward.h>
-
-namespace android {
-
-/**
- * The BufferQueue-backed block pool design which supports to request arbitrary count of graphic
- * buffers from IGBP, and use this buffer set among codec component and client.
- *
- * The block pool should restore the mapping table between slot indices and GraphicBuffer (or
- * C2GraphicAllocation). When component requests a new buffer, the block pool calls dequeueBuffer
- * to IGBP to obtain a valid slot index, and returns the corresponding buffer from map.
- */
-class C2VdaBqBlockPool : public C2BufferQueueBlockPool {
-public:
- C2VdaBqBlockPool(const std::shared_ptr<C2Allocator>& allocator, const local_id_t localId);
-
- ~C2VdaBqBlockPool() override = default;
-
- /**
- * It's a trick here. Return C2PlatformAllocatorStore::BUFFERQUEUE instead of the ID of backing
- * allocator for client's query. It's because in platform side this ID is recognized as
- * BufferQueue-backed block pool which is only allowed to set surface.
- */
- C2Allocator::id_t getAllocatorId() const override {
- return android::C2PlatformAllocatorStore::BUFFERQUEUE;
- };
-
- local_id_t getLocalId() const override { return mLocalId; };
-
- /**
- * Tries to dequeue a buffer from producer. If the producer is allowed allocation now, call
- * requestBuffer of dequeued slot for allocating new buffer and storing the reference into
- * |mSlotAllocations|.
- *
- * When the size of |mSlotAllocations| reaches the requested buffer count, set disallow
- * allocation to producer. After that buffer set is started to be recycled by dequeue.
- *
- * \retval C2_BAD_STATE informs the caller producer is switched.
- */
- c2_status_t fetchGraphicBlock(uint32_t width, uint32_t height, uint32_t format,
- C2MemoryUsage usage,
- std::shared_ptr<C2GraphicBlock>* block /* nonnull */) override;
-
- void setRenderCallback(const C2BufferQueueBlockPool::OnRenderCallback& renderCallback =
- C2BufferQueueBlockPool::OnRenderCallback()) override;
- void configureProducer(const android::sp<HGraphicBufferProducer>& producer) override;
-
- /**
- * Sends the request of arbitrary number of graphic buffers allocation. If producer is given,
- * it will set maxDequeuedBufferCount with regard to the requested buffer count and allow
- * allocation to producer.
- *
- * \note C2VdaBqBlockPool-specific function
- * \note caller should release all buffer references obtained from fetchGraphicBlock() before
- * calling this function.
- *
- * \param bufferCount the number of requested buffers
- *
- * \retval C2_OK the operation was successful.
- * \retval C2_NO_INIT this class is not initialized, or producer is not assigned.
- * \retval C2_BAD_VALUE |bufferCount| is not greater than zero.
- * \retval C2_CORRUPTED some unknown, unrecoverable error occured during operation (unexpected).
- */
- c2_status_t requestNewBufferSet(int32_t bufferCount, uint32_t width, uint32_t height,
- uint32_t format, C2MemoryUsage usage);
-
- /**
- * Set the callback that will be triggered when there is block available.
- *
- * \note C2VdaBqBlockPool-specific function
- *
- * \param cb the callback function that will be triggered when there is block available.
- *
- * Return false if we don't support to notify the caller when a buffer is available.
- *
- */
- bool setNotifyBlockAvailableCb(base::OnceClosure cb);
-
- std::optional<uint32_t> getBufferIdFromGraphicBlock(const C2Block2D& block);
-
-private:
- friend struct C2VdaBqBlockPoolData;
- class Impl;
-
- const local_id_t mLocalId;
- std::shared_ptr<Impl> mImpl;
-};
-
-} // namespace android
-#endif // ANDROID_V4L2_CODEC2_PLUGIN_STORE_C2_VDA_BQ_BLOCK_POOL_H
diff --git a/plugin_store/include/v4l2_codec2/plugin_store/C2VdaPooledBlockPool.h b/plugin_store/include/v4l2_codec2/plugin_store/C2VdaPooledBlockPool.h
deleted file mode 100644
index 749ff47..0000000
--- a/plugin_store/include/v4l2_codec2/plugin_store/C2VdaPooledBlockPool.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ANDROID_V4L2_CODEC2_PLUGIN_STORE_C2_VDA_POOLED_BLOCK_POOL_H
-#define ANDROID_V4L2_CODEC2_PLUGIN_STORE_C2_VDA_POOLED_BLOCK_POOL_H
-
-#include <memory>
-#include <mutex>
-#include <optional>
-#include <set>
-
-#include <C2Buffer.h>
-#include <C2BufferPriv.h>
-#include <C2PlatformSupport.h>
-#include <android-base/thread_annotations.h>
-
-namespace android {
-
-class C2VdaPooledBlockPool : public C2PooledBlockPool {
-public:
- using C2PooledBlockPool::C2PooledBlockPool;
- ~C2VdaPooledBlockPool() override = default;
-
- // Extracts the buffer ID from BufferPoolData of the graphic block.
- // |block| is the graphic block allocated by bufferpool block pool.
- static std::optional<uint32_t> getBufferIdFromGraphicBlock(const C2Block2D& block);
-
- // Allocate the specified number of buffers.
- // |bufferCount| is the number of requested buffers.
- c2_status_t requestNewBufferSet(int32_t bufferCount);
-
- // Return C2_OK and store a buffer in |block| if a buffer is successfully fetched.
- // Return C2_TIMED_OUT if the pool already allocated |mBufferCount| buffers but they are all in
- // use.
- // Return C2_NO_MEMORY if the pool fails to allocate a new buffer.
- c2_status_t fetchGraphicBlock(uint32_t width, uint32_t height, uint32_t format,
- C2MemoryUsage usage,
- std::shared_ptr<C2GraphicBlock>* block /* nonnull */) override;
-
-private:
- // Function mutex to lock at the start of each API function call for protecting the
- // synchronization of all member variables.
- std::mutex mMutex;
-
- // The ids of all allocated buffers.
- std::set<uint32_t> mBufferIds GUARDED_BY(mMutex);
- // The maximum count of allocated buffers.
- size_t mBufferCount GUARDED_BY(mMutex){0};
-};
-
-} // namespace android
-#endif // ANDROID_V4L2_CODEC2_PLUGIN_STORE_C2_VDA_POOLED_BLOCK_POOL_H
diff --git a/plugin_store/include/v4l2_codec2/plugin_store/H2BGraphicBufferProducer.h b/plugin_store/include/v4l2_codec2/plugin_store/H2BGraphicBufferProducer.h
deleted file mode 100644
index 11185bb..0000000
--- a/plugin_store/include/v4l2_codec2/plugin_store/H2BGraphicBufferProducer.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ANDROID_V4L2_CODEC2_PLUGIN_STORE_H2B_GRAPHIC_BUFFER_PRODUCER_H
-#define ANDROID_V4L2_CODEC2_PLUGIN_STORE_H2B_GRAPHIC_BUFFER_PRODUCER_H
-
-#include <C2Buffer.h>
-#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
-#include <android/hardware/graphics/bufferqueue/2.0/IProducerListener.h>
-#include <ui/Fence.h>
-#include <ui/GraphicBuffer.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-
-class H2BGraphicBufferProducer {
-public:
- using HGraphicBufferProducer =
- ::android::hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer;
- using HProducerListener = ::android::hardware::graphics::bufferqueue::V2_0::IProducerListener;
-
- explicit H2BGraphicBufferProducer(sp<HGraphicBufferProducer> base);
- ~H2BGraphicBufferProducer() = default;
-
- // Convert HIDL interface of IGraphicBufferProducer.
- status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
- status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
- status_t dequeueBuffer(uint32_t width, uint32_t height, uint32_t pixelFormat,
- C2AndroidMemoryUsage androidUsage, int* slot, sp<Fence>* fence);
- status_t detachBuffer(int slot);
- status_t attachBuffer(const sp<GraphicBuffer>& buffer, int* outSlot);
- status_t cancelBuffer(int slot, const sp<Fence>& fence);
- int query(int what, int* value);
- status_t allowAllocation(bool allow);
- status_t getUniqueId(uint64_t* outId) const;
- status_t connect(sp<HProducerListener> const& hListener, int32_t api,
- bool producerControlledByApp);
- status_t setDequeueTimeout(nsecs_t timeout);
-
- sp<HGraphicBufferProducer> getBase() { return mBase; }
-
-private:
- const sp<HGraphicBufferProducer> mBase;
-};
-
-} // namespace android
-#endif // ANDROID_V4L2_CODEC2_PLUGIN_STORE_H2B_GRAPHIC_BUFFER_PRODUCER_H
diff --git a/plugin_store/include/v4l2_codec2/plugin_store/V4L2AllocatorId.h b/plugin_store/include/v4l2_codec2/plugin_store/V4L2AllocatorId.h
index 0808963..2353076 100644
--- a/plugin_store/include/v4l2_codec2/plugin_store/V4L2AllocatorId.h
+++ b/plugin_store/include/v4l2_codec2/plugin_store/V4L2AllocatorId.h
@@ -12,9 +12,7 @@ namespace V4L2AllocatorId {
// The allocator ids used for V4L2DecodeComponent.
enum : C2AllocatorStore::id_t {
- V4L2_BUFFERQUEUE = C2PlatformAllocatorStore::PLATFORM_END,
- V4L2_BUFFERPOOL,
- SECURE_LINEAR,
+ SECURE_LINEAR = C2PlatformAllocatorStore::PLATFORM_END,
SECURE_GRAPHIC,
};
diff --git a/service/Android.bp b/service/Android.bp
index eaf5d3f..d2d70c7 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -8,7 +8,7 @@ package {
}
cc_binary {
- name: "android.hardware.media.c2@1.0-service-v4l2",
+ name: "android.hardware.media.c2@1.2-service-v4l2",
defaults: [
"hidl_defaults",
@@ -37,11 +37,11 @@ cc_binary {
multilib: {
lib32: {
suffix: "-32",
- init_rc: ["android.hardware.media.c2@1.0-service-v4l2-32.rc"],
+ init_rc: ["android.hardware.media.c2@1.2-service-v4l2-32.rc"],
},
lib64: {
suffix: "-64",
- init_rc: ["android.hardware.media.c2@1.0-service-v4l2-64.rc"],
+ init_rc: ["android.hardware.media.c2@1.2-service-v4l2-64.rc"],
},
},
vintf_fragments: ["android.hardware.media.c2@1.2-service-v4l2.xml"],
diff --git a/service/android.hardware.media.c2@1.0-service-v4l2-32.rc b/service/android.hardware.media.c2@1.2-service-v4l2-32.rc
index e4ddbc3..4fe0ccb 100644
--- a/service/android.hardware.media.c2@1.0-service-v4l2-32.rc
+++ b/service/android.hardware.media.c2@1.2-service-v4l2-32.rc
@@ -1,4 +1,4 @@
-service android-hardware-media-c2-v4l2-hal-1-0 /vendor/bin/hw/android.hardware.media.c2@1.0-service-v4l2-32
+service android-hardware-media-c2-v4l2-hal-1-2 /vendor/bin/hw/android.hardware.media.c2@1.2-service-v4l2-32
class hal
user media
group mediadrm drmrpc
diff --git a/service/android.hardware.media.c2@1.0-service-v4l2-64.rc b/service/android.hardware.media.c2@1.2-service-v4l2-64.rc
index 454953b..9869c6b 100644
--- a/service/android.hardware.media.c2@1.0-service-v4l2-64.rc
+++ b/service/android.hardware.media.c2@1.2-service-v4l2-64.rc
@@ -1,4 +1,4 @@
-service android-hardware-media-c2-v4l2-hal-1-0 /vendor/bin/hw/android.hardware.media.c2@1.0-service-v4l2-64
+service android-hardware-media-c2-v4l2-hal-1-2 /vendor/bin/hw/android.hardware.media.c2@1.2-service-v4l2-64
class hal
user media
group mediadrm drmrpc
diff --git a/service/service.cpp b/service/service.cpp
index 1fa9aae..bde1521 100644
--- a/service/service.cpp
+++ b/service/service.cpp
@@ -5,9 +5,9 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "android.hardware.media.c2@1.0-service-v4l2"
-#include <base/logging.h>
#include <C2Component.h>
-#include <codec2/hidl/1.0/ComponentStore.h>
+#include <base/logging.h>
+#include <codec2/hidl/1.2/ComponentStore.h>
#include <hidl/HidlTransportSupport.h>
#include <log/log.h>
#include <minijail.h>
@@ -43,7 +43,7 @@ int main(int /* argc */, char** /* argv */) {
// Create IComponentStore service.
{
- using namespace ::android::hardware::media::c2::V1_0;
+ using namespace ::android::hardware::media::c2::V1_2;
ALOGD("Instantiating Codec2's V4L2 IComponentStore service...");
android::sp<IComponentStore> store(