CCodec: Stop using output surface on stop()
Stop using output surface when MediaCodec#stop() was called.
Bug: 227121136
Change-Id: I43849d48d6c7b6d2a2b32ba346b7e45ff830f2a9
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index 42b3c43..198894d 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -1586,6 +1586,23 @@
mOutputBufferQueue->updateMaxDequeueBufferCount(maxDequeueCount);
}
+void Codec2Client::Component::stopUsingOutputSurface(
+ C2BlockPool::local_id_t blockPoolId) {
+ mOutputBufferQueue->stop();
+ Return<Status> transStatus = mBase1_0->setOutputSurface(
+ static_cast<uint64_t>(blockPoolId), nullptr);
+ if (!transStatus.isOk()) {
+ LOG(ERROR) << "setOutputSurface(stopUsingOutputSurface) -- transaction failed.";
+ } else {
+ c2_status_t status =
+ static_cast<c2_status_t>(static_cast<Status>(transStatus));
+ if (status != C2_OK) {
+ LOG(DEBUG) << "setOutputSurface(stopUsingOutputSurface) -- call failed: "
+ << status << ".";
+ }
+ }
+}
+
c2_status_t Codec2Client::Component::connectToInputSurface(
const std::shared_ptr<InputSurface>& inputSurface,
std::shared_ptr<InputSurfaceConnection>* connection) {
diff --git a/media/codec2/hidl/client/include/codec2/hidl/client.h b/media/codec2/hidl/client/include/codec2/hidl/client.h
index 347e58a..afb89e6 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/client.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/client.h
@@ -411,6 +411,10 @@
// Set max dequeue count for output surface.
void setOutputSurfaceMaxDequeueCount(int maxDequeueCount);
+ // Stop using the current output surface.
+ void stopUsingOutputSurface(
+ C2BlockPool::local_id_t blockPoolId);
+
// Connect to a given InputSurface.
c2_status_t connectToInputSurface(
const std::shared_ptr<InputSurface>& inputSurface,
diff --git a/media/codec2/hidl/client/include/codec2/hidl/output.h b/media/codec2/hidl/client/include/codec2/hidl/output.h
index 877148a..a13edf3 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/output.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/output.h
@@ -50,6 +50,10 @@
int maxDequeueBufferCount,
std::shared_ptr<V1_2::SurfaceSyncObj> *syncObj);
+ // Stop using the current output surface. Pending buffer opeations will not
+ // perform anymore.
+ void stop();
+
// Render a graphic block to current surface.
status_t outputBuffer(
const C2ConstGraphicBlock& block,
@@ -81,6 +85,7 @@
sp<GraphicBuffer> mBuffers[BufferQueueDefs::NUM_BUFFER_SLOTS]; // find a better way
std::weak_ptr<_C2BlockPoolData> mPoolDatas[BufferQueueDefs::NUM_BUFFER_SLOTS];
std::shared_ptr<C2SurfaceSyncMemory> mSyncMem;
+ bool mStopped;
bool registerBuffer(const C2ConstGraphicBlock& block);
};
diff --git a/media/codec2/hidl/client/output.cpp b/media/codec2/hidl/client/output.cpp
index de34c24..f789030 100644
--- a/media/codec2/hidl/client/output.cpp
+++ b/media/codec2/hidl/client/output.cpp
@@ -169,7 +169,7 @@
} // unnamed namespace
OutputBufferQueue::OutputBufferQueue()
- : mGeneration{0}, mBqId{0} {
+ : mGeneration{0}, mBqId{0}, mStopped{false} {
}
OutputBufferQueue::~OutputBufferQueue() {
@@ -219,6 +219,8 @@
poolDatas[BufferQueueDefs::NUM_BUFFER_SLOTS];
{
std::scoped_lock<std::mutex> l(mMutex);
+ bool stopped = mStopped;
+ mStopped = false;
if (generation == mGeneration) {
// case of old BlockPool destruction
C2SyncVariables *var = mSyncMem ? mSyncMem->mem() : nullptr;
@@ -258,7 +260,7 @@
return false;
}
for (int i = 0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; ++i) {
- if (mBqId == 0 || !mBuffers[i]) {
+ if (mBqId == 0 || !mBuffers[i] || stopped) {
continue;
}
std::shared_ptr<_C2BlockPoolData> data = mPoolDatas[i].lock();
@@ -317,6 +319,12 @@
return true;
}
+void OutputBufferQueue::stop() {
+ std::scoped_lock<std::mutex> l(mMutex);
+ mStopped = true;
+ mOwner.reset(); // destructor of the block will not triger IGBP::cancel()
+}
+
bool OutputBufferQueue::registerBuffer(const C2ConstGraphicBlock& block) {
std::shared_ptr<_C2BlockPoolData> data =
_C2BlockFactory::GetGraphicBlockPoolData(block);
@@ -325,7 +333,7 @@
}
std::scoped_lock<std::mutex> l(mMutex);
- if (!mIgbp) {
+ if (!mIgbp || mStopped) {
return false;
}
@@ -371,11 +379,17 @@
std::shared_ptr<C2SurfaceSyncMemory> syncMem;
mMutex.lock();
+ bool stopped = mStopped;
sp<IGraphicBufferProducer> outputIgbp = mIgbp;
uint32_t outputGeneration = mGeneration;
syncMem = mSyncMem;
mMutex.unlock();
+ if (stopped) {
+ LOG(INFO) << "outputBuffer -- already stopped.";
+ return DEAD_OBJECT;
+ }
+
status_t status = attachToBufferQueue(
block, outputIgbp, outputGeneration, &bqSlot, syncMem);
@@ -408,12 +422,18 @@
std::shared_ptr<C2SurfaceSyncMemory> syncMem;
mMutex.lock();
+ bool stopped = mStopped;
sp<IGraphicBufferProducer> outputIgbp = mIgbp;
uint32_t outputGeneration = mGeneration;
uint64_t outputBqId = mBqId;
syncMem = mSyncMem;
mMutex.unlock();
+ if (stopped) {
+ LOG(INFO) << "outputBuffer -- already stopped.";
+ return DEAD_OBJECT;
+ }
+
if (!outputIgbp) {
LOG(VERBOSE) << "outputBuffer -- output surface is null.";
return NO_INIT;
@@ -467,7 +487,7 @@
mMutex.lock();
mMaxDequeueBufferCount = maxDequeueBufferCount;
auto syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
- if (syncVar) {
+ if (syncVar && !mStopped) {
syncVar->lock();
syncVar->updateMaxDequeueCountLocked(maxDequeueBufferCount);
syncVar->unlock();
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 62a1d02..159e885 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1570,6 +1570,14 @@
Mutexed<Output>::Locked output(mOutput);
output->buffers.reset();
}
+ if (mOutputSurface.lock()->surface) {
+ C2BlockPool::local_id_t outputPoolId;
+ {
+ Mutexed<BlockPools>::Locked pools(mBlockPools);
+ outputPoolId = pools->outputPoolId;
+ }
+ mComponent->stopUsingOutputSurface(outputPoolId);
+ }
}
void CCodecBufferChannel::release() {