Enable DCM on-demand 38/75638/1
authorJiyong Min <jiyong.min@samsung.com>
Tue, 21 Jun 2016 00:52:42 +0000 (09:52 +0900)
committerJiyong Min <jiyong.min@samsung.com>
Tue, 21 Jun 2016 00:53:09 +0000 (09:53 +0900)
Change-Id: Iaf41d16050a6cad779427f6db254471c7d31a14e
Signed-off-by: Jiyong Min <jiyong.min@samsung.com>
CMakeLists.txt
doc/media_content_doc.h
include/media_content_type.h
include/media_info.h
include/media_info_private.h
packaging/capi-content-media-content.spec
src/media_info.c
test/CMakeLists.txt
test/media-content_test.c

index 845a360..9d8dec9 100755 (executable)
@@ -9,7 +9,7 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX})
 SET(INC_DIR include)
 INCLUDE_DIRECTORIES(${INC_DIR})
 
-SET(dependents "dlog libmedia-service media-thumbnail libmedia-utils capi-base-common vconf cynara-client cynara-creds-socket cynara-session")
+SET(dependents "dlog libmedia-service media-thumbnail libmedia-utils capi-base-common capi-system-info vconf cynara-client cynara-creds-socket cynara-session")
 SET(pc_dependents "dlog capi-base-common")
 
 INCLUDE(FindPkgConfig)
index dc39a40..18f9c8b 100755 (executable)
  *
  */
 
+/**
+ * @defgroup CAPI_CONTENT_MEDIA_FACE_DETECTION_MODULE Face Detection
+ * @brief The Face Detection API provides functions to detect face information about stored image files.
+ *
+ * @ingroup CAPI_CONTENT_MEDIA_INFO_MODULE
+ *
+ * @section CAPI_CONTENT_MEDIA_FACE_DETECTION_MODULE_HEADER Required Header
+ *   \#include <media_content.h>
+ *
+ * @section CAPI_CONTENT_MEDIA_FACE_DETECTION_MODULE_FEATURE Related Features
+ * This API is related with the following feature: \n
+ * - %http://tizen.org/feature/vision.face_recognition
+ * It is recommended to create applications with regard to features, to increase reliability. \n
+ *
+ * You can check if a device supports the related features for this API by using @ref CAPI_SYSTEM_SYSTEM_INFO_MODULE, thereby controlling the procedure of your application. \n
+ *
+ * To ensure your application is only running on a device with specific features, please define the features in your manifest file using the manifest editor in the SDK. \n
+ *
+ * More details on featuring your application can be found from <a href="https://developer.tizen.org/development/getting-started/native-application/understanding-tizen-programming/application-filtering"><b>Feature Element</b>.</a>
+ *
+ * @section CAPI_CONTENT_MEDIA_FACE_DETECTION_MODULE_OVERVIEW Overview
+ * The Face Detection API provides functions to detect face information associated with image files. \n
+ * Face information detected by mediavision API. To detect faces, you should use media_info_start_face_detection() API. \n
+ *
+ * API allows to:
+ * - start and cancel face detection with image files
+ *
+ *<p>
+ * To obtain the media handle (#media_info_h), call the #media_info_create() function.\n
+ * To start face detection, call the #media_info_start_face_detection() function.\n
+ * To cancel face detection after it's been started, call the #media_info_cancel_face_detection() function.\n
+ *
+ */
 
 /**
  * @defgroup CAPI_CONTENT_MEDIA_BOOKMARK_MODULE Media Bookmark
index 5757cb0..b774b94 100755 (executable)
@@ -148,6 +148,7 @@ typedef enum {
        MEDIA_CONTENT_ERROR_DB_BUSY                 = MEDIA_CONTENT_ERROR_CLASS | 0x02,    /**< DB operation BUSY */
        MEDIA_CONTENT_ERROR_NETWORK                 = MEDIA_CONTENT_ERROR_CLASS | 0x03,    /**< Network Fail */
        MEDIA_CONTENT_ERROR_UNSUPPORTED_CONTENT     = MEDIA_CONTENT_ERROR_CLASS | 0x04,    /**< Unsupported Content */
+       MEDIA_CONTENT_ERROR_NOT_SUPPORTED           = TIZEN_ERROR_NOT_SUPPORTED,           /**< Not supported */
 } media_content_error_e;
 
 /**
@@ -400,6 +401,32 @@ typedef void (*media_insert_burst_shot_completed_cb)(media_content_error_e error
  */
 typedef void (*media_thumbnail_completed_cb)(media_content_error_e error, const char *path, void *user_data);
 
+/**
+ * @ingroup CAPI_CONTENT_MEDIA_FACE_DETECTION_MODULE
+ * @brief Called when face detection on the image is completed.
+ *
+ * @details The following error codes can be delivered. \n
+ *         #MEDIA_CONTENT_ERROR_NONE, \n
+ *         #MEDIA_CONTENT_ERROR_OUT_OF_MEMORY, \n
+ *         #MEDIA_CONTENT_ERROR_INVALID_OPERATION, \n
+ *         #MEDIA_CONTENT_ERROR_DB_FAILED, \n
+ *         #MEDIA_CONTENT_ERROR_DB_BUSY, \n
+ *         #MEDIA_CONTENT_ERROR_UNSUPPORTED_CONTENT
+ *
+ * @since_tizen 3.0
+ *
+ * @remarks The callback is called in a separate thread(not in the main loop).
+ *
+ * @param[in] error     The error code
+ * @param[in] face_count      The number of all detected faces
+ * @param[in] user_data The user data passed from the foreach function
+ *
+ * @pre media_info_start_face_detection()
+ *
+ * @see media_info_start_face_detection()
+ */
+typedef void (*media_face_detection_completed_cb)(media_content_error_e error, const int face_count, void *user_data);
+
 
 /**
  * @ingroup CAPI_CONTENT_MEDIA_FOLDER_MODULE
index 0f5c838..e101485 100755 (executable)
@@ -1594,7 +1594,7 @@ int media_info_move_to_db(media_info_h media, const char* dst_path);
  * @privlevel public
  * @privilege %http://tizen.org/privilege/content.write
  *
- * @remarks If you want to destory media handle before callback invoked, you must cancel thumbnail request by using media_info_cancel_thumbnail() \n
+ * @remarks If you want to destroy media handle before callback invoked, you must cancel thumbnail request by using media_info_cancel_thumbnail() \n
  *          Since 3.0, if creation of a thumbnail is failed, empty string will be passed through media_thumbnail_completed_cb().
  *          Items in external storage except MMC not supported.
  *
@@ -1645,6 +1645,77 @@ int media_info_create_thumbnail(media_info_h media, media_thumbnail_completed_cb
 int media_info_cancel_thumbnail(media_info_h media);
 
 /**
+ * @ingroup CAPI_CONTENT_MEDIA_FACE_DETECTION_MODULE
+ * @brief Starts face detection for the given image, asynchronously.
+ * @details This function detects faces for given image item and calls the given callback function when the detection is completed. \n
+ *          The given callback function is called when the detection is completed. \n
+ *          To obtain the detected faces, call the media_info_foreach_face_from_db() function.
+ *
+ * @since_tizen 3.0
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/content.write \n
+ *                   %http://tizen.org/privilege/mediastorage
+ *
+ * @remarks If you want to destroy the media handle before callback invoked, you must cancel the face detection request by using media_info_cancel_face_detection(). \n
+ *          If face detection fails, the @a face_count argument in media_face_detection_completed_cb() will be set to 0.
+ *          Media items in external storage are not supported, with the exception of MMC items.
+ *
+ * @param[in] media     The media info handle
+ * @param[in] callback  The callback function to be invoked when detection is completed
+ * @param[in] user_data The user data to be passed to the callback function
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ *
+ * @retval #MEDIA_CONTENT_ERROR_NONE              Successful
+ * @retval #MEDIA_CONTENT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTENT_ERROR_OUT_OF_MEMORY     Out of memory
+ * @retval #MEDIA_CONTENT_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #MEDIA_CONTENT_ERROR_DB_FAILED         DB Operation failed
+ * @retval #MEDIA_CONTENT_ERROR_DB_BUSY           DB Operation busy
+ * @retval #MEDIA_CONTENT_ERROR_NETWORK           Network fail
+ * @retval #MEDIA_CONTENT_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MEDIA_CONTENT_ERROR_NOT_SUPPORTED     Not supported
+ *
+ * @pre This function requires opened connection to content service by media_content_connect().
+ *
+ * @see media_content_connect()
+ * @see media_info_cancel_face_detection()
+ */
+int media_info_start_face_detection(media_info_h media, media_face_detection_completed_cb callback, void *user_data);
+
+/**
+ * @ingroup CAPI_CONTENT_MEDIA_FACE_DETECTION_MODULE
+ * @brief Cancels face detection of image for the given media.
+ * @details This function cancels face detection for given media item. \n
+ *          If you cancel face detection request before callback is invoked, the callback registered by media_info_start_face_detection() API will not be invoked.
+ *
+ * @since_tizen 3.0
+ *
+ * @privlevel public
+ * @privilege %http://tizen.org/privilege/content.write
+ *
+ * @remarks If face detection is already done when you request the cancellation, this API return MEDIA_CONTENT_ERROR_INVALID_OPERATION
+ *
+ * @param[in] media The media info handle
+ *
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ *
+ * @retval #MEDIA_CONTENT_ERROR_NONE              Successful
+ * @retval #MEDIA_CONTENT_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #MEDIA_CONTENT_ERROR_PERMISSION_DENIED Permission denied
+ * @retval #MEDIA_CONTENT_ERROR_INVALID_OPERATION Invalid operation
+ *
+ * @pre This function requires opened connection to content service by media_content_connect().
+ *
+ * @see media_content_connect()
+ * @see media_info_start_face_detection()
+ */
+int media_info_cancel_face_detection(media_info_h media);
+
+/**
 * @brief Creates the media info handle.
 * @details If the information about the file that is already known, you can use this API to generate empty handler.
 *          And you can add the information to the generated handler using media_info_set_XXX() API.
index 693c1af..26e87dc 100755 (executable)
@@ -312,6 +312,7 @@ typedef struct {
        char *storage_uuid;
        int sync_status;
        unsigned int request_id;
+       unsigned int face_request_id;
        int is_360;
        image_meta_s *image_meta;
        video_meta_s *video_meta;
@@ -363,6 +364,12 @@ typedef struct {
 } media_thumbnail_cb_s;
 
 typedef struct {
+       media_info_s *handle;
+       void *user_data;
+       media_face_detection_completed_cb face_completed_cb;
+} media_face_cb_s;
+
+typedef struct {
        media_insert_completed_cb insert_completed_cb;
        char *insert_list_path;
        void *user_data;
@@ -642,6 +649,7 @@ typedef struct _media_content_cb_data {
 #define SELECT_MEDIA_COUNT_FROM_MEDIA_BY_ID            "SELECT COUNT(*) FROM "DB_TABLE_MEDIA_VIEW" WHERE media_uuid='%q' AND validity=1"
 #define SELECT_FACE_COUNT_BY_MEDIA_ID          "SELECT COUNT(*) FROM "FACE_MEDIA_JOIN" AND fa.media_uuid='%s'"
 #define SELECT_FACE_LIST_BY_MEDIA_ID           "SELECT fa.face_uuid, fa.media_uuid, fa.face_rect_x, fa.face_rect_y, fa.face_rect_w, fa.face_rect_h, fa.orientation, fa.face_tag FROM "FACE_MEDIA_JOIN" AND fa.media_uuid='%s'"
+#define SELECT_FACE_PATH_FROM_MEDIA            "SELECT path FROM "DB_TABLE_MEDIA_VIEW" media_uuid='%s'"
 
 #define DEFAULT_MEDIA_STORAGE_ID                       "media"
 
index 06fd460..df1e20c 100755 (executable)
@@ -1,6 +1,6 @@
 Name:       capi-content-media-content
 Summary:    A Media content library in Tizen Native API
-Version:    0.2.79
+Version:    0.2.80
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
@@ -9,6 +9,7 @@ Source1001:     capi-content-media-content.manifest
 BuildRequires:  cmake
 BuildRequires:  pkgconfig(dlog)
 BuildRequires:  pkgconfig(capi-base-common)
+BuildRequires:  pkgconfig(capi-system-info)
 BuildRequires:  pkgconfig(libmedia-service)
 BuildRequires:  pkgconfig(media-thumbnail)
 BuildRequires:  pkgconfig(libmedia-utils)
@@ -55,6 +56,7 @@ cp -rf %{_builddir}/%{name}-%{version}/LICENSE.APLv2.0 %{buildroot}/%{_datadir}/
 %{_libdir}/libcapi-content-media-content.so.*
 #License
 %{_datadir}/license/%{name}
+%{_bindir}/*
 
 %files devel
 %manifest %{name}.manifest
index 7d4577e..c3b9364 100755 (executable)
 
 #include <media_info.h>
 #include <media-thumbnail.h>
+#include <media-util-dcm.h>
 #include <media_info_private.h>
 #include <media_util_private.h>
+#include <system_info.h>
 
 static void __media_info_insert_completed_cb(media_request_result_s *result, void *user_data);
 static void __media_info_thumbnail_completed_cb(int error, const char *path, void *user_data);
+static void __media_info_face_completed_cb(int error, const int face_count, void *user_data);
 static bool __media_info_delete_batch_cb(media_info_h media, void *user_data);
 static int __media_info_insert_batch(media_batch_insert_e insert_type, const char **path_array, unsigned int array_length, media_insert_completed_cb completed_cb, void *user_data);
 
@@ -100,6 +103,38 @@ static void __media_info_thumbnail_completed_cb(int error, const char *path, voi
        return;
 }
 
+static bool __media_info_isFaceRecognition_feature_supported()
+{
+       bool isFaceRecognitionSupported = false;
+
+       const int nRetVal = system_info_get_platform_bool("http://tizen.org/feature/vision.face_recognition", &isFaceRecognitionSupported);
+
+       if (nRetVal != SYSTEM_INFO_ERROR_NONE) {
+               media_content_debug("SYSTEM_INFO_ERROR: vision.face_recognition [%d]", nRetVal);
+               return false;
+       }
+
+       return isFaceRecognitionSupported;
+}
+
+static void __media_info_face_completed_cb(int error, const int face_count, void *user_data)
+{
+       int error_value = MEDIA_CONTENT_ERROR_NONE;
+
+       media_face_cb_s *_face_cb = (media_face_cb_s *)user_data;
+
+       if (_face_cb != NULL) {
+               media_content_debug("error [%d], face_count [%d]", error, face_count);
+               error_value = _content_error_capi(MEDIA_THUMBNAIL_TYPE, error);
+               if (_face_cb->face_completed_cb)
+                       _face_cb->face_completed_cb(error_value, face_count, _face_cb->user_data);
+       }
+
+       SAFE_FREE(_face_cb);
+
+       return;
+}
+
 static bool __media_info_delete_batch_cb(media_info_h media, void *user_data)
 {
        int err = MEDIA_CONTENT_ERROR_NONE;
@@ -819,6 +854,7 @@ int media_info_clone(media_info_h *dst, media_info_h src)
                _dst->played_position = _src->played_position;
                _dst->sync_status = _src->sync_status;
                _dst->request_id = _src->request_id;
+               _dst->face_request_id = _src->face_request_id;
                _dst->is_360 = _src->is_360;
 
                if (_src->media_type == MEDIA_CONTENT_TYPE_IMAGE && _src->image_meta) {
@@ -2590,6 +2626,58 @@ int media_info_cancel_thumbnail(media_info_h media)
        return ret;
 }
 
+int media_info_start_face_detection(media_info_h media, media_face_detection_completed_cb callback, void *user_data)
+{
+       int ret = MEDIA_CONTENT_ERROR_NONE;
+       static unsigned int req_id = 0;
+       media_info_s *_media = (media_info_s*)media;
+
+       if (!__media_info_isFaceRecognition_feature_supported()) {
+               media_content_error("NOT_SUPPORTED(0x%08x)", MEDIA_CONTENT_ERROR_NOT_SUPPORTED);
+               return MEDIA_CONTENT_ERROR_NOT_SUPPORTED;
+       }
+
+       if (_media != NULL && STRING_VALID(_media->media_id) && STRING_VALID(_media->file_path)) {
+               media_face_cb_s *_face_cb = (media_face_cb_s*)calloc(1, sizeof(media_face_cb_s));
+               media_content_retvm_if(_face_cb == NULL, MEDIA_CONTENT_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
+               req_id++;
+               _media->face_request_id = req_id;
+
+               _face_cb->handle = _media;
+               _face_cb->user_data = user_data;
+               _face_cb->face_completed_cb = callback;
+
+               ret = dcm_request_extract_face_async(_media->face_request_id, _media->file_path, (FaceFunc)__media_info_face_completed_cb, (void *)_face_cb, tzplatform_getuid(TZ_USER_NAME));
+               ret = _content_error_capi(MEDIA_THUMBNAIL_TYPE, ret);
+       } else {
+               media_content_error("INVALID_PARAMETER(0x%08x)", MEDIA_CONTENT_ERROR_INVALID_PARAMETER);
+               ret = MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
+       }
+
+       return ret;
+}
+
+int media_info_cancel_face_detection(media_info_h media)
+{
+       int ret = MEDIA_CONTENT_ERROR_NONE;
+       media_info_s *_media = (media_info_s*)media;
+
+       if (!__media_info_isFaceRecognition_feature_supported()) {
+               media_content_error("NOT_SUPPORTED(0x%08x)", MEDIA_CONTENT_ERROR_NOT_SUPPORTED);
+               return MEDIA_CONTENT_ERROR_NOT_SUPPORTED;
+       }
+
+       if (_media != NULL && STRING_VALID(_media->media_id) && STRING_VALID(_media->file_path) && _media->face_request_id > 0) {
+               ret = dcm_request_cancel_face(_media->face_request_id, _media->file_path);
+               ret = _content_error_capi(MEDIA_THUMBNAIL_TYPE, ret);
+       } else {
+               media_content_error("INVALID_PARAMETER(0x%08x)", MEDIA_CONTENT_ERROR_INVALID_PARAMETER);
+               ret = MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
+       }
+
+       return ret;
+}
+
 static int __media_info_map_data_usr_to_svc(media_info_s *media, media_svc_content_info_s **service_content, media_content_storage_e storage_type)
 {
        media_content_retvm_if(media == NULL, MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "Invalid handle");
index af466da..a7e13f9 100755 (executable)
@@ -13,6 +13,8 @@ aux_source_directory(. sources)
 FOREACH(src ${sources})
     GET_FILENAME_COMPONENT(src_name ${src} NAME_WE)
     MESSAGE("${src_name}")
-    ADD_EXECUTABLE(${src_name} ${src})
-    TARGET_LINK_LIBRARIES(${src_name} ${fw_name} ${${fw_test}_LDFLAGS})
+    ADD_EXECUTABLE(${fw_test} ${src})
+    TARGET_LINK_LIBRARIES(${fw_test} ${fw_name} ${${fw_test}_LDFLAGS})
 ENDFOREACH()
+
+INSTALL(TARGETS ${fw_test} DESTINATION bin)
index ae86405..607ab13 100755 (executable)
@@ -877,7 +877,7 @@ int test_filter_create(void)
        int ret = MEDIA_CONTENT_ERROR_NONE;
 
        /* Filter for media */
-       const char *condition = "MEDIA_TYPE=3"; /*MEDIA_TYPE 0-image, 1-video, 2-sound, 3-music, 4-other*/
+       const char *condition = "MEDIA_TYPE=0"; /*MEDIA_TYPE 0-image, 1-video, 2-sound, 3-music, 4-other*/
        /*const char *condition = "MEDIA_TYPE IS NOT 0 AND MEDIA_DESCRIPTION IS NOT NULL"; */   /*MEDIA_TYPE 0-image, 1-video, 2-sound, 3-music, 4-other*/
 
        ret = media_filter_create(&g_filter);
@@ -2467,6 +2467,190 @@ int test_create_thumbnail(int cancel)
        return ret;
 }
 
+bool face_cb(media_face_h face, void *user_data)
+{
+       if (user_data != NULL) {
+               unsigned x, y, rect_w, rect_h;
+               media_face_get_face_rect(face, &x, &y, &rect_w, &rect_h);
+               media_content_debug("face(%p) x = %d, y = %d [%d, %d]", face, x, y, rect_w, rect_h);
+               return TRUE;
+       }
+       return FALSE;
+}
+
+void face_detection_complete_cb(media_content_error_e error, int count, void *user_data)
+{
+       int ret = MEDIA_CONTENT_ERROR_NONE;
+       g_cnt++;
+
+       media_content_debug("=================[%d][%d]", g_media_cnt, g_cnt);
+       media_content_debug("error_code [%d]", error);
+       media_content_debug("face_count [%d]", count);
+       if (count == 0) {
+               media_content_debug("No faces are detected!");
+       } else if (user_data != NULL) {
+               media_info_h media = (media_info_h)user_data;
+               char *media_id = NULL;
+               ret = media_info_get_media_id(media, &media_id);
+               if (ret != MEDIA_CONTENT_ERROR_NONE)
+                       media_content_error("media_info_get_media_id failed: %d", ret);
+               if (media_id != NULL) {
+                       ret = media_info_foreach_face_from_db(media_id, NULL, face_cb, NULL);
+                       if (ret != MEDIA_CONTENT_ERROR_NONE)
+                               media_content_error("media_info_foreach_face_from_db failed: %d", ret);
+               }
+               ret = media_info_destroy(media);
+               if (ret != MEDIA_CONTENT_ERROR_NONE)
+                       media_content_error("media_info_destroy failed: %d", ret);
+       }
+
+       if (g_cnt == g_media_cnt)
+               g_main_loop_quit(g_loop);
+
+       return;
+}
+
+bool start_face_detection_cb(media_info_h media, void *user_data)
+{
+       char *media_id = NULL;
+       media_info_h dst = NULL;
+       int ret = MEDIA_CONTENT_ERROR_NONE;
+
+       if (media == NULL) {
+               media_content_debug("NO Item");
+               return true;
+       }
+
+       ret = media_info_get_media_id(media, &media_id);
+       if (ret != MEDIA_CONTENT_ERROR_NONE)
+               media_content_error("media_info_get_media_id failed: %d", ret);
+       else
+               media_content_debug("media_id : [%s]", media_id);
+
+       ret = media_info_clone(&dst, media);
+       if (ret != MEDIA_CONTENT_ERROR_NONE)
+               media_content_error("media_info_clone failed: %d", ret);
+       else {
+               ret = media_info_start_face_detection(dst, face_detection_complete_cb, dst);
+               if (ret != MEDIA_CONTENT_ERROR_NONE)
+                       media_content_error("media_info_start_face_detection failed: %d", ret);
+       }
+
+       /* fix prevent: Resource leak */
+       SAFE_FREE(media_id);
+
+       return true;
+}
+
+bool cancel_face_detection_cb(media_info_h media, void *user_data)
+{
+       int ret = MEDIA_CONTENT_ERROR_NONE;
+
+       char *media_id = NULL;
+       media_info_h dst = NULL;
+
+       g_cnt++;
+
+       if (media == NULL) {
+               media_content_debug("NO Item");
+               return true;
+       }
+
+       ret = media_info_get_media_id(media, &media_id);
+       if (ret != MEDIA_CONTENT_ERROR_NONE)
+               media_content_error("media_info_get_media_id failed: %d", ret);
+       else
+               media_content_debug("media_id : [%s]", media_id);
+
+       ret = media_info_clone(&dst, media);
+       if (ret != MEDIA_CONTENT_ERROR_NONE)
+               media_content_error("media_info_clone failed: %d", ret);
+
+       ret = media_info_cancel_face_detection(dst);
+       if (ret != MEDIA_CONTENT_ERROR_NONE)
+               media_content_error("media_info_cancel_face_detection failed: %d", ret);
+
+       ret = media_info_destroy(dst);
+       if (ret != MEDIA_CONTENT_ERROR_NONE)
+                       media_content_error("media_info_destroy failed: %d", ret);
+
+       if (g_cnt == g_media_cnt)
+               g_main_loop_quit(g_loop);
+
+       /* fix prevent: Resource leak */
+       SAFE_FREE(media_id);
+
+       return true;
+}
+
+gboolean face_detection_start(gpointer data)
+{
+       int ret = MEDIA_CONTENT_ERROR_NONE;
+
+       ret = media_info_foreach_media_from_db(g_filter, start_face_detection_cb, NULL);
+
+       if (ret == MEDIA_CONTENT_ERROR_NONE)
+               media_content_debug("media_info_foreach_media_from_db is success");
+       else
+               media_content_error("media_info_foreach_media_from_db is failed");
+
+       return false;
+}
+
+gboolean face_detection_cancel(gpointer data)
+{
+       int ret = MEDIA_CONTENT_ERROR_NONE;
+
+       ret = media_info_foreach_media_from_db(g_filter, cancel_face_detection_cb, NULL);
+
+       if (ret == MEDIA_CONTENT_ERROR_NONE)
+               media_content_debug("media_info_foreach_media_from_db is success");
+       else
+               media_content_error("media_info_foreach_media_from_db is failed");
+
+       return false;
+}
+
+int test_start_face_detection(int cancel)
+{
+       int ret = MEDIA_CONTENT_ERROR_NONE;
+       GSource *source = NULL;
+       GMainContext *context = NULL;
+
+       test_filter_create();
+
+       ret = media_info_get_media_count_from_db(g_filter, &g_media_cnt);
+       if (ret != MEDIA_CONTENT_ERROR_NONE)
+               media_content_error("media_info_get_media_count_from_db failed: %d", ret);
+       else
+               media_content_debug("media_count : [%d]", g_media_cnt);
+
+       if (g_media_cnt == 0) {
+               goto END;
+       }
+       g_loop = g_main_loop_new(NULL, FALSE);
+       context = g_main_loop_get_context(g_loop);
+       source = g_idle_source_new();
+       g_source_set_callback(source, face_detection_start, NULL, NULL);
+       g_source_attach(source, context);
+
+       /* Logic to cancel */
+       if (cancel) {
+               GSource *cancel_src = NULL;
+               cancel_src = g_idle_source_new();
+               g_source_set_callback(cancel_src, face_detection_cancel, NULL, NULL);
+               g_source_attach(cancel_src, context);
+       }
+
+       g_main_loop_run(g_loop);
+       g_main_loop_unref(g_loop);
+
+END:
+       test_filter_destroy();
+
+       return ret;
+}
+
 int test_disconnect_database(void)
 {
        int ret = MEDIA_CONTENT_ERROR_NONE;
@@ -3325,6 +3509,10 @@ int main(int argc, char *argv[])
        if (ret != MEDIA_CONTENT_ERROR_NONE)
                return MEDIA_CONTENT_ERROR_NONE;
 
+       ret = test_start_face_detection(FALSE);
+       if (ret != MEDIA_CONTENT_ERROR_NONE)
+               return ret;
+
 #if 0
        ret = test_move();
        if (ret != MEDIA_CONTENT_ERROR_NONE)
@@ -3386,6 +3574,10 @@ int main(int argc, char *argv[])
        if (ret != MEDIA_CONTENT_ERROR_NONE)
                return ret;
 
+       ret = test_extrace_face(TRUE);
+       if (ret != MEDIA_CONTENT_ERROR_NONE)
+               return ret;
+
        ret = test_request_update_db();
        if (ret != MEDIA_CONTENT_ERROR_NONE)
                return ret;