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/libhwjpeg/Android.mk b/exynos5/hal/libhwjpeg/Android.mk
new file mode 100644
index 0000000..70e25fe
--- /dev/null
+++ b/exynos5/hal/libhwjpeg/Android.mk
@@ -0,0 +1,37 @@
+# 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.
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_C_INCLUDES := $(LOCAL_PATH) \
+	$(LOCAL_PATH)/../include
+
+LOCAL_SRC_FILES:= \
+	SecJpegCodecHal.cpp \
+	SecJpegEncoderHal.cpp \
+	SecJpegEncoder.cpp \
+	SecJpegDecoderHal.cpp
+
+LOCAL_SHARED_LIBRARIES :=    \
+	libcutils	\
+	libion
+
+#LOCAL_STATIC_LIBRARIES := \
+
+LOCAL_MODULE:= libhwjpeg
+
+LOCAL_MODULE_TAGS := eng
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/exynos5/hal/libhwjpeg/SecJpegCodecHal.cpp b/exynos5/hal/libhwjpeg/SecJpegCodecHal.cpp
new file mode 100644
index 0000000..b78212b
--- /dev/null
+++ b/exynos5/hal/libhwjpeg/SecJpegCodecHal.cpp
@@ -0,0 +1,338 @@
+/*
+ * Copyright Samsung Electronics Co.,LTD.
+ * Copyright (C) 2011 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.
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <math.h>
+#include <sys/poll.h>
+
+#include <cutils/log.h>
+
+#include <utils/Log.h>
+
+#include "SecJpegCodecHal.h"
+
+#define JPEG_ERROR_LOG(fmt,...)
+
+SecJpegCodecHal::SecJpegCodecHal()
+{
+}
+
+SecJpegCodecHal::~SecJpegCodecHal()
+{
+}
+
+int SecJpegCodecHal::t_v4l2Querycap(int iFd)
+{
+    struct v4l2_capability cap;
+    int iRet = ERROR_NONE;
+
+    iRet = ioctl(iFd, VIDIOC_QUERYCAP, &cap);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: VIDIOC_QUERYCAP failed", __func__, iRet);
+        return iRet;
+    }
+
+    return iRet;
+}
+
+int SecJpegCodecHal::t_v4l2SetJpegcomp(int iFd, int iQuality)
+{
+    struct v4l2_jpegcompression arg;
+    int iRet = ERROR_NONE;
+
+    arg.quality = iQuality;
+
+    iRet = ioctl(iFd, VIDIOC_S_JPEGCOMP, &arg);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: VIDIOC_S_JPEGCOMP failed", __func__, iRet);
+        return iRet;
+    }
+
+    return iRet;
+}
+
+int SecJpegCodecHal::t_v4l2SetFmt(int iFd, enum v4l2_buf_type eType, struct CONFIG *pstConfig)
+{
+    struct v4l2_format fmt;
+    int iRet = ERROR_NONE;
+
+    fmt.type = eType;
+    fmt.fmt.pix_mp.width = pstConfig->width;
+    fmt.fmt.pix_mp.height = pstConfig->height;
+    fmt.fmt.pix_mp.field = V4L2_FIELD_ANY;
+    fmt.fmt.pix_mp.num_planes = pstConfig->numOfPlanes;
+
+    if (pstConfig->mode == MODE_ENCODE)
+        fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_JPEG;
+
+    switch (fmt.type) {
+    case V4L2_BUF_TYPE_VIDEO_OUTPUT:    // fall through
+    case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+        break;
+    case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+        if (pstConfig->mode == MODE_ENCODE) {
+            fmt.fmt.pix_mp.pixelformat = pstConfig->pix.enc_fmt.in_fmt;
+        } else {
+            fmt.fmt.pix_mp.pixelformat = pstConfig->pix.dec_fmt.in_fmt;
+            fmt.fmt.pix_mp.plane_fmt[0].sizeimage = pstConfig->sizeJpeg;
+        }
+        break;
+    case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+        if (pstConfig->mode == MODE_ENCODE) {
+            fmt.fmt.pix_mp.pixelformat = pstConfig->pix.enc_fmt.out_fmt;
+        } else {
+            fmt.fmt.pix_mp.pixelformat = pstConfig->pix.dec_fmt.out_fmt;
+            fmt.fmt.pix_mp.width = pstConfig->scaled_width;
+            fmt.fmt.pix_mp.height = pstConfig->scaled_height;
+        }
+        break;
+    default:
+            return -ERROR_INVALID_V4l2_BUF_TYPE;
+            break;
+    }
+
+    iRet = ioctl(iFd, VIDIOC_S_FMT, &fmt);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: VIDIOC_S_FMT failed", __func__, iRet);
+        return iRet;
+    }
+
+    return iRet;
+}
+
+int SecJpegCodecHal::t_v4l2GetFmt(int iFd, enum v4l2_buf_type eType, struct CONFIG *pstConfig)
+{
+    struct v4l2_format fmt;
+    int iRet = ERROR_NONE;
+
+    fmt.type = eType;
+    iRet = ioctl(iFd, VIDIOC_G_FMT, &fmt);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: VIDIOC_G_FMT failed", __func__, iRet);
+        return iRet;
+    }
+
+    switch (fmt.type) {
+    case V4L2_BUF_TYPE_VIDEO_OUTPUT:    // fall through
+    case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+        pstConfig->width = fmt.fmt.pix.width;
+        pstConfig->height = fmt.fmt.pix.height;
+        break;
+    case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+        pstConfig->width = fmt.fmt.pix_mp.width;
+        pstConfig->height = fmt.fmt.pix_mp.height;
+        if (pstConfig->mode == MODE_ENCODE)
+            pstConfig->pix.enc_fmt.in_fmt = fmt.fmt.pix_mp.pixelformat;
+        else
+            pstConfig->pix.dec_fmt.in_fmt = fmt.fmt.pix_mp.pixelformat;
+        break;
+    case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+        pstConfig->width = fmt.fmt.pix_mp.width;
+        pstConfig->height = fmt.fmt.pix_mp.height;
+        if (pstConfig->mode == MODE_ENCODE)
+            pstConfig->pix.enc_fmt.out_fmt = fmt.fmt.pix_mp.pixelformat;
+        else
+            pstConfig->pix.dec_fmt.out_fmt = fmt.fmt.pix_mp.pixelformat;
+        break;
+    default:
+        return -ERROR_INVALID_V4l2_BUF_TYPE;
+    }
+
+    return iRet;
+}
+
+int SecJpegCodecHal::t_v4l2Reqbufs(int iFd, int iBufCount, struct BUF_INFO *pstBufInfo)
+{
+    struct v4l2_requestbuffers req;
+    int iRet = ERROR_NONE;
+
+    memset(&req, 0, sizeof(req));
+
+    req.type = pstBufInfo->buf_type;
+    req.memory = pstBufInfo->memory;
+
+    //if (pstBufInfo->memory == V4L2_MEMORY_MMAP)
+        req.count = iBufCount;
+
+    iRet = ioctl(iFd, VIDIOC_REQBUFS, &req);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: VIDIOC_REQBUFS failed", __func__, iRet);
+        return iRet;
+    }
+
+    return iRet;
+}
+
+int SecJpegCodecHal::t_v4l2Querybuf(int iFd, struct BUF_INFO *pstBufInfo, struct BUFFER *pstBuf)
+{
+    struct v4l2_buffer v4l2_buf;
+    struct v4l2_plane plane[JPEG_MAX_PLANE_CNT];
+    int iRet = ERROR_NONE;
+    int i;
+
+    memset(plane, 0, (int)JPEG_MAX_PLANE_CNT * sizeof(struct v4l2_plane));
+
+    v4l2_buf.index = 0;
+    v4l2_buf.type = pstBufInfo->buf_type;
+    v4l2_buf.memory = pstBufInfo->memory;
+    v4l2_buf.length = pstBufInfo->numOfPlanes;
+    v4l2_buf.m.planes = plane;
+
+    iRet = ioctl(iFd, VIDIOC_QUERYBUF, &v4l2_buf);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: VIDIOC_QUERYBUF failed", __func__, iRet);
+        return iRet;
+    }
+
+    for (i= 0; i < v4l2_buf.length; i++) {
+        pstBuf->size[i] = v4l2_buf.m.planes[i].length;
+        pstBuf->addr[i] = (char *) mmap(0,
+            pstBuf->size[i],
+            PROT_READ | PROT_WRITE, MAP_SHARED, iFd,
+            v4l2_buf.m.planes[i].m.mem_offset);
+
+        if (pstBuf->addr[i] == MAP_FAILED) {
+            JPEG_ERROR_LOG("[%s]: mmap failed", __func__);
+            return -ERROR_MMAP_FAILED;
+        }
+    }
+
+    return iRet;
+}
+
+int SecJpegCodecHal::t_v4l2Qbuf(int iFd, struct BUF_INFO *pstBufInfo, struct BUFFER *pstBuf)
+{
+    struct v4l2_buffer v4l2_buf;
+    struct v4l2_plane plane[JPEG_MAX_PLANE_CNT];
+    int i;
+    int iRet = ERROR_NONE;
+
+    memset(&v4l2_buf, 0, sizeof(struct v4l2_buffer));
+    memset(plane, 0, (int)JPEG_MAX_PLANE_CNT * sizeof(struct v4l2_plane));
+
+    v4l2_buf.index = 0;
+    v4l2_buf.type = pstBufInfo->buf_type;
+    v4l2_buf.memory = pstBufInfo->memory;
+    v4l2_buf.length = pstBufInfo->numOfPlanes;
+    v4l2_buf.m.planes = plane;
+
+    if (pstBufInfo->memory == V4L2_MEMORY_USERPTR) {
+        for (i = 0; i < pstBufInfo->numOfPlanes; i++) {
+            v4l2_buf.m.planes[i].m.userptr = (unsigned long)pstBuf->addr[i];
+            v4l2_buf.m.planes[i].length = pstBuf->size[i];
+        }
+    }
+
+    iRet = ioctl(iFd, VIDIOC_QBUF, &v4l2_buf);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d] VIDIOC_QBUF failed", __func__, iRet);
+        pstBuf->numOfPlanes = 0;
+        return iRet;
+    }
+
+    return iRet;
+}
+
+int SecJpegCodecHal::t_v4l2Dqbuf(int iFd, enum v4l2_buf_type eType, enum v4l2_memory eMemory)
+{
+    struct v4l2_buffer buf;
+    int iRet = ERROR_NONE;
+
+    memset(&buf, 0, sizeof(struct v4l2_buffer));
+
+    buf.type = eType;
+    buf.memory = eMemory;
+
+    iRet = ioctl(iFd, VIDIOC_DQBUF, &buf);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d] VIDIOC_DQBUF failed", __func__, iRet);
+        return iRet;
+    }
+
+    return iRet;
+}
+
+int SecJpegCodecHal::t_v4l2StreamOn(int iFd, enum v4l2_buf_type eType)
+{
+    int iRet = ERROR_NONE;
+
+    iRet = ioctl(iFd, VIDIOC_STREAMON, &eType);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d] VIDIOC_STREAMON failed", __func__, iRet);
+        return iRet;
+    }
+
+    return iRet;
+}
+
+int SecJpegCodecHal::t_v4l2StreamOff(int iFd, enum v4l2_buf_type eType)
+{
+    int iRet = ERROR_NONE;
+
+    iRet = ioctl(iFd, VIDIOC_STREAMOFF, &eType);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d] VIDIOC_STREAMOFF failed", __func__, iRet);
+        return iRet;
+    }
+
+    return iRet;
+}
+
+int SecJpegCodecHal::t_v4l2SetCtrl(int iFd, int iCid, int iValue)
+{
+    struct v4l2_control vc;
+    int iRet = ERROR_NONE;
+
+    vc.id = iCid;
+    vc.value = iValue;
+
+    iRet = ioctl(iFd, VIDIOC_S_CTRL, &vc);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s] VIDIOC_S_CTRL failed : cid(%d), value(%d)\n", __func__, iCid, iValue);
+        return iRet;
+    }
+
+    return iRet;
+}
+
+int SecJpegCodecHal::t_v4l2GetCtrl(int iFd, int iCid)
+{
+    struct v4l2_control ctrl;
+    int iRet = ERROR_NONE;
+
+    ctrl.id = iCid;
+
+    iRet = ioctl(iFd, VIDIOC_G_CTRL, &ctrl);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s] VIDIOC_G_CTRL failed : cid(%d)\n", __func__, ctrl.id);
+        return iRet;
+    }
+
+    return ctrl.value;
+}
+
diff --git a/exynos5/hal/libhwjpeg/SecJpegDecoderHal.cpp b/exynos5/hal/libhwjpeg/SecJpegDecoderHal.cpp
new file mode 100644
index 0000000..563b15a
--- /dev/null
+++ b/exynos5/hal/libhwjpeg/SecJpegDecoderHal.cpp
@@ -0,0 +1,498 @@
+/*
+ * Copyright Samsung Electronics Co.,LTD.
+ * Copyright (C) 2011 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.
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <math.h>
+#include <sys/poll.h>
+
+#include <cutils/log.h>
+
+#include <utils/Log.h>
+
+#include "SecJpegCodecHal.h"
+
+#define JPEG_ERROR_LOG(fmt,...)
+
+#define NUM_PLANES (1)
+#define NUM_BUFFERS (1)
+
+SecJpegDecoderHal::SecJpegDecoderHal()
+{
+    t_iJpegFd = -1;
+    t_bFlagCreate = false;
+}
+
+SecJpegDecoderHal::~SecJpegDecoderHal()
+{
+    if (t_bFlagCreate == true) {
+        this->destroy();
+    }
+}
+
+int SecJpegDecoderHal::create(void)
+{
+    if (t_bFlagCreate == true) {
+        return ERROR_JPEG_DEVICE_ALREADY_CREATE;
+    }
+
+    int iRet = ERROR_NONE;
+
+    t_iJpegFd = open(JPEG_DEC_NODE, O_RDWR, 0);
+
+    if (t_iJpegFd < 0) {
+        t_iJpegFd = -1;
+        JPEG_ERROR_LOG("[%s]: JPEG_DEC_NODE open failed", __func__);
+        return ERROR_CANNOT_OPEN_JPEG_DEVICE;
+    }
+
+    if (t_iJpegFd <= 0) {
+        t_iJpegFd = -1;
+        JPEG_ERROR_LOG("ERR(%s):JPEG device was closed\n", __func__);
+        return ERROR_JPEG_DEVICE_ALREADY_CLOSED;
+    }
+
+    iRet = t_v4l2Querycap(t_iJpegFd);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s]: QUERYCAP failed", __func__);
+        close(t_iJpegFd);
+        return ERROR_CANNOT_OPEN_JPEG_DEVICE;
+    }
+
+    memset(&t_stJpegConfig, 0, sizeof(struct CONFIG));
+    memset(&t_stJpegInbuf, 0, sizeof(struct BUFFER));
+    memset(&t_stJpegOutbuf, 0, sizeof(struct BUFFER));
+
+    t_stJpegConfig.mode = MODE_DECODE;
+
+    t_bFlagCreate = true;
+    t_bFlagCreateInBuf = false;
+    t_bFlagCreateOutBuf = false;
+    t_bFlagExcute = false;
+
+    t_iPlaneNum = 0;
+
+    return ERROR_NONE;
+}
+
+int SecJpegDecoderHal::destroy(void)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_ALREADY_DESTROY;
+    }
+
+    if (t_iJpegFd > 0) {
+        struct BUF_INFO stBufInfo;
+        int iRet = ERROR_NONE;
+
+        if (t_bFlagExcute) {
+            iRet = t_v4l2StreamOff(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+        }
+
+        if (t_bFlagExcute) {
+            stBufInfo.numOfPlanes = NUM_PLANES;
+            stBufInfo.memory = V4L2_MEMORY_MMAP;
+
+            stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+            iRet = t_v4l2Reqbufs(t_iJpegFd, 0, &stBufInfo);
+
+            stBufInfo.numOfPlanes = t_iPlaneNum;
+            stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+            iRet = t_v4l2Reqbufs(t_iJpegFd, 0, &stBufInfo);
+        }
+
+        iRet = close(t_iJpegFd);
+        if (iRet < 0) {
+            JPEG_ERROR_LOG("[%s:%d]: JPEG_DEC_NODE close failed", __func__, iRet);
+        }
+    }
+
+    t_iJpegFd = -1;
+    t_bFlagCreate = false;
+    return ERROR_NONE;
+}
+
+int SecJpegDecoderHal::setSize(int iW, int iH)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    if (iW < 0 || MAX_JPG_WIDTH < iW) {
+        return ERROR_INVALID_IMAGE_SIZE;
+    }
+
+    if (iH < 0 || MAX_JPG_HEIGHT < iH) {
+        return ERROR_INVALID_IMAGE_SIZE;
+    }
+
+    t_stJpegConfig.width = iW;
+    t_stJpegConfig.height = iH;
+
+    return ERROR_NONE;
+}
+
+int SecJpegDecoderHal::setJpegConfig(void *pConfig)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    if (pConfig == NULL) {
+        return ERROR_JPEG_CONFIG_POINTER_NULL;
+    }
+
+    memcpy(&t_stJpegConfig, pConfig, sizeof(struct CONFIG));
+
+    if (t_stJpegConfig.pix.dec_fmt.out_fmt == V4L2_PIX_FMT_NV12) {
+        t_iPlaneNum = 2;
+    } else {
+        t_iPlaneNum = 1;
+    }
+
+    return ERROR_NONE;
+}
+
+void *SecJpegDecoderHal::getJpegConfig(void)
+{
+    if (t_bFlagCreate == false) {
+        return NULL;
+    }
+
+    return &t_stJpegConfig;
+}
+
+char *SecJpegDecoderHal::getInBuf(int *piInputSize)
+{
+    if (t_bFlagCreate == false) {
+        return NULL;
+    }
+
+     if (t_bFlagCreateInBuf == false) {
+
+        *piInputSize = 0;
+        return NULL;
+    }
+
+    *piInputSize = t_stJpegInbuf.size[0];
+
+    return (char *)(t_stJpegInbuf.addr[0]);
+}
+
+char **SecJpegDecoderHal::getOutBuf(int *piOutputSize)
+{
+    if (t_bFlagCreate == false) {
+        return NULL;
+    }
+
+    if (t_bFlagCreateOutBuf == false) {
+
+        *piOutputSize = 0;
+        return NULL;
+    }
+
+    for (int i=0;i<t_iPlaneNum;i++) {
+        piOutputSize[i] = t_stJpegOutbuf.size[i];
+    }
+
+    return t_stJpegOutbuf.addr;
+}
+
+int  SecJpegDecoderHal::setInBuf(char *pcBuf, int iSize)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    if (pcBuf == NULL) {
+        return ERROR_BUFFR_IS_NULL;
+    }
+
+    if (iSize<=0) {
+        return ERROR_BUFFER_TOO_SMALL;
+    }
+
+    t_stJpegInbuf.addr[0] = pcBuf;
+    t_stJpegInbuf.size[0] = iSize;
+    t_stJpegInbuf.numOfPlanes = NUM_PLANES;
+
+    t_bFlagCreateInBuf = true;
+
+    return ERROR_NONE;
+}
+
+int  SecJpegDecoderHal::setOutBuf(char **pcBuf, int *iSize)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    if (pcBuf == NULL) {
+        return ERROR_BUFFR_IS_NULL;
+    }
+
+    if (iSize<=0) {
+        return ERROR_BUFFER_TOO_SMALL;
+    }
+
+    for(int i=0;i<t_iPlaneNum;i++) {
+        t_stJpegOutbuf.addr[i] = pcBuf[i];
+        t_stJpegOutbuf.size[i] = iSize[i];
+    }
+
+    t_stJpegOutbuf.numOfPlanes = t_iPlaneNum;
+
+    t_bFlagCreateOutBuf = true;
+
+    return ERROR_NONE;
+}
+
+int SecJpegDecoderHal::setCache(int iValue)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    if (t_v4l2SetCtrl(t_iJpegFd, V4L2_CID_CACHEABLE, iValue)<0) {
+        JPEG_ERROR_LOG("%s::cache setting failed\n", __func__);
+        return ERROR_CANNOT_CHANGE_CACHE_SETTING;
+    }
+
+    return ERROR_NONE;
+}
+
+int SecJpegDecoderHal::getSize(int *piW, int *piH)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    int iRet = t_v4l2GetFmt(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, &t_stJpegConfig);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s,%d]: get image size failed", __func__,iRet);
+        return ERROR_GET_SIZE_FAIL;
+    }
+
+    *piW = t_stJpegConfig.width;
+    *piH = t_stJpegConfig.height;
+
+    return ERROR_NONE;
+}
+
+int SecJpegDecoderHal::setColorFormat(int iV4l2ColorFormat)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    switch(iV4l2ColorFormat) {
+    case V4L2_PIX_FMT_YUYV:
+    case V4L2_PIX_FMT_RGB565X:
+    case V4L2_PIX_FMT_BGR32:
+    case V4L2_PIX_FMT_RGB32:
+        t_stJpegConfig.pix.dec_fmt.out_fmt = iV4l2ColorFormat;
+        break;
+    default:
+        t_iPlaneNum = 0;
+        return ERROR_INVALID_COLOR_FORMAT;
+        break;
+    }
+
+    if (iV4l2ColorFormat == V4L2_PIX_FMT_NV12) {
+        t_iPlaneNum = 2;
+    } else {
+        t_iPlaneNum = 1;
+    }
+
+    return ERROR_NONE;
+}
+
+int SecJpegDecoderHal::setJpegFormat(int iV4l2JpegFormat)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    switch(iV4l2JpegFormat) {
+    case V4L2_PIX_FMT_JPEG_444:
+    case V4L2_PIX_FMT_JPEG_422:
+    case V4L2_PIX_FMT_JPEG_420:
+    case V4L2_PIX_FMT_JPEG_GRAY:
+        t_stJpegConfig.pix.dec_fmt.in_fmt = iV4l2JpegFormat;
+        break;
+    default:
+        return ERROR_INVALID_JPEG_FORMAT;
+        break;
+    }
+
+    return ERROR_NONE;
+}
+
+int SecJpegDecoderHal::updateConfig(void)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    int iRet = ERROR_NONE;
+
+    t_stJpegConfig.numOfPlanes = NUM_PLANES;
+
+    t_stJpegConfig.mode = MODE_DECODE;
+
+    iRet = t_v4l2SetFmt(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, &t_stJpegConfig);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s,%d]: jpeg input S_FMT failed", __func__,iRet);
+        return ERROR_INVALID_JPEG_CONFIG;
+    }
+
+    struct BUF_INFO stBufInfo;
+
+    stBufInfo.numOfPlanes = NUM_PLANES;
+    stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+    stBufInfo.memory = V4L2_MEMORY_USERPTR;
+
+    iRet = t_v4l2Reqbufs(t_iJpegFd, NUM_BUFFERS, &stBufInfo);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: Input REQBUFS failed", __func__, iRet);
+        return ERROR_EXCUTE_FAIL;
+    }
+
+    t_stJpegConfig.numOfPlanes = t_iPlaneNum;
+    iRet = t_v4l2SetFmt(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, &t_stJpegConfig);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s,%d]: jpeg output S_FMT failed", __func__,iRet);
+        return ERROR_INVALID_JPEG_CONFIG;
+    }
+
+    stBufInfo.numOfPlanes = t_iPlaneNum;
+    stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+
+    iRet = t_v4l2Reqbufs(t_iJpegFd, NUM_BUFFERS, &stBufInfo);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: Output REQBUFS failed", __func__, iRet);
+        return ERROR_REQBUF_FAIL;
+    }
+
+    return ERROR_NONE;
+}
+
+int SecJpegDecoderHal::setScaledSize(int iW, int iH)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    if (iW < 0 || MAX_JPG_WIDTH < iW) {
+        return ERROR_INVALID_IMAGE_SIZE;
+    }
+
+    if (iH < 0 || MAX_JPG_HEIGHT < iH) {
+        return ERROR_INVALID_IMAGE_SIZE;
+    }
+
+    t_stJpegConfig.scaled_width = iW;
+    t_stJpegConfig.scaled_height = iH;
+
+    return ERROR_NONE;
+}
+
+int SecJpegDecoderHal::setJpegSize(int iJpegSize)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    if (iJpegSize<=0) {
+        return ERROR_JPEG_SIZE_TOO_SMALL;
+    }
+
+    t_stJpegConfig.sizeJpeg = iJpegSize;
+
+    return ERROR_NONE;
+}
+
+int SecJpegDecoderHal::decode(void)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    struct BUF_INFO stBufInfo;
+    int iRet = ERROR_NONE;
+
+    t_bFlagExcute = true;
+
+    stBufInfo.numOfPlanes = NUM_PLANES;
+    stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+
+    stBufInfo.memory = V4L2_MEMORY_USERPTR;
+
+    iRet = t_v4l2Qbuf(t_iJpegFd, &stBufInfo, &t_stJpegInbuf);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: Input QBUF failed", __func__, iRet);
+        return ERROR_EXCUTE_FAIL;
+    }
+
+    stBufInfo.numOfPlanes = t_iPlaneNum;
+    stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+
+    iRet = t_v4l2Qbuf(t_iJpegFd, &stBufInfo, &t_stJpegOutbuf);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: Output QBUF failed", __func__, iRet);
+        return ERROR_EXCUTE_FAIL;
+    }
+
+    stBufInfo.numOfPlanes = NUM_PLANES;
+    iRet = t_v4l2StreamOn(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: input stream on failed", __func__, iRet);
+        return ERROR_EXCUTE_FAIL;
+    }
+    stBufInfo.numOfPlanes = t_iPlaneNum;
+    iRet = t_v4l2StreamOn(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: output stream on failed", __func__, iRet);
+        return ERROR_EXCUTE_FAIL;
+    }
+
+    stBufInfo.numOfPlanes = NUM_PLANES;
+    iRet = t_v4l2Dqbuf(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_MMAP);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: Intput DQBUF failed", __func__, iRet);
+        return ERROR_EXCUTE_FAIL;
+    }
+    stBufInfo.numOfPlanes = t_iPlaneNum;
+    iRet = t_v4l2Dqbuf(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_MEMORY_MMAP);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: Output DQBUF failed", __func__, iRet);
+        return ERROR_EXCUTE_FAIL;
+    }
+
+    return ERROR_NONE;
+}
+
diff --git a/exynos5/hal/libhwjpeg/SecJpegEncoder.cpp b/exynos5/hal/libhwjpeg/SecJpegEncoder.cpp
new file mode 100644
index 0000000..6c118e1
--- /dev/null
+++ b/exynos5/hal/libhwjpeg/SecJpegEncoder.cpp
@@ -0,0 +1,952 @@
+/*
+ * Copyright Samsung Electronics Co.,LTD.
+ * Copyright (C) 2010 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.
+ * 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.
+ */
+
+#include <utils/Log.h>
+
+#include "SecJpegEncoder.h"
+
+static const char ExifAsciiPrefix[] = { 0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0 };
+
+#define JPEG_ERROR_LOG(fmt,...)
+
+#define JPEG_MAIN_DUMP  (0)
+#define JPEG_THUMB_DUMP (0)
+
+SecJpegEncoder::SecJpegEncoder()
+{
+    m_flagCreate = false;
+    m_jpegMain = NULL;
+    m_jpegThumb = NULL;
+    m_thumbnailW = 0;
+    m_thumbnailH = 0;
+    m_pThumbInputBuffer = NULL;
+    m_pThumbOutputBuffer = NULL;
+#ifdef JPEG_WA_FOR_PAGEFAULT
+    m_pJpegInputBuffer = 0;
+    m_pExtInBuf = NULL;
+    m_iInBufSize = 0;
+#endif // JPEG_WA_FOR_PAGEFAULT
+    m_ionJpegClient = 0;;
+    m_ionThumbInBuffer = 0;
+    m_ionThumbOutBuffer = 0;
+#ifdef JPEG_WA_FOR_PAGEFAULT
+    m_ionJpegInBuffer = 0;;
+#endif // JPEG_WA_FOR_PAGEFAULT
+}
+
+SecJpegEncoder::~SecJpegEncoder()
+{
+    if (m_flagCreate == true) {
+        this->destroy();
+    }
+}
+
+bool SecJpegEncoder::flagCreate(void)
+{
+    return m_flagCreate;
+}
+
+int SecJpegEncoder::create(void)
+{
+    int ret = ERROR_NONE;
+    if (m_flagCreate == true) {
+        return ERROR_ALREADY_CREATE;
+    }
+
+    if (m_jpegMain == NULL) {
+        m_jpegMain = new SecJpegEncoderHal;
+
+        if (m_jpegMain == NULL) {
+            JPEG_ERROR_LOG("ERR(%s):Cannot create SecJpegEncoderHal class\n", __func__);
+            return ERROR_CANNOT_CREATE_SEC_JPEG_ENC_HAL;
+        }
+
+        ret = m_jpegMain->create();
+        if (ret) {
+            return ret;
+        }
+
+        ret = m_jpegMain->setCache(JPEG_CACHE_ON);
+
+        if (ret) {
+            m_jpegMain->destroy();
+            return ret;
+        }
+    }
+
+    m_flagCreate = true;
+
+    return ERROR_NONE;
+}
+
+int SecJpegEncoder::destroy(void)
+{
+    if (m_flagCreate == false) {
+        return ERROR_ALREADY_DESTROY;
+    }
+
+    if (m_jpegMain != NULL) {
+        m_jpegMain->destroy();
+        delete m_jpegMain;
+        m_jpegMain = NULL;
+    }
+
+    if (m_jpegThumb != NULL) {
+        int iSize = sizeof(char)*m_thumbnailW*m_thumbnailH*4;
+
+#ifdef JPEG_WA_FOR_PAGEFAULT
+        iSize += JPEG_WA_BUFFER_SIZE;
+
+        freeJpegIonMemory(m_ionJpegClient, &m_ionJpegInBuffer, &m_pJpegInputBuffer, m_iInBufSize);
+#endif //JPEG_WA_FOR_PAGEFAULT
+
+        freeJpegIonMemory(m_ionJpegClient, &m_ionThumbInBuffer, &m_pThumbInputBuffer, iSize);
+        freeJpegIonMemory(m_ionJpegClient, &m_ionThumbOutBuffer, &m_pThumbOutputBuffer, iSize);
+
+        if (m_ionJpegClient != 0) {
+            ion_client_destroy(m_ionJpegClient);
+            m_ionJpegClient = 0;
+        }
+
+        m_jpegThumb->destroy();
+        delete m_jpegThumb;
+        m_jpegThumb = NULL;
+    }
+
+    m_flagCreate = false;
+    m_thumbnailW = 0;
+    m_thumbnailH = 0;
+    return ERROR_NONE;
+}
+
+int SecJpegEncoder::setSize(int w, int h)
+{
+    if (m_flagCreate == false) {
+        return ERROR_NOT_YET_CREATED;
+    }
+
+    return m_jpegMain->setSize(w, h);
+}
+
+
+int SecJpegEncoder::setQuality(int quality)
+{
+    if (m_flagCreate == false) {
+        return ERROR_NOT_YET_CREATED;
+    }
+
+    return m_jpegMain->setQuality(quality);
+}
+
+int SecJpegEncoder::setColorFormat(int colorFormat)
+{
+    if (m_flagCreate == false) {
+        return ERROR_NOT_YET_CREATED;
+    }
+
+    return m_jpegMain->setColorFormat(colorFormat);
+}
+
+int SecJpegEncoder::setJpegFormat(int jpegFormat)
+{
+    if (m_flagCreate == false) {
+        return ERROR_NOT_YET_CREATED;
+    }
+
+    return m_jpegMain->setJpegFormat(jpegFormat);
+}
+
+int SecJpegEncoder::updateConfig(void)
+{
+    if (m_flagCreate == false) {
+        return ERROR_NOT_YET_CREATED;
+    }
+
+    return m_jpegMain->updateConfig();
+}
+
+char *SecJpegEncoder::getInBuf(int *input_size)
+{
+    if (m_flagCreate == false) {
+        return NULL;
+    }
+
+    int inSize = 0;
+    char *inBuf = *(m_jpegMain->getInBuf(&inSize));
+
+    if (inBuf == NULL) {
+        JPEG_ERROR_LOG("%s::Fail to JPEG input buffer!!\n", __func__);
+        return NULL;
+    }
+
+    *input_size = inSize;
+
+    return inBuf;
+}
+
+char *SecJpegEncoder::getOutBuf(int *output_size)
+{
+    if (m_flagCreate == false) {
+        return NULL;
+    }
+
+    int outSize = 0;
+    char *outBuf = m_jpegMain->getOutBuf(&outSize);
+
+    if (outBuf == NULL) {
+        JPEG_ERROR_LOG("%s::Fail to JPEG input buffer!!\n", __func__);
+        return NULL;
+    }
+
+    *output_size = outSize;
+
+    return outBuf;
+}
+
+int  SecJpegEncoder::setInBuf(char *buf, int size)
+{
+    if (m_flagCreate == false) {
+        return ERROR_NOT_YET_CREATED;
+    }
+
+    if (buf == NULL) {
+        return ERROR_BUFFR_IS_NULL;
+    }
+
+    if (size<=0) {
+        return ERROR_BUFFER_TOO_SMALL;
+    }
+
+    int ret = ERROR_NONE;
+
+#ifdef JPEG_WA_FOR_PAGEFAULT
+    size += JPEG_WA_BUFFER_SIZE;
+
+    freeJpegIonMemory(m_ionJpegClient, &m_ionJpegInBuffer, &m_pJpegInputBuffer, size);
+
+    if (m_ionJpegClient == 0) {
+        m_ionJpegClient = ion_client_create();
+        if (m_ionJpegClient < 0) {
+            JPEG_ERROR_LOG("[%s]src ion client create failed, value = %d\n", __func__, size);
+            m_ionJpegClient = 0;
+            return ret;
+        }
+    }
+
+    ret = allocJpegIonMemory(m_ionJpegClient, &m_ionJpegInBuffer, &m_pJpegInputBuffer, size);
+    if (ret != ERROR_NONE) {
+        return ret;
+    }
+
+    ret = m_jpegMain->setInBuf(&m_pJpegInputBuffer, &size);
+    if (ret) {
+        JPEG_ERROR_LOG("%s::Fail to JPEG input buffer!!\n", __func__);
+        return ret;
+    }
+    m_iInBufSize = size;
+
+    m_pExtInBuf = buf;
+
+#else // NO JPEG_WA_FOR_PAGEFAULT
+    ret = m_jpegMain->setInBuf(&buf, &size);
+    if (ret) {
+        JPEG_ERROR_LOG("%s::Fail to JPEG input buffer!!\n", __func__);
+        return ret;
+    }
+#endif // JPEG_WA_FOR_PAGEFAULT
+
+    return ERROR_NONE;
+}
+
+int  SecJpegEncoder::setOutBuf(char *buf, int size)
+{
+    if (m_flagCreate == false) {
+        return ERROR_NOT_YET_CREATED;
+    }
+
+    if (buf == NULL) {
+        return ERROR_BUFFR_IS_NULL;
+    }
+
+    if (size<=0) {
+        return ERROR_BUFFER_TOO_SMALL;
+    }
+
+    int ret = ERROR_NONE;
+    ret = m_jpegMain->setOutBuf(buf, size);
+    if (ret) {
+        JPEG_ERROR_LOG("%s::Fail to JPEG output buffer!!\n", __func__);
+        return ret;
+    }
+
+    return ERROR_NONE;
+}
+
+int SecJpegEncoder::encode(int *size, exif_attribute_t *exifInfo)
+{
+    int ret = ERROR_NONE;
+    unsigned char *exifOut = NULL;
+
+    if (m_flagCreate == false) {
+        return ERROR_NOT_YET_CREATED;
+    }
+
+#ifdef JPEG_WA_FOR_PAGEFAULT
+    memcpy(m_pJpegInputBuffer, m_pExtInBuf, m_iInBufSize-JPEG_WA_BUFFER_SIZE);
+#endif // JPEG_WA_FOR_PAGEFAULT
+
+    ret = m_jpegMain->encode();
+    if (ret) {
+        JPEG_ERROR_LOG("encode failed\n");
+        return ret;
+    }
+
+    int iJpegSize = m_jpegMain->getJpegSize();
+
+    if (iJpegSize<=0) {
+        JPEG_ERROR_LOG("%s:: output_size is too small(%d)!!\n", __func__, iJpegSize);
+        return ERROR_OUT_BUFFER_SIZE_TOO_SMALL;
+    }
+
+    int iOutputSize = 0;
+    char *pcJpegBuffer = m_jpegMain->getOutBuf(&iOutputSize);
+
+    if (pcJpegBuffer == NULL) {
+        JPEG_ERROR_LOG("%s::buffer is null!!\n", __func__);
+        return ERROR_OUT_BUFFER_CREATE_FAIL;
+    }
+
+    if (exifInfo != NULL) {
+        unsigned int thumbLen, exifLen;
+
+        unsigned int bufSize = 0;
+        if (exifInfo->enableThumb) {
+            if (encodeThumbnail(&thumbLen)) {
+                bufSize = EXIF_FILE_SIZE;
+                exifInfo->enableThumb = false;
+            } else {
+                if (thumbLen > EXIF_LIMIT_SIZE) {
+                    bufSize = EXIF_FILE_SIZE;
+                    exifInfo->enableThumb = false;
+                }
+                else {
+                    bufSize = EXIF_FILE_SIZE + thumbLen;
+                }
+            }
+        } else {
+            bufSize = EXIF_FILE_SIZE;
+            exifInfo->enableThumb = false;
+        }
+
+        exifOut = new unsigned char[bufSize];
+        if (exifOut == NULL) {
+            JPEG_ERROR_LOG("%s::Failed to allocate for exifOut", __func__);
+            delete[] exifOut;
+            return ERROR_EXIFOUT_ALLOC_FAIL;
+        }
+        memset(exifOut, 0, bufSize);
+
+        if (makeExif (exifOut, exifInfo, &exifLen)) {
+            JPEG_ERROR_LOG("%s::Failed to make EXIF", __func__);
+            delete[] exifOut;
+            return ERROR_MAKE_EXIF_FAIL;
+        }
+
+        if (exifLen <= EXIF_LIMIT_SIZE) {
+            memmove(pcJpegBuffer+exifLen+2, pcJpegBuffer+2, iJpegSize - 2);
+            memcpy(pcJpegBuffer+2, exifOut, exifLen);
+            iJpegSize += exifLen;
+        }
+
+        delete[] exifOut;
+    }
+
+    *size = iJpegSize;
+
+    return ERROR_NONE;
+}
+
+int SecJpegEncoder::makeExif (unsigned char *exifOut,
+                              exif_attribute_t *exifInfo,
+                              unsigned int *size,
+                              bool useMainbufForThumb)
+{
+    unsigned char *pCur, *pApp1Start, *pIfdStart, *pGpsIfdPtr, *pNextIfdOffset;
+    unsigned int tmp, LongerTagOffest = 0, exifSizeExceptThumb;
+    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;
+            }
+            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
+    char *thumbBuf = NULL;
+    unsigned int thumbSize = 0;
+
+    if (useMainbufForThumb) {
+        if (m_jpegMain) {
+            thumbBuf = m_jpegMain->getOutBuf((int *)&thumbSize);
+            thumbSize = m_jpegMain->getJpegSize();
+        }
+    } else {
+        if (m_jpegThumb) {
+            thumbBuf = m_jpegThumb->getOutBuf((int *)&thumbSize);
+            thumbSize = m_jpegThumb->getJpegSize();
+        }
+    }
+
+    if (exifInfo->enableThumb && (thumbBuf != NULL) && (thumbSize != 0)) {
+        exifSizeExceptThumb = 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;
+        if (LongerTagOffest > EXIF_LIMIT_SIZE) {
+            LongerTagOffest = exifSizeExceptThumb;
+            tmp = 0;
+            memcpy(pNextIfdOffset, &tmp, OFFSET_SIZE);  // NEXT IFD offset skipped on 0th IFD
+        }
+    } 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);
+
+    return ERROR_NONE;
+}
+
+/*
+ * private member functions
+*/
+inline void SecJpegEncoder::writeExifIfd(unsigned char **pCur,
+                                             unsigned short tag,
+                                             unsigned short type,
+                                             unsigned int count,
+                                             unsigned int 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 SecJpegEncoder::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 SecJpegEncoder::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 SecJpegEncoder::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;
+}
+
+int SecJpegEncoder::m_scaleDownYuv422(char *srcBuf, unsigned int srcW, unsigned int srcH,
+                                           char *dstBuf, unsigned int dstW, unsigned int dstH)
+{
+    int step_x, step_y;
+    int iXsrc, iXdst;
+    int x, y, src_y_start_pos, dst_pos, src_pos;
+
+    if (dstW & 0x01 || dstH & 0x01) {
+        return ERROR_INVALID_SCALING_WIDTH_HEIGHT;
+    }
+
+    step_x = srcW / dstW;
+    step_y = srcH / dstH;
+
+    unsigned int srcWStride = srcW * 2;
+    unsigned int stepXStride = step_x * 2;
+
+    dst_pos = 0;
+    for (unsigned int y = 0; y < dstH; y++) {
+        src_y_start_pos = srcWStride * step_y * y;
+
+        for (unsigned int x = 0; x < dstW; x += 2) {
+            src_pos = src_y_start_pos + (stepXStride * x);
+
+            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 ERROR_NONE;
+}
+
+// thumbnail
+int SecJpegEncoder::setThumbnailSize(int w, int h)
+{
+    if (m_flagCreate == false) {
+        return ERROR_CANNOT_CREATE_SEC_JPEG_ENC_HAL;
+    }
+
+    if (w < 0 || MAX_JPG_WIDTH < w) {
+        return false;
+    }
+
+    if (h < 0 || MAX_JPG_HEIGHT < h) {
+        return false;
+    }
+
+    m_thumbnailW = w;
+    m_thumbnailH = h;
+    return ERROR_NONE;
+}
+
+
+int SecJpegEncoder::encodeThumbnail(unsigned int *size, bool useMain)
+{
+    int ret = ERROR_NONE;
+
+    if (m_flagCreate == false) {
+        return ERROR_CANNOT_CREATE_SEC_JPEG_ENC_HAL;
+    }
+
+    // create jpeg thumbnail class
+    if (m_jpegThumb == NULL) {
+        m_jpegThumb = new SecJpegEncoderHal;
+
+        if (m_jpegThumb == NULL) {
+            JPEG_ERROR_LOG("ERR(%s):Cannot open a jpeg device file\n", __func__);
+            return ERROR_CANNOT_CREATE_SEC_THUMB;
+        }
+    }
+
+    ret = m_jpegThumb->create();
+    if (ret) {
+        JPEG_ERROR_LOG("ERR(%s):Fail create\n", __func__);
+        return ret;
+    }
+
+        ret = m_jpegThumb->setCache(JPEG_CACHE_ON);
+    if (ret) {
+        JPEG_ERROR_LOG("ERR(%s):Fail cache set\n", __func__);
+        return ret;
+    }
+
+    void *pConfig = m_jpegMain->getJpegConfig();
+    if (pConfig == NULL) {
+        JPEG_ERROR_LOG("ERR(%s):Fail getJpegConfig\n", __func__);
+        return ERROR_BUFFR_IS_NULL;
+    }
+
+    ret = m_jpegThumb->setJpegConfig(pConfig);
+    if (ret) {
+        JPEG_ERROR_LOG("ERR(%s):Fail setJpegConfig\n", __func__);
+        return ret;
+    }
+
+    ret = m_jpegThumb->setQuality(JPEG_THUMBNAIL_QUALITY);
+    if (ret) {
+        JPEG_ERROR_LOG("ERR(%s):Fail setQuality\n", __func__);
+        return ret;
+    }
+
+    ret = m_jpegThumb->setSize(m_thumbnailW, m_thumbnailH);
+    if (ret) {
+        JPEG_ERROR_LOG("ERR(%s):Fail setSize\n", __func__);
+        return ret;
+    }
+
+    int iThumbSize = sizeof(char)*m_thumbnailW*m_thumbnailH*4;
+#ifdef JPEG_WA_FOR_PAGEFAULT
+    iThumbSize += JPEG_WA_BUFFER_SIZE;
+#endif //JPEG_WA_FOR_PAGEFAULT
+
+    freeJpegIonMemory(m_ionJpegClient, &m_ionThumbInBuffer, &m_pThumbInputBuffer, iThumbSize);
+    freeJpegIonMemory(m_ionJpegClient, &m_ionThumbOutBuffer, &m_pThumbOutputBuffer, iThumbSize);
+
+    if (m_ionJpegClient == 0) {
+        m_ionJpegClient = ion_client_create();
+        if (m_ionJpegClient < 0) {
+            JPEG_ERROR_LOG("[%s]src ion client create failed, value = %d\n", __func__, m_ionJpegClient);
+            m_ionJpegClient = 0;
+            return ret;
+        }
+    }
+
+    ret = allocJpegIonMemory(m_ionJpegClient, &m_ionThumbInBuffer, &m_pThumbInputBuffer, iThumbSize);
+    if (ret != ERROR_NONE) {
+        return ret;
+    }
+
+    ret = m_jpegThumb->setInBuf(&m_pThumbInputBuffer, &iThumbSize);
+    if (ret) {
+        JPEG_ERROR_LOG("ERR(%s):Fail setInBuf\n", __func__);
+        return ret;
+    }
+
+    ret = allocJpegIonMemory(m_ionJpegClient, &m_ionThumbOutBuffer, &m_pThumbOutputBuffer, iThumbSize);
+    if (ret != ERROR_NONE) {
+        return ret;
+    }
+
+    ret = m_jpegThumb->setOutBuf((char *)m_pThumbOutputBuffer, iThumbSize);
+    if (ret) {
+        JPEG_ERROR_LOG("ERR(%s):Fail setOutBuf\n", __func__);
+        return ret;
+    }
+
+    ret = m_jpegThumb->updateConfig();
+    if (ret) {
+        JPEG_ERROR_LOG("update config failed\n");
+        return ret;
+    }
+
+    if (useMain) {
+
+        int iW=0, iH=0;
+        int input_sizeMain=0, input_sizeThumb=0;
+
+        ret = m_jpegMain->getSize(&iW, &iH);
+        if (ret) {
+            JPEG_ERROR_LOG("ERR(%s):Fail setJpegConfig\n", __func__);
+            return ret;
+        }
+
+        ret = m_scaleDownYuv422(*(m_jpegMain->getInBuf(&input_sizeMain)),
+                              iW,
+                              iH,
+                              *(m_jpegThumb->getInBuf(&input_sizeThumb)),
+                              m_thumbnailW,
+                              m_thumbnailH);
+        if (ret) {
+            JPEG_ERROR_LOG("%s::m_scaleDownYuv422(%d, %d, %d, %d) fail", __func__, iW, iH, m_thumbnailW, m_thumbnailH);
+            return ret;
+        }
+    }
+    else {
+        return ERROR_IMPLEMENT_NOT_YET;
+    }
+
+    int outSizeThumb;
+
+    ret = m_jpegThumb->encode();
+    if (ret) {
+        JPEG_ERROR_LOG("encode failed\n");
+        return ret;
+    }
+
+    outSizeThumb = m_jpegThumb->getJpegSize();
+    if (outSizeThumb<=0) {
+        JPEG_ERROR_LOG("jpeg size is too small\n");
+        return ERROR_THUMB_JPEG_SIZE_TOO_SMALL;
+    }
+
+    *size = (unsigned int)outSizeThumb;
+
+    return ERROR_NONE;
+
+}
+
+int SecJpegEncoder::allocJpegIonMemory(ion_client ionClient, ion_buffer *ionBuffer, char **buffer, int size)
+{
+    int ret = ERROR_NONE;
+
+    if (ionClient == 0) {
+        JPEG_ERROR_LOG("[%s]ionClient is zero (%d)\n", __func__, ionClient);
+        return ERROR_BUFFR_IS_NULL;
+    }
+
+    *ionBuffer = ion_alloc(ionClient, size, 0, ION_HEAP_SYSTEM_MASK);
+    if (*ionBuffer == -1) {
+        JPEG_ERROR_LOG("[%s]ion_alloc(%d) failed\n", __func__, size);
+        *ionBuffer = 0;
+        return ret;
+    }
+
+    *buffer = (char *)ion_map(*ionBuffer, size, 0);
+    if (*buffer == MAP_FAILED) {
+        JPEG_ERROR_LOG("[%s]src ion map failed(%d)\n", __func__, size);
+        ion_free(*ionBuffer);
+        *ionBuffer = 0;
+        *buffer = NULL;
+        return ret;
+    }
+
+    return ret;
+}
+
+void SecJpegEncoder::freeJpegIonMemory(ion_client ionClient, ion_buffer *ionBuffer, char **buffer, int size)
+{
+    if (ionClient == 0) {
+        return;
+    }
+
+    if (*buffer != NULL) {
+        ion_unmap(*buffer, size);
+        *buffer = NULL;
+    }
+
+    if (*ionBuffer != 0) {
+        ion_free(*ionBuffer);
+        *ionBuffer = 0;
+    }
+}
+
diff --git a/exynos5/hal/libhwjpeg/SecJpegEncoderHal.cpp b/exynos5/hal/libhwjpeg/SecJpegEncoderHal.cpp
new file mode 100644
index 0000000..1a3deca
--- /dev/null
+++ b/exynos5/hal/libhwjpeg/SecJpegEncoderHal.cpp
@@ -0,0 +1,497 @@
+/*
+ * Copyright Samsung Electronics Co.,LTD.
+ * Copyright (C) 2011 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.
+ * 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <math.h>
+#include <sys/poll.h>
+
+#include <cutils/log.h>
+
+#include <utils/Log.h>
+
+#include "SecJpegCodecHal.h"
+
+#define JPEG_ERROR_LOG(fmt,...)
+
+#define NUM_PLANES (1)
+#define NUM_BUFFERS (1)
+
+SecJpegEncoderHal::SecJpegEncoderHal()
+{
+    t_iJpegFd = -1;
+    t_bFlagCreate = false;
+}
+
+SecJpegEncoderHal::~SecJpegEncoderHal()
+{
+    if (t_bFlagCreate == true) {
+        this->destroy();
+    }
+}
+
+int SecJpegEncoderHal::create(void)
+{
+    if (t_bFlagCreate == true) {
+        return ERROR_JPEG_DEVICE_ALREADY_CREATE;
+    }
+
+    int iRet = ERROR_NONE;
+
+    t_iJpegFd = open(JPEG_ENC_NODE, O_RDWR, 0);
+
+    if (t_iJpegFd < 0) {
+        t_iJpegFd = -1;
+        JPEG_ERROR_LOG("[%s]: JPEG_ENC_NODE open failed", __func__);
+        return ERROR_CANNOT_OPEN_JPEG_DEVICE;
+    }
+
+    if (t_iJpegFd <= 0) {
+        t_iJpegFd = -1;
+        JPEG_ERROR_LOG("ERR(%s):JPEG device was closed\n", __func__);
+        return ERROR_JPEG_DEVICE_ALREADY_CLOSED;
+    }
+
+    iRet = t_v4l2Querycap(t_iJpegFd);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s]: QUERYCAP failed", __func__);
+        close(t_iJpegFd);
+        return ERROR_CANNOT_OPEN_JPEG_DEVICE;
+    }
+
+    memset(&t_stJpegConfig, 0, sizeof(struct CONFIG));
+    memset(&t_stJpegInbuf, 0, sizeof(struct BUFFER));
+    memset(&t_stJpegOutbuf, 0, sizeof(struct BUFFER));
+
+    t_stJpegConfig.mode = MODE_ENCODE;
+
+    t_bFlagCreate = true;
+    t_bFlagCreateInBuf = false;
+    t_bFlagCreateOutBuf = false;
+    t_bFlagExcute = false;
+
+    t_iPlaneNum = 0;
+
+    return ERROR_NONE;
+}
+
+int SecJpegEncoderHal::destroy(void)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_ALREADY_DESTROY;
+    }
+
+    if (t_iJpegFd > 0) {
+        struct BUF_INFO stBufInfo;
+        int iRet = ERROR_NONE;
+
+        if (t_bFlagExcute) {
+            iRet = t_v4l2StreamOff(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+        }
+
+        if (t_bFlagExcute) {
+            stBufInfo.numOfPlanes = t_iPlaneNum;
+            stBufInfo.memory = V4L2_MEMORY_MMAP;
+
+            stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+            iRet = t_v4l2Reqbufs(t_iJpegFd, 0, &stBufInfo);
+
+            stBufInfo.numOfPlanes = NUM_PLANES;
+            stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+            iRet = t_v4l2Reqbufs(t_iJpegFd, 0, &stBufInfo);
+        }
+
+        iRet = close(t_iJpegFd);
+    }
+
+    t_iJpegFd = -1;
+    t_bFlagCreate = false;
+    return ERROR_NONE;
+}
+
+int SecJpegEncoderHal::setSize(int iW, int iH)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    if (iW < 0 || MAX_JPG_WIDTH < iW) {
+        return ERROR_INVALID_IMAGE_SIZE;
+    }
+
+    if (iH < 0 || MAX_JPG_HEIGHT < iH) {
+        return ERROR_INVALID_IMAGE_SIZE;
+    }
+
+    t_stJpegConfig.width = iW;
+    t_stJpegConfig.height = iH;
+
+    return ERROR_NONE;
+}
+
+int SecJpegEncoderHal::setJpegConfig(void *pConfig)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    if (pConfig == NULL) {
+        return ERROR_JPEG_CONFIG_POINTER_NULL;
+    }
+
+    memcpy(&t_stJpegConfig, pConfig, sizeof(struct CONFIG));
+
+    if (t_stJpegConfig.pix.enc_fmt.in_fmt == V4L2_PIX_FMT_NV12) {
+        t_iPlaneNum = 2;
+    } else {
+        t_iPlaneNum = 1;
+    }
+
+    return ERROR_NONE;
+}
+
+void *SecJpegEncoderHal::getJpegConfig(void)
+{
+    if (t_bFlagCreate == false) {
+        return NULL;
+    }
+
+    return &t_stJpegConfig;
+}
+
+char **SecJpegEncoderHal::getInBuf(int *piInputSize)
+{
+    if (t_bFlagCreate == false) {
+        return NULL;
+    }
+
+     if (t_bFlagCreateInBuf == false) {
+
+        *piInputSize = 0;
+        return NULL;
+    }
+
+    for (int i=0;i<t_iPlaneNum;i++) {
+        piInputSize[i] = t_stJpegInbuf.size[i];
+    }
+
+    return t_stJpegInbuf.addr;
+}
+
+char *SecJpegEncoderHal::getOutBuf(int *piOutputSize)
+{
+    if (t_bFlagCreate == false) {
+        return NULL;
+    }
+
+    if (t_bFlagCreateOutBuf == false) {
+
+        *piOutputSize = 0;
+        return NULL;
+    }
+
+    *piOutputSize = t_stJpegOutbuf.size[0];
+
+    return (char *)(t_stJpegOutbuf.addr[0]);
+}
+
+int SecJpegEncoderHal::setInBuf(char **pcBuf, int *iSize)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    if (pcBuf == NULL) {
+        return ERROR_BUFFR_IS_NULL;
+    }
+
+    if (iSize<=0) {
+        return ERROR_BUFFER_TOO_SMALL;
+    }
+
+    for(int i=0;i<t_iPlaneNum;i++) {
+        t_stJpegInbuf.addr[i] = pcBuf[i];
+        t_stJpegInbuf.size[i] = iSize[i];
+    }
+
+    t_stJpegInbuf.numOfPlanes = t_iPlaneNum;
+
+    t_bFlagCreateInBuf = true;
+
+    return ERROR_NONE;
+}
+
+int  SecJpegEncoderHal::setOutBuf(char *pcBuf, int iSize)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    if (pcBuf == NULL) {
+        return ERROR_BUFFR_IS_NULL;
+    }
+
+    if (iSize<=0) {
+        return ERROR_BUFFER_TOO_SMALL;
+    }
+
+    t_stJpegOutbuf.addr[0] = pcBuf;
+    t_stJpegOutbuf.size[0] = iSize;
+    t_stJpegOutbuf.numOfPlanes = NUM_PLANES;
+
+    t_bFlagCreateOutBuf = true;
+
+    return ERROR_NONE;
+}
+
+int SecJpegEncoderHal::setCache(int iValue)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    if (t_v4l2SetCtrl(t_iJpegFd, V4L2_CID_CACHEABLE, iValue)<0) {
+        JPEG_ERROR_LOG("%s::cache setting failed\n", __func__);
+        return ERROR_CANNOT_CHANGE_CACHE_SETTING;
+    }
+
+    return ERROR_NONE;
+}
+
+int SecJpegEncoderHal::getSize(int *piW, int *piH)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    if (t_stJpegConfig.width == 0 && t_stJpegConfig.height == 0) {
+        return ERROR_SIZE_NOT_SET_YET;
+    }
+
+    *piW = t_stJpegConfig.width;
+    *piH = t_stJpegConfig.height;
+
+    return ERROR_NONE;
+}
+
+int SecJpegEncoderHal::setColorFormat(int iV4l2ColorFormat)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    switch(iV4l2ColorFormat) {
+    case V4L2_PIX_FMT_YUYV:
+    case V4L2_PIX_FMT_RGB565X:
+    case V4L2_PIX_FMT_BGR32:
+    case V4L2_PIX_FMT_RGB32:
+        t_stJpegConfig.pix.enc_fmt.in_fmt = iV4l2ColorFormat;
+        break;
+    default:
+        t_iPlaneNum = 0;
+        return ERROR_INVALID_COLOR_FORMAT;
+        break;
+    }
+
+    if (iV4l2ColorFormat == V4L2_PIX_FMT_NV12) {
+        t_iPlaneNum = 2;
+    } else {
+        t_iPlaneNum = 1;
+    }
+
+    return ERROR_NONE;
+}
+
+int SecJpegEncoderHal::setJpegFormat(int iV4l2JpegFormat)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    switch(iV4l2JpegFormat) {
+    case V4L2_PIX_FMT_JPEG_444:
+    case V4L2_PIX_FMT_JPEG_422:
+    case V4L2_PIX_FMT_JPEG_420:
+    case V4L2_PIX_FMT_JPEG_GRAY:
+        t_stJpegConfig.pix.enc_fmt.out_fmt = iV4l2JpegFormat;
+        break;
+    default:
+        return ERROR_INVALID_JPEG_FORMAT;
+        break;
+    }
+
+    return ERROR_NONE;
+}
+
+int SecJpegEncoderHal::updateConfig(void)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    int iRet = ERROR_NONE;
+
+    iRet = t_v4l2SetJpegcomp(t_iJpegFd, t_stJpegConfig.enc_qual);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s,%d]: S_JPEGCOMP failed", __func__,iRet);
+        return ERROR_INVALID_JPEG_CONFIG;
+    }
+
+    t_stJpegConfig.numOfPlanes = t_iPlaneNum;
+
+    t_stJpegConfig.mode = MODE_ENCODE;
+
+    iRet = t_v4l2SetFmt(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, &t_stJpegConfig);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s,%d]: jpeg input S_FMT failed", __func__,iRet);
+        return ERROR_INVALID_JPEG_CONFIG;
+    }
+
+    struct BUF_INFO stBufInfo;
+
+    stBufInfo.numOfPlanes = t_iPlaneNum;
+    stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+    stBufInfo.memory = V4L2_MEMORY_USERPTR;
+
+    iRet = t_v4l2Reqbufs(t_iJpegFd, NUM_BUFFERS, &stBufInfo);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: Input REQBUFS failed", __func__, iRet);
+        return ERROR_EXCUTE_FAIL;
+    }
+
+    t_stJpegConfig.numOfPlanes = NUM_PLANES;
+    iRet = t_v4l2SetFmt(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, &t_stJpegConfig);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s,%d]: jpeg output S_FMT failed", __func__,iRet);
+        return ERROR_INVALID_JPEG_CONFIG;
+    }
+
+    stBufInfo.numOfPlanes = NUM_PLANES;
+    stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+
+    iRet = t_v4l2Reqbufs(t_iJpegFd, NUM_BUFFERS, &stBufInfo);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: Output REQBUFS failed", __func__, iRet);
+        return ERROR_REQBUF_FAIL;
+    }
+
+    return ERROR_NONE;
+}
+
+int SecJpegEncoderHal::setQuality(int iV4l2Quality)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    if (iV4l2Quality >= 90)
+        t_stJpegConfig.enc_qual = QUALITY_LEVEL_1;
+    else if (iV4l2Quality >= 80)
+        t_stJpegConfig.enc_qual = QUALITY_LEVEL_2;
+    else if (iV4l2Quality >= 70)
+        t_stJpegConfig.enc_qual = QUALITY_LEVEL_3;
+    else
+        t_stJpegConfig.enc_qual = QUALITY_LEVEL_4;
+
+    return ERROR_NONE;
+}
+
+int SecJpegEncoderHal::getJpegSize(void)
+{
+    if (t_bFlagCreate == false) {
+        return 0;
+    }
+
+    int iSize = t_v4l2GetCtrl(t_iJpegFd, V4L2_CID_CAM_JPEG_ENCODEDSIZE);
+
+    if (iSize < 0) {
+        JPEG_ERROR_LOG("%s::Fail to JPEG output buffer!!\n", __func__);
+        return 0;
+    }
+
+    return iSize;
+}
+
+int SecJpegEncoderHal::encode(void)
+{
+    if (t_bFlagCreate == false) {
+        return ERROR_JPEG_DEVICE_NOT_CREATE_YET;
+    }
+
+    struct BUF_INFO stBufInfo;
+    int iRet = ERROR_NONE;
+
+    t_bFlagExcute = true;
+
+    stBufInfo.numOfPlanes = t_iPlaneNum;
+    stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+
+    stBufInfo.memory = V4L2_MEMORY_USERPTR;
+
+    iRet = t_v4l2Qbuf(t_iJpegFd, &stBufInfo, &t_stJpegInbuf);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: Input QBUF failed", __func__, iRet);
+        return ERROR_EXCUTE_FAIL;
+    }
+
+    stBufInfo.numOfPlanes = NUM_PLANES;
+    stBufInfo.buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+
+    iRet = t_v4l2Qbuf(t_iJpegFd, &stBufInfo, &t_stJpegOutbuf);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: Output QBUF failed", __func__, iRet);
+        return ERROR_EXCUTE_FAIL;
+    }
+
+    stBufInfo.numOfPlanes = t_iPlaneNum;
+    iRet = t_v4l2StreamOn(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: input stream on failed", __func__, iRet);
+        return ERROR_EXCUTE_FAIL;
+    }
+    stBufInfo.numOfPlanes = NUM_PLANES;
+    iRet = t_v4l2StreamOn(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: output stream on failed", __func__, iRet);
+        return ERROR_EXCUTE_FAIL;
+    }
+
+    stBufInfo.numOfPlanes = t_iPlaneNum;
+    iRet = t_v4l2Dqbuf(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, V4L2_MEMORY_MMAP);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: Intput DQBUF failed", __func__, iRet);
+        return ERROR_EXCUTE_FAIL;
+    }
+    stBufInfo.numOfPlanes = NUM_PLANES;
+    iRet = t_v4l2Dqbuf(t_iJpegFd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, V4L2_MEMORY_MMAP);
+    if (iRet < 0) {
+        JPEG_ERROR_LOG("[%s:%d]: Output DQBUF failed", __func__, iRet);
+        return ERROR_EXCUTE_FAIL;
+    }
+    return ERROR_NONE;
+}
+