webrtc_internal: Add webrtc_set_display_surface_id() 76/289776/4 accepted/tizen/unified/20230405.153341
authorSangchul Lee <sc11.lee@samsung.com>
Tue, 14 Mar 2023 07:36:22 +0000 (16:36 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Thu, 30 Mar 2023 00:54:39 +0000 (09:54 +0900)
[Version] 0.4.6
[Issue Type] API

Change-Id: I8678951f128dcb448645e1032838c4392f9e2a20
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
include/webrtc_internal.h
include/webrtc_private.h
packaging/capi-media-webrtc.spec
src/webrtc_display.c
src/webrtc_internal.c
src/webrtc_sink.c
src/webrtc_source_loopback.c

index cde362f76892224cc2116ffc10d8587e5198de87..ff3ab1161021180a38c3406a76437b4dda4a51cd 100644 (file)
@@ -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.
index 085905295ced001d5f046a7b6a308c283f063877..37b2361bb1afc05f62b7607cf092d71fbeba0085 100644 (file)
@@ -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);
index f49b87a5148912a9eb921cd265a4633032b2f0bf..1252f214d46dee129b912d610f7eee857c2ba4a6 100644 (file)
@@ -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
index 9b993eaf15d25d993582b1e598723726b732aa4a..ebc931da9210bb188c1a6e7e8d7e957b57019b85 100644 (file)
@@ -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");
index d5aaa480ee54e0d5fdabaf330ed0df59d579bc9c..d9ebbb5edd09fc7755297d789ebaa2d1ad3af178 100644 (file)
@@ -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;
index 7c9c9a3a13ad7a8ad6b104a6ef942a4859b78e3e..51cb4d643793d31a10f474c080327499642963f2 100644 (file)
@@ -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;
index 7dc6b75b311aa7dd2110a962cbc775f98a0f2a3a..a9a1efe5c21ae638f106f0503fce8a0f86f952e7 100644 (file)
@@ -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");
        }