From 622ba142f83e528e52cc0b9ab864f0afa0b6b098 Mon Sep 17 00:00:00 2001 From: Ji Yong Min Date: Fri, 2 Oct 2015 09:36:14 +0900 Subject: [PATCH] Add DCM service Change-Id: Ie5bfd1f085790523b2637d0a711391f3363a44ba --- AUTHORS | 2 + CMakeLists.txt | 94 +++ LICENSE.APLv2.0 | 201 ++++++ NOTICE | 3 + dcm-service.pc.in | 14 + include/DcmColorUtils.h | 28 + include/DcmDbUtils.h | 54 ++ include/DcmDebugUtils.h | 114 ++++ include/DcmFaceUtils.h | 30 + include/DcmIpcUtils.h | 37 ++ include/DcmMainSvc.h | 58 ++ include/DcmScanSvc.h | 28 + include/DcmTypes.h | 149 +++++ libdcm-face/dcm-face-debug.h | 104 +++ libdcm-face/dcm-face.c | 153 +++++ libdcm-face/dcm-face_mediavision.c | 211 ++++++ libdcm-face/dcm-face_priv.h | 82 +++ libdcm-face/include/dcm-face.h | 119 ++++ libdcm-face/include/dcm-face_type.h | 88 +++ libdcm-util/dcm_image_codec.cpp | 444 +++++++++++++ libdcm-util/include/dcm_image_codec.h | 52 ++ libdcm-util/include/dcm_image_debug_utils.h | 136 ++++ packaging/dcm-service.manifest | 5 + packaging/dcm-service.spec | 75 +++ src/DcmColorUtils.cpp | 65 ++ src/DcmDbUtils.cpp | 557 ++++++++++++++++ src/DcmFaceUtils.cpp | 254 +++++++ src/DcmIpcUtils.cpp | 251 +++++++ src/DcmScanSvc.cpp | 695 ++++++++++++++++++++ svc/CMakeLists.txt | 22 + svc/DcmMainSvc.cpp | 296 +++++++++ 31 files changed, 4421 insertions(+) create mode 100755 AUTHORS create mode 100755 CMakeLists.txt create mode 100755 LICENSE.APLv2.0 create mode 100755 NOTICE create mode 100755 dcm-service.pc.in create mode 100755 include/DcmColorUtils.h create mode 100755 include/DcmDbUtils.h create mode 100755 include/DcmDebugUtils.h create mode 100755 include/DcmFaceUtils.h create mode 100755 include/DcmIpcUtils.h create mode 100755 include/DcmMainSvc.h create mode 100755 include/DcmScanSvc.h create mode 100755 include/DcmTypes.h create mode 100755 libdcm-face/dcm-face-debug.h create mode 100755 libdcm-face/dcm-face.c create mode 100755 libdcm-face/dcm-face_mediavision.c create mode 100755 libdcm-face/dcm-face_priv.h create mode 100755 libdcm-face/include/dcm-face.h create mode 100755 libdcm-face/include/dcm-face_type.h create mode 100755 libdcm-util/dcm_image_codec.cpp create mode 100755 libdcm-util/include/dcm_image_codec.h create mode 100755 libdcm-util/include/dcm_image_debug_utils.h create mode 100755 packaging/dcm-service.manifest create mode 100755 packaging/dcm-service.spec create mode 100755 src/DcmColorUtils.cpp create mode 100755 src/DcmDbUtils.cpp create mode 100755 src/DcmFaceUtils.cpp create mode 100755 src/DcmIpcUtils.cpp create mode 100755 src/DcmScanSvc.cpp create mode 100755 svc/CMakeLists.txt create mode 100755 svc/DcmMainSvc.cpp diff --git a/AUTHORS b/AUTHORS new file mode 100755 index 0000000..6e3e3ee --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Haejeon Kim +Jiyong Min diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..480328c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,94 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(dcm-service C CXX) +SET(VERSION_MAJOR 1) +SET(VERSION "${VERSION_MAJOR}.0.0") + +SET(DCMSVC-LIB "dcm-service") +SET(DCMFACE-LIB "dcm-face") +SET(DCMUTIL-LIB "dcm-util") +SET(SRCS + src/DcmColorUtils.cpp + src/DcmDbUtils.cpp + src/DcmFaceUtils.cpp + src/DcmIpcUtils.cpp + src/DcmScanSvc.cpp + ) + +SET(FACE_SRCS + libdcm-face/dcm-face.c + libdcm-face/dcm-face_mediavision.c + ) + +SET(UTIL_SRCS + libdcm-util/dcm_image_codec.cpp + ) + +SET(VENDOR "samsung") +SET(PACKAGE ${PROJECT_NAME}) +SET(PKGNAME "com.${VENDOR}.${PACKAGE}") +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(BINDIR "${PREFIX}/bin") +SET(DATADIR "${PREFIX}/share") +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${prefix}/lib") +SET(INCLUDEDIR "\${prefix}/include") + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") +MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/libdcm-util/include ${CMAKE_SOURCE_DIR}/libdcm-face/include) + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED glib-2.0 gthread-2.0 dlog ecore-evas evas sqlite3 capi-media-image-util capi-media-vision libexif media-thumbnail libmedia-utils +mmutil-imgp uuid vconf libtzplatform-config) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_C_FLAGS_RELEASE "-O2 -fPIC") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -fpermissive -fdump-rtl-expand -fPIC -Wall") +SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_CXX_FLAGS_RELEASE "-O2 -fPIC") + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DTARGET") + MESSAGE("add -DTARGET") +ENDIF("${ARCH}" STREQUAL "arm") + +ADD_DEFINITIONS("-DVENDOR=\"${VENDOR}\"") +ADD_DEFINITIONS("-DPACKAGE=\"${PACKAGE}\"") +ADD_DEFINITIONS("-DPACKAGE_NAME=\"${PKGNAME}\"") +ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") +#ADD_DEFINITIONS("-D_PERFORMANCE_CHECK_") + +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--hash-style=both") +CONFIGURE_FILE(dcm-service.pc.in dcm-service.pc @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/dcm-service.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + +ADD_SUBDIRECTORY(svc) + +LINK_DIRECTORIES(${LIB_INSTALL_DIR}) + +#AUX_SOURCE_DIRECTORY(${CMAKE_SOURCE_DIR}/src SRCS) +ADD_LIBRARY(${DCMFACE-LIB} SHARED ${FACE_SRCS}) +SET_TARGET_PROPERTIES(${DCMFACE-LIB} PROPERTIES SOVERSION ${VERSION_MAJOR}) +SET_TARGET_PROPERTIES(${DCMFACE-LIB} PROPERTIES VERSION ${VERSION}) +ADD_LIBRARY(${DCMUTIL-LIB} SHARED ${UTIL_SRCS}) +SET_TARGET_PROPERTIES(${DCMUTIL-LIB} PROPERTIES SOVERSION ${VERSION_MAJOR}) +SET_TARGET_PROPERTIES(${DCMUTIL-LIB} PROPERTIES VERSION ${VERSION}) +ADD_LIBRARY(${DCMSVC-LIB} SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${DCMSVC-LIB} ${pkgs_LDFLAGS} ${DCMFACE-LIB} ${DCMUTIL-LIB}) +SET_TARGET_PROPERTIES(${DCMSVC-LIB} PROPERTIES SOVERSION ${VERSION_MAJOR}) +SET_TARGET_PROPERTIES(${DCMSVC-LIB} PROPERTIES VERSION ${VERSION}) + +INSTALL(TARGETS ${DCMFACE-LIB} LIBRARY DESTINATION ${LIB_INSTALL_DIR}) +INSTALL(TARGETS ${DCMUTIL-LIB} LIBRARY DESTINATION ${LIB_INSTALL_DIR}) +INSTALL(TARGETS ${DCMSVC-LIB} LIBRARY DESTINATION ${LIB_INSTALL_DIR}) + diff --git a/LICENSE.APLv2.0 b/LICENSE.APLv2.0 new file mode 100755 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE.APLv2.0 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE b/NOTICE new file mode 100755 index 0000000..ccdad52 --- /dev/null +++ b/NOTICE @@ -0,0 +1,3 @@ +Copyright (c) Samsung Electronics Co., Ltd. All rights reserved. +Except as noted, this software is licensed under Apache License, Version 2. +Please, see the LICENSE file for Apache License terms and conditions. diff --git a/dcm-service.pc.in b/dcm-service.pc.in new file mode 100755 index 0000000..1a55c6d --- /dev/null +++ b/dcm-service.pc.in @@ -0,0 +1,14 @@ + +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=/usr +libdir=@LIB_INSTALL_DIR@ +includedir=/usr/include/media + +Name: @PC_NAME@ +Description: @PACKAGE_DESCRIPTION@ +Version: @VERSION@ +Requires: @PC_REQUIRED@ +Libs: -L${libdir} @PC_LDFLAGS@ +Cflags: -I${includedir} @PC_CFLAGS@ diff --git a/include/DcmColorUtils.h b/include/DcmColorUtils.h new file mode 100755 index 0000000..1ea7f69 --- /dev/null +++ b/include/DcmColorUtils.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _DCM_SVC_COLOR_H_ +#define _DCM_SVC_COLOR_H_ + +#include + +namespace DcmColorUtils { + int runColorExtractProcess(DcmScanItem *scan_item, DcmImageInfo *image_info); +} + +#endif /*_DCM_SVC_COLOR_H_*/ + diff --git a/include/DcmDbUtils.h b/include/DcmDbUtils.h new file mode 100755 index 0000000..33b450d --- /dev/null +++ b/include/DcmDbUtils.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _DCM_DB_UTILS_H_ +#define _DCM_DB_UTILS_H_ + +#include +#include +#include +#include +/*#include */ +#include +#include + +typedef bool (*dcm_svc_db_face_cb)(DcmFaceItem *face_item, void *user_data); + +class DcmDbUtils { +private: + DcmDbUtils(); + static DcmDbUtils *dcmDbUtils; + static MediaDBHandle *db_handle; + +public: + uid_t dcm_uid; + static DcmDbUtils *getInstance(); + int _dcm_svc_db_connect(uid_t uid); + int _dcm_svc_db_disconnect(); + int _dcm_svc_db_get_scan_image_list_by_path(GList **image_list, bool mmc_mounted, const char *file_path); + int _dcm_svc_db_get_scan_image_list_from_db(GList **image_list, bool mmc_mounted); + int _dcm_svc_db_insert_category_to_db(void *item); + int _dcm_svc_db_generate_uuid(DcmFaceItem **face); + int _dcm_svc_db_insert_face_to_db(DcmFaceItem *face); + int _dcm_svc_db_update_color_to_db(const DcmColorItem color); + int _dcm_svc_db_insert_face_to_face_scan_list(DcmScanItem *scan_item); + int _dcm_svc_db_check_scanned_by_media_uuid(const char *media_uuid, bool *media_scanned); + int _dcm_svc_db_send_noti(DcmFaceItem *face, DcmFaceItemUpdateItem update_item, DcmFaceItemUpdateType update_type); +}; + +#endif /*_DCM_DB_UTILS_H_*/ + diff --git a/include/DcmDebugUtils.h b/include/DcmDebugUtils.h new file mode 100755 index 0000000..5d337f3 --- /dev/null +++ b/include/DcmDebugUtils.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _DCM_DEBUG_UTILS_H_ +#define _DCM_DEBUG_UTILS_H_ + +#include + +#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""); \ + } while (0) + +#define dcm_debug_fleave() do { \ + LOGD(FONT_COLOR_RESET""); \ + } while (0) +#define dcm_retm_if(expr, fmt, arg...) do { \ + if(expr) { \ + LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg); \ + return; \ + } \ + } while (0) + +#define dcm_retvm_if(expr, val, fmt, arg...) do { \ + if(expr) { \ + LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg); \ + return (val); \ + } \ + } while (0) +#else +#define dcm_debug(fmt, arg...) +#define dcm_info(fmt, arg...) +#define dcm_warn(fmt, arg...) +#define dcm_error(fmt, arg...) + +#define dcm_sec_debug(fmt, arg...) +#define dcm_sec_info(fmt, arg...) +#define dcm_sec_warn(fmt, arg...) +#define dcm_sec_error(fmt, arg...) + +#endif + +#define DCM_CHECK_VAL(expr, val) dcm_retvm_if(!(expr), val, "Invalid parameter, return ERROR code!") +#define DCM_CHECK_NULL(expr) dcm_retvm_if(!(expr), NULL, "Invalid parameter, return NULL!") +#define DCM_CHECK_FALSE(expr) dcm_retvm_if(!(expr), FALSE, "Invalid parameter, return FALSE!") +#define DCM_CHECK(expr) dcm_retm_if (!(expr), "Invalid parameter, return!") + +#define DCM_SAFE_FREE(ptr) { if(ptr) {free(ptr); ptr = NULL;} } + +#endif /* _DCM_DEBUG_UTILS_H_ */ + diff --git a/include/DcmFaceUtils.h b/include/DcmFaceUtils.h new file mode 100755 index 0000000..8e64a28 --- /dev/null +++ b/include/DcmFaceUtils.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _DCM_SVC_FACE_H_ +#define _DCM_SVC_FACE_H_ + +#include + +namespace DcmFaceUtils { + int initialize(); + int finalize(); + int runFaceRecognizeProcess(DcmScanItem *scan_item, DcmImageInfo *image_info); +} + +#endif /*_DCM_SVC_FACE_H_*/ + diff --git a/include/DcmIpcUtils.h b/include/DcmIpcUtils.h new file mode 100755 index 0000000..0b37751 --- /dev/null +++ b/include/DcmIpcUtils.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _DCM_SVC_IPC_H_ +#define _DCM_SVC_IPC_H_ + +#include + +namespace DcmIpcUtils { + int createSocket(int *socket_fd, DcmIpcPortType port); + int acceptSocket(int serv_sock, int *client_sock); + int receiveSocketMsg(int client_sock, DcmIpcMsg *recv_msg); + int sendSocketMsg(DcmIpcMsgType msg_type, uid_t uid, const char *msg, DcmIpcPortType port); + int closeSocket(int socket_fd); + int createUDPSocket(int *socket_fd); + int receiveUDPSocketMsg(int socket_fd, DcmIpcMsg *recv_msg); + int sendUDPSocketMsg(DcmIpcMsgType msg_type, const char *msg); + int closeUDPSocket(int socket_fd); + int sendFaceMsg(const char *media_uuid); +} + +#endif /* _DCM_SVC_IPC_H_ */ + diff --git a/include/DcmMainSvc.h b/include/DcmMainSvc.h new file mode 100755 index 0000000..b7ac079 --- /dev/null +++ b/include/DcmMainSvc.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _DCM_MAIN_SVC_H_ +#define _DCM_MAIN_SVC_H_ + +#include +#include +#include + +#ifndef EXPORT_API +#define EXPORT_API __attribute__ ((visibility("default"))) +#endif + +class DcmMainSvc { + static DcmMainSvc *dcmMainSvc; + +public: + /* scan thread related */ + /* GMainLoop *g_dcm_svc_mainloop; */ + + /* scan thread related */ + GThread *scan_thread; + GAsyncQueue *scan_thread_ready; + + /* main thread related */ + GMainContext *main_loop_context; + GMainContext *main_thread_context; + GIOChannel *main_thread_recv_channel; + int main_thread_recv_socket; + GSource *main_thread_quit_timer; + bool scan_thread_working; + + static DcmMainSvc *getInstance(); + void dcmServiceStartjobs(); + void dcmServiceFinishjobs(); + int waitScanThreadReady(); + int createScanThread(); + int createQuitTimerMainLoop(); + void quitDcmSvcMainLoop(); +}; + +#endif /* _DCM_MAIN_SVC_H_ */ + diff --git a/include/DcmScanSvc.h b/include/DcmScanSvc.h new file mode 100755 index 0000000..8023f09 --- /dev/null +++ b/include/DcmScanSvc.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _DCM_SCAN_SVC_H_ +#define _DCM_SCAN_SVC_H_ + +#include + +namespace DcmScanMain { + gboolean runScanThread(void *data); +} + +#endif /* _DCM_SCAN_SVC_H_ */ + diff --git a/include/DcmTypes.h b/include/DcmTypes.h new file mode 100755 index 0000000..d371c11 --- /dev/null +++ b/include/DcmTypes.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _DCM_TYPES_H_ +#define _DCM_TYPES_H_ + +#include +#include + +/* + * Definitions defined here can be used by all threads + * If a definition can only be used in a specific thread, then this definition should be defined in that thread, not here. + */ + +#define DCM_MAX_PATH_SIZE 4096 +#define DCM_IPC_MSG_MAX_SIZE 4096 +#define DCM_DB_QUERY_MAX_SIZE 4096 + +typedef enum { + DCM_SUCCESS, + DCM_ERROR_INVALID_PARAMETER, + DCM_ERROR_NETWORK, + DCM_ERROR_DB_OPERATION, + DCM_ERROR_DB_NO_RESULT, + DCM_ERROR_FILE_NOT_EXIST, + DCM_ERROR_OUT_OF_MEMORY, + DCM_ERROR_VCONF_FAIL, + DCM_ERROR_SCAN_OPERATION, + DCM_ERROR_IMAGE_ALREADY_SCANNED, + DCM_ERROR_CREATE_THREAD_FAILED, + DCM_ERROR_IMAGE_UTIL_FAILED, + DCM_ERROR_ASYNC_QUEUE_FAILED, + DCM_ERROR_IPC, + DCM_ERROR_IPC_INVALID_MSG, + DCM_ERROR_INVALID_IMAGE_SIZE, + DCM_ERROR_CODEC_DECODE_FAILED, + DCM_ERROR_CODEC_ENCODE_FAILED, + DCM_ERROR_UNSUPPORTED_IMAGE_TYPE, + DCM_ERROR_FACE_ENGINE_FAILED, + DCM_ERROR_EXIF_FAILED, + DCM_ERROR_UUID_GENERATE_FAILED, + DCM_ERROR_DUPLICATED_DATA, +} DcmErrorType; + +typedef enum { + DCM_IPC_MSG_NONE, + DCM_IPC_MSG_SERVICE_READY, + DCM_IPC_MSG_KILL_SERVICE, + DCM_IPC_MSG_SCAN_READY, + DCM_IPC_MSG_SCAN_ALL, + DCM_IPC_MSG_SCAN_SINGLE, + DCM_IPC_MSG_SCAN_COMPLETED, + DCM_IPC_MSG_SCAN_TERMINATED, + DCM_IPC_MSG_MAX, +} DcmIpcMsgType; + +typedef enum { + DCM_IPC_PORT_SCAN_RECV, + DCM_IPC_PORT_DCM_RECV, + DCM_IPC_PORT_THUMB_RECV, + DCM_IPC_PORT_MAX, +} DcmIpcPortType; + +typedef struct { + DcmIpcMsgType msg_type; + uid_t uid; + size_t msg_size; /*this is size of message below and this does not include the terminationg null byte ('\0'). */ + char msg[DCM_IPC_MSG_MAX_SIZE]; +} DcmIpcMsg; + +typedef enum { + DCM_SCAN_ITEM_TYPE_NONE, + DCM_SCAN_ITEM_TYPE_SCAN_ALL, + DCM_SCAN_ITEM_TYPE_SCAN_SINGLE, + DCM_SCAN_ITEM_TYPE_MAX, +} DcmScanItemType; + +typedef struct { + char *media_uuid; + char *file_path; + char *storage_uuid; + int image_width; + int image_height; + int image_orientation; + char *mime_type; + DcmScanItemType scan_item_type; +} DcmScanItem; + +typedef enum { + DCM_FACE_ITEM_UPDATE_FACE = 0, /**< One face item is upated */ +} DcmFaceItemUpdateItem; + +typedef enum { + DCM_FACE_ITEM_INSERT = 0, /**< Database update operation is INSERT */ + DCM_FACE_ITEM_DELETE = 1, /**< Database update operation is DELETE */ + DCM_FACE_ITEM_UPDATE = 2, /**< Database update operation is UPDATE */ + DCM_FACE_ITEM_REMOVE = 3, /**< Database update operation is REMOVE */ +} DcmFaceItemUpdateType; + +typedef struct { + char *face_uuid; + char *media_uuid; + unsigned int face_rect_x; + unsigned int face_rect_y; + unsigned int face_rect_w; + unsigned int face_rect_h; + int orientation; +} DcmFaceItem; + +typedef struct { + char *media_uuid; + char *storage_uuid; + unsigned char rgb_r; + unsigned char rgb_g; + unsigned char rgb_b; +} DcmColorItem; + +typedef enum { + DCM_SVC_I420, + DCM_SVC_RGB888, +} DcmImageDecodeType; + +typedef struct { + unsigned char *pixel; /* decoding results, must be freed after use */ + unsigned int size; + int orientation; /* orientation information extracted from exif */ + unsigned int original_width; /* original image width */ + unsigned int original_height; /* original image height */ + unsigned int buffer_width; /* scaled image width used by decoder (width/height ratio should be the same as original) */ + unsigned int buffer_height; /* scaled image height used by decoder (width/height ratio should be the same as original) */ + DcmImageDecodeType decode_type; /* decoding pre-condition */ +} DcmImageInfo; + +#endif /* _DCM_TYPES_H_ */ + diff --git a/libdcm-face/dcm-face-debug.h b/libdcm-face/dcm-face-debug.h new file mode 100755 index 0000000..5c0886c --- /dev/null +++ b/libdcm-face/dcm-face-debug.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __FACE_DEBUG_H__ +#define __FACE_DEBUG_H__ + +#include + +#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""); \ + } while (0) + +#define dcm_debug_fleave() do { \ + LOGD(FONT_COLOR_RESET""); \ + } while (0) +#define dcm_retm_if(expr, fmt, arg...) do { \ + if(expr) { \ + LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg); \ + return; \ + } \ + } while (0) + +#define dcm_retvm_if(expr, val, fmt, arg...) do { \ + if(expr) { \ + LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, ##arg); \ + return (val); \ + } \ + } while (0) +#else +#define dcm_debug(fmt, arg...) +#define dcm_info(fmt, arg...) +#define dcm_warn(fmt, arg...) +#define dcm_error(fmt, arg...) + +#define dcm_sec_debug(fmt, arg...) +#define dcm_sec_info(fmt, arg...) +#define dcm_sec_warn(fmt, arg...) +#define dcm_sec_error(fmt, arg...) +#endif + + +#endif /*__FACE_DEBUG_H__ */ diff --git a/libdcm-face/dcm-face.c b/libdcm-face/dcm-face.c new file mode 100755 index 0000000..5533958 --- /dev/null +++ b/libdcm-face/dcm-face.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include + +#include "dcm-face.h" +#include "dcm-face_priv.h" + + +#define FACE_MAGIC_VALID (0xFF993311) +#define FACE_MAGIC_INVALID (0x393A3B3C) + +EXPORT_API int dcm_face_create(__inout dcm_face_h *handle) +{ + int ret = FACE_ERROR_NONE; + + dcm_retvm_if (handle == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid handle"); + + FaceHandleT *pFaceHandle = (FaceHandleT *)calloc(1, sizeof(FaceHandleT)); + dcm_retvm_if (pFaceHandle == NULL, FACE_ERROR_OUT_OF_MEMORY, "malloc fail"); + + ret = _face_handle_create(&(pFaceHandle->fengine)); + dcm_retvm_if (ret != FACE_ERROR_NONE, ret, "fail to _face_handle_create"); + + pFaceHandle->magic = FACE_MAGIC_VALID; + + *handle = pFaceHandle; + + dcm_info("face created. handle=0x%08x", *handle); + + return ret; +} + +EXPORT_API int dcm_face_destroy(__in dcm_face_h handle) +{ + int ret = FACE_ERROR_NONE; + dcm_info("face destroy. handle=0x%08x", handle); + + dcm_retvm_if (handle == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid handle"); + + ret = _face_handle_destroy(handle->fengine); + if (ret != FACE_ERROR_NONE) { + dcm_error("fail to _face_handle_destroy"); + return ret; + } + + handle->magic = FACE_MAGIC_INVALID; + + if (handle->image_info != NULL) + DCM_SAFE_FREE(handle->image_info->data); + DCM_SAFE_FREE(handle->image_info); + DCM_SAFE_FREE(handle); + + return ret; +} + +EXPORT_API int dcm_face_get_prefered_colorspace(__in dcm_face_h handle, __out face_image_colorspace_e *colorspace) +{ + dcm_retvm_if (handle == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid handle"); + dcm_retvm_if (colorspace == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid colorspace"); + + *colorspace = FACE_IMAGE_COLORSPACE_RGB888; + + return FACE_ERROR_NONE; +} + +EXPORT_API int dcm_face_set_image_info(dcm_face_h handle, face_image_colorspace_e colorspace, unsigned char *buffer, unsigned int width, unsigned int height, unsigned int size) +{ + FaceHandleT *_handle = (FaceHandleT *)handle; + unsigned char *data = NULL; + + dcm_debug_fenter(); + + dcm_retvm_if (handle == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid handle"); + dcm_retvm_if (buffer == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid buffer"); + + switch (colorspace) { + case FACE_IMAGE_COLORSPACE_YUV420: + case FACE_IMAGE_COLORSPACE_RGB888: + data = (unsigned char *)calloc(1, size); + memcpy(data, buffer, size); + break; + default: + dcm_error("Invalid colorspace : [%d]", colorspace); + return FACE_ERROR_INVALID_PARAMTER; + } + + if (_handle->image_info != NULL) + DCM_SAFE_FREE(_handle->image_info->data); + DCM_SAFE_FREE(_handle->image_info); + + _handle->image_info = (FaceImage *)calloc(1, sizeof(FaceImage)); + + if (_handle->image_info == NULL) { + dcm_error("Out of memory"); + DCM_SAFE_FREE(data); + return FACE_ERROR_OUT_OF_MEMORY; + } + + _handle->image_info->data = data; + _handle->image_info->width = width; + _handle->image_info->height = height; + _handle->image_info->size = size; + _handle->image_info->colorspace = colorspace; + _handle->image_info->magic = FACE_IMAGE_MAGIC; + + dcm_debug_fleave(); + + return FACE_ERROR_NONE; +} + +EXPORT_API int dcm_face_get_face_info(__in dcm_face_h handle, __out face_info_s *face_info) +{ + int ret = FACE_ERROR_NONE; + + dcm_debug_fenter(); + + dcm_retvm_if (handle == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid handle"); + dcm_retvm_if (face_info == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid face_info"); + + ret = _face_detect_faces(handle, &(face_info->rects), &(face_info->count)); + if (ret != FACE_ERROR_NONE) { + dcm_error("fail to _face_detect_faces"); + } + + dcm_debug_fleave(); + + return ret; +} + +EXPORT_API int dcm_face_destroy_face_info(face_info_s *face_info) +{ + dcm_retvm_if (face_info == NULL, FACE_ERROR_INVALID_PARAMTER, "Invalid face_info"); + + DCM_SAFE_FREE(face_info->rects); + DCM_SAFE_FREE(face_info); + + return FACE_ERROR_NONE; +} diff --git a/libdcm-face/dcm-face_mediavision.c b/libdcm-face/dcm-face_mediavision.c new file mode 100755 index 0000000..dcab375 --- /dev/null +++ b/libdcm-face/dcm-face_mediavision.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "dcm-face-debug.h" +#include "dcm-face.h" +#include "dcm-face_priv.h" + +typedef struct media_vision_h { + mv_engine_config_h cfg; + mv_source_h source; +} mv_handle; + +typedef struct media_vision_result_s { + face_error_e error; + face_rect_s *face_rect; + int count; +} mv_faceInfo; + +static face_error_e __convert_to_mv_error_e(mv_error_e err) +{ + if (err != MEDIA_VISION_ERROR_NONE) + dcm_error("Error from media vision : %d", err); + + switch (err) { + case MEDIA_VISION_ERROR_NONE: + return FACE_ERROR_NONE; + + case MEDIA_VISION_ERROR_NOT_SUPPORTED: + return FACE_ERROR_INVALID_PARAMTER; + + case MEDIA_VISION_ERROR_INVALID_PARAMETER: + return FACE_ERROR_INVALID_PARAMTER; + + case MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT: + return FACE_ERROR_INVALID_PARAMTER; + + case MEDIA_VISION_ERROR_OUT_OF_MEMORY: + return FACE_ERROR_OUT_OF_MEMORY; + + default: + break; + } + + return FACE_ERROR_OPERATION_FAILED; +} + +static int __convert_to_mv_colorspace_e(face_image_colorspace_e src, mv_colorspace_e *dst) +{ + switch (src) { + case FACE_IMAGE_COLORSPACE_YUV420: + *dst = MEDIA_VISION_COLORSPACE_I420; + return FACE_ERROR_NONE; + case FACE_IMAGE_COLORSPACE_RGB888: + *dst = MEDIA_VISION_COLORSPACE_RGB888; + return FACE_ERROR_NONE; + default: + *dst = MEDIA_VISION_COLORSPACE_INVALID; + dcm_error("Unknown colorspace : %d", src); + break; + } + + return FACE_ERROR_INVALID_PARAMTER; +} + +void __face_detected_cb(mv_source_h source, mv_engine_config_h cfg, mv_rectangle_s *faces_locations, int number_of_faces, void *user_data) +{ + mv_faceInfo* _data = (mv_faceInfo*)user_data; + + dcm_error("[No-Error] number of faces: %d", number_of_faces); + + if (number_of_faces == 0) { + _data->face_rect = NULL; + _data->count = 0; + _data->error = FACE_ERROR_NONE; + return; + } + + _data->face_rect = (face_rect_s *)calloc(number_of_faces, sizeof(face_rect_s)); + if (_data->face_rect == NULL) { + dcm_error("Cannout allocate face_rect_s"); + _data->face_rect = NULL; + _data->count = 0; + _data->error = FACE_ERROR_OUT_OF_MEMORY; + return; + } + + int i = 0; + + for (i = 0; i < number_of_faces ; i++) { + _data->face_rect[i].x = faces_locations[i].point.x; + _data->face_rect[i].y = faces_locations[i].point.y; + _data->face_rect[i].w = faces_locations[i].width; + _data->face_rect[i].h = faces_locations[i].height; + _data->face_rect[i].orientation = 0; /* set to default orientation */ + } + + _data->count = number_of_faces; + _data->error = FACE_ERROR_NONE; + + return; +} + +int _face_handle_create(__inout void **handle) +{ + int err = 0; + mv_handle* _handle = (mv_handle*)calloc(1, sizeof(mv_handle)); + + dcm_debug_fenter(); + + dcm_retvm_if(handle == NULL, FACE_ERROR_OUT_OF_MEMORY, "handle create fail"); + + err = mv_create_engine_config(&(_handle->cfg)); + if (err != MEDIA_VISION_ERROR_NONE) { + dcm_error("fail to mv_create_engine_config"); + DCM_SAFE_FREE(_handle); + return __convert_to_mv_error_e(err); + } + + err = mv_create_source(&(_handle->source)); + if (err != MEDIA_VISION_ERROR_NONE) { + dcm_error("fail to mv_create_source"); + mv_destroy_engine_config(_handle->cfg); + DCM_SAFE_FREE(_handle); + return __convert_to_mv_error_e(err); + } + + *handle = _handle; + + dcm_info("dcm_face_engine was created. handle=0x%08x", *handle); + + return FACE_ERROR_NONE; +} + +int _face_handle_destroy(__in void *handle) +{ + int err = 0; + + mv_handle* _handle = (mv_handle*)handle; + + dcm_info("dcm_face_engine destroy. handle=0x%08x", handle); + + err = mv_destroy_engine_config(_handle->cfg); + if (err != MEDIA_VISION_ERROR_NONE) { + dcm_error("Fail to mv_destroy_engine_config"); + return __convert_to_mv_error_e(err); + } + + err = mv_destroy_source(_handle->source); + if (err != MEDIA_VISION_ERROR_NONE) { + dcm_error("Fail to mv_destroy_source"); + return __convert_to_mv_error_e(err); + } + + return FACE_ERROR_NONE; +} + +int _face_detect_faces(__in dcm_face_h handle, __out face_rect_s *face_rect[], __out int *count) +{ + int err = FACE_ERROR_NONE; + mv_colorspace_e colorspace = MEDIA_VISION_COLORSPACE_INVALID; + mv_faceInfo result; + + dcm_retvm_if(handle == NULL, FACE_ERROR_OUT_OF_MEMORY, "invalid handle"); + dcm_retvm_if(face_rect == NULL, FACE_ERROR_OUT_OF_MEMORY, "invalid face_rect"); + dcm_retvm_if(count == NULL, FACE_ERROR_OUT_OF_MEMORY, "invalid count"); + + mv_handle *_fengine = (mv_handle *)handle->fengine; + + __convert_to_mv_colorspace_e(handle->image_info->colorspace, &colorspace); + + dcm_debug("face_detect image: %p, size: %d, width: %d, height: %d, color: %d", handle->image_info->data, handle->image_info->size, handle->image_info->width, handle->image_info->height, colorspace); + + err = mv_source_fill_by_buffer(_fengine->source, handle->image_info->data, handle->image_info->size, handle->image_info->width, handle->image_info->height, colorspace); + if (err != MEDIA_VISION_ERROR_NONE) { + dcm_error("Fail to mv_source_fill_by_buffer"); + return __convert_to_mv_error_e(err); + } + + err = mv_face_detect(_fengine->source, _fengine->cfg, (mv_face_detected_cb)__face_detected_cb, &result); + +/* wait_for_async(); */ + + if (result.error == FACE_ERROR_NONE) { + *face_rect = result.face_rect; + *count = result.count; + } else { + *face_rect = result.face_rect; + *count = result.count; + return result.error; + } + + return FACE_ERROR_NONE; +} diff --git a/libdcm-face/dcm-face_priv.h b/libdcm-face/dcm-face_priv.h new file mode 100755 index 0000000..a1abf71 --- /dev/null +++ b/libdcm-face/dcm-face_priv.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __TIZEN_UIX_FACE_PRIV_H__ +#define __TIZEN_UIX_FACE_PRIV_H__ + +#include +#include +#include "dcm-face-debug.h" + +#undef __in +#define __in + +#undef __out +#define __out + +#undef __inout +#define __inout + +#define FACE_IMAGE_MAGIC (0x1a2b3c4d) +#define FACE_INVALID_MAGIC (0xDEADBEAF) + +#define DCM_SAFE_FREE(src) { if(src) {free(src); src = NULL;}} + +typedef struct face_image_s { + unsigned char *data; + unsigned int width; + unsigned int height; + unsigned int size; + face_image_colorspace_e colorspace; + unsigned int magic; +} FaceImage; + +typedef struct face_handle_s { + void *fengine; + unsigned int magic; + FaceImage *image_info; +} FaceHandleT; + +int _face_handle_create(void **handle); + +/** + * @brief Destroys the handle to the face engine and releases all its resources. + * @param[in] face The face engine handle + * @return 0 on success, otherwise a negative error value. + * @retval #FACE_ERROR_NONE Successful + * @retval #FACE_ERROR_INVALID_PARAMTER Invalid parameter + * @retval #FACE_ERROR_ENGINE_NOT_FOUND face engine not found + * @see _face_handle_create() + */ +int _face_handle_destroy(void *handle); + +/** + * @brief Detects faces from the image data. + * @param[in] face The facial engine handle + * @param[in] image_type The type of the image + * @param[in] image The image handle to detect faces + * @param[out] face_rect The array of the detected face positions + * @param[out] count The number of the detected face positions + * @return 0 on success, otherwise a negative error value. + * @retval #FACE_ERROR_NONE Successful + * @retval #FACE_ERROR_INVALID_PARAMTER Invalid parameter + * @retval #FACE_ERROR_OUT_OF_MEMORY Out of memory + * @retval #FACE_ERROR_ENGINE_NOT_FOUND Facial engine not found + */ +int _face_detect_faces(dcm_face_h handle, face_rect_s *face_rect[], int *count); + + +#endif /* __TIZEN_UIX_FACE_PRIV_H__ */ + diff --git a/libdcm-face/include/dcm-face.h b/libdcm-face/include/dcm-face.h new file mode 100755 index 0000000..1637a72 --- /dev/null +++ b/libdcm-face/include/dcm-face.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __TIZEN_DCM_FACE_H__ +#define __TIZEN_DCM_FACE_H__ + +#include +#include "dcm-face_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup DCM_FACE_MODULE + * @{ + */ + +/** + * @brief Creates a handle to the facial engine. + * @remarks The @a face must be released with face_destroy() by you. + * @param[out] handle A face engine handle to be newly created on success + * @return 0 on success, otherwise a negative error value. + * @retval #FACE_ERROR_NONE Successful + * @retval #FACE_ERROR_INVALID_PARAMTER Invalid parameter + * @retval #FACE_ERROR_OUT_OF_MEMORY Out of memory + * @retval #FACE_ERROR_ENGINE_NOT_FOUND Facial engine not found + * @see dcm_face_destroy() + */ +int dcm_face_create(dcm_face_h *handle); + +/** + * @brief Destroys the handle to the facial engine and releases all its resources. + * @param[in] handle The face engine handle + * @return 0 on success, otherwise a negative error value. + * @retval #FACE_ERROR_NONE Successful + * @retval #FACE_ERROR_INVALID_PARAMTER Invalid parameter + * @retval #FACE_ERROR_ENGINE_NOT_FOUND Facial engine not found + * @see dcm_face_create() + */ +int dcm_face_destroy(dcm_face_h handle); + +/** + * @brief Gets the preferred color space of the facial engine. + * @remarks The preferred color space depends on the facial engine. + * @param[in] handle The facial engine handle + * @param[out] colorspace The preferred color space + * @return 0 on success, otherwise a negative error value. + * @retval #FACE_ERROR_NONE Successful + * @retval #FACE_ERROR_INVALID_PARAMTER Invalid parameter + * @see dcm_face_create() + */ +int dcm_face_get_prefered_colorspace(dcm_face_h handle, face_image_colorspace_e *colorspace); + +/** + * @brief Creates a face image handle containing the input image data + * @remarks The @a face_image must be released with face_image_destroy() by you. + * @remarks The @a buffer must not be released until @a face_image is released with face_image_destroy() + * @param[in] handle The facial engine handle + * @param[in] colorspace The colorspace of the image + * @param[in] buffer The buffer containing the image + * @param[in] width The width of the image + * @param[in] height The height of the image + * @param[in] size The size of the buffer + * @return 0 on success, otherwise a negative error value. + * @retval #FACE_ERROR_NONE Successful + * @retval #FACE_ERROR_INVALID_PARAMTER Invalid parameter + * @retval #FACE_ERROR_OUT_OF_MEMORY Out of memory + * @see dcm_face_create() + */ +int dcm_face_set_image_info(dcm_face_h handle, face_image_colorspace_e colorspace, unsigned char *buffer, unsigned int width, unsigned int height, unsigned int size); + +/** + * @brief Gets the face information of detected faces. + * @remarks The detected faces depends on the facial engine. + * @param[in] handle The facial engine handle + * @param[out] face info The face information with rect, count and so on + * @return 0 on success, otherwise a negative error value. + * @retval #FACE_ERROR_NONE Successful + * @retval #FACE_ERROR_INVALID_PARAMTER Invalid parameter + * @see dcm_face_destroy_face_info() + */ +int dcm_face_get_face_info(dcm_face_h handle, face_info_s *face_info); + +/** + * @brief Release the face information memory. + * @param[in] face_info The face information memory + * @return 0 on success, otherwise a negative error value. + * @retval #FACE_ERROR_NONE Successful + * @retval #FACE_ERROR_INVALID_PARAMTER Invalid parameter + * @see dcm_face_get_face_info() + */ +int dcm_face_destroy_face_info(face_info_s *face_info); + +/** + * @} + */ + + + +#ifdef __cplusplus +} +#endif + + +#endif /* __TIZEN_DCM_FACE_H__ */ + diff --git a/libdcm-face/include/dcm-face_type.h b/libdcm-face/include/dcm-face_type.h new file mode 100755 index 0000000..4884cd4 --- /dev/null +++ b/libdcm-face/include/dcm-face_type.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __TIZEN_DCM_FACE_TYPE_H__ +#define __TIZEN_DCM_FACE_TYPE_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup + * @{ + */ + +/** + * @brief Facel engine handle. + */ +typedef struct face_handle_s *dcm_face_h; + +/** + * @brief Enumerations of error codes for the Facial Engine API. + */ +typedef enum { + FACE_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */ + FACE_ERROR_INVALID_PARAMTER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ + FACE_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */ + FACE_ERROR_ENGINE_NOT_FOUND = TIZEN_ERROR_UIX_CLASS | 0x41, /**< Facial engine not found */ + FACE_ERROR_OPERATION_FAILED = TIZEN_ERROR_UIX_CLASS | 0x42, /**< Operation failed */ +} face_error_e; + +/** + * @brief Enumerations of color spaces + * @see face_image_create() + * @see face_attr_get_prefered_colorspace() + * + */ +typedef enum { + FACE_IMAGE_COLORSPACE_YUV420, /**< Y:U:V = 4:2:0 */ + FACE_IMAGE_COLORSPACE_RGB888, /**< RGB565, high-byte is Blue */ +} face_image_colorspace_e; + +/** + * @brief Represents a rectangular region in a coordinate space + */ +typedef struct { + int x; /**< The x coordinate of the top-left corner of the rectangle */ + int y; /**< The y coordinate of the top-left corner of the rectangle */ + int w; /**< The width of the rectangle */ + int h; /**< The height of the rectangle */ + int orientation; /** face orientation */ +} face_rect_s; + + +typedef struct { + face_rect_s *rects; + int count; +} face_info_s; + + + +/** + * @} + */ + + + +#ifdef __cplusplus +} +#endif + + +#endif /* __TIZEN_DCM_FACE_TYPE_H__ */ + diff --git a/libdcm-util/dcm_image_codec.cpp b/libdcm-util/dcm_image_codec.cpp new file mode 100755 index 0000000..8309dd6 --- /dev/null +++ b/libdcm-util/dcm_image_codec.cpp @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +static void _dcm_codec_calc_image_size(int ori_width, int ori_height, int tar_width, int tar_height, int *buf_width, int *buf_height) +{ + + *buf_width = 0; + *buf_height = 0; + + if (tar_width <= 0 && tar_height <= 0) { + dcm_warn("Invalid input decode size! Set decode size to original size"); + *buf_width = 0; + *buf_height = 0; + return; + } + + if (ori_width <= tar_width && ori_height <= tar_height) { + dcm_debug("Original image size is already smaller. Set docode size to original size"); + /* Make sure that decode buffer size can be divided by 8 (required by YUV420 decoding) */ + *buf_width = ori_width - (ori_width) % 8; + *buf_height = ori_height - (ori_height) % 8; + return; + } + + if (ori_width > ori_height) { + /* Scale image size based on input width */ + *buf_width = tar_width; + *buf_height = (int) (ori_height * (((double) tar_width) / ((double) ori_width))); + } else { + /* Scale image size based on input height */ + *buf_height = tar_height; + *buf_width = (int) (ori_width * (((double) tar_height) / ((double) ori_height))); + } + + /* Make sure that decode buffer size can be divided by 8 (required by YUV420 decoding) */ + *buf_width = *buf_width - (*buf_width) % 8; + *buf_height = *buf_height - (*buf_height) % 8; + + return; +} +#endif + +int __dcm_decode_image_with_evas(const char *origin_path, + int dest_width, int dest_height, + dcm_image_info *image_info) +{ + dcm_debug_fenter(); + + Ecore_Evas *resize_img_ee; + + resize_img_ee = ecore_evas_buffer_new(dest_width, dest_height); + if (!resize_img_ee) { + dcm_error("ecore_evas_buffer_new failed"); + return DCM_ERROR_CODEC_DECODE_FAILED; + } + + Evas *resize_img_e = ecore_evas_get(resize_img_ee); + if (!resize_img_e) { + dcm_error("ecore_evas_get failed"); + ecore_evas_free(resize_img_ee); + return DCM_ERROR_CODEC_DECODE_FAILED; + } + + Evas_Object *source_img = evas_object_image_add(resize_img_e); + if (!source_img) { + dcm_error("evas_object_image_add failed"); + ecore_evas_free(resize_img_ee); + return DCM_ERROR_CODEC_DECODE_FAILED; + } + + evas_object_image_file_set(source_img, origin_path, NULL); + + /* Get w/h of original image */ + int width = 0; + int height = 0; + + evas_object_image_size_get(source_img, &width, &height); + image_info->origin_width = width; + image_info->origin_height = height; + + evas_object_image_load_orientation_set(source_img, 1); + + ecore_evas_resize(resize_img_ee, dest_width, dest_height); + + evas_object_image_load_size_set(source_img, dest_width, dest_height); + evas_object_image_fill_set(source_img, 0, 0, dest_width, dest_height); + evas_object_image_filled_set(source_img, 1); + + evas_object_resize(source_img, dest_width, dest_height); + evas_object_show(source_img); + + /* Set alpha from original */ + image_info->alpha = evas_object_image_alpha_get(source_img); + if (image_info->alpha) ecore_evas_alpha_set(resize_img_ee, EINA_TRUE); + + /* Create target buffer and copy origin resized img to it */ + Ecore_Evas *target_ee = ecore_evas_buffer_new(dest_width, dest_height); + if (!target_ee) { + dcm_error("ecore_evas_buffer_new failed"); + ecore_evas_free(resize_img_ee); + return DCM_ERROR_CODEC_DECODE_FAILED; + } + + Evas *target_evas = ecore_evas_get(target_ee); + if (!target_evas) { + dcm_error("ecore_evas_get failed"); + ecore_evas_free(resize_img_ee); + ecore_evas_free(target_ee); + return DCM_ERROR_CODEC_DECODE_FAILED; + } + + Evas_Object *ret_image = evas_object_image_add(target_evas); + evas_object_image_size_set(ret_image, dest_width, dest_height); + evas_object_image_fill_set(ret_image, 0, 0, dest_width, dest_height); + evas_object_image_filled_set(ret_image, EINA_TRUE); + + evas_object_image_data_set(ret_image, (int *)ecore_evas_buffer_pixels_get(resize_img_ee)); + evas_object_image_data_update_add(ret_image, 0, 0, dest_width, dest_height); + + unsigned int buf_size = 0; + int stride = evas_object_image_stride_get(ret_image); + buf_size = (sizeof(unsigned char) * stride * dest_height); + dcm_debug("buf_size: %d", buf_size); + + image_info->size = buf_size; + image_info->width = dest_width; + image_info->height = dest_height; + image_info->data = (unsigned char *)malloc(buf_size); + if (image_info->data == NULL) { + dcm_error("Failed to allocate memory" ); + ecore_evas_free(resize_img_ee); + ecore_evas_free(target_ee); + + return DCM_ERROR_OUT_OF_MEMORY; + } + + void *image_data = evas_object_image_data_get(ret_image, 1); + if (image_data != NULL) { + memcpy(image_info->data, image_data, buf_size); + } else { + dcm_error("image_data is NULL. evas_object_image_data_get failed"); + } + + ecore_evas_free(target_ee); + ecore_evas_free(resize_img_ee); + + dcm_debug_fleave(); + + return DCM_SUCCESS; +} + +static int __dcm_codec_get_image_orientation(const char *path, int *orientation) +{ + int ret = DCM_SUCCESS; + ExifData *ed = NULL; + ExifEntry *entry = NULL; + int status = 0; + ExifByteOrder byte_order; + + DCM_CHECK_VAL(path, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(orientation, DCM_ERROR_INVALID_PARAMETER); + + ed = exif_data_new_from_file(path); + if (ed == NULL) { + dcm_error("Failed to create new exif data!"); + ret = DCM_ERROR_EXIF_FAILED; + goto DCM_SVC_DB_GET_FACE_ORIENTATION_FAILED; + } + + entry = exif_data_get_entry(ed, EXIF_TAG_ORIENTATION); + if (entry == NULL) { + dcm_warn("Exif entry not exist!"); + *orientation = 0; + ret = DCM_SUCCESS; + goto DCM_SVC_DB_GET_FACE_ORIENTATION_FAILED; + } + + byte_order = exif_data_get_byte_order(ed); + status = exif_get_short(entry->data, byte_order); + switch (status) { + case 1: + case 2: + *orientation = 0; + break; + case 3: + case 4: + *orientation = 180; + break; + case 5: + case 8: + *orientation = 270; + break; + case 6: + case 7: + *orientation = 90; + break; + default: + *orientation = 0; + break; + } + + dcm_debug("orientation: %d", *orientation); + +DCM_SVC_DB_GET_FACE_ORIENTATION_FAILED: + + if (ed != NULL) { + exif_data_unref(ed); + ed = NULL; + } + + return ret; +} + +static int __dcm_codec_rotate_by_orientation(const unsigned char *source, unsigned char **image_buffer, unsigned int *buff_width, unsigned int *buff_height, dcm_image_codec_type_e decode_type, int *orientation) +{ + int ret = IMAGE_UTIL_ERROR_NONE; + image_util_colorspace_e colorspace = IMAGE_UTIL_COLORSPACE_I420; + image_util_rotation_e rotate = IMAGE_UTIL_ROTATION_NONE; + unsigned char *rotated_buffer = NULL; + unsigned int rotated_buffer_size = 0; + int rotated_width = 0, rotated_height = 0; + + DCM_CHECK_VAL(source, DCM_ERROR_INVALID_PARAMETER); + + if (decode_type == DCM_IMAGE_CODEC_I420) { + colorspace = IMAGE_UTIL_COLORSPACE_I420; + } else if (decode_type == DCM_IMAGE_CODEC_RGB888) { + colorspace = IMAGE_UTIL_COLORSPACE_RGB888; + } + + /* Get rotate angle enum */ + if (*orientation == 180) { // 3-180 + rotate = IMAGE_UTIL_ROTATION_180; + } else if (*orientation == 90) { // 6-90 + rotate = IMAGE_UTIL_ROTATION_90; + } else if (*orientation == 270) { // 8-270 + rotate = IMAGE_UTIL_ROTATION_270; + } else { + rotate = IMAGE_UTIL_ROTATION_NONE; + } + + if (rotate == IMAGE_UTIL_ROTATION_90 || rotate == IMAGE_UTIL_ROTATION_270) { + rotated_width = *buff_height; + rotated_height = *buff_width; + } else { + rotated_width = *buff_width; + rotated_height = *buff_height; + } + + /* Calculate the rotated buffer size */ + ret = image_util_calculate_buffer_size(rotated_width, rotated_height, colorspace, &rotated_buffer_size); + if (ret != IMAGE_UTIL_ERROR_NONE) { + dcm_error("Failed to calculate buffer size! err: %d", ret); + return DCM_ERROR_IMAGE_UTIL_FAILED; + } + + /* Allocate rotated buffer */ + if (rotated_buffer_size <= 0) { + dcm_error("Invalid rotated buffer size!"); + return DCM_ERROR_IMAGE_UTIL_FAILED; + } + + dcm_debug("rotate buffer size: %u", rotated_buffer_size); + rotated_buffer = (unsigned char *) g_malloc0(rotated_buffer_size); + if (rotated_buffer == NULL) { + dcm_error("rotated_buffer is NULL!"); + return DCM_ERROR_IMAGE_UTIL_FAILED; + } + + try { + /* Rotate input bitmap */ + ret = image_util_rotate(rotated_buffer, &rotated_width, &rotated_height, rotate, source, + *buff_width, *buff_height, colorspace); + + if (ret != IMAGE_UTIL_ERROR_NONE || rotated_buffer == NULL) { + dcm_error("Failed to rotate image buffer! err: %d", ret); + throw DCM_ERROR_IMAGE_UTIL_FAILED; + } + + /* Decoded buffer size is set to rotated buffer size to match buffer */ + dcm_debug("After rotation: [width: %d] [height: %d]", rotated_width, rotated_height); + *buff_width = rotated_width; + *buff_height = rotated_height; + + /* Allocated pixel should be freed when scanning is finished for this rotated bitmap */ + *image_buffer = rotated_buffer; + dcm_warn("rotated decode buffer: %p", *image_buffer); + + } catch (DcmErrorType &e) { + DCM_SAFE_FREE(rotated_buffer); + dcm_error("image util rotate error!"); + return e; + } + + return DCM_SUCCESS; +} + +static int __dcm_decode_image_with_size_orient(const char *file_path, unsigned int target_width, unsigned int target_height, + dcm_image_codec_type_e decode_type, unsigned char **image_buffer, unsigned int *buff_width, unsigned int *buff_height, int *orientation, unsigned int *size) +{ + int ret = IMAGE_UTIL_ERROR_NONE; + image_util_colorspace_e colorspace = IMAGE_UTIL_COLORSPACE_I420; + unsigned char *decode_buffer = NULL; + + dcm_debug_fenter(); + + DCM_CHECK_VAL(file_path, DCM_ERROR_INVALID_PARAMETER); + + if (decode_type == DCM_IMAGE_CODEC_I420) { + colorspace = IMAGE_UTIL_COLORSPACE_I420; + } else if (decode_type == DCM_IMAGE_CODEC_RGB888) { + colorspace = IMAGE_UTIL_COLORSPACE_RGB888; + } + + /* Extract orientation from exif */ + ret = __dcm_codec_get_image_orientation(file_path, orientation); + if (ret != DCM_SUCCESS) { + dcm_error("Failed to extract orientation! err: %d", ret); + dcm_warn("Set orientation to default!"); + *orientation = 0; + } + + ret = image_util_decode_jpeg(file_path, colorspace, &decode_buffer, (int *)buff_width, (int *)buff_height, size); + dcm_debug("file:%s buffer:%p, size:%u, buff_width:%d, buff_height:%d", file_path, image_buffer, *size, *buff_width, *buff_height); + if (ret != IMAGE_UTIL_ERROR_NONE) { + dcm_error("Error image_util_decode_jpeg ret : %d", ret); + return DCM_ERROR_IMAGE_UTIL_FAILED; + } + + /* Rotate the decoded buffer according to orientation */ + if (*orientation == 0) { + *image_buffer = decode_buffer; + } else { + ret = __dcm_codec_rotate_by_orientation(decode_buffer, image_buffer, buff_width, buff_height, decode_type, orientation); + if (ret != DCM_SUCCESS) { + dcm_error("Failed to rotate image buffer! err: %d", ret); + return DCM_ERROR_CODEC_DECODE_FAILED; + } + } + + dcm_debug_fleave(); + + return DCM_SUCCESS; +} + +EXPORT_API +int dcm_decode_image_with_size_orient(const char *file_path, unsigned int target_width, unsigned int target_height, + dcm_image_codec_type_e decode_type, unsigned char **image_buffer, unsigned int *buff_width, unsigned int *buff_height, int *orientation, unsigned int *size) +{ + int ret = DCM_SUCCESS; + + ret = __dcm_decode_image_with_size_orient(file_path, target_width, target_height, decode_type, image_buffer, buff_width, buff_height, orientation, size); + if (ret != DCM_SUCCESS) { + dcm_error("Error _dcm_decode_image_with_size ret : %d", ret); + } + + return ret; +} + +EXPORT_API +int dcm_decode_image_with_evas(const char *file_path, unsigned int target_width, unsigned int target_height, + dcm_image_codec_type_e decode_type, unsigned char **image_buffer, unsigned int *buff_width, unsigned int *buff_height, int *orientation, unsigned int *size) +{ + int ret = DCM_SUCCESS; + dcm_image_info image_info = {0, }; + image_util_colorspace_e colorspace = IMAGE_UTIL_COLORSPACE_I420; + mm_util_img_format mm_colorspace = MM_UTIL_IMG_FMT_I420; + + DCM_CHECK_VAL(file_path, DCM_ERROR_INVALID_PARAMETER); + + memset(&image_info, 0, sizeof(image_info)); + + if (decode_type == DCM_IMAGE_CODEC_I420) { + colorspace = IMAGE_UTIL_COLORSPACE_I420; + mm_colorspace = MM_UTIL_IMG_FMT_I420; + } else if (decode_type == DCM_IMAGE_CODEC_RGB888) { + colorspace = IMAGE_UTIL_COLORSPACE_RGB888; + mm_colorspace = MM_UTIL_IMG_FMT_RGB888; + } + ret = __dcm_decode_image_with_evas(file_path, target_width, target_height, &image_info); + if (ret != DCM_SUCCESS) { + dcm_error("Error __dcm_decode_image_with_evas ret : %d", ret); + *buff_width = 0; + *buff_height = 0; + *orientation = 0; + *size = 0; + *image_buffer = NULL; + return DCM_ERROR_CODEC_DECODE_FAILED; + } + + *buff_width = image_info.width; + *buff_height = image_info.height; + *orientation = 0; + image_util_calculate_buffer_size(*buff_width, *buff_height, colorspace, size); + *image_buffer = (unsigned char *)malloc(sizeof(unsigned char) * (*size)); + if (*image_buffer == NULL) { + dcm_error("Error buffer allocation"); + DCM_SAFE_FREE(image_info.data); + return DCM_ERROR_CODEC_DECODE_FAILED; + } + int err = 0; + err = mm_util_convert_colorspace(image_info.data, + image_info.width, + image_info.height, + MM_UTIL_IMG_FMT_BGRA8888, + *image_buffer, + mm_colorspace); + + if (err < 0) { + dcm_error("Failed to change from argb888 to %d. (%d)", mm_colorspace, err); + DCM_SAFE_FREE(*image_buffer); + *image_buffer = NULL; + ret = DCM_ERROR_CODEC_DECODE_FAILED; + } + DCM_SAFE_FREE(image_info.data); + + return ret; +} diff --git a/libdcm-util/include/dcm_image_codec.h b/libdcm-util/include/dcm_image_codec.h new file mode 100755 index 0000000..37a80c3 --- /dev/null +++ b/libdcm-util/include/dcm_image_codec.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _DCM_IMAGE_CODEC_H_ +#define _DCM_IMAGE_CODEC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + DCM_IMAGE_CODEC_I420, + DCM_IMAGE_CODEC_RGB888, +} dcm_image_codec_type_e; + +typedef struct { + int size; + int width; + int height; + int origin_width; + int origin_height; + int alpha; + unsigned char *data; +} dcm_image_info; + + +/* Decoding image with input width and height, if possible (width/height ratio is kept the same as original), and rotate the buffer according to orientation */ +int dcm_decode_image_with_size_orient(const char *file_path, unsigned int target_width, unsigned int target_height, + dcm_image_codec_type_e decode_type, unsigned char **image_buffer, unsigned int *buff_width, unsigned int *buff_height, int *orientation, unsigned int *size); + +int dcm_decode_image_with_evas(const char *file_path, unsigned int target_width, unsigned int target_height, + dcm_image_codec_type_e decode_type, unsigned char **image_buffer, unsigned int *buff_width, unsigned int *buff_height, int *orientation, unsigned int *size); + +#ifdef __cplusplus +} +#endif + +#endif /*_DCM_IMAGE_CODEC_H_*/ diff --git a/libdcm-util/include/dcm_image_debug_utils.h b/libdcm-util/include/dcm_image_debug_utils.h new file mode 100755 index 0000000..f833d7a --- /dev/null +++ b/libdcm-util/include/dcm_image_debug_utils.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _DCM_DEBUG_UTILS_H_ +#define _DCM_DEBUG_UTILS_H_ + +#include +#include + +#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""); \ + } while (0) + +#define dcm_debug_fleave() do { \ + LOGD(FONT_COLOR_RESET""); \ + } while (0) +#else +#define dcm_debug(fmt, arg...) +#define dcm_info(fmt, arg...) +#define dcm_warn(fmt, arg...) +#define dcm_error(fmt, arg...) + +#define dcm_sec_debug(fmt, arg...) +#define dcm_sec_info(fmt, arg...) +#define dcm_sec_warn(fmt, arg...) +#define dcm_sec_error(fmt, arg...) + +#endif +#define dcm_retm_if(expr, fmt, arg...) do { \ + if(expr) { \ + dcm_error(fmt, ##arg); \ + dcm_error("(%s) -> %s() return", #expr, __FUNCTION__); \ + return; \ + } \ + } while (0) + +#define dcm_retvm_if(expr, val, fmt, arg...) do { \ + if(expr) { \ + dcm_error(fmt, ##arg); \ + dcm_error("(%s) -> %s() return", #expr, __FUNCTION__); \ + return (val); \ + } \ + } while (0) + +#define ERR_BUF_LENGHT 256 +#define dcm_stderror(fmt) do { \ + char dcm_stderror_buf[ERR_BUF_LENGHT] = {0, }; \ + strerror_r(errno, dcm_stderror_buf, ERR_BUF_LENGHT); \ + dcm_error(fmt" : standard error= [%s]", dcm_stderror_buf); \ + } while (0) + +#define DCM_CHECK_VAL(expr, val) dcm_retvm_if(!(expr), val , "Invalid parameter, return ERROR code!") +#define DCM_CHECK_NULL(expr) dcm_retvm_if(!(expr), NULL, "Invalid parameter, return NULL!") +#define DCM_CHECK_FALSE(expr) dcm_retvm_if(!(expr), FALSE, "Invalid parameter, return FALSE!") +#define DCM_CHECK(expr) dcm_retm_if (!(expr), "Invalid parameter, return!") + +#define DCM_SAFE_FREE(ptr) { if(ptr) {free(ptr); ptr = NULL;} } + +#endif /* _DCM_DEBUG_UTILS_H_ */ + diff --git a/packaging/dcm-service.manifest b/packaging/dcm-service.manifest new file mode 100755 index 0000000..97e8c31 --- /dev/null +++ b/packaging/dcm-service.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/dcm-service.spec b/packaging/dcm-service.spec new file mode 100755 index 0000000..c413547 --- /dev/null +++ b/packaging/dcm-service.spec @@ -0,0 +1,75 @@ +Name: dcm-service +Summary: Multimedia DCM(Digital Contents Management) Service +Version: 0.0.1 +Release: 0 +Group: Multimedia/Service +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz +Source1001: %{name}.manifest + +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig + +BuildRequires: cmake +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(gthread-2.0) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(ecore-evas) +BuildRequires: pkgconfig(evas) +BuildRequires: pkgconfig(libexif) +BuildRequires: pkgconfig(sqlite3) +BuildRequires: pkgconfig(capi-media-image-util) +BuildRequires: pkgconfig(capi-media-vision) +BuildRequires: pkgconfig(media-thumbnail) +BuildRequires: pkgconfig(libmedia-utils) +BuildRequires: pkgconfig(libtzplatform-config) +BuildRequires: pkgconfig(mmutil-imgp) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(uuid) + +%description +Description: Digital Contents Management(DCM) service process + +%package devel +Summary: Digital Contents Management service for multimedia applications. (development) +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +DCM service for multimedia applications. (development files) + +%prep +%setup -q +cp %{SOURCE1001} . + +%build +%cmake . +make %{?jobs:-j%jobs} +#export CFLAGS+=" -Wextra -Wno-array-bounds" +#export CFLAGS+=" -Wno-ignored-qualifiers -Wno-unused-parameter -Wshadow" +#export CFLAGS+=" -Wwrite-strings -Wswitch-default" + +%install +rm -rf %{buildroot} +%make_install + +#License +mkdir -p %{buildroot}/%{_datadir}/license +cp LICENSE.APLv2.0 %{buildroot}/%{_datadir}/license/%{name} + +%post -p /sbin/ldconfig +%postun -p /sbin/ldconfig + +%files +%manifest %{name}.manifest +%defattr(-,root,root,-) +%{_libdir}/*.so* +%{_bindir}/dcm-svc +#License +%{_datadir}/license/%{name} + +%files devel +%manifest %{name}.manifest +%{_libdir}/*.so +%{_libdir}/pkgconfig/%{name}.pc +#%{_includedir}/media/*.h diff --git a/src/DcmColorUtils.cpp b/src/DcmColorUtils.cpp new file mode 100755 index 0000000..f0c9aec --- /dev/null +++ b/src/DcmColorUtils.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int DcmColorUtils::runColorExtractProcess(DcmScanItem *scan_item, DcmImageInfo *image_info) +{ + DCM_CHECK_VAL(scan_item, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(image_info, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(image_info->pixel, DCM_ERROR_INVALID_PARAMETER); + + dcm_debug_fenter(); +#if 0 + DcmDbUtils *dcmDbUtils = DcmDbUtils::getInstance(); + int ret = IMAGE_UTIL_ERROR_NONE; + DcmColorItem colorItem = {0,}; + memset(&colorItem, 0, sizeof(DcmColorItem)); + + // Extracting color supports only RGB888 format + ret = image_util_extract_color_from_memory(image_info->pixel, image_info->buffer_width, image_info->buffer_height, &(colorItem.rgb_r), &(colorItem.rgb_g), &(colorItem.rgb_b)); + if (ret != IMAGE_UTIL_ERROR_NONE) { + dcm_error("image_util_extract_color_from_memory err= %d", ret); + return DCM_ERROR_IMAGE_UTIL_FAILED; + } + + dcm_debug("image_util_extract_color_from_memory result r:%02x, g:%02x, b:%02x", colorItem.rgb_r, colorItem.rgb_g, colorItem.rgb_b); + + colorItem.media_uuid = strdup(scan_item->media_uuid); + colorItem.storage_uuid = strdup(scan_item->storage_uuid); + ret = dcmDbUtils->_dcm_svc_db_update_color_to_db(colorItem); + if (ret != DCM_SUCCESS) { + dcm_error("Failed to update color item into db! err: %d", ret); + return DCM_ERROR_DB_OPERATION; + } +#endif + dcm_debug_fleave(); + + return DCM_SUCCESS; +} + diff --git a/src/DcmDbUtils.cpp b/src/DcmDbUtils.cpp new file mode 100755 index 0000000..4489fc5 --- /dev/null +++ b/src/DcmDbUtils.cpp @@ -0,0 +1,557 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DCM_STRING_VALID(str) ((str != NULL && strlen(str) > 0) ? TRUE : FALSE) +#define DCM_SQLITE3_FINALIZE(x) {if (x != NULL) {sqlite3_finalize(x);x=NULL;}} +#define DCM_SQLITE3_FREE(x) {if (x != NULL) {sqlite3_free(x);x=NULL;}} + +#define DB_TABLE_FACE "face" +#define DB_TABLE_FACE_SCAN_LIST "face_scan_list" +#define DB_TABLE_MEDIA "media" +#define FACE_ITEM "face_uuid, media_uuid, face_rect_x , face_rect_y, face_rect_w , face_rect_h, orientation" + +#define SELECT_PATH_FROM_UNEXTRACTED_DCM_MEDIA "SELECT media_uuid, path, storage_uuid, width, height, orientation, mime_type FROM media WHERE media_uuid NOT IN (SELECT DISTINCT media_uuid FROM face_scan_list) AND validity=1 AND media_type=0 AND (storage_type = 0 OR storage_type = 1);" +#define SELECT_PATH_FROM_UNEXTRACTED_DCM_INTERNAL_MEDIA "SELECT media_uuid, path, storage_uuid, width, height, orientation, mime_type FROM media WHERE media_uuid NOT IN (SELECT DISTINCT media_uuid FROM face_scan_list) AND validity=1 AND media_type=0 AND storage_type=0;" + +#define SELECT_MEDIA_INFO_BY_FILE_PATH_FROM_DB "SELECT media_uuid, storage_uuid, width, height, orientation, mime_type FROM media WHERE path = '%q';" +#define INSERT_FACE_ITEM_TO_DB "INSERT INTO "DB_TABLE_FACE" ("FACE_ITEM") VALUES ('%q', '%q', %d, %d, %d, %d, %d);" +#define UPDATE_COLOR_ITEM_TO_DB "UPDATE "DB_TABLE_MEDIA" SET color_r=%d, color_g=%d, color_b=%d WHERE media_uuid='%q' AND storage_uuid='%q';" + +static GMutex gMutexLock; + +namespace DcmDbUtilsInternal { +bool __dcm_svc_db_check_duplicated(MediaDBHandle *db_handle, DcmFaceItem *data); +bool __dcm_svc_db_check_duplicated_scan_list(MediaDBHandle *db_handle, const char *data); +static int __dcm_svc_sql_prepare_to_step(sqlite3 *handle, const char *sql_str, sqlite3_stmt** stmt); +static int __dcm_svc_sql_prepare_to_step_simple(sqlite3 *handle, const char *sql_str, sqlite3_stmt** stmt); +} + +static DcmDbUtils* DcmDbUtils::getInstance(void) +{ + if (dcmDbUtils == NULL) { + g_mutex_trylock(&gMutexLock); + + if (dcmDbUtils == NULL) { + dcmDbUtils = new DcmDbUtils(); + } + + g_mutex_unlock(&gMutexLock); + } + + return dcmDbUtils; +} + +DcmDbUtils *DcmDbUtils::dcmDbUtils = NULL; +MediaDBHandle *DcmDbUtils::db_handle = NULL; + +DcmDbUtils::DcmDbUtils(void) +{ + +} + +bool DcmDbUtilsInternal::__dcm_svc_db_check_duplicated(MediaDBHandle *db_handle, DcmFaceItem *data) +{ + int ret = MS_MEDIA_ERR_NONE; + sqlite3 * handle = (sqlite3 *)db_handle; + sqlite3_stmt *sql_stmt = NULL; + char *query_string = NULL; + int count = 0; + + DCM_CHECK_FALSE((data != NULL)); + DCM_CHECK_FALSE((data->media_uuid != NULL)); + + query_string = sqlite3_mprintf("SELECT count(*) FROM %s WHERE (media_uuid='%s' AND" + " face_rect_x='%d' AND face_rect_y='%d' AND face_rect_w='%d' AND face_rect_h='%d' AND orientation='%d')" + , DB_TABLE_FACE, data->media_uuid + , data->face_rect_x, data->face_rect_y, data->face_rect_w, data->face_rect_h, data->orientation); + + ret = __dcm_svc_sql_prepare_to_step(handle, query_string, &sql_stmt); + + if (ret != MS_MEDIA_ERR_NONE) { + dcm_error("error when __dcm_svc_sql_prepare_to_step. ret = [%d]", ret); + return TRUE; + } + + count = sqlite3_column_int(sql_stmt, 0); + + DCM_SQLITE3_FINALIZE(sql_stmt); + + if (count > 0) { + dcm_warn("duplicated face data!"); + return TRUE; + } + + return FALSE; +} + +bool DcmDbUtilsInternal::__dcm_svc_db_check_duplicated_scan_list(MediaDBHandle *db_handle, const char *data) +{ + int ret = MS_MEDIA_ERR_NONE; + sqlite3 * handle = (sqlite3 *)db_handle; + sqlite3_stmt *sql_stmt = NULL; + char *query_string = NULL; + int count = 0; + + DCM_CHECK_FALSE((data != NULL)); + + query_string = sqlite3_mprintf("SELECT count(*) FROM %s WHERE media_uuid='%s'", DB_TABLE_FACE_SCAN_LIST, data); + + ret = __dcm_svc_sql_prepare_to_step(handle, query_string, &sql_stmt); + + if (ret != MS_MEDIA_ERR_NONE) { + dcm_error("error when __dcm_svc_sql_prepare_to_step. ret = [%d]", ret); + return TRUE; + } + + count = sqlite3_column_int(sql_stmt, 0); + + DCM_SQLITE3_FINALIZE(sql_stmt); + + if (count > 0) { + dcm_warn("duplicated media data!"); + return TRUE; + } + + return FALSE; +} + + +static int DcmDbUtilsInternal::__dcm_svc_sql_prepare_to_step(sqlite3 *handle, const char *sql_str, sqlite3_stmt** stmt) +{ + int err = -1; + + dcm_debug("[SQL query] : %s", sql_str); + + if (!DCM_STRING_VALID(sql_str)) + { + dcm_error("invalid query"); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + err = sqlite3_prepare_v2(handle, sql_str, -1, stmt, NULL); + sqlite3_free((char *)sql_str); + + if (err != SQLITE_OK) { + dcm_error ("prepare error %d[%s]", err, sqlite3_errmsg(handle)); + if (err == SQLITE_CORRUPT) { + return MS_MEDIA_ERR_DB_CORRUPT; + } else if (err == SQLITE_PERM) { + return MS_MEDIA_ERR_DB_PERMISSION; + } + + return MS_MEDIA_ERR_DB_INTERNAL; + } + + err = sqlite3_step(*stmt); + if (err != SQLITE_ROW) { + dcm_error("[No-Error] Item not found. end of row [%s]", sqlite3_errmsg(handle)); + DCM_SQLITE3_FINALIZE(*stmt); + return MS_MEDIA_ERR_DB_NO_RECORD; + } + + return MS_MEDIA_ERR_NONE; +} + +static int DcmDbUtilsInternal::__dcm_svc_sql_prepare_to_step_simple(sqlite3 *handle, const char *sql_str, sqlite3_stmt** stmt) +{ + int err = -1; + + dcm_debug("[SQL query] : %s", sql_str); + + if (!DCM_STRING_VALID(sql_str)) + { + dcm_error("invalid query"); + return MS_MEDIA_ERR_INVALID_PARAMETER; + } + + err = sqlite3_prepare_v2(handle, sql_str, -1, stmt, NULL); + sqlite3_free((char *)sql_str); + + if (err != SQLITE_OK) { + dcm_error ("prepare error %d[%s]", err, sqlite3_errmsg(handle)); + if (err == SQLITE_CORRUPT) { + return MS_MEDIA_ERR_DB_CORRUPT; + } else if (err == SQLITE_PERM) { + return MS_MEDIA_ERR_DB_PERMISSION; + } + + return MS_MEDIA_ERR_DB_INTERNAL; + } + + return MS_MEDIA_ERR_NONE; +} + +int DcmDbUtils::_dcm_svc_db_connect(uid_t uid) +{ + int err = -1; + + dcm_debug("_dcm_svc_db_connect uid: %d", uid); + dcm_uid = uid; + + err = media_db_connect(&db_handle, dcm_uid, TRUE); + if (err != MS_MEDIA_ERR_NONE) { + dcm_error("media_db_connect failed: %d", err); + db_handle = NULL; + return err; + } + + dcm_warn("media db handle: %p", db_handle); + + dcm_debug_fleave(); + + return MS_MEDIA_ERR_NONE; +} + +int DcmDbUtils::_dcm_svc_db_disconnect(void) +{ + int err = -1; + + dcm_warn("media db handle: %p", db_handle); + + err = media_db_disconnect(db_handle); + if (err != MS_MEDIA_ERR_NONE) { + dcm_error("media_db_disconnect failed: %d", err); + db_handle = NULL; + return err; + } + + db_handle = NULL; + + dcm_debug_fleave(); + + return err; +} + + +int DcmDbUtils::_dcm_svc_db_get_scan_image_list_by_path(GList **image_list, bool mmc_mounted, const char *file_path) +{ + int ret = MS_MEDIA_ERR_NONE; + char *query_string = NULL; + sqlite3_stmt *sql_stmt = NULL; + + dcm_debug_fenter(); + + DCM_CHECK_VAL(db_handle, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(file_path, DCM_ERROR_INVALID_PARAMETER); + + /* Make query */ + if (mmc_mounted == true) { + query_string = sqlite3_mprintf(SELECT_MEDIA_INFO_BY_FILE_PATH_FROM_DB, file_path); + } else { + query_string = sqlite3_mprintf(SELECT_MEDIA_INFO_BY_FILE_PATH_FROM_DB, file_path); + } + + if (query_string == NULL) { + dcm_error("Failed to make query!"); + return MS_MEDIA_ERR_OUT_OF_MEMORY; + } + + ret = DcmDbUtilsInternal::__dcm_svc_sql_prepare_to_step_simple((sqlite3 *)db_handle, query_string, &sql_stmt); + if (ret != MS_MEDIA_ERR_NONE) { + dcm_error("error when __dcm_svc_sql_prepare_to_step. ret = [%d]", ret); + return TRUE; + } + + + while(sqlite3_step(sql_stmt) == SQLITE_ROW) { + DcmScanItem *scan_item = (DcmScanItem *) g_malloc0(sizeof(DcmScanItem)); + if (!scan_item) { + dcm_error("Failed to allocate memory for scan_item!"); + continue; + } + + if (DCM_STRING_VALID((const char *)sqlite3_column_text(sql_stmt, 0))) + scan_item->media_uuid = strdup((const char *)sqlite3_column_text(sql_stmt, 0)); + + if (DCM_STRING_VALID(file_path)) + scan_item->file_path = strdup(file_path); + + if (DCM_STRING_VALID((const char *)sqlite3_column_text(sql_stmt, 1))) + scan_item->storage_uuid = strdup((const char *)sqlite3_column_text(sql_stmt, 1)); + + scan_item->image_width = sqlite3_column_int(sql_stmt, 2); + scan_item->image_height = sqlite3_column_int(sql_stmt, 3); + scan_item->image_orientation = sqlite3_column_int(sql_stmt, 4); + if (DCM_STRING_VALID((const char *)sqlite3_column_text(sql_stmt, 5))) + scan_item->mime_type = strdup((const char *)sqlite3_column_text(sql_stmt, 5)); + + /* scan item retrieved by this function will be marked as SCAN_SINGLE */ + scan_item->scan_item_type = DCM_SCAN_ITEM_TYPE_SCAN_SINGLE; + + *image_list = g_list_append(*image_list, scan_item); + + dcm_sec_debug("media uuid: [%s] file path: [%s]", scan_item->media_uuid, scan_item->file_path); + } + + + DCM_SQLITE3_FINALIZE(sql_stmt); + + dcm_debug_fleave(); + + return ret; +} + +int DcmDbUtils::_dcm_svc_db_get_scan_image_list_from_db(GList **image_list, bool mmc_mounted) +{ + int ret = MS_MEDIA_ERR_NONE; + char * query_string = NULL; + sqlite3_stmt *sql_stmt = NULL; + + dcm_debug_fenter(); + + DCM_CHECK_VAL(db_handle, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(image_list, DCM_ERROR_INVALID_PARAMETER); + + /* Make query */ + if (mmc_mounted == true) { + query_string = sqlite3_mprintf(SELECT_PATH_FROM_UNEXTRACTED_DCM_MEDIA); + } else { + query_string = sqlite3_mprintf(SELECT_PATH_FROM_UNEXTRACTED_DCM_INTERNAL_MEDIA); + } + + ret = DcmDbUtilsInternal::__dcm_svc_sql_prepare_to_step_simple((sqlite3 *)db_handle, query_string, &sql_stmt); + if (ret != MS_MEDIA_ERR_NONE) { + dcm_error("error when __dcm_svc_sql_prepare_to_step_simple. ret = [%d]", ret); + return DCM_ERROR_DB_OPERATION; + } + + while(sqlite3_step(sql_stmt) == SQLITE_ROW) { + DcmScanItem *scan_item = (DcmScanItem *) g_malloc0(sizeof(DcmScanItem)); + if (!scan_item) { + dcm_error("Failed to allocate memory for scan_item!"); + continue; + } + + if (DCM_STRING_VALID((const char *)sqlite3_column_text(sql_stmt, 0))) + scan_item->media_uuid = strdup((const char *)sqlite3_column_text(sql_stmt, 0)); + + if (DCM_STRING_VALID((const char *)sqlite3_column_text(sql_stmt, 1))) + scan_item->file_path = strdup((const char *)sqlite3_column_text(sql_stmt, 1)); + + if (DCM_STRING_VALID((const char *)sqlite3_column_text(sql_stmt, 2))) + scan_item->storage_uuid = strdup((const char *)sqlite3_column_text(sql_stmt, 2)); + + scan_item->image_width = sqlite3_column_int(sql_stmt, 3); + scan_item->image_height = sqlite3_column_int(sql_stmt, 4); + scan_item->image_orientation = sqlite3_column_int(sql_stmt, 5); + if (DCM_STRING_VALID((const char *)sqlite3_column_text(sql_stmt, 6))) + scan_item->mime_type = strdup((const char *)sqlite3_column_text(sql_stmt, 6)); + + /* scan item retrieved by this function will be marked as SCAN_ALL */ + scan_item->scan_item_type = DCM_SCAN_ITEM_TYPE_SCAN_ALL; + + *image_list = g_list_append(*image_list, scan_item); + + dcm_sec_debug("media uuid: [%s] file path: [%s]", scan_item->media_uuid, scan_item->file_path); + } + + DCM_SQLITE3_FINALIZE(sql_stmt); + + dcm_debug_fleave(); + + return MS_MEDIA_ERR_NONE; +} + +int DcmDbUtils::_dcm_svc_db_generate_uuid(DcmFaceItem **face) +{ + int ret = MS_MEDIA_ERR_NONE; + uuid_t uuid_value; + static char uuid_unparsed[50] = {0, }; + + dcm_debug_fenter(); + DCM_CHECK_VAL(face, DCM_ERROR_INVALID_PARAMETER); + + uuid_generate(uuid_value); + uuid_unparse(uuid_value, uuid_unparsed); + + (*face)->face_uuid = strdup(uuid_unparsed); + + if ((*face)->face_uuid == NULL) { + ret = DCM_ERROR_UUID_GENERATE_FAILED; + } else { + dcm_debug("set face_uuid :%s", (*face)->face_uuid); + } + + dcm_debug_fleave(); + + return ret; +} + +int DcmDbUtils::_dcm_svc_db_insert_face_to_db(DcmFaceItem *face) +{ + int ret = MS_MEDIA_ERR_NONE; + char* query_string = NULL; + + dcm_debug_fenter(); + + DCM_CHECK_VAL(db_handle, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(face, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(face->face_uuid, DCM_ERROR_INVALID_PARAMETER); + + if (DcmDbUtilsInternal::__dcm_svc_db_check_duplicated(db_handle, face) == TRUE) { + dcm_error("[__dcm_svc_db_check_duplicated] The data is duplicated!"); + return DCM_ERROR_DUPLICATED_DATA; + } + + query_string = sqlite3_mprintf(INSERT_FACE_ITEM_TO_DB, face->face_uuid, face->media_uuid, face->face_rect_x, face->face_rect_y, face->face_rect_w, face->face_rect_h, face->orientation); + + dcm_debug("query is %s", query_string); + + g_mutex_trylock(&gMutexLock); + ret = media_db_request_update_db(query_string, dcm_uid); + if (ret != MS_MEDIA_ERR_NONE) { + dcm_error("media_db_request_update_db fail = %d, %s", ret, sqlite3_errmsg((sqlite3 *)db_handle)); + } + g_mutex_unlock(&gMutexLock); + + DCM_SQLITE3_FREE(query_string); + + dcm_debug_fleave(); + + return ret; +} + +int DcmDbUtils::_dcm_svc_db_insert_face_to_face_scan_list(DcmScanItem *scan_item) +{ + int ret = MS_MEDIA_ERR_NONE; + char* query_string = NULL; + + dcm_debug_fenter(); + + DCM_CHECK_VAL(db_handle, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(scan_item, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(scan_item->media_uuid, DCM_ERROR_INVALID_PARAMETER); + + if (DcmDbUtilsInternal::__dcm_svc_db_check_duplicated_scan_list(db_handle, scan_item->media_uuid) == TRUE) { + dcm_error("[_dcm_svc_db_insert_face_to_face_scan_list] The data is duplicated!"); + return DCM_ERROR_DUPLICATED_DATA; + } + + query_string = sqlite3_mprintf("INSERT INTO %s (media_uuid, storage_uuid) values('%q', '%q')", DB_TABLE_FACE_SCAN_LIST, scan_item->media_uuid, scan_item->storage_uuid); + + dcm_debug("query is %s", query_string); + + g_mutex_trylock(&gMutexLock); + ret = media_db_request_update_db(query_string, dcm_uid); + if (ret != MS_MEDIA_ERR_NONE) { + dcm_error("media_db_request_update_db is failed: %d, %s", ret, sqlite3_errmsg((sqlite3 *)db_handle)); + } + g_mutex_unlock(&gMutexLock); + + DCM_SQLITE3_FREE(query_string); + + dcm_debug_fleave(); + + return ret; +} + +int DcmDbUtils::_dcm_svc_db_update_color_to_db(DcmColorItem color) +{ + int ret = MS_MEDIA_ERR_NONE; + char* query_string = NULL; + + dcm_debug_fenter(); + + DCM_CHECK_VAL(db_handle, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(color.media_uuid, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(color.storage_uuid, DCM_ERROR_INVALID_PARAMETER); + + query_string = sqlite3_mprintf(UPDATE_COLOR_ITEM_TO_DB, (int)(color.rgb_r), (int)(color.rgb_g), (int)(color.rgb_b), color.media_uuid, color.storage_uuid); + dcm_debug("query is %s", query_string); + + g_mutex_trylock(&gMutexLock); + ret = media_db_request_update_db(query_string, dcm_uid); + if (ret != MS_MEDIA_ERR_NONE) { + dcm_error("media_db_request_update_db fail = %d, %s", ret, sqlite3_errmsg((sqlite3 *)db_handle)); + } + g_mutex_unlock(&gMutexLock); + + DCM_SQLITE3_FREE(query_string); + + dcm_debug_fleave(); + + return ret; +} + +int DcmDbUtils::_dcm_svc_db_check_scanned_by_media_uuid(const char *media_uuid, bool *media_scanned) +{ + int ret = MS_MEDIA_ERR_NONE; + char *query_string = NULL; + sqlite3_stmt *sql_stmt = NULL; + int count = 0; + + dcm_debug_fenter(); + + DCM_CHECK_VAL(db_handle, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(media_uuid, DCM_ERROR_INVALID_PARAMETER); + + query_string = sqlite3_mprintf("SELECT count(*) FROM %s WHERE (media_uuid='%q')", DB_TABLE_FACE_SCAN_LIST, media_uuid); + DCM_CHECK_VAL(query_string, DCM_ERROR_OUT_OF_MEMORY); + + ret = DcmDbUtilsInternal::__dcm_svc_sql_prepare_to_step((sqlite3 *)db_handle, query_string, &sql_stmt); + if (ret != MS_MEDIA_ERR_NONE) { + dcm_error("error when __dcm_svc_sql_prepare_to_step. ret = [%d]", ret); + return DCM_ERROR_DB_OPERATION; + } + + count = sqlite3_column_int(sql_stmt, 0); + + DCM_SQLITE3_FINALIZE(sql_stmt); + + if (count > 0) + *media_scanned = TRUE; + else + *media_scanned = FALSE; + + dcm_debug_fleave(); + + return ret; +} + +int DcmDbUtils::_dcm_svc_db_send_noti(DcmFaceItem *face, DcmFaceItemUpdateItem update_item, DcmFaceItemUpdateType update_type) +{ + int ret = MS_MEDIA_ERR_NONE; + + dcm_debug_fenter(); + + if (face == NULL) + { + //ret = DCM_ERROR_INVALID_PARAMETER; + } else { + //ret = media_face_db_update_send((media_face_item_type_e)update_item, (media_face_item_update_type_e)update_type, face->media_id, face->face_uuid); + } + + if (ret != MS_MEDIA_ERR_NONE) { + dcm_error("Failed to send noti after update db! err: %d, %s", ret, sqlite3_errmsg((sqlite3 *)db_handle)); + } + + dcm_debug_fleave(); + + return ret; +} diff --git a/src/DcmFaceUtils.cpp b/src/DcmFaceUtils.cpp new file mode 100755 index 0000000..a7d67d3 --- /dev/null +++ b/src/DcmFaceUtils.cpp @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace DcmFaceApi { +int createFaceItem(DcmFaceItem **face); +double caculateScaleFactor(DcmImageInfo *image_info); +void freeDcmFaceItem(void *data); +} + +static dcm_face_h dcm_face_handle = NULL; + +int DcmFaceUtils::initialize() +{ + int ret = FACE_ERROR_NONE; + + dcm_debug_fenter(); + + ret = dcm_face_create(&dcm_face_handle); + if (ret != FACE_ERROR_NONE) { + dcm_error("Failed to dcm_face_create err: %d", ret); + return DCM_ERROR_FACE_ENGINE_FAILED; + } + + dcm_debug_fleave(); + + return DCM_SUCCESS; +} + +int DcmFaceUtils::finalize() +{ + int ret = FACE_ERROR_NONE; + + dcm_debug_fenter(); + + DCM_CHECK_VAL(dcm_face_handle, DCM_ERROR_INVALID_PARAMETER); + + ret = dcm_face_destroy(dcm_face_handle); + if (ret != FACE_ERROR_NONE) { + dcm_error("Failed to dcm_face_destroy ret: %d", ret); + return DCM_ERROR_FACE_ENGINE_FAILED; + } + + dcm_face_handle = NULL; + + dcm_debug_fleave(); + + return DCM_SUCCESS; +} + +int DcmFaceUtils::runFaceRecognizeProcess(DcmScanItem *scan_item, DcmImageInfo *image_info) +{ + DcmDbUtils *dcmDbUtils = DcmDbUtils::getInstance(); + DcmFaceItem *face = NULL; + int face_area = 0; + int i = 0; + double scale_factor = 0.0; + int err = FACE_ERROR_NONE; + int ret = DCM_SUCCESS; + face_info_s *face_info = NULL; + + dcm_debug_fenter(); + + DCM_CHECK_VAL(dcm_face_handle, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(scan_item, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(image_info, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(image_info->pixel, DCM_ERROR_INVALID_PARAMETER); + + /* Create image buffer used for face detection */ + face_image_colorspace_e prefered_colorspace = FACE_IMAGE_COLORSPACE_RGB888; + + err = dcm_face_get_prefered_colorspace(dcm_face_handle, &prefered_colorspace); + if (err != FACE_ERROR_NONE) { + dcm_error("Failed to create face_image! err: %d", err); + ret = DCM_ERROR_FACE_ENGINE_FAILED; + goto DCM_SVC_FACE_RECOGNIZE_BUFFER_FAILED; + } + + dcm_debug("colorspce: [%d], w: [%d], h: [%d]", prefered_colorspace, image_info->buffer_width, image_info->buffer_height); + + err = dcm_face_set_image_info(dcm_face_handle, prefered_colorspace, image_info->pixel, image_info->buffer_width, image_info->buffer_height, image_info->size); + if (err != FACE_ERROR_NONE) { + dcm_error("Failed to dcm_face_set_image_info! err: %d", err); + ret = DCM_ERROR_FACE_ENGINE_FAILED; + goto DCM_SVC_FACE_RECOGNIZE_BUFFER_FAILED; + } + + face_info = (face_info_s*)g_malloc0(sizeof(face_info_s)); + + err = dcm_face_get_face_info(dcm_face_handle, face_info); + if (err != FACE_ERROR_NONE) { + dcm_error("Failed to get face info! err: %d", err); + ret = DCM_ERROR_FACE_ENGINE_FAILED; + goto DCM_SVC_FACE_RECOGNIZE_BUFFER_FAILED; + } + + dcm_warn("detected face count: %d", face_info->count); + if (face_info->count <= 0) { + goto DCM_SVC_FACE_RECOGNIZE_BUFFER_FAILED; + } + + /* Compute scale factor between decode size and original size */ + scale_factor = DcmFaceApi::caculateScaleFactor(image_info); + + /* Insert every face rectangle into database */ + for (i = 0; i < face_info->count; i++) { + face = NULL; + + err = DcmFaceApi::createFaceItem(&face); + if (err != DCM_SUCCESS) { + dcm_error("Failed to create face items! err: %d", err); + ret = err; + goto DCM_SVC_FACE_RECOGNIZE_BUFFER_FAILED; + } + + if (scale_factor > 1.0) { + face->face_rect_x = (int) (face_info->rects[i].x * scale_factor); + face->face_rect_y = (int) (face_info->rects[i].y * scale_factor); + face->face_rect_w = (int) (face_info->rects[i].w * scale_factor); + face->face_rect_h = (int) (face_info->rects[i].h * scale_factor); + } else { + face->face_rect_x = face_info->rects[i].x; + face->face_rect_y = face_info->rects[i].y; + face->face_rect_w = face_info->rects[i].w; + face->face_rect_h = face_info->rects[i].h; + } + face->orientation = face_info->rects[i].orientation; + + face_area += face->face_rect_w * face->face_rect_h; + dcm_debug("[#%d] face rect: XYWH (%d, %d, %d, %d)", i, face->face_rect_x, face->face_rect_y, face->face_rect_w, + face->face_rect_h); + + face->media_uuid = strdup(scan_item->media_uuid); + + /* Insert face rectangle into database */ + err = dcmDbUtils->_dcm_svc_db_generate_uuid(&face); + if (err != DCM_SUCCESS) { + dcm_error("Failed to set uuid! err: %d", err); + goto DCM_SVC_FACE_RECOGNIZE_BUFFER_FAILED; + } + err = dcmDbUtils->_dcm_svc_db_insert_face_to_db(face); + if (err != DCM_SUCCESS) { + dcm_error("Failed to insert face item into db! err: %d", err); + goto DCM_SVC_FACE_RECOGNIZE_BUFFER_FAILED; + } + + /* Send db updated notification */ + dcmDbUtils->_dcm_svc_db_send_noti(face, DCM_FACE_ITEM_UPDATE_FACE, DCM_FACE_ITEM_INSERT); + if (face != NULL) { + DcmFaceApi::freeDcmFaceItem(face); + face = NULL; + } + } + +DCM_SVC_FACE_RECOGNIZE_BUFFER_FAILED: + + dcmDbUtils->_dcm_svc_db_insert_face_to_face_scan_list(scan_item); + + if (face_info != NULL) { + dcm_face_destroy_face_info(face_info); + face_info = NULL; + } + + if (face != NULL) { + DcmFaceApi::freeDcmFaceItem(face); + face = NULL; + } + + dcm_debug_fleave(); + + return ret; +} + +int DcmFaceApi::createFaceItem(DcmFaceItem **face) +{ + DCM_CHECK_VAL(face, DCM_ERROR_INVALID_PARAMETER); + + *face = NULL; + + DcmFaceItem *_face = (DcmFaceItem*)g_malloc0(sizeof(DcmFaceItem)); + if (_face == NULL) + return DCM_ERROR_OUT_OF_MEMORY; + + *face = _face; + + return DCM_SUCCESS; +} + +double DcmFaceApi::caculateScaleFactor(DcmImageInfo *image_info) +{ + double scale_factor = 0.0; + + DCM_CHECK_VAL(image_info, 0.0); + + if (image_info->original_width >= image_info->original_height) { + if (image_info->buffer_width >= image_info->buffer_height) { + scale_factor = ((double) (image_info->original_width)) / ((double) (image_info->buffer_width)); + } else { + scale_factor = ((double) (image_info->original_width)) / ((double) (image_info->buffer_height)); + } + } else { + if (image_info->buffer_height >= image_info->buffer_width) { + scale_factor = ((double) (image_info->original_height)) / ((double) (image_info->buffer_height)); + } else { + scale_factor = ((double) (image_info->original_height)) / ((double) (image_info->buffer_width)); + } + } + + dcm_debug("scale_factor: %lf", scale_factor); + + return scale_factor; +} + +void DcmFaceApi::freeDcmFaceItem(void *data) +{ + DcmFaceItem *_face = (DcmFaceItem *)data; + DCM_CHECK(_face); + + DCM_SAFE_FREE(_face->face_uuid); + DCM_SAFE_FREE(_face->media_uuid); + DCM_SAFE_FREE(_face); + + return; +} diff --git a/src/DcmIpcUtils.cpp b/src/DcmIpcUtils.cpp new file mode 100755 index 0000000..c56a6ad --- /dev/null +++ b/src/DcmIpcUtils.cpp @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static char DCM_IPC_PATH[5][100] = + {"/var/run/media-server/dcm_ipc_scanthread_recv", + "/var/run/media-server/dcm_ipc_thumbserver_comm_recv", + "/var/run/media-server/media_ipc_thumbdcm_dcmrecv"}; + +int DcmIpcUtils::receiveSocketMsg(int client_sock, DcmIpcMsg *recv_msg) +{ + int recv_msg_size = 0; + + if ((recv_msg_size = read(client_sock, recv_msg, sizeof(DcmIpcMsg))) < 0) { + if (errno == EWOULDBLOCK) { + dcm_error("Timeout. Can't try any more"); + return DCM_ERROR_IPC; + } else { + dcm_error("recv failed : %s", strerror(errno)); + return DCM_ERROR_NETWORK; + } + } + dcm_sec_debug("[receive msg] type: %d, uid: %d, msg: %s, msg_size: %d", recv_msg->msg_type, recv_msg->uid, recv_msg->msg, recv_msg->msg_size); + + if (!(recv_msg->msg_type >= 0 && recv_msg->msg_type < DCM_IPC_MSG_MAX)) { + dcm_error("IPC message is wrong!"); + return DCM_ERROR_IPC_INVALID_MSG; + } + + return DCM_SUCCESS; +} + +int DcmIpcUtils::acceptSocket(int serv_sock, int* client_sock) +{ + DCM_CHECK_VAL(client_sock, DCM_ERROR_INVALID_PARAMETER); + int sockfd = -1; + struct sockaddr_un client_addr; + socklen_t client_addr_len = sizeof(client_addr); + + if ((sockfd = accept(serv_sock, (struct sockaddr*)&client_addr, &client_addr_len)) < 0) { + dcm_error("accept failed : %s", strerror(errno)); + *client_sock = -1; + return DCM_ERROR_NETWORK; + } + + *client_sock = sockfd; + + return DCM_SUCCESS; +} + +int DcmIpcUtils::createSocket(int *socket_fd, DcmIpcPortType port) +{ + DCM_CHECK_VAL(socket_fd, DCM_ERROR_INVALID_PARAMETER); + int sock = -1; + struct sockaddr_un serv_addr; + bool bind_success = false; + int i = 0; + + /* Create a new TCP socket */ + if ((sock = socket(PF_FILE, SOCK_STREAM, 0)) < 0) { + dcm_error("socket failed: %s", strerror(errno)); + return DCM_ERROR_NETWORK; + } + + /* Set socket address */ + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sun_family = AF_UNIX; + unlink(DCM_IPC_PATH[port]); + strcpy(serv_addr.sun_path, DCM_IPC_PATH[port]); + + /* Bind socket to local address */ + for (i = 0; i < 20; i++) { + if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0) { + bind_success = true; + break; + } + dcm_debug("#%d bind", i); + usleep(250000); + } + + if (bind_success == false) { + dcm_error("bind failed : %s %d_", strerror(errno), errno); + close(sock); + return DCM_ERROR_NETWORK; + } + dcm_debug("bind success"); + + /* Listenint */ + if (listen(sock, SOMAXCONN) < 0) { + dcm_error("listen failed : %s", strerror(errno)); + close(sock); + return DCM_ERROR_NETWORK; + } + dcm_debug("Listening..."); + + /* change permission of local socket file */ + if (chmod(DCM_IPC_PATH[port], 0660) < 0) + dcm_error("chmod failed [%s]", strerror(errno)); + /* + if (chown(DCM_IPC_PATH[port], 0, 5000) < 0) + dcm_dbgE("chown failed [%s]", strerror(errno)); + */ + + *socket_fd = sock; + + return DCM_SUCCESS; +} + +int DcmIpcUtils::sendSocketMsg(DcmIpcMsgType msg_type, uid_t uid, const char *msg, DcmIpcPortType port) +{ + if (port < 0 || port >= DCM_IPC_PORT_MAX) { + dcm_error("Invalid port! Stop sending message..."); + return DCM_ERROR_INVALID_PARAMETER; + } + dcm_debug("Send message type: %d", msg_type); + + int socket_fd = -1; + struct sockaddr_un serv_addr; + //struct timeval tv_timeout = { 10, 0 }; /* timeout: 10 seconds */ + DcmIpcMsg send_msg; + + /* Prepare send message */ + memset((void *)&send_msg, 0, sizeof(DcmIpcMsg)); + send_msg.msg_type = msg_type; + send_msg.uid = uid; + if (msg != NULL) { + send_msg.msg_size = strlen(msg); + strncpy(send_msg.msg, msg, send_msg.msg_size); + } + + /* If message size is larget than max_size, then message is invalid */ + if (send_msg.msg_size >= DCM_IPC_MSG_MAX_SIZE) { + dcm_error("Message size is invalid!"); + return DCM_ERROR_INVALID_IMAGE_SIZE; + } + + /* Create a new TCP socket */ + if ((socket_fd = socket(PF_FILE, SOCK_STREAM, 0)) < 0) { + dcm_error("socket failed: %s", strerror(errno)); + return DCM_ERROR_NETWORK; + } + + /* Set dcm thread socket address */ + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sun_family = AF_UNIX; + strcpy(serv_addr.sun_path, DCM_IPC_PATH[port]); + + /* Connect to the socket */ + if (connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) { + dcm_error("connect error : %s", strerror(errno)); + close(socket_fd); + return DCM_ERROR_NETWORK; + } + + /* Send msg to the socket */ + if (send(socket_fd, &send_msg, sizeof(send_msg), 0) != sizeof(send_msg)) { + dcm_error("send failed : %s", strerror(errno)); + close(socket_fd); + return DCM_ERROR_NETWORK; + } + + close(socket_fd); + return DCM_SUCCESS; +} + +int DcmIpcUtils::closeSocket(int socket_fd) +{ + close(socket_fd); + return DCM_SUCCESS; +} + +#define DCM_SVC_FACE_ASYNC_MEDIA_UUID_LENGTH 64 +#define DCM_SVC_FACE_ASYNC_UDP_SEND_PORT 1551 +#define DCM_SVC_FACE_ASYNC_INET_ADDR "127.0.0.1" +typedef struct +{ + int type; /* type should be set to 0 */ + char media_uuid[DCM_SVC_FACE_ASYNC_MEDIA_UUID_LENGTH]; +} dcm_svc_face_async_msg_s; + +int DcmIpcUtils::sendFaceMsg(const char *media_uuid) +{ + dcm_debug_fenter(); + DCM_CHECK_VAL(media_uuid, DCM_ERROR_INVALID_PARAMETER); + dcm_sec_debug("media_id: %s", media_uuid); + struct sockaddr_in client_addr; + int socket_fd = 0; + int ret = 0; + + /* Create send socket */ + if ((socket_fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + dcm_error("Failed to create socket for libface-svc! err: %s", strerror(errno)); + return DCM_ERROR_NETWORK; + } + dcm_debug("socket fd: %d", socket_fd); + + /* Set send message */ + dcm_svc_face_async_msg_s face_async_msg; + memset(&face_async_msg, 0x00, sizeof(dcm_svc_face_async_msg_s)); + face_async_msg.type = 0; + g_strlcpy(face_async_msg.media_uuid, media_uuid, sizeof(face_async_msg.media_uuid)); + + /* Set face async port and address */ + client_addr.sin_family = AF_INET; + client_addr.sin_port = htons(DCM_SVC_FACE_ASYNC_UDP_SEND_PORT); + client_addr.sin_addr.s_addr = inet_addr(DCM_SVC_FACE_ASYNC_INET_ADDR); + + /* Send message to libface-svc */ + ret = sendto(socket_fd, &face_async_msg, sizeof(dcm_svc_face_async_msg_s), MSG_NOSIGNAL, (struct sockaddr*)&client_addr, sizeof(client_addr)); + if (ret < 0) { + dcm_error("Failed to send message to libface-svc! err: %s", strerror(errno)); + close(socket_fd); + return DCM_ERROR_NETWORK; + } + + close(socket_fd); + dcm_debug_fleave(); + return DCM_SUCCESS; +} + diff --git a/src/DcmScanSvc.cpp b/src/DcmScanSvc.cpp new file mode 100755 index 0000000..f606515 --- /dev/null +++ b/src/DcmScanSvc.cpp @@ -0,0 +1,695 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../libdcm-util/include/dcm_image_codec.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MIME_TYPE_JPEG "image/jpeg" +#define MIME_TYPE_PNG "image/png" +#define MIME_TYPE_BMP "image/bmp" + +class DcmScanSvc { +public: + GMainLoop *g_scan_thread_mainloop; + GMainContext *scan_thread_main_context; + + /* scan all images */ + GList *scan_all_item_list; + unsigned int scan_all_curr_index; + + /* scan single images */ + GList *scan_single_item_list; + unsigned int scan_single_curr_index; + + void quitScanThread(); + int getMmcState(void); + int prepareImageList(); + int prepareImageListByPath(const char *file_path); + int clearAllItemList(); + int clearSingleItemList(); + int initialize(); + int finalize(); + int sendCompletedMsg(const char *msg, DcmIpcPortType port); + int getScanStatus(DcmScanItem *scan_item, bool *media_scanned); + int runScanProcess(DcmScanItem *scan_item); + int ScanAllItems(); + int ScanSingleItem(const char *file_path); + int terminateScanOperations(); + int receiveMsg(DcmIpcMsg *recv_msg); + +}; + +namespace DcmScanCallback { +void freeScanItem(void *data); +gboolean readyScanThreadIdle(gpointer data); +gboolean readMsg(GIOChannel *src, GIOCondition condition, gpointer data); +} + +void DcmScanSvc::quitScanThread() +{ + if (g_scan_thread_mainloop != NULL) { + dcm_warn("Quit scan thread mainloop!"); + g_main_loop_quit(g_scan_thread_mainloop); + } else { + dcm_warn("Scan thread mainloop is invalid!"); + } + + return; +} + +int DcmScanSvc::getMmcState(void) +{ + int err = -1; + int status = -1; + + err = vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &status); + if (err != 0) { + dcm_error("vconf_get_int Unexpected error code: %d", err); + } + + return status; +} + +int DcmScanSvc::prepareImageList() +{ + int ret = DCM_SUCCESS; + DcmDbUtils *dcmDbUtils = DcmDbUtils::getInstance(); + bool mmc_mounted = false; + + if (getMmcState() == VCONFKEY_SYSMAN_MMC_MOUNTED) { + mmc_mounted = true; + } else { + mmc_mounted = false; + } + + /* Get scan image list from db */ + ret = dcmDbUtils->_dcm_svc_db_get_scan_image_list_from_db(&(scan_all_item_list), mmc_mounted); + if (ret != MS_MEDIA_ERR_NONE) { + dcm_error("Failed to get image list from db! ret: %d", ret); + return ret; + } + + if (scan_all_item_list == NULL) { + dcm_debug("No image list for scanning"); + return DCM_ERROR_DB_NO_RESULT; + } + + if ((scan_all_item_list != NULL) && (g_list_length(scan_all_item_list) == 0)) { + dcm_debug("No image list from db!"); + return DCM_ERROR_DB_NO_RESULT; + } + + return DCM_SUCCESS; +} + +int DcmScanSvc::prepareImageListByPath(const char *file_path) +{ + int ret = DCM_SUCCESS; + DcmDbUtils *dcmDbUtils = DcmDbUtils::getInstance(); + bool mmc_mounted = false; + + if (getMmcState() == VCONFKEY_SYSMAN_MMC_MOUNTED) { + mmc_mounted = true; + } else { + mmc_mounted = false; + } + + /* Get scan image list from db */ + ret = dcmDbUtils->_dcm_svc_db_get_scan_image_list_by_path(&(scan_single_item_list), mmc_mounted, file_path); + if (ret != MS_MEDIA_ERR_NONE) { + dcm_error("Failed to get image list from db! ret: %d", ret); + return ret; + } + + if (scan_single_item_list == NULL) { + dcm_debug("No image list for scanning"); + return DCM_ERROR_DB_NO_RESULT; + } + + if ((scan_single_item_list != NULL) && (g_list_length(scan_single_item_list) == 0)) { + dcm_debug("No image list from db!"); + return DCM_ERROR_DB_NO_RESULT; + } + + return DCM_SUCCESS; +} + +int DcmScanSvc::clearAllItemList() +{ + dcm_debug_fenter(); + + if (scan_all_item_list != NULL) { + g_list_free_full(scan_all_item_list, DcmScanCallback::freeScanItem); + scan_all_item_list = NULL; + } + + scan_all_curr_index = 0; + + return DCM_SUCCESS; +} + +int DcmScanSvc::clearSingleItemList() +{ + dcm_debug_fenter(); + + if (scan_single_item_list) { + g_list_free_full(scan_single_item_list, DcmScanCallback::freeScanItem); + scan_single_item_list = NULL; + } + + scan_single_curr_index = 0; + + return DCM_SUCCESS; +} + +int DcmScanSvc::initialize() +{ + scan_all_item_list = NULL; + scan_all_curr_index = 0; + scan_single_item_list = NULL; + scan_single_curr_index = 0; + + DcmFaceUtils::initialize(); + + ecore_evas_init(); + + return DCM_SUCCESS; +} + +int DcmScanSvc::finalize() +{ + /* Only scan item lists are freed here, scan idles should be freed before this function */ + clearAllItemList(); + clearSingleItemList(); + DcmFaceUtils::finalize(); + + ecore_evas_shutdown(); + + return DCM_SUCCESS; +} + +int DcmScanSvc::sendCompletedMsg(const char *msg, DcmIpcPortType port) +{ + if ((scan_all_item_list == NULL) && (scan_single_item_list == NULL)) { + dcm_debug("Send completed message"); + DcmIpcUtils::sendSocketMsg(DCM_IPC_MSG_SCAN_COMPLETED, 0, msg, port); + } else { + if (scan_all_item_list) + dcm_warn("scan_all_item_list"); + + if (scan_single_item_list) + dcm_warn("scan_single_item_list"); + + dcm_warn("Scan operation is not finished yet. Keep scanning..."); + } + + return DCM_SUCCESS; +} + +int DcmScanSvc::getScanStatus(DcmScanItem *scan_item, bool *media_scanned) +{ + int ret = DCM_SUCCESS; + DcmDbUtils *dcmDbUtils = DcmDbUtils::getInstance(); + + DCM_CHECK_VAL(scan_item, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(scan_item->media_uuid, DCM_ERROR_INVALID_PARAMETER); + + /* Check if this media is scanned or not */ + ret = dcmDbUtils->_dcm_svc_db_check_scanned_by_media_uuid(scan_item->media_uuid, media_scanned); + if (ret != DCM_SUCCESS) { + dcm_error("Failed to check if this media item is scanned or not!"); + } + + return ret; +} + +int DcmScanSvc::runScanProcess(DcmScanItem *scan_item) +{ + bool media_scanned = false; + int ret = DCM_SUCCESS; + + dcm_debug_fenter(); + DCM_CHECK_VAL(scan_item, DCM_ERROR_INVALID_PARAMETER); + DCM_CHECK_VAL(scan_item->file_path, DCM_ERROR_INVALID_PARAMETER); + + DcmImageInfo image_info = {0, }; + memset(&image_info, 0, sizeof(DcmImageInfo)); + dcm_image_codec_type_e image_format = DCM_IMAGE_CODEC_RGB888; + + /* Process scan operation if the file exists */ + if (g_file_test(scan_item->file_path, (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) == TRUE) { + /* Get necessary information from db again. + * Media information will be inserted after face is detected. + * If media uuid does not exist, retry is needed */ + ret = getScanStatus(scan_item, &media_scanned); + if (ret != DCM_SUCCESS) { + dcm_error("Failed to get scan item info from db! err: %d", ret); + return ret; + } + + /* It is possible that when single and async scan for the same image is in the list. + * If the media uuid is already scanned, skip this scan. */ + if (media_scanned == true) { + dcm_warn("This media is scanned already! Skip..."); + DCM_SAFE_FREE(image_info.pixel); + return DCM_ERROR_IMAGE_ALREADY_SCANNED; + } else { + dcm_debug("This media is NOT scanned yet."); + } + + dcm_sec_debug("scan file path : [%s]", scan_item->file_path); + dcm_sec_debug("scan media uuid : [%s]", scan_item->media_uuid); + + ImgCodecType type = IMG_CODEC_NONE; + + image_info.original_width = scan_item->image_width; + image_info.original_height = scan_item->image_height; + + dcm_debug("scan media w : [%d], h : [%d], orientation : [%d]", image_info.original_width, image_info.original_height, scan_item->image_orientation); + + if (image_info.original_width <= 0 && image_info.original_height <= 0) { + ret = ImgGetImageInfo((const char *)(scan_item->file_path), &type, &(image_info.original_width), &(image_info.original_height)); + if (ret != DCM_SUCCESS) { + dcm_error("Failed ImgGetImageInfo! err: %d", ret); + return ret; + } + + dcm_debug("ImgGetImageInfo type: %d, width: %d, height: %d", type, image_info.original_width, image_info.original_height); + } + + if (strcmp(scan_item->mime_type, MIME_TYPE_JPEG) == 0) { + ret = dcm_decode_image_with_size_orient((const char *) (scan_item->file_path), image_info.original_width, + image_info.original_height, image_format, &(image_info.pixel), &(image_info.buffer_width), &(image_info.buffer_height), &(image_info.orientation), &(image_info.size)); + if (ret != DCM_SUCCESS) { + dcm_error("Failed dcm_decode_image_with_size_orient! err: %d", ret); + return ret; + } + } else if ((strcmp(scan_item->mime_type, MIME_TYPE_PNG) == 0) || (strcmp(scan_item->mime_type, MIME_TYPE_BMP) == 0)) { + ret = dcm_decode_image_with_evas((const char *) (scan_item->file_path), image_info.original_width, + image_info.original_height, image_format, &(image_info.pixel), &(image_info.buffer_width), &(image_info.buffer_height), &(image_info.orientation), &(image_info.size)); + if (ret != DCM_SUCCESS) { + dcm_error("Failed dcm_decode_image_with_evas! err: %d", ret); + return ret; + } + } else { + dcm_error("Failed not supported type! (%s)", scan_item->mime_type); + return DCM_ERROR_INVALID_PARAMETER; + } + image_info.decode_type = (DcmImageDecodeType)image_format; + + dcm_debug("Image info width: %d, height: %d, buf_width: %d, buf_height: %d, orientation: %d", + image_info.original_width, image_info.original_height, image_info.buffer_width, image_info.buffer_height, image_info.orientation); + + /* Process face scan */ + ret = DcmFaceUtils::runFaceRecognizeProcess(scan_item, &image_info); + if (ret != DCM_SUCCESS) { + dcm_error("Failed to process face detection! err: %d", ret); + } + + /* Set sleep time after face recognition */ + usleep(500000); + + /* Process color extract */ + ret = DcmColorUtils::runColorExtractProcess(scan_item, &image_info); + if (ret != DCM_SUCCESS) { + dcm_error("Failed to process color extraction! err: %d", ret); + } + + /* Free image buffer */ + DCM_SAFE_FREE(image_info.pixel); + } else { + dcm_warn("The file does not exist! Skip dcm scan for this file ..."); + } + + dcm_debug_fleave(); + + return ret; +} + +int DcmScanSvc::ScanAllItems() +{ + int ret = DCM_SUCCESS; + DcmScanItem *scan_item = NULL; + DcmDbUtils *dcmDbUtils = DcmDbUtils::getInstance(); + + dcm_debug_fenter(); + + clearAllItemList(); + + ret = prepareImageList(); + if (ret == DCM_ERROR_DB_NO_RESULT) { + dcm_debug("No items to Scan. Scan operation completed!!!"); + clearAllItemList(); + /* Send scan complete message to main thread (if all scan operations are finished) */ + sendCompletedMsg( NULL, DCM_IPC_PORT_DCM_RECV); + return DCM_SUCCESS; + } + + /* DCM scan started */ + unsigned int list_len = g_list_length(scan_all_item_list); + while (scan_all_curr_index < list_len) { + scan_item = (DcmScanItem *)g_list_nth_data(scan_all_item_list, scan_all_curr_index); + dcm_sec_debug("current index: %d, path: %s", scan_all_curr_index, scan_item->file_path); + + ret = runScanProcess(scan_item); + if (ret != DCM_SUCCESS) { + dcm_error("Failed to process scan job! err: %d", ret); + + /* If the scan item is not scanned, insert media uuid into face_scan_list */ + if (ret != DCM_ERROR_IMAGE_ALREADY_SCANNED) { + dcmDbUtils->_dcm_svc_db_insert_face_to_face_scan_list(scan_item); + } + } + + (scan_all_curr_index)++; + } + + dcm_warn("All images are scanned. Scan operation completed"); + + clearAllItemList(); + /* Send scan complete message to main thread (if all scan operations are finished) */ + sendCompletedMsg( NULL, DCM_IPC_PORT_DCM_RECV); + + dcm_debug_fleave(); + + return DCM_SUCCESS; +} + +int DcmScanSvc::ScanSingleItem(const char *file_path) +{ + int ret = DCM_SUCCESS; + DcmScanItem *scan_item = NULL; + DcmDbUtils *dcmDbUtils = DcmDbUtils::getInstance(); + + DCM_CHECK_VAL(file_path, DCM_ERROR_INVALID_PARAMETER); + + dcm_debug_fenter(); + + clearSingleItemList(); + + ret = prepareImageListByPath(file_path); + if (ret == DCM_ERROR_DB_NO_RESULT) { + dcm_debug("No items to Scan. Scan operation completed!!!"); + clearSingleItemList(); + /* Send scan complete message to main thread (if all scan operations are finished) */ + sendCompletedMsg( file_path/*ret*/, DCM_IPC_PORT_DCM_RECV); + return DCM_SUCCESS; + } + + dcm_debug("append scan item to scan item list"); + + /* DCM scan started */ + unsigned int list_len = g_list_length(scan_single_item_list); + if (scan_single_curr_index < list_len) { + scan_item = (DcmScanItem *)g_list_nth_data(scan_single_item_list, scan_single_curr_index); + dcm_sec_debug("current index: %d, path: %s, scan type: %d", scan_single_curr_index, scan_item->file_path, scan_item->scan_item_type); + + ret = runScanProcess(scan_item); + if (ret != DCM_SUCCESS) { + dcm_error("Failed to process scan job! err: %d", ret); + + /* If the scan item is not scanned, insert media uuid into face_scan_list */ + if (ret != DCM_ERROR_IMAGE_ALREADY_SCANNED) { + dcmDbUtils->_dcm_svc_db_insert_face_to_face_scan_list(scan_item); + } + } + + (scan_single_curr_index)++; + } + + clearSingleItemList(); + + dcm_debug_fleave(); + + return DCM_SUCCESS; +} + +int DcmScanSvc::terminateScanOperations() +{ + dcm_debug("Terminate scanning operations, and quit scan thread main loop"); + + quitScanThread(); + + return DCM_SUCCESS; +} + +int DcmScanSvc::receiveMsg(DcmIpcMsg *recv_msg) +{ + int ret = DCM_SUCCESS; + + DcmDbUtils *dcmDbUtils = DcmDbUtils::getInstance(); + DCM_CHECK_VAL(recv_msg, DCM_ERROR_INVALID_PARAMETER); + + ret = dcmDbUtils->_dcm_svc_db_connect(recv_msg->uid); + if (ret != MS_MEDIA_ERR_NONE) { + dcm_error("Failed to connect DB! err: %d", ret); + return ret; + } + + if (recv_msg->msg_type == DCM_IPC_MSG_SCAN_ALL) + { + /* Use timer to scan all unscanned images */ + ScanAllItems(); + } + else if (recv_msg->msg_type == DCM_IPC_MSG_SCAN_SINGLE) + { + /* Create a scan idle if not exist, and scan single image of which file path is reveived from tcp socket */ + if (recv_msg->msg_size > 0 && recv_msg->msg_size < DCM_IPC_MSG_MAX_SIZE) { + char *file_path = NULL; + file_path = strdup(recv_msg->msg); + if (file_path != NULL) { + ScanSingleItem((const char *) file_path); + DCM_SAFE_FREE(file_path); + } else { + dcm_error("Failed to copy message!"); + ret = DCM_ERROR_OUT_OF_MEMORY; + } + } else { + dcm_error("Invalid receive message!"); + ret = DCM_ERROR_IPC_INVALID_MSG; + } + } + else if (recv_msg->msg_type == DCM_IPC_MSG_SCAN_TERMINATED) + { + /* Destroy scan idles, and quit scan thread main loop */ + terminateScanOperations(); + } + else { + dcm_error("Invalid message type!"); + ret = DCM_ERROR_IPC_INVALID_MSG; + } + + ret = dcmDbUtils->_dcm_svc_db_disconnect(); + if (ret != DCM_SUCCESS) { + dcm_error("Failed to disconnect DB! err: %d", ret); + return FALSE; + } + + return ret; +} + +gboolean DcmScanCallback::readMsg(GIOChannel *src, GIOCondition condition, gpointer data) +{ + DcmScanSvc *dcmScanSvc = (DcmScanSvc *) data; + int sock = -1; + int client_sock = -1; + DcmIpcMsg recv_msg; + int err = 0; + + DCM_CHECK_FALSE(data); + + /* Get socket fd from IO channel */ + sock = g_io_channel_unix_get_fd(src); + if (sock < 0) { + dcm_error("Invalid socket fd!"); + return TRUE; + } + + /* Accept tcp client socket */ + err = DcmIpcUtils::acceptSocket(sock, &client_sock); + if (err != DCM_SUCCESS) { + dcm_error("Failed to accept tcp socket! err: %d", err); + return TRUE; + } + + /* Receive message from tcp socket */ + err = DcmIpcUtils::receiveSocketMsg(client_sock, &recv_msg); + if (err != DCM_SUCCESS) { + dcm_error("Failed to receive tcp msg! err: %d", err); + goto DCM_SVC_SCAN_READ_THREAD_RECV_SOCKET_FAILED; + } + + /* Process received message */ + err = dcmScanSvc->receiveMsg(&recv_msg); + if (err != DCM_SUCCESS) { + dcm_error("Error ocurred when process received message: %d", err); + goto DCM_SVC_SCAN_READ_THREAD_RECV_SOCKET_FAILED; + } + +DCM_SVC_SCAN_READ_THREAD_RECV_SOCKET_FAILED: + + if (close(client_sock) < 0) { + dcm_error("close failed [%s]", strerror(errno)); + } + + return TRUE; +} + +gboolean DcmScanCallback::readyScanThreadIdle(gpointer data) +{ + DcmMainSvc *ad = (DcmMainSvc *) data; + DcmIpcMsg *async_queue_msg = NULL; + + dcm_debug_fenter(); + + DCM_CHECK_FALSE(data); + DCM_CHECK_FALSE(ad->scan_thread_ready); + + async_queue_msg = (DcmIpcMsg*) g_malloc0(sizeof(DcmIpcMsg)); + async_queue_msg->msg_type = DCM_IPC_MSG_SCAN_READY; + + dcm_debug("scan thread ready : %p", ad->scan_thread_ready); + dcm_debug("async_queue_msg : %d", async_queue_msg->msg_type); + + g_async_queue_push(ad->scan_thread_ready, (gpointer) async_queue_msg); + + dcm_debug_fleave(); + + return FALSE; +} + +void DcmScanCallback::freeScanItem(void *data) +{ + DcmScanItem *scan_item = (DcmScanItem *) data; + + dcm_debug_fenter(); + + DCM_CHECK(scan_item); + DCM_CHECK(scan_item->file_path); + DCM_CHECK(scan_item->media_uuid); + DCM_CHECK(scan_item->storage_uuid); + + dcm_sec_debug("Free scan item. path: [%s]", scan_item->file_path); + + DCM_SAFE_FREE(scan_item->file_path); + DCM_SAFE_FREE(scan_item->media_uuid); + DCM_SAFE_FREE(scan_item->storage_uuid); + DCM_SAFE_FREE(scan_item); + + dcm_debug_fleave(); + + return; +} + +gboolean DcmScanMain::runScanThread(void *data) +{ + DcmMainSvc *dcmManSvc = (DcmMainSvc*) data; + DcmScanSvc dcmScanSvc; + int socket_fd = -1; + GSource *source = NULL; + GIOChannel *channel = NULL; + GMainContext *context = NULL; + GSource *scan_thread_ready_idle = NULL; + int err = 0; + + DCM_CHECK_VAL(data, DCM_ERROR_INVALID_PARAMETER); + + /* Init global variables */ + err = dcmScanSvc.initialize(); + if (err != DCM_SUCCESS) { + dcm_error("Failed to initialize scan thread global variable! err: %d", err); + goto DCM_SVC_SCAN_CREATE_SCAN_THREAD_FAILED; + } + + /* Create TCP Socket to receive message from main thread */ + err = DcmIpcUtils::createSocket(&socket_fd, DCM_IPC_PORT_SCAN_RECV); + if (err != DCM_SUCCESS) { + dcm_error("Failed to create socket! err: %d", err); + goto DCM_SVC_SCAN_CREATE_SCAN_THREAD_FAILED; + } + dcm_sec_warn("scan thread recv socket: %d", socket_fd); + + /* Create a new main context for scan thread */ + context = g_main_context_new(); + dcmScanSvc.scan_thread_main_context = context; + + /* Create a new main event loop */ + dcmScanSvc.g_scan_thread_mainloop = g_main_loop_new(context, FALSE); + + /* Create a new channel to watch TCP socket */ + channel = g_io_channel_unix_new(socket_fd); + source = g_io_create_watch(channel, G_IO_IN); + + /* Attach channel to main context in scan thread */ + g_source_set_callback(source, (GSourceFunc) DcmScanCallback::readMsg, (gpointer) &dcmScanSvc, NULL); + g_source_attach(source, context); + + /* Create a idle after scan thread is ready */ + scan_thread_ready_idle = g_idle_source_new(); + g_source_set_callback(scan_thread_ready_idle, DcmScanCallback::readyScanThreadIdle, (gpointer) dcmManSvc, NULL); + g_source_attach(scan_thread_ready_idle, context); + + /* Push main context to scan thread */ + g_main_context_push_thread_default(context); + + dcm_debug("********************************************"); + dcm_debug("*** DCM Service scan thread is running ***"); + dcm_debug("********************************************"); + + /* Start to run main event loop for scan thread */ + g_main_loop_run(dcmScanSvc.g_scan_thread_mainloop); + + dcm_debug("*** DCM Service scan thread will be closed ***"); + + /* Destroy IO channel */ + g_io_channel_shutdown(channel, FALSE, NULL); + g_io_channel_unref(channel); + + /* Close the TCP socket */ + close(socket_fd); + + /* Descrease the reference count of main loop of scan thread */ + g_main_loop_unref(dcmScanSvc.g_scan_thread_mainloop); + dcmScanSvc.g_scan_thread_mainloop = NULL; + +DCM_SVC_SCAN_CREATE_SCAN_THREAD_FAILED: + + err = dcmScanSvc.finalize(); + if (err != DCM_SUCCESS) { + dcm_error("Failed to de-initialize scan thread global variable! err: %d", err); + } + + return FALSE; +} + diff --git a/svc/CMakeLists.txt b/svc/CMakeLists.txt new file mode 100755 index 0000000..fe59a47 --- /dev/null +++ b/svc/CMakeLists.txt @@ -0,0 +1,22 @@ +SET(fw_name "dcm-service") +SET(DCM_SERVER "dcm-svc") + +INCLUDE(FindPkgConfig) +pkg_check_modules(${DCM_SERVER} REQUIRED dlog glib-2.0 gthread-2.0 libmedia-utils libexif libtzplatform-config sqlite3) + +FOREACH(flag ${${DCM_SERVER}_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE -Wall") +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--hash-style=both -Wl,-Bsymbolic") + +aux_source_directory(. sources) +FOREACH(src ${sources}) + GET_FILENAME_COMPONENT(src_name ${src} NAME_WE) + MESSAGE("${src_name}") + ADD_EXECUTABLE(${DCM_SERVER} ${src}) + TARGET_LINK_LIBRARIES(${DCM_SERVER} ${fw_name} ${${DCM_SERVER}_LDFLAGS}) +ENDFOREACH() + +INSTALL(TARGETS ${DCM_SERVER} DESTINATION bin) diff --git a/svc/DcmMainSvc.cpp b/svc/DcmMainSvc.cpp new file mode 100755 index 0000000..cc2b792 --- /dev/null +++ b/svc/DcmMainSvc.cpp @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#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; +} -- 2.34.1