media.c2 aidl: Implement IGraphicBufferAllocator
Implement IGraphicBufferAllocator c2aidl interface.
Bug: 254050314
Change-Id: Ib7ad6d91291ce1ea7dcefdebe24d1f217abac44b
diff --git a/media/codec2/hal/client/Android.bp b/media/codec2/hal/client/Android.bp
index 61ec10e..38b3edf 100644
--- a/media/codec2/hal/client/Android.bp
+++ b/media/codec2/hal/client/Android.bp
@@ -23,6 +23,7 @@
name: "libcodec2_client",
srcs: [
+ "GraphicBufferAllocator.cpp",
"GraphicsTracker.cpp",
"client.cpp",
"output.cpp",
diff --git a/media/codec2/hal/client/GraphicBufferAllocator.cpp b/media/codec2/hal/client/GraphicBufferAllocator.cpp
new file mode 100644
index 0000000..bbef1b5
--- /dev/null
+++ b/media/codec2/hal/client/GraphicBufferAllocator.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gui/IProducerListener.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+#include <codec2/aidl/GraphicBufferAllocator.h>
+#include <codec2/aidl/GraphicsTracker.h>
+
+namespace aidl::android::hardware::media::c2::implementation {
+
+class OnBufferReleasedListener : public ::android::BnProducerListener {
+private:
+ uint32_t mGeneration;
+ std::weak_ptr<GraphicBufferAllocator> mAllocator;
+public:
+ OnBufferReleasedListener(
+ uint32_t generation,
+ const std::shared_ptr<GraphicBufferAllocator> &allocator)
+ : mGeneration(generation), mAllocator(allocator) {}
+ virtual ~OnBufferReleasedListener() = default;
+ virtual void onBufferReleased() {
+ auto p = mAllocator.lock();
+ if (p) {
+ p->onBufferReleased(mGeneration);
+ }
+ }
+ virtual bool needsReleaseNotify() { return true; }
+};
+
+::ndk::ScopedAStatus GraphicBufferAllocator::allocate(
+ const IGraphicBufferAllocator::Description& in_desc,
+ IGraphicBufferAllocator::Allocation* _aidl_return) {
+ AHardwareBuffer *buf;
+ ::android::sp<::android::Fence> fence;
+ c2_status_t ret = allocate(
+ in_desc.width, in_desc.height, in_desc.format, in_desc.usage,
+ &buf, &fence);
+ if (ret == C2_OK) {
+ _aidl_return->buffer.reset(buf);
+ _aidl_return->fence = ::ndk::ScopedFileDescriptor(fence->dup());
+ return ::ndk::ScopedAStatus::ok();
+ }
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(ret);
+}
+
+::ndk::ScopedAStatus GraphicBufferAllocator::deallocate(int64_t in_id, bool* _aidl_return) {
+ *_aidl_return = deallocate(in_id, ::android::Fence::NO_FENCE);
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus GraphicBufferAllocator::getWaitableFds(
+ IGraphicBufferAllocator::WaitableFds* _aidl_return) {
+ int allocFd;
+ int statusFd;
+ c2_status_t ret = mGraphicsTracker->getWaitableFds(&allocFd, &statusFd);
+ if (ret == C2_OK) {
+ _aidl_return->allocEvent.set(allocFd);
+ _aidl_return->statusEvent.set(statusFd);
+ return ::ndk::ScopedAStatus::ok();
+ }
+ return ::ndk::ScopedAStatus::fromServiceSpecificError(ret);
+}
+
+bool GraphicBufferAllocator::configure(
+ const ::android::sp<IGraphicBufferProducer>& igbp,
+ uint32_t generation,
+ int maxDequeueBufferCount) {
+ c2_status_t ret = C2_OK;
+
+ ret = mGraphicsTracker->configureGraphics(igbp, generation);
+ if (ret != C2_OK) {
+ ALOGE("configuring igbp failed gen #(%d), configuring max dequeue count didn't happen",
+ (unsigned int)generation);
+ return false;
+ }
+
+ ret = mGraphicsTracker->configureMaxDequeueCount(maxDequeueBufferCount);
+ if (ret != C2_OK) {
+ ALOGE("configuring max dequeue count to %d failed", maxDequeueBufferCount);
+ return false;
+ }
+ return true;
+}
+
+void GraphicBufferAllocator::updateMaxDequeueBufferCount(int count) {
+ c2_status_t ret = mGraphicsTracker->configureMaxDequeueCount(count);
+ if (ret != C2_OK) {
+ ALOGE("updating max dequeue buffer count failed %d", ret);
+ }
+}
+
+void GraphicBufferAllocator::reset() {
+ mGraphicsTracker->stop();
+}
+
+const ::android::sp<::android::IProducerListener> GraphicBufferAllocator::createReleaseListener(
+ uint32_t generation) {
+ return new OnBufferReleasedListener(generation, ref<GraphicBufferAllocator>());
+}
+
+void GraphicBufferAllocator::onBufferReleased(uint32_t generation) {
+ mGraphicsTracker->onReleased(generation);
+}
+
+c2_status_t GraphicBufferAllocator::allocate(
+ uint32_t width, uint32_t height, ::android::PixelFormat format, uint64_t usage,
+ AHardwareBuffer **buf, ::android::sp<::android::Fence> *fence) {
+ return mGraphicsTracker->allocate(width, height, format, usage, buf, fence);
+}
+
+bool GraphicBufferAllocator::deallocate(const uint64_t id,
+ const ::android::sp<::android::Fence> &fence) {
+ c2_status_t ret = mGraphicsTracker->deallocate(id, fence);
+ if (ret != C2_OK) {
+ ALOGW("deallocate() %llu was not successful %d", (unsigned long long)id, ret);
+ return false;
+ }
+ return true;
+}
+
+c2_status_t GraphicBufferAllocator::displayBuffer(
+ const C2ConstGraphicBlock& block,
+ const IGraphicBufferProducer::QueueBufferInput& input,
+ IGraphicBufferProducer::QueueBufferOutput *output) {
+ return mGraphicsTracker->render(block, input, output);
+}
+
+GraphicBufferAllocator::~GraphicBufferAllocator() {}
+
+std::shared_ptr<GraphicBufferAllocator> GraphicBufferAllocator::CreateGraphicBufferAllocator(
+ int maxDequeueCount) {
+ return ::ndk::SharedRefBase::make<GraphicBufferAllocator>(maxDequeueCount);
+}
+
+GraphicBufferAllocator::GraphicBufferAllocator(int maxDequeueCount)
+ : mGraphicsTracker(GraphicsTracker::CreateGraphicsTracker(maxDequeueCount)) {}
+
+} // namespace aidl::android::hardware::media::c2::implementation
diff --git a/media/codec2/hal/client/include/codec2/aidl/GraphicBufferAllocator.h b/media/codec2/hal/client/include/codec2/aidl/GraphicBufferAllocator.h
new file mode 100644
index 0000000..f9c8aca
--- /dev/null
+++ b/media/codec2/hal/client/include/codec2/aidl/GraphicBufferAllocator.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/media/c2/BnGraphicBufferAllocator.h>
+
+#include <android-base/unique_fd.h>
+#include <gui/IGraphicBufferProducer.h>
+
+#include <memory>
+
+#include <C2Buffer.h>
+
+namespace aidl::android::hardware::media::c2::implementation {
+
+// forward declarations
+class GraphicsTracker;
+
+struct GraphicBufferAllocator : public BnGraphicBufferAllocator {
+public:
+ // HAL interfaces
+ ::ndk::ScopedAStatus allocate(const IGraphicBufferAllocator::Description& in_desc,
+ IGraphicBufferAllocator::Allocation* _aidl_return) override;
+
+ ::ndk::ScopedAStatus deallocate(int64_t in_id, bool* _aidl_return) override;
+
+ ::ndk::ScopedAStatus getWaitableFds(
+ IGraphicBufferAllocator::WaitableFds* _aidl_return) override;
+
+ /**
+ * Configuring Surface/BufferQueue for the interface.
+ *
+ * Configure Surface, generation # and max dequeueBuffer() count for
+ * allocate interface.
+ *
+ * @param igbp Surface where to allocate.
+ * @param generation Generation # for allocations.
+ * @param maxDequeueBufferCount
+ * Maximum # of pending allocations.
+ */
+ bool configure(const ::android::sp<::android::IGraphicBufferProducer>& igbp,
+ uint32_t generation,
+ int maxDequeueBufferCount);
+
+ /**
+ * Update max dequeue buffer count of BufferQueue.
+ *
+ * BufferQueue does not update this value if count is smaller
+ * than the currently dequeued count.
+ * TODO: better to update the value inside this interface.
+ * for return value inspection from BQ, also for delayed updates.
+ *
+ * @param count the new value to update
+ */
+ void updateMaxDequeueBufferCount(int count);
+
+ void reset();
+
+ /**
+ * Create a listener for buffer being released.
+ *
+ * Surface will register this listener and notify whenever the consumer
+ * releases a buffer.
+ *
+ * @param generation generation # for the BufferQueue.
+ * @return IProducerListener can be used when connect# to Surface.
+ */
+ const ::android::sp<::android::IProducerListener> createReleaseListener(
+ uint32_t generation);
+
+ /**
+ * Notifies a buffer being released.
+ *
+ * @param generation generation # for the BufferQueue.
+ */
+ void onBufferReleased(uint32_t generation);
+
+ /**
+ * Allocates a buffer.
+ *
+ * @param width width of the requested buffer.
+ * @param height height of the requested buffer.
+ * @param format format of the requested buffer.
+ * @param usage usage of the requested buffer.
+ * @param buf out param for created buffer.
+ * @param fence out param for a pending fence.
+ *
+ * @return OK When an allocation was created.
+ * C2_BAD_STATE Client is not in the state for allocating
+ * C2_BLOCKING operation is blocked. Waitable fds can be
+ * used to know when it unblocks.
+ * C2_CORRUPTED Failed with a serious reason.
+ */
+ c2_status_t allocate(uint32_t width, uint32_t height,
+ ::android::PixelFormat format, uint64_t usage,
+ AHardwareBuffer **buf, ::android::sp<::android::Fence> *fence);
+
+ /**
+ * De-allocate a buffer.
+ *
+ * @param id unique id for a buffer.
+ * @param fence write fence if it's deallocated due to
+ * cancellation of displaying
+ */
+ bool deallocate(const uint64_t id, const ::android::sp<::android::Fence> &fence);
+
+ /**
+ * Display a graphic buffer to BufferQueue.
+ *
+ * @param block block to display to Surface.
+ * @param input input parameter for displaying.
+ * @param output out parameter from Surface.
+ */
+ c2_status_t displayBuffer(
+ const C2ConstGraphicBlock& block,
+ const ::android::IGraphicBufferProducer::QueueBufferInput& input,
+ ::android::IGraphicBufferProducer::QueueBufferOutput *output);
+
+ ~GraphicBufferAllocator();
+
+ /**
+ * Create the interface.
+ *
+ * The interface and codec instance's relationship is 1 to 1.
+ * The interface will be cretaed in the beginning of Codec createion. And
+ * lives until the instance destroyed.
+ *
+ * @param maxDequeueCount Initial max allocatable count
+ */
+ static std::shared_ptr<GraphicBufferAllocator> CreateGraphicBufferAllocator(
+ int maxDequeueCount);
+private:
+ GraphicBufferAllocator(int maxDequeueCount);
+
+ std::shared_ptr<GraphicsTracker> mGraphicsTracker;
+
+ friend class ::ndk::SharedRefBase;
+};
+
+} // namespace aidl::android::hardware::media::c2::implementation