diff --git a/src/include/switch_core_media.h b/src/include/switch_core_media.h index 105cd50f97..c84416c86e 100644 --- a/src/include/switch_core_media.h +++ b/src/include/switch_core_media.h @@ -249,6 +249,8 @@ SWITCH_DECLARE(switch_core_media_params_t *) switch_core_media_get_mparams(switc SWITCH_DECLARE(void) switch_core_media_prepare_codecs(switch_core_session_t *session, switch_bool_t force); SWITCH_DECLARE(void) switch_core_media_start_udptl(switch_core_session_t *session, switch_t38_options_t *t38_options); SWITCH_DECLARE(void) switch_core_media_hard_mute(switch_core_session_t *session, switch_bool_t on); +SWITCH_DECLARE(cJSON *) switch_core_media_gen_json_constraint(float min, float ideal, float max); +SWITCH_DECLARE(switch_status_t) switch_core_media_media_params(switch_core_session_t *session, const char *json); SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg); diff --git a/src/include/switch_types.h b/src/include/switch_types.h index bfbdb9c3ce..2baddf0101 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1137,6 +1137,7 @@ typedef enum { SWITCH_MESSAGE_INDICATE_DEFLECT, SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ, SWITCH_MESSAGE_INDICATE_DISPLAY, + SWITCH_MESSAGE_INDICATE_MEDIA_PARAMS, SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY, SWITCH_MESSAGE_INDICATE_AUDIO_SYNC, SWITCH_MESSAGE_INDICATE_VIDEO_SYNC, @@ -1532,6 +1533,7 @@ typedef enum { CF_INTERCEPTED, CF_VIDEO_REFRESH_REQ, CF_MANUAL_VID_REFRESH, + CF_MANUAL_MEDIA_PARAMS, CF_SERVICE_AUDIO, CF_SERVICE_VIDEO, CF_ZRTP_PASSTHRU_REQ, diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 5d8313e5c5..960268cd4f 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -4041,6 +4041,46 @@ SWITCH_STANDARD_API(uuid_display_function) return SWITCH_STATUS_SUCCESS; } +#define MEDIA_PARAMS_SYNTAX " " +SWITCH_STANDARD_API(uuid_media_params_function) +{ + char *mycmd = NULL, *argv[2] = { 0 }; + int argc = 0; + switch_status_t status = SWITCH_STATUS_FALSE; + switch_core_session_t *tsession = NULL; + + if (!zstr(cmd) && (mycmd = strdup(cmd))) { + argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + } + + if (zstr(cmd) || argc < 2 || zstr(argv[0]) || zstr(argv[1])) { + stream->write_function(stream, "-USAGE: %s\n", MEDIA_PARAMS_SYNTAX); + goto end; + } else { + if ((tsession = switch_core_session_locate(argv[0]))) { + switch_channel_t *channel = switch_core_session_get_channel(session); + + if (switch_false(argv[1])) { + switch_channel_clear_flag(channel, CF_MANUAL_MEDIA_PARAMS); + } else if ((status = switch_core_media_media_params(tsession, argv[1])) == SWITCH_STATUS_SUCCESS) { + switch_channel_set_flag(channel, CF_MANUAL_MEDIA_PARAMS); + } + switch_core_session_rwunlock(tsession); + } + } + + if (status == SWITCH_STATUS_SUCCESS) { + stream->write_function(stream, "+OK Success\n"); + } else { + stream->write_function(stream, "-ERR Operation failed\n"); + } + + end: + + switch_safe_free(mycmd); + return SWITCH_STATUS_SUCCESS; +} + #define BUGLIST_SYNTAX "" SWITCH_STANDARD_API(uuid_buglist_function) { @@ -7636,6 +7676,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "uuid_deflect", "Send a deflect", uuid_deflect, UUID_DEFLECT_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_displace", "Displace audio", session_displace_function, " [start|stop] [] [mux]"); SWITCH_ADD_API(commands_api_interface, "uuid_display", "Update phone display", uuid_display_function, DISPLAY_SYNTAX); + SWITCH_ADD_API(commands_api_interface, "uuid_media_params", "Update remote vid params", uuid_media_params_function, MEDIA_PARAMS_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_drop_dtmf", "Drop all DTMF or replace it with a mask", uuid_drop_dtmf, UUID_DROP_DTMF_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_dump", "Dump session vars", uuid_dump_function, DUMP_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_exists", "Check if a uuid exists", uuid_exists_function, EXISTS_SYNTAX); @@ -7827,6 +7868,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) switch_console_set_complete("add uuid_deflect ::console::list_uuid"); switch_console_set_complete("add uuid_displace ::console::list_uuid"); switch_console_set_complete("add uuid_display ::console::list_uuid"); + switch_console_set_complete("add uuid_media_params ::console::list_uuid"); switch_console_set_complete("add uuid_drop_dtmf ::console::list_uuid"); switch_console_set_complete("add uuid_dump ::console::list_uuid"); switch_console_set_complete("add uuid_answer ::console::list_uuid"); diff --git a/src/mod/endpoints/mod_verto/mod_verto.c b/src/mod/endpoints/mod_verto/mod_verto.c index c5f2a1afb5..4420f86a21 100644 --- a/src/mod/endpoints/mod_verto/mod_verto.c +++ b/src/mod/endpoints/mod_verto/mod_verto.c @@ -2636,6 +2636,33 @@ static switch_status_t messagehook (switch_core_session_t *session, switch_core_ } } break; + case SWITCH_MESSAGE_INDICATE_MEDIA_PARAMS: + { + const char *json_text; + cJSON *jmsg = NULL, *params = NULL, *vparams = NULL; + jsock_t *jsock = NULL; + + if ((jsock = get_jsock(tech_pvt->jsock_uuid))) { + + json_text = msg->string_arg; + + if (json_text) { + jmsg = jrpc_new_req("verto.mediaParams", tech_pvt->call_id, ¶ms); + if ((vparams = cJSON_Parse((char *)json_text))) { + cJSON_AddItemToObject(params, "mediaParams", vparams); + jsock_queue_event(jsock, &jmsg, SWITCH_TRUE); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error Parsing Media Params\n"); + r = SWITCH_STATUS_FALSE; + cJSON_Delete(jmsg); + } + } + + switch_thread_rwlock_unlock(jsock->rwlock); + } + + } + break; case SWITCH_MESSAGE_INDICATE_MEDIA_RENEG: { jsock_t *jsock = NULL; diff --git a/src/switch_core_media.c b/src/switch_core_media.c index 71c02aa6a9..b6cb4b6670 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -12429,6 +12429,149 @@ SWITCH_DECLARE(void) switch_core_media_hard_mute(switch_core_session_t *session, switch_core_session_receive_message(session, &msg); } +SWITCH_DECLARE(cJSON *) switch_core_media_gen_json_constraint(float min, float ideal, float max) +{ + cJSON *ret = NULL, *n = NULL; + + if ((!ideal && !max)) { + ret = cJSON_CreateNumber(min); + } else { + ret = cJSON_CreateObject(); + n = cJSON_CreateNumber(min); + cJSON_AddItemToObject(ret, "min", n); + + if (ideal) { + n = cJSON_CreateNumber(ideal); + cJSON_AddItemToObject(ret, "ideal", n); + } + + if (max) { + n = cJSON_CreateNumber(max); + cJSON_AddItemToObject(ret, "max", n); + } + } + + return ret; +} + +static cJSON *parse_val(char *str) { + char *argv[3]; + int argc = 0; + float min = 0, ideal = 0, max = 0; + + argc = switch_separate_string(str, ':', argv, (sizeof(argv) / sizeof(argv[0]))); + + if (argc > 0) { + min = atof(argv[0]); + } + + if (argc > 1) { + ideal = atof(argv[1]); + } + + if (argc > 2) { + max = atof(argv[2]); + } + + return switch_core_media_gen_json_constraint(min, ideal, max); + +} + +SWITCH_DECLARE(switch_status_t) switch_core_media_media_params(switch_core_session_t *session, const char *json) +{ + switch_core_session_message_t msg = { 0 }; + char *parse = NULL; + char *argv[25]; + int argc = 0, i; + switch_status_t r = SWITCH_STATUS_SUCCESS; + cJSON *obj = NULL; + char *aspect = NULL, *fps = NULL, *width = NULL, *height = NULL, *jtmp = NULL; + + + if (switch_channel_test_flag(session->channel, CF_MANUAL_MEDIA_PARAMS)) { + return SWITCH_STATUS_INUSE; + } + + if (switch_stristr("=", json)) { + char *name, *val; + cJSON *video, *p; + int vid = 0; + + parse = strdup(json); + argc = switch_separate_string(parse, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + + for(i = 0; i < argc; i++) { + name = argv[i]; + if ((val = strchr(name, '='))) { + *val++ = '\0'; + } + + if (name && val) { + if (!strcmp(name, "aspect")) { + aspect = val; + vid++; + } else if (!strcmp(name, "fps")) { + fps = val; + vid++; + } else if (!strcmp(name, "width")) { + width = val; + vid++; + } else if (!strcmp(name, "height")) { + height = val; + vid++; + } + } + } + + obj = cJSON_CreateObject(); + + if (vid) { + video = cJSON_CreateObject(); + + if (fps) { + p = parse_val(fps); + cJSON_AddItemToObject(video, "frameRate", p); + } + + if (width) { + p = parse_val(width); + cJSON_AddItemToObject(video, "width", p); + } + + if (height) { + p = parse_val(height); + cJSON_AddItemToObject(video, "height", p); + } + + if (aspect) { + p = cJSON_CreateNumber(atof(aspect)); + cJSON_AddItemToObject(video, "aspectRatio", p); + } + + cJSON_AddItemToObject(obj, "video", video); + } + + jtmp = cJSON_PrintUnformatted(obj); + json = jtmp; + } + + + + msg.from = __FILE__; + + msg.message_id = SWITCH_MESSAGE_INDICATE_MEDIA_PARAMS; + msg.string_arg = json; + r = switch_core_session_receive_message(session, &msg); + + switch_safe_free(parse); + switch_safe_free(jtmp); + if (obj) { + cJSON_Delete(obj); + } + + return r; +} + static int check_engine(switch_rtp_engine_t *engine) { dtls_state_t dtls_state = switch_rtp_dtls_state(engine->rtp_session, DTLS_TYPE_RTP);