Camera-Unified HAL changes for 7x27a

Change-Id: Ie6f7fb08d38c29f72a82166503b3bdd8f7e29ac5
diff --git a/Android.mk b/Android.mk
index 3c9fe11..3c3ff99 100755
--- a/Android.mk
+++ b/Android.mk
@@ -14,11 +14,18 @@
 

 LOCAL_CFLAGS:= -DDLOPEN_LIBMMCAMERA=$(DLOPEN_LIBMMCAMERA)

 

+#define BUILD_UNIFIED_CODE

+BUILD_UNIFIED_CODE := FALSE

+

+ifeq ($(call is-board-platform,msm7627a),true)

+LOCAL_CFLAGS+= -DVFE_7X27A

+endif

+

 ifeq ($(strip $(TARGET_USES_ION)),true)

 LOCAL_CFLAGS += -DUSE_ION

 endif

 ifeq ($(call is-board-platform,msm8960),true)

-MM_CAM_FILES:= \

+   MM_CAM_FILES:= \

         mm_camera_interface2.c \

         mm_camera_stream.c \

         mm_camera_channel.c \

@@ -28,6 +35,20 @@
         mm_omx_jpeg_encoder.c \

         mm_camera_sock.c

 endif

+ifeq ($(call is-board-platform,msm7627a),true)

+ifeq ($(BUILD_UNIFIED_CODE), true)

+    MM_CAM_FILES:= \

+         mm_camera_interface2.c \

+         mm_camera_stream.c \

+         mm_camera_channel.c \

+         mm_camera.c \

+         mm_camera_poll_thread.c \

+         mm_camera_notify.c mm_camera_helper.c \

+         mm_omx_jpeg_encoder.c \

+        mm_camera_sock.c

+

+endif

+endif

 

 LOCAL_CFLAGS+= -DHW_ENCODE

 

@@ -40,6 +61,14 @@
                    QCameraHWI_Record.cpp QCameraHWI_Still.cpp \

                    QCameraHWI_Mem.cpp QCameraHWI_Display.cpp \

                    QCameraStream.cpp QualcommCamera2.cpp

+else ifeq ($(BUILD_UNIFIED_CODE), true)

+       ifeq ($(call is-board-platform,msm7627a),true)

+         LOCAL_HAL_FILES := QCameraHAL.cpp QCameraHWI_Parm.cpp\

+                          QCameraHWI.cpp QCameraHWI_Preview_7x27A.cpp \

+                          QCameraHWI_Record_7x27A.cpp QCameraHWI_Still.cpp \

+                          QCameraHWI_Mem.cpp QCameraHWI_Display.cpp \

+                          QCameraStream.cpp QualcommCamera2.cpp

+       endif

 else

 LOCAL_HAL_FILES := QualcommCamera.cpp QualcommCameraHardware.cpp

 MM_CAM_FILES:=

@@ -74,8 +103,12 @@
 ifeq ($(call is-board-platform,msm8960),true)

 LOCAL_C_INCLUDES+= $(TARGET_OUT_HEADERS)/mm-core/omxcore

 LOCAL_C_INCLUDES+= $(TARGET_OUT_HEADERS)/mm-still/mm-omx

+else ifeq ($(BUILD_UNIFIED_CODE), true)

+       ifeq ($(call is-board-platform,msm7627a),true)

+         LOCAL_C_INCLUDES+= $(TARGET_OUT_HEADERS)/mm-core/omxcore

+         LOCAL_C_INCLUDES+= $(TARGET_OUT_HEADERS)/mm-still/mm-omx

+       endif

 endif

-

 LOCAL_C_INCLUDES+= $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include/media

 LOCAL_C_INCLUDES+= $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include

 LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr

@@ -87,8 +120,12 @@
 

 ifeq ($(call is-board-platform,msm8960),true)

 LOCAL_SHARED_LIBRARIES:= libutils libui libcamera_client liblog libcutils libmmjpeg libmmstillomx libimage-jpeg-enc-omx-comp

+else ifeq ($(BUILD_UNIFIED_CODE), true)

+       ifeq ($(call is-board-platform,msm7627a),true)

+         LOCAL_SHARED_LIBRARIES:= libutils libui libcamera_client liblog libcutils libmmjpeg libmmstillomx libimage-jpeg-enc-omx-comp

+       endif

 else

-LOCAL_SHARED_LIBRARIES:= libutils libui libcamera_client liblog libcutils libmmjpeg

+   LOCAL_SHARED_LIBRARIES:= libutils libui libcamera_client liblog libcutils libmmjpeg

 endif

 

 LOCAL_SHARED_LIBRARIES+= libgenlock libbinder

diff --git a/QCameraHWI.h b/QCameraHWI.h
index 5c5661f..292881c 100755
--- a/QCameraHWI.h
+++ b/QCameraHWI.h
@@ -668,6 +668,7 @@
     bool mSendMetaData;
     bool mFullLiveshotEnabled;
     bool mRecordingHint;
+    bool mStartRecording;
     int mHdrMode;
 
 /*for histogram*/
diff --git a/QCameraHWI_Parm.cpp b/QCameraHWI_Parm.cpp
index 373767e..fb91705 100755
--- a/QCameraHWI_Parm.cpp
+++ b/QCameraHWI_Parm.cpp
@@ -135,6 +135,7 @@
     { 6144, 240, 160 },
     { 5006, 176, 144 },
 };
+#ifndef VFE_7X27A
 static camera_size_type jpeg_thumbnail_sizes[]  = {
   { 1920, 1088}, //1080p
   { 1280, 720}, // 720P, reserved
@@ -167,7 +168,6 @@
   { 240, 160}, // SQVGA
   { 176, 144}, // QCIF
 };
-
 static camera_size_type supported_video_sizes[] = {
   { 1920, 1088},// 1080p
   { 1280, 720}, // 720p
@@ -179,6 +179,62 @@
   { 320, 240},  // QVGA
   { 176, 144},  // QCIF
 };
+#else
+ static camera_size_type jpeg_thumbnail_sizes[]  = {
+  { 1920, 1088}, //1080p
+  { 1280, 720}, // 720P, reserved
+  { 800, 480}, // WVGA
+  { 864, 480},
+  { 768, 432},
+  { 720, 480},
+  { 640, 480}, // VGA
+  { 576, 432},
+  { 480, 320}, // HVGA
+  { 432, 240}, //WQVGA
+  { 384, 288},
+  { 352, 288}, // CIF
+  { 320, 240}, // QVGA
+  { 240, 160}, // SQVGA
+  { 176, 144}, // QCIF
+  {0,0}
+};
+
+static camera_size_type default_preview_sizes[] = {
+  { 1920, 1088}, //1080p
+  { 1280, 720}, // 720P, reserved
+  { 800, 480}, // WVGA
+  { 864, 480},
+  { 768, 432},
+  { 720, 480},
+  { 640, 480}, // VGA
+  { 576, 432},
+  { 480, 320}, // HVGA
+  { 432, 240}, //WQVGA
+  { 384, 288},
+  { 352, 288}, // CIF
+  { 320, 240}, // QVGA
+  { 240, 160}, // SQVGA
+  { 176, 144}, // QCIF
+};
+
+static camera_size_type supported_video_sizes[] = {
+  { 1920, 1088},// 1080p
+  { 1280, 720}, // 720p
+  { 800, 480},  // WVGA
+  { 864, 480},
+  { 768, 432},
+  { 720, 480},  // 480p
+  { 640, 480},  // VGA
+  { 576, 432},
+  { 480, 320},  // HVGA
+  { 432, 240}, //WQVGA
+  { 384, 288},
+  { 352, 288},  // CIF
+  { 320, 240},  // QVGA
+  { 240, 160}, // SQVGA
+  { 176, 144},  // QCIF
+};
+#endif
 #define SUPPORTED_VIDEO_SIZES_COUNT (sizeof(supported_video_sizes)/sizeof(camera_size_type))
 
 static struct camera_size_type zsl_picture_sizes[] = {
@@ -208,11 +264,17 @@
   { 320, 240}, // QVGA
   { 176, 144} // QCIF
 };
-
+#ifndef VFE_7X27A
 static camera_size_type hfr_sizes[] = {
   { 800, 480}, // WVGA
   { 640, 480} // VGA
 };
+#else
+ static camera_size_type hfr_sizes[] = {
+  { 432, 240}, //WQVGA
+  { 320, 240}  //QVGA
+};
+#endif
 
 static int iso_speed_values[] = {
     0, 1, 100, 200, 400, 800, 1600
@@ -1952,15 +2014,22 @@
 status_t QCameraHardwareInterface::setSelectableZoneAf(const CameraParameters& params)
 {
     LOGE("%s",__func__);
+    status_t rc = NO_ERROR;
     if(mHasAutoFocusSupport) {
         const char *str = params.get(CameraParameters::KEY_SELECTABLE_ZONE_AF);
         if (str != NULL) {
             int32_t value = attr_lookup(selectable_zone_af, sizeof(selectable_zone_af) / sizeof(str_map), str);
             if (value != NOT_FOUND) {
-                mParameters.set(CameraParameters::KEY_SELECTABLE_ZONE_AF, str);
-                bool ret = native_set_parms(MM_CAMERA_PARM_FOCUS_RECT, sizeof(value),
-                        (void *)&value);
-                return ret ? NO_ERROR : UNKNOWN_ERROR;
+                 rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_FOCUS_RECT);
+                 if(!rc) {
+                    LOGE("SelectableZoneAF  is not supported for this sensor");
+                    return NO_ERROR;
+                 }else {
+                    mParameters.set(CameraParameters::KEY_SELECTABLE_ZONE_AF, str);
+                    bool ret = native_set_parms(MM_CAMERA_PARM_FOCUS_RECT, sizeof(value),
+                            (void *)&value);
+                    return ret ? NO_ERROR : UNKNOWN_ERROR;
+                 }
             }
         }
         LOGE("Invalid selectable zone af value: %s", (str == NULL) ? "NULL" : str);
diff --git a/QCameraHWI_Preview_7x27A.cpp b/QCameraHWI_Preview_7x27A.cpp
new file mode 100644
index 0000000..165206a
--- /dev/null
+++ b/QCameraHWI_Preview_7x27A.cpp
@@ -0,0 +1,815 @@
+/*
+** Copyright (c) 2012 Code Aurora Forum. All rights reserved.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+/*#error uncomment this for compiler test!*/
+
+#define LOG_NDEBUG 0
+#define LOG_NIDEBUG 0
+#define LOG_TAG "QCameraHWI_Preview"
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include "QCameraHAL.h"
+#include "QCameraHWI.h"
+#include <gralloc_priv.h>
+#include <genlock.h>
+
+#define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
+
+/* QCameraHWI_Preview class implementation goes here*/
+/* following code implement the preview mode's image capture & display logic of this class*/
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+// Preview Callback
+// ---------------------------------------------------------------------------
+static void preview_notify_cb(mm_camera_ch_data_buf_t *frame,
+                                void *user_data)
+{
+  QCameraStream_preview *pme = (QCameraStream_preview *)user_data;
+  mm_camera_ch_data_buf_t *bufs_used = 0;
+  LOGV("%s: E", __func__);
+  /* for peview data, there is no queue, so directly use*/
+  if(pme==NULL) {
+    LOGE("%s: X : Incorrect cookie",__func__);
+    /*Call buf done*/
+    return;
+  }
+
+  pme->processPreviewFrame(frame);
+  LOGV("%s: X", __func__);
+}
+
+status_t QCameraStream_preview::setPreviewWindow(preview_stream_ops_t* window)
+{
+    status_t retVal = NO_ERROR;
+    LOGE(" %s: E ", __FUNCTION__);
+    if( window == NULL) {
+        LOGW(" Setting NULL preview window ");
+        /* TODO: Current preview window will be invalidated.
+         * Release all the buffers back */
+       // relinquishBuffers();
+    }
+    mDisplayLock.lock();
+    mPreviewWindow = window;
+    mDisplayLock.unlock();
+    LOGV(" %s : X ", __FUNCTION__ );
+    return retVal;
+}
+
+status_t QCameraStream_preview::getBufferFromSurface() {
+    int err = 0;
+    int numMinUndequeuedBufs = 0;
+	int format = 0;
+	status_t ret = NO_ERROR;
+
+    LOGI(" %s : E ", __FUNCTION__);
+
+    if( mPreviewWindow == NULL) {
+		LOGE("%s: mPreviewWindow = NULL", __func__);
+        return INVALID_OPERATION;
+	}
+    cam_ctrl_dimension_t dim;
+
+	//mDisplayLock.lock();
+    cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim);
+
+	format = mHalCamCtrl->getPreviewFormatInfo().Hal_format;
+	if(ret != NO_ERROR) {
+        LOGE("%s: display format %d is not supported", __func__, dim.prev_format);
+		goto end;
+	}
+	numMinUndequeuedBufs = 0;
+	if(mPreviewWindow->get_min_undequeued_buffer_count) {
+    err = mPreviewWindow->get_min_undequeued_buffer_count(mPreviewWindow, &numMinUndequeuedBufs);
+		if (err != 0) {
+			 LOGE("get_min_undequeued_buffer_count  failed: %s (%d)",
+						strerror(-err), -err);
+			 ret = UNKNOWN_ERROR;
+			 goto end;
+		}
+	}
+    mHalCamCtrl->mPreviewMemoryLock.lock();
+    mHalCamCtrl->mPreviewMemory.buffer_count = kPreviewBufferCount + numMinUndequeuedBufs;;
+    err = mPreviewWindow->set_buffer_count(mPreviewWindow, mHalCamCtrl->mPreviewMemory.buffer_count );
+    if (err != 0) {
+         LOGE("set_buffer_count failed: %s (%d)",
+                    strerror(-err), -err);
+         ret = UNKNOWN_ERROR;
+		 goto end;
+    }
+    err = mPreviewWindow->set_buffers_geometry(mPreviewWindow,
+                dim.display_width, dim.display_height, format);
+    if (err != 0) {
+         LOGE("set_buffers_geometry failed: %s (%d)",
+                    strerror(-err), -err);
+         ret = UNKNOWN_ERROR;
+		 goto end;
+    }
+    err = mPreviewWindow->set_usage(mPreviewWindow,
+                GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
+                GRALLOC_USAGE_PRIVATE_UNCACHED);
+	if(err != 0) {
+        /* set_usage error out */
+		LOGE("%s: set_usage rc = %d", __func__, err);
+		ret = UNKNOWN_ERROR;
+		goto end;
+	}
+	for (int cnt = 0; cnt < mHalCamCtrl->mPreviewMemory.buffer_count; cnt++) {
+		int stride;
+		err = mPreviewWindow->dequeue_buffer(mPreviewWindow,
+										&mHalCamCtrl->mPreviewMemory.buffer_handle[cnt],
+										&mHalCamCtrl->mPreviewMemory.stride[cnt]);
+		if(!err) {
+                    err = mPreviewWindow->lock_buffer(this->mPreviewWindow,
+                                       mHalCamCtrl->mPreviewMemory.buffer_handle[cnt]);
+
+                    // lock the buffer using genlock
+                    LOGD("%s: camera call genlock_lock", __FUNCTION__);
+                    if (GENLOCK_NO_ERROR != genlock_lock_buffer((native_handle_t *)(*mHalCamCtrl->mPreviewMemory.buffer_handle[cnt]),
+                                                      GENLOCK_WRITE_LOCK, GENLOCK_MAX_TIMEOUT)) {
+                       LOGE("%s: genlock_lock_buffer(WRITE) failed", __FUNCTION__);
+                       mHalCamCtrl->mPreviewMemory.local_flag[cnt] = BUFFER_UNLOCKED;
+	               mHalCamCtrl->mPreviewMemoryLock.unlock();
+                       return -EINVAL;
+                   }
+		   mHalCamCtrl->mPreviewMemory.local_flag[cnt] = BUFFER_LOCKED;
+		} else
+			LOGE("%s: dequeue_buffer idx = %d err = %d", __func__, cnt, err);
+
+		LOGE("%s: dequeue buf: %u\n", __func__, (unsigned int)mHalCamCtrl->mPreviewMemory.buffer_handle[cnt]);
+
+		if(err != 0) {
+            LOGE("%s: dequeue_buffer failed: %s (%d)", __func__,
+                    strerror(-err), -err);
+            ret = UNKNOWN_ERROR;
+			for(int i = 0; i < cnt; i++) {
+                        LOGD("%s: camera call genlock_unlock", __FUNCTION__);
+                        if (BUFFER_LOCKED == mHalCamCtrl->mPreviewMemory.local_flag[i]) {
+                             if (GENLOCK_FAILURE == genlock_unlock_buffer((native_handle_t *)
+                                                          (*(mHalCamCtrl->mPreviewMemory.buffer_handle[i])))) {
+                                LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
+	                        mHalCamCtrl->mPreviewMemoryLock.unlock();
+                                return -EINVAL;
+                             }
+                        }
+		        err = mPreviewWindow->cancel_buffer(mPreviewWindow,
+										mHalCamCtrl->mPreviewMemory.buffer_handle[i]);
+				mHalCamCtrl->mPreviewMemory.buffer_handle[i] = NULL;
+				mHalCamCtrl->mPreviewMemory.local_flag[i] = BUFFER_UNLOCKED;
+			}
+			goto end;
+		}
+		mHalCamCtrl->mPreviewMemory.private_buffer_handle[cnt] =
+		    (struct private_handle_t *)(*mHalCamCtrl->mPreviewMemory.buffer_handle[cnt]);
+		mHalCamCtrl->mPreviewMemory.camera_memory[cnt] =
+		    mHalCamCtrl->mGetMemory(mHalCamCtrl->mPreviewMemory.private_buffer_handle[cnt]->fd,
+			mHalCamCtrl->mPreviewMemory.private_buffer_handle[cnt]->size, 1, (void *)this);
+		LOGE("%s: idx = %d, fd = %d, size = %d, offset = %d", __func__,
+            cnt, mHalCamCtrl->mPreviewMemory.private_buffer_handle[cnt]->fd,
+			mHalCamCtrl->mPreviewMemory.private_buffer_handle[cnt]->size,
+			mHalCamCtrl->mPreviewMemory.private_buffer_handle[cnt]->offset);
+	}
+
+
+	memset(&mHalCamCtrl->mMetadata, 0, sizeof(mHalCamCtrl->mMetadata));
+	memset(mHalCamCtrl->mFace, 0, sizeof(mHalCamCtrl->mFace));
+
+    LOGI(" %s : X ",__FUNCTION__);
+end:
+	//mDisplayLock.unlock();
+	mHalCamCtrl->mPreviewMemoryLock.unlock();
+
+    return NO_ERROR;
+}
+
+status_t QCameraStream_preview::putBufferToSurface() {
+    int err = 0;
+	status_t ret = NO_ERROR;
+
+    LOGI(" %s : E ", __FUNCTION__);
+
+    //mDisplayLock.lock();
+    mHalCamCtrl->mPreviewMemoryLock.lock();
+	for (int cnt = 0; cnt < mHalCamCtrl->mPreviewMemory.buffer_count; cnt++) {
+        mHalCamCtrl->mPreviewMemory.camera_memory[cnt]->release(mHalCamCtrl->mPreviewMemory.camera_memory[cnt]);
+            if (BUFFER_LOCKED == mHalCamCtrl->mPreviewMemory.local_flag[cnt]) {
+                LOGD("%s: camera call genlock_unlock", __FUNCTION__);
+	        if (GENLOCK_FAILURE == genlock_unlock_buffer((native_handle_t *)
+                                                    (*(mHalCamCtrl->mPreviewMemory.buffer_handle[cnt])))) {
+                    LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
+	            mHalCamCtrl->mPreviewMemoryLock.unlock();
+                    return -EINVAL;
+                } else {
+                    mHalCamCtrl->mPreviewMemory.local_flag[cnt] = BUFFER_UNLOCKED;
+                }
+            }
+            err = mPreviewWindow->cancel_buffer(mPreviewWindow, mHalCamCtrl->mPreviewMemory.buffer_handle[cnt]);
+		LOGE(" put buffer %d successfully", cnt);
+	}
+	memset(&mHalCamCtrl->mPreviewMemory, 0, sizeof(mHalCamCtrl->mPreviewMemory));
+	mHalCamCtrl->mPreviewMemoryLock.unlock();
+	//mDisplayLock.unlock();
+    LOGI(" %s : X ",__FUNCTION__);
+    return NO_ERROR;
+}
+
+void QCameraStream_preview::notifyROIEvent(fd_roi_t roi)
+{
+    int faces_detected = roi.rect_num;
+    if(faces_detected > MAX_ROI)
+      faces_detected = MAX_ROI;
+    LOGI("%s, width = %d height = %d", __func__,
+       mHalCamCtrl->mDimension.display_width,
+       mHalCamCtrl->mDimension.display_height);
+    mDisplayLock.lock();
+    for (int i = 0; i < faces_detected; i++) {
+       mHalCamCtrl->mFace[i].rect[0] =
+           roi.faces[i].x*2000/mHalCamCtrl->mDimension.display_width - 1000;
+       mHalCamCtrl->mFace[i].rect[1] =
+           roi.faces[i].y*2000/mHalCamCtrl->mDimension.display_height - 1000;
+       mHalCamCtrl->mFace[i].rect[2] =
+           roi.faces[i].dx*2000/mHalCamCtrl->mDimension.display_width;
+       mHalCamCtrl->mFace[i].rect[3] =
+           roi.faces[i].dy*2000/mHalCamCtrl->mDimension.display_height;
+    }
+    mHalCamCtrl->mMetadata.number_of_faces = faces_detected;
+    mHalCamCtrl->mMetadata.faces = mHalCamCtrl->mFace;
+    mDisplayLock.unlock();
+}
+
+status_t QCameraStream_preview::initDisplayBuffers()
+{
+    status_t ret = NO_ERROR;
+    int width = 0;  /* width of channel  */
+    int height = 0; /* height of channel */
+    uint32_t frame_len = 0; /* frame planner length */
+    int buffer_num = 4; /* number of buffers for display */
+    const char *pmem_region;
+    uint8_t num_planes = 0;
+    uint32_t planes[VIDEO_MAX_PLANES];
+
+    cam_ctrl_dimension_t dim;
+
+    LOGE("%s:BEGIN",__func__);
+	memset(&mHalCamCtrl->mMetadata, 0, sizeof(camera_frame_metadata_t));
+	mHalCamCtrl->mPreviewMemoryLock.lock();
+	memset(&mHalCamCtrl->mPreviewMemory, 0, sizeof(mHalCamCtrl->mPreviewMemory));
+	mHalCamCtrl->mPreviewMemoryLock.unlock();
+	memset(&mNotifyBuffer, 0, sizeof(mNotifyBuffer));
+
+  /* get preview size, by qury mm_camera*/
+    memset(&dim, 0, sizeof(cam_ctrl_dimension_t));
+
+    memset(&(this->mDisplayStreamBuf),0, sizeof(this->mDisplayStreamBuf));
+
+    ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION, &dim);
+    if (MM_CAMERA_OK != ret) {
+      LOGE("%s: error - can't get camera dimension!", __func__);
+      LOGE("%s: X", __func__);
+      return BAD_VALUE;
+    }else {
+      width =  dim.display_width,
+      height = dim.display_height;
+    }
+
+	ret = getBufferFromSurface();
+	if(ret != NO_ERROR) {
+	 LOGE("%s: cannot get memory from surface texture client, ret = %d", __func__, ret);
+	 return ret;
+	}
+
+  /* set 4 buffers for display */
+  memset(&mDisplayStreamBuf, 0, sizeof(mDisplayStreamBuf));
+  mHalCamCtrl->mPreviewMemoryLock.lock();
+  this->mDisplayStreamBuf.num = mHalCamCtrl->mPreviewMemory.buffer_count;
+  this->myMode=myMode; /*Need to assign this in constructor after translating from mask*/
+  num_planes = 2;
+  planes[0] = dim.display_frame_offset.mp[0].len;
+  planes[1] = dim.display_frame_offset.mp[1].len;
+  this->mDisplayStreamBuf.frame_len = dim.display_frame_offset.frame_len;
+
+  mDisplayBuf.preview.buf.mp = new mm_camera_mp_buf_t[mDisplayStreamBuf.num];
+  if (!mDisplayBuf.preview.buf.mp) {
+	  LOGE("%s Error allocating memory for mplanar struct ", __func__);
+  }
+  memset(mDisplayBuf.preview.buf.mp, 0,
+    mDisplayStreamBuf.num * sizeof(mm_camera_mp_buf_t));
+
+  /*allocate memory for the buffers*/
+  void *vaddr = NULL;
+  for(int i = 0; i < mDisplayStreamBuf.num; i++){
+	  if (mHalCamCtrl->mPreviewMemory.private_buffer_handle[i] == NULL)
+		  continue;
+      mDisplayStreamBuf.frame[i].fd = mHalCamCtrl->mPreviewMemory.private_buffer_handle[i]->fd;
+      mDisplayStreamBuf.frame[i].cbcr_off = planes[0];
+      mDisplayStreamBuf.frame[i].y_off = 0;
+      mDisplayStreamBuf.frame[i].path = OUTPUT_TYPE_P;
+	  mHalCamCtrl->mPreviewMemory.addr_offset[i] =
+	      mHalCamCtrl->mPreviewMemory.private_buffer_handle[i]->offset;
+      mDisplayStreamBuf.frame[i].buffer =
+          (long unsigned int)mHalCamCtrl->mPreviewMemory.camera_memory[i]->data;
+
+	  LOGE("%s: idx = %d, fd = %d, size = %d, cbcr_offset = %d, y_offset = %d, offset = %d, vaddr = 0x%x",
+		  __func__, i,
+		  mDisplayStreamBuf.frame[i].fd,
+		  mHalCamCtrl->mPreviewMemory.private_buffer_handle[i]->size,
+		  mDisplayStreamBuf.frame[i].cbcr_off,
+		  mDisplayStreamBuf.frame[i].y_off,
+		  mHalCamCtrl->mPreviewMemory.addr_offset[i],
+		  (uint32_t)mDisplayStreamBuf.frame[i].buffer);
+
+
+        mDisplayBuf.preview.buf.mp[i].frame = mDisplayStreamBuf.frame[i];
+        mDisplayBuf.preview.buf.mp[i].frame_offset = mHalCamCtrl->mPreviewMemory.addr_offset[i];
+        mDisplayBuf.preview.buf.mp[i].num_planes = num_planes;
+
+		/* Plane 0 needs to be set seperately. Set other planes
+         * in a loop. */
+        mDisplayBuf.preview.buf.mp[i].planes[0].length = planes[0];
+        mDisplayBuf.preview.buf.mp[i].planes[0].m.userptr = mDisplayStreamBuf.frame[i].fd;
+        mDisplayBuf.preview.buf.mp[i].planes[0].data_offset = 0;
+        mDisplayBuf.preview.buf.mp[i].planes[0].reserved[0] =
+          mDisplayBuf.preview.buf.mp[i].frame_offset;
+        for (int j = 1; j < num_planes; j++) {
+          mDisplayBuf.preview.buf.mp[i].planes[j].length = planes[j];
+          mDisplayBuf.preview.buf.mp[i].planes[j].m.userptr =
+            mDisplayStreamBuf.frame[i].fd;
+		  mDisplayBuf.preview.buf.mp[i].planes[j].data_offset = 0;
+          mDisplayBuf.preview.buf.mp[i].planes[j].reserved[0] =
+            mDisplayBuf.preview.buf.mp[i].planes[j-1].reserved[0] +
+            mDisplayBuf.preview.buf.mp[i].planes[j-1].length;
+        }
+
+		for (int j = 0; j < num_planes; j++) {
+			LOGE("Planes: %d length: %d userptr: %lu offset: %d\n",
+				 j, mDisplayBuf.preview.buf.mp[i].planes[j].length,
+				 mDisplayBuf.preview.buf.mp[i].planes[j].m.userptr,
+				 mDisplayBuf.preview.buf.mp[i].planes[j].reserved[0]);
+		}
+
+  }/*end of for loop*/
+
+ /* register the streaming buffers for the channel*/
+  mDisplayBuf.ch_type = MM_CAMERA_CH_PREVIEW;
+  mDisplayBuf.preview.num = mDisplayStreamBuf.num;
+  mHalCamCtrl->mPreviewMemoryLock.unlock();
+  LOGE("%s:END",__func__);
+  return NO_ERROR;
+
+end:
+  if (MM_CAMERA_OK == ret ) {
+    LOGV("%s: X - NO_ERROR ", __func__);
+    return NO_ERROR;
+  }
+
+    LOGV("%s: out of memory clean up", __func__);
+  /* release the allocated memory */
+
+  LOGV("%s: X - BAD_VALUE ", __func__);
+  return BAD_VALUE;
+}
+
+void QCameraStream_preview::dumpFrameToFile(struct msm_frame* newFrame)
+{
+  int32_t enabled = 0;
+  int frm_num;
+  uint32_t  skip_mode;
+  char value[PROPERTY_VALUE_MAX];
+  char buf[32];
+  int w, h;
+  static int count = 0;
+  cam_ctrl_dimension_t dim;
+  int file_fd;
+  int rc = 0;
+  int len;
+  unsigned long addr;
+  unsigned long * tmp = (unsigned long *)newFrame->buffer;
+  addr = *tmp;
+  status_t ret = cam_config_get_parm(mHalCamCtrl->mCameraId,
+                 MM_CAMERA_PARM_DIMENSION, &dim);
+
+  w = dim.display_width;
+  h = dim.display_height;
+  len = (w * h)*3/2;
+  count++;
+  if(count < 100) {
+    snprintf(buf, sizeof(buf), "/data/mzhu%d.yuv", count);
+    file_fd = open(buf, O_RDWR | O_CREAT, 0777);
+
+    rc = write(file_fd, (const void *)addr, len);
+    LOGE("%s: file='%s', vaddr_old=0x%x, addr_map = 0x%p, len = %d, rc = %d",
+          __func__, buf, (uint32_t)newFrame->buffer, (void *)addr, len, rc);
+    close(file_fd);
+    LOGE("%s: dump %s, rc = %d, len = %d", __func__, buf, rc, len);
+  }
+}
+
+status_t QCameraStream_preview::processPreviewFrame(mm_camera_ch_data_buf_t *frame)
+{
+  LOGV("%s",__func__);
+  int err = 0;
+  int msgType = 0;
+  camera_memory_t *data = NULL;
+  camera_frame_metadata_t *metadata = NULL;
+
+  Mutex::Autolock lock(mStopCallbackLock);
+  if(!mActive) {
+    LOGE("Preview Stopped. Returning callback");
+    return NO_ERROR;
+  }
+  if(mHalCamCtrl==NULL) {
+    LOGE("%s: X: HAL control object not set",__func__);
+    /*Call buf done*/
+    return BAD_VALUE;
+  }
+  
+  mHalCamCtrl->mCallbackLock.lock();
+  camera_data_timestamp_callback rcb = mHalCamCtrl->mDataCbTimestamp;
+  void *rdata = mHalCamCtrl->mCallbackCookie;
+  mHalCamCtrl->mCallbackLock.unlock();
+
+  if (UNLIKELY(mHalCamCtrl->mDebugFps)) {
+      mHalCamCtrl->debugShowPreviewFPS();
+  }
+  //dumpFrameToFile(frame->def.frame);
+  mHalCamCtrl->dumpFrameToFile(frame->def.frame, HAL_DUMP_FRM_PREVIEW);
+
+  nsecs_t timeStamp = systemTime();
+
+  mHalCamCtrl->mPreviewMemoryLock.lock();
+  mNotifyBuffer[frame->def.idx] = *frame;
+  // mzhu fix me, need to check meta data also.
+
+  LOGI("Enqueue buf handle %p\n",
+  mHalCamCtrl->mPreviewMemory.buffer_handle[frame->def.idx]);
+  LOGD("%s: camera call genlock_unlock", __FUNCTION__);
+    if (BUFFER_LOCKED == mHalCamCtrl->mPreviewMemory.local_flag[frame->def.idx]) {
+        if (GENLOCK_FAILURE == genlock_unlock_buffer((native_handle_t*)
+	            (*mHalCamCtrl->mPreviewMemory.buffer_handle[frame->def.idx]))) {
+            LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
+	    mHalCamCtrl->mPreviewMemoryLock.unlock();
+            return -EINVAL;
+        } else {
+            mHalCamCtrl->mPreviewMemory.local_flag[frame->def.idx] = BUFFER_UNLOCKED;
+        }
+    } else {
+        LOGE("%s: buffer to be enqueued is not locked", __FUNCTION__);
+	mHalCamCtrl->mPreviewMemoryLock.unlock();
+        return -EINVAL;
+    }
+  err = this->mPreviewWindow->enqueue_buffer(this->mPreviewWindow,
+    (buffer_handle_t *)mHalCamCtrl->mPreviewMemory.buffer_handle[frame->def.idx]);
+  if(err != 0) {
+    LOGE("%s: enqueue_buffer failed, err = %d", __func__, err);
+  }
+  buffer_handle_t *buffer_handle = NULL;
+  int tmp_stride = 0;
+  err = this->mPreviewWindow->dequeue_buffer(this->mPreviewWindow,
+              &buffer_handle, &tmp_stride);
+  if (err == NO_ERROR && buffer_handle != NULL) {
+      err = this->mPreviewWindow->lock_buffer(this->mPreviewWindow, buffer_handle);
+      LOGD("%s: camera call genlock_lock", __FUNCTION__);
+      if (GENLOCK_FAILURE == genlock_lock_buffer((native_handle_t*)(*buffer_handle), GENLOCK_WRITE_LOCK,
+                                                 GENLOCK_MAX_TIMEOUT)) {
+            LOGE("%s: genlock_lock_buffer(WRITE) failed", __FUNCTION__);
+	    mHalCamCtrl->mPreviewMemoryLock.unlock();
+            return -EINVAL;
+      }
+      for(int i = 0; i < mHalCamCtrl->mPreviewMemory.buffer_count; i++) {
+		  LOGD("h1: %p h2: %p\n", mHalCamCtrl->mPreviewMemory.buffer_handle[i], buffer_handle);
+		  if(mHalCamCtrl->mPreviewMemory.buffer_handle[i] == buffer_handle) {
+	          mm_camera_ch_data_buf_t tmp_frame;
+                  mHalCamCtrl->mPreviewMemory.local_flag[i] = BUFFER_LOCKED;
+              if(MM_CAMERA_OK != cam_evt_buf_done(mCameraId, &mNotifyBuffer[i])) {
+                  LOGD("BUF DONE FAILED");
+                  mHalCamCtrl->mPreviewMemoryLock.unlock();
+                  return BAD_VALUE;
+              }
+			  break;
+		  }
+	  }
+  } else
+      LOGE("%s: error in dequeue_buffer, enqueue_buffer idx = %d, no free buffer now", __func__, frame->def.idx);
+  /* Save the last displayed frame. We'll be using it to fill the gap between
+     when preview stops and postview start during snapshot.*/
+  mLastQueuedFrame = &(mDisplayStreamBuf.frame[frame->def.idx]);
+  mHalCamCtrl->mPreviewMemoryLock.unlock();
+
+  mHalCamCtrl->mCallbackLock.lock();
+  camera_data_callback pcb = mHalCamCtrl->mDataCb;
+  mHalCamCtrl->mCallbackLock.unlock();
+  LOGD("Message enabled = 0x%x", mHalCamCtrl->mMsgEnabled);
+
+  if (pcb != NULL) {
+      //Sending preview callback if corresponding Msgs are enabled
+      if(mHalCamCtrl->mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) {
+          msgType |=  CAMERA_MSG_PREVIEW_FRAME;
+          data = mHalCamCtrl->mPreviewMemory.camera_memory[frame->def.idx];//mPreviewHeap->mBuffers[frame->def.idx];
+      } else {
+          data = NULL;
+      }
+      if(mHalCamCtrl->mMsgEnabled & CAMERA_MSG_PREVIEW_METADATA){
+          msgType  |= CAMERA_MSG_PREVIEW_METADATA;
+          metadata = &mHalCamCtrl->mMetadata;
+      } else {
+          metadata = NULL;
+      }
+      if(msgType) {
+          mStopCallbackLock.unlock();
+          pcb(msgType, data, 0, metadata, mHalCamCtrl->mCallbackCookie);
+      }
+	  LOGD("end of cb");
+  }
+  if(rcb != NULL)
+  {
+    if (mHalCamCtrl->mStoreMetaDataInFrame)
+    {
+          LOGE("sandeep:Metadata enabled");
+          mStopCallbackLock.unlock();
+          if(mHalCamCtrl->mStartRecording == true &&( mHalCamCtrl->mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
+          rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME,
+              mHalCamCtrl->mRecordingMemory.metadata_memory[frame->def.idx],
+              0, mHalCamCtrl->mCallbackCookie);
+    }
+    else
+    {
+        LOGE("sandeep:MetaData is not enabled");
+        if(mHalCamCtrl->mStartRecording == true &&( mHalCamCtrl->mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
+        {
+            mStopCallbackLock.unlock();
+            rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME,
+              mHalCamCtrl->mPreviewMemory.camera_memory[frame->def.idx],
+              0, mHalCamCtrl->mCallbackCookie);
+        }
+    }
+  }
+
+  /* Save the last displayed frame. We'll be using it to fill the gap between
+     when preview stops and postview start during snapshot.*/
+  //mLastQueuedFrame = frame->def.frame;
+/*
+  if(MM_CAMERA_OK != cam_evt_buf_done(mCameraId, frame))
+  {
+      LOGE("BUF DONE FAILED");
+      return BAD_VALUE;
+  }
+*/
+  return NO_ERROR;
+}
+
+// ---------------------------------------------------------------------------
+// QCameraStream_preview
+// ---------------------------------------------------------------------------
+
+QCameraStream_preview::
+QCameraStream_preview(int cameraId, camera_mode_t mode)
+  : QCameraStream(cameraId,mode),
+    mLastQueuedFrame(NULL)
+  {
+    mHalCamCtrl = NULL;
+    LOGE("%s: E", __func__);
+    LOGE("%s: X", __func__);
+  }
+// ---------------------------------------------------------------------------
+// QCameraStream_preview
+// ---------------------------------------------------------------------------
+
+QCameraStream_preview::~QCameraStream_preview() {
+    LOGV("%s: E", __func__);
+	if(mActive) {
+		stop();
+	}
+	if(mInit) {
+		release();
+	}
+	mInit = false;
+	mActive = false;
+    LOGV("%s: X", __func__);
+
+}
+// ---------------------------------------------------------------------------
+// QCameraStream_preview
+// ---------------------------------------------------------------------------
+
+status_t QCameraStream_preview::init() {
+
+  status_t ret = NO_ERROR;
+  LOGV("%s: E", __func__);
+
+  ret = QCameraStream::initChannel (mCameraId, MM_CAMERA_CH_PREVIEW_MASK);
+  if (NO_ERROR!=ret) {
+    LOGE("%s E: can't init native cammera preview ch\n",__func__);
+    return ret;
+  }
+
+  LOGE("Debug : %s : initChannel",__func__);
+  /* register a notify into the mmmm_camera_t object*/
+  (void) cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_PREVIEW,
+                                     preview_notify_cb, MM_CAMERA_REG_BUF_CB_INFINITE, 0, this);
+  LOGE("Debug : %s : cam_evt_register_buf_notify",__func__);
+  buffer_handle_t *buffer_handle = NULL;
+  int tmp_stride = 0;
+  mInit = true;
+  return ret;
+}
+// ---------------------------------------------------------------------------
+// QCameraStream_preview
+// ---------------------------------------------------------------------------
+
+status_t QCameraStream_preview::start()
+{
+    LOGV("%s: E", __func__);
+    status_t ret = NO_ERROR;
+    mm_camera_reg_buf_t *reg_buf=&mDisplayBuf;
+
+    Mutex::Autolock lock(mStopCallbackLock);
+
+    /* call start() in parent class to start the monitor thread*/
+    //QCameraStream::start ();
+    setFormat(MM_CAMERA_CH_PREVIEW_MASK);
+
+    if(NO_ERROR!=initDisplayBuffers()){
+        return BAD_VALUE;
+    }
+    LOGE("Debug : %s : initDisplayBuffers",__func__);
+    ret = cam_config_prepare_buf(mCameraId, reg_buf);
+    LOGE("Debug : %s : cam_config_prepare_buf",__func__);
+    if(ret != MM_CAMERA_OK) {
+        LOGV("%s:reg preview buf err=%d\n", __func__, ret);
+        ret = BAD_VALUE;
+    }else
+        ret = NO_ERROR;
+
+	/* For preview, the OP_MODE we set is dependent upon whether we are
+       starting camera or camcorder. For snapshot, anyway we disable preview.
+       However, for ZSL we need to set OP_MODE to OP_MODE_ZSL and not
+       OP_MODE_VIDEO. We'll set that for now in CamCtrl. So in case of
+       ZSL we skip setting Mode here */
+
+    if (!(myMode & CAMERA_ZSL_MODE)) {
+        LOGE("Setting OP MODE to MM_CAMERA_OP_MODE_VIDEO");
+        mm_camera_op_mode_type_t op_mode=MM_CAMERA_OP_MODE_VIDEO;
+        ret = cam_config_set_parm (mCameraId, MM_CAMERA_PARM_OP_MODE,
+                                        &op_mode);
+        LOGE("OP Mode Set");
+
+        if(MM_CAMERA_OK != ret) {
+          LOGE("%s: X :set mode MM_CAMERA_OP_MODE_VIDEO err=%d\n", __func__, ret);
+          return BAD_VALUE;
+        }
+    }else {
+        LOGE("Setting OP MODE to MM_CAMERA_OP_MODE_ZSL");
+        mm_camera_op_mode_type_t op_mode=MM_CAMERA_OP_MODE_ZSL;
+        ret = cam_config_set_parm (mCameraId, MM_CAMERA_PARM_OP_MODE,
+                                        &op_mode);
+        if(MM_CAMERA_OK != ret) {
+          LOGE("%s: X :set mode MM_CAMERA_OP_MODE_ZSL err=%d\n", __func__, ret);
+          return BAD_VALUE;
+        }
+     }
+
+    /* call mm_camera action start(...)  */
+    LOGE("Starting Preview/Video Stream. ");
+    ret = cam_ops_action(mCameraId, TRUE, MM_CAMERA_OPS_PREVIEW, 0);
+
+    if (MM_CAMERA_OK != ret) {
+      LOGE ("%s: preview streaming start err=%d\n", __func__, ret);
+      return BAD_VALUE;
+    }
+
+    LOGE("Debug : %s : Preview streaming Started",__func__);
+    ret = NO_ERROR;
+
+    mActive =  true;
+    LOGE("%s: X", __func__);
+    return NO_ERROR;
+  }
+
+
+// ---------------------------------------------------------------------------
+// QCameraStream_preview
+// ---------------------------------------------------------------------------
+  void QCameraStream_preview::stop() {
+    LOGE("%s: E", __func__);
+    int ret=MM_CAMERA_OK;
+
+    if(!mActive) {
+      return;
+    }
+    mActive =  false;
+    Mutex::Autolock lock(mStopCallbackLock);
+    /* unregister the notify fn from the mmmm_camera_t object*/
+
+    /* call stop() in parent class to stop the monitor thread*/
+    ret = cam_ops_action(mCameraId, FALSE, MM_CAMERA_OPS_PREVIEW, 0);
+    if(MM_CAMERA_OK != ret) {
+      LOGE ("%s: camera preview stop err=%d\n", __func__, ret);
+    }
+    LOGE("Debug : %s : Preview streaming Stopped",__func__);
+    ret = cam_config_unprepare_buf(mCameraId, MM_CAMERA_CH_PREVIEW);
+    if(ret != MM_CAMERA_OK) {
+      LOGE("%s:Unreg preview buf err=%d\n", __func__, ret);
+      //ret = BAD_VALUE;
+    }
+
+    LOGE("Debug : %s : Buffer Unprepared",__func__);
+    if (mDisplayBuf.preview.buf.mp != NULL) {
+        delete[] mDisplayBuf.preview.buf.mp;
+    }
+	/*free camera_memory handles and return buffer back to surface*/
+    putBufferToSurface();
+
+    LOGE("%s: X", __func__);
+
+  }
+// ---------------------------------------------------------------------------
+// QCameraStream_preview
+// ---------------------------------------------------------------------------
+  void QCameraStream_preview::release() {
+
+    LOGE("%s : BEGIN",__func__);
+    int ret=MM_CAMERA_OK,i;
+
+    if(!mInit)
+    {
+      LOGE("%s : Stream not Initalized",__func__);
+      return;
+    }
+
+    if(mActive) {
+      this->stop();
+    }
+
+    ret= QCameraStream::deinitChannel(mCameraId, MM_CAMERA_CH_PREVIEW);
+    LOGE("Debug : %s : De init Channel",__func__);
+    if(ret != MM_CAMERA_OK) {
+      LOGE("%s:Deinit preview channel failed=%d\n", __func__, ret);
+      //ret = BAD_VALUE;
+    }
+
+    (void)cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_PREVIEW,
+                                      NULL,
+					(mm_camera_register_buf_cb_type_t)NULL,
+					NULL,
+					NULL);
+	mInit = false;
+    LOGE("%s: END", __func__);
+
+  }
+
+QCameraStream*
+QCameraStream_preview::createInstance(int cameraId,
+                                      camera_mode_t mode)
+{
+  QCameraStream* pme = new QCameraStream_preview(cameraId, mode);
+  return pme;
+}
+// ---------------------------------------------------------------------------
+// QCameraStream_preview
+// ---------------------------------------------------------------------------
+
+void QCameraStream_preview::deleteInstance(QCameraStream *p)
+{
+  if (p){
+    LOGV("%s: BEGIN", __func__);
+    p->release();
+    delete p;
+    p = NULL;
+    LOGV("%s: END", __func__);
+  }
+}
+
+
+/* Temp helper function */
+void *QCameraStream_preview::getLastQueuedFrame(void)
+{
+    return mLastQueuedFrame;
+}
+
+/* Set preview pause flag */
+void QCameraStream_preview::setPreviewPauseFlag(bool bPaused)
+{
+    mbPausedBySnapshot = bPaused;
+}
+
+// ---------------------------------------------------------------------------
+// No code beyone this line
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/QCameraHWI_Record_7x27A.cpp b/QCameraHWI_Record_7x27A.cpp
new file mode 100644
index 0000000..d36fce1
--- /dev/null
+++ b/QCameraHWI_Record_7x27A.cpp
@@ -0,0 +1,721 @@
+/*

+** Copyright (c) 2012 Code Aurora Forum. All rights reserved.

+**

+** Licensed under the Apache License, Version 2.0 (the "License");

+** you may not use this file except in compliance with the License.

+** You may obtain a copy of the License at

+**

+**     http://www.apache.org/licenses/LICENSE-2.0

+**

+** Unless required by applicable law or agreed to in writing, software

+** distributed under the License is distributed on an "AS IS" BASIS,

+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+** See the License for the specific language governing permissions and

+** limitations under the License.

+*/

+

+/*#error uncomment this for compiler test!*/

+

+#define LOG_NDEBUG 0

+#define LOG_NIDEBUG 0

+#define LOG_TAG "QCameraHWI_Record"

+#include <utils/Log.h>

+#include <utils/threads.h>

+#include <cutils/properties.h>

+#include <fcntl.h>

+#include <sys/mman.h>

+

+#include "QCameraStream.h"

+

+

+#define LIKELY(exp)   __builtin_expect(!!(exp), 1)

+#define UNLIKELY(exp) __builtin_expect(!!(exp), 0)

+

+/* QCameraStream_record class implementation goes here*/

+/* following code implement the video streaming capture & encoding logic of this class*/

+// ---------------------------------------------------------------------------

+// QCameraStream_record createInstance()

+// ---------------------------------------------------------------------------

+namespace android {

+

+

+QCameraStream* QCameraStream_record::createInstance(int cameraId,

+                                      camera_mode_t mode)

+{

+  LOGV("%s: BEGIN", __func__);

+  QCameraStream* pme = new QCameraStream_record(cameraId, mode);

+  LOGV("%s: END", __func__);

+  return pme;

+}

+

+// ---------------------------------------------------------------------------

+// QCameraStream_record deleteInstance()

+// ---------------------------------------------------------------------------

+void QCameraStream_record::deleteInstance(QCameraStream *ptr)

+{

+  LOGV("%s: BEGIN", __func__);

+  if (ptr){

+    ptr->release();

+    delete ptr;

+    ptr = NULL;

+  }

+  LOGV("%s: END", __func__);

+}

+

+// ---------------------------------------------------------------------------

+// QCameraStream_record Constructor

+// ---------------------------------------------------------------------------

+QCameraStream_record::QCameraStream_record(int cameraId,

+                                           camera_mode_t mode)

+  :QCameraStream(cameraId,mode),

+   mDebugFps(false)

+{

+  mHalCamCtrl = NULL;

+  char value[PROPERTY_VALUE_MAX];

+  LOGV("%s: BEGIN", __func__);

+

+  property_get("persist.debug.sf.showfps", value, "0");

+  mDebugFps = atoi(value);

+

+  LOGV("%s: END", __func__);

+}

+

+// ---------------------------------------------------------------------------

+// QCameraStream_record Destructor

+// ---------------------------------------------------------------------------

+QCameraStream_record::~QCameraStream_record() {

+  LOGV("%s: BEGIN", __func__);

+  if(mActive) {

+    stop();

+  }

+  if(mInit) {

+    release();

+  }

+  mInit = false;

+  mActive = false;

+  LOGV("%s: END", __func__);

+

+}

+

+// ---------------------------------------------------------------------------

+// QCameraStream_record Callback from mm_camera

+// ---------------------------------------------------------------------------

+static void record_notify_cb(mm_camera_ch_data_buf_t *bufs_new,

+                              void *user_data)

+{

+  QCameraStream_record *pme = (QCameraStream_record *)user_data;

+  mm_camera_ch_data_buf_t *bufs_used = 0;

+  LOGV("%s: BEGIN", __func__);

+

+  /*

+  * Call Function Process Video Data

+  */

+  pme->processRecordFrame(bufs_new);

+  LOGV("%s: END", __func__);

+}

+

+// ---------------------------------------------------------------------------

+// QCameraStream_record

+// ---------------------------------------------------------------------------

+status_t QCameraStream_record::init()

+{

+  status_t ret = NO_ERROR;

+  LOGV("%s: BEGIN", __func__);

+#if 0

+  /*

+  *  Acquiring Video Channel

+  */

+  ret = QCameraStream::initChannel (mCameraId, MM_CAMERA_CH_VIDEO_MASK);

+  if (NO_ERROR!=ret) {

+    LOGE("%s ERROR: Can't init native cammera preview ch\n",__func__);

+    return ret;

+  }

+

+  /*

+  * Register the Callback with camera

+  */

+  (void) cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_VIDEO,

+                                            record_notify_cb,

+                                            this);

+#endif

+  mInit = true;

+  LOGV("%s: END", __func__);

+  return ret;

+}

+// ---------------------------------------------------------------------------

+// QCameraStream_record

+// ---------------------------------------------------------------------------

+

+status_t QCameraStream_record::start()

+{

+  status_t ret = NO_ERROR;

+  LOGE("%s: BEGIN", __func__);

+  mHalCamCtrl->mStartRecording  = true;

+  ret = initEncodeBuffers();

+  if (NO_ERROR!=ret) {

+    LOGE("%s ERROR: Buffer Allocation Failed\n",__func__);

+    return ret;

+  }

+

+#if 0

+  Mutex::Autolock lock(mStopCallbackLock);

+  if(!mInit) {

+    LOGE("%s ERROR: Record buffer not registered",__func__);

+    return BAD_VALUE;

+  }

+

+  setFormat(MM_CAMERA_CH_VIDEO_MASK);

+  //mRecordFreeQueueLock.lock();

+  //mRecordFreeQueue.clear();

+  //mRecordFreeQueueLock.unlock();

+  /*

+  *  Allocating Encoder Frame Buffers

+  */

+  ret = initEncodeBuffers();

+  if (NO_ERROR!=ret) {

+    LOGE("%s ERROR: Buffer Allocation Failed\n",__func__);

+    return ret;

+  }

+

+  ret = cam_config_prepare_buf(mCameraId, &mRecordBuf);

+  if(ret != MM_CAMERA_OK) {

+    LOGV("%s ERROR: Reg Record buf err=%d\n", __func__, ret);

+    ret = BAD_VALUE;

+  }else{

+    ret = NO_ERROR;

+  }

+

+  /*

+  * Start Video Streaming

+  */

+  ret = cam_ops_action(mCameraId, TRUE, MM_CAMERA_OPS_VIDEO, 0);

+  if (MM_CAMERA_OK != ret) {

+    LOGE ("%s ERROR: Video streaming start err=%d\n", __func__, ret);

+    ret = BAD_VALUE;

+  }else{

+    LOGE("%s : Video streaming Started",__func__);

+    ret = NO_ERROR;

+  }

+  mActive = true;

+#endif

+  LOGV("%s: END", __func__);

+  return ret;

+}

+

+// ---------------------------------------------------------------------------

+// QCameraStream_record

+// ---------------------------------------------------------------------------

+void QCameraStream_record::stop()

+{

+  status_t ret = NO_ERROR;

+  LOGE("%s: BEGIN", __func__);

+  mHalCamCtrl->mStartRecording  = false;

+#if 0

+  if(!mActive) {

+    LOGE("%s : Record stream not started",__func__);

+    return;

+  }

+  mActive =  false;

+  Mutex::Autolock lock(mStopCallbackLock);

+#if 0 //mzhu, when stop recording, all frame will be dirty. no need to queue frame back to kernel any more

+  mRecordFreeQueueLock.lock();

+  while(!mRecordFreeQueue.isEmpty()) {

+    LOGV("%s : Pre-releasing of Encoder buffers!\n", __FUNCTION__);

+    mm_camera_ch_data_buf_t releasedBuf = mRecordFreeQueue.itemAt(0);

+    mRecordFreeQueue.removeAt(0);

+    mRecordFreeQueueLock.unlock();

+    LOGV("%s (%d): releasedBuf.idx = %d\n", __FUNCTION__, __LINE__,

+                                              releasedBuf.video.video.idx);

+    if(MM_CAMERA_OK != cam_evt_buf_done(mCameraId,&releasedBuf))

+        LOGE("%s : Buf Done Failed",__func__);

+  }

+  mRecordFreeQueueLock.unlock();

+#if 0

+  while (!mRecordFreeQueue.isEmpty()) {

+        LOGE("%s : Waiting for Encoder to release all buffer!\n", __FUNCTION__);

+  }

+#endif

+#endif // mzhu

+  /* unregister the notify fn from the mmmm_camera_t object

+   *  call stop() in parent class to stop the monitor thread */

+

+  ret = cam_ops_action(mCameraId, FALSE, MM_CAMERA_OPS_VIDEO, 0);

+  if (MM_CAMERA_OK != ret) {

+    LOGE ("%s ERROR: Video streaming Stop err=%d\n", __func__, ret);

+  }

+

+  ret = cam_config_unprepare_buf(mCameraId, MM_CAMERA_CH_VIDEO);

+  if(ret != MM_CAMERA_OK){

+    LOGE("%s ERROR: Ureg video buf \n", __func__);

+  }

+#endif

+  for(int cnt = 0; cnt < mHalCamCtrl->mPreviewMemory.buffer_count; cnt++) {

+    if (mHalCamCtrl->mStoreMetaDataInFrame) {

+      struct encoder_media_buffer_type * packet =

+          (struct encoder_media_buffer_type  *)

+          mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]->data;

+      native_handle_delete(const_cast<native_handle_t *>(packet->meta_handle));

+      mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]->release(

+		    mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]);

+

+    }

+#if 0

+	  mHalCamCtrl->mRecordingMemory.camera_memory[cnt]->release(

+		  mHalCamCtrl->mRecordingMemory.camera_memory[cnt]);

+	  close(mHalCamCtrl->mRecordingMemory.fd[cnt]);

+

+#ifdef USE_ION

+    mHalCamCtrl->deallocate_ion_memory(&mHalCamCtrl->mRecordingMemory, cnt);

+#endif

+#endif

+  }

+#if 0

+memset(&mHalCamCtrl->mRecordingMemory, 0, sizeof(mHalCamCtrl->mRecordingMemory));

+  //mNumRecordFrames = 0;

+  delete[] recordframes;

+  if (mRecordBuf.video.video.buf.mp)

+    delete[] mRecordBuf.video.video.buf.mp;

+

+

+  mActive = false;

+#endif

+  LOGV("%s: END", __func__);

+

+}

+// ---------------------------------------------------------------------------

+// QCameraStream_record

+// ---------------------------------------------------------------------------

+void QCameraStream_record::release()

+{

+  status_t ret = NO_ERROR;

+  LOGV("%s: BEGIN", __func__);

+#if 0

+  if(mActive) {

+    stop();

+  }

+  if(!mInit) {

+    LOGE("%s : Record stream not initialized",__func__);

+    return;

+  }

+

+  ret= QCameraStream::deinitChannel(mCameraId, MM_CAMERA_CH_VIDEO);

+  if(ret != MM_CAMERA_OK) {

+    LOGE("%s:Deinit Video channel failed=%d\n", __func__, ret);

+  }

+  (void)cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_VIDEO,

+                                            NULL,

+                                            NULL);

+  mInit = false;

+#endif

+  LOGV("%s: END", __func__);

+}

+

+status_t QCameraStream_record::processRecordFrame(void *data)

+{

+    LOGE("%s : BEGIN",__func__);

+#if 0

+    mm_camera_ch_data_buf_t* frame = (mm_camera_ch_data_buf_t*) data;

+

+    Mutex::Autolock lock(mStopCallbackLock);

+    if(!mActive) {

+      LOGE("Recording Stopped. Returning callback");

+      return NO_ERROR;

+    }

+

+    if (UNLIKELY(mDebugFps)) {

+        debugShowVideoFPS();

+    }

+

+

+    mHalCamCtrl->dumpFrameToFile(frame->video.video.frame, HAL_DUMP_FRM_VIDEO);

+    mHalCamCtrl->mCallbackLock.lock();

+    camera_data_timestamp_callback rcb = mHalCamCtrl->mDataCbTimestamp;

+    void *rdata = mHalCamCtrl->mCallbackCookie;

+    mHalCamCtrl->mCallbackLock.unlock();

+

+	nsecs_t timeStamp = nsecs_t(frame->video.video.frame->ts.tv_sec)*1000000000LL + \

+                      frame->video.video.frame->ts.tv_nsec;

+

+  if(snapshot_enabled) {

+    LOGE("Live Snapshot Enabled");

+    frame->snapshot.main.frame = frame->video.video.frame;

+    frame->snapshot.main.idx = frame->video.video.idx;

+    frame->snapshot.thumbnail.frame = frame->video.video.frame;

+    frame->snapshot.thumbnail.idx = frame->video.video.idx;

+

+    dim.picture_width = mHalCamCtrl->mDimension.video_width;

+    dim.picture_height = mHalCamCtrl->mDimension.video_height;

+    dim.ui_thumbnail_width = mHalCamCtrl->mDimension.display_width;

+    dim.ui_thumbnail_height = mHalCamCtrl->mDimension.display_height;

+

+    mJpegMaxSize = mHalCamCtrl->mDimension.video_width * mHalCamCtrl->mDimension.video_width * 1.5;

+

+    LOGE("Picture w = %d , h = %d, size = %d",dim.picture_width,dim.picture_height,mJpegMaxSize);

+     if (mStreamSnap){

+        LOGE("%s:Deleting old Snapshot stream instance",__func__);

+        QCameraStream_Snapshot::deleteInstance (mStreamSnap);

+        mStreamSnap = NULL;

+    }

+

+    mStreamSnap = QCameraStream_Snapshot::createInstance(mCameraId,

+                                                       myMode);

+

+    if (!mStreamSnap) {

+        LOGE("%s: error - can't creat snapshot stream!", __func__);

+        return BAD_VALUE;

+    }

+    mStreamSnap->setHALCameraControl(this->mHalCamCtrl);

+    mStreamSnap->takePictureLiveshot(frame,&dim,mJpegMaxSize);

+

+    snapshot_enabled = false;

+  }

+

+  LOGE("Send Video frame to services/encoder TimeStamp : %lld",timeStamp);

+  mRecordedFrames[frame->video.video.idx] = *frame;

+#if 1

+  if (mHalCamCtrl->mStoreMetaDataInFrame) {

+    mStopCallbackLock.unlock();

+    if(mActive && (rcb != NULL) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {

+      rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME,

+              mHalCamCtrl->mRecordingMemory.metadata_memory[frame->video.video.idx],

+              0, mHalCamCtrl->mCallbackCookie);

+    }

+  } else {

+    //rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME, mRecordHeap->mBuffers[frame->video.video.idx], rdata);

+    mStopCallbackLock.unlock();

+    if(mActive && (rcb != NULL) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {

+      rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME,

+              mHalCamCtrl->mRecordingMemory.camera_memory[frame->video.video.idx],

+              0, mHalCamCtrl->mCallbackCookie);

+    }

+  }

+#else  //Dump the Frame

+    {

+      static int frameCnt = 0;

+      if (frameCnt <= 13 ) {

+        char buf[128];

+        snprintf(buf, sizeof(buf), "/data/%d_video.yuv", frameCnt);

+        int file_fd = open(buf, O_RDWR | O_CREAT, 0777);

+        LOGE("dumping video frame %d", frameCnt);

+        if (file_fd < 0) {

+          LOGE("cannot open file\n");

+        }

+        else

+        {

+          LOGE("Dump Frame size = %d",record_frame_len);

+          write(file_fd, (const void *)(const void *)frame->video.video.frame->buffer,

+          record_frame_len);

+        }

+        close(file_fd);

+      }

+      frameCnt++;

+    }

+    if(MM_CAMERA_OK! = cam_evt_buf_done(mCameraId, frame))

+      LOGE("%s : BUF DONE FAILED",__func__);

+#endif

+#endif

+  LOGE("%s : END",__func__);

+  return NO_ERROR;

+}

+

+//Record Related Functions

+status_t QCameraStream_record::initEncodeBuffers()

+{

+  LOGE("%s : BEGIN",__func__);

+  status_t ret = NO_ERROR;

+#if 0

+  const char *pmem_region;

+  uint32_t frame_len;

+  uint8_t num_planes;

+  uint32_t planes[VIDEO_MAX_PLANES];

+  //cam_ctrl_dimension_t dim;

+  int width = 0;  /* width of channel  */

+  int height = 0; /* height of channel */

+

+  pmem_region = "/dev/pmem_adsp";

+

+

+  memset(&mHalCamCtrl->mRecordingMemory, 0, sizeof(mHalCamCtrl->mRecordingMemory));

+  memset(&dim, 0, sizeof(cam_ctrl_dimension_t));

+  ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION, &dim);

+  if (MM_CAMERA_OK != ret) {

+    LOGE("%s: ERROR - can't get camera dimension!", __func__);

+    return BAD_VALUE;

+  }

+  else {

+    width =  dim.video_width;

+    height = dim.video_height;

+  }

+  num_planes = 2;

+  planes[0] = dim.video_frame_offset.mp[0].len;

+  planes[1] = dim.video_frame_offset.mp[1].len;

+  frame_len = dim.video_frame_offset.frame_len;

+

+#if 0

+  if(mRecordHeap == NULL)

+  {

+#ifdef USE_ION

+    mRecordHeap = new IonPool(

+                        MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,

+                        frame_len,

+                        VIDEO_BUFFER_COUNT,

+                        frame_len,

+                        planes[0],

+                        0,

+                        "record");

+#else

+    mRecordHeap = new PmemPool(pmem_region,

+                        MemoryHeapBase::READ_ONLY | MemoryHeapBase::NO_CACHING,

+                        MSM_PMEM_VIDEO,

+                        frame_len,

+                        VIDEO_BUFFER_COUNT,

+                        frame_len,

+                        planes[0],

+                        0,

+                        "record");

+#endif

+    if (!mRecordHeap->initialized()) {

+      mRecordHeap.clear();

+      mRecordHeap = NULL;

+      LOGE("%s: ERROR : could not initialize record heap.",__func__);

+      return BAD_VALUE;

+    }

+   } else {

+    /*if(mHFRMode == true) {

+    LOGI("%s: register record buffers with camera driver", __FUNCTION__);

+    register_record_buffers(true);

+    mHFRMode = false;

+    }*/

+  }

+	LOGE("PMEM Buffer Allocation Successfull");

+#endif

+

+#if 0

+  memset(&mRecordBuf, 0, sizeof(mRecordBuf));

+  /* allocate memory for mplanar frame struct. */

+  mRecordBuf.video.video.buf.mp = new mm_camera_mp_buf_t[VIDEO_BUFFER_COUNT *

+                                  sizeof(mm_camera_mp_buf_t)];

+  if (!mRecordBuf.video.video.buf.mp) {

+    LOGE("%s Error allocating memory for mplanar struct ", __func__);

+    mRecordHeap.clear();

+    mRecordHeap = NULL;

+    return BAD_VALUE;

+  }

+  memset(mRecordBuf.video.video.buf.mp, 0,

+         VIDEO_BUFFER_COUNT * sizeof(mm_camera_mp_buf_t));

+  mRecordBuf.ch_type = MM_CAMERA_CH_VIDEO;

+  mRecordBuf.video.video.num = VIDEO_BUFFER_COUNT;//kRecordBufferCount;

+  recordframes = new msm_frame[VIDEO_BUFFER_COUNT];

+  if(recordframes != NULL) {

+    memset(recordframes,0,sizeof(struct msm_frame) * VIDEO_BUFFER_COUNT);

+    for (int cnt = 0; cnt < VIDEO_BUFFER_COUNT; cnt++) {

+      recordframes[cnt].fd = mRecordHeap->mHeap->getHeapID();

+      recordframes[cnt].buffer =

+          (uint32_t)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt;

+      recordframes[cnt].y_off = 0;

+      recordframes[cnt].cbcr_off = planes[0];

+      recordframes[cnt].path = OUTPUT_TYPE_V;

+      //record_buffers_tracking_flag[cnt] = false;

+      record_offset[cnt] =  mRecordHeap->mAlignedBufferSize * cnt;

+      LOGE ("initRecord :  record heap , video buffers  buffer=%lu fd=%d offset = %d \n",

+        (unsigned long)recordframes[cnt].buffer, recordframes[cnt].fd, record_offset[cnt]);

+      mRecordBuf.video.video.buf.mp[cnt].frame = recordframes[cnt];

+      mRecordBuf.video.video.buf.mp[cnt].frame_offset = record_offset[cnt];

+      mRecordBuf.video.video.buf.mp[cnt].num_planes = num_planes;

+      /* Plane 0 needs to be set seperately. Set other planes

+       * in a loop. */

+      mRecordBuf.video.video.buf.mp[cnt].planes[0].reserved[0] =

+        mRecordBuf.video.video.buf.mp[cnt].frame_offset;

+      mRecordBuf.video.video.buf.mp[cnt].planes[0].length = planes[0];

+      mRecordBuf.video.video.buf.mp[cnt].planes[0].m.userptr =

+        recordframes[cnt].fd;

+      for (int j = 1; j < num_planes; j++) {

+        mRecordBuf.video.video.buf.mp[cnt].planes[j].length = planes[j];

+        mRecordBuf.video.video.buf.mp[cnt].planes[j].m.userptr =

+          recordframes[cnt].fd;

+        mRecordBuf.video.video.buf.mp[cnt].planes[j].reserved[0] =

+          mRecordBuf.video.video.buf.mp[cnt].planes[j-1].reserved[0] +

+          mRecordBuf.video.video.buf.mp[cnt].planes[j-1].length;

+      }

+    }

+    LOGE("Record buf type =%d, offset[1] =%d, buffer[1] =%lx", mRecordBuf.ch_type, record_offset[1], recordframes[1].buffer);

+    LOGE("%s : END",__func__);

+  } else {

+    ret = NO_MEMORY;

+  }

+  return ret;

+#endif

+

+    recordframes = new msm_frame[VIDEO_BUFFER_COUNT];

+    memset(recordframes,0,sizeof(struct msm_frame) * VIDEO_BUFFER_COUNT);

+

+		mRecordBuf.video.video.buf.mp = new mm_camera_mp_buf_t[VIDEO_BUFFER_COUNT *

+                                  sizeof(mm_camera_mp_buf_t)];

+		if (!mRecordBuf.video.video.buf.mp) {

+			LOGE("%s Error allocating memory for mplanar struct ", __func__);

+			return BAD_VALUE;

+		}

+		memset(mRecordBuf.video.video.buf.mp, 0,

+					 VIDEO_BUFFER_COUNT * sizeof(mm_camera_mp_buf_t));

+

+    memset(&mHalCamCtrl->mRecordingMemory, 0, sizeof(mHalCamCtrl->mRecordingMemory));

+    mHalCamCtrl->mRecordingMemory.buffer_count = VIDEO_BUFFER_COUNT;

+

+		mHalCamCtrl->mRecordingMemory.size = frame_len;

+		mHalCamCtrl->mRecordingMemory.cbcr_offset = planes[0];

+#endif

+    for (int cnt = 0; cnt < mHalCamCtrl->mPreviewMemory.buffer_count; cnt++) {

+#if 0

+#ifdef USE_ION

+      if(mHalCamCtrl->allocate_ion_memory(&mHalCamCtrl->mRecordingMemory, cnt, ION_CP_MM_HEAP_ID) < 0) {

+        LOGE("%s ION alloc failed\n", __func__);

+        return UNKNOWN_ERROR;

+      }

+#else

+		  mHalCamCtrl->mRecordingMemory.fd[cnt] = open("/dev/pmem_adsp", O_RDWR|O_SYNC);

+		  if(mHalCamCtrl->mRecordingMemory.fd[cnt] <= 0) {

+			  LOGE("%s: no pmem for frame %d", __func__, cnt);

+			  return UNKNOWN_ERROR;

+		  }

+#endif

+		  mHalCamCtrl->mRecordingMemory.camera_memory[cnt] =

+		    mHalCamCtrl->mGetMemory(mHalCamCtrl->mRecordingMemory.fd[cnt],

+		    mHalCamCtrl->mRecordingMemory.size, 1, (void *)this);

+#endif

+      if (mHalCamCtrl->mStoreMetaDataInFrame) {

+        mHalCamCtrl->mRecordingMemory.metadata_memory[cnt] =

+          mHalCamCtrl->mGetMemory(-1,

+          sizeof(struct encoder_media_buffer_type), 1, (void *)this);

+        struct encoder_media_buffer_type * packet =

+          (struct encoder_media_buffer_type  *)

+          mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]->data;

+        packet->meta_handle = native_handle_create(1, 2); //1 fd, 1 offset and 1 size

+        packet->buffer_type = kMetadataBufferTypeCameraSource;

+        native_handle_t * nh = const_cast<native_handle_t *>(packet->meta_handle);

+        nh->data[0] = mHalCamCtrl->mPreviewMemory.private_buffer_handle[cnt]->fd;

+        nh->data[1] = 0;

+        nh->data[2] = mHalCamCtrl->mPreviewMemory.private_buffer_handle[cnt]->size;

+        nh->data[3] = (uint32_t)mHalCamCtrl->mPreviewMemory.camera_memory[cnt]->data;

+      }

+ #if 0

+       recordframes[cnt].fd = mHalCamCtrl->mRecordingMemory.fd[cnt];

+       recordframes[cnt].buffer = (uint32_t)mHalCamCtrl->mRecordingMemory.camera_memory[cnt]->data;

+	    recordframes[cnt].y_off = 0;

+	    recordframes[cnt].cbcr_off = mHalCamCtrl->mRecordingMemory.cbcr_offset;

+	    recordframes[cnt].path = OUTPUT_TYPE_V;

+			//record_offset[cnt] =  mRecordHeap->mAlignedBufferSize * cnt;

+

+	    //record_buffers_tracking_flag[cnt] = false;

+	    //record_offset[cnt] =  0;

+	    LOGE ("initRecord :  record heap , video buffers  buffer=%lu fd=%d y_off=%d cbcr_off=%d\n",

+		    (unsigned long)recordframes[cnt].buffer, recordframes[cnt].fd, recordframes[cnt].y_off,

+		    recordframes[cnt].cbcr_off);

+	    //mNumRecordFrames++;

+

+			mRecordBuf.video.video.buf.mp[cnt].frame = recordframes[cnt];

+      mRecordBuf.video.video.buf.mp[cnt].frame_offset = 0;

+      mRecordBuf.video.video.buf.mp[cnt].num_planes = num_planes;

+      /* Plane 0 needs to be set seperately. Set other planes

+       * in a loop. */

+      mRecordBuf.video.video.buf.mp[cnt].planes[0].reserved[0] =

+        mRecordBuf.video.video.buf.mp[cnt].frame_offset;

+      mRecordBuf.video.video.buf.mp[cnt].planes[0].length = planes[0];

+      mRecordBuf.video.video.buf.mp[cnt].planes[0].m.userptr =

+        recordframes[cnt].fd;

+      for (int j = 1; j < num_planes; j++) {

+        mRecordBuf.video.video.buf.mp[cnt].planes[j].length = planes[j];

+        mRecordBuf.video.video.buf.mp[cnt].planes[j].m.userptr =

+          recordframes[cnt].fd;

+        mRecordBuf.video.video.buf.mp[cnt].planes[j].reserved[0] =

+          mRecordBuf.video.video.buf.mp[cnt].planes[j-1].reserved[0] +

+          mRecordBuf.video.video.buf.mp[cnt].planes[j-1].length;

+

+      }

+#endif

+    }

+#if 0

+    //memset(&mRecordBuf, 0, sizeof(mRecordBuf));

+    mRecordBuf.ch_type = MM_CAMERA_CH_VIDEO;

+    mRecordBuf.video.video.num = mHalCamCtrl->mRecordingMemory.buffer_count;//kRecordBufferCount;

+    //mRecordBuf.video.video.frame_offset = &record_offset[0];

+    //mRecordBuf.video.video.frame = &recordframes[0];

+#endif

+    LOGE("%s : END",__func__);

+    return NO_ERROR;

+}

+

+void QCameraStream_record::releaseRecordingFrame(const void *opaque)

+{

+    LOGE("%s : BEGIN, opaque = 0x%p",__func__, opaque);

+#if 0

+    if(!mActive)

+    {

+        LOGE("%s : Recording already stopped!!! Leak???",__func__);

+        return;

+    }

+    for(int cnt = 0; cnt < mHalCamCtrl->mRecordingMemory.buffer_count; cnt++) {

+      if (mHalCamCtrl->mStoreMetaDataInFrame) {

+        if(mHalCamCtrl->mRecordingMemory.metadata_memory[cnt] &&

+                mHalCamCtrl->mRecordingMemory.metadata_memory[cnt]->data == opaque) {

+            /* found the match */

+            if(MM_CAMERA_OK != cam_evt_buf_done(mCameraId, &mRecordedFrames[cnt]))

+                LOGE("%s : Buf Done Failed",__func__);

+            LOGE("%s : END",__func__);

+            return;

+        }

+      } else {

+        if(mHalCamCtrl->mRecordingMemory.camera_memory[cnt] &&

+                mHalCamCtrl->mRecordingMemory.camera_memory[cnt]->data == opaque) {

+            /* found the match */

+            if(MM_CAMERA_OK != cam_evt_buf_done(mCameraId, &mRecordedFrames[cnt]))

+                LOGE("%s : Buf Done Failed",__func__);

+            LOGE("%s : END",__func__);

+            return;

+        }

+      }

+    }

+#endif

+	LOGE("%s: cannot find the matched frame with opaue = 0x%p", __func__, opaque);

+}

+

+void QCameraStream_record::debugShowVideoFPS() const

+{

+#if 0

+  static int mFrameCount;

+  static int mLastFrameCount = 0;

+  static nsecs_t mLastFpsTime = 0;

+  static float mFps = 0;

+  mFrameCount++;

+  nsecs_t now = systemTime();

+  nsecs_t diff = now - mLastFpsTime;

+  if (diff > ms2ns(250)) {

+    mFps =  ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;

+    LOGI("Video Frames Per Second: %.4f", mFps);

+    mLastFpsTime = now;

+    mLastFrameCount = mFrameCount;

+  }

+#endif

+}

+

+#if 0

+sp<IMemoryHeap> QCameraStream_record::getHeap() const

+{

+  return mRecordHeap != NULL ? mRecordHeap->mHeap : NULL;

+}

+status_t  QCameraStream_record::takeLiveSnapshot()

+{

+  //snapshotframes = new msm_frame[1];

+  //memset(snapshotframes,0,sizeof(struct msm_frame));

+  //mJpegMaxSize = dim.video_width * dim.video_height * 1.5;

+  LOGE("%s: BEGIN", __func__);

+  mHalCamCtrl->snapshot_enabled = true;

+  LOGE("%s: END", __func__);

+  return true;

+}

+#endif

+

+status_t  QCameraStream_record::takeLiveSnapshot(){

+	return true;

+}

+

+}//namespace android

diff --git a/QCameraHWI_Still.cpp b/QCameraHWI_Still.cpp
index b43e90f..84adb88 100755
--- a/QCameraHWI_Still.cpp
+++ b/QCameraHWI_Still.cpp
@@ -1436,7 +1436,10 @@
         set_callbacks(snapshot_jpeg_fragment_cb, snapshot_jpeg_cb, this,
              mHalCamCtrl->mJpegMemory.camera_memory[0]->data, &mJpegOffset);
         omxJpegStart();
-        mm_jpeg_encoder_setMainImageQuality(mHalCamCtrl->getJpegQuality());
+	if (mHalCamCtrl->getJpegQuality())
+          mm_jpeg_encoder_setMainImageQuality(mHalCamCtrl->getJpegQuality());
+	else
+	   mm_jpeg_encoder_setMainImageQuality(85);
 
         LOGD("%s: Dimension to encode: main: %dx%d thumbnail: %dx%d", __func__,
              dimension.orig_picture_dx, dimension.orig_picture_dy,
diff --git a/QCameraStream.cpp b/QCameraStream.cpp
index 5d744c6..48c2363 100755
--- a/QCameraStream.cpp
+++ b/QCameraStream.cpp
@@ -1,5 +1,5 @@
 /*
-** Copyright (c) 2011 Code Aurora Forum. All rights reserved.
+** Copyright (c) 2011-2012 Code Aurora Forum. All rights reserved.
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
@@ -262,7 +262,7 @@
     int height = 0; /* height of channel */
     cam_ctrl_dimension_t dim;
     mm_camera_ch_image_fmt_parm_t fmt;
-
+    int preview_format;
     LOGE("%s: E",__func__);
 
     memset(&dim, 0, sizeof(cam_ctrl_dimension_t));
@@ -272,11 +272,14 @@
       LOGE("%s: X", __func__);
       return BAD_VALUE;
     }
-
+    char mDeviceName[PROPERTY_VALUE_MAX];
+    property_get("ro.product.device",mDeviceName," ");
     memset(&fmt, 0, sizeof(mm_camera_ch_image_fmt_parm_t));
     if(MM_CAMERA_CH_PREVIEW_MASK & ch_type_mask){
         fmt.ch_type = MM_CAMERA_CH_PREVIEW;
-        fmt.def.fmt = CAMERA_YUV_420_NV12; //dim.prev_format;
+        ret = cam_config_get_parm(mCameraId,
+                  MM_CAMERA_PARM_PREVIEW_FORMAT, &preview_format);
+        fmt.def.fmt = (cam_format_t)preview_format;
         fmt.def.dim.width = dim.display_width;
         fmt.def.dim.height =  dim.display_height;
     }else if(MM_CAMERA_CH_VIDEO_MASK & ch_type_mask){
diff --git a/mm_camera.c b/mm_camera.c
index dcc2a9b..6fbf486 100755
--- a/mm_camera.c
+++ b/mm_camera.c
@@ -484,6 +484,9 @@
              dim->width, dim->height);
     }
         break;
+    case MM_CAMERA_PARM_PREVIEW_FORMAT:
+        *((int *)parm->p_value) = my_obj->properties.preview_format;
+        break;
     case MM_CAMERA_PARM_MAX_PREVIEW_SIZE: {
         mm_camera_dimension_t *dim =
             (mm_camera_dimension_t *)parm->p_value;