From f502f9116ff94bb06750ee247164300f4baa2242 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Wed, 7 Apr 2021 21:05:40 +0900 Subject: [PATCH] Support media bridge as source module [Version] 0.4.54 [Issue Type] New feature Change-Id: Ibdc78bc0812feb78dd74d4e55e2d3bb91d9a8d06 Signed-off-by: Jeongmo Yang --- include/camera_private.h | 16 +++-- packaging/capi-media-camera.spec | 2 +- src/camera.c | 129 +++++++++++++++++++++++++++++++-------- test/camera_test.c | 34 +++++++++++ 4 files changed, 147 insertions(+), 34 deletions(-) diff --git a/include/camera_private.h b/include/camera_private.h index 814978e..00ec3e9 100644 --- a/include/camera_private.h +++ b/include/camera_private.h @@ -22,6 +22,7 @@ #define __TIZEN_MULTIMEDIA_CAMERA_PRIVATE_H__ #include #include +#include #include #include #include @@ -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 { diff --git a/packaging/capi-media-camera.spec b/packaging/capi-media-camera.spec index 33937e1..873a88c 100644 --- a/packaging/capi-media-camera.spec +++ b/packaging/capi-media-camera.spec @@ -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 diff --git a/src/camera.c b/src/camera.c index 6a6c0e1..f318ef3 100644 --- a/src/camera.c +++ b/src/camera.c @@ -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, ¤t_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, ¶m, 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, ¤t_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; diff --git a/test/camera_test.c b/test/camera_test.c index 1d69566..fb08d50 100644 --- a/test/camera_test.c +++ b/test/camera_test.c @@ -32,6 +32,7 @@ #include #include #include +#include /*----------------------------------------------------------------------- | 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; -- 2.7.4