Camera3: Send reprocess shutter notify and input buf after pproc

Send the reprocess shutter notify, and partial result with
the input buffer after the HAL has finished reading the input
buffer i.e. the pproc stage.
This unblocks future reprocess requests and enables parallelism
between the two reprocess stages - pproc and jpeg.
Note: This fixes a bug where the input before was returned while
the HAL was still using it

BUG=24497512
LACAM-1386

Ack by Tanmaya

Change-Id: I0587550572f66db6476f48653d7ab187a2ba1f56
diff --git a/QCamera2/HAL3/QCamera3Channel.cpp b/QCamera2/HAL3/QCamera3Channel.cpp
index ba640ea..ef9a50c 100644
--- a/QCamera2/HAL3/QCamera3Channel.cpp
+++ b/QCamera2/HAL3/QCamera3Channel.cpp
@@ -627,7 +627,9 @@
     }
 
     if (0 <= resultFrameNumber) {
-        mChannelCB(NULL, &result, (uint32_t)resultFrameNumber, mUserData);
+        if (mChannelCB) {
+            mChannelCB(NULL, &result, (uint32_t)resultFrameNumber, false, mUserData);
+        }
     } else {
         ALOGE("%s: Bad frame number", __func__);
     }
@@ -907,7 +909,7 @@
 
     mm_camera_buf_def_t meta_buf;
     cam_frame_len_offset_t offset = meta_planes.plane_info;
-    rc = mOfflineMetaMemory.getBufDef(offset, meta_buf, 0);
+    rc = mOfflineMetaMemory.getBufDef(offset, meta_buf, metaBufIdx);
     if (NO_ERROR != rc) {
         return rc;
     }
@@ -1263,7 +1265,10 @@
     if (NO_ERROR != rc) {
         ALOGE("%s: Error releasing offline memory %d", __func__, rc);
     }
-
+    /* Since reprocessing is done, send the callback to release the input buffer */
+    if (mChannelCB) {
+        mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
+    }
     issueChannelCb(resultBuffer, resultFrameNumber);
 
     return;
@@ -1293,7 +1298,9 @@
     result.acquire_fence = -1;
     result.release_fence = -1;
 
-    mChannelCB(NULL, &result, resultFrameNumber, mUserData);
+    if (mChannelCB) {
+        mChannelCB(NULL, &result, resultFrameNumber, false, mUserData);
+    }
 }
 
 /*===========================================================================
@@ -1696,7 +1703,9 @@
         ALOGE("%s: super_frame is not valid", __func__);
         return;
     }
-    mChannelCB(super_frame, NULL, requestNumber, mUserData);
+    if (mChannelCB) {
+        mChannelCB(super_frame, NULL, requestNumber, false, mUserData);
+    }
 }
 
 QCamera3StreamMem* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
@@ -2528,6 +2537,10 @@
         if (NO_ERROR != rc) {
             ALOGE("%s: Error releasing offline memory rc = %d", __func__, rc);
         }
+        /* Since reprocessing is done, send the callback to release the input buffer */
+        if (mChannelCB) {
+            mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
+        }
     }
 
     if (mBypass) {
@@ -2811,10 +2824,13 @@
             }
 
             CDBG("%s: Issue Callback", __func__);
-            obj->mChannelCB(NULL,
-                    &result,
-                    (uint32_t)resultFrameNumber,
-                    obj->mUserData);
+            if (obj->mChannelCB) {
+                obj->mChannelCB(NULL,
+                        &result,
+                        (uint32_t)resultFrameNumber,
+                        false,
+                        obj->mUserData);
+            }
 
             // release internal data for jpeg job
             if ((NULL != job->fwk_frame) || (NULL != job->fwk_src_buffer)) {
@@ -3440,6 +3456,7 @@
 {
     //Got the pproc data callback. Now send to jpeg encoding
     uint8_t frameIndex;
+    uint32_t resultFrameNumber;
     mm_camera_super_buf_t* frame = NULL;
     QCamera3ProcessingChannel *obj = (QCamera3ProcessingChannel *)inputChHandle;
 
@@ -3470,6 +3487,7 @@
     }
 
     if (mReprocessType == REPROCESS_TYPE_JPEG) {
+        resultFrameNumber =  mMemory->getFrameNumber(frameIndex);
         frame = (mm_camera_super_buf_t *)malloc(sizeof(mm_camera_super_buf_t));
         if (frame == NULL) {
            ALOGE("%s: Error allocating memory to save received_frame structure.",
@@ -3483,10 +3501,13 @@
             __func__, (uint32_t)frameIndex);
         *frame = *super_frame;
 
+        /* Since reprocessing is done, send the callback to release the input buffer */
+        if (mChannelCB) {
+            mChannelCB(NULL, NULL, resultFrameNumber, true, mUserData);
+        }
         obj->m_postprocessor.processPPData(frame);
     } else {
         buffer_handle_t *resultBuffer;
-        uint32_t resultFrameNumber;
         frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
         resultBuffer = (buffer_handle_t *)mGrallocMemory.getBufferHandle(frameIndex);
         resultFrameNumber = mGrallocMemory.getFrameNumber(frameIndex);
diff --git a/QCamera2/HAL3/QCamera3Channel.h b/QCamera2/HAL3/QCamera3Channel.h
index 6cb91c1..3bf4125 100644
--- a/QCamera2/HAL3/QCamera3Channel.h
+++ b/QCamera2/HAL3/QCamera3Channel.h
@@ -51,7 +51,8 @@
 
 typedef void (*channel_cb_routine)(mm_camera_super_buf_t *metadata,
                                 camera3_stream_buffer_t *buffer,
-                                uint32_t frame_number, void *userdata);
+                                uint32_t frame_number, bool isInputBuffer,
+                                void *userdata);
 class QCamera3Channel
 {
 public:
diff --git a/QCamera2/HAL3/QCamera3HWI.cpp b/QCamera2/HAL3/QCamera3HWI.cpp
index aeda643..f3e554a 100644
--- a/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/QCamera2/HAL3/QCamera3HWI.cpp
@@ -2511,8 +2511,6 @@
             }
         }
 
-        //TODO: batch handling for dropped metadata
-
         // Send empty metadata with already filled buffers for dropped metadata
         // and send valid metadata with already filled buffers for current metadata
         /* we could hit this case when we either
@@ -2520,36 +2518,9 @@
          * 2. miss a metadata buffer callback */
         if (i->frame_number < frame_number) {
             if (i->input_buffer) {
-                /* Clear notify_msg structure */
-                camera3_notify_msg_t notify_msg;
-                memset(&notify_msg, 0, sizeof(camera3_notify_msg_t));
-                notify_msg.type = CAMERA3_MSG_SHUTTER;
-                notify_msg.message.shutter.frame_number = i->frame_number;
-
-                i->partial_result_cnt++; //input request will not have urgent metadata
-                CameraMetadata settings;
-                if(i->settings) {
-                    settings = i->settings;
-                    if (settings.exists(ANDROID_SENSOR_TIMESTAMP)) {
-                        nsecs_t input_capture_time =
-                                settings.find(ANDROID_SENSOR_TIMESTAMP).data.i64[0];
-                        notify_msg.message.shutter.timestamp = (uint64_t)input_capture_time;
-                    } else {
-                        ALOGE("%s: No timestamp in input settings! Using current one.",
-                                __func__);
-                    }
-                } else {
-                    ALOGE("%s: Input settings missing!", __func__);
-                }
-                result.result = settings.release();
-                result.partial_result = i->partial_result_cnt;
-                CDBG("%s: Input request metadata notify frame_number = %u, capture_time = %llu",
-                       __func__, i->frame_number, notify_msg.message.shutter.timestamp);
-                mCallbackOps->notify(mCallbackOps, &notify_msg);
-                i->timestamp = (nsecs_t)notify_msg.message.shutter.timestamp;
-                CDBG("%s: Support notification !!!! notify frame_number = %u, capture_time = %llu",
-                        __func__, i->frame_number, notify_msg.message.shutter.timestamp);
-
+                /* this will be handled in handleInputBufferWithLock */
+                i++;
+                continue;
             } else {
                 ALOGE("%s: Fatal: Missing metadata buffer for frame number %d", __func__, i->frame_number);
                 if (free_and_bufdone_meta_buf) {
@@ -2692,7 +2663,7 @@
                         __func__, __LINE__, result.frame_number, i->timestamp);
             free_camera_metadata((camera_metadata_t *)result.result);
         }
-        // erase the element from the list
+
         i = erasePendingRequest(i);
 
         if (!mPendingReprocessResultList.empty()) {
@@ -2748,6 +2719,76 @@
         m_perfLock.lock_rel_timed();
     }
 }
+
+/*===========================================================================
+ * FUNCTION   : handleInputBufferWithLock
+ *
+ * DESCRIPTION: Handles input buffer and shutter callback with mMutex lock held.
+ *
+ * PARAMETERS : @frame_number: frame number of the input buffer
+ *
+ * RETURN     :
+ *
+ *==========================================================================*/
+void QCamera3HardwareInterface::handleInputBufferWithLock(uint32_t frame_number)
+{
+    ATRACE_CALL();
+    pendingRequestIterator i = mPendingRequestsList.begin();
+    while (i != mPendingRequestsList.end() && i->frame_number != frame_number){
+        i++;
+    }
+    if (i != mPendingRequestsList.end() && i->input_buffer) {
+        //found the right request
+        if (!i->shutter_notified) {
+            CameraMetadata settings;
+            camera3_notify_msg_t notify_msg;
+            memset(&notify_msg, 0, sizeof(camera3_notify_msg_t));
+            nsecs_t capture_time = systemTime(CLOCK_MONOTONIC);
+            if(i->settings) {
+                settings = i->settings;
+                if (settings.exists(ANDROID_SENSOR_TIMESTAMP)) {
+                    capture_time = settings.find(ANDROID_SENSOR_TIMESTAMP).data.i64[0];
+                } else {
+                    ALOGE("%s: No timestamp in input settings! Using current one.",
+                            __func__);
+                }
+            } else {
+                ALOGE("%s: Input settings missing!", __func__);
+            }
+
+            notify_msg.type = CAMERA3_MSG_SHUTTER;
+            notify_msg.message.shutter.frame_number = frame_number;
+            notify_msg.message.shutter.timestamp = (uint64_t)capture_time;
+            mCallbackOps->notify(mCallbackOps, &notify_msg);
+            i->shutter_notified = true;
+            CDBG("%s: Input request metadata notify frame_number = %u, capture_time = %llu",
+                       __func__, i->frame_number, notify_msg.message.shutter.timestamp);
+        }
+
+        if (i->input_buffer->release_fence != -1) {
+           int32_t rc = sync_wait(i->input_buffer->release_fence, TIMEOUT_NEVER);
+           close(i->input_buffer->release_fence);
+           if (rc != OK) {
+               ALOGE("%s: input buffer sync wait failed %d", __func__, rc);
+           }
+        }
+
+        camera3_capture_result result;
+        memset(&result, 0, sizeof(camera3_capture_result));
+        result.frame_number = frame_number;
+        result.result = i->settings;
+        result.input_buffer = i->input_buffer;
+        result.partial_result = PARTIAL_RESULT_COUNT;
+
+        mCallbackOps->process_capture_result(mCallbackOps, &result);
+        CDBG("%s: Input request metadata and input buffer frame_number = %u",
+                       __func__, i->frame_number);
+        i = erasePendingRequest(i);
+    } else {
+        ALOGE("%s: Could not find input request for frame number %d", __func__, frame_number);
+    }
+}
+
 /*===========================================================================
  * FUNCTION   : handleBufferWithLock
  *
@@ -2774,8 +2815,8 @@
         // Verify all pending requests frame_numbers are greater
         for (pendingRequestIterator j = mPendingRequestsList.begin();
                 j != mPendingRequestsList.end(); j++) {
-            if (j->frame_number < frame_number) {
-                ALOGE("%s: Error: pending frame number %d is smaller than %d",
+            if ((j->frame_number < frame_number) && !(j->input_buffer)) {
+                ALOGE("%s: Error: pending live frame number %d is smaller than %d",
                         __func__, j->frame_number, frame_number);
             }
         }
@@ -3415,6 +3456,7 @@
     extractJpegMetadata(mCurJpegMeta, request);
     pendingRequest.jpegMetadata = mCurJpegMeta;
     pendingRequest.settings = saveRequestSettings(mCurJpegMeta, request);
+    pendingRequest.shutter_notified = false;
 
     //extract capture intent
     if (meta.exists(ANDROID_CONTROL_CAPTURE_INTENT)) {
@@ -3453,6 +3495,7 @@
     mMetadataChannel->request(NULL, frameNumber);
 
     if(request->input_buffer != NULL){
+        CDBG("%s: Input request, frame_number %d", __func__, frameNumber);
         rc = setReprocParameters(request, &mReprocMeta, snapshotStreamId);
         if (NO_ERROR != rc) {
             ALOGE("%s: fail to set reproc parameters", __func__);
@@ -3772,7 +3815,7 @@
  * RETURN     : NONE
  *==========================================================================*/
 void QCamera3HardwareInterface::captureResultCb(mm_camera_super_buf_t *metadata_buf,
-                camera3_stream_buffer_t *buffer, uint32_t frame_number)
+                camera3_stream_buffer_t *buffer, uint32_t frame_number, bool isInputBuffer)
 {
     if (metadata_buf) {
         if (CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE == mOpMode) {
@@ -3785,6 +3828,10 @@
                     true /* free_and_bufdone_meta_buf */);
             pthread_mutex_unlock(&mMutex);
         }
+    } else if (isInputBuffer) {
+        pthread_mutex_lock(&mMutex);
+        handleInputBufferWithLock(frame_number);
+        pthread_mutex_unlock(&mMutex);
     } else {
         pthread_mutex_lock(&mMutex);
         handleBufferWithLock(buffer, frame_number);
@@ -8414,7 +8461,7 @@
  *==========================================================================*/
 void QCamera3HardwareInterface::captureResultCb(mm_camera_super_buf_t *metadata,
                 camera3_stream_buffer_t *buffer,
-                uint32_t frame_number, void *userdata)
+                uint32_t frame_number, bool isInputBuffer, void *userdata)
 {
     QCamera3HardwareInterface *hw = (QCamera3HardwareInterface *)userdata;
     if (hw == NULL) {
@@ -8422,7 +8469,7 @@
         return;
     }
 
-    hw->captureResultCb(metadata, buffer, frame_number);
+    hw->captureResultCb(metadata, buffer, frame_number, isInputBuffer);
     return;
 }
 
@@ -8825,7 +8872,7 @@
     QCamera3ReprocessChannel *pChannel = NULL;
 
     pChannel = new QCamera3ReprocessChannel(mCameraHandle->camera_handle,
-            mChannelHandle, mCameraHandle->ops, NULL, config.padding,
+            mChannelHandle, mCameraHandle->ops, captureResultCb, config.padding,
             CAM_QCOM_FEATURE_NONE, this, inputChHandle);
     if (NULL == pChannel) {
         ALOGE("%s: no mem for reprocess channel", __func__);
diff --git a/QCamera2/HAL3/QCamera3HWI.h b/QCamera2/HAL3/QCamera3HWI.h
index f2fbc98..75055b0 100644
--- a/QCamera2/HAL3/QCamera3HWI.h
+++ b/QCamera2/HAL3/QCamera3HWI.h
@@ -153,7 +153,7 @@
 
     static void captureResultCb(mm_camera_super_buf_t *metadata,
                 camera3_stream_buffer_t *buffer, uint32_t frame_number,
-                void *userdata);
+                bool isInputBuffer, void *userdata);
 
     int initialize(const camera3_callback_ops_t *callback_ops);
     int configureStreams(camera3_stream_configuration_t *stream_list);
@@ -187,7 +187,8 @@
     cam_denoise_process_type_t getTemporalDenoiseProcessPlate();
 
     void captureResultCb(mm_camera_super_buf_t *metadata,
-                camera3_stream_buffer_t *buffer, uint32_t frame_number);
+                camera3_stream_buffer_t *buffer, uint32_t frame_number,
+                bool isInputBuffer);
     cam_dimension_t calcMaxJpegDim();
     bool needOnlineRotation();
     uint32_t getJpegQuality();
@@ -234,6 +235,7 @@
             bool free_and_bufdone_meta_buf);
     void handleBufferWithLock(camera3_stream_buffer_t *buffer,
             uint32_t frame_number);
+    void handleInputBufferWithLock(uint32_t frame_number);
     void unblockRequestIfNecessary();
     void dumpMetadataToFile(tuning_params_t &meta, uint32_t &dumpFrameCount,
             bool enabled, const char *type, uint32_t frameNumber);
@@ -339,6 +341,7 @@
         uint8_t pipeline_depth;
         uint32_t partial_result_cnt;
         uint8_t capture_intent;
+        bool shutter_notified;
     } PendingRequestInfo;
     typedef struct {
         uint32_t frame_number;