From 9dea013aaf654e1c346bf5dab57dbd0e97490742 Mon Sep 17 00:00:00 2001 From: Hyunil Date: Wed, 12 May 2021 20:19:47 +0900 Subject: [PATCH] [0.3.144] Add PLAYER_DISPLAY_OVERLAY_SYNC_UI type for sync UI and video - player_set_display could get wayland tizen exported shell handle with new type - Display related function set as PLAYER_DISPLAY_OVERLAY cannot be used except for visible and PLAYER_ERROR_NOT_AVAILABLE is returned if they are used - Add sample function to player_test with move, resize and transform - Video is always rendered at full scale inside tizen exported shell Change-Id: I61c20cb7e124d16a86b0a11dbd941f6ae693b7d8 Signed-off-by: Hyunil --- include/player.h | 16 +++++++++ packaging/capi-media-player.spec | 3 +- src/player.c | 48 +++++++++++++++++++++++++-- test/CMakeLists.txt | 2 +- test/player_test.c | 72 ++++++++++++++++++++++++++++++++++++++-- 5 files changed, 134 insertions(+), 7 deletions(-) diff --git a/include/player.h b/include/player.h index 9dd3bde..815bf36 100644 --- a/include/player.h +++ b/include/player.h @@ -110,11 +110,22 @@ typedef enum { /** * @brief Enumeration for display type. * @since_tizen @if WEARABLE 2.3.1 @else 2.3 @endif + * @details In case of using #PLAYER_DISPLAY_TYPE_OVERLAY_SYNC_UI, the video is rendering in full scale in the rendering area.\n + * To change the video rendering position, use UI API functions like ecore_wl2_subsurface_exported_surface_move(), + * ecore_wl2_subsurface_exported_surface_resize(), ecore_wl2_subsurface_exported_surface_transform_set(), + * ecore_wl2_subsurface_exported_surface_show() and ecore_wl2_subsurface_exported_surface_commit().\n + * player_set_display_mode(), player_set_display_rotation() and player_set_display_roi_area() cannot be used and + * #PLAYER_ERROR_NOT_AVAILABLE is returned if they are used.\n + * Exported shell handle must be obtained by ecore_wl2_subsurface_exported_surface_handle_get() from Ecore_Wl2_Subsurface.\n + * Then the exported shell handle should be set with player_set_display().\n + * To render the first video buffer, commit by ecore_wl2_window_commit() after player_prepare() of Ecore_Wl2_Subsurface.\n + * Always commit with ecore_wl2_window_commit() with parent surface when the UI changes and the video needs to be synchronized. */ typedef enum { PLAYER_DISPLAY_TYPE_OVERLAY = 0, /**< Overlay surface display */ PLAYER_DISPLAY_TYPE_EVAS = 3, /**< Evas image object surface display (Since 4.0) */ PLAYER_DISPLAY_TYPE_NONE = 4, /**< This disposes of buffers (Since 4.0) */ + PLAYER_DISPLAY_TYPE_OVERLAY_SYNC_UI = 5 /**< Overlay surface display for synchronization between UI and video (Since 6.5) */ } player_display_type_e; /** @@ -1398,6 +1409,7 @@ int player_get_media_stream_buffer_min_threshold(player_h player, player_stream_ * @retval #PLAYER_ERROR_NONE Successful * @retval #PLAYER_ERROR_INVALID_PARAMETER Invalid parameter * @retval #PLAYER_ERROR_INVALID_OPERATION Invalid operation + * @retval #PLAYER_ERROR_NOT_AVAILABLE Not available (Since 6.5) * @see #player_display_mode_e * @see player_set_display() * @see player_get_display_mode() @@ -1415,6 +1427,7 @@ int player_set_display_mode(player_h player, player_display_mode_e mode); * @retval #PLAYER_ERROR_NONE Successful * @retval #PLAYER_ERROR_INVALID_PARAMETER Invalid parameter * @retval #PLAYER_ERROR_INVALID_OPERATION Invalid operation + * @retval #PLAYER_ERROR_NOT_AVAILABLE Not available (Since 6.5) * @see #player_display_mode_e * @see player_set_display_mode() */ @@ -1437,6 +1450,7 @@ int player_get_display_mode(player_h player, player_display_mode_e *mode); * @retval #PLAYER_ERROR_NONE Successful * @retval #PLAYER_ERROR_INVALID_PARAMETER Invalid parameter * @retval #PLAYER_ERROR_INVALID_OPERATION Invalid operation + * @retval #PLAYER_ERROR_NOT_AVAILABLE Not available (Since 6.5) * @see player_set_display() * @see player_set_display_mode() */ @@ -1486,6 +1500,7 @@ int player_is_display_visible(player_h player, bool *visible); * @retval #PLAYER_ERROR_NONE Successful * @retval #PLAYER_ERROR_INVALID_PARAMETER Invalid parameter * @retval #PLAYER_ERROR_INVALID_OPERATION Invalid operation + * @retval #PLAYER_ERROR_NOT_AVAILABLE Not available (Since 6.5) * @see #player_display_rotation_e * @see player_set_display() * @see player_get_display_rotation() @@ -1502,6 +1517,7 @@ int player_set_display_rotation(player_h player, player_display_rotation_e rotat * @retval #PLAYER_ERROR_NONE Successful * @retval #PLAYER_ERROR_INVALID_PARAMETER Invalid parameter * @retval #PLAYER_ERROR_INVALID_OPERATION Invalid operation + * @retval #PLAYER_ERROR_NOT_AVAILABLE Not available (Since 6.5) * @see #player_display_rotation_e * @see player_set_display_rotation() */ diff --git a/packaging/capi-media-player.spec b/packaging/capi-media-player.spec index 1d5880a..bad51bf 100644 --- a/packaging/capi-media-player.spec +++ b/packaging/capi-media-player.spec @@ -1,6 +1,6 @@ Name: capi-media-player Summary: A Media Player API -Version: 0.3.143 +Version: 0.3.144 Release: 0 Group: Multimedia/API License: Apache-2.0 @@ -18,6 +18,7 @@ BuildRequires: pkgconfig(tizen-extension-client) BuildRequires: pkgconfig(appcore-efl) BuildRequires: pkgconfig(elementary) BuildRequires: pkgconfig(ecore) +BuildRequires: pkgconfig(ecore-wl2) BuildRequires: pkgconfig(evas) BuildRequires: pkgconfig(capi-media-tool) BuildRequires: pkgconfig(mmsvc-player) diff --git a/src/player.c b/src/player.c index 90686b2..461f6bb 100644 --- a/src/player.c +++ b/src/player.c @@ -176,8 +176,6 @@ static bool _player_get_param_value(char *buf, ...) char *param_name = NULL; void *value = NULL; - LOGE("ENTER"); - void *jobj = muse_core_msg_object_new(buf, NULL, &err); if (!jobj) { @@ -3027,6 +3025,9 @@ int _player_convert_display_type(player_display_type_e type, mm_display_type_e * case PLAYER_DISPLAY_TYPE_OVERLAY: *out_type = MM_DISPLAY_TYPE_OVERLAY; break; + case PLAYER_DISPLAY_TYPE_OVERLAY_SYNC_UI: + *out_type = MM_DISPLAY_TYPE_OVERLAY_SYNC_UI; + break; case PLAYER_DISPLAY_TYPE_EVAS: *out_type = MM_DISPLAY_TYPE_EVAS; break; @@ -3094,7 +3095,9 @@ int player_set_display(player_h player, player_display_type_e type, player_displ return PLAYER_ERROR_INVALID_OPERATION; } - if (conv_type == MM_DISPLAY_TYPE_EVAS) { + if (conv_type == MM_DISPLAY_TYPE_OVERLAY_SYNC_UI) { + g_strlcpy(wl_win.exported_shell_handle, (char *)display, MAX_EXPORTED_SHELL_HANDLE_LEN); + } else if (conv_type == MM_DISPLAY_TYPE_EVAS) { /* before evas handle is created, user could set display information */ player_display_mode_e mode = PLAYER_DISPLAY_MODE_LETTER_BOX; player_display_rotation_e rotation = PLAYER_DISPLAY_ROTATION_NONE; @@ -3168,6 +3171,11 @@ int player_set_display_mode(player_h player, player_display_mode_e mode) PLAYER_GET_DISPLAY_TYPE(pc, display_type); + if (display_type == MM_DISPLAY_TYPE_OVERLAY_SYNC_UI) { + LOGE("Function is not available in MM_DISPLAY_TYPE_OVERLAY_SYNC_UI type"); + return PLAYER_ERROR_NOT_AVAILABLE; + } + if (display_type == MM_DISPLAY_TYPE_EVAS) { mm_ret = mm_display_interface_evas_set_mode(DP_INTERFACE(pc), mode); if (mm_ret != MM_ERROR_NONE) { @@ -3190,12 +3198,20 @@ int player_get_display_mode(player_h player, player_display_mode_e *pmode) player_cli_s *pc = (player_cli_s *)player; char *ret_buf = NULL; int mode = -1; + mm_display_type_e display_type = MM_DISPLAY_TYPE_NONE; PLAYER_INSTANCE_CHECK(player); PLAYER_NULL_ARG_CHECK(pmode); LOGD("ENTER"); + PLAYER_GET_DISPLAY_TYPE(pc, display_type); + + if (display_type == MM_DISPLAY_TYPE_OVERLAY_SYNC_UI) { + LOGE("Function is not available in MM_DISPLAY_TYPE_OVERLAY_SYNC_UI type"); + return PLAYER_ERROR_NOT_AVAILABLE; + } + PLAYER_SEND_MSG(api, pc, ret_buf, ret); if (ret == PLAYER_ERROR_NONE) { @@ -3223,6 +3239,11 @@ int player_set_video_roi_area(player_h player, double x_scale, double y_scale, PLAYER_GET_DISPLAY_TYPE(pc, display_type); + if (display_type == MM_DISPLAY_TYPE_OVERLAY_SYNC_UI) { + LOGE("Function is not available in MM_DISPLAY_TYPE_OVERLAY_SYNC_UI type"); + return PLAYER_ERROR_NOT_AVAILABLE; + } + if (display_type == MM_DISPLAY_TYPE_EVAS) { LOGE("Display type is EVAS, video display interface is not supported"); return PLAYER_ERROR_INVALID_OPERATION; @@ -3251,8 +3272,16 @@ int player_get_video_roi_area(player_h player, double *x_scale, double *y_scale, player_cli_s *pc = (player_cli_s *)player; char *ret_buf = NULL; double scale_x = 0, scale_y = 0, scale_w = 0, scale_h = 0; + mm_display_type_e display_type = MM_DISPLAY_TYPE_NONE; PLAYER_INSTANCE_CHECK(player); + PLAYER_GET_DISPLAY_TYPE(pc, display_type); + + if (display_type == MM_DISPLAY_TYPE_OVERLAY_SYNC_UI) { + LOGE("Function is not available in MM_DISPLAY_TYPE_OVERLAY_SYNC_UI type"); + return PLAYER_ERROR_NOT_AVAILABLE; + } + PLAYER_NULL_ARG_CHECK(x_scale && y_scale && w_scale && h_scale); PLAYER_SEND_MSG(api, pc, ret_buf, ret); @@ -3365,6 +3394,11 @@ int player_set_display_rotation(player_h player, player_display_rotation_e rotat PLAYER_GET_DISPLAY_TYPE(pc, display_type); + if (display_type == MM_DISPLAY_TYPE_OVERLAY_SYNC_UI) { + LOGE("Function is not available in MM_DISPLAY_TYPE_OVERLAY_SYNC_UI type"); + return PLAYER_ERROR_NOT_AVAILABLE; + } + if (display_type == MM_DISPLAY_TYPE_EVAS) { mm_ret = mm_display_interface_evas_set_rotation(DP_INTERFACE(pc), rotation); if (mm_ret != MM_ERROR_NONE) { @@ -3387,8 +3421,16 @@ int player_get_display_rotation(player_h player, player_display_rotation_e *prot muse_player_api_e api = MUSE_PLAYER_API_GET_DISPLAY_ROTATION; char *ret_buf = NULL; int rotation = -1; + mm_display_type_e display_type = MM_DISPLAY_TYPE_NONE; PLAYER_INSTANCE_CHECK(player); + PLAYER_GET_DISPLAY_TYPE(pc, display_type); + + if (display_type == MM_DISPLAY_TYPE_OVERLAY_SYNC_UI) { + LOGE("Function is not available in MM_DISPLAY_TYPE_OVERLAY_SYNC_UI type"); + return PLAYER_ERROR_NOT_AVAILABLE; + } + PLAYER_NULL_ARG_CHECK(protation); LOGD("ENTER"); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f805e0b..e0f2570 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -11,7 +11,7 @@ INCLUDE_DIRECTORIES(event-handler/include) link_directories(${CMAKE_SOURCE_DIR}/../) INCLUDE(FindPkgConfig) -pkg_check_modules(${fw_test} REQUIRED libudev libinput capi-system-info appcore-efl elementary ecore evas capi-media-sound-manager) +pkg_check_modules(${fw_test} REQUIRED libudev libinput capi-system-info appcore-efl elementary ecore ecore-wl2 evas capi-media-sound-manager) FOREACH(flag ${${fw_test}_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") ENDFOREACH(flag) diff --git a/test/player_test.c b/test/player_test.c index 2ba5f3e..1543532 100644 --- a/test/player_test.c +++ b/test/player_test.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #ifdef _ACTIVATE_EOM_ @@ -196,6 +197,8 @@ static Evas_Object *g_external_win_id; static Evas_Object *selected_win_id; static Evas_Object *g_eo[MAX_HANDLE] = { 0, }; +static Ecore_Wl2_Subsurface *g_ecore_wl2_subsurface = NULL; +static Ecore_Wl2_Window *g_ecore_wl2_window = NULL; static int g_current_surface_type = -1; typedef struct { @@ -554,6 +557,16 @@ static int app_create(void *data) return 0; } +static void __ecore_wl2_subsurface_del(Ecore_Wl2_Subsurface *ecore_wl2_subsurface) +{ + if (!ecore_wl2_subsurface) { + g_print("ecore_wl2_subsurface is NULL\n"); + return; + } + ecore_wl2_subsurface_del(ecore_wl2_subsurface); + ecore_wl2_subsurface = NULL; +} + static int app_terminate(void *data) { appdata *ad = data; @@ -569,6 +582,9 @@ static int app_terminate(void *data) g_eo[i] = NULL; } } + + __ecore_wl2_subsurface_del(g_ecore_wl2_subsurface); + if (g_win_id) { evas_object_del(g_win_id); g_win_id = NULL; @@ -1087,6 +1103,11 @@ static void _player_prepare(bool async) if (is_es_push_mode) pthread_create(&g_feed_video_thread_id, NULL, (void *)feed_video_data_thread_func, NULL); + if (g_current_surface_type == PLAYER_DISPLAY_TYPE_OVERLAY_SYNC_UI && + g_ecore_wl2_subsurface && g_ecore_wl2_window) { + ecore_wl2_window_commit(g_ecore_wl2_window, EINA_TRUE); + } + #ifdef USE_EVENT_HANDLER event_handler_set_dov_fov(); #endif @@ -1213,6 +1234,7 @@ static void _player_play() { int bRet = FALSE; int i = 0; + if (g_current_surface_type == PLAYER_DISPLAY_TYPE_OVERLAY) { #ifdef _ACTIVATE_EOM_ /* for checking external display.... */ @@ -1782,6 +1804,8 @@ static void change_surface(int option) { player_display_type_e surface_type = 0; int ret = PLAYER_ERROR_NONE; + Eina_Bool res = EINA_FALSE; + const char *exported_shell_handle = NULL; #ifdef _ACTIVATE_EOM_ int hdmi_output_id; eom_output_mode_e output_mode; @@ -1790,7 +1814,7 @@ static void change_surface(int option) case 0: /* X surface */ surface_type = PLAYER_DISPLAY_TYPE_OVERLAY; - g_print("change surface type to X\n"); + g_print("change surface type to OVERLAY\n"); break; case 1: /* EVAS surface */ @@ -1802,11 +1826,43 @@ static void change_surface(int option) surface_type = g_current_surface_type = PLAYER_DISPLAY_TYPE_NONE; player_set_display(g_player[0], PLAYER_DISPLAY_TYPE_NONE, NULL); break; + case 3: + g_print("change surface type to OVERLAY_SYNC_UI\n"); + surface_type = g_current_surface_type = PLAYER_DISPLAY_TYPE_OVERLAY_SYNC_UI; + Ecore_Wl2_Window *ecore_wl2_win = (Ecore_Wl2_Window *)elm_win_wl_window_get(g_win_id); + Ecore_Wl2_Subsurface *ecore_wl2_subsurface = ecore_wl2_subsurface_new(ecore_wl2_win); + g_ecore_wl2_window = ecore_wl2_win; + + res = ecore_wl2_subsurface_export(ecore_wl2_subsurface); + if (res != EINA_TRUE) { + g_print("failed to export foreign shell"); + return; + } + exported_shell_handle = ecore_wl2_subsurface_exported_surface_handle_get(ecore_wl2_subsurface); + if (!exported_shell_handle) { + g_print("failed to get exported foreign shell handle"); + return; + } + // Enables or disables exported surface synchronization for a given subsurface (default: EINA_TRUE) + ecore_wl2_subsurface_exported_surface_sync_set(ecore_wl2_subsurface, EINA_TRUE); + // If NULL is used, exported subsurface is placed under exported surface + ecore_wl2_subsurface_exported_surface_place_below(ecore_wl2_subsurface, NULL); + ecore_wl2_subsurface_exported_surface_move(ecore_wl2_subsurface, 200, 200); + ecore_wl2_subsurface_exported_surface_resize(ecore_wl2_subsurface, 500, 500); + ecore_wl2_subsurface_exported_surface_show(ecore_wl2_subsurface); + ecore_wl2_subsurface_exported_surface_commit(ecore_wl2_subsurface); + g_ecore_wl2_subsurface = ecore_wl2_subsurface; + player_set_display(g_player[0], PLAYER_DISPLAY_TYPE_OVERLAY_SYNC_UI, GET_DISPLAY(exported_shell_handle)); + + return; default: g_print("invalid surface type\n"); return; } + if (surface_type != PLAYER_DISPLAY_TYPE_OVERLAY_SYNC_UI && g_ecore_wl2_subsurface) + __ecore_wl2_subsurface_del(g_ecore_wl2_subsurface); + player_state_e player_state = PLAYER_STATE_NONE; ret = player_get_state(g_player[0], &player_state); if (ret) @@ -1898,6 +1954,15 @@ static void set_display_roi_area(int x, int y, int width, int height) static void set_display_rotation(int rotation) { + if (g_ecore_wl2_subsurface) { + g_print("set_display_rotation (%d)\n", rotation); + ecore_wl2_subsurface_exported_surface_transform_set(g_ecore_wl2_subsurface, rotation); + ecore_wl2_subsurface_exported_surface_show(g_ecore_wl2_subsurface); + ecore_wl2_subsurface_exported_surface_commit(g_ecore_wl2_subsurface); + ecore_wl2_window_commit(g_ecore_wl2_window, EINA_TRUE); + return; + } + if (player_set_display_rotation(g_player[0], rotation) != PLAYER_ERROR_NONE) g_print("failed to set_display_rotation\n"); #ifdef USE_EVENT_HANDLER @@ -1909,6 +1974,9 @@ static void set_display_rotation(int rotation) static void get_display_rotation() { player_display_rotation_e rotation = 0; + if (g_ecore_wl2_subsurface) + return; + player_get_display_rotation(g_player[0], &rotation); #ifdef USE_EVENT_HANDLER g_rotation = (player_display_rotation_e) rotation; @@ -2584,7 +2652,7 @@ static void displaymenu() } else if (g_menu_state == CURRENT_STATUS_LOOPING) { g_print("*** input looping value.(0: Not Looping, 1: Looping) \n"); } else if (g_menu_state == CURRENT_STATUS_DISPLAY_SURFACE_CHANGE) { - g_print("*** input display surface type.(0: Wayland surface, 1: EVAS surface, 2: No use surface (e.g: audio playback)) \n"); + g_print("*** input display surface type.(0: Wayland surface, 1: EVAS surface, 2: No use surface (e.g: audio playback)) 3: Wayland surface(foreign shell)\n"); } else if (g_menu_state == CURRENT_STATUS_EXPORT_VIDEO_FRAME) { g_print("*** set video_decoded_cb (0: none, 1: set cb) \n"); } else if (g_menu_state == CURRENT_STATUS_DISPLAY_MODE) { -- 2.7.4