CCodec: lock input surface for concurrent access
Bug: 351227733
Test: atest android.hardware.camera2.cts.RecordingTest
Test: atest android.mediav2.cts.CodecEncoderSurfaceTest
Change-Id: I552641100999f8efc33d1c6f218f23a77176d1d9
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index ae66a58..64d8f07 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -222,19 +222,20 @@
~HGraphicBufferSourceWrapper() override = default;
status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override {
- mNode = new C2OMXNode(comp);
- mOmxNode = new hardware::media::omx::V1_0::utils::TWOmxNode(mNode);
- mNode->setFrameSize(mWidth, mHeight);
+ Mutexed<sp<C2OMXNode>>::Locked node(mNode);
+ *node = new C2OMXNode(comp);
+ mOmxNode = new hardware::media::omx::V1_0::utils::TWOmxNode(*node);
+ (*node)->setFrameSize(mWidth, mHeight);
// Usage is queried during configure(), so setting it beforehand.
// 64 bit set parameter is existing only in C2OMXNode.
OMX_U64 usage64 = mConfig.mUsage;
- status_t res = mNode->setParameter(
+ status_t res = (*node)->setParameter(
(OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits64,
&usage64, sizeof(usage64));
if (res != OK) {
OMX_U32 usage = mConfig.mUsage & 0xFFFFFFFF;
- (void)mNode->setParameter(
+ (void)(*node)->setParameter(
(OMX_INDEXTYPE)OMX_IndexParamConsumerUsageBits,
&usage, sizeof(usage));
}
@@ -244,17 +245,18 @@
}
void disconnect() override {
- if (mNode == nullptr) {
+ Mutexed<sp<C2OMXNode>>::Locked node(mNode);
+ if ((*node) == nullptr) {
return;
}
- sp<IOMXBufferSource> source = mNode->getSource();
+ sp<IOMXBufferSource> source = (*node)->getSource();
if (source == nullptr) {
ALOGD("GBSWrapper::disconnect: node is not configured with OMXBufferSource.");
return;
}
source->onOmxIdle();
source->onOmxLoaded();
- mNode.clear();
+ node->clear();
mOmxNode.clear();
}
@@ -268,7 +270,11 @@
}
status_t start() override {
- sp<IOMXBufferSource> source = mNode->getSource();
+ Mutexed<sp<C2OMXNode>>::Locked node(mNode);
+ if ((*node) == nullptr) {
+ return NO_INIT;
+ }
+ sp<IOMXBufferSource> source = (*node)->getSource();
if (source == nullptr) {
return NO_INIT;
}
@@ -278,7 +284,7 @@
OMX_PARAM_PORTDEFINITIONTYPE param;
param.nPortIndex = kPortIndexInput;
- status_t err = mNode->getParameter(OMX_IndexParamPortDefinition,
+ status_t err = (*node)->getParameter(OMX_IndexParamPortDefinition,
¶m, sizeof(param));
if (err == OK) {
numSlots = param.nBufferCountActual;
@@ -297,6 +303,7 @@
}
status_t configure(Config &config) {
+ Mutexed<sp<C2OMXNode>>::Locked node(mNode);
std::stringstream status;
status_t err = OK;
@@ -317,7 +324,7 @@
// pts gap
if (config.mMinAdjustedFps > 0 || config.mFixedAdjustedFps > 0) {
- if (mNode != nullptr) {
+ if ((*node) != nullptr) {
OMX_PARAM_U32TYPE ptrGapParam = {};
ptrGapParam.nSize = sizeof(OMX_PARAM_U32TYPE);
float gap = (config.mMinAdjustedFps > 0)
@@ -326,7 +333,7 @@
// float -> uint32_t is undefined if the value is negative.
// First convert to int32_t to ensure the expected behavior.
ptrGapParam.nU32 = int32_t(gap);
- (void)mNode->setParameter(
+ (void)(*node)->setParameter(
(OMX_INDEXTYPE)OMX_IndexParamMaxFrameDurationForBitrateControl,
&ptrGapParam, sizeof(ptrGapParam));
}
@@ -426,8 +433,8 @@
// priority
if (mConfig.mPriority != config.mPriority) {
- if (config.mPriority != INT_MAX) {
- mNode->setPriority(config.mPriority);
+ if (config.mPriority != INT_MAX && (*node) != nullptr) {
+ (*node)->setPriority(config.mPriority);
}
mConfig.mPriority = config.mPriority;
}
@@ -441,24 +448,40 @@
}
void onInputBufferDone(c2_cntr64_t index) override {
- mNode->onInputBufferDone(index);
+ Mutexed<sp<C2OMXNode>>::Locked node(mNode);
+ if ((*node) == nullptr) {
+ return;
+ }
+ (*node)->onInputBufferDone(index);
}
void onInputBufferEmptied() override {
- mNode->onInputBufferEmptied();
+ Mutexed<sp<C2OMXNode>>::Locked node(mNode);
+ if ((*node) == nullptr) {
+ return;
+ }
+ (*node)->onInputBufferEmptied();
}
android_dataspace getDataspace() override {
- return mNode->getDataspace();
+ Mutexed<sp<C2OMXNode>>::Locked node(mNode);
+ if ((*node) == nullptr) {
+ return HAL_DATASPACE_UNKNOWN;
+ }
+ return (*node)->getDataspace();
}
uint32_t getPixelFormat() override {
- return mNode->getPixelFormat();
+ Mutexed<sp<C2OMXNode>>::Locked node(mNode);
+ if ((*node) == nullptr) {
+ return PIXEL_FORMAT_UNKNOWN;
+ }
+ return (*node)->getPixelFormat();
}
private:
sp<HGraphicBufferSource> mSource;
- sp<C2OMXNode> mNode;
+ Mutexed<sp<C2OMXNode>> mNode;
sp<hardware::media::omx::V1_0::IOmxNode> mOmxNode;
uint32_t mWidth;
uint32_t mHeight;
@@ -479,33 +502,39 @@
~AGraphicBufferSourceWrapper() override = default;
status_t connect(const std::shared_ptr<Codec2Client::Component> &comp) override {
- mNode = ::ndk::SharedRefBase::make<C2AidlNode>(comp);
- mNode->setFrameSize(mWidth, mHeight);
+ Mutexed<std::shared_ptr<C2AidlNode>>::Locked node(mNode);
+ *node = ::ndk::SharedRefBase::make<C2AidlNode>(comp);
+ (*node)->setFrameSize(mWidth, mHeight);
// Usage is queried during configure(), so setting it beforehand.
uint64_t usage = mConfig.mUsage;
- (void)mNode->setConsumerUsage((int64_t)usage);
+ (void)(*node)->setConsumerUsage((int64_t)usage);
return fromAidlStatus(mSource->configure(
- mNode, static_cast<::aidl::android::hardware::graphics::common::Dataspace>(
+ (*node), static_cast<::aidl::android::hardware::graphics::common::Dataspace>(
mDataSpace)));
}
void disconnect() override {
- if (mNode == nullptr) {
+ Mutexed<std::shared_ptr<C2AidlNode>>::Locked node(mNode);
+ if ((*node) == nullptr) {
return;
}
- std::shared_ptr<IAidlBufferSource> source = mNode->getSource();
+ std::shared_ptr<IAidlBufferSource> source = (*node)->getSource();
if (source == nullptr) {
ALOGD("GBSWrapper::disconnect: node is not configured with OMXBufferSource.");
return;
}
(void)source->onStop();
(void)source->onRelease();
- mNode.reset();
+ node->reset();
}
status_t start() override {
- std::shared_ptr<IAidlBufferSource> source = mNode->getSource();
+ Mutexed<std::shared_ptr<C2AidlNode>>::Locked node(mNode);
+ if ((*node) == nullptr) {
+ return NO_INIT;
+ }
+ std::shared_ptr<IAidlBufferSource> source = (*node)->getSource();
if (source == nullptr) {
return NO_INIT;
}
@@ -513,7 +542,7 @@
size_t numSlots = 16;
IAidlNode::InputBufferParams param;
- status_t err = fromAidlStatus(mNode->getInputBufferParams(¶m));
+ status_t err = fromAidlStatus((*node)->getInputBufferParams(¶m));
if (err == OK) {
numSlots = param.bufferCountActual;
}
@@ -531,6 +560,7 @@
}
status_t configure(Config &config) {
+ Mutexed<std::shared_ptr<C2AidlNode>>::Locked node(mNode);
std::stringstream status;
status_t err = OK;
@@ -551,14 +581,14 @@
// pts gap
if (config.mMinAdjustedFps > 0 || config.mFixedAdjustedFps > 0) {
- if (mNode != nullptr) {
+ if ((*node) != 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);
+ (void)(*node)->setAdjustTimestampGapUs(gapUs);
}
}
@@ -650,7 +680,7 @@
// priority
if (mConfig.mPriority != config.mPriority) {
if (config.mPriority != INT_MAX) {
- mNode->setPriority(config.mPriority);
+ (*node)->setPriority(config.mPriority);
}
mConfig.mPriority = config.mPriority;
}
@@ -664,24 +694,40 @@
}
void onInputBufferDone(c2_cntr64_t index) override {
- mNode->onInputBufferDone(index);
+ Mutexed<std::shared_ptr<C2AidlNode>>::Locked node(mNode);
+ if ((*node) == nullptr) {
+ return;
+ }
+ (*node)->onInputBufferDone(index);
}
void onInputBufferEmptied() override {
- mNode->onInputBufferEmptied();
+ Mutexed<std::shared_ptr<C2AidlNode>>::Locked node(mNode);
+ if ((*node) == nullptr) {
+ return;
+ }
+ (*node)->onInputBufferEmptied();
}
android_dataspace getDataspace() override {
- return mNode->getDataspace();
+ Mutexed<std::shared_ptr<C2AidlNode>>::Locked node(mNode);
+ if ((*node) == nullptr) {
+ return HAL_DATASPACE_UNKNOWN;
+ }
+ return (*node)->getDataspace();
}
uint32_t getPixelFormat() override {
- return mNode->getPixelFormat();
+ Mutexed<std::shared_ptr<C2AidlNode>>::Locked node(mNode);
+ if ((*node) == nullptr) {
+ return PIXEL_FORMAT_UNKNOWN;
+ }
+ return (*node)->getPixelFormat();
}
private:
std::shared_ptr<AGraphicBufferSource> mSource;
- std::shared_ptr<C2AidlNode> mNode;
+ Mutexed<std::shared_ptr<C2AidlNode>> mNode;
uint32_t mWidth;
uint32_t mHeight;
Config mConfig;
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index f0a4180..dd6782a 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -228,15 +228,17 @@
status_t CCodecBufferChannel::setInputSurface(
const std::shared_ptr<InputSurfaceWrapper> &surface) {
ALOGV("[%s] setInputSurface", mName);
- mInputSurface = surface;
- return mInputSurface->connect(mComponent);
+ Mutexed<std::shared_ptr<InputSurfaceWrapper>>::Locked inputSurface(mInputSurface);
+ *inputSurface = surface;
+ return (*inputSurface)->connect(mComponent);
}
status_t CCodecBufferChannel::signalEndOfInputStream() {
- if (mInputSurface == nullptr) {
+ Mutexed<std::shared_ptr<InputSurfaceWrapper>>::Locked inputSurface(mInputSurface);
+ if ((*inputSurface) == nullptr) {
return INVALID_OPERATION;
}
- return mInputSurface->signalEndOfInputStream();
+ return (*inputSurface)->signalEndOfInputStream();
}
status_t CCodecBufferChannel::queueInputBufferInternal(
@@ -1069,9 +1071,11 @@
return;
}
}
- if (android::media::codec::provider_->input_surface_throttle()
- && mInputSurface != nullptr) {
- mInputSurface->onInputBufferEmptied();
+ if (android::media::codec::provider_->input_surface_throttle()) {
+ Mutexed<std::shared_ptr<InputSurfaceWrapper>>::Locked inputSurface(mInputSurface);
+ if ((*inputSurface) != nullptr) {
+ (*inputSurface)->onInputBufferEmptied();
+ }
}
size_t numActiveSlots = 0;
while (!mPipelineWatcher.lock()->pipelineFull()) {
@@ -1689,7 +1693,7 @@
&& (hasCryptoOrDescrambler() || conforming)) {
input->buffers.reset(new SlotInputBuffers(mName));
} else if (graphic) {
- if (mInputSurface) {
+ if (mInputSurface.lock()->get()) {
input->buffers.reset(new DummyInputBuffers(mName));
} else if (mMetaMode == MODE_ANW) {
input->buffers.reset(new GraphicMetadataInputBuffers(mName));
@@ -1972,7 +1976,7 @@
status_t CCodecBufferChannel::prepareInitialInputBuffers(
std::map<size_t, sp<MediaCodecBuffer>> *clientInputBuffers, bool retry) {
- if (mInputSurface) {
+ if (mInputSurface.lock()->get()) {
return OK;
}
@@ -2098,9 +2102,7 @@
void CCodecBufferChannel::reset() {
stop();
- if (mInputSurface != nullptr) {
- mInputSurface.reset();
- }
+ mInputSurface.lock()->reset();
mPipelineWatcher.lock()->flush();
{
Mutexed<Input>::Locked input(mInput);
@@ -2195,7 +2197,7 @@
void CCodecBufferChannel::onInputBufferDone(
uint64_t frameIndex, size_t arrayIndex) {
- if (mInputSurface) {
+ if (mInputSurface.lock()->get()) {
return;
}
std::shared_ptr<C2Buffer> buffer =
@@ -2252,7 +2254,8 @@
notifyClient = false;
}
- if (mInputSurface == nullptr && (work->worklets.size() != 1u
+ bool hasInputSurface = (mInputSurface.lock()->get() != nullptr);
+ if (!hasInputSurface && (work->worklets.size() != 1u
|| !work->worklets.front()
|| !(work->worklets.front()->output.flags &
C2FrameData::FLAG_INCOMPLETE))) {
@@ -2461,7 +2464,7 @@
c2_cntr64_t timestamp =
worklet->output.ordinal.timestamp + work->input.ordinal.customOrdinal
- work->input.ordinal.timestamp;
- if (mInputSurface != nullptr) {
+ if (hasInputSurface) {
// When using input surface we need to restore the original input timestamp.
timestamp = work->input.ordinal.customOrdinal;
}
@@ -2788,7 +2791,7 @@
}
void CCodecBufferChannel::setInfoBuffer(const std::shared_ptr<C2InfoBuffer> &buffer) {
- if (mInputSurface == nullptr) {
+ if (mInputSurface.lock()->get() == nullptr) {
mInfoBuffers.push_back(buffer);
} else {
std::list<std::unique_ptr<C2Work>> items;
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index 94a5998..d4ccf7d 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -390,7 +390,7 @@
};
Mutexed<BlockPools> mBlockPools;
- std::shared_ptr<InputSurfaceWrapper> mInputSurface;
+ Mutexed<std::shared_ptr<InputSurfaceWrapper>> mInputSurface;
MetaMode mMetaMode;