--- /dev/null
+Haejeon Kim <backto.kim at samsung dot com>
+Jiyong Min <jiyong.min at samsung dot com>
--- /dev/null
+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})
+
--- /dev/null
+ 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.
--- /dev/null
+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.
--- /dev/null
+
+# 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@
--- /dev/null
+/*
+ * 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_*/
+
--- /dev/null
+/*
+ * 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_*/
+
--- /dev/null
+/*
+ * 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_ */
+
--- /dev/null
+/*
+ * 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_*/
+
--- /dev/null
+/*
+ * 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_ */
+
--- /dev/null
+/*
+ * 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_ */
+
--- /dev/null
+/*
+ * 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_ */
+
--- /dev/null
+/*
+ * 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_ */
+
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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__ */
+
--- /dev/null
+/*
+ * 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__ */
+
--- /dev/null
+/*
+ * 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__ */
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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_*/
--- /dev/null
+/*
+ * 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_ */
+
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
--- /dev/null
+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
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+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)
--- /dev/null
+/*
+ * 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;
+}