Support media bridge as source module 95/251695/12
authorJeongmo Yang <jm80.yang@samsung.com>
Wed, 7 Apr 2021 12:05:40 +0000 (21:05 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Fri, 23 Apr 2021 08:13:07 +0000 (17:13 +0900)
[Version] 0.4.54
[Issue Type] New feature

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

index 814978e..00ec3e9 100644 (file)
@@ -22,6 +22,7 @@
 #define __TIZEN_MULTIMEDIA_CAMERA_PRIVATE_H__
 #include <glib.h>
 #include <camera_internal.h>
+#include <media_bridge_internal.h>
 #include <muse_core.h>
 #include <muse_camera.h>
 #include <mm_display_interface.h>
@@ -49,13 +50,6 @@ extern "C" {
        param.value_size = size; \
 }
 
-#define PREVIEW_CB_TYPE_USER 0x0000000F
-#define PREVIEW_CB_TYPE_EVAS 0x000000F0
-
-#define CHECK_PREVIEW_CB(cb_info, cb_type) ((cb_info)->preview_cb_flag & cb_type)
-#define SET_PREVIEW_CB_TYPE(cb_info, cb_type) ((cb_info)->preview_cb_flag |= cb_type)
-#define UNSET_PREVIEW_CB_TYPE(cb_info, cb_type) ((cb_info)->preview_cb_flag &= ~cb_type)
-
 #define CAM_LOG_CRITICAL(format, args...) \
        do { \
                if (_camera_get_log_level() >= CAMERA_LOG_LEVEL_CRITICAL) \
@@ -161,14 +155,14 @@ typedef struct _camera_cb_info_s {
        media_format_h pkt_fmt;
        GMutex mp_data_mutex;
 
-       /* preview callback flag */
-       int preview_cb_flag;
+       /* preview */
        camera_pixel_format_e preview_format;
 
        /* display */
        muse_camera_display_info_s dp_info;
        mm_display_interface_h dp_interface;
        gboolean run_evas_render;
+       gboolean is_evas_render;
 
        /* get values */
        gint get_int[MUSE_CAMERA_GET_INT_NUM];
@@ -176,6 +170,10 @@ typedef struct _camera_cb_info_s {
        gchar get_string[MUSE_CAMERA_GET_STRING_NUM][MUSE_CAMERA_MSG_MAX_LENGTH];
        gdouble get_geotag[3];
        gint get_display_roi_area[4];
+
+       /* media bridge */
+       media_bridge_h bridge;
+       GMutex bridge_lock;
 } camera_cb_info_s;
 
 typedef struct _camera_message_s {
index 33937e1..873a88c 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-camera
 Summary:    A Camera API
-Version:    0.4.53
+Version:    0.4.54
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index 6a6c0e1..f318ef3 100644 (file)
@@ -327,9 +327,11 @@ static void __camera_event_handler_preview(camera_cb_info_s *cb_info, char *recv
        /* make media packet with below cases.
         * 1. media_packet_preview_cb is set
         * 2. EVAS display rendering
+        * 3. media bridge is set
         */
        if (cb_info->user_cb[MUSE_CAMERA_EVENT_TYPE_MEDIA_PACKET_PREVIEW] ||
-               CHECK_PREVIEW_CB(cb_info, PREVIEW_CB_TYPE_EVAS)) {
+               cb_info->is_evas_render ||
+               cb_info->bridge) {
                ret = __camera_media_packet_data_create(ret_fd, tfd, num_buffer_fd, bo, buffer_bo, data_bo, &mp_data);
                if (ret != CAMERA_ERROR_NONE) {
                        CAM_LOG_ERROR("__camera_media_packet_data_create failed[0x%x]", ret);
@@ -353,7 +355,7 @@ static void __camera_event_handler_preview(camera_cb_info_s *cb_info, char *recv
        }
 
        /* 2. call evas renderer */
-       if (CHECK_PREVIEW_CB(cb_info, PREVIEW_CB_TYPE_EVAS)) {
+       if (cb_info->is_evas_render) {
                if (cb_info->run_evas_render) {
                        media_packet_ref(pkt);
                        ret = mm_display_interface_evas_render(cb_info->dp_interface, pkt);
@@ -366,6 +368,20 @@ static void __camera_event_handler_preview(camera_cb_info_s *cb_info, char *recv
                }
        }
 
+       /* 3. media bridge */
+       g_mutex_lock(&cb_info->bridge_lock);
+
+       if (cb_info->bridge) {
+               media_packet_ref(pkt);
+               ret = media_bridge_push_packet(cb_info->bridge, pkt);
+               if (ret != MEDIA_BRIDGE_ERROR_NONE) {
+                       CAM_LOG_ERROR("push packet to bridge failed[0x%x]", ret);
+                       media_packet_unref(pkt);
+               }
+       }
+
+       g_mutex_unlock(&cb_info->bridge_lock);
+
 _PREVIEW_CB_HANDLER_DONE:
        /* send PREVIEW_CB_RETURN message if zero copy buffer is used(num_buffer_fd is bigger than 0)
           and preview callback(normal or media packet) is set. */
@@ -2075,6 +2091,7 @@ static camera_cb_info_s *__camera_client_callback_new(gint sockfd)
 
        g_mutex_init(&cb_info->fd_lock);
        g_mutex_init(&cb_info->mp_data_mutex);
+       g_mutex_init(&cb_info->bridge_lock);
 
        for (i = 0 ; i < MUSE_CAMERA_EVENT_TYPE_NUM ; i++)
                g_mutex_init(&cb_info->user_cb_mutex[i]);
@@ -2101,7 +2118,6 @@ static camera_cb_info_s *__camera_client_callback_new(gint sockfd)
        }
 
        cb_info->fd = sockfd;
-       cb_info->preview_cb_flag = 0;
 
        /* message receive thread */
        g_atomic_int_set(&cb_info->msg_recv_running, 1);
@@ -2131,6 +2147,7 @@ ErrorExit:
 
                g_mutex_clear(&cb_info->fd_lock);
                g_mutex_clear(&cb_info->mp_data_mutex);
+               g_mutex_clear(&cb_info->bridge_lock);
 
                for (i = 0 ; i < MUSE_CAMERA_API_MAX ; i++) {
                        g_mutex_clear(&cb_info->api_mutex[i]);
@@ -2168,6 +2185,7 @@ static void __camera_client_callback_destroy(camera_cb_info_s *cb_info)
 
        g_mutex_clear(&cb_info->fd_lock);
        g_mutex_clear(&cb_info->mp_data_mutex);
+       g_mutex_clear(&cb_info->bridge_lock);
 
        for (i = 0 ; i < MUSE_CAMERA_API_MAX ; i++) {
                g_mutex_clear(&cb_info->api_mutex[i]);
@@ -2193,8 +2211,6 @@ static void __camera_client_callback_destroy(camera_cb_info_s *cb_info)
                cb_info->dp_interface = NULL;
        }
 
-       cb_info->preview_cb_flag = 0;
-
        g_free(cb_info);
 }
 
@@ -2210,7 +2226,7 @@ int _camera_start_evas_rendering(camera_h camera)
 
        CAM_LOG_INFO("start");
 
-       if (!CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) {
+       if (!pc->cb_info->is_evas_render) {
                CAM_LOG_ERROR("EVAS surface is not set");
                return CAMERA_ERROR_NONE;
        }
@@ -2234,7 +2250,7 @@ int _camera_stop_evas_rendering(camera_h camera, bool keep_screen)
 
        CAM_LOG_INFO("stop - keep screen %d", keep_screen);
 
-       if (!CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) {
+       if (!pc->cb_info->is_evas_render) {
                CAM_LOG_ERROR("EVAS surface is not set");
                return CAMERA_ERROR_NONE;
        }
@@ -2518,7 +2534,6 @@ int camera_change_device(camera_h camera, camera_device_e device)
                        pc->cb_info->user_cb[i] = NULL;
                        pc->cb_info->user_data[i] = NULL;
                }
-               UNSET_PREVIEW_CB_TYPE(pc->cb_info, PREVIEW_CB_TYPE_USER);
        }
 
        return ret;
@@ -2594,7 +2609,7 @@ int camera_start_preview(camera_h camera)
                _camera_msg_send(api, NULL, pc->cb_info, &ret, CAMERA_CB_NO_TIMEOUT);
        }
 
-       if (ret == CAMERA_ERROR_NONE && CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) {
+       if (ret == CAMERA_ERROR_NONE && pc->cb_info->is_evas_render) {
                ret = _camera_start_evas_rendering(camera);
                if (ret != CAMERA_ERROR_NONE) {
                        CAM_LOG_ERROR("stop preview because of error");
@@ -2623,7 +2638,7 @@ int camera_stop_preview(camera_h camera)
        CAM_LOG_INFO("Enter");
 
 //LCOV_EXCL_START
-       if (CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) {
+       if (pc->cb_info->is_evas_render) {
                ret = camera_get_state(camera, &current_state);
                if (ret != CAMERA_ERROR_NONE) {
                        CAM_LOG_ERROR("failed to get current state 0x%x", ret);
@@ -3094,10 +3109,8 @@ int _camera_set_display(camera_h camera, mm_display_type_e type, void *display)
 
        _camera_msg_send_param1(api, cb_info, &ret, &param, CAMERA_CB_TIMEOUT);
 
-       if (ret == CAMERA_ERROR_NONE) {
-               if (type == MM_DISPLAY_TYPE_EVAS)
-                       SET_PREVIEW_CB_TYPE(cb_info, PREVIEW_CB_TYPE_EVAS);
-       }
+       if (ret == CAMERA_ERROR_NONE)
+               cb_info->is_evas_render = (type == MM_DISPLAY_TYPE_EVAS) ? TRUE : FALSE;
 
        return ret;
 }
@@ -3124,7 +3137,7 @@ int camera_set_preview_resolution(camera_h camera, int width, int height)
                return CAMERA_ERROR_INVALID_PARAMETER;
        }
 
-       if (CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) {
+       if (pc->cb_info->is_evas_render) {
                ret = camera_get_state(camera, &current_state);
                if (ret != CAMERA_ERROR_NONE) {
                        CAM_LOG_ERROR("failed to get current state 0x%x", ret);
@@ -3273,7 +3286,7 @@ int camera_set_display_rotation(camera_h camera, camera_rotation_e rotation)
                return CAMERA_ERROR_INVALID_PARAMETER;
        }
 
-       if (CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) {
+       if (pc->cb_info->is_evas_render) {
                ret = mm_display_interface_evas_set_rotation(pc->cb_info->dp_interface, rotation);
                if (ret != MM_ERROR_NONE) {
                        CAM_LOG_ERROR("failed to set rotation for evas surface 0x%x", ret);
@@ -3320,7 +3333,7 @@ int camera_set_display_flip(camera_h camera, camera_flip_e flip)
                return CAMERA_ERROR_INVALID_PARAMETER;
        }
 
-       if (CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) {
+       if (pc->cb_info->is_evas_render) {
                ret = mm_display_interface_evas_set_flip(pc->cb_info->dp_interface, flip);
                if (ret != MM_ERROR_NONE) {
                        CAM_LOG_ERROR("failed to set flip for evas surface 0x%x", ret);
@@ -3367,7 +3380,7 @@ int camera_set_display_visible(camera_h camera, bool visible)
                return CAMERA_ERROR_INVALID_PARAMETER;
        }
 
-       if (CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) {
+       if (pc->cb_info->is_evas_render) {
                ret = mm_display_interface_evas_set_visible(pc->cb_info->dp_interface, visible);
                if (ret != MM_ERROR_NONE) {
                        CAM_LOG_ERROR("failed to set visible for evas surface 0x%x", ret);
@@ -3414,7 +3427,7 @@ int camera_set_display_mode(camera_h camera, camera_display_mode_e mode)
                return CAMERA_ERROR_INVALID_PARAMETER;
        }
 
-       if (CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) {
+       if (pc->cb_info->is_evas_render) {
                ret = mm_display_interface_evas_set_mode(pc->cb_info->dp_interface, mode);
                if (ret != MM_ERROR_NONE) {
                        CAM_LOG_ERROR("failed to set geometry for evas surface 0x%x", ret);
@@ -3613,8 +3626,6 @@ int camera_set_preview_cb(camera_h camera, camera_preview_cb callback, void *use
                pc->cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_PREVIEW] = user_data;
 
                g_mutex_unlock(&pc->cb_info->user_cb_mutex[MUSE_CAMERA_EVENT_TYPE_PREVIEW]);
-
-               SET_PREVIEW_CB_TYPE(pc->cb_info, PREVIEW_CB_TYPE_USER);
        }
 
        CAM_LOG_INFO("ret : 0x%x", ret);
@@ -3645,8 +3656,6 @@ int camera_unset_preview_cb(camera_h camera)
                pc->cb_info->user_data[MUSE_CAMERA_EVENT_TYPE_PREVIEW] = NULL;
 
                g_mutex_unlock(&pc->cb_info->user_cb_mutex[MUSE_CAMERA_EVENT_TYPE_PREVIEW]);
-
-               UNSET_PREVIEW_CB_TYPE(pc->cb_info, PREVIEW_CB_TYPE_USER);
        }
 
        CAM_LOG_INFO("ret : 0x%x", ret);
@@ -6503,7 +6512,7 @@ int camera_attr_set_display_roi_area(camera_h camera, int x, int y, int width, i
 
        CAM_LOG_INFO("Enter");
 
-       if (CHECK_PREVIEW_CB(pc->cb_info, PREVIEW_CB_TYPE_EVAS)) {
+       if (pc->cb_info->is_evas_render) {
                ret = mm_display_interface_evas_set_roi_area(pc->cb_info->dp_interface, x, y, width, height);
                if (ret != MM_ERROR_NONE) {
                        CAM_LOG_ERROR("mm_evas_renderer_set_roi_area error 0x%x", ret);
@@ -6750,6 +6759,78 @@ _DONE:
 }
 
 
+int camera_media_bridge_set_bridge(camera_h camera, media_bridge_h bridge)
+{
+       int ret = CAMERA_ERROR_NONE;
+       camera_cli_s *pc = (camera_cli_s *)camera;
+       muse_camera_api_e api = MUSE_CAMERA_API_SET_MEDIA_BRIDGE;
+
+       if (!pc || !pc->cb_info) {
+               CAM_LOG_ERROR("NULL handle");
+               return CAMERA_ERROR_INVALID_PARAMETER;
+       }
+
+       g_mutex_lock(&pc->cb_info->bridge_lock);
+
+       if (pc->cb_info->bridge) {
+               CAM_LOG_ERROR("media bridge[%p] is already set", pc->cb_info->bridge);
+               ret = CAMERA_ERROR_INVALID_OPERATION;
+               goto _SET_MEDIA_BRIDGE_DONE;
+       }
+
+       _camera_msg_send(api, NULL, pc->cb_info, &ret, CAMERA_CB_TIMEOUT);
+       if (ret != CAMERA_ERROR_NONE) {
+               CAM_LOG_ERROR("set media bridge failed[0x%x]", ret);
+               goto _SET_MEDIA_BRIDGE_DONE;
+       }
+
+       pc->cb_info->bridge = bridge;
+
+       CAM_LOG_INFO("[%p] set media bridge[%p]", camera, bridge);
+
+_SET_MEDIA_BRIDGE_DONE:
+       g_mutex_unlock(&pc->cb_info->bridge_lock);
+
+       return ret;
+}
+
+
+int camera_media_bridge_unset_bridge(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_MEDIA_BRIDGE;
+
+       if (!pc || !pc->cb_info) {
+               CAM_LOG_ERROR("NULL handle");
+               return CAMERA_ERROR_INVALID_PARAMETER;
+       }
+
+       g_mutex_lock(&pc->cb_info->bridge_lock);
+
+       if (!pc->cb_info->bridge) {
+               CAM_LOG_ERROR("no media bridge");
+               ret = CAMERA_ERROR_INVALID_OPERATION;
+               goto _UNSET_MEDIA_BRIDGE_DONE;
+       }
+
+       _camera_msg_send(api, NULL, pc->cb_info, &ret, CAMERA_CB_TIMEOUT);
+       if (ret != CAMERA_ERROR_NONE) {
+               CAM_LOG_ERROR("unset media bridge failed[0x%x]", ret);
+               goto _UNSET_MEDIA_BRIDGE_DONE;
+       }
+
+       CAM_LOG_INFO("[%p] unset media bridge[%p]", camera, pc->cb_info->bridge);
+
+       pc->cb_info->bridge = NULL;
+
+_UNSET_MEDIA_BRIDGE_DONE:
+       g_mutex_unlock(&pc->cb_info->bridge_lock);
+
+       return ret;
+}
+
+
 int _camera_get_log_level(void)
 {
        return g_camera_log_level;
index 1d69566..fb08d50 100644 (file)
@@ -32,6 +32,7 @@
 #include <Elementary.h>
 #include <appcore-efl.h>
 #include <tbm_surface.h>
+#include <media_bridge_internal.h>
 
 /*-----------------------------------------------------------------------
 |    GLOBAL VARIABLE DEFINITIONS:                                       |
@@ -73,6 +74,8 @@ static struct timeval previous_time;
 static struct timeval current_time;
 static struct timeval result_time;
 
+static media_bridge_h bridge;
+
 /*-----------------------------------------------------------------------
 |    GLOBAL CONSTANT DEFINITIONS:                                       |
 -----------------------------------------------------------------------*/
@@ -395,6 +398,15 @@ static gboolean mode_change(gchar buf);
 int camcordertest_set_attr_int(const char* attr_subcategory, int value);
 
 
+static void __release_media_bridge()
+{
+       if (bridge) {
+               media_bridge_unset_source(bridge); /* not mandatory, it will be done in media_bridge_destroy() */
+               media_bridge_destroy(bridge);
+               bridge = NULL;
+       }
+}
+
 static inline void flush_stdin()
 {
        int ch;
@@ -895,6 +907,7 @@ static void print_menu()
                g_print("\t     'K' Video-stabilization \n");
                g_print("\t     'u' Touch AF area \n");
                g_print("\t     'n' Set file path to write captured image\n");
+               g_print("\t     'm' Set media bridge\n");
                g_print("\t     'b' back\n");
                g_print("\t=======================================\n");
                break;
@@ -980,6 +993,8 @@ static void main_menu(gchar buf)
                camera_unset_media_packet_preview_cb(hcamcorder->camera);
                break;
        case 'b': /* back */
+               __release_media_bridge();
+
                camera_stop_preview(hcamcorder->camera);
                camera_destroy(hcamcorder->camera);
                hcamcorder->camera = NULL;
@@ -1007,6 +1022,7 @@ static void setting_menu(gchar buf)
        int width = 0;
        int height = 0;
        int result = 0;
+       int set_bridge = 0;
 
        switch (buf) {
        /* Camera setting */
@@ -1455,6 +1471,24 @@ static void setting_menu(gchar buf)
                        g_print("\nset file path failed\n");
                }
                break;
+       case 'm': /* media bridge */
+               g_print("* Media Bridge !\n");
+               g_print("\tSet[1] or Unset[Others] :");
+               err = scanf("%d", &set_bridge);
+               flush_stdin();
+               if (set_bridge == 1) {
+                       __release_media_bridge();
+
+                       err = media_bridge_create(&bridge);
+                       err |= media_bridge_set_source(bridge, MEDIA_BRIDGE_MODULE_CAMERA, hcamcorder->camera);
+               } 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);
+               break;
        case 'b': /* back */
                hcamcorder->menu_state = MENU_STATE_MAIN;
                break;