From: Hyunil Date: Fri, 9 Apr 2021 10:29:22 +0000 (+0900) Subject: webrtc_source: Add WEBRTC_MEDIA_SOURCE_TYPE_SCREEN to media source type X-Git-Tag: submit/tizen/20210729.023123~88 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1d0086066de0687f6f9a079923858f5f9535241b;p=platform%2Fcore%2Fapi%2Fwebrtc.git webrtc_source: Add WEBRTC_MEDIA_SOURCE_TYPE_SCREEN to media source type - Function to use screen as a media source [Version] 0.1.153 [Issue Type] New API Change-Id: Iadb687bd4f3b94cfc4b7d5d0555a8a4874184c30 Signed-off-by: Hyunil --- diff --git a/include/webrtc.h b/include/webrtc.h index fd373711..1f481487 100644 --- a/include/webrtc.h +++ b/include/webrtc.h @@ -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; /** diff --git a/packaging/capi-media-webrtc.spec b/packaging/capi-media-webrtc.spec index ff14f56f..9c8f33be 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.1.152 +Version: 0.1.153 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/webrtc_ini.c b/src/webrtc_ini.c index a13aa041..fd2e1759 100644 --- a/src/webrtc_ini.c +++ b/src/webrtc_ini.c @@ -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 }, }; diff --git a/src/webrtc_source.c b/src/webrtc_source.c index 907a552d..1460f36e 100644 --- a/src/webrtc_source.c +++ b/src/webrtc_source.c @@ -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); diff --git a/test/webrtc_test.c b/test/webrtc_test.c index 0667f413..c932daac 100644 --- a/test/webrtc_test.c +++ b/test/webrtc_test.c @@ -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");