webrtc_source: Add WEBRTC_MEDIA_SOURCE_TYPE_SCREEN to media source type 12/256712/22
authorHyunil <hyunil46.park@samsung.com>
Fri, 9 Apr 2021 10:29:22 +0000 (19:29 +0900)
committerHyunil Park <hyunil46.park@samsung.com>
Fri, 23 Apr 2021 04:32:49 +0000 (04:32 +0000)
- Function to use screen as a media source

[Version] 0.1.153
[Issue Type] New API

Change-Id: Iadb687bd4f3b94cfc4b7d5d0555a8a4874184c30
Signed-off-by: Hyunil <hyunil46.park@samsung.com>
include/webrtc.h
packaging/capi-media-webrtc.spec
src/webrtc_ini.c
src/webrtc_source.c
test/webrtc_test.c

index fd373711723d4a792caddaf81d42884bbfd46562..1f481487e4b2bfbba4e445980e7888c73917ed96 100644 (file)
@@ -98,11 +98,12 @@ typedef enum
  * @since_tizen 6.5
  */
 typedef enum {
-       WEBRTC_MEDIA_SOURCE_TYPE_CAMERA,      /**<  Camera preview */
-       WEBRTC_MEDIA_SOURCE_TYPE_MIC,         /**<  Audio from microphone */
-       WEBRTC_MEDIA_SOURCE_TYPE_AUDIOTEST,   /**<  Audio test */
-       WEBRTC_MEDIA_SOURCE_TYPE_VIDEOTEST,   /**<  Video test */
-       WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET /**<  Media packet */
+       WEBRTC_MEDIA_SOURCE_TYPE_CAMERA,       /**<  Camera preview */
+       WEBRTC_MEDIA_SOURCE_TYPE_MIC,          /**<  Audio from microphone */
+       WEBRTC_MEDIA_SOURCE_TYPE_AUDIOTEST,    /**<  Audio test */
+       WEBRTC_MEDIA_SOURCE_TYPE_VIDEOTEST,    /**<  Video test */
+       WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET, /**<  Media packet */
+       WEBRTC_MEDIA_SOURCE_TYPE_SCREEN        /**<  Screen capture */
 } webrtc_media_source_type_e;
 
 /**
index ff14f56f3b6a693037d3b67d3e209a6860d2a2c4..9c8f33bee9dde0d7a0d598b19824b7edb983be4b 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-webrtc
 Summary:    A WebRTC library in Tizen Native API
-Version:    0.1.152
+Version:    0.1.153
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index a13aa041c495e3faae105d7796c652779175e069..fd2e1759713403e09a1b6df912daefc47fa3c130 100644 (file)
@@ -32,6 +32,7 @@
 #define INI_CATEGORY_SOURCE_AUDIOTEST     "source audiotest"
 #define INI_CATEGORY_SOURCE_VIDEOTEST     "source videotest"
 #define INI_CATEGORY_SOURCE_MEDIA_PACKET  "source media packet"
+#define INI_CATEGORY_SOURCE_SCREEN        "source screen"
 #define INI_CATEGORY_RENDERING_SINK       "rendering sink"
 #define INI_CATEGORY_VPXENC_PARAMS        "vpxenc params"
 
@@ -108,6 +109,7 @@ typedef enum {
        MEDIA_SOURCE_TYPE_AUDIOTEST,
        MEDIA_SOURCE_TYPE_VIDEOTEST,
        MEDIA_SOURCE_TYPE_MEDIA_PACKET,
+       MEDIA_SOURCE_TYPE_SCREEN,
        MEDIA_SOURCE_TYPE_MAX,
 } media_source_type_e;
 
@@ -121,6 +123,7 @@ static ini_category_name_s category_source_names[] = {
        [MEDIA_SOURCE_TYPE_AUDIOTEST] = { INI_CATEGORY_SOURCE_AUDIOTEST },
        [MEDIA_SOURCE_TYPE_VIDEOTEST] = { INI_CATEGORY_SOURCE_VIDEOTEST },
        [MEDIA_SOURCE_TYPE_MEDIA_PACKET] = { INI_CATEGORY_SOURCE_MEDIA_PACKET },
+       [MEDIA_SOURCE_TYPE_SCREEN] = { INI_CATEGORY_SOURCE_SCREEN },
        [MEDIA_SOURCE_TYPE_MAX] = { NULL },
 };
 
index 907a552d0ac5ddddde4e53d2106393fe63f7caa8..1460f36e75cd620d4d7384636d545cff6d09fd3d 100644 (file)
@@ -34,6 +34,8 @@
 #define DEFAULT_ELEMENT_VIDEOTESTSRC  "videotestsrc"
 #define DEFAULT_ELEMENT_AUDIOTESTSRC  "audiotestsrc"
 #define DEFAULT_ELEMENT_APPSRC        "appsrc"
+#define DEFAULT_ELEMENT_SCREENSRC     "waylandsrc"
+#define DEFAULT_ELEMENT_VIDEOCONVERT  "videoconvert"
 #define DEFAULT_ELEMENT_CAPSFILTER    "capsfilter"
 #define DEFAULT_ELEMENT_QUEUE         "queue"
 
@@ -222,6 +224,7 @@ static GstCaps *__make_default_raw_caps(webrtc_gst_slot_s *source, webrtc_ini_s
        switch (source->type) {
        case WEBRTC_MEDIA_SOURCE_TYPE_CAMERA:
        case WEBRTC_MEDIA_SOURCE_TYPE_VIDEOTEST:
+       case WEBRTC_MEDIA_SOURCE_TYPE_SCREEN:
                caps = gst_caps_new_simple(MEDIA_TYPE_VIDEO_RAW,
                                                "format", G_TYPE_STRING, ini_source->v_raw_format,
                                                "framerate", GST_TYPE_FRACTION, ini_source->v_framerate, 1,
@@ -349,6 +352,7 @@ static GstCaps *__make_default_encoded_caps(webrtc_gst_slot_s *source, webrtc_in
        switch (source->type) {
        case WEBRTC_MEDIA_SOURCE_TYPE_CAMERA:
        case WEBRTC_MEDIA_SOURCE_TYPE_VIDEOTEST:
+       case WEBRTC_MEDIA_SOURCE_TYPE_SCREEN:
                _media_type = __get_video_media_type(ini_source->v_codec);
                RET_VAL_IF(_media_type == NULL, NULL, "_media_type is NULL");
 
@@ -686,6 +690,8 @@ static const char *__get_default_element(webrtc_media_source_type_e type)
                element = DEFAULT_ELEMENT_VIDEOTESTSRC;
        else if (type == WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET)
                element = DEFAULT_ELEMENT_APPSRC;
+       else if (type == WEBRTC_MEDIA_SOURCE_TYPE_SCREEN)
+               element = DEFAULT_ELEMENT_SCREENSRC;
        else
                LOG_ERROR_IF_REACHED("type(%d)", type);
 
@@ -707,6 +713,109 @@ static const char *__get_source_element(webrtc_s *webrtc, webrtc_media_source_ty
        return source->source_element;
 }
 
+static int __create_elements_for_screensrc(webrtc_s *webrtc, webrtc_gst_slot_s *source,
+       GstElement **screensrc, GstElement **capsfilter, GstElement **videoconvert)
+{
+       GstCaps *caps = NULL;
+       gchar *caps_str = NULL;
+       ini_item_media_source_s *ini_source  = NULL;
+
+       RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+       RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
+       RET_VAL_IF(screensrc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "screensrc is NULL");
+       RET_VAL_IF(capsfilter == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "capsfilter is NULL");
+       RET_VAL_IF(videoconvert == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "videoconvert is NULL");
+
+       if (!(*screensrc = _create_element(__get_source_element(webrtc, WEBRTC_MEDIA_SOURCE_TYPE_SCREEN), NULL))) {
+               LOG_ERROR("failed to create screensrc");
+               return WEBRTC_ERROR_INVALID_OPERATION;
+       }
+
+       if (!(*videoconvert = _create_element(DEFAULT_ELEMENT_VIDEOCONVERT, NULL))) {
+               LOG_ERROR("failed to create videoconvert");
+               return WEBRTC_ERROR_INVALID_OPERATION;
+       }
+
+       if (!(*capsfilter = _create_element(DEFAULT_ELEMENT_CAPSFILTER, NULL))) {
+               LOG_ERROR("failed to create capsfilter");
+               return WEBRTC_ERROR_INVALID_OPERATION;
+       }
+
+       ini_source = _ini_get_source_by_type(&webrtc->ini, source->type);
+       if (ini_source == NULL)
+               ini_source = &webrtc->ini.media_source;
+
+       caps = gst_caps_new_simple(MEDIA_TYPE_VIDEO_RAW,
+                                       "format", G_TYPE_STRING, "BGRA",
+                                       "framerate", GST_TYPE_FRACTION, ini_source->v_framerate, 1,
+                                       "width", G_TYPE_INT, ini_source->v_width,
+                                       "height", G_TYPE_INT, ini_source->v_height,
+                                       NULL);
+       caps_str = gst_caps_to_string(caps);
+       LOG_INFO("capsfilter caps[%s] for screensrc", caps_str);
+       g_free(caps_str);
+
+       g_object_set(G_OBJECT(*capsfilter), "caps", caps, NULL);
+       gst_caps_unref(caps);
+
+       return WEBRTC_ERROR_NONE;
+}
+
+static int __build_screensrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
+{
+       int ret = WEBRTC_ERROR_NONE;
+       GstElement *screensrc = NULL;
+       GstElement *capsfilter1 = NULL;
+       GstElement *videoconvert = NULL;
+       GstElement *capsfilter2 = NULL;
+       GstElement *videoenc = NULL;
+       GstElement *videopay = NULL;
+       GstElement *queue = NULL;
+       GstElement *capsfilter3 = NULL;
+
+       RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+       RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
+       RET_VAL_IF(source->src_pad == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "src_pad is NULL");
+       RET_VAL_IF(source->bin == NULL, WEBRTC_ERROR_INVALID_OPERATION, "bin is NULL");
+
+       source->media_types = MEDIA_TYPE_VIDEO;
+
+       if ((ret = __create_elements_for_screensrc(webrtc, source, &screensrc, &capsfilter1, &videoconvert)) != WEBRTC_ERROR_NONE)
+               goto exit;
+
+       if ((ret = __create_rest_of_elements(webrtc, source, &capsfilter2, &videoenc, &videopay, &queue, &capsfilter3)) != WEBRTC_ERROR_NONE)
+               goto exit;
+
+       gst_bin_add_many(source->bin, screensrc, capsfilter1, videoconvert, capsfilter2, videoenc, videopay, queue, capsfilter3, NULL);
+       if (!gst_element_link_many(screensrc, capsfilter1, videoconvert, capsfilter2, videoenc, videopay, queue, capsfilter3, NULL)) {
+               LOG_ERROR("failed to gst_element_link_many()");
+               goto exit_with_remove_from_bin;
+       }
+
+       ret = _set_ghost_pad_target(source->src_pad, capsfilter3, true);
+       if (ret != WEBRTC_ERROR_NONE)
+               goto exit_with_remove_from_bin;
+
+       return WEBRTC_ERROR_NONE;
+
+exit_with_remove_from_bin:
+       gst_bin_remove_many(source->bin, screensrc, capsfilter1, videoconvert, capsfilter2, videoenc, videopay, queue, capsfilter3, NULL);
+
+       return WEBRTC_ERROR_INVALID_OPERATION;
+
+exit:
+       SAFE_GST_OBJECT_UNREF(screensrc);
+       SAFE_GST_OBJECT_UNREF(capsfilter1);
+       SAFE_GST_OBJECT_UNREF(videoconvert);
+       SAFE_GST_OBJECT_UNREF(capsfilter2);
+       SAFE_GST_OBJECT_UNREF(videoenc);
+       SAFE_GST_OBJECT_UNREF(videopay);
+       SAFE_GST_OBJECT_UNREF(queue);
+       SAFE_GST_OBJECT_UNREF(capsfilter3);
+
+       return ret;
+}
+
 static int __build_camerasrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
 {
        int ret = WEBRTC_ERROR_NONE;
@@ -1150,6 +1259,9 @@ static int __build_source_bin(webrtc_s *webrtc, webrtc_gst_slot_s *source)
        case WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET:
                return __build_mediapacketsrc(webrtc, source);
 
+       case WEBRTC_MEDIA_SOURCE_TYPE_SCREEN:
+               return __build_screensrc(webrtc, source);
+
        default:
                LOG_ERROR_IF_REACHED("type(%d)", source->type);
                return WEBRTC_ERROR_INVALID_PARAMETER;
@@ -1272,7 +1384,7 @@ int _add_media_source(webrtc_s *webrtc, webrtc_media_source_type_e type, unsigne
        RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
        RET_VAL_IF(webrtc->gst.source_slots == NULL, WEBRTC_ERROR_INVALID_OPERATION, "source_slots is NULL");
        RET_VAL_IF(source_id == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source_id is NULL");
-       RET_VAL_IF(type > WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET, WEBRTC_ERROR_INVALID_PARAMETER, "invalid source type(%d)", type);
+       RET_VAL_IF(type > WEBRTC_MEDIA_SOURCE_TYPE_SCREEN, WEBRTC_ERROR_INVALID_PARAMETER, "invalid source type(%d)", type);
 
        /* bin_name/source will be freed by function which is set to g_hash_table_new_full() */
        id = __get_unoccupied_id(webrtc->gst.source_slots);
index 0667f413842d1f724dc2622319ae59c70d573814..c932daacdf64d8f2554d2c5acf2798ab88b324b0 100644 (file)
@@ -3083,7 +3083,7 @@ static void displaymenu()
                display_sub_basic();
 
        } else if (g_conns[g_conn_index].menu_state == CURRENT_STATUS_ADD_MEDIA_SOURCE) {
-               g_print("*** input media source type.(1:camera, 2:mic, 3:audiotest, 4:videotest, 5:media packet)\n");
+               g_print("*** input media source type.(1:camera, 2:mic, 3:audiotest, 4:videotest, 5:media packet, 6:screen)\n");
 
        } else if (g_conns[g_conn_index].menu_state == CURRENT_STATUS_REMOVE_MEDIA_SOURCE) {
                g_print("*** input media source id to remove.\n");