QCamera3: Drop stuck YUV buffers

Buffers in the internal YUV channel can get stuck and essentially
fail to return in case their corresponding input metadata buffer doesn't
arrive.
In case of lost metadata results, Hal should check on depending post-process
tasks and drop them accordingly.

Bug: 79174003
Test: Camera CTS
Change-Id: Id7c6c1aa851d7b812301eb0aabb20a2aef053c4d
diff --git a/msm8998/QCamera2/HAL3/QCamera3Channel.cpp b/msm8998/QCamera2/HAL3/QCamera3Channel.cpp
index ac6a600..0e3b4af 100644
--- a/msm8998/QCamera2/HAL3/QCamera3Channel.cpp
+++ b/msm8998/QCamera2/HAL3/QCamera3Channel.cpp
@@ -1041,6 +1041,41 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : postprocFail
+ *
+ * DESCRIPTION: notify clients about failing post-process requests.
+ *
+ * PARAMETERS :
+ * @ppBuffer  : pointer to the pp buffer.
+ *
+ * RETURN     : 0 on success
+ *              -EINVAL on invalid input
+ *==========================================================================*/
+int32_t QCamera3ProcessingChannel::postprocFail(qcamera_hal3_pp_buffer_t *ppBuffer) {
+    if (ppBuffer == nullptr) {
+        return BAD_VALUE;
+    }
+
+    if (ppBuffer->output == nullptr) {
+        return BAD_VALUE;
+    }
+
+    camera3_stream_buffer_t result = {};
+    result.buffer = ppBuffer->output;
+
+    LOGE("Input frame number: %d dropped!", ppBuffer->frameNumber);
+    result.stream = mCamera3Stream;
+    result.status = CAMERA3_BUFFER_STATUS_ERROR;
+    result.acquire_fence = -1;
+    result.release_fence = -1;
+    if (mChannelCB) {
+        mChannelCB(NULL, &result, ppBuffer->frameNumber, false, mUserData);
+    }
+
+    return OK;
+}
+
+/*===========================================================================
  * FUNCTION   : request
  *
  * DESCRIPTION: handle the request - either with an input buffer or a direct
@@ -3037,6 +3072,55 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : postprocFail
+ *
+ * DESCRIPTION: notify clients about failing post-process requests.
+ *
+ * PARAMETERS :
+ * @ppBuffer  : pointer to the pp buffer.
+ *
+ * RETURN     : 0 on success
+ *              -EINVAL on invalid input
+ *==========================================================================*/
+int32_t QCamera3YUVChannel::postprocFail(qcamera_hal3_pp_buffer_t *ppBuffer) {
+    if (ppBuffer == nullptr) {
+        return BAD_VALUE;
+    }
+
+    {
+        List<PpInfo>::iterator ppInfo;
+
+        Mutex::Autolock lock(mOfflinePpLock);
+        for (ppInfo = mOfflinePpInfoList.begin();
+                ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
+            if (ppInfo->frameNumber == ppBuffer->frameNumber) {
+                break;
+            }
+        }
+
+        if (ppInfo == mOfflinePpInfoList.end()) {
+            LOGE("Offline reprocess info for frame number: %d not found!", ppBuffer->frameNumber);
+            return BAD_VALUE;
+        }
+
+        LOGE("Failed YUV post-process on frame number: %d removing from offline queue!",
+                ppBuffer->frameNumber);
+        mOfflinePpInfoList.erase(ppInfo);
+    }
+
+    int32_t bufferIndex = mMemory.getHeapBufferIndex(ppBuffer->frameNumber);
+    if (bufferIndex < 0) {
+        LOGE("Fatal %d: no buffer index for frame number %d", bufferIndex, ppBuffer->frameNumber);
+        return BAD_VALUE;
+    } else {
+        mMemory.markFrameNumber(bufferIndex, -1);
+        mFreeHeapBufferList.push_back(bufferIndex);
+    }
+
+    return QCamera3ProcessingChannel::postprocFail(ppBuffer);
+}
+
+/*===========================================================================
  * FUNCTION   : streamCbRoutine
  *
  * DESCRIPTION:
diff --git a/msm8998/QCamera2/HAL3/QCamera3Channel.h b/msm8998/QCamera2/HAL3/QCamera3Channel.h
index a23acd5..11eb3d1 100644
--- a/msm8998/QCamera2/HAL3/QCamera3Channel.h
+++ b/msm8998/QCamera2/HAL3/QCamera3Channel.h
@@ -250,6 +250,7 @@
             QCamera3Stream *stream);
     int32_t getStreamSize(cam_dimension_t &dim);
     virtual int32_t timeoutFrame(uint32_t frameNumber);
+    virtual int32_t postprocFail(qcamera_hal3_pp_buffer_t *ppBuffer);
 
     QCamera3PostProcessor m_postprocessor; // post processor
     void showDebugFPS(int32_t streamType);
@@ -497,6 +498,7 @@
     virtual void putStreamBufs();
     virtual void reprocessCbRoutine(buffer_handle_t *resultBuffer,
         uint32_t resultFrameNumber);
+    virtual int32_t postprocFail(qcamera_hal3_pp_buffer_t *ppBuffer);
 
 private:
     typedef struct {
diff --git a/msm8998/QCamera2/HAL3/QCamera3HWI.cpp b/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
index 82ef37b..d7a432c 100644
--- a/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/msm8998/QCamera2/HAL3/QCamera3HWI.cpp
@@ -4132,6 +4132,7 @@
                     if(p_is_metabuf_queued != NULL) {
                         *p_is_metabuf_queued = true;
                     }
+                    iter->need_metadata = false;
                     break;
                 }
             }
@@ -4629,6 +4630,24 @@
         }
 
         if (errorResult) {
+            // Check for any buffers that might be stuck in the post-process input queue
+            // awaiting metadata and queue an empty meta buffer. The invalid data should
+            // fail the offline post-process pass and return any buffers that otherwise
+            // will become lost.
+            for (auto it = iter->buffers.begin(); it != iter->buffers.end(); it++) {
+                if (it->need_metadata) {
+                    QCamera3ProcessingChannel *channel =
+                        reinterpret_cast<QCamera3ProcessingChannel *> (it->stream->priv);
+                    if (channel != nullptr) {
+                        LOGE("Dropped result: %d Unblocking any pending pp buffers!",
+                                iter->frame_number);
+                        channel->queueReprocMetadata(nullptr);
+                    }
+                    it->need_metadata = false;
+                    break;
+                }
+            }
+
             notifyError(iter->frame_number, CAMERA3_MSG_ERROR_RESULT);
         } else {
             result.output_buffers = nullptr;
diff --git a/msm8998/QCamera2/HAL3/QCamera3PostProc.cpp b/msm8998/QCamera2/HAL3/QCamera3PostProc.cpp
index 82925aa..fc0d8fb 100644
--- a/msm8998/QCamera2/HAL3/QCamera3PostProc.cpp
+++ b/msm8998/QCamera2/HAL3/QCamera3PostProc.cpp
@@ -2173,6 +2173,7 @@
                             LOGE("no mem for qcamera_hal3_pp_data_t");
                             ret = -1;
                         } else if (meta_buffer == NULL) {
+                            pme->m_parent->postprocFail(pp_buffer);
                             LOGE("failed to dequeue from m_inputMetaQ");
                             ret = -1;
                         } else if (pp_buffer == NULL) {