media.c2 aidl: use aidl based PersistentSurface for c2 aidl
Test: m
Bug: 322870482
Merged-In: I035874efebe2ed6e11a418e8570671c41fead14f
Change-Id: I035874efebe2ed6e11a418e8570671c41fead14f
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 7bf4dcc..d14068d 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -26,6 +26,9 @@
#include <C2ParamInternal.h>
#include <C2PlatformSupport.h>
+#include <aidl/android/hardware/graphics/common/Dataspace.h>
+#include <aidl/android/media/IAidlGraphicBufferSource.h>
+#include <aidl/android/media/IAidlBufferSource.h>
#include <android/IOMXBufferSource.h>
#include <android/hardware/media/c2/1.0/IInputSurface.h>
#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
@@ -41,6 +44,10 @@
#include <media/openmax/OMX_IndexExt.h>
#include <media/stagefright/foundation/avc_utils.h>
#include <media/stagefright/foundation/AUtils.h>
+#include <media/stagefright/aidlpersistentsurface/AidlGraphicBufferSource.h>
+#include <media/stagefright/aidlpersistentsurface/C2NodeDef.h>
+#include <media/stagefright/aidlpersistentsurface/wrapper/Conversion.h>
+#include <media/stagefright/aidlpersistentsurface/wrapper/WAidlGraphicBufferSource.h>
#include <media/stagefright/omx/1.0/WGraphicBufferSource.h>
#include <media/stagefright/omx/OmxGraphicBufferSource.h>
#include <media/stagefright/CCodec.h>
@@ -51,6 +58,7 @@
#include <media/stagefright/RenderedFrameInfo.h>
#include <utils/NativeHandle.h>
+#include "C2AidlNode.h"
#include "C2OMXNode.h"
#include "CCodecBufferChannel.h"
#include "CCodecConfig.h"
@@ -65,8 +73,14 @@
using ::android::hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
using android::base::StringPrintf;
using ::android::hardware::media::c2::V1_0::IInputSurface;
+using ::aidl::android::media::IAidlBufferSource;
+using ::aidl::android::media::IAidlNode;
+using ::android::media::AidlGraphicBufferSource;
+using ::android::media::WAidlGraphicBufferSource;
+using ::android::media::aidl_conversion::fromAidlStatus;
typedef hardware::media::omx::V1_0::IGraphicBufferSource HGraphicBufferSource;
+typedef aidl::android::media::IAidlGraphicBufferSource AGraphicBufferSource;
typedef CCodecConfig Config;
namespace {
@@ -190,11 +204,11 @@
std::shared_ptr<Codec2Client::InputSurfaceConnection> mConnection;
};
-class GraphicBufferSourceWrapper : public InputSurfaceWrapper {
+class HGraphicBufferSourceWrapper : public InputSurfaceWrapper {
public:
typedef hardware::media::omx::V1_0::Status OmxStatus;
- GraphicBufferSourceWrapper(
+ HGraphicBufferSourceWrapper(
const sp<HGraphicBufferSource> &source,
uint32_t width,
uint32_t height,
@@ -203,7 +217,7 @@
mDataSpace = HAL_DATASPACE_BT709;
mConfig.mUsage = usage;
}
- ~GraphicBufferSourceWrapper() override = default;
+ ~HGraphicBufferSourceWrapper() override = default;
status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override {
mNode = new C2OMXNode(comp);
@@ -445,6 +459,224 @@
Config mConfig;
};
+class AGraphicBufferSourceWrapper : public InputSurfaceWrapper {
+public:
+ AGraphicBufferSourceWrapper(
+ const std::shared_ptr<AGraphicBufferSource> &source,
+ uint32_t width,
+ uint32_t height,
+ uint64_t usage)
+ : mSource(source), mWidth(width), mHeight(height) {
+ mDataSpace = HAL_DATASPACE_BT709;
+ mConfig.mUsage = usage;
+ }
+ ~AGraphicBufferSourceWrapper() override = default;
+
+ status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override {
+ mNode = ::ndk::SharedRefBase::make<C2AidlNode>(comp);
+ mNode->setFrameSize(mWidth, mHeight);
+ // Usage is queried during configure(), so setting it beforehand.
+ uint64_t usage = mConfig.mUsage;
+ (void)mNode->setConsumerUsage((int64_t)usage);
+
+ return fromAidlStatus(mSource->configure(
+ mNode, static_cast<::aidl::android::hardware::graphics::common::Dataspace>(
+ mDataSpace)));
+ }
+
+ void disconnect() override {
+ if (mNode == nullptr) {
+ return;
+ }
+ std::shared_ptr<IAidlBufferSource> source = mNode->getSource();
+ if (source == nullptr) {
+ ALOGD("GBSWrapper::disconnect: node is not configured with OMXBufferSource.");
+ return;
+ }
+ (void)source->onStop();
+ (void)source->onRelease();
+ mNode.reset();
+ }
+
+ status_t start() override {
+ std::shared_ptr<IAidlBufferSource> source = mNode->getSource();
+ if (source == nullptr) {
+ return NO_INIT;
+ }
+
+ size_t numSlots = 16;
+
+ IAidlNode::InputBufferParams param;
+ status_t err = fromAidlStatus(mNode->getInputBufferParams(¶m));
+ if (err == OK) {
+ numSlots = param.bufferCountActual;
+ }
+
+ for (size_t i = 0; i < numSlots; ++i) {
+ (void)source->onInputBufferAdded(i);
+ }
+
+ (void)source->onStart();
+ return OK;
+ }
+
+ status_t signalEndOfInputStream() override {
+ return fromAidlStatus(mSource->signalEndOfInputStream());
+ }
+
+ status_t configure(Config &config) {
+ std::stringstream status;
+ status_t err = OK;
+
+ // handle each configuration granually, in case we need to handle part of the configuration
+ // elsewhere
+
+ // TRICKY: we do not unset frame delay repeating
+ if (config.mMinFps > 0 && config.mMinFps != mConfig.mMinFps) {
+ int64_t us = 1e6 / config.mMinFps + 0.5;
+ status_t res = fromAidlStatus(mSource->setRepeatPreviousFrameDelayUs(us));
+ status << " minFps=" << config.mMinFps << " => repeatDelayUs=" << us;
+ if (res != OK) {
+ status << " (=> " << asString(res) << ")";
+ err = res;
+ }
+ mConfig.mMinFps = config.mMinFps;
+ }
+
+ // pts gap
+ if (config.mMinAdjustedFps > 0 || config.mFixedAdjustedFps > 0) {
+ if (mNode != nullptr) {
+ float gap = (config.mMinAdjustedFps > 0)
+ ? c2_min(INT32_MAX + 0., 1e6 / config.mMinAdjustedFps + 0.5)
+ : c2_max(0. - INT32_MAX, -1e6 / config.mFixedAdjustedFps - 0.5);
+ // float -> uint32_t is undefined if the value is negative.
+ // First convert to int32_t to ensure the expected behavior.
+ int32_t gapUs = int32_t(gap);
+ (void)mNode->setAdjustTimestampGapUs(gapUs);
+ }
+ }
+
+ // max fps
+ // TRICKY: we do not unset max fps to 0 unless using fixed fps
+ if ((config.mMaxFps > 0 || (config.mFixedAdjustedFps > 0 && config.mMaxFps == -1))
+ && config.mMaxFps != mConfig.mMaxFps) {
+ status_t res = fromAidlStatus(mSource->setMaxFps(config.mMaxFps));
+ status << " maxFps=" << config.mMaxFps;
+ if (res != OK) {
+ status << " (=> " << asString(res) << ")";
+ err = res;
+ }
+ mConfig.mMaxFps = config.mMaxFps;
+ }
+
+ if (config.mTimeOffsetUs != mConfig.mTimeOffsetUs) {
+ status_t res = fromAidlStatus(mSource->setTimeOffsetUs(config.mTimeOffsetUs));
+ status << " timeOffset " << config.mTimeOffsetUs << "us";
+ if (res != OK) {
+ status << " (=> " << asString(res) << ")";
+ err = res;
+ }
+ mConfig.mTimeOffsetUs = config.mTimeOffsetUs;
+ }
+
+ if (config.mCaptureFps != mConfig.mCaptureFps || config.mCodedFps != mConfig.mCodedFps) {
+ status_t res =
+ fromAidlStatus(mSource->setTimeLapseConfig(config.mCodedFps, config.mCaptureFps));
+ status << " timeLapse " << config.mCaptureFps << "fps as " << config.mCodedFps << "fps";
+ if (res != OK) {
+ status << " (=> " << asString(res) << ")";
+ err = res;
+ }
+ mConfig.mCaptureFps = config.mCaptureFps;
+ mConfig.mCodedFps = config.mCodedFps;
+ }
+
+ if (config.mStartAtUs != mConfig.mStartAtUs
+ || (config.mStopped != mConfig.mStopped && !config.mStopped)) {
+ status_t res = fromAidlStatus(mSource->setStartTimeUs(config.mStartAtUs));
+ status << " start at " << config.mStartAtUs << "us";
+ if (res != OK) {
+ status << " (=> " << asString(res) << ")";
+ err = res;
+ }
+ mConfig.mStartAtUs = config.mStartAtUs;
+ mConfig.mStopped = config.mStopped;
+ }
+
+ // suspend-resume
+ if (config.mSuspended != mConfig.mSuspended) {
+ status_t res = fromAidlStatus(mSource->setSuspend(
+ config.mSuspended, config.mSuspendAtUs));
+ status << " " << (config.mSuspended ? "suspend" : "resume")
+ << " at " << config.mSuspendAtUs << "us";
+ if (res != OK) {
+ status << " (=> " << asString(res) << ")";
+ err = res;
+ }
+ mConfig.mSuspended = config.mSuspended;
+ mConfig.mSuspendAtUs = config.mSuspendAtUs;
+ }
+
+ if (config.mStopped != mConfig.mStopped && config.mStopped) {
+ status_t res = fromAidlStatus(mSource->setStopTimeUs(config.mStopAtUs));
+ status << " stop at " << config.mStopAtUs << "us";
+ if (res != OK) {
+ status << " (=> " << asString(res) << ")";
+ err = res;
+ } else {
+ status << " delayUs";
+ res = fromAidlStatus(mSource->getStopTimeOffsetUs(&config.mInputDelayUs));
+ if (res != OK) {
+ status << " (=> " << asString(res) << ")";
+ } else {
+ status << "=" << config.mInputDelayUs << "us";
+ }
+ mConfig.mInputDelayUs = config.mInputDelayUs;
+ }
+ mConfig.mStopAtUs = config.mStopAtUs;
+ mConfig.mStopped = config.mStopped;
+ }
+
+ // color aspects (android._color-aspects)
+
+ // consumer usage is queried earlier.
+
+ // priority
+ if (mConfig.mPriority != config.mPriority) {
+ if (config.mPriority != INT_MAX) {
+ mNode->setPriority(config.mPriority);
+ }
+ mConfig.mPriority = config.mPriority;
+ }
+
+ if (status.str().empty()) {
+ ALOGD("ISConfig not changed");
+ } else {
+ ALOGD("ISConfig%s", status.str().c_str());
+ }
+ return err;
+ }
+
+ void onInputBufferDone(c2_cntr64_t index) override {
+ mNode->onInputBufferDone(index);
+ }
+
+ android_dataspace getDataspace() override {
+ return mNode->getDataspace();
+ }
+
+ uint32_t getPixelFormat() override {
+ return mNode->getPixelFormat();
+ }
+
+private:
+ std::shared_ptr<AGraphicBufferSource> mSource;
+ std::shared_ptr<C2AidlNode> mNode;
+ uint32_t mWidth;
+ uint32_t mHeight;
+ Config mConfig;
+};
+
class Codec2ClientInterfaceWrapper : public C2ComponentStore {
std::shared_ptr<Codec2Client> mClient;
@@ -1629,28 +1861,46 @@
}
sp<PersistentSurface> persistentSurface = CreateCompatibleInputSurface();
- sp<hidl::base::V1_0::IBase> hidlTarget = persistentSurface->getHidlTarget();
- sp<IInputSurface> hidlInputSurface = IInputSurface::castFrom(hidlTarget);
- sp<HGraphicBufferSource> gbs = HGraphicBufferSource::castFrom(hidlTarget);
-
- if (hidlInputSurface) {
- std::shared_ptr<Codec2Client::InputSurface> inputSurface =
- std::make_shared<Codec2Client::InputSurface>(hidlInputSurface);
- err = setupInputSurface(std::make_shared<C2InputSurfaceWrapper>(
- inputSurface));
- bufferProducer = inputSurface->getGraphicBufferProducer();
- } else if (gbs) {
- int32_t width = 0;
- (void)outputFormat->findInt32("width", &width);
- int32_t height = 0;
- (void)outputFormat->findInt32("height", &height);
- err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>(
- gbs, width, height, usage));
- bufferProducer = persistentSurface->getBufferProducer();
+ if (persistentSurface->isTargetAidl()) {
+ ::ndk::SpAIBinder aidlTarget = persistentSurface->getAidlTarget();
+ std::shared_ptr<AGraphicBufferSource> gbs = AGraphicBufferSource::fromBinder(aidlTarget);
+ if (gbs) {
+ int32_t width = 0;
+ (void)outputFormat->findInt32("width", &width);
+ int32_t height = 0;
+ (void)outputFormat->findInt32("height", &height);
+ err = setupInputSurface(std::make_shared<AGraphicBufferSourceWrapper>(
+ gbs, width, height, usage));
+ bufferProducer = persistentSurface->getBufferProducer();
+ } else {
+ ALOGE("Corrupted input surface(aidl)");
+ mCallback->onInputSurfaceCreationFailed(UNKNOWN_ERROR);
+ return;
+ }
} else {
- ALOGE("Corrupted input surface");
- mCallback->onInputSurfaceCreationFailed(UNKNOWN_ERROR);
- return;
+ sp<hidl::base::V1_0::IBase> hidlTarget = persistentSurface->getHidlTarget();
+ sp<IInputSurface> hidlInputSurface = IInputSurface::castFrom(hidlTarget);
+ sp<HGraphicBufferSource> gbs = HGraphicBufferSource::castFrom(hidlTarget);
+
+ if (hidlInputSurface) {
+ std::shared_ptr<Codec2Client::InputSurface> inputSurface =
+ std::make_shared<Codec2Client::InputSurface>(hidlInputSurface);
+ err = setupInputSurface(std::make_shared<C2InputSurfaceWrapper>(
+ inputSurface));
+ bufferProducer = inputSurface->getGraphicBufferProducer();
+ } else if (gbs) {
+ int32_t width = 0;
+ (void)outputFormat->findInt32("width", &width);
+ int32_t height = 0;
+ (void)outputFormat->findInt32("height", &height);
+ err = setupInputSurface(std::make_shared<HGraphicBufferSourceWrapper>(
+ gbs, width, height, usage));
+ bufferProducer = persistentSurface->getBufferProducer();
+ } else {
+ ALOGE("Corrupted input surface");
+ mCallback->onInputSurfaceCreationFailed(UNKNOWN_ERROR);
+ return;
+ }
}
if (err != OK) {
@@ -1745,33 +1995,56 @@
outputFormat = config->mOutputFormat;
usage = config->mISConfig ? config->mISConfig->mUsage : 0;
}
- sp<hidl::base::V1_0::IBase> hidlTarget = surface->getHidlTarget();
- sp<IInputSurface> inputSurface = IInputSurface::castFrom(hidlTarget);
- sp<HGraphicBufferSource> gbs = HGraphicBufferSource::castFrom(hidlTarget);
- if (inputSurface) {
- status_t err = setupInputSurface(std::make_shared<C2InputSurfaceWrapper>(
- std::make_shared<Codec2Client::InputSurface>(inputSurface)));
- if (err != OK) {
- ALOGE("Failed to set up input surface: %d", err);
- mCallback->onInputSurfaceDeclined(err);
- return;
- }
- } else if (gbs) {
- int32_t width = 0;
- (void)outputFormat->findInt32("width", &width);
- int32_t height = 0;
- (void)outputFormat->findInt32("height", &height);
- status_t err = setupInputSurface(std::make_shared<GraphicBufferSourceWrapper>(
- gbs, width, height, usage));
- if (err != OK) {
- ALOGE("Failed to set up input surface: %d", err);
- mCallback->onInputSurfaceDeclined(err);
+ if (surface->isTargetAidl()) {
+ ::ndk::SpAIBinder aidlTarget = surface->getAidlTarget();
+ std::shared_ptr<AGraphicBufferSource> gbs = AGraphicBufferSource::fromBinder(aidlTarget);
+ if (gbs) {
+ int32_t width = 0;
+ (void)outputFormat->findInt32("width", &width);
+ int32_t height = 0;
+ (void)outputFormat->findInt32("height", &height);
+
+ status_t err = setupInputSurface(std::make_shared<AGraphicBufferSourceWrapper>(
+ gbs, width, height, usage));
+ if (err != OK) {
+ ALOGE("Failed to set up input surface(aidl): %d", err);
+ mCallback->onInputSurfaceDeclined(err);
+ return;
+ }
+ } else {
+ ALOGE("Failed to set input surface(aidl): Corrupted surface.");
+ mCallback->onInputSurfaceDeclined(UNKNOWN_ERROR);
return;
}
} else {
- ALOGE("Failed to set input surface: Corrupted surface.");
- mCallback->onInputSurfaceDeclined(UNKNOWN_ERROR);
- return;
+ sp<hidl::base::V1_0::IBase> hidlTarget = surface->getHidlTarget();
+ sp<IInputSurface> inputSurface = IInputSurface::castFrom(hidlTarget);
+ sp<HGraphicBufferSource> gbs = HGraphicBufferSource::castFrom(hidlTarget);
+ if (inputSurface) {
+ status_t err = setupInputSurface(std::make_shared<C2InputSurfaceWrapper>(
+ std::make_shared<Codec2Client::InputSurface>(inputSurface)));
+ if (err != OK) {
+ ALOGE("Failed to set up input surface: %d", err);
+ mCallback->onInputSurfaceDeclined(err);
+ return;
+ }
+ } else if (gbs) {
+ int32_t width = 0;
+ (void)outputFormat->findInt32("width", &width);
+ int32_t height = 0;
+ (void)outputFormat->findInt32("height", &height);
+ status_t err = setupInputSurface(std::make_shared<HGraphicBufferSourceWrapper>(
+ gbs, width, height, usage));
+ if (err != OK) {
+ ALOGE("Failed to set up input surface: %d", err);
+ mCallback->onInputSurfaceDeclined(err);
+ return;
+ }
+ } else {
+ ALOGE("Failed to set input surface: Corrupted surface.");
+ mCallback->onInputSurfaceDeclined(UNKNOWN_ERROR);
+ return;
+ }
}
// Formats can change after setupInputSurface
sp<AMessage> inputFormat;
@@ -2663,15 +2936,32 @@
Codec2Client::CreateInputSurface();
if (!inputSurface) {
if (property_get_int32("debug.stagefright.c2inputsurface", 0) == -1) {
- sp<IGraphicBufferProducer> gbp;
- sp<OmxGraphicBufferSource> gbs = new OmxGraphicBufferSource();
- status_t err = gbs->initCheck();
- if (err != OK) {
- ALOGE("Failed to create persistent input surface: error %d", err);
- return nullptr;
+ if (Codec2Client::IsAidlSelected()) {
+ sp<IGraphicBufferProducer> gbp;
+ sp<AidlGraphicBufferSource> gbs = new AidlGraphicBufferSource();
+ status_t err = gbs->initCheck();
+ if (err != OK) {
+ ALOGE("Failed to create persistent input surface: error %d", err);
+ return nullptr;
+ }
+ ALOGD("aidl based PersistentSurface created");
+ std::shared_ptr<WAidlGraphicBufferSource> wrapper =
+ ::ndk::SharedRefBase::make<WAidlGraphicBufferSource>(gbs);
+
+ return new PersistentSurface(
+ gbs->getIGraphicBufferProducer(), wrapper->asBinder());
+ } else {
+ sp<IGraphicBufferProducer> gbp;
+ sp<OmxGraphicBufferSource> gbs = new OmxGraphicBufferSource();
+ status_t err = gbs->initCheck();
+ if (err != OK) {
+ ALOGE("Failed to create persistent input surface: error %d", err);
+ return nullptr;
+ }
+ ALOGD("hidl based PersistentSurface created");
+ return new PersistentSurface(
+ gbs->getIGraphicBufferProducer(), new TWGraphicBufferSource(gbs));
}
- return new PersistentSurface(
- gbs->getIGraphicBufferProducer(), new TWGraphicBufferSource(gbs));
} else {
return nullptr;
}