From: Sangchul Lee Date: Fri, 23 Apr 2021 07:13:21 +0000 (+0900) Subject: Add API set for video source resolution X-Git-Tag: submit/tizen/20210729.023123~81 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F79%2F257379%2F14;p=platform%2Fcore%2Fapi%2Fwebrtc.git Add API set for video source resolution Functions are added as below. - webrtc_set_video_source_resolution() - webrtc_get_video_source_resolution() Test cases for these are added in webrtc_test. [Version] 0.1.160 [Issue Type] API Change-Id: Iea0ec96d4e05f900cd4d83e9480e38fb604ad1ab Signed-off-by: Sangchul Lee --- diff --git a/include/webrtc.h b/include/webrtc.h index 15c92e2d..e80bd2a9 100644 --- a/include/webrtc.h +++ b/include/webrtc.h @@ -503,6 +503,8 @@ int webrtc_get_state(webrtc_h webrtc, webrtc_state_e *state); * @retval #WEBRTC_ERROR_INVALID_STATE Invalid state * @pre @a webrtc state must be set to #WEBRTC_STATE_IDLE. * @see webrtc_remove_media_source() + * @see webrtc_set_video_source_resolution() + * @see webrtc_get_video_source_resolution() */ int webrtc_add_media_source(webrtc_h webrtc, webrtc_media_source_type_e type, unsigned int *source_id); @@ -523,6 +525,52 @@ int webrtc_add_media_source(webrtc_h webrtc, webrtc_media_source_type_e type, un */ int webrtc_remove_media_source(webrtc_h webrtc, unsigned int source_id); +/** + * @brief Sets a video source resolution. + * @details The following media source types are for the video source:\n + * #WEBRTC_MEDIA_SOURCE_TYPE_CAMERA\n + * #WEBRTC_MEDIA_SOURCE_TYPE_VIDEOTEST\n + * #WEBRTC_MEDIA_SOURCE_TYPE_SCREEN + * @since_tizen 6.5 + * @param[in] webrtc WebRTC handle + * @param[in] source_id The video source id + * @param[in] width The video width + * @param[in] height The video height + * @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 + * @retval #WEBRTC_ERROR_INVALID_STATE Invalid state + * @pre Add media source to @a webrtc to get @a source_id by calling webrtc_add_media_source(). + * @pre @a webrtc state must be set to #WEBRTC_STATE_IDLE. + * @see webrtc_add_media_source() + * @see webrtc_get_video_source_resolution() + */ +int webrtc_set_video_source_resolution(webrtc_h webrtc, unsigned int source_id, int width, int height); + +/** + * @brief Gets the video source resolution. + * @details The following media source types are for the video source:\n + * #WEBRTC_MEDIA_SOURCE_TYPE_CAMERA\n + * #WEBRTC_MEDIA_SOURCE_TYPE_VIDEOTEST\n + * #WEBRTC_MEDIA_SOURCE_TYPE_SCREEN + * @since_tizen 6.5 + * @param[in] webrtc WebRTC handle + * @param[in] source_id The video source id + * @param[out] width The video width + * @param[out] height The video height + * @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 Add media source to @a webrtc to get @a source_id by calling webrtc_add_media_source(). + * @see webrtc_add_media_source() + * @see webrtc_set_video_source_resolution() + */ +int webrtc_get_video_source_resolution(webrtc_h webrtc, unsigned int source_id, int *width, int *height); + /** * @brief Sets a callback function to be invoked when the buffer state of media packet source is changed. * @since_tizen 6.5 diff --git a/include/webrtc_private.h b/include/webrtc_private.h index accd45f3..1d20e1bf 100644 --- a/include/webrtc_private.h +++ b/include/webrtc_private.h @@ -384,6 +384,10 @@ typedef struct _webrtc_gst_slot_s { webrtc_media_source_type_e type; int media_types; /* values of media_type_e combined with bitwise 'or' */ int mlines[2]; /* index 0 for audio, 1 for video */ + struct { + int width; + int height; + } video_info; media_format_h media_format; bool zerocopy_enabled; GstAllocator *allocator; @@ -463,6 +467,8 @@ void _gst_destroy_pipeline(webrtc_s *webrtc); int _gst_pipeline_set_state(webrtc_s *webrtc, GstState state); int _add_media_source(webrtc_s *webrtc, webrtc_media_source_type_e type, unsigned int *source_id); int _remove_media_source(webrtc_s *webrtc, unsigned int source_id); +int _set_video_source_resolution(webrtc_s *webrtc, unsigned int source_id, int width, int height); +int _get_video_source_resolution(webrtc_s *webrtc, unsigned int source_id, int *width, int *height); int _set_media_format(webrtc_s *webrtc, unsigned int source_id, media_format_h format); bool _check_if_format_is_set_to_packet_sources(webrtc_s *webrtc); int _push_media_packet(webrtc_s *webrtc, unsigned int source_id, media_packet_h packet); diff --git a/packaging/capi-media-webrtc.spec b/packaging/capi-media-webrtc.spec index 08d29557..d539c9b7 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.159 +Version: 0.1.160 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/webrtc.c b/src/webrtc.c index e1b849b1..168dbcff 100644 --- a/src/webrtc.c +++ b/src/webrtc.c @@ -299,6 +299,44 @@ int webrtc_remove_media_source(webrtc_h webrtc, unsigned int source_id) return ret; } +int webrtc_set_video_source_resolution(webrtc_h webrtc, unsigned int source_id, int width, int height) +{ + int ret = WEBRTC_ERROR_NONE; + webrtc_s *_webrtc = (webrtc_s*)webrtc; + + RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL"); + RET_VAL_IF(width <= 0, WEBRTC_ERROR_INVALID_PARAMETER, "width <= 0"); + RET_VAL_IF(height <= 0, WEBRTC_ERROR_INVALID_PARAMETER, "height <= 0"); + + g_mutex_lock(&_webrtc->mutex); + + RET_VAL_WITH_UNLOCK_IF(_webrtc->state != WEBRTC_STATE_IDLE, WEBRTC_ERROR_INVALID_STATE, &_webrtc->mutex, "the state should be IDLE"); + + ret = _set_video_source_resolution(webrtc, source_id, width, height); + + g_mutex_unlock(&_webrtc->mutex); + + return ret; +} + +int webrtc_get_video_source_resolution(webrtc_h webrtc, unsigned int source_id, int *width, int *height) +{ + int ret = WEBRTC_ERROR_NONE; + webrtc_s *_webrtc = (webrtc_s*)webrtc; + + RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL"); + RET_VAL_IF(width == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "width is NULL"); + RET_VAL_IF(height == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "height is NULL"); + + g_mutex_lock(&_webrtc->mutex); + + ret = _get_video_source_resolution(webrtc, source_id, width, height); + + g_mutex_unlock(&_webrtc->mutex); + + return ret; +} + int webrtc_media_packet_source_set_buffer_state_changed_cb(webrtc_h webrtc, unsigned int source_id, webrtc_media_packet_source_buffer_state_changed_cb callback, void *user_data) { webrtc_s *_webrtc = (webrtc_s*)webrtc; diff --git a/src/webrtc_source.c b/src/webrtc_source.c index 66c19f84..ab78fe5e 100644 --- a/src/webrtc_source.c +++ b/src/webrtc_source.c @@ -39,6 +39,8 @@ #define DEFAULT_ELEMENT_CAPSFILTER "capsfilter" #define DEFAULT_ELEMENT_QUEUE "queue" +#define ELEMENT_NAME_FIRST_CAPSFILTER "firstCapsfilter" + typedef enum { CODEC_TYPE_OPUS, CODEC_TYPE_VORBIS, @@ -209,6 +211,39 @@ static bool __is_supported_mime_type(media_format_mimetype_e mime_type) } } +static GstCaps *__make_video_raw_caps_with_resolution(webrtc_gst_slot_s *source, webrtc_ini_s *ini, int width, int height) +{ + GstCaps *caps = NULL; + ini_item_media_source_s *ini_source; + + RET_VAL_IF(source == NULL, NULL, "source is NULL"); + RET_VAL_IF(ini == NULL, NULL, "ini is NULL"); + + ini_source = _ini_get_source_by_type(ini, source->type); + if (ini_source == NULL) + ini_source = &ini->media_source; + + 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, + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + NULL); + source->video_info.width = width; + source->video_info.height = height; + break; + default: + LOG_ERROR_IF_REACHED("type(%d)", source->type); + break; + } + + return caps; +} + static GstCaps *__make_default_raw_caps(webrtc_gst_slot_s *source, webrtc_ini_s *ini) { GstCaps *caps = NULL; @@ -231,6 +266,8 @@ static GstCaps *__make_default_raw_caps(webrtc_gst_slot_s *source, webrtc_ini_s "width", G_TYPE_INT, ini_source->v_width, "height", G_TYPE_INT, ini_source->v_height, NULL); + source->video_info.width = ini_source->v_width; + source->video_info.height = ini_source->v_height; break; case WEBRTC_MEDIA_SOURCE_TYPE_MIC: @@ -274,6 +311,7 @@ static GstCaps *__make_default_raw_caps(webrtc_gst_slot_s *source, webrtc_ini_s "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); + } else { LOG_ERROR_IF_REACHED("source->media_types(0x%x)", source->media_types); } @@ -361,6 +399,8 @@ static GstCaps *__make_default_encoded_caps(webrtc_gst_slot_s *source, webrtc_in "width", G_TYPE_INT, ini_source->v_width, "height", G_TYPE_INT, ini_source->v_height, NULL); + source->video_info.width = ini_source->v_width; + source->video_info.height = ini_source->v_height; break; case WEBRTC_MEDIA_SOURCE_TYPE_MIC: @@ -557,7 +597,7 @@ static int __create_rest_of_elements(webrtc_s *webrtc, webrtc_gst_slot_s *source RET_VAL_IF(capsfilter2 == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "capsfilter2 is NULL"); if (capsfilter) { - if (!(*capsfilter = _create_element(DEFAULT_ELEMENT_CAPSFILTER, NULL))) { + if (!(*capsfilter = _create_element(DEFAULT_ELEMENT_CAPSFILTER, ELEMENT_NAME_FIRST_CAPSFILTER))) { LOG_ERROR("failed to create capsfilter"); return WEBRTC_ERROR_INVALID_OPERATION; } @@ -1405,6 +1445,56 @@ int _remove_media_source(webrtc_s *webrtc, unsigned int source_id) return ret; } +int _set_video_source_resolution(webrtc_s *webrtc, unsigned int source_id, int width, int height) +{ + webrtc_gst_slot_s *source; + GstElement *capsfilter; + GstCaps *new_caps = NULL; + gchar *caps_str; + + RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL"); + RET_VAL_IF((source = _get_slot_by_id(webrtc->gst.source_slots, source_id)) == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "could not find source"); + RET_VAL_IF((source->media_types & MEDIA_TYPE_VIDEO) == 0x0, WEBRTC_ERROR_INVALID_PARAMETER, "it's not a video source"); + RET_VAL_IF((source->type == WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET), WEBRTC_ERROR_INVALID_PARAMETER, "this API does not support the media packet source"); + + /* it targets the capsfilter element right after the source element */ + capsfilter = __find_element_in_bin(source->bin, ELEMENT_NAME_FIRST_CAPSFILTER); + RET_VAL_IF(capsfilter == NULL, WEBRTC_ERROR_INVALID_OPERATION, "could not find the first capsfilter"); + + /* FIXME: check if the [width x height] is supported or not */ + + if (!(new_caps = __make_video_raw_caps_with_resolution(source, &webrtc->ini, width, height))) + return WEBRTC_ERROR_INVALID_OPERATION; + + caps_str = gst_caps_to_string(new_caps); + LOG_INFO("capsfilter caps[%s]", caps_str); + g_free(caps_str); + + g_object_set(G_OBJECT(capsfilter), "caps", new_caps, NULL); + gst_caps_unref(new_caps); + + return WEBRTC_ERROR_NONE; +} + +int _get_video_source_resolution(webrtc_s *webrtc, unsigned int source_id, int *width, int *height) +{ + webrtc_gst_slot_s *source; + + RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL"); + RET_VAL_IF(width == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "width is NULL"); + RET_VAL_IF(height == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "height is NULL"); + RET_VAL_IF((source = _get_slot_by_id(webrtc->gst.source_slots, source_id)) == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "could not find source"); + RET_VAL_IF((source->media_types & MEDIA_TYPE_VIDEO) == 0x0, WEBRTC_ERROR_INVALID_PARAMETER, "it's not a video source"); + RET_VAL_IF((source->type == WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET), WEBRTC_ERROR_INVALID_PARAMETER, "this API does not support the media packet source"); + + *width = source->video_info.width; + *height = source->video_info.height; + + LOG_INFO("source_id[%u], [%dx%d]", source_id, *width, *height); + + return WEBRTC_ERROR_NONE; +} + int _set_media_format(webrtc_s *webrtc, unsigned int source_id, media_format_h format) { int ret; diff --git a/test/webrtc_test.c b/test/webrtc_test.c index aa1c25f1..be8f62de 100644 --- a/test/webrtc_test.c +++ b/test/webrtc_test.c @@ -53,6 +53,8 @@ enum { CURRENT_STATUS_MAINMENU, CURRENT_STATUS_ADD_MEDIA_SOURCE, CURRENT_STATUS_REMOVE_MEDIA_SOURCE, + CURRENT_STATUS_SET_VIDEO_SOURCE_RESOLUTION, + CURRENT_STATUS_GET_VIDEO_SOURCE_RESOLUTION, CURRENT_STATUS_MEDIA_PACKET_SOURCE_SET_BUFFER_STATE_CHANGED_CB, CURRENT_STATUS_MEDIA_PACKET_SOURCE_UNSET_BUFFER_STATE_CHANGED_CB, CURRENT_STATUS_MEDIA_PACKET_SOURCE_SET_FORMAT, @@ -538,6 +540,30 @@ static void _webrtc_remove_media_source(int index, unsigned int source_id) } } +static void _webrtc_set_video_source_resolution(int index, unsigned int source_id, int width, int height) +{ + int ret = WEBRTC_ERROR_NONE; + + ret = webrtc_set_video_source_resolution(g_conns[index].webrtc, source_id, width, height); + if (ret != WEBRTC_ERROR_NONE) + g_print("failed to webrtc_set_video_source_resolution(), source_id[%u], ret[0x%x]\n", source_id, ret); + else + g_print("webrtc_set_video_source_resolution() success, source_id[%u], [%dx%d]\n", source_id, width, height); +} + +static void _webrtc_get_video_source_resolution(int index, unsigned int source_id) +{ + int ret = WEBRTC_ERROR_NONE; + int width; + int height; + + ret = webrtc_get_video_source_resolution(g_conns[index].webrtc, source_id, &width, &height); + if (ret != WEBRTC_ERROR_NONE) + g_print("failed to webrtc_set_video_source_resolution(), source_id[%u], ret[0x%x]\n", source_id, ret); + else + g_print("webrtc_get_video_source_resolution() success, source_id[%u], [%dx%d]\n", source_id, width, height); +} + #define VIDEO_WIDTH 352 #define VIDEO_HEIGHT 288 #define VIDEO_FRAME_RATE 30 @@ -2770,6 +2796,12 @@ void _interpret_main_menu(char *cmd) } else if (strncmp(cmd, "r", 1) == 0) { g_conns[g_conn_index].menu_state = CURRENT_STATUS_REMOVE_MEDIA_SOURCE; + } else if (strncmp(cmd, "v", 1) == 0) { + g_conns[g_conn_index].menu_state = CURRENT_STATUS_SET_VIDEO_SOURCE_RESOLUTION; + + } else if (strncmp(cmd, "l", 1) == 0) { + g_conns[g_conn_index].menu_state = CURRENT_STATUS_GET_VIDEO_SOURCE_RESOLUTION; + } else if (strncmp(cmd, "s", 1) == 0) { _webrtc_start(g_conn_index); @@ -3038,6 +3070,8 @@ void display_sub_basic() g_print("g. Get state\n"); g_print("a. Add media source\t"); g_print("r. Remove media source\n"); + g_print("v. Set video source resolution\t"); + g_print("l. Get video source resolution\n"); g_print("sf. Set media format to media packet source\n"); g_print("gd. Get transceiver direction\t"); g_print("td. Set transceiver direction\n"); @@ -3109,6 +3143,17 @@ static void displaymenu() } else if (g_conns[g_conn_index].menu_state == CURRENT_STATUS_REMOVE_MEDIA_SOURCE) { g_print("*** input media source id to remove.\n"); + } else if (g_conns[g_conn_index].menu_state == CURRENT_STATUS_SET_VIDEO_SOURCE_RESOLUTION) { + if (g_conns[g_conn_index].cnt == 0) + g_print("*** input source id.\n"); + else if (g_conns[g_conn_index].cnt == 1) + g_print("*** input width.\n"); + else if (g_conns[g_conn_index].cnt == 2) + g_print("*** input height.\n"); + + } else if (g_conns[g_conn_index].menu_state == CURRENT_STATUS_GET_VIDEO_SOURCE_RESOLUTION) { + g_print("*** input source id.\n"); + } else if (g_conns[g_conn_index].menu_state == CURRENT_STATUS_MEDIA_PACKET_SOURCE_SET_BUFFER_STATE_CHANGED_CB) { g_print("*** input media packet source id to set buffer state changed callback.\n"); @@ -3231,6 +3276,37 @@ static void interpret(char *cmd) reset_menu_state(); break; } + case CURRENT_STATUS_SET_VIDEO_SOURCE_RESOLUTION: { + static unsigned int id; + static int width; + static int height; + value = atoi(cmd); + + switch (g_conns[g_conn_index].cnt) { + case 0: + id = value; + g_conns[g_conn_index].cnt++; + break; + case 1: + width = value; + g_conns[g_conn_index].cnt++; + break; + case 2: + height = value; + _webrtc_set_video_source_resolution(g_conn_index, id, width, height); + id = width = height = 0; + g_conns[g_conn_index].cnt = 0; + reset_menu_state(); + break; + } + break; + } + case CURRENT_STATUS_GET_VIDEO_SOURCE_RESOLUTION: { + value = atoi(cmd); + _webrtc_get_video_source_resolution(g_conn_index, value); + reset_menu_state(); + break; + } case CURRENT_STATUS_MEDIA_PACKET_SOURCE_SET_BUFFER_STATE_CHANGED_CB: { value = atoi(cmd); _webrtc_media_packet_source_set_buffer_state_changed_cb(g_conn_index, value);