mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-23 20:51:58 +00:00
Merge branch 'master' into v1.4.beta
This commit is contained in:
@@ -558,11 +558,13 @@ opal
|
||||
/spandsp/src/Makefile.in
|
||||
/spandsp/src/make_math_fixed_tables
|
||||
/spandsp/src/make_modem_filter
|
||||
/spandsp/src/make_t43_gray_code_tables
|
||||
/spandsp/src/math_fixed_tables.h
|
||||
/spandsp/src/msvc/All/BuildLog make_at_dictionary.htm
|
||||
/spandsp/src/msvc/All/BuildLog make_modem_filter.htm
|
||||
/spandsp/src/spandsp.h
|
||||
/spandsp/src/stamp-h1
|
||||
/spandsp/src/t43_gray_code_tables.h
|
||||
/spandsp/src/v17_v32bis_rx_fixed_rrc.h
|
||||
/spandsp/src/v17_v32bis_rx_floating_rrc.h
|
||||
/spandsp/src/v17_v32bis_tx_fixed_rrc.h
|
||||
|
||||
@@ -1 +1 @@
|
||||
Wed Jul 3 11:09:02 CDT 2013
|
||||
Thu Jul 11 17:38:06 CDT 2013
|
||||
|
||||
@@ -590,7 +590,7 @@ static void print_media(sdp_printer_t *p,
|
||||
case sdp_proto_udp: proto = "udp"; break;
|
||||
case sdp_proto_rtp: proto = "RTP/AVP"; break;
|
||||
case sdp_proto_srtp: proto = "RTP/SAVP"; break;
|
||||
case sdp_proto_extended_srtp: proto = "RTP/SAVPF"; break;
|
||||
//case sdp_proto_extended_srtp: proto = "RTP/SAVPF"; break;
|
||||
case sdp_proto_udptl: proto = "udptl"; break;
|
||||
case sdp_proto_msrp: proto = "TCP/MSRP"; break;
|
||||
case sdp_proto_msrps: proto = "TCP/TLS/MSRP"; break;
|
||||
|
||||
@@ -139,6 +139,7 @@ SWITCH_DECLARE(void) switch_rtp_shutdown(void);
|
||||
SWITCH_DECLARE(switch_port_t) switch_rtp_set_start_port(switch_port_t port);
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtp_set_ssrc(switch_rtp_t *rtp_session, uint32_t ssrc);
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_ssrc(switch_rtp_t *rtp_session, uint32_t ssrc);
|
||||
|
||||
/*!
|
||||
\brief Set/Get RTP end port
|
||||
|
||||
@@ -1326,6 +1326,7 @@ typedef enum {
|
||||
CF_DTLS_OK,
|
||||
CF_VIDEO_PASSIVE,
|
||||
CF_NOVIDEO,
|
||||
CF_VIDEO_ECHO,
|
||||
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
|
||||
/* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */
|
||||
CF_FLAG_MAX
|
||||
|
||||
@@ -598,31 +598,39 @@ switch_mutex_unlock(obj->flag_mutex);
|
||||
|
||||
#define switch_set_string(_dst, _src) switch_copy_string(_dst, _src, sizeof(_dst))
|
||||
|
||||
SWITCH_DECLARE(char *) switch_url_encode(const char *url, char *buf, size_t len);
|
||||
SWITCH_DECLARE(char *) switch_url_decode(char *s);
|
||||
|
||||
static inline char *switch_sanitize_number(char *number)
|
||||
{
|
||||
char *p = number, *q;
|
||||
char *p, *q;
|
||||
char warp[] = "/:";
|
||||
int i;
|
||||
char *val;
|
||||
|
||||
switch_assert(number);
|
||||
|
||||
if (!(strchr(p, '/') || strchr(p, ':') || strchr(p, '@') || strchr(p, '%'))) {
|
||||
p = strdup(number);
|
||||
val = p;
|
||||
switch_url_decode(val);
|
||||
|
||||
if (!(strchr(val, '/') || strchr(val, ':') || strchr(val, '@') || strchr(val, '%'))) {
|
||||
return number;
|
||||
}
|
||||
|
||||
while ((q = strrchr(p, '@')))
|
||||
while ((q = strrchr(val, '@')))
|
||||
*q = '\0';
|
||||
|
||||
while ((q = strrchr(p, '%')))
|
||||
while ((q = strrchr(val, '%')))
|
||||
*q = '\0';
|
||||
|
||||
for (i = 0; i < (int) strlen(warp); i++) {
|
||||
while (p && (q = strchr(p, warp[i])))
|
||||
p = q + 1;
|
||||
while (val && (q = strchr(val, warp[i])))
|
||||
val = q + 1;
|
||||
}
|
||||
free(p);
|
||||
|
||||
return p;
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline switch_bool_t switch_string_var_check(char *s, switch_bool_t disable)
|
||||
@@ -930,8 +938,6 @@ SWITCH_DECLARE(char *) switch_util_quote_shell_arg_pool(const char *string, swit
|
||||
|
||||
|
||||
#define SWITCH_READ_ACCEPTABLE(status) (status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK)
|
||||
SWITCH_DECLARE(char *) switch_url_encode(const char *url, char *buf, size_t len);
|
||||
SWITCH_DECLARE(char *) switch_url_decode(char *s);
|
||||
SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to,
|
||||
const char *from,
|
||||
const char *headers,
|
||||
|
||||
@@ -201,7 +201,8 @@ typedef enum {
|
||||
CFLAG_VIDEO_BRIDGE = (1 << 14),
|
||||
CFLAG_AUDIO_ALWAYS = (1 << 15),
|
||||
CFLAG_ENDCONF_FORCED = (1 << 16),
|
||||
CFLAG_RFC4579 = (1 << 17)
|
||||
CFLAG_RFC4579 = (1 << 17),
|
||||
CFLAG_FLOOR_CHANGE = (1 << 18)
|
||||
} conf_flag_t;
|
||||
|
||||
typedef enum {
|
||||
@@ -394,6 +395,7 @@ typedef struct conference_relationship {
|
||||
struct conference_member {
|
||||
uint32_t id;
|
||||
switch_core_session_t *session;
|
||||
switch_channel_t *channel;
|
||||
conference_obj_t *conference;
|
||||
switch_memory_pool_t *pool;
|
||||
switch_buffer_t *audio_buffer;
|
||||
@@ -1443,15 +1445,20 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
|
||||
|
||||
conference_send_presence(conference);
|
||||
|
||||
|
||||
|
||||
channel = switch_core_session_get_channel(member->session);
|
||||
switch_channel_set_flag(channel, CF_VIDEO_PASSIVE);
|
||||
|
||||
switch_channel_set_variable_printf(channel, "conference_member_id", "%d", member->id);
|
||||
switch_channel_set_variable_printf(channel, "conference_moderator", "%s", switch_test_flag(member, MFLAG_MOD) ? "true" : "false");
|
||||
switch_channel_set_variable(channel, "conference_recording", conference->record_filename);
|
||||
switch_channel_set_variable(channel, CONFERENCE_UUID_VARIABLE, conference->uuid_str);
|
||||
|
||||
|
||||
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_VIDEO)) {
|
||||
switch_channel_clear_flag(channel, CF_VIDEO_ECHO);
|
||||
/* Tell the channel to request a fresh vid frame */
|
||||
switch_core_session_refresh_video(member->session);
|
||||
}
|
||||
|
||||
if (!switch_channel_get_variable(channel, "conference_call_key")) {
|
||||
char *key = switch_core_session_sprintf(member->session, "conf_%s_%s_%s",
|
||||
@@ -1565,6 +1572,20 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe
|
||||
return status;
|
||||
}
|
||||
|
||||
static void conference_set_floor_holder(conference_obj_t *conference, conference_member_t *member)
|
||||
{
|
||||
|
||||
if (conference->floor_holder && conference->floor_holder != member) {
|
||||
switch_channel_clear_flag(conference->floor_holder->channel, CF_VIDEO_PASSIVE);
|
||||
}
|
||||
|
||||
if ((conference->floor_holder = member)) {
|
||||
switch_channel_set_flag(member->channel, CF_VIDEO_PASSIVE);
|
||||
switch_core_session_refresh_video(conference->floor_holder->session);
|
||||
switch_set_flag(conference, CFLAG_FLOOR_CHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Gain exclusive access and remove the member from the list */
|
||||
static switch_status_t conference_del_member(conference_obj_t *conference, conference_member_t *member)
|
||||
{
|
||||
@@ -1648,7 +1669,9 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe
|
||||
}
|
||||
|
||||
if (member == member->conference->floor_holder) {
|
||||
member->conference->floor_holder = NULL;
|
||||
//member->conference->floor_holder = NULL;
|
||||
conference_set_floor_holder(member->conference, NULL);
|
||||
|
||||
|
||||
if (test_eflag(conference, EFLAG_FLOOR_CHANGE)) {
|
||||
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT);
|
||||
@@ -1673,7 +1696,10 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe
|
||||
}
|
||||
}
|
||||
|
||||
switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE);
|
||||
if (switch_channel_test_flag(channel, CF_VIDEO)) {
|
||||
switch_channel_set_flag(channel, CF_VIDEO_ECHO);
|
||||
switch_channel_clear_flag(channel, CF_VIDEO_PASSIVE);
|
||||
}
|
||||
|
||||
conference_send_presence(conference);
|
||||
switch_channel_set_variable(channel, "conference_call_key", NULL);
|
||||
@@ -1839,19 +1865,15 @@ static void *SWITCH_THREAD_FUNC conference_video_thread_run(switch_thread_t *thr
|
||||
conference_member_t *imember;
|
||||
switch_frame_t *vid_frame;
|
||||
switch_status_t status;
|
||||
int has_vid = 1, want_refresh = 0;
|
||||
int want_refresh = 0;
|
||||
int yield = 0;
|
||||
switch_core_session_t *session;
|
||||
switch_core_session_message_t msg = { 0 };
|
||||
char buf[65536];
|
||||
|
||||
conference->video_running = 1;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Video thread started for conference %s\n", conference->name);
|
||||
|
||||
/* Tell the channel to request a fresh vid frame */
|
||||
msg.from = __FILE__;
|
||||
msg.message_id = SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ;
|
||||
|
||||
while (has_vid && conference->video_running == 1 && globals.running && !switch_test_flag(conference, CFLAG_DESTRUCT)) {
|
||||
while (conference->video_running == 1 && globals.running && !switch_test_flag(conference, CFLAG_DESTRUCT)) {
|
||||
if (yield) {
|
||||
switch_yield(yield);
|
||||
yield = 0;
|
||||
@@ -1887,12 +1909,21 @@ static void *SWITCH_THREAD_FUNC conference_video_thread_run(switch_thread_t *thr
|
||||
goto do_continue;
|
||||
}
|
||||
|
||||
if (vid_frame && switch_test_flag(vid_frame, SFF_CNG)) {
|
||||
yield = 10000;
|
||||
goto do_continue;
|
||||
}
|
||||
|
||||
memcpy(buf, vid_frame->packet, vid_frame->packetlen);
|
||||
|
||||
switch_mutex_unlock(conference->mutex);
|
||||
switch_mutex_lock(conference->mutex);
|
||||
has_vid = 0;
|
||||
want_refresh = 0;
|
||||
|
||||
if (switch_test_flag(conference, CFLAG_FLOOR_CHANGE)) {
|
||||
switch_clear_flag(conference, CFLAG_FLOOR_CHANGE);
|
||||
}
|
||||
|
||||
for (imember = conference->members; imember; imember = imember->next) {
|
||||
switch_core_session_t *isession = imember->session;
|
||||
switch_channel_t *ichannel;
|
||||
@@ -1908,21 +1939,20 @@ static void *SWITCH_THREAD_FUNC conference_video_thread_run(switch_thread_t *thr
|
||||
switch_channel_clear_flag(ichannel, CF_VIDEO_REFRESH_REQ);
|
||||
}
|
||||
|
||||
if (imember->session && switch_channel_test_flag(ichannel, CF_VIDEO)) {
|
||||
has_vid++;
|
||||
if (isession && switch_channel_test_flag(ichannel, CF_VIDEO)) {
|
||||
memcpy(vid_frame->packet, buf, vid_frame->packetlen);
|
||||
switch_core_session_write_video_frame(imember->session, vid_frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
}
|
||||
|
||||
switch_core_session_rwunlock(isession);
|
||||
}
|
||||
|
||||
if (want_refresh) {
|
||||
switch_core_session_receive_message(session, &msg);
|
||||
if (want_refresh && session) {
|
||||
switch_core_session_refresh_video(session);
|
||||
want_refresh = 0;
|
||||
}
|
||||
|
||||
do_continue:
|
||||
|
||||
switch_mutex_unlock(conference->mutex);
|
||||
}
|
||||
|
||||
@@ -2078,7 +2108,8 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
|
||||
}
|
||||
}
|
||||
|
||||
conference->floor_holder = floor_holder;
|
||||
//conference->floor_holder = floor_holder;
|
||||
conference_set_floor_holder(conference, floor_holder);
|
||||
}
|
||||
|
||||
|
||||
@@ -5219,7 +5250,8 @@ static switch_status_t conf_api_sub_floor(conference_member_t *member, switch_st
|
||||
switch_mutex_lock(member->conference->mutex);
|
||||
|
||||
if (member->conference->floor_holder == member) {
|
||||
member->conference->floor_holder = NULL;
|
||||
//member->conference->floor_holder = NULL;
|
||||
conference_set_floor_holder(member->conference, NULL);
|
||||
if (test_eflag(member->conference, EFLAG_FLOOR_CHANGE)) {
|
||||
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT);
|
||||
conference_add_event_data(member->conference, event);
|
||||
@@ -5232,7 +5264,8 @@ static switch_status_t conf_api_sub_floor(conference_member_t *member, switch_st
|
||||
}
|
||||
}
|
||||
} else if (member->conference->floor_holder == NULL) {
|
||||
member->conference->floor_holder = member;
|
||||
//member->conference->floor_holder = member;
|
||||
conference_set_floor_holder(member->conference, member);
|
||||
if (test_eflag(member->conference, EFLAG_FLOOR_CHANGE)) {
|
||||
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT);
|
||||
conference_add_event_data(member->conference, event);
|
||||
@@ -5272,7 +5305,8 @@ static switch_status_t conf_api_sub_enforce_floor(conference_member_t *member, s
|
||||
|
||||
if (member->conference->floor_holder != member) {
|
||||
conference_member_t *old_member = member->conference->floor_holder;
|
||||
member->conference->floor_holder = member;
|
||||
//member->conference->floor_holder = member;
|
||||
conference_set_floor_holder(member->conference, member);
|
||||
if (test_eflag(member->conference, EFLAG_FLOOR_CHANGE)) {
|
||||
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT);
|
||||
conference_add_event_data(member->conference, event);
|
||||
@@ -7781,6 +7815,7 @@ SWITCH_STANDARD_APP(conference_function)
|
||||
}
|
||||
|
||||
member.session = session;
|
||||
member.channel = switch_core_session_get_channel(session);
|
||||
member.pool = switch_core_session_get_pool(session);
|
||||
|
||||
if (setup_media(&member, conference)) {
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
/*****************************************************************************/
|
||||
/* SKINNY FUNCTIONS */
|
||||
/*****************************************************************************/
|
||||
char* skinny_codec2string(enum skinny_codecs skinnycodec)
|
||||
char* skinny_codec2string(skinny_codecs skinnycodec)
|
||||
{
|
||||
switch (skinnycodec) {
|
||||
case SKINNY_CODEC_ALAW_64K:
|
||||
@@ -155,8 +155,8 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
|
||||
memcpy(request, mbuf, bytes);
|
||||
#ifdef SKINNY_MEGA_DEBUG
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
||||
"Got request: length=%d,reserved=%x,type=%x\n",
|
||||
request->length,request->reserved,request->type);
|
||||
"Got request: length=%d,version=%x,type=%x\n",
|
||||
request->length,request->version,request->type);
|
||||
#endif
|
||||
if(request->length < SKINNY_MESSAGE_FIELD_SIZE) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
@@ -623,6 +623,26 @@ switch_status_t perform_send_set_speaker_mode(listener_t *listener,
|
||||
return skinny_send_reply_quiet(listener, message);
|
||||
}
|
||||
|
||||
switch_status_t perform_send_srvreq_response(listener_t *listener,
|
||||
const char *file, const char *func, int line,
|
||||
char *ip, uint32_t port)
|
||||
{
|
||||
skinny_message_t *message;
|
||||
|
||||
message = switch_core_alloc(listener->pool, 12+sizeof(message->data.serv_res_mess));
|
||||
message->type = SERVER_RESPONSE_MESSAGE;
|
||||
message->length = 4 + sizeof(message->data.serv_res_mess);
|
||||
|
||||
message->data.serv_res_mess.serverListenPort[0] = port;
|
||||
switch_inet_pton(AF_INET,ip, &message->data.serv_res_mess.serverIpAddr[0]);
|
||||
switch_copy_string(message->data.serv_res_mess.server[0].serverName,ip,sizeof(message->data.serv_res_mess.server[0].serverName));
|
||||
|
||||
skinny_log_l_ffl(listener, file, func, line, SWITCH_LOG_DEBUG,
|
||||
"Sending Server Request Response with IP (%s) and Port (%d)\n", ip, port);
|
||||
|
||||
return skinny_send_reply(listener, message);
|
||||
}
|
||||
|
||||
switch_status_t perform_send_start_media_transmission(listener_t *listener,
|
||||
const char *file, const char *func, int line,
|
||||
uint32_t conference_id,
|
||||
|
||||
@@ -36,6 +36,53 @@
|
||||
/* mod_skinny.h should be loaded first */
|
||||
#include "mod_skinny.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* SKINNY TYPES */
|
||||
/*****************************************************************************/
|
||||
typedef enum {
|
||||
SKINNY_CODEC_NONE = 0,
|
||||
SKINNY_CODEC_NONSTANDARD = 1,
|
||||
SKINNY_CODEC_ALAW_64K = 2,
|
||||
SKINNY_CODEC_ALAW_56K = 3,
|
||||
SKINNY_CODEC_ULAW_64K = 4,
|
||||
SKINNY_CODEC_ULAW_56K = 5,
|
||||
SKINNY_CODEC_G722_64K = 6,
|
||||
SKINNY_CODEC_G722_56K = 7,
|
||||
SKINNY_CODEC_G722_48K = 8,
|
||||
SKINNY_CODEC_G723_1 = 9,
|
||||
SKINNY_CODEC_G728 = 10,
|
||||
SKINNY_CODEC_G729 = 11,
|
||||
SKINNY_CODEC_G729A = 12,
|
||||
SKINNY_CODEC_IS11172 = 13,
|
||||
SKINNY_CODEC_IS13818 = 14,
|
||||
SKINNY_CODEC_G729B = 15,
|
||||
SKINNY_CODEC_G729AB = 16,
|
||||
SKINNY_CODEC_GSM_FULL = 18,
|
||||
SKINNY_CODEC_GSM_HALF = 19,
|
||||
SKINNY_CODEC_GSM_EFULL = 20,
|
||||
SKINNY_CODEC_WIDEBAND_256K = 25,
|
||||
SKINNY_CODEC_DATA_64K = 32,
|
||||
SKINNY_CODEC_DATA_56K = 33,
|
||||
SKINNY_CODEC_G722_1_32K = 40,
|
||||
SKINNY_CODEC_G722_1_24K = 41,
|
||||
SKINNY_CODEC_GSM = 80,
|
||||
SKINNY_CODEC_ACTIVEVOICE = 81,
|
||||
SKINNY_CODEC_G726_32K = 82,
|
||||
SKINNY_CODEC_G726_24K = 83,
|
||||
SKINNY_CODEC_G726_16K = 84,
|
||||
SKINNY_CODEC_G729B_BIS = 85,
|
||||
SKINNY_CODEC_G729B_LOW = 86,
|
||||
SKINNY_CODEC_H261 = 100,
|
||||
SKINNY_CODEC_H263 = 101,
|
||||
SKINNY_CODEC_VIDEO = 102,
|
||||
SKINNY_CODEC_H264 = 103,
|
||||
SKINNY_CODEC_T120 = 105,
|
||||
SKINNY_CODEC_H224 = 106,
|
||||
SKINNY_CODEC_RFC2833_DYNPAYLOAD = 257
|
||||
} skinny_codecs;
|
||||
|
||||
char* skinny_codec2string(skinny_codecs skinnycodec);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* SKINNY MESSAGE DATA */
|
||||
/*****************************************************************************/
|
||||
@@ -145,6 +192,8 @@ struct PACKED capabilities_res_message {
|
||||
struct station_capabilities caps[SWITCH_MAX_CODECS];
|
||||
};
|
||||
|
||||
#define SERVER_REQ_MESSAGE 0x0012
|
||||
|
||||
/* AlarmMessage */
|
||||
#define ALARM_MESSAGE 0x0020
|
||||
struct PACKED alarm_message {
|
||||
@@ -207,6 +256,147 @@ struct PACKED data_message {
|
||||
#define DEVICE_TO_USER_DATA_RESPONSE_MESSAGE 0x002F
|
||||
/* See struct PACKED data_message */
|
||||
|
||||
#define UPDATE_CAPABILITIES_MESSAGE 0x0030
|
||||
|
||||
#define MAX_CUSTOM_PICTURES 6
|
||||
#define MAX_LAYOUT_WITH_SAME_SERVICE 5
|
||||
#define MAX_SERVICE_TYPE 4
|
||||
#define SKINNY_MAX_CAPABILITIES 18 /*!< max capabilities allowed in Cap response message */
|
||||
#define SKINNY_MAX_VIDEO_CAPABILITIES 10
|
||||
#define SKINNY_MAX_DATA_CAPABILITIES 5
|
||||
#define MAX_LEVEL_PREFERENCE 4
|
||||
|
||||
/*!
|
||||
* \brief Picture Format Structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t custom_picture_format_width; /*!< Picture Width */
|
||||
uint32_t custom_picture_format_height; /*!< Picture Height */
|
||||
uint32_t custom_picture_format_pixelAspectRatio; /*!< Picture Pixel Aspect Ratio */
|
||||
uint32_t custom_picture_format_pixelclockConversionCode; /*!< Picture Pixel Conversion Code */
|
||||
uint32_t custom_picture_format_pixelclockDivisor; /*!< Picture Pixel Divisor */
|
||||
} custom_picture_format_t;
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Video Level Preference Structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t transmitPreference; /*!< Transmit Preference */
|
||||
uint32_t format; /*!< Format / Codec */
|
||||
uint32_t maxBitRate; /*!< Maximum BitRate */
|
||||
uint32_t minBitRate; /*!< Minimum BitRate */
|
||||
uint32_t MPI; /*!< */
|
||||
uint32_t serviceNumber; /*!< Service Number */
|
||||
} levelPreference_t; /*!< Level Preference Structure */
|
||||
|
||||
/*!
|
||||
* \brief Layout Config Structure (Update Capabilities Message Struct)
|
||||
* \since 20080111
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t layout; /*!< Layout \todo what is layout? */
|
||||
} layoutConfig_t; /*!< Layout Config Structure */
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Service Resource Structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t layoutCount; /*!< Layout Count */
|
||||
layoutConfig_t layout[MAX_LAYOUT_WITH_SAME_SERVICE]; /*!< Layout */
|
||||
uint32_t serviceNum; /*!< Service Number */
|
||||
uint32_t maxStreams; /*!< Maximum number of Streams */
|
||||
uint32_t maxConferences; /*!< Maximum number of Conferences */
|
||||
uint32_t activeConferenceOnRegistration; /*!< Active Conference On Registration */
|
||||
} serviceResource_t;
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Audio Capabilities Structure
|
||||
*/
|
||||
typedef struct {
|
||||
skinny_codecs payload_capability; /*!< PayLoad Capability */
|
||||
uint32_t maxFramesPerPacket; /*!< Maximum Number of Frames per IP Packet */
|
||||
uint32_t unknown[2]; /*!< this are related to G.723 */
|
||||
} audioCap_t;
|
||||
|
||||
/*!
|
||||
* \brief Video Capabilities Structure
|
||||
*/
|
||||
typedef struct {
|
||||
skinny_codecs payload_capability; /*!< PayLoad Capability */
|
||||
uint32_t transmitOreceive; /*!< Transmit of Receive */
|
||||
uint32_t levelPreferenceCount; /*!< Level of Preference Count */
|
||||
|
||||
levelPreference_t levelPreference[MAX_LEVEL_PREFERENCE]; /*!< Level Preference */
|
||||
|
||||
// uint32_t codec_options[2]; /*!< Codec Options */
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint32_t unknown1;
|
||||
uint32_t unknown2;
|
||||
} h263;
|
||||
struct {
|
||||
uint32_t profile; /*!< H264 profile */
|
||||
uint32_t level; /*!< H264 level */
|
||||
} h264;
|
||||
} codec_options;
|
||||
|
||||
/**
|
||||
* Codec options contains data specific for every codec
|
||||
*
|
||||
* Here is a list of known parameters per codec
|
||||
// H.261
|
||||
uint32_t temporalSpatialTradeOffCapability;
|
||||
uint32_t stillImageTransmission;
|
||||
|
||||
// H.263
|
||||
uint32_t h263_capability_bitfield;
|
||||
uint32_t annexNandWFutureUse;
|
||||
|
||||
// Video
|
||||
uint32_t modelNumber;
|
||||
uint32_t bandwidth;
|
||||
*/
|
||||
} videoCap_t; /*!< Video Capabilities Structure */
|
||||
|
||||
/*!
|
||||
* \brief Data Capabilities Structure
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t payload_capability; /*!< Payload Capability */
|
||||
uint32_t transmitOrReceive; /*!< Transmit or Receive */
|
||||
uint32_t protocolDependentData; /*!< Protocol Dependent Data */
|
||||
uint32_t maxBitRate; /*!< Maximum BitRate */
|
||||
} dataCap_t; /*!< Data Capabilities Structure */
|
||||
|
||||
|
||||
struct PACKED update_capabilities_message {
|
||||
uint32_t audio_cap_count; /*!< Audio Capability Count */
|
||||
uint32_t videoCapCount; /*!< Video Capability Count */
|
||||
uint32_t dataCapCount; /*!< Data Capability Count */
|
||||
uint32_t RTPPayloadFormat; /*!< RTP Payload Format */
|
||||
uint32_t custom_picture_formatCount; /*!< Custom Picture Format Count */
|
||||
|
||||
custom_picture_format_t custom_picture_format[MAX_CUSTOM_PICTURES]; /*!< Custom Picture Format */
|
||||
|
||||
uint32_t activeStreamsOnRegistration; /*!< Active Streams on Registration */
|
||||
uint32_t maxBW; /*!< Max BW ?? */
|
||||
|
||||
uint32_t serviceResourceCount; /*!< Service Resource Count */
|
||||
serviceResource_t serviceResource[MAX_SERVICE_TYPE]; /*!< Service Resource */
|
||||
|
||||
audioCap_t audioCaps[SKINNY_MAX_CAPABILITIES]; /*!< Audio Capabilities */
|
||||
videoCap_t videoCaps[SKINNY_MAX_VIDEO_CAPABILITIES]; /*!< Video Capabilities */
|
||||
dataCap_t dataCaps[SKINNY_MAX_DATA_CAPABILITIES]; /*!< Data Capabilities */
|
||||
|
||||
uint32_t unknown; /*!< Unknown */
|
||||
};
|
||||
|
||||
|
||||
/* ServiceUrlStatReqMessage */
|
||||
#define SERVICE_URL_STAT_REQ_MESSAGE 0x0033
|
||||
struct PACKED service_url_stat_req_message {
|
||||
@@ -442,6 +632,23 @@ struct PACKED register_reject_message {
|
||||
char error[33];
|
||||
};
|
||||
|
||||
#define SERVER_RESPONSE_MESSAGE 0x009E
|
||||
#define ServerMaxNameSize 48
|
||||
#define StationMaxServers 5
|
||||
/*!
|
||||
* \brief Station Identifier Structure
|
||||
*/
|
||||
typedef struct {
|
||||
char serverName[ServerMaxNameSize]; /*!< Server Name */
|
||||
} ServerIdentifier;
|
||||
|
||||
struct PACKED server_response_message {
|
||||
ServerIdentifier server[StationMaxServers]; /*!< Server Identifier */
|
||||
uint32_t serverListenPort[StationMaxServers]; /*!< Server is Listening on Port */
|
||||
uint32_t serverIpAddr[StationMaxServers]; /*!< Server IP Port */
|
||||
}; /*!< Server Result Message Structure */
|
||||
|
||||
|
||||
/* ResetMessage */
|
||||
#define RESET_MESSAGE 0x009F
|
||||
struct PACKED reset_message {
|
||||
@@ -670,6 +877,7 @@ union skinny_data {
|
||||
/* no data for CAPABILITIES_REQ_MESSAGE */
|
||||
struct register_reject_message reg_rej;
|
||||
struct reset_message reset;
|
||||
struct server_response_message serv_res_mess;
|
||||
/* no data for KEEP_ALIVE_ACK_MESSAGE */
|
||||
struct open_receive_channel_message open_receive_channel;
|
||||
struct close_receive_channel_message close_receive_channel;
|
||||
@@ -690,6 +898,7 @@ union skinny_data {
|
||||
/* see field "extended_data" for USER_TO_DEVICE_DATA_VERSION1_MESSAGE */
|
||||
struct dialed_phone_book_ack_message dialed_phone_book_ack;
|
||||
|
||||
struct update_capabilities_message upd_cap;
|
||||
struct data_message data;
|
||||
struct extended_data_message extended_data;
|
||||
|
||||
@@ -702,7 +911,7 @@ union skinny_data {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* header is length+reserved
|
||||
* header is length+version
|
||||
* body is type+data
|
||||
* length is length of body
|
||||
*/
|
||||
@@ -719,47 +928,7 @@ struct PACKED skinny_message {
|
||||
|
||||
typedef struct skinny_message skinny_message_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* SKINNY TYPES */
|
||||
/*****************************************************************************/
|
||||
enum skinny_codecs {
|
||||
SKINNY_CODEC_ALAW_64K = 2,
|
||||
SKINNY_CODEC_ALAW_56K = 3,
|
||||
SKINNY_CODEC_ULAW_64K = 4,
|
||||
SKINNY_CODEC_ULAW_56K = 5,
|
||||
SKINNY_CODEC_G722_64K = 6,
|
||||
SKINNY_CODEC_G722_56K = 7,
|
||||
SKINNY_CODEC_G722_48K = 8,
|
||||
SKINNY_CODEC_G723_1 = 9,
|
||||
SKINNY_CODEC_G728 = 10,
|
||||
SKINNY_CODEC_G729 = 11,
|
||||
SKINNY_CODEC_G729A = 12,
|
||||
SKINNY_CODEC_IS11172 = 13,
|
||||
SKINNY_CODEC_IS13818 = 14,
|
||||
SKINNY_CODEC_G729B = 15,
|
||||
SKINNY_CODEC_G729AB = 16,
|
||||
SKINNY_CODEC_GSM_FULL = 18,
|
||||
SKINNY_CODEC_GSM_HALF = 19,
|
||||
SKINNY_CODEC_GSM_EFULL = 20,
|
||||
SKINNY_CODEC_WIDEBAND_256K = 25,
|
||||
SKINNY_CODEC_DATA_64K = 32,
|
||||
SKINNY_CODEC_DATA_56K = 33,
|
||||
SKINNY_CODEC_GSM = 80,
|
||||
SKINNY_CODEC_ACTIVEVOICE = 81,
|
||||
SKINNY_CODEC_G726_32K = 82,
|
||||
SKINNY_CODEC_G726_24K = 83,
|
||||
SKINNY_CODEC_G726_16K = 84,
|
||||
SKINNY_CODEC_G729B_BIS = 85,
|
||||
SKINNY_CODEC_G729B_LOW = 86,
|
||||
SKINNY_CODEC_H261 = 100,
|
||||
SKINNY_CODEC_H263 = 101,
|
||||
SKINNY_CODEC_VIDEO = 102,
|
||||
SKINNY_CODEC_T120 = 105,
|
||||
SKINNY_CODEC_H224 = 106,
|
||||
SKINNY_CODEC_RFC2833_DYNPAYLOAD = 257
|
||||
};
|
||||
|
||||
char* skinny_codec2string(enum skinny_codecs skinnycodec);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* SKINNY FUNCTIONS */
|
||||
@@ -851,6 +1020,11 @@ switch_status_t perform_send_set_speaker_mode(listener_t *listener,
|
||||
uint32_t mode);
|
||||
#define send_set_speaker_mode(listener, ...) perform_send_set_speaker_mode(listener, __FILE__, __SWITCH_FUNC__, __LINE__, __VA_ARGS__)
|
||||
|
||||
switch_status_t perform_send_srvreq_response(listener_t *listener,
|
||||
const char *file, const char *func, int line,
|
||||
char *ip, uint32_t port);
|
||||
#define send_srvreq_response(listener, ...) perform_send_srvreq_response(listener, __FILE__, __SWITCH_FUNC__, __LINE__, __VA_ARGS__)
|
||||
|
||||
switch_status_t perform_send_start_media_transmission(listener_t *listener,
|
||||
const char *file, const char *func, int line,
|
||||
uint32_t conference_id,
|
||||
|
||||
@@ -2184,6 +2184,79 @@ switch_status_t skinny_handle_accessory_status_message(listener_t *listener, ski
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
switch_status_t skinny_handle_updatecapabilities(listener_t *listener, skinny_message_t *request)
|
||||
{
|
||||
char *sql;
|
||||
skinny_profile_t *profile;
|
||||
|
||||
uint32_t i = 0;
|
||||
uint32_t n = 0;
|
||||
char *codec_order[SWITCH_MAX_CODECS];
|
||||
char *codec_string;
|
||||
|
||||
size_t string_len, string_pos, pos;
|
||||
|
||||
switch_assert(listener->profile);
|
||||
switch_assert(listener->device_name);
|
||||
|
||||
profile = listener->profile;
|
||||
|
||||
skinny_check_data_length(request, sizeof(request->data.upd_cap.audio_cap_count));
|
||||
|
||||
n = request->data.upd_cap.audio_cap_count;
|
||||
if (n > SWITCH_MAX_CODECS) {
|
||||
n = SWITCH_MAX_CODECS;
|
||||
}
|
||||
string_len = -1;
|
||||
|
||||
skinny_check_data_length(request, sizeof(request->data.upd_cap.audio_cap_count) + n * sizeof(request->data.upd_cap.audioCaps[0]));
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
char *codec = skinny_codec2string(request->data.upd_cap.audioCaps[i].payload_capability);
|
||||
codec_order[i] = codec;
|
||||
string_len += strlen(codec)+1;
|
||||
}
|
||||
i = 0;
|
||||
pos = 0;
|
||||
codec_string = switch_core_alloc(listener->pool, string_len+1);
|
||||
for (string_pos = 0; string_pos < string_len; string_pos++) {
|
||||
char *codec = codec_order[i];
|
||||
switch_assert(i < n);
|
||||
if(pos == strlen(codec)) {
|
||||
codec_string[string_pos] = ',';
|
||||
i++;
|
||||
pos = 0;
|
||||
} else {
|
||||
codec_string[string_pos] = codec[pos++];
|
||||
}
|
||||
}
|
||||
codec_string[string_len] = '\0';
|
||||
if ((sql = switch_mprintf(
|
||||
"UPDATE skinny_devices SET codec_string='%s' WHERE name='%s'",
|
||||
codec_string,
|
||||
listener->device_name
|
||||
))) {
|
||||
skinny_execute_sql(profile, sql, profile->sql_mutex);
|
||||
switch_safe_free(sql);
|
||||
}
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
||||
"Codecs %s supported.\n", codec_string);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
switch_status_t skinny_handle_server_req_message(listener_t *listener, skinny_message_t *request)
|
||||
{
|
||||
skinny_profile_t *profile;
|
||||
|
||||
profile = listener->profile;
|
||||
|
||||
skinny_log_l(listener, SWITCH_LOG_INFO, "Received Server Request Message (length=%d).\n", request->length);
|
||||
|
||||
send_srvreq_response(listener, profile->ip, profile->port);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
switch_status_t skinny_handle_xml_alarm(listener_t *listener, skinny_message_t *request)
|
||||
{
|
||||
switch_event_t *event = NULL;
|
||||
@@ -2209,7 +2282,7 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re
|
||||
skinny_log_l(listener, SWITCH_LOG_DEBUG, "Received %s (type=%x,length=%d).\n",
|
||||
skinny_message_type2str(request->type), request->type, request->length);
|
||||
}
|
||||
if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE && request->type != XML_ALARM_MESSAGE) {
|
||||
if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE && request->type != XML_ALARM_MESSAGE && request->type != KEEP_ALIVE_MESSAGE) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
|
||||
"Device should send a register message first. Received %s (type=%x,length=%d).\n", skinny_message_type2str(request->type), request->type, request->length);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
@@ -2281,6 +2354,10 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re
|
||||
return skinny_handle_accessory_status_message(listener, request);
|
||||
case XML_ALARM_MESSAGE:
|
||||
return skinny_handle_xml_alarm(listener, request);
|
||||
case UPDATE_CAPABILITIES_MESSAGE:
|
||||
return skinny_handle_updatecapabilities(listener, request);
|
||||
case SERVER_REQ_MESSAGE:
|
||||
return skinny_handle_server_req_message(listener, request);
|
||||
default:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
|
||||
"Unhandled %s (type=%x,length=%d).\n", skinny_message_type2str(request->type), request->type, request->length);
|
||||
|
||||
@@ -61,6 +61,7 @@ struct skinny_table SKINNY_MESSAGE_TYPES[] = {
|
||||
{REGISTER_AVAILABLE_LINES_MESSAGE, "RegisterAvailableLinesMessage"},
|
||||
{DEVICE_TO_USER_DATA_MESSAGE, "DeviceToUserDataMessage"},
|
||||
{DEVICE_TO_USER_DATA_RESPONSE_MESSAGE, "DeviceToUserDataResponseMessage"},
|
||||
{UPDATE_CAPABILITIES_MESSAGE, "DeviceUpdateCapabilities"},
|
||||
{SERVICE_URL_STAT_REQ_MESSAGE, "ServiceUrlStatReqMessage"},
|
||||
{FEATURE_STAT_REQ_MESSAGE, "FeatureStatReqMessage"},
|
||||
{DEVICE_TO_USER_DATA_VERSION1_MESSAGE, "DeviceToUserDataVersion1Message"},
|
||||
@@ -84,7 +85,9 @@ struct skinny_table SKINNY_MESSAGE_TYPES[] = {
|
||||
{BUTTON_TEMPLATE_RES_MESSAGE, "ButtonTemplateResMessage"},
|
||||
{VERSION_MESSAGE, "VersionMessage"},
|
||||
{CAPABILITIES_REQ_MESSAGE, "CapabilitiesReqMessage"},
|
||||
{SERVER_REQ_MESSAGE, "Server Request Message"},
|
||||
{REGISTER_REJECT_MESSAGE, "RegisterRejectMessage"},
|
||||
{SERVER_RESPONSE_MESSAGE, "ServerResponseMessage"},
|
||||
{RESET_MESSAGE, "ResetMessage"},
|
||||
{KEEP_ALIVE_ACK_MESSAGE, "KeepAliveAckMessage"},
|
||||
{OPEN_RECEIVE_CHANNEL_MESSAGE, "OpenReceiveChannelMessage"},
|
||||
@@ -115,18 +118,59 @@ SKINNY_DECLARE_STR2ID(skinny_str2message_type, SKINNY_MESSAGE_TYPES, -1)
|
||||
{1, "Cisco 30 SP+"},
|
||||
{2, "Cisco 12 SP+"},
|
||||
{3, "Cisco 12 SP"},
|
||||
{4, "Cisco 12"},
|
||||
{4, "Cisco 12 S"},
|
||||
{5, "Cisco 30 VIP"},
|
||||
{6, "Cisco IP Phone 7910"},
|
||||
{7, "Cisco IP Phone 7960"},
|
||||
{8, "Cisco IP Phone 7940"},
|
||||
{9, "Cisco IP Phone 7935"},
|
||||
{6, "Cisco 7910"},
|
||||
{7, "Cisco 7960"},
|
||||
{8, "Cisco 7940"},
|
||||
{9, "Cisco 7935"},
|
||||
{10, "Cisco VGC Phone"},
|
||||
{11, "Cisco VGC Virtual Phone"},
|
||||
{12, "Cisco ATA 186"},
|
||||
{365, "Cisco IP Phone CP-7921G"},
|
||||
{404, "Cisco IP Phone CP-7962G"},
|
||||
{436, "Cisco IP Phone CP-7965G"},
|
||||
{30018, "Cisco IP Phone CP-7961G"},
|
||||
{30019, "Cisco IP Phone 7936"},
|
||||
{30, "Cisco Analog Access"},
|
||||
{40, "Cisco Digital Access"},
|
||||
{42, "Cisco Digital Access+"},
|
||||
{43, "Cisco Digital Access WS-X6608"},
|
||||
{47, "Cisco Analog Access WS-X6624"},
|
||||
{51, "Cisco Conference Bridge WS-X6608"},
|
||||
{61, "Cisco H.323 Phone"},
|
||||
{100, "Cisco Load Simulator"},
|
||||
{111, "Cisco Media Termination Point Hardware"},
|
||||
{115, "Cisco 7941"},
|
||||
{115, "Cisco CP-7941G"},
|
||||
{119, "Cisco 7971"},
|
||||
{120, "Cisco MGCP Station"},
|
||||
{121, "Cisco MGCP Trunk"},
|
||||
{124, "Cisco 7914 14-Button Line Expansion Module"},
|
||||
{302, "Cisco 7985"},
|
||||
{307, "Cisco 7911"},
|
||||
{308, "Cisco 7961G-GE"},
|
||||
{309, "Cisco 7941G-GE"},
|
||||
{335, "Cisco Motorola CN622"},
|
||||
{348, "Cisco 7931"},
|
||||
{358, "Cisco Unified Personal Communicator"},
|
||||
{365, "Cisco 7921"},
|
||||
{369, "Cisco 7906"},
|
||||
{375, "Cisco TelePresence"},
|
||||
{404, "Cisco 7962"},
|
||||
{412, "Cisco 3951"},
|
||||
{431, "Cisco 7937"},
|
||||
{434, "Cisco 7942"},
|
||||
{435, "Cisco 7945"},
|
||||
{436, "Cisco 7965"},
|
||||
{437, "Cisco 7975"},
|
||||
{446, "Cisco 3911"},
|
||||
{20000, "Cisco 7905"},
|
||||
{30002, "Cisco 7920"},
|
||||
{30006, "Cisco 7970"},
|
||||
{30007, "Cisco 7912"},
|
||||
{30008, "Cisco 7902"},
|
||||
{30018, "Cisco 7961"},
|
||||
{30019, "Cisco 7936"},
|
||||
{30027, "Cisco Analog Phone"},
|
||||
{30028, "Cisco ISDN BRI Phone"},
|
||||
{30032, "Cisco SCCP gateway virtual phone"},
|
||||
{30035, "Cisco IP-STE"},
|
||||
{0, NULL}
|
||||
};
|
||||
SKINNY_DECLARE_ID2STR(skinny_device_type2str, SKINNY_DEVICE_TYPES, "UnknownDeviceType")
|
||||
|
||||
@@ -87,12 +87,12 @@ if (my_matches) {\
|
||||
}
|
||||
|
||||
|
||||
extern struct skinny_table SKINNY_MESSAGE_TYPES[72];
|
||||
extern struct skinny_table SKINNY_MESSAGE_TYPES[75];
|
||||
const char *skinny_message_type2str(uint32_t id);
|
||||
uint32_t skinny_str2message_type(const char *str);
|
||||
#define SKINNY_PUSH_MESSAGE_TYPES SKINNY_DECLARE_PUSH_MATCH(SKINNY_MESSAGE_TYPES)
|
||||
|
||||
extern struct skinny_table SKINNY_DEVICE_TYPES[16];
|
||||
extern struct skinny_table SKINNY_DEVICE_TYPES[75];
|
||||
const char *skinny_device_type2str(uint32_t id);
|
||||
uint32_t skinny_str2device_type(const char *str);
|
||||
#define SKINNY_PUSH_DEVICE_TYPES SKINNY_DECLARE_PUSH_MATCH(SKINNY_DEVICE_TYPES)
|
||||
|
||||
+47
-8
@@ -126,6 +126,7 @@ typedef struct switch_rtp_engine_s {
|
||||
uint32_t max_missed_packets;
|
||||
uint32_t max_missed_hold_packets;
|
||||
uint32_t ssrc;
|
||||
uint32_t remote_ssrc;
|
||||
switch_port_t remote_rtcp_port;
|
||||
switch_rtp_bug_flag_t rtp_bugs;
|
||||
|
||||
@@ -1985,6 +1986,8 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_
|
||||
generate_local_fingerprint(smh, type);
|
||||
switch_channel_set_flag(smh->session->channel, CF_DTLS);
|
||||
|
||||
} else if (!engine->remote_ssrc && !strcasecmp(attr->a_name, "ssrc") && attr->a_value) {
|
||||
engine->remote_ssrc = (uint32_t) atol(attr->a_value);
|
||||
#ifdef RTCP_MUX
|
||||
} else if (!strcasecmp(attr->a_name, "rtcp-mux")) {
|
||||
engine->rtcp_mux = SWITCH_TRUE;
|
||||
@@ -2294,7 +2297,6 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
|
||||
codec_array = smh->codecs;
|
||||
total_codecs = smh->mparams->num_codecs;
|
||||
|
||||
|
||||
if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
|
||||
return 0;
|
||||
}
|
||||
@@ -2459,9 +2461,12 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s
|
||||
got_webrtc++;
|
||||
switch_core_session_set_ice(session);
|
||||
}
|
||||
|
||||
|
||||
if (m->m_proto_name && !strcasecmp(m->m_proto_name, "UDP/TLS/RTP/SAVPF")) {
|
||||
switch_channel_set_flag(session->channel, CF_WEBRTC_MOZ);
|
||||
printf("PRICK FACE 1\n");
|
||||
} else {
|
||||
printf("PRICK FACE 2 [%s]\n", m->m_proto_name);
|
||||
}
|
||||
|
||||
if (m->m_proto == sdp_proto_srtp || m->m_proto == sdp_proto_extended_srtp) {
|
||||
@@ -3790,7 +3795,8 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread started\n", switch_channel_get_name(session->channel));
|
||||
switch_core_session_refresh_video(session);
|
||||
|
||||
switch_channel_set_flag(channel, CF_VIDEO_ECHO);
|
||||
|
||||
while (switch_channel_up_nosig(channel)) {
|
||||
|
||||
if (switch_channel_test_flag(channel, CF_VIDEO_PASSIVE)) {
|
||||
@@ -3812,7 +3818,6 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi
|
||||
|
||||
status = switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
|
||||
|
||||
if (!SWITCH_READ_ACCEPTABLE(status)) {
|
||||
switch_cond_next();
|
||||
continue;
|
||||
@@ -3828,7 +3833,9 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi
|
||||
continue;
|
||||
}
|
||||
|
||||
switch_core_session_write_video_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
if (switch_channel_test_flag(channel, CF_VIDEO_ECHO)) {
|
||||
switch_core_session_write_video_frame(session, read_frame, SWITCH_IO_FLAG_NONE, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4092,6 +4099,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
|
||||
switch_rtp_set_ssrc(a_engine->rtp_session, a_engine->ssrc);
|
||||
}
|
||||
|
||||
if (a_engine->remote_ssrc) {
|
||||
switch_rtp_set_remote_ssrc(a_engine->rtp_session, a_engine->remote_ssrc);
|
||||
}
|
||||
|
||||
switch_channel_set_flag(session->channel, CF_FS_RTP);
|
||||
|
||||
@@ -4552,6 +4562,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi
|
||||
switch_rtp_set_ssrc(v_engine->rtp_session, v_engine->ssrc);
|
||||
}
|
||||
|
||||
if (v_engine->remote_ssrc) {
|
||||
switch_rtp_set_remote_ssrc(v_engine->rtp_session, v_engine->remote_ssrc);
|
||||
}
|
||||
|
||||
if (v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].ready) {
|
||||
|
||||
gen_ice(session, SWITCH_MEDIA_TYPE_VIDEO, NULL, 0);
|
||||
@@ -5125,7 +5139,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
|
||||
switch_rtp_engine_t *a_engine, *v_engine;
|
||||
switch_media_handle_t *smh;
|
||||
ice_t *ice_out;
|
||||
|
||||
int vp8 = 0;
|
||||
|
||||
switch_assert(session);
|
||||
|
||||
@@ -5629,6 +5643,10 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
|
||||
|
||||
if (v_engine->codec_params.rm_encoding) {
|
||||
const char *of;
|
||||
|
||||
if (!strcasecmp(v_engine->codec_params.rm_encoding, "VP8")) {
|
||||
vp8 = v_engine->codec_params.pt;
|
||||
}
|
||||
|
||||
rate = v_engine->codec_params.rm_rate;
|
||||
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\n",
|
||||
@@ -5694,6 +5712,10 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
|
||||
|
||||
channels = get_channels(imp);
|
||||
|
||||
if (!strcasecmp(imp->iananame, "VP8")) {
|
||||
vp8 = ianacode;
|
||||
}
|
||||
|
||||
if (channels > 1) {
|
||||
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\n", ianacode, imp->iananame,
|
||||
imp->samples_per_second, channels);
|
||||
@@ -5733,7 +5755,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
|
||||
}
|
||||
|
||||
|
||||
if (smh->mparams->rtcp_audio_interval_msec) {
|
||||
if (smh->mparams->rtcp_video_interval_msec) {
|
||||
if (v_engine->rtcp_mux > 0) {
|
||||
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp-mux\n");
|
||||
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\n", v_port, family, ip);
|
||||
@@ -5751,7 +5773,9 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
|
||||
uint32_t c2 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 2);
|
||||
uint32_t c3 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 1);
|
||||
uint32_t c4 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 2);
|
||||
|
||||
const char *vbw;
|
||||
int bw = 256;
|
||||
|
||||
tmp1[10] = '\0';
|
||||
tmp2[10] = '\0';
|
||||
switch_stun_random_string(tmp1, 10, "0123456789");
|
||||
@@ -5760,6 +5784,21 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
|
||||
ice_out = &v_engine->ice_out;
|
||||
|
||||
|
||||
if ((vbw = switch_channel_get_variable(smh->session->channel, "rtp_video_max_bandwidth"))) {
|
||||
int v = atoi(vbw);
|
||||
bw = v;
|
||||
}
|
||||
|
||||
if (bw > 0) {
|
||||
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "b=AS:%d\n", bw);
|
||||
}
|
||||
|
||||
|
||||
if (vp8) {
|
||||
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf),
|
||||
"a=rtcp-fb:%d ccm fir\n", vp8);
|
||||
}
|
||||
|
||||
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u cname:%s\n", v_engine->ssrc, smh->cname);
|
||||
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u msid:%s v0\n", v_engine->ssrc, smh->msid);
|
||||
switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u mslabel:%s\n", v_engine->ssrc, smh->msid);
|
||||
|
||||
@@ -2567,6 +2567,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flag
|
||||
*flags = application_interface->flags;
|
||||
}
|
||||
|
||||
if (!switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA) && (switch_channel_test_flag(session->channel, CF_VIDEO))) {
|
||||
switch_core_session_refresh_video(session);
|
||||
}
|
||||
|
||||
if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) && !switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA)) {
|
||||
switch_ivr_media(session->uuid_str, SMF_NONE);
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Application %s Requires media on channel %s!\n",
|
||||
|
||||
+246
-45
@@ -34,6 +34,8 @@
|
||||
//#define RTP_DEBUG_WRITE_DELTA
|
||||
//#define DEBUG_MISSED_SEQ
|
||||
|
||||
#define FIR_COUNTDOWN 100
|
||||
|
||||
#include <switch.h>
|
||||
#ifndef _MSC_VER
|
||||
#include <switch_private.h>
|
||||
@@ -116,7 +118,6 @@ typedef struct {
|
||||
uint8_t r3;
|
||||
} rtcp_fir_t;
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, r1, 1)
|
||||
#endif
|
||||
@@ -264,6 +265,13 @@ static int dtls_state_dummy(switch_rtp_t *rtp_session, switch_dtls_t *dtls);
|
||||
|
||||
dtls_state_handler_t dtls_states[DS_INVALID] = {dtls_state_handshake, dtls_state_setup, dtls_state_ready, dtls_state_dummy};
|
||||
|
||||
typedef struct ts_normalize_s {
|
||||
uint32_t last_ssrc;
|
||||
uint32_t last_frame;
|
||||
uint32_t ts;
|
||||
uint32_t delta;
|
||||
uint8_t m;
|
||||
} ts_normalize_t;
|
||||
|
||||
struct switch_rtp {
|
||||
/*
|
||||
@@ -281,6 +289,8 @@ struct switch_rtp {
|
||||
rtcp_msg_t rtcp_send_msg;
|
||||
rtcp_ext_msg_t rtcp_ext_send_msg;
|
||||
uint8_t fir_seq;
|
||||
uint16_t fir_countdown;
|
||||
ts_normalize_t ts_norm;
|
||||
switch_sockaddr_t *remote_addr, *rtcp_remote_addr;
|
||||
rtp_msg_t recv_msg;
|
||||
rtcp_msg_t rtcp_recv_msg;
|
||||
@@ -307,6 +317,7 @@ struct switch_rtp {
|
||||
|
||||
uint16_t seq;
|
||||
uint32_t ssrc;
|
||||
uint32_t remote_ssrc;
|
||||
int8_t sending_dtmf;
|
||||
uint8_t need_mark;
|
||||
switch_payload_t payload;
|
||||
@@ -698,10 +709,10 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice)
|
||||
elapsed = (unsigned int) ((switch_micro_time_now() - rtp_session->last_stun) / 1000);
|
||||
|
||||
if (elapsed > 30000) {
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "No stun for a long time (PUNT!)\n");
|
||||
status = SWITCH_STATUS_GENERR;
|
||||
goto end;
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "No stun for a long time!\n");
|
||||
rtp_session->last_stun = switch_micro_time_now();
|
||||
//status = SWITCH_STATUS_GENERR;
|
||||
//goto end;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -743,7 +754,7 @@ static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice)
|
||||
|
||||
ice->sending = 3;
|
||||
|
||||
end:
|
||||
// end:
|
||||
READ_DEC(rtp_session);
|
||||
|
||||
return status;
|
||||
@@ -1329,20 +1340,31 @@ static void send_fir(switch_rtp_t *rtp_session)
|
||||
return;
|
||||
}
|
||||
|
||||
if (rtp_session->remote_ssrc == 0) {
|
||||
rtp_session->remote_ssrc = rtp_session->stats.rtcp.peer_ssrc;
|
||||
}
|
||||
|
||||
if (rtp_session->remote_ssrc == 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "Peer ssrc not known yet for FIR\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (rtp_session->rtcp_sock_output && rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP]) {
|
||||
rtcp_fir_t *fir = (rtcp_fir_t *) rtp_session->rtcp_ext_send_msg.body;
|
||||
switch_size_t rtcp_bytes;
|
||||
|
||||
|
||||
rtp_session->rtcp_ext_send_msg.header.version = 2;
|
||||
rtp_session->rtcp_ext_send_msg.header.p = 0;
|
||||
rtp_session->rtcp_ext_send_msg.header.fmt = 4;
|
||||
rtp_session->rtcp_ext_send_msg.header.pt = 206;
|
||||
|
||||
rtp_session->rtcp_ext_send_msg.header.send_ssrc = htonl(rtp_session->ssrc);
|
||||
rtp_session->rtcp_ext_send_msg.header.recv_ssrc = htonl(rtp_session->stats.rtcp.peer_ssrc);
|
||||
rtp_session->rtcp_ext_send_msg.header.recv_ssrc = 0;//htonl(rtp_session->stats.rtcp.peer_ssrc);
|
||||
|
||||
fir->ssrc = htonl(rtp_session->stats.rtcp.peer_ssrc);
|
||||
fir->seq = (uint8_t) htonl(rtp_session->fir_seq++);
|
||||
//fir->ssrc = htonl(rtp_session->stats.rtcp.peer_ssrc);
|
||||
fir->ssrc = htonl(rtp_session->remote_ssrc);
|
||||
fir->seq = ++rtp_session->fir_seq;
|
||||
fir->r1 = fir->r2 = fir->r3 = 0;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG1, "Sending RTCP FIR %d\n", rtp_session->fir_seq);
|
||||
|
||||
@@ -1409,6 +1431,92 @@ static void send_fir(switch_rtp_t *rtp_session)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static void send_pli(switch_rtp_t *rtp_session)
|
||||
{
|
||||
|
||||
if (!rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && rtp_session->ice.ice_user) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (rtp_session->rtcp_sock_output && rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP]) {
|
||||
switch_size_t rtcp_bytes;
|
||||
|
||||
rtp_session->rtcp_ext_send_msg.header.version = 2;
|
||||
rtp_session->rtcp_ext_send_msg.header.p = 0;
|
||||
rtp_session->rtcp_ext_send_msg.header.fmt = 1;
|
||||
rtp_session->rtcp_ext_send_msg.header.pt = 206;
|
||||
|
||||
rtp_session->rtcp_ext_send_msg.header.send_ssrc = htonl(rtp_session->ssrc);
|
||||
rtp_session->rtcp_ext_send_msg.header.recv_ssrc = 0;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG1, "Sending RTCP PLI\n");
|
||||
|
||||
rtcp_bytes = sizeof(switch_rtcp_ext_hdr_t);
|
||||
rtp_session->rtcp_ext_send_msg.header.length = htons((u_short)(rtcp_bytes / 4) - 1);
|
||||
|
||||
|
||||
#ifdef ENABLE_SRTP
|
||||
if (rtp_session->flags[SWITCH_RTP_FLAG_SECURE_SEND]) {
|
||||
int sbytes = (int) rtcp_bytes;
|
||||
int stat = srtp_protect_rtcp(rtp_session->send_ctx[rtp_session->srtp_idx_rtcp], &rtp_session->rtcp_ext_send_msg.header, &sbytes);
|
||||
|
||||
if (stat) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_ERROR, "Error: SRTP RTCP protection failed with code %d\n", stat);
|
||||
goto end;
|
||||
} else {
|
||||
rtcp_bytes = sbytes;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_ZRTP
|
||||
/* ZRTP Send */
|
||||
if (zrtp_on && !rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA]) {
|
||||
unsigned int sbytes = (int) rtcp_bytes;
|
||||
zrtp_status_t stat = zrtp_status_fail;
|
||||
|
||||
stat = zrtp_process_rtcp(rtp_session->zrtp_stream, (void *) &rtp_session->rtcp_ext_send_msg, &sbytes);
|
||||
|
||||
switch (stat) {
|
||||
case zrtp_status_ok:
|
||||
break;
|
||||
case zrtp_status_drop:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection drop with code %d\n", stat);
|
||||
goto end;
|
||||
break;
|
||||
case zrtp_status_fail:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection fail with code %d\n", stat);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
rtcp_bytes = sbytes;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_EXTRA
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "%s SEND %s RTCP %ld\n",
|
||||
switch_core_session_get_name(rtp_session->session),
|
||||
rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] ? "video" : "audio", rtcp_bytes);
|
||||
#endif
|
||||
if (switch_socket_sendto(rtp_session->rtcp_sock_output, rtp_session->rtcp_remote_addr, 0, (void *)&rtp_session->rtcp_ext_send_msg, &rtcp_bytes ) != SWITCH_STATUS_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG,"RTCP packet not written\n");
|
||||
} else {
|
||||
rtp_session->stats.inbound.period_packet_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
end:
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int check_rtcp_and_ice(switch_rtp_t *rtp_session)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -1442,10 +1550,6 @@ static int check_rtcp_and_ice(switch_rtp_t *rtp_session)
|
||||
rtcp_ok = 0;
|
||||
}
|
||||
|
||||
//if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
|
||||
// rtcp_ok = 0;
|
||||
//}
|
||||
|
||||
if (rtp_session->rtcp_sock_output && rtcp_ok && rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP] && !rtp_session->flags[SWITCH_RTP_FLAG_RTCP_PASSTHRU]) {
|
||||
struct switch_rtcp_senderinfo *sr = (struct switch_rtcp_senderinfo*) rtp_session->rtcp_send_msg.body;
|
||||
const char* str_cname=NULL;
|
||||
@@ -2123,6 +2227,10 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_
|
||||
status = enable_remote_rtcp_socket(rtp_session, err);
|
||||
}
|
||||
|
||||
if (rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP] && rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
|
||||
rtp_session->rtcp_remote_addr = rtp_session->remote_addr;
|
||||
}
|
||||
|
||||
switch_mutex_unlock(rtp_session->write_mutex);
|
||||
|
||||
return status;
|
||||
@@ -2224,7 +2332,7 @@ static int dtls_state_ready(switch_rtp_t *rtp_session, switch_dtls_t *dtls)
|
||||
if (dtls->new_state) {
|
||||
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
|
||||
switch_core_session_t *other_session;
|
||||
send_fir(rtp_session);
|
||||
rtp_session->fir_countdown = FIR_COUNTDOWN;
|
||||
|
||||
if (rtp_session->session && switch_core_session_get_partner(rtp_session->session, &other_session) == SWITCH_STATUS_SUCCESS) {
|
||||
switch_core_session_refresh_video(other_session);
|
||||
@@ -2682,6 +2790,13 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_ssrc(switch_rtp_t *rtp_session, u
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_ssrc(switch_rtp_t *rtp_session, uint32_t ssrc)
|
||||
{
|
||||
rtp_session->remote_ssrc = ssrc;
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session,
|
||||
switch_payload_t payload,
|
||||
uint32_t samples_per_interval,
|
||||
@@ -2781,6 +2896,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_create(switch_rtp_t **new_rtp_session
|
||||
switch_rtp_clear_flag(rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
|
||||
}
|
||||
|
||||
|
||||
if (channel) {
|
||||
switch_channel_set_private(channel, "__rtcp_audio_rtp_session", rtp_session);
|
||||
}
|
||||
@@ -3221,7 +3337,10 @@ SWITCH_DECLARE(void) switch_rtp_flush(switch_rtp_t *rtp_session)
|
||||
SWITCH_DECLARE(void) switch_rtp_video_refresh(switch_rtp_t *rtp_session)
|
||||
{
|
||||
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && rtp_session->ice.ice_user) {
|
||||
send_fir(rtp_session);
|
||||
if (!rtp_session->fir_countdown) {
|
||||
//send_fir(rtp_session);
|
||||
rtp_session->fir_countdown = FIR_COUNTDOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3827,6 +3946,7 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
|
||||
uint32_t ts = 0;
|
||||
unsigned char *b = NULL;
|
||||
int sync = 0;
|
||||
switch_time_t now;
|
||||
|
||||
switch_assert(bytes);
|
||||
more:
|
||||
@@ -3896,15 +4016,14 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (status == SWITCH_STATUS_SUCCESS && *bytes) {
|
||||
if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) {
|
||||
*flags &= ~SFF_RTCP;
|
||||
if (rtp_session->recv_msg.header.pt != rtp_session->rpayload && (!rtp_session->recv_te ||
|
||||
rtp_session->recv_msg.header.pt != rtp_session->recv_te) &&
|
||||
if (rtp_session->recv_msg.header.pt != rtp_session->rpayload &&
|
||||
(!rtp_session->recv_te || rtp_session->recv_msg.header.pt != rtp_session->recv_te) &&
|
||||
(!rtp_session->cng_pt || rtp_session->recv_msg.header.pt != rtp_session->cng_pt) &&
|
||||
rtp_session->rtcp_recv_msg_p->header.version == 2 && rtp_session->rtcp_recv_msg_p->header.type > 199 &&
|
||||
rtp_session->rtcp_recv_msg_p->header.type < 208) { //rtcp muxed
|
||||
rtp_session->rtcp_recv_msg_p->header.version == 2 &&
|
||||
rtp_session->rtcp_recv_msg_p->header.type > 199 && rtp_session->rtcp_recv_msg_p->header.type < 208) { //rtcp muxed
|
||||
*flags |= SFF_RTCP;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
@@ -3952,11 +4071,13 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
|
||||
|
||||
udptl:
|
||||
|
||||
ts = ntohl(rtp_session->recv_msg.header.ts);
|
||||
ts = 0;
|
||||
rtp_session->recv_msg.ebody = NULL;
|
||||
now = switch_micro_time_now();
|
||||
|
||||
if (*bytes) {
|
||||
uint16_t seq = ntohs((uint16_t) rtp_session->recv_msg.header.seq);
|
||||
ts = ntohl(rtp_session->recv_msg.header.ts);
|
||||
|
||||
if (!rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA] && !rtp_session->flags[SWITCH_RTP_FLAG_UDPTL] &&
|
||||
rtp_session->recv_msg.header.version == 2 && rtp_session->recv_msg.header.x) { /* header extensions */
|
||||
@@ -3981,40 +4102,47 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
|
||||
if (num_missed == 1) { /* We missed one packet */
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missed one RTP frame with sequence [%d]%s. Time since last read [%ld]\n",
|
||||
rtp_session->last_seq+1, (flushed_packets_diff == 1) ? " (flushed by FS)" : " (missed)",
|
||||
rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
|
||||
rtp_session->last_read_time ? now-rtp_session->last_read_time : 0);
|
||||
} else { /* We missed multiple packets */
|
||||
if (flushed_packets_diff == 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Missed %ld RTP frames from sequence [%d] to [%d] (missed). Time since last read [%ld]\n",
|
||||
num_missed, rtp_session->last_seq+1, seq-1,
|
||||
rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
|
||||
rtp_session->last_read_time ? now-rtp_session->last_read_time : 0);
|
||||
} else if (flushed_packets_diff == num_missed) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Missed %ld RTP frames from sequence [%d] to [%d] (flushed by FS). Time since last read [%ld]\n",
|
||||
num_missed, rtp_session->last_seq+1, seq-1,
|
||||
rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
|
||||
rtp_session->last_read_time ? now-rtp_session->last_read_time : 0);
|
||||
} else if (num_missed > flushed_packets_diff) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Missed %ld RTP frames from sequence [%d] to [%d] (%ld packets flushed by FS, %ld packets missed)."
|
||||
" Time since last read [%ld]\n",
|
||||
num_missed, rtp_session->last_seq+1, seq-1,
|
||||
flushed_packets_diff, num_missed-flushed_packets_diff,
|
||||
rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
|
||||
rtp_session->last_read_time ? now-rtp_session->last_read_time : 0);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Missed %ld RTP frames from sequence [%d] to [%d] (%ld packets flushed by FS). Time since last read [%ld]\n",
|
||||
num_missed, rtp_session->last_seq+1, seq-1,
|
||||
flushed_packets_diff, rtp_session->last_read_time ? switch_micro_time_now()-rtp_session->last_read_time : 0);
|
||||
flushed_packets_diff, rtp_session->last_read_time ? now-rtp_session->last_read_time : 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
rtp_session->last_seq = seq;
|
||||
}
|
||||
|
||||
|
||||
rtp_session->last_flush_packet_count = rtp_session->stats.inbound.flush_packet_count;
|
||||
rtp_session->last_read_time = switch_micro_time_now();
|
||||
rtp_session->last_flush_packet_count = rtp_session->stats.inbound.flush_packet_count;
|
||||
|
||||
|
||||
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] && now - rtp_session->last_read_time > 500000) {
|
||||
switch_rtp_video_refresh(rtp_session);
|
||||
}
|
||||
|
||||
rtp_session->last_read_time = now;
|
||||
}
|
||||
|
||||
if (!rtp_session->flags[SWITCH_RTP_FLAG_PROXY_MEDIA] && !rtp_session->flags[SWITCH_RTP_FLAG_UDPTL] && !rtp_session->flags[SWITCH_RTP_FLAG_VIDEO] &&
|
||||
*bytes && (!rtp_session->recv_te || rtp_session->recv_msg.header.pt != rtp_session->recv_te) &&
|
||||
@@ -4121,7 +4249,17 @@ static switch_status_t read_rtp_packet(switch_rtp_t *rtp_session, switch_size_t
|
||||
}
|
||||
|
||||
|
||||
rtp_session->last_read_ts = ts;
|
||||
if (*bytes && rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
|
||||
unsigned int diff = ts - rtp_session->last_read_ts;
|
||||
|
||||
if (abs(diff) > 10000) {
|
||||
switch_rtp_video_refresh(rtp_session);
|
||||
}
|
||||
}
|
||||
|
||||
if (ts) {
|
||||
rtp_session->last_read_ts = ts;
|
||||
}
|
||||
|
||||
if (rtp_session->flags[SWITCH_RTP_FLAG_BYTESWAP] && rtp_session->recv_msg.header.pt == rtp_session->rpayload) {
|
||||
switch_swap_linear((int16_t *)RTP_BODY(rtp_session), (int) *bytes - rtp_header_len);
|
||||
@@ -4251,16 +4389,13 @@ static switch_status_t read_rtcp_packet(switch_rtp_t *rtp_session, switch_size_t
|
||||
if (rtp_session->rtcp_dtls) {
|
||||
char *b = (char *) &rtp_session->rtcp_recv_msg;
|
||||
|
||||
//printf("RECV2 %d %ld\n", *b, *bytes);
|
||||
|
||||
if (*b == 0 || *b == 1) {
|
||||
if (rtp_session->rtcp_ice.ice_user) {
|
||||
handle_ice(rtp_session, &rtp_session->rtcp_ice, (void *) &rtp_session->rtcp_recv_msg, *bytes);
|
||||
}
|
||||
*bytes = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (*bytes && (*b >= 20) && (*b <= 64)) {
|
||||
rtp_session->rtcp_dtls->bytes = *bytes;
|
||||
rtp_session->rtcp_dtls->data = (void *) &rtp_session->rtcp_recv_msg;
|
||||
@@ -4474,14 +4609,15 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
||||
pt = 20000;
|
||||
}
|
||||
|
||||
if ((rtp_session->ice.ice_user && rtp_session->flags[SWITCH_RTP_FLAG_VIDEO])) {
|
||||
pt = 10000;
|
||||
}
|
||||
|
||||
if ((io_flags & SWITCH_IO_FLAG_NOBLOCK)) {
|
||||
pt = 0;
|
||||
}
|
||||
|
||||
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
|
||||
pt = 100000;
|
||||
}
|
||||
|
||||
poll_status = switch_poll(rtp_session->read_pollfd, 1, &fdr, pt);
|
||||
|
||||
if (rtp_session->dtmf_data.out_digit_dur > 0) {
|
||||
@@ -4499,6 +4635,22 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
if (rtp_session->flags[SWITCH_RTP_FLAG_VIDEO]) {
|
||||
//switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_CRIT, "Read bytes (%i) %ld\n", status, bytes);
|
||||
|
||||
if (bytes == 0) {
|
||||
if (check_rtcp_and_ice(rtp_session) == -1) {
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
// This is dumb
|
||||
switch_rtp_video_refresh(rtp_session);
|
||||
goto rtcp;
|
||||
}
|
||||
}
|
||||
|
||||
if ((*flags & SFF_PROXY_PACKET)) {
|
||||
ret = (int) bytes;
|
||||
goto end;
|
||||
@@ -4509,8 +4661,8 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
||||
has_rtcp = 1;
|
||||
goto rtcp;
|
||||
}
|
||||
|
||||
//switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, "Read bytes (%i) %ld\n", status, bytes);
|
||||
|
||||
|
||||
}
|
||||
poll_loop = 0;
|
||||
} else {
|
||||
@@ -4539,9 +4691,11 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
} else if ((!(io_flags & SWITCH_IO_FLAG_NOBLOCK)) &&
|
||||
(rtp_session->dtmf_data.out_digit_dur == 0)) {
|
||||
goto recvfrom;
|
||||
}
|
||||
|
||||
if ((!(io_flags & SWITCH_IO_FLAG_NOBLOCK)) &&
|
||||
(rtp_session->dtmf_data.out_digit_dur == 0)) {
|
||||
return_cng_frame();
|
||||
}
|
||||
}
|
||||
@@ -4572,7 +4726,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_
|
||||
|
||||
if (rtcp_status == SWITCH_STATUS_SUCCESS) {
|
||||
switch_rtp_reset_media_timer(rtp_session);
|
||||
|
||||
|
||||
if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_PASSTHRU] || rtp_session->rtcp_recv_msg_p->header.type == 206) {
|
||||
switch_channel_t *channel = switch_core_session_get_channel(rtp_session->session);
|
||||
const char *uuid = switch_channel_get_partner_uuid(channel);
|
||||
@@ -5118,6 +5272,13 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
if (rtp_session->fir_countdown) {
|
||||
if (--rtp_session->fir_countdown == 0) {
|
||||
send_fir(rtp_session);
|
||||
//send_pli(rtp_session);
|
||||
}
|
||||
}
|
||||
|
||||
bytes = rtp_common_read(rtp_session, &frame->payload, &frame->flags, io_flags);
|
||||
|
||||
frame->data = RTP_BODY(rtp_session);
|
||||
@@ -5311,6 +5472,45 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (switch_rtp_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) {
|
||||
/* Normalize the timestamps to our own base by generating a made up starting point then adding the measured deltas to that base
|
||||
so if the timestamps and ssrc of the source change, it will not break the other end's jitter bufffer / decoder etc *cough* CHROME *cough*
|
||||
*/
|
||||
|
||||
if (!rtp_session->ts_norm.ts) {
|
||||
rtp_session->ts_norm.ts = (uint32_t) rand() % 1000000 + 1;
|
||||
}
|
||||
|
||||
if (!rtp_session->ts_norm.last_ssrc || send_msg->header.ssrc != rtp_session->ts_norm.last_ssrc) {
|
||||
if (rtp_session->ts_norm.last_ssrc) {
|
||||
rtp_session->ts_norm.m = 1;
|
||||
if (rtp_session->ts_norm.delta) {
|
||||
rtp_session->ts_norm.ts += rtp_session->ts_norm.delta;
|
||||
}
|
||||
}
|
||||
rtp_session->ts_norm.last_ssrc = send_msg->header.ssrc;
|
||||
rtp_session->ts_norm.last_frame = ntohl(send_msg->header.ts);
|
||||
}
|
||||
|
||||
|
||||
if (ntohl(send_msg->header.ts) != rtp_session->ts_norm.last_frame) {
|
||||
rtp_session->ts_norm.delta = ntohl(send_msg->header.ts) - rtp_session->ts_norm.last_frame;
|
||||
rtp_session->ts_norm.ts += rtp_session->ts_norm.delta;
|
||||
}
|
||||
|
||||
rtp_session->ts_norm.last_frame = ntohl(send_msg->header.ts);
|
||||
send_msg->header.ts = htonl(rtp_session->ts_norm.ts);
|
||||
|
||||
if (rtp_session->ts_norm.m) {
|
||||
if (send_msg->header.m) {
|
||||
rtp_session->ts_norm.m = 0;
|
||||
} else {
|
||||
send_msg->header.m = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
send_msg->header.ssrc = htonl(rtp_session->ssrc);
|
||||
|
||||
if (rtp_session->flags[SWITCH_RTP_FLAG_GOOGLEHACK] && rtp_session->send_msg.header.pt == 97) {
|
||||
@@ -5447,6 +5647,8 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
|
||||
send = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (send) {
|
||||
send_msg->header.seq = htons(++rtp_session->seq);
|
||||
|
||||
@@ -5549,7 +5751,6 @@ static int rtp_common_write(switch_rtp_t *rtp_session,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (switch_socket_sendto(rtp_session->sock_output, rtp_session->remote_addr, 0, (void *) send_msg, &bytes) != SWITCH_STATUS_SUCCESS) {
|
||||
rtp_session->seq--;
|
||||
ret = -1;
|
||||
|
||||
Reference in New Issue
Block a user