Merge "QCamera2: HAL3: fix CTS testDynamicBlackWhiteLevel" into nyc-dev
am: 3ecb267128

* commit '3ecb267128d25fd3eae410bdc3173a165cd971f0':
  QCamera2: HAL3: fix CTS testDynamicBlackWhiteLevel

Change-Id: I5a4a39f1257b9928c279f9c0b0de4eff824c2470
diff --git a/camera/QCamera2/HAL3/QCamera3Channel.cpp b/camera/QCamera2/HAL3/QCamera3Channel.cpp
index 781fa88..52acc1c 100644
--- a/camera/QCamera2/HAL3/QCamera3Channel.cpp
+++ b/camera/QCamera2/HAL3/QCamera3Channel.cpp
@@ -1801,11 +1801,68 @@
     return QCamera3RegularChannel::initialize(isType);
 }
 
+#define GET_RAW_PIXEL(row_start,j) (row_start[5*(j/4)+j%4]<<2|((row_start[5*(j/4)+4]>>(j%4))&0x03))
+static void calculateBlacklevelForRaw10(mm_camera_buf_def_t *frame,
+    uint32_t stridebytes,
+    float (&fwk_blacklevel)[4],
+    int32_t opticalBlackRegions[4]){
+
+    int32_t left   = opticalBlackRegions[0];
+    int32_t right  = opticalBlackRegions[2];
+    int32_t top    = opticalBlackRegions[1];
+    int32_t bottom = opticalBlackRegions[3];
+    int32_t count  = 0;
+
+    fwk_blacklevel[0] = 0.0;
+    fwk_blacklevel[1] = 0.0;
+    fwk_blacklevel[2] = 0.0;
+    fwk_blacklevel[3] = 0.0;
+
+    for(int32_t i = top ; i < bottom ; i += 2){
+        uint8_t* row_start = (uint8_t *)frame->buffer + i * stridebytes;
+        for(int32_t j = left ; j < right ; j += 2){
+            count++;
+            fwk_blacklevel[0] += GET_RAW_PIXEL(row_start,j);
+            fwk_blacklevel[1] += GET_RAW_PIXEL(row_start,(j+1));
+            fwk_blacklevel[2] += GET_RAW_PIXEL((row_start+stridebytes),j);
+            fwk_blacklevel[3] += GET_RAW_PIXEL((row_start+stridebytes),(j+1));
+        }
+    }
+    fwk_blacklevel[0] = fwk_blacklevel[0]/count;
+    fwk_blacklevel[1] = fwk_blacklevel[1]/count;
+    fwk_blacklevel[2] = fwk_blacklevel[2]/count;
+    fwk_blacklevel[3] = fwk_blacklevel[3]/count;
+}
+
 void QCamera3RawChannel::streamCbRoutine(
                         mm_camera_super_buf_t *super_frame,
                         QCamera3Stream * stream)
 {
     ATRACE_CALL();
+    CDBG("%s, E.", __func__);
+    QCamera3HardwareInterface* hw = (QCamera3HardwareInterface*)mUserData;
+    int32_t opticalBlackRegions[4];
+
+    if (mIsRaw16 && hw->getBlackLevelRegion(opticalBlackRegions) == true) {
+        if (RAW_FORMAT == CAM_FORMAT_BAYER_MIPI_RAW_10BPP_GBRG) {
+            QCamera3HardwareInterface* hw = (QCamera3HardwareInterface*)mUserData;
+            uint32_t frame_number = 0;
+            float dynamic_blacklevel[4] = {0.0, 0.0, 0.0, 0.0};
+
+            cam_frame_len_offset_t offset;
+            memset(&offset, 0, sizeof(cam_frame_len_offset_t));
+            stream->getFrameOffset(offset);
+            calculateBlacklevelForRaw10(super_frame->bufs[0],(uint32_t)offset.mp[0].stride_in_bytes,
+                dynamic_blacklevel, opticalBlackRegions);
+            frame_number = mMemory.getFrameNumber((uint8_t)super_frame->bufs[0]->buf_idx);
+            CDBG("%s, frame_number:%d, dynamic black level (%f, %f, %f, %f)",
+                __func__, frame_number,
+                dynamic_blacklevel[0], dynamic_blacklevel[1],
+                dynamic_blacklevel[2], dynamic_blacklevel[3]);
+            hw->sendDynamicBlackLevel(dynamic_blacklevel, frame_number);
+        }
+    }
+
     /* Move this back down once verified */
     if (mRawDump)
         dumpRawSnapshot(super_frame->bufs[0]);
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.cpp b/camera/QCamera2/HAL3/QCamera3HWI.cpp
index 34fed36..59ef87b 100644
--- a/camera/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/camera/QCamera2/HAL3/QCamera3HWI.cpp
@@ -58,7 +58,7 @@
 #define DATA_PTR(MEM_OBJ,INDEX) MEM_OBJ->getPtr( INDEX )
 
 #define EMPTY_PIPELINE_DELAY 2
-#define PARTIAL_RESULT_COUNT 2
+#define PARTIAL_RESULT_COUNT 3
 #define FRAME_SKIP_DELAY     0
 #define CAM_MAX_SYNC_LATENCY 4
 
@@ -2423,6 +2423,7 @@
     int32_t frame_number_valid, urgent_frame_number_valid;
     uint32_t frame_number, urgent_frame_number;
     int64_t capture_time;
+    bool unfinished_raw_request = false;
 
     int32_t *p_frame_number_valid =
             POINTER_OF_META(CAM_INTF_META_FRAME_NUMBER_VALID, metadata);
@@ -2516,8 +2517,6 @@
         memset(&result, 0, sizeof(camera3_capture_result_t));
 
         CDBG("%s: frame_number in the list is %u", __func__, i->frame_number);
-        i->partial_result_cnt++;
-        result.partial_result = i->partial_result_cnt;
 
         // Check whether any stream buffer corresponding to this is dropped or not
         // If dropped, then send the ERROR_BUFFER for the corresponding stream
@@ -2562,6 +2561,20 @@
                 /* this will be handled in handleInputBufferWithLock */
                 i++;
                 continue;
+            } else if (i->need_dynamic_blklvl) {
+                unfinished_raw_request = true;
+                // i->partial_result_cnt--;
+                CDBG("%s, frame number:%d, partial_result:%d, unfinished raw request..",
+                        __func__, i->frame_number, i->partial_result_cnt);
+                i++;
+                continue;
+            } else if (i->pending_extra_result) {
+                CDBG("%s, frame_number:%d, partial_result:%d, need_dynamic_blklvl:%d",
+                        __func__, i->frame_number, i->partial_result_cnt,
+                        i->need_dynamic_blklvl);
+                // i->partial_result_cnt--;
+                i++;
+                continue;
             } else {
                 ALOGE("%s: Fatal: Missing metadata buffer for frame number %d", __func__, i->frame_number);
                 if (free_and_bufdone_meta_buf) {
@@ -2576,7 +2589,22 @@
                 goto done_metadata;
             }
         } else {
-            mPendingLiveRequest--;
+            i->partial_result_cnt++;
+            CDBG("%s, frame_number:%d, need_dynamic_blklvl:%d, partial cnt:%d\n",
+                    __func__, i->frame_number, i->need_dynamic_blklvl,
+                    i->partial_result_cnt);
+            if (!i->need_dynamic_blklvl) {
+                CDBG("%s, meta for request without raw, frame number: %d\n",
+                        __func__, i->frame_number);
+                if (!unfinished_raw_request) {
+                    i->partial_result_cnt++;
+                    CDBG("%s, no raw request pending, send the final (cnt:%d) partial result",
+                            __func__, i->partial_result_cnt);
+                }
+            }
+
+            result.partial_result = i->partial_result_cnt;
+
             /* Clear notify_msg structure */
             camera3_notify_msg_t notify_msg;
             memset(&notify_msg, 0, sizeof(camera3_notify_msg_t));
@@ -2607,7 +2635,7 @@
 
             result.result = translateFromHalMetadata(metadata,
                     i->timestamp, i->request_id, i->jpegMetadata, i->pipeline_depth,
-                    i->capture_intent, i->hybrid_ae_enable, internalPproc);
+                    i->capture_intent, i->hybrid_ae_enable, internalPproc, i->need_dynamic_blklvl);
 
             saveExifParams(metadata);
 
@@ -2694,22 +2722,31 @@
             }
             result.output_buffers = result_buffers;
             mCallbackOps->process_capture_result(mCallbackOps, &result);
-            CDBG("%s %d: meta frame_number = %u, capture_time = %lld",
-                    __func__, __LINE__, result.frame_number, i->timestamp);
+            CDBG("%s %d: meta frame_number = %u, capture_time = %lld, partial:%d",
+                    __func__, __LINE__, result.frame_number, i->timestamp, result.partial_result);
             free_camera_metadata((camera_metadata_t *)result.result);
             delete[] result_buffers;
         } else {
             mCallbackOps->process_capture_result(mCallbackOps, &result);
-            CDBG("%s %d: meta frame_number = %u, capture_time = %lld",
-                        __func__, __LINE__, result.frame_number, i->timestamp);
+            CDBG("%s %d: meta frame_number = %u, capture_time = %lld, partial:%d",
+                        __func__, __LINE__, result.frame_number, i->timestamp, result.partial_result);
             free_camera_metadata((camera_metadata_t *)result.result);
         }
 
-        i = erasePendingRequest(i);
+        if (i->partial_result_cnt == PARTIAL_RESULT_COUNT) {
+            mPendingLiveRequest--;
+            i = erasePendingRequest(i);
+        } else {
+            CDBG("%s, keep in list, frame number:%d, partial result:%d",
+                    __func__, i->frame_number, i->partial_result_cnt);
+            i->pending_extra_result = true;
+            i++;
+        }
 
         if (!mPendingReprocessResultList.empty()) {
             handlePendingReprocResults(frame_number + 1);
         }
+
     }
 
 done_metadata:
@@ -2830,6 +2867,104 @@
     }
 }
 
+bool QCamera3HardwareInterface::getBlackLevelRegion(int (&opticalBlackRegions)[4])
+{
+    if (gCamCapability[mCameraId]->optical_black_region_count > 0) {
+        /*just calculate one region black level and send to fwk*/
+        for (size_t i = 0; i <  4; i++) {
+            opticalBlackRegions[i] = gCamCapability[mCameraId]->optical_black_regions[i];
+        }
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+void QCamera3HardwareInterface::sendDynamicBlackLevel(float blacklevel[4], uint32_t frame_number)
+{
+    CDBG("%s, E.\n", __func__);
+    pthread_mutex_lock(&mMutex);
+    sendDynamicBlackLevelWithLock(blacklevel, frame_number);
+    pthread_mutex_unlock(&mMutex);
+    CDBG("%s, X.\n", __func__);
+}
+
+void QCamera3HardwareInterface::sendDynamicBlackLevelWithLock(float blacklevel[4], uint32_t frame_number)
+{
+    CDBG("%s, E. frame_number:%d\n", __func__, frame_number);
+
+    pendingRequestIterator i = mPendingRequestsList.begin();
+    while (i != mPendingRequestsList.end() && i->frame_number != frame_number){
+        i++;
+    }
+    if ((i == mPendingRequestsList.end()) || !i->need_dynamic_blklvl) {
+        ALOGE("%s, error: invalid frame number.", __func__);
+        return;
+    }
+
+    i->partial_result_cnt++;
+
+    CameraMetadata camMetadata;
+    int64_t fwk_frame_number = (int64_t)frame_number;
+    camMetadata.update(ANDROID_SYNC_FRAME_NUMBER, &fwk_frame_number, 1);
+
+    // update dynamic black level here
+    camMetadata.update(ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL, blacklevel, 4);
+
+    camera3_capture_result_t result;
+    memset(&result, 0, sizeof(camera3_capture_result_t));
+    result.frame_number = frame_number;
+    result.num_output_buffers = 0;
+    result.result = camMetadata.release();
+    result.partial_result = i->partial_result_cnt;
+
+    CDBG("%s, partial result:%d, frame_number:%d, pending extra result:%d\n",
+            __func__, result.partial_result, frame_number, i->pending_extra_result);
+    mCallbackOps->process_capture_result(mCallbackOps, &result);
+    free_camera_metadata((camera_metadata_t *)result.result);
+
+    if (i->partial_result_cnt == PARTIAL_RESULT_COUNT) {
+        CDBG("%s, remove cur request from pending list.", __func__);
+        mPendingLiveRequest--;
+        i = erasePendingRequest(i);
+
+        // traverse the remaining pending list to see whether need to send cached ones..
+        while (i != mPendingRequestsList.end()) {
+            CDBG("%s, frame number:%d, partial_result:%d, pending extra result:%d",
+                    __func__, i->frame_number, i->partial_result_cnt,
+                    i->pending_extra_result);
+
+            if ((i->partial_result_cnt == PARTIAL_RESULT_COUNT - 1)
+                    && (i->need_dynamic_blklvl == false) /* in case two consecutive raw requests */) {
+                // send out final result, and remove it from pending list.
+                CameraMetadata camMetadata;
+                int64_t fwk_frame_number = (int64_t)i->frame_number;
+                camMetadata.update(ANDROID_SYNC_FRAME_NUMBER, &fwk_frame_number, 1);
+
+                memset(&result, 0, sizeof(camera3_capture_result_t));
+                result.frame_number = i->frame_number;
+                result.num_output_buffers = 0;
+                result.result = camMetadata.release();
+                result.partial_result = i->partial_result_cnt + 1;
+
+                mCallbackOps->process_capture_result(mCallbackOps, &result);
+                free_camera_metadata((camera_metadata_t *)result.result);
+
+                mPendingLiveRequest--;
+                i = erasePendingRequest(i);
+                CDBG("%s, mPendingLiveRequest:%d, pending list size:%d",
+                        __func__, mPendingLiveRequest, mPendingRequestsList.size());
+            } else {
+                break;
+            }
+        }
+    }
+
+    unblockRequestIfNecessary();
+    CDBG("%s, X.mPendingLiveRequest = %d\n", __func__, mPendingLiveRequest);
+}
+
+
 /*===========================================================================
  * FUNCTION   : handleBufferWithLock
  *
@@ -2852,7 +2987,14 @@
     while (i != mPendingRequestsList.end() && i->frame_number != frame_number){
         i++;
     }
-    if (i == mPendingRequestsList.end()) {
+    if (i == mPendingRequestsList.end() || i->pending_extra_result == true) {
+        if (i != mPendingRequestsList.end()) {
+            // though the pendingRequestInfo is still in the list,
+            // still send the buffer directly, as the pending_extra_result is true,
+            // and we've already received meta for this frame number.
+            CDBG("%s, send the buffer directly, frame number:%d",
+                    __func__, i->frame_number);
+        }
         // Verify all pending requests frame_numbers are greater
         for (pendingRequestIterator j = mPendingRequestsList.begin();
                 j != mPendingRequestsList.end(); j++) {
@@ -3498,6 +3640,8 @@
     pendingRequest.jpegMetadata = mCurJpegMeta;
     pendingRequest.settings = saveRequestSettings(mCurJpegMeta, request);
     pendingRequest.shutter_notified = false;
+    pendingRequest.need_dynamic_blklvl = false;
+    pendingRequest.pending_extra_result = false;
 
     //extract capture intent
     if (meta.exists(ANDROID_CONTROL_CAPTURE_INTENT)) {
@@ -3529,6 +3673,13 @@
         CDBG("%s: frame = %d, buffer = %p, streamTypeMask = %d, stream format = %d",
                 __func__, frameNumber, bufferInfo.buffer,
                 channel->getStreamTypeMask(), bufferInfo.stream->format);
+
+        if (bufferInfo.stream->format == HAL_PIXEL_FORMAT_RAW16) {
+            if (gCamCapability[mCameraId]->optical_black_region_count > 0) {
+                CDBG("%s, frame_number:%d, need dynamic blacklevel", __func__, frameNumber);
+                pendingRequest.need_dynamic_blklvl = true;
+            }
+        }
     }
     mPendingBuffersMap.last_frame_number = frameNumber;
     latestRequest = mPendingRequestsList.insert(
@@ -4045,7 +4196,8 @@
                                  uint8_t pipeline_depth,
                                  uint8_t capture_intent,
                                  uint8_t hybrid_ae_enable,
-                                 bool pprocDone)
+                                 bool pprocDone,
+                                 bool dynamic_blklvl)
 {
     CameraMetadata camMetadata;
     camera_metadata_t *resultMetadata;
@@ -4201,14 +4353,17 @@
         camMetadata.update(QCAMERA3_SENSOR_DYNAMIC_BLACK_LEVEL_PATTERN, fwk_blackLevelInd, 4);
         camMetadata.update(NEXUS_EXPERIMENTAL_2015_SENSOR_DYNAMIC_BLACK_LEVEL, fwk_blackLevelInd, 4);
 
-        // Update the ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL
-        // Need convert the internal 16 bit depth to sensor 10 bit sensor raw
-        // depth space.
-        fwk_blackLevelInd[0] /= 64.0;
-        fwk_blackLevelInd[1] /= 64.0;
-        fwk_blackLevelInd[2] /= 64.0;
-        fwk_blackLevelInd[3] /= 64.0;
-        camMetadata.update(ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL, fwk_blackLevelInd, 4);
+        // if dynmaic_blklvl is true, we calculate blklvl from raw callback
+        // otherwise, use the value from linearization LUT.
+        if (dynamic_blklvl == false) {
+            // Need convert the internal 16 bit depth to sensor 10 bit sensor raw
+            // depth space.
+            fwk_blackLevelInd[0] /= 64.0;
+            fwk_blackLevelInd[1] /= 64.0;
+            fwk_blackLevelInd[2] /= 64.0;
+            fwk_blackLevelInd[3] /= 64.0;
+            camMetadata.update(ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL, fwk_blackLevelInd, 4);
+        }
     }
 
     // Fixed whitelevel is used by ISP/Sensor
@@ -5759,8 +5914,17 @@
     if (gCamCapability[cameraId]->optical_black_region_count != 0 &&
             gCamCapability[cameraId]->optical_black_region_count <= MAX_OPTICAL_BLACK_REGIONS) {
         int32_t opticalBlackRegions[MAX_OPTICAL_BLACK_REGIONS * 4];
-        for (size_t i = 0; i < gCamCapability[cameraId]->optical_black_region_count * 4; i++) {
+        for (size_t i = 0; i < gCamCapability[cameraId]->optical_black_region_count * 4; i+=4) {
+            // Left
             opticalBlackRegions[i] = gCamCapability[cameraId]->optical_black_regions[i];
+            //Top
+            opticalBlackRegions[i + 1] = gCamCapability[cameraId]->optical_black_regions[i + 1];
+            // Width
+            opticalBlackRegions[i + 2] = gCamCapability[cameraId]->optical_black_regions[i + 2] -
+                    gCamCapability[cameraId]->optical_black_regions[i];
+            // Height
+            opticalBlackRegions[i + 3] = gCamCapability[cameraId]->optical_black_regions[i + 3] -
+                    gCamCapability[cameraId]->optical_black_regions[i + 1];
         }
         staticInfo.update(ANDROID_SENSOR_OPTICAL_BLACK_REGIONS,
                 opticalBlackRegions, gCamCapability[cameraId]->optical_black_region_count * 4);
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.h b/camera/QCamera2/HAL3/QCamera3HWI.h
index ab7a513..0302b05 100644
--- a/camera/QCamera2/HAL3/QCamera3HWI.h
+++ b/camera/QCamera2/HAL3/QCamera3HWI.h
@@ -174,7 +174,7 @@
                             nsecs_t timestamp, int32_t request_id,
                             const CameraMetadata& jpegMetadata, uint8_t pipeline_depth,
                             uint8_t capture_intent, uint8_t hybrid_ae_enable,
-                            bool pprocDone);
+                            bool pprocDone, bool dynamic_blklvl);
     camera_metadata_t* saveRequestSettings(const CameraMetadata& jpegMetadata,
                             camera3_capture_request_t *request);
     int initParameters();
@@ -213,6 +213,9 @@
         cam_cds_mode_type_t val;
     } QCameraPropMap;
 
+    bool getBlackLevelRegion(int (&opticalBlackRegions)[4]);
+    void sendDynamicBlackLevel(float blacklevel[4], uint32_t frame_number);
+    void sendDynamicBlackLevelWithLock(float blacklevel[4], uint32_t frame_number);
 
 private:
 
@@ -344,6 +347,8 @@
         uint8_t capture_intent;
         bool shutter_notified;
         uint8_t hybrid_ae_enable;
+        bool need_dynamic_blklvl;
+        bool pending_extra_result;
     } PendingRequestInfo;
     typedef struct {
         uint32_t frame_number;