media.c2 aidl: connect CCodec, Codec2Client and HAL
Test: m
Bug: 254050314
Change-Id: I63640f14416f8c3c3c4e1eb52ab85ae6bb04d421
diff --git a/media/codec2/hal/aidl/Component.cpp b/media/codec2/hal/aidl/Component.cpp
index 4f5b899..4605af3 100644
--- a/media/codec2/hal/aidl/Component.cpp
+++ b/media/codec2/hal/aidl/Component.cpp
@@ -294,46 +294,49 @@
static constexpr IComponent::BlockPoolAllocator::Tag IGBA =
IComponent::BlockPoolAllocator::allocator;
c2_status_t status = C2_OK;
+ ::android::C2PlatformAllocatorDesc allocatorParam;
switch (allocator.getTag()) {
- case ALLOCATOR_ID:
-#ifdef __ANDROID_APEX__
- status = ::android::CreateCodec2BlockPool(
- static_cast<::android::C2PlatformAllocatorStore::id_t>(
- allocator.get<ALLOCATOR_ID>()),
- mComponent,
- &c2BlockPool);
-#else
- status = ComponentStore::GetFilterWrapper()->createBlockPool(
- static_cast<::android::C2PlatformAllocatorStore::id_t>(
- allocator.get<ALLOCATOR_ID>()),
- mComponent,
- &c2BlockPool);
-#endif
- if (status != C2_OK) {
- blockPool = nullptr;
- }
- break;
- case IGBA:
- // FIXME
- break;
+ case ALLOCATOR_ID: {
+ allocatorParam.allocatorId =
+ allocator.get<IComponent::BlockPoolAllocator::allocatorId>();
+ }
+ break;
+ case IGBA: {
+ allocatorParam.allocatorId = ::android::C2PlatformAllocatorStore::IGBA;
+ allocatorParam.igba =
+ allocator.get<IComponent::BlockPoolAllocator::allocator>().igba;
+ allocatorParam.waitableFd.reset(
+ allocator.get<IComponent::BlockPoolAllocator::allocator>()
+ .waitableFd.dup().release());
+ }
+ break;
default:
- break;
+ return ScopedAStatus::fromServiceSpecificError(C2_CORRUPTED);
}
- if (blockPool) {
+#ifdef __ANDROID_APEX__
+ status = ::android::CreateCodec2BlockPool(
+ allocatorParam,
+ mComponent,
+ &c2BlockPool);
+#else
+ status = ComponentStore::GetFilterWrapper()->createBlockPool(
+ allocatorParam,
+ mComponent,
+ &c2BlockPool);
+#endif
+ if (status != C2_OK) {
+ return ScopedAStatus::fromServiceSpecificError(status);
+ }
+ {
mBlockPoolsMutex.lock();
mBlockPools.emplace(c2BlockPool->getLocalId(), c2BlockPool);
mBlockPoolsMutex.unlock();
- } else if (status == C2_OK) {
- status = C2_CORRUPTED;
}
blockPool->blockPoolId = c2BlockPool ? c2BlockPool->getLocalId() : 0;
blockPool->configurable = SharedRefBase::make<CachedConfigurable>(
std::make_unique<BlockPoolIntf>(c2BlockPool));
- if (status == C2_OK) {
- return ScopedAStatus::ok();
- }
- return ScopedAStatus::fromServiceSpecificError(status);
+ return ScopedAStatus::ok();
}
ScopedAStatus Component::destroyBlockPool(int64_t blockPoolId) {
diff --git a/media/codec2/hal/client/client.cpp b/media/codec2/hal/client/client.cpp
index e8e7cb2..2d19ecc 100644
--- a/media/codec2/hal/client/client.cpp
+++ b/media/codec2/hal/client/client.cpp
@@ -19,6 +19,8 @@
#define ATRACE_TAG ATRACE_TAG_VIDEO
#include <android-base/logging.h>
#include <utils/Trace.h>
+
+#include <codec2/aidl/GraphicBufferAllocator.h>
#include <codec2/hidl/client.h>
#include <C2Debug.h>
#include <C2BufferPriv.h>
@@ -74,6 +76,7 @@
#include <limits>
#include <map>
#include <mutex>
+#include <optional>
#include <sstream>
#include <thread>
#include <type_traits>
@@ -96,6 +99,9 @@
V2_0::utils::H2BGraphicBufferProducer;
using ::android::hardware::media::c2::V1_2::SurfaceSyncObj;
+using AidlGraphicBufferAllocator = ::aidl::android::hardware::media::c2::
+ implementation::GraphicBufferAllocator;
+
namespace bufferpool2_aidl = ::aidl::android::hardware::media::bufferpool2;
namespace bufferpool_hidl = ::android::hardware::media::bufferpool::V2_0;
namespace c2_aidl = ::aidl::android::hardware::media::c2;
@@ -1041,6 +1047,85 @@
}
};
+// The class holds GraphicBufferAllocator and the associated id of
+// HAL side BlockPool.
+// This is tightly coupled with BlockPool creation and destruction.
+// The life cycle inside class will be as follows.
+//
+// On createBlockPool client request.
+// 1. this::create() creates a GraphicBufferAllocator and set it as
+// the current.
+// 2. C2AIDL_HAL::createBlockPool() creates a C2BlockPool using
+// the GraphicBufferAllocator created in #1.
+// 3. this::setCurrentId() associates the id returned in #2 to the current
+//
+// On destroyBlockPool cliet request
+// 1. C2AIDL_HAL::destroyBlockPool() destroys the block pool
+// from HAL process.
+// 2. this::remove() destroys GraphicBufferAllocator which is associatted
+// with the C2BlockPool in #1.
+//
+struct Codec2Client::Component::GraphicBufferAllocators {
+private:
+ std::optional<C2BlockPool::local_id_t> mCurrentId;
+ std::shared_ptr<AidlGraphicBufferAllocator> mCurrent;
+
+ // A new BlockPool is created before the old BlockPool is destroyed.
+ // This holds the reference of the old BlockPool when a new BlockPool is
+ // created until the old BlockPool is explicitly requested for destruction.
+ std::map<C2BlockPool::local_id_t, std::shared_ptr<AidlGraphicBufferAllocator>> mOlds;
+ std::mutex mMutex;
+
+public:
+ // Creates a GraphicBufferAllocator which will be passed to HAL
+ // for creating C2BlockPool. And the created GraphicBufferAllocator
+ // will be used afterwards by current().
+ std::shared_ptr<AidlGraphicBufferAllocator> create() {
+ std::unique_lock<std::mutex> l(mMutex);
+ if (mCurrent) {
+ // If this is not stopped.
+ mCurrent->reset();
+ if (mCurrentId.has_value()) {
+ mOlds.emplace(mCurrentId.value(), mCurrent);
+ }
+ mCurrentId.reset();
+ mCurrent.reset();
+ }
+ // TODO: integrate initial value with CCodec/CCodecBufferChannel
+ mCurrent =
+ AidlGraphicBufferAllocator::CreateGraphicBufferAllocator(3 /* maxDequeueCount */);
+ ALOGD("GraphicBufferAllocator created");
+ return mCurrent;
+ }
+
+ // Associates the blockpool Id returned from HAL to the
+ // current GraphicBufferAllocator.
+ void setCurrentId(C2BlockPool::local_id_t id) {
+ std::unique_lock<std::mutex> l(mMutex);
+ CHECK(!mCurrentId.has_value());
+ mCurrentId = id;
+ }
+
+ // Returns the current GraphicBufferAllocator.
+ std::shared_ptr<AidlGraphicBufferAllocator> current() {
+ std::unique_lock<std::mutex> l(mMutex);
+ return mCurrent;
+ }
+
+ // Removes the GraphicBufferAllocator associated with given \p id.
+ void remove(C2BlockPool::local_id_t id) {
+ std::unique_lock<std::mutex> l(mMutex);
+ mOlds.erase(id);
+ if (mCurrentId == id) {
+ if (mCurrent) {
+ mCurrent->reset();
+ mCurrent.reset();
+ }
+ mCurrentId.reset();
+ }
+ }
+};
+
// Codec2Client
Codec2Client::Codec2Client(sp<HidlBase> const& base,
sp<c2_hidl::IConfigurable> const& configurable,
@@ -1125,6 +1210,7 @@
<< status << ".";
}
(*component)->mAidlBufferPoolSender->setReceiver(mAidlHostPoolManager);
+ aidlListener->component = *component;
return status;
}
@@ -1951,7 +2037,7 @@
},
mAidlBase{base},
mAidlBufferPoolSender{std::make_unique<AidlBufferPoolSender>()},
- mOutputBufferQueue{std::make_unique<OutputBufferQueue>()} {
+ mGraphicBufferAllocators{std::make_unique<GraphicBufferAllocators>()} {
}
Codec2Client::Component::~Component() {
@@ -1966,11 +2052,42 @@
std::shared_ptr<Codec2Client::Configurable>* configurable) {
if (mAidlBase) {
c2_aidl::IComponent::BlockPool aidlBlockPool;
- ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(static_cast<int32_t>(id),
- &aidlBlockPool);
- c2_status_t status = GetC2Status(transStatus, "createBlockPool");
- if (status != C2_OK) {
- return status;
+ c2_status_t status = C2_OK;
+
+ // TODO: Temporary mapping for the current CCodecBufferChannel.
+ // Handle this properly and remove this temporary allocator mapping.
+ id = id == C2PlatformAllocatorStore::BUFFERQUEUE ?
+ C2PlatformAllocatorStore::IGBA : id;
+
+ if (id == C2PlatformAllocatorStore::IGBA) {
+ std::shared_ptr<AidlGraphicBufferAllocator> gba =
+ mGraphicBufferAllocators->create();
+ ::ndk::ScopedFileDescriptor waitableFd;
+ ::ndk::ScopedAStatus ret = gba->getWaitableFd(&waitableFd);
+ status = GetC2Status(ret, "Gba::getWaitableFd");
+ if (status != C2_OK) {
+ return status;
+ }
+ c2_aidl::IComponent::BlockPoolAllocator allocator;
+ allocator.set<c2_aidl::IComponent::BlockPoolAllocator::allocator>();
+ allocator.get<c2_aidl::IComponent::BlockPoolAllocator::allocator>().igba =
+ c2_aidl::IGraphicBufferAllocator::fromBinder(gba->asBinder());
+ allocator.get<c2_aidl::IComponent::BlockPoolAllocator::allocator>().waitableFd =
+ std::move(waitableFd);
+ ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(
+ allocator, &aidlBlockPool);
+ status = GetC2Status(transStatus, "createBlockPool");
+ if (status != C2_OK) {
+ return status;
+ }
+ mGraphicBufferAllocators->setCurrentId(aidlBlockPool.blockPoolId);
+ } else {
+ ::ndk::ScopedAStatus transStatus = mAidlBase->createBlockPool(
+ static_cast<int32_t>(id), &aidlBlockPool);
+ status = GetC2Status(transStatus, "createBlockPool");
+ if (status != C2_OK) {
+ return status;
+ }
}
*blockPoolId = aidlBlockPool.blockPoolId;
*configurable = std::make_shared<Configurable>(aidlBlockPool.configurable);
@@ -2003,6 +2120,7 @@
c2_status_t Codec2Client::Component::destroyBlockPool(
C2BlockPool::local_id_t localId) {
if (mAidlBase) {
+ mGraphicBufferAllocators->remove(localId);
::ndk::ScopedAStatus transStatus = mAidlBase->destroyBlockPool(localId);
return GetC2Status(transStatus, "destroyBlockPool");
}
@@ -2017,8 +2135,12 @@
void Codec2Client::Component::handleOnWorkDone(
const std::list<std::unique_ptr<C2Work>> &workItems) {
- // Output bufferqueue-based blocks' lifetime management
- mOutputBufferQueue->holdBufferQueueBlocks(workItems);
+ if (mAidlBase) {
+ holdIgbaBlocks(workItems);
+ } else {
+ // Output bufferqueue-based blocks' lifetime management
+ mOutputBufferQueue->holdBufferQueueBlocks(workItems);
+ }
}
c2_status_t Codec2Client::Component::queue(
@@ -2102,8 +2224,12 @@
}
}
- // Output bufferqueue-based blocks' lifetime management
- mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
+ if (mAidlBase) {
+ holdIgbaBlocks(*flushedWork);
+ } else {
+ // Output bufferqueue-based blocks' lifetime management
+ mOutputBufferQueue->holdBufferQueueBlocks(*flushedWork);
+ }
return status;
}
@@ -2242,6 +2368,17 @@
const sp<IGraphicBufferProducer>& surface,
uint32_t generation,
int maxDequeueCount) {
+ if (mAidlBase) {
+ std::shared_ptr<AidlGraphicBufferAllocator> gba =
+ mGraphicBufferAllocators->current();
+ if (!gba) {
+ LOG(ERROR) << "setOutputSurface for AIDL -- "
+ "GraphicBufferAllocator was not created.";
+ return C2_CORRUPTED;
+ }
+ bool ret = gba->configure(surface, generation, maxDequeueCount);
+ return ret ? C2_OK : C2_CORRUPTED;
+ }
uint64_t bqId = 0;
sp<IGraphicBufferProducer> nullIgbp;
sp<HGraphicBufferProducer2> nullHgbp;
@@ -2303,10 +2440,6 @@
ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx%s",
generation, (long long)consumerUsage, syncObj ? " sync" : "");
- if (mAidlBase) {
- // FIXME
- return C2_OMITTED;
- }
Return<c2_hidl::Status> transStatus = syncObj ?
mHidlBase1_2->setOutputSurfaceWithSyncObj(
static_cast<uint64_t>(blockPoolId),
@@ -2335,26 +2468,51 @@
const QueueBufferInput& input,
QueueBufferOutput* output) {
ScopedTrace trace(ATRACE_TAG,"Codec2Client::Component::queueToOutputSurface");
+ if (mAidlBase) {
+ std::shared_ptr<AidlGraphicBufferAllocator> gba =
+ mGraphicBufferAllocators->current();
+ if (gba) {
+ return gba->displayBuffer(block, input, output);
+ } else {
+ return C2_NOT_FOUND;
+ }
+ }
return mOutputBufferQueue->outputBuffer(block, input, output);
}
void Codec2Client::Component::pollForRenderedFrames(FrameEventHistoryDelta* delta) {
+ if (mAidlBase) {
+ // TODO b/311348680
+ return;
+ }
mOutputBufferQueue->pollForRenderedFrames(delta);
}
void Codec2Client::Component::setOutputSurfaceMaxDequeueCount(
int maxDequeueCount) {
+ if (mAidlBase) {
+ std::shared_ptr<AidlGraphicBufferAllocator> gba =
+ mGraphicBufferAllocators->current();
+ if (gba) {
+ gba->updateMaxDequeueBufferCount(maxDequeueCount);
+ }
+ return;
+ }
mOutputBufferQueue->updateMaxDequeueBufferCount(maxDequeueCount);
}
void Codec2Client::Component::stopUsingOutputSurface(
C2BlockPool::local_id_t blockPoolId) {
- std::scoped_lock lock(mOutputMutex);
- mOutputBufferQueue->stop();
if (mAidlBase) {
- // FIXME
+ std::shared_ptr<AidlGraphicBufferAllocator> gba =
+ mGraphicBufferAllocators->current();
+ if (gba) {
+ gba->reset();
+ }
return;
}
+ std::scoped_lock lock(mOutputMutex);
+ mOutputBufferQueue->stop();
Return<c2_hidl::Status> transStatus = mHidlBase1_0->setOutputSurface(
static_cast<uint64_t>(blockPoolId), nullptr);
if (!transStatus.isOk()) {
@@ -2372,9 +2530,50 @@
void Codec2Client::Component::onBufferReleasedFromOutputSurface(
uint32_t generation) {
+ if (mAidlBase) {
+ std::shared_ptr<AidlGraphicBufferAllocator> gba =
+ mGraphicBufferAllocators->current();
+ if (gba) {
+ gba->onBufferReleased(generation);
+ }
+ return;
+ }
mOutputBufferQueue->onBufferReleased(generation);
}
+void Codec2Client::Component::holdIgbaBlocks(
+ const std::list<std::unique_ptr<C2Work>>& workList) {
+ if (!mAidlBase) {
+ return;
+ }
+ std::shared_ptr<AidlGraphicBufferAllocator> gba =
+ mGraphicBufferAllocators->current();
+ if (!gba) {
+ return;
+ }
+ std::shared_ptr<c2_aidl::IGraphicBufferAllocator> igba =
+ c2_aidl::IGraphicBufferAllocator::fromBinder(gba->asBinder());
+ for (const std::unique_ptr<C2Work>& work : workList) {
+ if (!work) [[unlikely]] {
+ continue;
+ }
+ for (const std::unique_ptr<C2Worklet>& worklet : work->worklets) {
+ if (!worklet) {
+ continue;
+ }
+ for (const std::shared_ptr<C2Buffer>& buffer : worklet->output.buffers) {
+ if (buffer) {
+ for (const C2ConstGraphicBlock& block : buffer->data().graphicBlocks()) {
+ std::shared_ptr<_C2BlockPoolData> poolData =
+ _C2BlockFactory::GetGraphicBlockPoolData(block);
+ _C2BlockFactory::RegisterIgba(poolData, igba);
+ }
+ }
+ }
+ }
+ }
+}
+
c2_status_t Codec2Client::Component::connectToInputSurface(
const std::shared_ptr<InputSurface>& inputSurface,
std::shared_ptr<InputSurfaceConnection>* connection) {
diff --git a/media/codec2/hal/client/include/codec2/hidl/client.h b/media/codec2/hal/client/include/codec2/hidl/client.h
index a8dd0bf..3b7f7a6 100644
--- a/media/codec2/hal/client/include/codec2/hidl/client.h
+++ b/media/codec2/hal/client/include/codec2/hidl/client.h
@@ -478,6 +478,14 @@
void onBufferReleasedFromOutputSurface(
uint32_t generation);
+ // When the client received \p workList and the blocks inside
+ // \p workList are IGBA based graphic blocks, specify the owner
+ // as the current IGBA for the future operations.
+ // Future operations could be rendering the blocks to the surface
+ // or deallocating blocks to the surface.
+ void holdIgbaBlocks(
+ const std::list<std::unique_ptr<C2Work>>& workList);
+
// Connect to a given InputSurface.
c2_status_t connectToInputSurface(
const std::shared_ptr<InputSurface>& inputSurface,
@@ -517,6 +525,9 @@
// In order to prevent the race condition mutex is added.
std::mutex mOutputMutex;
+ struct GraphicBufferAllocators;
+ std::unique_ptr<GraphicBufferAllocators> mGraphicBufferAllocators;
+
class AidlDeathManager;
static AidlDeathManager *GetAidlDeathManager();
std::optional<size_t> mAidlDeathSeq;
diff --git a/media/codec2/hal/plugin/FilterWrapper.cpp b/media/codec2/hal/plugin/FilterWrapper.cpp
index d5124fd..197d6e7 100644
--- a/media/codec2/hal/plugin/FilterWrapper.cpp
+++ b/media/codec2/hal/plugin/FilterWrapper.cpp
@@ -969,6 +969,15 @@
C2PlatformAllocatorStore::id_t allocatorId,
std::shared_ptr<const C2Component> component,
std::shared_ptr<C2BlockPool> *pool) {
+ C2PlatformAllocatorDesc allocatorParam;
+ allocatorParam.allocatorId = allocatorId;
+ return createBlockPool(allocatorParam, component, pool);
+}
+
+c2_status_t FilterWrapper::createBlockPool(
+ C2PlatformAllocatorDesc &allocatorParam,
+ std::shared_ptr<const C2Component> component,
+ std::shared_ptr<C2BlockPool> *pool) {
std::unique_lock lock(mWrappedComponentsMutex);
for (auto it = mWrappedComponents.begin(); it != mWrappedComponents.end(); ) {
std::shared_ptr<const C2Component> comp = it->front().lock();
@@ -983,13 +992,13 @@
[](const std::weak_ptr<const C2Component> &el) {
return el.lock();
});
- if (C2_OK == CreateCodec2BlockPool(allocatorId, components, pool)) {
+ if (C2_OK == CreateCodec2BlockPool(allocatorParam, components, pool)) {
return C2_OK;
}
}
++it;
}
- return CreateCodec2BlockPool(allocatorId, component, pool);
+ return CreateCodec2BlockPool(allocatorParam, component, pool);
}
c2_status_t FilterWrapper::queryParamsForPreviousComponent(
diff --git a/media/codec2/hal/plugin/FilterWrapperStub.cpp b/media/codec2/hal/plugin/FilterWrapperStub.cpp
index 01ca596..3fd5409 100644
--- a/media/codec2/hal/plugin/FilterWrapperStub.cpp
+++ b/media/codec2/hal/plugin/FilterWrapperStub.cpp
@@ -45,7 +45,16 @@
C2PlatformAllocatorStore::id_t allocatorId,
std::shared_ptr<const C2Component> component,
std::shared_ptr<C2BlockPool> *pool) {
- return CreateCodec2BlockPool(allocatorId, component, pool);
+ C2PlatformAllocatorDesc allocatorParam;
+ allocatorParam.allocatorId = allocatorId;
+ return createBlockPool(allocatorParam, component, pool);
+}
+
+c2_status_t FilterWrapper::createBlockPool(
+ C2PlatformAllocatorDesc &allocatorParam,
+ std::shared_ptr<const C2Component> component,
+ std::shared_ptr<C2BlockPool> *pool) {
+ return CreateCodec2BlockPool(allocatorParam, component, pool);
}
} // namespace android
diff --git a/media/codec2/hal/plugin/internal/FilterWrapper.h b/media/codec2/hal/plugin/internal/FilterWrapper.h
index cf2cc30..dcffb5c 100644
--- a/media/codec2/hal/plugin/internal/FilterWrapper.h
+++ b/media/codec2/hal/plugin/internal/FilterWrapper.h
@@ -90,6 +90,14 @@
std::shared_ptr<C2BlockPool> *pool);
/**
+ * Create a C2BlockPool object with |allocatorParam| for |component|.
+ */
+ c2_status_t createBlockPool(
+ C2PlatformAllocatorDesc &allocatorParam,
+ std::shared_ptr<const C2Component> component,
+ std::shared_ptr<C2BlockPool> *pool);
+
+ /**
* Query parameters that |intf| wants from the previous component.
*/
c2_status_t queryParamsForPreviousComponent(
diff --git a/media/codec2/vndk/C2Fence.cpp b/media/codec2/vndk/C2Fence.cpp
index 4c385f1..52ebe25 100644
--- a/media/codec2/vndk/C2Fence.cpp
+++ b/media/codec2/vndk/C2Fence.cpp
@@ -26,6 +26,8 @@
#include <C2FenceFactory.h>
#include <C2SurfaceSyncObj.h>
+#include <utility>
+
#define MAX_FENCE_FDS 1
class C2Fence::Impl {
@@ -485,17 +487,26 @@
mValid = (mPipeFd.get() >= 0);
}
+ PipeFenceImpl(::android::base::unique_fd &&ufd) : mPipeFd{std::move(ufd)} {
+ mValid = (mPipeFd.get() >= 0);
+ }
+
private:
friend struct _C2FenceFactory;
static constexpr int kPipeFenceWaitLimitSecs = 5;
mutable std::atomic<bool> mValid;
- ::android::base::unique_fd mPipeFd;
+ const ::android::base::unique_fd mPipeFd;
};
C2Fence _C2FenceFactory::CreatePipeFence(int fd) {
+ ::android::base::unique_fd ufd{fd};
+ return CreatePipeFence(std::move(ufd));
+}
+
+C2Fence _C2FenceFactory::CreatePipeFence(::android::base::unique_fd &&ufd) {
std::shared_ptr<_C2FenceFactory::PipeFenceImpl> impl =
- std::make_shared<_C2FenceFactory::PipeFenceImpl>(fd);
+ std::make_shared<_C2FenceFactory::PipeFenceImpl>(std::move(ufd));
std::shared_ptr<C2Fence::Impl> p = std::static_pointer_cast<C2Fence::Impl>(impl);
if (!p) {
ALOGE("PipeFence creation failure");
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index 76c378d..e7fd14f 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -26,12 +26,15 @@
#include <C2BqBufferPriv.h>
#include <C2Component.h>
#include <C2Config.h>
+#include <C2IgbaBufferPriv.h>
#include <C2PlatformStorePluginLoader.h>
#include <C2PlatformSupport.h>
#include <codec2/common/HalSelection.h>
#include <cutils/properties.h>
#include <util/C2InterfaceHelper.h>
+#include <aidl/android/hardware/media/c2/IGraphicBufferAllocator.h>
+
#include <dlfcn.h>
#include <unistd.h> // getpagesize
@@ -92,6 +95,9 @@
/// returns a shared-singleton bufferqueue supporting gralloc allocator
std::shared_ptr<C2Allocator> fetchBufferQueueAllocator();
+ /// returns a shared-singleton IGBA supporting AHardwareBuffer/gralloc allocator
+ std::shared_ptr<C2Allocator> fetchIgbaAllocator();
+
/// component store to use
std::mutex _mComponentStoreSetLock; // protects the entire updating _mComponentStore and its
// dependencies
@@ -158,6 +164,10 @@
*allocator = fetchBlobAllocator();
break;
+ case C2PlatformAllocatorStore::IGBA:
+ *allocator = fetchIgbaAllocator();
+ break;
+
default:
// Try to create allocator from platform store plugins.
c2_status_t res =
@@ -389,6 +399,18 @@
return allocator;
}
+std::shared_ptr<C2Allocator> C2PlatformAllocatorStoreImpl::fetchIgbaAllocator() {
+ static std::mutex mutex;
+ static std::weak_ptr<C2Allocator> ahwbAllocator;
+ std::lock_guard<std::mutex> lock(mutex);
+ std::shared_ptr<C2Allocator> allocator = ahwbAllocator.lock();
+ if (allocator == nullptr) {
+ allocator = std::make_shared<C2AllocatorAhwb>(C2PlatformAllocatorStore::IGBA);
+ ahwbAllocator = allocator;
+ }
+ return allocator;
+}
+
namespace {
std::mutex gPreferredComponentStoreMutex;
std::shared_ptr<C2ComponentStore> gPreferredComponentStore;
@@ -460,12 +482,13 @@
private:
c2_status_t _createBlockPool(
- C2PlatformAllocatorStore::id_t allocatorId,
+ C2PlatformAllocatorDesc &allocatorParam,
std::vector<std::shared_ptr<const C2Component>> components,
C2BlockPool::local_id_t poolId,
std::shared_ptr<C2BlockPool> *pool) {
std::shared_ptr<C2AllocatorStore> allocatorStore =
GetCodec2PlatformAllocatorStore();
+ C2PlatformAllocatorStore::id_t allocatorId = allocatorParam.allocatorId;
std::shared_ptr<C2Allocator> allocator;
c2_status_t res = C2_NOT_FOUND;
@@ -532,6 +555,22 @@
components.begin(), components.end());
}
break;
+ case C2PlatformAllocatorStore::IGBA:
+ res = allocatorStore->fetchAllocator(
+ C2PlatformAllocatorStore::IGBA, &allocator);
+ if (res == C2_OK) {
+ std::shared_ptr<C2BlockPool> ptr(
+ new C2IgbaBlockPool(allocator,
+ allocatorParam.igba,
+ std::move(allocatorParam.waitableFd),
+ poolId), deleter);
+ *pool = ptr;
+ mBlockPools[poolId] = ptr;
+ mComponents[poolId].insert(
+ mComponents[poolId].end(),
+ components.begin(), components.end());
+ }
+ break;
default:
// Try to create block pool from platform store plugins.
std::shared_ptr<C2BlockPool> ptr;
@@ -554,10 +593,20 @@
C2PlatformAllocatorStore::id_t allocatorId,
std::vector<std::shared_ptr<const C2Component>> components,
std::shared_ptr<C2BlockPool> *pool) {
- std::unique_lock lock(mMutex);
- return _createBlockPool(allocatorId, components, mBlockPoolSeqId++, pool);
+ C2PlatformAllocatorDesc allocator;
+ allocator.allocatorId = allocatorId;
+ return createBlockPool(allocator, components, pool);
}
+ c2_status_t createBlockPool(
+ C2PlatformAllocatorDesc &allocator,
+ std::vector<std::shared_ptr<const C2Component>> components,
+ std::shared_ptr<C2BlockPool> *pool) {
+ std::unique_lock lock(mMutex);
+ return _createBlockPool(allocator, components, mBlockPoolSeqId++, pool);
+ }
+
+
c2_status_t getBlockPool(
C2BlockPool::local_id_t blockPoolId,
std::shared_ptr<const C2Component> component,
@@ -586,8 +635,10 @@
}
// TODO: remove this. this is temporary
if (blockPoolId == C2BlockPool::PLATFORM_START) {
+ C2PlatformAllocatorDesc allocator;
+ allocator.allocatorId = C2PlatformAllocatorStore::BUFFERQUEUE;
return _createBlockPool(
- C2PlatformAllocatorStore::BUFFERQUEUE, {component}, blockPoolId, pool);
+ allocator, {component}, blockPoolId, pool);
}
return C2_NOT_FOUND;
}
@@ -644,7 +695,9 @@
std::shared_ptr<C2BlockPool> *pool) {
pool->reset();
- return sBlockPoolCache->createBlockPool(allocatorId, components, pool);
+ C2PlatformAllocatorDesc allocator;
+ allocator.allocatorId = allocatorId;
+ return sBlockPoolCache->createBlockPool(allocator, components, pool);
}
c2_status_t CreateCodec2BlockPool(
@@ -653,7 +706,27 @@
std::shared_ptr<C2BlockPool> *pool) {
pool->reset();
- return sBlockPoolCache->createBlockPool(allocatorId, {component}, pool);
+ C2PlatformAllocatorDesc allocator;
+ allocator.allocatorId = allocatorId;
+ return sBlockPoolCache->createBlockPool(allocator, {component}, pool);
+}
+
+c2_status_t CreateCodec2BlockPool(
+ C2PlatformAllocatorDesc &allocator,
+ const std::vector<std::shared_ptr<const C2Component>> &components,
+ std::shared_ptr<C2BlockPool> *pool) {
+ pool->reset();
+
+ return sBlockPoolCache->createBlockPool(allocator, components, pool);
+}
+
+c2_status_t CreateCodec2BlockPool(
+ C2PlatformAllocatorDesc &allocator,
+ std::shared_ptr<const C2Component> component,
+ std::shared_ptr<C2BlockPool> *pool) {
+ pool->reset();
+
+ return sBlockPoolCache->createBlockPool(allocator, {component}, pool);
}
class C2PlatformComponentStore : public C2ComponentStore {
diff --git a/media/codec2/vndk/include/C2FenceFactory.h b/media/codec2/vndk/include/C2FenceFactory.h
index 9b09980..4f974ca 100644
--- a/media/codec2/vndk/include/C2FenceFactory.h
+++ b/media/codec2/vndk/include/C2FenceFactory.h
@@ -20,6 +20,8 @@
#include <C2Buffer.h>
+#include <android-base/unique_fd.h>
+
/*
* Create a list of fds from fence
*
@@ -69,6 +71,7 @@
/*
* Create C2Fence from an fd created by pipe()/pipe2() syscall.
+ * The ownership of \p fd is transterred to the returned C2Fence.
*
* \param fd An fd representing the write end from a pair of
* file descriptors which are created by
@@ -76,6 +79,15 @@
*/
static C2Fence CreatePipeFence(int fd);
+ /*
+ * Create C2Fence from a unique_fd created by pipe()/pipe2() syscall.
+ *
+ * \param ufd A unique_fd representing the write end from a pair
+ * of file descriptors which are created by
+ * pipe()/pipe2() syscall.
+ */
+ static C2Fence CreatePipeFence(::android::base::unique_fd &&ufd);
+
/**
* Create a native handle from fence for marshalling
*
diff --git a/media/codec2/vndk/include/C2IgbaBufferPriv.h b/media/codec2/vndk/include/C2IgbaBufferPriv.h
index a5676b7..5879263 100644
--- a/media/codec2/vndk/include/C2IgbaBufferPriv.h
+++ b/media/codec2/vndk/include/C2IgbaBufferPriv.h
@@ -17,6 +17,8 @@
#include <C2Buffer.h>
+#include <android-base/unique_fd.h>
+
#include <memory>
namespace aidl::android::hardware::media::c2 {
@@ -32,8 +34,9 @@
public:
explicit C2IgbaBlockPool(
const std::shared_ptr<C2Allocator> &allocator,
- const std::shared_ptr<
- ::aidl::android::hardware::media::c2::IGraphicBufferAllocator> &igba,
+ const std::shared_ptr<::aidl::android::hardware::media::c2::IGraphicBufferAllocator>
+ &igba,
+ ::android::base::unique_fd &&ufd,
const local_id_t localId);
virtual ~C2IgbaBlockPool() = default;
@@ -89,8 +92,7 @@
C2IgbaBlockPoolData(
const AHardwareBuffer *buffer,
- const std::shared_ptr<::aidl::android::hardware::media::c2::IGraphicBufferAllocator>
- &igba);
+ std::shared_ptr<::aidl::android::hardware::media::c2::IGraphicBufferAllocator> &igba);
virtual ~C2IgbaBlockPoolData() override;
@@ -103,7 +105,10 @@
void disown();
+ void registerIgba(std::shared_ptr<
+ ::aidl::android::hardware::media::c2::IGraphicBufferAllocator> &igba);
+
bool mOwned;
const AHardwareBuffer *mBuffer;
- const std::weak_ptr<::aidl::android::hardware::media::c2::IGraphicBufferAllocator> mIgba;
+ std::weak_ptr<::aidl::android::hardware::media::c2::IGraphicBufferAllocator> mIgba;
};
diff --git a/media/codec2/vndk/include/C2PlatformSupport.h b/media/codec2/vndk/include/C2PlatformSupport.h
index 221a799..6fa155a 100644
--- a/media/codec2/vndk/include/C2PlatformSupport.h
+++ b/media/codec2/vndk/include/C2PlatformSupport.h
@@ -22,6 +22,12 @@
#include <memory>
+#include <android-base/unique_fd.h>
+
+namespace aidl::android::hardware::media::c2 {
+class IGraphicBufferAllocator;
+}
+
namespace android {
/**
@@ -164,6 +170,53 @@
std::shared_ptr<C2BlockPool> *pool);
/**
+ * BlockPool creation parameters regarding allocator.
+ *
+ * igba, waitableFd are required only when allocatorId is
+ * C2PlatformAllocatorStore::IGBA.
+ */
+struct C2PlatformAllocatorDesc {
+ C2PlatformAllocatorStore::id_t allocatorId;
+ std::shared_ptr<::aidl::android::hardware::media::c2::IGraphicBufferAllocator> igba;
+ ::android::base::unique_fd waitableFd; // This will be passed and moved to C2Fence
+ // implementation.
+};
+
+/**
+ * Creates a block pool.
+ * \param allocator allocator ID and parameters which are used to allocate blocks
+ * \param component the component using the block pool (must be non-null)
+ * \param pool pointer to where the created block pool shall be store on success.
+ * nullptr will be stored here on failure
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_BAD_VALUE the component is null
+ * \retval C2_NOT_FOUND if the allocator does not exist
+ * \retval C2_NO_MEMORY not enough memory to create a block pool
+ */
+c2_status_t CreateCodec2BlockPool(
+ C2PlatformAllocatorDesc &allocator,
+ std::shared_ptr<const C2Component> component,
+ std::shared_ptr<C2BlockPool> *pool);
+
+/**
+ * Creates a block pool.
+ * \param allocator allocator ID and parameters which are used to allocate blocks
+ * \param components the components using the block pool
+ * \param pool pointer to where the created block pool shall be store on success.
+ * nullptr will be stored here on failure
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_BAD_VALUE the component is null
+ * \retval C2_NOT_FOUND if the allocator does not exist
+ * \retval C2_NO_MEMORY not enough memory to create a block pool
+ */
+c2_status_t CreateCodec2BlockPool(
+ C2PlatformAllocatorDesc &allocator,
+ const std::vector<std::shared_ptr<const C2Component>> &components,
+ std::shared_ptr<C2BlockPool> *pool);
+
+/**
* Returns the platform component store.
* \retval nullptr if the platform component store could not be obtained
*/
diff --git a/media/codec2/vndk/internal/C2BlockInternal.h b/media/codec2/vndk/internal/C2BlockInternal.h
index 8198ee1..4baf2db 100644
--- a/media/codec2/vndk/internal/C2BlockInternal.h
+++ b/media/codec2/vndk/internal/C2BlockInternal.h
@@ -39,6 +39,12 @@
}
+namespace aidl::android::hardware::media::c2 {
+
+// IGraphicBufferAllocator for media.c2 aidl
+class IGraphicBufferAllocator;
+}
+
typedef struct AHardwareBuffer AHardwareBuffer;
using bufferpool_BufferPoolData = android::hardware::media::bufferpool::BufferPoolData;
@@ -472,6 +478,16 @@
*/
static void DisownIgbaBlock(
const std::shared_ptr<_C2BlockPoolData>& poolData);
+
+ /**
+ * When the client receives a block from HAL, the client needs to store
+ * IGraphicBufferAllocator from which the block was originally allocated.
+ * The stored \p igba will be used in the dtor to deallocate the buffer.
+ * (calling IGraphicBufferAllocator::deallocate to reclaim.)
+ */
+ static void RegisterIgba(
+ const std::shared_ptr<_C2BlockPoolData>& poolData,
+ std::shared_ptr<::aidl::android::hardware::media::c2::IGraphicBufferAllocator> &igba);
};
#endif // ANDROID_STAGEFRIGHT_C2BLOCK_INTERNAL_H_
diff --git a/media/codec2/vndk/platform/C2IgbaBuffer.cpp b/media/codec2/vndk/platform/C2IgbaBuffer.cpp
index 853d5a3..2051e8f 100644
--- a/media/codec2/vndk/platform/C2IgbaBuffer.cpp
+++ b/media/codec2/vndk/platform/C2IgbaBuffer.cpp
@@ -67,7 +67,8 @@
return err;
}
std::shared_ptr<C2IgbaBlockPoolData> poolData =
- std::make_shared<C2IgbaBlockPoolData>(ahwb, igba);
+ std::make_shared<C2IgbaBlockPoolData>(
+ ahwb, const_cast<std::shared_ptr<C2IGBA>&>(igba));
*block = _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
return C2_OK;
} else {
@@ -79,7 +80,7 @@
C2IgbaBlockPoolData::C2IgbaBlockPoolData(
const AHardwareBuffer *buffer,
- const std::shared_ptr<C2IGBA> &igba) : mOwned(true), mBuffer(buffer), mIgba(igba) {
+ std::shared_ptr<C2IGBA> &igba) : mOwned(true), mBuffer(buffer), mIgba(igba) {
CHECK(mBuffer);
AHardwareBuffer_acquire(const_cast<AHardwareBuffer *>(mBuffer));
}
@@ -115,6 +116,10 @@
mOwned = false;
}
+void C2IgbaBlockPoolData::registerIgba(std::shared_ptr<C2IGBA> &igba) {
+ mIgba = igba;
+}
+
std::shared_ptr<C2GraphicBlock> _C2BlockFactory::CreateGraphicBlock(AHardwareBuffer *ahwb) {
// TODO: get proper allocator? and synchronization? or allocator-less?
static std::shared_ptr<C2AllocatorAhwb> sAllocator = std::make_shared<C2AllocatorAhwb>(0);
@@ -148,22 +153,30 @@
}
}
+void _C2BlockFactory::RegisterIgba(
+ const std::shared_ptr<_C2BlockPoolData>& data,
+ std::shared_ptr<C2IGBA> &igba) {
+ if (data && data->getType() == _C2BlockPoolData::TYPE_AHWBUFFER) {
+ const std::shared_ptr<C2IgbaBlockPoolData> poolData =
+ std::static_pointer_cast<C2IgbaBlockPoolData>(data);
+ poolData->registerIgba(igba);
+ }
+}
+
C2IgbaBlockPool::C2IgbaBlockPool(
const std::shared_ptr<C2Allocator> &allocator,
const std::shared_ptr<C2IGBA> &igba,
+ ::android::base::unique_fd &&ufd,
const local_id_t localId) : mAllocator(allocator), mIgba(igba), mLocalId(localId) {
if (!mIgba) {
mValid = false;
return;
}
- // TODO: Remove IPC (This is a nested IPC call during c2aidl creatBlockPool().
- ::ndk::ScopedFileDescriptor fd;
- ::ndk::ScopedAStatus status = mIgba->getWaitableFd(&fd);
- if (!status.isOk()) {
+ if (ufd.get() < 0) {
mValid = false;
return;
}
- mWaitFence = _C2FenceFactory::CreatePipeFence(fd.release());
+ mWaitFence = _C2FenceFactory::CreatePipeFence(std::move(ufd));
if (!mWaitFence.valid()) {
mValid = false;
return;