Add API set for video source resolution 79/257379/14
authorSangchul Lee <sc11.lee@samsung.com>
Fri, 23 Apr 2021 07:13:21 +0000 (16:13 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Thu, 29 Apr 2021 08:07:28 +0000 (17:07 +0900)
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 <sc11.lee@samsung.com>
include/webrtc.h
include/webrtc_private.h
packaging/capi-media-webrtc.spec
src/webrtc.c
src/webrtc_source.c
test/webrtc_test.c

index 15c92e2d4c82e3c7ea18f4e510ba01952c79b877..e80bd2a9c54496e7c6b0264c1fcc064b8bef85b8 100644 (file)
@@ -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
index accd45f3aec135d819ee0312f5e53633cec28fc1..1d20e1bf6f58720b9c46fbd9061e891107020da1 100644 (file)
@@ -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);
index 08d29557dcb809e841c96e78f0f3205e27ee843a..d539c9b73a30d3208e1501e505507fb8e20cb5de 100644 (file)
@@ -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
index e1b849b1a7628f0fb1b28703b5bfb887d3fc18a2..168dbcff8cc69452e5155f92ab937c6e75850daa 100644 (file)
@@ -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;
index 66c19f842d259a69d60e09690e3029db88af5b8f..ab78fe5e37c85aebc0b90dd85a505d57352a3ceb 100644 (file)
@@ -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;
index aa1c25f1141fffa49504417cd3090da709ad3c13..be8f62de16a653af020480da654c6c81e1923622 100644 (file)
@@ -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);