camera: Mako camera hal upgrade
- Restructure of mm-camera-interface and HAL.
- Change to disable FS live snap if H/W doesn't support.
- Fix Ghosting effect in JPEG on zoom and rot.
- Support double buf padding for rotation in ZSL case.
- Fix buffer corruption for FS live snap shot.
Change-Id: If1667f0c185e2e341dd2dac586510659ea2743d7
diff --git a/camera/Android.mk b/camera/Android.mk
index 7730ec8..befb25f 100644
--- a/camera/Android.mk
+++ b/camera/Android.mk
@@ -15,6 +15,7 @@
endif
LOCAL_PATH:= $(call my-dir)
+ LOCAL_PATH1:= $(call my-dir)
include $(CLEAR_VARS)
@@ -138,4 +139,8 @@
include $(LOCAL_PATH)/mm-camera-interface/Android.mk
endif
+#Enable only to compile new interafece and HAL files.
+ifeq ($(V4L2_BASED_LIBCAM),true)
+include $(LOCAL_PATH1)/QCamera/Android.mk
+endif
endif
diff --git a/camera/QCamera/Android.mk b/camera/QCamera/Android.mk
new file mode 100755
index 0000000..c36c538
--- /dev/null
+++ b/camera/QCamera/Android.mk
@@ -0,0 +1,3 @@
+ifeq ($(TARGET_ARCH),arm)
+ include $(call all-subdir-makefiles)
+endif
diff --git a/camera/QCamera/HAL/Android.mk b/camera/QCamera/HAL/Android.mk
new file mode 100755
index 0000000..e520431
--- /dev/null
+++ b/camera/QCamera/HAL/Android.mk
@@ -0,0 +1,3 @@
+LOCAL_PATH:= $(call my-dir)
+#include $(LOCAL_PATH)/core/Android.mk
+#include $(LOCAL_PATH)/test/Android.mk
diff --git a/camera/QCamera/HAL/core/Android.mk b/camera/QCamera/HAL/core/Android.mk
new file mode 100755
index 0000000..367313a
--- /dev/null
+++ b/camera/QCamera/HAL/core/Android.mk
@@ -0,0 +1,91 @@
+
+#ifeq ($(call is-board-platform,msm8960),true)
+OLD_LOCAL_PATH := $(LOCAL_PATH)
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+ifeq ($(strip $(TARGET_USES_ION)),true)
+LOCAL_CFLAGS += -DUSE_ION
+endif
+
+DLOPEN_LIBMMCAMERA:=0
+
+LOCAL_CFLAGS:= -DDLOPEN_LIBMMCAMERA=$(DLOPEN_LIBMMCAMERA)
+
+LOCAL_CFLAGS += -DCAMERA_ION_HEAP_ID=ION_CP_MM_HEAP_ID # 8660=SMI, Rest=EBI
+LOCAL_CFLAGS += -DCAMERA_ZSL_ION_HEAP_ID=ION_CP_MM_HEAP_ID
+
+LOCAL_CFLAGS+= -DHW_ENCODE
+LOCAL_CFLAGS+= -DUSE_NEON_CONVERSION
+
+ifeq ($(call is-board-platform,msm8960),true)
+ LOCAL_CFLAGS += -DCAMERA_GRALLOC_HEAP_ID=GRALLOC_USAGE_PRIVATE_MM_HEAP
+ LOCAL_CFLAGS += -DCAMERA_GRALLOC_FALLBACK_HEAP_ID=GRALLOC_USAGE_PRIVATE_IOMMU_HEAP
+ LOCAL_CFLAGS += -DCAMERA_ION_FALLBACK_HEAP_ID=ION_IOMMU_HEAP_ID
+ LOCAL_CFLAGS += -DCAMERA_ZSL_ION_FALLBACK_HEAP_ID=ION_IOMMU_HEAP_ID
+ LOCAL_CFLAGS += -DCAMERA_GRALLOC_CACHING_ID=0
+else ifeq ($(call is-chipset-prefix-in-board-platform,msm8660),true)
+ LOCAL_CFLAGS += -DCAMERA_GRALLOC_HEAP_ID=GRALLOC_USAGE_PRIVATE_CAMERA_HEAP
+ LOCAL_CFLAGS += -DCAMERA_GRALLOC_FALLBACK_HEAP_ID=GRALLOC_USAGE_PRIVATE_CAMERA_HEAP # Don't Care
+ LOCAL_CFLAGS += -DCAMERA_ION_FALLBACK_HEAP_ID=ION_CAMERA_HEAP_ID # EBI
+ LOCAL_CFLAGS += -DCAMERA_ZSL_ION_FALLBACK_HEAP_ID=ION_CAMERA_HEAP_ID
+ LOCAL_CFLAGS += -DCAMERA_GRALLOC_CACHING_ID=0
+else
+ LOCAL_CFLAGS += -DCAMERA_GRALLOC_HEAP_ID=GRALLOC_USAGE_PRIVATE_ADSP_HEAP
+ LOCAL_CFLAGS += -DCAMERA_GRALLOC_FALLBACK_HEAP_ID=GRALLOC_USAGE_PRIVATE_ADSP_HEAP # Don't Care
+ LOCAL_CFLAGS += -DCAMERA_GRALLOC_CACHING_ID=GRALLOC_USAGE_PRIVATE_UNCACHED #uncached
+endif
+
+LOCAL_HAL_FILES := \
+ src/QCameraHAL.cpp \
+ src/QCameraHWI_Parm.cpp \
+ src/QCameraHWI.cpp \
+ src/QCameraHWI_Preview.cpp \
+ src/QCameraHWI_Record.cpp \
+ src/QCameraHWI_Still.cpp \
+ src/QCameraHWI_Mem.cpp \
+ src/QCameraStream.cpp
+
+LOCAL_HAL_WRAPPER_FILES := ../wrapper/QualcommCamera.cpp
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../wrapper \
+ $(LOCAL_PATH)/inc \
+ $(TARGET_OUT_INTERMEDIATES)/include/mm-camera-interface_badger \
+
+# may need remove this includes
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-camera
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-still \
+ $(TARGET_OUT_HEADERS)/mm-still/jpeg
+#end
+
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include/media
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+
+LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc \
+ hardware/qcom/display/libgenlock \
+ hardware/qcom/media/libstagefrighthw
+
+# if debug service layer and up , use stub camera!
+LOCAL_C_INCLUDES += \
+ frameworks/base/services/camera/libcameraservice
+
+LOCAL_SRC_FILES := \
+ $(LOCAL_HAL_WRAPPER_FILES) \
+ $(LOCAL_HAL_FILES)
+
+LOCAL_SHARED_LIBRARIES := libutils libui libcamera_client liblog libcutils
+LOCAL_SHARED_LIBRARIES += libmmcamera_interface_badger
+LOCAL_SHARED_LIBRARIES+= libgenlock libbinder
+
+LOCAL_CFLAGS += -include bionic/libc/kernel/common/linux/socket.h
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_MODULE:= camera_badger.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_SHARED_LIBRARY)
+
+LOCAL_PATH := $(OLD_LOCAL_PATH)
+
diff --git a/camera/QCamera/HAL/core/inc/QCameraHAL.h b/camera/QCamera/HAL/core/inc/QCameraHAL.h
new file mode 100755
index 0000000..c13d9bc
--- /dev/null
+++ b/camera/QCamera/HAL/core/inc/QCameraHAL.h
@@ -0,0 +1,37 @@
+/*
+** Copyright (c) 2011 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.
+*/
+
+#ifndef ANDROID_HARDWARE_QCAMERA_HAL_H
+#define ANDROID_HARDWARE_QCAMERA_HAL_H
+
+
+#include "QCameraHWI.h"
+
+extern "C" {
+#include <mm_camera_interface2.h>
+}
+namespace android {
+
+/* HAL should return NULL if it fails to open camera hardware. */
+extern "C" void *
+ QCameraHAL_openCameraHardware(int cameraId, int mode);
+extern "C" int HAL_getNumberOfCameras();
+extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo);
+
+}; // namespace android
+
+#endif
+
diff --git a/camera/QCamera/HAL/core/inc/QCameraHWI.h b/camera/QCamera/HAL/core/inc/QCameraHWI.h
new file mode 100755
index 0000000..eb02d0a
--- /dev/null
+++ b/camera/QCamera/HAL/core/inc/QCameraHWI.h
@@ -0,0 +1,836 @@
+/*
+** 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.
+** 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.
+*/
+
+#ifndef ANDROID_HARDWARE_QCAMERA_HARDWARE_INTERFACE_H
+#define ANDROID_HARDWARE_QCAMERA_HARDWARE_INTERFACE_H
+
+
+#include <utils/threads.h>
+//#include <camera/CameraHardwareInterface.h>
+#include <hardware/camera.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <binder/MemoryHeapPmem.h>
+#include <utils/threads.h>
+#include <cutils/properties.h>
+#include <camera/Camera.h>
+#include <camera/CameraParameters.h>
+#include <system/window.h>
+#include <system/camera.h>
+#include <hardware/camera.h>
+#include <gralloc_priv.h>
+#include <QComOMXMetadata.h>
+
+extern "C" {
+#include <linux/android_pmem.h>
+#include <linux/ion.h>
+//#include <camera.h>
+//#include <camera_defs_i.h>
+#include <mm_camera_interface2.h>
+
+#include "mm_omx_jpeg_encoder.h"
+
+} //extern C
+
+#include "QCameraHWI_Mem.h"
+#include "QCameraStream.h"
+
+//Error codes
+#define NOT_FOUND -1
+#define MAX_ZOOM_RATIOS 62
+
+#ifdef Q12
+#undef Q12
+#endif
+
+#define Q12 4096
+#define QCAMERA_PARM_ENABLE 1
+#define QCAMERA_PARM_DISABLE 0
+#define PREVIEW_TBL_MAX_SIZE 14
+#define VIDEO_TBL_MAX_SIZE 14
+#define THUMB_TBL_MAX_SIZE 16
+#define HFR_TBL_MAX_SIZE 2
+
+struct str_map {
+ const char *const desc;
+ int val;
+};
+
+struct preview_format_info_t {
+ int Hal_format;
+ cam_format_t mm_cam_format;
+ cam_pad_format_t padding;
+ int num_planar;
+};
+
+typedef enum {
+ CAMERA_STATE_UNINITED,
+ CAMERA_STATE_READY,
+ CAMERA_STATE_PREVIEW_START_CMD_SENT,
+ CAMERA_STATE_PREVIEW_STOP_CMD_SENT,
+ CAMERA_STATE_PREVIEW,
+ CAMERA_STATE_RECORD_START_CMD_SENT, /*5*/
+ CAMERA_STATE_RECORD_STOP_CMD_SENT,
+ CAMERA_STATE_RECORD,
+ CAMERA_STATE_SNAP_START_CMD_SENT,
+ CAMERA_STATE_SNAP_STOP_CMD_SENT,
+ CAMERA_STATE_SNAP_CMD_ACKED, /*10 - snapshot comd acked, snapshot not done yet*/
+ CAMERA_STATE_ZSL_START_CMD_SENT,
+ CAMERA_STATE_ZSL,
+ CAMERA_STATE_AF_START_CMD_SENT,
+ CAMERA_STATE_AF_STOP_CMD_SENT,
+ CAMERA_STATE_ERROR, /*15*/
+
+ /*Add any new state above*/
+ CAMERA_STATE_MAX
+} HAL_camera_state_type_t;
+
+enum {
+ BUFFER_NOT_OWNED,
+ BUFFER_UNLOCKED,
+ BUFFER_LOCKED,
+};
+
+typedef enum {
+ HAL_DUMP_FRM_PREVIEW = 1,
+ HAL_DUMP_FRM_VIDEO = 1<<1,
+ HAL_DUMP_FRM_MAIN = 1<<2,
+ HAL_DUMP_FRM_THUMBNAIL = 1<<3,
+
+ /*8 bits mask*/
+ HAL_DUMP_FRM_MAX = 1 << 8
+} HAL_cam_dump_frm_type_t;
+
+
+typedef enum {
+ HAL_CAM_MODE_ZSL = 1,
+
+ /*add new entry before and update the max entry*/
+ HAL_CAM_MODE_MAX = HAL_CAM_MODE_ZSL << 1,
+} qQamera_mode_t;
+
+#define HAL_DUMP_FRM_MASK_ALL ( HAL_DUMP_FRM_PREVIEW + HAL_DUMP_FRM_VIDEO + \
+ HAL_DUMP_FRM_MAIN + HAL_DUMP_FRM_THUMBNAIL)
+#define QCAMERA_HAL_PREVIEW_STOPPED 0
+#define QCAMERA_HAL_PREVIEW_START 1
+#define QCAMERA_HAL_PREVIEW_STARTED 2
+#define QCAMERA_HAL_RECORDING_STARTED 3
+#define QCAMERA_HAL_TAKE_PICTURE 4
+
+
+typedef struct {
+ int buffer_count;
+ buffer_handle_t *buffer_handle[MM_CAMERA_MAX_NUM_FRAMES];
+ struct private_handle_t *private_buffer_handle[MM_CAMERA_MAX_NUM_FRAMES];
+ int stride[MM_CAMERA_MAX_NUM_FRAMES];
+ uint32_t addr_offset[MM_CAMERA_MAX_NUM_FRAMES];
+ uint8_t local_flag[MM_CAMERA_MAX_NUM_FRAMES];
+ camera_memory_t *camera_memory[MM_CAMERA_MAX_NUM_FRAMES];
+ int main_ion_fd[MM_CAMERA_MAX_NUM_FRAMES];
+ struct ion_fd_data ion_info_fd[MM_CAMERA_MAX_NUM_FRAMES];
+} QCameraHalMemory_t;
+
+
+typedef struct {
+ int buffer_count;
+ uint32_t size;
+ uint32_t y_offset;
+ uint32_t cbcr_offset;
+ int fd[MM_CAMERA_MAX_NUM_FRAMES];
+ int local_flag[MM_CAMERA_MAX_NUM_FRAMES];
+ camera_memory_t* camera_memory[MM_CAMERA_MAX_NUM_FRAMES];
+ camera_memory_t* metadata_memory[MM_CAMERA_MAX_NUM_FRAMES];
+ int main_ion_fd[MM_CAMERA_MAX_NUM_FRAMES];
+ struct ion_allocation_data alloc[MM_CAMERA_MAX_NUM_FRAMES];
+ struct ion_fd_data ion_info_fd[MM_CAMERA_MAX_NUM_FRAMES];
+} QCameraHalHeap_t;
+
+typedef struct {
+ camera_memory_t* camera_memory[3];
+ int main_ion_fd[3];
+ struct ion_allocation_data alloc[3];
+ struct ion_fd_data ion_info_fd[3];
+ int fd[3];
+ int size;
+} QCameraStatHeap_t;
+
+typedef struct {
+ int32_t msg_type;
+ int32_t ext1;
+ int32_t ext2;
+ void *cookie;
+} argm_notify_t;
+
+typedef struct {
+ int32_t msg_type;
+ camera_memory_t *data;
+ unsigned int index;
+ camera_frame_metadata_t *metadata;
+ void *cookie;
+} argm_data_cb_t;
+
+typedef struct {
+ camera_notify_callback notifyCb;
+ camera_data_callback dataCb;
+ argm_notify_t argm_notify;
+ argm_data_cb_t argm_data_cb;
+} app_notify_cb_t;
+
+/* camera_area_t
+ * rectangle with weight to store the focus and metering areas.
+ * x1, y1, x2, y2: from -1000 to 1000
+ * weight: 0 to 1000
+ */
+typedef struct {
+ int x1, y1, x2, y2;
+ int weight;
+} camera_area_t;
+
+//EXIF globals
+static const char ExifAsciiPrefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 }; // "ASCII\0\0\0"
+static const char ExifUndefinedPrefix[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // "\0\0\0\0\0\0\0\0"
+
+//EXIF detfines
+#define MAX_EXIF_TABLE_ENTRIES 14
+#define GPS_PROCESSING_METHOD_SIZE 101
+#define FOCAL_LENGTH_DECIMAL_PRECISION 100
+#define EXIF_ASCII_PREFIX_SIZE 8 //(sizeof(ExifAsciiPrefix))
+
+typedef struct{
+ //GPS tags
+ rat_t latitude[3];
+ rat_t longitude[3];
+ char lonRef[2];
+ char latRef[2];
+ rat_t altitude;
+ rat_t gpsTimeStamp[3];
+ char gpsDateStamp[20];
+ char gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE+GPS_PROCESSING_METHOD_SIZE];
+ //Other tags
+ char dateTime[20];
+ rat_t focalLength;
+ uint16_t flashMode;
+ uint16_t isoSpeed;
+
+ bool mAltitude;
+ bool mLongitude;
+ bool mLatitude;
+ bool mTimeStamp;
+ bool mGpsProcess;
+
+ int mAltitude_ref;
+ long mGPSTimestamp;
+
+} exif_values_t;
+
+namespace android {
+
+class QCameraStream;
+
+class QCameraHardwareInterface : public virtual RefBase {
+public:
+
+ QCameraHardwareInterface(int cameraId, int mode);
+
+ /** Set the ANativeWindow to which preview frames are sent */
+ int setPreviewWindow(preview_stream_ops_t* window);
+
+ /** Set the notification and data callbacks */
+ void setCallbacks(camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void *user);
+
+ /**
+ * The following three functions all take a msg_type, which is a bitmask of
+ * the messages defined in include/ui/Camera.h
+ */
+
+ /**
+ * Enable a message, or set of messages.
+ */
+ void enableMsgType(int32_t msg_type);
+
+ /**
+ * Disable a message, or a set of messages.
+ *
+ * Once received a call to disableMsgType(CAMERA_MSG_VIDEO_FRAME), camera
+ * HAL should not rely on its client to call releaseRecordingFrame() to
+ * release video recording frames sent out by the cameral HAL before and
+ * after the disableMsgType(CAMERA_MSG_VIDEO_FRAME) call. Camera HAL
+ * clients must not modify/access any video recording frame after calling
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME).
+ */
+ void disableMsgType(int32_t msg_type);
+
+ /**
+ * Query whether a message, or a set of messages, is enabled. Note that
+ * this is operates as an AND, if any of the messages queried are off, this
+ * will return false.
+ */
+ int msgTypeEnabled(int32_t msg_type);
+
+ /**
+ * Start preview mode.
+ */
+ int startPreview();
+ int startPreview2();
+
+ /**
+ * Stop a previously started preview.
+ */
+ void stopPreview();
+
+ /**
+ * Returns true if preview is enabled.
+ */
+ int previewEnabled();
+
+
+ /**
+ * Request the camera HAL to store meta data or real YUV data in the video
+ * buffers sent out via CAMERA_MSG_VIDEO_FRAME for a recording session. If
+ * it is not called, the default camera HAL behavior is to store real YUV
+ * data in the video buffers.
+ *
+ * This method should be called before startRecording() in order to be
+ * effective.
+ *
+ * If meta data is stored in the video buffers, it is up to the receiver of
+ * the video buffers to interpret the contents and to find the actual frame
+ * data with the help of the meta data in the buffer. How this is done is
+ * outside of the scope of this method.
+ *
+ * Some camera HALs may not support storing meta data in the video buffers,
+ * but all camera HALs should support storing real YUV data in the video
+ * buffers. If the camera HAL does not support storing the meta data in the
+ * video buffers when it is requested to do do, INVALID_OPERATION must be
+ * returned. It is very useful for the camera HAL to pass meta data rather
+ * than the actual frame data directly to the video encoder, since the
+ * amount of the uncompressed frame data can be very large if video size is
+ * large.
+ *
+ * @param enable if true to instruct the camera HAL to store
+ * meta data in the video buffers; false to instruct
+ * the camera HAL to store real YUV data in the video
+ * buffers.
+ *
+ * @return OK on success.
+ */
+ int storeMetaDataInBuffers(int enable);
+
+ /**
+ * Start record mode. When a record image is available, a
+ * CAMERA_MSG_VIDEO_FRAME message is sent with the corresponding
+ * frame. Every record frame must be released by a camera HAL client via
+ * releaseRecordingFrame() before the client calls
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME). After the client calls
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's
+ * responsibility to manage the life-cycle of the video recording frames,
+ * and the client must not modify/access any video recording frames.
+ */
+ int startRecording();
+
+ /**
+ * Stop a previously started recording.
+ */
+ void stopRecording();
+
+ /**
+ * Returns true if recording is enabled.
+ */
+ int recordingEnabled();
+
+ /**
+ * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME.
+ *
+ * It is camera HAL client's responsibility to release video recording
+ * frames sent out by the camera HAL before the camera HAL receives a call
+ * to disableMsgType(CAMERA_MSG_VIDEO_FRAME). After it receives the call to
+ * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's
+ * responsibility to manage the life-cycle of the video recording frames.
+ */
+ void releaseRecordingFrame(const void *opaque);
+
+ /**
+ * Start auto focus, the notification callback routine is called with
+ * CAMERA_MSG_FOCUS once when focusing is complete. autoFocus() will be
+ * called again if another auto focus is needed.
+ */
+ int autoFocus();
+
+ /**
+ * Cancels auto-focus function. If the auto-focus is still in progress,
+ * this function will cancel it. Whether the auto-focus is in progress or
+ * not, this function will return the focus position to the default. If
+ * the camera does not support auto-focus, this is a no-op.
+ */
+ int cancelAutoFocus();
+
+ /**
+ * Take a picture.
+ */
+ int takePicture();
+
+ /**
+ * Cancel a picture that was started with takePicture. Calling this method
+ * when no picture is being taken is a no-op.
+ */
+ int cancelPicture();
+
+ /**
+ * Set the camera parameters. This returns BAD_VALUE if any parameter is
+ * invalid or not supported.
+ */
+ int setParameters(const char *parms);
+
+ //status_t setParameters(const CameraParameters& params);
+ /** Retrieve the camera parameters. The buffer returned by the camera HAL
+ must be returned back to it with put_parameters, if put_parameters
+ is not NULL.
+ */
+ int getParameters(char **parms);
+
+ /** The camera HAL uses its own memory to pass us the parameters when we
+ call get_parameters. Use this function to return the memory back to
+ the camera HAL, if put_parameters is not NULL. If put_parameters
+ is NULL, then you have to use free() to release the memory.
+ */
+ void putParameters(char *);
+
+ /**
+ * Send command to camera driver.
+ */
+ int sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
+
+ /**
+ * Release the hardware resources owned by this object. Note that this is
+ * *not* done in the destructor.
+ */
+ void release();
+
+ /**
+ * Dump state of the camera hardware
+ */
+ int dump(int fd);
+
+ //virtual sp<IMemoryHeap> getPreviewHeap() const;
+ //virtual sp<IMemoryHeap> getRawHeap() const;
+
+
+ status_t takeLiveSnapshot();
+ status_t takeFullSizeLiveshot();
+ bool canTakeFullSizeLiveshot();
+
+ //virtual status_t getBufferInfo( sp<IMemory>& Frame,
+ //size_t *alignedSize);
+ void getPictureSize(int *picture_width, int *picture_height) const;
+ void getPreviewSize(int *preview_width, int *preview_height) const;
+ cam_format_t getPreviewFormat() const;
+
+ cam_pad_format_t getPreviewPadding() const;
+
+ //bool useOverlay(void);
+ //virtual status_t setOverlay(const sp<Overlay> &overlay);
+ void processEvent(mm_camera_event_t *);
+ int getJpegQuality() const;
+ int getNumOfSnapshots(void) const;
+ int getNumOfSnapshots(const CameraParameters& params);
+ int getThumbSizesFromAspectRatio(uint32_t aspect_ratio,
+ int *picture_width,
+ int *picture_height);
+ bool isRawSnapshot();
+ bool mShutterSoundPlayed;
+ void dumpFrameToFile(struct msm_frame*, HAL_cam_dump_frm_type_t);
+
+ static QCameraHardwareInterface *createInstance(int, int);
+ status_t setZSLBurstLookBack(const CameraParameters& params);
+ status_t setZSLBurstInterval(const CameraParameters& params);
+ int getZSLBurstInterval(void);
+ int getZSLQueueDepth(void) const;
+ int getZSLBackLookCount(void) const;
+
+ ~QCameraHardwareInterface();
+ int initHeapMem(QCameraHalHeap_t *heap, int num_of_buf, int pmem_type,
+ int frame_len, int cbcr_off, int y_off, mm_cameara_stream_buf_t *StreamBuf,
+ mm_camera_buf_def_t *buf_def, uint8_t num_planes, uint32_t *planes);
+
+ int releaseHeapMem( QCameraHalHeap_t *heap);
+ status_t sendMappingBuf(int ext_mode, int idx, int fd, uint32_t size,
+ int cameraid, mm_camera_socket_msg_type msg_type);
+ status_t sendUnMappingBuf(int ext_mode, int idx, int cameraid,
+ mm_camera_socket_msg_type msg_type);
+
+ int allocate_ion_memory(QCameraHalHeap_t *p_camera_memory, int cnt,
+ int ion_type);
+ int deallocate_ion_memory(QCameraHalHeap_t *p_camera_memory, int cnt);
+
+ int allocate_ion_memory(QCameraStatHeap_t *p_camera_memory, int cnt,
+ int ion_type);
+ int deallocate_ion_memory(QCameraStatHeap_t *p_camera_memory, int cnt);
+
+ int cache_ops(int ion_fd, struct ion_flush_data *cache_inv_data, int type);
+
+ void dumpFrameToFile(const void * data, uint32_t size, char* name,
+ char* ext, int index);
+ preview_format_info_t getPreviewFormatInfo( );
+ bool isCameraReady();
+ bool isNoDisplayMode();
+
+private:
+ int16_t zoomRatios[MAX_ZOOM_RATIOS];
+ struct camera_size_type default_preview_sizes[PREVIEW_TBL_MAX_SIZE];
+ struct camera_size_type default_video_sizes[VIDEO_TBL_MAX_SIZE];
+ struct camera_size_type default_hfr_sizes[HFR_TBL_MAX_SIZE];
+ struct camera_size_type default_thumbnail_sizes[THUMB_TBL_MAX_SIZE];
+ unsigned int preview_sizes_count;
+ unsigned int video_sizes_count;
+ unsigned int thumbnail_sizes_count;
+ unsigned int hfr_sizes_count;
+
+
+ bool mUseOverlay;
+
+ void loadTables();
+ void initDefaultParameters();
+ bool getMaxPictureDimension(mm_camera_dimension_t *dim);
+
+ status_t updateFocusDistances();
+
+ bool native_set_parms(mm_camera_parm_type_t type, uint16_t length, void *value);
+ bool native_set_parms( mm_camera_parm_type_t type, uint16_t length, void *value, int *result);
+
+ void hasAutoFocusSupport();
+ void debugShowPreviewFPS() const;
+ //void prepareSnapshotAndWait();
+
+ bool isPreviewRunning();
+ bool isRecordingRunning();
+ bool isSnapshotRunning();
+
+ void processChannelEvent(mm_camera_ch_event_t *, app_notify_cb_t *);
+ void processPreviewChannelEvent(mm_camera_ch_event_type_t channelEvent, app_notify_cb_t *);
+ void processRecordChannelEvent(mm_camera_ch_event_type_t channelEvent, app_notify_cb_t *);
+ void processSnapshotChannelEvent(mm_camera_ch_event_type_t channelEvent, app_notify_cb_t *);
+ void processCtrlEvent(mm_camera_ctrl_event_t *, app_notify_cb_t *);
+ void processStatsEvent(mm_camera_stats_event_t *, app_notify_cb_t *);
+ void processInfoEvent(mm_camera_info_event_t *event, app_notify_cb_t *);
+ void processprepareSnapshotEvent(cam_ctrl_status_t *);
+ void roiEvent(fd_roi_t roi, app_notify_cb_t *);
+ void zoomEvent(cam_ctrl_status_t *status, app_notify_cb_t *);
+ void autofocusevent(cam_ctrl_status_t *status, app_notify_cb_t *);
+ void handleZoomEventForPreview(app_notify_cb_t *);
+ void handleZoomEventForSnapshot(void);
+ status_t autoFocusEvent(cam_ctrl_status_t *, app_notify_cb_t *);
+
+ void filterPictureSizes();
+ bool supportsSceneDetection();
+ bool supportsSelectableZoneAf();
+ bool supportsFaceDetection();
+ bool supportsRedEyeReduction();
+ bool preview_parm_config (cam_ctrl_dimension_t* dim,CameraParameters& parm);
+
+ void stopPreviewInternal();
+ void stopRecordingInternal();
+ //void stopPreviewZSL();
+ status_t cancelPictureInternal();
+ //status_t startPreviewZSL();
+ void pausePreviewForSnapshot();
+ void pausePreviewForZSL();
+ status_t resumePreviewAfterSnapshot();
+
+ status_t runFaceDetection();
+
+ status_t setParameters(const CameraParameters& params);
+ CameraParameters& getParameters() ;
+
+ status_t setCameraMode(const CameraParameters& params);
+ status_t setPictureSizeTable(void);
+ status_t setPreviewSizeTable(void);
+ status_t setVideoSizeTable(void);
+ status_t setPreviewSize(const CameraParameters& params);
+ status_t setJpegThumbnailSize(const CameraParameters& params);
+ status_t setPreviewFpsRange(const CameraParameters& params);
+ status_t setPreviewFrameRate(const CameraParameters& params);
+ status_t setPreviewFrameRateMode(const CameraParameters& params);
+ status_t setVideoSize(const CameraParameters& params);
+ status_t setPictureSize(const CameraParameters& params);
+ status_t setJpegQuality(const CameraParameters& params);
+ status_t setNumOfSnapshot(const CameraParameters& params);
+ status_t setJpegRotation(int isZSL);
+ int getJpegRotation(void);
+ int getISOSpeedValue();
+ status_t setAntibanding(const CameraParameters& params);
+ status_t setEffect(const CameraParameters& params);
+ status_t setExposureCompensation(const CameraParameters ¶ms);
+ status_t setAutoExposure(const CameraParameters& params);
+ status_t setWhiteBalance(const CameraParameters& params);
+ status_t setFlash(const CameraParameters& params);
+ status_t setGpsLocation(const CameraParameters& params);
+ status_t setRotation(const CameraParameters& params);
+ status_t setZoom(const CameraParameters& params);
+ status_t setFocusMode(const CameraParameters& params);
+ status_t setBrightness(const CameraParameters& params);
+ status_t setSkinToneEnhancement(const CameraParameters& params);
+ status_t setOrientation(const CameraParameters& params);
+ status_t setLensshadeValue(const CameraParameters& params);
+ status_t setMCEValue(const CameraParameters& params);
+ status_t setISOValue(const CameraParameters& params);
+ status_t setPictureFormat(const CameraParameters& params);
+ status_t setSharpness(const CameraParameters& params);
+ status_t setContrast(const CameraParameters& params);
+ status_t setSaturation(const CameraParameters& params);
+ status_t setWaveletDenoise(const CameraParameters& params);
+ status_t setSceneMode(const CameraParameters& params);
+ status_t setContinuousAf(const CameraParameters& params);
+ status_t setFaceDetection(const char *str);
+ status_t setSceneDetect(const CameraParameters& params);
+ status_t setStrTextures(const CameraParameters& params);
+ status_t setPreviewFormat(const CameraParameters& params);
+ status_t setSelectableZoneAf(const CameraParameters& params);
+ status_t setOverlayFormats(const CameraParameters& params);
+ status_t setHighFrameRate(const CameraParameters& params);
+ status_t setRedeyeReduction(const CameraParameters& params);
+ status_t setAEBracket(const CameraParameters& params);
+ status_t setFaceDetect(const CameraParameters& params);
+ status_t setDenoise(const CameraParameters& params);
+ status_t setAecAwbLock(const CameraParameters & params);
+ status_t setHistogram(int histogram_en);
+ status_t setRecordingHint(const CameraParameters& params);
+ status_t setRecordingHintValue(const int32_t value);
+ status_t setFocusAreas(const CameraParameters& params);
+ status_t setMeteringAreas(const CameraParameters& params);
+ status_t setFullLiveshot(void);
+ status_t setDISMode(void);
+ status_t setCaptureBurstExp(void);
+ status_t setPowerMode(const CameraParameters& params);
+ void takePicturePrepareHardware( );
+ status_t setNoDisplayMode(const CameraParameters& params);
+
+ isp3a_af_mode_t getAutoFocusMode(const CameraParameters& params);
+ bool isValidDimension(int w, int h);
+
+ String8 create_values_str(const str_map *values, int len);
+
+ void setMyMode(int mode);
+ bool isZSLMode();
+ bool isWDenoiseEnabled();
+ void wdenoiseEvent(cam_ctrl_status_t status, void *cookie);
+ bool isLowPowerCamcorder();
+ void freePictureTable(void);
+ void freeVideoSizeTable(void);
+
+ int32_t createPreview();
+ int32_t createRecord();
+ int32_t createSnapshot();
+
+ int getHDRMode();
+ //EXIF
+ void addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
+ uint32_t count, uint8_t copy, void *data);
+ void setExifTags();
+ void initExifData();
+ void deinitExifData();
+ void setExifTagsGPS();
+ exif_tags_info_t* getExifData(){ return mExifData; }
+ int getExifTableNumEntries() { return mExifTableNumEntries; }
+ void parseGPSCoordinate(const char *latlonString, rat_t* coord);
+
+ int mCameraId;
+ camera_mode_t myMode;
+
+ CameraParameters mParameters;
+ //sp<Overlay> mOverlay;
+ int32_t mMsgEnabled;
+
+ camera_notify_callback mNotifyCb;
+ camera_data_callback mDataCb;
+ camera_data_timestamp_callback mDataCbTimestamp;
+ camera_request_memory mGetMemory;
+ void *mCallbackCookie;
+
+ //sp<MemoryHeapBase> mPreviewHeap; //@Guru : Need to remove
+ sp<AshmemPool> mMetaDataHeap;
+
+ mutable Mutex mLock;
+ //mutable Mutex eventLock;
+ Mutex mCallbackLock;
+ Mutex mPreviewMemoryLock;
+ Mutex mRecordingMemoryLock;
+ Mutex mAutofocusLock;
+ Mutex mMetaDataWaitLock;
+ Mutex mRecordFrameLock;
+ Mutex mRecordLock;
+ Condition mRecordWait;
+ pthread_mutex_t mAsyncCmdMutex;
+ pthread_cond_t mAsyncCmdWait;
+
+ QCameraStream *mStreamDisplay;
+ QCameraStream *mStreamRecord;
+ QCameraStream *mStreamSnap;
+ QCameraStream *mStreamLiveSnap;
+
+ cam_ctrl_dimension_t mDimension;
+ int mPreviewWidth, mPreviewHeight;
+ int videoWidth, videoHeight;
+ int thumbnailWidth, thumbnailHeight;
+ int maxSnapshotWidth, maxSnapshotHeight;
+ int mPreviewFormat;
+ int mFps;
+ int mDebugFps;
+ int mBrightness;
+ int mContrast;
+ int mBestShotMode;
+ int mEffects;
+ int mSkinToneEnhancement;
+ int mDenoiseValue;
+ int mHJR;
+ int mRotation;
+ int mJpegQuality;
+ int mThumbnailQuality;
+ int mTargetSmoothZoom;
+ int mSmoothZoomStep;
+ int mMaxZoom;
+ int mCurrentZoom;
+ int mSupportedPictureSizesCount;
+ int mFaceDetectOn;
+ int mDumpFrmCnt;
+ int mDumpSkipCnt;
+ int mFocusMode;
+
+ unsigned int mPictureSizeCount;
+ unsigned int mPreviewSizeCount;
+ int mPowerMode;
+ unsigned int mVideoSizeCount;
+
+ bool mAutoFocusRunning;
+ bool mMultiTouch;
+ bool mHasAutoFocusSupport;
+ bool mInitialized;
+ bool mDisEnabled;
+ bool strTexturesOn;
+ bool mIs3DModeOn;
+ bool mSmoothZoomRunning;
+ bool mPreparingSnapshot;
+ bool mParamStringInitialized;
+ bool mZoomSupported;
+ bool mSendMetaData;
+ bool mFullLiveshotEnabled;
+ bool mRecordingHint;
+ bool mStartRecording;
+ bool mReleasedRecordingFrame;
+ int mHdrMode;
+ int mSnapshotFormat;
+ int mZslInterval;
+ bool mRestartPreview;
+
+/*for histogram*/
+ int mStatsOn;
+ int mCurrentHisto;
+ bool mSendData;
+ sp<AshmemPool> mStatHeap;
+ camera_memory_t *mStatsMapped[3];
+ QCameraStatHeap_t mHistServer;
+ int32_t mStatSize;
+
+ bool mZslLookBackMode;
+ int mZslLookBackValue;
+ int mHFRLevel;
+ bool mZslEmptyQueueFlag;
+ String8 mEffectValues;
+ String8 mIsoValues;
+ String8 mSceneModeValues;
+ String8 mSceneDetectValues;
+ String8 mFocusModeValues;
+ String8 mSelectableZoneAfValues;
+ String8 mAutoExposureValues;
+ String8 mWhitebalanceValues;
+ String8 mAntibandingValues;
+ String8 mFrameRateModeValues;
+ String8 mTouchAfAecValues;
+ String8 mPreviewSizeValues;
+ String8 mPictureSizeValues;
+ String8 mVideoSizeValues;
+ String8 mFlashValues;
+ String8 mLensShadeValues;
+ String8 mMceValues;
+ String8 mHistogramValues;
+ String8 mSkinToneEnhancementValues;
+ String8 mPictureFormatValues;
+ String8 mDenoiseValues;
+ String8 mZoomRatioValues;
+ String8 mPreviewFrameRateValues;
+ String8 mPreviewFormatValues;
+ String8 mFaceDetectionValues;
+ String8 mHfrValues;
+ String8 mHfrSizeValues;
+ String8 mRedeyeReductionValues;
+ String8 denoise_value;
+ String8 mFpsRangesSupportedValues;
+ String8 mZslValues;
+ String8 mFocusDistance;
+
+ friend class QCameraStream;
+ friend class QCameraStream_record;
+ friend class QCameraStream_preview;
+ friend class QCameraStream_Snapshot;
+
+ camera_size_type* mPictureSizes;
+ camera_size_type* mPreviewSizes;
+ camera_size_type* mVideoSizes;
+ const camera_size_type * mPictureSizesPtr;
+ HAL_camera_state_type_t mCameraState;
+
+ /* Temporary - can be removed after Honeycomb*/
+#ifdef USE_ION
+ sp<IonPool> mPostPreviewHeap;
+#else
+ sp<PmemPool> mPostPreviewHeap;
+#endif
+ mm_cameara_stream_buf_t mPrevForPostviewBuf;
+ int mStoreMetaDataInFrame;
+ preview_stream_ops_t *mPreviewWindow;
+ Mutex mStateLock;
+ int mPreviewState;
+ /*preview memory with display case: memory is allocated and freed via
+ gralloc */
+ QCameraHalMemory_t mPreviewMemory;
+
+ /*preview memory without display case: memory is allocated
+ directly by camera */
+ QCameraHalHeap_t mNoDispPreviewMemory;
+
+ QCameraHalHeap_t mSnapshotMemory;
+ QCameraHalHeap_t mThumbnailMemory;
+ QCameraHalHeap_t mRecordingMemory;
+ QCameraHalHeap_t mJpegMemory;
+ QCameraHalHeap_t mRawMemory;
+ camera_frame_metadata_t mMetadata;
+ camera_face_t mFace[MAX_ROI];
+ preview_format_info_t mPreviewFormatInfo;
+ friend void liveshot_callback(mm_camera_ch_data_buf_t *frame,void *user_data);
+
+ //EXIF
+ exif_tags_info_t mExifData[MAX_EXIF_TABLE_ENTRIES]; //Exif tags for JPEG encoder
+ exif_values_t mExifValues; //Exif values in usable format
+ int mExifTableNumEntries; //NUmber of entries in mExifData
+ int mNoDisplayMode;
+};
+
+}; // namespace android
+
+#endif
diff --git a/camera/QCamera/HAL/core/inc/QCameraHWI_Mem.h b/camera/QCamera/HAL/core/inc/QCameraHWI_Mem.h
new file mode 100755
index 0000000..079b0f9
--- /dev/null
+++ b/camera/QCamera/HAL/core/inc/QCameraHWI_Mem.h
@@ -0,0 +1,111 @@
+/*
+** 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.
+** 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.
+*/
+
+
+#ifndef __QCAMERAHWI_MEM_H
+#define __QCAMERAHWI_MEM_H
+
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <utils/threads.h>
+#include <stdint.h>
+
+extern "C" {
+#include <linux/android_pmem.h>
+#include <linux/ion.h>
+#include <camera.h>
+#include <camera_defs_i.h>
+
+}
+
+
+#define VIDEO_BUFFER_COUNT 5
+#define VIDEO_BUFFER_COUNT_LOW_POWER_CAMCORDER 9
+
+#define PREVIEW_BUFFER_COUNT 5
+
+namespace android {
+
+// This class represents a heap which maintains several contiguous
+// buffers. The heap may be backed by pmem (when pmem_pool contains
+// the name of a /dev/pmem* file), or by ashmem (when pmem_pool == NULL).
+
+struct MemPool : public RefBase {
+ MemPool(int buffer_size, int num_buffers,
+ int frame_size,
+ const char *name);
+
+ virtual ~MemPool() = 0;
+
+ void completeInitialization();
+ bool initialized() const {
+ return mHeap != NULL && mHeap->base() != MAP_FAILED;
+ }
+
+ virtual status_t dump(int fd, const Vector<String16>& args) const;
+
+ int mBufferSize;
+ int mAlignedBufferSize;
+ int mNumBuffers;
+ int mFrameSize;
+ sp<MemoryHeapBase> mHeap;
+ sp<MemoryBase> *mBuffers;
+
+ const char *mName;
+};
+
+class AshmemPool : public MemPool {
+public:
+ AshmemPool(int buffer_size, int num_buffers,
+ int frame_size,
+ const char *name);
+};
+
+class PmemPool : public MemPool {
+public:
+ PmemPool(const char *pmem_pool,
+ int flags, int pmem_type,
+ int buffer_size, int num_buffers,
+ int frame_size, int cbcr_offset,
+ int yoffset, const char *name);
+ virtual ~PmemPool();
+ int mFd;
+ int mPmemType;
+ int mCbCrOffset;
+ int myOffset;
+ int mCameraControlFd;
+ uint32_t mAlignedSize;
+ struct pmem_region mSize;
+};
+
+class IonPool : public MemPool {
+public:
+ IonPool( int flags,
+ int buffer_size, int num_buffers,
+ int frame_size, int cbcr_offset,
+ int yoffset, const char *name);
+ virtual ~IonPool();
+ int mFd;
+ int mCbCrOffset;
+ int myOffset;
+ int mCameraControlFd;
+ uint32_t mAlignedSize;
+private:
+ static const char mIonDevName[];
+};
+
+};
+#endif
diff --git a/camera/QCamera/HAL/core/inc/QCameraStream.h b/camera/QCamera/HAL/core/inc/QCameraStream.h
new file mode 100755
index 0000000..8c416e4
--- /dev/null
+++ b/camera/QCamera/HAL/core/inc/QCameraStream.h
@@ -0,0 +1,377 @@
+/*
+** Copyright 2008, Google Inc.
+** Copyright (c) 2009-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.
+*/
+
+#ifndef ANDROID_HARDWARE_QCAMERA_STREAM_H
+#define ANDROID_HARDWARE_QCAMERA_STREAM_H
+
+
+#include <utils/threads.h>
+
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <utils/threads.h>
+
+#include "QCameraHWI.h"
+#include "QCameraHWI_Mem.h"
+
+extern "C" {
+
+#include <camera.h>
+#include <camera_defs_i.h>
+#include <mm_camera_interface2.h>
+
+#define DEFAULT_STREAM_WIDTH 320
+#define DEFAULT_STREAM_HEIGHT 240
+#define DEFAULT_LIVESHOT_WIDTH 2592
+#define DEFAULT_LIVESHOT_HEIGHT 1944
+
+#define MM_CAMERA_CH_PREVIEW_MASK (0x01 << MM_CAMERA_CH_PREVIEW)
+#define MM_CAMERA_CH_VIDEO_MASK (0x01 << MM_CAMERA_CH_VIDEO)
+#define MM_CAMERA_CH_SNAPSHOT_MASK (0x01 << MM_CAMERA_CH_SNAPSHOT)
+
+} /* extern C*/
+
+
+namespace android {
+
+class QCameraHardwareInterface;
+
+class StreamQueue {
+private:
+ Mutex mQueueLock;
+ Condition mQueueWait;
+ bool mInitialized;
+
+ //Vector<struct msm_frame *> mContainer;
+ Vector<void *> mContainer;
+public:
+ StreamQueue();
+ virtual ~StreamQueue();
+ bool enqueue(void *element);
+ void flush();
+ void* dequeue();
+ void init();
+ void deinit();
+ bool isInitialized();
+bool isEmpty();
+};
+
+
+class QCameraStream { //: public virtual RefBase{
+
+public:
+ bool mInit;
+ bool mActive;
+
+ virtual status_t init();
+ virtual status_t start();
+ virtual void stop();
+ virtual void release();
+
+ status_t setFormat(uint8_t ch_type_mask);
+ status_t setMode(int enable);
+
+ virtual void setHALCameraControl(QCameraHardwareInterface* ctrl);
+
+ //static status_t openChannel(mm_camera_t *, mm_camera_channel_type_t ch_type);
+ virtual status_t initChannel(int cameraId, uint32_t ch_type_mask);
+ virtual status_t deinitChannel(int cameraId, mm_camera_channel_type_t ch_type);
+ virtual void releaseRecordingFrame(const void *opaque)
+ {
+ ;
+ }
+#if 0 // mzhu
+ virtual status_t getBufferInfo(sp<IMemory>& Frame, size_t *alignedSize)
+ {
+ return NO_ERROR;
+ }
+#endif // mzhu
+ virtual void prepareHardware()
+ {
+ ;
+ }
+ virtual sp<IMemoryHeap> getHeap() const{return NULL;}
+ virtual status_t initDisplayBuffers(){return NO_ERROR;}
+ virtual status_t initPreviewOnlyBuffers(){return NO_ERROR;}
+ virtual sp<IMemoryHeap> getRawHeap() const {return NULL;}
+ virtual void *getLastQueuedFrame(void){return NULL;}
+ virtual status_t takePictureZSL(void){return NO_ERROR;}
+ virtual status_t takeLiveSnapshot(){return NO_ERROR;}
+ virtual status_t takePictureLiveshot(mm_camera_ch_data_buf_t* recvd_frame,
+ cam_ctrl_dimension_t *dim,
+ int frame_len){return NO_ERROR;}
+ virtual void setModeLiveSnapshot(bool){;}
+ virtual status_t initSnapshotBuffers(cam_ctrl_dimension_t *dim,
+ int num_of_buf){return NO_ERROR;}
+
+ virtual void setFullSizeLiveshot(bool){};
+ /* Set the ANativeWindow */
+ virtual int setPreviewWindow(preview_stream_ops_t* window) {return NO_ERROR;}
+ virtual void notifyROIEvent(fd_roi_t roi) {;}
+ virtual void notifyWDenoiseEvent(cam_ctrl_status_t status, void * cookie) {;}
+ virtual void resetSnapshotCounters(void ){};
+
+ QCameraStream();
+ QCameraStream(int, camera_mode_t);
+ virtual ~QCameraStream();
+ QCameraHardwareInterface* mHalCamCtrl;
+ mm_camera_ch_crop_t mCrop;
+
+ int mCameraId;
+ camera_mode_t myMode;
+
+ mutable Mutex mStopCallbackLock;
+private:
+ StreamQueue mBusyQueue;
+ StreamQueue mFreeQueue;
+public:
+ friend void liveshot_callback(mm_camera_ch_data_buf_t *frame,void *user_data);
+};
+
+/*
+* Record Class
+*/
+class QCameraStream_record : public QCameraStream {
+public:
+ status_t init();
+ status_t start() ;
+ void stop() ;
+ void release() ;
+
+ static QCameraStream* createInstance(int cameraId, camera_mode_t);
+ static void deleteInstance(QCameraStream *p);
+
+ QCameraStream_record() {};
+ virtual ~QCameraStream_record();
+
+ status_t processRecordFrame(void *data);
+ status_t initEncodeBuffers();
+ status_t getBufferInfo(sp<IMemory>& Frame, size_t *alignedSize);
+ //sp<IMemoryHeap> getHeap() const;
+
+ void releaseRecordingFrame(const void *opaque);
+ void debugShowVideoFPS() const;
+
+ status_t takeLiveSnapshot();
+private:
+ QCameraStream_record(int, camera_mode_t);
+ void releaseEncodeBuffer();
+
+ cam_ctrl_dimension_t dim;
+ bool mDebugFps;
+
+ mm_camera_reg_buf_t mRecordBuf;
+ //int record_frame_len;
+ //static const int maxFrameCnt = 16;
+ //camera_memory_t *mCameraMemoryPtr[maxFrameCnt];
+ //int mNumRecordFrames;
+ //sp<PmemPool> mRecordHeap[maxFrameCnt];
+ struct msm_frame *recordframes;
+ //uint32_t record_offset[VIDEO_BUFFER_COUNT];
+ mm_camera_ch_data_buf_t mRecordedFrames[MM_CAMERA_MAX_NUM_FRAMES];
+ //Mutex mRecordFreeQueueLock;
+ //Vector<mm_camera_ch_data_buf_t> mRecordFreeQueue;
+
+ int mJpegMaxSize;
+ QCameraStream *mStreamSnap;
+
+};
+
+class QCameraStream_preview : public QCameraStream {
+public:
+ status_t init();
+ status_t start() ;
+ void stop() ;
+ void release() ;
+
+ static QCameraStream* createInstance(int, camera_mode_t);
+ static void deleteInstance(QCameraStream *p);
+
+ QCameraStream_preview() {};
+ virtual ~QCameraStream_preview();
+ void *getLastQueuedFrame(void);
+ /*init preview buffers with display case*/
+ status_t initDisplayBuffers();
+ /*init preview buffers without display case*/
+ status_t initPreviewOnlyBuffers();
+
+ status_t processPreviewFrame(mm_camera_ch_data_buf_t *frame);
+
+ /*init preview buffers with display case*/
+ status_t processPreviewFrameWithDisplay(mm_camera_ch_data_buf_t *frame);
+ /*init preview buffers without display case*/
+ status_t processPreviewFrameWithOutDisplay(mm_camera_ch_data_buf_t *frame);
+
+ int setPreviewWindow(preview_stream_ops_t* window);
+ void notifyROIEvent(fd_roi_t roi);
+ friend class QCameraHardwareInterface;
+
+private:
+ QCameraStream_preview(int cameraId, camera_mode_t);
+ /*allocate and free buffers with display case*/
+ status_t getBufferFromSurface();
+ status_t putBufferToSurface();
+
+ /*allocate and free buffers without display case*/
+ status_t getBufferNoDisplay();
+ status_t freeBufferNoDisplay();
+
+ void dumpFrameToFile(struct msm_frame* newFrame);
+ bool mFirstFrameRcvd;
+
+ int8_t my_id;
+ mm_camera_op_mode_type_t op_mode;
+ cam_ctrl_dimension_t dim;
+ struct msm_frame *mLastQueuedFrame;
+ mm_camera_reg_buf_t mDisplayBuf;
+ mm_cameara_stream_buf_t mDisplayStreamBuf;
+ Mutex mDisplayLock;
+ preview_stream_ops_t *mPreviewWindow;
+ static const int kPreviewBufferCount = PREVIEW_BUFFER_COUNT;
+ mm_camera_ch_data_buf_t mNotifyBuffer[16];
+ int8_t mNumFDRcvd;
+ int mVFEOutputs;
+ int mHFRFrameCnt;
+ int mHFRFrameSkip;
+};
+
+/* Snapshot Class - handle data flow*/
+class QCameraStream_Snapshot : public QCameraStream {
+public:
+ status_t init();
+ status_t start();
+ void stop();
+ void release();
+ void prepareHardware();
+ static QCameraStream* createInstance(int cameraId, camera_mode_t);
+ static void deleteInstance(QCameraStream *p);
+
+ status_t takePictureZSL(void);
+ status_t takePictureLiveshot(mm_camera_ch_data_buf_t* recvd_frame,
+ cam_ctrl_dimension_t *dim,
+ int frame_len);
+ status_t receiveRawPicture(mm_camera_ch_data_buf_t* recvd_frame);
+ void receiveCompleteJpegPicture(jpeg_event_t event);
+ void receiveJpegFragment(uint8_t *ptr, uint32_t size);
+ void deInitBuffer(void);
+ sp<IMemoryHeap> getRawHeap() const;
+ int getSnapshotState();
+ /*Temp: to be removed once event handling is enabled in mm-camera*/
+ void runSnapshotThread(void *data);
+ bool isZSLMode();
+ void setFullSizeLiveshot(bool);
+ void notifyWDenoiseEvent(cam_ctrl_status_t status, void * cookie);
+ friend void liveshot_callback(mm_camera_ch_data_buf_t *frame,void *user_data);
+ void resetSnapshotCounters(void );
+
+private:
+ QCameraStream_Snapshot(int, camera_mode_t);
+ virtual ~QCameraStream_Snapshot();
+
+ /* snapshot related private members */
+ status_t initJPEGSnapshot(int num_of_snapshots);
+ status_t initRawSnapshot(int num_of_snapshots);
+ status_t initZSLSnapshot(void);
+ status_t initFullLiveshot(void);
+ status_t cancelPicture();
+ void notifyShutter(common_crop_t *crop,
+ bool play_shutter_sound);
+ status_t initSnapshotBuffers(cam_ctrl_dimension_t *dim,
+ int num_of_buf);
+ status_t initRawSnapshotBuffers(cam_ctrl_dimension_t *dim,
+ int num_of_buf);
+ status_t deinitRawSnapshotBuffers(void);
+ status_t deinitSnapshotBuffers(void);
+ status_t initRawSnapshotChannel(cam_ctrl_dimension_t* dim,
+ int num_snapshots);
+ status_t initSnapshotFormat(cam_ctrl_dimension_t *dim);
+ status_t takePictureRaw(void);
+ status_t takePictureJPEG(void);
+ status_t startStreamZSL(void);
+ void deinitSnapshotChannel(mm_camera_channel_type_t);
+ status_t configSnapshotDimension(cam_ctrl_dimension_t* dim);
+ status_t encodeData(mm_camera_ch_data_buf_t* recvd_frame,
+ common_crop_t *crop_info,
+ int frame_len,
+ bool enqueued);
+ status_t encodeDisplayAndSave(mm_camera_ch_data_buf_t* recvd_frame,
+ bool enqueued);
+ status_t setZSLChannelAttribute(void);
+ void handleError();
+ void setSnapshotState(int state);
+ void setModeLiveSnapshot(bool);
+ bool isLiveSnapshot(void);
+ void stopPolling(void);
+ bool isFullSizeLiveshot(void);
+ status_t doWaveletDenoise(mm_camera_ch_data_buf_t* frame);
+ status_t sendWDenoiseStartMsg(mm_camera_ch_data_buf_t * frame);
+ void lauchNextWDenoiseFromQueue();
+
+ /* Member variables */
+
+ int mSnapshotFormat;
+ int mPictureWidth;
+ int mPictureHeight;
+ cam_format_t mPictureFormat;
+ int mPostviewWidth;
+ int mPostviewHeight;
+ int mThumbnailWidth;
+ int mThumbnailHeight;
+ cam_format_t mThumbnailFormat;
+ int mJpegOffset;
+ int mSnapshotState;
+ int mNumOfSnapshot;
+ int mNumOfRecievedJPEG;
+ bool mModeLiveSnapshot;
+ bool mBurstModeFlag;
+ int mActualPictureWidth;
+ int mActualPictureHeight;
+ bool mJpegDownscaling;
+ sp<AshmemPool> mJpegHeap;
+ /*TBD:Bikas: This is defined in HWI too.*/
+#ifdef USE_ION
+ sp<IonPool> mDisplayHeap;
+ sp<IonPool> mPostviewHeap;
+#else
+ sp<PmemPool> mDisplayHeap;
+ sp<PmemPool> mPostviewHeap;
+#endif
+ mm_camera_ch_data_buf_t *mCurrentFrameEncoded;
+ mm_cameara_stream_buf_t mSnapshotStreamBuf;
+ mm_cameara_stream_buf_t mPostviewStreamBuf;
+ StreamQueue mSnapshotQueue;
+ static const int mMaxSnapshotBufferCount = 16;
+ int mSnapshotBufferNum;
+ int mMainfd[mMaxSnapshotBufferCount];
+ int mThumbfd[mMaxSnapshotBufferCount];
+ int mMainSize;
+ int mThumbSize;
+ camera_memory_t *mCameraMemoryPtrMain[mMaxSnapshotBufferCount];
+ camera_memory_t *mCameraMemoryPtrThumb[mMaxSnapshotBufferCount];
+ int mJpegSessionId;
+ int dump_fd;
+ bool mFullLiveshot;
+ StreamQueue mWDNQueue; // queue to hold frames while one frame is sent out for WDN
+ bool mIsDoingWDN; // flag to indicate if WDN is going on (one frame is sent out for WDN)
+ bool mDropThumbnail;
+ int mJpegQuality;
+}; // QCameraStream_Snapshot
+
+
+}; // namespace android
+
+#endif
diff --git a/camera/QCamera/HAL/core/src/QCameraHAL.cpp b/camera/QCamera/HAL/core/src/QCameraHAL.cpp
new file mode 100755
index 0000000..993405e
--- /dev/null
+++ b/camera/QCamera/HAL/core/src/QCameraHAL.cpp
@@ -0,0 +1,133 @@
+/*
+** Copyright (c) 2011 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 "QCameraHAL"
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+
+/* include QCamera Hardware Interface Header*/
+#include "QCameraHAL.h"
+
+int HAL_numOfCameras = 0;
+camera_info_t HAL_cameraInfo[MSM_MAX_CAMERA_SENSORS];
+mm_camera_t * HAL_camerahandle[MSM_MAX_CAMERA_SENSORS];
+int HAL_currentCameraMode;
+
+namespace android {
+/* HAL function implementation goes here*/
+
+/**
+ * The functions need to be provided by the camera HAL.
+ *
+ * If getNumberOfCameras() returns N, the valid cameraId for getCameraInfo()
+ * and openCameraHardware() is 0 to N-1.
+ */
+extern "C" int HAL_getNumberOfCameras()
+{
+ /* try to query every time we get the call!*/
+ uint8_t num_camera = 0;
+ mm_camera_t * handle_base = 0;
+ LOGV("%s: E", __func__);
+
+ handle_base= mm_camera_query(&num_camera);
+
+ if (!handle_base) {
+ HAL_numOfCameras = 0;
+ }
+ else
+ {
+ camera_info_t* p_camera_info = 0;
+ HAL_numOfCameras=num_camera;
+
+ LOGI("Handle base =0x%p",handle_base);
+ LOGI("getCameraInfo: numOfCameras = %d", HAL_numOfCameras);
+ for(int i = 0; i < HAL_numOfCameras; i++) {
+ LOGI("Handle [%d]=0x%p",i,handle_base+i);
+ HAL_camerahandle[i]=handle_base + i;
+ p_camera_info = &(HAL_camerahandle[i]->camera_info);
+ if (p_camera_info) {
+ LOGI("Camera sensor %d info:", i);
+ LOGI("camera_id: %d", p_camera_info->camera_id);
+ LOGI("modes_supported: %x", p_camera_info->modes_supported);
+ LOGI("position: %d", p_camera_info->position);
+ LOGI("sensor_mount_angle: %d", p_camera_info->sensor_mount_angle);
+ }
+ }
+ }
+
+ LOGV("%s: X", __func__);
+
+ return HAL_numOfCameras;
+}
+
+extern "C" int HAL_isIn3DMode()
+{
+ return HAL_currentCameraMode == CAMERA_MODE_3D;
+}
+
+extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo)
+{
+ mm_camera_t *mm_camer_obj = 0;
+ LOGV("%s: E", __func__);
+
+ if (!HAL_numOfCameras || HAL_numOfCameras < cameraId || !cameraInfo)
+ return;
+ else
+ mm_camer_obj = HAL_camerahandle[cameraId];
+
+ if (!mm_camer_obj)
+ return;
+ else {
+ cameraInfo->facing =
+ (FRONT_CAMERA == mm_camer_obj->camera_info.position)?
+ CAMERA_FACING_FRONT : CAMERA_FACING_BACK;
+
+ cameraInfo->orientation = mm_camer_obj->camera_info.sensor_mount_angle;
+#if 0
+ // TODO: fix me
+ /* We always supprot ZSL in our stack*/
+ cameraInfo->mode = CAMERA_SUPPORT_MODE_ZSL;
+ if (mm_camer_obj->camera_info.modes_supported & CAMERA_MODE_2D) {
+ cameraInfo->mode |= CAMERA_SUPPORT_MODE_2D;
+ }
+ if (mm_camer_obj->camera_info.modes_supported & CAMERA_MODE_3D) {
+ cameraInfo->mode |= CAMERA_SUPPORT_MODE_3D;
+ }
+#endif
+ }
+ LOGV("%s: X", __func__);
+ return;
+}
+
+/* HAL should return NULL if it fails to open camera hardware. */
+extern "C" void * HAL_openCameraHardware(int cameraId, int mode)
+{
+ LOGV("%s: E", __func__);
+ if (!HAL_numOfCameras || HAL_numOfCameras < cameraId ||cameraId < 0) {
+ return NULL;
+ }
+ return QCameraHAL_openCameraHardware(cameraId, mode);
+}
+
+
+}; // namespace android
diff --git a/camera/QCamera/HAL/core/src/QCameraHWI.cpp b/camera/QCamera/HAL/core/src/QCameraHWI.cpp
new file mode 100755
index 0000000..64ef663
--- /dev/null
+++ b/camera/QCamera/HAL/core/src/QCameraHWI.cpp
@@ -0,0 +1,2497 @@
+/*
+** 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.
+** 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_NIDEBUG 0
+
+#define LOG_TAG "QCameraHWI"
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <cutils/properties.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include "QCameraHAL.h"
+#include "QCameraHWI.h"
+
+/* QCameraHardwareInterface class implementation goes here*/
+/* following code implement the contol logic of this class*/
+
+namespace android {
+static void HAL_event_cb(mm_camera_event_t *evt, void *user_data)
+{
+ QCameraHardwareInterface *obj = (QCameraHardwareInterface *)user_data;
+ if (obj) {
+ obj->processEvent(evt);
+ } else {
+ LOGE("%s: NULL user_data", __func__);
+ }
+}
+
+int32_t QCameraHardwareInterface::createRecord()
+{
+ int32_t ret = MM_CAMERA_OK;
+ LOGV("%s : BEGIN",__func__);
+
+ /*
+ * Creating Instance of record stream.
+ */
+ LOGE("Mymode Record = %d",myMode);
+ mStreamRecord = QCameraStream_record::createInstance(mCameraId,
+ myMode);
+
+ if (!mStreamRecord) {
+ LOGE("%s: error - can't creat record stream!", __func__);
+ return BAD_VALUE;
+ }
+
+ /* Store HAL object in record stream Object */
+ mStreamRecord->setHALCameraControl(this);
+
+ /*Init Channel */
+ ret = mStreamRecord->init();
+ if (MM_CAMERA_OK != ret){
+ LOGE("%s: error - can't init Record channel!", __func__);
+ return BAD_VALUE;
+ }
+ LOGV("%s : END",__func__);
+ return ret;
+}
+
+int32_t QCameraHardwareInterface::createSnapshot()
+{
+ int32_t ret = MM_CAMERA_OK;
+ LOGV("%s : BEGIN",__func__);
+
+ /*
+ * Creating Instance of Snapshot stream.
+ */
+ LOGE("Mymode Snap = %d",myMode);
+ mStreamSnap = QCameraStream_Snapshot::createInstance(mCameraId,
+ myMode);
+ if (!mStreamSnap) {
+ LOGE("%s: error - can't creat snapshot stream!", __func__);
+ return BAD_VALUE;
+ }
+
+ /* Store HAL object in Snapshot stream Object */
+ mStreamSnap->setHALCameraControl(this);
+
+ /*Init Channel */
+ ret = mStreamSnap->init();
+ if (MM_CAMERA_OK != ret){
+ LOGE("%s: error - can't init Snapshot channel!", __func__);
+ return BAD_VALUE;
+ }
+ LOGV("%s : END",__func__);
+ return ret;
+}
+
+int32_t QCameraHardwareInterface::createPreview()
+{
+ int32_t ret = MM_CAMERA_OK;
+ LOGV("%s : BEGIN",__func__);
+
+ LOGE("Mymode Preview = %d",myMode);
+ mStreamDisplay = QCameraStream_preview::createInstance(mCameraId,
+ myMode);
+ if (!mStreamDisplay) {
+ LOGE("%s: error - can't creat preview stream!", __func__);
+ return BAD_VALUE;
+ }
+
+ mStreamDisplay->setHALCameraControl(this);
+
+ /*now init all the buffers and send to steam object*/
+ ret = mStreamDisplay->init();
+ if (MM_CAMERA_OK != ret){
+ LOGE("%s: error - can't init Preview channel!", __func__);
+ return BAD_VALUE;
+ }
+ LOGV("%s : END",__func__);
+ return ret;
+}
+
+/* constructor */
+QCameraHardwareInterface::
+QCameraHardwareInterface(int cameraId, int mode)
+ : mCameraId(cameraId),
+ mParameters(),
+ mMsgEnabled(0),
+ mNotifyCb(0),
+ mDataCb(0),
+ mDataCbTimestamp(0),
+ mCallbackCookie(0),
+ //mPreviewHeap(0),
+ mStreamDisplay (NULL), mStreamRecord(NULL), mStreamSnap(NULL),
+ mFps(0),
+ mDebugFps(0),
+ mMaxZoom(0),
+ mCurrentZoom(0),
+ mSupportedPictureSizesCount(15),
+ mDumpFrmCnt(0), mDumpSkipCnt(0),
+ mPictureSizeCount(15),
+ mPreviewSizeCount(13),
+ mVideoSizeCount(0),
+ mAutoFocusRunning(false),
+ mHasAutoFocusSupport(false),
+ mInitialized(false),
+ mIs3DModeOn(0),
+ mSmoothZoomRunning(false),
+ mParamStringInitialized(false),
+ mFaceDetectOn(0),
+ mDisEnabled(0),
+ mZoomSupported(false),
+ mFullLiveshotEnabled(true),
+ mRecordingHint(0),
+ mStatsOn(0), mCurrentHisto(-1), mSendData(false), mStatHeap(NULL),
+ mZslLookBackMode(0),
+ mZslLookBackValue(0),
+ mZslEmptyQueueFlag(FALSE),
+ mPictureSizes(NULL),
+ mVideoSizes(NULL),
+ mCameraState(CAMERA_STATE_UNINITED),
+ mPostPreviewHeap(NULL),
+ mHdrMode(HDR_BRACKETING_OFF),
+ mStreamLiveSnap(NULL),
+ mExifTableNumEntries(0),
+ mDenoiseValue(0),
+ mSnapshotFormat(0),
+ mStartRecording(0),
+ mZslInterval(1),
+ mNoDisplayMode(0),
+ mBrightness(0),
+ mContrast(0),
+ mEffects(0),
+ mBestShotMode(0),
+ mHJR(0),
+ mSkinToneEnhancement(0),
+ mRotation(0),
+ mFocusMode(AF_MODE_MAX),
+ mPreviewFormat(CAMERA_YUV_420_NV21),
+ mRestartPreview(false),
+ mReleasedRecordingFrame(false)
+{
+ LOGI("QCameraHardwareInterface: E");
+ int32_t result = MM_CAMERA_E_GENERAL;
+ char value[PROPERTY_VALUE_MAX];
+
+ pthread_mutex_init(&mAsyncCmdMutex, NULL);
+ pthread_cond_init(&mAsyncCmdWait, NULL);
+
+ property_get("persist.debug.sf.showfps", value, "0");
+ mDebugFps = atoi(value);
+ mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED;
+ mPreviewWindow = NULL;
+ property_get("camera.hal.fps", value, "0");
+ mFps = atoi(value);
+
+ LOGI("Init mPreviewState = %d", mPreviewState);
+
+ property_get("persist.camera.hal.multitouchaf", value, "0");
+ mMultiTouch = atoi(value);
+
+ property_get("persist.camera.full.liveshot", value, "1");
+ mFullLiveshotEnabled = atoi(value);
+
+ property_get("persist.camera.hal.dis", value, "0");
+ mDisEnabled = atoi(value);
+
+ /* Open camera stack! */
+ result=cam_ops_open(mCameraId, MM_CAMERA_OP_MODE_NOTUSED);
+ if (result == MM_CAMERA_OK) {
+ int i;
+ mm_camera_event_type_t evt;
+ for (i = 0; i < MM_CAMERA_EVT_TYPE_MAX; i++) {
+ evt = (mm_camera_event_type_t) i;
+ if (cam_evt_is_event_supported(mCameraId, evt)){
+ cam_evt_register_event_notify(mCameraId,
+ HAL_event_cb, (void *)this, evt);
+ }
+ }
+ }
+ LOGV("Cam open returned %d",result);
+ if(MM_CAMERA_OK != result) {
+ LOGE("startCamera: cam_ops_open failed: id = %d", mCameraId);
+ return;
+ }
+
+ loadTables();
+ /* Setup Picture Size and Preview size tables */
+ setPictureSizeTable();
+ LOGD("%s: Picture table size: %d", __func__, mPictureSizeCount);
+ LOGD("%s: Picture table: ", __func__);
+ for(unsigned int i=0; i < mPictureSizeCount;i++) {
+ LOGD(" %d %d", mPictureSizes[i].width, mPictureSizes[i].height);
+ }
+
+ setPreviewSizeTable();
+ LOGD("%s: Preview table size: %d", __func__, mPreviewSizeCount);
+ LOGD("%s: Preview table: ", __func__);
+ for(unsigned int i=0; i < mPreviewSizeCount;i++) {
+ LOGD(" %d %d", mPreviewSizes[i].width, mPreviewSizes[i].height);
+ }
+
+ setVideoSizeTable();
+ LOGD("%s: Video table size: %d", __func__, mVideoSizeCount);
+ LOGD("%s: Video table: ", __func__);
+ for(unsigned int i=0; i < mVideoSizeCount;i++) {
+ LOGD(" %d %d", mVideoSizes[i].width, mVideoSizes[i].height);
+ }
+
+ /* set my mode - update myMode member variable due to difference in
+ enum definition between upper and lower layer*/
+ setMyMode(mode);
+ initDefaultParameters();
+
+ //Create Stream Objects
+ //Preview
+ result = createPreview();
+ if(result != MM_CAMERA_OK) {
+ LOGE("%s X: Failed to create Preview Object",__func__);
+ return;
+ }
+
+ //Record
+ result = createRecord();
+ if(result != MM_CAMERA_OK) {
+ LOGE("%s X: Failed to create Record Object",__func__);
+ return;
+ }
+
+ //Snapshot
+ result = createSnapshot();
+ if(result != MM_CAMERA_OK) {
+ LOGE("%s X: Failed to create Record Object",__func__);
+ return;
+ }
+ mCameraState = CAMERA_STATE_READY;
+
+ LOGI("QCameraHardwareInterface: X");
+}
+
+QCameraHardwareInterface::~QCameraHardwareInterface()
+{
+ LOGI("~QCameraHardwareInterface: E");
+ int result;
+
+ switch(mPreviewState) {
+ case QCAMERA_HAL_PREVIEW_STOPPED:
+ break;
+ case QCAMERA_HAL_PREVIEW_START:
+ break;
+ case QCAMERA_HAL_PREVIEW_STARTED:
+ stopPreview();
+ break;
+ case QCAMERA_HAL_RECORDING_STARTED:
+ stopRecordingInternal();
+ stopPreview();
+ break;
+ case QCAMERA_HAL_TAKE_PICTURE:
+ cancelPictureInternal();
+ break;
+ default:
+ break;
+ }
+ mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED;
+
+ freePictureTable();
+ freeVideoSizeTable();
+ if(mStatHeap != NULL) {
+ mStatHeap.clear( );
+ mStatHeap = NULL;
+ }
+ /* Join the threads, complete operations and then delete
+ the instances. */
+ cam_ops_close(mCameraId);
+ if(mStreamDisplay){
+ QCameraStream_preview::deleteInstance (mStreamDisplay);
+ mStreamDisplay = NULL;
+ }
+ if(mStreamRecord) {
+ QCameraStream_record::deleteInstance (mStreamRecord);
+ mStreamRecord = NULL;
+ }
+ if(mStreamSnap) {
+ QCameraStream_Snapshot::deleteInstance (mStreamSnap);
+ mStreamSnap = NULL;
+ }
+
+ if (mStreamLiveSnap){
+ QCameraStream_Snapshot::deleteInstance (mStreamLiveSnap);
+ mStreamLiveSnap = NULL;
+ }
+
+ pthread_mutex_destroy(&mAsyncCmdMutex);
+ pthread_cond_destroy(&mAsyncCmdWait);
+
+ LOGI("~QCameraHardwareInterface: X");
+}
+
+bool QCameraHardwareInterface::isCameraReady()
+{
+ LOGE("isCameraReady mCameraState %d", mCameraState);
+ return (mCameraState == CAMERA_STATE_READY);
+}
+
+void QCameraHardwareInterface::release()
+{
+ LOGI("release: E");
+ Mutex::Autolock l(&mLock);
+
+ switch(mPreviewState) {
+ case QCAMERA_HAL_PREVIEW_STOPPED:
+ break;
+ case QCAMERA_HAL_PREVIEW_START:
+ break;
+ case QCAMERA_HAL_PREVIEW_STARTED:
+ stopPreviewInternal();
+ break;
+ case QCAMERA_HAL_RECORDING_STARTED:
+ stopRecordingInternal();
+ stopPreviewInternal();
+ break;
+ case QCAMERA_HAL_TAKE_PICTURE:
+ cancelPictureInternal();
+ break;
+ default:
+ break;
+ }
+#if 0
+ if (isRecordingRunning()) {
+ stopRecordingInternal();
+ LOGI("release: stopRecordingInternal done.");
+ }
+ if (isPreviewRunning()) {
+ stopPreview(); //stopPreviewInternal();
+ LOGI("release: stopPreviewInternal done.");
+ }
+ if (isSnapshotRunning()) {
+ cancelPictureInternal();
+ LOGI("release: cancelPictureInternal done.");
+ }
+ if (mCameraState == CAMERA_STATE_ERROR) {
+ //TBD: If Error occurs then tear down
+ LOGI("release: Tear down.");
+ }
+#endif
+ mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED;
+ LOGI("release: X");
+}
+
+void QCameraHardwareInterface::setCallbacks(
+ camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void *user)
+{
+ LOGE("setCallbacks: E");
+ Mutex::Autolock lock(mLock);
+ mNotifyCb = notify_cb;
+ mDataCb = data_cb;
+ mDataCbTimestamp = data_cb_timestamp;
+ mGetMemory = get_memory;
+ mCallbackCookie = user;
+ LOGI("setCallbacks: X");
+}
+
+void QCameraHardwareInterface::enableMsgType(int32_t msgType)
+{
+ LOGI("enableMsgType: E, msgType =0x%x", msgType);
+ Mutex::Autolock lock(mLock);
+ mMsgEnabled |= msgType;
+ LOGI("enableMsgType: X, msgType =0x%x, mMsgEnabled=0x%x", msgType, mMsgEnabled);
+}
+
+void QCameraHardwareInterface::disableMsgType(int32_t msgType)
+{
+ LOGI("disableMsgType: E");
+ Mutex::Autolock lock(mLock);
+ mMsgEnabled &= ~msgType;
+ LOGI("disableMsgType: X, msgType =0x%x, mMsgEnabled=0x%x", msgType, mMsgEnabled);
+}
+
+int QCameraHardwareInterface::msgTypeEnabled(int32_t msgType)
+{
+ LOGI("msgTypeEnabled: E");
+ Mutex::Autolock lock(mLock);
+ return (mMsgEnabled & msgType);
+ LOGI("msgTypeEnabled: X");
+}
+#if 0
+status_t QCameraHardwareInterface::dump(int fd, const Vector<String16>& args) const
+{
+ LOGI("dump: E");
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ AutoMutex lock(&mLock);
+ write(fd, result.string(), result.size());
+ LOGI("dump: E");
+ return NO_ERROR;
+}
+#endif
+
+int QCameraHardwareInterface::dump(int fd)
+{
+ LOGE("%s: not supported yet", __func__);
+ return -1;
+}
+
+status_t QCameraHardwareInterface::sendCommand(int32_t command, int32_t arg1,
+ int32_t arg2)
+{
+ LOGI("sendCommand: E");
+ status_t rc = NO_ERROR;
+ Mutex::Autolock l(&mLock);
+
+ switch (command) {
+ case CAMERA_CMD_HISTOGRAM_ON:
+ LOGE("histogram set to on");
+ rc = setHistogram(1);
+ break;
+ case CAMERA_CMD_HISTOGRAM_OFF:
+ LOGE("histogram set to off");
+ rc = setHistogram(0);
+ break;
+ case CAMERA_CMD_HISTOGRAM_SEND_DATA:
+ LOGE("histogram send data");
+ mSendData = true;
+ rc = NO_ERROR;
+ break;
+ case CAMERA_CMD_START_FACE_DETECTION:
+ if(supportsFaceDetection() == false){
+ LOGE("Face detection support is not available");
+ return NO_ERROR;
+ }
+ setFaceDetection("on");
+ return runFaceDetection();
+ case CAMERA_CMD_STOP_FACE_DETECTION:
+ if(supportsFaceDetection() == false){
+ LOGE("Face detection support is not available");
+ return NO_ERROR;
+ }
+ setFaceDetection("off");
+ return runFaceDetection();
+#if 0
+ case CAMERA_CMD_SEND_META_DATA:
+ mMetaDataWaitLock.lock();
+ if(mFaceDetectOn == true) {
+ mSendMetaData = true;
+ }
+ mMetaDataWaitLock.unlock();
+ return NO_ERROR;
+#endif
+#if 0 /* To Do: will enable it later */
+ case CAMERA_CMD_START_SMOOTH_ZOOM :
+ LOGV("HAL sendcmd start smooth zoom %d %d", arg1 , arg2);
+ /*TO DO: get MaxZoom from parameter*/
+ int MaxZoom = 100;
+
+ switch(mCameraState ) {
+ case CAMERA_STATE_PREVIEW:
+ case CAMERA_STATE_RECORD_CMD_SENT:
+ case CAMERA_STATE_RECORD:
+ mTargetSmoothZoom = arg1;
+ mCurrentZoom = mParameters.getInt("zoom");
+ mSmoothZoomStep = (mCurrentZoom > mTargetSmoothZoom)? -1: 1;
+ if(mCurrentZoom == mTargetSmoothZoom) {
+ LOGV("Smoothzoom target zoom value is same as "
+ "current zoom value, return...");
+ mNotifyCallback(CAMERA_MSG_ZOOM,
+ mCurrentZoom, 1, mCallbackCookie);
+ } else if(mCurrentZoom < 0 || mCurrentZoom > MaxZoom ||
+ mTargetSmoothZoom < 0 || mTargetSmoothZoom > MaxZoom) {
+ LOGE(" ERROR : beyond supported zoom values, break..");
+ mNotifyCallback(CAMERA_MSG_ZOOM,
+ mCurrentZoom, 0, mCallbackCookie);
+ } else {
+ mSmoothZoomRunning = true;
+ mCurrentZoom += mSmoothZoomStep;
+ if ((mSmoothZoomStep < 0 && mCurrentZoom < mTargetSmoothZoom)||
+ (mSmoothZoomStep > 0 && mCurrentZoom > mTargetSmoothZoom )) {
+ mCurrentZoom = mTargetSmoothZoom;
+ }
+ mParameters.set("zoom", mCurrentZoom);
+ setZoom(mParameters);
+ }
+ break;
+ default:
+ LOGV(" No preview, no smoothzoom ");
+ break;
+ }
+ rc = NO_ERROR;
+ break;
+
+ case CAMERA_CMD_STOP_SMOOTH_ZOOM:
+ if(mSmoothZoomRunning) {
+ mSmoothZoomRunning = false;
+ /*To Do: send cmd to stop zooming*/
+ }
+ LOGV("HAL sendcmd stop smooth zoom");
+ rc = NO_ERROR;
+ break;
+#endif
+ default:
+ break;
+ }
+ LOGI("sendCommand: X");
+ return rc;
+}
+
+void QCameraHardwareInterface::setMyMode(int mode)
+{
+ LOGI("setMyMode: E");
+ if (mode & CAMERA_SUPPORT_MODE_3D) {
+ myMode = CAMERA_MODE_3D;
+ }else {
+ /* default mode is 2D */
+ myMode = CAMERA_MODE_2D;
+ }
+
+ if (mode & CAMERA_SUPPORT_MODE_ZSL) {
+ myMode = (camera_mode_t)(myMode |CAMERA_ZSL_MODE);
+ }else {
+ myMode = (camera_mode_t) (myMode | CAMERA_NONZSL_MODE);
+ }
+ LOGI("setMyMode: Set mode to %d (passed mode: %d)", myMode, mode);
+ LOGI("setMyMode: X");
+}
+/* static factory function */
+QCameraHardwareInterface *QCameraHardwareInterface::createInstance(int cameraId, int mode)
+{
+ LOGI("createInstance: E");
+ QCameraHardwareInterface *cam = new QCameraHardwareInterface(cameraId, mode);
+ if (cam ) {
+ if (cam->mCameraState != CAMERA_STATE_READY) {
+ LOGE("createInstance: Failed");
+ delete cam;
+ cam = NULL;
+ }
+ }
+
+ if (cam) {
+ //sp<CameraHardwareInterface> hardware(cam);
+ LOGI("createInstance: X");
+ return cam;
+ } else {
+ return NULL;
+ }
+}
+/* external plug in function */
+extern "C" void *
+QCameraHAL_openCameraHardware(int cameraId, int mode)
+{
+ LOGI("QCameraHAL_openCameraHardware: E");
+ return (void *) QCameraHardwareInterface::createInstance(cameraId, mode);
+}
+
+#if 0
+bool QCameraHardwareInterface::useOverlay(void)
+{
+ LOGI("useOverlay: E");
+ mUseOverlay = TRUE;
+ LOGI("useOverlay: X");
+ return mUseOverlay;
+}
+#endif
+
+bool QCameraHardwareInterface::isPreviewRunning() {
+ LOGI("isPreviewRunning: E");
+ bool ret = false;
+ LOGI("isPreviewRunning: camera state:%d", mCameraState);
+
+ if((mCameraState == CAMERA_STATE_PREVIEW) ||
+ (mCameraState == CAMERA_STATE_PREVIEW_START_CMD_SENT) ||
+ (mCameraState == CAMERA_STATE_RECORD) ||
+ (mCameraState == CAMERA_STATE_RECORD_START_CMD_SENT) ||
+ (mCameraState == CAMERA_STATE_ZSL) ||
+ (mCameraState == CAMERA_STATE_ZSL_START_CMD_SENT)){
+ return true;
+ }
+ LOGI("isPreviewRunning: X");
+ return ret;
+}
+
+bool QCameraHardwareInterface::isRecordingRunning() {
+ LOGE("isRecordingRunning: E");
+ bool ret = false;
+ if(QCAMERA_HAL_RECORDING_STARTED == mPreviewState)
+ ret = true;
+ //if((mCameraState == CAMERA_STATE_RECORD) ||
+ // (mCameraState == CAMERA_STATE_RECORD_START_CMD_SENT)) {
+ // return true;
+ //}
+ LOGE("isRecordingRunning: X");
+ return ret;
+}
+
+bool QCameraHardwareInterface::isSnapshotRunning() {
+ LOGE("isSnapshotRunning: E");
+ bool ret = false;
+ //if((mCameraState == CAMERA_STATE_SNAP_CMD_ACKED) ||
+ // (mCameraState == CAMERA_STATE_SNAP_START_CMD_SENT)) {
+ // return true;
+ //}
+ switch(mPreviewState) {
+ case QCAMERA_HAL_PREVIEW_STOPPED:
+ case QCAMERA_HAL_PREVIEW_START:
+ case QCAMERA_HAL_PREVIEW_STARTED:
+ case QCAMERA_HAL_RECORDING_STARTED:
+ default:
+ break;
+ case QCAMERA_HAL_TAKE_PICTURE:
+ ret = true;
+ break;
+ }
+ LOGI("isSnapshotRunning: X");
+ return ret;
+}
+
+bool QCameraHardwareInterface::isZSLMode() {
+ return (myMode & CAMERA_ZSL_MODE);
+}
+
+int QCameraHardwareInterface::getHDRMode() {
+ return mHdrMode;
+}
+
+void QCameraHardwareInterface::debugShowPreviewFPS() const
+{
+ 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("Preview Frames Per Second: %.4f", mFps);
+ mLastFpsTime = now;
+ mLastFrameCount = mFrameCount;
+ }
+}
+
+void QCameraHardwareInterface::
+processPreviewChannelEvent(mm_camera_ch_event_type_t channelEvent, app_notify_cb_t *app_cb) {
+ LOGI("processPreviewChannelEvent: E");
+ switch(channelEvent) {
+ case MM_CAMERA_CH_EVT_STREAMING_ON:
+ mCameraState =
+ isZSLMode() ? CAMERA_STATE_ZSL : CAMERA_STATE_PREVIEW;
+ break;
+ case MM_CAMERA_CH_EVT_STREAMING_OFF:
+ mCameraState = CAMERA_STATE_READY;
+ break;
+ case MM_CAMERA_CH_EVT_DATA_DELIVERY_DONE:
+ break;
+ default:
+ break;
+ }
+ LOGI("processPreviewChannelEvent: X");
+ return;
+}
+
+void QCameraHardwareInterface::processRecordChannelEvent(
+ mm_camera_ch_event_type_t channelEvent, app_notify_cb_t *app_cb) {
+ LOGI("processRecordChannelEvent: E");
+ switch(channelEvent) {
+ case MM_CAMERA_CH_EVT_STREAMING_ON:
+ mCameraState = CAMERA_STATE_RECORD;
+ break;
+ case MM_CAMERA_CH_EVT_STREAMING_OFF:
+ mCameraState = CAMERA_STATE_PREVIEW;
+ break;
+ case MM_CAMERA_CH_EVT_DATA_DELIVERY_DONE:
+ break;
+ default:
+ break;
+ }
+ LOGI("processRecordChannelEvent: X");
+ return;
+}
+
+void QCameraHardwareInterface::
+processSnapshotChannelEvent(mm_camera_ch_event_type_t channelEvent, app_notify_cb_t *app_cb) {
+ LOGI("processSnapshotChannelEvent: E evt=%d state=%d", channelEvent,
+ mCameraState);
+ switch(channelEvent) {
+ case MM_CAMERA_CH_EVT_STREAMING_ON:
+ if (!mFullLiveshotEnabled) {
+ mCameraState =
+ isZSLMode() ? CAMERA_STATE_ZSL : CAMERA_STATE_SNAP_CMD_ACKED;
+ }
+ break;
+ case MM_CAMERA_CH_EVT_STREAMING_OFF:
+ if (!mFullLiveshotEnabled) {
+ mCameraState = CAMERA_STATE_READY;
+ }
+ break;
+ case MM_CAMERA_CH_EVT_DATA_DELIVERY_DONE:
+ break;
+ case MM_CAMERA_CH_EVT_DATA_REQUEST_MORE:
+ if (isZSLMode()) {
+ /* ZSL Mode: In ZSL Burst Mode, users may request for number of
+ snapshots larger than internal size of ZSL queue. So we'll need
+ process the remaining frames as they become available.
+ In such case, we'll get this event */
+ if(NULL != mStreamSnap)
+ mStreamSnap->takePictureZSL();
+ }
+ break;
+ default:
+ break;
+ }
+ LOGI("processSnapshotChannelEvent: X");
+ return;
+}
+
+void QCameraHardwareInterface::processChannelEvent(
+ mm_camera_ch_event_t *event, app_notify_cb_t *app_cb)
+{
+ LOGI("processChannelEvent: E");
+ Mutex::Autolock lock(mLock);
+ switch(event->ch) {
+ case MM_CAMERA_CH_PREVIEW:
+ processPreviewChannelEvent(event->evt, app_cb);
+ break;
+ case MM_CAMERA_CH_VIDEO:
+ processRecordChannelEvent(event->evt, app_cb);
+ break;
+ case MM_CAMERA_CH_SNAPSHOT:
+ processSnapshotChannelEvent(event->evt, app_cb);
+ break;
+ default:
+ break;
+ }
+ LOGI("processChannelEvent: X");
+ return;
+}
+
+void QCameraHardwareInterface::processCtrlEvent(mm_camera_ctrl_event_t *event, app_notify_cb_t *app_cb)
+{
+ LOGI("processCtrlEvent: %d, E",event->evt);
+ Mutex::Autolock lock(mLock);
+ switch(event->evt)
+ {
+ case MM_CAMERA_CTRL_EVT_ZOOM_DONE:
+ zoomEvent(&event->status, app_cb);
+ break;
+ case MM_CAMERA_CTRL_EVT_AUTO_FOCUS_DONE:
+ autoFocusEvent(&event->status, app_cb);
+ break;
+ case MM_CAMERA_CTRL_EVT_PREP_SNAPSHOT:
+ break;
+ case MM_CAMERA_CTRL_EVT_WDN_DONE:
+ wdenoiseEvent(event->status, (void *)(event->cookie));
+ break;
+ case MM_CAMERA_CTRL_EVT_ERROR:
+ app_cb->notifyCb = mNotifyCb;
+ app_cb->argm_notify.msg_type = CAMERA_MSG_ERROR;
+ app_cb->argm_notify.ext1 = CAMERA_ERROR_UNKNOWN;
+ app_cb->argm_notify.cookie = mCallbackCookie;
+ break;
+ default:
+ break;
+ }
+ LOGI("processCtrlEvent: X");
+ return;
+}
+
+void QCameraHardwareInterface::processStatsEvent(
+ mm_camera_stats_event_t *event, app_notify_cb_t *app_cb)
+{
+ LOGI("processStatsEvent: E");
+ if (!isPreviewRunning( )) {
+ LOGE("preview is not running");
+ return;
+ }
+
+ switch (event->event_id) {
+ case MM_CAMERA_STATS_EVT_HISTO:
+ {
+ LOGE("HAL process Histo: mMsgEnabled=0x%x, mStatsOn=%d, mSendData=%d, mDataCb=%p ",
+ (mMsgEnabled & CAMERA_MSG_STATS_DATA), mStatsOn, mSendData, mDataCb);
+ int msgEnabled = mMsgEnabled;
+ /*get stats buffer based on index*/
+ camera_preview_histogram_info* hist_info =
+ (camera_preview_histogram_info*) mHistServer.camera_memory[event->e.stats_histo.index]->data;
+
+ if(mStatsOn == QCAMERA_PARM_ENABLE && mSendData &&
+ mDataCb && (msgEnabled & CAMERA_MSG_STATS_DATA) ) {
+ uint32_t *dest;
+ mSendData = false;
+ mCurrentHisto = (mCurrentHisto + 1) % 3;
+ // The first element of the array will contain the maximum hist value provided by driver.
+ *(uint32_t *)((unsigned int)(mStatsMapped[mCurrentHisto]->data)) = hist_info->max_value;
+ memcpy((uint32_t *)((unsigned int)mStatsMapped[mCurrentHisto]->data + sizeof(int32_t)),
+ (uint32_t *)hist_info->buffer,(sizeof(int32_t) * 256));
+
+ app_cb->dataCb = mDataCb;
+ app_cb->argm_data_cb.msg_type = CAMERA_MSG_STATS_DATA;
+ app_cb->argm_data_cb.data = mStatsMapped[mCurrentHisto];
+ app_cb->argm_data_cb.index = 0;
+ app_cb->argm_data_cb.metadata = NULL;
+ app_cb->argm_data_cb.cookie = mCallbackCookie;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ LOGV("receiveCameraStats X");
+}
+
+void QCameraHardwareInterface::processInfoEvent(
+ mm_camera_info_event_t *event, app_notify_cb_t *app_cb) {
+ LOGI("processInfoEvent: %d, E",event->event_id);
+ //Mutex::Autolock lock(eventLock);
+ switch(event->event_id)
+ {
+ case MM_CAMERA_INFO_EVT_ROI:
+ roiEvent(event->e.roi, app_cb);
+ break;
+ default:
+ break;
+ }
+ LOGI("processInfoEvent: X");
+ return;
+}
+
+void QCameraHardwareInterface::processEvent(mm_camera_event_t *event)
+{
+ app_notify_cb_t app_cb;
+ LOGE("processEvent: type :%d E",event->event_type);
+ if(mPreviewState == QCAMERA_HAL_PREVIEW_STOPPED){
+ LOGE("Stop recording issued. Return from process Event");
+ return;
+ }
+ memset(&app_cb, 0, sizeof(app_notify_cb_t));
+ switch(event->event_type)
+ {
+ case MM_CAMERA_EVT_TYPE_CH:
+ processChannelEvent(&event->e.ch, &app_cb);
+ break;
+ case MM_CAMERA_EVT_TYPE_CTRL:
+ processCtrlEvent(&event->e.ctrl, &app_cb);
+ break;
+ case MM_CAMERA_EVT_TYPE_STATS:
+ processStatsEvent(&event->e.stats, &app_cb);
+ break;
+ case MM_CAMERA_EVT_TYPE_INFO:
+ processInfoEvent(&event->e.info, &app_cb);
+ break;
+ default:
+ break;
+ }
+ LOGE(" App_cb Notify %p, datacb=%p", app_cb.notifyCb, app_cb.dataCb);
+ if (app_cb.notifyCb) {
+ app_cb.notifyCb(app_cb.argm_notify.msg_type,
+ app_cb.argm_notify.ext1, app_cb.argm_notify.ext2,
+ app_cb.argm_notify.cookie);
+ }
+ if (app_cb.dataCb) {
+ app_cb.dataCb(app_cb.argm_data_cb.msg_type,
+ app_cb.argm_data_cb.data, app_cb.argm_data_cb.index,
+ app_cb.argm_data_cb.metadata, app_cb.argm_data_cb.cookie);
+ }
+ LOGI("processEvent: X");
+ return;
+}
+
+bool QCameraHardwareInterface::preview_parm_config (cam_ctrl_dimension_t* dim,
+ CameraParameters& parm)
+{
+ LOGI("preview_parm_config: E");
+ bool matching = true;
+ int display_width = 0; /* width of display */
+ int display_height = 0; /* height of display */
+ uint16_t video_width = 0; /* width of the video */
+ uint16_t video_height = 0; /* height of the video */
+
+ /* First check if the preview resolution is the same, if not, change it*/
+ parm.getPreviewSize(&display_width, &display_height);
+ if (display_width && display_height) {
+ matching = (display_width == dim->display_width) &&
+ (display_height == dim->display_height);
+
+ if (!matching) {
+ dim->display_width = display_width;
+ dim->display_height = display_height;
+ }
+ }
+ else
+ matching = false;
+
+ cam_format_t value = getPreviewFormat();
+
+ if(value != NOT_FOUND && value != dim->prev_format ) {
+ //Setting to Parameter requested by the Upper layer
+ dim->prev_format = value;
+ }else{
+ //Setting to default Format.
+ dim->prev_format = CAMERA_YUV_420_NV21;
+ }
+ mPreviewFormat = dim->prev_format;
+
+ dim->prev_padding_format = getPreviewPadding( );
+
+ dim->enc_format = CAMERA_YUV_420_NV12;
+ dim->orig_video_width = mDimension.orig_video_width;
+ dim->orig_video_height = mDimension.orig_video_height;
+ dim->video_width = mDimension.video_width;
+ dim->video_height = mDimension.video_height;
+ dim->video_chroma_width = mDimension.video_width;
+ dim->video_chroma_height = mDimension.video_height;
+ /* Reset the Main image and thumbnail formats here,
+ * since they might have been changed when video size
+ * livesnapshot was taken. */
+ if (mSnapshotFormat == 1)
+ dim->main_img_format = CAMERA_YUV_422_NV61;
+ else
+ dim->main_img_format = CAMERA_YUV_420_NV21;
+ dim->thumb_format = CAMERA_YUV_420_NV21;
+ LOGI("preview_parm_config: X");
+ return matching;
+}
+
+status_t QCameraHardwareInterface::startPreview()
+{
+ status_t retVal = NO_ERROR;
+
+ LOGE("%s: mPreviewState =%d", __func__, mPreviewState);
+ Mutex::Autolock lock(mLock);
+ switch(mPreviewState) {
+ case QCAMERA_HAL_PREVIEW_STOPPED:
+ case QCAMERA_HAL_TAKE_PICTURE:
+ mPreviewState = QCAMERA_HAL_PREVIEW_START;
+ LOGE("%s: HAL::startPreview begin", __func__);
+
+ if(QCAMERA_HAL_PREVIEW_START == mPreviewState &&
+ (mPreviewWindow || isNoDisplayMode())) {
+ LOGE("%s: start preview now", __func__);
+ retVal = startPreview2();
+ if(retVal == NO_ERROR)
+ mPreviewState = QCAMERA_HAL_PREVIEW_STARTED;
+ } else {
+ LOGE("%s: received startPreview, but preview window = null", __func__);
+ }
+ break;
+ case QCAMERA_HAL_PREVIEW_START:
+ case QCAMERA_HAL_PREVIEW_STARTED:
+ break;
+ case QCAMERA_HAL_RECORDING_STARTED:
+ LOGE("%s: cannot start preview in recording state", __func__);
+ break;
+ default:
+ LOGE("%s: unknow state %d received", __func__, mPreviewState);
+ retVal = UNKNOWN_ERROR;
+ break;
+ }
+ return retVal;
+}
+
+status_t QCameraHardwareInterface::startPreview2()
+{
+ LOGI("startPreview2: E");
+ status_t ret = NO_ERROR;
+
+ cam_ctrl_dimension_t dim;
+ mm_camera_dimension_t maxDim;
+ bool initPreview = false;
+
+ if (mPreviewState == QCAMERA_HAL_PREVIEW_STARTED) { //isPreviewRunning()){
+ LOGE("%s:Preview already started mCameraState = %d!", __func__, mCameraState);
+ LOGE("%s: X", __func__);
+ return NO_ERROR;
+ }
+
+ /* get existing preview information, by qury mm_camera*/
+ 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 preview dimension!", __func__);
+ LOGE("%s: X", __func__);
+ return BAD_VALUE;
+ }
+
+ /* config the parmeters and see if we need to re-init the stream*/
+ initPreview = preview_parm_config (&dim, mParameters);
+
+ if (mRecordingHint && mFullLiveshotEnabled) {
+#if 0
+ /* Camcorder mode and Full resolution liveshot enabled
+ * TBD lookup table for correct aspect ratio matching size */
+ memset(&maxDim, 0, sizeof(mm_camera_dimension_t));
+ getMaxPictureDimension(&maxDim);
+ if (!maxDim.width || !maxDim.height) {
+ maxDim.width = DEFAULT_LIVESHOT_WIDTH;
+ maxDim.height = DEFAULT_LIVESHOT_HEIGHT;
+ }
+ /* TODO Remove this hack after adding code to get live shot dimension */
+ if (!mCameraId) {
+ maxDim.width = DEFAULT_LIVESHOT_WIDTH;
+ maxDim.height = DEFAULT_LIVESHOT_HEIGHT;
+ }
+ dim.picture_width = maxDim.width;
+ dim.picture_height = maxDim.height;
+ mParameters.setPictureSize(dim.picture_width, dim.picture_height);
+ LOGI("%s Setting Liveshot dimension as %d x %d", __func__,
+ maxDim.width, maxDim.height);
+#endif
+ int mPictureWidth, mPictureHeight;
+ bool matching;
+ /* First check if the picture resolution is the same, if not, change it*/
+ getPictureSize(&mPictureWidth, &mPictureHeight);
+
+ matching = (mPictureWidth == dim.picture_width) &&
+ (mPictureHeight == dim.picture_height);
+
+ if (!matching) {
+ dim.picture_width = mPictureWidth;
+ dim.picture_height = mPictureHeight;
+ dim.ui_thumbnail_height = dim.display_height;
+ dim.ui_thumbnail_width = dim.display_width;
+ }
+ LOGE("%s: Fullsize Liveshaot Picture size to set: %d x %d", __func__,
+ dim.picture_width, dim.picture_height);
+ mParameters.setPictureSize(dim.picture_width, dim.picture_height);
+ }
+
+ ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim);
+ if (MM_CAMERA_OK != ret) {
+ LOGE("%s X: error - can't config preview parms!", __func__);
+ return BAD_VALUE;
+ }
+
+ mStreamDisplay->setMode(myMode & CAMERA_ZSL_MODE);
+ mStreamSnap->setMode(myMode & CAMERA_ZSL_MODE);
+ mStreamRecord->setMode(myMode & CAMERA_ZSL_MODE);
+ LOGE("%s: myMode = %d", __func__, myMode);
+
+ LOGE("%s: setPreviewWindow", __func__);
+ mStreamDisplay->setPreviewWindow(mPreviewWindow);
+
+ if(isZSLMode()) {
+ /* Start preview streaming */
+ ret = mStreamDisplay->start();
+ if (MM_CAMERA_OK != ret){
+ LOGE("%s: X -error - can't start nonZSL stream!", __func__);
+ return BAD_VALUE;
+ }
+
+ /* Start ZSL stream */
+ ret = mStreamSnap->start();
+ if (MM_CAMERA_OK != ret){
+ LOGE("%s: error - can't start Snapshot stream!", __func__);
+ mStreamDisplay->stop();
+ return BAD_VALUE;
+ }
+ }else{
+ ret = mStreamDisplay->start();
+ }
+
+ /*call QCameraStream_noneZSL::start() */
+ if (MM_CAMERA_OK != ret){
+ LOGE("%s: X error - can't start stream!", __func__);
+ return BAD_VALUE;
+ }
+ if(MM_CAMERA_OK == ret)
+ mCameraState = CAMERA_STATE_PREVIEW_START_CMD_SENT;
+ else
+ mCameraState = CAMERA_STATE_ERROR;
+
+ if(mPostPreviewHeap != NULL) {
+ mPostPreviewHeap.clear();
+ mPostPreviewHeap = NULL;
+ }
+
+ LOGI("startPreview: X");
+ return ret;
+}
+
+void QCameraHardwareInterface::stopPreview()
+{
+ LOGI("%s: stopPreview: E", __func__);
+ Mutex::Autolock lock(mLock);
+ mm_camera_util_profile("HAL: stopPreview(): E");
+ mFaceDetectOn = false;
+
+ // reset recording hint to the value passed from Apps
+ const char * str = mParameters.get(CameraParameters::KEY_RECORDING_HINT);
+ if((str != NULL) && !strcmp(str, "true")){
+ mRecordingHint = TRUE;
+ } else {
+ mRecordingHint = FALSE;
+ }
+
+ switch(mPreviewState) {
+ case QCAMERA_HAL_PREVIEW_START:
+ //mPreviewWindow = NULL;
+ mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED;
+ break;
+ case QCAMERA_HAL_PREVIEW_STARTED:
+ stopPreviewInternal();
+ mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED;
+ break;
+ case QCAMERA_HAL_RECORDING_STARTED:
+ stopRecordingInternal();
+ stopPreviewInternal();
+ mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED;
+ break;
+ case QCAMERA_HAL_TAKE_PICTURE:
+ case QCAMERA_HAL_PREVIEW_STOPPED:
+ default:
+ break;
+ }
+ LOGI("stopPreview: X, mPreviewState = %d", mPreviewState);
+}
+
+#if 0 //mzhu
+void QCameraHardwareInterface::stopPreviewZSL()
+{
+ LOGI("stopPreviewZSL: E");
+
+ if(!mStreamDisplay || !mStreamSnap) {
+ LOGE("mStreamDisplay/mStreamSnap is null");
+ return;
+ }
+ LOGI("stopPreview: X, mPreviewState = %d", mPreviewState);
+}
+#endif
+void QCameraHardwareInterface::stopPreviewInternal()
+{
+ LOGI("stopPreviewInternal: E");
+ status_t ret = NO_ERROR;
+
+ if(!mStreamDisplay) {
+ LOGE("mStreamDisplay is null");
+ return;
+ }
+
+ if(isZSLMode()) {
+ /* take care snapshot object for ZSL mode */
+ mStreamSnap->stop();
+ }
+ mStreamDisplay->stop();
+
+ mCameraState = CAMERA_STATE_PREVIEW_STOP_CMD_SENT;
+ LOGI("stopPreviewInternal: X");
+}
+
+int QCameraHardwareInterface::previewEnabled()
+{
+ LOGI("previewEnabled: E");
+ Mutex::Autolock lock(mLock);
+ LOGE("%s: mCameraState = %d", __func__, mCameraState);
+ switch(mPreviewState) {
+ case QCAMERA_HAL_PREVIEW_STOPPED:
+ case QCAMERA_HAL_TAKE_PICTURE:
+ default:
+ return false;
+ break;
+ case QCAMERA_HAL_PREVIEW_START:
+ case QCAMERA_HAL_PREVIEW_STARTED:
+ case QCAMERA_HAL_RECORDING_STARTED:
+ return true;
+ break;
+ }
+ return false;
+}
+
+status_t QCameraHardwareInterface::startRecording()
+{
+ LOGI("startRecording: E");
+ status_t ret = NO_ERROR;
+ Mutex::Autolock lock(mLock);
+
+ switch(mPreviewState) {
+ case QCAMERA_HAL_PREVIEW_STOPPED:
+ LOGE("%s: preview has not been started", __func__);
+ ret = UNKNOWN_ERROR;
+ break;
+ case QCAMERA_HAL_PREVIEW_START:
+ LOGE("%s: no preview native window", __func__);
+ ret = UNKNOWN_ERROR;
+ break;
+ case QCAMERA_HAL_PREVIEW_STARTED:
+ if (mRecordingHint == FALSE) {
+ LOGE("%s: start recording when hint is false, stop preview first", __func__);
+ stopPreviewInternal();
+ mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED;
+
+ // Set recording hint to TRUE
+ mRecordingHint = TRUE;
+ setRecordingHintValue(mRecordingHint);
+
+ // start preview again
+ mPreviewState = QCAMERA_HAL_PREVIEW_START;
+ if (startPreview2() == NO_ERROR)
+ mPreviewState = QCAMERA_HAL_PREVIEW_STARTED;
+ }
+ ret = mStreamRecord->start();
+ if (MM_CAMERA_OK != ret){
+ LOGE("%s: error - mStreamRecord->start!", __func__);
+ ret = BAD_VALUE;
+ break;
+ }
+ if(MM_CAMERA_OK == ret)
+ mCameraState = CAMERA_STATE_RECORD_START_CMD_SENT;
+ else
+ mCameraState = CAMERA_STATE_ERROR;
+ mPreviewState = QCAMERA_HAL_RECORDING_STARTED;
+ break;
+ case QCAMERA_HAL_RECORDING_STARTED:
+ LOGE("%s: ", __func__);
+ break;
+ case QCAMERA_HAL_TAKE_PICTURE:
+ default:
+ ret = BAD_VALUE;
+ break;
+ }
+ LOGI("startRecording: X");
+ return ret;
+}
+
+void QCameraHardwareInterface::stopRecording()
+{
+ LOGI("stopRecording: E");
+ Mutex::Autolock lock(mLock);
+ switch(mPreviewState) {
+ case QCAMERA_HAL_PREVIEW_STOPPED:
+ case QCAMERA_HAL_PREVIEW_START:
+ case QCAMERA_HAL_PREVIEW_STARTED:
+ break;
+ case QCAMERA_HAL_RECORDING_STARTED:
+ stopRecordingInternal();
+ mPreviewState = QCAMERA_HAL_PREVIEW_STARTED;
+ break;
+ case QCAMERA_HAL_TAKE_PICTURE:
+ default:
+ break;
+ }
+ LOGI("stopRecording: X");
+
+}
+void QCameraHardwareInterface::stopRecordingInternal()
+{
+ LOGI("stopRecordingInternal: E");
+ status_t ret = NO_ERROR;
+
+ if(!mStreamRecord) {
+ LOGE("mStreamRecord is null");
+ return;
+ }
+
+ /*
+ * call QCameraStream_record::stop()
+ * Unregister Callback, action stop
+ */
+ mStreamRecord->stop();
+ mCameraState = CAMERA_STATE_PREVIEW; //TODO : Apurva : Hacked for 2nd time Recording
+ mPreviewState = QCAMERA_HAL_PREVIEW_STARTED;
+ LOGI("stopRecordingInternal: X");
+ return;
+}
+
+int QCameraHardwareInterface::recordingEnabled()
+{
+ int ret = 0;
+ Mutex::Autolock lock(mLock);
+ LOGV("%s: E", __func__);
+ switch(mPreviewState) {
+ case QCAMERA_HAL_PREVIEW_STOPPED:
+ case QCAMERA_HAL_PREVIEW_START:
+ case QCAMERA_HAL_PREVIEW_STARTED:
+ break;
+ case QCAMERA_HAL_RECORDING_STARTED:
+ ret = 1;
+ break;
+ case QCAMERA_HAL_TAKE_PICTURE:
+ default:
+ break;
+ }
+ LOGV("%s: X, ret = %d", __func__, ret);
+ return ret; //isRecordingRunning();
+}
+
+/**
+* Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME.
+*/
+void QCameraHardwareInterface::releaseRecordingFrame(const void *opaque)
+{
+ LOGV("%s : BEGIN",__func__);
+ if(mStreamRecord == NULL) {
+ LOGE("Record stream Not Initialized");
+ return;
+ }
+ mStreamRecord->releaseRecordingFrame(opaque);
+ LOGV("%s : END",__func__);
+ return;
+}
+
+status_t QCameraHardwareInterface::autoFocusEvent(cam_ctrl_status_t *status, app_notify_cb_t *app_cb)
+{
+ LOGE("autoFocusEvent: E");
+ int ret = NO_ERROR;
+/************************************************************
+ BEGIN MUTEX CODE
+*************************************************************/
+
+ LOGE("%s:%d: Trying to acquire AF bit lock",__func__,__LINE__);
+ mAutofocusLock.lock();
+ LOGE("%s:%d: Acquired AF bit lock",__func__,__LINE__);
+
+ if(mAutoFocusRunning==false) {
+ LOGE("%s:AF not running, discarding stale event",__func__);
+ mAutofocusLock.unlock();
+ return ret;
+ }
+
+ mAutoFocusRunning = false;
+ mAutofocusLock.unlock();
+
+/************************************************************
+ END MUTEX CODE
+*************************************************************/
+ if(status==NULL) {
+ LOGE("%s:NULL ptr received for status",__func__);
+ return BAD_VALUE;
+ }
+
+ /* update focus distances after autofocus is done */
+ if(updateFocusDistances() != NO_ERROR) {
+ LOGE("%s: updateFocusDistances failed for %d", __FUNCTION__, mFocusMode);
+ }
+
+ /*(Do?) we need to make sure that the call back is the
+ last possible step in the execution flow since the same
+ context might be used if a fail triggers another round
+ of AF then the mAutoFocusRunning flag and other state
+ variables' validity will be under question*/
+
+ if (mNotifyCb && ( mMsgEnabled & CAMERA_MSG_FOCUS)){
+ LOGE("%s:Issuing callback to service",__func__);
+
+ /* "Accepted" status is not appropriate it should be used for
+ initial cmd, event reporting should only give use SUCCESS/FAIL
+ */
+
+ app_cb->notifyCb = mNotifyCb;
+ app_cb->argm_notify.msg_type = CAMERA_MSG_FOCUS;
+ app_cb->argm_notify.ext2 = 0;
+ app_cb->argm_notify.cookie = mCallbackCookie;
+
+ LOGE("Auto foucs state =%d", *status);
+ if(*status==CAM_CTRL_SUCCESS) {
+ app_cb->argm_notify.ext1 = true;
+ }
+ else if(*status==CAM_CTRL_FAILED){
+ app_cb->argm_notify.ext1 = false;
+ }
+ else{
+ app_cb->notifyCb = NULL;
+ LOGE("%s:Unknown AF status (%d) received",__func__,*status);
+ }
+
+ }/*(mNotifyCb && ( mMsgEnabled & CAMERA_MSG_FOCUS))*/
+ else{
+ LOGE("%s:Call back not enabled",__func__);
+ }
+
+ LOGE("autoFocusEvent: X");
+ return ret;
+
+}
+
+status_t QCameraHardwareInterface::cancelPicture()
+{
+ LOGI("cancelPicture: E");
+ status_t ret = MM_CAMERA_OK;
+ Mutex::Autolock lock(mLock);
+
+ switch(mPreviewState) {
+ case QCAMERA_HAL_PREVIEW_STOPPED:
+ case QCAMERA_HAL_PREVIEW_START:
+ case QCAMERA_HAL_PREVIEW_STARTED:
+ case QCAMERA_HAL_RECORDING_STARTED:
+ default:
+ break;
+ case QCAMERA_HAL_TAKE_PICTURE:
+ ret = cancelPictureInternal();
+ break;
+ }
+ LOGI("cancelPicture: X");
+ return ret;
+}
+
+status_t QCameraHardwareInterface::cancelPictureInternal()
+{
+ LOGI("cancelPictureInternal: E");
+ status_t ret = MM_CAMERA_OK;
+ if(mCameraState != CAMERA_STATE_READY) {
+ if(mStreamSnap) {
+ mStreamSnap->stop();
+ mCameraState = CAMERA_STATE_SNAP_STOP_CMD_SENT;
+ }
+ } else {
+ LOGE("%s: Cannot process cancel picture as snapshot is already done",__func__);
+ }
+ LOGI("cancelPictureInternal: X");
+ return ret;
+}
+
+void QCameraHardwareInterface::pausePreviewForSnapshot()
+{
+ stopPreviewInternal( );
+}
+status_t QCameraHardwareInterface::resumePreviewAfterSnapshot()
+{
+ status_t ret = NO_ERROR;
+ ret = mStreamDisplay->start();
+ return ret;
+}
+
+void liveshot_callback(mm_camera_ch_data_buf_t *recvd_frame,
+ void *user_data)
+{
+ QCameraHardwareInterface *pme = (QCameraHardwareInterface *)user_data;
+ cam_ctrl_dimension_t dim;
+ int mJpegMaxSize;
+ status_t ret;
+ LOGE("%s: E", __func__);
+
+
+ mm_camera_ch_data_buf_t* frame =
+ (mm_camera_ch_data_buf_t *)malloc(sizeof(mm_camera_ch_data_buf_t));
+ if (frame == NULL) {
+ LOGE("%s: Error allocating memory to save received_frame structure.", __func__);
+ cam_evt_buf_done(pme->mCameraId, recvd_frame);
+ return ;
+ }
+ memcpy(frame, recvd_frame, sizeof(mm_camera_ch_data_buf_t));
+
+ LOGE("<DEBUG> Liveshot buffer idx:%d",frame->video.video.idx);
+ memset(&dim, 0, sizeof(cam_ctrl_dimension_t));
+ ret = cam_config_get_parm(pme->mCameraId, MM_CAMERA_PARM_DIMENSION, &dim);
+ if (MM_CAMERA_OK != ret) {
+ LOGE("%s: error - can't get dimension!", __func__);
+ LOGE("%s: X", __func__);
+ }
+
+#if 1
+ 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 = pme->mDimension.video_width;
+ dim.picture_height = pme->mDimension.video_height;
+ dim.ui_thumbnail_width = pme->mDimension.video_width;
+ dim.ui_thumbnail_height = pme->mDimension.video_height;
+ dim.main_img_format = pme->mDimension.enc_format;
+ dim.thumb_format = pme->mDimension.enc_format;
+
+ mJpegMaxSize = pme->mDimension.video_width * pme->mDimension.video_width * 1.5;
+
+ LOGE("Picture w = %d , h = %d, size = %d",dim.picture_width,dim.picture_height,mJpegMaxSize);
+ if (pme->mStreamLiveSnap){
+ LOGE("%s:Deleting old Snapshot stream instance",__func__);
+ QCameraStream_Snapshot::deleteInstance (pme->mStreamLiveSnap);
+ pme->mStreamLiveSnap = NULL;
+ }
+
+ pme->mStreamLiveSnap = (QCameraStream_Snapshot*)QCameraStream_Snapshot::createInstance(pme->mCameraId,
+ pme->myMode);
+
+ if (!pme->mStreamLiveSnap) {
+ LOGE("%s: error - can't creat snapshot stream!", __func__);
+ return ;
+ }
+ pme->mStreamLiveSnap->setModeLiveSnapshot(true);
+ pme->mStreamLiveSnap->setHALCameraControl(pme);
+ pme->mStreamLiveSnap->initSnapshotBuffers(&dim,1);
+ LOGE("Calling live shot");
+
+
+ ((QCameraStream_Snapshot*)(pme->mStreamLiveSnap))->takePictureLiveshot(frame,&dim,mJpegMaxSize);
+
+#else
+
+
+
+
+ if(MM_CAMERA_OK != cam_evt_buf_done(pme->mCameraId,frame )) {
+ LOGE(" BUF DONE FAILED");
+ }
+#endif
+ LOGE("%s: X", __func__);
+
+}
+
+status_t QCameraHardwareInterface::takePicture()
+{
+ LOGI("takePicture: E");
+ status_t ret = MM_CAMERA_OK;
+ Mutex::Autolock lock(mLock);
+
+ mStreamSnap->resetSnapshotCounters( );
+ switch(mPreviewState) {
+ case QCAMERA_HAL_PREVIEW_STARTED:
+ mStreamSnap->setFullSizeLiveshot(false);
+ if (isZSLMode()) {
+ if (mStreamSnap != NULL) {
+ pausePreviewForZSL();
+ ret = mStreamSnap->takePictureZSL();
+ if (ret != MM_CAMERA_OK) {
+ LOGE("%s: Error taking ZSL snapshot!", __func__);
+ ret = BAD_VALUE;
+ }
+ }
+ else {
+ LOGE("%s: ZSL stream not active! Failure!!", __func__);
+ ret = BAD_VALUE;
+ }
+ return ret;
+ }
+
+ /*prepare snapshot, e.g LED*/
+ takePicturePrepareHardware( );
+ /* There's an issue where we have a glimpse of corrupted data between
+ a time we stop a preview and display the postview. It happens because
+ when we call stopPreview we deallocate the preview buffers hence overlay
+ displays garbage value till we enqueue postview buffer to be displayed.
+ Hence for temporary fix, we'll do memcopy of the last frame displayed and
+ queue it to overlay*/
+ // mzhu storePreviewFrameForPostview();
+
+ /* stop preview */
+ pausePreviewForSnapshot();
+
+ /* call Snapshot start() :*/
+ ret = mStreamSnap->start();
+ if (MM_CAMERA_OK != ret){
+ /* mzhu: fix me, restore preview */
+ LOGE("%s: error - can't start Snapshot stream!", __func__);
+ return BAD_VALUE;
+ }
+
+ if(MM_CAMERA_OK == ret)
+ mCameraState = CAMERA_STATE_SNAP_START_CMD_SENT;
+ else
+ mCameraState = CAMERA_STATE_ERROR;
+ mPreviewState = QCAMERA_HAL_TAKE_PICTURE;
+ break;
+ case QCAMERA_HAL_TAKE_PICTURE:
+ break;
+ case QCAMERA_HAL_PREVIEW_STOPPED:
+ case QCAMERA_HAL_PREVIEW_START:
+ ret = UNKNOWN_ERROR;
+ break;
+ case QCAMERA_HAL_RECORDING_STARTED:
+ if (canTakeFullSizeLiveshot()) {
+ LOGD(" Calling takeFullSizeLiveshot");
+ takeFullSizeLiveshot();
+ }else{
+ (void) cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_VIDEO,
+ liveshot_callback,
+ MM_CAMERA_REG_BUF_CB_COUNT,
+ 1,
+ this);
+ }
+
+ break;
+ default:
+ ret = UNKNOWN_ERROR;
+ break;
+ }
+ LOGI("takePicture: X");
+ return ret;
+}
+
+bool QCameraHardwareInterface::canTakeFullSizeLiveshot() {
+ bool ret;
+ if (mFullLiveshotEnabled && !isLowPowerCamcorder()) {
+ /* Full size liveshot enabled. */
+
+ /* If Picture size is same as video size, switch to Video size
+ * live snapshot */
+ if ((mDimension.picture_width == mDimension.video_width) &&
+ (mDimension.picture_height == mDimension.video_height)) {
+ return FALSE;
+ }
+
+ if (mDisEnabled) {
+ /* If DIS is enabled and Picture size is
+ * less than (video size + 10% DIS Margin)
+ * then fall back to Video size liveshot. */
+ if ((mDimension.picture_width <
+ (int)(mDimension.video_width * 1.1)) ||
+ (mDimension.picture_height <
+ (int)(mDimension.video_height * 1.1))) {
+ ret = FALSE;
+ } else {
+ /* Go with Full size live snapshot. */
+ ret = TRUE;
+ }
+ } else {
+ /* DIS Disabled. Go with Full size live snapshot */
+ ret = TRUE;
+ }
+ } else {
+ /* Full size liveshot disabled. Fallback to Video size liveshot. */
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
+status_t QCameraHardwareInterface::takeFullSizeLiveshot()
+{
+ status_t ret = NO_ERROR;
+ if (mStreamLiveSnap){
+ LOGE("%s:Deleting old Snapshot stream instance",__func__);
+ QCameraStream_Snapshot::deleteInstance (mStreamLiveSnap);
+ mStreamLiveSnap = NULL;
+ }
+ mStreamLiveSnap = QCameraStream_Snapshot::createInstance(mCameraId, myMode);
+
+ if (!mStreamLiveSnap) {
+ LOGE("%s: error - can't creat snapshot stream!", __func__);
+ /* mzhu: fix me, restore preview */
+ return BAD_VALUE;
+ }
+
+ /* Store HAL object in snapshot stream Object */
+ mStreamLiveSnap->setHALCameraControl(this);
+
+ mStreamLiveSnap->setFullSizeLiveshot(true);
+
+ /* Call snapshot init*/
+ ret = mStreamLiveSnap->init();
+ if (MM_CAMERA_OK != ret){
+ LOGE("%s: error - can't init Snapshot stream!", __func__);
+ return BAD_VALUE;
+ }
+
+ /* call Snapshot start() :*/
+ mStreamLiveSnap->resetSnapshotCounters( );
+ ret = mStreamLiveSnap->start();
+ if (MM_CAMERA_OK != ret){
+ /* mzhu: fix me, restore preview */
+ LOGE("%s: error - can't start Snapshot stream!", __func__);
+ return BAD_VALUE;
+ }
+ return ret;
+}
+
+status_t QCameraHardwareInterface::takeLiveSnapshot()
+{
+ status_t ret = NO_ERROR;
+ LOGI("takeLiveSnapshot: E");
+ mStreamRecord->takeLiveSnapshot();
+ LOGI("takeLiveSnapshot: X");
+ return ret;
+}
+
+status_t QCameraHardwareInterface::autoFocus()
+{
+ LOGI("autoFocus: E");
+ status_t ret = NO_ERROR;
+ Mutex::Autolock lock(mLock);
+ LOGI("autoFocus: Got lock");
+ bool status = true;
+ isp3a_af_mode_t afMode = getAutoFocusMode(mParameters);
+
+ if(mAutoFocusRunning==true){
+ LOGE("%s:AF already running should not have got this call",__func__);
+ return NO_ERROR;
+ }
+
+ if (afMode == AF_MODE_MAX) {
+ /* This should never happen. We cannot send a
+ * callback notifying error from this place because
+ * the CameraService has called this function after
+ * acquiring the lock. So if we try to issue a callback
+ * from this place, the callback will try to acquire
+ * the same lock in CameraService and it will result
+ * in deadlock. So, let the call go in to the lower
+ * layer. The lower layer will anyway return error if
+ * the autofocus is not supported or if the focus
+ * value is invalid.
+ * Just print out the error. */
+ LOGE("%s:Invalid AF mode (%d)", __func__, afMode);
+ }
+
+ LOGI("%s:AF start (mode %d)", __func__, afMode);
+ if(MM_CAMERA_OK != cam_ops_action(mCameraId, TRUE,
+ MM_CAMERA_OPS_FOCUS, &afMode)) {
+ LOGE("%s: AF command failed err:%d error %s",
+ __func__, errno, strerror(errno));
+ return UNKNOWN_ERROR;
+ }
+
+ mAutoFocusRunning = true;
+ LOGI("autoFocus: X");
+ return ret;
+}
+
+status_t QCameraHardwareInterface::cancelAutoFocus()
+{
+ LOGE("cancelAutoFocus: E");
+ status_t ret = NO_ERROR;
+ Mutex::Autolock lock(mLock);
+
+/**************************************************************
+ BEGIN MUTEX CODE
+*************************************************************/
+
+ mAutofocusLock.lock();
+ if(mAutoFocusRunning) {
+
+ mAutoFocusRunning = false;
+ mAutofocusLock.unlock();
+
+ }else/*(!mAutoFocusRunning)*/{
+
+ mAutofocusLock.unlock();
+ LOGE("%s:Af not running",__func__);
+ return NO_ERROR;
+ }
+/**************************************************************
+ END MUTEX CODE
+*************************************************************/
+
+
+ if(MM_CAMERA_OK!=cam_ops_action(mCameraId,FALSE,MM_CAMERA_OPS_FOCUS,NULL )) {
+ LOGE("%s: AF command failed err:%d error %s",__func__, errno,strerror(errno));
+ }
+
+ LOGE("cancelAutoFocus: X");
+ return NO_ERROR;
+}
+
+#if 0 //mzhu
+/*==========================================================================
+ * FUNCTION - prepareSnapshotAndWait -
+ *
+ * DESCRIPTION: invoke preparesnapshot and wait for it done
+ it can be called within takepicture, so no need
+ to grab mLock.
+ *=========================================================================*/
+void QCameraHardwareInterface::prepareSnapshotAndWait()
+{
+ LOGI("prepareSnapshotAndWait: E");
+ int rc = 0;
+ /*To Do: call mm camera preparesnapshot */
+ if(!rc ) {
+ mPreparingSnapshot = true;
+ pthread_mutex_lock(&mAsyncCmdMutex);
+ pthread_cond_wait(&mAsyncCmdWait, &mAsyncCmdMutex);
+ pthread_mutex_unlock(&mAsyncCmdMutex);
+ mPreparingSnapshot = false;
+ }
+ LOGI("prepareSnapshotAndWait: X");
+}
+#endif //mzhu
+
+/*==========================================================================
+ * FUNCTION - processprepareSnapshotEvent -
+ *
+ * DESCRIPTION: Process the event of preparesnapshot done msg
+ unblock prepareSnapshotAndWait( )
+ *=========================================================================*/
+void QCameraHardwareInterface::processprepareSnapshotEvent(cam_ctrl_status_t *status)
+{
+ LOGI("processprepareSnapshotEvent: E");
+ pthread_mutex_lock(&mAsyncCmdMutex);
+ pthread_cond_signal(&mAsyncCmdWait);
+ pthread_mutex_unlock(&mAsyncCmdMutex);
+ LOGI("processprepareSnapshotEvent: X");
+}
+
+void QCameraHardwareInterface::roiEvent(fd_roi_t roi,app_notify_cb_t *app_cb)
+{
+ LOGE("roiEvent: E");
+
+ if(mStreamDisplay) mStreamDisplay->notifyROIEvent(roi);
+#if 0 //TODO: move to preview obj
+ mCallbackLock.lock();
+ data_callback mcb = mDataCb;
+ void *mdata = mCallbackCookie;
+ int msgEnabled = mMsgEnabled;
+ mCallbackLock.unlock();
+
+ mMetaDataWaitLock.lock();
+ if (mFaceDetectOn == true && mSendMetaData == true) {
+ mSendMetaData = false;
+ int faces_detected = roi.rect_num;
+ int max_faces_detected = MAX_ROI * 4;
+ int array[max_faces_detected + 1];
+
+ array[0] = faces_detected * 4;
+ for (int i = 1, j = 0;j < MAX_ROI; j++, i = i + 4) {
+ if (j < faces_detected) {
+ array[i] = roi.faces[j].x;
+ array[i+1] = roi.faces[j].y;
+ array[i+2] = roi.faces[j].dx;
+ array[i+3] = roi.faces[j].dy;
+ } else {
+ array[i] = -1;
+ array[i+1] = -1;
+ array[i+2] = -1;
+ array[i+3] = -1;
+ }
+ }
+ if(mMetaDataHeap != NULL){
+ LOGV("mMetaDataHEap is non-NULL");
+ memcpy((uint32_t *)mMetaDataHeap->mHeap->base(), (uint32_t *)array, (sizeof(int)*(MAX_ROI*4+1)));
+ mMetaDataWaitLock.unlock();
+
+ if (mcb != NULL && (msgEnabled & CAMERA_MSG_META_DATA)) {
+ mcb(CAMERA_MSG_META_DATA, mMetaDataHeap->mBuffers[0], mdata);
+ }
+ } else {
+ mMetaDataWaitLock.unlock();
+ LOGE("runPreviewThread mMetaDataHeap is NULL");
+ }
+ } else {
+ mMetaDataWaitLock.unlock();
+ }
+#endif // mzhu
+ LOGE("roiEvent: X");
+}
+
+
+void QCameraHardwareInterface::handleZoomEventForSnapshot(void)
+{
+ mm_camera_ch_crop_t v4l2_crop;
+
+
+ LOGI("%s: E", __func__);
+
+ memset(&v4l2_crop,0,sizeof(v4l2_crop));
+ v4l2_crop.ch_type=MM_CAMERA_CH_SNAPSHOT;
+
+ LOGI("%s: Fetching crop info", __func__);
+ cam_config_get_parm(mCameraId,MM_CAMERA_PARM_CROP,&v4l2_crop);
+
+ LOGI("%s: Crop info received for main: %d, %d, %d, %d ", __func__,
+ v4l2_crop.snapshot.main_crop.left,
+ v4l2_crop.snapshot.main_crop.top,
+ v4l2_crop.snapshot.main_crop.width,
+ v4l2_crop.snapshot.main_crop.height);
+ LOGI("%s: Crop info received for thumbnail: %d, %d, %d, %d ",__func__,
+ v4l2_crop.snapshot.thumbnail_crop.left,
+ v4l2_crop.snapshot.thumbnail_crop.top,
+ v4l2_crop.snapshot.thumbnail_crop.width,
+ v4l2_crop.snapshot.thumbnail_crop.height);
+
+ if(mStreamSnap) {
+ LOGD("%s: Setting crop info for snapshot", __func__);
+ memcpy(&(mStreamSnap->mCrop), &v4l2_crop, sizeof(v4l2_crop));
+ }
+ if(mFullLiveshotEnabled && mStreamLiveSnap){
+ LOGD("%s: Setting crop info for snapshot", __func__);
+ memcpy(&(mStreamLiveSnap->mCrop), &v4l2_crop, sizeof(v4l2_crop));
+ }
+ LOGD("%s: X", __func__);
+}
+
+void QCameraHardwareInterface::handleZoomEventForPreview(app_notify_cb_t *app_cb)
+{
+ mm_camera_ch_crop_t v4l2_crop;
+
+ LOGI("%s: E", __func__);
+
+ /*regular zooming or smooth zoom stopped*/
+ if (!mSmoothZoomRunning && mPreviewWindow) {
+ memset(&v4l2_crop, 0, sizeof(v4l2_crop));
+ v4l2_crop.ch_type = MM_CAMERA_CH_PREVIEW;
+
+ LOGI("%s: Fetching crop info", __func__);
+ cam_config_get_parm(mCameraId,MM_CAMERA_PARM_CROP,&v4l2_crop);
+
+ LOGI("%s: Crop info received: %d, %d, %d, %d ", __func__,
+ v4l2_crop.crop.left,
+ v4l2_crop.crop.top,
+ v4l2_crop.crop.width,
+ v4l2_crop.crop.height);
+
+ mPreviewWindow->set_crop(mPreviewWindow,
+ v4l2_crop.crop.left,
+ v4l2_crop.crop.top,
+ v4l2_crop.crop.left + v4l2_crop.crop.width,
+ v4l2_crop.crop.top + v4l2_crop.crop.height);
+ LOGI("%s: Done setting crop", __func__);
+ LOGI("%s: Currrent zoom :%d",__func__, mCurrentZoom);
+ }
+
+ LOGI("%s: X", __func__);
+}
+
+void QCameraHardwareInterface::zoomEvent(cam_ctrl_status_t *status, app_notify_cb_t *app_cb)
+{
+ LOGI("zoomEvent: state:%d E",mPreviewState);
+ switch (mPreviewState) {
+ case QCAMERA_HAL_PREVIEW_STOPPED:
+ break;
+ case QCAMERA_HAL_PREVIEW_START:
+ break;
+ case QCAMERA_HAL_PREVIEW_STARTED:
+ handleZoomEventForPreview(app_cb);
+ if (isZSLMode())
+ handleZoomEventForSnapshot();
+ break;
+ case QCAMERA_HAL_RECORDING_STARTED:
+ handleZoomEventForPreview(app_cb);
+ if (mFullLiveshotEnabled)
+ handleZoomEventForSnapshot();
+ break;
+ case QCAMERA_HAL_TAKE_PICTURE:
+ if(isZSLMode())
+ handleZoomEventForPreview(app_cb);
+ handleZoomEventForSnapshot();
+ break;
+ default:
+ break;
+ }
+ LOGI("zoomEvent: X");
+}
+
+void QCameraHardwareInterface::dumpFrameToFile(const void * data, uint32_t size, char* name, char* ext, int index)
+{
+ char buf[32];
+ int file_fd;
+ if ( data != NULL) {
+ char * str;
+ snprintf(buf, sizeof(buf), "/data/%s_%d.%s", name, index, ext);
+ LOGE("marvin, %s size =%d", buf, size);
+ file_fd = open(buf, O_RDWR | O_CREAT, 0777);
+ write(file_fd, data, size);
+ close(file_fd);
+ }
+}
+
+void QCameraHardwareInterface::dumpFrameToFile(struct msm_frame* newFrame,
+ HAL_cam_dump_frm_type_t frm_type)
+{
+ int32_t enabled = 0;
+ int frm_num;
+ uint32_t skip_mode;
+ char value[PROPERTY_VALUE_MAX];
+ char buf[32];
+ int main_422 = 1;
+ property_get("persist.camera.dumpimg", value, "0");
+ enabled = atoi(value);
+
+ LOGV(" newFrame =%p, frm_type = %d", newFrame, frm_type);
+ if(enabled & HAL_DUMP_FRM_MASK_ALL) {
+ if((enabled & frm_type) && newFrame) {
+ frm_num = ((enabled & 0xffff0000) >> 16);
+ if(frm_num == 0) frm_num = 10; /*default 10 frames*/
+ if(frm_num > 256) frm_num = 256; /*256 buffers cycle around*/
+ skip_mode = ((enabled & 0x0000ff00) >> 8);
+ if(skip_mode == 0) skip_mode = 1; /*no -skip */
+
+ if( mDumpSkipCnt % skip_mode == 0) {
+ if (mDumpFrmCnt >= 0 && mDumpFrmCnt <= frm_num) {
+ int w, h;
+ int file_fd;
+ switch (frm_type) {
+ case HAL_DUMP_FRM_PREVIEW:
+ w = mDimension.display_width;
+ h = mDimension.display_height;
+ snprintf(buf, sizeof(buf), "/data/%dp_%dx%d.yuv", mDumpFrmCnt, w, h);
+ file_fd = open(buf, O_RDWR | O_CREAT, 0777);
+ break;
+ case HAL_DUMP_FRM_VIDEO:
+ w = mDimension.video_width;
+ h = mDimension.video_height;
+ snprintf(buf, sizeof(buf),"/data/%dv_%dx%d.yuv", mDumpFrmCnt, w, h);
+ file_fd = open(buf, O_RDWR | O_CREAT, 0777);
+ break;
+ case HAL_DUMP_FRM_MAIN:
+ w = mDimension.picture_width;
+ h = mDimension.picture_height;
+ snprintf(buf, sizeof(buf), "/data/%dm_%dx%d.yuv", mDumpFrmCnt, w, h);
+ file_fd = open(buf, O_RDWR | O_CREAT, 0777);
+ if (mDimension.main_img_format == CAMERA_YUV_422_NV16 ||
+ mDimension.main_img_format == CAMERA_YUV_422_NV61)
+ main_422 = 2;
+ break;
+ case HAL_DUMP_FRM_THUMBNAIL:
+ w = mDimension.ui_thumbnail_width;
+ h = mDimension.ui_thumbnail_height;
+ snprintf(buf, sizeof(buf),"/data/%dt_%dx%d.yuv", mDumpFrmCnt, w, h);
+ file_fd = open(buf, O_RDWR | O_CREAT, 0777);
+ break;
+ default:
+ w = h = 0;
+ file_fd = -1;
+ break;
+ }
+
+ if (file_fd < 0) {
+ LOGE("%s: cannot open file:type=%d\n", __func__, frm_type);
+ } else {
+ LOGE("%s: %d %d", __func__, newFrame->y_off, newFrame->cbcr_off);
+ write(file_fd, (const void *)(newFrame->buffer+newFrame->y_off), w * h);
+ write(file_fd, (const void *)
+ (newFrame->buffer + newFrame->cbcr_off), w * h / 2 * main_422);
+ close(file_fd);
+ LOGE("dump %s", buf);
+ }
+ } else if(frm_num == 256){
+ mDumpFrmCnt = 0;
+ }
+ mDumpFrmCnt++;
+ }
+ mDumpSkipCnt++;
+ }
+ } else {
+ mDumpFrmCnt = 0;
+ }
+}
+
+status_t QCameraHardwareInterface::setPreviewWindow(preview_stream_ops_t* window)
+{
+ status_t retVal = NO_ERROR;
+ LOGE(" %s: E mPreviewState = %d, mStreamDisplay = %p", __FUNCTION__, mPreviewState, mStreamDisplay);
+ if( window == NULL) {
+ LOGE("%s:Received Setting NULL preview window", __func__);
+ }
+ Mutex::Autolock lock(mLock);
+ switch(mPreviewState) {
+ case QCAMERA_HAL_PREVIEW_START:
+ mPreviewWindow = window;
+ if(mPreviewWindow) {
+ /* we have valid surface now, start preview */
+ LOGE("%s: calling startPreview2", __func__);
+ retVal = startPreview2();
+ if(retVal == NO_ERROR)
+ mPreviewState = QCAMERA_HAL_PREVIEW_STARTED;
+ LOGE("%s: startPreview2 done, mPreviewState = %d", __func__, mPreviewState);
+ } else
+ LOGE("%s: null window received, mPreviewState = %d", __func__, mPreviewState);
+ break;
+ case QCAMERA_HAL_PREVIEW_STARTED:
+ /* new window comes */
+ LOGE("%s: bug, cannot handle new window in started state", __func__);
+ //retVal = UNKNOWN_ERROR;
+ break;
+ case QCAMERA_HAL_PREVIEW_STOPPED:
+ case QCAMERA_HAL_TAKE_PICTURE:
+ mPreviewWindow = window;
+ LOGE("%s: mPreviewWindow = 0x%p, mStreamDisplay = 0x%p",
+ __func__, mPreviewWindow, mStreamDisplay);
+ if(mStreamDisplay)
+ retVal = mStreamDisplay->setPreviewWindow(window);
+ break;
+ default:
+ LOGE("%s: bug, cannot handle new window in state %d", __func__, mPreviewState);
+ retVal = UNKNOWN_ERROR;
+ break;
+ }
+ LOGE(" %s : X, mPreviewState = %d", __FUNCTION__, mPreviewState);
+ return retVal;
+}
+
+int QCameraHardwareInterface::storeMetaDataInBuffers(int enable)
+{
+ /* this is a dummy func now. fix me later */
+ mStoreMetaDataInFrame = enable;
+ return 0;
+}
+
+status_t QCameraHardwareInterface::sendMappingBuf(int ext_mode, int idx, int fd,
+ uint32_t size, int cameraid,
+ mm_camera_socket_msg_type msg_type)
+{
+ cam_sock_packet_t packet;
+ memset(&packet, 0, sizeof(cam_sock_packet_t));
+ packet.msg_type = msg_type;
+ packet.payload.frame_fd_map.ext_mode = ext_mode;
+ packet.payload.frame_fd_map.frame_idx = idx;
+ packet.payload.frame_fd_map.fd = fd;
+ packet.payload.frame_fd_map.size = size;
+
+ if ( cam_ops_sendmsg(cameraid, &packet, sizeof(cam_sock_packet_t), packet.payload.frame_fd_map.fd) <= 0 ) {
+ LOGE("%s: sending frame mapping buf msg Failed", __func__);
+ return FAILED_TRANSACTION;
+ }
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::sendUnMappingBuf(int ext_mode, int idx, int cameraid,
+ mm_camera_socket_msg_type msg_type)
+{
+ cam_sock_packet_t packet;
+ memset(&packet, 0, sizeof(cam_sock_packet_t));
+ packet.msg_type = msg_type;
+ packet.payload.frame_fd_unmap.ext_mode = ext_mode;
+ packet.payload.frame_fd_unmap.frame_idx = idx;
+ if ( cam_ops_sendmsg(cameraid, &packet, sizeof(cam_sock_packet_t), 0) <= 0 ) {
+ LOGE("%s: sending frame unmapping buf msg Failed", __func__);
+ return FAILED_TRANSACTION;
+ }
+ return NO_ERROR;
+}
+
+int QCameraHardwareInterface::allocate_ion_memory(QCameraHalHeap_t *p_camera_memory, int cnt, int ion_type)
+{
+ int rc = 0;
+ struct ion_handle_data handle_data;
+
+ p_camera_memory->main_ion_fd[cnt] = open("/dev/ion", O_RDONLY);
+ if (p_camera_memory->main_ion_fd[cnt] < 0) {
+ LOGE("Ion dev open failed\n");
+ LOGE("Error is %s\n", strerror(errno));
+ goto ION_OPEN_FAILED;
+ }
+ p_camera_memory->alloc[cnt].len = p_camera_memory->size;
+ /* to make it page size aligned */
+ p_camera_memory->alloc[cnt].len = (p_camera_memory->alloc[cnt].len + 4095) & (~4095);
+ p_camera_memory->alloc[cnt].align = 4096;
+ p_camera_memory->alloc[cnt].flags = ion_type;
+
+ rc = ioctl(p_camera_memory->main_ion_fd[cnt], ION_IOC_ALLOC, &p_camera_memory->alloc[cnt]);
+ if (rc < 0) {
+ LOGE("ION allocation failed\n");
+ goto ION_ALLOC_FAILED;
+ }
+
+ p_camera_memory->ion_info_fd[cnt].handle = p_camera_memory->alloc[cnt].handle;
+ rc = ioctl(p_camera_memory->main_ion_fd[cnt], ION_IOC_SHARE, &p_camera_memory->ion_info_fd[cnt]);
+ if (rc < 0) {
+ LOGE("ION map failed %s\n", strerror(errno));
+ goto ION_MAP_FAILED;
+ }
+ p_camera_memory->fd[cnt] = p_camera_memory->ion_info_fd[cnt].fd;
+ return 0;
+
+ION_MAP_FAILED:
+ handle_data.handle = p_camera_memory->ion_info_fd[cnt].handle;
+ ioctl(p_camera_memory->main_ion_fd[cnt], ION_IOC_FREE, &handle_data);
+ION_ALLOC_FAILED:
+ close(p_camera_memory->main_ion_fd[cnt]);
+ p_camera_memory->main_ion_fd[cnt] = -1;
+ION_OPEN_FAILED:
+ return -1;
+}
+
+int QCameraHardwareInterface::deallocate_ion_memory(QCameraHalHeap_t *p_camera_memory, int cnt)
+{
+ struct ion_handle_data handle_data;
+ int rc = 0;
+
+ if (p_camera_memory->main_ion_fd[cnt] > 0) {
+ handle_data.handle = p_camera_memory->ion_info_fd[cnt].handle;
+ ioctl(p_camera_memory->main_ion_fd[cnt], ION_IOC_FREE, &handle_data);
+ close(p_camera_memory->main_ion_fd[cnt]);
+ p_camera_memory->main_ion_fd[cnt] = -1;
+ }
+ return rc;
+}
+
+int QCameraHardwareInterface::allocate_ion_memory(QCameraStatHeap_t *p_camera_memory, int cnt, int ion_type)
+{
+ int rc = 0;
+ struct ion_handle_data handle_data;
+
+ p_camera_memory->main_ion_fd[cnt] = open("/dev/ion", O_RDONLY);
+ if (p_camera_memory->main_ion_fd[cnt] < 0) {
+ LOGE("Ion dev open failed\n");
+ LOGE("Error is %s\n", strerror(errno));
+ goto ION_OPEN_FAILED;
+ }
+ p_camera_memory->alloc[cnt].len = p_camera_memory->size;
+ /* to make it page size aligned */
+ p_camera_memory->alloc[cnt].len = (p_camera_memory->alloc[cnt].len + 4095) & (~4095);
+ p_camera_memory->alloc[cnt].align = 4096;
+ p_camera_memory->alloc[cnt].flags = (0x1 << ion_type | 0x1 << ION_IOMMU_HEAP_ID);
+
+ rc = ioctl(p_camera_memory->main_ion_fd[cnt], ION_IOC_ALLOC, &p_camera_memory->alloc[cnt]);
+ if (rc < 0) {
+ LOGE("ION allocation failed\n");
+ goto ION_ALLOC_FAILED;
+ }
+
+ p_camera_memory->ion_info_fd[cnt].handle = p_camera_memory->alloc[cnt].handle;
+ rc = ioctl(p_camera_memory->main_ion_fd[cnt], ION_IOC_SHARE, &p_camera_memory->ion_info_fd[cnt]);
+ if (rc < 0) {
+ LOGE("ION map failed %s\n", strerror(errno));
+ goto ION_MAP_FAILED;
+ }
+ p_camera_memory->fd[cnt] = p_camera_memory->ion_info_fd[cnt].fd;
+ return 0;
+
+ION_MAP_FAILED:
+ handle_data.handle = p_camera_memory->ion_info_fd[cnt].handle;
+ ioctl(p_camera_memory->main_ion_fd[cnt], ION_IOC_FREE, &handle_data);
+ION_ALLOC_FAILED:
+ close(p_camera_memory->main_ion_fd[cnt]);
+ p_camera_memory->main_ion_fd[cnt] = -1;
+ION_OPEN_FAILED:
+ return -1;
+}
+
+int QCameraHardwareInterface::cache_ops(int ion_fd,
+ struct ion_flush_data *cache_data, int type)
+{
+ int rc = 0;
+
+ rc = ioctl(ion_fd, type, cache_data);
+ if (rc < 0)
+ LOGE("%s: Cache Invalidate failed\n", __func__);
+ else
+ LOGV("%s: Cache OPs type(%d) success", __func__);
+
+ return rc;
+}
+
+int QCameraHardwareInterface::deallocate_ion_memory(QCameraStatHeap_t *p_camera_memory, int cnt)
+{
+ struct ion_handle_data handle_data;
+ int rc = 0;
+
+ if (p_camera_memory->main_ion_fd[cnt] > 0) {
+ handle_data.handle = p_camera_memory->ion_info_fd[cnt].handle;
+ ioctl(p_camera_memory->main_ion_fd[cnt], ION_IOC_FREE, &handle_data);
+ close(p_camera_memory->main_ion_fd[cnt]);
+ p_camera_memory->main_ion_fd[cnt] = -1;
+ }
+ return rc;
+}
+
+int QCameraHardwareInterface::initHeapMem( QCameraHalHeap_t *heap,
+ int num_of_buf,
+ int buf_len,
+ int y_off,
+ int cbcr_off,
+ int pmem_type,
+ mm_cameara_stream_buf_t *StreamBuf,
+ mm_camera_buf_def_t *buf_def,
+ uint8_t num_planes,
+ uint32_t *planes
+)
+{
+ int rc = 0;
+ int i;
+ int path;
+ struct msm_frame *frame;
+ LOGE("Init Heap =%p. stream_buf =%p, pmem_type =%d, num_of_buf=%d. buf_len=%d, cbcr_off=%d",
+ heap, StreamBuf, pmem_type, num_of_buf, buf_len, cbcr_off);
+ if(num_of_buf > MM_CAMERA_MAX_NUM_FRAMES || heap == NULL ||
+ mGetMemory == NULL ) {
+ LOGE("Init Heap error");
+ rc = -1;
+ return rc;
+ }
+ memset(heap, 0, sizeof(QCameraHalHeap_t));
+ for (i=0; i<MM_CAMERA_MAX_NUM_FRAMES;i++) {
+ heap->main_ion_fd[i] = -1;
+ heap->fd[i] = -1;
+ }
+ heap->buffer_count = num_of_buf;
+ heap->size = buf_len;
+ heap->y_offset = y_off;
+ heap->cbcr_offset = cbcr_off;
+
+ if (StreamBuf != NULL) {
+ StreamBuf->num = num_of_buf;
+ StreamBuf->frame_len = buf_len;
+ switch (pmem_type) {
+ case MSM_PMEM_MAINIMG:
+ case MSM_PMEM_RAW_MAINIMG:
+ path = OUTPUT_TYPE_S;
+ break;
+
+ case MSM_PMEM_THUMBNAIL:
+ path = OUTPUT_TYPE_T;
+ break;
+
+ default:
+ rc = -1;
+ return rc;
+ }
+ }
+
+
+ for(i = 0; i < num_of_buf; i++) {
+#ifdef USE_ION
+ if (isZSLMode())
+ rc = allocate_ion_memory(heap, i, ((0x1 << CAMERA_ZSL_ION_HEAP_ID) |
+ (0x1 << CAMERA_ZSL_ION_FALLBACK_HEAP_ID)));
+ else
+ rc = allocate_ion_memory(heap, i, ((0x1 << CAMERA_ION_HEAP_ID) |
+ (0x1 << CAMERA_ION_FALLBACK_HEAP_ID)));
+
+ if (rc < 0) {
+ LOGE("%sION allocation failed\n", __func__);
+ break;
+ }
+#else
+ if (pmem_type == MSM_PMEM_MAX)
+ heap->fd[i] = -1;
+ else {
+ heap->fd[i] = open("/dev/pmem_adsp", O_RDWR|O_SYNC);
+ if ( heap->fd[i] <= 0) {
+ rc = -1;
+ LOGE("Open fail: heap->fd[%d] =%d", i, heap->fd[i]);
+ break;
+ }
+ }
+#endif
+ heap->camera_memory[i] = mGetMemory( heap->fd[i], buf_len, 1, (void *)this);
+
+ if (heap->camera_memory[i] == NULL ) {
+ LOGE("Getmem fail %d: ", i);
+ rc = -1;
+ break;
+ }
+ if (StreamBuf != NULL) {
+ frame = &(StreamBuf->frame[i]);
+ memset(frame, 0, sizeof(struct msm_frame));
+ frame->fd = heap->fd[i];
+ frame->phy_offset = 0;
+ frame->buffer = (uint32_t) heap->camera_memory[i]->data;
+ frame->path = path;
+ frame->cbcr_off = planes[0]+heap->cbcr_offset;
+ frame->y_off = heap->y_offset;
+ frame->fd_data = heap->ion_info_fd[i];
+ frame->ion_alloc = heap->alloc[i];
+ frame->ion_dev_fd = heap->main_ion_fd[i];
+ LOGD("%s: Buffer idx: %d addr: %x fd: %d phy_offset: %d"
+ "cbcr_off: %d y_off: %d frame_len: %d", __func__,
+ i, (unsigned int)frame->buffer, frame->fd,
+ frame->phy_offset, cbcr_off, y_off, frame->ion_alloc.len);
+
+ buf_def->buf.mp[i].frame = *frame;
+ buf_def->buf.mp[i].frame_offset = 0;
+ buf_def->buf.mp[i].num_planes = num_planes;
+ /* Plane 0 needs to be set seperately. Set other planes
+ * in a loop. */
+ buf_def->buf.mp[i].planes[0].length = planes[0];
+ buf_def->buf.mp[i].planes[0].m.userptr = frame->fd;
+ buf_def->buf.mp[i].planes[0].data_offset = y_off;
+ buf_def->buf.mp[i].planes[0].reserved[0] =
+ buf_def->buf.mp[i].frame_offset;
+ for (int j = 1; j < num_planes; j++) {
+ buf_def->buf.mp[i].planes[j].length = planes[j];
+ buf_def->buf.mp[i].planes[j].m.userptr = frame->fd;
+ buf_def->buf.mp[i].planes[j].data_offset = cbcr_off;
+ buf_def->buf.mp[i].planes[j].reserved[0] =
+ buf_def->buf.mp[i].planes[j-1].reserved[0] +
+ buf_def->buf.mp[i].planes[j-1].length;
+ }
+ } else {
+ }
+
+ LOGE("heap->fd[%d] =%d, camera_memory=%p", i, heap->fd[i], heap->camera_memory[i]);
+ heap->local_flag[i] = 1;
+ }
+ if( rc < 0) {
+ releaseHeapMem(heap);
+ }
+ return rc;
+
+}
+
+int QCameraHardwareInterface::releaseHeapMem( QCameraHalHeap_t *heap)
+{
+ int rc = 0;
+ LOGE("Release %p", heap);
+ if (heap != NULL) {
+
+ for (int i = 0; i < heap->buffer_count; i++) {
+ if(heap->camera_memory[i] != NULL) {
+ heap->camera_memory[i]->release( heap->camera_memory[i] );
+ heap->camera_memory[i] = NULL;
+ } else if (heap->fd[i] <= 0) {
+ LOGE("impossible: amera_memory[%d] = %p, fd = %d",
+ i, heap->camera_memory[i], heap->fd[i]);
+ }
+
+ if(heap->fd[i] > 0) {
+ close(heap->fd[i]);
+ heap->fd[i] = -1;
+ }
+#ifdef USE_ION
+ deallocate_ion_memory(heap, i);
+#endif
+ }
+ heap->buffer_count = 0;
+ heap->size = 0;
+ heap->y_offset = 0;
+ heap->cbcr_offset = 0;
+ }
+ return rc;
+}
+
+preview_format_info_t QCameraHardwareInterface::getPreviewFormatInfo( )
+{
+ return mPreviewFormatInfo;
+}
+
+void QCameraHardwareInterface::wdenoiseEvent(cam_ctrl_status_t status, void *cookie)
+{
+ LOGI("wdnEvent: preview state:%d E",mPreviewState);
+ if (mStreamSnap != NULL) {
+ LOGI("notifyWDNEvent to snapshot stream");
+ mStreamSnap->notifyWDenoiseEvent(status, cookie);
+ }
+}
+
+bool QCameraHardwareInterface::isWDenoiseEnabled()
+{
+ return mDenoiseValue;
+}
+
+void QCameraHardwareInterface::takePicturePrepareHardware()
+{
+ LOGV("%s: E", __func__);
+
+ /* Prepare snapshot*/
+ cam_ops_action(mCameraId,
+ TRUE,
+ MM_CAMERA_OPS_PREPARE_SNAPSHOT,
+ this);
+ LOGV("%s: X", __func__);
+}
+
+bool QCameraHardwareInterface::isNoDisplayMode()
+{
+ return (mNoDisplayMode != 0);
+}
+
+void QCameraHardwareInterface::pausePreviewForZSL()
+{
+ if(mRestartPreview) {
+ stopPreviewInternal();
+ mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED;
+ startPreview2();
+ mPreviewState = QCAMERA_HAL_PREVIEW_STARTED;
+ mRestartPreview = false;
+ }
+}
+}; // namespace android
+
diff --git a/camera/QCamera/HAL/core/src/QCameraHWI_Mem.cpp b/camera/QCamera/HAL/core/src/QCameraHWI_Mem.cpp
new file mode 100755
index 0000000..fbd7180
--- /dev/null
+++ b/camera/QCamera/HAL/core/src/QCameraHWI_Mem.cpp
@@ -0,0 +1,402 @@
+/*
+** 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.
+** 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_Mem"
+#include <utils/Log.h>
+
+#include <utils/Errors.h>
+#include <utils/threads.h>
+#include <binder/MemoryHeapPmem.h>
+#include <utils/String16.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <cutils/properties.h>
+#include <math.h>
+#if HAVE_ANDROID_OS
+#include <linux/android_pmem.h>
+#endif
+#include <linux/ioctl.h>
+#include <camera/CameraParameters.h>
+#include <media/mediarecorder.h>
+#include <gralloc_priv.h>
+
+#include "QCameraHWI_Mem.h"
+
+#define CAMERA_HAL_UNUSED(expr) do { (void)(expr); } while (0)
+
+/* QCameraHardwareInterface class implementation goes here*/
+/* following code implement the contol logic of this class*/
+
+namespace android {
+
+
+static bool register_buf(int size,
+ int frame_size,
+ int cbcr_offset,
+ int yoffset,
+ int pmempreviewfd,
+ uint32_t offset,
+ uint8_t *buf,
+ int pmem_type,
+ bool vfe_can_write,
+ bool register_buffer = true);
+
+#if 0
+MMCameraDL::MMCameraDL(){
+ LOGV("MMCameraDL: E");
+ libmmcamera = NULL;
+#if DLOPEN_LIBMMCAMERA
+ libmmcamera = ::dlopen("liboemcamera.so", RTLD_NOW);
+#endif
+ LOGV("Open MM camera DL libeomcamera loaded at %p ", libmmcamera);
+ LOGV("MMCameraDL: X");
+}
+
+void * MMCameraDL::pointer(){
+ return libmmcamera;
+}
+
+MMCameraDL::~MMCameraDL(){
+ LOGV("~MMCameraDL: E");
+ LINK_mm_camera_destroy();
+ if (libmmcamera != NULL) {
+ ::dlclose(libmmcamera);
+ LOGV("closed MM Camera DL ");
+ }
+ libmmcamera = NULL;
+ LOGV("~MMCameraDL: X");
+}
+
+
+wp<MMCameraDL> MMCameraDL::instance;
+Mutex MMCameraDL::singletonLock;
+
+
+sp<MMCameraDL> MMCameraDL::getInstance(){
+ Mutex::Autolock instanceLock(singletonLock);
+ sp<MMCameraDL> mmCamera = instance.promote();
+ if(mmCamera == NULL){
+ mmCamera = new MMCameraDL();
+ instance = mmCamera;
+ }
+ return mmCamera;
+}
+#endif
+
+MemPool::MemPool(int buffer_size, int num_buffers,
+ int frame_size,
+ const char *name) :
+ mBufferSize(buffer_size),
+ mNumBuffers(num_buffers),
+ mFrameSize(frame_size),
+ mBuffers(NULL), mName(name)
+{
+ int page_size_minus_1 = getpagesize() - 1;
+ mAlignedBufferSize = (buffer_size + page_size_minus_1) & (~page_size_minus_1);
+}
+
+void MemPool::completeInitialization()
+{
+ // If we do not know how big the frame will be, we wait to allocate
+ // the buffers describing the individual frames until we do know their
+ // size.
+
+ if (mFrameSize > 0) {
+ mBuffers = new sp<MemoryBase>[mNumBuffers];
+ for (int i = 0; i < mNumBuffers; i++) {
+ mBuffers[i] = new
+ MemoryBase(mHeap,
+ i * mAlignedBufferSize,
+ mFrameSize);
+ }
+ }
+}
+
+AshmemPool::AshmemPool(int buffer_size, int num_buffers,
+ int frame_size,
+ const char *name) :
+ MemPool(buffer_size,
+ num_buffers,
+ frame_size,
+ name)
+{
+ LOGV("constructing MemPool %s backed by ashmem: "
+ "%d frames @ %d uint8_ts, "
+ "buffer size %d",
+ mName,
+ num_buffers, frame_size, buffer_size);
+
+ int page_mask = getpagesize() - 1;
+ int ashmem_size = buffer_size * num_buffers;
+ ashmem_size += page_mask;
+ ashmem_size &= ~page_mask;
+
+ mHeap = new MemoryHeapBase(ashmem_size);
+
+ completeInitialization();
+}
+
+static bool register_buf(int size,
+ int frame_size,
+ int cbcr_offset,
+ int yoffset,
+ int pmempreviewfd,
+ uint32_t offset,
+ uint8_t *buf,
+ int pmem_type,
+ bool vfe_can_write,
+ bool register_buffer)
+{
+ struct msm_pmem_info pmemBuf;
+ CAMERA_HAL_UNUSED(frame_size);
+
+ pmemBuf.type = pmem_type;
+ pmemBuf.fd = pmempreviewfd;
+ pmemBuf.offset = offset;
+ pmemBuf.len = size;
+ pmemBuf.vaddr = buf;
+ pmemBuf.y_off = yoffset;
+ pmemBuf.cbcr_off = cbcr_offset;
+
+ pmemBuf.active = vfe_can_write;
+
+ LOGV("register_buf: reg = %d buffer = %p",
+ !register_buffer, buf);
+ /*TODO*/
+ /*if(native_start_ops(register_buffer ? CAMERA_OPS_REGISTER_BUFFER :
+ CAMERA_OPS_UNREGISTER_BUFFER ,(void *)&pmemBuf) < 0) {
+ LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM error %s",
+ strerror(errno));
+ return false;
+ }*/
+
+ return true;
+
+}
+
+#if 0
+bool register_record_buffers(bool register_buffer) {
+ LOGI("%s: (%d) E", __FUNCTION__, register_buffer);
+ struct msm_pmem_info pmemBuf;
+
+ for (int cnt = 0; cnt < VIDEO_BUFFER_COUNT; ++cnt) {
+ pmemBuf.type = MSM_PMEM_VIDEO;
+ pmemBuf.fd = mRecordHeap->mHeap->getHeapID();
+ pmemBuf.offset = mRecordHeap->mAlignedBufferSize * cnt;
+ pmemBuf.len = mRecordHeap->mBufferSize;
+ pmemBuf.vaddr = (uint8_t *)mRecordHeap->mHeap->base() + mRecordHeap->mAlignedBufferSize * cnt;
+ pmemBuf.y_off = 0;
+ pmemBuf.cbcr_off = recordframes[0].cbcr_off;
+ if(register_buffer == true) {
+ pmemBuf.active = (cnt<ACTIVE_VIDEO_BUFFERS);
+ if( (mVpeEnabled) && (cnt == kRecordBufferCount-1)) {
+ pmemBuf.type = MSM_PMEM_VIDEO_VPE;
+ pmemBuf.active = 1;
+ }
+ } else {
+ pmemBuf.active = false;
+ }
+
+ LOGV("register_buf: reg = %d buffer = %p", !register_buffer,
+ (void *)pmemBuf.vaddr);
+ if(native_start_ops(register_buffer ? CAMERA_OPS_REGISTER_BUFFER :
+ CAMERA_OPS_UNREGISTER_BUFFER ,(void *)&pmemBuf) < 0) {
+ LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM error %s",
+ strerror(errno));
+ return false;
+ }
+ }
+ return true;
+}
+#endif
+PmemPool::PmemPool(const char *pmem_pool,
+ int flags,
+ int pmem_type,
+ int buffer_size, int num_buffers,
+ int frame_size, int cbcr_offset,
+ int yOffset, const char *name) :
+ MemPool(buffer_size,num_buffers,frame_size,name),
+ mPmemType(pmem_type),
+ mCbCrOffset(cbcr_offset),
+ myOffset(yOffset)
+{
+ LOGI("constructing MemPool %s backed by pmem pool %s: "
+ "%d frames @ %d bytes, buffer size %d",
+ mName,
+ pmem_pool, num_buffers, frame_size,
+ buffer_size);
+
+ //mMMCameraDLRef = MMCameraDL::getInstance();
+
+
+ // Make a new mmap'ed heap that can be shared across processes.
+ // mAlignedBufferSize is already in 4k aligned. (do we need total size necessary to be in power of 2??)
+ mAlignedSize = mAlignedBufferSize * num_buffers;
+
+ sp<MemoryHeapBase> masterHeap =
+ new MemoryHeapBase(pmem_pool, mAlignedSize, flags);
+
+ if (masterHeap->getHeapID() < 0) {
+ LOGE("failed to construct master heap for pmem pool %s", pmem_pool);
+ masterHeap.clear();
+ return;
+ }
+
+ sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, flags);
+ if (pmemHeap->getHeapID() >= 0) {
+ pmemHeap->slap();
+ masterHeap.clear();
+ mHeap = pmemHeap;
+ pmemHeap.clear();
+
+ mFd = mHeap->getHeapID();
+ if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
+ LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
+ pmem_pool,
+ ::strerror(errno), errno);
+ mHeap.clear();
+ return;
+ }
+
+ LOGE("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
+ pmem_pool,
+ mFd,
+ mSize.len);
+ LOGE("mBufferSize=%d, mAlignedBufferSize=%d\n", mBufferSize, mAlignedBufferSize);
+
+#if 0
+ // Unregister preview buffers with the camera drivers. Allow the VFE to write
+ // to all preview buffers except for the last one.
+ // Only Register the preview, snapshot and thumbnail buffers with the kernel.
+ if( (strcmp("postview", mName) != 0) ){
+ int num_buf = num_buffers;
+ if(!strcmp("preview", mName)) num_buf = kPreviewBufferCount;
+ LOGD("num_buffers = %d", num_buf);
+ for (int cnt = 0; cnt < num_buf; ++cnt) {
+ int active = 1;
+ if(pmem_type == MSM_PMEM_VIDEO){
+ active = (cnt<ACTIVE_VIDEO_BUFFERS);
+ //When VPE is enabled, set the last record
+ //buffer as active and pmem type as PMEM_VIDEO_VPE
+ //as this is a requirement from VPE operation.
+ //No need to set this pmem type to VIDEO_VPE while unregistering,
+ //because as per camera stack design: "the VPE AXI is also configured
+ //when VFE is configured for VIDEO, which is as part of preview
+ //initialization/start. So during this VPE AXI config camera stack
+ //will lookup the PMEM_VIDEO_VPE buffer and give it as o/p of VPE and
+ //change it's type to PMEM_VIDEO".
+ if( (mVpeEnabled) && (cnt == kRecordBufferCount-1)) {
+ active = 1;
+ pmem_type = MSM_PMEM_VIDEO_VPE;
+ }
+ LOGV(" pmempool creating video buffers : active %d ", active);
+ }
+ else if (pmem_type == MSM_PMEM_PREVIEW){
+ active = (cnt < ACTIVE_PREVIEW_BUFFERS);
+ }
+ else if ((pmem_type == MSM_PMEM_MAINIMG)
+ || (pmem_type == MSM_PMEM_THUMBNAIL)){
+ active = (cnt < ACTIVE_ZSL_BUFFERS);
+ }
+ register_buf(mBufferSize,
+ mFrameSize, mCbCrOffset, myOffset,
+ mHeap->getHeapID(),
+ mAlignedBufferSize * cnt,
+ (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
+ pmem_type,
+ active);
+ }
+ }
+#endif
+ completeInitialization();
+ }
+ else LOGE("pmem pool %s error: could not create master heap!",
+ pmem_pool);
+ LOGI("%s: (%s) X ", __FUNCTION__, mName);
+}
+
+PmemPool::~PmemPool()
+{
+ LOGI("%s: %s E", __FUNCTION__, mName);
+#if 0
+ if (mHeap != NULL) {
+ // Unregister preview buffers with the camera drivers.
+ // Only Unregister the preview, snapshot and thumbnail
+ // buffers with the kernel.
+ if( (strcmp("postview", mName) != 0) ){
+ int num_buffers = mNumBuffers;
+ if(!strcmp("preview", mName)) num_buffers = PREVIEW_BUFFER_COUNT;
+ for (int cnt = 0; cnt < num_buffers; ++cnt) {
+ register_buf(mBufferSize,
+ mFrameSize,
+ mCbCrOffset,
+ myOffset,
+ mHeap->getHeapID(),
+ mAlignedBufferSize * cnt,
+ (uint8_t *)mHeap->base() + mAlignedBufferSize * cnt,
+ mPmemType,
+ false,
+ false /* unregister */);
+ }
+ }
+ }
+ mMMCameraDLRef.clear();
+#endif
+ LOGI("%s: %s X", __FUNCTION__, mName);
+}
+MemPool::~MemPool()
+{
+ LOGV("destroying MemPool %s", mName);
+ if (mFrameSize > 0)
+ delete [] mBuffers;
+ mHeap.clear();
+ LOGV("destroying MemPool %s completed", mName);
+}
+
+
+status_t MemPool::dump(int fd, const Vector<String16>& args) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ CAMERA_HAL_UNUSED(args);
+ snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
+ result.append(buffer);
+ if (mName) {
+ snprintf(buffer, 255, "mem pool name (%s)\n", mName);
+ result.append(buffer);
+ }
+ if (mHeap != 0) {
+ snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
+ mHeap->getBase(), mHeap->getSize(),
+ mHeap->getFlags(), mHeap->getDevice());
+ result.append(buffer);
+ }
+ snprintf(buffer, 255,
+ "buffer size (%d), number of buffers (%d), frame size(%d)",
+ mBufferSize, mNumBuffers, mFrameSize);
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+};
diff --git a/camera/QCamera/HAL/core/src/QCameraHWI_Parm.cpp b/camera/QCamera/HAL/core/src/QCameraHWI_Parm.cpp
new file mode 100755
index 0000000..564a481
--- /dev/null
+++ b/camera/QCamera/HAL/core/src/QCameraHWI_Parm.cpp
@@ -0,0 +1,4073 @@
+/*
+** 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.
+** 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.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_NIDEBUG 0
+#define LOG_TAG "QCameraHWI_Parm"
+#include <utils/Log.h>
+
+#include <utils/Errors.h>
+#include <utils/threads.h>
+#include <binder/MemoryHeapPmem.h>
+#include <utils/String16.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <cutils/properties.h>
+#include <math.h>
+#if HAVE_ANDROID_OS
+#include <linux/android_pmem.h>
+#endif
+#include <linux/ioctl.h>
+#include <camera/CameraParameters.h>
+#include <media/mediarecorder.h>
+#include <gralloc_priv.h>
+
+#include "linux/msm_mdp.h"
+#include <linux/fb.h>
+#include <limits>
+
+
+extern "C" {
+#include <fcntl.h>
+#include <time.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <termios.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/system_properties.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <linux/ion.h>
+#include <camera.h>
+#include <cam_fifo.h>
+#include <jpege.h>
+
+} // extern "C"
+
+#include "QCameraHWI.h"
+
+/* QCameraHardwareInterface class implementation goes here*/
+/* following code implements the parameter logic of this class*/
+#define EXPOSURE_COMPENSATION_MAXIMUM_NUMERATOR 12
+#define EXPOSURE_COMPENSATION_MINIMUM_NUMERATOR -12
+#define EXPOSURE_COMPENSATION_DEFAULT_NUMERATOR 0
+#define EXPOSURE_COMPENSATION_DENOMINATOR 6
+#define EXPOSURE_COMPENSATION_STEP ((float (1))/EXPOSURE_COMPENSATION_DENOMINATOR)
+#define DEFAULT_CAMERA_AREA "(0, 0, 0, 0, 0)"
+
+#define HDR_HAL_FRAME 2
+
+#define BURST_INTREVAL_MIN 1
+#define BURST_INTREVAL_MAX 10
+#define BURST_INTREVAL_DEFAULT 1
+
+//Default FPS
+#define MINIMUM_FPS 5
+#define MAXIMUM_FPS 120
+#define DEFAULT_FIXED_FPS 30
+#define DEFAULT_FPS MAXIMUM_FPS
+
+//Default Picture Width
+#define DEFAULT_PICTURE_WIDTH 640
+#define DEFAULT_PICTURE_HEIGHT 480
+
+//Default Video Width
+#define DEFAULT_VIDEO_WIDTH 1920
+#define DEFAULT_VIDEO_HEIGHT 1088
+
+#define THUMBNAIL_SIZE_COUNT (sizeof(thumbnail_sizes)/sizeof(thumbnail_size_type))
+#define DEFAULT_THUMBNAIL_SETTING 4
+#define THUMBNAIL_WIDTH_STR "512"
+#define THUMBNAIL_HEIGHT_STR "384"
+#define THUMBNAIL_SMALL_HEIGHT 144
+
+#define DONT_CARE_COORDINATE -1
+
+//for histogram stats
+#define HISTOGRAM_STATS_SIZE 257
+
+//Supported preview fps ranges should be added to this array in the form (minFps,maxFps)
+static android::FPSRange FpsRangesSupported[] = {
+ android::FPSRange(MINIMUM_FPS*1000,MAXIMUM_FPS*1000)
+ };
+#define FPS_RANGES_SUPPORTED_COUNT (sizeof(FpsRangesSupported)/sizeof(FpsRangesSupported[0]))
+
+
+typedef struct {
+ uint32_t aspect_ratio;
+ uint32_t width;
+ uint32_t height;
+} thumbnail_size_type;
+
+static thumbnail_size_type thumbnail_sizes[] = {
+{ 7281, 512, 288 }, //1.777778
+{ 6826, 480, 288 }, //1.666667
+{ 6808, 256, 154 }, //1.66233
+{ 6144, 432, 288 }, //1.5
+{ 5461, 512, 384 }, //1.333333
+{ 5006, 352, 288 }, //1.222222
+{ 5461, 320, 240 }, //1.33333
+{ 5006, 176, 144 }, //1.222222
+
+};
+
+static struct camera_size_type zsl_picture_sizes[] = {
+ { 1024, 768}, // 1MP XGA
+ { 800, 600}, //SVGA
+ { 800, 480}, // WVGA
+ { 640, 480}, // VGA
+ { 352, 288}, //CIF
+ { 320, 240}, // QVGA
+ { 176, 144} // QCIF
+};
+
+static camera_size_type default_picture_sizes[] = {
+ { 4000, 3000}, // 12MP
+ { 3200, 2400}, // 8MP
+ { 2592, 1944}, // 5MP
+ { 2048, 1536}, // 3MP QXGA
+ { 1920, 1088}, //HD1080
+ { 1600, 1200}, // 2MP UXGA
+ { 1280, 768}, //WXGA
+ { 1280, 720}, //HD720
+ { 1024, 768}, // 1MP XGA
+ { 800, 600}, //SVGA
+ { 800, 480}, // WVGA
+ { 640, 480}, // VGA
+ { 352, 288}, //CIF
+ { 320, 240}, // QVGA
+ { 176, 144} // QCIF
+};
+
+static int iso_speed_values[] = {
+ 0, 1, 100, 200, 400, 800, 1600
+};
+
+extern int HAL_numOfCameras;
+extern camera_info_t HAL_cameraInfo[MSM_MAX_CAMERA_SENSORS];
+extern mm_camera_t * HAL_camerahandle[MSM_MAX_CAMERA_SENSORS];
+
+namespace android {
+
+static uint32_t HFR_SIZE_COUNT=2;
+static const int PICTURE_FORMAT_JPEG = 1;
+static const int PICTURE_FORMAT_RAW = 2;
+
+/********************************************************************/
+static const str_map effects[] = {
+ { CameraParameters::EFFECT_NONE, CAMERA_EFFECT_OFF },
+ { CameraParameters::EFFECT_MONO, CAMERA_EFFECT_MONO },
+ { CameraParameters::EFFECT_NEGATIVE, CAMERA_EFFECT_NEGATIVE },
+ { CameraParameters::EFFECT_SOLARIZE, CAMERA_EFFECT_SOLARIZE },
+ { CameraParameters::EFFECT_SEPIA, CAMERA_EFFECT_SEPIA },
+ { CameraParameters::EFFECT_POSTERIZE, CAMERA_EFFECT_POSTERIZE },
+ { CameraParameters::EFFECT_WHITEBOARD, CAMERA_EFFECT_WHITEBOARD },
+ { CameraParameters::EFFECT_BLACKBOARD, CAMERA_EFFECT_BLACKBOARD },
+ { CameraParameters::EFFECT_AQUA, CAMERA_EFFECT_AQUA },
+ { CameraParameters::EFFECT_EMBOSS, CAMERA_EFFECT_EMBOSS },
+ { CameraParameters::EFFECT_SKETCH, CAMERA_EFFECT_SKETCH },
+ { CameraParameters::EFFECT_NEON, CAMERA_EFFECT_NEON }
+};
+
+static const str_map iso[] = {
+ { CameraParameters::ISO_AUTO, CAMERA_ISO_AUTO},
+ { CameraParameters::ISO_HJR, CAMERA_ISO_DEBLUR},
+ { CameraParameters::ISO_100, CAMERA_ISO_100},
+ { CameraParameters::ISO_200, CAMERA_ISO_200},
+ { CameraParameters::ISO_400, CAMERA_ISO_400},
+ { CameraParameters::ISO_800, CAMERA_ISO_800 },
+ { CameraParameters::ISO_1600, CAMERA_ISO_1600 }
+};
+
+static const str_map scenemode[] = {
+ { CameraParameters::SCENE_MODE_AUTO, CAMERA_BESTSHOT_OFF },
+ { CameraParameters::SCENE_MODE_ASD, CAMERA_BESTSHOT_AUTO },
+ { CameraParameters::SCENE_MODE_ACTION, CAMERA_BESTSHOT_ACTION },
+ { CameraParameters::SCENE_MODE_PORTRAIT, CAMERA_BESTSHOT_PORTRAIT },
+ { CameraParameters::SCENE_MODE_LANDSCAPE, CAMERA_BESTSHOT_LANDSCAPE },
+ { CameraParameters::SCENE_MODE_NIGHT, CAMERA_BESTSHOT_NIGHT },
+ { CameraParameters::SCENE_MODE_NIGHT_PORTRAIT, CAMERA_BESTSHOT_NIGHT_PORTRAIT },
+ { CameraParameters::SCENE_MODE_THEATRE, CAMERA_BESTSHOT_THEATRE },
+ { CameraParameters::SCENE_MODE_BEACH, CAMERA_BESTSHOT_BEACH },
+ { CameraParameters::SCENE_MODE_SNOW, CAMERA_BESTSHOT_SNOW },
+ { CameraParameters::SCENE_MODE_SUNSET, CAMERA_BESTSHOT_SUNSET },
+ { CameraParameters::SCENE_MODE_STEADYPHOTO, CAMERA_BESTSHOT_ANTISHAKE },
+ { CameraParameters::SCENE_MODE_FIREWORKS , CAMERA_BESTSHOT_FIREWORKS },
+ { CameraParameters::SCENE_MODE_SPORTS , CAMERA_BESTSHOT_SPORTS },
+ { CameraParameters::SCENE_MODE_PARTY, CAMERA_BESTSHOT_PARTY },
+ { CameraParameters::SCENE_MODE_CANDLELIGHT, CAMERA_BESTSHOT_CANDLELIGHT },
+ { CameraParameters::SCENE_MODE_BACKLIGHT, CAMERA_BESTSHOT_BACKLIGHT },
+ { CameraParameters::SCENE_MODE_FLOWERS, CAMERA_BESTSHOT_FLOWERS },
+ { CameraParameters::SCENE_MODE_AR, CAMERA_BESTSHOT_AR },
+};
+
+static const str_map scenedetect[] = {
+ { CameraParameters::SCENE_DETECT_OFF, FALSE },
+ { CameraParameters::SCENE_DETECT_ON, TRUE },
+};
+
+#define DONT_CARE AF_MODE_MAX
+static const str_map focus_modes[] = {
+ { CameraParameters::FOCUS_MODE_AUTO, AF_MODE_AUTO},
+ { CameraParameters::FOCUS_MODE_INFINITY, AF_MODE_INFINITY },
+ { CameraParameters::FOCUS_MODE_NORMAL, AF_MODE_NORMAL },
+ { CameraParameters::FOCUS_MODE_MACRO, AF_MODE_MACRO },
+ { CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE, AF_MODE_CAF},
+ { CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO, AF_MODE_CAF }
+};
+
+static const str_map selectable_zone_af[] = {
+ { CameraParameters::SELECTABLE_ZONE_AF_AUTO, AUTO },
+ { CameraParameters::SELECTABLE_ZONE_AF_SPOT_METERING, SPOT },
+ { CameraParameters::SELECTABLE_ZONE_AF_CENTER_WEIGHTED, CENTER_WEIGHTED },
+ { CameraParameters::SELECTABLE_ZONE_AF_FRAME_AVERAGE, AVERAGE }
+};
+
+// from qcamera/common/camera.h
+static const str_map autoexposure[] = {
+ { CameraParameters::AUTO_EXPOSURE_FRAME_AVG, CAMERA_AEC_FRAME_AVERAGE },
+ { CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED, CAMERA_AEC_CENTER_WEIGHTED },
+ { CameraParameters::AUTO_EXPOSURE_SPOT_METERING, CAMERA_AEC_SPOT_METERING }
+};
+
+// from aeecamera.h
+static const str_map whitebalance[] = {
+ { CameraParameters::WHITE_BALANCE_AUTO, CAMERA_WB_AUTO },
+ { CameraParameters::WHITE_BALANCE_INCANDESCENT, CAMERA_WB_INCANDESCENT },
+ { CameraParameters::WHITE_BALANCE_FLUORESCENT, CAMERA_WB_FLUORESCENT },
+ { CameraParameters::WHITE_BALANCE_DAYLIGHT, CAMERA_WB_DAYLIGHT },
+ { CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT, CAMERA_WB_CLOUDY_DAYLIGHT }
+};
+
+static const str_map antibanding[] = {
+ { CameraParameters::ANTIBANDING_OFF, CAMERA_ANTIBANDING_OFF },
+ { CameraParameters::ANTIBANDING_50HZ, CAMERA_ANTIBANDING_50HZ },
+ { CameraParameters::ANTIBANDING_60HZ, CAMERA_ANTIBANDING_60HZ },
+ { CameraParameters::ANTIBANDING_AUTO, CAMERA_ANTIBANDING_AUTO }
+};
+
+static const str_map frame_rate_modes[] = {
+ {CameraParameters::KEY_PREVIEW_FRAME_RATE_AUTO_MODE, FPS_MODE_AUTO},
+ {CameraParameters::KEY_PREVIEW_FRAME_RATE_FIXED_MODE, FPS_MODE_FIXED}
+};
+
+static const str_map touchafaec[] = {
+ { CameraParameters::TOUCH_AF_AEC_OFF, FALSE },
+ { CameraParameters::TOUCH_AF_AEC_ON, TRUE }
+};
+
+static const str_map hfr[] = {
+ { CameraParameters::VIDEO_HFR_OFF, CAMERA_HFR_MODE_OFF },
+ { CameraParameters::VIDEO_HFR_2X, CAMERA_HFR_MODE_60FPS },
+ { CameraParameters::VIDEO_HFR_3X, CAMERA_HFR_MODE_90FPS },
+ { CameraParameters::VIDEO_HFR_4X, CAMERA_HFR_MODE_120FPS },
+};
+static const int HFR_VALUES_COUNT = (sizeof(hfr)/sizeof(str_map));
+
+static const str_map flash[] = {
+ { CameraParameters::FLASH_MODE_OFF, LED_MODE_OFF },
+ { CameraParameters::FLASH_MODE_AUTO, LED_MODE_AUTO },
+ { CameraParameters::FLASH_MODE_ON, LED_MODE_ON },
+ { CameraParameters::FLASH_MODE_TORCH, LED_MODE_TORCH}
+};
+
+static const str_map lensshade[] = {
+ { CameraParameters::LENSSHADE_ENABLE, TRUE },
+ { CameraParameters::LENSSHADE_DISABLE, FALSE }
+};
+
+static const str_map mce[] = {
+ { CameraParameters::MCE_ENABLE, TRUE },
+ { CameraParameters::MCE_DISABLE, FALSE }
+};
+
+static const str_map histogram[] = {
+ { CameraParameters::HISTOGRAM_ENABLE, TRUE },
+ { CameraParameters::HISTOGRAM_DISABLE, FALSE }
+};
+
+static const str_map skinToneEnhancement[] = {
+ { CameraParameters::SKIN_TONE_ENHANCEMENT_ENABLE, TRUE },
+ { CameraParameters::SKIN_TONE_ENHANCEMENT_DISABLE, FALSE }
+};
+
+static const str_map denoise[] = {
+ { CameraParameters::DENOISE_OFF, FALSE },
+ { CameraParameters::DENOISE_ON, TRUE }
+};
+
+static const str_map facedetection[] = {
+ { CameraParameters::FACE_DETECTION_OFF, FALSE },
+ { CameraParameters::FACE_DETECTION_ON, TRUE }
+};
+
+static const str_map redeye_reduction[] = {
+ { CameraParameters::REDEYE_REDUCTION_ENABLE, TRUE },
+ { CameraParameters::REDEYE_REDUCTION_DISABLE, FALSE }
+};
+
+static const str_map picture_formats[] = {
+ {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
+ {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
+};
+
+static const str_map recording_Hints[] = {
+ {"false", FALSE},
+ {"true", TRUE}
+};
+
+static const str_map preview_formats[] = {
+ {CameraParameters::PIXEL_FORMAT_YUV420SP, HAL_PIXEL_FORMAT_YCrCb_420_SP},
+ {CameraParameters::PIXEL_FORMAT_YUV420SP_ADRENO, HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO},
+ {CameraParameters::PIXEL_FORMAT_YV12, HAL_PIXEL_FORMAT_YV12},
+ {CameraParameters::PIXEL_FORMAT_YUV420P,HAL_PIXEL_FORMAT_YV12},
+ {CameraParameters::PIXEL_FORMAT_NV12, HAL_PIXEL_FORMAT_YCbCr_420_SP}
+};
+
+static const preview_format_info_t preview_format_info_list[] = {
+ {HAL_PIXEL_FORMAT_YCrCb_420_SP, CAMERA_YUV_420_NV21, CAMERA_PAD_TO_WORD, 2},
+ {HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO, CAMERA_YUV_420_NV21, CAMERA_PAD_TO_4K, 2},
+ {HAL_PIXEL_FORMAT_YCbCr_420_SP, CAMERA_YUV_420_NV12, CAMERA_PAD_TO_WORD, 2},
+ {HAL_PIXEL_FORMAT_YV12, CAMERA_YUV_420_YV12, CAMERA_PAD_TO_WORD, 3}
+};
+
+static const str_map zsl_modes[] = {
+ { CameraParameters::ZSL_OFF, FALSE },
+ { CameraParameters::ZSL_ON, TRUE },
+};
+
+
+static const str_map hdr_bracket[] = {
+ { CameraParameters::AE_BRACKET_HDR_OFF,HDR_BRACKETING_OFF},
+ { CameraParameters::AE_BRACKET_HDR,HDR_MODE },
+ { CameraParameters::AE_BRACKET,EXP_BRACKETING_MODE }
+};
+
+typedef enum {
+ NORMAL_POWER,
+ LOW_POWER
+} power_mode;
+
+static const str_map power_modes[] = {
+ { CameraParameters::NORMAL_POWER,NORMAL_POWER },
+ { CameraParameters::LOW_POWER,LOW_POWER }
+};
+
+/**************************************************************************/
+static int attr_lookup(const str_map arr[], int len, const char *name)
+{
+ if (name) {
+ for (int i = 0; i < len; i++) {
+ if (!strcmp(arr[i].desc, name))
+ return arr[i].val;
+ }
+ }
+ return NOT_FOUND;
+}
+
+bool QCameraHardwareInterface::native_set_parms(
+ mm_camera_parm_type_t type, uint16_t length, void *value)
+{
+ LOGE("%s : type : %d Value : %d",__func__,type,*((int *)value));
+ if(MM_CAMERA_OK != cam_config_set_parm(mCameraId, type,value )) {
+ LOGE("native_set_parms failed: type %d length %d error %s",
+ type, length, strerror(errno));
+ return false;
+ }
+
+ return true;
+
+}
+
+bool QCameraHardwareInterface::native_set_parms(
+ mm_camera_parm_type_t type, uint16_t length, void *value, int *result)
+{
+ *result= cam_config_set_parm(mCameraId, type,value );
+ if(MM_CAMERA_OK == *result) {
+ LOGE("native_set_parms: succeeded : %d", *result);
+ return true;
+ }
+
+ LOGE("native_set_parms failed: type %d length %d error str %s error# %d",
+ type, length, strerror(errno), errno);
+ return false;
+}
+
+//Filter Picture sizes based on max width and height
+/* TBD: do we still need this - except for ZSL? */
+void QCameraHardwareInterface::filterPictureSizes(){
+ unsigned int i;
+ if(mPictureSizeCount <= 0)
+ return;
+ maxSnapshotWidth = mPictureSizes[0].width;
+ maxSnapshotHeight = mPictureSizes[0].height;
+ // Iterate through all the width and height to find the max value
+ for(i =0; i<mPictureSizeCount;i++){
+ if(((maxSnapshotWidth < mPictureSizes[i].width) &&
+ (maxSnapshotHeight <= mPictureSizes[i].height))){
+ maxSnapshotWidth = mPictureSizes[i].width;
+ maxSnapshotHeight = mPictureSizes[i].height;
+ }
+ }
+ if(myMode & CAMERA_ZSL_MODE){
+ // due to lack of PMEM we restrict to lower resolution
+ mPictureSizesPtr = zsl_picture_sizes;
+ mSupportedPictureSizesCount = 7;
+ }else{
+ mPictureSizesPtr = mPictureSizes;
+ mSupportedPictureSizesCount = mPictureSizeCount;
+ }
+}
+
+static String8 create_sizes_str(const camera_size_type *sizes, int len) {
+ String8 str;
+ char buffer[32];
+
+ if (len > 0) {
+ snprintf(buffer, sizeof(buffer), "%dx%d", sizes[0].width, sizes[0].height);
+ str.append(buffer);
+ }
+ for (int i = 1; i < len; i++) {
+ snprintf(buffer, sizeof(buffer), ",%dx%d", sizes[i].width, sizes[i].height);
+ str.append(buffer);
+ }
+ return str;
+}
+
+String8 QCameraHardwareInterface::create_values_str(const str_map *values, int len) {
+ String8 str;
+
+ if (len > 0) {
+ str.append(values[0].desc);
+ }
+ for (int i = 1; i < len; i++) {
+ str.append(",");
+ str.append(values[i].desc);
+ }
+ return str;
+}
+
+static String8 create_fps_str(const android:: FPSRange* fps, int len) {
+ String8 str;
+ char buffer[32];
+
+ if (len > 0) {
+ snprintf(buffer, sizeof(buffer), "(%d,%d)", fps[0].minFPS, fps[0].maxFPS);
+ str.append(buffer);
+ }
+ for (int i = 1; i < len; i++) {
+ snprintf(buffer, sizeof(buffer), ",(%d,%d)", fps[i].minFPS, fps[i].maxFPS);
+ str.append(buffer);
+ }
+ return str;
+}
+
+static String8 create_values_range_str(int min, int max){
+ String8 str;
+ char buffer[32];
+
+ if(min <= max){
+ snprintf(buffer, sizeof(buffer), "%d", min);
+ str.append(buffer);
+
+ for (int i = min + 1; i <= max; i++) {
+ snprintf(buffer, sizeof(buffer), ",%d", i);
+ str.append(buffer);
+ }
+ }
+ return str;
+}
+
+static int parse_size(const char *str, int &width, int &height)
+{
+ // Find the width.
+ char *end;
+ int w = (int)strtol(str, &end, 10);
+ // If an 'x' or 'X' does not immediately follow, give up.
+ if ( (*end != 'x') && (*end != 'X') )
+ return -1;
+
+ // Find the height, immediately after the 'x'.
+ int h = (int)strtol(end+1, 0, 10);
+
+ width = w;
+ height = h;
+
+ return 0;
+}
+
+bool QCameraHardwareInterface::isValidDimension(int width, int height) {
+ bool retVal = FALSE;
+ /* This function checks if a given resolution is valid or not.
+ * A particular resolution is considered valid if it satisfies
+ * the following conditions:
+ * 1. width & height should be multiple of 16.
+ * 2. width & height should be less than/equal to the dimensions
+ * supported by the camera sensor.
+ * 3. the aspect ratio is a valid aspect ratio and is among the
+ * commonly used aspect ratio as determined by the thumbnail_sizes
+ * data structure.
+ */
+
+ if( (width == CEILING16(width)) && (height == CEILING16(height))
+ && (width <= maxSnapshotWidth)
+ && (height <= maxSnapshotHeight) )
+ {
+ uint32_t pictureAspectRatio = (uint32_t)((width * Q12)/height);
+ for(uint32_t i = 0; i < THUMBNAIL_SIZE_COUNT; i++ ) {
+ if(thumbnail_sizes[i].aspect_ratio == pictureAspectRatio) {
+ retVal = TRUE;
+ break;
+ }
+ }
+ }
+ return retVal;
+}
+
+void QCameraHardwareInterface::hasAutoFocusSupport(){
+
+ LOGV("%s",__func__);
+
+ if(isZSLMode()){
+ mHasAutoFocusSupport = false;
+ return;
+ }
+
+ if(cam_ops_is_op_supported (mCameraId, MM_CAMERA_OPS_FOCUS )) {
+ mHasAutoFocusSupport = true;
+ }
+ else {
+ LOGE("AutoFocus is not supported");
+ mHasAutoFocusSupport = false;
+ }
+
+ LOGV("%s:rc= %d",__func__, mHasAutoFocusSupport);
+
+}
+
+bool QCameraHardwareInterface::supportsSceneDetection() {
+ bool rc = cam_config_is_parm_supported(mCameraId,MM_CAMERA_PARM_ASD_ENABLE);
+ return rc;
+}
+
+bool QCameraHardwareInterface::supportsFaceDetection() {
+ bool rc = cam_config_is_parm_supported(mCameraId,MM_CAMERA_PARM_FD);
+ return rc;
+}
+
+bool QCameraHardwareInterface::supportsSelectableZoneAf() {
+ bool rc = cam_config_is_parm_supported(mCameraId,MM_CAMERA_PARM_FOCUS_RECT);
+ return rc;
+}
+
+bool QCameraHardwareInterface::supportsRedEyeReduction() {
+ bool rc = cam_config_is_parm_supported(mCameraId,MM_CAMERA_PARM_REDEYE_REDUCTION);
+ return rc;
+}
+
+static String8 create_str(int16_t *arr, int length){
+ String8 str;
+ char buffer[32] = {0};
+
+ if(length > 0){
+ snprintf(buffer, sizeof(buffer), "%d", arr[0]);
+ str.append(buffer);
+ }
+
+ for (int i =1;i<length;i++){
+ snprintf(buffer, sizeof(buffer), ",%d",arr[i]);
+ str.append(buffer);
+ }
+ return str;
+}
+
+bool QCameraHardwareInterface::getMaxPictureDimension(mm_camera_dimension_t *maxDim)
+{
+ bool ret = NO_ERROR;
+ mm_camera_dimension_t dim;
+
+ ret = cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_MAX_PICTURE_SIZE, &dim);
+ if (ret != NO_ERROR)
+ return ret;
+
+ /* Find the first dimension in the mPictureSizes
+ * array which is smaller than the max dimension.
+ * This will be the valid max picture resolution */
+ for (unsigned int i = 0; i < mPictureSizeCount; i++) {
+ if ((mPictureSizes[i].width <= dim.width) &&
+ (mPictureSizes[i].height <= dim.height)) {
+ maxDim->height = mPictureSizes[i].height;
+ maxDim->width = mPictureSizes[i].width;
+ break;
+ }
+ }
+ LOGD("%s: Found Max Picture dimension: %d x %d", __func__,
+ maxDim->width, maxDim->height);
+ return ret;
+}
+void QCameraHardwareInterface::loadTables()
+{
+
+ bool ret = NO_ERROR;
+ LOGE("%s: E", __func__);
+
+ ret = cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_PREVIEW_SIZES_CNT, &preview_sizes_count);
+
+ default_sizes_tbl_t preview_sizes_tbl;
+ preview_sizes_tbl.tbl_size=preview_sizes_count;
+ preview_sizes_tbl.sizes_tbl=&default_preview_sizes[0];
+ if(MM_CAMERA_OK != cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_DEF_PREVIEW_SIZES, &preview_sizes_tbl)){
+ LOGE("%s:Failed to get default preview sizes",__func__);
+ }
+ ret = cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_VIDEO_SIZES_CNT, &video_sizes_count);
+
+ default_sizes_tbl_t video_sizes_tbl;
+ video_sizes_tbl.tbl_size=video_sizes_count;
+ video_sizes_tbl.sizes_tbl=&default_video_sizes[0];
+ if(MM_CAMERA_OK != cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_DEF_VIDEO_SIZES, &video_sizes_tbl)){
+ LOGE("%s:Failed to get default video sizes",__func__);
+ }
+
+ ret = cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_THUMB_SIZES_CNT, &thumbnail_sizes_count);
+
+ default_sizes_tbl_t thumbnail_sizes_tbl;
+ thumbnail_sizes_tbl.tbl_size=thumbnail_sizes_count;
+ thumbnail_sizes_tbl.sizes_tbl=&default_thumbnail_sizes[0];
+ if(MM_CAMERA_OK != cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_DEF_THUMB_SIZES, &thumbnail_sizes_tbl)){
+ LOGE("%s:Failed to get default thumbnail sizes",__func__);
+ }
+
+ ret = cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_HFR_SIZES_CNT, &hfr_sizes_count);
+
+ default_sizes_tbl_t hfr_sizes_tbl;
+ hfr_sizes_tbl.tbl_size=hfr_sizes_count;
+ hfr_sizes_tbl.sizes_tbl=&default_hfr_sizes[0];
+ if(MM_CAMERA_OK != cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_DEF_HFR_SIZES, &hfr_sizes_tbl)){
+ LOGE("%s:Failed to get default HFR sizes",__func__);
+ }
+ LOGE("%s: X", __func__);
+}
+void QCameraHardwareInterface::initDefaultParameters()
+{
+ bool ret;
+ char prop[PROPERTY_VALUE_MAX];
+ mm_camera_dimension_t maxDim;
+ int rc = MM_CAMERA_OK;
+ LOGI("%s: E", __func__);
+
+ memset(&maxDim, 0, sizeof(mm_camera_dimension_t));
+ ret = getMaxPictureDimension(&maxDim);
+
+ if (ret != NO_ERROR) {
+ LOGE("%s: Cannot get Max picture size supported", __func__);
+ return;
+ }
+ if (!maxDim.width || !maxDim.height) {
+ maxDim.width = DEFAULT_LIVESHOT_WIDTH;
+ maxDim.height = DEFAULT_LIVESHOT_HEIGHT;
+ }
+
+ memset(prop, 0, sizeof(prop));
+ property_get("persist.camera.snap.format", prop, "0");
+ mSnapshotFormat = atoi(prop);
+ LOGV("%s: prop =(%s), snap_format=%d", __func__, prop, mSnapshotFormat);
+
+ //cam_ctrl_dimension_t dim;
+ mHFRLevel = 0;
+ memset(&mDimension, 0, sizeof(cam_ctrl_dimension_t));
+ memset(&mPreviewFormatInfo, 0, sizeof(preview_format_info_t));
+ mDimension.video_width = DEFAULT_VIDEO_WIDTH;
+ mDimension.video_height = DEFAULT_VIDEO_HEIGHT;
+ // mzhu mDimension.picture_width = DEFAULT_STREAM_WIDTH;
+ // mzhu mDimension.picture_height = DEFAULT_STREAM_HEIGHT;
+ mDimension.picture_width = maxDim.width;
+ mDimension.picture_height = maxDim.height;
+ mDimension.display_width = DEFAULT_STREAM_WIDTH;
+ mDimension.display_height = DEFAULT_STREAM_HEIGHT;
+ mDimension.orig_picture_dx = mDimension.picture_width;
+ mDimension.orig_picture_dy = mDimension.picture_height;
+ mDimension.ui_thumbnail_width = DEFAULT_STREAM_WIDTH;
+ mDimension.ui_thumbnail_height = DEFAULT_STREAM_HEIGHT;
+ mDimension.orig_video_width = DEFAULT_STREAM_WIDTH;
+ mDimension.orig_video_height = DEFAULT_STREAM_HEIGHT;
+
+ mDimension.prev_format = CAMERA_YUV_420_NV21;
+ mDimension.enc_format = CAMERA_YUV_420_NV12;
+ if (mSnapshotFormat == 1) {
+ mDimension.main_img_format = CAMERA_YUV_422_NV61;
+ } else {
+ mDimension.main_img_format = CAMERA_YUV_420_NV21;
+ }
+ mDimension.thumb_format = CAMERA_YUV_420_NV21;
+ LOGV("%s: main_img_format =%d, thumb_format=%d", __func__,
+ mDimension.main_img_format, mDimension.thumb_format);
+ mDimension.prev_padding_format = CAMERA_PAD_TO_WORD;
+
+ ret = native_set_parms(MM_CAMERA_PARM_DIMENSION,
+ sizeof(cam_ctrl_dimension_t), (void *) &mDimension);
+ if(!ret) {
+ LOGE("MM_CAMERA_PARM_DIMENSION Failed.");
+ return;
+ }
+
+ hasAutoFocusSupport();
+
+ // Initialize constant parameter strings. This will happen only once in the
+ // lifetime of the mediaserver process.
+ if (true/*!mParamStringInitialized*/) {
+ //filter picture sizes
+ filterPictureSizes();
+ mPictureSizeValues = create_sizes_str(
+ mPictureSizesPtr, mSupportedPictureSizesCount);
+ mPreviewSizeValues = create_sizes_str(
+ mPreviewSizes, mPreviewSizeCount);
+ mVideoSizeValues = create_sizes_str(
+ mVideoSizes, mVideoSizeCount);
+
+ //Query for max HFR value
+ camera_hfr_mode_t maxHFR;
+ cam_config_get_parm(mCameraId, MM_CAMERA_PARM_MAX_HFR_MODE, (void *)&maxHFR);
+ //Filter HFR values and build parameter string
+ String8 str;
+ for(int i=0; i<HFR_VALUES_COUNT; i++){
+ if(hfr[i].val <= maxHFR){
+ if(i>0) str.append(",");
+ str.append(hfr[i].desc);
+ }
+ }
+ mHfrValues = str;
+ mHfrSizeValues = create_sizes_str(
+ default_hfr_sizes, hfr_sizes_count);
+ mFpsRangesSupportedValues = create_fps_str(
+ FpsRangesSupported,FPS_RANGES_SUPPORTED_COUNT );
+ mParameters.set(
+ CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE,
+ mFpsRangesSupportedValues);
+ mParameters.setPreviewFpsRange(MINIMUM_FPS*1000,MAXIMUM_FPS*1000);
+ mFlashValues = create_values_str(
+ flash, sizeof(flash) / sizeof(str_map));
+ mLensShadeValues = create_values_str(
+ lensshade,sizeof(lensshade)/sizeof(str_map));
+ mMceValues = create_values_str(
+ mce,sizeof(mce)/sizeof(str_map));
+ mEffectValues = create_values_str(effects, sizeof(effects) / sizeof(str_map));
+ mAntibandingValues = create_values_str(
+ antibanding, sizeof(antibanding) / sizeof(str_map));
+ mIsoValues = create_values_str(iso,sizeof(iso)/sizeof(str_map));
+ mAutoExposureValues = create_values_str(
+ autoexposure, sizeof(autoexposure) / sizeof(str_map));
+ mWhitebalanceValues = create_values_str(
+ whitebalance, sizeof(whitebalance) / sizeof(str_map));
+
+ if(mHasAutoFocusSupport){
+ mFocusModeValues = create_values_str(
+ focus_modes, sizeof(focus_modes) / sizeof(str_map));
+ }
+
+ mSceneModeValues = create_values_str(scenemode, sizeof(scenemode) / sizeof(str_map));
+
+ if(mHasAutoFocusSupport){
+ mTouchAfAecValues = create_values_str(
+ touchafaec,sizeof(touchafaec)/sizeof(str_map));
+ }
+ //Currently Enabling Histogram for 8x60
+ mHistogramValues = create_values_str(
+ histogram,sizeof(histogram)/sizeof(str_map));
+
+ mSkinToneEnhancementValues = create_values_str(
+ skinToneEnhancement,sizeof(skinToneEnhancement)/sizeof(str_map));
+
+ mPictureFormatValues = create_values_str(
+ picture_formats, sizeof(picture_formats)/sizeof(str_map));
+
+ mZoomSupported=false;
+ mMaxZoom=0;
+ mm_camera_zoom_tbl_t zmt;
+ if(MM_CAMERA_OK != cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_MAXZOOM, &mMaxZoom)){
+ LOGE("%s:Failed to get max zoom",__func__);
+ }else{
+
+ LOGE("Max Zoom:%d",mMaxZoom);
+ /* Kernel driver limits the max amount of data that can be retreived through a control
+ command to 260 bytes hence we conservatively limit to 110 zoom ratios */
+ if(mMaxZoom>MAX_ZOOM_RATIOS) {
+ LOGE("%s:max zoom is larger than sizeof zoomRatios table",__func__);
+ mMaxZoom=MAX_ZOOM_RATIOS-1;
+ }
+ zmt.size=mMaxZoom;
+ zmt.zoom_ratio_tbl=&zoomRatios[0];
+ if(MM_CAMERA_OK != cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_ZOOM_RATIO, &zmt)){
+ LOGE("%s:Failed to get max zoom ratios",__func__);
+ }else{
+ mZoomSupported=true;
+ mZoomRatioValues = create_str(zoomRatios, mMaxZoom);
+ }
+ }
+
+ LOGE("Zoom supported:%d",mZoomSupported);
+
+ denoise_value = create_values_str(
+ denoise, sizeof(denoise) / sizeof(str_map));
+
+ if(supportsFaceDetection()) {
+ mFaceDetectionValues = create_values_str(
+ facedetection, sizeof(facedetection) / sizeof(str_map));
+ }
+
+ if(mHasAutoFocusSupport){
+ mSelectableZoneAfValues = create_values_str(
+ selectable_zone_af, sizeof(selectable_zone_af) / sizeof(str_map));
+ }
+
+ mSceneDetectValues = create_values_str(scenedetect, sizeof(scenedetect) / sizeof(str_map));
+
+ mRedeyeReductionValues = create_values_str(
+ redeye_reduction, sizeof(redeye_reduction) / sizeof(str_map));
+
+ mZslValues = create_values_str(
+ zsl_modes,sizeof(zsl_modes)/sizeof(str_map));
+
+ mParamStringInitialized = true;
+ }
+
+ //set supported video sizes
+ mParameters.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES, mVideoSizeValues.string());
+
+ //set default video size to first one in supported table
+ String8 vSize = create_sizes_str(&mVideoSizes[0], 1);
+ mParameters.set(CameraParameters::KEY_VIDEO_SIZE, vSize.string());
+
+ //Set Preview size
+ int default_preview_width, default_preview_height;
+ cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DEFAULT_PREVIEW_WIDTH,
+ &default_preview_width);
+ cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DEFAULT_PREVIEW_HEIGHT,
+ &default_preview_height);
+ mParameters.setPreviewSize(default_preview_width, default_preview_height);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
+ mPreviewSizeValues.string());
+ mDimension.display_width = default_preview_width;
+ mDimension.display_height = default_preview_height;
+
+ //Set Preview Frame Rate
+ if(mFps >= MINIMUM_FPS && mFps <= MAXIMUM_FPS) {
+ mPreviewFrameRateValues = create_values_range_str(
+ MINIMUM_FPS, mFps);
+ }else{
+ mPreviewFrameRateValues = create_values_range_str(
+ MINIMUM_FPS, MAXIMUM_FPS);
+ }
+
+
+ if (cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_FPS)) {
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES,
+ mPreviewFrameRateValues.string());
+ } else {
+ mParameters.set(
+ CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES,
+ DEFAULT_FIXED_FPS);
+ }
+
+ //Set Preview Frame Rate Modes
+ mParameters.setPreviewFrameRateMode("frame-rate-auto");
+ mFrameRateModeValues = create_values_str(
+ frame_rate_modes, sizeof(frame_rate_modes) / sizeof(str_map));
+ if(cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_FPS_MODE)){
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATE_MODES,
+ mFrameRateModeValues.string());
+ }
+
+ //Set Preview Format
+ //mParameters.setPreviewFormat("yuv420sp"); // informative
+ mParameters.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP);
+
+ mPreviewFormatValues = create_values_str(
+ preview_formats, sizeof(preview_formats) / sizeof(str_map));
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
+ mPreviewFormatValues.string());
+
+ //Set Overlay Format
+ mParameters.set("overlay-format", HAL_PIXEL_FORMAT_YCbCr_420_SP);
+ mParameters.set("max-num-detected-faces-hw", "2");
+
+ //Set Picture Size
+ mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
+ mPictureSizeValues.string());
+
+ //Set Preview Frame Rate
+ if(mFps >= MINIMUM_FPS && mFps <= MAXIMUM_FPS) {
+ mParameters.setPreviewFrameRate(mFps);
+ }else{
+ mParameters.setPreviewFrameRate(DEFAULT_FPS);
+ }
+
+ //Set Picture Format
+ mParameters.setPictureFormat("jpeg"); // informative
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
+ mPictureFormatValues);
+
+ mParameters.set(CameraParameters::KEY_JPEG_QUALITY, "85"); // max quality
+ mJpegQuality = 85;
+ //Set Video Format
+ mParameters.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT, "yuv420sp");
+
+ //Set Thumbnail parameters
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
+ THUMBNAIL_WIDTH_STR); // informative
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
+ THUMBNAIL_HEIGHT_STR); // informative
+ mDimension.ui_thumbnail_width =
+ thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].width;
+ mDimension.ui_thumbnail_height =
+ thumbnail_sizes[DEFAULT_THUMBNAIL_SETTING].height;
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "90");
+ String8 valuesStr = create_sizes_str(default_thumbnail_sizes, thumbnail_sizes_count);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES,
+ valuesStr.string());
+ // Define CAMERA_SMOOTH_ZOOM in Android.mk file , to enable smoothzoom
+#ifdef CAMERA_SMOOTH_ZOOM
+ mParameters.set(CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED, "true");
+#endif
+ if(mZoomSupported){
+ mParameters.set(CameraParameters::KEY_ZOOM_SUPPORTED, "true");
+ LOGE("max zoom is %d", mMaxZoom-1);
+ /* mMaxZoom value that the query interface returns is the size
+ LOGV("max zoom is %d", mMaxZoom-1);
+ * mMaxZoom value that the query interface returns is the size
+ * of zoom table. So the actual max zoom value will be one
+ * less than that value. */
+
+ mParameters.set("max-zoom",mMaxZoom-1);
+ mParameters.set(CameraParameters::KEY_ZOOM_RATIOS,
+ mZoomRatioValues);
+ } else
+ {
+ mParameters.set(CameraParameters::KEY_ZOOM_SUPPORTED, "false");
+ }
+
+ /* Enable zoom support for video application if VPE enabled */
+ if(mZoomSupported) {
+ mParameters.set("video-zoom-support", "true");
+ } else {
+ mParameters.set("video-zoom-support", "false");
+ }
+
+ //8960 supports Power modes : Low power, Normal Power.
+ mParameters.set("power-mode-supported", "true");
+ //Set Live shot support
+ rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_LIVESHOT_MAIN);
+ if(!rc) {
+ LOGE("%s:LIVESHOT is not supported", __func__);
+ mParameters.set("video-snapshot-supported", "false");
+ } else {
+ mParameters.set("video-snapshot-supported", "true");
+ }
+
+ //Set default power mode
+ mParameters.set(CameraParameters::KEY_POWER_MODE,"Normal_Power");
+
+ //Set Camera Mode
+ mParameters.set(CameraParameters::KEY_CAMERA_MODE,0);
+ mParameters.set(CameraParameters::KEY_AE_BRACKET_HDR,"Off");
+
+ //Set Antibanding
+ mParameters.set(CameraParameters::KEY_ANTIBANDING,
+ CameraParameters::ANTIBANDING_OFF);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
+ mAntibandingValues);
+
+ //Set Effect
+ mParameters.set(CameraParameters::KEY_EFFECT,
+ CameraParameters::EFFECT_NONE);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_EFFECTS, mEffectValues);
+
+ //Set Auto Exposure
+ mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE,
+ CameraParameters::AUTO_EXPOSURE_FRAME_AVG);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE, mAutoExposureValues);
+
+ //Set WhiteBalance
+ mParameters.set(CameraParameters::KEY_WHITE_BALANCE,
+ CameraParameters::WHITE_BALANCE_AUTO);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,mWhitebalanceValues);
+
+ //Set AEC_LOCK
+ mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK, "false");
+ if(cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_AEC_LOCK)){
+ mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED, "true");
+ } else {
+ mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED, "false");
+ }
+ //Set AWB_LOCK
+ mParameters.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, "false");
+ if(cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_AWB_LOCK))
+ mParameters.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED, "true");
+ else
+ mParameters.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED, "false");
+
+ //Set Focus Mode
+ if(mHasAutoFocusSupport){
+ mParameters.set(CameraParameters::KEY_FOCUS_MODE,
+ CameraParameters::FOCUS_MODE_AUTO);
+ mFocusMode = AF_MODE_AUTO;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
+ mFocusModeValues);
+ mParameters.set(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS, "1");
+ mParameters.set(CameraParameters::KEY_MAX_NUM_METERING_AREAS, "1");
+ } else {
+ mParameters.set(CameraParameters::KEY_FOCUS_MODE,
+ CameraParameters::FOCUS_MODE_INFINITY);
+ mFocusMode = DONT_CARE;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
+ CameraParameters::FOCUS_MODE_INFINITY);
+ mParameters.set(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS, "0");
+ mParameters.set(CameraParameters::KEY_MAX_NUM_METERING_AREAS, "0");
+ }
+
+ mParameters.set(CameraParameters::KEY_FOCUS_AREAS, DEFAULT_CAMERA_AREA);
+ mParameters.set(CameraParameters::KEY_METERING_AREAS, DEFAULT_CAMERA_AREA);
+
+ //Set Flash
+ if (cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_LED_MODE)) {
+ mParameters.set(CameraParameters::KEY_FLASH_MODE,
+ CameraParameters::FLASH_MODE_OFF);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
+ mFlashValues);
+ }
+
+ //Set Sharpness
+ mParameters.set(CameraParameters::KEY_MAX_SHARPNESS,
+ CAMERA_MAX_SHARPNESS);
+ mParameters.set(CameraParameters::KEY_SHARPNESS,
+ CAMERA_DEF_SHARPNESS);
+
+ //Set Contrast
+ mParameters.set(CameraParameters::KEY_MAX_CONTRAST,
+ CAMERA_MAX_CONTRAST);
+ mParameters.set(CameraParameters::KEY_CONTRAST,
+ CAMERA_DEF_CONTRAST);
+
+ //Set Saturation
+ mParameters.set(CameraParameters::KEY_MAX_SATURATION,
+ CAMERA_MAX_SATURATION);
+ mParameters.set(CameraParameters::KEY_SATURATION,
+ CAMERA_DEF_SATURATION);
+
+ //Set Brightness/luma-adaptaion
+ mParameters.set("luma-adaptation", "3");
+
+ mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
+ CameraParameters::PIXEL_FORMAT_JPEG);
+
+ //Set Lensshading
+ mParameters.set(CameraParameters::KEY_LENSSHADE,
+ CameraParameters::LENSSHADE_ENABLE);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES,
+ mLensShadeValues);
+
+ //Set ISO Mode
+ mParameters.set(CameraParameters::KEY_ISO_MODE,
+ CameraParameters::ISO_AUTO);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_ISO_MODES,
+ mIsoValues);
+
+ //Set MCE
+ mParameters.set(CameraParameters::KEY_MEMORY_COLOR_ENHANCEMENT,
+ CameraParameters::MCE_ENABLE);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_MEM_COLOR_ENHANCE_MODES,
+ mMceValues);
+ //Set HFR
+ if (cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_HFR)) {
+ mParameters.set(CameraParameters::KEY_VIDEO_HIGH_FRAME_RATE,
+ CameraParameters::VIDEO_HFR_OFF);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_HFR_SIZES,
+ mHfrSizeValues.string());
+ mParameters.set(CameraParameters::KEY_SUPPORTED_VIDEO_HIGH_FRAME_RATE_MODES,
+ mHfrValues);
+ } else{
+ mParameters.set(CameraParameters::KEY_SUPPORTED_HFR_SIZES,"");
+ }
+
+ //Set Histogram
+ mParameters.set(CameraParameters::KEY_HISTOGRAM,
+ CameraParameters::HISTOGRAM_DISABLE);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_HISTOGRAM_MODES,
+ mHistogramValues);
+
+ //Set SkinTone Enhancement
+ mParameters.set(CameraParameters::KEY_SKIN_TONE_ENHANCEMENT,
+ CameraParameters::SKIN_TONE_ENHANCEMENT_DISABLE);
+ mParameters.set("skinToneEnhancement", "0");
+ mParameters.set(CameraParameters::KEY_SUPPORTED_SKIN_TONE_ENHANCEMENT_MODES,
+ mSkinToneEnhancementValues);
+
+ //Set Scene Mode
+ mParameters.set(CameraParameters::KEY_SCENE_MODE,
+ CameraParameters::SCENE_MODE_AUTO);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES,
+ mSceneModeValues);
+
+ //Set Streaming Textures
+ mParameters.set("strtextures", "OFF");
+
+ //Set Denoise
+ mParameters.set(CameraParameters::KEY_DENOISE,
+ CameraParameters::DENOISE_OFF);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_DENOISE,
+ denoise_value);
+ //Set Touch AF/AEC
+ mParameters.set(CameraParameters::KEY_TOUCH_AF_AEC,
+ CameraParameters::TOUCH_AF_AEC_OFF);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_TOUCH_AF_AEC,
+ mTouchAfAecValues);
+ mParameters.set("touchAfAec-dx","100");
+ mParameters.set("touchAfAec-dy","100");
+
+ //Set Scene Detection
+ mParameters.set(CameraParameters::KEY_SCENE_DETECT,
+ CameraParameters::SCENE_DETECT_OFF);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_SCENE_DETECT,
+ mSceneDetectValues);
+
+ //Set Selectable Zone AF
+ mParameters.set(CameraParameters::KEY_SELECTABLE_ZONE_AF,
+ CameraParameters::SELECTABLE_ZONE_AF_AUTO);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_SELECTABLE_ZONE_AF,
+ mSelectableZoneAfValues);
+
+ //Set Face Detection
+ mParameters.set(CameraParameters::KEY_FACE_DETECTION,
+ CameraParameters::FACE_DETECTION_OFF);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FACE_DETECTION,
+ mFaceDetectionValues);
+
+ //Set Red Eye Reduction
+ mParameters.set(CameraParameters::KEY_REDEYE_REDUCTION,
+ CameraParameters::REDEYE_REDUCTION_DISABLE);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_REDEYE_REDUCTION,
+ mRedeyeReductionValues);
+
+ //Set ZSL
+ mParameters.set(CameraParameters::KEY_ZSL,
+ CameraParameters::ZSL_OFF);
+ mParameters.set(CameraParameters::KEY_SUPPORTED_ZSL_MODES,
+ mZslValues);
+
+ //Set Focal length, horizontal and vertical view angles
+ float focalLength = 0.0f;
+ float horizontalViewAngle = 0.0f;
+ float verticalViewAngle = 0.0f;
+ cam_config_get_parm(mCameraId, MM_CAMERA_PARM_FOCAL_LENGTH,
+ (void *)&focalLength);
+ mParameters.setFloat(CameraParameters::KEY_FOCAL_LENGTH,
+ focalLength);
+ cam_config_get_parm(mCameraId, MM_CAMERA_PARM_HORIZONTAL_VIEW_ANGLE,
+ (void *)&horizontalViewAngle);
+ mParameters.setFloat(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE,
+ horizontalViewAngle);
+ cam_config_get_parm(mCameraId, MM_CAMERA_PARM_VERTICAL_VIEW_ANGLE,
+ (void *)&verticalViewAngle);
+ mParameters.setFloat(CameraParameters::KEY_VERTICAL_VIEW_ANGLE,
+ verticalViewAngle);
+
+ //Set Exposure Compensation
+ mParameters.set(
+ CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION,
+ EXPOSURE_COMPENSATION_MAXIMUM_NUMERATOR);
+ mParameters.set(
+ CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION,
+ EXPOSURE_COMPENSATION_MINIMUM_NUMERATOR);
+ mParameters.set(
+ CameraParameters::KEY_EXPOSURE_COMPENSATION,
+ EXPOSURE_COMPENSATION_DEFAULT_NUMERATOR);
+ mParameters.setFloat(
+ CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP,
+ EXPOSURE_COMPENSATION_STEP);
+
+ mParameters.set("num-snaps-per-shutter", 1);
+
+ mParameters.set("capture-burst-captures-values", getZSLQueueDepth());
+ mParameters.set("capture-burst-interval-supported", "true");
+ mParameters.set("capture-burst-interval-max", BURST_INTREVAL_MAX); /*skip frames*/
+ mParameters.set("capture-burst-interval-min", BURST_INTREVAL_MIN); /*skip frames*/
+ mParameters.set("capture-burst-interval", BURST_INTREVAL_DEFAULT); /*skip frames*/
+ mParameters.set("capture-burst-retroactive", 0);
+ mParameters.set("capture-burst-retroactive-max", getZSLQueueDepth());
+ mParameters.set("capture-burst-exposures", "");
+ mParameters.set("capture-burst-exposures-values",
+ "-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11,12");
+ {
+ String8 CamModeStr;
+ char buffer[32];
+ int flag = 0;
+
+ for (int i = 0; i < HAL_CAM_MODE_MAX; i++) {
+ if ( 0 ) { /*exclude some conflicting case*/
+ } else {
+ if (flag == 0) { /*first item*/
+ snprintf(buffer, sizeof(buffer), "%d", i);
+ } else {
+ snprintf(buffer, sizeof(buffer), ",%d", i);
+ }
+ flag = 1;
+ CamModeStr.append(buffer);
+ }
+ }
+ mParameters.set("camera-mode-values", CamModeStr);
+ }
+
+ mParameters.set("ae-bracket-hdr-values",
+ create_values_str(hdr_bracket, sizeof(hdr_bracket)/sizeof(str_map) ));
+
+// if(mIs3DModeOn)
+// mParameters.set("3d-frame-format", "left-right");
+ mParameters.set("no-display-mode", 0);
+ //mUseOverlay = useOverlay();
+ mParameters.set("zoom", 0);
+
+ int mNuberOfVFEOutputs;
+ ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_VFE_OUTPUT_ENABLE, &mNuberOfVFEOutputs);
+ if(ret != MM_CAMERA_OK) {
+ LOGE("get parm MM_CAMERA_PARM_VFE_OUTPUT_ENABLE failed");
+ ret = BAD_VALUE;
+ }
+ if(mNuberOfVFEOutputs == 1)
+ {
+ mParameters.set(CameraParameters::KEY_SINGLE_ISP_OUTPUT_ENABLED, "true");
+ } else {
+ mParameters.set(CameraParameters::KEY_SINGLE_ISP_OUTPUT_ENABLED, "false");
+ }
+
+ if (setParameters(mParameters) != NO_ERROR) {
+ LOGE("Failed to set default parameters?!");
+ }
+ mInitialized = true;
+ strTexturesOn = false;
+
+ LOGI("%s: X", __func__);
+ return;
+}
+
+/**
+ * Set the camera parameters. This returns BAD_VALUE if any parameter is
+ * invalid or not supported.
+ */
+
+int QCameraHardwareInterface::setParameters(const char *parms)
+{
+ CameraParameters param;
+ String8 str = String8(parms);
+ param.unflatten(str);
+ status_t ret = setParameters(param);
+ if(ret == NO_ERROR)
+ return 0;
+ else
+ return -1;
+}
+
+/**
+ * Set the camera parameters. This returns BAD_VALUE if any parameter is
+ * invalid or not supported. */
+status_t QCameraHardwareInterface::setParameters(const CameraParameters& params)
+{
+ status_t ret = NO_ERROR;
+
+ LOGI("%s: E", __func__);
+// Mutex::Autolock l(&mLock);
+ status_t rc, final_rc = NO_ERROR;
+
+ if ((rc = setCameraMode(params))) final_rc = rc;
+ if ((rc = setPowerMode(params))) final_rc = rc;
+ if ((rc = setPreviewSize(params))) final_rc = rc;
+ if ((rc = setVideoSize(params))) final_rc = rc;
+ if ((rc = setPictureSize(params))) final_rc = rc;
+ if ((rc = setJpegThumbnailSize(params))) final_rc = rc;
+ if ((rc = setJpegQuality(params))) final_rc = rc;
+ if ((rc = setEffect(params))) final_rc = rc;
+ if ((rc = setGpsLocation(params))) final_rc = rc;
+ if ((rc = setRotation(params))) final_rc = rc;
+ if ((rc = setZoom(params))) final_rc = rc;
+ if ((rc = setOrientation(params))) final_rc = rc;
+ if ((rc = setLensshadeValue(params))) final_rc = rc;
+ if ((rc = setMCEValue(params))) final_rc = rc;
+ if ((rc = setPictureFormat(params))) final_rc = rc;
+ if ((rc = setSharpness(params))) final_rc = rc;
+ if ((rc = setSaturation(params))) final_rc = rc;
+ if ((rc = setSceneMode(params))) final_rc = rc;
+ if ((rc = setContrast(params))) final_rc = rc;
+ if ((rc = setFaceDetect(params))) final_rc = rc;
+ if ((rc = setStrTextures(params))) final_rc = rc;
+ if ((rc = setPreviewFormat(params))) final_rc = rc;
+ if ((rc = setSkinToneEnhancement(params))) final_rc = rc;
+ if ((rc = setWaveletDenoise(params))) final_rc = rc;
+ if ((rc = setAntibanding(params))) final_rc = rc;
+ // if ((rc = setOverlayFormats(params))) final_rc = rc;
+ if ((rc = setRedeyeReduction(params))) final_rc = rc;
+ if ((rc = setCaptureBurstExp())) final_rc = rc;
+
+ const char *str_val = params.get("capture-burst-exposures");
+ if ( str_val == NULL || strlen(str_val)==0 ) {
+ char burst_exp[PROPERTY_VALUE_MAX];
+ memset(burst_exp, 0, sizeof(burst_exp));
+ property_get("persist.capture.burst.exposures", burst_exp, "");
+ if ( strlen(burst_exp)>0 ) {
+ mParameters.set("capture-burst-exposures", burst_exp);
+ }
+ } else {
+ mParameters.set("capture-burst-exposures", str_val);
+ }
+ mParameters.set("num-snaps-per-shutter", params.get("num-snaps-per-shutter"));
+
+ if ((rc = setAEBracket(params))) final_rc = rc;
+ // if ((rc = setDenoise(params))) final_rc = rc;
+ if ((rc = setPreviewFpsRange(params))) final_rc = rc;
+ if((rc = setRecordingHint(params))) final_rc = rc;
+ if ((rc = setNumOfSnapshot(params))) final_rc = rc;
+ if ((rc = setAecAwbLock(params))) final_rc = rc;
+
+ const char *str = params.get(CameraParameters::KEY_SCENE_MODE);
+ int32_t value = attr_lookup(scenemode, sizeof(scenemode) / sizeof(str_map), str);
+
+ if((value != NOT_FOUND) && (value == CAMERA_BESTSHOT_OFF )) {
+ //if ((rc = setPreviewFrameRateMode(params))) final_rc = rc;
+ if ((rc = setPreviewFrameRate(params))) final_rc = rc;
+ if ((rc = setAutoExposure(params))) final_rc = rc;
+ if ((rc = setExposureCompensation(params))) final_rc = rc;
+ if ((rc = setWhiteBalance(params))) final_rc = rc;
+ if ((rc = setFlash(params))) final_rc = rc;
+ if ((rc = setFocusMode(params))) final_rc = rc;
+ if ((rc = setBrightness(params))) final_rc = rc;
+ if ((rc = setISOValue(params))) final_rc = rc;
+ if ((rc = setFocusAreas(params))) final_rc = rc;
+ if ((rc = setMeteringAreas(params))) final_rc = rc;
+ }
+ //selectableZoneAF needs to be invoked after continuous AF
+ if ((rc = setSelectableZoneAf(params))) final_rc = rc;
+ // setHighFrameRate needs to be done at end, as there can
+ // be a preview restart, and need to use the updated parameters
+ if ((rc = setHighFrameRate(params))) final_rc = rc;
+ if ((rc = setZSLBurstLookBack(params))) final_rc = rc;
+ if ((rc = setZSLBurstInterval(params))) final_rc = rc;
+ if ((rc = setNoDisplayMode(params))) final_rc = rc;
+
+ //Update Exiftag values.
+ setExifTags();
+
+ LOGI("%s: X", __func__);
+ return final_rc;
+}
+
+/** Retrieve the camera parameters. The buffer returned by the camera HAL
+ must be returned back to it with put_parameters, if put_parameters
+ is not NULL.
+ */
+int QCameraHardwareInterface::getParameters(char **parms)
+{
+ char* rc = NULL;
+ String8 str;
+ CameraParameters param = getParameters();
+ //param.dump();
+ str = param.flatten( );
+ rc = (char *)malloc(sizeof(char)*(str.length()+1));
+ if(rc != NULL){
+ memset(rc, 0, sizeof(char)*(str.length()+1));
+ strncpy(rc, str.string(), str.length());
+ rc[str.length()] = 0;
+ *parms = rc;
+ }
+ return 0;
+}
+
+/** The camera HAL uses its own memory to pass us the parameters when we
+ call get_parameters. Use this function to return the memory back to
+ the camera HAL, if put_parameters is not NULL. If put_parameters
+ is NULL, then you have to use free() to release the memory.
+*/
+void QCameraHardwareInterface::putParameters(char *rc)
+{
+ free(rc);
+ rc = NULL;
+}
+
+CameraParameters& QCameraHardwareInterface::getParameters()
+{
+ Mutex::Autolock lock(mLock);
+ mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES, mFocusDistance.string());
+ return mParameters;
+}
+
+status_t QCameraHardwareInterface::runFaceDetection()
+{
+ bool ret = true;
+
+ const char *str = mParameters.get(CameraParameters::KEY_FACE_DETECTION);
+ if (str != NULL) {
+ int value = attr_lookup(facedetection,
+ sizeof(facedetection) / sizeof(str_map), str);
+#if 0
+ mMetaDataWaitLock.lock();
+ if (value == true) {
+ if(mMetaDataHeap != NULL)
+ mMetaDataHeap.clear();
+
+ mMetaDataHeap =
+ new AshmemPool((sizeof(int)*(MAX_ROI*4+1)),
+ 1,
+ (sizeof(int)*(MAX_ROI*4+1)),
+ "metadata");
+ if (!mMetaDataHeap->initialized()) {
+ LOGE("Meta Data Heap allocation failed ");
+ mMetaDataHeap.clear();
+ LOGE("runFaceDetection X: error initializing mMetaDataHeap");
+ mMetaDataWaitLock.unlock();
+ return UNKNOWN_ERROR;
+ }
+ mSendMetaData = true;
+ } else {
+ if(mMetaDataHeap != NULL)
+ mMetaDataHeap.clear();
+ }
+ mMetaDataWaitLock.unlock();
+#endif
+ cam_ctrl_dimension_t dim;
+ cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim);
+ preview_parm_config (&dim, mParameters);
+ LOGE("%s: why set_dimension everytime?", __func__);
+ ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim);
+ ret = native_set_parms(MM_CAMERA_PARM_FD, sizeof(int8_t), (void *)&value);
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+ }
+ LOGE("Invalid Face Detection value: %s", (str == NULL) ? "NULL" : str);
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setSharpness(const CameraParameters& params)
+{
+ bool ret = false;
+ int rc = MM_CAMERA_OK;
+ LOGE("%s",__func__);
+ rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_SHARPNESS);
+ if(!rc) {
+ LOGE("%s:CONTRAST not supported", __func__);
+ return NO_ERROR;
+ }
+ int sharpness = params.getInt(CameraParameters::KEY_SHARPNESS);
+ if((sharpness < CAMERA_MIN_SHARPNESS
+ || sharpness > CAMERA_MAX_SHARPNESS))
+ return UNKNOWN_ERROR;
+
+ LOGV("setting sharpness %d", sharpness);
+ mParameters.set(CameraParameters::KEY_SHARPNESS, sharpness);
+ ret = native_set_parms(MM_CAMERA_PARM_SHARPNESS, sizeof(sharpness),
+ (void *)&sharpness);
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+}
+
+status_t QCameraHardwareInterface::setSaturation(const CameraParameters& params)
+{
+ bool ret = false;
+ int rc = MM_CAMERA_OK;
+ LOGE("%s",__func__);
+ rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_SATURATION);
+ if(!rc) {
+ LOGE("%s:MM_CAMERA_PARM_SATURATION not supported", __func__);
+ return NO_ERROR;
+ }
+ int result;
+ int saturation = params.getInt(CameraParameters::KEY_SATURATION);
+
+ if((saturation < CAMERA_MIN_SATURATION)
+ || (saturation > CAMERA_MAX_SATURATION))
+ return UNKNOWN_ERROR;
+
+ LOGV("Setting saturation %d", saturation);
+ mParameters.set(CameraParameters::KEY_SATURATION, saturation);
+ ret = native_set_parms(MM_CAMERA_PARM_SATURATION, sizeof(saturation),
+ (void *)&saturation, (int *)&result);
+ if(result != MM_CAMERA_OK)
+ LOGI("Saturation Value: %d is not set as the selected value is not supported", saturation);
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+}
+
+status_t QCameraHardwareInterface::setContrast(const CameraParameters& params)
+{
+ LOGE("%s E", __func__ );
+ int rc = MM_CAMERA_OK;
+ rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_CONTRAST);
+ if(!rc) {
+ LOGE("%s:CONTRAST not supported", __func__);
+ return NO_ERROR;
+ }
+ const char *str = params.get(CameraParameters::KEY_SCENE_MODE);
+ LOGE("Contrast : %s",str);
+ int32_t value = attr_lookup(scenemode, sizeof(scenemode) / sizeof(str_map), str);
+ if(value == CAMERA_BESTSHOT_OFF) {
+ int contrast = params.getInt(CameraParameters::KEY_CONTRAST);
+ if((contrast < CAMERA_MIN_CONTRAST)
+ || (contrast > CAMERA_MAX_CONTRAST))
+ {
+ LOGE("Contrast Value not matching");
+ return UNKNOWN_ERROR;
+ }
+ LOGV("setting contrast %d", contrast);
+ mParameters.set(CameraParameters::KEY_CONTRAST, contrast);
+ LOGE("Calling Contrast set on Lower layer");
+ bool ret = native_set_parms(MM_CAMERA_PARM_CONTRAST, sizeof(contrast),
+ (void *)&contrast);
+ LOGE("Lower layer returned %d", ret);
+ int bestshot_reconfigure;
+ cam_config_get_parm(mCameraId, MM_CAMERA_PARM_BESTSHOT_RECONFIGURE,
+ &bestshot_reconfigure);
+ if(bestshot_reconfigure) {
+ if (mContrast != contrast) {
+ mContrast = contrast;
+ if (mPreviewState == QCAMERA_HAL_PREVIEW_STARTED && ret) {
+ mRestartPreview = 1;
+ pausePreviewForZSL();
+ }
+ }
+ }
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+ } else {
+ LOGI(" Contrast value will not be set " \
+ "when the scenemode selected is %s", str);
+ return NO_ERROR;
+ }
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setSceneDetect(const CameraParameters& params)
+{
+ LOGE("%s",__func__);
+ bool retParm;
+ int rc = MM_CAMERA_OK;
+
+ rc = cam_config_is_parm_supported(mCameraId,MM_CAMERA_PARM_ASD_ENABLE);
+ if(!rc) {
+ LOGE("%s:MM_CAMERA_PARM_ASD_ENABLE not supported", __func__);
+ return NO_ERROR;
+ }
+
+ const char *str = params.get(CameraParameters::KEY_SCENE_DETECT);
+ LOGE("Scene Detect string : %s",str);
+ if (str != NULL) {
+ int32_t value = attr_lookup(scenedetect, sizeof(scenedetect) / sizeof(str_map), str);
+ LOGE("Scenedetect Value : %d",value);
+ if (value != NOT_FOUND) {
+ mParameters.set(CameraParameters::KEY_SCENE_DETECT, str);
+
+ retParm = native_set_parms(MM_CAMERA_PARM_ASD_ENABLE, sizeof(value),
+ (void *)&value);
+
+ return retParm ? NO_ERROR : UNKNOWN_ERROR;
+ }
+ }
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setZoom(const CameraParameters& params)
+{
+ status_t rc = NO_ERROR;
+
+ LOGE("%s: E",__func__);
+
+
+ if( !( cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_ZOOM))) {
+ LOGE("%s:MM_CAMERA_PARM_ZOOM not supported", __func__);
+ return NO_ERROR;
+ }
+ // No matter how many different zoom values the driver can provide, HAL
+ // provides applictations the same number of zoom levels. The maximum driver
+ // zoom value depends on sensor output (VFE input) and preview size (VFE
+ // output) because VFE can only crop and cannot upscale. If the preview size
+ // is bigger, the maximum zoom ratio is smaller. However, we want the
+ // zoom ratio of each zoom level is always the same whatever the preview
+ // size is. Ex: zoom level 1 is always 1.2x, zoom level 2 is 1.44x, etc. So,
+ // we need to have a fixed maximum zoom value and do read it from the
+ // driver.
+ static const int ZOOM_STEP = 1;
+ int32_t zoom_level = params.getInt("zoom");
+ if(zoom_level >= 0 && zoom_level <= mMaxZoom-1) {
+ mParameters.set("zoom", zoom_level);
+ int32_t zoom_value = ZOOM_STEP * zoom_level;
+ bool ret = native_set_parms(MM_CAMERA_PARM_ZOOM,
+ sizeof(zoom_value), (void *)&zoom_value);
+ if(ret) {
+ mCurrentZoom=zoom_level;
+ }
+ rc = ret ? NO_ERROR : UNKNOWN_ERROR;
+ } else {
+ rc = BAD_VALUE;
+ }
+ LOGE("%s X",__func__);
+ return rc;
+
+}
+
+status_t QCameraHardwareInterface::setISOValue(const CameraParameters& params) {
+
+ status_t rc = NO_ERROR;
+ LOGE("%s",__func__);
+
+ rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_ISO);
+ if(!rc) {
+ LOGE("%s:MM_CAMERA_PARM_ISO not supported", __func__);
+ return NO_ERROR;
+ }
+ const char *str = params.get(CameraParameters::KEY_ISO_MODE);
+ LOGE("ISO string : %s",str);
+ int8_t temp_hjr;
+ if (str != NULL) {
+ int value = (camera_iso_mode_type)attr_lookup(
+ iso, sizeof(iso) / sizeof(str_map), str);
+ LOGE("ISO Value : %d",value);
+ if (value != NOT_FOUND) {
+ camera_iso_mode_type temp = (camera_iso_mode_type) value;
+ if (value == CAMERA_ISO_DEBLUR) {
+ temp_hjr = true;
+ native_set_parms(MM_CAMERA_PARM_HJR, sizeof(int8_t), (void*)&temp_hjr);
+ mHJR = value;
+ }
+ else {
+ if (mHJR == CAMERA_ISO_DEBLUR) {
+ temp_hjr = false;
+ native_set_parms(MM_CAMERA_PARM_HJR, sizeof(int8_t), (void*)&temp_hjr);
+ mHJR = value;
+ }
+ }
+
+ mParameters.set(CameraParameters::KEY_ISO_MODE, str);
+ native_set_parms(MM_CAMERA_PARM_ISO, sizeof(camera_iso_mode_type), (void *)&temp);
+ return NO_ERROR;
+ }
+ }
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::updateFocusDistances()
+{
+ LOGV("%s: IN", __FUNCTION__);
+ focus_distances_info_t focusDistances;
+ if(cam_config_get_parm(mCameraId, MM_CAMERA_PARM_FOCUS_DISTANCES,
+ &focusDistances) == MM_CAMERA_OK) {
+ String8 str;
+ char buffer[32] = {0};
+ //set all distances to infinity if focus mode is infinity
+ if(mFocusMode == AF_MODE_INFINITY) {
+ snprintf(buffer, sizeof(buffer), "Infinity,");
+ str.append(buffer);
+ snprintf(buffer, sizeof(buffer), "Infinity,");
+ str.append(buffer);
+ snprintf(buffer, sizeof(buffer), "Infinity");
+ str.append(buffer);
+ } else {
+ snprintf(buffer, sizeof(buffer), "%f", focusDistances.focus_distance[0]);
+ str.append(buffer);
+ snprintf(buffer, sizeof(buffer), ",%f", focusDistances.focus_distance[1]);
+ str.append(buffer);
+ snprintf(buffer, sizeof(buffer), ",%f", focusDistances.focus_distance[2]);
+ str.append(buffer);
+ }
+ LOGE("%s: setting KEY_FOCUS_DISTANCES as %s", __FUNCTION__, str.string());
+ mFocusDistance = str;
+ return NO_ERROR;
+ }
+ LOGE("%s: get CAMERA_PARM_FOCUS_DISTANCES failed!!!", __FUNCTION__);
+ return BAD_VALUE;
+}
+
+// Parse string like "(1, 2, 3, 4, ..., N)"
+// num is pointer to an allocated array of size N
+static int parseNDimVector(const char *str, int *num, int N, char delim = ',')
+{
+ char *start, *end;
+ if(num == NULL) {
+ LOGE("Invalid output array (num == NULL)");
+ return -1;
+ }
+ //check if string starts and ends with parantheses
+ if(str[0] != '(' || str[strlen(str)-1] != ')') {
+ LOGE("Invalid format of string %s, valid format is (n1, n2, n3, n4 ...)", str);
+ return -1;
+ }
+ start = (char*) str;
+ start++;
+ for(int i=0; i<N; i++) {
+ *(num+i) = (int) strtol(start, &end, 10);
+ if(*end != delim && i < N-1) {
+ LOGE("Cannot find delimeter '%c' in string \"%s\". end = %c", delim, str, *end);
+ return -1;
+ }
+ start = end+1;
+ }
+ return 0;
+}
+
+// parse string like "(1, 2, 3, 4, 5),(1, 2, 3, 4, 5),..."
+static int parseCameraAreaString(const char* str, int max_num_areas,
+ camera_area_t *pAreas, int *num_areas_found)
+{
+ char area_str[32];
+ const char *start, *end, *p;
+ start = str; end = NULL;
+ int values[5], index=0;
+ *num_areas_found = 0;
+
+ while(start != NULL) {
+ if(*start != '(') {
+ LOGE("%s: error: Ill formatted area string: %s", __func__, str);
+ return -1;
+ }
+ end = strchr(start, ')');
+ if(end == NULL) {
+ LOGE("%s: error: Ill formatted area string: %s", __func__, str);
+ return -1;
+ }
+ int i;
+ for (i=0,p=start; p<=end; p++, i++) {
+ area_str[i] = *p;
+ }
+ area_str[i] = '\0';
+ if(parseNDimVector(area_str, values, 5) < 0){
+ LOGE("%s: error: Failed to parse the area string: %s", __func__, area_str);
+ return -1;
+ }
+ // no more areas than max_num_areas are accepted.
+ if(index >= max_num_areas) {
+ LOGE("%s: error: too many areas specified %s", __func__, str);
+ return -1;
+ }
+ pAreas[index].x1 = values[0];
+ pAreas[index].y1 = values[1];
+ pAreas[index].x2 = values[2];
+ pAreas[index].y2 = values[3];
+ pAreas[index].weight = values[4];
+
+ index++;
+ start = strchr(end, '('); // serach for next '('
+ }
+ (*num_areas_found) = index;
+ return 0;
+}
+static bool validateCameraAreas(camera_area_t *areas, int num_areas)
+{
+ for(int i=0; i<num_areas; i++) {
+
+ // handle special case (0, 0, 0, 0, 0)
+ if((areas[i].x1 == 0) && (areas[i].y1 == 0)
+ && (areas[i].x2 == 0) && (areas[i].y2 == 0) && (areas[i].weight == 0)) {
+ continue;
+ }
+ if(areas[i].x1 < -1000) return false; // left should be >= -1000
+ if(areas[i].y1 < -1000) return false; // top should be >= -1000
+ if(areas[i].x2 > 1000) return false; // right should be <= 1000
+ if(areas[i].y2 > 1000) return false; // bottom should be <= 1000
+ if(areas[i].weight <= 0 || areas[i].weight > 1000) // weight should be in [1, 1000]
+ return false;
+ if(areas[i].x1 >= areas[i].x2) { // left should be < right
+ return false;
+ }
+ if(areas[i].y1 >= areas[i].y2) // top should be < bottom
+ return false;
+ }
+ return true;
+}
+
+status_t QCameraHardwareInterface::setFocusAreas(const CameraParameters& params)
+{
+ LOGE("%s: E", __func__);
+ status_t rc;
+ int max_num_af_areas = mParameters.getInt(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS);
+ if(max_num_af_areas == 0) {
+ return NO_ERROR;
+ }
+ const char *str = params.get(CameraParameters::KEY_FOCUS_AREAS);
+ if (str == NULL) {
+ LOGE("%s: Parameter string is null", __func__);
+ rc = NO_ERROR;
+ } else {
+ camera_area_t *areas = new camera_area_t[max_num_af_areas];
+ int num_areas_found=0;
+ if(parseCameraAreaString(str, max_num_af_areas, areas, &num_areas_found) < 0) {
+ LOGE("%s: Failed to parse the string: %s", __func__, str);
+ delete areas;
+ return BAD_VALUE;
+ }
+ for(int i=0; i<num_areas_found; i++) {
+ LOGD("FocusArea[%d] = (%d, %d, %d, %d, %d)", i, (areas[i].x1), (areas[i].y1),
+ (areas[i].x2), (areas[i].y2), (areas[i].weight));
+ }
+ if(validateCameraAreas(areas, num_areas_found) == false) {
+ LOGE("%s: invalid areas specified : %s", __func__, str);
+ delete areas;
+ return BAD_VALUE;
+ }
+ mParameters.set(CameraParameters::KEY_FOCUS_AREAS, str);
+ num_areas_found = 1; //temp; need to change after the multi-roi is enabled
+
+ //if the native_set_parms is called when preview is not started, it
+ //crashes in lower layer, so return of preview is not started
+ if(mPreviewState == QCAMERA_HAL_PREVIEW_STOPPED) {
+ delete areas;
+ return NO_ERROR;
+ }
+
+ //for special area string (0, 0, 0, 0, 0), set the num_areas_found to 0,
+ //so no action is takenby the lower layer
+ if(num_areas_found == 1 && (areas[0].x1 == 0) && (areas[0].y1 == 0)
+ && (areas[0].x2 == 0) && (areas[0].y2 == 0) && (areas[0].weight == 0)) {
+ num_areas_found = 0;
+ }
+#if 1 //temp solution
+
+ roi_info_t af_roi_value;
+ memset(&af_roi_value, 0, sizeof(roi_info_t));
+ uint16_t x1, x2, y1, y2, dx, dy;
+ int previewWidth, previewHeight;
+ this->getPreviewSize(&previewWidth, &previewHeight);
+ //transform the coords from (-1000, 1000) to (0, previewWidth or previewHeight)
+ x1 = (uint16_t)((areas[0].x1 + 1000.0f)*(previewWidth/2000.0f));
+ y1 = (uint16_t)((areas[0].y1 + 1000.0f)*(previewHeight/2000.0f));
+ x2 = (uint16_t)((areas[0].x2 + 1000.0f)*(previewWidth/2000.0f));
+ y2 = (uint16_t)((areas[0].y2 + 1000.0f)*(previewHeight/2000.0f));
+ dx = x2 - x1;
+ dy = y2 - y1;
+
+ af_roi_value.num_roi = num_areas_found;
+ af_roi_value.roi[0].x = x1;
+ af_roi_value.roi[0].y = y1;
+ af_roi_value.roi[0].dx = dx;
+ af_roi_value.roi[0].dy = dy;
+ af_roi_value.is_multiwindow = 0;
+ if (native_set_parms(MM_CAMERA_PARM_AF_ROI, sizeof(roi_info_t), (void*)&af_roi_value))
+ rc = NO_ERROR;
+ else
+ rc = BAD_VALUE;
+ delete areas;
+#endif
+#if 0 //better solution with multi-roi, to be enabled later
+ af_mtr_area_t afArea;
+ afArea.num_area = num_areas_found;
+
+ uint16_t x1, x2, y1, y2, dx, dy;
+ int previewWidth, previewHeight;
+ this->getPreviewSize(&previewWidth, &previewHeight);
+
+ for(int i=0; i<num_areas_found; i++) {
+ //transform the coords from (-1000, 1000) to (0, previewWidth or previewHeight)
+ x1 = (uint16_t)((areas[i].x1 + 1000.0f)*(previewWidth/2000.0f));
+ y1 = (uint16_t)((areas[i].y1 + 1000.0f)*(previewHeight/2000.0f));
+ x2 = (uint16_t)((areas[i].x2 + 1000.0f)*(previewWidth/2000.0f));
+ y2 = (uint16_t)((areas[i].y2 + 1000.0f)*(previewHeight/2000.0f));
+ dx = x2 - x1;
+ dy = y2 - y1;
+ afArea.mtr_area[i].x = x1;
+ afArea.mtr_area[i].y = y1;
+ afArea.mtr_area[i].dx = dx;
+ afArea.mtr_area[i].dy = dy;
+ afArea.weight[i] = areas[i].weight;
+ }
+
+ if(native_set_parms(MM_CAMERA_PARM_AF_MTR_AREA, sizeof(af_mtr_area_t), (void*)&afArea))
+ rc = NO_ERROR;
+ else
+ rc = BAD_VALUE;*/
+#endif
+ }
+ LOGE("%s: X", __func__);
+ return rc;
+}
+
+status_t QCameraHardwareInterface::setMeteringAreas(const CameraParameters& params)
+{
+ LOGE("%s: E", __func__);
+ status_t rc;
+ int max_num_mtr_areas = mParameters.getInt(CameraParameters::KEY_MAX_NUM_METERING_AREAS);
+ if(max_num_mtr_areas == 0) {
+ return NO_ERROR;
+ }
+
+ const char *str = params.get(CameraParameters::KEY_METERING_AREAS);
+ if (str == NULL) {
+ LOGE("%s: Parameter string is null", __func__);
+ rc = NO_ERROR;
+ } else {
+ camera_area_t *areas = new camera_area_t[max_num_mtr_areas];
+ int num_areas_found=0;
+ if(parseCameraAreaString(str, max_num_mtr_areas, areas, &num_areas_found) < 0) {
+ LOGE("%s: Failed to parse the string: %s", __func__, str);
+ delete areas;
+ return BAD_VALUE;
+ }
+ for(int i=0; i<num_areas_found; i++) {
+ LOGD("MeteringArea[%d] = (%d, %d, %d, %d, %d)", i, (areas[i].x1), (areas[i].y1),
+ (areas[i].x2), (areas[i].y2), (areas[i].weight));
+ }
+ if(validateCameraAreas(areas, num_areas_found) == false) {
+ LOGE("%s: invalid areas specified : %s", __func__, str);
+ delete areas;
+ return BAD_VALUE;
+ }
+ mParameters.set(CameraParameters::KEY_METERING_AREAS, str);
+
+ //if the native_set_parms is called when preview is not started, it
+ //crashes in lower layer, so return of preview is not started
+ if(mPreviewState == QCAMERA_HAL_PREVIEW_STOPPED) {
+ delete areas;
+ return NO_ERROR;
+ }
+
+ num_areas_found = 1; //temp; need to change after the multi-roi is enabled
+
+ //for special area string (0, 0, 0, 0, 0), set the num_areas_found to 0,
+ //so no action is takenby the lower layer
+ if(num_areas_found == 1 && (areas[0].x1 == 0) && (areas[0].y1 == 0)
+ && (areas[0].x2 == 0) && (areas[0].y2 == 0) && (areas[0].weight == 0)) {
+ num_areas_found = 0;
+ }
+#if 1
+ cam_set_aec_roi_t aec_roi_value;
+ uint16_t x1, x2, y1, y2;
+ int previewWidth, previewHeight;
+ this->getPreviewSize(&previewWidth, &previewHeight);
+ //transform the coords from (-1000, 1000) to (0, previewWidth or previewHeight)
+ x1 = (uint16_t)((areas[0].x1 + 1000.0f)*(previewWidth/2000.0f));
+ y1 = (uint16_t)((areas[0].y1 + 1000.0f)*(previewHeight/2000.0f));
+ x2 = (uint16_t)((areas[0].x2 + 1000.0f)*(previewWidth/2000.0f));
+ y2 = (uint16_t)((areas[0].y2 + 1000.0f)*(previewHeight/2000.0f));
+ delete areas;
+
+ if(num_areas_found == 1) {
+ aec_roi_value.aec_roi_enable = AEC_ROI_ON;
+ aec_roi_value.aec_roi_type = AEC_ROI_BY_COORDINATE;
+ aec_roi_value.aec_roi_position.coordinate.x = (x1+x2)/2;
+ aec_roi_value.aec_roi_position.coordinate.y = (y1+y2)/2;
+ } else {
+ aec_roi_value.aec_roi_enable = AEC_ROI_OFF;
+ aec_roi_value.aec_roi_type = AEC_ROI_BY_COORDINATE;
+ aec_roi_value.aec_roi_position.coordinate.x = DONT_CARE_COORDINATE;
+ aec_roi_value.aec_roi_position.coordinate.y = DONT_CARE_COORDINATE;
+ }
+
+ if(native_set_parms(MM_CAMERA_PARM_AEC_ROI, sizeof(cam_set_aec_roi_t), (void *)&aec_roi_value))
+ rc = NO_ERROR;
+ else
+ rc = BAD_VALUE;
+#endif
+#if 0 //solution including multi-roi, to be enabled later
+ aec_mtr_area_t aecArea;
+ aecArea.num_area = num_areas_found;
+
+ uint16_t x1, x2, y1, y2, dx, dy;
+ int previewWidth, previewHeight;
+ this->getPreviewSize(&previewWidth, &previewHeight);
+
+ for(int i=0; i<num_areas_found; i++) {
+ //transform the coords from (-1000, 1000) to (0, previewWidth or previewHeight)
+ x1 = (uint16_t)((areas[i].x1 + 1000.0f)*(previewWidth/2000.0f));
+ y1 = (uint16_t)((areas[i].y1 + 1000.0f)*(previewHeight/2000.0f));
+ x2 = (uint16_t)((areas[i].x2 + 1000.0f)*(previewWidth/2000.0f));
+ y2 = (uint16_t)((areas[i].y2 + 1000.0f)*(previewHeight/2000.0f));
+ dx = x2 - x1;
+ dy = y2 - y1;
+ aecArea.mtr_area[i].x = x1;
+ aecArea.mtr_area[i].y = y1;
+ aecArea.mtr_area[i].dx = dx;
+ aecArea.mtr_area[i].dy = dy;
+ aecArea.weight[i] = areas[i].weight;
+ }
+ delete areas;
+
+ if(native_set_parms(MM_CAMERA_PARM_AEC_MTR_AREA, sizeof(aec_mtr_area_t), (void*)&aecArea))
+ rc = NO_ERROR;
+ else
+ rc = BAD_VALUE;
+#endif
+ }
+ LOGE("%s: X", __func__);
+ return rc;
+}
+
+status_t QCameraHardwareInterface::setFocusMode(const CameraParameters& params)
+{
+ const char *str = params.get(CameraParameters::KEY_FOCUS_MODE);
+ const char *prev_str = mParameters.get(CameraParameters::KEY_FOCUS_MODE);
+ LOGE("%s",__func__);
+ if (str != NULL) {
+ LOGE("Focus mode %s",str);
+ int32_t value = attr_lookup(focus_modes,
+ sizeof(focus_modes) / sizeof(str_map), str);
+ if (value != NOT_FOUND) {
+ mParameters.set(CameraParameters::KEY_FOCUS_MODE, str);
+ mFocusMode = value;
+
+ if(updateFocusDistances() != NO_ERROR) {
+ LOGE("%s: updateFocusDistances failed for %s", __FUNCTION__, str);
+ return UNKNOWN_ERROR;
+ }
+ mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES, mFocusDistance.string());
+ if(mHasAutoFocusSupport){
+ bool ret = native_set_parms(MM_CAMERA_PARM_FOCUS_MODE,
+ sizeof(value),
+ (void *)&value);
+
+ int cafSupport = FALSE;
+ if(!strcmp(str, CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO) ||
+ !strcmp(str, CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE)){
+ cafSupport = TRUE;
+ }
+ LOGE("Continuous Auto Focus %d", cafSupport);
+ ret = native_set_parms(MM_CAMERA_PARM_CONTINUOUS_AF, sizeof(cafSupport),
+ (void *)&cafSupport);
+ }
+
+ return NO_ERROR;
+ }
+ LOGE("%s:Could not look up str value",__func__);
+ }
+ LOGE("Invalid focus mode value: %s", (str == NULL) ? "NULL" : str);
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setSceneMode(const CameraParameters& params)
+{
+ status_t rc = NO_ERROR;
+ LOGE("%s",__func__);
+
+ rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_BESTSHOT_MODE);
+ if(!rc) {
+ LOGE("%s:Parameter Scenemode is not supported for this sensor", __func__);
+ return NO_ERROR;
+ }
+ const char *str = params.get(CameraParameters::KEY_SCENE_MODE);
+ LOGE("Scene Mode string : %s",str);
+
+ if (str != NULL) {
+ int32_t value = attr_lookup(scenemode, sizeof(scenemode) / sizeof(str_map), str);
+ LOGE("Setting Scenemode value = %d",value );
+ if (value != NOT_FOUND) {
+ mParameters.set(CameraParameters::KEY_SCENE_MODE, str);
+ bool ret = native_set_parms(MM_CAMERA_PARM_BESTSHOT_MODE, sizeof(value),
+ (void *)&value);
+ int bestshot_reconfigure;
+ cam_config_get_parm(mCameraId, MM_CAMERA_PARM_BESTSHOT_RECONFIGURE,
+ &bestshot_reconfigure);
+ if(bestshot_reconfigure) {
+ if (mBestShotMode != value) {
+ mBestShotMode = value;
+ if (mPreviewState == QCAMERA_HAL_PREVIEW_STARTED && ret) {
+ mRestartPreview = 1;
+ pausePreviewForZSL();
+ }
+ }
+ }
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+ }
+ }
+ LOGE("Invalid scenemode value: %s", (str == NULL) ? "NULL" : str);
+ return BAD_VALUE;
+}
+
+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) {
+ 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);
+ return BAD_VALUE;
+
+ }
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setEffect(const CameraParameters& params)
+{
+ LOGE("%s",__func__);
+ status_t rc = NO_ERROR;
+ const char *str = params.get(CameraParameters::KEY_EFFECT);
+ int result;
+ if (str != NULL) {
+ LOGE("Setting effect %s",str);
+ int32_t value = attr_lookup(effects, sizeof(effects) / sizeof(str_map), str);
+ if (value != NOT_FOUND) {
+ rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_EFFECT);
+ if(!rc) {
+ LOGE("Camera Effect - %s mode is not supported for this sensor",str);
+ return NO_ERROR;
+ }else {
+ mParameters.set(CameraParameters::KEY_EFFECT, str);
+ LOGE("Setting effect to lower HAL : %d",value);
+ bool ret = native_set_parms(MM_CAMERA_PARM_EFFECT, sizeof(value),
+ (void *)&value,(int *)&result);
+ if(result != MM_CAMERA_OK) {
+ LOGI("Camera Effect: %s is not set as the selected value is not supported ", str);
+ }
+ int bestshot_reconfigure;
+ cam_config_get_parm(mCameraId, MM_CAMERA_PARM_BESTSHOT_RECONFIGURE,
+ &bestshot_reconfigure);
+ if(bestshot_reconfigure) {
+ if (mEffects != value) {
+ mEffects = value;
+ if (mPreviewState == QCAMERA_HAL_PREVIEW_STARTED && ret) {
+ mRestartPreview = 1;
+ pausePreviewForZSL();
+ }
+ }
+ }
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+ }
+ }
+ }
+ LOGE("Invalid effect value: %s", (str == NULL) ? "NULL" : str);
+ LOGE("setEffect X");
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setBrightness(const CameraParameters& params) {
+
+ LOGE("%s",__func__);
+ status_t rc = NO_ERROR;
+ rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_BRIGHTNESS);
+ if(!rc) {
+ LOGE("MM_CAMERA_PARM_BRIGHTNESS mode is not supported for this sensor");
+ return NO_ERROR;
+ }
+ int brightness = params.getInt("luma-adaptation");
+ if (mBrightness != brightness) {
+ LOGV(" new brightness value : %d ", brightness);
+ mBrightness = brightness;
+ mParameters.set("luma-adaptation", brightness);
+ bool ret = native_set_parms(MM_CAMERA_PARM_BRIGHTNESS, sizeof(mBrightness),
+ (void *)&mBrightness);
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+ }
+
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setAutoExposure(const CameraParameters& params)
+{
+
+ LOGE("%s",__func__);
+ status_t rc = NO_ERROR;
+ rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_EXPOSURE);
+ if(!rc) {
+ LOGE("MM_CAMERA_PARM_EXPOSURE mode is not supported for this sensor");
+ return NO_ERROR;
+ }
+ const char *str = params.get(CameraParameters::KEY_AUTO_EXPOSURE);
+ if (str != NULL) {
+ int32_t value = attr_lookup(autoexposure, sizeof(autoexposure) / sizeof(str_map), str);
+ if (value != NOT_FOUND) {
+ mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE, str);
+ bool ret = native_set_parms(MM_CAMERA_PARM_EXPOSURE, sizeof(value),
+ (void *)&value);
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+ }
+ }
+ LOGE("Invalid auto exposure value: %s", (str == NULL) ? "NULL" : str);
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setExposureCompensation(
+ const CameraParameters & params){
+ LOGE("%s",__func__);
+ status_t rc = NO_ERROR;
+ rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_EXPOSURE_COMPENSATION);
+ if(!rc) {
+ LOGE("MM_CAMERA_PARM_EXPOSURE_COMPENSATION mode is not supported for this sensor");
+ return NO_ERROR;
+ }
+ int numerator = params.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION);
+ if(EXPOSURE_COMPENSATION_MINIMUM_NUMERATOR <= numerator &&
+ numerator <= EXPOSURE_COMPENSATION_MAXIMUM_NUMERATOR){
+ int16_t numerator16 = (int16_t)(numerator & 0x0000ffff);
+ uint16_t denominator16 = EXPOSURE_COMPENSATION_DENOMINATOR;
+ uint32_t value = 0;
+ value = numerator16 << 16 | denominator16;
+
+ mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION,
+ numerator);
+ bool ret = native_set_parms(MM_CAMERA_PARM_EXPOSURE_COMPENSATION,
+ sizeof(value), (void *)&value);
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+ }
+ LOGE("Invalid Exposure Compensation");
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setWhiteBalance(const CameraParameters& params)
+{
+
+ LOGE("%s",__func__);
+ status_t rc = NO_ERROR;
+ rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_WHITE_BALANCE);
+ if(!rc) {
+ LOGE("MM_CAMERA_PARM_WHITE_BALANCE mode is not supported for this sensor");
+ return NO_ERROR;
+ }
+ int result;
+
+ const char *str = params.get(CameraParameters::KEY_WHITE_BALANCE);
+ if (str != NULL) {
+ int32_t value = attr_lookup(whitebalance, sizeof(whitebalance) / sizeof(str_map), str);
+ if (value != NOT_FOUND) {
+ mParameters.set(CameraParameters::KEY_WHITE_BALANCE, str);
+ bool ret = native_set_parms(MM_CAMERA_PARM_WHITE_BALANCE, sizeof(value),
+ (void *)&value, (int *)&result);
+ if(result != MM_CAMERA_OK) {
+ LOGI("WhiteBalance Value: %s is not set as the selected value is not supported ", str);
+ }
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+ }
+ }
+ LOGE("Invalid whitebalance value: %s", (str == NULL) ? "NULL" : str);
+ return BAD_VALUE;
+}
+status_t QCameraHardwareInterface::setAntibanding(const CameraParameters& params)
+{
+ int result;
+
+ LOGE("%s",__func__);
+ status_t rc = NO_ERROR;
+ rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_ANTIBANDING);
+ if(!rc) {
+ LOGE("ANTIBANDING mode is not supported for this sensor");
+ return NO_ERROR;
+ }
+ const char *str = params.get(CameraParameters::KEY_ANTIBANDING);
+ if (str != NULL) {
+ int value = (camera_antibanding_type)attr_lookup(
+ antibanding, sizeof(antibanding) / sizeof(str_map), str);
+ if (value != NOT_FOUND) {
+ camera_antibanding_type temp = (camera_antibanding_type) value;
+ LOGE("Antibanding Value : %d",value);
+ mParameters.set(CameraParameters::KEY_ANTIBANDING, str);
+ bool ret = native_set_parms(MM_CAMERA_PARM_ANTIBANDING,
+ sizeof(camera_antibanding_type), (void *)&value ,(int *)&result);
+ if(result != MM_CAMERA_OK) {
+ LOGI("AntiBanding Value: %s is not supported for the given BestShot Mode", str);
+ }
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+ }
+ }
+ LOGE("Invalid antibanding value: %s", (str == NULL) ? "NULL" : str);
+
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setPreviewFrameRate(const CameraParameters& params)
+{
+ LOGE("%s: E",__func__);
+ status_t rc = NO_ERROR;
+ uint16_t fps = (uint16_t)params.getPreviewFrameRate();
+ LOGV("%s: requested preview frame rate is %d", __func__, fps);
+
+ mParameters.setPreviewFrameRate(fps);
+ LOGE("%s: X",__func__);
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setPreviewFrameRateMode(const CameraParameters& params) {
+
+ LOGE("%s",__func__);
+ status_t rc = NO_ERROR;
+ rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_FPS);
+ if(!rc) {
+ LOGE(" CAMERA FPS mode is not supported for this sensor");
+ return NO_ERROR;
+ }
+ rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_FPS_MODE);
+ if(!rc) {
+ LOGE("CAMERA FPS MODE mode is not supported for this sensor");
+ return NO_ERROR;
+ }
+
+ const char *previousMode = mParameters.getPreviewFrameRateMode();
+ const char *str = params.getPreviewFrameRateMode();
+ if (NULL == previousMode) {
+ LOGE("Preview Frame Rate Mode is NULL\n");
+ return NO_ERROR;
+ }
+ if (NULL == str) {
+ LOGE("Preview Frame Rate Mode is NULL\n");
+ return NO_ERROR;
+ }
+ if( mInitialized && !strcmp(previousMode, str)) {
+ LOGE("frame rate mode same as previous mode %s", previousMode);
+ return NO_ERROR;
+ }
+ int32_t frameRateMode = attr_lookup(frame_rate_modes, sizeof(frame_rate_modes) / sizeof(str_map),str);
+ if(frameRateMode != NOT_FOUND) {
+ LOGV("setPreviewFrameRateMode: %s ", str);
+ mParameters.setPreviewFrameRateMode(str);
+ bool ret = native_set_parms(MM_CAMERA_PARM_FPS_MODE, sizeof(frameRateMode), (void *)&frameRateMode);
+ if(!ret) return ret;
+ //set the fps value when chaging modes
+ int16_t fps = (uint16_t)params.getPreviewFrameRate();
+ if(MINIMUM_FPS <= fps && fps <=MAXIMUM_FPS){
+ mParameters.setPreviewFrameRate(fps);
+ ret = native_set_parms(MM_CAMERA_PARM_FPS,
+ sizeof(fps), (void *)&fps);
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+ }
+ LOGE("Invalid preview frame rate value: %d", fps);
+ return BAD_VALUE;
+ }
+ LOGE("Invalid preview frame rate mode value: %s", (str == NULL) ? "NULL" : str);
+
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setSkinToneEnhancement(const CameraParameters& params) {
+ LOGE("%s",__func__);
+ status_t rc = NO_ERROR;
+ rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_SCE_FACTOR);
+ if(!rc) {
+ LOGE("SkinToneEnhancement is not supported for this sensor");
+ return NO_ERROR;
+ }
+ int skinToneValue = params.getInt("skinToneEnhancement");
+ if (mSkinToneEnhancement != skinToneValue) {
+ LOGV(" new skinTone correction value : %d ", skinToneValue);
+ mSkinToneEnhancement = skinToneValue;
+ mParameters.set("skinToneEnhancement", skinToneValue);
+ bool ret = native_set_parms(MM_CAMERA_PARM_SCE_FACTOR, sizeof(mSkinToneEnhancement),
+ (void *)&mSkinToneEnhancement);
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+ }
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setWaveletDenoise(const CameraParameters& params) {
+ LOGE("%s",__func__);
+ status_t rc = NO_ERROR;
+ rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_WAVELET_DENOISE);
+ if(rc != MM_CAMERA_PARM_SUPPORT_SET) {
+ LOGE("Wavelet Denoise is not supported for this sensor");
+ /* TO DO */
+// return NO_ERROR;
+ }
+ const char *str = params.get(CameraParameters::KEY_DENOISE);
+ if (str != NULL) {
+ int value = attr_lookup(denoise,
+ sizeof(denoise) / sizeof(str_map), str);
+ if ((value != NOT_FOUND) && (mDenoiseValue != value)) {
+ mDenoiseValue = value;
+ mParameters.set(CameraParameters::KEY_DENOISE, str);
+
+ char prop[PROPERTY_VALUE_MAX];
+ memset(prop, 0, sizeof(prop));
+ property_get("persist.denoise.process.plates", prop, "0");
+
+ denoise_param_t temp;
+ memset(&temp, 0, sizeof(denoise_param_t));
+ temp.denoise_enable = value;
+ temp.process_plates = atoi(prop);
+ LOGE("Denoise enable=%d, plates=%d", temp.denoise_enable, temp.process_plates);
+ bool ret = native_set_parms(MM_CAMERA_PARM_WAVELET_DENOISE, sizeof(temp),
+ (void *)&temp);
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+ }
+ return NO_ERROR;
+ }
+ LOGE("Invalid Denoise value: %s", (str == NULL) ? "NULL" : str);
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setVideoSize(const CameraParameters& params)
+{
+ const char *str= NULL;
+ LOGE("%s: E", __func__);
+ str = params.get(CameraParameters::KEY_VIDEO_SIZE);
+ if(!str) {
+ mParameters.set(CameraParameters::KEY_VIDEO_SIZE, "");
+ //If application didn't set this parameter string, use the values from
+ //getPreviewSize() as video dimensions.
+ LOGE("No Record Size requested, use the preview dimensions");
+ videoWidth = mPreviewWidth;
+ videoHeight = mPreviewHeight;
+ } else {
+ //Extract the record witdh and height that application requested.
+ LOGI("%s: requested record size %s", __func__, str);
+ if(!parse_size(str, videoWidth, videoHeight)) {
+ mParameters.set(CameraParameters::KEY_VIDEO_SIZE, str);
+ //VFE output1 shouldn't be greater than VFE output2.
+ if( (mPreviewWidth > videoWidth) || (mPreviewHeight > videoHeight)) {
+ //Set preview sizes as record sizes.
+ LOGE("Preview size %dx%d is greater than record size %dx%d,\
+ resetting preview size to record size",mPreviewWidth,
+ mPreviewHeight, videoWidth, videoHeight);
+ mPreviewWidth = videoWidth;
+ mPreviewHeight = videoHeight;
+ mParameters.setPreviewSize(mPreviewWidth, mPreviewHeight);
+ }
+
+ if(mIs3DModeOn == true) {
+ /* As preview and video frames are same in 3D mode,
+ * preview size should be same as video size. This
+ * cahnge is needed to take of video resolutions
+ * like 720P and 1080p where the application can
+ * request different preview sizes like 768x432
+ */
+ LOGE("3D mod is on");
+ mPreviewWidth = videoWidth;
+ mPreviewHeight = videoHeight;
+ mParameters.setPreviewSize(mPreviewWidth, mPreviewHeight);
+ }
+ } else {
+ mParameters.set(CameraParameters::KEY_VIDEO_SIZE, "");
+ LOGE("%s: error :failed to parse parameter record-size (%s)", __func__, str);
+ return BAD_VALUE;
+ }
+ }
+ LOGE("%s: preview dimensions: %dx%d", __func__, mPreviewWidth, mPreviewHeight);
+ LOGE("%s: video dimensions: %dx%d", __func__, videoWidth, videoHeight);
+ mDimension.display_width = mPreviewWidth;
+ mDimension.display_height= mPreviewHeight;
+ mDimension.orig_video_width = videoWidth;
+ mDimension.orig_video_height = videoHeight;
+ mDimension.video_width = videoWidth;
+ mDimension.video_height = videoHeight;
+
+ LOGE("%s: X", __func__);
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setCameraMode(const CameraParameters& params) {
+ int32_t value = params.getInt(CameraParameters::KEY_CAMERA_MODE);
+ mParameters.set(CameraParameters::KEY_CAMERA_MODE,value);
+
+ LOGI("ZSL is enabled %d", value);
+ if (value == 1) {
+ myMode = (camera_mode_t)(myMode | CAMERA_ZSL_MODE);
+ } else {
+ myMode = (camera_mode_t)(myMode & ~CAMERA_ZSL_MODE);
+ }
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setPowerMode(const CameraParameters& params) {
+ uint32_t value = NORMAL_POWER;
+ const char *powermode = NULL;
+
+ powermode = params.get(CameraParameters::KEY_POWER_MODE);
+ if (powermode != NULL) {
+ value = attr_lookup(power_modes,
+ sizeof(power_modes) / sizeof(str_map), powermode);
+ if((value == LOW_POWER) || mHFRLevel > 1) {
+ LOGI("Enable Low Power Mode");
+ value = LOW_POWER;
+ mPowerMode = value;
+ mParameters.set(CameraParameters::KEY_POWER_MODE,"Low_Power");
+ } else {
+ LOGE("Enable Normal Power Mode");
+ mPowerMode = value;
+ mParameters.set(CameraParameters::KEY_POWER_MODE,"Normal_Power");
+ }
+ }
+
+ LOGI("%s Low power mode %s value = %d", __func__,
+ value ? "Enabled" : "Disabled", value);
+ native_set_parms(MM_CAMERA_PARM_LOW_POWER_MODE, sizeof(value),
+ (void *)&value);
+ return NO_ERROR;
+}
+
+
+status_t QCameraHardwareInterface::setPreviewSize(const CameraParameters& params)
+{
+ int width, height;
+ params.getPreviewSize(&width, &height);
+ LOGE("################requested preview size %d x %d", width, height);
+
+ // Validate the preview size
+ for (size_t i = 0; i < mPreviewSizeCount; ++i) {
+ if (width == mPreviewSizes[i].width
+ && height == mPreviewSizes[i].height) {
+ mParameters.setPreviewSize(width, height);
+ LOGE("setPreviewSize: width: %d heigh: %d", width, height);
+ mPreviewWidth = width;
+ mPreviewHeight = height;
+ mDimension.display_width = width;
+ mDimension.display_height = height;
+ return NO_ERROR;
+ }
+ }
+ LOGE("Invalid preview size requested: %dx%d", width, height);
+ return BAD_VALUE;
+}
+status_t QCameraHardwareInterface::setPreviewFpsRange(const CameraParameters& params)
+{
+ LOGV("%s: E", __func__);
+ int minFps,maxFps;
+ int prevMinFps, prevMaxFps;
+ int rc = NO_ERROR;
+ bool found = false;
+
+ mParameters.getPreviewFpsRange(&prevMinFps, &prevMaxFps);
+ LOGE("%s: Existing FpsRange Values:(%d, %d)", __func__, prevMinFps, prevMaxFps);
+ params.getPreviewFpsRange(&minFps,&maxFps);
+ LOGE("%s: Requested FpsRange Values:(%d, %d)", __func__, minFps, maxFps);
+
+ if(mInitialized && (minFps == prevMinFps && maxFps == prevMaxFps)) {
+ LOGE("%s: No change in FpsRange", __func__);
+ rc = NO_ERROR;
+ goto end;
+ }
+ for(size_t i=0; i<FPS_RANGES_SUPPORTED_COUNT; i++) {
+ // if the value is in the supported list
+ if(minFps==FpsRangesSupported[i].minFPS && maxFps == FpsRangesSupported[i].maxFPS){
+ found = true;
+ LOGE("FPS: i=%d : minFps = %d, maxFps = %d ",i,FpsRangesSupported[i].minFPS,FpsRangesSupported[i].maxFPS );
+ mParameters.setPreviewFpsRange(minFps,maxFps);
+ // validate the values
+ bool valid = true;
+ // FPS can not be negative
+ if(minFps < 0 || maxFps < 0) valid = false;
+ // minFps must be >= maxFps
+ if(minFps > maxFps) valid = false;
+
+ if(valid) {
+ //Set the FPS mode
+ const char *str = (minFps == maxFps) ?
+ CameraParameters::KEY_PREVIEW_FRAME_RATE_FIXED_MODE:
+ CameraParameters::KEY_PREVIEW_FRAME_RATE_AUTO_MODE;
+ LOGE("%s FPS_MODE = %s", __func__, str);
+ int32_t frameRateMode = attr_lookup(frame_rate_modes,
+ sizeof(frame_rate_modes) / sizeof(str_map),str);
+ bool ret;
+ ret = native_set_parms(MM_CAMERA_PARM_FPS_MODE, sizeof(int32_t),
+ (void *)&frameRateMode);
+
+ //set FPS values
+ uint32_t fps; //lower 2 bytes specify maxFps and higher 2 bytes specify minFps
+ fps = ((uint32_t)(minFps/1000) << 16) + ((uint16_t)(maxFps/1000));
+ ret = native_set_parms(MM_CAMERA_PARM_FPS, sizeof(uint32_t), (void *)&fps);
+ mParameters.setPreviewFpsRange(minFps, maxFps);
+ if(ret)
+ rc = NO_ERROR;
+ else {
+ rc = BAD_VALUE;
+ LOGE("%s: error: native_set_params failed", __func__);
+ }
+ } else {
+ LOGE("%s: error: invalid FPS range value", __func__);
+ rc = BAD_VALUE;
+ }
+ }
+ }
+ if(found == false){
+ LOGE("%s: error: FPS range value not supported", __func__);
+ rc = BAD_VALUE;
+ }
+end:
+ LOGV("%s: X", __func__);
+ return rc;
+}
+
+status_t QCameraHardwareInterface::setJpegThumbnailSize(const CameraParameters& params){
+ int width = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
+ int height = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
+
+ LOGE("requested jpeg thumbnail size %d x %d", width, height);
+
+ // Validate the picture size
+ for (unsigned int i = 0; i < thumbnail_sizes_count; ++i) {
+ if (width == default_thumbnail_sizes[i].width
+ && height == default_thumbnail_sizes[i].height) {
+ thumbnailWidth = width;
+ thumbnailHeight = height;
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, width);
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, height);
+ return NO_ERROR;
+ }
+ }
+ LOGE("error: setting jpeg thumbnail size");
+ return BAD_VALUE;
+}
+status_t QCameraHardwareInterface::setPictureSize(const CameraParameters& params)
+{
+ int width, height;
+ LOGE("QualcommCameraHardware::setPictureSize E");
+ params.getPictureSize(&width, &height);
+ LOGE("requested picture size %d x %d", width, height);
+
+ // Validate the picture size
+ for (int i = 0; i < mSupportedPictureSizesCount; ++i) {
+ if (width == mPictureSizesPtr[i].width
+ && height == mPictureSizesPtr[i].height) {
+ int old_width, old_height;
+ mParameters.getPictureSize(&old_width,&old_height);
+ if(width != old_width || height != old_height) {
+ mRestartPreview = true;
+ }
+ mParameters.setPictureSize(width, height);
+ mDimension.picture_width = width;
+ mDimension.picture_height = height;
+ return NO_ERROR;
+ }
+ }
+ /* Dimension not among the ones in the list. Check if
+ * its a valid dimension, if it is, then configure the
+ * camera accordingly. else reject it.
+ */
+ if( isValidDimension(width, height) ) {
+ mParameters.setPictureSize(width, height);
+ mDimension.picture_width = width;
+ mDimension.picture_height = height;
+ return NO_ERROR;
+ } else
+ LOGE("Invalid picture size requested: %dx%d", width, height);
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setJpegRotation(int isZsl) {
+ return mm_jpeg_encoder_setRotation(mRotation, isZsl);
+}
+
+int QCameraHardwareInterface::getJpegRotation(void) {
+ return mRotation;
+}
+
+int QCameraHardwareInterface::getISOSpeedValue()
+{
+ const char *iso_str = mParameters.get(CameraParameters::KEY_ISO_MODE);
+ int iso_index = attr_lookup(iso, sizeof(iso) / sizeof(str_map), iso_str);
+ int iso_value = iso_speed_values[iso_index];
+ return iso_value;
+}
+
+
+status_t QCameraHardwareInterface::setJpegQuality(const CameraParameters& params) {
+ status_t rc = NO_ERROR;
+ int quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
+ LOGE("setJpegQuality E");
+ if (quality >= 0 && quality <= 100) {
+ mParameters.set(CameraParameters::KEY_JPEG_QUALITY, quality);
+ mJpegQuality = quality;
+ } else {
+ LOGE("Invalid jpeg quality=%d", quality);
+ rc = BAD_VALUE;
+ }
+
+ quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
+ if (quality >= 0 && quality <= 100) {
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, quality);
+ } else {
+ LOGE("Invalid jpeg thumbnail quality=%d", quality);
+ rc = BAD_VALUE;
+ }
+ LOGE("setJpegQuality X");
+ return rc;
+}
+
+status_t QCameraHardwareInterface::
+setNumOfSnapshot(const CameraParameters& params) {
+ status_t rc = NO_ERROR;
+
+ int num_of_snapshot = getNumOfSnapshots(params);
+
+ if (num_of_snapshot <= 0) {
+ num_of_snapshot = 1;
+ }
+ LOGI("number of snapshots = %d", num_of_snapshot);
+ mParameters.set("num-snaps-per-shutter", num_of_snapshot);
+
+ bool result = native_set_parms(MM_CAMERA_PARM_SNAPSHOT_BURST_NUM,
+ sizeof(int),
+ (void *)&num_of_snapshot);
+ if(!result)
+ LOGI("%s:Failure setting number of snapshots!!!", __func__);
+ return rc;
+}
+
+status_t QCameraHardwareInterface::setPreviewFormat(const CameraParameters& params) {
+ const char *str = params.getPreviewFormat();
+ int32_t previewFormat = attr_lookup(preview_formats, sizeof(preview_formats) / sizeof(str_map), str);
+ if(previewFormat != NOT_FOUND) {
+ int num = sizeof(preview_format_info_list)/sizeof(preview_format_info_t);
+ int i;
+
+ for (i = 0; i < num; i++) {
+ if (preview_format_info_list[i].Hal_format == previewFormat) {
+ mPreviewFormatInfo = preview_format_info_list[i];
+ break;
+ }
+ }
+
+ if (i == num) {
+ mPreviewFormatInfo.mm_cam_format = CAMERA_YUV_420_NV21;
+ mPreviewFormatInfo.padding = CAMERA_PAD_TO_WORD;
+ return BAD_VALUE;
+ }
+ bool ret = native_set_parms(MM_CAMERA_PARM_PREVIEW_FORMAT, sizeof(cam_format_t),
+ (void *)&mPreviewFormatInfo.mm_cam_format);
+ mParameters.set(CameraParameters::KEY_PREVIEW_FORMAT, str);
+ mPreviewFormat = mPreviewFormatInfo.mm_cam_format;
+ LOGI("Setting preview format to %d, i =%d, num=%d, hal_format=%d",
+ mPreviewFormat, i, num, mPreviewFormatInfo.Hal_format);
+ return NO_ERROR;
+ } else if ( strTexturesOn ) {
+ mPreviewFormatInfo.mm_cam_format = CAMERA_YUV_420_NV21;
+ mPreviewFormatInfo.padding = CAMERA_PAD_TO_4K;
+ } else {
+ mPreviewFormatInfo.mm_cam_format = CAMERA_YUV_420_NV21;
+ mPreviewFormatInfo.padding = CAMERA_PAD_TO_WORD;
+ }
+ LOGE("Invalid preview format value: %s", (str == NULL) ? "NULL" : str);
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setStrTextures(const CameraParameters& params) {
+ const char *str = params.get("strtextures");
+ const char *prev_str = mParameters.get("strtextures");
+
+ if(str != NULL) {
+ if(!strcmp(str,prev_str)) {
+ return NO_ERROR;
+ }
+ int str_size = strlen(str);
+ mParameters.set("strtextures", str);
+ if(str_size == 2) {
+ if(!strncmp(str, "on", str_size) || !strncmp(str, "ON", str_size)){
+ LOGI("Resetting mUseOverlay to false");
+ strTexturesOn = true;
+ mUseOverlay = false;
+ }
+ }else if(str_size == 3){
+ if (!strncmp(str, "off", str_size) || !strncmp(str, "OFF", str_size)) {
+ strTexturesOn = false;
+ mUseOverlay = true;
+ }
+ }
+
+ }
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setFlash(const CameraParameters& params)
+{
+ LOGI("%s: E",__func__);
+ int rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_LED_MODE);
+ if(!rc) {
+ LOGE("%s:LED FLASH not supported", __func__);
+ return NO_ERROR;
+ }
+
+ const char *str = params.get(CameraParameters::KEY_FLASH_MODE);
+ if (str != NULL) {
+ int32_t value = attr_lookup(flash, sizeof(flash) / sizeof(str_map), str);
+ if (value != NOT_FOUND) {
+ mParameters.set(CameraParameters::KEY_FLASH_MODE, str);
+ bool ret = native_set_parms(MM_CAMERA_PARM_LED_MODE,
+ sizeof(value), (void *)&value);
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+ }
+ }
+ LOGE("Invalid flash mode value: %s", (str == NULL) ? "NULL" : str);
+
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setAecAwbLock(const CameraParameters & params)
+{
+ LOGD("%s : E", __func__);
+ status_t rc = NO_ERROR;
+ int32_t value;
+ const char* str;
+
+ //for AEC lock
+ str = params.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK);
+ value = (strcmp(str, "true") == 0)? 1 : 0;
+ mParameters.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK, str);
+ rc = (native_set_parms(MM_CAMERA_PARM_AEC_LOCK, sizeof(int32_t), (void *)(&value))) ?
+ NO_ERROR : UNKNOWN_ERROR;
+
+ //for AWB lock
+ str = params.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK);
+ value = (strcmp(str, "true") == 0)? 1 : 0;
+ mParameters.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, str);
+ rc = (native_set_parms(MM_CAMERA_PARM_AWB_LOCK, sizeof(int32_t), (void *)(&value))) ?
+ NO_ERROR : UNKNOWN_ERROR;
+ LOGD("%s : X", __func__);
+ return rc;
+}
+
+status_t QCameraHardwareInterface::setOverlayFormats(const CameraParameters& params)
+{
+ mParameters.set("overlay-format", HAL_PIXEL_FORMAT_YCbCr_420_SP);
+ if(mIs3DModeOn == true) {
+ int ovFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP|HAL_3D_IN_SIDE_BY_SIDE_L_R|HAL_3D_OUT_SIDE_BY_SIDE;
+ mParameters.set("overlay-format", ovFormat);
+ }
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setMCEValue(const CameraParameters& params)
+{
+ LOGE("%s",__func__);
+ status_t rc = NO_ERROR;
+ rc = cam_config_is_parm_supported(mCameraId,MM_CAMERA_PARM_MCE);
+ if(!rc) {
+ LOGE("MM_CAMERA_PARM_MCE mode is not supported for this sensor");
+ return NO_ERROR;
+ }
+ const char *str = params.get(CameraParameters::KEY_MEMORY_COLOR_ENHANCEMENT);
+ if (str != NULL) {
+ int value = attr_lookup(mce, sizeof(mce) / sizeof(str_map), str);
+ if (value != NOT_FOUND) {
+ int temp = (int8_t)value;
+ LOGI("%s: setting MCE value of %s", __FUNCTION__, str);
+ mParameters.set(CameraParameters::KEY_MEMORY_COLOR_ENHANCEMENT, str);
+
+ native_set_parms(MM_CAMERA_PARM_MCE, sizeof(int8_t), (void *)&temp);
+ return NO_ERROR;
+ }
+ }
+ LOGE("Invalid MCE value: %s", (str == NULL) ? "NULL" : str);
+
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setHighFrameRate(const CameraParameters& params)
+{
+
+ bool mCameraRunning;
+
+ int rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_HFR);
+ if(!rc) {
+ LOGE("%s: MM_CAMERA_PARM_HFR not supported", __func__);
+ return NO_ERROR;
+ }
+
+ const char *str = params.get(CameraParameters::KEY_VIDEO_HIGH_FRAME_RATE);
+ if (str != NULL) {
+ int value = attr_lookup(hfr, sizeof(hfr) / sizeof(str_map), str);
+ if (value != NOT_FOUND) {
+ mHFRLevel = (int32_t)value;
+ //Check for change in HFR value
+ const char *oldHfr = mParameters.get(CameraParameters::KEY_VIDEO_HIGH_FRAME_RATE);
+ if(strcmp(oldHfr, str)){
+ mParameters.set(CameraParameters::KEY_VIDEO_HIGH_FRAME_RATE, str);
+// mHFRMode = true;
+ mCameraRunning=isPreviewRunning();
+ if(mCameraRunning == true) {
+// mHFRThreadWaitLock.lock();
+// pthread_attr_t pattr;
+// pthread_attr_init(&pattr);
+// pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);
+// mHFRThreadRunning = !pthread_create(&mHFRThread,
+// &pattr,
+// hfr_thread,
+// (void*)NULL);
+// mHFRThreadWaitLock.unlock();
+ stopPreviewInternal();
+ mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED;
+ native_set_parms(MM_CAMERA_PARM_HFR, sizeof(int32_t), (void *)&mHFRLevel);
+ mPreviewState = QCAMERA_HAL_PREVIEW_START;
+ if (startPreview2() == NO_ERROR)
+ mPreviewState = QCAMERA_HAL_PREVIEW_STARTED;
+ return NO_ERROR;
+ }
+ }
+ native_set_parms(MM_CAMERA_PARM_HFR, sizeof(int32_t), (void *)&mHFRLevel);
+ return NO_ERROR;
+ }
+ }
+ LOGE("Invalid HFR value: %s", (str == NULL) ? "NULL" : str);
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setLensshadeValue(const CameraParameters& params)
+{
+
+ int rc = cam_config_is_parm_supported(mCameraId, MM_CAMERA_PARM_ROLLOFF);
+ if(!rc) {
+ LOGE("%s:LENS SHADING not supported", __func__);
+ return NO_ERROR;
+ }
+
+ const char *str = params.get(CameraParameters::KEY_LENSSHADE);
+ if (str != NULL) {
+ int value = attr_lookup(lensshade,
+ sizeof(lensshade) / sizeof(str_map), str);
+ if (value != NOT_FOUND) {
+ int8_t temp = (int8_t)value;
+ mParameters.set(CameraParameters::KEY_LENSSHADE, str);
+ native_set_parms(MM_CAMERA_PARM_ROLLOFF, sizeof(int8_t), (void *)&temp);
+ return NO_ERROR;
+ }
+ }
+ LOGE("Invalid lensShade value: %s", (str == NULL) ? "NULL" : str);
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setFaceDetect(const CameraParameters& params)
+{
+ const char *str = params.get(CameraParameters::KEY_FACE_DETECTION);
+ LOGE("setFaceDetect: %s", str);
+ if (str != NULL) {
+ int value = attr_lookup(facedetection,
+ sizeof(facedetection) / sizeof(str_map), str);
+ mFaceDetectOn = value;
+ LOGE("%s Face detection value = %d",__func__, value);
+ cam_ctrl_dimension_t dim;
+// cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim);
+// preview_parm_config (&dim, mParameters);
+// cam_config_set_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim);
+ native_set_parms(MM_CAMERA_PARM_FD, sizeof(int8_t), (void *)&value);
+ mParameters.set(CameraParameters::KEY_FACE_DETECTION, str);
+ return NO_ERROR;
+ }
+ LOGE("Invalid Face Detection value: %s", (str == NULL) ? "NULL" : str);
+ return BAD_VALUE;
+}
+status_t QCameraHardwareInterface::setFaceDetection(const char *str)
+{
+ if(supportsFaceDetection() == false){
+ LOGE("Face detection is not enabled");
+ return NO_ERROR;
+ }
+ if (str != NULL) {
+ int value = attr_lookup(facedetection,
+ sizeof(facedetection) / sizeof(str_map), str);
+ if (value != NOT_FOUND) {
+ mMetaDataWaitLock.lock();
+ mFaceDetectOn = value;
+ mMetaDataWaitLock.unlock();
+ mParameters.set(CameraParameters::KEY_FACE_DETECTION, str);
+ native_set_parms(MM_CAMERA_PARM_FD, sizeof(int8_t), (void *)&value);
+ mParameters.set(CameraParameters::KEY_FACE_DETECTION, str);
+ return NO_ERROR;
+ }
+ }
+ LOGE("Invalid Face Detection value: %s", (str == NULL) ? "NULL" : str);
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setAEBracket(const CameraParameters& params)
+{
+ if(!cam_config_is_parm_supported(mCameraId,MM_CAMERA_PARM_HDR) || (myMode & CAMERA_ZSL_MODE)) {
+ LOGI("Parameter HDR is not supported for this sensor/ ZSL mode");
+
+ if (myMode & CAMERA_ZSL_MODE) {
+ LOGE("In ZSL mode, reset AEBBracket to HDR_OFF mode");
+ exp_bracketing_t temp;
+ memset(&temp, 0, sizeof(temp));
+ mHdrMode = HDR_BRACKETING_OFF;
+ temp.hdr_enable= FALSE;
+ temp.mode = HDR_BRACKETING_OFF;
+ native_set_parms(MM_CAMERA_PARM_HDR, sizeof(exp_bracketing_t), (void *)&temp);
+ }
+ return NO_ERROR;
+ }
+ const char *str = params.get(CameraParameters::KEY_AE_BRACKET_HDR);
+
+ if (str != NULL) {
+ int value = attr_lookup(hdr_bracket,
+ sizeof(hdr_bracket) / sizeof(str_map), str);
+ exp_bracketing_t temp;
+ memset(&temp, 0, sizeof(temp));
+ switch (value) {
+ case HDR_MODE:
+ {
+ mHdrMode = HDR_MODE;
+ temp.hdr_enable= TRUE;
+ temp.mode = HDR_MODE;
+ temp.total_frames = 3;
+ temp.total_hal_frames = getNumOfSnapshots();
+ LOGI("%s: setting HDR frames (%d)", __FUNCTION__, temp.total_hal_frames);
+ native_set_parms(MM_CAMERA_PARM_HDR, sizeof(exp_bracketing_t), (void *)&temp);
+ }
+ break;
+ case EXP_BRACKETING_MODE:
+ {
+ int numFrames = getNumOfSnapshots();
+ const char *str_val = params.get("capture-burst-exposures");
+ if ((str_val != NULL) && (strlen(str_val)>0)) {
+ LOGI("%s: capture-burst-exposures %s", __FUNCTION__, str_val);
+
+ mHdrMode = EXP_BRACKETING_MODE;
+ temp.hdr_enable = FALSE;
+ temp.mode = EXP_BRACKETING_MODE;
+ temp.total_frames = (numFrames > MAX_SNAPSHOT_BUFFERS -2) ? MAX_SNAPSHOT_BUFFERS -2 : numFrames;
+ temp.total_hal_frames = temp.total_frames;
+ strlcpy(temp.values, str_val, MAX_EXP_BRACKETING_LENGTH);
+ LOGI("%s: setting Exposure Bracketing value of %s, frame (%d)", __FUNCTION__, temp.values, temp.total_hal_frames);
+ native_set_parms(MM_CAMERA_PARM_HDR, sizeof(exp_bracketing_t), (void *)&temp);
+ }
+ else {
+ /* Apps not set capture-burst-exposures, error case fall into bracketing off mode */
+ LOGI("%s: capture-burst-exposures not set, back to HDR OFF mode", __FUNCTION__);
+ mHdrMode = HDR_BRACKETING_OFF;
+ temp.hdr_enable= FALSE;
+ temp.mode = HDR_BRACKETING_OFF;
+ native_set_parms(MM_CAMERA_PARM_HDR, sizeof(exp_bracketing_t), (void *)&temp);
+ }
+ }
+ break;
+ case HDR_BRACKETING_OFF:
+ default:
+ {
+ mHdrMode = HDR_BRACKETING_OFF;
+ temp.hdr_enable= FALSE;
+ temp.mode = HDR_BRACKETING_OFF;
+ native_set_parms(MM_CAMERA_PARM_HDR, sizeof(exp_bracketing_t), (void *)&temp);
+ }
+ break;
+ }
+
+ /* save the value*/
+ mParameters.set(CameraParameters::KEY_AE_BRACKET_HDR, str);
+ }
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setCaptureBurstExp()
+{
+ char burst_exp[PROPERTY_VALUE_MAX];
+ memset(burst_exp, 0, sizeof(burst_exp));
+ property_get("persist.capture.burst.exposures", burst_exp, "");
+ if (NULL != burst_exp)
+ mParameters.set("capture-burst-exposures", burst_exp);
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setRedeyeReduction(const CameraParameters& params)
+{
+ if(supportsRedEyeReduction() == false) {
+ LOGE("Parameter Redeye Reduction is not supported for this sensor");
+ return NO_ERROR;
+ }
+
+ const char *str = params.get(CameraParameters::KEY_REDEYE_REDUCTION);
+ if (str != NULL) {
+ int value = attr_lookup(redeye_reduction, sizeof(redeye_reduction) / sizeof(str_map), str);
+ if (value != NOT_FOUND) {
+ int8_t temp = (int8_t)value;
+ LOGI("%s: setting Redeye Reduction value of %s", __FUNCTION__, str);
+ mParameters.set(CameraParameters::KEY_REDEYE_REDUCTION, str);
+
+ native_set_parms(MM_CAMERA_PARM_REDEYE_REDUCTION, sizeof(int8_t), (void *)&temp);
+ return NO_ERROR;
+ }
+ }
+ LOGE("Invalid Redeye Reduction value: %s", (str == NULL) ? "NULL" : str);
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setGpsLocation(const CameraParameters& params)
+{
+ const char *method = params.get(CameraParameters::KEY_GPS_PROCESSING_METHOD);
+ if (method) {
+ mParameters.set(CameraParameters::KEY_GPS_PROCESSING_METHOD, method);
+ }else {
+ mParameters.remove(CameraParameters::KEY_GPS_PROCESSING_METHOD);
+ }
+
+ const char *latitude = params.get(CameraParameters::KEY_GPS_LATITUDE);
+ if (latitude) {
+ LOGE("latitude %s",latitude);
+ mParameters.set(CameraParameters::KEY_GPS_LATITUDE, latitude);
+ }else {
+ mParameters.remove(CameraParameters::KEY_GPS_LATITUDE);
+ }
+
+ const char *latitudeRef = params.get(CameraParameters::KEY_GPS_LATITUDE_REF);
+ if (latitudeRef) {
+ mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF, latitudeRef);
+ }else {
+ mParameters.remove(CameraParameters::KEY_GPS_LATITUDE_REF);
+ }
+
+ const char *longitude = params.get(CameraParameters::KEY_GPS_LONGITUDE);
+ if (longitude) {
+ mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, longitude);
+ }else {
+ mParameters.remove(CameraParameters::KEY_GPS_LONGITUDE);
+ }
+
+ const char *longitudeRef = params.get(CameraParameters::KEY_GPS_LONGITUDE_REF);
+ if (longitudeRef) {
+ mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, longitudeRef);
+ }else {
+ mParameters.remove(CameraParameters::KEY_GPS_LONGITUDE_REF);
+ }
+
+ const char *altitudeRef = params.get(CameraParameters::KEY_GPS_ALTITUDE_REF);
+ if (altitudeRef) {
+ mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, altitudeRef);
+ }else {
+ mParameters.remove(CameraParameters::KEY_GPS_ALTITUDE_REF);
+ }
+
+ const char *altitude = params.get(CameraParameters::KEY_GPS_ALTITUDE);
+ if (altitude) {
+ mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, altitude);
+ }else {
+ mParameters.remove(CameraParameters::KEY_GPS_ALTITUDE);
+ }
+
+ const char *status = params.get(CameraParameters::KEY_GPS_STATUS);
+ if (status) {
+ mParameters.set(CameraParameters::KEY_GPS_STATUS, status);
+ }
+
+ const char *dateTime = params.get(CameraParameters::KEY_EXIF_DATETIME);
+ if (dateTime) {
+ mParameters.set(CameraParameters::KEY_EXIF_DATETIME, dateTime);
+ }else {
+ mParameters.remove(CameraParameters::KEY_EXIF_DATETIME);
+ }
+
+ const char *timestamp = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
+ if (timestamp) {
+ mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, timestamp);
+ }else {
+ mParameters.remove(CameraParameters::KEY_GPS_TIMESTAMP);
+ }
+ LOGE("setGpsLocation X");
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setRotation(const CameraParameters& params)
+{
+ status_t rc = NO_ERROR;
+ int rotation = params.getInt(CameraParameters::KEY_ROTATION);
+ if (rotation != NOT_FOUND) {
+ if (rotation == 0 || rotation == 90 || rotation == 180
+ || rotation == 270) {
+ mParameters.set(CameraParameters::KEY_ROTATION, rotation);
+ mRotation = rotation;
+ } else {
+ LOGE("Invalid rotation value: %d", rotation);
+ rc = BAD_VALUE;
+ }
+ }
+ LOGE("setRotation");
+ return rc;
+}
+
+status_t QCameraHardwareInterface::setDenoise(const CameraParameters& params)
+{
+#if 0
+ if(!mCfgControl.mm_camera_is_supported(MM_CAMERA_PARM_WAVELET_DENOISE)) {
+ LOGE("Wavelet Denoise is not supported for this sensor");
+ return NO_ERROR;
+ }
+ const char *str = params.get(CameraParameters::KEY_DENOISE);
+ if (str != NULL) {
+ int value = attr_lookup(denoise,
+ sizeof(denoise) / sizeof(str_map), str);
+ if ((value != NOT_FOUND) && (mDenoiseValue != value)) {
+ mDenoiseValue = value;
+ mParameters.set(CameraParameters::KEY_DENOISE, str);
+ bool ret = native_set_parms(MM_CAMERA_PARM_WAVELET_DENOISE, sizeof(value),
+ (void *)&value);
+ return ret ? NO_ERROR : UNKNOWN_ERROR;
+ }
+ return NO_ERROR;
+ }
+ LOGE("Invalid Denoise value: %s", (str == NULL) ? "NULL" : str);
+#endif
+ return BAD_VALUE;
+}
+
+status_t QCameraHardwareInterface::setOrientation(const CameraParameters& params)
+{
+ const char *str = params.get("orientation");
+
+ if (str != NULL) {
+ if (strcmp(str, "portrait") == 0 || strcmp(str, "landscape") == 0) {
+ // Camera service needs this to decide if the preview frames and raw
+ // pictures should be rotated.
+ mParameters.set("orientation", str);
+ } else {
+ LOGE("Invalid orientation value: %s", str);
+ return BAD_VALUE;
+ }
+ }
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setPictureFormat(const CameraParameters& params)
+{
+ const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
+
+ if(str != NULL){
+ int32_t value = attr_lookup(picture_formats,
+ sizeof(picture_formats) / sizeof(str_map), str);
+ if(value != NOT_FOUND){
+ mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
+ } else {
+ LOGE("Invalid Picture Format value: %s", str);
+ return BAD_VALUE;
+ }
+ }
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setRecordingHintValue(const int32_t value)
+{
+ native_set_parms(MM_CAMERA_PARM_RECORDING_HINT, sizeof(value),
+ (void *)&value);
+ if (value == TRUE){
+ native_set_parms(MM_CAMERA_PARM_CAF_ENABLE, sizeof(value),
+ (void *)&value);
+ }
+ setDISMode();
+ setFullLiveshot();
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setRecordingHint(const CameraParameters& params)
+{
+
+ const char * str = params.get(CameraParameters::KEY_RECORDING_HINT);
+
+ if(str != NULL){
+ int32_t value = attr_lookup(recording_Hints,
+ sizeof(recording_Hints) / sizeof(str_map), str);
+ if(value != NOT_FOUND){
+ mRecordingHint = value;
+ setRecordingHintValue(mRecordingHint);
+ mParameters.set(CameraParameters::KEY_RECORDING_HINT, str);
+ return NO_ERROR;
+ } else {
+ LOGE("Invalid Picture Format value: %s", str);
+ setDISMode();
+ setFullLiveshot();
+ return BAD_VALUE;
+ }
+ }
+ setDISMode();
+ setFullLiveshot();
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setDISMode() {
+ /* Enable DIS only if
+ * - Camcorder mode AND
+ * - DIS property is set AND
+ * - Not in Low power mode. */
+ uint32_t value = mRecordingHint && mDisEnabled
+ && !isLowPowerCamcorder();
+
+ LOGI("%s DIS is %s value = %d", __func__,
+ value ? "Enabled" : "Disabled", value);
+ native_set_parms(MM_CAMERA_PARM_DIS_ENABLE, sizeof(value),
+ (void *)&value);
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setFullLiveshot()
+{
+ /* Enable full size liveshot only if
+ * - Camcorder mode AND
+ * - Full size liveshot is enabled. */
+ uint32_t value = mRecordingHint && mFullLiveshotEnabled
+ && !isLowPowerCamcorder();
+
+ if (((mDimension.picture_width == mDimension.video_width) &&
+ (mDimension.picture_height == mDimension.video_height))) {
+ /* If video size matches the live snapshot size
+ * turn off full size liveshot to get higher fps. */
+ value = 0;
+ }
+
+ LOGI("%s Full size liveshot %s value = %d", __func__,
+ value ? "Enabled" : "Disabled", value);
+ native_set_parms(MM_CAMERA_PARM_FULL_LIVESHOT, sizeof(value),
+ (void *)&value);
+ return NO_ERROR;
+}
+
+
+isp3a_af_mode_t QCameraHardwareInterface::getAutoFocusMode(
+ const CameraParameters& params)
+{
+ isp3a_af_mode_t afMode = AF_MODE_MAX;
+ afMode = (isp3a_af_mode_t)mFocusMode;
+ return afMode;
+}
+
+void QCameraHardwareInterface::getPictureSize(int *picture_width,
+ int *picture_height) const
+{
+ mParameters.getPictureSize(picture_width, picture_height);
+}
+
+void QCameraHardwareInterface::getPreviewSize(int *preview_width,
+ int *preview_height) const
+{
+ mParameters.getPreviewSize(preview_width, preview_height);
+}
+
+cam_format_t QCameraHardwareInterface::getPreviewFormat() const
+{
+ cam_format_t foramt = CAMERA_YUV_420_NV21;
+ const char *str = mParameters.getPreviewFormat();
+ int32_t value = attr_lookup(preview_formats,
+ sizeof(preview_formats)/sizeof(str_map),
+ str);
+
+ if(value != NOT_FOUND) {
+ int num = sizeof(preview_format_info_list)/sizeof(preview_format_info_t);
+ int i;
+ for (i = 0; i < num; i++) {
+ if (preview_format_info_list[i].Hal_format == value) {
+ foramt = preview_format_info_list[i].mm_cam_format;
+ break;
+ }
+ }
+ }
+
+ return foramt;
+}
+
+cam_pad_format_t QCameraHardwareInterface::getPreviewPadding() const
+{
+ return mPreviewFormatInfo.padding;
+}
+
+int QCameraHardwareInterface::getJpegQuality() const
+{
+ return mJpegQuality;
+}
+
+int QCameraHardwareInterface::getNumOfSnapshots(void) const
+{
+ char prop[PROPERTY_VALUE_MAX];
+ memset(prop, 0, sizeof(prop));
+ property_get("persist.camera.snapshot.number", prop, "0");
+ LOGI("%s: prop enable/disable = %d", __func__, atoi(prop));
+ if (atoi(prop)) {
+ LOGE("%s: Reading maximum no of snapshots = %d"
+ "from properties", __func__, atoi(prop));
+ return atoi(prop);
+ } else {
+ return mParameters.getInt("num-snaps-per-shutter");
+ }
+}
+
+int QCameraHardwareInterface::getNumOfSnapshots(const CameraParameters& params)
+{
+ char prop[PROPERTY_VALUE_MAX];
+ memset(prop, 0, sizeof(prop));
+ property_get("persist.camera.snapshot.number", prop, "0");
+ LOGI("%s: prop enable/disable = %d", __func__, atoi(prop));
+ if (atoi(prop)) {
+ LOGI("%s: Reading maximum no of snapshots = %d"
+ "from properties", __func__, atoi(prop));
+ return atoi(prop);
+ } else {
+ return params.getInt("num-snaps-per-shutter");
+ }
+
+}
+
+int QCameraHardwareInterface::
+getThumbSizesFromAspectRatio(uint32_t aspect_ratio,
+ int *picture_width,
+ int *picture_height)
+{
+ for(unsigned int i = 0; i < THUMBNAIL_SIZE_COUNT; i++ ){
+ if(thumbnail_sizes[i].aspect_ratio == aspect_ratio)
+ {
+ *picture_width = thumbnail_sizes[i].width;
+ *picture_height = thumbnail_sizes[i].height;
+ return NO_ERROR;
+ }
+ }
+
+ return BAD_VALUE;
+}
+
+bool QCameraHardwareInterface::isRawSnapshot()
+{
+ const char *format = mParameters.getPictureFormat();
+ if( format!= NULL &&
+ !strcmp(format, CameraParameters::PIXEL_FORMAT_RAW)){
+ return true;
+ }
+ else{
+ return false;
+ }
+}
+
+status_t QCameraHardwareInterface::setPreviewSizeTable(void)
+{
+ status_t ret = NO_ERROR;
+ mm_camera_dimension_t dim;
+ struct camera_size_type* preview_size_table;
+ int preview_table_size;
+ int i = 0;
+ char str[10] = {0};
+
+ /* Initialize table with default values */
+ preview_size_table = default_preview_sizes;
+ preview_table_size = preview_sizes_count;
+
+
+ /* Get maximum preview size supported by sensor*/
+ memset(&dim, 0, sizeof(mm_camera_dimension_t));
+ ret = cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_MAX_PREVIEW_SIZE, &dim);
+ if (ret != NO_ERROR) {
+ LOGE("%s: Failure getting Max Preview Size supported by camera",
+ __func__);
+ goto end;
+ }
+
+ LOGD("%s: Max Preview Sizes Supported: %d X %d", __func__,
+ dim.width, dim.height);
+
+ for (i = 0; i < preview_table_size; i++) {
+ if ((preview_size_table->width <= dim.width) &&
+ (preview_size_table->height <= dim.height)) {
+ LOGD("%s: Camera Preview Size Table "
+ "Max width: %d height %d table_size: %d",
+ __func__, preview_size_table->width,
+ preview_size_table->height, preview_table_size - i);
+ break;
+ }
+ preview_size_table++;
+ }
+ //set preferred preview size to maximum preview size
+ sprintf(str, "%dx%d", preview_size_table->width, preview_size_table->height);
+ mParameters.set(CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO, str);
+ LOGD("KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO = %s", str);
+
+end:
+ /* Save the table in global member*/
+ mPreviewSizes = preview_size_table;
+ mPreviewSizeCount = preview_table_size - i;
+
+ return ret;
+}
+
+status_t QCameraHardwareInterface::setPictureSizeTable(void)
+{
+ status_t ret = NO_ERROR;
+ mm_camera_dimension_t dim;
+ struct camera_size_type* picture_size_table;
+ int picture_table_size;
+ int i = 0, count = 0;
+
+ /* Initialize table with default values */
+ picture_table_size = sizeof(default_picture_sizes)/
+ sizeof(default_picture_sizes[0]);
+ picture_size_table = default_picture_sizes;
+ mPictureSizes =
+ ( struct camera_size_type *)malloc(picture_table_size *
+ sizeof(struct camera_size_type));
+ if (mPictureSizes == NULL) {
+ LOGE("%s: Failre allocating memory to store picture size table",__func__);
+ goto end;
+ }
+
+ /* Get maximum picture size supported by sensor*/
+ memset(&dim, 0, sizeof(mm_camera_dimension_t));
+ ret = cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_MAX_PICTURE_SIZE, &dim);
+ if (ret != NO_ERROR) {
+ LOGE("%s: Failure getting Max Picture Size supported by camera",
+ __func__);
+ ret = NO_MEMORY;
+ free(mPictureSizes);
+ mPictureSizes = NULL;
+ goto end;
+ }
+
+ LOGD("%s: Max Picture Sizes Supported: %d X %d", __func__,
+ dim.width, dim.height);
+
+ for (i = 0; i < picture_table_size; i++) {
+ /* We'll store those dimensions whose width AND height
+ are less than or equal to maximum supported */
+ if ((picture_size_table->width <= dim.width) &&
+ (picture_size_table->height <= dim.height)) {
+ LOGD("%s: Camera Picture Size Table "
+ "Max width: %d height %d table_size: %d",
+ __func__, picture_size_table->width,
+ picture_size_table->height, count+1);
+ mPictureSizes[count].height = picture_size_table->height;
+ mPictureSizes[count].width = picture_size_table->width;
+ count++;
+ }
+ picture_size_table++;
+ }
+ mPictureSizeCount = count;
+
+end:
+ /* In case of error, we use default picture sizes */
+ if (ret != NO_ERROR) {
+ mPictureSizes = default_picture_sizes;
+ mPictureSizeCount = picture_table_size;
+ }
+ return ret;
+}
+
+status_t QCameraHardwareInterface::setVideoSizeTable(void)
+{
+ status_t ret = NO_ERROR;
+ mm_camera_dimension_t dim;
+ struct camera_size_type* video_size_table;
+ int video_table_size;
+ int i = 0, count = 0;
+ LOGE("%s: E", __func__);
+
+ /* Initialize table with default values */
+ video_table_size = video_sizes_count;
+ video_size_table = default_video_sizes;
+ mVideoSizes =
+ (struct camera_size_type *)malloc(video_table_size *
+ sizeof(struct camera_size_type));
+ if(mVideoSizes == NULL) {
+ LOGE("%s: error allocating memory to store video size table",__func__);
+ ret = BAD_VALUE;
+ goto end;
+ }
+
+ /* Get maximum video size supported by sensor*/
+ memset(&dim, 0, sizeof(mm_camera_dimension_t));
+ ret = cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_MAX_VIDEO_SIZE, &dim);
+ if(ret != NO_ERROR) {
+ LOGE("%s: error getting Max Video Size supported by camera",
+ __func__);
+ ret = NO_MEMORY;
+ free(mVideoSizes);
+ mVideoSizes = NULL;
+ ret = BAD_VALUE;
+ goto end;
+ }
+
+ LOGD("%s: Max Video Size Supported: %d X %d", __func__,
+ dim.width, dim.height);
+
+ for(i=0; i < video_table_size; i++) {
+ /* We'll store those dimensions whose width AND height
+ are less than or equal to maximum supported */
+ if((video_size_table->width <= dim.width) &&
+ (video_size_table->height <= dim.height)) {
+ LOGD("%s: Supported Video Size [%d] = %dx%d", __func__, count, video_size_table->width,
+ video_size_table->height);
+ mVideoSizes[count].height = video_size_table->height;
+ mVideoSizes[count].width = video_size_table->width;
+ count++;
+ }
+ video_size_table++;
+ }
+ mVideoSizeCount = count;
+
+end:
+ LOGE("%s: X", __func__);
+ return ret;
+}
+
+void QCameraHardwareInterface::freeVideoSizeTable(void)
+{
+ if(mVideoSizes != NULL)
+ {
+ free(mVideoSizes);
+ }
+ mVideoSizeCount = 0;
+}
+
+
+void QCameraHardwareInterface::freePictureTable(void)
+{
+ /* If we couldn't allocate memory to store picture table
+ we use the picture table pointer to point to default
+ picture table array. In that case we cannot free it.*/
+ if ((mPictureSizes != default_picture_sizes) && mPictureSizes) {
+ free(mPictureSizes);
+ }
+}
+
+status_t QCameraHardwareInterface::setHistogram(int histogram_en)
+{
+ LOGE("setHistogram: E");
+ if(mStatsOn == histogram_en) {
+ return NO_ERROR;
+ }
+
+ mSendData = histogram_en;
+ mStatsOn = histogram_en;
+ mCurrentHisto = -1;
+ mStatSize = sizeof(uint32_t)* HISTOGRAM_STATS_SIZE;
+
+ if (histogram_en == QCAMERA_PARM_ENABLE) {
+ /*Currently the Ashmem is multiplying the buffer size with total number
+ of buffers and page aligning. This causes a crash in JNI as each buffer
+ individually expected to be page aligned */
+ int page_size_minus_1 = getpagesize() - 1;
+ int statSize = sizeof (camera_preview_histogram_info );
+ int32_t mAlignedStatSize = ((statSize + page_size_minus_1) & (~page_size_minus_1));
+#if 0
+ mStatHeap =
+ new AshmemPool(mAlignedStatSize, 3, statSize, "stat");
+ if (!mStatHeap->initialized()) {
+ LOGE("Stat Heap X failed ");
+ mStatHeap.clear();
+ mStatHeap = NULL;
+ return UNKNOWN_ERROR;
+ }
+#endif
+ for(int cnt = 0; cnt<3; cnt++) {
+ mStatsMapped[cnt]=mGetMemory(-1, mStatSize, 1, mCallbackCookie);
+ if(mStatsMapped[cnt] == NULL) {
+ LOGE("Failed to get camera memory for stats heap index: %d", cnt);
+ return(-1);
+ } else {
+ LOGE("Received following info for stats mapped data:%p,handle:%p, size:%d,release:%p",
+ mStatsMapped[cnt]->data ,mStatsMapped[cnt]->handle, mStatsMapped[cnt]->size, mStatsMapped[cnt]->release);
+ }
+ mHistServer.size = sizeof(camera_preview_histogram_info);
+#ifdef USE_ION
+ if(allocate_ion_memory(&mHistServer, cnt, ION_CP_MM_HEAP_ID) < 0) {
+ LOGE("%s ION alloc failed\n", __func__);
+ return -1;
+ }
+#else
+ mHistServer.fd[cnt] = open("/dev/pmem_adsp", O_RDWR|O_SYNC);
+ if(mHistServer.fd[cnt] <= 0) {
+ LOGE("%s: no pmem for frame %d", __func__, cnt);
+ return -1;
+ }
+#endif
+ mHistServer.camera_memory[cnt]=mGetMemory(mHistServer.fd[cnt],mHistServer.size, 1, mCallbackCookie);
+ if(mHistServer.camera_memory[cnt] == NULL) {
+ LOGE("Failed to get camera memory for server side histogram index: %d", cnt);
+ return(-1);
+ } else {
+ LOGE("Received following info for server side histogram data:%p,handle:%p, size:%d,release:%p",
+ mHistServer.camera_memory[cnt]->data ,mHistServer.camera_memory[cnt]->handle,
+ mHistServer.camera_memory[cnt]->size, mHistServer.camera_memory[cnt]->release);
+ }
+ /*Register buffer at back-end*/
+ if (NO_ERROR != sendMappingBuf(0, cnt, mHistServer.fd[cnt],
+ mHistServer.size, mCameraId,
+ CAM_SOCK_MSG_TYPE_HIST_MAPPING)) {
+ LOGE("%s could not send buffer to back-end\n", __func__);
+ }
+ }
+ }
+ LOGV("Setting histogram = %d", histogram_en);
+ native_set_parms(MM_CAMERA_PARM_HISTOGRAM, sizeof(int), &histogram_en);
+ if(histogram_en == QCAMERA_PARM_DISABLE)
+ {
+ //release memory
+ for(int i=0; i<3; i++){
+ if(mStatsMapped[i] != NULL) {
+ mStatsMapped[i]->release(mStatsMapped[i]);
+ }
+ /*Unregister buffer at back-end */
+ if (NO_ERROR != sendUnMappingBuf(0, i, mCameraId, CAM_SOCK_MSG_TYPE_HIST_UNMAPPING)) {
+ LOGE("%s could not unregister buffer from back-end\n", __func__);
+ }
+ if(mHistServer.camera_memory[i] != NULL) {
+ mHistServer.camera_memory[i]->release(mHistServer.camera_memory[i]);
+ }
+ close(mHistServer.fd[i]);
+#ifdef USE_ION
+ deallocate_ion_memory(&mHistServer, i);
+#endif
+ }
+ }
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setZSLBurstLookBack(const CameraParameters& params)
+{
+ const char *v = params.get("capture-burst-retroactive");
+ if (v) {
+ int look_back = atoi(v);
+ LOGI("%s: look_back =%d", __func__, look_back);
+ mParameters.set("capture-burst-retroactive", look_back);
+ }
+ return NO_ERROR;
+}
+
+status_t QCameraHardwareInterface::setZSLBurstInterval(const CameraParameters& params)
+{
+ mZslInterval = BURST_INTREVAL_DEFAULT;
+ const char *v = params.get("capture-burst-interval");
+ if (v) {
+ int interval = atoi(v);
+ LOGI("%s: Interval =%d", __func__, interval);
+ if(interval < BURST_INTREVAL_MIN ||interval > BURST_INTREVAL_MAX ) {
+ return BAD_VALUE;
+ }
+ mZslInterval = interval;
+ }
+ return NO_ERROR;
+}
+
+int QCameraHardwareInterface::getZSLBurstInterval( void )
+{
+ int val;
+
+ if (mZslInterval == BURST_INTREVAL_DEFAULT) {
+ char prop[PROPERTY_VALUE_MAX];
+ memset(prop, 0, sizeof(prop));
+ property_get("persist.camera.zsl.interval", prop, "1");
+ val = atoi(prop);
+ LOGD("%s: prop interval = %d", __func__, val);
+ } else {
+ val = mZslInterval;
+ }
+ return val;
+}
+
+
+int QCameraHardwareInterface::getZSLQueueDepth(void) const
+{
+ char prop[PROPERTY_VALUE_MAX];
+ memset(prop, 0, sizeof(prop));
+ property_get("persist.camera.zsl.queuedepth", prop, "2");
+ LOGI("%s: prop = %d", __func__, atoi(prop));
+ return atoi(prop);
+}
+
+int QCameraHardwareInterface::getZSLBackLookCount(void) const
+{
+ int look_back;
+ char prop[PROPERTY_VALUE_MAX];
+ memset(prop, 0, sizeof(prop));
+ property_get("persist.camera.zsl.backlookcnt", prop, "0");
+ LOGI("%s: prop = %d", __func__, atoi(prop));
+ look_back = atoi(prop);
+ if (look_back == 0 ) {
+ look_back = mParameters.getInt("capture-burst-retroactive");
+ LOGE("%s: look_back = %d", __func__, look_back);
+ }
+ return look_back;
+}
+
+//EXIF functions
+void QCameraHardwareInterface::deinitExifData()
+{
+ LOGD("Clearing EXIF data");
+ for(int i=0; i<MAX_EXIF_TABLE_ENTRIES; i++)
+ {
+ //clear all data
+ memset(&mExifData[i], 0x00, sizeof(exif_tags_info_t));
+ }
+ mExifTableNumEntries = 0;
+}
+
+void QCameraHardwareInterface::addExifTag(exif_tag_id_t tagid, exif_tag_type_t type,
+ uint32_t count, uint8_t copy, void *data) {
+
+ if(mExifTableNumEntries >= MAX_EXIF_TABLE_ENTRIES) {
+ LOGE("%s: Number of entries exceeded limit", __func__);
+ return;
+ }
+ int index = mExifTableNumEntries;
+ mExifData[index].tag_id = tagid;
+ mExifData[index].tag_entry.type = type;
+ mExifData[index].tag_entry.count = count;
+ mExifData[index].tag_entry.copy = copy;
+ if((type == EXIF_RATIONAL) && (count > 1))
+ mExifData[index].tag_entry.data._rats = (rat_t *)data;
+ if((type == EXIF_RATIONAL) && (count == 1))
+ mExifData[index].tag_entry.data._rat = *(rat_t *)data;
+ else if(type == EXIF_ASCII)
+ mExifData[index].tag_entry.data._ascii = (char *)data;
+ else if(type == EXIF_BYTE)
+ mExifData[index].tag_entry.data._byte = *(uint8_t *)data;
+ else if((type == EXIF_SHORT) && (count > 1))
+ mExifData[index].tag_entry.data._shorts = (uint16_t *)data;
+ else if((type == EXIF_SHORT) && (count == 1))
+ mExifData[index].tag_entry.data._short = *(uint16_t *)data;
+ // Increase number of entries
+ mExifTableNumEntries++;
+}
+
+rat_t getRational(int num, int denom)
+{
+ rat_t temp = {num, denom};
+ return temp;
+}
+
+void QCameraHardwareInterface::initExifData(){
+ if(mExifValues.dateTime) {
+ addExifTag(EXIFTAGID_EXIF_DATE_TIME_ORIGINAL, EXIF_ASCII,
+ 20, 1, (void *)mExifValues.dateTime);
+ }
+ addExifTag(EXIFTAGID_FOCAL_LENGTH, EXIF_RATIONAL, 1, 1, (void *)&(mExifValues.focalLength));
+ addExifTag(EXIFTAGID_ISO_SPEED_RATING,EXIF_SHORT,1,1,(void *)&(mExifValues.isoSpeed));
+
+ if(mExifValues.mGpsProcess) {
+ addExifTag(EXIFTAGID_GPS_PROCESSINGMETHOD, EXIF_ASCII,
+ EXIF_ASCII_PREFIX_SIZE + strlen(mExifValues.gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE) + 1,
+ 1, (void *)mExifValues.gpsProcessingMethod);
+ }
+
+ if(mExifValues.mLatitude) {
+ addExifTag(EXIFTAGID_GPS_LATITUDE, EXIF_RATIONAL, 3, 1, (void *)mExifValues.latitude);
+
+ if(mExifValues.latRef) {
+ addExifTag(EXIFTAGID_GPS_LATITUDE_REF, EXIF_ASCII, 2,
+ 1, (void *)mExifValues.latRef);
+ }
+ }
+
+ if(mExifValues.mLongitude) {
+ addExifTag(EXIFTAGID_GPS_LONGITUDE, EXIF_RATIONAL, 3, 1, (void *)mExifValues.longitude);
+
+ if(mExifValues.lonRef) {
+ addExifTag(EXIFTAGID_GPS_LONGITUDE_REF, EXIF_ASCII, 2,
+ 1, (void *)mExifValues.lonRef);
+ }
+ }
+
+ if(mExifValues.mAltitude) {
+ addExifTag(EXIFTAGID_GPS_ALTITUDE, EXIF_RATIONAL, 1,
+ 1, (void *)&(mExifValues.altitude));
+
+ addExifTag(EXIFTAGID_GPS_ALTITUDE_REF, EXIF_BYTE, 1, 1, (void *)&mExifValues.mAltitude_ref);
+ }
+
+ if(mExifValues.mTimeStamp) {
+ time_t unixTime;
+ struct tm *UTCTimestamp;
+
+ unixTime = (time_t)mExifValues.mGPSTimestamp;
+ UTCTimestamp = gmtime(&unixTime);
+
+ strftime(mExifValues.gpsDateStamp, sizeof(mExifValues.gpsDateStamp), "%Y:%m:%d", UTCTimestamp);
+ addExifTag(EXIFTAGID_GPS_DATESTAMP, EXIF_ASCII,
+ strlen(mExifValues.gpsDateStamp)+1 , 1, (void *)mExifValues.gpsDateStamp);
+
+ mExifValues.gpsTimeStamp[0] = getRational(UTCTimestamp->tm_hour, 1);
+ mExifValues.gpsTimeStamp[1] = getRational(UTCTimestamp->tm_min, 1);
+ mExifValues.gpsTimeStamp[2] = getRational(UTCTimestamp->tm_sec, 1);
+
+ addExifTag(EXIFTAGID_GPS_TIMESTAMP, EXIF_RATIONAL,
+ 3, 1, (void *)mExifValues.gpsTimeStamp);
+ LOGE("EXIFTAGID_GPS_TIMESTAMP set");
+ }
+
+}
+
+//Add all exif tags in this function
+void QCameraHardwareInterface::setExifTags()
+{
+ const char *str;
+
+ //set TimeStamp
+ str = mParameters.get(CameraParameters::KEY_EXIF_DATETIME);
+ if(str != NULL) {
+ strncpy(mExifValues.dateTime, str, 19);
+ mExifValues.dateTime[19] = '\0';
+ }
+
+ //Set focal length
+ int focalLengthValue = (int) (mParameters.getFloat(
+ CameraParameters::KEY_FOCAL_LENGTH) * FOCAL_LENGTH_DECIMAL_PRECISION);
+
+ mExifValues.focalLength = getRational(focalLengthValue, FOCAL_LENGTH_DECIMAL_PRECISION);
+
+ //Set ISO Speed
+ mExifValues.isoSpeed = getISOSpeedValue();
+
+ //set gps tags
+ setExifTagsGPS();
+}
+
+void QCameraHardwareInterface::setExifTagsGPS()
+{
+ const char *str = NULL;
+
+ //Set GPS processing method
+ str = mParameters.get(CameraParameters::KEY_GPS_PROCESSING_METHOD);
+ if(str != NULL) {
+ memcpy(mExifValues.gpsProcessingMethod, ExifAsciiPrefix, EXIF_ASCII_PREFIX_SIZE);
+ strncpy(mExifValues.gpsProcessingMethod + EXIF_ASCII_PREFIX_SIZE, str,
+ GPS_PROCESSING_METHOD_SIZE - 1);
+ mExifValues.gpsProcessingMethod[EXIF_ASCII_PREFIX_SIZE + GPS_PROCESSING_METHOD_SIZE-1] = '\0';
+ LOGE("EXIFTAGID_GPS_PROCESSINGMETHOD = %s %s", mExifValues.gpsProcessingMethod,
+ mExifValues.gpsProcessingMethod+8);
+ mExifValues.mGpsProcess = true;
+ }else{
+ mExifValues.mGpsProcess = false;
+ }
+ str = NULL;
+
+ //Set Latitude
+ str = mParameters.get(CameraParameters::KEY_GPS_LATITUDE);
+ if(str != NULL) {
+ parseGPSCoordinate(str, mExifValues.latitude);
+ LOGE("EXIFTAGID_GPS_LATITUDE = %s", str);
+
+ //set Latitude Ref
+ float latitudeValue = mParameters.getFloat(CameraParameters::KEY_GPS_LATITUDE);
+ if(latitudeValue < 0.0f) {
+ mExifValues.latRef[0] = 'S';
+ } else {
+ mExifValues.latRef[0] = 'N';
+ }
+ mExifValues.latRef[1] = '\0';
+ mExifValues.mLatitude = true;
+ mParameters.set(CameraParameters::KEY_GPS_LATITUDE_REF,mExifValues.latRef);
+ LOGE("EXIFTAGID_GPS_LATITUDE_REF = %s", mExifValues.latRef);
+ }else{
+ mExifValues.mLatitude = false;
+ }
+
+ //set Longitude
+ str = NULL;
+ str = mParameters.get(CameraParameters::KEY_GPS_LONGITUDE);
+ if(str != NULL) {
+ parseGPSCoordinate(str, mExifValues.longitude);
+ LOGE("EXIFTAGID_GPS_LONGITUDE = %s", str);
+
+ //set Longitude Ref
+ float longitudeValue = mParameters.getFloat(CameraParameters::KEY_GPS_LONGITUDE);
+ if(longitudeValue < 0.0f) {
+ mExifValues.lonRef[0] = 'W';
+ } else {
+ mExifValues.lonRef[0] = 'E';
+ }
+ mExifValues.lonRef[1] = '\0';
+ mExifValues.mLongitude = true;
+ LOGE("EXIFTAGID_GPS_LONGITUDE_REF = %s", mExifValues.lonRef);
+ mParameters.set(CameraParameters::KEY_GPS_LONGITUDE_REF, mExifValues.lonRef);
+ }else{
+ mExifValues.mLongitude = false;
+ }
+
+ //set Altitude
+ str = mParameters.get(CameraParameters::KEY_GPS_ALTITUDE);
+ if(str != NULL) {
+ double value = atof(str);
+ mExifValues.mAltitude_ref = 0;
+ if(value < 0){
+ mExifValues.mAltitude_ref = 1;
+ value = -value;
+ }
+ mExifValues.altitude = getRational(value*1000, 1000);
+ mExifValues.mAltitude = true;
+ //set AltitudeRef
+ mParameters.set(CameraParameters::KEY_GPS_ALTITUDE_REF, mExifValues.mAltitude_ref);
+ LOGE("EXIFTAGID_GPS_ALTITUDE = %f", value);
+ }else{
+ mExifValues.mAltitude = false;
+ }
+
+ //set Gps TimeStamp
+ str = NULL;
+ str = mParameters.get(CameraParameters::KEY_GPS_TIMESTAMP);
+ if(str != NULL) {
+ mExifValues.mTimeStamp = true;
+ mExifValues.mGPSTimestamp = atol(str);
+ }else{
+ mExifValues.mTimeStamp = false;
+ }
+}
+
+//latlonString is string formatted coordinate
+//coord is rat_t[3]
+void QCameraHardwareInterface::parseGPSCoordinate(const char *latlonString, rat_t* coord)
+{
+ if(coord == NULL) {
+ LOGE("%s: error, invalid argument coord == NULL", __func__);
+ return;
+ }
+ float degF = fabs(atof(latlonString));
+ float minF = (degF- (int) degF) * 60;
+ float secF = (minF - (int) minF) * 60;
+
+ coord[0] = getRational((int) degF, 1);
+ coord[1] = getRational((int) minF, 1);
+ coord[2] = getRational((int) (secF * 10000), 10000);
+}
+
+bool QCameraHardwareInterface::isLowPowerCamcorder() {
+
+ if (mPowerMode == LOW_POWER)
+ return true;
+
+ if(mHFRLevel > 1) /* hard code the value now. Need to move tgtcommon to camear.h */
+ return true;
+
+ return false;
+}
+
+status_t QCameraHardwareInterface::setNoDisplayMode(const CameraParameters& params)
+{
+ char prop[PROPERTY_VALUE_MAX];
+ memset(prop, 0, sizeof(prop));
+ property_get("persist.camera.nodisplay", prop, "0");
+ int prop_val = atoi(prop);
+
+ if (prop_val == 0) {
+ const char *str_val = params.get("no-display-mode");
+ if(str_val && strlen(str_val) > 0) {
+ mNoDisplayMode = atoi(str_val);
+ } else {
+ mNoDisplayMode = 0;
+ }
+ LOGD("Param mNoDisplayMode =%d", mNoDisplayMode);
+ } else {
+ mNoDisplayMode = prop_val;
+ LOGD("prop mNoDisplayMode =%d", mNoDisplayMode);
+ }
+ return NO_ERROR;
+}
+
+}; /*namespace android */
diff --git a/camera/QCamera/HAL/core/src/QCameraHWI_Preview.cpp b/camera/QCamera/HAL/core/src/QCameraHWI_Preview.cpp
new file mode 100755
index 0000000..9ecb85f
--- /dev/null
+++ b/camera/QCamera/HAL/core/src/QCameraHWI_Preview.cpp
@@ -0,0 +1,1434 @@
+/*
+** 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.
+** 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_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();
+ }
+ Mutex::Autolock lock(mStopCallbackLock);
+ mPreviewWindow = window;
+ 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;
+ int gralloc_usage;
+
+ LOGI(" %s : E ", __FUNCTION__);
+
+ if( mPreviewWindow == NULL) {
+ LOGE("%s: mPreviewWindow = NULL", __func__);
+ return INVALID_OPERATION;
+ }
+ cam_ctrl_dimension_t dim;
+
+ //mDisplayLock.lock();
+ ret = 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;
+ if(mHalCamCtrl->isZSLMode()) {
+ if(mHalCamCtrl->getZSLQueueDepth() > numMinUndequeuedBufs)
+ mHalCamCtrl->mPreviewMemory.buffer_count +=
+ mHalCamCtrl->getZSLQueueDepth() - 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;
+ }
+
+ ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_VFE_OUTPUT_ENABLE, &mVFEOutputs);
+ if(ret != MM_CAMERA_OK) {
+ LOGE("get parm MM_CAMERA_PARM_VFE_OUTPUT_ENABLE failed");
+ ret = BAD_VALUE;
+ goto end;
+ }
+
+ //as software encoder is used to encode 720p, to enhance the performance
+ //cashed pmem is used here
+ if(mVFEOutputs == 1 && dim.display_height == 720)
+ gralloc_usage = CAMERA_GRALLOC_HEAP_ID | CAMERA_GRALLOC_FALLBACK_HEAP_ID;
+ else
+ gralloc_usage = CAMERA_GRALLOC_HEAP_ID | CAMERA_GRALLOC_FALLBACK_HEAP_ID |
+ CAMERA_GRALLOC_CACHING_ID;
+ err = mPreviewWindow->set_usage(mPreviewWindow, gralloc_usage);
+ if(err != 0) {
+ /* set_usage error out */
+ LOGE("%s: set_usage rc = %d", __func__, err);
+ ret = UNKNOWN_ERROR;
+ goto end;
+ }
+ ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_HFR_FRAME_SKIP, &mHFRFrameSkip);
+ if(ret != MM_CAMERA_OK) {
+ LOGE("get parm MM_CAMERA_PARM_HFR_FRAME_SKIP failed");
+ ret = BAD_VALUE;
+ 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) {
+ LOGE("%s: dequeue buf hdl =%p", __func__, *mHalCamCtrl->mPreviewMemory.buffer_handle[cnt]);
+ err = mPreviewWindow->lock_buffer(this->mPreviewWindow,
+ mHalCamCtrl->mPreviewMemory.buffer_handle[cnt]);
+ // lock the buffer using genlock
+ LOGE("%s: camera call genlock_lock, hdl=%p", __FUNCTION__, (*mHalCamCtrl->mPreviewMemory.buffer_handle[cnt]));
+ 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;
+ } else {
+ LOGE("%s: genlock_lock_buffer hdl =%p", __FUNCTION__, *mHalCamCtrl->mPreviewMemory.buffer_handle[cnt]);
+ mHalCamCtrl->mPreviewMemory.local_flag[cnt] = BUFFER_LOCKED;
+ }
+ } else {
+ mHalCamCtrl->mPreviewMemory.local_flag[cnt] = BUFFER_NOT_OWNED;
+ LOGE("%s: dequeue_buffer idx = %d err = %d", __func__, cnt, err);
+ }
+
+ LOGE("%s: dequeue buf: %p\n", __func__, 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++) {
+ if (BUFFER_LOCKED == mHalCamCtrl->mPreviewMemory.local_flag[i]) {
+ LOGE("%s: camera call genlock_unlock", __FUNCTION__);
+ if (GENLOCK_FAILURE == genlock_unlock_buffer((native_handle_t *)
+ (*(mHalCamCtrl->mPreviewMemory.buffer_handle[i])))) {
+ LOGE("%s: genlock_unlock_buffer failed: hdl =%p", __FUNCTION__, (*(mHalCamCtrl->mPreviewMemory.buffer_handle[i])) );
+ //mHalCamCtrl->mPreviewMemoryLock.unlock();
+ //return -EINVAL;
+ } else {
+ mHalCamCtrl->mPreviewMemory.local_flag[i] = BUFFER_UNLOCKED;
+ }
+ }
+ if( mHalCamCtrl->mPreviewMemory.local_flag[i] != BUFFER_NOT_OWNED) {
+ err = mPreviewWindow->cancel_buffer(mPreviewWindow,
+ mHalCamCtrl->mPreviewMemory.buffer_handle[i]);
+ }
+ mHalCamCtrl->mPreviewMemory.local_flag[i] = BUFFER_NOT_OWNED;
+ LOGE("%s: cancel_buffer: hdl =%p", __func__, (*mHalCamCtrl->mPreviewMemory.buffer_handle[i]));
+ mHalCamCtrl->mPreviewMemory.buffer_handle[i] = NULL;
+ }
+ memset(&mHalCamCtrl->mPreviewMemory, 0, sizeof(mHalCamCtrl->mPreviewMemory));
+ goto end;
+ }
+
+ mHalCamCtrl->mPreviewMemory.private_buffer_handle[cnt] =
+ (struct private_handle_t *)(*mHalCamCtrl->mPreviewMemory.buffer_handle[cnt]);
+#ifdef USE_ION
+ mHalCamCtrl->mPreviewMemory.main_ion_fd[cnt] = open("/dev/ion", O_RDONLY);
+ if (mHalCamCtrl->mPreviewMemory.main_ion_fd[cnt] < 0) {
+ LOGE("%s: failed: could not open ion device\n", __func__);
+ } else {
+ mHalCamCtrl->mPreviewMemory.ion_info_fd[cnt].fd =
+ mHalCamCtrl->mPreviewMemory.private_buffer_handle[cnt]->fd;
+ if (ioctl(mHalCamCtrl->mPreviewMemory.main_ion_fd[cnt],
+ ION_IOC_IMPORT, &mHalCamCtrl->mPreviewMemory.ion_info_fd[cnt]) < 0)
+ LOGE("ION import failed\n");
+ }
+#endif
+ 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 ret;
+}
+
+status_t QCameraStream_preview::putBufferToSurface() {
+ int err = 0;
+ status_t ret = NO_ERROR;
+
+ LOGI(" %s : E ", __FUNCTION__);
+
+ mHalCamCtrl->mPreviewMemoryLock.lock();
+ for (int cnt = 0; cnt < mHalCamCtrl->mPreviewMemory.buffer_count; cnt++) {
+ if (cnt < mHalCamCtrl->mPreviewMemory.buffer_count) {
+ if (NO_ERROR != mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW, cnt, mCameraId,
+ CAM_SOCK_MSG_TYPE_FD_UNMAPPING)) {
+ LOGE("%s: sending data Msg Failed", __func__);
+ }
+ }
+
+ mHalCamCtrl->mPreviewMemory.camera_memory[cnt]->release(mHalCamCtrl->mPreviewMemory.camera_memory[cnt]);
+#ifdef USE_ION
+ struct ion_handle_data ion_handle;
+ ion_handle.handle = mHalCamCtrl->mPreviewMemory.ion_info_fd[cnt].handle;
+ if (ioctl(mHalCamCtrl->mPreviewMemory.main_ion_fd[cnt], ION_IOC_FREE, &ion_handle)
+ < 0)
+ LOGE("%s: ion free failed\n", __func__);
+ close(mHalCamCtrl->mPreviewMemory.main_ion_fd[cnt]);
+#endif
+ 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, handle =%p", __FUNCTION__, (*(mHalCamCtrl->mPreviewMemory.buffer_handle[cnt])));
+ continue;
+ //mHalCamCtrl->mPreviewMemoryLock.unlock();
+ //return -EINVAL;
+ } else {
+
+ LOGD("%s: genlock_unlock_buffer, handle =%p", __FUNCTION__, (*(mHalCamCtrl->mPreviewMemory.buffer_handle[cnt])));
+ mHalCamCtrl->mPreviewMemory.local_flag[cnt] = BUFFER_UNLOCKED;
+ }
+ }
+ if( mHalCamCtrl->mPreviewMemory.local_flag[cnt] != BUFFER_NOT_OWNED) {
+ err = mPreviewWindow->cancel_buffer(mPreviewWindow, mHalCamCtrl->mPreviewMemory.buffer_handle[cnt]);
+ LOGD("%s: cancel_buffer: hdl =%p", __func__, (*mHalCamCtrl->mPreviewMemory.buffer_handle[cnt]));
+ }
+ mHalCamCtrl->mPreviewMemory.local_flag[cnt] = BUFFER_NOT_OWNED;
+
+ LOGD(" put buffer %d successfully", cnt);
+ }
+
+ if (mDisplayBuf.preview.buf.mp != NULL) {
+ delete[] mDisplayBuf.preview.buf.mp;
+ mDisplayBuf.preview.buf.mp = NULL;
+ }
+
+ mHalCamCtrl->mPreviewMemoryLock.unlock();
+ memset(&mHalCamCtrl->mPreviewMemory, 0, sizeof(mHalCamCtrl->mPreviewMemory));
+ LOGI(" %s : X ",__FUNCTION__);
+ return NO_ERROR;
+}
+
+
+status_t QCameraStream_preview::getBufferNoDisplay( )
+{
+ int err = 0;
+ status_t ret = NO_ERROR;
+ int i, num_planes, frame_len, y_off, cbcr_off;
+ cam_ctrl_dimension_t dim;
+ uint32_t planes[VIDEO_MAX_PLANES];
+
+ LOGI("%s : E ", __FUNCTION__);
+
+
+ ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION, &dim);
+ if(ret != NO_ERROR) {
+ LOGE("%s: display format %d is not supported", __func__, dim.prev_format);
+ goto end;
+ }
+ mHalCamCtrl->mPreviewMemoryLock.lock();
+ mHalCamCtrl->mNoDispPreviewMemory.buffer_count = kPreviewBufferCount;
+ if(mHalCamCtrl->isZSLMode()) {
+ if(mHalCamCtrl->getZSLQueueDepth() > kPreviewBufferCount - 3)
+ mHalCamCtrl->mNoDispPreviewMemory.buffer_count =
+ mHalCamCtrl->getZSLQueueDepth() + 3;
+ }
+
+ num_planes = dim.display_frame_offset.num_planes;
+ for ( i = 0; i < num_planes; i++) {
+ planes[i] = dim.display_frame_offset.mp[i].len;
+ }
+
+ frame_len = dim.picture_frame_offset.frame_len;
+ y_off = dim.picture_frame_offset.mp[0].offset;
+ cbcr_off = dim.picture_frame_offset.mp[1].offset;
+ LOGE("%s: main image: rotation = %d, yoff = %d, cbcroff = %d, size = %d, width = %d, height = %d",
+ __func__, dim.rotation, y_off, cbcr_off, frame_len,
+ dim.display_width, dim.display_height);
+ if (mHalCamCtrl->initHeapMem(&mHalCamCtrl->mNoDispPreviewMemory,
+ mHalCamCtrl->mNoDispPreviewMemory.buffer_count,
+ frame_len, y_off, cbcr_off, MSM_PMEM_MAINIMG,
+ NULL,NULL, num_planes, planes) < 0) {
+ ret = NO_MEMORY;
+ goto end;
+ };
+
+ 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::freeBufferNoDisplay()
+{
+ int err = 0;
+ status_t ret = NO_ERROR;
+
+ LOGI(" %s : E ", __FUNCTION__);
+
+ //mDisplayLock.lock();
+ mHalCamCtrl->mPreviewMemoryLock.lock();
+ for (int cnt = 0; cnt < mHalCamCtrl->mNoDispPreviewMemory.buffer_count; cnt++) {
+ if (cnt < mHalCamCtrl->mNoDispPreviewMemory.buffer_count) {
+ if (NO_ERROR != mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW,
+ cnt, mCameraId, CAM_SOCK_MSG_TYPE_FD_UNMAPPING)) {
+ LOGE("%s: sending data Msg Failed", __func__);
+ }
+ }
+ }
+ mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mNoDispPreviewMemory);
+ memset(&mHalCamCtrl->mNoDispPreviewMemory, 0, sizeof(mHalCamCtrl->mNoDispPreviewMemory));
+ if (mDisplayBuf.preview.buf.mp != NULL) {
+ delete[] mDisplayBuf.preview.buf.mp;
+ mDisplayBuf.preview.buf.mp = NULL;
+ }
+
+ mHalCamCtrl->mPreviewMemoryLock.unlock();
+ LOGI(" %s : X ",__FUNCTION__);
+ return NO_ERROR;
+}
+
+void QCameraStream_preview::notifyROIEvent(fd_roi_t roi)
+{
+ switch (roi.type) {
+ case FD_ROI_TYPE_HEADER:
+ {
+ mDisplayLock.lock();
+ mNumFDRcvd = 0;
+ memset(mHalCamCtrl->mFace, 0, sizeof(mHalCamCtrl->mFace));
+ mHalCamCtrl->mMetadata.faces = mHalCamCtrl->mFace;
+ mHalCamCtrl->mMetadata.number_of_faces = roi.d.hdr.num_face_detected;
+ if(mHalCamCtrl->mMetadata.number_of_faces > MAX_ROI)
+ mHalCamCtrl->mMetadata.number_of_faces = MAX_ROI;
+ mDisplayLock.unlock();
+
+ if (mHalCamCtrl->mMetadata.number_of_faces == 0) {
+ // Clear previous faces
+ mHalCamCtrl->mCallbackLock.lock();
+ camera_data_callback pcb = mHalCamCtrl->mDataCb;
+ mHalCamCtrl->mCallbackLock.unlock();
+
+ if (pcb && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_PREVIEW_METADATA)){
+ LOGE("%s: Face detection RIO callback", __func__);
+ pcb(CAMERA_MSG_PREVIEW_METADATA, NULL, 0, &mHalCamCtrl->mMetadata, mHalCamCtrl->mCallbackCookie);
+ }
+ }
+ }
+ break;
+ case FD_ROI_TYPE_DATA:
+ {
+ mDisplayLock.lock();
+ int idx = roi.d.data.idx;
+ if (idx >= mHalCamCtrl->mMetadata.number_of_faces) {
+ mDisplayLock.unlock();
+ LOGE("%s: idx %d out of boundary %d", __func__, idx, mHalCamCtrl->mMetadata.number_of_faces);
+ break;
+ }
+
+ mHalCamCtrl->mFace[idx].id = roi.d.data.face.id;
+ mHalCamCtrl->mFace[idx].score = roi.d.data.face.score;
+
+ // top
+ mHalCamCtrl->mFace[idx].rect[0] =
+ roi.d.data.face.face_boundary.x*2000/mHalCamCtrl->mDimension.display_width - 1000;
+ //right
+ mHalCamCtrl->mFace[idx].rect[1] =
+ roi.d.data.face.face_boundary.y*2000/mHalCamCtrl->mDimension.display_height - 1000;
+ //bottom
+ mHalCamCtrl->mFace[idx].rect[2] = mHalCamCtrl->mFace[idx].rect[0] +
+ roi.d.data.face.face_boundary.dx*2000/mHalCamCtrl->mDimension.display_width;
+ //left
+ mHalCamCtrl->mFace[idx].rect[3] = mHalCamCtrl->mFace[idx].rect[1] +
+ roi.d.data.face.face_boundary.dy*2000/mHalCamCtrl->mDimension.display_height;
+
+ // Center of left eye
+ mHalCamCtrl->mFace[idx].left_eye[0] =
+ roi.d.data.face.left_eye_center[0]*2000/mHalCamCtrl->mDimension.display_width - 1000;
+ mHalCamCtrl->mFace[idx].left_eye[1] =
+ roi.d.data.face.left_eye_center[1]*2000/mHalCamCtrl->mDimension.display_height - 1000;
+
+ // Center of right eye
+ mHalCamCtrl->mFace[idx].right_eye[0] =
+ roi.d.data.face.right_eye_center[0]*2000/mHalCamCtrl->mDimension.display_width - 1000;
+ mHalCamCtrl->mFace[idx].right_eye[1] =
+ roi.d.data.face.right_eye_center[1]*2000/mHalCamCtrl->mDimension.display_height - 1000;
+
+ // Center of mouth
+ mHalCamCtrl->mFace[idx].mouth[0] =
+ roi.d.data.face.mouth_center[0]*2000/mHalCamCtrl->mDimension.display_width - 1000;
+ mHalCamCtrl->mFace[idx].mouth[1] =
+ roi.d.data.face.mouth_center[1]*2000/mHalCamCtrl->mDimension.display_height - 1000;
+
+ mHalCamCtrl->mFace[idx].smile_degree = roi.d.data.face.smile_degree;
+ mHalCamCtrl->mFace[idx].smile_score = roi.d.data.face.smile_confidence;
+ mHalCamCtrl->mFace[idx].blink_detected = roi.d.data.face.blink_detected;
+ mHalCamCtrl->mFace[idx].face_recognised = roi.d.data.face.is_face_recognised;
+ mHalCamCtrl->mFace[idx].gaze_angle = roi.d.data.face.gaze_angle;
+ /* newly added */
+ mHalCamCtrl->mFace[idx].updown_dir = roi.d.data.face.updown_dir;
+ mHalCamCtrl->mFace[idx].leftright_dir = roi.d.data.face.leftright_dir;
+ mHalCamCtrl->mFace[idx].roll_dir = roi.d.data.face.roll_dir;
+ mHalCamCtrl->mFace[idx].leye_blink = roi.d.data.face.left_blink;
+ mHalCamCtrl->mFace[idx].reye_blink = roi.d.data.face.right_blink;
+ mHalCamCtrl->mFace[idx].left_right_gaze = roi.d.data.face.left_right_gaze;
+ mHalCamCtrl->mFace[idx].top_bottom_gaze = roi.d.data.face.top_bottom_gaze;
+ LOGE("%s: Face(%d, %d, %d, %d), leftEye(%d, %d), rightEye(%d, %d), mouth(%d, %d), smile(%d, %d), face_recg(%d)", __func__,
+ mHalCamCtrl->mFace[idx].rect[0], mHalCamCtrl->mFace[idx].rect[1],
+ mHalCamCtrl->mFace[idx].rect[2], mHalCamCtrl->mFace[idx].rect[3],
+ mHalCamCtrl->mFace[idx].left_eye[0], mHalCamCtrl->mFace[idx].left_eye[1],
+ mHalCamCtrl->mFace[idx].right_eye[0], mHalCamCtrl->mFace[idx].right_eye[1],
+ mHalCamCtrl->mFace[idx].mouth[0], mHalCamCtrl->mFace[idx].mouth[1],
+ mHalCamCtrl->mFace[idx].smile_degree, mHalCamCtrl->mFace[idx].smile_score,
+ mHalCamCtrl->mFace[idx].face_recognised);
+ LOGE("%s: gaze(%d, %d, %d), updown(%d), leftright(%d), roll(%d), blink(%d, %d, %d)", __func__,
+ mHalCamCtrl->mFace[idx].gaze_angle, mHalCamCtrl->mFace[idx].left_right_gaze,
+ mHalCamCtrl->mFace[idx].top_bottom_gaze, mHalCamCtrl->mFace[idx].updown_dir,
+ mHalCamCtrl->mFace[idx].leftright_dir, mHalCamCtrl->mFace[idx].roll_dir,
+ mHalCamCtrl->mFace[idx].blink_detected,
+ mHalCamCtrl->mFace[idx].leye_blink, mHalCamCtrl->mFace[idx].reye_blink);
+
+ mNumFDRcvd++;
+ mDisplayLock.unlock();
+
+ if (mNumFDRcvd == mHalCamCtrl->mMetadata.number_of_faces) {
+ mHalCamCtrl->mCallbackLock.lock();
+ camera_data_callback pcb = mHalCamCtrl->mDataCb;
+ mHalCamCtrl->mCallbackLock.unlock();
+
+ if (pcb && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_PREVIEW_METADATA)){
+ LOGE("%s: Face detection RIO callback with %d faces detected (score=%d)", __func__, mNumFDRcvd, mHalCamCtrl->mFace[idx].score);
+ pcb(CAMERA_MSG_PREVIEW_METADATA, NULL, 0, &mHalCamCtrl->mMetadata, mHalCamCtrl->mCallbackCookie);
+ }
+ }
+ }
+ break;
+ }
+}
+
+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];
+ void *vaddr = NULL;
+ 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 */
+ mHalCamCtrl->mPreviewMemoryLock.lock();
+ memset(&mDisplayStreamBuf, 0, sizeof(mDisplayStreamBuf));
+ 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;
+
+ memset(&mDisplayBuf, 0, sizeof(mDisplayBuf));
+ 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__);
+ ret = NO_MEMORY;
+ goto error;
+ }
+ memset(mDisplayBuf.preview.buf.mp, 0,
+ mDisplayStreamBuf.num * sizeof(mm_camera_mp_buf_t));
+
+ /*allocate memory for the buffers*/
+ 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;
+ mDisplayStreamBuf.frame[i].ion_alloc.len = mHalCamCtrl->mPreviewMemory.private_buffer_handle[i]->size;
+ mDisplayStreamBuf.frame[i].ion_dev_fd = mHalCamCtrl->mPreviewMemory.main_ion_fd[i];
+ mDisplayStreamBuf.frame[i].fd_data = mHalCamCtrl->mPreviewMemory.ion_info_fd[i];
+
+ 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);
+
+ ret = mHalCamCtrl->sendMappingBuf(
+ MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW,
+ i,
+ mDisplayStreamBuf.frame[i].fd,
+ mHalCamCtrl->mPreviewMemory.private_buffer_handle[i]->size,
+ mCameraId, CAM_SOCK_MSG_TYPE_FD_MAPPING);
+ if (NO_ERROR != ret) {
+ LOGE("%s: sending mapping data Msg Failed", __func__);
+ goto error;
+ }
+
+ 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;
+
+error:
+ mHalCamCtrl->mPreviewMemoryLock.unlock();
+ putBufferToSurface();
+
+ LOGV("%s: X", __func__);
+ return ret;
+}
+
+status_t QCameraStream_preview::initPreviewOnlyBuffers()
+{
+ 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->mNoDispPreviewMemory, 0, sizeof(mHalCamCtrl->mNoDispPreviewMemory));
+ mHalCamCtrl->mPreviewMemoryLock.unlock();
+ memset(&mNotifyBuffer, 0, sizeof(mNotifyBuffer));
+
+/* get preview size, by qury mm_camera*/
+ 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__);
+ LOGE("%s: X", __func__);
+ return BAD_VALUE;
+ }else {
+ width = dim.display_width;
+ height = dim.display_height;
+ }
+
+ ret = getBufferNoDisplay( );
+ 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->mNoDispPreviewMemory.buffer_count;
+ this->myMode=myMode; /*Need to assign this in constructor after translating from mask*/
+ num_planes = dim.display_frame_offset.num_planes;
+ for (int i = 0; i < num_planes; i++) {
+ planes[i] = dim.display_frame_offset.mp[i].len;
+ }
+ this->mDisplayStreamBuf.frame_len = dim.display_frame_offset.frame_len;
+
+ memset(&mDisplayBuf, 0, sizeof(mDisplayBuf));
+ 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->mNoDispPreviewMemory.camera_memory[i] == NULL)
+ continue;
+ mDisplayStreamBuf.frame[i].fd = mHalCamCtrl->mNoDispPreviewMemory.fd[i];
+ mDisplayStreamBuf.frame[i].cbcr_off = planes[0];
+ mDisplayStreamBuf.frame[i].y_off = 0;
+ mDisplayStreamBuf.frame[i].path = OUTPUT_TYPE_P;
+ mDisplayStreamBuf.frame[i].buffer =
+ (long unsigned int)mHalCamCtrl->mNoDispPreviewMemory.camera_memory[i]->data;
+ mDisplayStreamBuf.frame[i].ion_dev_fd = mHalCamCtrl->mNoDispPreviewMemory.main_ion_fd[i];
+ mDisplayStreamBuf.frame[i].fd_data = mHalCamCtrl->mNoDispPreviewMemory.ion_info_fd[i];
+
+ LOGE("%s: idx = %d, fd = %d, size = %d, cbcr_offset = %d, y_offset = %d, "
+ "vaddr = 0x%x", __func__, i, mDisplayStreamBuf.frame[i].fd,
+ frame_len,
+ mDisplayStreamBuf.frame[i].cbcr_off, mDisplayStreamBuf.frame[i].y_off,
+ (uint32_t)mDisplayStreamBuf.frame[i].buffer);
+
+ if (NO_ERROR != mHalCamCtrl->sendMappingBuf(
+ MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW,
+ i,
+ mDisplayStreamBuf.frame[i].fd,
+ mHalCamCtrl->mNoDispPreviewMemory.size,
+ mCameraId, CAM_SOCK_MSG_TYPE_FD_MAPPING)) {
+ LOGE("%s: sending mapping data Msg Failed", __func__);
+ }
+
+ mDisplayBuf.preview.buf.mp[i].frame = mDisplayStreamBuf.frame[i];
+ mDisplayBuf.preview.buf.mp[i].frame_offset = mDisplayStreamBuf.frame[i].y_off;
+ 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::processPreviewFrameWithDisplay(
+ mm_camera_ch_data_buf_t *frame)
+{
+ LOGV("%s",__func__);
+ int err = 0;
+ int msgType = 0;
+ int i;
+ 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();
+ nsecs_t timeStamp = seconds_to_nanoseconds(frame->def.frame->ts.tv_sec) ;
+ timeStamp += frame->def.frame->ts.tv_nsec;
+
+ if(mFirstFrameRcvd == false) {
+ mm_camera_util_profile("HAL: First preview frame received");
+ mFirstFrameRcvd = true;
+ }
+
+ if (UNLIKELY(mHalCamCtrl->mDebugFps)) {
+ mHalCamCtrl->debugShowPreviewFPS();
+ }
+ //dumpFrameToFile(frame->def.frame);
+ mHalCamCtrl->dumpFrameToFile(frame->def.frame, HAL_DUMP_FRM_PREVIEW);
+
+ mHalCamCtrl->mPreviewMemoryLock.lock();
+ mNotifyBuffer[frame->def.idx] = *frame;
+
+ 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]) {
+ LOGD("%s: genlock_unlock_buffer hdl =%p", __FUNCTION__, (*mHalCamCtrl->mPreviewMemory.buffer_handle[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;
+ }
+
+#ifdef USE_ION
+ struct ion_flush_data cache_inv_data;
+ int ion_fd;
+ ion_fd = frame->def.frame->ion_dev_fd;
+ cache_inv_data.vaddr = (void *)frame->def.frame->buffer;
+ cache_inv_data.fd = frame->def.frame->fd;
+ cache_inv_data.handle = frame->def.frame->fd_data.handle;
+ cache_inv_data.length = frame->def.frame->ion_alloc.len;
+
+ if (mHalCamCtrl->cache_ops(ion_fd, &cache_inv_data, ION_IOC_CLEAN_CACHES) < 0)
+ LOGE("%s: Cache clean for Preview buffer %p fd = %d failed", __func__,
+ cache_inv_data.vaddr, cache_inv_data.fd);
+#endif
+
+ if(mHFRFrameSkip == 1)
+ {
+ const char *str = mHalCamCtrl->mParameters.get(
+ CameraParameters::KEY_VIDEO_HIGH_FRAME_RATE);
+ if(str != NULL){
+ int is_hfr_off = 0;
+ mHFRFrameCnt++;
+ if(!strcmp(str, CameraParameters::VIDEO_HFR_OFF)) {
+ is_hfr_off = 1;
+ err = this->mPreviewWindow->enqueue_buffer(this->mPreviewWindow,
+ (buffer_handle_t *)mHalCamCtrl->mPreviewMemory.buffer_handle[frame->def.idx]);
+ } else if (!strcmp(str, CameraParameters::VIDEO_HFR_2X)) {
+ mHFRFrameCnt %= 2;
+ } else if (!strcmp(str, CameraParameters::VIDEO_HFR_3X)) {
+ mHFRFrameCnt %= 3;
+ } else if (!strcmp(str, CameraParameters::VIDEO_HFR_4X)) {
+ mHFRFrameCnt %= 4;
+ }
+ if(mHFRFrameCnt == 0)
+ err = this->mPreviewWindow->enqueue_buffer(this->mPreviewWindow,
+ (buffer_handle_t *)mHalCamCtrl->mPreviewMemory.buffer_handle[frame->def.idx]);
+ else if(!is_hfr_off)
+ err = this->mPreviewWindow->cancel_buffer(this->mPreviewWindow,
+ (buffer_handle_t *)mHalCamCtrl->mPreviewMemory.buffer_handle[frame->def.idx]);
+ } else
+ err = this->mPreviewWindow->enqueue_buffer(this->mPreviewWindow,
+ (buffer_handle_t *)mHalCamCtrl->mPreviewMemory.buffer_handle[frame->def.idx]);
+ } else {
+ 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);
+ } else {
+ LOGD("%s: enqueue_buffer hdl=%p", __func__, *mHalCamCtrl->mPreviewMemory.buffer_handle[frame->def.idx]);
+ mHalCamCtrl->mPreviewMemory.local_flag[frame->def.idx] = BUFFER_NOT_OWNED;
+ }
+ 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) {
+
+ LOGD("%s: dequed buf hdl =%p", __func__, *buffer_handle);
+ for(i = 0; i < mHalCamCtrl->mPreviewMemory.buffer_count; i++) {
+ if(mHalCamCtrl->mPreviewMemory.buffer_handle[i] == buffer_handle) {
+ mHalCamCtrl->mPreviewMemory.local_flag[i] = BUFFER_UNLOCKED;
+ break;
+ }
+ }
+ if (i < mHalCamCtrl->mPreviewMemory.buffer_count ) {
+ err = this->mPreviewWindow->lock_buffer(this->mPreviewWindow, buffer_handle);
+ LOGD("%s: camera call genlock_lock: hdl =%p", __FUNCTION__, *buffer_handle);
+ 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;
+ } else {
+ mHalCamCtrl->mPreviewMemory.local_flag[i] = BUFFER_LOCKED;
+
+ if(MM_CAMERA_OK != cam_evt_buf_done(mCameraId, &mNotifyBuffer[i])) {
+ LOGE("BUF DONE FAILED");
+ }
+ }
+ }
+ } 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);
+
+ camera_memory_t *previewMem = NULL;
+
+ if (pcb != NULL) {
+ LOGD("%s: mMsgEnabled =0x%x, preview format =%d", __func__,
+ mHalCamCtrl->mMsgEnabled, mHalCamCtrl->mPreviewFormat);
+ //Sending preview callback if corresponding Msgs are enabled
+ if(mHalCamCtrl->mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) {
+ LOGE("Q%s: PCB callback enabled", __func__);
+ msgType |= CAMERA_MSG_PREVIEW_FRAME;
+ int previewBufSize;
+ /* The preview buffer size sent back in the callback should be (width*height*bytes_per_pixel)
+ * As all preview formats we support, use 12 bits per pixel, buffer size = previewWidth * previewHeight * 3/2.
+ * We need to put a check if some other formats are supported in future. (punits) */
+ if((mHalCamCtrl->mPreviewFormat == CAMERA_YUV_420_NV21) || (mHalCamCtrl->mPreviewFormat == CAMERA_YUV_420_NV12) ||
+ (mHalCamCtrl->mPreviewFormat == CAMERA_YUV_420_YV12))
+ {
+ previewBufSize = mHalCamCtrl->mPreviewWidth * mHalCamCtrl->mPreviewHeight * 3/2;
+ if(previewBufSize != mHalCamCtrl->mPreviewMemory.private_buffer_handle[frame->def.idx]->size) {
+ previewMem = mHalCamCtrl->mGetMemory(mHalCamCtrl->mPreviewMemory.private_buffer_handle[frame->def.idx]->fd,
+ previewBufSize, 1, mHalCamCtrl->mCallbackCookie);
+ if (!previewMem || !previewMem->data) {
+ LOGE("%s: mGetMemory failed.\n", __func__);
+ } else {
+ data = previewMem;
+ }
+ } else
+ data = mHalCamCtrl->mPreviewMemory.camera_memory[frame->def.idx];
+ } else {
+ data = mHalCamCtrl->mPreviewMemory.camera_memory[frame->def.idx];
+ LOGE("Invalid preview format, buffer size in preview callback may be wrong.");
+ }
+ } else {
+ data = NULL;
+ }
+ if(msgType) {
+ mStopCallbackLock.unlock();
+ if(mActive)
+ pcb(msgType, data, 0, metadata, mHalCamCtrl->mCallbackCookie);
+ if (previewMem)
+ previewMem->release(previewMem);
+ }
+ LOGD("end of cb");
+ } else {
+ LOGD("%s PCB is not enabled", __func__);
+ }
+ if(rcb != NULL && mVFEOutputs == 1)
+ {
+ int flagwait = 1;
+ if(mHalCamCtrl->mStartRecording == true &&
+ ( mHalCamCtrl->mMsgEnabled & CAMERA_MSG_VIDEO_FRAME))
+ {
+ if (mHalCamCtrl->mStoreMetaDataInFrame)
+ {
+ if(mHalCamCtrl->mRecordingMemory.metadata_memory[frame->def.idx])
+ {
+ flagwait = 1;
+ mStopCallbackLock.unlock();
+ rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME,
+ mHalCamCtrl->mRecordingMemory.metadata_memory[frame->def.idx],
+ 0, mHalCamCtrl->mCallbackCookie);
+ }else
+ flagwait = 0;
+ }
+ else
+ {
+ mStopCallbackLock.unlock();
+ rcb(timeStamp, CAMERA_MSG_VIDEO_FRAME,
+ mHalCamCtrl->mPreviewMemory.camera_memory[frame->def.idx],
+ 0, mHalCamCtrl->mCallbackCookie);
+ }
+
+ if(flagwait){
+ Mutex::Autolock rLock(&mHalCamCtrl->mRecordFrameLock);
+ if (mHalCamCtrl->mReleasedRecordingFrame != true) {
+ mHalCamCtrl->mRecordWait.wait(mHalCamCtrl->mRecordFrameLock);
+ }
+ mHalCamCtrl->mReleasedRecordingFrame = false;
+ }
+ }
+ }
+ /* 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;
+}
+
+
+status_t QCameraStream_preview::processPreviewFrameWithOutDisplay(
+ mm_camera_ch_data_buf_t *frame)
+{
+ LOGV("%s",__func__);
+ int err = 0;
+ int msgType = 0;
+ int i;
+ 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;
+ }
+
+ if (UNLIKELY(mHalCamCtrl->mDebugFps)) {
+ mHalCamCtrl->debugShowPreviewFPS();
+ }
+ //dumpFrameToFile(frame->def.frame);
+ mHalCamCtrl->dumpFrameToFile(frame->def.frame, HAL_DUMP_FRM_PREVIEW);
+
+ mHalCamCtrl->mPreviewMemoryLock.lock();
+ mNotifyBuffer[frame->def.idx] = *frame;
+
+ /* 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);
+
+ camera_memory_t *previewMem = NULL;
+ int previewWidth, previewHeight;
+ mHalCamCtrl->mParameters.getPreviewSize(&previewWidth, &previewHeight);
+
+#ifdef USE_ION
+ struct ion_flush_data cache_inv_data;
+ int ion_fd;
+ ion_fd = frame->def.frame->ion_dev_fd;
+ cache_inv_data.vaddr = (void *)frame->def.frame->buffer;
+ cache_inv_data.fd = frame->def.frame->fd;
+ cache_inv_data.handle = frame->def.frame->fd_data.handle;
+ cache_inv_data.length = frame->def.frame->ion_alloc.len;
+
+ if (mHalCamCtrl->cache_ops(ion_fd, &cache_inv_data, ION_IOC_CLEAN_CACHES) < 0)
+ LOGE("%s: Cache clean for Preview buffer %p fd = %d failed", __func__,
+ cache_inv_data.vaddr, cache_inv_data.fd);
+#endif
+
+ if (pcb != NULL) {
+ //Sending preview callback if corresponding Msgs are enabled
+ if(mHalCamCtrl->mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) {
+ msgType |= CAMERA_MSG_PREVIEW_FRAME;
+ int previewBufSize;
+ /* For CTS : Forcing preview memory buffer lenth to be
+ 'previewWidth * previewHeight * 3/2'.
+ Needed when gralloc allocated extra memory.*/
+ //Can add this check for other formats as well.
+ if( mHalCamCtrl->mPreviewFormat == CAMERA_YUV_420_NV21) {
+ previewBufSize = previewWidth * previewHeight * 3/2;
+ if(previewBufSize != mHalCamCtrl->mPreviewMemory.private_buffer_handle[frame->def.idx]->size) {
+ previewMem = mHalCamCtrl->mGetMemory(mHalCamCtrl->mPreviewMemory.private_buffer_handle[frame->def.idx]->fd,
+ previewBufSize, 1, mHalCamCtrl->mCallbackCookie);
+ if (!previewMem || !previewMem->data) {
+ LOGE("%s: mGetMemory failed.\n", __func__);
+ } else {
+ data = previewMem;
+ }
+ } else
+ data = mHalCamCtrl->mPreviewMemory.camera_memory[frame->def.idx];//mPreviewHeap->mBuffers[frame->def.idx];
+ } else
+ 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();
+ if(mActive)
+ pcb(msgType, data, 0, metadata, mHalCamCtrl->mCallbackCookie);
+ if (previewMem)
+ previewMem->release(previewMem);
+ }
+
+ if(MM_CAMERA_OK != cam_evt_buf_done(mCameraId, &mNotifyBuffer[frame->def.idx])) {
+ LOGE("BUF DONE FAILED");
+ }
+
+ LOGD("end of cb");
+ }
+
+ return NO_ERROR;
+}
+
+status_t QCameraStream_preview::processPreviewFrame (
+ mm_camera_ch_data_buf_t *frame)
+{
+ if (mHalCamCtrl->isNoDisplayMode()) {
+ return processPreviewFrameWithOutDisplay(frame);
+ } else {
+ return processPreviewFrameWithDisplay(frame);
+ }
+}
+
+// ---------------------------------------------------------------------------
+// QCameraStream_preview
+// ---------------------------------------------------------------------------
+
+QCameraStream_preview::
+QCameraStream_preview(int cameraId, camera_mode_t mode)
+ : QCameraStream(cameraId,mode),
+ mLastQueuedFrame(NULL),
+ mNumFDRcvd(0),
+ mFirstFrameRcvd(false)
+ {
+ 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;
+
+ Mutex::Autolock lock(mStopCallbackLock);
+
+ /* call start() in parent class to start the monitor thread*/
+ //QCameraStream::start ();
+ setFormat(MM_CAMERA_CH_PREVIEW_MASK);
+
+ if (mHalCamCtrl->isNoDisplayMode()) {
+ if(NO_ERROR!=initPreviewOnlyBuffers()){
+ return BAD_VALUE;
+ }
+ } else {
+ if(NO_ERROR!=initDisplayBuffers()){
+ return BAD_VALUE;
+ }
+ }
+ LOGE("Debug : %s : initDisplayBuffers",__func__);
+
+ ret = cam_config_prepare_buf(mCameraId, &mDisplayBuf);
+ 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;
+ goto error;
+ }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);
+ ret = BAD_VALUE;
+ goto error;
+ }
+ }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);
+ ret = BAD_VALUE;
+ goto error;
+ }
+ }
+
+ /* call mm_camera action start(...) */
+ LOGE("Starting Preview/Video Stream. ");
+ mFirstFrameRcvd = false;
+ 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);
+ ret = BAD_VALUE;
+ goto error;
+ }
+
+ LOGE("Debug : %s : Preview streaming Started",__func__);
+ ret = NO_ERROR;
+
+ mActive = true;
+ goto end;
+
+error:
+ putBufferToSurface();
+end:
+ LOGE("%s: X", __func__);
+ return ret;
+ }
+
+
+// ---------------------------------------------------------------------------
+// QCameraStream_preview
+// ---------------------------------------------------------------------------
+ void QCameraStream_preview::stop() {
+ LOGE("%s: E", __func__);
+ int ret=MM_CAMERA_OK;
+
+ if(!mActive) {
+ return;
+ }
+ Mutex::Autolock lock(mStopCallbackLock);
+ mActive = false;
+ /* unregister the notify fn from the mmmm_camera_t object*/
+
+ LOGI("%s: Stop the thread \n", __func__);
+ /* 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);
+ }
+ 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;
+ }
+
+ /* In case of a clean stop, we need to clean all buffers*/
+ LOGE("Debug : %s : Buffer Unprepared",__func__);
+ /*free camera_memory handles and return buffer back to surface*/
+ if (! mHalCamCtrl->isNoDisplayMode() ) {
+ putBufferToSurface();
+ } else {
+ freeBufferNoDisplay( );
+ }
+
+ 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;
+}
+
+// ---------------------------------------------------------------------------
+// No code beyone this line
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/camera/QCamera/HAL/core/src/QCameraHWI_Record.cpp b/camera/QCamera/HAL/core/src/QCameraHWI_Record.cpp
new file mode 100755
index 0000000..c2e0084
--- /dev/null
+++ b/camera/QCamera/HAL/core/src/QCameraHWI_Record.cpp
@@ -0,0 +1,582 @@
+/*
+** Copyright (c) 2011 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__);
+
+ /*
+ * 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,
+ MM_CAMERA_REG_BUF_CB_INFINITE,
+ 0,
+ this);
+
+ mInit = true;
+ LOGV("%s: END", __func__);
+ return ret;
+}
+// ---------------------------------------------------------------------------
+// QCameraStream_record
+// ---------------------------------------------------------------------------
+
+status_t QCameraStream_record::start()
+{
+ status_t ret = NO_ERROR;
+ LOGV("%s: BEGIN", __func__);
+
+ 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__);
+ goto error;
+ }
+
+ 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;
+ goto error;
+ }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;
+ goto error;
+ }else{
+ LOGE("%s : Video streaming Started",__func__);
+ ret = NO_ERROR;
+ }
+ mActive = true;
+ LOGV("%s: END", __func__);
+ return ret;
+
+error:
+ releaseEncodeBuffer();
+ LOGV("%s: END", __func__);
+ return ret;
+}
+
+void QCameraStream_record::releaseEncodeBuffer() {
+ for(int cnt = 0; cnt < mHalCamCtrl->mRecordingMemory.buffer_count; cnt++) {
+ if (NO_ERROR !=
+ mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_VIDEO, cnt,
+ mCameraId, CAM_SOCK_MSG_TYPE_FD_UNMAPPING))
+ LOGE("%s: Unmapping Video Data Failed", __func__);
+
+ 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]);
+
+ }
+ mHalCamCtrl->mRecordingMemory.camera_memory[cnt]->release(
+ mHalCamCtrl->mRecordingMemory.camera_memory[cnt]);
+ close(mHalCamCtrl->mRecordingMemory.fd[cnt]);
+ mHalCamCtrl->mRecordingMemory.fd[cnt] = -1;
+
+#ifdef USE_ION
+ mHalCamCtrl->deallocate_ion_memory(&mHalCamCtrl->mRecordingMemory, cnt);
+#endif
+ }
+ memset(&mHalCamCtrl->mRecordingMemory, 0, sizeof(mHalCamCtrl->mRecordingMemory));
+ //mNumRecordFrames = 0;
+ delete[] recordframes;
+ if (mRecordBuf.video.video.buf.mp)
+ delete[] mRecordBuf.video.video.buf.mp;
+}
+
+// ---------------------------------------------------------------------------
+// QCameraStream_record
+// ---------------------------------------------------------------------------
+void QCameraStream_record::stop()
+{
+ status_t ret = NO_ERROR;
+ LOGV("%s: BEGIN", __func__);
+
+ 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__);
+ }
+
+ releaseEncodeBuffer();
+
+ mActive = false;
+ LOGV("%s: END", __func__);
+
+}
+// ---------------------------------------------------------------------------
+// QCameraStream_record
+// ---------------------------------------------------------------------------
+void QCameraStream_record::release()
+{
+ status_t ret = NO_ERROR;
+ LOGV("%s: BEGIN", __func__);
+
+ 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,
+ (mm_camera_register_buf_cb_type_t)NULL,
+ NULL,
+ NULL);
+ mInit = false;
+ LOGV("%s: END", __func__);
+}
+
+status_t QCameraStream_record::processRecordFrame(void *data)
+{
+ LOGV("%s : BEGIN",__func__);
+ 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;
+
+ LOGE("Send Video frame to services/encoder TimeStamp : %lld",timeStamp);
+ mRecordedFrames[frame->video.video.idx] = *frame;
+
+#ifdef USE_ION
+ struct ion_flush_data cache_inv_data;
+ int ion_fd;
+ ion_fd = frame->video.video.frame->ion_dev_fd;
+ cache_inv_data.vaddr = (void *)frame->video.video.frame->buffer;
+ cache_inv_data.fd = frame->video.video.frame->fd;
+ cache_inv_data.handle = frame->video.video.frame->fd_data.handle;
+ cache_inv_data.length = frame->video.video.frame->ion_alloc.len;
+
+ if (mHalCamCtrl->cache_ops(ion_fd, &cache_inv_data, ION_IOC_CLEAN_CACHES) < 0)
+ LOGE("%s: Cache clean for Video buffer %p fd = %d failed", __func__,
+ cache_inv_data.vaddr, cache_inv_data.fd);
+#endif
+
+ 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 {
+ 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);
+ }
+ }
+
+ LOGV("%s : END",__func__);
+ return NO_ERROR;
+}
+
+//Record Related Functions
+status_t QCameraStream_record::initEncodeBuffers()
+{
+ LOGE("%s : BEGIN",__func__);
+ status_t ret = NO_ERROR;
+ 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 */
+ int buf_cnt;
+ 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;
+
+ buf_cnt = VIDEO_BUFFER_COUNT;
+ if(mHalCamCtrl->isLowPowerCamcorder()) {
+ LOGE("%s: lower power camcorder selected", __func__);
+ buf_cnt = VIDEO_BUFFER_COUNT_LOW_POWER_CAMCORDER;
+ }
+ recordframes = new msm_frame[buf_cnt];
+ memset(recordframes,0,sizeof(struct msm_frame) * buf_cnt);
+
+ mRecordBuf.video.video.buf.mp = new mm_camera_mp_buf_t[buf_cnt *
+ 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,
+ buf_cnt * sizeof(mm_camera_mp_buf_t));
+
+ memset(&mHalCamCtrl->mRecordingMemory, 0, sizeof(mHalCamCtrl->mRecordingMemory));
+ for (int i=0; i<MM_CAMERA_MAX_NUM_FRAMES;i++) {
+ mHalCamCtrl->mRecordingMemory.main_ion_fd[i] = -1;
+ mHalCamCtrl->mRecordingMemory.fd[i] = -1;
+ }
+
+ mHalCamCtrl->mRecordingMemory.buffer_count = buf_cnt;
+
+ mHalCamCtrl->mRecordingMemory.size = frame_len;
+ mHalCamCtrl->mRecordingMemory.cbcr_offset = planes[0];
+
+ for (int cnt = 0; cnt < mHalCamCtrl->mRecordingMemory.buffer_count; cnt++) {
+#ifdef USE_ION
+ if(mHalCamCtrl->allocate_ion_memory(&mHalCamCtrl->mRecordingMemory, cnt,
+ ((0x1 << CAMERA_ION_HEAP_ID) | (0x1 << CAMERA_ION_FALLBACK_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);
+
+ 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->mRecordingMemory.fd[cnt];
+ nh->data[1] = 0;
+ nh->data[2] = mHalCamCtrl->mRecordingMemory.size;
+ }
+ 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;
+ recordframes[cnt].fd_data = mHalCamCtrl->mRecordingMemory.ion_info_fd[cnt];
+ recordframes[cnt].ion_alloc = mHalCamCtrl->mRecordingMemory.alloc[cnt];
+ recordframes[cnt].ion_dev_fd = mHalCamCtrl->mRecordingMemory.main_ion_fd[cnt];
+
+ if (NO_ERROR !=
+ mHalCamCtrl->sendMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_VIDEO, cnt,
+ recordframes[cnt].fd, mHalCamCtrl->mRecordingMemory.size, mCameraId,
+ CAM_SOCK_MSG_TYPE_FD_MAPPING))
+ LOGE("%s: sending mapping data Msg Failed", __func__);
+
+ 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;
+ }
+ }
+
+ //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];
+ LOGE("%s : END",__func__);
+ return NO_ERROR;
+}
+
+void QCameraStream_record::releaseRecordingFrame(const void *opaque)
+{
+ LOGV("%s : BEGIN, opaque = 0x%p",__func__, opaque);
+ 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__);
+ LOGV("%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__);
+ LOGV("%s : END",__func__);
+ return;
+ }
+ }
+ }
+ LOGE("%s: cannot find the matched frame with opaue = 0x%p", __func__, opaque);
+}
+
+void QCameraStream_record::debugShowVideoFPS() const
+{
+ 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;
+ }
+}
+
+#if 0
+sp<IMemoryHeap> QCameraStream_record::getHeap() const
+{
+ return mRecordHeap != NULL ? mRecordHeap->mHeap : NULL;
+}
+
+#endif
+status_t QCameraStream_record::takeLiveSnapshot(){
+ return true;
+}
+
+}//namespace android
+
diff --git a/camera/QCamera/HAL/core/src/QCameraHWI_Still.cpp b/camera/QCamera/HAL/core/src/QCameraHWI_Still.cpp
new file mode 100755
index 0000000..f569741
--- /dev/null
+++ b/camera/QCamera/HAL/core/src/QCameraHWI_Still.cpp
@@ -0,0 +1,2507 @@
+/*
+** 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.
+** 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_NDDEBUG 0
+#define LOG_NIDEBUG 0
+#define LOG_TAG "QCameraHWI_Still"
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <media/mediarecorder.h>
+#include <math.h>
+#include "QCameraHAL.h"
+#include "QCameraHWI.h"
+
+#define THUMBNAIL_DEFAULT_WIDTH 512
+#define THUMBNAIL_DEFAULT_HEIGHT 384
+
+/* following code implement the still image capture & encoding logic of this class*/
+namespace android {
+
+typedef enum {
+ SNAPSHOT_STATE_ERROR,
+ SNAPSHOT_STATE_UNINIT,
+ SNAPSHOT_STATE_CH_ACQUIRED,
+ SNAPSHOT_STATE_BUF_NOTIF_REGD,
+ SNAPSHOT_STATE_BUF_INITIALIZED,
+ SNAPSHOT_STATE_INITIALIZED,
+ SNAPSHOT_STATE_IMAGE_CAPTURE_STRTD,
+ SNAPSHOT_STATE_YUV_RECVD,
+ SNAPSHOT_STATE_JPEG_ENCODING,
+ SNAPSHOT_STATE_JPEG_ENCODE_DONE,
+ SNAPSHOT_STATE_JPEG_COMPLETE_ENCODE_DONE,
+
+ /*Add any new state above*/
+ SNAPSHOT_STATE_MAX
+} snapshot_state_type_t;
+
+
+//-----------------------------------------------------------------------
+// Constants
+//----------------------------------------------------------------------
+static const int PICTURE_FORMAT_JPEG = 1;
+static const int PICTURE_FORMAT_RAW = 2;
+static const int POSTVIEW_SMALL_HEIGHT = 144;
+
+// ---------------------------------------------------------------------------
+/* static functions*/
+// ---------------------------------------------------------------------------
+
+
+
+/* TBD: Temp: to be removed*/
+static pthread_mutex_t g_s_mutex;
+static int g_status = 0;
+static pthread_cond_t g_s_cond_v;
+
+static void mm_app_snapshot_done()
+{
+ pthread_mutex_lock(&g_s_mutex);
+ g_status = TRUE;
+ pthread_cond_signal(&g_s_cond_v);
+ pthread_mutex_unlock(&g_s_mutex);
+}
+
+static void mm_app_snapshot_wait()
+{
+ pthread_mutex_lock(&g_s_mutex);
+ if(FALSE == g_status) pthread_cond_wait(&g_s_cond_v, &g_s_mutex);
+ pthread_mutex_unlock(&g_s_mutex);
+ g_status = FALSE;
+}
+
+static int mm_app_dump_snapshot_frame(char *filename,
+ const void *buffer,
+ uint32_t len)
+{
+ char bufp[128];
+ int file_fdp;
+ int rc = 0;
+
+ file_fdp = open(filename, O_RDWR | O_CREAT, 0777);
+
+ if (file_fdp < 0) {
+ rc = -1;
+ goto end;
+ }
+ write(file_fdp,
+ (const void *)buffer, len);
+ close(file_fdp);
+end:
+ return rc;
+}
+
+/* Callback received when a frame is available after snapshot*/
+static void snapshot_notify_cb(mm_camera_ch_data_buf_t *recvd_frame,
+ void *user_data)
+{
+ QCameraStream_Snapshot *pme = (QCameraStream_Snapshot *)user_data;
+
+ LOGD("%s: E", __func__);
+
+ if (pme != NULL) {
+ pme->receiveRawPicture(recvd_frame);
+ }
+ else{
+ LOGW("%s: Snapshot obj NULL in callback", __func__);
+ }
+
+ LOGD("%s: X", __func__);
+
+}
+
+/* Once we give frame for encoding, we get encoded jpeg image
+ fragments by fragment. We'll need to store them in a buffer
+ to form complete JPEG image */
+static void snapshot_jpeg_fragment_cb(uint8_t *ptr,
+ uint32_t size,
+ void *user_data)
+{
+ QCameraStream_Snapshot *pme = (QCameraStream_Snapshot *)user_data;
+
+ LOGE("%s: E",__func__);
+ if (pme != NULL) {
+ pme->receiveJpegFragment(ptr,size);
+ }
+ else
+ LOGW("%s: Receive jpeg fragment cb obj Null", __func__);
+
+ LOGD("%s: X",__func__);
+}
+
+/* This callback is received once the complete JPEG encoding is done */
+static void snapshot_jpeg_cb(jpeg_event_t event, void *user_data)
+{
+ QCameraStream_Snapshot *pme = (QCameraStream_Snapshot *)user_data;
+ LOGE("%s: E ",__func__);
+
+ if (event != JPEG_EVENT_DONE) {
+ if (event == JPEG_EVENT_THUMBNAIL_DROPPED) {
+ LOGE("%s: Error in thumbnail encoding (event: %d)!!!",
+ __func__, event);
+ LOGD("%s: X",__func__);
+ return;
+ }
+ else {
+ LOGE("%s: Error (event: %d) while jpeg encoding!!!",
+ __func__, event);
+ }
+ }
+
+ if (pme != NULL) {
+ pme->receiveCompleteJpegPicture(event);
+ LOGE(" Completed issuing JPEG callback");
+ /* deinit only if we are done taking requested number of snapshots */
+ if (pme->getSnapshotState() == SNAPSHOT_STATE_JPEG_COMPLETE_ENCODE_DONE) {
+ LOGE(" About to issue deinit callback");
+ /* If it's ZSL Mode, we don't deinit now. We'll stop the polling thread and
+ deinit the channel/buffers only when we change the mode from zsl to
+ non-zsl. */
+ if (!(pme->isZSLMode())) {
+ pme->stop();
+ }
+ }
+ }
+ else
+ LOGW("%s: Receive jpeg cb Obj Null", __func__);
+
+
+ LOGD("%s: X",__func__);
+
+}
+
+// ---------------------------------------------------------------------------
+/* private functions*/
+// ---------------------------------------------------------------------------
+
+void QCameraStream_Snapshot::
+receiveJpegFragment(uint8_t *ptr, uint32_t size)
+{
+ LOGE("%s: E", __func__);
+#if 0
+ if (mJpegHeap != NULL) {
+ LOGE("%s: Copy jpeg...", __func__);
+ memcpy((uint8_t *)mJpegHeap->mHeap->base()+ mJpegOffset, ptr, size);
+ mJpegOffset += size;
+ }
+ else {
+ LOGE("%s: mJpegHeap is NULL!", __func__);
+ }
+ #else
+ if(mHalCamCtrl->mJpegMemory.camera_memory[0] != NULL && ptr != NULL && size > 0) {
+ memcpy((uint8_t *)((uint32_t)mHalCamCtrl->mJpegMemory.camera_memory[0]->data + mJpegOffset), ptr, size);
+ mJpegOffset += size;
+
+
+ /*
+ memcpy((uint8_t *)((uint32_t)mHalCamCtrl->mJpegMemory.camera_memory[0]->data + mJpegOffset), ptr, size);
+ mJpegOffset += size;
+ */
+ } else {
+ LOGE("%s: mJpegHeap is NULL!", __func__);
+ }
+
+
+ #endif
+
+ LOGD("%s: X", __func__);
+}
+
+
+void QCameraStream_Snapshot::
+receiveCompleteJpegPicture(jpeg_event_t event)
+{
+ int msg_type = CAMERA_MSG_COMPRESSED_IMAGE;
+ LOGE("%s: E", __func__);
+ camera_memory_t *encodedMem = NULL;
+ camera_data_callback jpg_data_cb = NULL;
+ bool fail_cb_flag = false;
+
+ //Mutex::Autolock l(&snapshotLock);
+ mStopCallbackLock.lock( );
+ if(!mActive && !isLiveSnapshot()) {
+ LOGE("%s : Cancel Picture",__func__);
+ fail_cb_flag = true;
+ goto end;
+ }
+
+ if(mCurrentFrameEncoded!=NULL /*&& !isLiveSnapshot()*/){
+ LOGV("<DEBUG>: Calling buf done for snapshot buffer");
+ cam_evt_buf_done(mCameraId, mCurrentFrameEncoded);
+ }
+ mHalCamCtrl->dumpFrameToFile(mHalCamCtrl->mJpegMemory.camera_memory[0]->data, mJpegOffset, (char *)"debug", (char *)"jpg", 0);
+
+end:
+ msg_type = CAMERA_MSG_COMPRESSED_IMAGE;
+ if (mHalCamCtrl->mDataCb && (mHalCamCtrl->mMsgEnabled & msg_type)) {
+ jpg_data_cb = mHalCamCtrl->mDataCb;
+ }else{
+ LOGE("%s: JPEG callback was cancelled--not delivering image.", __func__);
+ }
+ setSnapshotState(SNAPSHOT_STATE_JPEG_ENCODE_DONE);
+ mNumOfRecievedJPEG++;
+ mHalCamCtrl->deinitExifData();
+
+ /* free the resource we allocated to maintain the structure */
+ //mm_camera_do_munmap(main_fd, (void *)main_buffer_addr, mSnapshotStreamBuf.frame_len);
+ if(mCurrentFrameEncoded) {
+ free(mCurrentFrameEncoded);
+ mCurrentFrameEncoded = NULL;
+ }
+
+ /* Before leaving check the jpeg queue. If it's not empty give the available
+ frame for encoding*/
+ if (!mSnapshotQueue.isEmpty()) {
+ LOGI("%s: JPEG Queue not empty. Dequeue and encode.", __func__);
+ mm_camera_ch_data_buf_t* buf =
+ (mm_camera_ch_data_buf_t *)mSnapshotQueue.dequeue();
+ //encodeDisplayAndSave(buf, 1);
+ if ( NO_ERROR != encodeDisplayAndSave(buf, 1)){
+ fail_cb_flag = true;
+ }
+ } else if (mNumOfSnapshot == mNumOfRecievedJPEG ) { /* finished */
+ LOGD("%s: Before omxJpegFinish", __func__);
+ omxJpegFinish();
+ LOGD("%s: After omxJpegFinish", __func__);
+ /* getRemainingSnapshots call will give us number of snapshots still
+ remaining after flushing current zsl buffer once*/
+ LOGD("%s: Complete JPEG Encoding Done!", __func__);
+ setSnapshotState(SNAPSHOT_STATE_JPEG_COMPLETE_ENCODE_DONE);
+ mBurstModeFlag = false;
+ mSnapshotQueue.flush();
+ mNumOfRecievedJPEG = 0;
+ /* in case of zsl, we need to reset some of the zsl attributes */
+ if (isZSLMode()){
+ LOGD("%s: Resetting the ZSL attributes", __func__);
+ setZSLChannelAttribute();
+ }
+ if (!isZSLMode() && !isLiveSnapshot()){
+ //Stop polling before calling datacb for if not ZSL mode
+ stopPolling();
+ }
+
+ } else {
+ LOGD("%s: mNumOfRecievedJPEG(%d), mNumOfSnapshot(%d)", __func__, mNumOfRecievedJPEG, mNumOfSnapshot);
+ }
+ if(fail_cb_flag && mHalCamCtrl->mDataCb &&
+ (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
+ /* get picture failed. Give jpeg callback with NULL data
+ * to the application to restore to preview mode
+ */
+ jpg_data_cb = mHalCamCtrl->mDataCb;
+ }
+ if(!fail_cb_flag) {
+ camera_memory_t *encodedMem = mHalCamCtrl->mGetMemory(
+ mHalCamCtrl->mJpegMemory.fd[0], mJpegOffset, 1, mHalCamCtrl);
+ if (!encodedMem || !encodedMem->data) {
+ LOGE("%s: mGetMemory failed.\n", __func__);
+ }
+ memcpy(encodedMem->data, mHalCamCtrl->mJpegMemory.camera_memory[0]->data, mJpegOffset );
+ mStopCallbackLock.unlock( );
+ if ((mActive || isLiveSnapshot()) && jpg_data_cb != NULL) {
+ LOGV("%s: Calling upperlayer callback to store JPEG image", __func__);
+ jpg_data_cb (msg_type,encodedMem, 0, NULL,mHalCamCtrl->mCallbackCookie);
+ }
+ encodedMem->release( encodedMem );
+ jpg_data_cb = NULL;
+ }else{
+ LOGV("Image Encoding Failed... Notify Upper layer");
+ mStopCallbackLock.unlock( );
+ if((mActive || isLiveSnapshot()) && jpg_data_cb != NULL) {
+ jpg_data_cb (CAMERA_MSG_COMPRESSED_IMAGE,NULL, 0, NULL,
+ mHalCamCtrl->mCallbackCookie);
+ }
+ }
+ //reset jpeg_offset
+ mJpegOffset = 0;
+ LOGD("%s: X", __func__);
+}
+
+status_t QCameraStream_Snapshot::
+configSnapshotDimension(cam_ctrl_dimension_t* dim)
+{
+ bool matching = true;
+ cam_format_t img_format;
+ status_t ret = NO_ERROR;
+ LOGD("%s: E", __func__);
+
+ LOGI("%s:Passed picture size: %d X %d", __func__,
+ dim->picture_width, dim->picture_height);
+ LOGI("%s:Passed postview size: %d X %d", __func__,
+ dim->ui_thumbnail_width, dim->ui_thumbnail_height);
+
+ /* First check if the picture resolution is the same, if not, change it*/
+ mHalCamCtrl->getPictureSize(&mPictureWidth, &mPictureHeight);
+ LOGD("%s: Picture size received: %d x %d", __func__,
+ mPictureWidth, mPictureHeight);
+ /*Current VFE software design requires picture size >= display size for ZSL*/
+ if (isZSLMode()){
+ mPostviewWidth = dim->display_width;
+ mPostviewHeight = dim->display_height;
+ } else {
+ mPostviewWidth = mHalCamCtrl->mParameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
+ mPostviewHeight = mHalCamCtrl->mParameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
+ }
+ /*If application requested thumbnail size to be (0,0)
+ then configure second outout to a default size.
+ Jpeg encoder will drop thumbnail as reflected in encodeParams.
+ */
+ mDropThumbnail = false;
+ if (mPostviewWidth == 0 && mPostviewHeight == 0) {
+ mPostviewWidth = THUMBNAIL_DEFAULT_WIDTH;
+ mPostviewHeight = THUMBNAIL_DEFAULT_HEIGHT;
+ mDropThumbnail = true;
+ }
+
+ LOGD("%s: Postview size received: %d x %d", __func__,
+ mPostviewWidth, mPostviewHeight);
+
+ matching = (mPictureWidth == dim->picture_width) &&
+ (mPictureHeight == dim->picture_height);
+ matching &= (dim->ui_thumbnail_width == mPostviewWidth) &&
+ (dim->ui_thumbnail_height == mPostviewHeight);
+
+ /* picture size currently set do not match with the one wanted
+ by user.*/
+ if (!matching) {
+ if (mPictureWidth < mPostviewWidth || mPictureHeight < mPostviewHeight) {
+ //Changes to Handle VFE limitation.
+ mActualPictureWidth = mPictureWidth;
+ mActualPictureHeight = mPictureHeight;
+ mPictureWidth = mPostviewWidth;
+ mPictureHeight = mPostviewHeight;
+ mJpegDownscaling = TRUE;
+ }else{
+ mJpegDownscaling = FALSE;
+ }
+ dim->picture_width = mPictureWidth;
+ dim->picture_height = mPictureHeight;
+ dim->ui_thumbnail_height = mThumbnailHeight = mPostviewHeight;
+ dim->ui_thumbnail_width = mThumbnailWidth = mPostviewWidth;
+ }
+ #if 0
+ img_format = mHalCamCtrl->getPreviewFormat();
+ if (img_format) {
+ matching &= (img_format == dim->main_img_format);
+ if (!matching) {
+ dim->main_img_format = img_format;
+ dim->thumb_format = img_format;
+ }
+ }
+ #endif
+ if (!matching) {
+ LOGD("%s: Image Sizes before set parm call: main: %dx%d thumbnail: %dx%d",
+ __func__,
+ dim->picture_width, dim->picture_height,
+ dim->ui_thumbnail_width, dim->ui_thumbnail_height);
+
+ ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,dim);
+ if (NO_ERROR != ret) {
+ LOGE("%s: error - can't config snapshot parms!", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+ }
+ /* set_parm will return corrected dimension based on aspect ratio and
+ ceiling size */
+ mPictureWidth = dim->picture_width;
+ mPictureHeight = dim->picture_height;
+ mPostviewHeight = mThumbnailHeight = dim->ui_thumbnail_height;
+ mPostviewWidth = mThumbnailWidth = dim->ui_thumbnail_width;
+ mPictureFormat= dim->main_img_format;
+ mThumbnailFormat = dim->thumb_format;
+
+ LOGD("%s: Image Format: %d", __func__, dim->main_img_format);
+ LOGI("%s: Image Sizes: main: %dx%d thumbnail: %dx%d", __func__,
+ dim->picture_width, dim->picture_height,
+ dim->ui_thumbnail_width, dim->ui_thumbnail_height);
+end:
+ LOGD("%s: X", __func__);
+ return ret;
+}
+
+status_t QCameraStream_Snapshot::
+initRawSnapshotChannel(cam_ctrl_dimension_t *dim,
+ int num_of_snapshots)
+{
+ status_t ret = NO_ERROR;
+ mm_camera_ch_image_fmt_parm_t fmt;
+ mm_camera_channel_attr_t ch_attr;
+
+ mm_camera_raw_streaming_type_t raw_stream_type =
+ MM_CAMERA_RAW_STREAMING_CAPTURE_SINGLE;
+
+ LOGD("%s: E", __func__);
+
+ /* Initialize stream - set format, acquire channel */
+ /*TBD: Currently we only support single raw capture*/
+ LOGE("num_of_snapshots = %d",num_of_snapshots);
+ if (num_of_snapshots == 1) {
+ raw_stream_type = MM_CAMERA_RAW_STREAMING_CAPTURE_SINGLE;
+ }
+
+ /* Set channel attribute */
+ LOGD("%s: Set Raw Snapshot Channel attribute", __func__);
+ memset(&ch_attr, 0, sizeof(ch_attr));
+ ch_attr.type = MM_CAMERA_CH_ATTR_RAW_STREAMING_TYPE;
+ ch_attr.raw_streaming_mode = raw_stream_type;
+
+ if( NO_ERROR !=
+ cam_ops_ch_set_attr(mCameraId, MM_CAMERA_CH_RAW, &ch_attr)) {
+ LOGD("%s: Failure setting Raw channel attribute.", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
+ memset(&fmt, 0, sizeof(mm_camera_ch_image_fmt_parm_t));
+ fmt.ch_type = MM_CAMERA_CH_RAW;
+ fmt.def.fmt = CAMERA_BAYER_SBGGR10;
+ fmt.def.dim.width = dim->raw_picture_width;
+ fmt.def.dim.height = dim->raw_picture_height;
+
+
+ LOGV("%s: Raw snapshot channel fmt: %d", __func__,
+ fmt.def.fmt);
+ LOGV("%s: Raw snapshot resolution: %dX%d", __func__,
+ dim->raw_picture_width, dim->raw_picture_height);
+
+ LOGD("%s: Set Raw Snapshot channel image format", __func__);
+ ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_CH_IMAGE_FMT, &fmt);
+ if (NO_ERROR != ret) {
+ LOGE("%s: Set Raw Snapshot Channel format err=%d\n", __func__, ret);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
+end:
+ if (ret != NO_ERROR) {
+ handleError();
+ }
+ LOGE("%s: X", __func__);
+ return ret;
+
+}
+
+status_t QCameraStream_Snapshot::
+setZSLChannelAttribute(void)
+{
+ status_t ret = NO_ERROR;
+ mm_camera_channel_attr_t ch_attr;
+ LOGD("%s: E", __func__);
+
+ memset(&ch_attr, 0, sizeof(mm_camera_channel_attr_t));
+ ch_attr.type = MM_CAMERA_CH_ATTR_BUFFERING_FRAME;
+ ch_attr.buffering_frame.look_back = mHalCamCtrl->getZSLBackLookCount();
+ ch_attr.buffering_frame.water_mark = mHalCamCtrl->getZSLQueueDepth();
+ ch_attr.buffering_frame.interval = mHalCamCtrl->getZSLBurstInterval( );
+ LOGE("%s: ZSL queue_depth = %d, back_look_count = %d", __func__,
+ ch_attr.buffering_frame.water_mark,
+ ch_attr.buffering_frame.look_back);
+ if( NO_ERROR !=
+ cam_ops_ch_set_attr(mCameraId, MM_CAMERA_CH_SNAPSHOT, &ch_attr)) {
+ LOGD("%s: Failure setting ZSL channel attribute.", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+end:
+ LOGD("%s: X", __func__);
+ return ret;
+}
+
+status_t QCameraStream_Snapshot::
+initSnapshotFormat(cam_ctrl_dimension_t *dim)
+{
+ status_t ret = NO_ERROR;
+ mm_camera_ch_image_fmt_parm_t fmt;
+
+ LOGD("%s: E", __func__);
+
+ /* For ZSL mode we'll need to set channel attribute */
+ if (isZSLMode()) {
+ ret = setZSLChannelAttribute();
+ if (ret != NO_ERROR) {
+ goto end;
+ }
+ }
+
+ memset(&fmt, 0, sizeof(mm_camera_ch_image_fmt_parm_t));
+ fmt.ch_type = MM_CAMERA_CH_SNAPSHOT;
+ fmt.snapshot.main.fmt = dim->main_img_format;
+ fmt.snapshot.main.dim.width = dim->picture_width;
+ fmt.snapshot.main.dim.height = dim->picture_height;
+
+ fmt.snapshot.thumbnail.fmt = dim->thumb_format;
+ fmt.snapshot.thumbnail.dim.width = dim->ui_thumbnail_width;
+ fmt.snapshot.thumbnail.dim.height = dim->ui_thumbnail_height;
+
+ LOGV("%s: Snapshot channel fmt = main: %d thumbnail: %d", __func__,
+ dim->main_img_format, dim->thumb_format);
+ LOGV("%s: Snapshot channel resolution = main: %dX%d thumbnail: %dX%d",
+ __func__, dim->picture_width, dim->picture_height,
+ dim->ui_thumbnail_width, dim->ui_thumbnail_height);
+
+ LOGD("%s: Set Snapshot channel image format", __func__);
+ ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_CH_IMAGE_FMT, &fmt);
+ if (NO_ERROR != ret) {
+ LOGE("%s: Set Snapshot Channel format err=%d\n", __func__, ret);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
+end:
+ if (ret != NO_ERROR) {
+ handleError();
+ }
+ LOGE("%s: X", __func__);
+ return ret;
+
+}
+
+void QCameraStream_Snapshot::
+deinitSnapshotChannel(mm_camera_channel_type_t ch_type)
+{
+ LOGD("%s: E", __func__);
+
+ /* unreg buf notify*/
+ if (getSnapshotState() >= SNAPSHOT_STATE_BUF_NOTIF_REGD){
+ if (NO_ERROR != cam_evt_register_buf_notify(mCameraId,
+ ch_type, NULL,(mm_camera_register_buf_cb_type_t)NULL,NULL, this)) {
+ LOGE("%s: Failure to unregister buf notification", __func__);
+ }
+ }
+
+ if (getSnapshotState() >= SNAPSHOT_STATE_CH_ACQUIRED) {
+ LOGD("%s: Release snapshot channel", __func__);
+ cam_ops_ch_release(mCameraId, ch_type);
+ }
+
+ LOGD("%s: X",__func__);
+}
+
+status_t QCameraStream_Snapshot::
+initRawSnapshotBuffers(cam_ctrl_dimension_t *dim, int num_of_buf)
+{
+ status_t ret = NO_ERROR;
+ struct msm_frame *frame;
+ uint32_t frame_len;
+ uint8_t num_planes;
+ uint32_t planes[VIDEO_MAX_PLANES];
+ mm_camera_reg_buf_t reg_buf;
+
+ LOGD("%s: E", __func__);
+ memset(®_buf, 0, sizeof(mm_camera_reg_buf_t));
+ memset(&mSnapshotStreamBuf, 0, sizeof(mSnapshotStreamBuf));
+
+ if ((num_of_buf == 0) || (num_of_buf > MM_CAMERA_MAX_NUM_FRAMES)) {
+ LOGE("%s: Invalid number of buffers (=%d) requested!", __func__, num_of_buf);
+ ret = BAD_VALUE;
+ goto end;
+ }
+
+ reg_buf.def.buf.mp = new mm_camera_mp_buf_t[num_of_buf];
+ if (!reg_buf.def.buf.mp) {
+ LOGE("%s Error allocating memory for mplanar struct ", __func__);
+ ret = NO_MEMORY;
+ goto end;
+ }
+ memset(reg_buf.def.buf.mp, 0, num_of_buf * sizeof(mm_camera_mp_buf_t));
+
+ /* Get a frame len for buffer to be allocated*/
+ frame_len = mm_camera_get_msm_frame_len(CAMERA_BAYER_SBGGR10,
+ myMode,
+ dim->raw_picture_width,
+ dim->raw_picture_height,
+ OUTPUT_TYPE_S,
+ &num_planes, planes);
+
+ if (mHalCamCtrl->initHeapMem(&mHalCamCtrl->mRawMemory, num_of_buf,
+ frame_len, 0, planes[0], MSM_PMEM_RAW_MAINIMG,
+ &mSnapshotStreamBuf, ®_buf.def,
+ num_planes, planes) < 0) {
+ ret = NO_MEMORY;
+ goto end;
+ }
+
+ /* register the streaming buffers for the channel*/
+ reg_buf.ch_type = MM_CAMERA_CH_RAW;
+ reg_buf.def.num = mSnapshotStreamBuf.num;
+
+ ret = cam_config_prepare_buf(mCameraId, ®_buf);
+ if(ret != NO_ERROR) {
+ LOGV("%s:reg snapshot buf err=%d\n", __func__, ret);
+ ret = FAILED_TRANSACTION;
+ mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mRawMemory);
+ goto end;
+ }
+
+ /* If we have reached here successfully, we have allocated buffer.
+ Set state machine.*/
+ setSnapshotState(SNAPSHOT_STATE_BUF_INITIALIZED);
+
+end:
+ /* If it's error, we'll need to do some needful */
+ if (ret != NO_ERROR) {
+ handleError();
+ }
+ if (reg_buf.def.buf.mp)
+ delete []reg_buf.def.buf.mp;
+ LOGD("%s: X", __func__);
+ return ret;
+}
+
+status_t QCameraStream_Snapshot::deinitRawSnapshotBuffers(void)
+{
+ int ret = NO_ERROR;
+
+ LOGD("%s: E", __func__);
+
+ /* deinit buffers only if we have already allocated */
+ if (getSnapshotState() >= SNAPSHOT_STATE_BUF_INITIALIZED ){
+
+ LOGD("%s: Unpreparing Snapshot Buffer", __func__);
+ ret = cam_config_unprepare_buf(mCameraId, MM_CAMERA_CH_RAW);
+ if(ret != NO_ERROR) {
+ LOGE("%s:Unreg Raw snapshot buf err=%d\n", __func__, ret);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+ mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mRawMemory);
+ }
+
+end:
+ LOGD("%s: X", __func__);
+ return ret;
+}
+
+status_t QCameraStream_Snapshot::
+initSnapshotBuffers(cam_ctrl_dimension_t *dim, int num_of_buf)
+{
+ status_t ret = NO_ERROR;
+ struct msm_frame *frame;
+ uint32_t frame_len, y_off, cbcr_off;
+ uint8_t num_planes;
+ uint32_t planes[VIDEO_MAX_PLANES];
+ mm_camera_reg_buf_t reg_buf;
+ int rotation = 0;
+
+ LOGD("%s: E", __func__);
+ memset(®_buf, 0, sizeof(mm_camera_reg_buf_t));
+ memset(&mSnapshotStreamBuf, 0, sizeof(mSnapshotStreamBuf));
+
+ if ((num_of_buf == 0) || (num_of_buf > MM_CAMERA_MAX_NUM_FRAMES)) {
+ LOGE("%s: Invalid number of buffers (=%d) requested!",
+ __func__, num_of_buf);
+ ret = BAD_VALUE;
+ goto end;
+ }
+
+ LOGD("%s: Mode: %d Num_of_buf: %d ImageSizes: main: %dx%d thumb: %dx%d",
+ __func__, myMode, num_of_buf,
+ dim->picture_width, dim->picture_height,
+ dim->ui_thumbnail_width, dim->ui_thumbnail_height);
+
+ reg_buf.snapshot.main.buf.mp = new mm_camera_mp_buf_t[num_of_buf];
+ if (!reg_buf.snapshot.main.buf.mp) {
+ LOGE("%s Error allocating memory for mplanar struct ", __func__);
+ ret = NO_MEMORY;
+ goto end;
+ }
+ memset(reg_buf.snapshot.main.buf.mp, 0,
+ num_of_buf * sizeof(mm_camera_mp_buf_t));
+ if (!isFullSizeLiveshot()) {
+ reg_buf.snapshot.thumbnail.buf.mp = new mm_camera_mp_buf_t[num_of_buf];
+ if (!reg_buf.snapshot.thumbnail.buf.mp) {
+ LOGE("%s Error allocating memory for mplanar struct ", __func__);
+ ret = NO_MEMORY;
+ goto end;
+ }
+ memset(reg_buf.snapshot.thumbnail.buf.mp, 0,
+ num_of_buf * sizeof(mm_camera_mp_buf_t));
+ }
+ /* Number of buffers to be set*/
+ /* Set the JPEG Rotation here since get_buffer_offset needs
+ * the value of rotation.*/
+ mHalCamCtrl->setJpegRotation(isZSLMode());
+ if(!isZSLMode())
+ rotation = mHalCamCtrl->getJpegRotation();
+ else
+ rotation = 0;
+ if(rotation != dim->rotation) {
+ dim->rotation = rotation;
+ ret = cam_config_set_parm(mHalCamCtrl->mCameraId, MM_CAMERA_PARM_DIMENSION, dim);
+ }
+
+ if(isLiveSnapshot()) {
+ ret = cam_config_set_parm(mHalCamCtrl->mCameraId, MM_CAMERA_PARM_DIMENSION, dim);
+ }
+ num_planes = 2;
+ planes[0] = dim->picture_frame_offset.mp[0].len;
+ planes[1] = dim->picture_frame_offset.mp[1].len;
+ frame_len = dim->picture_frame_offset.frame_len;
+ y_off = dim->picture_frame_offset.mp[0].offset;
+ cbcr_off = dim->picture_frame_offset.mp[1].offset;
+ LOGE("%s: main image: rotation = %d, yoff = %d, cbcroff = %d, size = %d, width = %d, height = %d",
+ __func__, dim->rotation, y_off, cbcr_off, frame_len, dim->picture_width, dim->picture_height);
+ if (mHalCamCtrl->initHeapMem (&mHalCamCtrl->mJpegMemory, 1, frame_len, 0, cbcr_off,
+ MSM_PMEM_MAX, NULL, NULL, num_planes, planes) < 0) {
+ LOGE("%s: Error allocating JPEG memory", __func__);
+ ret = NO_MEMORY;
+ goto end;
+ }
+ if(!isLiveSnapshot()) {
+ if (mHalCamCtrl->initHeapMem(&mHalCamCtrl->mSnapshotMemory, num_of_buf,
+ frame_len, y_off, cbcr_off, MSM_PMEM_MAINIMG, &mSnapshotStreamBuf,
+ ®_buf.snapshot.main, num_planes, planes) < 0) {
+ ret = NO_MEMORY;
+ mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mJpegMemory);
+ goto end;
+ };
+ num_planes = 2;
+ planes[0] = dim->thumb_frame_offset.mp[0].len;
+ planes[1] = dim->thumb_frame_offset.mp[1].len;
+ frame_len = planes[0] + planes[1];
+ if (!isFullSizeLiveshot()) {
+ y_off = dim->thumb_frame_offset.mp[0].offset;
+ cbcr_off = dim->thumb_frame_offset.mp[1].offset;
+ LOGE("%s: thumbnail: rotation = %d, yoff = %d, cbcroff = %d, size = %d, width = %d, height = %d",
+ __func__, dim->rotation, y_off, cbcr_off, frame_len,
+ dim->thumbnail_width, dim->thumbnail_height);
+
+ if (mHalCamCtrl->initHeapMem(&mHalCamCtrl->mThumbnailMemory, num_of_buf,
+ frame_len, y_off, cbcr_off, MSM_PMEM_THUMBNAIL, &mPostviewStreamBuf,
+ ®_buf.snapshot.thumbnail, num_planes, planes) < 0) {
+ ret = NO_MEMORY;
+ mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mSnapshotMemory);
+ mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mJpegMemory);
+ goto end;
+ }
+ }
+ /* register the streaming buffers for the channel*/
+ reg_buf.ch_type = MM_CAMERA_CH_SNAPSHOT;
+ reg_buf.snapshot.main.num = mSnapshotStreamBuf.num;
+
+ if (!isFullSizeLiveshot())
+ reg_buf.snapshot.thumbnail.num = mPostviewStreamBuf.num;
+ else
+ reg_buf.snapshot.thumbnail.num = 0;
+
+ ret = cam_config_prepare_buf(mCameraId, ®_buf);
+ if(ret != NO_ERROR) {
+ LOGV("%s:reg snapshot buf err=%d\n", __func__, ret);
+ ret = FAILED_TRANSACTION;
+ if (!isFullSizeLiveshot()){
+ mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mThumbnailMemory);
+ }
+ mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mSnapshotMemory);
+ mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mJpegMemory);
+ goto end;
+ }
+ }
+
+ /* If we have reached here successfully, we have allocated buffer.
+ Set state machine.*/
+ setSnapshotState(SNAPSHOT_STATE_BUF_INITIALIZED);
+end:
+ if (ret != NO_ERROR) {
+ handleError();
+ }
+ if (reg_buf.snapshot.main.buf.mp)
+ delete []reg_buf.snapshot.main.buf.mp;
+ if (reg_buf.snapshot.thumbnail.buf.mp)
+ delete []reg_buf.snapshot.thumbnail.buf.mp;
+ LOGD("%s: X", __func__);
+ return ret;
+}
+
+status_t QCameraStream_Snapshot::
+deinitSnapshotBuffers(void)
+{
+ int ret = NO_ERROR;
+
+ LOGD("%s: E", __func__);
+
+ /* Deinit only if we have already initialized*/
+ if (getSnapshotState() >= SNAPSHOT_STATE_BUF_INITIALIZED ){
+
+ if(!isLiveSnapshot()) {
+ LOGD("%s: Unpreparing Snapshot Buffer", __func__);
+ ret = cam_config_unprepare_buf(mCameraId, MM_CAMERA_CH_SNAPSHOT);
+ if(ret != NO_ERROR) {
+ LOGE("%s:unreg snapshot buf err=%d\n", __func__, ret);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+ }
+
+ /* Clear main and thumbnail heap*/
+ if(!isLiveSnapshot()) {
+ mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mSnapshotMemory);
+ if (!isFullSizeLiveshot())
+ mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mThumbnailMemory);
+ }
+ mHalCamCtrl->releaseHeapMem(&mHalCamCtrl->mJpegMemory);
+ }
+end:
+ LOGD("%s: X", __func__);
+ return ret;
+}
+
+void QCameraStream_Snapshot::deInitBuffer(void)
+{
+ mm_camera_channel_type_t ch_type;
+
+ LOGI("%s: E", __func__);
+
+ if( getSnapshotState() == SNAPSHOT_STATE_UNINIT) {
+ LOGD("%s: Already deinit'd!", __func__);
+ return;
+ }
+
+ if (mSnapshotFormat == PICTURE_FORMAT_RAW) {
+ /* deinit buffer */
+ deinitRawSnapshotBuffers();
+ }
+ else
+ {
+ if (!isZSLMode() &&
+ ((mHalCamCtrl->getHDRMode() == HDR_MODE) || (mHalCamCtrl->isWDenoiseEnabled()))) {
+ /*register main and thumbnail buffers at back-end for frameproc*/
+ for (int i = 0; i < mHalCamCtrl->mSnapshotMemory.buffer_count; i++) {
+ if (NO_ERROR != mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN, i, mCameraId,
+ CAM_SOCK_MSG_TYPE_FD_UNMAPPING)) {
+ LOGE("%s: sending unmapping data Msg Failed", __func__);
+ }
+ if (NO_ERROR != mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL, i, mCameraId,
+ CAM_SOCK_MSG_TYPE_FD_UNMAPPING)) {
+ LOGE("%s: sending unmapping data Msg Failed", __func__);
+ }
+ }
+ }
+
+ deinitSnapshotBuffers();
+ }
+
+
+ /* deinit jpeg buffer if allocated */
+ if(mJpegHeap != NULL) mJpegHeap.clear();
+ mJpegHeap = NULL;
+
+ /* memset some global structure */
+ memset(&mSnapshotStreamBuf, 0, sizeof(mSnapshotStreamBuf));
+ memset(&mPostviewStreamBuf, 0, sizeof(mPostviewStreamBuf));
+ mSnapshotQueue.flush();
+ mWDNQueue.flush();
+
+ setSnapshotState(SNAPSHOT_STATE_UNINIT);
+
+ LOGD("%s: X", __func__);
+}
+
+/*Temp: to be removed once event handling is enabled in mm-camera.
+ We need an event - one event for
+ stream-off to disable OPS_SNAPSHOT*/
+void QCameraStream_Snapshot::runSnapshotThread(void *data)
+{
+ LOGD("%s: E", __func__);
+
+ if (mSnapshotFormat == PICTURE_FORMAT_RAW) {
+ /* TBD: Temp: Needs to be removed once event handling is enabled.
+ We cannot call mm-camera interface to stop snapshot from callback
+ function as it causes deadlock. Hence handling it here temporarily
+ in this thread. Later mm-camera intf will give us event in separate
+ thread context */
+ mm_app_snapshot_wait();
+ /* Send command to stop snapshot polling thread*/
+ stop();
+ }
+ LOGD("%s: X", __func__);
+}
+
+/*Temp: to be removed once event handling is enabled in mm-camera*/
+static void *snapshot_thread(void *obj)
+{
+ QCameraStream_Snapshot *pme = (QCameraStream_Snapshot *)obj;
+ LOGD("%s: E", __func__);
+ if (pme != 0) {
+ pme->runSnapshotThread(obj);
+ }
+ else LOGW("not starting snapshot thread: the object went away!");
+ LOGD("%s: X", __func__);
+ return NULL;
+}
+
+/*Temp: to be removed later*/
+static pthread_t mSnapshotThread;
+
+status_t QCameraStream_Snapshot::initJPEGSnapshot(int num_of_snapshots)
+{
+ status_t ret = NO_ERROR;
+ cam_ctrl_dimension_t dim;
+ mm_camera_op_mode_type_t op_mode;
+
+ LOGV("%s: E", __func__);
+
+ if (isFullSizeLiveshot())
+ goto end;
+
+ LOGD("%s: Get current dimension", __func__);
+ /* Query mm_camera to get current dimension */
+ memset(&dim, 0, sizeof(cam_ctrl_dimension_t));
+ ret = cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_DIMENSION, &dim);
+ if (NO_ERROR != ret) {
+ LOGE("%s: error - can't get preview dimension!", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
+ /* Set camera op mode to MM_CAMERA_OP_MODE_CAPTURE */
+ LOGD("Setting OP_MODE_CAPTURE");
+ op_mode = MM_CAMERA_OP_MODE_CAPTURE;
+ if( NO_ERROR != cam_config_set_parm(mCameraId,
+ MM_CAMERA_PARM_OP_MODE, &op_mode)) {
+ LOGE("%s: MM_CAMERA_OP_MODE_CAPTURE failed", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
+ /* config the parmeters and see if we need to re-init the stream*/
+ LOGI("%s: Configure Snapshot Dimension", __func__);
+ ret = configSnapshotDimension(&dim);
+ if (ret != NO_ERROR) {
+ LOGE("%s: Setting snapshot dimension failed", __func__);
+ goto end;
+ }
+
+ /* Initialize stream - set format, acquire channel */
+ ret = initSnapshotFormat(&dim);
+ if (NO_ERROR != ret) {
+ LOGE("%s: error - can't init nonZSL stream!", __func__);
+ goto end;
+ }
+
+ ret = initSnapshotBuffers(&dim, num_of_snapshots);
+ if ( NO_ERROR != ret ){
+ LOGE("%s: Failure allocating memory for Snapshot buffers", __func__);
+ goto end;
+ }
+
+ if (!isZSLMode() &&
+ ((mHalCamCtrl->getHDRMode() == HDR_MODE) || (mHalCamCtrl->isWDenoiseEnabled()))) {
+ /*register main and thumbnail buffers at back-end for frameproc*/
+ for (int i = 0; i < num_of_snapshots; i++) {
+ if (NO_ERROR != mHalCamCtrl->sendMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN, i,
+ mSnapshotStreamBuf.frame[i].fd, mHalCamCtrl->mSnapshotMemory.size, mCameraId,
+ CAM_SOCK_MSG_TYPE_FD_MAPPING)) {
+ LOGE("%s: sending mapping data Msg Failed", __func__);
+ }
+ if (NO_ERROR != mHalCamCtrl->sendMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL, i,
+ mPostviewStreamBuf.frame[i].fd, mHalCamCtrl->mThumbnailMemory.size, mCameraId,
+ CAM_SOCK_MSG_TYPE_FD_MAPPING)) {
+ LOGE("%s: sending mapping data Msg Failed", __func__);
+ }
+ }
+ }
+
+end:
+ /* Based on what state we are in, we'll need to handle error -
+ like deallocating memory if we have already allocated */
+ if (ret != NO_ERROR) {
+ handleError();
+ }
+ LOGV("%s: X", __func__);
+ return ret;
+
+}
+
+status_t QCameraStream_Snapshot::initRawSnapshot(int num_of_snapshots)
+{
+ status_t ret = NO_ERROR;
+ cam_ctrl_dimension_t dim;
+ bool initSnapshot = false;
+ mm_camera_op_mode_type_t op_mode;
+
+ LOGV("%s: E", __func__);
+
+ /* Set camera op mode to MM_CAMERA_OP_MODE_CAPTURE */
+ LOGD("%s: Setting OP_MODE_CAPTURE", __func__);
+ op_mode = MM_CAMERA_OP_MODE_CAPTURE;
+ if( NO_ERROR != cam_config_set_parm(mCameraId,
+ MM_CAMERA_PARM_OP_MODE, &op_mode)) {
+ LOGE("%s: MM_CAMERA_OP_MODE_CAPTURE failed", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
+ /* For raw snapshot, we do not know the dimension as it
+ depends on sensor to sensor. We call getDimension which will
+ give us raw width and height */
+ 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 dimension!", __func__);
+ LOGE("%s: X", __func__);
+ goto end;
+ }
+ LOGD("%s: Raw Snapshot dimension: %dx%d", __func__,
+ dim.raw_picture_width,
+ dim.raw_picture_height);
+
+
+ ret = initRawSnapshotChannel(&dim, num_of_snapshots);
+ if (NO_ERROR != ret) {
+ LOGE("%s: error - can't init nonZSL stream!", __func__);
+ goto end;
+ }
+
+ ret = initRawSnapshotBuffers(&dim, num_of_snapshots);
+ if ( NO_ERROR != ret ){
+ LOGE("%s: Failure allocating memory for Raw Snapshot buffers",
+ __func__);
+ goto end;
+ }
+ setSnapshotState(SNAPSHOT_STATE_INITIALIZED);
+
+end:
+ if (ret != NO_ERROR) {
+ handleError();
+ }
+ LOGV("%s: X", __func__);
+ return ret;
+}
+
+status_t QCameraStream_Snapshot::initFullLiveshot(void)
+{
+ status_t ret = NO_ERROR;
+ cam_ctrl_dimension_t dim;
+ bool matching = true;
+
+ 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 dimension!", __func__);
+ return ret;
+ }
+#if 1
+ /* First check if the picture resolution is the same, if not, change it*/
+ mHalCamCtrl->getPictureSize(&mPictureWidth, &mPictureHeight);
+ LOGD("%s: Picture size received: %d x %d", __func__,
+ mPictureWidth, mPictureHeight);
+
+ //Use main image as input to encoder to generate thumbnail
+ mThumbnailWidth = dim.picture_width;
+ mThumbnailHeight = dim.picture_height;
+ matching = (mPictureWidth == dim.picture_width) &&
+ (mPictureHeight == dim.picture_height);
+
+ //Actual thumbnail size requested
+ mPostviewWidth = mHalCamCtrl->mParameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
+ mPostviewHeight = mHalCamCtrl->mParameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
+
+ mDropThumbnail = false;
+ if (mPostviewWidth == 0 && mPostviewHeight == 0) {
+ mPostviewWidth = THUMBNAIL_DEFAULT_WIDTH;
+ mPostviewHeight = THUMBNAIL_DEFAULT_HEIGHT;
+ mDropThumbnail = true;
+ }
+
+ if (!matching) {
+ dim.picture_width = mPictureWidth;
+ dim.picture_height = mPictureHeight;
+ dim.ui_thumbnail_height = mThumbnailHeight;
+ dim.ui_thumbnail_width = mThumbnailWidth;
+ }
+ LOGD("%s: Picture size to set: %d x %d", __func__,
+ dim.picture_width, dim.picture_height);
+ ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim);
+#endif
+ /* Initialize stream - set format, acquire channel */
+ ret = initSnapshotFormat(&dim);
+ if (NO_ERROR != ret) {
+ LOGE("%s: error - can't init nonZSL stream!", __func__);
+ return ret;
+ }
+ ret = initSnapshotBuffers(&dim, 1);
+ if ( NO_ERROR != ret ){
+ LOGE("%s: Failure allocating memory for Snapshot buffers", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+status_t QCameraStream_Snapshot::initZSLSnapshot(void)
+{
+ status_t ret = NO_ERROR;
+ cam_ctrl_dimension_t dim;
+ mm_camera_op_mode_type_t op_mode;
+
+ LOGV("%s: E", __func__);
+
+ LOGD("%s: Get current dimension", __func__);
+ /* Query mm_camera to get current dimension */
+ memset(&dim, 0, sizeof(cam_ctrl_dimension_t));
+ ret = cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_DIMENSION, &dim);
+ if (NO_ERROR != ret) {
+ LOGE("%s: error - can't get preview dimension!", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
+ /* config the parmeters and see if we need to re-init the stream*/
+ LOGD("%s: Configure Snapshot Dimension", __func__);
+ ret = configSnapshotDimension(&dim);
+ if (ret != NO_ERROR) {
+ LOGE("%s: Setting snapshot dimension failed", __func__);
+ goto end;
+ }
+
+ /* Initialize stream - set format, acquire channel */
+ ret = initSnapshotFormat(&dim);
+ if (NO_ERROR != ret) {
+ LOGE("%s: error - can't init nonZSL stream!", __func__);
+ goto end;
+ }
+
+ /* For ZSL we'll have to allocate buffers for internal queue
+ maintained by mm-camera lib plus around 3 buffers used for
+ data handling by lower layer.*/
+
+ ret = initSnapshotBuffers(&dim, mHalCamCtrl->getZSLQueueDepth() + 3);
+ if ( NO_ERROR != ret ){
+ LOGE("%s: Failure allocating memory for Snapshot buffers", __func__);
+ goto end;
+ }
+
+end:
+ /* Based on what state we are in, we'll need to handle error -
+ like deallocating memory if we have already allocated */
+ if (ret != NO_ERROR) {
+ handleError();
+ }
+ LOGV("%s: X", __func__);
+ return ret;
+
+}
+
+status_t QCameraStream_Snapshot::
+takePictureJPEG(void)
+{
+ status_t ret = NO_ERROR;
+
+ LOGD("%s: E", __func__);
+
+ /* Take snapshot */
+ LOGD("%s: Call MM_CAMERA_OPS_SNAPSHOT", __func__);
+ if (NO_ERROR != cam_ops_action(mCameraId,
+ TRUE,
+ MM_CAMERA_OPS_SNAPSHOT,
+ this)) {
+ LOGE("%s: Failure taking snapshot", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
+ /* TBD: Temp: to be removed once event callback
+ is implemented in mm-camera lib */
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ pthread_create(&mSnapshotThread,&attr,
+ snapshot_thread, (void *)this);
+
+end:
+ if (ret != NO_ERROR) {
+ handleError();
+ }
+
+ LOGD("%s: X", __func__);
+ return ret;
+
+}
+
+status_t QCameraStream_Snapshot::
+takePictureRaw(void)
+{
+ status_t ret = NO_ERROR;
+
+ LOGD("%s: E", __func__);
+
+ /* Take snapshot */
+ LOGD("%s: Call MM_CAMERA_OPS_SNAPSHOT", __func__);
+ if (NO_ERROR != cam_ops_action(mCameraId,
+ TRUE,
+ MM_CAMERA_OPS_RAW,
+ this)) {
+ LOGE("%s: Failure taking snapshot", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
+ /* TBD: Temp: to be removed once event callback
+ is implemented in mm-camera lib */
+ /* Wait for snapshot frame callback to return*/
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ pthread_create(&mSnapshotThread,&attr,
+ snapshot_thread, (void *)this);
+
+end:
+ if (ret != NO_ERROR) {
+ handleError();
+ }
+ LOGD("%s: X", __func__);
+ return ret;
+
+}
+
+/* This is called from vide stream object */
+status_t QCameraStream_Snapshot::
+takePictureLiveshot(mm_camera_ch_data_buf_t* recvd_frame,
+ cam_ctrl_dimension_t *dim,
+ int frame_len)
+{
+ status_t ret = NO_ERROR;
+ common_crop_t crop_info;
+ //common_crop_t crop;
+ uint32_t aspect_ratio;
+ camera_notify_callback notifyCb;
+ camera_data_callback dataCb;
+
+ LOGI("%s: E", __func__);
+
+ /* set flag to indicate we are doing livesnapshot */
+ resetSnapshotCounters( );
+ setModeLiveSnapshot(true);
+
+ if(!mHalCamCtrl->mShutterSoundPlayed) {
+ notifyShutter(&crop_info, TRUE);
+ }
+ notifyShutter(&crop_info, FALSE);
+ mHalCamCtrl->mShutterSoundPlayed = FALSE;
+
+ // send upperlayer callback for raw image (data or notify, not both)
+ if((mHalCamCtrl->mDataCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE)){
+ dataCb = mHalCamCtrl->mDataCb;
+ } else {
+ dataCb = NULL;
+ }
+ if((mHalCamCtrl->mNotifyCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE_NOTIFY)){
+ notifyCb = mHalCamCtrl->mNotifyCb;
+ } else {
+ notifyCb = NULL;
+ }
+
+ LOGI("%s:Passed picture size: %d X %d", __func__,
+ dim->picture_width, dim->picture_height);
+ LOGI("%s:Passed thumbnail size: %d X %d", __func__,
+ dim->ui_thumbnail_width, dim->ui_thumbnail_height);
+
+ mPictureWidth = dim->picture_width;
+ mPictureHeight = dim->picture_height;
+ mThumbnailWidth = dim->ui_thumbnail_width;
+ mThumbnailHeight = dim->ui_thumbnail_height;
+ mPictureFormat = dim->main_img_format;
+ mThumbnailFormat = dim->thumb_format;
+
+ memset(&crop_info, 0, sizeof(common_crop_t));
+ crop_info.in1_w = mPictureWidth;
+ crop_info.in1_h = mPictureHeight;
+ /* For low power live snapshot the thumbnail output size is set to default size.
+ In case of live snapshot video buffer = thumbnail buffer. For higher resolutions
+ the thumnail will be dropped if its more than 64KB. To avoid thumbnail drop
+ set thumbnail as configured by application. This will be a size lower than video size*/
+ mDropThumbnail = false;
+ if(mHalCamCtrl->thumbnailWidth == 0 && mHalCamCtrl->thumbnailHeight == 0) {
+ LOGE("Live Snapshot thumbnail will be dropped as indicated by application");
+ mDropThumbnail = true;
+ }
+ crop_info.out1_w = mHalCamCtrl->thumbnailWidth;
+ crop_info.out1_h = mHalCamCtrl->thumbnailHeight;
+ ret = encodeData(recvd_frame, &crop_info, frame_len, 0);
+ if (ret != NO_ERROR) {
+ LOGE("%s: Failure configuring JPEG encoder", __func__);
+
+ /* Failure encoding this frame. Just notify upper layer
+ about it.*/
+ if(mHalCamCtrl->mDataCb &&
+ (mHalCamCtrl->mMsgEnabled & MEDIA_RECORDER_MSG_COMPRESSED_IMAGE)) {
+ /* get picture failed. Give jpeg callback with NULL data
+ * to the application to restore to preview mode
+ */
+ }
+ setModeLiveSnapshot(false);
+ goto end;
+ }
+
+ if (dataCb) {
+ dataCb(CAMERA_MSG_RAW_IMAGE, mHalCamCtrl->mSnapshotMemory.camera_memory[0],
+ 1, NULL, mHalCamCtrl->mCallbackCookie);
+ }
+ if (notifyCb) {
+ notifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mHalCamCtrl->mCallbackCookie);
+ }
+
+end:
+ LOGI("%s: X", __func__);
+ return ret;
+}
+
+status_t QCameraStream_Snapshot::
+takePictureZSL(void)
+{
+ status_t ret = NO_ERROR;
+ mm_camera_ops_parm_get_buffered_frame_t param;
+
+ LOGE("%s: E", __func__);
+
+ memset(¶m, 0, sizeof(param));
+ param.ch_type = MM_CAMERA_CH_SNAPSHOT;
+
+ /* Take snapshot */
+ LOGE("%s: Call MM_CAMERA_OPS_GET_BUFFERED_FRAME", __func__);
+
+ mNumOfSnapshot = mHalCamCtrl->getNumOfSnapshots();
+ if (NO_ERROR != cam_ops_action(mCameraId,
+ TRUE,
+ MM_CAMERA_OPS_GET_BUFFERED_FRAME,
+ ¶m)) {
+ LOGE("%s: Failure getting zsl frame(s)", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
+ /* TBD: Temp: to be removed once event callback
+ is implemented in mm-camera lib */
+/* pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ pthread_create(&mSnapshotThread,&attr,
+ snapshot_thread, (void *)this);
+*/
+end:
+ LOGD("%s: X", __func__);
+ return ret;
+}
+
+status_t QCameraStream_Snapshot::
+startStreamZSL(void)
+{
+ status_t ret = NO_ERROR;
+
+ LOGD("%s: E", __func__);
+
+ /* Start ZSL - it'll start queuing the frames */
+ LOGD("%s: Call MM_CAMERA_OPS_ZSL", __func__);
+ if (NO_ERROR != cam_ops_action(mCameraId,
+ TRUE,
+ MM_CAMERA_OPS_ZSL,
+ this)) {
+ LOGE("%s: Failure starting ZSL stream", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
+end:
+ LOGD("%s: X", __func__);
+ return ret;
+
+}
+
+status_t QCameraStream_Snapshot::
+encodeData(mm_camera_ch_data_buf_t* recvd_frame,
+ common_crop_t *crop_info,
+ int frame_len,
+ bool enqueued)
+{
+ status_t ret = NO_ERROR;
+ cam_ctrl_dimension_t dimension;
+ struct msm_frame *postviewframe;
+ struct msm_frame *mainframe;
+ common_crop_t crop;
+ cam_point_t main_crop_offset;
+ cam_point_t thumb_crop_offset;
+ int width, height;
+ uint8_t *thumbnail_buf;
+ uint32_t thumbnail_fd;
+
+ omx_jpeg_encode_params encode_params;
+
+ /* If it's the only frame, we directly pass to encoder.
+ If not, we'll queue it and check during next jpeg .
+ Also, if the queue isn't empty then we need to queue this
+ one too till its turn comes (only if it's not already
+ queued up there)*/
+ LOGD("%s: getSnapshotState()=%d, enqueued =%d, Q empty=%d", __func__, getSnapshotState(), enqueued, mSnapshotQueue.isEmpty());
+ LOGD("%s: mNumOfRecievedJPEG=%d, mNumOfSnapshot =%d", __func__, mNumOfRecievedJPEG, mNumOfSnapshot);
+ if((getSnapshotState() == SNAPSHOT_STATE_JPEG_ENCODING) ||
+ (!mSnapshotQueue.isEmpty() && !enqueued)){ /*busy and new buffer*/
+ /* encoding is going on. Just queue the frame for now.*/
+ LOGD("%s: JPEG encoding in progress."
+ "Enqueuing frame id(%d) for later processing.", __func__,
+ recvd_frame->snapshot.main.idx);
+ mSnapshotQueue.enqueue((void *)recvd_frame);
+ } else if (enqueued ||
+ (mNumOfRecievedJPEG != mNumOfSnapshot && mNumOfRecievedJPEG != 0)) { /*not busy, not first*/
+ LOGD("%s: JPG not busy, not first frame.", __func__);
+
+ // For full-size live shot, use mainimage to generate thumbnail
+ if (isFullSizeLiveshot()) {
+ postviewframe = recvd_frame->snapshot.main.frame;
+ } else {
+ postviewframe = recvd_frame->snapshot.thumbnail.frame;
+ }
+ mainframe = recvd_frame->snapshot.main.frame;
+ cam_config_get_parm(mHalCamCtrl->mCameraId, MM_CAMERA_PARM_DIMENSION, &dimension);
+ LOGD("%s: main_fmt =%d, tb_fmt =%d", __func__, dimension.main_img_format, dimension.thumb_format);
+ /*since this is the continue job, we only care about the input buffer*/
+ encode_params.thumbnail_buf = (uint8_t *)postviewframe->buffer;
+ encode_params.thumbnail_fd = postviewframe->fd;
+ encode_params.snapshot_buf = (uint8_t *)mainframe->buffer;
+ encode_params.snapshot_fd = mainframe->fd;
+ encode_params.dimension = &dimension;
+ /*update exif parameters in HAL*/
+ mHalCamCtrl->setExifTags();
+
+ encode_params.exif_data = mHalCamCtrl->getExifData();
+ encode_params.exif_numEntries = mHalCamCtrl->getExifTableNumEntries();
+ if (!omxJpegEncodeNext(&encode_params)){
+ LOGE("%s: Failure! JPEG encoder returned error.", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+ /* Save the pointer to the frame sent for encoding. we'll need it to
+ tell kernel that we are done with the frame.*/
+ mCurrentFrameEncoded = recvd_frame;
+ setSnapshotState(SNAPSHOT_STATE_JPEG_ENCODING);
+ } else { /*not busy and new buffer (first job)*/
+
+ LOGD("%s: JPG Idle and first frame.", __func__);
+
+ // For full-size live shot, use mainimage to generate thumbnail
+ if (isFullSizeLiveshot()){
+ postviewframe = recvd_frame->snapshot.main.frame;
+ } else {
+ postviewframe = recvd_frame->snapshot.thumbnail.frame;
+ }
+ mainframe = recvd_frame->snapshot.main.frame;
+ cam_config_get_parm(mHalCamCtrl->mCameraId, MM_CAMERA_PARM_DIMENSION, &dimension);
+ LOGD("%s: main_fmt =%d, tb_fmt =%d", __func__, dimension.main_img_format, dimension.thumb_format);
+
+ dimension.orig_picture_dx = mPictureWidth;
+ dimension.orig_picture_dy = mPictureHeight;
+
+ if(!mDropThumbnail) {
+ if(isZSLMode()) {
+ LOGI("Setting input thumbnail size to previewWidth= %d previewheight= %d in ZSL mode",
+ mHalCamCtrl->mPreviewWidth, mHalCamCtrl->mPreviewHeight);
+ dimension.thumbnail_width = width = mHalCamCtrl->mPreviewWidth;
+ dimension.thumbnail_height = height = mHalCamCtrl->mPreviewHeight;
+ } else {
+ dimension.thumbnail_width = width = mThumbnailWidth;
+ dimension.thumbnail_height = height = mThumbnailHeight;
+ }
+ } else {
+ dimension.thumbnail_width = width = 0;
+ dimension.thumbnail_height = height = 0;
+ }
+ dimension.main_img_format = mPictureFormat;
+ dimension.thumb_format = mThumbnailFormat;
+
+ /*TBD: Move JPEG handling to the mm-camera library */
+ LOGD("Setting callbacks, initializing encoder and start encoding.");
+ LOGD(" Passing my obj: %x", (unsigned int) this);
+ set_callbacks(snapshot_jpeg_fragment_cb, snapshot_jpeg_cb, this,
+ mHalCamCtrl->mJpegMemory.camera_memory[0]->data, &mJpegOffset);
+ omxJpegStart();
+ if (mHalCamCtrl->getJpegQuality())
+ mm_jpeg_encoder_setMainImageQuality(mHalCamCtrl->getJpegQuality());
+ else
+ mm_jpeg_encoder_setMainImageQuality(85);
+
+ LOGE("%s: Dimension to encode: main: %dx%d thumbnail: %dx%d", __func__,
+ dimension.orig_picture_dx, dimension.orig_picture_dy,
+ dimension.thumbnail_width, dimension.thumbnail_height);
+
+ /*TBD: Pass 0 as cropinfo for now as v4l2 doesn't provide
+ cropinfo. It'll be changed later.*/
+ memset(&crop,0,sizeof(common_crop_t));
+ memset(&main_crop_offset,0,sizeof(cam_point_t));
+ memset(&thumb_crop_offset,0,sizeof(cam_point_t));
+
+ /* Setting crop info */
+
+ /*Main image*/
+ crop.in2_w=mCrop.snapshot.main_crop.width;// dimension.picture_width
+ crop.in2_h=mCrop.snapshot.main_crop.height;// dimension.picture_height;
+ if (!mJpegDownscaling) {
+ crop.out2_w = mPictureWidth;
+ crop.out2_h = mPictureHeight;
+ } else {
+ crop.out2_w = mActualPictureWidth;
+ crop.out2_h = mActualPictureHeight;
+ if (!crop.in2_w || !crop.in2_h) {
+ crop.in2_w = mPictureWidth;
+ crop.in2_h = mPictureHeight;
+ }
+ }
+ main_crop_offset.x=mCrop.snapshot.main_crop.left;
+ main_crop_offset.y=mCrop.snapshot.main_crop.top;
+ /*Thumbnail image*/
+ crop.in1_w=mCrop.snapshot.thumbnail_crop.width; //dimension.thumbnail_width;
+ crop.in1_h=mCrop.snapshot.thumbnail_crop.height; // dimension.thumbnail_height;
+ if(isLiveSnapshot() || isFullSizeLiveshot()) {
+ crop.out1_w= mHalCamCtrl->thumbnailWidth;
+ crop.out1_h= mHalCamCtrl->thumbnailHeight;
+ LOGD("Thumbnail width= %d height= %d for livesnapshot", crop.out1_w, crop.out1_h);
+ } else {
+ crop.out1_w = width;
+ crop.out1_h = height;
+ }
+ thumb_crop_offset.x=mCrop.snapshot.thumbnail_crop.left;
+ thumb_crop_offset.y=mCrop.snapshot.thumbnail_crop.top;
+
+ //update exif parameters in HAL
+ mHalCamCtrl->initExifData();
+
+ /*Fill in the encode parameters*/
+ encode_params.dimension = (const cam_ctrl_dimension_t *)&dimension;
+ //if (!isFullSizeLiveshot()) {
+ encode_params.thumbnail_buf = (uint8_t *)postviewframe->buffer;
+ encode_params.thumbnail_fd = postviewframe->fd;
+ encode_params.thumbnail_offset = postviewframe->phy_offset;
+ encode_params.thumb_crop_offset = &thumb_crop_offset;
+ //}
+ encode_params.snapshot_buf = (uint8_t *)mainframe->buffer;
+ encode_params.snapshot_fd = mainframe->fd;
+ encode_params.snapshot_offset = mainframe->phy_offset;
+ encode_params.scaling_params = &crop;
+ encode_params.exif_data = mHalCamCtrl->getExifData();
+ encode_params.exif_numEntries = mHalCamCtrl->getExifTableNumEntries();
+
+ if (isLiveSnapshot() && !isFullSizeLiveshot())
+ encode_params.a_cbcroffset = mainframe->cbcr_off;
+ else
+ encode_params.a_cbcroffset = -1;
+ encode_params.main_crop_offset = &main_crop_offset;
+
+ if (mDropThumbnail)
+ encode_params.hasThumbnail = 0;
+ else
+ encode_params.hasThumbnail = 1;
+ encode_params.thumb_crop_offset = &thumb_crop_offset;
+ encode_params.main_format = dimension.main_img_format;
+ encode_params.thumbnail_format = dimension.thumb_format;
+
+ if (!omxJpegEncode(&encode_params)){
+ LOGE("%s: Failure! JPEG encoder returned error.", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
+ /* Save the pointer to the frame sent for encoding. we'll need it to
+ tell kernel that we are done with the frame.*/
+ mCurrentFrameEncoded = recvd_frame;
+ setSnapshotState(SNAPSHOT_STATE_JPEG_ENCODING);
+ }
+
+end:
+ LOGD("%s: X", __func__);
+ return ret;
+}
+
+/* Called twice - 1st to play shutter sound and 2nd to configure
+ overlay/surfaceflinger for postview */
+void QCameraStream_Snapshot::notifyShutter(common_crop_t *crop,
+ bool mPlayShutterSoundOnly)
+{
+ LOGD("%s: E", __func__);
+ if(!mActive && !isLiveSnapshot()) {
+ LOGE("__debbug: Snapshot thread stopped \n");
+ return;
+ }
+ if(mHalCamCtrl->mNotifyCb)
+ mHalCamCtrl->mNotifyCb(CAMERA_MSG_SHUTTER, 0, mPlayShutterSoundOnly,
+ mHalCamCtrl->mCallbackCookie);
+ LOGD("%s: X", __func__);
+}
+
+status_t QCameraStream_Snapshot::
+encodeDisplayAndSave(mm_camera_ch_data_buf_t* recvd_frame,
+ bool enqueued)
+{
+ status_t ret = NO_ERROR;
+ struct msm_frame *postview_frame;
+ struct ion_flush_data cache_inv_data;
+ int ion_fd;
+ int buf_index = 0;
+ ssize_t offset_addr = 0;
+ common_crop_t dummy_crop;
+ /* send frame for encoding */
+ LOGE("%s: Send frame for encoding", __func__);
+ /*TBD: Pass 0 as cropinfo for now as v4l2 doesn't provide
+ cropinfo. It'll be changed later.*/
+ if(!mActive) {
+ LOGE("Cancel Picture.. Stop is called");
+ return NO_ERROR;
+ }
+ if(isZSLMode()){
+ LOGE("%s: set JPEG rotation in ZSL mode", __func__);
+ mHalCamCtrl->setJpegRotation(isZSLMode());
+ }
+#ifdef USE_ION
+ /*Clean out(Write-back) cache before sending for JPEG*/
+ memset(&cache_inv_data, 0, sizeof(struct ion_flush_data));
+
+ cache_inv_data.vaddr = (void*)recvd_frame->snapshot.main.frame->buffer;
+ cache_inv_data.fd = recvd_frame->snapshot.main.frame->fd;
+ cache_inv_data.handle = recvd_frame->snapshot.main.frame->fd_data.handle;
+ cache_inv_data.length = recvd_frame->snapshot.main.frame->ion_alloc.len;
+ ion_fd = recvd_frame->snapshot.main.frame->ion_dev_fd;
+ if(ion_fd > 0) {
+ if(ioctl(ion_fd, ION_IOC_CLEAN_INV_CACHES, &cache_inv_data) < 0)
+ LOGE("%s: Cache Invalidate failed\n", __func__);
+ else {
+ LOGD("%s: Successful cache invalidate\n", __func__);
+ if(!isFullSizeLiveshot()) {
+ ion_fd = recvd_frame->snapshot.thumbnail.frame->ion_dev_fd;
+ cache_inv_data.vaddr = (void*)recvd_frame->snapshot.thumbnail.frame->buffer;
+ cache_inv_data.fd = recvd_frame->snapshot.thumbnail.frame->fd;
+ cache_inv_data.handle = recvd_frame->snapshot.thumbnail.frame->fd_data.handle;
+ cache_inv_data.length = recvd_frame->snapshot.thumbnail.frame->ion_alloc.len;
+ if(ioctl(ion_fd, ION_IOC_CLEAN_INV_CACHES, &cache_inv_data) < 0)
+ LOGE("%s: Cache Invalidate failed\n", __func__);
+ else
+ LOGD("%s: Successful cache invalidate\n", __func__);
+ }
+ }
+ }
+#endif
+ memset(&dummy_crop,0,sizeof(common_crop_t));
+ ret = encodeData(recvd_frame, &dummy_crop, mSnapshotStreamBuf.frame_len,
+ enqueued);
+ if (ret != NO_ERROR) {
+ LOGE("%s: Failure configuring JPEG encoder", __func__);
+
+ goto end;
+ }
+
+ /* Display postview image*/
+ /* If it's burst mode, we won't be displaying postview of all the captured
+ images - only the first one */
+ LOGD("%s: Burst mode flag %d", __func__, mBurstModeFlag);
+
+end:
+ LOGD("%s: X", __func__);
+ return ret;
+}
+
+status_t QCameraStream_Snapshot::receiveRawPicture(mm_camera_ch_data_buf_t* recvd_frame)
+{
+ int buf_index = 0;
+ common_crop_t crop;
+ int rc = NO_ERROR;
+
+ camera_notify_callback notifyCb;
+ camera_data_callback dataCb, jpgDataCb;
+
+ LOGD("%s: E ", __func__);
+ mStopCallbackLock.lock( );
+ if(!mActive) {
+ mStopCallbackLock.unlock();
+ LOGD("%s: Stop receiving raw pic ", __func__);
+ return NO_ERROR;
+ }
+
+ mHalCamCtrl->dumpFrameToFile(recvd_frame->snapshot.main.frame, HAL_DUMP_FRM_MAIN);
+ if (!isFullSizeLiveshot())
+ mHalCamCtrl->dumpFrameToFile(recvd_frame->snapshot.thumbnail.frame,
+ HAL_DUMP_FRM_THUMBNAIL);
+
+ /* If it's raw snapshot, we just want to tell upperlayer to save the image*/
+ if(mSnapshotFormat == PICTURE_FORMAT_RAW) {
+ LOGD("%s: Call notifyShutter 2nd time in case of RAW", __func__);
+ mStopCallbackLock.unlock();
+ if(!mHalCamCtrl->mShutterSoundPlayed) {
+ notifyShutter(&crop, TRUE);
+ }
+ notifyShutter(&crop, FALSE);
+ mHalCamCtrl->mShutterSoundPlayed = FALSE;
+
+ mStopCallbackLock.lock( );
+ LOGD("%s: Sending Raw Snapshot Callback to Upperlayer", __func__);
+ buf_index = recvd_frame->def.idx;
+
+ if (mHalCamCtrl->mDataCb && mActive &&
+ (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)){
+ dataCb = mHalCamCtrl->mDataCb;
+ } else {
+ dataCb = NULL;
+ }
+ mStopCallbackLock.unlock();
+
+ if(dataCb) {
+ dataCb(
+ CAMERA_MSG_COMPRESSED_IMAGE,
+ mHalCamCtrl->mRawMemory.camera_memory[buf_index], 0, NULL,
+ mHalCamCtrl->mCallbackCookie);
+ }
+ /* TBD: Temp: To be removed once event handling is enabled */
+ mm_app_snapshot_done();
+ } else {
+ /*TBD: v4l2 doesn't have support to provide cropinfo along with
+ frame. We'll need to query.*/
+ memset(&crop, 0, sizeof(common_crop_t));
+
+ /*maftab*/
+ #if 0
+ crop.in1_w=mCrop.snapshot.thumbnail_crop.width;
+ crop.in1_h=mCrop.snapshot.thumbnail_crop.height;
+ crop.out1_w=mThumbnailWidth;
+ crop.out1_h=mThumbnailHeight;
+ #endif
+
+ LOGD("%s: Call notifyShutter 2nd time", __func__);
+ /* The recvd_frame structre we receive from lower library is a local
+ variable. So we'll need to save this structure so that we won't
+ be later pointing to garbage data when that variable goes out of
+ scope */
+ mm_camera_ch_data_buf_t* frame =
+ (mm_camera_ch_data_buf_t *)malloc(sizeof(mm_camera_ch_data_buf_t));
+ if (frame == NULL) {
+ LOGE("%s: Error allocating memory to save received_frame structure.", __func__);
+ cam_evt_buf_done(mCameraId, recvd_frame);
+ mStopCallbackLock.unlock();
+ return BAD_VALUE;
+ }
+ memcpy(frame, recvd_frame, sizeof(mm_camera_ch_data_buf_t));
+
+ //mStopCallbackLock.lock();
+
+ // only in ZSL mode and Wavelet Denoise is enabled, we will send frame to deamon to do WDN
+ if (isZSLMode() && mHalCamCtrl->isWDenoiseEnabled()) {
+ if(mIsDoingWDN){
+ mWDNQueue.enqueue((void *)frame);
+ LOGD("%s: Wavelet denoise is going on, queue frame", __func__);
+ rc = NO_ERROR;
+ } else {
+ LOGD("%s: Start Wavelet denoise", __func__);
+ mIsDoingWDN = TRUE; // set the falg to TRUE because we are going to do WDN
+
+ // No WDN is going on so far, we will start it here
+ rc = doWaveletDenoise(frame);
+ if ( NO_ERROR != rc ) {
+ LOGE("%s: Error while doing wavelet denoise", __func__);
+ mIsDoingWDN = FALSE;
+ }
+ }
+ }
+ else {
+ LOGD("%s: encodeDisplayAndSave ", __func__);
+ rc = encodeDisplayAndSave(frame, 0);
+ }
+
+
+ // send upperlayer callback for raw image (data or notify, not both)
+ if((mHalCamCtrl->mDataCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE)){
+ dataCb = mHalCamCtrl->mDataCb;
+ } else {
+ dataCb = NULL;
+ }
+ if((mHalCamCtrl->mNotifyCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE_NOTIFY)){
+ notifyCb = mHalCamCtrl->mNotifyCb;
+ } else {
+ notifyCb = NULL;
+ }
+
+ mStopCallbackLock.unlock();
+ if(!mHalCamCtrl->mShutterSoundPlayed) {
+ notifyShutter(&crop, TRUE);
+ }
+ notifyShutter(&crop, FALSE);
+ mHalCamCtrl->mShutterSoundPlayed = FALSE;
+
+
+ if (rc != NO_ERROR)
+ {
+ LOGE("%s: Error while encoding/displaying/saving image", __func__);
+ cam_evt_buf_done(mCameraId, recvd_frame);
+
+ if(mHalCamCtrl->mDataCb &&
+ (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
+ /* get picture failed. Give jpeg callback with NULL data
+ * to the application to restore to preview mode
+ */
+ jpgDataCb = mHalCamCtrl->mDataCb;
+ } else {
+ jpgDataCb = NULL;
+ }
+ LOGE("%s: encode err so data cb", __func__);
+ //mStopCallbackLock.unlock();
+ if (dataCb) {
+ dataCb(CAMERA_MSG_RAW_IMAGE, mHalCamCtrl->mSnapshotMemory.camera_memory[0],
+ 1, NULL, mHalCamCtrl->mCallbackCookie);
+ }
+ if (notifyCb) {
+ notifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mHalCamCtrl->mCallbackCookie);
+ }
+ if (jpgDataCb) {
+ jpgDataCb(CAMERA_MSG_COMPRESSED_IMAGE,
+ NULL, 0, NULL,
+ mHalCamCtrl->mCallbackCookie);
+ }
+
+ if (frame != NULL) {
+ free(frame);
+ }
+ } else {
+
+ //mStopCallbackLock.unlock();
+ if (dataCb) {
+ dataCb(CAMERA_MSG_RAW_IMAGE, mHalCamCtrl->mSnapshotMemory.camera_memory[0],
+ 1, NULL, mHalCamCtrl->mCallbackCookie);
+ }
+ if (notifyCb) {
+ notifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mHalCamCtrl->mCallbackCookie);
+ }
+ }
+ }
+
+ LOGD("%s: X", __func__);
+ return NO_ERROR;
+}
+
+//-------------------------------------------------------------------
+// Helper Functions
+//-------------------------------------------------------------------
+void QCameraStream_Snapshot::handleError()
+{
+ mm_camera_channel_type_t ch_type;
+ LOGD("%s: E", __func__);
+
+ /* Depending upon the state we'll have to
+ handle error */
+ switch(getSnapshotState()) {
+ case SNAPSHOT_STATE_JPEG_ENCODING:
+ if(mJpegHeap != NULL) mJpegHeap.clear();
+ mJpegHeap = NULL;
+
+ case SNAPSHOT_STATE_YUV_RECVD:
+ case SNAPSHOT_STATE_IMAGE_CAPTURE_STRTD:
+ stopPolling();
+ case SNAPSHOT_STATE_INITIALIZED:
+ case SNAPSHOT_STATE_BUF_INITIALIZED:
+ if (mSnapshotFormat == PICTURE_FORMAT_JPEG) {
+ deinitSnapshotBuffers();
+ }else
+ {
+ deinitRawSnapshotBuffers();
+ }
+ case SNAPSHOT_STATE_BUF_NOTIF_REGD:
+ case SNAPSHOT_STATE_CH_ACQUIRED:
+ if (mSnapshotFormat == PICTURE_FORMAT_JPEG) {
+ deinitSnapshotChannel(MM_CAMERA_CH_SNAPSHOT);
+ }else
+ {
+ deinitSnapshotChannel(MM_CAMERA_CH_RAW);
+ }
+ default:
+ /* Set the state to ERROR */
+ setSnapshotState(SNAPSHOT_STATE_ERROR);
+ break;
+ }
+
+ LOGD("%s: X", __func__);
+}
+
+void QCameraStream_Snapshot::setSnapshotState(int state)
+{
+ LOGD("%s: Setting snapshot state to: %d",
+ __func__, state);
+ mSnapshotState = state;
+}
+
+int QCameraStream_Snapshot::getSnapshotState()
+{
+ return mSnapshotState;
+}
+
+void QCameraStream_Snapshot::setModeLiveSnapshot(bool value)
+{
+ mModeLiveSnapshot = value;
+}
+
+bool QCameraStream_Snapshot::isLiveSnapshot(void)
+{
+ return mModeLiveSnapshot;
+}
+bool QCameraStream_Snapshot::isZSLMode()
+{
+ return (myMode & CAMERA_ZSL_MODE);
+}
+
+void QCameraStream_Snapshot::setFullSizeLiveshot(bool value)
+{
+ mFullLiveshot = value;
+}
+
+bool QCameraStream_Snapshot::isFullSizeLiveshot()
+{
+ return mFullLiveshot;
+}
+
+void QCameraStream_Snapshot::resetSnapshotCounters(void )
+{
+ mNumOfSnapshot = mHalCamCtrl->getNumOfSnapshots();
+ if (mNumOfSnapshot <= 0) {
+ mNumOfSnapshot = 1;
+ }
+ mNumOfRecievedJPEG = 0;
+ LOGD("%s: Number of images to be captured: %d", __func__, mNumOfSnapshot);
+}
+
+//------------------------------------------------------------------
+// Constructor and Destructor
+//------------------------------------------------------------------
+QCameraStream_Snapshot::
+QCameraStream_Snapshot(int cameraId, camera_mode_t mode)
+ : QCameraStream(cameraId,mode),
+ mSnapshotFormat(PICTURE_FORMAT_JPEG),
+ mPictureWidth(0), mPictureHeight(0),
+ mPictureFormat(CAMERA_YUV_420_NV21),
+ mPostviewWidth(0), mPostviewHeight(0),
+ mThumbnailWidth(0), mThumbnailHeight(0),
+ mThumbnailFormat(CAMERA_YUV_420_NV21),
+ mJpegOffset(0),
+ mSnapshotState(SNAPSHOT_STATE_UNINIT),
+ mNumOfSnapshot(1),
+ mModeLiveSnapshot(false),
+ mBurstModeFlag(false),
+ mActualPictureWidth(0),
+ mActualPictureHeight(0),
+ mJpegDownscaling(false),
+ mJpegHeap(NULL),
+ mDisplayHeap(NULL),
+ mPostviewHeap(NULL),
+ mCurrentFrameEncoded(NULL),
+ mJpegSessionId(0),
+ mFullLiveshot(false),
+ mDropThumbnail(false)
+ {
+ LOGV("%s: E", __func__);
+
+ /*initialize snapshot queue*/
+ mSnapshotQueue.init();
+
+ /*initialize WDN queue*/
+ mWDNQueue.init();
+ mIsDoingWDN = FALSE;
+
+ memset(&mSnapshotStreamBuf, 0, sizeof(mSnapshotStreamBuf));
+ memset(&mPostviewStreamBuf, 0, sizeof(mPostviewStreamBuf));
+ mSnapshotBufferNum = 0;
+ mMainSize = 0;
+ mThumbSize = 0;
+ for(int i = 0; i < mMaxSnapshotBufferCount; i++) {
+ mMainfd[i] = 0;
+ mThumbfd[i] = 0;
+ mCameraMemoryPtrMain[i] = NULL;
+ mCameraMemoryPtrThumb[i] = NULL;
+ }
+ /*load the jpeg lib*/
+ mJpegSessionId = omxJpegOpen( );
+ LOGV("%s: X", __func__);
+ }
+
+
+QCameraStream_Snapshot::~QCameraStream_Snapshot() {
+ LOGV("%s: E", __func__);
+
+ /* deinit snapshot queue */
+ if (mSnapshotQueue.isInitialized()) {
+ mSnapshotQueue.deinit();
+ }
+ /* deinit snapshot queue */
+ if (mWDNQueue.isInitialized()) {
+ mWDNQueue.deinit();
+ }
+
+ if(mActive) {
+ stop();
+ }
+ if(mInit) {
+ release();
+ }
+ mInit = false;
+ mActive = false;
+ if (mJpegSessionId > 0) {
+ omxJpegClose( );
+ mJpegSessionId = 0;
+ }
+ LOGV("%s: X", __func__);
+
+}
+
+//------------------------------------------------------------------
+// Public Members
+//------------------------------------------------------------------
+status_t QCameraStream_Snapshot::init()
+{
+ status_t ret = NO_ERROR;
+ mm_camera_op_mode_type_t op_mode;
+
+ LOGV("%s: E", __func__);
+ /* Check the state. If we have already started snapshot
+ process just return*/
+ if (getSnapshotState() != SNAPSHOT_STATE_UNINIT) {
+ ret = isZSLMode() ? NO_ERROR : INVALID_OPERATION;
+ LOGE("%s: Trying to take picture while snapshot is in progress",
+ __func__);
+ goto end;
+ }
+ mInit = true;
+
+end:
+ /*if (ret == NO_ERROR) {
+ setSnapshotState(SNAPSHOT_STATE_INITIALIZED);
+ }*/
+ LOGV("%s: X", __func__);
+ return ret;
+}
+
+status_t QCameraStream_Snapshot::start(void) {
+ status_t ret = NO_ERROR;
+
+ LOGV("%s: E", __func__);
+
+ Mutex::Autolock lock(mStopCallbackLock);
+
+ /* Keep track of number of snapshots to take - in case of
+ multiple snapshot/burst mode */
+
+ if(mHalCamCtrl->isRawSnapshot()) {
+ LOGD("%s: Acquire Raw Snapshot Channel", __func__);
+ ret = cam_ops_ch_acquire(mCameraId, MM_CAMERA_CH_RAW);
+ if (NO_ERROR != ret) {
+ LOGE("%s: Failure Acquiring Raw Snapshot Channel error =%d\n",
+ __func__, ret);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+ /* Snapshot channel is acquired */
+ setSnapshotState(SNAPSHOT_STATE_CH_ACQUIRED);
+ LOGD("%s: Register buffer notification. My object: %x",
+ __func__, (unsigned int) this);
+ (void) cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_RAW,
+ snapshot_notify_cb,
+ MM_CAMERA_REG_BUF_CB_INFINITE,
+ 0,
+ this);
+ /* Set the state to buffer notification completed */
+ setSnapshotState(SNAPSHOT_STATE_BUF_NOTIF_REGD);
+ }else{
+ LOGD("%s: Acquire Snapshot Channel", __func__);
+ ret = cam_ops_ch_acquire(mCameraId, MM_CAMERA_CH_SNAPSHOT);
+ if (NO_ERROR != ret) {
+ LOGE("%s: Failure Acquiring Snapshot Channel error =%d\n", __func__, ret);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+ /* Snapshot channel is acquired */
+ setSnapshotState(SNAPSHOT_STATE_CH_ACQUIRED);
+ LOGD("%s: Register buffer notification. My object: %x",
+ __func__, (unsigned int) this);
+ (void) cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_SNAPSHOT,
+ snapshot_notify_cb,
+ MM_CAMERA_REG_BUF_CB_INFINITE,
+ 0,
+ this);
+ /* Set the state to buffer notification completed */
+ setSnapshotState(SNAPSHOT_STATE_BUF_NOTIF_REGD);
+ }
+
+ if (isZSLMode()) {
+ prepareHardware();
+ ret = initZSLSnapshot();
+ if(ret != NO_ERROR) {
+ LOGE("%s : Error while Initializing ZSL snapshot",__func__);
+ goto end;
+ }
+ mHalCamCtrl->setExifTags();
+ /* In case of ZSL, start will only start snapshot stream and
+ continuously queue the frames in a queue. When user clicks
+ shutter we'll call get buffer from the queue and pass it on */
+ ret = startStreamZSL();
+ goto end;
+ }
+
+ if (isFullSizeLiveshot())
+ ret = initFullLiveshot();
+
+ /* Check if it's a raw snapshot or JPEG*/
+ if(mHalCamCtrl->isRawSnapshot()) {
+ mSnapshotFormat = PICTURE_FORMAT_RAW;
+ ret = initRawSnapshot(mNumOfSnapshot);
+ }else{
+ //JPEG
+ mSnapshotFormat = PICTURE_FORMAT_JPEG;
+ ret = initJPEGSnapshot(mNumOfSnapshot);
+ }
+ if(ret != NO_ERROR) {
+ LOGE("%s : Error while Initializing snapshot",__func__);
+ goto end;
+ }
+
+ //Update Exiftag values.
+ mHalCamCtrl->setExifTags();
+
+ if (mSnapshotFormat == PICTURE_FORMAT_RAW) {
+ ret = takePictureRaw();
+ goto end;
+ }
+ else{
+ ret = takePictureJPEG();
+ goto end;
+ }
+
+end:
+ if (ret == NO_ERROR) {
+ setSnapshotState(SNAPSHOT_STATE_IMAGE_CAPTURE_STRTD);
+ mActive = true;
+ } else {
+ deInitBuffer();
+ }
+
+ LOGV("%s: X", __func__);
+ return ret;
+ }
+
+void QCameraStream_Snapshot::stopPolling(void)
+{
+ mm_camera_ops_type_t ops_type;
+
+ if (mSnapshotFormat == PICTURE_FORMAT_JPEG) {
+ ops_type = isZSLMode() ? MM_CAMERA_OPS_ZSL : MM_CAMERA_OPS_SNAPSHOT;
+ }else
+ ops_type = MM_CAMERA_OPS_RAW;
+
+ if( NO_ERROR != cam_ops_action(mCameraId, FALSE,
+ ops_type, this)) {
+ LOGE("%s: Failure stopping snapshot", __func__);
+ }
+}
+
+void QCameraStream_Snapshot::stop(void)
+{
+ mm_camera_ops_type_t ops_type;
+ status_t ret = NO_ERROR;
+
+ LOGV("%s: E", __func__);
+ //Mutex::Autolock l(&snapshotLock);
+
+ if(!mActive) {
+ LOGV("%s: Not Active return now", __func__);
+ return;
+ }
+ mActive = false;
+ Mutex::Autolock lock(mStopCallbackLock);
+ if (getSnapshotState() != SNAPSHOT_STATE_UNINIT) {
+ /* Stop polling for further frames */
+ stopPolling();
+
+ if(getSnapshotState() == SNAPSHOT_STATE_JPEG_ENCODING) {
+ LOGV("Destroy Jpeg Instance");
+ omxJpegAbort();
+ }
+
+ /* Depending upon current state, we'll need to allocate-deallocate-deinit*/
+ deInitBuffer();
+ }
+
+ if(mSnapshotFormat == PICTURE_FORMAT_RAW) {
+ ret= QCameraStream::deinitChannel(mCameraId, MM_CAMERA_CH_RAW);
+ if(ret != MM_CAMERA_OK) {
+ LOGE("%s:Deinit RAW channel failed=%d\n", __func__, ret);
+ }
+ (void)cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_RAW,
+ NULL,
+ (mm_camera_register_buf_cb_type_t)NULL,
+ NULL,
+ NULL);
+ } else {
+ ret= QCameraStream::deinitChannel(mCameraId, MM_CAMERA_CH_SNAPSHOT);
+ if(ret != MM_CAMERA_OK) {
+ LOGE("%s:Deinit Snapshot channel failed=%d\n", __func__, ret);
+ }
+ (void)cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_SNAPSHOT,
+ NULL,
+ (mm_camera_register_buf_cb_type_t)NULL,
+ NULL,
+ NULL);
+ }
+
+ /* release is generally called in case of explicit call from
+ upper-layer during disconnect. So we need to deinit everything
+ whatever state we are in */
+ LOGV("Calling omxjpegjoin from release\n");
+ omxJpegFinish();
+#if 0
+ omxJpegClose();
+#endif
+ mFullLiveshot = false;
+ LOGV("%s: X", __func__);
+
+}
+
+void QCameraStream_Snapshot::release()
+{
+ status_t ret = NO_ERROR;
+ LOGV("%s: E", __func__);
+ //Mutex::Autolock l(&snapshotLock);
+
+ if(isLiveSnapshot()) {
+ deInitBuffer();
+ }
+ if(!mInit){
+ LOGE("%s : Stream not Initalized",__func__);
+ return;
+ }
+
+ if(mActive) {
+ this->stop();
+ mActive = FALSE;
+ }
+
+ /* release is generally called in case of explicit call from
+ upper-layer during disconnect. So we need to deinit everything
+ whatever state we are in */
+
+ //deinit();
+ mInit = false;
+ LOGV("%s: X", __func__);
+
+}
+
+void QCameraStream_Snapshot::prepareHardware()
+{
+ LOGV("%s: E", __func__);
+
+ /* Prepare snapshot*/
+ cam_ops_action(mCameraId,
+ TRUE,
+ MM_CAMERA_OPS_PREPARE_SNAPSHOT,
+ this);
+ LOGV("%s: X", __func__);
+}
+
+sp<IMemoryHeap> QCameraStream_Snapshot::getRawHeap() const
+{
+ return ((mDisplayHeap != NULL) ? mDisplayHeap->mHeap : NULL);
+}
+
+QCameraStream*
+QCameraStream_Snapshot::createInstance(int cameraId,
+ camera_mode_t mode)
+{
+
+ QCameraStream* pme = new QCameraStream_Snapshot(cameraId, mode);
+
+ return pme;
+}
+
+void QCameraStream_Snapshot::deleteInstance(QCameraStream *p)
+{
+ if (p){
+ p->release();
+ delete p;
+ p = NULL;
+ }
+}
+
+void QCameraStream_Snapshot::notifyWDenoiseEvent(cam_ctrl_status_t status, void * cookie)
+{
+ camera_notify_callback notifyCb;
+ camera_data_callback dataCb, jpgDataCb;
+ int rc = NO_ERROR;
+ mm_camera_ch_data_buf_t *frame = (mm_camera_ch_data_buf_t *)cookie;
+
+ LOGI("%s: WDN Done status (%d) received",__func__,status);
+ Mutex::Autolock lock(mStopCallbackLock);
+ if (frame == NULL) {
+ LOGE("%s: cookie is returned NULL", __func__);
+ } else {
+ // first unmapping the fds
+ mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN, frame->snapshot.main.idx, mCameraId,
+ CAM_SOCK_MSG_TYPE_FD_UNMAPPING);
+ mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL, frame->snapshot.thumbnail.idx, mCameraId,
+ CAM_SOCK_MSG_TYPE_FD_UNMAPPING);
+
+ // then do JPEG encoding
+ rc = encodeDisplayAndSave(frame, 0);
+ }
+
+ // send upperlayer callback for raw image (data or notify, not both)
+ if((mHalCamCtrl->mDataCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE)){
+ dataCb = mHalCamCtrl->mDataCb;
+ } else {
+ dataCb = NULL;
+ }
+ if((mHalCamCtrl->mNotifyCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE_NOTIFY)){
+ notifyCb = mHalCamCtrl->mNotifyCb;
+ } else {
+ notifyCb = NULL;
+ }
+ if(mHalCamCtrl->mDataCb &&
+ (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
+ /* get picture failed. Give jpeg callback with NULL data
+ * to the application to restore to preview mode
+ */
+ jpgDataCb = mHalCamCtrl->mDataCb;
+ } else {
+ jpgDataCb = NULL;
+ }
+
+ // launch next WDN if there is more in WDN Queue
+ lauchNextWDenoiseFromQueue();
+
+ mStopCallbackLock.unlock();
+
+ if (rc != NO_ERROR)
+ {
+ LOGE("%s: Error while encoding/displaying/saving image", __func__);
+ if (frame) {
+ cam_evt_buf_done(mCameraId, frame);
+ }
+
+ if (dataCb) {
+ dataCb(CAMERA_MSG_RAW_IMAGE, mHalCamCtrl->mSnapshotMemory.camera_memory[0],
+ 1, NULL, mHalCamCtrl->mCallbackCookie);
+ }
+ if (notifyCb) {
+ notifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mHalCamCtrl->mCallbackCookie);
+ }
+ if (jpgDataCb) {
+ jpgDataCb(CAMERA_MSG_COMPRESSED_IMAGE,
+ NULL, 0, NULL,
+ mHalCamCtrl->mCallbackCookie);
+ }
+
+ if (frame != NULL) {
+ free(frame);
+ }
+ }
+}
+
+void QCameraStream_Snapshot::lauchNextWDenoiseFromQueue()
+{
+ do {
+ mm_camera_ch_data_buf_t *frame = NULL;
+ if ( mWDNQueue.isEmpty() ||
+ (NULL == (frame = (mm_camera_ch_data_buf_t *)mWDNQueue.dequeue())) ) {
+ // set the flag back to FALSE when no WDN going on
+ mIsDoingWDN = FALSE;
+ break;
+ }
+
+ if ( NO_ERROR != doWaveletDenoise(frame) ) {
+ LOGE("%s: Error while doing wavelet denoise", __func__);
+ if (frame != NULL) {
+ free(frame);
+ }
+ } else {
+ // we sent out req for WDN, so we can break here
+ LOGD("%s: Send out req for doing wavelet denoise, return here", __func__);
+ break;
+ }
+ } while (TRUE);
+}
+
+status_t QCameraStream_Snapshot::doWaveletDenoise(mm_camera_ch_data_buf_t* frame)
+{
+ status_t ret = NO_ERROR;
+ cam_sock_packet_t packet;
+ cam_ctrl_dimension_t dim;
+
+ LOGD("%s: E", __func__);
+
+ // get dim on the fly
+ memset(&dim, 0, sizeof(cam_ctrl_dimension_t));
+ ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION, &dim);
+ if (NO_ERROR != ret) {
+ LOGE("%s: error - can't get dimension!", __func__);
+ return FAILED_TRANSACTION;
+ }
+
+ // send main frame mapping through domain socket
+ if (NO_ERROR != mHalCamCtrl->sendMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN,
+ frame->snapshot.main.idx,
+ frame->snapshot.main.frame->fd,
+ dim.picture_frame_offset.frame_len, mCameraId,
+ CAM_SOCK_MSG_TYPE_FD_MAPPING)) {
+ LOGE("%s: sending main frame mapping buf msg Failed", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
+ // send thumbnail frame mapping through domain socket
+ if (NO_ERROR != mHalCamCtrl->sendMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL,
+ frame->snapshot.thumbnail.idx,
+ frame->snapshot.thumbnail.frame->fd,
+ dim.display_frame_offset.frame_len, mCameraId,
+ CAM_SOCK_MSG_TYPE_FD_MAPPING)) {
+ LOGE("%s: sending thumbnail frame mapping buf msg Failed", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
+ // ask deamon to start wdn operation
+ if (NO_ERROR != sendWDenoiseStartMsg(frame)) {
+ LOGE("%s: sending thumbnail frame mapping buf msg Failed", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
+end:
+ LOGD("%s: X", __func__);
+ return ret;
+}
+
+status_t QCameraStream_Snapshot::sendWDenoiseStartMsg(mm_camera_ch_data_buf_t * frame)
+{
+ cam_sock_packet_t packet;
+ memset(&packet, 0, sizeof(cam_sock_packet_t));
+ packet.msg_type = CAM_SOCK_MSG_TYPE_WDN_START;
+ packet.payload.wdn_start.cookie = (unsigned long)frame;
+ packet.payload.wdn_start.num_frames = MM_MAX_WDN_NUM;
+ packet.payload.wdn_start.ext_mode[0] = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
+ packet.payload.wdn_start.ext_mode[1] = MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
+ packet.payload.wdn_start.frame_idx[0] = frame->snapshot.main.idx;
+ packet.payload.wdn_start.frame_idx[1] = frame->snapshot.thumbnail.idx;
+ if ( cam_ops_sendmsg(mCameraId, &packet, sizeof(packet), 0) <= 0 ) {
+ LOGE("%s: sending start wavelet denoise msg failed", __func__);
+ return FAILED_TRANSACTION;
+ }
+ return NO_ERROR;
+}
+
+}; // namespace android
+
diff --git a/camera/QCamera/HAL/core/src/QCameraStream.cpp b/camera/QCamera/HAL/core/src/QCameraStream.cpp
new file mode 100755
index 0000000..48c2363
--- /dev/null
+++ b/camera/QCamera/HAL/core/src/QCameraStream.cpp
@@ -0,0 +1,364 @@
+/*
+** 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.
+** 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 __FILE__
+#include <utils/Log.h>
+#include <utils/threads.h>
+
+
+#include "QCameraStream.h"
+
+/* QCameraStream class implementation goes here*/
+/* following code implement the control logic of this class*/
+
+namespace android {
+
+StreamQueue::StreamQueue(){
+ mInitialized = false;
+}
+
+StreamQueue::~StreamQueue(){
+ flush();
+}
+
+void StreamQueue::init(){
+ Mutex::Autolock l(&mQueueLock);
+ mInitialized = true;
+ mQueueWait.signal();
+}
+
+void StreamQueue::deinit(){
+ Mutex::Autolock l(&mQueueLock);
+ mInitialized = false;
+ mQueueWait.signal();
+}
+
+bool StreamQueue::isInitialized(){
+ Mutex::Autolock l(&mQueueLock);
+ return mInitialized;
+}
+
+bool StreamQueue::enqueue(
+ void * element){
+ Mutex::Autolock l(&mQueueLock);
+ if(mInitialized == false)
+ return false;
+
+ mContainer.add(element);
+ mQueueWait.signal();
+ return true;
+}
+
+bool StreamQueue::isEmpty(){
+ return (mInitialized && mContainer.isEmpty());
+}
+void* StreamQueue::dequeue(){
+
+ void *frame;
+ mQueueLock.lock();
+ while(mInitialized && mContainer.isEmpty()){
+ mQueueWait.wait(mQueueLock);
+ }
+
+ if(!mInitialized){
+ mQueueLock.unlock();
+ return NULL;
+ }
+
+ frame = mContainer.itemAt(0);
+ mContainer.removeAt(0);
+ mQueueLock.unlock();
+ return frame;
+}
+
+void StreamQueue::flush(){
+ Mutex::Autolock l(&mQueueLock);
+ mContainer.clear();
+}
+
+
+// ---------------------------------------------------------------------------
+// QCameraStream
+// ---------------------------------------------------------------------------
+
+/* initialize a streaming channel*/
+status_t QCameraStream::initChannel(int cameraId,
+ uint32_t ch_type_mask)
+{
+#if 0
+ int rc = MM_CAMERA_OK;
+ int i;
+ status_t ret = NO_ERROR;
+ int width = 0; /* width of channel */
+ int height = 0; /* height of channel */
+ cam_ctrl_dimension_t dim;
+ mm_camera_ch_image_fmt_parm_t fmt;
+
+ memset(&dim, 0, sizeof(cam_ctrl_dimension_t));
+ rc = cam_config_get_parm(cameraId, MM_CAMERA_PARM_DIMENSION, &dim);
+ if (MM_CAMERA_OK != rc) {
+ LOGE("%s: error - can't get camera dimension!", __func__);
+ LOGE("%s: X", __func__);
+ return BAD_VALUE;
+ }
+
+ if(MM_CAMERA_CH_PREVIEW_MASK & ch_type_mask) {
+ rc = cam_ops_ch_acquire(cameraId, MM_CAMERA_CH_PREVIEW);
+ LOGV("%s:ch_acquire MM_CAMERA_CH_PREVIEW, rc=%d\n",__func__, rc);
+
+ if(MM_CAMERA_OK != rc) {
+ LOGE("%s: preview channel acquir error =%d\n", __func__, rc);
+ LOGE("%s: X", __func__);
+ return BAD_VALUE;
+ }
+ else{
+ memset(&fmt, 0, sizeof(mm_camera_ch_image_fmt_parm_t));
+ fmt.ch_type = MM_CAMERA_CH_PREVIEW;
+ fmt.def.fmt = CAMERA_YUV_420_NV12; //dim.prev_format;
+ fmt.def.dim.width = dim.display_width;
+ fmt.def.dim.height = dim.display_height;
+ LOGV("%s: preview channel fmt = %d", __func__,
+ dim.prev_format);
+ LOGV("%s: preview channel resolution = %d X %d", __func__,
+ dim.display_width, dim.display_height);
+
+ rc = cam_config_set_parm(cameraId, MM_CAMERA_PARM_CH_IMAGE_FMT, &fmt);
+ LOGV("%s: preview MM_CAMERA_PARM_CH_IMAGE_FMT rc = %d\n", __func__, rc);
+ if(MM_CAMERA_OK != rc) {
+ LOGE("%s:set preview channel format err=%d\n", __func__, ret);
+ LOGE("%s: X", __func__);
+ ret = BAD_VALUE;
+ }
+ }
+ }
+
+
+ if(MM_CAMERA_CH_VIDEO_MASK & ch_type_mask)
+ {
+ rc = cam_ops_ch_acquire(cameraId, MM_CAMERA_CH_VIDEO);
+ LOGV("%s:ch_acquire MM_CAMERA_CH_VIDEO, rc=%d\n",__func__, rc);
+
+ if(MM_CAMERA_OK != rc) {
+ LOGE("%s: video channel acquir error =%d\n", __func__, rc);
+ LOGE("%s: X", __func__);
+ ret = BAD_VALUE;
+ }
+ else {
+ memset(&fmt, 0, sizeof(mm_camera_ch_image_fmt_parm_t));
+ fmt.ch_type = MM_CAMERA_CH_VIDEO;
+ fmt.video.video.fmt = CAMERA_YUV_420_NV12; //dim.enc_format;
+ fmt.video.video.dim.width = dim.video_width;
+ fmt.video.video.dim.height = dim.video_height;
+ LOGV("%s: video channel fmt = %d", __func__,
+ dim.enc_format);
+ LOGV("%s: video channel resolution = %d X %d", __func__,
+ dim.video_width, dim.video_height);
+
+ rc = cam_config_set_parm(cameraId, MM_CAMERA_PARM_CH_IMAGE_FMT, &fmt);
+
+ LOGV("%s: video MM_CAMERA_PARM_CH_IMAGE_FMT rc = %d\n", __func__, rc);
+ if(MM_CAMERA_OK != rc) {
+ LOGE("%s:set video channel format err=%d\n", __func__, rc);
+ LOGE("%s: X", __func__);
+ ret= BAD_VALUE;
+ }
+ }
+
+ } /*MM_CAMERA_CH_VIDEO*/
+#endif
+
+ int rc = MM_CAMERA_OK;
+ status_t ret = NO_ERROR;
+ mm_camera_op_mode_type_t op_mode=MM_CAMERA_OP_MODE_VIDEO;
+ int i;
+
+ LOGV("QCameraStream::initChannel : E");
+ if(MM_CAMERA_CH_PREVIEW_MASK & ch_type_mask){
+ rc = cam_ops_ch_acquire(cameraId, MM_CAMERA_CH_PREVIEW);
+ LOGV("%s:ch_acquire MM_CAMERA_CH_PREVIEW, rc=%d\n",__func__, rc);
+ if(MM_CAMERA_OK != rc) {
+ LOGE("%s: preview channel acquir error =%d\n", __func__, rc);
+ LOGE("%s: X", __func__);
+ return BAD_VALUE;
+ }
+ /*Callback register*/
+ /* register a notify into the mmmm_camera_t object*/
+ /* ret = cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_PREVIEW,
+ preview_notify_cb,
+ this);
+ LOGV("Buf notify MM_CAMERA_CH_PREVIEW, rc=%d\n",rc);*/
+ }else if(MM_CAMERA_CH_VIDEO_MASK & ch_type_mask){
+ rc = cam_ops_ch_acquire(cameraId, MM_CAMERA_CH_VIDEO);
+ LOGV("%s:ch_acquire MM_CAMERA_CH_VIDEO, rc=%d\n",__func__, rc);
+ if(MM_CAMERA_OK != rc) {
+ LOGE("%s: preview channel acquir error =%d\n", __func__, rc);
+ LOGE("%s: X", __func__);
+ return BAD_VALUE;
+ }
+ /*Callback register*/
+ /* register a notify into the mmmm_camera_t object*/
+ /*ret = cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_VIDEO,
+ record_notify_cb,
+ this);
+ LOGV("Buf notify MM_CAMERA_CH_VIDEO, rc=%d\n",rc);*/
+ }
+
+ ret = (MM_CAMERA_OK==rc)? NO_ERROR : BAD_VALUE;
+ LOGV("%s: X, ret = %d", __func__, ret);
+ return ret;
+}
+
+status_t QCameraStream::deinitChannel(int cameraId,
+ mm_camera_channel_type_t ch_type)
+{
+
+ int rc = MM_CAMERA_OK;
+
+ LOGV("%s: E, channel = %d\n", __func__, ch_type);
+
+ if (MM_CAMERA_CH_MAX <= ch_type) {
+ LOGE("%s: X: BAD_VALUE", __func__);
+ return BAD_VALUE;
+ }
+
+ cam_ops_ch_release(cameraId, ch_type);
+
+ LOGV("%s: X, channel = %d\n", __func__, ch_type);
+ return NO_ERROR;
+}
+
+status_t QCameraStream::setMode(int enable) {
+ LOGE("%s :myMode %x ", __func__, myMode);
+ if (enable) {
+ myMode = (camera_mode_t)(myMode | CAMERA_ZSL_MODE);
+ } else {
+ myMode = (camera_mode_t)(myMode & ~CAMERA_ZSL_MODE);
+ }
+ return NO_ERROR;
+}
+
+status_t QCameraStream::setFormat(uint8_t ch_type_mask)
+{
+ int rc = MM_CAMERA_OK;
+ status_t ret = NO_ERROR;
+ int width = 0; /* width of channel */
+ 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));
+ rc = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION, &dim);
+ if (MM_CAMERA_OK != rc) {
+ LOGE("%s: error - can't get camera dimension!", __func__);
+ 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;
+ 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){
+ fmt.ch_type = MM_CAMERA_CH_VIDEO;
+ fmt.video.video.fmt = CAMERA_YUV_420_NV21; //dim.enc_format;
+ fmt.video.video.dim.width = dim.video_width;
+ fmt.video.video.dim.height = dim.video_height;
+ }/*else if(MM_CAMERA_CH_SNAPSHOT_MASK & ch_type_mask){
+ if(mHalCamCtrl->isRawSnapshot()) {
+ fmt.ch_type = MM_CAMERA_CH_RAW;
+ fmt.def.fmt = CAMERA_BAYER_SBGGR10;
+ fmt.def.dim.width = dim.raw_picture_width;
+ fmt.def.dim.height = dim.raw_picture_height;
+ }else{
+ //Jpeg???
+ fmt.ch_type = MM_CAMERA_CH_SNAPSHOT;
+ fmt.snapshot.main.fmt = dim.main_img_format;
+ fmt.snapshot.main.dim.width = dim.picture_width;
+ fmt.snapshot.main.dim.height = dim.picture_height;
+
+ fmt.snapshot.thumbnail.fmt = dim.thumb_format;
+ fmt.snapshot.thumbnail.dim.width = dim.ui_thumbnail_width;
+ fmt.snapshot.thumbnail.dim.height = dim.ui_thumbnail_height;
+ }
+ }*/
+
+ rc = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_CH_IMAGE_FMT, &fmt);
+ LOGV("%s: Stream MM_CAMERA_PARM_CH_IMAGE_FMT rc = %d\n", __func__, rc);
+ if(MM_CAMERA_OK != rc) {
+ LOGE("%s:set stream channel format err=%d\n", __func__, ret);
+ LOGE("%s: X", __func__);
+ ret = BAD_VALUE;
+ }
+ LOGE("%s: X",__func__);
+ return ret;
+}
+
+QCameraStream::QCameraStream (){
+ mInit = false;
+ mActive = false;
+ /* memset*/
+ memset(&mCrop, 0, sizeof(mm_camera_ch_crop_t));
+}
+
+QCameraStream::QCameraStream (int cameraId, camera_mode_t mode)
+ :mCameraId(cameraId),
+ myMode(mode)
+{
+ mInit = false;
+ mActive = false;
+
+ /* memset*/
+ memset(&mCrop, 0, sizeof(mm_camera_ch_crop_t));
+}
+
+QCameraStream::~QCameraStream () {;}
+
+
+status_t QCameraStream::init() {
+ return NO_ERROR;
+}
+
+status_t QCameraStream::start() {
+ return NO_ERROR;
+}
+
+void QCameraStream::stop() {
+ return;
+}
+
+void QCameraStream::release() {
+ return;
+}
+
+void QCameraStream::setHALCameraControl(QCameraHardwareInterface* ctrl) {
+
+ /* provide a frame data user,
+ for the queue monitor thread to call the busy queue is not empty*/
+ mHalCamCtrl = ctrl;
+}
+
+}; // namespace android
diff --git a/camera/QCamera/HAL/test/Android.mk b/camera/QCamera/HAL/test/Android.mk
new file mode 100755
index 0000000..d3f5a12
--- /dev/null
+++ b/camera/QCamera/HAL/test/Android.mk
@@ -0,0 +1 @@
+
diff --git a/camera/QCamera/HAL/wrapper/QualcommCamera.cpp b/camera/QCamera/HAL/wrapper/QualcommCamera.cpp
new file mode 100755
index 0000000..2875e27
--- /dev/null
+++ b/camera/QCamera/HAL/wrapper/QualcommCamera.cpp
@@ -0,0 +1,506 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+ *
+ */
+/*#error uncomment this for compiler test!*/
+
+//#define LOG_NDEBUG 0
+#define LOG_NIDEBUG 0
+#define LOG_TAG "QualcommCamera"
+#include <utils/Log.h>
+#include <utils/threads.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include "QCameraHAL.h"
+/* include QCamera Hardware Interface Header*/
+#include "QualcommCamera.h"
+//#include "QualcommCameraHardware.h"
+//#include <camera/CameraHardwareInterface.h>
+
+extern "C" {
+#include <sys/time.h>
+}
+
+/* HAL function implementation goes here*/
+
+/**
+ * The functions need to be provided by the camera HAL.
+ *
+ * If getNumberOfCameras() returns N, the valid cameraId for getCameraInfo()
+ * and openCameraHardware() is 0 to N-1.
+ */
+
+static hw_module_methods_t camera_module_methods = {
+ open: camera_device_open,
+};
+
+static hw_module_t camera_common = {
+ tag: HARDWARE_MODULE_TAG,
+ version_major: 0,
+ version_minor: 01,
+ id: CAMERA_HARDWARE_MODULE_ID,
+ name: "Qcamera",
+ author:"Qcom",
+ methods: &camera_module_methods,
+ dso: NULL,
+ //reserved[0]: 0,
+};
+camera_module_t HAL_MODULE_INFO_SYM = {
+ common: camera_common,
+ get_number_of_cameras: get_number_of_cameras,
+ get_camera_info: get_camera_info,
+};
+
+camera_device_ops_t camera_ops = {
+ set_preview_window: android::set_preview_window,
+ set_callbacks: android::set_CallBacks,
+ enable_msg_type: android::enable_msg_type,
+ disable_msg_type: android::disable_msg_type,
+ msg_type_enabled: android::msg_type_enabled,
+
+ start_preview: android::start_preview,
+ stop_preview: android::stop_preview,
+ preview_enabled: android::preview_enabled,
+ store_meta_data_in_buffers: android::store_meta_data_in_buffers,
+
+ start_recording: android::start_recording,
+ stop_recording: android::stop_recording,
+ recording_enabled: android::recording_enabled,
+ release_recording_frame: android::release_recording_frame,
+
+ auto_focus: android::auto_focus,
+ cancel_auto_focus: android::cancel_auto_focus,
+
+ take_picture: android::take_picture,
+ cancel_picture: android::cancel_picture,
+
+ set_parameters: android::set_parameters,
+ get_parameters: android::get_parameters,
+ put_parameters: android::put_parameters,
+ send_command: android::send_command,
+
+ release: android::release,
+ dump: android::dump,
+};
+
+namespace android {
+
+typedef struct {
+ camera_device hw_dev;
+ //sp<CameraHardwareInterface> hardware;
+ QCameraHardwareInterface *hardware;
+ int camera_released;
+ int cameraId;
+ //CameraParameters parameters;
+} camera_hardware_t;
+
+typedef struct {
+ camera_memory_t mem;
+ int32_t msgType;
+ sp<IMemory> dataPtr;
+ void* user;
+ unsigned int index;
+} q_cam_memory_t;
+
+QCameraHardwareInterface *util_get_Hal_obj( struct camera_device * device)
+{
+ QCameraHardwareInterface *hardware = NULL;
+ if(device && device->priv){
+ camera_hardware_t *camHal = (camera_hardware_t *)device->priv;
+ hardware = camHal->hardware;
+ }
+ return hardware;
+}
+
+#if 0 //mzhu
+CameraParameters* util_get_HAL_parameter( struct camera_device * device)
+{
+ CameraParameters *param = NULL;
+ if(device && device->priv){
+ camera_hardware_t *camHal = (camera_hardware_t *)device->priv;
+ param = &(camHal->parameters);
+ }
+ return param;
+}
+#endif //mzhu
+
+extern "C" int get_number_of_cameras()
+{
+ /* try to query every time we get the call!*/
+
+ LOGE("Q%s: E", __func__);
+ return android::HAL_getNumberOfCameras( );
+}
+
+extern "C" int get_camera_info(int camera_id, struct camera_info *info)
+{
+ int rc = -1;
+ LOGE("Q%s: E", __func__);
+ if(info) {
+ struct CameraInfo camInfo;
+ memset(&camInfo, -1, sizeof (struct CameraInfo));
+ android::HAL_getCameraInfo(camera_id, &camInfo);
+ if (camInfo.facing >= 0) {
+ rc = 0;
+ info->facing = camInfo.facing;
+ info->orientation = camInfo.orientation;
+ }
+ }
+ LOGV("Q%s: X", __func__);
+ return rc;
+}
+
+
+/* HAL should return NULL if it fails to open camera hardware. */
+extern "C" int camera_device_open(
+ const struct hw_module_t* module, const char* id,
+ struct hw_device_t** hw_device)
+{
+ int rc = -1;
+ int mode = 0; // TODO: need to add 3d/2d mode, etc
+ camera_device *device = NULL;
+ if(module && id && hw_device) {
+ int cameraId = atoi(id);
+
+ if (!strcmp(module->name, camera_common.name)) {
+ camera_hardware_t *camHal =
+ (camera_hardware_t *) malloc(sizeof (camera_hardware_t));
+ if(!camHal) {
+ *hw_device = NULL;
+ LOGE("%s: end in no mem", __func__);
+ return rc;
+ }
+ /* we have the camera_hardware obj malloced */
+ memset(camHal, 0, sizeof (camera_hardware_t));
+ camHal->hardware = new QCameraHardwareInterface(cameraId, mode); //HAL_openCameraHardware(cameraId);
+ if (camHal->hardware && camHal->hardware->isCameraReady()) {
+ camHal->cameraId = cameraId;
+ device = &camHal->hw_dev;
+ device->common.close = close_camera_device;
+ device->ops = &camera_ops;
+ device->priv = (void *)camHal;
+ rc = 0;
+ } else {
+ if (camHal->hardware) {
+ delete camHal->hardware;
+ camHal->hardware = NULL;
+ }
+ free(camHal);
+ device = NULL;
+ }
+ }
+ }
+ /* pass actual hw_device ptr to framework. This amkes that we actally be use memberof() macro */
+ *hw_device = (hw_device_t*)&device->common;
+ LOGE("%s: end rc %d", __func__, rc);
+ return rc;
+}
+
+extern "C" int close_camera_device( hw_device_t *hw_dev)
+{
+ LOGE("Q%s: device =%p E", __func__, hw_dev);
+ int rc = -1;
+ camera_device_t *device = (camera_device_t *)hw_dev;
+
+ if(device) {
+ camera_hardware_t *camHal = (camera_hardware_t *)device->priv;
+ if(camHal ) {
+ QCameraHardwareInterface *hardware = util_get_Hal_obj( device);
+ if(!camHal->camera_released) {
+ if(hardware != NULL) {
+ hardware->release( );
+ }
+ }
+ if(hardware != NULL)
+ delete hardware;
+ free(camHal);
+ }
+ rc = 0;
+ }
+ return rc;
+}
+
+
+int set_preview_window(struct camera_device * device,
+ struct preview_stream_ops *window)
+{
+ int rc = -1;
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+
+ if(hardware != NULL) {
+ rc = hardware->setPreviewWindow(window);
+ }
+ return rc;
+}
+
+void set_CallBacks(struct camera_device * device,
+ camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void *user)
+{
+ LOGE("Q%s: E", __func__);
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ hardware->setCallbacks(notify_cb,data_cb, data_cb_timestamp, get_memory, user);
+ }
+}
+
+void enable_msg_type(struct camera_device * device, int32_t msg_type)
+{
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ hardware->enableMsgType(msg_type);
+ }
+}
+
+void disable_msg_type(struct camera_device * device, int32_t msg_type)
+{
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ LOGE("Q%s: E", __func__);
+ if(hardware != NULL){
+ hardware->disableMsgType(msg_type);
+ }
+}
+
+int msg_type_enabled(struct camera_device * device, int32_t msg_type)
+{
+ LOGE("Q%s: E", __func__);
+ int rc = -1;
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ rc = hardware->msgTypeEnabled(msg_type);
+ }
+ return rc;
+}
+
+int start_preview(struct camera_device * device)
+{
+ LOGE("Q%s: E", __func__);
+ int rc = -1;
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ rc = hardware->startPreview( );
+ }
+ LOGE("Q%s: X", __func__);
+ return rc;
+}
+
+void stop_preview(struct camera_device * device)
+{
+ LOGE("Q%s: E", __func__);
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ hardware->stopPreview( );
+ }
+}
+
+int preview_enabled(struct camera_device * device)
+{
+ LOGE("Q%s: E", __func__);
+ int rc = -1;
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ rc = hardware->previewEnabled( );
+ }
+ return rc;
+}
+
+int store_meta_data_in_buffers(struct camera_device * device, int enable)
+{
+ LOGE("Q%s: E", __func__);
+ int rc = -1;
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ rc = hardware->storeMetaDataInBuffers(enable);
+ }
+ return rc;
+}
+
+int start_recording(struct camera_device * device)
+{
+ LOGE("Q%s: E", __func__);
+ int rc = -1;
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ rc = hardware->startRecording( );
+ }
+ return rc;
+}
+
+void stop_recording(struct camera_device * device)
+{
+ LOGE("Q%s: E", __func__);
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ hardware->stopRecording( );
+ }
+}
+
+int recording_enabled(struct camera_device * device)
+{
+ LOGE("Q%s: E", __func__);
+ int rc = -1;
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ rc = hardware->recordingEnabled( );
+ }
+ return rc;
+}
+
+void release_recording_frame(struct camera_device * device,
+ const void *opaque)
+{
+ LOGV("Q%s: E", __func__);
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ hardware->releaseRecordingFrame(opaque);
+ }
+}
+
+int auto_focus(struct camera_device * device)
+{
+ LOGE("Q%s: E", __func__);
+ int rc = -1;
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ rc = hardware->autoFocus( );
+ }
+ return rc;
+}
+
+int cancel_auto_focus(struct camera_device * device)
+{
+ LOGE("Q%s: E", __func__);
+ int rc = -1;
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ rc = hardware->cancelAutoFocus( );
+ }
+ return rc;
+}
+
+int take_picture(struct camera_device * device)
+{
+ LOGE("Q%s: E", __func__);
+ int rc = -1;
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ rc = hardware->takePicture( );
+ }
+ return rc;
+}
+
+int cancel_picture(struct camera_device * device)
+
+{
+ LOGE("Q%s: E", __func__);
+ int rc = -1;
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ rc = hardware->cancelPicture( );
+ }
+ return rc;
+}
+
+int set_parameters(struct camera_device * device, const char *parms)
+
+{
+ LOGE("Q%s: E", __func__);
+ int rc = -1;
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL && parms){
+ //CameraParameters param;// = util_get_HAL_parameter(device);
+ //String8 str = String8(parms);
+
+ //param.unflatten(str);
+ rc = hardware->setParameters(parms);
+ //rc = 0;
+ }
+ return rc;
+}
+
+char* get_parameters(struct camera_device * device)
+{
+ LOGE("Q%s: E", __func__);
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ char *parms = NULL;
+ hardware->getParameters(&parms);
+ return parms;
+ }
+ return NULL;
+}
+
+void put_parameters(struct camera_device * device, char *parm)
+
+{
+ LOGE("Q%s: E", __func__);
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ hardware->putParameters(parm);
+ }
+}
+
+int send_command(struct camera_device * device,
+ int32_t cmd, int32_t arg1, int32_t arg2)
+{
+ LOGE("Q%s: E", __func__);
+ int rc = -1;
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ rc = hardware->sendCommand( cmd, arg1, arg2);
+ }
+ return rc;
+}
+
+void release(struct camera_device * device)
+{
+ LOGE("Q%s: E", __func__);
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ camera_hardware_t *camHal = (camera_hardware_t *)device->priv;
+ hardware->release( );
+ camHal->camera_released = true;
+ }
+}
+
+int dump(struct camera_device * device, int fd)
+{
+ LOGE("Q%s: E", __func__);
+ int rc = -1;
+ QCameraHardwareInterface *hardware = util_get_Hal_obj(device);
+ if(hardware != NULL){
+ rc = hardware->dump( fd );
+ //rc = 0;
+ }
+ return rc;
+}
+
+}; // namespace android
diff --git a/camera/QCamera/HAL/wrapper/QualcommCamera.h b/camera/QCamera/HAL/wrapper/QualcommCamera.h
new file mode 100755
index 0000000..81dbf93
--- /dev/null
+++ b/camera/QCamera/HAL/wrapper/QualcommCamera.h
@@ -0,0 +1,108 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 ANDROID_HARDWARE_QUALCOMM_CAMERA_H
+#define ANDROID_HARDWARE_QUALCOMM_CAMERA_H
+
+
+#include "QCameraHWI.h"
+
+extern "C" {
+/*#include <hardware/camera.h>*/
+
+ int get_number_of_cameras();
+ int get_camera_info(int camera_id, struct camera_info *info);
+
+ int camera_device_open(const struct hw_module_t* module, const char* id,
+ struct hw_device_t** device);
+
+ hw_device_t * open_camera_device(int cameraId);
+
+ int close_camera_device( hw_device_t *);
+
+namespace android {
+ int set_preview_window(struct camera_device *,
+ struct preview_stream_ops *window);
+ void set_CallBacks(struct camera_device *,
+ camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void *user);
+
+ void enable_msg_type(struct camera_device *, int32_t msg_type);
+
+ void disable_msg_type(struct camera_device *, int32_t msg_type);
+ int msg_type_enabled(struct camera_device *, int32_t msg_type);
+
+ int start_preview(struct camera_device *);
+
+ void stop_preview(struct camera_device *);
+
+ int preview_enabled(struct camera_device *);
+ int store_meta_data_in_buffers(struct camera_device *, int enable);
+
+ int start_recording(struct camera_device *);
+
+ void stop_recording(struct camera_device *);
+
+ int recording_enabled(struct camera_device *);
+
+ void release_recording_frame(struct camera_device *,
+ const void *opaque);
+
+ int auto_focus(struct camera_device *);
+
+ int cancel_auto_focus(struct camera_device *);
+
+ int take_picture(struct camera_device *);
+
+ int cancel_picture(struct camera_device *);
+
+ int set_parameters(struct camera_device *, const char *parms);
+
+ char* get_parameters(struct camera_device *);
+
+ void put_parameters(struct camera_device *, char *);
+
+ int send_command(struct camera_device *,
+ int32_t cmd, int32_t arg1, int32_t arg2);
+
+ void release(struct camera_device *);
+
+ int dump(struct camera_device *, int fd);
+
+
+
+}; // namespace android
+
+} //extern "C"
+
+#endif
+
diff --git a/camera/QCamera/stack/Android.mk b/camera/QCamera/stack/Android.mk
new file mode 100755
index 0000000..c7307a7
--- /dev/null
+++ b/camera/QCamera/stack/Android.mk
@@ -0,0 +1,4 @@
+LOCAL_PATH:= $(call my-dir)
+include $(LOCAL_PATH)/mm-camera-interface/Android.mk
+include $(LOCAL_PATH)/mm-camera-test/Android.mk
+#include $(LOCAL_PATH)/mm-jpeg-interface/Android.mk
diff --git a/camera/QCamera/stack/common/cam_list.h b/camera/QCamera/stack/common/cam_list.h
new file mode 100755
index 0000000..87ad6cf
--- /dev/null
+++ b/camera/QCamera/stack/common/cam_list.h
@@ -0,0 +1,74 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+/* This file is a slave copy from /vendor/qcom/propreitary/mm-cammera/common,
+ * Please do not modify it directly here. */
+
+#ifndef __CAMLIST_H
+#define __CAMLIST_H
+
+#include <stddef.h>
+
+#define member_of(ptr, type, member) ({ \
+ const typeof(((type *)0)->member) *__mptr = (ptr); \
+ (type *)((char *)__mptr - offsetof(type,member));})
+
+struct cam_list {
+ struct cam_list *next, *prev;
+};
+
+static inline void cam_list_init(struct cam_list *ptr)
+{
+ ptr->next = ptr;
+ ptr->prev = ptr;
+}
+
+static inline void cam_list_add_tail_node(struct cam_list *item,
+ struct cam_list *head)
+{
+ struct cam_list *prev = head->prev;
+
+ head->prev = item;
+ item->next = head;
+ item->prev = prev;
+ prev->next = item;
+}
+
+static inline void cam_list_del_node(struct cam_list *ptr)
+{
+ struct cam_list *prev = ptr->prev;
+ struct cam_list *next = ptr->next;
+
+ next->prev = ptr->prev;
+ prev->next = ptr->next;
+ ptr->next = ptr;
+ ptr->prev = ptr;
+}
+
+#endif /* __CAMLIST_H */
diff --git a/camera/QCamera/stack/mm-camera-interface/Android.mk b/camera/QCamera/stack/mm-camera-interface/Android.mk
new file mode 100755
index 0000000..1464eff
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-interface/Android.mk
@@ -0,0 +1,61 @@
+#ifeq ($(call is-board-platform,msm8960),true)
+OLD_LOCAL_PATH := $(LOCAL_PATH)
+LOCAL_PATH := $(call my-dir)
+USE_BIONIC_HEADER:=true
+
+include $(CLEAR_VARS)
+
+MM_CAM_FILES := \
+ src/mm_camera_interface.c \
+ src/mm_camera_stream.c \
+ src/mm_camera_channel.c \
+ src/mm_camera.c \
+ src/mm_camera_thread.c \
+ src/mm_camera_data.c \
+ src/mm_camera_sock.c \
+ src/mm_camera_helper.c
+
+LOCAL_CFLAGS += -D_ANDROID_
+LOCAL_COPY_HEADERS_TO := mm-camera-interface_badger
+LOCAL_COPY_HEADERS := inc/mm_camera_interface.h
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/inc \
+ $(LOCAL_PATH)/../common \
+ $(LOCAL_PATH)/../../../ \
+ $(TARGET_OUT_HEADERS)/mm-camera \
+ $(TARGET_OUT_HEADERS)/mm-camera/common
+
+ifneq ($(strip $(USE_BIONIC_HEADER)),true)
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include/media
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+endif
+
+# (BEGIN) Need to remove later once dependency on jpeg removed
+LOCAL_C_INCLUDES += \
+ $(TARGET_OUT_HEADERS)/mm-still \
+ $(TARGET_OUT_HEADERS)/mm-still/jpeg \
+ $(TARGET_OUT_HEADERS)/mm-core/omxcore \
+ $(TARGET_OUT_HEADERS)/mm-still/mm-omx
+# (END) Need to remove later once dependency on jpeg removed
+
+LOCAL_C_INCLUDES+= hardware/qcom/media/mm-core/inc
+LOCAL_CFLAGS += -include bionic/libc/kernel/common/linux/socket.h
+LOCAL_CFLAGS += -include bionic/libc/kernel/common/linux/un.h
+
+LOCAL_SRC_FILES := $(MM_CAM_FILES)
+
+LOCAL_MODULE := libmmcamera_interface_badger
+LOCAL_PRELINK_MODULE := false
+LOCAL_SHARED_LIBRARIES := libdl libcutils liblog
+LOCAL_MODULE_TAGS := optional
+
+# (BEGIN) Need to remove later once dependency on jpeg removed
+# LOCAL_SHARED_LIBRARIES += libmmjpeg_interface
+# (END) Need to remove later once dependency on jpeg removed
+
+include $(BUILD_SHARED_LIBRARY)
+
+LOCAL_PATH := $(OLD_LOCAL_PATH)
+#endif
diff --git a/camera/QCamera/stack/mm-camera-interface/inc/mm_camera.h b/camera/QCamera/stack/mm-camera-interface/inc/mm_camera.h
new file mode 100755
index 0000000..1a46acf
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-interface/inc/mm_camera.h
@@ -0,0 +1,619 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 __MM_CAMERA_H__
+#define __MM_CAMERA_H__
+
+#include "mm_camera_interface.h"
+
+/**********************************************************************************
+* Data structure declare
+***********************************************************************************/
+/* num of streams allowed in a channel obj */
+#define MM_CAMEAR_STRAEM_NUM_MAX 8
+/* num of channels allowed in a camera obj */
+#define MM_CAMERA_CHANNEL_MAX 1
+/* num of callbacks allowed for an event type */
+#define MM_CAMERA_EVT_ENTRY_MAX 4
+/* num of data callbacks allowed in a stream obj */
+#define MM_CAMERA_STREAM_BUF_CB_MAX 4
+/* num of data poll threads allowed in a channel obj */
+#define MM_CAMERA_CHANNEL_POLL_THREAD_MAX 1
+
+#define MM_CAMERA_DEV_NAME_LEN 32
+#define MM_CAMERA_DEV_OPEN_TRIES 2
+#define MM_CAMERA_DEV_OPEN_RETRY_SLEEP 20
+
+struct mm_channel;
+struct mm_stream;
+struct mm_camera_obj;
+
+/* common use */
+typedef struct {
+ struct cam_list list;
+ void* data;
+} mm_camera_q_node_t;
+
+typedef struct {
+ mm_camera_q_node_t head; /* dummy head */
+ uint32_t size;
+ pthread_mutex_t lock;
+} mm_camera_queue_t;
+
+typedef enum
+{
+ MM_CAMERA_ASYNC_CMD_TYPE_STOP, /* async stop */
+ MM_CAMERA_ASYNC_CMD_TYPE_MAX
+} mm_camera_async_cmd_type_t;
+
+typedef struct {
+ struct mm_channel* ch_obj;
+ uint8_t num_streams;
+ uint32_t stream_ids[MM_CAMEAR_STRAEM_NUM_MAX];
+} mm_camera_async_stop_cmd_t;
+
+typedef struct {
+ mm_camera_async_cmd_type_t cmd_type;
+ union {
+ mm_camera_async_stop_cmd_t stop_cmd;
+ } u;
+} mm_camera_async_cmd_t;
+
+typedef enum
+{
+ MM_CAMERA_CMD_TYPE_DATA_CB, /* dataB CMD */
+ MM_CAMERA_CMD_TYPE_EVT_CB, /* evtCB CMD */
+ MM_CAMERA_CMD_TYPE_ASYNC_CB, /* asyncCB CMD */
+ MM_CAMERA_CMD_TYPE_EXIT, /* EXIT */
+ MM_CAMERA_CMD_TYPE_REQ_DATA_CB,/* request data */
+ MM_CAMERA_CMD_TYPE_MAX
+} mm_camera_cmdcb_type_t;
+
+typedef struct {
+ uint32_t stream_id;
+ uint32_t frame_idx;
+ uint8_t need_pp; /* flag if pp needed on this buf */
+ mm_camera_buf_def_t *buf; /* ref to buf */
+} mm_camera_buf_info_t;
+
+typedef struct {
+ mm_camera_cmdcb_type_t cmd_type;
+ union {
+ mm_camera_buf_info_t buf; /* frame buf if dataCB */
+ mm_camera_event_t evt; /* evt if evtCB */
+ mm_camera_async_cmd_t async; /* async cmd */
+ } u;
+} mm_camera_cmdcb_t;
+
+typedef void (*mm_camera_cmd_cb_t)(mm_camera_cmdcb_t * cmd_cb, void* user_data);
+
+typedef struct {
+ mm_camera_queue_t cmd_queue; /* cmd queue (queuing dataCB, asyncCB, or exitCMD) */
+ pthread_t cmd_pid; /* cmd thread ID */
+ sem_t cmd_sem; /* semaphore for cmd thread */
+ mm_camera_cmd_cb_t cb; /* cb for cmd */
+ void* user_data; /* user_data for cb */
+} mm_camera_cmd_thread_t;
+
+typedef enum {
+ MM_CAMERA_POLL_TYPE_EVT,
+ MM_CAMERA_POLL_TYPE_CH,
+ MM_CAMERA_POLL_TYPE_MAX
+} mm_camera_poll_thread_type_t;
+
+/* function ptr defined for poll notify CB,
+ * registered at poll thread with poll fd */
+typedef void (*mm_camera_poll_notify_t)(void *user_data);
+
+typedef struct {
+ int32_t fd;
+ mm_camera_poll_notify_t notify_cb;
+ uint32_t handler;
+ void* user_data;
+} mm_camera_poll_entry_t;
+
+typedef struct {
+ mm_camera_poll_thread_type_t poll_type;
+ /* array to store poll fd and cb info
+ * for MM_CAMERA_POLL_TYPE_EVT, only index 0 is valid;
+ * for MM_CAMERA_POLL_TYPE_CH, depends on valid stream fd */
+ mm_camera_poll_entry_t poll_entries[MM_CAMEAR_STRAEM_NUM_MAX];
+ int32_t pfds[2];
+ pthread_t pid;
+ int32_t state;
+ int timeoutms;
+ uint32_t cmd;
+ struct pollfd poll_fds[MM_CAMEAR_STRAEM_NUM_MAX+1];
+ uint8_t num_fds;
+ pthread_mutex_t mutex;
+ pthread_cond_t cond_v;
+ int32_t status;
+ //void *my_obj;
+} mm_camera_poll_thread_t;
+
+/* mm_stream */
+typedef enum {
+ MM_STREAM_STATE_NOTUSED = 0, /* not used */
+ MM_STREAM_STATE_INITED, /* inited */
+ MM_STREAM_STATE_ACQUIRED, /* acquired, fd opened */
+ MM_STREAM_STATE_CFG, /* fmt & dim configured */
+ MM_STREAM_STATE_BUFFED, /* buf allocated */
+ MM_STREAM_STATE_REG, /* buf regged, stream off */
+ MM_STREAM_STATE_ACTIVE_STREAM_ON, /* active with stream on */
+ MM_STREAM_STATE_ACTIVE_STREAM_OFF, /* active with stream off */
+ MM_STREAM_STATE_MAX
+} mm_stream_state_type_t;
+
+typedef enum {
+ MM_STREAM_EVT_ACQUIRE,
+ MM_STREAM_EVT_RELEASE,
+ MM_STREAM_EVT_SET_FMT,
+ MM_STREAM_EVT_GET_BUF,
+ MM_STREAM_EVT_PUT_BUF,
+ MM_STREAM_EVT_REG_BUF,
+ MM_STREAM_EVT_UNREG_BUF,
+ MM_STREAM_EVT_START,
+ MM_STREAM_EVT_STOP,
+ MM_STREAM_EVT_QBUF,
+ MM_STREAM_EVT_SET_PARM,
+ MM_STREAM_EVT_GET_PARM,
+ MM_STREAM_EVT_MAX
+} mm_stream_evt_type_t;
+
+typedef struct {
+ mm_camera_buf_notify_t cb;
+ void *user_data;
+ /* cb_count = -1: infinite
+ * cb_count > 0: register only for required times */
+ int8_t cb_count;
+} mm_stream_data_cb_t;
+
+typedef struct {
+ /* buf reference count */
+ uint8_t buf_refcnt;
+
+ /* This flag is to indicate if after allocation,
+ * the corresponding buf needs to qbuf into kernel
+ * (e.g. for preview usecase, display needs to hold two bufs,
+ * so no need to qbuf these two bufs initially) */
+ uint8_t initial_reg_flag;
+
+ /* indicate if buf is in kernel(1) or client(0) */
+ uint8_t in_kernel;
+} mm_stream_buf_status_t;
+
+typedef struct mm_stream {
+ uint32_t my_hdl;
+ uint32_t inst_hdl;
+ int32_t fd;
+ mm_stream_state_type_t state;
+
+ /* ext_image_mode used as id for stream obj */
+ uint32_t ext_image_mode;
+
+ /* sensor index used */
+ uint32_t sensor_idx;
+
+ mm_camera_image_fmt_t fmt;
+
+ mm_camera_cmd_thread_t cmd_thread;
+
+ /* dataCB registered on this stream obj */
+ pthread_mutex_t cb_lock; /* cb lock to protect buf_cb */
+ mm_stream_data_cb_t buf_cb[MM_CAMERA_STREAM_BUF_CB_MAX];
+
+ /* stream buffer management */
+ pthread_mutex_t buf_lock;
+ uint8_t buf_num; /* num of buffers allocated */
+ mm_camera_buf_def_t* buf; /* ptr to buf array */
+ mm_stream_buf_status_t* buf_status; /* ptr to buf status array */
+
+ /* reference to parent channel_obj */
+ struct mm_channel* ch_obj;
+
+ uint8_t is_bundled; /* flag if stream is bundled */
+ uint8_t is_pp_needed; /* flag if need to do post processing, set when streamon */
+ uint8_t is_local_buf; /* flag if buf is local copy, no need to qbuf to kernel */
+ uint8_t hal_requested_num_bufs;
+ uint8_t need_stream_on; /* flag if stream need streamon when start */
+
+ mm_camera_frame_len_offset frame_offset; /*Stream buffer offset information*/
+} mm_stream_t;
+
+/* mm_channel */
+typedef enum {
+ MM_CHANNEL_STATE_NOTUSED = 0, /* not used */
+ MM_CHANNEL_STATE_STOPPED, /* stopped */
+ MM_CHANNEL_STATE_ACTIVE, /* active, at least one stream active */
+ MM_CHANNEL_STATE_PAUSED, /* paused */
+ MM_CHANNEL_STATE_MAX
+} mm_channel_state_type_t;
+
+typedef enum {
+ MM_CHANNEL_EVT_ADD_STREAM,
+ MM_CHANNEL_EVT_DEL_STREAM,
+ MM_CHANNEL_EVT_START_STREAM,
+ MM_CHANNEL_EVT_STOP_STREAM,
+ MM_CHANNEL_EVT_TEARDOWN_STREAM,
+ MM_CHANNEL_EVT_CONFIG_STREAM,
+ MM_CHANNEL_EVT_PAUSE,
+ MM_CHANNEL_EVT_RESUME,
+ MM_CHANNEL_EVT_INIT_BUNDLE,
+ MM_CHANNEL_EVT_DESTROY_BUNDLE,
+ MM_CHANNEL_EVT_REQUEST_SUPER_BUF,
+ MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF,
+ MM_CHANNEL_EVT_START_FOCUS,
+ MM_CHANNEL_EVT_ABORT_FOCUS,
+ MM_CHANNEL_EVT_PREPARE_SNAPSHOT,
+ MM_CHANNEL_EVT_SET_STREAM_PARM,
+ MM_CHANNEL_EVT_GET_STREAM_PARM,
+ MM_CHANNEL_EVT_DELETE,
+ MM_CHANNEL_EVT_MAX
+} mm_channel_evt_type_t;
+
+typedef struct {
+ mm_camera_buf_notify_t buf_cb;
+ void *user_data;
+ uint32_t ext_image_mode;
+ uint32_t sensor_idx;
+} mm_evt_paylod_add_stream_t;
+
+typedef struct {
+ uint32_t stream_id;
+ mm_camera_stream_config_t *config;
+} mm_evt_paylod_config_stream_t;
+
+typedef struct {
+ mm_camera_stream_parm_t parm_type;
+ void *value;
+} mm_evt_paylod_stream_parm_t;
+
+typedef struct {
+ mm_camera_buf_notify_t super_frame_notify_cb;
+ void *user_data;
+ mm_camera_bundle_attr_t *attr;
+ uint8_t num_streams;
+ uint32_t *stream_ids;
+} mm_evt_payload_bundle_stream_t;
+
+typedef struct {
+ uint8_t num_streams;
+ uint32_t *stream_ids;
+} mm_evt_payload_start_stream_t;
+
+typedef struct {
+ uint8_t num_streams;
+ uint32_t *stream_ids;
+} mm_evt_payload_stop_stream_t;
+
+typedef struct {
+ uint32_t sensor_idx;
+ uint32_t focus_mode;
+} mm_evt_payload_start_focus_t;
+
+typedef struct {
+ uint8_t num_of_bufs;
+ mm_camera_buf_info_t super_buf[MM_CAMEAR_MAX_STRAEM_BUNDLE];
+ uint8_t matched;
+} mm_channel_queue_node_t;
+
+typedef struct {
+ mm_camera_queue_t que;
+ uint8_t num_streams;
+ /* container for bundled stream handlers */
+ uint32_t bundled_streams[MM_CAMEAR_MAX_STRAEM_BUNDLE];
+ mm_camera_bundle_attr_t attr;
+ uint32_t expected_frame_id;
+ uint32_t match_cnt;
+} mm_channel_queue_t;
+
+typedef struct {
+ /* queue to store bundled super buffers */
+ mm_channel_queue_t superbuf_queue;
+ mm_camera_buf_notify_t super_buf_notify_cb;
+ void *user_data;
+} mm_channel_bundle_t;
+
+typedef struct mm_channel {
+ uint32_t my_hdl;
+ mm_channel_state_type_t state;
+ pthread_mutex_t ch_lock; /* channel lock */
+
+ /* stream bundle info in the channel */
+ mm_channel_bundle_t bundle;
+
+ /* num of pending suferbuffers */
+ uint32_t pending_cnt;
+ uint32_t pending_pp_cnt; /*pending cnt for post processing frames */
+
+ /* cmd thread for superbuffer dataCB and async stop*/
+ mm_camera_cmd_thread_t cmd_thread;
+
+ /* data poll thread
+ * currently one data poll thread per channel
+ * could extended to support one data poll thread per stream in the channel */
+ mm_camera_poll_thread_t poll_thread[MM_CAMERA_CHANNEL_POLL_THREAD_MAX];
+
+ /* container for all streams in channel
+ * stream is indexed by ext_image_mode */
+ mm_stream_t streams[MM_CAMEAR_STRAEM_NUM_MAX];
+
+ /* reference to parent cam_obj */
+ struct mm_camera_obj* cam_obj;
+} mm_channel_t;
+
+/* struct to store information about pp cookie*/
+typedef struct {
+ uint32_t cam_hdl;
+ uint32_t ch_hdl;
+ uint32_t stream_hdl;
+ mm_channel_queue_node_t* super_buf;
+} mm_channel_pp_info_t;
+
+/* mm_camera */
+typedef struct {
+ mm_camera_event_notify_t evt_cb;
+ void *user_data;
+} mm_camera_evt_entry_t;
+
+typedef struct {
+ mm_camera_evt_entry_t evt[MM_CAMERA_EVT_ENTRY_MAX];
+ /* reg_count <=0: infinite
+ * reg_count > 0: register only for required times */
+ int reg_count;
+} mm_camera_evt_obj_t;
+
+typedef struct mm_camera_obj {
+ uint32_t my_hdl;
+ int ref_count;
+ int32_t ctrl_fd;
+ int32_t ds_fd; /* domain socket fd */
+ cam_prop_t properties;
+ mm_camera_2nd_sensor_t second_sensor; /*second sensor info */
+ pthread_mutex_t cam_lock;
+ pthread_mutex_t cb_lock; /* lock for evt cb */
+ mm_channel_t ch[MM_CAMERA_CHANNEL_MAX];
+ mm_camera_evt_obj_t evt[MM_CAMERA_EVT_TYPE_MAX];
+ uint32_t evt_type_mask;
+ mm_camear_mem_vtbl_t *mem_vtbl; /* vtable for memory management */
+ mm_camera_poll_thread_t evt_poll_thread; /* evt poll thread */
+ mm_camera_cmd_thread_t evt_thread; /* thread for evt CB */
+ mm_camera_cmd_thread_t async_cmd_thread; /* thread for async cmd */
+ mm_camera_vtbl_t vtbl;
+
+ /* some local variables */
+ uint32_t snap_burst_num_by_user;
+ camera_mode_t current_mode;
+ uint8_t need_pp;
+ uint32_t op_mode;
+ cam_ctrl_dimension_t dim;
+} mm_camera_obj_t;
+
+typedef struct {
+ mm_camera_info_t camera[MSM_MAX_CAMERA_SENSORS];
+ int8_t num_cam;
+ char video_dev_name[MSM_MAX_CAMERA_SENSORS][MM_CAMERA_DEV_NAME_LEN];
+ mm_camera_obj_t *cam_obj[MSM_MAX_CAMERA_SENSORS];
+} mm_camera_ctrl_t;
+
+/**********************************************************************************
+* external function declare
+***********************************************************************************/
+/* utility functions */
+/* set int32_t value */
+extern int32_t mm_camera_util_s_ctrl(int32_t fd,
+ uint32_t id,
+ int32_t value);
+
+extern int32_t mm_camera_util_private_s_ctrl( int32_t fd,
+ uint32_t id, void* value);
+
+/* get int32_t value */
+extern int32_t mm_camera_util_g_ctrl(int32_t fd,
+ uint32_t id,int32_t *value);
+
+/* send msg throught domain socket for fd mapping */
+extern int32_t mm_camera_util_sendmsg(mm_camera_obj_t *my_obj,
+ void *msg,
+ uint32_t buf_size,
+ int sendfd);
+
+/* mm-camera */
+extern int32_t mm_camera_open(mm_camera_obj_t *my_obj);
+extern int32_t mm_camera_close(mm_camera_obj_t *my_obj);
+extern uint8_t mm_camera_is_event_supported(mm_camera_obj_t *my_obj,
+ mm_camera_event_type_t evt_type);
+extern int32_t mm_camera_register_event_notify(mm_camera_obj_t *my_obj,
+ mm_camera_event_notify_t evt_cb,
+ void * user_data,
+ mm_camera_event_type_t evt_type);
+extern int32_t mm_camera_qbuf(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ mm_camera_buf_def_t *buf);
+extern mm_camera_2nd_sensor_t * mm_camera_query_2nd_sensor_info(mm_camera_obj_t *my_obj);
+extern int32_t mm_camera_sync(mm_camera_obj_t *my_obj);
+extern int32_t mm_camera_is_parm_supported(mm_camera_obj_t *my_obj,
+ mm_camera_parm_type_t parm_type,
+ uint8_t *support_set_parm,
+ uint8_t *support_get_parm);
+extern int32_t mm_camera_set_parm(mm_camera_obj_t *my_obj,
+ mm_camera_parm_type_t parm_type,
+ void* p_value);
+extern int32_t mm_camera_get_parm(mm_camera_obj_t *my_obj,
+ mm_camera_parm_type_t parm_type,
+ void* p_value);
+extern uint32_t mm_camera_add_channel(mm_camera_obj_t *my_obj);
+extern void mm_camera_del_channel(mm_camera_obj_t *my_obj,
+ uint32_t ch_id);
+extern uint32_t mm_camera_add_stream(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ mm_camera_buf_notify_t buf_cb, void *user_data,
+ uint32_t ext_image_mode, uint32_t sensor_idx);
+extern int32_t mm_camera_del_stream(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint32_t stream_id);
+extern int32_t mm_camera_config_stream(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint32_t stream_id,
+ mm_camera_stream_config_t *config);
+extern int32_t mm_camera_bundle_streams(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ mm_camera_buf_notify_t super_frame_notify_cb,
+ void *user_data,
+ mm_camera_bundle_attr_t *attr,
+ uint8_t num_streams,
+ uint32_t *stream_ids);
+extern int32_t mm_camera_destroy_bundle(mm_camera_obj_t *my_obj,
+ uint32_t ch_id);
+extern int32_t mm_camera_start_streams(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint8_t num_streams,
+ uint32_t *stream_ids);
+extern int32_t mm_camera_stop_streams(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint8_t num_streams,
+ uint32_t *stream_ids);
+extern int32_t mm_camera_async_teardown_streams(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint8_t num_streams,
+ uint32_t *stream_ids);
+extern int32_t mm_camera_request_super_buf(mm_camera_obj_t *my_obj,
+ uint32_t ch_id);
+extern int32_t mm_camera_cancel_super_buf_request(mm_camera_obj_t *my_obj,
+ uint32_t ch_id);
+extern int32_t mm_camera_start_focus(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint32_t sensor_idx,
+ uint32_t focus_mode);
+extern int32_t mm_camera_abort_focus(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint32_t sensor_idx);
+extern int32_t mm_camera_prepare_snapshot(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint32_t sensor_idx);
+extern int32_t mm_camera_set_stream_parm(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint32_t s_id,
+ mm_camera_stream_parm_t parm_type,
+ void* p_value);
+
+extern int32_t mm_camera_get_stream_parm(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint32_t s_id,
+ mm_camera_stream_parm_t parm_type,
+ void* p_value);
+
+extern int32_t mm_camera_register_event_notify_internal(
+ mm_camera_obj_t *my_obj,
+ mm_camera_event_notify_t evt_cb,
+ void * user_data,
+ mm_camera_event_type_t evt_type);
+extern int32_t mm_camera_map_buf(mm_camera_obj_t *my_obj,
+ int ext_mode,
+ int idx,
+ int fd,
+ uint32_t size);
+extern int32_t mm_camera_unmap_buf(mm_camera_obj_t *my_obj,
+ int ext_mode,
+ int idx);
+extern int32_t mm_camera_send_ch_event(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint32_t stream_id,
+ mm_camera_ch_event_type_t evt);
+
+
+/* mm_channel */
+extern int32_t mm_channel_fsm_fn(mm_channel_t *my_obj,
+ mm_channel_evt_type_t evt,
+ void * in_val,
+ void * out_val);
+
+/* qbuf is a special case that not going through state machine.
+ * This is to avoid deadlock when trying to aquire ch_lock,
+ * from the context of dataCB, but async stop is holding ch_lock */
+extern int32_t mm_channel_qbuf(mm_channel_t *my_obj,
+ mm_camera_buf_def_t *buf);
+
+/* Allow other stream to register dataCB at certain stream.
+ * This is for use case of video sized live snapshot,
+ * because snapshot stream need register one time CB at video stream.
+ * ext_image_mode and sensor_idx are used to identify the destinate stream
+ * to be register with dataCB. */
+extern int32_t mm_channel_reg_stream_cb(mm_channel_t *my_obj,
+ mm_stream_data_cb_t *cb,
+ uint32_t ext_image_mode,
+ uint32_t sensor_idx);
+
+/* mm_stream */
+extern int32_t mm_stream_fsm_fn(mm_stream_t *my_obj,
+ mm_stream_evt_type_t evt,
+ void * in_val,
+ void * out_val);
+/* Allow other stream to register dataCB at certain stream.
+ * This is for use case of video sized live snapshot,
+ * because snapshot stream need register one time CB at video stream.
+ * ext_image_mode and sensor_idx are used to identify the destinate stream
+ * to be register with dataCB. */
+extern int32_t mm_stream_reg_buf_cb(mm_stream_t *my_obj,
+ mm_stream_data_cb_t *val);
+
+/* utiltity fucntion declared in mm-camera-inteface2.c
+ * and need be used by mm-camera and below*/
+uint32_t mm_camera_util_generate_handler(uint8_t index);
+const char * mm_camera_util_get_dev_name(uint32_t cam_handler);
+uint8_t mm_camera_util_get_index_by_handler(uint32_t handler);
+
+/* queue functions */
+extern int32_t mm_camera_queue_init(mm_camera_queue_t* queue);
+extern int32_t mm_camera_queue_enq(mm_camera_queue_t* queue, void* node);
+extern void* mm_camera_queue_deq(mm_camera_queue_t* queue);
+extern int32_t mm_camera_queue_deinit(mm_camera_queue_t* queue);
+extern int32_t mm_camera_queue_flush(mm_camera_queue_t* queue);
+
+/* poll/cmd thread functions */
+extern int32_t mm_camera_poll_thread_launch(
+ mm_camera_poll_thread_t * poll_cb,
+ mm_camera_poll_thread_type_t poll_type);
+extern int32_t mm_camera_poll_thread_release(mm_camera_poll_thread_t *poll_cb);
+extern int32_t mm_camera_poll_thread_add_poll_fd(
+ mm_camera_poll_thread_t * poll_cb,
+ uint32_t handler,
+ int32_t fd,
+ mm_camera_poll_notify_t nofity_cb,
+ void *userdata);
+extern int32_t mm_camera_poll_thread_del_poll_fd(
+ mm_camera_poll_thread_t * poll_cb,
+ uint32_t handler);
+extern int32_t mm_camera_cmd_thread_launch(
+ mm_camera_cmd_thread_t * cmd_thread,
+ mm_camera_cmd_cb_t cb,
+ void* user_data);
+extern int32_t mm_camera_cmd_thread_release(mm_camera_cmd_thread_t * cmd_thread);
+
+#endif /* __MM_CAMERA_H__ */
diff --git a/camera/QCamera/stack/mm-camera-interface/inc/mm_camera_dbg.h b/camera/QCamera/stack/mm-camera-interface/inc/mm_camera_dbg.h
new file mode 100755
index 0000000..f701658
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-interface/inc/mm_camera_dbg.h
@@ -0,0 +1,70 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 __MM_CAMERA_DBG_H__
+#define __MM_CAMERA_DBG_H__
+
+#define LOG_DEBUG 1
+
+#ifndef LOG_DEBUG
+ #ifdef _ANDROID_
+ #undef LOG_NIDEBUG
+ #undef LOG_TAG
+ #define LOG_NIDEBUG 0
+ #define LOG_TAG "mm-libcamera2"
+ #include <utils/Log.h>
+ #else
+ #include <stdio.h>
+ #define ALOGE CDBG
+ #endif
+ #undef CDBG
+ #define CDBG(fmt, args...) do{}while(0)
+#else
+ #ifdef _ANDROID_
+ #undef LOG_NIDEBUG
+ #undef LOG_TAG
+ #define LOG_NIDEBUG 0
+ #define LOG_TAG "mm-libcamera2"
+ #include <utils/Log.h>
+ #define CDBG(fmt, args...) ALOGE(fmt, ##args)
+ #else
+ #include <stdio.h>
+ #define CDBG(fmt, args...) fprintf(stderr, fmt, ##args)
+ #define ALOGE(fmt, args...) fprintf(stderr, fmt, ##args)
+ #endif
+#endif
+
+#ifdef _ANDROID_
+ #define CDBG_HIGH(fmt, args...) ALOGE(fmt, ##args)
+ #define CDBG_ERROR(fmt, args...) ALOGE(fmt, ##args)
+#else
+ #define CDBG_HIGH(fmt, args...) fprintf(stderr, fmt, ##args)
+ #define CDBG_ERROR(fmt, args...) fprintf(stderr, fmt, ##args)
+#endif
+#endif /* __MM_CAMERA_DBG_H__ */
diff --git a/camera/QCamera/stack/mm-camera-interface/inc/mm_camera_interface.h b/camera/QCamera/stack/mm-camera-interface/inc/mm_camera_interface.h
new file mode 100755
index 0000000..53d9b03
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-interface/inc/mm_camera_interface.h
@@ -0,0 +1,343 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 __MM_CAMERA_INTERFACE_H__
+#define __MM_CAMERA_INTERFACE_H__
+#include <linux/ion.h>
+#include <camera.h>
+#include <QCamera_Intf.h>
+#include "cam_list.h"
+
+#define MM_CAMERA_MAX_NUM_FRAMES 16
+#define MM_CAMEAR_MAX_STRAEM_BUNDLE 4
+#define MM_CAMERA_MAX_2ND_SENSORS 4
+
+typedef enum {
+ MM_CAMERA_WHITE_BALANCE_AUTO,
+ MM_CAMERA_WHITE_BALANCE_OFF,
+ MM_CAMERA_WHITE_BALANCE_DAYLIGHT,
+ MM_CAMERA_WHITE_BALANCE_INCANDESCENT,
+ MM_CAMERA_WHITE_BALANCE_FLUORESCENT,
+ MM_CAMERA_WHITE_BALANCE_CLOUDY,
+ MM_CAMERA_WHITE_BALANCE_MAX
+} mm_camera_white_balance_mode_type_t;
+
+typedef enum {
+ MM_CAMERA_STREAM_OFFSET,
+ MM_CAMERA_STREAM_CID,
+ MM_CAMERA_STREAM_CROP
+}mm_camera_stream_parm_t;
+
+typedef struct {
+ int32_t width;
+ int32_t height;
+} mm_camera_dimension_t;
+
+typedef struct{
+ uint32_t tbl_size;
+ struct camera_size_type *sizes_tbl;
+}default_sizes_tbl_t;
+
+typedef struct {
+ int32_t left;
+ int32_t top;
+ int32_t width;
+ int32_t height;
+} mm_camera_rect_t;
+
+/* TBD: meta header needs to move to msm_camear.h */
+typedef enum {
+ /* no meta data header used */
+ MM_CAMEAR_META_DATA_TYPE_DEF,
+ /* has focus flag, exposure idx,
+ * flash flag, etc. TBD */
+ MM_CAMEAR_META_DATA_TYPE_BRACKETING,
+ MM_CAMEAR_META_DATA_TYPE_MAX,
+} mm_camera_meta_header_t;
+
+typedef struct {
+ cam_format_t fmt;
+ mm_camera_meta_header_t meta_header;
+ uint32_t width;
+ uint32_t height;
+ uint8_t rotation;
+} mm_camera_image_fmt_t;
+
+typedef struct {
+ /* image format */
+ mm_camera_image_fmt_t fmt;
+
+ /* num of buffers needed */
+ uint8_t num_of_bufs;
+
+ /* flag to indicate if this stream need stream on */
+ uint8_t need_stream_on;
+} mm_camera_stream_config_t;
+
+typedef struct {
+ uint8_t name[32];
+ int32_t min_value;
+ int32_t max_value;
+ int32_t step;
+ int32_t default_value;
+} mm_camera_ctrl_cap_sharpness_t;
+
+typedef struct {
+ int16_t *zoom_ratio_tbl;
+ int32_t size;
+} mm_camera_zoom_tbl_t;
+
+typedef enum {
+ /* ZSL use case: get burst of frames */
+ MM_CAMERA_SUPER_BUF_NOTIFY_BURST = 0,
+ /* get continuous frames: when the super buf is
+ * ready dispatch it to HAL */
+ MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS,
+ MM_CAMERA_SUPER_BUF_NOTIFY_MAX
+}mm_camera_super_buf_notify_mode_t;
+
+typedef enum {
+ /* save the frame. No matter focused or not */
+ MM_CAMERA_SUPER_BUF_PRIORITY_NORMAL = 0,
+ /* only queue the frame that is focused. Will enable
+ * meta data header to carry focus info*/
+ MM_CAMERA_SUPER_BUF_PRIORITY_FOCUS,
+ /* after shutter, only queue matched exposure index */
+ MM_CAMERA_SUPER_BUF_PRIORITY_EXPOSURE_BRACKETING,
+ MM_CAMERA_SUPER_BUF_PRIORITY_MAX
+}mm_camera_super_buf_priority_t;
+
+typedef struct {
+ mm_camera_super_buf_notify_mode_t notify_mode;
+ /* queue depth. Only for burst mode */
+ uint8_t water_mark;
+ /* look back how many frames from last buf */
+ uint8_t look_back;
+ /* after send first frame to HAL, how many frames
+ * needing to be skipped for next delivery? */
+ uint8_t post_frame_skip;
+ /* save matched priority frames only */
+ mm_camera_super_buf_priority_t priority;
+ /* in burst mode, how many super
+ * bufs for each shutter press? */
+ uint8_t burst_num;
+} mm_camera_bundle_attr_t;
+
+typedef struct {
+ uint8_t camera_id; /* camera id */
+ camera_info_t camera_info; /* postion, mount_angle, etc. */
+ enum sensor_type_t main_sensor_type; /* BAYER, YUV, JPEG_SOC, etc. */
+ char *video_dev_name; /* device node name, e.g. /dev/video1 */
+} mm_camera_info_t;
+
+typedef struct {
+ uint8_t cid;
+ uint8_t dt;
+}stream_cid_t;
+
+/* the stats struct will need rework after
+ * defining the stats buf sharing logic */
+typedef struct {
+ int type;
+ uint32_t length;
+ void *value;
+} mm_camera_stats_t;
+
+typedef struct {
+ uint32_t stream_id; /* stream handler */
+ int8_t buf_idx; /* buf idx within the stream bufs */
+
+ struct timespec ts; /* time stamp, to be filled when DQBUF*/
+ uint32_t frame_idx; /* frame sequence num, to be filled when DQBUF */
+
+ int8_t num_planes; /* num of planes, to be filled during mem allocation */
+ struct v4l2_plane planes[VIDEO_MAX_PLANES]; /* plane info, to be filled during mem allocation*/
+ int fd; /* fd of the frame, to be filled during mem allocation */
+ void* buffer; /* ptr to real frame buffer, to be filled during mem allocation */
+ uint32_t frame_len; /* len of the whole frame, to be filled during mem allocation */
+} mm_camera_buf_def_t;
+
+typedef struct {
+ uint32_t camera_handle;
+ uint32_t ch_id;
+ uint8_t num_bufs;
+ mm_camera_buf_def_t* bufs[MM_CAMEAR_MAX_STRAEM_BUNDLE];
+} mm_camera_super_buf_t;
+
+typedef void (*mm_camera_event_notify_t)(uint32_t camera_handle,
+ mm_camera_event_t *evt,
+ void *user_data);
+
+typedef void (*mm_camera_buf_notify_t) (mm_camera_super_buf_t *bufs,
+ void *user_data);
+typedef cam_frame_len_offset_t mm_camera_frame_len_offset;
+
+typedef struct {
+ void *user_data;
+ int32_t (*get_buf) (uint32_t camera_handle,
+ uint32_t ch_id, uint32_t stream_id,
+ void *user_data,
+ mm_camera_frame_len_offset *frame_offset_info,
+ uint8_t num_bufs,
+ uint8_t *initial_reg_flag,
+ mm_camera_buf_def_t *bufs);
+ int32_t (*put_buf) (uint32_t camera_handle,
+ uint32_t ch_id, uint32_t stream_id,
+ void *user_data, uint8_t num_bufs,
+ mm_camera_buf_def_t *bufs);
+} mm_camear_mem_vtbl_t;
+
+typedef struct {
+ uint8_t num_2nd_sensors;
+ uint8_t sensor_idxs[MM_CAMERA_MAX_2ND_SENSORS];
+} mm_camera_2nd_sensor_t;
+
+typedef struct {
+ int32_t (*sync) (uint32_t camera_handle);
+ uint8_t (*is_event_supported) (uint32_t camera_handle,
+ mm_camera_event_type_t evt_type);
+ int32_t (*register_event_notify) (uint32_t camera_handle,
+ mm_camera_event_notify_t evt_cb,
+ void * user_data,
+ mm_camera_event_type_t evt_type);
+ int32_t (*qbuf) (uint32_t camera_handle, uint32_t ch_id,
+ mm_camera_buf_def_t *buf);
+ void (*camera_close) (uint32_t camera_handle);
+ /* Only fo supporting advanced 2nd sensors. If no secondary sensor needed
+ * HAL can ignore this function */
+ mm_camera_2nd_sensor_t * (*query_2nd_sensor_info) (uint32_t camera_handle);
+ /* if the parm is supported: TRUE - support, FALSE - not support */
+ int32_t (*is_parm_supported) (uint32_t camera_handle,
+ mm_camera_parm_type_t parm_type,
+ uint8_t *support_set_parm,
+ uint8_t *support_get_parm);
+ /* set a parmÂ’s current value */
+ int32_t (*set_parm) (uint32_t camera_handle,
+ mm_camera_parm_type_t parm_type,
+ void* p_value);
+ /* get a parmÂ’s current value */
+ int32_t (*get_parm) (uint32_t camera_handle,
+ mm_camera_parm_type_t parm_type,
+ void* p_value);
+ /* ch_id returned, zero is invalid ch_id */
+ uint32_t (*ch_acquire) (uint32_t camera_handle);
+ /* relaese channel */
+ void (*ch_release) (uint32_t camera_handle, uint32_t ch_id);
+ /* return stream_id. zero is invalid stream_id
+ * default set to preview: ext_image_mode = 0
+ * default set to primary sensor: sensor_idx = 0
+ * value of ext_image_mode is defined in msm_camera.h
+ */
+ uint32_t (*add_stream) (uint32_t camera_handle, uint32_t ch_id,
+ mm_camera_buf_notify_t buf_cb, void *user_data,
+ uint32_t ext_image_mode, uint32_t sensor_idx);
+ /* delete stream */
+ int32_t (*del_stream) (uint32_t camera_handle, uint32_t ch_id,
+ uint32_t stream_id);
+ /* set straem format This will trigger getting bufs from HAL */
+ int32_t (*config_stream) (uint32_t camera_handle, uint32_t ch_id,
+ uint32_t stream_id,
+ mm_camera_stream_config_t *config);
+ /* setup super buf bundle for ZSL */
+ int32_t (*init_stream_bundle) (uint32_t camera_handle, uint32_t ch_id,
+ mm_camera_buf_notify_t super_frame_notify_cb,
+ void *user_data, mm_camera_bundle_attr_t *attr,
+ uint8_t num_streams, uint32_t *stream_ids);
+ /* remove the super buf bundle */
+ int32_t (*destroy_stream_bundle) (uint32_t camera_handle, uint32_t ch_id);
+ /* start streaming */
+ int32_t (*start_streams) (uint32_t camera_handle, uint32_t ch_id,
+ uint8_t num_streams, uint32_t *stream_ids);
+ /* stop streaming */
+ int32_t (*stop_streams) (uint32_t camera_handle, uint32_t ch_id,
+ uint8_t num_streams, uint32_t *stream_ids);
+ /* tear down streams asyncly */
+ int32_t (*async_teardown_streams) (uint32_t camera_handle, uint32_t ch_id,
+ uint8_t num_streams, uint32_t *stream_ids);
+ /* get super bufs. for burst mode only */
+ int32_t (*request_super_buf) (uint32_t camera_handle, uint32_t ch_id);
+ /* abort the super buf dispatching. for burst mode only */
+ int32_t (*cancel_super_buf_request) (uint32_t camera_handle,
+ uint32_t ch_id);
+ /* start focus: by default sensor_idx=0 */
+ int32_t (*start_focus) (uint32_t camera_handle,
+ uint32_t ch_id,
+ uint32_t sensor_idx,
+ uint32_t focus_mode);
+ /* abort focus: by default sensor_idx=0 */
+ int32_t (*abort_focus) (uint32_t camera_handle,
+ uint32_t ch_id,
+ uint32_t sensor_idx);
+ /* prepare hardware will settle aec and flash.
+ * by default sensor_idx=0 */
+ int32_t (*prepare_snapshot) (uint32_t camera_handle,
+ uint32_t ch_id,
+ uint32_t sensor_idx);
+ /* set a parmÂ’s current value */
+ int32_t (*set_stream_parm) (uint32_t camera_handle,
+ uint32_t ch_id,
+ uint32_t s_id,
+ mm_camera_stream_parm_t parm_type,
+ void* p_value);
+ /* get a parmÂ’s current value */
+ int32_t (*get_stream_parm) (uint32_t camera_handle,
+ uint32_t ch_id,
+ uint32_t s_id,
+ mm_camera_stream_parm_t parm_type,
+ void* p_value);
+} mm_camera_ops_t;
+
+typedef struct {
+ uint32_t camera_handle; /* camera object handle */
+ mm_camera_info_t *camera_info; /* reference pointer of camear info */
+ mm_camera_ops_t *ops; /* API call table */
+} mm_camera_vtbl_t;
+
+mm_camera_info_t * camera_query(uint8_t *num_cameras);
+mm_camera_vtbl_t * camera_open(uint8_t camera_idx,
+ mm_camear_mem_vtbl_t *mem_vtbl);
+
+typedef enum {
+ MM_CAMERA_PREVIEW,
+ MM_CAMERA_VIDEO,
+ MM_CAMERA_SNAPSHOT_MAIN,
+ MM_CAMERA_SNAPSHOT_THUMBNAIL,
+ MM_CAMERA_SNAPSHOT_RAW,
+ MM_CAMERA_RDI
+}mm_camera_img_mode;
+
+/* may remove later */
+typedef enum {
+ MM_CAMERA_OP_MODE_NOTUSED,
+ MM_CAMERA_OP_MODE_CAPTURE,
+ MM_CAMERA_OP_MODE_VIDEO,
+ MM_CAMERA_OP_MODE_ZSL,
+ MM_CAMERA_OP_MODE_MAX
+} mm_camera_op_mode_type_t;
+#endif /*__MM_CAMERA_INTERFACE_H__*/
diff --git a/camera/QCamera/stack/mm-camera-interface/inc/mm_camera_sock.h b/camera/QCamera/stack/mm-camera-interface/inc/mm_camera_sock.h
new file mode 100755
index 0000000..9519754
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-interface/inc/mm_camera_sock.h
@@ -0,0 +1,57 @@
+/*
+Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 __MM_CAMERA_SOCKET_H__
+#define __MM_CAMERA_SOCKET_H__
+
+#include <inttypes.h>
+
+typedef enum {
+ MM_CAMERA_SOCK_TYPE_UDP,
+ MM_CAMERA_SOCK_TYPE_TCP,
+} mm_camera_sock_type_t;
+
+int mm_camera_socket_create(int cam_id, mm_camera_sock_type_t sock_type);
+
+int mm_camera_socket_sendmsg(
+ int fd,
+ void *msg,
+ uint32_t buf_size,
+ int sendfd);
+
+int mm_camera_socket_recvmsg(
+ int fd,
+ void *msg,
+ uint32_t buf_size,
+ int *rcvdfd);
+
+void mm_camera_socket_close(int fd);
+
+#endif /*__MM_CAMERA_SOCKET_H__*/
+
diff --git a/camera/QCamera/stack/mm-camera-interface/src/mm_camera.c b/camera/QCamera/stack/mm-camera-interface/src/mm_camera.c
new file mode 100755
index 0000000..826b5dd
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-interface/src/mm_camera.c
@@ -0,0 +1,1774 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <semaphore.h>
+
+#include "mm_camera_dbg.h"
+#include "mm_camera_sock.h"
+#include "mm_camera_interface.h"
+#include "mm_camera.h"
+
+#define SET_PARM_BIT32(parm, parm_arr) \
+ (parm_arr[parm/32] |= (1<<(parm%32)))
+
+#define GET_PARM_BIT32(parm, parm_arr) \
+ ((parm_arr[parm/32]>>(parm%32))& 0x1)
+
+/* internal function declare */
+int32_t mm_camera_send_native_ctrl_cmd(mm_camera_obj_t * my_obj,
+ cam_ctrl_type type,
+ uint32_t length,
+ void *value);
+int32_t mm_camera_send_native_ctrl_timeout_cmd(mm_camera_obj_t * my_obj,
+ cam_ctrl_type type,
+ uint32_t length,
+ void *value,
+ int timeout);
+int mm_camera_evt_sub(mm_camera_obj_t * my_obj,
+ mm_camera_event_type_t evt_type,
+ int reg_count);
+int32_t mm_camera_set_general_parm(mm_camera_obj_t * my_obj,
+ mm_camera_parm_type_t parm_type,
+ void* p_value);
+int32_t mm_camera_enqueue_evt(mm_camera_obj_t *my_obj,
+ mm_camera_event_t *event);
+extern int32_t mm_channel_init(mm_channel_t *my_obj);
+
+mm_channel_t * mm_camera_util_get_channel_by_handler(
+ mm_camera_obj_t * cam_obj,
+ uint32_t handler)
+{
+ int i;
+ mm_channel_t *ch_obj = NULL;
+ uint8_t ch_idx = mm_camera_util_get_index_by_handler(handler);
+
+ for(i = 0; i < MM_CAMERA_CHANNEL_MAX; i++) {
+ if (handler == cam_obj->ch[i].my_hdl) {
+ ch_obj = &cam_obj->ch[i];
+ break;
+ }
+ }
+ return ch_obj;
+}
+
+static void mm_camera_dispatch_app_event(mm_camera_cmdcb_t *cmd_cb,
+ void* user_data)
+{
+ int i;
+ mm_camera_event_type_t evt_type = cmd_cb->u.evt.event_type;
+ mm_camera_event_t *event = &cmd_cb->u.evt;
+ mm_camera_obj_t * my_obj = (mm_camera_obj_t *)user_data;
+ if (NULL != my_obj) {
+ if (evt_type < MM_CAMERA_EVT_TYPE_MAX) {
+ pthread_mutex_lock(&my_obj->cb_lock);
+ for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
+ if(my_obj->evt[evt_type].evt[i].evt_cb) {
+ my_obj->evt[evt_type].evt[i].evt_cb(
+ my_obj->my_hdl,
+ event,
+ my_obj->evt[evt_type].evt[i].user_data);
+ }
+ }
+ pthread_mutex_unlock(&my_obj->cb_lock);
+ }
+ }
+}
+
+static void mm_camera_handle_async_cmd(mm_camera_cmdcb_t *cmd_cb,
+ void* user_data)
+{
+ int i;
+ mm_camera_async_cmd_t *async_cmd = &cmd_cb->u.async;
+ mm_camera_obj_t * my_obj = NULL;
+ mm_evt_payload_stop_stream_t payload;
+
+ my_obj = (mm_camera_obj_t *)user_data;
+ if (NULL != my_obj) {
+ if (MM_CAMERA_ASYNC_CMD_TYPE_STOP == async_cmd->cmd_type) {
+ memset(&payload, 0, sizeof(mm_evt_payload_stop_stream_t));
+ payload.num_streams = async_cmd->u.stop_cmd.num_streams;
+ payload.stream_ids = async_cmd->u.stop_cmd.stream_ids;
+ mm_channel_fsm_fn(async_cmd->u.stop_cmd.ch_obj,
+ MM_CHANNEL_EVT_TEARDOWN_STREAM,
+ (void*)&payload,
+ NULL);
+ }
+ }
+}
+
+static void mm_camera_event_notify(void* user_data)
+{
+ struct v4l2_event ev;
+ int rc;
+ mm_camera_event_t *evt = NULL;
+ mm_camera_cmdcb_t *node = NULL;
+
+ mm_camera_obj_t *my_obj = (mm_camera_obj_t*)user_data;
+ if (NULL != my_obj) {
+ /* read evt */
+ memset(&ev, 0, sizeof(ev));
+ rc = ioctl(my_obj->ctrl_fd, VIDIOC_DQEVENT, &ev);
+ evt = (mm_camera_event_t *)ev.u.data;
+
+ if (rc >= 0) {
+ if(ev.type == V4L2_EVENT_PRIVATE_START+MSM_CAM_APP_NOTIFY_ERROR_EVENT) {
+ evt->event_type = MM_CAMERA_EVT_TYPE_CTRL;
+ evt->e.ctrl.evt = MM_CAMERA_CTRL_EVT_ERROR;
+ }
+
+ mm_camera_enqueue_evt(my_obj, evt);
+ }
+ }
+}
+
+int32_t mm_camera_enqueue_evt(mm_camera_obj_t *my_obj,
+ mm_camera_event_t *event)
+{
+ int32_t rc = 0;
+ mm_camera_cmdcb_t *node = NULL;
+
+ node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
+ if (NULL != node) {
+ memset(node, 0, sizeof(mm_camera_cmdcb_t));
+ node->cmd_type = MM_CAMERA_CMD_TYPE_EVT_CB;
+ memcpy(&node->u.evt, event, sizeof(mm_camera_event_t));
+
+ /* enqueue to evt cmd thread */
+ mm_camera_queue_enq(&(my_obj->evt_thread.cmd_queue), node);
+ /* wake up evt cmd thread */
+ sem_post(&(my_obj->evt_thread.cmd_sem));
+ } else {
+ CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
+ rc = -1;
+ }
+
+ return rc;
+}
+
+/* send local CH evt to HAL
+ * may not needed since we have return val for each channel/stream operation */
+int32_t mm_camera_send_ch_event(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint32_t stream_id,
+ mm_camera_ch_event_type_t evt)
+{
+ int rc = 0;
+ mm_camera_event_t event;
+ event.event_type = MM_CAMERA_EVT_TYPE_CH;
+ event.e.ch.evt = evt;
+ /* TODO: need to change the ch evt struct to include ch_id and stream_id. */
+ event.e.ch.ch = stream_id;
+ CDBG("%s: stream on event, type=0x%x, ch=%d, evt=%d",
+ __func__, event.event_type, event.e.ch.ch, event.e.ch.evt);
+ rc = mm_camera_enqueue_evt(my_obj, &event);
+ return rc;
+}
+
+int32_t mm_camera_open(mm_camera_obj_t *my_obj)
+{
+ char dev_name[MM_CAMERA_DEV_NAME_LEN];
+ int32_t rc = 0;
+ int8_t n_try=MM_CAMERA_DEV_OPEN_TRIES;
+ uint8_t sleep_msec=MM_CAMERA_DEV_OPEN_RETRY_SLEEP;
+ uint8_t i;
+ uint8_t cam_idx = mm_camera_util_get_index_by_handler(my_obj->my_hdl);
+
+ CDBG("%s: begin\n", __func__);
+
+ snprintf(dev_name, sizeof(dev_name), "/dev/%s",
+ mm_camera_util_get_dev_name(my_obj->my_hdl));
+
+ do{
+ n_try--;
+ my_obj->ctrl_fd = open(dev_name, O_RDWR | O_NONBLOCK);
+ CDBG("%s: ctrl_fd = %d, errno == %d", __func__, my_obj->ctrl_fd, errno);
+ if((my_obj->ctrl_fd > 0) || (errno != EIO) || (n_try <= 0 )) {
+ CDBG_ERROR("%s: opened, break out while loop", __func__);
+ break;
+ }
+ CDBG("%s:failed with I/O error retrying after %d milli-seconds",
+ __func__,sleep_msec);
+ usleep(sleep_msec*1000);
+ }while(n_try>0);
+
+ if (my_obj->ctrl_fd <= 0) {
+ CDBG_ERROR("%s: cannot open control fd of '%s' (%s)\n",
+ __func__, dev_name, strerror(errno));
+ rc = -1;
+ goto on_error;
+ }
+
+ /* open domain socket*/
+ n_try=MM_CAMERA_DEV_OPEN_TRIES;
+ do{
+ n_try--;
+ my_obj->ds_fd = mm_camera_socket_create(cam_idx, MM_CAMERA_SOCK_TYPE_UDP);
+ CDBG("%s: ds_fd = %d, errno = %d", __func__, my_obj->ds_fd, errno);
+ if((my_obj->ds_fd > 0) || (n_try <= 0 )) {
+ CDBG("%s: opened, break out while loop", __func__);
+ break;
+ }
+ CDBG("%s:failed with I/O error retrying after %d milli-seconds",
+ __func__,sleep_msec);
+ usleep(sleep_msec*1000);
+ }while(n_try>0);
+
+ if (my_obj->ds_fd <= 0) {
+ CDBG_ERROR("%s: cannot open domain socket fd of '%s'(%s)\n",
+ __func__, dev_name, strerror(errno));
+ rc = -1;
+ goto on_error;
+ }
+
+ /* set ctrl_fd to be the mem_mapping fd */
+ rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
+ MSM_V4L2_PID_MMAP_INST, 0);
+ if (rc < 0) {
+ CDBG_ERROR("error: ioctl VIDIOC_S_CTRL MSM_V4L2_PID_MMAP_INST failed: %s\n",
+ strerror(errno));
+ goto on_error;
+ }
+
+ /* set geo mode to 2D by default */
+ my_obj->current_mode = CAMERA_MODE_2D;
+
+ /* TODO:
+ * We need to remove function call once we consider sync as saperate API
+ * and HAL needs to call after each camera open call.
+ */
+ mm_camera_sync(my_obj);
+
+ pthread_mutex_init(&my_obj->cb_lock, NULL);
+
+ CDBG("%s : Launch async cmd Thread in Cam Open",__func__);
+ mm_camera_cmd_thread_launch(&my_obj->async_cmd_thread,
+ mm_camera_handle_async_cmd,
+ (void *)my_obj);
+
+ CDBG("%s : Launch evt Thread in Cam Open",__func__);
+ mm_camera_cmd_thread_launch(&my_obj->evt_thread,
+ mm_camera_dispatch_app_event,
+ (void *)my_obj);
+
+ /* launch event poll thread
+ * we will add evt fd into event poll thread upon user first register for evt */
+ CDBG("%s : Launch evt Poll Thread in Cam Open",__func__);
+ mm_camera_poll_thread_launch(&my_obj->evt_poll_thread,
+ MM_CAMERA_POLL_TYPE_EVT);
+
+ CDBG("%s: end (rc = %d)\n", __func__, rc);
+ /* we do not need to unlock cam_lock here before return
+ * because for open, it's done within intf_lock */
+ return rc;
+
+on_error:
+ if (my_obj->ctrl_fd > 0) {
+ close(my_obj->ctrl_fd);
+ my_obj->ctrl_fd = -1;
+ }
+ if (my_obj->ds_fd > 0) {
+ mm_camera_socket_close(my_obj->ds_fd);
+ my_obj->ds_fd = -1;
+ }
+
+ /* we do not need to unlock cam_lock here before return
+ * because for open, it's done within intf_lock */
+ return rc;
+}
+
+int32_t mm_camera_close(mm_camera_obj_t *my_obj)
+{
+ CDBG("%s : Close evt Poll Thread in Cam Close",__func__);
+ mm_camera_poll_thread_release(&my_obj->evt_poll_thread);
+
+ CDBG("%s : Close evt cmd Thread in Cam Close",__func__);
+ mm_camera_cmd_thread_release(&my_obj->evt_thread);
+
+ CDBG("%s : Close asyn cmd Thread in Cam Close",__func__);
+ mm_camera_cmd_thread_release(&my_obj->async_cmd_thread);
+
+ if(my_obj->ctrl_fd > 0) {
+ close(my_obj->ctrl_fd);
+ my_obj->ctrl_fd = -1;
+ }
+ if(my_obj->ds_fd > 0) {
+ mm_camera_socket_close(my_obj->ds_fd);
+ my_obj->ds_fd = -1;
+ }
+
+ pthread_mutex_destroy(&my_obj->cb_lock);
+
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ return 0;
+}
+
+uint8_t mm_camera_is_event_supported(mm_camera_obj_t *my_obj, mm_camera_event_type_t evt_type)
+{
+ switch(evt_type) {
+ case MM_CAMERA_EVT_TYPE_CH:
+ case MM_CAMERA_EVT_TYPE_CTRL:
+ case MM_CAMERA_EVT_TYPE_STATS:
+ case MM_CAMERA_EVT_TYPE_INFO:
+ return 1;
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+int32_t mm_camera_register_event_notify_internal(
+ mm_camera_obj_t *my_obj,
+ mm_camera_event_notify_t evt_cb,
+ void * user_data,
+ mm_camera_event_type_t evt_type)
+{
+ int i;
+ int rc = -1;
+ mm_camera_evt_obj_t *evt_array = NULL;
+
+ pthread_mutex_lock(&my_obj->cb_lock);
+ evt_array = &my_obj->evt[evt_type];
+ if(evt_cb) {
+ /* this is reg case */
+ for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
+ if(evt_array->evt[i].user_data == NULL) {
+ evt_array->evt[i].evt_cb = evt_cb;
+ evt_array->evt[i].user_data = user_data;
+ evt_array->reg_count++;
+ rc = 0;
+ break;
+ }
+ }
+ } else {
+ /* this is unreg case */
+ for(i = 0; i < MM_CAMERA_EVT_ENTRY_MAX; i++) {
+ if(evt_array->evt[i].user_data == user_data) {
+ evt_array->evt[i].evt_cb = NULL;
+ evt_array->evt[i].user_data = NULL;
+ evt_array->reg_count--;
+ rc = 0;
+ break;
+ }
+ }
+ }
+
+ if(rc == 0 && evt_array->reg_count <= 1) {
+ /* subscribe/unsubscribe event to kernel */
+ rc = mm_camera_evt_sub(my_obj, evt_type, evt_array->reg_count);
+ }
+
+ pthread_mutex_unlock(&my_obj->cb_lock);
+ return rc;
+}
+
+int32_t mm_camera_register_event_notify(mm_camera_obj_t *my_obj,
+ mm_camera_event_notify_t evt_cb,
+ void * user_data,
+ mm_camera_event_type_t evt_type)
+{
+ int i;
+ int rc = -1;
+ mm_camera_evt_obj_t *evt_array = &my_obj->evt[evt_type];
+
+ rc = mm_camera_register_event_notify_internal(my_obj, evt_cb,
+ user_data, evt_type);
+
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ return rc;
+}
+
+int32_t mm_camera_qbuf(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ mm_camera_buf_def_t *buf)
+{
+ int rc = -1;
+ mm_channel_t * ch_obj = NULL;
+ ch_obj = mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ /* we always assume qbuf will be done before channel/stream is fully stopped
+ * because qbuf is done within dataCB context
+ * in order to avoid deadlock, we are not locking ch_lock for qbuf */
+ if (NULL != ch_obj) {
+ rc = mm_channel_qbuf(ch_obj, buf);
+ }
+
+ return rc;
+}
+
+mm_camera_2nd_sensor_t * mm_camera_query_2nd_sensor_info(mm_camera_obj_t *my_obj)
+{
+ /* TODO: need to sync with backend how to get 2nd sensor info */
+ return NULL;
+}
+
+int32_t mm_camera_sync(mm_camera_obj_t *my_obj)
+{
+ int32_t rc = 0;
+
+ /* get camera capabilities */
+ memset(&my_obj->properties, 0, sizeof(cam_prop_t));
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_GET_CAPABILITIES,
+ sizeof(cam_prop_t),
+ (void *)&my_obj->properties);
+ if (rc != 0) {
+ CDBG_ERROR("%s: cannot get camera capabilities\n", __func__);
+ goto on_error;
+ }
+
+ /* TODO */
+ /* after kernel/backend support query of offline pp capability
+ * we can get the value from capabilities.
+ * for now, hard-coded to 1, meaning always need post processing */
+ //my_obj->need_pp = 1;
+ my_obj->need_pp = 0;
+
+on_error:
+ /* TODO:
+ * We need to enable below lock once we consider sync as saperate API
+ * and HAL needs to call after each camera open call.
+ */
+ //pthread_mutex_unlock(&my_obj->cam_lock);
+ return rc;
+
+}
+
+int32_t mm_camera_is_parm_supported(mm_camera_obj_t *my_obj,
+ mm_camera_parm_type_t parm_type,
+ uint8_t *support_set_parm,
+ uint8_t *support_get_parm)
+{
+ /* TODO: need to sync with backend if it can support set/get */
+ int32_t rc = 0;
+ *support_set_parm = GET_PARM_BIT32(parm_type,
+ my_obj->properties.parm);
+ *support_get_parm = GET_PARM_BIT32(parm_type,
+ my_obj->properties.parm);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ return rc;
+}
+
+int32_t mm_camera_util_set_op_mode(mm_camera_obj_t * my_obj,
+ mm_camera_op_mode_type_t *op_mode)
+{
+ int32_t rc = 0;
+ int32_t v4l2_op_mode = MSM_V4L2_CAM_OP_DEFAULT;
+
+ if (my_obj->op_mode == *op_mode)
+ goto end;
+ switch(*op_mode) {
+ case MM_CAMERA_OP_MODE_ZSL:
+ v4l2_op_mode = MSM_V4L2_CAM_OP_ZSL;
+ break;
+ case MM_CAMERA_OP_MODE_CAPTURE:
+ v4l2_op_mode = MSM_V4L2_CAM_OP_CAPTURE;
+ break;
+ case MM_CAMERA_OP_MODE_VIDEO:
+ v4l2_op_mode = MSM_V4L2_CAM_OP_VIDEO;
+ break;
+ default:
+ rc = - 1;
+ goto end;
+ break;
+ }
+ if(0 != (rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
+ MSM_V4L2_PID_CAM_MODE, v4l2_op_mode))){
+ CDBG_ERROR("%s: input op_mode=%d, s_ctrl rc=%d\n", __func__, *op_mode, rc);
+ goto end;
+ }
+ /* if success update mode field */
+ my_obj->op_mode = *op_mode;
+end:
+ CDBG("%s: op_mode=%d,rc=%d\n", __func__, *op_mode, rc);
+ return rc;
+}
+
+int32_t mm_camera_set_parm(mm_camera_obj_t *my_obj,
+ mm_camera_parm_type_t parm_type,
+ void* p_value)
+{
+ int32_t rc = 0;
+ CDBG("%s type =%d", __func__, parm_type);
+ switch(parm_type) {
+ case MM_CAMERA_PARM_OP_MODE:
+ rc = mm_camera_util_set_op_mode(my_obj,
+ (mm_camera_op_mode_type_t *)p_value);
+ break;
+ case MM_CAMERA_PARM_DIMENSION:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_DIMENSION, sizeof(cam_ctrl_dimension_t), p_value);
+ if(rc != 0) {
+ CDBG("%s: mm_camera_send_native_ctrl_cmd err=%d\n", __func__, rc);
+ break;
+ }
+ memcpy(&my_obj->dim, (cam_ctrl_dimension_t *)p_value,
+ sizeof(cam_ctrl_dimension_t));
+ CDBG("%s: dw=%d,dh=%d,vw=%d,vh=%d,pw=%d,ph=%d,tw=%d,th=%d,raw_w=%d,raw_h=%d\n",
+ __func__,
+ my_obj->dim.display_width,my_obj->dim.display_height,
+ my_obj->dim.video_width, my_obj->dim.video_height,
+ my_obj->dim.picture_width,my_obj->dim.picture_height,
+ my_obj->dim.ui_thumbnail_width,my_obj->dim.ui_thumbnail_height,
+ my_obj->dim.raw_picture_width,my_obj->dim.raw_picture_height);
+ break;
+ case MM_CAMERA_PARM_SNAPSHOT_BURST_NUM:
+ my_obj->snap_burst_num_by_user = *((uint32_t *)p_value);
+ break;
+ default:
+ rc = mm_camera_set_general_parm(my_obj, parm_type, p_value);
+ break;
+ }
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ return rc;
+}
+
+int32_t mm_camera_get_parm(mm_camera_obj_t *my_obj,
+ mm_camera_parm_type_t parm_type,
+ void* p_value)
+{
+ int32_t rc = 0;
+
+ switch(parm_type) {
+ case MM_CAMERA_PARM_MAX_PICTURE_SIZE:
+ {
+ mm_camera_dimension_t *dim =
+ (mm_camera_dimension_t *)p_value;
+ dim->height = my_obj->properties.max_pict_height;
+ dim->width = my_obj->properties.max_pict_width;
+ CDBG("%s: Max Picture Size: %d X %d\n", __func__,
+ dim->width, dim->height);
+ }
+ break;
+ case MM_CAMERA_PARM_PREVIEW_FORMAT:
+ *((int *)p_value) = my_obj->properties.preview_format;
+ break;
+ case MM_CAMERA_PARM_PREVIEW_SIZES_CNT:
+ *((int *)p_value) = my_obj->properties.preview_sizes_cnt;
+ break;
+ case MM_CAMERA_PARM_VIDEO_SIZES_CNT:
+ *((int *)p_value) = my_obj->properties.video_sizes_cnt;
+ break;
+ case MM_CAMERA_PARM_THUMB_SIZES_CNT:
+ *((int *)p_value) = my_obj->properties.thumb_sizes_cnt;
+ break;
+ case MM_CAMERA_PARM_HFR_SIZES_CNT:
+ *((int *)p_value) = my_obj->properties.hfr_sizes_cnt;
+ break;
+ case MM_CAMERA_PARM_HFR_FRAME_SKIP:
+ *((int *)p_value) = my_obj->properties.hfr_frame_skip;
+ break;
+ case MM_CAMERA_PARM_DEFAULT_PREVIEW_WIDTH:
+ *((int *)p_value) = my_obj->properties.default_preview_width;
+ break;
+ case MM_CAMERA_PARM_DEFAULT_PREVIEW_HEIGHT:
+ *((int *)p_value) = my_obj->properties.default_preview_height;
+ break;
+ case MM_CAMERA_PARM_MAX_PREVIEW_SIZE:
+ {
+ mm_camera_dimension_t *dim =
+ (mm_camera_dimension_t *)p_value;
+ dim->height = my_obj->properties.max_preview_height;
+ dim->width = my_obj->properties.max_preview_width;
+ CDBG("%s: Max Preview Size: %d X %d\n", __func__,
+ dim->width, dim->height);
+ }
+ break;
+ case MM_CAMERA_PARM_MAX_VIDEO_SIZE:
+ {
+ mm_camera_dimension_t *dim =
+ (mm_camera_dimension_t *)p_value;
+ dim->height = my_obj->properties.max_video_height;
+ dim->width = my_obj->properties.max_video_width;
+ CDBG("%s: Max Video Size: %d X %d\n", __func__,
+ dim->width, dim->height);
+ }
+ break;
+ case MM_CAMERA_PARM_MAX_HFR_MODE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_GET_PARM_MAX_HFR_MODE,
+ sizeof(camera_hfr_mode_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_FOCAL_LENGTH:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_GET_PARM_FOCAL_LENGTH,
+ sizeof(float),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_HORIZONTAL_VIEW_ANGLE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_GET_PARM_HORIZONTAL_VIEW_ANGLE,
+ sizeof(float),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_VERTICAL_VIEW_ANGLE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_GET_PARM_VERTICAL_VIEW_ANGLE,
+ sizeof(float),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_FOCUS_DISTANCES:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_GET_PARM_FOCUS_DISTANCES,
+ sizeof(focus_distances_info_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_QUERY_FALSH4SNAP:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_QUERY_FLASH_FOR_SNAPSHOT,
+ sizeof(int),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_3D_FRAME_FORMAT:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_GET_PARM_3D_FRAME_FORMAT,
+ sizeof(camera_3d_frame_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_MAXZOOM:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_GET_PARM_MAXZOOM,
+ sizeof(int),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_ZOOM_RATIO:
+ {
+ mm_camera_zoom_tbl_t *tbl = (mm_camera_zoom_tbl_t *)p_value;
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_GET_PARM_ZOOMRATIOS,
+ sizeof(int16_t)*tbl->size,
+ (void *)(tbl->zoom_ratio_tbl));
+ }
+ break;
+ case MM_CAMERA_PARM_DEF_PREVIEW_SIZES:
+ {
+ default_sizes_tbl_t *tbl = (default_sizes_tbl_t*)p_value;
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_GET_PARM_DEF_PREVIEW_SIZES,
+ sizeof(struct camera_size_type)*tbl->tbl_size,
+ (void* )(tbl->sizes_tbl));
+ }
+ break;
+ case MM_CAMERA_PARM_DEF_VIDEO_SIZES:
+ {
+ default_sizes_tbl_t *tbl = (default_sizes_tbl_t*)p_value;
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_GET_PARM_DEF_VIDEO_SIZES,
+ sizeof(struct camera_size_type)*tbl->tbl_size,
+ (void *)(tbl->sizes_tbl));
+ }
+ break;
+ case MM_CAMERA_PARM_DEF_THUMB_SIZES:
+ {
+ default_sizes_tbl_t *tbl = (default_sizes_tbl_t*)p_value;
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_GET_PARM_DEF_THUMB_SIZES,
+ sizeof(struct camera_size_type)*tbl->tbl_size,
+ (void *)(tbl->sizes_tbl));
+ }
+ break;
+ case MM_CAMERA_PARM_DEF_HFR_SIZES:
+ {
+ default_sizes_tbl_t *tbl = (default_sizes_tbl_t*)p_value;
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_GET_PARM_DEF_HFR_SIZES,
+ sizeof(struct camera_size_type)*tbl->tbl_size,
+ (void *)(tbl->sizes_tbl));
+ }
+ break;
+ case MM_CAMERA_PARM_SNAPSHOT_BURST_NUM:
+ *((int *)p_value) = my_obj->snap_burst_num_by_user;
+ break;
+ case MM_CAMERA_PARM_VFE_OUTPUT_ENABLE:
+ *((int *)p_value) = my_obj->properties.vfe_output_enable;
+ break;
+ case MM_CAMERA_PARM_DIMENSION:
+ memcpy(p_value, &my_obj->dim, sizeof(my_obj->dim));
+ CDBG("%s: dw=%d,dh=%d,vw=%d,vh=%d,pw=%d,ph=%d,tw=%d,th=%d,ovx=%x,ovy=%d,opx=%d,opy=%d, m_fmt=%d, t_ftm=%d\n",
+ __func__,
+ my_obj->dim.display_width,my_obj->dim.display_height,
+ my_obj->dim.video_width,my_obj->dim.video_height,
+ my_obj->dim.picture_width,my_obj->dim.picture_height,
+ my_obj->dim.ui_thumbnail_width,my_obj->dim.ui_thumbnail_height,
+ my_obj->dim.orig_video_width,my_obj->dim.orig_video_height,
+ my_obj->dim.orig_picture_width,my_obj->dim.orig_picture_height,
+ my_obj->dim.main_img_format, my_obj->dim.thumb_format);
+ break;
+ case MM_CAMERA_PARM_OP_MODE:
+ *((mm_camera_op_mode_type_t *)p_value) = my_obj->op_mode;
+ break;
+ default:
+ /* needs to add more implementation */
+ rc = -1;
+ break;
+ }
+
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ return rc;
+}
+
+uint32_t mm_camera_add_channel(mm_camera_obj_t *my_obj)
+{
+ mm_channel_t *ch_obj = NULL;
+ uint8_t ch_idx = 0;
+ uint32_t ch_hdl = 0;
+
+ for(ch_idx = 0; ch_idx < MM_CAMERA_CHANNEL_MAX; ch_idx++) {
+ if (MM_CHANNEL_STATE_NOTUSED == my_obj->ch[ch_idx].state) {
+ ch_obj = &my_obj->ch[ch_idx];
+ break;
+ }
+ }
+
+ if (NULL != ch_obj) {
+ /* initialize channel obj */
+ memset(ch_obj, 0, sizeof(mm_channel_t));
+ ch_hdl = mm_camera_util_generate_handler(ch_idx);
+ ch_obj->my_hdl = ch_hdl;
+ ch_obj->state = MM_CHANNEL_STATE_STOPPED;
+ ch_obj->cam_obj = my_obj;
+ pthread_mutex_init(&ch_obj->ch_lock, NULL);
+ }
+
+ mm_channel_init(ch_obj);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ return ch_hdl;
+}
+
+void mm_camera_del_channel(mm_camera_obj_t *my_obj,
+ uint32_t ch_id)
+{
+ mm_channel_t * ch_obj =
+ mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+
+ if (NULL != ch_obj) {
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ mm_channel_fsm_fn(ch_obj,
+ MM_CHANNEL_EVT_DELETE,
+ NULL,
+ NULL);
+
+ pthread_mutex_destroy(&ch_obj->ch_lock);
+ memset(ch_obj, 0, sizeof(mm_channel_t));
+ } else {
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ }
+}
+
+uint32_t mm_camera_add_stream(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ mm_camera_buf_notify_t buf_cb, void *user_data,
+ uint32_t ext_image_mode, uint32_t sensor_idx)
+{
+ uint32_t s_hdl = 0;
+ mm_channel_t * ch_obj =
+ mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+ mm_evt_paylod_add_stream_t payload;
+ void* out_val = NULL;
+
+ if (NULL != ch_obj) {
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ memset(&payload, 0, sizeof(mm_evt_paylod_add_stream_t));
+ payload.buf_cb = buf_cb;
+ payload.user_data = user_data;
+ payload.ext_image_mode = ext_image_mode;
+ payload.sensor_idx = sensor_idx;
+ mm_channel_fsm_fn(ch_obj,
+ MM_CHANNEL_EVT_ADD_STREAM,
+ (void*)&payload,
+ (void*)&s_hdl);
+ } else {
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ }
+
+ return s_hdl;
+}
+
+int32_t mm_camera_del_stream(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint32_t stream_id)
+{
+ int32_t rc = -1;
+ mm_channel_t * ch_obj =
+ mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+
+ if (NULL != ch_obj) {
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ rc = mm_channel_fsm_fn(ch_obj,
+ MM_CHANNEL_EVT_DEL_STREAM,
+ (void*)&stream_id,
+ NULL);
+ } else {
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ }
+
+ return rc;
+}
+
+int32_t mm_camera_config_stream(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint32_t stream_id,
+ mm_camera_stream_config_t *config)
+{
+ int32_t rc = -1;
+ mm_channel_t * ch_obj =
+ mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+ mm_evt_paylod_config_stream_t payload;
+
+ if (NULL != ch_obj) {
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ memset(&payload, 0, sizeof(mm_evt_paylod_config_stream_t));
+ payload.stream_id = stream_id;
+ payload.config = config;
+ rc = mm_channel_fsm_fn(ch_obj,
+ MM_CHANNEL_EVT_CONFIG_STREAM,
+ (void*)&payload,
+ NULL);
+ } else {
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ }
+
+ return rc;
+}
+
+int32_t mm_camera_bundle_streams(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ mm_camera_buf_notify_t super_frame_notify_cb,
+ void *user_data,
+ mm_camera_bundle_attr_t *attr,
+ uint8_t num_streams,
+ uint32_t *stream_ids)
+{
+ int32_t rc = -1;
+ mm_channel_t * ch_obj =
+ mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+ mm_evt_payload_bundle_stream_t payload;
+
+ if (NULL != ch_obj) {
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ memset(&payload, 0, sizeof(mm_evt_payload_bundle_stream_t));
+ payload.super_frame_notify_cb = super_frame_notify_cb;
+ payload.user_data = user_data;
+ payload.attr = attr;
+ payload.num_streams = num_streams;
+ payload.stream_ids = stream_ids;
+ rc = mm_channel_fsm_fn(ch_obj,
+ MM_CHANNEL_EVT_INIT_BUNDLE,
+ (void*)&payload,
+ NULL);
+ } else {
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ }
+
+ return rc;
+}
+
+int32_t mm_camera_destroy_bundle(mm_camera_obj_t *my_obj, uint32_t ch_id)
+{
+ int32_t rc = -1;
+ mm_channel_t * ch_obj =
+ mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+
+ if (NULL != ch_obj) {
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ rc = mm_channel_fsm_fn(ch_obj,
+ MM_CHANNEL_EVT_DESTROY_BUNDLE,
+ NULL,
+ NULL);
+ } else {
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ }
+
+ return rc;
+}
+
+int32_t mm_camera_start_streams(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint8_t num_streams,
+ uint32_t *stream_ids)
+{
+ int32_t rc = -1;
+ mm_channel_t * ch_obj =
+ mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+ mm_evt_payload_start_stream_t payload;
+
+ if (NULL != ch_obj) {
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ memset(&payload, 0, sizeof(mm_evt_payload_start_stream_t));
+ payload.num_streams = num_streams;
+ payload.stream_ids = stream_ids;
+ rc = mm_channel_fsm_fn(ch_obj,
+ MM_CHANNEL_EVT_START_STREAM,
+ (void*)&payload,
+ NULL);
+ } else {
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ }
+
+ return rc;
+}
+
+int32_t mm_camera_stop_streams(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint8_t num_streams,
+ uint32_t *stream_ids)
+{
+ int32_t rc = 0;
+ mm_evt_payload_stop_stream_t payload;
+ mm_camera_cmdcb_t * node = NULL;
+
+ mm_channel_t * ch_obj =
+ mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+
+ if (NULL != ch_obj) {
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ memset(&payload, 0, sizeof(mm_evt_payload_stop_stream_t));
+ payload.num_streams = num_streams;
+ payload.stream_ids = stream_ids;
+
+ rc = mm_channel_fsm_fn(ch_obj,
+ MM_CHANNEL_EVT_STOP_STREAM,
+ (void*)&payload,
+ NULL);
+ } else {
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ }
+ return rc;
+}
+
+int32_t mm_camera_async_teardown_streams(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint8_t num_streams,
+ uint32_t *stream_ids)
+{
+ int32_t rc = 0;
+ mm_evt_payload_stop_stream_t payload;
+ mm_camera_cmdcb_t * node = NULL;
+
+ mm_channel_t * ch_obj =
+ mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+
+ if (NULL != ch_obj) {
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ /* enqueu asyn stop cmd to async_cmd_thread */
+ node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
+ if (NULL != node) {
+ memset(node, 0, sizeof(mm_camera_cmdcb_t));
+ node->cmd_type = MM_CAMERA_CMD_TYPE_ASYNC_CB;
+ node->u.async.cmd_type = MM_CAMERA_ASYNC_CMD_TYPE_STOP;
+ node->u.async.u.stop_cmd.ch_obj = ch_obj;
+ node->u.async.u.stop_cmd.num_streams = num_streams;
+ memcpy(node->u.async.u.stop_cmd.stream_ids, stream_ids, sizeof(uint32_t)*num_streams);
+
+ /* enqueue to async cmd thread */
+ mm_camera_queue_enq(&(my_obj->async_cmd_thread.cmd_queue), node);
+ /* wake up async cmd thread */
+ sem_post(&(my_obj->async_cmd_thread.cmd_sem));
+ } else {
+ CDBG_ERROR("%s: No memory for mm_camera_cmdcb_t", __func__);
+ pthread_mutex_unlock(&ch_obj->ch_lock);
+ rc = -1;
+ return rc;
+ }
+ } else {
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ }
+ return rc;
+}
+
+int32_t mm_camera_request_super_buf(mm_camera_obj_t *my_obj, uint32_t ch_id)
+{
+ int32_t rc = -1;
+ mm_channel_t * ch_obj =
+ mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+
+ if (NULL != ch_obj) {
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ rc = mm_channel_fsm_fn(ch_obj,
+ MM_CHANNEL_EVT_REQUEST_SUPER_BUF,
+ NULL,
+ NULL);
+ } else {
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ }
+
+ return rc;
+}
+
+int32_t mm_camera_cancel_super_buf_request(mm_camera_obj_t *my_obj, uint32_t ch_id)
+{
+ int32_t rc = -1;
+ mm_channel_t * ch_obj =
+ mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+
+ if (NULL != ch_obj) {
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ rc = mm_channel_fsm_fn(ch_obj,
+ MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF,
+ NULL,
+ NULL);
+ } else {
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ }
+
+ return rc;
+}
+
+int32_t mm_camera_start_focus(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint32_t sensor_idx,
+ uint32_t focus_mode)
+{
+ int32_t rc = -1;
+ mm_evt_payload_start_focus_t payload;
+ mm_channel_t * ch_obj =
+ mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+
+ if (NULL != ch_obj) {
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ memset(&payload, 0, sizeof(mm_evt_payload_start_focus_t));
+ payload.sensor_idx = sensor_idx;
+ payload.focus_mode = focus_mode;
+ rc = mm_channel_fsm_fn(ch_obj,
+ MM_CHANNEL_EVT_START_FOCUS,
+ (void *)&payload,
+ NULL);
+ } else {
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ }
+
+ return rc;
+}
+
+int32_t mm_camera_abort_focus(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint32_t sensor_idx)
+{
+ int32_t rc = -1;
+ mm_channel_t * ch_obj =
+ mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+
+ if (NULL != ch_obj) {
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ rc = mm_channel_fsm_fn(ch_obj,
+ MM_CHANNEL_EVT_ABORT_FOCUS,
+ (void*)sensor_idx,
+ NULL);
+ } else {
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ }
+
+ return rc;
+}
+
+int32_t mm_camera_prepare_snapshot(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint32_t sensor_idx)
+{
+ int32_t rc = -1;
+ mm_channel_t * ch_obj =
+ mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+
+ if (NULL != ch_obj) {
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ rc = mm_channel_fsm_fn(ch_obj,
+ MM_CHANNEL_EVT_PREPARE_SNAPSHOT,
+ (void *)sensor_idx,
+ NULL);
+ } else {
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ }
+
+ return rc;
+}
+
+int32_t mm_camera_set_stream_parm(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint32_t s_id,
+ mm_camera_stream_parm_t parm_type,
+ void* p_value)
+{
+ int32_t rc = -1;
+ mm_evt_paylod_stream_parm_t payload;
+ mm_channel_t * ch_obj =
+ mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+
+ if (NULL != ch_obj) {
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ memset(&payload,0,sizeof(mm_evt_paylod_stream_parm_t));
+ payload.parm_type = parm_type;
+ payload.value = p_value;
+ rc = mm_channel_fsm_fn(ch_obj,
+ MM_CHANNEL_EVT_SET_STREAM_PARM,
+ (void *)s_id,
+ &payload);
+ } else {
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ }
+
+ return rc;
+}
+
+int32_t mm_camera_get_stream_parm(mm_camera_obj_t *my_obj,
+ uint32_t ch_id,
+ uint32_t s_id,
+ mm_camera_stream_parm_t parm_type,
+ void* p_value)
+{
+ int32_t rc = -1;
+ mm_evt_paylod_stream_parm_t payload;
+ mm_channel_t * ch_obj =
+ mm_camera_util_get_channel_by_handler(my_obj, ch_id);
+
+ if (NULL != ch_obj) {
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ pthread_mutex_unlock(&my_obj->cam_lock);
+
+ memset(&payload,0,sizeof(mm_evt_paylod_stream_parm_t));
+ payload.parm_type = parm_type;
+ payload.value = p_value;
+ rc = mm_channel_fsm_fn(ch_obj,
+ MM_CHANNEL_EVT_GET_STREAM_PARM,
+ (void *)s_id,
+ &payload);
+ } else {
+ pthread_mutex_unlock(&my_obj->cam_lock);
+ }
+
+ return rc;
+}
+
+int32_t mm_camera_ctrl_set_specialEffect (mm_camera_obj_t *my_obj, int32_t effect) {
+ struct v4l2_control ctrl;
+ if (effect == CAMERA_EFFECT_MAX)
+ effect = CAMERA_EFFECT_OFF;
+ int rc = 0;
+
+ ctrl.id = MSM_V4L2_PID_EFFECT;
+ ctrl.value = effect;
+ rc = ioctl(my_obj->ctrl_fd, VIDIOC_S_CTRL, &ctrl);
+ return rc;
+}
+
+int32_t mm_camera_ctrl_set_auto_focus (mm_camera_obj_t *my_obj, int32_t value)
+{
+ int32_t rc = 0;
+ struct v4l2_queryctrl queryctrl;
+
+ memset (&queryctrl, 0, sizeof (queryctrl));
+ queryctrl.id = V4L2_CID_FOCUS_AUTO;
+
+ if(value != 0 && value != 1) {
+ CDBG("%s:boolean required, invalid value = %d\n",__func__, value);
+ return -1;
+ }
+ if (-1 == ioctl (my_obj->ctrl_fd, VIDIOC_QUERYCTRL, &queryctrl)) {
+ CDBG ("V4L2_CID_FOCUS_AUTO is not supported\n");
+ } else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
+ CDBG ("%s:V4L2_CID_FOCUS_AUTO is not supported\n", __func__);
+ } else {
+ if(0 != (rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
+ V4L2_CID_FOCUS_AUTO, value))){
+ CDBG("%s: error, id=0x%x, value=%d, rc = %d\n",
+ __func__, V4L2_CID_FOCUS_AUTO, value, rc);
+ rc = -1;
+ }
+ }
+ return rc;
+}
+
+int32_t mm_camera_ctrl_set_whitebalance (mm_camera_obj_t *my_obj, int32_t mode) {
+
+ int32_t rc = 0, value;
+ uint32_t id;
+
+ switch(mode) {
+ case MM_CAMERA_WHITE_BALANCE_AUTO:
+ id = V4L2_CID_AUTO_WHITE_BALANCE;
+ value = 1; /* TRUE */
+ break;
+ case MM_CAMERA_WHITE_BALANCE_OFF:
+ id = V4L2_CID_AUTO_WHITE_BALANCE;
+ value = 0; /* FALSE */
+ break;
+ case MM_CAMERA_WHITE_BALANCE_DAYLIGHT:
+ id = V4L2_CID_WHITE_BALANCE_TEMPERATURE;
+ value = 6500;
+ break;
+ case MM_CAMERA_WHITE_BALANCE_INCANDESCENT:
+ id = V4L2_CID_WHITE_BALANCE_TEMPERATURE;
+ value = 2800;
+ break;
+ case MM_CAMERA_WHITE_BALANCE_FLUORESCENT:
+ id = V4L2_CID_WHITE_BALANCE_TEMPERATURE;
+ value = 4200;
+ break;
+ case MM_CAMERA_WHITE_BALANCE_CLOUDY:
+ id = V4L2_CID_WHITE_BALANCE_TEMPERATURE;
+ value = 7500;
+ break;
+ default:
+ id = V4L2_CID_WHITE_BALANCE_TEMPERATURE;
+ value = 4200;
+ break;
+ }
+ rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd, id, value);
+ if(0 != rc){
+ CDBG("%s: error, exp_metering_action_param=%d, rc = %d\n", __func__, value, rc);
+ }
+ return rc;
+}
+
+int32_t mm_camera_set_general_parm(mm_camera_obj_t * my_obj,
+ mm_camera_parm_type_t parm_type,
+ void* p_value)
+{
+ int rc = -1;
+ int isZSL =0;
+
+ switch(parm_type) {
+ case MM_CAMERA_PARM_EXPOSURE:
+ rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
+ MSM_V4L2_PID_EXP_METERING,
+ *((int32_t *)p_value));
+ break;
+ case MM_CAMERA_PARM_SHARPNESS:
+ rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
+ V4L2_CID_SHARPNESS,
+ *((int32_t *)p_value));
+ break;
+ case MM_CAMERA_PARM_CONTRAST:
+ rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
+ V4L2_CID_CONTRAST,
+ *((int32_t *)p_value));
+ break;
+ case MM_CAMERA_PARM_SATURATION:
+ rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
+ V4L2_CID_SATURATION,
+ *((int32_t *)p_value));
+ break;
+ case MM_CAMERA_PARM_BRIGHTNESS:
+ rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
+ V4L2_CID_BRIGHTNESS,
+ *((int32_t *)p_value));
+ break;
+ case MM_CAMERA_PARM_WHITE_BALANCE:
+ rc = mm_camera_ctrl_set_whitebalance (my_obj, *((int32_t *)p_value));
+ break;
+ case MM_CAMERA_PARM_ISO:
+ rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
+ MSM_V4L2_PID_ISO,
+ *((int32_t *)p_value));
+ break;
+ case MM_CAMERA_PARM_ZOOM:
+ rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
+ V4L2_CID_ZOOM_ABSOLUTE,
+ *((int32_t *)p_value));
+ break;
+ case MM_CAMERA_PARM_LUMA_ADAPTATION:
+ rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
+ MSM_V4L2_PID_LUMA_ADAPTATION,
+ *((int32_t *)p_value));
+ break;
+ case MM_CAMERA_PARM_ANTIBANDING:
+ rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
+ V4L2_CID_POWER_LINE_FREQUENCY,
+ *((int32_t *)p_value));
+ break;
+ case MM_CAMERA_PARM_CONTINUOUS_AF:
+ rc = mm_camera_ctrl_set_auto_focus(my_obj,
+ *((int32_t *)p_value));
+ break;
+ case MM_CAMERA_PARM_HJR:
+ rc = mm_camera_util_s_ctrl(my_obj->ctrl_fd,
+ MSM_V4L2_PID_HJR,
+ *((int32_t *)p_value));
+ break;
+ case MM_CAMERA_PARM_EFFECT:
+ rc = mm_camera_ctrl_set_specialEffect (my_obj,
+ *((int32_t *)p_value));
+ break;
+ case MM_CAMERA_PARM_FPS:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_FPS,
+ sizeof(uint32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_FPS_MODE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_FPS_MODE,
+ sizeof(int32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_EXPOSURE_COMPENSATION:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_EXPOSURE_COMPENSATION,
+ sizeof(int32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_LED_MODE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_LED_MODE,
+ sizeof(int32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_ROLLOFF:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_ROLLOFF,
+ sizeof(int32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_MODE:
+ my_obj->current_mode = *((camera_mode_t *)p_value);
+ break;
+ case MM_CAMERA_PARM_FOCUS_RECT:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_FOCUS_RECT,
+ sizeof(int32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_AEC_ROI:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_AEC_ROI,
+ sizeof(cam_set_aec_roi_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_AF_ROI:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_AF_ROI,
+ sizeof(roi_info_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_FOCUS_MODE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_AF_MODE,
+ sizeof(int32_t),
+ p_value);
+ break;
+#if 0 /* to be enabled later: @punits */
+ case MM_CAMERA_PARM_AF_MTR_AREA:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_AF_MTR_AREA,
+ sizeof(af_mtr_area_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_AEC_MTR_AREA:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_AEC_MTR_AREA,
+ sizeof(aec_mtr_area_t),
+ p_value);
+ break;
+#endif
+ case MM_CAMERA_PARM_CAF_ENABLE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_CAF,
+ sizeof(uint32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_BESTSHOT_MODE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_BESTSHOT_MODE,
+ sizeof(int32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_VIDEO_DIS:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_VIDEO_DIS_PARAMS,
+ sizeof(video_dis_param_ctrl_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_VIDEO_ROT:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_VIDEO_ROT_PARAMS,
+ sizeof(video_rotation_param_ctrl_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_SCE_FACTOR:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_SCE_FACTOR,
+ sizeof(int32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_FD:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_FD,
+ sizeof(int32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_AEC_LOCK:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_AEC_LOCK,
+ sizeof(int32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_AWB_LOCK:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_AWB_LOCK,
+ sizeof(int32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_MCE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_MCE,
+ sizeof(int32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_HORIZONTAL_VIEW_ANGLE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_GET_PARM_HORIZONTAL_VIEW_ANGLE,
+ sizeof(focus_distances_info_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_VERTICAL_VIEW_ANGLE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_GET_PARM_VERTICAL_VIEW_ANGLE,
+ sizeof(focus_distances_info_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_RESET_LENS_TO_INFINITY:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_RESET_LENS_TO_INFINITY,
+ 0, NULL);
+ break;
+ case MM_CAMERA_PARM_SNAPSHOTDATA:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_GET_PARM_SNAPSHOTDATA,
+ sizeof(snapshotData_info_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_HFR:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_HFR,
+ sizeof(int32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_REDEYE_REDUCTION:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_REDEYE_REDUCTION,
+ sizeof(int32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_WAVELET_DENOISE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_WAVELET_DENOISE,
+ sizeof(denoise_param_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_3D_DISPLAY_DISTANCE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_3D_DISPLAY_DISTANCE,
+ sizeof(float),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_3D_VIEW_ANGLE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_3D_VIEW_ANGLE,
+ sizeof(uint32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_ZOOM_RATIO:
+ break;
+ case MM_CAMERA_PARM_HISTOGRAM:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_HISTOGRAM,
+ sizeof(int8_t),
+ p_value);
+ break;
+ /* Moved to mm-jpeg-interface */
+ /* case MM_CAMERA_PARM_JPEG_ROTATION:
+ break; */
+ case MM_CAMERA_PARM_ASD_ENABLE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_ASD_ENABLE,
+ sizeof(uint32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_RECORDING_HINT:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_RECORDING_HINT,
+ sizeof(uint32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_PREVIEW_FORMAT:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_PREVIEW_FORMAT,
+ sizeof(uint32_t),
+ p_value);
+ break;
+ /* TODO: need code review to determine any of the three is redundent
+ * MM_CAMERA_PARM_DIS_ENABLE,
+ * MM_CAMERA_PARM_FULL_LIVESHOT,
+ * MM_CAMERA_PARM_LOW_POWER_MODE*/
+ case MM_CAMERA_PARM_DIS_ENABLE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_DIS_ENABLE,
+ sizeof(uint32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_FULL_LIVESHOT:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_FULL_LIVESHOT,
+ sizeof(uint32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_LOW_POWER_MODE:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_LOW_POWER_MODE,
+ sizeof(uint32_t),
+ p_value);
+ break;
+ case MM_CAMERA_PARM_HDR:
+ rc = mm_camera_send_native_ctrl_cmd(my_obj,
+ CAMERA_SET_PARM_HDR,
+ sizeof(exp_bracketing_t),
+ p_value);
+ break;
+ default:
+ CDBG("%s: default: parm %d not supported\n", __func__, parm_type);
+ break;
+ }
+ return rc;
+}
+
+int32_t mm_camera_util_private_s_ctrl(int32_t fd, uint32_t id, void* value)
+{
+ int rc = -1;
+ struct msm_camera_v4l2_ioctl_t v4l2_ioctl;
+
+ memset(&v4l2_ioctl, 0, sizeof(v4l2_ioctl));
+ v4l2_ioctl.id = id;
+ v4l2_ioctl.ioctl_ptr = value;
+ rc = ioctl (fd, MSM_CAM_V4L2_IOCTL_PRIVATE_S_CTRL, &v4l2_ioctl);
+
+ if(rc) {
+ CDBG_ERROR("%s: fd=%d, S_CTRL, id=0x%x, value = 0x%x, rc = %d\n",
+ __func__, fd, id, (uint32_t)value, rc);
+ rc = 1;
+ }
+ return rc;
+}
+
+int32_t mm_camera_send_native_ctrl_cmd(mm_camera_obj_t * my_obj,
+ cam_ctrl_type type,
+ uint32_t length,
+ void *value)
+{
+ return mm_camera_send_native_ctrl_timeout_cmd(my_obj, type,
+ length, value,
+ 1000);
+}
+
+int32_t mm_camera_send_native_ctrl_timeout_cmd(mm_camera_obj_t * my_obj,
+ cam_ctrl_type type,
+ uint32_t length,
+ void *value,
+ int timeout)
+{
+ int rc = -1;
+ struct msm_ctrl_cmd ctrl_cmd;
+
+ memset(&ctrl_cmd, 0, sizeof(ctrl_cmd));
+ ctrl_cmd.type = type;
+ ctrl_cmd.length = (uint16_t)length;
+ ctrl_cmd.timeout_ms = timeout;
+ ctrl_cmd.value = value;
+ ctrl_cmd.status = (uint16_t)CAM_CTRL_SUCCESS;
+ rc = mm_camera_util_private_s_ctrl(my_obj->ctrl_fd,
+ MSM_V4L2_PID_CTRL_CMD,
+ (void*)&ctrl_cmd);
+ CDBG("%s: type=%d, rc = %d, status = %d\n",
+ __func__, type, rc, ctrl_cmd.status);
+ if(rc != 0 || ((ctrl_cmd.status != CAM_CTRL_ACCEPTED) &&
+ (ctrl_cmd.status != CAM_CTRL_SUCCESS) &&
+ (ctrl_cmd.status != CAM_CTRL_INVALID_PARM)))
+ rc = -1;
+ return rc;
+}
+
+int mm_camera_evt_sub(mm_camera_obj_t * my_obj,
+ mm_camera_event_type_t evt_type,
+ int reg_count)
+{
+ int rc = 0;
+ struct v4l2_event_subscription sub;
+
+ memset(&sub, 0, sizeof(sub));
+ sub.type = V4L2_EVENT_PRIVATE_START+MSM_CAM_APP_NOTIFY_EVENT;
+ if(reg_count == 0) {
+ /* unsubscribe */
+ if(my_obj->evt_type_mask == (uint32_t)(1 << evt_type)) {
+ rc = ioctl(my_obj->ctrl_fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
+ CDBG("%s: unsubscribe event 0x%x, rc = %d", __func__, sub.type, rc);
+ sub.type = V4L2_EVENT_PRIVATE_START+MSM_CAM_APP_NOTIFY_ERROR_EVENT;
+ rc = ioctl(my_obj->ctrl_fd, VIDIOC_UNSUBSCRIBE_EVENT, &sub);
+ CDBG("%s: unsubscribe event 0x%x, rc = %d", __func__, sub.type, rc);
+ }
+ my_obj->evt_type_mask &= ~(1 << evt_type);
+ if(my_obj->evt_type_mask == 0) {
+ /* remove evt fd from the polling thraed when unreg the last event */
+ mm_camera_poll_thread_del_poll_fd(&my_obj->evt_poll_thread, my_obj->my_hdl);
+ }
+ } else {
+ if(!my_obj->evt_type_mask) {
+ /* this is the first reg event */
+ rc = ioctl(my_obj->ctrl_fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
+ CDBG("%s: subscribe event 0x%x, rc = %d", __func__, sub.type, rc);
+ if (rc < 0)
+ goto end;
+ sub.type = V4L2_EVENT_PRIVATE_START+MSM_CAM_APP_NOTIFY_ERROR_EVENT;
+ rc = ioctl(my_obj->ctrl_fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
+ CDBG("%s: subscribe event 0x%x, rc = %d", __func__, sub.type, rc);
+ if (rc < 0)
+ goto end;
+ }
+ my_obj->evt_type_mask |= (1 << evt_type);
+ if(my_obj->evt_type_mask == (uint32_t)(1 << evt_type)) {
+ /* add evt fd to polling thread when subscribe the first event */
+ rc = mm_camera_poll_thread_add_poll_fd(&my_obj->evt_poll_thread,
+ my_obj->my_hdl,
+ my_obj->ctrl_fd,
+ mm_camera_event_notify,
+ (void*)my_obj);
+ }
+ }
+end:
+ return rc;
+}
+
+int32_t mm_camera_util_sendmsg(mm_camera_obj_t *my_obj, void *msg, uint32_t buf_size, int sendfd)
+{
+ return mm_camera_socket_sendmsg(my_obj->ds_fd, msg, buf_size, sendfd);
+}
+
+int32_t mm_camera_map_buf(mm_camera_obj_t *my_obj,
+ int ext_mode,
+ int idx,
+ int fd,
+ uint32_t size)
+{
+ cam_sock_packet_t packet;
+ memset(&packet, 0, sizeof(cam_sock_packet_t));
+ packet.msg_type = CAM_SOCK_MSG_TYPE_FD_MAPPING;
+ packet.payload.frame_fd_map.ext_mode = ext_mode;
+ packet.payload.frame_fd_map.frame_idx = idx;
+ packet.payload.frame_fd_map.fd = fd;
+ packet.payload.frame_fd_map.size = size;
+
+ return mm_camera_util_sendmsg(my_obj, &packet,
+ sizeof(cam_sock_packet_t),
+ packet.payload.frame_fd_map.fd);
+}
+
+int32_t mm_camera_unmap_buf(mm_camera_obj_t *my_obj,
+ int ext_mode,
+ int idx)
+{
+ cam_sock_packet_t packet;
+ memset(&packet, 0, sizeof(cam_sock_packet_t));
+ packet.msg_type = CAM_SOCK_MSG_TYPE_FD_UNMAPPING;
+ packet.payload.frame_fd_unmap.ext_mode = ext_mode;
+ packet.payload.frame_fd_unmap.frame_idx = idx;
+ return mm_camera_util_sendmsg(my_obj, &packet,
+ sizeof(cam_sock_packet_t),
+ packet.payload.frame_fd_map.fd);
+}
+
+int32_t mm_camera_util_s_ctrl(int32_t fd, uint32_t id, int32_t value)
+{
+ int rc = 0;
+ struct v4l2_control control;
+
+ memset(&control, 0, sizeof(control));
+ control.id = id;
+ control.value = value;
+ rc = ioctl (fd, VIDIOC_S_CTRL, &control);
+
+ if(rc) {
+ CDBG("%s: fd=%d, S_CTRL, id=0x%x, value = 0x%x, rc = %d\n",
+ __func__, fd, id, (uint32_t)value, rc);
+ }
+ return rc;
+}
+
+int32_t mm_camera_util_g_ctrl( int32_t fd, uint32_t id, int32_t *value)
+{
+ int rc = 0;
+ struct v4l2_control control;
+
+ memset(&control, 0, sizeof(control));
+ control.id = id;
+ control.value = (int32_t)value;
+ rc = ioctl (fd, VIDIOC_G_CTRL, &control);
+ if(rc) {
+ CDBG("%s: fd=%d, G_CTRL, id=0x%x, rc = %d\n", __func__, fd, id, rc);
+ }
+ *value = control.value;
+ return rc;
+}
diff --git a/camera/QCamera/stack/mm-camera-interface/src/mm_camera_channel.c b/camera/QCamera/stack/mm-camera-interface/src/mm_camera_channel.c
new file mode 100755
index 0000000..81c3585
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-interface/src/mm_camera_channel.c
@@ -0,0 +1,1536 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <semaphore.h>
+
+#include "mm_camera_dbg.h"
+#include "mm_camera_interface.h"
+#include "mm_camera.h"
+
+extern mm_camera_obj_t* mm_camera_util_get_camera_by_handler(uint32_t cam_handler);
+extern mm_channel_t * mm_camera_util_get_channel_by_handler(
+ mm_camera_obj_t * cam_obj,
+ uint32_t handler);
+extern int32_t mm_camera_send_native_ctrl_cmd(mm_camera_obj_t * my_obj,
+ cam_ctrl_type type,
+ uint32_t length,
+ void *value);
+extern int32_t mm_camera_send_native_ctrl_timeout_cmd(mm_camera_obj_t * my_obj,
+ cam_ctrl_type type,
+ uint32_t length,
+ void *value,
+ int timeout);
+
+/* internal function declare goes here */
+int32_t mm_channel_qbuf(mm_channel_t *my_obj,
+ mm_camera_buf_def_t *buf);
+int32_t mm_channel_init(mm_channel_t *my_obj);
+void mm_channel_release(mm_channel_t *my_obj);
+uint32_t mm_channel_add_stream(mm_channel_t *my_obj,
+ mm_camera_buf_notify_t buf_cb, void *user_data,
+ uint32_t ext_image_mode, uint32_t sensor_idx);
+int32_t mm_channel_del_stream(mm_channel_t *my_obj,
+ uint32_t stream_id);
+int32_t mm_channel_config_stream(mm_channel_t *my_obj,
+ uint32_t stream_id,
+ mm_camera_stream_config_t *config);
+int32_t mm_channel_bundle_stream(mm_channel_t *my_obj,
+ mm_camera_buf_notify_t super_frame_notify_cb,
+ void *user_data,
+ mm_camera_bundle_attr_t *attr,
+ uint8_t num_streams,
+ uint32_t *stream_ids);
+int32_t mm_channel_destroy_bundle(mm_channel_t *my_obj);
+int32_t mm_channel_start_streams(mm_channel_t *my_obj,
+ uint8_t num_streams,
+ uint32_t *stream_ids);
+int32_t mm_channel_stop_streams(mm_channel_t *my_obj,
+ uint8_t num_streams,
+ uint32_t *stream_ids,
+ uint8_t tear_down_flag);
+int32_t mm_channel_request_super_buf(mm_channel_t *my_obj);
+int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj);
+int32_t mm_channel_start_focus(mm_channel_t *my_obj,
+ uint32_t sensor_idx,
+ uint32_t focus_mode);
+int32_t mm_channel_abort_focus(mm_channel_t *my_obj,
+ uint32_t sensor_idx);
+int32_t mm_channel_prepare_snapshot(mm_channel_t *my_obj,
+ uint32_t sensor_idx);
+int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
+ uint32_t s_id,
+ void *value);
+int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
+ uint32_t s_id,
+ void *value);
+uint8_t mm_channel_need_do_pp(mm_channel_t *my_obj,
+ mm_channel_queue_node_t *super_buf);
+int32_t mm_channel_do_post_processing(mm_channel_t *my_obj,
+ mm_channel_queue_node_t *super_buf);
+int32_t mm_channel_cancel_post_processing(mm_channel_t *my_obj);
+int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t* my_obj,
+ mm_channel_queue_t * queue);
+int32_t mm_channel_superbuf_skip(mm_channel_t* my_obj,
+ mm_channel_queue_t * queue);
+
+/* state machine function declare */
+int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
+ mm_channel_evt_type_t evt,
+ void * in_val,
+ void * out_val);
+int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
+ mm_channel_evt_type_t evt,
+ void * in_val,
+ void * out_val);
+int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
+ mm_channel_evt_type_t evt,
+ void * in_val,
+ void * out_val);
+int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
+ mm_channel_evt_type_t evt,
+ void * in_val,
+ void * out_val);
+
+/* channel super queue functions */
+int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue);
+int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue);
+int32_t mm_channel_superbuf_comp_and_enqueue(mm_channel_t *ch_obj,
+ mm_channel_queue_t * queue,
+ mm_camera_buf_info_t *buf);
+mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue);
+
+/* channel utility function */
+mm_stream_t * mm_channel_util_get_stream_by_handler(
+ mm_channel_t * ch_obj,
+ uint32_t handler)
+{
+ int i;
+ mm_stream_t *s_obj = NULL;
+ uint8_t ch_idx = mm_camera_util_get_index_by_handler(handler);
+
+ for(i = 0; i < MM_CAMEAR_STRAEM_NUM_MAX; i++) {
+ if (handler == ch_obj->streams[i].my_hdl) {
+ s_obj = &ch_obj->streams[i];
+ break;
+ }
+ }
+ return s_obj;
+}
+
+/* CB for handling post processing result from ctrl evt */
+static void mm_channel_pp_result_notify(uint32_t camera_handler,
+ mm_camera_event_t *evt,
+ void *user_data)
+{
+ uint32_t ch_hdl = (uint32_t)user_data;
+ mm_camera_obj_t *cam_obj = NULL;
+ mm_channel_t *ch_obj = NULL;
+ mm_channel_queue_node_t * node = NULL;
+ mm_channel_pp_info_t* pp_info = NULL;
+
+ cam_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+ if (NULL == cam_obj) {
+ CDBG("%s: No matching camera handler", __func__);
+ return;
+ }
+
+ ch_obj = mm_camera_util_get_channel_by_handler(cam_obj, ch_hdl);
+ if (NULL == ch_obj) {
+ CDBG("%s: No matching channel handler", __func__);
+ return;
+ }
+
+ pthread_mutex_lock(&ch_obj->ch_lock);
+ if (ch_obj->pending_pp_cnt > 0) {
+ if (MM_CAMERA_EVT_TYPE_CTRL == evt->event_type) {
+ /* PP result is sent as CTRL event
+ * currently we only have WNR */
+ if (MM_CAMERA_CTRL_EVT_WDN_DONE == evt->e.ctrl.evt) {
+ /* WNR result */
+ pp_info = (mm_channel_pp_info_t *)evt->e.ctrl.cookie;
+ if (NULL != pp_info) {
+ node = pp_info->super_buf;
+ }
+ }
+ }
+
+ if (NULL != node) {
+ uint8_t pp_done = 1;
+ if (CAM_CTRL_SUCCESS == evt->e.ctrl.status) {
+ uint8_t i;
+ /* 1) update need_pp flag as action done */
+ for (i=0; i<node->num_of_bufs; i++) {
+ if (node->super_buf[i].stream_id == pp_info->stream_hdl) {
+ /* stream pp is done, set the flag to 0*/
+ node->super_buf[i].need_pp = 0;
+ break;
+ }
+ }
+
+ /* 2) check if all bufs done with pp */
+ for (i=0; i<node->num_of_bufs; i++) {
+ if (node->super_buf[i].need_pp) {
+ pp_done = 0;
+ break;
+ }
+ }
+ }
+
+ if (pp_done) {
+ /* send super buf to CB */
+ if (NULL != ch_obj->bundle.super_buf_notify_cb) {
+ mm_camera_super_buf_t super_buf;
+ uint8_t i;
+
+ memset(&super_buf, 0, sizeof(mm_camera_super_buf_t));
+ super_buf.num_bufs = node->num_of_bufs;
+ for (i=0; i<node->num_of_bufs; i++) {
+ super_buf.bufs[i] = node->super_buf[i].buf;
+ }
+ super_buf.camera_handle = ch_obj->cam_obj->my_hdl;
+ super_buf.ch_id = ch_obj->my_hdl;
+
+ ch_obj->bundle.super_buf_notify_cb(&super_buf,
+ ch_obj->bundle.user_data);
+ ch_obj->pending_pp_cnt--;
+ } else {
+ /* buf done with the nonuse super buf */
+ uint8_t i;
+ for (i=0; i<node->num_of_bufs; i++) {
+ mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
+ }
+ }
+
+ /* done with node, free it */
+ free(node);
+ }
+ }
+ }
+ pthread_mutex_unlock(&ch_obj->ch_lock);
+}
+
+/* CB for processing stream buffer */
+static void mm_channel_process_stream_buf(mm_camera_cmdcb_t * cmd_cb,
+ void *user_data)
+{
+ mm_camera_super_buf_notify_mode_t notify_mode;
+ mm_channel_queue_node_t *node = NULL;
+ mm_channel_t *ch_obj = (mm_channel_t *)user_data;
+ if (NULL == ch_obj) {
+ return;
+ }
+
+ if (MM_CAMERA_CMD_TYPE_DATA_CB == cmd_cb->cmd_type) {
+ /* comp_and_enqueue */
+ mm_channel_superbuf_comp_and_enqueue(
+ ch_obj,
+ &ch_obj->bundle.superbuf_queue,
+ &cmd_cb->u.buf);
+ }
+
+ notify_mode = ch_obj->bundle.superbuf_queue.attr.notify_mode;
+
+ /* bufdone for overflowed bufs */
+ mm_channel_superbuf_bufdone_overflow(ch_obj, &ch_obj->bundle.superbuf_queue);
+
+ /* lock ch_lock */
+ pthread_mutex_lock(&ch_obj->ch_lock);
+
+ /* dispatch frame if pending_cnt>0 or is in continuous streaming mode */
+ while ( (ch_obj->pending_cnt > 0) ||
+ (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == notify_mode) ) {
+
+ /* skip frames if needed */
+ mm_channel_superbuf_skip(ch_obj, &ch_obj->bundle.superbuf_queue);
+
+ /* dequeue */
+ node = mm_channel_superbuf_dequeue(&ch_obj->bundle.superbuf_queue);
+ if (NULL != node) {
+ /* decrease pending_cnt */
+ CDBG("%s: Super Buffer received, Call client callback",__func__);
+ if (MM_CAMERA_SUPER_BUF_NOTIFY_BURST == notify_mode) {
+ ch_obj->pending_cnt--;
+ }
+
+ if (mm_channel_need_do_pp(ch_obj, node)) {
+ /* do post processing */
+ ch_obj->pending_pp_cnt++;
+ mm_channel_do_post_processing(ch_obj, node);
+ /* no need to free node here
+ * node will be as cookie sent to backend doing pp */
+ } else {
+ /* dispatch superbuf */
+ if (NULL != ch_obj->bundle.super_buf_notify_cb) {
+ mm_camera_super_buf_t super_buf;
+ uint8_t i;
+
+ memset(&super_buf, 0, sizeof(mm_camera_super_buf_t));
+ super_buf.num_bufs = node->num_of_bufs;
+ for (i=0; i<node->num_of_bufs; i++) {
+ super_buf.bufs[i] = node->super_buf[i].buf;
+ }
+ super_buf.camera_handle = ch_obj->cam_obj->my_hdl;
+ super_buf.ch_id = ch_obj->my_hdl;
+
+ ch_obj->bundle.super_buf_notify_cb(&super_buf,
+ ch_obj->bundle.user_data);
+ } else {
+ /* buf done with the nonuse super buf */
+ uint8_t i;
+ for (i=0; i<node->num_of_bufs; i++) {
+ mm_channel_qbuf(ch_obj, node->super_buf[i].buf);
+ }
+ }
+ free(node);
+ }
+ } else {
+ /* no superbuf avail, break the loop */
+ CDBG_ERROR("%s : Superbuffer not available",__func__);
+ break;
+ }
+ }
+
+ /* unlock ch_lock */
+ pthread_mutex_unlock(&ch_obj->ch_lock);
+}
+
+/* state machine entry */
+int32_t mm_channel_fsm_fn(mm_channel_t *my_obj,
+ mm_channel_evt_type_t evt,
+ void * in_val,
+ void * out_val)
+{
+ int32_t rc = -1;
+
+ CDBG("%s : E state = %d",__func__,my_obj->state);
+ switch (my_obj->state) {
+ case MM_CHANNEL_STATE_NOTUSED:
+ rc = mm_channel_fsm_fn_notused(my_obj, evt, in_val, out_val);
+ break;
+ case MM_CHANNEL_STATE_STOPPED:
+ rc = mm_channel_fsm_fn_stopped(my_obj, evt, in_val, out_val);
+ break;
+ case MM_CHANNEL_STATE_ACTIVE:
+ rc = mm_channel_fsm_fn_active(my_obj, evt, in_val, out_val);
+ break;
+ case MM_CHANNEL_STATE_PAUSED:
+ rc = mm_channel_fsm_fn_paused(my_obj, evt, in_val, out_val);
+ break;
+ default:
+ CDBG("%s: Not a valid state (%d)", __func__, my_obj->state);
+ break;
+ }
+
+ /* unlock ch_lock */
+ pthread_mutex_unlock(&my_obj->ch_lock);
+ CDBG("%s : X rc = %d",__func__,rc);
+ return rc;
+}
+
+int32_t mm_channel_fsm_fn_notused(mm_channel_t *my_obj,
+ mm_channel_evt_type_t evt,
+ void * in_val,
+ void * out_val)
+{
+ int32_t rc = -1;
+
+ switch (evt) {
+ default:
+ CDBG_ERROR("%s: invalid state (%d) for evt (%d)",
+ __func__, my_obj->state, evt);
+ break;
+ }
+
+ return rc;
+}
+
+int32_t mm_channel_fsm_fn_stopped(mm_channel_t *my_obj,
+ mm_channel_evt_type_t evt,
+ void * in_val,
+ void * out_val)
+{
+ int32_t rc = -1;
+ CDBG("%s : E evt = %d",__func__,evt);
+ switch (evt) {
+ case MM_CHANNEL_EVT_ADD_STREAM:
+ {
+ uint32_t s_hdl = 0;
+ mm_evt_paylod_add_stream_t *payload =
+ (mm_evt_paylod_add_stream_t *)in_val;
+ s_hdl = mm_channel_add_stream(my_obj,
+ payload->buf_cb,
+ payload->user_data,
+ payload->ext_image_mode,
+ payload->sensor_idx);
+ *((uint32_t*)out_val) = s_hdl;
+ rc = 0;
+ }
+ break;
+ case MM_CHANNEL_EVT_DEL_STREAM:
+ {
+ uint32_t s_id = *((uint32_t *)in_val);
+ rc = mm_channel_del_stream(my_obj, s_id);
+ }
+ break;
+ case MM_CHANNEL_EVT_START_STREAM:
+ {
+ mm_evt_payload_start_stream_t *payload =
+ (mm_evt_payload_start_stream_t *)in_val;
+ rc = mm_channel_start_streams(my_obj,
+ payload->num_streams,
+ payload->stream_ids);
+ /* first stream started in stopped state
+ * move to active state */
+ if (0 == rc) {
+ my_obj->state = MM_CHANNEL_STATE_ACTIVE;
+ }
+ }
+ break;
+ case MM_CHANNEL_EVT_CONFIG_STREAM:
+ {
+ mm_evt_paylod_config_stream_t *payload =
+ (mm_evt_paylod_config_stream_t *)in_val;
+ rc = mm_channel_config_stream(my_obj,
+ payload->stream_id,
+ payload->config);
+ }
+ break;
+ case MM_CHANNEL_EVT_INIT_BUNDLE:
+ {
+ mm_evt_payload_bundle_stream_t *payload =
+ (mm_evt_payload_bundle_stream_t *)in_val;
+ rc = mm_channel_bundle_stream(my_obj,
+ payload->super_frame_notify_cb,
+ payload->user_data,
+ payload->attr,
+ payload->num_streams,
+ payload->stream_ids);
+ }
+ break;
+ case MM_CHANNEL_EVT_DESTROY_BUNDLE:
+ rc = mm_channel_destroy_bundle(my_obj);
+ break;
+ case MM_CHANNEL_EVT_PREPARE_SNAPSHOT:
+ {
+ uint32_t sensor_idx = (uint32_t)in_val;
+ rc = mm_channel_prepare_snapshot(my_obj, sensor_idx);
+ }
+ break;
+ case MM_CHANNEL_EVT_DELETE:
+ mm_channel_release(my_obj);
+ rc = 0;
+ break;
+ case MM_CHANNEL_EVT_SET_STREAM_PARM:
+ {
+ uint32_t s_id = (uint32_t)in_val;
+ rc = mm_channel_set_stream_parm(my_obj, s_id, out_val);
+ }
+ break;
+ case MM_CHANNEL_EVT_GET_STREAM_PARM:
+ {
+ uint32_t s_id = (uint32_t)in_val;
+ rc = mm_channel_get_stream_parm(my_obj, s_id, out_val);
+ }
+ break;
+ default:
+ CDBG_ERROR("%s: invalid state (%d) for evt (%d)",
+ __func__, my_obj->state, evt);
+ break;
+ }
+ CDBG("%s : E rc = %d",__func__,rc);
+ return rc;
+}
+
+int32_t mm_channel_fsm_fn_active(mm_channel_t *my_obj,
+ mm_channel_evt_type_t evt,
+ void * in_val,
+ void * out_val)
+{
+ int32_t rc = -1;
+
+ CDBG("%s : E evt = %d",__func__,evt);
+ switch (evt) {
+ case MM_CHANNEL_EVT_CONFIG_STREAM:
+ {
+ mm_evt_paylod_config_stream_t *payload =
+ (mm_evt_paylod_config_stream_t *)in_val;
+ rc = mm_channel_config_stream(my_obj,
+ payload->stream_id,
+ payload->config);
+ }
+ break;
+ case MM_CHANNEL_EVT_START_STREAM:
+ {
+ mm_evt_payload_start_stream_t *payload =
+ (mm_evt_payload_start_stream_t *)in_val;
+ rc = mm_channel_start_streams(my_obj,
+ payload->num_streams,
+ payload->stream_ids);
+ }
+ break;
+ case MM_CHANNEL_EVT_STOP_STREAM:
+ case MM_CHANNEL_EVT_TEARDOWN_STREAM:
+ {
+ int i;
+ uint8_t tear_down_flag = (MM_CHANNEL_EVT_TEARDOWN_STREAM == evt)? 1:0;
+ uint8_t all_stopped = 1;
+ mm_evt_payload_stop_stream_t *payload =
+ (mm_evt_payload_stop_stream_t *)in_val;
+
+ rc = mm_channel_stop_streams(my_obj,
+ payload->num_streams,
+ payload->stream_ids,
+ tear_down_flag);
+
+ /* check if all streams are stopped
+ * then we move to stopped state */
+
+ for (i=0; i<MM_CAMEAR_STRAEM_NUM_MAX; i++) {
+ if (MM_STREAM_STATE_ACTIVE_STREAM_ON == my_obj->streams[i].state ||
+ MM_STREAM_STATE_ACTIVE_STREAM_OFF == my_obj->streams[i].state) {
+ all_stopped = 0;
+ break;
+ }
+ }
+ if (all_stopped) {
+ my_obj->state = MM_CHANNEL_STATE_STOPPED;
+ }
+
+ }
+ break;
+ case MM_CHANNEL_EVT_INIT_BUNDLE:
+ {
+ mm_evt_payload_bundle_stream_t *payload =
+ (mm_evt_payload_bundle_stream_t *)in_val;
+ rc = mm_channel_bundle_stream(my_obj,
+ payload->super_frame_notify_cb,
+ payload->user_data,
+ payload->attr,
+ payload->num_streams,
+ payload->stream_ids);
+ }
+ break;
+ case MM_CHANNEL_EVT_DESTROY_BUNDLE:
+ rc = mm_channel_destroy_bundle(my_obj);
+ break;
+ case MM_CHANNEL_EVT_REQUEST_SUPER_BUF:
+ rc = mm_channel_request_super_buf(my_obj);
+ break;
+ case MM_CHANNEL_EVT_CANCEL_REQUEST_SUPER_BUF:
+ rc = mm_channel_cancel_super_buf_request(my_obj);
+ break;
+ case MM_CHANNEL_EVT_START_FOCUS:
+ {
+ mm_evt_payload_start_focus_t* payload =
+ (mm_evt_payload_start_focus_t *)in_val;
+ rc = mm_channel_start_focus(my_obj,
+ payload->sensor_idx,
+ payload->focus_mode);
+ }
+ break;
+ case MM_CHANNEL_EVT_ABORT_FOCUS:
+ {
+ uint32_t sensor_idx = (uint32_t)in_val;
+ rc = mm_channel_abort_focus(my_obj, sensor_idx);
+ }
+ break;
+ case MM_CHANNEL_EVT_PREPARE_SNAPSHOT:
+ {
+ uint32_t sensor_idx = (uint32_t)in_val;
+ rc = mm_channel_prepare_snapshot(my_obj, sensor_idx);
+ }
+ break;
+ case MM_CHANNEL_EVT_SET_STREAM_PARM:
+ {
+ uint32_t s_id = (uint32_t)in_val;
+ rc = mm_channel_set_stream_parm(my_obj, s_id, out_val);
+ }
+ break;
+ case MM_CHANNEL_EVT_GET_STREAM_PARM:
+ {
+ uint32_t s_id = (uint32_t)in_val;
+ rc = mm_channel_get_stream_parm(my_obj, s_id, out_val);
+ }
+ break;
+
+ case MM_CHANNEL_EVT_DEL_STREAM:
+ {
+ uint32_t s_id = *((uint32_t *)in_val);
+ rc = mm_channel_del_stream(my_obj, s_id);
+ }
+ break;
+ default:
+ CDBG_ERROR("%s: invalid state (%d) for evt (%d)",
+ __func__, my_obj->state, evt);
+ break;
+ }
+ CDBG("%s : X rc = %d",__func__,rc);
+ return rc;
+}
+
+int32_t mm_channel_fsm_fn_paused(mm_channel_t *my_obj,
+ mm_channel_evt_type_t evt,
+ void * in_val,
+ void * out_val)
+{
+ int32_t rc = -1;
+
+ /* currently we are not supporting pause/resume channel */
+ CDBG_ERROR("%s: evt (%d) not supported in state (%d)",
+ __func__, evt, my_obj->state);
+
+ return rc;
+}
+
+int32_t mm_channel_init(mm_channel_t *my_obj)
+{
+ int32_t rc = 0;
+ CDBG("%s : Launch data poll thread in channel open",__func__);
+ mm_camera_poll_thread_launch(&my_obj->poll_thread[0],
+ MM_CAMERA_POLL_TYPE_CH);
+
+ /* change state to stopped state */
+ my_obj->state = MM_CHANNEL_STATE_STOPPED;
+ return rc;
+}
+
+void mm_channel_release(mm_channel_t *my_obj)
+{
+ /* stop data poll thread */
+ mm_camera_poll_thread_release(&my_obj->poll_thread[0]);
+
+ /* change state to notused state */
+ my_obj->state = MM_CHANNEL_STATE_NOTUSED;
+}
+
+uint32_t mm_channel_add_stream(mm_channel_t *my_obj,
+ mm_camera_buf_notify_t buf_cb, void *user_data,
+ uint32_t ext_image_mode, uint32_t sensor_idx)
+{
+ int32_t rc = 0;
+ uint8_t idx = 0;
+ uint32_t s_hdl = 0;
+ mm_stream_t *stream_obj = NULL;
+
+ CDBG("%s : image mode = %d",__func__,ext_image_mode);
+ /* check available stream */
+ for (idx = 0; idx < MM_CAMEAR_STRAEM_NUM_MAX; idx++) {
+ if (MM_STREAM_STATE_NOTUSED == my_obj->streams[idx].state) {
+ stream_obj = &my_obj->streams[idx];
+ break;
+ }
+ }
+ if (NULL == stream_obj) {
+ CDBG_ERROR("%s: streams reach max, no more stream allowed to add", __func__);
+ return s_hdl;
+ }
+
+ /* initialize stream object */
+ memset(stream_obj, 0, sizeof(mm_stream_t));
+ stream_obj->my_hdl = mm_camera_util_generate_handler(idx);
+ stream_obj->ch_obj = my_obj;
+ /* cd through intf always palced at idx 0 of buf_cb */
+ stream_obj->buf_cb[0].cb = buf_cb;
+ stream_obj->buf_cb[0].user_data = user_data;
+ stream_obj->buf_cb[0].cb_count = -1; /* infinite by default */
+ stream_obj->ext_image_mode = ext_image_mode + 1;
+ stream_obj->sensor_idx = sensor_idx;
+ stream_obj->fd = -1;
+ pthread_mutex_init(&stream_obj->buf_lock, NULL);
+ pthread_mutex_init(&stream_obj->cb_lock, NULL);
+ stream_obj->state = MM_STREAM_STATE_INITED;
+
+ /* acquire stream */
+ rc = mm_stream_fsm_fn(stream_obj, MM_STREAM_EVT_ACQUIRE, NULL, NULL);
+ if (0 == rc) {
+ s_hdl = stream_obj->my_hdl;
+ } else {
+ /* error during acquire, de-init */
+ pthread_mutex_destroy(&stream_obj->buf_lock);
+ pthread_mutex_destroy(&stream_obj->cb_lock);
+ memset(stream_obj, 0, sizeof(mm_stream_t));
+ }
+ CDBG("%s : stream handle = %d",__func__,s_hdl);
+ return s_hdl;
+}
+
+int32_t mm_channel_del_stream(mm_channel_t *my_obj,
+ uint32_t stream_id)
+{
+ int rc = -1;
+ mm_stream_t * stream_obj = NULL;
+ stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
+
+ if (NULL == stream_obj) {
+ CDBG_ERROR("%s :Invalid Stream Object",__func__);
+ return rc;
+ }
+
+ rc = mm_stream_fsm_fn(stream_obj,
+ MM_STREAM_EVT_RELEASE,
+ NULL,
+ NULL);
+
+ return rc;
+}
+
+int32_t mm_channel_config_stream(mm_channel_t *my_obj,
+ uint32_t stream_id,
+ mm_camera_stream_config_t *config)
+{
+ int rc = -1;
+ mm_stream_t * stream_obj = NULL;
+ CDBG("%s : E stream ID = %d",__func__,stream_id);
+ stream_obj = mm_channel_util_get_stream_by_handler(my_obj, stream_id);
+
+ if (NULL == stream_obj) {
+ CDBG_ERROR("%s : X rc = %d",__func__,rc);
+ return rc;
+ }
+
+ /* set stream fmt */
+ rc = mm_stream_fsm_fn(stream_obj,
+ MM_STREAM_EVT_SET_FMT,
+ (void *)config,
+ NULL);
+ CDBG("%s : X rc = %d",__func__,rc);
+ return rc;
+}
+
+int32_t mm_channel_bundle_stream(mm_channel_t *my_obj,
+ mm_camera_buf_notify_t super_frame_notify_cb,
+ void *user_data,
+ mm_camera_bundle_attr_t *attr,
+ uint8_t num_streams,
+ uint32_t *stream_ids)
+{
+ int32_t rc = 0;
+ int i;
+ mm_stream_t* s_objs[MM_CAMEAR_MAX_STRAEM_BUNDLE] = {NULL};
+
+ /* first check if all streams to be bundled are valid */
+ for (i=0; i < num_streams; i++) {
+ s_objs[i] = mm_channel_util_get_stream_by_handler(my_obj, stream_ids[i]);
+ if (NULL == s_objs[i]) {
+ CDBG_ERROR("%s: invalid stream handler %d (idx=%d) to be bundled",
+ __func__, stream_ids[i], i);
+ return -1;
+ }
+ }
+
+ /* init superbuf queue */
+ mm_channel_superbuf_queue_init(&my_obj->bundle.superbuf_queue);
+
+ /* save bundle config */
+ memcpy(&my_obj->bundle.superbuf_queue.attr, attr, sizeof(mm_camera_bundle_attr_t));
+ my_obj->bundle.super_buf_notify_cb = super_frame_notify_cb;
+ my_obj->bundle.user_data = user_data;
+ my_obj->bundle.superbuf_queue.num_streams = num_streams;
+ my_obj->bundle.superbuf_queue.expected_frame_id = 0;
+
+ for (i=0; i < num_streams; i++) {
+ /* set bundled flag to streams */
+ s_objs[i]->is_bundled = 1;
+ /* init bundled streams to invalid value -1 */
+ //my_obj->bundle.superbuf_queue.bundled_streams[i] = -1;
+ my_obj->bundle.superbuf_queue.bundled_streams[i] = stream_ids[i];
+ }
+
+ /* launch cmd thread for super buf dataCB */
+ mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
+ mm_channel_process_stream_buf,
+ (void*)my_obj);
+
+ /* check if we need to do post-processing */
+ if (my_obj->cam_obj->need_pp) {
+ /* register postProcessingCB at camera evt polling thread
+ * because pp result is coming from ctrl evt */
+ mm_camera_register_event_notify_internal(my_obj->cam_obj,
+ mm_channel_pp_result_notify,
+ (void *)my_obj->my_hdl,
+ MM_CAMERA_EVT_TYPE_CTRL);
+ }
+
+ return rc;
+}
+
+/* bundled streams must all be stopped before bundle can be destroyed */
+int32_t mm_channel_destroy_bundle(mm_channel_t *my_obj)
+{
+
+ mm_camera_cmd_thread_release(&my_obj->cmd_thread);
+
+ /* deinit superbuf queue */
+ mm_channel_superbuf_queue_deinit(&my_obj->bundle.superbuf_queue);
+
+ /* memset bundle info */
+ memset(&my_obj->bundle, 0, sizeof(mm_channel_bundle_t));
+ return 0;
+}
+
+int32_t mm_channel_start_streams(mm_channel_t *my_obj,
+ uint8_t num_streams,
+ uint32_t *stream_ids)
+{
+ int32_t rc = 0;
+ int i, j;
+ mm_stream_t* s_objs[MM_CAMEAR_MAX_STRAEM_BUNDLE] = {NULL};
+ uint8_t num_streams_to_start = num_streams;
+ uint32_t streams_to_start[MM_CAMEAR_MAX_STRAEM_BUNDLE];
+ uint8_t bundle_to_start = 0;
+
+ /* check if any bundled stream to be start,
+ * then all bundled stream should be started */
+ memcpy(streams_to_start, stream_ids, sizeof(uint32_t) * num_streams);
+ for (i=0; i < num_streams; i++) {
+ for (j=0; j < my_obj->bundle.superbuf_queue.num_streams; j++) {
+ if (stream_ids[i] == my_obj->bundle.superbuf_queue.bundled_streams[j]) {
+ bundle_to_start = 1;
+ break;
+ }
+ }
+ }
+
+ if (bundle_to_start) {
+ uint8_t need_add;
+ /* add bundled streams into the start list if not already added*/
+ for (i=0; i<my_obj->bundle.superbuf_queue.num_streams; i++) {
+ need_add = 1;
+ for (j=0; j<num_streams; j++) {
+ if (stream_ids[j] == my_obj->bundle.superbuf_queue.bundled_streams[i]) {
+ need_add = 0;
+ break;
+ }
+ }
+ if (need_add) {
+ streams_to_start[num_streams_to_start++] =
+ my_obj->bundle.superbuf_queue.bundled_streams[i];
+ }
+ }
+ }
+
+ /* check if all streams to be started are valid */
+ for (i=0; i<num_streams_to_start; i++) {
+ s_objs[i] = mm_channel_util_get_stream_by_handler(my_obj, streams_to_start[i]);
+
+ if (NULL == s_objs[i]) {
+ CDBG_ERROR("%s: invalid stream handler %d (idx=%d) to be started",
+ __func__, streams_to_start[i], i);
+ return -1;
+ }
+ }
+
+ for (i=0; i<num_streams_to_start; i++) {
+ /* allocate buf */
+ rc = mm_stream_fsm_fn(s_objs[i],
+ MM_STREAM_EVT_GET_BUF,
+ NULL,
+ NULL);
+ if (0 != rc) {
+ CDBG_ERROR("%s: get buf failed at idx(%d)", __func__, i);
+ break;
+ }
+
+ /* reg buf */
+ rc = mm_stream_fsm_fn(s_objs[i],
+ MM_STREAM_EVT_REG_BUF,
+ NULL,
+ NULL);
+ if (0 != rc) {
+ CDBG_ERROR("%s: reg buf failed at idx(%d)", __func__, i);
+ break;
+ }
+
+ /* TODO */
+ /* for now, hard-coded to 1 for main image stream */
+ /* Query if stream need to do pp under current hardware configuration,
+ * when camera has offline pp capability */
+ if (my_obj->cam_obj->need_pp) {
+ if (MSM_V4L2_EXT_CAPTURE_MODE_MAIN == s_objs[i]->ext_image_mode) {
+ s_objs[i]->is_pp_needed = 1;
+ } else {
+ s_objs[i]->is_pp_needed = 0;
+ }
+ }
+
+ /* start stream */
+ rc = mm_stream_fsm_fn(s_objs[i],
+ MM_STREAM_EVT_START,
+ NULL,
+ NULL);
+ if (0 != rc) {
+ CDBG_ERROR("%s: start stream failed at idx(%d)", __func__, i);
+ break;
+ }
+ }
+
+ /* error handling */
+ if (0 != rc) {
+ for (j=0; j<=i; j++) {
+ /* stop streams*/
+ mm_stream_fsm_fn(s_objs[i],
+ MM_STREAM_EVT_STOP,
+ NULL,
+ NULL);
+
+ /* unreg buf */
+ mm_stream_fsm_fn(s_objs[i],
+ MM_STREAM_EVT_UNREG_BUF,
+ NULL,
+ NULL);
+
+ /* put buf back */
+ mm_stream_fsm_fn(s_objs[i],
+ MM_STREAM_EVT_PUT_BUF,
+ NULL,
+ NULL);
+ }
+ }
+
+ return rc;
+}
+
+/* Required: bundled streams need to be stopped together */
+int32_t mm_channel_stop_streams(mm_channel_t *my_obj,
+ uint8_t num_streams,
+ uint32_t *stream_ids,
+ uint8_t tear_down_flag)
+{
+ int32_t rc = 0;
+ int i, j;
+ mm_stream_t* s_objs[MM_CAMEAR_MAX_STRAEM_BUNDLE] = {NULL};
+ uint8_t num_streams_to_stop = num_streams;
+ uint32_t streams_to_stop[MM_CAMEAR_MAX_STRAEM_BUNDLE];
+ uint8_t bundle_to_stop = 0;
+
+ /* make sure bundled streams are stopped together */
+ memcpy(streams_to_stop, stream_ids, sizeof(uint32_t) * num_streams);
+ for (i=0; i<num_streams; i++) {
+ for (j=0; j<my_obj->bundle.superbuf_queue.num_streams; j++) {
+ if (stream_ids[i] == my_obj->bundle.superbuf_queue.bundled_streams[j]) {
+ bundle_to_stop = 1;
+ break;
+ }
+ }
+ }
+ if (bundle_to_stop) {
+ uint8_t need_add;
+ /* add bundled streams into the start list if not already added*/
+ for (i=0; i<my_obj->bundle.superbuf_queue.num_streams; i++) {
+ need_add = 1;
+ for (j=0; j<num_streams; j++) {
+ if (stream_ids[j] == my_obj->bundle.superbuf_queue.bundled_streams[i]) {
+ need_add = 0;
+ break;
+ }
+ }
+ if (need_add) {
+ streams_to_stop[num_streams_to_stop++] =
+ my_obj->bundle.superbuf_queue.bundled_streams[i];
+ }
+ }
+ }
+
+ for (i=0; i<num_streams_to_stop; i++) {
+ s_objs[i] = mm_channel_util_get_stream_by_handler(my_obj, streams_to_stop[i]);
+
+ if (NULL != s_objs[i]) {
+ /* stream off */
+ mm_stream_fsm_fn(s_objs[i],
+ MM_STREAM_EVT_STOP,
+ NULL,
+ NULL);
+
+ /* unreg buf at kernel */
+ mm_stream_fsm_fn(s_objs[i],
+ MM_STREAM_EVT_UNREG_BUF,
+ NULL,
+ NULL);
+ }
+ }
+
+ /* since all streams are stopped, we are safe to
+ * release all buffers allocated in stream */
+ for (i=0; i<num_streams_to_stop; i++) {
+ if (NULL != s_objs[i]) {
+ /* put buf back */
+ mm_stream_fsm_fn(s_objs[i],
+ MM_STREAM_EVT_PUT_BUF,
+ NULL,
+ NULL);
+
+ if (tear_down_flag) {
+ /* to tear down stream totally, stream needs to be released */
+ mm_stream_fsm_fn(s_objs[i],
+ MM_STREAM_EVT_RELEASE,
+ NULL,
+ NULL);
+ }
+ }
+ }
+
+ return rc;
+}
+
+int32_t mm_channel_request_super_buf(mm_channel_t *my_obj)
+{
+ int32_t rc = 0;
+ mm_camera_cmdcb_t* node = NULL;
+
+ /* set pending_cnt
+ * will trigger dispatching super frames if pending_cnt > 0 */
+ my_obj->pending_cnt = my_obj->bundle.superbuf_queue.attr.burst_num;
+
+ /* send sem_post to wake up cmd thread to dispatch super buffer */
+ node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
+ if (NULL != node) {
+ memset(node, 0, sizeof(mm_camera_cmdcb_t));
+ node->cmd_type = MM_CAMERA_CMD_TYPE_REQ_DATA_CB;
+
+ /* enqueue to cmd thread */
+ mm_camera_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
+
+ /* wake up cmd thread */
+ sem_post(&(my_obj->cmd_thread.cmd_sem));
+ } else {
+ CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
+ rc = -1;
+ }
+
+ return rc;
+}
+
+int32_t mm_channel_cancel_super_buf_request(mm_channel_t *my_obj)
+{
+ int32_t rc = 0;
+ /* reset pending_cnt */
+ my_obj->pending_cnt = 0;
+
+ if (my_obj->pending_pp_cnt > 0) {
+ rc = mm_channel_cancel_post_processing(my_obj);
+ }
+ my_obj->pending_pp_cnt = 0;
+ return rc;
+}
+
+int32_t mm_channel_qbuf(mm_channel_t *my_obj,
+ mm_camera_buf_def_t *buf)
+{
+ int32_t rc = -1;
+ struct ion_flush_data cache_inv_data;
+ int ion_fd;
+ struct msm_frame *cache_frame;
+ struct msm_frame *cache_frame1 = NULL;
+
+ mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, buf->stream_id);
+
+ if (NULL != s_obj) {
+ rc = mm_stream_fsm_fn(s_obj,
+ MM_STREAM_EVT_QBUF,
+ (void *)buf,
+ NULL);
+ }
+
+#ifdef USE_ION
+ cache_inv_data.vaddr = cache_frame->buffer;
+ cache_inv_data.fd = cache_frame->fd;
+ cache_inv_data.handle = cache_frame->fd_data.handle;
+ cache_inv_data.length = cache_frame->ion_alloc.len;
+ ion_fd = cache_frame->ion_dev_fd;
+ if(ion_fd > 0) {
+ if(ioctl(ion_fd, ION_IOC_INV_CACHES, &cache_inv_data) < 0)
+ CDBG_ERROR("%s: Cache Invalidate failed\n", __func__);
+ else {
+ CDBG("%s: Successful cache invalidate\n", __func__);
+ if(cache_frame1) {
+ ion_fd = cache_frame1->ion_dev_fd;
+ cache_inv_data.vaddr = cache_frame1->buffer;
+ cache_inv_data.fd = cache_frame1->fd;
+ cache_inv_data.handle = cache_frame1->fd_data.handle;
+ cache_inv_data.length = cache_frame1->ion_alloc.len;
+ if(ioctl(ion_fd, ION_IOC_INV_CACHES, &cache_inv_data) < 0)
+ CDBG_ERROR("%s: Cache Invalidate failed\n", __func__);
+ else
+ CDBG("%s: Successful cache invalidate\n", __func__);
+ }
+ }
+ }
+#endif
+
+ return rc;
+}
+
+int32_t mm_channel_start_focus(mm_channel_t *my_obj,
+ uint32_t sensor_idx,
+ uint32_t focus_mode)
+{
+ return mm_camera_send_native_ctrl_cmd(my_obj->cam_obj,
+ CAMERA_SET_PARM_AUTO_FOCUS,
+ sizeof(uint32_t), (void*)focus_mode);
+}
+
+int32_t mm_channel_abort_focus(mm_channel_t *my_obj, uint32_t sensor_idx)
+{
+ return mm_camera_send_native_ctrl_cmd(my_obj->cam_obj,
+ CAMERA_AUTO_FOCUS_CANCEL,
+ 0, NULL);
+}
+
+int32_t mm_channel_prepare_snapshot(mm_channel_t *my_obj, uint32_t sensor_idx)
+{
+ return mm_camera_send_native_ctrl_timeout_cmd(my_obj->cam_obj,
+ CAMERA_PREPARE_SNAPSHOT,
+ 0, NULL, 2000);
+}
+
+int32_t mm_channel_set_stream_parm(mm_channel_t *my_obj,
+ uint32_t s_id,
+ void *value)
+{
+ int32_t rc = -1;
+ mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, s_id);
+ if (NULL != s_obj) {
+ rc = mm_stream_fsm_fn(s_obj,
+ MM_STREAM_EVT_SET_PARM,
+ value,
+ NULL);
+ }
+
+ return rc;
+}
+
+int32_t mm_channel_get_stream_parm(mm_channel_t *my_obj,
+ uint32_t s_id,
+ void *value)
+{
+ int32_t rc = -1;
+ mm_stream_t* s_obj = mm_channel_util_get_stream_by_handler(my_obj, s_id);
+ if (NULL != s_obj) {
+ rc = mm_stream_fsm_fn(s_obj,
+ MM_STREAM_EVT_GET_PARM,
+ NULL,
+ value);
+ }
+
+ return rc;
+}
+
+uint8_t mm_channel_need_do_pp(mm_channel_t *my_obj,
+ mm_channel_queue_node_t *super_buf)
+{
+ uint8_t need_pp = 0;
+ uint8_t i;
+
+ for (i=0; i<super_buf->num_of_bufs; i++) {
+ if (super_buf->super_buf[i].need_pp) {
+ need_pp = 1;
+ break;
+ }
+ }
+ return need_pp;
+}
+
+int32_t mm_channel_do_post_processing(mm_channel_t *my_obj,
+ mm_channel_queue_node_t *super_buf)
+{
+ int32_t rc = 0;
+ cam_sock_packet_t packet;
+ uint8_t i;
+ mm_stream_t* s_obj = NULL;
+ mm_channel_pp_info_t *cookie = NULL;
+
+ /* TODO : currently we only do WNR, may need extended PP */
+ /* send cmd to backend to start pp */
+ for (i=0; i<super_buf->num_of_bufs; i++) {
+ if (super_buf->super_buf[i].need_pp) {
+ s_obj = mm_channel_util_get_stream_by_handler(my_obj, super_buf->super_buf[i].stream_id);
+ if (NULL != s_obj) {
+ cookie = (mm_channel_pp_info_t*)malloc(sizeof(mm_channel_pp_info_t));
+ if (NULL != cookie) {
+ memset(&packet, 0, sizeof(cam_sock_packet_t));
+ memset(cookie, 0, sizeof(mm_channel_pp_info_t));
+ cookie->cam_hdl = my_obj->cam_obj->my_hdl;
+ cookie->ch_hdl = my_obj->my_hdl;
+ cookie->stream_hdl = s_obj->my_hdl;
+ cookie->super_buf = super_buf;
+
+ packet.msg_type = CAM_SOCK_MSG_TYPE_WDN_START;
+ packet.payload.wdn_start.cookie = (unsigned long)cookie;
+ packet.payload.wdn_start.num_frames = 1;
+ packet.payload.wdn_start.ext_mode[0] = s_obj->ext_image_mode;
+ packet.payload.wdn_start.frame_idx[0] = super_buf->super_buf[i].buf->buf_idx;
+ rc = mm_camera_util_sendmsg(my_obj->cam_obj, &packet, sizeof(packet), 0);
+ if (0 != rc) {
+ CDBG_ERROR("%s: Send DoPP msg failed (rc=%d)", __func__, rc);
+ free(cookie);
+ break;
+ }
+ } else {
+ CDBG_ERROR("%s: No memory for mm_channel_pp_info_t", __func__);
+ break;
+ }
+ }
+ }
+ }
+
+ return rc;
+}
+
+int32_t mm_channel_cancel_post_processing(mm_channel_t *my_obj)
+{
+ int32_t rc = 0;
+ /* TODO */
+ /* need send cmd to backend to cancel all pp request */
+
+ return rc;
+}
+
+int32_t mm_channel_reg_stream_cb(mm_channel_t *my_obj,
+ mm_stream_data_cb_t *cb,
+ uint32_t ext_image_mode,
+ uint32_t sensor_idx)
+{
+ uint8_t idx;
+ mm_stream_t *dest_stream = NULL;
+ int32_t rc = -1;
+
+ /* browse all streams in channel to find the destination */
+ for (idx=0; idx < MM_CAMEAR_STRAEM_NUM_MAX; idx++) {
+ if (my_obj->streams[idx].state != MM_STREAM_STATE_NOTUSED &&
+ my_obj->streams[idx].ext_image_mode == ext_image_mode &&
+ my_obj->streams[idx].sensor_idx == sensor_idx) {
+ /* find matching stream as the destination */
+ dest_stream = &my_obj->streams[idx];
+ break;
+ }
+ }
+
+ if (NULL != dest_stream) {
+ rc = mm_stream_reg_buf_cb(dest_stream, cb);
+ }
+
+ return rc;
+}
+
+int32_t mm_channel_superbuf_queue_init(mm_channel_queue_t * queue)
+{
+ return mm_camera_queue_init(&queue->que);
+}
+
+int32_t mm_channel_superbuf_queue_deinit(mm_channel_queue_t * queue)
+{
+ return mm_camera_queue_deinit(&queue->que);
+}
+
+int8_t mm_channel_util_seq_comp_w_rollover(uint32_t v1,
+ uint32_t v2)
+{
+ int8_t ret = 0;
+
+ /* TODO: need to handle the case if v2 roll over to 0 */
+ if (v1 > v2) {
+ ret = 1;
+ } else if (v1 < v2) {
+ ret = -1;
+ }
+
+ return ret;
+}
+
+int32_t mm_channel_superbuf_comp_and_enqueue(
+ mm_channel_t* ch_obj,
+ mm_channel_queue_t * queue,
+ mm_camera_buf_info_t *buf_info)
+{
+ mm_camera_q_node_t* node = NULL;
+ struct cam_list *head = NULL;
+ struct cam_list *pos = NULL;
+ mm_channel_queue_node_t* super_buf = NULL;
+ uint8_t buf_s_idx, i;
+
+ for (buf_s_idx=0; buf_s_idx < queue->num_streams; buf_s_idx++) {
+ if (buf_info->stream_id == queue->bundled_streams[buf_s_idx]) {
+ break;
+ }
+ }
+ if (buf_s_idx == queue->num_streams) {
+ CDBG_ERROR("%s: buf from stream (%d) not bundled", __func__, buf_info->stream_id);
+ return -1;
+ }
+
+ if (mm_channel_util_seq_comp_w_rollover(buf_info->frame_idx,
+ queue->expected_frame_id) < 0) {
+ /* incoming buf is older than expected buf id, will discard it */
+ mm_channel_qbuf(ch_obj, buf_info->buf);
+ return 0;
+ }
+
+ if (MM_CAMERA_SUPER_BUF_PRIORITY_NORMAL != queue->attr.priority) {
+ /* TODO */
+ /* need to decide if we want to queue the frame based on focus or exposure
+ * if frame not to be queued, we need to qbuf it back */
+ }
+
+ /* comp */
+ pthread_mutex_lock(&queue->que.lock);
+ head = &queue->que.head.list;
+ /* get the last one in the queue which is possibly having no matching */
+ pos = head->next;
+ while (pos != head) {
+ node = member_of(pos, mm_camera_q_node_t, list);
+ super_buf = (mm_channel_queue_node_t*)node->data;
+ if (NULL != super_buf) {
+ if (super_buf->matched) {
+ /* find a matched super buf, move to next one */
+ pos = pos->next;
+ continue;
+ } else {
+ /* have an unmatched super buf, break the loop */
+ break;
+ }
+ }
+ }
+
+ if (pos == head) {
+ /* all nodes in queue are mtached, or no node in queue
+ * create a new node */
+ mm_channel_queue_node_t *new_buf = NULL;
+ mm_camera_q_node_t* new_node = NULL;
+
+ new_buf = (mm_channel_queue_node_t*)malloc(sizeof(mm_channel_queue_node_t));
+ new_node = (mm_camera_q_node_t*)malloc(sizeof(mm_camera_q_node_t));
+ if (NULL != new_buf && NULL != new_node) {
+ memset(new_buf, 0, sizeof(mm_channel_queue_node_t));
+ memset(new_node, 0, sizeof(mm_camera_q_node_t));
+ new_node->data = (void *)new_buf;
+ new_buf->num_of_bufs = queue->num_streams;
+ memcpy(&new_buf->super_buf[buf_s_idx], buf_info, sizeof(mm_camera_buf_info_t));
+
+ /* enqueue */
+ //cam_list_add_tail_node(&node->list, &queue->que.head.list);
+ cam_list_add_tail_node(&new_node->list, &queue->que.head.list);
+ queue->que.size++;
+
+ if(queue->num_streams == 1) {
+ //TODO : Check. Live snapshot will have one stream in bundle?
+ new_buf->matched = 1;
+
+ if (new_buf->matched) {
+ queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip;
+ queue->match_cnt++;
+ }
+ }
+ } else {
+ /* No memory */
+ if (NULL != new_buf) {
+ free(new_buf);
+ }
+ if (NULL != new_node) {
+ free(new_node);
+ }
+ /* qbuf the new buf since we cannot enqueue */
+ mm_channel_qbuf(ch_obj, buf_info->buf);
+ }
+ } else {
+ /* find an unmatched super buf */
+ if (super_buf->super_buf[buf_s_idx].frame_idx == 0) {
+ /* new frame from the stream_id */
+ uint8_t is_new = 1;
+ uint32_t frame_idx;
+
+ for (i=0; i < super_buf->num_of_bufs; i++) {
+ //for (i=0; i < buf_s_idx; i++) {
+ if(super_buf->super_buf[i].buf == NULL) {
+ continue;
+ }
+ frame_idx = super_buf->super_buf[i].buf->frame_idx;
+ if (frame_idx == 0) {
+ continue;
+ }
+ if (frame_idx < buf_info->frame_idx) {
+ /* existing frame is older than the new frame, qbuf it */
+ mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
+ memset(&super_buf->super_buf[i], 0, sizeof(mm_camera_buf_info_t));
+ } else if (frame_idx > buf_info->frame_idx) {
+ /* new frame is older */
+ is_new = 0;
+ break;
+ }else{
+ //TODO: reveiw again
+ break;
+ }
+ }
+ if (is_new) {
+ memcpy(&super_buf->super_buf[buf_s_idx], buf_info, sizeof(mm_camera_buf_info_t));
+
+ /* check if superbuf is all matched */
+ super_buf->matched = 1;
+ for (i=0; i < super_buf->num_of_bufs; i++) {
+ if (super_buf->super_buf[i].frame_idx == 0) {
+ super_buf->matched = 0;
+ break;
+ }
+ }
+
+ if (super_buf->matched) {
+ queue->expected_frame_id = buf_info->frame_idx + queue->attr.post_frame_skip;
+ queue->match_cnt++;
+ }
+ } else {
+ mm_channel_qbuf(ch_obj, buf_info->buf);
+ }
+ } else {
+ if (super_buf->super_buf[buf_s_idx].frame_idx < buf_info->frame_idx) {
+ /* current frames in superbuf are older than the new frame
+ * qbuf all current frames */
+ for (i=0; i<super_buf->num_of_bufs; i++) {
+ if (super_buf->super_buf[i].frame_idx != 0) {
+ mm_channel_qbuf(ch_obj, super_buf->super_buf[i].buf);
+ memset(&super_buf->super_buf[i], 0, sizeof(mm_camera_buf_info_t));
+ }
+ }
+ /* add the new frame into the superbuf */
+ memcpy(&super_buf->super_buf[buf_s_idx], buf_info, sizeof(mm_camera_buf_info_t));
+ } else {
+ /* the new frame is older, just ignor */
+ mm_channel_qbuf(ch_obj, buf_info->buf);
+ }
+ }
+ }
+ pthread_mutex_unlock(&queue->que.lock);
+
+ return 0;
+}
+
+mm_channel_queue_node_t* mm_channel_superbuf_dequeue_internal(mm_channel_queue_t * queue)
+{
+ mm_camera_q_node_t* node = NULL;
+ struct cam_list *head = NULL;
+ struct cam_list *pos = NULL;
+ mm_channel_queue_node_t* super_buf = NULL;
+
+ head = &queue->que.head.list;
+ pos = head->next;
+ if (pos != head) {
+ /* get the first node */
+ node = member_of(pos, mm_camera_q_node_t, list);
+ super_buf = (mm_channel_queue_node_t*)node->data;
+ if (NULL != super_buf) {
+ if (super_buf->matched) {
+ /* we found a mtaching super buf, dequeue it */
+ cam_list_del_node(&node->list);
+ queue->que.size--;
+ queue->match_cnt--;
+ free(node);
+ } else {
+ super_buf = NULL;
+ }
+ }
+ }
+
+ return super_buf;
+}
+
+mm_channel_queue_node_t* mm_channel_superbuf_dequeue(mm_channel_queue_t * queue)
+{
+ mm_camera_q_node_t* node = NULL;
+ struct cam_list *head = NULL;
+ struct cam_list *pos = NULL;
+ mm_channel_queue_node_t* super_buf = NULL;
+
+ pthread_mutex_lock(&queue->que.lock);
+ super_buf = mm_channel_superbuf_dequeue_internal(queue);
+ pthread_mutex_unlock(&queue->que.lock);
+
+ return super_buf;
+}
+
+int32_t mm_channel_superbuf_bufdone_overflow(mm_channel_t* my_obj,
+ mm_channel_queue_t * queue)
+{
+ int32_t rc = 0, i;
+ mm_channel_queue_node_t* super_buf = NULL;
+ if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
+ /* for continuous streaming mode, no overflow is needed */
+ return 0;
+ }
+
+ /* bufdone overflowed bufs */
+ pthread_mutex_lock(&queue->que.lock);
+ while (queue->match_cnt > queue->attr.water_mark) {
+ super_buf = mm_channel_superbuf_dequeue_internal(queue);
+ if (NULL != super_buf) {
+ for (i=0; i<super_buf->num_of_bufs; i++) {
+ if (NULL != super_buf->super_buf[i].buf) {
+ mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
+ }
+ }
+ free(super_buf);
+ }
+ }
+ pthread_mutex_unlock(&queue->que.lock);
+
+ return rc;
+}
+
+int32_t mm_channel_superbuf_skip(mm_channel_t* my_obj,
+ mm_channel_queue_t * queue)
+{
+ int32_t rc = 0, i, count;
+ mm_channel_queue_node_t* super_buf = NULL;
+ if (MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS == queue->attr.notify_mode) {
+ /* for continuous streaming mode, no skip is needed */
+ return 0;
+ }
+
+ /* bufdone overflowed bufs */
+ pthread_mutex_lock(&queue->que.lock);
+ while (queue->match_cnt > queue->attr.look_back) {
+ super_buf = mm_channel_superbuf_dequeue_internal(queue);
+ if (NULL != super_buf) {
+ for (i=0; i<super_buf->num_of_bufs; i++) {
+ if (NULL != super_buf->super_buf[i].buf) {
+ mm_channel_qbuf(my_obj, super_buf->super_buf[i].buf);
+ }
+ }
+ free(super_buf);
+ }
+ }
+ pthread_mutex_unlock(&queue->que.lock);
+
+ return rc;
+}
+
diff --git a/camera/QCamera/stack/mm-camera-interface/src/mm_camera_data.c b/camera/QCamera/stack/mm-camera-interface/src/mm_camera_data.c
new file mode 100755
index 0000000..b55e617
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-interface/src/mm_camera_data.c
@@ -0,0 +1,228 @@
+/*
+Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <camera.h>
+#include <semaphore.h>
+
+#include "mm_camera_dbg.h"
+#include "mm_camera_interface.h"
+#include "mm_camera.h"
+
+#if 0
+#undef CDBG
+#undef LOG_TAG
+#define CDBG ALOGE
+#define LOG_TAG "NotifyLogs"
+#endif
+
+int32_t mm_camera_queue_init(mm_camera_queue_t* queue)
+{
+ pthread_mutex_init(&queue->lock, NULL);
+ cam_list_init(&queue->head.list);
+ queue->size = 0;
+ return 0;
+}
+
+int32_t mm_camera_queue_enq(mm_camera_queue_t* queue, void* data)
+{
+ mm_camera_q_node_t* node =
+ (mm_camera_q_node_t *)malloc(sizeof(mm_camera_q_node_t));
+ if (NULL == node) {
+ CDBG_ERROR("%s: No memory for mm_camera_q_node_t", __func__);
+ return -1;
+ }
+
+ memset(node, 0, sizeof(mm_camera_q_node_t));
+ node->data = data;
+
+ pthread_mutex_lock(&queue->lock);
+ cam_list_add_tail_node(&node->list, &queue->head.list);
+ queue->size++;
+ pthread_mutex_unlock(&queue->lock);
+
+ return 0;
+
+}
+
+void* mm_camera_queue_deq(mm_camera_queue_t* queue)
+{
+ mm_camera_q_node_t* node = NULL;
+ void* data = NULL;
+ struct cam_list *head = NULL;
+ struct cam_list *pos = NULL;
+
+ pthread_mutex_lock(&queue->lock);
+ head = &queue->head.list;
+ pos = head->next;
+ if (pos != head) {
+ node = member_of(pos, mm_camera_q_node_t, list);
+ cam_list_del_node(&node->list);
+ queue->size--;
+ }
+ pthread_mutex_unlock(&queue->lock);
+
+ if (NULL != node) {
+ data = node->data;
+ free(node);
+ }
+
+ return data;
+}
+
+int32_t mm_camera_queue_deinit(mm_camera_queue_t* queue)
+{
+ mm_camera_queue_flush(queue);
+ pthread_mutex_destroy(&queue->lock);
+ return 0;
+}
+
+int32_t mm_camera_queue_flush(mm_camera_queue_t* queue)
+{
+ mm_camera_q_node_t* node = NULL;
+ void* data = NULL;
+ struct cam_list *head = NULL;
+ struct cam_list *pos = NULL;
+
+ pthread_mutex_lock(&queue->lock);
+ head = &queue->head.list;
+ pos = head->next;
+
+ while(pos != head) {
+ node = member_of(pos, mm_camera_q_node_t, list);
+ cam_list_del_node(&node->list);
+ queue->size--;
+
+ /* TODO later to consider ptr inside data */
+ /* for now we only assume there is no ptr inside data
+ * so we free data directly */
+ if (NULL != node->data) {
+ free(node->data);
+ }
+ free(node);
+ pos = pos->next;
+ }
+ queue->size = 0;
+ pthread_mutex_unlock(&queue->lock);
+ return 0;
+}
+
+static void *mm_camera_cmd_thread(void *data)
+{
+ int rc = 0;
+ int running = 1;
+ int ret;
+ mm_camera_cmd_thread_t *cmd_thread =
+ (mm_camera_cmd_thread_t *)data;
+ mm_camera_cmdcb_t* node = NULL;
+
+ do {
+ do {
+ ret = sem_wait(&cmd_thread->cmd_sem);
+ if (ret != 0 && errno != EINVAL) {
+ CDBG_ERROR("%s: sem_wait error (%s)",
+ __func__, strerror(errno));
+ return NULL;
+ }
+ } while (ret != 0);
+
+ /* we got notified about new cmd avail in cmd queue */
+ node = (mm_camera_cmdcb_t*)mm_camera_queue_deq(&cmd_thread->cmd_queue);
+ if (node != NULL) {
+ switch (node->cmd_type) {
+ case MM_CAMERA_CMD_TYPE_EVT_CB:
+ case MM_CAMERA_CMD_TYPE_DATA_CB:
+ case MM_CAMERA_CMD_TYPE_ASYNC_CB:
+ case MM_CAMERA_CMD_TYPE_REQ_DATA_CB:
+ if (NULL != cmd_thread->cb) {
+ cmd_thread->cb(node, cmd_thread->user_data);
+ }
+ break;
+ case MM_CAMERA_CMD_TYPE_EXIT:
+ default:
+ running = 0;
+ break;
+ }
+ free(node);
+ }
+ } while (running);
+ return NULL;
+}
+
+int32_t mm_camera_cmd_thread_launch(mm_camera_cmd_thread_t * cmd_thread,
+ mm_camera_cmd_cb_t cb,
+ void* user_data)
+{
+ int32_t rc = 0;
+
+ sem_init(&cmd_thread->cmd_sem, 0, 0);
+ mm_camera_queue_init(&cmd_thread->cmd_queue);
+ cmd_thread->cb = cb;
+ cmd_thread->user_data = user_data;
+
+ /* launch the thread */
+ pthread_create(&cmd_thread->cmd_pid,
+ NULL,
+ mm_camera_cmd_thread,
+ (void *)cmd_thread);
+ return rc;
+}
+
+int32_t mm_camera_cmd_thread_release(mm_camera_cmd_thread_t * cmd_thread)
+{
+ int32_t rc = 0;
+ mm_camera_buf_info_t buf_info;
+ mm_camera_cmdcb_t* node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
+ if (NULL == node) {
+ CDBG_ERROR("%s: No memory for mm_camera_cmdcb_t", __func__);
+ return -1;
+ }
+
+ memset(node, 0, sizeof(mm_camera_cmdcb_t));
+ node->cmd_type = MM_CAMERA_CMD_TYPE_EXIT;
+
+ mm_camera_queue_enq(&cmd_thread->cmd_queue, node);
+ sem_post(&cmd_thread->cmd_sem);
+
+ /* wait until cmd thread exits */
+ if (pthread_join(cmd_thread->cmd_pid, NULL) != 0) {
+ CDBG("%s: pthread dead already\n", __func__);
+ }
+ mm_camera_queue_deinit(&cmd_thread->cmd_queue);
+
+ sem_destroy(&cmd_thread->cmd_sem);
+ memset(cmd_thread, 0, sizeof(mm_camera_cmd_thread_t));
+ return rc;
+}
+
diff --git a/camera/QCamera/stack/mm-camera-interface/src/mm_camera_helper.c b/camera/QCamera/stack/mm-camera-interface/src/mm_camera_helper.c
new file mode 100755
index 0000000..da5b61d
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-interface/src/mm_camera_helper.c
@@ -0,0 +1,318 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include "mm_camera_dbg.h"
+#include <time.h>
+#include "mm_camera_interface.h"
+#include <linux/ion.h>
+
+#define MM_CAMERA_PROFILE 1
+
+struct file;
+struct inode;
+struct vm_area_struct;
+
+/*===========================================================================
+ * FUNCTION - do_mmap -
+ *
+ * DESCRIPTION: retured virtual addresss
+ *==========================================================================*/
+uint8_t *mm_camera_do_mmap(uint32_t size, int *pmemFd)
+{
+ void *ret; /* returned virtual address */
+ int pmem_fd = open("/dev/pmem_adsp", O_RDWR|O_SYNC);
+
+ if (pmem_fd <= 0) {
+ CDBG("do_mmap: Open device /dev/pmem_adsp failed!\n");
+ return NULL;
+ }
+ /* to make it page size aligned */
+ size = (size + 4095) & (~4095);
+ ret = mmap(NULL,
+ size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ pmem_fd,
+ 0);
+ if (ret == MAP_FAILED) {
+ CDBG("do_mmap: pmem mmap() failed: %s (%d)\n", strerror(errno), errno);
+ close(pmem_fd);
+ return NULL;
+ }
+ CDBG("do_mmap: pmem mmap fd %d ptr %p len %u\n", pmem_fd, ret, size);
+ *pmemFd = pmem_fd;
+ return(uint8_t *)ret;
+}
+
+/*===========================================================================
+ * FUNCTION - do_munmap -
+ *
+ * DESCRIPTION:
+ *==========================================================================*/
+int mm_camera_do_munmap(int pmem_fd, void *addr, size_t size)
+{
+ int rc;
+
+ if (pmem_fd <= 0) {
+ CDBG("%s:invalid fd=%d\n", __func__, pmem_fd);
+ return -1;
+ }
+ size = (size + 4095) & (~4095);
+ CDBG("munmapped size = %d, virt_addr = 0x%p\n",
+ size, addr);
+ rc = (munmap(addr, size));
+ close(pmem_fd);
+ CDBG("do_mmap: pmem munmap fd %d ptr %p len %u rc %d\n", pmem_fd, addr,
+ size, rc);
+ return rc;
+}
+
+#ifdef USE_ION
+uint8_t *mm_camera_do_mmap_ion(int ion_fd, struct ion_allocation_data *alloc,
+ struct ion_fd_data *ion_info_fd, int *mapFd)
+{
+ void *ret; /* returned virtual address */
+ int rc = 0;
+ struct ion_handle_data handle_data;
+
+ /* to make it page size aligned */
+ alloc->len = (alloc->len + 4095) & (~4095);
+
+ rc = ioctl(ion_fd, ION_IOC_ALLOC, alloc);
+ if (rc < 0) {
+ CDBG_ERROR("ION allocation failed\n");
+ goto ION_ALLOC_FAILED;
+ }
+
+ ion_info_fd->handle = alloc->handle;
+ rc = ioctl(ion_fd, ION_IOC_SHARE, ion_info_fd);
+ if (rc < 0) {
+ CDBG_ERROR("ION map failed %s\n", strerror(errno));
+ goto ION_MAP_FAILED;
+ }
+ *mapFd = ion_info_fd->fd;
+ /*ret = mmap(NULL,
+ alloc->len,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ *mapFd,
+ 0);
+
+ if (ret == MAP_FAILED) {
+ CDBG_ERROR("ION_MMAP_FAILED: %s (%d)\n", strerror(errno), errno);
+ goto ION_MAP_FAILED;
+ }*/
+
+ return ret;
+
+ION_MAP_FAILED:
+ handle_data.handle = ion_info_fd->handle;
+ ioctl(ion_fd, ION_IOC_FREE, &handle_data);
+ION_ALLOC_FAILED:
+ return NULL;
+}
+
+int mm_camera_do_munmap_ion (int ion_fd, struct ion_fd_data *ion_info_fd,
+ void *addr, size_t size)
+{
+ int rc = 0;
+ rc = munmap(addr, size);
+ close(ion_info_fd->fd);
+
+ struct ion_handle_data handle_data;
+ handle_data.handle = ion_info_fd->handle;
+ ioctl(ion_fd, ION_IOC_FREE, &handle_data);
+ return rc;
+}
+#endif
+
+/*============================================================
+ FUNCTION mm_camera_dump_image
+ DESCRIPTION:
+==============================================================*/
+int mm_camera_dump_image(void *addr, uint32_t size, char *filename)
+{
+ int file_fd = open(filename, O_RDWR | O_CREAT, 0777);
+
+ if (file_fd < 0) {
+ CDBG_HIGH("%s: cannot open file\n", __func__);
+ return -1;
+ } else
+ write(file_fd, addr, size);
+ close(file_fd);
+ CDBG("%s: %s, size=%d\n", __func__, filename, size);
+ return 0;
+}
+
+uint32_t mm_camera_get_msm_frame_len(cam_format_t fmt_type,
+ camera_mode_t mode,
+ int width,
+ int height,
+ int image_type,
+ uint8_t *num_planes,
+ uint32_t plane[])
+{
+ uint32_t size;
+ *num_planes = 0;
+ int local_height;
+
+ switch (fmt_type) {
+ case CAMERA_YUV_420_NV12:
+ case CAMERA_YUV_420_NV21:
+ *num_planes = 2;
+ if(CAMERA_MODE_3D == mode) {
+ size = (uint32_t)(PAD_TO_2K(width*height)*3/2);
+ plane[0] = PAD_TO_WORD(width*height);
+ } else {
+ if (image_type == OUTPUT_TYPE_V) {
+ plane[0] = PAD_TO_2K(width * height);
+ plane[1] = PAD_TO_2K(width * height/2);
+ } else if (image_type == OUTPUT_TYPE_P) {
+ plane[0] = PAD_TO_WORD(width * height);
+ plane[1] = PAD_TO_WORD(width * height/2);
+ } else {
+ plane[0] = PAD_TO_WORD(width * CEILING16(height));
+ plane[1] = PAD_TO_WORD(width * CEILING16(height)/2);
+ }
+ size = plane[0] + plane[1];
+ }
+ break;
+ case CAMERA_BAYER_SBGGR10:
+ *num_planes = 1;
+ plane[0] = PAD_TO_WORD(width * height);
+ size = plane[0];
+ break;
+ case CAMERA_YUV_422_NV16:
+ case CAMERA_YUV_422_NV61:
+ if( image_type == OUTPUT_TYPE_S || image_type == OUTPUT_TYPE_V) {
+ local_height = CEILING16(height);
+ } else {
+ local_height = height;
+ }
+ *num_planes = 2;
+ plane[0] = PAD_TO_WORD(width * height);
+ plane[1] = PAD_TO_WORD(width * height);
+ size = plane[0] + plane[1];
+ break;
+ default:
+ CDBG("%s: format %d not supported.\n",
+ __func__, fmt_type);
+ size = 0;
+ }
+ CDBG("%s:fmt=%d,image_type=%d,width=%d,height=%d,frame_len=%d\n",
+ __func__, fmt_type, image_type, width, height, size);
+ return size;
+}
+
+void mm_camera_util_profile(const char *str)
+{
+#if (MM_CAMERA_PROFILE)
+ struct timespec cur_time;
+
+ clock_gettime(CLOCK_REALTIME, &cur_time);
+ CDBG_HIGH("PROFILE %s: %ld.%09ld\n", str,
+ cur_time.tv_sec, cur_time.tv_nsec);
+#endif
+}
+
+/*===========================================================================
+ * FUNCTION - mm_camera_do_mmap_ion -
+ *
+ * DESCRIPTION:
+ *==========================================================================*/
+uint8_t *mm_camera_do_mmap_ion(int ion_fd, struct ion_allocation_data *alloc,
+ struct ion_fd_data *ion_info_fd, int *mapFd)
+{
+ void *ret; /* returned virtual address */
+ int rc = 0;
+ struct ion_handle_data handle_data;
+
+ /* to make it page size aligned */
+ alloc->len = (alloc->len + 4095) & (~4095);
+ alloc->align = 4096;
+
+ rc = ioctl(ion_fd, ION_IOC_ALLOC, alloc);
+ if (rc < 0) {
+ CDBG_ERROR("ION allocation failed %s\n", strerror(errno));
+ goto ION_ALLOC_FAILED;
+ }
+
+ ion_info_fd->handle = alloc->handle;
+ rc = ioctl(ion_fd, ION_IOC_SHARE, ion_info_fd);
+ if (rc < 0) {
+ CDBG_ERROR("ION map failed %s\n", strerror(errno));
+ goto ION_MAP_FAILED;
+ }
+ *mapFd = ion_info_fd->fd;
+ ret = mmap(NULL,
+ alloc->len,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ *mapFd,
+ 0);
+
+ if (ret == MAP_FAILED) {
+ CDBG_ERROR("ION_MMAP_FAILED: %s (%d)\n", strerror(errno), errno);
+ goto ION_MAP_FAILED;
+ }
+
+ return ret;
+
+ION_MAP_FAILED:
+ handle_data.handle = ion_info_fd->handle;
+ ioctl(ion_fd, ION_IOC_FREE, &handle_data);
+ION_ALLOC_FAILED:
+ return NULL;
+}
+
+/*===========================================================================
+ * FUNCTION - mm_camera_do_munmap_ion -
+ *
+ * DESCRIPTION:
+ *==========================================================================*/
+int mm_camera_do_munmap_ion (int ion_fd, struct ion_fd_data *ion_info_fd,
+ void *addr, size_t size)
+{
+ int rc = 0;
+ rc = munmap(addr, size);
+ close(ion_info_fd->fd);
+
+ struct ion_handle_data handle_data;
+ handle_data.handle = ion_info_fd->handle;
+ ioctl(ion_fd, ION_IOC_FREE, &handle_data);
+ return rc;
+}
diff --git a/camera/QCamera/stack/mm-camera-interface/src/mm_camera_interface.c b/camera/QCamera/stack/mm-camera-interface/src/mm_camera_interface.c
new file mode 100755
index 0000000..54cf3ac
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-interface/src/mm_camera_interface.c
@@ -0,0 +1,951 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <linux/media.h>
+#include <semaphore.h>
+
+#include "mm_camera_dbg.h"
+#include "mm_camera_interface.h"
+#include "mm_camera.h"
+
+static pthread_mutex_t g_intf_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static mm_camera_ctrl_t g_cam_ctrl = {{{0, {0, 0, 0, 0}, 0, 0}}, 0, {{0}}, {0}};
+
+static pthread_mutex_t g_handler_lock = PTHREAD_MUTEX_INITIALIZER;
+static uint16_t g_handler_history_count = 0; /* history count for handler */
+
+/* utility function to generate handler */
+uint32_t mm_camera_util_generate_handler(uint8_t index)
+{
+ uint32_t handler = 0;
+ pthread_mutex_lock(&g_handler_lock);
+ g_handler_history_count++;
+ if (0 == g_handler_history_count) {
+ g_handler_history_count++;
+ }
+ handler = g_handler_history_count;
+ handler = (handler<<8) | index;
+ pthread_mutex_unlock(&g_handler_lock);
+ return handler;
+}
+
+uint8_t mm_camera_util_get_index_by_handler(uint32_t handler)
+{
+ return (handler&0x000000ff);
+}
+
+const char *mm_camera_util_get_dev_name(uint32_t cam_handler)
+{
+ char *dev_name = NULL;
+ uint8_t cam_idx = mm_camera_util_get_index_by_handler(cam_handler);
+ dev_name = g_cam_ctrl.camera[cam_idx].video_dev_name;
+ return dev_name;
+}
+
+mm_camera_obj_t* mm_camera_util_get_camera_by_handler(uint32_t cam_handler)
+{
+ mm_camera_obj_t *cam_obj = NULL;
+ uint8_t cam_idx = mm_camera_util_get_index_by_handler(cam_handler);
+
+ if ((NULL != g_cam_ctrl.cam_obj[cam_idx]) &&
+ (cam_handler == g_cam_ctrl.cam_obj[cam_idx]->my_hdl)) {
+ cam_obj = g_cam_ctrl.cam_obj[cam_idx];
+ }
+ return cam_obj;
+}
+
+static int32_t mm_camera_intf_sync(uint32_t camera_handler)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ CDBG("%s E: camera_handler = %d ",__func__,camera_handler);
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_sync(my_obj);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+/* check if the parm is supported */
+static int32_t mm_camera_intf_is_parm_supported(uint32_t camera_handler,
+ mm_camera_parm_type_t parm_type,
+ uint8_t *support_set_parm,
+ uint8_t *support_get_parm)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+ *support_set_parm = 0;
+ *support_get_parm = 0;
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_is_parm_supported(my_obj, parm_type, support_set_parm, support_get_parm);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ return rc;
+}
+
+/* set a parmÂ’s current value */
+static int32_t mm_camera_intf_set_parm(uint32_t camera_handler,
+ mm_camera_parm_type_t parm_type,
+ void* p_value)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_set_parm(my_obj, parm_type, p_value);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ return rc;
+}
+
+/* get a parmÂ’s current value */
+static int32_t mm_camera_intf_get_parm(uint32_t camera_handler,
+ mm_camera_parm_type_t parm_type,
+ void* p_value)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_get_parm(my_obj, parm_type, p_value);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ return rc;
+}
+
+static void mm_camera_intf_close(uint32_t camera_handler)
+{
+ int32_t rc = -1;
+ uint8_t cam_idx = camera_handler & 0x00ff;
+ mm_camera_obj_t * my_obj = NULL;
+
+ CDBG("%s E: camera_handler = %d ",__func__,camera_handler);
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if (my_obj){
+ my_obj->ref_count--;
+
+ if(my_obj->ref_count > 0) {
+ /* still have reference to obj, return here */
+ CDBG("%s: ref_count=%d\n", __func__, my_obj->ref_count);
+ pthread_mutex_unlock(&g_intf_lock);
+ return;
+ }
+
+ /* need close camera here as no other reference
+ * first empty g_cam_ctrl's referent to cam_obj */
+ g_cam_ctrl.cam_obj[cam_idx] = NULL;
+
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+
+ mm_camera_close(my_obj);
+
+ pthread_mutex_destroy(&my_obj->cam_lock);
+ free(my_obj);
+
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+}
+
+static uint32_t mm_camera_intf_add_channel(uint32_t camera_handler)
+{
+ uint32_t ch_id = 0;
+ mm_camera_obj_t * my_obj = NULL;
+
+ CDBG("%s :E camera_handler = %d",__func__,camera_handler);
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ ch_id = mm_camera_add_channel(my_obj);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X ch_id = %d",__func__,ch_id);
+ return ch_id;
+}
+
+static void mm_camera_intf_del_channel(uint32_t camera_handler, uint32_t ch_id)
+{
+ mm_camera_obj_t * my_obj = NULL;
+
+ CDBG("%s :E ch_id = %d",__func__,ch_id);
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ mm_camera_del_channel(my_obj, ch_id);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X",__func__);
+}
+
+static uint8_t mm_camera_intf_is_event_supported(uint32_t camera_handler,
+ mm_camera_event_type_t evt_type)
+{
+ switch(evt_type) {
+ case MM_CAMERA_EVT_TYPE_CH:
+ case MM_CAMERA_EVT_TYPE_CTRL:
+ case MM_CAMERA_EVT_TYPE_STATS:
+ case MM_CAMERA_EVT_TYPE_INFO:
+ return 1;
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+static int32_t mm_camera_intf_register_event_notify(
+ uint32_t camera_handler,
+ mm_camera_event_notify_t evt_cb,
+ void * user_data,
+ mm_camera_event_type_t evt_type)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ CDBG("%s :E evt_type = %d",__func__,evt_type);
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_register_event_notify(my_obj, evt_cb, user_data, evt_type);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :E rc = %d",__func__,rc);
+ return rc;
+}
+
+static mm_camera_2nd_sensor_t * mm_camera_intf_query_2nd_sensor_info(uint32_t camera_handler)
+{
+ mm_camera_2nd_sensor_t *sensor_info = NULL;
+ mm_camera_obj_t * my_obj = NULL;
+
+ CDBG("%s :E camera_handler = %d",__func__,camera_handler);
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ sensor_info = mm_camera_query_2nd_sensor_info(my_obj);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X",__func__);
+ return sensor_info;
+}
+
+static int32_t mm_camera_intf_qbuf(uint32_t camera_handler,
+ uint32_t ch_id,
+ mm_camera_buf_def_t *buf)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_qbuf(my_obj, ch_id, buf);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X evt_type = %d",__func__,rc);
+ return rc;
+}
+
+static uint32_t mm_camera_intf_add_stream(
+ uint32_t camera_handler,
+ uint32_t ch_id,
+ mm_camera_buf_notify_t buf_cb, void *user_data,
+ uint32_t ext_image_mode, uint32_t sensor_idx)
+{
+ uint32_t stream_id = 0;
+ mm_camera_obj_t * my_obj = NULL;
+
+ CDBG("%s : E handle = %d ch_id = %d",__func__,camera_handler,
+ ch_id);
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ stream_id = mm_camera_add_stream(my_obj, ch_id, buf_cb,
+ user_data, ext_image_mode, sensor_idx);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X stream_id = %d",__func__,stream_id);
+ return stream_id;
+}
+
+static int32_t mm_camera_intf_del_stream(
+ uint32_t camera_handler,
+ uint32_t ch_id,
+ uint32_t stream_id)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ CDBG("%s : E handle = %d ch_id = %d stream_id = %d",__func__,camera_handler,
+ ch_id,stream_id);
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_del_stream(my_obj, ch_id, stream_id);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+static int32_t mm_camera_intf_config_stream(
+ uint32_t camera_handler,
+ uint32_t ch_id,
+ uint32_t stream_id,
+ mm_camera_stream_config_t *config)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ CDBG("%s :E handle = %d, ch_id = %d,stream_id = %d",__func__,
+ camera_handler,ch_id,stream_id);
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ CDBG("%s :mm_camera_intf_config_stream stream_id = %d",__func__,stream_id);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_config_stream(my_obj, ch_id, stream_id, config);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+static int32_t mm_camera_intf_bundle_streams(
+ uint32_t camera_handler,
+ uint32_t ch_id,
+ mm_camera_buf_notify_t super_frame_notify_cb,
+ void *user_data,
+ mm_camera_bundle_attr_t *attr,
+ uint8_t num_streams,
+ uint32_t *stream_ids)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ CDBG("%s :E handle = %d, ch_id = %d",__func__,
+ camera_handler,ch_id);
+
+ if (MM_CAMEAR_MAX_STRAEM_BUNDLE < num_streams) {
+ CDBG_ERROR("%s: number of streams (%d) exceeds max (%d)",
+ __func__, num_streams, MM_CAMEAR_MAX_STRAEM_BUNDLE);
+ return rc;
+ }
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_bundle_streams(my_obj, ch_id,
+ super_frame_notify_cb,
+ user_data, attr,
+ num_streams, stream_ids);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+static int32_t mm_camera_intf_destroy_bundle(uint32_t camera_handler,
+ uint32_t ch_id)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ CDBG("%s :E handle = %d, ch_id = %d",__func__,
+ camera_handler,ch_id);
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_destroy_bundle(my_obj, ch_id);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+static int32_t mm_camera_intf_start_streams(
+ uint32_t camera_handler,
+ uint32_t ch_id,
+ uint8_t num_streams,
+ uint32_t *stream_ids)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ CDBG("%s :E camera_handler = %d,ch_id = %d, num_streams = %d",
+ __func__,camera_handler,ch_id,num_streams);
+ if (MM_CAMEAR_STRAEM_NUM_MAX < num_streams) {
+ CDBG_ERROR("%s: num of streams (%d) exceeds MAX (%d)",
+ __func__, num_streams, MM_CAMEAR_STRAEM_NUM_MAX);
+ return rc;
+ }
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_start_streams(my_obj, ch_id, num_streams, stream_ids);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+static int32_t mm_camera_intf_stop_streams(
+ uint32_t camera_handler,
+ uint32_t ch_id,
+ uint8_t num_streams,
+ uint32_t *stream_ids)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ CDBG("%s :E camera_handler = %d,ch_id = %d, num_streams = %d",
+ __func__,camera_handler,ch_id,num_streams);
+
+ if (MM_CAMEAR_STRAEM_NUM_MAX < num_streams) {
+ CDBG_ERROR("%s: num of streams (%d) exceeds MAX (%d)",
+ __func__, num_streams, MM_CAMEAR_STRAEM_NUM_MAX);
+ return rc;
+ }
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_stop_streams(my_obj, ch_id,
+ num_streams, stream_ids);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+static int32_t mm_camera_intf_async_teardown_streams(
+ uint32_t camera_handler,
+ uint32_t ch_id,
+ uint8_t num_streams,
+ uint32_t *stream_ids)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ CDBG("%s :E camera_handler = %d,ch_id = %d, num_streams = %d",
+ __func__,camera_handler,ch_id,num_streams);
+
+ if (MM_CAMEAR_STRAEM_NUM_MAX < num_streams) {
+ CDBG_ERROR("%s: num of streams (%d) exceeds MAX (%d)",
+ __func__, num_streams, MM_CAMEAR_STRAEM_NUM_MAX);
+ return rc;
+ }
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_async_teardown_streams(my_obj, ch_id,
+ num_streams, stream_ids);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+static int32_t mm_camera_intf_request_super_buf(
+ uint32_t camera_handler,
+ uint32_t ch_id)
+{
+ int32_t rc = -1;
+ CDBG("%s :E camera_handler = %d,ch_id = %d",
+ __func__,camera_handler,ch_id);
+ mm_camera_obj_t * my_obj = NULL;
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_request_super_buf(my_obj, ch_id);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+static int32_t mm_camera_intf_cancel_super_buf_request(
+ uint32_t camera_handler,
+ uint32_t ch_id)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ CDBG("%s :E camera_handler = %d,ch_id = %d",
+ __func__,camera_handler,ch_id);
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_cancel_super_buf_request(my_obj, ch_id);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+static int32_t mm_camera_intf_start_focus(
+ uint32_t camera_handler,
+ uint32_t ch_id,
+ uint32_t sensor_idx,
+ uint32_t focus_mode)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ CDBG("%s :E camera_handler = %d,ch_id = %d, focus_mode = %d",
+ __func__,camera_handler,ch_id,focus_mode);
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_start_focus(my_obj, ch_id, sensor_idx, focus_mode);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+static int32_t mm_camera_intf_abort_focus(
+ uint32_t camera_handler,
+ uint32_t ch_id,
+ uint32_t sensor_idx)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_abort_focus(my_obj, ch_id, sensor_idx);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+static int32_t mm_camera_intf_prepare_snapshot(
+ uint32_t camera_handler,
+ uint32_t ch_id,
+ uint32_t sensor_idx)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handler);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_prepare_snapshot(my_obj, ch_id, sensor_idx);
+ } else {
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+static int32_t mm_camera_intf_set_stream_parm(
+ uint32_t camera_handle,
+ uint32_t ch_id,
+ uint32_t s_id,
+ mm_camera_stream_parm_t parm_type,
+ void* p_value)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
+
+ CDBG("%s :E camera_handle = %d,ch_id = %d,s_id = %d,parm_type = %d",__func__,
+ camera_handle,ch_id,s_id,parm_type);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_set_stream_parm(my_obj,ch_id,s_id,
+ parm_type,
+ p_value);
+ }else{
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+static int32_t mm_camera_intf_get_stream_parm(
+ uint32_t camera_handle,
+ uint32_t ch_id,
+ uint32_t s_id,
+ mm_camera_stream_parm_t parm_type,
+ void* p_value)
+{
+ int32_t rc = -1;
+ mm_camera_obj_t * my_obj = NULL;
+
+ pthread_mutex_lock(&g_intf_lock);
+ my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
+
+ CDBG("%s :E camera_handle = %d,ch_id = %d,s_id = %d,parm_type = %d",__func__,
+ camera_handle,ch_id,s_id,parm_type);
+
+ if(my_obj) {
+ pthread_mutex_lock(&my_obj->cam_lock);
+ pthread_mutex_unlock(&g_intf_lock);
+ rc = mm_camera_get_stream_parm(my_obj,ch_id,s_id,
+ parm_type,
+ p_value);
+ }else{
+ pthread_mutex_unlock(&g_intf_lock);
+ }
+
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+mm_camera_info_t * camera_query(uint8_t *num_cameras)
+{
+ int i = 0, rc = 0;
+ int dev_fd = 0;
+ struct media_device_info mdev_info;
+ int num_media_devices = 0;
+ if (!num_cameras) {
+ CDBG_ERROR("%s: num_cameras is NULL\n", __func__);
+ return NULL;
+ }
+
+ CDBG("%s : E",__func__);
+ /* lock the mutex */
+ pthread_mutex_lock(&g_intf_lock);
+ *num_cameras = 0;
+ while (1) {
+ char dev_name[32];
+ snprintf(dev_name, sizeof(dev_name), "/dev/media%d", num_media_devices);
+ dev_fd = open(dev_name, O_RDWR | O_NONBLOCK);
+ if (dev_fd < 0) {
+ CDBG("Done discovering media devices\n");
+ break;
+ }
+ num_media_devices++;
+ rc = ioctl(dev_fd, MEDIA_IOC_DEVICE_INFO, &mdev_info);
+ if (rc < 0) {
+ CDBG_ERROR("Error: ioctl media_dev failed: %s\n", strerror(errno));
+ close(dev_fd);
+ break;
+ }
+
+ if(strncmp(mdev_info.model, QCAMERA_NAME, sizeof(mdev_info.model) != 0)) {
+ close(dev_fd);
+ continue;
+ }
+
+ char * mdev_cfg;
+ int cam_type = 0, mount_angle = 0, info_index = 0;
+ mdev_cfg = strtok(mdev_info.serial, "-");
+ while(mdev_cfg != NULL) {
+ if(info_index == 0) {
+ if(strcmp(mdev_cfg, QCAMERA_NAME))
+ break;
+ } else if(info_index == 1) {
+ mount_angle = atoi(mdev_cfg);
+ } else if(info_index == 2) {
+ cam_type = atoi(mdev_cfg);
+ }
+ mdev_cfg = strtok(NULL, "-");
+ info_index++;
+ }
+
+ if(info_index == 0) {
+ close(dev_fd);
+ continue;
+ }
+
+ int num_entities = 1;
+ while (1) {
+ struct media_entity_desc entity;
+ memset(&entity, 0, sizeof(entity));
+ entity.id = num_entities++;
+ rc = ioctl(dev_fd, MEDIA_IOC_ENUM_ENTITIES, &entity);
+ if (rc < 0) {
+ CDBG("Done enumerating media entities\n");
+ rc = 0;
+ break;
+ }
+ if(entity.type == MEDIA_ENT_T_DEVNODE_V4L && entity.group_id == QCAMERA_VNODE_GROUP_ID) {
+ strncpy(g_cam_ctrl.video_dev_name[*num_cameras],
+ entity.name, sizeof(entity.name));
+ g_cam_ctrl.camera[*num_cameras].video_dev_name =
+ &g_cam_ctrl.video_dev_name[*num_cameras][0];
+ break;
+ }
+ }
+
+ //g_cam_ctrl.camera[*num_cameras].camera_info.camera_id = *num_cameras;
+ g_cam_ctrl.camera[*num_cameras].camera_id = *num_cameras;
+
+ g_cam_ctrl.camera[*num_cameras].
+ camera_info.modes_supported = CAMERA_MODE_2D;
+
+ if(cam_type > 1) {
+ g_cam_ctrl.camera[*num_cameras].
+ camera_info.modes_supported |= CAMERA_MODE_3D;
+ }
+
+ g_cam_ctrl.camera[*num_cameras].camera_info.position =
+ (cam_type == 1) ? FRONT_CAMERA : BACK_CAMERA;
+
+ g_cam_ctrl.camera[*num_cameras].camera_info.sensor_mount_angle =
+ mount_angle;
+
+ g_cam_ctrl.camera[*num_cameras].main_sensor_type = 0;
+
+ CDBG("%s: dev_info[id=%d,name='%s',pos=%d,modes=0x%x,sensor=%d mount_angle = %d]\n",
+ __func__, *num_cameras,
+ g_cam_ctrl.camera[*num_cameras].video_dev_name,
+ g_cam_ctrl.camera[*num_cameras].camera_info.position,
+ g_cam_ctrl.camera[*num_cameras].camera_info.modes_supported,
+ g_cam_ctrl.camera[*num_cameras].main_sensor_type,
+ g_cam_ctrl.camera[*num_cameras].camera_info.sensor_mount_angle);
+
+ *num_cameras += 1;
+ if (dev_fd > 0) {
+ close(dev_fd);
+ }
+ }
+ *num_cameras = *num_cameras;
+ g_cam_ctrl.num_cam = *num_cameras;
+
+ /* unlock the mutex */
+ pthread_mutex_unlock(&g_intf_lock);
+ CDBG("%s: num_cameras=%d\n", __func__, g_cam_ctrl.num_cam);
+ if(rc == 0)
+ return &g_cam_ctrl.camera[0];
+ else
+ return NULL;
+}
+
+/* camera ops v-table */
+static mm_camera_ops_t mm_camera_ops = {
+ .sync = mm_camera_intf_sync,
+ .is_event_supported = mm_camera_intf_is_event_supported,
+ .register_event_notify = mm_camera_intf_register_event_notify,
+ .qbuf = mm_camera_intf_qbuf,
+ .camera_close = mm_camera_intf_close,
+ .query_2nd_sensor_info = mm_camera_intf_query_2nd_sensor_info,
+ .is_parm_supported = mm_camera_intf_is_parm_supported,
+ .set_parm = mm_camera_intf_set_parm,
+ .get_parm = mm_camera_intf_get_parm,
+ .ch_acquire = mm_camera_intf_add_channel,
+ .ch_release = mm_camera_intf_del_channel,
+ .add_stream = mm_camera_intf_add_stream,
+ .del_stream = mm_camera_intf_del_stream,
+ .config_stream = mm_camera_intf_config_stream,
+ .init_stream_bundle = mm_camera_intf_bundle_streams,
+ .destroy_stream_bundle = mm_camera_intf_destroy_bundle,
+ .start_streams = mm_camera_intf_start_streams,
+ .stop_streams = mm_camera_intf_stop_streams,
+ .async_teardown_streams = mm_camera_intf_async_teardown_streams,
+ .request_super_buf = mm_camera_intf_request_super_buf,
+ .cancel_super_buf_request = mm_camera_intf_cancel_super_buf_request,
+ .start_focus = mm_camera_intf_start_focus,
+ .abort_focus = mm_camera_intf_abort_focus,
+ .prepare_snapshot = mm_camera_intf_prepare_snapshot,
+ .set_stream_parm = mm_camera_intf_set_stream_parm,
+ .get_stream_parm = mm_camera_intf_get_stream_parm
+};
+
+/* open camera. */
+mm_camera_vtbl_t * camera_open(uint8_t camera_idx,
+ mm_camear_mem_vtbl_t *mem_vtbl)
+{
+ int32_t rc = 0;
+ mm_camera_obj_t* cam_obj = NULL;
+
+ CDBG("%s: E camera_idx = %d\n", __func__,camera_idx);
+ if (MSM_MAX_CAMERA_SENSORS <= camera_idx) {
+ CDBG_ERROR("%s: Invalid camera_idx (%d)", __func__, camera_idx);
+ return NULL;
+ }
+
+ pthread_mutex_lock(&g_intf_lock);
+ /* opened already */
+ if(NULL != g_cam_ctrl.cam_obj[camera_idx]) {
+ /* Add reference */
+ g_cam_ctrl.cam_obj[camera_idx]->ref_count++;
+ pthread_mutex_unlock(&g_intf_lock);
+ CDBG("%s: opened alreadyn", __func__);
+ return &cam_obj->vtbl;
+ }
+
+ cam_obj = (mm_camera_obj_t *)malloc(sizeof(mm_camera_obj_t));
+ if(NULL == cam_obj) {
+ pthread_mutex_unlock(&g_intf_lock);
+ CDBG("%s: no mem", __func__);
+ return NULL;
+ }
+
+ /* initialize camera obj */
+ memset(cam_obj, 0, sizeof(mm_camera_obj_t));
+ cam_obj->ctrl_fd = -1;
+ cam_obj->ds_fd = -1;
+ cam_obj->ref_count++;
+ cam_obj->my_hdl = mm_camera_util_generate_handler(camera_idx);
+ cam_obj->vtbl.camera_handle = cam_obj->my_hdl; /* set handler */
+ cam_obj->vtbl.camera_info = &g_cam_ctrl.camera[camera_idx];
+ cam_obj->vtbl.ops = &mm_camera_ops;
+ cam_obj->mem_vtbl = mem_vtbl; /* save mem_vtbl */
+ pthread_mutex_init(&cam_obj->cam_lock, NULL);
+
+ rc = mm_camera_open(cam_obj);
+ if(rc != 0) {
+ CDBG_ERROR("%s: mm_camera_open err = %d", __func__, rc);
+ pthread_mutex_destroy(&cam_obj->cam_lock);
+ g_cam_ctrl.cam_obj[camera_idx] = NULL;
+ free(cam_obj);
+ cam_obj = NULL;
+ pthread_mutex_unlock(&g_intf_lock);
+ return NULL;
+ }else{
+ CDBG("%s: Open succeded\n", __func__);
+ g_cam_ctrl.cam_obj[camera_idx] = cam_obj;
+ pthread_mutex_unlock(&g_intf_lock);
+ return &cam_obj->vtbl;
+ }
+}
diff --git a/camera/QCamera/stack/mm-camera-interface/src/mm_camera_sock.c b/camera/QCamera/stack/mm-camera-interface/src/mm_camera_sock.c
new file mode 100755
index 0000000..2f68d1d
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-interface/src/mm_camera_sock.c
@@ -0,0 +1,224 @@
+/*
+Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <linux/un.h>
+
+#include "mm_camera_dbg.h"
+#include "mm_camera_sock.h"
+
+/*===========================================================================
+ * FUNCTION - mm_camera_socket_create -
+ *
+ * DESCRIPTION: opens a domain socket tied to camera ID and socket type
+ * int cam_id: camera ID
+ * mm_camera_sock_type_t sock_type: socket type, TCP/UDP
+ * retured fd related to the domain socket
+ *==========================================================================*/
+int mm_camera_socket_create(int cam_id, mm_camera_sock_type_t sock_type)
+{
+ int socket_fd;
+ struct sockaddr_un sock_addr;
+ int sktype;
+ int rc;
+
+ switch (sock_type)
+ {
+ case MM_CAMERA_SOCK_TYPE_UDP:
+ sktype = SOCK_DGRAM;
+ break;
+ case MM_CAMERA_SOCK_TYPE_TCP:
+ sktype = SOCK_STREAM;
+ break;
+ default:
+ CDBG_ERROR("%s: unknown socket type =%d", __func__, sock_type);
+ return -1;
+ }
+ socket_fd = socket(AF_UNIX, sktype, 0);
+ if (socket_fd < 0) {
+ CDBG_ERROR("%s: error create socket fd =%d", __func__, socket_fd);
+ return socket_fd;
+ }
+
+ memset(&sock_addr, 0, sizeof(sock_addr));
+ sock_addr.sun_family = AF_UNIX;
+ snprintf(sock_addr.sun_path, UNIX_PATH_MAX, "/data/cam_socket%d", cam_id);
+ if((rc = connect(socket_fd, (struct sockaddr *) &sock_addr,
+ sizeof(sock_addr))) != 0) {
+ close(socket_fd);
+ socket_fd = -1;
+ CDBG_ERROR("%s: socket_fd=%d %s ", __func__, socket_fd, strerror(errno));
+ }
+
+ CDBG("%s: socket_fd=%d %s", __func__, socket_fd, sock_addr.sun_path);
+ return socket_fd;
+}
+
+/*===========================================================================
+ * FUNCTION - mm_camera_socket_close -
+ *
+ * DESCRIPTION: close domain socket by its fd
+ *==========================================================================*/
+void mm_camera_socket_close(int fd)
+{
+ if (fd > 0) {
+ close(fd);
+ }
+}
+
+/*===========================================================================
+ * FUNCTION - mm_camera_socket_sendmsg -
+ *
+ * DESCRIPTION: send msg through domain socket
+ * int fd: socket fd
+ * mm_camera_sock_msg_packet_t *msg: pointer to msg to be sent over domain socket
+ * int sendfd: file descriptors to be sent
+ * return the total bytes of sent msg
+ *==========================================================================*/
+int mm_camera_socket_sendmsg(
+ int fd,
+ void *msg,
+ uint32_t buf_size,
+ int sendfd)
+{
+ struct msghdr msgh;
+ struct iovec iov[1];
+ struct cmsghdr * cmsghp = NULL;
+ char control[CMSG_SPACE(sizeof(int))];
+
+ if (msg == NULL) {
+ CDBG("%s: msg is NULL", __func__);
+ return -1;
+ }
+ memset(&msgh, 0, sizeof(msgh));
+ msgh.msg_name = NULL;
+ msgh.msg_namelen = 0;
+
+ iov[0].iov_base = msg;
+ iov[0].iov_len = buf_size;
+ msgh.msg_iov = iov;
+ msgh.msg_iovlen = 1;
+ CDBG("%s: iov_len=%d", __func__, iov[0].iov_len);
+
+ msgh.msg_control = NULL;
+ msgh.msg_controllen = 0;
+
+ /* if sendfd is vlaid, we need to pass it through control msg */
+ if( sendfd > 0) {
+ msgh.msg_control = control;
+ msgh.msg_controllen = sizeof(control);
+ cmsghp = CMSG_FIRSTHDR(&msgh);
+ if (cmsghp != NULL) {
+ CDBG("%s: Got ctrl msg pointer", __func__);
+ cmsghp->cmsg_level = SOL_SOCKET;
+ cmsghp->cmsg_type = SCM_RIGHTS;
+ cmsghp->cmsg_len = CMSG_LEN(sizeof(int));
+ *((int *)CMSG_DATA(cmsghp)) = sendfd;
+ CDBG("%s: cmsg data=%d", __func__, *((int *) CMSG_DATA(cmsghp)));
+ } else {
+ CDBG("%s: ctrl msg NULL", __func__);
+ return -1;
+ }
+ }
+
+ return sendmsg(fd, &(msgh), 0);
+}
+
+/*===========================================================================
+ * FUNCTION - mm_camera_socket_recvmsg -
+ *
+ * DESCRIPTION: receive msg from domain socket.
+ * int fd: socket fd
+ * void *msg: pointer to mm_camera_sock_msg_packet_t to hold incoming msg,
+ * need be allocated by the caller
+ * uint32_t buf_size: the size of the buf that holds incoming msg
+ * int *rcvdfd: pointer to hold recvd file descriptor if not NULL.
+ * return the total bytes of received msg
+ *==========================================================================*/
+int mm_camera_socket_recvmsg(
+ int fd,
+ void *msg,
+ uint32_t buf_size,
+ int *rcvdfd)
+{
+ struct msghdr msgh;
+ struct iovec iov[1];
+ struct cmsghdr *cmsghp = NULL;
+ char control[CMSG_SPACE(sizeof(int))];
+ int rcvd_fd = -1;
+ int rcvd_len = 0;
+
+ if ( (msg == NULL) || (buf_size <= 0) ) {
+ CDBG_ERROR(" %s: msg buf is NULL", __func__);
+ return -1;
+ }
+
+ memset(&msgh, 0, sizeof(msgh));
+ msgh.msg_name = NULL;
+ msgh.msg_namelen = 0;
+ msgh.msg_control = control;
+ msgh.msg_controllen = sizeof(control);
+
+ iov[0].iov_base = msg;
+ iov[0].iov_len = buf_size;
+ msgh.msg_iov = iov;
+ msgh.msg_iovlen = 1;
+
+ if ( (rcvd_len = recvmsg(fd, &(msgh), 0)) <= 0) {
+ CDBG_ERROR(" %s: recvmsg failed", __func__);
+ return rcvd_len;
+ }
+
+ CDBG("%s: msg_ctrl %p len %d", __func__, msgh.msg_control, msgh.msg_controllen);
+
+ if( ((cmsghp = CMSG_FIRSTHDR(&msgh)) != NULL) &&
+ (cmsghp->cmsg_len == CMSG_LEN(sizeof(int))) ) {
+ if (cmsghp->cmsg_level == SOL_SOCKET &&
+ cmsghp->cmsg_type == SCM_RIGHTS) {
+ CDBG("%s: CtrlMsg is valid", __func__);
+ rcvd_fd = *((int *) CMSG_DATA(cmsghp));
+ CDBG("%s: Receieved fd=%d", __func__, rcvd_fd);
+ } else {
+ CDBG_ERROR("%s: Unexpected Control Msg. Line=%d", __func__, __LINE__);
+ }
+ }
+
+ if (rcvdfd) {
+ *rcvdfd = rcvd_fd;
+ }
+
+ return rcvd_len;
+}
+
diff --git a/camera/QCamera/stack/mm-camera-interface/src/mm_camera_stream.c b/camera/QCamera/stack/mm-camera-interface/src/mm_camera_stream.c
new file mode 100755
index 0000000..88dc9c1
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-interface/src/mm_camera_stream.c
@@ -0,0 +1,1563 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <time.h>
+#include <semaphore.h>
+
+#include "mm_camera_dbg.h"
+#include "mm_camera_interface.h"
+#include "mm_camera.h"
+
+#define MM_CAMERA_MAX_NUM_FRAMES 16
+
+/* internal function decalre */
+int32_t mm_stream_qbuf(mm_stream_t *my_obj,
+ mm_camera_buf_def_t *buf);
+int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj);
+int32_t mm_stream_set_fmt(mm_stream_t * my_obj);
+int32_t mm_stream_get_offset(mm_stream_t *my_obj);
+int32_t mm_stream_set_cid(mm_stream_t *my_obj,stream_cid_t *in_value);
+int32_t mm_stream_init_bufs(mm_stream_t * my_obj);
+int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj);
+int32_t mm_stream_request_buf(mm_stream_t * my_obj);
+int32_t mm_stream_unreg_buf(mm_stream_t * my_obj);
+int32_t mm_stream_release(mm_stream_t *my_obj);
+int32_t mm_stream_get_crop(mm_stream_t *my_obj,
+ mm_camera_rect_t *crop);
+int32_t mm_stream_get_cid(mm_stream_t *my_obj,
+ stream_cid_t *out_value);
+int32_t mm_stream_set_parm_acquire(mm_stream_t *my_obj,
+ void *value);
+int32_t mm_stream_get_parm_acquire(mm_stream_t *my_obj,
+ void *value);
+int32_t mm_stream_set_parm_config(mm_stream_t *my_obj,
+ void *value);
+int32_t mm_stream_get_parm_config(mm_stream_t *my_obj,
+ void *value);
+int32_t mm_stream_set_parm_start(mm_stream_t *my_obj,
+ void *value);
+int32_t mm_stream_get_parm_start(mm_stream_t *my_obj,
+ void *value);
+int32_t mm_stream_streamon(mm_stream_t *my_obj);
+int32_t mm_stream_streamoff(mm_stream_t *my_obj);
+int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
+ mm_camera_buf_info_t* buf_info);
+int32_t mm_stream_config(mm_stream_t *my_obj,
+ mm_camera_stream_config_t *config);
+uint8_t mm_stream_need_stream_on(mm_stream_t *my_obj);
+int32_t mm_stream_reg_buf(mm_stream_t * my_obj);
+int32_t mm_stream_buf_done(mm_stream_t * my_obj,
+ mm_camera_buf_def_t *frame);
+
+
+/* state machine function declare */
+int32_t mm_stream_fsm_inited(mm_stream_t * my_obj,
+ mm_stream_evt_type_t evt,
+ void * in_val,
+ void * out_val);
+int32_t mm_stream_fsm_acquired(mm_stream_t * my_obj,
+ mm_stream_evt_type_t evt,
+ void * in_val,
+ void * out_val);
+int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj,
+ mm_stream_evt_type_t evt,
+ void * in_val,
+ void * out_val);
+int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj,
+ mm_stream_evt_type_t evt,
+ void * in_val,
+ void * out_val);
+int32_t mm_stream_fsm_reg(mm_stream_t * my_obj,
+ mm_stream_evt_type_t evt,
+ void * in_val,
+ void * out_val);
+int32_t mm_stream_fsm_active_stream_on(mm_stream_t * my_obj,
+ mm_stream_evt_type_t evt,
+ void * in_val,
+ void * out_val);
+int32_t mm_stream_fsm_active_stream_off(mm_stream_t * my_obj,
+ mm_stream_evt_type_t evt,
+ void * in_val,
+ void * out_val);
+
+extern int32_t mm_camera_send_native_ctrl_cmd(mm_camera_obj_t * my_obj,
+ cam_ctrl_type type,
+ uint32_t length,
+ void *value);
+
+static int get_stream_inst_handle(mm_stream_t *my_obj)
+{
+ int rc = 0;
+ uint32_t inst_handle;
+ struct msm_camera_v4l2_ioctl_t v4l2_ioctl;
+
+ v4l2_ioctl.id = MSM_V4L2_PID_INST_HANDLE;
+ v4l2_ioctl.ioctl_ptr = &inst_handle;
+ v4l2_ioctl.len = sizeof(inst_handle);
+ rc = ioctl(my_obj->fd, MSM_CAM_V4L2_IOCTL_PRIVATE_G_CTRL, &v4l2_ioctl);
+ if (rc) {
+ CDBG_ERROR("%s Error getting mctl pp inst handle", __func__);
+ return rc;
+ }
+
+ my_obj->inst_hdl = inst_handle;
+ CDBG("%s: inst handle = %x rc = %d\n", __func__,
+ my_obj->inst_hdl, rc);
+ return rc;
+}
+
+void mm_stream_handle_rcvd_buf(mm_stream_t *my_obj,
+ mm_camera_buf_info_t *buf_info)
+{
+ int32_t i;
+ uint8_t has_cb = 0;
+
+ /* enqueue to super buf thread */
+ if (my_obj->is_bundled) {
+ mm_camera_cmdcb_t* node = NULL;
+
+ /* send sem_post to wake up channel cmd thread to enqueue to super buffer */
+ node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
+ if (NULL != node) {
+ memset(node, 0, sizeof(mm_camera_cmdcb_t));
+ node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB;
+ memcpy(&node->u.buf, buf_info, sizeof(mm_camera_buf_info_t));
+
+ /* enqueue to cmd thread */
+ mm_camera_queue_enq(&(my_obj->ch_obj->cmd_thread.cmd_queue), node);
+
+ /* wake up cmd thread */
+ sem_post(&(my_obj->ch_obj->cmd_thread.cmd_sem));
+ } else {
+ CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
+ }
+ }
+
+ /* check if has CB */
+ for (i=0 ; i< MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
+ if(NULL != my_obj->buf_cb[i].cb) {
+ has_cb = 1;
+ }
+ }
+ if(has_cb) {
+ mm_camera_cmdcb_t* node = NULL;
+
+ /* send sem_post to wake up cmd thread to dispatch dataCB */
+ node = (mm_camera_cmdcb_t *)malloc(sizeof(mm_camera_cmdcb_t));
+ if (NULL != node) {
+ memset(node, 0, sizeof(mm_camera_cmdcb_t));
+ node->cmd_type = MM_CAMERA_CMD_TYPE_DATA_CB;
+ memcpy(&node->u.buf, buf_info, sizeof(mm_camera_buf_info_t));
+
+ /* enqueue to cmd thread */
+ mm_camera_queue_enq(&(my_obj->cmd_thread.cmd_queue), node);
+
+ /* wake up cmd thread */
+ sem_post(&(my_obj->cmd_thread.cmd_sem));
+ } else {
+ CDBG_ERROR("%s: No memory for mm_camera_node_t", __func__);
+ }
+ }
+}
+
+static void mm_stream_data_notify(void* user_data)
+{
+ mm_stream_t *my_obj = (mm_stream_t*)user_data;
+ int32_t idx = -1, i, rc;
+ uint8_t has_cb = 0;
+ mm_camera_buf_info_t buf_info;
+
+ if (NULL == my_obj) {
+ return;
+ }
+
+ if (MM_STREAM_STATE_ACTIVE_STREAM_ON != my_obj->state) {
+ /* this Cb will only received in active_stream_on state
+ * if not so, return here */
+ CDBG_ERROR("%s: ERROR!! Wrong state (%d) to receive data notify!",
+ __func__, my_obj->state);
+ return;
+ }
+
+ memset(&buf_info, 0, sizeof(mm_camera_buf_info_t));
+
+ pthread_mutex_lock(&my_obj->buf_lock);
+ rc = mm_stream_read_msm_frame(my_obj, &buf_info);
+ if (rc != 0) {
+ pthread_mutex_unlock(&my_obj->buf_lock);
+ return;
+ }
+ idx = buf_info.buf->buf_idx;
+
+ /* update buffer location */
+ my_obj->buf_status[idx].in_kernel = 0;
+
+ /* update buf ref count */
+ if (my_obj->is_bundled) {
+ /* need to add into super buf since bundled, add ref count */
+ my_obj->buf_status[idx].buf_refcnt++;
+ }
+
+ for (i=0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
+ if(NULL != my_obj->buf_cb[i].cb) {
+ /* for every CB, add ref count */
+ my_obj->buf_status[idx].buf_refcnt++;
+ has_cb = 1;
+ }
+ }
+ pthread_mutex_unlock(&my_obj->buf_lock);
+
+ mm_stream_handle_rcvd_buf(my_obj, &buf_info);
+}
+
+/* special function for dataCB registered at other stream */
+static void mm_stream_buf_notify(mm_camera_super_buf_t *super_buf,
+ void *user_data)
+{
+ mm_stream_t * my_obj = (mm_stream_t*)user_data;
+ mm_camera_buf_info_t buf_info;
+ int8_t i;
+ mm_camera_buf_def_t *buf = super_buf->bufs[0];
+
+ CDBG("%s : E",__func__);
+ if (my_obj == NULL) {
+ return;
+ }
+
+ if (MM_STREAM_STATE_ACTIVE_STREAM_OFF != my_obj->state) {
+ /* this CB will only received in active_stream_off state
+ * if not so, return here */
+ return;
+ }
+
+ /* 1) copy buf into local buf */
+ if (my_obj->buf_num <= 0) {
+ CDBG_ERROR("%s: Local buf is not allocated yet", __func__);
+ return;
+ }
+
+ my_obj->buf[0].buf_idx = 0;
+ my_obj->buf[0].stream_id = my_obj->my_hdl;
+ my_obj->buf[0].frame_idx = buf->frame_idx;
+
+ memcpy(&my_obj->buf[0].ts, &buf->ts, sizeof(buf->ts));
+
+ memcpy(&my_obj->buf[0].planes,&buf->planes,buf->num_planes * sizeof(struct v4l2_plane));
+
+ /* set flag to indicate buf be to sent out is from local */
+ my_obj->is_local_buf = 1;
+
+ /* 2) buf_done the buf from other stream */
+ mm_channel_qbuf(my_obj->ch_obj, buf);
+
+ /* 3) handle received buf */
+ memset(&buf_info, 0, sizeof(mm_camera_buf_info_t));
+ buf_info.frame_idx =my_obj->buf[0].frame_idx;
+ buf_info.buf = &my_obj->buf[0];
+ buf_info.stream_id = my_obj->my_hdl;
+ mm_stream_handle_rcvd_buf(my_obj, &buf_info);
+}
+
+static void mm_stream_dispatch_app_data(mm_camera_cmdcb_t *cmd_cb,
+ void* user_data)
+{
+ int i;
+ mm_stream_t * my_obj = (mm_stream_t *)user_data;
+ mm_camera_buf_info_t* buf_info = NULL;
+ mm_camera_super_buf_t super_buf;
+
+ if (NULL == my_obj) {
+ return;
+ }
+
+ if (MM_CAMERA_CMD_TYPE_DATA_CB != cmd_cb->cmd_type) {
+ CDBG_ERROR("%s: Wrong cmd_type (%d) for dataCB",
+ __func__, cmd_cb->cmd_type);
+ return;
+ }
+
+ buf_info = &cmd_cb->u.buf;
+ memset(&super_buf, 0, sizeof(mm_camera_super_buf_t));
+ super_buf.num_bufs = 1;
+ super_buf.bufs[0] = buf_info->buf;
+ super_buf.camera_handle = my_obj->ch_obj->cam_obj->my_hdl;
+ super_buf.ch_id = my_obj->ch_obj->my_hdl;
+
+
+ pthread_mutex_lock(&my_obj->cb_lock);
+ for(i = 0; i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
+ if(NULL != my_obj->buf_cb[i].cb) {
+ if (my_obj->buf_cb[i].cb_count != 0) {
+ /* if <0, means infinite CB
+ * if >0, means CB for certain times
+ * both case we need to call CB */
+ my_obj->buf_cb[i].cb(&super_buf,
+ my_obj->buf_cb[i].user_data);
+ }
+
+ /* if >0, reduce count by 1 every time we called CB until reaches 0
+ * when count reach 0, reset the buf_cb to have no CB */
+ if (my_obj->buf_cb[i].cb_count > 0) {
+ my_obj->buf_cb[i].cb_count--;
+ if (0 == my_obj->buf_cb[i].cb_count) {
+ my_obj->buf_cb[i].cb = NULL;
+ my_obj->buf_cb[i].user_data = NULL;
+ }
+ }
+ }
+ }
+ pthread_mutex_unlock(&my_obj->cb_lock);
+}
+
+/* state machine entry */
+int32_t mm_stream_fsm_fn(mm_stream_t *my_obj,
+ mm_stream_evt_type_t evt,
+ void * in_val,
+ void * out_val)
+{
+ int32_t rc = -1;
+
+ CDBG("%s : E - evt = %d, my_obj->state = %d",__func__,evt,my_obj->state);
+ switch (my_obj->state) {
+ case MM_STREAM_STATE_NOTUSED:
+ CDBG("%s: Not handling evt in unused state", __func__);
+ break;
+ case MM_STREAM_STATE_INITED:
+ rc = mm_stream_fsm_inited(my_obj, evt, in_val, out_val);
+ break;
+ case MM_STREAM_STATE_ACQUIRED:
+ rc = mm_stream_fsm_acquired(my_obj, evt, in_val, out_val);
+ break;
+ case MM_STREAM_STATE_CFG:
+ rc = mm_stream_fsm_cfg(my_obj, evt, in_val, out_val);
+ break;
+ case MM_STREAM_STATE_BUFFED:
+ rc = mm_stream_fsm_buffed(my_obj, evt, in_val, out_val);
+ break;
+ case MM_STREAM_STATE_REG:
+ rc = mm_stream_fsm_reg(my_obj, evt, in_val, out_val);
+ break;
+ case MM_STREAM_STATE_ACTIVE_STREAM_ON:
+ rc = mm_stream_fsm_active_stream_on(my_obj, evt, in_val, out_val);
+ break;
+ case MM_STREAM_STATE_ACTIVE_STREAM_OFF:
+ rc = mm_stream_fsm_active_stream_off(my_obj, evt, in_val, out_val);
+ break;
+ default:
+ CDBG("%s: Not a valid state (%d)", __func__, my_obj->state);
+ break;
+ }
+ CDBG("%s : X rc =%d",__func__,rc);
+ return rc;
+}
+
+int32_t mm_stream_fsm_inited(mm_stream_t *my_obj,
+ mm_stream_evt_type_t evt,
+ void * in_val,
+ void * out_val)
+{
+ int32_t rc = 0;
+ char dev_name[MM_CAMERA_DEV_NAME_LEN];
+
+ CDBG("%s :E evt = %d",__func__,evt);
+ switch(evt) {
+ case MM_STREAM_EVT_ACQUIRE:
+ if ((NULL == my_obj->ch_obj) || (NULL == my_obj->ch_obj->cam_obj)) {
+ CDBG_ERROR("%s: NULL channel or camera obj\n", __func__);
+ rc = -1;
+ break;
+ }
+
+ snprintf(dev_name, sizeof(dev_name), "/dev/%s",
+ mm_camera_util_get_dev_name(my_obj->ch_obj->cam_obj->my_hdl));
+
+ my_obj->fd = open(dev_name, O_RDWR | O_NONBLOCK);
+ if (my_obj->fd <= 0) {
+ CDBG_ERROR("%s: open dev returned %d\n", __func__, my_obj->fd);
+ rc = -1;
+ break;
+ }
+ CDBG("%s: open dev fd = %d, ext_image_mode = %d, sensor_idx = %d\n",
+ __func__, my_obj->fd, my_obj->ext_image_mode, my_obj->sensor_idx);
+ rc = mm_stream_set_ext_mode(my_obj);
+ if (0 == rc) {
+ my_obj->state = MM_STREAM_STATE_ACQUIRED;
+ } else {
+ /* failed setting ext_mode
+ * close fd */
+ if(my_obj->fd > 0) {
+ close(my_obj->fd);
+ my_obj->fd = -1;
+ }
+ break;
+ }
+ rc = get_stream_inst_handle(my_obj);
+ if(rc) {
+ if(my_obj->fd > 0) {
+ close(my_obj->fd);
+ my_obj->fd = -1;
+ }
+ }
+ break;
+ default:
+ CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
+ __func__,evt,my_obj->state);
+ rc = -1;
+ break;
+ }
+ return rc;
+}
+
+int32_t mm_stream_fsm_acquired(mm_stream_t *my_obj,
+ mm_stream_evt_type_t evt,
+ void * in_val,
+ void * out_val)
+{
+ int32_t rc = 0;
+
+ CDBG("%s :E evt = %d",__func__,evt);
+ switch(evt) {
+ case MM_STREAM_EVT_SET_FMT:
+ {
+ mm_camera_stream_config_t *config =
+ (mm_camera_stream_config_t *)in_val;
+
+ rc = mm_stream_config(my_obj, config);
+
+ /* change state to configed */
+ my_obj->state = MM_STREAM_STATE_CFG;
+
+ break;
+ }
+ case MM_STREAM_EVT_RELEASE:
+ rc = mm_stream_release(my_obj);
+ /* change state to not used */
+ my_obj->state = MM_STREAM_STATE_NOTUSED;
+ break;
+ case MM_STREAM_EVT_SET_PARM:
+ rc = mm_stream_set_parm_acquire(my_obj, in_val);
+ break;
+ case MM_STREAM_EVT_GET_PARM:
+ rc = mm_stream_get_parm_acquire(my_obj,out_val);
+ break;
+ default:
+ CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
+ __func__, evt, my_obj->state);
+ rc = -1;
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+int32_t mm_stream_fsm_cfg(mm_stream_t * my_obj,
+ mm_stream_evt_type_t evt,
+ void * in_val,
+ void * out_val)
+{
+ int32_t rc = 0;
+ CDBG("%s :E evt = %d",__func__,evt);
+ switch(evt) {
+ case MM_STREAM_EVT_SET_FMT:
+ {
+ mm_camera_stream_config_t *config =
+ (mm_camera_stream_config_t *)in_val;
+
+ rc = mm_stream_config(my_obj, config);
+
+ /* change state to configed */
+ my_obj->state = MM_STREAM_STATE_CFG;
+
+ break;
+ }
+ case MM_STREAM_EVT_RELEASE:
+ rc = mm_stream_release(my_obj);
+ my_obj->state = MM_STREAM_STATE_NOTUSED;
+ break;
+ case MM_STREAM_EVT_SET_PARM:
+ rc = mm_stream_set_parm_config(my_obj, in_val);
+ break;
+ case MM_STREAM_EVT_GET_PARM:
+ rc = mm_stream_get_parm_config(my_obj, out_val);
+ break;
+ case MM_STREAM_EVT_GET_BUF:
+ rc = mm_stream_init_bufs(my_obj);
+ /* change state to buff allocated */
+ if(0 == rc) {
+ my_obj->state = MM_STREAM_STATE_BUFFED;
+ }
+ break;
+ default:
+ CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
+ __func__, evt, my_obj->state);
+ rc = -1;
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+int32_t mm_stream_fsm_buffed(mm_stream_t * my_obj,
+ mm_stream_evt_type_t evt,
+ void * in_val,
+ void * out_val)
+{
+ int32_t rc = 0;
+ CDBG("%s :E evt = %d",__func__,evt);
+ switch(evt) {
+ case MM_STREAM_EVT_PUT_BUF:
+ rc = mm_stream_deinit_bufs(my_obj);
+ /* change state to configed */
+ if(0 == rc) {
+ my_obj->state = MM_STREAM_STATE_CFG;
+ }
+ break;
+ case MM_STREAM_EVT_REG_BUF:
+ rc = mm_stream_reg_buf(my_obj);
+ /* change state to regged */
+ if(0 == rc) {
+ my_obj->state = MM_STREAM_STATE_REG;
+ }
+ break;
+ case MM_STREAM_EVT_SET_PARM:
+ rc = mm_stream_set_parm_config(my_obj, in_val);
+ break;
+ case MM_STREAM_EVT_GET_PARM:
+ rc = mm_stream_get_parm_config(my_obj, out_val);
+ break;
+ default:
+ CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
+ __func__, evt, my_obj->state);
+ rc = -1;
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+int32_t mm_stream_fsm_reg(mm_stream_t * my_obj,
+ mm_stream_evt_type_t evt,
+ void * in_val,
+ void * out_val)
+{
+ int32_t rc = 0;
+ CDBG("%s :E evt = %d",__func__,evt);
+
+ switch(evt) {
+ case MM_STREAM_EVT_UNREG_BUF:
+ rc = mm_stream_unreg_buf(my_obj);
+
+ /* change state to buffed */
+ my_obj->state = MM_STREAM_STATE_BUFFED;
+ break;
+ case MM_STREAM_EVT_START:
+ {
+ /* launch cmd thread if CB is not null */
+ if (NULL != my_obj->buf_cb) {
+ mm_camera_cmd_thread_launch(&my_obj->cmd_thread,
+ mm_stream_dispatch_app_data,
+ (void *)my_obj);
+
+ }
+
+ if(mm_stream_need_stream_on(my_obj)) {
+ rc = mm_stream_streamon(my_obj);
+ if (0 != rc) {
+ /* failed stream on, need to release cmd thread if it's launched */
+ if (NULL != my_obj->buf_cb) {
+ mm_camera_cmd_thread_release(&my_obj->cmd_thread);
+
+ }
+ break;
+ }
+ my_obj->state = MM_STREAM_STATE_ACTIVE_STREAM_ON;
+ } else {
+ /* register one time CB at video fd */
+ CDBG("%s : Video Size snapshot Enabled",__func__);
+ mm_stream_data_cb_t cb;
+ memset(&cb, 0, sizeof(mm_stream_data_cb_t));
+ cb.cb_count = 1; /* one time reigstration */
+ cb.user_data = (void*)my_obj;
+ cb.cb = mm_stream_buf_notify;
+ rc = mm_channel_reg_stream_cb(my_obj->ch_obj, &cb,
+ MSM_V4L2_EXT_CAPTURE_MODE_VIDEO,
+ my_obj->sensor_idx);
+ my_obj->state = MM_STREAM_STATE_ACTIVE_STREAM_OFF;
+ }
+ }
+ break;
+ case MM_STREAM_EVT_SET_PARM:
+ rc = mm_stream_set_parm_config(my_obj, in_val);
+ break;
+ case MM_STREAM_EVT_GET_PARM:
+ rc = mm_stream_get_parm_config(my_obj, out_val);
+ break;
+ default:
+ CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
+ __func__, evt, my_obj->state);
+ rc = -1;
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+int32_t mm_stream_fsm_active_stream_on(mm_stream_t * my_obj,
+ mm_stream_evt_type_t evt,
+ void * in_val,
+ void * out_val)
+{
+ int32_t rc = 0;
+ CDBG("%s :E evt = %d",__func__,evt);
+ switch(evt) {
+ case MM_STREAM_EVT_QBUF:
+ rc = mm_stream_buf_done(my_obj, (mm_camera_buf_def_t *)in_val);
+ break;
+ case MM_STREAM_EVT_STOP:
+ {
+ rc = mm_stream_streamoff(my_obj);
+ if (NULL != my_obj->buf_cb) {
+ mm_camera_cmd_thread_release(&my_obj->cmd_thread);
+
+ }
+ my_obj->state = MM_STREAM_STATE_REG;
+ }
+ break;
+ case MM_STREAM_EVT_SET_PARM:
+ rc = mm_stream_set_parm_start(my_obj, in_val);
+ break;
+ case MM_STREAM_EVT_GET_PARM:
+ rc = mm_stream_get_parm_start(my_obj, out_val);
+ break;
+ default:
+ CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
+ __func__, evt, my_obj->state);
+ return -1;
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+int32_t mm_stream_fsm_active_stream_off(mm_stream_t * my_obj,
+ mm_stream_evt_type_t evt,
+ void * in_val,
+ void * out_val)
+{
+ int32_t rc = 0;
+ CDBG("%s :E evt = %d",__func__,evt);
+ switch(evt) {
+ case MM_STREAM_EVT_QBUF:
+ rc = mm_stream_buf_done(my_obj, (mm_camera_buf_def_t *)in_val);
+ break;
+ case MM_STREAM_EVT_STOP:
+ {
+ if (NULL != my_obj->buf_cb) {
+ rc = mm_camera_cmd_thread_release(&my_obj->cmd_thread);
+
+ }
+ my_obj->state = MM_STREAM_STATE_REG;
+ }
+ break;
+ case MM_STREAM_EVT_SET_PARM:
+ rc = mm_stream_set_parm_config(my_obj, in_val);
+ break;
+ case MM_STREAM_EVT_GET_PARM:
+ rc = mm_stream_get_parm_config(my_obj, out_val);
+ break;
+ default:
+ CDBG_ERROR("%s: Invalid evt=%d, stream_state=%d",
+ __func__, evt, my_obj->state);
+ return -1;
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+int32_t mm_stream_config(mm_stream_t *my_obj,
+ mm_camera_stream_config_t *config)
+{
+ int32_t rc = 0;
+ memcpy(&my_obj->fmt, &config->fmt, sizeof(mm_camera_image_fmt_t));
+ my_obj->hal_requested_num_bufs = config->num_of_bufs;
+ my_obj->need_stream_on = config->need_stream_on;
+
+ rc = mm_stream_get_offset(my_obj);
+ if(rc != 0) {
+ CDBG_ERROR("%s: Error in offset query",__func__);
+ return rc;
+ }
+ if(mm_stream_need_stream_on(my_obj)) {
+ /* only send fmt to backend if we need streamon */
+ rc = mm_stream_set_fmt(my_obj);
+ }
+ return rc;
+}
+
+int32_t mm_stream_release(mm_stream_t *my_obj)
+{
+ int32_t rc;
+
+ /* close fd */
+ if(my_obj->fd > 0)
+ {
+ close(my_obj->fd);
+ }
+
+ /* destroy mutex */
+ pthread_mutex_destroy(&my_obj->buf_lock);
+ pthread_mutex_destroy(&my_obj->cb_lock);
+
+ /* reset stream obj */
+ memset(my_obj, 0, sizeof(mm_stream_t));
+ my_obj->fd = -1;
+
+ return 0;
+}
+
+uint8_t mm_stream_need_stream_on(mm_stream_t *my_obj)
+{
+ return my_obj->need_stream_on;
+}
+
+int32_t mm_stream_streamon(mm_stream_t *my_obj)
+{
+ int32_t rc;
+ enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+
+ CDBG("%s :E",__func__);
+ /* Add fd to data poll thread */
+ rc = mm_camera_poll_thread_add_poll_fd(&my_obj->ch_obj->poll_thread[0],
+ my_obj->my_hdl,
+ my_obj->fd,
+ mm_stream_data_notify,
+ (void*)my_obj);
+ if (rc < 0) {
+ return rc;
+ }
+ rc = ioctl(my_obj->fd, VIDIOC_STREAMON, &buf_type);
+ if (rc < 0) {
+ CDBG_ERROR("%s: ioctl VIDIOC_STREAMON failed: rc=%d\n",
+ __func__, rc);
+ /* remove fd from data poll thread in case of failure */
+ mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl);
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+int32_t mm_stream_streamoff(mm_stream_t *my_obj)
+{
+ int32_t rc;
+ enum v4l2_buf_type buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+
+ /* step1: remove fd from data poll thread */
+ mm_camera_poll_thread_del_poll_fd(&my_obj->ch_obj->poll_thread[0], my_obj->my_hdl);
+
+ /* step2: stream off */
+ rc = ioctl(my_obj->fd, VIDIOC_STREAMOFF, &buf_type);
+ if (rc < 0) {
+ CDBG_ERROR("%s: STREAMOFF failed: %s\n",
+ __func__, strerror(errno));
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+static uint32_t mm_stream_util_get_v4l2_fmt(cam_format_t fmt,
+ uint8_t *num_planes)
+{
+ uint32_t val;
+ switch(fmt) {
+ case CAMERA_YUV_420_NV12:
+ val = V4L2_PIX_FMT_NV12;
+ *num_planes = 2;
+ break;
+ case CAMERA_YUV_420_NV21:
+ val = V4L2_PIX_FMT_NV21;
+ *num_planes = 2;
+ break;
+ case CAMERA_BAYER_SBGGR10:
+ case CAMERA_RDI:
+ val= V4L2_PIX_FMT_SBGGR10;
+ *num_planes = 1;
+ break;
+ case CAMERA_YUV_422_NV61:
+ val= V4L2_PIX_FMT_NV61;
+ *num_planes = 2;
+ break;
+ default:
+ val = 0;
+ *num_planes = 0;
+ break;
+ }
+ return val;
+}
+
+int32_t mm_stream_read_msm_frame(mm_stream_t * my_obj,
+ mm_camera_buf_info_t* buf_info)
+{
+ int32_t idx = -1, rc = 0;
+ struct v4l2_buffer vb;
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+ uint32_t i = 0;
+ uint8_t num_planes = 0;
+
+ mm_stream_util_get_v4l2_fmt(my_obj->fmt.fmt,
+ &num_planes);
+
+ memset(&vb, 0, sizeof(vb));
+ vb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ vb.memory = V4L2_MEMORY_USERPTR;
+ vb.m.planes = &planes[0];
+ vb.length = num_planes;
+
+ rc = ioctl(my_obj->fd, VIDIOC_DQBUF, &vb);
+ if (rc < 0) {
+ CDBG_ERROR("%s: VIDIOC_DQBUF ioctl call failed (rc=%d)\n",
+ __func__, rc);
+ } else {
+ int8_t idx = vb.index;
+ buf_info->buf = &my_obj->buf[idx];
+ buf_info->frame_idx = vb.sequence;
+ buf_info->stream_id = my_obj->my_hdl;
+ buf_info->need_pp = my_obj->is_pp_needed;
+
+ buf_info->buf->stream_id = my_obj->my_hdl;
+ buf_info->buf->buf_idx = idx;
+ buf_info->buf->frame_idx = vb.sequence;
+ buf_info->buf->ts.tv_sec = vb.timestamp.tv_sec;
+ buf_info->buf->ts.tv_nsec = vb.timestamp.tv_usec * 1000;
+
+ for(i = 0; i < vb.length; i++) {
+ CDBG("%s plane %d addr offset: %d data offset:%d\n",
+ __func__, i, vb.m.planes[i].reserved[0],
+ vb.m.planes[i].data_offset);
+ buf_info->buf->planes[i].reserved[0] =
+ vb.m.planes[i].reserved[0];
+ buf_info->buf->planes[i].data_offset =
+ vb.m.planes[i].data_offset;
+ }
+
+
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+int32_t mm_stream_get_crop(mm_stream_t *my_obj,
+ mm_camera_rect_t *crop)
+{
+ struct v4l2_crop crop_info;
+ int32_t rc = 0;
+
+ memset(&crop_info, 0, sizeof(crop_info));
+ crop_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ rc = ioctl(my_obj->fd, VIDIOC_G_CROP, &crop_info);
+ if (0 == rc) {
+ crop->left = crop_info.c.left;
+ crop->top = crop_info.c.top;
+ crop->width = crop_info.c.width;
+ crop->height = crop_info.c.height;
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+int32_t mm_stream_set_parm_acquire(mm_stream_t *my_obj,
+ void *in_value)
+{
+ int32_t rc = 0;
+ mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)in_value;
+ mm_camera_stream_parm_t parm_type = payload->parm_type;
+
+ CDBG("%s: parm_type = %d",__func__,(int)parm_type);
+ switch(parm_type) {
+ case MM_CAMERA_STREAM_CID:{
+ stream_cid_t *value = (stream_cid_t *)in_value;
+ mm_stream_set_cid(my_obj,value);
+ break;
+ }
+ default:
+ CDBG_ERROR("%s : Parm -%d set is not supported here",__func__,(int)parm_type);
+ break;
+ }
+ return rc;
+}
+int32_t mm_stream_get_parm_acquire(mm_stream_t *my_obj,
+ void *out_value)
+{
+ int32_t rc = 0;
+ mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)out_value;
+ mm_camera_stream_parm_t parm_type = payload->parm_type;
+
+ CDBG("%s: parm_type = %d",__func__,(int)parm_type);
+ switch(parm_type) {
+ case MM_CAMERA_STREAM_CID:{
+ stream_cid_t *value = (stream_cid_t *)out_value;
+ rc = mm_stream_get_cid(my_obj,value);
+ break;
+ }
+ case MM_CAMERA_STREAM_CROP:{
+ mm_camera_rect_t *crop = (mm_camera_rect_t *)out_value;
+ rc = mm_stream_get_crop(my_obj, crop);
+ break;
+ }
+ default:
+ CDBG_ERROR("%s : Parm -%d get is not supported here",__func__,(int)parm_type);
+ break;
+ }
+ return rc;
+}
+
+int32_t mm_stream_set_parm_config(mm_stream_t *my_obj,
+ void *in_value)
+{
+ int32_t rc = 0;
+ mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)in_value;
+ mm_camera_stream_parm_t parm_type = payload->parm_type;
+ void *value = payload->value;
+
+ CDBG("%s: parm_type = %d",__func__,(int)parm_type);
+ switch(parm_type) {
+ default:
+ CDBG_ERROR("%s : Parm -%d set is not supported here",__func__,(int)parm_type);
+ break;
+ }
+ return rc;
+}
+int32_t mm_stream_get_parm_config(mm_stream_t *my_obj,
+ void *out_value)
+{
+ int32_t rc = 0;
+ mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)out_value;
+
+ if(payload == NULL) {
+ CDBG_ERROR("%s : Invalid Argument",__func__);
+ return -1;
+ }
+ CDBG("%s: parm_type = %d",__func__,(int)payload->parm_type);
+ switch(payload->parm_type) {
+ case MM_CAMERA_STREAM_OFFSET:
+ memcpy(payload->value,(void *)&my_obj->frame_offset,sizeof(mm_camera_frame_len_offset));
+ break;
+ case MM_CAMERA_STREAM_CROP:{
+ mm_camera_rect_t *crop = (mm_camera_rect_t *)payload->value;
+ rc = mm_stream_get_crop(my_obj, crop);
+ break;
+ }
+ default:
+ CDBG_ERROR("%s : Parm -%d get is not supported here",__func__,(int)payload->parm_type);
+ break;
+ }
+ return rc;
+}
+
+int32_t mm_stream_set_parm_start(mm_stream_t *my_obj,
+ void *in_value)
+{
+ int32_t rc = 0;
+ mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)in_value;
+ mm_camera_stream_parm_t parm_type = payload->parm_type;
+ void *value = payload->value;
+
+ CDBG("%s: parm_type = %d",__func__,(int)parm_type);
+ switch(parm_type) {
+ default:
+ CDBG_ERROR("%s : Parm -%d set is not supported here",__func__,(int)parm_type);
+ break;
+ }
+ return rc;
+}
+int32_t mm_stream_get_parm_start(mm_stream_t *my_obj,
+ void *out_value)
+{
+ int32_t rc = 0;
+ mm_evt_paylod_stream_parm_t *payload = (mm_evt_paylod_stream_parm_t *)out_value;
+
+ if(payload == NULL) {
+ CDBG_ERROR("%s : Invalid Argument",__func__);
+ return -1;
+ }
+ CDBG("%s: parm_type = %d",__func__,(int)payload->parm_type);
+ switch(payload->parm_type) {
+ case MM_CAMERA_STREAM_OFFSET:
+ memcpy(payload->value,(void *)&my_obj->frame_offset,sizeof(mm_camera_frame_len_offset));
+ break;
+ case MM_CAMERA_STREAM_CROP:{
+ mm_camera_rect_t *crop = (mm_camera_rect_t *)payload->value;
+ rc = mm_stream_get_crop(my_obj, crop);
+ break;
+ }
+ default:
+ CDBG_ERROR("%s : Parm -%d get is not supported here",__func__,(int)payload->parm_type);
+ break;
+ }
+ return rc;
+}
+int32_t mm_stream_set_ext_mode(mm_stream_t * my_obj)
+{
+ int32_t rc = 0;
+ struct v4l2_streamparm s_parm;
+
+ s_parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ s_parm.parm.capture.extendedmode = my_obj->ext_image_mode;
+
+ rc = ioctl(my_obj->fd, VIDIOC_S_PARM, &s_parm);
+ CDBG("%s:stream fd=%d, rc=%d, extended_mode=%d\n",
+ __func__, my_obj->fd, rc,
+ s_parm.parm.capture.extendedmode);
+ return rc;
+}
+
+int32_t mm_stream_qbuf(mm_stream_t *my_obj, mm_camera_buf_def_t *buf)
+{
+ int32_t i, rc = 0;
+ int *ret;
+ struct v4l2_buffer buffer;
+
+ memset(&buffer, 0, sizeof(buffer));
+ buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ buffer.memory = V4L2_MEMORY_USERPTR;
+ buffer.index = buf->buf_idx;
+ buffer.m.planes = &buf->planes[0];
+ buffer.length = buf->num_planes;
+
+ CDBG("%s:stream_hdl=%d,fd=%d,frame idx=%d,num_planes = %d\n", __func__,
+ buf->stream_id, buf->fd, buffer.index, buffer.length);
+
+ rc = ioctl(my_obj->fd, VIDIOC_QBUF, &buffer);
+ CDBG("%s: qbuf idx:%d, rc:%d", __func__, buffer.index, rc);
+ return rc;
+}
+
+/* This function let kernel know amount of buffers will be registered */
+int32_t mm_stream_request_buf(mm_stream_t * my_obj)
+{
+ int32_t rc = 0;
+ uint8_t i,reg = 0;
+ struct v4l2_requestbuffers bufreq;
+ uint8_t buf_num = my_obj->buf_num;
+
+ if(buf_num > MM_CAMERA_MAX_NUM_FRAMES) {
+ CDBG_ERROR("%s: buf num %d > max limit %d\n",
+ __func__, buf_num, MM_CAMERA_MAX_NUM_FRAMES);
+ return -1;
+ }
+ pthread_mutex_lock(&my_obj->buf_lock);
+ for(i = 0; i < buf_num; i++){
+ if (my_obj->buf_status[i].initial_reg_flag){
+ reg = 1;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&my_obj->buf_lock);
+ if(!reg) {
+ //No need to register a buffer
+ CDBG_ERROR("No Need to register this buffer");
+ return rc;
+ }
+ memset(&bufreq, 0, sizeof(bufreq));
+ bufreq.count = buf_num;
+ bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ bufreq.memory = V4L2_MEMORY_USERPTR;
+ rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
+ if (rc < 0) {
+ CDBG_ERROR("%s: fd=%d, ioctl VIDIOC_REQBUFS failed: rc=%d\n",
+ __func__, my_obj->fd, rc);
+ }
+ CDBG("%s :X rc = %d",__func__,rc);
+ return rc;
+}
+
+int32_t mm_stream_get_frame_len_offset(mm_camera_image_fmt_t* img_fmt,
+ camera_mode_t mode,
+ int image_type,
+ mm_camera_frame_len_offset * frame_offset)
+{
+ /* TODO : this function should query the frame len from backend using cmd */
+ /* for now, it's still use hardcoded value */
+ uint32_t width, height;
+ int local_height;
+
+ width = img_fmt->width;
+ height = img_fmt->height;
+
+ switch (img_fmt->fmt) {
+ case CAMERA_YUV_420_NV12:
+ case CAMERA_YUV_420_NV21:
+ frame_offset->num_planes = 2;
+ if (image_type == OUTPUT_TYPE_V) {
+ frame_offset->mp[0].len = PAD_TO_2K(width * height);
+ frame_offset->mp[1].len = PAD_TO_2K(width * height/2);
+ /* TODO: offset to count in meta header*/
+ frame_offset->mp[0].offset = 0;
+ frame_offset->mp[1].offset = 0;
+ } else if (image_type == OUTPUT_TYPE_P) {
+ frame_offset->mp[0].len = PAD_TO_WORD(width * height);
+ frame_offset->mp[1].len = PAD_TO_WORD(width * height/2);
+ /* TODO: offset to count in meta header*/
+ frame_offset->mp[0].offset = 0;
+ frame_offset->mp[1].offset = 0;
+ } else {
+ frame_offset->mp[0].len = PAD_TO_WORD(width * CEILING16(height));
+ frame_offset->mp[1].len = PAD_TO_WORD(width * CEILING16(height)/2);
+ /* TODO: offset to count in meta header*/
+ frame_offset->mp[0].offset = 0;
+ frame_offset->mp[1].offset = 0;
+ }
+ frame_offset->frame_len =
+ PAD_TO_4K(frame_offset->mp[0].len + frame_offset->mp[1].len);
+ break;
+ case CAMERA_BAYER_SBGGR10:
+ frame_offset->num_planes = 1;
+ frame_offset->mp[0].len = PAD_TO_WORD(width * height);
+ frame_offset->frame_len = frame_offset->mp[0].len;
+ break;
+ case CAMERA_YUV_422_NV16:
+ case CAMERA_YUV_422_NV61:
+ if( image_type == OUTPUT_TYPE_S || image_type == OUTPUT_TYPE_V) {
+ local_height = CEILING16(height);
+ } else {
+ local_height = height;
+ }
+ frame_offset->num_planes = 2;
+ frame_offset->mp[0].len = PAD_TO_WORD(width * height);
+ frame_offset->mp[1].len = PAD_TO_WORD(width * height);
+ /* TODO: offset to count in meta header*/
+ frame_offset->mp[0].offset = 0;
+ frame_offset->mp[1].offset = 0;
+ frame_offset->frame_len =
+ frame_offset->mp[0].len + frame_offset->mp[1].len;
+ break;
+ default:
+ CDBG("%s: format %d not supported.\n",
+ __func__, img_fmt->fmt);
+ frame_offset->frame_len = 0;
+ }
+ CDBG("%s:fmt=%d,image_type=%d,width=%d,height=%d,frame_len=%d\n",
+ __func__, img_fmt->fmt, image_type, width, height, frame_offset->frame_len);
+ return 0;
+}
+
+int32_t mm_stream_init_bufs(mm_stream_t * my_obj)
+{
+ int32_t i, rc = 0, j;
+ int image_type;
+ mm_camear_mem_vtbl_t *mem_vtbl = NULL;
+ mm_camera_frame_len_offset frame_offset;
+ uint8_t *reg_flags = NULL;
+
+ /* deinit buf if it's not NULL*/
+ if (NULL != my_obj->buf) {
+ mm_stream_deinit_bufs(my_obj);
+ }
+
+ my_obj->buf_num = my_obj->hal_requested_num_bufs;
+ /* if stream needs do pp, allocate extra one buf for pp*/
+ if (my_obj->is_pp_needed) {
+ my_obj->buf_num++;
+ }
+
+ my_obj->buf =
+ (mm_camera_buf_def_t*)malloc(sizeof(mm_camera_buf_def_t) * my_obj->buf_num);
+ my_obj->buf_status =
+ (mm_stream_buf_status_t*)malloc(sizeof(mm_stream_buf_status_t) * my_obj->buf_num);
+ reg_flags = (uint8_t *)malloc(sizeof(uint8_t) * my_obj->buf_num);
+
+ if (NULL == my_obj->buf ||
+ NULL == my_obj->buf_status ||
+ NULL == reg_flags) {
+ CDBG_ERROR("%s: No memory for buf", __func__);
+ rc = -1;
+ goto error_malloc;
+ }
+
+ memset(my_obj->buf, 0, sizeof(mm_camera_buf_def_t) * my_obj->buf_num);
+ memset(my_obj->buf_status, 0, sizeof(mm_stream_buf_status_t) * my_obj->buf_num);
+ memset(reg_flags, 0, sizeof(uint8_t) * my_obj->buf_num);
+
+ mem_vtbl = my_obj->ch_obj->cam_obj->mem_vtbl;
+ rc = mem_vtbl->get_buf(my_obj->ch_obj->cam_obj->my_hdl,
+ my_obj->ch_obj->my_hdl,
+ my_obj->my_hdl,
+ mem_vtbl->user_data,
+ &my_obj->frame_offset,
+ my_obj->buf_num,
+ reg_flags,
+ my_obj->buf);
+
+ if (0 != rc) {
+ CDBG_ERROR("%s: Error get buf, rc = %d\n", __func__, rc);
+ goto error_malloc;
+ }
+
+ for (i=0; i < my_obj->buf_num; i++) {
+ my_obj->buf_status[i].initial_reg_flag = reg_flags[i];
+ my_obj->buf[i].stream_id = my_obj->my_hdl;
+ }
+
+ free(reg_flags);
+ reg_flags = NULL;
+
+ for (i=0; i < my_obj->buf_num; i++) {
+ if (my_obj->buf[i].fd > 0) {
+ if(0 >= (rc = mm_camera_map_buf(my_obj->ch_obj->cam_obj,
+ my_obj->ext_image_mode,
+ i,
+ my_obj->buf[i].fd,
+ my_obj->buf[i].frame_len)))
+ {
+ CDBG_ERROR("%s: Error mapping buf (rc = %d)", __func__, rc);
+ goto error_map;
+ }
+ } else {
+ CDBG_ERROR("%s: Invalid fd for buf idx (%d)", __func__, i);
+ }
+ }
+
+ return 0;
+
+error_map:
+ /* error, unmapping previously mapped bufs */
+ for (j=0; j<i; j++) {
+ if (my_obj->buf[j].fd > 0) {
+ mm_camera_unmap_buf(my_obj->ch_obj->cam_obj,
+ my_obj->ext_image_mode,
+ j);
+ }
+ }
+
+ /* put buf back */
+ mem_vtbl->put_buf(my_obj->ch_obj->cam_obj->my_hdl,
+ my_obj->ch_obj->my_hdl,
+ my_obj->my_hdl,
+ mem_vtbl->user_data,
+ my_obj->buf_num,
+ my_obj->buf);
+
+error_malloc:
+ if (NULL != my_obj->buf) {
+ free(my_obj->buf);
+ my_obj->buf = NULL;
+ }
+ if (NULL != my_obj->buf_status) {
+ free(my_obj->buf_status);
+ my_obj->buf_status = NULL;
+ }
+ if (NULL != reg_flags) {
+ free(reg_flags);
+ reg_flags = NULL;
+ }
+
+ return rc;
+}
+
+/* return buffers to surface or release buffers allocated */
+int32_t mm_stream_deinit_bufs(mm_stream_t * my_obj)
+{
+ int32_t rc = 0, i;
+ mm_camear_mem_vtbl_t *mem_vtbl = NULL;
+
+ if (NULL == my_obj->buf) {
+ CDBG("%s: Buf is NULL, no need to deinit", __func__);
+ return rc;
+ }
+
+ /* IOMMU unmapping */
+ for (i=0; i<my_obj->buf_num; i++) {
+ if (my_obj->buf[i].fd > 0) {
+ rc = mm_camera_unmap_buf(my_obj->ch_obj->cam_obj,
+ my_obj->ext_image_mode,
+ i);
+ if (rc < 0 ) {
+ CDBG_ERROR("%s: Error unmapping bufs at idx(%d) rc=%d",
+ __func__, i, rc);
+ }
+ }
+ }
+
+ /* release bufs */
+ mem_vtbl = my_obj->ch_obj->cam_obj->mem_vtbl;
+ if (NULL != mem_vtbl) {
+ rc = mem_vtbl->put_buf(my_obj->ch_obj->cam_obj->my_hdl,
+ my_obj->ch_obj->my_hdl,
+ my_obj->my_hdl,
+ mem_vtbl->user_data,
+ my_obj->buf_num,
+ my_obj->buf);
+ } else {
+ CDBG_ERROR("%s: mem table is NULL, cannot release buf", __func__);
+ rc = -1;
+ }
+
+ free(my_obj->buf);
+ my_obj->buf = NULL;
+ free(my_obj->buf_status);
+ my_obj->buf_status = NULL;
+
+ return rc;
+}
+
+int32_t mm_stream_reg_buf(mm_stream_t * my_obj)
+{
+ int32_t rc = 0;
+ uint8_t i;
+
+ rc = mm_stream_request_buf(my_obj);
+ if (rc != 0) {
+ return rc;
+ }
+
+ pthread_mutex_lock(&my_obj->buf_lock);
+ for(i = 0; i < my_obj->buf_num; i++){
+ my_obj->buf[i].buf_idx = i;
+
+ /* check if need to qbuf initially */
+ if (my_obj->buf_status[i].initial_reg_flag) {
+ rc = mm_stream_qbuf(my_obj, &my_obj->buf[i]);
+ if (rc != 0) {
+ CDBG_ERROR("%s: VIDIOC_QBUF rc = %d\n", __func__, rc);
+ return rc;
+ }
+ }
+
+ my_obj->buf_status[i].buf_refcnt = 0;
+ my_obj->buf_status[i].in_kernel = 1;
+ }
+ pthread_mutex_unlock(&my_obj->buf_lock);
+ return rc;
+}
+
+int32_t mm_stream_unreg_buf(mm_stream_t * my_obj)
+{
+ struct v4l2_requestbuffers bufreq;
+ int32_t i, rc = 0,reg = 0;
+
+ pthread_mutex_lock(&my_obj->buf_lock);
+ if (NULL != my_obj->buf_status) {
+ for(i = 0; i < my_obj->buf_num; i++){
+ if (my_obj->buf_status[i].initial_reg_flag){
+ reg = 1;
+ break;
+ }
+ }
+ }
+ pthread_mutex_unlock(&my_obj->buf_lock);
+ if(!reg) {
+ //No need to unregister a buffer
+ goto end;
+ }
+ bufreq.count = 0;
+ bufreq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ bufreq.memory = V4L2_MEMORY_USERPTR;
+ rc = ioctl(my_obj->fd, VIDIOC_REQBUFS, &bufreq);
+ if (rc < 0) {
+ CDBG_ERROR("%s: fd=%d, VIDIOC_REQBUFS failed, rc=%d\n",
+ __func__, my_obj->fd, rc);
+ }
+
+end:
+ /* reset buf reference count */
+ pthread_mutex_lock(&my_obj->buf_lock);
+ if (NULL != my_obj->buf_status) {
+ for(i = 0; i < my_obj->buf_num; i++){
+ my_obj->buf_status[i].buf_refcnt = 0;
+ my_obj->buf_status[i].in_kernel = 0;
+ }
+ }
+ pthread_mutex_unlock(&my_obj->buf_lock);
+
+ return rc;
+}
+
+int32_t mm_stream_set_fmt(mm_stream_t *my_obj)
+{
+ int32_t rc = 0;
+ struct v4l2_format fmt;
+
+ if(my_obj->fmt.width == 0 || my_obj->fmt.height == 0) {
+ CDBG_ERROR("%s:invalid input[w=%d,h=%d,fmt=%d]\n",
+ __func__, my_obj->fmt.width, my_obj->fmt.height, my_obj->fmt.fmt);
+ return -1;
+ }
+
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ fmt.fmt.pix_mp.width = my_obj->fmt.width;
+ fmt.fmt.pix_mp.height= my_obj->fmt.height;
+ fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
+ fmt.fmt.pix_mp.pixelformat =
+ mm_stream_util_get_v4l2_fmt(my_obj->fmt.fmt,
+ &(fmt.fmt.pix_mp.num_planes));
+ rc = ioctl(my_obj->fd, VIDIOC_S_FMT, &fmt);
+ CDBG("%s:fd=%d, ext_image_mode=%d, rc=%d\n",
+ __func__, my_obj->fd, my_obj->ext_image_mode, rc);
+
+ return rc;
+}
+
+int32_t mm_stream_get_offset(mm_stream_t *my_obj)
+{
+ int32_t rc = 0;
+ cam_frame_resolution_t frame_offset;
+
+ memset(&my_obj->frame_offset,0,sizeof(mm_camera_frame_len_offset));
+
+ frame_offset.format = my_obj->fmt.fmt;
+ frame_offset.image_mode = my_obj->ext_image_mode;
+ frame_offset.rotation = my_obj->fmt.rotation;
+ frame_offset.width = my_obj->fmt.width;
+ frame_offset.height = my_obj->fmt.height;
+
+ switch (my_obj->ext_image_mode) {
+ case MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW:
+ case MSM_V4L2_EXT_CAPTURE_MODE_MAIN:
+ case MSM_V4L2_EXT_CAPTURE_MODE_RAW:
+ case MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL:
+ case MSM_V4L2_EXT_CAPTURE_MODE_RDI:
+ frame_offset.padding_format = CAMERA_PAD_TO_WORD;
+ break;
+ case MSM_V4L2_EXT_CAPTURE_MODE_VIDEO:
+ default:
+ frame_offset.padding_format = CAMERA_PAD_TO_2K;
+ break;
+ }
+
+ CDBG("%s: format = %d, image_mode = %d, padding_format = %d, rotation = %d,"
+ "width = %d height = %d",
+ __func__,frame_offset.format,frame_offset.image_mode,frame_offset.padding_format,
+ frame_offset.rotation,frame_offset.width,frame_offset.height);
+
+ rc = mm_camera_send_native_ctrl_cmd(my_obj->ch_obj->cam_obj,
+ CAMERA_GET_PARM_FRAME_RESOLUTION,
+ sizeof(cam_frame_resolution_t),
+ &frame_offset);
+ if(rc != 0) {
+ CDBG_ERROR("%s: Failed to get the stream offset and frame length",__func__);
+ return rc;
+ }
+ my_obj->fmt.width = frame_offset.width;
+ my_obj->fmt.height = frame_offset.height;
+ memcpy(&my_obj->frame_offset,&frame_offset.frame_offset,sizeof(mm_camera_frame_len_offset));
+ CDBG("%s: Frame length = %d width = %d, height = %d, rc = %d",
+ __func__,my_obj->frame_offset.frame_len,my_obj->fmt.width,my_obj->fmt.height,rc);
+ return rc;
+}
+
+
+int32_t mm_stream_set_cid(mm_stream_t *my_obj,stream_cid_t *value)
+{
+ int32_t rc = 0;
+ cam_cid_info_t cam_cid_info;
+
+ cam_cid_info.num_cids = 1;
+ cam_cid_info.cid_entries[0].cid = value->cid;
+ cam_cid_info.cid_entries[0].dt = value->dt;
+ cam_cid_info.cid_entries[0].inst_handle = my_obj->inst_hdl;
+
+ rc = mm_camera_send_native_ctrl_cmd(my_obj->ch_obj->cam_obj,
+ CAMERA_SET_PARM_CID,
+ sizeof(cam_cid_info_t),
+ &cam_cid_info);
+ if(rc != 0) {
+ CDBG_ERROR("%s: Failed to set the CID",__func__);
+ return rc;
+ }
+ return rc;
+}
+
+int32_t mm_stream_get_cid(mm_stream_t *my_obj,stream_cid_t *out_value)
+{
+ //TODO: Need to use sensor structure init in camera query
+ int32_t rc = 0;
+ return rc;
+}
+
+int32_t mm_stream_buf_done(mm_stream_t * my_obj,
+ mm_camera_buf_def_t *frame)
+{
+ int32_t rc = 0;
+
+ if (my_obj->is_local_buf) {
+ /* special case for video-sized live snapshot
+ * buf is local, no need to qbuf to kernel */
+ return 0;
+ }
+
+ pthread_mutex_lock(&my_obj->buf_lock);
+
+ if(my_obj->buf_status[frame->buf_idx].buf_refcnt == 0) {
+ CDBG("%s: Error Trying to free second time?(idx=%d) count=%d, ext_image_mode=%d\n",
+ __func__, frame->buf_idx,
+ my_obj->buf_status[frame->buf_idx].buf_refcnt,
+ my_obj->ext_image_mode);
+ rc = -1;
+ }else{
+ my_obj->buf_status[frame->buf_idx].buf_refcnt--;
+ if (0 == my_obj->buf_status[frame->buf_idx].buf_refcnt) {
+ CDBG("<DEBUG> : Buf done for buffer:%d:%d", my_obj->ext_image_mode, frame->buf_idx);
+ rc = mm_stream_qbuf(my_obj, frame);
+ if(rc < 0) {
+ CDBG_ERROR("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n",
+ __func__, frame->buf_idx, rc);
+ } else {
+ my_obj->buf_status[frame->buf_idx].in_kernel = 1;
+ }
+ }else{
+ CDBG("<DEBUG> : Still ref count pending count :%d",
+ my_obj->buf_status[frame->buf_idx].buf_refcnt);
+ CDBG("<DEBUG> : for buffer:%p:%d, ext_image_mode=%d",
+ my_obj, frame->buf_idx, my_obj->ext_image_mode);
+ }
+ }
+ pthread_mutex_unlock(&my_obj->buf_lock);
+ return rc;
+}
+
+int32_t mm_stream_reg_buf_cb(mm_stream_t *my_obj,
+ mm_stream_data_cb_t *val)
+{
+ int32_t rc = -1;
+ uint8_t i;
+
+ pthread_mutex_lock(&my_obj->cb_lock);
+ for (i=0 ;i < MM_CAMERA_STREAM_BUF_CB_MAX; i++) {
+ if(NULL == my_obj->buf_cb[i].cb) {
+ memcpy(&my_obj->buf_cb[i], val, sizeof(mm_stream_data_cb_t));
+ rc = 0;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&my_obj->cb_lock);
+
+ return rc;
+}
diff --git a/camera/QCamera/stack/mm-camera-interface/src/mm_camera_thread.c b/camera/QCamera/stack/mm-camera-interface/src/mm_camera_thread.c
new file mode 100755
index 0000000..7d45d4d
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-interface/src/mm_camera_thread.c
@@ -0,0 +1,361 @@
+/*
+Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <semaphore.h>
+
+#include "mm_camera_dbg.h"
+#include "mm_camera_interface.h"
+#include "mm_camera.h"
+
+typedef enum {
+ /* poll entries updated */
+ MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED,
+ /* exit */
+ MM_CAMERA_PIPE_CMD_EXIT,
+ /* max count */
+ MM_CAMERA_PIPE_CMD_MAX
+} mm_camera_pipe_cmd_type_t;
+
+typedef enum {
+ MM_CAMERA_POLL_TASK_STATE_STOPPED,
+ MM_CAMERA_POLL_TASK_STATE_POLL, /* polling pid in polling state. */
+ MM_CAMERA_POLL_TASK_STATE_MAX
+} mm_camera_poll_task_state_type_t;
+
+typedef struct {
+ uint8_t cmd;
+ mm_camera_event_t event;
+} mm_camera_sig_evt_t;
+
+static int32_t mm_camera_poll_sig(mm_camera_poll_thread_t *poll_cb,
+ uint32_t cmd)
+{
+ /* send through pipe */
+ /* get the mutex */
+ mm_camera_sig_evt_t cmd_evt;
+ int len;
+
+ CDBG("%s: E cmd = %d", __func__,cmd);
+ memset(&cmd_evt, 0, sizeof(cmd_evt));
+ cmd_evt.cmd = cmd;
+ pthread_mutex_lock(&poll_cb->mutex);
+ /* reset the statue to false */
+ poll_cb->status = FALSE;
+ /* send cmd to worker */
+
+ len = write(poll_cb->pfds[1], &cmd_evt, sizeof(cmd_evt));
+ if(len < 1) {
+ CDBG_ERROR("%s: len = %d, errno = %d", __func__, len, errno);
+ }
+ CDBG("%s: begin IN mutex write done, len = %d", __func__, len);
+ /* wait till worker task gives positive signal */
+ if (FALSE == poll_cb->status) {
+ CDBG("%s: wait", __func__);
+ pthread_cond_wait(&poll_cb->cond_v, &poll_cb->mutex);
+ }
+ /* done */
+ pthread_mutex_unlock(&poll_cb->mutex);
+ CDBG("%s: X", __func__);
+ return 0;
+}
+
+static void mm_camera_poll_sig_done(mm_camera_poll_thread_t *poll_cb)
+{
+ pthread_mutex_lock(&poll_cb->mutex);
+ poll_cb->status = TRUE;
+ pthread_cond_signal(&poll_cb->cond_v);
+ CDBG("%s: done, in mutex", __func__);
+ pthread_mutex_unlock(&poll_cb->mutex);
+}
+
+static void mm_camera_poll_set_state(mm_camera_poll_thread_t *poll_cb,
+ mm_camera_poll_task_state_type_t state)
+{
+ poll_cb->state = state;
+}
+
+static void mm_camera_poll_proc_pipe(mm_camera_poll_thread_t *poll_cb)
+{
+ ssize_t read_len;
+ int i;
+ mm_camera_sig_evt_t cmd_evt;
+ read_len = read(poll_cb->pfds[0], &cmd_evt, sizeof(cmd_evt));
+ CDBG("%s: read_fd = %d, read_len = %d, expect_len = %d cmd = %d",
+ __func__, poll_cb->pfds[0], (int)read_len, (int)sizeof(cmd_evt), cmd_evt.cmd);
+ switch (cmd_evt.cmd) {
+ case MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED:
+ /* we always have index 0 for pipe read */
+ poll_cb->num_fds = 0;
+ poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->pfds[0];
+ poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI;
+ poll_cb->num_fds++;
+
+ if (MM_CAMERA_POLL_TYPE_EVT == poll_cb->poll_type) {
+ if (poll_cb->poll_entries[0].fd > 0) {
+ /* fd is valid, we update poll_fds */
+ poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->poll_entries[0].fd;
+ poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI;
+ poll_cb->num_fds++;
+ }
+ } else if (MM_CAMERA_POLL_TYPE_CH == poll_cb->poll_type) {
+ for(i = 0; i < MM_CAMEAR_STRAEM_NUM_MAX; i++) {
+ if(poll_cb->poll_entries[i].fd > 0) {
+ /* fd is valid, we update poll_fds to this fd */
+ poll_cb->poll_fds[poll_cb->num_fds].fd = poll_cb->poll_entries[i].fd;
+ poll_cb->poll_fds[poll_cb->num_fds].events = POLLIN|POLLRDNORM|POLLPRI;
+ poll_cb->num_fds++;
+ } else {
+ /* fd is invalid, we set the entry to -1 to prevent polling.
+ * According to spec, polling will not poll on entry with fd=-1.
+ * If this is not the case, we need to skip these invalid fds
+ * when updating this array.
+ * We still keep fd=-1 in this array because this makes easier to
+ * map cb associated with this fd once incoming data avail by directly
+ * using the index-1(0 is reserved for pipe read, so need to reduce index by 1) */
+ poll_cb->poll_fds[poll_cb->num_fds].fd = -1;
+ poll_cb->poll_fds[poll_cb->num_fds].events = 0;
+ poll_cb->num_fds++;
+ }
+ }
+ }
+ mm_camera_poll_sig_done(poll_cb);
+ break;
+
+ case MM_CAMERA_PIPE_CMD_EXIT:
+ default:
+ mm_camera_poll_set_state(poll_cb, MM_CAMERA_POLL_TASK_STATE_STOPPED);
+ mm_camera_poll_sig_done(poll_cb);
+ break;
+ }
+}
+
+static void *mm_camera_poll_fn(mm_camera_poll_thread_t *poll_cb)
+{
+ int rc = 0, i;
+
+ CDBG("%s: poll type = %d, num_fd = %d poll_cb = %p\n",
+ __func__, poll_cb->poll_type, poll_cb->num_fds,poll_cb);
+ do {
+ for(i = 0; i < poll_cb->num_fds; i++) {
+ poll_cb->poll_fds[i].events = POLLIN|POLLRDNORM|POLLPRI;
+ }
+
+ rc = poll(poll_cb->poll_fds, poll_cb->num_fds, poll_cb->timeoutms);
+ if(rc > 0) {
+ if ((poll_cb->poll_fds[0].revents & POLLIN) &&
+ (poll_cb->poll_fds[0].revents & POLLRDNORM)) {
+ /* if we have data on pipe, we only process pipe in this iteration */
+ CDBG("%s: cmd received on pipe\n", __func__);
+ mm_camera_poll_proc_pipe(poll_cb);
+ } else {
+ for(i=1; i<poll_cb->num_fds; i++) {
+ /* Checking for ctrl events */
+ if ((poll_cb->poll_type == MM_CAMERA_POLL_TYPE_EVT) &&
+ (poll_cb->poll_fds[i].revents & POLLPRI)) {
+ CDBG("%s: mm_camera_evt_notify\n", __func__);
+ if (NULL != poll_cb->poll_entries[i-1].notify_cb) {
+ poll_cb->poll_entries[i-1].notify_cb(poll_cb->poll_entries[i-1].user_data);
+ }
+ }
+
+ if ((poll_cb->poll_type == MM_CAMERA_POLL_TYPE_CH) &&
+ (poll_cb->poll_fds[i].revents & POLLIN) &&
+ (poll_cb->poll_fds[i].revents & POLLRDNORM)) {
+ CDBG("%s: mm_stream_data_notify\n", __func__);
+ if (NULL != poll_cb->poll_entries[i-1].notify_cb) {
+ poll_cb->poll_entries[i-1].notify_cb(poll_cb->poll_entries[i-1].user_data);
+ }
+ }
+ }
+ }
+ } else {
+ /* in error case sleep 10 us and then continue. hard coded here */
+ usleep(10);
+ continue;
+ }
+ } while (poll_cb->state == MM_CAMERA_POLL_TASK_STATE_POLL);
+ return NULL;
+}
+
+static void *mm_camera_poll_thread(void *data)
+{
+ int rc = 0;
+ int i;
+ void *ret = NULL;
+ mm_camera_poll_thread_t *poll_cb = (mm_camera_poll_thread_t *)data;
+
+ /* add pipe read fd into poll first */
+ poll_cb->poll_fds[poll_cb->num_fds++].fd = poll_cb->pfds[0];
+
+ //poll_cb->poll_fds[poll_cb->num_fds++].fd = (((mm_camera_obj_t *)poll_cb->my_obj)->ctrl_fd);
+
+ mm_camera_poll_sig_done(poll_cb);
+ mm_camera_poll_set_state(poll_cb, MM_CAMERA_POLL_TASK_STATE_POLL);
+ ret = mm_camera_poll_fn(poll_cb);
+ return ret;
+}
+
+int32_t mm_camera_poll_thread_notify_entries_updated(mm_camera_poll_thread_t * poll_cb)
+{
+ /* send poll entries updated signal to poll thread */
+ return mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED);
+}
+
+int32_t mm_camera_poll_thread_add_poll_fd(mm_camera_poll_thread_t * poll_cb,
+ uint32_t handler,
+ int32_t fd,
+ mm_camera_poll_notify_t notify_cb,
+ void* userdata)
+{
+ int32_t rc = -1;
+ uint8_t idx = 0;
+
+ if (MM_CAMERA_POLL_TYPE_CH == poll_cb->poll_type) {
+ /* get stream idx from handler if CH type */
+ idx = mm_camera_util_get_index_by_handler(handler);
+ } else {
+ /* for EVT type, only idx=0 is valid */
+ idx = 0;
+ }
+
+ if (MM_CAMEAR_STRAEM_NUM_MAX > idx) {
+ poll_cb->poll_entries[idx].fd = fd;
+ poll_cb->poll_entries[idx].handler = handler;
+ poll_cb->poll_entries[idx].notify_cb = notify_cb;
+ poll_cb->poll_entries[idx].user_data = userdata;
+ /* send poll entries updated signal to poll thread */
+ rc = mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED);
+ } else {
+ CDBG_ERROR("%s: invalid handler %d (%d)",
+ __func__, handler, idx);
+ }
+ return rc;
+}
+
+int32_t mm_camera_poll_thread_del_poll_fd(mm_camera_poll_thread_t * poll_cb,
+ uint32_t handler)
+{
+ int32_t rc = -1;
+ uint8_t idx = 0;
+
+ if (MM_CAMERA_POLL_TYPE_CH == poll_cb->poll_type) {
+ /* get stream idx from handler if CH type */
+ idx = mm_camera_util_get_index_by_handler(handler);
+ } else {
+ /* for EVT type, only idx=0 is valid */
+ idx = 0;
+ }
+
+ if ((MM_CAMEAR_STRAEM_NUM_MAX > idx) &&
+ (handler == poll_cb->poll_entries[idx].handler)) {
+ /* reset poll entry */
+ poll_cb->poll_entries[idx].fd = -1; /* set fd to invalid */
+ poll_cb->poll_entries[idx].handler = 0;
+ poll_cb->poll_entries[idx].notify_cb = NULL;
+
+ /* send poll entries updated signal to poll thread */
+ rc = mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_POLL_ENTRIES_UPDATED);
+ } else {
+ CDBG_ERROR("%s: invalid handler %d (%d)",
+ __func__, handler, idx);
+ }
+
+ return rc;
+}
+
+int32_t mm_camera_poll_thread_launch(mm_camera_poll_thread_t * poll_cb,
+ mm_camera_poll_thread_type_t poll_type)
+{
+ int32_t rc = 0;
+ poll_cb->poll_type = poll_type;
+
+ poll_cb->pfds[0] = 0;
+ poll_cb->pfds[1] = 0;
+ rc = pipe(poll_cb->pfds);
+ if(rc < 0) {
+ CDBG_ERROR("%s: pipe open rc=%d\n", __func__, rc);
+ return -1;
+ }
+
+ poll_cb->timeoutms = -1; /* Infinite seconds */
+
+ CDBG("%s: poll_type = %d, read fd = %d, write fd = %d timeout = %d",
+ __func__, poll_cb->poll_type,
+ poll_cb->pfds[0], poll_cb->pfds[1],poll_cb->timeoutms);
+
+ pthread_mutex_init(&poll_cb->mutex, NULL);
+ pthread_cond_init(&poll_cb->cond_v, NULL);
+
+ /* launch the thread */
+ pthread_mutex_lock(&poll_cb->mutex);
+ poll_cb->status = 0;
+ pthread_create(&poll_cb->pid, NULL, mm_camera_poll_thread, (void *)poll_cb);
+ if(!poll_cb->status) {
+ pthread_cond_wait(&poll_cb->cond_v, &poll_cb->mutex);
+ }
+ pthread_mutex_unlock(&poll_cb->mutex);
+ CDBG("%s: End",__func__);
+ return rc;
+}
+
+int32_t mm_camera_poll_thread_release(mm_camera_poll_thread_t *poll_cb)
+{
+ int32_t rc = 0;
+ if(MM_CAMERA_POLL_TASK_STATE_STOPPED == poll_cb->state) {
+ CDBG_ERROR("%s: err, poll thread is not running.\n", __func__);
+ return rc;
+ }
+
+ /* send exit signal to poll thread */
+ mm_camera_poll_sig(poll_cb, MM_CAMERA_PIPE_CMD_EXIT);
+ /* wait until poll thread exits */
+ if (pthread_join(poll_cb->pid, NULL) != 0) {
+ CDBG_ERROR("%s: pthread dead already\n", __func__);
+ }
+
+ /* close pipe */
+ if(poll_cb->pfds[0]) {
+ close(poll_cb->pfds[0]);
+ }
+ if(poll_cb->pfds[1]) {
+ close(poll_cb->pfds[1]);
+ }
+
+ pthread_mutex_destroy(&poll_cb->mutex);
+ pthread_cond_destroy(&poll_cb->cond_v);
+ memset(poll_cb, 0, sizeof(mm_camera_poll_thread_t));
+ return rc;
+}
diff --git a/camera/QCamera/stack/mm-camera-test/Android.mk b/camera/QCamera/stack/mm-camera-test/Android.mk
new file mode 100755
index 0000000..1228680
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-test/Android.mk
@@ -0,0 +1,63 @@
+LOCAL_PATH:=$(call my-dir)
+USE_BIONIC_HEADER:=true
+include $(CLEAR_VARS)
+
+ifeq ($(call is-board-platform,msm8960),true)
+LOCAL_CFLAGS:= \
+ -DAMSS_VERSION=$(AMSS_VERSION) \
+ $(mmcamera_debug_defines) \
+ $(mmcamera_debug_cflags) \
+ $(USE_SERVER_TREE) \
+ -include camera_defs_i.h
+
+ifneq ($(strip $(USE_BIONIC_HEADER)),true)
+LOCAL_CFLAGS += -include $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include/linux/ion.h
+endif
+
+ifeq ($(strip $(TARGET_USES_ION)),true)
+LOCAL_CFLAGS += -DUSE_ION
+endif
+
+LOCAL_CFLAGS += -D_ANDROID_
+
+LOCAL_SRC_FILES:= \
+ src/mm_qcamera_main_menu.c \
+ src/mm_qcamera_display.c \
+ src/mm_qcamera_app.c \
+ src/mm_qcamera_snapshot.c \
+ src/mm_qcamera_video.c \
+ src/mm_qcamera_preview.c \
+ src/mm_qcamera_rdi.c \
+ src/mm_qcamera_unit_test.c \
+ src/mm_qcamera_dual_test.c
+
+LOCAL_C_INCLUDES:=$(LOCAL_PATH)/inc
+LOCAL_C_INCLUDES+= \
+ $(TARGET_OUT_INTERMEDIATES)/include/mm-camera-interface_badger \
+ $(TARGET_OUT_INTERMEDIATES)/include/mm-still/jpeg \
+ $(TARGET_OUT_INTERMEDIATES)/include/mm-camera \
+ $(LOCAL_PATH)/../mm-camera-interface/inc \
+ $(LOCAL_PATH)/../common \
+ $(LOCAL_PATH)/../../../ \
+
+ifneq ($(strip $(USE_BIONIC_HEADER)),true)
+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
+endif
+
+ifeq ($(call is-board-platform,msm8960),true)
+LOCAL_CFLAGS += -DCAMERA_ION_HEAP_ID=ION_CP_MM_HEAP_ID
+else
+LOCAL_CFLAGS += -DCAMERA_ION_HEAP_ID=ION_CAMERA_HEAP_ID
+endif
+
+LOCAL_SHARED_LIBRARIES:= \
+ libcutils libdl
+
+LOCAL_MODULE:= mm-qcamera-app-badger
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
+endif
diff --git a/camera/QCamera/stack/mm-camera-test/inc/mm_qcamera_app.h b/camera/QCamera/stack/mm-camera-test/inc/mm_qcamera_app.h
new file mode 100755
index 0000000..524a4b5
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-test/inc/mm_qcamera_app.h
@@ -0,0 +1,212 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 __MM_QCAMERA_APP_H__
+#define __MM_QCAMERA_APP_H__
+
+#define DISABLE_JPEG_ENCODING
+
+#include "camera.h"
+#include "mm_qcamera_main_menu.h"
+#include "mm_camera_interface.h"
+#ifndef DISABLE_JPEG_ENCODING
+#include "mm_omx_jpeg_encoder.h"
+#endif
+
+#define MM_APP_MAX_DUMP_FRAME_NUM 1000
+
+#define PREVIEW_BUF_NUM 7
+#define VIDEO_BUF_NUM 7
+
+typedef enum {
+ MM_CAMERA_OK,
+ MM_CAMERA_E_GENERAL,
+ MM_CAMERA_E_NO_MEMORY,
+ MM_CAMERA_E_NOT_SUPPORTED,
+ MM_CAMERA_E_INVALID_INPUT,
+ MM_CAMERA_E_INVALID_OPERATION, /* 5 */
+ MM_CAMERA_E_ENCODE,
+ MM_CAMERA_E_BUFFER_REG,
+ MM_CAMERA_E_PMEM_ALLOC,
+ MM_CAMERA_E_CAPTURE_FAILED,
+ MM_CAMERA_E_CAPTURE_TIMEOUT, /* 10 */
+}mm_camera_status_type_t;
+
+typedef struct {
+ int num;
+ uint32_t frame_len;
+ struct msm_frame frame[MM_CAMERA_MAX_NUM_FRAMES];
+
+ uint32_t fd[MM_CAMERA_MAX_NUM_FRAMES];
+ int main_ion_fd[MM_CAMERA_MAX_NUM_FRAMES];
+ struct ion_allocation_data alloc[MM_CAMERA_MAX_NUM_FRAMES];
+ struct ion_fd_data ion_info_fd[MM_CAMERA_MAX_NUM_FRAMES];
+ int reg[MM_CAMERA_MAX_NUM_FRAMES];
+} mm_camear_app_buf_t;
+
+typedef struct {
+ int id;
+ mm_camera_stream_config_t str_config;
+}mm_camear_stream_t;
+
+typedef enum{
+ CAMERA_STATE_OPEN,
+ CAMERA_STATE_PREVIEW,
+ CAMERA_STATE_RECORD,
+ CAMERA_STATE_SNAPSHOT,
+ CAMERA_STATE_RDI
+}camera_state;
+
+typedef enum{
+ CAMERA_MODE,
+ RECORDER_MODE,
+ ZSL_MODE,
+ RDI_MODE
+}camera_mode;
+
+typedef struct {
+ mm_camera_vtbl_t *cam;
+ mm_camear_mem_vtbl_t *mem_cam;
+ int8_t my_id;
+ //mm_camera_op_mode_type_t op_mode;
+ uint32_t ch_id;
+ cam_ctrl_dimension_t dim;
+ int open_flag;
+ int ionfd;
+ mm_camear_stream_t stream[8];
+ camera_mode cam_mode;
+ camera_state cam_state;
+ int fullSizeSnapshot;
+} mm_camera_app_obj_t;
+
+typedef struct {
+ void *ptr;
+ mm_camera_info_t *(*mm_camera_query) (uint8_t *num_cameras);
+ mm_camera_vtbl_t *(*mm_camera_open) (uint8_t camera_idx,
+ mm_camear_mem_vtbl_t *mem_vtbl);
+
+ /*uint8_t *(*mm_camera_do_mmap)(uint32_t size, int *pmemFd);
+ int (*mm_camera_do_munmap)(int pmem_fd, void *addr, size_t size);
+
+ uint8_t *(*mm_camera_do_mmap_ion)(int ion_fd, struct ion_allocation_data *alloc,
+ struct ion_fd_data *ion_info_fd, int *mapFd);
+ int (*mm_camera_do_munmap_ion) (int ion_fd, struct ion_fd_data *ion_info_fd,
+ void *addr, size_t size);*/
+#if 0
+ uint32_t (*mm_camera_get_msm_frame_len)(cam_format_t fmt_type,
+ camera_mode_t mode,
+ int width,
+ int height,
+ int image_type,
+ uint8_t *num_planes,
+ uint32_t planes[]);
+#ifndef DISABLE_JPEG_ENCODING
+ void (*set_callbacks)(jpegfragment_callback_t fragcallback,
+ jpeg_callback_t eventcallback, void* userdata, void* output_buffer,
+ int * outBufferSize);
+ int8_t (*omxJpegOpen)(void);
+ void (*omxJpegClose)(void);
+ int8_t (*omxJpegStart)(void);
+ int8_t (*omxJpegEncode)(omx_jpeg_encode_params *encode_params);
+ void (*omxJpegFinish)(void);
+ int8_t (*mm_jpeg_encoder_setMainImageQuality)(uint32_t quality);
+#endif
+#endif
+} hal_interface_lib_t;
+
+typedef struct {
+ //mm_camera_vtbl_t *cam;
+ uint8_t num_cameras;
+ mm_camera_app_obj_t *obj[2];
+ mm_camera_info_t *cam_info;
+ int use_overlay;
+ int use_user_ptr;
+ hal_interface_lib_t hal_lib;
+ int cam_open;
+ int run_sanity;
+} mm_camera_app_t;
+
+extern mm_camera_app_t my_cam_app;
+extern USER_INPUT_DISPLAY_T input_display;
+extern int mm_app_dl_render(int frame_fd, struct crop_info * cropinfo);
+extern mm_camera_app_obj_t *mm_app_get_cam_obj(int8_t cam_id);
+extern int mm_app_load_hal();
+extern int mm_app_init();
+extern void mm_app_user_ptr(int use_user_ptr);
+extern int mm_app_open_ch(int cam_id);
+extern void mm_app_close_ch(int cam_id, int ch_type);
+extern int mm_app_set_dim(int8_t cam_id, cam_ctrl_dimension_t *dim);
+extern int mm_app_run_unit_test();
+extern int mm_app_unit_test_entry(mm_camera_app_t *cam_app);
+extern int mm_app_unit_test();
+extern void mm_app_set_dim_def(cam_ctrl_dimension_t *dim);
+extern int mm_app_open(uint8_t camera_idx);
+extern int mm_app_close(int8_t cam_id);
+extern int startPreview(int cam_id);
+extern int mm_app_stop_preview(int cam_id);
+extern int mm_app_stop_video(int cam_id);
+extern int startRecording(int cam_id);
+extern int stopRecording(int cam_id);
+extern int mm_app_take_picture(int cam_id);
+extern int mm_app_take_raw_picture(int cam_id);
+extern int mm_app_get_dim(int8_t cam_id, cam_ctrl_dimension_t *dim);
+extern int mm_app_streamon_preview(int cam_id);
+extern int mm_app_set_snapshot_fmt(int cam_id,mm_camera_image_fmt_t *fmt);
+
+extern int mm_app_dual_test_entry(mm_camera_app_t *cam_app);
+extern int mm_app_dual_test();
+
+extern int mm_camera_app_wait();
+extern void mm_camera_app_done();
+
+extern int mm_stream_initbuf(uint32_t camera_handle,
+ uint32_t ch_id, uint32_t stream_id,
+ void *user_data,
+ mm_camera_frame_len_offset *frame_offset_info,
+ uint8_t num_bufs,
+ uint8_t *initial_reg_flag,
+ mm_camera_buf_def_t *bufs);
+
+extern int mm_stream_deinitbuf(uint32_t camera_handle,
+ uint32_t ch_id, uint32_t stream_id,
+ void *user_data, uint8_t num_bufs,
+ mm_camera_buf_def_t *bufs);
+
+extern void mm_app_preview_notify_cb(mm_camera_super_buf_t *bufs,
+ void *user_data);
+#endif /* __MM_QCAMERA_APP_H__ */
+
+
+
+
+
+
+
+
+
diff --git a/camera/QCamera/stack/mm-camera-test/inc/mm_qcamera_display_dimensions.h b/camera/QCamera/stack/mm-camera-test/inc/mm_qcamera_display_dimensions.h
new file mode 100755
index 0000000..231fecc
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-test/inc/mm_qcamera_display_dimensions.h
@@ -0,0 +1,43 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 __MM_QCAMERA_DISPLAY_DIMENSIONS__
+#define __MM_QCAMERA_DISPLAY_DIMENSIONS__
+
+#define PREVIEW_WIDTH 800
+#define PREVIEW_HEIGHT 480
+#define DISPLAY_WIDTH 800
+#define DISPLAY_HEIGHT 480
+#define THUMBNAIL_WIDTH 192
+#define THUMBNAIL_HEIGHT 144
+#define PICTURE_WIDTH 1280
+#define PICTURE_HEIGHT 960
+
+#endif /* __MM_QCAMERA_DISPLAY_DIMENSIONS__ */
diff --git a/camera/QCamera/stack/mm-camera-test/inc/mm_qcamera_main_menu.h b/camera/QCamera/stack/mm-camera-test/inc/mm_qcamera_main_menu.h
new file mode 100755
index 0000000..076b2f6
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-test/inc/mm_qcamera_main_menu.h
@@ -0,0 +1,465 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 __MM_QCAMERA_MAIN_MENU_H__
+#define __MM_QCAMERA_MAIN_MENU_H__
+
+#include "camera.h"
+#include "mm_camera_interface.h"
+
+
+#define VIDEO_BUFFER_SIZE (PREVIEW_WIDTH * PREVIEW_HEIGHT * 3/2)
+#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2)
+#define SNAPSHOT_BUFFER_SIZE (PICTURE_WIDTH * PICTURE_HEIGHT * 3/2)
+
+/*===========================================================================
+ * Macro
+ *===========================================================================*/
+#define PREVIEW_FRAMES_NUM 4
+#define VIDEO_FRAMES_NUM 4
+#define THUMBNAIL_FRAMES_NUM 1
+#define SNAPSHOT_FRAMES_NUM 1
+#define MAX_NUM_FORMAT 32
+
+typedef enum
+{
+ STOP_CAMERA = 1,
+ PREVIEW_VIDEO_RESOLUTION = 2,
+ TAKE_YUV_SNAPSHOT = 3,
+ TAKE_RAW_SNAPSHOT = 4,
+ TAKE_ZSL_SNAPSHOT = 5,
+ //TAKE_LIVE_SNAPSHOT = 17,
+ START_RECORDING = 6,
+ START_RDI = 7,
+ STOP_RDI = 8,
+ SWITCH_CAMERA = 9,
+ //STOP_RECORDING = 7,
+ //SET_WHITE_BALANCE = 3,
+ //SET_EXP_METERING = 4,
+ //GET_CTRL_VALUE = 5,
+ //TOGGLE_AFR = 6,
+ //SET_ISO = 7,
+ //BRIGHTNESS_GOTO_SUBMENU = 8,
+ //CONTRAST_GOTO_SUBMENU = 9,
+ //EV_GOTO_SUBMENU = 10,
+ //SATURATION_GOTO_SUBMENU = 11,
+ //SET_ZOOM = 12,
+ //SET_SHARPNESS = 13,
+} Camera_main_menu_t;
+
+typedef enum
+{
+ ACTION_NO_ACTION,
+ ACTION_STOP_CAMERA,
+ ACTION_PREVIEW_VIDEO_RESOLUTION,
+ ACTION_TAKE_YUV_SNAPSHOT,
+ ACTION_TAKE_RAW_SNAPSHOT,
+ ACTION_TAKE_ZSL_SNAPSHOT,
+ ACTION_TAKE_LIVE_SNAPSHOT,
+ ACTION_START_RECORDING,
+ ACTION_STOP_RECORDING,
+ ACTION_START_RDI,
+ ACTION_STOP_RDI,
+ ACTION_SWITCH_CAMERA,
+ ACTION_SET_WHITE_BALANCE,
+ ACTION_SET_EXP_METERING,
+ ACTION_GET_CTRL_VALUE,
+ ACTION_TOGGLE_AFR,
+ ACTION_SET_ISO,
+ ACTION_BRIGHTNESS_INCREASE,
+ ACTION_BRIGHTNESS_DECREASE,
+ ACTION_CONTRAST_INCREASE,
+ ACTION_CONTRAST_DECREASE,
+ ACTION_EV_INCREASE,
+ ACTION_EV_DECREASE,
+ ACTION_SATURATION_INCREASE,
+ ACTION_SATURATION_DECREASE,
+ ACTION_SET_ZOOM,
+ ACTION_SHARPNESS_INCREASE,
+ ACTION_SHARPNESS_DECREASE,
+} camera_action_t;
+
+#define INVALID_KEY_PRESS 0
+#define BASE_OFFSET ('Z' - 'A' + 1)
+#define BASE_OFFSET_NUM ('Z' - 'A' + 2)
+#define PAD_TO_WORD(a) (((a)+3)&~3)
+
+
+#define SQCIF_WIDTH 128
+#define SQCIF_HEIGHT 96
+#define QCIF_WIDTH 176
+#define QCIF_HEIGHT 144
+#define QVGA_WIDTH 320
+#define QVGA_HEIGHT 240
+#define HD_THUMBNAIL_WIDTH 256
+#define HD_THUMBNAIL_HEIGHT 144
+#define CIF_WIDTH 352
+#define CIF_HEIGHT 288
+#define VGA_WIDTH 640
+#define VGA_HEIGHT 480
+#define WVGA_WIDTH 800
+#define WVGA_HEIGHT 480
+
+#define MP1_WIDTH 1280
+#define MP1_HEIGHT 960
+#define MP2_WIDTH 1600
+#define MP2_HEIGHT 1200
+#define MP3_WIDTH 2048
+#define MP3_HEIGHT 1536
+#define MP5_WIDTH 2592
+#define MP5_HEIGHT 1944
+
+#define SVGA_WIDTH 800
+#define SVGA_HEIGHT 600
+#define XGA_WIDTH 1024
+#define XGA_HEIGHT 768
+#define HD720_WIDTH 1280
+#define HD720_HEIGHT 720
+#define WXGA_WIDTH 1280
+#define WXGA_HEIGHT 768
+#define HD1080_WIDTH 1920
+#define HD1080_HEIGHT 1080
+
+typedef enum
+{
+ RESOLUTION_MIN = 1,
+ SQCIF = RESOLUTION_MIN,
+ QCIF = 2,
+ QVGA = 3,
+ CIF = 4,
+ VGA = 5,
+ WVGA = 6,
+ SVGA = 7,
+ XGA = 8,
+ HD720 = 9,
+ RESOLUTION_PREVIEW_VIDEO_MAX = HD720,
+ WXGA = 10,
+ MP1 = 11,
+ MP2 = 12,
+ HD1080 = 13,
+ MP3 = 14,
+ MP5 = 15,
+ RESOLUTION_MAX = MP5,
+} Camera_Resolution;
+
+
+typedef enum {
+ WHITE_BALANCE_STATE = 1,
+ WHITE_BALANCE_TEMPERATURE = 2,
+ BRIGHTNESS_CTRL = 3,
+ EV = 4,
+ CONTRAST_CTRL = 5,
+ SATURATION_CTRL = 6,
+ SHARPNESS_CTRL = 7,
+} Get_Ctrl_modes;
+
+typedef enum {
+ WHITE_BALANCE_AUTO = 1,
+ WHITE_BALANCE_OFF = 2,
+ WHITE_BALANCE_DAYLIGHT = 3,
+ WHITE_BALANCE_INCANDESCENT = 4,
+ WHITE_BALANCE_FLUORESCENT = 5,
+} White_Balance_modes;
+
+typedef enum {
+ EXP_METERING_FRAME_AVERAGE = 1,
+ EXP_METERING_CENTER_WEIGHTED = 2,
+ EXP_METERING_SPOT_METERING = 3,
+} Exp_Metering_modes;
+
+typedef enum {
+ ISO_AUTO = 1,
+ ISO_DEBLUR = 2,
+ ISO_100 = 3,
+ ISO_200 = 4,
+ ISO_400 = 5,
+ ISO_800 = 6,
+ ISO_1600 = 7,
+} ISO_modes;
+
+typedef enum
+{
+ MENU_ID_MAIN,
+ MENU_ID_PREVIEWVIDEORESOLUTIONCHANGE,
+ MENU_ID_WHITEBALANCECHANGE,
+ MENU_ID_EXPMETERINGCHANGE,
+ MENU_ID_GET_CTRL_VALUE,
+ MENU_ID_TOGGLEAFR,
+ MENU_ID_ISOCHANGE,
+ MENU_ID_BRIGHTNESSCHANGE,
+ MENU_ID_CONTRASTCHANGE,
+ MENU_ID_EVCHANGE,
+ MENU_ID_SATURATIONCHANGE,
+ MENU_ID_ZOOMCHANGE,
+ MENU_ID_SHARPNESSCHANGE,
+ MENU_ID_SWITCHCAMERA,
+ MENU_ID_RECORD,
+ MENU_ID_INVALID,
+} menu_id_change_t;
+
+typedef enum
+{
+ INCREASE_ZOOM = 1,
+ DECREASE_ZOOM = 2,
+ INCREASE_STEP_ZOOM = 3,
+ DECREASE_STEP_ZOOM = 4,
+} Camera_Zoom;
+
+typedef enum
+{
+ INC_CONTRAST = 1,
+ DEC_CONTRAST = 2,
+} Camera_Contrast_changes;
+
+typedef enum
+{
+ INC_BRIGHTNESS = 1,
+ DEC_BRIGHTNESS = 2,
+} Camera_Brightness_changes;
+
+typedef enum
+{
+ INCREASE_EV = 1,
+ DECREASE_EV = 2,
+} Camera_EV_changes;
+
+typedef enum {
+ INC_SATURATION = 1,
+ DEC_SATURATION = 2,
+} Camera_Saturation_changes;
+
+typedef enum
+{
+ INC_ISO = 1,
+ DEC_ISO = 2,
+} Camera_ISO_changes;
+
+typedef enum
+{
+ INC_SHARPNESS = 1,
+ DEC_SHARPNESS = 2,
+} Camera_Sharpness_changes;
+
+typedef enum {
+ ZOOM_IN = 1,
+ ZOOM_OUT = 2,
+} Zoom_direction;
+
+typedef enum
+{
+ LIVE_SNAPSHOT_MENU = 1,
+ STOP_RECORDING_MENU = 2,
+} Record_changes;
+
+typedef struct{
+ Camera_main_menu_t main_menu;
+ char * menu_name;
+} CAMERA_MAIN_MENU_TBL_T;
+
+typedef struct{
+ Camera_Resolution cs_id;
+ uint16_t width;
+ uint16_t height;
+ char * name;
+ char * str_name;
+} PREVIEW_DIMENSION_TBL_T;
+
+typedef struct {
+ White_Balance_modes wb_id;
+ char * wb_name;
+} WHITE_BALANCE_TBL_T;
+
+typedef struct {
+ int cam_id;
+ char * cam_name;
+} CAMERA_TBL_T;
+
+typedef struct {
+ int act_id;
+ char * act_name;
+} RECORD_TBL_T;
+
+typedef struct {
+ Get_Ctrl_modes get_ctrl_id;
+ char * get_ctrl_name;
+} GET_CTRL_TBL_T;
+
+typedef struct{
+ Exp_Metering_modes exp_metering_id;
+ char * exp_metering_name;
+} EXP_METERING_TBL_T;
+
+typedef struct {
+ ISO_modes iso_modes;
+ char *iso_modes_name;
+} ISO_TBL_T;
+
+typedef struct {
+ Zoom_direction zoom_direction;
+ char * zoom_direction_name;
+} ZOOM_TBL_T;
+
+typedef struct {
+ Camera_Sharpness_changes sharpness_change;
+ char *sharpness_change_name;
+} SHARPNESS_TBL_T;
+
+typedef struct {
+ Camera_Brightness_changes bc_id;
+ char * brightness_name;
+} CAMERA_BRIGHTNESS_TBL_T;
+
+typedef struct {
+ Camera_Contrast_changes cc_id;
+ char * contrast_name;
+} CAMERA_CONTRST_TBL_T;
+
+typedef struct {
+ Camera_EV_changes ec_id;
+ char * EV_name;
+} CAMERA_EV_TBL_T;
+
+typedef struct {
+ Camera_Saturation_changes sc_id;
+ char * saturation_name;
+} CAMERA_SATURATION_TBL_T;
+
+typedef struct {
+ Camera_Sharpness_changes bc_id;
+ char * sharpness_name;
+} CAMERA_SHARPNESS_TBL_T;
+
+
+typedef struct {
+ void *frameThread;
+ int8_t (*setDimension)(int , void *);
+ int8_t (*setDefaultParams)(int );
+ int8_t (*registerPreviewBuf)(int , void *, uint32_t, struct msm_frame *, int8_t );
+ int8_t (*unregisterPreviewBuf)(int , void *, uint32_t, int , unsigned char *);
+ int8_t (*registerVideoBuf)(int , void *, uint32_t, struct msm_frame *, int8_t );
+ int8_t (*unregisterVideoBuf)(int , void *, uint32_t, int , unsigned char *);
+ int8_t (*startPreview)(int );
+ int8_t (*stopPreview)(int );
+ int8_t (*startVideo)(int );
+ int8_t (*stopVideo)(int );
+ int8_t (*startRecording)(int );
+ int8_t (*stopRecording)(int );
+ int8_t (*startSnapshot)(int );
+ int8_t (*startRawSnapshot)(int );
+
+ int8_t (*registerSnapshotBuf)(int , void *, int , int ,
+ unsigned char *, unsigned char *);
+
+ int8_t (*registerRawSnapshotBuf)(int , void *, int , unsigned char *);
+
+ int8_t (*unregisterSnapshotBuf)(int , void *, int , int ,
+ unsigned char *, unsigned char *);
+
+ int8_t (*unregisterRawSnapshotBuf)(int , void *, int , unsigned char *);
+ int8_t (*getPicture)(int fd, struct crop_info *cropInfo );
+ int8_t (*stopSnapshot)(int );
+ int8_t (*jpegEncode)(const char *path, void *, int, int , unsigned char *,
+ unsigned char *, void *, camera_encoding_rotate_t rotate);
+ int8_t (*setZoom)(int , void *);
+ int8_t (*getMaxZoom)(int fd, void *pZm);
+ int8_t (*setSpecialEffect)(int, int effect);
+ int8_t (*setBrightness)(int, int);
+ int8_t (*setContrast)(int, int);
+ int8_t (*setSaturation)(int, int);
+ int8_t (*setEV)(int , int );
+ int8_t (*setAntiBanding)(int , int32_t antibanding);
+ int8_t (*setWhiteBalance)(int , int32_t );
+ int8_t (*setAecMode)(int , camera_auto_exposure_mode_type );
+ int8_t (*setIso)(int , camera_iso_mode_type );
+ int8_t (*setSharpness)(int , int );
+ int8_t (*setAutoFocus)(int , isp3a_af_mode_t, cam_af_ctrl_t *);
+ int8_t (*sethjr) (int fd, int8_t hjr_status);
+ int8_t (*setLensShading) (int fd, int8_t rolloff_status);
+ int8_t (*setLedMode) (int fd, led_mode_t led_mode);
+ int8_t (*getSharpness_AF) (int fd, int32_t *sharpness);
+ int8_t (*setMotionIso) (int fd, motion_iso_t motion_iso);
+ int8_t (*setHue) (int fd, int32_t hue);
+ int8_t (*cancelAF) (int fd);
+ int8_t (*getAfStep) (int fd, int32_t *afStep);
+ int8_t (*setAfStep) (int fd, int32_t afStep);
+ int8_t (*enableAFD) (int fd);
+ int8_t (*prepareSnapshot) (int fd);
+ int8_t (*setFpsMode) (int fd, fps_mode_t fps_mode);
+ int8_t (*setFps) (int fd, uint16_t fps);
+ int8_t (*setAFFocusRect) (int fd, cam_af_focusrect_t af_focus_rect);
+} interface_ctrl_t;
+
+int8_t native_interface_init(interface_ctrl_t *intrfcCtrl, int *camfd);
+int8_t v4l2_interface_init(interface_ctrl_t *intrfcCtrl, int *videofd);
+
+int set_zoom (int zoom_action_param);
+int set_hjr (void);
+int LensShading (void);
+int decrease_contrast (void);
+int increase_contrast (void);
+int decrease_saturation (void);
+int increase_saturation (void);
+int decrease_brightness (void);
+int increase_brightness (void);
+int decrease_EV (void);
+int increase_EV (void);
+int set_iso (int iso_action_param);
+int decrease_sharpness (void);
+int increase_sharpness (void);
+int SpecialEffect (void);
+int set_exp_metering (int exp_metering_action_param);
+int LED_mode_change (void);
+int set_sharpness_AF (void);
+int set_auto_focus (void);
+int set_antibanding (void);
+int set_whitebalance (int wb_action_param);
+int print_current_menu ();
+int set_MotionIso (void);
+int start_preview (void);
+int stop_preview (void);
+static int start_video (void);
+static int stop_video (void);
+int start_recording (void);
+int stop_recording (void);
+int snapshot_resolution (int);
+int preview_video_resolution (int);
+int system_init(void);
+int system_destroy(void);
+int toggle_hue(void);
+int cancel_af(void);
+int get_af_step();
+int set_af_step();
+int enable_afd();
+int prepare_snapshot();
+int set_fps_mode(void);
+int get_ctrl_value (int ctrl_value_mode_param);
+int toggle_afr ();
+int take_yuv_snapshot(int cam_id);
+int take_raw_snapshot();
+#endif /* __MM_QCAMERA_MAIN_MENU_H__ */
diff --git a/camera/QCamera/stack/mm-camera-test/inc/mm_qcamera_unit_test.h b/camera/QCamera/stack/mm-camera-test/inc/mm_qcamera_unit_test.h
new file mode 100755
index 0000000..2a95120
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-test/inc/mm_qcamera_unit_test.h
@@ -0,0 +1,46 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 __MM_QCAMERA_APP_UNIT_TEST_H__
+#define __MM_QCAMERA_APP_UNIT_TEST_H__
+
+#include "camera.h"
+#include "mm_qcamera_main_menu.h"
+#include "mm_camera_interface.h"
+#include "mm_qcamera_app.h"
+
+typedef int (*mm_app_test_t) (mm_camera_app_t *cam_apps);
+typedef struct {
+ mm_app_test_t f;
+ int r;
+} mm_app_tc_t;
+
+#endif
+
+/* __MM_QCAMERA_APP_UNIT_TEST_H__ */
diff --git a/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_app.c b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_app.c
new file mode 100755
index 0000000..6f89fcc
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_app.c
@@ -0,0 +1,405 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include "mm_camera_dbg.h"
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <dlfcn.h>
+#include "mm_qcamera_main_menu.h"
+#include "mm_qcamera_app.h"
+
+
+mm_camera_app_t my_cam_app;
+
+static pthread_mutex_t app_mutex;
+static int thread_status = 0;
+static pthread_cond_t app_cond_v;
+
+#define MM_QCAMERA_APP_WAIT_TIME 1000000000
+
+int mm_camera_app_timedwait()
+{
+ int rc = 0;
+ pthread_mutex_lock(&app_mutex);
+ if(FALSE == thread_status) {
+ struct timespec tw;
+ memset(&tw, 0, sizeof tw);
+ tw.tv_sec = 0;
+ tw.tv_nsec = time(0) + MM_QCAMERA_APP_WAIT_TIME;
+
+ //pthread_cond_wait(&app_cond_v, &app_mutex);
+ rc = pthread_cond_timedwait(&app_cond_v, &app_mutex,&tw);
+ thread_status = FALSE;
+ }
+ pthread_mutex_unlock(&app_mutex);
+ return rc;
+}
+
+int mm_camera_app_wait()
+{
+ int rc = 0;
+ pthread_mutex_lock(&app_mutex);
+ if(FALSE == thread_status){
+ pthread_cond_wait(&app_cond_v, &app_mutex);
+ thread_status = FALSE;
+ }
+ pthread_mutex_unlock(&app_mutex);
+ return rc;
+}
+
+void mm_camera_app_done()
+{
+ pthread_mutex_lock(&app_mutex);
+ thread_status = TRUE;
+ pthread_cond_signal(&app_cond_v);
+ pthread_mutex_unlock(&app_mutex);
+}
+
+
+mm_camera_app_obj_t *mm_app_get_cam_obj(int8_t cam_id)
+{
+ mm_camera_app_obj_t *temp = my_cam_app.obj[cam_id];
+ return temp;
+}
+
+void mm_app_user_ptr(int use_user_ptr)
+{
+ my_cam_app.use_user_ptr = use_user_ptr;
+}
+
+void mm_app_set_dim_def(cam_ctrl_dimension_t *dim)
+{
+ dim->display_width = WVGA_WIDTH;
+ dim->display_height = WVGA_HEIGHT;
+ input_display.user_input_display_width = dim->display_width;
+ input_display.user_input_display_height = dim->display_height;
+ dim->video_width = WVGA_WIDTH;
+ dim->video_width = CEILING32(dim->video_width);
+ dim->video_height = WVGA_HEIGHT;
+ dim->orig_video_width = dim->video_width;
+ dim->orig_video_height = dim->video_height;
+ dim->picture_width = MP1_WIDTH;
+ dim->picture_height = MP1_HEIGHT;
+ dim->orig_picture_dx = dim->picture_width;
+ dim->orig_picture_dy = dim->picture_height;
+ dim->ui_thumbnail_height = QVGA_HEIGHT;
+ dim->ui_thumbnail_width = QVGA_WIDTH;
+ dim->thumbnail_height = dim->ui_thumbnail_height;
+ dim->thumbnail_width = dim->ui_thumbnail_width;
+ dim->orig_picture_width = dim->picture_width;
+ dim->orig_picture_height = dim->picture_height;
+ dim->orig_thumb_width = dim->thumbnail_width;
+ dim->orig_thumb_height = dim->thumbnail_height;
+ dim->raw_picture_height = MP1_HEIGHT;
+ dim->raw_picture_width = MP1_WIDTH;
+ dim->hjr_xtra_buff_for_bayer_filtering;
+ dim->prev_format = CAMERA_YUV_420_NV21;
+ dim->enc_format = CAMERA_YUV_420_NV12;
+ dim->thumb_format = CAMERA_YUV_420_NV21;
+ dim->main_img_format = CAMERA_YUV_420_NV21;
+ dim->prev_padding_format = CAMERA_PAD_TO_4K;
+ dim->display_luma_width = dim->display_width;
+ dim->display_luma_height = dim->display_height;
+ dim->display_chroma_width = dim->display_width;
+ dim->display_chroma_height = dim->display_height;
+ dim->video_luma_width = dim->orig_video_width;
+ dim->video_luma_height = dim->orig_video_height;
+ dim->video_chroma_width = dim->orig_video_width;
+ dim->video_chroma_height = dim->orig_video_height;
+ dim->thumbnail_luma_width = dim->thumbnail_width;
+ dim->thumbnail_luma_height = dim->thumbnail_height;
+ dim->thumbnail_chroma_width = dim->thumbnail_width;
+ dim->thumbnail_chroma_height = dim->thumbnail_height;
+ dim->main_img_luma_width = dim->picture_width;
+ dim->main_img_luma_height = dim->picture_height;
+ dim->main_img_chroma_width = dim->picture_width;
+ dim->main_img_chroma_height = dim->picture_height;
+}
+
+int mm_app_load_hal()
+{
+ memset(&my_cam_app, 0, sizeof(my_cam_app));
+ memset(&my_cam_app.hal_lib, 0, sizeof(hal_interface_lib_t));
+#if defined(_MSM7630_)
+ my_cam_app.hal_lib.ptr = dlopen("/usr/lib/hw/camera.msm7630.so", RTLD_LAZY);
+#elif defined(_MSM7627A_)
+ my_cam_app.hal_lib.ptr = dlopen("/usr/lib/hw/camera.msm7627A.so", RTLD_LAZY);
+#else
+ //my_cam_app.hal_lib.ptr = dlopen("hw/camera.msm8960.so", RTLD_NOW);
+ my_cam_app.hal_lib.ptr = dlopen("libmmcamera_interface_badger.so", RTLD_NOW);
+#endif
+ if (!my_cam_app.hal_lib.ptr) {
+ CDBG_ERROR("%s Error opening HAL library %s\n", __func__, dlerror());
+ return -1;
+ }
+ *(void **)&(my_cam_app.hal_lib.mm_camera_query) =
+ dlsym(my_cam_app.hal_lib.ptr,
+ "camera_query");
+ *(void **)&(my_cam_app.hal_lib.mm_camera_open) =
+ dlsym(my_cam_app.hal_lib.ptr,
+ "camera_open");
+ return 0;
+}
+
+int mm_app_init()
+{
+ int rc = MM_CAMERA_OK;
+ CDBG("%s:BEGIN\n", __func__);
+ my_cam_app.cam_info = (mm_camera_info_t *)my_cam_app.hal_lib.mm_camera_query(&my_cam_app.num_cameras);
+ if(my_cam_app.cam_info == NULL) {
+ CDBG_ERROR("%s: Failed to query camera\n", __func__);
+ rc = -1;
+ }
+ CDBG("%s:END, num_cameras = %d\n", __func__, my_cam_app.num_cameras);
+ return rc;
+}
+
+static void notify_evt_cb(uint32_t camera_handle,
+ mm_camera_event_t *evt,void *user_data)
+{
+ CDBG("%s:E evt = %d",__func__,evt->event_type);
+
+ switch(evt->event_type)
+ {
+ case MM_CAMERA_EVT_TYPE_CH:
+ break;
+ case MM_CAMERA_EVT_TYPE_CTRL:
+ break;
+ case MM_CAMERA_EVT_TYPE_STATS:
+ break;
+ case MM_CAMERA_EVT_TYPE_INFO:
+ break;
+ default:
+ break;
+ }
+ CDBG("%s:X",__func__);
+}
+
+int mm_app_open(uint8_t cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = NULL;
+ int i;
+ mm_camera_event_type_t evt;
+
+ pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("%s:BEGIN\n", __func__);
+ if(pme != NULL) {
+ CDBG("%s:cam already open.nop\n",__func__);
+ goto end;
+ }
+ my_cam_app.cam_open = cam_id;
+ my_cam_app.obj[cam_id] = (mm_camera_app_obj_t *)malloc(sizeof(mm_camera_app_obj_t));
+ pme = my_cam_app.obj[cam_id];
+
+ pme->mem_cam = (mm_camear_mem_vtbl_t *)malloc(sizeof(mm_camear_mem_vtbl_t));
+ memset(pme->mem_cam,0,sizeof(mm_camear_mem_vtbl_t));
+ pme->mem_cam->user_data = pme;
+
+ pme->cam = my_cam_app.hal_lib.mm_camera_open(cam_id,pme->mem_cam);
+ if(pme->cam == NULL) {
+ CDBG("%s:dev open error=%d\n", __func__, rc);
+ memset(pme,0, sizeof(pme));
+ return -1;
+ }
+ CDBG("Open Camera id = %d handle = %d",cam_id,pme->cam->camera_handle);
+
+ pme->ch_id = cam_id;
+ pme->open_flag = TRUE;
+ mm_app_set_dim_def(&pme->dim);
+
+ for (i = 0; i < MM_CAMERA_EVT_TYPE_MAX; i++) {
+ evt = (mm_camera_event_type_t) i;
+ pme->cam->ops->register_event_notify(pme->cam->camera_handle,notify_evt_cb,pme,evt);
+ }
+ pme->cam_state = CAMERA_STATE_OPEN;
+ pme->cam_mode = CAMERA_MODE;
+ pme->fullSizeSnapshot = 0;
+
+ pme->ch_id = pme->cam->ops->ch_acquire(pme->cam->camera_handle);
+ CDBG("Channel Acquired Successfully %d",pme->ch_id);
+end:
+ CDBG("%s:END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_close(int8_t cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("%s:BEGIN\n", __func__);
+ if(!pme->cam) {
+ CDBG("%s:cam already closed. nop\n",__func__);
+ goto end;
+ }
+
+ pme->cam->ops->ch_release(pme->cam->camera_handle,pme->ch_id);
+ pme->cam->ops->camera_close(pme->cam->camera_handle);
+ pme->open_flag = FALSE;
+ pme->cam = NULL;
+ pme->my_id = 0;
+ free(pme->mem_cam);
+ pme->mem_cam = NULL;
+ memset(&pme->dim, 0, sizeof(pme->dim));
+ memset(&pme->dim, 0, sizeof(pme->dim));
+
+ free(pme);
+ pme = NULL;
+ my_cam_app.obj[cam_id] = NULL;
+
+end:
+ CDBG("%s:END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+void switchRes(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+ switch(pme->cam_state) {
+ case CAMERA_STATE_RECORD:
+ if(MM_CAMERA_OK != stopRecording(cam_id)){
+ CDBG_ERROR("%s:Cannot stop video err=%d\n", __func__, rc);
+ return -1;
+ }
+ case CAMERA_STATE_PREVIEW:
+ if(MM_CAMERA_OK != mm_app_stop_preview(cam_id)){
+ CDBG_ERROR("%s: Cannot switch to camera mode=%d\n", __func__);
+ return -1;
+ }
+ break;
+ case CAMERA_STATE_SNAPSHOT:
+ default:
+ break;
+ }
+}
+void switchCamera(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ if(my_cam_app.cam_open == cam_id){
+ return;
+ }
+
+ switch(pme->cam_state) {
+ case CAMERA_STATE_RECORD:
+ if(MM_CAMERA_OK != stopRecording(cam_id)){
+ CDBG_ERROR("%s:Cannot stop video err=%d\n", __func__, rc);
+ return -1;
+ }
+ case CAMERA_STATE_PREVIEW:
+ if(MM_CAMERA_OK != mm_app_stop_preview(cam_id)){
+ CDBG_ERROR("%s: Cannot switch to camera mode=%d\n", __func__);
+ return -1;
+ }
+ break;
+ case CAMERA_STATE_SNAPSHOT:
+ default:
+ break;
+ }
+
+ mm_app_close(my_cam_app.cam_open);
+ mm_app_open(cam_id);
+}
+
+int mm_app_set_dim(int8_t cam_id, cam_ctrl_dimension_t *dim)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("%s:BEGIN\n", __func__);
+
+ memcpy(&pme->dim, dim, sizeof(cam_ctrl_dimension_t));
+ if(MM_CAMERA_OK != (rc = pme->cam->ops->set_parm(
+ pme->cam->camera_handle,MM_CAMERA_PARM_DIMENSION, &pme->dim)))
+ {
+ CDBG_ERROR("%s: set dimension err=%d\n", __func__, rc);
+ }
+ CDBG("%s:END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_get_dim(int8_t cam_id, cam_ctrl_dimension_t *dim)
+{
+ int rc = MM_CAMERA_OK;
+#if 0
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+ CDBG("%s:BEGIN\n", __func__);
+ if(pme->open_flag != TRUE) {
+ CDBG("%s: dev not open yet\n", __func__);
+ rc = -MM_CAMERA_E_INVALID_OPERATION;
+ goto end;
+ }
+ /* now we only use the upper portion. TBD: needs to be fixed later */
+ //memcpy(&pme->dim, dim, sizeof(cam_ctrl_dimension_t));
+ if(MM_CAMERA_OK != (rc = pme->cam->cfg->get_parm(pme->cam,
+ MM_CAMERA_PARM_DIMENSION, &pme->dim))) {
+ CDBG("%s: set dimension err=%d\n", __func__, rc);
+ }
+ CDBG("%s: raw_w=%d,raw_h=%d\n",
+ __func__, pme->dim.orig_picture_width, pme->dim.orig_picture_height);
+ if(dim)
+ memcpy(dim, &pme->dim, sizeof(cam_ctrl_dimension_t));
+
+end:
+ CDBG("%s:END, rc=%d\n", __func__, rc);
+#endif
+ return rc;
+}
+
+void mm_app_close_ch(int cam_id, int ch_type)
+{
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ pme->cam->ops->ch_release(pme->cam->camera_handle,pme->ch_id);
+ CDBG("%s:END,cam_id = %d, ch = %d\n", __func__, cam_id, ch_type);
+
+}
+
+int mm_app_unit_test()
+{
+ my_cam_app.run_sanity = 1;
+ mm_app_unit_test_entry(&my_cam_app);
+ return 0;
+}
+
+int mm_app_dual_test()
+{
+ my_cam_app.run_sanity = 1;
+ mm_app_dual_test_entry(&my_cam_app);
+ return 0;
+}
diff --git a/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_display.c b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_display.c
new file mode 100755
index 0000000..da3399d
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_display.c
@@ -0,0 +1,572 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <sys/ioctl.h>
+struct file;
+struct inode;
+#include <linux/android_pmem.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <string.h>
+
+#include <inttypes.h>
+#include <linux/msm_mdp.h>
+#include <linux/fb.h>
+#include "camera.h"
+#include "mm_camera_dbg.h"
+
+#ifdef DRAW_RECTANGLES
+extern roi_info_t camframe_roi;
+
+#undef CAM_FRM_DRAW_RECT
+#define CAM_FRM_DRAW_RECT
+#endif
+
+#ifdef CAM_FRM_DRAW_FD_RECT
+#undef CAM_FRM_DRAW_RECT
+#define CAM_FRM_DRAW_RECT
+#endif
+
+struct fb_var_screeninfo vinfo;
+struct fb_fix_screeninfo finfo;
+int fb_fd = 0;
+union {
+ char dummy[sizeof(struct mdp_blit_req_list) +
+ sizeof(struct mdp_blit_req) * 1];
+ struct mdp_blit_req_list list;
+} yuv;
+
+static pthread_t cam_frame_fb_thread_id;
+static int camframe_fb_exit;
+
+static int is_camframe_fb_thread_ready;
+USER_INPUT_DISPLAY_T input_display;
+
+unsigned use_overlay = 0;
+struct msmfb_overlay_data ov_front, ov_back, *ovp_front, *ovp_back;
+struct mdp_overlay overlay, *overlayp;
+int vid_buf_front_id, vid_buf_back_id;
+static unsigned char please_initialize = 1;
+int num_of_ready_frames = 0;
+
+static pthread_cond_t sub_thread_ready_cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t sub_thread_ready_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t camframe_fb_cond = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t camframe_fb_mutex = PTHREAD_MUTEX_INITIALIZER;
+static void notify_camframe_fb_thread();
+
+void use_overlay_fb_display_driver(void)
+{
+ use_overlay = 1;
+}
+
+void overlay_set_params(struct mdp_blit_req *e)
+{
+ int result;
+
+ if (please_initialize) {
+ overlayp = &overlay;
+ ovp_front = &ov_front;
+ ovp_back = &ov_back;
+
+ overlayp->id = MSMFB_NEW_REQUEST;
+ }
+
+ overlayp->src.width = e->src.width;
+ overlayp->src.height = e->src.height;
+ overlayp->src.format = e->src.format;
+
+ overlayp->src_rect.x = e->src_rect.x;
+ overlayp->src_rect.y = e->src_rect.y;
+ overlayp->src_rect.w = e->src_rect.w;
+ overlayp->src_rect.h = e->src_rect.h;
+
+ overlayp->dst_rect.x = e->dst_rect.x;
+ overlayp->dst_rect.y = e->dst_rect.y;
+ /* ROTATOR is enabled in overlay library, swap dimensions
+ here to take care of that */
+ overlayp->dst_rect.w = e->dst_rect.h;
+ overlayp->dst_rect.h = e->dst_rect.w;
+
+ if (overlayp->dst_rect.w > 480)
+ overlayp->dst_rect.w = 480;
+ if (overlayp->dst_rect.h > 800)
+ overlayp->dst_rect.h = 800;
+
+ overlayp->z_order = 0; // FB_OVERLAY_VID_0;
+ overlayp->alpha = e->alpha;
+ overlayp->transp_mask = 0; /* 0xF81F */
+ overlayp->flags = e->flags;
+ overlayp->is_fg = 1;
+
+ if (please_initialize) {
+ CDBG("src.width %d height %d; src_rect.x %d y %d w %d h %d; dst_rect.x %d y %d w %d h %d\n",
+ overlayp->src.width, overlayp->src.height,
+ overlayp->src_rect.x, overlayp->src_rect.y, overlayp->src_rect.w, overlayp->src_rect.h,
+ overlayp->dst_rect.x, overlayp->dst_rect.y, overlayp->dst_rect.w, overlayp->dst_rect.h
+ );
+
+ result = ioctl(fb_fd, MSMFB_OVERLAY_SET, overlayp);
+ if (result < 0) {
+ CDBG("ERROR: MSMFB_OVERLAY_SET failed!, result =%d\n", result);
+ }
+ }
+
+ if (please_initialize) {
+ vid_buf_front_id = overlayp->id; /* keep return id */
+
+ ov_front.id = overlayp->id;
+ ov_back.id = overlayp->id;
+ please_initialize = 0;
+ }
+
+ return;
+}
+
+void overlay_set_frame(struct msm_frame *frame)
+{
+ ov_front.data.offset = 0;
+ ov_front.data.memory_id = frame->fd;
+ return;
+}
+
+/*===========================================================================
+ * FUNCTION test_app_camframe_callback
+ * DESCRIPTION display frame
+ *==========================================================================*/
+void test_app_camframe_callback(struct msm_frame *frame)
+{
+ int result = 0;
+ struct mdp_blit_req *e;
+ struct timeval td1, td2;
+ struct timezone tz;
+
+ common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
+
+ /* Initialize yuv structure */
+ yuv.list.count = 1;
+
+ e = &yuv.list.req[0];
+
+ e->src.width = input_display.user_input_display_width;
+ e->src.height = input_display.user_input_display_height;
+ e->src.format = MDP_Y_CRCB_H2V2;
+ e->src.offset = 0;
+ e->src.memory_id = frame->fd;
+
+ e->dst.width = vinfo.xres;
+ e->dst.height = vinfo.yres;
+ e->dst.format = MDP_RGB_565;
+ e->dst.offset = 0;
+ e->dst.memory_id = fb_fd;
+
+ e->transp_mask = 0xffffffff;
+ e->flags = 0;
+ e->alpha = 0xff;
+
+ /* Starting doing MDP Cropping */
+ if (frame->path == OUTPUT_TYPE_P) {
+
+ if (crop->in2_w != 0 || crop->in2_h != 0) {
+
+ e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
+
+ e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
+
+ e->src_rect.w = crop->in2_w;
+ e->src_rect.h = crop->in2_h;
+
+ CDBG("e->src_rect.x = %d\n", e->src_rect.x);
+ CDBG("e->src_rect.y = %d\n", e->src_rect.y);
+ CDBG("e->src_rect.w = %d\n", e->src_rect.w);
+ CDBG("e->src_rect.h = %d\n", e->src_rect.h);
+
+ e->dst_rect.x = 0;
+ e->dst_rect.y = 0;
+ e->dst_rect.w = input_display.user_input_display_width;
+ e->dst_rect.h = input_display.user_input_display_height;
+ } else {
+ e->src_rect.x = 0;
+ e->src_rect.y = 0;
+ e->src_rect.w = input_display.user_input_display_width;
+ e->src_rect.h = input_display.user_input_display_height;
+
+ e->dst_rect.x = 0;
+ e->dst_rect.y = 0;
+ e->dst_rect.w = input_display.user_input_display_width;
+ e->dst_rect.h = input_display.user_input_display_height;
+ }
+ if (use_overlay) overlay_set_params(e);
+ } else {
+
+ }
+
+ gettimeofday(&td1, &tz);
+
+ if (use_overlay) overlay_set_frame(frame);
+ else {
+ result = ioctl(fb_fd, MSMFB_BLIT, &yuv.list);
+ if (result < 0) {
+ CDBG("MSM_FBIOBLT failed! line=%d\n", __LINE__);
+ }
+ }
+
+ gettimeofday(&td2, &tz);
+ CDBG("Profiling: MSMFB_BLIT takes %ld microseconds\n",
+ ((td2.tv_sec - td1.tv_sec) * 1000000 + (td2.tv_usec - td1.tv_usec)));
+
+ td1 = td2;
+ notify_camframe_fb_thread();
+ /* add frame back to the free queue*/
+ //camframe_add_frame(CAM_PREVIEW_FRAME, frame);
+}
+
+void notify_camframe_fb_thread()
+{
+ pthread_mutex_lock(&camframe_fb_mutex);
+
+ num_of_ready_frames ++;
+ pthread_cond_signal(&camframe_fb_cond);
+
+ pthread_mutex_unlock(&camframe_fb_mutex);
+}
+
+void camframe_fb_thread_ready_signal(void);
+
+void *camframe_fb_thread(void *data)
+{
+ int result = 0;
+ static struct timeval td1, td2;
+ struct timezone tz;
+
+#ifdef _ANDROID_
+ fb_fd = open(ANDROID_FB0, O_RDWR);
+ CDBG("%s:android dl '%s', fd=%d\n", __func__, ANDROID_FB0, fb_fd);
+#else
+ fb_fd = open(LE_FB0, O_RDWR);
+ CDBG("%s:LE_FB0 dl, '%s', fd=%d\n", __func__, LE_FB0, fb_fd);
+#endif
+ if (fb_fd < 0) {
+ CDBG_ERROR("cannot open framebuffer %s or %s file node\n",
+ ANDROID_FB0, LE_FB0);
+ goto fail1;
+ }
+
+ if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
+ CDBG_ERROR("cannot retrieve vscreenInfo!\n");
+ goto fail;
+ }
+
+ if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
+ CDBG_ERROR("can't retrieve fscreenInfo!\n");
+ goto fail;
+ }
+
+ vinfo.activate = FB_ACTIVATE_VBL;
+
+ camframe_fb_thread_ready_signal();
+
+ pthread_mutex_lock(&camframe_fb_mutex);
+ while (!camframe_fb_exit) {
+ CDBG("cam_frame_fb_thread: num_of_ready_frames: %d\n", num_of_ready_frames);
+ if (num_of_ready_frames <= 0) {
+ pthread_cond_wait(&camframe_fb_cond, &camframe_fb_mutex);
+ }
+ if (num_of_ready_frames > 0) {
+ num_of_ready_frames --;
+
+ gettimeofday(&td1, &tz);
+ if (use_overlay) {
+ result = ioctl(fb_fd, MSMFB_OVERLAY_PLAY, ovp_front);
+ } else {
+ result = ioctl(fb_fd, FBIOPAN_DISPLAY, &vinfo);
+ }
+
+ gettimeofday(&td2, &tz);
+
+ CDBG("Profiling: frame timestamp after FBIO display = %ld ms\n",
+ (td2.tv_sec*1000) + (td2.tv_usec/1000));
+
+ CDBG("cam_frame_fb_thread: elapse time for FBIOPAN_DISPLAY = %ld, return = %d\n",
+ (td2.tv_sec - td1.tv_sec) * 1000000 + td2.tv_usec - td1.tv_usec, result);
+
+ if (result < 0) {
+ CDBG("DISPLAY: Failed\n");
+ }
+ }
+ }
+
+ pthread_mutex_unlock(&camframe_fb_mutex);
+
+ if (use_overlay) {
+ if (ioctl(fb_fd, MSMFB_OVERLAY_UNSET, &vid_buf_front_id)) {
+ CDBG("\nERROR! MSMFB_OVERLAY_UNSET failed! (Line %d)\n", __LINE__);
+ goto fail;
+ }
+ }
+
+ return NULL;
+
+ fail:
+ close(fb_fd);
+ fail1:
+ camframe_fb_exit = -1;
+ camframe_fb_thread_ready_signal();
+ return NULL;
+}
+
+int launch_camframe_fb_thread(void)
+{
+
+ camframe_fb_exit = 0;
+ is_camframe_fb_thread_ready = 0;
+ pthread_create(&cam_frame_fb_thread_id, NULL, camframe_fb_thread, NULL);
+
+ /* Waiting for launching sub thread ready signal. */
+ CDBG("launch_camframe_fb_thread(), call pthread_cond_wait\n");
+
+ pthread_mutex_lock(&sub_thread_ready_mutex);
+ if (!is_camframe_fb_thread_ready) {
+ pthread_cond_wait(&sub_thread_ready_cond, &sub_thread_ready_mutex);
+ }
+ pthread_mutex_unlock(&sub_thread_ready_mutex);
+
+ CDBG("launch_camframe_fb_thread(), call pthread_cond_wait done\n");
+ CDBG("%s:fb rc=%d\n", __func__, camframe_fb_exit);
+ return camframe_fb_exit;
+}
+
+void release_camframe_fb_thread(void)
+{
+ camframe_fb_exit = 1;
+ please_initialize = 1;
+
+ /* Notify the camframe fb thread to wake up */
+ if (cam_frame_fb_thread_id != 0) {
+ pthread_mutex_lock(&camframe_fb_mutex);
+ pthread_cond_signal(&camframe_fb_cond);
+ pthread_mutex_unlock(&camframe_fb_mutex);
+ if (pthread_join(cam_frame_fb_thread_id, NULL) != 0) {
+ CDBG("cam_frame_fb_thread exit failure!\n");
+ }
+ close(fb_fd);
+ }
+}
+
+void camframe_fb_thread_ready_signal(void)
+{
+ /* Send the signal to control thread to indicate that the cam frame fb
+ * ready.
+ */
+ CDBG("cam_frame_fb_thread() is ready, call pthread_cond_signal\n");
+
+ pthread_mutex_lock(&sub_thread_ready_mutex);
+ is_camframe_fb_thread_ready = 1;
+ pthread_cond_signal(&sub_thread_ready_cond);
+ pthread_mutex_unlock(&sub_thread_ready_mutex);
+
+ CDBG("cam_frame_fb_thread() is ready, call pthread_cond_signal done\n");
+}
+
+#ifdef CAM_FRM_DRAW_RECT
+void draw_rect(char *buf, int buf_w,
+ int x, int y, int dx, int dy)
+{
+ int i;
+ int left = x;
+ int right = x+dx;
+ int top = y;
+ int bottom = y+dy;
+
+ for (i = left; i < right; i++) {
+ buf[top*buf_w+i] = 0xff;
+ buf[bottom*buf_w+i] = 0xff;
+ }
+ for (i = top; i < bottom; i++) {
+ buf[i*buf_w+left] = 0xff;
+ buf[i*buf_w+right] = 0xff;
+ }
+}
+#endif
+
+void draw_rectangles(struct msm_frame* newFrame)
+{
+ struct fd_roi_t *p_fd_roi;
+#ifdef DRAW_RECTANGLES
+ uint8_t i;
+ for (i = 0; i < camframe_roi.num_roi; i++) {
+ CDBG("%s: camframe_roi: i=%d, x=%d, y=%d, dx=%d, dy=%d\n", __func__,
+ i, camframe_roi.roi[i].x, camframe_roi.roi[i].y,
+ camframe_roi.roi[i].dx, camframe_roi.roi[i].dy);
+ draw_rect((char*)newFrame->buffer, 640,
+ camframe_roi.roi[i].x, camframe_roi.roi[i].y,
+ camframe_roi.roi[i].dx, camframe_roi.roi[i].dy);
+ }
+#endif
+
+#ifdef CAM_FRM_DRAW_FD_RECT
+ p_fd_roi = (struct fd_roi_t *)newFrame->roi_info.info;
+ if(p_fd_roi && p_fd_roi->rect_num > 0){
+ int i;
+ for(i =0; i < p_fd_roi->rect_num; i++)
+ {
+ draw_rect((char*)newFrame->buffer, 800,
+ p_fd_roi->faces[i].x, p_fd_roi->faces[i].y,
+ p_fd_roi->faces[i].dx, p_fd_roi->faces[i].dy);
+ }
+ }
+#endif
+}
+
+/*===========================================================================
+ * FUNCTION - v4l2_render -
+ *
+ * DESCRIPTION:
+ *==========================================================================*/
+int v4l2_render(int frame_fd, struct v4l2_buffer *vb, struct v4l2_crop *crop)
+{
+ struct mdp_blit_req *e;
+ /* Initialize yuv structure */
+ yuv.list.count = 1;
+ e = &yuv.list.req[0];
+
+ e->src.width = input_display.user_input_display_width;
+ e->src.height = input_display.user_input_display_height;
+ e->src.format = MDP_Y_CBCR_H2V2;
+ e->src.offset = 0;
+ e->src.memory_id = frame_fd;
+
+ e->dst.width = vinfo.xres;
+ e->dst.height = vinfo.yres;
+ e->dst.format = MDP_RGB_565;
+ e->dst.offset = 0;
+ e->dst.memory_id = fb_fd;
+
+ e->transp_mask = 0xffffffff;
+ e->flags = 0;
+ e->alpha = 0xff;
+
+ if (crop != NULL && (crop->c.width != 0 || crop->c.height != 0)) {
+ e->src_rect.x = crop->c.left;
+ e->src_rect.y = crop->c.top;
+ e->src_rect.w = crop->c.width;
+ e->src_rect.h = crop->c.height;
+
+ e->dst_rect.x = 0;
+ e->dst_rect.y = 0;
+ e->dst_rect.w = input_display.user_input_display_width;
+ e->dst_rect.h = input_display.user_input_display_height;
+ } else {
+ e->dst_rect.x = 0;
+ e->dst_rect.y = 0;
+ e->dst_rect.w = input_display.user_input_display_width;
+ e->dst_rect.h = input_display.user_input_display_height;
+
+ e->src_rect.x = 0;
+ e->src_rect.y = 0;
+ e->src_rect.w = input_display.user_input_display_width;
+ e->src_rect.h = input_display.user_input_display_height;
+ }
+ overlay_set_params(e);
+ ov_front.data.offset = 0;
+ ov_front.data.memory_id = frame_fd;
+ notify_camframe_fb_thread();
+
+ return TRUE;
+}
+
+int mm_app_dl_render(int frame_fd, struct crop_info * cropinfo)
+{
+ struct mdp_blit_req *e;
+ int croplen = 0;
+ //struct crop_info *cropinfo;
+ common_crop_t *crop;
+
+ //cropinfo = (struct crop_info *)vb->input;
+ if(cropinfo != NULL) {
+ crop = (common_crop_t *)cropinfo->info;
+ }
+ /* Initialize yuv structure */
+ yuv.list.count = 1;
+ e = &yuv.list.req[0];
+
+ e->src.width = input_display.user_input_display_width;
+ e->src.height = input_display.user_input_display_height;
+ e->src.format = MDP_Y_CRCB_H2V2;
+ e->src.offset = 0;
+ e->src.memory_id = frame_fd;
+
+ e->dst.width = vinfo.xres;
+ e->dst.height = vinfo.yres;
+ e->dst.format = MDP_RGB_565;
+ e->dst.offset = 0;
+ e->dst.memory_id = fb_fd;
+
+ e->transp_mask = 0xffffffff;
+ e->flags = 0;
+ e->alpha = 0xff;
+
+ if (cropinfo != NULL && (crop->in2_w != 0 || crop->in2_h != 0)) {
+ e->src_rect.x = (crop->out2_w - crop->in2_w + 1) / 2 - 1;
+ e->src_rect.y = (crop->out2_h - crop->in2_h + 1) / 2 - 1;
+ e->src_rect.w = crop->in2_w;
+ e->src_rect.h = crop->in2_h;
+
+ e->dst_rect.x = 0;
+ e->dst_rect.y = 0;
+ e->dst_rect.w = input_display.user_input_display_width;
+ e->dst_rect.h = input_display.user_input_display_height;
+ } else {
+ e->dst_rect.x = 0;
+ e->dst_rect.y = 0;
+ e->dst_rect.w = input_display.user_input_display_width;
+ e->dst_rect.h = input_display.user_input_display_height;
+
+ e->src_rect.x = 0;
+ e->src_rect.y = 0;
+ e->src_rect.w = input_display.user_input_display_width;
+ e->src_rect.h = input_display.user_input_display_height;
+ }
+
+ overlay_set_params(e);
+
+ ov_front.data.offset = 0;
+ ov_front.data.memory_id = frame_fd;
+ notify_camframe_fb_thread();
+
+ return TRUE;
+}
+
+
diff --git a/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_dual_test.c b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_dual_test.c
new file mode 100755
index 0000000..37f0144
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_dual_test.c
@@ -0,0 +1,565 @@
+/*
+Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include "mm_camera_dbg.h"
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include "mm_qcamera_unit_test.h"
+
+#define MM_QCAMERA_APP_UTEST_MAX_MAIN_LOOP 4
+#define MM_QCAM_APP_TEST_NUM 128
+
+#define MM_QCAMERA_APP_INTERATION 5
+#define MM_QCAMERA_APP_WAIT_TIME 1000000000
+
+static mm_app_tc_t mm_app_tc[MM_QCAM_APP_TEST_NUM];
+static int num_test_cases = 0;
+
+int mm_app_dtc_0(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i,j;
+ int result = 0;
+ int front_camera = 1;
+ int back_camera = 0;
+
+ printf("\n Verifying Preview on back Camera and RDI on Front camera...\n");
+
+ if(mm_app_open(back_camera) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_open() back camera err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ if(system_dimension_set(back_camera) != MM_CAMERA_OK){
+ CDBG_ERROR("%s:system_dimension_set() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+ if( MM_CAMERA_OK != (rc = startPreview(back_camera))) {
+ CDBG_ERROR("%s: back camera startPreview() err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ mm_camera_app_wait();
+ if(mm_app_open(front_camera) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_open() front camera err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ if(system_dimension_set(front_camera) != MM_CAMERA_OK){
+ CDBG_ERROR("%s:system_dimension_set() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+ if( MM_CAMERA_OK != (rc = startRdi(front_camera))) {
+ CDBG_ERROR("%s: startPreview() backcamera err=%d\n", __func__, rc);
+ goto end;
+ }
+ mm_camera_app_wait();
+
+ if( MM_CAMERA_OK != (rc = stopRdi(front_camera))) {
+ CDBG_ERROR("%s: startPreview() backcamera err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ if( MM_CAMERA_OK != (rc = stopPreview(my_cam_app.cam_open))) {
+ CDBG("%s: startPreview() err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ if( mm_app_close(my_cam_app.cam_open) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_close() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+end:
+ if(rc == 0) {
+ printf("\nPassed\n");
+ }else{
+ printf("\nFailed\n");
+ }
+ CDBG("%s:END, rc = %d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_dtc_1(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i,j;
+ int result = 0;
+
+ printf("\n Verifying Snapshot on front and back camera...\n");
+ for(i = 0; i < cam_apps->num_cameras; i++) {
+ if( mm_app_open(i) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_open() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ if(system_dimension_set(my_cam_app.cam_open) != MM_CAMERA_OK){
+ CDBG_ERROR("%s:system_dimension_set() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+ if( MM_CAMERA_OK != (rc = startPreview(my_cam_app.cam_open))) {
+ CDBG_ERROR("%s: startPreview() err=%d\n", __func__, rc);
+ break;
+ }
+ for(j = 0; j < MM_QCAMERA_APP_INTERATION; j++) {
+ if( MM_CAMERA_OK != (rc = takePicture_yuv(my_cam_app.cam_open))) {
+ CDBG_ERROR("%s: TakePicture() err=%d\n", __func__, rc);
+ break;
+ }
+ /*if(mm_camera_app_timedwait() == ETIMEDOUT) {
+ CDBG_ERROR("%s: Snapshot/Preview Callback not received in time or qbuf Faile\n", __func__);
+ break;
+ }*/
+ mm_camera_app_wait();
+ result++;
+ }
+ if( MM_CAMERA_OK != (rc = stopPreview(my_cam_app.cam_open))) {
+ CDBG("%s: startPreview() err=%d\n", __func__, rc);
+ break;
+ }
+ if( mm_app_close(my_cam_app.cam_open) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_close() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ if(result != MM_QCAMERA_APP_INTERATION) {
+ printf("%s: Snapshot Start/Stop Fails for Camera %d in %d iteration", __func__, i,j);
+ rc = -1;
+ break;
+ }
+
+ result = 0;
+ }
+end:
+ if(rc == 0) {
+ printf("\t***Passed***\n");
+ }else{
+ printf("\t***Failed***\n");
+ }
+ CDBG("%s:END, rc = %d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_dtc_2(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i,j;
+ int result = 0;
+
+ printf("\n Verifying Video on front and back camera...\n");
+ for(i = 0; i < cam_apps->num_cameras; i++) {
+ if( mm_app_open(i) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_open() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ if(system_dimension_set(my_cam_app.cam_open) != MM_CAMERA_OK){
+ CDBG_ERROR("%s:system_dimension_set() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+ if( MM_CAMERA_OK != (rc = startPreview(my_cam_app.cam_open))) {
+ CDBG_ERROR("%s: startPreview() err=%d\n", __func__, rc);
+ break;
+ }
+ for(j = 0; j < MM_QCAMERA_APP_INTERATION; j++) {
+ if( MM_CAMERA_OK != (rc = startRecording(my_cam_app.cam_open))) {
+ CDBG_ERROR("%s: StartVideorecording() err=%d\n", __func__, rc);
+ break;
+ }
+
+ /*if(mm_camera_app_timedwait() == ETIMEDOUT) {
+ CDBG_ERROR("%s: Video Callback not received in time\n", __func__);
+ break;
+ }*/
+ mm_camera_app_wait();
+ if( MM_CAMERA_OK != (rc = stopRecording(my_cam_app.cam_open))) {
+ CDBG_ERROR("%s: Stopvideorecording() err=%d\n", __func__, rc);
+ break;
+ }
+ result++;
+ }
+ if( MM_CAMERA_OK != (rc = stopPreview(my_cam_app.cam_open))) {
+ CDBG("%s: startPreview() err=%d\n", __func__, rc);
+ break;
+ }
+ if( mm_app_close(my_cam_app.cam_open) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_close() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ if(result != MM_QCAMERA_APP_INTERATION) {
+ printf("%s: Video Start/Stop Fails for Camera %d in %d iteration", __func__, i,j);
+ rc = -1;
+ break;
+ }
+
+ result = 0;
+ }
+end:
+ if(rc == 0) {
+ printf("\nPassed\n");
+ }else{
+ printf("\nFailed\n");
+ }
+ CDBG("%s:END, rc = %d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_dtc_3(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i,j;
+ int result = 0;
+
+ printf("\n Verifying RDI Stream on front and back camera...\n");
+ if(cam_apps->num_cameras == 0) {
+ CDBG_ERROR("%s:Query Failed: Num of cameras = %d\n",__func__, cam_apps->num_cameras);
+ rc = -1;
+ goto end;
+ }
+ for(i = 0; i < cam_apps->num_cameras; i++) {
+ if( mm_app_open(i) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_open() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ if(system_dimension_set(my_cam_app.cam_open) != MM_CAMERA_OK){
+ CDBG_ERROR("%s:system_dimension_set() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ for(j = 0; j < MM_QCAMERA_APP_INTERATION; j++) {
+ if( MM_CAMERA_OK != (rc = startRdi(my_cam_app.cam_open))) {
+ CDBG_ERROR("%s: StartVideorecording() err=%d\n", __func__, rc);
+ break;
+ }
+
+ /*if(mm_camera_app_timedwait() == ETIMEDOUT) {
+ CDBG_ERROR("%s: Video Callback not received in time\n", __func__);
+ break;
+ }*/
+ mm_camera_app_wait();
+ if( MM_CAMERA_OK != (rc = stopRdi(my_cam_app.cam_open))) {
+ CDBG_ERROR("%s: Stopvideorecording() err=%d\n", __func__, rc);
+ break;
+ }
+ result++;
+ }
+ if( mm_app_close(my_cam_app.cam_open) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_close() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ if(result != MM_QCAMERA_APP_INTERATION) {
+ printf("%s: Video Start/Stop Fails for Camera %d in %d iteration", __func__, i,j);
+ rc = -1;
+ break;
+ }
+
+ result = 0;
+ }
+end:
+ if(rc == 0) {
+ printf("\nPassed\n");
+ }else{
+ printf("\nFailed\n");
+ }
+ CDBG("%s:END, rc = %d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_dtc_4(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i;
+ printf("Running %s - open/close ,video0, open/close preview channel only\n", __func__);
+#if 0
+ for(i = 0; i < MM_QCAMERA_APP_UTEST_MAX_MAIN_LOOP; i++) {
+ if ( 0 != (rc = mm_app_open(cam_id, MM_CAMERA_OP_MODE_NOTUSED))) {
+ CDBG("%s: open cam %d at opmode = %d err, loop=%d, rc=%d\n", __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+ if(0 != (rc = mm_app_open_preview(cam_id))) {
+ goto end;
+ }
+ if(0 != (rc = mm_app_close_preview(cam_id))) {
+ goto end;
+ }
+ if ( 0 != (rc = mm_app_close(cam_id))) {
+ CDBG("%s: close cam %d at opmode = %d err,loop=%d, rc=%d\n", __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+ }
+end:
+#endif
+ CDBG("%s:END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+
+
+int mm_app_dtc_5(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i;
+ printf("Running %s - open/close ,video0, open/close snapshot channel only\n", __func__);
+#if 0
+ for(i = 0; i < MM_QCAMERA_APP_UTEST_MAX_MAIN_LOOP; i++) {
+ if ( 0 != (rc = mm_app_open(cam_id, MM_CAMERA_OP_MODE_NOTUSED))) {
+ CDBG("%s: open cam %d at opmode = %d err, loop=%d, rc=%d\n",
+ __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+ if(0 != (rc = mm_app_open_snapshot(cam_id))) {
+ goto end;
+ }
+ if(0 != (rc = mm_app_close_snapshot(cam_id))) {
+ goto end;
+ }
+ if ( 0 != (rc = mm_app_close(cam_id))) {
+ CDBG("%s: close cam %d at opmode = %d err,loop=%d, rc=%d\n",
+ __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+ }
+end:
+#endif
+ CDBG("%s:END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_dtc_6(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i;
+ printf("Running %s - simple preview \n", __func__);
+#if 0
+ if ( 0 != (rc = mm_app_open(cam_id, MM_CAMERA_OP_MODE_NOTUSED))) {
+ CDBG("%s: open cam %d at opmode = %d err, loop=%d, rc=%d\n",
+ __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+
+ for(i = 0; i < MM_QCAMERA_APP_UTEST_MAX_MAIN_LOOP; i++) {
+ if(0 != (rc = mm_app_init_preview(cam_id))) {
+ goto end;
+ }
+ if(0 != (rc = mm_app_start_preview(cam_id))) {
+ goto end;
+ }
+ /* sleep 8 seconds */
+ usleep(8000000);
+ if(0 != (rc = mm_app_stop_preview(cam_id))) {
+ goto end;
+ }
+ if(0 != (rc=mm_app_deinit_preview(cam_id))) {
+ goto end;
+ }
+ if(0 != (rc = mm_app_close_preview(cam_id))) {
+ goto end;
+ }
+ }
+ if ( 0 != (rc = mm_app_close(cam_id))) {
+ CDBG("%s: close cam %d at opmode = %d err,loop=%d, rc=%d\n",
+ __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+end:
+#endif
+ CDBG("%s:END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_dtc_7(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i;
+ printf("Running %s - simple preview and recording \n", __func__);
+#if 0
+ if ( 0 != (rc = mm_app_open(cam_id, MM_CAMERA_OP_MODE_NOTUSED))) {
+ CDBG("%s: open cam %d at opmode = %d err, loop=%d, rc=%d\n",
+ __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+
+ for(i = 0; i < MM_QCAMERA_APP_UTEST_MAX_MAIN_LOOP; i++) {
+ if(0 != (rc = mm_app_init_preview(cam_id))) {
+ goto end;
+ }
+ if(0 != (rc = mm_app_start_preview(cam_id))) {
+ goto end;
+ }
+ /* sleep 8 seconds */
+ usleep(8000000);
+ if(0 != (rc = mm_app_start_recording(cam_id))) {
+ goto end;
+ }
+ usleep(1000000);
+ if(0 != (rc = mm_app_stop_recording(cam_id))) {
+ goto end;
+ }
+ usleep(8000000);
+ if(0 != (rc = mm_app_stop_preview(cam_id))) {
+ goto end;
+ }
+ if(0 != (rc=mm_app_deinit_preview(cam_id))) {
+ goto end;
+ }
+ if(0 != (rc = mm_app_close_preview(cam_id))) {
+ goto end;
+ }
+ }
+ if ( 0 != (rc = mm_app_close(cam_id))) {
+ CDBG("%s: close cam %d at opmode = %d err,loop=%d, rc=%d\n",
+ __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+end:
+#endif
+ CDBG("%s:END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_dtc_8(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i;
+ printf("Running %s - preview, recording, and snapshot, then preview again \n", __func__);
+#if 0
+ if ( 0 != (rc = mm_app_open(cam_id, MM_CAMERA_OP_MODE_NOTUSED))) {
+ CDBG("%s: open cam %d at opmode = %d err, loop=%d, rc=%d\n",
+ __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+
+ for(i = 0; i < MM_QCAMERA_APP_UTEST_MAX_MAIN_LOOP; i++) {
+ if(0 != (rc = mm_app_init_preview(cam_id))) {
+ goto end;
+ }
+ if(0 != (rc = mm_app_start_preview(cam_id))) {
+ goto end;
+ }
+ /* sleep 8 seconds */
+ usleep(8000000);
+ if(0 != (rc = mm_app_start_recording(cam_id))) {
+ goto end;
+ }
+ usleep(1000000);
+ if(0 != (rc = mm_app_stop_recording(cam_id))) {
+ goto end;
+ }
+ if(0 != (rc = mm_app_stop_preview(cam_id))) {
+ goto end;
+ }
+ if(0!=(rc=mm_app_init_snapshot(cam_id))) {
+ goto end;
+ }
+ if(0 != (rc=mm_app_take_picture(cam_id))) {
+ goto end;
+ }
+ if( 0 != (rc = mm_app_deinit_snahspot(cam_id))) {
+ goto end;
+ }
+ if(0 != (rc = mm_app_start_preview(cam_id))) {
+ goto end;
+ }
+ usleep(8000000);
+ if(0 != (rc=mm_app_deinit_preview(cam_id))) {
+ goto end;
+ }
+ if(0 != (rc = mm_app_close_preview(cam_id))) {
+ goto end;
+ }
+ }
+ if ( 0 != (rc = mm_app_close(cam_id))) {
+ CDBG("%s: close cam %d at opmode = %d err,loop=%d, rc=%d\n",
+ __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+end:
+#endif
+ CDBG("%s:END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+
+int mm_app_gen_dual_test_cases()
+{
+ int tc = 0;
+ memset(mm_app_tc, 0, sizeof(mm_app_tc));
+ if(tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_dtc_0;
+ /*if(tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_dtc_1;
+ if(tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_dtc_2;
+ if(tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_dtc_3;
+ if(tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_dtc_4;
+ if(tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_dtc_5;
+ if(tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_dtc_6;
+ if(tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_dtc_7;
+ if(tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_dtc_8;*/
+ return tc;
+}
+
+int mm_app_dual_test_entry(mm_camera_app_t *cam_app)
+{
+ int rc = MM_CAMERA_OK;
+ int i, tc = 0;
+ int cam_id = 0;
+
+ tc = mm_app_gen_dual_test_cases();
+ CDBG("Running %d test cases\n",tc);
+ for(i = 0; i < tc; i++) {
+ mm_app_tc[i].r = mm_app_tc[i].f(cam_app);
+ if(mm_app_tc[i].r != MM_CAMERA_OK) {
+ printf("%s: test case %d error = %d, abort unit testing engine!!!!\n",
+ __func__, i, mm_app_tc[i].r);
+ rc = mm_app_tc[i].r;
+ goto end;
+ }
+ }
+end:
+ printf("nTOTAL_TSET_CASE = %d, NUM_TEST_RAN = %d, rc=%d\n", tc, i, rc);
+ return rc;
+}
+
+
+
+
diff --git a/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_main_menu.c b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_main_menu.c
new file mode 100755
index 0000000..89fca13
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_main_menu.c
@@ -0,0 +1,1930 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <termios.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#ifdef _ANDROID_
+#include <cutils/log.h>
+#endif
+#include <dlfcn.h>
+
+#include "camera.h"
+#include "mm_camera_dbg.h"
+#include "mm_qcamera_main_menu.h"
+#include "mm_qcamera_display_dimensions.h"
+#include "camera_defs_i.h"
+#include "mm_qcamera_app.h"
+
+#define CAMERA_OPENED 0
+
+#define VIDEO_BUFFER_SIZE (PREVIEW_WIDTH * PREVIEW_HEIGHT * 3/2)
+#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2)
+#define SNAPSHOT_BUFFER_SIZE (PICTURE_WIDTH * PICTURE_HEIGHT * 3/2)
+/*===========================================================================
+ * Macro
+ *===========================================================================*/
+#define PREVIEW_FRAMES_NUM 4
+#define VIDEO_FRAMES_NUM 4
+#define THUMBNAIL_FRAMES_NUM 1
+#define SNAPSHOT_FRAMES_NUM 1
+#define MAX_NUM_FORMAT 32
+/*===========================================================================
+ * Defines
+ *===========================================================================*/
+
+const CAMERA_MAIN_MENU_TBL_T camera_main_menu_tbl[] = {
+ {STOP_CAMERA, "Stop preview/video and exit camera."},
+ {PREVIEW_VIDEO_RESOLUTION, "Preview/Video Resolution: SQCIF/QCIF/"
+ "QVGA/CIF/VGA/WVGA... Default WVGA."},
+ {TAKE_YUV_SNAPSHOT, "Take a snapshot"},
+ {TAKE_RAW_SNAPSHOT, "Take a raw snapshot"},
+ {TAKE_ZSL_SNAPSHOT, "Take a ZSL snapshot"},
+ {START_RECORDING, "Start RECORDING"},
+ {START_RDI, "Start RDI stream"},
+ {STOP_RDI, "Stop RDI stream"},
+ {SWITCH_CAMERA, "Switch Camera"},
+#if 0
+ {SET_WHITE_BALANCE, "Set white balance mode: Auto/Off/Daylight/Incandescent/Fluorescent. Default Auto."},
+ {SET_EXP_METERING, "Set exposure metering mode: FrameAverage/CenterWeighted/SpotMetering. Default CenterWeighted"},
+ {GET_CTRL_VALUE, "Get control value menu"},
+ {TOGGLE_AFR, "Toggle auto frame rate. Default fixed frame rate"},
+ {SET_ISO, "ISO changes."},
+ {BRIGHTNESS_GOTO_SUBMENU, "Brightness changes."},
+ {CONTRAST_GOTO_SUBMENU, "Contrast changes."},
+ {EV_GOTO_SUBMENU, "EV changes."},
+ {SATURATION_GOTO_SUBMENU, "Saturation changes."},
+ {SET_ZOOM, "Set Digital Zoom."},
+ {SET_SHARPNESS, "Set Sharpness."},
+#endif
+};
+
+const PREVIEW_DIMENSION_TBL_T preview_video_dimension_tbl[] = {
+ { SQCIF, SQCIF_WIDTH, SQCIF_HEIGHT, "SQCIF", "Preview/Video Resolution: SQCIF <128x96>"},
+ { QCIF, QCIF_WIDTH, QCIF_HEIGHT, "QCIF", "Preview/Video Resolution: QCIF <176x144>"},
+ { QVGA, QVGA_WIDTH, QVGA_HEIGHT, "QVGA", "Preview/Video Resolution: QVGA <320x240>"},
+ { CIF, CIF_WIDTH, CIF_HEIGHT, "CIF", "Preview/Video Resolution: CIF <352x288>"},
+ { VGA, VGA_WIDTH, VGA_HEIGHT, "VGA", "Preview/Video Resolution: VGA <640x480>"},
+ { WVGA, WVGA_WIDTH, WVGA_HEIGHT, "WVGA", "Preview/Video Resolution: WVGA <800x480>"},
+ { SVGA, SVGA_WIDTH, SVGA_HEIGHT, "SVGA", "Preview/Video Resolution: SVGA <800x600>"},
+ { XGA, XGA_WIDTH, XGA_HEIGHT, "XGA", "Preview/Video Resolution: XGA <1024x768>"},
+ { HD720, HD720_WIDTH, HD720_HEIGHT, "HD720", "Preview/Video Resolution: HD720 <1280x720>"},
+};
+
+const CAMERA_BRIGHTNESS_TBL_T brightness_change_tbl[] = {
+ {INC_BRIGHTNESS, "Increase Brightness by one step."},
+ {DEC_BRIGHTNESS, "Decrease Brightness by one step."},
+};
+
+const CAMERA_CONTRST_TBL_T contrast_change_tbl[] = {
+ {INC_CONTRAST, "Increase Contrast by one step."},
+ {DEC_CONTRAST, "Decrease Contrast by one step."},
+};
+
+const CAMERA_EV_TBL_T camera_EV_tbl[] = {
+ {INCREASE_EV, "Increase EV by one step."},
+ {DECREASE_EV, "Decrease EV by one step."},
+};
+
+const CAMERA_SATURATION_TBL_T camera_saturation_tbl[] = {
+ {INC_SATURATION, "Increase Satuation by one step."},
+ {DEC_SATURATION, "Decrease Satuation by one step."},
+};
+
+const CAMERA_SHARPNESS_TBL_T camera_sharpness_tbl[] = {
+ {INC_SHARPNESS, "Increase Sharpness."},
+ {DEC_SHARPNESS, "Decrease Sharpness."},
+};
+
+const WHITE_BALANCE_TBL_T white_balance_tbl[] = {
+ { MM_CAMERA_WHITE_BALANCE_AUTO, "White Balance - Auto"},
+ { MM_CAMERA_WHITE_BALANCE_OFF, "White Balance - Off"},
+ { MM_CAMERA_WHITE_BALANCE_DAYLIGHT, "White Balance - Daylight"},
+ { MM_CAMERA_WHITE_BALANCE_INCANDESCENT, "White Balance - Incandescent"},
+ { MM_CAMERA_WHITE_BALANCE_FLUORESCENT, "White Balance - Fluorescent"},
+};
+
+const CAMERA_TBL_T cam_tbl[] = {
+ { 1, "Back Camera"},
+ { 2, "Front Camera"},
+};
+
+const RECORD_TBL_T record_tbl[] = {
+ { LIVE_SNAPSHOT_MENU, "Take Live snapshot"},
+ { STOP_RECORDING_MENU, "Stop Recording"},
+};
+
+const GET_CTRL_TBL_T get_ctrl_tbl[] = {
+ { WHITE_BALANCE_STATE, "Get white balance state (auto/off)"},
+ { WHITE_BALANCE_TEMPERATURE, "Get white balance temperature"},
+ { BRIGHTNESS_CTRL, "Get brightness value"},
+ { EV, "Get exposure value"},
+ { CONTRAST_CTRL, "Get contrast value"},
+ { SATURATION_CTRL, "Get saturation value"},
+ { SHARPNESS_CTRL, "Get sharpness value"},
+};
+
+const EXP_METERING_TBL_T exp_metering_tbl[] = {
+ { EXP_METERING_FRAME_AVERAGE, "Exposure Metering - Frame Average"},
+ { EXP_METERING_CENTER_WEIGHTED, "Exposure Metering - Center Weighted"},
+ { EXP_METERING_SPOT_METERING, "Exposure Metering - Spot Metering"},
+};
+
+const ISO_TBL_T iso_tbl[] = {
+ { ISO_AUTO, "ISO: Auto"},
+ { ISO_DEBLUR, "ISO: Deblur"},
+ { ISO_100, "ISO: 100"},
+ { ISO_200, "ISO: 200"},
+ { ISO_400, "ISO: 400"},
+ { ISO_800, "ISO: 800"},
+ { ISO_1600, "ISO: 1600"},
+};
+
+const ZOOM_TBL_T zoom_tbl[] = {
+ { ZOOM_IN, "Zoom In one step"},
+ { ZOOM_OUT, "Zoom Out one step"},
+};
+
+
+struct v4l2_fmtdesc enumfmtdesc[MAX_NUM_FORMAT];
+struct v4l2_format current_fmt;
+
+/*===========================================================================
+ * Forward declarations
+ *===========================================================================*/
+static int set_fps(int fps);
+static int start_snapshot (void);
+static int stop_snapshot (void);
+/*===========================================================================
+ * Static global variables
+ *===========================================================================*/
+USER_INPUT_DISPLAY_T input_display;
+static int camframe_status = 0;
+
+#ifdef _ANDROID_
+char *sdcard_path = "/data";
+#else
+char *sdcard_path = ".";
+#endif
+
+//void *libqcamera = NULL;
+//void (**LINK_jpegfragment_callback)(uint8_t * buff_ptr , uint32_t buff_size);
+//void (**LINK_jpeg_callback)(void);
+
+int num_supported_fmts = 0;
+int memoryType = V4L2_MEMORY_MMAP; /* default */
+int preview_video_resolution_flag = 0;
+int effect = CAMERA_EFFECT_OFF;
+int brightness = CAMERA_DEF_BRIGHTNESS;
+int contrast = CAMERA_DEF_CONTRAST;
+int saturation = CAMERA_DEF_SATURATION;
+int sharpness = CAMERA_DEF_SHARPNESS;
+int32_t ev_num = 0;
+uint8_t ezTune = FALSE;
+int pmemThumbnailfd = 0;
+int pmemSnapshotfd = 0;
+int pmemRawSnapshotfd = 0;
+int fdSnapshot = 0;
+int fdThumbnail = 0;
+char snapshotBuf[256] = { 0};
+char thumbnailBuf[256] = { 0};
+uint32_t snapshot_buff_size = 0;
+uint32_t raw_snapshot_buffer_size = 0;
+static int thumbnailCntr = 0, snapshotCntr = 0;
+unsigned char *thumbnail_buf = NULL, *main_img_buf = NULL, *raw_img_buf = NULL;
+int32_t *sharpness_AF = NULL;
+struct crop_info cropInfo;
+common_crop_t cropInfo_s;
+
+interface_ctrl_t intrfcCtrl;
+config3a_wb_t autoWB = CAMERA_WB_AUTO;
+isp3a_af_mode_t af_mode = AF_MODE_AUTO;
+cam_af_focusrect_t afFocusRect = AUTO;
+
+cam_af_ctrl_t af_ctrl;
+camera_iso_mode_type iso = CAMERA_ISO_AUTO;
+camera_antibanding_type antibanding = CAMERA_ANTIBANDING_OFF;
+camera_auto_exposure_mode_type aec_mode = CAMERA_AEC_CENTER_WEIGHTED;
+led_mode_t led_mode = LED_MODE_OFF;
+motion_iso_t motion_iso = MOTION_ISO_OFF;
+int32_t hue = CAMERA_DEF_HUE;
+fps_mode_t fps_mode = FPS_MODE_AUTO;
+
+struct v4l2_cropcap cropcap;
+struct v4l2_queryctrl zoom_queryctrl;
+struct v4l2_queryctrl sharpness_queryctrl;
+int zoom_level;
+
+Camera_Resolution Resolution;
+//int32_t g_camParmInfo_current_value = 0;
+//extern unsigned long preview_frames_buf;
+//extern void test_app_mmcamera_videoframe_callback(struct msm_frame *frame); // video_cam.c
+
+/* To flush free video buffers queue */
+//void (*LINK_cam_frame_flush_free_video)(void);
+static int submain();
+
+//struct v4l2_frame_buffer frames[PREVIEW_FRAMES_NUM];
+//struct v4l2_frame_buffer video_frames[VIDEO_FRAMES_NUM];
+
+//pthread_t frame_thread;
+
+void test_app_camframe_timeout_callback(void)
+{
+ camframe_status = -1;
+}
+
+/*===========================================================================
+ * FUNCTION - keypress_to_event -
+ *
+ * DESCRIPTION:
+ *==========================================================================*/
+int keypress_to_event(char keypress)
+{
+ char out_buf = INVALID_KEY_PRESS;
+ if ((keypress >= 'A' && keypress <= 'Z') ||
+ (keypress >= 'a' && keypress <= 'z')) {
+ out_buf = tolower(keypress);
+ out_buf = out_buf - 'a' + 1;
+ } else if (keypress >= '1' && keypress <= '9') {
+ out_buf = keypress;
+ out_buf = keypress - '1' + BASE_OFFSET_NUM;
+ }
+ return out_buf;
+}
+
+int next_menu(menu_id_change_t current_menu_id, char keypress, camera_action_t * action_id_ptr, int * action_param)
+{
+ char output_to_event;
+ menu_id_change_t next_menu_id = MENU_ID_INVALID;
+ * action_id_ptr = ACTION_NO_ACTION;
+
+ output_to_event = keypress_to_event(keypress);
+ CDBG("current_menu_id=%d\n",current_menu_id);
+ CDBG("output_to_event=%d\n",output_to_event);
+ switch(current_menu_id) {
+ case MENU_ID_MAIN:
+ switch(output_to_event) {
+ case STOP_CAMERA:
+ * action_id_ptr = ACTION_STOP_CAMERA;
+ CDBG("STOP_CAMERA\n");
+ break;
+
+ case PREVIEW_VIDEO_RESOLUTION:
+ next_menu_id = MENU_ID_PREVIEWVIDEORESOLUTIONCHANGE;
+ CDBG("next_menu_id = MENU_ID_PREVIEWVIDEORESOLUTIONCHANGE = %d\n", next_menu_id);
+ break;
+#if 0
+ case SET_WHITE_BALANCE:
+ next_menu_id = MENU_ID_WHITEBALANCECHANGE;
+ CDBG("next_menu_id = MENU_ID_WHITEBALANCECHANGE = %d\n", next_menu_id);
+ break;
+
+ case SET_EXP_METERING:
+ next_menu_id = MENU_ID_EXPMETERINGCHANGE;
+ CDBG("next_menu_id = MENU_ID_EXPMETERINGCHANGE = %d\n", next_menu_id);
+ break;
+
+ case GET_CTRL_VALUE:
+ next_menu_id = MENU_ID_GET_CTRL_VALUE;
+ CDBG("next_menu_id = MENU_ID_GET_CTRL_VALUE = %d\n", next_menu_id);
+ break;
+
+ case BRIGHTNESS_GOTO_SUBMENU:
+ next_menu_id = MENU_ID_BRIGHTNESSCHANGE;
+ CDBG("next_menu_id = MENU_ID_BRIGHTNESSCHANGE = %d\n", next_menu_id);
+ break;
+
+ case CONTRAST_GOTO_SUBMENU:
+ next_menu_id = MENU_ID_CONTRASTCHANGE;
+ break;
+
+ case EV_GOTO_SUBMENU:
+ next_menu_id = MENU_ID_EVCHANGE;
+ break;
+
+ case SATURATION_GOTO_SUBMENU:
+ next_menu_id = MENU_ID_SATURATIONCHANGE;
+ break;
+
+ case TOGGLE_AFR:
+ * action_id_ptr = ACTION_TOGGLE_AFR;
+ CDBG("next_menu_id = MENU_ID_TOGGLEAFR = %d\n", next_menu_id);
+ break;
+
+ case SET_ISO:
+ next_menu_id = MENU_ID_ISOCHANGE;
+ CDBG("next_menu_id = MENU_ID_ISOCHANGE = %d\n", next_menu_id);
+ break;
+
+ case SET_ZOOM:
+ next_menu_id = MENU_ID_ZOOMCHANGE;
+ CDBG("next_menu_id = MENU_ID_ZOOMCHANGE = %d\n", next_menu_id);
+ break;
+
+ case SET_SHARPNESS:
+ next_menu_id = MENU_ID_SHARPNESSCHANGE;
+ CDBG("next_menu_id = MENU_ID_SHARPNESSCHANGE = %d\n", next_menu_id);
+ break;
+#endif
+ case TAKE_YUV_SNAPSHOT:
+ * action_id_ptr = ACTION_TAKE_YUV_SNAPSHOT;
+ CDBG("Taking YUV snapshot\n");
+ break;
+
+ case TAKE_RAW_SNAPSHOT:
+ * action_id_ptr = ACTION_TAKE_RAW_SNAPSHOT;
+ CDBG("Taking RAW snapshot\n");
+ break;
+ case START_RECORDING:
+ *action_id_ptr = ACTION_START_RECORDING;
+ next_menu_id = MENU_ID_RECORD;
+ CDBG("Start recording\n");
+ break;
+ /*case STOP_RECORDING:
+ * action_id_ptr = ACTION_STOP_RECORDING;
+ CDBG("Stop recording\n");
+ break;*/
+ case SWITCH_CAMERA:
+ next_menu_id = MENU_ID_SWITCHCAMERA;
+ CDBG("SWitch Camera\n");
+ break;
+ case TAKE_ZSL_SNAPSHOT:
+ * action_id_ptr = ACTION_TAKE_ZSL_SNAPSHOT;
+ CDBG("Taking ZSL snapshot\n");
+ break;
+ case START_RDI:
+ * action_id_ptr = ACTION_START_RDI;
+ break;
+ case STOP_RDI:
+ * action_id_ptr = ACTION_STOP_RDI;
+ break;
+ default:
+ next_menu_id = MENU_ID_MAIN;
+ CDBG("next_menu_id = MENU_ID_MAIN = %d\n", next_menu_id);
+ break;
+ }
+ break;
+
+ case MENU_ID_PREVIEWVIDEORESOLUTIONCHANGE:
+ printf("MENU_ID_PREVIEWVIDEORESOLUTIONCHANGE\n");
+ * action_id_ptr = ACTION_PREVIEW_VIDEO_RESOLUTION;
+ if (output_to_event > RESOLUTION_PREVIEW_VIDEO_MAX ||
+ output_to_event < RESOLUTION_MIN) {
+ next_menu_id = current_menu_id;
+ }
+ else {
+ next_menu_id = MENU_ID_MAIN;
+ * action_param = output_to_event;
+ }
+ break;
+
+ case MENU_ID_WHITEBALANCECHANGE:
+ printf("MENU_ID_WHITEBALANCECHANGE\n");
+ * action_id_ptr = ACTION_SET_WHITE_BALANCE;
+ if (output_to_event > 0 &&
+ output_to_event <= sizeof(white_balance_tbl)/sizeof(white_balance_tbl[0])) {
+ next_menu_id = MENU_ID_MAIN;
+ * action_param = output_to_event;
+ }
+ else {
+ next_menu_id = current_menu_id;
+ }
+ break;
+
+ case MENU_ID_EXPMETERINGCHANGE:
+ printf("MENU_ID_EXPMETERINGCHANGE\n");
+ * action_id_ptr = ACTION_SET_EXP_METERING;
+ if (output_to_event > 0 &&
+ output_to_event <= sizeof(exp_metering_tbl)/sizeof(exp_metering_tbl[0])) {
+ next_menu_id = MENU_ID_MAIN;
+ * action_param = output_to_event;
+ }
+ else {
+ next_menu_id = current_menu_id;
+ }
+ break;
+
+ case MENU_ID_GET_CTRL_VALUE:
+ printf("MENU_ID_GET_CTRL_VALUE\n");
+ * action_id_ptr = ACTION_GET_CTRL_VALUE;
+ if (output_to_event > 0 &&
+ output_to_event <= sizeof(get_ctrl_tbl)/sizeof(get_ctrl_tbl[0])) {
+ next_menu_id = MENU_ID_MAIN;
+ * action_param = output_to_event;
+ }
+ else {
+ next_menu_id = current_menu_id;
+ }
+ break;
+
+ case MENU_ID_BRIGHTNESSCHANGE:
+ switch (output_to_event) {
+ case INC_BRIGHTNESS:
+ * action_id_ptr = ACTION_BRIGHTNESS_INCREASE;
+ next_menu_id = MENU_ID_MAIN;
+ break;
+
+ case DEC_BRIGHTNESS:
+ * action_id_ptr = ACTION_BRIGHTNESS_DECREASE;
+ next_menu_id = MENU_ID_MAIN;
+ break;
+
+ default:
+ next_menu_id = MENU_ID_BRIGHTNESSCHANGE;
+ break;
+ }
+ break;
+
+ case MENU_ID_CONTRASTCHANGE:
+ switch (output_to_event) {
+ case INC_CONTRAST:
+ * action_id_ptr = ACTION_CONTRAST_INCREASE;
+ next_menu_id = MENU_ID_MAIN;
+ break;
+
+ case DEC_CONTRAST:
+ * action_id_ptr = ACTION_CONTRAST_DECREASE;
+ next_menu_id = MENU_ID_MAIN;
+ break;
+
+ default:
+ next_menu_id = MENU_ID_CONTRASTCHANGE;
+ break;
+ }
+ break;
+
+ case MENU_ID_EVCHANGE:
+ switch (output_to_event) {
+ case INCREASE_EV:
+ * action_id_ptr = ACTION_EV_INCREASE;
+ next_menu_id = MENU_ID_MAIN;
+ break;
+
+ case DECREASE_EV:
+ * action_id_ptr = ACTION_EV_DECREASE;
+ next_menu_id = MENU_ID_MAIN;
+ break;
+
+ default:
+ next_menu_id = MENU_ID_EVCHANGE;
+ break;
+ }
+ break;
+
+ case MENU_ID_SATURATIONCHANGE:
+ switch (output_to_event) {
+ case INC_SATURATION:
+ * action_id_ptr = ACTION_SATURATION_INCREASE;
+ next_menu_id = MENU_ID_MAIN;
+ break;
+
+ case DEC_SATURATION:
+ * action_id_ptr = ACTION_SATURATION_DECREASE;
+ next_menu_id = MENU_ID_MAIN;
+ break;
+
+ default:
+ next_menu_id = MENU_ID_EVCHANGE;
+ break;
+ }
+ break;
+
+ case MENU_ID_ISOCHANGE:
+ printf("MENU_ID_ISOCHANGE\n");
+ * action_id_ptr = ACTION_SET_ISO;
+ if (output_to_event > 0 &&
+ output_to_event <= sizeof(iso_tbl)/sizeof(iso_tbl[0])) {
+ next_menu_id = MENU_ID_MAIN;
+ * action_param = output_to_event;
+ } else {
+ next_menu_id = current_menu_id;
+ }
+ break;
+
+ case MENU_ID_ZOOMCHANGE:
+ * action_id_ptr = ACTION_SET_ZOOM;
+ if (output_to_event > 0 &&
+ output_to_event <= sizeof(zoom_tbl)/sizeof(zoom_tbl[0])) {
+ next_menu_id = MENU_ID_MAIN;
+ * action_param = output_to_event;
+ } else {
+ next_menu_id = current_menu_id;
+ }
+ break;
+
+ case MENU_ID_SHARPNESSCHANGE:
+ switch (output_to_event) {
+ case INC_SHARPNESS:
+ * action_id_ptr = ACTION_SHARPNESS_INCREASE;
+ next_menu_id = MENU_ID_MAIN;
+ break;
+ case DEC_SHARPNESS:
+ * action_id_ptr = ACTION_SHARPNESS_DECREASE;
+ next_menu_id = MENU_ID_MAIN;
+ break;
+ default:
+ next_menu_id = MENU_ID_SHARPNESSCHANGE;
+ break;
+ }
+ break;
+ case MENU_ID_SWITCHCAMERA:
+ * action_id_ptr = ACTION_SWITCH_CAMERA;
+ if (output_to_event >= 0 &&
+ output_to_event <= sizeof(cam_tbl)/sizeof(cam_tbl[0])) {
+ next_menu_id = MENU_ID_MAIN;
+ * action_param = output_to_event;
+ } else {
+ next_menu_id = current_menu_id;
+ }
+ break;
+ case MENU_ID_RECORD:
+ switch (output_to_event) {
+ case LIVE_SNAPSHOT_MENU:
+ * action_id_ptr = ACTION_TAKE_LIVE_SNAPSHOT;
+ next_menu_id = MENU_ID_RECORD;
+ break;
+
+ default:
+ case STOP_RECORDING_MENU:
+ * action_id_ptr = ACTION_STOP_RECORDING;
+ next_menu_id = MENU_ID_MAIN;
+ break;
+ }
+ default:
+ CDBG("menu id is wrong: %d\n", current_menu_id);
+ break;
+ }
+
+ return next_menu_id;
+}
+
+/*===========================================================================
+ * FUNCTION - print_menu_preview_video -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+static void print_menu_preview_video(void) {
+ unsigned int i;
+
+ printf("\n");
+ printf("===========================================\n");
+ printf(" Camera is in preview/video mode now \n");
+ printf("===========================================\n\n");
+
+ char menuNum = 'A';
+ for (i = 0; i < sizeof(camera_main_menu_tbl)/sizeof(camera_main_menu_tbl[0]); i++) {
+ if (i == BASE_OFFSET) {
+ menuNum = '1';
+ }
+
+ printf("%c. %s\n", menuNum, camera_main_menu_tbl[i].menu_name);
+ menuNum++;
+ }
+
+ printf("\nPlease enter your choice: ");
+
+ return;
+}
+
+static void camera_preview_video_resolution_change_tbl(void) {
+ unsigned int i;
+
+ printf("\n");
+ printf("==========================================================\n");
+ printf(" Camera is in preview/video resolution mode \n");
+ printf("==========================================================\n\n");
+
+ char previewVideomenuNum = 'A';
+ for (i = 0; i < sizeof(preview_video_dimension_tbl) /
+ sizeof(preview_video_dimension_tbl[0]); i++) {
+ printf("%c. %s\n", previewVideomenuNum,
+ preview_video_dimension_tbl[i].str_name);
+ previewVideomenuNum++;
+ }
+
+ printf("\nPlease enter your choice for Preview/Video Resolution: ");
+ return;
+}
+
+static void camera_preview_video_wb_change_tbl(void) {
+ unsigned int i;
+ printf("\n");
+ printf("==========================================================\n");
+ printf(" Camera is in white balance change mode \n");
+ printf("==========================================================\n\n");
+
+ char submenuNum = 'A';
+ for (i = 0 ; i < sizeof(white_balance_tbl) /
+ sizeof(white_balance_tbl[0]); i++) {
+ //printf("%c. %s\n", submenuNum, white_balance_tbl[i].wb_name);
+ submenuNum++;
+ }
+ printf("\nPlease enter your choice for White Balance modes: ");
+ return;
+}
+
+static void camera_preview_video_get_ctrl_value_tbl(void) {
+ unsigned int i;
+ printf("\n");
+ printf("==========================================================\n");
+ printf(" Camera is in get control value mode \n");
+ printf("==========================================================\n\n");
+
+ char submenuNum = 'A';
+ for (i = 0 ; i < sizeof(get_ctrl_tbl) /
+ sizeof(get_ctrl_tbl[0]); i++) {
+ printf("%c. %s\n", submenuNum, get_ctrl_tbl[i].get_ctrl_name);
+ submenuNum++;
+ }
+ printf("\nPlease enter your choice for control value you want to get: ");
+ return;
+}
+
+static void camera_preview_video_exp_metering_change_tbl(void) {
+ unsigned int i;
+ printf("\n");
+ printf("==========================================================\n");
+ printf(" Camera is in exposure metering change mode \n");
+ printf("==========================================================\n\n");
+
+ char submenuNum = 'A';
+ for (i = 0 ; i < sizeof(exp_metering_tbl) /
+ sizeof(exp_metering_tbl[0]); i++) {
+ printf("%c. %s\n", submenuNum, exp_metering_tbl[i].exp_metering_name);
+ submenuNum++;
+ }
+ printf("\nPlease enter your choice for exposure metering modes: ");
+ return;
+}
+
+static void camera_contrast_change_tbl(void) {
+ unsigned int i;
+
+ printf("\n");
+ printf("==========================================================\n");
+ printf(" Camera is in change contrast resolution mode \n");
+ printf("==========================================================\n\n");
+
+ char contrastmenuNum = 'A';
+ for (i = 0; i < sizeof(contrast_change_tbl) /
+ sizeof(contrast_change_tbl[0]); i++) {
+ printf("%c. %s\n", contrastmenuNum,
+ contrast_change_tbl[i].contrast_name);
+ contrastmenuNum++;
+ }
+
+ printf("\nPlease enter your choice for contrast Change: ");
+ return;
+}
+
+static void camera_EV_change_tbl(void) {
+ unsigned int i;
+
+ printf("\n");
+ printf("===========================================\n");
+ printf(" Camera is in EV change mode now \n");
+ printf("===========================================\n\n");
+
+ char submenuNum = 'A';
+ for (i = 0; i < sizeof(camera_EV_tbl)/sizeof(camera_EV_tbl[0]); i++) {
+ printf("%c. %s\n", submenuNum, camera_EV_tbl[i].EV_name);
+ submenuNum++;
+ }
+
+ printf("\nPlease enter your choice for EV changes: ");
+ return;
+}
+
+static void camera_preview_video_zoom_change_tbl(void) {
+ unsigned int i;
+ struct v4l2_control ctrl;
+
+ memset(&ctrl, 0, sizeof(ctrl));
+ ctrl.id = V4L2_CID_ZOOM_ABSOLUTE;
+#if 0 /* TBD */
+ if (ioctl(camfd, VIDIOC_G_CTRL, &ctrl) >= 0) {
+ zoom_level = ctrl.value;
+ printf("\n");
+ printf("==========================================================\n");
+ printf(" Camera is in zoom change mode: %d, [%d..%d] \n",
+ ctrl.value, zoom_queryctrl.minimum, zoom_queryctrl.maximum);
+ printf("==========================================================\n\n");
+
+ char submenuNum = 'A';
+ for (i = 0 ; i < sizeof(zoom_tbl) /
+ sizeof(zoom_tbl[0]); i++) {
+ printf("%c. %s\n", submenuNum, zoom_tbl[i].zoom_direction_name);
+ submenuNum++;
+ }
+ printf("\nPlease enter your choice for zoom change direction: ");
+ } else {
+ printf("\nVIDIOC_G_CTRL error: %d\n", errno);
+ }
+#endif /* TBD */
+ return;
+}
+
+static void camera_brightness_change_tbl(void) {
+ unsigned int i;
+
+ printf("\n");
+ printf("==========================================================\n");
+ printf(" Camera is in change brightness mode \n");
+ printf("==========================================================\n\n");
+
+ char brightnessmenuNum = 'A';
+ for (i = 0; i < sizeof(brightness_change_tbl) /
+ sizeof(brightness_change_tbl[0]); i++) {
+ printf("%c. %s\n", brightnessmenuNum,
+ brightness_change_tbl[i].brightness_name);
+ brightnessmenuNum++;
+ }
+
+ printf("\nPlease enter your choice for Brightness Change: ");
+ return;
+}
+
+static void camera_saturation_change_tbl(void) {
+ unsigned int i;
+
+ printf("\n");
+ printf("==========================================================\n");
+ printf(" Camera is in change saturation mode \n");
+ printf("==========================================================\n\n");
+
+ char saturationmenuNum = 'A';
+ for (i = 0; i < sizeof(camera_saturation_tbl) /
+ sizeof(camera_saturation_tbl[0]); i++) {
+ printf("%c. %s\n", saturationmenuNum,
+ camera_saturation_tbl[i].saturation_name);
+ saturationmenuNum++;
+ }
+
+ printf("\nPlease enter your choice for Saturation Change: ");
+ return;
+}
+
+char * set_preview_video_dimension_tbl(Camera_Resolution cs_id, uint16_t * width, uint16_t * height)
+{
+ unsigned int i;
+ char * ptr = NULL;
+ for (i = 0; i < sizeof(preview_video_dimension_tbl) /
+ sizeof(preview_video_dimension_tbl[0]); i++) {
+ if (cs_id == preview_video_dimension_tbl[i].cs_id) {
+ *width = preview_video_dimension_tbl[i].width;
+ *height = preview_video_dimension_tbl[i].height;
+ ptr = preview_video_dimension_tbl[i].name;
+ break;
+ }
+ }
+ return ptr;
+}
+
+static void camera_preview_video_iso_change_tbl(void) {
+ unsigned int i;
+ printf("\n");
+ printf("==========================================================\n");
+ printf(" Camera is in ISO change mode \n");
+ printf("==========================================================\n\n");
+
+ char submenuNum = 'A';
+ for (i = 0 ; i < sizeof(iso_tbl) /
+ sizeof(iso_tbl[0]); i++) {
+ printf("%c. %s\n", submenuNum, iso_tbl[i].iso_modes_name);
+ submenuNum++;
+ }
+ printf("\nPlease enter your choice for iso modes: ");
+ return;
+}
+
+static void camera_preview_video_sharpness_change_tbl(void) {
+ unsigned int i;
+ printf("\n");
+ printf("==========================================================\n");
+ printf(" Camera is in sharpness change mode \n");
+ printf("==========================================================\n\n");
+
+ char submenuNum = 'A';
+ for (i = 0 ; i < sizeof(camera_sharpness_tbl) /
+ sizeof(camera_sharpness_tbl[0]); i++) {
+ printf("%c. %s\n", submenuNum, camera_sharpness_tbl[i].sharpness_name);
+ submenuNum++;
+ }
+ printf("\nPlease enter your choice for sharpness modes: ");
+ return;
+}
+
+static void camera_record_tbl(void) {
+ unsigned int i;
+ printf("\n");
+ printf("==========================================================\n");
+ printf(" Camera is in record mode \n");
+ printf("==========================================================\n\n");
+
+ char submenuNum = 'A';
+ for (i = 0 ; i < sizeof(record_tbl) /
+ sizeof(record_tbl[0]); i++) {
+ printf("%c. %s\n", submenuNum, record_tbl[i].act_name);
+ submenuNum++;
+ }
+ printf("\nPlease enter your choice: ");
+ return;
+}
+
+static void camera_switch_tbl(void) {
+ unsigned int i;
+ printf("\n");
+ printf("==========================================================\n");
+ printf(" Camera is in switch camera mode \n");
+ printf("==========================================================\n\n");
+
+ char submenuNum = 'A';
+ for (i = 0 ; i < sizeof(cam_tbl) /
+ sizeof(cam_tbl[0]); i++) {
+ printf("%c. %s\n", submenuNum, cam_tbl[i].cam_name);
+ submenuNum++;
+ }
+ printf("\nPlease enter your choice for camera modes: ");
+ return;
+}
+/*===========================================================================
+ * FUNCTION - increase_contrast -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+int increase_contrast (void) {
+ ++contrast;
+ if (contrast > CAMERA_MAX_CONTRAST) {
+ contrast = CAMERA_MAX_CONTRAST;
+ printf("Reached max CONTRAST. \n");
+ } else
+ printf("Increase CONTRAST to %d\n", contrast);
+
+ /*intrfcCtrl.setContrast(camfd, contrast);*/
+
+ struct v4l2_queryctrl queryctrl;
+ struct v4l2_control control;
+
+ memset (&queryctrl, 0, sizeof (queryctrl));
+ queryctrl.id = V4L2_CID_CONTRAST;
+#if 0 /* TBD */
+ if (-1 == ioctl (camfd, VIDIOC_QUERYCTRL, &queryctrl)) {
+ if (errno != EINVAL) {
+ perror ("VIDIOC_QUERYCTRL");
+ exit (EXIT_FAILURE);
+ } else {
+ printf ("V4L2_CID_contrast is not supported\n");
+ }
+ } else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
+ printf ("V4L2_CID_contrast is not supported\n");
+ } else {
+ memset (&control, 0, sizeof (control));
+ control.id = V4L2_CID_CONTRAST;
+ /* Decreasing the contrast */
+ control.value = contrast;
+
+ // if (-1 == ioctl (camfd, VIDIOC_S_CTRL, &control)) {
+ // perror ("VIDIOC_S_CTRL");
+ // return -1;
+ // }
+ }
+#endif /* TBD */
+ return 0;
+}
+
+/*===========================================================================
+ * FUNCTION - decrease_contrast -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+int decrease_contrast (void) {
+ --contrast;
+ if (contrast < CAMERA_MIN_CONTRAST) {
+ contrast = CAMERA_MIN_CONTRAST;
+ printf("Reached min CONTRAST. \n");
+ } else
+ printf("Decrease CONTRAST to %d\n", contrast);
+
+ /*intrfcCtrl.setContrast(camfd, contrast);*/
+ struct v4l2_queryctrl queryctrl;
+ struct v4l2_control control;
+
+ memset (&queryctrl, 0, sizeof (queryctrl));
+ queryctrl.id = V4L2_CID_CONTRAST;
+#if 0 /* TBD */
+ if (-1 == ioctl (camfd, VIDIOC_QUERYCTRL, &queryctrl)) {
+ if (errno != EINVAL) {
+ perror ("VIDIOC_QUERYCTRL");
+ exit (EXIT_FAILURE);
+ } else {
+ printf ("V4L2_CID_contrast is not supported\n");
+ }
+ } else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
+ printf ("V4L2_CID_contrast is not supported\n");
+ } else {
+ memset (&control, 0, sizeof (control));
+ control.id = V4L2_CID_CONTRAST;
+ /* Decreasing the contrast */
+ control.value = contrast;
+
+ // if (-1 == ioctl (camfd, VIDIOC_S_CTRL, &control)) {
+ // perror ("VIDIOC_S_CTRL");
+ // return -1;
+ // }
+ }
+#endif /* TBD */
+ return 0;
+}
+
+/*===========================================================================
+ * FUNCTION - decrease_brightness -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+int decrease_brightness (void) {
+ brightness -= CAMERA_BRIGHTNESS_STEP;
+ if (brightness < CAMERA_MIN_BRIGHTNESS) {
+ brightness = CAMERA_MIN_BRIGHTNESS;
+ printf("Reached min BRIGHTNESS. \n");
+ } else
+ printf("Decrease BRIGHTNESS to %d\n", brightness);
+
+ struct v4l2_queryctrl queryctrl;
+ struct v4l2_control control;
+
+ memset (&queryctrl, 0, sizeof (queryctrl));
+ queryctrl.id = V4L2_CID_BRIGHTNESS;
+#if 0 /* TBD */
+ if (-1 == ioctl (camfd, VIDIOC_QUERYCTRL, &queryctrl)) {
+ if (errno != EINVAL) {
+ perror ("VIDIOC_QUERYCTRL");
+ exit (EXIT_FAILURE);
+ } else {
+ printf ("V4L2_CID_BRIGHTNESS is not supported\n");
+ }
+ } else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
+ printf ("V4L2_CID_BRIGHTNESS is not supported\n");
+ } else {
+ memset (&control, 0, sizeof (control));
+ control.id = V4L2_CID_BRIGHTNESS;
+ /* Decreasing the Brightness */
+ control.value = brightness;
+
+ if (-1 == ioctl (camfd, VIDIOC_S_CTRL, &control)) {
+ perror ("VIDIOC_S_CTRL");
+ return -1;
+ }
+ }
+#endif /* TBD */
+ return 0;
+}
+
+/*===========================================================================
+ * FUNCTION - increase_brightness -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+int increase_brightness (void) {
+ brightness += CAMERA_BRIGHTNESS_STEP;
+ if (brightness > CAMERA_MAX_BRIGHTNESS) {
+ brightness = CAMERA_MAX_BRIGHTNESS;
+ printf("Reached max BRIGHTNESS. \n");
+ } else
+ printf("Increase BRIGHTNESS to %d\n", brightness);
+
+ struct v4l2_queryctrl queryctrl;
+ struct v4l2_control control;
+
+ memset (&queryctrl, 0, sizeof (queryctrl));
+ queryctrl.id = V4L2_CID_BRIGHTNESS;
+#if 0 /* TBD */
+ if (-1 == ioctl (camfd, VIDIOC_QUERYCTRL, &queryctrl)) {
+ if (errno != EINVAL) {
+ perror ("VIDIOC_QUERYCTRL");
+ exit (EXIT_FAILURE);
+ } else {
+ printf ("V4L2_CID_BRIGHTNESS is not supported\n");
+ }
+ } else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
+ printf ("V4L2_CID_BRIGHTNESS is not supported\n");
+ } else {
+ memset (&control, 0, sizeof (control));
+ control.id = V4L2_CID_BRIGHTNESS;
+ /* Increasing the Brightness */
+ control.value = brightness;
+
+ if (-1 == ioctl (camfd, VIDIOC_S_CTRL, &control)) {
+ perror ("VIDIOC_S_CTRL");
+ return -1;
+ }
+ }
+#endif /* TBD */
+ return 0;
+}
+
+/*===========================================================================
+ * FUNCTION - increase_EV -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+int increase_EV (void) {
+ int32_t ev = 0;
+ if (++ev_num <= 12) {
+ ev = (ev_num << 16) | 6;
+ printf("Increase EV to %d\n", ev_num);
+ } else {
+ printf("Reached max EV. \n");
+ ev = ev_num;
+ }
+
+ struct v4l2_queryctrl queryctrl;
+ struct v4l2_control control;
+
+ memset (&queryctrl, 0, sizeof (queryctrl));
+ queryctrl.id = V4L2_CID_EXPOSURE;
+#if 0 /* TBD */
+ if (-1 == ioctl (camfd, VIDIOC_QUERYCTRL, &queryctrl)) {
+ if (errno != EINVAL) {
+ perror ("VIDIOC_QUERYCTRL");
+ exit (EXIT_FAILURE);
+ } else {
+ printf ("V4L2_CID_EXPOSURE is not supported\n");
+ }
+ } else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
+ printf ("V4L2_CID_EXPOSURE is not supported\n");
+ } else {
+ memset (&control, 0, sizeof (control));
+ control.id = V4L2_CID_EXPOSURE;
+ /* Increasing the EV*/
+ control.value = ev;
+
+ if (-1 == ioctl (camfd, VIDIOC_S_CTRL, &control)) {
+ perror ("VIDIOC_S_CTRL");
+ return -1;
+ }
+ }
+#endif /* TBD */
+ return 0;
+}
+
+/*===========================================================================
+ * FUNCTION - decrease_EV -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+int decrease_EV (void) {
+ int32_t ev = 0;
+ if (--ev_num > -12) {
+ ev = (ev_num << 16) | 6;
+ printf("Decrease EV to %d\n", ev_num);
+ } else {
+ printf("Reached min EV. \n");
+ ev = ev_num;
+ }
+
+ struct v4l2_queryctrl queryctrl;
+ struct v4l2_control control;
+
+ memset (&queryctrl, 0, sizeof (queryctrl));
+ queryctrl.id = V4L2_CID_EXPOSURE;
+#if 0 /* TBD */
+ if (-1 == ioctl (camfd, VIDIOC_QUERYCTRL, &queryctrl)) {
+ if (errno != EINVAL) {
+ perror ("VIDIOC_QUERYCTRL");
+ exit (EXIT_FAILURE);
+ } else {
+ printf ("V4L2_CID_EXPOSURE is not supported\n");
+ }
+ } else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
+ printf ("V4L2_CID_EXPOSURE is not supported\n");
+ } else {
+ memset (&control, 0, sizeof (control));
+ control.id = V4L2_CID_EXPOSURE;
+ /* Increasing the EV*/
+ control.value = ev;
+
+ if (-1 == ioctl (camfd, VIDIOC_S_CTRL, &control)) {
+ perror ("VIDIOC_S_CTRL");
+ return -1;
+ }
+ }
+#endif /* TBD */
+ return 0;
+}
+
+/*===========================================================================
+ * FUNCTION - increase_contrast -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+int increase_saturation (void) {
+ ++saturation;
+ if (saturation > CAMERA_MAX_SATURATION) {
+ saturation = CAMERA_MAX_SATURATION;
+ printf("Reached max saturation. \n");
+ } else
+ printf("Increase saturation to %d\n", saturation);
+
+ /*intrfcCtrl.setContrast(camfd, contrast);*/
+
+ struct v4l2_queryctrl queryctrl;
+ struct v4l2_control control;
+
+ memset (&queryctrl, 0, sizeof (queryctrl));
+ queryctrl.id = V4L2_CID_SATURATION;
+#if 0 /* TBD */
+ if (-1 == ioctl (camfd, VIDIOC_QUERYCTRL, &queryctrl)) {
+ if (errno != EINVAL) {
+ perror ("VIDIOC_QUERYCTRL");
+ exit (EXIT_FAILURE);
+ } else {
+ printf ("V4L2_CID_saturation is not supported\n");
+ }
+ } else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
+ printf ("V4L2_CID_saturation is not supported\n");
+ } else {
+ memset (&control, 0, sizeof (control));
+ control.id = V4L2_CID_SATURATION;
+ /* Decreasing the contrast */
+ control.value = saturation;
+
+ if (-1 == ioctl (camfd, VIDIOC_S_CTRL, &control)) {
+ perror ("VIDIOC_S_CTRL");
+ return -1;
+ }
+ }
+#endif /* TBD */
+ return 0;
+}
+
+/*===========================================================================
+ * FUNCTION - decrease_saturation -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+int decrease_saturation (void) {
+ --saturation;
+ if (saturation < CAMERA_MIN_SATURATION) {
+ saturation = CAMERA_MIN_SATURATION;
+ printf("Reached min saturation. \n");
+ } else
+ printf("Decrease saturation to %d\n", saturation);
+
+ /*intrfcCtrl.setContrast(camfd, contrast);*/
+ struct v4l2_queryctrl queryctrl;
+ struct v4l2_control control;
+
+ memset (&queryctrl, 0, sizeof (queryctrl));
+ queryctrl.id = V4L2_CID_SATURATION;
+#if 0 /* TBD */
+ if (-1 == ioctl (camfd, VIDIOC_QUERYCTRL, &queryctrl)) {
+ if (errno != EINVAL) {
+ perror ("VIDIOC_QUERYCTRL");
+ exit (EXIT_FAILURE);
+ } else {
+ printf ("V4L2_CID_saturation is not supported\n");
+ }
+ } else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
+ printf ("V4L2_CID_saturation is not supported\n");
+ } else {
+ memset (&control, 0, sizeof (control));
+ control.id = V4L2_CID_SATURATION;
+ /* Decreasing the contrast */
+ control.value = saturation;
+
+ if (-1 == ioctl (camfd, VIDIOC_S_CTRL, &control)) {
+ perror ("VIDIOC_S_CTRL");
+ return -1;
+ }
+ }
+#endif /* TBD */
+ return 0;
+}
+
+int takePicture_yuv(int cam_id)
+{
+ int rc = 0;
+ CDBG("%s:BEGIN\n", __func__);
+ if(0 != (rc = mm_app_take_picture(cam_id))) {
+ CDBG_ERROR("%s: mm_app_take_picture() err=%d\n", __func__, rc);
+ }
+ return rc;
+}
+
+int takePicture_zsl(int cam_id)
+{
+ int rc = 0;
+ CDBG("%s:BEGIN\n", __func__);
+ if(0 != (rc = mm_app_take_zsl(cam_id))) {
+ CDBG_ERROR("%s: mm_app_take_picture() err=%d\n", __func__, rc);
+ }
+ return rc;
+}
+
+int takePicture_live(int cam_id)
+{
+ int rc = 0;
+ CDBG("%s:BEGIN\n", __func__);
+ if(0 != (rc = mm_app_take_live_snapshot(cam_id))) {
+ CDBG_ERROR("%s: mm_app_take_picture() err=%d\n", __func__, rc);
+ }
+ return rc;
+}
+
+int takePicture_raw(int cam_id)
+{
+ int rc = 0;
+ CDBG("%s:BEGIN\n", __func__);
+ if(0 != (rc = mm_app_take_raw_picture(cam_id))) {
+ CDBG("%s: mm_app_take_raw_picture() err=%d\n", __func__, rc);
+ }
+ return rc;
+}
+int system_dimension_set(int cam_id)
+{
+ static cam_ctrl_dimension_t dim;
+ int rc = 0;
+
+ if (preview_video_resolution_flag == 0) {
+ mm_app_set_dim_def(&dim);
+ } else {
+ dim.video_width = input_display.user_input_display_width;
+ dim.video_width = CEILING32(dim.video_width);
+ dim.video_height = input_display.user_input_display_height;
+ dim.orig_video_width = dim.video_width;
+ dim.orig_video_height = dim.video_height;
+ dim.display_width = dim.video_width;
+ dim.display_height = dim.video_height;
+ }
+ rc = mm_app_set_dim(cam_id, &dim);
+ return rc;
+}
+
+/*int run_test_harness()
+{
+ int good_test_cnt = 0;
+
+ rc = run_test_1();
+ if(rc < 0)
+ CDBG_EROR("%s: run_test_1 err = %d", __func__, rc);
+ rc = run_test_2();
+}*/
+/*===========================================================================
+ * FUNCTION - main -
+ *
+ * DESCRIPTION:
+ *==========================================================================*/
+int main(int argc, char **argv)
+{
+ int keep_on_going = 1;
+ int c, rc = 0, tmp_fd;
+ int run_tc = 0;
+ int run_dual_tc = 0;
+ struct v4l2_capability v4l2_cap;
+
+ /* get v4l2 params - memory type etc */
+ while ((c = getopt(argc, argv, "tdh")) != -1) {
+ //printf("usage: %s [-m] [-u] [-o]\n", argv[1]);
+ switch (c) {
+#if 0
+ case 'm':
+ memoryType = V4L2_MEMORY_MMAP;
+ break;
+
+ case 'o':
+ /*use_overlay_fb_display_driver();*/
+ break;
+ case 'u':
+ memoryType = V4L2_MEMORY_USERPTR;
+ break;
+#endif
+ case 't':
+ run_tc = 1;
+ break;
+ case 'd':
+ run_dual_tc = 1;
+ break;
+ case 'h':
+ default:
+ printf("usage: %s [-m] [-u] [-o]\n", argv[0]);
+ printf("-m: V4L2_MEMORY_MMAP. \n");
+ printf("-o: use overlay fb display driver\n");
+ printf("-u: V4L2_MEMORY_USERPTR\n");
+ exit(0);
+ }
+ }
+
+ CDBG("\nCamera Test Application\n");
+
+ struct timeval tdBeforePreviewVideo, tdStopCamera;
+ struct timezone tz;
+
+ //return run_test_harness();
+ if((rc = mm_app_load_hal())) {
+ CDBG_ERROR("%s:mm_app_init err=%d\n", __func__, rc);
+ exit(-1);
+ }
+ /* we must init mm_app first */
+ if(mm_app_init() != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_init err=%d\n", __func__, rc);
+ exit(-1);
+ }
+
+ if(run_tc) {
+ printf("\tRunning unit test engine only\n");
+ rc = mm_app_unit_test();
+ printf("\tUnit test engine. EXIT(%d)!!!\n", rc);
+ exit(rc);
+ }
+
+ if(run_dual_tc) {
+ printf("\tRunning Dual camera test engine only\n");
+ rc = mm_app_dual_test();
+ printf("\t Dual camera engine. EXIT(%d)!!!\n", rc);
+ exit(rc);
+ }
+
+ gettimeofday(&tdBeforePreviewVideo, &tz);
+
+ CDBG("Profiling: Start Camera timestamp = %ld ms\n",
+ (tdBeforePreviewVideo.tv_sec * 1000) + (tdBeforePreviewVideo.tv_usec/1000));
+
+ /* launch the primary camera in default mode */
+ if( mm_app_open(CAMERA_OPENED)) {
+ CDBG_ERROR("%s:mm_app_open() err=%d\n",__func__, rc);
+ exit(-2);
+ }
+
+ /* main loop doing the work*/
+ do {
+ keep_on_going = submain();
+ } while ( keep_on_going );
+
+ /* Clean up and exit. */
+ CDBG("Exiting the app\n");
+
+error_ionfd_open:
+ mm_app_close(CAMERA_OPENED);
+
+ gettimeofday(&tdStopCamera, &tz);
+ CDBG("Exiting application\n");
+ CDBG("Profiling: Stop camera end timestamp = %ld ms\n",
+ (tdStopCamera.tv_sec * 1000) + (tdStopCamera.tv_usec/1000));
+
+ return 0;
+}
+
+
+/*===========================================================================
+ * FUNCTION - submain -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+static int submain()
+{
+ int rc = 0;
+ int back_mainflag = 0;
+ char tc_buf[3];
+ int stop_preview = 1;
+ menu_id_change_t current_menu_id = MENU_ID_MAIN, next_menu_id;
+ camera_action_t action_id;
+ int action_param;
+ int i;
+ int cam_id;
+
+ CDBG("%s:E", __func__);
+ struct timeval tdStopCamera;
+ struct timezone tz;
+
+ cam_id = my_cam_app.cam_open;
+
+ rc = system_dimension_set(cam_id);
+ CDBG("Start Preview");
+ if( 0 != (rc = startPreview(cam_id))) {
+ CDBG("%s: startPreview() err=%d\n", __func__, rc);
+ return 0;
+ }
+
+ do {
+ print_current_menu (current_menu_id);
+ fgets(tc_buf, 3, stdin);
+
+ next_menu_id = next_menu(current_menu_id, tc_buf[0], &action_id, &action_param);
+
+ if (next_menu_id != MENU_ID_INVALID) {
+ current_menu_id = next_menu_id;
+ }
+ if (action_id == ACTION_NO_ACTION) {
+ continue;
+ }
+ if(camframe_status == -1) {
+ printf("Preview/Video ERROR condition reported Closing Camera APP\n");
+ break;
+ }
+
+ switch(action_id) {
+ case ACTION_STOP_CAMERA:
+ CDBG("ACTION_STOP_CAMERA \n");
+ stopPreview(cam_id);
+ break;
+
+ case ACTION_PREVIEW_VIDEO_RESOLUTION:
+ back_mainflag = 1;
+ CDBG("Selection for the preview/video resolution change\n");
+ switchRes(cam_id);
+ preview_video_resolution (action_param);
+ break;
+ case ACTION_SET_WHITE_BALANCE:
+ CDBG("Selection for the White Balance changes\n");
+ set_whitebalance(action_param);
+ break;
+
+ case ACTION_SET_EXP_METERING:
+ CDBG("Selection for the Exposure Metering changes\n");
+ set_exp_metering(action_param);
+ break;
+
+ case ACTION_GET_CTRL_VALUE:
+ CDBG("Selection for getting control value\n");
+ get_ctrl_value(action_param);
+ break;
+
+ case ACTION_BRIGHTNESS_INCREASE:
+ printf("Increase brightness\n");
+ increase_brightness();
+ break;
+
+ case ACTION_BRIGHTNESS_DECREASE:
+ printf("Decrease brightness\n");
+ decrease_brightness();
+ break;
+
+ case ACTION_CONTRAST_INCREASE:
+ CDBG("Selection for the contrast increase\n");
+ increase_contrast ();
+ break;
+
+ case ACTION_CONTRAST_DECREASE:
+ CDBG("Selection for the contrast decrease\n");
+ decrease_contrast ();
+ break;
+
+ case ACTION_EV_INCREASE:
+ CDBG("Selection for the EV increase\n");
+ increase_EV ();
+ break;
+
+ case ACTION_EV_DECREASE:
+ CDBG("Selection for the EV decrease\n");
+ decrease_EV ();
+ break;
+
+ case ACTION_SATURATION_INCREASE:
+ CDBG("Selection for the EV increase\n");
+ increase_saturation ();
+ break;
+
+ case ACTION_SATURATION_DECREASE:
+ CDBG("Selection for the EV decrease\n");
+ decrease_saturation ();
+ break;
+
+ case ACTION_TOGGLE_AFR:
+ CDBG("Select for auto frame rate toggling\n");
+ toggle_afr();
+ break;
+
+ case ACTION_SET_ISO:
+ CDBG("Select for ISO changes\n");
+ set_iso(action_param);
+ break;
+
+ case ACTION_SET_ZOOM:
+ CDBG("Selection for the zoom direction changes\n");
+ set_zoom(action_param);
+ break;
+
+ case ACTION_SHARPNESS_INCREASE:
+ CDBG("Selection for sharpness increase\n");
+ increase_sharpness();
+ break;
+
+ case ACTION_SHARPNESS_DECREASE:
+ CDBG("Selection for sharpness decrease\n");
+ decrease_sharpness();
+ break;
+
+ case ACTION_TAKE_YUV_SNAPSHOT:
+ CDBG("Take YUV snapshot\n");
+ if (takePicture_yuv(cam_id) < 0)
+ goto ERROR;
+ break;
+ case ACTION_TAKE_RAW_SNAPSHOT:
+ CDBG("Take YUV snapshot\n");
+ if (takePicture_raw(cam_id) < 0)
+ goto ERROR;
+ break;
+ case ACTION_START_RECORDING:
+ CDBG("Start recording action\n");
+ if (startRecording(cam_id) < 0)
+ goto ERROR;
+ break;
+ case ACTION_STOP_RECORDING:
+ CDBG("Stop recording action\n");
+ if (stopRecording(cam_id) < 0)
+ goto ERROR;
+ break;
+ case ACTION_NO_ACTION:
+ printf("Go back to main menu");
+ break;
+ case ACTION_SWITCH_CAMERA:
+ CDBG("Toggle Camera action\n");
+ back_mainflag = 1;
+ if (switchCamera(action_param - 1) < 0)
+ goto ERROR;
+ break;
+
+ case ACTION_TAKE_ZSL_SNAPSHOT:
+ CDBG("Take ZSL snapshot\n");
+ if (takePicture_zsl(cam_id) < 0)
+ {
+ CDBG("Error");
+ goto ERROR;
+ }
+ break;
+ case ACTION_START_RDI:
+ CDBG("Start RDI Stream\n");
+ startRdi(cam_id);
+ break;
+ case ACTION_STOP_RDI:
+ CDBG("Stop RDI Stream\n");
+ stopRdi(cam_id);
+ break;
+ case ACTION_TAKE_LIVE_SNAPSHOT:
+ CDBG("Take Live snapshot\n");
+ if (takePicture_live(cam_id) < 0)
+ {
+ CDBG("Error");
+ goto ERROR;
+ }
+ break;
+
+ default:
+ printf("\n\n!!!!!WRONG INPUT: %d!!!!\n", action_id);
+ break;
+ }
+
+ usleep(1000 * 1000);
+ CDBG("action_id = %d\n", action_id);
+ camframe_status = 0;
+
+ } while ((action_id != ACTION_STOP_CAMERA) &&
+ (action_id != ACTION_PREVIEW_VIDEO_RESOLUTION) && (action_id !=ACTION_SWITCH_CAMERA));
+ action_id = ACTION_NO_ACTION;
+
+ //system_destroy();
+
+
+ return back_mainflag;
+
+ERROR:
+ back_mainflag = 0;
+ return back_mainflag;
+}
+
+
+/*===========================================================================
+ * FUNCTION - preview_resolution -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+int preview_video_resolution (int preview_video_action_param) {
+ char * resolution_name;
+ CDBG("Selecting the action for preview/video resolution = %d \n", preview_video_action_param);
+ resolution_name = set_preview_video_dimension_tbl(preview_video_action_param,
+ & input_display.user_input_display_width,
+ & input_display.user_input_display_height);
+
+ CDBG("Selected preview/video resolution is %s\n", resolution_name);
+
+ if (resolution_name == NULL) {
+ CDBG("main:%d set_preview_dimension failed!\n", __LINE__);
+ goto ERROR;
+ }
+
+ CDBG("Selected Preview Resolution: display_width = %d, display_height = %d\n",
+ input_display.user_input_display_width, input_display.user_input_display_height);
+
+ preview_video_resolution_flag = 1;
+ return 0;
+
+ERROR:
+ return -1;
+}
+
+/*===========================================================================
+ * FUNCTION - set_whitebalance -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+int set_whitebalance (int wb_action_param) {
+
+ int rc = 0;
+ struct v4l2_control ctrl;
+
+ if (wb_action_param == MM_CAMERA_WHITE_BALANCE_AUTO) {
+ ctrl.id = V4L2_CID_AUTO_WHITE_BALANCE;
+ ctrl.value = TRUE;
+ // rc = ioctl(camfd, VIDIOC_S_CTRL, &ctrl);
+
+ } else if ( wb_action_param == MM_CAMERA_WHITE_BALANCE_OFF) {
+ ctrl.id = V4L2_CID_AUTO_WHITE_BALANCE;
+ ctrl.value = FALSE;
+ // rc = ioctl(camfd, VIDIOC_S_CTRL, &ctrl);
+
+ } else {
+ int temperature = 6500;
+
+ switch (wb_action_param) {
+ case MM_CAMERA_WHITE_BALANCE_DAYLIGHT:
+ temperature = 6500;
+ break;
+ case MM_CAMERA_WHITE_BALANCE_INCANDESCENT:
+ temperature = 2800;
+ break;
+ case MM_CAMERA_WHITE_BALANCE_FLUORESCENT:
+ temperature = 4200;
+ break;
+ default:
+ temperature = 4200;
+ break;
+ }
+
+ ctrl.id = V4L2_CID_WHITE_BALANCE_TEMPERATURE;
+ ctrl.value = temperature;
+ // rc = ioctl(camfd, VIDIOC_S_CTRL, &ctrl);
+ }
+
+DONE:
+ return rc;
+}
+
+
+/*===========================================================================
+ * FUNCTION - set_exp_metering -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+int set_exp_metering (int exp_metering_action_param) {
+
+ int rc = 0;
+ struct v4l2_control ctrl;
+
+ ctrl.id = MSM_V4L2_PID_EXP_METERING;
+ ctrl.value = exp_metering_action_param;
+ // rc = ioctl(camfd, VIDIOC_S_CTRL, &ctrl);
+
+ return rc;
+}
+
+int get_ctrl_value (int ctrl_value_mode_param){
+
+ int rc = 0;
+ struct v4l2_control ctrl;
+
+ if (ctrl_value_mode_param == WHITE_BALANCE_STATE) {
+ printf("You chose WHITE_BALANCE_STATE\n");
+ ctrl.id = V4L2_CID_AUTO_WHITE_BALANCE;
+ }
+ else if (ctrl_value_mode_param == WHITE_BALANCE_TEMPERATURE) {
+ printf("You chose WHITE_BALANCE_TEMPERATURE\n");
+ ctrl.id = V4L2_CID_WHITE_BALANCE_TEMPERATURE;
+ }
+ else if (ctrl_value_mode_param == BRIGHTNESS_CTRL) {
+ printf("You chose brightness value\n");
+ ctrl.id = V4L2_CID_BRIGHTNESS;
+ }
+ else if (ctrl_value_mode_param == EV) {
+ printf("You chose exposure value\n");
+ ctrl.id = V4L2_CID_EXPOSURE;
+ }
+ else if (ctrl_value_mode_param == CONTRAST_CTRL) {
+ printf("You chose contrast value\n");
+ ctrl.id = V4L2_CID_CONTRAST;
+ }
+ else if (ctrl_value_mode_param == SATURATION_CTRL) {
+ printf("You chose saturation value\n");
+ ctrl.id = V4L2_CID_SATURATION;
+ } else if (ctrl_value_mode_param == SHARPNESS_CTRL) {
+ printf("You chose sharpness value\n");
+ ctrl.id = V4L2_CID_SHARPNESS;
+ }
+
+ // rc = ioctl(camfd, VIDIOC_G_CTRL, &ctrl);
+
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION - toggle_afr -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+int toggle_afr () {
+ int rc = 0;
+ struct v4l2_control ctrl;
+
+ memset(&ctrl, 0, sizeof(ctrl));
+ ctrl.id = V4L2_CID_EXPOSURE_AUTO;
+// rc = ioctl(camfd, VIDIOC_G_CTRL, &ctrl);
+ if (rc == -1) {
+ CDBG("%s: VIDIOC_G_CTRL V4L2_CID_EXPOSURE_AUTO failed: %s\n",
+ __func__, strerror(errno));
+ return rc;
+ }
+
+ /* V4L2_CID_EXPOSURE_AUTO needs to be AUTO or SHUTTER_PRIORITY */
+ if (ctrl.value != V4L2_EXPOSURE_AUTO &&
+ ctrl.value != V4L2_EXPOSURE_SHUTTER_PRIORITY) {
+ CDBG("%s: V4L2_CID_EXPOSURE_AUTO needs to be AUTO/SHUTTER_PRIORITY\n",
+ __func__);
+ return -1;
+ }
+
+ /* Get V4L2_CID_EXPOSURE_AUTO_PRIORITY */
+ memset(&ctrl, 0, sizeof(ctrl));
+ ctrl.id = V4L2_CID_EXPOSURE_AUTO_PRIORITY;
+ // rc = ioctl(camfd, VIDIOC_G_CTRL, &ctrl);
+ if (rc == -1) {
+ CDBG("%s: VIDIOC_G_CTRL V4L2_CID_EXPOSURE_AUTO_PRIORITY failed: %s\n",
+ __func__, strerror(errno));
+ return rc;
+ }
+
+ ctrl.value = !ctrl.value;
+ printf("V4L2_CID_EXPOSURE_AUTO_PRIORITY changed to %d\n", ctrl.value);
+ // rc = ioctl(camfd, VIDIOC_S_CTRL, &ctrl);
+ if (rc == -1) {
+ CDBG("%s: VIDIOC_S_CTRL V4L2_CID_EXPOSURE_AUTO_PRIORITY failed: %s\n",
+ __func__, strerror(errno));
+ }
+ return rc;
+}
+
+int set_zoom (int zoom_action_param) {
+ int rc = 0;
+ struct v4l2_control ctrl;
+
+ if (zoom_action_param == ZOOM_IN) {
+ zoom_level += zoom_queryctrl.step;
+ if (zoom_level > zoom_queryctrl.maximum)
+ zoom_level = zoom_queryctrl.maximum;
+ } else if (zoom_action_param == ZOOM_OUT) {
+ zoom_level -= zoom_queryctrl.step;
+ if (zoom_level < zoom_queryctrl.minimum)
+ zoom_level = zoom_queryctrl.minimum;
+ } else {
+ CDBG("%s: Invalid zoom_action_param value\n", __func__);
+ return -EINVAL;
+ }
+ ctrl.id = V4L2_CID_ZOOM_ABSOLUTE;
+ ctrl.value = zoom_level;
+ // rc = ioctl(camfd, VIDIOC_S_CTRL, &ctrl);
+
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION - set_iso -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+int set_iso (int iso_action_param) {
+ int rc = 0;
+ struct v4l2_control ctrl;
+
+ ctrl.id = MSM_V4L2_PID_ISO;
+ ctrl.value = iso_action_param - 1;
+ // rc = ioctl(camfd, VIDIOC_S_CTRL, &ctrl);
+
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION - increase_sharpness -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+int increase_sharpness () {
+ int rc = 0;
+ struct v4l2_control ctrl;
+
+ sharpness += sharpness_queryctrl.step;
+ if (sharpness > sharpness_queryctrl.maximum)
+ sharpness = sharpness_queryctrl.maximum;
+
+ ctrl.id = V4L2_CID_SHARPNESS;
+ ctrl.value = sharpness;
+ // rc = ioctl(camfd, VIDIOC_S_CTRL, &ctrl);
+
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION - decrease_sharpness -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+int decrease_sharpness () {
+ int rc = 0;
+ struct v4l2_control ctrl;
+
+ sharpness -= sharpness_queryctrl.step;
+ if (sharpness < sharpness_queryctrl.minimum)
+ sharpness = sharpness_queryctrl.minimum;
+
+ ctrl.id = V4L2_CID_SHARPNESS;
+ ctrl.value = sharpness;
+ // rc = ioctl(camfd, VIDIOC_S_CTRL, &ctrl);
+
+ return rc;
+}
+
+/*===========================================================================
+ * FUNCTION - print_current_menu -
+ *
+ * DESCRIPTION:
+ * ===========================================================================*/
+int print_current_menu (menu_id_change_t current_menu_id) {
+ if (current_menu_id == MENU_ID_MAIN) {
+ print_menu_preview_video ();
+ } else if (current_menu_id == MENU_ID_PREVIEWVIDEORESOLUTIONCHANGE) {
+ camera_preview_video_resolution_change_tbl ();
+ }else if (current_menu_id == MENU_ID_WHITEBALANCECHANGE) {
+ camera_preview_video_wb_change_tbl();
+ } else if (current_menu_id == MENU_ID_EXPMETERINGCHANGE) {
+ camera_preview_video_exp_metering_change_tbl();
+ } else if (current_menu_id == MENU_ID_GET_CTRL_VALUE) {
+ camera_preview_video_get_ctrl_value_tbl();
+ } else if (current_menu_id == MENU_ID_ISOCHANGE) {
+ camera_preview_video_iso_change_tbl();
+ } else if (current_menu_id == MENU_ID_BRIGHTNESSCHANGE) {
+ camera_brightness_change_tbl ();
+ } else if (current_menu_id == MENU_ID_CONTRASTCHANGE) {
+ camera_contrast_change_tbl ();
+ } else if (current_menu_id == MENU_ID_EVCHANGE) {
+ camera_EV_change_tbl ();
+ } else if (current_menu_id == MENU_ID_SATURATIONCHANGE) {
+ camera_saturation_change_tbl ();
+ } else if (current_menu_id == MENU_ID_ZOOMCHANGE) {
+ camera_preview_video_zoom_change_tbl();
+ } else if (current_menu_id == MENU_ID_SHARPNESSCHANGE) {
+ camera_preview_video_sharpness_change_tbl();
+ }else if (current_menu_id == MENU_ID_SWITCHCAMERA) {
+ camera_switch_tbl();
+ }else if (current_menu_id == MENU_ID_RECORD) {
+ camera_record_tbl();
+ }
+
+ return 0;
+}
+
diff --git a/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_preview.c b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_preview.c
new file mode 100755
index 0000000..f060730
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_preview.c
@@ -0,0 +1,1075 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include "mm_camera_dbg.h"
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <linux/ion.h>
+#include "mm_qcamera_app.h"
+
+
+/*===========================================================================
+ * FUNCTION - mm_camera_do_mmap_ion -
+ *
+ * DESCRIPTION:
+ *==========================================================================*/
+uint8_t *mm_camera_do_mmap_ion(int ion_fd, struct ion_allocation_data *alloc,
+ struct ion_fd_data *ion_info_fd, int *mapFd)
+{
+ void *ret; /* returned virtual address */
+ int rc = 0;
+ struct ion_handle_data handle_data;
+
+ /* to make it page size aligned */
+ alloc->len = (alloc->len + 4095) & (~4095);
+
+ rc = ioctl(ion_fd, ION_IOC_ALLOC, alloc);
+ if (rc < 0) {
+ CDBG_ERROR("ION allocation failed %s\n", strerror(errno));
+ goto ION_ALLOC_FAILED;
+ }
+
+ ion_info_fd->handle = alloc->handle;
+ rc = ioctl(ion_fd, ION_IOC_SHARE, ion_info_fd);
+ if (rc < 0) {
+ CDBG_ERROR("ION map failed %s\n", strerror(errno));
+ goto ION_MAP_FAILED;
+ }
+ *mapFd = ion_info_fd->fd;
+ ret = mmap(NULL,
+ alloc->len,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ *mapFd,
+ 0);
+
+ if (ret == MAP_FAILED) {
+ CDBG_ERROR("ION_MMAP_FAILED: %s (%d)\n", strerror(errno), errno);
+ goto ION_MAP_FAILED;
+ }
+
+ return ret;
+
+ ION_MAP_FAILED:
+ handle_data.handle = ion_info_fd->handle;
+ ioctl(ion_fd, ION_IOC_FREE, &handle_data);
+ ION_ALLOC_FAILED:
+ return NULL;
+}
+
+/*===========================================================================
+ * FUNCTION - mm_camera_do_munmap_ion -
+ *
+ * DESCRIPTION:
+ *==========================================================================*/
+int mm_camera_do_munmap_ion (int ion_fd, struct ion_fd_data *ion_info_fd,
+ void *addr, size_t size)
+{
+ int rc = 0;
+ rc = munmap(addr, size);
+ close(ion_info_fd->fd);
+
+ struct ion_handle_data handle_data;
+ handle_data.handle = ion_info_fd->handle;
+ ioctl(ion_fd, ION_IOC_FREE, &handle_data);
+ return rc;
+}
+
+
+int mm_app_set_preview_fmt(int cam_id,mm_camera_image_fmt_t *fmt)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ fmt->meta_header = MM_CAMEAR_META_DATA_TYPE_DEF;
+ fmt->fmt = pme->dim.prev_format;
+ fmt->width = pme->dim.display_width;
+ fmt->height = pme->dim.display_height;
+ return rc;
+}
+
+//void dumpFrameToFile(struct msm_frame* newFrame, int w, int h, char* name, int main_422)
+void dumpFrameToFile(mm_camera_buf_def_t* newFrame, int w, int h, char* name, int main_422)
+{
+ char buf[32];
+ int file_fd;
+ int i;
+ char *ext = "yuv";
+#if 0
+ if ( newFrame != NULL) {
+ char * str;
+ snprintf(buf, sizeof(buf), "/data/%s.%s", name,ext);
+ file_fd = open(buf, O_RDWR | O_CREAT, 0777);
+ if (file_fd < 0) {
+ CDBG_ERROR("%s: cannot open file\n", __func__);
+ } else {
+ CDBG("%s: %d %d", __func__, newFrame->y_off, newFrame->cbcr_off);
+ write(file_fd, (const void *)(newFrame->buffer+newFrame->y_off), w * h);
+ write(file_fd, (const void *)
+ (newFrame->buffer + newFrame->cbcr_off), w * h / 2 * main_422);
+ close(file_fd);
+ CDBG("dump %s", buf);
+ }
+ }
+#endif
+ if ( newFrame != NULL) {
+ char * str;
+ snprintf(buf, sizeof(buf), "/data/%s.%s", name,ext);
+ file_fd = open(buf, O_RDWR | O_CREAT, 0777);
+ if (file_fd < 0) {
+ CDBG_ERROR("%s: cannot open file\n", __func__);
+ } else {
+ int y_off = newFrame->buffer + newFrame->planes[0].data_offset;
+ //int cbcr_off = newFrame->buffer + newFrame->planes[1].data_offset;//newFrame->buffer + newFrame->planes[0].length;
+ int cbcr_off = newFrame->buffer + newFrame->planes[0].length;
+ CDBG("%s: Y_off = %p cbcr_off = %p", __func__, y_off,cbcr_off);
+ CDBG("%s: Y_off length = %d cbcr_off length = %d", __func__, newFrame->planes[0].length,newFrame->planes[1].length);
+
+ write(file_fd, (const void *)(y_off), newFrame->planes[0].length);
+ write(file_fd, (const void *)(cbcr_off),
+ (newFrame->planes[1].length * newFrame->num_planes));
+ /*for(i = 1; i < newFrame->num_planes; i++) {
+ CDBG("%s: CBCR = %d", __func__, newFrame->planes[j].data_offset);
+ write(file_fd, (const void *)
+ (newFrame->planes[i].data_offset), w * h / 2 * main_422);
+ }*/
+ close(file_fd);
+ CDBG("dump %s", buf);
+ }
+ }
+}
+
+int mm_app_open_camera(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int value = 0;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ if (pme->cam_mode == CAMERA_MODE) {
+ return rc;
+ }
+
+ if (MM_CAMERA_OK != (rc = mm_app_stop_preview(cam_id))) {
+ CDBG_ERROR("%s:Stop preview err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ pme->cam->ops->set_parm(pme->cam->camera_handle,MM_CAMERA_PARM_RECORDING_HINT, &value);
+
+ if (MM_CAMERA_OK != (rc = mm_app_start_preview(cam_id))) {
+ CDBG_ERROR("%s:Start preview err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ pme->cam_mode = CAMERA_MODE;
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+
+int mm_app_open_zsl(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int value = 0;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ if (pme->cam_mode == ZSL_MODE) {
+ return rc;
+ }
+
+ if (MM_CAMERA_OK != (rc = mm_app_stop_preview(cam_id))) {
+ CDBG_ERROR("%s:Stop preview err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ pme->cam->ops->set_parm(pme->cam->camera_handle,MM_CAMERA_PARM_RECORDING_HINT, &value);
+
+ if (MM_CAMERA_OK != (rc = mm_app_start_preview_zsl(cam_id))) {
+ CDBG_ERROR("%s:stream on preview err=%d\n", __func__, rc);
+ goto end;
+ }
+ pme->cam_mode = ZSL_MODE;
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+}
+#if 0
+int mm_stream_deinit_preview_buf(uint32_t camera_handle,
+ uint32_t ch_id, uint32_t stream_id,
+ void *user_data, uint8_t num_bufs,
+ mm_camera_buf_def_t *bufs)
+{
+ int i, rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
+ for (i = 0; i < num_bufs; i++) {
+ rc = my_cam_app.hal_lib.mm_camera_do_munmap_ion (pme->ionfd, &(pme->preview_buf.frame[i].fd_data),
+ (void *)pme->preview_buf.frame[i].buffer, bufs[i].frame_len);
+ if (rc != MM_CAMERA_OK) {
+ CDBG("%s: mm_camera_do_munmap err, pmem_fd = %d, rc = %d",
+ __func__, bufs[i].fd, rc);
+ }
+ }
+ close(pme->ionfd);
+ return rc;
+}
+
+int mm_stream_init_preview_buf(uint32_t camera_handle,
+ uint32_t ch_id, uint32_t stream_id,
+ void *user_data,
+ mm_camera_frame_len_offset *frame_offset_info,
+ uint8_t num_bufs,
+ uint8_t *initial_reg_flag,
+ mm_camera_buf_def_t *bufs)
+{
+ int i,j,num_planes, frame_len, y_off, cbcr_off;
+ uint32_t planes[VIDEO_MAX_PLANES];
+ uint32_t pmem_addr = 0;
+
+ mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
+
+ num_planes = frame_offset_info->num_planes;
+ for ( i = 0; i < num_planes; i++) {
+ planes[i] = frame_offset_info->mp[i].len;
+ }
+
+ frame_len = frame_offset_info->frame_len;
+ y_off = frame_offset_info->mp[0].offset;
+ cbcr_off = frame_offset_info->mp[1].offset;
+
+ CDBG("Allocating Preview Memory for %d buffers frame_len = %d",num_bufs,frame_offset_info->frame_len);
+
+ for (i = 0; i < num_bufs ; i++) {
+ int j;
+ pme->preview_buf.reg[i] = 1;
+ initial_reg_flag[i] = 1;
+
+ pme->preview_buf.frame_len = frame_len;
+ pme->preview_buf.frame[i].ion_alloc.len = pme->preview_buf.frame_len;
+ pme->preview_buf.frame[i].ion_alloc.flags =
+ (0x1 << CAMERA_ION_HEAP_ID | 0x1 << ION_IOMMU_HEAP_ID);
+ pme->preview_buf.frame[i].ion_alloc.align = 4096;
+
+ pmem_addr = (unsigned long) my_cam_app.hal_lib.mm_camera_do_mmap_ion(pme->ionfd,
+ &(pme->preview_buf.frame[i].ion_alloc), &(pme->preview_buf.frame[i].fd_data),
+ &pme->preview_buf.frame[i].fd);
+
+ pme->preview_buf.frame[i].buffer = pmem_addr;
+ pme->preview_buf.frame[i].path = OUTPUT_TYPE_P;
+ pme->preview_buf.frame[i].y_off = 0;
+ pme->preview_buf.frame[i].cbcr_off = planes[0];
+ pme->preview_buf.frame[i].phy_offset = 0;
+
+ CDBG("Buffer allocated Successfully fd = %d",pme->preview_buf.frame[i].fd);
+
+ bufs[i].fd = pme->preview_buf.frame[i].fd;
+ //bufs[i].buffer = pmem_addr;
+ bufs[i].frame_len = pme->preview_buf.frame[i].ion_alloc.len;
+ bufs[i].num_planes = num_planes;
+
+ bufs[i].frame = &pme->preview_buf.frame[i];
+
+ /* Plane 0 needs to be set seperately. Set other planes
+ * in a loop. */
+ bufs[i].planes[0].length = planes[0];
+ bufs[i].planes[0].m.userptr = bufs[i].fd;
+ bufs[i].planes[0].data_offset = y_off;
+ bufs[i].planes[0].reserved[0] = 0;
+ //buf_def->buf.mp[i].frame_offset;
+ for (j = 1; j < num_planes; j++) {
+ bufs[i].planes[j].length = planes[j];
+ bufs[i].planes[j].m.userptr = bufs[i].fd;
+ bufs[i].planes[j].data_offset = cbcr_off;
+ bufs[i].planes[j].reserved[0] =
+ bufs[i].planes[j-1].reserved[0] +
+ bufs[i].planes[j-1].length;
+ }
+ }
+ return MM_CAMERA_OK;
+}
+#endif
+
+int mm_stream_initbuf(uint32_t camera_handle,
+ uint32_t ch_id, uint32_t stream_id,
+ void *user_data,
+ mm_camera_frame_len_offset *frame_offset_info,
+ uint8_t num_bufs,
+ uint8_t *initial_reg_flag,
+ mm_camera_buf_def_t *bufs)
+{
+ int i,y_off, cbcr_off,num_planes;
+ int plane_len;
+ struct ion_allocation_data ion_alloc;
+ struct ion_fd_data ion_info_fd;
+ uint32_t pmem_addr = 0;
+ uint32_t planes[VIDEO_MAX_PLANES];
+
+ mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
+
+ num_planes = frame_offset_info->num_planes;
+ if (num_planes == 1) {
+ y_off = frame_offset_info->mp[0].offset;;
+ cbcr_off = 0;
+ } else {
+ y_off = frame_offset_info->mp[0].offset;
+ cbcr_off = frame_offset_info->mp[1].offset;
+ }
+
+ CDBG("%s: y_off = %d,cbcr_off = %d,num_planes = %d",__func__,y_off,
+ cbcr_off,num_planes);
+
+ pme->ionfd = open("/dev/ion", O_RDONLY);
+ if (pme->ionfd < 0) {
+ ALOGE("Ion dev open failed\n");
+ ALOGE("Error is %s\n", strerror(errno));
+ }
+
+ for (i = 0; i < num_bufs ; i++) {
+ int j;
+
+ //if(pme->cam_mode != RECORDER_MODE || pme->fullSizeSnapshot) {
+ initial_reg_flag[i] = 1;
+ //}else{
+ //initial_reg_flag[i] = 0;
+ //}
+
+ ion_alloc.len = frame_offset_info->frame_len;
+ ion_alloc.flags =
+ (0x1 << CAMERA_ION_HEAP_ID | 0x1 << ION_IOMMU_HEAP_ID);
+ ion_alloc.align = 4096;
+
+ /*bufs[i].buffer = my_cam_app.hal_lib.mm_camera_do_mmap_ion(pme->ionfd,
+ &ion_alloc, &ion_info_fd,
+ &bufs[i].fd);*/
+
+ bufs[i].buffer = mm_camera_do_mmap_ion(pme->ionfd,
+ &ion_alloc, &ion_info_fd,
+ &bufs[i].fd);
+ CDBG(" %s : Buffer allocated fd = %d, length = %d, y_off = %d cdcr_off = %d",
+ __func__,bufs[i].fd,ion_alloc.len,y_off,cbcr_off);
+
+ bufs[i].frame_len = ion_alloc.len;
+ bufs[i].num_planes = num_planes;
+
+ /* Plane 0 needs to be set seperately. Set other planes
+ * in a loop. */
+ bufs[i].planes[0].length = frame_offset_info->mp[0].len;
+ bufs[i].planes[0].m.userptr = bufs[i].fd;
+ bufs[i].planes[0].data_offset = y_off;
+ bufs[i].planes[0].reserved[0] = 0;
+ //buf_def->buf.mp[i].frame_offset;
+ for (j = 1; j < num_planes; j++) {
+ bufs[i].planes[j].length = frame_offset_info->mp[j].len;
+ bufs[i].planes[j].m.userptr = bufs[i].fd;
+ bufs[i].planes[j].data_offset = cbcr_off;
+ bufs[i].planes[j].reserved[0] =
+ bufs[i].planes[j-1].reserved[0] +
+ bufs[i].planes[j-1].length;
+ }
+ }
+ CDBG("%s: X",__func__);
+ return MM_CAMERA_OK;
+}
+
+#if 0
+int mm_stream_initbuf_1(uint32_t camera_handle,
+ uint32_t ch_id, uint32_t stream_id,
+ void *user_data,
+ mm_camera_frame_len_offset *frame_offset_info,
+ uint8_t num_bufs,
+ uint8_t *initial_reg_flag,
+ mm_camera_buf_def_t *bufs)
+{
+ int i;
+ int streamType = 0;
+
+ mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
+
+ CDBG("%s : E ", __FUNCTION__);
+
+ for (i= 0; i < 5; i++) {
+ if (pme->stream[i].id == stream_id) {
+ CDBG("Allocate Memory for Stream %d",i);
+ streamType = i;
+ break;
+ }
+ }
+
+ streamType = MM_CAMERA_PREVIEW;
+ switch (streamType) {
+ case MM_CAMERA_PREVIEW:
+ mm_stream_init_preview_buf( camera_handle,
+ ch_id, stream_id,
+ user_data,
+ frame_offset_info,
+ num_bufs,
+ initial_reg_flag,
+ bufs);
+ break;
+ case MM_CAMERA_VIDEO:
+ mm_stream_init_video_buf( camera_handle,
+ ch_id, stream_id,
+ user_data,
+ frame_offset_info,
+ num_bufs,
+ initial_reg_flag,
+ bufs);
+ break;
+ case MM_CAMERA_SNAPSHOT_MAIN:
+ mm_stream_init_main_buf( camera_handle,
+ ch_id, stream_id,
+ user_data,
+ frame_offset_info,
+ num_bufs,
+ initial_reg_flag,
+ bufs);
+ break;
+ case MM_CAMERA_SNAPSHOT_THUMBNAIL:
+ mm_stream_init_thumbnail_buf( camera_handle,
+ ch_id, stream_id,
+ user_data,
+ frame_offset_info,
+ num_bufs,
+ initial_reg_flag,
+ bufs);
+ break;
+ default:
+ break;
+ }
+
+ CDBG(" %s : X ",__FUNCTION__);
+ return MM_CAMERA_OK;
+}
+#endif
+int mm_stream_deinitbuf(uint32_t camera_handle,
+ uint32_t ch_id, uint32_t stream_id,
+ void *user_data, uint8_t num_bufs,
+ mm_camera_buf_def_t *bufs)
+{
+ int i, rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
+
+ CDBG("%s: E",__func__);
+
+ for (i = 0; i < num_bufs; i++) {
+ /*rc = my_cam_app.hal_lib.mm_camera_do_munmap_ion (pme->ionfd, &bufs[i].fd,
+ (void *)bufs[i].buffer, bufs[i].frame_len);*/
+ rc = mm_camera_do_munmap_ion (pme->ionfd, &bufs[i].fd,
+ (void *)bufs[i].buffer, bufs[i].frame_len);
+ }
+ close(pme->ionfd);
+ CDBG("%s: X",__func__);
+ return rc;
+}
+
+#if 0
+static int mm_stream_deinitbuf_1(uint32_t camera_handle,
+ uint32_t ch_id, uint32_t stream_id,
+ void *user_data, uint8_t num_bufs,
+ mm_camera_buf_def_t *bufs)
+{
+ int i, rc = MM_CAMERA_OK;
+ int streamType = 0;
+ mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
+ CDBG("%s: BEGIN",__func__);
+
+ for (i= 0; i < 5; i++) {
+ if (pme->stream[i].id == stream_id) {
+ CDBG("Allocate Memory for Stream %d",i);
+ streamType = i;
+ break;
+ }
+ }
+ streamType = MM_CAMERA_PREVIEW;
+ switch (streamType) {
+ case MM_CAMERA_PREVIEW:
+ mm_stream_deinit_preview_buf(camera_handle,
+ ch_id, stream_id,
+ user_data, num_bufs,
+ bufs);
+ break;
+ case MM_CAMERA_VIDEO:
+ mm_stream_deinit_video_buf(camera_handle,
+ ch_id, stream_id,
+ user_data, num_bufs,
+ bufs);
+ break;
+ case MM_CAMERA_SNAPSHOT_MAIN:
+ mm_stream_deinit_main_buf(camera_handle,
+ ch_id, stream_id,
+ user_data, num_bufs,
+ bufs);
+ break;
+ case MM_CAMERA_SNAPSHOT_THUMBNAIL:
+ mm_stream_deinit_thumbnail_buf(camera_handle,
+ ch_id, stream_id,
+ user_data, num_bufs,
+ bufs);
+ break;
+ default:
+ break;
+ }
+
+ /* zero out the buf stuct */
+ CDBG("%s: END",__func__);
+ return MM_CAMERA_OK;
+}
+#endif
+
+void preview_cb_signal(mm_camera_app_obj_t *pme)
+{
+ if (pme->cam_state == CAMERA_STATE_PREVIEW) {
+ mm_camera_app_done();
+ }
+}
+
+void mm_app_preview_notify_cb(mm_camera_super_buf_t *bufs,
+ void *user_data)
+{
+ int rc;
+ mm_camera_buf_def_t *frame = NULL;
+ mm_camera_app_obj_t *pme = NULL;
+ CDBG("%s: BEGIN\n", __func__);
+ frame = bufs->bufs[MM_CAMERA_PREVIEW] ;
+ pme = (mm_camera_app_obj_t *)user_data;
+
+ CDBG("%s: BEGIN - length=%d, frame idx = %d\n", __func__, frame->frame_len, frame->frame_idx);
+
+ //dumpFrameToFile(frame->frame,pme->dim.display_width,pme->dim.display_height,"preview", 1);
+ dumpFrameToFile(frame,pme->dim.display_width,pme->dim.display_height,"preview", 1);
+ if (!my_cam_app.run_sanity) {
+ if (0 != (rc = mm_app_dl_render(frame->fd, NULL))) {
+ CDBG("%s:DL rendering err=%d, frame fd=%d,frame idx = %d\n",
+ __func__, rc, frame->fd, frame->frame_idx);
+ }
+ }
+
+ CDBG("In CB function i/p = %p o/p = %p",bufs->bufs[MM_CAMERA_PREVIEW],frame);
+
+ if (MM_CAMERA_OK != pme->cam->ops->qbuf(pme->cam->camera_handle,pme->ch_id,frame)) {
+ CDBG_ERROR("%s: Failed in Preview Qbuf\n", __func__);
+ return;
+ }
+ if (my_cam_app.run_sanity) {
+ preview_cb_signal(pme);
+ }
+ CDBG("%s: END\n", __func__);
+
+}
+
+static void mm_app_zsl_notify_cb(mm_camera_super_buf_t *bufs,
+ void *user_data)
+{
+ int rc;
+ int i = 0;
+ mm_camera_buf_def_t *preview_frame = NULL;
+ mm_camera_buf_def_t *main_frame = NULL;
+ mm_camera_buf_def_t *thumb_frame = NULL;
+ mm_camera_app_obj_t *pme = NULL;
+ CDBG("%s: BEGIN\n", __func__);
+
+ pme = (mm_camera_app_obj_t *)user_data;
+
+ CDBG("%s : total streams = %d",__func__,bufs->num_bufs);
+ preview_frame = bufs->bufs[0] ;
+ main_frame = bufs->bufs[1];
+ thumb_frame = bufs->bufs[0];
+
+ //dumpFrameToFile(preview_frame->frame,pme->dim.display_width,pme->dim.display_height,"preview", 1);
+ dumpFrameToFile(preview_frame,pme->dim.display_width,pme->dim.display_height,"zsl_preview", 1);
+ if (0 != (rc = mm_app_dl_render(preview_frame->fd, NULL))) {
+ CDBG("%s:DL rendering err=%d, frame fd=%d,frame idx = %d\n",
+ __func__, rc, preview_frame->fd, preview_frame->frame_idx);
+ }
+
+ if (bufs->num_bufs == 2 && main_frame != NULL) {
+ CDBG("mainframe frame_idx = %d fd = %d frame length = %d",main_frame->frame_idx,main_frame->fd,main_frame->frame_len);
+ CDBG("thumnail frame_idx = %d fd = %d frame length = %d",thumb_frame->frame_idx,thumb_frame->fd,thumb_frame->frame_len);
+
+ //dumpFrameToFile(main_frame->frame,pme->dim.picture_width,pme->dim.picture_height,"main", 1);
+ //dumpFrameToFile(thumb_frame->frame,pme->dim.thumbnail_width,pme->dim.thumbnail_height,"thumb", 1);
+
+ dumpFrameToFile(main_frame,pme->dim.picture_width,pme->dim.picture_height,"zsl_main", 1);
+ dumpFrameToFile(thumb_frame,pme->dim.thumbnail_width,pme->dim.thumbnail_height,"zsl_thumb", 1);
+
+ if (MM_CAMERA_OK != pme->cam->ops->qbuf(pme->cam->camera_handle,pme->ch_id,main_frame)) {
+ CDBG_ERROR("%s: Failed in thumbnail Qbuf\n", __func__);
+ }
+ }
+
+ if (MM_CAMERA_OK != pme->cam->ops->qbuf(pme->cam->camera_handle,pme->ch_id,preview_frame)) {
+ CDBG_ERROR("%s: Failed in Preview Qbuf\n", __func__);
+ }
+ CDBG("%s: END\n", __func__);
+}
+
+int mm_app_prepare_preview(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int op_mode;
+
+ CDBG("%s: E",__func__);
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ pme->mem_cam->get_buf = mm_stream_initbuf;
+ pme->mem_cam->put_buf = mm_stream_deinitbuf;
+ pme->mem_cam->user_data = pme;
+
+ op_mode = MM_CAMERA_OP_MODE_VIDEO;
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->set_parm(
+ pme->cam->camera_handle,MM_CAMERA_PARM_OP_MODE, &op_mode))) {
+ CDBG_ERROR("%s: Set preview op mode error",__func__);
+ goto end;
+ }
+
+ pme->stream[MM_CAMERA_PREVIEW].id = pme->cam->ops->add_stream(pme->cam->camera_handle,pme->ch_id,
+ mm_app_preview_notify_cb,pme,
+ MM_CAMERA_PREVIEW, 0);
+
+ if (!pme->stream[MM_CAMERA_PREVIEW].id) {
+ CDBG_ERROR("%s:Add stream preview error =%d\n", __func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+ CDBG("%s :Add stream is successfull stream ID = %d",__func__,pme->stream[MM_CAMERA_PREVIEW].id);
+
+ mm_app_set_preview_fmt(cam_id,&pme->stream[MM_CAMERA_PREVIEW].str_config.fmt);
+ pme->stream[MM_CAMERA_PREVIEW].str_config.need_stream_on = 1;
+ pme->stream[MM_CAMERA_PREVIEW].str_config.num_of_bufs = PREVIEW_BUF_NUM;
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->config_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_PREVIEW].id,
+ &pme->stream[MM_CAMERA_PREVIEW].str_config))) {
+ CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
+ goto end;
+ }
+ end:
+ return rc;
+}
+
+int mm_app_unprepare_preview(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ return rc;
+}
+
+int mm_app_streamon_preview(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int stream[2];
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+ mm_camera_frame_len_offset frame_offset_info;
+
+ stream[0] = pme->stream[MM_CAMERA_PREVIEW].id;
+ stream[1] = 0;
+
+ pme->cam->ops->get_stream_parm(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_PREVIEW].id,MM_CAMERA_STREAM_OFFSET,&frame_offset_info);
+ ALOGE("DEBUG : length = %d",frame_offset_info.frame_len);
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->start_streams(pme->cam->camera_handle,pme->ch_id,1,&stream))) {
+ CDBG_ERROR("%s : Start Stream preview Error",__func__);
+ goto end;
+ }
+ pme->cam_state = CAMERA_STATE_PREVIEW;
+ end:
+ CDBG("%s: X rc = %d",__func__,rc);
+ return rc;
+}
+
+int mm_app_prepare_preview_zsl(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_bundle_attr_t attr;
+ int stream[3];
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+ int op_mode = 0;
+
+ op_mode = MM_CAMERA_OP_MODE_ZSL;
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->set_parm(
+ pme->cam->camera_handle,MM_CAMERA_PARM_OP_MODE, &op_mode))) {
+ CDBG_ERROR("%s: Set preview op mode error",__func__);
+ goto end;
+ }
+
+ pme->stream[MM_CAMERA_PREVIEW].id = pme->cam->ops->add_stream(pme->cam->camera_handle,pme->ch_id,
+ mm_app_preview_notify_cb,pme,
+ MM_CAMERA_PREVIEW, 0);
+
+ if (!pme->stream[MM_CAMERA_PREVIEW].id) {
+ CDBG_ERROR("%s:Add stream preview error =%d\n", __func__, rc);
+ goto end;
+ }
+
+ CDBG("%s :Add stream is successfull stream ID = %d",__func__,pme->stream[MM_CAMERA_PREVIEW].id);
+
+ mm_app_set_preview_fmt(cam_id,&pme->stream[MM_CAMERA_PREVIEW].str_config.fmt);
+ pme->stream[MM_CAMERA_PREVIEW].str_config.need_stream_on = 1;
+ pme->stream[MM_CAMERA_PREVIEW].str_config.num_of_bufs = PREVIEW_BUF_NUM;
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->config_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_PREVIEW].id,
+ &pme->stream[MM_CAMERA_PREVIEW].str_config))) {
+ CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id = pme->cam->ops->add_stream(pme->cam->camera_handle,pme->ch_id,
+ NULL,pme,
+ MM_CAMERA_SNAPSHOT_MAIN, 0);
+
+ CDBG("Add Snapshot main is successfull stream ID = %d",pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id);
+ if (!pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id) {
+ CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+ pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config.need_stream_on = 1;
+ pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config.num_of_bufs = 7;
+
+ mm_app_set_snapshot_fmt(cam_id,&pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config.fmt);
+
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->config_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id,
+ &pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config))) {
+ CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
+ goto end;
+ }
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_streamon_preview_zsl(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_bundle_attr_t attr;
+ int stream[3];
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+ int op_mode = 0;
+
+
+ stream[0] = pme->stream[MM_CAMERA_PREVIEW].id;
+ stream[1] = pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id;
+
+ attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
+ attr.burst_num = 1;
+ attr.look_back = 2;
+ attr.post_frame_skip = 0;
+ attr.water_mark = 2;
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->init_stream_bundle(
+ pme->cam->camera_handle,pme->ch_id,mm_app_zsl_notify_cb,pme,&attr,2,stream))) {
+ CDBG_ERROR("%s:init_stream_bundle err=%d\n", __func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->start_streams(pme->cam->camera_handle,pme->ch_id,
+ 2, stream))) {
+ CDBG_ERROR("%s:start_streams err=%d\n", __func__, rc);
+ rc = -1;
+ goto end;
+ }
+ pme->cam_state = CAMERA_STATE_PREVIEW;
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+
+}
+
+int initDisplay()
+{
+ int rc = MM_CAMERA_OK;
+
+ use_overlay_fb_display_driver();
+ if (launch_camframe_fb_thread()) {
+ CDBG_ERROR("%s:launch_camframe_fb_thread failed!\n", __func__);
+ //rc = -MM_CAMERA_E_GENERAL;
+ }
+ CDBG("%s: launch_camframe_fb_thread done\n", __func__);
+ return rc;
+}
+
+int deinitDisplay()
+{
+ /* stop the display thread */
+ release_camframe_fb_thread();
+ return MM_CAMERA_OK;
+}
+
+int mm_app_start_preview(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+ int op_mode = 0;
+
+ CDBG("pme = %p, pme->cam =%p, pme->cam->camera_handle = %d",
+ pme,pme->cam,pme->cam->camera_handle);
+
+ if (pme->cam_state == CAMERA_STATE_PREVIEW) {
+ return rc;
+ }
+
+ if (!my_cam_app.run_sanity) {
+ if (MM_CAMERA_OK != initDisplay()) {
+ CDBG_ERROR("%s : Could not initalize display",__func__);
+ goto end;
+ }
+ }
+
+ if (MM_CAMERA_OK != (rc = mm_app_prepare_preview(cam_id))) {
+ CDBG_ERROR("%s:Stream On Preview failed rc=%d\n", __func__, rc);
+ goto end;
+ }
+
+ if (MM_CAMERA_OK != (rc = mm_app_streamon_preview(cam_id))) {
+ CDBG_ERROR("%s:Stream On Preview failed rc=%d\n", __func__, rc);
+ goto end;
+ }
+
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_start_preview_zsl(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("pme = %p, pme->cam =%p, pme->cam->camera_handle = %d",
+ pme,pme->cam,pme->cam->camera_handle);
+
+ if (!my_cam_app.run_sanity) {
+ if (MM_CAMERA_OK != initDisplay()) {
+ CDBG_ERROR("%s : Could not initalize display",__func__);
+ goto end;
+ }
+ }
+
+ pme->mem_cam->get_buf = mm_stream_initbuf;
+ pme->mem_cam->put_buf = mm_stream_deinitbuf;
+ pme->mem_cam->user_data = pme;
+
+ if (MM_CAMERA_OK != (rc = mm_app_prepare_preview_zsl(cam_id))) {
+ CDBG_ERROR("%s:Prepare preview err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ if (MM_CAMERA_OK != (rc = mm_app_streamon_preview_zsl(cam_id))) {
+ CDBG_ERROR("%s:stream on preview err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ /*if(MM_CAMERA_OK != (rc = mm_app_bundle_zsl_stream(cam_id))){
+ CDBG_ERROR("%s: bundle and start of ZSl err=%d\n", __func__, rc);
+ goto end;
+ }*/
+
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+static int mm_app_streamoff_preview(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int stream[2];
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ stream[0] = pme->stream[MM_CAMERA_PREVIEW].id;
+ stream[1] = 0;
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->stop_streams(pme->cam->camera_handle,pme->ch_id,1,&stream))) {
+ CDBG_ERROR("%s : Preview Stream off Error",__func__);
+ goto end;
+ }
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->del_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_PREVIEW].id))) {
+ CDBG_ERROR("%s : Delete Stream Preview error",__func__);
+ goto end;
+ }
+ CDBG("del_stream successfull");
+ pme->cam_state = CAMERA_STATE_OPEN;
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+
+ return rc;
+}
+
+static int mm_app_streamoff_preview_zsl(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int stream[2];
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ stream[0] = pme->stream[MM_CAMERA_PREVIEW].id;
+ stream[1] = pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id;
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->destroy_stream_bundle(pme->cam->camera_handle,pme->ch_id))) {
+ CDBG_ERROR("%s : ZSL Snapshot destroy_stream_bundle Error",__func__);
+ goto end;
+ }
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->stop_streams(pme->cam->camera_handle,pme->ch_id,2,&stream))) {
+ CDBG_ERROR("%s : Preview Stream off Error",__func__);
+ goto end;
+ }
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->del_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_PREVIEW].id))) {
+ CDBG_ERROR("%s : Delete Stream Preview error",__func__);
+ goto end;
+ }
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->del_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id))) {
+ CDBG_ERROR("%s : Delete Stream Preview error",__func__);
+ goto end;
+ }
+ CDBG("del_stream successfull");
+ pme->cam_state = CAMERA_STATE_OPEN;
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+
+ return rc;
+}
+
+int startPreview(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("%s: Start Preview",__func__);
+
+ if (pme->cam_mode == ZSL_MODE || pme->cam_mode == RECORDER_MODE) {
+ switch (pme->cam_state) {
+ case CAMERA_STATE_RECORD:
+ if (MM_CAMERA_OK != mm_app_stop_video(cam_id)) {
+ CDBG_ERROR("%s:Cannot stop video err=%d\n", __func__, rc);
+ return -1;
+ }
+ case CAMERA_STATE_PREVIEW:
+ if (MM_CAMERA_OK != mm_app_open_camera(cam_id)) {
+ CDBG_ERROR("%s: Cannot switch to camera mode=%d\n", __func__);
+ return -1;
+ }
+ break;
+ case CAMERA_STATE_SNAPSHOT:
+ default:
+ break;
+ }
+ } else if (pme->cam_mode == CAMERA_MODE && pme->cam_state == CAMERA_STATE_OPEN) {
+
+ if (MM_CAMERA_OK != (rc = mm_app_start_preview(cam_id))) {
+ CDBG_ERROR("%s:preview streaming on err=%d\n", __func__, rc);
+ return -1;
+ }
+ }
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+int stopPreview(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("%s : pme->cam_mode = %d, pme->cam_state = %d",__func__,pme->cam_mode,pme->cam_state);
+
+ if (pme->cam_mode == CAMERA_MODE && pme->cam_state == CAMERA_STATE_PREVIEW) {
+ if (MM_CAMERA_OK != (rc = mm_app_stop_preview(cam_id))) {
+ CDBG("%s:streamoff preview err=%d\n", __func__, rc);
+ goto end;
+ }
+ } else if (pme->cam_mode == ZSL_MODE && pme->cam_state == CAMERA_STATE_PREVIEW) {
+ if (MM_CAMERA_OK != (rc = mm_app_stop_preview_zsl(cam_id))) {
+ CDBG("%s:streamoff preview err=%d\n", __func__, rc);
+ goto end;
+ }
+ } else if (pme->cam_mode == RECORDER_MODE && pme->cam_state == CAMERA_STATE_PREVIEW) {
+ if (MM_CAMERA_OK != (rc = mm_app_stop_preview(cam_id))) {
+ CDBG("%s:streamoff preview err=%d\n", __func__, rc);
+ goto end;
+ }
+ mm_app_unprepare_video(cam_id);
+ }
+ end:
+ return rc;
+}
+
+int mm_app_stop_preview(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ if (MM_CAMERA_OK != (rc = mm_app_streamoff_preview(cam_id))) {
+ CDBG_ERROR("%s : Delete Stream Preview error",__func__);
+ goto end;
+ }
+
+ CDBG("Stop Preview successfull");
+
+ if (!my_cam_app.run_sanity) {
+ deinitDisplay();
+ }
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_stop_preview_zsl(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ if (MM_CAMERA_OK != (rc = mm_app_streamoff_preview_zsl(cam_id))) {
+ CDBG_ERROR("%s : Delete Stream Preview error",__func__);
+ goto end;
+ }
+
+ CDBG("Stop Preview successfull");
+ if (!my_cam_app.run_sanity) {
+ deinitDisplay();
+ }
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+}
diff --git a/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_rdi.c b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_rdi.c
new file mode 100755
index 0000000..f59f498
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_rdi.c
@@ -0,0 +1,329 @@
+/*
+Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include "mm_camera_dbg.h"
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <linux/ion.h>
+#include "mm_qcamera_app.h"
+
+/*typedef enum {
+ STREAM_IMAGE,
+ STREAM_RAW,
+ STREAM_IMAGE_AND_RAW,
+ STREAM_RAW_AND_RAW,
+ STREAM_MAX,
+} mm_camera_channel_stream_info_t;*/
+
+#define RDI_MASK STREAM_RAW
+mm_camera_channel_stream_info_t rdi_mode;
+
+static int mm_app_set_rdi_fmt(int cam_id,mm_camera_image_fmt_t *fmt)
+{
+ int rc = MM_CAMERA_OK;
+ cam_ctrl_dimension_t dim;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ fmt->meta_header = MM_CAMEAR_META_DATA_TYPE_DEF;
+ //pme->cam->ops->get_parm(pme->cam->camera_handle,MM_CAMERA_PARM_DIMENSION, &dim);
+ fmt->fmt = CAMERA_BAYER_SBGGR10;//CAMERA_RDI;
+ fmt->width = 0;
+ fmt->height = 0;
+ fmt->rotation = 0;
+
+ CDBG("%s: RDI Dimensions = %d X %d",__func__,fmt->width,fmt->height);
+ return rc;
+}
+
+int mm_app_open_rdi(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int value = RDI_MASK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ if (pme->cam_mode == RDI_MODE) {
+ return rc;
+ }
+
+ if (MM_CAMERA_OK != (rc = stopPreview(cam_id))) {
+ CDBG_ERROR("%s:Stop preview err=%d\n", __func__, rc);
+ goto end;
+ }
+ pme->cam_mode = RDI_MODE;
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+void rdi_cb_signal(mm_camera_app_obj_t *pme)
+{
+ if (pme->cam_mode == RDI_MODE) {
+ mm_camera_app_done();
+ }
+}
+
+static void mm_app_rdi_notify_cb(mm_camera_super_buf_t *bufs,
+ void *user_data)
+{
+ int rc;
+ mm_camera_buf_def_t *frame = NULL;
+ mm_camera_app_obj_t *pme = NULL;
+ CDBG("%s: BEGIN\n", __func__);
+ frame = bufs->bufs[0] ;
+ pme = (mm_camera_app_obj_t *)user_data;
+
+ CDBG("%s: BEGIN - length=%d, frame idx = %d\n", __func__, frame->frame_len, frame->frame_idx);
+
+ //dumpFrameToFile(frame->frame,pme->dim.display_width,pme->dim.display_height,"preview", 1);
+ dumpFrameToFile(frame,pme->dim.rdi0_width,pme->dim.rdi0_height,"rdi", 1);
+
+ if (MM_CAMERA_OK != pme->cam->ops->qbuf(pme->cam->camera_handle,pme->ch_id,frame)) {
+ CDBG_ERROR("%s: Failed in Preview Qbuf\n", __func__);
+ return;
+ }
+ if (my_cam_app.run_sanity) {
+ mm_camera_app_done(pme);
+ }
+ CDBG("%s: END\n", __func__);
+
+}
+
+int mm_app_prepare_rdi(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int op_mode;
+ int value = RDI_MASK;
+
+ CDBG("%s: E",__func__);
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ pme->mem_cam->get_buf = mm_stream_initbuf;
+ pme->mem_cam->put_buf = mm_stream_deinitbuf;
+ pme->mem_cam->user_data = pme;
+
+ //pme->cam->ops->set_parm(pme->cam->camera_handle,MM_CAMERA_PARM_CH_INTERFACE, &value);
+ //pme->cam->ops->get_parm(pme->cam->camera_handle,MM_CAMERA_PARM_CH_INTERFACE, &rdi_mode);
+
+ pme->stream[MM_CAMERA_RDI].id = pme->cam->ops->add_stream(pme->cam->camera_handle,pme->ch_id,
+ mm_app_rdi_notify_cb,pme,
+ MM_CAMERA_RDI, 0);
+
+ if (!pme->stream[MM_CAMERA_RDI].id) {
+ CDBG_ERROR("%s:Add RDI error =%d\n", __func__, rc);
+ rc = -1;
+ goto end;
+ }
+ CDBG("%s :Add RDI stream is successfull stream ID = %d",__func__,pme->stream[MM_CAMERA_RDI].id);
+
+ mm_app_set_rdi_fmt(cam_id,&pme->stream[MM_CAMERA_RDI].str_config.fmt);
+ pme->stream[MM_CAMERA_RDI].str_config.need_stream_on = 1;
+ pme->stream[MM_CAMERA_RDI].str_config.num_of_bufs = 7;
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->config_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_RDI].id,
+ &pme->stream[MM_CAMERA_RDI].str_config))) {
+ CDBG_ERROR("%s:RDI streaming err=%d\n", __func__, rc);
+ goto end;
+ }
+#if 0
+ if (rdi_mode == STREAM_IMAGE_AND_RAW) {
+ pme->stream[MM_CAMERA_PREVIEW].id = pme->cam->ops->add_stream(pme->cam->camera_handle,pme->ch_id,
+ mm_app_preview_notify_cb,pme,
+ MM_CAMERA_PREVIEW, 0);
+
+ if (!pme->stream[MM_CAMERA_PREVIEW].id) {
+ CDBG_ERROR("%s:Add stream preview error =%d\n", __func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+ CDBG("%s :Add stream is successfull stream ID = %d",__func__,pme->stream[MM_CAMERA_PREVIEW].id);
+
+ mm_app_set_preview_fmt(cam_id,&pme->stream[MM_CAMERA_PREVIEW].str_config.fmt);
+ pme->stream[MM_CAMERA_PREVIEW].str_config.need_stream_on = 1;
+ pme->stream[MM_CAMERA_PREVIEW].str_config.num_of_bufs = PREVIEW_BUF_NUM;
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->config_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_PREVIEW].id,
+ &pme->stream[MM_CAMERA_PREVIEW].str_config))) {
+ CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
+ goto end;
+ }
+ }
+#endif
+ end:
+ return rc;
+}
+
+int mm_app_unprepare_rdi(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ return rc;
+}
+
+int mm_app_streamon_rdi(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int stream[2];
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+ int num_of_streams;
+
+ /*if(rdi_mode == STREAM_IMAGE_AND_RAW){
+ num_of_streams = 2;
+ stream[0] = pme->stream[MM_CAMERA_RDI].id;
+ stream[1] = pme->stream[MM_CAMERA_PREVIEW].id;
+ }else */{
+ num_of_streams = 1;
+ stream[0] = pme->stream[MM_CAMERA_RDI].id;
+ }
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->start_streams(pme->cam->camera_handle,pme->ch_id,num_of_streams,&stream))) {
+ CDBG_ERROR("%s : Start RDI Stream preview Error",__func__);
+ goto end;
+ }
+ pme->cam_state = CAMERA_STATE_RDI;
+ end:
+ CDBG("%s: X rc = %d",__func__,rc);
+ return rc;
+}
+
+int mm_app_start_rdi(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+ int op_mode = 0;
+
+ CDBG("pme = %p, pme->cam =%p, pme->cam->camera_handle = %d",
+ pme,pme->cam,pme->cam->camera_handle);
+
+ if (pme->cam_state == CAMERA_STATE_RDI) {
+ return rc;
+ }
+
+ if (MM_CAMERA_OK != (rc = mm_app_prepare_rdi(cam_id))) {
+ CDBG_ERROR("%s:Prepare RDI failed rc=%d\n", __func__, rc);
+ goto end;
+ }
+
+ if (MM_CAMERA_OK != (rc = mm_app_streamon_rdi(cam_id))) {
+ CDBG_ERROR("%s:Stream On RDI failed rc=%d\n", __func__, rc);
+ goto end;
+ }
+
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+static int mm_app_streamoff_rdi(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int stream[2];
+ int num_of_streams;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ /*if(rdi_mode == STREAM_IMAGE_AND_RAW){
+ num_of_streams = 2;
+ stream[0] = pme->stream[MM_CAMERA_RDI].id;
+ stream[1] = pme->stream[MM_CAMERA_PREVIEW].id;
+ }else*/{
+ num_of_streams = 1;
+ stream[0] = pme->stream[MM_CAMERA_RDI].id;
+ }
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->stop_streams(pme->cam->camera_handle,pme->ch_id,num_of_streams,&stream))) {
+ CDBG_ERROR("%s : RDI Stream off Error",__func__);
+ goto end;
+ }
+
+ /*if(rdi_mode == STREAM_IMAGE_AND_RAW) {
+ if(MM_CAMERA_OK != (rc = pme->cam->ops->del_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_PREVIEW].id)))
+ {
+ CDBG_ERROR("%s : Delete Preview error",__func__);
+ goto end;
+ }
+ }*/
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->del_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_RDI].id))) {
+ CDBG_ERROR("%s : Delete Stream RDI error",__func__);
+ goto end;
+ }
+ CDBG("del_stream successfull");
+ pme->cam_state = CAMERA_STATE_OPEN;
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+
+ return rc;
+}
+
+int startRdi(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("%s: Start Preview",__func__);
+
+ if (pme->cam_mode == ZSL_MODE || pme->cam_mode == RECORDER_MODE || pme->cam_mode == CAMERA_MODE) {
+ switch (pme->cam_state) {
+ case CAMERA_STATE_RECORD:
+ if (MM_CAMERA_OK != mm_app_stop_video(cam_id)) {
+ CDBG_ERROR("%s:Cannot stop video err=%d\n", __func__, rc);
+ return -1;
+ }
+ case CAMERA_STATE_PREVIEW:
+ if (MM_CAMERA_OK != mm_app_open_rdi(cam_id)) {
+ CDBG_ERROR("%s: Cannot switch to camera mode=%d\n", __func__);
+ return -1;
+ }
+ case CAMERA_STATE_SNAPSHOT:
+ default:
+ break;
+ }
+ }
+ mm_app_start_rdi(cam_id);
+ return rc;
+}
+
+int stopRdi(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ mm_app_streamoff_rdi(cam_id);
+
+ end:
+ return rc;
+}
+
+
diff --git a/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_snapshot.c b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_snapshot.c
new file mode 100755
index 0000000..eec350d
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_snapshot.c
@@ -0,0 +1,1401 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include "mm_camera_dbg.h"
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include "mm_qcamera_app.h"
+
+#define BUFF_SIZE_128 128
+
+//static mm_camera_ch_data_buf_t *mCurrentFrameEncoded;
+static int JpegOffset = 0;
+static int raw_snapshot_cnt = 0;
+static int snapshot_cnt = 0;
+static pthread_mutex_t g_s_mutex;
+static int g_status = 0;
+static pthread_cond_t g_s_cond_v;
+
+
+static void mm_app_snapshot_done()
+{
+ pthread_mutex_lock(&g_s_mutex);
+ g_status = TRUE;
+ pthread_cond_signal(&g_s_cond_v);
+ pthread_mutex_unlock(&g_s_mutex);
+}
+
+static int mm_app_dump_snapshot_frame(struct msm_frame *frame,
+ uint32_t len, int is_main, int is_raw)
+{
+ char bufp[BUFF_SIZE_128];
+ int file_fdp;
+ int rc = 0;
+
+ if (is_raw) {
+ snprintf(bufp, BUFF_SIZE_128, "/data/main_raw_%d.yuv", raw_snapshot_cnt);
+ } else {
+ if (is_main) {
+ snprintf(bufp, BUFF_SIZE_128, "/data/main_%d.yuv", snapshot_cnt);
+ } else {
+ snprintf(bufp, BUFF_SIZE_128, "/data/thumb_%d.yuv", snapshot_cnt);
+ }
+ }
+
+ file_fdp = open(bufp, O_RDWR | O_CREAT, 0777);
+
+ if (file_fdp < 0) {
+ CDBG("cannot open file %s\n", bufp);
+ rc = -1;
+ goto end;
+ }
+ CDBG("%s:dump snapshot frame to '%s'\n", __func__, bufp);
+ write(file_fdp,
+ (const void *)frame->buffer, len);
+ close(file_fdp);
+ end:
+ return rc;
+}
+
+
+static void mm_app_dump_jpeg_frame(const void * data, uint32_t size, char* name, char* ext, int index)
+{
+ char buf[32];
+ int file_fd;
+ if ( data != NULL) {
+ char * str;
+ snprintf(buf, sizeof(buf), "/data/%s_%d.%s", name, index, ext);
+ CDBG("%s size =%d", buf, size);
+ file_fd = open(buf, O_RDWR | O_CREAT, 0777);
+ write(file_fd, data, size);
+ close(file_fd);
+ }
+}
+
+static int mm_app_set_thumbnail_fmt(int cam_id,mm_camera_image_fmt_t *fmt)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ fmt->meta_header = MM_CAMEAR_META_DATA_TYPE_DEF;
+ fmt->fmt = pme->dim.thumb_format;
+ fmt->width = pme->dim.thumbnail_width;
+ fmt->height = pme->dim.thumbnail_height;
+ CDBG("Thumbnail Dimension = %dX%d",fmt->width,fmt->height);
+ return rc;
+}
+
+int mm_app_set_snapshot_fmt(int cam_id,mm_camera_image_fmt_t *fmt)
+{
+
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+ fmt->meta_header = MM_CAMEAR_META_DATA_TYPE_DEF;
+ fmt->fmt = pme->dim.main_img_format;
+ fmt->width = pme->dim.picture_width;
+ fmt->height = pme->dim.picture_height;
+ CDBG("Snapshot Dimension = %dX%d",fmt->width,fmt->height);
+ return rc;
+}
+
+int mm_app_set_live_snapshot_fmt(int cam_id,mm_camera_image_fmt_t *fmt)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+ fmt->meta_header = MM_CAMEAR_META_DATA_TYPE_DEF;
+ fmt->fmt = pme->dim.enc_format;
+ fmt->width = pme->dim.video_width;
+ fmt->height = pme->dim.video_height;
+ CDBG("Livesnapshot Dimension = %dX%d",fmt->width,fmt->height);
+ return rc;
+}
+
+int mm_app_set_raw_snapshot_fmt(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+#if 0
+ /* now we hard code format */
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ mm_camera_ch_image_fmt_parm_t fmt;
+
+ CDBG("%s: BEGIN\n", __func__);
+ memset(&fmt, 0, sizeof(mm_camera_ch_image_fmt_parm_t));
+ fmt.ch_type = MM_CAMERA_CH_RAW;
+ fmt.def.fmt = CAMERA_BAYER_SBGGR10;
+ fmt.def.dim.width = pme->dim.raw_picture_width;
+ fmt.def.dim.height = pme->dim.raw_picture_height;
+ rc = pme->cam->cfg->set_parm(pme->cam, MM_CAMERA_PARM_CH_IMAGE_FMT, &fmt);
+ if (rc != MM_CAMERA_OK) {
+ CDBG("%s:set raw snapshot format err=%d\n", __func__, rc);
+ }
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+#endif
+ return rc;
+}
+
+int mm_app_prepare_raw_snapshot_buf(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+#if 0
+ int j;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+ mm_camera_reg_buf_t reg_buf;
+ uint32_t y_off, cbcr_off;
+ uint8_t num_planes_main;
+ uint32_t planes_main[VIDEO_MAX_PLANES];
+
+ CDBG("%s: BEGIN, raw_w=%d, raw_h=%d\n",
+ __func__, pme->dim.raw_picture_width, pme->dim.raw_picture_height);
+ memset(®_buf, 0, sizeof(reg_buf));
+ reg_buf.def.buf.mp = malloc(sizeof(mm_camera_mp_buf_t));
+ if (!reg_buf.def.buf.mp) {
+ CDBG_ERROR("%s Error allocating memory for mplanar struct ", __func__);
+ rc = -MM_CAMERA_E_NO_MEMORY;
+ goto end;
+ }
+
+ // setup main buffer
+ memset(&pme->raw_snapshot_buf, 0, sizeof(pme->raw_snapshot_buf));
+ pme->raw_snapshot_buf.num = 1;
+ pme->raw_snapshot_buf.frame_len =
+ my_cam_app.hal_lib.mm_camera_get_msm_frame_len(CAMERA_BAYER_SBGGR10,
+ CAMERA_MODE_2D,
+ pme->dim.raw_picture_width,
+ pme->dim.raw_picture_height,
+ OUTPUT_TYPE_S,
+ &num_planes_main,
+ planes_main);
+#ifdef USE_ION
+ pme->raw_snapshot_buf.frame[0].ion_alloc.len = pme->raw_snapshot_buf.frame_len;
+ pme->raw_snapshot_buf.frame[0].ion_alloc.flags = (0x1 << CAMERA_ION_HEAP_ID);
+ pme->raw_snapshot_buf.frame[0].ion_alloc.align = 4096;
+#endif
+ pme->raw_snapshot_buf.frame[0].buffer = (unsigned long) my_cam_app.hal_lib.mm_camera_do_mmap(
+ pme->raw_snapshot_buf.frame_len, &pme->raw_snapshot_buf.frame[0].fd);
+
+
+ if (!pme->raw_snapshot_buf.frame[0].buffer) {
+ CDBG("%s:no mem for snapshot buf\n", __func__);
+ rc = -MM_CAMERA_E_NO_MEMORY;
+ goto end;
+ }
+ pme->raw_snapshot_buf.frame[0].path = OUTPUT_TYPE_S;
+ pme->preview_buf.frame[0].y_off = 0;
+ pme->raw_snapshot_buf.frame[0].cbcr_off = planes_main[0];
+
+ /*setup registration buffer*/
+ reg_buf.def.buf.mp[0].frame = pme->raw_snapshot_buf.frame[0];
+ reg_buf.def.buf.mp[0].frame_offset = 0;
+ reg_buf.def.buf.mp[0].num_planes = num_planes_main;
+
+ reg_buf.def.buf.mp[0].planes[0].length = planes_main[0];
+ reg_buf.def.buf.mp[0].planes[0].m.userptr = pme->raw_snapshot_buf.frame[0].fd;
+ reg_buf.def.buf.mp[0].planes[0].data_offset = 0;
+ reg_buf.def.buf.mp[0].planes[0].reserved[0] = reg_buf.def.buf.mp[0].frame_offset;
+ for (j = 1; j < num_planes_main; j++) {
+ reg_buf.def.buf.mp[0].planes[j].length = planes_main[j];
+ reg_buf.def.buf.mp[0].planes[j].m.userptr = pme->raw_snapshot_buf.frame[0].fd;
+ reg_buf.def.buf.mp[0].planes[j].data_offset = 0;
+ reg_buf.def.buf.mp[0].planes[j].reserved[0] = reg_buf.def.buf.mp[0].planes[j-1].reserved[0] +
+ reg_buf.def.buf.mp[0].planes[j-1].length;
+ }
+
+ reg_buf.ch_type = MM_CAMERA_CH_RAW;
+ reg_buf.def.num = pme->raw_snapshot_buf.num;
+ rc = pme->cam->cfg->prepare_buf(pme->cam, ®_buf);
+ if (rc != MM_CAMERA_OK) {
+ CDBG("%s:reg snapshot buf err=%d\n", __func__, rc);
+ goto end;
+ }
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+#endif
+ return rc;
+}
+
+static int mm_app_unprepare_raw_snapshot_buf(int cam_id)
+{
+ int i, rc = MM_CAMERA_OK;
+#if 0
+ /* now we hard code format */
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("%s: BEGIN\n", __func__);
+ rc = pme->cam->cfg->unprepare_buf(pme->cam, MM_CAMERA_CH_RAW);
+ rc = my_cam_app.hal_lib.mm_camera_do_munmap(pme->raw_snapshot_buf.frame[0].fd,
+ (void *)pme->raw_snapshot_buf.frame[0].buffer,
+ pme->raw_snapshot_buf.frame_len);
+ rc = my_cam_app.hal_lib.mm_camera_do_munmap(pme->jpeg_buf.frame[0].fd,
+ (void *)pme->jpeg_buf.frame[0].buffer,
+ pme->jpeg_buf.frame_len);
+ /* zero out the buf stuct */
+ memset(&pme->raw_snapshot_buf, 0, sizeof(pme->raw_snapshot_buf));
+ memset(&pme->jpeg_buf, 0, sizeof(pme->jpeg_buf));
+
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+#endif
+ return rc;
+}
+
+#ifndef DISABLE_JPEG_ENCODING
+/* Once we give frame for encoding, we get encoded jpeg image
+ fragments by fragment. We'll need to store them in a buffer
+ to form complete JPEG image */
+static void snapshot_jpeg_fragment_cb(uint8_t *ptr,
+ uint32_t size,
+ void *user_data)
+{
+#if 0
+ mm_camera_app_obj_t *pme = user_data;
+
+ CDBG("%s: E",__func__);
+ if (pme) {
+ memcpy((uint8_t *)((uint32_t)pme->jpeg_buf.frame[0].buffer + JpegOffset), ptr, size);
+ JpegOffset += size;
+ }
+ CDBG("%s: X",__func__);
+#endif
+}
+#endif
+/* This callback is received once the complete JPEG encoding is done */
+static void snapshot_raw_cb(mm_camera_super_buf_t *bufs,
+ void *user_data)
+{
+
+ int rc;
+ int i = 0;
+ mm_camera_buf_def_t *main_frame = NULL;
+ mm_camera_buf_def_t *thumb_frame = NULL;
+ mm_camera_app_obj_t *pme = NULL;
+ CDBG("%s: BEGIN\n", __func__);
+
+ pme = (mm_camera_app_obj_t *)user_data;
+
+ CDBG("%s : total streams = %d",__func__,bufs->num_bufs);
+ main_frame = bufs->bufs[0];
+ thumb_frame = bufs->bufs[1];
+
+ CDBG("mainframe frame_idx = %d fd = %d frame length = %d",main_frame->frame_idx,main_frame->fd,main_frame->frame_len);
+ CDBG("thumnail frame_idx = %d fd = %d frame length = %d",thumb_frame->frame_idx,thumb_frame->fd,thumb_frame->frame_len);
+
+ //dumpFrameToFile(main_frame->frame,pme->dim.picture_width,pme->dim.picture_height,"main", 1);
+ //dumpFrameToFile(thumb_frame->frame,pme->dim.thumbnail_width,pme->dim.thumbnail_height,"thumb", 1);
+
+ dumpFrameToFile(main_frame,pme->dim.picture_width,pme->dim.picture_height,"main", 1);
+ dumpFrameToFile(thumb_frame,pme->dim.thumbnail_width,pme->dim.thumbnail_height,"thumb", 1);
+
+ if (MM_CAMERA_OK != pme->cam->ops->qbuf(pme->cam->camera_handle,pme->ch_id,main_frame)) {
+ CDBG_ERROR("%s: Failed in thumbnail Qbuf\n", __func__);
+ }
+ if (MM_CAMERA_OK != pme->cam->ops->qbuf(pme->cam->camera_handle,pme->ch_id,thumb_frame)) {
+ CDBG_ERROR("%s: Failed in thumbnail Qbuf\n", __func__);
+ }
+
+ mm_app_snapshot_done();
+ CDBG("%s: END\n", __func__);
+
+
+}
+
+#ifndef DISABLE_JPEG_ENCODING
+static int encodeData(mm_camera_super_buf_t* recvd_frame,
+ int frame_len,
+ int enqueued,
+ mm_camera_app_obj_t *pme)
+{
+ int ret = -1;
+#if 0
+
+ cam_ctrl_dimension_t dimension;
+ struct msm_frame *postviewframe;
+ struct msm_frame *mainframe;
+ common_crop_t crop;
+ cam_point_t main_crop_offset;
+ cam_point_t thumb_crop_offset;
+ int width, height;
+ uint8_t *thumbnail_buf;
+ uint32_t thumbnail_fd;
+
+ omx_jpeg_encode_params encode_params;
+ postviewframe = recvd_frame->snapshot.thumbnail.frame;
+ mainframe = recvd_frame->snapshot.main.frame;
+ dimension.orig_picture_dx = pme->dim.picture_width;
+ dimension.orig_picture_dy = pme->dim.picture_height;
+ dimension.thumbnail_width = pme->dim.ui_thumbnail_width;
+ dimension.thumbnail_height = pme->dim.ui_thumbnail_height;
+ dimension.main_img_format = pme->dim.main_img_format;
+ dimension.thumb_format = pme->dim.thumb_format;
+
+ CDBG("Setting callbacks, initializing encoder and start encoding.");
+ my_cam_app.hal_lib.set_callbacks(snapshot_jpeg_fragment_cb, snapshot_jpeg_cb, pme,
+ (void *)pme->jpeg_buf.frame[0].buffer, &JpegOffset);
+ my_cam_app.hal_lib.omxJpegStart();
+ my_cam_app.hal_lib.mm_jpeg_encoder_setMainImageQuality(85);
+
+ /*TBD: Pass 0 as cropinfo for now as v4l2 doesn't provide
+ cropinfo. It'll be changed later.*/
+ memset(&crop,0,sizeof(common_crop_t));
+ memset(&main_crop_offset,0,sizeof(cam_point_t));
+ memset(&thumb_crop_offset,0,sizeof(cam_point_t));
+
+ /*Fill in the encode parameters*/
+ encode_params.dimension = (const cam_ctrl_dimension_t *)&dimension;
+ encode_params.thumbnail_buf = (uint8_t *)postviewframe->buffer;
+ encode_params.thumbnail_fd = postviewframe->fd;
+ encode_params.thumbnail_offset = postviewframe->phy_offset;
+ encode_params.snapshot_buf = (uint8_t *)mainframe->buffer;
+ encode_params.snapshot_fd = mainframe->fd;
+ encode_params.snapshot_offset = mainframe->phy_offset;
+ encode_params.scaling_params = &crop;
+ encode_params.exif_data = NULL;
+ encode_params.exif_numEntries = 0;
+ encode_params.a_cbcroffset = -1;
+ encode_params.main_crop_offset = &main_crop_offset;
+ encode_params.thumb_crop_offset = &thumb_crop_offset;
+
+ if (!my_cam_app.hal_lib.omxJpegEncode(&encode_params)) {
+ CDBG_ERROR("%s: Failure! JPEG encoder returned error.", __func__);
+ ret = -1;
+ goto end;
+ }
+
+ /* Save the pointer to the frame sent for encoding. we'll need it to
+ tell kernel that we are done with the frame.*/
+ mCurrentFrameEncoded = recvd_frame;
+
+ end:
+ CDBG("%s: X", __func__);
+#endif
+ return ret;
+}
+
+static int encodeDisplayAndSave(mm_camera_super_buf_t* recvd_frame,
+ int enqueued, mm_camera_app_obj_t *pme)
+{
+ int ret = -1;
+#if 0
+
+
+ CDBG("%s: Send frame for encoding", __func__);
+ ret = encodeData(recvd_frame, pme->snapshot_buf.frame_len,
+ enqueued, pme);
+ if (!ret) {
+ CDBG_ERROR("%s: Failure configuring JPEG encoder", __func__);
+ }
+
+ LOGD("%s: X", __func__);
+#endif
+ return ret;
+}
+#endif //DISABLE_JPEG_ENCODING
+static void mm_app_snapshot_notify_cb(mm_camera_super_buf_t *bufs,
+ void *user_data)
+{
+#if 0
+ mm_camera_app_obj_t *pme = user_data;
+ int rc;
+
+ CDBG("%s: BEGIN\n", __func__);
+ snapshot_cnt++;
+ mm_app_dump_snapshot_frame(bufs->snapshot.main.frame, pme->snapshot_buf.frame_len, TRUE, 0);
+ mm_app_dump_snapshot_frame(bufs->snapshot.thumbnail.frame, pme->thumbnail_buf.frame_len, FALSE, 0);
+#ifndef DISABLE_JPEG_ENCODING
+ /* The recvd_frame structre we receive from lower library is a local
+variable. So we'll need to save this structure so that we won't
+be later pointing to garbage data when that variable goes out of
+scope */
+ mm_camera_ch_data_buf_t* frame =
+ (mm_camera_ch_data_buf_t *)malloc(sizeof(mm_camera_ch_data_buf_t));
+ if (frame == NULL) {
+ CDBG_ERROR("%s: Error allocating memory to save received_frame structure.", __func__);
+ goto error1;
+ }
+ memcpy(frame, bufs, sizeof(mm_camera_ch_data_buf_t));
+ rc = encodeDisplayAndSave(frame, 0, pme);
+ if (!rc) {
+ CDBG_ERROR("%s: Error encoding buffer.", __func__);
+ goto error;
+ }
+#endif //DISABLE_JPEG_ENCODING
+ /* return buffer back for taking next snapshot */
+ pme->cam->evt->buf_done(pme->cam, bufs);
+ mm_app_snapshot_done();
+/*
+ CDBG("%s: calling mm_app_snapshot_done()\n", __func__);
+ mm_app_snapshot_done();
+*/
+ CDBG("%s: END\n", __func__);
+ return;
+ error:
+ /*if (frame != NULL)
+ free(frame);*/
+ error1:
+ pme->cam->evt->buf_done(pme->cam, bufs);
+ mm_app_snapshot_done();
+#endif
+ return;
+}
+
+static void mm_app_raw_snapshot_notify_cb(mm_camera_super_buf_t *bufs,
+ void *user_data)
+{
+#if 0
+ mm_camera_app_obj_t *pme = user_data;
+ static int loop = 0;
+
+ CDBG("%s: BEGIN\n", __func__);
+ raw_snapshot_cnt++;
+ mm_app_dump_snapshot_frame(bufs->def.frame, pme->raw_snapshot_buf.frame_len, TRUE, 1);
+ /* return buffer back for taking next snapshot */
+ pme->cam->evt->buf_done(pme->cam, bufs);
+ CDBG("%s: calling mm_app_snapshot_done()\n", __func__);
+ mm_app_snapshot_done();
+ CDBG("%s: END\n", __func__);
+#endif
+}
+static int mm_app_reg_snapshot_data_cb(int cam_id, int is_reg)
+{
+ int rc = MM_CAMERA_OK;
+#if 0
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+
+ CDBG("%s: BEGIN\n", __func__);
+ if (is_reg) {
+ rc = pme->cam->evt->register_buf_notify(pme->cam,
+ MM_CAMERA_CH_SNAPSHOT,
+ mm_app_snapshot_notify_cb,
+ MM_CAMERA_REG_BUF_CB_INFINITE, 0,
+ pme);
+ if (rc != MM_CAMERA_OK) {
+ CDBG("%s:register snapshot data notify cb err=%d\n",
+ __func__, rc);
+ goto end;
+ }
+ } else {
+ rc = pme->cam->evt->register_buf_notify(pme->cam,
+ MM_CAMERA_CH_SNAPSHOT,
+ NULL,
+ (mm_camera_register_buf_cb_type_t)NULL,
+ 0, pme);
+ if (rc != MM_CAMERA_OK) {
+ CDBG("%s:unregister snapshot data notify cb err=%d\n",
+ __func__, rc);
+ goto end;
+ }
+ }
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+#endif
+ return rc;
+}
+static int mm_app_reg_raw_snapshot_data_cb(int cam_id, int is_reg)
+{
+ int rc = MM_CAMERA_OK;
+#if 0
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+
+ CDBG("%s: BEGIN\n", __func__);
+ if (is_reg) {
+ rc = pme->cam->evt->register_buf_notify(pme->cam,
+ MM_CAMERA_CH_RAW,
+ mm_app_raw_snapshot_notify_cb,
+ MM_CAMERA_REG_BUF_CB_INFINITE, 0,
+ pme);
+ if (rc != MM_CAMERA_OK) {
+ CDBG("%s:register raw snapshot data notify cb err=%d\n",
+ __func__, rc);
+ goto end;
+ }
+ } else {
+ rc = pme->cam->evt->register_buf_notify(pme->cam,
+ MM_CAMERA_CH_RAW,
+ NULL,
+ (mm_camera_register_buf_cb_type_t)NULL, 0, pme);
+ if (rc != MM_CAMERA_OK) {
+ CDBG("%s:unregister raw snapshot data notify cb err=%d\n",
+ __func__, rc);
+ goto end;
+ }
+ }
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+#endif
+ return rc;
+}
+
+int mm_app_add_snapshot_stream(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id = pme->cam->ops->add_stream(pme->cam->camera_handle,pme->ch_id,
+ NULL,pme,
+ MM_CAMERA_SNAPSHOT_MAIN, 0);
+
+ CDBG("Add Snapshot main is successfull stream ID = %d",pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id);
+ if (!pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id) {
+ CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+ pme->stream[MM_CAMERA_SNAPSHOT_THUMBNAIL].id = pme->cam->ops->add_stream(pme->cam->camera_handle,pme->ch_id,
+ NULL,pme,
+ MM_CAMERA_SNAPSHOT_THUMBNAIL, 0);
+ if (!pme->stream[MM_CAMERA_SNAPSHOT_THUMBNAIL].id) {
+ CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
+ rc = -1;
+ goto end;
+ }
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+void mm_app_set_snapshot_mode(int cam_id,int op_mode)
+{
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+ pme->cam->ops->set_parm(pme->cam->camera_handle,MM_CAMERA_PARM_OP_MODE, &op_mode);
+
+}
+
+int mm_app_config_snapshot_format(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ mm_app_set_snapshot_fmt(cam_id,&pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config.fmt);
+
+ mm_app_set_thumbnail_fmt(cam_id,&pme->stream[MM_CAMERA_SNAPSHOT_THUMBNAIL].str_config.fmt);
+
+ pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config.need_stream_on = 1;
+ pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config.num_of_bufs = 1;
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->config_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id,
+ &pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config))) {
+ CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ pme->stream[MM_CAMERA_SNAPSHOT_THUMBNAIL].str_config.need_stream_on = 1;
+ pme->stream[MM_CAMERA_SNAPSHOT_THUMBNAIL].str_config.num_of_bufs = 1;
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->config_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_SNAPSHOT_THUMBNAIL].id,
+ &pme->stream[MM_CAMERA_SNAPSHOT_THUMBNAIL].str_config))) {
+ CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
+ goto end;
+ }
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+
+}
+
+int mm_app_streamon_snapshot(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int stream[2];
+ mm_camera_bundle_attr_t attr;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ stream[0] = pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id;
+ stream[1] = pme->stream[MM_CAMERA_SNAPSHOT_THUMBNAIL].id;
+
+ attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
+ attr.burst_num = 1;
+ attr.look_back = 2;
+ attr.post_frame_skip = 0;
+ attr.water_mark = 2;
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->init_stream_bundle(
+ pme->cam->camera_handle,pme->ch_id,snapshot_raw_cb,pme,&attr,2,stream))) {
+ CDBG_ERROR("%s:init_stream_bundle err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->start_streams(pme->cam->camera_handle,pme->ch_id,
+ 2, stream))) {
+ CDBG_ERROR("%s:start_streams err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ if (MM_CAMERA_OK != (rc =pme->cam->ops->request_super_buf(pme->cam->camera_handle,pme->ch_id))) {
+ CDBG_ERROR("%s:request_super_buf err=%d\n", __func__, rc);
+ goto end;
+ }
+ pme->cam_state = CAMERA_STATE_SNAPSHOT;
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_streamoff_snapshot(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int stream[2];
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ stream[0] = pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id;
+ stream[1] = pme->stream[MM_CAMERA_SNAPSHOT_THUMBNAIL].id;
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->stop_streams(pme->cam->camera_handle,pme->ch_id,2,&stream))) {
+ CDBG_ERROR("%s : Snapshot Stream off Error",__func__);
+ goto end;
+ }
+ CDBG("Stop snapshot main successfull");
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->destroy_stream_bundle(pme->cam->camera_handle,pme->ch_id))) {
+ CDBG_ERROR("%s : Snapshot destroy_stream_bundle Error",__func__);
+ goto end;
+ }
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->del_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id))) {
+ CDBG_ERROR("%s : Snapshot main image del_stream Error",__func__);
+ goto end;
+ }
+ CDBG("del_stream successfull");
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->del_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_SNAPSHOT_THUMBNAIL].id))) {
+ CDBG_ERROR("%s : Snapshot thumnail image del_stream Error",__func__);
+ goto end;
+ }
+ CDBG("del_stream successfull");
+
+ end:
+ return rc;
+}
+
+int mm_app_start_snapshot(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int stream[2];
+ int op_mode = 0;
+
+ mm_camera_bundle_attr_t attr;
+
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ if (MM_CAMERA_OK != mm_app_stop_preview(cam_id)) {
+ CDBG_ERROR("%s: Stop preview Failed cam_id=%d\n",__func__,cam_id);
+ return -1;
+ }
+
+ op_mode = MM_CAMERA_OP_MODE_CAPTURE;
+ mm_app_set_snapshot_mode(cam_id,op_mode);
+
+ pme->cam->ops->prepare_snapshot(pme->cam->camera_handle,pme->ch_id,0);
+
+ if (MM_CAMERA_OK != (rc = mm_app_add_snapshot_stream(cam_id))) {
+ CDBG_ERROR("%s : Add Snapshot stream err",__func__);
+ }
+
+ if (MM_CAMERA_OK != (rc = mm_app_config_snapshot_format(cam_id))) {
+ CDBG_ERROR("%s : Config Snapshot stream err",__func__);
+ }
+
+ if (MM_CAMERA_OK != (rc = mm_app_streamon_snapshot(cam_id))) {
+ CDBG_ERROR("%s : Stream on Snapshot stream err",__func__);
+ }
+
+#if 0
+ /*start OMX Jpeg encoder*/
+#ifndef DISABLE_JPEG_ENCODING
+ my_cam_app.hal_lib.omxJpegOpen();
+#endif
+
+#endif
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+
+ return rc;
+}
+
+
+int mm_app_stop_snapshot(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int stream[2];
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ stream[0] = pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id;
+ stream[1] = pme->stream[MM_CAMERA_SNAPSHOT_THUMBNAIL].id;
+
+ if (MM_CAMERA_OK != (rc = mm_app_streamoff_snapshot(cam_id))) {
+ CDBG_ERROR("%s : Stream off Snapshot stream err",__func__);
+ }
+ pme->cam_state = CAMERA_STATE_OPEN;
+#if 0
+#ifndef DISABLE_JPEG_ENCODING
+ my_cam_app.hal_lib.omxJpegClose();
+#endif
+#endif
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+
+ return rc;
+}
+
+int mm_app_start_raw_snapshot(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+#if 0
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+ mm_camera_channel_attr_t attr;
+
+
+ attr.type = MM_CAMERA_CH_ATTR_RAW_STREAMING_TYPE;
+ attr.raw_streaming_mode = MM_CAMERA_RAW_STREAMING_CAPTURE_SINGLE;
+
+ if (MM_CAMERA_OK != (rc = mm_app_set_op_mode(cam_id, MM_CAMERA_OP_MODE_CAPTURE))) {
+ CDBG("%s:mm_app_set_op_mode(op_mode=%d) err=%d\n", __func__,
+ MM_CAMERA_OP_MODE_CAPTURE, rc);
+ goto end;
+ }
+ if (MM_CAMERA_OK != (rc = mm_app_open_ch(cam_id, MM_CAMERA_CH_RAW))) {
+ CDBG("%s:open raw snapshot channel err=%d\n", __func__, rc);
+ goto end;
+ }
+ if (MM_CAMERA_OK != (rc = mm_app_set_raw_snapshot_fmt(cam_id))) {
+ CDBG("%s:set raw snapshot format err=%d\n", __func__, rc);
+ goto end;
+ }
+ mm_app_get_dim(cam_id, NULL);
+ if (MM_CAMERA_OK != (rc = mm_app_prepare_raw_snapshot_buf(cam_id))) {
+ CDBG("%s:reg raw snapshot buf err=%d\n", __func__, rc);
+ goto end;
+ }
+ if (MM_CAMERA_OK != (rc = mm_app_reg_raw_snapshot_data_cb(cam_id, TRUE))) {
+ CDBG("%s:reg raw snapshot data cb err=%d\n", __func__, rc);
+ }
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->ch_set_attr(pme->cam, MM_CAMERA_CH_RAW, &attr))) {
+ CDBG("%s:set raw capture attribute err=%d\n", __func__, rc);
+ goto end;
+ }
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->action(pme->cam, TRUE, MM_CAMERA_OPS_RAW, 0))) {
+ CDBG("%s:snapshot streaming err=%d\n", __func__, rc);
+ goto end;
+ }
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+#endif
+ return rc;
+}
+
+int mm_app_stop_raw_snapshot(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+#if 0
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+
+ CDBG("%s: BEGIN\n", __func__);
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->action(pme->cam, FALSE, MM_CAMERA_OPS_RAW, 0))) {
+ CDBG("%s:stop raw snapshot streaming err=%d\n", __func__, rc);
+ goto end;
+ }
+ if (MM_CAMERA_OK != (rc = mm_app_unprepare_raw_snapshot_buf(cam_id))) {
+ CDBG("%s:mm_app_unprepare_raw_snapshot_buf err=%d\n", __func__, rc);
+ return rc;
+ }
+ if (MM_CAMERA_OK != (rc = mm_app_reg_raw_snapshot_data_cb(cam_id, FALSE))) {
+ CDBG("%s:mm_app_reg_raw_snapshot_data_cb err=%d\n", __func__, rc);
+ return rc;
+ }
+ mm_app_close_ch(cam_id, MM_CAMERA_CH_RAW);
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+#endif
+ return rc;
+}
+
+static void mm_app_snapshot_wait(int cam_id)
+{
+ pthread_mutex_lock(&g_s_mutex);
+ if (FALSE == g_status) {
+ pthread_cond_wait(&g_s_cond_v, &g_s_mutex);
+ g_status = FALSE;
+ }
+ pthread_mutex_unlock(&g_s_mutex);
+}
+
+#if 0
+int mm_stream_deinit_thumbnail_buf(uint32_t camera_handle,
+ uint32_t ch_id, uint32_t stream_id,
+ void *user_data, uint8_t num_bufs,
+ mm_camera_buf_def_t *bufs)
+{
+ int i, rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
+
+ for (i = 0; i < num_bufs; i++) {
+ rc = my_cam_app.hal_lib.mm_camera_do_munmap_ion (pme->ionfd, &(pme->thumbnail_buf.frame[i].fd_data),
+ (void *)pme->thumbnail_buf.frame[i].buffer, pme->thumbnail_buf.frame_len);
+ if (rc != MM_CAMERA_OK) {
+ CDBG("%s: mm_camera_do_munmap err, pmem_fd = %d, rc = %d",
+ __func__, bufs[i].fd, rc);
+ }
+ }
+ return rc;
+}
+
+int mm_stream_deinit_main_buf(uint32_t camera_handle,
+ uint32_t ch_id, uint32_t stream_id,
+ void *user_data, uint8_t num_bufs,
+ mm_camera_buf_def_t *bufs)
+{
+ int i, rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
+
+ for (i = 0; i < num_bufs; i++) {
+ rc = my_cam_app.hal_lib.mm_camera_do_munmap_ion (pme->ionfd, &(pme->snapshot_buf.frame[i].fd_data),
+ (void *)pme->snapshot_buf.frame[i].buffer, pme->snapshot_buf.frame_len);
+ if (rc != MM_CAMERA_OK) {
+ CDBG("%s: mm_camera_do_munmap err, pmem_fd = %d, rc = %d",
+ __func__, bufs[i].fd, rc);
+ }
+ }
+ return rc;
+}
+
+int mm_stream_init_main_buf(uint32_t camera_handle,
+ uint32_t ch_id, uint32_t stream_id,
+ void *user_data,
+ mm_camera_frame_len_offset *frame_offset_info,
+ uint8_t num_bufs,
+ uint8_t *initial_reg_flag,
+ mm_camera_buf_def_t *bufs)
+{
+ int i,j,num_planes, frame_len, y_off, cbcr_off;
+ uint32_t planes[VIDEO_MAX_PLANES];
+ uint32_t pmem_addr = 0;
+
+ mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
+
+ num_planes = frame_offset_info->num_planes;
+ for ( i = 0; i < num_planes; i++) {
+ planes[i] = frame_offset_info->mp[i].len;
+ }
+
+ frame_len = frame_offset_info->frame_len;
+ y_off = frame_offset_info->mp[0].offset;
+ cbcr_off = frame_offset_info->mp[1].offset;
+
+ CDBG("Allocating main image Memory for %d buffers frame_len = %d",num_bufs,frame_offset_info->frame_len);
+
+ for (i = 0; i < num_bufs ; i++) {
+ int j;
+ if (pme->cam_mode != RECORDER_MODE || pme->fullSizeSnapshot) {
+ pme->snapshot_buf.reg[i] = 1;
+ initial_reg_flag[i] = 1;
+ } else {
+ pme->snapshot_buf.reg[i] = 0;
+ initial_reg_flag[i] = 0;
+ }
+
+ pme->snapshot_buf.frame_len = frame_len;
+
+ pme->snapshot_buf.frame[i].ion_alloc.len = pme->snapshot_buf.frame_len;
+ pme->snapshot_buf.frame[i].ion_alloc.flags =
+ (0x1 << CAMERA_ION_HEAP_ID | 0x1 << ION_IOMMU_HEAP_ID);
+ pme->snapshot_buf.frame[i].ion_alloc.align = 4096;
+
+ pmem_addr = (unsigned long) my_cam_app.hal_lib.mm_camera_do_mmap_ion(pme->ionfd,
+ &(pme->snapshot_buf.frame[i].ion_alloc), &(pme->snapshot_buf.frame[i].fd_data),
+ &pme->snapshot_buf.frame[i].fd);
+
+ pme->snapshot_buf.frame[i].buffer = pmem_addr;
+ pme->snapshot_buf.frame[i].path = OUTPUT_TYPE_S;
+ pme->snapshot_buf.frame[i].y_off = 0;
+ pme->snapshot_buf.frame[i].cbcr_off = planes[0];
+ pme->snapshot_buf.frame[i].phy_offset = 0;
+
+ CDBG("Buffer allocated Successfully fd = %d",pme->snapshot_buf.frame[i].fd);
+
+ bufs[i].fd = pme->snapshot_buf.frame[i].fd;
+ //bufs[i].buffer = pmem_addr;
+ bufs[i].frame_len = pme->snapshot_buf.frame[i].ion_alloc.len;
+ bufs[i].num_planes = num_planes;
+
+ bufs[i].frame = &pme->snapshot_buf.frame[i];
+
+ /* Plane 0 needs to be set seperately. Set other planes
+ * in a loop. */
+ bufs[i].planes[0].length = planes[0];
+ bufs[i].planes[0].m.userptr = bufs[i].fd;
+ bufs[i].planes[0].data_offset = y_off;
+ bufs[i].planes[0].reserved[0] = 0;
+ //buf_def->buf.mp[i].frame_offset;
+ for (j = 1; j < num_planes; j++) {
+ bufs[i].planes[j].length = planes[j];
+ bufs[i].planes[j].m.userptr = bufs[i].fd;
+ bufs[i].planes[j].data_offset = cbcr_off;
+ bufs[i].planes[j].reserved[0] =
+ bufs[i].planes[j-1].reserved[0] +
+ bufs[i].planes[j-1].length;
+ }
+ }
+ return MM_CAMERA_OK;
+}
+
+int mm_stream_init_thumbnail_buf(uint32_t camera_handle,
+ uint32_t ch_id, uint32_t stream_id,
+ void *user_data,
+ mm_camera_frame_len_offset *frame_offset_info,
+ uint8_t num_bufs,
+ uint8_t *initial_reg_flag,
+ mm_camera_buf_def_t *bufs)
+{
+ int i,j,num_planes, frame_len, y_off, cbcr_off;
+ uint32_t planes[VIDEO_MAX_PLANES];
+ uint32_t pmem_addr = 0;
+
+ mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
+
+ num_planes = frame_offset_info->num_planes;
+ for ( i = 0; i < num_planes; i++) {
+ planes[i] = frame_offset_info->mp[i].len;
+ }
+
+ frame_len = frame_offset_info->frame_len;
+ y_off = frame_offset_info->mp[0].offset;
+ cbcr_off = frame_offset_info->mp[1].offset;
+
+ CDBG("Allocating thumanail image Memory for %d buffers frame_len = %d",num_bufs,frame_offset_info->frame_len);
+
+ for (i = 0; i < num_bufs ; i++) {
+ int j;
+ pme->thumbnail_buf.reg[i] = 1;
+ initial_reg_flag[i] = 1;
+
+ pme->thumbnail_buf.frame_len = frame_len;
+ pme->thumbnail_buf.frame[i].ion_alloc.len = pme->thumbnail_buf.frame_len;
+ pme->thumbnail_buf.frame[i].ion_alloc.flags =
+ (0x1 << CAMERA_ION_HEAP_ID | 0x1 << ION_IOMMU_HEAP_ID);
+ pme->thumbnail_buf.frame[i].ion_alloc.align = 4096;
+
+ pmem_addr = (unsigned long) my_cam_app.hal_lib.mm_camera_do_mmap_ion(pme->ionfd,
+ &(pme->thumbnail_buf.frame[i].ion_alloc), &(pme->thumbnail_buf.frame[i].fd_data),
+ &pme->thumbnail_buf.frame[i].fd);
+
+ pme->thumbnail_buf.frame[i].buffer = pmem_addr;
+ pme->thumbnail_buf.frame[i].path = OUTPUT_TYPE_S;
+ pme->thumbnail_buf.frame[i].y_off = 0;
+ pme->thumbnail_buf.frame[i].cbcr_off = planes[0];
+ pme->thumbnail_buf.frame[i].phy_offset = 0;
+
+ CDBG("Buffer allocated Successfully fd = %d",pme->thumbnail_buf.frame[i].fd);
+
+ bufs[i].fd = pme->thumbnail_buf.frame[i].fd;
+ //bufs[i].buffer = pmem_addr;
+ bufs[i].frame_len = pme->thumbnail_buf.frame[i].ion_alloc.len;
+ bufs[i].num_planes = num_planes;
+
+ bufs[i].frame = &pme->thumbnail_buf.frame[i];
+
+ /* Plane 0 needs to be set seperately. Set other planes
+ * in a loop. */
+ bufs[i].planes[0].length = planes[0];
+ bufs[i].planes[0].m.userptr = bufs[i].fd;
+ bufs[i].planes[0].data_offset = y_off;
+ bufs[i].planes[0].reserved[0] = 0;
+ //buf_def->buf.mp[i].frame_offset;
+ for (j = 1; j < num_planes; j++) {
+ bufs[i].planes[j].length = planes[j];
+ bufs[i].planes[j].m.userptr = bufs[i].fd;
+ bufs[i].planes[j].data_offset = cbcr_off;
+ bufs[i].planes[j].reserved[0] =
+ bufs[i].planes[j-1].reserved[0] +
+ bufs[i].planes[j-1].length;
+ }
+ }
+ return MM_CAMERA_OK;
+}
+#endif
+#if 0
+int mm_app_bundle_zsl_stream(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int stream[3];
+ mm_camera_bundle_attr_t attr;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ stream[0] = pme->stream[MM_CAMERA_PREVIEW].id;
+ stream[1] = pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id;
+
+ attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
+ attr.burst_num = 1;
+ attr.look_back = 2;
+ attr.post_frame_skip = 0;
+ attr.water_mark = 2;
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->init_stream_bundle(
+ pme->cam->camera_handle,pme->ch_id,mm_app_zsl_notify_cb,pme,&attr,2,stream))) {
+ CDBG_ERROR("%s:init_stream_bundle err=%d\n", __func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->start_streams(pme->cam->camera_handle,pme->ch_id,
+ 2, stream))) {
+ CDBG_ERROR("%s:start_streams err=%d\n", __func__, rc);
+ rc = -1;
+ goto end;
+ }
+ end:
+ return rc;
+}
+#endif
+
+static void mm_app_live_notify_cb(mm_camera_super_buf_t *bufs,
+ void *user_data)
+{
+
+ int rc;
+ int i = 0;
+ mm_camera_buf_def_t *main_frame = NULL;
+ mm_camera_app_obj_t *pme = NULL;
+ CDBG("%s: BEGIN\n", __func__);
+
+ pme = (mm_camera_app_obj_t *)user_data;
+
+ CDBG("%s : total streams = %d",__func__,bufs->num_bufs);
+ main_frame = bufs->bufs[0];
+ //thumb_frame = bufs->bufs[1];
+
+ CDBG("mainframe frame_idx = %d fd = %d frame length = %d",main_frame->frame_idx,main_frame->fd,main_frame->frame_len);
+ //CDBG("thumnail frame_idx = %d fd = %d frame length = %d",thumb_frame->frame_idx,thumb_frame->fd,thumb_frame->frame_len);
+
+ //dumpFrameToFile(main_frame->frame,pme->dim.picture_width,pme->dim.picture_height,"main", 1);
+
+ dumpFrameToFile(main_frame,pme->dim.picture_width,pme->dim.picture_height,"liveshot_main", 1);
+
+ if (MM_CAMERA_OK != pme->cam->ops->qbuf(pme->cam->camera_handle,pme->ch_id,main_frame)) {
+ CDBG_ERROR("%s: Failed in thumbnail Qbuf\n", __func__);
+ }
+ /*if(MM_CAMERA_OK != pme->cam->ops->qbuf(pme->cam->camera_handle,pme->ch_id,thumb_frame))
+ {
+ CDBG_ERROR("%s: Failed in thumbnail Qbuf\n", __func__);
+ }*/
+
+ mm_app_snapshot_done();
+ CDBG("%s: END\n", __func__);
+
+
+}
+
+int mm_app_prepare_live_snapshot(int cam_id)
+{
+ int rc = 0;
+ int stream[1];
+ mm_camera_bundle_attr_t attr;
+ int value = 0;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+ CDBG("%s:BEGIN, cam_id=%d\n",__func__,cam_id);
+
+ stream[0] = pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id;
+ //stream[1] = pme->stream[MM_CAMERA_PREVIEW].id; //Need to clarify
+
+ attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_BURST;
+ attr.burst_num = 1;
+ attr.look_back = 2;
+ attr.post_frame_skip = 0;
+ attr.water_mark = 2;
+
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->set_parm(
+ pme->cam->camera_handle,MM_CAMERA_PARM_FULL_LIVESHOT, (void *)&value))) {
+ CDBG_ERROR("%s: set dimension err=%d\n", __func__, rc);
+ }
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->init_stream_bundle(
+ pme->cam->camera_handle,pme->ch_id,mm_app_live_notify_cb,pme,&attr,1,stream))) {
+ CDBG_ERROR("%s:init_stream_bundle err=%d\n", __func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->start_streams(pme->cam->camera_handle,pme->ch_id,
+ 1, stream))) {
+ CDBG_ERROR("%s:start_streams err=%d\n", __func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+
+ end:
+ CDBG("%s:END, cam_id=%d\n",__func__,cam_id);
+ return rc;
+}
+
+int mm_app_unprepare_live_snapshot(int cam_id)
+{
+ int rc = 0;
+ int stream[2];
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+ CDBG("%s:BEGIN, cam_id=%d\n",__func__,cam_id);
+
+ stream[0] = pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id;
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->stop_streams(pme->cam->camera_handle,pme->ch_id,1,&stream))) {
+ CDBG_ERROR("%s : Snapshot Stream off Error",__func__);
+ return -1;
+ }
+
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->destroy_stream_bundle(pme->cam->camera_handle,pme->ch_id))) {
+ CDBG_ERROR("%s : Snapshot destroy_stream_bundle Error",__func__);
+ return -1;
+ }
+ CDBG("%s:END, cam_id=%d\n",__func__,cam_id);
+ return rc;
+}
+
+int mm_app_take_live_snapshot(int cam_id)
+{
+ int rc = 0;
+ int stream[3];
+ mm_camera_bundle_attr_t attr;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("%s:BEGIN, cam_id=%d\n",__func__,cam_id);
+
+ if (pme->cam_mode == RECORDER_MODE &&
+ pme->cam_state == CAMERA_STATE_RECORD) {
+ //Code to get live shot
+ if (mm_app_prepare_live_snapshot(cam_id) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s: Failed prepare liveshot",__func__);
+ return -1;
+ }
+ if (MM_CAMERA_OK != (rc =pme->cam->ops->request_super_buf(pme->cam->camera_handle,pme->ch_id))) {
+ CDBG_ERROR("%s:request_super_buf err=%d\n", __func__, rc);
+ return -1;
+ }
+ CDBG("%s:waiting images\n",__func__);
+ mm_app_snapshot_wait(cam_id);
+
+ if (MM_CAMERA_OK !=mm_app_unprepare_live_snapshot(cam_id)) {
+ CDBG_ERROR("%s: Snapshot Stop error",__func__);
+ }
+
+ } else {
+ CDBG_ERROR("%s: Should not come here for liveshot",__func__);
+ }
+ return rc;
+}
+
+int mm_app_take_picture_zsl(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int value = 1;
+ int op_mode;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("%s: Take picture ZSL",__func__);
+
+ if (MM_CAMERA_OK != (rc =pme->cam->ops->request_super_buf(pme->cam->camera_handle,pme->ch_id))) {
+ CDBG_ERROR("%s:request_super_buf err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ CDBG("%s: Start ZSL Preview",__func__);
+
+ end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_take_picture_yuv(int cam_id)
+{
+ int rc;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("%s:BEGIN, cam_id=%d\n",__func__,cam_id);
+
+ if (MM_CAMERA_OK != mm_app_start_snapshot(cam_id)) {
+ CDBG_ERROR("%s: cam_id=%d\n",__func__,cam_id);
+ rc = -1;
+ goto end;
+ }
+
+ CDBG("%s:waiting images\n",__func__);
+ mm_app_snapshot_wait(cam_id);
+
+ if (MM_CAMERA_OK !=mm_app_stop_snapshot(cam_id)) {
+ CDBG_ERROR("%s: Snapshot Stop error",__func__);
+ }
+
+ preview:
+ if (MM_CAMERA_OK != (rc = mm_app_start_preview(cam_id))) {
+ CDBG("%s:preview start stream err=%d\n", __func__, rc);
+ }
+ end:
+ CDBG("%s:END, cam_id=%d\n",__func__,cam_id);
+ return rc;
+}
+
+int mm_app_take_zsl(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("%s:BEGIN, cam_id=%d\n",__func__,cam_id);
+
+ if (pme->cam_mode == RECORDER_MODE) {
+ switch (pme->cam_state) {
+ case CAMERA_STATE_RECORD:
+ if (MM_CAMERA_OK != mm_app_stop_video(cam_id)) {
+ CDBG_ERROR("%s:Cannot stop video err=%d\n", __func__, rc);
+ return -1;
+ }
+ case CAMERA_STATE_PREVIEW:
+ if (MM_CAMERA_OK != mm_app_open_zsl(cam_id)) {
+ CDBG_ERROR("%s: Cannot switch to camera mode=%d\n", __func__);
+ return -1;
+ }
+ break;
+ case CAMERA_STATE_SNAPSHOT:
+ default:
+ CDBG("%s: Cannot normal pciture in record mode\n", __func__);
+ break;
+ }
+ } else if (pme->cam_mode == CAMERA_MODE) {
+ switch (pme->cam_state) {
+ case CAMERA_STATE_PREVIEW:
+ mm_app_open_zsl(cam_id);
+ break;
+
+ case CAMERA_STATE_SNAPSHOT:
+ case CAMERA_STATE_RECORD:
+ default:
+ CDBG("%s: Cannot normal pciture in record mode\n", __func__);
+ break;
+ }
+ }
+
+ if (pme->cam_mode == ZSL_MODE && pme->cam_state == CAMERA_STATE_PREVIEW) {
+ mm_app_take_picture_zsl(cam_id);
+ }
+ return rc;
+}
+
+int mm_app_take_picture(int cam_id)
+{
+ int rc = 0;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("%s:BEGIN, cam_id=%d\n",__func__,cam_id);
+
+ if (pme->cam_mode == RECORDER_MODE) {
+ switch (pme->cam_state) {
+ case CAMERA_STATE_RECORD:
+ if (MM_CAMERA_OK != mm_app_stop_video(cam_id)) {
+ CDBG_ERROR("%s:Cannot stop video err=%d\n", __func__, rc);
+ return -1;
+ }
+ case CAMERA_STATE_PREVIEW:
+ if (MM_CAMERA_OK != mm_app_open_camera(cam_id)) {
+ CDBG_ERROR("%s: Cannot switch to camera mode=%d\n", __func__,rc);
+ return -1;
+ }
+ break;
+ case CAMERA_STATE_SNAPSHOT:
+ default:
+ CDBG("%s: Cannot normal pciture in record mode\n", __func__);
+ break;
+ }
+ } else if (pme->cam_mode == ZSL_MODE) {
+ switch (pme->cam_state) {
+ case CAMERA_STATE_PREVIEW:
+ mm_app_open_camera(cam_id);
+ break;
+
+ case CAMERA_STATE_SNAPSHOT:
+ case CAMERA_STATE_RECORD:
+ default:
+ CDBG("%s: Cannot normal pciture in record mode\n", __func__);
+ break;
+ }
+ }
+
+ CDBG("%s : Takepicture : mode = %d state = %d, rc = %d",__func__,pme->cam_mode,pme->cam_state,rc);
+ if (pme->cam_mode == CAMERA_MODE && pme->cam_state == CAMERA_STATE_PREVIEW) {
+ mm_app_take_picture_yuv(cam_id);
+ }
+ return rc;
+}
+
+int mm_app_take_raw_picture(int cam_id)
+{
+ int rc;
+#if 0
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("%s:BEGIN, cam_id=%d\n",__func__,cam_id);
+ g_status = FALSE;
+ if (MM_CAMERA_OK != (rc = pme->cam->ops->action(pme->cam, TRUE, MM_CAMERA_OPS_PREPARE_SNAPSHOT, 0))) {
+ CDBG("%s:prepare snapshot err=%d\n", __func__, rc);
+ goto end;
+ }
+ if (MM_CAMERA_OK != (rc = mm_app_stop_preview(cam_id))) {
+ CDBG("%s:mm_app_stop_preview err=%d\n", __func__, rc);
+ goto end;
+ }
+ if (MM_CAMERA_OK != mm_app_start_raw_snapshot(cam_id))
+ goto preview;
+ CDBG("%s:waiting images\n",__func__);
+ mm_app_snapshot_wait(cam_id);
+ CDBG("%s:calling mm_app_stop_snapshot() \n",__func__);
+ mm_app_stop_raw_snapshot(cam_id);
+ preview:
+ mm_app_start_preview(cam_id);
+ end:
+ CDBG("%s:END, cam_id=%d\n",__func__,cam_id);
+#endif
+ return rc;
+}
+
diff --git a/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_unit_test.c b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_unit_test.c
new file mode 100755
index 0000000..1b19181
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_unit_test.c
@@ -0,0 +1,559 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include "mm_camera_dbg.h"
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include "mm_qcamera_unit_test.h"
+
+#define MM_QCAMERA_APP_UTEST_MAX_MAIN_LOOP 4
+#define MM_QCAM_APP_TEST_NUM 128
+
+#define MM_QCAMERA_APP_INTERATION 5
+
+static mm_app_tc_t mm_app_tc[MM_QCAM_APP_TEST_NUM];
+static int num_test_cases = 0;
+
+int mm_app_tc_0(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i,j;
+ int result = 0;
+
+ printf("\n Verifying Preview on front and back camera...\n");
+ if (cam_apps->num_cameras == 0) {
+ CDBG_ERROR("%s:Query Failed: Num of cameras = %d\n",__func__, cam_apps->num_cameras);
+ rc = -1;
+ goto end;
+ }
+ for (i = 0; i < cam_apps->num_cameras; i++) {
+ if ( mm_app_open(i) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_open() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ if (system_dimension_set(my_cam_app.cam_open) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:system_dimension_set() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+ for (j = 0; j < MM_QCAMERA_APP_INTERATION; j++) {
+ if ( MM_CAMERA_OK != (rc = startPreview(my_cam_app.cam_open))) {
+ CDBG_ERROR("%s: startPreview() err=%d\n", __func__, rc);
+ break;
+ }
+ /*if(mm_camera_app_timedwait() == ETIMEDOUT) {
+ CDBG_ERROR("%s: Preview Callback not received in time or qbuf failed\n", __func__);
+ break;
+ }*/
+ mm_camera_app_wait();
+ if ( MM_CAMERA_OK != (rc = stopPreview(my_cam_app.cam_open))) {
+ CDBG("%s: startPreview() err=%d\n", __func__, rc);
+ break;
+ }
+ result++;
+ }
+ if ( mm_app_close(my_cam_app.cam_open) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_close() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+ if (result != MM_QCAMERA_APP_INTERATION) {
+ printf("%s: Preview Start/Stop Fails for Camera %d in %d iteration", __func__, i,j);
+ rc = -1;
+ break;
+ }
+
+ result = 0;
+ }
+ end:
+ if (rc == 0) {
+ printf("\nPassed\n");
+ } else {
+ printf("\nFailed\n");
+ }
+ CDBG("%s:END, rc = %d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_tc_1(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i,j;
+ int result = 0;
+
+ printf("\n Verifying Snapshot on front and back camera...\n");
+ for (i = 0; i < cam_apps->num_cameras; i++) {
+ if ( mm_app_open(i) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_open() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ if (system_dimension_set(my_cam_app.cam_open) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:system_dimension_set() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+ if ( MM_CAMERA_OK != (rc = startPreview(my_cam_app.cam_open))) {
+ CDBG_ERROR("%s: startPreview() err=%d\n", __func__, rc);
+ break;
+ }
+ for (j = 0; j < MM_QCAMERA_APP_INTERATION; j++) {
+ if ( MM_CAMERA_OK != (rc = takePicture_yuv(my_cam_app.cam_open))) {
+ CDBG_ERROR("%s: TakePicture() err=%d\n", __func__, rc);
+ break;
+ }
+ /*if(mm_camera_app_timedwait() == ETIMEDOUT) {
+ CDBG_ERROR("%s: Snapshot/Preview Callback not received in time or qbuf Faile\n", __func__);
+ break;
+ }*/
+ mm_camera_app_wait();
+ result++;
+ }
+ if ( MM_CAMERA_OK != (rc = stopPreview(my_cam_app.cam_open))) {
+ CDBG("%s: startPreview() err=%d\n", __func__, rc);
+ break;
+ }
+ if ( mm_app_close(my_cam_app.cam_open) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_close() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ if (result != MM_QCAMERA_APP_INTERATION) {
+ printf("%s: Snapshot Start/Stop Fails for Camera %d in %d iteration", __func__, i,j);
+ rc = -1;
+ break;
+ }
+
+ result = 0;
+ }
+ end:
+ if (rc == 0) {
+ printf("\t***Passed***\n");
+ } else {
+ printf("\t***Failed***\n");
+ }
+ CDBG("%s:END, rc = %d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_tc_2(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i,j;
+ int result = 0;
+
+ printf("\n Verifying Video on front and back camera...\n");
+ for (i = 0; i < cam_apps->num_cameras; i++) {
+ if ( mm_app_open(i) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_open() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ if (system_dimension_set(my_cam_app.cam_open) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:system_dimension_set() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+ if ( MM_CAMERA_OK != (rc = startPreview(my_cam_app.cam_open))) {
+ CDBG_ERROR("%s: startPreview() err=%d\n", __func__, rc);
+ break;
+ }
+ for (j = 0; j < MM_QCAMERA_APP_INTERATION; j++) {
+ if ( MM_CAMERA_OK != (rc = startRecording(my_cam_app.cam_open))) {
+ CDBG_ERROR("%s: StartVideorecording() err=%d\n", __func__, rc);
+ break;
+ }
+
+ /*if(mm_camera_app_timedwait() == ETIMEDOUT) {
+ CDBG_ERROR("%s: Video Callback not received in time\n", __func__);
+ break;
+ }*/
+ mm_camera_app_wait();
+ if ( MM_CAMERA_OK != (rc = stopRecording(my_cam_app.cam_open))) {
+ CDBG_ERROR("%s: Stopvideorecording() err=%d\n", __func__, rc);
+ break;
+ }
+ result++;
+ }
+ if ( MM_CAMERA_OK != (rc = stopPreview(my_cam_app.cam_open))) {
+ CDBG("%s: startPreview() err=%d\n", __func__, rc);
+ break;
+ }
+ if ( mm_app_close(my_cam_app.cam_open) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_close() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ if (result != MM_QCAMERA_APP_INTERATION) {
+ printf("%s: Video Start/Stop Fails for Camera %d in %d iteration", __func__, i,j);
+ rc = -1;
+ break;
+ }
+
+ result = 0;
+ }
+ end:
+ if (rc == 0) {
+ printf("\nPassed\n");
+ } else {
+ printf("\nFailed\n");
+ }
+ CDBG("%s:END, rc = %d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_tc_3(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i,j;
+ int result = 0;
+
+ printf("\n Verifying RDI Stream on front and back camera...\n");
+ if (cam_apps->num_cameras == 0) {
+ CDBG_ERROR("%s:Query Failed: Num of cameras = %d\n",__func__, cam_apps->num_cameras);
+ rc = -1;
+ goto end;
+ }
+ for (i = 0; i < cam_apps->num_cameras; i++) {
+ if ( mm_app_open(i) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_open() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ if (system_dimension_set(my_cam_app.cam_open) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:system_dimension_set() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ for (j = 0; j < MM_QCAMERA_APP_INTERATION; j++) {
+ if ( MM_CAMERA_OK != (rc = startRdi(my_cam_app.cam_open))) {
+ CDBG_ERROR("%s: StartVideorecording() err=%d\n", __func__, rc);
+ break;
+ }
+
+ /*if(mm_camera_app_timedwait() == ETIMEDOUT) {
+ CDBG_ERROR("%s: Video Callback not received in time\n", __func__);
+ break;
+ }*/
+ mm_camera_app_wait();
+ if ( MM_CAMERA_OK != (rc = stopRdi(my_cam_app.cam_open))) {
+ CDBG_ERROR("%s: Stopvideorecording() err=%d\n", __func__, rc);
+ break;
+ }
+ result++;
+ }
+ if ( mm_app_close(my_cam_app.cam_open) != MM_CAMERA_OK) {
+ CDBG_ERROR("%s:mm_app_close() err=%d\n",__func__, rc);
+ rc = -1;
+ goto end;
+ }
+ if (result != MM_QCAMERA_APP_INTERATION) {
+ printf("%s: Video Start/Stop Fails for Camera %d in %d iteration", __func__, i,j);
+ rc = -1;
+ break;
+ }
+
+ result = 0;
+ }
+ end:
+ if (rc == 0) {
+ printf("\nPassed\n");
+ } else {
+ printf("\nFailed\n");
+ }
+ CDBG("%s:END, rc = %d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_tc_4(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i;
+ printf("Running %s - open/close ,video0, open/close preview channel only\n", __func__);
+#if 0
+ for (i = 0; i < MM_QCAMERA_APP_UTEST_MAX_MAIN_LOOP; i++) {
+ if ( 0 != (rc = mm_app_open(cam_id, MM_CAMERA_OP_MODE_NOTUSED))) {
+ CDBG("%s: open cam %d at opmode = %d err, loop=%d, rc=%d\n", __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+ if (0 != (rc = mm_app_open_preview(cam_id))) {
+ goto end;
+ }
+ if (0 != (rc = mm_app_close_preview(cam_id))) {
+ goto end;
+ }
+ if ( 0 != (rc = mm_app_close(cam_id))) {
+ CDBG("%s: close cam %d at opmode = %d err,loop=%d, rc=%d\n", __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+ }
+end:
+#endif
+ CDBG("%s:END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+
+
+int mm_app_tc_5(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i;
+ printf("Running %s - open/close ,video0, open/close snapshot channel only\n", __func__);
+#if 0
+ for (i = 0; i < MM_QCAMERA_APP_UTEST_MAX_MAIN_LOOP; i++) {
+ if ( 0 != (rc = mm_app_open(cam_id, MM_CAMERA_OP_MODE_NOTUSED))) {
+ CDBG("%s: open cam %d at opmode = %d err, loop=%d, rc=%d\n",
+ __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+ if (0 != (rc = mm_app_open_snapshot(cam_id))) {
+ goto end;
+ }
+ if (0 != (rc = mm_app_close_snapshot(cam_id))) {
+ goto end;
+ }
+ if ( 0 != (rc = mm_app_close(cam_id))) {
+ CDBG("%s: close cam %d at opmode = %d err,loop=%d, rc=%d\n",
+ __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+ }
+ end:
+#endif
+ CDBG("%s:END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_tc_6(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i;
+ printf("Running %s - simple preview \n", __func__);
+#if 0
+ if ( 0 != (rc = mm_app_open(cam_id, MM_CAMERA_OP_MODE_NOTUSED))) {
+ CDBG("%s: open cam %d at opmode = %d err, loop=%d, rc=%d\n",
+ __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+
+ for (i = 0; i < MM_QCAMERA_APP_UTEST_MAX_MAIN_LOOP; i++) {
+ if (0 != (rc = mm_app_init_preview(cam_id))) {
+ goto end;
+ }
+ if (0 != (rc = mm_app_start_preview(cam_id))) {
+ goto end;
+ }
+ /* sleep 8 seconds */
+ usleep(8000000);
+ if (0 != (rc = mm_app_stop_preview(cam_id))) {
+ goto end;
+ }
+ if (0 != (rc=mm_app_deinit_preview(cam_id))) {
+ goto end;
+ }
+ if (0 != (rc = mm_app_close_preview(cam_id))) {
+ goto end;
+ }
+ }
+ if ( 0 != (rc = mm_app_close(cam_id))) {
+ CDBG("%s: close cam %d at opmode = %d err,loop=%d, rc=%d\n",
+ __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+end:
+#endif
+ CDBG("%s:END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_tc_7(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i;
+ printf("Running %s - simple preview and recording \n", __func__);
+#if 0
+ if ( 0 != (rc = mm_app_open(cam_id, MM_CAMERA_OP_MODE_NOTUSED))) {
+ CDBG("%s: open cam %d at opmode = %d err, loop=%d, rc=%d\n",
+ __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+
+ for (i = 0; i < MM_QCAMERA_APP_UTEST_MAX_MAIN_LOOP; i++) {
+ if (0 != (rc = mm_app_init_preview(cam_id))) {
+ goto end;
+ }
+ if (0 != (rc = mm_app_start_preview(cam_id))) {
+ goto end;
+ }
+ /* sleep 8 seconds */
+ usleep(8000000);
+ if (0 != (rc = mm_app_start_recording(cam_id))) {
+ goto end;
+ }
+ usleep(1000000);
+ if (0 != (rc = mm_app_stop_recording(cam_id))) {
+ goto end;
+ }
+ usleep(8000000);
+ if (0 != (rc = mm_app_stop_preview(cam_id))) {
+ goto end;
+ }
+ if (0 != (rc=mm_app_deinit_preview(cam_id))) {
+ goto end;
+ }
+ if (0 != (rc = mm_app_close_preview(cam_id))) {
+ goto end;
+ }
+ }
+ if ( 0 != (rc = mm_app_close(cam_id))) {
+ CDBG("%s: close cam %d at opmode = %d err,loop=%d, rc=%d\n",
+ __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+end:
+#endif
+ CDBG("%s:END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+int mm_app_tc_8(mm_camera_app_t *cam_apps)
+{
+ int rc = MM_CAMERA_OK;
+ int i;
+ printf("Running %s - preview, recording, and snapshot, then preview again \n", __func__);
+#if 0
+ if ( 0 != (rc = mm_app_open(cam_id, MM_CAMERA_OP_MODE_NOTUSED))) {
+ CDBG("%s: open cam %d at opmode = %d err, loop=%d, rc=%d\n",
+ __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+
+ for (i = 0; i < MM_QCAMERA_APP_UTEST_MAX_MAIN_LOOP; i++) {
+ if (0 != (rc = mm_app_init_preview(cam_id))) {
+ goto end;
+ }
+ if (0 != (rc = mm_app_start_preview(cam_id))) {
+ goto end;
+ }
+ /* sleep 8 seconds */
+ usleep(8000000);
+ if (0 != (rc = mm_app_start_recording(cam_id))) {
+ goto end;
+ }
+ usleep(1000000);
+ if (0 != (rc = mm_app_stop_recording(cam_id))) {
+ goto end;
+ }
+ if (0 != (rc = mm_app_stop_preview(cam_id))) {
+ goto end;
+ }
+ if (0!=(rc=mm_app_init_snapshot(cam_id))) {
+ goto end;
+ }
+ if (0 != (rc=mm_app_take_picture(cam_id))) {
+ goto end;
+ }
+ if ( 0 != (rc = mm_app_deinit_snahspot(cam_id))) {
+ goto end;
+ }
+ if (0 != (rc = mm_app_start_preview(cam_id))) {
+ goto end;
+ }
+ usleep(8000000);
+ if (0 != (rc=mm_app_deinit_preview(cam_id))) {
+ goto end;
+ }
+ if (0 != (rc = mm_app_close_preview(cam_id))) {
+ goto end;
+ }
+ }
+ if ( 0 != (rc = mm_app_close(cam_id))) {
+ CDBG("%s: close cam %d at opmode = %d err,loop=%d, rc=%d\n",
+ __func__, cam_id, MM_CAMERA_OP_MODE_NOTUSED, i, rc);
+ goto end;
+ }
+end:
+#endif
+ CDBG("%s:END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+
+int mm_app_gen_test_cases()
+{
+ int tc = 0;
+ memset(mm_app_tc, 0, sizeof(mm_app_tc));
+ if (tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_tc_0;
+ if (tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_tc_1;
+ if (tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_tc_2;
+ if (tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_tc_3;
+ /*if(tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_tc_4;
+ if(tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_tc_5;
+ if(tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_tc_6;
+ if(tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_tc_7;
+ if(tc < MM_QCAM_APP_TEST_NUM) mm_app_tc[tc++].f = mm_app_tc_8;*/
+ return tc;
+}
+
+int mm_app_unit_test_entry(mm_camera_app_t *cam_app)
+{
+ int rc = MM_CAMERA_OK;
+ int i, tc = 0;
+ int cam_id = 0;
+
+ tc = mm_app_gen_test_cases();
+ CDBG("Running %d test cases\n",tc);
+ for (i = 0; i < tc; i++) {
+ mm_app_tc[i].r = mm_app_tc[i].f(cam_app);
+ if (mm_app_tc[i].r != MM_CAMERA_OK) {
+ printf("%s: test case %d error = %d, abort unit testing engine!!!!\n",
+ __func__, i, mm_app_tc[i].r);
+ rc = mm_app_tc[i].r;
+ goto end;
+ }
+ }
+ end:
+ printf("nTOTAL_TSET_CASE = %d, NUM_TEST_RAN = %d, rc=%d\n", tc, i, rc);
+ return rc;
+}
+
+
+
+
diff --git a/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_video.c b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_video.c
new file mode 100755
index 0000000..b23f9b3
--- /dev/null
+++ b/camera/QCamera/stack/mm-camera-test/src/mm_qcamera_video.c
@@ -0,0 +1,484 @@
+/*
+Copyright (c) 2011-2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include "mm_camera_dbg.h"
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include "mm_qcamera_app.h"
+
+#define BUFF_SIZE_128 128
+static int num_run = 0;
+
+static int mm_app_dump_video_frame(struct msm_frame *frame,
+ uint32_t len)
+{
+ static int v_cnt = 0;
+ char bufp[BUFF_SIZE_128];
+ int file_fdp;
+ int rc = 0;
+
+ return rc; /* disable dump */
+
+ v_cnt++;
+ if(0 == (v_cnt % 10))
+ snprintf(bufp, BUFF_SIZE_128, "/data/v_%d.yuv", v_cnt);
+ else
+ return 0;
+
+ file_fdp = open(bufp, O_RDWR | O_CREAT, 0777);
+
+ if (file_fdp < 0) {
+ CDBG("cannot open file %s\n", bufp);
+ rc = -1;
+ goto end;
+ }
+ CDBG("%s:dump frame to '%s'\n", __func__, bufp);
+ write(file_fdp,
+ (const void *)frame->buffer, len);
+ close(file_fdp);
+end:
+ return rc;
+}
+
+static int mm_app_set_video_fmt(int cam_id,mm_camera_image_fmt_t *fmt)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ fmt->meta_header = MM_CAMEAR_META_DATA_TYPE_DEF;
+ fmt->fmt = pme->dim.enc_format;
+ fmt->width = pme->dim.video_width;
+ fmt->height = pme->dim.video_height;
+ return rc;
+}
+
+#if 0
+int mm_stream_deinit_video_buf(uint32_t camera_handle,
+ uint32_t ch_id, uint32_t stream_id,
+ void *user_data, uint8_t num_bufs,
+ mm_camera_buf_def_t *bufs)
+{
+ int i, rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
+
+ for(i = 0; i < num_bufs; i++) {
+ rc = my_cam_app.hal_lib.mm_camera_do_munmap_ion (pme->ionfd, &(pme->video_buf.frame[i].fd_data),
+ (void *)pme->video_buf.frame[i].buffer, pme->video_buf.frame_len);
+ if(rc != MM_CAMERA_OK) {
+ CDBG_ERROR("%s: mm_camera_do_munmap err, pmem_fd = %d, rc = %d",
+ __func__, bufs[i].fd, rc);
+ }
+ }
+ return rc;
+}
+
+int mm_stream_init_video_buf(uint32_t camera_handle,
+ uint32_t ch_id, uint32_t stream_id,
+ void *user_data,
+ mm_camera_frame_len_offset *frame_offset_info,
+ uint8_t num_bufs,
+ uint8_t *initial_reg_flag,
+ mm_camera_buf_def_t *bufs)
+{
+ int i,j,num_planes, frame_len, y_off, cbcr_off;
+ uint32_t planes[VIDEO_MAX_PLANES];
+ uint32_t pmem_addr = 0;
+
+ mm_camera_app_obj_t *pme = (mm_camera_app_obj_t *)user_data;
+
+ num_planes = frame_offset_info->num_planes;
+ for ( i = 0; i < num_planes; i++) {
+ planes[i] = frame_offset_info->mp[i].len;
+ }
+
+ frame_len = frame_offset_info->frame_len;
+ y_off = frame_offset_info->mp[0].offset;
+ cbcr_off = frame_offset_info->mp[1].offset;
+
+ CDBG("Allocating video Memory for %d buffers frame_len = %d",num_bufs,frame_offset_info->frame_len);
+
+ for (i = 0; i < num_bufs ; i++) {
+ int j;
+ pme->video_buf.reg[i] = 1;
+ initial_reg_flag[i] = 1;
+
+ pme->video_buf.frame_len = frame_len;
+ pme->video_buf.frame[i].ion_alloc.len = pme->video_buf.frame_len;
+ pme->video_buf.frame[i].ion_alloc.flags =
+ (0x1 << CAMERA_ION_HEAP_ID | 0x1 << ION_IOMMU_HEAP_ID);
+ pme->video_buf.frame[i].ion_alloc.align = 4096;
+
+ pmem_addr = (unsigned long) my_cam_app.hal_lib.mm_camera_do_mmap_ion(pme->ionfd,
+ &(pme->video_buf.frame[i].ion_alloc), &(pme->video_buf.frame[i].fd_data),
+ &pme->video_buf.frame[i].fd);
+
+ pme->video_buf.frame[i].buffer = pmem_addr;
+ pme->video_buf.frame[i].path = OUTPUT_TYPE_V;
+ pme->video_buf.frame[i].y_off = 0;
+ pme->video_buf.frame[i].cbcr_off = planes[0];
+ pme->video_buf.frame[i].phy_offset = 0;
+
+ CDBG("Buffer allocated Successfully fd = %d",pme->video_buf.frame[i].fd);
+
+ bufs[i].fd = pme->video_buf.frame[i].fd;
+ //bufs[i].buffer = pmem_addr;
+ bufs[i].frame_len = pme->video_buf.frame[i].ion_alloc.len;
+ bufs[i].num_planes = num_planes;
+
+ bufs[i].frame = &pme->video_buf.frame[i];
+
+ /* Plane 0 needs to be set seperately. Set other planes
+ * in a loop. */
+ bufs[i].planes[0].length = planes[0];
+ bufs[i].planes[0].m.userptr = bufs[i].fd;
+ bufs[i].planes[0].data_offset = y_off;
+ bufs[i].planes[0].reserved[0] = 0;
+ //buf_def->buf.mp[i].frame_offset;
+ for (j = 1; j < num_planes; j++) {
+ bufs[i].planes[j].length = planes[j];
+ bufs[i].planes[j].m.userptr = bufs[i].fd;
+ bufs[i].planes[j].data_offset = cbcr_off;
+ bufs[i].planes[j].reserved[0] =
+ bufs[i].planes[j-1].reserved[0] +
+ bufs[i].planes[j-1].length;
+ }
+ }
+ return MM_CAMERA_OK;
+}
+#endif
+
+void video_cb_signal(mm_camera_app_obj_t *pme)
+{
+ if(pme->cam_state == CAMERA_STATE_RECORD) {
+ mm_camera_app_done();
+ }
+}
+
+static void mm_app_video_notify_cb(mm_camera_super_buf_t *bufs,
+ void *user_data)
+{
+ int rc;
+ mm_camera_buf_def_t *frame = NULL;
+ mm_camera_app_obj_t *pme = NULL;
+ CDBG("%s: BEGIN\n", __func__);
+ frame = bufs->bufs[MM_CAMERA_PREVIEW] ;
+ pme = (mm_camera_app_obj_t *)user_data;
+
+ CDBG("%s: BEGIN - length=%d, frame idx = %d\n", __func__, frame->frame_len, frame->frame_idx);
+ //Need to code to Send to Encoder .. Simulat
+ CDBG("In CB function i/p = %p o/p = %p",bufs->bufs[MM_CAMERA_PREVIEW],frame);
+
+ dumpFrameToFile(frame,pme->dim.orig_video_width,pme->dim.orig_video_height,"video", 1);
+ if(MM_CAMERA_OK != pme->cam->ops->qbuf(pme->cam->camera_handle,pme->ch_id,frame))
+ {
+ CDBG_ERROR("%s: Failed in Snapshot Qbuf\n", __func__);
+ return;
+ }
+ video_cb_signal(pme);
+ CDBG("%s: END\n", __func__);
+
+}
+
+int mm_app_config_video(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ mm_app_set_video_fmt(cam_id,&pme->stream[MM_CAMERA_VIDEO].str_config.fmt);
+ pme->stream[MM_CAMERA_VIDEO].str_config.need_stream_on = 1;
+ pme->stream[MM_CAMERA_VIDEO].str_config.num_of_bufs = VIDEO_BUF_NUM;
+
+ if(MM_CAMERA_OK != (rc = pme->cam->ops->config_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_VIDEO].id,
+ &pme->stream[MM_CAMERA_VIDEO].str_config))) {
+ CDBG_ERROR("%s:MM_CAMERA_VIDEO config streaming err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ CDBG("config_stream stream is successfull");
+
+ pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config.need_stream_on = pme->fullSizeSnapshot;
+ pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config.num_of_bufs = 1;
+
+ mm_app_set_live_snapshot_fmt(cam_id,&pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config.fmt);
+
+ if(MM_CAMERA_OK != (rc = pme->cam->ops->config_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id,
+ &pme->stream[MM_CAMERA_SNAPSHOT_MAIN].str_config))) {
+ CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
+ goto end;
+ }
+end:
+ return rc;
+
+}
+
+int mm_app_prepare_video(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ pme->stream[MM_CAMERA_VIDEO].id = pme->cam->ops->add_stream(pme->cam->camera_handle,pme->ch_id,
+ mm_app_video_notify_cb,pme,
+ MM_CAMERA_VIDEO, 0);
+
+ if(!pme->stream[MM_CAMERA_VIDEO].id) {
+ CDBG("%s:MM_CAMERA_VIDEO streaming err = %d\n", __func__, rc);
+ rc = -1;
+ goto end;
+ }
+
+ CDBG("Add stream is successfull stream ID = %d",pme->stream[MM_CAMERA_PREVIEW].id);
+
+ /* Code to add live snapshot*/
+ pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id = pme->cam->ops->add_stream(pme->cam->camera_handle,pme->ch_id,
+ NULL,pme,
+ MM_CAMERA_SNAPSHOT_MAIN, 0);
+
+ CDBG("Add Snapshot main is successfull stream ID = %d",pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id);
+ if(!pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id) {
+ CDBG_ERROR("%s:preview streaming err=%d\n", __func__, rc);
+ rc = -1;
+ goto end;
+ }
+ /*if(mm_app_config_video(cam_id) != MM_CAMERA_OK)
+ {
+ CDBG_ERROR("%s:Video config err=%d\n", __func__, rc);
+ }*/
+end:
+ return rc;
+}
+
+int mm_app_unprepare_video(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ if(MM_CAMERA_OK != (rc = pme->cam->ops->del_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_VIDEO].id))){
+ CDBG_ERROR("%s : Delete Stream Video error",__func__);
+ goto end;
+ }
+
+ if(MM_CAMERA_OK != (rc = pme->cam->ops->del_stream(pme->cam->camera_handle,pme->ch_id,pme->stream[MM_CAMERA_SNAPSHOT_MAIN].id))){
+ CDBG_ERROR("%s : Delete Stream Video error",__func__);
+ goto end;
+ }
+end:
+ CDBG("del_stream successfull");
+ return rc;
+}
+
+static int mm_app_streamon_video(int cam_id)
+{
+ int stream[2];
+ int rc = MM_CAMERA_OK;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ if(mm_app_config_video(cam_id) != MM_CAMERA_OK)
+ {
+ CDBG_ERROR("%s:Video config err=%d\n", __func__, rc);
+ }
+
+ stream[MM_CAMERA_VIDEO] = pme->stream[MM_CAMERA_VIDEO].id;
+ if(MM_CAMERA_OK != (rc = pme->cam->ops->start_streams(pme->cam->camera_handle,pme->ch_id,1,&stream[1])))
+ {
+ CDBG_ERROR("%s : Start Stream video Error",__func__);
+ return -1;
+ }
+ CDBG("Start video stream is successfull");
+ pme->cam_state = CAMERA_STATE_RECORD;
+ return rc;
+}
+
+static int mm_app_streamoff_video(int cam_id)
+{
+ int stream[2];
+ int rc = MM_CAMERA_OK;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ stream[0] = pme->stream[MM_CAMERA_VIDEO].id;
+
+ if(MM_CAMERA_OK != (rc =pme->cam->ops->stop_streams(pme->cam->camera_handle,pme->ch_id,1,&stream)))
+ {
+ CDBG_ERROR("%s : stop Stream video Error",__func__);
+ goto end;
+ }
+ CDBG("stop video stream is successfull");
+ pme->cam_state = CAMERA_STATE_PREVIEW;
+end:
+ return rc;
+
+}
+int mm_app_stop_video(int cam_id)
+{
+ int stream[2];
+ int rc = MM_CAMERA_OK;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ stream[0] = pme->stream[MM_CAMERA_VIDEO].id;
+
+ if(MM_CAMERA_OK != (rc = mm_app_streamoff_video(cam_id))){
+ CDBG_ERROR("%s : Video Stream off error",__func__);
+ goto end;
+ }
+end:
+ return rc;
+}
+
+static int mm_app_start_video(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("pme = %p, pme->cam =%p, pme->ch = %d pme->cam->camera_handle = %d",
+ pme,pme->cam,pme->ch_id,pme->cam->camera_handle);
+
+ if(MM_CAMERA_OK != (rc = mm_app_prepare_video(cam_id))){
+ CDBG_ERROR("%s:MM_CAMERA_VIDEO streaming err = %d\n", __func__, rc);
+ goto end;
+ }
+ if(MM_CAMERA_OK != (rc = mm_app_streamon_video(cam_id))){
+ CDBG_ERROR("%s:MM_CAMERA_VIDEO streaming err = %d\n", __func__, rc);
+ goto end;
+ }
+
+end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+
+ return rc;
+}
+
+int mm_app_open_recorder(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+ int value = 1;
+ int powermode = 1;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("%s: mm_app_open_recorder",__func__);
+ if(pme->cam_mode == RECORDER_MODE) {
+ CDBG("%s : Already in record mode",__func__);
+ return rc;
+ }
+
+ if(MM_CAMERA_OK != (rc = mm_app_stop_preview(cam_id))){
+ CDBG_ERROR("%s:Stop preview err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ if(MM_CAMERA_OK != initDisplay())
+ {
+ CDBG_ERROR("%s : Could not initalize display",__func__);
+ goto end;
+ }
+
+ pme->cam->ops->set_parm(pme->cam->camera_handle,MM_CAMERA_PARM_RECORDING_HINT, &value);
+
+ pme->cam->ops->set_parm(pme->cam->camera_handle,MM_CAMERA_PARM_LOW_POWER_MODE, &powermode);
+
+
+ if(MM_CAMERA_OK != (rc = mm_app_prepare_preview(cam_id))){
+ CDBG_ERROR("%s:stream on preview err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ if(MM_CAMERA_OK != (rc = mm_app_prepare_video(cam_id))){
+ CDBG_ERROR("%s:stream on video err=%d\n", __func__, rc);
+ goto end;
+ }
+
+ if(MM_CAMERA_OK != (rc = mm_app_streamon_preview(cam_id))){
+ CDBG_ERROR("%s:start preview err=%d\n", __func__, rc);
+ goto end;
+ }
+ pme->cam_mode = RECORDER_MODE;
+end:
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+int startRecording(int cam_id)
+{
+ int rc = MM_CAMERA_OK;
+
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ CDBG("%s: Start Recording mode = %d state = %d",__func__,pme->cam_mode,pme->cam_state);
+
+ if(pme->cam_mode == CAMERA_MODE || pme->cam_mode == ZSL_MODE) {
+ switch(pme->cam_state) {
+ case CAMERA_STATE_PREVIEW:
+ if(MM_CAMERA_OK != mm_app_open_recorder(cam_id)){
+ CDBG_ERROR("%s: Open Record Failed \n", __func__);
+ return -1;
+ }
+ break;
+ case CAMERA_STATE_RECORD:
+ case CAMERA_STATE_SNAPSHOT:
+ default:
+ break;
+ }
+ }/*else{
+ mm_app_prepare_video(cam_id);
+ }*/
+ CDBG("%s : startRecording : mode = %d state = %d",__func__,pme->cam_mode,pme->cam_state);
+ if(pme->cam_mode == RECORDER_MODE && pme->cam_state == CAMERA_STATE_PREVIEW){
+ if(MM_CAMERA_OK != mm_app_streamon_video(cam_id)){
+ CDBG_ERROR("%s:start video err=%d\n", __func__, rc);
+ return -1;
+ }
+ }
+ CDBG("%s: END, rc=%d\n", __func__, rc);
+ return rc;
+}
+
+int stopRecording(int cam_id)
+{
+
+ int rc = MM_CAMERA_OK;
+ mm_camera_app_obj_t *pme = mm_app_get_cam_obj(cam_id);
+
+ if(pme->cam_mode != RECORDER_MODE || pme->cam_state != CAMERA_STATE_RECORD) {
+ return rc;
+ }
+ if(MM_CAMERA_OK != mm_app_stop_video(cam_id)){
+ CDBG_ERROR("%s:stop video err=%d\n", __func__, rc);
+ return -1;
+ }
+ return rc;
+}
+
diff --git a/camera/QCamera/stack/mm-jpeg-interface/Android.mk b/camera/QCamera/stack/mm-jpeg-interface/Android.mk
new file mode 100755
index 0000000..a0aef69
--- /dev/null
+++ b/camera/QCamera/stack/mm-jpeg-interface/Android.mk
@@ -0,0 +1,34 @@
+OLD_LOCAL_PATH := $(LOCAL_PATH)
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_CFLAGS+= -D_ANDROID_
+LOCAL_COPY_HEADERS_TO := mm-camera-interface
+LOCAL_COPY_HEADERS = inc/mm_jpeg_interface.h
+
+LOCAL_C_INCLUDES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include/media
+LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/inc \
+ $(LOCAL_PATH)/../common \
+ $(LOCAL_PATH)/../../../ \
+ $(TARGET_OUT_HEADERS)/mm-still \
+ $(TARGET_OUT_HEADERS)/mm-still/jpeg \
+ $(TARGET_OUT_HEADERS)/mm-core/omxcore \
+ $(TARGET_OUT_HEADERS)/mm-still/mm-omx
+
+LOCAL_SRC_FILES := \
+ src/mm_jpeg_queue.c \
+ src/mm_jpeg.c \
+ src/mm_jpeg_interface.c
+
+LOCAL_MODULE := libmmjpeg_interface
+LOCAL_PRELINK_MODULE := false
+LOCAL_SHARED_LIBRARIES := libdl libcutils liblog libmmstillomx libimage-jpeg-enc-omx-comp
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+
+LOCAL_PATH := $(OLD_LOCAL_PATH)
diff --git a/camera/QCamera/stack/mm-jpeg-interface/inc/mm_jpeg.h b/camera/QCamera/stack/mm-jpeg-interface/inc/mm_jpeg.h
new file mode 100755
index 0000000..4147c09
--- /dev/null
+++ b/camera/QCamera/stack/mm-jpeg-interface/inc/mm_jpeg.h
@@ -0,0 +1,166 @@
+
+/* Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 MM_JPEG_H_
+#define MM_JPEG_H_
+
+#include "mm_jpeg_interface.h"
+#include "cam_list.h"
+#include "OMX_Types.h"
+#include "OMX_Index.h"
+#include "OMX_Core.h"
+#include "OMX_Component.h"
+#include "omx_jpeg_ext.h"
+#include <semaphore.h>
+
+typedef struct {
+ struct cam_list list;
+ void* data;
+} mm_jpeg_q_node_t;
+
+typedef struct {
+ mm_jpeg_q_node_t head; /* dummy head */
+ uint32_t size;
+ pthread_mutex_t lock;
+} mm_jpeg_queue_t;
+
+typedef enum
+{
+ MM_JPEG_CMD_TYPE_JOB, /* job cmd */
+ MM_JPEG_CMD_TYPE_EXIT, /* EXIT cmd for exiting jobMgr thread */
+ MM_JPEG_CMD_TYPE_MAX
+} mm_jpeg_cmd_type_t;
+
+typedef struct {
+ OMX_BUFFERHEADERTYPE* buf_header;
+ uint32_t portIdx;
+} mm_jpeg_omx_buf_info;
+
+typedef struct {
+ uint8_t num_bufs;
+ mm_jpeg_omx_buf_info bufs[MAX_SRC_BUF_NUM];
+} mm_jpeg_omx_src_buf;
+
+typedef struct {
+ uint32_t client_hdl; /* client handler */
+ uint32_t jobId; /* job ID */
+ mm_jpeg_job job; /* job description */
+ pthread_t cb_pid; /* cb thread heandler*/
+
+ void* jpeg_obj; /* ptr to mm_jpeg_obj */
+ jpeg_job_status_t job_status; /* job status */
+ uint8_t thumbnail_dropped; /* flag indicating if thumbnail is dropped */
+ int32_t jpeg_size; /* the size of jpeg output after job is done */
+
+ mm_jpeg_omx_src_buf src_bufs[JPEG_SRC_IMAGE_TYPE_MAX];
+ mm_jpeg_omx_buf_info sink_buf;
+} mm_jpeg_job_entry;
+
+typedef struct {
+ mm_jpeg_cmd_type_t type;
+ union {
+ mm_jpeg_job_entry entry;
+ };
+} mm_jpeg_job_q_node_t;
+
+typedef struct {
+ uint8_t is_used; /* flag: if is a valid client */
+ uint32_t client_handle; /* client handle */
+} mm_jpeg_client_t;
+
+typedef struct {
+ pthread_t pid; /* job cmd thread ID */
+ sem_t job_sem; /* semaphore for job cmd thread */
+ mm_jpeg_queue_t job_queue; /* queue for job to do */
+} mm_jpeg_job_cmd_thread_t;
+
+typedef enum {
+ MM_JPEG_EVENT_MASK_JPEG_DONE = 0x00000001, /* jpeg job is done */
+ MM_JPEG_EVENT_MASK_JPEG_ABORT = 0x00000002, /* jpeg job is aborted */
+ MM_JPEG_EVENT_MASK_JPEG_ERROR = 0x00000004, /* jpeg job has error */
+ MM_JPEG_EVENT_MASK_CMD_COMPLETE = 0x00000100 /* omx cmd complete evt */
+} mm_jpeg_event_mask_t;
+
+typedef struct {
+ uint32_t evt;
+ int omx_value1; /* only valid when evt_mask == MM_JPEG_EVENT_MASK_CMD_COMPLETE */
+ int omx_value2; /* only valid when evt_mask == MM_JPEG_EVENT_MASK_CMD_COMPLETE */
+} mm_jpeg_evt_t;
+
+#define MAX_JPEG_CLIENT_NUM 8
+typedef struct mm_jpeg_obj_t {
+ /* ClientMgr */
+ int num_clients; /* num of clients */
+ mm_jpeg_client_t clnt_mgr[MAX_JPEG_CLIENT_NUM]; /* client manager */
+
+ /* JobMkr */
+ pthread_mutex_t job_lock; /* job lock */
+ mm_jpeg_job_cmd_thread_t job_mgr; /* job mgr thread including todo_q*/
+ mm_jpeg_queue_t ongoing_job_q; /* queue for ongoing jobs */
+
+ /* Notifier */
+ mm_jpeg_queue_t cb_q; /* queue for CB threads */
+
+ /* OMX related */
+ OMX_HANDLETYPE omx_handle; /* handle to omx engine */
+
+ pthread_mutex_t omx_evt_lock;
+ pthread_cond_t omx_evt_cond;
+ mm_jpeg_evt_t omx_evt_rcvd;
+} mm_jpeg_obj;
+
+extern int32_t mm_jpeg_init(mm_jpeg_obj *my_obj);
+extern int32_t mm_jpeg_deinit(mm_jpeg_obj *my_obj);
+extern uint32_t mm_jpeg_new_client(mm_jpeg_obj *my_obj);
+extern int32_t mm_jpeg_start_job(mm_jpeg_obj *my_obj,
+ uint32_t client_hdl,
+ mm_jpeg_job* job,
+ uint32_t* jobId);
+extern int32_t mm_jpeg_abort_job(mm_jpeg_obj *my_obj,
+ uint32_t client_hdl,
+ uint32_t jobId);
+extern int32_t mm_jpeg_close(mm_jpeg_obj *my_obj,
+ uint32_t client_hdl);
+
+/* utiltity fucntion declared in mm-camera-inteface2.c
+ * and need be used by mm-camera and below*/
+uint32_t mm_jpeg_util_generate_handler(uint8_t index);
+uint8_t mm_jpeg_util_get_index_by_handler(uint32_t handler);
+
+/* basic queue functions */
+extern int32_t mm_jpeg_queue_init(mm_jpeg_queue_t* queue);
+extern int32_t mm_jpeg_queue_enq(mm_jpeg_queue_t* queue, void* node);
+extern void* mm_jpeg_queue_deq(mm_jpeg_queue_t* queue);
+extern int32_t mm_jpeg_queue_deinit(mm_jpeg_queue_t* queue);
+extern int32_t mm_jpeg_queue_flush(mm_jpeg_queue_t* queue);
+extern uint32_t mm_jpeg_queue_get_size(mm_jpeg_queue_t* queue);
+
+#endif /* MM_JPEG_H_ */
+
+
diff --git a/camera/QCamera/stack/mm-jpeg-interface/inc/mm_jpeg_dbg.h b/camera/QCamera/stack/mm-jpeg-interface/inc/mm_jpeg_dbg.h
new file mode 100755
index 0000000..6c9ebec
--- /dev/null
+++ b/camera/QCamera/stack/mm-jpeg-interface/inc/mm_jpeg_dbg.h
@@ -0,0 +1,70 @@
+/*
+Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 __MM_JPEG_DBG_H__
+#define __MM_JPEG_DBG_H__
+
+#define LOG_DEBUG 1
+
+#ifndef LOG_DEBUG
+ #ifdef _ANDROID_
+ #undef LOG_NIDEBUG
+ #undef LOG_TAG
+ #define LOG_NIDEBUG 0
+ #define LOG_TAG "mm-jpeg-intf"
+ #include <utils/Log.h>
+ #else
+ #include <stdio.h>
+ #define ALOGE CDBG
+ #endif
+ #undef CDBG
+ #define CDBG(fmt, args...) do{}while(0)
+#else
+ #ifdef _ANDROID_
+ #undef LOG_NIDEBUG
+ #undef LOG_TAG
+ #define LOG_NIDEBUG 0
+ #define LOG_TAG "mm-jpeg-intf"
+ #include <utils/Log.h>
+ #define CDBG(fmt, args...) ALOGE(fmt, ##args)
+ #else
+ #include <stdio.h>
+ #define CDBG(fmt, args...) fprintf(stderr, fmt, ##args)
+ #define ALOGE(fmt, args...) fprintf(stderr, fmt, ##args)
+ #endif
+#endif
+
+#ifdef _ANDROID_
+ #define CDBG_HIGH(fmt, args...) ALOGE(fmt, ##args)
+ #define CDBG_ERROR(fmt, args...) ALOGE(fmt, ##args)
+#else
+ #define CDBG_HIGH(fmt, args...) fprintf(stderr, fmt, ##args)
+ #define CDBG_ERROR(fmt, args...) fprintf(stderr, fmt, ##args)
+#endif
+#endif /* __MM_JPEG_DBG_H__ */
diff --git a/camera/QCamera/stack/mm-jpeg-interface/inc/mm_jpeg_interface.h b/camera/QCamera/stack/mm-jpeg-interface/inc/mm_jpeg_interface.h
new file mode 100755
index 0000000..f59febd
--- /dev/null
+++ b/camera/QCamera/stack/mm-jpeg-interface/inc/mm_jpeg_interface.h
@@ -0,0 +1,209 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 MM_JPEG_INTERFACE_H_
+#define MM_JPEG_INTERFACE_H_
+#include "QCamera_Intf.h"
+
+typedef struct {
+ int width;
+ int height;
+} image_resolution;
+
+typedef enum {
+ JPEG_SRC_IMAGE_FMT_YUV,
+ JPEG_SRC_IMAGE_FMT_BITSTREAM
+} jpeg_enc_src_img_fmt_t;
+
+typedef enum {
+ JPEG_SRC_IMAGE_TYPE_MAIN,
+ JPEG_SRC_IMAGE_TYPE_THUMB,
+ JPEG_SRC_IMAGE_TYPE_MAX
+} jpeg_enc_src_img_type_t;
+
+typedef struct {
+ int32_t offset_x;
+ int32_t offset_y;
+ int32_t width;
+ int32_t height;
+} image_crop_t;
+
+typedef struct {
+ uint8_t sequence; /*for jpeg bit streams, assembling is based on sequence. sequence starts from 0*/
+ uint8_t *buf_vaddr; /*ptr to buf*/
+ int fd; /*fd of buf*/
+ uint32_t buf_size; /* total size of buf (header + image) */
+ uint32_t data_offset; /*data offset*/
+} src_bitstream_buffer_t;
+
+typedef struct {
+ uint8_t *buf_vaddr; /*ptr to buf*/
+ int fd; /*fd of buf*/
+ cam_frame_len_offset_t offset; /*alway use multi-planar, offset is used to skip the metadata header*/
+} src_image_buffer_t;
+
+typedef enum {
+ MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2,
+ MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2,
+ MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1,
+ MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1,
+ MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V2,
+ MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V2,
+ MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V1,
+ MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V1,
+ MM_JPEG_COLOR_FORMAT_RGB565,
+ MM_JPEG_COLOR_FORMAT_RGB888,
+ MM_JPEG_COLOR_FORMAT_RGBa,
+ MM_JPEG_COLOR_FORMAT_BITSTREAM,
+ MM_JPEG_COLOR_FORMAT_MAX
+} mm_jpeg_color_format;
+
+#define MAX_SRC_BUF_NUM 2
+typedef struct {
+ /* src img format: YUV, Bitstream */
+ jpeg_enc_src_img_fmt_t img_fmt;
+
+ /* num of buf in src img */
+ uint8_t num_bufs;
+
+ /* src img bufs */
+ union {
+ src_bitstream_buffer_t bit_stream[MAX_SRC_BUF_NUM];
+ src_image_buffer_t src_image[MAX_SRC_BUF_NUM];
+ };
+
+ /* src img type: main or thumbnail */
+ jpeg_enc_src_img_type_t type;
+
+ /* color format */
+ mm_jpeg_color_format color_format;
+
+ /* src img dimension */
+ image_resolution src_dim;
+
+ /* jpeg output dimension */
+ image_resolution out_dim;
+
+ /* crop information */
+ image_crop_t crop;
+
+ /* jpeg quality: range 0~100 */
+ uint32_t quality;
+} src_image_buffer_info;
+
+typedef struct {
+ uint8_t *buf_vaddr; /*ptr to buf*/
+ int fd; /*fd of buf*/
+ int buf_len;
+} out_image_buffer_info;
+
+typedef struct {
+ /* num of src imgs: e.g. main/thumbnail img
+ * if main img only: src_img_num = 1;
+ * if main+thumbnail: src_img_num = 2;
+ * No support for thumbnail only case */
+ uint8_t src_img_num;
+
+ /* index 0 is always for main image
+ * if thumbnail presented, it will be in index 1 */
+ src_image_buffer_info src_img[JPEG_SRC_IMAGE_TYPE_MAX];
+} src_image_buffer_config;
+
+typedef struct {
+ src_image_buffer_config src_imgs;
+ out_image_buffer_info sink_img;
+} jpeg_image_buffer_config;
+
+typedef struct {
+ /* config for scr images */
+ jpeg_image_buffer_config buf_info;
+
+ /* rotation informaiton */
+ int rotation;
+
+ /* num of exif entries */
+ int exif_numEntries;
+
+ /* buf to exif entries, caller needs to
+ * take care of the memory manage with insider ptr */
+ exif_tags_info_t *exif_data;
+} mm_jpeg_encode_params;
+
+typedef enum {
+ JPEG_JOB_STATUS_DONE = 0,
+ JPEG_JOB_STATUS_ERROR
+} jpeg_job_status_t;
+
+typedef void (*jpeg_encode_callback_t)(jpeg_job_status_t status,
+ uint8_t thumbnailDroppedFlag,
+ uint32_t client_hdl,
+ uint32_t jobId,
+ uint8_t* out_data,
+ uint32_t data_size,
+ void *userData);
+
+typedef struct {
+ mm_jpeg_encode_params encode_parm;
+ jpeg_encode_callback_t jpeg_cb;
+ void* userdata;
+} mm_jpeg_encode_job;
+
+typedef enum {
+ JPEG_JOB_TYPE_ENCODE,
+ //JPEG_JOB_TYPE_DECODE, /*enable decode later*/
+ JPEG_JOB_TYPE_MAX
+} mm_jpeg_job_type_t;
+
+typedef struct {
+ mm_jpeg_job_type_t job_type;
+ union {
+ mm_jpeg_encode_job encode_job;
+ };
+} mm_jpeg_job;
+
+typedef struct {
+ /* start a job -- async call
+ * the result of job (DONE/ERROR) will rcvd through CB */
+ int32_t (* start_job) (uint32_t client_hdl, mm_jpeg_job* job, uint32_t* jobId);
+
+ /* abort a job -- sync call */
+ int32_t (* abort_job) (uint32_t client_hdl, uint32_t jobId);
+
+ /* close a jpeg client -- sync call */
+ int32_t (* close) (uint32_t clientHdl);
+} mm_jpeg_ops_t;
+
+/* open a jpeg client -- sync call
+ * returns client_handle.
+ * failed if client_handle=0
+ * jpeg ops tbl will be filled in if open succeeds */
+uint32_t jpeg_open(mm_jpeg_ops_t *ops);
+
+#endif /* MM_JPEG_INTERFACE_H_ */
+
+
diff --git a/camera/QCamera/stack/mm-jpeg-interface/src/mm_jpeg.c b/camera/QCamera/stack/mm-jpeg-interface/src/mm_jpeg.c
new file mode 100755
index 0000000..48ac062
--- /dev/null
+++ b/camera/QCamera/stack/mm-jpeg-interface/src/mm_jpeg.c
@@ -0,0 +1,1297 @@
+/*
+Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <semaphore.h>
+
+#include "mm_jpeg_dbg.h"
+#include "mm_jpeg_interface.h"
+#include "mm_jpeg.h"
+
+/* define max num of supported concurrent jpeg jobs by OMX engine.
+ * Current, only one per time */
+#define NUM_MAX_JPEG_CNCURRENT_JOBS 1
+
+#define INPUT_PORT_MAIN 0
+#define INPUT_PORT_THUMBNAIL 2
+#define OUTPUT_PORT 1
+
+void mm_jpeg_job_wait_for_event(mm_jpeg_obj *my_obj, uint32_t evt_mask);
+void mm_jpeg_job_wait_for_cmd_complete(mm_jpeg_obj *my_obj,
+ int cmd,
+ int status);
+OMX_ERRORTYPE mm_jpeg_etbdone(OMX_HANDLETYPE hComponent,
+ OMX_PTR pAppData,
+ OMX_BUFFERHEADERTYPE* pBuffer);
+OMX_ERRORTYPE mm_jpeg_ftbdone(OMX_HANDLETYPE hComponent,
+ OMX_PTR pAppData,
+ OMX_BUFFERHEADERTYPE* pBuffer);
+OMX_ERRORTYPE mm_jpeg_handle_omx_event(OMX_HANDLETYPE hComponent,
+ OMX_PTR pAppData,
+ OMX_EVENTTYPE eEvent,
+ OMX_U32 nData1,
+ OMX_U32 nData2,
+ OMX_PTR pEventData);
+/* special queue functions for job queue */
+int32_t mm_jpeg_queue_update_flag(mm_jpeg_queue_t* queue, uint32_t job_id, uint8_t flag);
+mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_client_id(mm_jpeg_queue_t* queue, uint32_t client_hdl);
+mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_job_id(mm_jpeg_queue_t* queue, uint32_t job_id);
+
+int32_t mm_jpeg_omx_load(mm_jpeg_obj* my_obj)
+{
+ int32_t rc = 0;
+ OMX_CALLBACKTYPE callbacks;
+
+ callbacks.EmptyBufferDone = mm_jpeg_etbdone;
+ callbacks.FillBufferDone = mm_jpeg_ftbdone;
+ callbacks.EventHandler = mm_jpeg_handle_omx_event;
+ rc = OMX_GetHandle(&my_obj->omx_handle,
+ "OMX.qcom.image.jpeg.encoder",
+ (void*)my_obj,
+ &callbacks);
+
+ if (0 != rc) {
+ CDBG_ERROR("%s : OMX_GetHandle failed (%d)",__func__, rc);
+ return rc;
+ }
+
+ rc = OMX_Init();
+ if (0 != rc) {
+ CDBG_ERROR("%s : OMX_Init failed (%d)",__func__, rc);
+ OMX_FreeHandle(my_obj->omx_handle);
+ }
+
+ return rc;
+}
+
+int32_t mm_jpeg_omx_unload(mm_jpeg_obj *my_obj)
+{
+ int32_t rc = 0;
+ rc = OMX_Deinit();
+ OMX_FreeHandle(my_obj->omx_handle);
+
+ return rc;
+}
+
+int32_t mm_jpeg_omx_abort_job(mm_jpeg_obj *my_obj, mm_jpeg_job_entry* job_entry)
+{
+ int32_t rc = 0;
+ uint8_t i, j;
+
+ OMX_SendCommand(my_obj->omx_handle, OMX_CommandFlush, 0, NULL);
+ mm_jpeg_job_wait_for_event(my_obj,
+ MM_JPEG_EVENT_MASK_JPEG_DONE|MM_JPEG_EVENT_MASK_JPEG_ABORT|MM_JPEG_EVENT_MASK_JPEG_ERROR);
+ CDBG("%s:waitForEvent: OMX_CommandFlush: DONE", __func__);
+
+ OMX_SendCommand(my_obj->omx_handle, OMX_CommandStateSet, OMX_StateIdle, NULL);
+ OMX_SendCommand(my_obj->omx_handle, OMX_CommandStateSet, OMX_StateLoaded, NULL);
+
+ /* free buffers used in OMX processing */
+ for (i = 0; i < JPEG_SRC_IMAGE_TYPE_MAX; i++) {
+ for (j = 0; j < job_entry->src_bufs[i].num_bufs; j++) {
+ if (NULL != job_entry->src_bufs[i].bufs[j].buf_header) {
+ OMX_FreeBuffer(my_obj->omx_handle,
+ job_entry->src_bufs[i].bufs[j].portIdx,
+ job_entry->src_bufs[i].bufs[j].buf_header);
+ }
+ }
+ }
+ OMX_FreeBuffer(my_obj->omx_handle,
+ job_entry->sink_buf.portIdx,
+ job_entry->sink_buf.buf_header);
+
+ return rc;
+}
+
+/* TODO: needs revisit after omx lib supports multi src buffers */
+int32_t mm_jpeg_omx_config_main_buffer_offset(mm_jpeg_obj* my_obj, src_image_buffer_info *src_buf)
+{
+ int32_t rc = 0;
+ uint8_t i;
+ OMX_INDEXTYPE buf_offset_idx;
+ omx_jpeg_buffer_offset buffer_offset;
+
+ for (i = 0; i < src_buf->num_bufs; i++) {
+ OMX_GetExtensionIndex(my_obj->omx_handle,
+ "omx.qcom.jpeg.exttype.buffer_offset",
+ &buf_offset_idx);
+ memset(&buffer_offset, 0, sizeof(buffer_offset));
+
+ switch (src_buf->img_fmt) {
+ case JPEG_SRC_IMAGE_FMT_YUV:
+ if (1 == src_buf->src_image[i].offset.num_planes) {
+ buffer_offset.yOffset =
+ src_buf->src_image[i].offset.sp.y_offset;
+ buffer_offset.cbcrOffset =
+ src_buf->src_image[i].offset.sp.cbcr_offset;
+ buffer_offset.totalSize =
+ src_buf->src_image[i].offset.sp.len;
+ } else {
+ buffer_offset.yOffset =
+ src_buf->src_image[i].offset.mp[0].offset;
+ buffer_offset.cbcrOffset =
+ src_buf->src_image[i].offset.mp[1].offset;
+ buffer_offset.totalSize =
+ src_buf->src_image[i].offset.frame_len;
+ }
+ CDBG("%s: idx=%d, yOffset =%d, cbcrOffset =%d, totalSize = %d\n",
+ __func__, i, buffer_offset.yOffset, buffer_offset.cbcrOffset, buffer_offset.totalSize);
+ OMX_SetParameter(my_obj->omx_handle, buf_offset_idx, &buffer_offset);
+ break;
+ case JPEG_SRC_IMAGE_FMT_BITSTREAM:
+ /* TODO: need visit here when bit stream is supported */
+ buffer_offset.yOffset =
+ src_buf->bit_stream[i].data_offset;
+ buffer_offset.totalSize =
+ src_buf->bit_stream[i].buf_size;
+ CDBG("%s: idx=%d, yOffset =%d, cbcrOffset =%d, totalSize = %d\n",
+ __func__, i, buffer_offset.yOffset, buffer_offset.cbcrOffset, buffer_offset.totalSize);
+ OMX_SetParameter(my_obj->omx_handle, buf_offset_idx, &buffer_offset);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return rc;
+}
+
+/* TODO: needs revisit after omx lib supports multi src buffers */
+int32_t mm_jpeg_omx_config_port(mm_jpeg_obj* my_obj, src_image_buffer_info *src_buf, int port_idx)
+{
+ int32_t rc = 0;
+ uint8_t i;
+ OMX_PARAM_PORTDEFINITIONTYPE input_port;
+
+ for (i = 0; i < src_buf->num_bufs; i++) {
+ memset(&input_port, 0, sizeof(input_port));
+ input_port.nPortIndex = port_idx;
+ OMX_GetParameter(my_obj->omx_handle, OMX_IndexParamPortDefinition, &input_port);
+ input_port.format.image.nFrameWidth = src_buf->src_dim.width;
+ input_port.format.image.nFrameHeight =src_buf->src_dim.height;
+ input_port.format.image.nStride = src_buf->src_dim.width;
+ input_port.format.image.nSliceHeight = src_buf->src_dim.height;
+ switch (src_buf->img_fmt) {
+ case JPEG_SRC_IMAGE_FMT_YUV:
+ input_port.nBufferSize = src_buf->src_image[i].offset.frame_len;
+ break;
+ case JPEG_SRC_IMAGE_FMT_BITSTREAM:
+ input_port.nBufferSize = src_buf->bit_stream[i].buf_size;
+ break;
+ }
+
+ OMX_SetParameter(my_obj->omx_handle, OMX_IndexParamPortDefinition, &input_port);
+ }
+
+ return rc;
+}
+
+omx_jpeg_color_format map_jpeg_format(mm_jpeg_color_format color_fmt)
+{
+ switch (color_fmt) {
+ case MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V2:
+ return OMX_YCRCBLP_H2V2;
+ case MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V2:
+ return OMX_YCBCRLP_H2V2;
+ case MM_JPEG_COLOR_FORMAT_YCRCBLP_H2V1:
+ return OMX_YCRCBLP_H2V1;
+ case MM_JPEG_COLOR_FORMAT_YCBCRLP_H2V1:
+ return OMX_YCBCRLP_H2V1;
+ case MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V2:
+ return OMX_YCRCBLP_H1V2;
+ case MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V2:
+ return OMX_YCBCRLP_H1V2;
+ case MM_JPEG_COLOR_FORMAT_YCRCBLP_H1V1:
+ return OMX_YCRCBLP_H1V1;
+ case MM_JPEG_COLOR_FORMAT_YCBCRLP_H1V1:
+ return OMX_YCBCRLP_H1V1;
+ case MM_JPEG_COLOR_FORMAT_RGB565:
+ return OMX_RGB565;
+ case MM_JPEG_COLOR_FORMAT_RGB888:
+ return OMX_RGB888;
+ case MM_JPEG_COLOR_FORMAT_RGBa:
+ return OMX_RGBa;
+ case MM_JPEG_COLOR_FORMAT_BITSTREAM:
+ /* TODO: need to change to new bitstream value once omx interface changes */
+ return OMX_JPEG_BITSTREAM_H2V2;
+ default:
+ return OMX_JPEG_COLOR_FORMAT_MAX;
+ }
+}
+
+int32_t mm_jpeg_omx_config_user_preference(mm_jpeg_obj* my_obj, mm_jpeg_encode_job* job)
+{
+ int32_t rc = 0;
+ OMX_INDEXTYPE user_pref_idx;
+ omx_jpeg_user_preferences user_preferences;
+
+ memset(&user_preferences, 0, sizeof(user_preferences));
+ user_preferences.color_format =
+ map_jpeg_format(job->encode_parm.buf_info.src_imgs.src_img[JPEG_SRC_IMAGE_TYPE_MAIN].color_format);
+ if (job->encode_parm.buf_info.src_imgs.src_img_num > 1) {
+ user_preferences.thumbnail_color_format =
+ map_jpeg_format(job->encode_parm.buf_info.src_imgs.src_img[JPEG_SRC_IMAGE_TYPE_THUMB].color_format);
+ }
+ OMX_GetExtensionIndex(my_obj->omx_handle,
+ "omx.qcom.jpeg.exttype.user_preferences",
+ &user_pref_idx);
+ CDBG("%s:User Preferences: color_format %d, thumbnail_color_format = %d",
+ __func__, user_preferences.color_format, user_preferences.thumbnail_color_format);
+ OMX_SetParameter(my_obj->omx_handle, user_pref_idx, &user_preferences);
+ return rc;
+}
+
+int32_t mm_jpeg_omx_config_thumbnail(mm_jpeg_obj* my_obj, mm_jpeg_encode_job* job)
+{
+ int32_t rc = -1;
+ OMX_INDEXTYPE thumb_idx, q_idx;
+ omx_jpeg_thumbnail thumbnail;
+ omx_jpeg_thumbnail_quality quality;
+
+ src_image_buffer_info *src_buf =
+ &(job->encode_parm.buf_info.src_imgs.src_img[JPEG_SRC_IMAGE_TYPE_THUMB]);
+
+ /* config port */
+ rc = mm_jpeg_omx_config_port(my_obj, src_buf, INPUT_PORT_THUMBNAIL);
+ if (0 != rc) {
+ CDBG_ERROR("%s: config port failed", __func__);
+ return rc;
+ }
+
+ /* check crop boundary */
+ if ((src_buf->crop.width == 0) || (src_buf->crop.height == 0) ||
+ (src_buf->crop.width + src_buf->crop.offset_x > src_buf->src_dim.width) ||
+ (src_buf->crop.height + src_buf->crop.offset_y > src_buf->src_dim.height)) {
+ CDBG_ERROR("%s: invalid crop boundary (%d, %d) offset (%d, %d) out of (%d, %d)",
+ __func__,
+ src_buf->crop.width,
+ src_buf->crop.height,
+ src_buf->crop.offset_x,
+ src_buf->crop.offset_y,
+ src_buf->src_dim.width,
+ src_buf->src_dim.height);
+ return rc;
+ }
+
+ memset(&thumbnail, 0, sizeof(thumbnail));
+
+ /* thumbnail crop info */
+ thumbnail.cropWidth = CEILING2(src_buf->crop.width);
+ thumbnail.cropHeight = CEILING2(src_buf->crop.height);
+ thumbnail.left = src_buf->crop.offset_x;
+ thumbnail.top = src_buf->crop.offset_y;
+
+ /* thumbnail output dimention */
+ thumbnail.width = src_buf->out_dim.width;
+ thumbnail.height = src_buf->out_dim.height;
+
+ /* set scaling flag */
+ if (thumbnail.left > 0 || thumbnail.top > 0 ||
+ src_buf->crop.width != src_buf->out_dim.width ||
+ src_buf->crop.height != src_buf->out_dim.height) {
+ thumbnail.scaling = 1;
+ }
+
+ /* set omx thumbnail info */
+ OMX_GetExtensionIndex(my_obj->omx_handle, "omx.qcom.jpeg.exttype.thumbnail", &thumb_idx);
+ OMX_SetParameter(my_obj->omx_handle, thumb_idx, &thumbnail);
+
+ OMX_GetExtensionIndex(my_obj->omx_handle, "omx.qcom.jpeg.exttype.thumbnail_quality", &q_idx);
+ OMX_GetParameter(my_obj->omx_handle, q_idx, &quality);
+ quality.nQFactor = src_buf->quality;
+ OMX_SetParameter(my_obj->omx_handle, q_idx, &quality);
+
+ rc = 0;
+ return rc;
+}
+
+int32_t mm_jpeg_omx_config_main_crop(mm_jpeg_obj* my_obj, src_image_buffer_info *src_buf)
+{
+ int32_t rc = 0;
+ OMX_CONFIG_RECTTYPE rect_type;
+
+ /* error check first */
+ if (src_buf->crop.width + src_buf->crop.offset_x > src_buf->src_dim.width ||
+ src_buf->crop.height + src_buf->crop.offset_y > src_buf->src_dim.height) {
+ CDBG_ERROR("%s: invalid crop boundary (%d, %d) out of (%d, %d)", __func__,
+ src_buf->crop.width + src_buf->crop.offset_x,
+ src_buf->crop.height + src_buf->crop.offset_y,
+ src_buf->src_dim.width,
+ src_buf->src_dim.height);
+ return -1;
+ }
+
+ if (src_buf->crop.width && src_buf->crop.width) {
+ /* Scaler information */
+ memset(&rect_type, 0, sizeof(rect_type));
+ rect_type.nWidth = CEILING2(src_buf->crop.width);
+ rect_type.nHeight = CEILING2(src_buf->crop.width);
+ rect_type.nLeft = src_buf->crop.offset_x;
+ rect_type.nTop = src_buf->crop.offset_y;
+ rect_type.nPortIndex = OUTPUT_PORT;
+ OMX_SetConfig(my_obj->omx_handle, OMX_IndexConfigCommonInputCrop, &rect_type);
+
+ if (src_buf->out_dim.width && src_buf->out_dim.height) {
+ memset(&rect_type, 0, sizeof(rect_type));
+ rect_type.nWidth = src_buf->out_dim.width;
+ rect_type.nHeight = src_buf->out_dim.height;
+ rect_type.nPortIndex = OUTPUT_PORT;
+ OMX_SetConfig(my_obj->omx_handle, OMX_IndexConfigCommonOutputCrop, &rect_type);
+ }
+
+ } else {
+ CDBG_ERROR("%s: There is no main image scaling information", __func__);
+ rc = -1;
+ }
+
+ return rc;
+}
+
+int32_t mm_jpeg_omx_config_main(mm_jpeg_obj* my_obj, mm_jpeg_encode_job* job)
+{
+ int32_t rc = 0;
+ src_image_buffer_info *src_buf =
+ &(job->encode_parm.buf_info.src_imgs.src_img[JPEG_SRC_IMAGE_TYPE_MAIN]);
+ OMX_IMAGE_PARAM_QFACTORTYPE q_factor;
+
+ /* config port */
+ rc = mm_jpeg_omx_config_port(my_obj, src_buf, INPUT_PORT_MAIN);
+ if (0 != rc) {
+ CDBG_ERROR("%s: config port failed", __func__);
+ return rc;
+ }
+
+ /* config buffer offset */
+ rc = mm_jpeg_omx_config_main_buffer_offset(my_obj, src_buf);
+ if (0 != rc) {
+ CDBG_ERROR("%s: config buffer offset failed", __func__);
+ return rc;
+ }
+
+ /* config crop */
+ rc = mm_jpeg_omx_config_main_crop(my_obj, src_buf);
+ if (0 != rc) {
+ CDBG_ERROR("%s: config crop failed", __func__);
+ return rc;
+ }
+
+ /* set quality */
+ memset(&q_factor, 0, sizeof(q_factor));
+ q_factor.nPortIndex = INPUT_PORT_MAIN;
+ OMX_GetParameter(my_obj->omx_handle, OMX_IndexParamQFactor, &q_factor);
+ q_factor.nQFactor = src_buf->quality;
+ OMX_SetParameter(my_obj->omx_handle, OMX_IndexParamQFactor, &q_factor);
+
+ return rc;
+}
+
+int32_t mm_jpeg_omx_config_common(mm_jpeg_obj* my_obj, mm_jpeg_encode_job* job)
+{
+ int32_t rc;
+ int i;
+ OMX_INDEXTYPE exif_idx;
+ omx_jpeg_exif_info_tag tag;
+ OMX_CONFIG_ROTATIONTYPE rotate;
+
+ /* config user prefernces */
+ rc = mm_jpeg_omx_config_user_preference(my_obj, job);
+ if (0 != rc) {
+ CDBG_ERROR("%s: config user preferences failed", __func__);
+ return rc;
+ }
+
+ /* set rotation */
+ memset(&rotate, 0, sizeof(rotate));
+ rotate.nPortIndex = OUTPUT_PORT;
+ rotate.nRotation = job->encode_parm.rotation;
+ OMX_SetConfig(my_obj->omx_handle, OMX_IndexConfigCommonRotate, &rotate);
+ CDBG("%s: Set rotation to %d\n", __func__, job->encode_parm.rotation);
+
+ /* set exif tags */
+ OMX_GetExtensionIndex(my_obj->omx_handle, "omx.qcom.jpeg.exttype.exif", &exif_idx);
+ for(i = 0; i < job->encode_parm.exif_numEntries; i++) {
+ memcpy(&tag, job->encode_parm.exif_data + i, sizeof(omx_jpeg_exif_info_tag));
+ OMX_SetParameter(my_obj->omx_handle, exif_idx, &tag);
+ }
+
+ return rc;
+}
+
+int32_t mm_jpeg_omx_use_buf(mm_jpeg_obj* my_obj,
+ src_image_buffer_info *src_buf,
+ mm_jpeg_omx_src_buf* omx_src_buf,
+ int port_idx)
+{
+ int32_t rc = 0;
+ uint8_t i;
+ omx_jpeg_pmem_info pmem_info;
+
+ omx_src_buf->num_bufs = src_buf->num_bufs;
+ for (i = 0; i < src_buf->num_bufs; i++) {
+ memset(&pmem_info, 0, sizeof(pmem_info));
+ switch (src_buf->img_fmt) {
+ case JPEG_SRC_IMAGE_FMT_YUV:
+ pmem_info.fd = src_buf->src_image[i].fd;
+ pmem_info.offset = 0;
+ omx_src_buf->bufs[i].portIdx = port_idx;
+ OMX_UseBuffer(my_obj->omx_handle,
+ &omx_src_buf->bufs[i].buf_header,
+ port_idx,
+ &pmem_info,
+ src_buf->src_image[i].offset.frame_len,
+ (void *)src_buf->src_image[i].buf_vaddr);
+ break;
+ case JPEG_SRC_IMAGE_FMT_BITSTREAM:
+ pmem_info.fd = src_buf->bit_stream[i].fd;
+ pmem_info.offset = 0;
+ omx_src_buf->bufs[i].portIdx = port_idx;
+ OMX_UseBuffer(my_obj->omx_handle,
+ &omx_src_buf->bufs[i].buf_header,
+ port_idx,
+ &pmem_info,
+ src_buf->bit_stream[i].buf_size,
+ (void *)src_buf->bit_stream[i].buf_vaddr);
+ break;
+ default:
+ rc = -1;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+int32_t mm_jpeg_omx_encode(mm_jpeg_obj* my_obj, mm_jpeg_job_entry* job_entry)
+{
+ int32_t rc = 0;
+ uint8_t i;
+ mm_jpeg_encode_job* job = &job_entry->job.encode_job;
+ uint8_t has_thumbnail = job->encode_parm.buf_info.src_imgs.src_img_num > 1? 1 : 0;
+ src_image_buffer_info *src_buf[JPEG_SRC_IMAGE_TYPE_MAX];
+ mm_jpeg_omx_src_buf *omx_src_buf[JPEG_SRC_IMAGE_TYPE_MAX];
+
+ /* config main img */
+ rc = mm_jpeg_omx_config_main(my_obj, job);
+ if (0 != rc) {
+ CDBG_ERROR("%s: config main img failed", __func__);
+ return rc;
+ }
+
+ /* config thumbnail */
+ rc = mm_jpeg_omx_config_thumbnail(my_obj, job);
+ if (0 != rc) {
+ CDBG_ERROR("%s: config thumbnail img failed", __func__);
+ return rc;
+ }
+
+ /* common config */
+ rc = mm_jpeg_omx_config_common(my_obj, job);
+ if (0 != rc) {
+ CDBG_ERROR("%s: config common failed", __func__);
+ return rc;
+ }
+
+ /* config input omx buffer for main input */
+ src_buf[JPEG_SRC_IMAGE_TYPE_MAIN] = &(job->encode_parm.buf_info.src_imgs.src_img[JPEG_SRC_IMAGE_TYPE_MAIN]);
+ omx_src_buf[JPEG_SRC_IMAGE_TYPE_MAIN] = &job_entry->src_bufs[JPEG_SRC_IMAGE_TYPE_MAIN];
+ rc = mm_jpeg_omx_use_buf(my_obj,
+ src_buf[JPEG_SRC_IMAGE_TYPE_MAIN],
+ omx_src_buf[JPEG_SRC_IMAGE_TYPE_MAIN],
+ INPUT_PORT_MAIN);
+ if (0 != rc) {
+ CDBG_ERROR("%s: config main input omx buffer failed", __func__);
+ return rc;
+ }
+
+ /* config input omx buffer for thumbnail input if there is thumbnail */
+ if (has_thumbnail) {
+ src_buf[JPEG_SRC_IMAGE_TYPE_THUMB] = &(job->encode_parm.buf_info.src_imgs.src_img[JPEG_SRC_IMAGE_TYPE_THUMB]);
+ omx_src_buf[JPEG_SRC_IMAGE_TYPE_THUMB] = &job_entry->src_bufs[JPEG_SRC_IMAGE_TYPE_THUMB];
+ rc = mm_jpeg_omx_use_buf(my_obj,
+ src_buf[JPEG_SRC_IMAGE_TYPE_THUMB],
+ omx_src_buf[JPEG_SRC_IMAGE_TYPE_THUMB],
+ INPUT_PORT_THUMBNAIL);
+ if (0 != rc) {
+ CDBG_ERROR("%s: config thumbnail input omx buffer failed", __func__);
+ return rc;
+ }
+ }
+
+ /* config output omx buffer */
+ job_entry->sink_buf.portIdx = OUTPUT_PORT;
+ OMX_UseBuffer(my_obj->omx_handle,
+ &job_entry->sink_buf.buf_header,
+ job_entry->sink_buf.portIdx,
+ NULL,
+ job->encode_parm.buf_info.sink_img.buf_len,
+ (void *)job->encode_parm.buf_info.sink_img.buf_vaddr);
+
+ /* wait for OMX state ready */
+ mm_jpeg_job_wait_for_cmd_complete(my_obj, OMX_CommandStateSet, OMX_StateIdle);
+ CDBG("%s: State changed to OMX_StateIdle\n", __func__);
+
+ /* start OMX encoding by sending executing cmd */
+ OMX_SendCommand(my_obj->omx_handle, OMX_CommandStateSet, OMX_StateExecuting, NULL);
+ mm_jpeg_job_wait_for_cmd_complete(my_obj, OMX_CommandStateSet, OMX_StateExecuting);
+
+ /* start input fedding and output writing */
+ for (i = 0; i < job_entry->src_bufs[JPEG_SRC_IMAGE_TYPE_MAIN].num_bufs; i++) {
+ OMX_EmptyThisBuffer(my_obj->omx_handle,
+ job_entry->src_bufs[JPEG_SRC_IMAGE_TYPE_MAIN].bufs[i].buf_header);
+ }
+ if (has_thumbnail) {
+ for (i = 0; i < job_entry->src_bufs[JPEG_SRC_IMAGE_TYPE_THUMB].num_bufs; i++) {
+ OMX_EmptyThisBuffer(my_obj->omx_handle,
+ job_entry->src_bufs[JPEG_SRC_IMAGE_TYPE_THUMB].bufs[i].buf_header);
+ }
+ }
+ OMX_FillThisBuffer(my_obj->omx_handle, job_entry->sink_buf.buf_header);
+
+ return rc;
+}
+
+static void *mm_jpeg_notify_thread(void *data)
+{
+ mm_jpeg_job_q_node_t* job_node = (mm_jpeg_job_q_node_t *)data;
+ mm_jpeg_job_entry * job_entry = &job_node->entry;
+ mm_jpeg_obj* my_obj = (mm_jpeg_obj *)job_entry->jpeg_obj;
+ void* node = NULL;
+ int32_t rc = 0;
+
+ if (NULL == my_obj) {
+ CDBG_ERROR("%s: jpeg obj is NULL", __func__);
+ return NULL;
+ }
+
+ /* Add to cb queue */
+ rc = mm_jpeg_queue_enq(&my_obj->cb_q, data);
+ if (0 != rc) {
+ CDBG_ERROR("%s: enqueue into cb_q failed", __func__);
+ return NULL;
+ }
+
+ /* call cb */
+ if (NULL != job_entry->job.encode_job.jpeg_cb) {
+ /* has callback, send CB */
+ job_entry->job.encode_job.jpeg_cb(job_entry->job_status,
+ job_entry->thumbnail_dropped,
+ job_entry->client_hdl,
+ job_entry->jobId,
+ job_entry->job.encode_job.encode_parm.buf_info.sink_img.buf_vaddr,
+ job_entry->jpeg_size,
+ job_entry->job.encode_job.userdata);
+ } else {
+ CDBG_ERROR("%s: no cb provided, no action", __func__);
+ }
+
+ /* Remove from cb queue */
+ node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->cb_q, job_entry->jobId);
+ if (NULL != node) {
+ free(node);
+ }
+
+ return NULL;
+}
+
+/* process encoding job */
+int32_t mm_jpeg_process_encoding_job(mm_jpeg_obj *my_obj, mm_jpeg_job_q_node_t* job_node)
+{
+ int32_t rc = 0;
+ mm_jpeg_job_entry* job_entry = &job_node->entry;
+
+ /* call OMX_Encode */
+ rc = mm_jpeg_omx_encode(my_obj, job_entry);
+ if (0 == rc) {
+ /* sent encode cmd to OMX, queue job into ongoing queue */
+ rc = mm_jpeg_queue_enq(&my_obj->ongoing_job_q, job_node);
+ } else {
+ /* OMX encode failed, notify error through callback */
+ job_entry->job_status = JPEG_JOB_STATUS_ERROR;
+ if (NULL != job_entry->job.encode_job.jpeg_cb) {
+ /* has callback, create a thread to send CB */
+ pthread_create(&job_entry->cb_pid,
+ NULL,
+ mm_jpeg_notify_thread,
+ (void *)job_node);
+
+ } else {
+ CDBG_ERROR("%s: no cb provided, return here", __func__);
+ free(job_node);
+ }
+ }
+
+ return rc;
+}
+/* process job (encoding/decoding) */
+int32_t mm_jpeg_process_job(mm_jpeg_obj *my_obj, mm_jpeg_job_q_node_t* job_node)
+{
+ int32_t rc = 0;
+
+ switch (job_node->entry.job.job_type) {
+ case JPEG_JOB_TYPE_ENCODE:
+ rc = mm_jpeg_process_encoding_job(my_obj, job_node);
+ break;
+ default:
+ CDBG_ERROR("%s: job type not supported (%d)",
+ __func__, job_node->entry.job.job_type);
+ rc = -1;
+ break;
+ }
+
+ return rc;
+}
+
+static void *mm_jpeg_jobmgr_thread(void *data)
+{
+ int rc = 0;
+ int running = 1;
+ uint32_t num_ongoing_jobs = 0;
+ mm_jpeg_obj *my_obj = (mm_jpeg_obj*)data;
+ mm_jpeg_job_cmd_thread_t *cmd_thread =
+ (mm_jpeg_job_cmd_thread_t *)data;
+ mm_jpeg_job_q_node_t* node = NULL;
+
+ do {
+ do {
+ rc = sem_wait(&cmd_thread->job_sem);
+ if (rc != 0 && errno != EINVAL) {
+ CDBG_ERROR("%s: sem_wait error (%s)",
+ __func__, strerror(errno));
+ return NULL;
+ }
+ } while (rc != 0);
+
+ /* check ongoing q size */
+ num_ongoing_jobs = mm_jpeg_queue_get_size(&my_obj->ongoing_job_q);
+ if (num_ongoing_jobs >= NUM_MAX_JPEG_CNCURRENT_JOBS) {
+ continue;
+ }
+
+ pthread_mutex_lock(&my_obj->job_lock);
+ /* can go ahead with new work */
+ node = (mm_jpeg_job_q_node_t*)mm_jpeg_queue_deq(&cmd_thread->job_queue);
+ if (node != NULL) {
+ switch (node->type) {
+ case MM_JPEG_CMD_TYPE_JOB:
+ rc = mm_jpeg_process_job(my_obj, node);
+ if (0 != rc) {
+ /* free node in error case */
+ free(node);
+ }
+ break;
+ case MM_JPEG_CMD_TYPE_EXIT:
+ default:
+ /* free node */
+ free(node);
+ /* set running flag to false */
+ running = 0;
+ break;
+ }
+ }
+ pthread_mutex_unlock(&my_obj->job_lock);
+
+ } while (running);
+ return NULL;
+}
+
+int32_t mm_jpeg_jobmgr_thread_launch(mm_jpeg_obj * my_obj)
+{
+ int32_t rc = 0;
+ mm_jpeg_job_cmd_thread_t * job_mgr = &my_obj->job_mgr;
+
+ sem_init(&job_mgr->job_sem, 0, 0);
+ mm_jpeg_queue_init(&job_mgr->job_queue);
+
+ /* launch the thread */
+ pthread_create(&job_mgr->pid,
+ NULL,
+ mm_jpeg_jobmgr_thread,
+ (void *)my_obj);
+ return rc;
+}
+
+int32_t mm_jpeg_jobmgr_thread_release(mm_jpeg_obj * my_obj)
+{
+ int32_t rc = 0;
+ mm_jpeg_job_cmd_thread_t * cmd_thread = &my_obj->job_mgr;
+ mm_jpeg_job_q_node_t* node =
+ (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t));
+ if (NULL == node) {
+ CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__);
+ return -1;
+ }
+
+ memset(node, 0, sizeof(mm_jpeg_job_q_node_t));
+ node->type = MM_JPEG_CMD_TYPE_EXIT;
+
+ mm_jpeg_queue_enq(&cmd_thread->job_queue, node);
+ sem_post(&cmd_thread->job_sem);
+
+ /* wait until cmd thread exits */
+ if (pthread_join(cmd_thread->pid, NULL) != 0) {
+ CDBG("%s: pthread dead already\n", __func__);
+ }
+ mm_jpeg_queue_deinit(&cmd_thread->job_queue);
+
+ sem_destroy(&cmd_thread->job_sem);
+ memset(cmd_thread, 0, sizeof(mm_jpeg_job_cmd_thread_t));
+ return rc;
+}
+
+int32_t mm_jpeg_init(mm_jpeg_obj *my_obj)
+{
+ int32_t rc = 0;
+
+ /* init locks */
+ pthread_mutex_init(&my_obj->job_lock, NULL);
+ pthread_mutex_init(&my_obj->omx_evt_lock, NULL);
+ pthread_cond_init(&my_obj->omx_evt_cond, NULL);
+
+ /* init ongoing job queue */
+ rc = mm_jpeg_queue_init(&my_obj->ongoing_job_q);
+
+ /* init job semaphore and launch jobmgr thread */
+ CDBG("%s : Launch jobmgr thread",__func__);
+ rc = mm_jpeg_jobmgr_thread_launch(my_obj);
+
+ /* load OMX */
+ rc = mm_jpeg_omx_load(my_obj);
+ if (0 != rc) {
+ /* roll back in error case */
+ mm_jpeg_jobmgr_thread_release(my_obj);
+ mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
+ pthread_mutex_destroy(&my_obj->job_lock);
+ pthread_mutex_destroy(&my_obj->omx_evt_lock);
+ pthread_cond_destroy(&my_obj->omx_evt_cond);
+ }
+
+ return rc;
+}
+
+int32_t mm_jpeg_deinit(mm_jpeg_obj *my_obj)
+{
+ int32_t rc = 0;
+
+ /* unload OMX engine */
+ rc = mm_jpeg_omx_unload(my_obj);
+
+ /* release jobmgr thread */
+ rc = mm_jpeg_jobmgr_thread_release(my_obj);
+
+ /* deinit ongoing job queue */
+ rc = mm_jpeg_queue_deinit(&my_obj->ongoing_job_q);
+
+ /* destroy locks */
+ pthread_mutex_destroy(&my_obj->job_lock);
+ pthread_mutex_destroy(&my_obj->omx_evt_lock);
+ pthread_cond_destroy(&my_obj->omx_evt_cond);
+
+ return rc;
+}
+
+uint32_t mm_jpeg_new_client(mm_jpeg_obj *my_obj)
+{
+ uint32_t client_hdl = 0;
+ uint8_t idx;
+
+ if (my_obj->num_clients >= MAX_JPEG_CLIENT_NUM) {
+ CDBG_ERROR("%s: num of clients reached limit", __func__);
+ return client_hdl;
+ }
+
+ for (idx = 0; idx < MAX_JPEG_CLIENT_NUM; idx++) {
+ if (0 == my_obj->clnt_mgr[idx].is_used) {
+ break;
+ }
+ }
+
+ if (idx < MAX_JPEG_CLIENT_NUM) {
+ /* client entry avail */
+ /* generate client handler by index */
+ client_hdl = mm_jpeg_util_generate_handler(idx);
+
+ /* update client entry */
+ my_obj->clnt_mgr[idx].is_used = 1;
+ my_obj->clnt_mgr[idx].client_handle = client_hdl;
+
+ /* increse client count */
+ my_obj->num_clients++;
+ }
+
+ return client_hdl;
+}
+
+int32_t mm_jpeg_start_job(mm_jpeg_obj *my_obj,
+ uint32_t client_hdl,
+ mm_jpeg_job* job,
+ uint32_t* jobId)
+{
+ int32_t rc = -1;
+ uint8_t clnt_idx = 0;
+ uint32_t job_id = 0;
+ mm_jpeg_job_q_node_t* node = NULL;
+
+ *jobId = 0;
+
+ /* check if valid client */
+ clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl);
+ if (clnt_idx >= MAX_JPEG_CLIENT_NUM ) {
+ CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl);
+ return rc;
+ }
+
+ /* generate client handler by index */
+ job_id = mm_jpeg_util_generate_handler(clnt_idx);
+
+ /* enqueue new job into todo job queue */
+ node = (mm_jpeg_job_q_node_t *)malloc(sizeof(mm_jpeg_job_q_node_t));
+ if (NULL == node) {
+ CDBG_ERROR("%s: No memory for mm_jpeg_job_q_node_t", __func__);
+ return -rc;
+ }
+
+ memset(node, 0, sizeof(mm_jpeg_job_q_node_t));
+ node->type = MM_JPEG_CMD_TYPE_JOB;
+ node->entry.client_hdl = client_hdl;
+ node->entry.jobId = job_id;
+ memcpy(&node->entry.job, job, sizeof(mm_jpeg_job));
+ node->entry.jpeg_obj = (void*)my_obj; /* save a ptr to jpeg_obj */
+
+ rc = mm_jpeg_queue_enq(&my_obj->job_mgr.job_queue, node);
+ if (0 == rc) {
+ sem_post(&my_obj->job_mgr.job_sem);
+ *jobId = job_id;
+ }
+
+ return rc;
+}
+
+int32_t mm_jpeg_abort_job(mm_jpeg_obj *my_obj,
+ uint32_t client_hdl,
+ uint32_t jobId)
+{
+ int32_t rc = -1;
+ uint8_t clnt_idx = 0;
+ void * node = NULL;
+ mm_jpeg_job_entry* job_entry = NULL;
+
+ /* check if valid client */
+ clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl);
+ if (clnt_idx >= MAX_JPEG_CLIENT_NUM ) {
+ CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl);
+ return rc;
+ }
+
+ pthread_mutex_lock(&my_obj->job_lock);
+
+ /* abort job if in ongoing queue */
+ node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q, jobId);
+ if (NULL != node) {
+ /* find job that is OMX ongoing, ask OMX to abort the job */
+ job_entry = &(((mm_jpeg_job_q_node_t *)node)->entry);
+ rc = mm_jpeg_omx_abort_job(my_obj, job_entry);
+ free(node);
+ goto abort_done;
+ }
+
+ /* abort job if in todo queue */
+ node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->job_mgr.job_queue, jobId);
+ if (NULL != node) {
+ /* simply delete it */
+ free(node);
+ goto abort_done;
+ }
+
+ /* abort job if in cb queue */
+ node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->cb_q, jobId);
+ if (NULL != node) {
+ /* join cb thread */
+ job_entry = &(((mm_jpeg_job_q_node_t *)node)->entry);
+ if (pthread_join(job_entry->cb_pid, NULL) != 0) {
+ CDBG("%s: pthread dead already\n", __func__);
+ }
+ free(node);
+ }
+
+abort_done:
+ pthread_mutex_unlock(&my_obj->job_lock);
+
+ /* wake up jobMgr thread to work on new job if there is any */
+ sem_post(&my_obj->job_mgr.job_sem);
+
+ return rc;
+}
+
+int32_t mm_jpeg_close(mm_jpeg_obj *my_obj, uint32_t client_hdl)
+{
+ int32_t rc = -1;
+ uint8_t clnt_idx = 0;
+ void* node = NULL;
+ mm_jpeg_job_entry* job_entry = NULL;
+
+ /* check if valid client */
+ clnt_idx = mm_jpeg_util_get_index_by_handler(client_hdl);
+ if (clnt_idx >= MAX_JPEG_CLIENT_NUM ) {
+ CDBG_ERROR("%s: invalid client with handler (%d)", __func__, client_hdl);
+ return rc;
+ }
+
+ /* abort all jobs from the client */
+ pthread_mutex_lock(&my_obj->job_lock);
+
+ /* abort job if in ongoing queue */
+ node = mm_jpeg_queue_remove_job_by_client_id(&my_obj->ongoing_job_q, client_hdl);
+ while (NULL != node) {
+ /* find job that is OMX ongoing, ask OMX to abort the job */
+ job_entry = &(((mm_jpeg_job_q_node_t *)node)->entry);
+ rc = mm_jpeg_omx_abort_job(my_obj, job_entry);
+ free(node);
+
+ /* find next job from ongoing queue that belongs to this client */
+ node = mm_jpeg_queue_remove_job_by_client_id(&my_obj->ongoing_job_q, client_hdl);
+ }
+
+ /* abort job if in todo queue */
+ node = mm_jpeg_queue_remove_job_by_client_id(&my_obj->job_mgr.job_queue, client_hdl);
+ while (NULL != node) {
+ /* simply delete the job if in todo queue */
+ free(node);
+
+ /* find next job from todo queue that belongs to this client */
+ node = mm_jpeg_queue_remove_job_by_client_id(&my_obj->job_mgr.job_queue, client_hdl);
+ }
+
+ /* abort job if in cb queue */
+ node = mm_jpeg_queue_remove_job_by_client_id(&my_obj->cb_q, client_hdl);
+ while (NULL != node) {
+ /* join cb thread */
+ job_entry = &(((mm_jpeg_job_q_node_t *)node)->entry);
+ if (pthread_join(job_entry->cb_pid, NULL) != 0) {
+ CDBG("%s: pthread dead already\n", __func__);
+ }
+ free(node);
+
+ /* find next job from cb queue that belongs to this client */
+ node = mm_jpeg_queue_remove_job_by_client_id(&my_obj->cb_q, client_hdl);
+ }
+
+ pthread_mutex_unlock(&my_obj->job_lock);
+
+ /* invalidate client entry */
+ memset(&my_obj->clnt_mgr[clnt_idx], 0, sizeof(mm_jpeg_client_t));
+
+ return rc;
+}
+
+void mm_jpeg_job_wait_for_event(mm_jpeg_obj *my_obj, uint32_t evt_mask)
+{
+ pthread_mutex_lock(&my_obj->omx_evt_lock);
+ while (!(my_obj->omx_evt_rcvd.evt & evt_mask)) {
+ pthread_cond_wait(&my_obj->omx_evt_cond, &my_obj->omx_evt_lock);
+ }
+ CDBG("%s:done", __func__);
+ pthread_mutex_unlock(&my_obj->omx_evt_lock);
+}
+
+void mm_jpeg_job_wait_for_cmd_complete(mm_jpeg_obj *my_obj,
+ int cmd,
+ int status)
+{
+ pthread_mutex_lock(&my_obj->omx_evt_lock);
+ while (!((my_obj->omx_evt_rcvd.evt & MM_JPEG_EVENT_MASK_CMD_COMPLETE) &&
+ (my_obj->omx_evt_rcvd.omx_value1 == cmd) &&
+ (my_obj->omx_evt_rcvd.omx_value2 == status))) {
+ pthread_cond_wait(&my_obj->omx_evt_cond, &my_obj->omx_evt_lock);
+ }
+ CDBG("%s:done", __func__);
+ pthread_mutex_unlock(&my_obj->omx_evt_lock);
+}
+
+OMX_ERRORTYPE mm_jpeg_etbdone(OMX_HANDLETYPE hComponent,
+ OMX_PTR pAppData,
+ OMX_BUFFERHEADERTYPE* pBuffer)
+{
+ /* no process needed for etbdone, return here */
+ return 0;
+}
+
+OMX_ERRORTYPE mm_jpeg_ftbdone(OMX_HANDLETYPE hComponent,
+ OMX_PTR pAppData,
+ OMX_BUFFERHEADERTYPE* pBuffer)
+{
+ int rc = 0;
+ void* node = NULL;
+ mm_jpeg_job_entry* job_entry = NULL;
+ mm_jpeg_obj * my_obj = (mm_jpeg_obj*)pAppData;
+
+ if (NULL != my_obj) {
+ CDBG_ERROR("%s: pAppData is NULL, return here", __func__);
+ return rc;
+ }
+
+ /* signal JPEG_DONE event */
+ pthread_mutex_lock(&my_obj->omx_evt_lock);
+ my_obj->omx_evt_rcvd.evt = MM_JPEG_EVENT_MASK_JPEG_DONE;
+ pthread_cond_signal(&my_obj->omx_evt_cond);
+ pthread_mutex_unlock(&my_obj->omx_evt_lock);
+
+ /* If OMX can support multi encoding, it should provide a way to pass jobID.
+ * then we can find job by jobID from ongoing queue.
+ * For now, since OMX only support one job per time, we simply dequeue it. */
+ pthread_mutex_lock(&my_obj->job_lock);
+ node = mm_jpeg_queue_deq(&my_obj->ongoing_job_q);
+ if (NULL != node) {
+ job_entry = &(((mm_jpeg_job_q_node_t *)node)->entry);;
+ /* find job that is OMX ongoing */
+ job_entry->jpeg_size = pBuffer->nFilledLen;
+ job_entry->job_status = JPEG_JOB_STATUS_DONE;
+ CDBG("%s:filled len = %u, status = %d",
+ __func__, job_entry->jpeg_size, job_entry->job_status);
+
+ if (NULL != job_entry->job.encode_job.jpeg_cb) {
+ /* has callback, create a thread to send CB */
+ pthread_create(&job_entry->cb_pid,
+ NULL,
+ mm_jpeg_notify_thread,
+ node);
+
+ } else {
+ CDBG_ERROR("%s: no cb provided, return here", __func__);
+ free(node);
+ }
+ }
+ pthread_mutex_unlock(&my_obj->job_lock);
+
+ /* Wake up jobMgr thread to work on next job if there is any */
+ sem_post(&my_obj->job_mgr.job_sem);
+
+ return rc;
+}
+
+OMX_ERRORTYPE mm_jpeg_handle_omx_event(OMX_HANDLETYPE hComponent,
+ OMX_PTR pAppData,
+ OMX_EVENTTYPE eEvent,
+ OMX_U32 nData1,
+ OMX_U32 nData2,
+ OMX_PTR pEventData)
+{
+ int rc = 0;
+ void* node = NULL;
+ mm_jpeg_job_entry* job_entry = NULL;
+ mm_jpeg_obj * my_obj = (mm_jpeg_obj*)pAppData;
+ uint32_t jobId = 0;
+
+ if (NULL != my_obj) {
+ CDBG_ERROR("%s: pAppData is NULL, return here", __func__);
+ return rc;
+ }
+
+ /* signal event */
+ switch (eEvent) {
+ case OMX_EVENT_JPEG_ABORT:
+ {
+ /* signal error evt */
+ pthread_mutex_lock(&my_obj->omx_evt_lock);
+ my_obj->omx_evt_rcvd.evt = MM_JPEG_EVENT_MASK_JPEG_ABORT;
+ pthread_cond_signal(&my_obj->omx_evt_cond);
+ pthread_mutex_unlock(&my_obj->omx_evt_lock);
+ }
+ break;
+ case OMX_EventError:
+ {
+ switch (nData1) {
+ case OMX_EVENT_THUMBNAIL_DROPPED:
+ {
+ uint8_t thumbnail_dropped_flag = 1;
+ mm_jpeg_queue_update_flag(&my_obj->ongoing_job_q,
+ jobId,
+ thumbnail_dropped_flag);
+ }
+ break;
+ case OMX_EVENT_JPEG_ERROR:
+ {
+ /* signal error evt */
+ pthread_mutex_lock(&my_obj->omx_evt_lock);
+ my_obj->omx_evt_rcvd.evt = MM_JPEG_EVENT_MASK_JPEG_ERROR;
+ pthread_cond_signal(&my_obj->omx_evt_cond);
+ pthread_mutex_unlock(&my_obj->omx_evt_lock);
+
+ /* send CB for error case */
+ /* If OMX can support multi encoding, it should provide a way to pass jobID.
+ * then we can find job by jobID from ongoing queue.
+ * For now, since OMX only support one job per time, we simply dequeue it. */
+ pthread_mutex_lock(&my_obj->job_lock);
+ node = mm_jpeg_queue_deq(&my_obj->ongoing_job_q);
+ if (NULL != node) {
+ job_entry = &(((mm_jpeg_job_q_node_t *)node)->entry);;
+
+ /* find job that is OMX ongoing */
+ job_entry->job_status = JPEG_JOB_STATUS_ERROR;
+ if (NULL != job_entry->job.encode_job.jpeg_cb) {
+ /* has callback, create a thread to send CB */
+ pthread_create(&job_entry->cb_pid,
+ NULL,
+ mm_jpeg_notify_thread,
+ node);
+
+ } else {
+ CDBG_ERROR("%s: no cb provided, return here", __func__);
+ free(node);
+ }
+ }
+ pthread_mutex_unlock(&my_obj->job_lock);
+
+ /* Wake up jobMgr thread to work on next job if there is any */
+ sem_post(&my_obj->job_mgr.job_sem);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case OMX_EventCmdComplete:
+ {
+ /* signal cmd complete evt */
+ pthread_mutex_lock(&my_obj->omx_evt_lock);
+ my_obj->omx_evt_rcvd.evt = MM_JPEG_EVENT_MASK_CMD_COMPLETE;
+ my_obj->omx_evt_rcvd.omx_value1 = nData1;
+ my_obj->omx_evt_rcvd.omx_value2 = nData2;
+ pthread_cond_signal(&my_obj->omx_evt_cond);
+ pthread_mutex_unlock(&my_obj->omx_evt_lock);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return rc;
+}
+
+/* remove the first job from the queue with matching client handle */
+mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_client_id(mm_jpeg_queue_t* queue, uint32_t client_hdl)
+{
+ mm_jpeg_q_node_t* node = NULL;
+ mm_jpeg_job_q_node_t* data = NULL;
+ mm_jpeg_job_q_node_t* job_node = NULL;
+ struct cam_list *head = NULL;
+ struct cam_list *pos = NULL;
+
+ pthread_mutex_lock(&queue->lock);
+ head = &queue->head.list;
+ pos = head->next;
+ while(pos != head) {
+ node = member_of(pos, mm_jpeg_q_node_t, list);
+ data = (mm_jpeg_job_q_node_t *)node->data;
+
+ if (data && (data->entry.client_hdl == client_hdl)) {
+ job_node = data;
+ cam_list_del_node(&node->list);
+ queue->size--;
+ break;
+ }
+ pos = pos->next;
+ }
+
+ pthread_mutex_unlock(&queue->lock);
+
+ return job_node;
+}
+
+/* remove job from the queue with matching job id */
+mm_jpeg_job_q_node_t* mm_jpeg_queue_remove_job_by_job_id(mm_jpeg_queue_t* queue, uint32_t job_id)
+{
+ mm_jpeg_q_node_t* node = NULL;
+ mm_jpeg_job_q_node_t* data = NULL;
+ mm_jpeg_job_q_node_t* job_node = NULL;
+ struct cam_list *head = NULL;
+ struct cam_list *pos = NULL;
+
+ pthread_mutex_lock(&queue->lock);
+ head = &queue->head.list;
+ pos = head->next;
+ while(pos != head) {
+ node = member_of(pos, mm_jpeg_q_node_t, list);
+ data = (mm_jpeg_job_q_node_t *)node->data;
+
+ if (data && (data->entry.jobId == job_id)) {
+ job_node = data;
+ cam_list_del_node(&node->list);
+ queue->size--;
+ break;
+ }
+ pos = pos->next;
+ }
+
+ pthread_mutex_unlock(&queue->lock);
+
+ return job_node;
+}
+
+/* update thumbnail dropped flag in job queue */
+int32_t mm_jpeg_queue_update_flag(mm_jpeg_queue_t* queue, uint32_t job_id, uint8_t flag)
+{
+ int32_t rc = 0;
+ mm_jpeg_q_node_t* node = NULL;
+ mm_jpeg_job_q_node_t* data = NULL;
+ mm_jpeg_job_q_node_t* job_node = NULL;
+ struct cam_list *head = NULL;
+ struct cam_list *pos = NULL;
+
+ pthread_mutex_lock(&queue->lock);
+ head = &queue->head.list;
+ pos = head->next;
+ while(pos != head) {
+ node = member_of(pos, mm_jpeg_q_node_t, list);
+ data = (mm_jpeg_job_q_node_t *)node->data;
+
+ if (data && (data->entry.jobId == job_id)) {
+ job_node = data;
+ break;
+ }
+ pos = pos->next;
+ }
+
+ if (job_node) {
+ /* find matching job for its job id */
+ job_node->entry.thumbnail_dropped = flag;
+ } else {
+ CDBG_ERROR("%s: No entry for jobId = %d", __func__, job_id);
+ rc = -1;
+ }
+ pthread_mutex_unlock(&queue->lock);
+
+ return rc;
+}
diff --git a/camera/QCamera/stack/mm-jpeg-interface/src/mm_jpeg_interface.c b/camera/QCamera/stack/mm-jpeg-interface/src/mm_jpeg_interface.c
new file mode 100755
index 0000000..bf998c1
--- /dev/null
+++ b/camera/QCamera/stack/mm-jpeg-interface/src/mm_jpeg_interface.c
@@ -0,0 +1,202 @@
+/*
+Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <semaphore.h>
+
+#include "mm_jpeg_dbg.h"
+#include "mm_jpeg_interface.h"
+#include "mm_jpeg.h"
+
+static pthread_mutex_t g_intf_lock = PTHREAD_MUTEX_INITIALIZER;
+static mm_jpeg_obj* g_jpeg_obj = NULL;
+
+static pthread_mutex_t g_handler_lock = PTHREAD_MUTEX_INITIALIZER;
+static uint16_t g_handler_history_count = 0; /* history count for handler */
+
+/* utility function to generate handler */
+uint32_t mm_jpeg_util_generate_handler(uint8_t index)
+{
+ uint32_t handler = 0;
+ pthread_mutex_lock(&g_handler_lock);
+ g_handler_history_count++;
+ if (0 == g_handler_history_count) {
+ g_handler_history_count++;
+ }
+ handler = g_handler_history_count;
+ handler = (handler<<8) | index;
+ pthread_mutex_unlock(&g_handler_lock);
+ return handler;
+}
+
+uint8_t mm_jpeg_util_get_index_by_handler(uint32_t handler)
+{
+ return (handler&0x000000ff);
+}
+
+static int32_t mm_jpeg_intf_start_job(uint32_t client_hdl, mm_jpeg_job* job, uint32_t* jobId)
+{
+ int32_t rc = -1;
+
+ if (0 == client_hdl ||
+ NULL == job ||
+ NULL == jobId) {
+ CDBG_ERROR("%s: invalid parameters for client_hdl, job or jobId", __func__);
+ return rc;
+ }
+
+ pthread_mutex_lock(&g_intf_lock);
+ if (NULL == g_jpeg_obj) {
+ /* mm_jpeg obj not exists, return error */
+ CDBG_ERROR("%s: mm_jpeg is not opened yet", __func__);
+ pthread_mutex_unlock(&g_intf_lock);
+ return rc;
+ }
+
+ rc = mm_jpeg_start_job(g_jpeg_obj, client_hdl, job, jobId);
+ pthread_mutex_unlock(&g_intf_lock);
+ return rc;
+}
+
+static int32_t mm_jpeg_intf_abort_job(uint32_t client_hdl, uint32_t jobId)
+{
+ int32_t rc = -1;
+
+ if (0 == client_hdl || 0 == jobId) {
+ CDBG_ERROR("%s: invalid client_hdl or jobId", __func__);
+ return rc;
+ }
+
+ pthread_mutex_lock(&g_intf_lock);
+ if (NULL == g_jpeg_obj) {
+ /* mm_jpeg obj not exists, return error */
+ CDBG_ERROR("%s: mm_jpeg is not opened yet", __func__);
+ pthread_mutex_unlock(&g_intf_lock);
+ return rc;
+ }
+
+ rc = mm_jpeg_abort_job(g_jpeg_obj, client_hdl, jobId);
+ pthread_mutex_unlock(&g_intf_lock);
+ return rc;
+}
+
+static int32_t mm_jpeg_intf_close(uint32_t client_hdl)
+{
+ int32_t rc = -1;
+
+ if (0 == client_hdl) {
+ CDBG_ERROR("%s: invalid client_hdl", __func__);
+ return rc;
+ }
+
+ pthread_mutex_lock(&g_intf_lock);
+ if (NULL == g_jpeg_obj) {
+ /* mm_jpeg obj not exists, return error */
+ CDBG_ERROR("%s: mm_jpeg is not opened yet", __func__);
+ pthread_mutex_unlock(&g_intf_lock);
+ return rc;
+ }
+
+ rc = mm_jpeg_close(g_jpeg_obj, client_hdl);
+
+ if(0 == rc) {
+ if (0 == g_jpeg_obj->num_clients) {
+ /* No client, close jpeg internally */
+ rc = mm_jpeg_deinit(g_jpeg_obj);
+ free(g_jpeg_obj);
+ g_jpeg_obj = NULL;
+ }
+ }
+
+ pthread_mutex_unlock(&g_intf_lock);
+ return rc;
+}
+
+/* open jpeg client */
+uint32_t jpeg_open(mm_jpeg_ops_t *ops)
+{
+ int32_t rc = 0;
+ uint32_t clnt_hdl = 0;
+ mm_jpeg_obj* jpeg_obj = NULL;
+
+ pthread_mutex_lock(&g_intf_lock);
+ /* first time open */
+ if(NULL == g_jpeg_obj) {
+ jpeg_obj = (mm_jpeg_obj *)malloc(sizeof(mm_jpeg_obj));
+ if(NULL == jpeg_obj) {
+ CDBG_ERROR("%s: no mem", __func__);
+ pthread_mutex_unlock(&g_intf_lock);
+ return clnt_hdl;
+ }
+
+ /* initialize jpeg obj */
+ memset(jpeg_obj, 0, sizeof(mm_jpeg_obj));
+ rc = mm_jpeg_init(jpeg_obj);
+ if(0 != rc) {
+ CDBG_ERROR("%s: mm_jpeg_init err = %d", __func__, rc);
+ free(jpeg_obj);
+ pthread_mutex_unlock(&g_intf_lock);
+ return clnt_hdl;
+ }
+
+ /* remember in global variable */
+ g_jpeg_obj = jpeg_obj;
+ }
+
+ /* open new client */
+ clnt_hdl = mm_jpeg_new_client(g_jpeg_obj);
+ if (clnt_hdl > 0) {
+ /* valid client */
+ if (NULL != ops) {
+ /* fill in ops tbl if ptr not NULL */
+ ops->start_job = mm_jpeg_intf_start_job;
+ ops->abort_job = mm_jpeg_intf_abort_job;
+ //ops->abort_job_all = mm_jpeg_intf_close,
+ ops->close = mm_jpeg_intf_close;
+ }
+ } else {
+ /* failed new client */
+ CDBG_ERROR("%s: mm_jpeg_new_client failed", __func__);
+
+ if (0 == g_jpeg_obj->num_clients) {
+ /* no client, close jpeg */
+ mm_jpeg_deinit(g_jpeg_obj);
+ free(g_jpeg_obj);
+ g_jpeg_obj = NULL;
+ }
+ }
+
+ pthread_mutex_unlock(&g_intf_lock);
+ return clnt_hdl;
+}
diff --git a/camera/QCamera/stack/mm-jpeg-interface/src/mm_jpeg_queue.c b/camera/QCamera/stack/mm-jpeg-interface/src/mm_jpeg_queue.c
new file mode 100755
index 0000000..9e9723a
--- /dev/null
+++ b/camera/QCamera/stack/mm-jpeg-interface/src/mm_jpeg_queue.c
@@ -0,0 +1,134 @@
+/*
+Copyright (c) 2012, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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.
+*/
+
+#include <pthread.h>
+#include "mm_jpeg_dbg.h"
+#include "mm_jpeg.h"
+
+int32_t mm_jpeg_queue_init(mm_jpeg_queue_t* queue)
+{
+ pthread_mutex_init(&queue->lock, NULL);
+ cam_list_init(&queue->head.list);
+ queue->size = 0;
+ return 0;
+}
+
+int32_t mm_jpeg_queue_enq(mm_jpeg_queue_t* queue, void* data)
+{
+ mm_jpeg_q_node_t* node =
+ (mm_jpeg_q_node_t *)malloc(sizeof(mm_jpeg_q_node_t));
+ if (NULL == node) {
+ CDBG_ERROR("%s: No memory for mm_jpeg_q_node_t", __func__);
+ return -1;
+ }
+
+ memset(node, 0, sizeof(mm_jpeg_q_node_t));
+ node->data = data;
+
+ pthread_mutex_lock(&queue->lock);
+ cam_list_add_tail_node(&node->list, &queue->head.list);
+ queue->size++;
+ pthread_mutex_unlock(&queue->lock);
+
+ return 0;
+
+}
+
+void* mm_jpeg_queue_deq(mm_jpeg_queue_t* queue)
+{
+ mm_jpeg_q_node_t* node = NULL;
+ void* data = NULL;
+ struct cam_list *head = NULL;
+ struct cam_list *pos = NULL;
+
+ pthread_mutex_lock(&queue->lock);
+ head = &queue->head.list;
+ pos = head->next;
+ if (pos != head) {
+ node = member_of(pos, mm_jpeg_q_node_t, list);
+ cam_list_del_node(&node->list);
+ queue->size--;
+ }
+ pthread_mutex_unlock(&queue->lock);
+
+ if (NULL != node) {
+ data = node->data;
+ free(node);
+ }
+
+ return data;
+}
+
+uint32_t mm_jpeg_queue_get_size(mm_jpeg_queue_t* queue)
+{
+ uint32_t size = 0;
+
+ pthread_mutex_lock(&queue->lock);
+ size = queue->size;
+ pthread_mutex_unlock(&queue->lock);
+
+ return size;
+
+}
+
+int32_t mm_jpeg_queue_deinit(mm_jpeg_queue_t* queue)
+{
+ mm_jpeg_queue_flush(queue);
+ pthread_mutex_destroy(&queue->lock);
+ return 0;
+}
+
+int32_t mm_jpeg_queue_flush(mm_jpeg_queue_t* queue)
+{
+ mm_jpeg_q_node_t* node = NULL;
+ void* data = NULL;
+ struct cam_list *head = NULL;
+ struct cam_list *pos = NULL;
+
+ pthread_mutex_lock(&queue->lock);
+ head = &queue->head.list;
+ pos = head->next;
+
+ while(pos != head) {
+ node = member_of(pos, mm_jpeg_q_node_t, list);
+ cam_list_del_node(&node->list);
+ queue->size--;
+
+ /* for now we only assume there is no ptr inside data
+ * so we free data directly */
+ if (NULL != node->data) {
+ free(node->data);
+ }
+ free(node);
+ pos = pos->next;
+ }
+ queue->size = 0;
+ pthread_mutex_unlock(&queue->lock);
+ return 0;
+}
diff --git a/camera/QCameraHWI.cpp b/camera/QCameraHWI.cpp
index ff4204a..5bc9e32 100644
--- a/camera/QCameraHWI.cpp
+++ b/camera/QCameraHWI.cpp
@@ -200,7 +200,7 @@
property_get("camera.hal.fps", value, "0");
mFps = atoi(value);
- ALOGV("Init mPreviewState = %d", mPreviewState);
+ ALOGI("Init mPreviewState = %d", mPreviewState);
property_get("persist.camera.hal.multitouchaf", value, "0");
mMultiTouch = atoi(value);
@@ -233,24 +233,24 @@
loadTables();
/* Setup Picture Size and Preview size tables */
setPictureSizeTable();
- ALOGV("%s: Picture table size: %d", __func__, mPictureSizeCount);
- ALOGV("%s: Picture table: ", __func__);
+ ALOGD("%s: Picture table size: %d", __func__, mPictureSizeCount);
+ ALOGD("%s: Picture table: ", __func__);
for(unsigned int i=0; i < mPictureSizeCount;i++) {
- ALOGV(" %d %d", mPictureSizes[i].width, mPictureSizes[i].height);
+ ALOGD(" %d %d", mPictureSizes[i].width, mPictureSizes[i].height);
}
setPreviewSizeTable();
- ALOGV("%s: Preview table size: %d", __func__, mPreviewSizeCount);
- ALOGV("%s: Preview table: ", __func__);
+ ALOGD("%s: Preview table size: %d", __func__, mPreviewSizeCount);
+ ALOGD("%s: Preview table: ", __func__);
for(unsigned int i=0; i < mPreviewSizeCount;i++) {
- ALOGV(" %d %d", mPreviewSizes[i].width, mPreviewSizes[i].height);
+ ALOGD(" %d %d", mPreviewSizes[i].width, mPreviewSizes[i].height);
}
setVideoSizeTable();
- ALOGV("%s: Video table size: %d", __func__, mVideoSizeCount);
- ALOGV("%s: Video table: ", __func__);
+ ALOGD("%s: Video table size: %d", __func__, mVideoSizeCount);
+ ALOGD("%s: Video table: ", __func__);
for(unsigned int i=0; i < mVideoSizeCount;i++) {
- ALOGV(" %d %d", mVideoSizes[i].width, mVideoSizes[i].height);
+ ALOGD(" %d %d", mVideoSizes[i].width, mVideoSizes[i].height);
}
/* set my mode - update myMode member variable due to difference in
@@ -281,12 +281,12 @@
}
mCameraState = CAMERA_STATE_READY;
- ALOGV("QCameraHardwareInterface: X");
+ ALOGI("QCameraHardwareInterface: X");
}
QCameraHardwareInterface::~QCameraHardwareInterface()
{
- ALOGV("~QCameraHardwareInterface: E");
+ ALOGI("~QCameraHardwareInterface: E");
int result;
switch(mPreviewState) {
@@ -339,7 +339,7 @@
pthread_mutex_destroy(&mAsyncCmdMutex);
pthread_cond_destroy(&mAsyncCmdWait);
- ALOGV("~QCameraHardwareInterface: X");
+ ALOGI("~QCameraHardwareInterface: X");
}
bool QCameraHardwareInterface::isCameraReady()
@@ -350,7 +350,7 @@
void QCameraHardwareInterface::release()
{
- ALOGV("release: E");
+ ALOGI("release: E");
Mutex::Autolock l(&mLock);
switch(mPreviewState) {
@@ -374,23 +374,23 @@
#if 0
if (isRecordingRunning()) {
stopRecordingInternal();
- ALOGV("release: stopRecordingInternal done.");
+ ALOGI("release: stopRecordingInternal done.");
}
if (isPreviewRunning()) {
stopPreview(); //stopPreviewInternal();
- ALOGV("release: stopPreviewInternal done.");
+ ALOGI("release: stopPreviewInternal done.");
}
if (isSnapshotRunning()) {
cancelPictureInternal();
- ALOGV("release: cancelPictureInternal done.");
+ ALOGI("release: cancelPictureInternal done.");
}
if (mCameraState == CAMERA_STATE_ERROR) {
//TBD: If Error occurs then tear down
- ALOGV("release: Tear down.");
+ ALOGI("release: Tear down.");
}
#endif
mPreviewState = QCAMERA_HAL_PREVIEW_STOPPED;
- ALOGV("release: X");
+ ALOGI("release: X");
}
void QCameraHardwareInterface::setCallbacks(
@@ -400,63 +400,63 @@
camera_request_memory get_memory,
void *user)
{
- ALOGV("setCallbacks: E");
+ ALOGE("setCallbacks: E");
Mutex::Autolock lock(mLock);
mNotifyCb = notify_cb;
mDataCb = data_cb;
mDataCbTimestamp = data_cb_timestamp;
mGetMemory = get_memory;
mCallbackCookie = user;
- ALOGV("setCallbacks: X");
+ ALOGI("setCallbacks: X");
}
void QCameraHardwareInterface::enableMsgType(int32_t msgType)
{
- ALOGV("enableMsgType: E, msgType =0x%x", msgType);
+ ALOGI("enableMsgType: E, msgType =0x%x", msgType);
Mutex::Autolock lock(mLock);
mMsgEnabled |= msgType;
- ALOGV("enableMsgType: X, msgType =0x%x, mMsgEnabled=0x%x", msgType, mMsgEnabled);
+ ALOGI("enableMsgType: X, msgType =0x%x, mMsgEnabled=0x%x", msgType, mMsgEnabled);
}
void QCameraHardwareInterface::disableMsgType(int32_t msgType)
{
- ALOGV("disableMsgType: E");
+ ALOGI("disableMsgType: E");
Mutex::Autolock lock(mLock);
mMsgEnabled &= ~msgType;
- ALOGV("disableMsgType: X, msgType =0x%x, mMsgEnabled=0x%x", msgType, mMsgEnabled);
+ ALOGI("disableMsgType: X, msgType =0x%x, mMsgEnabled=0x%x", msgType, mMsgEnabled);
}
int QCameraHardwareInterface::msgTypeEnabled(int32_t msgType)
{
- ALOGV("msgTypeEnabled: E");
+ ALOGI("msgTypeEnabled: E");
Mutex::Autolock lock(mLock);
return (mMsgEnabled & msgType);
- ALOGV("msgTypeEnabled: X");
+ ALOGI("msgTypeEnabled: X");
}
#if 0
status_t QCameraHardwareInterface::dump(int fd, const Vector<String16>& args) const
{
- ALOGV("dump: E");
+ ALOGI("dump: E");
const size_t SIZE = 256;
char buffer[SIZE];
String8 result;
AutoMutex lock(&mLock);
write(fd, result.string(), result.size());
- ALOGV("dump: E");
+ ALOGI("dump: E");
return NO_ERROR;
}
#endif
int QCameraHardwareInterface::dump(int fd)
{
- ALOGV("%s: not supported yet", __func__);
+ ALOGE("%s: not supported yet", __func__);
return -1;
}
status_t QCameraHardwareInterface::sendCommand(int32_t command, int32_t arg1,
int32_t arg2)
{
- ALOGV("sendCommand: E");
+ ALOGI("sendCommand: E");
status_t rc = NO_ERROR;
Mutex::Autolock l(&mLock);
@@ -550,13 +550,13 @@
default:
break;
}
- ALOGV("sendCommand: X");
+ ALOGI("sendCommand: X");
return rc;
}
void QCameraHardwareInterface::setMyMode(int mode)
{
- ALOGV("setMyMode: E");
+ ALOGI("setMyMode: E");
//if (mode & CAMERA_SUPPORT_MODE_3D) {
// myMode = CAMERA_MODE_3D;
//}else {
@@ -569,13 +569,13 @@
//}else {
myMode = (camera_mode_t) (myMode | CAMERA_NONZSL_MODE);
//}
- ALOGV("setMyMode: Set mode to %d (passed mode: %d)", myMode, mode);
- ALOGV("setMyMode: X");
+ ALOGI("setMyMode: Set mode to %d (passed mode: %d)", myMode, mode);
+ ALOGI("setMyMode: X");
}
/* static factory function */
QCameraHardwareInterface *QCameraHardwareInterface::createInstance(int cameraId, int mode)
{
- ALOGV("createInstance: E");
+ ALOGI("createInstance: E");
QCameraHardwareInterface *cam = new QCameraHardwareInterface(cameraId, mode);
if (cam ) {
if (cam->mCameraState != CAMERA_STATE_READY) {
@@ -587,7 +587,7 @@
if (cam) {
//sp<CameraHardwareInterface> hardware(cam);
- ALOGV("createInstance: X");
+ ALOGI("createInstance: X");
return cam;
} else {
return NULL;
@@ -597,24 +597,24 @@
extern "C" void *
QCameraHAL_openCameraHardware(int cameraId, int mode)
{
- ALOGV("QCameraHAL_openCameraHardware: E");
+ ALOGI("QCameraHAL_openCameraHardware: E");
return (void *) QCameraHardwareInterface::createInstance(cameraId, mode);
}
#if 0
bool QCameraHardwareInterface::useOverlay(void)
{
- ALOGV("useOverlay: E");
+ ALOGI("useOverlay: E");
mUseOverlay = TRUE;
- ALOGV("useOverlay: X");
+ ALOGI("useOverlay: X");
return mUseOverlay;
}
#endif
bool QCameraHardwareInterface::isPreviewRunning() {
- ALOGV("isPreviewRunning: E");
+ ALOGI("isPreviewRunning: E");
bool ret = false;
- ALOGV("isPreviewRunning: camera state:%d", mCameraState);
+ ALOGI("isPreviewRunning: camera state:%d", mCameraState);
if((mCameraState == CAMERA_STATE_PREVIEW) ||
(mCameraState == CAMERA_STATE_PREVIEW_START_CMD_SENT) ||
@@ -624,7 +624,7 @@
(mCameraState == CAMERA_STATE_ZSL_START_CMD_SENT)){
return true;
}
- ALOGV("isPreviewRunning: X");
+ ALOGI("isPreviewRunning: X");
return ret;
}
@@ -659,7 +659,7 @@
ret = true;
break;
}
- ALOGV("isSnapshotRunning: X");
+ ALOGI("isSnapshotRunning: X");
return ret;
}
@@ -682,7 +682,7 @@
nsecs_t diff = now - mLastFpsTime;
if (diff > ms2ns(250)) {
mFps = ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
- ALOGV("Preview Frames Per Second: %.4f", mFps);
+ ALOGI("Preview Frames Per Second: %.4f", mFps);
mLastFpsTime = now;
mLastFrameCount = mFrameCount;
}
@@ -690,7 +690,7 @@
void QCameraHardwareInterface::
processPreviewChannelEvent(mm_camera_ch_event_type_t channelEvent, app_notify_cb_t *app_cb) {
- ALOGV("processPreviewChannelEvent: E");
+ ALOGI("processPreviewChannelEvent: E");
switch(channelEvent) {
case MM_CAMERA_CH_EVT_STREAMING_ON:
mCameraState =
@@ -704,13 +704,13 @@
default:
break;
}
- ALOGV("processPreviewChannelEvent: X");
+ ALOGI("processPreviewChannelEvent: X");
return;
}
void QCameraHardwareInterface::processRecordChannelEvent(
mm_camera_ch_event_type_t channelEvent, app_notify_cb_t *app_cb) {
- ALOGV("processRecordChannelEvent: E");
+ ALOGI("processRecordChannelEvent: E");
switch(channelEvent) {
case MM_CAMERA_CH_EVT_STREAMING_ON:
mCameraState = CAMERA_STATE_RECORD;
@@ -723,13 +723,13 @@
default:
break;
}
- ALOGV("processRecordChannelEvent: X");
+ ALOGI("processRecordChannelEvent: X");
return;
}
void QCameraHardwareInterface::
processSnapshotChannelEvent(mm_camera_ch_event_type_t channelEvent, app_notify_cb_t *app_cb) {
- ALOGV("processSnapshotChannelEvent: E evt=%d state=%d", channelEvent,
+ ALOGI("processSnapshotChannelEvent: E evt=%d state=%d", channelEvent,
mCameraState);
switch(channelEvent) {
case MM_CAMERA_CH_EVT_STREAMING_ON:
@@ -758,14 +758,14 @@
default:
break;
}
- ALOGV("processSnapshotChannelEvent: X");
+ ALOGI("processSnapshotChannelEvent: X");
return;
}
void QCameraHardwareInterface::processChannelEvent(
mm_camera_ch_event_t *event, app_notify_cb_t *app_cb)
{
- ALOGV("processChannelEvent: E");
+ ALOGI("processChannelEvent: E");
Mutex::Autolock lock(mLock);
switch(event->ch) {
case MM_CAMERA_CH_PREVIEW:
@@ -780,13 +780,13 @@
default:
break;
}
- ALOGV("processChannelEvent: X");
+ ALOGI("processChannelEvent: X");
return;
}
void QCameraHardwareInterface::processCtrlEvent(mm_camera_ctrl_event_t *event, app_notify_cb_t *app_cb)
{
- ALOGV("processCtrlEvent: %d, E",event->evt);
+ ALOGI("processCtrlEvent: %d, E",event->evt);
Mutex::Autolock lock(mLock);
switch(event->evt)
{
@@ -810,14 +810,14 @@
default:
break;
}
- ALOGV("processCtrlEvent: X");
+ ALOGI("processCtrlEvent: X");
return;
}
void QCameraHardwareInterface::processStatsEvent(
mm_camera_stats_event_t *event, app_notify_cb_t *app_cb)
{
- ALOGV("processStatsEvent: E");
+ ALOGI("processStatsEvent: E");
if (!isPreviewRunning( )) {
ALOGE("preview is not running");
return;
@@ -864,7 +864,7 @@
void QCameraHardwareInterface::processInfoEvent(
mm_camera_info_event_t *event, app_notify_cb_t *app_cb) {
- ALOGV("processInfoEvent: %d, E",event->event_id);
+ ALOGI("processInfoEvent: %d, E",event->event_id);
//Mutex::Autolock lock(eventLock);
switch(event->event_id)
{
@@ -874,16 +874,16 @@
default:
break;
}
- ALOGV("processInfoEvent: X");
+ ALOGI("processInfoEvent: X");
return;
}
void QCameraHardwareInterface::processEvent(mm_camera_event_t *event)
{
app_notify_cb_t app_cb;
- ALOGV("processEvent: type :%d E",event->event_type);
+ ALOGE("processEvent: type :%d E",event->event_type);
if(mPreviewState == QCAMERA_HAL_PREVIEW_STOPPED){
- ALOGV("Stop recording issued. Return from process Event");
+ ALOGE("Stop recording issued. Return from process Event");
return;
}
memset(&app_cb, 0, sizeof(app_notify_cb_t));
@@ -904,7 +904,7 @@
default:
break;
}
- ALOGV(" App_cb Notify %p, datacb=%p", app_cb.notifyCb, app_cb.dataCb);
+ ALOGE(" App_cb Notify %p, datacb=%p", app_cb.notifyCb, app_cb.dataCb);
if (app_cb.notifyCb) {
app_cb.notifyCb(app_cb.argm_notify.msg_type,
app_cb.argm_notify.ext1, app_cb.argm_notify.ext2,
@@ -915,14 +915,14 @@
app_cb.argm_data_cb.data, app_cb.argm_data_cb.index,
app_cb.argm_data_cb.metadata, app_cb.argm_data_cb.cookie);
}
- ALOGV("processEvent: X");
+ ALOGI("processEvent: X");
return;
}
bool QCameraHardwareInterface::preview_parm_config (cam_ctrl_dimension_t* dim,
QCameraParameters& parm)
{
- ALOGV("preview_parm_config: E");
+ ALOGI("preview_parm_config: E");
bool matching = true;
int display_width = 0; /* width of display */
int display_height = 0; /* height of display */
@@ -971,7 +971,7 @@
else
dim->main_img_format = CAMERA_YUV_420_NV21;
dim->thumb_format = CAMERA_YUV_420_NV21;
- ALOGV("preview_parm_config: X");
+ ALOGI("preview_parm_config: X");
return matching;
}
@@ -1013,7 +1013,7 @@
status_t QCameraHardwareInterface::startPreview2()
{
- ALOGV("startPreview2: E");
+ ALOGI("startPreview2: E");
status_t ret = NO_ERROR;
cam_ctrl_dimension_t dim;
@@ -1057,7 +1057,7 @@
dim.picture_width = maxDim.width;
dim.picture_height = maxDim.height;
mParameters.setPictureSize(dim.picture_width, dim.picture_height);
- ALOGV("%s Setting Liveshot dimension as %d x %d", __func__,
+ ALOGI("%s Setting Liveshot dimension as %d x %d", __func__,
maxDim.width, maxDim.height);
#endif
int mPictureWidth, mPictureHeight;
@@ -1127,13 +1127,13 @@
mPostPreviewHeap = NULL;
}
- ALOGV("startPreview: X");
+ ALOGI("startPreview: X");
return ret;
}
void QCameraHardwareInterface::stopPreview()
{
- ALOGV("%s: stopPreview: E", __func__);
+ ALOGI("%s: stopPreview: E", __func__);
Mutex::Autolock lock(mLock);
mm_camera_util_profile("HAL: stopPreview(): E");
mFaceDetectOn = false;
@@ -1165,24 +1165,24 @@
default:
break;
}
- ALOGV("stopPreview: X, mPreviewState = %d", mPreviewState);
+ ALOGI("stopPreview: X, mPreviewState = %d", mPreviewState);
}
#if 0 //mzhu
void QCameraHardwareInterface::stopPreviewZSL()
{
- ALOGV("stopPreviewZSL: E");
+ ALOGI("stopPreviewZSL: E");
if(!mStreamDisplay || !mStreamSnap) {
ALOGE("mStreamDisplay/mStreamSnap is null");
return;
}
- ALOGV("stopPreview: X, mPreviewState = %d", mPreviewState);
+ ALOGI("stopPreview: X, mPreviewState = %d", mPreviewState);
}
#endif
void QCameraHardwareInterface::stopPreviewInternal()
{
- ALOGV("stopPreviewInternal: E");
+ ALOGI("stopPreviewInternal: E");
status_t ret = NO_ERROR;
if(!mStreamDisplay) {
@@ -1197,12 +1197,12 @@
mStreamDisplay->stop();
mCameraState = CAMERA_STATE_PREVIEW_STOP_CMD_SENT;
- ALOGV("stopPreviewInternal: X");
+ ALOGI("stopPreviewInternal: X");
}
int QCameraHardwareInterface::previewEnabled()
{
- ALOGV("previewEnabled: E");
+ ALOGI("previewEnabled: E");
Mutex::Autolock lock(mLock);
ALOGE("%s: mCameraState = %d", __func__, mCameraState);
switch(mPreviewState) {
@@ -1222,7 +1222,7 @@
status_t QCameraHardwareInterface::startRecording()
{
- ALOGV("startRecording: E");
+ ALOGI("startRecording: E");
status_t ret = NO_ERROR;
Mutex::Autolock lock(mLock);
@@ -1271,13 +1271,13 @@
ret = BAD_VALUE;
break;
}
- ALOGV("startRecording: X");
+ ALOGI("startRecording: X");
return ret;
}
void QCameraHardwareInterface::stopRecording()
{
- ALOGV("stopRecording: E");
+ ALOGI("stopRecording: E");
Mutex::Autolock lock(mLock);
switch(mPreviewState) {
case QCAMERA_HAL_PREVIEW_STOPPED:
@@ -1292,12 +1292,12 @@
default:
break;
}
- ALOGV("stopRecording: X");
+ ALOGI("stopRecording: X");
}
void QCameraHardwareInterface::stopRecordingInternal()
{
- ALOGV("stopRecordingInternal: E");
+ ALOGI("stopRecordingInternal: E");
status_t ret = NO_ERROR;
if(!mStreamRecord) {
@@ -1312,7 +1312,7 @@
mStreamRecord->stop();
mCameraState = CAMERA_STATE_PREVIEW; //TODO : Apurva : Hacked for 2nd time Recording
mPreviewState = QCAMERA_HAL_PREVIEW_STARTED;
- ALOGV("stopRecordingInternal: X");
+ ALOGI("stopRecordingInternal: X");
return;
}
@@ -1354,18 +1354,18 @@
status_t QCameraHardwareInterface::autoFocusEvent(cam_ctrl_status_t *status, app_notify_cb_t *app_cb)
{
- ALOGV("autoFocusEvent: E");
+ ALOGE("autoFocusEvent: E");
int ret = NO_ERROR;
/************************************************************
BEGIN MUTEX CODE
*************************************************************/
- ALOGV("%s:%d: Trying to acquire AF bit lock",__func__,__LINE__);
+ ALOGE("%s:%d: Trying to acquire AF bit lock",__func__,__LINE__);
mAutofocusLock.lock();
- ALOGV("%s:%d: Acquired AF bit lock",__func__,__LINE__);
+ ALOGE("%s:%d: Acquired AF bit lock",__func__,__LINE__);
if(mAutoFocusRunning==false) {
- ALOGV("%s:AF not running, discarding stale event",__func__);
+ ALOGE("%s:AF not running, discarding stale event",__func__);
mAutofocusLock.unlock();
return ret;
}
@@ -1428,7 +1428,7 @@
status_t QCameraHardwareInterface::cancelPicture()
{
- ALOGV("cancelPicture: E");
+ ALOGI("cancelPicture: E");
status_t ret = MM_CAMERA_OK;
Mutex::Autolock lock(mLock);
@@ -1443,13 +1443,13 @@
ret = cancelPictureInternal();
break;
}
- ALOGV("cancelPicture: X");
+ ALOGI("cancelPicture: X");
return ret;
}
status_t QCameraHardwareInterface::cancelPictureInternal()
{
- ALOGV("cancelPictureInternal: E");
+ ALOGI("cancelPictureInternal: E");
status_t ret = MM_CAMERA_OK;
if(mCameraState != CAMERA_STATE_READY) {
if(mStreamSnap) {
@@ -1459,7 +1459,7 @@
} else {
ALOGE("%s: Cannot process cancel picture as snapshot is already done",__func__);
}
- ALOGV("cancelPictureInternal: X");
+ ALOGI("cancelPictureInternal: X");
return ret;
}
@@ -1480,9 +1480,17 @@
QCameraHardwareInterface *pme = (QCameraHardwareInterface *)user_data;
cam_ctrl_dimension_t dim;
int mJpegMaxSize;
+ int mNuberOfVFEOutputs = 0;
status_t ret;
ALOGE("%s: E", __func__);
+ ret = cam_config_get_parm(pme->mCameraId,MM_CAMERA_PARM_VFE_OUTPUT_ENABLE,
+ &mNuberOfVFEOutputs);
+ if (ret != MM_CAMERA_OK) {
+ ALOGE("get parm MM_CAMERA_PARM_VFE_OUTPUT_ENABLE failed");
+ cam_evt_buf_done(pme->mCameraId, recvd_frame);
+ return ;
+ }
mm_camera_ch_data_buf_t* frame =
(mm_camera_ch_data_buf_t *)malloc(sizeof(mm_camera_ch_data_buf_t));
@@ -1493,7 +1501,10 @@
}
memcpy(frame, recvd_frame, sizeof(mm_camera_ch_data_buf_t));
- ALOGE("<DEBUG> Liveshot buffer idx:%d",frame->video.video.idx);
+ if (mNuberOfVFEOutputs == 1)
+ ALOGE("<DEBUG> Liveshot buffer idx:%d",frame->def.idx);
+ else
+ ALOGE("<DEBUG> Liveshot buffer idx:%d",frame->video.video.idx);
memset(&dim, 0, sizeof(cam_ctrl_dimension_t));
ret = cam_config_get_parm(pme->mCameraId, MM_CAMERA_PARM_DIMENSION, &dim);
if (MM_CAMERA_OK != ret) {
@@ -1503,17 +1514,29 @@
#if 1
ALOGE("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;
+ if (mNuberOfVFEOutputs == 1){
+ frame->snapshot.main.frame = frame->def.frame;
+ frame->snapshot.main.idx = frame->def.idx;
+ frame->snapshot.thumbnail.frame = frame->def.frame;
+ frame->snapshot.thumbnail.idx = frame->def.idx;
+ } else {
+ 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 = pme->mDimension.video_width;
dim.picture_height = pme->mDimension.video_height;
dim.ui_thumbnail_width = pme->mDimension.video_width;
dim.ui_thumbnail_height = pme->mDimension.video_height;
- dim.main_img_format = pme->mDimension.enc_format;
- dim.thumb_format = pme->mDimension.enc_format;
+ if (mNuberOfVFEOutputs == 1){
+ dim.main_img_format = pme->mDimension.prev_format;
+ dim.thumb_format = pme->mDimension.prev_format;
+ } else {
+ dim.main_img_format = pme->mDimension.enc_format;
+ dim.thumb_format = pme->mDimension.enc_format;
+ }
mJpegMaxSize = pme->mDimension.video_width * pme->mDimension.video_width * 1.5;
@@ -1554,8 +1577,9 @@
status_t QCameraHardwareInterface::takePicture()
{
- ALOGV("takePicture: E");
+ ALOGI("takePicture: E");
status_t ret = MM_CAMERA_OK;
+ int mNuberOfVFEOutputs = 0;
Mutex::Autolock lock(mLock);
mStreamSnap->resetSnapshotCounters( );
@@ -1616,11 +1640,25 @@
ALOGD(" Calling takeFullSizeLiveshot");
takeFullSizeLiveshot();
}else{
- (void) cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_VIDEO,
+ ret = cam_config_get_parm(mCameraId, MM_CAMERA_PARM_VFE_OUTPUT_ENABLE,
+ &mNuberOfVFEOutputs);
+ if (ret != MM_CAMERA_OK) {
+ ALOGE("get parm MM_CAMERA_PARM_VFE_OUTPUT_ENABLE failed");
+ ret = BAD_VALUE;
+ }
+ if (mNuberOfVFEOutputs == 1){
+ (void) cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_PREVIEW,
liveshot_callback,
MM_CAMERA_REG_BUF_CB_COUNT,
1,
this);
+ } else {
+ (void) cam_evt_register_buf_notify(mCameraId, MM_CAMERA_CH_VIDEO,
+ liveshot_callback,
+ MM_CAMERA_REG_BUF_CB_COUNT,
+ 1,
+ this);
+ }
}
break;
@@ -1628,7 +1666,7 @@
ret = UNKNOWN_ERROR;
break;
}
- ALOGV("takePicture: X");
+ ALOGI("takePicture: X");
return ret;
}
@@ -1711,18 +1749,18 @@
status_t QCameraHardwareInterface::takeLiveSnapshot()
{
status_t ret = NO_ERROR;
- ALOGV("takeLiveSnapshot: E");
+ ALOGI("takeLiveSnapshot: E");
mStreamRecord->takeLiveSnapshot();
- ALOGV("takeLiveSnapshot: X");
+ ALOGI("takeLiveSnapshot: X");
return ret;
}
status_t QCameraHardwareInterface::autoFocus()
{
- ALOGV("autoFocus: E");
+ ALOGI("autoFocus: E");
status_t ret = NO_ERROR;
Mutex::Autolock lock(mLock);
- ALOGV("autoFocus: Got lock");
+ ALOGI("autoFocus: Got lock");
bool status = true;
isp3a_af_mode_t afMode = getAutoFocusMode(mParameters);
@@ -1746,7 +1784,7 @@
ALOGE("%s:Invalid AF mode (%d)", __func__, afMode);
}
- ALOGV("%s:AF start (mode %d)", __func__, afMode);
+ ALOGI("%s:AF start (mode %d)", __func__, afMode);
if(MM_CAMERA_OK != cam_ops_action(mCameraId, TRUE,
MM_CAMERA_OPS_FOCUS, &afMode)) {
ALOGE("%s: AF command failed err:%d error %s",
@@ -1755,7 +1793,7 @@
}
mAutoFocusRunning = true;
- ALOGV("autoFocus: X");
+ ALOGI("autoFocus: X");
return ret;
}
@@ -1804,7 +1842,7 @@
*=========================================================================*/
void QCameraHardwareInterface::prepareSnapshotAndWait()
{
- ALOGV("prepareSnapshotAndWait: E");
+ ALOGI("prepareSnapshotAndWait: E");
int rc = 0;
/*To Do: call mm camera preparesnapshot */
if(!rc ) {
@@ -1814,7 +1852,7 @@
pthread_mutex_unlock(&mAsyncCmdMutex);
mPreparingSnapshot = false;
}
- ALOGV("prepareSnapshotAndWait: X");
+ ALOGI("prepareSnapshotAndWait: X");
}
#endif //mzhu
@@ -1826,16 +1864,16 @@
*=========================================================================*/
void QCameraHardwareInterface::processprepareSnapshotEvent(cam_ctrl_status_t *status)
{
- ALOGV("processprepareSnapshotEvent: E");
+ ALOGI("processprepareSnapshotEvent: E");
pthread_mutex_lock(&mAsyncCmdMutex);
pthread_cond_signal(&mAsyncCmdWait);
pthread_mutex_unlock(&mAsyncCmdMutex);
- ALOGV("processprepareSnapshotEvent: X");
+ ALOGI("processprepareSnapshotEvent: X");
}
void QCameraHardwareInterface::roiEvent(fd_roi_t roi,app_notify_cb_t *app_cb)
{
- ALOGV("roiEvent: E");
+ ALOGE("roiEvent: E");
if(mStreamDisplay) mStreamDisplay->notifyROIEvent(roi);
#if 0 //TODO: move to preview obj
@@ -1882,7 +1920,7 @@
mMetaDataWaitLock.unlock();
}
#endif // mzhu
- ALOGV("roiEvent: X");
+ ALOGE("roiEvent: X");
}
@@ -1891,20 +1929,20 @@
mm_camera_ch_crop_t v4l2_crop;
- ALOGV("%s: E", __func__);
+ ALOGI("%s: E", __func__);
memset(&v4l2_crop,0,sizeof(v4l2_crop));
v4l2_crop.ch_type=MM_CAMERA_CH_SNAPSHOT;
- ALOGV("%s: Fetching crop info", __func__);
+ ALOGI("%s: Fetching crop info", __func__);
cam_config_get_parm(mCameraId,MM_CAMERA_PARM_CROP,&v4l2_crop);
- ALOGV("%s: Crop info received for main: %d, %d, %d, %d ", __func__,
+ ALOGI("%s: Crop info received for main: %d, %d, %d, %d ", __func__,
v4l2_crop.snapshot.main_crop.left,
v4l2_crop.snapshot.main_crop.top,
v4l2_crop.snapshot.main_crop.width,
v4l2_crop.snapshot.main_crop.height);
- ALOGV("%s: Crop info received for thumbnail: %d, %d, %d, %d ",__func__,
+ ALOGI("%s: Crop info received for thumbnail: %d, %d, %d, %d ",__func__,
v4l2_crop.snapshot.thumbnail_crop.left,
v4l2_crop.snapshot.thumbnail_crop.top,
v4l2_crop.snapshot.thumbnail_crop.width,
@@ -1925,17 +1963,17 @@
{
mm_camera_ch_crop_t v4l2_crop;
- ALOGV("%s: E", __func__);
+ ALOGI("%s: E", __func__);
/*regular zooming or smooth zoom stopped*/
if (!mSmoothZoomRunning && mPreviewWindow) {
memset(&v4l2_crop, 0, sizeof(v4l2_crop));
v4l2_crop.ch_type = MM_CAMERA_CH_PREVIEW;
- ALOGV("%s: Fetching crop info", __func__);
+ ALOGI("%s: Fetching crop info", __func__);
cam_config_get_parm(mCameraId,MM_CAMERA_PARM_CROP,&v4l2_crop);
- ALOGV("%s: Crop info received: %d, %d, %d, %d ", __func__,
+ ALOGI("%s: Crop info received: %d, %d, %d, %d ", __func__,
v4l2_crop.crop.left,
v4l2_crop.crop.top,
v4l2_crop.crop.width,
@@ -1946,16 +1984,16 @@
v4l2_crop.crop.top,
v4l2_crop.crop.left + v4l2_crop.crop.width,
v4l2_crop.crop.top + v4l2_crop.crop.height);
- ALOGV("%s: Done setting crop", __func__);
- ALOGV("%s: Currrent zoom :%d",__func__, mCurrentZoom);
+ ALOGI("%s: Done setting crop", __func__);
+ ALOGI("%s: Currrent zoom :%d",__func__, mCurrentZoom);
}
- ALOGV("%s: X", __func__);
+ ALOGI("%s: X", __func__);
}
void QCameraHardwareInterface::zoomEvent(cam_ctrl_status_t *status, app_notify_cb_t *app_cb)
{
- ALOGV("zoomEvent: state:%d E",mPreviewState);
+ ALOGI("zoomEvent: state:%d E",mPreviewState);
switch (mPreviewState) {
case QCAMERA_HAL_PREVIEW_STOPPED:
break;
@@ -1979,13 +2017,14 @@
default:
break;
}
- ALOGV("zoomEvent: X");
+ ALOGI("zoomEvent: X");
}
void QCameraHardwareInterface::dumpFrameToFile(const void * data, uint32_t size, char* name, char* ext, int index)
{
char buf[32];
int file_fd;
+ static int i = 0 ;
if ( data != NULL) {
char * str;
snprintf(buf, sizeof(buf), "/data/%s_%d.%s", name, index, ext);
@@ -1993,6 +2032,7 @@
file_fd = open(buf, O_RDWR | O_CREAT, 0777);
write(file_fd, data, size);
close(file_fd);
+ i++;
}
}
@@ -2458,9 +2498,9 @@
void QCameraHardwareInterface::wdenoiseEvent(cam_ctrl_status_t status, void *cookie)
{
- ALOGV("wdnEvent: preview state:%d E",mPreviewState);
+ ALOGI("wdnEvent: preview state:%d E",mPreviewState);
if (mStreamSnap != NULL) {
- ALOGV("notifyWDNEvent to snapshot stream");
+ ALOGI("notifyWDNEvent to snapshot stream");
mStreamSnap->notifyWDenoiseEvent(status, cookie);
}
}
diff --git a/camera/QCameraHWI_Parm.cpp b/camera/QCameraHWI_Parm.cpp
index 6d9fc79..09fe6b0 100644
--- a/camera/QCameraHWI_Parm.cpp
+++ b/camera/QCameraHWI_Parm.cpp
@@ -923,6 +923,27 @@
mParameters.set("overlay-format", HAL_PIXEL_FORMAT_YCbCr_420_SP);
mParameters.set("max-num-detected-faces-hw", "2");
+ // Set supported max faces
+ int maxNumFaces = 0;
+ if (supportsFaceDetection()) {
+ //Query the maximum number of faces supported by hardware.
+ if(MM_CAMERA_OK != cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_MAX_NUM_FACES_DECT, &maxNumFaces)){
+ ALOGE("%s:Failed to get max number of faces supported",__func__);
+ }
+ }
+ mParameters.set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW, maxNumFaces);
+ //This paramtere is set to default here. This will be changed by application
+ //if it needs to support specific number of faces. See also setParameters.
+ mParameters.set(QCameraParameters::KEY_MAX_NUM_REQUESTED_FACES, 2);
+
+ // Set camera features supported flag
+ int32_t featureFlag = 0;
+ if (supportsFaceDetection()) {
+ featureFlag |= 0x00000001; // bit 0 indicate faciral feature
+ }
+ mParameters.set(QCameraParameters::KEY_SUPPORTED_CAMERA_FEATURES, featureFlag);
+
//Set Picture Size
mParameters.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
mParameters.set(QCameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
@@ -1439,36 +1460,11 @@
if (str != NULL) {
int value = attr_lookup(facedetection,
sizeof(facedetection) / sizeof(str_map), str);
-#if 0
- mMetaDataWaitLock.lock();
- if (value == true) {
- if(mMetaDataHeap != NULL)
- mMetaDataHeap.clear();
-
- mMetaDataHeap =
- new AshmemPool((sizeof(int)*(MAX_ROI*4+1)),
- 1,
- (sizeof(int)*(MAX_ROI*4+1)),
- "metadata");
- if (!mMetaDataHeap->initialized()) {
- ALOGE("Meta Data Heap allocation failed ");
- mMetaDataHeap.clear();
- ALOGE("runFaceDetection X: error initializing mMetaDataHeap");
- mMetaDataWaitLock.unlock();
- return UNKNOWN_ERROR;
- }
- mSendMetaData = true;
- } else {
- if(mMetaDataHeap != NULL)
- mMetaDataHeap.clear();
- }
- mMetaDataWaitLock.unlock();
-#endif
- cam_ctrl_dimension_t dim;
- cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim);
- preview_parm_config (&dim, mParameters);
- ret = cam_config_set_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim);
- ret = native_set_parms(MM_CAMERA_PARM_FD, sizeof(int8_t), (void *)&value);
+ fd_set_parm_t fd_set_parm;
+ int requested_faces = mParameters.getInt(QCameraParameters::KEY_MAX_NUM_REQUESTED_FACES);
+ fd_set_parm.fd_mode = value;
+ fd_set_parm.num_fd = requested_faces;
+ ret = native_set_parms(MM_CAMERA_PARM_FD, sizeof(fd_set_parm_t), (void *)&fd_set_parm);
return ret ? NO_ERROR : UNKNOWN_ERROR;
}
ALOGE("Invalid Face Detection value: %s", (str == NULL) ? "NULL" : str);
@@ -2961,18 +2957,23 @@
status_t QCameraHardwareInterface::setFaceDetect(const QCameraParameters& params)
{
+ int requested_faces = params.getInt(QCameraParameters::KEY_MAX_NUM_REQUESTED_FACES);
+ int hardware_supported_faces = mParameters.getInt(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW);
+ if (requested_faces > hardware_supported_faces) {
+ requested_faces = hardware_supported_faces;
+ }
+ mParameters.set(QCameraParameters::KEY_MAX_NUM_REQUESTED_FACES, requested_faces);
const char *str = params.get(QCameraParameters::KEY_FACE_DETECTION);
ALOGE("setFaceDetect: %s", str);
if (str != NULL) {
+ fd_set_parm_t fd_set_parm;
int value = attr_lookup(facedetection,
sizeof(facedetection) / sizeof(str_map), str);
mFaceDetectOn = value;
- ALOGV("%s Face detection value = %d",__func__, value);
- cam_ctrl_dimension_t dim;
-// cam_config_get_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim);
-// preview_parm_config (&dim, mParameters);
-// cam_config_set_parm(mCameraId, MM_CAMERA_PARM_DIMENSION,&dim);
- native_set_parms(MM_CAMERA_PARM_FD, sizeof(int8_t), (void *)&value);
+ fd_set_parm.fd_mode = value;
+ fd_set_parm.num_fd = requested_faces;
+ ALOGE("%s Face detection value = %d, num_fd = %d",__func__, value, requested_faces);
+ native_set_parms(MM_CAMERA_PARM_FD, sizeof(fd_set_parm_t), (void *)&fd_set_parm);
mParameters.set(QCameraParameters::KEY_FACE_DETECTION, str);
return NO_ERROR;
}
@@ -2986,14 +2987,18 @@
return NO_ERROR;
}
if (str != NULL) {
+ int requested_faces = mParameters.getInt(QCameraParameters::KEY_MAX_NUM_REQUESTED_FACES);
int value = attr_lookup(facedetection,
sizeof(facedetection) / sizeof(str_map), str);
if (value != NOT_FOUND) {
+ fd_set_parm_t fd_set_parm;
mMetaDataWaitLock.lock();
mFaceDetectOn = value;
mMetaDataWaitLock.unlock();
- mParameters.set(QCameraParameters::KEY_FACE_DETECTION, str);
- native_set_parms(MM_CAMERA_PARM_FD, sizeof(int8_t), (void *)&value);
+ fd_set_parm.fd_mode = value;
+ fd_set_parm.num_fd = requested_faces;
+ ALOGI("%s Face detection value = %d, num_fd = %d",__func__, value, requested_faces);
+ native_set_parms(MM_CAMERA_PARM_FD, sizeof(fd_set_parm_t), (void *)&fd_set_parm);
mParameters.set(QCameraParameters::KEY_FACE_DETECTION, str);
return NO_ERROR;
}
diff --git a/camera/QCameraHWI_Preview.cpp b/camera/QCameraHWI_Preview.cpp
index 02ec5a4..f2df36f 100644
--- a/camera/QCameraHWI_Preview.cpp
+++ b/camera/QCameraHWI_Preview.cpp
@@ -462,10 +462,13 @@
mHalCamCtrl->mFace[idx].blink_detected = roi.d.data.face.blink_detected;
mHalCamCtrl->mFace[idx].face_recognised = roi.d.data.face.is_face_recognised;
mHalCamCtrl->mFace[idx].gaze_angle = roi.d.data.face.gaze_angle;
+
/* newly added */
- mHalCamCtrl->mFace[idx].updown_dir = roi.d.data.face.updown_dir;
- mHalCamCtrl->mFace[idx].leftright_dir = roi.d.data.face.leftright_dir;
- mHalCamCtrl->mFace[idx].roll_dir = roi.d.data.face.roll_dir;
+ // upscale by 2 to recover from demaen downscaling
+ mHalCamCtrl->mFace[idx].updown_dir = roi.d.data.face.updown_dir*2;
+ mHalCamCtrl->mFace[idx].leftright_dir = roi.d.data.face.leftright_dir*2;
+ mHalCamCtrl->mFace[idx].roll_dir = roi.d.data.face.roll_dir*2;
+
mHalCamCtrl->mFace[idx].leye_blink = roi.d.data.face.left_blink;
mHalCamCtrl->mFace[idx].reye_blink = roi.d.data.face.right_blink;
mHalCamCtrl->mFace[idx].left_right_gaze = roi.d.data.face.left_right_gaze;
diff --git a/camera/QCameraHWI_Preview_7x27A.cpp b/camera/QCameraHWI_Preview_7x27A.cpp
index acb8bc1..a2fa672 100644
--- a/camera/QCameraHWI_Preview_7x27A.cpp
+++ b/camera/QCameraHWI_Preview_7x27A.cpp
@@ -302,9 +302,21 @@
roi.d.data.face.mouth_center[1]*2000/mHalCamCtrl->mDimension.display_height - 1000;
mHalCamCtrl->mFace[idx].smile_degree = roi.d.data.face.smile_degree;
- mHalCamCtrl->mFace[idx].smile_score = roi.d.data.face.smile_confidence / 10; //Keep within range 1~100
+ mHalCamCtrl->mFace[idx].smile_score = roi.d.data.face.smile_confidence;
mHalCamCtrl->mFace[idx].blink_detected = roi.d.data.face.blink_detected;
mHalCamCtrl->mFace[idx].face_recognised = roi.d.data.face.is_face_recognised;
+ mHalCamCtrl->mFace[idx].gaze_angle = roi.d.data.face.gaze_angle;
+
+ /* newly added */
+ // upscale by 2 to recover from demaen downscaling
+ mHalCamCtrl->mFace[idx].updown_dir = roi.d.data.face.updown_dir*2;
+ mHalCamCtrl->mFace[idx].leftright_dir = roi.d.data.face.leftright_dir*2;
+ mHalCamCtrl->mFace[idx].roll_dir = roi.d.data.face.roll_dir*2;
+
+ mHalCamCtrl->mFace[idx].leye_blink = roi.d.data.face.left_blink;
+ mHalCamCtrl->mFace[idx].reye_blink = roi.d.data.face.right_blink;
+ mHalCamCtrl->mFace[idx].left_right_gaze = roi.d.data.face.left_right_gaze;
+ mHalCamCtrl->mFace[idx].top_bottom_gaze = roi.d.data.face.top_bottom_gaze;
ALOGE("%s: Face(%d, %d, %d, %d), leftEye(%d, %d), rightEye(%d, %d), mouth(%d, %d), smile(%d, %d), blinked(%d)", __func__,
mHalCamCtrl->mFace[idx].rect[0], mHalCamCtrl->mFace[idx].rect[1],
diff --git a/camera/QCameraHWI_Still.cpp b/camera/QCameraHWI_Still.cpp
index 4b4946a..7d5e16e 100644
--- a/camera/QCameraHWI_Still.cpp
+++ b/camera/QCameraHWI_Still.cpp
@@ -486,6 +486,7 @@
status_t ret = NO_ERROR;
mm_camera_ch_image_fmt_parm_t fmt;
mm_camera_channel_attr_t ch_attr;
+ cam_format_t raw_fmt;
mm_camera_raw_streaming_type_t raw_stream_type =
MM_CAMERA_RAW_STREAMING_CAPTURE_SINGLE;
@@ -512,9 +513,17 @@
goto end;
}
+ ret = cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_RAW_SNAPSHOT_FMT, &raw_fmt);
+ if (NO_ERROR != ret) {
+ ALOGE("%s: error - can't get raw snapshot fmt!", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
memset(&fmt, 0, sizeof(mm_camera_ch_image_fmt_parm_t));
fmt.ch_type = MM_CAMERA_CH_RAW;
- fmt.def.fmt = CAMERA_BAYER_SBGGR10;
+ fmt.def.fmt = raw_fmt;
fmt.def.dim.width = dim->raw_picture_width;
fmt.def.dim.height = dim->raw_picture_height;
@@ -646,6 +655,7 @@
uint8_t num_planes;
uint32_t planes[VIDEO_MAX_PLANES];
mm_camera_reg_buf_t reg_buf;
+ cam_format_t raw_fmt;
ALOGD("%s: E", __func__);
memset(®_buf, 0, sizeof(mm_camera_reg_buf_t));
@@ -665,8 +675,16 @@
}
memset(reg_buf.def.buf.mp, 0, num_of_buf * sizeof(mm_camera_mp_buf_t));
+ ret = cam_config_get_parm(mCameraId,
+ MM_CAMERA_PARM_RAW_SNAPSHOT_FMT, &raw_fmt);
+ if (NO_ERROR != ret) {
+ ALOGE("%s: error - can't get raw snapshot fmt!", __func__);
+ ret = FAILED_TRANSACTION;
+ goto end;
+ }
+
/* Get a frame len for buffer to be allocated*/
- frame_len = mm_camera_get_msm_frame_len(CAMERA_BAYER_SBGGR10,
+ frame_len = mm_camera_get_msm_frame_len(raw_fmt,
myMode,
dim->raw_picture_width,
dim->raw_picture_height,
@@ -1487,6 +1505,8 @@
int width, height;
uint8_t *thumbnail_buf;
uint32_t thumbnail_fd;
+ uint8_t hw_encode = true;
+ int mNuberOfVFEOutputs = 0;
omx_jpeg_encode_params encode_params;
@@ -1577,7 +1597,25 @@
set_callbacks(snapshot_jpeg_fragment_cb, snapshot_jpeg_cb, this,
mHalCamCtrl->mJpegMemory.camera_memory[0]->data, &mJpegOffset);
- if(omxJpegStart() != NO_ERROR){
+ if (isLiveSnapshot() || isFullSizeLiveshot()) {
+ /* determine the target type */
+ ret = cam_config_get_parm(mCameraId,MM_CAMERA_PARM_VFE_OUTPUT_ENABLE,
+ &mNuberOfVFEOutputs);
+ if (ret != MM_CAMERA_OK) {
+ ALOGE("get parm MM_CAMERA_PARM_VFE_OUTPUT_ENABLE failed");
+ ret = BAD_VALUE;
+ }
+ /* VFE 2x has hardware limitation:
+ * It can't support concurrent
+ * video encoding and jpeg encoding
+ * So switch to software for liveshot
+ */
+ if (mNuberOfVFEOutputs == 1)
+ hw_encode = false;
+ }
+ ALOGD("%s: hw_encode: %d\n",__func__, hw_encode);
+
+ if(omxJpegStart(hw_encode) != NO_ERROR){
ALOGE("Error In omxJpegStart!!! Return");
ret = FAILED_TRANSACTION;
goto end;
diff --git a/camera/QCameraParameters.cpp b/camera/QCameraParameters.cpp
index 1d387c6..7405468 100644
--- a/camera/QCameraParameters.cpp
+++ b/camera/QCameraParameters.cpp
@@ -136,6 +136,8 @@
const char QCameraParameters::KEY_MAX_SATURATION[] = "max-saturation";
const char QCameraParameters::KEY_SINGLE_ISP_OUTPUT_ENABLED[] = "single-isp-output-enabled";
+const char QCameraParameters::KEY_SUPPORTED_CAMERA_FEATURES[] = "qc-camera-features";
+const char QCameraParameters::KEY_MAX_NUM_REQUESTED_FACES[] = "qc-max-num-requested-faces";
//Values for DENOISE
const char QCameraParameters::DENOISE_OFF[] = "denoise-off";
diff --git a/camera/QCameraParameters.h b/camera/QCameraParameters.h
index 6920413..84cbfec 100644
--- a/camera/QCameraParameters.h
+++ b/camera/QCameraParameters.h
@@ -229,6 +229,8 @@
static const char KEY_SINGLE_ISP_OUTPUT_ENABLED[];
+ static const char KEY_SUPPORTED_CAMERA_FEATURES[];
+ static const char KEY_MAX_NUM_REQUESTED_FACES[];
enum {
CAMERA_ORIENTATION_UNKNOWN = 0,
diff --git a/camera/QCamera_Intf.h b/camera/QCamera_Intf.h
index 22ba919..12c85ac 100644
--- a/camera/QCamera_Intf.h
+++ b/camera/QCamera_Intf.h
@@ -81,7 +81,8 @@
CAMERA_RDI,
CAMERA_YUV_420_YV12,
CAMERA_YUV_422_NV16,
- CAMERA_YUV_422_NV61
+ CAMERA_YUV_422_NV61,
+ CAMERA_YUV_422_YUYV,
} cam_format_t;
typedef enum {
@@ -208,6 +209,7 @@
uint32_t default_preview_width;
uint32_t default_preview_height;
uint32_t bestshot_reconfigure;
+ uint32_t pxlcode;
}cam_prop_t;
typedef struct {
@@ -242,6 +244,7 @@
cam_format_t main_img_format;
cam_format_t rdi0_format;
cam_format_t rdi1_format;
+ cam_format_t raw_img_format;
cam_pad_format_t prev_padding_format;
cam_pad_format_t enc_padding_format;
cam_pad_format_t thumb_padding_format;
@@ -270,6 +273,31 @@
uint32_t channel_interface_mask;
} cam_ctrl_dimension_t;
+typedef struct {
+ uint8_t cid;
+ uint8_t dt;
+ uint32_t inst_handle;
+} cam_cid_entry_t;
+
+#define CAM_MAX_CID_NUM 8
+typedef struct {
+ /*should we hard code max CIDs? if not we need to have two CMD*/
+ uint8_t num_cids;
+ cam_cid_entry_t cid_entries[CAM_MAX_CID_NUM];
+} cam_cid_info_t;
+
+typedef struct {
+ /* we still use prev, video, main,
+ * thumb to interprete image types */
+ uint32_t image_mode; /* input */
+ cam_format_t format; /* input */
+ cam_pad_format_t padding_format; /* input */
+ int rotation; /* input */
+ uint16_t width; /* input/output */
+ uint16_t height; /* input/output */
+ cam_frame_len_offset_t frame_offset; /* output */
+} cam_frame_resolution_t;
+
/* Add enumenrations at the bottom but before MM_CAMERA_PARM_MAX */
typedef enum {
MM_CAMERA_PARM_PICT_SIZE,
@@ -375,8 +403,12 @@
MM_CAMERA_PARM_CH_INTERFACE,
//or single output enabled to differentiate 7x27a with others
MM_CAMERA_PARM_BESTSHOT_RECONFIGURE,
- MM_CAMERA_MAX_NUM_FACES_DECT,
+ MM_CAMERA_PARM_MAX_NUM_FACES_DECT,
MM_CAMERA_PARM_FPS_RANGE,
+ MM_CAMERA_PARM_CID,
+ MM_CAMERA_PARM_FRAME_RESOLUTION,
+ MM_CAMERA_PARM_RAW_SNAPSHOT_FMT,
+ MM_CAMERA_PARM_FACIAL_FEATURE_INFO,
MM_CAMERA_PARM_CAF_LOCK_CANCEL,
MM_CAMERA_PARM_MAX
} mm_camera_parm_type_t;
@@ -518,6 +550,9 @@
CAMERA_GET_MAX_NUM_FACES_DECT,
CAMERA_SET_CHANNEL_STREAM,
CAMERA_GET_CHANNEL_STREAM,
+ CAMERA_SET_PARM_CID, /*125*/
+ CAMERA_GET_PARM_FRAME_RESOLUTION,
+ CAMERA_GET_FACIAL_FEATURE_INFO,
CAMERA_SET_CAF_LOCK_CANCEL,
CAMERA_CTRL_PARM_MAX
} cam_ctrl_type;
@@ -583,6 +618,10 @@
CAMERA_ISO_MAX
} camera_iso_mode_type;
+typedef enum {
+ MM_CAMERA_FACIAL_FEATURE_FD, // facial detection
+ MM_CAMERA_FACIAL_FEATURE_MAX
+} camera_facial_features;
typedef enum {
AEC_ROI_OFF,
@@ -828,6 +867,11 @@
} fd_roi_type_t;
typedef struct {
+ int fd_mode;
+ int num_fd;
+} fd_set_parm_t;
+
+typedef struct {
uint32_t frame_id;
int16_t num_face_detected;
} fd_roi_header_type;
diff --git a/camera/mm-camera-interface/mm_camera.c b/camera/mm-camera-interface/mm_camera.c
index 227e00b..727a884 100644
--- a/camera/mm-camera-interface/mm_camera.c
+++ b/camera/mm-camera-interface/mm_camera.c
@@ -312,7 +312,7 @@
CAMERA_SET_SCE_FACTOR, sizeof(int32_t), (void *)parm->p_value);
case MM_CAMERA_PARM_FD:
return mm_camera_send_native_ctrl_cmd(my_obj,
- CAMERA_SET_PARM_FD, sizeof(int32_t), (void *)parm->p_value);
+ CAMERA_SET_PARM_FD, sizeof(fd_set_parm_t), (void *)parm->p_value);
case MM_CAMERA_PARM_AEC_LOCK:
return mm_camera_send_native_ctrl_cmd(my_obj,
CAMERA_SET_AEC_LOCK, sizeof(int32_t), (void *)parm->p_value);
@@ -527,6 +527,9 @@
dim->width, dim->height);
}
break;
+ case MM_CAMERA_PARM_RAW_SNAPSHOT_FMT:
+ *((cam_format_t *)parm->p_value) = my_obj->properties.pxlcode;
+ break;
case MM_CAMERA_PARM_PREVIEW_FORMAT:
*((int *)parm->p_value) = my_obj->properties.preview_format;
break;
@@ -630,6 +633,12 @@
case MM_CAMERA_PARM_VFE_OUTPUT_ENABLE:
*((int *)parm->p_value) = my_obj->properties.vfe_output_enable;
break;
+ case MM_CAMERA_PARM_MAX_NUM_FACES_DECT:
+ return mm_camera_send_native_ctrl_cmd(my_obj, CAMERA_GET_MAX_NUM_FACES_DECT,
+ sizeof(int), (void *)parm->p_value);
+ case MM_CAMERA_PARM_FACIAL_FEATURE_INFO:
+ return mm_camera_send_native_ctrl_cmd(my_obj, CAMERA_GET_FACIAL_FEATURE_INFO,
+ sizeof(int), (void *)parm->p_value);
default:
/* needs to add more implementation */
rc = -1;
diff --git a/camera/mm-camera-interface/mm_camera_helper.c b/camera/mm-camera-interface/mm_camera_helper.c
index 7d0377d..bee4e0b 100644
--- a/camera/mm-camera-interface/mm_camera_helper.c
+++ b/camera/mm-camera-interface/mm_camera_helper.c
@@ -217,6 +217,11 @@
plane[0] = PAD_TO_WORD(width * height);
size = plane[0];
break;
+ case CAMERA_YUV_422_YUYV:
+ *num_planes = 1;
+ plane[0] = PAD_TO_WORD(width * height);
+ size = plane[0];
+ break;
case CAMERA_YUV_422_NV16:
case CAMERA_YUV_422_NV61:
if( image_type == OUTPUT_TYPE_S || image_type == OUTPUT_TYPE_V) {
diff --git a/camera/mm-camera-interface/mm_camera_stream.c b/camera/mm-camera-interface/mm_camera_stream.c
index 4b12757..96c23d9 100644
--- a/camera/mm-camera-interface/mm_camera_stream.c
+++ b/camera/mm-camera-interface/mm_camera_stream.c
@@ -315,6 +315,10 @@
val= V4L2_PIX_FMT_NV61;
*num_planes = 2;
break;
+ case CAMERA_YUV_422_YUYV:
+ val= V4L2_PIX_FMT_YUYV;
+ *num_planes = 1;
+ break;
default:
val = 0;
*num_planes = 0;
diff --git a/camera/mm-camera-interface/mm_omx_jpeg_encoder.c b/camera/mm-camera-interface/mm_omx_jpeg_encoder.c
index bd21495..066280b 100644
--- a/camera/mm-camera-interface/mm_omx_jpeg_encoder.c
+++ b/camera/mm-camera-interface/mm_omx_jpeg_encoder.c
@@ -266,12 +266,12 @@
return TRUE;
}
-int8_t omxJpegStart()
+int8_t omxJpegStart(uint8_t hw_encode_enable)
{
int rc = 0;
ALOGE("%s", __func__);
pthread_mutex_lock(&jpege_mutex);
- hw_encode = true;
+ hw_encode = hw_encode_enable;
callbacks.EmptyBufferDone = etbdone;
callbacks.FillBufferDone = ftbdone;
callbacks.EventHandler = eventHandler;
diff --git a/camera/mm-camera-interface/mm_omx_jpeg_encoder.h b/camera/mm-camera-interface/mm_omx_jpeg_encoder.h
index c995ead..7893334 100644
--- a/camera/mm-camera-interface/mm_omx_jpeg_encoder.h
+++ b/camera/mm-camera-interface/mm_omx_jpeg_encoder.h
@@ -51,7 +51,7 @@
}omx_jpeg_encode_params;
int8_t omxJpegOpen();
-int8_t omxJpegStart();
+int8_t omxJpegStart(uint8_t hw_encode_enable);
int8_t omxJpegEncode(omx_jpeg_encode_params *encode_params);
int8_t omxJpegEncodeNext(omx_jpeg_encode_params *encode_params);
void omxJpegFinish();