camera: update AU_LINUX_ANDROID_LA.BF64.1.2.9.05.01.00.089.199

Camera3: Enable offline postprocessing for large YUV streams
QCamera2/HAL3: Silence dynamicblackLevel logs

Bug: 22843933
Change-Id: I28ae0512f1817736c3804e6fa2d2833b8681d2c8
diff --git a/QCamera2/Android.mk b/QCamera2/Android.mk
index 4de60e0..bb3e846 100644
--- a/QCamera2/Android.mk
+++ b/QCamera2/Android.mk
@@ -19,7 +19,8 @@
         HAL3/QCamera3Channel.cpp \
         HAL3/QCamera3VendorTags.cpp \
         HAL3/QCamera3PostProc.cpp \
-        HAL3/QCamera3CropRegionMapper.cpp
+        HAL3/QCamera3CropRegionMapper.cpp \
+        HAL3/QCamera3StreamMem.cpp
 
 #HAL 1.0 source
 LOCAL_SRC_FILES += \
diff --git a/QCamera2/HAL3/QCamera3Channel.cpp b/QCamera2/HAL3/QCamera3Channel.cpp
index cbe404e..eba928b 100644
--- a/QCamera2/HAL3/QCamera3Channel.cpp
+++ b/QCamera2/HAL3/QCamera3Channel.cpp
@@ -572,13 +572,16 @@
             QCamera3Channel(cam_handle, cam_ops, cb_routine,
                     paddingInfo, postprocess_mask, userData, numBuffers),
             m_postprocessor(this),
+            mMemory(numBuffers),
             mCamera3Stream(stream),
             mNumBufs(CAM_MAX_NUM_BUFS_PER_STREAM),
             mStreamType(stream_type),
             mPostProcStarted(false),
             mInputBufferConfig(false),
             m_pMetaChannel(metadataChannel),
-            mMetaFrame(NULL)
+            mMetaFrame(NULL),
+            mOfflineMemory(0),
+            mOfflineMetaMemory(1)
 {
     int32_t rc = m_postprocessor.init(&mMemory, mPostProcMask);
     if (rc != 0) {
@@ -638,26 +641,11 @@
     int32_t resultFrameNumber;
     camera3_stream_buffer_t result;
 
-    if (NULL == stream) {
-        ALOGE("%s: Invalid stream", __func__);
+    if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
+        ALOGE("%s: Error with the stream callback", __func__);
         return;
     }
 
-    if(NULL == super_frame) {
-         ALOGE("%s: Invalid Super buffer",__func__);
-         return;
-    }
-
-    if(super_frame->num_bufs != 1) {
-         ALOGE("%s: Multiple streams are not supported",__func__);
-         return;
-    }
-    if(NULL == super_frame->bufs[0]) {
-         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
-                  __func__);
-         return;
-    }
-
     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
     if(frameIndex >= mNumBufs) {
          ALOGE("%s: Error, Invalid index for buffer",__func__);
@@ -704,10 +692,10 @@
  *              output request
  *
  * PARAMETERS :
- * @buffer       : pointer to the output buffer
- * @frameNumber  : frame number of the request
- * @pInputBuffer : pointer to input buffer if an input request
- * @metadata     : parameters associated with the request
+ * @buffer          : pointer to the output buffer
+ * @frameNumber     : frame number of the request
+ * @pInputBuffer    : pointer to input buffer if an input request
+ * @metadata        : parameters associated with the request
  *
  * RETURN     : 0 on a success start of capture
  *              -EINVAL on invalid input
@@ -730,8 +718,10 @@
         //need to send to reprocessing
         CDBG("%s: Got a request with input buffer, output streamType = %d", __func__, mStreamType);
         reprocess_config_t reproc_cfg;
+        cam_dimension_t dim;
         memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
-        setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat);
+        memset(&dim, 0, sizeof(dim));
+        setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
         startPostProc((NULL != pInputBuffer), reproc_cfg);
 
         qcamera_fwk_input_pp_data_t *src_frame = NULL;
@@ -942,6 +932,44 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : checkStreamCbErrors
+ *
+ * DESCRIPTION: check the stream callback for errors
+ *
+ * PARAMETERS :
+ *   @super_frame : the super frame with filled buffer
+ *   @stream      : stream on which the buffer was requested and filled
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3ProcessingChannel::checkStreamCbErrors(mm_camera_super_buf_t *super_frame,
+        QCamera3Stream *stream)
+{
+    if (NULL == stream) {
+        ALOGE("%s: Invalid stream", __func__);
+        return BAD_VALUE;
+    }
+
+    if(NULL == super_frame) {
+         ALOGE("%s: Invalid Super buffer",__func__);
+         return BAD_VALUE;
+    }
+
+    if(super_frame->num_bufs != 1) {
+         ALOGE("%s: Multiple streams are not supported",__func__);
+         return BAD_VALUE;
+    }
+    if(NULL == super_frame->bufs[0]) {
+         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
+                  __func__);
+         return BAD_VALUE;
+    }
+    return NO_ERROR;
+}
+
+/*===========================================================================
  * FUNCTION   : getStreamBufs
  *
  * DESCRIPTION: get the buffers allocated to the stream
@@ -953,7 +981,7 @@
  *              NO_ERROR  -- success
  *              none-zero failure code
  *==========================================================================*/
-QCamera3Memory* QCamera3ProcessingChannel::getStreamBufs(uint32_t /*len*/)
+QCamera3StreamMem* QCamera3ProcessingChannel::getStreamBufs(uint32_t /*len*/)
 {
     return &mMemory;
 }
@@ -1101,7 +1129,10 @@
                 streamType = CAM_STREAM_TYPE_VIDEO;
                 streamFormat = VIDEO_FORMAT;
             } else if(stream->stream_type == CAMERA3_STREAM_INPUT ||
-                    stream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL){
+                    stream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL ||
+                    (stream->usage & GRALLOC_USAGE_HW_CAMERA_ZSL) ==
+                    GRALLOC_USAGE_HW_CAMERA_ZSL){
+                //TODO: Fix HW_CAMERA_ZSL check logic in other places as well
                 streamType = CAM_STREAM_TYPE_SNAPSHOT;
                 streamFormat = SNAPSHOT_FORMAT;
             } else {
@@ -1141,7 +1172,7 @@
 int32_t QCamera3ProcessingChannel::setReprocConfig(reprocess_config_t &reproc_cfg,
         camera3_stream_buffer_t *pInputBuffer,
         metadata_buffer_t *metadata,
-        cam_format_t streamFormat)
+        cam_format_t streamFormat, cam_dimension_t dim)
 {
     int32_t rc = 0;
     reproc_cfg.padding = mPaddingInfo;
@@ -1156,14 +1187,12 @@
         reproc_cfg.input_stream_dim.width = (int32_t)pInputBuffer->stream->width;
         reproc_cfg.input_stream_dim.height = (int32_t)pInputBuffer->stream->height;
     } else {
-        reproc_cfg.input_stream_dim.width = (int32_t)mCamera3Stream->width;
-        reproc_cfg.input_stream_dim.height = (int32_t)mCamera3Stream->height;
+        reproc_cfg.input_stream_dim.width = (int32_t)dim.width;
+        reproc_cfg.input_stream_dim.height = (int32_t)dim.height;
         reproc_cfg.src_channel = this;
     }
     reproc_cfg.output_stream_dim.width = mCamera3Stream->width;
     reproc_cfg.output_stream_dim.height = mCamera3Stream->height;
-    reproc_cfg.stream_type = mStreamType;
-    reproc_cfg.stream_format = streamFormat;
     reproc_cfg.reprocess_type = getReprocessType();
 
     //offset calculation
@@ -1175,35 +1204,36 @@
                     pInputBuffer->stream->format);
             return rc;
         }
-        CDBG("%s: reproc_cfg.stream_type = %d, reproc_cfg.stream_format = %d", __func__,
-                reproc_cfg.stream_type, reproc_cfg.stream_format);
-
-        switch (reproc_cfg.stream_type) {
-            case CAM_STREAM_TYPE_CALLBACK:
-            case CAM_STREAM_TYPE_PREVIEW:
-                rc = mm_stream_calc_offset_preview(streamFormat,
-                        &reproc_cfg.input_stream_dim,
-                        &reproc_cfg.input_stream_plane_info);
-                break;
-            case CAM_STREAM_TYPE_VIDEO:
-                rc = mm_stream_calc_offset_video(&reproc_cfg.input_stream_dim,
-                        &reproc_cfg.input_stream_plane_info);
-                break;
-            case CAM_STREAM_TYPE_RAW:
-                rc = mm_stream_calc_offset_raw(streamFormat, &reproc_cfg.input_stream_dim,
-                        reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
-                break;
-            case CAM_STREAM_TYPE_SNAPSHOT:
-            default:
-                rc = mm_stream_calc_offset_snapshot(streamFormat, &reproc_cfg.input_stream_dim,
-                        reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
-                break;
-        }
-        if (rc != 0) {
-            ALOGE("%s: Stream %d plane info calculation failed!", __func__, mStreamType);
-            return rc;
-        }
+    } else {
+        reproc_cfg.stream_type = mStreamType;
+        reproc_cfg.stream_format = streamFormat;
     }
+
+    switch (reproc_cfg.stream_type) {
+        case CAM_STREAM_TYPE_CALLBACK:
+        case CAM_STREAM_TYPE_PREVIEW:
+            rc = mm_stream_calc_offset_preview(streamFormat,
+                    &reproc_cfg.input_stream_dim,
+                    &reproc_cfg.input_stream_plane_info);
+            break;
+        case CAM_STREAM_TYPE_VIDEO:
+            rc = mm_stream_calc_offset_video(&reproc_cfg.input_stream_dim,
+                    &reproc_cfg.input_stream_plane_info);
+            break;
+        case CAM_STREAM_TYPE_RAW:
+            rc = mm_stream_calc_offset_raw(streamFormat, &reproc_cfg.input_stream_dim,
+                    reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
+            break;
+        case CAM_STREAM_TYPE_SNAPSHOT:
+        default:
+            rc = mm_stream_calc_offset_snapshot(streamFormat, &reproc_cfg.input_stream_dim,
+                    reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
+            break;
+    }
+    if (rc != 0) {
+        ALOGE("%s: Stream %d plane info calculation failed!", __func__, mStreamType);
+    }
+
     return rc;
 }
 
@@ -1235,6 +1265,7 @@
     result.release_fence = -1;
 
     mChannelCB(NULL, &result, resultFrameNumber, mUserData);
+
     return;
 }
 
@@ -1632,7 +1663,7 @@
     mChannelCB(super_frame, NULL, requestNumber, mUserData);
 }
 
-QCamera3Memory* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
+QCamera3StreamMem* QCamera3MetadataChannel::getStreamBufs(uint32_t len)
 {
     int rc;
     if (len < sizeof(metadata_buffer_t)) {
@@ -1642,7 +1673,7 @@
                 sizeof(metadata_buffer_t));
         return NULL;
     }
-    mMemory = new QCamera3HeapMemory();
+    mMemory = new QCamera3StreamMem(MIN_STREAMING_BUFFER_NUM);
     if (!mMemory) {
         ALOGE("%s: unable to create metadata memory", __func__);
         return NULL;
@@ -2011,12 +2042,12 @@
  *   @len       : Length of each buffer to be allocated
  *
  * RETURN     : NULL on buffer allocation failure
- *              QCamera3Memory object on sucess
+ *              QCamera3StreamMem object on sucess
  *==========================================================================*/
-QCamera3Memory* QCamera3RawDumpChannel::getStreamBufs(uint32_t len)
+QCamera3StreamMem* QCamera3RawDumpChannel::getStreamBufs(uint32_t len)
 {
     int rc;
-    mMemory = new QCamera3HeapMemory();
+    mMemory = new QCamera3StreamMem(mNumBuffers);
 
     if (!mMemory) {
         ALOGE("%s: unable to create heap memory", __func__);
@@ -2137,6 +2168,12 @@
                     paddingInfo, userData, stream, stream_type, postprocess_mask,
                     metadataChannel)
 {
+
+    mBypass = (postprocess_mask == CAM_QCOM_FEATURE_NONE);
+    mEdgeMode.edge_mode = CAM_EDGE_MODE_OFF;
+    mEdgeMode.sharpness = 0;
+    mNoiseRedMode = CAM_NOISE_REDUCTION_MODE_OFF;
+    memset(&mCropRegion, 0, sizeof(mCropRegion));
 }
 
 /*===========================================================================
@@ -2151,6 +2188,8 @@
  *==========================================================================*/
 QCamera3YUVChannel::~QCamera3YUVChannel()
 {
+   // Deallocation of heap buffers allocated in mMemory is freed
+   // automatically by its destructor
 }
 
 /*===========================================================================
@@ -2199,6 +2238,34 @@
             mNumBufs,
             mPostProcMask,
             mIsType);
+    if (rc < 0) {
+        ALOGE("%s: addStream failed", __func__);
+        return rc;
+    }
+
+    if (mBypass) {
+         // Allocate heap buffers up front
+        cam_stream_buf_plane_info_t buf_planes;
+        memset(&buf_planes, 0, sizeof(buf_planes));
+        rc = mm_stream_calc_offset_preview(mStreamFormat, &streamDim, &buf_planes);
+        if (rc < 0) {
+            ALOGE("%s: mm_stream_calc_offset_preview failed", __func__);
+            return rc;
+        }
+
+        // TODO: Do not queue heap buffers up front because we don't know whether
+        // heap buffers will be used or not. It depends on the actual request
+        rc = mMemory.allocate(mNumBuffers, buf_planes.plane_info.frame_len, false);
+        if (rc == NO_ERROR) {
+
+            Mutex::Autolock lock(mOfflinePpLock);
+            mFreeHeapBufferList.clear();
+
+            for (uint32_t i = 0; i < mNumBuffers; i++) {
+                mFreeHeapBufferList.push_back(i);
+            }
+        }
+    }
 
     return rc;
 }
@@ -2226,6 +2293,320 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : request
+ *
+ * DESCRIPTION: entry function for a request on a YUV stream. This function
+ *              has the logic to service a request based on its type
+ *
+ * PARAMETERS :
+ * @buffer          : pointer to the output buffer
+ * @frameNumber     : frame number of the request
+ * @pInputBuffer    : pointer to input buffer if an input request
+ * @metadata        : parameters associated with the request
+ *
+ * RETURN     : 0 on a success start of capture
+ *              -EINVAL on invalid input
+ *              -ENODEV on serious error
+ *==========================================================================*/
+int32_t QCamera3YUVChannel::request(buffer_handle_t *buffer,
+        uint32_t frameNumber,
+        camera3_stream_buffer_t* pInputBuffer,
+        metadata_buffer_t* metadata, bool &needMetadata)
+{
+    int32_t rc = NO_ERROR;
+    int index;
+    Mutex::Autolock lock(mOfflinePpLock);
+
+    CDBG("%s: pInputBuffer is %p", __func__, pInputBuffer);
+    CDBG("%s, frame number %d", __func__, frameNumber);
+    if (NULL == buffer || NULL == metadata) {
+        ALOGE("%s: Invalid buffer/metadata in channel request", __func__);
+        return BAD_VALUE;
+    }
+
+    PpInfo ppInfo;
+    memset(&ppInfo, 0, sizeof(ppInfo));
+    ppInfo.frameNumber = frameNumber;
+    ppInfo.offlinePpFlag = false;
+    if (mBypass && !pInputBuffer ) {
+        ppInfo.offlinePpFlag = needsFramePostprocessing(metadata);
+        ppInfo.output = buffer;
+        mOfflinePpInfoList.push_back(ppInfo);
+    }
+
+    CDBG("%s: offlinePpFlag is %d", __func__, ppInfo.offlinePpFlag);
+    needMetadata = ppInfo.offlinePpFlag;
+    if (!ppInfo.offlinePpFlag) {
+        // regular request
+        return QCamera3ProcessingChannel::request(buffer, frameNumber, pInputBuffer, metadata);
+    } else {
+        //we need to send this frame through the CPP
+        //Allocate heap memory, then buf done on the buffer
+        if (mFreeHeapBufferList.empty()) {
+            ALOGE("%s: mFreeHeapBufferList is null. Fatal", __func__);
+            return BAD_VALUE;
+        }
+
+        /* Configure and start postproc if necessary */
+        reprocess_config_t reproc_cfg;
+        cam_dimension_t dim;
+        memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
+        memset(&dim, 0, sizeof(dim));
+        mStreams[0]->getFrameDimension(dim);
+        setReprocConfig(reproc_cfg, NULL, metadata, mStreamFormat, dim);
+
+        // Start postprocessor without input buffer
+        startPostProc(false, reproc_cfg);
+
+        uint32_t bufIdx = *(mFreeHeapBufferList.begin());
+        mFreeHeapBufferList.erase(mFreeHeapBufferList.begin());
+        CDBG("%s: erasing %d", __func__, bufIdx);
+
+        mMemory.markFrameNumber(bufIdx, frameNumber);
+        mStreams[0]->bufDone(bufIdx);
+    }
+    return rc;
+}
+
+/*===========================================================================
+ * FUNCTION   : streamCbRoutine
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS :
+ * @super_frame : the super frame with filled buffer
+ * @stream      : stream on which the buffer was requested and filled
+ *
+ * RETURN     : none
+ *==========================================================================*/
+void QCamera3YUVChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
+        QCamera3Stream *stream)
+{
+    ATRACE_CALL();
+    uint8_t frameIndex;
+    int32_t resultFrameNumber;
+
+    if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
+        ALOGE("%s: Error with the stream callback", __func__);
+        return;
+    }
+
+    frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
+    if(frameIndex >= mNumBufs) {
+         ALOGE("%s: Error, Invalid index for buffer",__func__);
+         stream->bufDone(frameIndex);
+         return;
+    }
+
+    if (mBypass) {
+        List<PpInfo>::iterator ppInfo;
+
+        Mutex::Autolock lock(mOfflinePpLock);
+        resultFrameNumber = mMemory.getFrameNumber(frameIndex);
+        for (ppInfo = mOfflinePpInfoList.begin();
+                ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
+            if (ppInfo->frameNumber == (uint32_t)resultFrameNumber) {
+                break;
+            }
+        }
+        CDBG("%s, frame index %d, frame number %d", __func__, frameIndex, resultFrameNumber);
+        //check the reprocessing required flag against the frame number
+        if (ppInfo == mOfflinePpInfoList.end()) {
+            ALOGE("%s: Error, request for frame number is a reprocess.", __func__);
+            stream->bufDone(frameIndex);
+            return;
+        }
+
+        if (ppInfo->offlinePpFlag) {
+            mm_camera_super_buf_t *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.",
+                        __func__);
+                if(stream) {
+                    stream->bufDone(frameIndex);
+                }
+                return;
+            }
+
+            *frame = *super_frame;
+            m_postprocessor.processData(frame, ppInfo->output, resultFrameNumber);
+            free(super_frame);
+            return;
+        } else {
+            if (ppInfo != mOfflinePpInfoList.begin()) {
+                // There is pending reprocess buffer, cache current buffer
+                if (ppInfo->callback_buffer != NULL) {
+                    ALOGE("%s: Fatal: cached callback_buffer is already present",
+                        __func__);
+
+                }
+                ppInfo->callback_buffer = super_frame;
+                return;
+            } else {
+                mOfflinePpInfoList.erase(ppInfo);
+            }
+        }
+    }
+
+    QCamera3ProcessingChannel::streamCbRoutine(super_frame, stream);
+    return;
+}
+
+/*===========================================================================
+ * FUNCTION   : reprocessCbRoutine
+ *
+ * DESCRIPTION: callback function for the reprocessed frame. This frame now
+ *              should be returned to the framework. This same callback is
+ *              used during input reprocessing or offline postprocessing
+ *
+ * PARAMETERS :
+ * @resultBuffer      : buffer containing the reprocessed data
+ * @resultFrameNumber : frame number on which the buffer was requested
+ *
+ * RETURN     : NONE
+ *
+ *==========================================================================*/
+void QCamera3YUVChannel::reprocessCbRoutine(buffer_handle_t *resultBuffer,
+        uint32_t resultFrameNumber)
+{
+    CDBG("%s E: frame number %d", __func__, resultFrameNumber);
+    Vector<mm_camera_super_buf_t *> pendingCbs;
+
+    if (mBypass) {
+        int32_t rc = handleOfflinePpCallback(resultFrameNumber, pendingCbs);
+        if (rc != NO_ERROR) {
+            return;
+        }
+    }
+
+    // Call all pending callbacks to return buffers
+    for (size_t i = 0; i < pendingCbs.size(); i++) {
+        QCamera3ProcessingChannel::streamCbRoutine(
+                pendingCbs[i], mStreams[0]);
+    }
+
+
+    QCamera3ProcessingChannel::reprocessCbRoutine(
+            resultBuffer, resultFrameNumber);
+}
+
+/*===========================================================================
+ * FUNCTION   : needsFramePostprocessing
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS :
+ *
+ * RETURN     :
+ *  TRUE if frame needs to be postprocessed
+ *  FALSE is frame does not need to be postprocessed
+ *
+ *==========================================================================*/
+bool QCamera3YUVChannel::needsFramePostprocessing(metadata_buffer_t *meta)
+{
+    bool ppNeeded = false;
+
+    //sharpness
+    IF_META_AVAILABLE(cam_edge_application_t, edgeMode, CAM_INTF_META_EDGE_MODE, meta) {
+        mEdgeMode = *edgeMode;
+    }
+
+    //wnr
+    IF_META_AVAILABLE(uint32_t, noiseRedMode, CAM_INTF_META_NOISE_REDUCTION_MODE, meta) {
+        mNoiseRedMode = *noiseRedMode;
+    }
+
+    IF_META_AVAILABLE(cam_crop_region_t, scalerCropRegion, CAM_INTF_META_SCALER_CROP_REGION, meta) {
+        //check the crop against the max downscale factor and then set ppNeeded
+        //gCamCapability[cameraId]->max_downscale_factor
+    }
+
+    if (!(CAM_EDGE_MODE_OFF == mEdgeMode.edge_mode) ||
+            (CAM_EDGE_MODE_ZERO_SHUTTER_LAG == mEdgeMode.edge_mode)) {
+        ppNeeded = true;
+    }
+    if (!((CAM_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG == mNoiseRedMode) ||
+             (CAM_NOISE_REDUCTION_MODE_OFF == mNoiseRedMode))) {
+        ppNeeded = true;
+    }
+
+    return ppNeeded;
+}
+
+/*===========================================================================
+ * FUNCTION   : handleOfflinePpCallback
+ *
+ * DESCRIPTION: callback function for the reprocessed frame from offline
+ *              postprocessing.
+ *
+ * PARAMETERS :
+ * @resultFrameNumber : frame number on which the buffer was requested
+ * @pendingCbs        : pending buffers to be returned first
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3YUVChannel::handleOfflinePpCallback(uint32_t resultFrameNumber,
+            Vector<mm_camera_super_buf_t *>& pendingCbs)
+{
+    Mutex::Autolock lock(mOfflinePpLock);
+    List<PpInfo>::iterator ppInfo;
+
+    for (ppInfo = mOfflinePpInfoList.begin();
+            ppInfo != mOfflinePpInfoList.end(); ppInfo++) {
+        if (ppInfo->frameNumber == resultFrameNumber) {
+            break;
+        }
+    }
+
+    if (ppInfo == mOfflinePpInfoList.end()) {
+        ALOGI("%s: Request of frame number %d is reprocessing",
+                __func__, resultFrameNumber);
+        return NO_ERROR;
+    }
+
+    // Return pending buffer callbacks
+    while (ppInfo != mOfflinePpInfoList.begin()) {
+        List<PpInfo>::iterator pending = mOfflinePpInfoList.begin();
+
+        // Call streamCbRoutine for cached callbacks
+        if (!(pending->callback_buffer)) {
+            ALOGE("%s: Fatal: cached callback info  is NULL.", __func__);
+            return BAD_VALUE;
+        }
+
+        pendingCbs.push_back(pending->callback_buffer);
+
+        mOfflinePpInfoList.erase(pending);
+    }
+
+    if (ppInfo->offlinePpFlag) {
+        // Need to get the input buffer frame index from the
+        // mMemory object and add that to the free heap buffers list.
+        int32_t bufferIndex =
+                mMemory.getHeapBufferIndex(resultFrameNumber);
+        if (bufferIndex < 0) {
+            ALOGE("%s: Fatal %d: no buffer index for frame number %d",
+                    __func__, bufferIndex, resultFrameNumber);
+            return BAD_VALUE;
+        }
+        mFreeHeapBufferList.push_back(bufferIndex);
+        mOfflinePpInfoList.erase(ppInfo);
+
+    } else {
+        ALOGE("%s: Fatal: request of frame number %d doesn't need"
+                " offline postprocessing. However there is"
+                " reprocessing callback.", __func__,
+                resultFrameNumber);
+        return BAD_VALUE;
+    }
+
+    return NO_ERROR;
+}
+
+/*===========================================================================
  * FUNCTION   : getReprocessType
  *
  * DESCRIPTION: get the type of reprocess output supported by this channel
@@ -2403,7 +2784,6 @@
                                 paddingInfo, userData, stream, CAM_STREAM_TYPE_SNAPSHOT,
                                 postprocess_mask, metadataChannel, numBuffers),
                         mNumSnapshotBufs(0),
-                        mCurrentBufIndex(-1),
                         mYuvMemory(NULL)
 {
     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
@@ -2500,19 +2880,13 @@
     int32_t rc = NO_ERROR;
 
     reprocess_config_t reproc_cfg;
+    cam_dimension_t dim;
     memset(&reproc_cfg, 0, sizeof(reprocess_config_t));
-    setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat);
     //make sure to set the correct input stream dim in case of YUV size override
     //and recalculate the plane info
-    if (pInputBuffer == NULL) {
-       reproc_cfg.input_stream_dim.width = (int32_t)mYuvWidth;
-       reproc_cfg.input_stream_dim.height = (int32_t)mYuvHeight;
-       rc = mm_stream_calc_offset_snapshot(mStreamFormat, &reproc_cfg.input_stream_dim,
-               reproc_cfg.padding, &reproc_cfg.input_stream_plane_info);
-       if (rc != 0) {
-        ALOGE("%s: Stream %d plane info calculation failed!", __func__, mStreamType);
-       }
-    }
+    dim.width = (int32_t)mYuvWidth;
+    dim.height = (int32_t)mYuvHeight;
+    setReprocConfig(reproc_cfg, pInputBuffer, metadata, mStreamFormat, dim);
 
     // Picture stream has already been started before any request comes in
     if (!m_bIsActive) {
@@ -2540,9 +2914,6 @@
 
     rc = mMemory.markFrameNumber((uint32_t)index, frameNumber);
 
-    //Start the postprocessor for jpeg encoding. Pass mMemory as dest buffer
-    mCurrentBufIndex = (uint32_t)index;
-
     // Start postprocessor
     startPostProc((NULL != pInputBuffer), reproc_cfg);
 
@@ -2625,6 +2996,17 @@
     return;
 }
 
+/*===========================================================================
+ * FUNCTION   : streamCbRoutine
+ *
+ * DESCRIPTION:
+ *
+ * PARAMETERS :
+ * @super_frame : the super frame with filled buffer
+ * @stream      : stream on which the buffer was requested and filled
+ *
+ * RETURN     : none
+ *==========================================================================*/
 void QCamera3PicChannel::streamCbRoutine(mm_camera_super_buf_t *super_frame,
                             QCamera3Stream *stream)
 {
@@ -2636,19 +3018,10 @@
     //Got the yuv callback. Calling yuv callback handler in PostProc
     uint8_t frameIndex;
     mm_camera_super_buf_t* frame = NULL;
-    if(!super_frame) {
-         ALOGE("%s: Invalid Super buffer",__func__);
-         return;
-    }
 
-    if(super_frame->num_bufs != 1) {
-         ALOGE("%s: Multiple streams are not supported",__func__);
-         return;
-    }
-    if(super_frame->bufs[0] == NULL ) {
-         ALOGE("%s: Error, Super buffer frame does not contain valid buffer",
-                  __func__);
-         return;
+    if (checkStreamCbErrors(super_frame, stream) != NO_ERROR) {
+        ALOGE("%s: Error with the stream callback", __func__);
+        return;
     }
 
     frameIndex = (uint8_t)super_frame->bufs[0]->buf_idx;
@@ -2692,11 +3065,11 @@
     return;
 }
 
-QCamera3Memory* QCamera3PicChannel::getStreamBufs(uint32_t len)
+QCamera3StreamMem* QCamera3PicChannel::getStreamBufs(uint32_t len)
 {
     int rc = 0;
 
-    mYuvMemory = new QCamera3HeapMemory();
+    mYuvMemory = new QCamera3StreamMem(mCamera3Stream->max_buffers);
     if (!mYuvMemory) {
         ALOGE("%s: unable to create metadata memory", __func__);
         return NULL;
@@ -2834,10 +3207,12 @@
     mReprocessType(REPROCESS_TYPE_NONE),
     m_pSrcChannel(NULL),
     m_pMetaChannel(NULL),
-    mMemory(NULL)
+    mMemory(NULL),
+    mGrallocMemory(0)
 {
     memset(mSrcStreamHandles, 0, sizeof(mSrcStreamHandles));
-    mOfflineMetaIndex = (int32_t) (mNumBuffers -1);
+    mOfflineBuffersIndex = mNumBuffers -1;
+    mOfflineMetaIndex = (int32_t) (2*mNumBuffers -1);
 }
 
 
@@ -3001,6 +3376,15 @@
                     __func__, rc, frameIndex);
         }
         obj->reprocessCbRoutine(resultBuffer, resultFrameNumber);
+
+        // TODO: Do we need to deallcoate mOfflineMetaMemory and
+        // mOfflineMemory for framework reprocessing?
+        obj->m_postprocessor.releaseOfflineBuffers();
+        qcamera_hal3_pp_data_t *pp_job = obj->m_postprocessor.dequeuePPJob(resultFrameNumber);
+        if (pp_job != NULL) {
+            obj->m_postprocessor.releasePPJobData(pp_job);
+        }
+        free(pp_job);
     }
     free(super_frame);
     return;
@@ -3017,7 +3401,8 @@
  *==========================================================================*/
 QCamera3ReprocessChannel::QCamera3ReprocessChannel() :
     m_pSrcChannel(NULL),
-    m_pMetaChannel(NULL)
+    m_pMetaChannel(NULL),
+    mGrallocMemory(0)
 {
 }
 
@@ -3028,13 +3413,13 @@
  *
  * PARAMETERS : none
  *
- * RETURN     : QCamera3Memory *
+ * RETURN     : QCamera3StreamMem *
  *==========================================================================*/
-QCamera3Memory* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
+QCamera3StreamMem* QCamera3ReprocessChannel::getStreamBufs(uint32_t len)
 {
     int rc = 0;
     if (mReprocessType == REPROCESS_TYPE_JPEG) {
-        mMemory = new QCamera3HeapMemory();
+        mMemory = new QCamera3StreamMem(mNumBuffers);
         if (!mMemory) {
             ALOGE("%s: unable to create reproc memory", __func__);
             return NULL;
@@ -3233,18 +3618,19 @@
  *              NO_ERROR  -- success
  *              none-zero failure code
  *==========================================================================*/
-int32_t QCamera3ReprocessChannel::extractFrameCropAndRotation(mm_camera_super_buf_t *frame,
+int32_t QCamera3ReprocessChannel::extractFrameCropAndRotation(qcamera_hal3_pp_buffer_t *pp_buffer,
         mm_camera_buf_def_t *meta_buffer, jpeg_settings_t *jpeg_settings,
         qcamera_fwk_input_pp_data_t &fwk_frame)
 {
     int32_t rc = NO_ERROR;
     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
-    if ((NULL == meta_buffer) || (NULL == frame) || (NULL == jpeg_settings) ||
+    if ((NULL == meta_buffer) || (NULL == pp_buffer) || (NULL == pp_buffer->input) ||
             (NULL == hal_obj)) {
         return BAD_VALUE;
     }
 
     metadata_buffer_t *meta = (metadata_buffer_t *)meta_buffer->buffer;
+    mm_camera_super_buf_t *frame = pp_buffer->input;
     if (NULL == meta) {
         return BAD_VALUE;
     }
@@ -3254,20 +3640,22 @@
         QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
 
         if (pStream != NULL && pSrcStream != NULL) {
-            // Find rotation info for reprocess stream
-            cam_rotation_info_t rotation_info;
-            memset(&rotation_info, 0, sizeof(rotation_info));
-            if (jpeg_settings->jpeg_orientation == 0) {
-               rotation_info.rotation = ROTATE_0;
-            } else if (jpeg_settings->jpeg_orientation == 90) {
-               rotation_info.rotation = ROTATE_90;
-            } else if (jpeg_settings->jpeg_orientation == 180) {
-               rotation_info.rotation = ROTATE_180;
-            } else if (jpeg_settings->jpeg_orientation == 270) {
-               rotation_info.rotation = ROTATE_270;
+            if (jpeg_settings) {
+                // Find rotation info for reprocess stream
+                cam_rotation_info_t rotation_info;
+                memset(&rotation_info, 0, sizeof(rotation_info));
+                if (jpeg_settings->jpeg_orientation == 0) {
+                   rotation_info.rotation = ROTATE_0;
+                } else if (jpeg_settings->jpeg_orientation == 90) {
+                   rotation_info.rotation = ROTATE_90;
+                } else if (jpeg_settings->jpeg_orientation == 180) {
+                   rotation_info.rotation = ROTATE_180;
+                } else if (jpeg_settings->jpeg_orientation == 270) {
+                   rotation_info.rotation = ROTATE_270;
+                }
+                rotation_info.streamId = mStreams[0]->getMyServerID();
+                ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
             }
-            rotation_info.streamId = mStreams[0]->getMyServerID();
-            ADD_SET_PARAM_ENTRY_TO_BATCH(meta, CAM_INTF_PARM_ROTATION, rotation_info);
 
             // Find and insert crop info for reprocess stream
             IF_META_AVAILABLE(cam_crop_data_t, crop_data, CAM_INTF_META_CROP_DATA, meta) {
@@ -3312,6 +3700,7 @@
 
             fwk_frame.input_buffer = *frame->bufs[i];
             fwk_frame.metadata_buffer = *meta_buffer;
+            fwk_frame.output_buffer = pp_buffer->output;
             break;
         } else {
             ALOGE("%s: Source/Re-process streams are invalid", __func__);
@@ -3657,6 +4046,7 @@
         m_pSrcChannel = src_config.src_channel;
         m_pMetaChannel = pMetaChannel;
         mReprocessType = src_config.reprocess_type;
+        CDBG("%s: mReprocessType is %d", __func__, mReprocessType);
     }
     if(m_camOps->request_super_buf(m_camHandle,m_handle,1,0) < 0) {
         ALOGE("%s: Request for super buffer failed",__func__);
@@ -3738,10 +4128,10 @@
     free(super_frame);
 }
 
-QCamera3Memory* QCamera3SupportChannel::getStreamBufs(uint32_t len)
+QCamera3StreamMem* QCamera3SupportChannel::getStreamBufs(uint32_t len)
 {
     int rc;
-    mMemory = new QCamera3HeapMemory();
+    mMemory = new QCamera3StreamMem(MIN_STREAMING_BUFFER_NUM);
     if (!mMemory) {
         ALOGE("%s: unable to create heap memory", __func__);
         return NULL;
diff --git a/QCamera2/HAL3/QCamera3Channel.h b/QCamera2/HAL3/QCamera3Channel.h
index 8417301..bb13c30 100644
--- a/QCamera2/HAL3/QCamera3Channel.h
+++ b/QCamera2/HAL3/QCamera3Channel.h
@@ -33,6 +33,7 @@
 #include <hardware/camera3.h>
 #include "QCamera3Stream.h"
 #include "QCamera3Mem.h"
+#include "QCamera3StreamMem.h"
 #include "QCamera3PostProc.h"
 #include "QCamera3HALHeader.h"
 #include "utils/Vector.h"
@@ -83,7 +84,7 @@
                             QCamera3Stream *stream) = 0;
 
     virtual int32_t registerBuffer(buffer_handle_t *buffer, cam_is_type_t isType) = 0;
-    virtual QCamera3Memory *getStreamBufs(uint32_t len) = 0;
+    virtual QCamera3StreamMem *getStreamBufs(uint32_t len) = 0;
     virtual void putStreamBufs() = 0;
 
     QCamera3Stream *getStreamByHandle(uint32_t streamHandle);
@@ -165,13 +166,15 @@
             metadata_buffer_t* metadata);
     virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
             QCamera3Stream *stream);
-    virtual QCamera3Memory *getStreamBufs(uint32_t len);
+    virtual QCamera3StreamMem *getStreamBufs(uint32_t len);
     virtual void putStreamBufs();
     virtual int32_t registerBuffer(buffer_handle_t *buffer, cam_is_type_t isType);
 
+    virtual int32_t stop();
+
     virtual reprocess_type_t getReprocessType() = 0;
 
-    void reprocessCbRoutine(buffer_handle_t *resultBuffer,
+    virtual void reprocessCbRoutine(buffer_handle_t *resultBuffer,
             uint32_t resultFrameNumber);
 
     int32_t queueReprocMetadata(mm_camera_super_buf_t *metadata);
@@ -182,13 +185,15 @@
     int32_t setReprocConfig(reprocess_config_t &reproc_cfg,
             camera3_stream_buffer_t *pInputBuffer,
             metadata_buffer_t *metadata,
-            cam_format_t streamFormat);
+            cam_format_t streamFormat, cam_dimension_t dim);
     int32_t setFwkInputPPData(qcamera_fwk_input_pp_data_t *src_frame,
             camera3_stream_buffer_t *pInputBuffer,
             reprocess_config_t *reproc_cfg,
             metadata_buffer_t *metadata,
             buffer_handle_t *output_buffer,
             uint32_t frameNumber);
+    int32_t checkStreamCbErrors(mm_camera_super_buf_t *super_frame,
+            QCamera3Stream *stream);
 
     QCamera3PostProcessor m_postprocessor; // post processor
 
@@ -197,7 +202,7 @@
     void startPostProc(bool inputBufExists,
             const reprocess_config_t &reproc_cfg);
 
-    QCamera3GrallocMemory mMemory; //output buffer allocated by fwk
+    QCamera3StreamMem mMemory; //output buffer allocated by fwk
     camera3_stream_t *mCamera3Stream;
     uint32_t mNumBufs;
     cam_stream_type_t mStreamType;
@@ -210,11 +215,10 @@
 
     QCamera3Channel *m_pMetaChannel;
     mm_camera_super_buf_t *mMetaFrame;
-    QCamera3GrallocMemory mOfflineMemory; //reprocessing input buffer
-    QCamera3HeapMemory mOfflineMetaMemory; //reprocessing metadata buffer
+    QCamera3StreamMem mOfflineMemory; //reprocessing input buffer
+    QCamera3StreamMem mOfflineMetaMemory; //reprocessing metadata buffer
 
 private:
-    int32_t stop();
 
     bool m_bWNROn;
 };
@@ -273,13 +277,13 @@
     virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
                             QCamera3Stream *stream);
 
-    virtual QCamera3Memory *getStreamBufs(uint32_t le);
+    virtual QCamera3StreamMem *getStreamBufs(uint32_t le);
     virtual void putStreamBufs();
     virtual int32_t registerBuffer(buffer_handle_t * /*buffer*/, cam_is_type_t /*isType*/)
             { return NO_ERROR; };
 
 private:
-    QCamera3HeapMemory *mMemory;
+    QCamera3StreamMem *mMemory;
 };
 
 /* QCamera3RawChannel is for opaqueu/cross-platform raw stream containing
@@ -333,7 +337,7 @@
     virtual int32_t initialize(cam_is_type_t isType);
     virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
                             QCamera3Stream *stream);
-    virtual QCamera3Memory *getStreamBufs(uint32_t le);
+    virtual QCamera3StreamMem *getStreamBufs(uint32_t le);
     virtual void putStreamBufs();
     virtual int32_t registerBuffer(buffer_handle_t * /*buffer*/, cam_is_type_t /*isType*/)
             { return NO_ERROR; };
@@ -345,7 +349,7 @@
 
 private:
     bool mRawDump;
-    QCamera3HeapMemory *mMemory;
+    QCamera3StreamMem *mMemory;
 };
 
 /* QCamera3YUVChannel is used to handle flexible YUV streams that are directly
@@ -355,19 +359,54 @@
 {
 public:
     QCamera3YUVChannel(uint32_t cam_handle,
-        mm_camera_ops_t *cam_ops,
-        channel_cb_routine cb_routine,
-        cam_padding_info_t *paddingInfo,
-        void *userData,
-        camera3_stream_t *stream,
-        cam_stream_type_t stream_type,
-        uint32_t postprocess_mask,
-        QCamera3Channel *metadataChannel);
-     ~QCamera3YUVChannel();
+            mm_camera_ops_t *cam_ops,
+            channel_cb_routine cb_routine,
+            cam_padding_info_t *paddingInfo,
+            void *userData,
+            camera3_stream_t *stream,
+            cam_stream_type_t stream_type,
+            uint32_t postprocess_mask,
+            QCamera3Channel *metadataChannel);
+    ~QCamera3YUVChannel();
     virtual int32_t initialize(cam_is_type_t isType);
+    virtual int32_t request(buffer_handle_t *buffer,
+            uint32_t frameNumber,
+            camera3_stream_buffer_t* pInputBuffer,
+            metadata_buffer_t* metadata, bool &needMetadata);
     virtual reprocess_type_t getReprocessType();
     virtual int32_t start();
+    virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
+            QCamera3Stream *stream);
+    virtual void reprocessCbRoutine(buffer_handle_t *resultBuffer,
+        uint32_t resultFrameNumber);
 
+private:
+    typedef struct {
+        uint32_t frameNumber;
+        bool offlinePpFlag;
+        buffer_handle_t *output;
+        mm_camera_super_buf_t *callback_buffer;
+    } PpInfo;
+
+    // Whether offline postprocessing is required for this channel
+    bool mBypass;
+    // Current edge, noise, and crop region setting
+    cam_edge_application_t mEdgeMode;
+    uint32_t mNoiseRedMode;
+    cam_crop_region_t mCropRegion;
+
+    // Mutex to protect mOfflinePpFlagMap and mFreeHeapBufferList
+    Mutex mOfflinePpLock;
+    // Map between free number and whether the request needs to be
+    // postprocessed.
+    List<PpInfo> mOfflinePpInfoList;
+    // Heap buffer index list
+    List<uint32_t> mFreeHeapBufferList;
+
+private:
+    bool needsFramePostprocessing(metadata_buffer_t* meta);
+    int32_t handleOfflinePpCallback(uint32_t resultFrameNumber,
+            Vector<mm_camera_super_buf_t *>& pendingCbs);
 };
 
 /* QCamera3PicChannel is for JPEG stream, which contains a YUV stream generated
@@ -395,7 +434,7 @@
     virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
             QCamera3Stream *stream);
 
-    virtual QCamera3Memory *getStreamBufs(uint32_t le);
+    virtual QCamera3StreamMem *getStreamBufs(uint32_t le);
     virtual void putStreamBufs();
     virtual reprocess_type_t getReprocessType();
 
@@ -420,7 +459,7 @@
     uint32_t mNumSnapshotBufs;
     uint32_t mYuvWidth, mYuvHeight;
     int32_t mCurrentBufIndex;
-    QCamera3HeapMemory *mYuvMemory;
+    QCamera3StreamMem *mYuvMemory;
     // Keep a list of free buffers
     Mutex mFreeBuffersLock;
     List<uint32_t> mFreeBufferList;
@@ -442,12 +481,12 @@
     int32_t doReprocessOffline(qcamera_fwk_input_pp_data_t *frame);
     int32_t doReprocess(int buf_fd, size_t buf_length, int32_t &ret_val,
                         mm_camera_super_buf_t *meta_buf);
-    int32_t extractFrameCropAndRotation(mm_camera_super_buf_t *frame,
+    int32_t extractFrameCropAndRotation(qcamera_hal3_pp_buffer_t *pp_buffer,
             mm_camera_buf_def_t *meta_buffer,
             jpeg_settings_t *jpeg_settings,
             qcamera_fwk_input_pp_data_t &fwk_frame);
     int32_t extractCrop(qcamera_fwk_input_pp_data_t *frame);
-    virtual QCamera3Memory *getStreamBufs(uint32_t len);
+    virtual QCamera3StreamMem *getStreamBufs(uint32_t len);
     virtual void putStreamBufs();
     virtual int32_t initialize(cam_is_type_t isType);
     int32_t unmapOfflineBuffers(bool all);
@@ -482,8 +521,8 @@
     uint32_t mSrcStreamHandles[MAX_STREAM_NUM_IN_BUNDLE];
     QCamera3ProcessingChannel *m_pSrcChannel; // ptr to source channel for reprocess
     QCamera3Channel *m_pMetaChannel;
-    QCamera3HeapMemory *mMemory;
-    QCamera3GrallocMemory mGrallocMemory;
+    QCamera3StreamMem *mMemory;
+    QCamera3StreamMem mGrallocMemory;
 };
 
 
@@ -507,14 +546,14 @@
     virtual void streamCbRoutine(mm_camera_super_buf_t *super_frame,
                             QCamera3Stream *stream);
 
-    virtual QCamera3Memory *getStreamBufs(uint32_t le);
+    virtual QCamera3StreamMem *getStreamBufs(uint32_t le);
     virtual void putStreamBufs();
     virtual int32_t registerBuffer(buffer_handle_t * /*buffer*/, cam_is_type_t /*isType*/)
             { return NO_ERROR; };
 
     static cam_dimension_t kDim;
 private:
-    QCamera3HeapMemory *mMemory;
+    QCamera3StreamMem *mMemory;
     cam_dimension_t mDim;
     cam_stream_type_t mStreamType;
 };
diff --git a/QCamera2/HAL3/QCamera3HWI.cpp b/QCamera2/HAL3/QCamera3HWI.cpp
index 8c53123..2e497c4 100755
--- a/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/QCamera2/HAL3/QCamera3HWI.cpp
@@ -412,7 +412,7 @@
     //        this stage by the framework
     for (List<stream_info_t *>::iterator it = mStreamInfo.begin();
         it != mStreamInfo.end(); it++) {
-        QCamera3Channel *channel = (*it)->channel;
+        QCamera3ProcessingChannel *channel = (*it)->channel;
         if (channel) {
             channel->stop();
         }
@@ -429,7 +429,7 @@
 
     for (List<stream_info_t *>::iterator it = mStreamInfo.begin();
         it != mStreamInfo.end(); it++) {
-        QCamera3Channel *channel = (*it)->channel;
+        QCamera3ProcessingChannel *channel = (*it)->channel;
         if (channel)
             delete channel;
         free (*it);
@@ -1029,7 +1029,7 @@
      * if they appear again, they will be validated */
     for (List<stream_info_t*>::iterator it = mStreamInfo.begin();
             it != mStreamInfo.end(); it++) {
-        QCamera3Channel *channel = (QCamera3Channel*)(*it)->stream->priv;
+        QCamera3ProcessingChannel *channel = (QCamera3ProcessingChannel*)(*it)->stream->priv;
         channel->stop();
         (*it)->status = INVALID;
     }
@@ -1065,12 +1065,17 @@
     size_t processedStreamCnt = 0;
     // Number of streams on ISP encoder path
     size_t numStreamsOnEncoder = 0;
-    cam_dimension_t maxViewfinderSize;
+    size_t numYuv888OnEncoder = 0;
+    bool bYuv888OverrideJpeg = false;
+    cam_dimension_t largeYuv888Size = {0, 0};
+    cam_dimension_t maxViewfinderSize = {0, 0};
     bool bJpegExceeds4K = false;
     bool bUseCommonFeatureMask = false;
     uint32_t commonFeatureMask = 0;
     maxViewfinderSize = gCamCapability[mCameraId]->max_viewfinder_size;
     camera3_stream_t *inputStream = NULL;
+    bool isJpeg = false;
+    cam_dimension_t jpegSize = {0, 0};
 
     /*EIS configuration*/
     bool eisSupported = false;
@@ -1117,9 +1122,10 @@
     for (size_t i = 0; i < streamList->num_streams; i++) {
         camera3_stream_t *newStream = streamList->streams[i];
         ALOGI("%s: stream[%d] type = %d, format = %d, width = %d, "
-                "height = %d, rotation = %d",
+                "height = %d, rotation = %d, usage = 0x%x",
                 __func__, i, newStream->stream_type, newStream->format,
-                newStream->width, newStream->height, newStream->rotation);
+                newStream->width, newStream->height, newStream->rotation,
+                newStream->usage);
         if (newStream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL ||
                 newStream->stream_type == CAMERA3_STREAM_INPUT){
             isZsl = true;
@@ -1129,6 +1135,9 @@
         }
 
         if (newStream->format == HAL_PIXEL_FORMAT_BLOB) {
+            isJpeg = true;
+            jpegSize.width = newStream->width;
+            jpegSize.height = newStream->height;
             if (newStream->width > VIDEO_4K_WIDTH ||
                     newStream->height > VIDEO_4K_HEIGHT)
                 bJpegExceeds4K = true;
@@ -1151,8 +1160,8 @@
             switch (newStream->format) {
             case HAL_PIXEL_FORMAT_BLOB:
                 stallStreamCnt++;
-                if (((int32_t)newStream->width > maxViewfinderSize.width) ||
-                        ((int32_t)newStream->height > maxViewfinderSize.height)) {
+                if (isOnEncoder(maxViewfinderSize, newStream->width,
+                        newStream->height)) {
                     commonFeatureMask |= CAM_QCOM_FEATURE_NONE;
                     numStreamsOnEncoder++;
                 }
@@ -1164,8 +1173,8 @@
                 break;
             case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
                 processedStreamCnt++;
-                if (((int32_t)newStream->width > maxViewfinderSize.width) ||
-                        ((int32_t)newStream->height > maxViewfinderSize.height)) {
+                if (isOnEncoder(maxViewfinderSize, newStream->width,
+                        newStream->height)) {
                     if (newStream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL ||
                             newStream->usage & GRALLOC_USAGE_HW_CAMERA_ZSL) {
                         commonFeatureMask |= CAM_QCOM_FEATURE_NONE;
@@ -1176,10 +1185,20 @@
                 }
                 break;
             case HAL_PIXEL_FORMAT_YCbCr_420_888:
+                processedStreamCnt++;
+                if (isOnEncoder(maxViewfinderSize, newStream->width,
+                        newStream->height)) {
+                    commonFeatureMask |= CAM_QCOM_FEATURE_NONE;
+                    numStreamsOnEncoder++;
+                    numYuv888OnEncoder++;
+                    largeYuv888Size.width = newStream->width;
+                    largeYuv888Size.height = newStream->height;
+                }
+                break;
             default:
                 processedStreamCnt++;
-                if (((int32_t)newStream->width > maxViewfinderSize.width) ||
-                        ((int32_t)newStream->height > maxViewfinderSize.height)) {
+                if (isOnEncoder(maxViewfinderSize, newStream->width,
+                        newStream->height)) {
                     commonFeatureMask |= CAM_QCOM_FEATURE_PP_SUPERSET_HAL3;
                     numStreamsOnEncoder++;
                 }
@@ -1220,6 +1239,7 @@
         CDBG_HIGH("%s: Multiple streams above max viewfinder size, common mask needed",
                 __func__);
     }
+
     /* Check if BLOB size is greater than 4k in 4k recording case */
     if (m_bIs4KVideo && bJpegExceeds4K) {
         ALOGE("%s: HAL doesn't support Blob size greater than 4k in 4k recording",
@@ -1228,6 +1248,16 @@
         return -EINVAL;
     }
 
+    // If jpeg stream is available, and a YUV 888 stream is on Encoder path, and
+    // the YUV stream's size is greater or equal to the JPEG size, set common
+    // postprocess mask to NONE, so that we can take advantage of postproc bypass.
+    if (numYuv888OnEncoder && isJpeg &&
+            largeYuv888Size.width >= jpegSize.width &&
+            largeYuv888Size.height >= jpegSize.height) {
+        bYuv888OverrideJpeg = true;
+        commonFeatureMask = CAM_QCOM_FEATURE_NONE;
+    }
+
     rc = validateStreamDimensions(streamList);
     if (rc == NO_ERROR) {
         rc = validateStreamRotations(streamList);
@@ -1251,8 +1281,8 @@
         for (List<stream_info_t*>::iterator it=mStreamInfo.begin();
                 it != mStreamInfo.end(); it++) {
             if ((*it)->stream == newStream) {
-                QCamera3Channel *channel =
-                    (QCamera3Channel*)(*it)->stream->priv;
+                QCamera3ProcessingChannel *channel =
+                    (QCamera3ProcessingChannel*)(*it)->stream->priv;
                 stream_exists = true;
                 if (channel)
                     delete channel;
@@ -1376,7 +1406,7 @@
         mStreamConfigInfo.stream_sizes[mStreamConfigInfo.num_streams].height = (int32_t)newStream->height;
         if ((newStream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL
                 || newStream->usage & GRALLOC_USAGE_HW_CAMERA_ZSL) &&
-            newStream->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED && jpegStream){
+            newStream->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED){
             mStreamConfigInfo.type[mStreamConfigInfo.num_streams] = CAM_STREAM_TYPE_SNAPSHOT;
             mStreamConfigInfo.postprocess_mask[mStreamConfigInfo.num_streams] = CAM_QCOM_FEATURE_NONE;
         } else if(newStream->stream_type == CAMERA3_STREAM_INPUT) {
@@ -1405,7 +1435,18 @@
               break;
            case HAL_PIXEL_FORMAT_YCbCr_420_888:
               mStreamConfigInfo.type[mStreamConfigInfo.num_streams] = CAM_STREAM_TYPE_CALLBACK;
-              mStreamConfigInfo.postprocess_mask[mStreamConfigInfo.num_streams] = CAM_QCOM_FEATURE_PP_SUPERSET_HAL3;
+              if (isOnEncoder(maxViewfinderSize, newStream->width,
+                      newStream->height)) {
+                  if (bUseCommonFeatureMask)
+                      mStreamConfigInfo.postprocess_mask[mStreamConfigInfo.num_streams] =
+                              commonFeatureMask;
+                  else
+                      mStreamConfigInfo.postprocess_mask[mStreamConfigInfo.num_streams] =
+                              CAM_QCOM_FEATURE_NONE;
+              } else {
+                  mStreamConfigInfo.postprocess_mask[mStreamConfigInfo.num_streams] =
+                          CAM_QCOM_FEATURE_PP_SUPERSET_HAL3;
+              }
               break;
            case HAL_PIXEL_FORMAT_BLOB:
               mStreamConfigInfo.type[mStreamConfigInfo.num_streams] = CAM_STREAM_TYPE_SNAPSHOT;
@@ -1414,8 +1455,8 @@
                           = CAM_QCOM_FEATURE_PP_SUPERSET_HAL3;
               } else {
                   if (bUseCommonFeatureMask &&
-                          (((int32_t)newStream->width > maxViewfinderSize.width) ||
-                                  ((int32_t)newStream->height > maxViewfinderSize.height))) {
+                          isOnEncoder(maxViewfinderSize, newStream->width,
+                                  newStream->height)) {
                       mStreamConfigInfo.postprocess_mask[mStreamConfigInfo.num_streams] = commonFeatureMask;
                   } else {
                       mStreamConfigInfo.postprocess_mask[mStreamConfigInfo.num_streams] = CAM_QCOM_FEATURE_NONE;
@@ -1437,6 +1478,11 @@
                           (int32_t)videoWidth;
                   mStreamConfigInfo.stream_sizes[mStreamConfigInfo.num_streams].height =
                           (int32_t)videoHeight;
+              } else if (bYuv888OverrideJpeg) {
+                  mStreamConfigInfo.stream_sizes[mStreamConfigInfo.num_streams].width =
+                          (int32_t)largeYuv888Size.width;
+                  mStreamConfigInfo.stream_sizes[mStreamConfigInfo.num_streams].height =
+                          (int32_t)largeYuv888Size.height;
               }
               break;
            case HAL_PIXEL_FORMAT_RAW_OPAQUE:
@@ -1483,7 +1529,7 @@
 
             if (newStream->stream_type == CAMERA3_STREAM_OUTPUT ||
                     newStream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL) {
-                QCamera3Channel *channel = NULL;
+                QCamera3ProcessingChannel *channel = NULL;
                 switch (newStream->format) {
                 case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
                     /* use higher number of buffers for HFR mode */
@@ -1522,7 +1568,7 @@
                     newStream->max_buffers = channel->getNumBuffers();
                     newStream->priv = channel;
                     break;
-                case HAL_PIXEL_FORMAT_YCbCr_420_888:
+                case HAL_PIXEL_FORMAT_YCbCr_420_888: {
                     channel = new QCamera3YUVChannel(mCameraHandle->camera_handle,
                             mCameraHandle->ops, captureResultCb,
                             &gCamCapability[mCameraId]->padding_info,
@@ -1540,6 +1586,7 @@
                     newStream->max_buffers = channel->getNumBuffers();
                     newStream->priv = channel;
                     break;
+                }
                 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
                 case HAL_PIXEL_FORMAT_RAW16:
                 case HAL_PIXEL_FORMAT_RAW10:
@@ -1556,7 +1603,7 @@
                         return -ENOMEM;
                     }
                     newStream->max_buffers = mRawChannel->getNumBuffers();
-                    newStream->priv = (QCamera3Channel*)mRawChannel;
+                    newStream->priv = (QCamera3ProcessingChannel*)mRawChannel;
                     break;
                 case HAL_PIXEL_FORMAT_BLOB:
                     // Max live snapshot inflight buffer is 1. This is to mitigate
@@ -1573,8 +1620,11 @@
                         pthread_mutex_unlock(&mMutex);
                         return -ENOMEM;
                     }
-                    newStream->priv = (QCamera3Channel*)mPictureChannel;
+                    newStream->priv = (QCamera3ProcessingChannel*)mPictureChannel;
                     newStream->max_buffers = mPictureChannel->getNumBuffers();
+                    mPictureChannel->overrideYuvSize(
+                            mStreamConfigInfo.stream_sizes[mStreamConfigInfo.num_streams].width,
+                            mStreamConfigInfo.stream_sizes[mStreamConfigInfo.num_streams].height);
                     break;
 
                 default:
@@ -1591,7 +1641,7 @@
             for (List<stream_info_t*>::iterator it=mStreamInfo.begin();
                     it != mStreamInfo.end(); it++) {
                 if ((*it)->stream == newStream) {
-                    (*it)->channel = (QCamera3Channel*) newStream->priv;
+                    (*it)->channel = (QCamera3ProcessingChannel*) newStream->priv;
                     break;
                 }
             }
@@ -1607,24 +1657,6 @@
             mStreamConfigInfo.num_streams++;
     }
 
-    if (isZsl) {
-        if (zslStream == NULL) {
-            ALOGE("%s: Error Zsl stream handle missing", __func__);
-            pthread_mutex_unlock(&mMutex);
-            return -EINVAL;
-        }
-        /* This override is possible since the f/w gaurantees that the ZSL
-           stream will always be the active array size in case of Bidirectional
-           or will be limited to the max i/p stream size which we can control to
-           be equal to be the largest YUV/Opaque stream size
-           */
-        if (mPictureChannel) {
-           mPictureChannel->overrideYuvSize(zslStream->width, zslStream->height);
-        }
-    } else if (mPictureChannel && m_bIs4KVideo) {
-        mPictureChannel->overrideYuvSize(videoWidth, videoHeight);
-    }
-
     //RAW DUMP channel
     if (mEnableRawDump && isRawStreamRequested == false){
         cam_dimension_t rawDumpSize;
@@ -1806,8 +1838,8 @@
     // Validate all buffers
     b = request->output_buffers;
     do {
-        QCamera3Channel *channel =
-                static_cast<QCamera3Channel*>(b->stream->priv);
+        QCamera3ProcessingChannel *channel =
+                static_cast<QCamera3ProcessingChannel*>(b->stream->priv);
         if (channel == NULL) {
             ALOGE("%s: Request %d: Buffer %ld: Unconfigured stream!",
                     __func__, frameNumber, (long)idx);
@@ -2265,7 +2297,7 @@
         }
         goto done_metadata;
     }
-    CDBG("%s: valid frame_number = %u, capture_time = %lld", __func__,
+    CDBG_HIGH("%s: valid frame_number = %u, capture_time = %lld", __func__,
             frame_number, capture_time);
 
     for (pendingRequestIterator i = mPendingRequestsList.begin();
@@ -2290,7 +2322,7 @@
             for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
                     j != i->buffers.end(); j++) {
                if (j->stream->format != HAL_PIXEL_FORMAT_BLOB) {
-                   QCamera3Channel *channel = (QCamera3Channel *)j->stream->priv;
+                   QCamera3ProcessingChannel *channel = (QCamera3ProcessingChannel *)j->stream->priv;
                    uint32_t streamID = channel->getStreamID(channel->getStreamTypeMask());
                    for (uint32_t k = 0; k < p_cam_frame_drop->cam_stream_ID.num_streams; k++) {
                        if (streamID == p_cam_frame_drop->cam_stream_ID.streamID[k]) {
@@ -2373,15 +2405,26 @@
                                frame_number);
                     }
                 }
+            }
 
-
-                mPictureChannel->queueReprocMetadata(metadata_buf);
-            } else {
+            // Find channel requiring metadata, and queue the current metadata.
+            //TODO: for now, we don't support two streams requiring metadata at the same time.
+            // (because we are not making copies, and metadata buffer is not reference counted.
+            pendingBufferIterator iter = i->buffers.begin();
+            while (iter != i->buffers.end() && !iter->need_metadata)
+                iter++;
+            if (iter == i->buffers.end()) {
+                CDBG("%s: couldn't find need_metadata for this metadata", __func__);
                 // Return metadata buffer
                 if (free_and_bufdone_meta_buf) {
                     mMetadataChannel->bufDone(metadata_buf);
                     free(metadata_buf);
                 }
+            } else {
+                CDBG("%s: need_metadata is set for this metadata", __func__);
+                QCamera3ProcessingChannel *channel =
+                        (QCamera3ProcessingChannel *)iter->stream->priv;
+                channel->queueReprocMetadata(metadata_buf);
             }
         }
         if (!result.result) {
@@ -2518,7 +2561,7 @@
             }
         }
         result.output_buffers = buffer;
-        CDBG("%s: result frame_number = %d, buffer = %p",
+        CDBG_HIGH("%s: result frame_number = %d, buffer = %p",
                 __func__, frame_number, buffer->buffer);
 
         for (List<PendingBufferInfo>::iterator k =
@@ -2626,7 +2669,7 @@
                         j->buffer = (camera3_stream_buffer_t *)malloc(
                             sizeof(camera3_stream_buffer_t));
                         *(j->buffer) = *buffer;
-                        CDBG("%s: cache buffer %p at result frame_number %d",
+                        CDBG_HIGH("%s: cache buffer %p at result frame_number %d",
                             __func__, buffer, frame_number);
                     }
                 }
@@ -2652,6 +2695,7 @@
    pthread_cond_signal(&mRequestCond);
 }
 
+
 /*===========================================================================
  * FUNCTION   : processCaptureRequest
  *
@@ -2983,7 +3027,7 @@
         request_id = mCurrentRequestId;
     }
 
-    CDBG("%s: %d, num_output_buffers = %d input_buffer = %p frame_number = %d",
+    CDBG_HIGH("%s: %d, num_output_buffers = %d input_buffer = %p frame_number = %d",
                                     __func__, __LINE__,
                                     request->num_output_buffers,
                                     request->input_buffer,
@@ -3081,6 +3125,7 @@
 
     /* Update pending request list and pending buffers map */
     PendingRequestInfo pendingRequest;
+    pendingRequestIterator latestRequest;
     pendingRequest.frame_number = frameNumber;
     pendingRequest.num_buffers = request->num_output_buffers;
     pendingRequest.request_id = request_id;
@@ -3110,6 +3155,7 @@
 
     for (size_t i = 0; i < request->num_output_buffers; i++) {
         RequestedBufferInfo requestedBuf;
+        memset(&requestedBuf, 0, sizeof(requestedBuf));
         requestedBuf.stream = request->output_buffers[i].stream;
         requestedBuf.buffer = NULL;
         pendingRequest.buffers.push_back(requestedBuf);
@@ -3126,11 +3172,8 @@
                 __func__, frameNumber, bufferInfo.buffer,
                 channel->getStreamTypeMask(), bufferInfo.stream->format);
     }
-    CDBG("%s: mPendingBuffersMap.num_buffers = %d",
-          __func__, mPendingBuffersMap.num_buffers);
-
-    mPendingRequestsList.push_back(pendingRequest);
-
+    latestRequest = mPendingRequestsList.insert(
+            mPendingRequestsList.end(), pendingRequest);
     if(mFlush) {
         pthread_mutex_unlock(&mMutex);
         return NO_ERROR;
@@ -3149,6 +3192,8 @@
     }
 
     // Call request on other streams
+    uint32_t streams_need_metadata = 0;
+    pendingBufferIterator pendingBufferIter = latestRequest->buffers.begin();
     for (size_t i = 0; i < request->num_output_buffers; i++) {
         const camera3_stream_buffer_t& output = request->output_buffers[i];
         QCamera3Channel *channel = (QCamera3Channel *)output.stream->priv;
@@ -3182,16 +3227,25 @@
                     pthread_mutex_unlock(&mMutex);
                     return rc;
                 }
+                pendingBufferIter->need_metadata = true;
+                streams_need_metadata++;
             }
         } else if (output.stream->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
-            rc = channel->request(output.buffer, frameNumber,
+            bool needMetadata = false;
+            QCamera3YUVChannel *yuvChannel = (QCamera3YUVChannel *)channel;
+            rc = yuvChannel->request(output.buffer, frameNumber,
                     pInputBuffer,
-                    (pInputBuffer ? &mReprocMeta : mParameters));
+                    (pInputBuffer ? &mReprocMeta : mParameters), needMetadata);
             if (rc < 0) {
                 ALOGE("%s: Fail to request on YUV channel", __func__);
                 pthread_mutex_unlock(&mMutex);
                 return rc;
             }
+            pendingBufferIter->need_metadata = needMetadata;
+            if (needMetadata)
+                streams_need_metadata += 1;
+            CDBG("%s: calling YUV channel request, need_metadata is %d",
+                    __func__, needMetadata);
         } else {
             CDBG("%s: %d, request with buffer %p, frame_number %d", __func__,
                 __LINE__, output.buffer, frameNumber);
@@ -3209,6 +3263,15 @@
                 return rc;
             }
         }
+        pendingBufferIter++;
+    }
+
+    //If 2 streams have need_metadata set to true, fail the request, unless
+    //we copy/reference count the metadata buffer
+    if (streams_need_metadata > 1) {
+        //TODO: Return error from here
+        ALOGE("s: not supporting request in which two streams requires"
+                " 2 HAL metadata for reprocessing", __func__);
     }
 
     if(request->input_buffer == NULL) {
@@ -3722,11 +3785,11 @@
         fwk_blackLevelInd[2] = blackLevelInd->cam_black_level[2];
         fwk_blackLevelInd[3] = blackLevelInd->cam_black_level[3];
 
-        ALOGE("%s: dynamicblackLevel = %d %d %d %d", __func__,
-          blackLevelInd->cam_black_level[0],
-          blackLevelInd->cam_black_level[1],
-          blackLevelInd->cam_black_level[2],
-          blackLevelInd->cam_black_level[3]);
+        CDBG("%s: dynamicblackLevel = %d %d %d %d", __func__,
+            blackLevelInd->cam_black_level[0],
+            blackLevelInd->cam_black_level[1],
+            blackLevelInd->cam_black_level[2],
+            blackLevelInd->cam_black_level[3]);
         camMetadata.update(QCAMERA3_SENSOR_DYNAMIC_BLACK_LEVEL_PATTERN, fwk_blackLevelInd, 4);
     }
 
@@ -4665,6 +4728,7 @@
                 thumbnail_size,
                 frame_settings.find(ANDROID_JPEG_THUMBNAIL_SIZE).count);
     }
+
 }
 
 /*===========================================================================
@@ -5746,7 +5810,8 @@
 
     uint8_t available_edge_modes[] = {ANDROID_EDGE_MODE_OFF,
                                       ANDROID_EDGE_MODE_FAST,
-                                      ANDROID_EDGE_MODE_HIGH_QUALITY};
+                                      ANDROID_EDGE_MODE_HIGH_QUALITY,
+                                      ANDROID_EDGE_MODE_ZERO_SHUTTER_LAG};
     staticInfo.update(ANDROID_EDGE_AVAILABLE_EDGE_MODES,
             available_edge_modes,
             sizeof(available_edge_modes)/sizeof(available_edge_modes[0]));
@@ -5754,7 +5819,8 @@
     uint8_t available_noise_red_modes[] = {ANDROID_NOISE_REDUCTION_MODE_OFF,
                                            ANDROID_NOISE_REDUCTION_MODE_FAST,
                                            ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY,
-                                           ANDROID_NOISE_REDUCTION_MODE_MINIMAL};
+                                           ANDROID_NOISE_REDUCTION_MODE_MINIMAL,
+                                           ANDROID_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG};
     staticInfo.update(ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
             available_noise_red_modes,
             sizeof(available_noise_red_modes)/sizeof(available_noise_red_modes[0]));
@@ -8509,7 +8575,7 @@
 
     pendingRequestIterator i = mPendingRequestsList.begin();
     frameNum = i->frame_number;
-    CDBG("%s: Oldest frame num on  mPendingRequestsList = %d",
+    CDBG_HIGH("%s: Oldest frame num on  mPendingRequestsList = %d",
       __func__, frameNum);
 
     // Go through the pending buffers and group them depending
@@ -8543,7 +8609,7 @@
 
         // Send Error notify to frameworks for each buffer for which
         // metadata buffer is already sent
-        CDBG("%s: Sending ERROR BUFFER for frame %d number of buffer %d",
+        CDBG_HIGH("%s: Sending ERROR BUFFER for frame %d number of buffer %d",
           __func__, frame_number, pending.size());
 
         pStream_Buf = new camera3_stream_buffer_t[pending.size()];
@@ -8567,7 +8633,7 @@
             pStream_Buf[j].status = CAMERA3_BUFFER_STATUS_ERROR;
             pStream_Buf[j].stream = info.stream;
             mCallbackOps->notify(mCallbackOps, &notify_msg);
-            CDBG("%s: notify frame_number = %d stream %p", __func__,
+            CDBG_HIGH("%s: notify frame_number = %d stream %p", __func__,
                     frame_number, info.stream);
         }
 
@@ -8580,7 +8646,7 @@
         delete [] pStream_Buf;
     }
 
-    CDBG("%s:Sending ERROR REQUEST for all pending requests", __func__);
+    CDBG_HIGH("%s:Sending ERROR REQUEST for all pending requests", __func__);
 
     flushMap.clear();
     for (List<PendingBufferInfo>::iterator k =
@@ -8605,7 +8671,7 @@
     for (size_t iFlush = 0; iFlush < flushMap.size(); iFlush++) {
         uint32_t frame_number = flushMap.keyAt(iFlush);
         const Vector<PendingBufferInfo> &pending = flushMap.valueAt(iFlush);
-        CDBG("%s:Sending ERROR REQUEST for frame %d",
+        CDBG_HIGH("%s:Sending ERROR REQUEST for frame %d",
               __func__, frame_number);
 
         // Send shutter notify to frameworks
@@ -8653,9 +8719,17 @@
     mPendingBuffersMap.num_buffers = 0;
     mPendingBuffersMap.mPendingBufferList.clear();
     mPendingReprocessResultList.clear();
-    CDBG("%s: Cleared all the pending buffers ", __func__);
+    CDBG_HIGH("%s: Cleared all the pending buffers ", __func__);
 
     return rc;
 }
 
+bool QCamera3HardwareInterface::isOnEncoder(
+        const cam_dimension_t max_viewfinder_size,
+        uint32_t width, uint32_t height)
+{
+    return (width > (uint32_t)max_viewfinder_size.width ||
+            height > (uint32_t)max_viewfinder_size.height);
+}
+
 }; //end namespace qcamera
diff --git a/QCamera2/HAL3/QCamera3HWI.h b/QCamera2/HAL3/QCamera3HWI.h
index e3aae7f..31ffb5e 100644
--- a/QCamera2/HAL3/QCamera3HWI.h
+++ b/QCamera2/HAL3/QCamera3HWI.h
@@ -100,7 +100,7 @@
     camera3_stream_buffer_set_t buffer_set;
     stream_status_t status;
     int registered;
-    QCamera3Channel *channel;
+    QCamera3ProcessingChannel *channel;
 } stream_info_t;
 
 class QCamera3HardwareInterface {
@@ -246,6 +246,8 @@
             metadata_buffer_t *hal_metadata);
     int32_t extractSceneMode(const CameraMetadata &frame_settings, uint8_t metaMode,
             metadata_buffer_t *hal_metadata);
+    int32_t numOfSizesOnEncoder(const camera3_stream_configuration_t *streamList,
+            const cam_dimension_t &maxViewfinderSize);
 
     void updatePowerHint(bool bWasVideo, bool bIsVideo);
     int32_t getSensorOutputSize(cam_dimension_t &sensor_dim);
@@ -254,6 +256,9 @@
     int32_t stopAllChannels();
     int32_t notifyErrorForPendingRequests();
 
+    bool isOnEncoder(const cam_dimension_t max_viewfinder_size,
+            uint32_t width, uint32_t height);
+
     camera3_device_t   mCameraDevice;
     uint32_t           mCameraId;
     mm_camera_vtbl_t  *mCameraHandle;
@@ -292,6 +297,9 @@
     typedef struct {
         camera3_stream_t *stream;
         camera3_stream_buffer_t *buffer;
+        // metadata needs to be consumed by the corresponding stream
+        // in order to generate the buffer.
+        bool need_metadata;
     } RequestedBufferInfo;
     typedef struct {
         uint32_t frame_number;
@@ -320,6 +328,7 @@
         camera3_stream_t *stream;
         // Buffer handle
         buffer_handle_t *buffer;
+
     } PendingBufferInfo;
 
     typedef struct {
@@ -338,6 +347,8 @@
     typedef KeyedVector<uint32_t, Vector<PendingBufferInfo> > FlushMap;
     typedef List<QCamera3HardwareInterface::PendingRequestInfo>::iterator
             pendingRequestIterator;
+    typedef List<QCamera3HardwareInterface::RequestedBufferInfo>::iterator
+            pendingBufferIterator;
 
     List<PendingReprocessResult> mPendingReprocessResultList;
     List<PendingRequestInfo> mPendingRequestsList;
diff --git a/QCamera2/HAL3/QCamera3Mem.cpp b/QCamera2/HAL3/QCamera3Mem.cpp
index 74e328b..1d730b1 100644
--- a/QCamera2/HAL3/QCamera3Mem.cpp
+++ b/QCamera2/HAL3/QCamera3Mem.cpp
@@ -66,6 +66,7 @@
         mMemInfo[i].main_ion_fd = -1;
         mMemInfo[i].handle = 0;
         mMemInfo[i].size = 0;
+        mCurrentFrameNumbers[i] = -1;
     }
 }
 
@@ -261,7 +262,25 @@
 QCamera3HeapMemory::QCamera3HeapMemory()
     : QCamera3Memory()
 {
-    for (int i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i ++)
+    mMaxCnt = MM_CAMERA_MAX_NUM_FRAMES;
+    for (uint32_t i = 0; i < mMaxCnt; i ++)
+        mPtr[i] = NULL;
+}
+
+/*===========================================================================
+ * FUNCTION   : QCamera3HeapMemory
+ *
+ * DESCRIPTION: constructor of QCamera3HeapMemory for ion memory used internally in HAL
+ *
+ * PARAMETERS : none
+ *
+ * RETURN     : none
+ *==========================================================================*/
+QCamera3HeapMemory::QCamera3HeapMemory(uint32_t maxCnt)
+    : QCamera3Memory()
+{
+    mMaxCnt = MIN(maxCnt, MM_CAMERA_MAX_NUM_FRAMES);
+    for (uint32_t i = 0; i < mMaxCnt; i ++)
         mPtr[i] = NULL;
 }
 
@@ -279,59 +298,6 @@
 }
 
 /*===========================================================================
- * FUNCTION   : alloc
- *
- * DESCRIPTION: allocate requested number of buffers of certain size
- *
- * PARAMETERS :
- *   @count   : number of buffers to be allocated
- *   @size    : lenght of the buffer to be allocated
- *   @heap_id : heap id to indicate where the buffers will be allocated from
- *
- * RETURN     : int32_t type of status
- *              NO_ERROR  -- success
- *              none-zero failure code
- *==========================================================================*/
-int QCamera3HeapMemory::alloc(uint32_t count, size_t size, unsigned int heap_id)
-{
-    int rc = OK;
-    if (count > MM_CAMERA_MAX_NUM_FRAMES) {
-        ALOGE("Buffer count %d out of bound. Max is %d", count, MM_CAMERA_MAX_NUM_FRAMES);
-        return BAD_INDEX;
-    }
-    if (mBufferCount) {
-        ALOGE("Allocating a already allocated heap memory");
-        return INVALID_OPERATION;
-    }
-
-    for (uint32_t i = 0; i < count; i ++) {
-        rc = allocOneBuffer(mMemInfo[i], heap_id, size);
-        if (rc < 0) {
-            ALOGE("AllocateIonMemory failed");
-            for (int32_t j = (int32_t)(i - 1); j >= 0; j--)
-                deallocOneBuffer(mMemInfo[j]);
-            break;
-        }
-    }
-    return rc;
-}
-
-/*===========================================================================
- * FUNCTION   : dealloc
- *
- * DESCRIPTION: deallocate buffers
- *
- * PARAMETERS : none
- *
- * RETURN     : none
- *==========================================================================*/
-void QCamera3HeapMemory::dealloc()
-{
-    for (uint32_t i = 0U; i < mBufferCount; i++)
-        deallocOneBuffer(mMemInfo[i]);
-}
-
-/*===========================================================================
  * FUNCTION   : allocOneBuffer
  *
  * DESCRIPTION: impl of allocating one buffers of certain size
@@ -448,6 +414,100 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : markFrameNumber
+ *
+ * DESCRIPTION: We use this function from the request call path to mark the
+ *              buffers with the frame number they are intended for this info
+ *              is used later when giving out callback & it is duty of PP to
+ *              ensure that data for that particular frameNumber/Request is
+ *              written to this buffer.
+ * PARAMETERS :
+ *   @index   : index of the buffer
+ *   @frame#  : Frame number from the framework
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3HeapMemory::markFrameNumber(uint32_t index, uint32_t frameNumber)
+{
+    Mutex::Autolock lock(mLock);
+
+    if (index >= mBufferCount) {
+        ALOGE("%s: Index %d out of bounds, current buffer count is %d",
+                __func__, index, mBufferCount);
+        return BAD_INDEX;
+    }
+
+    if (0 == mMemInfo[index].handle) {
+        ALOGE("%s: Buffer at %d not allocated", __func__, index);
+        return BAD_INDEX;
+    }
+
+    mCurrentFrameNumbers[index] = (int32_t)frameNumber;
+
+    return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION   : getFrameNumber
+ *
+ * DESCRIPTION: We use this to fetch the frameNumber for the request with which
+ *              this buffer was given to HAL
+ *
+ *
+ * PARAMETERS :
+ *   @index   : index of the buffer
+ *
+ * RETURN     : int32_t frameNumber
+ *              positive/zero  -- success
+ *              negative failure
+ *==========================================================================*/
+int32_t QCamera3HeapMemory::getFrameNumber(uint32_t index)
+{
+    Mutex::Autolock lock(mLock);
+
+    if (index >= mBufferCount) {
+        ALOGE("%s: Index %d out of bounds, current buffer count is %d",
+                __func__, index, mBufferCount);
+        return -1;
+    }
+
+    if (0 == mMemInfo[index].handle) {
+        ALOGE("%s: Buffer at %d not registered", __func__, index);
+        return -1;
+    }
+
+    return mCurrentFrameNumbers[index];
+}
+
+/*===========================================================================
+ * FUNCTION   : getBufferIndex
+ *
+ * DESCRIPTION: We use this to fetch the buffer index for the request with
+ *              a particular frame number
+ *
+ *
+ * PARAMETERS :
+ *   @frameNumber  : frame number of the buffer
+ *
+ * RETURN     : int32_t buffer index
+ *              negative failure
+ *==========================================================================*/
+int32_t QCamera3HeapMemory::getBufferIndex(uint32_t frameNumber)
+{
+    Mutex::Autolock lock(mLock);
+
+    for (uint32_t index = 0;
+            index < mBufferCount; index++) {
+        if (mMemInfo[index].handle &&
+                mCurrentFrameNumbers[index] == (int32_t)frameNumber)
+            return (int32_t)index;
+    }
+    return -1;
+}
+
+/*===========================================================================
  * FUNCTION   : getPtr
  *
  * DESCRIPTION: Return buffer pointer
@@ -479,30 +539,50 @@
 int QCamera3HeapMemory::allocate(uint32_t count, size_t size, bool queueAll)
 {
     unsigned int heap_id_mask = 0x1 << ION_IOMMU_HEAP_ID;
-    int rc = alloc(count, size, heap_id_mask);
-    if (rc < 0)
-        return rc;
+    uint32_t i;
+    int rc = NO_ERROR;
 
-    for (uint32_t i = 0; i < count; i ++) {
+    //Note that now we allow incremental allocation. In other words, we allow
+    //multiple alloc being called as long as the sum of count does not exceed
+    //mMaxCnt.
+    if (mBufferCount + count > mMaxCnt) {
+        ALOGE("Buffer count %d + %d out of bound. Max is %d",
+                mBufferCount, count, mMaxCnt);
+        return BAD_INDEX;
+    }
+
+    for (i = 0; i < count; i ++) {
+        rc = allocOneBuffer(mMemInfo[mBufferCount+i], heap_id_mask, size);
+        if (rc < 0) {
+            ALOGE("AllocateIonMemory failed");
+            goto ALLOC_FAILED;
+        }
+
         void *vaddr = mmap(NULL,
-                    mMemInfo[i].size,
+                    mMemInfo[mBufferCount+i].size,
                     PROT_READ | PROT_WRITE,
                     MAP_SHARED,
-                    mMemInfo[i].fd, 0);
+                    mMemInfo[mBufferCount+i].fd, 0);
         if (vaddr == MAP_FAILED) {
-            for (int32_t j = (int32_t)(i - 1); j >= 0; j --) {
-                munmap(mPtr[j], mMemInfo[j].size);
-                rc = NO_MEMORY;
-                break;
-            }
+            deallocOneBuffer(mMemInfo[mBufferCount+i]);
+            ALOGE("%s: mmap failed for buffer %d", __func__, i);
+            goto ALLOC_FAILED;
         } else
             mPtr[i] = vaddr;
     }
     if (rc == 0)
-        mBufferCount = count;
+        mBufferCount += count;
 
     mQueueAll = queueAll;
     return OK;
+
+ALLOC_FAILED:
+    for (uint32_t j = 0; j < i; j++) {
+        munmap(mPtr[mBufferCount+j], mMemInfo[mBufferCount+j].size);
+        mPtr[mBufferCount+j] = NULL;
+        deallocOneBuffer(mMemInfo[mBufferCount+j]);
+    }
+    return NO_MEMORY;
 }
 
 /*===========================================================================
@@ -519,8 +599,9 @@
     for (uint32_t i = 0; i < mBufferCount; i++) {
         munmap(mPtr[i], mMemInfo[i].size);
         mPtr[i] = NULL;
+        deallocOneBuffer(mMemInfo[i]);
+        mCurrentFrameNumbers[i] = -1;
     }
-    dealloc();
     mBufferCount = 0;
 }
 
@@ -604,17 +685,16 @@
  *              preview stream buffers are allocated from gralloc native_windoe
  *
  * PARAMETERS :
- *   @getMemory : camera memory request ops table
+ *   @startIdx : start index of array after which we can register buffers in.
  *
  * RETURN     : none
  *==========================================================================*/
-QCamera3GrallocMemory::QCamera3GrallocMemory()
-        : QCamera3Memory()
+QCamera3GrallocMemory::QCamera3GrallocMemory(uint32_t startIdx)
+        : QCamera3Memory(), mStartIdx(startIdx)
 {
     for (int i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i ++) {
         mBufferHandle[i] = NULL;
         mPrivateHandle[i] = NULL;
-        mCurrentFrameNumbers[i] = -1;
     }
 }
 
@@ -654,7 +734,7 @@
             (type == CAM_STREAM_TYPE_VIDEO) ? ITU_R_709 : ITU_R_601_FR;
     int32_t idx = -1;
 
-    CDBG(" %s : E ", __FUNCTION__);
+    CDBG("%s: E", __func__);
 
     memset(&ion_info_fd, 0, sizeof(ion_info_fd));
 
@@ -664,9 +744,9 @@
     }
 
     Mutex::Autolock lock(mLock);
-    if (mBufferCount >= (MM_CAMERA_MAX_NUM_FRAMES - 1)) {
+    if (mBufferCount >= (MM_CAMERA_MAX_NUM_FRAMES - 1 - mStartIdx)) {
         ALOGE("%s: Number of buffers %d greater than what's supported %d",
-                __func__, mBufferCount, MM_CAMERA_MAX_NUM_FRAMES);
+                __func__, mBufferCount, MM_CAMERA_MAX_NUM_FRAMES - mStartIdx);
         return BAD_INDEX;
     }
 
@@ -696,8 +776,8 @@
             goto end;
         }
     }
-    ALOGV("%s: idx = %d, fd = %d, size = %d, offset = %d",
-            __func__, mBufferCount, mPrivateHandle[mBufferCount]->fd,
+    CDBG("%s: idx = %d, fd = %d, size = %d, offset = %d",
+            __func__, idx, mPrivateHandle[idx]->fd,
             mPrivateHandle[idx]->size,
             mPrivateHandle[idx]->offset);
     mMemInfo[idx].fd = mPrivateHandle[idx]->fd;
@@ -752,6 +832,7 @@
     mMemInfo[idx].main_ion_fd = -1;
     mBufferHandle[idx] = NULL;
     mPrivateHandle[idx] = NULL;
+    mCurrentFrameNumbers[idx] = -1;
     mBufferCount--;
 
     return NO_ERROR;
@@ -781,6 +862,11 @@
                 __func__, idx, MM_CAMERA_MAX_NUM_FRAMES);
         return BAD_VALUE;
     }
+    if (idx < mStartIdx) {
+        ALOGE("%s: buffer index %d less than starting index %d",
+                __func__, idx, mStartIdx);
+        return BAD_INDEX;
+    }
 
     if (0 == mMemInfo[idx].handle) {
         ALOGE("%s: Trying to unregister buffer at %d which still not registered",
@@ -811,7 +897,7 @@
 
     CDBG("%s: E ", __FUNCTION__);
 
-    for (uint32_t cnt = 0; cnt < MM_CAMERA_MAX_NUM_FRAMES; cnt++) {
+    for (uint32_t cnt = mStartIdx; cnt < MM_CAMERA_MAX_NUM_FRAMES; cnt++) {
         if (0 == mMemInfo[cnt].handle) {
             continue;
         }
@@ -849,6 +935,11 @@
         ALOGE("%s: Index out of bounds", __func__);
         return BAD_INDEX;
     }
+    if (index < mStartIdx) {
+        ALOGE("%s: buffer index %d less than starting index %d",
+                __func__, index, mStartIdx);
+        return BAD_INDEX;
+    }
 
     if (0 == mMemInfo[index].handle) {
         ALOGE("%s: Buffer at %d not registered", __func__, index);
@@ -882,6 +973,11 @@
         ALOGE("%s: Index out of bounds", __func__);
         return -1;
     }
+    if (index < mStartIdx) {
+        ALOGE("%s: buffer index %d less than starting index %d",
+                __func__, index, mStartIdx);
+        return BAD_INDEX;
+    }
 
     if (0 == mMemInfo[index].handle) {
         ALOGE("%s: Buffer at %d not registered", __func__, index);
@@ -892,6 +988,30 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : getBufferIndex
+ *
+ * DESCRIPTION: We use this to fetch the buffer index for the request with
+ *              a particular frame number
+ *
+ *
+ * PARAMETERS :
+ *   @frameNumber  : frame number of the buffer
+ *
+ * RETURN     : int32_t buffer index
+ *              negative failure
+ *==========================================================================*/
+int32_t QCamera3GrallocMemory::getBufferIndex(uint32_t frameNumber)
+{
+    for (uint32_t index = mStartIdx;
+            index < MM_CAMERA_MAX_NUM_FRAMES; index++) {
+        if (mMemInfo[index].handle &&
+                mCurrentFrameNumbers[index] == (int32_t)frameNumber)
+            return (int32_t)index;
+    }
+    return -1;
+}
+
+/*===========================================================================
  * FUNCTION   : cacheOps
  *
  * DESCRIPTION: ion related memory cache operations
@@ -906,6 +1026,16 @@
  *==========================================================================*/
 int QCamera3GrallocMemory::cacheOps(uint32_t index, unsigned int cmd)
 {
+    if (index >= MM_CAMERA_MAX_NUM_FRAMES) {
+        ALOGE("%s: Index out of bounds", __func__);
+        return -1;
+    }
+    if (index < mStartIdx) {
+        ALOGE("%s: buffer index %d less than starting index %d",
+                __func__, index, mStartIdx);
+        return BAD_INDEX;
+    }
+
     return cacheOpsInternal(index, cmd, mPtr[index]);
 }
 
@@ -950,7 +1080,7 @@
     if (!key) {
         return BAD_VALUE;
     }
-    for (uint32_t i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i++) {
+    for (uint32_t i = mStartIdx; i < MM_CAMERA_MAX_NUM_FRAMES; i++) {
         if (mBufferHandle[i] == key) {
             index = (int)i;
             break;
@@ -981,7 +1111,7 @@
         return index;
     }
 
-    for (size_t i = 0; i < MM_CAMERA_MAX_NUM_FRAMES; i++) {
+    for (size_t i = mStartIdx; i < MM_CAMERA_MAX_NUM_FRAMES; i++) {
         if (0 == mMemInfo[i].handle) {
             index = i;
             break;
@@ -1009,6 +1139,12 @@
                 __func__, index, MM_CAMERA_MAX_NUM_FRAMES);
         return NULL;
     }
+    if (index < mStartIdx) {
+        ALOGE("%s: buffer index %d less than starting index %d",
+                __func__, index, mStartIdx);
+        return NULL;
+    }
+
 
     if (0 == mMemInfo[index].handle) {
         ALOGE("%s: Buffer at %d not registered", __func__, index);
@@ -1054,6 +1190,11 @@
                 __func__, index, MM_CAMERA_MAX_NUM_FRAMES);
         return NULL;
     }
+    if (index < mStartIdx) {
+        ALOGE("%s: buffer index %d less than starting index %d",
+                __func__, index, mStartIdx);
+        return NULL;
+    }
 
     if (0 == mMemInfo[index].handle) {
         ALOGE("%s: Buffer at %d not registered", __func__, index);
@@ -1062,5 +1203,4 @@
 
     return mBufferHandle[index];
 }
-
 }; //namespace qcamera
diff --git a/QCamera2/HAL3/QCamera3Mem.h b/QCamera2/HAL3/QCamera3Mem.h
index b32f6dc..e8154cd 100644
--- a/QCamera2/HAL3/QCamera3Mem.h
+++ b/QCamera2/HAL3/QCamera3Mem.h
@@ -67,6 +67,10 @@
     virtual int getMatchBufIndex(void *object) = 0;
     virtual void *getPtr(uint32_t index) = 0;
 
+    virtual int32_t markFrameNumber(uint32_t index, uint32_t frameNumber) = 0;
+    virtual int32_t getFrameNumber(uint32_t index) = 0;
+    virtual int32_t getBufferIndex(uint32_t frameNumber) = 0;
+
     QCamera3Memory();
     virtual ~QCamera3Memory();
 
@@ -87,6 +91,7 @@
     uint32_t mBufferCount;
     struct QCamera3MemInfo mMemInfo[MM_CAMERA_MAX_NUM_FRAMES];
     void *mPtr[MM_CAMERA_MAX_NUM_FRAMES];
+    int32_t mCurrentFrameNumbers[MM_CAMERA_MAX_NUM_FRAMES];
     Mutex mLock;
 };
 
@@ -96,6 +101,7 @@
 class QCamera3HeapMemory : public QCamera3Memory {
 public:
     QCamera3HeapMemory();
+    QCamera3HeapMemory(uint32_t maxCnt);
     virtual ~QCamera3HeapMemory();
 
     int allocate(uint32_t count, size_t size, bool queueAll);
@@ -105,22 +111,25 @@
     virtual int getRegFlags(uint8_t *regFlags);
     virtual int getMatchBufIndex(void *object);
     virtual void *getPtr(uint32_t index);
+
+    virtual int32_t markFrameNumber(uint32_t index, uint32_t frameNumber);
+    virtual int32_t getFrameNumber(uint32_t index);
+    virtual int32_t getBufferIndex(uint32_t frameNumber);
+
 protected:
     virtual void *getPtrLocked(uint32_t index);
 private:
-    int alloc(uint32_t count, size_t size, unsigned int heap_id);
-    void dealloc();
-
     int allocOneBuffer(struct QCamera3MemInfo &memInfo,
             unsigned int heap_id, size_t size);
     void deallocOneBuffer(struct QCamera3MemInfo &memInfo);
     bool mQueueAll;
+    uint32_t mMaxCnt;
 };
 
 // Gralloc Memory shared with frameworks
 class QCamera3GrallocMemory : public QCamera3Memory {
 public:
-    QCamera3GrallocMemory();
+    QCamera3GrallocMemory(uint32_t startIdx);
     virtual ~QCamera3GrallocMemory();
 
     int registerBuffer(buffer_handle_t *buffer, cam_stream_type_t type);
@@ -130,8 +139,11 @@
     virtual int getRegFlags(uint8_t *regFlags);
     virtual int getMatchBufIndex(void *object);
     virtual void *getPtr(uint32_t index);
-    int32_t markFrameNumber(uint32_t index, uint32_t frameNumber);
-    int32_t getFrameNumber(uint32_t index);
+
+    virtual int32_t markFrameNumber(uint32_t index, uint32_t frameNumber);
+    virtual int32_t getFrameNumber(uint32_t index);
+    virtual int32_t getBufferIndex(uint32_t frameNumber);
+
     void *getBufferHandle(uint32_t index);
 protected:
     virtual void *getPtrLocked(uint32_t index);
@@ -140,8 +152,8 @@
     int32_t getFreeIndexLocked();
     buffer_handle_t *mBufferHandle[MM_CAMERA_MAX_NUM_FRAMES];
     struct private_handle_t *mPrivateHandle[MM_CAMERA_MAX_NUM_FRAMES];
-    int32_t mCurrentFrameNumbers[MM_CAMERA_MAX_NUM_FRAMES];
-};
 
+    uint32_t mStartIdx;
+};
 };
 #endif
diff --git a/QCamera2/HAL3/QCamera3PostProc.cpp b/QCamera2/HAL3/QCamera3PostProc.cpp
index a9b3a9b..65a6206 100644
--- a/QCamera2/HAL3/QCamera3PostProc.cpp
+++ b/QCamera2/HAL3/QCamera3PostProc.cpp
@@ -74,7 +74,6 @@
       m_ongoingPPQ(releaseOngoingPPData, this),
       m_inputJpegQ(releaseJpegData, this),
       m_ongoingJpegQ(releaseJpegData, this),
-      m_inputRawQ(releasePPInputData, this),
       m_inputMetaQ(releaseMetadata, this),
       m_jpegSettingsQ(NULL, this)
 {
@@ -109,7 +108,7 @@
  *              NO_ERROR  -- success
  *              none-zero failure code
  *==========================================================================*/
-int32_t QCamera3PostProcessor::init(QCamera3Memory *memory,
+int32_t QCamera3PostProcessor::init(QCamera3StreamMem *memory,
         uint32_t postprocess_mask)
 {
     ATRACE_CALL();
@@ -421,7 +420,7 @@
 
     // src buf config
     //Pass input main image buffer info to encoder.
-    QCamera3Memory *pStreamMem = main_stream->getStreamBufs();
+    QCamera3StreamMem *pStreamMem = main_stream->getStreamBufs();
     if (pStreamMem == NULL) {
         ALOGE("%s: cannot get stream bufs from main stream", __func__);
         ret = BAD_VALUE;
@@ -433,7 +432,7 @@
             encode_parm.src_main_buf[i].index = i;
             bufSize = pStreamMem->getSize(i);
             if (BAD_INDEX == bufSize) {
-            ALOGE("%s: cannot retrieve buffer size for buffer %u", __func__, i);
+                ALOGE("%s: cannot retrieve buffer size for buffer %u", __func__, i);
                 ret = BAD_VALUE;
                 goto on_error;
             }
@@ -503,13 +502,18 @@
     return ret;
 }
 
+int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *input) {
+    return processData(input, NULL, 0);
+}
+
 /*===========================================================================
  * FUNCTION   : processData
  *
  * DESCRIPTION: enqueue data into dataProc thread
  *
  * PARAMETERS :
- *   @frame   : process frame
+ *   @frame   : process input frame
+ *   @output  : process output frame
  *
  * RETURN     : int32_t type of status
  *              NO_ERROR  -- success
@@ -518,16 +522,30 @@
  * NOTE       : depends on if offline reprocess is needed, received frame will
  *              be sent to either input queue of postprocess or jpeg encoding
  *==========================================================================*/
-int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *frame)
+int32_t QCamera3PostProcessor::processData(mm_camera_super_buf_t *input,
+        buffer_handle_t *output, uint32_t frameNumber)
 {
+    CDBG("%s: E", __func__);
     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)m_parent->mUserData;
     pthread_mutex_lock(&mReprocJobLock);
+
     // enqueue to post proc input queue
-    m_inputPPQ.enqueue((void *)frame);
-    if (!(m_inputMetaQ.isEmpty())) {
-       CDBG("%s: meta queue is not empty, do next job", __func__);
-       m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
+    qcamera_hal3_pp_buffer_t *pp_buffer = (qcamera_hal3_pp_buffer_t *)malloc(
+            sizeof(qcamera_hal3_pp_buffer_t));
+    if (NULL == pp_buffer) {
+        ALOGE("%s: out of memory", __func__);
+        return NO_MEMORY;
     }
+    memset(pp_buffer, 0, sizeof(*pp_buffer));
+    pp_buffer->input = input;
+    pp_buffer->output = output;
+    pp_buffer->frameNumber = frameNumber;
+    m_inputPPQ.enqueue((void *)pp_buffer);
+    if (!(m_inputMetaQ.isEmpty())) {
+        CDBG("%s: meta queue is not empty, do next job", __func__);
+        m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
+    } else
+        CDBG("%s: metadata queue is empty", __func__);
     pthread_mutex_unlock(&mReprocJobLock);
 
     return NO_ERROR;
@@ -603,7 +621,8 @@
  *==========================================================================*/
 int32_t QCamera3PostProcessor::processPPMetadata(mm_camera_super_buf_t *reproc_meta)
 {
-   pthread_mutex_lock(&mReprocJobLock);
+    CDBG("%s: E", __func__);
+    pthread_mutex_lock(&mReprocJobLock);
     // enqueue to metadata input queue
     m_inputMetaQ.enqueue((void *)reproc_meta);
     if (!(m_inputPPQ.isEmpty())) {
@@ -640,26 +659,6 @@
 }
 
 /*===========================================================================
- * FUNCTION   : processRawData
- *
- * DESCRIPTION: enqueue raw data into dataProc thread
- *
- * PARAMETERS :
- *   @frame   : process frame received from mm-camera-interface
- *
- * RETURN     : int32_t type of status
- *              NO_ERROR  -- success
- *              none-zero failure code
- *==========================================================================*/
-int32_t QCamera3PostProcessor::processRawData(mm_camera_super_buf_t *frame)
-{
-    // enqueu to raw input queue
-    m_inputRawQ.enqueue((void *)frame);
-    m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
-    return NO_ERROR;
-}
-
-/*===========================================================================
  * FUNCTION   : processPPData
  *
  * DESCRIPTION: process received frame after reprocess.
@@ -720,6 +719,31 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : dequeuePPJob
+ *
+ * DESCRIPTION: find a postprocessing job from ongoing pp queue by frame number
+ *
+ * PARAMETERS :
+ *   @frameNumber : frame number for the pp job
+ *
+ * RETURN     : ptr to a pp job struct. NULL if not found.
+ *==========================================================================*/
+qcamera_hal3_pp_data_t *QCamera3PostProcessor::dequeuePPJob(uint32_t frameNumber) {
+    qcamera_hal3_pp_data_t *pp_job = NULL;
+    pp_job = (qcamera_hal3_pp_data_t *)m_ongoingPPQ.dequeue();
+
+    if (pp_job == NULL) {
+        ALOGE("%s: Fatal: ongoing PP queue is empty", __func__);
+        return NULL;
+    }
+    if (pp_job->fwk_src_frame &&
+            (pp_job->fwk_src_frame->frameNumber != frameNumber)) {
+        ALOGE("%s: head of pp queue doesn't match requested frame number", __func__);
+    }
+    return pp_job;
+}
+
+/*===========================================================================
  * FUNCTION   : findJpegJobByJobId
  *
  * DESCRIPTION: find a jpeg job from ongoing Jpeg queue by its job ID
@@ -761,7 +785,14 @@
 {
     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
     if (NULL != pme) {
-        pme->releaseSuperBuf((mm_camera_super_buf_t *)data);
+        qcamera_hal3_pp_buffer_t *buf = (qcamera_hal3_pp_buffer_t *)data;
+        if (NULL != buf) {
+            if (buf->input) {
+                pme->releaseSuperBuf(buf->input);
+                free(buf->input);
+                buf->input = NULL;
+            }
+        }
     }
 }
 
@@ -818,22 +849,13 @@
 {
     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
     if (NULL != pme) {
-        qcamera_hal3_pp_data_t *pp_job = (qcamera_hal3_pp_data_t *)data;
-        if (NULL != pp_job->src_frame) {
-            pme->releaseSuperBuf(pp_job->src_frame);
-            free(pp_job->src_frame);
-            if (NULL != pp_job->src_metadata) {
-                pme->m_parent->metadataBufDone(pp_job->src_metadata);
-                free(pp_job->src_metadata);
-            }
-            pp_job->src_frame = NULL;
-            pp_job->metadata = NULL;
-        }
+        qcamera_hal3_pp_data_t *pp_data = (qcamera_hal3_pp_data_t *)data;
 
-        if (NULL != pp_job->fwk_src_frame) {
-            free(pp_job->fwk_src_frame);
-            pp_job->fwk_src_frame = NULL;
-        }
+        if (pp_data && pp_data->src_frame)
+          pme->releaseSuperBuf(pp_data->src_frame);
+
+        pme->releasePPJobData(pp_data);
+
     }
 }
 
@@ -943,6 +965,46 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : releasePPJobData
+ *
+ * DESCRIPTION: function to release internal resources in p pjob struct
+ *
+ * PARAMETERS :
+ *   @job     : ptr to pp job struct
+ *
+ * RETURN     : None
+ *
+ * NOTE       : Original source metadata buffer needs to be released and
+ *              queued back to kernel for future use. src_frame, src_metadata,
+ *              and fwk_src_frame structures need to be freed.
+ *==========================================================================*/
+void QCamera3PostProcessor::releasePPJobData(qcamera_hal3_pp_data_t *pp_job)
+{
+    ATRACE_CALL();
+    CDBG("%s: E", __func__);
+    if (NULL != pp_job) {
+        if (NULL != pp_job->src_frame) {
+            free(pp_job->src_frame);
+            if (NULL != pp_job->src_metadata) {
+                m_parent->metadataBufDone(pp_job->src_metadata);
+                free(pp_job->src_metadata);
+            }
+            pp_job->src_frame = NULL;
+            pp_job->metadata = NULL;
+        }
+
+        if (NULL != pp_job->fwk_src_frame) {
+            free(pp_job->fwk_src_frame);
+            pp_job->fwk_src_frame = NULL;
+        }
+    }
+
+    /* Additional trigger to process any pending jobs in the input queue */
+    m_dataProcTh.sendCmd(CAMERA_CMD_TYPE_DO_NEXT_JOB, FALSE, FALSE);
+    CDBG("%s: X", __func__);
+}
+
+/*===========================================================================
  * FUNCTION   : getColorfmtFromImgFmt
  *
  * DESCRIPTION: function to return jpeg color format based on its image format
@@ -1278,7 +1340,7 @@
        return BAD_VALUE;
     }
 
-    QCamera3Memory *memObj = (QCamera3Memory *)main_frame->mem_info;
+    QCamera3StreamMem *memObj = (QCamera3StreamMem *)main_frame->mem_info;
     if (NULL == memObj) {
         ALOGE("%s : Memeory Obj of main frame is NULL", __func__);
         return NO_MEMORY;
@@ -1539,7 +1601,6 @@
             pme->m_inputJpegQ.init();
             pme->m_inputPPQ.init();
             pme->m_inputFWKPPQ.init();
-            pme->m_inputRawQ.init();
             pme->m_inputMetaQ.init();
 
             break;
@@ -1580,9 +1641,6 @@
                 // flush framework input Postproc Queue
                 pme->m_inputFWKPPQ.flush();
 
-                // flush input raw Queue
-                pme->m_inputRawQ.flush();
-
                 pme->m_inputMetaQ.flush();
 
                 // signal cmd is completed
@@ -1598,7 +1656,7 @@
                 if (is_active == TRUE) {
                     // check if there is any ongoing jpeg jobs
                     if (pme->m_ongoingJpegQ.isEmpty()) {
-                       CDBG("%s: ongoing jpeg queue is empty so doing the jpeg job", __func__);
+                        CDBG("%s: ongoing jpeg queue is empty so doing the jpeg job", __func__);
                         // no ongoing jpeg job, we are fine to send jpeg encoding job
                         qcamera_hal3_jpeg_data_t *jpeg_job =
                             (qcamera_hal3_jpeg_data_t *)pme->m_inputJpegQ.dequeue();
@@ -1671,8 +1729,8 @@
                     CDBG_HIGH("%s: dequeuing pp frame", __func__);
                     pthread_mutex_lock(&pme->mReprocJobLock);
                     if(!pme->m_inputPPQ.isEmpty() && !pme->m_inputMetaQ.isEmpty()) {
-                        mm_camera_super_buf_t *pp_frame =
-                            (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
+                        qcamera_hal3_pp_buffer_t *pp_buffer =
+                            (qcamera_hal3_pp_buffer_t *)pme->m_inputPPQ.dequeue();
                         meta_buffer =
                             (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
                         jpeg_settings_t *jpeg_settings =
@@ -1690,21 +1748,22 @@
                             ret = -1;
                         } else {
                             memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
-                            pp_job->src_frame = pp_frame;
+                            pp_job->src_frame = pp_buffer->input;
                             pp_job->src_metadata = meta_buffer;
                             if (meta_buffer->bufs[0] != NULL) {
                                 pp_job->metadata = (metadata_buffer_t *)
                                         meta_buffer->bufs[0]->buffer;
                             }
                             pp_job->jpeg_settings = jpeg_settings;
-                            pme->m_ongoingPPQ.enqueue((void *)pp_job);
                             if (pme->m_pReprocChannel != NULL) {
                                 mm_camera_buf_def_t *meta_buffer_arg = NULL;
                                 meta_buffer_arg = meta_buffer->bufs[0];
                                 qcamera_fwk_input_pp_data_t fwk_frame;
                                 memset(&fwk_frame, 0, sizeof(qcamera_fwk_input_pp_data_t));
+                                fwk_frame.frameNumber = pp_buffer->frameNumber;
+                                pme->m_ongoingPPQ.enqueue((void *)pp_job);
                                 ret = pme->m_pReprocChannel->extractFrameCropAndRotation(
-                                        pp_frame, meta_buffer_arg,
+                                        pp_buffer, meta_buffer_arg,
                                         pp_job->jpeg_settings,
                                         fwk_frame);
                                 if (NO_ERROR == ret) {
@@ -1717,9 +1776,9 @@
                                     }
                                 }
                             } else {
-                                CDBG_HIGH("%s: No reprocess. Calling processPPData directly",
+                                ALOGE("%s: No reprocess. Calling processPPData directly",
                                     __func__);
-                                ret = pme->processPPData(pp_frame);
+                                ret = pme->processPPData(pp_buffer->input);
                             }
                         }
 
@@ -1729,9 +1788,12 @@
                                 free(pp_job);
                             }
                             // free frame
-                            if (pp_frame != NULL) {
-                                pme->releaseSuperBuf(pp_frame);
-                                free(pp_frame);
+                            if (pp_buffer != NULL) {
+                                if (pp_buffer->input) {
+                                    pme->releaseSuperBuf(pp_buffer->input);
+                                    free(pp_buffer->input);
+                                }
+                                free(pp_buffer);
                             }
                             //free metadata
                             if (NULL != meta_buffer) {
@@ -1749,16 +1811,16 @@
                     if (NULL != jpeg_job) {
                         free(jpeg_job);
                     }
-                    mm_camera_super_buf_t *super_buf;
-                    super_buf = (mm_camera_super_buf_t *)pme->m_inputRawQ.dequeue();
-                    if (NULL != super_buf) {
-                        pme->releaseSuperBuf(super_buf);
-                        free(super_buf);
-                    }
-                    super_buf = (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
-                    if (NULL != super_buf) {
-                        pme->releaseSuperBuf(super_buf);
-                        free(super_buf);
+
+                    qcamera_hal3_pp_buffer_t* pp_buf =
+                            (qcamera_hal3_pp_buffer_t *)pme->m_inputPPQ.dequeue();
+                    if (NULL != pp_buf) {
+                        if (pp_buf->input) {
+                            pme->releaseSuperBuf(pp_buf->input);
+                            free(pp_buf->input);
+                            pp_buf->input = NULL;
+                        }
+                        free(pp_buf);
                     }
                     mm_camera_super_buf_t *metadata = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
                     if (metadata != NULL) {
diff --git a/QCamera2/HAL3/QCamera3PostProc.h b/QCamera2/HAL3/QCamera3PostProc.h
index 16ba598..1737bb4 100644
--- a/QCamera2/HAL3/QCamera3PostProc.h
+++ b/QCamera2/HAL3/QCamera3PostProc.h
@@ -49,6 +49,7 @@
 class QCamera3ReprocessChannel;
 class QCamera3Stream;
 class QCamera3Memory;
+class QCamera3StreamMem;
 
 typedef struct {
     camera3_stream_buffer_t src_frame;// source frame
@@ -81,6 +82,12 @@
     mm_camera_super_buf_t *src_metadata;
 } qcamera_hal3_pp_data_t;
 
+typedef struct {
+    mm_camera_super_buf_t *input;
+    buffer_handle_t *output;
+    uint32_t frameNumber;
+} qcamera_hal3_pp_buffer_t;
+
 #define MAX_HAL3_EXIF_TABLE_ENTRIES 22
 class QCamera3Exif
 {
@@ -106,7 +113,7 @@
     QCamera3PostProcessor(QCamera3ProcessingChannel *ch_ctrl);
     virtual ~QCamera3PostProcessor();
 
-    int32_t init(QCamera3Memory *mMemory,
+    int32_t init(QCamera3StreamMem *mMemory,
             uint32_t postprocess_mask);
     int32_t initJpeg(jpeg_encode_callback_t jpeg_cb,
             cam_dimension_t *m_max_pic_dim,
@@ -115,13 +122,16 @@
     int32_t start(const reprocess_config_t &config);
     int32_t stop();
     int32_t processData(qcamera_fwk_input_pp_data_t *frame);
-    int32_t processData(mm_camera_super_buf_t *frame);
-    int32_t processRawData(mm_camera_super_buf_t *frame);
+    int32_t processData(mm_camera_super_buf_t *input,
+            buffer_handle_t *output, uint32_t frameNumber);
+    int32_t processData(mm_camera_super_buf_t *input);
     int32_t processPPData(mm_camera_super_buf_t *frame);
     int32_t processPPMetadata(mm_camera_super_buf_t *reproc_meta);
     int32_t processJpegSettingData(jpeg_settings_t *jpeg_settings);
+    qcamera_hal3_pp_data_t *dequeuePPJob(uint32_t frameNumber);
     qcamera_hal3_jpeg_data_t *findJpegJobByJobId(uint32_t jobId);
     void releaseJpegJobData(qcamera_hal3_jpeg_data_t *job);
+    void releasePPJobData(qcamera_hal3_pp_data_t *job);
     int32_t releaseOfflineBuffers();
 
 private:
@@ -161,7 +171,7 @@
     uint32_t                   mPostProcMask;
 
     uint32_t                   m_bThumbnailNeeded;
-    QCamera3Memory             *mOutputMem;
+    QCamera3StreamMem          *mOutputMem;
     QCamera3ReprocessChannel *  m_pReprocChannel;
 
     QCameraQueue m_inputPPQ;            // input queue for postproc
diff --git a/QCamera2/HAL3/QCamera3Stream.cpp b/QCamera2/HAL3/QCamera3Stream.cpp
index 3f005e0..7e7902c 100644
--- a/QCamera2/HAL3/QCamera3Stream.cpp
+++ b/QCamera2/HAL3/QCamera3Stream.cpp
@@ -745,22 +745,28 @@
         return NO_MEMORY;
     }
 
-    uint32_t registeredBuffers = mStreamBufs->getCnt();
-    for (uint32_t i = 0; i < registeredBuffers; i++) {
-        ssize_t bufSize = mStreamBufs->getSize(i);
-        if (BAD_INDEX != bufSize) {
-            rc = ops_tbl->map_ops(i, -1, mStreamBufs->getFd(i),
-                    (size_t)bufSize, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
-            if (rc < 0) {
-                ALOGE("%s: map_stream_buf failed: %d", __func__, rc);
-                for (uint32_t j = 0; j < i; j++) {
-                    ops_tbl->unmap_ops(j, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
+    for (uint32_t i = 0; i < mNumBufs; i++) {
+        if (mStreamBufs->valid(i)) {
+            ssize_t bufSize = mStreamBufs->getSize(i);
+            if (BAD_INDEX != bufSize) {
+                rc = ops_tbl->map_ops(i, -1, mStreamBufs->getFd(i),
+                        (size_t)bufSize, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
+                        ops_tbl->userdata);
+                if (rc < 0) {
+                    ALOGE("%s: map_stream_buf failed: %d", __func__, rc);
+                    for (uint32_t j = 0; j < i; j++) {
+                        if (mStreamBufs->valid(j)) {
+                            ops_tbl->unmap_ops(j, -1,
+                                    CAM_MAPPING_BUF_TYPE_STREAM_BUF,
+                                    ops_tbl->userdata);
+                        }
+                    }
+                    return INVALID_OPERATION;
                 }
+            } else {
+                ALOGE("Failed to retrieve buffer size (bad index)");
                 return INVALID_OPERATION;
             }
-        } else {
-            ALOGE("Failed to retrieve buffer size (bad index)");
-            return INVALID_OPERATION;
         }
     }
 
@@ -768,8 +774,11 @@
     regFlags = (uint8_t *)malloc(sizeof(uint8_t) * mNumBufs);
     if (!regFlags) {
         ALOGE("%s: Out of memory", __func__);
-        for (uint32_t i = 0; i < registeredBuffers; i++) {
-            ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
+        for (uint32_t i = 0; i < mNumBufs; i++) {
+            if (mStreamBufs->valid(i)) {
+                ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
+                        ops_tbl->userdata);
+            }
         }
         return NO_MEMORY;
     }
@@ -778,23 +787,31 @@
     mBufDefs = (mm_camera_buf_def_t *)malloc(mNumBufs * sizeof(mm_camera_buf_def_t));
     if (mBufDefs == NULL) {
         ALOGE("%s: Failed to allocate mm_camera_buf_def_t %d", __func__, rc);
-        for (uint32_t i = 0; i < registeredBuffers; i++) {
-            ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
+        for (uint32_t i = 0; i < mNumBufs; i++) {
+            if (mStreamBufs->valid(i)) {
+                ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
+                        ops_tbl->userdata);
+            }
         }
         free(regFlags);
         regFlags = NULL;
         return INVALID_OPERATION;
     }
     memset(mBufDefs, 0, mNumBufs * sizeof(mm_camera_buf_def_t));
-    for (uint32_t i = 0; i < registeredBuffers; i++) {
-        mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[i], i);
+    for (uint32_t i = 0; i < mNumBufs; i++) {
+        if (mStreamBufs->valid(i)) {
+            mStreamBufs->getBufDef(mFrameLenOffset, mBufDefs[i], i);
+        }
     }
 
     rc = mStreamBufs->getRegFlags(regFlags);
     if (rc < 0) {
         ALOGE("%s: getRegFlags failed %d", __func__, rc);
-        for (uint32_t i = 0; i < registeredBuffers; i++) {
-            ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
+        for (uint32_t i = 0; i < mNumBufs; i++) {
+            if (mStreamBufs->valid(i)) {
+                ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF,
+                        ops_tbl->userdata);
+            }
         }
         free(mBufDefs);
         mBufDefs = NULL;
@@ -827,7 +844,7 @@
     Mutex::Autolock lock(mLock);
 
     for (uint32_t i = 0; i < mNumBufs; i++) {
-        if (NULL != mBufDefs[i].mem_info) {
+        if (mStreamBufs->valid(i) && NULL != mBufDefs[i].mem_info) {
             rc = ops_tbl->unmap_ops(i, -1, CAM_MAPPING_BUF_TYPE_STREAM_BUF, ops_tbl->userdata);
             if (rc < 0) {
                 ALOGE("%s: un-map stream buf failed: %d", __func__, rc);
diff --git a/QCamera2/HAL3/QCamera3Stream.h b/QCamera2/HAL3/QCamera3Stream.h
index 4ba4567..b3abbed 100644
--- a/QCamera2/HAL3/QCamera3Stream.h
+++ b/QCamera2/HAL3/QCamera3Stream.h
@@ -34,6 +34,7 @@
 #include "utils/Mutex.h"
 #include "QCameraCmdThread.h"
 #include "QCamera3Mem.h"
+#include "QCamera3StreamMem.h"
 
 extern "C" {
 #include <mm_camera_interface.h>
@@ -82,7 +83,7 @@
     int32_t getFrameOffset(cam_frame_len_offset_t &offset);
     int32_t getFrameDimension(cam_dimension_t &dim);
     int32_t getFormat(cam_format_t &fmt);
-    QCamera3Memory *getStreamBufs() {return mStreamBufs;};
+    QCamera3StreamMem *getStreamBufs() {return mStreamBufs;};
     uint32_t getMyServerID();
 
     int32_t mapBuf(uint8_t buf_type, uint32_t buf_idx,
@@ -108,7 +109,7 @@
     QCameraCmdThread mProcTh; // thread for dataCB
 
     QCamera3HeapMemory *mStreamInfoBuf;
-    QCamera3Memory *mStreamBufs;
+    QCamera3StreamMem *mStreamBufs;
     mm_camera_buf_def_t *mBufDefs;
     cam_frame_len_offset_t mFrameLenOffset;
     cam_padding_info_t mPaddingInfo;
diff --git a/QCamera2/HAL3/QCamera3StreamMem.cpp b/QCamera2/HAL3/QCamera3StreamMem.cpp
new file mode 100644
index 0000000..24329e1
--- /dev/null
+++ b/QCamera2/HAL3/QCamera3StreamMem.cpp
@@ -0,0 +1,478 @@
+/* Copyright (c) 2012-2015, The Linux Foundataion. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define LOG_TAG "QCamera3StreamMem"
+
+#include <string.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <utils/Log.h>
+#include <utils/Errors.h>
+#include <gralloc_priv.h>
+#include <qdMetaData.h>
+#include "QCamera3Mem.h"
+#include "QCamera3HWI.h"
+
+extern "C" {
+#include <mm_camera_interface.h>
+}
+
+using namespace android;
+
+namespace qcamera {
+
+/*===========================================================================
+ * FUNCTION   : QCamera3StreamMem
+ *
+ * DESCRIPTION: default constructor of QCamera3StreamMem
+ *
+ * PARAMETERS : none
+ *
+ * RETURN     : None
+ *==========================================================================*/
+QCamera3StreamMem::QCamera3StreamMem(uint32_t maxHeapBuffer) :
+        mHeapMem(maxHeapBuffer),
+        mGrallocMem(maxHeapBuffer),
+        mMaxHeapBuffers(maxHeapBuffer)
+{
+}
+
+/*===========================================================================
+ * FUNCTION   : QCamera3StreamMem
+ *
+ * DESCRIPTION: destructor of QCamera3StreamMem
+ *
+ * PARAMETERS : none
+ *
+ * RETURN     : None
+ *==========================================================================*/
+QCamera3StreamMem::~QCamera3StreamMem()
+{
+    clear();
+}
+
+/*===========================================================================
+ * FUNCTION   : getCnt
+ *
+ * DESCRIPTION: query number of buffers allocated/registered
+ *
+ * PARAMETERS : none
+ *
+ * RETURN     : number of buffers allocated
+ *==========================================================================*/
+uint32_t QCamera3StreamMem::getCnt()
+{
+    Mutex::Autolock lock(mLock);
+
+    return (mHeapMem.getCnt() + mGrallocMem.getCnt());
+}
+
+/*===========================================================================
+ * FUNCTION   : getRegFlags
+ *
+ * DESCRIPTION: query initial reg flags
+ *
+ * PARAMETERS :
+ *   @regFlags: initial reg flags of the allocated/registered buffers
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int QCamera3StreamMem::getRegFlags(uint8_t * regFlags)
+{
+    // Assume that all buffers allocated can be queued.
+    mHeapMem.getRegFlags(regFlags);
+    return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION   : getFd
+ *
+ * DESCRIPTION: return file descriptor of the indexed buffer
+ *
+ * PARAMETERS :
+ *   @index   : index of the buffer
+ *
+ * RETURN     : file descriptor
+ *==========================================================================*/
+int QCamera3StreamMem::getFd(uint32_t index)
+{
+    Mutex::Autolock lock(mLock);
+
+    if (index < mMaxHeapBuffers)
+        return mHeapMem.getFd(index);
+    else
+        return mGrallocMem.getFd(index);
+}
+
+/*===========================================================================
+ * FUNCTION   : getSize
+ *
+ * DESCRIPTION: return buffer size of the indexed buffer
+ *
+ * PARAMETERS :
+ *   @index   : index of the buffer
+ *
+ * RETURN     : buffer size
+ *==========================================================================*/
+ssize_t QCamera3StreamMem::getSize(uint32_t index)
+{
+    Mutex::Autolock lock(mLock);
+
+    if (index < mMaxHeapBuffers)
+        return mHeapMem.getSize(index);
+    else
+        return mGrallocMem.getSize(index);
+}
+
+/*===========================================================================
+ * FUNCTION   : invalidateCache
+ *
+ * DESCRIPTION: invalidate the cache of the indexed buffer
+ *
+ * PARAMETERS :
+ *   @index   : index of the buffer
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int QCamera3StreamMem::invalidateCache(uint32_t index)
+{
+    Mutex::Autolock lock(mLock);
+
+    if (index < mMaxHeapBuffers)
+        return mHeapMem.invalidateCache(index);
+    else
+        return mGrallocMem.invalidateCache(index);
+}
+
+/*===========================================================================
+ * FUNCTION   : cleanInvalidateCache
+ *
+ * DESCRIPTION: clean and invalidate the cache of the indexed buffer
+ *
+ * PARAMETERS :
+ *   @index   : index of the buffer
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int QCamera3StreamMem::cleanInvalidateCache(uint32_t index)
+{
+    Mutex::Autolock lock(mLock);
+
+    if (index < mMaxHeapBuffers)
+        return mHeapMem.cleanInvalidateCache(index);
+    else
+        return mGrallocMem.cleanInvalidateCache(index);
+}
+
+/*===========================================================================
+ * FUNCTION   : getBufDef
+ *
+ * DESCRIPTION: query detailed buffer information
+ *
+ * PARAMETERS :
+ *   @offset  : [input] frame buffer offset
+ *   @bufDef  : [output] reference to struct to store buffer definition
+ *   @index   : [input] index of the buffer
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3StreamMem::getBufDef(const cam_frame_len_offset_t &offset,
+        mm_camera_buf_def_t &bufDef, uint32_t index)
+{
+    int32_t ret = NO_ERROR;
+
+    if (index < mMaxHeapBuffers)
+        ret = mHeapMem.getBufDef(offset, bufDef, index);
+    else
+        ret = mGrallocMem.getBufDef(offset, bufDef, index);
+
+    bufDef.mem_info = (void *)this;
+
+    return ret;
+}
+
+/*===========================================================================
+ * FUNCTION   : getPtr
+ *
+ * DESCRIPTION: return virtual address of the indexed buffer
+ *
+ * PARAMETERS :
+ *   @index   : index of the buffer
+ *
+ * RETURN     : virtual address
+ *==========================================================================*/
+void* QCamera3StreamMem::getPtr(uint32_t index)
+{
+    Mutex::Autolock lock(mLock);
+
+    if (index < mMaxHeapBuffers)
+        return mHeapMem.getPtr(index);
+    else
+        return mGrallocMem.getPtr(index);
+}
+
+/*===========================================================================
+ * FUNCTION   : valid
+ *
+ * DESCRIPTION: return whether there is a valid buffer at the current index
+ *
+ * PARAMETERS :
+ *   @index   : index of the buffer
+ *
+ * RETURN     : true if there is a buffer, false otherwise
+ *==========================================================================*/
+bool QCamera3StreamMem::valid(uint32_t index)
+{
+    Mutex::Autolock lock(mLock);
+
+    if (index < mMaxHeapBuffers)
+        return (mHeapMem.getSize(index) > 0);
+    else
+        return (mGrallocMem.getSize(index) > 0);
+}
+
+/*===========================================================================
+ * FUNCTION   : registerBuffer
+ *
+ * DESCRIPTION: registers frameworks-allocated gralloc buffer_handle_t
+ *
+ * PARAMETERS :
+ *   @buffers : buffer_handle_t pointer
+ *   @type :    cam_stream_type_t
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int QCamera3StreamMem::registerBuffer(buffer_handle_t *buffer,
+        cam_stream_type_t type)
+{
+    Mutex::Autolock lock(mLock);
+    return mGrallocMem.registerBuffer(buffer, type);
+}
+
+
+/*===========================================================================
+ * FUNCTION   : unregisterBuffer
+ *
+ * DESCRIPTION: unregister buffer
+ *
+ * PARAMETERS :
+ *   @idx     : unregister buffer at index 'idx'
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3StreamMem::unregisterBuffer(size_t idx)
+{
+    Mutex::Autolock lock(mLock);
+    return mGrallocMem.unregisterBuffer(idx);
+}
+
+/*===========================================================================
+ * FUNCTION   : getMatchBufIndex
+ *
+ * DESCRIPTION: query buffer index by object ptr
+ *
+ * PARAMETERS :
+ *   @opaque  : opaque ptr
+ *
+ * RETURN     : buffer index if match found,
+ *              -1 if failed
+ *==========================================================================*/
+int QCamera3StreamMem::getMatchBufIndex(void *object)
+{
+    Mutex::Autolock lock(mLock);
+    return mGrallocMem.getMatchBufIndex(object);
+}
+
+/*===========================================================================
+ * FUNCTION   : getBufferHandle
+ *
+ * DESCRIPTION: return framework pointer
+ *
+ * PARAMETERS :
+ *   @index   : index of the buffer
+ *
+ * RETURN     : buffer ptr if match found
+                NULL if failed
+ *==========================================================================*/
+void *QCamera3StreamMem::getBufferHandle(uint32_t index)
+{
+    Mutex::Autolock lock(mLock);
+    return mGrallocMem.getBufferHandle(index);
+}
+
+/*===========================================================================
+ * FUNCTION   : unregisterBuffers
+ *
+ * DESCRIPTION: unregister buffers
+ *
+ * PARAMETERS : none
+ *
+ * RETURN     : none
+ *==========================================================================*/
+void QCamera3StreamMem::unregisterBuffers()
+{
+    Mutex::Autolock lock(mLock);
+    mGrallocMem.unregisterBuffers();
+}
+
+
+/*===========================================================================
+ * FUNCTION   : allocate
+ *
+ * DESCRIPTION: allocate requested number of buffers of certain size
+ *
+ * PARAMETERS :
+ *   @count   : number of buffers to be allocated
+ *   @size    : lenght of the buffer to be allocated
+ *   @queueAll: queue all buffers in the beginning
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int QCamera3StreamMem::allocate(uint32_t count, size_t size, bool queueAll)
+{
+    Mutex::Autolock lock(mLock);
+    return mHeapMem.allocate(count, size, queueAll);
+}
+
+/*===========================================================================
+ * FUNCTION   : deallocate
+ *
+ * DESCRIPTION: deallocate heap buffers
+ *
+ * PARAMETERS : none
+ *
+ * RETURN     : none
+ *==========================================================================*/
+void QCamera3StreamMem::deallocate()
+{
+    Mutex::Autolock lock(mLock);
+    mHeapMem.deallocate();
+}
+
+/*===========================================================================
+ * FUNCTION   : markFrameNumber
+ *
+ * DESCRIPTION: We use this function from the request call path to mark the
+ *              buffers with the frame number they are intended for this info
+ *              is used later when giving out callback & it is duty of PP to
+ *              ensure that data for that particular frameNumber/Request is
+ *              written to this buffer.
+ * PARAMETERS :
+ *   @index   : index of the buffer
+ *   @frame#  : Frame number from the framework
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3StreamMem::markFrameNumber(uint32_t index, uint32_t frameNumber)
+{
+    Mutex::Autolock lock(mLock);
+    if (index < mMaxHeapBuffers)
+        return mHeapMem.markFrameNumber(index, frameNumber);
+    else
+        return mGrallocMem.markFrameNumber(index, frameNumber);
+}
+
+/*===========================================================================
+ * FUNCTION   : getFrameNumber
+ *
+ * DESCRIPTION: We use this to fetch the frameNumber for the request with which
+ *              this buffer was given to HAL
+ *
+ *
+ * PARAMETERS :
+ *   @index   : index of the buffer
+ *
+ * RETURN     : int32_t frameNumber
+ *              positive/zero  -- success
+ *              negative failure
+ *==========================================================================*/
+int32_t QCamera3StreamMem::getFrameNumber(uint32_t index)
+{
+    Mutex::Autolock lock(mLock);
+    if (index < mMaxHeapBuffers)
+        return mHeapMem.getFrameNumber(index);
+    else
+        return mGrallocMem.getFrameNumber(index);
+}
+
+/*===========================================================================
+ * FUNCTION   : getGrallocBufferIndex
+ *
+ * DESCRIPTION: We use this to fetch the gralloc buffer index based on frameNumber
+ *
+ * PARAMETERS :
+ *   @frameNumber : frame Number
+ *
+ * RETURN     : int32_t buffer index
+ *              positive/zero  -- success
+ *              negative failure
+ *==========================================================================*/
+int32_t QCamera3StreamMem::getGrallocBufferIndex(uint32_t frameNumber)
+{
+    Mutex::Autolock lock(mLock);
+    int32_t index = mGrallocMem.getBufferIndex(frameNumber);
+    return index;
+}
+
+/*===========================================================================
+ * FUNCTION   : getHeapBufferIndex
+ *
+ * DESCRIPTION: We use this to fetch the heap buffer index based on frameNumber
+ *
+ * PARAMETERS :
+ *   @frameNumber : frame Number
+ *
+ * RETURN     : int32_t buffer index
+ *              positive/zero  -- success
+ *              negative failure
+ *==========================================================================*/
+int32_t QCamera3StreamMem::getHeapBufferIndex(uint32_t frameNumber)
+{
+    Mutex::Autolock lock(mLock);
+    int32_t index = mHeapMem.getBufferIndex(frameNumber);
+    return index;
+}
+
+}; //namespace qcamera
diff --git a/QCamera2/HAL3/QCamera3StreamMem.h b/QCamera2/HAL3/QCamera3StreamMem.h
new file mode 100644
index 0000000..a9569f8
--- /dev/null
+++ b/QCamera2/HAL3/QCamera3StreamMem.h
@@ -0,0 +1,96 @@
+/* Copyright (c) 2012-2015, The Linux Foundataion. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __QCAMERA3_STREAMMEM_H__
+#define __QCAMERA3_STREAMMEM_H__
+
+#include <hardware/camera3.h>
+#include <utils/Mutex.h>
+#include "QCamera3Mem.h"
+
+extern "C" {
+#include <sys/types.h>
+#include <linux/msm_ion.h>
+#include <mm_camera_interface.h>
+}
+
+using namespace android;
+
+namespace qcamera {
+
+class QCamera3StreamMem {
+public:
+    QCamera3StreamMem(uint32_t maxHeapBuffer);
+    virtual ~QCamera3StreamMem();
+
+    uint32_t getCnt();
+    int getRegFlags(uint8_t *regFlags);
+
+    // Helper function to access individual QCamera3Buffer object
+    int getFd(uint32_t index);
+    ssize_t getSize(uint32_t index);
+    int invalidateCache(uint32_t index);
+    int cleanInvalidateCache(uint32_t index);
+    int32_t getBufDef(const cam_frame_len_offset_t &offset,
+            mm_camera_buf_def_t &bufDef, uint32_t index);
+    void *getPtr(uint32_t index);
+
+    bool valid(uint32_t index);
+
+    // Gralloc buffer related functions
+    int registerBuffer(buffer_handle_t *buffer, cam_stream_type_t type);
+    int unregisterBuffer(uint32_t index);
+    int getMatchBufIndex(void *object);
+    void *getBufferHandle(uint32_t index);
+    void unregisterBuffers(); //TODO: relace with unififed clear() function?
+
+    // Heap buffer related functions
+    //TODO: Support returning buffer indices to the caller.
+    int allocate(uint32_t count, size_t size, bool queueAll);
+    void deallocate(); //TODO: replace with unified clear() function?
+
+    // Clear function: unregister for gralloc buffer, and deallocate for heap buffer
+    void clear() {unregisterBuffers(); deallocate(); }
+
+    // Frame number getter and setter
+    int32_t markFrameNumber(uint32_t index, uint32_t frameNumber);
+    int32_t getFrameNumber(uint32_t index);
+    int32_t getGrallocBufferIndex(uint32_t frameNumber);
+    int32_t getHeapBufferIndex(uint32_t frameNumber);
+
+private:
+    //variables
+    QCamera3HeapMemory mHeapMem;
+    QCamera3GrallocMemory mGrallocMem;
+    uint32_t mMaxHeapBuffers;
+    Mutex mLock;
+};
+
+};
+#endif // __QCAMERA3_STREAMMEM_H__
diff --git a/QCamera2/stack/common/cam_types.h b/QCamera2/stack/common/cam_types.h
index e9ffd3c..f2c469d 100644
--- a/QCamera2/stack/common/cam_types.h
+++ b/QCamera2/stack/common/cam_types.h
@@ -705,13 +705,15 @@
     CAM_NOISE_REDUCTION_MODE_OFF,
     CAM_NOISE_REDUCTION_MODE_FAST,
     CAM_NOISE_REDUCTION_MODE_HIGH_QUALITY,
-    CAM_NOISE_REDUCTION_MODE_MINIMAL
+    CAM_NOISE_REDUCTION_MODE_MINIMAL,
+    CAM_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG
 } cam_noise_reduction_mode_t;
 
 typedef enum {
     CAM_EDGE_MODE_OFF,
     CAM_EDGE_MODE_FAST,
     CAM_EDGE_MODE_HIGH_QUALITY,
+    CAM_EDGE_MODE_ZERO_SHUTTER_LAG,
 } cam_edge_mode_t;
 
 typedef struct {
diff --git a/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c b/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
index 756413c..2eb27bc 100755
--- a/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
+++ b/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
@@ -1267,7 +1267,7 @@
         buf_info->buf->ts.tv_sec  = vb.timestamp.tv_sec;
         buf_info->buf->ts.tv_nsec = vb.timestamp.tv_usec * 1000;
 
-        CDBG("%s: VIDIOC_DQBUF buf_index %d, frame_idx %d, stream type %d, rc %d,"
+        CDBG_HIGH("%s: VIDIOC_DQBUF buf_index %d, frame_idx %d, stream type %d, rc %d,"
                 "queued: %d, buf_type = %d",
             __func__, vb.index, buf_info->buf->frame_idx,
             my_obj->stream_info->stream_type, rc,
@@ -1512,7 +1512,7 @@
                 my_obj, my_obj->stream_info->stream_type);
         }
     } else {
-        CDBG("%s: VIDIOC_QBUF buf_index %d, stream type %d, rc %d, queued: %d", __func__,
+        CDBG_HIGH("%s: VIDIOC_QBUF buf_index %d, stream type %d, rc %d, queued: %d", __func__,
             buffer.index, my_obj->stream_info->stream_type, rc, my_obj->queued_buffer_count);
     }
 
@@ -1607,6 +1607,9 @@
     packet.payload.buf_map.stream_id = my_obj->server_stream_id;
     packet.payload.buf_map.frame_idx = frame_idx;
     packet.payload.buf_map.plane_idx = plane_idx;
+
+    CDBG("%s: mapping buf_type %d, stream_id %d, frame_idx %d, fd %d, size %d",
+            __func__, buf_type, my_obj->server_stream_id, frame_idx, fd, size);
     return mm_camera_util_sendmsg(my_obj->ch_obj->cam_obj,
                                   &packet,
                                   sizeof(cam_sock_packet_t),