summaryrefslogtreecommitdiffstats
path: root/libcamera
diff options
context:
space:
mode:
authorPawit Pornkitprasan <p.pawit@gmail.com>2011-12-17 21:43:12 +0700
committerPawit Pornkitprasan <p.pawit@gmail.com>2011-12-17 21:43:12 +0700
commit37f650885d00ebd1c151dad333637601caa69e06 (patch)
treea04e485a5b80c937e51ce0c788d9967d5005c070 /libcamera
parente77e8675c0e60bba6e54d0f7d434d56068085276 (diff)
downloaddevice_samsung_aries-common-37f650885d00ebd1c151dad333637601caa69e06.zip
device_samsung_aries-common-37f650885d00ebd1c151dad333637601caa69e06.tar.gz
device_samsung_aries-common-37f650885d00ebd1c151dad333637601caa69e06.tar.bz2
Import libcamera from crespo
Diffstat (limited to 'libcamera')
-rw-r--r--libcamera/Android.mk22
-rw-r--r--libcamera/NOTICE190
-rwxr-xr-xlibcamera/SecCamera.cpp3061
-rwxr-xr-xlibcamera/SecCamera.h575
-rwxr-xr-xlibcamera/SecCameraHWInterface.cpp2717
-rw-r--r--libcamera/SecCameraHWInterface.h214
6 files changed, 6779 insertions, 0 deletions
diff --git a/libcamera/Android.mk b/libcamera/Android.mk
new file mode 100644
index 0000000..e286cea
--- /dev/null
+++ b/libcamera/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# HAL module implemenation stored in
+# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.product.board>.so
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../libs3cjpeg
+
+LOCAL_SRC_FILES:= \
+ SecCamera.cpp SecCameraHWInterface.cpp
+
+LOCAL_SHARED_LIBRARIES:= libutils libcutils libbinder liblog libcamera_client libhardware
+LOCAL_SHARED_LIBRARIES+= libs3cjpeg
+
+LOCAL_MODULE := camera.aries
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/libcamera/NOTICE b/libcamera/NOTICE
new file mode 100644
index 0000000..f921593
--- /dev/null
+++ b/libcamera/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/libcamera/SecCamera.cpp b/libcamera/SecCamera.cpp
new file mode 100755
index 0000000..9c2d023
--- /dev/null
+++ b/libcamera/SecCamera.cpp
@@ -0,0 +1,3061 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ * Copyright 2010, Samsung Electronics Co. LTD
+ *
+ * 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.
+ */
+
+/*
+************************************
+* Filename: SecCamera.cpp
+* Author: Sachin P. Kamat
+* Purpose: This file interacts with the Camera and JPEG drivers.
+*************************************
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "SecCamera"
+
+#include <utils/Log.h>
+
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/poll.h>
+#include "SecCamera.h"
+#include "cutils/properties.h"
+
+using namespace android;
+
+#define CHECK(return_value) \
+ if (return_value < 0) { \
+ LOGE("%s::%d fail. errno: %s, m_camera_id = %d\n", \
+ __func__, __LINE__, strerror(errno), m_camera_id); \
+ return -1; \
+ }
+
+
+#define CHECK_PTR(return_value) \
+ if (return_value < 0) { \
+ LOGE("%s::%d fail, errno: %s, m_camera_id = %d\n", \
+ __func__,__LINE__, strerror(errno), m_camera_id); \
+ return NULL; \
+ }
+
+#define ALIGN_TO_32B(x) ((((x) + (1 << 5) - 1) >> 5) << 5)
+#define ALIGN_TO_128B(x) ((((x) + (1 << 7) - 1) >> 7) << 7)
+#define ALIGN_TO_8KB(x) ((((x) + (1 << 13) - 1) >> 13) << 13)
+
+namespace android {
+
+// ======================================================================
+// Camera controls
+
+static struct timeval time_start;
+static struct timeval time_stop;
+
+unsigned long measure_time(struct timeval *start, struct timeval *stop)
+{
+ unsigned long sec, usec, time;
+
+ sec = stop->tv_sec - start->tv_sec;
+
+ if (stop->tv_usec >= start->tv_usec) {
+ usec = stop->tv_usec - start->tv_usec;
+ } else {
+ usec = stop->tv_usec + 1000000 - start->tv_usec;
+ sec--;
+ }
+
+ time = (sec * 1000000) + usec;
+
+ return time;
+}
+
+static int get_pixel_depth(unsigned int fmt)
+{
+ int depth = 0;
+
+ switch (fmt) {
+ case V4L2_PIX_FMT_NV12:
+ depth = 12;
+ break;
+ case V4L2_PIX_FMT_NV12T:
+ depth = 12;
+ break;
+ case V4L2_PIX_FMT_NV21:
+ depth = 12;
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ depth = 12;
+ break;
+
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_YVYU:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_VYUY:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_NV61:
+ case V4L2_PIX_FMT_YUV422P:
+ depth = 16;
+ break;
+
+ case V4L2_PIX_FMT_RGB32:
+ depth = 32;
+ break;
+ }
+
+ return depth;
+}
+
+#define ALIGN_W(x) (((x) + 0x7F) & (~0x7F)) // Set as multiple of 128
+#define ALIGN_H(x) (((x) + 0x1F) & (~0x1F)) // Set as multiple of 32
+#define ALIGN_BUF(x) (((x) + 0x1FFF)& (~0x1FFF)) // Set as multiple of 8K
+
+static int fimc_poll(struct pollfd *events)
+{
+ int ret;
+
+ /* 10 second delay is because sensor can take a long time
+ * to do auto focus and capture in dark settings
+ */
+ ret = poll(events, 1, 10000);
+ if (ret < 0) {
+ LOGE("ERR(%s):poll error\n", __func__);
+ return ret;
+ }
+
+ if (ret == 0) {
+ LOGE("ERR(%s):No data in 10 secs..\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+int SecCamera::previewPoll(bool preview)
+{
+ int ret;
+
+ if (preview) {
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+ int status = 0;
+
+ if (!(++m_esd_check_count % 60)) {
+ status = getCameraSensorESDStatus();
+ m_esd_check_count = 0;
+ if (status) {
+ LOGE("ERR(%s) ESD status(%d)", __func__, status);
+ return status;
+ }
+ }
+#endif
+
+ ret = poll(&m_events_c, 1, 1000);
+ } else {
+ ret = poll(&m_events_c2, 1, 1000);
+ }
+
+ if (ret < 0) {
+ LOGE("ERR(%s):poll error\n", __func__);
+ return ret;
+ }
+
+ if (ret == 0) {
+ LOGE("ERR(%s):No data in 1 secs.. Camera Device Reset \n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int fimc_v4l2_querycap(int fp)
+{
+ struct v4l2_capability cap;
+ int ret = 0;
+
+ ret = ioctl(fp, VIDIOC_QUERYCAP, &cap);
+
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_QUERYCAP failed\n", __func__);
+ return -1;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
+ LOGE("ERR(%s):no capture devices\n", __func__);
+ return -1;
+ }
+
+ return ret;
+}
+
+static const __u8* fimc_v4l2_enuminput(int fp, int index)
+{
+ static struct v4l2_input input;
+
+ input.index = index;
+ if (ioctl(fp, VIDIOC_ENUMINPUT, &input) != 0) {
+ LOGE("ERR(%s):No matching index found\n", __func__);
+ return NULL;
+ }
+ LOGI("Name of input channel[%d] is %s\n", input.index, input.name);
+
+ return input.name;
+}
+
+
+static int fimc_v4l2_s_input(int fp, int index)
+{
+ struct v4l2_input input;
+ int ret;
+
+ input.index = index;
+
+ ret = ioctl(fp, VIDIOC_S_INPUT, &input);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_S_INPUT failed\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int fimc_v4l2_s_fmt(int fp, int width, int height, unsigned int fmt, int flag_capture)
+{
+ struct v4l2_format v4l2_fmt;
+ struct v4l2_pix_format pixfmt;
+ int ret;
+
+ v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ memset(&pixfmt, 0, sizeof(pixfmt));
+
+ pixfmt.width = width;
+ pixfmt.height = height;
+ pixfmt.pixelformat = fmt;
+
+ pixfmt.sizeimage = (width * height * get_pixel_depth(fmt)) / 8;
+
+ pixfmt.field = V4L2_FIELD_NONE;
+
+ v4l2_fmt.fmt.pix = pixfmt;
+
+ /* Set up for capture */
+ ret = ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_S_FMT failed\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int fimc_v4l2_s_fmt_cap(int fp, int width, int height, unsigned int fmt)
+{
+ struct v4l2_format v4l2_fmt;
+ struct v4l2_pix_format pixfmt;
+ int ret;
+
+ memset(&pixfmt, 0, sizeof(pixfmt));
+
+ v4l2_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ pixfmt.width = width;
+ pixfmt.height = height;
+ pixfmt.pixelformat = fmt;
+ if (fmt == V4L2_PIX_FMT_JPEG) {
+ pixfmt.colorspace = V4L2_COLORSPACE_JPEG;
+ }
+
+ pixfmt.sizeimage = (width * height * get_pixel_depth(fmt)) / 8;
+
+ v4l2_fmt.fmt.pix = pixfmt;
+
+ //LOGE("ori_w %d, ori_h %d, w %d, h %d\n", width, height, v4l2_fmt.fmt.pix.width, v4l2_fmt.fmt.pix.height);
+
+ /* Set up for capture */
+ ret = ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_S_FMT failed\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int fimc_v4l2_enum_fmt(int fp, unsigned int fmt)
+{
+ struct v4l2_fmtdesc fmtdesc;
+ int found = 0;
+
+ fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmtdesc.index = 0;
+
+ while (ioctl(fp, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
+ if (fmtdesc.pixelformat == fmt) {
+ LOGV("passed fmt = %#x found pixel format[%d]: %s\n", fmt, fmtdesc.index, fmtdesc.description);
+ found = 1;
+ break;
+ }
+
+ fmtdesc.index++;
+ }
+
+ if (!found) {
+ LOGE("unsupported pixel format\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int fimc_v4l2_reqbufs(int fp, enum v4l2_buf_type type, int nr_bufs)
+{
+ struct v4l2_requestbuffers req;
+ int ret;
+
+ req.count = nr_bufs;
+ req.type = type;
+ req.memory = V4L2_MEMORY_MMAP;
+
+ ret = ioctl(fp, VIDIOC_REQBUFS, &req);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_REQBUFS failed\n", __func__);
+ return -1;
+ }
+
+ return req.count;
+}
+
+static int fimc_v4l2_querybuf(int fp, struct fimc_buffer *buffer, enum v4l2_buf_type type)
+{
+ struct v4l2_buffer v4l2_buf;
+ int ret;
+
+ LOGI("%s :", __func__);
+
+ v4l2_buf.type = type;
+ v4l2_buf.memory = V4L2_MEMORY_MMAP;
+ v4l2_buf.index = 0;
+
+ ret = ioctl(fp , VIDIOC_QUERYBUF, &v4l2_buf);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_QUERYBUF failed\n", __func__);
+ return -1;
+ }
+
+ buffer->length = v4l2_buf.length;
+ if ((buffer->start = (char *)mmap(0, v4l2_buf.length,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ fp, v4l2_buf.m.offset)) < 0) {
+ LOGE("%s %d] mmap() failed\n",__func__, __LINE__);
+ return -1;
+ }
+
+ LOGI("%s: buffer->start = %p v4l2_buf.length = %d",
+ __func__, buffer->start, v4l2_buf.length);
+
+ return 0;
+}
+
+static int fimc_v4l2_streamon(int fp)
+{
+ enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ int ret;
+
+ ret = ioctl(fp, VIDIOC_STREAMON, &type);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_STREAMON failed\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int fimc_v4l2_streamoff(int fp)
+{
+ enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ int ret;
+
+ LOGV("%s :", __func__);
+ ret = ioctl(fp, VIDIOC_STREAMOFF, &type);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_STREAMOFF failed\n", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int fimc_v4l2_qbuf(int fp, int index)
+{
+ struct v4l2_buffer v4l2_buf;
+ int ret;
+
+ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ v4l2_buf.memory = V4L2_MEMORY_MMAP;
+ v4l2_buf.index = index;
+
+ ret = ioctl(fp, VIDIOC_QBUF, &v4l2_buf);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_QBUF failed\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int fimc_v4l2_dqbuf(int fp)
+{
+ struct v4l2_buffer v4l2_buf;
+ int ret;
+
+ v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ v4l2_buf.memory = V4L2_MEMORY_MMAP;
+
+ ret = ioctl(fp, VIDIOC_DQBUF, &v4l2_buf);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_DQBUF failed, dropped frame\n", __func__);
+ return ret;
+ }
+
+ return v4l2_buf.index;
+}
+
+static int fimc_v4l2_g_ctrl(int fp, unsigned int id)
+{
+ struct v4l2_control ctrl;
+ int ret;
+
+ ctrl.id = id;
+
+ ret = ioctl(fp, VIDIOC_G_CTRL, &ctrl);
+ if (ret < 0) {
+ LOGE("ERR(%s): VIDIOC_G_CTRL(id = 0x%x (%d)) failed, ret = %d\n",
+ __func__, id, id-V4L2_CID_PRIVATE_BASE, ret);
+ return ret;
+ }
+
+ return ctrl.value;
+}
+
+static int fimc_v4l2_s_ctrl(int fp, unsigned int id, unsigned int value)
+{
+ struct v4l2_control ctrl;
+ int ret;
+
+ ctrl.id = id;
+ ctrl.value = value;
+
+ ret = ioctl(fp, VIDIOC_S_CTRL, &ctrl);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_S_CTRL(id = %#x (%d), value = %d) failed ret = %d\n",
+ __func__, id, id-V4L2_CID_PRIVATE_BASE, value, ret);
+
+ return ret;
+ }
+
+ return ctrl.value;
+}
+
+static int fimc_v4l2_s_ext_ctrl(int fp, unsigned int id, void *value)
+{
+ struct v4l2_ext_controls ctrls;
+ struct v4l2_ext_control ctrl;
+ int ret;
+
+ ctrl.id = id;
+ ctrl.reserved = value;
+
+ ctrls.ctrl_class = V4L2_CTRL_CLASS_CAMERA;
+ ctrls.count = 1;
+ ctrls.controls = &ctrl;
+
+ ret = ioctl(fp, VIDIOC_S_EXT_CTRLS, &ctrls);
+ if (ret < 0)
+ LOGE("ERR(%s):VIDIOC_S_EXT_CTRLS failed\n", __func__);
+
+ return ret;
+}
+
+static int fimc_v4l2_g_parm(int fp, struct v4l2_streamparm *streamparm)
+{
+ int ret;
+
+ streamparm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ ret = ioctl(fp, VIDIOC_G_PARM, streamparm);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_G_PARM failed\n", __func__);
+ return -1;
+ }
+
+ LOGV("%s : timeperframe: numerator %d, denominator %d\n", __func__,
+ streamparm->parm.capture.timeperframe.numerator,
+ streamparm->parm.capture.timeperframe.denominator);
+
+ return 0;
+}
+
+static int fimc_v4l2_s_parm(int fp, struct v4l2_streamparm *streamparm)
+{
+ int ret;
+
+ streamparm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ ret = ioctl(fp, VIDIOC_S_PARM, streamparm);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_S_PARM failed\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+// ======================================================================
+// Constructor & Destructor
+
+SecCamera::SecCamera() :
+ m_flag_init(0),
+ m_camera_id(CAMERA_ID_BACK),
+ m_cam_fd(-1),
+ m_cam_fd2(-1),
+ m_preview_v4lformat(V4L2_PIX_FMT_NV21),
+ m_preview_width (0),
+ m_preview_height (0),
+ m_preview_max_width (MAX_BACK_CAMERA_PREVIEW_WIDTH),
+ m_preview_max_height (MAX_BACK_CAMERA_PREVIEW_HEIGHT),
+ m_snapshot_v4lformat(-1),
+ m_snapshot_width (0),
+ m_snapshot_height (0),
+ m_snapshot_max_width (MAX_BACK_CAMERA_SNAPSHOT_WIDTH),
+ m_snapshot_max_height (MAX_BACK_CAMERA_SNAPSHOT_HEIGHT),
+ m_angle(-1),
+ m_anti_banding(-1),
+ m_wdr(-1),
+ m_anti_shake(-1),
+ m_zoom_level(-1),
+ m_object_tracking(-1),
+ m_smart_auto(-1),
+ m_beauty_shot(-1),
+ m_vintage_mode(-1),
+ m_face_detect(-1),
+ m_gps_enabled(false),
+ m_gps_latitude(-1),
+ m_gps_longitude(-1),
+ m_gps_altitude(-1),
+ m_gps_timestamp(-1),
+ m_vtmode(0),
+ m_sensor_mode(-1),
+ m_shot_mode(-1),
+ m_exif_orientation(-1),
+ m_blur_level(-1),
+ m_chk_dataline(-1),
+ m_video_gamma(-1),
+ m_slow_ae(-1),
+ m_camera_af_flag(-1),
+ m_flag_camera_start(0),
+ m_jpeg_thumbnail_width (0),
+ m_jpeg_thumbnail_height(0),
+ m_jpeg_quality(100)
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+ ,
+ m_esd_check_count(0)
+#endif // ENABLE_ESD_PREVIEW_CHECK
+{
+ m_params = (struct sec_cam_parm*)&m_streamparm.parm.raw_data;
+ struct v4l2_captureparm capture;
+ m_params->capture.timeperframe.numerator = 1;
+ m_params->capture.timeperframe.denominator = 0;
+ m_params->contrast = -1;
+ m_params->effects = -1;
+ m_params->brightness = -1;
+ m_params->flash_mode = -1;
+ m_params->focus_mode = -1;
+ m_params->iso = -1;
+ m_params->metering = -1;
+ m_params->saturation = -1;
+ m_params->scene_mode = -1;
+ m_params->sharpness = -1;
+ m_params->white_balance = -1;
+
+ memset(&m_capture_buf, 0, sizeof(m_capture_buf));
+
+ LOGV("%s :", __func__);
+}
+
+SecCamera::~SecCamera()
+{
+ LOGV("%s :", __func__);
+}
+
+int SecCamera::initCamera(int index)
+{
+ LOGV("%s :", __func__);
+ int ret = 0;
+
+ if (!m_flag_init) {
+ /* Arun C
+ * Reset the lense position only during camera starts; don't do
+ * reset between shot to shot
+ */
+ m_camera_af_flag = -1;
+
+ m_cam_fd = open(CAMERA_DEV_NAME, O_RDWR);
+ if (m_cam_fd < 0) {
+ LOGE("ERR(%s):Cannot open %s (error : %s)\n", __func__, CAMERA_DEV_NAME, strerror(errno));
+ return -1;
+ }
+ LOGV("%s: open(%s) --> m_cam_fd %d", __FUNCTION__, CAMERA_DEV_NAME, m_cam_fd);
+
+ LOGE("initCamera: m_cam_fd(%d), m_jpeg_fd(%d)", m_cam_fd, m_jpeg_fd);
+
+ ret = fimc_v4l2_querycap(m_cam_fd);
+ CHECK(ret);
+ if (!fimc_v4l2_enuminput(m_cam_fd, index))
+ return -1;
+ ret = fimc_v4l2_s_input(m_cam_fd, index);
+ CHECK(ret);
+
+ m_cam_fd2 = open(CAMERA_DEV_NAME2, O_RDWR);
+ LOGV("%s: open(%s) --> m_cam_fd2 = %d", __FUNCTION__, CAMERA_DEV_NAME2, m_cam_fd2);
+ if (m_cam_fd2 < 0) {
+ LOGE("ERR(%s):Cannot open %s (error : %s)\n", __func__, CAMERA_DEV_NAME2, strerror(errno));
+ return -1;
+ }
+
+ LOGE("initCamera: m_cam_fd2(%d)", m_cam_fd2);
+
+ ret = fimc_v4l2_querycap(m_cam_fd2);
+ CHECK(ret);
+ if (!fimc_v4l2_enuminput(m_cam_fd2, index))
+ return -1;
+ ret = fimc_v4l2_s_input(m_cam_fd2, index);
+ CHECK(ret);
+
+ m_camera_id = index;
+
+ switch (m_camera_id) {
+ case CAMERA_ID_FRONT:
+ m_preview_max_width = MAX_FRONT_CAMERA_PREVIEW_WIDTH;
+ m_preview_max_height = MAX_FRONT_CAMERA_PREVIEW_HEIGHT;
+ m_snapshot_max_width = MAX_FRONT_CAMERA_SNAPSHOT_WIDTH;
+ m_snapshot_max_height = MAX_FRONT_CAMERA_SNAPSHOT_HEIGHT;
+ break;
+
+ case CAMERA_ID_BACK:
+ m_preview_max_width = MAX_BACK_CAMERA_PREVIEW_WIDTH;
+ m_preview_max_height = MAX_BACK_CAMERA_PREVIEW_HEIGHT;
+ m_snapshot_max_width = MAX_BACK_CAMERA_SNAPSHOT_WIDTH;
+ m_snapshot_max_height = MAX_BACK_CAMERA_SNAPSHOT_HEIGHT;
+ break;
+ }
+
+ setExifFixedAttribute();
+
+ m_flag_init = 1;
+ LOGI("%s : initialized", __FUNCTION__);
+ }
+ return 0;
+}
+
+void SecCamera::resetCamera()
+{
+ LOGV("%s :", __func__);
+ DeinitCamera();
+ initCamera(m_camera_id);
+}
+
+void SecCamera::DeinitCamera()
+{
+ LOGV("%s :", __func__);
+
+ if (m_flag_init) {
+
+ stopRecord();
+
+ /* close m_cam_fd after stopRecord() because stopRecord()
+ * uses m_cam_fd to change frame rate
+ */
+ LOGI("DeinitCamera: m_cam_fd(%d)", m_cam_fd);
+ if (m_cam_fd > -1) {
+ close(m_cam_fd);
+ m_cam_fd = -1;
+ }
+
+ LOGI("DeinitCamera: m_cam_fd2(%d)", m_cam_fd2);
+ if (m_cam_fd2 > -1) {
+ close(m_cam_fd2);
+ m_cam_fd2 = -1;
+ }
+
+ m_flag_init = 0;
+ }
+ else LOGI("%s : already deinitialized", __FUNCTION__);
+}
+
+
+int SecCamera::getCameraFd(void)
+{
+ return m_cam_fd;
+}
+
+// ======================================================================
+// Preview
+
+int SecCamera::startPreview(void)
+{
+ v4l2_streamparm streamparm;
+ struct sec_cam_parm *parms;
+ parms = (struct sec_cam_parm*)&streamparm.parm.raw_data;
+ LOGV("%s :", __func__);
+
+ // aleady started
+ if (m_flag_camera_start > 0) {
+ LOGE("ERR(%s):Preview was already started\n", __func__);
+ return 0;
+ }
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ memset(&m_events_c, 0, sizeof(m_events_c));
+ m_events_c.fd = m_cam_fd;
+ m_events_c.events = POLLIN | POLLERR;
+
+ /* enum_fmt, s_fmt sample */
+ int ret = fimc_v4l2_enum_fmt(m_cam_fd,m_preview_v4lformat);
+ CHECK(ret);
+ ret = fimc_v4l2_s_fmt(m_cam_fd, m_preview_width,m_preview_height,m_preview_v4lformat, 0);
+ CHECK(ret);
+
+ ret = fimc_v4l2_reqbufs(m_cam_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, MAX_BUFFERS);
+ CHECK(ret);
+
+ LOGV("%s : m_preview_width: %d m_preview_height: %d m_angle: %d\n",
+ __func__, m_preview_width, m_preview_height, m_angle);
+
+ ret = fimc_v4l2_s_ctrl(m_cam_fd,
+ V4L2_CID_CAMERA_CHECK_DATALINE, m_chk_dataline);
+ CHECK(ret);
+
+ if (m_camera_id == CAMERA_ID_FRONT) {
+ /* VT mode setting */
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_VT_MODE, m_vtmode);
+ CHECK(ret);
+ }
+
+ /* start with all buffers in queue */
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ ret = fimc_v4l2_qbuf(m_cam_fd, i);
+ CHECK(ret);
+ }
+
+ ret = fimc_v4l2_streamon(m_cam_fd);
+ CHECK(ret);
+
+ m_flag_camera_start = 1;
+
+ ret = fimc_v4l2_s_parm(m_cam_fd, &m_streamparm);
+ CHECK(ret);
+
+ if (m_camera_id == CAMERA_ID_FRONT) {
+ /* Blur setting */
+ LOGV("m_blur_level = %d", m_blur_level);
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_VGA_BLUR,
+ m_blur_level);
+ CHECK(ret);
+ }
+
+ // It is a delay for a new frame, not to show the previous bigger ugly picture frame.
+ ret = fimc_poll(&m_events_c);
+ CHECK(ret);
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_RETURN_FOCUS, 0);
+ CHECK(ret);
+
+ LOGV("%s: got the first frame of the preview\n", __func__);
+
+ return 0;
+}
+
+int SecCamera::stopPreview(void)
+{
+ int ret;
+
+ LOGV("%s :", __func__);
+
+ if (m_flag_camera_start == 0) {
+ LOGW("%s: doing nothing because m_flag_camera_start is zero", __func__);
+ return 0;
+ }
+
+ if (m_params->flash_mode == FLASH_MODE_TORCH)
+ setFlashMode(FLASH_MODE_OFF);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ ret = fimc_v4l2_streamoff(m_cam_fd);
+ CHECK(ret);
+
+ m_flag_camera_start = 0;
+
+ return ret;
+}
+
+//Recording
+int SecCamera::startRecord(void)
+{
+ int ret, i;
+
+ LOGV("%s :", __func__);
+
+ // aleady started
+ if (m_flag_record_start > 0) {
+ LOGE("ERR(%s):Preview was already started\n", __func__);
+ return 0;
+ }
+
+ if (m_cam_fd2 <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ /* enum_fmt, s_fmt sample */
+ ret = fimc_v4l2_enum_fmt(m_cam_fd2, V4L2_PIX_FMT_NV12T);
+ CHECK(ret);
+
+ LOGI("%s: m_recording_width = %d, m_recording_height = %d\n",
+ __func__, m_recording_width, m_recording_height);
+
+ ret = fimc_v4l2_s_fmt(m_cam_fd2, m_recording_width,
+ m_recording_height, V4L2_PIX_FMT_NV12T, 0);
+ CHECK(ret);
+
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FRAME_RATE,
+ m_params->capture.timeperframe.denominator);
+ CHECK(ret);
+
+ ret = fimc_v4l2_reqbufs(m_cam_fd2, V4L2_BUF_TYPE_VIDEO_CAPTURE, MAX_BUFFERS);
+ CHECK(ret);
+
+ /* start with all buffers in queue */
+ for (i = 0; i < MAX_BUFFERS; i++) {
+ ret = fimc_v4l2_qbuf(m_cam_fd2, i);
+ CHECK(ret);
+ }
+
+ ret = fimc_v4l2_streamon(m_cam_fd2);
+ CHECK(ret);
+
+ // Get and throw away the first frame since it is often garbled.
+ memset(&m_events_c2, 0, sizeof(m_events_c2));
+ m_events_c2.fd = m_cam_fd2;
+ m_events_c2.events = POLLIN | POLLERR;
+ ret = fimc_poll(&m_events_c2);
+ CHECK(ret);
+
+ m_flag_record_start = 1;
+
+ return 0;
+}
+
+int SecCamera::stopRecord(void)
+{
+ int ret;
+
+ LOGV("%s :", __func__);
+
+ if (m_flag_record_start == 0) {
+ LOGW("%s: doing nothing because m_flag_record_start is zero", __func__);
+ return 0;
+ }
+
+ if (m_cam_fd2 <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ m_flag_record_start = 0;
+
+ ret = fimc_v4l2_streamoff(m_cam_fd2);
+ CHECK(ret);
+
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FRAME_RATE,
+ FRAME_RATE_AUTO);
+ CHECK(ret);
+
+ return 0;
+}
+
+unsigned int SecCamera::getRecPhyAddrY(int index)
+{
+ unsigned int addr_y;
+
+ addr_y = fimc_v4l2_s_ctrl(m_cam_fd2, V4L2_CID_PADDR_Y, index);
+ CHECK((int)addr_y);
+ return addr_y;
+}
+
+unsigned int SecCamera::getRecPhyAddrC(int index)
+{
+ unsigned int addr_c;
+
+ addr_c = fimc_v4l2_s_ctrl(m_cam_fd2, V4L2_CID_PADDR_CBCR, index);
+ CHECK((int)addr_c);
+ return addr_c;
+}
+
+unsigned int SecCamera::getPhyAddrY(int index)
+{
+ unsigned int addr_y;
+
+ addr_y = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_PADDR_Y, index);
+ CHECK((int)addr_y);
+ return addr_y;
+}
+
+unsigned int SecCamera::getPhyAddrC(int index)
+{
+ unsigned int addr_c;
+
+ addr_c = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_PADDR_CBCR, index);
+ CHECK((int)addr_c);
+ return addr_c;
+}
+
+void SecCamera::pausePreview()
+{
+ fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_STREAM_PAUSE, 0);
+}
+
+int SecCamera::getPreview()
+{
+ int index;
+ int ret;
+
+ if (m_flag_camera_start == 0 || previewPoll(true) == 0) {
+ LOGE("ERR(%s):Start Camera Device Reset \n", __func__);
+ /* GAUDI Project([arun.c@samsung.com]) 2010.05.20. [Implemented ESD code] */
+ /*
+ * When there is no data for more than 1 second from the camera we inform
+ * the FIMC driver by calling fimc_v4l2_s_input() with a special value = 1000
+ * FIMC driver identify that there is something wrong with the camera
+ * and it restarts the sensor.
+ */
+ stopPreview();
+ /* Reset Only Camera Device */
+ ret = fimc_v4l2_querycap(m_cam_fd);
+ CHECK(ret);
+ if (fimc_v4l2_enuminput(m_cam_fd, m_camera_id))
+ return -1;
+ ret = fimc_v4l2_s_input(m_cam_fd, 1000);
+ CHECK(ret);
+ ret = startPreview();
+ if (ret < 0) {
+ LOGE("ERR(%s): startPreview() return %d\n", __func__, ret);
+ return 0;
+ }
+ }
+
+ index = fimc_v4l2_dqbuf(m_cam_fd);
+ if (!(0 <= index && index < MAX_BUFFERS)) {
+ LOGE("ERR(%s):wrong index = %d\n", __func__, index);
+ return -1;
+ }
+
+ ret = fimc_v4l2_qbuf(m_cam_fd, index);
+ CHECK(ret);
+
+ return index;
+}
+
+int SecCamera::getRecordFrame()
+{
+ if (m_flag_record_start == 0) {
+ LOGE("%s: m_flag_record_start is 0", __func__);
+ return -1;
+ }
+
+ previewPoll(false);
+ return fimc_v4l2_dqbuf(m_cam_fd2);
+}
+
+int SecCamera::releaseRecordFrame(int index)
+{
+ if (!m_flag_record_start) {
+ /* this can happen when recording frames are returned after
+ * the recording is stopped at the driver level. we don't
+ * need to return the buffers in this case and we've seen
+ * cases where fimc could crash if we called qbuf and it
+ * wasn't expecting it.
+ */
+ LOGI("%s: recording not in progress, ignoring", __func__);
+ return 0;
+ }
+
+ return fimc_v4l2_qbuf(m_cam_fd2, index);
+}
+
+int SecCamera::setPreviewSize(int width, int height, int pixel_format)
+{
+ LOGV("%s(width(%d), height(%d), format(%d))", __func__, width, height, pixel_format);
+
+ int v4lpixelformat = pixel_format;
+
+#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0
+ if (v4lpixelformat == V4L2_PIX_FMT_YUV420)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_YUV420");
+ else if (v4lpixelformat == V4L2_PIX_FMT_NV12)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_NV12");
+ else if (v4lpixelformat == V4L2_PIX_FMT_NV12T)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_NV12T");
+ else if (v4lpixelformat == V4L2_PIX_FMT_NV21)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_NV21");
+ else if (v4lpixelformat == V4L2_PIX_FMT_YUV422P)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_YUV422P");
+ else if (v4lpixelformat == V4L2_PIX_FMT_YUYV)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_YUYV");
+ else if (v4lpixelformat == V4L2_PIX_FMT_RGB565)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_RGB565");
+ else
+ LOGV("PreviewFormat:UnknownFormat");
+#endif
+ m_preview_width = width;
+ m_preview_height = height;
+ m_preview_v4lformat = v4lpixelformat;
+
+ return 0;
+}
+
+int SecCamera::getPreviewSize(int *width, int *height, int *frame_size)
+{
+ *width = m_preview_width;
+ *height = m_preview_height;
+ *frame_size = m_frameSize(m_preview_v4lformat, m_preview_width, m_preview_height);
+
+ return 0;
+}
+
+int SecCamera::getPreviewMaxSize(int *width, int *height)
+{
+ *width = m_preview_max_width;
+ *height = m_preview_max_height;
+
+ return 0;
+}
+
+int SecCamera::getPreviewPixelFormat(void)
+{
+ return m_preview_v4lformat;
+}
+
+
+// ======================================================================
+// Snapshot
+/*
+ * Devide getJpeg() as two funcs, setSnapshotCmd() & getJpeg() because of the shutter sound timing.
+ * Here, just send the capture cmd to camera ISP to start JPEG capture.
+ */
+int SecCamera::setSnapshotCmd(void)
+{
+ LOGV("%s :", __func__);
+
+ int ret = 0;
+
+ LOG_TIME_DEFINE(0)
+ LOG_TIME_DEFINE(1)
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return 0;
+ }
+
+ if (m_flag_camera_start > 0) {
+ LOG_TIME_START(0)
+ LOGW("WARN(%s):Camera was in preview, should have been stopped\n", __func__);
+ stopPreview();
+ LOG_TIME_END(0)
+ }
+
+ memset(&m_events_c, 0, sizeof(m_events_c));
+ m_events_c.fd = m_cam_fd;
+ m_events_c.events = POLLIN | POLLERR;
+
+ LOG_TIME_START(1) // prepare
+ int nframe = 1;
+
+ ret = fimc_v4l2_enum_fmt(m_cam_fd,m_snapshot_v4lformat);
+ CHECK(ret);
+ ret = fimc_v4l2_s_fmt_cap(m_cam_fd, m_snapshot_width, m_snapshot_height, V4L2_PIX_FMT_JPEG);
+ CHECK(ret);
+ ret = fimc_v4l2_reqbufs(m_cam_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, nframe);
+ CHECK(ret);
+ ret = fimc_v4l2_querybuf(m_cam_fd, &m_capture_buf, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ CHECK(ret);
+
+ ret = fimc_v4l2_qbuf(m_cam_fd, 0);
+ CHECK(ret);
+
+ ret = fimc_v4l2_streamon(m_cam_fd);
+ CHECK(ret);
+ LOG_TIME_END(1)
+
+ return 0;
+}
+
+int SecCamera::endSnapshot(void)
+{
+ int ret;
+
+ LOGI("%s :", __func__);
+ if (m_capture_buf.start) {
+ munmap(m_capture_buf.start, m_capture_buf.length);
+ LOGI("munmap():virt. addr %p size = %d\n",
+ m_capture_buf.start, m_capture_buf.length);
+ m_capture_buf.start = NULL;
+ m_capture_buf.length = 0;
+ }
+ return 0;
+}
+
+/*
+ * Set Jpeg quality & exif info and get JPEG data from camera ISP
+ */
+unsigned char* SecCamera::getJpeg(int *jpeg_size, unsigned int *phyaddr)
+{
+ LOGV("%s :", __func__);
+
+ int index, ret = 0;
+ unsigned char *addr;
+
+ LOG_TIME_DEFINE(2)
+
+ // capture
+ ret = fimc_poll(&m_events_c);
+ CHECK_PTR(ret);
+ index = fimc_v4l2_dqbuf(m_cam_fd);
+ if (index != 0) {
+ LOGE("ERR(%s):wrong index = %d\n", __func__, index);
+ return NULL;
+ }
+
+ *jpeg_size = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_MAIN_SIZE);
+ CHECK_PTR(*jpeg_size);
+
+ int main_offset = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_MAIN_OFFSET);
+ CHECK_PTR(main_offset);
+ m_postview_offset = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET);
+ CHECK_PTR(m_postview_offset);
+
+ ret = fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_STREAM_PAUSE, 0);
+ CHECK_PTR(ret);
+ LOGV("\nsnapshot dqueued buffer = %d snapshot_width = %d snapshot_height = %d, size = %d\n\n",
+ index, m_snapshot_width, m_snapshot_height, *jpeg_size);
+
+ addr = (unsigned char*)(m_capture_buf.start) + main_offset;
+ *phyaddr = getPhyAddrY(index) + m_postview_offset;
+
+ LOG_TIME_START(2) // post
+ ret = fimc_v4l2_streamoff(m_cam_fd);
+ CHECK_PTR(ret);
+ LOG_TIME_END(2)
+
+ return addr;
+}
+
+int SecCamera::getExif(unsigned char *pExifDst, unsigned char *pThumbSrc)
+{
+ JpegEncoder jpgEnc;
+
+ LOGV("%s : m_jpeg_thumbnail_width = %d, height = %d",
+ __func__, m_jpeg_thumbnail_width, m_jpeg_thumbnail_height);
+ if ((m_jpeg_thumbnail_width > 0) && (m_jpeg_thumbnail_height > 0)) {
+ int inFormat = JPG_MODESEL_YCBCR;
+ int outFormat = JPG_422;
+ switch (m_snapshot_v4lformat) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_YUV420:
+ outFormat = JPG_420;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YUV422P:
+ outFormat = JPG_422;
+ break;
+ }
+
+ if (jpgEnc.setConfig(JPEG_SET_ENCODE_IN_FORMAT, inFormat) != JPG_SUCCESS)
+ return -1;
+
+ if (jpgEnc.setConfig(JPEG_SET_SAMPING_MODE, outFormat) != JPG_SUCCESS)
+ return -1;
+
+ if (jpgEnc.setConfig(JPEG_SET_ENCODE_QUALITY, JPG_QUALITY_LEVEL_2) != JPG_SUCCESS)
+ return -1;
+
+ int thumbWidth, thumbHeight, thumbSrcSize;
+ getThumbnailConfig(&thumbWidth, &thumbHeight, &thumbSrcSize);
+ if (jpgEnc.setConfig(JPEG_SET_ENCODE_WIDTH, thumbWidth) != JPG_SUCCESS)
+ return -1;
+
+ if (jpgEnc.setConfig(JPEG_SET_ENCODE_HEIGHT, thumbHeight) != JPG_SUCCESS)
+ return -1;
+
+ char *pInBuf = (char *)jpgEnc.getInBuf(thumbSrcSize);
+ if (pInBuf == NULL)
+ return -1;
+ memcpy(pInBuf, pThumbSrc, thumbSrcSize);
+
+ unsigned int thumbSize;
+
+ jpgEnc.encode(&thumbSize, NULL);
+
+ LOGV("%s : enableThumb set to true", __func__);
+ mExifInfo.enableThumb = true;
+ } else {
+ LOGV("%s : enableThumb set to false", __func__);
+ mExifInfo.enableThumb = false;
+ }
+
+ unsigned int exifSize;
+
+ setExifChangedAttribute();
+
+ LOGV("%s: calling jpgEnc.makeExif, mExifInfo.width set to %d, height to %d\n",
+ __func__, mExifInfo.width, mExifInfo.height);
+
+ jpgEnc.makeExif(pExifDst, &mExifInfo, &exifSize, true);
+
+ return exifSize;
+}
+
+void SecCamera::getPostViewConfig(int *width, int *height, int *size)
+{
+ if (m_preview_width == 1024) {
+ *width = BACK_CAMERA_POSTVIEW_WIDE_WIDTH;
+ *height = BACK_CAMERA_POSTVIEW_HEIGHT;
+ *size = BACK_CAMERA_POSTVIEW_WIDE_WIDTH * BACK_CAMERA_POSTVIEW_HEIGHT * BACK_CAMERA_POSTVIEW_BPP / 8;
+ } else {
+ *width = BACK_CAMERA_POSTVIEW_WIDTH;
+ *height = BACK_CAMERA_POSTVIEW_HEIGHT;
+ *size = BACK_CAMERA_POSTVIEW_WIDTH * BACK_CAMERA_POSTVIEW_HEIGHT * BACK_CAMERA_POSTVIEW_BPP / 8;
+ }
+ LOGV("[5B] m_preview_width : %d, mPostViewWidth = %d mPostViewHeight = %d mPostViewSize = %d",
+ m_preview_width, *width, *height, *size);
+}
+
+void SecCamera::getThumbnailConfig(int *width, int *height, int *size)
+{
+ if (m_camera_id == CAMERA_ID_BACK) {
+ *width = BACK_CAMERA_THUMBNAIL_WIDTH;
+ *height = BACK_CAMERA_THUMBNAIL_HEIGHT;
+ *size = BACK_CAMERA_THUMBNAIL_WIDTH * BACK_CAMERA_THUMBNAIL_HEIGHT
+ * BACK_CAMERA_THUMBNAIL_BPP / 8;
+ } else {
+ *width = FRONT_CAMERA_THUMBNAIL_WIDTH;
+ *height = FRONT_CAMERA_THUMBNAIL_HEIGHT;
+ *size = FRONT_CAMERA_THUMBNAIL_WIDTH * FRONT_CAMERA_THUMBNAIL_HEIGHT
+ * FRONT_CAMERA_THUMBNAIL_BPP / 8;
+ }
+}
+
+int SecCamera::getPostViewOffset(void)
+{
+ return m_postview_offset;
+}
+
+int SecCamera::getSnapshotAndJpeg(unsigned char *yuv_buf, unsigned char *jpeg_buf,
+ unsigned int *output_size)
+{
+ LOGV("%s :", __func__);
+
+ int index;
+ //unsigned int addr;
+ unsigned char *addr;
+ int ret = 0;
+
+ LOG_TIME_DEFINE(0)
+ LOG_TIME_DEFINE(1)
+ LOG_TIME_DEFINE(2)
+ LOG_TIME_DEFINE(3)
+ LOG_TIME_DEFINE(4)
+ LOG_TIME_DEFINE(5)
+
+ //fimc_v4l2_streamoff(m_cam_fd); [zzangdol] remove - it is separate in HWInterface with camera_id
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ if (m_flag_camera_start > 0) {
+ LOG_TIME_START(0)
+ LOGW("WARN(%s):Camera was in preview, should have been stopped\n", __func__);
+ stopPreview();
+ LOG_TIME_END(0)
+ }
+
+ memset(&m_events_c, 0, sizeof(m_events_c));
+ m_events_c.fd = m_cam_fd;
+ m_events_c.events = POLLIN | POLLERR;
+
+#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0
+ if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV420)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_YUV420");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_NV12");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12T)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_NV12T");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV21)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_NV21");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV422P)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_YUV422P");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUYV)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_YUYV");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_UYVY)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_UYVY");
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565)
+ LOGV("SnapshotFormat:V4L2_PIX_FMT_RGB565");
+ else
+ LOGV("SnapshotFormat:UnknownFormat");
+#endif
+
+ LOG_TIME_START(1) // prepare
+ int nframe = 1;
+
+ ret = fimc_v4l2_enum_fmt(m_cam_fd,m_snapshot_v4lformat);
+ CHECK(ret);
+ ret = fimc_v4l2_s_fmt_cap(m_cam_fd, m_snapshot_width, m_snapshot_height, m_snapshot_v4lformat);
+ CHECK(ret);
+ ret = fimc_v4l2_reqbufs(m_cam_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE, nframe);
+ CHECK(ret);
+ ret = fimc_v4l2_querybuf(m_cam_fd, &m_capture_buf, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ CHECK(ret);
+
+ ret = fimc_v4l2_qbuf(m_cam_fd, 0);
+ CHECK(ret);
+
+ ret = fimc_v4l2_streamon(m_cam_fd);
+ CHECK(ret);
+ LOG_TIME_END(1)
+
+ LOG_TIME_START(2) // capture
+ fimc_poll(&m_events_c);
+ index = fimc_v4l2_dqbuf(m_cam_fd);
+ fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_STREAM_PAUSE, 0);
+ LOGV("\nsnapshot dequeued buffer = %d snapshot_width = %d snapshot_height = %d\n\n",
+ index, m_snapshot_width, m_snapshot_height);
+
+ LOG_TIME_END(2)
+
+ LOGI("%s : calling memcpy from m_capture_buf", __func__);
+ memcpy(yuv_buf, (unsigned char*)m_capture_buf.start, m_snapshot_width * m_snapshot_height * 2);
+ LOG_TIME_START(5) // post
+ fimc_v4l2_streamoff(m_cam_fd);
+ LOG_TIME_END(5)
+
+ LOG_CAMERA("getSnapshotAndJpeg intervals : stopPreview(%lu), prepare(%lu),"
+ " capture(%lu), memcpy(%lu), yuv2Jpeg(%lu), post(%lu) us",
+ LOG_TIME(0), LOG_TIME(1), LOG_TIME(2), LOG_TIME(3), LOG_TIME(4), LOG_TIME(5));
+ /* JPEG encoding */
+ JpegEncoder jpgEnc;
+ int inFormat = JPG_MODESEL_YCBCR;
+ int outFormat = JPG_422;
+
+ switch (m_snapshot_v4lformat) {
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_YUV420:
+ outFormat = JPG_420;
+ break;
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YUV422P:
+ default:
+ outFormat = JPG_422;
+ break;
+ }
+
+ if (jpgEnc.setConfig(JPEG_SET_ENCODE_IN_FORMAT, inFormat) != JPG_SUCCESS)
+ LOGE("[JPEG_SET_ENCODE_IN_FORMAT] Error\n");
+
+ if (jpgEnc.setConfig(JPEG_SET_SAMPING_MODE, outFormat) != JPG_SUCCESS)
+ LOGE("[JPEG_SET_SAMPING_MODE] Error\n");
+
+ image_quality_type_t jpegQuality;
+ if (m_jpeg_quality >= 90)
+ jpegQuality = JPG_QUALITY_LEVEL_1;
+ else if (m_jpeg_quality >= 80)
+ jpegQuality = JPG_QUALITY_LEVEL_2;
+ else if (m_jpeg_quality >= 70)
+ jpegQuality = JPG_QUALITY_LEVEL_3;
+ else
+ jpegQuality = JPG_QUALITY_LEVEL_4;
+
+ if (jpgEnc.setConfig(JPEG_SET_ENCODE_QUALITY, jpegQuality) != JPG_SUCCESS)
+ LOGE("[JPEG_SET_ENCODE_QUALITY] Error\n");
+ if (jpgEnc.setConfig(JPEG_SET_ENCODE_WIDTH, m_snapshot_width) != JPG_SUCCESS)
+ LOGE("[JPEG_SET_ENCODE_WIDTH] Error\n");
+
+ if (jpgEnc.setConfig(JPEG_SET_ENCODE_HEIGHT, m_snapshot_height) != JPG_SUCCESS)
+ LOGE("[JPEG_SET_ENCODE_HEIGHT] Error\n");
+
+ unsigned int snapshot_size = m_snapshot_width * m_snapshot_height * 2;
+ unsigned char *pInBuf = (unsigned char *)jpgEnc.getInBuf(snapshot_size);
+
+ if (pInBuf == NULL) {
+ LOGE("JPEG input buffer is NULL!!\n");
+ return -1;
+ }
+ memcpy(pInBuf, yuv_buf, snapshot_size);
+
+ setExifChangedAttribute();
+ jpgEnc.encode(output_size, NULL);
+
+ uint64_t outbuf_size;
+ unsigned char *pOutBuf = (unsigned char *)jpgEnc.getOutBuf(&outbuf_size);
+
+ if (pOutBuf == NULL) {
+ LOGE("JPEG output buffer is NULL!!\n");
+ return -1;
+ }
+
+ memcpy(jpeg_buf, pOutBuf, outbuf_size);
+
+ return 0;
+}
+
+
+int SecCamera::setSnapshotSize(int width, int height)
+{
+ LOGV("%s(width(%d), height(%d))", __func__, width, height);
+
+ m_snapshot_width = width;
+ m_snapshot_height = height;
+
+ return 0;
+}
+
+int SecCamera::getSnapshotSize(int *width, int *height, int *frame_size)
+{
+ *width = m_snapshot_width;
+ *height = m_snapshot_height;
+
+ int frame = 0;
+
+ frame = m_frameSize(m_snapshot_v4lformat, m_snapshot_width, m_snapshot_height);
+
+ // set it big.
+ if (frame == 0)
+ frame = m_snapshot_width * m_snapshot_height * BPP;
+
+ *frame_size = frame;
+
+ return 0;
+}
+
+int SecCamera::getSnapshotMaxSize(int *width, int *height)
+{
+ switch (m_camera_id) {
+ case CAMERA_ID_FRONT:
+ m_snapshot_max_width = MAX_FRONT_CAMERA_SNAPSHOT_WIDTH;
+ m_snapshot_max_height = MAX_FRONT_CAMERA_SNAPSHOT_HEIGHT;
+ break;
+
+ default:
+ case CAMERA_ID_BACK:
+ m_snapshot_max_width = MAX_BACK_CAMERA_SNAPSHOT_WIDTH;
+ m_snapshot_max_height = MAX_BACK_CAMERA_SNAPSHOT_HEIGHT;
+ break;
+ }
+
+ *width = m_snapshot_max_width;
+ *height = m_snapshot_max_height;
+
+ return 0;
+}
+
+int SecCamera::setSnapshotPixelFormat(int pixel_format)
+{
+ int v4lpixelformat= pixel_format;
+
+ if (m_snapshot_v4lformat != v4lpixelformat) {
+ m_snapshot_v4lformat = v4lpixelformat;
+ }
+
+#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0
+ if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV420)
+ LOGE("%s : SnapshotFormat:V4L2_PIX_FMT_YUV420", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV12", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV12T)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV12T", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_NV21)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_NV21", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUV422P)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_YUV422P", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_YUYV)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_YUYV", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_UYVY)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_UYVY", __func__);
+ else if (m_snapshot_v4lformat == V4L2_PIX_FMT_RGB565)
+ LOGD("%s : SnapshotFormat:V4L2_PIX_FMT_RGB565", __func__);
+ else
+ LOGD("SnapshotFormat:UnknownFormat");
+#endif
+ return 0;
+}
+
+int SecCamera::getSnapshotPixelFormat(void)
+{
+ return m_snapshot_v4lformat;
+}
+
+// ======================================================================
+// Settings
+
+int SecCamera::getCameraId(void)
+{
+ return m_camera_id;
+}
+
+// -----------------------------------
+
+int SecCamera::setAutofocus(void)
+{
+ LOGV("%s :", __func__);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_ON) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_AUTO_FOCUS", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int SecCamera::getAutoFocusResult(void)
+{
+ int af_result, count, ret;
+
+ for (count = 0; count < FIRST_AF_SEARCH_COUNT; count++) {
+ ret = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_AUTO_FOCUS_RESULT_FIRST);
+ if (ret != AF_PROGRESS)
+ break;
+ usleep(AF_DELAY);
+ }
+ if ((count >= FIRST_AF_SEARCH_COUNT) || (ret != AF_SUCCESS)) {
+ LOGV("%s : 1st AF timed out, failed, or was canceled", __func__);
+ af_result = 0;
+ goto finish_auto_focus;
+ }
+
+ for (count = 0; count < SECOND_AF_SEARCH_COUNT; count++) {
+ ret = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_AUTO_FOCUS_RESULT_SECOND);
+ /* low byte is garbage. done when high byte is 0x0 */
+ if (!(ret & 0xff00))
+ break;
+ usleep(AF_DELAY);
+ }
+ if (count >= SECOND_AF_SEARCH_COUNT) {
+ LOGV("%s : 2nd AF timed out, failed, or was canceled", __func__);
+ af_result = 0;
+ goto finish_auto_focus;
+ }
+
+ af_result = 1;
+ LOGV("%s : AF was successful, returning %d", __func__, af_result);
+
+finish_auto_focus:
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FINISH_AUTO_FOCUS, 0) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_PRE_FLASH", __func__);
+ return -1;
+ }
+ return af_result;
+}
+
+int SecCamera::cancelAutofocus(void)
+{
+ LOGV("%s :", __func__);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_AUTO_FOCUS, AUTO_FOCUS_OFF) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_AUTO_FOCUS", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+// -----------------------------------
+
+int SecCamera::zoomIn(void)
+{
+ LOGV("%s :", __func__);
+ return 0;
+}
+
+int SecCamera::zoomOut(void)
+{
+ LOGV("%s :", __func__);
+ return 0;
+}
+
+// -----------------------------------
+
+int SecCamera::SetRotate(int angle)
+{
+ LOGE("%s(angle(%d))", __func__, angle);
+
+ if (m_angle != angle) {
+ switch (angle) {
+ case -360:
+ case 0:
+ case 360:
+ m_angle = 0;
+ break;
+
+ case -270:
+ case 90:
+ m_angle = 90;
+ break;
+
+ case -180:
+ case 180:
+ m_angle = 180;
+ break;
+
+ case -90:
+ case 270:
+ m_angle = 270;
+ break;
+
+ default:
+ LOGE("ERR(%s):Invalid angle(%d)", __func__, angle);
+ return -1;
+ }
+
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_ROTATION, angle) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_ROTATION", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getRotate(void)
+{
+ LOGV("%s : angle(%d)", __func__, m_angle);
+ return m_angle;
+}
+
+int SecCamera::setFrameRate(int frame_rate)
+{
+ LOGV("%s(FrameRate(%d))", __func__, frame_rate);
+
+ if (frame_rate < FRAME_RATE_AUTO || FRAME_RATE_MAX < frame_rate )
+ LOGE("ERR(%s):Invalid frame_rate(%d)", __func__, frame_rate);
+
+ if (m_params->capture.timeperframe.denominator != (unsigned)frame_rate) {
+ m_params->capture.timeperframe.denominator = frame_rate;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FRAME_RATE, frame_rate) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FRAME_RATE", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------
+
+int SecCamera::setVerticalMirror(void)
+{
+ LOGV("%s :", __func__);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_VFLIP, 0) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_VFLIP", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int SecCamera::setHorizontalMirror(void)
+{
+ LOGV("%s :", __func__);
+
+ if (m_cam_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed\n", __func__);
+ return -1;
+ }
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_HFLIP, 0) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_HFLIP", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+// -----------------------------------
+
+int SecCamera::setWhiteBalance(int white_balance)
+{
+ LOGV("%s(white_balance(%d))", __func__, white_balance);
+
+ if (white_balance <= WHITE_BALANCE_BASE || WHITE_BALANCE_MAX <= white_balance) {
+ LOGE("ERR(%s):Invalid white_balance(%d)", __func__, white_balance);
+ return -1;
+ }
+
+ if (m_params->white_balance != white_balance) {
+ m_params->white_balance = white_balance;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_WHITE_BALANCE, white_balance) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_WHITE_BALANCE", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getWhiteBalance(void)
+{
+ LOGV("%s : white_balance(%d)", __func__, m_params->white_balance);
+ return m_params->white_balance;
+}
+
+// -----------------------------------
+
+int SecCamera::setBrightness(int brightness)
+{
+ LOGV("%s(brightness(%d))", __func__, brightness);
+
+ brightness += EV_DEFAULT;
+
+ if (brightness < EV_MINUS_4 || EV_PLUS_4 < brightness) {
+ LOGE("ERR(%s):Invalid brightness(%d)", __func__, brightness);
+ return -1;
+ }
+
+ if (m_params->brightness != brightness) {
+ m_params->brightness = brightness;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_BRIGHTNESS, brightness) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_BRIGHTNESS", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getBrightness(void)
+{
+ LOGV("%s : brightness(%d)", __func__, m_params->brightness);
+ return m_params->brightness;
+}
+
+// -----------------------------------
+
+int SecCamera::setImageEffect(int image_effect)
+{
+ LOGV("%s(image_effect(%d))", __func__, image_effect);
+
+ if (image_effect <= IMAGE_EFFECT_BASE || IMAGE_EFFECT_MAX <= image_effect) {
+ LOGE("ERR(%s):Invalid image_effect(%d)", __func__, image_effect);
+ return -1;
+ }
+
+ if (m_params->effects != image_effect) {
+ m_params->effects = image_effect;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_EFFECT, image_effect) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_EFFECT", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getImageEffect(void)
+{
+ LOGV("%s : image_effect(%d)", __func__, m_params->effects);
+ return m_params->effects;
+}
+
+// ======================================================================
+int SecCamera::setAntiBanding(int anti_banding)
+{
+ LOGV("%s(anti_banding(%d))", __func__, anti_banding);
+
+ if (anti_banding < ANTI_BANDING_AUTO || ANTI_BANDING_OFF < anti_banding) {
+ LOGE("ERR(%s):Invalid anti_banding (%d)", __func__, anti_banding);
+ return -1;
+ }
+
+ if (m_anti_banding != anti_banding) {
+ m_anti_banding = anti_banding;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ANTI_BANDING, anti_banding) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ANTI_BANDING", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+//======================================================================
+int SecCamera::setSceneMode(int scene_mode)
+{
+ LOGV("%s(scene_mode(%d))", __func__, scene_mode);
+
+ if (scene_mode <= SCENE_MODE_BASE || SCENE_MODE_MAX <= scene_mode) {
+ LOGE("ERR(%s):Invalid scene_mode (%d)", __func__, scene_mode);
+ return -1;
+ }
+
+ if (m_params->scene_mode != scene_mode) {
+ m_params->scene_mode = scene_mode;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SCENE_MODE, scene_mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SCENE_MODE", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getSceneMode(void)
+{
+ return m_params->scene_mode;
+}
+
+//======================================================================
+
+int SecCamera::setFlashMode(int flash_mode)
+{
+ LOGV("%s(flash_mode(%d))", __func__, flash_mode);
+
+ if (flash_mode <= FLASH_MODE_BASE || FLASH_MODE_MAX <= flash_mode) {
+ LOGE("ERR(%s):Invalid flash_mode (%d)", __func__, flash_mode);
+ return -1;
+ }
+
+ if (m_params->flash_mode != flash_mode) {
+ m_params->flash_mode = flash_mode;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FLASH_MODE, flash_mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FLASH_MODE", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getFlashMode(void)
+{
+ return m_params->flash_mode;
+}
+
+//======================================================================
+
+int SecCamera::setISO(int iso_value)
+{
+ LOGV("%s(iso_value(%d))", __func__, iso_value);
+ if (iso_value < ISO_AUTO || ISO_MAX <= iso_value) {
+ LOGE("ERR(%s):Invalid iso_value (%d)", __func__, iso_value);
+ return -1;
+ }
+
+ if (m_params->iso != iso_value) {
+ m_params->iso = iso_value;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ISO, iso_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ISO", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getISO(void)
+{
+ return m_params->iso;
+}
+
+//======================================================================
+
+int SecCamera::setContrast(int contrast_value)
+{
+ LOGV("%s(contrast_value(%d))", __func__, contrast_value);
+
+ if (contrast_value < CONTRAST_MINUS_2 || CONTRAST_MAX <= contrast_value) {
+ LOGE("ERR(%s):Invalid contrast_value (%d)", __func__, contrast_value);
+ return -1;
+ }
+
+ if (m_params->contrast != contrast_value) {
+ m_params->contrast = contrast_value;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_CONTRAST, contrast_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_CONTRAST", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getContrast(void)
+{
+ return m_params->contrast;
+}
+
+//======================================================================
+
+int SecCamera::setSaturation(int saturation_value)
+{
+ LOGV("%s(saturation_value(%d))", __func__, saturation_value);
+
+ if (saturation_value <SATURATION_MINUS_2 || SATURATION_MAX<= saturation_value) {
+ LOGE("ERR(%s):Invalid saturation_value (%d)", __func__, saturation_value);
+ return -1;
+ }
+
+ if (m_params->saturation != saturation_value) {
+ m_params->saturation = saturation_value;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SATURATION, saturation_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SATURATION", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getSaturation(void)
+{
+ return m_params->saturation;
+}
+
+//======================================================================
+
+int SecCamera::setSharpness(int sharpness_value)
+{
+ LOGV("%s(sharpness_value(%d))", __func__, sharpness_value);
+
+ if (sharpness_value < SHARPNESS_MINUS_2 || SHARPNESS_MAX <= sharpness_value) {
+ LOGE("ERR(%s):Invalid sharpness_value (%d)", __func__, sharpness_value);
+ return -1;
+ }
+
+ if (m_params->sharpness != sharpness_value) {
+ m_params->sharpness = sharpness_value;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SHARPNESS, sharpness_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SHARPNESS", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getSharpness(void)
+{
+ return m_params->sharpness;
+}
+
+//======================================================================
+
+int SecCamera::setWDR(int wdr_value)
+{
+ LOGV("%s(wdr_value(%d))", __func__, wdr_value);
+
+ if (wdr_value < WDR_OFF || WDR_MAX <= wdr_value) {
+ LOGE("ERR(%s):Invalid wdr_value (%d)", __func__, wdr_value);
+ return -1;
+ }
+
+ if (m_wdr != wdr_value) {
+ m_wdr = wdr_value;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_WDR, wdr_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_WDR", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getWDR(void)
+{
+ return m_wdr;
+}
+
+//======================================================================
+
+int SecCamera::setAntiShake(int anti_shake)
+{
+ LOGV("%s(anti_shake(%d))", __func__, anti_shake);
+
+ if (anti_shake < ANTI_SHAKE_OFF || ANTI_SHAKE_MAX <= anti_shake) {
+ LOGE("ERR(%s):Invalid anti_shake (%d)", __func__, anti_shake);
+ return -1;
+ }
+
+ if (m_anti_shake != anti_shake) {
+ m_anti_shake = anti_shake;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ANTI_SHAKE, anti_shake) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ANTI_SHAKE", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getAntiShake(void)
+{
+ return m_anti_shake;
+}
+
+//======================================================================
+
+
+int SecCamera::setMetering(int metering_value)
+{
+ LOGV("%s(metering (%d))", __func__, metering_value);
+
+ if (metering_value <= METERING_BASE || METERING_MAX <= metering_value) {
+ LOGE("ERR(%s):Invalid metering_value (%d)", __func__, metering_value);
+ return -1;
+ }
+
+ if (m_params->metering != metering_value) {
+ m_params->metering = metering_value;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_METERING, metering_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_METERING", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getMetering(void)
+{
+ return m_params->metering;
+}
+
+//======================================================================
+
+int SecCamera::setJpegQuality(int jpeg_quality)
+{
+ LOGV("%s(jpeg_quality (%d))", __func__, jpeg_quality);
+
+ if (jpeg_quality < JPEG_QUALITY_ECONOMY || JPEG_QUALITY_MAX <= jpeg_quality) {
+ LOGE("ERR(%s):Invalid jpeg_quality (%d)", __func__, jpeg_quality);
+ return -1;
+ }
+
+ if (m_jpeg_quality != jpeg_quality) {
+ m_jpeg_quality = jpeg_quality;
+ if (m_flag_camera_start && (m_camera_id == CAMERA_ID_BACK)) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAM_JPEG_QUALITY, jpeg_quality) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAM_JPEG_QUALITY", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getJpegQuality(void)
+{
+ return m_jpeg_quality;
+}
+
+//======================================================================
+
+int SecCamera::setZoom(int zoom_level)
+{
+ LOGV("%s(zoom_level (%d))", __func__, zoom_level);
+
+ if (zoom_level < ZOOM_LEVEL_0 || ZOOM_LEVEL_MAX <= zoom_level) {
+ LOGE("ERR(%s):Invalid zoom_level (%d)", __func__, zoom_level);
+ return -1;
+ }
+
+ if (m_zoom_level != zoom_level) {
+ m_zoom_level = zoom_level;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_ZOOM, zoom_level) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_ZOOM", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getZoom(void)
+{
+ return m_zoom_level;
+}
+
+//======================================================================
+
+int SecCamera::setObjectTracking(int object_tracking)
+{
+ LOGV("%s(object_tracking (%d))", __func__, object_tracking);
+
+ if (object_tracking < OBJECT_TRACKING_OFF || OBJECT_TRACKING_MAX <= object_tracking) {
+ LOGE("ERR(%s):Invalid object_tracking (%d)", __func__, object_tracking);
+ return -1;
+ }
+
+ if (m_object_tracking != object_tracking) {
+ m_object_tracking = object_tracking;
+ }
+
+ return 0;
+}
+
+int SecCamera::getObjectTracking(void)
+{
+ return m_object_tracking;
+}
+
+int SecCamera::getObjectTrackingStatus(void)
+{
+ int obj_status = 0;
+ obj_status = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_OBJ_TRACKING_STATUS);
+ return obj_status;
+}
+
+int SecCamera::setObjectTrackingStartStop(int start_stop)
+{
+ LOGV("%s(object_tracking_start_stop (%d))", __func__, start_stop);
+
+ if (m_object_tracking_start_stop != start_stop) {
+ m_object_tracking_start_stop = start_stop;
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_OBJ_TRACKING_START_STOP, start_stop) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_OBJ_TRACKING_START_STOP", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::setTouchAFStartStop(int start_stop)
+{
+ LOGV("%s(touch_af_start_stop (%d))", __func__, start_stop);
+
+ if (m_touch_af_start_stop != start_stop) {
+ m_touch_af_start_stop = start_stop;
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_TOUCH_AF_START_STOP, start_stop) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_TOUCH_AF_START_STOP", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+//======================================================================
+
+int SecCamera::setSmartAuto(int smart_auto)
+{
+ LOGV("%s(smart_auto (%d))", __func__, smart_auto);
+
+ if (smart_auto < SMART_AUTO_OFF || SMART_AUTO_MAX <= smart_auto) {
+ LOGE("ERR(%s):Invalid smart_auto (%d)", __func__, smart_auto);
+ return -1;
+ }
+
+ if (m_smart_auto != smart_auto) {
+ m_smart_auto = smart_auto;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SMART_AUTO, smart_auto) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SMART_AUTO", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getSmartAuto(void)
+{
+ return m_smart_auto;
+}
+
+int SecCamera::getAutosceneStatus(void)
+{
+ int autoscene_status = -1;
+
+ if (getSmartAuto() == SMART_AUTO_ON) {
+ autoscene_status = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_SMART_AUTO_STATUS);
+
+ if ((autoscene_status < SMART_AUTO_STATUS_AUTO) || (autoscene_status > SMART_AUTO_STATUS_MAX)) {
+ LOGE("ERR(%s):Invalid getAutosceneStatus (%d)", __func__, autoscene_status);
+ return -1;
+ }
+ }
+ //LOGV("%s : autoscene_status (%d)", __func__, autoscene_status);
+ return autoscene_status;
+}
+//======================================================================
+
+int SecCamera::setBeautyShot(int beauty_shot)
+{
+ LOGV("%s(beauty_shot (%d))", __func__, beauty_shot);
+
+ if (beauty_shot < BEAUTY_SHOT_OFF || BEAUTY_SHOT_MAX <= beauty_shot) {
+ LOGE("ERR(%s):Invalid beauty_shot (%d)", __func__, beauty_shot);
+ return -1;
+ }
+
+ if (m_beauty_shot != beauty_shot) {
+ m_beauty_shot = beauty_shot;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_BEAUTY_SHOT, beauty_shot) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_BEAUTY_SHOT", __func__);
+ return -1;
+ }
+ }
+
+ setFaceDetect(FACE_DETECTION_ON_BEAUTY);
+ }
+
+ return 0;
+}
+
+int SecCamera::getBeautyShot(void)
+{
+ return m_beauty_shot;
+}
+
+//======================================================================
+
+int SecCamera::setVintageMode(int vintage_mode)
+{
+ LOGV("%s(vintage_mode(%d))", __func__, vintage_mode);
+
+ if (vintage_mode <= VINTAGE_MODE_BASE || VINTAGE_MODE_MAX <= vintage_mode) {
+ LOGE("ERR(%s):Invalid vintage_mode (%d)", __func__, vintage_mode);
+ return -1;
+ }
+
+ if (m_vintage_mode != vintage_mode) {
+ m_vintage_mode = vintage_mode;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_VINTAGE_MODE, vintage_mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_VINTAGE_MODE", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getVintageMode(void)
+{
+ return m_vintage_mode;
+}
+
+//======================================================================
+
+int SecCamera::setFocusMode(int focus_mode)
+{
+ LOGV("%s(focus_mode(%d))", __func__, focus_mode);
+
+ if (FOCUS_MODE_MAX <= focus_mode) {
+ LOGE("ERR(%s):Invalid focus_mode (%d)", __func__, focus_mode);
+ return -1;
+ }
+
+ if (m_params->focus_mode != focus_mode) {
+ m_params->focus_mode = focus_mode;
+
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FOCUS_MODE, focus_mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FOCUS_MODE", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getFocusMode(void)
+{
+ return m_params->focus_mode;
+}
+
+//======================================================================
+
+int SecCamera::setFaceDetect(int face_detect)
+{
+ LOGV("%s(face_detect(%d))", __func__, face_detect);
+
+ if (m_face_detect != face_detect) {
+ m_face_detect = face_detect;
+ if (m_flag_camera_start) {
+ if (m_face_detect != FACE_DETECTION_OFF) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FOCUS_MODE, FOCUS_MODE_AUTO) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FOCUS_MODin face detecion", __func__);
+ return -1;
+ }
+ }
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FACE_DETECTION, face_detect) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FACE_DETECTION", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getFaceDetect(void)
+{
+ return m_face_detect;
+}
+
+//======================================================================
+
+int SecCamera::setGPSLatitude(const char *gps_latitude)
+{
+ LOGV("%s(gps_latitude(%s))", __func__, gps_latitude);
+ if (gps_latitude == NULL)
+ m_gps_enabled = false;
+ else {
+ m_gps_enabled = true;
+ m_gps_latitude = lround(strtod(gps_latitude, NULL) * 10000000);
+ }
+
+ LOGV("%s(m_gps_latitude(%ld))", __func__, m_gps_latitude);
+ return 0;
+}
+
+int SecCamera::setGPSLongitude(const char *gps_longitude)
+{
+ LOGV("%s(gps_longitude(%s))", __func__, gps_longitude);
+ if (gps_longitude == NULL)
+ m_gps_enabled = false;
+ else {
+ m_gps_enabled = true;
+ m_gps_longitude = lround(strtod(gps_longitude, NULL) * 10000000);
+ }
+
+ LOGV("%s(m_gps_longitude(%ld))", __func__, m_gps_longitude);
+ return 0;
+}
+
+int SecCamera::setGPSAltitude(const char *gps_altitude)
+{
+ LOGV("%s(gps_altitude(%s))", __func__, gps_altitude);
+ if (gps_altitude == NULL)
+ m_gps_altitude = 0;
+ else {
+ m_gps_altitude = lround(strtod(gps_altitude, NULL) * 100);
+ }
+
+ LOGV("%s(m_gps_altitude(%ld))", __func__, m_gps_altitude);
+ return 0;
+}
+
+int SecCamera::setGPSTimeStamp(const char *gps_timestamp)
+{
+ LOGV("%s(gps_timestamp(%s))", __func__, gps_timestamp);
+ if (gps_timestamp == NULL)
+ m_gps_timestamp = 0;
+ else
+ m_gps_timestamp = atol(gps_timestamp);
+
+ LOGV("%s(m_gps_timestamp(%ld))", __func__, m_gps_timestamp);
+ return 0;
+}
+
+int SecCamera::setGPSProcessingMethod(const char *gps_processing_method)
+{
+ LOGV("%s(gps_processing_method(%s))", __func__, gps_processing_method);
+ memset(mExifInfo.gps_processing_method, 0, sizeof(mExifInfo.gps_processing_method));
+ if (gps_processing_method != NULL) {
+ size_t len = strlen(gps_processing_method);
+ if (len > sizeof(mExifInfo.gps_processing_method)) {
+ len = sizeof(mExifInfo.gps_processing_method);
+ }
+ memcpy(mExifInfo.gps_processing_method, gps_processing_method, len);
+ }
+ return 0;
+}
+
+int SecCamera::setFaceDetectLockUnlock(int facedetect_lockunlock)
+{
+ LOGV("%s(facedetect_lockunlock(%d))", __func__, facedetect_lockunlock);
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_FACEDETECT_LOCKUNLOCK, facedetect_lockunlock) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FACEDETECT_LOCKUNLOCK", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int SecCamera::setObjectPosition(int x, int y)
+{
+ LOGV("%s(setObjectPosition(x=%d, y=%d))", __func__, x, y);
+
+ if (m_preview_width ==640)
+ x = x - 80;
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_OBJECT_POSITION_X, x) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_OBJECT_POSITION_X", __func__);
+ return -1;
+ }
+
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_OBJECT_POSITION_Y, y) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_OBJECT_POSITION_Y", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+//======================================================================
+
+int SecCamera::setGamma(int gamma)
+{
+ LOGV("%s(gamma(%d))", __func__, gamma);
+
+ if (gamma < GAMMA_OFF || GAMMA_MAX <= gamma) {
+ LOGE("ERR(%s):Invalid gamma (%d)", __func__, gamma);
+ return -1;
+ }
+
+ if (m_video_gamma != gamma) {
+ m_video_gamma = gamma;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_GAMMA, gamma) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_GAMMA", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+//======================================================================
+
+int SecCamera::setSlowAE(int slow_ae)
+{
+ LOGV("%s(slow_ae(%d))", __func__, slow_ae);
+
+ if (slow_ae < GAMMA_OFF || GAMMA_MAX <= slow_ae) {
+ LOGE("ERR(%s):Invalid slow_ae (%d)", __func__, slow_ae);
+ return -1;
+ }
+
+ if (m_slow_ae!= slow_ae) {
+ m_slow_ae = slow_ae;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_SET_SLOW_AE, slow_ae) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SET_SLOW_AE", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+//======================================================================
+int SecCamera::setRecordingSize(int width, int height)
+{
+ LOGV("%s(width(%d), height(%d))", __func__, width, height);
+
+ m_recording_width = width;
+ m_recording_height = height;
+
+ return 0;
+}
+
+//======================================================================
+
+int SecCamera::setExifOrientationInfo(int orientationInfo)
+{
+ LOGV("%s(orientationInfo(%d))", __func__, orientationInfo);
+
+ if (orientationInfo < 0) {
+ LOGE("ERR(%s):Invalid orientationInfo (%d)", __func__, orientationInfo);
+ return -1;
+ }
+ m_exif_orientation = orientationInfo;
+
+ return 0;
+}
+
+//======================================================================
+int SecCamera::setBatchReflection()
+{
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_BATCH_REFLECTION, 1) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_BATCH_REFLECTION", __func__);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*Video call*/
+int SecCamera::setVTmode(int vtmode)
+{
+ LOGV("%s(vtmode (%d))", __func__, vtmode);
+
+ if (vtmode < VT_MODE_OFF || VT_MODE_MAX <= vtmode) {
+ LOGE("ERR(%s):Invalid vtmode (%d)", __func__, vtmode);
+ return -1;
+ }
+
+ if (m_vtmode != vtmode) {
+ m_vtmode = vtmode;
+ }
+
+ return 0;
+}
+
+/* Camcorder fix fps */
+int SecCamera::setSensorMode(int sensor_mode)
+{
+ LOGV("%s(sensor_mode (%d))", __func__, sensor_mode);
+
+ if (sensor_mode < SENSOR_MODE_CAMERA || SENSOR_MODE_MOVIE < sensor_mode) {
+ LOGE("ERR(%s):Invalid sensor mode (%d)", __func__, sensor_mode);
+ return -1;
+ }
+
+ if (m_sensor_mode != sensor_mode) {
+ m_sensor_mode = sensor_mode;
+ }
+
+ return 0;
+}
+
+/* Shot mode */
+/* SINGLE = 0
+* CONTINUOUS = 1
+* PANORAMA = 2
+* SMILE = 3
+* SELF = 6
+*/
+int SecCamera::setShotMode(int shot_mode)
+{
+ LOGV("%s(shot_mode (%d))", __func__, shot_mode);
+ if (shot_mode < SHOT_MODE_SINGLE || SHOT_MODE_SELF < shot_mode) {
+ LOGE("ERR(%s):Invalid shot_mode (%d)", __func__, shot_mode);
+ return -1;
+ }
+ m_shot_mode = shot_mode;
+
+ return 0;
+}
+
+int SecCamera::getVTmode(void)
+{
+ return m_vtmode;
+}
+
+int SecCamera::setBlur(int blur_level)
+{
+ LOGV("%s(level (%d))", __func__, blur_level);
+
+ if (blur_level < BLUR_LEVEL_0 || BLUR_LEVEL_MAX <= blur_level) {
+ LOGE("ERR(%s):Invalid level (%d)", __func__, blur_level);
+ return -1;
+ }
+
+ if (m_blur_level != blur_level) {
+ m_blur_level = blur_level;
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_VGA_BLUR, blur_level) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_VGA_BLUR", __func__);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+int SecCamera::getBlur(void)
+{
+ return m_blur_level;
+}
+
+int SecCamera::setDataLineCheck(int chk_dataline)
+{
+ LOGV("%s(chk_dataline (%d))", __func__, chk_dataline);
+
+ if (chk_dataline < CHK_DATALINE_OFF || CHK_DATALINE_MAX <= chk_dataline) {
+ LOGE("ERR(%s):Invalid chk_dataline (%d)", __func__, chk_dataline);
+ return -1;
+ }
+
+ m_chk_dataline = chk_dataline;
+
+ return 0;
+}
+
+int SecCamera::getDataLineCheck(void)
+{
+ return m_chk_dataline;
+}
+
+int SecCamera::setDataLineCheckStop(void)
+{
+ LOGV("%s", __func__);
+
+ if (m_flag_camera_start) {
+ if (fimc_v4l2_s_ctrl(m_cam_fd, V4L2_CID_CAMERA_CHECK_DATALINE_STOP, 1) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_CHECK_DATALINE_STOP", __func__);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+const __u8* SecCamera::getCameraSensorName(void)
+{
+ LOGV("%s", __func__);
+
+ return fimc_v4l2_enuminput(m_cam_fd, getCameraId());
+}
+
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+int SecCamera::getCameraSensorESDStatus(void)
+{
+ LOGV("%s", __func__);
+
+ // 0 : normal operation, 1 : abnormal operation
+ int status = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_ESD_INT);
+
+ return status;
+}
+#endif // ENABLE_ESD_PREVIEW_CHECK
+
+// ======================================================================
+// Jpeg
+
+int SecCamera::setJpegThumbnailSize(int width, int height)
+{
+ LOGV("%s(width(%d), height(%d))", __func__, width, height);
+
+ m_jpeg_thumbnail_width = width;
+ m_jpeg_thumbnail_height = height;
+
+ return 0;
+}
+
+int SecCamera::getJpegThumbnailSize(int *width, int *height)
+{
+ if (width)
+ *width = m_jpeg_thumbnail_width;
+ if (height)
+ *height = m_jpeg_thumbnail_height;
+
+ return 0;
+}
+
+void SecCamera::setExifFixedAttribute()
+{
+ char property[PROPERTY_VALUE_MAX];
+
+ //2 0th IFD TIFF Tags
+ //3 Maker
+ property_get("ro.product.brand", property, EXIF_DEF_MAKER);
+ strncpy((char *)mExifInfo.maker, property,
+ sizeof(mExifInfo.maker) - 1);
+ mExifInfo.maker[sizeof(mExifInfo.maker) - 1] = '\0';
+ //3 Model
+ property_get("ro.product.model", property, EXIF_DEF_MODEL);
+ strncpy((char *)mExifInfo.model, property,
+ sizeof(mExifInfo.model) - 1);
+ mExifInfo.model[sizeof(mExifInfo.model) - 1] = '\0';
+ //3 Software
+ property_get("ro.build.id", property, EXIF_DEF_SOFTWARE);
+ strncpy((char *)mExifInfo.software, property,
+ sizeof(mExifInfo.software) - 1);
+ mExifInfo.software[sizeof(mExifInfo.software) - 1] = '\0';
+
+ //3 YCbCr Positioning
+ mExifInfo.ycbcr_positioning = EXIF_DEF_YCBCR_POSITIONING;
+
+ //2 0th IFD Exif Private Tags
+ //3 F Number
+ mExifInfo.fnumber.num = EXIF_DEF_FNUMBER_NUM;
+ mExifInfo.fnumber.den = EXIF_DEF_FNUMBER_DEN;
+ //3 Exposure Program
+ mExifInfo.exposure_program = EXIF_DEF_EXPOSURE_PROGRAM;
+ //3 Exif Version
+ memcpy(mExifInfo.exif_version, EXIF_DEF_EXIF_VERSION, sizeof(mExifInfo.exif_version));
+ //3 Aperture
+ uint32_t av = APEX_FNUM_TO_APERTURE((double)mExifInfo.fnumber.num/mExifInfo.fnumber.den);
+ mExifInfo.aperture.num = av*EXIF_DEF_APEX_DEN;
+ mExifInfo.aperture.den = EXIF_DEF_APEX_DEN;
+ //3 Maximum lens aperture
+ mExifInfo.max_aperture.num = mExifInfo.aperture.num;
+ mExifInfo.max_aperture.den = mExifInfo.aperture.den;
+ //3 Lens Focal Length
+ if (m_camera_id == CAMERA_ID_BACK)
+ mExifInfo.focal_length.num = BACK_CAMERA_FOCAL_LENGTH;
+ else
+ mExifInfo.focal_length.num = FRONT_CAMERA_FOCAL_LENGTH;
+
+ mExifInfo.focal_length.den = EXIF_DEF_FOCAL_LEN_DEN;
+ //3 User Comments
+ strcpy((char *)mExifInfo.user_comment, EXIF_DEF_USERCOMMENTS);
+ //3 Color Space information
+ mExifInfo.color_space = EXIF_DEF_COLOR_SPACE;
+ //3 Exposure Mode
+ mExifInfo.exposure_mode = EXIF_DEF_EXPOSURE_MODE;
+
+ //2 0th IFD GPS Info Tags
+ unsigned char gps_version[4] = { 0x02, 0x02, 0x00, 0x00 };
+ memcpy(mExifInfo.gps_version_id, gps_version, sizeof(gps_version));
+
+ //2 1th IFD TIFF Tags
+ mExifInfo.compression_scheme = EXIF_DEF_COMPRESSION;
+ mExifInfo.x_resolution.num = EXIF_DEF_RESOLUTION_NUM;
+ mExifInfo.x_resolution.den = EXIF_DEF_RESOLUTION_DEN;
+ mExifInfo.y_resolution.num = EXIF_DEF_RESOLUTION_NUM;
+ mExifInfo.y_resolution.den = EXIF_DEF_RESOLUTION_DEN;
+ mExifInfo.resolution_unit = EXIF_DEF_RESOLUTION_UNIT;
+}
+
+void SecCamera::setExifChangedAttribute()
+{
+ //2 0th IFD TIFF Tags
+ //3 Width
+ mExifInfo.width = m_snapshot_width;
+ //3 Height
+ mExifInfo.height = m_snapshot_height;
+ //3 Orientation
+ switch (m_exif_orientation) {
+ case 0:
+ mExifInfo.orientation = EXIF_ORIENTATION_UP;
+ break;
+ case 90:
+ mExifInfo.orientation = EXIF_ORIENTATION_90;
+ break;
+ case 180:
+ mExifInfo.orientation = EXIF_ORIENTATION_180;
+ break;
+ case 270:
+ mExifInfo.orientation = EXIF_ORIENTATION_270;
+ break;
+ default:
+ mExifInfo.orientation = EXIF_ORIENTATION_UP;
+ break;
+ }
+ //3 Date time
+ time_t rawtime;
+ struct tm *timeinfo;
+ time(&rawtime);
+ timeinfo = localtime(&rawtime);
+ strftime((char *)mExifInfo.date_time, 20, "%Y:%m:%d %H:%M:%S", timeinfo);
+
+ //2 0th IFD Exif Private Tags
+ //3 Exposure Time
+ int shutterSpeed = fimc_v4l2_g_ctrl(m_cam_fd,
+ V4L2_CID_CAMERA_GET_SHT_TIME);
+ /* TBD - front camera needs to be fixed to support this g_ctrl,
+ it current returns a negative err value, so avoid putting
+ odd value into exif for now */
+ if (shutterSpeed < 0) {
+ LOGE("%s: error %d getting shutterSpeed, camera_id = %d, using 100",
+ __func__, shutterSpeed, m_camera_id);
+ shutterSpeed = 100;
+ }
+ mExifInfo.exposure_time.num = 1;
+ // x us -> 1/x s */
+ mExifInfo.exposure_time.den = (uint32_t)(1000000 / shutterSpeed);
+
+ //3 ISO Speed Rating
+ int iso = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_GET_ISO);
+ /* TBD - front camera needs to be fixed to support this g_ctrl,
+ it current returns a negative err value, so avoid putting
+ odd value into exif for now */
+ if (iso < 0) {
+ LOGE("%s: error %d getting iso, camera_id = %d, using 100",
+ __func__, iso, m_camera_id);
+ iso = ISO_100;
+ }
+ switch(iso) {
+ case ISO_50:
+ mExifInfo.iso_speed_rating = 50;
+ break;
+ case ISO_100:
+ mExifInfo.iso_speed_rating = 100;
+ break;
+ case ISO_200:
+ mExifInfo.iso_speed_rating = 200;
+ break;
+ case ISO_400:
+ mExifInfo.iso_speed_rating = 400;
+ break;
+ case ISO_800:
+ mExifInfo.iso_speed_rating = 800;
+ break;
+ case ISO_1600:
+ mExifInfo.iso_speed_rating = 1600;
+ break;
+ default:
+ mExifInfo.iso_speed_rating = 100;
+ break;
+ }
+
+ uint32_t av, tv, bv, sv, ev;
+ av = APEX_FNUM_TO_APERTURE((double)mExifInfo.fnumber.num / mExifInfo.fnumber.den);
+ tv = APEX_EXPOSURE_TO_SHUTTER((double)mExifInfo.exposure_time.num / mExifInfo.exposure_time.den);
+ sv = APEX_ISO_TO_FILMSENSITIVITY(mExifInfo.iso_speed_rating);
+ bv = av + tv - sv;
+ ev = av + tv;
+ LOGD("Shutter speed=%d us, iso=%d\n", shutterSpeed, mExifInfo.iso_speed_rating);
+ LOGD("AV=%d, TV=%d, SV=%d\n", av, tv, sv);
+
+ //3 Shutter Speed
+ mExifInfo.shutter_speed.num = tv*EXIF_DEF_APEX_DEN;
+ mExifInfo.shutter_speed.den = EXIF_DEF_APEX_DEN;
+ //3 Brightness
+ mExifInfo.brightness.num = bv*EXIF_DEF_APEX_DEN;
+ mExifInfo.brightness.den = EXIF_DEF_APEX_DEN;
+ //3 Exposure Bias
+ if (m_params->scene_mode == SCENE_MODE_BEACH_SNOW) {
+ mExifInfo.exposure_bias.num = EXIF_DEF_APEX_DEN;
+ mExifInfo.exposure_bias.den = EXIF_DEF_APEX_DEN;
+ } else {
+ mExifInfo.exposure_bias.num = 0;
+ mExifInfo.exposure_bias.den = 0;
+ }
+ //3 Metering Mode
+ switch (m_params->metering) {
+ case METERING_SPOT:
+ mExifInfo.metering_mode = EXIF_METERING_SPOT;
+ break;
+ case METERING_MATRIX:
+ mExifInfo.metering_mode = EXIF_METERING_AVERAGE;
+ break;
+ case METERING_CENTER:
+ mExifInfo.metering_mode = EXIF_METERING_CENTER;
+ break;
+ default :
+ mExifInfo.metering_mode = EXIF_METERING_AVERAGE;
+ break;
+ }
+
+ //3 Flash
+ int flash = fimc_v4l2_g_ctrl(m_cam_fd, V4L2_CID_CAMERA_GET_FLASH_ONOFF);
+ if (flash < 0)
+ mExifInfo.flash = EXIF_DEF_FLASH;
+ else
+ mExifInfo.flash = flash;
+
+ //3 White Balance
+ if (m_params->white_balance == WHITE_BALANCE_AUTO)
+ mExifInfo.white_balance = EXIF_WB_AUTO;
+ else
+ mExifInfo.white_balance = EXIF_WB_MANUAL;
+ //3 Scene Capture Type
+ switch (m_params->scene_mode) {
+ case SCENE_MODE_PORTRAIT:
+ mExifInfo.scene_capture_type = EXIF_SCENE_PORTRAIT;
+ break;
+ case SCENE_MODE_LANDSCAPE:
+ mExifInfo.scene_capture_type = EXIF_SCENE_LANDSCAPE;
+ break;
+ case SCENE_MODE_NIGHTSHOT:
+ mExifInfo.scene_capture_type = EXIF_SCENE_NIGHT;
+ break;
+ default:
+ mExifInfo.scene_capture_type = EXIF_SCENE_STANDARD;
+ break;
+ }
+
+ //2 0th IFD GPS Info Tags
+ if (m_gps_enabled) {
+ if (m_gps_latitude >= 0)
+ strcpy((char *)mExifInfo.gps_latitude_ref, "N");
+ else
+ strcpy((char *)mExifInfo.gps_latitude_ref, "S");
+
+ if (m_gps_longitude >= 0)
+ strcpy((char *)mExifInfo.gps_longitude_ref, "E");
+ else
+ strcpy((char *)mExifInfo.gps_longitude_ref, "W");
+
+ if (m_gps_altitude >= 0)
+ mExifInfo.gps_altitude_ref = 0;
+ else
+ mExifInfo.gps_altitude_ref = 1;
+
+ mExifInfo.gps_latitude[0].num = (uint32_t)labs(m_gps_latitude);
+ mExifInfo.gps_latitude[0].den = 10000000;
+ mExifInfo.gps_latitude[1].num = 0;
+ mExifInfo.gps_latitude[1].den = 1;
+ mExifInfo.gps_latitude[2].num = 0;
+ mExifInfo.gps_latitude[2].den = 1;
+
+ mExifInfo.gps_longitude[0].num = (uint32_t)labs(m_gps_longitude);
+ mExifInfo.gps_longitude[0].den = 10000000;
+ mExifInfo.gps_longitude[1].num = 0;
+ mExifInfo.gps_longitude[1].den = 1;
+ mExifInfo.gps_longitude[2].num = 0;
+ mExifInfo.gps_longitude[2].den = 1;
+
+ mExifInfo.gps_altitude.num = (uint32_t)labs(m_gps_altitude);
+ mExifInfo.gps_altitude.den = 100;
+
+ struct tm tm_data;
+ gmtime_r(&m_gps_timestamp, &tm_data);
+ mExifInfo.gps_timestamp[0].num = tm_data.tm_hour;
+ mExifInfo.gps_timestamp[0].den = 1;
+ mExifInfo.gps_timestamp[1].num = tm_data.tm_min;
+ mExifInfo.gps_timestamp[1].den = 1;
+ mExifInfo.gps_timestamp[2].num = tm_data.tm_sec;
+ mExifInfo.gps_timestamp[2].den = 1;
+ snprintf((char*)mExifInfo.gps_datestamp, sizeof(mExifInfo.gps_datestamp),
+ "%04d:%02d:%02d", tm_data.tm_year + 1900, tm_data.tm_mon + 1, tm_data.tm_mday);
+
+ mExifInfo.enableGps = true;
+ } else {
+ mExifInfo.enableGps = false;
+ }
+
+ //2 1th IFD TIFF Tags
+ mExifInfo.widthThumb = m_jpeg_thumbnail_width;
+ mExifInfo.heightThumb = m_jpeg_thumbnail_height;
+}
+
+// ======================================================================
+// Conversions
+
+inline int SecCamera::m_frameSize(int format, int width, int height)
+{
+ int size = 0;
+
+ switch (format) {
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ size = (width * height * 3 / 2);
+ break;
+
+ case V4L2_PIX_FMT_NV12T:
+ size = ALIGN_TO_8KB(ALIGN_TO_128B(width) * ALIGN_TO_32B(height)) +
+ ALIGN_TO_8KB(ALIGN_TO_128B(width) * ALIGN_TO_32B(height / 2));
+ break;
+
+ case V4L2_PIX_FMT_YUV422P:
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ size = (width * height * 2);
+ break;
+
+ default :
+ LOGE("ERR(%s):Invalid V4L2 pixel format(%d)\n", __func__, format);
+ case V4L2_PIX_FMT_RGB565:
+ size = (width * height * BPP);
+ break;
+ }
+
+ return size;
+}
+
+status_t SecCamera::dump(int fd)
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ snprintf(buffer, 255, "dump(%d)\n", fd);
+ result.append(buffer);
+ ::write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+double SecCamera::jpeg_ratio = 0.7;
+int SecCamera::interleaveDataSize = 5242880;
+int SecCamera::jpegLineLength = 636;
+
+}; // namespace android
diff --git a/libcamera/SecCamera.h b/libcamera/SecCamera.h
new file mode 100755
index 0000000..ec0e470
--- /dev/null
+++ b/libcamera/SecCamera.h
@@ -0,0 +1,575 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+** Copyright 2010, Samsung Electronics Co. LTD
+**
+** 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_CAMERA_SEC_H
+#define ANDROID_HARDWARE_CAMERA_SEC_H
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/stat.h>
+
+#include <utils/RefBase.h>
+#include <linux/videodev2.h>
+#include <videodev2_samsung.h>
+
+#include <utils/String8.h>
+
+#include "JpegEncoder.h"
+
+namespace android {
+
+#define ENABLE_ESD_PREVIEW_CHECK
+
+#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0
+#define LOG_CAMERA LOGD
+#define LOG_CAMERA_PREVIEW LOGD
+
+#define LOG_TIME_DEFINE(n) \
+ struct timeval time_start_##n, time_stop_##n; unsigned long log_time_##n = 0;
+
+#define LOG_TIME_START(n) \
+ gettimeofday(&time_start_##n, NULL);
+
+#define LOG_TIME_END(n) \
+ gettimeofday(&time_stop_##n, NULL); log_time_##n = measure_time(&time_start_##n, &time_stop_##n);
+
+#define LOG_TIME(n) \
+ log_time_##n
+
+#else
+#define LOG_CAMERA(...)
+#define LOG_CAMERA_PREVIEW(...)
+#define LOG_TIME_DEFINE(n)
+#define LOG_TIME_START(n)
+#define LOG_TIME_END(n)
+#define LOG_TIME(n)
+#endif
+
+#define JOIN(x, y) JOIN_AGAIN(x, y)
+#define JOIN_AGAIN(x, y) x ## y
+
+#define FRONT_CAM VGA
+#define BACK_CAM S5K4ECGX
+
+#if !defined (FRONT_CAM) || !defined(BACK_CAM)
+#error "Please define the Camera module"
+#endif
+
+#define S5K4ECGX_PREVIEW_WIDTH 720
+#define S5K4ECGX_PREVIEW_HEIGHT 480
+#define S5K4ECGX_SNAPSHOT_WIDTH 2560
+#define S5K4ECGX_SNAPSHOT_HEIGHT 1920
+
+#define S5K4ECGX_POSTVIEW_WIDTH 640
+#define S5K4ECGX_POSTVIEW_WIDE_WIDTH 800
+#define S5K4ECGX_POSTVIEW_HEIGHT 480
+#define S5K4ECGX_POSTVIEW_BPP 16
+
+#define S5K4ECGX_THUMBNAIL_WIDTH 320
+#define S5K4ECGX_THUMBNAIL_HEIGHT 240
+#define S5K4ECGX_THUMBNAIL_BPP 16
+
+/* focal length of 3.43mm */
+#define S5K4ECGX_FOCAL_LENGTH 343
+
+#define VGA_PREVIEW_WIDTH 640
+#define VGA_PREVIEW_HEIGHT 480
+#define VGA_SNAPSHOT_WIDTH 640
+#define VGA_SNAPSHOT_HEIGHT 480
+
+#define VGA_THUMBNAIL_WIDTH 160
+#define VGA_THUMBNAIL_HEIGHT 120
+#define VGA_THUMBNAIL_BPP 16
+
+/* focal length of 0.9mm */
+#define VGA_FOCAL_LENGTH 90
+
+#define MAX_BACK_CAMERA_PREVIEW_WIDTH JOIN(BACK_CAM,_PREVIEW_WIDTH)
+#define MAX_BACK_CAMERA_PREVIEW_HEIGHT JOIN(BACK_CAM,_PREVIEW_HEIGHT)
+#define MAX_BACK_CAMERA_SNAPSHOT_WIDTH JOIN(BACK_CAM,_SNAPSHOT_WIDTH)
+#define MAX_BACK_CAMERA_SNAPSHOT_HEIGHT JOIN(BACK_CAM,_SNAPSHOT_HEIGHT)
+#define BACK_CAMERA_POSTVIEW_WIDTH JOIN(BACK_CAM,_POSTVIEW_WIDTH)
+#define BACK_CAMERA_POSTVIEW_WIDE_WIDTH JOIN(BACK_CAM,_POSTVIEW_WIDE_WIDTH)
+#define BACK_CAMERA_POSTVIEW_HEIGHT JOIN(BACK_CAM,_POSTVIEW_HEIGHT)
+#define BACK_CAMERA_POSTVIEW_BPP JOIN(BACK_CAM,_POSTVIEW_BPP)
+#define BACK_CAMERA_THUMBNAIL_WIDTH JOIN(BACK_CAM,_THUMBNAIL_WIDTH)
+#define BACK_CAMERA_THUMBNAIL_HEIGHT JOIN(BACK_CAM,_THUMBNAIL_HEIGHT)
+#define BACK_CAMERA_THUMBNAIL_BPP JOIN(BACK_CAM,_THUMBNAIL_BPP)
+
+#define BACK_CAMERA_FOCAL_LENGTH JOIN(BACK_CAM,_FOCAL_LENGTH)
+
+#define MAX_FRONT_CAMERA_PREVIEW_WIDTH JOIN(FRONT_CAM,_PREVIEW_WIDTH)
+#define MAX_FRONT_CAMERA_PREVIEW_HEIGHT JOIN(FRONT_CAM,_PREVIEW_HEIGHT)
+#define MAX_FRONT_CAMERA_SNAPSHOT_WIDTH JOIN(FRONT_CAM,_SNAPSHOT_WIDTH)
+#define MAX_FRONT_CAMERA_SNAPSHOT_HEIGHT JOIN(FRONT_CAM,_SNAPSHOT_HEIGHT)
+
+#define FRONT_CAMERA_THUMBNAIL_WIDTH JOIN(FRONT_CAM,_THUMBNAIL_WIDTH)
+#define FRONT_CAMERA_THUMBNAIL_HEIGHT JOIN(FRONT_CAM,_THUMBNAIL_HEIGHT)
+#define FRONT_CAMERA_THUMBNAIL_BPP JOIN(FRONT_CAM,_THUMBNAIL_BPP)
+#define FRONT_CAMERA_FOCAL_LENGTH JOIN(FRONT_CAM,_FOCAL_LENGTH)
+
+#define DEFAULT_JPEG_THUMBNAIL_WIDTH 256
+#define DEFAULT_JPEG_THUMBNAIL_HEIGHT 192
+
+#define CAMERA_DEV_NAME "/dev/video0"
+#define CAMERA_DEV_NAME2 "/dev/video2"
+
+#define CAMERA_DEV_NAME_TEMP "/data/videotmp_000"
+#define CAMERA_DEV_NAME2_TEMP "/data/videotemp_002"
+
+
+#define BPP 2
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#define MAX_BUFFERS 9 // 11
+
+#define FIRST_AF_SEARCH_COUNT 80
+#define SECOND_AF_SEARCH_COUNT 80
+#define AF_PROGRESS 0x01
+#define AF_SUCCESS 0x02
+#define AF_DELAY 50000
+
+/*
+ * V 4 L 2 F I M C E X T E N S I O N S
+ *
+ */
+#define V4L2_CID_ROTATION (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_PADDR_Y (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_PADDR_CB (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_PADDR_CR (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PADDR_CBCR (V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_STREAM_PAUSE (V4L2_CID_PRIVATE_BASE + 53)
+
+#define V4L2_CID_CAM_JPEG_MAIN_SIZE (V4L2_CID_PRIVATE_BASE + 32)
+#define V4L2_CID_CAM_JPEG_MAIN_OFFSET (V4L2_CID_PRIVATE_BASE + 33)
+#define V4L2_CID_CAM_JPEG_THUMB_SIZE (V4L2_CID_PRIVATE_BASE + 34)
+#define V4L2_CID_CAM_JPEG_THUMB_OFFSET (V4L2_CID_PRIVATE_BASE + 35)
+#define V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET (V4L2_CID_PRIVATE_BASE + 36)
+#define V4L2_CID_CAM_JPEG_QUALITY (V4L2_CID_PRIVATE_BASE + 37)
+
+#define TPATTERN_COLORBAR 1
+#define TPATTERN_HORIZONTAL 2
+#define TPATTERN_VERTICAL 3
+
+#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U')
+
+/* FOURCC for FIMC specific */
+#define V4L2_PIX_FMT_VYUY v4l2_fourcc('V', 'Y', 'U', 'Y')
+#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6')
+#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1')
+#define V4L2_PIX_FMT_NV12T v4l2_fourcc('T', 'V', '1', '2')
+/*
+ * U S E R D E F I N E D T Y P E S
+ *
+ */
+
+struct fimc_buffer {
+ void *start;
+ size_t length;
+};
+
+struct yuv_fmt_list {
+ const char *name;
+ const char *desc;
+ unsigned int fmt;
+ int depth;
+ int planes;
+};
+
+//s1 [Apply factory standard]
+struct camsensor_date_info {
+ unsigned int year;
+ unsigned int month;
+ unsigned int date;
+};
+
+class SecCamera : public virtual RefBase {
+public:
+
+ enum CAMERA_ID {
+ CAMERA_ID_BACK = 0,
+ CAMERA_ID_FRONT = 1,
+ };
+
+ enum JPEG_QUALITY {
+ JPEG_QUALITY_ECONOMY = 0,
+ JPEG_QUALITY_NORMAL = 50,
+ JPEG_QUALITY_SUPERFINE = 100,
+ JPEG_QUALITY_MAX,
+ };
+
+ enum OBJECT_TRACKING {
+ OBJECT_TRACKING_OFF,
+ OBJECT_TRACKING_ON,
+ OBJECT_TRACKING_MAX,
+ };
+
+ /*VT call*/
+ enum VT_MODE {
+ VT_MODE_OFF,
+ VT_MODE_ON,
+ VT_MODE_MAX,
+ };
+
+ /*Camera sensor mode - Camcorder fix fps*/
+ enum SENSOR_MODE {
+ SENSOR_MODE_CAMERA,
+ SENSOR_MODE_MOVIE,
+ };
+
+ /*Camera Shot mode*/
+ enum SHOT_MODE {
+ SHOT_MODE_SINGLE = 0,
+ SHOT_MODE_CONTINUOUS = 1,
+ SHOT_MODE_PANORAMA = 2,
+ SHOT_MODE_SMILE = 3,
+ SHOT_MODE_SELF = 6,
+ };
+
+ enum CHK_DATALINE {
+ CHK_DATALINE_OFF,
+ CHK_DATALINE_ON,
+ CHK_DATALINE_MAX,
+ };
+
+ int m_touch_af_start_stop;
+
+ struct gps_info_latiude {
+ unsigned int north_south;
+ unsigned int dgree;
+ unsigned int minute;
+ unsigned int second;
+ } gpsInfoLatitude;
+ struct gps_info_longitude {
+ unsigned int east_west;
+ unsigned int dgree;
+ unsigned int minute;
+ unsigned int second;
+ } gpsInfoLongitude;
+ struct gps_info_altitude {
+ unsigned int plus_minus;
+ unsigned int dgree;
+ unsigned int minute;
+ unsigned int second;
+ } gpsInfoAltitude;
+
+ SecCamera();
+ virtual ~SecCamera();
+
+ static SecCamera* createInstance(void)
+ {
+ static SecCamera singleton;
+ return &singleton;
+ }
+ status_t dump(int fd);
+
+ int getCameraId(void);
+
+ int startPreview(void);
+ int stopPreview(void);
+
+ int startRecord(void);
+ int stopRecord(void);
+ int getRecordFrame(void);
+ int releaseRecordFrame(int index);
+ unsigned int getRecPhyAddrY(int);
+ unsigned int getRecPhyAddrC(int);
+
+ int getPreview(void);
+ int setPreviewSize(int width, int height, int pixel_format);
+ int getPreviewSize(int *width, int *height, int *frame_size);
+ int getPreviewMaxSize(int *width, int *height);
+ int getPreviewPixelFormat(void);
+ int setPreviewImage(int index, unsigned char *buffer, int size);
+
+ int setSnapshotSize(int width, int height);
+ int getSnapshotSize(int *width, int *height, int *frame_size);
+ int getSnapshotMaxSize(int *width, int *height);
+ int setSnapshotPixelFormat(int pixel_format);
+ int getSnapshotPixelFormat(void);
+
+ unsigned char* getJpeg(unsigned char *snapshot_data, int snapshot_size, int *size);
+ unsigned char* yuv2Jpeg(unsigned char *raw_data, int raw_size,
+ int *jpeg_size,
+ int width, int height, int pixel_format);
+
+ int setJpegThumbnailSize(int width, int height);
+ int getJpegThumbnailSize(int *width, int *height);
+
+ int setAutofocus(void);
+ int zoomIn(void);
+ int zoomOut(void);
+
+ int SetRotate(int angle);
+ int getRotate(void);
+
+ int setVerticalMirror(void);
+ int setHorizontalMirror(void);
+
+ int setWhiteBalance(int white_balance);
+ int getWhiteBalance(void);
+
+ int setBrightness(int brightness);
+ int getBrightness(void);
+
+ int setImageEffect(int image_effect);
+ int getImageEffect(void);
+
+ int setSceneMode(int scene_mode);
+ int getSceneMode(void);
+
+ int setFlashMode(int flash_mode);
+ int getFlashMode(void);
+
+ int setMetering(int metering_value);
+ int getMetering(void);
+
+ int setISO(int iso_value);
+ int getISO(void);
+
+ int setContrast(int contrast_value);
+ int getContrast(void);
+
+ int setSaturation(int saturation_value);
+ int getSaturation(void);
+
+ int setSharpness(int sharpness_value);
+ int getSharpness(void);
+
+ int setWDR(int wdr_value);
+ int getWDR(void);
+
+ int setAntiShake(int anti_shake);
+ int getAntiShake(void);
+
+ int setJpegQuality(int jpeg_qality);
+ int getJpegQuality(void);
+
+ int setZoom(int zoom_level);
+ int getZoom(void);
+
+ int setObjectTracking(int object_tracking);
+ int getObjectTracking(void);
+ int getObjectTrackingStatus(void);
+
+ int setSmartAuto(int smart_auto);
+ int getSmartAuto(void);
+ int getAutosceneStatus(void);
+
+ int setBeautyShot(int beauty_shot);
+ int getBeautyShot(void);
+
+ int setVintageMode(int vintage_mode);
+ int getVintageMode(void);
+
+ int setFocusMode(int focus_mode);
+ int getFocusMode(void);
+
+ int setFaceDetect(int face_detect);
+ int getFaceDetect(void);
+
+ int setGPSLatitude(const char *gps_latitude);
+ int setGPSLongitude(const char *gps_longitude);
+ int setGPSAltitude(const char *gps_altitude);
+ int setGPSTimeStamp(const char *gps_timestamp);
+ int setGPSProcessingMethod(const char *gps_timestamp);
+ int cancelAutofocus(void);
+ int setFaceDetectLockUnlock(int facedetect_lockunlock);
+ int setObjectPosition(int x, int y);
+ int setObjectTrackingStartStop(int start_stop);
+ int setTouchAFStartStop(int start_stop);
+ int setCAFStatus(int on_off);
+ int getAutoFocusResult(void);
+ int setAntiBanding(int anti_banding);
+ int getPostview(void);
+ int setRecordingSize(int width, int height);
+ int setGamma(int gamma);
+ int setSlowAE(int slow_ae);
+ int setExifOrientationInfo(int orientationInfo);
+ int setBatchReflection(void);
+ int setSnapshotCmd(void);
+ int endSnapshot(void);
+ int setCameraSensorReset(void);
+ int setSensorMode(int sensor_mode); /* Camcorder fix fps */
+ int setShotMode(int shot_mode); /* Shot mode */
+ /*VT call*/
+ int setVTmode(int vtmode);
+ int getVTmode(void);
+ int setBlur(int blur_level);
+ int getBlur(void);
+ int setDataLineCheck(int chk_dataline);
+ int getDataLineCheck(void);
+ int setDataLineCheckStop(void);
+ int setDefultIMEI(int imei);
+ int getDefultIMEI(void);
+ const __u8* getCameraSensorName(void);
+ int previewPoll(bool preview);
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+ int getCameraSensorESDStatus(void);
+#endif // ENABLE_ESD_PREVIEW_CHECK
+
+ int setFrameRate(int frame_rate);
+ unsigned char* getJpeg(int*, unsigned int*);
+ int getSnapshotAndJpeg(unsigned char *yuv_buf, unsigned char *jpeg_buf,
+ unsigned int *output_size);
+ int getExif(unsigned char *pExifDst, unsigned char *pThumbSrc);
+
+ void getPostViewConfig(int*, int*, int*);
+ void getThumbnailConfig(int *width, int *height, int *size);
+
+ int getPostViewOffset(void);
+ int getCameraFd(void);
+ int getJpegFd(void);
+ void SetJpgAddr(unsigned char *addr);
+ unsigned int getPhyAddrY(int);
+ unsigned int getPhyAddrC(int);
+ void pausePreview();
+ int initCamera(int index);
+ void DeinitCamera();
+ static void setJpegRatio(double ratio)
+ {
+ if((ratio < 0) || (ratio > 1))
+ return;
+
+ jpeg_ratio = ratio;
+ }
+
+ static double getJpegRatio()
+ {
+ return jpeg_ratio;
+ }
+
+ static void setInterleaveDataSize(int x)
+ {
+ interleaveDataSize = x;
+ }
+
+ static int getInterleaveDataSize()
+ {
+ return interleaveDataSize;
+ }
+
+ static void setJpegLineLength(int x)
+ {
+ jpegLineLength = x;
+ }
+
+ static int getJpegLineLength()
+ {
+ return jpegLineLength;
+ }
+
+
+private:
+ v4l2_streamparm m_streamparm;
+ struct sec_cam_parm *m_params;
+ int m_flag_init;
+
+ int m_camera_id;
+
+ int m_cam_fd;
+
+ int m_cam_fd2;
+ struct pollfd m_events_c2;
+ int m_flag_record_start;
+
+ int m_preview_v4lformat;
+ int m_preview_width;
+ int m_preview_height;
+ int m_preview_max_width;
+ int m_preview_max_height;
+
+ int m_snapshot_v4lformat;
+ int m_snapshot_width;
+ int m_snapshot_height;
+ int m_snapshot_max_width;
+ int m_snapshot_max_height;
+
+ int m_angle;
+ int m_anti_banding;
+ int m_wdr;
+ int m_anti_shake;
+ int m_zoom_level;
+ int m_object_tracking;
+ int m_smart_auto;
+ int m_beauty_shot;
+ int m_vintage_mode;
+ int m_face_detect;
+ int m_object_tracking_start_stop;
+ int m_recording_width;
+ int m_recording_height;
+ bool m_gps_enabled;
+ long m_gps_latitude; /* degrees * 1e7 */
+ long m_gps_longitude; /* degrees * 1e7 */
+ long m_gps_altitude; /* metres * 100 */
+ long m_gps_timestamp;
+ int m_vtmode;
+ int m_sensor_mode; /*Camcorder fix fps */
+ int m_shot_mode; /* Shot mode */
+ int m_exif_orientation;
+ int m_blur_level;
+ int m_chk_dataline;
+ int m_video_gamma;
+ int m_slow_ae;
+ int m_caf_on_off;
+ int m_default_imei;
+ int m_camera_af_flag;
+
+ int m_flag_camera_start;
+
+ int m_jpeg_fd;
+ int m_jpeg_thumbnail_width;
+ int m_jpeg_thumbnail_height;
+ int m_jpeg_quality;
+
+ int m_postview_offset;
+
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+ int m_esd_check_count;
+#endif // ENABLE_ESD_PREVIEW_CHECK
+
+ exif_attribute_t mExifInfo;
+
+ struct fimc_buffer m_capture_buf;
+ struct pollfd m_events_c;
+
+ inline int m_frameSize(int format, int width, int height);
+
+ void setExifChangedAttribute();
+ void setExifFixedAttribute();
+ void resetCamera();
+
+ static double jpeg_ratio;
+ static int interleaveDataSize;
+ static int jpegLineLength;
+};
+
+extern unsigned long measure_time(struct timeval *start, struct timeval *stop);
+
+}; // namespace android
+
+#endif // ANDROID_HARDWARE_CAMERA_SEC_H
diff --git a/libcamera/SecCameraHWInterface.cpp b/libcamera/SecCameraHWInterface.cpp
new file mode 100755
index 0000000..ca82669
--- /dev/null
+++ b/libcamera/SecCameraHWInterface.cpp
@@ -0,0 +1,2717 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+** Copyright 2010, Samsung Electronics Co. LTD
+**
+** 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_TAG "CameraHardwareSec"
+#include <utils/Log.h>
+
+#include "SecCameraHWInterface.h"
+#include <utils/threads.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <camera/Camera.h>
+#include <media/stagefright/MetadataBufferType.h>
+
+#define VIDEO_COMMENT_MARKER_H 0xFFBE
+#define VIDEO_COMMENT_MARKER_L 0xFFBF
+#define VIDEO_COMMENT_MARKER_LENGTH 4
+#define JPEG_EOI_MARKER 0xFFD9
+#define HIBYTE(x) (((x) >> 8) & 0xFF)
+#define LOBYTE(x) ((x) & 0xFF)
+
+#define BACK_CAMERA_AUTO_FOCUS_DISTANCES_STR "0.10,1.20,Infinity"
+#define BACK_CAMERA_MACRO_FOCUS_DISTANCES_STR "0.10,0.20,Infinity"
+#define BACK_CAMERA_INFINITY_FOCUS_DISTANCES_STR "0.10,1.20,Infinity"
+#define FRONT_CAMERA_FOCUS_DISTANCES_STR "0.20,0.25,Infinity"
+
+// FIXME:
+// -- The actual preview color is set to YV12. The preview frames
+// returned via preview callback must be generated by color
+// conversion if the requested preview color format for the
+// preview frames is _not_ YV12. The reason that YV12 is used
+// for actual preview is because that is the only color format
+// supported by gralloc. Matching the preview cor format with
+// gralloc color format improves performance since no color
+// conversion is needed for preview.
+//
+// -- we only support two preview color formats that client
+// applications can set: NV21 and YUV420/YV12.
+
+namespace android {
+
+struct addrs {
+ uint32_t type; // make sure that this is 4 byte.
+ unsigned int addr_y;
+ unsigned int addr_cbcr;
+ unsigned int buf_index;
+ unsigned int reserved;
+};
+
+struct addrs_cap {
+ unsigned int addr_y;
+ unsigned int width;
+ unsigned int height;
+};
+
+static const int INITIAL_SKIP_FRAME = 3;
+static const int EFFECT_SKIP_FRAME = 1;
+
+gralloc_module_t const* CameraHardwareSec::mGrallocHal;
+
+CameraHardwareSec::CameraHardwareSec(int cameraId, camera_device_t *dev)
+ :
+ mCaptureInProgress(false),
+ mParameters(),
+ mCameraSensorName(NULL),
+ mSkipFrame(0),
+ mNotifyCb(0),
+ mDataCb(0),
+ mDataCbTimestamp(0),
+ mCallbackCookie(0),
+ mMsgEnabled(0),
+ mRecordRunning(false),
+ mPostViewWidth(0),
+ mPostViewHeight(0),
+ mPostViewSize(0),
+ mHalDevice(dev)
+{
+ LOGV("%s :", __func__);
+ int ret = 0;
+
+ mPreviewWindow = NULL;
+ mSecCamera = SecCamera::createInstance();
+
+ mRawHeap = NULL;
+ mPreviewHeap = NULL;
+ mRecordHeap = NULL;
+
+ if (!mGrallocHal) {
+ ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&mGrallocHal);
+ if (ret)
+ LOGE("ERR(%s):Fail on loading gralloc HAL", __func__);
+ }
+
+ ret = mSecCamera->initCamera(cameraId);
+ if (ret < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera init", __func__);
+ }
+
+ mSecCamera->getPostViewConfig(&mPostViewWidth, &mPostViewHeight, &mPostViewSize);
+ LOGV("mPostViewWidth = %d mPostViewHeight = %d mPostViewSize = %d",
+ mPostViewWidth,mPostViewHeight,mPostViewSize);
+
+ initDefaultParameters(cameraId);
+
+ mExitAutoFocusThread = false;
+ mExitPreviewThread = false;
+ /* whether the PreviewThread is active in preview or stopped. we
+ * create the thread but it is initially in stopped state.
+ */
+ mPreviewRunning = false;
+ mPreviewStartDeferred = false;
+ mPreviewThread = new PreviewThread(this);
+ mAutoFocusThread = new AutoFocusThread(this);
+ mPictureThread = new PictureThread(this);
+}
+
+int CameraHardwareSec::getCameraId() const
+{
+ return mSecCamera->getCameraId();
+}
+
+void CameraHardwareSec::initDefaultParameters(int cameraId)
+{
+ if (mSecCamera == NULL) {
+ LOGE("ERR(%s):mSecCamera object is NULL", __func__);
+ return;
+ }
+
+ CameraParameters p;
+ CameraParameters ip;
+
+ mCameraSensorName = mSecCamera->getCameraSensorName();
+ LOGV("CameraSensorName: %s", mCameraSensorName);
+
+ int preview_max_width = 0;
+ int preview_max_height = 0;
+ int snapshot_max_width = 0;
+ int snapshot_max_height = 0;
+
+ if (cameraId == SecCamera::CAMERA_ID_BACK) {
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
+ "720x480,640x480,352x288,176x144");
+ p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
+ "2560x1920,2048x1536,1600x1200,1280x960,640x480");
+ } else {
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
+ "640x480,320x240,176x144");
+ p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
+ "640x480");
+ }
+
+ p.getSupportedPreviewSizes(mSupportedPreviewSizes);
+
+ // If these fail, then we are using an invalid cameraId and we'll leave the
+ // sizes at zero to catch the error.
+ if (mSecCamera->getPreviewMaxSize(&preview_max_width,
+ &preview_max_height) < 0)
+ LOGE("getPreviewMaxSize fail (%d / %d) \n",
+ preview_max_width, preview_max_height);
+ if (mSecCamera->getSnapshotMaxSize(&snapshot_max_width,
+ &snapshot_max_height) < 0)
+ LOGE("getSnapshotMaxSize fail (%d / %d) \n",
+ snapshot_max_width, snapshot_max_height);
+ String8 previewColorString;
+ previewColorString = CameraParameters::PIXEL_FORMAT_YUV420SP;
+ previewColorString.append(",");
+ previewColorString.append(CameraParameters::PIXEL_FORMAT_YUV420P);
+ p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP);
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, previewColorString.string());
+ p.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT, CameraParameters::PIXEL_FORMAT_YUV420P);
+ p.setPreviewSize(preview_max_width, preview_max_height);
+
+ p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
+ p.setPictureSize(snapshot_max_width, snapshot_max_height);
+ p.set(CameraParameters::KEY_JPEG_QUALITY, "100"); // maximum quality
+ p.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
+ CameraParameters::PIXEL_FORMAT_JPEG);
+
+ String8 parameterString;
+
+ if (cameraId == SecCamera::CAMERA_ID_BACK) {
+ parameterString = CameraParameters::FOCUS_MODE_AUTO;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::FOCUS_MODE_INFINITY);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::FOCUS_MODE_MACRO);
+ p.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
+ parameterString.string());
+ p.set(CameraParameters::KEY_FOCUS_MODE,
+ CameraParameters::FOCUS_MODE_AUTO);
+ p.set(CameraParameters::KEY_FOCUS_DISTANCES,
+ BACK_CAMERA_AUTO_FOCUS_DISTANCES_STR);
+ p.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES,
+ "320x240,0x0");
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, "320");
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, "240");
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, "30");
+ p.setPreviewFrameRate(30);
+ } else {
+ parameterString = CameraParameters::FOCUS_MODE_FIXED;
+ p.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
+ parameterString.string());
+ p.set(CameraParameters::KEY_FOCUS_MODE,
+ CameraParameters::FOCUS_MODE_FIXED);
+ p.set(CameraParameters::KEY_FOCUS_DISTANCES,
+ FRONT_CAMERA_FOCUS_DISTANCES_STR);
+ p.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES,
+ "160x120,0x0");
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, "160");
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, "120");
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES, "15");
+ p.setPreviewFrameRate(15);
+ }
+
+ parameterString = CameraParameters::EFFECT_NONE;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::EFFECT_MONO);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::EFFECT_NEGATIVE);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::EFFECT_SEPIA);
+ p.set(CameraParameters::KEY_SUPPORTED_EFFECTS, parameterString.string());
+
+ if (cameraId == SecCamera::CAMERA_ID_BACK) {
+ parameterString = CameraParameters::FLASH_MODE_ON;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::FLASH_MODE_OFF);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::FLASH_MODE_AUTO);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::FLASH_MODE_TORCH);
+ p.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
+ parameterString.string());
+ p.set(CameraParameters::KEY_FLASH_MODE,
+ CameraParameters::FLASH_MODE_OFF);
+
+ parameterString = CameraParameters::SCENE_MODE_AUTO;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_PORTRAIT);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_LANDSCAPE);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_NIGHT);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_BEACH);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_SNOW);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_SUNSET);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_FIREWORKS);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_SPORTS);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_PARTY);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_CANDLELIGHT);
+ p.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES,
+ parameterString.string());
+ p.set(CameraParameters::KEY_SCENE_MODE,
+ CameraParameters::SCENE_MODE_AUTO);
+
+ /* we have two ranges, 4-30fps for night mode and
+ * 15-30fps for all others
+ */
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(15000,30000)");
+ p.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "15000,30000");
+
+ p.set(CameraParameters::KEY_FOCAL_LENGTH, "3.43");
+ } else {
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(7500,30000)");
+ p.set(CameraParameters::KEY_PREVIEW_FPS_RANGE, "7500,30000");
+
+ p.set(CameraParameters::KEY_FOCAL_LENGTH, "0.9");
+ }
+
+ parameterString = CameraParameters::WHITE_BALANCE_AUTO;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::WHITE_BALANCE_INCANDESCENT);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::WHITE_BALANCE_FLUORESCENT);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::WHITE_BALANCE_DAYLIGHT);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT);
+ p.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
+ parameterString.string());
+
+ ip.set("sharpness-min", 0);
+ ip.set("sharpness-max", 4);
+ ip.set("saturation-min", 0);
+ ip.set("saturation-max", 4);
+ ip.set("contrast-min", 0);
+ ip.set("contrast-max", 4);
+
+ p.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, "100");
+
+ p.set(CameraParameters::KEY_ROTATION, 0);
+ p.set(CameraParameters::KEY_WHITE_BALANCE, CameraParameters::WHITE_BALANCE_AUTO);
+
+ p.set(CameraParameters::KEY_EFFECT, CameraParameters::EFFECT_NONE);
+
+ ip.set("sharpness", SHARPNESS_DEFAULT);
+ ip.set("contrast", CONTRAST_DEFAULT);
+ ip.set("saturation", SATURATION_DEFAULT);
+ ip.set("iso", "auto");
+ ip.set("metering", "center");
+
+ ip.set("wdr", 0);
+ ip.set("chk_dataline", 0);
+ if (cameraId == SecCamera::CAMERA_ID_FRONT) {
+ ip.set("vtmode", 0);
+ ip.set("blur", 0);
+ }
+
+ p.set(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, "51.2");
+ p.set(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, "39.4");
+
+ p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, "0");
+ p.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION, "4");
+ p.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, "-4");
+ p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, "0.5");
+
+ mParameters = p;
+ mInternalParameters = ip;
+
+ /* make sure mSecCamera has all the settings we do. applications
+ * aren't required to call setParameters themselves (only if they
+ * want to change something.
+ */
+ setParameters(p);
+ mSecCamera->setISO(ISO_AUTO);
+ mSecCamera->setMetering(METERING_CENTER);
+ mSecCamera->setContrast(CONTRAST_DEFAULT);
+ mSecCamera->setSharpness(SHARPNESS_DEFAULT);
+ mSecCamera->setSaturation(SATURATION_DEFAULT);
+ if (cameraId == SecCamera::CAMERA_ID_BACK)
+ mSecCamera->setFrameRate(30);
+ else
+ mSecCamera->setFrameRate(15);
+}
+
+CameraHardwareSec::~CameraHardwareSec()
+{
+ LOGV("%s", __func__);
+ mSecCamera->DeinitCamera();
+}
+
+status_t CameraHardwareSec::setPreviewWindow(preview_stream_ops *w)
+{
+ int min_bufs;
+
+ mPreviewWindow = w;
+ LOGV("%s: mPreviewWindow %p", __func__, mPreviewWindow);
+
+ if (!w) {
+ LOGE("preview window is NULL!");
+ return OK;
+ }
+
+ mPreviewLock.lock();
+
+ if (mPreviewRunning && !mPreviewStartDeferred) {
+ LOGI("stop preview (window change)");
+ stopPreviewInternal();
+ }
+
+ if (w->get_min_undequeued_buffer_count(w, &min_bufs)) {
+ LOGE("%s: could not retrieve min undequeued buffer count", __func__);
+ return INVALID_OPERATION;
+ }
+
+ if (min_bufs >= kBufferCount) {
+ LOGE("%s: min undequeued buffer count %d is too high (expecting at most %d)", __func__,
+ min_bufs, kBufferCount - 1);
+ }
+
+ LOGV("%s: setting buffer count to %d", __func__, kBufferCount);
+ if (w->set_buffer_count(w, kBufferCount)) {
+ LOGE("%s: could not set buffer count", __func__);
+ return INVALID_OPERATION;
+ }
+
+ int preview_width;
+ int preview_height;
+ mParameters.getPreviewSize(&preview_width, &preview_height);
+ int hal_pixel_format = HAL_PIXEL_FORMAT_YV12;
+
+ const char *str_preview_format = mParameters.getPreviewFormat();
+ LOGV("%s: preview format %s", __func__, str_preview_format);
+
+ if (w->set_usage(w, GRALLOC_USAGE_SW_WRITE_OFTEN)) {
+ LOGE("%s: could not set usage on gralloc buffer", __func__);
+ return INVALID_OPERATION;
+ }
+
+ if (w->set_buffers_geometry(w,
+ preview_width, preview_height,
+ hal_pixel_format)) {
+ LOGE("%s: could not set buffers geometry to %s",
+ __func__, str_preview_format);
+ return INVALID_OPERATION;
+ }
+
+ if (mPreviewRunning && mPreviewStartDeferred) {
+ LOGV("start/resume preview");
+ status_t ret = startPreviewInternal();
+ if (ret == OK) {
+ mPreviewStartDeferred = false;
+ mPreviewCondition.signal();
+ }
+ }
+ mPreviewLock.unlock();
+
+ return OK;
+}
+
+void CameraHardwareSec::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)
+{
+ mNotifyCb = notify_cb;
+ mDataCb = data_cb;
+ mDataCbTimestamp = data_cb_timestamp;
+ mGetMemoryCb = get_memory;
+ mCallbackCookie = user;
+}
+
+void CameraHardwareSec::enableMsgType(int32_t msgType)
+{
+ LOGV("%s : msgType = 0x%x, mMsgEnabled before = 0x%x",
+ __func__, msgType, mMsgEnabled);
+ mMsgEnabled |= msgType;
+
+ LOGV("%s : mMsgEnabled = 0x%x", __func__, mMsgEnabled);
+}
+
+void CameraHardwareSec::disableMsgType(int32_t msgType)
+{
+ LOGV("%s : msgType = 0x%x, mMsgEnabled before = 0x%x",
+ __func__, msgType, mMsgEnabled);
+ mMsgEnabled &= ~msgType;
+ LOGV("%s : mMsgEnabled = 0x%x", __func__, mMsgEnabled);
+}
+
+bool CameraHardwareSec::msgTypeEnabled(int32_t msgType)
+{
+ return (mMsgEnabled & msgType);
+}
+
+// ---------------------------------------------------------------------------
+void CameraHardwareSec::setSkipFrame(int frame)
+{
+ Mutex::Autolock lock(mSkipFrameLock);
+ if (frame < mSkipFrame)
+ return;
+
+ mSkipFrame = frame;
+}
+
+int CameraHardwareSec::previewThreadWrapper()
+{
+ LOGI("%s: starting", __func__);
+ while (1) {
+ mPreviewLock.lock();
+ while (!mPreviewRunning) {
+ LOGI("%s: calling mSecCamera->stopPreview() and waiting", __func__);
+ mSecCamera->stopPreview();
+ /* signal that we're stopping */
+ mPreviewStoppedCondition.signal();
+ mPreviewCondition.wait(mPreviewLock);
+ LOGI("%s: return from wait", __func__);
+ }
+ mPreviewLock.unlock();
+
+ if (mExitPreviewThread) {
+ LOGI("%s: exiting", __func__);
+ mSecCamera->stopPreview();
+ return 0;
+ }
+ previewThread();
+ }
+}
+
+int CameraHardwareSec::previewThread()
+{
+ int index;
+ nsecs_t timestamp;
+ unsigned int phyYAddr;
+ unsigned int phyCAddr;
+ struct addrs *addrs;
+
+ index = mSecCamera->getPreview();
+ if (index < 0) {
+ LOGE("ERR(%s):Fail on SecCamera->getPreview()", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+// LOGV("%s: index %d", __func__, index);
+
+ mSkipFrameLock.lock();
+ if (mSkipFrame > 0) {
+ mSkipFrame--;
+ mSkipFrameLock.unlock();
+ LOGV("%s: index %d skipping frame", __func__, index);
+ return NO_ERROR;
+ }
+ mSkipFrameLock.unlock();
+
+ timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+
+ phyYAddr = mSecCamera->getPhyAddrY(index);
+ phyCAddr = mSecCamera->getPhyAddrC(index);
+
+ if (phyYAddr == 0xffffffff || phyCAddr == 0xffffffff) {
+ LOGE("ERR(%s):Fail on SecCamera getPhyAddr Y addr = %0x C addr = %0x",
+ __func__, phyYAddr, phyCAddr);
+ return UNKNOWN_ERROR;
+ }
+
+ int width, height, frame_size, offset;
+
+ mSecCamera->getPreviewSize(&width, &height, &frame_size);
+
+ offset = frame_size * index;
+
+ if (mPreviewWindow && mGrallocHal) {
+ buffer_handle_t *buf_handle;
+ int stride;
+ if (0 != mPreviewWindow->dequeue_buffer(mPreviewWindow, &buf_handle, &stride)) {
+ LOGE("Could not dequeue gralloc buffer!\n");
+ goto callbacks;
+ }
+
+ void *vaddr;
+ if (!mGrallocHal->lock(mGrallocHal,
+ *buf_handle,
+ GRALLOC_USAGE_SW_WRITE_OFTEN,
+ 0, 0, width, height, &vaddr)) {
+ char *frame = ((char *)mPreviewHeap->data) + offset;
+
+ // the code below assumes YUV, not RGB
+ {
+ int h;
+ char *src = frame;
+ char *ptr = (char *)vaddr;
+
+ // Copy the Y plane, while observing the stride
+ for (h = 0; h < height; h++) {
+ memcpy(ptr, src, width);
+ ptr += stride;
+ src += width;
+ }
+
+ {
+ // U
+ char *v = ptr;
+ ptr += stride * height / 4;
+ for (h = 0; h < height / 2; h++) {
+ memcpy(ptr, src, width / 2);
+ ptr += stride / 2;
+ src += width / 2;
+ }
+ // V
+ ptr = v;
+ for (h = 0; h < height / 2; h++) {
+ memcpy(ptr, src, width / 2);
+ ptr += stride / 2;
+ src += width / 2;
+ }
+ }
+ }
+
+ mGrallocHal->unlock(mGrallocHal, *buf_handle);
+ }
+ else
+ LOGE("%s: could not obtain gralloc buffer", __func__);
+
+ if (0 != mPreviewWindow->enqueue_buffer(mPreviewWindow, buf_handle)) {
+ LOGE("Could not enqueue gralloc buffer!\n");
+ goto callbacks;
+ }
+ }
+
+callbacks:
+ // Notify the client of a new frame.
+ if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) {
+ const char * preview_format = mParameters.getPreviewFormat();
+ if (!strcmp(preview_format, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
+ // Color conversion from YUV420 to NV21
+ char *vu = ((char *)mPreviewHeap->data) + offset + width * height;
+ const int uv_size = (width * height) >> 1;
+ char saved_uv[uv_size];
+ memcpy(saved_uv, vu, uv_size);
+ char *u = saved_uv;
+ char *v = u + (uv_size >> 1);
+
+ int h = 0;
+ while (h < width * height / 4) {
+ *vu++ = *v++;
+ *vu++ = *u++;
+ ++h;
+ }
+ }
+ mDataCb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap, index, NULL, mCallbackCookie);
+ }
+
+ Mutex::Autolock lock(mRecordLock);
+ if (mRecordRunning == true) {
+ index = mSecCamera->getRecordFrame();
+ if (index < 0) {
+ LOGE("ERR(%s):Fail on SecCamera->getRecord()", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+ phyYAddr = mSecCamera->getRecPhyAddrY(index);
+ phyCAddr = mSecCamera->getRecPhyAddrC(index);
+
+ if (phyYAddr == 0xffffffff || phyCAddr == 0xffffffff) {
+ LOGE("ERR(%s):Fail on SecCamera getRectPhyAddr Y addr = %0x C addr = %0x", __func__,
+ phyYAddr, phyCAddr);
+ return UNKNOWN_ERROR;
+ }
+
+ addrs = (struct addrs *)mRecordHeap->data;
+
+ addrs[index].type = kMetadataBufferTypeCameraSource;
+ addrs[index].addr_y = phyYAddr;
+ addrs[index].addr_cbcr = phyCAddr;
+ addrs[index].buf_index = index;
+
+ // Notify the client of a new frame.
+ if (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME) {
+ mDataCbTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME,
+ mRecordHeap, index, mCallbackCookie);
+ } else {
+ mSecCamera->releaseRecordFrame(index);
+ }
+ }
+
+ return NO_ERROR;
+}
+
+status_t CameraHardwareSec::startPreview()
+{
+ int ret = 0; //s1 [Apply factory standard]
+
+ LOGV("%s :", __func__);
+
+ if (waitCaptureCompletion() != NO_ERROR) {
+ return TIMED_OUT;
+ }
+
+ mPreviewLock.lock();
+ if (mPreviewRunning) {
+ // already running
+ LOGE("%s : preview thread already running", __func__);
+ mPreviewLock.unlock();
+ return INVALID_OPERATION;
+ }
+
+ mPreviewRunning = true;
+ mPreviewStartDeferred = false;
+
+ if (!mPreviewWindow) {
+ LOGI("%s : deferring", __func__);
+ mPreviewStartDeferred = true;
+ mPreviewLock.unlock();
+ return NO_ERROR;
+ }
+
+ ret = startPreviewInternal();
+ if (ret == OK)
+ mPreviewCondition.signal();
+
+ mPreviewLock.unlock();
+ return ret;
+}
+
+status_t CameraHardwareSec::startPreviewInternal()
+{
+ LOGV("%s", __func__);
+
+ int ret = mSecCamera->startPreview();
+ LOGV("%s : mSecCamera->startPreview() returned %d", __func__, ret);
+
+ if (ret < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->startPreview()", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+ setSkipFrame(INITIAL_SKIP_FRAME);
+
+ int width, height, frame_size;
+
+ mSecCamera->getPreviewSize(&width, &height, &frame_size);
+
+ LOGD("mPreviewHeap(fd(%d), size(%d), width(%d), height(%d))",
+ mSecCamera->getCameraFd(), frame_size, width, height);
+ if (mPreviewHeap) {
+ mPreviewHeap->release(mPreviewHeap);
+ mPreviewHeap = 0;
+ }
+
+ mPreviewHeap = mGetMemoryCb((int)mSecCamera->getCameraFd(),
+ frame_size,
+ kBufferCount,
+ 0); // no cookie
+
+ mSecCamera->getPostViewConfig(&mPostViewWidth, &mPostViewHeight, &mPostViewSize);
+ LOGV("CameraHardwareSec: mPostViewWidth = %d mPostViewHeight = %d mPostViewSize = %d",
+ mPostViewWidth,mPostViewHeight,mPostViewSize);
+
+ return NO_ERROR;
+}
+
+void CameraHardwareSec::stopPreviewInternal()
+{
+ LOGV("%s :", __func__);
+
+ /* request that the preview thread stop. */
+ if (mPreviewRunning) {
+ mPreviewRunning = false;
+ if (!mPreviewStartDeferred) {
+ mPreviewCondition.signal();
+ /* wait until preview thread is stopped */
+ mPreviewStoppedCondition.wait(mPreviewLock);
+ }
+ else
+ LOGV("%s : preview running but deferred, doing nothing", __func__);
+ } else
+ LOGI("%s : preview not running, doing nothing", __func__);
+}
+
+void CameraHardwareSec::stopPreview()
+{
+ LOGV("%s :", __func__);
+
+ /* request that the preview thread stop. */
+ mPreviewLock.lock();
+ stopPreviewInternal();
+ mPreviewLock.unlock();
+}
+
+bool CameraHardwareSec::previewEnabled()
+{
+ Mutex::Autolock lock(mPreviewLock);
+ LOGV("%s : %d", __func__, mPreviewRunning);
+ return mPreviewRunning;
+}
+
+// ---------------------------------------------------------------------------
+
+status_t CameraHardwareSec::startRecording()
+{
+ LOGV("%s :", __func__);
+
+ Mutex::Autolock lock(mRecordLock);
+
+ if (mRecordHeap) {
+ mRecordHeap->release(mRecordHeap);
+ mRecordHeap = 0;
+ }
+ mRecordHeap = mGetMemoryCb(-1, sizeof(struct addrs), kBufferCount, NULL);
+ if (!mRecordHeap) {
+ LOGE("ERR(%s): Record heap creation fail", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+ if (mRecordRunning == false) {
+ if (mSecCamera->startRecord() < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->startRecord()", __func__);
+ return UNKNOWN_ERROR;
+ }
+ mRecordRunning = true;
+ }
+ return NO_ERROR;
+}
+
+void CameraHardwareSec::stopRecording()
+{
+ LOGV("%s :", __func__);
+
+ Mutex::Autolock lock(mRecordLock);
+
+ if (mRecordRunning == true) {
+ if (mSecCamera->stopRecord() < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->stopRecord()", __func__);
+ return;
+ }
+ mRecordRunning = false;
+ }
+}
+
+bool CameraHardwareSec::recordingEnabled()
+{
+ LOGV("%s :", __func__);
+
+ return mRecordRunning;
+}
+
+void CameraHardwareSec::releaseRecordingFrame(const void *opaque)
+{
+ struct addrs *addrs = (struct addrs *)opaque;
+ mSecCamera->releaseRecordFrame(addrs->buf_index);
+}
+
+// ---------------------------------------------------------------------------
+
+int CameraHardwareSec::autoFocusThread()
+{
+ int count =0;
+ int af_status =0 ;
+
+ LOGV("%s : starting", __func__);
+
+ /* block until we're told to start. we don't want to use
+ * a restartable thread and requestExitAndWait() in cancelAutoFocus()
+ * because it would cause deadlock between our callbacks and the
+ * caller of cancelAutoFocus() which both want to grab the same lock
+ * in CameraServices layer.
+ */
+ mFocusLock.lock();
+ /* check early exit request */
+ if (mExitAutoFocusThread) {
+ mFocusLock.unlock();
+ LOGV("%s : exiting on request0", __func__);
+ return NO_ERROR;
+ }
+ mFocusCondition.wait(mFocusLock);
+ /* check early exit request */
+ if (mExitAutoFocusThread) {
+ mFocusLock.unlock();
+ LOGV("%s : exiting on request1", __func__);
+ return NO_ERROR;
+ }
+ mFocusLock.unlock();
+
+ LOGV("%s : calling setAutoFocus", __func__);
+ if (mSecCamera->setAutofocus() < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setAutofocus()", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+ af_status = mSecCamera->getAutoFocusResult();
+
+ if (af_status == 0x01) {
+ LOGV("%s : AF Success!!", __func__);
+ if (mMsgEnabled & CAMERA_MSG_FOCUS)
+ mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
+ } else if (af_status == 0x02) {
+ LOGV("%s : AF Cancelled !!", __func__);
+ if (mMsgEnabled & CAMERA_MSG_FOCUS) {
+ /* CAMERA_MSG_FOCUS only takes a bool. true for
+ * finished and false for failure. cancel is still
+ * considered a true result.
+ */
+ mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
+ }
+ } else {
+ LOGV("%s : AF Fail !!", __func__);
+ LOGV("%s : mMsgEnabled = 0x%x", __func__, mMsgEnabled);
+ if (mMsgEnabled & CAMERA_MSG_FOCUS)
+ mNotifyCb(CAMERA_MSG_FOCUS, false, 0, mCallbackCookie);
+ }
+
+ LOGV("%s : exiting with no error", __func__);
+ return NO_ERROR;
+}
+
+status_t CameraHardwareSec::autoFocus()
+{
+ LOGV("%s :", __func__);
+ /* signal autoFocusThread to run once */
+ mFocusCondition.signal();
+ return NO_ERROR;
+}
+
+/* 2009.10.14 by icarus for added interface */
+status_t CameraHardwareSec::cancelAutoFocus()
+{
+ LOGV("%s :", __func__);
+
+ // cancelAutoFocus should be allowed after preview is started. But if
+ // the preview is deferred, cancelAutoFocus will fail. Ignore it if that is
+ // the case.
+ if (mPreviewRunning && mPreviewStartDeferred) return NO_ERROR;
+
+ if (mSecCamera->cancelAutofocus() < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->cancelAutofocus()", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+ return NO_ERROR;
+}
+
+int CameraHardwareSec::save_jpeg( unsigned char *real_jpeg, int jpeg_size)
+{
+ FILE *yuv_fp = NULL;
+ char filename[100], *buffer = NULL;
+
+ /* file create/open, note to "wb" */
+ yuv_fp = fopen("/data/camera_dump.jpeg", "wb");
+ if (yuv_fp == NULL) {
+ LOGE("Save jpeg file open error");
+ return -1;
+ }
+
+ LOGV("[BestIQ] real_jpeg size ========> %d\n", jpeg_size);
+ buffer = (char *) malloc(jpeg_size);
+ if (buffer == NULL) {
+ LOGE("Save YUV] buffer alloc failed");
+ if (yuv_fp)
+ fclose(yuv_fp);
+
+ return -1;
+ }
+
+ memcpy(buffer, real_jpeg, jpeg_size);
+
+ fflush(stdout);
+
+ fwrite(buffer, 1, jpeg_size, yuv_fp);
+
+ fflush(yuv_fp);
+
+ if (yuv_fp)
+ fclose(yuv_fp);
+ if (buffer)
+ free(buffer);
+
+ return 0;
+}
+
+void CameraHardwareSec::save_postview(const char *fname, uint8_t *buf, uint32_t size)
+{
+ int nw;
+ int cnt = 0;
+ uint32_t written = 0;
+
+ LOGD("opening file [%s]\n", fname);
+ int fd = open(fname, O_RDWR | O_CREAT);
+ if (fd < 0) {
+ LOGE("failed to create file [%s]: %s", fname, strerror(errno));
+ return;
+ }
+
+ LOGD("writing %d bytes to file [%s]\n", size, fname);
+ while (written < size) {
+ nw = ::write(fd, buf + written, size - written);
+ if (nw < 0) {
+ LOGE("failed to write to file %d [%s]: %s",written,fname, strerror(errno));
+ break;
+ }
+ written += nw;
+ cnt++;
+ }
+ LOGD("done writing %d bytes to file [%s] in %d passes\n",size, fname, cnt);
+ ::close(fd);
+}
+
+bool CameraHardwareSec::scaleDownYuv422(char *srcBuf, uint32_t srcWidth, uint32_t srcHeight,
+ char *dstBuf, uint32_t dstWidth, uint32_t dstHeight)
+{
+ int32_t step_x, step_y;
+ int32_t iXsrc, iXdst;
+ int32_t x, y, src_y_start_pos, dst_pos, src_pos;
+
+ if (dstWidth % 2 != 0 || dstHeight % 2 != 0){
+ LOGE("scale_down_yuv422: invalid width, height for scaling");
+ return false;
+ }
+
+ step_x = srcWidth / dstWidth;
+ step_y = srcHeight / dstHeight;
+
+ dst_pos = 0;
+ for (uint32_t y = 0; y < dstHeight; y++) {
+ src_y_start_pos = (y * step_y * (srcWidth * 2));
+
+ for (uint32_t x = 0; x < dstWidth; x += 2) {
+ src_pos = src_y_start_pos + (x * (step_x * 2));
+
+ dstBuf[dst_pos++] = srcBuf[src_pos ];
+ dstBuf[dst_pos++] = srcBuf[src_pos + 1];
+ dstBuf[dst_pos++] = srcBuf[src_pos + 2];
+ dstBuf[dst_pos++] = srcBuf[src_pos + 3];
+ }
+ }
+
+ return true;
+}
+
+bool CameraHardwareSec::YUY2toNV21(void *srcBuf, void *dstBuf, uint32_t srcWidth, uint32_t srcHeight)
+{
+ int32_t x, y, src_y_start_pos, dst_cbcr_pos, dst_pos, src_pos;
+ unsigned char *srcBufPointer = (unsigned char *)srcBuf;
+ unsigned char *dstBufPointer = (unsigned char *)dstBuf;
+
+ dst_pos = 0;
+ dst_cbcr_pos = srcWidth*srcHeight;
+ for (uint32_t y = 0; y < srcHeight; y++) {
+ src_y_start_pos = (y * (srcWidth * 2));
+
+ for (uint32_t x = 0; x < (srcWidth * 2); x += 2) {
+ src_pos = src_y_start_pos + x;
+
+ dstBufPointer[dst_pos++] = srcBufPointer[src_pos];
+ }
+ }
+ for (uint32_t y = 0; y < srcHeight; y += 2) {
+ src_y_start_pos = (y * (srcWidth * 2));
+
+ for (uint32_t x = 0; x < (srcWidth * 2); x += 4) {
+ src_pos = src_y_start_pos + x;
+
+ dstBufPointer[dst_cbcr_pos++] = srcBufPointer[src_pos + 3];
+ dstBufPointer[dst_cbcr_pos++] = srcBufPointer[src_pos + 1];
+ }
+ }
+
+ return true;
+}
+
+int CameraHardwareSec::pictureThread()
+{
+ LOGV("%s :", __func__);
+
+ int jpeg_size = 0;
+ int ret = NO_ERROR;
+ unsigned char *jpeg_data = NULL;
+ int postview_offset = 0;
+ unsigned char *postview_data = NULL;
+
+ unsigned char *addr = NULL;
+ int mPostViewWidth, mPostViewHeight, mPostViewSize;
+ int mThumbWidth, mThumbHeight, mThumbSize;
+ int cap_width, cap_height, cap_frame_size;
+ int JpegImageSize, JpegExifSize;
+ bool isLSISensor = false;
+
+ unsigned int output_size = 0;
+
+ mSecCamera->getPostViewConfig(&mPostViewWidth, &mPostViewHeight, &mPostViewSize);
+ mSecCamera->getThumbnailConfig(&mThumbWidth, &mThumbHeight, &mThumbSize);
+ int postviewHeapSize = mPostViewSize;
+ mSecCamera->getSnapshotSize(&cap_width, &cap_height, &cap_frame_size);
+ int mJpegHeapSize;
+ if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK)
+ mJpegHeapSize = cap_frame_size * SecCamera::getJpegRatio();
+ else
+ mJpegHeapSize = cap_frame_size;
+
+ LOG_TIME_DEFINE(0)
+ LOG_TIME_START(0)
+// sp<MemoryBase> buffer = new MemoryBase(mRawHeap, 0, mPostViewSize + 8);
+
+ struct addrs_cap *addrs = (struct addrs_cap *)mRawHeap->data;
+
+ addrs[0].width = mPostViewWidth;
+ addrs[0].height = mPostViewHeight;
+ LOGV("[5B] mPostViewWidth = %d mPostViewHeight = %d\n",mPostViewWidth,mPostViewHeight);
+
+ camera_memory_t *JpegHeap = mGetMemoryCb(-1, mJpegHeapSize, 1, 0);
+ sp<MemoryHeapBase> PostviewHeap = new MemoryHeapBase(mPostViewSize);
+ sp<MemoryHeapBase> ThumbnailHeap = new MemoryHeapBase(mThumbSize);
+
+ LOG_TIME_DEFINE(1)
+ LOG_TIME_START(1)
+
+ int picture_size, picture_width, picture_height;
+ mSecCamera->getSnapshotSize(&picture_width, &picture_height, &picture_size);
+ int picture_format = mSecCamera->getSnapshotPixelFormat();
+
+ unsigned int phyAddr;
+
+ // Modified the shutter sound timing for Jpeg capture
+ if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK)
+ mSecCamera->setSnapshotCmd();
+ if (mMsgEnabled & CAMERA_MSG_SHUTTER) {
+ mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
+ }
+
+ if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK){
+ jpeg_data = mSecCamera->getJpeg(&jpeg_size, &phyAddr);
+ if (jpeg_data == NULL) {
+ LOGE("ERR(%s):Fail on SecCamera->getSnapshot()", __func__);
+ ret = UNKNOWN_ERROR;
+ goto out;
+ }
+ } else {
+ if (mSecCamera->getSnapshotAndJpeg((unsigned char*)PostviewHeap->base(),
+ (unsigned char*)JpegHeap->data, &output_size) < 0) {
+ ret = UNKNOWN_ERROR;
+ goto out;
+ }
+ LOGI("snapshotandjpeg done\n");
+ }
+
+ LOG_TIME_END(1)
+ LOG_CAMERA("getSnapshotAndJpeg interval: %lu us", LOG_TIME(1));
+
+ if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK) {
+ isLSISensor = !strncmp((const char*)mCameraSensorName, "S5K4ECGX", 8);
+ if(isLSISensor) {
+ LOGI("== Camera Sensor Detect %s - Samsung LSI SOC 5M ==\n", mCameraSensorName);
+ // LSI 5M SOC
+ if (!SplitFrame(jpeg_data, SecCamera::getInterleaveDataSize(),
+ SecCamera::getJpegLineLength(),
+ mPostViewWidth * 2, mPostViewWidth,
+ JpegHeap->data, &JpegImageSize,
+ PostviewHeap->base(), &mPostViewSize)) {
+ ret = UNKNOWN_ERROR;
+ goto out;
+ }
+ } else {
+ LOGI("== Camera Sensor Detect %s Sony SOC 5M ==\n", mCameraSensorName);
+ decodeInterleaveData(jpeg_data,
+ SecCamera::getInterleaveDataSize(),
+ mPostViewWidth, mPostViewHeight,
+ &JpegImageSize, JpegHeap->data, PostviewHeap->base());
+ }
+ } else {
+ JpegImageSize = static_cast<int>(output_size);
+ }
+ scaleDownYuv422((char *)PostviewHeap->base(), mPostViewWidth, mPostViewHeight,
+ (char *)ThumbnailHeap->base(), mThumbWidth, mThumbHeight);
+
+ memcpy(mRawHeap->data, PostviewHeap->base(), postviewHeapSize);
+
+ if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
+ mDataCb(CAMERA_MSG_RAW_IMAGE, mRawHeap, 0, NULL, mCallbackCookie);
+ } else if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE_NOTIFY) {
+ mNotifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mCallbackCookie);
+ }
+
+ if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
+ camera_memory_t *ExifHeap =
+ mGetMemoryCb(-1, EXIF_FILE_SIZE + JPG_STREAM_BUF_SIZE, 1, 0);
+ JpegExifSize = mSecCamera->getExif((unsigned char *)ExifHeap->data,
+ (unsigned char *)ThumbnailHeap->base());
+
+ LOGV("JpegExifSize=%d", JpegExifSize);
+
+ if (JpegExifSize < 0) {
+ ret = UNKNOWN_ERROR;
+ ExifHeap->release(ExifHeap);
+ goto out;
+ }
+
+ camera_memory_t *mem = mGetMemoryCb(-1, JpegImageSize + JpegExifSize, 1, 0);
+ uint8_t *ptr = (uint8_t *) mem->data;
+ memcpy(ptr, JpegHeap->data, 2); ptr += 2;
+ memcpy(ptr, ExifHeap->data, JpegExifSize); ptr += JpegExifSize;
+ memcpy(ptr, (uint8_t *) JpegHeap->data + 2, JpegImageSize - 2);
+ mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, 0, NULL, mCallbackCookie);
+ mem->release(mem);
+ ExifHeap->release(ExifHeap);
+ }
+
+ LOG_TIME_END(0)
+ LOG_CAMERA("pictureThread interval: %lu us", LOG_TIME(0));
+
+ LOGV("%s : pictureThread end", __func__);
+
+out:
+ JpegHeap->release(JpegHeap);
+ mSecCamera->endSnapshot();
+ mCaptureLock.lock();
+ mCaptureInProgress = false;
+ mCaptureCondition.broadcast();
+ mCaptureLock.unlock();
+
+ return ret;
+}
+
+status_t CameraHardwareSec::waitCaptureCompletion() {
+ // 5 seconds timeout
+ nsecs_t endTime = 5000000000LL + systemTime(SYSTEM_TIME_MONOTONIC);
+ Mutex::Autolock lock(mCaptureLock);
+ while (mCaptureInProgress) {
+ nsecs_t remainingTime = endTime - systemTime(SYSTEM_TIME_MONOTONIC);
+ if (remainingTime <= 0) {
+ LOGE("Timed out waiting picture thread.");
+ return TIMED_OUT;
+ }
+ LOGD("Waiting for picture thread to complete.");
+ mCaptureCondition.waitRelative(mCaptureLock, remainingTime);
+ }
+ return NO_ERROR;
+}
+
+status_t CameraHardwareSec::takePicture()
+{
+ LOGV("%s :", __func__);
+
+ stopPreview();
+
+ if (!mRawHeap) {
+ int rawHeapSize = mPostViewSize;
+ LOGV("mRawHeap : MemoryHeapBase(previewHeapSize(%d))", rawHeapSize);
+ mRawHeap = mGetMemoryCb(-1, rawHeapSize, 1, 0);
+ if (!mRawHeap) {
+ LOGE("ERR(%s): Raw heap creation fail", __func__);
+ }
+ }
+
+ if (waitCaptureCompletion() != NO_ERROR) {
+ return TIMED_OUT;
+ }
+
+ if (mPictureThread->run("CameraPictureThread", PRIORITY_DEFAULT) != NO_ERROR) {
+ LOGE("%s : couldn't run picture thread", __func__);
+ return INVALID_OPERATION;
+ }
+ mCaptureLock.lock();
+ mCaptureInProgress = true;
+ mCaptureLock.unlock();
+
+ return NO_ERROR;
+}
+
+status_t CameraHardwareSec::cancelPicture()
+{
+ LOGV("%s", __func__);
+
+ if (mPictureThread.get()) {
+ LOGV("%s: waiting for picture thread to exit", __func__);
+ mPictureThread->requestExitAndWait();
+ LOGV("%s: picture thread has exited", __func__);
+ }
+
+ return NO_ERROR;
+}
+
+bool CameraHardwareSec::CheckVideoStartMarker(unsigned char *pBuf)
+{
+ if (!pBuf) {
+ LOGE("CheckVideoStartMarker() => pBuf is NULL\n");
+ return false;
+ }
+
+ if (HIBYTE(VIDEO_COMMENT_MARKER_H) == * pBuf && LOBYTE(VIDEO_COMMENT_MARKER_H) == *(pBuf + 1) &&
+ HIBYTE(VIDEO_COMMENT_MARKER_L) == *(pBuf + 2) && LOBYTE(VIDEO_COMMENT_MARKER_L) == *(pBuf + 3))
+ return true;
+
+ return false;
+}
+
+bool CameraHardwareSec::CheckEOIMarker(unsigned char *pBuf)
+{
+ if (!pBuf) {
+ LOGE("CheckEOIMarker() => pBuf is NULL\n");
+ return false;
+ }
+
+ // EOI marker [FF D9]
+ if (HIBYTE(JPEG_EOI_MARKER) == *pBuf && LOBYTE(JPEG_EOI_MARKER) == *(pBuf + 1))
+ return true;
+
+ return false;
+}
+
+bool CameraHardwareSec::FindEOIMarkerInJPEG(unsigned char *pBuf, int dwBufSize, int *pnJPEGsize)
+{
+ if (NULL == pBuf || 0 >= dwBufSize) {
+ LOGE("FindEOIMarkerInJPEG() => There is no contents.");
+ return false;
+ }
+
+ unsigned char *pBufEnd = pBuf + dwBufSize;
+
+ while (pBuf < pBufEnd) {
+ if (CheckEOIMarker(pBuf++))
+ return true;
+
+ (*pnJPEGsize)++;
+ }
+
+ return false;
+}
+
+bool CameraHardwareSec::SplitFrame(unsigned char *pFrame, int dwSize,
+ int dwJPEGLineLength, int dwVideoLineLength, int dwVideoHeight,
+ void *pJPEG, int *pdwJPEGSize,
+ void *pVideo, int *pdwVideoSize)
+{
+ LOGV("===========SplitFrame Start==============");
+
+ if (NULL == pFrame || 0 >= dwSize) {
+ LOGE("There is no contents (pFrame=%p, dwSize=%d", pFrame, dwSize);
+ return false;
+ }
+
+ if (0 == dwJPEGLineLength || 0 == dwVideoLineLength) {
+ LOGE("There in no input information for decoding interleaved jpeg");
+ return false;
+ }
+
+ unsigned char *pSrc = pFrame;
+ unsigned char *pSrcEnd = pFrame + dwSize;
+
+ unsigned char *pJ = (unsigned char *)pJPEG;
+ int dwJSize = 0;
+ unsigned char *pV = (unsigned char *)pVideo;
+ int dwVSize = 0;
+
+ bool bRet = false;
+ bool isFinishJpeg = false;
+
+ while (pSrc < pSrcEnd) {
+ // Check video start marker
+ if (CheckVideoStartMarker(pSrc)) {
+ int copyLength;
+
+ if (pSrc + dwVideoLineLength <= pSrcEnd)
+ copyLength = dwVideoLineLength;
+ else
+ copyLength = pSrcEnd - pSrc - VIDEO_COMMENT_MARKER_LENGTH;
+
+ // Copy video data
+ if (pV) {
+ memcpy(pV, pSrc + VIDEO_COMMENT_MARKER_LENGTH, copyLength);
+ pV += copyLength;
+ dwVSize += copyLength;
+ }
+
+ pSrc += copyLength + VIDEO_COMMENT_MARKER_LENGTH;
+ } else {
+ // Copy pure JPEG data
+ int size = 0;
+ int dwCopyBufLen = dwJPEGLineLength <= pSrcEnd-pSrc ? dwJPEGLineLength : pSrcEnd - pSrc;
+
+ if (FindEOIMarkerInJPEG((unsigned char *)pSrc, dwCopyBufLen, &size)) {
+ isFinishJpeg = true;
+ size += 2; // to count EOF marker size
+ } else {
+ if ((dwCopyBufLen == 1) && (pJPEG < pJ)) {
+ unsigned char checkBuf[2] = { *(pJ - 1), *pSrc };
+
+ if (CheckEOIMarker(checkBuf))
+ isFinishJpeg = true;
+ }
+ size = dwCopyBufLen;
+ }
+
+ memcpy(pJ, pSrc, size);
+
+ dwJSize += size;
+
+ pJ += dwCopyBufLen;
+ pSrc += dwCopyBufLen;
+ }
+ if (isFinishJpeg)
+ break;
+ }
+
+ if (isFinishJpeg) {
+ bRet = true;
+ if(pdwJPEGSize)
+ *pdwJPEGSize = dwJSize;
+ if(pdwVideoSize)
+ *pdwVideoSize = dwVSize;
+ } else {
+ LOGE("DecodeInterleaveJPEG_WithOutDT() => Can not find EOI");
+ bRet = false;
+ if(pdwJPEGSize)
+ *pdwJPEGSize = 0;
+ if(pdwVideoSize)
+ *pdwVideoSize = 0;
+ }
+ LOGV("===========SplitFrame end==============");
+
+ return bRet;
+}
+
+int CameraHardwareSec::decodeInterleaveData(unsigned char *pInterleaveData,
+ int interleaveDataSize,
+ int yuvWidth,
+ int yuvHeight,
+ int *pJpegSize,
+ void *pJpegData,
+ void *pYuvData)
+{
+ if (pInterleaveData == NULL)
+ return false;
+
+ bool ret = true;
+ unsigned int *interleave_ptr = (unsigned int *)pInterleaveData;
+ unsigned char *jpeg_ptr = (unsigned char *)pJpegData;
+ unsigned char *yuv_ptr = (unsigned char *)pYuvData;
+ unsigned char *p;
+ int jpeg_size = 0;
+ int yuv_size = 0;
+
+ int i = 0;
+
+ LOGV("decodeInterleaveData Start~~~");
+ while (i < interleaveDataSize) {
+ if ((*interleave_ptr == 0xFFFFFFFF) || (*interleave_ptr == 0x02FFFFFF) ||
+ (*interleave_ptr == 0xFF02FFFF)) {
+ // Padding Data
+// LOGE("%d(%x) padding data\n", i, *interleave_ptr);
+ interleave_ptr++;
+ i += 4;
+ }
+ else if ((*interleave_ptr & 0xFFFF) == 0x05FF) {
+ // Start-code of YUV Data
+// LOGE("%d(%x) yuv data\n", i, *interleave_ptr);
+ p = (unsigned char *)interleave_ptr;
+ p += 2;
+ i += 2;
+
+ // Extract YUV Data
+ if (pYuvData != NULL) {
+ memcpy(yuv_ptr, p, yuvWidth * 2);
+ yuv_ptr += yuvWidth * 2;
+ yuv_size += yuvWidth * 2;
+ }
+ p += yuvWidth * 2;
+ i += yuvWidth * 2;
+
+ // Check End-code of YUV Data
+ if ((*p == 0xFF) && (*(p + 1) == 0x06)) {
+ interleave_ptr = (unsigned int *)(p + 2);
+ i += 2;
+ } else {
+ ret = false;
+ break;
+ }
+ } else {
+ // Extract JPEG Data
+// LOGE("%d(%x) jpg data, jpeg_size = %d bytes\n", i, *interleave_ptr, jpeg_size);
+ if (pJpegData != NULL) {
+ memcpy(jpeg_ptr, interleave_ptr, 4);
+ jpeg_ptr += 4;
+ jpeg_size += 4;
+ }
+ interleave_ptr++;
+ i += 4;
+ }
+ }
+ if (ret) {
+ if (pJpegData != NULL) {
+ // Remove Padding after EOI
+ for (i = 0; i < 3; i++) {
+ if (*(--jpeg_ptr) != 0xFF) {
+ break;
+ }
+ jpeg_size--;
+ }
+ *pJpegSize = jpeg_size;
+
+ }
+ // Check YUV Data Size
+ if (pYuvData != NULL) {
+ if (yuv_size != (yuvWidth * yuvHeight * 2)) {
+ ret = false;
+ }
+ }
+ }
+ LOGV("decodeInterleaveData End~~~");
+ return ret;
+}
+
+status_t CameraHardwareSec::dump(int fd) const
+{
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ const Vector<String16> args;
+
+ if (mSecCamera != 0) {
+ mSecCamera->dump(fd);
+ mParameters.dump(fd, args);
+ mInternalParameters.dump(fd, args);
+ snprintf(buffer, 255, " preview running(%s)\n", mPreviewRunning?"true": "false");
+ result.append(buffer);
+ } else {
+ result.append("No camera client yet.\n");
+ }
+ write(fd, result.string(), result.size());
+ return NO_ERROR;
+}
+
+bool CameraHardwareSec::isSupportedPreviewSize(const int width,
+ const int height) const
+{
+ unsigned int i;
+
+ for (i = 0; i < mSupportedPreviewSizes.size(); i++) {
+ if (mSupportedPreviewSizes[i].width == width &&
+ mSupportedPreviewSizes[i].height == height)
+ return true;
+ }
+
+ return false;
+}
+
+bool CameraHardwareSec::isSupportedParameter(const char * const parm,
+ const char * const supported_parm) const
+{
+ const char *pStart;
+ const char *pEnd;
+
+ if (!parm || !supported_parm)
+ return false;
+
+ pStart = supported_parm;
+
+ while (true) {
+ pEnd = strchr(pStart, ',');
+ if (!pEnd) {
+ if (!strcmp(parm, pStart))
+ return true;
+ else
+ return false;
+ }
+ if (!strncmp(parm, pStart, pEnd - pStart)) {
+ return true;
+ }
+ pStart = pEnd + 1;
+ }
+ /* NOTREACHED */
+}
+
+status_t CameraHardwareSec::setParameters(const CameraParameters& params)
+{
+ LOGV("%s :", __func__);
+
+ status_t ret = NO_ERROR;
+
+ /* if someone calls us while picture thread is running, it could screw
+ * up the sensor quite a bit so return error.
+ */
+ if (waitCaptureCompletion() != NO_ERROR) {
+ return TIMED_OUT;
+ }
+
+ // preview size
+ int new_preview_width = 0;
+ int new_preview_height = 0;
+ params.getPreviewSize(&new_preview_width, &new_preview_height);
+ const char *new_str_preview_format = params.getPreviewFormat();
+ LOGV("%s : new_preview_width x new_preview_height = %dx%d, format = %s",
+ __func__, new_preview_width, new_preview_height, new_str_preview_format);
+
+ if (strcmp(new_str_preview_format, CameraParameters::PIXEL_FORMAT_YUV420SP) &&
+ strcmp(new_str_preview_format, CameraParameters::PIXEL_FORMAT_YUV420P)) {
+ LOGE("Unsupported preview color format: %s", new_str_preview_format);
+ return BAD_VALUE;
+ }
+
+ if (0 < new_preview_width && 0 < new_preview_height &&
+ new_str_preview_format != NULL &&
+ isSupportedPreviewSize(new_preview_width, new_preview_height)) {
+ int new_preview_format = V4L2_PIX_FMT_YUV420;
+
+ int current_preview_width, current_preview_height, current_frame_size;
+ mSecCamera->getPreviewSize(&current_preview_width,
+ &current_preview_height,
+ &current_frame_size);
+ int current_pixel_format = mSecCamera->getPreviewPixelFormat();
+
+ if (current_preview_width != new_preview_width ||
+ current_preview_height != new_preview_height ||
+ current_pixel_format != new_preview_format) {
+ if (mSecCamera->setPreviewSize(new_preview_width, new_preview_height,
+ new_preview_format) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setPreviewSize(width(%d), height(%d), format(%d))",
+ __func__, new_preview_width, new_preview_height, new_preview_format);
+ ret = UNKNOWN_ERROR;
+ } else {
+ if (mPreviewWindow) {
+ if (mPreviewRunning && !mPreviewStartDeferred) {
+ LOGE("ERR(%s): preview is running, cannot change size and format!",
+ __func__);
+ ret = INVALID_OPERATION;
+ }
+
+ LOGV("%s: mPreviewWindow (%p) set_buffers_geometry", __func__, mPreviewWindow);
+ LOGV("%s: mPreviewWindow->set_buffers_geometry (%p)", __func__,
+ mPreviewWindow->set_buffers_geometry);
+ mPreviewWindow->set_buffers_geometry(mPreviewWindow,
+ new_preview_width, new_preview_height,
+ new_preview_format);
+ LOGV("%s: DONE mPreviewWindow (%p) set_buffers_geometry", __func__, mPreviewWindow);
+ }
+
+ mParameters.setPreviewSize(new_preview_width, new_preview_height);
+ mParameters.setPreviewFormat(new_str_preview_format);
+ }
+ }
+ else LOGV("%s: preview size and format has not changed", __func__);
+ } else {
+ LOGE("%s: Invalid preview size(%dx%d)",
+ __func__, new_preview_width, new_preview_height);
+
+ ret = INVALID_OPERATION;
+ }
+
+ int new_picture_width = 0;
+ int new_picture_height = 0;
+
+ params.getPictureSize(&new_picture_width, &new_picture_height);
+ LOGV("%s : new_picture_width x new_picture_height = %dx%d", __func__, new_picture_width, new_picture_height);
+ if (0 < new_picture_width && 0 < new_picture_height) {
+ LOGV("%s: setSnapshotSize", __func__);
+ if (mSecCamera->setSnapshotSize(new_picture_width, new_picture_height) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setSnapshotSize(width(%d), height(%d))",
+ __func__, new_picture_width, new_picture_height);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.setPictureSize(new_picture_width, new_picture_height);
+ }
+ }
+
+ // picture format
+ const char *new_str_picture_format = params.getPictureFormat();
+ LOGV("%s : new_str_picture_format %s", __func__, new_str_picture_format);
+ if (new_str_picture_format != NULL) {
+ int new_picture_format = 0;
+
+ if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_RGB565))
+ new_picture_format = V4L2_PIX_FMT_RGB565;
+ else if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_RGBA8888))
+ new_picture_format = V4L2_PIX_FMT_RGB32;
+ else if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_YUV420SP))
+ new_picture_format = V4L2_PIX_FMT_NV21;
+ else if (!strcmp(new_str_picture_format, "yuv420sp_custom"))
+ new_picture_format = V4L2_PIX_FMT_NV12T;
+ else if (!strcmp(new_str_picture_format, "yuv420p"))
+ new_picture_format = V4L2_PIX_FMT_YUV420;
+ else if (!strcmp(new_str_picture_format, "yuv422i"))
+ new_picture_format = V4L2_PIX_FMT_YUYV;
+ else if (!strcmp(new_str_picture_format, "uyv422i_custom")) //Zero copy UYVY format
+ new_picture_format = V4L2_PIX_FMT_UYVY;
+ else if (!strcmp(new_str_picture_format, "uyv422i")) //Non-zero copy UYVY format
+ new_picture_format = V4L2_PIX_FMT_UYVY;
+ else if (!strcmp(new_str_picture_format, CameraParameters::PIXEL_FORMAT_JPEG))
+ new_picture_format = V4L2_PIX_FMT_YUYV;
+ else if (!strcmp(new_str_picture_format, "yuv422p"))
+ new_picture_format = V4L2_PIX_FMT_YUV422P;
+ else
+ new_picture_format = V4L2_PIX_FMT_NV21; //for 3rd party
+
+ if (mSecCamera->setSnapshotPixelFormat(new_picture_format) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setSnapshotPixelFormat(format(%d))", __func__, new_picture_format);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.setPictureFormat(new_str_picture_format);
+ }
+ }
+
+ //JPEG image quality
+ int new_jpeg_quality = params.getInt(CameraParameters::KEY_JPEG_QUALITY);
+ LOGV("%s : new_jpeg_quality %d", __func__, new_jpeg_quality);
+ /* we ignore bad values */
+ if (new_jpeg_quality >=1 && new_jpeg_quality <= 100) {
+ if (mSecCamera->setJpegQuality(new_jpeg_quality) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setJpegQuality(quality(%d))", __func__, new_jpeg_quality);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_JPEG_QUALITY, new_jpeg_quality);
+ }
+ }
+
+ // JPEG thumbnail size
+ int new_jpeg_thumbnail_width = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
+ int new_jpeg_thumbnail_height= params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
+ if (0 <= new_jpeg_thumbnail_width && 0 <= new_jpeg_thumbnail_height) {
+ if (mSecCamera->setJpegThumbnailSize(new_jpeg_thumbnail_width, new_jpeg_thumbnail_height) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setJpegThumbnailSize(width(%d), height(%d))", __func__, new_jpeg_thumbnail_width, new_jpeg_thumbnail_height);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, new_jpeg_thumbnail_width);
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, new_jpeg_thumbnail_height);
+ }
+ }
+
+ // frame rate
+ int new_frame_rate = params.getPreviewFrameRate();
+ /* ignore any fps request, we're determine fps automatically based
+ * on scene mode. don't return an error because it causes CTS failure.
+ */
+ if (new_frame_rate != mParameters.getPreviewFrameRate()) {
+ LOGW("WARN(%s): request for preview frame %d not allowed, != %d\n",
+ __func__, new_frame_rate, mParameters.getPreviewFrameRate());
+ }
+
+ // rotation
+ int new_rotation = params.getInt(CameraParameters::KEY_ROTATION);
+ LOGV("%s : new_rotation %d", __func__, new_rotation);
+ if (0 <= new_rotation) {
+ LOGV("%s : set orientation:%d\n", __func__, new_rotation);
+ if (mSecCamera->setExifOrientationInfo(new_rotation) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setExifOrientationInfo(%d)", __func__, new_rotation);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_ROTATION, new_rotation);
+ }
+ }
+
+ // brightness
+ int new_exposure_compensation = params.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION);
+ int max_exposure_compensation = params.getInt(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION);
+ int min_exposure_compensation = params.getInt(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION);
+ LOGV("%s : new_exposure_compensation %d", __func__, new_exposure_compensation);
+ if ((min_exposure_compensation <= new_exposure_compensation) &&
+ (max_exposure_compensation >= new_exposure_compensation)) {
+ if (mSecCamera->setBrightness(new_exposure_compensation) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setBrightness(brightness(%d))", __func__, new_exposure_compensation);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, new_exposure_compensation);
+ }
+ }
+
+ // whitebalance
+ const char *new_white_str = params.get(CameraParameters::KEY_WHITE_BALANCE);
+ LOGV("%s : new_white_str %s", __func__, new_white_str);
+ if (new_white_str != NULL) {
+ int new_white = -1;
+
+ if (!strcmp(new_white_str, CameraParameters::WHITE_BALANCE_AUTO))
+ new_white = WHITE_BALANCE_AUTO;
+ else if (!strcmp(new_white_str,
+ CameraParameters::WHITE_BALANCE_DAYLIGHT))
+ new_white = WHITE_BALANCE_SUNNY;
+ else if (!strcmp(new_white_str,
+ CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT))
+ new_white = WHITE_BALANCE_CLOUDY;
+ else if (!strcmp(new_white_str,
+ CameraParameters::WHITE_BALANCE_FLUORESCENT))
+ new_white = WHITE_BALANCE_FLUORESCENT;
+ else if (!strcmp(new_white_str,
+ CameraParameters::WHITE_BALANCE_INCANDESCENT))
+ new_white = WHITE_BALANCE_TUNGSTEN;
+ else {
+ LOGE("ERR(%s):Invalid white balance(%s)", __func__, new_white_str); //twilight, shade, warm_flourescent
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_white) {
+ if (mSecCamera->setWhiteBalance(new_white) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setWhiteBalance(white(%d))", __func__, new_white);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_WHITE_BALANCE, new_white_str);
+ }
+ }
+ }
+
+ // scene mode
+ const char *new_scene_mode_str = params.get(CameraParameters::KEY_SCENE_MODE);
+ const char *current_scene_mode_str = mParameters.get(CameraParameters::KEY_SCENE_MODE);
+
+ // fps range
+ int new_min_fps = 0;
+ int new_max_fps = 0;
+ int current_min_fps, current_max_fps;
+ params.getPreviewFpsRange(&new_min_fps, &new_max_fps);
+ mParameters.getPreviewFpsRange(&current_min_fps, &current_max_fps);
+ /* our fps range is determined by the sensor, reject any request
+ * that isn't exactly what we're already at.
+ * but the check is performed when requesting only changing fps range
+ */
+ if (new_scene_mode_str && current_scene_mode_str) {
+ if (!strcmp(new_scene_mode_str, current_scene_mode_str)) {
+ if ((new_min_fps != current_min_fps) || (new_max_fps != current_max_fps)) {
+ LOGW("%s : requested new_min_fps = %d, new_max_fps = %d not allowed",
+ __func__, new_min_fps, new_max_fps);
+ LOGE("%s : current_min_fps = %d, current_max_fps = %d",
+ __func__, current_min_fps, current_max_fps);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+ } else {
+ /* Check basic validation if scene mode is different */
+ if ((new_min_fps > new_max_fps) ||
+ (new_min_fps < 0) || (new_max_fps < 0))
+ ret = UNKNOWN_ERROR;
+ }
+
+ const char *new_focus_mode_str = params.get(CameraParameters::KEY_FOCUS_MODE);
+
+ if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK) {
+ int new_scene_mode = -1;
+
+ const char *new_flash_mode_str = params.get(CameraParameters::KEY_FLASH_MODE);
+
+ // fps range is (15000,30000) by default.
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(15000,30000)");
+ mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE,
+ "15000,30000");
+
+ if (!strcmp(new_scene_mode_str, CameraParameters::SCENE_MODE_AUTO)) {
+ new_scene_mode = SCENE_MODE_NONE;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "on,off,auto,torch");
+ } else {
+ // defaults for non-auto scene modes
+ if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK) {
+ new_focus_mode_str = CameraParameters::FOCUS_MODE_AUTO;
+ }
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+
+ if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_PORTRAIT)) {
+ new_scene_mode = SCENE_MODE_PORTRAIT;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_AUTO;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "auto");
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_LANDSCAPE)) {
+ new_scene_mode = SCENE_MODE_LANDSCAPE;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "off");
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_SPORTS)) {
+ new_scene_mode = SCENE_MODE_SPORTS;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "off");
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_PARTY)) {
+ new_scene_mode = SCENE_MODE_PARTY_INDOOR;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_AUTO;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "auto");
+ } else if ((!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_BEACH)) ||
+ (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_SNOW))) {
+ new_scene_mode = SCENE_MODE_BEACH_SNOW;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "off");
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_SUNSET)) {
+ new_scene_mode = SCENE_MODE_SUNSET;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "off");
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_NIGHT)) {
+ new_scene_mode = SCENE_MODE_NIGHTSHOT;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE, "(4000,30000)");
+ mParameters.set(CameraParameters::KEY_PREVIEW_FPS_RANGE,
+ "4000,30000");
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "off");
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_FIREWORKS)) {
+ new_scene_mode = SCENE_MODE_FIREWORKS;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "off");
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_CANDLELIGHT)) {
+ new_scene_mode = SCENE_MODE_CANDLE_LIGHT;
+ new_flash_mode_str = CameraParameters::FLASH_MODE_OFF;
+ mParameters.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES, "off");
+ } else {
+ LOGE("%s::unmatched scene_mode(%s)",
+ __func__, new_scene_mode_str); //action, night-portrait, theatre, steadyphoto
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+ // focus mode
+ if (new_focus_mode_str != NULL) {
+ int new_focus_mode = -1;
+
+ if (!strcmp(new_focus_mode_str,
+ CameraParameters::FOCUS_MODE_AUTO)) {
+ new_focus_mode = FOCUS_MODE_AUTO;
+ mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES,
+ BACK_CAMERA_AUTO_FOCUS_DISTANCES_STR);
+ }
+ else if (!strcmp(new_focus_mode_str,
+ CameraParameters::FOCUS_MODE_MACRO)) {
+ new_focus_mode = FOCUS_MODE_MACRO;
+ mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES,
+ BACK_CAMERA_MACRO_FOCUS_DISTANCES_STR);
+ }
+ else if (!strcmp(new_focus_mode_str,
+ CameraParameters::FOCUS_MODE_INFINITY)) {
+ new_focus_mode = FOCUS_MODE_INFINITY;
+ mParameters.set(CameraParameters::KEY_FOCUS_DISTANCES,
+ BACK_CAMERA_INFINITY_FOCUS_DISTANCES_STR);
+ }
+ else {
+ LOGE("%s::unmatched focus_mode(%s)", __func__, new_focus_mode_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_focus_mode) {
+ if (mSecCamera->setFocusMode(new_focus_mode) < 0) {
+ LOGE("%s::mSecCamera->setFocusMode(%d) fail", __func__, new_focus_mode);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_FOCUS_MODE, new_focus_mode_str);
+ }
+ }
+ }
+
+ // flash..
+ if (new_flash_mode_str != NULL) {
+ int new_flash_mode = -1;
+
+ if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_OFF))
+ new_flash_mode = FLASH_MODE_OFF;
+ else if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_AUTO))
+ new_flash_mode = FLASH_MODE_AUTO;
+ else if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_ON))
+ new_flash_mode = FLASH_MODE_ON;
+ else if (!strcmp(new_flash_mode_str, CameraParameters::FLASH_MODE_TORCH))
+ new_flash_mode = FLASH_MODE_TORCH;
+ else {
+ LOGE("%s::unmatched flash_mode(%s)", __func__, new_flash_mode_str); //red-eye
+ ret = UNKNOWN_ERROR;
+ }
+ if (0 <= new_flash_mode) {
+ if (mSecCamera->setFlashMode(new_flash_mode) < 0) {
+ LOGE("%s::mSecCamera->setFlashMode(%d) fail", __func__, new_flash_mode);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_FLASH_MODE, new_flash_mode_str);
+ }
+ }
+ }
+
+ // scene..
+ if (0 <= new_scene_mode) {
+ if (mSecCamera->setSceneMode(new_scene_mode) < 0) {
+ LOGE("%s::mSecCamera->setSceneMode(%d) fail", __func__, new_scene_mode);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_SCENE_MODE, new_scene_mode_str);
+ }
+ }
+ } else {
+ if (!isSupportedParameter(new_focus_mode_str,
+ mParameters.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES))) {
+ LOGE("%s: Unsupported focus mode: %s", __func__, new_focus_mode_str);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+
+ // image effect
+ const char *new_image_effect_str = params.get(CameraParameters::KEY_EFFECT);
+ if (new_image_effect_str != NULL) {
+
+ int new_image_effect = -1;
+
+ if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_NONE))
+ new_image_effect = IMAGE_EFFECT_NONE;
+ else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_MONO))
+ new_image_effect = IMAGE_EFFECT_BNW;
+ else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_SEPIA))
+ new_image_effect = IMAGE_EFFECT_SEPIA;
+ else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_AQUA))
+ new_image_effect = IMAGE_EFFECT_AQUA;
+ else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_NEGATIVE))
+ new_image_effect = IMAGE_EFFECT_NEGATIVE;
+ else {
+ //posterize, whiteboard, blackboard, solarize
+ LOGE("ERR(%s):Invalid effect(%s)", __func__, new_image_effect_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (new_image_effect >= 0) {
+ if (mSecCamera->setImageEffect(new_image_effect) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setImageEffect(effect(%d))", __func__, new_image_effect);
+ ret = UNKNOWN_ERROR;
+ } else {
+ const char *old_image_effect_str = mParameters.get(CameraParameters::KEY_EFFECT);
+
+ if (old_image_effect_str) {
+ if (strcmp(old_image_effect_str, new_image_effect_str)) {
+ setSkipFrame(EFFECT_SKIP_FRAME);
+ }
+ }
+
+ mParameters.set(CameraParameters::KEY_EFFECT, new_image_effect_str);
+ }
+ }
+ }
+
+ //vt mode
+ int new_vtmode = mInternalParameters.getInt("vtmode");
+ if (0 <= new_vtmode) {
+ if (mSecCamera->setVTmode(new_vtmode) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setVTMode(%d)", __func__, new_vtmode);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+ //contrast
+ int new_contrast = mInternalParameters.getInt("contrast");
+
+ if (0 <= new_contrast) {
+ if (mSecCamera->setContrast(new_contrast) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setContrast(%d)", __func__, new_contrast);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+ //WDR
+ int new_wdr = mInternalParameters.getInt("wdr");
+
+ if (0 <= new_wdr) {
+ if (mSecCamera->setWDR(new_wdr) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setWDR(%d)", __func__, new_wdr);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+ //anti shake
+ int new_anti_shake = mInternalParameters.getInt("anti-shake");
+
+ if (0 <= new_anti_shake) {
+ if (mSecCamera->setAntiShake(new_anti_shake) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setWDR(%d)", __func__, new_anti_shake);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+ // gps latitude
+ const char *new_gps_latitude_str = params.get(CameraParameters::KEY_GPS_LATITUDE);
+ if (mSecCamera->setGPSLatitude(new_gps_latitude_str) < 0) {
+ LOGE("%s::mSecCamera->setGPSLatitude(%s) fail", __func__, new_gps_latitude_str);
+ ret = UNKNOWN_ERROR;
+ } else {
+ if (new_gps_latitude_str) {
+ mParameters.set(CameraParameters::KEY_GPS_LATITUDE, new_gps_latitude_str);
+ } else {
+ mParameters.remove(CameraParameters::KEY_GPS_LATITUDE);
+ }
+ }
+
+ // gps longitude
+ const char *new_gps_longitude_str = params.get(CameraParameters::KEY_GPS_LONGITUDE);
+
+ if (mSecCamera->setGPSLongitude(new_gps_longitude_str) < 0) {
+ LOGE("%s::mSecCamera->setGPSLongitude(%s) fail", __func__, new_gps_longitude_str);
+ ret = UNKNOWN_ERROR;
+ } else {
+ if (new_gps_longitude_str) {
+ mParameters.set(CameraParameters::KEY_GPS_LONGITUDE, new_gps_longitude_str);
+ } else {
+ mParameters.remove(CameraParameters::KEY_GPS_LONGITUDE);
+ }
+ }
+
+ // gps altitude
+ const char *new_gps_altitude_str = params.get(CameraParameters::KEY_GPS_ALTITUDE);
+
+ if (mSecCamera->setGPSAltitude(new_gps_altitude_str) < 0) {
+ LOGE("%s::mSecCamera->setGPSAltitude(%s) fail", __func__, new_gps_altitude_str);
+ ret = UNKNOWN_ERROR;
+ } else {
+ if (new_gps_altitude_str) {
+ mParameters.set(CameraParameters::KEY_GPS_ALTITUDE, new_gps_altitude_str);
+ } else {
+ mParameters.remove(CameraParameters::KEY_GPS_ALTITUDE);
+ }
+ }
+
+ // gps timestamp
+ const char *new_gps_timestamp_str = params.get(CameraParameters::KEY_GPS_TIMESTAMP);
+
+ if (mSecCamera->setGPSTimeStamp(new_gps_timestamp_str) < 0) {
+ LOGE("%s::mSecCamera->setGPSTimeStamp(%s) fail", __func__, new_gps_timestamp_str);
+ ret = UNKNOWN_ERROR;
+ } else {
+ if (new_gps_timestamp_str) {
+ mParameters.set(CameraParameters::KEY_GPS_TIMESTAMP, new_gps_timestamp_str);
+ } else {
+ mParameters.remove(CameraParameters::KEY_GPS_TIMESTAMP);
+ }
+ }
+
+ // gps processing method
+ const char *new_gps_processing_method_str = params.get(CameraParameters::KEY_GPS_PROCESSING_METHOD);
+
+ if (mSecCamera->setGPSProcessingMethod(new_gps_processing_method_str) < 0) {
+ LOGE("%s::mSecCamera->setGPSProcessingMethod(%s) fail", __func__, new_gps_processing_method_str);
+ ret = UNKNOWN_ERROR;
+ } else {
+ if (new_gps_processing_method_str) {
+ mParameters.set(CameraParameters::KEY_GPS_PROCESSING_METHOD, new_gps_processing_method_str);
+ } else {
+ mParameters.remove(CameraParameters::KEY_GPS_PROCESSING_METHOD);
+ }
+ }
+
+ // Recording size
+ int new_recording_width = mInternalParameters.getInt("recording-size-width");
+ int new_recording_height= mInternalParameters.getInt("recording-size-height");
+
+ if (0 < new_recording_width && 0 < new_recording_height) {
+ if (mSecCamera->setRecordingSize(new_recording_width, new_recording_height) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setRecordingSize(width(%d), height(%d))", __func__, new_recording_width, new_recording_height);
+ ret = UNKNOWN_ERROR;
+ }
+ } else {
+ if (mSecCamera->setRecordingSize(new_preview_width, new_preview_height) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setRecordingSize(width(%d), height(%d))", __func__, new_preview_width, new_preview_height);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+ //gamma
+ const char *new_gamma_str = mInternalParameters.get("video_recording_gamma");
+
+ if (new_gamma_str != NULL) {
+ int new_gamma = -1;
+ if (!strcmp(new_gamma_str, "off"))
+ new_gamma = GAMMA_OFF;
+ else if (!strcmp(new_gamma_str, "on"))
+ new_gamma = GAMMA_ON;
+ else {
+ LOGE("%s::unmatched gamma(%s)", __func__, new_gamma_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_gamma) {
+ if (mSecCamera->setGamma(new_gamma) < 0) {
+ LOGE("%s::mSecCamera->setGamma(%d) fail", __func__, new_gamma);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+ }
+
+ //slow ae
+ const char *new_slow_ae_str = mInternalParameters.get("slow_ae");
+
+ if (new_slow_ae_str != NULL) {
+ int new_slow_ae = -1;
+
+ if (!strcmp(new_slow_ae_str, "off"))
+ new_slow_ae = SLOW_AE_OFF;
+ else if (!strcmp(new_slow_ae_str, "on"))
+ new_slow_ae = SLOW_AE_ON;
+ else {
+ LOGE("%s::unmatched slow_ae(%s)", __func__, new_slow_ae_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_slow_ae) {
+ if (mSecCamera->setSlowAE(new_slow_ae) < 0) {
+ LOGE("%s::mSecCamera->setSlowAE(%d) fail", __func__, new_slow_ae);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+ }
+
+ /*Camcorder fix fps*/
+ int new_sensor_mode = mInternalParameters.getInt("cam_mode");
+
+ if (0 <= new_sensor_mode) {
+ if (mSecCamera->setSensorMode(new_sensor_mode) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setSensorMode(%d)", __func__, new_sensor_mode);
+ ret = UNKNOWN_ERROR;
+ }
+ } else {
+ new_sensor_mode=0;
+ }
+
+ /*Shot mode*/
+ int new_shot_mode = mInternalParameters.getInt("shot_mode");
+
+ if (0 <= new_shot_mode) {
+ if (mSecCamera->setShotMode(new_shot_mode) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setShotMode(%d)", __func__, new_shot_mode);
+ ret = UNKNOWN_ERROR;
+ }
+ } else {
+ new_shot_mode=0;
+ }
+
+ //blur for Video call
+ int new_blur_level = mInternalParameters.getInt("blur");
+
+ if (0 <= new_blur_level) {
+ if (mSecCamera->setBlur(new_blur_level) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setBlur(%d)", __func__, new_blur_level);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+
+
+ // chk_dataline
+ int new_dataline = mInternalParameters.getInt("chk_dataline");
+
+ if (0 <= new_dataline) {
+ if (mSecCamera->setDataLineCheck(new_dataline) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setDataLineCheck(%d)", __func__, new_dataline);
+ ret = UNKNOWN_ERROR;
+ }
+ }
+ LOGV("%s return ret = %d", __func__, ret);
+
+ return ret;
+}
+
+CameraParameters CameraHardwareSec::getParameters() const
+{
+ LOGV("%s :", __func__);
+ return mParameters;
+}
+
+status_t CameraHardwareSec::sendCommand(int32_t command, int32_t arg1, int32_t arg2)
+{
+ return BAD_VALUE;
+}
+
+void CameraHardwareSec::release()
+{
+ LOGV("%s", __func__);
+
+ /* shut down any threads we have that might be running. do it here
+ * instead of the destructor. we're guaranteed to be on another thread
+ * than the ones below. if we used the destructor, since the threads
+ * have a reference to this object, we could wind up trying to wait
+ * for ourself to exit, which is a deadlock.
+ */
+ if (mPreviewThread != NULL) {
+ /* this thread is normally already in it's threadLoop but blocked
+ * on the condition variable or running. signal it so it wakes
+ * up and can exit.
+ */
+ mPreviewThread->requestExit();
+ mExitPreviewThread = true;
+ mPreviewRunning = true; /* let it run so it can exit */
+ mPreviewCondition.signal();
+ mPreviewThread->requestExitAndWait();
+ mPreviewThread.clear();
+ }
+ if (mAutoFocusThread != NULL) {
+ /* this thread is normally already in it's threadLoop but blocked
+ * on the condition variable. signal it so it wakes up and can exit.
+ */
+ mFocusLock.lock();
+ mAutoFocusThread->requestExit();
+ mExitAutoFocusThread = true;
+ mFocusCondition.signal();
+ mFocusLock.unlock();
+ mAutoFocusThread->requestExitAndWait();
+ mAutoFocusThread.clear();
+ }
+ if (mPictureThread != NULL) {
+ mPictureThread->requestExitAndWait();
+ mPictureThread.clear();
+ }
+
+ if (mRawHeap) {
+ mRawHeap->release(mRawHeap);
+ mRawHeap = 0;
+ }
+ if (mPreviewHeap) {
+ mPreviewHeap->release(mPreviewHeap);
+ mPreviewHeap = 0;
+ }
+ if (mRecordHeap) {
+ mRecordHeap->release(mRecordHeap);
+ mRecordHeap = 0;
+ }
+
+ /* close after all the heaps are cleared since those
+ * could have dup'd our file descriptor.
+ */
+ mSecCamera->DeinitCamera();
+}
+
+status_t CameraHardwareSec::storeMetaDataInBuffers(bool enable)
+{
+ // FIXME:
+ // metadata buffer mode can be turned on or off.
+ // Samsung needs to fix this.
+ if (!enable) {
+ LOGE("Non-metadata buffer mode is not supported!");
+ return INVALID_OPERATION;
+ }
+ return OK;
+}
+
+static CameraInfo sCameraInfo[] = {
+ {
+ CAMERA_FACING_BACK,
+ 90, /* orientation */
+ },
+ {
+ CAMERA_FACING_FRONT,
+ 270, /* orientation */
+ }
+};
+
+/** Close this device */
+
+static camera_device_t *g_cam_device;
+
+static int HAL_camera_device_close(struct hw_device_t* device)
+{
+ LOGI("%s", __func__);
+ if (device) {
+ camera_device_t *cam_device = (camera_device_t *)device;
+ delete static_cast<CameraHardwareSec *>(cam_device->priv);
+ free(cam_device);
+ g_cam_device = 0;
+ }
+ return 0;
+}
+
+static inline CameraHardwareSec *obj(struct camera_device *dev)
+{
+ return reinterpret_cast<CameraHardwareSec *>(dev->priv);
+}
+
+/** Set the preview_stream_ops to which preview frames are sent */
+static int HAL_camera_device_set_preview_window(struct camera_device *dev,
+ struct preview_stream_ops *buf)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->setPreviewWindow(buf);
+}
+
+/** Set the notification and data callbacks */
+static void HAL_camera_device_set_callbacks(struct camera_device *dev,
+ camera_notify_callback notify_cb,
+ camera_data_callback data_cb,
+ camera_data_timestamp_callback data_cb_timestamp,
+ camera_request_memory get_memory,
+ void* user)
+{
+ LOGV("%s", __func__);
+ obj(dev)->setCallbacks(notify_cb, data_cb, data_cb_timestamp,
+ get_memory,
+ 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.
+ */
+static void HAL_camera_device_enable_msg_type(struct camera_device *dev, int32_t msg_type)
+{
+ LOGV("%s", __func__);
+ obj(dev)->enableMsgType(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).
+ */
+static void HAL_camera_device_disable_msg_type(struct camera_device *dev, int32_t msg_type)
+{
+ LOGV("%s", __func__);
+ obj(dev)->disableMsgType(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.
+ */
+static int HAL_camera_device_msg_type_enabled(struct camera_device *dev, int32_t msg_type)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->msgTypeEnabled(msg_type);
+}
+
+/**
+ * Start preview mode.
+ */
+static int HAL_camera_device_start_preview(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->startPreview();
+}
+
+/**
+ * Stop a previously started preview.
+ */
+static void HAL_camera_device_stop_preview(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ obj(dev)->stopPreview();
+}
+
+/**
+ * Returns true if preview is enabled.
+ */
+static int HAL_camera_device_preview_enabled(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->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.
+ */
+static int HAL_camera_device_store_meta_data_in_buffers(struct camera_device *dev, int enable)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->storeMetaDataInBuffers(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.
+ */
+static int HAL_camera_device_start_recording(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->startRecording();
+}
+
+/**
+ * Stop a previously started recording.
+ */
+static void HAL_camera_device_stop_recording(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ obj(dev)->stopRecording();
+}
+
+/**
+ * Returns true if recording is enabled.
+ */
+static int HAL_camera_device_recording_enabled(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->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.
+ */
+static void HAL_camera_device_release_recording_frame(struct camera_device *dev,
+ const void *opaque)
+{
+ LOGV("%s", __func__);
+ obj(dev)->releaseRecordingFrame(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.
+ */
+static int HAL_camera_device_auto_focus(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->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.
+ */
+static int HAL_camera_device_cancel_auto_focus(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->cancelAutoFocus();
+}
+
+/**
+ * Take a picture.
+ */
+static int HAL_camera_device_take_picture(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->takePicture();
+}
+
+/**
+ * Cancel a picture that was started with takePicture. Calling this method
+ * when no picture is being taken is a no-op.
+ */
+static int HAL_camera_device_cancel_picture(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->cancelPicture();
+}
+
+/**
+ * Set the camera parameters. This returns BAD_VALUE if any parameter is
+ * invalid or not supported.
+ */
+static int HAL_camera_device_set_parameters(struct camera_device *dev,
+ const char *parms)
+{
+ LOGV("%s", __func__);
+ String8 str(parms);
+ CameraParameters p(str);
+ return obj(dev)->setParameters(p);
+}
+
+/** Return the camera parameters. */
+char *HAL_camera_device_get_parameters(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ String8 str;
+ CameraParameters parms = obj(dev)->getParameters();
+ str = parms.flatten();
+ return strdup(str.string());
+}
+
+void HAL_camera_device_put_parameters(struct camera_device *dev, char *parms)
+{
+ LOGV("%s", __func__);
+ free(parms);
+}
+
+/**
+ * Send command to camera driver.
+ */
+static int HAL_camera_device_send_command(struct camera_device *dev,
+ int32_t cmd, int32_t arg1, int32_t arg2)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->sendCommand(cmd, arg1, arg2);
+}
+
+/**
+ * Release the hardware resources owned by this object. Note that this is
+ * *not* done in the destructor.
+ */
+static void HAL_camera_device_release(struct camera_device *dev)
+{
+ LOGV("%s", __func__);
+ obj(dev)->release();
+}
+
+/**
+ * Dump state of the camera hardware
+ */
+static int HAL_camera_device_dump(struct camera_device *dev, int fd)
+{
+ LOGV("%s", __func__);
+ return obj(dev)->dump(fd);
+}
+
+static int HAL_getNumberOfCameras()
+{
+ LOGV("%s", __func__);
+ return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]);
+}
+
+static int HAL_getCameraInfo(int cameraId, struct camera_info *cameraInfo)
+{
+ LOGV("%s", __func__);
+ memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));
+ return 0;
+}
+
+#define SET_METHOD(m) m : HAL_camera_device_##m
+
+static camera_device_ops_t camera_device_ops = {
+ SET_METHOD(set_preview_window),
+ SET_METHOD(set_callbacks),
+ SET_METHOD(enable_msg_type),
+ SET_METHOD(disable_msg_type),
+ SET_METHOD(msg_type_enabled),
+ SET_METHOD(start_preview),
+ SET_METHOD(stop_preview),
+ SET_METHOD(preview_enabled),
+ SET_METHOD(store_meta_data_in_buffers),
+ SET_METHOD(start_recording),
+ SET_METHOD(stop_recording),
+ SET_METHOD(recording_enabled),
+ SET_METHOD(release_recording_frame),
+ SET_METHOD(auto_focus),
+ SET_METHOD(cancel_auto_focus),
+ SET_METHOD(take_picture),
+ SET_METHOD(cancel_picture),
+ SET_METHOD(set_parameters),
+ SET_METHOD(get_parameters),
+ SET_METHOD(put_parameters),
+ SET_METHOD(send_command),
+ SET_METHOD(release),
+ SET_METHOD(dump),
+};
+
+#undef SET_METHOD
+
+static int HAL_camera_device_open(const struct hw_module_t* module,
+ const char *id,
+ struct hw_device_t** device)
+{
+ LOGV("%s", __func__);
+
+ int cameraId = atoi(id);
+ if (cameraId < 0 || cameraId >= HAL_getNumberOfCameras()) {
+ LOGE("Invalid camera ID %s", id);
+ return -EINVAL;
+ }
+
+ if (g_cam_device) {
+ if (obj(g_cam_device)->getCameraId() == cameraId) {
+ LOGV("returning existing camera ID %s", id);
+ goto done;
+ } else {
+ LOGE("Cannot open camera %d. camera %d is already running!",
+ cameraId, obj(g_cam_device)->getCameraId());
+ return -ENOSYS;
+ }
+ }
+
+ g_cam_device = (camera_device_t *)malloc(sizeof(camera_device_t));
+ if (!g_cam_device)
+ return -ENOMEM;
+
+ g_cam_device->common.tag = HARDWARE_DEVICE_TAG;
+ g_cam_device->common.version = 1;
+ g_cam_device->common.module = const_cast<hw_module_t *>(module);
+ g_cam_device->common.close = HAL_camera_device_close;
+
+ g_cam_device->ops = &camera_device_ops;
+
+ LOGI("%s: open camera %s", __func__, id);
+
+ g_cam_device->priv = new CameraHardwareSec(cameraId, g_cam_device);
+
+done:
+ *device = (hw_device_t *)g_cam_device;
+ LOGI("%s: opened camera %s (%p)", __func__, id, *device);
+ return 0;
+}
+
+static hw_module_methods_t camera_module_methods = {
+ open : HAL_camera_device_open
+};
+
+extern "C" {
+ struct camera_module HAL_MODULE_INFO_SYM = {
+ common : {
+ tag : HARDWARE_MODULE_TAG,
+ version_major : 1,
+ version_minor : 0,
+ id : CAMERA_HARDWARE_MODULE_ID,
+ name : "Crespo camera HAL",
+ author : "Samsung Corporation",
+ methods : &camera_module_methods,
+ },
+ get_number_of_cameras : HAL_getNumberOfCameras,
+ get_camera_info : HAL_getCameraInfo
+ };
+}
+
+}; // namespace android
diff --git a/libcamera/SecCameraHWInterface.h b/libcamera/SecCameraHWInterface.h
new file mode 100644
index 0000000..e99aff6
--- /dev/null
+++ b/libcamera/SecCameraHWInterface.h
@@ -0,0 +1,214 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+** Copyright 2010, Samsung Electronics Co. LTD
+**
+** 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_CAMERA_HARDWARE_SEC_H
+#define ANDROID_HARDWARE_CAMERA_HARDWARE_SEC_H
+
+#include "SecCamera.h"
+#include <utils/threads.h>
+#include <utils/RefBase.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <hardware/camera.h>
+#include <hardware/gralloc.h>
+#include <camera/CameraParameters.h>
+
+namespace android {
+ class CameraHardwareSec : public virtual RefBase {
+public:
+ virtual 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);
+
+ virtual void enableMsgType(int32_t msgType);
+ virtual void disableMsgType(int32_t msgType);
+ virtual bool msgTypeEnabled(int32_t msgType);
+
+ virtual status_t startPreview();
+ virtual void stopPreview();
+ virtual bool previewEnabled();
+
+ virtual status_t startRecording();
+ virtual void stopRecording();
+ virtual bool recordingEnabled();
+ virtual void releaseRecordingFrame(const void *opaque);
+
+ virtual status_t autoFocus();
+ virtual status_t cancelAutoFocus();
+ virtual status_t takePicture();
+ virtual status_t cancelPicture();
+ virtual status_t dump(int fd) const;
+ virtual status_t setParameters(const CameraParameters& params);
+ virtual CameraParameters getParameters() const;
+ virtual status_t sendCommand(int32_t command, int32_t arg1, int32_t arg2);
+ virtual status_t setPreviewWindow(preview_stream_ops *w);
+ virtual status_t storeMetaDataInBuffers(bool enable);
+ virtual void release();
+
+ inline int getCameraId() const;
+
+ CameraHardwareSec(int cameraId, camera_device_t *dev);
+ virtual ~CameraHardwareSec();
+private:
+ status_t startPreviewInternal();
+ void stopPreviewInternal();
+
+ static const int kBufferCount = MAX_BUFFERS;
+ static const int kBufferCountForRecord = MAX_BUFFERS;
+
+ class PreviewThread : public Thread {
+ CameraHardwareSec *mHardware;
+ public:
+ PreviewThread(CameraHardwareSec *hw):
+ Thread(false),
+ mHardware(hw) { }
+ virtual void onFirstRef() {
+ run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
+ }
+ virtual bool threadLoop() {
+ mHardware->previewThreadWrapper();
+ return false;
+ }
+ };
+
+ class PictureThread : public Thread {
+ CameraHardwareSec *mHardware;
+ public:
+ PictureThread(CameraHardwareSec *hw):
+ Thread(false),
+ mHardware(hw) { }
+ virtual bool threadLoop() {
+ mHardware->pictureThread();
+ return false;
+ }
+ };
+
+ class AutoFocusThread : public Thread {
+ CameraHardwareSec *mHardware;
+ public:
+ AutoFocusThread(CameraHardwareSec *hw): Thread(false), mHardware(hw) { }
+ virtual void onFirstRef() {
+ run("CameraAutoFocusThread", PRIORITY_DEFAULT);
+ }
+ virtual bool threadLoop() {
+ mHardware->autoFocusThread();
+ return true;
+ }
+ };
+
+ void initDefaultParameters(int cameraId);
+ void initHeapLocked();
+
+ sp<PreviewThread> mPreviewThread;
+ int previewThread();
+ int previewThreadWrapper();
+
+ sp<AutoFocusThread> mAutoFocusThread;
+ int autoFocusThread();
+
+ sp<PictureThread> mPictureThread;
+ int pictureThread();
+ bool mCaptureInProgress;
+
+ int save_jpeg(unsigned char *real_jpeg, int jpeg_size);
+ void save_postview(const char *fname, uint8_t *buf,
+ uint32_t size);
+ int decodeInterleaveData(unsigned char *pInterleaveData,
+ int interleaveDataSize,
+ int yuvWidth,
+ int yuvHeight,
+ int *pJpegSize,
+ void *pJpegData,
+ void *pYuvData);
+ bool YUY2toNV21(void *srcBuf, void *dstBuf, uint32_t srcWidth, uint32_t srcHeight);
+ bool scaleDownYuv422(char *srcBuf, uint32_t srcWidth,
+ uint32_t srcHight, char *dstBuf,
+ uint32_t dstWidth, uint32_t dstHight);
+
+ bool CheckVideoStartMarker(unsigned char *pBuf);
+ bool CheckEOIMarker(unsigned char *pBuf);
+ bool FindEOIMarkerInJPEG(unsigned char *pBuf,
+ int dwBufSize, int *pnJPEGsize);
+ bool SplitFrame(unsigned char *pFrame, int dwSize,
+ int dwJPEGLineLength, int dwVideoLineLength,
+ int dwVideoHeight, void *pJPEG,
+ int *pdwJPEGSize, void *pVideo,
+ int *pdwVideoSize);
+ void setSkipFrame(int frame);
+ bool isSupportedPreviewSize(const int width,
+ const int height) const;
+ bool isSupportedParameter(const char * const parm,
+ const char * const supported_parm) const;
+ status_t waitCaptureCompletion();
+ /* used by auto focus thread to block until it's told to run */
+ mutable Mutex mFocusLock;
+ mutable Condition mFocusCondition;
+ bool mExitAutoFocusThread;
+
+ /* used by preview thread to block until it's told to run */
+ mutable Mutex mPreviewLock;
+ mutable Condition mPreviewCondition;
+ mutable Condition mPreviewStoppedCondition;
+ bool mPreviewRunning;
+ bool mPreviewStartDeferred;
+ bool mExitPreviewThread;
+
+ preview_stream_ops *mPreviewWindow;
+
+ /* used to guard mCaptureInProgress */
+ mutable Mutex mCaptureLock;
+ mutable Condition mCaptureCondition;
+
+ CameraParameters mParameters;
+ CameraParameters mInternalParameters;
+
+ camera_memory_t *mPreviewHeap;
+ camera_memory_t *mRawHeap;
+ camera_memory_t *mRecordHeap;
+
+ SecCamera *mSecCamera;
+ const __u8 *mCameraSensorName;
+
+ mutable Mutex mSkipFrameLock;
+ int mSkipFrame;
+
+ camera_notify_callback mNotifyCb;
+ camera_data_callback mDataCb;
+ camera_data_timestamp_callback mDataCbTimestamp;
+ camera_request_memory mGetMemoryCb;
+ void *mCallbackCookie;
+
+ int32_t mMsgEnabled;
+
+ bool mRecordRunning;
+ mutable Mutex mRecordLock;
+ int mPostViewWidth;
+ int mPostViewHeight;
+ int mPostViewSize;
+
+ Vector<Size> mSupportedPreviewSizes;
+
+ camera_device_t *mHalDevice;
+ static gralloc_module_t const* mGrallocHal;
+};
+
+}; // namespace android
+
+#endif