Add DCM service 30/48930/5 accepted/tizen/mobile/20151008.004722 accepted/tizen/tv/20151008.004753 accepted/tizen/wearable/20151008.004759 submit/tizen/20151007.093349
authorJi Yong Min <jiyong.min@samsung.com>
Fri, 2 Oct 2015 00:36:14 +0000 (09:36 +0900)
committerJi Yong Min <jiyong.min@samsung.com>
Mon, 5 Oct 2015 08:03:23 +0000 (17:03 +0900)
Change-Id: Ie5bfd1f085790523b2637d0a711391f3363a44ba

31 files changed:
AUTHORS [new file with mode: 0755]
CMakeLists.txt [new file with mode: 0755]
LICENSE.APLv2.0 [new file with mode: 0755]
NOTICE [new file with mode: 0755]
dcm-service.pc.in [new file with mode: 0755]
include/DcmColorUtils.h [new file with mode: 0755]
include/DcmDbUtils.h [new file with mode: 0755]
include/DcmDebugUtils.h [new file with mode: 0755]
include/DcmFaceUtils.h [new file with mode: 0755]
include/DcmIpcUtils.h [new file with mode: 0755]
include/DcmMainSvc.h [new file with mode: 0755]
include/DcmScanSvc.h [new file with mode: 0755]
include/DcmTypes.h [new file with mode: 0755]
libdcm-face/dcm-face-debug.h [new file with mode: 0755]
libdcm-face/dcm-face.c [new file with mode: 0755]
libdcm-face/dcm-face_mediavision.c [new file with mode: 0755]
libdcm-face/dcm-face_priv.h [new file with mode: 0755]
libdcm-face/include/dcm-face.h [new file with mode: 0755]
libdcm-face/include/dcm-face_type.h [new file with mode: 0755]
libdcm-util/dcm_image_codec.cpp [new file with mode: 0755]
libdcm-util/include/dcm_image_codec.h [new file with mode: 0755]
libdcm-util/include/dcm_image_debug_utils.h [new file with mode: 0755]
packaging/dcm-service.manifest [new file with mode: 0755]
packaging/dcm-service.spec [new file with mode: 0755]
src/DcmColorUtils.cpp [new file with mode: 0755]
src/DcmDbUtils.cpp [new file with mode: 0755]
src/DcmFaceUtils.cpp [new file with mode: 0755]
src/DcmIpcUtils.cpp [new file with mode: 0755]
src/DcmScanSvc.cpp [new file with mode: 0755]
svc/CMakeLists.txt [new file with mode: 0755]
svc/DcmMainSvc.cpp [new file with mode: 0755]

diff --git a/AUTHORS b/AUTHORS
new file mode 100755 (executable)
index 0000000..6e3e3ee
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,2 @@
+Haejeon Kim <backto.kim at samsung dot com>
+Jiyong Min <jiyong.min at samsung dot com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..480328c
--- /dev/null
@@ -0,0 +1,94 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(dcm-service C CXX)
+SET(VERSION_MAJOR 1)
+SET(VERSION "${VERSION_MAJOR}.0.0")
+
+SET(DCMSVC-LIB "dcm-service")
+SET(DCMFACE-LIB "dcm-face")
+SET(DCMUTIL-LIB "dcm-util")
+SET(SRCS
+       src/DcmColorUtils.cpp
+       src/DcmDbUtils.cpp
+       src/DcmFaceUtils.cpp
+       src/DcmIpcUtils.cpp
+       src/DcmScanSvc.cpp
+       )
+
+SET(FACE_SRCS
+       libdcm-face/dcm-face.c
+       libdcm-face/dcm-face_mediavision.c
+       )
+
+SET(UTIL_SRCS
+       libdcm-util/dcm_image_codec.cpp
+       )
+
+SET(VENDOR "samsung")
+SET(PACKAGE ${PROJECT_NAME})
+SET(PKGNAME "com.${VENDOR}.${PACKAGE}")
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(BINDIR "${PREFIX}/bin")
+SET(DATADIR "${PREFIX}/share")
+SET(EXEC_PREFIX "\${prefix}")
+SET(LIBDIR "\${prefix}/lib")
+SET(INCLUDEDIR "\${prefix}/include")
+
+IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+       SET(CMAKE_BUILD_TYPE "Release")
+ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+MESSAGE("Build type: ${CMAKE_BUILD_TYPE}")
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/libdcm-util/include ${CMAKE_SOURCE_DIR}/libdcm-face/include)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(pkgs REQUIRED glib-2.0 gthread-2.0 dlog ecore-evas evas sqlite3 capi-media-image-util capi-media-vision libexif media-thumbnail libmedia-utils 
+mmutil-imgp uuid vconf libtzplatform-config)
+
+FOREACH(flag ${pkgs_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_C_FLAGS_RELEASE "-O2 -fPIC")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -fpermissive -fdump-rtl-expand -fPIC -Wall")
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_CXX_FLAGS_RELEASE "-O2 -fPIC")
+
+FIND_PROGRAM(UNAME NAMES uname)
+EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH")
+IF("${ARCH}" STREQUAL "arm")
+       ADD_DEFINITIONS("-DTARGET")
+       MESSAGE("add -DTARGET")
+ENDIF("${ARCH}" STREQUAL "arm")
+
+ADD_DEFINITIONS("-DVENDOR=\"${VENDOR}\"")
+ADD_DEFINITIONS("-DPACKAGE=\"${PACKAGE}\"")
+ADD_DEFINITIONS("-DPACKAGE_NAME=\"${PKGNAME}\"")
+ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"")
+#ADD_DEFINITIONS("-D_PERFORMANCE_CHECK_")
+
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--hash-style=both")
+CONFIGURE_FILE(dcm-service.pc.in dcm-service.pc @ONLY)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/dcm-service.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+
+ADD_SUBDIRECTORY(svc)
+
+LINK_DIRECTORIES(${LIB_INSTALL_DIR})
+
+#AUX_SOURCE_DIRECTORY(${CMAKE_SOURCE_DIR}/src SRCS)
+ADD_LIBRARY(${DCMFACE-LIB} SHARED ${FACE_SRCS})
+SET_TARGET_PROPERTIES(${DCMFACE-LIB} PROPERTIES SOVERSION ${VERSION_MAJOR})
+SET_TARGET_PROPERTIES(${DCMFACE-LIB} PROPERTIES VERSION ${VERSION})
+ADD_LIBRARY(${DCMUTIL-LIB} SHARED ${UTIL_SRCS})
+SET_TARGET_PROPERTIES(${DCMUTIL-LIB} PROPERTIES SOVERSION ${VERSION_MAJOR})
+SET_TARGET_PROPERTIES(${DCMUTIL-LIB} PROPERTIES VERSION ${VERSION})
+ADD_LIBRARY(${DCMSVC-LIB} SHARED ${SRCS})
+TARGET_LINK_LIBRARIES(${DCMSVC-LIB} ${pkgs_LDFLAGS} ${DCMFACE-LIB} ${DCMUTIL-LIB})
+SET_TARGET_PROPERTIES(${DCMSVC-LIB} PROPERTIES SOVERSION ${VERSION_MAJOR})
+SET_TARGET_PROPERTIES(${DCMSVC-LIB} PROPERTIES VERSION ${VERSION})
+
+INSTALL(TARGETS ${DCMFACE-LIB} LIBRARY DESTINATION ${LIB_INSTALL_DIR})
+INSTALL(TARGETS ${DCMUTIL-LIB} LIBRARY DESTINATION ${LIB_INSTALL_DIR})
+INSTALL(TARGETS ${DCMSVC-LIB} LIBRARY DESTINATION ${LIB_INSTALL_DIR})
+
diff --git a/LICENSE.APLv2.0 b/LICENSE.APLv2.0
new file mode 100755 (executable)
index 0000000..261eeb9
--- /dev/null
@@ -0,0 +1,201 @@
+                                 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
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
diff --git a/NOTICE b/NOTICE
new file mode 100755 (executable)
index 0000000..ccdad52
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,3 @@
+Copyright (c) Samsung Electronics Co., Ltd. All rights reserved.
+Except as noted, this software is licensed under Apache License, Version 2.
+Please, see the LICENSE file for Apache License terms and conditions.
diff --git a/dcm-service.pc.in b/dcm-service.pc.in
new file mode 100755 (executable)
index 0000000..1a55c6d
--- /dev/null
@@ -0,0 +1,14 @@
+
+# Package Information for pkg-config
+
+prefix=@PREFIX@
+exec_prefix=/usr
+libdir=@LIB_INSTALL_DIR@
+includedir=/usr/include/media
+
+Name: @PC_NAME@
+Description: @PACKAGE_DESCRIPTION@
+Version: @VERSION@
+Requires: @PC_REQUIRED@
+Libs: -L${libdir} @PC_LDFLAGS@
+Cflags: -I${includedir} @PC_CFLAGS@
diff --git a/include/DcmColorUtils.h b/include/DcmColorUtils.h
new file mode 100755 (executable)
index 0000000..1ea7f69
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _DCM_SVC_COLOR_H_
+#define _DCM_SVC_COLOR_H_
+
+#include <DcmTypes.h>
+
+namespace DcmColorUtils {
+       int runColorExtractProcess(DcmScanItem *scan_item, DcmImageInfo *image_info);
+}
+
+#endif /*_DCM_SVC_COLOR_H_*/
+
diff --git a/include/DcmDbUtils.h b/include/DcmDbUtils.h
new file mode 100755 (executable)
index 0000000..33b450d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _DCM_DB_UTILS_H_
+#define _DCM_DB_UTILS_H_
+
+#include <stdbool.h>
+#include <sqlite3.h>
+#include <glib.h>
+#include <media-util.h>
+/*#include <media-util-noti-face.h> */
+#include <dcm-face.h>
+#include <DcmTypes.h>
+
+typedef bool (*dcm_svc_db_face_cb)(DcmFaceItem *face_item, void *user_data);
+
+class DcmDbUtils {
+private:
+       DcmDbUtils();
+       static DcmDbUtils *dcmDbUtils;
+       static MediaDBHandle *db_handle;
+
+public:
+       uid_t dcm_uid;
+       static DcmDbUtils *getInstance();
+       int _dcm_svc_db_connect(uid_t uid);
+       int _dcm_svc_db_disconnect();
+       int _dcm_svc_db_get_scan_image_list_by_path(GList **image_list, bool mmc_mounted, const char *file_path);
+       int _dcm_svc_db_get_scan_image_list_from_db(GList **image_list, bool mmc_mounted);
+       int _dcm_svc_db_insert_category_to_db(void *item);
+       int _dcm_svc_db_generate_uuid(DcmFaceItem **face);
+       int _dcm_svc_db_insert_face_to_db(DcmFaceItem *face);
+       int _dcm_svc_db_update_color_to_db(const DcmColorItem color);
+       int _dcm_svc_db_insert_face_to_face_scan_list(DcmScanItem *scan_item);
+       int _dcm_svc_db_check_scanned_by_media_uuid(const char *media_uuid, bool *media_scanned);
+       int _dcm_svc_db_send_noti(DcmFaceItem *face, DcmFaceItemUpdateItem update_item, DcmFaceItemUpdateType update_type);
+};
+
+#endif /*_DCM_DB_UTILS_H_*/
+
diff --git a/include/DcmDebugUtils.h b/include/DcmDebugUtils.h
new file mode 100755 (executable)
index 0000000..5d337f3
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _DCM_DEBUG_UTILS_H_
+#define _DCM_DEBUG_UTILS_H_
+
+#include <dlog.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define _USE_DLOG_
+#define LOG_TAG "DCM_SVC"
+
+/* anci c color type */
+#define FONT_COLOR_RESET    "\033[0m"
+#define FONT_COLOR_RED      "\033[31m"
+#define FONT_COLOR_GREEN    "\033[32m"
+#define FONT_COLOR_YELLOW   "\033[33m"
+#define FONT_COLOR_BLUE     "\033[34m"
+#define FONT_COLOR_PURPLE   "\033[35m"
+#define FONT_COLOR_CYAN     "\033[36m"
+#define FONT_COLOR_GRAY     "\033[37m"
+
+/*#undef _USE_DLOG_ */
+#ifdef _USE_DLOG_
+#define dcm_debug(fmt, arg...) do { \
+               LOGD(FONT_COLOR_CYAN""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_info(fmt, arg...) do { \
+               LOGI(FONT_COLOR_YELLOW""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_warn(fmt, arg...) do { \
+               LOGW(FONT_COLOR_GREEN""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_error(fmt, arg...) do { \
+               LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_sec_debug(fmt, arg...) do { \
+               SECURE_LOGD(FONT_COLOR_CYAN""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_sec_info(fmt, arg...) do { \
+               SECURE_LOGI(FONT_COLOR_YELLOW""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_sec_warn(fmt, arg...) do { \
+               SECURE_LOGW(FONT_COLOR_GREEN""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_sec_error(fmt, arg...) do { \
+               SECURE_LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+#define dcm_debug_fenter() do { \
+                       LOGD(FONT_COLOR_RESET"<Enter>"); \
+               } while (0)
+
+#define dcm_debug_fleave() do { \
+                       LOGD(FONT_COLOR_RESET"<Leave>"); \
+               } while (0)
+#define dcm_retm_if(expr, fmt, arg...) do { \
+                       if(expr) { \
+                               LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg); \
+                               return; \
+                       } \
+               } while (0)
+
+#define dcm_retvm_if(expr, val, fmt, arg...) do { \
+                       if(expr) { \
+                               LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg); \
+                               return (val); \
+                       } \
+               } while (0)
+#else
+#define dcm_debug(fmt, arg...)
+#define dcm_info(fmt, arg...)
+#define dcm_warn(fmt, arg...)
+#define dcm_error(fmt, arg...)
+
+#define dcm_sec_debug(fmt, arg...)
+#define dcm_sec_info(fmt, arg...)
+#define dcm_sec_warn(fmt, arg...)
+#define dcm_sec_error(fmt, arg...)
+
+#endif
+
+#define DCM_CHECK_VAL(expr, val)               dcm_retvm_if(!(expr), val,   "Invalid parameter, return ERROR code!")
+#define DCM_CHECK_NULL(expr)                   dcm_retvm_if(!(expr), NULL,  "Invalid parameter, return NULL!")
+#define DCM_CHECK_FALSE(expr)                  dcm_retvm_if(!(expr), FALSE, "Invalid parameter, return FALSE!")
+#define DCM_CHECK(expr)                                dcm_retm_if (!(expr),        "Invalid parameter, return!")
+
+#define DCM_SAFE_FREE(ptr) { if(ptr) {free(ptr); ptr = NULL;} }
+
+#endif /* _DCM_DEBUG_UTILS_H_ */
+
diff --git a/include/DcmFaceUtils.h b/include/DcmFaceUtils.h
new file mode 100755 (executable)
index 0000000..8e64a28
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _DCM_SVC_FACE_H_
+#define _DCM_SVC_FACE_H_
+
+#include <DcmTypes.h>
+
+namespace DcmFaceUtils {
+       int initialize();
+       int finalize();
+       int runFaceRecognizeProcess(DcmScanItem *scan_item, DcmImageInfo *image_info);
+}
+
+#endif /*_DCM_SVC_FACE_H_*/
+
diff --git a/include/DcmIpcUtils.h b/include/DcmIpcUtils.h
new file mode 100755 (executable)
index 0000000..0b37751
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _DCM_SVC_IPC_H_
+#define _DCM_SVC_IPC_H_
+
+#include <DcmTypes.h>
+
+namespace DcmIpcUtils {
+       int createSocket(int *socket_fd, DcmIpcPortType port);
+       int acceptSocket(int serv_sock, int *client_sock);
+       int receiveSocketMsg(int client_sock, DcmIpcMsg *recv_msg);
+       int sendSocketMsg(DcmIpcMsgType msg_type, uid_t uid, const char *msg, DcmIpcPortType port);
+       int closeSocket(int socket_fd);
+       int createUDPSocket(int *socket_fd);
+       int receiveUDPSocketMsg(int socket_fd, DcmIpcMsg *recv_msg);
+       int sendUDPSocketMsg(DcmIpcMsgType msg_type, const char *msg);
+       int closeUDPSocket(int socket_fd);
+       int sendFaceMsg(const char *media_uuid);
+}
+
+#endif /* _DCM_SVC_IPC_H_ */
+
diff --git a/include/DcmMainSvc.h b/include/DcmMainSvc.h
new file mode 100755 (executable)
index 0000000..b7ac079
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _DCM_MAIN_SVC_H_
+#define _DCM_MAIN_SVC_H_
+
+#include <glib.h>
+#include <DcmTypes.h>
+#include <DcmIpcUtils.h>
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__ ((visibility("default")))
+#endif
+
+class DcmMainSvc {
+       static DcmMainSvc *dcmMainSvc;
+
+public:
+       /* scan thread related */
+       /* GMainLoop *g_dcm_svc_mainloop; */
+
+       /* scan thread related */
+       GThread *scan_thread;
+       GAsyncQueue *scan_thread_ready;
+
+       /* main thread related */
+       GMainContext *main_loop_context;
+       GMainContext *main_thread_context;
+       GIOChannel *main_thread_recv_channel;
+       int main_thread_recv_socket;
+       GSource *main_thread_quit_timer;
+       bool scan_thread_working;
+
+       static DcmMainSvc *getInstance();
+       void dcmServiceStartjobs();
+       void dcmServiceFinishjobs();
+       int waitScanThreadReady();
+       int createScanThread();
+       int createQuitTimerMainLoop();
+       void quitDcmSvcMainLoop();
+};
+
+#endif /* _DCM_MAIN_SVC_H_ */
+
diff --git a/include/DcmScanSvc.h b/include/DcmScanSvc.h
new file mode 100755 (executable)
index 0000000..8023f09
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _DCM_SCAN_SVC_H_
+#define _DCM_SCAN_SVC_H_
+
+#include <glib.h>
+
+namespace DcmScanMain {
+       gboolean runScanThread(void *data);
+}
+
+#endif /* _DCM_SCAN_SVC_H_ */
+
diff --git a/include/DcmTypes.h b/include/DcmTypes.h
new file mode 100755 (executable)
index 0000000..d371c11
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _DCM_TYPES_H_
+#define _DCM_TYPES_H_
+
+#include <glib.h>
+#include <unistd.h>
+
+/*
+  * Definitions defined here can be used by all threads
+  * If a definition can only be used in a specific thread, then this definition should be defined in that thread, not here.
+  */
+
+#define DCM_MAX_PATH_SIZE 4096
+#define DCM_IPC_MSG_MAX_SIZE 4096
+#define DCM_DB_QUERY_MAX_SIZE 4096
+
+typedef enum {
+       DCM_SUCCESS,
+       DCM_ERROR_INVALID_PARAMETER,
+       DCM_ERROR_NETWORK,
+       DCM_ERROR_DB_OPERATION,
+       DCM_ERROR_DB_NO_RESULT,
+       DCM_ERROR_FILE_NOT_EXIST,
+       DCM_ERROR_OUT_OF_MEMORY,
+       DCM_ERROR_VCONF_FAIL,
+       DCM_ERROR_SCAN_OPERATION,
+       DCM_ERROR_IMAGE_ALREADY_SCANNED,
+       DCM_ERROR_CREATE_THREAD_FAILED,
+       DCM_ERROR_IMAGE_UTIL_FAILED,
+       DCM_ERROR_ASYNC_QUEUE_FAILED,
+       DCM_ERROR_IPC,
+       DCM_ERROR_IPC_INVALID_MSG,
+       DCM_ERROR_INVALID_IMAGE_SIZE,
+       DCM_ERROR_CODEC_DECODE_FAILED,
+       DCM_ERROR_CODEC_ENCODE_FAILED,
+       DCM_ERROR_UNSUPPORTED_IMAGE_TYPE,
+       DCM_ERROR_FACE_ENGINE_FAILED,
+       DCM_ERROR_EXIF_FAILED,
+       DCM_ERROR_UUID_GENERATE_FAILED,
+       DCM_ERROR_DUPLICATED_DATA,
+} DcmErrorType;
+
+typedef enum {
+       DCM_IPC_MSG_NONE,
+       DCM_IPC_MSG_SERVICE_READY,
+       DCM_IPC_MSG_KILL_SERVICE,
+       DCM_IPC_MSG_SCAN_READY,
+       DCM_IPC_MSG_SCAN_ALL,
+       DCM_IPC_MSG_SCAN_SINGLE,
+       DCM_IPC_MSG_SCAN_COMPLETED,
+       DCM_IPC_MSG_SCAN_TERMINATED,
+       DCM_IPC_MSG_MAX,
+} DcmIpcMsgType;
+
+typedef enum {
+       DCM_IPC_PORT_SCAN_RECV,
+       DCM_IPC_PORT_DCM_RECV,
+       DCM_IPC_PORT_THUMB_RECV,
+       DCM_IPC_PORT_MAX,
+} DcmIpcPortType;
+
+typedef struct {
+       DcmIpcMsgType msg_type;
+       uid_t uid;
+       size_t msg_size; /*this is size of message below and this does not include the terminationg null byte ('\0'). */
+       char msg[DCM_IPC_MSG_MAX_SIZE];
+} DcmIpcMsg;
+
+typedef enum {
+       DCM_SCAN_ITEM_TYPE_NONE,
+       DCM_SCAN_ITEM_TYPE_SCAN_ALL,
+       DCM_SCAN_ITEM_TYPE_SCAN_SINGLE,
+       DCM_SCAN_ITEM_TYPE_MAX,
+} DcmScanItemType;
+
+typedef struct {
+       char *media_uuid;
+       char *file_path;
+       char *storage_uuid;
+       int image_width;
+       int image_height;
+       int image_orientation;
+       char *mime_type;
+       DcmScanItemType scan_item_type;
+} DcmScanItem;
+
+typedef enum {
+       DCM_FACE_ITEM_UPDATE_FACE       = 0,    /**< One face item is upated */
+} DcmFaceItemUpdateItem;
+
+typedef enum {
+       DCM_FACE_ITEM_INSERT            = 0,    /**< Database update operation is INSERT */
+       DCM_FACE_ITEM_DELETE            = 1,    /**< Database update operation is DELETE */
+       DCM_FACE_ITEM_UPDATE            = 2,    /**< Database update operation is UPDATE */
+       DCM_FACE_ITEM_REMOVE            = 3,    /**< Database update operation is REMOVE */
+} DcmFaceItemUpdateType;
+
+typedef struct {
+       char *face_uuid;
+       char *media_uuid;
+       unsigned int face_rect_x;
+       unsigned int face_rect_y;
+       unsigned int face_rect_w;
+       unsigned int face_rect_h;
+       int orientation;
+} DcmFaceItem;
+
+typedef struct {
+       char *media_uuid;
+       char *storage_uuid;
+       unsigned char rgb_r;
+       unsigned char rgb_g;
+       unsigned char rgb_b;
+} DcmColorItem;
+
+typedef enum {
+       DCM_SVC_I420,
+       DCM_SVC_RGB888,
+} DcmImageDecodeType;
+
+typedef struct {
+       unsigned char *pixel;           /* decoding results, must be freed after use */
+       unsigned int size;
+       int orientation;                        /* orientation information extracted from exif */
+       unsigned int original_width;                    /* original image width */
+       unsigned int original_height;           /* original image height */
+       unsigned int buffer_width;                      /* scaled image width used by decoder (width/height ratio should be the same as original) */
+       unsigned int buffer_height;                     /* scaled image height used by decoder (width/height ratio should be the same as original) */
+       DcmImageDecodeType decode_type; /* decoding pre-condition */
+} DcmImageInfo;
+
+#endif /* _DCM_TYPES_H_ */
+
diff --git a/libdcm-face/dcm-face-debug.h b/libdcm-face/dcm-face-debug.h
new file mode 100755 (executable)
index 0000000..5c0886c
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __FACE_DEBUG_H__
+#define __FACE_DEBUG_H__
+
+#include <dlog.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define _USE_DLOG_
+#define LOG_TAG "DCM_FACE"
+
+/* anci c color type */
+#define FONT_COLOR_RESET    "\033[0m"
+#define FONT_COLOR_RED      "\033[31m"
+#define FONT_COLOR_GREEN    "\033[32m"
+#define FONT_COLOR_YELLOW   "\033[33m"
+#define FONT_COLOR_BLUE     "\033[34m"
+#define FONT_COLOR_PURPLE   "\033[35m"
+#define FONT_COLOR_CYAN     "\033[36m "
+#define FONT_COLOR_GRAY     "\033[37m"
+
+/*#undef _USE_DLOG_ */
+#ifdef _USE_DLOG_
+#define dcm_debug(fmt, arg...) do { \
+               LOGD(FONT_COLOR_CYAN""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_info(fmt, arg...) do { \
+               LOGI(FONT_COLOR_YELLOW""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_warn(fmt, arg...) do { \
+               LOGW(FONT_COLOR_GREEN""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_error(fmt, arg...) do { \
+               LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_sec_debug(fmt, arg...) do { \
+               SECURE_LOGD(FONT_COLOR_CYAN""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_sec_info(fmt, arg...) do { \
+               SECURE_LOGI(FONT_COLOR_YELLOW""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_sec_warn(fmt, arg...) do { \
+               SECURE_LOGW(FONT_COLOR_GREEN""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_sec_error(fmt, arg...) do { \
+               SECURE_LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+#define dcm_debug_fenter() do { \
+                       LOGD(FONT_COLOR_RESET"<Enter>"); \
+               } while (0)
+
+#define dcm_debug_fleave() do { \
+                       LOGD(FONT_COLOR_RESET"<Leave>"); \
+               } while (0)
+#define dcm_retm_if(expr, fmt, arg...) do { \
+                       if(expr) { \
+                               LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg); \
+                               return; \
+                       } \
+               } while (0)
+
+#define dcm_retvm_if(expr, val, fmt, arg...) do { \
+                       if(expr) { \
+                               LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg); \
+                               return (val); \
+                       } \
+               } while (0)
+#else
+#define dcm_debug(fmt, arg...)
+#define dcm_info(fmt, arg...)
+#define dcm_warn(fmt, arg...)
+#define dcm_error(fmt, arg...)
+
+#define dcm_sec_debug(fmt, arg...)
+#define dcm_sec_info(fmt, arg...)
+#define dcm_sec_warn(fmt, arg...)
+#define dcm_sec_error(fmt, arg...)
+#endif
+
+
+#endif /*__FACE_DEBUG_H__ */
diff --git a/libdcm-face/dcm-face.c b/libdcm-face/dcm-face.c
new file mode 100755 (executable)
index 0000000..5533958
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "dcm-face.h"
+#include "dcm-face_priv.h"
+
+
+#define FACE_MAGIC_VALID       (0xFF993311)
+#define FACE_MAGIC_INVALID     (0x393A3B3C)
+
+EXPORT_API int dcm_face_create(__inout dcm_face_h *handle)
+{
+       int ret = FACE_ERROR_NONE;
+
+       dcm_retvm_if (handle == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid handle");
+
+       FaceHandleT *pFaceHandle = (FaceHandleT *)calloc(1, sizeof(FaceHandleT));
+       dcm_retvm_if (pFaceHandle == NULL, FACE_ERROR_OUT_OF_MEMORY, "malloc fail");
+
+       ret = _face_handle_create(&(pFaceHandle->fengine));
+       dcm_retvm_if (ret != FACE_ERROR_NONE, ret, "fail to _face_handle_create");
+
+       pFaceHandle->magic = FACE_MAGIC_VALID;
+
+       *handle = pFaceHandle;
+
+       dcm_info("face created. handle=0x%08x", *handle);
+
+       return ret;
+}
+
+EXPORT_API int dcm_face_destroy(__in dcm_face_h handle)
+{
+       int ret = FACE_ERROR_NONE;
+       dcm_info("face destroy. handle=0x%08x", handle);
+
+       dcm_retvm_if (handle == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid handle");
+
+       ret = _face_handle_destroy(handle->fengine);
+       if (ret != FACE_ERROR_NONE) {
+               dcm_error("fail to _face_handle_destroy");
+               return ret;
+       }
+
+       handle->magic = FACE_MAGIC_INVALID;
+
+       if (handle->image_info != NULL)
+               DCM_SAFE_FREE(handle->image_info->data);
+       DCM_SAFE_FREE(handle->image_info);
+       DCM_SAFE_FREE(handle);
+
+       return ret;
+}
+
+EXPORT_API int dcm_face_get_prefered_colorspace(__in dcm_face_h handle, __out face_image_colorspace_e *colorspace)
+{
+       dcm_retvm_if (handle == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid handle");
+       dcm_retvm_if (colorspace == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid colorspace");
+
+       *colorspace = FACE_IMAGE_COLORSPACE_RGB888;
+
+       return FACE_ERROR_NONE;
+}
+
+EXPORT_API int dcm_face_set_image_info(dcm_face_h handle, face_image_colorspace_e colorspace, unsigned char *buffer, unsigned int width, unsigned int height, unsigned int size)
+{
+       FaceHandleT *_handle = (FaceHandleT *)handle;
+       unsigned char *data = NULL;
+
+       dcm_debug_fenter();
+
+       dcm_retvm_if (handle == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid handle");
+       dcm_retvm_if (buffer == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid buffer");
+
+       switch (colorspace) {
+               case FACE_IMAGE_COLORSPACE_YUV420:
+               case FACE_IMAGE_COLORSPACE_RGB888:
+                       data = (unsigned char *)calloc(1, size);
+                       memcpy(data, buffer, size);
+                       break;
+               default:
+                       dcm_error("Invalid colorspace : [%d]", colorspace);
+                       return FACE_ERROR_INVALID_PARAMTER;
+       }
+
+       if (_handle->image_info != NULL)
+               DCM_SAFE_FREE(_handle->image_info->data);
+       DCM_SAFE_FREE(_handle->image_info);
+
+       _handle->image_info = (FaceImage *)calloc(1, sizeof(FaceImage));
+
+       if (_handle->image_info == NULL) {
+               dcm_error("Out of memory");
+               DCM_SAFE_FREE(data);
+               return FACE_ERROR_OUT_OF_MEMORY;
+       }
+
+       _handle->image_info->data = data;
+       _handle->image_info->width = width;
+       _handle->image_info->height = height;
+       _handle->image_info->size = size;
+       _handle->image_info->colorspace = colorspace;
+       _handle->image_info->magic = FACE_IMAGE_MAGIC;
+
+       dcm_debug_fleave();
+
+       return FACE_ERROR_NONE;
+}
+
+EXPORT_API int dcm_face_get_face_info(__in dcm_face_h handle, __out face_info_s *face_info)
+{
+       int ret = FACE_ERROR_NONE;
+
+       dcm_debug_fenter();
+
+       dcm_retvm_if (handle == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid handle");
+       dcm_retvm_if (face_info == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid face_info");
+
+       ret = _face_detect_faces(handle, &(face_info->rects), &(face_info->count));
+       if (ret != FACE_ERROR_NONE) {
+               dcm_error("fail to _face_detect_faces");
+       }
+
+       dcm_debug_fleave();
+
+       return ret;
+}
+
+EXPORT_API int dcm_face_destroy_face_info(face_info_s *face_info)
+{
+       dcm_retvm_if (face_info == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid face_info");
+
+       DCM_SAFE_FREE(face_info->rects);
+       DCM_SAFE_FREE(face_info);
+
+       return FACE_ERROR_NONE;
+}
diff --git a/libdcm-face/dcm-face_mediavision.c b/libdcm-face/dcm-face_mediavision.c
new file mode 100755 (executable)
index 0000000..dcab375
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdbool.h>
+#include <mv_common.h>
+#include <mv_face.h>
+#include <mv_face_type.h>
+
+#include "dcm-face-debug.h"
+#include "dcm-face.h"
+#include "dcm-face_priv.h"
+
+typedef struct media_vision_h {
+       mv_engine_config_h cfg;
+       mv_source_h source;
+} mv_handle;
+
+typedef struct media_vision_result_s {
+       face_error_e error;
+       face_rect_s *face_rect;
+       int count;
+} mv_faceInfo;
+
+static face_error_e __convert_to_mv_error_e(mv_error_e err)
+{
+       if (err != MEDIA_VISION_ERROR_NONE)
+               dcm_error("Error from media vision : %d", err);
+
+       switch (err) {
+               case MEDIA_VISION_ERROR_NONE:
+                       return FACE_ERROR_NONE;
+
+               case MEDIA_VISION_ERROR_NOT_SUPPORTED:
+                       return FACE_ERROR_INVALID_PARAMTER;
+
+               case MEDIA_VISION_ERROR_INVALID_PARAMETER:
+                       return FACE_ERROR_INVALID_PARAMTER;
+
+               case MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT:
+                       return FACE_ERROR_INVALID_PARAMTER;
+
+               case MEDIA_VISION_ERROR_OUT_OF_MEMORY:
+                       return FACE_ERROR_OUT_OF_MEMORY;
+
+               default:
+                       break;
+       }
+
+       return FACE_ERROR_OPERATION_FAILED;
+}
+
+static int __convert_to_mv_colorspace_e(face_image_colorspace_e src, mv_colorspace_e *dst)
+{
+       switch (src) {
+               case FACE_IMAGE_COLORSPACE_YUV420:
+                       *dst = MEDIA_VISION_COLORSPACE_I420;
+                       return FACE_ERROR_NONE;
+               case FACE_IMAGE_COLORSPACE_RGB888:
+                       *dst = MEDIA_VISION_COLORSPACE_RGB888;
+                       return FACE_ERROR_NONE;
+               default:
+                       *dst = MEDIA_VISION_COLORSPACE_INVALID;
+                       dcm_error("Unknown colorspace : %d", src);
+                       break;
+       }
+
+       return FACE_ERROR_INVALID_PARAMTER;
+}
+
+void __face_detected_cb(mv_source_h source, mv_engine_config_h cfg, mv_rectangle_s *faces_locations, int number_of_faces, void *user_data)
+{
+       mv_faceInfo* _data = (mv_faceInfo*)user_data;
+
+       dcm_error("[No-Error] number of faces: %d", number_of_faces);
+
+       if (number_of_faces == 0) {
+               _data->face_rect = NULL;
+               _data->count = 0;
+               _data->error = FACE_ERROR_NONE;
+               return;
+       }
+
+       _data->face_rect = (face_rect_s *)calloc(number_of_faces, sizeof(face_rect_s));
+       if (_data->face_rect == NULL) {
+               dcm_error("Cannout allocate face_rect_s");
+               _data->face_rect = NULL;
+               _data->count = 0;
+               _data->error = FACE_ERROR_OUT_OF_MEMORY;
+               return;
+       }
+
+       int i = 0;
+
+       for (i = 0; i < number_of_faces ; i++) {
+               _data->face_rect[i].x = faces_locations[i].point.x;
+               _data->face_rect[i].y = faces_locations[i].point.y;
+               _data->face_rect[i].w = faces_locations[i].width;
+               _data->face_rect[i].h = faces_locations[i].height;
+               _data->face_rect[i].orientation = 0;  /* set to default orientation */
+       }
+
+       _data->count = number_of_faces;
+       _data->error = FACE_ERROR_NONE;
+
+       return;
+}
+
+int _face_handle_create(__inout void **handle)
+{
+       int err = 0;
+       mv_handle* _handle = (mv_handle*)calloc(1, sizeof(mv_handle));
+
+       dcm_debug_fenter();
+
+       dcm_retvm_if(handle == NULL, FACE_ERROR_OUT_OF_MEMORY, "handle create fail");
+
+       err = mv_create_engine_config(&(_handle->cfg));
+       if (err != MEDIA_VISION_ERROR_NONE) {
+               dcm_error("fail to mv_create_engine_config");
+               DCM_SAFE_FREE(_handle);
+               return __convert_to_mv_error_e(err);
+       }
+
+       err = mv_create_source(&(_handle->source));
+       if (err != MEDIA_VISION_ERROR_NONE) {
+               dcm_error("fail to mv_create_source");
+               mv_destroy_engine_config(_handle->cfg);
+               DCM_SAFE_FREE(_handle);
+               return __convert_to_mv_error_e(err);
+       }
+
+       *handle = _handle;
+
+       dcm_info("dcm_face_engine was created. handle=0x%08x", *handle);
+
+       return FACE_ERROR_NONE;
+}
+
+int _face_handle_destroy(__in void *handle)
+{
+       int err = 0;
+
+       mv_handle* _handle = (mv_handle*)handle;
+
+       dcm_info("dcm_face_engine destroy. handle=0x%08x", handle);
+
+       err = mv_destroy_engine_config(_handle->cfg);
+       if (err != MEDIA_VISION_ERROR_NONE) {
+               dcm_error("Fail to mv_destroy_engine_config");
+               return __convert_to_mv_error_e(err);
+       }
+
+       err = mv_destroy_source(_handle->source);
+       if (err != MEDIA_VISION_ERROR_NONE) {
+               dcm_error("Fail to mv_destroy_source");
+               return __convert_to_mv_error_e(err);
+       }
+
+       return FACE_ERROR_NONE;
+}
+
+int _face_detect_faces(__in dcm_face_h handle, __out face_rect_s *face_rect[], __out int *count)
+{
+       int err = FACE_ERROR_NONE;
+       mv_colorspace_e colorspace = MEDIA_VISION_COLORSPACE_INVALID;
+       mv_faceInfo result;
+
+       dcm_retvm_if(handle == NULL, FACE_ERROR_OUT_OF_MEMORY, "invalid handle");
+       dcm_retvm_if(face_rect == NULL, FACE_ERROR_OUT_OF_MEMORY, "invalid face_rect");
+       dcm_retvm_if(count == NULL, FACE_ERROR_OUT_OF_MEMORY, "invalid count");
+
+       mv_handle *_fengine = (mv_handle *)handle->fengine;
+
+       __convert_to_mv_colorspace_e(handle->image_info->colorspace, &colorspace);
+
+       dcm_debug("face_detect image: %p, size: %d, width: %d, height: %d, color: %d", handle->image_info->data, handle->image_info->size, handle->image_info->width, handle->image_info->height, colorspace);
+
+       err = mv_source_fill_by_buffer(_fengine->source, handle->image_info->data, handle->image_info->size, handle->image_info->width, handle->image_info->height, colorspace);
+       if (err != MEDIA_VISION_ERROR_NONE) {
+               dcm_error("Fail to mv_source_fill_by_buffer");
+               return __convert_to_mv_error_e(err);
+       }
+
+       err = mv_face_detect(_fengine->source, _fengine->cfg, (mv_face_detected_cb)__face_detected_cb, &result);
+
+/*     wait_for_async(); */
+
+       if (result.error == FACE_ERROR_NONE) {
+               *face_rect = result.face_rect;
+               *count = result.count;
+       } else {
+               *face_rect = result.face_rect;
+               *count = result.count;
+               return result.error;
+       }
+
+       return FACE_ERROR_NONE;
+}
diff --git a/libdcm-face/dcm-face_priv.h b/libdcm-face/dcm-face_priv.h
new file mode 100755 (executable)
index 0000000..a1abf71
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __TIZEN_UIX_FACE_PRIV_H__
+#define __TIZEN_UIX_FACE_PRIV_H__
+
+#include <stdlib.h>
+#include <glib.h>
+#include "dcm-face-debug.h"
+
+#undef __in
+#define __in
+
+#undef __out
+#define __out
+
+#undef __inout
+#define __inout
+
+#define FACE_IMAGE_MAGIC               (0x1a2b3c4d)
+#define FACE_INVALID_MAGIC             (0xDEADBEAF)
+
+#define DCM_SAFE_FREE(src)      { if(src) {free(src); src = NULL;}}
+
+typedef struct face_image_s {
+       unsigned char *data;
+       unsigned int width;
+       unsigned int height;
+       unsigned int size;
+       face_image_colorspace_e colorspace;
+       unsigned int magic;
+} FaceImage;
+
+typedef struct face_handle_s {
+       void *fengine;
+       unsigned int magic;
+       FaceImage *image_info;
+} FaceHandleT;
+
+int _face_handle_create(void **handle);
+
+/**
+ * @brief Destroys the handle to the face engine and releases all its resources.
+ * @param[in] face The face engine handle
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #FACE_ERROR_NONE Successful
+ * @retval #FACE_ERROR_INVALID_PARAMTER Invalid parameter
+ * @retval #FACE_ERROR_ENGINE_NOT_FOUND face engine not found
+ * @see _face_handle_create()
+ */
+int _face_handle_destroy(void *handle);
+
+/**
+ * @brief Detects faces from the image data.
+ * @param[in] face The facial engine handle
+ * @param[in] image_type The type of the image
+ * @param[in] image The image handle to detect faces
+ * @param[out] face_rect The array of the detected face positions
+ * @param[out] count The number of the detected face positions
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #FACE_ERROR_NONE Successful
+ * @retval #FACE_ERROR_INVALID_PARAMTER Invalid parameter
+ * @retval #FACE_ERROR_OUT_OF_MEMORY   Out of memory
+ * @retval #FACE_ERROR_ENGINE_NOT_FOUND Facial engine not found
+ */
+int _face_detect_faces(dcm_face_h handle, face_rect_s *face_rect[], int *count);
+
+
+#endif /* __TIZEN_UIX_FACE_PRIV_H__ */
+
diff --git a/libdcm-face/include/dcm-face.h b/libdcm-face/include/dcm-face.h
new file mode 100755 (executable)
index 0000000..1637a72
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __TIZEN_DCM_FACE_H__
+#define __TIZEN_DCM_FACE_H__
+
+#include <tizen.h>
+#include "dcm-face_type.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup DCM_FACE_MODULE
+ * @{
+ */
+
+/**
+ * @brief Creates a handle to the facial engine.
+ * @remarks The @a face must be released with face_destroy() by you.
+ * @param[out] handle A face engine handle to be newly created on success
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #FACE_ERROR_NONE    Successful
+ * @retval #FACE_ERROR_INVALID_PARAMTER Invalid parameter
+ * @retval #FACE_ERROR_OUT_OF_MEMORY   Out of memory
+ * @retval #FACE_ERROR_ENGINE_NOT_FOUND Facial engine not found
+ * @see dcm_face_destroy()
+ */
+int dcm_face_create(dcm_face_h *handle);
+
+/**
+ * @brief Destroys the handle to the facial engine and releases all its resources.
+ * @param[in] handle The face engine handle
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #FACE_ERROR_NONE Successful
+ * @retval #FACE_ERROR_INVALID_PARAMTER Invalid parameter
+ * @retval #FACE_ERROR_ENGINE_NOT_FOUND Facial engine not found
+ * @see dcm_face_create()
+ */
+int dcm_face_destroy(dcm_face_h handle);
+
+/**
+ * @brief Gets the preferred color space of the facial engine.
+ * @remarks The preferred color space depends on the facial engine.
+ * @param[in] handle The facial engine handle
+ * @param[out] colorspace The preferred color space
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #FACE_ERROR_NONE Successful
+ * @retval #FACE_ERROR_INVALID_PARAMTER Invalid parameter
+ * @see dcm_face_create()
+ */
+int dcm_face_get_prefered_colorspace(dcm_face_h handle, face_image_colorspace_e *colorspace);
+
+/**
+ * @brief Creates a face image handle containing the input image data
+ * @remarks The @a face_image must be released with face_image_destroy() by you.
+ * @remarks The @a buffer must not be released until @a face_image is released with face_image_destroy()
+ * @param[in] handle The facial engine handle
+ * @param[in] colorspace The colorspace of the image
+ * @param[in] buffer The buffer containing the image
+ * @param[in] width The width of the image
+ * @param[in] height The height of the image
+ * @param[in] size The size of the buffer
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #FACE_ERROR_NONE    Successful
+ * @retval #FACE_ERROR_INVALID_PARAMTER Invalid parameter
+ * @retval #FACE_ERROR_OUT_OF_MEMORY   Out of memory
+ * @see dcm_face_create()
+  */
+int dcm_face_set_image_info(dcm_face_h handle, face_image_colorspace_e colorspace, unsigned char *buffer, unsigned int width, unsigned int height, unsigned int size);
+
+/**
+ * @brief Gets the face information of detected faces.
+ * @remarks The detected faces depends on the facial engine.
+ * @param[in] handle The facial engine handle
+ * @param[out] face info The face information with rect, count and so on
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #FACE_ERROR_NONE Successful
+ * @retval #FACE_ERROR_INVALID_PARAMTER Invalid parameter
+ * @see dcm_face_destroy_face_info()
+ */
+int dcm_face_get_face_info(dcm_face_h handle, face_info_s *face_info);
+
+/**
+ * @brief Release the face information memory.
+ * @param[in] face_info The face information memory
+ * @return 0 on success, otherwise a negative error value.
+ * @retval #FACE_ERROR_NONE Successful
+ * @retval #FACE_ERROR_INVALID_PARAMTER Invalid parameter
+ * @see dcm_face_get_face_info()
+ */
+int dcm_face_destroy_face_info(face_info_s *face_info);
+
+/**
+ * @}
+ */
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif         /* __TIZEN_DCM_FACE_H__ */
+
diff --git a/libdcm-face/include/dcm-face_type.h b/libdcm-face/include/dcm-face_type.h
new file mode 100755 (executable)
index 0000000..4884cd4
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __TIZEN_DCM_FACE_TYPE_H__
+#define __TIZEN_DCM_FACE_TYPE_H__
+
+#include <tizen.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup
+ * @{
+ */
+
+/**
+ * @brief Facel engine handle.
+ */
+typedef struct face_handle_s *dcm_face_h;
+
+/**
+ * @brief Enumerations of error codes for the Facial Engine API.
+ */
+typedef enum {
+       FACE_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */
+       FACE_ERROR_INVALID_PARAMTER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+       FACE_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */
+       FACE_ERROR_ENGINE_NOT_FOUND = TIZEN_ERROR_UIX_CLASS | 0x41, /**< Facial engine not found */
+       FACE_ERROR_OPERATION_FAILED = TIZEN_ERROR_UIX_CLASS | 0x42, /**< Operation failed */
+} face_error_e;
+
+/**
+ * @brief Enumerations of color spaces
+ * @see face_image_create()
+ * @see face_attr_get_prefered_colorspace()
+ *
+ */
+typedef enum {
+       FACE_IMAGE_COLORSPACE_YUV420,                   /**< Y:U:V = 4:2:0 */
+       FACE_IMAGE_COLORSPACE_RGB888,                   /**< RGB565, high-byte is Blue  */
+} face_image_colorspace_e;
+
+/**
+ * @brief Represents a rectangular region in a coordinate space
+ */
+typedef struct {
+       int x;          /**< The x coordinate of the top-left corner of the rectangle */
+       int y;          /**< The y coordinate of the top-left corner of the rectangle */
+       int w;          /**< The width of the rectangle */
+       int h;          /**< The height of the rectangle */
+       int orientation;        /** face orientation */
+} face_rect_s;
+
+
+typedef struct {
+       face_rect_s *rects;
+       int count;
+} face_info_s;
+
+
+
+/**
+ * @}
+ */
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif         /* __TIZEN_DCM_FACE_TYPE_H__ */
+
diff --git a/libdcm-util/dcm_image_codec.cpp b/libdcm-util/dcm_image_codec.cpp
new file mode 100755 (executable)
index 0000000..8309dd6
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <Evas.h>
+#include <Ecore_Evas.h>
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <image_util.h>
+#include <libexif/exif-data.h>
+#include <mm_util_imgp.h>
+#include <dcm_image_debug_utils.h>
+#include <dcm_image_codec.h>
+
+#if 0
+static void _dcm_codec_calc_image_size(int ori_width, int ori_height, int tar_width, int tar_height, int *buf_width, int *buf_height)
+{
+
+    *buf_width = 0;
+    *buf_height = 0;
+
+    if (tar_width <= 0 && tar_height <= 0) {
+        dcm_warn("Invalid input decode size! Set decode size to original size");
+        *buf_width = 0;
+        *buf_height = 0;
+        return;
+    }
+
+    if (ori_width <= tar_width && ori_height <= tar_height) {
+        dcm_debug("Original image size is already smaller. Set docode size to original size");
+        /* Make sure that decode buffer size can be divided by 8 (required by YUV420 decoding) */
+        *buf_width = ori_width - (ori_width) % 8;
+        *buf_height = ori_height - (ori_height) % 8;
+        return;
+    }
+
+    if (ori_width > ori_height) {
+        /* Scale image size based on input width */
+        *buf_width = tar_width;
+        *buf_height = (int) (ori_height * (((double) tar_width) / ((double) ori_width)));
+    } else {
+        /* Scale image size based on input height */
+        *buf_height = tar_height;
+        *buf_width = (int) (ori_width * (((double) tar_height) / ((double) ori_height)));
+    }
+
+    /* Make sure that decode buffer size can be divided by 8 (required by YUV420 decoding) */
+    *buf_width = *buf_width - (*buf_width) % 8;
+    *buf_height = *buf_height - (*buf_height) % 8;
+
+       return;
+}
+#endif
+
+int __dcm_decode_image_with_evas(const char *origin_path,
+                                       int dest_width, int dest_height,
+                                       dcm_image_info *image_info)
+{
+       dcm_debug_fenter();
+
+       Ecore_Evas *resize_img_ee;
+
+       resize_img_ee = ecore_evas_buffer_new(dest_width, dest_height);
+       if (!resize_img_ee) {
+               dcm_error("ecore_evas_buffer_new failed");
+               return DCM_ERROR_CODEC_DECODE_FAILED;
+       }
+
+       Evas *resize_img_e = ecore_evas_get(resize_img_ee);
+       if (!resize_img_e) {
+               dcm_error("ecore_evas_get failed");
+               ecore_evas_free(resize_img_ee);
+               return DCM_ERROR_CODEC_DECODE_FAILED;
+       }
+
+       Evas_Object *source_img = evas_object_image_add(resize_img_e);
+       if (!source_img) {
+               dcm_error("evas_object_image_add failed");
+               ecore_evas_free(resize_img_ee);
+               return DCM_ERROR_CODEC_DECODE_FAILED;
+       }
+
+       evas_object_image_file_set(source_img, origin_path, NULL);
+
+       /* Get w/h of original image */
+       int width = 0;
+       int height = 0;
+
+       evas_object_image_size_get(source_img, &width, &height);
+       image_info->origin_width = width;
+       image_info->origin_height = height;
+
+       evas_object_image_load_orientation_set(source_img, 1);
+
+       ecore_evas_resize(resize_img_ee, dest_width, dest_height);
+
+       evas_object_image_load_size_set(source_img, dest_width, dest_height);
+       evas_object_image_fill_set(source_img, 0, 0, dest_width, dest_height);
+       evas_object_image_filled_set(source_img, 1);
+
+       evas_object_resize(source_img, dest_width, dest_height);
+       evas_object_show(source_img);
+
+       /* Set alpha from original */
+       image_info->alpha = evas_object_image_alpha_get(source_img);
+       if (image_info->alpha) ecore_evas_alpha_set(resize_img_ee, EINA_TRUE);
+
+       /* Create target buffer and copy origin resized img to it */
+       Ecore_Evas *target_ee = ecore_evas_buffer_new(dest_width, dest_height);
+       if (!target_ee) {
+               dcm_error("ecore_evas_buffer_new failed");
+               ecore_evas_free(resize_img_ee);
+               return DCM_ERROR_CODEC_DECODE_FAILED;
+       }
+
+       Evas *target_evas = ecore_evas_get(target_ee);
+       if (!target_evas) {
+               dcm_error("ecore_evas_get failed");
+               ecore_evas_free(resize_img_ee);
+               ecore_evas_free(target_ee);
+               return DCM_ERROR_CODEC_DECODE_FAILED;
+       }
+
+       Evas_Object *ret_image = evas_object_image_add(target_evas);
+       evas_object_image_size_set(ret_image, dest_width, dest_height);
+       evas_object_image_fill_set(ret_image, 0, 0, dest_width, dest_height);
+       evas_object_image_filled_set(ret_image, EINA_TRUE);
+
+       evas_object_image_data_set(ret_image, (int *)ecore_evas_buffer_pixels_get(resize_img_ee));
+       evas_object_image_data_update_add(ret_image, 0, 0, dest_width, dest_height);
+
+       unsigned int buf_size = 0;
+       int stride = evas_object_image_stride_get(ret_image);
+       buf_size = (sizeof(unsigned char) * stride * dest_height);
+       dcm_debug("buf_size: %d", buf_size);
+
+       image_info->size = buf_size;
+       image_info->width = dest_width;
+       image_info->height = dest_height;
+       image_info->data = (unsigned char *)malloc(buf_size);
+       if (image_info->data == NULL) {
+               dcm_error("Failed to allocate memory" );
+               ecore_evas_free(resize_img_ee);
+               ecore_evas_free(target_ee);
+
+               return DCM_ERROR_OUT_OF_MEMORY;
+       }
+
+       void *image_data = evas_object_image_data_get(ret_image, 1);
+       if (image_data != NULL) {
+               memcpy(image_info->data, image_data, buf_size);
+       } else {
+               dcm_error("image_data is NULL. evas_object_image_data_get failed");
+       }
+
+       ecore_evas_free(target_ee);
+       ecore_evas_free(resize_img_ee);
+
+       dcm_debug_fleave();
+
+       return DCM_SUCCESS;
+}
+
+static int __dcm_codec_get_image_orientation(const char *path, int *orientation)
+{
+       int ret = DCM_SUCCESS;
+       ExifData *ed = NULL;
+       ExifEntry *entry = NULL;
+       int status = 0;
+       ExifByteOrder byte_order;
+
+       DCM_CHECK_VAL(path, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(orientation, DCM_ERROR_INVALID_PARAMETER);
+
+       ed = exif_data_new_from_file(path);
+       if (ed == NULL) {
+               dcm_error("Failed to create new exif data!");
+               ret = DCM_ERROR_EXIF_FAILED;
+               goto DCM_SVC_DB_GET_FACE_ORIENTATION_FAILED;
+       }
+
+       entry = exif_data_get_entry(ed, EXIF_TAG_ORIENTATION);
+       if (entry == NULL) {
+               dcm_warn("Exif entry not exist!");
+               *orientation = 0;
+               ret = DCM_SUCCESS;
+               goto DCM_SVC_DB_GET_FACE_ORIENTATION_FAILED;
+       }
+
+       byte_order = exif_data_get_byte_order(ed);
+       status = exif_get_short(entry->data, byte_order);
+       switch (status) {
+               case 1:
+               case 2:
+                       *orientation = 0;
+                       break;
+               case 3:
+               case 4:
+                       *orientation = 180;
+                       break;
+               case 5:
+               case 8:
+                       *orientation = 270;
+                       break;
+               case 6:
+               case 7:
+                       *orientation = 90;
+                       break;
+               default:
+                       *orientation = 0;
+                       break;
+       }
+
+       dcm_debug("orientation: %d", *orientation);
+
+DCM_SVC_DB_GET_FACE_ORIENTATION_FAILED:
+
+       if (ed != NULL) {
+               exif_data_unref(ed);
+               ed = NULL;
+       }
+
+       return ret;
+}
+
+static int __dcm_codec_rotate_by_orientation(const unsigned char *source, unsigned char **image_buffer, unsigned int *buff_width, unsigned int *buff_height, dcm_image_codec_type_e decode_type, int *orientation)
+{
+       int ret = IMAGE_UTIL_ERROR_NONE;
+       image_util_colorspace_e colorspace = IMAGE_UTIL_COLORSPACE_I420;
+       image_util_rotation_e rotate = IMAGE_UTIL_ROTATION_NONE;
+       unsigned char *rotated_buffer = NULL;
+       unsigned int rotated_buffer_size = 0;
+       int rotated_width = 0, rotated_height = 0;
+
+       DCM_CHECK_VAL(source, DCM_ERROR_INVALID_PARAMETER);
+
+       if (decode_type == DCM_IMAGE_CODEC_I420) {
+               colorspace = IMAGE_UTIL_COLORSPACE_I420;
+       } else if (decode_type == DCM_IMAGE_CODEC_RGB888) {
+               colorspace = IMAGE_UTIL_COLORSPACE_RGB888;
+       }
+
+       /* Get rotate angle enum */
+       if (*orientation == 180) { // 3-180
+               rotate = IMAGE_UTIL_ROTATION_180;
+       } else if (*orientation == 90) { // 6-90
+               rotate = IMAGE_UTIL_ROTATION_90;
+       } else if (*orientation == 270) { // 8-270
+               rotate = IMAGE_UTIL_ROTATION_270;
+       } else {
+               rotate = IMAGE_UTIL_ROTATION_NONE;
+       }
+
+       if (rotate == IMAGE_UTIL_ROTATION_90 || rotate == IMAGE_UTIL_ROTATION_270) {
+               rotated_width = *buff_height;
+               rotated_height = *buff_width;
+       } else {
+               rotated_width = *buff_width;
+               rotated_height = *buff_height;
+       }
+
+       /* Calculate the rotated buffer size */
+       ret = image_util_calculate_buffer_size(rotated_width, rotated_height, colorspace, &rotated_buffer_size);
+       if (ret != IMAGE_UTIL_ERROR_NONE) {
+               dcm_error("Failed to calculate buffer size! err: %d", ret);
+               return DCM_ERROR_IMAGE_UTIL_FAILED;
+       }
+
+       /* Allocate rotated buffer */
+       if (rotated_buffer_size <= 0) {
+               dcm_error("Invalid rotated buffer size!");
+               return DCM_ERROR_IMAGE_UTIL_FAILED;
+       }
+
+       dcm_debug("rotate buffer size: %u", rotated_buffer_size);
+       rotated_buffer = (unsigned char *) g_malloc0(rotated_buffer_size);
+       if (rotated_buffer == NULL) {
+               dcm_error("rotated_buffer is NULL!");
+               return DCM_ERROR_IMAGE_UTIL_FAILED;
+       }
+
+       try {
+               /* Rotate input bitmap */
+               ret = image_util_rotate(rotated_buffer, &rotated_width, &rotated_height, rotate, source,
+               *buff_width, *buff_height, colorspace);
+
+               if (ret != IMAGE_UTIL_ERROR_NONE || rotated_buffer == NULL) {
+                       dcm_error("Failed to rotate image buffer! err: %d", ret);
+                       throw DCM_ERROR_IMAGE_UTIL_FAILED;
+               }
+
+               /* Decoded buffer size is set to rotated buffer size to match buffer */
+               dcm_debug("After rotation: [width: %d] [height: %d]", rotated_width, rotated_height);
+               *buff_width = rotated_width;
+               *buff_height = rotated_height;
+
+               /* Allocated pixel should be freed when scanning is finished for this rotated bitmap */
+               *image_buffer = rotated_buffer;
+               dcm_warn("rotated decode buffer: %p", *image_buffer);
+
+       } catch (DcmErrorType &e) {
+               DCM_SAFE_FREE(rotated_buffer);
+               dcm_error("image util rotate error!");
+               return e;
+       }
+
+       return DCM_SUCCESS;
+}
+
+static int __dcm_decode_image_with_size_orient(const char *file_path, unsigned int target_width, unsigned int target_height,
+       dcm_image_codec_type_e decode_type, unsigned char **image_buffer, unsigned int *buff_width, unsigned int *buff_height, int *orientation, unsigned int *size)
+{
+       int ret = IMAGE_UTIL_ERROR_NONE;
+       image_util_colorspace_e colorspace = IMAGE_UTIL_COLORSPACE_I420;
+       unsigned char *decode_buffer = NULL;
+
+       dcm_debug_fenter();
+
+       DCM_CHECK_VAL(file_path, DCM_ERROR_INVALID_PARAMETER);
+
+       if (decode_type == DCM_IMAGE_CODEC_I420) {
+               colorspace = IMAGE_UTIL_COLORSPACE_I420;
+       } else if (decode_type == DCM_IMAGE_CODEC_RGB888) {
+               colorspace = IMAGE_UTIL_COLORSPACE_RGB888;
+       }
+
+       /* Extract orientation from exif */
+       ret = __dcm_codec_get_image_orientation(file_path, orientation);
+       if (ret != DCM_SUCCESS) {
+               dcm_error("Failed to extract orientation! err: %d", ret);
+               dcm_warn("Set orientation to default!");
+               *orientation = 0;
+       }
+
+       ret = image_util_decode_jpeg(file_path, colorspace, &decode_buffer, (int *)buff_width, (int *)buff_height, size);
+       dcm_debug("file:%s buffer:%p, size:%u, buff_width:%d, buff_height:%d", file_path, image_buffer, *size, *buff_width, *buff_height);
+       if (ret != IMAGE_UTIL_ERROR_NONE) {
+               dcm_error("Error image_util_decode_jpeg ret : %d", ret);
+               return DCM_ERROR_IMAGE_UTIL_FAILED;
+       }
+
+       /* Rotate the decoded buffer according to orientation */
+       if (*orientation == 0) {
+               *image_buffer = decode_buffer;
+       } else {
+               ret = __dcm_codec_rotate_by_orientation(decode_buffer, image_buffer, buff_width, buff_height, decode_type, orientation);
+               if (ret != DCM_SUCCESS) {
+                       dcm_error("Failed to rotate image buffer! err: %d", ret);
+                       return DCM_ERROR_CODEC_DECODE_FAILED;
+               }
+       }
+
+       dcm_debug_fleave();
+
+       return DCM_SUCCESS;
+}
+
+EXPORT_API
+int dcm_decode_image_with_size_orient(const char *file_path, unsigned int target_width, unsigned int target_height, 
+       dcm_image_codec_type_e decode_type, unsigned char **image_buffer, unsigned int *buff_width, unsigned int *buff_height, int *orientation, unsigned int *size)
+{
+       int ret = DCM_SUCCESS;
+
+       ret = __dcm_decode_image_with_size_orient(file_path, target_width, target_height, decode_type, image_buffer, buff_width, buff_height, orientation, size);
+       if (ret != DCM_SUCCESS) {
+               dcm_error("Error _dcm_decode_image_with_size ret : %d", ret);
+       }
+
+       return ret;
+}
+
+EXPORT_API
+int dcm_decode_image_with_evas(const char *file_path, unsigned int target_width, unsigned int target_height,
+        dcm_image_codec_type_e decode_type, unsigned char **image_buffer, unsigned int *buff_width, unsigned int *buff_height, int *orientation, unsigned int *size)
+{
+       int ret = DCM_SUCCESS;
+       dcm_image_info image_info = {0, };
+       image_util_colorspace_e colorspace = IMAGE_UTIL_COLORSPACE_I420;
+       mm_util_img_format mm_colorspace = MM_UTIL_IMG_FMT_I420;
+
+       DCM_CHECK_VAL(file_path, DCM_ERROR_INVALID_PARAMETER);
+
+       memset(&image_info, 0, sizeof(image_info));
+
+       if (decode_type == DCM_IMAGE_CODEC_I420) {
+               colorspace = IMAGE_UTIL_COLORSPACE_I420;
+               mm_colorspace = MM_UTIL_IMG_FMT_I420;
+       } else if (decode_type == DCM_IMAGE_CODEC_RGB888) {
+               colorspace = IMAGE_UTIL_COLORSPACE_RGB888;
+               mm_colorspace = MM_UTIL_IMG_FMT_RGB888;
+       }
+       ret = __dcm_decode_image_with_evas(file_path, target_width, target_height, &image_info);
+       if (ret != DCM_SUCCESS) {
+               dcm_error("Error __dcm_decode_image_with_evas ret : %d", ret);
+               *buff_width = 0;
+               *buff_height = 0;
+               *orientation = 0;
+               *size = 0;
+               *image_buffer = NULL;
+               return DCM_ERROR_CODEC_DECODE_FAILED;
+       }
+
+       *buff_width = image_info.width;
+       *buff_height = image_info.height;
+       *orientation = 0;
+       image_util_calculate_buffer_size(*buff_width, *buff_height, colorspace, size);
+       *image_buffer = (unsigned char *)malloc(sizeof(unsigned char) * (*size));
+       if (*image_buffer == NULL) {
+               dcm_error("Error buffer allocation");
+               DCM_SAFE_FREE(image_info.data);
+               return DCM_ERROR_CODEC_DECODE_FAILED;
+       }
+       int err = 0;
+       err = mm_util_convert_colorspace(image_info.data,
+                                       image_info.width,
+                                       image_info.height,
+                                       MM_UTIL_IMG_FMT_BGRA8888,
+                                       *image_buffer,
+                                       mm_colorspace);
+
+       if (err < 0) {
+               dcm_error("Failed to change from argb888 to %d. (%d)", mm_colorspace, err);
+               DCM_SAFE_FREE(*image_buffer);
+               *image_buffer = NULL;
+               ret = DCM_ERROR_CODEC_DECODE_FAILED;
+       }
+       DCM_SAFE_FREE(image_info.data);
+
+       return ret;
+}
diff --git a/libdcm-util/include/dcm_image_codec.h b/libdcm-util/include/dcm_image_codec.h
new file mode 100755 (executable)
index 0000000..37a80c3
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _DCM_IMAGE_CODEC_H_
+#define _DCM_IMAGE_CODEC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+       DCM_IMAGE_CODEC_I420,
+       DCM_IMAGE_CODEC_RGB888,
+} dcm_image_codec_type_e;
+
+typedef struct {
+       int size;
+       int width;
+       int height;
+       int origin_width;
+       int origin_height;
+       int alpha;
+       unsigned char *data;
+} dcm_image_info;
+
+
+/* Decoding image with input width and height, if possible (width/height ratio is kept the same as original), and rotate the buffer according to orientation */
+int dcm_decode_image_with_size_orient(const char *file_path, unsigned int target_width, unsigned int target_height, 
+               dcm_image_codec_type_e decode_type, unsigned char **image_buffer, unsigned int *buff_width, unsigned int *buff_height, int *orientation, unsigned int *size);
+
+int dcm_decode_image_with_evas(const char *file_path, unsigned int target_width, unsigned int target_height,
+        dcm_image_codec_type_e decode_type, unsigned char **image_buffer, unsigned int *buff_width, unsigned int *buff_height, int *orientation, unsigned int *size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_DCM_IMAGE_CODEC_H_*/
diff --git a/libdcm-util/include/dcm_image_debug_utils.h b/libdcm-util/include/dcm_image_debug_utils.h
new file mode 100755 (executable)
index 0000000..f833d7a
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _DCM_DEBUG_UTILS_H_
+#define _DCM_DEBUG_UTILS_H_
+
+#include <string.h>
+#include <dlog.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define _USE_DLOG_
+#define LOG_TAG "DCM_IMAGE_CODEC"
+
+typedef enum {
+       DCM_SUCCESS,
+       DCM_ERROR_EXIF_FAILED,
+       DCM_ERROR_INVALID_PARAMETER,
+       DCM_ERROR_OUT_OF_MEMORY,
+       DCM_ERROR_IMAGE_UTIL_FAILED,
+       DCM_ERROR_CODEC_DECODE_FAILED,
+       DCM_ERROR_INVALID_IMAGE_SIZE,
+       DCM_ERROR_UNSUPPORTED_IMAGE_TYPE,
+} DcmErrorType;
+
+/* anci c color type */
+#define FONT_COLOR_RESET    "\033[0m"
+#define FONT_COLOR_RED      "\033[31m"
+#define FONT_COLOR_GREEN    "\033[32m"
+#define FONT_COLOR_YELLOW   "\033[33m"
+#define FONT_COLOR_BLUE     "\033[34m"
+#define FONT_COLOR_PURPLE   "\033[35m"
+#define FONT_COLOR_CYAN     "\033[36m"
+#define FONT_COLOR_GRAY     "\033[37m"
+
+/*#undef _USE_DLOG_ */
+#ifdef _USE_DLOG_
+#define dcm_debug(fmt, arg...) do { \
+               LOGD(FONT_COLOR_CYAN""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_info(fmt, arg...) do { \
+               LOGI(FONT_COLOR_YELLOW""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_warn(fmt, arg...) do { \
+               LOGW(FONT_COLOR_GREEN""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_error(fmt, arg...) do { \
+               LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET  , ##arg); \
+       } while (0)
+
+#define dcm_sec_debug(fmt, arg...) do { \
+               SECURE_LOGD(FONT_COLOR_CYAN""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_sec_info(fmt, arg...) do { \
+               SECURE_LOGI(FONT_COLOR_YELLOW""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_sec_warn(fmt, arg...) do { \
+               SECURE_LOGW(FONT_COLOR_GREEN""fmt""FONT_COLOR_RESET, ##arg); \
+       } while (0)
+
+#define dcm_sec_error(fmt, arg...) do { \
+               SECURE_LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET , ##arg); \
+       } while (0)
+
+#define dcm_debug_fenter() do { \
+               LOGD(FONT_COLOR_RESET"<Enter>"); \
+       } while (0)
+
+#define dcm_debug_fleave() do { \
+               LOGD(FONT_COLOR_RESET"<Leave>"); \
+       } while (0)
+#else
+#define dcm_debug(fmt, arg...)
+#define dcm_info(fmt, arg...)
+#define dcm_warn(fmt, arg...)
+#define dcm_error(fmt, arg...)
+
+#define dcm_sec_debug(fmt, arg...)
+#define dcm_sec_info(fmt, arg...)
+#define dcm_sec_warn(fmt, arg...)
+#define dcm_sec_error(fmt, arg...)
+
+#endif
+#define dcm_retm_if(expr, fmt, arg...) do { \
+               if(expr) { \
+                       dcm_error(fmt, ##arg); \
+               dcm_error("(%s) -> %s() return", #expr, __FUNCTION__); \
+                       return; \
+               } \
+       } while (0)
+
+#define dcm_retvm_if(expr, val, fmt, arg...) do { \
+               if(expr) { \
+                       dcm_error(fmt, ##arg); \
+               dcm_error("(%s) -> %s() return", #expr, __FUNCTION__); \
+                       return (val); \
+               } \
+       } while (0)
+
+#define ERR_BUF_LENGHT 256
+#define dcm_stderror(fmt) do { \
+               char dcm_stderror_buf[ERR_BUF_LENGHT] = {0, }; \
+               strerror_r(errno, dcm_stderror_buf, ERR_BUF_LENGHT); \
+               dcm_error(fmt" : standard error= [%s]", dcm_stderror_buf); \
+       } while (0)
+
+#define DCM_CHECK_VAL(expr, val)               dcm_retvm_if(!(expr), val , "Invalid parameter, return ERROR code!")
+#define DCM_CHECK_NULL(expr)                   dcm_retvm_if(!(expr), NULL, "Invalid parameter, return NULL!")
+#define DCM_CHECK_FALSE(expr)                  dcm_retvm_if(!(expr), FALSE, "Invalid parameter, return FALSE!")
+#define DCM_CHECK(expr)                                dcm_retm_if (!(expr),        "Invalid parameter, return!")
+
+#define DCM_SAFE_FREE(ptr) { if(ptr) {free(ptr); ptr = NULL;} }
+
+#endif /* _DCM_DEBUG_UTILS_H_ */
+
diff --git a/packaging/dcm-service.manifest b/packaging/dcm-service.manifest
new file mode 100755 (executable)
index 0000000..97e8c31
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_"/>
+       </request>
+</manifest>
diff --git a/packaging/dcm-service.spec b/packaging/dcm-service.spec
new file mode 100755 (executable)
index 0000000..c413547
--- /dev/null
@@ -0,0 +1,75 @@
+Name:       dcm-service
+Summary:    Multimedia DCM(Digital Contents Management) Service 
+Version:    0.0.1
+Release:    0
+Group:      Multimedia/Service
+License:    Apache-2.0
+Source0:    %{name}-%{version}.tar.gz
+Source1001:     %{name}.manifest
+
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+BuildRequires:  cmake
+BuildRequires:  pkgconfig(glib-2.0)
+BuildRequires:  pkgconfig(gthread-2.0)
+BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(ecore-evas)
+BuildRequires:  pkgconfig(evas)
+BuildRequires:  pkgconfig(libexif)
+BuildRequires:  pkgconfig(sqlite3)
+BuildRequires:  pkgconfig(capi-media-image-util)
+BuildRequires:  pkgconfig(capi-media-vision)
+BuildRequires:  pkgconfig(media-thumbnail)
+BuildRequires:  pkgconfig(libmedia-utils)
+BuildRequires:  pkgconfig(libtzplatform-config)
+BuildRequires:  pkgconfig(mmutil-imgp)
+BuildRequires:  pkgconfig(vconf)
+BuildRequires:  pkgconfig(uuid)
+
+%description
+Description: Digital Contents Management(DCM) service process
+
+%package devel
+Summary:    Digital Contents Management service for multimedia applications. (development)
+Group:      Development/Libraries
+Requires:   %{name} = %{version}-%{release}
+
+%description devel
+DCM service for multimedia applications. (development files)
+
+%prep
+%setup -q
+cp %{SOURCE1001} .
+
+%build
+%cmake .
+make %{?jobs:-j%jobs}
+#export CFLAGS+=" -Wextra -Wno-array-bounds"
+#export CFLAGS+=" -Wno-ignored-qualifiers -Wno-unused-parameter -Wshadow"
+#export CFLAGS+=" -Wwrite-strings -Wswitch-default"
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+#License
+mkdir -p %{buildroot}/%{_datadir}/license
+cp LICENSE.APLv2.0 %{buildroot}/%{_datadir}/license/%{name}
+
+%post -p /sbin/ldconfig
+%postun -p /sbin/ldconfig
+
+%files
+%manifest %{name}.manifest
+%defattr(-,root,root,-)
+%{_libdir}/*.so*
+%{_bindir}/dcm-svc
+#License
+%{_datadir}/license/%{name}
+
+%files devel
+%manifest %{name}.manifest
+%{_libdir}/*.so
+%{_libdir}/pkgconfig/%{name}.pc
+#%{_includedir}/media/*.h
diff --git a/src/DcmColorUtils.cpp b/src/DcmColorUtils.cpp
new file mode 100755 (executable)
index 0000000..f0c9aec
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <glib.h>
+#include <image_util.h>
+#include <dcm_image_codec.h>
+#include <DcmDbUtils.h>
+#include <DcmTypes.h>
+#include <DcmDebugUtils.h>
+#include <DcmColorUtils.h>
+
+
+int DcmColorUtils::runColorExtractProcess(DcmScanItem *scan_item, DcmImageInfo *image_info)
+{
+       DCM_CHECK_VAL(scan_item, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(image_info, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(image_info->pixel, DCM_ERROR_INVALID_PARAMETER);
+
+       dcm_debug_fenter();
+#if 0
+       DcmDbUtils *dcmDbUtils = DcmDbUtils::getInstance();
+       int ret = IMAGE_UTIL_ERROR_NONE;
+       DcmColorItem colorItem = {0,};
+       memset(&colorItem, 0, sizeof(DcmColorItem));
+
+       // Extracting color supports only RGB888 format
+       ret = image_util_extract_color_from_memory(image_info->pixel, image_info->buffer_width, image_info->buffer_height, &(colorItem.rgb_r), &(colorItem.rgb_g), &(colorItem.rgb_b));
+       if (ret != IMAGE_UTIL_ERROR_NONE) {
+               dcm_error("image_util_extract_color_from_memory err= %d", ret);
+               return DCM_ERROR_IMAGE_UTIL_FAILED;
+       }
+
+       dcm_debug("image_util_extract_color_from_memory result r:%02x, g:%02x, b:%02x", colorItem.rgb_r, colorItem.rgb_g, colorItem.rgb_b);
+
+       colorItem.media_uuid = strdup(scan_item->media_uuid);
+       colorItem.storage_uuid = strdup(scan_item->storage_uuid);
+       ret = dcmDbUtils->_dcm_svc_db_update_color_to_db(colorItem);
+       if (ret != DCM_SUCCESS) {
+               dcm_error("Failed to update color item into db! err: %d", ret);
+               return DCM_ERROR_DB_OPERATION;
+       }
+#endif
+       dcm_debug_fleave();
+
+       return DCM_SUCCESS;
+}
+
diff --git a/src/DcmDbUtils.cpp b/src/DcmDbUtils.cpp
new file mode 100755 (executable)
index 0000000..4489fc5
--- /dev/null
@@ -0,0 +1,557 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <string.h>
+#include <unistd.h>
+#include <media-util.h>
+#include <tzplatform_config.h>
+#include <DcmDbUtils.h>
+#include <DcmTypes.h>
+#include <DcmDebugUtils.h>
+#include <uuid/uuid.h>
+
+#define DCM_STRING_VALID(str)          ((str != NULL && strlen(str) > 0) ? TRUE : FALSE)
+#define DCM_SQLITE3_FINALIZE(x)                {if (x != NULL) {sqlite3_finalize(x);x=NULL;}}
+#define DCM_SQLITE3_FREE(x)                    {if (x != NULL) {sqlite3_free(x);x=NULL;}}
+
+#define DB_TABLE_FACE "face"
+#define DB_TABLE_FACE_SCAN_LIST "face_scan_list"
+#define DB_TABLE_MEDIA "media"
+#define FACE_ITEM "face_uuid, media_uuid, face_rect_x , face_rect_y, face_rect_w , face_rect_h, orientation"
+
+#define SELECT_PATH_FROM_UNEXTRACTED_DCM_MEDIA "SELECT media_uuid, path, storage_uuid, width, height, orientation, mime_type FROM media WHERE media_uuid NOT IN (SELECT DISTINCT media_uuid FROM face_scan_list) AND validity=1 AND media_type=0 AND (storage_type = 0 OR storage_type = 1);"
+#define SELECT_PATH_FROM_UNEXTRACTED_DCM_INTERNAL_MEDIA "SELECT media_uuid, path, storage_uuid, width, height, orientation, mime_type FROM media WHERE media_uuid NOT IN (SELECT DISTINCT media_uuid FROM face_scan_list) AND validity=1 AND media_type=0 AND storage_type=0;"
+
+#define SELECT_MEDIA_INFO_BY_FILE_PATH_FROM_DB "SELECT media_uuid, storage_uuid, width, height, orientation, mime_type FROM media WHERE path = '%q';"
+#define INSERT_FACE_ITEM_TO_DB "INSERT INTO "DB_TABLE_FACE" ("FACE_ITEM") VALUES ('%q', '%q', %d, %d, %d, %d, %d);"
+#define UPDATE_COLOR_ITEM_TO_DB "UPDATE "DB_TABLE_MEDIA" SET color_r=%d, color_g=%d, color_b=%d WHERE media_uuid='%q' AND storage_uuid='%q';"
+
+static GMutex gMutexLock;
+
+namespace DcmDbUtilsInternal {
+bool __dcm_svc_db_check_duplicated(MediaDBHandle *db_handle, DcmFaceItem *data);
+bool __dcm_svc_db_check_duplicated_scan_list(MediaDBHandle *db_handle, const char *data);
+static int __dcm_svc_sql_prepare_to_step(sqlite3 *handle, const char *sql_str, sqlite3_stmt** stmt);
+static int __dcm_svc_sql_prepare_to_step_simple(sqlite3 *handle, const char *sql_str, sqlite3_stmt** stmt);
+}
+
+static DcmDbUtils* DcmDbUtils::getInstance(void)
+{
+       if (dcmDbUtils == NULL) {
+               g_mutex_trylock(&gMutexLock);
+
+               if (dcmDbUtils == NULL) {
+                       dcmDbUtils = new DcmDbUtils();
+               }
+
+               g_mutex_unlock(&gMutexLock);
+       }
+
+       return dcmDbUtils;
+}
+
+DcmDbUtils *DcmDbUtils::dcmDbUtils = NULL;
+MediaDBHandle *DcmDbUtils::db_handle = NULL;
+
+DcmDbUtils::DcmDbUtils(void)
+{
+
+}
+
+bool DcmDbUtilsInternal::__dcm_svc_db_check_duplicated(MediaDBHandle *db_handle, DcmFaceItem *data)
+{
+       int ret = MS_MEDIA_ERR_NONE;
+       sqlite3 * handle = (sqlite3 *)db_handle;
+       sqlite3_stmt *sql_stmt = NULL;
+       char *query_string = NULL;
+       int count = 0;
+
+       DCM_CHECK_FALSE((data != NULL));
+       DCM_CHECK_FALSE((data->media_uuid != NULL));
+
+       query_string = sqlite3_mprintf("SELECT count(*) FROM %s WHERE (media_uuid='%s' AND"
+               " face_rect_x='%d' AND face_rect_y='%d' AND face_rect_w='%d' AND face_rect_h='%d' AND orientation='%d')"
+               , DB_TABLE_FACE, data->media_uuid
+               , data->face_rect_x, data->face_rect_y, data->face_rect_w, data->face_rect_h, data->orientation);
+
+       ret = __dcm_svc_sql_prepare_to_step(handle, query_string, &sql_stmt);
+
+       if (ret != MS_MEDIA_ERR_NONE) {
+               dcm_error("error when __dcm_svc_sql_prepare_to_step. ret = [%d]", ret);
+               return TRUE;
+       }
+
+       count = sqlite3_column_int(sql_stmt, 0);
+
+       DCM_SQLITE3_FINALIZE(sql_stmt);
+
+       if (count > 0) {
+               dcm_warn("duplicated face data!");
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+bool DcmDbUtilsInternal::__dcm_svc_db_check_duplicated_scan_list(MediaDBHandle *db_handle, const char *data)
+{
+       int ret = MS_MEDIA_ERR_NONE;
+       sqlite3 * handle = (sqlite3 *)db_handle;
+       sqlite3_stmt *sql_stmt = NULL;
+       char *query_string = NULL;
+       int count = 0;
+
+       DCM_CHECK_FALSE((data != NULL));
+
+       query_string = sqlite3_mprintf("SELECT count(*) FROM %s WHERE media_uuid='%s'", DB_TABLE_FACE_SCAN_LIST, data);
+
+       ret = __dcm_svc_sql_prepare_to_step(handle, query_string, &sql_stmt);
+
+       if (ret != MS_MEDIA_ERR_NONE) {
+               dcm_error("error when __dcm_svc_sql_prepare_to_step. ret = [%d]", ret);
+               return TRUE;
+       }
+
+       count = sqlite3_column_int(sql_stmt, 0);
+
+       DCM_SQLITE3_FINALIZE(sql_stmt);
+
+       if (count > 0) {
+               dcm_warn("duplicated media data!");
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+
+static int DcmDbUtilsInternal::__dcm_svc_sql_prepare_to_step(sqlite3 *handle, const char *sql_str, sqlite3_stmt** stmt)
+{
+       int err = -1;
+
+       dcm_debug("[SQL query] : %s", sql_str);
+
+       if (!DCM_STRING_VALID(sql_str))
+       {
+               dcm_error("invalid query");
+               return MS_MEDIA_ERR_INVALID_PARAMETER;
+       }
+
+       err = sqlite3_prepare_v2(handle, sql_str, -1, stmt, NULL);
+       sqlite3_free((char *)sql_str);
+
+       if (err != SQLITE_OK) {
+               dcm_error ("prepare error %d[%s]", err, sqlite3_errmsg(handle));
+               if (err == SQLITE_CORRUPT) {
+                       return MS_MEDIA_ERR_DB_CORRUPT;
+               } else if (err == SQLITE_PERM) {
+                       return MS_MEDIA_ERR_DB_PERMISSION;
+               }
+
+               return MS_MEDIA_ERR_DB_INTERNAL;
+       }
+
+       err = sqlite3_step(*stmt);
+       if (err != SQLITE_ROW) {
+               dcm_error("[No-Error] Item not found. end of row [%s]", sqlite3_errmsg(handle));
+               DCM_SQLITE3_FINALIZE(*stmt);
+               return MS_MEDIA_ERR_DB_NO_RECORD;
+       }
+
+       return MS_MEDIA_ERR_NONE;
+}
+
+static int DcmDbUtilsInternal::__dcm_svc_sql_prepare_to_step_simple(sqlite3 *handle, const char *sql_str, sqlite3_stmt** stmt)
+{
+       int err = -1;
+
+       dcm_debug("[SQL query] : %s", sql_str);
+
+       if (!DCM_STRING_VALID(sql_str))
+       {
+               dcm_error("invalid query");
+               return MS_MEDIA_ERR_INVALID_PARAMETER;
+       }
+
+       err = sqlite3_prepare_v2(handle, sql_str, -1, stmt, NULL);
+       sqlite3_free((char *)sql_str);
+
+       if (err != SQLITE_OK) {
+               dcm_error ("prepare error %d[%s]", err, sqlite3_errmsg(handle));
+               if (err == SQLITE_CORRUPT) {
+                       return MS_MEDIA_ERR_DB_CORRUPT;
+               } else if (err == SQLITE_PERM) {
+                       return MS_MEDIA_ERR_DB_PERMISSION;
+               }
+
+               return MS_MEDIA_ERR_DB_INTERNAL;
+       }
+
+       return MS_MEDIA_ERR_NONE;
+}
+
+int DcmDbUtils::_dcm_svc_db_connect(uid_t uid)
+{
+       int err = -1;
+
+       dcm_debug("_dcm_svc_db_connect uid: %d", uid);
+       dcm_uid = uid;
+
+       err = media_db_connect(&db_handle, dcm_uid, TRUE);
+       if (err != MS_MEDIA_ERR_NONE) {
+               dcm_error("media_db_connect failed: %d", err);
+               db_handle = NULL;
+               return err;
+       }
+
+       dcm_warn("media db handle: %p", db_handle);
+
+       dcm_debug_fleave();
+
+       return MS_MEDIA_ERR_NONE;
+}
+
+int DcmDbUtils::_dcm_svc_db_disconnect(void)
+{
+       int err = -1;
+
+       dcm_warn("media db handle: %p", db_handle);
+
+       err = media_db_disconnect(db_handle);
+       if (err != MS_MEDIA_ERR_NONE) {
+               dcm_error("media_db_disconnect failed: %d", err);
+               db_handle = NULL;
+               return err;
+       }
+
+       db_handle = NULL;
+
+       dcm_debug_fleave();
+
+       return err;
+}
+
+
+int DcmDbUtils::_dcm_svc_db_get_scan_image_list_by_path(GList **image_list, bool mmc_mounted, const char *file_path)
+{
+       int ret = MS_MEDIA_ERR_NONE;
+       char *query_string = NULL;
+       sqlite3_stmt *sql_stmt = NULL;
+
+       dcm_debug_fenter();
+
+       DCM_CHECK_VAL(db_handle, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(file_path, DCM_ERROR_INVALID_PARAMETER);
+
+       /* Make query */
+       if (mmc_mounted == true) {
+               query_string = sqlite3_mprintf(SELECT_MEDIA_INFO_BY_FILE_PATH_FROM_DB, file_path);
+       } else {
+               query_string = sqlite3_mprintf(SELECT_MEDIA_INFO_BY_FILE_PATH_FROM_DB, file_path);
+       }
+
+       if (query_string == NULL) {
+               dcm_error("Failed to make query!");
+               return MS_MEDIA_ERR_OUT_OF_MEMORY;
+       }
+
+       ret = DcmDbUtilsInternal::__dcm_svc_sql_prepare_to_step_simple((sqlite3 *)db_handle, query_string, &sql_stmt);
+       if (ret != MS_MEDIA_ERR_NONE) {
+               dcm_error("error when __dcm_svc_sql_prepare_to_step. ret = [%d]", ret);
+               return TRUE;
+       }
+
+       
+       while(sqlite3_step(sql_stmt) == SQLITE_ROW) {
+               DcmScanItem *scan_item = (DcmScanItem *) g_malloc0(sizeof(DcmScanItem));
+               if (!scan_item) {
+                       dcm_error("Failed to allocate memory for scan_item!");
+                       continue;
+               }
+
+               if (DCM_STRING_VALID((const char *)sqlite3_column_text(sql_stmt, 0)))
+                       scan_item->media_uuid = strdup((const char *)sqlite3_column_text(sql_stmt, 0));
+
+               if (DCM_STRING_VALID(file_path))
+                       scan_item->file_path = strdup(file_path);
+
+               if (DCM_STRING_VALID((const char *)sqlite3_column_text(sql_stmt, 1)))
+                       scan_item->storage_uuid = strdup((const char *)sqlite3_column_text(sql_stmt, 1));
+
+               scan_item->image_width = sqlite3_column_int(sql_stmt, 2);
+               scan_item->image_height = sqlite3_column_int(sql_stmt, 3);
+               scan_item->image_orientation = sqlite3_column_int(sql_stmt, 4);
+               if (DCM_STRING_VALID((const char *)sqlite3_column_text(sql_stmt, 5)))
+                       scan_item->mime_type = strdup((const char *)sqlite3_column_text(sql_stmt, 5));
+
+               /* scan item retrieved by this function will be marked as SCAN_SINGLE */
+               scan_item->scan_item_type = DCM_SCAN_ITEM_TYPE_SCAN_SINGLE;
+
+               *image_list = g_list_append(*image_list, scan_item);
+
+               dcm_sec_debug("media uuid: [%s] file path: [%s]", scan_item->media_uuid, scan_item->file_path);
+       }
+       
+
+       DCM_SQLITE3_FINALIZE(sql_stmt);
+
+       dcm_debug_fleave();
+
+       return ret;
+}
+
+int DcmDbUtils::_dcm_svc_db_get_scan_image_list_from_db(GList **image_list, bool mmc_mounted)
+{
+       int ret = MS_MEDIA_ERR_NONE;
+       char * query_string = NULL;
+       sqlite3_stmt *sql_stmt = NULL;
+
+       dcm_debug_fenter();
+
+       DCM_CHECK_VAL(db_handle, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(image_list, DCM_ERROR_INVALID_PARAMETER);
+
+       /* Make query */
+       if (mmc_mounted == true) {
+               query_string = sqlite3_mprintf(SELECT_PATH_FROM_UNEXTRACTED_DCM_MEDIA);
+       } else {
+               query_string = sqlite3_mprintf(SELECT_PATH_FROM_UNEXTRACTED_DCM_INTERNAL_MEDIA);
+       }
+
+       ret = DcmDbUtilsInternal::__dcm_svc_sql_prepare_to_step_simple((sqlite3 *)db_handle, query_string, &sql_stmt);
+       if (ret != MS_MEDIA_ERR_NONE) {
+               dcm_error("error when __dcm_svc_sql_prepare_to_step_simple. ret = [%d]", ret);
+               return DCM_ERROR_DB_OPERATION;
+       }
+
+       while(sqlite3_step(sql_stmt) == SQLITE_ROW) {
+               DcmScanItem *scan_item = (DcmScanItem *) g_malloc0(sizeof(DcmScanItem));
+               if (!scan_item) {
+                       dcm_error("Failed to allocate memory for scan_item!");
+                       continue;
+               }
+
+               if (DCM_STRING_VALID((const char *)sqlite3_column_text(sql_stmt, 0)))
+                       scan_item->media_uuid = strdup((const char *)sqlite3_column_text(sql_stmt, 0));
+
+               if (DCM_STRING_VALID((const char *)sqlite3_column_text(sql_stmt, 1)))
+                       scan_item->file_path = strdup((const char *)sqlite3_column_text(sql_stmt, 1));
+
+               if (DCM_STRING_VALID((const char *)sqlite3_column_text(sql_stmt, 2)))
+                       scan_item->storage_uuid = strdup((const char *)sqlite3_column_text(sql_stmt, 2));
+
+               scan_item->image_width = sqlite3_column_int(sql_stmt, 3);
+               scan_item->image_height = sqlite3_column_int(sql_stmt, 4);
+               scan_item->image_orientation = sqlite3_column_int(sql_stmt, 5);
+               if (DCM_STRING_VALID((const char *)sqlite3_column_text(sql_stmt, 6)))
+                       scan_item->mime_type = strdup((const char *)sqlite3_column_text(sql_stmt, 6));
+
+               /* scan item retrieved by this function will be marked as SCAN_ALL */
+               scan_item->scan_item_type = DCM_SCAN_ITEM_TYPE_SCAN_ALL;
+
+               *image_list = g_list_append(*image_list, scan_item);
+
+               dcm_sec_debug("media uuid: [%s] file path: [%s]", scan_item->media_uuid, scan_item->file_path);
+       }
+
+       DCM_SQLITE3_FINALIZE(sql_stmt);
+
+       dcm_debug_fleave();
+
+       return MS_MEDIA_ERR_NONE;
+}
+
+int DcmDbUtils::_dcm_svc_db_generate_uuid(DcmFaceItem **face)
+{
+       int ret = MS_MEDIA_ERR_NONE;
+       uuid_t uuid_value;
+       static char uuid_unparsed[50] = {0, };
+
+       dcm_debug_fenter();
+       DCM_CHECK_VAL(face, DCM_ERROR_INVALID_PARAMETER);
+
+       uuid_generate(uuid_value);
+       uuid_unparse(uuid_value, uuid_unparsed);
+
+       (*face)->face_uuid = strdup(uuid_unparsed);
+
+       if ((*face)->face_uuid == NULL) {
+               ret = DCM_ERROR_UUID_GENERATE_FAILED;
+       } else {
+               dcm_debug("set face_uuid :%s", (*face)->face_uuid);
+       }
+
+       dcm_debug_fleave();
+
+       return ret;
+}
+
+int DcmDbUtils::_dcm_svc_db_insert_face_to_db(DcmFaceItem *face)
+{
+       int ret = MS_MEDIA_ERR_NONE;
+       char* query_string = NULL;
+
+       dcm_debug_fenter();
+
+       DCM_CHECK_VAL(db_handle, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(face, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(face->face_uuid, DCM_ERROR_INVALID_PARAMETER);
+
+       if (DcmDbUtilsInternal::__dcm_svc_db_check_duplicated(db_handle, face) == TRUE) {
+               dcm_error("[__dcm_svc_db_check_duplicated] The data is duplicated!");
+               return DCM_ERROR_DUPLICATED_DATA;
+       }
+
+       query_string = sqlite3_mprintf(INSERT_FACE_ITEM_TO_DB, face->face_uuid, face->media_uuid, face->face_rect_x, face->face_rect_y, face->face_rect_w, face->face_rect_h, face->orientation);
+
+       dcm_debug("query is %s", query_string);
+
+       g_mutex_trylock(&gMutexLock);
+       ret = media_db_request_update_db(query_string, dcm_uid);
+       if (ret != MS_MEDIA_ERR_NONE) {
+               dcm_error("media_db_request_update_db fail = %d, %s", ret, sqlite3_errmsg((sqlite3 *)db_handle));
+       }
+       g_mutex_unlock(&gMutexLock);
+
+       DCM_SQLITE3_FREE(query_string);
+
+       dcm_debug_fleave();
+
+       return ret;
+}
+
+int DcmDbUtils::_dcm_svc_db_insert_face_to_face_scan_list(DcmScanItem *scan_item)
+{
+       int ret = MS_MEDIA_ERR_NONE;
+       char* query_string = NULL;
+
+       dcm_debug_fenter();
+
+       DCM_CHECK_VAL(db_handle, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(scan_item, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(scan_item->media_uuid, DCM_ERROR_INVALID_PARAMETER);
+
+       if (DcmDbUtilsInternal::__dcm_svc_db_check_duplicated_scan_list(db_handle, scan_item->media_uuid) == TRUE) {
+               dcm_error("[_dcm_svc_db_insert_face_to_face_scan_list] The data is duplicated!");
+               return DCM_ERROR_DUPLICATED_DATA;
+       }
+
+       query_string = sqlite3_mprintf("INSERT INTO %s (media_uuid, storage_uuid) values('%q', '%q')", DB_TABLE_FACE_SCAN_LIST, scan_item->media_uuid, scan_item->storage_uuid);
+
+       dcm_debug("query is %s", query_string);
+
+       g_mutex_trylock(&gMutexLock);
+       ret = media_db_request_update_db(query_string, dcm_uid);
+       if (ret != MS_MEDIA_ERR_NONE) {
+               dcm_error("media_db_request_update_db is failed: %d, %s", ret, sqlite3_errmsg((sqlite3 *)db_handle));
+       }
+       g_mutex_unlock(&gMutexLock);
+
+       DCM_SQLITE3_FREE(query_string);
+
+       dcm_debug_fleave();
+
+       return ret;
+}
+
+int DcmDbUtils::_dcm_svc_db_update_color_to_db(DcmColorItem color)
+{
+       int ret = MS_MEDIA_ERR_NONE;
+       char* query_string = NULL;
+
+       dcm_debug_fenter();
+
+       DCM_CHECK_VAL(db_handle, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(color.media_uuid, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(color.storage_uuid, DCM_ERROR_INVALID_PARAMETER);
+
+       query_string = sqlite3_mprintf(UPDATE_COLOR_ITEM_TO_DB, (int)(color.rgb_r), (int)(color.rgb_g), (int)(color.rgb_b), color.media_uuid, color.storage_uuid);
+       dcm_debug("query is %s", query_string);
+
+       g_mutex_trylock(&gMutexLock);
+       ret = media_db_request_update_db(query_string, dcm_uid);
+       if (ret != MS_MEDIA_ERR_NONE) {
+               dcm_error("media_db_request_update_db fail = %d, %s", ret, sqlite3_errmsg((sqlite3 *)db_handle));
+       }
+       g_mutex_unlock(&gMutexLock);
+
+       DCM_SQLITE3_FREE(query_string);
+
+       dcm_debug_fleave();
+
+       return ret;
+}
+
+int DcmDbUtils::_dcm_svc_db_check_scanned_by_media_uuid(const char *media_uuid, bool *media_scanned)
+{
+       int ret = MS_MEDIA_ERR_NONE;
+       char *query_string = NULL;
+       sqlite3_stmt *sql_stmt = NULL;
+       int count = 0;
+
+       dcm_debug_fenter();
+
+       DCM_CHECK_VAL(db_handle, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(media_uuid, DCM_ERROR_INVALID_PARAMETER);
+
+       query_string = sqlite3_mprintf("SELECT count(*) FROM %s WHERE (media_uuid='%q')", DB_TABLE_FACE_SCAN_LIST, media_uuid);
+       DCM_CHECK_VAL(query_string, DCM_ERROR_OUT_OF_MEMORY);
+
+       ret = DcmDbUtilsInternal::__dcm_svc_sql_prepare_to_step((sqlite3 *)db_handle, query_string, &sql_stmt);
+       if (ret != MS_MEDIA_ERR_NONE) {
+               dcm_error("error when __dcm_svc_sql_prepare_to_step. ret = [%d]", ret);
+               return DCM_ERROR_DB_OPERATION;
+       }
+
+       count = sqlite3_column_int(sql_stmt, 0);
+
+       DCM_SQLITE3_FINALIZE(sql_stmt);
+
+       if (count > 0)
+               *media_scanned = TRUE;
+       else
+               *media_scanned = FALSE;
+
+       dcm_debug_fleave();
+
+       return ret;
+}
+
+int DcmDbUtils::_dcm_svc_db_send_noti(DcmFaceItem *face, DcmFaceItemUpdateItem update_item, DcmFaceItemUpdateType update_type)
+{
+       int ret = MS_MEDIA_ERR_NONE;
+
+       dcm_debug_fenter();
+
+       if (face == NULL)
+       {
+               //ret = DCM_ERROR_INVALID_PARAMETER;
+       } else {
+               //ret = media_face_db_update_send((media_face_item_type_e)update_item, (media_face_item_update_type_e)update_type, face->media_id, face->face_uuid);
+       }
+
+       if (ret != MS_MEDIA_ERR_NONE) {
+               dcm_error("Failed to send noti after update db! err: %d, %s", ret, sqlite3_errmsg((sqlite3 *)db_handle));
+       }
+
+       dcm_debug_fleave();
+
+       return ret;
+}
diff --git a/src/DcmFaceUtils.cpp b/src/DcmFaceUtils.cpp
new file mode 100755 (executable)
index 0000000..a7d67d3
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <unistd.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <glib.h>
+#include <image_util.h>
+#include <dcm-face.h>
+#include <dcm_image_codec.h>
+#include <DcmDbUtils.h>
+#include <DcmTypes.h>
+#include <DcmDebugUtils.h>
+#include <DcmFaceUtils.h>
+
+
+namespace DcmFaceApi {
+int createFaceItem(DcmFaceItem **face);
+double caculateScaleFactor(DcmImageInfo *image_info);
+void freeDcmFaceItem(void *data);
+}
+
+static dcm_face_h dcm_face_handle = NULL;
+
+int DcmFaceUtils::initialize()
+{
+       int ret = FACE_ERROR_NONE;
+
+       dcm_debug_fenter();
+
+       ret = dcm_face_create(&dcm_face_handle);
+       if (ret != FACE_ERROR_NONE) {
+               dcm_error("Failed to dcm_face_create err: %d", ret);
+               return DCM_ERROR_FACE_ENGINE_FAILED;
+       }
+
+       dcm_debug_fleave();
+
+       return DCM_SUCCESS;
+}
+
+int DcmFaceUtils::finalize()
+{
+       int ret = FACE_ERROR_NONE;
+
+       dcm_debug_fenter();
+
+       DCM_CHECK_VAL(dcm_face_handle, DCM_ERROR_INVALID_PARAMETER);
+
+       ret = dcm_face_destroy(dcm_face_handle);
+       if (ret != FACE_ERROR_NONE) {
+               dcm_error("Failed to dcm_face_destroy ret: %d", ret);
+               return DCM_ERROR_FACE_ENGINE_FAILED;
+       }
+
+       dcm_face_handle = NULL;
+
+       dcm_debug_fleave();
+
+       return DCM_SUCCESS;
+}
+
+int DcmFaceUtils::runFaceRecognizeProcess(DcmScanItem *scan_item, DcmImageInfo *image_info)
+{
+       DcmDbUtils *dcmDbUtils = DcmDbUtils::getInstance();
+       DcmFaceItem *face = NULL;
+       int face_area = 0;
+       int i = 0;
+       double scale_factor = 0.0;
+       int err = FACE_ERROR_NONE;
+       int ret = DCM_SUCCESS;
+       face_info_s *face_info = NULL;
+
+       dcm_debug_fenter();
+
+       DCM_CHECK_VAL(dcm_face_handle, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(scan_item, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(image_info, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(image_info->pixel, DCM_ERROR_INVALID_PARAMETER);
+
+       /* Create image buffer used for face detection */
+       face_image_colorspace_e prefered_colorspace = FACE_IMAGE_COLORSPACE_RGB888;
+
+       err = dcm_face_get_prefered_colorspace(dcm_face_handle, &prefered_colorspace);
+       if (err != FACE_ERROR_NONE) {
+               dcm_error("Failed to create face_image! err: %d", err);
+               ret = DCM_ERROR_FACE_ENGINE_FAILED;
+               goto DCM_SVC_FACE_RECOGNIZE_BUFFER_FAILED;
+       }
+
+       dcm_debug("colorspce: [%d], w: [%d], h: [%d]", prefered_colorspace, image_info->buffer_width, image_info->buffer_height);
+
+       err = dcm_face_set_image_info(dcm_face_handle, prefered_colorspace, image_info->pixel, image_info->buffer_width, image_info->buffer_height, image_info->size);
+       if (err != FACE_ERROR_NONE) {
+               dcm_error("Failed to dcm_face_set_image_info! err: %d", err);
+               ret = DCM_ERROR_FACE_ENGINE_FAILED;
+               goto DCM_SVC_FACE_RECOGNIZE_BUFFER_FAILED;
+       }
+
+       face_info = (face_info_s*)g_malloc0(sizeof(face_info_s));
+
+       err = dcm_face_get_face_info(dcm_face_handle, face_info);
+       if (err != FACE_ERROR_NONE) {
+               dcm_error("Failed to get face info! err: %d", err);
+               ret = DCM_ERROR_FACE_ENGINE_FAILED;
+               goto DCM_SVC_FACE_RECOGNIZE_BUFFER_FAILED;
+       }
+
+       dcm_warn("detected face count: %d", face_info->count);
+       if (face_info->count <= 0) {
+               goto DCM_SVC_FACE_RECOGNIZE_BUFFER_FAILED;
+       }
+
+       /* Compute scale factor between decode size and original size */
+       scale_factor = DcmFaceApi::caculateScaleFactor(image_info);
+
+       /* Insert every face rectangle into database */
+       for (i = 0; i < face_info->count; i++) {
+               face = NULL;
+
+               err = DcmFaceApi::createFaceItem(&face);
+               if (err != DCM_SUCCESS) {
+                       dcm_error("Failed to create face items! err: %d", err);
+                       ret = err;
+                       goto DCM_SVC_FACE_RECOGNIZE_BUFFER_FAILED;
+               }
+
+               if (scale_factor > 1.0) {
+                       face->face_rect_x = (int) (face_info->rects[i].x * scale_factor);
+                       face->face_rect_y = (int) (face_info->rects[i].y * scale_factor);
+                       face->face_rect_w = (int) (face_info->rects[i].w * scale_factor);
+                       face->face_rect_h = (int) (face_info->rects[i].h * scale_factor);
+               } else {
+                       face->face_rect_x = face_info->rects[i].x;
+                       face->face_rect_y = face_info->rects[i].y;
+                       face->face_rect_w = face_info->rects[i].w;
+                       face->face_rect_h = face_info->rects[i].h;
+               }
+               face->orientation = face_info->rects[i].orientation;
+
+               face_area += face->face_rect_w * face->face_rect_h;
+               dcm_debug("[#%d] face rect: XYWH (%d, %d, %d, %d)", i, face->face_rect_x, face->face_rect_y, face->face_rect_w,
+               face->face_rect_h);
+
+               face->media_uuid = strdup(scan_item->media_uuid);
+
+               /* Insert face rectangle into database */
+               err = dcmDbUtils->_dcm_svc_db_generate_uuid(&face);
+               if (err != DCM_SUCCESS) {
+                       dcm_error("Failed to set uuid! err: %d", err);
+                       goto DCM_SVC_FACE_RECOGNIZE_BUFFER_FAILED;
+               }
+               err = dcmDbUtils->_dcm_svc_db_insert_face_to_db(face);
+               if (err != DCM_SUCCESS) {
+                       dcm_error("Failed to insert face item into db! err: %d", err);
+                       goto DCM_SVC_FACE_RECOGNIZE_BUFFER_FAILED;
+               }
+
+               /* Send db updated notification */
+               dcmDbUtils->_dcm_svc_db_send_noti(face, DCM_FACE_ITEM_UPDATE_FACE, DCM_FACE_ITEM_INSERT);
+               if (face != NULL) {
+                       DcmFaceApi::freeDcmFaceItem(face);
+                       face = NULL;
+               }
+       }
+
+DCM_SVC_FACE_RECOGNIZE_BUFFER_FAILED:
+
+       dcmDbUtils->_dcm_svc_db_insert_face_to_face_scan_list(scan_item);
+
+       if (face_info != NULL) {
+               dcm_face_destroy_face_info(face_info);
+               face_info = NULL;
+       }
+
+       if (face != NULL) {
+               DcmFaceApi::freeDcmFaceItem(face);
+               face = NULL;
+       }
+
+       dcm_debug_fleave();
+
+       return ret;
+}
+
+int DcmFaceApi::createFaceItem(DcmFaceItem **face)
+{
+       DCM_CHECK_VAL(face, DCM_ERROR_INVALID_PARAMETER);
+
+       *face = NULL;
+
+       DcmFaceItem *_face = (DcmFaceItem*)g_malloc0(sizeof(DcmFaceItem));
+       if (_face == NULL)
+               return DCM_ERROR_OUT_OF_MEMORY;
+
+       *face = _face;
+
+       return DCM_SUCCESS;
+}
+
+double DcmFaceApi::caculateScaleFactor(DcmImageInfo *image_info)
+{
+       double scale_factor = 0.0;
+
+       DCM_CHECK_VAL(image_info, 0.0);
+
+       if (image_info->original_width >= image_info->original_height) {
+               if (image_info->buffer_width >= image_info->buffer_height) {
+                       scale_factor = ((double) (image_info->original_width)) / ((double) (image_info->buffer_width));
+               } else {
+                       scale_factor = ((double) (image_info->original_width)) / ((double) (image_info->buffer_height));
+               }
+       } else {
+               if (image_info->buffer_height >= image_info->buffer_width) {
+                       scale_factor = ((double) (image_info->original_height)) / ((double) (image_info->buffer_height));
+               } else {
+                       scale_factor = ((double) (image_info->original_height)) / ((double) (image_info->buffer_width));
+               }
+       }
+
+       dcm_debug("scale_factor: %lf", scale_factor);
+
+       return scale_factor;
+}
+
+void DcmFaceApi::freeDcmFaceItem(void *data)
+{
+       DcmFaceItem *_face = (DcmFaceItem *)data;
+       DCM_CHECK(_face);
+
+       DCM_SAFE_FREE(_face->face_uuid);
+       DCM_SAFE_FREE(_face->media_uuid);
+       DCM_SAFE_FREE(_face);
+
+       return;
+}
diff --git a/src/DcmIpcUtils.cpp b/src/DcmIpcUtils.cpp
new file mode 100755 (executable)
index 0000000..c56a6ad
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+#include <sys/syscall.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
+
+#include <DcmIpcUtils.h>
+#include <DcmTypes.h>
+#include <DcmDebugUtils.h>
+
+static char DCM_IPC_PATH[5][100] =
+                       {"/var/run/media-server/dcm_ipc_scanthread_recv",
+                        "/var/run/media-server/dcm_ipc_thumbserver_comm_recv",
+                        "/var/run/media-server/media_ipc_thumbdcm_dcmrecv"};
+
+int DcmIpcUtils::receiveSocketMsg(int client_sock, DcmIpcMsg *recv_msg)
+{
+       int recv_msg_size = 0;
+
+       if ((recv_msg_size = read(client_sock, recv_msg, sizeof(DcmIpcMsg))) < 0) {
+               if (errno == EWOULDBLOCK) {
+                       dcm_error("Timeout. Can't try any more");
+                       return DCM_ERROR_IPC;
+               } else {
+                       dcm_error("recv failed : %s", strerror(errno));
+                       return DCM_ERROR_NETWORK;
+               }
+       }
+       dcm_sec_debug("[receive msg] type: %d, uid: %d, msg: %s, msg_size: %d", recv_msg->msg_type, recv_msg->uid, recv_msg->msg, recv_msg->msg_size);
+
+       if (!(recv_msg->msg_type >= 0 && recv_msg->msg_type < DCM_IPC_MSG_MAX)) {
+               dcm_error("IPC message is wrong!");
+               return DCM_ERROR_IPC_INVALID_MSG;
+       }
+
+       return DCM_SUCCESS;
+}
+
+int DcmIpcUtils::acceptSocket(int serv_sock, int* client_sock)
+{
+       DCM_CHECK_VAL(client_sock, DCM_ERROR_INVALID_PARAMETER);
+       int sockfd = -1;
+       struct sockaddr_un client_addr;
+       socklen_t client_addr_len = sizeof(client_addr);
+
+       if ((sockfd = accept(serv_sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) {
+               dcm_error("accept failed : %s", strerror(errno));
+               *client_sock = -1;
+               return DCM_ERROR_NETWORK;
+       }
+
+       *client_sock = sockfd;
+
+       return DCM_SUCCESS;
+}
+
+int DcmIpcUtils::createSocket(int *socket_fd, DcmIpcPortType port)
+{
+       DCM_CHECK_VAL(socket_fd, DCM_ERROR_INVALID_PARAMETER);
+       int sock = -1;
+       struct sockaddr_un serv_addr;
+       bool bind_success = false;
+       int i = 0;
+
+       /* Create a new TCP socket */
+       if ((sock = socket(PF_FILE, SOCK_STREAM, 0)) < 0) {
+               dcm_error("socket failed: %s", strerror(errno));
+               return DCM_ERROR_NETWORK;
+       }
+
+       /* Set socket address */
+       memset(&serv_addr, 0, sizeof(serv_addr));
+       serv_addr.sun_family = AF_UNIX;
+       unlink(DCM_IPC_PATH[port]);
+       strcpy(serv_addr.sun_path, DCM_IPC_PATH[port]);
+
+       /* Bind socket to local address */
+       for (i = 0; i < 20; i++) {
+               if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0) {
+                       bind_success = true;
+                       break;
+               }
+               dcm_debug("#%d bind", i);
+               usleep(250000);
+       }
+
+       if (bind_success == false) {
+               dcm_error("bind failed : %s %d_", strerror(errno), errno);
+               close(sock);
+               return DCM_ERROR_NETWORK;
+       }
+       dcm_debug("bind success");
+
+       /* Listenint */
+       if (listen(sock, SOMAXCONN) < 0) {
+               dcm_error("listen failed : %s", strerror(errno));
+               close(sock);
+               return DCM_ERROR_NETWORK;
+       }
+       dcm_debug("Listening...");
+
+       /* change permission of local socket file */
+       if (chmod(DCM_IPC_PATH[port], 0660) < 0)
+               dcm_error("chmod failed [%s]", strerror(errno));
+       /*
+       if (chown(DCM_IPC_PATH[port], 0, 5000) < 0)
+               dcm_dbgE("chown failed [%s]", strerror(errno));
+       */
+
+       *socket_fd = sock;
+
+       return DCM_SUCCESS;
+}
+
+int DcmIpcUtils::sendSocketMsg(DcmIpcMsgType msg_type, uid_t uid, const char *msg, DcmIpcPortType port)
+{
+       if (port < 0 || port >= DCM_IPC_PORT_MAX) {
+               dcm_error("Invalid port! Stop sending message...");
+               return DCM_ERROR_INVALID_PARAMETER;
+       }
+       dcm_debug("Send message type: %d", msg_type);
+
+       int socket_fd = -1;
+       struct sockaddr_un serv_addr;
+       //struct timeval tv_timeout = { 10, 0 }; /* timeout: 10 seconds */
+       DcmIpcMsg send_msg;
+
+       /* Prepare send message */
+       memset((void *)&send_msg, 0, sizeof(DcmIpcMsg));
+       send_msg.msg_type = msg_type;
+       send_msg.uid = uid;
+       if (msg != NULL) {
+               send_msg.msg_size = strlen(msg);
+               strncpy(send_msg.msg, msg, send_msg.msg_size);
+       }
+
+       /* If message size is larget than max_size, then message is invalid */
+       if (send_msg.msg_size >= DCM_IPC_MSG_MAX_SIZE) {
+               dcm_error("Message size is invalid!");
+               return DCM_ERROR_INVALID_IMAGE_SIZE;
+       }
+
+       /* Create a new TCP socket */
+       if ((socket_fd = socket(PF_FILE, SOCK_STREAM, 0)) < 0) {
+               dcm_error("socket failed: %s", strerror(errno));
+               return DCM_ERROR_NETWORK;
+       }
+
+       /* Set dcm thread socket address */
+       memset(&serv_addr, 0, sizeof(serv_addr));
+       serv_addr.sun_family = AF_UNIX;
+       strcpy(serv_addr.sun_path, DCM_IPC_PATH[port]);
+
+       /* Connect to the socket */
+       if (connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
+               dcm_error("connect error : %s", strerror(errno));
+               close(socket_fd);
+               return DCM_ERROR_NETWORK;
+       }
+
+       /* Send msg to the socket */
+       if (send(socket_fd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) {
+               dcm_error("send failed : %s", strerror(errno));
+               close(socket_fd);
+               return DCM_ERROR_NETWORK;
+       }
+
+       close(socket_fd);
+       return DCM_SUCCESS;
+}
+
+int DcmIpcUtils::closeSocket(int socket_fd)
+{
+       close(socket_fd);
+       return DCM_SUCCESS;
+}
+
+#define DCM_SVC_FACE_ASYNC_MEDIA_UUID_LENGTH 64
+#define DCM_SVC_FACE_ASYNC_UDP_SEND_PORT 1551
+#define DCM_SVC_FACE_ASYNC_INET_ADDR "127.0.0.1"
+typedef struct
+{
+       int type; /* type should be set to 0 */
+       char media_uuid[DCM_SVC_FACE_ASYNC_MEDIA_UUID_LENGTH];
+} dcm_svc_face_async_msg_s;
+
+int DcmIpcUtils::sendFaceMsg(const char *media_uuid)
+{
+       dcm_debug_fenter();
+       DCM_CHECK_VAL(media_uuid, DCM_ERROR_INVALID_PARAMETER);
+       dcm_sec_debug("media_id: %s", media_uuid);
+       struct sockaddr_in client_addr;
+       int socket_fd = 0;
+       int ret = 0;
+
+       /* Create send socket */
+       if ((socket_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+               dcm_error("Failed to create socket for libface-svc! err: %s", strerror(errno));
+               return DCM_ERROR_NETWORK;
+       }
+       dcm_debug("socket fd: %d", socket_fd);
+
+       /* Set send message */
+       dcm_svc_face_async_msg_s face_async_msg;
+       memset(&face_async_msg, 0x00, sizeof(dcm_svc_face_async_msg_s));
+       face_async_msg.type = 0;
+       g_strlcpy(face_async_msg.media_uuid, media_uuid, sizeof(face_async_msg.media_uuid));
+
+       /* Set face async port and address */
+       client_addr.sin_family = AF_INET;
+       client_addr.sin_port = htons(DCM_SVC_FACE_ASYNC_UDP_SEND_PORT);
+       client_addr.sin_addr.s_addr = inet_addr(DCM_SVC_FACE_ASYNC_INET_ADDR);
+
+       /* Send message to libface-svc */
+       ret = sendto(socket_fd, &face_async_msg, sizeof(dcm_svc_face_async_msg_s), MSG_NOSIGNAL, (struct sockaddr*)&client_addr, sizeof(client_addr));
+       if (ret < 0) {
+               dcm_error("Failed to send message to libface-svc! err: %s", strerror(errno));
+               close(socket_fd);
+               return DCM_ERROR_NETWORK;
+       }
+
+       close(socket_fd);
+       dcm_debug_fleave();
+       return DCM_SUCCESS;
+}
+
diff --git a/src/DcmScanSvc.cpp b/src/DcmScanSvc.cpp
new file mode 100755 (executable)
index 0000000..f606515
--- /dev/null
@@ -0,0 +1,695 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+#include <vconf.h>
+#include <img-codec-parser.h>
+
+#include "../libdcm-util/include/dcm_image_codec.h"
+#include <DcmDbUtils.h>
+#include <DcmColorUtils.h>
+#include <DcmFaceUtils.h>
+#include <DcmIpcUtils.h>
+#include <DcmTypes.h>
+#include <DcmScanSvc.h>
+#include <DcmMainSvc.h>
+#include <DcmDebugUtils.h>
+#include <Ecore_Evas.h>
+
+#define MIME_TYPE_JPEG "image/jpeg"
+#define MIME_TYPE_PNG "image/png"
+#define MIME_TYPE_BMP "image/bmp"
+
+class DcmScanSvc {
+public:
+    GMainLoop *g_scan_thread_mainloop;
+    GMainContext *scan_thread_main_context;
+
+    /* scan all images */
+    GList *scan_all_item_list;
+    unsigned int scan_all_curr_index;
+
+    /* scan single images */
+    GList *scan_single_item_list;
+    unsigned int scan_single_curr_index;
+
+    void quitScanThread();
+    int getMmcState(void);
+    int prepareImageList();
+       int prepareImageListByPath(const char *file_path);
+    int clearAllItemList();
+    int clearSingleItemList();
+    int initialize();
+    int finalize();
+    int sendCompletedMsg(const char *msg, DcmIpcPortType port);
+    int getScanStatus(DcmScanItem *scan_item, bool *media_scanned);
+    int runScanProcess(DcmScanItem *scan_item);
+    int ScanAllItems();
+    int ScanSingleItem(const char *file_path);
+    int terminateScanOperations();
+    int receiveMsg(DcmIpcMsg *recv_msg);
+
+};
+
+namespace DcmScanCallback {
+void freeScanItem(void *data);
+gboolean readyScanThreadIdle(gpointer data);
+gboolean readMsg(GIOChannel *src, GIOCondition condition, gpointer data);
+}
+
+void DcmScanSvc::quitScanThread()
+{
+       if (g_scan_thread_mainloop != NULL) {
+               dcm_warn("Quit scan thread mainloop!");
+               g_main_loop_quit(g_scan_thread_mainloop);
+       } else {
+               dcm_warn("Scan thread mainloop is invalid!");
+       }
+
+       return;
+}
+
+int DcmScanSvc::getMmcState(void)
+{
+       int err = -1;
+       int status = -1;
+
+       err = vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &status);
+       if (err != 0) {
+               dcm_error("vconf_get_int Unexpected error code: %d", err);
+       }
+
+       return status;
+}
+
+int DcmScanSvc::prepareImageList()
+{
+       int ret = DCM_SUCCESS;
+       DcmDbUtils *dcmDbUtils = DcmDbUtils::getInstance();
+       bool mmc_mounted = false;
+
+       if (getMmcState() == VCONFKEY_SYSMAN_MMC_MOUNTED) {
+               mmc_mounted = true;
+       } else {
+               mmc_mounted = false;
+       }
+
+       /* Get scan image list from db */
+       ret = dcmDbUtils->_dcm_svc_db_get_scan_image_list_from_db(&(scan_all_item_list), mmc_mounted);
+       if (ret != MS_MEDIA_ERR_NONE) {
+               dcm_error("Failed to get image list from db! ret: %d", ret);
+               return ret;
+       }
+
+       if (scan_all_item_list == NULL) {
+               dcm_debug("No image list for scanning");
+               return DCM_ERROR_DB_NO_RESULT;
+       }
+
+       if ((scan_all_item_list != NULL) && (g_list_length(scan_all_item_list) == 0)) {
+               dcm_debug("No image list from db!");
+               return DCM_ERROR_DB_NO_RESULT;
+       }
+
+       return DCM_SUCCESS;
+}
+
+int DcmScanSvc::prepareImageListByPath(const char *file_path)
+{
+       int ret = DCM_SUCCESS;
+       DcmDbUtils *dcmDbUtils = DcmDbUtils::getInstance();
+       bool mmc_mounted = false;
+
+       if (getMmcState() == VCONFKEY_SYSMAN_MMC_MOUNTED) {
+               mmc_mounted = true;
+       } else {
+               mmc_mounted = false;
+       }
+
+       /* Get scan image list from db */
+       ret = dcmDbUtils->_dcm_svc_db_get_scan_image_list_by_path(&(scan_single_item_list), mmc_mounted, file_path);
+       if (ret != MS_MEDIA_ERR_NONE) {
+               dcm_error("Failed to get image list from db! ret: %d", ret);
+               return ret;
+       }
+
+       if (scan_single_item_list == NULL) {
+               dcm_debug("No image list for scanning");
+               return DCM_ERROR_DB_NO_RESULT;
+       }
+
+       if ((scan_single_item_list != NULL) && (g_list_length(scan_single_item_list) == 0)) {
+               dcm_debug("No image list from db!");
+               return DCM_ERROR_DB_NO_RESULT;
+       }
+
+       return DCM_SUCCESS;
+}
+
+int DcmScanSvc::clearAllItemList()
+{
+       dcm_debug_fenter();
+
+       if (scan_all_item_list != NULL) {
+               g_list_free_full(scan_all_item_list, DcmScanCallback::freeScanItem);
+               scan_all_item_list = NULL;
+       }
+
+       scan_all_curr_index = 0;
+
+       return DCM_SUCCESS;
+}
+
+int DcmScanSvc::clearSingleItemList()
+{
+       dcm_debug_fenter();
+
+       if (scan_single_item_list) {
+               g_list_free_full(scan_single_item_list, DcmScanCallback::freeScanItem);
+               scan_single_item_list = NULL;
+       }
+
+       scan_single_curr_index = 0;
+
+       return DCM_SUCCESS;
+}
+
+int DcmScanSvc::initialize()
+{
+       scan_all_item_list = NULL;
+       scan_all_curr_index = 0;
+       scan_single_item_list = NULL;
+       scan_single_curr_index = 0;
+
+       DcmFaceUtils::initialize();
+
+       ecore_evas_init();
+
+       return DCM_SUCCESS;
+}
+
+int DcmScanSvc::finalize()
+{
+       /* Only scan item lists are freed here, scan idles should be freed before this function */
+       clearAllItemList();
+       clearSingleItemList();
+       DcmFaceUtils::finalize();
+
+       ecore_evas_shutdown();
+
+       return DCM_SUCCESS;
+}
+
+int DcmScanSvc::sendCompletedMsg(const char *msg, DcmIpcPortType port)
+{
+       if ((scan_all_item_list == NULL) && (scan_single_item_list == NULL)) {
+               dcm_debug("Send completed message");
+               DcmIpcUtils::sendSocketMsg(DCM_IPC_MSG_SCAN_COMPLETED, 0, msg, port);
+       } else {
+               if (scan_all_item_list)
+                       dcm_warn("scan_all_item_list");
+
+               if (scan_single_item_list)
+                       dcm_warn("scan_single_item_list");
+
+               dcm_warn("Scan operation is not finished yet. Keep scanning...");
+       }
+
+       return DCM_SUCCESS;
+}
+
+int DcmScanSvc::getScanStatus(DcmScanItem *scan_item, bool *media_scanned)
+{
+       int ret = DCM_SUCCESS;
+       DcmDbUtils *dcmDbUtils = DcmDbUtils::getInstance();
+
+       DCM_CHECK_VAL(scan_item, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(scan_item->media_uuid, DCM_ERROR_INVALID_PARAMETER);
+
+       /* Check if this media is scanned or not */
+       ret = dcmDbUtils->_dcm_svc_db_check_scanned_by_media_uuid(scan_item->media_uuid, media_scanned);
+       if (ret != DCM_SUCCESS) {
+               dcm_error("Failed to check if this media item is scanned or not!");
+       }
+
+       return ret;
+}
+
+int DcmScanSvc::runScanProcess(DcmScanItem *scan_item)
+{
+       bool media_scanned = false;
+       int ret = DCM_SUCCESS;
+
+       dcm_debug_fenter();
+       DCM_CHECK_VAL(scan_item, DCM_ERROR_INVALID_PARAMETER);
+       DCM_CHECK_VAL(scan_item->file_path, DCM_ERROR_INVALID_PARAMETER);
+
+       DcmImageInfo image_info = {0, };
+       memset(&image_info, 0, sizeof(DcmImageInfo));
+       dcm_image_codec_type_e image_format = DCM_IMAGE_CODEC_RGB888;
+
+       /* Process scan operation if the file exists */
+       if (g_file_test(scan_item->file_path, (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) == TRUE) {
+               /* Get necessary information from db again.
+               * Media information will be inserted after face is detected.
+               * If media uuid does not exist, retry is needed */
+               ret = getScanStatus(scan_item, &media_scanned);
+               if (ret != DCM_SUCCESS) {
+                       dcm_error("Failed to get scan item info from db! err: %d", ret);
+                       return ret;
+               }
+
+               /* It is possible that when single and async scan for the same image is in the list.
+               * If the media uuid is already scanned, skip this scan. */
+               if (media_scanned == true) {
+                       dcm_warn("This media is scanned already! Skip...");
+                       DCM_SAFE_FREE(image_info.pixel);
+                       return DCM_ERROR_IMAGE_ALREADY_SCANNED;
+               } else {
+                       dcm_debug("This media is NOT scanned yet.");
+               }
+
+               dcm_sec_debug("scan file path : [%s]", scan_item->file_path);
+               dcm_sec_debug("scan media uuid : [%s]", scan_item->media_uuid);
+
+               ImgCodecType type = IMG_CODEC_NONE;
+
+               image_info.original_width = scan_item->image_width;
+               image_info.original_height = scan_item->image_height;
+
+               dcm_debug("scan media w : [%d], h : [%d], orientation : [%d]", image_info.original_width, image_info.original_height, scan_item->image_orientation);
+
+               if (image_info.original_width <= 0 && image_info.original_height <= 0) {
+                       ret = ImgGetImageInfo((const char *)(scan_item->file_path), &type, &(image_info.original_width), &(image_info.original_height));
+                       if (ret != DCM_SUCCESS) {
+                               dcm_error("Failed ImgGetImageInfo! err: %d", ret);
+                               return ret;
+                       }
+
+                       dcm_debug("ImgGetImageInfo type: %d, width: %d, height: %d", type, image_info.original_width, image_info.original_height);
+               }
+
+               if (strcmp(scan_item->mime_type, MIME_TYPE_JPEG) == 0) {
+                       ret = dcm_decode_image_with_size_orient((const char *) (scan_item->file_path), image_info.original_width,
+                               image_info.original_height, image_format, &(image_info.pixel), &(image_info.buffer_width), &(image_info.buffer_height), &(image_info.orientation), &(image_info.size));
+                       if (ret != DCM_SUCCESS) {
+                               dcm_error("Failed dcm_decode_image_with_size_orient! err: %d", ret);
+                               return ret;
+                       }
+               } else if ((strcmp(scan_item->mime_type, MIME_TYPE_PNG) == 0) || (strcmp(scan_item->mime_type, MIME_TYPE_BMP) == 0)) {
+                       ret = dcm_decode_image_with_evas((const char *) (scan_item->file_path), image_info.original_width,
+                               image_info.original_height, image_format, &(image_info.pixel), &(image_info.buffer_width), &(image_info.buffer_height), &(image_info.orientation), &(image_info.size));
+                       if (ret != DCM_SUCCESS) {
+                               dcm_error("Failed dcm_decode_image_with_evas! err: %d", ret);
+                               return ret;
+                       }
+               } else {
+                       dcm_error("Failed not supported type! (%s)", scan_item->mime_type);
+                       return DCM_ERROR_INVALID_PARAMETER;
+               }
+               image_info.decode_type = (DcmImageDecodeType)image_format;
+
+               dcm_debug("Image info width: %d, height: %d, buf_width: %d, buf_height: %d, orientation: %d",
+                       image_info.original_width, image_info.original_height, image_info.buffer_width, image_info.buffer_height, image_info.orientation);
+
+               /* Process face scan */
+               ret = DcmFaceUtils::runFaceRecognizeProcess(scan_item, &image_info);
+               if (ret != DCM_SUCCESS) {
+                       dcm_error("Failed to process face detection! err: %d", ret);
+               }
+
+               /* Set sleep time after face recognition */
+               usleep(500000);
+
+               /* Process color extract */
+               ret = DcmColorUtils::runColorExtractProcess(scan_item, &image_info);
+               if (ret != DCM_SUCCESS) {
+                       dcm_error("Failed to process color extraction! err: %d", ret);
+               }
+
+               /* Free image buffer */
+               DCM_SAFE_FREE(image_info.pixel);
+       } else {
+               dcm_warn("The file does not exist! Skip dcm scan for this file ...");
+       }
+
+       dcm_debug_fleave();
+
+       return ret;
+}
+
+int DcmScanSvc::ScanAllItems()
+{
+       int ret = DCM_SUCCESS;
+       DcmScanItem *scan_item = NULL;
+       DcmDbUtils *dcmDbUtils = DcmDbUtils::getInstance();
+
+       dcm_debug_fenter();
+
+       clearAllItemList();
+
+       ret = prepareImageList();
+       if (ret == DCM_ERROR_DB_NO_RESULT) {
+               dcm_debug("No items to Scan. Scan operation completed!!!");
+               clearAllItemList();
+               /* Send scan complete message to main thread (if all scan operations are finished) */
+               sendCompletedMsg( NULL, DCM_IPC_PORT_DCM_RECV);
+               return DCM_SUCCESS;
+       }
+
+       /* DCM scan started */
+       unsigned int list_len = g_list_length(scan_all_item_list);
+       while (scan_all_curr_index < list_len) {
+               scan_item = (DcmScanItem *)g_list_nth_data(scan_all_item_list, scan_all_curr_index);
+               dcm_sec_debug("current index: %d, path: %s", scan_all_curr_index, scan_item->file_path);
+
+               ret = runScanProcess(scan_item);
+               if (ret != DCM_SUCCESS) {
+                       dcm_error("Failed to process scan job! err: %d", ret);
+
+                       /* If the scan item is not scanned, insert media uuid into face_scan_list */
+                       if (ret != DCM_ERROR_IMAGE_ALREADY_SCANNED) {
+                               dcmDbUtils->_dcm_svc_db_insert_face_to_face_scan_list(scan_item);
+                       }
+               }
+
+               (scan_all_curr_index)++;
+       }
+
+       dcm_warn("All images are scanned. Scan operation completed");
+
+       clearAllItemList();
+       /* Send scan complete message to main thread (if all scan operations are finished) */
+       sendCompletedMsg( NULL, DCM_IPC_PORT_DCM_RECV);
+
+       dcm_debug_fleave();
+
+       return DCM_SUCCESS;
+}
+
+int DcmScanSvc::ScanSingleItem(const char *file_path)
+{
+       int ret = DCM_SUCCESS;
+       DcmScanItem *scan_item = NULL;
+       DcmDbUtils *dcmDbUtils = DcmDbUtils::getInstance();
+
+       DCM_CHECK_VAL(file_path, DCM_ERROR_INVALID_PARAMETER);
+
+       dcm_debug_fenter();
+
+       clearSingleItemList();
+
+       ret = prepareImageListByPath(file_path);
+       if (ret == DCM_ERROR_DB_NO_RESULT) {
+               dcm_debug("No items to Scan. Scan operation completed!!!");
+               clearSingleItemList();
+               /* Send scan complete message to main thread (if all scan operations are finished) */
+               sendCompletedMsg( file_path/*ret*/, DCM_IPC_PORT_DCM_RECV);
+               return DCM_SUCCESS;
+       }
+
+       dcm_debug("append scan item to scan item list");
+
+       /* DCM scan started */
+       unsigned int list_len = g_list_length(scan_single_item_list);
+       if (scan_single_curr_index < list_len) {
+               scan_item = (DcmScanItem *)g_list_nth_data(scan_single_item_list, scan_single_curr_index);
+               dcm_sec_debug("current index: %d, path: %s, scan type: %d", scan_single_curr_index, scan_item->file_path, scan_item->scan_item_type);
+
+               ret = runScanProcess(scan_item);
+               if (ret != DCM_SUCCESS) {
+                       dcm_error("Failed to process scan job! err: %d", ret);
+
+                       /* If the scan item is not scanned, insert media uuid into face_scan_list */
+                       if (ret != DCM_ERROR_IMAGE_ALREADY_SCANNED) {
+                               dcmDbUtils->_dcm_svc_db_insert_face_to_face_scan_list(scan_item);
+                       }
+               }
+
+               (scan_single_curr_index)++;
+       }
+
+       clearSingleItemList();
+
+       dcm_debug_fleave();
+
+       return DCM_SUCCESS;
+}
+
+int DcmScanSvc::terminateScanOperations()
+{
+       dcm_debug("Terminate scanning operations, and quit scan thread main loop");
+
+       quitScanThread();
+
+       return DCM_SUCCESS;
+}
+
+int DcmScanSvc::receiveMsg(DcmIpcMsg *recv_msg)
+{
+       int ret = DCM_SUCCESS;
+
+       DcmDbUtils *dcmDbUtils = DcmDbUtils::getInstance();
+       DCM_CHECK_VAL(recv_msg, DCM_ERROR_INVALID_PARAMETER);
+
+       ret = dcmDbUtils->_dcm_svc_db_connect(recv_msg->uid);
+       if (ret != MS_MEDIA_ERR_NONE) {
+               dcm_error("Failed to connect DB! err: %d", ret);
+               return ret;
+       }
+
+       if (recv_msg->msg_type == DCM_IPC_MSG_SCAN_ALL)
+       {
+               /* Use timer to scan all unscanned images */
+               ScanAllItems();
+       }
+       else if (recv_msg->msg_type == DCM_IPC_MSG_SCAN_SINGLE)
+       {
+               /* Create a scan idle if not exist, and scan single image of which file path is reveived from tcp socket */
+               if (recv_msg->msg_size > 0 && recv_msg->msg_size < DCM_IPC_MSG_MAX_SIZE) {
+                       char *file_path = NULL;
+                       file_path = strdup(recv_msg->msg);
+                       if (file_path != NULL) {
+                               ScanSingleItem((const char *) file_path);
+                               DCM_SAFE_FREE(file_path);
+                       } else {
+                               dcm_error("Failed to copy message!");
+                               ret = DCM_ERROR_OUT_OF_MEMORY;
+                       }
+               } else {
+                       dcm_error("Invalid receive message!");
+                       ret = DCM_ERROR_IPC_INVALID_MSG;
+               }
+       }
+       else if (recv_msg->msg_type == DCM_IPC_MSG_SCAN_TERMINATED)
+       {
+               /* Destroy scan idles, and quit scan thread main loop */
+               terminateScanOperations();
+       }
+       else {
+               dcm_error("Invalid message type!");
+               ret = DCM_ERROR_IPC_INVALID_MSG;
+       }
+
+       ret = dcmDbUtils->_dcm_svc_db_disconnect();
+       if (ret != DCM_SUCCESS) {
+               dcm_error("Failed to disconnect DB! err: %d", ret);
+               return FALSE;
+       }
+
+       return ret;
+}
+
+gboolean DcmScanCallback::readMsg(GIOChannel *src, GIOCondition condition, gpointer data)
+{
+       DcmScanSvc *dcmScanSvc = (DcmScanSvc *) data;
+       int sock = -1;
+       int client_sock = -1;
+       DcmIpcMsg recv_msg;
+       int err = 0;
+
+       DCM_CHECK_FALSE(data);
+
+       /* Get socket fd from IO channel */
+       sock = g_io_channel_unix_get_fd(src);
+       if (sock < 0) {
+               dcm_error("Invalid socket fd!");
+               return TRUE;
+       }
+
+       /* Accept tcp client socket */
+       err = DcmIpcUtils::acceptSocket(sock, &client_sock);
+       if (err != DCM_SUCCESS) {
+               dcm_error("Failed to accept tcp socket! err: %d", err);
+               return TRUE;
+       }
+
+       /* Receive message from tcp socket */
+       err = DcmIpcUtils::receiveSocketMsg(client_sock, &recv_msg);
+       if (err != DCM_SUCCESS) {
+               dcm_error("Failed to receive tcp msg! err: %d", err);
+               goto DCM_SVC_SCAN_READ_THREAD_RECV_SOCKET_FAILED;
+       }
+
+       /* Process received message */
+       err = dcmScanSvc->receiveMsg(&recv_msg);
+       if (err != DCM_SUCCESS) {
+               dcm_error("Error ocurred when process received message: %d", err);
+               goto DCM_SVC_SCAN_READ_THREAD_RECV_SOCKET_FAILED;
+       }
+
+DCM_SVC_SCAN_READ_THREAD_RECV_SOCKET_FAILED:
+
+       if (close(client_sock) < 0) {
+               dcm_error("close failed [%s]", strerror(errno));
+       }
+
+       return TRUE;
+}
+
+gboolean DcmScanCallback::readyScanThreadIdle(gpointer data)
+{
+       DcmMainSvc *ad = (DcmMainSvc *) data;
+       DcmIpcMsg *async_queue_msg = NULL;
+
+       dcm_debug_fenter();
+
+       DCM_CHECK_FALSE(data);
+       DCM_CHECK_FALSE(ad->scan_thread_ready);
+
+       async_queue_msg = (DcmIpcMsg*) g_malloc0(sizeof(DcmIpcMsg));
+       async_queue_msg->msg_type = DCM_IPC_MSG_SCAN_READY;
+
+       dcm_debug("scan thread ready : %p", ad->scan_thread_ready);
+       dcm_debug("async_queue_msg : %d", async_queue_msg->msg_type);
+
+       g_async_queue_push(ad->scan_thread_ready, (gpointer) async_queue_msg);
+
+       dcm_debug_fleave();
+
+       return FALSE;
+}
+
+void DcmScanCallback::freeScanItem(void *data)
+{
+       DcmScanItem *scan_item = (DcmScanItem *) data;
+
+       dcm_debug_fenter();
+
+       DCM_CHECK(scan_item);
+       DCM_CHECK(scan_item->file_path);
+       DCM_CHECK(scan_item->media_uuid);
+       DCM_CHECK(scan_item->storage_uuid);
+
+       dcm_sec_debug("Free scan item. path: [%s]", scan_item->file_path);
+
+       DCM_SAFE_FREE(scan_item->file_path);
+       DCM_SAFE_FREE(scan_item->media_uuid);
+       DCM_SAFE_FREE(scan_item->storage_uuid);
+       DCM_SAFE_FREE(scan_item);
+
+       dcm_debug_fleave();
+
+       return;
+}
+
+gboolean DcmScanMain::runScanThread(void *data)
+{
+       DcmMainSvc *dcmManSvc = (DcmMainSvc*) data;
+       DcmScanSvc dcmScanSvc;
+       int socket_fd = -1;
+       GSource *source = NULL;
+       GIOChannel *channel = NULL;
+       GMainContext *context = NULL;
+       GSource *scan_thread_ready_idle = NULL;
+       int err = 0;
+
+       DCM_CHECK_VAL(data, DCM_ERROR_INVALID_PARAMETER);
+
+       /* Init global variables */
+       err = dcmScanSvc.initialize();
+       if (err != DCM_SUCCESS) {
+               dcm_error("Failed to initialize scan thread global variable! err: %d", err);
+               goto DCM_SVC_SCAN_CREATE_SCAN_THREAD_FAILED;
+       }
+
+       /* Create TCP Socket to receive message from main thread */
+       err = DcmIpcUtils::createSocket(&socket_fd, DCM_IPC_PORT_SCAN_RECV);
+       if (err != DCM_SUCCESS) {
+               dcm_error("Failed to create socket! err: %d", err);
+               goto DCM_SVC_SCAN_CREATE_SCAN_THREAD_FAILED;
+       }
+       dcm_sec_warn("scan thread recv socket: %d", socket_fd);
+
+       /* Create a new main context for scan thread */
+       context = g_main_context_new();
+       dcmScanSvc.scan_thread_main_context = context;
+
+       /* Create a new main event loop */
+       dcmScanSvc.g_scan_thread_mainloop = g_main_loop_new(context, FALSE);
+
+       /* Create a new channel to watch TCP socket */
+       channel = g_io_channel_unix_new(socket_fd);
+       source = g_io_create_watch(channel, G_IO_IN);
+
+       /* Attach channel to main context in scan thread */
+       g_source_set_callback(source, (GSourceFunc) DcmScanCallback::readMsg, (gpointer) &dcmScanSvc, NULL);
+       g_source_attach(source, context);
+
+       /* Create a idle after scan thread is ready */
+       scan_thread_ready_idle = g_idle_source_new();
+       g_source_set_callback(scan_thread_ready_idle, DcmScanCallback::readyScanThreadIdle, (gpointer) dcmManSvc, NULL);
+       g_source_attach(scan_thread_ready_idle, context);
+
+       /* Push main context to scan thread */
+       g_main_context_push_thread_default(context);
+
+       dcm_debug("********************************************");
+       dcm_debug("*** DCM Service scan thread is running ***");
+       dcm_debug("********************************************");
+
+       /* Start to run main event loop for scan thread */
+       g_main_loop_run(dcmScanSvc.g_scan_thread_mainloop);
+
+       dcm_debug("*** DCM Service scan thread will be closed ***");
+
+       /* Destroy IO channel */
+       g_io_channel_shutdown(channel, FALSE, NULL);
+       g_io_channel_unref(channel);
+
+       /* Close the TCP socket */
+       close(socket_fd);
+
+       /* Descrease the reference count of main loop of scan thread */
+       g_main_loop_unref(dcmScanSvc.g_scan_thread_mainloop);
+       dcmScanSvc.g_scan_thread_mainloop = NULL;
+
+DCM_SVC_SCAN_CREATE_SCAN_THREAD_FAILED:
+
+       err = dcmScanSvc.finalize();
+       if (err != DCM_SUCCESS) {
+               dcm_error("Failed to de-initialize scan thread global variable! err: %d", err);
+       }
+
+       return FALSE;
+}
+
diff --git a/svc/CMakeLists.txt b/svc/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..fe59a47
--- /dev/null
@@ -0,0 +1,22 @@
+SET(fw_name "dcm-service")
+SET(DCM_SERVER "dcm-svc")
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(${DCM_SERVER} REQUIRED dlog glib-2.0 gthread-2.0 libmedia-utils libexif libtzplatform-config sqlite3)
+
+FOREACH(flag ${${DCM_SERVER}_CFLAGS})
+    SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE -Wall")
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--hash-style=both -Wl,-Bsymbolic")
+
+aux_source_directory(. sources)
+FOREACH(src ${sources})
+    GET_FILENAME_COMPONENT(src_name ${src} NAME_WE)
+    MESSAGE("${src_name}")
+    ADD_EXECUTABLE(${DCM_SERVER} ${src})
+    TARGET_LINK_LIBRARIES(${DCM_SERVER} ${fw_name} ${${DCM_SERVER}_LDFLAGS})
+ENDFOREACH()
+
+INSTALL(TARGETS ${DCM_SERVER} DESTINATION bin)
diff --git a/svc/DcmMainSvc.cpp b/svc/DcmMainSvc.cpp
new file mode 100755 (executable)
index 0000000..cc2b792
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <glib.h>
+#include <DcmMainSvc.h>
+#include <DcmIpcUtils.h>
+#include <DcmTypes.h>
+#include <DcmScanSvc.h>
+#include <DcmDebugUtils.h>
+
+
+#define DCM_SVC_MAIN_THREAD_TIMEOUT_SEC 20
+
+namespace DcmMainSvcCallBack {
+gboolean readMsg(GIOChannel *src, GIOCondition condition, gpointer data);
+gboolean quitTimerAtMainLoop(gpointer data);
+}
+
+
+DcmMainSvc *DcmMainSvc::dcmMainSvc = NULL;
+GMainLoop *g_dcm_svc_mainloop;
+static GMutex gMutexLock;
+
+static DcmMainSvc* DcmMainSvc::getInstance(void)
+{
+       if (dcmMainSvc == NULL) {
+               g_mutex_trylock(&gMutexLock);
+
+               if (dcmMainSvc == NULL) {
+                       dcmMainSvc = new DcmMainSvc();
+               }
+
+               g_mutex_unlock(&gMutexLock);
+       }
+
+       return dcmMainSvc;
+}
+
+void DcmMainSvc::dcmServiceStartjobs(void)
+{
+       /* Send ready response to thumbnail-server */
+       if (DcmIpcUtils::sendSocketMsg(DCM_IPC_MSG_SERVICE_READY, 0, NULL, DCM_IPC_PORT_THUMB_RECV) != DCM_SUCCESS) {
+               dcm_error("Failed to send ready message");
+       }
+}
+
+void DcmMainSvc::dcmServiceFinishjobs(void)
+{
+       /* TODO: free resources for dcm-service */
+}
+
+int DcmMainSvc::waitScanThreadReady()
+{
+       int ret = DCM_SUCCESS;
+       DcmIpcMsg *async_queue_msg = NULL;
+
+       /* Wait until the scan thread is ready (timeout: 5 sec) */
+       async_queue_msg = (DcmIpcMsg *)g_async_queue_timeout_pop(scan_thread_ready, 5000000);
+       if (async_queue_msg == NULL) {
+               dcm_error("Async queue timeout!");
+               return DCM_ERROR_ASYNC_QUEUE_FAILED;
+       }
+
+       /* Check if scan thread is created */
+       if (async_queue_msg->msg_type == DCM_IPC_MSG_SCAN_READY) {
+               dcm_warn("DCM scan thread is ready!");
+               g_async_queue_unref(scan_thread_ready);
+               scan_thread_ready = NULL;
+       } else {
+               dcm_error("Invalid async queue message!");
+               ret = DCM_ERROR_ASYNC_QUEUE_FAILED;
+       }
+
+       /* Free the received ipc message */
+       DCM_SAFE_FREE(async_queue_msg);
+
+       return ret;
+}
+
+int DcmMainSvc::createScanThread()
+{
+       int ret = DCM_SUCCESS;
+
+       dcm_debug_fenter();
+
+       /* Create a new async queue to wait util scan thread is created */
+       scan_thread_ready = g_async_queue_new();
+       if (scan_thread_ready == NULL) {
+               dcm_error("Failed to create async queue!");
+               return DCM_ERROR_ASYNC_QUEUE_FAILED;
+       }
+
+       /* Create the scan thread */
+       scan_thread = g_thread_new("dcm_scan_thread", (GThreadFunc) DcmScanMain::runScanThread, (gpointer) this);
+       if (scan_thread == NULL) {
+               dcm_error("Failed to create scan thread!");
+               return DCM_ERROR_CREATE_THREAD_FAILED;
+       }
+
+       ret = waitScanThreadReady();
+       /* Wait until scan thread is ready */
+       if (ret != DCM_SUCCESS) {
+               dcm_error("Failed to wait for scan thread to be ready! err: %d", ret);
+               return ret;
+       }
+
+       dcm_debug_fleave();
+
+       return DCM_SUCCESS;
+}
+
+gboolean DcmMainSvcCallBack::readMsg(GIOChannel *src, GIOCondition condition, gpointer data)
+{
+       DcmIpcMsg recv_msg;
+       int sock = -1;
+       int ret = 0;
+       int client_sock;
+
+       DcmMainSvc *dcmSvc = DcmMainSvc::getInstance();
+
+       memset((void *)&recv_msg, 0, sizeof(recv_msg));
+
+       sock = g_io_channel_unix_get_fd(src);
+       if (sock < 0) {
+               dcm_error("sock fd is invalid!");
+               return TRUE;
+       }
+
+       /* Accept tcp client socket */
+       ret = DcmIpcUtils::acceptSocket(sock, &client_sock);
+       if (ret != DCM_SUCCESS) {
+               dcm_error("Failed to accept tcp socket! err: %d", ret);
+               return TRUE;
+       }
+
+       if (DcmIpcUtils::receiveSocketMsg(client_sock, &recv_msg) < 0) {
+               dcm_error("getRecvMsg failed");
+               return TRUE;
+       }
+
+       dcm_debug("Received msg_type : [%d]", recv_msg.msg_type);
+
+       if (dcmSvc->scan_thread == NULL) {
+               dcm_debug("scan thread is not started yet!");
+               /* Create scan thread before main loop is started */
+               if (dcmSvc->createScanThread() != DCM_SUCCESS) {
+                       dcm_error("Failed to create scan thread! Exit main thread...");
+                       return TRUE;
+               }
+               
+               dcmSvc->scan_thread_working = true;
+       } else {
+               dcm_debug("scan thread is already running!");
+       }
+
+       if (recv_msg.msg_type == DCM_IPC_MSG_SCAN_COMPLETED) {
+               dcm_debug("Scan completed!");
+               dcmSvc->scan_thread_working = false;
+               dcmSvc->createQuitTimerMainLoop();
+       } else if (recv_msg.msg_type == DCM_IPC_MSG_KILL_SERVICE) {
+               dcm_warn("Quit dcm-svc main loop!");
+               dcmSvc->quitDcmSvcMainLoop();
+       } else if (recv_msg.msg_type == DCM_IPC_MSG_SCAN_ALL) {
+               ret = DcmIpcUtils::sendSocketMsg(DCM_IPC_MSG_SCAN_ALL, recv_msg.uid, NULL, DCM_IPC_PORT_SCAN_RECV);
+       } else if (recv_msg.msg_type == DCM_IPC_MSG_SCAN_SINGLE) {
+               ret = DcmIpcUtils::sendSocketMsg(DCM_IPC_MSG_SCAN_SINGLE, recv_msg.uid, recv_msg.msg, DCM_IPC_PORT_SCAN_RECV);
+       } else {
+               dcm_debug("createDcmSvcReadSocket, invalid message.");          
+       }
+
+       if (DcmIpcUtils::closeSocket(client_sock) < 0) {
+               dcm_error("close failed [%s]", strerror(errno));
+       }
+
+       return TRUE;
+}
+
+gboolean DcmMainSvcCallBack::quitTimerAtMainLoop(gpointer data)
+{
+       DcmMainSvc *dcmSvcApp = (DcmMainSvc *) data;
+
+       dcm_debug_fenter();
+
+       DCM_CHECK_FALSE(data);
+
+       if (dcmSvcApp->scan_thread_working == true) {
+               dcm_warn("Scan thread is working! DO NOT quit main thread!");
+       } else {
+               dcm_warn("Quit dcm-svc main loop!");
+               DcmIpcUtils::sendSocketMsg(DCM_IPC_MSG_KILL_SERVICE, 0, NULL, DCM_IPC_PORT_DCM_RECV);
+       }
+
+       dcm_debug_fleave();
+
+       return FALSE;
+}
+
+int DcmMainSvc::createQuitTimerMainLoop()
+{
+       GSource *quit_timer = NULL;
+
+       dcm_debug_fenter();
+
+       if (main_thread_quit_timer != NULL) {
+               dcm_debug("Delete old quit timer!");
+               g_source_destroy(main_thread_quit_timer);
+               main_thread_quit_timer = NULL;
+       }
+
+       quit_timer = g_timeout_source_new_seconds(DCM_SVC_MAIN_THREAD_TIMEOUT_SEC);
+       DCM_CHECK_VAL(quit_timer, DCM_ERROR_OUT_OF_MEMORY);
+
+       g_source_set_callback(quit_timer, DcmMainSvcCallBack::quitTimerAtMainLoop, (gpointer) this, NULL);
+       g_source_attach(quit_timer, main_loop_context);
+       main_thread_quit_timer = quit_timer;
+
+       dcm_debug_fleave();
+
+       return DCM_SUCCESS;
+}
+
+void DcmMainSvc::quitDcmSvcMainLoop()
+{
+       if (g_dcm_svc_mainloop != NULL) {
+               dcm_debug("Quit DCM thread main loop!");
+               g_main_loop_quit(g_dcm_svc_mainloop);
+       } else {
+               dcm_error("Invalid DCM thread main loop!");
+       }
+}
+
+EXPORT_API int main(int argc, char *argv[])
+{
+       DcmMainSvc *dcmSvc = DcmMainSvc::getInstance();
+       int sockfd = -1;
+
+       GSource *source = NULL;
+       GIOChannel *channel = NULL;
+       GMainContext *context = NULL;
+
+       /* Create and bind new socket to mainloop */
+       if (DcmIpcUtils::createSocket(&sockfd, DCM_IPC_PORT_DCM_RECV) != DCM_SUCCESS) {
+               dcm_error("Failed to create socket");
+               return -1;
+       }
+
+       g_dcm_svc_mainloop = g_main_loop_new(context, FALSE);
+       context = g_main_loop_get_context(g_dcm_svc_mainloop);
+
+       /* Create new channel to watch new socket for mainloop */
+       channel = g_io_channel_unix_new(sockfd);
+       source = g_io_create_watch(channel, G_IO_IN);
+
+       /* Set callback to be called when socket is readable */
+       g_source_set_callback(source, (GSourceFunc)DcmMainSvcCallBack::readMsg, NULL, NULL);
+       g_source_attach(source, context);
+
+       dcmSvc->main_loop_context = context;
+
+       dcmSvc->dcmServiceStartjobs();
+
+       dcm_debug("********************************************");
+       dcm_debug("****** DCM Service is running ******");
+       dcm_debug("********************************************");
+
+       g_main_loop_run(g_dcm_svc_mainloop);
+
+       dcmSvc->dcmServiceFinishjobs();
+
+       dcm_debug("DCM Service is shutting down...");
+       g_io_channel_shutdown(channel, FALSE, NULL);
+       g_io_channel_unref(channel);
+       g_main_loop_unref(g_dcm_svc_mainloop);
+
+       return 0;
+}