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/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();