From: Sangchul Lee Date: Tue, 14 Mar 2023 07:36:22 +0000 (+0900) Subject: webrtc_internal: Add webrtc_set_display_surface_id() X-Git-Tag: accepted/tizen/unified/20230405.153341^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fa2cd406491cc7861d0aeaef57fbc296faa5596d;p=platform%2Fcore%2Fapi%2Fwebrtc.git webrtc_internal: Add webrtc_set_display_surface_id() [Version] 0.4.6 [Issue Type] API Change-Id: I8678951f128dcb448645e1032838c4392f9e2a20 Signed-off-by: Sangchul Lee --- diff --git a/include/webrtc_internal.h b/include/webrtc_internal.h index cde362f7..ff3ab116 100644 --- a/include/webrtc_internal.h +++ b/include/webrtc_internal.h @@ -141,6 +141,34 @@ typedef void (*webrtc_signaling_message_cb)(webrtc_signaling_message_type_e type */ int webrtc_set_ecore_wl_display(webrtc_h webrtc, unsigned int track_id, void *ecore_wl_window); +/** + * @internal + * @brief Sets a display surface id to the video track to be rendered. + * @since_tizen 7.5 + * @remarks Call this function within webrtc_track_added_cb(), otherwise #WEBRTC_ERROR_INVALID_OPERATION will be returned.\n + * If webrtc_set_encoded_video_frame_cb() has been called, it will return #WEBRTC_ERROR_INVALID_OPERATION. + * @param[in] webrtc WebRTC handle + * @param[in] track_id The track id + * @param[in] surface_id The display surface id + * @param[in] x The start X coordinate of the display surface + * @param[in] y The start Y coordinate of the display surface + * @param[in] width Width of the display surface + * @param[in] height Height of the display surface + * @return @c 0 on success, + * otherwise a negative error value + * @retval #WEBRTC_ERROR_NONE Successful + * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #WEBRTC_ERROR_INVALID_OPERATION Invalid operation + * @pre webrtc_track_added_cb() must be set by calling webrtc_set_track_added_cb(). + * @see webrtc_set_track_added_cb() + * @see webrtc_unset_track_added_cb() + * @see webrtc_set_display_mode() + * @see webrtc_get_display_mode() + * @see webrtc_set_display_visible() + * @see webrtc_get_display_visible() + */ +int webrtc_set_display_surface_id(webrtc_h webrtc, unsigned int track_id, int surface_id, int x, int y, int width, int height); + /** * @internal * @brief Sets mute to the audio track. diff --git a/include/webrtc_private.h b/include/webrtc_private.h index 08590529..37b2361b 100644 --- a/include/webrtc_private.h +++ b/include/webrtc_private.h @@ -424,6 +424,10 @@ typedef struct _webrtc_display { void *surface; int type; int overlay_surface_id; + int x; + int y; + int w; + int h; GMutex mutex; mm_display_interface_h mm_display; @@ -784,6 +788,7 @@ int _add_rendering_sink_bin(webrtc_s *webrtc, GstPad *src_pad, bool is_audio); int _add_forwarding_sink_bin(webrtc_s *webrtc, GstPad *src_pad, bool is_audio); int _set_stream_info_to_sink(webrtc_s *webrtc, unsigned int track_id, sound_stream_info_h stream_info); int _set_display_to_sink(webrtc_s *webrtc, unsigned int track_id, unsigned int type, void *display); +int _set_display_surface_id_to_sink(webrtc_s *webrtc, unsigned int track_id, int surface_id, int x, int y, int width, int height); int _set_display_mode_to_sink(webrtc_s *webrtc, unsigned int track_id, webrtc_display_mode_e mode); int _get_display_mode_from_sink(webrtc_s *webrtc, unsigned int track_id, webrtc_display_mode_e *mode); int _set_display_visible_to_sink(webrtc_s *webrtc, unsigned int track_id, bool visible); @@ -806,9 +811,10 @@ int _capture_video_frame(webrtc_gst_slot_s *sink); /* display */ void _video_stream_decoded_cb(GstElement *object, GstBuffer *buffer, GstPad *pad, gpointer data); int _apply_display(webrtc_display_s *display); -webrtc_display_s *_alloc_display(void); +webrtc_display_s *_alloc_display(bool use_mm_display); void _release_display(webrtc_display_s *display); void _set_display_type_and_surface(webrtc_display_s *display, webrtc_display_type_e type, void *surface); +void _set_display_surface_id(webrtc_display_s *display, int surface_id, int x, int y, int w, int h); int _set_display_mode(webrtc_display_s *display, webrtc_display_mode_e mode); int _get_display_mode(webrtc_display_s *display, webrtc_display_mode_e *mode); int _set_display_visible(webrtc_display_s *display, bool visible); diff --git a/packaging/capi-media-webrtc.spec b/packaging/capi-media-webrtc.spec index f49b87a5..1252f214 100644 --- a/packaging/capi-media-webrtc.spec +++ b/packaging/capi-media-webrtc.spec @@ -1,6 +1,6 @@ Name: capi-media-webrtc Summary: A WebRTC library in Tizen Native API -Version: 0.4.5 +Version: 0.4.6 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/webrtc_display.c b/src/webrtc_display.c index 9b993eaf..ebc931da 100644 --- a/src/webrtc_display.c +++ b/src/webrtc_display.c @@ -684,6 +684,12 @@ static int __set_overlay_display(webrtc_display_s *display) RET_VAL_IF(display->type != WEBRTC_DISPLAY_TYPE_OVERLAY && display->type != WEBRTC_DISPLAY_TYPE_ECORE_WL, WEBRTC_ERROR_INVALID_OPERATION, "invalid display type(%d)", display->type); + if (display->overlay_surface_id > 0) { + /* NOTE: In this case, we did not create mm_display handle, therefore just skip it. */ + LOG_DEBUG("already have overlay_surface_id[%d], skip it", display->overlay_surface_id); + return WEBRTC_ERROR_NONE; + } + if (display->type == WEBRTC_DISPLAY_TYPE_ECORE_WL) type = MM_DISPLAY_TYPE_OVERLAY_EXT; @@ -763,11 +769,11 @@ int _apply_display(webrtc_display_s *display) return ret; } -webrtc_display_s *_alloc_display(void) +webrtc_display_s *_alloc_display(bool use_mm_display) { webrtc_display_s *display = g_new0(webrtc_display_s, 1); - if (mm_display_interface_init(&display->mm_display) != MM_ERROR_NONE) { + if (use_mm_display && mm_display_interface_init(&display->mm_display) != MM_ERROR_NONE) { LOG_ERROR("failed to mm_display_interface_init()"); g_free(display); return NULL; @@ -777,8 +783,8 @@ webrtc_display_s *_alloc_display(void) display->mode = WEBRTC_DISPLAY_MODE_LETTER_BOX; display->visible = true; - LOG_DEBUG("alloc display[%p, mm_display:%p, mode:%u, visible:%u]", - display, display->mm_display, display->mode, display->visible); + LOG_DEBUG("use_mm_display[%d], display[%p, mm_display:%p, mode:%u, visible:%u]", + use_mm_display, display, display->mm_display, display->mode, display->visible); return display; } @@ -798,6 +804,23 @@ void _set_display_type_and_surface(webrtc_display_s *display, webrtc_display_typ LOG_INFO("display[%p, type:%d, surface:%p]", display, type, surface); } +void _set_display_surface_id(webrtc_display_s *display, int surface_id, int x, int y, int w, int h) +{ + g_autoptr(GMutexLocker) locker = NULL; + + RET_IF(display == NULL, "display is NULL"); + + locker = g_mutex_locker_new(&display->mutex); + + display->overlay_surface_id = surface_id; + display->x = x; + display->y = y; + display->w = w; + display->h = h; + + LOG_INFO("display[%p, surface_id:%d, x:%d, y:%d, w:%d, h:%d]", display, surface_id, x, y, w, h); +} + void _release_display(webrtc_display_s *display) { RET_IF(display == NULL, "display is NULL"); diff --git a/src/webrtc_internal.c b/src/webrtc_internal.c index d5aaa480..d9ebbb5e 100644 --- a/src/webrtc_internal.c +++ b/src/webrtc_internal.c @@ -41,6 +41,24 @@ int webrtc_set_ecore_wl_display(webrtc_h webrtc, unsigned int track_id, void *ec return ret; } +int webrtc_set_display_surface_id(webrtc_h webrtc, unsigned int track_id, int surface_id, int x, int y, int width, int height) +{ + g_autoptr(GMutexLocker) locker = NULL; + webrtc_s *_webrtc = (webrtc_s *)webrtc; + + RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL"); + RET_VAL_IF(track_id == 0, WEBRTC_ERROR_INVALID_PARAMETER, "track id is 0"); + + locker = g_mutex_locker_new(&_webrtc->mutex); + + RET_VAL_IF(_webrtc->track_added_cb.callback == NULL, WEBRTC_ERROR_INVALID_OPERATION, "track added callback was not set"); + RET_VAL_IF(_webrtc->encoded_video_frame_cb.callback, WEBRTC_ERROR_INVALID_OPERATION, "encoded video frame callback was set"); + RET_VAL_IF(!_is_owner_of_track_build_context(_webrtc, track_id), WEBRTC_ERROR_INVALID_OPERATION, + "this function should be called within the track added callback"); + + return _set_display_surface_id_to_sink(webrtc, track_id, surface_id, x, y, width, height); +} + int webrtc_set_audio_mute(webrtc_h webrtc, unsigned int track_id, bool mute) { g_autoptr(GMutexLocker) locker = NULL; diff --git a/src/webrtc_sink.c b/src/webrtc_sink.c index 7c9c9a3a..51cb4d64 100644 --- a/src/webrtc_sink.c +++ b/src/webrtc_sink.c @@ -203,6 +203,13 @@ static int __build_videosink(webrtc_s *webrtc, GstElement *decodebin, GstPad *sr /* FIXME: The order of setting property and display is important when 'use-tbm' is true. The reverse does not work */ gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(videosink), sink->display->overlay_surface_id); + LOG_DEBUG("overlay_surface_id[%d]", sink->display->overlay_surface_id); + if (sink->display->w > 0 && sink->display->h > 0) { + gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(videosink), sink->display->x, sink->display->y, + sink->display->w, sink->display->h); + LOG_DEBUG("render rectangle[x:%d, y:%d, w:%d, h:%d]", sink->display->x, sink->display->y, + sink->display->w, sink->display->h); + } if (!g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(videosink)), "display-geometry-method")) { LOG_ERROR("could not find 'display-geometry-method' property"); goto exit; @@ -1174,7 +1181,7 @@ int _set_display_to_sink(webrtc_s *webrtc, unsigned int track_id, unsigned int t RET_VAL_IF((sink->media_types & MEDIA_TYPE_VIDEO) == 0x0, WEBRTC_ERROR_INVALID_OPERATION, "it's not a video track"); if (sink->display == NULL) { - sink->display = _alloc_display(); + sink->display = _alloc_display(true); RET_VAL_IF(sink->display == NULL, WEBRTC_ERROR_INVALID_OPERATION, "sink->display is NULL"); } @@ -1185,6 +1192,32 @@ int _set_display_to_sink(webrtc_s *webrtc, unsigned int track_id, unsigned int t return WEBRTC_ERROR_NONE; } +int _set_display_surface_id_to_sink(webrtc_s *webrtc, unsigned int track_id, int surface_id, int x, int y, int width, int height) +{ + webrtc_gst_slot_s *sink; + + RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL"); + RET_VAL_IF(track_id == 0, WEBRTC_ERROR_INVALID_PARAMETER, "track id is 0"); + RET_VAL_IF(width <= 0 || height <= 0, WEBRTC_ERROR_INVALID_PARAMETER, "invalid width or height"); + + sink = __find_sink_slot_by_id(webrtc, track_id); + RET_VAL_IF(sink == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "sink is NULL"); + RET_VAL_IF(sink->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL"); + RET_VAL_IF(sink->encoded_frame_cb != NULL, WEBRTC_ERROR_INVALID_OPERATION, "it may be a forwarding sink for encoded frame callback"); + RET_VAL_IF((sink->media_types & MEDIA_TYPE_VIDEO) == 0x0, WEBRTC_ERROR_INVALID_OPERATION, "it's not a video track"); + + if (sink->display == NULL) { + sink->display = _alloc_display(false); + RET_VAL_IF(sink->display == NULL, WEBRTC_ERROR_INVALID_OPERATION, "sink->display is NULL"); + } + + LOG_INFO("webrtc[%p] track_id[%u]", webrtc, track_id); + + _set_display_surface_id(sink->display, surface_id, x, y, width, height); + + return WEBRTC_ERROR_NONE; +} + int _set_display_mode_to_sink(webrtc_s *webrtc, unsigned int track_id, webrtc_display_mode_e mode) { webrtc_gst_slot_s *sink; diff --git a/src/webrtc_source_loopback.c b/src/webrtc_source_loopback.c index 7dc6b75b..a9a1efe5 100644 --- a/src/webrtc_source_loopback.c +++ b/src/webrtc_source_loopback.c @@ -423,7 +423,7 @@ int _set_video_loopback(webrtc_s *webrtc, unsigned int source_id, unsigned int t RET_VAL_IF(source->av[AV_IDX_VIDEO].render.pipeline, WEBRTC_ERROR_INVALID_OPERATION, "video loopback has already been set"); if (source->display == NULL) { - source->display = _alloc_display(); + source->display = _alloc_display(true); RET_VAL_IF(source->display == NULL, WEBRTC_ERROR_INVALID_OPERATION, "source->display is NULL"); }