Add new internal APIs for setting or unsetting crop screen source 24/263424/16
authorHyunil <hyunil46.park@samsung.com>
Thu, 2 Sep 2021 05:57:27 +0000 (14:57 +0900)
committerHyunil <hyunil46.park@samsung.com>
Tue, 14 Sep 2021 06:59:55 +0000 (15:59 +0900)
- webrtc_screen_source_set_crop()
- webrtc_screen_source_unset_crop()
- Add function test to webrtc_test

[Version] 0.2.98
[Issue Type] New feature

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

index 60e78262fca05a9136f67f7b007f44300686326b..c5a70a2b0737a1b2b90fc77376bd097bb7d0ee58 100644 (file)
@@ -172,6 +172,53 @@ int webrtc_add_media_source_internal(webrtc_h webrtc, webrtc_media_source_type_i
  */
 int webrtc_file_source_set_path(webrtc_h webrtc, unsigned int source_id, const char *path);
 
+/**
+ * @internal
+ * @brief Sets the crop coordinates of screen source.
+ * @since_tizen 6.5
+ * @remarks The base position is always the upper left conner of the UI coordinates.\n
+ *          If the physical display is rotated and the UI is also rotated according to the rotation, @a portrait_mode and the cropping coordinates must be updated.\n
+ *          The display resolution and video resolution of this screen source are different,
+ *          this function uses the input parameters to crop the screen source based on the display resolution and it changes the video resolution of the screen source as a result.
+ * @param[in] webrtc     WebRTC handle
+ * @param[in] source_id  The file source id
+ * @param[in] x          X coordinate of the upper left conner of the result area
+ * @param[in] y          Y coordinate of the upper left conner of the result area
+ * @param[in] w          Width of UI for cropping
+ * @param[in] h          Height of UI for cropping
+ * @param[out] width     Cropped video resolution width
+ * @param[out] height    Cropped video resolution height
+ * @param[in] portrait_mode  Screen is portrait mode or not (@c true = portrait mode, @c false = landscape mode)
+ * @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 screen 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_NEGOTIATING or #WEBRTC_STATE_PLAYING.
+ * @see webrtc_screen_source_unset_crop()
+ */
+int webrtc_screen_source_set_crop(webrtc_h webrtc, unsigned int source_id, int x, int y, int w, int h, bool portrait_mode, int *width, int *height);
+
+/**
+ * @internal
+ * @brief Unsets the crop coordinates of screen source.
+ * @since_tizen 6.5
+ * @param[in] webrtc       WebRTC handle
+ * @param[in] source_id    The file source id
+ * @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 screen 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_NEGOTIATING or #WEBRTC_STATE_PLAYING.
+ * @see webrtc_screen_source_set_crop()
+ */
+int webrtc_screen_source_unset_crop(webrtc_h webrtc, unsigned int source_id);
+
 /**
  * @internal
  * @brief Creates a signaling server for private network.
index d24dc757f4499d51784fe6e79f80f569e9465be1..6e7251d68df88624ceb76f25a98353eac484579c 100644 (file)
@@ -560,6 +560,8 @@ int _set_sound_stream_info(webrtc_s *webrtc, unsigned int source_id, sound_strea
 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 _set_media_path(webrtc_s *webrtc, unsigned int source_id, const char *path);
+int _set_screen_source_crop(webrtc_s *webrtc, unsigned int source_id, int x, int y, int w, int h, bool portrait_mode, int *width, int *height);
+int _unset_screen_source_crop(webrtc_s *webrtc, unsigned int source_id);
 bool _check_if_path_is_set_to_file_sources(webrtc_s *webrtc);
 int _push_media_packet(webrtc_s *webrtc, unsigned int source_id, media_packet_h packet);
 void _invoke_state_changed_cb(webrtc_s *webrtc, webrtc_state_e old, webrtc_state_e new);
index 9650774d61a75ced9c892ad3eaecb7087281fc42..5ea9afef01d8324e8b8b2998f56828d117cdc100 100644 (file)
@@ -1,6 +1,6 @@
 Name:       capi-media-webrtc
 Summary:    A WebRTC library in Tizen Native API
-Version:    0.2.97
+Version:    0.2.98
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index 8ec2477938df2d9535f0673d899292014c805a63..a2c7200a8fb3dbd56458dfa77b51bb1fd7913670 100644 (file)
@@ -92,4 +92,47 @@ int webrtc_file_source_set_path(webrtc_h webrtc, unsigned int source_id, const c
        RET_VAL_IF(_webrtc->state != WEBRTC_STATE_IDLE, WEBRTC_ERROR_INVALID_STATE, "the state should be IDLE");
 
        return _set_media_path(_webrtc, source_id, path);
-}
\ No newline at end of file
+}
+
+int webrtc_screen_source_set_crop(webrtc_h webrtc, unsigned int source_id, int x, int y, int w, int h, bool portrait_mode, int *width, int *height)
+{
+       int ret = WEBRTC_ERROR_NONE;
+       webrtc_gst_slot_s *source = NULL;
+       webrtc_s *_webrtc = (webrtc_s*)webrtc;
+
+       RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+       RET_VAL_IF(_webrtc->state == WEBRTC_STATE_IDLE, WEBRTC_ERROR_INVALID_STATE, "the state should not be IDLE");
+       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->type != WEBRTC_MEDIA_SOURCE_TYPE_SCREEN, WEBRTC_ERROR_INVALID_PARAMETER, "media source type is not screen");
+       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 = _set_screen_source_crop(_webrtc, source_id, x, y, w, h, portrait_mode, width, height);
+
+       g_mutex_unlock(&_webrtc->mutex);
+
+       return ret;
+}
+
+int webrtc_screen_source_unset_crop(webrtc_h webrtc, unsigned int source_id)
+{
+       int ret = WEBRTC_ERROR_NONE;
+       webrtc_gst_slot_s *source = NULL;
+       webrtc_s *_webrtc = (webrtc_s*)webrtc;
+
+       RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+       RET_VAL_IF(_webrtc->state == WEBRTC_STATE_IDLE, WEBRTC_ERROR_INVALID_STATE, "the state should not be IDLE");
+       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->type != WEBRTC_MEDIA_SOURCE_TYPE_SCREEN, WEBRTC_ERROR_INVALID_PARAMETER, "media source type is not screen");
+
+       g_mutex_lock(&_webrtc->mutex);
+
+       ret = _unset_screen_source_crop(_webrtc, source_id);
+
+       g_mutex_unlock(&_webrtc->mutex);
+
+       return ret;
+}
+
index 4eb2ef0ce0883391829c85d00ec9ac1a6330de49..2ffd0bdc18be4e847a90e3b84b96028ffb688587 100644 (file)
@@ -37,6 +37,7 @@
 #define DEFAULT_ELEMENT_QUEUE          "queue"
 #define DEFAULT_ELEMENT_VOLUME         "volume"
 #define DEFAULT_ELEMENT_INPUT_SELECTOR "input-selector"
+#define DEFAULT_ELEMENT_VIDEOCROP      "videocrop"
 
 #define ELEMENT_NAME_FIRST_CAPSFILTER "firstCapsfilter"
 #define ELEMENT_NAME_RTP_CAPSFILTER   "rtpCapsfilter"
@@ -52,6 +53,9 @@
 #define DEFAULT_NAME_VIDEO_CAPSFILTER "videoCapsfilter"
 #define DEFAULT_NAME_AUDIO_PAYLOAD    "audioPayload"
 #define DEFAULT_NAME_VIDEO_PAYLOAD    "videoPayload"
+#define DEFAULT_NAME_VIDEOCROP        "videoCrop"
+#define DEFAULT_NAME_SCREENSRC        "waylandSrc"
+
 
 #define APPEND_ELEMENT(x_list, x_element) \
 do { \
@@ -815,6 +819,7 @@ static int __create_rest_of_elements(webrtc_s *webrtc, webrtc_gst_slot_s *source
        GstElement *payloader;
        GstElement *queue;
        GstElement *capsfilter2;
+       GstElement *videocrop;
        GstCaps *sink_caps;
        element_info_s elem_info;
        const gchar *encoder_klass_name;
@@ -862,6 +867,12 @@ static int __create_rest_of_elements(webrtc_s *webrtc, webrtc_gst_slot_s *source
                }
        }
 
+       if (source->type == WEBRTC_MEDIA_SOURCE_TYPE_SCREEN && !source->zerocopy_enabled) {
+               if (!(videocrop = _create_element(DEFAULT_ELEMENT_VIDEOCROP, DEFAULT_NAME_VIDEOCROP)))
+                       goto error;
+               APPEND_ELEMENT(*element_list, videocrop);
+       }
+
        if (source->zerocopy_enabled)
                encoder = __get_hw_encoder_element(webrtc, source);
        else
@@ -1236,7 +1247,7 @@ static int __build_screensrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
        source->media_types = MEDIA_TYPE_VIDEO;
        source->zerocopy_enabled = __is_hw_encoder_used(webrtc, source->type, source->media_types);
 
-       if (!(screensrc = _create_element(__get_source_element(webrtc, WEBRTC_MEDIA_SOURCE_TYPE_SCREEN), ELEMENT_NAME_VIDEO_SRC)))
+       if (!(screensrc = _create_element(__get_source_element(webrtc, WEBRTC_MEDIA_SOURCE_TYPE_SCREEN), DEFAULT_NAME_SCREENSRC)))
                return WEBRTC_ERROR_INVALID_OPERATION;
        APPEND_ELEMENT(switch_src_list, screensrc);
 
@@ -1253,9 +1264,11 @@ static int __build_screensrc(webrtc_s *webrtc, webrtc_gst_slot_s *source)
                goto exit;
        APPEND_ELEMENT(element_list, videoswitch);
 
-       if (!(videoconvert = _create_element(DEFAULT_ELEMENT_VIDEOCONVERT, NULL)))
-               goto exit;
-       APPEND_ELEMENT(element_list, videoconvert);
+       if (!source->zerocopy_enabled) {
+               if (!(videoconvert = _create_element(DEFAULT_ELEMENT_VIDEOCONVERT, NULL)))
+                       goto exit;
+               APPEND_ELEMENT(element_list, videoconvert);
+       }
 
        if ((ret = __create_rest_of_elements(webrtc, source, true, &element_list)) != WEBRTC_ERROR_NONE)
                goto exit;
@@ -3829,3 +3842,91 @@ int _get_display_visible_from_loopback(webrtc_s *webrtc, unsigned int track_id,
 
        return WEBRTC_ERROR_NONE;
 }
+
+int _set_screen_source_crop(webrtc_s *webrtc, unsigned int source_id, int x, int y, int w, int h, bool portrait_mode, int *width, int *height)
+{
+       webrtc_gst_slot_s *source = NULL;
+       GstElement *screen_source = NULL;
+       GstElement *videocrop = NULL;
+       int src_width, src_height, output_width, output_height;
+       int mirroring_x, mirroring_y, mirroring_width, mirroring_height;
+       float rw, rh;
+       int left, right, top, bottom;
+
+       RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+       RET_VAL_IF(source_id == 0, WEBRTC_ERROR_INVALID_PARAMETER, "source_id is 0");
+       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->type != WEBRTC_MEDIA_SOURCE_TYPE_SCREEN, WEBRTC_ERROR_INVALID_PARAMETER, "source type is not screen");
+       RET_VAL_IF(w == 0, WEBRTC_ERROR_INVALID_PARAMETER, "w is 0");
+       RET_VAL_IF(h == 0, WEBRTC_ERROR_INVALID_PARAMETER, "h is 0");
+       RET_VAL_IF(width == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "width is NULL");
+       RET_VAL_IF(height == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "height is NULL");
+
+       screen_source =  gst_bin_get_by_name(source->bin, DEFAULT_NAME_SCREENSRC);
+       RET_VAL_IF(screen_source == NULL, WEBRTC_ERROR_INVALID_OPERATION, "sreen_source is NULL");
+
+       videocrop =  gst_bin_get_by_name(source->bin, DEFAULT_NAME_VIDEOCROP);
+       RET_VAL_IF(videocrop == NULL, WEBRTC_ERROR_INVALID_OPERATION, "videocrop is NULL");
+
+       LOG_INFO("set source crop x:%d, y:%d, width:%d, height:%d, mode:%s", x, y, w, h, (portrait_mode) ? "portrait" : "landscape");
+
+       g_object_get(G_OBJECT(screen_source),
+                       portrait_mode ? "mirroring-v-src-width" : "mirroring-h-src-width", &src_width,
+                       portrait_mode ? "mirroring-v-src-height" : "mirroring-h-src-height", &src_height,
+                       portrait_mode ? "mirroring-v-x" : "mirroring-h-x", &mirroring_x,
+                       portrait_mode ? "mirroring-v-y" : "mirroring-h-y", &mirroring_y,
+                       portrait_mode ? "mirroring-v-width" : "mirroring-h-width", &mirroring_width,
+                       portrait_mode ? "mirroring-v-height" : "mirroring-h-height", &mirroring_height,
+                       "output-width", &output_width,
+                       "output-height", &output_height,
+                       NULL);
+
+       rw = (float)src_width / mirroring_width;
+       rh = (float)src_height / mirroring_height;
+       left = mirroring_x + ((float)x / rw);
+       right = output_width - (left + (float)w / rw);
+       top = mirroring_y + ((float)y /rh);
+       bottom = output_height - (top + (float)h / rh);
+
+       LOG_INFO("Screen source info: source[width:%d, height:%d], output[width:%d, height:%d]"
+               "mirroring[x:%d y:%d width:%d, height:%d", src_width, src_height, output_width,
+               output_height, mirroring_x, mirroring_y, mirroring_width, mirroring_height);
+
+       g_object_set(G_OBJECT(videocrop), "left", left, "right", right, "top", top,
+                       "bottom", bottom, NULL);
+
+       LOG_INFO("cropped: left:%d, right:%d, top:%d, bottom:%d", left, right, top, bottom);
+
+       *width = output_width - (left + right);
+       *height = output_height - (top + bottom);
+       LOG_INFO("source_id[%u], video resolution is changed [%dx%d] ==> [%dx%d]", source_id,
+                       output_width, output_height, *width, *height);
+
+       return WEBRTC_ERROR_NONE;
+}
+
+int _unset_screen_source_crop(webrtc_s *webrtc, unsigned int source_id)
+{
+       webrtc_gst_slot_s *source = NULL;
+       GstElement *videocrop = NULL;
+       GstElement *screen_source = NULL;
+       int left, right, top, bottom;
+
+       RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+       RET_VAL_IF(source_id == 0, WEBRTC_ERROR_INVALID_PARAMETER, "source_id is 0");
+       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->type != WEBRTC_MEDIA_SOURCE_TYPE_SCREEN, WEBRTC_ERROR_INVALID_PARAMETER, "source type is not screen");
+
+       screen_source =  gst_bin_get_by_name(source->bin, DEFAULT_NAME_SCREENSRC);
+       RET_VAL_IF(screen_source == NULL, WEBRTC_ERROR_INVALID_OPERATION, "sreen_source is NULL");
+
+       videocrop =  gst_bin_get_by_name(source->bin, DEFAULT_NAME_VIDEOCROP);
+       RET_VAL_IF(videocrop == NULL, WEBRTC_ERROR_INVALID_OPERATION, "videocrop is NULL");
+
+       g_object_get(G_OBJECT(videocrop), "left", &left, "right", &right, "top", &top, "bottom", &bottom, NULL);
+       RET_VAL_IF(left == 0 && right == 0 && top == 0 && bottom == 0, WEBRTC_ERROR_INVALID_OPERATION, "webrtc_screen_source_set_crop was not set");
+
+       g_object_set(G_OBJECT(videocrop), "left", 0, "right", 0, "top", 0, "bottom", 0, NULL);
+
+       return WEBRTC_ERROR_NONE;
+}
index 6cce4113a84c4aed7c055a4e38b63d00ff5de626..0fc4867b6875d9afc098a96a051cf6da9109e8a6 100644 (file)
@@ -98,6 +98,8 @@ enum {
        CURRENT_STATUS_CREATE_PRIVATE_SIGNALING_SERVER,
        CURRENT_STATUS_CONNECT_TO_PRIVATE_SIGNALING_SERVER,
        CURRENT_STATUS_MUTE_MEDIA_SOURCE,
+       CURRENT_STATUS_SET_CROP_SCREEN_SOURCE,
+       CURRENT_STATUS_UNSET_CROP_SCREEN_SOURCE,
        CURRENT_STATUS_TERMINATE,
 };
 
@@ -1071,6 +1073,26 @@ static void _webrtc_media_source_set_mute(int index, unsigned int source_id, web
                g_print("webrtc_media_source_get_mute() success, source_id[%d], mute_status[%d]\n", source_id, mute_status);
 }
 
+static void _webrtc_screen_source_set_crop(int index, unsigned int source_id, int x, int y, int w, int h, int is_vertical, int *width, int *height)
+{
+       int ret = WEBRTC_ERROR_NONE;
+
+       ret = webrtc_screen_source_set_crop(g_conns[index].webrtc, source_id, x, y, w, h, is_vertical, width, height);
+       if (ret != WEBRTC_ERROR_NONE)
+               g_print("failed to webrtc_screen_source_set_crop(), source_id[%d], ret[0x%x]\n", source_id, ret);
+
+       g_print("cropped video resolution[%dx%d]\n", *width, *height);
+}
+
+static void _webrtc_screen_source_unset_crop(int index, unsigned int source_id)
+{
+       int ret = WEBRTC_ERROR_NONE;
+
+       ret = webrtc_screen_source_unset_crop(g_conns[index].webrtc, source_id);
+       if (ret != WEBRTC_ERROR_NONE)
+               g_print("failed to webrtc_screen_source_unset_crop(), source_id[%d], ret[0x%x]\n", source_id, ret);
+}
+
 static void __offer_created_cb(webrtc_h webrtc, const char *description, void *user_data)
 {
        connection_s *conn = (connection_s *)user_data;
@@ -3728,6 +3750,12 @@ void _interpret_main_menu(char *cmd)
                } else if (strncmp(cmd, "scd", 3) == 0) {
                        _webrtc_signaling_disconnect(g_conn_index);
 
+               } else if (strncmp(cmd, "scs", 3) == 0) {
+                               g_conns[g_conn_index].menu_state = CURRENT_STATUS_SET_CROP_SCREEN_SOURCE;
+
+               } else if (strncmp(cmd, "ucs", 3) == 0) {
+                               g_conns[g_conn_index].menu_state = CURRENT_STATUS_UNSET_CROP_SCREEN_SOURCE;
+
                } else {
                        g_print("unknown menu \n");
                }
@@ -3819,6 +3847,8 @@ void display_sub_basic()
        g_print("gv. Get display visible\n");
        g_print("al. Set audio loopback\t");
        g_print("vl. Set video loopback\n");
+       g_print("scs. Set crop screen source\n");
+       g_print("ucs. Unset crop screen source\n");
        g_print("------------------------------------- Data Channel --------------------------------------\n");
        g_print("cd. Create data channel\t");
        g_print("dd. Destroy data channel\n");
@@ -3990,6 +4020,24 @@ static void displaymenu()
                else if (g_conns[g_conn_index].cnt == 2)
                        g_print("*** input mute mode.(0:unmuted 1:muted)\n");
 
+       } else if (g_conns[g_conn_index].menu_state == CURRENT_STATUS_SET_CROP_SCREEN_SOURCE) {
+               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 x.\n");
+               else if (g_conns[g_conn_index].cnt == 2)
+                       g_print("*** input y.\n");
+               else if (g_conns[g_conn_index].cnt == 3)
+                       g_print("*** input width.\n");
+               else if (g_conns[g_conn_index].cnt == 4)
+                       g_print("*** input height.\n");
+               else if (g_conns[g_conn_index].cnt == 5)
+                       g_print("*** input whether screen rotates (0: horizontal, 1: vertical).\n");
+
+       } else if (g_conns[g_conn_index].menu_state == CURRENT_STATUS_UNSET_CROP_SCREEN_SOURCE) {
+               if (g_conns[g_conn_index].cnt == 0)
+                       g_print("*** input source id.\n");
+
        } else if (g_conns[g_conn_index].menu_state == CURRENT_STATUS_SET_STUN_SERVER) {
                g_print("*** input STUN server address.\n");
 
@@ -4467,6 +4515,53 @@ static void interpret(char *cmd)
                }
                break;
        }
+       case CURRENT_STATUS_SET_CROP_SCREEN_SOURCE: {
+               static unsigned int id;
+               static int x;
+               static int y;
+               static int w;
+               static int h;
+               static int is_vertical;
+               value = atoi(cmd);
+
+               switch (g_conns[g_conn_index].cnt) {
+               case 0:
+                       id = value;
+                       g_conns[g_conn_index].cnt++;
+                       break;
+               case 1:
+                       x = value;
+                       g_conns[g_conn_index].cnt++;
+                       break;
+               case 2:
+                       y =  value;
+                       g_conns[g_conn_index].cnt++;
+                       break;
+               case 3:
+                       w = value;
+                       g_conns[g_conn_index].cnt++;
+                       break;
+               case 4:
+                       h = value;
+                       g_conns[g_conn_index].cnt++;
+                       break;
+               case 5:
+                       is_vertical = value;
+                       int width, height;
+                       _webrtc_screen_source_set_crop(g_conn_index, id, x, y, w, h, is_vertical, &width, &height);
+                       x = y = w = h = is_vertical = 0;
+                       g_conns[g_conn_index].cnt = 0;
+                       reset_menu_state();
+                       break;
+               }
+               break;
+       }
+       case CURRENT_STATUS_UNSET_CROP_SCREEN_SOURCE: {
+               value = atoi(cmd);
+               _webrtc_screen_source_unset_crop(g_conn_index, value);
+               reset_menu_state();
+               break;
+       }
        case CURRENT_STATUS_MUTE_MEDIA_SOURCE: {
                static unsigned int id;
                static unsigned int media_type;