exynos: reorganized and updated from insignal
Changes needed on exynos4210 devices:
libcsc -> libseccscapi
libswconverter -> remove
TARGET_HAL_PATH := hardware/samsung/exynos4/hal
TARGET_OMX_PATH := hardware/samsung/exynos/multimedia/openmax
$(call inherit-product, hardware/samsung/exynos4210.mk)
Change-Id: Ic59ef95b85ef37b3f38fb36cf6a364a5414685ee
diff --git a/exynos5/hal/libcamera/Android.mk b/exynos5/hal/libcamera/Android.mk
new file mode 100644
index 0000000..9ab5b2f
--- /dev/null
+++ b/exynos5/hal/libcamera/Android.mk
@@ -0,0 +1,28 @@
+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_SRC_FILES:= \
+ SecCamera.cpp \
+ SecCameraHWInterface.cpp \
+ mediactl.cpp \
+
+LOCAL_SHARED_LIBRARIES:= libutils libcutils libbinder liblog libcamera_client libhardware
+
+LOCAL_CFLAGS += -DGAIA_FW_BETA
+
+ifeq ($(BOARD_USES_HWJPEG),true)
+LOCAL_SHARED_LIBRARIES += libhwjpeg
+LOCAL_CFLAGS += -DSAMSUNG_EXYNOS5250
+endif
+
+LOCAL_MODULE := camera.$(TARGET_DEVICE)
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/exynos5/hal/libcamera/NOTICE b/exynos5/hal/libcamera/NOTICE
new file mode 100644
index 0000000..f921593
--- /dev/null
+++ b/exynos5/hal/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/exynos5/hal/libcamera/SecCamera.cpp b/exynos5/hal/libcamera/SecCamera.cpp
new file mode 100644
index 0000000..2b434c5
--- /dev/null
+++ b/exynos5/hal/libcamera/SecCamera.cpp
@@ -0,0 +1,3693 @@
+/*
+ * 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 <string.h>
+#include <stdlib.h>
+#include <sys/poll.h>
+#include "SecCamera.h"
+#include "cutils/properties.h"
+#include <videodev2.h>
+#include "mediactl.h"
+#include "v4l2subdev.h"
+
+using namespace android;
+
+#define CHECK(return_value) \
+ if (return_value < 0) { \
+ LOGE("%s::%d fail. errno: %s, m_camera_id = %d", \
+ __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", \
+ __func__,__LINE__, strerror(errno), m_camera_id); \
+ return NULL; \
+ }
+
+#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
+
+namespace android {
+
+static struct timeval time_start;
+static struct timeval time_stop;
+int cam_fd1, cam_fd2;
+
+#if defined(LOG_NDEBUG) && LOG_NDEBUG == 0
+unsigned long measure_time_camera(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;
+}
+#endif
+
+static int gsc_cap_open(int id)
+{
+ char node[20];
+ int fd;
+
+ id += GSC_VD_NODE_OFFSET;
+ sprintf(node, "%s%d", PFX_NODE_GSC, id);
+ LOGE("(%s): %s%d", __func__, PFX_NODE_GSC, id);
+
+ fd = open(node, O_RDWR, 0);
+ if(fd < 0) {
+ LOGE("ERR(%s): Open gscaler video device failed", __func__);
+ return -1;
+ }
+ LOGE("%s open", node);
+
+ return fd;
+}
+
+static int close_buffers(struct SecBuffer *buffers)
+{
+ int i, j;
+ int ret;
+
+ for (i = 0; i < MAX_BUFFERS; i++) {
+ for(j = 0; j < MAX_PLANES; j++) {
+ if (buffers[i].virt.extP[j]) {
+ buffers[i].virt.extP[j] = NULL;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int get_pixel_depth(unsigned int fmt)
+{
+ int depth = 0;
+
+ switch (fmt) {
+ case V4L2_PIX_FMT_JPEG:
+ depth = 8;
+ break;
+
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV12T:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
+ case V4L2_PIX_FMT_YVU420M:
+ case V4L2_PIX_FMT_NV12M:
+ case V4L2_PIX_FMT_NV12MT:
+ depth = 12;
+ break;
+
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_RGB565X:
+ 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;
+
+ default:
+ LOGE("ERR(%s):Get depth failed.", __func__);
+ break;
+ }
+
+ return depth;
+}
+
+static int gsc_cap_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", __func__);
+ return ret;
+ }
+
+ if (ret == 0) {
+ LOGE("ERR(%s):No data in 10 secs..", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int v4l2_gsc_cap_querycap(int fp)
+{
+ struct v4l2_capability cap;
+
+ if (ioctl(fp, VIDIOC_QUERYCAP, &cap) < 0) {
+ LOGE("ERR(%s):VIDIOC_QUERYCAP failed", __func__);
+ return -1;
+ }
+
+ if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE)) {
+ LOGE("ERR(%s):no capture devices", __func__);
+ return -1;
+ }
+ if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
+ LOGE("ERR(%s):no streaming capture devices", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static const __u8* v4l2_gsc_cap_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", __func__);
+ return NULL;
+ }
+ LOGI("Name of input channel[%d] is %s", input.index, input.name);
+
+ return input.name;
+}
+
+static int v4l2_gsc_cap_s_input(int fp, int index)
+{
+ struct v4l2_input input;
+
+ input.index = index;
+
+ if (ioctl(fp, VIDIOC_S_INPUT, &input) < 0) {
+ LOGE("ERR(%s):VIDIOC_S_INPUT failed", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int v4l2_gsc_cap_g_fmt(int fp)
+{
+ struct v4l2_format v4l2_fmt;
+
+ v4l2_fmt.type = V4L2_BUF_TYPE;
+
+ if(ioctl(fp, VIDIOC_G_FMT, &v4l2_fmt) < 0){
+ LOGE("ERR(%s):VIDIOC_G_FMT failed", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int v4l2_gsc_cap_s_fmt(int fp, int width, int height, unsigned int fmt, enum v4l2_field field, unsigned int num_plane)
+{
+ struct v4l2_format v4l2_fmt;
+ struct v4l2_pix_format pixfmt;
+ unsigned int framesize;
+
+ memset(&v4l2_fmt, 0, sizeof(struct v4l2_format));
+ v4l2_fmt.type = V4L2_BUF_TYPE;
+
+ framesize = (width * height * get_pixel_depth(fmt)) / 8;
+
+ v4l2_fmt.fmt.pix_mp.width = width;
+ v4l2_fmt.fmt.pix_mp.height = height;
+ v4l2_fmt.fmt.pix_mp.pixelformat = fmt;
+ v4l2_fmt.fmt.pix_mp.field = field;
+ if (num_plane == 1) {
+ v4l2_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = framesize;
+ } else if (num_plane == 2) {
+ v4l2_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = ALIGN(width * height, 2048);
+ v4l2_fmt.fmt.pix_mp.plane_fmt[1].sizeimage = ALIGN(width/2, 16) * ALIGN(height/2, 16) * 2;
+ } else if (num_plane == 3) {
+ v4l2_fmt.fmt.pix_mp.plane_fmt[0].sizeimage = ALIGN(width, 16) * ALIGN(height, 16);
+ v4l2_fmt.fmt.pix_mp.plane_fmt[1].sizeimage = ALIGN(width/2, 8) * ALIGN(height/2, 8);
+ v4l2_fmt.fmt.pix_mp.plane_fmt[2].sizeimage = ALIGN(width/2, 8) * ALIGN(height/2, 8);
+ } else {
+ LOGE("ERR(%s): Invalid plane number", __func__);
+ return -1;
+ }
+ v4l2_fmt.fmt.pix_mp.num_planes = num_plane;
+
+ /* Set up for capture */
+ if (ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
+ LOGE("ERR(%s):VIDIOC_S_FMT failed", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int v4l2_gsc_cap_s_fmt_cap(int fp, int width, int height, unsigned int fmt)
+{
+ struct v4l2_format v4l2_fmt;
+ struct v4l2_pix_format pixfmt;
+
+ memset(&pixfmt, 0, sizeof(pixfmt));
+
+ v4l2_fmt.type = V4L2_BUF_TYPE;
+
+ pixfmt.width = width;
+ pixfmt.height = height;
+ pixfmt.pixelformat = fmt;
+ if (fmt == V4L2_PIX_FMT_JPEG)
+ pixfmt.colorspace = V4L2_COLORSPACE_JPEG;
+
+ v4l2_fmt.fmt.pix = pixfmt;
+
+ /* Set up for capture */
+ if (ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
+ LOGE("ERR(%s):VIDIOC_S_FMT failed", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int v4l2_gsc_cap_s_fmt_is(int fp, int width, int height, unsigned int fmt, enum v4l2_field field)
+{
+ struct v4l2_format v4l2_fmt;
+ struct v4l2_pix_format pixfmt;
+
+ memset(&pixfmt, 0, sizeof(pixfmt));
+
+ v4l2_fmt.type = V4L2_BUF_TYPE_PRIVATE;
+
+ pixfmt.width = width;
+ pixfmt.height = height;
+ pixfmt.pixelformat = fmt;
+ pixfmt.field = field;
+
+ v4l2_fmt.fmt.pix = pixfmt;
+
+ /* Set up for capture */
+ if (ioctl(fp, VIDIOC_S_FMT, &v4l2_fmt) < 0) {
+ LOGE("ERR(%s):VIDIOC_S_FMT failed", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int v4l2_gsc_cap_enum_fmt(int fp, unsigned int fmt)
+{
+ struct v4l2_fmtdesc fmtdesc;
+ int found = 0;
+
+ fmtdesc.type = V4L2_BUF_TYPE;
+ fmtdesc.index = 0;
+
+ while (ioctl(fp, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
+ if (fmtdesc.pixelformat == fmt) {
+ LOGV("Passed fmt = %#x found pixel format[%d]: %s", fmt, fmtdesc.index, fmtdesc.description);
+ found = 1;
+ break;
+ }
+
+ fmtdesc.index++;
+ }
+
+ if (!found) {
+ LOGE("unsupported pixel format");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int v4l2_gsc_cap_reqbufs(int fp, enum v4l2_buf_type type, int nr_bufs)
+{
+ struct v4l2_requestbuffers req;
+
+ req.count = nr_bufs;
+ req.type = type;
+ req.memory = V4L2_MEMORY_TYPE;
+
+ if (ioctl(fp, VIDIOC_REQBUFS, &req) < 0) {
+ LOGE("ERR(%s):VIDIOC_REQBUFS failed", __func__);
+ return -1;
+ }
+
+ if (req.count > MAX_BUFFERS ) {
+ LOGE("ERR(%s):Insufficient buffer memory on", __func__);
+ return -1;
+ }
+
+ return req.count;
+}
+
+static int v4l2_gsc_cap_querybuf(int fp, struct SecBuffer *buffers, enum v4l2_buf_type type, int nr_frames, int num_plane)
+{
+ struct v4l2_buffer v4l2_buf;
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+ int i, plane_index;
+
+ for (i = 0; i < nr_frames; i++) {
+ v4l2_buf.type = type;
+ v4l2_buf.memory = V4L2_MEMORY_TYPE;
+ v4l2_buf.index = i;
+ v4l2_buf.m.planes = planes;
+ v4l2_buf.length = num_plane; // this is for multi-planar
+ LOGV("QUERYBUF(index=%d)", i);
+ LOGV("Memory plane is %d", v4l2_buf.length);
+
+ if (ioctl(fp, VIDIOC_QUERYBUF, &v4l2_buf) < 0) {
+ LOGE("ERR(%s):VIDIOC_QUERYBUF failed", __func__);
+ return -1;
+ }
+
+ for (plane_index = 0; plane_index < num_plane; plane_index++) {
+ LOGV("Offset : 0x%x", v4l2_buf.m.planes[plane_index].m.mem_offset);
+ LOGV("Plane Length : 0x%x", v4l2_buf.m.planes[plane_index].length);
+
+ buffers[i].phys.extP[plane_index] = (unsigned int)v4l2_buf.m.planes[plane_index].cookie;
+
+ buffers[i].size.extS[plane_index] = v4l2_buf.m.planes[plane_index].length;
+ LOGV("Length[%d] : 0x%x", i, buffers[i].size.extS[plane_index]);
+ if ((buffers[i].virt.extP[plane_index] = (char *)mmap(0, v4l2_buf.m.planes[plane_index].length,
+ PROT_READ | PROT_WRITE, MAP_SHARED, fp, v4l2_buf.m.planes[plane_index].m.mem_offset)) < 0) {
+ LOGE("mmap failed");
+ return -1;
+ }
+ LOGV("vaddr[%d][%d] : 0x%x", i, plane_index, (__u32) buffers[i].virt.extP[plane_index]);
+ }
+ }
+ return 0;
+}
+
+static int v4l2_gsc_cap_streamon(int fp)
+{
+ enum v4l2_buf_type type = V4L2_BUF_TYPE;
+ int ret;
+
+ LOGV("%s : On streaming I/O", __func__);
+ ret = ioctl(fp, VIDIOC_STREAMON, &type);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_STREAMON failed", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int v4l2_gsc_cap_streamoff(int fp)
+{
+ enum v4l2_buf_type type = V4L2_BUF_TYPE;
+ int ret;
+
+ LOGV("%s :", __func__);
+ ret = ioctl(fp, VIDIOC_STREAMOFF, &type);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_STREAMOFF failed", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int v4l2_gsc_cap_qbuf(int fp, int width, int height, struct SecBuffer *vaddr, int index, int num_plane)
+{
+ struct v4l2_buffer v4l2_buf;
+ int ret;
+
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+
+ v4l2_buf.m.planes = planes;
+ v4l2_buf.length = num_plane;
+
+ v4l2_buf.type = V4L2_BUF_TYPE;
+ v4l2_buf.memory = V4L2_MEMORY_TYPE;
+ v4l2_buf.index = index;
+
+ if(fp == cam_fd1) {
+ if (num_plane == 1) {
+ v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0];
+ v4l2_buf.m.planes[0].length = width * height * 2;
+ } else if (num_plane == 2) {
+ v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0];
+ v4l2_buf.m.planes[0].length = ALIGN(width, 16) * ALIGN(height, 16);
+ v4l2_buf.m.planes[1].m.userptr = (long unsigned int)vaddr[index].virt.extP[1];
+ v4l2_buf.m.planes[1].length = ALIGN(width/2, 16) * ALIGN(height/2, 16);
+ } else if (num_plane == 3) {
+ v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0];
+ v4l2_buf.m.planes[0].length = ALIGN(width, 16) * ALIGN(height, 16);
+ v4l2_buf.m.planes[1].m.userptr = (long unsigned int)vaddr[index].virt.extP[1];
+ v4l2_buf.m.planes[1].length = ALIGN(width/2, 8) * ALIGN(height/2, 8);
+ v4l2_buf.m.planes[2].m.userptr = (long unsigned int)vaddr[index].virt.extP[2];
+ v4l2_buf.m.planes[2].length = ALIGN(width/2, 8) * ALIGN(height/2, 8);
+ } else {
+ LOGE("ERR(%s): Invalid plane number", __func__);
+ return -1;
+ }
+ }
+ else if(fp == cam_fd2) {
+ v4l2_buf.m.planes[0].m.userptr = (long unsigned int)vaddr[index].virt.extP[0];
+ v4l2_buf.m.planes[0].length = ALIGN(ALIGN(width, 16) * ALIGN(height, 16), 2048);
+ v4l2_buf.m.planes[1].m.userptr = (long unsigned int)vaddr[index].virt.extP[1];
+ v4l2_buf.m.planes[1].length = ALIGN(ALIGN(width, 16) * ALIGN(height >> 1, 8), 2048);
+ }
+ else {
+ return -1;
+ }
+
+ ret = ioctl(fp, VIDIOC_QBUF, &v4l2_buf);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_QBUF failed", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int v4l2_gsc_cap_dqbuf(int fp, int num_plane)
+{
+ struct v4l2_buffer v4l2_buf;
+ int ret;
+
+ struct v4l2_plane planes[VIDEO_MAX_PLANES];
+
+ v4l2_buf.m.planes = planes;
+ v4l2_buf.length = num_plane;
+
+ v4l2_buf.type = V4L2_BUF_TYPE;
+ v4l2_buf.memory = V4L2_MEMORY_TYPE;
+
+ ret = ioctl(fp, VIDIOC_DQBUF, &v4l2_buf);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_DQBUF failed, dropped frame", __func__);
+ return ret;
+ }
+
+ return v4l2_buf.index;
+}
+
+static int v4l2_gsc_cap_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",
+ __func__, id, id-V4L2_CID_PRIVATE_BASE, ret);
+ return ret;
+ }
+
+ return ctrl.value;
+}
+
+static int v4l2_gsc_cap_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",
+ __func__, id, id-V4L2_CID_PRIVATE_BASE, value, ret);
+
+ return ret;
+ }
+
+ return ctrl.value;
+}
+
+static int v4l2_gsc_cap_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;
+
+ 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", __func__);
+
+ return ret;
+}
+
+static int v4l2_gsc_cap_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", __func__);
+ return ret;
+ }
+
+ LOGV("%s : timeperframe: numerator %d, denominator %d", __func__,
+ streamparm->parm.capture.timeperframe.numerator,
+ streamparm->parm.capture.timeperframe.denominator);
+
+ return ret;
+}
+
+static int v4l2_gsc_cap_s_parm(int fp, struct v4l2_streamparm *streamparm)
+{
+ int ret;
+
+ streamparm->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+
+ ret = ioctl(fp, VIDIOC_S_PARM, streamparm);
+ if (ret < 0) {
+ LOGE("ERR(%s):VIDIOC_S_PARM failed", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int v4l2_subdev_open(struct media_entity *entity)
+{
+ int fd;
+
+ fd = open(entity->devname, O_RDWR, 0);
+ if(fd < 0){
+ LOGE("ERR(%s): Open failed.", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int v4l2_subdev_get_fmt(int fd, struct v4l2_subdev_format *fmt)
+{
+ if(ioctl(fd, VIDIOC_SUBDEV_G_FMT, fmt)) {
+ LOGE("ERR(%s): subdev get foramt failed.", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+SecCamera::SecCamera() :
+ m_flagCreate(0),
+ m_camera_id(CAMERA_ID_BACK),
+ m_gsc_vd_fd(-1),
+ m_cam_fd2(-1),
+ m_jpeg_fd(-1),
+ m_flag_record_start(0),
+ m_preview_v4lformat(V4L2_PIX_FMT_YVU420M),
+ 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_picture_vaddr(NULL),
+ m_recording_en (0),
+ m_recording_width (0),
+ m_recording_height (0),
+ 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_object_tracking_start_stop(-1),
+ m_gps_latitude(-1),
+ m_gps_longitude(-1),
+ m_gps_altitude(-1),
+ m_gps_timestamp(-1),
+ m_sensor_mode(-1),
+ m_shot_mode(-1),
+ m_exif_orientation(-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_thumbnail_quality(100),
+ m_jpeg_quality(100),
+ m_touch_af_start_stop(-1),
+ m_postview_offset(0)
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+ ,
+ m_esd_check_count(0)
+#endif // ENABLE_ESD_PREVIEW_CHECK
+{
+ memset(&m_streamparm, 0, sizeof(m_streamparm));
+ 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->exposure = -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(&mExifInfo, 0, sizeof(mExifInfo));
+
+ memset(&m_events_c, 0, sizeof(m_events_c));
+ memset(&m_events_c2, 0, sizeof(m_events_c2));
+}
+
+SecCamera::~SecCamera()
+{
+ LOGV("%s :", __func__);
+ DestroyCamera();
+}
+
+bool SecCamera::CreateCamera(int index)
+{
+ LOGV("%s:", __func__);
+ char node[30];
+ int i;
+ int ret = 0;
+
+ LOGV("%s: m_flagCreate : %d", __func__, m_flagCreate);
+ if (!m_flagCreate) {
+ /* Arun C
+ * Reset the lense position only during camera starts; don't do
+ * reset between shot to shot
+ */
+ m_flagCreate = 1;
+ m_camera_af_flag = -1;
+
+ /* media device open */
+ LOGV("%s: m_flagCreate : %d", __func__, m_flagCreate);
+
+ media = media_open();
+ if (media == NULL) {
+ LOGE("ERR(%s):Cannot open media device (error : %s)", __func__, strerror(errno));
+ return -1;
+ }
+
+#ifndef GAIA_FW_BETA
+ //////////////////
+ /* GET ENTITIES */
+ //////////////////
+ /* camera subdev */
+ strcpy(node, M5MOLS_ENTITY_NAME);
+ LOGV("%s : node : %s", __func__, node);
+ camera_sd_entity = media_get_entity_by_name(media, node, strlen(node));
+ LOGV("%s : camera_sd_entity : 0x%p", __func__, camera_sd_entity);
+
+ /* mipi-csis subdev */
+ sprintf(node, "%s.%d", PFX_SUBDEV_ENTITY_MIPI_CSIS, MIPI_NUM);
+ LOGV("%s : node : %s", __func__, node);
+ mipi_sd_entity = media_get_entity_by_name(media, node, strlen(node));
+ LOGV("%s : mipi_sd_entity : 0x%p", __func__, mipi_sd_entity);
+
+ /* fimc-lite subdev */
+ sprintf(node, "%s.%d", PFX_SUBDEV_ENTITY_FLITE, FLITE_NUM);
+ LOGV("%s : node : %s", __func__, node);
+ flite_sd_entity = media_get_entity_by_name(media, node, strlen(node));
+ LOGV("%s : flite_sd_entity : 0x%p", __func__, flite_sd_entity);
+
+ /* gscaler-capture subdev */
+ sprintf(node, "%s.%d", PFX_SUBDEV_ENTITY_GSC_CAP, GSC_NUM);
+ LOGV("%s : node : %s", __func__, node);
+ gsc_cap_sd_entity = media_get_entity_by_name(media, node, strlen(node));
+ LOGV("%s : gsc_cap_sd_entity : 0x%p", __func__, gsc_cap_sd_entity);
+
+ /* gscaler-capture subdev */
+ sprintf(node, "%s.%d", PFX_VIDEODEV_ENTITY_GSC_CAP, GSC_NUM);
+ LOGV("%s : node : %s", __func__, node);
+ gsc_cap_vd_entity = media_get_entity_by_name(media, node, strlen(node));
+ LOGV("%s : gsc_cap_vd_entity : 0x%p", __func__, gsc_cap_vd_entity);
+
+ LOGV("camera_sd : numlink : %d", camera_sd_entity->num_links);
+ LOGV("mipi_sd : numlink : %d", mipi_sd_entity->num_links);
+ LOGV("flite_sd : numlink : %d", flite_sd_entity->num_links);
+ LOGV("gsc_cap_sd : numlink : %d", gsc_cap_sd_entity->num_links);
+ LOGV("gsc_cap_vd : numlink : %d", gsc_cap_vd_entity->num_links);
+
+ //////////////////
+ /* SETUP LINKS */
+ //////////////////
+ /*camera sensor to mipi-csis */
+ links = camera_sd_entity->links;
+ if (links == NULL ||
+ links->source->entity != camera_sd_entity ||
+ links->sink->entity != mipi_sd_entity) {
+ LOGE("ERR(%s): Cannot make link camera sensor to mipi-csis", __func__);
+ return -1;
+ }
+ if (media_setup_link(media, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) {
+ LOGE("ERR(%s): Cannot make setup camera sensor to mipi-csis", __func__);
+ return -1;
+ }
+ LOGV("[LINK SUCCESS] camera seneor to mipi-csis");
+
+ /*mipi-csis to fimc-lite*/
+ for(i = 0; i < mipi_sd_entity->num_links; i++) {
+ links = &mipi_sd_entity->links[i];
+ LOGV("(%s), i=%d: links->source->entity : %p, mipi_sd_entity : %p", __func__, i,
+ links->source->entity, mipi_sd_entity);
+ LOGV("(%s), i=%d: links->sink->entity : %p, flite_sd_entity : %p", __func__, i,
+ links->sink->entity, flite_sd_entity);
+ if (links == NULL ||
+ links->source->entity != mipi_sd_entity ||
+ links->sink->entity != flite_sd_entity) {
+ continue;
+ } else if (media_setup_link(media, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) {
+ LOGE("ERR(%s): Cannot make setup mipi-csis to fimc-lite", __func__);
+ return -1;
+ }
+ }
+ LOGV("[LINK SUCCESS] mipi-csis to fimc-lite");
+
+ /*fimc-lite to gscaler capture device*/
+ for(i = 0; i < gsc_cap_sd_entity->num_links; i++) {
+ links = &gsc_cap_sd_entity->links[i];
+ LOGV("(%s), i=%d: links->source->entity : %p, flite_sd_entity : %p", __func__, i,
+ links->source->entity, flite_sd_entity);
+ LOGV("(%s), i=%d: links->sink->entity : %p, gsc_cap_sd_entity : %p", __func__, i,
+ links->sink->entity, gsc_cap_sd_entity);
+ if (links == NULL ||
+ links->source->entity != flite_sd_entity ||
+ links->sink->entity != gsc_cap_sd_entity) {
+ continue;
+ } else if (media_setup_link(media, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) {
+ LOGE("ERR(%s): Cannot make setup fimc-lite to gscaler capture device", __func__);
+ return -1;
+ }
+ }
+ LOGV("[LINK SUCCESS] fimc-lite to gscaler capture device");
+
+ /*gscaler capture device to gscaler video device*/
+ for(i = 0; i < gsc_cap_vd_entity->num_links; i++) {
+ links = &gsc_cap_vd_entity->links[i];
+ LOGV("(%s), i=%d: links->source->entity : %p, gsc_cap_sd_entity : %p", __func__, i,
+ links->source->entity, gsc_cap_sd_entity);
+ LOGV("(%s), i=%d: links->sink->entity : %p, gsc_cap_vd_entity : %p", __func__, i,
+ links->sink->entity, gsc_cap_vd_entity);
+ if (links == NULL ||
+ links->source->entity != gsc_cap_sd_entity ||
+ links->sink->entity != gsc_cap_vd_entity) {
+ continue;
+ } else if (media_setup_link(media, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) {
+ LOGE("ERR(%s): Cannot make setup gscaler capture device to gscaler video device", __func__);
+ return -1;
+ }
+ }
+ LOGV("[LINK SUCCESS] gscaler capture device to gscaler video device");
+#else
+//////////////////////////////
+// internal IS
+//////////////////////////////
+ //////////////////
+ /* GET ENTITIES */
+ //////////////////
+ /* ISP sensor subdev */
+ memset(&node, 0x00, sizeof(node));
+ strcpy(node, ISP_SENSOR_ENTITY_NAME);
+ isp_sensor_entity = media_get_entity_by_name(media, node, strlen(node));
+
+ /* ISP front subdev */
+ memset(&node, 0x00, sizeof(node));
+ strcpy(node, ISP_FRONT_ENTITY_NAME);
+ isp_front_entity = media_get_entity_by_name(media, node, strlen(node));
+
+ /* ISP back subdev */
+ memset(&node, 0x00, sizeof(node));
+ strcpy(node, ISP_BACK_ENTITY_NAME);
+ isp_back_entity = media_get_entity_by_name(media, node, strlen(node));
+
+
+ /* ISP ScalerC video node */
+ memset(&node, 0x00, sizeof(node));
+ strcpy(node, ISP_VIDEO_SCALERC_NAME);
+ isp_scalerc_entity = media_get_entity_by_name(media, node, strlen(node));
+
+ /* ISP ScalerP video node */
+ memset(&node, 0x00, sizeof(node));
+ strcpy(node, ISP_VIDEO_SCALERP_NAME);
+ isp_scalerp_entity = media_get_entity_by_name(media, node, strlen(node));
+
+ /* ISP 3DNR video node */
+ memset(&node, 0x00, sizeof(node));
+ strcpy(node, ISP_VIDEO_3DNR_NAME);
+ isp_3dnr_entity = media_get_entity_by_name(media, node, strlen(node));
+
+ LOGV("isp_sensor_entity : numlink : %d", isp_sensor_entity->num_links);
+ LOGV("isp_front_entity : numlink : %d", isp_front_entity->num_links);
+ LOGV("isp_back_entity : numlink : %d", isp_back_entity->num_links);
+ LOGV("isp_scalerc_entity : numlink : %d", isp_scalerc_entity->num_links);
+ LOGV("isp_scalerp_entity : numlink : %d", isp_scalerp_entity->num_links);
+ LOGV("isp_3dnr_entity : numlink : %d", isp_3dnr_entity->num_links);
+
+ //////////////////
+ /* SETUP LINKS */
+ //////////////////
+ /* SENSOR TO FRONT */
+ links = isp_sensor_entity->links;
+ if (links == NULL ||
+ links->source->entity != isp_sensor_entity ||
+ links->sink->entity != isp_front_entity) {
+ LOGE("[ERR] Can not make link isp_sensor to isp_front\n");
+ return -1;
+ }
+ if(media_setup_link(media, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) {
+ LOGE("[ERR] Can not make setup isp_sensor to isp_front\n");
+ return -1;
+ }
+ LOGV("[LINK SUCCESS] Sensor to front");
+
+ /* FRONT TO BACK */
+ for (i = 0; i < isp_front_entity->num_links; i++){
+ links = &isp_front_entity->links[i];
+ if (links == NULL ||
+ links->source->entity != isp_front_entity ||
+ links->sink->entity != isp_back_entity) {
+ LOGV("(%s), i=%d: links->source->entity : %p, isp_front_entity : %p", __func__, i,
+ links->source->entity, isp_front_entity);
+ LOGV("(%s), i=%d: links->sink->entity : %p, isp_back_entity : %p", __func__, i,
+ links->sink->entity, isp_back_entity);
+ continue;
+ } else if(media_setup_link(media, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) {
+ LOGE("[ERR] Can not make setup isp_front to isp_back\n");
+ return -1;
+ }
+ }
+ LOGV("[LINK SUCCESS] front to back");
+
+ /* BACK TO ScalerP Video*/
+ for (i = 0; i < isp_back_entity->num_links; i++){
+ links = &isp_back_entity->links[i];
+ if (links == NULL ||
+ links->source->entity != isp_back_entity ||
+ links->sink->entity != isp_scalerp_entity) {
+ LOGV("(%s), i=%d: links->source->entity : %p, isp_front_entity : %p", __func__, i,
+ links->source->entity, isp_front_entity);
+ LOGV("(%s), i=%d: links->sink->entity : %p, isp_back_entity : %p", __func__, i,
+ links->sink->entity, isp_back_entity);
+ continue;
+ }
+ if(media_setup_link(media, links->source, links->sink, MEDIA_LNK_FL_ENABLED) < 0) {
+ LOGE("[ERR] Can not make setup isp_back to scalerP\n");
+ return -1;
+ }
+ }
+ LOGV("[LINK SUCCESS] back to scalerP");
+#endif
+
+ m_gsc_vd_fd = gsc_cap_open(0);
+ cam_fd1 = m_gsc_vd_fd;
+ if (m_gsc_vd_fd < 0) {
+ LOGE("ERR(%s):Cannot open %s (error : %s)", __func__, PFX_NODE_GSC, strerror(errno));
+ return -1;
+ }
+
+#ifndef GAIA_FW_BETA
+ if (!v4l2_gsc_cap_enuminput(m_gsc_vd_fd, index)) {
+ LOGE("m_gsc_vd_fd(%d) v4l2_gsc_cap_enuminput fail", m_gsc_vd_fd);
+ return -1;
+ }
+
+ ret = v4l2_gsc_cap_s_input(m_gsc_vd_fd, index);
+ CHECK(ret);
+#endif
+
+ 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();
+ }
+ return 0;
+}
+
+void SecCamera::resetCamera()
+{
+ LOGV("%s :", __func__);
+ DestroyCamera();
+ CreateCamera(m_camera_id);
+}
+
+bool SecCamera::DestroyCamera()
+{
+ LOGV("%s :", __func__);
+
+ if (m_flagCreate) {
+
+ stopRecord();
+
+ /* close m_gsc_vd_fd after stopRecord() because stopRecord()
+ * uses m_gsc_vd_fd to change frame rate
+ */
+ LOGI("DestroyCamera: m_gsc_vd_fd(%d)", m_gsc_vd_fd);
+ if (m_gsc_vd_fd > -1) {
+ close(m_gsc_vd_fd);
+ m_gsc_vd_fd = -1;
+ }
+
+ LOGI("DestroyCamera: m_cam_fd2(%d)", m_cam_fd2);
+ if (m_cam_fd2 > -1) {
+ close(m_cam_fd2);
+ m_cam_fd2 = -1;
+ }
+
+ m_flagCreate = 0;
+ } else
+ LOGI("%s : already deinitialized", __func__);
+
+ return 0;
+}
+
+int SecCamera::getCameraFd(void)
+{
+ return m_gsc_vd_fd;
+}
+
+unsigned char* SecCamera::getPictureVaddr(void)
+{
+ return m_picture_vaddr;
+}
+
+int SecCamera::startPreview(void)
+{
+ v4l2_streamparm streamparm;
+ struct sec_cam_parm *parms;
+ int ret;
+
+ parms = (struct sec_cam_parm*)&streamparm.parm.raw_data;
+ LOGV("%s :", __func__);
+
+ // check preview is aleady started.
+ if (m_flag_camera_start > 0) {
+ LOGE("ERR(%s):Preview was already started", __func__);
+ return 0;
+ }
+
+ if (m_gsc_vd_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ memset(&m_events_c, 0, sizeof(m_events_c));
+ m_events_c.fd = m_gsc_vd_fd;
+ m_events_c.events = POLLIN | POLLERR;
+
+#ifndef GAIA_FW_BETA
+ /* enum_fmt, s_fmt sample */
+ ret = v4l2_gsc_cap_enum_fmt(m_gsc_vd_fd, m_preview_v4lformat);
+ CHECK(ret);
+
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+ LOGV("Internal_is(%d), %s", Internal_is, (const char*)getCameraSensorName());
+
+ if (Internal_is) {
+ if (!m_recording_en)
+ v4l2_gsc_cap_s_fmt_is(m_gsc_vd_fd, m_preview_width, m_preview_height,
+ m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_STILL);
+ else
+ v4l2_gsc_cap_s_fmt_is(m_gsc_vd_fd, m_recording_width, m_recording_height,
+ m_preview_v4lformat, (enum v4l2_field) IS_MODE_PREVIEW_STILL);
+
+ }
+
+ ret = v4l2_gsc_cap_s_fmt(m_gsc_vd_fd, m_preview_width, m_preview_height, m_preview_v4lformat, V4L2_FIELD_ANY, PREVIEW_NUM_PLANE);
+ CHECK(ret);
+
+ if (Internal_is) {
+ if (!m_recording_en)
+ ret = v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_S_SCENARIO_MODE, IS_MODE_PREVIEW_STILL);
+ else
+ ret = v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_S_SCENARIO_MODE, IS_MODE_PREVIEW_STILL);
+ }
+ CHECK(ret);
+
+ ret = v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CACHEABLE, 1);
+ CHECK(ret);
+#endif
+
+ ret = v4l2_gsc_cap_reqbufs(m_gsc_vd_fd, V4L2_BUF_TYPE, MAX_BUFFERS);
+ CHECK(ret);
+
+ LOGV("%s : m_preview_width: %d m_preview_height: %d m_angle: %d",
+ __func__, m_preview_width, m_preview_height, m_angle);
+
+ LOGV("m_camera_id : %d", m_camera_id);
+
+ /* start with all buffers in queue */
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ ret = v4l2_gsc_cap_qbuf(m_gsc_vd_fd, m_preview_width, m_preview_height, m_buffers_preview, i, PREVIEW_NUM_PLANE);
+ CHECK(ret);
+ }
+
+ ret = v4l2_gsc_cap_streamon(m_gsc_vd_fd);
+ CHECK(ret);
+
+ m_flag_camera_start = 1;
+/* TO DO : Frame Rate set is will be availeable.
+ if (setFrameRate(m_params->capture.timeperframe.denominator) < 0)
+ LOGE("ERR(%s):Fail on setFrameRate(%d)",
+ __func__, m_params->capture.timeperframe.denominator);
+*/
+ LOGV("%s: got the first frame of the preview", __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_gsc_vd_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ ret = v4l2_gsc_cap_streamoff(m_gsc_vd_fd);
+ CHECK(ret);
+
+ close_buffers(m_buffers_preview);
+
+ v4l2_gsc_cap_reqbufs(m_gsc_vd_fd, V4L2_BUF_TYPE, 0);
+
+ 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", __func__);
+ return 0;
+ }
+
+ if (m_cam_fd2 <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ /* enum_fmt, s_fmt sample */
+ ret = v4l2_gsc_cap_enum_fmt(m_cam_fd2, RECORD_PIX_FMT);
+ CHECK(ret);
+
+ LOGI("%s: m_recording_width = %d, m_recording_height = %d",
+ __func__, m_recording_width, m_recording_height);
+
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+ LOGV("Internal_is(%d), %s", Internal_is, (const char*)getCameraSensorName());
+
+// if (Internal_is)
+// v4l2_gsc_cap_s_fmt_is(m_cam_fd2, m_recording_width, m_recording_height, RECORD_PIX_FMT, (enum v4l2_field) IS_MODE_CAPTURE_VIDEO);
+
+ ret = v4l2_gsc_cap_s_fmt(m_cam_fd2, m_recording_width,
+ m_recording_height, RECORD_PIX_FMT, V4L2_FIELD_ANY, RECORD_NUM_PLANE);
+ CHECK(ret);
+
+ ret = v4l2_gsc_cap_reqbufs(m_cam_fd2, V4L2_BUF_TYPE, MAX_BUFFERS);
+ CHECK(ret);
+
+ /* start with all buffers in queue */
+ for (i = 0; i < MAX_BUFFERS; i++) {
+ ret = v4l2_gsc_cap_qbuf(m_cam_fd2, m_recording_width, m_recording_height, m_buffers_record, i, RECORD_NUM_PLANE);
+ 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 = v4l2_gsc_cap_streamon(m_cam_fd2);
+ 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", __func__);
+ return -1;
+ }
+
+ m_flag_record_start = 0;
+
+ ret = v4l2_gsc_cap_streamoff(m_cam_fd2);
+ CHECK(ret);
+
+ close_buffers(m_buffers_record);
+
+ v4l2_gsc_cap_reqbufs(m_cam_fd2, V4L2_BUF_TYPE, 0);
+
+ return 0;
+}
+
+int SecCamera::getRecordAddr(int index, SecBuffer *buffer)
+{
+ buffer->phys.extP[0] = (unsigned int)m_buffers_record[index].phys.extP[0];
+ buffer->phys.extP[1] = (unsigned int)(m_buffers_record[index].phys.extP[0] + (m_recording_width * m_recording_height));
+ return 0;
+}
+
+int SecCamera::getPreviewAddr(int index, SecBuffer *buffer)
+{
+ buffer->phys.extP[0] = (unsigned int)m_buffers_preview[index].phys.extP[0];
+ buffer->phys.extP[1] = (unsigned int)m_buffers_preview[index].phys.extP[1];
+ buffer->virt.extP[0] = m_buffers_preview[index].virt.extP[0];
+ return 0;
+}
+
+void SecCamera::setUserBufferAddr(void *ptr, int index, int mode)
+{
+ if (mode == PREVIEW_MODE) {
+ m_buffers_preview[index].virt.extP[0] = (char *)((unsigned int *)ptr)[0];
+ m_buffers_preview[index].virt.extP[1] = (char *)((unsigned int *)ptr)[1];
+ m_buffers_preview[index].virt.extP[2] = (char *)((unsigned int *)ptr)[2];
+ } else if (mode == RECORD_MODE) {
+ m_buffers_record[index].virt.extP[0] = (char *)ptr;
+ m_buffers_record[index].virt.extP[1] = (char *)ptr + ((ALIGN(m_recording_width, 16) * ALIGN(m_recording_height, 16)));
+ } else
+ LOGE("%s: Invalid fd!!!", __func__);
+}
+
+int SecCamera::getPreview()
+{
+ int index;
+ int ret;
+
+ LOGV("%s: ", __func__);
+ if (m_flag_camera_start == 0 || gsc_cap_poll(&m_events_c) == 0) {
+ LOGE("ERR(%s):Start Camera Device Reset", __func__);
+ /*
+ * When there is no data for more than 1 second from the camera we inform
+ * the FIMC driver by calling v4l2_gsc_cap_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 = v4l2_gsc_cap_querycap(m_gsc_vd_fd);
+ CHECK(ret);
+#ifndef GAIA_FW_BETA
+ if (v4l2_gsc_cap_enuminput(m_gsc_vd_fd, m_camera_id))
+ return -1;
+ ret = v4l2_gsc_cap_s_input(m_gsc_vd_fd, 1000);
+ CHECK(ret);
+#endif
+ m_preview_state = 0;
+ return -1;
+ ret = startPreview();
+ if (ret < 0) {
+ LOGE("ERR(%s): startPreview() return %d", __func__, ret);
+ return 0;
+ }
+ }
+
+ index = v4l2_gsc_cap_dqbuf(m_gsc_vd_fd, PREVIEW_NUM_PLANE);
+ if (!(0 <= index && index < MAX_BUFFERS)) {
+ LOGE("ERR(%s):wrong index = %d", __func__, index);
+ return -1;
+ }
+
+ return index;
+}
+
+int SecCamera::setPreviewFrame(int index)
+{
+ int ret;
+ ret = v4l2_gsc_cap_qbuf(m_gsc_vd_fd, m_preview_width, m_preview_height, m_buffers_preview, index, PREVIEW_NUM_PLANE);
+ CHECK(ret);
+
+ return ret;
+}
+
+int SecCamera::getRecordFrame()
+{
+ if (m_flag_record_start == 0) {
+ LOGE("%s: m_flag_record_start is 0", __func__);
+ return -1;
+ }
+
+ gsc_cap_poll(&m_events_c2);
+ int index = v4l2_gsc_cap_dqbuf(m_cam_fd2, RECORD_NUM_PLANE);
+ if (!(0 <= index && index < MAX_BUFFERS)) {
+ LOGE("ERR(%s):wrong index = %d", __func__, index);
+ return -1;
+ }
+
+ return index;
+}
+
+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 v4l2_gsc_cap_qbuf(m_cam_fd2, m_recording_width, m_recording_height, m_buffers_record, index, RECORD_NUM_PLANE);
+}
+
+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_YVU420)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_YVU420");
+ else if (v4lpixelformat == V4L2_PIX_FMT_YVU420M)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_YVU420M");
+ else if (v4lpixelformat == V4L2_PIX_FMT_NV12)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_NV12");
+ else if (v4lpixelformat == V4L2_PIX_FMT_NV12M)
+ LOGV("PreviewFormat:V4L2_PIX_FMT_NV12M");
+ 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 = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_preview_v4lformat), *width, *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;
+}
+
+/*
+ * 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;
+
+ if (m_gsc_vd_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return 0;
+ }
+
+ if (m_flag_camera_start > 0) {
+ LOGW("WARN(%s):Camera was in preview, should have been stopped", __func__);
+ stopPreview();
+ }
+
+ memset(&m_events_c, 0, sizeof(m_events_c));
+ m_events_c.fd = m_gsc_vd_fd;
+ m_events_c.events = POLLIN | POLLERR;
+
+ int nframe = 1;
+
+ ret = v4l2_gsc_cap_enum_fmt(m_gsc_vd_fd,m_snapshot_v4lformat);
+ CHECK(ret);
+
+ ret = v4l2_gsc_cap_reqbufs(m_gsc_vd_fd, V4L2_BUF_TYPE, nframe);
+ CHECK(ret);
+
+#ifdef GAIA_FW_BETA
+ ret = v4l2_gsc_cap_querybuf(m_gsc_vd_fd, &m_capture_buf, V4L2_BUF_TYPE, 1, 2);
+ CHECK(ret);
+#endif
+
+ ret = v4l2_gsc_cap_qbuf(m_gsc_vd_fd, m_snapshot_width, m_snapshot_height, m_buffers_preview, 0, 1);
+ CHECK(ret);
+
+ ret = v4l2_gsc_cap_streamon(m_gsc_vd_fd);
+ CHECK(ret);
+
+ return 0;
+}
+
+int SecCamera::endSnapshot(void)
+{
+ int ret;
+
+ LOGI("%s :", __func__);
+ if (m_capture_buf.virt.extP[0]) {
+ munmap(m_capture_buf.virt.extP[0], m_capture_buf.size.extS[0]);
+ LOGI("munmap():virt. addr %p size = %d",
+ m_capture_buf.virt.extP[0], m_capture_buf.size.extS[0]);
+ m_capture_buf.virt.extP[0] = NULL;
+ m_capture_buf.size.extS[0] = 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)
+{
+ int index, ret = 0;
+ unsigned char *addr;
+ SecBuffer jpegAddr;
+
+ // capture
+ ret = gsc_cap_poll(&m_events_c);
+ CHECK_PTR(ret);
+ index = v4l2_gsc_cap_dqbuf(m_gsc_vd_fd, 1);
+
+ if (index != 0) {
+ LOGE("ERR(%s):wrong index = %d", __func__, index);
+ return NULL;
+ }
+
+ *jpeg_size = v4l2_gsc_cap_g_ctrl(m_gsc_vd_fd, V4L2_CID_CAM_JPEG_MAIN_SIZE);
+ CHECK_PTR(*jpeg_size);
+
+ int main_offset = v4l2_gsc_cap_g_ctrl(m_gsc_vd_fd, V4L2_CID_CAM_JPEG_MAIN_OFFSET);
+ CHECK_PTR(main_offset);
+ m_postview_offset = v4l2_gsc_cap_g_ctrl(m_gsc_vd_fd, V4L2_CID_CAM_JPEG_POSTVIEW_OFFSET);
+ CHECK_PTR(m_postview_offset);
+
+ ret = v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_STREAM_PAUSE, 0);
+ CHECK_PTR(ret);
+ LOGV("\nsnapshot dqueued buffer = %d snapshot_width = %d snapshot_height = %d, size = %d",
+ index, m_snapshot_width, m_snapshot_height, *jpeg_size);
+
+ addr = (unsigned char*)(m_capture_buf.virt.extP[0]) + main_offset;
+ getPreviewAddr(index, &jpegAddr);
+ *phyaddr = jpegAddr.phys.extP[0] + m_postview_offset;
+
+ ret = v4l2_gsc_cap_streamoff(m_gsc_vd_fd);
+ CHECK_PTR(ret);
+
+ return addr;
+}
+
+int SecCamera::getExif(unsigned char *pExifDst, unsigned char *pThumbSrc)
+{
+ /*TODO : to be added HW JPEG code. */
+ return 0;
+}
+
+void SecCamera::getPostViewConfig(int *width, int *height, int *size)
+{
+ *width = m_snapshot_width;
+ *height = m_snapshot_height;
+ *size = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_snapshot_v4lformat), *width, *height);
+ 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)
+{
+ *width = m_jpeg_thumbnail_width;
+ *height = m_jpeg_thumbnail_height;
+ *size = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_snapshot_v4lformat), *width, *height);
+}
+
+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 char *addr;
+ int ret = 0;
+
+ if (m_gsc_vd_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ if (m_flag_camera_start > 0) {
+ LOGW("WARN(%s):Camera was in preview, should have been stopped", __func__);
+ stopPreview();
+ }
+
+ memset(&m_events_c, 0, sizeof(m_events_c));
+ m_events_c.fd = m_gsc_vd_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
+
+ int nframe = 1;
+
+ ret = v4l2_gsc_cap_enum_fmt(m_gsc_vd_fd, m_snapshot_v4lformat);
+ CHECK(ret);
+
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+ LOGV("Internal_is(%d), %s", Internal_is, (const char*)getCameraSensorName());
+
+ ret = v4l2_gsc_cap_s_fmt_cap(m_gsc_vd_fd, m_snapshot_width, m_snapshot_height, m_snapshot_v4lformat);
+ CHECK(ret);
+
+ ret = v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CACHEABLE, 1);
+ CHECK(ret);
+ ret = v4l2_gsc_cap_reqbufs(m_gsc_vd_fd, V4L2_BUF_TYPE, nframe);
+ CHECK(ret);
+
+#ifdef GAIA_FW_BETA
+ ret = v4l2_gsc_cap_querybuf(m_gsc_vd_fd, &m_capture_buf, V4L2_BUF_TYPE, 1, 2);
+ CHECK(ret);
+#endif
+
+ struct SecBuffer my_buf;
+ my_buf.virt.p = (char *)yuv_buf;
+
+#ifndef GAIA_FW_BETA
+ ret = v4l2_gsc_cap_qbuf(m_gsc_vd_fd, m_snapshot_width, m_snapshot_height, &my_buf, 0, 1);
+ CHECK(ret);
+#else
+ ret = v4l2_gsc_cap_qbuf(m_gsc_vd_fd, m_snapshot_width, m_snapshot_height, &m_capture_buf, 0, 1);
+ CHECK(ret);
+#endif
+
+ ret = v4l2_gsc_cap_streamon(m_gsc_vd_fd);
+ CHECK(ret);
+
+ gsc_cap_poll(&m_events_c);
+
+ index = v4l2_gsc_cap_dqbuf(m_gsc_vd_fd, 1);
+
+#ifdef GAIA_FW_BETA
+ ret = v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_STREAM_PAUSE, 0);
+ CHECK_PTR(ret);
+ LOGV("\nsnapshot dequeued buffer = %d snapshot_width = %d snapshot_height = %d",
+ index, m_snapshot_width, m_snapshot_height);
+
+ yuv_buf = (unsigned char*)m_capture_buf.virt.extP[0];
+#endif
+ m_picture_vaddr = yuv_buf;
+ v4l2_gsc_cap_streamoff(m_gsc_vd_fd);
+
+ /* TODO: JPEG encode for smdk5250 */
+
+ 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 = FRAME_SIZE(V4L2_PIX_2_HAL_PIXEL_FORMAT(m_snapshot_v4lformat), *width, *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;
+}
+
+int SecCamera::getCameraId(void)
+{
+ return m_camera_id;
+}
+
+int SecCamera::setAutofocus(void)
+{
+ LOGV("%s :", __func__);
+
+ if (m_gsc_vd_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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;
+
+ af_result = v4l2_gsc_cap_g_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_AUTO_FOCUS_RESULT);
+
+ LOGV("%s : returning %d", __func__, af_result);
+
+ return af_result;
+}
+
+int SecCamera::cancelAutofocus(void)
+{
+ LOGV("%s :", __func__);
+
+ if (m_gsc_vd_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ 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 (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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);
+
+ m_params->capture.timeperframe.denominator = frame_rate;
+ if (m_flag_camera_start) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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_gsc_vd_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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_gsc_vd_fd <= 0) {
+ LOGE("ERR(%s):Camera was closed", __func__);
+ return -1;
+ }
+
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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);
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+
+ if (Internal_is) {
+ if (white_balance < IS_AWB_AUTO || IS_AWB_MAX <= white_balance) {
+ LOGE("ERR(%s):Invalid white_balance(%d)", __func__, white_balance);
+ return -1;
+ }
+ } else {
+ 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 (Internal_is) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_AWB_MODE, white_balance) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_AWB_MODE", __func__);
+ return -1;
+ }
+ } else {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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);
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+
+ if (Internal_is) {
+ brightness += IS_BRIGHTNESS_DEFAULT;
+ if (brightness < IS_BRIGHTNESS_MINUS_2 || IS_BRIGHTNESS_PLUS2 < brightness) {
+ LOGE("ERR(%s):Invalid brightness(%d)", __func__, brightness);
+ return -1;
+ }
+ } else {
+ LOGW("WARN(%s):Not supported brightness setting", __func__);
+ return 0;
+ }
+
+ if (m_params->brightness != brightness) {
+ m_params->brightness = brightness;
+ if (m_flag_camera_start) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_BRIGHTNESS, brightness) < EV_MINUS_4) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_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::setExposure(int exposure)
+{
+ LOGV("%s(exposure(%d))", __func__, exposure);
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+
+ if (Internal_is) {
+ exposure += IS_EXPOSURE_DEFAULT;
+ if (exposure < IS_EXPOSURE_MINUS_2 || IS_EXPOSURE_PLUS2 < exposure) {
+ LOGE("ERR(%s):Invalid exposure(%d)", __func__, exposure);
+ return -1;
+ }
+ } else {
+ exposure += EV_DEFAULT;
+ if (exposure < EV_MINUS_4 || EV_PLUS_4 < exposure) {
+ LOGE("ERR(%s):Invalid exposure(%d)", __func__, exposure);
+ return -1;
+ }
+ }
+
+ if (m_params->exposure != exposure) {
+ m_params->exposure = exposure;
+ if (m_flag_camera_start) {
+ if (Internal_is) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_EXPOSURE, exposure) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_EXPOSURE", __func__);
+ return -1;
+ }
+ } else {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_BRIGHTNESS, exposure) < EV_MINUS_4) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_BRIGHTNESS", __func__);
+ return -1;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getExposure(void)
+{
+ LOGV("%s : exposure(%d)", __func__, m_params->exposure);
+ return m_params->exposure;
+}
+
+int SecCamera::setImageEffect(int image_effect)
+{
+ LOGV("%s(image_effect(%d))", __func__, image_effect);
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+
+ if (Internal_is) {
+ if (image_effect < IS_IMAGE_EFFECT_DISABLE || IS_IMAGE_EFFECT_MAX <= image_effect) {
+ LOGE("ERR(%s):Invalid image_effect(%d)", __func__, image_effect);
+ return -1;
+ }
+ } else {
+ 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 (Internal_is) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_IMAGE_EFFECT, image_effect) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_IMAGE_EFFECT", __func__);
+ return -1;
+ }
+ } else {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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);
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+
+ if (Internal_is) {
+ if (anti_banding < IS_AFC_DISABLE || IS_AFC_MAX <= anti_banding) {
+ LOGE("ERR(%s):Invalid anti_banding (%d)", __func__, anti_banding);
+ return -1;
+ }
+ } else {
+ 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 (Internal_is) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_AFC_MODE, anti_banding) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_AFC_MODE", __func__);
+ return -1;
+ }
+ } else {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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 (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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);
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+
+ if (Internal_is) {
+ if (flash_mode <= IS_FLASH_MODE_OFF || IS_FLASH_MODE_MAX <= flash_mode) {
+ LOGE("ERR(%s):Invalid flash_mode (%d)", __func__, flash_mode);
+ return -1;
+ }
+ } else {
+ 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 (Internal_is) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_FLASH_MODE, flash_mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_FLASH_MODE", __func__);
+ return -1;
+ }
+ } else {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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);
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+
+ if (Internal_is) {
+ if (iso_value < IS_ISO_AUTO || IS_ISO_MAX <= iso_value) {
+ LOGE("ERR(%s):Invalid iso_value (%d)", __func__, iso_value);
+ return -1;
+ }
+ } else {
+ 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 (Internal_is) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_ISO, iso_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_ISO", __func__);
+ return -1;
+ }
+ } else {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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);
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+
+ if (Internal_is) {
+ if (contrast_value < IS_CONTRAST_AUTO || IS_CONTRAST_MAX <= contrast_value) {
+ LOGE("ERR(%s):Invalid contrast_value (%d)", __func__, contrast_value);
+ return -1;
+ }
+ } else {
+ 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 (Internal_is) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_CONTRAST, contrast_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_CONTRAST", __func__);
+ return -1;
+ }
+ } else {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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);
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+
+ if (Internal_is) {
+ saturation_value += IS_SATURATION_DEFAULT;
+ if (saturation_value < IS_SATURATION_MINUS_2 || IS_SATURATION_MAX <= saturation_value) {
+ LOGE("ERR(%s):Invalid saturation_value (%d)", __func__, saturation_value);
+ return -1;
+ }
+ } else {
+ saturation_value += SATURATION_DEFAULT;
+ 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 (Internal_is) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_SATURATION, saturation_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SATURATION", __func__);
+ return -1;
+ }
+ } else {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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);
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+
+ if (Internal_is) {
+ sharpness_value += IS_SHARPNESS_DEFAULT;
+ if (sharpness_value < IS_SHARPNESS_MINUS_2 || IS_SHARPNESS_MAX <= sharpness_value) {
+ LOGE("ERR(%s):Invalid sharpness_value (%d)", __func__, sharpness_value);
+ return -1;
+ }
+ } else {
+ sharpness_value += SHARPNESS_DEFAULT;
+ 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 (Internal_is) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_SHARPNESS, sharpness_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_SHARPNESS", __func__);
+ return -1;
+ }
+ } else {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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::setHue(int hue_value)
+{
+ LOGV("%s(hue_value(%d))", __func__, hue_value);
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+
+ if (Internal_is) {
+ hue_value += IS_HUE_DEFAULT;
+ if (hue_value < IS_HUE_MINUS_2 || IS_HUE_MAX <= hue_value) {
+ LOGE("ERR(%s):Invalid hue_value (%d)", __func__, hue_value);
+ return -1;
+ }
+ } else {
+ LOGW("WARN(%s):Not supported hue setting", __func__);
+ return 0;
+ }
+
+ if (m_params->hue != hue_value) {
+ m_params->hue = hue_value;
+ if (m_flag_camera_start) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_HUE, hue_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_HUE", __func__);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int SecCamera::getHue(void)
+{
+ return m_params->hue;
+}
+
+int SecCamera::setWDR(int wdr_value)
+{
+ LOGV("%s(wdr_value(%d))", __func__, wdr_value);
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+
+ if (Internal_is) {
+ if (wdr_value < IS_DRC_BYPASS_DISABLE || IS_DRC_BYPASS_MAX <= wdr_value) {
+ LOGE("ERR(%s):Invalid drc_value (%d)", __func__, wdr_value);
+ return -1;
+ }
+ } else {
+ 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 (Internal_is) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_SET_DRC, wdr_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_SET_DRC", __func__);
+ return -1;
+ }
+ } else {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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 (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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);
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+
+ if (Internal_is) {
+ if (metering_value < IS_METERING_AVERAGE || IS_METERING_MAX <= metering_value) {
+ LOGE("ERR(%s):Invalid metering_value (%d)", __func__, metering_value);
+ return -1;
+ }
+ } else {
+ 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 (Internal_is) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_METERING, metering_value) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_METERING", __func__);
+ return -1;
+ }
+ } else {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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;
+#ifdef JPEG_FROM_SENSOR
+ if (m_flag_camera_start && (m_camera_id == CAMERA_ID_BACK)) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAM_JPEG_QUALITY, jpeg_quality) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAM_JPEG_QUALITY", __func__);
+ return -1;
+ }
+ }
+#endif
+ }
+
+ 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 (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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 = v4l2_gsc_cap_g_ctrl(m_gsc_vd_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 (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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 (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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 (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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 = v4l2_gsc_cap_g_ctrl(m_gsc_vd_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;
+ }
+ }
+ 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 (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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 (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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);
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+
+ if (Internal_is) {
+ if (IS_FOCUS_MODE_MAX <= focus_mode) {
+ LOGE("ERR(%s):Invalid focus_mode (%d)", __func__, focus_mode);
+ return -1;
+ }
+ } else {
+ 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;
+#ifdef AF_SUPPORT
+ if (m_flag_camera_start) {
+ if (Internal_is) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_FOCUS_MODE, focus_mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_FOCUS_MODE", __func__);
+ return -1;
+ }
+ } else {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_FOCUS_MODE, focus_mode) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_FOCUS_MODE", __func__);
+ return -1;
+ }
+ }
+ }
+#endif
+ }
+
+ 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);
+ int Internal_is = !strncmp((const char*)getCameraSensorName(), "ISP Camera", 10);
+
+ if (m_face_detect != face_detect) {
+ m_face_detect = face_detect;
+ if (m_flag_camera_start) {
+ if (m_face_detect != FACE_DETECTION_OFF) {
+ if (Internal_is) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CAMERA_FOCUS_MODE, IS_FOCUS_MODE_AUTO) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CAMERA_FOCUS_MODin face detecion", __func__);
+ return -1;
+ }
+ } else {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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 (Internal_is) {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_IS_CMD_FD, face_detect) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_IS_CMD_FD", __func__);
+ return -1;
+ }
+ } else {
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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)
+{
+ double conveted_latitude = 0;
+ LOGV("%s(gps_latitude(%s))", __func__, gps_latitude);
+ if (gps_latitude == NULL)
+ m_gps_latitude = 0;
+ else {
+ conveted_latitude = atof(gps_latitude);
+ m_gps_latitude = (long)(conveted_latitude * 10000 / 1);
+ }
+
+ LOGV("%s(m_gps_latitude(%ld))", __func__, m_gps_latitude);
+ return 0;
+}
+
+int SecCamera::setGPSLongitude(const char *gps_longitude)
+{
+ double conveted_longitude = 0;
+ LOGV("%s(gps_longitude(%s))", __func__, gps_longitude);
+ if (gps_longitude == NULL)
+ m_gps_longitude = 0;
+ else {
+ conveted_longitude = atof(gps_longitude);
+ m_gps_longitude = (long)(conveted_longitude * 10000 / 1);
+ }
+
+ LOGV("%s(m_gps_longitude(%ld))", __func__, m_gps_longitude);
+ return 0;
+}
+
+int SecCamera::setGPSAltitude(const char *gps_altitude)
+{
+ double conveted_altitude = 0;
+ LOGV("%s(gps_altitude(%s))", __func__, gps_altitude);
+ if (gps_altitude == NULL)
+ m_gps_altitude = 0;
+ else {
+ conveted_altitude = atof(gps_altitude);
+ m_gps_altitude = (long)(conveted_altitude * 100 / 1);
+ }
+
+ 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 (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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 (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_OBJECT_POSITION_X, x) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_OBJECT_POSITION_X", __func__);
+ return -1;
+ }
+
+ if (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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 (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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 (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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::setRecording(int recording_en)
+{
+ LOGV("%s(recoding_en(%d))", __func__, recording_en);
+
+ m_recording_en = recording_en;
+
+ 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::getRecordingSize(int *width, int *height)
+{
+ *width = m_recording_width;
+ *height = m_recording_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 (v4l2_gsc_cap_s_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_BATCH_REFLECTION, 1) < 0) {
+ LOGE("ERR(%s):Fail on V4L2_CID_CAMERA_BATCH_REFLECTION", __func__);
+ return -1;
+ }
+ }
+
+ 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::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 (v4l2_gsc_cap_s_ctrl(m_gsc_vd_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 v4l2_gsc_cap_enuminput(m_gsc_vd_fd, getCameraId());
+}
+
+#ifdef ENABLE_ESD_PREVIEW_CHECK
+int SecCamera::getCameraSensorESDStatus(void)
+{
+ LOGV("%s", __func__);
+
+ // 0 : normal operation, 1 : abnormal operation
+ int status = v4l2_gsc_cap_g_ctrl(m_gsc_vd_fd, V4L2_CID_ESD_INT);
+
+ return status;
+}
+#endif // ENABLE_ESD_PREVIEW_CHECK
+
+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;
+}
+
+int SecCamera::setJpegThumbnailQuality(int jpeg_thumbnail_quality)
+{
+ LOGV("%s(jpeg_thumbnail_quality (%d))", __func__, jpeg_thumbnail_quality);
+
+ if (jpeg_thumbnail_quality < JPEG_QUALITY_ECONOMY || JPEG_QUALITY_MAX <= jpeg_thumbnail_quality) {
+ LOGE("ERR(%s):Invalid jpeg_thumbnail_quality (%d)", __func__, jpeg_thumbnail_quality);
+ return -1;
+ }
+
+ if (m_jpeg_thumbnail_quality != jpeg_thumbnail_quality) {
+ m_jpeg_thumbnail_quality = jpeg_thumbnail_quality;
+ }
+
+ return 0;
+}
+
+int SecCamera::getJpegThumbnailQuality(void)
+{
+ return m_jpeg_thumbnail_quality;
+}
+
+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 90:
+ mExifInfo.orientation = EXIF_ORIENTATION_90;
+ break;
+ case 180:
+ mExifInfo.orientation = EXIF_ORIENTATION_180;
+ break;
+ case 270:
+ mExifInfo.orientation = EXIF_ORIENTATION_270;
+ break;
+ case 0:
+ 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 = v4l2_gsc_cap_g_ctrl(m_gsc_vd_fd, V4L2_CID_CAMERA_GET_SHT_TIME);
+ int shutterSpeed = 100;
+
+ /* 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 = m_params->iso;
+ //int iso = v4l2_gsc_cap_g_ctrl(m_gsc_vd_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", shutterSpeed, mExifInfo.iso_speed_rating);
+ LOGD("AV=%d, TV=%d, SV=%d", 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 = m_params->flash_mode;
+ //int flash = v4l2_gsc_cap_g_ctrl(m_gsc_vd_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_latitude != 0 && m_gps_longitude != 0) {
+ 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;
+
+ double latitude = fabs(m_gps_latitude / 10000.0);
+ double longitude = fabs(m_gps_longitude / 10000.0);
+ double altitude = fabs(m_gps_altitude / 100.0);
+
+ mExifInfo.gps_latitude[0].num = (uint32_t)latitude;
+ mExifInfo.gps_latitude[0].den = 1;
+ mExifInfo.gps_latitude[1].num = (uint32_t)((latitude - mExifInfo.gps_latitude[0].num) * 60);
+ mExifInfo.gps_latitude[1].den = 1;
+ mExifInfo.gps_latitude[2].num = (uint32_t)((((latitude - mExifInfo.gps_latitude[0].num) * 60)
+ - mExifInfo.gps_latitude[1].num) * 60);
+ mExifInfo.gps_latitude[2].den = 1;
+
+ mExifInfo.gps_longitude[0].num = (uint32_t)longitude;
+ mExifInfo.gps_longitude[0].den = 1;
+ mExifInfo.gps_longitude[1].num = (uint32_t)((longitude - mExifInfo.gps_longitude[0].num) * 60);
+ mExifInfo.gps_longitude[1].den = 1;
+ mExifInfo.gps_longitude[2].num = (uint32_t)((((longitude - mExifInfo.gps_longitude[0].num) * 60)
+ - mExifInfo.gps_longitude[1].num) * 60);
+ mExifInfo.gps_longitude[2].den = 1;
+
+ mExifInfo.gps_altitude.num = (uint32_t)altitude;
+ mExifInfo.gps_altitude.den = 1;
+
+ 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;
+}
+
+int SecCamera::makeExif (unsigned char *exifOut,
+ unsigned char *thumb_buf,
+ unsigned int thumb_size,
+ exif_attribute_t *exifInfo,
+ unsigned int *size,
+ bool useMainbufForThumb)
+{
+ unsigned char *pCur, *pApp1Start, *pIfdStart, *pGpsIfdPtr, *pNextIfdOffset;
+ unsigned int tmp, LongerTagOffest = 0;
+ pApp1Start = pCur = exifOut;
+
+ //2 Exif Identifier Code & TIFF Header
+ pCur += 4; // Skip 4 Byte for APP1 marker and length
+ unsigned char ExifIdentifierCode[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
+ memcpy(pCur, ExifIdentifierCode, 6);
+ pCur += 6;
+
+ /* Byte Order - little endian, Offset of IFD - 0x00000008.H */
+ unsigned char TiffHeader[8] = { 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00 };
+ memcpy(pCur, TiffHeader, 8);
+ pIfdStart = pCur;
+ pCur += 8;
+
+ //2 0th IFD TIFF Tags
+ if (exifInfo->enableGps)
+ tmp = NUM_0TH_IFD_TIFF;
+ else
+ tmp = NUM_0TH_IFD_TIFF - 1;
+
+ memcpy(pCur, &tmp, NUM_SIZE);
+ pCur += NUM_SIZE;
+
+ LongerTagOffest += 8 + NUM_SIZE + tmp*IFD_SIZE + OFFSET_SIZE;
+
+ writeExifIfd(&pCur, EXIF_TAG_IMAGE_WIDTH, EXIF_TYPE_LONG,
+ 1, exifInfo->width);
+ writeExifIfd(&pCur, EXIF_TAG_IMAGE_HEIGHT, EXIF_TYPE_LONG,
+ 1, exifInfo->height);
+ writeExifIfd(&pCur, EXIF_TAG_MAKE, EXIF_TYPE_ASCII,
+ strlen((char *)exifInfo->maker) + 1, exifInfo->maker, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_MODEL, EXIF_TYPE_ASCII,
+ strlen((char *)exifInfo->model) + 1, exifInfo->model, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT,
+ 1, exifInfo->orientation);
+ writeExifIfd(&pCur, EXIF_TAG_SOFTWARE, EXIF_TYPE_ASCII,
+ strlen((char *)exifInfo->software) + 1, exifInfo->software, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_DATE_TIME, EXIF_TYPE_ASCII,
+ 20, exifInfo->date_time, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_YCBCR_POSITIONING, EXIF_TYPE_SHORT,
+ 1, exifInfo->ycbcr_positioning);
+ writeExifIfd(&pCur, EXIF_TAG_EXIF_IFD_POINTER, EXIF_TYPE_LONG,
+ 1, LongerTagOffest);
+ if (exifInfo->enableGps) {
+ pGpsIfdPtr = pCur;
+ pCur += IFD_SIZE; // Skip a ifd size for gps IFD pointer
+ }
+
+ pNextIfdOffset = pCur; // Skip a offset size for next IFD offset
+ pCur += OFFSET_SIZE;
+
+ //2 0th IFD Exif Private Tags
+ pCur = pIfdStart + LongerTagOffest;
+
+ tmp = NUM_0TH_IFD_EXIF;
+ memcpy(pCur, &tmp , NUM_SIZE);
+ pCur += NUM_SIZE;
+
+ LongerTagOffest += NUM_SIZE + NUM_0TH_IFD_EXIF*IFD_SIZE + OFFSET_SIZE;
+
+ writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_TIME, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->exposure_time, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_FNUMBER, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->fnumber, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_PROGRAM, EXIF_TYPE_SHORT,
+ 1, exifInfo->exposure_program);
+ writeExifIfd(&pCur, EXIF_TAG_ISO_SPEED_RATING, EXIF_TYPE_SHORT,
+ 1, exifInfo->iso_speed_rating);
+ writeExifIfd(&pCur, EXIF_TAG_EXIF_VERSION, EXIF_TYPE_UNDEFINED,
+ 4, exifInfo->exif_version);
+ writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_ORG, EXIF_TYPE_ASCII,
+ 20, exifInfo->date_time, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_DATE_TIME_DIGITIZE, EXIF_TYPE_ASCII,
+ 20, exifInfo->date_time, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_SHUTTER_SPEED, EXIF_TYPE_SRATIONAL,
+ 1, (rational_t *)&exifInfo->shutter_speed, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_APERTURE, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->aperture, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_BRIGHTNESS, EXIF_TYPE_SRATIONAL,
+ 1, (rational_t *)&exifInfo->brightness, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_BIAS, EXIF_TYPE_SRATIONAL,
+ 1, (rational_t *)&exifInfo->exposure_bias, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_MAX_APERTURE, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->max_aperture, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_METERING_MODE, EXIF_TYPE_SHORT,
+ 1, exifInfo->metering_mode);
+ writeExifIfd(&pCur, EXIF_TAG_FLASH, EXIF_TYPE_SHORT,
+ 1, exifInfo->flash);
+ writeExifIfd(&pCur, EXIF_TAG_FOCAL_LENGTH, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->focal_length, &LongerTagOffest, pIfdStart);
+ char code[8] = { 0x00, 0x00, 0x00, 0x49, 0x49, 0x43, 0x53, 0x41 };
+ int commentsLen = strlen((char *)exifInfo->user_comment) + 1;
+ memmove(exifInfo->user_comment + sizeof(code), exifInfo->user_comment, commentsLen);
+ memcpy(exifInfo->user_comment, code, sizeof(code));
+ writeExifIfd(&pCur, EXIF_TAG_USER_COMMENT, EXIF_TYPE_UNDEFINED,
+ commentsLen + sizeof(code), exifInfo->user_comment, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_COLOR_SPACE, EXIF_TYPE_SHORT,
+ 1, exifInfo->color_space);
+ writeExifIfd(&pCur, EXIF_TAG_PIXEL_X_DIMENSION, EXIF_TYPE_LONG,
+ 1, exifInfo->width);
+ writeExifIfd(&pCur, EXIF_TAG_PIXEL_Y_DIMENSION, EXIF_TYPE_LONG,
+ 1, exifInfo->height);
+ writeExifIfd(&pCur, EXIF_TAG_EXPOSURE_MODE, EXIF_TYPE_LONG,
+ 1, exifInfo->exposure_mode);
+ writeExifIfd(&pCur, EXIF_TAG_WHITE_BALANCE, EXIF_TYPE_LONG,
+ 1, exifInfo->white_balance);
+ writeExifIfd(&pCur, EXIF_TAG_SCENCE_CAPTURE_TYPE, EXIF_TYPE_LONG,
+ 1, exifInfo->scene_capture_type);
+ tmp = 0;
+ memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset
+ pCur += OFFSET_SIZE;
+
+ //2 0th IFD GPS Info Tags
+ if (exifInfo->enableGps) {
+ writeExifIfd(&pGpsIfdPtr, EXIF_TAG_GPS_IFD_POINTER, EXIF_TYPE_LONG,
+ 1, LongerTagOffest); // GPS IFD pointer skipped on 0th IFD
+
+ pCur = pIfdStart + LongerTagOffest;
+
+ if (exifInfo->gps_processing_method[0] == 0) {
+ // don't create GPS_PROCESSING_METHOD tag if there isn't any
+ tmp = NUM_0TH_IFD_GPS - 1;
+ } else {
+ tmp = NUM_0TH_IFD_GPS;
+ }
+ memcpy(pCur, &tmp, NUM_SIZE);
+ pCur += NUM_SIZE;
+
+ LongerTagOffest += NUM_SIZE + tmp*IFD_SIZE + OFFSET_SIZE;
+
+ writeExifIfd(&pCur, EXIF_TAG_GPS_VERSION_ID, EXIF_TYPE_BYTE,
+ 4, exifInfo->gps_version_id);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_LATITUDE_REF, EXIF_TYPE_ASCII,
+ 2, exifInfo->gps_latitude_ref);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_LATITUDE, EXIF_TYPE_RATIONAL,
+ 3, exifInfo->gps_latitude, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_LONGITUDE_REF, EXIF_TYPE_ASCII,
+ 2, exifInfo->gps_longitude_ref);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_LONGITUDE, EXIF_TYPE_RATIONAL,
+ 3, exifInfo->gps_longitude, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_ALTITUDE_REF, EXIF_TYPE_BYTE,
+ 1, exifInfo->gps_altitude_ref);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_ALTITUDE, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->gps_altitude, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_TIMESTAMP, EXIF_TYPE_RATIONAL,
+ 3, exifInfo->gps_timestamp, &LongerTagOffest, pIfdStart);
+ tmp = strlen((char*)exifInfo->gps_processing_method);
+ if (tmp > 0) {
+ if (tmp > 100) {
+ tmp = 100;
+ }
+ static const char ExifAsciiPrefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };
+ unsigned char tmp_buf[100+sizeof(ExifAsciiPrefix)];
+ memcpy(tmp_buf, ExifAsciiPrefix, sizeof(ExifAsciiPrefix));
+ memcpy(&tmp_buf[sizeof(ExifAsciiPrefix)], exifInfo->gps_processing_method, tmp);
+ writeExifIfd(&pCur, EXIF_TAG_GPS_PROCESSING_METHOD, EXIF_TYPE_UNDEFINED,
+ tmp+sizeof(ExifAsciiPrefix), tmp_buf, &LongerTagOffest, pIfdStart);
+ }
+ writeExifIfd(&pCur, EXIF_TAG_GPS_DATESTAMP, EXIF_TYPE_ASCII,
+ 11, exifInfo->gps_datestamp, &LongerTagOffest, pIfdStart);
+ tmp = 0;
+ memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset
+ pCur += OFFSET_SIZE;
+ }
+
+ //2 1th IFD TIFF Tags
+
+ unsigned char *thumbBuf = thumb_buf;
+ unsigned int thumbSize = thumb_size;
+
+ if (exifInfo->enableThumb && (thumbBuf != NULL) && (thumbSize > 0)) {
+ tmp = LongerTagOffest;
+ memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE); // NEXT IFD offset skipped on 0th IFD
+
+ pCur = pIfdStart + LongerTagOffest;
+
+ tmp = NUM_1TH_IFD_TIFF;
+ memcpy(pCur, &tmp, NUM_SIZE);
+ pCur += NUM_SIZE;
+
+ LongerTagOffest += NUM_SIZE + NUM_1TH_IFD_TIFF*IFD_SIZE + OFFSET_SIZE;
+
+ writeExifIfd(&pCur, EXIF_TAG_IMAGE_WIDTH, EXIF_TYPE_LONG,
+ 1, exifInfo->widthThumb);
+ writeExifIfd(&pCur, EXIF_TAG_IMAGE_HEIGHT, EXIF_TYPE_LONG,
+ 1, exifInfo->heightThumb);
+ writeExifIfd(&pCur, EXIF_TAG_COMPRESSION_SCHEME, EXIF_TYPE_SHORT,
+ 1, exifInfo->compression_scheme);
+ writeExifIfd(&pCur, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT,
+ 1, exifInfo->orientation);
+ writeExifIfd(&pCur, EXIF_TAG_X_RESOLUTION, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->x_resolution, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_Y_RESOLUTION, EXIF_TYPE_RATIONAL,
+ 1, &exifInfo->y_resolution, &LongerTagOffest, pIfdStart);
+ writeExifIfd(&pCur, EXIF_TAG_RESOLUTION_UNIT, EXIF_TYPE_SHORT,
+ 1, exifInfo->resolution_unit);
+ writeExifIfd(&pCur, EXIF_TAG_JPEG_INTERCHANGE_FORMAT, EXIF_TYPE_LONG,
+ 1, LongerTagOffest);
+ writeExifIfd(&pCur, EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LEN, EXIF_TYPE_LONG,
+ 1, thumbSize);
+
+ tmp = 0;
+ memcpy(pCur, &tmp, OFFSET_SIZE); // next IFD offset
+ pCur += OFFSET_SIZE;
+
+ memcpy(pIfdStart + LongerTagOffest, thumbBuf, thumbSize);
+ LongerTagOffest += thumbSize;
+ } else {
+ tmp = 0;
+ memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE); // NEXT IFD offset skipped on 0th IFD
+ }
+
+ unsigned char App1Marker[2] = { 0xff, 0xe1 };
+ memcpy(pApp1Start, App1Marker, 2);
+ pApp1Start += 2;
+
+ *size = 10 + LongerTagOffest;
+ tmp = *size - 2; // APP1 Maker isn't counted
+ unsigned char size_mm[2] = {(tmp >> 8) & 0xFF, tmp & 0xFF};
+ memcpy(pApp1Start, size_mm, 2);
+
+ LOGD("makeExif X");
+
+ return 0;
+}
+
+inline void SecCamera::writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ uint32_t value)
+{
+ memcpy(*pCur, &tag, 2);
+ *pCur += 2;
+ memcpy(*pCur, &type, 2);
+ *pCur += 2;
+ memcpy(*pCur, &count, 4);
+ *pCur += 4;
+ memcpy(*pCur, &value, 4);
+ *pCur += 4;
+}
+
+inline void SecCamera::writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ unsigned char *pValue)
+{
+ char buf[4] = { 0,};
+
+ memcpy(buf, pValue, count);
+ memcpy(*pCur, &tag, 2);
+ *pCur += 2;
+ memcpy(*pCur, &type, 2);
+ *pCur += 2;
+ memcpy(*pCur, &count, 4);
+ *pCur += 4;
+ memcpy(*pCur, buf, 4);
+ *pCur += 4;
+}
+
+inline void SecCamera::writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ unsigned char *pValue,
+ unsigned int *offset,
+ unsigned char *start)
+{
+ memcpy(*pCur, &tag, 2);
+ *pCur += 2;
+ memcpy(*pCur, &type, 2);
+ *pCur += 2;
+ memcpy(*pCur, &count, 4);
+ *pCur += 4;
+ memcpy(*pCur, offset, 4);
+ *pCur += 4;
+ memcpy(start + *offset, pValue, count);
+ *offset += count;
+}
+
+inline void SecCamera::writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ rational_t *pValue,
+ unsigned int *offset,
+ unsigned char *start)
+{
+ memcpy(*pCur, &tag, 2);
+ *pCur += 2;
+ memcpy(*pCur, &type, 2);
+ *pCur += 2;
+ memcpy(*pCur, &count, 4);
+ *pCur += 4;
+ memcpy(*pCur, offset, 4);
+ *pCur += 4;
+ memcpy(start + *offset, pValue, 8 * count);
+ *offset += 8 * count;
+}
+
+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/exynos5/hal/libcamera/SecCamera.h b/exynos5/hal/libcamera/SecCamera.h
new file mode 100644
index 0000000..1af19ee
--- /dev/null
+++ b/exynos5/hal/libcamera/SecCamera.h
@@ -0,0 +1,698 @@
+/*
+**
+** 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 <sys/types.h>
+
+#include <utils/RefBase.h>
+#include <videodev2.h>
+#include <videodev2_samsung.h>
+#include <linux/vt.h>
+
+#include <media.h>
+#include <v4l2-mediabus.h>
+#include <v4l2-subdev.h>
+
+#include <sec_utils_v4l2.h>
+
+#include "SecBuffer.h"
+
+#include <mediactl.h>
+#include <v4l2subdev.h>
+
+#include <utils/String8.h>
+
+#include "SecJpegEncoder.h"
+
+#include "Exif.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_camera(&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 M5MO
+#define BACK_CAM S5K4E5
+
+#if !defined (FRONT_CAM) || !defined(BACK_CAM)
+#error "Please define the Camera module"
+#endif
+
+#define M5MO_PREVIEW_WIDTH 1920
+#define M5MO_PREVIEW_HEIGHT 1080
+#define M5MO_SNAPSHOT_WIDTH 3264
+#define M5MO_SNAPSHOT_HEIGHT 2448
+
+#define M5MO_THUMBNAIL_WIDTH 320
+#define M5MO_THUMBNAIL_HEIGHT 240
+#define M5MO_THUMBNAIL_BPP 16
+
+#define M5MO_FPS 30
+
+/* focal length of 3.43mm */
+#define M5MO_FOCAL_LENGTH 343
+
+#define S5K4E5_PREVIEW_WIDTH 1920
+#define S5K4E5_PREVIEW_HEIGHT 1080
+#define S5K4E5_SNAPSHOT_WIDTH 1920
+#define S5K4E5_SNAPSHOT_HEIGHT 1080
+
+#define S5K4E5_THUMBNAIL_WIDTH 320
+#define S5K4E5_THUMBNAIL_HEIGHT 240
+#define S5K4E5_THUMBNAIL_BPP 16
+
+#define S5K4E5_FPS 30
+
+/* focal length of 0.9mm */
+#define S5K4E5_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_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_FPS JOIN(BACK_CAM,_FPS)
+
+#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_FPS JOIN(FRONT_CAM,_FPS)
+
+#define FRONT_CAMERA_FOCAL_LENGTH JOIN(FRONT_CAM,_FOCAL_LENGTH)
+
+#define DEFAULT_JPEG_THUMBNAIL_WIDTH 256
+#define DEFAULT_JPEG_THUMBNAIL_HEIGHT 192
+
+#define PFX_NODE_GSC "/dev/video"
+
+#define M5MOLS_ENTITY_NAME "M5MOLS 5-001f"
+#define PFX_SUBDEV_ENTITY_MIPI_CSIS "s5p-mipi-csis"
+#define PFX_SUBDEV_ENTITY_FLITE "exynos-fimc-lite"
+#define PFX_SUBDEV_ENTITY_GSC_CAP "gsc-cap-subdev"
+#define PFX_VIDEODEV_ENTITY_GSC_CAP "exynos-gsc"
+#define FIMD1_ENTITY_NAME "s5p-fimd1"
+
+#define GAIA_FW_BETA 1
+
+#ifndef GAIA_FW_BETA
+#define GSC_VD_NODE_OFFSET 25 //GSCALER 0 (0:25, 1:28, 2:31, 3:34)
+#else
+#define GSC_VD_NODE_OFFSET 41 //INTERNAL_ISP 4E5
+
+#define ISP_SENSOR_MAX_ENTITIES 1
+#define ISP_SENSOR_PAD_SOURCE_FRONT 0
+#define ISP_SENSOR_PADS_NUM 1
+
+#define ISP_FRONT_MAX_ENTITIES 1
+#define ISP_FRONT_PAD_SINK 0
+#define ISP_FRONT_PAD_SOURCE_BACK 1
+#define ISP_FRONT_PAD_SOURCE_BAYER 2
+#define ISP_FRONT_PAD_SOURCE_SCALERC 3
+#define ISP_FRONT_PADS_NUM 4
+
+#define ISP_BACK_MAX_ENTITIES 1
+#define ISP_BACK_PAD_SINK 0
+#define ISP_BACK_PAD_SOURCE_3DNR 1
+#define ISP_BACK_PAD_SOURCE_SCALERP 2
+#define ISP_BACK_PADS_NUM 3
+
+#define ISP_MODULE_NAME "exynos5-fimc-is"
+#define ISP_SENSOR_ENTITY_NAME "exynos5-fimc-is-sensor"
+#define ISP_FRONT_ENTITY_NAME "exynos5-fimc-is-front"
+#define ISP_BACK_ENTITY_NAME "exynos5-fimc-is-back"
+#define ISP_VIDEO_BAYER_NAME "exynos5-fimc-is-bayer"
+#define ISP_VIDEO_SCALERC_NAME "exynos5-fimc-is-scalerc"
+#define ISP_VIDEO_3DNR_NAME "exynos5-fimc-is-3dnr"
+#define ISP_VIDEO_SCALERP_NAME "exynos5-fimc-is-scalerp"
+
+#endif
+#define MIPI_NUM 1
+#define FLITE_NUM 1
+#define GSC_NUM 0
+
+#define PFX_SUBDEV_NODE "/dev/v4l-subdev"
+
+#define BPP 2
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#ifndef GAIA_FW_BETA
+#define MAX_BUFFERS 8
+#else
+#define MAX_BUFFERS 4 //external : 8, internal : 4
+#endif
+
+#define MAX_PLANES (3)
+#define V4L2_BUF_TYPE V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
+
+#define V4L2_MEMORY_TYPE V4L2_MEMORY_USERPTR
+#define RECORD_PIX_FMT V4L2_PIX_FMT_NV12M
+#define PREVIEW_NUM_PLANE (3)
+#define RECORD_NUM_PLANE (2)
+
+/*
+ * 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
+ *
+ */
+#define PREVIEW_MODE 1
+#define RECORD_MODE 2
+
+/* We use this struct as the v4l2_streamparm raw_data for
+ * VIDIOC_G_PARM and VIDIOC_S_PARM
+ */
+struct sec_cam_parm {
+ struct v4l2_captureparm capture;
+ int contrast;
+ int effects;
+ int brightness;
+ int exposure;
+ int flash_mode;
+ int focus_mode;
+ int iso;
+ int metering;
+ int saturation;
+ int scene_mode;
+ int sharpness;
+ int hue;
+ int white_balance;
+};
+
+struct yuv_fmt_list {
+ const char *name;
+ const char *desc;
+ unsigned int fmt;
+ int depth;
+ int planes;
+};
+
+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;
+
+ SecCamera();
+ virtual ~SecCamera();
+
+ static SecCamera* createInstance(void)
+ {
+ static SecCamera singleton;
+ return &singleton;
+ }
+ status_t dump(int fd);
+
+ bool CreateCamera(int index);
+ bool DestroyCamera(void);
+ int getCameraId(void);
+
+ int startPreview(void);
+ int stopPreview(void);
+ int getPreviewState(void)
+ {
+ return m_preview_state;
+ }
+ void clearPreviewState(void)
+ {
+ m_preview_state = 0;
+ }
+
+ int startRecord(void);
+ int stopRecord(void);
+ int setPreviewFrame(int index);
+ int getRecordFrame(void);
+ int releaseRecordFrame(int index);
+ int getRecordAddr(int index, SecBuffer *buffer);
+
+ 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 setJpegThumbnailQuality(int jpeg_thumbnail_quality);
+ int getJpegThumbnailQuality(void);
+
+ int setAutofocus(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 setExposure(int exposure);
+ int getExposure(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 setHue(int hue_value);
+ int getHue(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 setRecording(int recording_en);
+ int setRecordingSize(int width, int height);
+ int getRecordingSize(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 */
+ int setDataLineCheck(int chk_dataline);
+ int getDataLineCheck(void);
+ int setDataLineCheckStop(void);
+ int setDefultIMEI(int imei);
+ int getDefultIMEI(void);
+ const __u8* getCameraSensorName(void);
+#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);
+ unsigned char* getPictureVaddr(void);
+ int getJpegFd(void);
+ void SetJpgAddr(unsigned char *addr);
+ int getPreviewAddr(int index, SecBuffer *buffer);
+ void setUserBufferAddr(void *ptr, int index, int mode);
+ 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_flagCreate;
+ int m_preview_state;
+ int m_camera_id;
+
+ /* v4l2 sub-dev file description */
+ int m_cam_sd_fd;
+ int m_mipi_sd_fd;
+ int m_flite_sd_fd;
+ int m_gsc_sd_fd;
+ int m_gsc_vd_fd;
+
+ /* media controller variable */
+ struct media_device *media;
+ struct media_link *links;
+ struct media_pad *pads;
+
+ struct media_entity *camera_sd_entity;
+ struct media_entity *mipi_sd_entity;
+ struct media_entity *flite_sd_entity;
+ struct media_entity *gsc_cap_sd_entity;
+ struct media_entity *gsc_cap_vd_entity;
+ struct media_entity *isp_sensor_entity;
+ struct media_entity *isp_front_entity;
+ struct media_entity *isp_back_entity;
+ struct media_entity *isp_scalerc_entity;
+ struct media_entity *isp_scalerp_entity;
+ struct media_entity *isp_3dnr_entity;
+
+ 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;
+ unsigned char* m_picture_vaddr;
+
+ 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_en;
+ int m_recording_width;
+ int m_recording_height;
+ long m_gps_latitude;
+ long m_gps_longitude;
+ long m_gps_altitude;
+ long m_gps_timestamp;
+ int m_sensor_mode; /*Camcorder fix fps */
+ int m_shot_mode; /* Shot mode */
+ int m_exif_orientation;
+ int m_chk_dataline;
+ int m_video_gamma;
+ int m_slow_ae;
+ 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_thumbnail_quality;
+ 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 SecBuffer m_capture_buf;
+ struct SecBuffer m_buffers_preview[MAX_BUFFERS];
+ struct SecBuffer m_buffers_record[MAX_BUFFERS];
+ struct pollfd m_events_c;
+
+ inline void writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ uint32_t value);
+ inline void writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ unsigned char *pValue);
+ inline void writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ rational_t *pValue,
+ unsigned int *offset,
+ unsigned char *start);
+ inline void writeExifIfd(unsigned char **pCur,
+ unsigned short tag,
+ unsigned short type,
+ unsigned int count,
+ unsigned char *pValue,
+ unsigned int *offset,
+ unsigned char *start);
+
+ void setExifChangedAttribute();
+ void setExifFixedAttribute();
+ int makeExif (unsigned char *exifOut,
+ unsigned char *thumb_buf,
+ unsigned int thumb_size,
+ exif_attribute_t *exifInfo,
+ unsigned int *size,
+ bool useMainbufForThumb);
+ void resetCamera();
+
+ static double jpeg_ratio;
+ static int interleaveDataSize;
+ static int jpegLineLength;
+};
+
+extern unsigned long measure_time_camera(struct timeval *start, struct timeval *stop);
+
+}; // namespace android
+
+#endif // ANDROID_HARDWARE_CAMERA_SEC_H
diff --git a/exynos5/hal/libcamera/SecCameraHWInterface.cpp b/exynos5/hal/libcamera/SecCameraHWInterface.cpp
new file mode 100644
index 0000000..8cfbccc
--- /dev/null
+++ b/exynos5/hal/libcamera/SecCameraHWInterface.cpp
@@ -0,0 +1,3043 @@
+/*
+**
+** 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 ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
+
+#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"
+//#define USE_EGL
+
+// This hack does two things:
+// -- it sets preview to NV21 (YUV420SP)
+// -- it sets gralloc to YV12
+//
+// The reason being: the samsung encoder understands only yuv420sp, and gralloc
+// does yv12 and rgb565. So what we do is we break up the interleaved UV in
+// separate V and U planes, which makes preview look good, and enabled the
+// encoder as well.
+//
+// FIXME: Samsung needs to enable support for proper yv12 coming out of the
+// camera, and to fix their video encoder to work with yv12.
+// FIXME: It also seems like either Samsung's YUV420SP (NV21) or img's YV12 has
+// the color planes switched. We need to figure which side is doing it
+// wrong and have the respective party fix it.
+
+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(),
+ mFrameSizeDelta(0),
+ mCameraSensorName(NULL),
+ mSkipFrame(0),
+ mNotifyCb(0),
+ mDataCb(0),
+ mDataCbTimestamp(0),
+ mCallbackCookie(0),
+ mMsgEnabled(CAMERA_MSG_RAW_IMAGE),
+ 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;
+ for(int i = 0; i < BUFFER_COUNT_FOR_ARRAY; i++)
+ mRecordHeap[i] = 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->CreateCamera(cameraId);
+ if (ret < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera init", __func__);
+ mSecCamera->DestroyCamera();
+ }
+
+ 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;
+
+#ifndef GAIA_FW_BETA
+ mCameraSensorName = mSecCamera->getCameraSensorName();
+ if (mCameraSensorName == NULL) {
+ LOGE("ERR(%s):mCameraSensorName is NULL", __func__);
+ return;
+ }
+ LOGV("CameraSensorName: %s", mCameraSensorName);
+ int Internal_is = !strncmp((const char*)mCameraSensorName, "ISP Camera", 10);
+#else
+ int Internal_is = 0;
+ //sprintf((char *)mCameraSensorName, "%s", "temp name");
+#endif
+ 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,
+ "3264x2448,2576x1948,1920x1080,1280x720,800x480,720x480,640x480,320x240,528x432,176x144");
+ p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
+ "3264x2448,1920x1080,1280x720,800x480,720x480,640x480");
+ if (Internal_is)
+ p.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES,
+ "1920x1080,1280x720,640x480,176x144");
+ } else {
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
+ "1392x1392,1280x720,640x480,352x288,320x240,176x144");
+ p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
+ "1392x1392,1280x960,640x480");
+ if (Internal_is)
+ p.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES,
+ "1280x720,640x480,176x144");
+ }
+
+ 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)",
+ preview_max_width, preview_max_height);
+ if (mSecCamera->getSnapshotMaxSize(&snapshot_max_width,
+ &snapshot_max_height) < 0)
+ LOGE("getSnapshotMaxSize fail (%d / %d)",
+ snapshot_max_width, snapshot_max_height);
+
+ p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420P); mFrameSizeDelta = 16;
+ p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS, CameraParameters::PIXEL_FORMAT_YUV420P);
+ p.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT, CameraParameters::PIXEL_FORMAT_YUV420SP);
+ 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);
+
+ p.set(CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO, "1280x720");
+
+ 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, "7,15,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, "7,15,30");
+ p.setPreviewFrameRate(30);
+ }
+
+ 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_BEACH);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::SCENE_MODE_SNOW);
+ 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());
+
+ 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);
+
+ p.set("contrast", "auto");
+ p.set("iso", "auto");
+ p.set("metering", "center");
+ p.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, "2");
+ p.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION, "-2");
+ p.set(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP, "1");
+
+ p.set("brightness", 0);
+ p.set("brightness-max", 2);
+ p.set("brightness-min", -2);
+
+ p.set("saturation", 0);
+ p.set("saturation-max", 2);
+ p.set("saturation-min", -2);
+
+ p.set("sharpness", 0);
+ p.set("sharpness-max", 2);
+ p.set("sharpness-min", -2);
+
+ p.set("hue", 0);
+ p.set("hue-max", 2);
+ p.set("hue-min", -2);
+
+ parameterString = CameraParameters::ANTIBANDING_AUTO;
+ parameterString.append(",");
+ parameterString.append(CameraParameters::ANTIBANDING_50HZ);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::ANTIBANDING_60HZ);
+ parameterString.append(",");
+ parameterString.append(CameraParameters::ANTIBANDING_OFF);
+ p.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
+ parameterString.string());
+
+ p.set(CameraParameters::KEY_ANTIBANDING, CameraParameters::ANTIBANDING_OFF);
+
+ 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);
+ if (cameraId == SecCamera::CAMERA_ID_BACK)
+ mSecCamera->setFrameRate(BACK_CAMERA_FPS);
+ else
+ mSecCamera->setFrameRate(FRONT_CAMERA_FPS);
+}
+
+CameraHardwareSec::~CameraHardwareSec()
+{
+ LOGV("%s", __func__);
+ mSecCamera->DestroyCamera();
+}
+
+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 >= BUFFER_COUNT_FOR_GRALLOC) {
+ LOGE("%s: min undequeued buffer count %d is too high (expecting at most %d)", __func__,
+ min_bufs, BUFFER_COUNT_FOR_GRALLOC - 1);
+ }
+
+ LOGV("%s: setting buffer count to %d", __func__, BUFFER_COUNT_FOR_GRALLOC);
+ if (w->set_buffer_count(w, BUFFER_COUNT_FOR_GRALLOC)) {
+ 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;
+
+ const char *str_preview_format = mParameters.getPreviewFormat();
+ LOGV("%s: str preview format %s width : %d height : %d ", __func__, str_preview_format, preview_width, preview_height);
+ mFrameSizeDelta = 16;
+
+ hal_pixel_format = HAL_PIXEL_FORMAT_YV12;
+
+ if (!strcmp(str_preview_format,
+ CameraParameters::PIXEL_FORMAT_RGB565)) {
+ hal_pixel_format = HAL_PIXEL_FORMAT_RGB_565;
+ mFrameSizeDelta = 0;
+ } else if (!strcmp(str_preview_format,
+ CameraParameters::PIXEL_FORMAT_RGBA8888)) {
+ hal_pixel_format = HAL_PIXEL_FORMAT_RGBA_8888;
+ mFrameSizeDelta = 0;
+ } else if (!strcmp(str_preview_format,
+ CameraParameters::PIXEL_FORMAT_YUV420SP)) {
+ hal_pixel_format = HAL_PIXEL_FORMAT_YCrCb_420_SP;
+ } else if (!strcmp(str_preview_format,
+ CameraParameters::PIXEL_FORMAT_YUV420P))
+ hal_pixel_format = HAL_PIXEL_FORMAT_YV12;
+
+#ifdef USE_EGL
+ if (w->set_usage(w, GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_ION)) {
+ LOGE("%s: could not set usage on gralloc buffer", __func__);
+ return INVALID_OPERATION;
+ }
+#else
+ if (w->set_usage(w, GRALLOC_USAGE_SW_WRITE_OFTEN
+ | GRALLOC_USAGE_HWC_HWOVERLAY | GRALLOC_USAGE_HW_ION)) {
+ LOGE("%s: could not set usage on gralloc buffer", __func__);
+ return INVALID_OPERATION;
+ }
+#endif
+
+ 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;
+ }
+
+ for(int i = 0; i < BUFFER_COUNT_FOR_ARRAY; i++)
+ if (0 != mPreviewWindow->dequeue_buffer(mPreviewWindow, &mBufferHandle[i], &mStride[i])) {
+ LOGE("%s: Could not dequeue gralloc buffer[%d]!!", __func__, i);
+ 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;
+
+ mPreviewLock.lock();
+ if ((msgType & (CAMERA_MSG_PREVIEW_FRAME | CAMERA_MSG_VIDEO_FRAME)) &&
+ mPreviewRunning && mPreviewStartDeferred) {
+ LOGV("%s: starting deferred preview", __func__);
+ if (startPreviewInternal() == OK) {
+ mPreviewStartDeferred = false;
+ mPreviewCondition.signal();
+ }
+ }
+ mPreviewLock.unlock();
+
+ 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;
+ SecBuffer previewAddr, recordAddr;
+ static int numArray = 0;
+ void *virAddr[3];
+ private_handle_t *hnd = NULL;
+
+ index = mSecCamera->getPreview();
+
+ if (index < 0) {
+ LOGE("ERR(%s):Fail on SecCamera->getPreview()", __func__);
+ if (mSecCamera->getPreviewState()) {
+ stopPreview();
+ startPreview();
+ mSecCamera->clearPreviewState();
+ }
+ return UNKNOWN_ERROR;
+ }
+
+ mSkipFrameLock.lock();
+ if (mSkipFrame > 0) {
+ mSkipFrame--;
+ mSkipFrameLock.unlock();
+ LOGV("%s: index %d skipping frame", __func__, index);
+ if (mSecCamera->setPreviewFrame(index) < 0) {
+ LOGE("%s: Could not qbuff[%d]!!", __func__, index);
+ return UNKNOWN_ERROR;
+ }
+ return NO_ERROR;
+ }
+ mSkipFrameLock.unlock();
+
+ timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+
+ int width, height, frame_size, offset;
+
+ mSecCamera->getPreviewSize(&width, &height, &frame_size);
+
+ offset = frame_size * index;
+
+ if (mPreviewWindow && mGrallocHal && mPreviewRunning) {
+ hnd = (private_handle_t*)*mBufferHandle[index];
+
+ if (mPreviewHeap) {
+ mPreviewHeap->release(mPreviewHeap);
+ mPreviewHeap = 0;
+ }
+
+ mPreviewHeap = mGetMemoryCb(hnd->fd, frame_size, 1, 0);
+
+ hnd = NULL;
+
+ mGrallocHal->unlock(mGrallocHal, *mBufferHandle[index]);
+ if (0 != mPreviewWindow->enqueue_buffer(mPreviewWindow, mBufferHandle[index])) {
+ LOGE("%s: Could not enqueue gralloc buffer[%d]!!", __func__, index);
+ goto callbacks;
+ }
+
+ numArray = index;
+
+ if (0 != mPreviewWindow->dequeue_buffer(mPreviewWindow, &mBufferHandle[numArray], &mStride[numArray])) {
+ LOGE("%s: Could not dequeue gralloc buffer[%d]!!", __func__, numArray);
+ goto callbacks;
+ }
+
+ if (!mGrallocHal->lock(mGrallocHal,
+ *mBufferHandle[numArray],
+ GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_YUV_ADDR,
+ 0, 0, width, height, virAddr)) {
+ mSecCamera->getPreviewAddr(index, &previewAddr);
+ char *frame = (char *)previewAddr.virt.extP[0];
+
+#ifdef USE_EGL
+ int m_Ywidth = ALIGN(width, 16);
+ int m_Yheight = ALIGN(height, 16);
+ int m_UVwidth = ALIGN(width/2, 8);
+ int m_UVheight = ALIGN(height/2, 8);
+ virAddr[1] = virAddr[0] + (m_Ywidth * m_Yheight);
+ virAddr[2] = virAddr[1] + (m_UVwidth * m_UVheight);
+#endif
+
+ mSecCamera->setUserBufferAddr(virAddr, index, PREVIEW_MODE);
+ }
+ else
+ LOGE("%s: could not obtain gralloc buffer", __func__);
+
+ if (mSecCamera->setPreviewFrame(index) < 0) {
+ LOGE("%s: Fail qbuf, index(%d)", __func__, index);
+ goto callbacks;
+ }
+ index = 0;
+ }
+
+callbacks:
+ // Notify the client of a new frame.
+ if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
+ mDataCb(CAMERA_MSG_PREVIEW_FRAME, mPreviewHeap, index, NULL, mCallbackCookie);
+
+ Mutex::Autolock lock(mRecordLock);
+ if (mRecordRunning == true) {
+ int recordingIndex = 0;
+
+ index = mSecCamera->getRecordFrame();
+ if (index < 0) {
+ LOGE("ERR(%s):Fail on SecCamera->getRecordFrame()", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+ numArray = index;
+
+ // Notify the client of a new frame.
+ if (mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)
+ mDataCbTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME,
+ mRecordHeap[numArray], recordingIndex, mCallbackCookie);
+ else
+ mSecCamera->releaseRecordFrame(index);
+ }
+
+ return NO_ERROR;
+}
+
+status_t CameraHardwareSec::startPreview()
+{
+ int ret = 0;
+
+ LOGV("%s :", __func__);
+
+ Mutex::Autolock lock(mStateLock);
+ if (mCaptureInProgress) {
+ LOGE("%s : capture in progress, not allowed", __func__);
+ return INVALID_OPERATION;
+ }
+
+ mPreviewLock.lock();
+ if (mPreviewRunning) {
+ // already running
+ LOGE("%s : preview thread already running", __func__);
+ mPreviewLock.unlock();
+ return INVALID_OPERATION;
+ }
+
+ mPreviewRunning = true;
+ mPreviewStartDeferred = false;
+
+ if (!mPreviewWindow &&
+ !(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) &&
+ !(mMsgEnabled & CAMERA_MSG_VIDEO_FRAME)) {
+ 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 width, height, frame_size;
+
+ mSecCamera->getPreviewSize(&width, &height, &frame_size);
+ LOGD("mPreviewHeap(fd(%d), size(%d), width(%d), height(%d))",
+ mSecCamera->getCameraFd(), frame_size + mFrameSizeDelta, width, height);
+
+ void *vaddr[3];
+
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ !mGrallocHal->lock(mGrallocHal,
+ *mBufferHandle[i],
+ GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_YUV_ADDR,
+ 0, 0, width, height, vaddr);
+ memset(vaddr[0], 0, width*height*2);
+ int m_Ywidth = ALIGN(width, 16);
+ int m_Yheight = ALIGN(height, 16);
+ int m_UVwidth = ALIGN(width/2, 8);
+ int m_UVheight = ALIGN(height/2, 8);
+ vaddr[1] = vaddr[0] + (m_Ywidth * m_Yheight);
+ vaddr[2] = vaddr[1] + (m_UVwidth * m_UVheight);
+ mSecCamera->setUserBufferAddr(vaddr, i, PREVIEW_MODE);
+ }
+
+ 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);
+
+ if (mPreviewHeap) {
+ mPreviewHeap->release(mPreviewHeap);
+ mPreviewHeap = 0;
+ }
+
+ 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);
+
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ if (0 != mPreviewWindow->enqueue_buffer(mPreviewWindow, mBufferHandle[i]))
+ LOGE("%s: Fail to enqueue buffer[%d]", __func__, i);
+ }
+ }
+ 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);
+
+ for(int i = 0; i<BUFFER_COUNT_FOR_ARRAY; i++){
+ if (mRecordHeap[i] != NULL) {
+ mRecordHeap[i]->release(mRecordHeap[i]);
+ mRecordHeap[i] = 0;
+ }
+
+ int width, height;
+
+ mSecCamera->getRecordingSize(&width, &height);
+ mRecordHeap[i] = mGetMemoryCb(-1, (ALIGN((ALIGN(width, 16) * ALIGN(height, 16)), 2048)
+ + ALIGN((ALIGN(width, 16) * ALIGN(height >> 1, 8)), 2048)), 1, NULL);
+ mSecCamera->setUserBufferAddr((void *)(mRecordHeap[i]->data), i, RECORD_MODE);
+ if (!mRecordHeap[i]) {
+ LOGE("ERR(%s): Record heap[%d] creation fail", __func__, i);
+ return UNKNOWN_ERROR;
+ }
+ }
+
+ LOGV("mRecordHeaps alloc done");
+
+ 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__);
+ LOGV("%s : %d", __func__, mPreviewRunning);
+
+ return mRecordRunning;
+}
+
+void CameraHardwareSec::releaseRecordingFrame(const void *opaque)
+{
+ int i;
+ for (i = 0; i < MAX_BUFFERS; i++)
+ if ((char *)mRecordHeap[i]->data == (char *)opaque)
+ break;
+
+ mSecCamera->releaseRecordFrame(i);
+}
+
+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();
+
+#ifdef GAIA_FW_BETA
+ if (mMsgEnabled & CAMERA_MSG_FOCUS)
+ mNotifyCb(CAMERA_MSG_FOCUS, false, 0, mCallbackCookie);
+
+ //LOGV("%s : exiting with no error", __func__);
+ return NO_ERROR;
+#else
+
+#ifdef AF_SUPPORT
+ LOGV("%s : calling setAutoFocus", __func__);
+ if (mSecCamera->setAutofocus() < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setAutofocus()", __func__);
+ return UNKNOWN_ERROR;
+ }
+
+ af_status = mSecCamera->getAutoFocusResult();
+#else
+ sleep(1);
+ af_status = 0x02;
+#endif
+
+ 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;
+#endif
+}
+
+status_t CameraHardwareSec::autoFocus()
+{
+ LOGV("%s :", __func__);
+ /* signal autoFocusThread to run once */
+ mFocusCondition.signal();
+ return NO_ERROR;
+}
+
+status_t CameraHardwareSec::cancelAutoFocus()
+{
+ LOGV("%s :", __func__);
+#ifndef GAIA_FW_BETA
+
+ if (mSecCamera->cancelAutofocus() < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->cancelAutofocus()", __func__);
+ return UNKNOWN_ERROR;
+ }
+#endif
+ 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", 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]", 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]", 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",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;
+
+ 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;
+#ifdef JPEG_FROM_SENSOR
+ if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK)
+ mJpegHeapSize = cap_frame_size * SecCamera::getJpegRatio();
+ else
+#endif
+ mJpegHeapSize = cap_frame_size;
+
+ //sp<MemoryBase> buffer = new MemoryBase(mRawHeap, 0, mPostViewSize + 8);
+
+ LOGV("[5B] mPostViewWidth = %d mPostViewHeight = %d\n",mPostViewWidth,mPostViewHeight);
+
+ camera_memory_t *JpegHeap = mGetMemoryCb(-1, mJpegHeapSize, 1, 0);
+#ifndef GAIA_FW_BETA
+ sp<MemoryHeapBase> PostviewHeap = new MemoryHeapBaseIon(mPostViewSize);
+ sp<MemoryHeapBase> ThumbnailHeap = new MemoryHeapBaseIon(mThumbSize);
+#else
+ sp<MemoryHeapBase> PostviewHeap = new MemoryHeapBase(mPostViewSize);
+ sp<MemoryHeapBase> ThumbnailHeap = new MemoryHeapBase(mThumbSize);
+#endif
+
+ if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
+ 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
+#ifdef JPEG_FROM_SENSOR
+ 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;
+ }
+ } else {
+#endif
+ if (mMsgEnabled & CAMERA_MSG_SHUTTER)
+ mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
+ if (mSecCamera->getSnapshotAndJpeg((unsigned char*)PostviewHeap->base(),
+ (unsigned char*)JpegHeap->data, &output_size) < 0) {
+ mStateLock.lock();
+ mCaptureInProgress = false;
+ mStateLock.unlock();
+ JpegHeap->release(JpegHeap);
+ return UNKNOWN_ERROR;
+ }
+ LOGI("snapshotandjpeg done");
+#ifdef JPEG_FROM_SENSOR
+ }
+#endif
+ }
+
+ int JpegImageSize, JpegExifSize;
+ bool isLSISensor = false;
+
+#ifdef JPEG_FROM_SENSOR
+ if (mSecCamera->getCameraId() == SecCamera::CAMERA_ID_BACK) {
+ LOGV("%s, %s", __func__, (const char*)mCameraSensorName); //to check sensor name
+ isLSISensor = !strncmp((const char*)mCameraSensorName, "S5K4ECGX", 8);
+ if (isLSISensor) {
+ LOGI("== Camera Sensor Detect %s - Samsung LSI SOC 5M ==", mCameraSensorName);
+ // LSI 5M SOC
+ if (!SplitFrame(jpeg_data, SecCamera::getInterleaveDataSize(),
+ SecCamera::getJpegLineLength(),
+ mPostViewWidth * 2, mPostViewWidth,
+ JpegHeap->data, &JpegImageSize,
+ PostviewHeap->base(), &mPostViewSize)) {
+ JpegHeap->release(JpegHeap);
+ return UNKNOWN_ERROR;
+ }
+ } else {
+ LOGI("== Camera Sensor Detect %s Sony SOC 5M ==", mCameraSensorName);
+ decodeInterleaveData(jpeg_data,
+ SecCamera::getInterleaveDataSize(),
+ mPostViewWidth, mPostViewHeight,
+ &JpegImageSize, JpegHeap->data, PostviewHeap->base());
+ }
+ } else
+#endif
+ JpegImageSize = static_cast<int>(output_size);
+
+ scaleDownYuv422((char *)mSecCamera->getPictureVaddr(), mPostViewWidth, mPostViewHeight,
+ (char *)ThumbnailHeap->base(), mThumbWidth, mThumbHeight);
+
+#ifdef GAIA_FW_BETA
+ int rawHeapSize = mPostViewSize;
+ LOGV("mRawHeap : MemoryHeapBase(previewHeapSize(%d))", rawHeapSize);
+ mRawHeap = mGetMemoryCb((int)mSecCamera->getCameraFd(), rawHeapSize, 1, 0);
+ if (!mRawHeap)
+ LOGE("ERR(%s): Raw heap creation fail", __func__);
+
+ if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE)
+ mDataCb(CAMERA_MSG_RAW_IMAGE, mRawHeap, 0, NULL, mCallbackCookie);
+#endif
+
+ mStateLock.lock();
+ mCaptureInProgress = false;
+ mStateLock.unlock();
+
+ if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
+ camera_memory_t *ExifHeap =
+ mGetMemoryCb(-1, EXIF_FILE_SIZE + mThumbSize, 1, 0);
+
+ JpegExifSize = mSecCamera->getExif((unsigned char *)ExifHeap->data,
+ (unsigned char *)ThumbnailHeap->base());
+ LOGV("JpegExifSize=%d", JpegExifSize);
+
+ if (JpegExifSize < 0) {
+ ret = UNKNOWN_ERROR;
+ goto out;
+ }
+
+ int mJpegHeapSize_out = JpegImageSize + JpegExifSize;
+ camera_memory_t *JpegHeap_out = mGetMemoryCb(-1, mJpegHeapSize_out, 1, 0);
+
+ unsigned char *ExifStart = (unsigned char *)JpegHeap_out->data + 2;
+ unsigned char *ImageStart = ExifStart + JpegExifSize;
+
+ memcpy(JpegHeap_out->data, JpegHeap->data, 2);
+ memcpy(ExifStart, ExifHeap->data, JpegExifSize);
+ memcpy(ImageStart, JpegHeap->data + 2, JpegImageSize - 2);
+
+ mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, JpegHeap_out, 0, NULL, mCallbackCookie);
+
+ if (ExifHeap) {
+ ExifHeap->release(ExifHeap);
+ ExifHeap = 0;
+ }
+
+ if (JpegHeap_out) {
+ JpegHeap_out->release(JpegHeap_out);
+ JpegHeap_out = 0;
+ }
+ }
+
+ LOGV("%s : pictureThread end", __func__);
+
+out:
+ if (JpegHeap) {
+ JpegHeap->release(JpegHeap);
+ JpegHeap = 0;
+ }
+
+ if (mRawHeap) {
+ mRawHeap->release(mRawHeap);
+ mRawHeap = 0;
+ }
+
+ return ret;
+}
+
+status_t CameraHardwareSec::takePicture()
+{
+ LOGV("%s :", __func__);
+
+ stopPreview();
+
+ Mutex::Autolock lock(mStateLock);
+ if (mCaptureInProgress) {
+ LOGE("%s : capture already in progress", __func__);
+ return INVALID_OPERATION;
+ }
+
+ if (mPictureThread->run("CameraPictureThread", PRIORITY_DEFAULT) != NO_ERROR) {
+ LOGE("%s : couldn't run picture thread", __func__);
+ return INVALID_OPERATION;
+ }
+ mCaptureInProgress = true;
+
+ 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");
+ 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");
+ 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
+ interleave_ptr++;
+ i += 4;
+ } else if ((*interleave_ptr & 0xFFFF) == 0x05FF) {
+ // Start-code of YUV Data
+ 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
+ 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;
+}
+
+status_t CameraHardwareSec::setParameters(const CameraParameters& params)
+{
+ LOGV("%s :", __func__);
+#ifndef GAIA_FW_BETA
+ int Internal_is = !strncmp((const char*)mSecCamera->getCameraSensorName(), "ISP Camera", 10);
+#else
+ int Internal_is = 0;
+#endif
+ 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. we can't wait because
+ * that would cause deadlock with the callbacks
+ */
+ mStateLock.lock();
+ if (mCaptureInProgress) {
+ mStateLock.unlock();
+ LOGE("%s : capture in progress, not allowed", __func__);
+ return UNKNOWN_ERROR;
+ }
+ mStateLock.unlock();
+
+ // preview size
+#ifdef GAIA_FW_BETA
+ int new_preview_width = 1920;
+ int new_preview_height = 1080;
+#else
+ int new_preview_width = 0;
+ int new_preview_height = 0;
+ params.getPreviewSize(&new_preview_width, &new_preview_height);
+#endif
+ 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 (0 < new_preview_width && 0 < new_preview_height &&
+ new_str_preview_format != NULL &&
+ isSupportedPreviewSize(new_preview_width, new_preview_height)) {
+ int new_preview_format = 0;
+
+ mFrameSizeDelta = 16;
+ if (!strcmp(new_str_preview_format,
+ CameraParameters::PIXEL_FORMAT_RGB565)) {
+ new_preview_format = V4L2_PIX_FMT_RGB565;
+ mFrameSizeDelta = 0;
+ }
+ else if (!strcmp(new_str_preview_format,
+ CameraParameters::PIXEL_FORMAT_RGBA8888)) {
+ new_preview_format = V4L2_PIX_FMT_RGB32;
+ mFrameSizeDelta = 0;
+ }
+ else if (!strcmp(new_str_preview_format,
+ CameraParameters::PIXEL_FORMAT_YUV420SP))
+ new_preview_format = V4L2_PIX_FMT_NV21;
+ else if (!strcmp(new_str_preview_format,
+ CameraParameters::PIXEL_FORMAT_YUV420P))
+ new_preview_format = V4L2_PIX_FMT_YVU420M;
+
+ else if (!strcmp(new_str_preview_format, "yuv420sp_custom"))
+ new_preview_format = V4L2_PIX_FMT_NV12T;
+ else if (!strcmp(new_str_preview_format, "yuv422i"))
+ new_preview_format = V4L2_PIX_FMT_YUYV;
+ else if (!strcmp(new_str_preview_format, "yuv422p"))
+ new_preview_format = V4L2_PIX_FMT_YUV422P;
+ else
+ new_preview_format = V4L2_PIX_FMT_NV21; //for 3rd party
+
+ int current_preview_width, current_preview_height, current_frame_size;
+ mSecCamera->getPreviewSize(¤t_preview_width,
+ ¤t_preview_height,
+ ¤t_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;
+ }
+
+#ifndef GAIA_FW_BETA
+ 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);
+ }
+ }
+
+ // JPEG thumbnail quality
+ int new_jpeg_thumbnail_quality = params.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
+ LOGV("%s : new_jpeg_thumbnail_quality %d", __func__, new_jpeg_thumbnail_quality);
+ /* we ignore bad values */
+ if (new_jpeg_thumbnail_quality >=1 && new_jpeg_thumbnail_quality <= 100) {
+ if (mSecCamera->setJpegThumbnailQuality(new_jpeg_thumbnail_quality) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setJpegThumbnailQuality(quality(%d))",
+ __func__, new_jpeg_thumbnail_quality);
+ ret = UNKNOWN_ERROR;
+ } else
+ mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY, new_jpeg_thumbnail_quality);
+ }
+
+ // 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()) {
+ if (mSecCamera->setFrameRate(new_frame_rate) < 0){
+ LOGE("ERR(%s):Fail on mSecCamera->setFrameRate(%d)", __func__, new_frame_rate);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.setPreviewFrameRate(new_frame_rate);
+ }
+ }
+
+ // 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", __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_brightness = params.getInt("brightness");
+ int max_brightness = params.getInt("brightness-max");
+ int min_brightness = params.getInt("brightness-min");
+ LOGV("%s : new_brightness %d", __func__, new_brightness);
+ if ((min_brightness <= new_brightness) &&
+ (max_brightness >= new_brightness)) {
+ if (mSecCamera->setBrightness(new_brightness) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setBrightness(brightness(%d))", __func__, new_brightness);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set("brightness", new_brightness);
+ }
+ }
+
+ // saturation
+ int new_saturation = params.getInt("saturation");
+ int max_saturation = params.getInt("saturation-max");
+ int min_saturation = params.getInt("saturation-min");
+ LOGV("%s : new_saturation %d", __func__, new_saturation);
+ if ((min_saturation <= new_saturation) &&
+ (max_saturation >= new_saturation)) {
+ if (mSecCamera->setSaturation(new_saturation) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setSaturation(saturation(%d))", __func__, new_saturation);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set("saturation", new_saturation);
+ }
+ }
+
+ // sharpness
+ int new_sharpness = params.getInt("sharpness");
+ int max_sharpness = params.getInt("sharpness-max");
+ int min_sharpness = params.getInt("sharpness-min");
+ LOGV("%s : new_sharpness %d", __func__, new_sharpness);
+ if ((min_sharpness <= new_sharpness) &&
+ (max_sharpness >= new_sharpness)) {
+ if (mSecCamera->setSharpness(new_sharpness) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setSharpness(sharpness(%d))", __func__, new_sharpness);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set("sharpness", new_sharpness);
+ }
+ }
+
+ // hue
+ int new_hue = params.getInt("hue");
+ int max_hue = params.getInt("hue-max");
+ int min_hue = params.getInt("hue-min");
+ LOGV("%s : new_hue %d", __func__, new_hue);
+ if ((min_hue <= new_hue) &&
+ (max_hue >= new_hue)) {
+ if (mSecCamera->setHue(new_hue) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setHue(hue(%d))", __func__, new_hue);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set("hue", new_hue);
+ }
+ }
+
+ // exposure
+ 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->setExposure(new_exposure_compensation) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setExposure(exposure(%d))", __func__, new_exposure_compensation);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_EXPOSURE_COMPENSATION, new_exposure_compensation);
+ }
+ }
+
+ // ISO
+ const char *new_iso_str = params.get("iso");
+ LOGV("%s : new_iso_str %s", __func__, new_iso_str);
+ if (new_iso_str != NULL) {
+ int new_iso = -1;
+
+ if (!strcmp(new_iso_str, "auto")) {
+ if (Internal_is)
+ new_iso = IS_ISO_AUTO;
+ else
+ new_iso = ISO_AUTO;
+ } else if (!strcmp(new_iso_str, "50")) {
+ if (Internal_is)
+ new_iso = IS_ISO_50;
+ else
+ new_iso = ISO_50;
+ } else if (!strcmp(new_iso_str, "100")) {
+ if (Internal_is)
+ new_iso = IS_ISO_100;
+ else
+ new_iso = ISO_100;
+ } else if (!strcmp(new_iso_str, "200")) {
+ if (Internal_is)
+ new_iso = IS_ISO_200;
+ else
+ new_iso = ISO_200;
+ } else if (!strcmp(new_iso_str, "400")) {
+ if (Internal_is)
+ new_iso = IS_ISO_400;
+ else
+ new_iso = ISO_400;
+ } else if (!strcmp(new_iso_str, "800")) {
+ if (Internal_is)
+ new_iso = IS_ISO_800;
+ else
+ new_iso = ISO_800;
+ } else if (!strcmp(new_iso_str, "1600")) {
+ if (Internal_is)
+ new_iso = IS_ISO_1600;
+ else
+ new_iso = ISO_1600;
+ } else {
+ LOGE("ERR(%s):Invalid iso value(%s)", __func__, new_iso_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_iso) {
+ if (mSecCamera->setISO(new_iso) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setISO(iso(%d))", __func__, new_iso);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set("iso", new_iso_str);
+ }
+ }
+ }
+
+ // 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)) {
+ if (Internal_is)
+ new_white = IS_AWB_AUTO;
+ else
+ new_white = WHITE_BALANCE_AUTO;
+ } else if (!strcmp(new_white_str,
+ CameraParameters::WHITE_BALANCE_DAYLIGHT)) {
+ if (Internal_is)
+ new_white = IS_AWB_DAYLIGHT;
+ else
+ new_white = WHITE_BALANCE_SUNNY;
+ } else if (!strcmp(new_white_str,
+ CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT)) {
+ if (Internal_is)
+ new_white = IS_AWB_CLOUDY;
+ else
+ new_white = WHITE_BALANCE_CLOUDY;
+ } else if (!strcmp(new_white_str,
+ CameraParameters::WHITE_BALANCE_FLUORESCENT)) {
+ if (Internal_is)
+ new_white = IS_AWB_FLUORESCENT;
+ else
+ new_white = WHITE_BALANCE_FLUORESCENT;
+ } else if (!strcmp(new_white_str,
+ CameraParameters::WHITE_BALANCE_INCANDESCENT)) {
+ if (Internal_is)
+ new_white = IS_AWB_TUNGSTEN;
+ else
+ 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);
+ }
+ }
+ }
+
+ // Metering
+ const char *new_metering_str = params.get("metering");
+ LOGV("%s : new_metering_str %s", __func__, new_metering_str);
+ if (new_metering_str != NULL) {
+ int new_metering = -1;
+
+ if (!strcmp(new_metering_str, "center")) {
+ if (Internal_is)
+ new_metering = IS_METERING_AVERAGE;
+ else
+ new_metering = METERING_CENTER;
+ } else if (!strcmp(new_metering_str, "spot")) {
+ if (Internal_is)
+ new_metering = IS_METERING_SPOT;
+ else
+ new_metering = METERING_SPOT;
+ } else if (!strcmp(new_metering_str, "matrix")) {
+ if (Internal_is)
+ new_metering = IS_METERING_MATRIX;
+ else
+ new_metering = METERING_MATRIX;
+ } else {
+ LOGE("ERR(%s):Invalid metering value(%s)", __func__, new_metering_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_metering) {
+ if (mSecCamera->setMetering(new_metering) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setMetering(metering(%d))", __func__, new_metering);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set("metering", new_metering_str);
+ }
+ }
+ }
+
+ // AFC
+ const char *new_antibanding_str = params.get(CameraParameters::KEY_ANTIBANDING);
+ LOGV("%s : new_antibanding_str %s", __func__, new_antibanding_str);
+ if (new_antibanding_str != NULL) {
+ int new_antibanding = -1;
+
+ if (!strcmp(new_antibanding_str, CameraParameters::ANTIBANDING_AUTO)) {
+ if (Internal_is)
+ new_antibanding = IS_AFC_AUTO;
+ else
+ new_antibanding = ANTI_BANDING_AUTO;
+ } else if (!strcmp(new_antibanding_str, CameraParameters::ANTIBANDING_50HZ)) {
+ if (Internal_is)
+ new_antibanding = IS_AFC_MANUAL_50HZ;
+ else
+ new_antibanding = ANTI_BANDING_50HZ;
+ } else if (!strcmp(new_antibanding_str, CameraParameters::ANTIBANDING_60HZ)) {
+ if (Internal_is)
+ new_antibanding = IS_AFC_MANUAL_60HZ;
+ else
+ new_antibanding = ANTI_BANDING_60HZ;
+ } else if (!strcmp(new_antibanding_str, CameraParameters::ANTIBANDING_OFF)) {
+ if (Internal_is)
+ new_antibanding = IS_AFC_DISABLE;
+ else
+ new_antibanding = ANTI_BANDING_OFF;
+ } else {
+ LOGE("ERR(%s):Invalid antibanding value(%s)", __func__, new_antibanding_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_antibanding) {
+ if (mSecCamera->setAntiBanding(new_antibanding) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setAntiBanding(antibanding(%d))", __func__, new_antibanding);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set(CameraParameters::KEY_ANTIBANDING, new_antibanding_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(¤t_min_fps, ¤t_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;
+ }
+
+ if (new_scene_mode_str != NULL) {
+ int new_scene_mode = -1;
+
+ const char *new_flash_mode_str = params.get(CameraParameters::KEY_FLASH_MODE);
+ const char *new_focus_mode_str;
+
+ new_focus_mode_str = params.get(CameraParameters::KEY_FOCUS_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;
+ } 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;
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_LANDSCAPE)) {
+ new_scene_mode = SCENE_MODE_LANDSCAPE;
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_SPORTS)) {
+ new_scene_mode = SCENE_MODE_SPORTS;
+ } 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;
+ } 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;
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_SUNSET)) {
+ new_scene_mode = SCENE_MODE_SUNSET;
+ } 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");
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_FIREWORKS)) {
+ new_scene_mode = SCENE_MODE_FIREWORKS;
+ } else if (!strcmp(new_scene_mode_str,
+ CameraParameters::SCENE_MODE_CANDLELIGHT)) {
+ new_scene_mode = SCENE_MODE_CANDLE_LIGHT;
+ } 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);
+ }
+ }
+ }
+
+ // 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)) {
+ if (Internal_is)
+ new_image_effect = IS_IMAGE_EFFECT_DISABLE;
+ else
+ new_image_effect = IMAGE_EFFECT_NONE;
+ } else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_MONO)) {
+ if (Internal_is)
+ new_image_effect = IS_IMAGE_EFFECT_MONOCHROME;
+ else
+ new_image_effect = IMAGE_EFFECT_BNW;
+ } else if (!strcmp(new_image_effect_str, CameraParameters::EFFECT_SEPIA)) {
+ if (Internal_is)
+ new_image_effect = IS_IMAGE_EFFECT_SEPIA;
+ else
+ 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)) {
+ if (Internal_is)
+ new_image_effect = IS_IMAGE_EFFECT_NEGATIVE_MONO;
+ else
+ LOGW("WARN(%s):Invalid effect value (%s)", __func__, new_image_effect_str);
+ } 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);
+ }
+ }
+ }
+
+ //contrast
+ const char *new_contrast_str = params.get("contrast");
+ LOGV("%s : new_contrast_str %s", __func__, new_contrast_str);
+ if (new_contrast_str != NULL) {
+ int new_contrast = -1;
+
+ if (!strcmp(new_contrast_str, "auto")) {
+ if (Internal_is)
+ new_contrast = IS_CONTRAST_AUTO;
+ else
+ LOGW("WARN(%s):Invalid contrast value (%s)", __func__, new_contrast_str);
+ } else if (!strcmp(new_contrast_str, "-2")) {
+ if (Internal_is)
+ new_contrast = IS_CONTRAST_MINUS_2;
+ else
+ new_contrast = CONTRAST_MINUS_2;
+ } else if (!strcmp(new_contrast_str, "-1")) {
+ if (Internal_is)
+ new_contrast = IS_CONTRAST_MINUS_1;
+ else
+ new_contrast = CONTRAST_MINUS_1;
+ } else if (!strcmp(new_contrast_str, "0")) {
+ if (Internal_is)
+ new_contrast = IS_CONTRAST_DEFAULT;
+ else
+ new_contrast = CONTRAST_DEFAULT;
+ } else if (!strcmp(new_contrast_str, "1")) {
+ if (Internal_is)
+ new_contrast = IS_CONTRAST_PLUS_1;
+ else
+ new_contrast = CONTRAST_PLUS_1;
+ } else if (!strcmp(new_contrast_str, "2")) {
+ if (Internal_is)
+ new_contrast = IS_CONTRAST_PLUS_2;
+ else
+ new_contrast = CONTRAST_PLUS_2;
+ } else {
+ LOGE("ERR(%s):Invalid contrast value(%s)", __func__, new_contrast_str);
+ ret = UNKNOWN_ERROR;
+ }
+
+ if (0 <= new_contrast) {
+ if (mSecCamera->setContrast(new_contrast) < 0) {
+ LOGE("ERR(%s):Fail on mSecCamera->setContrast(contrast(%d))", __func__, new_contrast);
+ ret = UNKNOWN_ERROR;
+ } else {
+ mParameters.set("contrast", new_contrast_str);
+ }
+ }
+ }
+
+ //WDR
+ int new_wdr = params.getInt("wdr");
+ LOGV("%s : new_wdr %d", __func__, new_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 = 0;
+ int new_recording_height = 0;
+ params.getVideoSize(&new_recording_width, &new_recording_height);
+ LOGV("new_recording_width (%d) new_recording_height (%d)",
+ new_recording_width, new_recording_height);
+
+ int current_recording_width, current_recording_height;
+ mSecCamera->getRecordingSize(¤t_recording_width, ¤t_recording_height);
+ LOGV("current_recording_width (%d) current_recording_height (%d)",
+ current_recording_width, current_recording_height);
+
+ if (0 < new_recording_width && 0 < new_recording_height) {
+ if (current_recording_width != new_recording_width ||
+ current_recording_height != 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 (Internal_is && mPreviewWindow && mPreviewRunning) {
+ mSecCamera->setRecording(1);
+ stopPreview();
+ startPreview();
+ mSecCamera->setRecording(0);
+ }
+ }
+ }
+ mParameters.setVideoSize(new_recording_width, new_recording_height);
+ } 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;
+ }
+
+ // 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);
+#endif
+
+ 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;
+ }
+ for(int i = 0; i < BUFFER_COUNT_FOR_ARRAY; i++) {
+ if (mRecordHeap[i]) {
+ mRecordHeap[i]->release(mRecordHeap[i]);
+ mRecordHeap[i] = 0;
+ }
+ }
+
+ /* close after all the heaps are cleared since those
+ * could have dup'd our file descriptor.
+ */
+ mSecCamera->DestroyCamera();
+}
+
+static CameraInfo sCameraInfo[] = {
+ {
+ CAMERA_FACING_BACK,
+ 0, /* orientation */
+ },
+ {
+ CAMERA_FACING_FRONT,
+ 0, /* orientation */
+ }
+};
+
+status_t CameraHardwareSec::storeMetaDataInBuffers(bool enable)
+{
+ if (!enable) {
+ LOGE("Non-metadata buffer mode is not supported!");
+ return INVALID_OPERATION;
+ }
+ return OK;
+}
+
+/** 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());
+}
+
+static 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 : "orion 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/exynos5/hal/libcamera/SecCameraHWInterface.h b/exynos5/hal/libcamera/SecCameraHWInterface.h
new file mode 100644
index 0000000..6be8ae2
--- /dev/null
+++ b/exynos5/hal/libcamera/SecCameraHWInterface.h
@@ -0,0 +1,219 @@
+/*
+**
+** 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
+
+#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>
+#include <binder/MemoryHeapBaseIon.h>
+#include <sec_utils_v4l2.h>
+
+#include "gralloc_priv.h"
+
+#define BUFFER_COUNT_FOR_GRALLOC (MAX_BUFFERS + 4)
+#define BUFFER_COUNT_FOR_ARRAY (MAX_BUFFERS)
+
+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();
+
+ 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();
+ mHardware->mSecCamera->endSnapshot();
+ 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;
+ /* 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 threading state */
+ mutable Mutex mStateLock;
+
+ CameraParameters mParameters;
+ CameraParameters mInternalParameters;
+
+ int mFrameSizeDelta;
+ camera_memory_t *mPreviewHeap;
+ camera_memory_t *mRawHeap;
+ camera_memory_t *mRecordHeap[BUFFER_COUNT_FOR_ARRAY];
+
+ buffer_handle_t *mBufferHandle[BUFFER_COUNT_FOR_ARRAY];
+ int mStride[BUFFER_COUNT_FOR_ARRAY];
+
+
+ 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
diff --git a/exynos5/hal/libcamera/mediactl.cpp b/exynos5/hal/libcamera/mediactl.cpp
new file mode 100644
index 0000000..468acc4
--- /dev/null
+++ b/exynos5/hal/libcamera/mediactl.cpp
@@ -0,0 +1,668 @@
+/*
+ * Media controller interface library
+ *
+ * Copyright (C) 2010-2011 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//#include "config.h"
+#define LOG_NDEBUG 0
+#define LOG_TAG "Mediactl"
+
+#include <utils/Log.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+
+#include <poll.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <linux/videodev2.h>
+#include <media.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+
+#include "mediactl.h"
+
+#define KF_MSG 0x1
+#define KF_ANY 0x2
+
+#define perror_exit(cond, func) \
+ if (cond) { \
+ fprintf(stderr, "[%s:%d]: ", __func__, __LINE__);\
+ perror(func);\
+ exit(EXIT_FAILURE);\
+ }
+
+struct media_pad *media_entity_remote_source(struct media_pad *pad)
+{
+ unsigned int i;
+
+ if (!(pad->flags & MEDIA_PAD_FL_SINK))
+ return NULL;
+
+ for (i = 0; i < pad->entity->num_links; ++i) {
+ struct media_link *link = &pad->entity->links[i];
+
+ if (!(link->flags & MEDIA_LNK_FL_ENABLED))
+ continue;
+
+ if (link->sink == pad)
+ return link->source;
+ }
+
+ return NULL;
+}
+
+struct media_entity *media_get_entity_by_name(struct media_device *media,
+ const char *name, size_t length)
+{
+ unsigned int i;
+ struct media_entity *entity;
+ entity = (struct media_entity*)calloc(1, sizeof(struct media_entity));
+ for (i = 0; i < media->entities_count; ++i) {
+ entity = &media->entities[i];
+
+ if (strncmp(entity->info.name, name, length) == 0)
+ return entity;
+ }
+
+ return NULL;
+}
+
+struct media_entity *media_get_entity_by_id(struct media_device *media,
+ __u32 id)
+{
+ unsigned int i;
+
+ for (i = 0; i < media->entities_count; ++i) {
+ struct media_entity *entity = &media->entities[i];
+
+ if (entity->info.id == id)
+ return entity;
+ }
+
+ return NULL;
+}
+
+int media_setup_link(struct media_device *media,
+ struct media_pad *source,
+ struct media_pad *sink,
+ __u32 flags)
+{
+ struct media_link *link;
+ struct media_link_desc ulink;
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < source->entity->num_links; i++) {
+ link = &source->entity->links[i];
+
+ if (link->source->entity == source->entity &&
+ link->source->index == source->index &&
+ link->sink->entity == sink->entity &&
+ link->sink->index == sink->index)
+ break;
+ }
+
+ if (i == source->entity->num_links) {
+ LOGE("%s: Link not found", __func__);
+ return -ENOENT;
+ }
+
+ /* source pad */
+ ulink.source.entity = source->entity->info.id;
+ ulink.source.index = source->index;
+ ulink.source.flags = MEDIA_PAD_FL_SOURCE;
+
+ /* sink pad */
+ ulink.sink.entity = sink->entity->info.id;
+ ulink.sink.index = sink->index;
+ ulink.sink.flags = MEDIA_PAD_FL_SINK;
+
+ ulink.flags = flags | (link->flags & MEDIA_LNK_FL_IMMUTABLE);
+
+ ret = ioctl(media->fd, MEDIA_IOC_SETUP_LINK, &ulink);
+ if (ret == -1) {
+ LOGE("%s: Unable to setup link (%s)",
+ __func__, strerror(errno));
+ return -errno;
+ }
+
+ link->flags = ulink.flags;
+ link->twin->flags = ulink.flags;
+ return 0;
+}
+
+int media_reset_links(struct media_device *media)
+{
+ unsigned int i, j;
+ int ret;
+
+ for (i = 0; i < media->entities_count; ++i) {
+ struct media_entity *entity = &media->entities[i];
+
+ for (j = 0; j < entity->num_links; j++) {
+ struct media_link *link = &entity->links[j];
+
+ if (link->flags & MEDIA_LNK_FL_IMMUTABLE ||
+ link->source->entity != entity)
+ continue;
+
+ ret = media_setup_link(media, link->source, link->sink,
+ link->flags & ~MEDIA_LNK_FL_ENABLED);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static struct media_link *media_entity_add_link(struct media_entity *entity)
+{
+ if (entity->num_links >= entity->max_links) {
+ struct media_link *links = entity->links;
+ unsigned int max_links = entity->max_links * 2;
+ unsigned int i;
+
+ links = (struct media_link*)realloc(links, max_links * sizeof *links);
+ if (links == NULL)
+ return NULL;
+
+ for (i = 0; i < entity->num_links; ++i)
+ links[i].twin->twin = &links[i];
+
+ entity->max_links = max_links;
+ entity->links = links;
+ }
+
+ return &entity->links[entity->num_links++];
+}
+
+static int media_enum_links(struct media_device *media)
+{
+ LOGV("%s: start", __func__);
+ __u32 id;
+ int ret = 0;
+
+ for (id = 1; id <= media->entities_count; id++) {
+ struct media_entity *entity = &media->entities[id - 1];
+ struct media_links_enum links;
+ unsigned int i;
+
+ links.entity = entity->info.id;
+ links.pads = (struct media_pad_desc*)malloc(entity->info.pads * sizeof(struct media_pad_desc));
+ links.links = (struct media_link_desc*)malloc(entity->info.links * sizeof(struct media_link_desc));
+
+ if (ioctl(media->fd, MEDIA_IOC_ENUM_LINKS, &links) < 0) {
+ LOGE(
+ "%s: Unable to enumerate pads and links (%s).",
+ __func__, strerror(errno));
+ free(links.pads);
+ free(links.links);
+ return -errno;
+ }
+
+ for (i = 0; i < entity->info.pads; ++i) {
+ entity->pads[i].entity = entity;
+ entity->pads[i].index = links.pads[i].index;
+ entity->pads[i].flags = links.pads[i].flags;
+ }
+
+ for (i = 0; i < entity->info.links; ++i) {
+ struct media_link_desc *link = &links.links[i];
+ struct media_link *fwdlink;
+ struct media_link *backlink;
+ struct media_entity *source;
+ struct media_entity *sink;
+
+ source = media_get_entity_by_id(media, link->source.entity);
+ sink = media_get_entity_by_id(media, link->sink.entity);
+ if (source == NULL || sink == NULL) {
+ LOGE(
+ "WARNING entity %u link %u from %u/%u to %u/%u is invalid!",
+ id, i, link->source.entity,
+ link->source.index,
+ link->sink.entity,
+ link->sink.index);
+ ret = -EINVAL;
+ } else {
+ fwdlink = media_entity_add_link(source);
+ fwdlink->source = &source->pads[link->source.index];
+ fwdlink->sink = &sink->pads[link->sink.index];
+ fwdlink->flags = link->flags;
+
+ backlink = media_entity_add_link(sink);
+ backlink->source = &source->pads[link->source.index];
+ backlink->sink = &sink->pads[link->sink.index];
+ backlink->flags = link->flags;
+
+ fwdlink->twin = backlink;
+ backlink->twin = fwdlink;
+ }
+ }
+
+ free(links.pads);
+ free(links.links);
+ }
+ return ret;
+}
+
+#ifdef HAVE_LIBUDEV
+
+#include <libudev.h>
+
+static inline int media_udev_open(struct udev **udev)
+{
+ *udev = udev_new();
+ if (*udev == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+static inline void media_udev_close(struct udev *udev)
+{
+ if (udev != NULL)
+ udev_unref(udev);
+}
+
+static int media_get_devname_udev(struct udev *udev,
+ struct media_entity *entity)
+{
+ struct udev_device *device;
+ dev_t devnum;
+ const char *p;
+ int ret = -ENODEV;
+
+ if (udev == NULL)
+ return -EINVAL;
+
+ devnum = makedev(entity->info.v4l.major, entity->info.v4l.minor);
+ LOGE("looking up device: %u:%u",
+ major(devnum), minor(devnum));
+ device = udev_device_new_from_devnum(udev, 'c', devnum);
+ if (device) {
+ p = udev_device_get_devnode(device);
+ if (p) {
+ strncpy(entity->devname, p, sizeof(entity->devname));
+ entity->devname[sizeof(entity->devname) - 1] = '\0';
+ }
+ ret = 0;
+ }
+
+ udev_device_unref(device);
+
+ return ret;
+}
+
+#else /* HAVE_LIBUDEV */
+
+struct udev;
+
+static inline int media_udev_open(struct udev **udev) { return 0; }
+
+static inline void media_udev_close(struct udev *udev) { }
+
+static inline int media_get_devname_udev(struct udev *udev,
+ struct media_entity *entity)
+{
+ return -ENOTSUP;
+}
+
+#endif /* HAVE_LIBUDEV */
+
+static int media_get_devname_sysfs(struct media_entity *entity)
+{
+ //struct stat devstat;
+ char devname[32];
+ char sysname[32];
+ char target[1024];
+ char *p;
+ int ret;
+
+ sprintf(sysname, "/sys/dev/char/%u:%u", entity->info.v4l.major,
+ entity->info.v4l.minor);
+
+ ret = readlink(sysname, target, sizeof(target));
+ if (ret < 0)
+ return -errno;
+
+ target[ret] = '\0';
+ p = strrchr(target, '/');
+ if (p == NULL)
+ return -EINVAL;
+
+ sprintf(devname, "/tmp/%s", p + 1);
+
+ ret = mknod(devname, 0666 | S_IFCHR, MKDEV(81, entity->info.v4l.minor));
+ strcpy(entity->devname, devname);
+
+ return 0;
+}
+
+int get_media_fd(struct media_device *media)
+{
+ ssize_t num;
+ int media_node;
+ char *ptr;
+ char media_buf[6];
+
+ LOGV("%s(%s)", __func__, MEDIA_DEV);
+
+ media->fd = open(MEDIA_DEV, O_RDWR, 0);
+ if( media->fd < 0) {
+ LOGE("Open sysfs media device failed, media->fd : 0x%p", media->fd);
+ return -1;
+ }
+ LOGV("media->fd : %p", media->fd);
+
+ return media->fd;
+
+}
+
+static int media_enum_entities(struct media_device *media)
+{
+ struct media_entity *entity;
+ unsigned int size;
+ __u32 id;
+ int ret;
+ entity = (struct media_entity*)calloc(1, sizeof(struct media_entity));
+ for (id = 0, ret = 0; ; id = entity->info.id) {
+ size = (media->entities_count + 1) * sizeof(*media->entities);
+ media->entities = (struct media_entity*)realloc(media->entities, size);
+
+ entity = &media->entities[media->entities_count];
+ memset(entity, 0, sizeof(*entity));
+ entity->fd = -1;
+ entity->info.id = id | MEDIA_ENT_ID_FLAG_NEXT;
+ entity->media = media;
+
+ ret = ioctl(media->fd, MEDIA_IOC_ENUM_ENTITIES, &entity->info);
+
+ if (ret < 0) {
+ ret = errno != EINVAL ? -errno : 0;
+ break;
+ }
+
+ /* Number of links (for outbound links) plus number of pads (for
+ * inbound links) is a good safe initial estimate of the total
+ * number of links.
+ */
+ entity->max_links = entity->info.pads + entity->info.links;
+
+ entity->pads = (struct media_pad*)malloc(entity->info.pads * sizeof(*entity->pads));
+ entity->links = (struct media_link*)malloc(entity->max_links * sizeof(*entity->links));
+ if (entity->pads == NULL || entity->links == NULL) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ media->entities_count++;
+
+ /* Find the corresponding device name. */
+ if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE &&
+ media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+ continue;
+
+ /* Fall back to get the device name via sysfs */
+ media_get_devname_sysfs(entity);
+ if (ret < 0)
+ LOGE("media_get_devname failed");
+ }
+
+ return ret;
+}
+
+static void media_debug_default(void *ptr, ...)
+{
+ va_list argptr;
+ va_start(argptr, ptr);
+ vprintf((const char*)ptr, argptr);
+ va_end(argptr);
+}
+
+void media_debug_set_handler(struct media_device *media,
+ void (*debug_handler)(void *, ...),
+ void *debug_priv)
+{
+ if (debug_handler) {
+ media->debug_handler = debug_handler;
+ media->debug_priv = debug_priv;
+ } else {
+ media->debug_handler = media_debug_default;
+ media->debug_priv = NULL;
+ }
+}
+
+struct media_device *media_open_debug(
+ const char *name, void (*debug_handler)(void *, ...),
+ void *debug_priv)
+{
+ struct media_device *media;
+ int ret;
+
+ media = (struct media_device*)calloc(1, sizeof(struct media_device));
+ if (media == NULL) {
+ LOGE("%s: media : %p", __func__, media);
+ return NULL;
+ }
+
+ media_debug_set_handler(media, debug_handler, debug_priv);
+
+ LOGV("Opening media device %s", name);
+ LOGV("%s: media : %p", __func__, media);
+
+ media->fd = get_media_fd(media);
+ if (media->fd < 0) {
+ media_close(media);
+ LOGE("%s: failed get_media_fd %s",
+ __func__, name);
+ return NULL;
+ }
+
+ LOGV("%s: media->fd : %p", __func__, media->fd);
+ ret = media_enum_entities(media);
+
+ if (ret < 0) {
+ LOGE(
+ "%s: Unable to enumerate entities for device %s (%s)",
+ __func__, name, strerror(-ret));
+ media_close(media);
+ return NULL;
+ }
+
+ LOGV("Found %u entities", media->entities_count);
+ LOGV("Enumerating pads and links");
+
+ ret = media_enum_links(media);
+ if (ret < 0) {
+ LOGE(
+ "%s: Unable to enumerate pads and linksfor device %s",
+ __func__, name);
+ media_close(media);
+ return NULL;
+ }
+
+ return media;
+}
+
+struct media_device *media_open(void)
+{
+ return media_open_debug(NULL, (void (*)(void *, ...))fprintf, stdout);
+}
+
+void media_close(struct media_device *media)
+{
+ unsigned int i;
+
+ if (media->fd != -1)
+ close(media->fd);
+
+ for (i = 0; i < media->entities_count; ++i) {
+ struct media_entity *entity = &media->entities[i];
+
+ free(entity->pads);
+ free(entity->links);
+ if (entity->fd != -1)
+ close(entity->fd);
+ }
+
+ free(media->entities);
+ free(media);
+}
+
+struct media_pad *media_parse_pad(struct media_device *media,
+ const char *p, char **endp)
+{
+ unsigned int entity_id, pad;
+ struct media_entity *entity;
+ char *end;
+
+ for (; isspace(*p); ++p);
+
+ if (*p == '"') {
+ for (end = (char *)p + 1; *end && *end != '"'; ++end);
+ if (*end != '"')
+ return NULL;
+
+ entity = media_get_entity_by_name(media, p + 1, end - p - 1);
+ if (entity == NULL)
+ return NULL;
+
+ ++end;
+ } else {
+ entity_id = strtoul(p, &end, 10);
+ entity = media_get_entity_by_id(media, entity_id);
+ if (entity == NULL)
+ return NULL;
+ }
+ for (; isspace(*end); ++end);
+
+ if (*end != ':')
+ return NULL;
+ for (p = end + 1; isspace(*p); ++p);
+
+ pad = strtoul(p, &end, 10);
+ for (p = end; isspace(*p); ++p);
+
+ if (pad >= entity->info.pads)
+ return NULL;
+
+ for (p = end; isspace(*p); ++p);
+ if (endp)
+ *endp = (char *)p;
+
+ return &entity->pads[pad];
+}
+
+struct media_link *media_parse_link(struct media_device *media,
+ const char *p, char **endp)
+{
+ struct media_link *link;
+ struct media_pad *source;
+ struct media_pad *sink;
+ unsigned int i;
+ char *end;
+
+ source = media_parse_pad(media, p, &end);
+ if (source == NULL)
+ return NULL;
+
+ if (end[0] != '-' || end[1] != '>')
+ return NULL;
+ p = end + 2;
+
+ sink = media_parse_pad(media, p, &end);
+ if (sink == NULL)
+ return NULL;
+
+ *endp = end;
+
+ for (i = 0; i < source->entity->num_links; i++) {
+ link = &source->entity->links[i];
+
+ if (link->source == source && link->sink == sink)
+ return link;
+ }
+
+ return NULL;
+}
+
+int media_parse_setup_link(struct media_device *media,
+ const char *p, char **endp)
+{
+ struct media_link *link;
+ __u32 flags;
+ char *end;
+
+ link = media_parse_link(media, p, &end);
+ if (link == NULL) {
+ LOGE(
+ "%s: Unable to parse link", __func__);
+ return -EINVAL;
+ }
+
+ p = end;
+ if (*p++ != '[') {
+ LOGE("Unable to parse link flags");
+ return -EINVAL;
+ }
+
+ flags = strtoul(p, &end, 10);
+ for (p = end; isspace(*p); p++);
+ if (*p++ != ']') {
+ LOGE("Unable to parse link flags");
+ return -EINVAL;
+ }
+
+ for (; isspace(*p); p++);
+ *endp = (char *)p;
+
+ LOGV(
+ "Setting up link %u:%u -> %u:%u [%u]",
+ link->source->entity->info.id, link->source->index,
+ link->sink->entity->info.id, link->sink->index,
+ flags);
+
+ return media_setup_link(media, link->source, link->sink, flags);
+}
+
+int media_parse_setup_links(struct media_device *media, const char *p)
+{
+ char *end;
+ int ret;
+
+ do {
+ ret = media_parse_setup_link(media, p, &end);
+ if (ret < 0)
+ return ret;
+
+ p = end + 1;
+ } while (*end == ',');
+
+ return *end ? -EINVAL : 0;
+}
diff --git a/exynos5/hal/libcamera/mediactl.h b/exynos5/hal/libcamera/mediactl.h
new file mode 100644
index 0000000..f28ce16
--- /dev/null
+++ b/exynos5/hal/libcamera/mediactl.h
@@ -0,0 +1,270 @@
+/*
+ * Media controller interface library
+ *
+ * Copyright (C) 2010-2011 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MEDIA_H__
+#define __MEDIA_H__
+
+#include <media.h>
+
+#define GAIA_FW_BETA 1
+
+#ifndef GAIA_FW_BETA
+#define MEDIA_DEV "/dev/media1" //M5MO : External ISP
+#else
+#define MEDIA_DEV "/dev/media2" //4E5 : Internal ISP
+#endif
+
+#define MEDIA_MINOR 0
+
+#define KF_MSG 0x1
+#define KF_ANY 0x2
+
+struct media_link {
+ struct media_pad *source;
+ struct media_pad *sink;
+ struct media_link *twin;
+ __u32 flags;
+ __u32 padding[3];
+};
+
+struct media_pad {
+ struct media_entity *entity;
+ __u32 index;
+ __u32 flags;
+ __u32 padding[3];
+};
+
+struct media_entity {
+ struct media_device *media;
+ struct media_entity_desc info;
+ struct media_pad *pads;
+ struct media_link *links;
+ unsigned int max_links;
+ unsigned int num_links;
+
+ char devname[32];
+ int fd;
+ __u32 padding[6];
+};
+
+struct media_device {
+ int fd;
+ struct media_entity *entities;
+ unsigned int entities_count;
+ void (*debug_handler)(void *, ...);
+ void *debug_priv;
+ __u32 padding[6];
+};
+
+#define media_dbg(media, ...) \
+ (media)->debug_handler((media)->debug_priv, __VA_ARGS__)
+
+/**
+ * @brief Set a handler for debug messages.
+ * @param media - device instance.
+ * @param debug_handler - debug message handler
+ * @param debug_priv - first argument to debug message handler
+ *
+ * Set a handler for debug messages that will be called whenever
+ * debugging information is to be printed. The handler expects an
+ * fprintf-like function.
+ */
+void media_debug_set_handler(
+ struct media_device *media, void (*debug_handler)(void *, ...),
+ void *debug_priv);
+
+/**
+ * @brief Open a media device with debugging enabled.
+ * @param name - name (including path) of the device node.
+ * @param debug_handler - debug message handler
+ * @param debug_priv - first argument to debug message handler
+ *
+ * Open the media device referenced by @a name and enumerate entities, pads and
+ * links.
+ *
+ * Calling media_open_debug() instead of media_open() is equivalent to
+ * media_open() and media_debug_set_handler() except that debugging is
+ * also enabled during media_open().
+ *
+ * @return A pointer to a newly allocated media_device structure instance on
+ * success and NULL on failure. The returned pointer must be freed with
+ * media_close when the device isn't needed anymore.
+ */
+struct media_device *media_open_debug(
+ const char *name, void (*debug_handler)(void *, ...),
+ void *debug_priv);
+
+/**
+ * @brief Open a media device.
+ * @param name - name (including path) of the device node.
+ *
+ * Open the media device referenced by @a name and enumerate entities, pads and
+ * links.
+ *
+ * @return A pointer to a newly allocated media_device structure instance on
+ * success and NULL on failure. The returned pointer must be freed with
+ * media_close when the device isn't needed anymore.
+ */
+struct media_device *media_open(void);
+
+/**
+ * @brief Close a media device.
+ * @param media - device instance.
+ *
+ * Close the @a media device instance and free allocated resources. Access to the
+ * device instance is forbidden after this function returns.
+ */
+void media_close(struct media_device *media);
+
+/**
+ * @brief Locate the pad at the other end of a link.
+ * @param pad - sink pad at one end of the link.
+ *
+ * Locate the source pad connected to @a pad through an enabled link. As only one
+ * link connected to a sink pad can be enabled at a time, the connected source
+ * pad is guaranteed to be unique.
+ *
+ * @return A pointer to the connected source pad, or NULL if all links connected
+ * to @a pad are disabled. Return NULL also if @a pad is not a sink pad.
+ */
+struct media_pad *media_entity_remote_source(struct media_pad *pad);
+
+/**
+ * @brief Get the type of an entity.
+ * @param entity - the entity.
+ *
+ * @return The type of @a entity.
+ */
+static inline unsigned int media_entity_type(struct media_entity *entity)
+{
+ return entity->info.type & MEDIA_ENT_TYPE_MASK;
+}
+
+/**
+ * @brief Find an entity by its name.
+ * @param media - media device.
+ * @param name - entity name.
+ * @param length - size of @a name.
+ *
+ * Search for an entity with a name equal to @a name.
+ *
+ * @return A pointer to the entity if found, or NULL otherwise.
+ */
+struct media_entity *media_get_entity_by_name(struct media_device *media,
+ const char *name, size_t length);
+
+/**
+ * @brief Find an entity by its ID.
+ * @param media - media device.
+ * @param id - entity ID.
+ *
+ * Search for an entity with an ID equal to @a id.
+ *
+ * @return A pointer to the entity if found, or NULL otherwise.
+ */
+struct media_entity *media_get_entity_by_id(struct media_device *media,
+ __u32 id);
+
+/**
+ * @brief Configure a link.
+ * @param media - media device.
+ * @param source - source pad at the link origin.
+ * @param sink - sink pad at the link target.
+ * @param flags - configuration flags.
+ *
+ * Locate the link between @a source and @a sink, and configure it by applying
+ * the new @a flags.
+ *
+ * Only the MEDIA_LINK_FLAG_ENABLED flag is writable.
+ *
+ * @return 0 on success, -1 on failure:
+ * -ENOENT: link not found
+ * - other error codes returned by MEDIA_IOC_SETUP_LINK
+ */
+int media_setup_link(struct media_device *media,
+ struct media_pad *source, struct media_pad *sink,
+ __u32 flags);
+
+/**
+ * @brief Reset all links to the disabled state.
+ * @param media - media device.
+ *
+ * Disable all links in the media device. This function is usually used after
+ * opening a media device to reset all links to a known state.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int media_reset_links(struct media_device *media);
+
+/**
+ * @brief Parse string to a pad on the media device.
+ * @param media - media device.
+ * @param p - input string
+ * @param endp - pointer to string where parsing ended
+ *
+ * Parse NULL terminated string describing a pad and return its struct
+ * media_pad instance.
+ *
+ * @return Pointer to struct media_pad on success, NULL on failure.
+ */
+struct media_pad *media_parse_pad(struct media_device *media,
+ const char *p, char **endp);
+
+/**
+ * @brief Parse string to a link on the media device.
+ * @param media - media device.
+ * @param p - input string
+ * @param endp - pointer to p where parsing ended
+ *
+ * Parse NULL terminated string p describing a link and return its struct
+ * media_link instance.
+ *
+ * @return Pointer to struct media_link on success, NULL on failure.
+ */
+struct media_link *media_parse_link(struct media_device *media,
+ const char *p, char **endp);
+
+/**
+ * @brief Parse string to a link on the media device and set it up.
+ * @param media - media device.
+ * @param p - input string
+ *
+ * Parse NULL terminated string p describing a link and its configuration
+ * and configure the link.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int media_parse_setup_link(struct media_device *media,
+ const char *p, char **endp);
+
+/**
+ * @brief Parse string to link(s) on the media device and set it up.
+ * @param media - media device.
+ * @param p - input string
+ *
+ * Parse NULL terminated string p describing link(s) separated by
+ * commas (,) and configure the link(s).
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int media_parse_setup_links(struct media_device *media, const char *p);
+
+#endif
diff --git a/exynos5/hal/libcamera/v4l2subdev.h b/exynos5/hal/libcamera/v4l2subdev.h
new file mode 100644
index 0000000..20e0557
--- /dev/null
+++ b/exynos5/hal/libcamera/v4l2subdev.h
@@ -0,0 +1,200 @@
+/*
+ * V4L2 subdev interface library
+ *
+ * Copyright (C) 2010-2011 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SUBDEV_H__
+#define __SUBDEV_H__
+
+#include <v4l2-subdev.h>
+
+struct media_entity;
+
+/**
+ * @brief Open a sub-device.
+ * @param entity - sub-device media entity.
+ *
+ * Open the V4L2 subdev device node associated with @a entity. The file
+ * descriptor is stored in the media_entity structure.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_open(struct media_entity *entity);
+
+/**
+ * @brief Close a sub-device.
+ * @param entity - sub-device media entity.
+ *
+ * Close the V4L2 subdev device node associated with the @a entity and opened by
+ * a previous call to v4l2_subdev_open() (either explicit or implicit).
+ */
+void v4l2_subdev_close(struct media_entity *entity);
+
+/**
+ * @brief Retrieve the format on a pad.
+ * @param entity - subdev-device media entity.
+ * @param format - format to be filled.
+ * @param pad - pad number.
+ * @param which - identifier of the format to get.
+ *
+ * Retrieve the current format on the @a entity @a pad and store it in the
+ * @a format structure.
+ *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to retrieve the try format stored
+ * in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to retrieve the current
+ * active format.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_get_format(struct media_entity *entity,
+ struct v4l2_mbus_framefmt *format, unsigned int pad,
+ enum v4l2_subdev_format_whence which);
+
+/**
+ * @brief Set the format on a pad.
+ * @param entity - subdev-device media entity.
+ * @param format - format.
+ * @param pad - pad number.
+ * @param which - identifier of the format to set.
+ *
+ * Set the format on the @a entity @a pad to @a format. The driver is allowed to
+ * modify the requested format, in which case @a format is updated with the
+ * modifications.
+ *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the try format stored in the
+ * file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to configure the device with an
+ * active format.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_set_format(struct media_entity *entity,
+ struct v4l2_mbus_framefmt *format, unsigned int pad,
+ enum v4l2_subdev_format_whence which);
+
+/**
+ * @brief Retrieve the crop rectangle on a pad.
+ * @param entity - subdev-device media entity.
+ * @param rect - crop rectangle to be filled.
+ * @param pad - pad number.
+ * @param which - identifier of the format to get.
+ *
+ * Retrieve the current crop rectangleon the @a entity @a pad and store it in
+ * the @a rect structure.
+ *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to retrieve the try crop rectangle
+ * stored in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to retrieve the
+ * current active crop rectangle.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_get_crop(struct media_entity *entity, struct v4l2_rect *rect,
+ unsigned int pad, enum v4l2_subdev_format_whence which);
+
+/**
+ * @brief Set the crop rectangle on a pad.
+ * @param entity - subdev-device media entity.
+ * @param rect - crop rectangle.
+ * @param pad - pad number.
+ * @param which - identifier of the format to set.
+ *
+ * Set the crop rectangle on the @a entity @a pad to @a rect. The driver is
+ * allowed to modify the requested rectangle, in which case @a rect is updated
+ * with the modifications.
+ *
+ * @a which is set to V4L2_SUBDEV_FORMAT_TRY to set the try crop rectangle
+ * stored in the file handle, of V4L2_SUBDEV_FORMAT_ACTIVE to configure the
+ * device with an active crop rectangle.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_set_crop(struct media_entity *entity, struct v4l2_rect *rect,
+ unsigned int pad, enum v4l2_subdev_format_whence which);
+
+/**
+ * @brief Retrieve the frame interval on a sub-device.
+ * @param entity - subdev-device media entity.
+ * @param interval - frame interval to be filled.
+ *
+ * Retrieve the current frame interval on subdev @a entity and store it in the
+ * @a interval structure.
+ *
+ * Frame interval retrieving is usually supported only on devices at the
+ * beginning of video pipelines, such as sensors.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+
+int v4l2_subdev_get_frame_interval(struct media_entity *entity,
+ struct v4l2_fract *interval);
+
+/**
+ * @brief Set the frame interval on a sub-device.
+ * @param entity - subdev-device media entity.
+ * @param interval - frame interval.
+ *
+ * Set the frame interval on subdev @a entity to @a interval. The driver is
+ * allowed to modify the requested frame interval, in which case @a interval is
+ * updated with the modifications.
+ *
+ * Frame interval setting is usually supported only on devices at the beginning
+ * of video pipelines, such as sensors.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_set_frame_interval(struct media_entity *entity,
+ struct v4l2_fract *interval);
+
+/**
+ * @brief Parse a string and apply format, crop and frame interval settings.
+ * @param media - media device.
+ * @param p - input string
+ * @param endp - pointer to string p where parsing ended (return)
+ *
+ * Parse string @a p and apply format, crop and frame interval settings to a
+ * subdev pad specified in @a p. @a endp will be written a pointer where
+ * parsing of @a p ended.
+ *
+ * Format strings are separeted by commas (,).
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int v4l2_subdev_parse_setup_formats(struct media_device *media, const char *p);
+
+/**
+ * @brief Convert media bus pixel code to string.
+ * @param code - input string
+ *
+ * Convert media bus pixel code @a code to a human-readable string.
+ *
+ * @return A pointer to a string on success, NULL on failure.
+ */
+const char *v4l2_subdev_pixelcode_to_string(enum v4l2_mbus_pixelcode code);
+
+/**
+ * @brief Parse string to media bus pixel code.
+ * @param string - input string
+ * @param lenght - length of the string
+ *
+ * Parse human readable string @a string to an media bus pixel code.
+ *
+ * @return media bus pixelcode on success, -1 on failure.
+ */
+enum v4l2_mbus_pixelcode v4l2_subdev_string_to_pixelcode(const char *string,
+ unsigned int length);
+#endif