Add new internal APIs for extra preview 54/257554/2
authorJeongmo Yang <jm80.yang@samsung.com>
Mon, 19 Apr 2021 08:16:44 +0000 (17:16 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Wed, 28 Apr 2021 09:30:44 +0000 (18:30 +0900)
[Version] 0.4.55
[Issue Type] New feature

Change-Id: I2c48a36eb958642b99bcb7ec18ce900399868c76
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
include/camera_internal.h
packaging/capi-media-camera.spec
src/camera.c
src/camera_internal.c
test/camera_test.c

index 46a1aae..7f37ecf 100644 (file)
@@ -82,6 +82,7 @@ typedef struct _camera_stream_data_s {
        void *internal_buffer;          /**< Internal buffer pointer */
        int stride[BUFFER_MAX_PLANE_NUM];    /**< Stride of each plane */
        int elevation[BUFFER_MAX_PLANE_NUM]; /**< Elevation of each plane */
+       int extra_stream_id;            /**< ID of extra preview stream */
 } camera_stream_data_s;
 
 
@@ -117,6 +118,20 @@ typedef void (*camera_device_list_changed_cb)(camera_device_list_s *list, void *
 
 /**
  * @internal
+ * @brief Called to register for notifications about delivering a copy of the new extra preview frames.
+ * @since_tizen 6.5
+ * @param[in] frame     The reference pointer to extra preview stream data
+ * @param[in] stream_id The id of stream
+ * @param[in] user_data The user data passed from the callback registration function
+ * @pre camera_start_preview() will invoke this callback function if you register this callback using camera_set_extra_preview_cb().
+ * @see camera_start_preview()
+ * @see camera_set_extra_preview_cb()
+ * @see camera_unset_extra_preview_cb()
+ */
+typedef void (*camera_extra_preview_cb)(camera_preview_data_s *frame, int stream_id, void *user_data);
+
+/**
+ * @internal
  * @brief Start the evas rendering.
  * @since_tizen 3.0
  * @param[in] camera The handle to the camera
@@ -332,6 +347,37 @@ int camera_attr_get_flash_brightness(camera_h camera, int *level);
 int camera_attr_get_flash_brightness_range(camera_h camera, int *min, int *max);
 
 /**
+ * @internal
+ * @brief Registers a callback function to be called for extra preview frames.
+ * @since_tizen 6.5
+ * @param[in] camera    The handle to the camera
+ * @param[in] callback  The callback function to be registered
+ * @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 #CAMERA_ERROR_NONE Successful
+ * @retval #CAMERA_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #CAMERA_ERROR_SERVICE_DISCONNECTED The socket to multimedia server is disconnected
+ * @pre The camera state must be set to #CAMERA_STATE_CREATED or #CAMERA_STATE_PREVIEW.
+ * @see camera_start_preview()
+ * @see camera_unset_extra_preview_cb()
+ * @see camera_extra_preview_cb()
+ */
+int camera_set_extra_preview_cb(camera_h camera, camera_extra_preview_cb callback, void *user_data);
+
+/**
+ * @internal
+ * @brief Unregisters the callback function.
+ * @since_tizen 6.5
+ * @param[in] camera The handle to the camera
+ * @return @c 0 on success, otherwise a negative error value
+ * @retval #CAMERA_ERROR_NONE Successful
+ * @retval #CAMERA_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #CAMERA_ERROR_SERVICE_DISCONNECTED The socket to multimedia server is disconnected
+ * @see camera_set_extra_preview_cb()
+ */
+int camera_unset_extra_preview_cb(camera_h camera);
+
+/**
  * @}
  */
 #ifdef __cplusplus
index 873a88c..9261581 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-camera
 Summary:    A Camera API
-Version:    0.4.54
+Version:    0.4.55
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index f318ef3..258101e 100644 (file)
@@ -317,13 +317,26 @@ static void __camera_event_handler_preview(camera_cb_info_s *cb_info, char *recv
        }
 
        /* preview callback */
-       if (cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_PREVIEW]) {
+       if (cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_PREVIEW] ||
+               cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_EXTRA_PREVIEW]) {
                camera_create_preview_frame(stream, num_buffer_fd, buffer_bo_handle, &data_bo_handle, &frame);
 
-               ((camera_preview_cb)cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_PREVIEW])(&frame,
-                       cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_PREVIEW]);
+               if (cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_PREVIEW] &&
+                       stream->extra_stream_id < 0) {
+                       ((camera_preview_cb)cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_PREVIEW])(&frame,
+                               cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_PREVIEW]);
+               }
+
+               if (cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_EXTRA_PREVIEW] &&
+                       stream->extra_stream_id >= 0) {
+                       ((camera_extra_preview_cb)cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_EXTRA_PREVIEW])(&frame,
+                               stream->extra_stream_id, cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_EXTRA_PREVIEW]);
+               }
        }
 
+       if (stream->extra_stream_id >= 0)
+               goto _PREVIEW_CB_HANDLER_DONE;
+
        /* make media packet with below cases.
         * 1. media_packet_preview_cb is set
         * 2. EVAS display rendering
index 234e6a9..ab2b4f1 100644 (file)
@@ -433,4 +433,64 @@ int camera_attr_get_flash_brightness_range(camera_h camera, int *min, int *max)
 
        return ret;
 }
+
+
+int camera_set_extra_preview_cb(camera_h camera, camera_extra_preview_cb callback, void *user_data)
+{
+       int ret = CAMERA_ERROR_NONE;
+       camera_cli_s *pc = (camera_cli_s *)camera;
+       muse_camera_api_e api = MUSE_CAMERA_API_SET_EXTRA_PREVIEW_CB;
+
+       if (!pc || !pc->cb_info || !callback) {
+               CAM_LOG_ERROR("NULL pointer %p %p", pc, callback);
+               return CAMERA_ERROR_INVALID_PARAMETER;
+       }
+
+       CAM_LOG_INFO("Enter");
+
+       _camera_msg_send(api, NULL, pc->cb_info, &ret, CAMERA_CB_TIMEOUT);
+
+       if (ret == CAMERA_ERROR_NONE) {
+               g_mutex_lock(&pc->cb_info->user_cb_mutex[MUSE_CAMERA_EVENT_TYPE_EXTRA_PREVIEW]);
+
+               pc->cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_EXTRA_PREVIEW] = callback;
+               pc->cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_EXTRA_PREVIEW] = user_data;
+
+               g_mutex_unlock(&pc->cb_info->user_cb_mutex[MUSE_CAMERA_EVENT_TYPE_EXTRA_PREVIEW]);
+       }
+
+       CAM_LOG_INFO("ret : 0x%x", ret);
+
+       return ret;
+}
+
+
+int camera_unset_extra_preview_cb(camera_h camera)
+{
+       int ret = CAMERA_ERROR_NONE;
+       camera_cli_s *pc = (camera_cli_s *)camera;
+       muse_camera_api_e api = MUSE_CAMERA_API_UNSET_EXTRA_PREVIEW_CB;
+
+       if (!pc || !pc->cb_info) {
+               CAM_LOG_ERROR("NULL handle");
+               return CAMERA_ERROR_INVALID_PARAMETER;
+       }
+
+       CAM_LOG_INFO("Enter");
+
+       _camera_msg_send(api, NULL, pc->cb_info, &ret, CAMERA_CB_TIMEOUT);
+
+       if (ret == CAMERA_ERROR_NONE) {
+               g_mutex_lock(&pc->cb_info->user_cb_mutex[MUSE_CAMERA_EVENT_TYPE_EXTRA_PREVIEW]);
+
+               pc->cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_EXTRA_PREVIEW] = NULL;
+               pc->cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_EXTRA_PREVIEW] = NULL;
+
+               g_mutex_unlock(&pc->cb_info->user_cb_mutex[MUSE_CAMERA_EVENT_TYPE_EXTRA_PREVIEW]);
+       }
+
+       CAM_LOG_INFO("ret : 0x%x", ret);
+
+       return ret;
+}
 //LCOV_EXCL_STOP
index fb08d50..4cd0b99 100644 (file)
@@ -67,8 +67,9 @@ static camera_device_e camera_device;
 static GTimer *timer;
 static int g_camera_device_state_changed_cb_id;
 static int g_camera_device_list_changed_cb_id;
-static int g_camera_preview_cb_file_write;
-static int g_camera_mp_preview_cb_file_write;
+static int g_camera_preview_cb_dump;
+static int g_camera_extra_preview_cb_dump;
+static int g_camera_mp_preview_cb_dump;
 
 static struct timeval previous_time;
 static struct timeval current_time;
@@ -96,6 +97,7 @@ static media_bridge_h bridge;
 -----------------------------------------------------------------------*/
 #define DEFAULT_FILE_PATH               "/home/owner/media"
 #define PREVIEW_CB_DUMP_FILE_NAME       "preview.data"
+#define EXTRA_PREVIEW_CB_DUMP_FILE_NAME "extra_preview.data"
 #define MP_PREVIEW_CB_DUMP_FILE_NAME    "mp_preview.data"
 #define MAX_FILE_NAME_LENGTH            256
 #define MAX_FILE_PATH_LENGTH            (MAX_FILE_NAME_LENGTH - 20)
@@ -499,41 +501,21 @@ static void _camera_interrupt_started_cb(camera_policy_e policy, camera_state_e
        return;
 }
 
-void _camera_preview_cb(camera_preview_data_s *frame, void *user_data)
+static void _dump_preview_data(camera_preview_data_s *frame, const char *file_name)
 {
-       char preview_dump[MAX_FILE_NAME_LENGTH] = {'\0',};
+       char dump_path[MAX_FILE_NAME_LENGTH] = {'\0',};
        FILE *fp = NULL;
 
        if (!frame) {
-               g_print("\n[PREVIEW_CB] NULL frame!\n");
+               g_print("\n[DUMP_PREVIEW_DATA] NULL frame\n");
                return;
        }
 
-       g_print("[PREVIEW_CB] preview callback - format[%d] res[%dx%d] num plane[%d] ",
-               frame->format, frame->width, frame->height, frame->num_of_planes);
+       snprintf(dump_path, MAX_FILE_NAME_LENGTH, "%s/%s", DEFAULT_FILE_PATH, file_name);
 
-       if (frame->num_of_planes == 1) {
-               g_print("size YUV[%d]\n",
-                       frame->data.single_plane.size);
-       } else if (frame->num_of_planes == 2) {
-               g_print("size Y[%d] UV[%d]\n",
-                       frame->data.double_plane.y_size,
-                       frame->data.double_plane.uv_size);
-       } else if (frame->num_of_planes == 3) {
-               g_print("size Y[%d] U[%d] V[%d]\n",
-                       frame->data.triple_plane.y_size,
-                       frame->data.triple_plane.u_size,
-                       frame->data.triple_plane.v_size);
-       }
-
-       if (!g_camera_preview_cb_file_write)
-               return;
-
-       snprintf(preview_dump, MAX_FILE_NAME_LENGTH, "%s/%s", DEFAULT_FILE_PATH, PREVIEW_CB_DUMP_FILE_NAME);
-
-       fp = fopen(preview_dump, "a");
+       fp = fopen(dump_path, "a");
        if (fp == NULL) {
-               g_print("\n[PREVIEW_CB] file[%s] open failed\n", preview_dump);
+               g_print("\n[DUMP_PREVIEW_DATA] file[%s] open failed\n", dump_path);
                return;
        }
 
@@ -563,11 +545,66 @@ void _camera_preview_cb(camera_preview_data_s *frame, void *user_data)
                }
        }
 
-       g_print("[PREVIEW_CB] file[%s] write done\n", preview_dump);
+       g_print("[DUMP_PREVIEW_DATA] file[%s] write done\n", dump_path);
 
        fclose(fp);
 }
 
+static void _camera_print_preview_info(camera_preview_data_s *frame)
+{
+       if (!frame) {
+               g_print("\n[PREVIEW_CB] NULL frame!\n");
+               return;
+       }
+
+       g_print("format[%d] res[%dx%d] num plane[%d] ",
+               frame->format, frame->width, frame->height, frame->num_of_planes);
+
+       if (frame->num_of_planes == 1) {
+               g_print("size [%d]\n",
+                       frame->data.single_plane.size);
+       } else if (frame->num_of_planes == 2) {
+               g_print("size Y[%d] UV[%d]\n",
+                       frame->data.double_plane.y_size,
+                       frame->data.double_plane.uv_size);
+       } else if (frame->num_of_planes == 3) {
+               g_print("size Y[%d] U[%d] V[%d]\n",
+                       frame->data.triple_plane.y_size,
+                       frame->data.triple_plane.u_size,
+                       frame->data.triple_plane.v_size);
+       }
+}
+
+static void _camera_preview_cb(camera_preview_data_s *frame, void *user_data)
+{
+       if (!frame) {
+               g_print("\n[PREVIEW_CB] NULL frame!\n");
+               return;
+       }
+
+       g_print("[PREVIEW_CB] preview callback - ");
+
+       _camera_print_preview_info(frame);
+
+       if (g_camera_preview_cb_dump)
+               _dump_preview_data(frame, PREVIEW_CB_DUMP_FILE_NAME);
+}
+
+static void _camera_extra_preview_cb(camera_preview_data_s *frame, int stream_id, void *user_data)
+{
+       if (!frame) {
+               g_print("\n[PREVIEW_CB] NULL frame!\n");
+               return;
+       }
+
+       g_print("[EXTRA_PREVIEW_CB][stream_id:%d] preview callback - ", stream_id);
+
+       _camera_print_preview_info(frame);
+
+       if (g_camera_extra_preview_cb_dump)
+               _dump_preview_data(frame, EXTRA_PREVIEW_CB_DUMP_FILE_NAME);
+}
+
 
 static void _camera_media_packet_preview_cb(media_packet_h pkt, void *user_data)
 {
@@ -575,7 +612,7 @@ static void _camera_media_packet_preview_cb(media_packet_h pkt, void *user_data)
        int width = 0;
        int height = 0;
        unsigned int i = 0;
-       char mp_preview_dump[MAX_FILE_NAME_LENGTH] = {'\0',};
+       char mp_dump_path[MAX_FILE_NAME_LENGTH] = {'\0',};
        FILE *fp = NULL;
        media_format_h fmt = NULL;
        media_format_mimetype_e type = MEDIA_FORMAT_I420;
@@ -616,12 +653,11 @@ static void _camera_media_packet_preview_cb(media_packet_h pkt, void *user_data)
        g_print("                tbm surface [%dx%d], total size[%u]\n",
                s_info.width, s_info.height, s_info.size);
 
-       if (g_camera_mp_preview_cb_file_write) {
-               snprintf(mp_preview_dump, MAX_FILE_NAME_LENGTH, "%s/%s", DEFAULT_FILE_PATH, MP_PREVIEW_CB_DUMP_FILE_NAME);
-
-               fp = fopen(mp_preview_dump, "a");
+       if (g_camera_mp_preview_cb_dump) {
+               snprintf(mp_dump_path, MAX_FILE_NAME_LENGTH, "%s/%s", DEFAULT_FILE_PATH, MP_PREVIEW_CB_DUMP_FILE_NAME);
+               fp = fopen(mp_dump_path, "a");
                if (fp == NULL) {
-                       g_print("\n[MP_PREVIEW_CB] file[%s] open failed ====\n", mp_preview_dump);
+                       g_print("\n[MP_PREVIEW_CB] file[%s] open failed ====\n", mp_dump_path);
                        goto _MEDIA_PACKET_PREVIEW_CB_OUT;
                }
        }
@@ -834,10 +870,9 @@ static void print_menu()
                g_print("\t   '2' Multishot test\n");
                g_print("\t   '3' Setting\n");
                g_print("\t   '4' Change device (CAMERA0 <-> CAMERA1)\n");
-               g_print("\t   '5' Set preview callback\n");
-               g_print("\t   '6' Unset preview callback\n");
-               g_print("\t   '7' Set media packet preview callback\n");
-               g_print("\t   '8' Unset media packet preview callback\n");
+               g_print("\t   '5' Set/Unset preview callback\n");
+               g_print("\t   '6' Set/Unset extra preview callback\n");
+               g_print("\t   '7' Set/Unset media packet preview callback\n");
                g_print("\t   'b' back\n");
                g_print("\t=======================================\n");
                break;
@@ -927,6 +962,7 @@ static void main_menu(gchar buf)
        int err = 0;
        int interval = 0;
        int count = 0;
+       int set_cb = 0;
 
        switch (buf) {
        case '1': /* Capture */
@@ -975,22 +1011,49 @@ static void main_menu(gchar buf)
                camera_start_preview(hcamcorder->camera);
                break;
        case '5':
-               g_print("\n\tWrite preview data to file(0:NO, Others:YES) : ");
-               err = scanf("%d", &g_camera_preview_cb_file_write);
+               g_print("* Preview Callback\n");
+               g_print("\tUnset[0] / Set[Others] :");
+               err = scanf("%d", &set_cb);
                flush_stdin();
-               camera_set_preview_cb(hcamcorder->camera, _camera_preview_cb, hcamcorder->camera);
+               if (set_cb) {
+                       g_print("\n\tDump preview data to file - NO[0], YES[Others] : ");
+                       err = scanf("%d", &g_camera_preview_cb_dump);
+                       flush_stdin();
+                       err = camera_set_preview_cb(hcamcorder->camera, _camera_preview_cb, hcamcorder->camera);
+               } else {
+                       err = camera_unset_preview_cb(hcamcorder->camera);
+               }
+               g_print("\tresult[0x%x]\n\n", err);
                break;
        case '6':
-               camera_unset_preview_cb(hcamcorder->camera);
+               g_print("* Extra Preview Callback\n");
+               g_print("\tUnset[0] / Set[Others] :");
+               err = scanf("%d", &set_cb);
+               flush_stdin();
+               if (set_cb) {
+                       g_print("\n\tDump extra preview data to file - NO[0], YES[Others] : ");
+                       err = scanf("%d", &g_camera_extra_preview_cb_dump);
+                       flush_stdin();
+                       err = camera_set_extra_preview_cb(hcamcorder->camera, _camera_extra_preview_cb, hcamcorder->camera);
+               } else {
+                       err = camera_unset_extra_preview_cb(hcamcorder->camera);
+               }
+               g_print("\tresult[0x%x]\n\n", err);
                break;
        case '7':
-               g_print("\n\tWrite preview data to file(0:NO, Others:YES) : ");
-               err = scanf("%d", &g_camera_mp_preview_cb_file_write);
+               g_print("* Media Packet Preview Callback\n");
+               g_print("\tUnset[0] / Set[Others] :");
+               err = scanf("%d", &set_cb);
                flush_stdin();
-               camera_set_media_packet_preview_cb(hcamcorder->camera, _camera_media_packet_preview_cb, hcamcorder->camera);
-               break;
-       case '8':
-               camera_unset_media_packet_preview_cb(hcamcorder->camera);
+               if (set_cb) {
+                       g_print("\n\tDump media packet preview data to file - NO[0], YES[Others] : ");
+                       err = scanf("%d", &g_camera_mp_preview_cb_dump);
+                       flush_stdin();
+                       err = camera_set_media_packet_preview_cb(hcamcorder->camera, _camera_media_packet_preview_cb, hcamcorder->camera);
+               } else {
+                       err = camera_unset_media_packet_preview_cb(hcamcorder->camera);
+               }
+               g_print("\tresult[0x%x]\n\n", err);
                break;
        case 'b': /* back */
                __release_media_bridge();
@@ -1473,10 +1536,10 @@ static void setting_menu(gchar buf)
                break;
        case 'm': /* media bridge */
                g_print("* Media Bridge !\n");
-               g_print("\tSet[1] or Unset[Others] :");
+               g_print("\tUnset[0] / Set[Others] :");
                err = scanf("%d", &set_bridge);
                flush_stdin();
-               if (set_bridge == 1) {
+               if (set_bridge) {
                        __release_media_bridge();
 
                        err = media_bridge_create(&bridge);
@@ -1484,10 +1547,7 @@ static void setting_menu(gchar buf)
                } else {
                        __release_media_bridge();
                }
-               if (err != 0)
-                       g_print("Failed to set/unset[%d] media bridge[%x]\n", set_bridge, err);
-               else
-                       g_print("Succeed to set/unset[%d] media bridge\n", set_bridge);
+               g_print("\tresult[0x%x]\n\n", err);
                break;
        case 'b': /* back */
                hcamcorder->menu_state = MENU_STATE_MAIN;