FreeSWITCH API Documentation  1.7.0
switch_core_media.c
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  *
28  * switch_core_media.c -- Core Media
29  *
30  */
31 
32 #include <switch.h>
33 #include <switch_ssl.h>
34 #include <switch_stun.h>
35 #include <switch_nat.h>
37 #include <switch_curl.h>
38 #include <errno.h>
39 #include <sofia-sip/sdp.h>
40 #include <sofia-sip/su.h>
41 
42 static switch_t38_options_t * switch_core_media_process_udptl(switch_core_session_t *session, sdp_session_t *sdp, sdp_media_t *m);
43 static void switch_core_media_find_zrtp_hash(switch_core_session_t *session, sdp_session_t *sdp);
44 static void switch_core_media_set_r_sdp_codec_string(switch_core_session_t *session, const char *codec_string, sdp_session_t *sdp, switch_sdp_type_t sdp_type);
45 static void gen_ice(switch_core_session_t *session, switch_media_type_t type, const char *ip, switch_port_t port);
46 //#define GOOGLE_ICE
47 #define RTCP_MUX
48 #define MAX_CODEC_CHECK_FRAMES 50//x:mod_sofia.h
49 #define MAX_MISMATCH_FRAMES 5//x:mod_sofia.h
50 #define type2str(type) type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio"
51 #define VIDEO_REFRESH_FREQ 1000000
52 
53 typedef enum {
54  SMF_INIT = (1 << 0),
55  SMF_READY = (1 << 1),
56  SMF_JB_PAUSED = (1 << 2)
57 } smh_flag_t;
58 
59 
60 typedef struct secure_settings_s {
68 
69 typedef struct core_video_globals_s {
70  int cpu_count;
71  int cur_cpu;
74  uint32_t fps;
75  uint32_t synced;
77 
79 
80 struct media_helper {
86  int up;
87 };
88 
89 typedef enum {
94 
95 typedef struct switch_rtp_engine_s {
98 
100 
105 
108 
111  uint32_t check_frames;
112  uint32_t mismatch_count;
113  uint32_t last_codec_ms;
117  uint32_t ssrc;
118  uint32_t remote_ssrc;
121 
122 
125  char *adv_sdp_ip;
129 
130 
131  /** ZRTP **/
134 
138 
139  uint32_t timestamp_send;
140 
143 
146 
147  int8_t rtcp_mux;
148 
151 
154 
157 
158  struct media_helper mh;
160 
161 
162  uint8_t reset_codec;
164 
165  uint8_t fir;
166  uint8_t pli;
167  uint8_t nack;
168  uint8_t tmmbr;
169  uint8_t no_crypto;
175  uint8_t new_ice;
176  uint8_t new_dtls;
177  uint32_t sdp_bw;
178  uint8_t reject_avp;
180 
192 
194  char *origin;
195 
199 
207 
209  uint32_t num_rates;
210 
211  uint32_t owner_id;
212  uint32_t session_id;
213 
215 
216  char *msid;
217  char *cname;
218 
232 
233  uint64_t vid_frames;
234  time_t vid_started;
236 
239 };
240 
242  { "AEAD_AES_256_GCM_8", AEAD_AES_256_GCM_8, 44},
243  { "AEAD_AES_128_GCM_8", AEAD_AES_128_GCM_8, 28},
244  { "AES_CM_256_HMAC_SHA1_80", AES_CM_256_HMAC_SHA1_80, 46},
245  { "AES_CM_192_HMAC_SHA1_80", AES_CM_192_HMAC_SHA1_80, 38},
246  { "AES_CM_128_HMAC_SHA1_80", AES_CM_128_HMAC_SHA1_80, 30},
247  { "AES_CM_256_HMAC_SHA1_32", AES_CM_256_HMAC_SHA1_32, 46},
248  { "AES_CM_192_HMAC_SHA1_32", AES_CM_192_HMAC_SHA1_32, 38},
249  { "AES_CM_128_HMAC_SHA1_32", AES_CM_128_HMAC_SHA1_32, 30},
250  { "AES_CM_128_NULL_AUTH", AES_CM_128_NULL_AUTH, 30}
251 };
252 
254 {
255  int i;
256 
257  for (i = 0; i < CRYPTO_INVALID; i++) {
258  if (!strncasecmp(str, SUITES[i].name, strlen(SUITES[i].name))) {
259  return SUITES[i].type;
260  }
261  }
262 
263  return CRYPTO_INVALID;
264 }
265 
266 
268 {
270  return SUITES[type].name;
271 }
272 
273 
275 {
277  return SUITES[type].keylen;
278 }
279 
280 static inline switch_media_flow_t sdp_media_flow(unsigned in)
281 {
282  switch(in) {
283  case sdp_sendonly:
285  case sdp_recvonly:
287  case sdp_sendrecv:
289  case sdp_inactive:
291  }
292 
294 }
295 
296 static int get_channels(const char *name, int dft)
297 {
298 
299  if (!zstr(name) && !switch_true(switch_core_get_variable("NDLB_broken_opus_sdp")) && !strcasecmp(name, "opus")) {
300  return 2; /* IKR???*/
301  }
302 
303  return dft ? dft : 1;
304 }
305 
307 {
308  switch_rtp_engine_t *aleg_engine;
309  switch_rtp_engine_t *bleg_engine;
310 
311  if (!aleg_session->media_handle || !bleg_session->media_handle) return;
312  aleg_engine = &aleg_session->media_handle->engines[type];
313  bleg_engine = &bleg_session->media_handle->engines[type];
314 
315 
316 
318  "Deciding whether to pass zrtp-hash between a-leg and b-leg\n");
319 
320  if (!(switch_channel_test_flag(aleg_session->channel, CF_ZRTP_PASSTHRU_REQ))) {
322  "CF_ZRTP_PASSTHRU_REQ not set on a-leg, so not propagating zrtp-hash\n");
323  return;
324  }
325 
326  if (aleg_engine->remote_sdp_zrtp_hash) {
327  switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_session->channel), SWITCH_LOG_DEBUG, "Passing a-leg remote zrtp-hash (audio) to b-leg\n");
328  bleg_engine->local_sdp_zrtp_hash = switch_core_session_strdup(bleg_session, aleg_engine->remote_sdp_zrtp_hash);
329  switch_channel_set_variable(bleg_session->channel, "l_sdp_audio_zrtp_hash", bleg_engine->local_sdp_zrtp_hash);
330  }
331 
332  if (bleg_engine->remote_sdp_zrtp_hash) {
333  switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(aleg_session->channel), SWITCH_LOG_DEBUG, "Passing b-leg remote zrtp-hash (audio) to a-leg\n");
334  aleg_engine->local_sdp_zrtp_hash = switch_core_session_strdup(aleg_session, bleg_engine->remote_sdp_zrtp_hash);
335  switch_channel_set_variable(aleg_session->channel, "l_sdp_audio_zrtp_hash", aleg_engine->local_sdp_zrtp_hash);
336  }
337 }
338 
340 {
342  time_t now;
343  uint32_t fps;
344 
345  switch_assert(session);
346 
347  if (!(smh = session->media_handle)) {
348  return SWITCH_STATUS_FALSE;
349  }
350 
351  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
352  return 0;
353  }
354 
355  now = switch_epoch_time_now(NULL);
356 
357  if (!(smh->vid_started && smh->vid_frames && smh->vid_started < now)) {
358  return 0;
359  }
360 
361  fps = switch_round_to_step(smh->vid_frames / (now - smh->vid_started), 5);
362 
363  if (smh->vid_frames > 1000) {
364  smh->vid_started = switch_epoch_time_now(NULL);
365  smh->vid_frames = 1;
366  }
367 
368  if (fps > 0) {
369  video_globals.fps = fps;
370 
371  if (smh->vid_params.fps != fps) {
372  switch_channel_set_variable_printf(session->channel, "video_fps", "%d", fps);
373  smh->vid_params.fps = fps;
374  }
375  }
376 
377  return fps;
378 }
379 
381 {
382  _switch_core_media_pass_zrtp_hash2(aleg_session, bleg_session, SWITCH_MEDIA_TYPE_AUDIO);
383  _switch_core_media_pass_zrtp_hash2(aleg_session, bleg_session, SWITCH_MEDIA_TYPE_VIDEO);
384 }
385 
386 
388 {
390 
391  switch_core_session_t *other_session;
392  switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "Deciding whether to pass zrtp-hash between legs\n");
394  switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "CF_ZRTP_PASSTHRU_REQ not set, so not propagating zrtp-hash\n");
395  return;
396  } else if (!(switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS)) {
397  switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "No partner channel found, so not propagating zrtp-hash\n");
398  return;
399  } else {
400  switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "Found peer channel; propagating zrtp-hash if set\n");
401  switch_core_media_pass_zrtp_hash2(session, other_session);
402  switch_core_session_rwunlock(other_session);
403  }
404 }
405 
407 {
408  switch_rtp_engine_t *engine;
409  if (!session->media_handle) return NULL;
410 
411  engine = &session->media_handle->engines[type];
412 
413  if (local) {
414  return engine->local_sdp_zrtp_hash;
415  }
416 
417 
418  return engine->remote_sdp_zrtp_hash;
419 
420 }
421 
422 static void switch_core_media_find_zrtp_hash(switch_core_session_t *session, sdp_session_t *sdp)
423 {
425  switch_rtp_engine_t *audio_engine;
426  switch_rtp_engine_t *video_engine;
427  sdp_media_t *m;
428  sdp_attribute_t *attr;
429  int got_audio = 0, got_video = 0;
430 
431  if (!session->media_handle) return;
432 
433  audio_engine = &session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO];
434  video_engine = &session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO];
435 
436 
437  switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG1, "Looking for zrtp-hash\n");
438  for (m = sdp->sdp_media; m; m = m->m_next) {
439  if (got_audio && got_video) break;
440  if (m->m_port && ((m->m_type == sdp_media_audio && !got_audio)
441  || (m->m_type == sdp_media_video && !got_video))) {
442  for (attr = m->m_attributes; attr; attr = attr->a_next) {
443  if (zstr(attr->a_name)) continue;
444  if (strcasecmp(attr->a_name, "zrtp-hash") || !(attr->a_value)) continue;
445  if (m->m_type == sdp_media_audio) {
447  "Found audio zrtp-hash; setting r_sdp_audio_zrtp_hash=%s\n", attr->a_value);
448  switch_channel_set_variable(channel, "r_sdp_audio_zrtp_hash", attr->a_value);
449  audio_engine->remote_sdp_zrtp_hash = switch_core_session_strdup(session, attr->a_value);
450  got_audio++;
451  } else if (m->m_type == sdp_media_video) {
453  "Found video zrtp-hash; setting r_sdp_video_zrtp_hash=%s\n", attr->a_value);
454  switch_channel_set_variable(channel, "r_sdp_video_zrtp_hash", attr->a_value);
455  video_engine->remote_sdp_zrtp_hash = switch_core_session_strdup(session, attr->a_value);
456  got_video++;
457  }
459  break;
460  }
461  }
462  }
463 }
464 
465 
466 static switch_t38_options_t * switch_core_media_process_udptl(switch_core_session_t *session, sdp_session_t *sdp, sdp_media_t *m)
467 {
468  switch_t38_options_t *t38_options = switch_channel_get_private(session->channel, "t38_options");
469  sdp_attribute_t *attr;
470 
471  switch_assert(sdp);
472 
473  if (!t38_options) {
474  t38_options = switch_core_session_alloc(session, sizeof(switch_t38_options_t));
475 
476  // set some default value
477  t38_options->T38FaxVersion = 0;
478  t38_options->T38MaxBitRate = 14400;
479  t38_options->T38FaxRateManagement = switch_core_session_strdup(session, "transferredTCF");
480  t38_options->T38FaxUdpEC = switch_core_session_strdup(session, "t38UDPRedundancy");
481  t38_options->T38FaxMaxBuffer = 500;
482  t38_options->T38FaxMaxDatagram = 500;
483  }
484 
485  t38_options->remote_port = (switch_port_t)m->m_port;
486 
487  if (sdp->sdp_origin) {
488  t38_options->sdp_o_line = switch_core_session_strdup(session, sdp->sdp_origin->o_username);
489  } else {
490  t38_options->sdp_o_line = "unknown";
491  }
492 
493  if (m->m_connections && m->m_connections->c_address) {
494  t38_options->remote_ip = switch_core_session_strdup(session, m->m_connections->c_address);
495  } else if (sdp->sdp_connection && sdp->sdp_connection->c_address) {
496  t38_options->remote_ip = switch_core_session_strdup(session, sdp->sdp_connection->c_address);
497  }
498 
499  for (attr = m->m_attributes; attr; attr = attr->a_next) {
500  if (!strcasecmp(attr->a_name, "T38FaxVersion") && attr->a_value) {
501  t38_options->T38FaxVersion = (uint16_t) atoi(attr->a_value);
502  } else if (!strcasecmp(attr->a_name, "T38MaxBitRate") && attr->a_value) {
503  t38_options->T38MaxBitRate = (uint32_t) atoi(attr->a_value);
504  } else if (!strcasecmp(attr->a_name, "T38FaxFillBitRemoval")) {
505  t38_options->T38FaxFillBitRemoval = switch_safe_atoi(attr->a_value, 1);
506  } else if (!strcasecmp(attr->a_name, "T38FaxTranscodingMMR")) {
507  t38_options->T38FaxTranscodingMMR = switch_safe_atoi(attr->a_value, 1);
508  } else if (!strcasecmp(attr->a_name, "T38FaxTranscodingJBIG")) {
509  t38_options->T38FaxTranscodingJBIG = switch_safe_atoi(attr->a_value, 1);
510  } else if (!strcasecmp(attr->a_name, "T38FaxRateManagement") && attr->a_value) {
511  t38_options->T38FaxRateManagement = switch_core_session_strdup(session, attr->a_value);
512  } else if (!strcasecmp(attr->a_name, "T38FaxMaxBuffer") && attr->a_value) {
513  t38_options->T38FaxMaxBuffer = (uint32_t) atoi(attr->a_value);
514  } else if (!strcasecmp(attr->a_name, "T38FaxMaxDatagram") && attr->a_value) {
515  t38_options->T38FaxMaxDatagram = (uint32_t) atoi(attr->a_value);
516  } else if (!strcasecmp(attr->a_name, "T38FaxUdpEC") && attr->a_value) {
517  t38_options->T38FaxUdpEC = switch_core_session_strdup(session, attr->a_value);
518  } else if (!strcasecmp(attr->a_name, "T38VendorInfo") && attr->a_value) {
519  t38_options->T38VendorInfo = switch_core_session_strdup(session, attr->a_value);
520  }
521  }
522 
523  switch_channel_set_variable(session->channel, "has_t38", "true");
524  switch_channel_set_private(session->channel, "t38_options", t38_options);
526 
527  switch_channel_execute_on(session->channel, "sip_execute_on_image");
528  switch_channel_api_on(session->channel, "sip_api_on_image");
529 
530  return t38_options;
531 }
532 
534 {
535  switch_rtp_engine_t *a_engine;
536  switch_rtp_engine_t *v_engine;
538  const char *val;
539  int x = 0;
540 
541  switch_assert(session);
542 
543  if (!(smh = session->media_handle)) {
544  return SWITCH_STATUS_FALSE;
545  }
546 
547  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
548  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
549 
551  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
552  !switch_channel_test_flag(session->channel, CF_AVPF)) {
553  /* Reactivate the NAT buster flag. */
554 
555  if (a_engine->rtp_session) {
557  x++;
558  }
559 
560  if (v_engine->rtp_session) {
562  x++;
563  }
564  }
565 
567 }
568 
570 {
572 
573  switch_assert(session);
574 
575  if (!(smh = session->media_handle)) {
576  return SWITCH_STATUS_FALSE;
577  }
578 
579  *vid_params = smh->vid_params;
580 
581  return SWITCH_STATUS_SUCCESS;
582 }
583 
585 {
586  sdp_media_t *m;
587  sdp_parser_t *parser = NULL;
588  sdp_session_t *sdp;
589  switch_t38_options_t *t38_options = NULL;
590 
591  if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
592  return NULL;
593  }
594 
595  if (!(sdp = sdp_session(parser))) {
596  sdp_parser_free(parser);
597  return NULL;
598  }
599 
600  for (m = sdp->sdp_media; m; m = m->m_next) {
601  if (m->m_proto == sdp_proto_udptl && m->m_type == sdp_media_image && m->m_port) {
602  t38_options = switch_core_media_process_udptl(session, sdp, m);
603  break;
604  }
605  }
606 
607  sdp_parser_free(parser);
608 
609  return t38_options;
610 
611 }
612 
613 
614 
615 //?
617  switch_core_session_t *other_session, switch_t38_options_t *t38_options)
618 {
619  char *remote_host;
620  switch_port_t remote_port;
621  char tmp[32] = "";
622  switch_rtp_engine_t *a_engine;
624 
625  switch_assert(session);
626 
627  if (!(smh = session->media_handle)) {
628  return SWITCH_STATUS_FALSE;
629  }
630 
631  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
632 
633  remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
634  remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
635 
636  a_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, t38_options->remote_ip);
637  a_engine->cur_payload_map->remote_sdp_port = t38_options->remote_port;
638 
639  if (remote_host && remote_port && !strcmp(remote_host, a_engine->cur_payload_map->remote_sdp_ip) &&
640  remote_port == a_engine->cur_payload_map->remote_sdp_port) {
642  "Audio params are unchanged for %s.\n",
643  switch_channel_get_name(session->channel));
644  } else {
645  const char *err = NULL;
646 
648  "Audio params changed for %s from %s:%d to %s:%d\n",
649  switch_channel_get_name(session->channel),
650  remote_host, remote_port, a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
651 
652  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
657  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
659  }
660  }
661 
662  switch_core_media_copy_t38_options(t38_options, other_session);
663 
664  return SWITCH_STATUS_SUCCESS;
665 
666 }
667 
669  switch_media_type_t type,
670  const char *iananame,
671  uint32_t rate,
672  switch_payload_t *ptP,
673  switch_payload_t *recv_ptP,
674  char **fmtpP)
675 {
676  payload_map_t *pmap;
678  switch_rtp_engine_t *engine;
679  switch_payload_t pt = 0, recv_pt = 0;
680  int found = 0;
681  char *fmtp = NULL;
682 
683  switch_assert(session);
684 
685  if (!(smh = session->media_handle)) {
686  return SWITCH_STATUS_FALSE;
687  }
688 
689  engine = &smh->engines[type];
690 
692  for (pmap = engine->payload_map; pmap ; pmap = pmap->next) {
693 
694  if (!pmap->allocated) continue;
695 
696  if (!strcasecmp(pmap->iananame, iananame) && (!rate || (rate == pmap->rate))) {
697  pt = pmap->pt;
698  recv_pt = pmap->recv_pt;
699  fmtp = pmap->rm_fmtp;
700  found++;
701  break;
702  }
703  }
705 
706  if (found) {
707  if (ptP) {
708  *ptP = pt;
709  }
710  if (recv_ptP) {
711  *recv_ptP = recv_pt;
712  }
713 
714  if (!zstr(fmtp) && fmtpP) {
715  *fmtpP = fmtp;
716  }
717 
718  return SWITCH_STATUS_SUCCESS;
719  }
720 
721  return SWITCH_STATUS_FALSE;
722 
723 }
724 
725 
727  switch_media_type_t type,
728  const char *name,
729  const char *modname,
730  const char *fmtp,
731  switch_sdp_type_t sdp_type,
732  uint32_t pt,
733  uint32_t rate,
734  uint32_t ptime,
735  uint32_t channels,
736  uint8_t negotiated)
737 {
738  payload_map_t *pmap;
739  int exists = 0;
741  switch_rtp_engine_t *engine;
742  int local_pt = 0;
743 
744  switch_assert(session);
745 
746  if (!(smh = session->media_handle)) {
747  return NULL;
748  }
749 
750  engine = &smh->engines[type];
751 
753 
754  for (pmap = engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) {
755  exists = (!strcasecmp(name, pmap->iananame) && pmap->pt == pt && (!pmap->rate || rate == pmap->rate) && (!pmap->ptime || pmap->ptime == ptime));
756 
757  if (exists) {
758 
759  if (!zstr(fmtp) && !zstr(pmap->rm_fmtp)) {
760  if (strcmp(pmap->rm_fmtp, fmtp)) {
761  exists = 0;
762  local_pt = pmap->pt;
763  continue;
764  }
765  }
766 
767  break;
768  }
769  }
770 
771 
772  if (!exists) {
773  switch_ssize_t hlen = -1;
774 
775  if (engine->payload_map && !engine->payload_map->allocated) {
776  pmap = engine->payload_map;
777  } else {
778  pmap = switch_core_alloc(session->pool, sizeof(*pmap));
779  }
780 
781  pmap->type = type;
782  pmap->iananame = switch_core_strdup(session->pool, name);
783  pmap->rm_encoding = pmap->iananame;
784  pmap->hash = switch_ci_hashfunc_default(pmap->iananame, &hlen);
785  pmap->channels = 1;
786  }
787 
788  pmap->sdp_type = sdp_type;
789 
790  if (ptime) {
791  pmap->ptime = ptime;
792  }
793 
794  if (rate) {
795  pmap->rate = rate;
796  }
797 
798  if (channels) {
799  pmap->channels = channels;
800  }
801 
802  if (modname) {
803  pmap->modname = switch_core_strdup(session->pool, modname);
804  }
805 
806  if (!zstr(fmtp) && (zstr(pmap->rm_fmtp) || strcmp(pmap->rm_fmtp, fmtp))) {
807  pmap->rm_fmtp = switch_core_strdup(session->pool, fmtp);
808  }
809 
810  pmap->allocated = 1;
811 
812  pmap->recv_pt = (switch_payload_t) pt;
813 
814 
815  if (sdp_type == SDP_TYPE_REQUEST || !exists) {
816  pmap->pt = (switch_payload_t) (local_pt ? local_pt : pt);
817  }
818 
819  if (negotiated) {
820  pmap->negotiated = negotiated;
821  }
822 
823  if (!exists) {
824  if (pmap == engine->payload_map) {
825  engine->pmap_tail = pmap;
826  } else if (!engine->payload_map) {
827  engine->payload_map = engine->pmap_tail = pmap;
828  } else {
829  engine->pmap_tail->next = pmap;
830  engine->pmap_tail = engine->pmap_tail->next;
831  }
832  }
833 
835 
836  return pmap;
837 }
838 
839 
840 
841 
843 {
844  const char *preferred = NULL, *fallback = NULL;
846 
847  switch_assert(session);
848 
849  if (!(smh = session->media_handle)) {
850  preferred = "PCMU";
851  fallback = "PCMU";
852  } else {
853 
854  if (!(preferred = switch_channel_get_variable(session->channel, "absolute_codec_string"))) {
855  preferred = switch_channel_get_variable(session->channel, "codec_string");
856  }
857 
858  if (!preferred) {
859  if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
860  preferred = smh->mparams->outbound_codec_string;
861  fallback = smh->mparams->inbound_codec_string;
862 
863  } else {
864  preferred = smh->mparams->inbound_codec_string;
865  fallback = smh->mparams->outbound_codec_string;
866  }
867  }
868  }
869 
870  return !zstr(preferred) ? preferred : fallback;
871 }
872 
874 {
875  int i;
877 
878  const char *vars[] = { "rtp_last_audio_local_crypto_key",
879  "srtp_remote_audio_crypto_key",
880  "srtp_remote_audio_crypto_tag",
881  "srtp_remote_audio_crypto_type",
882  "srtp_remote_video_crypto_key",
883  "srtp_remote_video_crypto_tag",
884  "srtp_remote_video_crypto_type",
885  "rtp_secure_media",
886  "rtp_secure_media_inbound",
887  "rtp_secure_media_outbound",
888  NULL};
889 
890  for(i = 0; vars[i] ;i++) {
891  switch_channel_set_variable(session->channel, vars[i], NULL);
892  }
893 
894  if (!(smh = session->media_handle)) {
895  return;
896  }
897  for (i = 0; i < CRYPTO_INVALID; i++) {
900  }
901 
902 }
903 
905 {
906  if (!session->media_handle) {
907  return NULL;
908  }
909 
910  return session->media_handle->engines[type].ssec[session->media_handle->engines[type].crypto_type].local_crypto_key;
911 }
912 
913 
914 
916 {
917 
918  if (switch_stristr("clear", str)) {
919  *flag_pole = 0;
920  }
921 
922  if (switch_stristr("CISCO_SKIP_MARK_BIT_2833", str)) {
923  *flag_pole |= RTP_BUG_CISCO_SKIP_MARK_BIT_2833;
924  }
925 
926  if (switch_stristr("~CISCO_SKIP_MARK_BIT_2833", str)) {
927  *flag_pole &= ~RTP_BUG_CISCO_SKIP_MARK_BIT_2833;
928  }
929 
930  if (switch_stristr("SONUS_SEND_INVALID_TIMESTAMP_2833", str)) {
932  }
933 
934  if (switch_stristr("~SONUS_SEND_INVALID_TIMESTAMP_2833", str)) {
936  }
937 
938  if (switch_stristr("IGNORE_MARK_BIT", str)) {
939  *flag_pole |= RTP_BUG_IGNORE_MARK_BIT;
940  }
941 
942  if (switch_stristr("~IGNORE_MARK_BIT", str)) {
943  *flag_pole &= ~RTP_BUG_IGNORE_MARK_BIT;
944  }
945 
946  if (switch_stristr("SEND_LINEAR_TIMESTAMPS", str)) {
947  *flag_pole |= RTP_BUG_SEND_LINEAR_TIMESTAMPS;
948  }
949 
950  if (switch_stristr("~SEND_LINEAR_TIMESTAMPS", str)) {
951  *flag_pole &= ~RTP_BUG_SEND_LINEAR_TIMESTAMPS;
952  }
953 
954  if (switch_stristr("START_SEQ_AT_ZERO", str)) {
955  *flag_pole |= RTP_BUG_START_SEQ_AT_ZERO;
956  }
957 
958  if (switch_stristr("~START_SEQ_AT_ZERO", str)) {
959  *flag_pole &= ~RTP_BUG_START_SEQ_AT_ZERO;
960  }
961 
962  if (switch_stristr("NEVER_SEND_MARKER", str)) {
963  *flag_pole |= RTP_BUG_NEVER_SEND_MARKER;
964  }
965 
966  if (switch_stristr("~NEVER_SEND_MARKER", str)) {
967  *flag_pole &= ~RTP_BUG_NEVER_SEND_MARKER;
968  }
969 
970  if (switch_stristr("IGNORE_DTMF_DURATION", str)) {
971  *flag_pole |= RTP_BUG_IGNORE_DTMF_DURATION;
972  }
973 
974  if (switch_stristr("~IGNORE_DTMF_DURATION", str)) {
975  *flag_pole &= ~RTP_BUG_IGNORE_DTMF_DURATION;
976  }
977 
978  if (switch_stristr("ACCEPT_ANY_PACKETS", str)) {
979  *flag_pole |= RTP_BUG_ACCEPT_ANY_PACKETS;
980  }
981 
982  if (switch_stristr("~ACCEPT_ANY_PACKETS", str)) {
983  *flag_pole &= ~RTP_BUG_ACCEPT_ANY_PACKETS;
984  }
985 
986  if (switch_stristr("ACCEPT_ANY_PAYLOAD", str)) {
987  *flag_pole |= RTP_BUG_ACCEPT_ANY_PAYLOAD;
988  }
989 
990  if (switch_stristr("~ACCEPT_ANY_PAYLOAD", str)) {
991  *flag_pole &= ~RTP_BUG_ACCEPT_ANY_PAYLOAD;
992  }
993 
994  if (switch_stristr("GEN_ONE_GEN_ALL", str)) {
995  *flag_pole |= RTP_BUG_GEN_ONE_GEN_ALL;
996  }
997 
998  if (switch_stristr("~GEN_ONE_GEN_ALL", str)) {
999  *flag_pole &= ~RTP_BUG_GEN_ONE_GEN_ALL;
1000  }
1001 
1002  if (switch_stristr("CHANGE_SSRC_ON_MARKER", str)) {
1003  *flag_pole |= RTP_BUG_CHANGE_SSRC_ON_MARKER;
1004  }
1005 
1006  if (switch_stristr("~CHANGE_SSRC_ON_MARKER", str)) {
1007  *flag_pole &= ~RTP_BUG_CHANGE_SSRC_ON_MARKER;
1008  }
1009 
1010  if (switch_stristr("FLUSH_JB_ON_DTMF", str)) {
1011  *flag_pole |= RTP_BUG_FLUSH_JB_ON_DTMF;
1012  }
1013 
1014  if (switch_stristr("~FLUSH_JB_ON_DTMF", str)) {
1015  *flag_pole &= ~RTP_BUG_FLUSH_JB_ON_DTMF;
1016  }
1017 
1018  if (switch_stristr("ALWAYS_AUTO_ADJUST", str)) {
1020  }
1021 
1022  if (switch_stristr("~ALWAYS_AUTO_ADJUST", str)) {
1024  }
1025 }
1026 
1027 
1029  switch_media_type_t type,
1030  int index, switch_rtp_crypto_key_type_t ctype, switch_rtp_crypto_direction_t direction, int force)
1031 {
1032  unsigned char b64_key[512] = "";
1033  unsigned char *key;
1034  const char *val;
1035  switch_channel_t *channel;
1036  char *p;
1037  switch_rtp_engine_t *engine;
1038 
1039  switch_assert(smh);
1040  channel = switch_core_session_get_channel(smh->session);
1041 
1042  engine = &smh->engines[type];
1043 
1044  if (!force && engine->ssec[ctype].local_raw_key[0]) {
1045  return SWITCH_STATUS_SUCCESS;
1046  }
1047 
1048 
1049 
1050 //#define SAME_KEY
1051 #ifdef SAME_KEY
1052  if (switch_channel_test_flag(channel, CF_AVPF) && type == SWITCH_MEDIA_TYPE_VIDEO) {
1053  if (direction == SWITCH_RTP_CRYPTO_SEND) {
1054  memcpy(engine->ssec[ctype].local_raw_key, smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec.local_raw_key, SUITES[ctype].keylen);
1055  key = engine->ssec[ctype].local_raw_key;
1056  } else {
1057  memcpy(engine->ssec[ctype].remote_raw_key, smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec.remote_raw_key, SUITES[ctype].keylen);
1058  key = engine->ssec[ctype].remote_raw_key;
1059  }
1060  } else {
1061 #endif
1062  if (direction == SWITCH_RTP_CRYPTO_SEND) {
1063  key = engine->ssec[ctype].local_raw_key;
1064  } else {
1065  key = engine->ssec[ctype].remote_raw_key;
1066  }
1067 
1068  switch_rtp_get_random(key, SUITES[ctype].keylen);
1069 #ifdef SAME_KEY
1070  }
1071 #endif
1072 
1073  switch_b64_encode(key, SUITES[ctype].keylen, b64_key, sizeof(b64_key));
1074  p = strrchr((char *) b64_key, '=');
1075 
1076  while (p && *p && *p == '=') {
1077  *p-- = '\0';
1078  }
1079 
1080  if (index == SWITCH_NO_CRYPTO_TAG) index = ctype + 1;
1081 
1082  engine->ssec[ctype].local_crypto_key = switch_core_session_sprintf(smh->session, "%d %s inline:%s", index, SUITES[ctype].name, b64_key);
1083  switch_channel_set_variable_name_printf(smh->session->channel, engine->ssec[ctype].local_crypto_key, "rtp_last_%s_local_crypto_key", type2str(type));
1085 
1086  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Set Local %s crypto Key [%s]\n",
1087  type2str(type),
1088  engine->ssec[ctype].local_crypto_key);
1089 
1090  if (!(smh->mparams->ndlb & SM_NDLB_DISABLE_SRTP_AUTH) &&
1091  !((val = switch_channel_get_variable(channel, "NDLB_support_asterisk_missing_srtp_auth")) && switch_true(val))) {
1092  engine->ssec[ctype].crypto_type = ctype;
1093  } else {
1094  engine->ssec[ctype].crypto_type = AES_CM_128_NULL_AUTH;
1095  }
1096 
1097  return SWITCH_STATUS_SUCCESS;
1098 }
1099 
1100 
1101 
1102 
1103 
1105 {
1106  unsigned char key[SWITCH_RTP_MAX_CRYPTO_LEN];
1108  char *p;
1109 
1110 
1111  p = strchr(key_str, ' ');
1112 
1113  if (p && *p && *(p + 1)) {
1114  p++;
1115 
1117 
1118  if (type == CRYPTO_INVALID) {
1119  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error near [%s]\n", p);
1120  goto bad;
1121  }
1122 
1123  p = strchr(p, ' ');
1124  if (p && *p && *(p + 1)) {
1125  p++;
1126  if (strncasecmp(p, "inline:", 7)) {
1127  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Parse Error near [%s]\n", p);
1128  goto bad;
1129  }
1130 
1131  p += 7;
1132  switch_b64_decode(p, (char *) key, sizeof(key));
1133 
1134  if (direction == SWITCH_RTP_CRYPTO_SEND) {
1135  memcpy(ssec->local_raw_key, key, SUITES[type].keylen);
1136  } else {
1137  memcpy(ssec->remote_raw_key, key, SUITES[type].keylen);
1138  }
1139  return SWITCH_STATUS_SUCCESS;
1140  }
1141 
1142  }
1143 
1144  bad:
1145 
1147  return SWITCH_STATUS_FALSE;
1148 
1149 }
1150 
1152 {
1153  switch_rtp_engine_t *engine;
1154  if (!session->media_handle) return;
1155  engine = &session->media_handle->engines[type];
1156  engine->rtp_session = rtp_session;
1157  engine->type = type;
1158 }
1159 
1160 
1162 {
1163  const char *tmp;
1164  switch_rtp_engine_t *engine;
1165  char *keyvar, *tagvar, *ctypevar;
1166 
1167  if (!session->media_handle) return;
1168  engine = &session->media_handle->engines[type];
1169 
1170  if (type == SWITCH_MEDIA_TYPE_AUDIO) {
1171  keyvar = "srtp_remote_audio_crypto_key";
1172  tagvar = "srtp_remote_audio_crypto_tag";
1173  ctypevar = "srtp_remote_audio_crypto_type";
1174  } else {
1175  keyvar = "srtp_remote_video_crypto_key";
1176  tagvar = "srtp_remote_video_crypto_tag";
1177  ctypevar = "srtp_remote_video_crypto_type";
1178  }
1179 
1180  if ((tmp = switch_channel_get_variable(session->channel, keyvar))) {
1181  if ((tmp = switch_channel_get_variable(session->channel, ctypevar))) {
1183  }
1184 
1185  engine->ssec[engine->crypto_type].remote_crypto_key = switch_core_session_strdup(session, tmp);
1186 
1187  if ((tmp = switch_channel_get_variable(session->channel, tagvar))) {
1188  int tv = atoi(tmp);
1189  engine->ssec[engine->crypto_type].crypto_tag = tv;
1190  } else {
1191  engine->ssec[engine->crypto_type].crypto_tag = 1;
1192  }
1193 
1195  }
1196 }
1197 
1198 
1200 {
1201  switch_rtp_engine_t *engine;
1202  const char *varname;
1203 
1204  if (type == SWITCH_MEDIA_TYPE_AUDIO) {
1205  varname = "rtp_secure_audio_confirmed";
1206  } else {
1207  varname = "rtp_secure_video_confirmed";
1208  }
1209 
1210  if (!session->media_handle) return;
1211 
1212  engine = &session->media_handle->engines[type];
1213 
1215  return;
1216  }
1217 
1218  if (engine->ssec[engine->crypto_type].remote_crypto_key && switch_channel_test_flag(session->channel, CF_SECURE)) {
1220 
1221 
1223  engine->ssec[engine->crypto_type].crypto_type,
1224  engine->ssec[engine->crypto_type].local_raw_key,
1225  SUITES[engine->ssec[engine->crypto_type].crypto_type].keylen);
1226 
1228  engine->ssec[engine->crypto_type].crypto_tag,
1229  engine->ssec[engine->crypto_type].crypto_type,
1230  engine->ssec[engine->crypto_type].remote_raw_key,
1231  SUITES[engine->ssec[engine->crypto_type].crypto_type].keylen);
1232 
1233  switch_channel_set_variable(session->channel, varname, "true");
1234 
1235 
1236  switch_channel_set_variable(session->channel, "rtp_secure_media_negotiated", SUITES[engine->crypto_type].name);
1237 
1238  }
1239 
1240 }
1241 
1243 {
1244  const char *var = NULL;
1245  const char *val = NULL;
1246  char *suites = NULL;
1247  switch_media_handle_t *smh;
1248  char *fields[CRYPTO_INVALID+1];
1249  int argc = 0, i = 0, j = 0, k = 0;
1250 
1251  if (!(smh = session->media_handle)) {
1252  return;
1253  }
1254 
1255  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
1256  return;
1257  }
1258 
1260  var = "rtp_secure_media_inbound";
1261  } else {
1262  var = "rtp_secure_media_outbound";
1263  }
1264 
1265  if (!(val = switch_channel_get_variable(session->channel, var))) {
1266  var = "rtp_secure_media";
1267  val = switch_channel_get_variable(session->channel, var);
1268  }
1269 
1270  if (!zstr(val) && (suites = strchr(val, ':'))) {
1271  *suites++ = '\0';
1272  }
1273 
1274  if (zstr(suites)) {
1275  suites = (char *) switch_channel_get_variable(session->channel, "rtp_secure_media_suites");
1276  }
1277 
1278  if (zstr(val)) {
1280  val = "optional";
1281  } else {
1282  val = "forbidden";
1283  }
1284  }
1285 
1286  if (!strcasecmp(val, "optional")) {
1288  } else if (switch_true(val) || !strcasecmp(val, "mandatory")) {
1290  } else {
1292  if (!switch_false(val) && strcasecmp(val, "forbidden")) {
1293  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "INVALID VALUE FOR %s defaulting to 'forbidden'\n", var);
1294  }
1295  }
1296 
1297  if (smh->crypto_mode != CRYPTO_MODE_FORBIDDEN && !zstr(suites)) {
1298  argc = switch_split((char *)suites, ':', fields);
1299 
1300  for (i = 0; i < argc; i++) {
1301  int ok = 0;
1302 
1303  for (j = 0; j < CRYPTO_INVALID; j++) {
1304  if (!strcasecmp(fields[i], SUITES[j].name)) {
1305  smh->crypto_suite_order[k++] = SUITES[j].type;
1306  ok++;
1307  break;
1308  }
1309  }
1310 
1311  if (!ok) {
1312  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "INVALID SUITE SUPPLIED\n");
1313  }
1314 
1315  }
1316  } else {
1317  for (i = 0; i < CRYPTO_INVALID; i++) {
1318  smh->crypto_suite_order[k++] = SUITES[i].type;
1319  }
1320  }
1321 }
1322 
1323 
1324 
1326  const char *varname,
1327  switch_media_type_t type, const char *crypto, int crypto_tag, switch_sdp_type_t sdp_type)
1328 {
1329  int got_crypto = 0;
1330  int i = 0;
1331  int ctype = 0;
1332  const char *vval = NULL;
1333  switch_rtp_engine_t *engine;
1334  switch_media_handle_t *smh;
1335 
1336  if (!(smh = session->media_handle)) {
1337  return 0;
1338  }
1339 
1340  if (smh->crypto_mode == CRYPTO_MODE_FORBIDDEN) {
1341  return -1;
1342  }
1343 
1344  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
1345  return 0;
1346  }
1347 
1348  engine = &session->media_handle->engines[type];
1349 
1350  for (i = 0; smh->crypto_suite_order[i] != CRYPTO_INVALID; i++) {
1352 
1353  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,"looking for crypto suite [%s] in [%s]\n", SUITES[j].name, crypto);
1354 
1355  if (switch_stristr(SUITES[j].name, crypto)) {
1356  ctype = SUITES[j].type;
1357  vval = SUITES[j].name;
1358  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Found suite %s\n", vval);
1359  switch_channel_set_variable(session->channel, "rtp_secure_media_negotiated", vval);
1360  break;
1361  }
1362  }
1363 
1364  if (engine->ssec[engine->crypto_type].remote_crypto_key && switch_rtp_ready(engine->rtp_session)) {
1365  /* Compare all the key. The tag may remain the same even if key changed */
1366  if (crypto && engine->crypto_type != CRYPTO_INVALID && !strcmp(crypto, engine->ssec[engine->crypto_type].remote_crypto_key)) {
1367  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Existing key is still valid.\n");
1368  got_crypto = 1;
1369  } else {
1370  const char *a = switch_stristr("AE", engine->ssec[engine->crypto_type].remote_crypto_key);
1371  const char *b = switch_stristr("AE", crypto);
1372 
1373  if (sdp_type == SDP_TYPE_REQUEST) {
1374  if (!vval) {
1375  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Unsupported Crypto [%s]\n", crypto);
1376  goto end;
1377  }
1378  switch_channel_set_variable(session->channel, varname, vval);
1379 
1380  switch_core_media_build_crypto(session->media_handle, type, crypto_tag, ctype, SWITCH_RTP_CRYPTO_SEND, 1);
1382  engine->ssec[engine->crypto_type].local_raw_key, SUITES[ctype].keylen);
1383  }
1384 
1385  if (a && b && !strncasecmp(a, b, 23)) {
1386  engine->crypto_type = ctype;
1387 
1388  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Change Remote key to [%s]\n", crypto);
1389  engine->ssec[engine->crypto_type].remote_crypto_key = switch_core_session_strdup(session, crypto);
1390 
1391  if (engine->type == SWITCH_MEDIA_TYPE_AUDIO) {
1392  switch_channel_set_variable(session->channel, "srtp_remote_audio_crypto_key", crypto);
1393  switch_channel_set_variable_printf(session->channel, "srtp_remote_audio_crypto_tag", "%d", crypto_tag);
1394  switch_channel_set_variable_printf(session->channel, "srtp_remote_audio_crypto_type", "%s", switch_core_media_crypto_type2str(ctype));
1395  } else if (engine->type == SWITCH_MEDIA_TYPE_VIDEO) {
1396  switch_channel_set_variable(session->channel, "srtp_remote_video_crypto_key", crypto);
1397  switch_channel_set_variable_printf(session->channel, "srtp_remote_video_crypto_tag", "%d", crypto_tag);
1398  switch_channel_set_variable_printf(session->channel, "srtp_remote_video_crypto_type", "%s", switch_core_media_crypto_type2str(ctype));
1399  }
1400 
1401  engine->ssec[engine->crypto_type].crypto_tag = crypto_tag;
1402 
1403 
1404  if (switch_rtp_ready(engine->rtp_session) && switch_channel_test_flag(session->channel, CF_SECURE)) {
1407  engine->ssec[engine->crypto_type].crypto_type, engine->ssec[engine->crypto_type].remote_raw_key, SUITES[engine->ssec[engine->crypto_type].crypto_type].keylen);
1408  }
1409  got_crypto++;
1410 
1411  } else {
1412  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Ignoring unacceptable key\n");
1413  }
1414  }
1415  } else if (!switch_rtp_ready(engine->rtp_session)) {
1416 
1417  if (!vval) {
1418  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Unsupported Crypto [%s]\n", crypto);
1419  goto end;
1420  }
1421 
1422  engine->crypto_type = ctype;
1423  engine->ssec[engine->crypto_type].remote_crypto_key = switch_core_session_strdup(session, crypto);
1424  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set Remote Key [%s]\n", engine->ssec[engine->crypto_type].remote_crypto_key);
1425  if (engine->type == SWITCH_MEDIA_TYPE_AUDIO) {
1426  switch_channel_set_variable(session->channel, "srtp_remote_audio_crypto_key", crypto);
1427  switch_channel_set_variable_printf(session->channel, "srtp_remote_audio_crypto_type", "%s", switch_core_media_crypto_type2str(ctype));
1428  } else if (engine->type == SWITCH_MEDIA_TYPE_VIDEO) {
1429  switch_channel_set_variable(session->channel, "srtp_remote_video_crypto_key", crypto);
1430  switch_channel_set_variable_printf(session->channel, "srtp_remote_video_crypto_type", "%s", switch_core_media_crypto_type2str(ctype));
1431  }
1432 
1433  engine->ssec[engine->crypto_type].crypto_tag = crypto_tag;
1434  got_crypto++;
1435 
1436  switch_channel_set_variable(session->channel, varname, vval);
1438 
1439  if (zstr(engine->ssec[engine->crypto_type].local_crypto_key)) {
1440  switch_core_media_build_crypto(session->media_handle, type, crypto_tag, ctype, SWITCH_RTP_CRYPTO_SEND, 1);
1441  }
1442  }
1443 
1444  end:
1445 
1446  return got_crypto;
1447 }
1448 
1449 
1451 {
1453  switch_media_handle_t *smh;
1454  int i;
1455 
1457  return;
1458  }
1459 
1460  if (!(smh = session->media_handle)) {
1461  return;
1462  }
1463 
1465  return;
1466  }
1467 
1468  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
1469  return;
1470  }
1471 
1473 
1474  for (i = 0; smh->crypto_suite_order[i] != CRYPTO_INVALID; i++) {
1475  switch_core_media_build_crypto(session->media_handle,
1477 
1478  switch_core_media_build_crypto(session->media_handle,
1480  }
1481 
1482 }
1483 
1484 #define add_stat(_i, _s) \
1485  switch_snprintf(var_name, sizeof(var_name), "rtp_%s_%s", switch_str_nil(prefix), _s) ; \
1486  switch_snprintf(var_val, sizeof(var_val), "%" SWITCH_SIZE_T_FMT, _i); \
1487  switch_channel_set_variable(channel, var_name, var_val)
1488 
1489 #define add_stat_double(_i, _s) \
1490  switch_snprintf(var_name, sizeof(var_name), "rtp_%s_%s", switch_str_nil(prefix), _s) ; \
1491  switch_snprintf(var_val, sizeof(var_val), "%0.2f", _i); \
1492  switch_channel_set_variable(channel, var_name, var_val)
1493 
1494 static void set_stats(switch_core_session_t *session, switch_media_type_t type, const char *prefix)
1495 {
1496  switch_rtp_stats_t *stats = switch_core_media_get_stats(session, type, NULL);
1498 
1499  char var_name[256] = "", var_val[35] = "";
1500 
1501  if (stats) {
1502  stats->inbound.std_deviation = sqrt(stats->inbound.variance);
1503 
1504  add_stat(stats->inbound.raw_bytes, "in_raw_bytes");
1505  add_stat(stats->inbound.media_bytes, "in_media_bytes");
1506  add_stat(stats->inbound.packet_count, "in_packet_count");
1507  add_stat(stats->inbound.media_packet_count, "in_media_packet_count");
1508  add_stat(stats->inbound.skip_packet_count, "in_skip_packet_count");
1509  add_stat(stats->inbound.jb_packet_count, "in_jitter_packet_count");
1510  add_stat(stats->inbound.dtmf_packet_count, "in_dtmf_packet_count");
1511  add_stat(stats->inbound.cng_packet_count, "in_cng_packet_count");
1512  add_stat(stats->inbound.flush_packet_count, "in_flush_packet_count");
1513  add_stat(stats->inbound.largest_jb_size, "in_largest_jb_size");
1514  add_stat_double(stats->inbound.min_variance, "in_jitter_min_variance");
1515  add_stat_double(stats->inbound.max_variance, "in_jitter_max_variance");
1516  add_stat_double(stats->inbound.lossrate, "in_jitter_loss_rate");
1517  add_stat_double(stats->inbound.burstrate, "in_jitter_burst_rate");
1518  add_stat_double(stats->inbound.mean_interval, "in_mean_interval");
1519  add_stat(stats->inbound.flaws, "in_flaw_total");
1520  add_stat_double(stats->inbound.R, "in_quality_percentage");
1521  add_stat_double(stats->inbound.mos, "in_mos");
1522 
1523 
1524  add_stat(stats->outbound.raw_bytes, "out_raw_bytes");
1525  add_stat(stats->outbound.media_bytes, "out_media_bytes");
1526  add_stat(stats->outbound.packet_count, "out_packet_count");
1527  add_stat(stats->outbound.media_packet_count, "out_media_packet_count");
1528  add_stat(stats->outbound.skip_packet_count, "out_skip_packet_count");
1529  add_stat(stats->outbound.dtmf_packet_count, "out_dtmf_packet_count");
1530  add_stat(stats->outbound.cng_packet_count, "out_cng_packet_count");
1531 
1532  add_stat(stats->rtcp.packet_count, "rtcp_packet_count");
1533  add_stat(stats->rtcp.octet_count, "rtcp_octet_count");
1534 
1535  }
1536 }
1537 
1539 {
1540  switch_media_handle_t *smh;
1541  switch_rtp_engine_t *a_engine, *v_engine;
1542 
1543  switch_assert(session);
1544 
1545  if (!(smh = session->media_handle)) {
1546  return;
1547  }
1548 
1549  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
1550  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
1551 
1552  if (a_engine->rtp_session) {
1554  }
1555 
1556  if (v_engine->rtp_session) {
1558  }
1559 
1560 }
1561 
1563 {
1564 
1565  if (!session->media_handle) {
1566  return;
1567  }
1568 
1570 
1571  set_stats(session, SWITCH_MEDIA_TYPE_AUDIO, "audio");
1572  set_stats(session, SWITCH_MEDIA_TYPE_VIDEO, "video");
1573 }
1574 
1575 
1576 
1578 {
1579  switch_media_handle_t *smh;
1580  switch_rtp_engine_t *a_engine, *v_engine;
1581 
1582  switch_assert(session);
1583 
1584  if (!(smh = session->media_handle)) {
1585  return;
1586  }
1587 
1588  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
1589  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
1590 
1591 
1592  if (smh->video_timer.timer_interface) {
1594  }
1595 
1596  if (switch_core_codec_ready(&a_engine->read_codec)) {
1598  }
1599 
1600  if (switch_core_codec_ready(&a_engine->write_codec)) {
1602  }
1603 
1604  if (switch_core_codec_ready(&v_engine->read_codec)) {
1606  }
1607 
1608  if (switch_core_codec_ready(&v_engine->write_codec)) {
1610  }
1611 
1615 
1616 
1617 
1618 }
1619 
1620 
1622 {
1624  switch_media_handle_t *smh = NULL;
1625  int i;
1626 
1627  *smhp = NULL;
1628 
1629  if (zstr(params->sdp_username)) {
1630  params->sdp_username = "FreeSWITCH";
1631  }
1632 
1633 
1634  if ((session->media_handle = switch_core_session_alloc(session, (sizeof(*smh))))) {
1635  session->media_handle->session = session;
1636 
1637 
1638  *smhp = session->media_handle;
1639  switch_set_flag(session->media_handle, SMF_INIT);
1640  session->media_handle->media_flags[SCMF_RUNNING] = 1;
1641  session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].read_frame.buflen = SWITCH_RTP_MAX_BUF_LEN;
1642  session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].type = SWITCH_MEDIA_TYPE_AUDIO;
1643  session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].crypto_type = CRYPTO_INVALID;
1644 
1645  for (i = 0; i < CRYPTO_INVALID; i++) {
1646  session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec[i].crypto_type = i;
1647  }
1648 
1649  session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].read_frame.buflen = SWITCH_RTP_MAX_BUF_LEN;
1650  session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].type = SWITCH_MEDIA_TYPE_VIDEO;
1651  session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].crypto_type = CRYPTO_INVALID;
1652 
1653 
1654  switch_channel_set_variable(session->channel, "video_media_flow", "sendrecv");
1655  switch_channel_set_variable(session->channel, "audio_media_flow", "sendrecv");
1656 
1657  session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].smode = SWITCH_MEDIA_FLOW_SENDRECV;
1658  session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].smode = SWITCH_MEDIA_FLOW_SENDRECV;
1659 
1660  for (i = 0; i < CRYPTO_INVALID; i++) {
1661  session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].ssec[i].crypto_type = i;
1662  }
1663 
1664  session->media_handle->mparams = params;
1665 
1666  if (!session->media_handle->mparams->video_key_freq) {
1667  session->media_handle->mparams->video_key_freq = 10000000;
1668  }
1669 
1670  if (!session->media_handle->mparams->video_key_first) {
1671  session->media_handle->mparams->video_key_first = 1000000;
1672  }
1673 
1674 
1675  for (i = 0; i <= CRYPTO_INVALID; i++) {
1676  session->media_handle->crypto_suite_order[i] = CRYPTO_INVALID;
1677  }
1678 
1679  switch_mutex_init(&session->media_handle->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
1680  switch_mutex_init(&session->media_handle->sdp_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
1681  switch_mutex_init(&session->media_handle->control_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
1682 
1683  session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].ssrc =
1684  (uint32_t) ((intptr_t) &session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO] + (uint32_t) time(NULL));
1685 
1686  session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].ssrc =
1687  (uint32_t) ((intptr_t) &session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO] + (uint32_t) time(NULL) / 2);
1688 
1689  session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].payload_map = switch_core_alloc(session->pool, sizeof(payload_map_t));
1690  session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].cur_payload_map = session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].payload_map;
1691  session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO].cur_payload_map->current = 1;
1692  session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].payload_map = switch_core_alloc(session->pool, sizeof(payload_map_t));
1693  session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].cur_payload_map = session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].payload_map;
1694  session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].cur_payload_map->current = 1;
1695  session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO].codec_settings.video.try_hardware_encoder = 1;
1696 
1697  switch_channel_set_flag(session->channel, CF_DTLS_OK);
1698 
1699  status = SWITCH_STATUS_SUCCESS;
1700  }
1701 
1702 
1703  return status;
1704 }
1705 
1707 {
1708  switch_assert(smh);
1709 
1710  smh->media_flags[flag] = 1;
1711 
1712 }
1713 
1715 {
1716  int i;
1717  switch_assert(smh);
1718 
1719  for(i = 0; i < SCMF_MAX; i++) {
1720  if (flags[i]) {
1721  smh->media_flags[i] = flags[i];
1722  }
1723  }
1724 
1725 }
1726 
1728 {
1729  switch_assert(smh);
1730 
1731  smh->media_flags[flag] = 0;
1732 }
1733 
1735 {
1736  switch_assert(smh);
1737  return smh->media_flags[flag];
1738 }
1739 
1741 {
1743  switch_media_handle_t *smh;
1744  switch_rtp_engine_t *engine = NULL;
1745 
1746  switch_assert(session);
1747 
1748  if (!(smh = session->media_handle)) {
1749  goto end;
1750  }
1751 
1752  if (!smh->media_flags[SCMF_RUNNING]) {
1753  goto end;
1754  }
1755 
1756  engine = &smh->engines[type];
1757  flow = engine->smode;
1758 
1759  end:
1760 
1761  return flow;
1762 }
1763 
1765 {
1766  if (session->media_handle && switch_test_flag(session->media_handle, SMF_INIT)) {
1767  return SWITCH_STATUS_SUCCESS;
1768  }
1769 
1770  return SWITCH_STATUS_FALSE;
1771 }
1772 
1773 
1774 
1776 {
1778  return session->media_handle;
1779  }
1780 
1781  return NULL;
1782 }
1783 
1785 {
1786  if (!session->media_handle) {
1787  return SWITCH_STATUS_FALSE;
1788  }
1789 
1790  return SWITCH_STATUS_SUCCESS;
1791 }
1792 
1794 {
1795  switch_assert(smh);
1796  return smh->mparams;
1797 }
1798 
1800 {
1801  const char *abs, *codec_string = NULL;
1802  const char *ocodec = NULL, *val;
1803  switch_media_handle_t *smh;
1804  char *tmp_codec_string;
1805 
1806  switch_assert(session);
1807 
1808  if (!(smh = session->media_handle)) {
1809  return;
1810  }
1811 
1812  if (!force && (switch_channel_test_flag(session->channel, CF_PROXY_MODE) || switch_channel_test_flag(session->channel, CF_PROXY_MEDIA))) {
1813  return;
1814  }
1815 
1816  if (force) {
1817  smh->mparams->num_codecs = 0;
1818  }
1819 
1820  if (smh->mparams->num_codecs) {
1821  return;
1822  }
1823 
1824  smh->payload_space = 0;
1825 
1826  switch_assert(smh->session != NULL);
1827 
1828  if ((abs = switch_channel_get_variable(session->channel, "absolute_codec_string"))) {
1829  codec_string = abs;
1830  goto ready;
1831  }
1832 
1833  val = switch_channel_get_variable_dup(session->channel, "media_mix_inbound_outbound_codecs", SWITCH_FALSE, -1);
1834  if (!val || !switch_true(val)) {
1835  if ((ocodec = switch_channel_get_variable(session->channel, SWITCH_ORIGINATOR_CODEC_VARIABLE))) {
1836  codec_string = ocodec;
1837  goto ready;
1838  }
1839  }
1840 
1841  if (!(codec_string = switch_channel_get_variable(session->channel, "codec_string"))) {
1842  codec_string = switch_core_media_get_codec_string(smh->session);
1843  }
1844 
1845  if (codec_string && *codec_string == '=') {
1846  codec_string++;
1847  goto ready;
1848  }
1849 
1850  if (ocodec) {
1851  if (!codec_string || (smh->media_flags[SCMF_DISABLE_TRANSCODING])) {
1852  codec_string = ocodec;
1853  } else {
1854  if (!(codec_string = switch_core_session_sprintf(smh->session, "%s,%s", ocodec, codec_string))) {
1855  codec_string = ocodec;
1856  }
1857  }
1858  }
1859 
1860  ready:
1861 
1862  if (!codec_string) {
1863  codec_string = "PCMU@20i,PCMA@20i,speex@20i";
1864  }
1865 
1866  tmp_codec_string = switch_core_session_strdup(smh->session, codec_string);
1867  switch_channel_set_variable(session->channel, "rtp_use_codec_string", codec_string);
1868  smh->codec_order_last = switch_separate_string(tmp_codec_string, ',', smh->codec_order, SWITCH_MAX_CODECS);
1870 
1871 }
1872 
1873 
1874 
1875 static void check_jb(switch_core_session_t *session, const char *input, int32_t jb_msec, int32_t maxlen, switch_bool_t silent)
1876 {
1877  const char *val;
1878  switch_media_handle_t *smh;
1879  switch_rtp_engine_t *a_engine = NULL, *v_engine = NULL;
1880 
1881  switch_assert(session);
1882 
1883  if (!(smh = session->media_handle)) {
1884  return;
1885  }
1886 
1887  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
1888  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
1889 
1890 
1891  if (!zstr(input)) {
1892  const char *s;
1893  if (a_engine->rtp_session) {
1894  if (!strcasecmp(input, "pause")) {
1896  return;
1897  } else if (!strcasecmp(input, "resume")) {
1899  return;
1900  } else if (!strcasecmp(input, "stop")) {
1902  return;
1903  } else if (!strncasecmp(input, "debug:", 6)) {
1904  s = input + 6;
1905  if (s && !strcmp(s, "off")) {
1906  s = NULL;
1907  }
1909  return;
1910  }
1911 
1912  switch_channel_set_variable(session->channel, "jitterbuffer_msec", input);
1913  }
1914 
1915  if (v_engine->rtp_session) {
1916  if (!strncasecmp(input, "vbsize:", 7)) {
1917  int frames = 0, max_frames = 0;
1918  s = input + 7;
1919 
1920  frames = atoi(s);
1921 
1922  if ((s = strchr(s, ':')) && *(s+1) != '\0') {
1923  max_frames = atoi(s+1);
1924  }
1925 
1926  if (frames > 0) {
1927  switch_rtp_set_video_buffer_size(v_engine->rtp_session, frames, max_frames);
1928  }
1929  return;
1930  } else if (!strncasecmp(input, "vdebug:", 7)) {
1931  s = input + 7;
1932 
1933  if (s && !strcmp(s, "off")) {
1934  s = NULL;
1935  }
1936  switch_rtp_debug_jitter_buffer(v_engine->rtp_session, s);
1937  return;
1938  }
1939  }
1940  }
1941 
1942 
1943  if (jb_msec || (val = switch_channel_get_variable(session->channel, "jitterbuffer_msec")) || (val = smh->mparams->jb_msec)) {
1944  char *p;
1945 
1946  if (!jb_msec) {
1947  jb_msec = atoi(val);
1948 
1949  if (strchr(val, 'p') && jb_msec > 0) {
1950  jb_msec *= -1;
1951  }
1952 
1953  if ((p = strchr(val, ':'))) {
1954  p++;
1955  maxlen = atoi(p);
1956 
1957  if (strchr(p, 'p') && maxlen > 0) {
1958  maxlen *= -1;
1959  }
1960  }
1961  }
1962 
1963  if (jb_msec < 0 && jb_msec > -1000) {
1964  jb_msec = (a_engine->read_codec.implementation->microseconds_per_packet / 1000) * abs(jb_msec);
1965  }
1966 
1967  if (maxlen < 0 && maxlen > -1000) {
1968  maxlen = (a_engine->read_codec.implementation->microseconds_per_packet / 1000) * abs(maxlen);
1969  }
1970 
1971  if (jb_msec < 10 || jb_msec > 10000) {
1973  "Invalid Jitterbuffer spec [%d] must be between 10 and 10000\n", jb_msec);
1974  } else {
1975  int qlen, maxqlen = 50;
1976 
1977  qlen = jb_msec / (a_engine->read_impl.microseconds_per_packet / 1000);
1978 
1979  if (maxlen) {
1980  maxqlen = maxlen / (a_engine->read_impl.microseconds_per_packet / 1000);
1981  }
1982 
1983  if (maxqlen < qlen) {
1984  maxqlen = qlen * 5;
1985  }
1986  if (switch_rtp_activate_jitter_buffer(a_engine->rtp_session, qlen, maxqlen,
1987  a_engine->read_impl.samples_per_packet,
1989  if (!silent) {
1991  SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames) (%d max frames)\n",
1992  jb_msec, qlen, maxqlen);
1993  }
1995  if (!switch_false(switch_channel_get_variable(session->channel, "rtp_jitter_buffer_plc"))) {
1997  }
1998  } else if (!silent) {
2000  SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen);
2001  }
2002 
2003  }
2004  }
2005 
2006 }
2007 
2009 {
2010  int32_t jb_sync_msec = 0;
2011  uint32_t fps = 0, frames = 0;
2012  uint32_t min_frames = 0;
2013  uint32_t max_frames = 0;
2014  uint32_t cur_frames = 0;
2015  switch_media_handle_t *smh;
2016  switch_rtp_engine_t *v_engine = NULL;
2017  int sync_audio = 0, sync_video = 0;
2018 
2019  const char *var;
2020 
2021  switch_assert(session);
2022 
2023  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
2024  return;
2025  }
2026 
2027  if (!(smh = session->media_handle)) {
2028  return;
2029  }
2030 
2031  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
2032 
2033  if ((var = switch_channel_get_variable_dup(session->channel, "jb_av_sync_msec", SWITCH_FALSE, -1))) {
2034  int tmp;
2035  char *p;
2036 
2037  if (!strcasecmp(var, "disabled")) {
2038  return;
2039  }
2040 
2041  tmp = atol(var);
2042 
2043  if (tmp && tmp > -50 && tmp < 10000) {
2044  jb_sync_msec = tmp;
2045  }
2046 
2047  if ((p = strchr(var, ':'))) {
2048  p++;
2049  frames = atoi(p);
2050  }
2051  }
2052 
2053  fps = switch_core_media_get_video_fps(session);
2054 
2055  switch_rtp_get_video_buffer_size(v_engine->rtp_session, &min_frames, &max_frames, &cur_frames, NULL);
2056 
2057  if (!frames) {
2058  if (cur_frames != min_frames) {
2059  frames = cur_frames;
2060  } else {
2061  frames = fps / 7.5;
2062  if (frames < 1) frames = 1;
2063  sync_audio = 1;
2064  }
2065  }
2066 
2067  if (!jb_sync_msec) {
2068  jb_sync_msec = frames * 75;
2069  }
2070 
2071 
2072  if (frames != cur_frames) {
2073  switch_rtp_set_video_buffer_size(v_engine->rtp_session, frames, 0);
2074  sync_audio = 1;
2075  sync_video = 1;
2076  }
2077 
2079  SWITCH_LOG_DEBUG1, "%s %s \"%s\" Sync A/V JB to %dms %u VFrames FPS %u a:%s v:%s\n",
2081  switch_channel_get_name(session->channel),
2082  switch_channel_get_variable_dup(session->channel, "caller_id_name", SWITCH_FALSE, -1),
2083  jb_sync_msec, frames, video_globals.fps, sync_audio ? "yes" : "no", sync_video ? "yes" : "no");
2084 
2085  if (sync_audio) {
2086  check_jb(session, NULL, jb_sync_msec, 0, SWITCH_TRUE);
2087  }
2088 
2089  video_globals.synced++;
2090 }
2091 
2092 
2093 //?
2095 {
2096  switch_rtp_engine_t *engine;
2097  switch_media_handle_t *smh;
2098 
2099  switch_assert(session);
2100 
2101  if (!(smh = session->media_handle)) {
2102  return SWITCH_STATUS_FALSE;
2103  }
2104 
2105  if (!smh->media_flags[SCMF_RUNNING]) {
2106  return SWITCH_STATUS_FALSE;
2107  }
2108 
2109  engine = &smh->engines[type];
2110 
2111  if (!engine->read_codec.implementation || !switch_core_codec_ready(&engine->read_codec)) {
2112  return SWITCH_STATUS_FALSE;
2113  }
2114 
2115  switch_assert(engine->rtp_session != NULL);
2116 
2117 
2118  if (!switch_channel_up_nosig(session->channel) || !switch_rtp_ready(engine->rtp_session) || switch_channel_test_flag(session->channel, CF_NOT_READY)) {
2119  return SWITCH_STATUS_FALSE;
2120  }
2121 
2122  if (lock) {
2123  if (smh->read_mutex[type] && switch_mutex_trylock(smh->read_mutex[type]) != SWITCH_STATUS_SUCCESS) {
2124  /* return CNG, another thread is already reading */
2125  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s is already being read for %s\n",
2126  switch_channel_get_name(session->channel), type2str(type));
2127  return SWITCH_STATUS_INUSE;
2128  }
2129  } else {
2130  switch_mutex_unlock(smh->read_mutex[type]);
2131  }
2132 
2133  return SWITCH_STATUS_SUCCESS;
2134 }
2135 
2136 
2137 //?
2139  switch_io_flag_t flags, int stream_id, switch_media_type_t type)
2140 {
2141  switch_rtcp_frame_t rtcp_frame;
2142  switch_rtp_engine_t *engine;
2143  switch_status_t status;
2144  switch_media_handle_t *smh;
2145  int do_cng = 0;
2146 
2147  switch_assert(session);
2148 
2149  if (!(smh = session->media_handle)) {
2150  return SWITCH_STATUS_FALSE;
2151  }
2152 
2153  if (!smh->media_flags[SCMF_RUNNING]) {
2154  return SWITCH_STATUS_FALSE;
2155  }
2156 
2157  engine = &smh->engines[type];
2158 
2159  if (!engine->read_codec.implementation || !switch_core_codec_ready(&engine->read_codec)) {
2160  return SWITCH_STATUS_FALSE;
2161  }
2162 
2163  if (!switch_channel_up_nosig(session->channel) || !switch_rtp_ready(engine->rtp_session) || switch_channel_test_flag(session->channel, CF_NOT_READY)) {
2164  return SWITCH_STATUS_FALSE;
2165  }
2166 
2167  if (smh->read_mutex[type] && switch_mutex_trylock(smh->read_mutex[type]) != SWITCH_STATUS_SUCCESS) {
2168  /* return CNG, another thread is already reading */
2169  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s is already being read for %s\n",
2170  switch_channel_get_name(session->channel), type2str(type));
2171  return SWITCH_STATUS_INUSE;
2172  }
2173 
2174 
2175  engine->read_frame.datalen = 0;
2176  engine->read_frame.flags = SFF_NONE;
2177  engine->read_frame.m = SWITCH_FALSE;
2178  engine->read_frame.img = NULL;
2179 
2180  while (smh->media_flags[SCMF_RUNNING] && engine->read_frame.datalen == 0) {
2181  engine->read_frame.flags = SFF_NONE;
2182  status = switch_rtp_zerocopy_read_frame(engine->rtp_session, &engine->read_frame, flags);
2183  if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
2184  if (status == SWITCH_STATUS_TIMEOUT) {
2185 
2186  if (switch_channel_get_variable(session->channel, "execute_on_media_timeout")) {
2187  *frame = &engine->read_frame;
2188  switch_set_flag((*frame), SFF_CNG);
2189  (*frame)->datalen = engine->read_impl.encoded_bytes_per_packet;
2190  memset((*frame)->data, 0, (*frame)->datalen);
2191  switch_channel_execute_on(session->channel, "execute_on_media_timeout");
2193  }
2194 
2195 
2197  }
2198  goto end;
2199  }
2200 
2201  if (switch_channel_test_flag(session->channel, CF_LEG_HOLDING)) {
2202  status = SWITCH_STATUS_INUSE;
2203  goto end;
2204  }
2205 
2206  if (status == SWITCH_STATUS_BREAK) {
2207  goto end;
2208  }
2209 
2210  if (type == SWITCH_MEDIA_TYPE_VIDEO && engine->read_frame.m) {
2211 
2212  if (!smh->vid_started) {
2213  smh->vid_started = switch_epoch_time_now(NULL);
2214  }
2215  smh->vid_frames++;
2216 
2217  if ((smh->vid_frames % 15) == 0) {
2219  }
2220 
2221  if (smh->vid_frames == 1 || ((smh->vid_frames % 300) == 0)) {
2222  check_jb_sync(session);
2223  }
2224  }
2225 
2226 
2227  /* re-set codec if necessary */
2228  if (engine->reset_codec > 0) {
2229  const char *val;
2230  int rtp_timeout_sec = 0;
2231  int rtp_hold_timeout_sec = 0;
2232 
2233  engine->reset_codec = 0;
2234 
2235  if (switch_rtp_ready(engine->rtp_session)) {
2236  if (type == SWITCH_MEDIA_TYPE_VIDEO) {
2238  } else {
2240  *frame = NULL;
2242  }
2243  }
2244 
2245  if (type == SWITCH_MEDIA_TYPE_AUDIO && engine->read_impl.samples_per_second) {
2246  if ((val = switch_channel_get_variable(session->channel, "rtp_timeout_sec"))) {
2247  int v = atoi(val);
2248  if (v >= 0) {
2249  rtp_timeout_sec = v;
2250  }
2251  }
2252 
2253  if ((val = switch_channel_get_variable(session->channel, "rtp_hold_timeout_sec"))) {
2254  int v = atoi(val);
2255  if (v >= 0) {
2256  rtp_hold_timeout_sec = v;
2257  }
2258  }
2259 
2260  if (rtp_timeout_sec) {
2261  engine->max_missed_packets = (engine->read_impl.samples_per_second * rtp_timeout_sec) /
2262  engine->read_impl.samples_per_packet;
2263 
2265  if (!rtp_hold_timeout_sec) {
2266  rtp_hold_timeout_sec = rtp_timeout_sec * 10;
2267  }
2268  }
2269 
2270  if (rtp_hold_timeout_sec) {
2271  engine->max_missed_hold_packets = (engine->read_impl.samples_per_second * rtp_hold_timeout_sec) /
2272  engine->read_impl.samples_per_packet;
2273  }
2274  }
2275  }
2276 
2277  check_jb(session, NULL, 0, 0, SWITCH_FALSE);
2278 
2279  engine->check_frames = 0;
2280  engine->last_ts = 0;
2281  engine->last_seq = 0;
2282 
2283  do_cng = 1;
2284  }
2285 
2286  if (do_cng) {
2287  /* return CNG for now */
2288  *frame = &engine->read_frame;
2289  switch_set_flag((*frame), SFF_CNG);
2290  (*frame)->datalen = engine->read_impl.encoded_bytes_per_packet;
2291  memset((*frame)->data, 0, (*frame)->datalen);
2293  }
2294 
2295 
2296  /* Try to read an RTCP frame, if successful raise an event */
2297  if (switch_rtcp_zerocopy_read_frame(engine->rtp_session, &rtcp_frame) == SWITCH_STATUS_SUCCESS) {
2298  switch_event_t *event;
2299 
2301  char value[30];
2302  char header[50];
2303  int i;
2304 
2305  char *uuid = switch_core_session_get_uuid(session);
2306  if (uuid) {
2308  }
2309 
2310  snprintf(value, sizeof(value), "%.8x", rtcp_frame.ssrc);
2311  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SSRC", value);
2312 
2313  snprintf(value, sizeof(value), "%u", rtcp_frame.ntp_msw);
2314  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Most-Significant-Word", value);
2315 
2316  snprintf(value, sizeof(value), "%u", rtcp_frame.ntp_lsw);
2317  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Least-Significant-Word", value);
2318 
2319  snprintf(value, sizeof(value), "%u", rtcp_frame.timestamp);
2320  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Timestamp", value);
2321 
2322  snprintf(value, sizeof(value), "%u", rtcp_frame.packet_count);
2323  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sender-Packet-Count", value);
2324 
2325  snprintf(value, sizeof(value), "%u", rtcp_frame.octect_count);
2326  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Octect-Packet-Count", value);
2327 
2328  snprintf(value, sizeof(value), "%u", engine->read_frame.timestamp);
2329  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Last-RTP-Timestamp", value);
2330 
2331  snprintf(value, sizeof(value), "%u", engine->read_frame.rate);
2332  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Rate", value);
2333 
2334  snprintf(value, sizeof(value), "%" SWITCH_TIME_T_FMT, switch_time_now());
2335  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Capture-Time", value);
2336 
2337  // Add sources info
2338  for (i = 0; i < rtcp_frame.report_count; i++) {
2339  snprintf(header, sizeof(header), "Source%u-SSRC", i);
2340  snprintf(value, sizeof(value), "%.8x", rtcp_frame.reports[i].ssrc);
2341  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
2342  snprintf(header, sizeof(header), "Source%u-Fraction", i);
2343  snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].fraction);
2344  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
2345  snprintf(header, sizeof(header), "Source%u-Lost", i);
2346  snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].lost);
2347  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
2348  snprintf(header, sizeof(header), "Source%u-Loss-Avg", i);
2349  snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].loss_avg);
2350  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
2351  snprintf(header, sizeof(header), "Source%u-Highest-Sequence-Number-Received", i);
2352  snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].highest_sequence_number_received);
2353  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
2354  snprintf(header, sizeof(header), "Source%u-Jitter", i);
2355  snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].jitter);
2356  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
2357  snprintf(header, sizeof(header), "Source%u-LSR", i);
2358  snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].lsr);
2359  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
2360  snprintf(header, sizeof(header), "Source%u-DLSR", i);
2361  snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].dlsr);
2362  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
2363  }
2364 
2365  switch_event_fire(&event);
2366  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "Dispatched RTCP event\n");
2367  }
2368  }
2369 
2370  /* Fast PASS! */
2371  if (switch_test_flag((&engine->read_frame), SFF_PROXY_PACKET)) {
2372  *frame = &engine->read_frame;
2374  }
2375 
2376  if (switch_rtp_has_dtmf(engine->rtp_session)) {
2377  switch_dtmf_t dtmf = { 0 };
2378  switch_rtp_dequeue_dtmf(engine->rtp_session, &dtmf);
2379  switch_channel_queue_dtmf(session->channel, &dtmf);
2380  }
2381 
2382  if (engine->read_frame.datalen > 0) {
2383  uint32_t bytes = 0;
2384  int frames = 1;
2385 
2386  /* autofix timing */
2387  if (!switch_test_flag((&engine->read_frame), SFF_CNG)) {
2388  if (!engine->read_codec.implementation || !switch_core_codec_ready(&engine->read_codec)) {
2389  *frame = NULL;
2391  }
2392 
2393  /* check for timing issues */
2395 
2396 
2397  engine->check_frames++;
2398 
2399  if (!engine->read_impl.encoded_bytes_per_packet) {
2401  goto skip;
2402  }
2403 
2404  if (smh->media_flags[SCMF_AUTOFIX_TIMING] && (engine->read_frame.datalen % 10) == 0) {
2405 
2406  if (engine->last_ts && engine->read_frame.datalen != engine->read_impl.encoded_bytes_per_packet) {
2407 
2408  uint32_t codec_ms = (int) (engine->read_frame.timestamp -
2409  engine->last_ts) / (engine->read_impl.samples_per_second / 1000);
2410 
2411  if (engine->last_seq && (int) (engine->read_frame.seq - engine->last_seq) > 1) {
2412  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Correcting calculated ptime value from %d to %d to compensate for %d lost packet(s)\n", codec_ms, codec_ms / (int) (engine->read_frame.seq - engine->last_seq), (int) (engine->read_frame.seq - engine->last_seq - 1));
2413  codec_ms = codec_ms / (int) (engine->read_frame.seq - engine->last_seq);
2414  }
2415 
2416  if ((codec_ms % 10) != 0 || codec_ms > engine->read_impl.samples_per_packet * 10) {
2417  engine->last_ts = 0;
2418  engine->last_seq = 0;
2419  goto skip;
2420  }
2421 
2422 
2423  if (engine->last_codec_ms && engine->last_codec_ms == codec_ms) {
2424  engine->mismatch_count++;
2425  }
2426 
2427  engine->last_codec_ms = codec_ms;
2428 
2429  if (engine->mismatch_count > MAX_MISMATCH_FRAMES) {
2430  if (codec_ms != engine->cur_payload_map->codec_ms) {
2431 
2432  if (codec_ms > 120) { /* yeah right */
2434  "Your phone is trying to send timestamps that suggest an increment of %dms per packet\n"
2435  "That seems hard to believe so I am going to go on ahead and um ignore that, mmkay?\n",
2436  (int) codec_ms);
2438  goto skip;
2439  }
2440 
2441  engine->read_frame.datalen = 0;
2442 
2443  if (codec_ms != engine->cur_payload_map->codec_ms) {
2445  "Asynchronous PTIME not supported, changing our end from %d to %d\n",
2446  (int) engine->cur_payload_map->codec_ms,
2447  (int) codec_ms
2448  );
2449 
2450  switch_channel_set_variable_printf(session->channel, "rtp_h_X-Broken-PTIME", "Adv=%d;Sent=%d",
2451  (int) engine->cur_payload_map->codec_ms, (int) codec_ms);
2452 
2453  engine->cur_payload_map->codec_ms = codec_ms;
2454 
2455  /* mark to re-set codec */
2456  engine->reset_codec = 2;
2457  }
2458  }
2459  }
2460 
2461  } else {
2462  engine->mismatch_count = 0;
2463  }
2464 
2465  engine->last_ts = engine->read_frame.timestamp;
2466  engine->last_seq = engine->read_frame.seq;
2467 
2468 
2469  } else {
2470  engine->mismatch_count = 0;
2471  engine->last_ts = 0;
2472  engine->last_seq = 0;
2473  }
2474  }
2475 
2476  /* autofix payload type */
2477 
2478  if (!engine->reset_codec &&
2479  engine->codec_negotiated &&
2480  (!smh->mparams->cng_pt || engine->read_frame.payload != smh->mparams->cng_pt) &&
2481  (!smh->mparams->recv_te || engine->read_frame.payload != smh->mparams->recv_te) &&
2482  (!smh->mparams->te || engine->read_frame.payload != smh->mparams->te) &&
2483  engine->read_frame.payload != engine->cur_payload_map->recv_pt &&
2484  engine->read_frame.payload != engine->cur_payload_map->agreed_pt &&
2485  engine->read_frame.payload != engine->cur_payload_map->pt) {
2486 
2487  payload_map_t *pmap;
2488 
2489 
2491  "alternate payload received (received %d, expecting %d)\n",
2492  (int) engine->read_frame.payload, (int) engine->cur_payload_map->agreed_pt);
2493 
2494 
2495  /* search for payload type */
2497  for (pmap = engine->payload_map; pmap; pmap = pmap->next) {
2498  if (engine->read_frame.payload == pmap->recv_pt && pmap->negotiated) {
2499  engine->cur_payload_map = pmap;
2500  engine->cur_payload_map->current = 1;
2502  "Changing current codec to %s (payload type %d).\n",
2503  pmap->iananame, pmap->pt);
2504 
2505  /* mark to re-set codec */
2506  engine->reset_codec = 1;
2507  break;
2508  }
2509  }
2511 
2512  if (!engine->reset_codec) {
2514  "Could not change to payload type %d, ignoring...\n",
2515  (int) engine->read_frame.payload);
2516  }
2517  }
2518 
2519  skip:
2520 
2521  if ((bytes = engine->read_impl.encoded_bytes_per_packet)) {
2522  frames = (engine->read_frame.datalen / bytes);
2523  }
2524  engine->read_frame.samples = (int) (frames * engine->read_impl.samples_per_packet);
2525 
2526  if (engine->read_frame.datalen == 0) {
2527  continue;
2528  }
2529  }
2530  break;
2531  }
2532  }
2533 
2534  if (engine->read_frame.datalen == 0) {
2535  *frame = NULL;
2536  }
2537 
2538  *frame = &engine->read_frame;
2539 
2540  status = SWITCH_STATUS_SUCCESS;
2541 
2542  end:
2543 
2544  if (smh->read_mutex[type]) {
2545  switch_mutex_unlock(smh->read_mutex[type]);
2546  }
2547 
2548  return status;
2549 }
2550 
2551 //?
2553  switch_frame_t *frame, switch_io_flag_t flags, int stream_id, switch_media_type_t type)
2554 {
2556  int bytes = 0, samples = 0, frames = 0;
2557  switch_rtp_engine_t *engine;
2558  switch_media_handle_t *smh;
2559 
2560  switch_assert(session);
2561 
2562  if (!(smh = session->media_handle)) {
2563  return SWITCH_STATUS_FALSE;
2564  }
2565 
2566  if (!smh->media_flags[SCMF_RUNNING]) {
2567  return SWITCH_STATUS_FALSE;
2568  }
2569 
2570  engine = &smh->engines[type];
2571 
2572 
2573  if (switch_channel_test_flag(session->channel, CF_VIDEO_ONLY) && type == SWITCH_MEDIA_TYPE_AUDIO) {
2574  return SWITCH_STATUS_SUCCESS;
2575  }
2576 
2577  while (!(engine->read_codec.implementation && switch_rtp_ready(engine->rtp_session))) {
2578  if (switch_channel_ready(session->channel)) {
2579  switch_yield(10000);
2580  } else {
2581  return SWITCH_STATUS_GENERR;
2582  }
2583  }
2584 
2585  if (!engine->read_codec.implementation || !switch_core_codec_ready(&engine->read_codec)) {
2586  return SWITCH_STATUS_GENERR;
2587  }
2588 
2589 
2590  if (!engine->read_codec.implementation || !switch_core_codec_ready(&engine->read_codec)) {
2591  return SWITCH_STATUS_FALSE;
2592  }
2593 
2594  if (!switch_test_flag(frame, SFF_CNG) && !switch_test_flag(frame, SFF_PROXY_PACKET)) {
2595  if (engine->read_impl.encoded_bytes_per_packet) {
2596  bytes = engine->read_impl.encoded_bytes_per_packet;
2597  frames = ((int) frame->datalen / bytes);
2598  } else
2599  frames = 1;
2600 
2601  samples = frames * engine->read_impl.samples_per_packet;
2602  }
2603 
2604  engine->timestamp_send += samples;
2605 
2606  if (switch_rtp_write_frame(engine->rtp_session, frame) < 0) {
2607  status = SWITCH_STATUS_FALSE;
2608  }
2609 
2610 
2611  return status;
2612 }
2613 
2614 
2615 //?
2617 {
2619  switch_t38_options_t *local_t38_options = switch_channel_get_private(channel, "t38_options");
2620 
2621  switch_assert(t38_options);
2622 
2623  if (!local_t38_options) {
2624  local_t38_options = switch_core_session_alloc(session, sizeof(switch_t38_options_t));
2625  }
2626 
2627  local_t38_options->T38MaxBitRate = t38_options->T38MaxBitRate;
2628  local_t38_options->T38FaxFillBitRemoval = t38_options->T38FaxFillBitRemoval;
2629  local_t38_options->T38FaxTranscodingMMR = t38_options->T38FaxTranscodingMMR;
2630  local_t38_options->T38FaxTranscodingJBIG = t38_options->T38FaxTranscodingJBIG;
2631  local_t38_options->T38FaxRateManagement = switch_core_session_strdup(session, t38_options->T38FaxRateManagement);
2632  local_t38_options->T38FaxMaxBuffer = t38_options->T38FaxMaxBuffer;
2633  local_t38_options->T38FaxMaxDatagram = t38_options->T38FaxMaxDatagram;
2634  local_t38_options->T38FaxUdpEC = switch_core_session_strdup(session, t38_options->T38FaxUdpEC);
2635  local_t38_options->T38VendorInfo = switch_core_session_strdup(session, t38_options->T38VendorInfo);
2636  local_t38_options->remote_ip = switch_core_session_strdup(session, t38_options->remote_ip);
2637  local_t38_options->remote_port = t38_options->remote_port;
2638 
2639 
2640  switch_channel_set_private(channel, "t38_options", local_t38_options);
2641 
2642 }
2643 
2644 //?
2646 {
2647  int i = 0;
2648  switch_media_handle_t *smh;
2649 
2650  switch_assert(session);
2651 
2652  if (!(smh = session->media_handle) || !mimp) {
2653  return SWITCH_STATUS_FALSE;
2654  }
2655 
2656 
2657  for (i = 0; i < smh->mparams->num_codecs; i++) {
2658  const switch_codec_implementation_t *imp = smh->codecs[i];
2659 
2660  if (!strcasecmp(imp->iananame, mimp->iananame) && imp->actual_samples_per_second == mimp->actual_samples_per_second) {
2661  *pt = smh->ianacodes[i];
2662 
2663  return SWITCH_STATUS_SUCCESS;
2664  }
2665  }
2666 
2667  return SWITCH_STATUS_FALSE;
2668 }
2669 
2670 //#define get_int_value(_var, _set) { const char *__v = switch_channel_get_variable(session->channel, _var); if (__v) { _set = atol(__v);} }
2671 //?
2673 {
2674  switch_media_handle_t *smh;
2675  switch_rtp_engine_t *engine;
2676 
2677  switch_assert(session);
2678 
2679  if (!(smh = session->media_handle)) {
2680  return;
2681  }
2682 
2683  if (!(engine = &smh->engines[type])) return;
2684 
2685  switch(type) {
2687  break;
2688  case SWITCH_MEDIA_TYPE_VIDEO: {
2689  uint32_t system_bw = 0;
2690  const char *var = NULL, *bwv;
2691 
2692  if ((var = switch_channel_get_variable(session->channel, "video_try_hardware_encoder"))) {
2694  }
2695 
2696  if (!(bwv = switch_channel_get_variable(session->channel, "rtp_video_max_bandwidth"))) {
2697  bwv = switch_channel_get_variable(session->channel, "rtp_video_max_bandwidth_out");
2698  }
2699 
2700  if (!bwv) {
2701  bwv = "1mb";
2702  }
2703 
2704  system_bw = switch_parse_bandwidth_string(bwv);
2705 
2706  if (engine->sdp_bw && engine->sdp_bw <= system_bw) {
2707  engine->codec_settings.video.bandwidth = engine->sdp_bw;
2708  } else {
2709  engine->codec_settings.video.bandwidth = system_bw;
2710  }
2711  }
2712  break;
2713  default:
2714  break;
2715  }
2716 }
2717 
2718 
2719 //?
2721 {
2722  switch_media_handle_t *smh;
2723  switch_rtp_engine_t *v_engine;
2724 
2725  switch_assert(session);
2726 
2727  if (!(smh = session->media_handle)) {
2728  return SWITCH_STATUS_FALSE;
2729  }
2730  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
2731 
2732 
2733  if (!v_engine->codec_negotiated) {
2734  return SWITCH_STATUS_FALSE;
2735  }
2736 
2737  if (v_engine->read_codec.implementation && switch_core_codec_ready(&v_engine->read_codec)) {
2738  if (!force) {
2739  return SWITCH_STATUS_SUCCESS;
2740  }
2741  if (strcasecmp(v_engine->read_codec.implementation->iananame, v_engine->cur_payload_map->rm_encoding) ||
2743 
2744  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Changing Codec from %s to %s\n",
2748  } else {
2749  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Already using %s\n",
2750  v_engine->read_codec.implementation->iananame);
2751  return SWITCH_STATUS_SUCCESS;
2752  }
2753  }
2754 
2756 
2757  if (switch_core_codec_init(&v_engine->read_codec,
2758  v_engine->cur_payload_map->rm_encoding,
2759  v_engine->cur_payload_map->modname,
2760  v_engine->cur_payload_map->rm_fmtp,
2761  v_engine->cur_payload_map->rm_rate,
2762  0,
2763  1,
2766  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
2767  return SWITCH_STATUS_FALSE;
2768  } else {
2769  if (switch_core_codec_init(&v_engine->write_codec,
2770  v_engine->cur_payload_map->rm_encoding,
2771  v_engine->cur_payload_map->modname,
2772  v_engine->cur_payload_map->rm_fmtp,
2773  v_engine->cur_payload_map->rm_rate,
2774  0,
2775  1,
2778  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
2779  return SWITCH_STATUS_FALSE;
2780  } else {
2781  v_engine->read_frame.rate = v_engine->cur_payload_map->rm_rate;
2782  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set VIDEO Codec %s %s/%ld %d ms\n",
2783  switch_channel_get_name(session->channel), v_engine->cur_payload_map->rm_encoding,
2784  v_engine->cur_payload_map->rm_rate, v_engine->cur_payload_map->codec_ms);
2785  v_engine->read_frame.codec = &v_engine->read_codec;
2786 
2787  v_engine->write_codec.fmtp_out = switch_core_session_strdup(session, v_engine->write_codec.fmtp_out);
2788 
2789  v_engine->write_codec.agreed_pt = v_engine->cur_payload_map->agreed_pt;
2790  v_engine->read_codec.agreed_pt = v_engine->cur_payload_map->agreed_pt;
2793 
2794 
2795  switch_channel_set_variable_printf(session->channel, "rtp_last_video_codec_string", "%s@%dh",
2796  v_engine->cur_payload_map->rm_encoding, v_engine->cur_payload_map->rm_rate);
2797 
2798 
2799  if (switch_rtp_ready(v_engine->rtp_session)) {
2800  switch_core_session_message_t msg = { 0 };
2801 
2802  msg.from = __FILE__;
2804 
2806 
2807  //XX
2808 
2809  switch_core_session_receive_message(session, &msg);
2810 
2811 
2812  }
2813 
2814  switch_channel_set_variable(session->channel, "rtp_use_video_codec_name", v_engine->cur_payload_map->rm_encoding);
2815  switch_channel_set_variable(session->channel, "rtp_use_video_codec_fmtp", v_engine->cur_payload_map->rm_fmtp);
2816  switch_channel_set_variable_printf(session->channel, "rtp_use_video_codec_rate", "%d", v_engine->cur_payload_map->rm_rate);
2817  switch_channel_set_variable_printf(session->channel, "rtp_use_video_codec_ptime", "%d", 0);
2818  }
2819  }
2820  return SWITCH_STATUS_SUCCESS;
2821 }
2822 
2823 
2824 //?
2826 {
2828  int resetting = 0;
2829  switch_media_handle_t *smh;
2830  switch_rtp_engine_t *a_engine;
2831 
2832  switch_assert(session);
2833 
2834  if (!(smh = session->media_handle)) {
2835  return SWITCH_STATUS_FALSE;
2836  }
2837  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
2838 
2839  if (!a_engine->cur_payload_map->iananame) {
2840  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No audio codec available\n");
2842  }
2843 
2844  if (switch_core_codec_ready(&a_engine->read_codec)) {
2845  if (!force) {
2847  }
2848 
2849  if (strcasecmp(a_engine->read_impl.iananame, a_engine->cur_payload_map->iananame) ||
2850  (uint32_t) a_engine->read_impl.microseconds_per_packet / 1000 != a_engine->cur_payload_map->codec_ms ||
2851  a_engine->read_impl.samples_per_second != a_engine->cur_payload_map->rm_rate ) {
2852 
2853  if (session->read_resampler) {
2854  switch_mutex_lock(session->resample_mutex);
2855  switch_resample_destroy(&session->read_resampler);
2856  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating read resampler\n");
2857  switch_mutex_unlock(session->resample_mutex);
2858  }
2859 
2860  if (session->write_resampler) {
2861  switch_mutex_lock(session->resample_mutex);
2862  switch_resample_destroy(&session->write_resampler);
2863  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating write resampler\n");
2864  switch_mutex_unlock(session->resample_mutex);
2865  }
2866 
2867  switch_core_session_reset(session, 0, 0);
2868  switch_channel_audio_sync(session->channel);
2869 
2871  "Changing Codec from %s@%dms@%dhz to %s@%dms@%luhz\n",
2872  a_engine->read_impl.iananame,
2873  a_engine->read_impl.microseconds_per_packet / 1000,
2875 
2876  a_engine->cur_payload_map->iananame,
2877  a_engine->cur_payload_map->codec_ms,
2878  a_engine->cur_payload_map->rm_rate);
2879 
2883  resetting = 1;
2887  switch_channel_audio_sync(session->channel);
2888  } else {
2889  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Already using %s\n", a_engine->read_impl.iananame);
2891  }
2892  }
2893 
2894 
2896 
2898  a_engine->cur_payload_map->iananame,
2899  a_engine->cur_payload_map->modname,
2900  a_engine->cur_payload_map->rm_fmtp,
2901  a_engine->cur_payload_map->rm_rate,
2902  a_engine->cur_payload_map->codec_ms,
2903  a_engine->cur_payload_map->channels,
2904  a_engine->cur_payload_map->bitrate,
2907  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
2910  }
2911 
2912  a_engine->read_codec.session = session;
2913 
2914 
2916  a_engine->cur_payload_map->iananame,
2917  a_engine->cur_payload_map->modname,
2918  a_engine->cur_payload_map->rm_fmtp,
2919  a_engine->cur_payload_map->rm_rate,
2920  a_engine->cur_payload_map->codec_ms,
2921  a_engine->cur_payload_map->channels,
2922  a_engine->cur_payload_map->bitrate,
2925  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
2928  }
2929 
2930  a_engine->write_codec.session = session;
2931 
2932  if (switch_rtp_ready(a_engine->rtp_session)) {
2933  switch_channel_audio_sync(session->channel);
2934  switch_rtp_reset_jb(a_engine->rtp_session);
2935  }
2936 
2937  switch_channel_set_variable(session->channel, "rtp_use_codec_name", a_engine->cur_payload_map->iananame);
2938  switch_channel_set_variable(session->channel, "rtp_use_codec_fmtp", a_engine->cur_payload_map->rm_fmtp);
2939  switch_channel_set_variable_printf(session->channel, "rtp_use_codec_rate", "%d", a_engine->cur_payload_map->rm_rate);
2940  switch_channel_set_variable_printf(session->channel, "rtp_use_codec_ptime", "%d", a_engine->cur_payload_map->codec_ms);
2941  switch_channel_set_variable_printf(session->channel, "rtp_use_codec_channels", "%d", a_engine->cur_payload_map->channels);
2942  switch_channel_set_variable_printf(session->channel, "rtp_last_audio_codec_string", "%s@%dh@%di@%dc",
2943  a_engine->cur_payload_map->iananame, a_engine->cur_payload_map->rm_rate, a_engine->cur_payload_map->codec_ms, a_engine->cur_payload_map->channels);
2944 
2947 
2948  a_engine->read_impl = *a_engine->read_codec.implementation;
2949  a_engine->write_impl = *a_engine->write_codec.implementation;
2950 
2953 
2954  if (switch_rtp_ready(a_engine->rtp_session)) {
2956 
2962  }
2963  }
2964 
2965  a_engine->read_frame.rate = a_engine->cur_payload_map->rm_rate;
2966 
2967  if (!switch_core_codec_ready(&a_engine->read_codec)) {
2968  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
2970  }
2971 
2972  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set Codec %s %s/%ld %d ms %d samples %d bits %d channels\n",
2973  switch_channel_get_name(session->channel), a_engine->cur_payload_map->iananame, a_engine->cur_payload_map->rm_rate,
2974  a_engine->cur_payload_map->codec_ms,
2976  a_engine->read_frame.codec = &a_engine->read_codec;
2977  a_engine->read_frame.channels = a_engine->read_impl.number_of_channels;
2978  a_engine->write_codec.agreed_pt = a_engine->cur_payload_map->agreed_pt;
2979  a_engine->read_codec.agreed_pt = a_engine->cur_payload_map->agreed_pt;
2980 
2981  if (force != 2) {
2983  switch_core_session_set_write_codec(session, &a_engine->write_codec);
2984  }
2985 
2986  a_engine->cur_payload_map->fmtp_out = switch_core_session_strdup(session, a_engine->write_codec.fmtp_out);
2987 
2988  if (switch_rtp_ready(a_engine->rtp_session)) {
2990  }
2991 
2992  end:
2993 
2994  if (resetting) {
2997  }
2998 
2999  return status;
3000 }
3002 {
3003  switch_media_handle_t *smh;
3004  switch_rtp_engine_t *engine;
3005 
3006  switch_assert(session);
3007 
3008  if (!(smh = session->media_handle)) {
3009  return;
3010  }
3011 
3012  engine = &smh->engines[type];
3013 
3014  engine->ice_in.chosen[0] = 0;
3015  engine->ice_in.chosen[1] = 0;
3016  engine->ice_in.is_chosen[0] = 0;
3017  engine->ice_in.is_chosen[1] = 0;
3018  engine->ice_in.cand_idx[0] = 0;
3019  engine->ice_in.cand_idx[1] = 0;
3020  memset(&engine->ice_in, 0, sizeof(engine->ice_in));
3021  engine->remote_rtcp_port = 0;
3022 
3023  if (engine->rtp_session) {
3024  switch_rtp_reset(engine->rtp_session);
3025  }
3026 
3027 }
3028 
3029 //?
3031 {
3034 
3035 }
3036 
3038 {
3039  switch_rtp_engine_t *a_engine, *v_engine;
3040  switch_media_handle_t *smh;
3041 
3042  switch_assert(session);
3043 
3044  if (!(smh = session->media_handle)) {
3045  return;
3046  }
3047 
3048  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
3049  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
3050 
3051  if (a_engine->rtp_session) {
3053  }
3054 
3055  if (v_engine->rtp_session) {
3057  }
3058 }
3059 
3061 {
3062  switch_rtp_engine_t *a_engine, *v_engine;
3063  switch_media_handle_t *smh;
3064 
3065  switch_assert(session);
3066 
3067  if (!(smh = session->media_handle)) {
3068  return;
3069  }
3070 
3071  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
3072  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
3073 
3074  if (a_engine->rtp_session) {
3076  }
3077 
3078  if (v_engine->rtp_session) {
3080  }
3081 }
3082 
3083 
3084 //?
3086 {
3087  switch_media_handle_t *smh;
3088  switch_rtp_engine_t *engine;
3089 
3090  switch_assert(session);
3091 
3092  if (!(smh = session->media_handle)) {
3093  return SWITCH_STATUS_FALSE;
3094  }
3095 
3096  engine = &smh->engines[type];
3097 
3098  if (engine->cand_acl_count < SWITCH_MAX_CAND_ACL) {
3099  engine->cand_acl[engine->cand_acl_count++] = switch_core_session_strdup(session, acl_name);
3100  return SWITCH_STATUS_SUCCESS;
3101  }
3102 
3103  return SWITCH_STATUS_FALSE;
3104 }
3105 
3106 //?
3108 {
3109  switch_media_handle_t *smh;
3110 
3111  switch_assert(session);
3112 
3113  if (!(smh = session->media_handle)) {
3114  return;
3115  }
3116 
3117  if (smh->mparams->num_codecs && !switch_channel_test_flag(session->channel, CF_VIDEO_POSSIBLE)) {
3118  int i;
3119  smh->video_count = 0;
3120  for (i = 0; i < smh->mparams->num_codecs; i++) {
3121 
3122  if (smh->codecs[i]->codec_type == SWITCH_CODEC_TYPE_VIDEO) {
3123  if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_INBOUND &&
3124  switch_channel_test_flag(session->channel, CF_NOVIDEO)) {
3125  continue;
3126  }
3127  smh->video_count++;
3128  }
3129  }
3130  if (smh->video_count) {
3131  switch_channel_set_flag(session->channel, CF_VIDEO_POSSIBLE);
3132  }
3133  }
3134 }
3135 
3136 //?
3138 {
3139  switch_rtp_engine_t *engine = &smh->engines[type];
3140 
3141  if (!engine->local_dtls_fingerprint.len) {
3142  if (engine->remote_dtls_fingerprint.type) {
3144  } else {
3145  engine->local_dtls_fingerprint.type = "sha-256";
3146  }
3148  }
3149 }
3150 
3151 //?
3152 static int dtls_ok(switch_core_session_t *session)
3153 {
3154  return switch_channel_test_flag(session->channel, CF_DTLS_OK);
3155 }
3156 
3157 #ifdef _MSC_VER
3158 /* remove this if the break is removed from the following for loop which causes unreachable code loop */
3159 /* for (i = 0; i < engine->cand_acl_count; i++) { */
3160 #pragma warning(push)
3161 #pragma warning(disable:4702)
3162 #endif
3163 
3164 //?
3166 {
3167  switch_call_direction_t r = switch_channel_direction(session->channel);
3168 
3169  if (switch_channel_test_flag(session->channel, CF_3PCC)) {
3171  }
3172 
3173  if ((switch_channel_test_flag(session->channel, CF_REINVITE) || switch_channel_test_flag(session->channel, CF_RECOVERING))
3174  && switch_channel_test_flag(session->channel, CF_AVPF)) {
3176  }
3177 
3178  return r;
3179 }
3180 
3181 
3182 //?
3184 {
3186 
3187  if (zstr(ip)) {
3188  return status;
3189  }
3190 
3191  if (strchr(ip, ':')) {
3192  if (!zstr(smh->mparams->rtpip6)) {
3193  smh->mparams->rtpip = smh->mparams->rtpip6;
3194  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s choosing family v6\n",
3196  status = SWITCH_STATUS_SUCCESS;
3197  }
3198  } else {
3199  if (!zstr(smh->mparams->rtpip4)) {
3200  smh->mparams->rtpip = smh->mparams->rtpip4;
3201  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s choosing family v4\n",
3203  status = SWITCH_STATUS_SUCCESS;
3204  }
3205  }
3206 
3207  return status;
3208 }
3209 
3210 //?
3212 {
3214 
3215  if (zstr(ip)) {
3216  return r;
3217  }
3218 
3219  if (strchr(ip, ':')) {
3220  r = (switch_bool_t) !zstr(smh->mparams->rtpip6);
3221  } else {
3222  r = (switch_bool_t) !zstr(smh->mparams->rtpip4);
3223  }
3224 
3225  return r;
3226 }
3227 
3228 //?
3229 static switch_status_t check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_session_t *sdp, sdp_media_t *m)
3230 {
3231  switch_rtp_engine_t *engine = &smh->engines[type];
3232  sdp_attribute_t *attr;
3233  int i = 0, got_rtcp_mux = 0;
3234  const char *val;
3235  int ice_seen = 0, cid = 0, ai = 0;
3236 
3237  //if (engine->ice_in.is_chosen[0] && engine->ice_in.is_chosen[1]) {
3238  //return SWITCH_STATUS_SUCCESS;
3239  //}
3240 
3241  engine->ice_in.chosen[0] = 0;
3242  engine->ice_in.chosen[1] = 0;
3243  engine->ice_in.is_chosen[0] = 0;
3244  engine->ice_in.is_chosen[1] = 0;
3245  engine->ice_in.cand_idx[0] = 0;
3246  engine->ice_in.cand_idx[1] = 0;
3247  engine->remote_ssrc = 0;
3248 
3249  if (m) {
3250  attr = m->m_attributes;
3251  } else {
3252  attr = sdp->sdp_attributes;
3253  }
3254 
3255  for (; attr; attr = attr->a_next) {
3256  char *data;
3257  char *fields[15];
3258  int argc = 0, j = 0;
3259 
3260  if (zstr(attr->a_name)) {
3261  continue;
3262  }
3263 
3264  if (!strcasecmp(attr->a_name, "ice-ufrag")) {
3265  if (engine->ice_in.ufrag && !strcmp(engine->ice_in.ufrag, attr->a_value)) {
3266  engine->new_ice = 0;
3267  } else {
3268  engine->ice_in.ufrag = switch_core_session_strdup(smh->session, attr->a_value);
3269  engine->new_ice = 1;
3270  }
3271  ice_seen++;
3272  } else if (!strcasecmp(attr->a_name, "ice-pwd")) {
3273  if (!engine->ice_in.pwd || strcmp(engine->ice_in.pwd, attr->a_value)) {
3274  engine->ice_in.pwd = switch_core_session_strdup(smh->session, attr->a_value);
3275  }
3276  } else if (!strcasecmp(attr->a_name, "ice-options")) {
3277  engine->ice_in.options = switch_core_session_strdup(smh->session, attr->a_value);
3278  } else if (!strcasecmp(attr->a_name, "setup")) {
3279  if (!strcasecmp(attr->a_value, "passive") || !strcasecmp(attr->a_value, "actpass")) {
3280  if (!engine->dtls_controller) {
3281  engine->new_dtls = 1;
3282  engine->new_ice = 1;
3283  }
3284  engine->dtls_controller = 1;
3285  } else if (!strcasecmp(attr->a_value, "active")) {
3286  if (engine->dtls_controller) {
3287  engine->new_dtls = 1;
3288  engine->new_ice = 1;
3289  }
3290  engine->dtls_controller = 0;
3291  }
3292  } else if (switch_rtp_has_dtls() && dtls_ok(smh->session) && !strcasecmp(attr->a_name, "fingerprint") && !zstr(attr->a_value)) {
3293  char *p;
3294 
3295  engine->remote_dtls_fingerprint.type = switch_core_session_strdup(smh->session, attr->a_value);
3296 
3297  if ((p = strchr(engine->remote_dtls_fingerprint.type, ' '))) {
3298  *p++ = '\0';
3299 
3301  !zstr(engine->remote_dtls_fingerprint.str) && !strcmp(engine->remote_dtls_fingerprint.str, p)) {
3302  engine->new_dtls = 0;
3303  } else {
3305  engine->new_dtls = 1;
3306  engine->new_ice = 1;
3307  }
3308  }
3309 
3310 
3311  //if (strcasecmp(engine->remote_dtls_fingerprint.type, "sha-256")) {
3312  // switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_WARNING, "Unsupported fingerprint type.\n");
3313  //engine->local_dtls_fingerprint.type = NULL;
3314  //engine->remote_dtls_fingerprint.type = NULL;
3315  //}
3316 
3317 
3318  generate_local_fingerprint(smh, type);
3320 
3321  } else if (!engine->remote_ssrc && !strcasecmp(attr->a_name, "ssrc") && attr->a_value) {
3322  engine->remote_ssrc = (uint32_t) atol(attr->a_value);
3323 
3324  if (engine->rtp_session && engine->remote_ssrc) {
3326  }
3327 
3328 
3329 #ifdef RTCP_MUX
3330  } else if (!strcasecmp(attr->a_name, "rtcp-mux")) {
3331  engine->rtcp_mux = SWITCH_TRUE;
3333  got_rtcp_mux++;
3334 #endif
3335  } else if (!strcasecmp(attr->a_name, "candidate")) {
3337 
3338  if (!engine->cand_acl_count) {
3339  engine->cand_acl[engine->cand_acl_count++] = "wan.auto";
3340  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_WARNING, "NO candidate ACL defined, Defaulting to wan.auto\n");
3341  }
3342 
3343 
3344  if (!switch_stristr(" udp ", attr->a_value)) {
3345  continue;
3346  }
3347 
3348  data = switch_core_session_strdup(smh->session, attr->a_value);
3349 
3350  argc = switch_split(data, ' ', fields);
3351 
3352  cid = fields[1] ? atoi(fields[1]) - 1 : 0;
3353 
3354  if (argc < 5 || engine->ice_in.cand_idx[cid] >= MAX_CAND - 1) {
3356  continue;
3357  }
3358 
3359  for (i = 0; i < argc; i++) {
3360  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG1, "CAND %d [%s]\n", i, fields[i]);
3361  }
3362 
3363  if (!ip_possible(smh, fields[4])) {
3365  "Drop %s Candidate cid: %d proto: %s type: %s addr: %s:%s (no network path)\n",
3366  type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
3367  cid+1, fields[2], fields[7], fields[4], fields[5]);
3368  continue;
3369  } else {
3371  "Save %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n",
3372  type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
3373  cid+1, fields[2], fields[7], fields[4], fields[5]);
3374  }
3375 
3376 
3377  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].foundation = switch_core_session_strdup(smh->session, fields[0]);
3378  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].component_id = atoi(fields[1]);
3379  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].transport = switch_core_session_strdup(smh->session, fields[2]);
3380  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].priority = atol(fields[3]);
3381  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].con_addr = switch_core_session_strdup(smh->session, fields[4]);
3382  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].con_port = (switch_port_t)atoi(fields[5]);
3383 
3384  j = 6;
3385 
3386  while(j < argc && fields[j+1]) {
3387  if (!strcasecmp(fields[j], "typ")) {
3388  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].cand_type = switch_core_session_strdup(smh->session, fields[j+1]);
3389  } else if (!strcasecmp(fields[j], "raddr")) {
3390  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].raddr = switch_core_session_strdup(smh->session, fields[j+1]);
3391  } else if (!strcasecmp(fields[j], "rport")) {
3392  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].rport = (switch_port_t)atoi(fields[j+1]);
3393  } else if (!strcasecmp(fields[j], "generation")) {
3394  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].generation = switch_core_session_strdup(smh->session, fields[j+1]);
3395  }
3396 
3397  j += 2;
3398  }
3399 
3400  engine->ice_in.cand_idx[cid]++;
3401  }
3402  }
3403 
3404  if (!ice_seen) {
3405  return SWITCH_STATUS_SUCCESS;
3406  }
3407 
3408 
3409  for (cid = 0; cid < 2; cid++) {
3410  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Searching for %s candidate.\n", cid ? "rtcp" : "rtp");
3411 
3412  for (ai = 0; ai < engine->cand_acl_count; ai++) {
3413  for (i = 0; i < engine->ice_in.cand_idx[cid]; i++) {
3414  if (switch_check_network_list_ip(engine->ice_in.cands[i][cid].con_addr, engine->cand_acl[ai])) {
3416  "Choose %s candidate, index %d, %s:%d\n", cid ? "rtcp" : "rtp", i,
3417  engine->ice_in.cands[i][cid].con_addr, engine->ice_in.cands[i][cid].con_port);
3418 
3419  engine->ice_in.chosen[cid] = i;
3420  engine->ice_in.is_chosen[cid] = 1;
3421  engine->ice_in.cands[i][cid].ready++;
3422  ip_choose_family(smh, engine->ice_in.cands[i][cid].con_addr);
3423 
3424  if (cid == 0 && got_rtcp_mux && engine->ice_in.cand_idx[1] < MAX_CAND) {
3425 
3427  "Choose same candidate, index %d, for rtcp based on rtcp-mux attribute %s:%d\n", engine->ice_in.cand_idx[1],
3428  engine->ice_in.cands[i][cid].con_addr, engine->ice_in.cands[i][cid].con_port);
3429 
3430 
3431  engine->ice_in.cands[engine->ice_in.cand_idx[1]][1] = engine->ice_in.cands[i][0];
3432  engine->ice_in.chosen[1] = engine->ice_in.cand_idx[1];
3433  engine->ice_in.is_chosen[1] = 1;
3434  engine->ice_in.cand_idx[1]++;
3435 
3436  goto done_choosing;
3437  }
3438 
3439  goto next_cid;
3440  }
3441  }
3442  }
3443 
3444  next_cid:
3445 
3446  continue;
3447  }
3448 
3449  done_choosing:
3450 
3451 
3452  if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) {
3453  /* PUNT */
3454  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s no suitable candidates found.\n",
3456  return SWITCH_STATUS_FALSE;
3457  }
3458 
3459  for (i = 0; i < 2; i++) {
3460  if (engine->ice_in.cands[engine->ice_in.chosen[i]][i].ready) {
3461  if (zstr(engine->ice_in.ufrag) || zstr(engine->ice_in.pwd)) {
3462  engine->ice_in.cands[engine->ice_in.chosen[i]][i].ready = 0;
3463  }
3464  }
3465  }
3466 
3467 
3468  if (engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr && engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port) {
3469  char tmp[80] = "";
3470  engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(smh->session, (char *) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
3472  "setting remote %s ice addr to index %d %s:%d based on candidate\n", type2str(type), engine->ice_in.chosen[0],
3473  engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port);
3474  engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++;
3475 
3476  engine->remote_rtp_ice_port = (switch_port_t) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port;
3477  engine->remote_rtp_ice_addr = switch_core_session_strdup(smh->session, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
3478 
3479  engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(smh->session, (char *) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
3480  engine->cur_payload_map->remote_sdp_port = (switch_port_t) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port;
3481 
3482  if (!smh->mparams->remote_ip) {
3484  }
3485 
3486  switch_snprintf(tmp, sizeof(tmp), "%d", engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port);
3489  }
3490 
3491  if (engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port) {
3493  "Setting remote rtcp %s addr to %s:%d based on candidate\n", type2str(type),
3494  engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port);
3495  engine->remote_rtcp_ice_port = engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port;
3496  engine->remote_rtcp_ice_addr = switch_core_session_strdup(smh->session, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr);
3497 
3498  engine->remote_rtcp_port = engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port;
3499  }
3500 
3501 
3502  if (m && !got_rtcp_mux) {
3503  engine->rtcp_mux = -1;
3504  }
3505 
3507  if (switch_rtp_ready(engine->rtp_session) && engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready && engine->new_ice) {
3508  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "RE-Activating %s ICE\n", type2str(type));
3509 
3511  engine->ice_in.ufrag,
3512  engine->ice_out.ufrag,
3513  engine->ice_out.pwd,
3514  engine->ice_in.pwd,
3515  IPR_RTP,
3516 #ifdef GOOGLE_ICE
3518  NULL
3519 #else
3520  switch_ice_direction(smh->session) ==
3522  &engine->ice_in
3523 #endif
3524  );
3525 
3526 
3527  engine->new_ice = 0;
3528  }
3529 
3530 
3531  if (engine->rtp_session && ((val = switch_channel_get_variable(smh->session->channel,
3532  type == SWITCH_MEDIA_TYPE_VIDEO ?
3533  "rtcp_video_interval_msec" : "rtcp_audio_interval_msec"))
3534  || (val = type == SWITCH_MEDIA_TYPE_VIDEO ?
3536 
3537  switch_port_t remote_rtcp_port = engine->remote_rtcp_port;
3538 
3539  if (remote_rtcp_port) {
3540  if (!strcasecmp(val, "passthru")) {
3541  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "Activating %s RTCP PASSTHRU PORT %d\n",
3542  type2str(type), remote_rtcp_port);
3543  switch_rtp_activate_rtcp(engine->rtp_session, -1, remote_rtcp_port, engine->rtcp_mux > 0);
3544  } else {
3545  int interval = atoi(val);
3546  if (interval < 100 || interval > 500000) {
3548  "Invalid rtcp interval spec [%d] must be between 100 and 500000\n", interval);
3549  interval = 5000;
3550  }
3551 
3552  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "Activating %s RTCP PORT %d\n", type2str(type), remote_rtcp_port);
3553  switch_rtp_activate_rtcp(engine->rtp_session, interval, remote_rtcp_port, engine->rtcp_mux > 0);
3554  }
3555  }
3556  }
3557 
3558  if (engine->rtp_session && engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready) {
3559  if (engine->rtcp_mux > 0 && !strcmp(engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr)
3560  && engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port == engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port) {
3561  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "Skipping %s RTCP ICE (Same as RTP)\n", type2str(type));
3562  } else {
3563  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "Activating %s RTCP ICE\n", type2str(type));
3564 
3566  engine->ice_in.ufrag,
3567  engine->ice_out.ufrag,
3568  engine->ice_out.pwd,
3569  engine->ice_in.pwd,
3570  IPR_RTCP,
3571 #ifdef GOOGLE_ICE
3573  NULL
3574 #else
3575  switch_ice_direction(smh->session) ==
3577  &engine->ice_in
3578 #endif
3579  );
3580  }
3581 
3582  }
3583 
3584  }
3585 
3586  return ice_seen ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_BREAK;
3587 }
3588 #ifdef _MSC_VER
3589 #pragma warning(pop)
3590 #endif
3591 
3593 {
3594  switch_media_handle_t *smh;
3595 
3596  switch_assert(session);
3597 
3598  if (!(smh = session->media_handle)) {
3599  return;
3600  }
3601 
3602  switch_channel_set_flag(session->channel, CF_VERBOSE_SDP);
3603  switch_channel_set_flag(session->channel, CF_AVPF);
3604  switch_channel_set_flag(session->channel, CF_ICE);
3607 
3608 }
3609 
3610 #define MAX_MATCHES 30
3611 struct matches {
3613  sdp_rtpmap_t *map;
3614  int rate;
3616 };
3617 
3618 static void greedy_sort(switch_media_handle_t *smh, struct matches *matches, int m_idx, const switch_codec_implementation_t **codec_array, int total_codecs)
3619 {
3620  int j = 0, f = 0, g;
3621  struct matches mtmp[MAX_MATCHES] = { { 0 } };
3622  for(j = 0; j < m_idx; j++) {
3623  *&mtmp[j] = *&matches[j];
3624  }
3625  for (g = 0; g < smh->mparams->num_codecs && g < total_codecs; g++) {
3626  const switch_codec_implementation_t *imp = codec_array[g];
3627 
3628  for(j = 0; j < m_idx; j++) {
3629  if (mtmp[j].imp == imp) {
3630  *&matches[f++] = *&mtmp[j];
3631  }
3632  }
3633  }
3634 }
3635 
3636 static void clear_pmaps(switch_rtp_engine_t *engine)
3637 {
3638  payload_map_t *pmap;
3639 
3640  for (pmap = engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) {
3641  pmap->negotiated = 0;
3642  pmap->current = 0;
3643  }
3644 }
3645 
3646 //?
3647 SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *session, const char *r_sdp, uint8_t *proceed, switch_sdp_type_t sdp_type)
3648 {
3649  uint8_t match = 0;
3650  uint8_t vmatch = 0;
3651  switch_payload_t best_te = 0, cng_pt = 0;
3652  unsigned long best_te_rate = 8000, cng_rate = 8000;
3653  sdp_media_t *m;
3654  sdp_attribute_t *attr;
3655  int ptime = 0, dptime = 0, maxptime = 0, dmaxptime = 0;
3656  int sendonly = 0, recvonly = 0;
3657  int greedy = 0, x = 0, skip = 0;
3659  const char *val;
3660  const char *crypto = NULL;
3661  int got_crypto = 0, got_video_crypto = 0, got_audio = 0, saw_audio = 0, got_avp = 0, got_video_avp = 0, got_video_savp = 0, got_savp = 0, got_udptl = 0, got_webrtc = 0;
3662  int scrooge = 0;
3663  sdp_parser_t *parser = NULL;
3664  sdp_session_t *sdp;
3665  int reneg = 1;
3666  const switch_codec_implementation_t **codec_array;
3667  int total_codecs;
3668  switch_rtp_engine_t *a_engine, *v_engine;
3669  switch_media_handle_t *smh;
3670  uint32_t near_rate = 0;
3671  const switch_codec_implementation_t *mimp = NULL, *near_match = NULL;
3672  sdp_rtpmap_t *mmap = NULL, *near_map = NULL;
3673  struct matches matches[MAX_MATCHES] = { { 0 } };
3674  struct matches near_matches[MAX_MATCHES] = { { 0 } };
3675  int codec_ms = 0;
3676  uint32_t remote_codec_rate = 0, fmtp_remote_codec_rate = 0;
3677  const char *tmp;
3678  int m_idx = 0;
3679  int nm_idx = 0;
3680 
3681  switch_assert(session);
3682 
3683  if (!(smh = session->media_handle)) {
3684  return 0;
3685  }
3686 
3687  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
3688  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
3689 
3690  codec_array = smh->codecs;
3691  total_codecs = smh->mparams->num_codecs;
3692 
3693  if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
3694  return 0;
3695  }
3696 
3697  if (!(sdp = sdp_session(parser))) {
3698  sdp_parser_free(parser);
3699  return 0;
3700  }
3701 
3703 
3704  if (dtls_ok(session) && (tmp = switch_channel_get_variable(smh->session->channel, "webrtc_enable_dtls")) && switch_false(tmp)) {
3707  }
3708 
3709  v_engine->new_dtls = 1;
3710  v_engine->new_ice = 1;
3711  a_engine->new_dtls = 1;
3712  a_engine->new_ice = 1;
3713  a_engine->reject_avp = 0;
3714 
3716 
3717  clear_pmaps(a_engine);
3718  clear_pmaps(v_engine);
3719 
3720  if (proceed) *proceed = 1;
3721 
3724 
3725  if ((val = switch_channel_get_variable(channel, "rtp_codec_negotiation"))) {
3726  if (!strcasecmp(val, "generous")) {
3727  greedy = 0;
3728  scrooge = 0;
3729  } else if (!strcasecmp(val, "greedy")) {
3730  greedy = 1;
3731  scrooge = 0;
3732  } else if (!strcasecmp(val, "scrooge")) {
3733  scrooge = 1;
3734  greedy = 1;
3735  } else {
3736  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "rtp_codec_negotiation ignored invalid value : '%s' \n", val );
3737  }
3738  }
3739 
3740  if ((smh->origin = switch_core_session_strdup(session, (char *) sdp->sdp_origin->o_username))) {
3741 
3743 
3744  if (strstr(smh->origin, "CiscoSystemsSIP-GW-UserAgent")) {
3746  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Activate Buggy RFC2833 Mode!\n");
3747  }
3748  }
3749 
3751  if (strstr(smh->origin, "Sonus_UAC")) {
3754  "Hello,\nI see you have a Sonus!\n"
3755  "FYI, Sonus cannot follow the RFC on the proper way to send DTMF.\n"
3756  "Sadly, my creator had to spend several hours figuring this out so I thought you'd like to know that!\n"
3757  "Don't worry, DTMF will work but you may want to ask them to fix it......\n");
3758  }
3759  }
3760  }
3761 
3762  if ((val = switch_channel_get_variable(session->channel, "rtp_liberal_dtmf")) && switch_true(val)) {
3763  switch_channel_set_flag(session->channel, CF_LIBERAL_DTMF);
3764  }
3765 
3766  if (switch_stristr("T38FaxFillBitRemoval:", r_sdp) || switch_stristr("T38FaxTranscodingMMR:", r_sdp) ||
3767  switch_stristr("T38FaxTranscodingJBIG:", r_sdp)) {
3768  switch_channel_set_variable(session->channel, "t38_broken_boolean", "true");
3769  }
3770 
3771  switch_core_media_find_zrtp_hash(session, sdp);
3773 
3774  check_ice(smh, SWITCH_MEDIA_TYPE_AUDIO, sdp, NULL);
3775  check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, NULL);
3776 
3777  if ((sdp->sdp_connection && sdp->sdp_connection->c_address && !strcmp(sdp->sdp_connection->c_address, "0.0.0.0"))) {
3778  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "RFC2543 from March 1999 called; They want their 0.0.0.0 hold method back.....\n");
3779  sendonly = 2; /* global sendonly always wins */
3780  }
3781 
3782  for (m = sdp->sdp_media; m; m = m->m_next) {
3783  sdp_connection_t *connection;
3784  switch_core_session_t *other_session;
3785 
3786  if (!m->m_port) {
3787  continue;
3788  }
3789 
3790  if (m->m_type == sdp_media_audio) {
3791  saw_audio = 1;
3792  }
3793 
3794  ptime = dptime;
3795  maxptime = dmaxptime;
3796 
3797  if (m->m_proto == sdp_proto_extended_srtp || m->m_proto == sdp_proto_extended_rtp) {
3798  got_webrtc++;
3799  switch_core_session_set_ice(session);
3800  }
3801 
3802  if (m->m_proto_name && !strcasecmp(m->m_proto_name, "UDP/TLS/RTP/SAVPF")) {
3803  switch_channel_set_flag(session->channel, CF_AVPF_MOZ);
3804  }
3805 
3806  if (m->m_proto_name && !strcasecmp(m->m_proto_name, "UDP/RTP/AVPF")) {
3807  switch_channel_set_flag(session->channel, CF_AVPF_MOZ);
3808  }
3809 
3810  if (m->m_proto == sdp_proto_srtp || m->m_proto == sdp_proto_extended_srtp) {
3811  if (m->m_type == sdp_media_audio) {
3812  got_savp++;
3813  } else {
3814  got_video_savp++;
3815  }
3816  } else if (m->m_proto == sdp_proto_rtp) {
3817  if (m->m_type == sdp_media_audio) {
3818  got_avp++;
3819  } else {
3820  got_video_avp++;
3821  }
3822  } else if (m->m_proto == sdp_proto_udptl) {
3823  got_udptl++;
3824  }
3825 
3826  if (got_udptl && m->m_type == sdp_media_image && m->m_port) {
3827  switch_t38_options_t *t38_options = switch_core_media_process_udptl(session, sdp, m);
3828 
3829  if (switch_channel_test_app_flag_key("T38", session->channel, CF_APP_T38_NEGOTIATED)) {
3830  match = 1;
3831  goto done;
3832  }
3833 
3834  if (switch_true(switch_channel_get_variable(channel, "refuse_t38"))) {
3835  switch_channel_clear_app_flag_key("T38", session->channel, CF_APP_T38);
3836  match = 0;
3837  goto done;
3838  } else {
3839  const char *var = switch_channel_get_variable(channel, "t38_passthru");
3841 
3842 
3843  if (switch_channel_test_app_flag_key("T38", session->channel, CF_APP_T38)) {
3844  if (proceed) *proceed = 0;
3845  }
3846 
3847  if (var) {
3848  if (!(pass = switch_true(var))) {
3849  if (!strcasecmp(var, "once")) {
3850  pass = 2;
3851  }
3852  }
3853  }
3854 
3855  if ((pass == 2 && switch_channel_test_flag(smh->session->channel, CF_T38_PASSTHRU))
3856  || !switch_channel_test_flag(session->channel, CF_REINVITE) ||
3857 
3858  switch_channel_test_flag(session->channel, CF_PROXY_MODE) ||
3859  switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) ||
3860  !switch_rtp_ready(a_engine->rtp_session)) {
3861  pass = 0;
3862  }
3863 
3864  if (pass && switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
3865  switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
3867  char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
3868  switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
3869  char tmp[32] = "";
3870 
3871 
3872  if (!switch_channel_test_flag(other_channel, CF_ANSWERED)) {
3874  SWITCH_LOG_WARNING, "%s Error Passing T.38 to unanswered channel %s\n",
3875  switch_channel_get_name(session->channel), switch_channel_get_name(other_channel));
3876  switch_core_session_rwunlock(other_session);
3877 
3878  pass = 0;
3879  match = 0;
3880  goto done;
3881  }
3882 
3883 
3884  if (switch_true(switch_channel_get_variable(session->channel, "t38_broken_boolean")) &&
3885  switch_true(switch_channel_get_variable(session->channel, "t38_pass_broken_boolean"))) {
3886  switch_channel_set_variable(other_channel, "t38_broken_boolean", "true");
3887  }
3888 
3889  a_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, t38_options->remote_ip);
3890  a_engine->cur_payload_map->remote_sdp_port = t38_options->remote_port;
3891 
3892  if (remote_host && remote_port && !strcmp(remote_host, a_engine->cur_payload_map->remote_sdp_ip) && remote_port == a_engine->cur_payload_map->remote_sdp_port) {
3893  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n",
3894  switch_channel_get_name(session->channel));
3895  } else {
3896  const char *err = NULL;
3897 
3898  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n",
3899  switch_channel_get_name(session->channel),
3900  remote_host, remote_port, a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
3901 
3902  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
3905 
3908  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
3910  }
3911 
3913  }
3914 
3915 
3916 
3917  switch_core_media_copy_t38_options(t38_options, other_session);
3918 
3921 
3922  msg = switch_core_session_alloc(other_session, sizeof(*msg));
3924  msg->from = __FILE__;
3925  msg->string_arg = switch_core_session_strdup(other_session, r_sdp);
3926  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing T38 req to other leg.\n%s\n", r_sdp);
3927  switch_core_session_queue_message(other_session, msg);
3928  switch_core_session_rwunlock(other_session);
3929  }
3930  }
3931 
3932 
3933  /* do nothing here, mod_fax will trigger a response (if it's listening =/) */
3934  match = 1;
3935  goto done;
3936  } else if (m->m_type == sdp_media_audio && m->m_port && got_audio && got_savp) {
3937  a_engine->reject_avp = 1;
3938  } else if (m->m_type == sdp_media_audio && m->m_port && !got_audio) {
3939  sdp_rtpmap_t *map;
3940  int ice = 0;
3941 
3942  nm_idx = 0;
3943  m_idx = 0;
3944  memset(matches, 0, sizeof(matches[0]) * MAX_MATCHES);
3945  memset(near_matches, 0, sizeof(near_matches[0]) * MAX_MATCHES);
3946 
3947  if (!sendonly && (m->m_mode == sdp_sendonly || m->m_mode == sdp_inactive)) {
3948  sendonly = 1;
3949  }
3950 
3951  if (!sendonly && m->m_connections && m->m_connections->c_address && !strcmp(m->m_connections->c_address, "0.0.0.0")) {
3952  sendonly = 1;
3953  }
3954 
3955 
3956  a_engine->rmode = sdp_media_flow(m->m_mode);
3957 
3958  if (sdp_type == SDP_TYPE_REQUEST) {
3959  switch(a_engine->rmode) {
3961  switch_channel_set_variable(smh->session->channel, "audio_media_flow", "sendonly");
3962  a_engine->smode = SWITCH_MEDIA_FLOW_SENDONLY;
3963  break;
3965  switch_channel_set_variable(smh->session->channel, "audio_media_flow", "recvonly");
3966  a_engine->smode = SWITCH_MEDIA_FLOW_RECVONLY;
3967  break;
3968  default:
3969  switch_channel_set_variable(smh->session->channel, "audio_media_flow", "sendrecv");
3970  a_engine->smode = SWITCH_MEDIA_FLOW_SENDRECV;
3971  break;
3972  }
3973  }
3974 
3975  for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) {
3976  if (zstr(attr->a_name)) {
3977  continue;
3978  }
3979 
3980 
3981  if (!strncasecmp(attr->a_name, "ice", 3)) {
3982  ice++;
3983  } else if (sendonly < 2 && !strcasecmp(attr->a_name, "sendonly")) {
3984  sendonly = 1;
3985  switch_channel_set_variable(session->channel, "media_audio_mode", "recvonly");
3986  } else if (sendonly < 2 && !strcasecmp(attr->a_name, "inactive")) {
3987  sendonly = 1;
3988  switch_channel_set_variable(session->channel, "media_audio_mode", "inactive");
3989  } else if (!strcasecmp(attr->a_name, "recvonly")) {
3990  switch_channel_set_variable(session->channel, "media_audio_mode", "sendonly");
3991  recvonly = 1;
3992 
3993  if (switch_rtp_ready(a_engine->rtp_session)) {
3995  a_engine->max_missed_hold_packets = 0;
3996  a_engine->max_missed_packets = 0;
3997  } else {
3998  switch_channel_set_variable(session->channel, "rtp_timeout_sec", "0");
3999  switch_channel_set_variable(session->channel, "rtp_hold_timeout_sec", "0");
4000  }
4001  } else if (sendonly < 2 && !strcasecmp(attr->a_name, "sendrecv")) {
4002  sendonly = 0;
4003  } else if (!strcasecmp(attr->a_name, "ptime")) {
4004  ptime = dptime = atoi(attr->a_value);
4005  } else if (!strcasecmp(attr->a_name, "maxptime")) {
4006  maxptime = dmaxptime = atoi(attr->a_value);
4007  }
4008  }
4009 
4010  if (sendonly == 2 && ice) {
4011  sendonly = 0;
4012  }
4013 
4014 
4015  if (sendonly != 1 && recvonly != 1) {
4016  switch_channel_set_variable(session->channel, "media_audio_mode", NULL);
4017  }
4018 
4019  if (sdp_type == SDP_TYPE_RESPONSE) {
4020  if (sendonly) {
4021  a_engine->smode = sdp_media_flow(sdp_sendonly);
4022  } else if (recvonly) {
4023  a_engine->smode = sdp_media_flow(sdp_recvonly);
4024  }
4025  }
4026 
4027 
4029  || ((val = switch_channel_get_variable(session->channel, "rtp_disable_hold"))
4030  && switch_true(val)))
4031  && !smh->mparams->hold_laps) {
4032  smh->mparams->hold_laps++;
4033  if (switch_core_media_toggle_hold(session, sendonly)) {
4035  if ((val = switch_channel_get_variable(session->channel, "rtp_renegotiate_codec_on_hold"))) {
4036  reneg = switch_true(val);
4037  }
4038  }
4039  }
4040 
4041  if (reneg) {
4043 
4044  if ((val = switch_channel_get_variable(session->channel, "rtp_renegotiate_codec_on_reinvite"))) {
4045  reneg = switch_true(val);
4046  }
4047  }
4048 
4049  if (session->bugs) {
4051  "Session is connected to a media bug. "
4052  "Re-Negotiation implicitly disabled.\n");
4053  reneg = 0;
4054  }
4055 
4056  if (switch_channel_test_flag(session->channel, CF_RECOVERING)) {
4057  reneg = 0;
4058  }
4059 
4060  if (sdp_type == SDP_TYPE_RESPONSE && smh->num_negotiated_codecs) {
4061  /* response to re-invite or update, only negotiated codecs are valid */
4062  reneg = 0;
4063  }
4064 
4065 
4066  if (!reneg && smh->num_negotiated_codecs) {
4067  codec_array = smh->negotiated_codecs;
4068  total_codecs = smh->num_negotiated_codecs;
4069  } else if (reneg) {
4070  smh->mparams->num_codecs = 0;
4072  codec_array = smh->codecs;
4073  total_codecs = smh->mparams->num_codecs;
4074  }
4075 
4076 
4077  if (switch_rtp_has_dtls() && dtls_ok(session)) {
4078  for (attr = m->m_attributes; attr; attr = attr->a_next) {
4079 
4080  if (!strcasecmp(attr->a_name, "fingerprint") && !zstr(attr->a_value)) {
4081  got_crypto = 1;
4082  }
4083  }
4084  }
4085 
4086  for (attr = m->m_attributes; attr; attr = attr->a_next) {
4087 
4088  if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value) {
4089  switch_channel_set_variable(session->channel, "rtp_remote_audio_rtcp_port", attr->a_value);
4090  a_engine->remote_rtcp_port = (switch_port_t)atoi(attr->a_value);
4091  if (!smh->mparams->rtcp_audio_interval_msec) {
4093  }
4094  } else if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
4095  ptime = atoi(attr->a_value);
4096  } else if (!strcasecmp(attr->a_name, "maxptime") && attr->a_value) {
4097  maxptime = atoi(attr->a_value);
4098  } else if (got_crypto < 1 && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) {
4099  int crypto_tag;
4100 
4101  if (!(smh->mparams->ndlb & SM_NDLB_ALLOW_CRYPTO_IN_AVP) &&
4102  !switch_true(switch_channel_get_variable(session->channel, "rtp_allow_crypto_in_avp"))) {
4103  if (m->m_proto != sdp_proto_srtp && !got_webrtc) {
4104  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "a=crypto in RTP/AVP, refer to rfc3711\n");
4105  match = 0;
4106  goto done;
4107  }
4108  }
4109 
4110  crypto = attr->a_value;
4111  crypto_tag = atoi(crypto);
4112  got_crypto = switch_core_session_check_incoming_crypto(session,
4113  "rtp_has_crypto", SWITCH_MEDIA_TYPE_AUDIO, crypto, crypto_tag, sdp_type);
4114 
4115  }
4116  }
4117 
4118  if (got_crypto == -1 && got_savp && !got_avp && !got_webrtc) {
4119  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Declining invite with only SAVP because secure media is administratively disabled\n");
4120  match = 0;
4121  break;
4122  }
4123 
4124  connection = sdp->sdp_connection;
4125  if (m->m_connections) {
4126  connection = m->m_connections;
4127  }
4128 
4129  if (!connection) {
4130  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n");
4131  match = 0;
4132  break;
4133  }
4134 
4135  x = 0;
4136 
4137  for (map = m->m_rtpmaps; map; map = map->rm_next) {
4138  int32_t i;
4139  const char *rm_encoding;
4140  uint32_t map_bit_rate = 0;
4141  switch_codec_fmtp_t codec_fmtp = { 0 };
4142  int map_channels = map->rm_params ? atoi(map->rm_params) : 1;
4143 
4144  if (!(rm_encoding = map->rm_encoding)) {
4145  rm_encoding = "";
4146  }
4147 
4148 
4149  if (!strcasecmp(rm_encoding, "telephone-event")) {
4150  if (!best_te || map->rm_rate == a_engine->cur_payload_map->rm_rate) {
4151  best_te = (switch_payload_t) map->rm_pt;
4152  best_te_rate = map->rm_rate;
4153  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set telephone-event payload to %u@%ld\n", best_te, best_te_rate);
4154  }
4155  continue;
4156  }
4157 
4158  if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && !cng_pt && !strcasecmp(rm_encoding, "CN")) {
4159  cng_pt = (switch_payload_t) map->rm_pt;
4160  if (a_engine->rtp_session) {
4161  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u\n", cng_pt);
4162  switch_rtp_set_cng_pt(a_engine->rtp_session, smh->mparams->cng_pt);
4163  }
4164  continue;
4165  }
4166 
4167 
4168  if (x++ < skip) {
4169  continue;
4170  }
4171 
4172  if (match) {
4173  continue;
4174  }
4175 
4176  codec_ms = ptime;
4177 
4178  if (switch_channel_get_variable(session->channel, "rtp_h_X-Broken-PTIME") && a_engine->read_impl.microseconds_per_packet) {
4179  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Overwriting ptime from a known broken endpoint with the currently used value of %d ms\n", a_engine->read_impl.microseconds_per_packet / 1000);
4180  codec_ms = a_engine->read_impl.microseconds_per_packet / 1000;
4181  }
4182 
4183  if (maxptime && (!codec_ms || codec_ms > maxptime)) {
4184  codec_ms = maxptime;
4185  }
4186 
4187  if (!codec_ms) {
4188  codec_ms = switch_default_ptime(rm_encoding, map->rm_pt);
4189  }
4190 
4191  map_bit_rate = switch_known_bitrate((switch_payload_t)map->rm_pt);
4192 
4193  if (!ptime && !strcasecmp(map->rm_encoding, "g723")) {
4194  codec_ms = 30;
4195  }
4196 
4197  remote_codec_rate = map->rm_rate;
4198  fmtp_remote_codec_rate = 0;
4199  memset(&codec_fmtp, 0, sizeof(codec_fmtp));
4200 
4201  if (zstr(map->rm_fmtp)) {
4202  if (!strcasecmp(map->rm_encoding, "ilbc")) {
4203  codec_ms = 30;
4204  map_bit_rate = 13330;
4205  } else if (!strcasecmp(map->rm_encoding, "isac")) {
4206  codec_ms = 30;
4207  map_bit_rate = 32000;
4208  }
4209  } else {
4210  if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) {
4211  if (codec_fmtp.bits_per_second) {
4212  map_bit_rate = codec_fmtp.bits_per_second;
4213  }
4214  if (codec_fmtp.microseconds_per_packet) {
4215  codec_ms = (codec_fmtp.microseconds_per_packet / 1000);
4216  }
4217  if (codec_fmtp.actual_samples_per_second) {
4218  fmtp_remote_codec_rate = codec_fmtp.actual_samples_per_second;
4219  }
4220  if (codec_fmtp.stereo) {
4221  map_channels = 2;
4222  } else if (!strcasecmp(map->rm_encoding, "opus")) {
4223  map_channels = 1;
4224  }
4225  }
4226  }
4227 
4228  for (i = 0; i < smh->mparams->num_codecs && i < total_codecs; i++) {
4229  const switch_codec_implementation_t *imp = codec_array[i];
4230  uint32_t bit_rate = imp->bits_per_second;
4231  uint32_t codec_rate = imp->samples_per_second;
4232 
4233  if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
4234  continue;
4235  }
4236 
4237  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio Codec Compare [%s:%d:%u:%d:%u:%d]/[%s:%d:%u:%d:%u:%d]\n",
4238  rm_encoding, map->rm_pt, (int) remote_codec_rate, codec_ms, map_bit_rate, map_channels,
4239  imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate, imp->number_of_channels);
4240  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
4241  match = (map->rm_pt == imp->ianacode) ? 1 : 0;
4242  } else {
4243  match = (!strcasecmp(rm_encoding, imp->iananame) &&
4244  ((map->rm_pt < 96 && imp->ianacode < 96) || (map->rm_pt > 95 && imp->ianacode > 95)) &&
4245  (remote_codec_rate == codec_rate || fmtp_remote_codec_rate == imp->actual_samples_per_second)) ? 1 : 0;
4246  if (fmtp_remote_codec_rate) {
4247  remote_codec_rate = fmtp_remote_codec_rate;
4248  }
4249  }
4250 
4251  if (match && bit_rate && map_bit_rate && map_bit_rate != bit_rate && strcasecmp(map->rm_encoding, "ilbc") &&
4252  strcasecmp(map->rm_encoding, "isac")) {
4253  /* if a bit rate is specified and doesn't match, this is not a codec match, except for ILBC */
4254  match = 0;
4255  }
4256 
4257  if (match && remote_codec_rate && codec_rate && remote_codec_rate != codec_rate && (!strcasecmp(map->rm_encoding, "pcma") ||
4258  !strcasecmp(map->rm_encoding, "pcmu"))) {
4259  /* if the sampling rate is specified and doesn't match, this is not a codec match for G.711 */
4260  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sampling rates have to match for G.711\n");
4261  match = 0;
4262  }
4263 
4264  if (match) {
4265  if (scrooge) {
4267  "Bah HUMBUG! Sticking with %s@%uh@%ui\n",
4268  imp->iananame, imp->samples_per_second, imp->microseconds_per_packet / 1000);
4269  } else if ((ptime && codec_ms && codec_ms * 1000 != imp->microseconds_per_packet) || remote_codec_rate != codec_rate) {
4270  /* ptime does not match */
4271  match = 0;
4272 
4274  "Audio Codec Compare [%s:%d:%u:%d:%u:%d] is saved as a near-match\n",
4275  imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate, imp->number_of_channels);
4276 
4277  near_matches[nm_idx].codec_idx = i;
4278  near_matches[nm_idx].rate = remote_codec_rate;
4279  near_matches[nm_idx].imp = imp;
4280  near_matches[nm_idx].map = map;
4281  nm_idx++;
4282 
4283  continue;
4284  }
4285 
4286  matches[m_idx].codec_idx = i;
4287  matches[m_idx].rate = codec_rate;
4288  matches[m_idx].imp = imp;
4289  matches[m_idx].map = map;
4290  m_idx++;
4291 
4293  "Audio Codec Compare [%s:%d:%u:%d:%u:%d] ++++ is saved as a match\n",
4294  imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate, imp->number_of_channels);
4295 
4296  if (m_idx >= MAX_MATCHES) {
4297  break;
4298  }
4299 
4300  match = 0;
4301  }
4302  }
4303 
4304  if (m_idx >= MAX_MATCHES) {
4305  break;
4306  }
4307  }
4308 
4309  if (smh->crypto_mode == CRYPTO_MODE_MANDATORY && got_crypto < 1) {
4310  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Crypto not negotiated but required.\n");
4311  match = 0;
4312  m_idx = nm_idx = 0;
4313  }
4314 
4315 
4316  if (!m_idx && nm_idx) {
4317  int j;
4318 
4319  for(j = 0; j < nm_idx; j++) {
4320  const switch_codec_implementation_t *search[1];
4321  char *prefs[1];
4322  char tmp[80];
4323  int num;
4324  const switch_codec_implementation_t *timp = NULL;
4325 
4326  near_rate = near_matches[j].rate;
4327  near_match = near_matches[j].imp;
4328  near_map = near_matches[j].map;
4329 
4330  switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui%dc", near_match->iananame, near_rate ? near_rate : near_match->samples_per_second,
4331  codec_ms, near_match->number_of_channels);
4332 
4333  prefs[0] = tmp;
4334  num = switch_loadable_module_get_codecs_sorted(search, 1, prefs, 1);
4335 
4336  if (num) {
4337  timp = search[0];
4338  } else {
4339  timp = near_match;
4340  }
4341 
4342  if (!maxptime || timp->microseconds_per_packet / 1000 <= maxptime) {
4343  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Substituting codec %s@%ui@%uh@%dc\n",
4345  match = 1;
4346 
4347  matches[m_idx].codec_idx = near_matches[j].codec_idx;
4348  matches[m_idx].rate = near_rate;
4349  matches[m_idx].imp = timp;
4350  matches[m_idx].map = near_map;
4351  m_idx++;
4352 
4353  break;
4354  }
4355  }
4356  }
4357 
4358  if (m_idx) {
4359  int j;
4360 
4361  if (greedy) { /* sort in favor of mine */
4362  greedy_sort(smh, matches, m_idx, codec_array, total_codecs);
4363  }
4364 
4365  match = 1;
4366  a_engine->codec_negotiated = 1;
4367  smh->num_negotiated_codecs = 0;
4368 
4369  for(j = 0; j < m_idx; j++) {
4372  matches[j].map->rm_encoding,
4373  matches[j].imp->modname,
4374  matches[j].map->rm_fmtp,
4375  sdp_type,
4376  matches[j].map->rm_pt,
4377  matches[j].imp->samples_per_second,
4378  matches[j].imp->microseconds_per_packet / 1000,
4379  matches[j].imp->number_of_channels,
4380  SWITCH_TRUE);
4381 
4382  mimp = matches[j].imp;
4383  mmap = matches[j].map;
4384 
4385  if (j == 0) {
4386  a_engine->cur_payload_map = pmap;
4387  a_engine->cur_payload_map->current = 1;
4388  if (a_engine->rtp_session) {
4389  switch_rtp_set_default_payload(a_engine->rtp_session, pmap->pt);
4390  }
4391  }
4392 
4393  pmap->rm_encoding = switch_core_session_strdup(session, (char *) mmap->rm_encoding);
4394  pmap->iananame = switch_core_session_strdup(session, (char *) mimp->iananame);
4395  pmap->recv_pt = (switch_payload_t) mmap->rm_pt;
4396  pmap->rm_rate = mimp->samples_per_second;
4397  pmap->adv_rm_rate = mimp->samples_per_second;
4398  if (strcasecmp(mimp->iananame, "g722")) {
4399  pmap->rm_rate = mimp->actual_samples_per_second;
4400  }
4401  pmap->codec_ms = mimp->microseconds_per_packet / 1000;
4402  pmap->bitrate = mimp->bits_per_second;
4403  pmap->channels = mmap->rm_params ? atoi(mmap->rm_params) : 1;
4404 
4405  if (!strcasecmp((char *) mmap->rm_encoding, "opus")) {
4406  if (pmap->channels == 1) {
4407  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid SDP for opus. Don't ask.. but it needs a /2\n");
4408  pmap->adv_channels = 1;
4409  } else {
4410  pmap->adv_channels = 2; /* IKR ???*/
4411  }
4412  if (!zstr((char *) mmap->rm_fmtp) && switch_stristr("stereo=1", (char *) mmap->rm_fmtp)) {
4413  pmap->channels = 2;
4414  } else {
4415  pmap->channels = 1;
4416  }
4417  } else {
4418  pmap->adv_channels = pmap->channels;
4419  }
4420 
4421  pmap->remote_sdp_ip = switch_core_session_strdup(session, (char *) connection->c_address);
4422  pmap->remote_sdp_port = (switch_port_t) m->m_port;
4423  pmap->rm_fmtp = switch_core_session_strdup(session, (char *) mmap->rm_fmtp);
4424 
4425  pmap->agreed_pt = (switch_payload_t) mmap->rm_pt;
4426  smh->negotiated_codecs[smh->num_negotiated_codecs++] = mimp;
4427  pmap->recv_pt = (switch_payload_t)mmap->rm_pt;
4428 
4429  }
4430  }
4431 
4432  if (match) {
4433  char tmp[50];
4434  //const char *mirror = switch_channel_get_variable(session->channel, "rtp_mirror_remote_audio_codec_payload");
4435 
4436 
4437  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
4440 
4441 
4442  if (a_engine->cur_payload_map->pt == smh->mparams->te) {
4443  switch_payload_t pl = 0;
4444  payload_map_t *pmap;
4445 
4447  for (pmap = a_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
4448  if (pmap->pt > pl) {
4449  pl = pmap->pt;
4450  }
4451  }
4453 
4454  smh->mparams->te = (switch_payload_t) ++pl;
4455  }
4456 
4457 
4458 
4459 #if 0
4460  if (!switch_true(mirror) &&
4463  switch_core_media_get_offered_pt(session, matches[0].imp, &a_engine->cur_payload_map->recv_pt);
4464  }
4465 #endif
4466 
4467  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->recv_pt);
4468  switch_channel_set_variable(session->channel, "rtp_audio_recv_pt", tmp);
4469 
4470  if (a_engine->read_impl.iananame) {
4471  if (!switch_core_codec_ready(&a_engine->read_codec) ||
4472  ((strcasecmp(matches[0].imp->iananame, a_engine->read_impl.iananame) ||
4473  matches[0].imp->microseconds_per_packet != a_engine->read_impl.microseconds_per_packet ||
4474  matches[0].imp->samples_per_second != a_engine->read_impl.samples_per_second
4475  ))) {
4476 
4477  a_engine->reset_codec = 1;
4478  }
4479  } else if (switch_core_media_set_codec(session, 0, smh->mparams->codec_flags) != SWITCH_STATUS_SUCCESS) {
4480  match = 0;
4481  }
4482 
4483  if (match) {
4484  if (check_ice(smh, SWITCH_MEDIA_TYPE_AUDIO, sdp, m) == SWITCH_STATUS_FALSE) {
4485  match = 0;
4486  got_audio = 0;
4487  } else {
4488  got_audio = 1;
4489  }
4490  }
4491 
4492  }
4493 
4494  for (map = m->m_rtpmaps; map; map = map->rm_next) {
4495  const char *rm_encoding;
4496 
4497  if (!(rm_encoding = map->rm_encoding)) {
4498  rm_encoding = "";
4499  }
4500 
4501  if (!strcasecmp(rm_encoding, "telephone-event")) {
4502  if (!best_te || map->rm_rate == a_engine->cur_payload_map->adv_rm_rate) {
4503  best_te = (switch_payload_t) map->rm_pt;
4504  best_te_rate = map->rm_rate;
4505  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set telephone-event payload to %u@%lu\n", best_te, best_te_rate);
4506  }
4507  continue;
4508  }
4509 
4510  if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && !strcasecmp(rm_encoding, "CN")) {
4511 
4512  if (!cng_pt || map->rm_rate == a_engine->cur_payload_map->adv_rm_rate) {
4513  cng_pt = (switch_payload_t) map->rm_pt;
4514  cng_rate = map->rm_rate;
4515 
4516  if (a_engine->rtp_session) {
4517  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u@%lu\n", cng_pt, cng_rate);
4518  switch_rtp_set_cng_pt(a_engine->rtp_session, smh->mparams->cng_pt);
4519  }
4520  }
4521  continue;
4522  }
4523  }
4524 
4525  if (cng_rate != a_engine->cur_payload_map->adv_rm_rate) {
4526  cng_rate = 8000;
4527  }
4528 
4529  if (best_te_rate != a_engine->cur_payload_map->adv_rm_rate) {
4530  best_te_rate = 8000;
4531  }
4532 
4533  if (!best_te && (switch_media_handle_test_media_flag(smh, SCMF_LIBERAL_DTMF) ||
4534  switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF))) {
4536  "No 2833 in SDP. Liberal DTMF mode adding %d as telephone-event.\n", smh->mparams->te);
4537  best_te = smh->mparams->te;
4538  }
4539 
4540  if (best_te) {
4541  smh->mparams->te_rate = best_te_rate;
4542 
4543  if (smh->mparams->dtmf_type == DTMF_AUTO) {
4544  if (sdp_type == SDP_TYPE_REQUEST) {
4545  smh->mparams->te = smh->mparams->recv_te = (switch_payload_t) best_te;
4546  switch_channel_set_variable(session->channel, "dtmf_type", "rfc2833");
4547  smh->mparams->dtmf_type = DTMF_2833;
4548  } else {
4549  smh->mparams->te = (switch_payload_t) best_te;
4550  switch_channel_set_variable(session->channel, "dtmf_type", "rfc2833");
4551  smh->mparams->dtmf_type = DTMF_2833;
4552  }
4553  }
4554 
4555  if (a_engine->rtp_session) {
4557  switch_channel_set_variable_printf(session->channel, "rtp_2833_send_payload", "%d", smh->mparams->te);
4559  switch_channel_set_variable_printf(session->channel, "rtp_2833_recv_payload", "%d", smh->mparams->recv_te);
4560  }
4561 
4562 
4563  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Set 2833 dtmf send payload to %u recv payload to %u\n",
4564  switch_channel_get_name(session->channel), smh->mparams->te, smh->mparams->recv_te);
4565 
4566 
4567  } else {
4568  /* by default, use SIP INFO if 2833 is not in the SDP */
4569  if (!switch_false(switch_channel_get_variable(channel, "rtp_info_when_no_2833"))) {
4570  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No 2833 in SDP. Disable 2833 dtmf and switch to INFO\n");
4571  switch_channel_set_variable(session->channel, "dtmf_type", "info");
4572  smh->mparams->dtmf_type = DTMF_INFO;
4573  smh->mparams->recv_te = smh->mparams->te = 0;
4574  } else {
4575  switch_channel_set_variable(session->channel, "dtmf_type", "none");
4576  smh->mparams->dtmf_type = DTMF_NONE;
4577  smh->mparams->recv_te = smh->mparams->te = 0;
4578  }
4579  }
4580 
4581  } else if (m->m_type == sdp_media_video && m->m_port) {
4582  sdp_rtpmap_t *map;
4583  const char *rm_encoding;
4584  const switch_codec_implementation_t *mimp = NULL;
4585  int i;
4586 
4587  vmatch = 0;
4588  nm_idx = 0;
4589  m_idx = 0;
4590  memset(matches, 0, sizeof(matches[0]) * MAX_MATCHES);
4591  memset(near_matches, 0, sizeof(near_matches[0]) * MAX_MATCHES);
4592 
4593  switch_channel_set_variable(session->channel, "video_possible", "true");
4594  switch_channel_set_flag(session->channel, CF_VIDEO_SDP_RECVD);
4595 
4596  connection = sdp->sdp_connection;
4597  if (m->m_connections) {
4598  connection = m->m_connections;
4599  }
4600 
4601  if (!connection) {
4602  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n");
4603  match = 0;
4604  break;
4605  }
4606 
4607  v_engine->rmode = sdp_media_flow(m->m_mode);
4608 
4609  if (sdp_type == SDP_TYPE_REQUEST) {
4610  sdp_bandwidth_t *bw;
4611  int tias = 0;
4612 
4613  for (bw = m->m_bandwidths; bw; bw = bw->b_next) {
4614  if (bw->b_modifier == sdp_bw_as && !tias) {
4615  v_engine->sdp_bw = bw->b_value / 1024;
4616  } else if (bw->b_modifier == sdp_bw_tias) {
4617  tias = 1;
4618  v_engine->sdp_bw = bw->b_value / 1024;
4619  }
4620  }
4621 
4622  switch(v_engine->rmode) {
4624  switch_channel_set_variable(smh->session->channel, "video_media_flow", "sendonly");
4625  v_engine->smode = SWITCH_MEDIA_FLOW_SENDONLY;
4627  break;
4629  switch_channel_set_variable(smh->session->channel, "video_media_flow", "recvonly");
4630  v_engine->smode = SWITCH_MEDIA_FLOW_RECVONLY;
4631  break;
4632  default:
4633  switch_channel_set_variable(smh->session->channel, "video_media_flow", "sendrecv");
4634  v_engine->smode = SWITCH_MEDIA_FLOW_SENDRECV;
4635  break;
4636  }
4637  }
4638 
4639 
4640  for (map = m->m_rtpmaps; map; map = map->rm_next) {
4641 
4642  if (switch_rtp_has_dtls() && dtls_ok(session)) {
4643  for (attr = m->m_attributes; attr; attr = attr->a_next) {
4644  if (!strcasecmp(attr->a_name, "fingerprint") && !zstr(attr->a_value)) {
4645  got_video_crypto = 1;
4646  }
4647  }
4648  }
4649 
4650  for (attr = m->m_attributes; attr; attr = attr->a_next) {
4651  if (!strcasecmp(attr->a_name, "framerate") && attr->a_value) {
4652  //framerate = atoi(attr->a_value);
4653  } else if (!strcasecmp(attr->a_name, "rtcp-fb")) {
4654  if (!zstr(attr->a_value)) {
4655  if (switch_stristr("fir", attr->a_value)) {
4656  v_engine->fir++;
4657  }
4658 
4659  if (switch_stristr("pli", attr->a_value)) {
4660  v_engine->pli++;
4661  }
4662 
4663  if (switch_stristr("nack", attr->a_value)) {
4664  v_engine->nack++;
4665  }
4666 
4667  if (switch_stristr("tmmbr", attr->a_value)) {
4668  v_engine->tmmbr++;
4669  }
4670 
4672  }
4673  } else if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value && !strcmp(attr->a_value, "1")) {
4674  switch_channel_set_variable(session->channel, "rtp_remote_video_rtcp_port", attr->a_value);
4675  v_engine->remote_rtcp_port = (switch_port_t)atoi(attr->a_value);
4676  if (!smh->mparams->rtcp_video_interval_msec) {
4678  }
4679  } else if (!got_video_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) {
4680  int crypto_tag;
4681 
4682  if (!(smh->mparams->ndlb & SM_NDLB_ALLOW_CRYPTO_IN_AVP) &&
4683  !switch_true(switch_channel_get_variable(session->channel, "rtp_allow_crypto_in_avp"))) {
4684  if (m->m_proto != sdp_proto_srtp && !got_webrtc) {
4685  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "a=crypto in RTP/AVP, refer to rfc3711\n");
4686  match = 0;
4687  goto done;
4688  }
4689  }
4690 
4691  crypto = attr->a_value;
4692  crypto_tag = atoi(crypto);
4693 
4694  got_video_crypto = switch_core_session_check_incoming_crypto(session,
4695  "rtp_has_video_crypto",
4696  SWITCH_MEDIA_TYPE_VIDEO, crypto, crypto_tag, sdp_type);
4697 
4698  }
4699  }
4700 
4701  if (!(rm_encoding = map->rm_encoding)) {
4702  rm_encoding = "";
4703  }
4704 
4705  for (i = 0; i < total_codecs; i++) {
4706  const switch_codec_implementation_t *imp = codec_array[i];
4707 
4708  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
4709  continue;
4710  }
4711 
4712  if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_INBOUND &&
4713  switch_channel_test_flag(session->channel, CF_NOVIDEO)) {
4714  continue;
4715  }
4716 
4717  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video Codec Compare [%s:%d]/[%s:%d]\n",
4718  rm_encoding, map->rm_pt, imp->iananame, imp->ianacode);
4719  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
4720  vmatch = (map->rm_pt == imp->ianacode) ? 1 : 0;
4721  } else {
4722  vmatch = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1;
4723  }
4724 
4725  if (vmatch && (map->rm_rate == imp->samples_per_second)) {
4726  matches[m_idx].imp = imp;
4727  matches[m_idx].map = map;
4728 
4729  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video Codec Compare [%s:%d] +++ is saved as a match\n",
4730  imp->iananame, imp->ianacode);
4731  m_idx++;
4732  }
4733 
4734  vmatch = 0;
4735  }
4736  }
4737 
4738  if (smh->crypto_mode == CRYPTO_MODE_MANDATORY && got_video_crypto < 1) {
4739  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Crypto not negotiated but required.\n");
4740  vmatch = 0;
4741  m_idx = 0;
4742  }
4743 
4744  if (m_idx) {
4745  char tmp[50];
4746  //const char *mirror = switch_channel_get_variable(session->channel, "rtp_mirror_remote_video_codec_payload");
4747  int j = 0;
4748 
4749  if (greedy) { /* sort in favor of mine */
4750  greedy_sort(smh, matches, m_idx, codec_array, total_codecs);
4751  }
4752 
4753  vmatch = 1;
4754  v_engine->codec_negotiated = 1;
4755 
4756  for(j = 0; j < m_idx; j++) {
4759  matches[j].map->rm_encoding,
4760  matches[j].imp->modname,
4761  matches[j].map->rm_fmtp,
4762  sdp_type,
4763  matches[j].map->rm_pt,
4764  matches[j].imp->samples_per_second,
4765  matches[j].imp->microseconds_per_packet / 1000,
4766  matches[j].imp->number_of_channels,
4767  SWITCH_TRUE);
4768 
4769  if (j == 0) {
4770  v_engine->cur_payload_map = pmap;
4771  v_engine->cur_payload_map->current = 1;
4772  if (v_engine->rtp_session) {
4773  switch_rtp_set_default_payload(v_engine->rtp_session, pmap->pt);
4774  }
4775  }
4776 
4777  mimp = matches[j].imp;
4778  map = matches[j].map;
4779 
4780  pmap->rm_encoding = switch_core_session_strdup(session, (char *) map->rm_encoding);
4781  pmap->recv_pt = (switch_payload_t) map->rm_pt;
4782  pmap->rm_rate = map->rm_rate;
4783  pmap->codec_ms = mimp->microseconds_per_packet / 1000;
4784 
4785 
4786  pmap->remote_sdp_ip = switch_core_session_strdup(session, (char *) connection->c_address);
4787  pmap->remote_sdp_port = (switch_port_t) m->m_port;
4788 
4789  pmap->rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp);
4790 
4791  pmap->agreed_pt = (switch_payload_t) map->rm_pt;
4792 
4793  smh->negotiated_codecs[smh->num_negotiated_codecs++] = mimp;
4794 
4795 #if 0
4796  if (j == 0 && (!switch_true(mirror) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND)) {
4797  switch_core_media_get_offered_pt(session, mimp, &pmap->recv_pt);
4798  }
4799 #endif
4800  }
4801 
4802 
4803 
4804  switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->cur_payload_map->remote_sdp_port);
4807  switch_channel_set_variable(session->channel, "rtp_video_fmtp", v_engine->cur_payload_map->rm_fmtp);
4808  switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->cur_payload_map->agreed_pt);
4809  switch_channel_set_variable(session->channel, "rtp_video_pt", tmp);
4811  switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->cur_payload_map->recv_pt);
4812  switch_channel_set_variable(session->channel, "rtp_video_recv_pt", tmp);
4813 
4814  if (switch_core_codec_ready(&v_engine->read_codec) && strcasecmp(matches[0].imp->iananame, v_engine->read_codec.implementation->iananame)) {
4815  v_engine->reset_codec = 1;
4816  }
4817 
4819  if (check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, m) == SWITCH_STATUS_FALSE) {
4820  vmatch = 0;
4821  }
4822  }
4823  }
4824  }
4825  }
4826 
4827  if (!saw_audio) {
4828  payload_map_t *pmap;
4829 
4830  a_engine->rmode = SWITCH_MEDIA_FLOW_DISABLED;
4831  switch_channel_set_variable(smh->session->channel, "audio_media_flow", "inactive");
4832 
4833 
4834  pmap = switch_core_media_add_payload_map(session,
4836  "L16",
4837  NULL,
4838  NULL,
4840  97,
4841  8000,
4842  20,
4843  1,
4844  SWITCH_TRUE);
4845 
4846  pmap->remote_sdp_ip = "127.0.0.1";
4847  pmap->remote_sdp_port = 9999;
4848  pmap->agreed_pt = 97;
4849  pmap->recv_pt = 97;
4850  pmap->codec_ms = 20;
4851  a_engine->cur_payload_map = pmap;
4853  }
4854 
4855 
4856  if (!match && vmatch) match = 1;
4857 
4858  done:
4859 
4860  if (parser) {
4861  sdp_parser_free(parser);
4862  }
4863 
4864  smh->mparams->cng_pt = cng_pt;
4865  smh->mparams->cng_rate = cng_rate;
4866 
4867  return match;
4868 }
4869 
4870 //?
4871 
4873 {
4874  int changed = 0;
4875  switch_rtp_engine_t *a_engine, *v_engine;
4876  switch_media_handle_t *smh;
4877  switch_core_session_t *b_session = NULL;
4878  switch_channel_t *b_channel = NULL;
4879 
4880  switch_assert(session);
4881 
4882  if (!(smh = session->media_handle)) {
4883  return 0;
4884  }
4885 
4886  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
4887  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
4888 
4889 
4890  if (switch_core_session_get_partner(session, &b_session) == SWITCH_STATUS_SUCCESS) {
4891  b_channel = switch_core_session_get_channel(b_session);
4892  }
4893 
4894  if (sendonly && switch_channel_test_flag(session->channel, CF_ANSWERED)) {
4895  if (!switch_channel_test_flag(session->channel, CF_PROTO_HOLD)) {
4896  const char *stream;
4897  const char *msg = "hold";
4898  const char *info;
4899 
4900  if ((switch_channel_test_flag(session->channel, CF_SLA_BARGE) || switch_channel_test_flag(session->channel, CF_SLA_BARGING)) &&
4901  (!b_channel || switch_channel_test_flag(b_channel, CF_EVENT_LOCK_PRI))) {
4902  switch_channel_mark_hold(session->channel, sendonly);
4903  switch_channel_set_flag(session->channel, CF_PROTO_HOLD);
4904  changed = 0;
4905  goto end;
4906  }
4907 
4908  info = switch_channel_get_variable(session->channel, "presence_call_info");
4909 
4910  if (info) {
4911  if (switch_stristr("private", info)) {
4912  msg = "hold-private";
4913  }
4914  }
4915 
4916  if (a_engine->rtp_session) {
4918  }
4919 
4920  if (v_engine->rtp_session) {
4922  }
4923 
4924  switch_channel_set_flag(session->channel, CF_PROTO_HOLD);
4925  switch_channel_mark_hold(session->channel, SWITCH_TRUE);
4926  switch_channel_presence(session->channel, "unknown", msg, NULL);
4927  changed = 1;
4928 
4929  if (a_engine->max_missed_hold_packets && a_engine->rtp_session) {
4931  }
4932 
4933  if (!(stream = switch_channel_get_hold_music(session->channel))) {
4934  stream = "local_stream://moh";
4935  }
4936 
4937 
4938  if (stream && strcasecmp(stream, "silence") && (!b_channel || !switch_channel_test_flag(b_channel, CF_EVENT_LOCK_PRI))) {
4939  if (!strcasecmp(stream, "indicate_hold")) {
4940  switch_channel_set_flag(session->channel, CF_SUSPEND);
4941  switch_channel_set_flag(session->channel, CF_HOLD);
4943  } else {
4946  switch_yield(250000);
4947  }
4948  }
4949 
4950  }
4951  } else {
4952  if (switch_channel_test_flag(session->channel, CF_HOLD_LOCK)) {
4953  switch_channel_set_flag(session->channel, CF_PROTO_HOLD);
4954  switch_channel_mark_hold(session->channel, SWITCH_TRUE);
4955 
4956  if (a_engine->rtp_session) {
4958  }
4959 
4960  if (v_engine->rtp_session) {
4962  }
4963 
4964  changed = 1;
4965  }
4966 
4967  switch_channel_clear_flag(session->channel, CF_HOLD_LOCK);
4968 
4969  if (switch_channel_test_flag(session->channel, CF_PROTO_HOLD)) {
4970  int media_on_hold_a = switch_true(switch_channel_get_variable_dup(session->channel, "bypass_media_resume_on_hold", SWITCH_FALSE, -1));
4971  int media_on_hold_b = 0;
4972  int bypass_after_hold_a = 0;
4973  int bypass_after_hold_b = 0;
4974 
4975  if (media_on_hold_a) {
4976  bypass_after_hold_a = switch_true(switch_channel_get_variable_dup(session->channel, "bypass_media_after_hold", SWITCH_FALSE, -1));
4977  }
4978 
4979  if (b_channel) {
4980  if ((media_on_hold_b = switch_true(switch_channel_get_variable_dup(b_channel, "bypass_media_resume_on_hold", SWITCH_FALSE, -1)))) {
4981  bypass_after_hold_b = switch_true(switch_channel_get_variable_dup(b_channel, "bypass_media_after_hold", SWITCH_FALSE, -1));
4982  }
4983  }
4984 
4985  switch_yield(250000);
4986 
4987  if (b_channel && (switch_channel_test_flag(session->channel, CF_BYPASS_MEDIA_AFTER_HOLD) ||
4988  switch_channel_test_flag(b_channel, CF_BYPASS_MEDIA_AFTER_HOLD) || bypass_after_hold_a || bypass_after_hold_b)) {
4989  /* try to stay out from media stream */
4991  }
4992 
4993  if (a_engine->max_missed_packets && a_engine->rtp_session) {
4996  }
4997 
4998  if (b_channel) {
4999  if (switch_channel_test_flag(session->channel, CF_HOLD)) {
5000  switch_ivr_unhold(b_session);
5001  switch_channel_clear_flag(session->channel, CF_SUSPEND);
5002  switch_channel_clear_flag(session->channel, CF_HOLD);
5003  } else {
5004  switch_channel_stop_broadcast(b_channel);
5005  switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
5006  }
5007  }
5008 
5010 
5011  switch_channel_clear_flag(session->channel, CF_PROTO_HOLD);
5012  switch_channel_mark_hold(session->channel, SWITCH_FALSE);
5013  switch_channel_presence(session->channel, "unknown", "unhold", NULL);
5014 
5015  if (a_engine->rtp_session) {
5017  }
5018 
5019  if (v_engine->rtp_session) {
5021  }
5022 
5023  changed = 1;
5024  }
5025  }
5026 
5027 
5028  end:
5029 
5030  if (b_session) {
5031  switch_core_session_rwunlock(b_session);
5032  }
5033 
5034 
5035  return changed;
5036 }
5037 
5038 
5040 {
5041  switch_media_handle_t *smh;
5042  switch_rtp_engine_t *v_engine;
5044 
5045  switch_assert(session);
5046 
5047  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
5048  return NULL;
5049  }
5050 
5051  if (!(smh = session->media_handle)) {
5052  return NULL;
5053  }
5054 
5055  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
5056 
5057 
5058 
5059  if (rw == SWITCH_RW_READ) {
5061  fh = smh->video_read_fh;
5063  } else {
5065  fh = smh->video_write_fh;
5067  }
5068 
5069 
5070 
5071  return fh;
5072 }
5073 
5074 
5076 {
5077  switch_core_session_t *session = (switch_core_session_t *) obj;
5078  switch_media_handle_t *smh;
5079  unsigned char *buf = NULL;
5080  switch_frame_t fr = { 0 };
5081  switch_rtp_engine_t *v_engine;
5083  switch_timer_t timer = { 0 };
5084  int fps;
5086 
5088  return NULL;
5089  }
5090 
5091  if (!(smh = session->media_handle)) {
5092  return NULL;
5093  }
5094 
5096 
5097  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
5098 
5099 
5100  buf = switch_core_session_alloc(session, buflen);
5101  fr.packet = buf;
5102  fr.packetlen = buflen;
5103  fr.data = buf + 12;
5104  fr.buflen = buflen - 12;
5106 
5107 
5108  if (smh->video_write_fh->mm.source_fps) {
5109  fps = (int) smh->video_write_fh->mm.source_fps;
5110  } else {
5111  fps = video_globals.fps;
5112  }
5113 
5114  if (!fps) {
5115  fps = 15;
5116  }
5117 
5118 
5119  switch_core_timer_init(&timer, "soft", (int)(1000 / fps) , 1, switch_core_session_get_pool(session));
5120 
5121  while (smh->video_write_thread_running > 0 &&
5124 
5125  switch_core_timer_next(&timer);
5127 
5128  if (smh->video_write_fh->mm.source_fps && smh->video_write_fh->mm.source_fps != fps) {
5129  switch_core_timer_destroy(&timer);
5130  switch_core_timer_init(&timer, "soft", (int)(1000 / fps) , 1, switch_core_session_get_pool(session));
5131  }
5132 
5134  wstatus = switch_core_file_read_video(smh->video_write_fh, &fr, read_flags);
5135 
5136  if (wstatus == SWITCH_STATUS_SUCCESS) {
5138  switch_img_free(&fr.img);
5139  } else if (wstatus != SWITCH_STATUS_BREAK && wstatus != SWITCH_STATUS_IGNORE) {
5141  }
5142  }
5144  }
5145 
5146  switch_core_timer_destroy(&timer);
5147 
5149 
5151  smh->video_write_thread_running = 0;
5152 
5153  return NULL;
5154 }
5155 
5157 {
5158  switch_media_handle_t *smh;
5159  switch_rtp_engine_t *v_engine;
5160 
5161  switch_assert(session);
5162 
5163  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
5164  return SWITCH_STATUS_FALSE;
5165  }
5166 
5167  if (!(smh = session->media_handle)) {
5168  return SWITCH_STATUS_FALSE;
5169  }
5170 
5171  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
5172 
5173  if (rw == SWITCH_RW_READ) {
5175  } else {
5177  }
5178 
5179  return SWITCH_STATUS_SUCCESS;
5180 
5181 }
5182 
5184 {
5185  switch_media_handle_t *smh;
5186  switch_rtp_engine_t *v_engine;
5187 
5188  switch_assert(session);
5189 
5190  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
5191  return SWITCH_STATUS_FALSE;
5192  }
5193 
5194  if (!(smh = session->media_handle)) {
5195  return SWITCH_STATUS_FALSE;
5196  }
5197 
5198  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
5199 
5200  if (rw == SWITCH_RW_READ) {
5202  } else {
5204  }
5205 
5206  return SWITCH_STATUS_SUCCESS;
5207 }
5208 
5210 {
5211  switch_media_handle_t *smh;
5212  switch_rtp_engine_t *v_engine;
5213 
5214  switch_assert(session);
5215 
5216  if (!(smh = session->media_handle)) {
5217  return SWITCH_STATUS_FALSE;
5218  }
5219 
5220  if (!smh->video_read_fh && !smh->video_read_fh && !switch_channel_test_flag(session->channel, CF_VIDEO)) {
5221  return SWITCH_STATUS_FALSE;
5222  }
5223 
5224  if (fh && !switch_core_file_has_video(fh, SWITCH_TRUE)) {
5225  return SWITCH_STATUS_FALSE;
5226  }
5227 
5228  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
5229 
5231 
5232  //if (!v_engine->media_thread) {
5233  // return SWITCH_STATUS_FALSE;
5234  //}
5235 
5236 
5237 
5238  if (rw == SWITCH_RW_READ) {
5240 
5241  if (fh && smh->video_read_fh) {
5242  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "File is already open\n");
5244  return SWITCH_STATUS_FALSE;
5245  }
5246 
5247 
5248  if (fh) {
5251  } else if (smh->video_read_fh) {
5254  }
5255 
5256  if (!fh) {
5258  }
5259 
5260  smh->video_read_fh = fh;
5261 
5263 
5264  } else {
5266  if (fh && smh->video_write_fh) {
5267  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "File is already open\n");
5268  smh->video_write_fh = fh;
5270  return SWITCH_STATUS_SUCCESS;
5271  }
5272 
5273  if (fh) {
5275  } else {
5277  }
5278 
5280 
5281  if (fh) {
5282  switch_threadattr_t *thd_attr = NULL;
5283 
5286  smh->video_write_thread_running = 1;
5288  }
5289 
5290  if (!fh && smh->video_write_thread) {
5291  switch_status_t st;
5292 
5293  if (smh->video_write_thread_running > 0) {
5294  smh->video_write_thread_running = -1;
5295  }
5299  smh->video_write_thread = NULL;
5300  }
5301 
5302  smh->video_write_fh = fh;
5303 
5305  }
5306 
5307  if (!fh) switch_channel_video_sync(session->channel);
5308 
5310 
5311 
5312  return SWITCH_STATUS_SUCCESS;
5313 }
5314 
5315 int next_cpu(void)
5316 {
5317  int x = 0;
5318 
5319  switch_mutex_lock(video_globals.mutex);
5320  x = video_globals.cur_cpu++;
5321  if (video_globals.cur_cpu == video_globals.cpu_count) {
5322  video_globals.cur_cpu = 0;
5323  }
5324  switch_mutex_unlock(video_globals.mutex);
5325  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Binding to CPU %d\n", x);
5326 
5327  return x;
5328 }
5329 
5331 {
5332  if (video_globals.cpu_count > 1) {
5334  }
5335 }
5336 
5337 
5339 {
5340  struct media_helper *mh = obj;
5343  switch_status_t status;
5344  switch_frame_t *read_frame = NULL;
5345  switch_media_handle_t *smh;
5346  uint32_t loops = 0, xloops = 0, vloops = 0;
5347  switch_image_t *blank_img = NULL;
5348  switch_frame_t fr = { 0 };
5349  unsigned char *buf = NULL;
5350  switch_rgb_color_t bgcolor;
5351  switch_rtp_engine_t *v_engine = NULL;
5352  const char *var;
5354 
5355  if (!(smh = session->media_handle)) {
5356  return NULL;
5357  }
5358 
5360 
5361  if ((var = switch_channel_get_variable(session->channel, "core_video_blank_image"))) {
5362  blank_img = switch_img_read_png(var, SWITCH_IMG_FMT_I420);
5363  }
5364 
5365  if (!blank_img) {
5366  switch_color_set_rgb(&bgcolor, "#000000");
5367  if ((blank_img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, 352, 288, 1))) {
5368  switch_img_fill(blank_img, 0, 0, blank_img->d_w, blank_img->d_h, &bgcolor);
5369  }
5370  }
5371 
5372 
5373 
5374  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
5375  v_engine->thread_id = switch_thread_self();
5376 
5378 
5379  mh->up = 1;
5381 
5383 
5384  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread started. Echo is %s\n",
5385  switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
5387 
5388  buf = switch_core_session_alloc(session, buflen);
5389  fr.packet = buf;
5390  fr.packetlen = buflen;
5391  fr.data = buf + 12;
5392  fr.buflen = buflen - 12;
5393 
5395 
5396  while (switch_channel_up_nosig(channel)) {
5397  int send_blank = 0;
5398 
5399  if (!switch_channel_test_flag(channel, CF_VIDEO)) {
5400  if ((++loops % 100) == 0) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Waiting for video......\n");
5401  switch_yield(20000);
5402  continue;
5403  }
5404 
5405  if (!switch_channel_test_flag(channel, CF_VIDEO_READY) &&
5408  }
5409 
5411  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread paused. Echo is %s\n",
5412  switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
5414  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread resumed Echo is %s\n",
5415  switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
5417  }
5418 
5420  continue;
5421  }
5422 
5423  if (!switch_channel_media_up(session->channel)) {
5424  switch_yield(10000);
5425  continue;
5426  }
5427 
5428  if (smh->video_function) {
5429  int run = 0;
5430 
5432  if (smh->video_function_running == 0) {
5433  smh->video_function_running = 1;
5434  run = 1;
5435  }
5437 
5438  if (run) {
5439  smh->video_function(session, smh->video_user_data);
5441  smh->video_function = NULL;
5442  smh->video_user_data = NULL;
5443  smh->video_function_running = 0;
5445  }
5446  }
5447 
5448  status = switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
5449 
5450  if (!SWITCH_READ_ACCEPTABLE(status)) {
5451  switch_cond_next();
5452  continue;
5453  }
5454 
5455  vloops++;
5456 
5457  send_blank = 1;
5458 
5459  if (switch_channel_test_flag(channel, CF_VIDEO_READY) && !switch_test_flag(read_frame, SFF_CNG)) {
5461  if (smh->video_read_fh && switch_test_flag(smh->video_read_fh, SWITCH_FILE_OPEN) && read_frame->img) {
5462  smh->video_read_fh->mm.fps = smh->vid_params.fps;
5463  switch_core_file_write_video(smh->video_read_fh, read_frame);
5464  }
5466  }
5467 
5469  send_blank = 0;
5470  }
5471 
5472  if (send_blank) {
5473  if (read_frame && (switch_channel_test_flag(channel, CF_VIDEO_ECHO))) {
5475  } else if (blank_img) {
5476  fr.img = blank_img;
5477  switch_yield(10000);
5479  }
5480  }
5481  }
5482 
5483  switch_img_free(&blank_img);
5484 
5486 
5489 
5490  mh->up = 0;
5491  return NULL;
5492 }
5493 
5495 {
5496  switch_threadattr_t *thd_attr = NULL;
5498  switch_rtp_engine_t *v_engine = NULL;
5499  switch_media_handle_t *smh;
5500 
5501  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
5502  return SWITCH_STATUS_NOTIMPL;
5503  }
5504 
5505  if (!(smh = session->media_handle)) {
5506  return SWITCH_STATUS_FALSE;
5507  }
5508 
5509  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
5510 
5512 
5513  if (v_engine->media_thread) {
5515  return SWITCH_STATUS_FALSE;
5516  }
5517 
5518  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Starting Video thread\n", switch_core_session_get_name(session));
5519 
5520  if (v_engine->rtp_session) {
5522  }
5523 
5524  v_engine->mh.session = session;
5525  switch_threadattr_create(&thd_attr, pool);
5527 
5528  switch_thread_cond_create(&v_engine->mh.cond, pool);
5534  switch_thread_create(&v_engine->media_thread, thd_attr, video_helper_thread, &v_engine->mh, switch_core_session_get_pool(session));
5535 
5537  return SWITCH_STATUS_SUCCESS;
5538 }
5539 
5541 {
5542  switch_media_handle_t *smh;
5543 
5544  if (!(smh = session->media_handle)) {
5545  return;
5546  }
5547 
5549 
5551  if (!smh->video_function_running) {
5552  smh->video_function = video_function;
5553  smh->video_user_data = user_data;
5555  }
5557 }
5558 
5560 {
5561  switch_media_handle_t *smh;
5562  int r;
5563 
5564  if (!(smh = session->media_handle)) {
5565  return 0;
5566  }
5567 
5569  r = (smh->video_function_running > 0);
5571 
5572  return r;
5573 }
5574 
5576 {
5577  switch_media_handle_t *smh;
5578 
5579  if (!(smh = session->media_handle)) {
5580  return;
5581  }
5582 
5584  if (smh->video_function_running > 0) {
5585  smh->video_function_running = -1;
5586  }
5588 
5589  while(smh->video_function_running != 0) {
5590  switch_yield(10000);
5591  }
5592 }
5593 
5595 {
5596  switch_rtp_engine_t *v_engine;
5597  switch_media_handle_t *smh;
5598 
5599  switch_assert(session);
5600 
5601  if (!(smh = session->media_handle)) {
5602  return SWITCH_FALSE;
5603  }
5604 
5605  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
5606 
5608 }
5609 
5610 
5611 //?
5612 #define RA_PTR_LEN 512
5614 {
5615  const char *err;
5616  char rip[RA_PTR_LEN] = "";
5617  char rp[RA_PTR_LEN] = "";
5618  char rvp[RA_PTR_LEN] = "";
5619  char *p, *ip_ptr = NULL, *port_ptr = NULL, *vid_port_ptr = NULL, *pe;
5620  int x;
5621  const char *val;
5623  switch_rtp_engine_t *a_engine, *v_engine;
5624  switch_media_handle_t *smh;
5625 
5626  switch_assert(session);
5627 
5628  if (!(smh = session->media_handle)) {
5629  return SWITCH_STATUS_FALSE;
5630  }
5631 
5632  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
5633  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
5634 
5635  if (zstr(sdp_str)) {
5636  sdp_str = smh->mparams->remote_sdp_str;
5637  }
5638 
5639  if (zstr(sdp_str)) {
5640  goto end;
5641  }
5642 
5643  if ((p = (char *) switch_stristr("c=IN IP4 ", sdp_str)) || (p = (char *) switch_stristr("c=IN IP6 ", sdp_str))) {
5644  ip_ptr = p + 9;
5645  }
5646 
5647  if ((p = (char *) switch_stristr("m=audio ", sdp_str))) {
5648  port_ptr = p + 8;
5649  }
5650 
5651  if ((p = (char *) switch_stristr("m=image ", sdp_str))) {
5652  char *tmp = p + 8;
5653 
5654  if (tmp && atoi(tmp)) {
5655  port_ptr = tmp;
5656  }
5657  }
5658 
5659  if ((p = (char *) switch_stristr("m=video ", sdp_str))) {
5660  vid_port_ptr = p + 8;
5661  }
5662 
5663  if (!(ip_ptr && port_ptr)) {
5664  goto end;
5665  }
5666 
5667  p = ip_ptr;
5668  pe = p + strlen(p);
5669  x = 0;
5670  while (x < sizeof(rip) - 1 && p && *p && ((*p >= '0' && *p <= '9') || *p == '.' || *p == ':' || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F'))) {
5671  rip[x++] = *p;
5672  p++;
5673  if (p >= pe) {
5674  goto end;
5675  }
5676  }
5677 
5678  p = port_ptr;
5679  x = 0;
5680  while (x < sizeof(rp) - 1 && p && *p && (*p >= '0' && *p <= '9')) {
5681  rp[x++] = *p;
5682  p++;
5683  if (p >= pe) {
5684  goto end;
5685  }
5686  }
5687 
5688  p = vid_port_ptr;
5689  x = 0;
5690  while (x < sizeof(rvp) - 1 && p && *p && (*p >= '0' && *p <= '9')) {
5691  rvp[x++] = *p;
5692  p++;
5693  if (p >= pe) {
5694  goto end;
5695  }
5696  }
5697 
5698  if (!(*rip && *rp)) {
5700  goto end;
5701  }
5702 
5703  a_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, rip);
5704  a_engine->cur_payload_map->remote_sdp_port = (switch_port_t) atoi(rp);
5705 
5706  if (*rvp) {
5707  v_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, rip);
5708  v_engine->cur_payload_map->remote_sdp_port = (switch_port_t) atoi(rvp);
5709  switch_channel_set_flag(session->channel, CF_VIDEO_POSSIBLE);
5710  switch_channel_set_flag(session->channel, CF_VIDEO);
5711  }
5712 
5713  if (v_engine->cur_payload_map->remote_sdp_ip && v_engine->cur_payload_map->remote_sdp_port) {
5714  if (!strcmp(v_engine->cur_payload_map->remote_sdp_ip, rip) && atoi(rvp) == v_engine->cur_payload_map->remote_sdp_port) {
5715  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote video address:port [%s:%d] has not changed.\n",
5717  } else {
5718  switch_channel_set_flag(session->channel, CF_VIDEO_POSSIBLE);
5719  switch_channel_set_flag(session->channel, CF_VIDEO);
5720  if (switch_rtp_ready(v_engine->rtp_session)) {
5721  const char *rport = NULL;
5722  switch_port_t remote_rtcp_port = v_engine->remote_rtcp_port;
5723 
5724  if (!remote_rtcp_port) {
5725  if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_video_rtcp_port"))) {
5726  remote_rtcp_port = (switch_port_t)atoi(rport);
5727  }
5728  }
5729 
5730 
5732  v_engine->cur_payload_map->remote_sdp_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
5733  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", err);
5734  } else {
5735  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "VIDEO RTP CHANGING DEST TO: [%s:%d]\n",
5738  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
5739  !switch_channel_test_flag(session->channel, CF_AVPF)) {
5740  /* Reactivate the NAT buster flag. */
5742  }
5744  v_engine->check_frames = 0;
5745  }
5746  }
5747  }
5748  }
5749  }
5750 
5751  if (switch_rtp_ready(a_engine->rtp_session)) {
5752  char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
5753  switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
5754  const char *rport = NULL;
5755  switch_port_t remote_rtcp_port = 0;
5756 
5757  if (remote_host && remote_port && !strcmp(remote_host, a_engine->cur_payload_map->remote_sdp_ip) && remote_port == a_engine->cur_payload_map->remote_sdp_port) {
5758  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote address:port [%s:%d] has not changed.\n",
5761  } else if (remote_host && ( (strcmp(remote_host, "0.0.0.0") == 0) ||
5762  (strcmp(a_engine->cur_payload_map->remote_sdp_ip, "0.0.0.0") == 0))) {
5763 
5765  "Remote address changed from [%s] to [%s]. Ignoring...\n",
5766  a_engine->cur_payload_map->remote_sdp_ip, remote_host);
5768  }
5769 
5770  if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_audio_rtcp_port"))) {
5771  remote_rtcp_port = (switch_port_t)atoi(rport);
5772  }
5773 
5774 
5776  a_engine->cur_payload_map->remote_sdp_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
5777  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
5778  status = SWITCH_STATUS_GENERR;
5779  } else {
5780  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n",
5783  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
5784  !switch_channel_test_flag(session->channel, CF_AVPF)) {
5785  /* Reactivate the NAT buster flag. */
5787  }
5789  a_engine->check_frames = 0;
5790  }
5791  status = SWITCH_STATUS_SUCCESS;
5792  }
5793  }
5794 
5795  end:
5796 
5797  return status;
5798 }
5799 
5800 //?
5802 {
5803  switch_assert(network_ip);
5804 
5805  return (smh->mparams->extsipip &&
5806  !switch_check_network_list_ip(network_ip, "loopback.auto") &&
5807  !switch_check_network_list_ip(network_ip, smh->mparams->local_network));
5808 }
5809 
5810 //?
5812 
5813 {
5814  char *error = "";
5816  int x;
5817  switch_port_t myport = *port;
5819  char *stun_ip = NULL;
5820  switch_media_handle_t *smh;
5822 
5823  switch_assert(session);
5824 
5825  if (!(smh = session->media_handle)) {
5826  return SWITCH_STATUS_FALSE;
5827  }
5828 
5829  if (!sourceip) {
5830  return status;
5831  }
5832 
5833  if (!strncasecmp(sourceip, "host:", 5)) {
5834  status = (*ip = switch_stun_host_lookup(sourceip + 5, pool)) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
5835  } else if (!strncasecmp(sourceip, "stun:", 5)) {
5836  char *p;
5837 
5838  stun_ip = strdup(sourceip + 5);
5839 
5840  if ((p = strchr(stun_ip, ':'))) {
5841  int iport;
5842  *p++ = '\0';
5843  iport = atoi(p);
5844  if (iport > 0 && iport < 0xFFFF) {
5845  stun_port = (switch_port_t) iport;
5846  }
5847  }
5848 
5849  if (zstr(stun_ip)) {
5850  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! NO STUN SERVER\n");
5851  goto out;
5852  }
5853 
5854  for (x = 0; x < 5; x++) {
5855  if ((status = switch_stun_lookup(ip, port, stun_ip, stun_port, &error, pool)) != SWITCH_STATUS_SUCCESS) {
5856  switch_yield(100000);
5857  } else {
5858  break;
5859  }
5860  }
5861  if (status != SWITCH_STATUS_SUCCESS) {
5862  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! %s:%d [%s]\n", stun_ip, stun_port, error);
5863  goto out;
5864  }
5865  if (!*ip) {
5866  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! No IP returned\n");
5867  goto out;
5868  }
5869  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "STUN Success [%s]:[%d]\n", *ip, *port);
5870  status = SWITCH_STATUS_SUCCESS;
5871 
5872  if (myport == *port && !strcmp(*ip, smh->mparams->rtpip)) {
5873  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "STUN Not Required ip and port match. [%s]:[%d]\n", *ip, *port);
5874  } else {
5875  smh->mparams->stun_ip = switch_core_session_strdup(session, stun_ip);
5876  smh->mparams->stun_port = stun_port;
5877  smh->mparams->stun_flags |= STUN_FLAG_SET;
5878  }
5879  } else {
5880  *ip = (char *) sourceip;
5881  status = SWITCH_STATUS_SUCCESS;
5882  }
5883 
5884  out:
5885 
5886  switch_safe_free(stun_ip);
5887 
5888  return status;
5889 }
5890 
5891 //?
5893 {
5894  switch_rtp_engine_t *engine;
5895  switch_media_handle_t *smh;
5896 
5897  switch_assert(session);
5898 
5899  if (!(smh = session->media_handle)) {
5900  return;
5901  }
5902 
5903  engine = &smh->engines[type];
5904 
5905  engine->check_frames = 0;
5906  engine->last_ts = 0;
5907  engine->last_seq = 0;
5908 }
5909 
5910 
5911 
5912 //?
5914 {
5915  char *lookup_rtpip; /* Pointer to externally looked up address */
5916  switch_port_t sdp_port; /* The external port to be sent in the SDP */
5917  const char *use_ip = NULL; /* The external IP to be sent in the SDP */
5918  switch_rtp_engine_t *engine;
5919  switch_media_handle_t *smh;
5920  const char *tstr = switch_media_type2str(type);
5921  char vname[128] = "";
5922 
5923  switch_assert(session);
5924 
5925  if (!(smh = session->media_handle)) {
5926  return SWITCH_STATUS_FALSE;
5927  }
5928 
5929  engine = &smh->engines[type];
5930 
5931  lookup_rtpip = smh->mparams->rtpip;
5932 
5933  /* Don't do anything if we're in proxy mode or if a (remote) port already has been found */
5934  if (!force) {
5935  if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) ||
5936  switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) || engine->adv_sdp_port) {
5937  return SWITCH_STATUS_SUCCESS;
5938  }
5939  }
5940 
5941  /* Release the local sdp port */
5942  if (engine->local_sdp_port) {
5944  }
5945 
5946  /* Request a local port from the core's allocator */
5947  if (!(engine->local_sdp_port = switch_rtp_request_port(smh->mparams->rtpip))) {
5948  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "No %s RTP ports available!\n", tstr);
5949  return SWITCH_STATUS_FALSE;
5950  }
5951 
5952  engine->local_sdp_ip = smh->mparams->rtpip;
5953 
5954 
5955  sdp_port = engine->local_sdp_port;
5956 
5957  /* Check if NAT is detected */
5958  if (!zstr(smh->mparams->remote_ip) && switch_core_media_check_nat(smh, smh->mparams->remote_ip)) {
5959  /* Yes, map the port through switch_nat */
5961 
5962  switch_snprintf(vname, sizeof(vname), "rtp_adv_%s_ip", tstr);
5963 
5964  /* Find an IP address to use */
5965  if (!(use_ip = switch_channel_get_variable(session->channel, vname))
5966  && !zstr(smh->mparams->extrtpip)) {
5967  use_ip = smh->mparams->extrtpip;
5968  }
5969 
5970  if (use_ip) {
5971  if (switch_core_media_ext_address_lookup(session, &lookup_rtpip, &sdp_port, use_ip) != SWITCH_STATUS_SUCCESS) {
5972  /* Address lookup was required and fail (external ip was "host:..." or "stun:...") */
5973  return SWITCH_STATUS_FALSE;
5974  } else {
5975  /* Address properly resolved, use it as external ip */
5976  use_ip = lookup_rtpip;
5977  }
5978  } else {
5979  /* No external ip found, use the profile's rtp ip */
5980  use_ip = smh->mparams->rtpip;
5981  }
5982  } else {
5983  /* No NAT traversal required, use the profile's rtp ip */
5984  use_ip = smh->mparams->rtpip;
5985  }
5986 
5987  engine->adv_sdp_port = sdp_port;
5988  engine->adv_sdp_ip = smh->mparams->adv_sdp_audio_ip = smh->mparams->extrtpip = switch_core_session_strdup(session, use_ip);
5989 
5990 
5991  if (type == SWITCH_MEDIA_TYPE_AUDIO) {
5993  switch_channel_set_variable_printf(session->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE, "%d", sdp_port);
5995  } else {
5997  switch_channel_set_variable_printf(session->channel, SWITCH_LOCAL_VIDEO_PORT_VARIABLE, "%d", sdp_port);
5998  }
5999 
6000  return SWITCH_STATUS_SUCCESS;
6001 }
6002 
6004 {
6006  switch_media_handle_t *smh;
6007 
6008  if (!(smh = session->media_handle)) {
6009  return SWITCH_STATUS_FALSE;
6010  }
6011 
6012  if (zstr(smh->mparams->rtpip)) {
6013 
6014  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no media ip\n",
6017 
6018  return SWITCH_STATUS_FALSE;
6019  }
6020 
6021  if (audio && (status = switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_AUDIO, 0)) == SWITCH_STATUS_SUCCESS) {
6022  if (video) {
6024  if (switch_channel_test_flag(session->channel, CF_VIDEO_POSSIBLE)) {
6026  }
6027  }
6028  }
6029 
6030  return status;
6031 }
6032 
6033 
6034 
6035 //?
6037 {
6038  switch_rtp_engine_t *a_engine, *v_engine;
6039  switch_media_handle_t *smh;
6040 
6041  switch_assert(session);
6042 
6043  if (!(smh = session->media_handle)) {
6044  return;
6045  }
6046 
6047  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
6048  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
6049 
6050  if (v_engine->media_thread) {
6051  switch_status_t st;
6052  switch_channel_clear_flag(session->channel, CF_VIDEO_PASSIVE);
6053 
6054  v_engine->mh.up = 0;
6055  switch_thread_join(&st, v_engine->media_thread);
6056  v_engine->media_thread = NULL;
6057  }
6058 
6059  if (v_engine->rtp_session) {
6060  switch_rtp_destroy(&v_engine->rtp_session);
6061  } else if (v_engine->local_sdp_port) {
6063  }
6064 
6065 
6066  if (v_engine->local_sdp_port > 0 && !zstr(smh->mparams->remote_ip) &&
6070  }
6071 
6072 
6073  if (a_engine->rtp_session) {
6074  switch_rtp_destroy(&a_engine->rtp_session);
6075  } else if (a_engine->local_sdp_port) {
6077  }
6078 
6079  if (a_engine->local_sdp_port > 0 && !zstr(smh->mparams->remote_ip) &&
6083  }
6084 
6085 }
6086 
6087 
6088 //?
6089 static void gen_ice(switch_core_session_t *session, switch_media_type_t type, const char *ip, switch_port_t port)
6090 {
6091  switch_media_handle_t *smh;
6092  switch_rtp_engine_t *engine;
6093  char tmp[33] = "";
6094 
6095  switch_assert(session);
6096 
6097  if (!(smh = session->media_handle)) {
6098  return;
6099  }
6100 
6101  engine = &smh->engines[type];
6102 
6103 #ifdef RTCP_MUX
6104  if (!engine->rtcp_mux) {// && type == SWITCH_MEDIA_TYPE_AUDIO) {
6105  engine->rtcp_mux = SWITCH_TRUE;
6106  }
6107 #endif
6108 
6109  if (!smh->msid) {
6110  switch_stun_random_string(tmp, 32, NULL);
6111  tmp[32] = '\0';
6112  smh->msid = switch_core_session_strdup(session, tmp);
6113  }
6114 
6115  if (!smh->cname) {
6116  switch_stun_random_string(tmp, 16, NULL);
6117  tmp[16] = '\0';
6118  smh->cname = switch_core_session_strdup(session, tmp);
6119  }
6120 
6121  if (!engine->ice_out.ufrag) {
6122  switch_stun_random_string(tmp, 16, NULL);
6123  tmp[16] = '\0';
6124  engine->ice_out.ufrag = switch_core_session_strdup(session, tmp);
6125  }
6126 
6127  if (!engine->ice_out.pwd) {
6128  switch_stun_random_string(tmp, 24, NULL);
6129  tmp[24] = '\0';
6130  engine->ice_out.pwd = switch_core_session_strdup(session, tmp);
6131  }
6132 
6133  if (!engine->ice_out.cands[0][0].foundation) {
6134  switch_stun_random_string(tmp, 10, "0123456789");
6135  tmp[10] = '\0';
6136  engine->ice_out.cands[0][0].foundation = switch_core_session_strdup(session, tmp);
6137  }
6138 
6139  engine->ice_out.cands[0][0].transport = "udp";
6140 
6141  if (!engine->ice_out.cands[0][0].component_id) {
6142  engine->ice_out.cands[0][0].component_id = 1;
6143  engine->ice_out.cands[0][0].priority = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - engine->ice_out.cands[0][0].component_id);
6144  }
6145 
6146  if (!zstr(ip)) {
6147  engine->ice_out.cands[0][0].con_addr = switch_core_session_strdup(session, ip);
6148  }
6149 
6150  if (port) {
6151  engine->ice_out.cands[0][0].con_port = port;
6152  }
6153 
6154  engine->ice_out.cands[0][0].generation = "0";
6155  //add rport stuff later
6156 
6157  engine->ice_out.cands[0][0].ready = 1;
6158 
6159 
6160 }
6161 
6163 {
6164  switch_media_handle_t *smh;
6165  switch_rtp_engine_t *v_engine;
6166 
6167  if (!(smh = session->media_handle)) {
6168  return;
6169  }
6170 
6171  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
6172 
6173  if ((!smh->mparams->external_video_source) && (!v_engine->rtp_session)) {
6174  return;
6175  }
6176 
6177  if (!v_engine->media_thread) {
6178  return;
6179  }
6180 
6181  if (!v_engine->mh.cond_mutex) {
6182  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Channel %s has no cond?\n",
6183  switch_channel_get_name(session->channel));
6184  return;
6185  }
6186 
6189  switch_mutex_unlock(v_engine->mh.cond_mutex);
6190  }
6191 }
6192 
6194 {
6195  if (switch_channel_test_flag(session->channel, CF_REINVITE) && engine->new_dtls) {
6196 
6197  if (!zstr(engine->local_dtls_fingerprint.str) && switch_rtp_has_dtls() && dtls_ok(session)) {
6198  dtls_type_t xtype, dtype = engine->dtls_controller ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
6199 
6200  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "RE-SETTING %s DTLS\n", type2str(engine->type));
6201 
6202  xtype = DTLS_TYPE_RTP;
6203  if (engine->rtcp_mux > 0) xtype |= DTLS_TYPE_RTCP;
6204 
6205  switch_rtp_add_dtls(engine->rtp_session, &engine->local_dtls_fingerprint, &engine->remote_dtls_fingerprint, dtype | xtype);
6206 
6207  if (engine->rtcp_mux < 1) {
6208  xtype = DTLS_TYPE_RTCP;
6209  switch_rtp_add_dtls(engine->rtp_session, &engine->local_dtls_fingerprint, &engine->remote_dtls_fingerprint, dtype | xtype);
6210  }
6211 
6212  }
6213  engine->new_dtls = 0;
6214  }
6215 }
6216 
6217 //?
6219 
6220 {
6221  const char *err = NULL;
6222  const char *val = NULL;
6225  char tmp[50];
6226  char *timer_name = NULL;
6227  const char *var;
6228  switch_rtp_engine_t *a_engine, *v_engine;
6229  switch_media_handle_t *smh;
6230 
6231  switch_assert(session);
6232 
6233  if (!(smh = session->media_handle)) {
6234  return SWITCH_STATUS_FALSE;
6235  }
6236 
6237  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
6238  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
6239 
6240 
6241  if (switch_channel_down(session->channel)) {
6242  return SWITCH_STATUS_FALSE;
6243  }
6244 
6245 
6246  if (switch_rtp_ready(a_engine->rtp_session)) {
6248  }
6249 
6250  if (a_engine->crypto_type != CRYPTO_INVALID) {
6251  switch_channel_set_flag(session->channel, CF_SECURE);
6252  }
6253 
6254  if (switch_channel_test_flag(session->channel, CF_PROXY_MODE)) {
6255  status = SWITCH_STATUS_SUCCESS;
6256  goto end;
6257  }
6258 
6259  if (!switch_channel_test_flag(session->channel, CF_REINVITE)) {
6260  if (switch_rtp_ready(a_engine->rtp_session)) {
6261  if (switch_channel_test_flag(session->channel, CF_VIDEO_POSSIBLE) && !switch_rtp_ready(v_engine->rtp_session)) {
6262  goto video;
6263  }
6264 
6265  status = SWITCH_STATUS_SUCCESS;
6266  goto end;
6267  }
6268  }
6269 
6270  if ((status = switch_core_media_set_codec(session, 0, smh->mparams->codec_flags)) != SWITCH_STATUS_SUCCESS) {
6271  goto end;
6272  }
6273 
6275 
6276 
6277  memset(flags, 0, sizeof(flags));
6278  flags[SWITCH_RTP_FLAG_DATAWAIT]++;
6279 
6281  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
6282  flags[SWITCH_RTP_FLAG_AUTOADJ]++;
6283  }
6284 
6286  || ((val = switch_channel_get_variable(session->channel, "pass_rfc2833")) && switch_true(val))) {
6287  switch_channel_set_flag(session->channel, CF_PASS_RFC2833);
6288  }
6289 
6290 
6292  || ((val = switch_channel_get_variable(session->channel, "rtp_autoflush")) && switch_true(val))) {
6293  flags[SWITCH_RTP_FLAG_AUTOFLUSH]++;
6294  }
6295 
6297  ((val = switch_channel_get_variable(session->channel, "rtp_rewrite_timestamps")) && switch_true(val)))) {
6298  flags[SWITCH_RTP_FLAG_RAW_WRITE]++;
6299  }
6300 
6302  smh->mparams->cng_pt = 0;
6303  } else if (smh->mparams->cng_pt) {
6304  flags[SWITCH_RTP_FLAG_AUTO_CNG]++;
6305  }
6306 
6307 #if __BYTE_ORDER == __LITTLE_ENDIAN
6308  if (!strcasecmp(a_engine->read_impl.iananame, "L16")) {
6309  flags[SWITCH_RTP_FLAG_BYTESWAP]++;
6310  }
6311 #endif
6312 
6313  if ((flags[SWITCH_RTP_FLAG_BYTESWAP]) && (val = switch_channel_get_variable(session->channel, "rtp_disable_byteswap")) && switch_true(val)) {
6314  flags[SWITCH_RTP_FLAG_BYTESWAP] = 0;
6315  }
6316 
6317  if ((val = switch_channel_get_variable(session->channel, "rtp_gen_ts_delta")) && switch_true(val)) {
6318  flags[SWITCH_RTP_FLAG_GEN_TS_DELTA] = 1;
6319  }
6320 
6321  if (a_engine->rtp_session && switch_channel_test_flag(session->channel, CF_REINVITE)) {
6322  //const char *ip = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
6323  //const char *port = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
6324  char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
6325  switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
6326 
6327  if (remote_host && remote_port && !strcmp(remote_host, a_engine->cur_payload_map->remote_sdp_ip) &&
6328  remote_port == a_engine->cur_payload_map->remote_sdp_port) {
6329  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n",
6330  switch_channel_get_name(session->channel));
6331  a_engine->cur_payload_map->negotiated = 1;
6332  //XX
6333  goto video;
6334  } else {
6335  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n",
6336  switch_channel_get_name(session->channel),
6337  remote_host, remote_port, a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
6338 
6339  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
6342  }
6343  }
6344 
6345  if (!switch_channel_test_flag(session->channel, CF_PROXY_MEDIA)) {
6346  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP [%s] %s port %d -> %s port %d codec: %u ms: %d\n",
6347  switch_channel_get_name(session->channel),
6348  a_engine->local_sdp_ip,
6349  a_engine->local_sdp_port,
6350  a_engine->cur_payload_map->remote_sdp_ip,
6352 
6353  //XX
6354  }
6355 
6356  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->local_sdp_port);
6360 
6361  if (a_engine->rtp_session && switch_channel_test_flag(session->channel, CF_REINVITE)) {
6362  const char *rport = NULL;
6363  switch_port_t remote_rtcp_port = a_engine->remote_rtcp_port;
6364 
6365  if (!remote_rtcp_port) {
6366  if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_audio_rtcp_port"))) {
6367  remote_rtcp_port = (switch_port_t)atoi(rport);
6368  }
6369  }
6370 
6372  remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
6373  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
6374  } else {
6375  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n",
6377 
6378  if (switch_channel_test_flag(session->channel, CF_PROTO_HOLD) && strcmp(a_engine->cur_payload_map->remote_sdp_ip, "0.0.0.0")) {
6379  switch_core_media_toggle_hold(session, 0);
6380  }
6381 
6382 
6384  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
6385  !switch_channel_test_flag(session->channel, CF_AVPF)) {
6386  /* Reactivate the NAT buster flag. */
6388  }
6389  }
6390 
6391  if (session && a_engine) {
6392  check_dtls_reinvite(session, a_engine);
6393  }
6394 
6395  goto video;
6396  }
6397 
6398  if (switch_channel_test_flag(session->channel, CF_PROXY_MEDIA)) {
6399  switch_core_media_proxy_remote_addr(session, NULL);
6400 
6401  memset(flags, 0, sizeof(flags));
6402  flags[SWITCH_RTP_FLAG_DATAWAIT]++;
6403  flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++;
6404 
6406  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
6407  flags[SWITCH_RTP_FLAG_AUTOADJ]++;
6408  }
6409  timer_name = NULL;
6410 
6412  "PROXY AUDIO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
6413  switch_channel_get_name(session->channel),
6414  a_engine->cur_payload_map->remote_sdp_ip,
6415  a_engine->cur_payload_map->remote_sdp_port,
6416  a_engine->cur_payload_map->remote_sdp_ip,
6418 
6419  if (switch_rtp_ready(a_engine->rtp_session)) {
6421  }
6422 
6423  } else {
6424  timer_name = smh->mparams->timer_name;
6425 
6426  if ((var = switch_channel_get_variable(session->channel, "rtp_timer_name"))) {
6427  timer_name = (char *) var;
6428  }
6429  }
6430 
6431  if (switch_channel_up(session->channel)) {
6432  switch_channel_set_variable(session->channel, "rtp_use_timer_name", timer_name);
6433 
6434  a_engine->rtp_session = switch_rtp_new(a_engine->local_sdp_ip,
6435  a_engine->local_sdp_port,
6436  a_engine->cur_payload_map->remote_sdp_ip,
6437  a_engine->cur_payload_map->remote_sdp_port,
6438  a_engine->cur_payload_map->agreed_pt,
6439  a_engine->read_impl.samples_per_packet,
6440  a_engine->cur_payload_map->codec_ms * 1000,
6441  flags, timer_name, &err, switch_core_session_get_pool(session));
6442 
6443  if (switch_rtp_ready(a_engine->rtp_session)) {
6444  switch_rtp_set_payload_map(a_engine->rtp_session, &a_engine->payload_map);
6445  }
6446  }
6447 
6448  if (switch_rtp_ready(a_engine->rtp_session)) {
6449  uint8_t vad_in = (smh->mparams->vflags & VAD_IN);
6450  uint8_t vad_out = (smh->mparams->vflags & VAD_OUT);
6451  uint8_t inb = switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_INBOUND;
6452  const char *ssrc;
6453 
6456 
6457  //switch_core_media_set_rtp_session(session, SWITCH_MEDIA_TYPE_AUDIO, a_engine->rtp_session);
6458 
6459  if ((ssrc = switch_channel_get_variable(session->channel, "rtp_use_ssrc"))) {
6460  uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10);
6461  switch_rtp_set_ssrc(a_engine->rtp_session, ssrc_ul);
6462  a_engine->ssrc = ssrc_ul;
6463  } else {
6464  switch_rtp_set_ssrc(a_engine->rtp_session, a_engine->ssrc);
6465  }
6466 
6467  if (a_engine->remote_ssrc) {
6468  switch_rtp_set_remote_ssrc(a_engine->rtp_session, a_engine->remote_ssrc);
6469  }
6470 
6471  switch_channel_set_flag(session->channel, CF_FS_RTP);
6472 
6473  switch_channel_set_variable_printf(session->channel, "rtp_use_pt", "%d", a_engine->cur_payload_map->agreed_pt);
6474 
6475  if ((val = switch_channel_get_variable(session->channel, "rtp_enable_vad_in")) && switch_true(val)) {
6476  vad_in = 1;
6477  }
6478  if ((val = switch_channel_get_variable(session->channel, "rtp_enable_vad_out")) && switch_true(val)) {
6479  vad_out = 1;
6480  }
6481 
6482  if ((val = switch_channel_get_variable(session->channel, "rtp_disable_vad_in")) && switch_true(val)) {
6483  vad_in = 0;
6484  }
6485  if ((val = switch_channel_get_variable(session->channel, "rtp_disable_vad_out")) && switch_true(val)) {
6486  vad_out = 0;
6487  }
6488 
6489 
6490  a_engine->ssrc = switch_rtp_get_ssrc(a_engine->rtp_session);
6491  switch_channel_set_variable_printf(session->channel, "rtp_use_ssrc", "%u", a_engine->ssrc);
6492 
6493 
6494 
6496  a_engine->rtp_bugs |= RTP_BUG_IGNORE_MARK_BIT;
6497  }
6498 
6499  if ((val = switch_channel_get_variable(session->channel, "rtp_manual_rtp_bugs"))) {
6500  switch_core_media_parse_rtp_bugs(&a_engine->rtp_bugs, val);
6501  }
6502 
6503  //if (switch_channel_test_flag(session->channel, CF_AVPF)) {
6504  // smh->mparams->manual_rtp_bugs = RTP_BUG_SEND_LINEAR_TIMESTAMPS;
6505  //}
6506 
6508 
6509  if ((vad_in && inb) || (vad_out && !inb)) {
6511 
6512  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP Engage VAD for %s ( %s %s )\n",
6513  switch_channel_get_name(switch_core_session_get_channel(session)), vad_in ? "in" : "", vad_out ? "out" : "");
6514  }
6515 
6516 
6517  if (a_engine->ice_in.cands[a_engine->ice_in.chosen[0]][0].ready) {
6518 
6519  gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, NULL, 0);
6520 
6521  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating Audio ICE\n");
6522 
6524  a_engine->ice_in.ufrag,
6525  a_engine->ice_out.ufrag,
6526  a_engine->ice_out.pwd,
6527  a_engine->ice_in.pwd,
6528  IPR_RTP,
6529 #ifdef GOOGLE_ICE
6531  NULL
6532 #else
6533  switch_ice_direction(session) ==
6535  &a_engine->ice_in
6536 #endif
6537  );
6538 
6539 
6540 
6541  }
6542 
6543 
6544 
6545  if ((val = switch_channel_get_variable(session->channel, "rtcp_audio_interval_msec")) || (val = smh->mparams->rtcp_audio_interval_msec)) {
6546  const char *rport = switch_channel_get_variable(session->channel, "rtp_remote_audio_rtcp_port");
6547  switch_port_t remote_rtcp_port = a_engine->remote_rtcp_port;
6548 
6549  if (!remote_rtcp_port && rport) {
6550  remote_rtcp_port = (switch_port_t)atoi(rport);
6551  }
6552 
6553  if (!strcasecmp(val, "passthru")) {
6554  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating RTCP PASSTHRU PORT %d\n", remote_rtcp_port);
6555  switch_rtp_activate_rtcp(a_engine->rtp_session, -1, remote_rtcp_port, a_engine->rtcp_mux > 0);
6556  } else if (remote_rtcp_port) {
6557  int interval = atoi(val);
6558  if (interval < 100 || interval > 500000) {
6560  "Invalid rtcp interval spec [%d] must be between 100 and 500000\n", interval);
6561  interval = 5000;
6562  }
6563 
6564  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Activating RTCP PORT %d\n", remote_rtcp_port);
6565  switch_rtp_activate_rtcp(a_engine->rtp_session, interval, remote_rtcp_port, a_engine->rtcp_mux > 0);
6566 
6567  }
6568 
6569  if (a_engine->ice_in.cands[a_engine->ice_in.chosen[1]][1].ready) {
6570  if (a_engine->rtcp_mux > 0 && !strcmp(a_engine->ice_in.cands[a_engine->ice_in.chosen[1]][1].con_addr, a_engine->ice_in.cands[a_engine->ice_in.chosen[0]][0].con_addr)
6571  && a_engine->ice_in.cands[a_engine->ice_in.chosen[1]][1].con_port == a_engine->ice_in.cands[a_engine->ice_in.chosen[0]][0].con_port) {
6572  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Skipping RTCP ICE (Same as RTP)\n");
6573  } else {
6574  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating RTCP ICE\n");
6575 
6577  a_engine->ice_in.ufrag,
6578  a_engine->ice_out.ufrag,
6579  a_engine->ice_out.pwd,
6580  a_engine->ice_in.pwd,
6581  IPR_RTCP,
6582 #ifdef GOOGLE_ICE
6584  NULL
6585 #else
6586  switch_ice_direction(session) ==
6588  &a_engine->ice_in
6589 #endif
6590  );
6591  }
6592 
6593  }
6594  }
6595 
6596  if (!zstr(a_engine->local_dtls_fingerprint.str) && switch_rtp_has_dtls() && dtls_ok(smh->session)) {
6597  dtls_type_t xtype, dtype = a_engine->dtls_controller ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
6598 
6599  //if (switch_channel_test_flag(smh->session->channel, CF_3PCC)) {
6600  // dtype = (dtype == DTLS_TYPE_CLIENT) ? DTLS_TYPE_SERVER : DTLS_TYPE_CLIENT;
6601  //}
6602 
6603  xtype = DTLS_TYPE_RTP;
6604  if (a_engine->rtcp_mux > 0 && smh->mparams->rtcp_audio_interval_msec) xtype |= DTLS_TYPE_RTCP;
6605 
6606  switch_rtp_add_dtls(a_engine->rtp_session, &a_engine->local_dtls_fingerprint, &a_engine->remote_dtls_fingerprint, dtype | xtype);
6607 
6608  if (a_engine->rtcp_mux < 1 && smh->mparams->rtcp_audio_interval_msec) {
6609  xtype = DTLS_TYPE_RTCP;
6610  switch_rtp_add_dtls(a_engine->rtp_session, &a_engine->local_dtls_fingerprint, &a_engine->remote_dtls_fingerprint, dtype | xtype);
6611  }
6612 
6613  }
6614 
6615  check_jb(session, NULL, 0, 0, SWITCH_FALSE);
6616 
6617  if ((val = switch_channel_get_variable(session->channel, "rtp_timeout_sec"))) {
6618  int v = atoi(val);
6619  if (v >= 0) {
6620  smh->mparams->rtp_timeout_sec = v;
6621  }
6622  }
6623 
6624  if ((val = switch_channel_get_variable(session->channel, "rtp_hold_timeout_sec"))) {
6625  int v = atoi(val);
6626  if (v >= 0) {
6627  smh->mparams->rtp_hold_timeout_sec = v;
6628  }
6629  }
6630 
6631  if (smh->mparams->rtp_timeout_sec) {
6633 
6635  if (!smh->mparams->rtp_hold_timeout_sec) {
6637  }
6638  }
6639 
6640  if (smh->mparams->rtp_hold_timeout_sec) {
6642  }
6643 
6644  if (smh->mparams->te) {
6645  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Set 2833 dtmf send payload to %u\n",
6646  switch_channel_get_name(session->channel), smh->mparams->te);
6648  switch_channel_set_variable_printf(session->channel, "rtp_2833_send_payload", "%d", smh->mparams->te);
6649  }
6650 
6651  if (smh->mparams->recv_te) {
6652  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Set 2833 dtmf receive payload to %u\n",
6653  switch_channel_get_name(session->channel), smh->mparams->recv_te);
6655  switch_channel_set_variable_printf(session->channel, "rtp_2833_recv_payload", "%d", smh->mparams->recv_te);
6656  }
6657 
6658  //XX
6659 
6661  ((val = switch_channel_get_variable(session->channel, "supress_cng")) && switch_true(val)) ||
6662  ((val = switch_channel_get_variable(session->channel, "suppress_cng")) && switch_true(val))) {
6663  smh->mparams->cng_pt = 0;
6664  }
6665 
6666  if (((val = switch_channel_get_variable(session->channel, "rtp_digit_delay")))) {
6667  int delayi = atoi(val);
6668  if (delayi < 0) delayi = 0;
6669  smh->mparams->dtmf_delay = (uint32_t) delayi;
6670  }
6671 
6672 
6673  if (smh->mparams->dtmf_delay) {
6676  "%s Set rtp dtmf delay to %u\n", switch_channel_get_name(session->channel), smh->mparams->dtmf_delay);
6677 
6678  }
6679 
6681  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u\n", smh->mparams->cng_pt);
6682  switch_rtp_set_cng_pt(a_engine->rtp_session, smh->mparams->cng_pt);
6683  }
6684 
6686 
6687  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
6690 
6691 
6692  if (switch_channel_test_flag(session->channel, CF_ZRTP_PASSTHRU)) {
6693  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating ZRTP PROXY MODE\n");
6694  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Disable NOTIMER_DURING_BRIDGE\n");
6696  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Activating audio UDPTL mode\n");
6698  }
6699 
6700 
6701 
6702 
6703 
6704 
6705  video:
6706 
6707  if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
6709  }
6710 
6711  if (switch_channel_test_flag(session->channel, CF_VIDEO_POSSIBLE) && v_engine->cur_payload_map->rm_encoding && v_engine->cur_payload_map->remote_sdp_port) {
6712  /******************************************************************************************/
6713  if (v_engine->rtp_session && switch_channel_test_flag(session->channel, CF_REINVITE)) {
6714  //const char *ip = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
6715  //const char *port = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
6716  char *remote_host = switch_rtp_get_remote_host(v_engine->rtp_session);
6717  switch_port_t remote_port = switch_rtp_get_remote_port(v_engine->rtp_session);
6718 
6719 
6720 
6721  if (remote_host && remote_port && !strcmp(remote_host, v_engine->cur_payload_map->remote_sdp_ip) && remote_port == v_engine->cur_payload_map->remote_sdp_port) {
6722  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video params are unchanged for %s.\n",
6723  switch_channel_get_name(session->channel));
6724  v_engine->cur_payload_map->negotiated = 1;
6725  goto video_up;
6726  } else {
6727  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video params changed for %s from %s:%d to %s:%d\n",
6728  switch_channel_get_name(session->channel),
6729  remote_host, remote_port, v_engine->cur_payload_map->remote_sdp_ip, v_engine->cur_payload_map->remote_sdp_port);
6730  }
6731  }
6732 
6733  if (!switch_channel_test_flag(session->channel, CF_PROXY_MEDIA)) {
6734  if (switch_rtp_ready(v_engine->rtp_session)) {
6736  "VIDEO RTP [%s] %s port %d -> %s port %d codec: %u\n", switch_channel_get_name(session->channel),
6737  v_engine->local_sdp_ip, v_engine->local_sdp_port, v_engine->cur_payload_map->remote_sdp_ip,
6738  v_engine->cur_payload_map->remote_sdp_port, v_engine->cur_payload_map->agreed_pt);
6739 
6741  }
6742  }
6743 
6744  switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->local_sdp_port);
6747 
6748 
6749  if (v_engine->rtp_session && switch_channel_test_flag(session->channel, CF_REINVITE)) {
6750  const char *rport = NULL;
6751  switch_port_t remote_rtcp_port = v_engine->remote_rtcp_port;
6752 
6753  //switch_channel_clear_flag(session->channel, CF_REINVITE);
6754 
6755  if (!remote_rtcp_port) {
6756  if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_video_rtcp_port"))) {
6757  remote_rtcp_port = (switch_port_t)atoi(rport);
6758  }
6759  }
6760 
6762  (v_engine->rtp_session, v_engine->cur_payload_map->remote_sdp_ip, v_engine->cur_payload_map->remote_sdp_port, remote_rtcp_port, SWITCH_TRUE,
6763  &err) != SWITCH_STATUS_SUCCESS) {
6764  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", err);
6765  } else {
6766  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "VIDEO RTP CHANGING DEST TO: [%s:%d]\n",
6769  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
6770  /* Reactivate the NAT buster flag. */
6772  }
6773 
6774  }
6775  goto video_up;
6776  }
6777 
6778  if (switch_channel_test_flag(session->channel, CF_PROXY_MEDIA)) {
6779  switch_core_media_proxy_remote_addr(session, NULL);
6780 
6781  memset(flags, 0, sizeof(flags));
6782  flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++;
6783  flags[SWITCH_RTP_FLAG_DATAWAIT]++;
6784 
6786  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
6787  flags[SWITCH_RTP_FLAG_AUTOADJ]++;
6788  }
6789  timer_name = NULL;
6790 
6792  "PROXY VIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
6793  switch_channel_get_name(session->channel),
6794  a_engine->cur_payload_map->remote_sdp_ip,
6795  v_engine->local_sdp_port,
6796  v_engine->cur_payload_map->remote_sdp_ip,
6798 
6799  if (switch_rtp_ready(v_engine->rtp_session)) {
6801  }
6802  } else {
6803  timer_name = smh->mparams->timer_name;
6804 
6805  if ((var = switch_channel_get_variable(session->channel, "rtp_timer_name"))) {
6806  timer_name = (char *) var;
6807  }
6808  }
6809 
6810  /******************************************************************************************/
6811 
6812  if (v_engine->rtp_session) {
6813  goto video_up;
6814  }
6815 
6816 
6817  if (!v_engine->local_sdp_port) {
6819  }
6820 
6821  memset(flags, 0, sizeof(flags));
6822  flags[SWITCH_RTP_FLAG_DATAWAIT]++;
6823  flags[SWITCH_RTP_FLAG_RAW_WRITE]++;
6824 
6826  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
6827  !switch_channel_test_flag(session->channel, CF_AVPF)) {
6828  flags[SWITCH_RTP_FLAG_AUTOADJ]++;
6829  }
6830 
6831  if (switch_channel_test_flag(session->channel, CF_PROXY_MEDIA)) {
6832  flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++;
6833  }
6835 
6836  flags[SWITCH_RTP_FLAG_USE_TIMER] = 0;
6837  flags[SWITCH_RTP_FLAG_NOBLOCK] = 0;
6838  flags[SWITCH_RTP_FLAG_VIDEO]++;
6839 
6840  if (v_engine->fir) {
6841  flags[SWITCH_RTP_FLAG_FIR]++;
6842  }
6843 
6844  if (v_engine->pli) {
6845  flags[SWITCH_RTP_FLAG_PLI]++;
6846  }
6847 
6848  if (v_engine->nack) {
6849  flags[SWITCH_RTP_FLAG_NACK]++;
6850  }
6851 
6852  if (v_engine->tmmbr) {
6853  flags[SWITCH_RTP_FLAG_TMMBR]++;
6854  }
6855 
6856  v_engine->rtp_session = switch_rtp_new(a_engine->local_sdp_ip,
6857  v_engine->local_sdp_port,
6858  v_engine->cur_payload_map->remote_sdp_ip,
6859  v_engine->cur_payload_map->remote_sdp_port,
6860  v_engine->cur_payload_map->agreed_pt,
6861  1, 90000, flags, NULL, &err, switch_core_session_get_pool(session));
6862 
6863 
6864  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%sVIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n",
6865  switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) ? "PROXY " : "",
6866  switch_channel_get_name(session->channel),
6867  a_engine->local_sdp_ip,
6868  v_engine->local_sdp_port,
6869  v_engine->cur_payload_map->remote_sdp_ip,
6871  0, switch_rtp_ready(v_engine->rtp_session) ? "SUCCESS" : err);
6872 
6873 
6874  if (switch_rtp_ready(v_engine->rtp_session)) {
6875  const char *ssrc;
6876 
6877  if (v_engine->fir) {
6879  }
6880 
6881  if (v_engine->pli) {
6883  }
6884 
6885  switch_rtp_set_payload_map(v_engine->rtp_session, &v_engine->payload_map);
6886  switch_channel_set_flag(session->channel, CF_VIDEO);
6888 
6889  if ((ssrc = switch_channel_get_variable(session->channel, "rtp_use_video_ssrc"))) {
6890  uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10);
6891  switch_rtp_set_ssrc(v_engine->rtp_session, ssrc_ul);
6892  v_engine->ssrc = ssrc_ul;
6893  } else {
6894  switch_rtp_set_ssrc(v_engine->rtp_session, v_engine->ssrc);
6895  }
6896 
6897  if (v_engine->remote_ssrc) {
6898  switch_rtp_set_remote_ssrc(v_engine->rtp_session, v_engine->remote_ssrc);
6899  }
6900 
6901  if (v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].ready) {
6902 
6903  gen_ice(session, SWITCH_MEDIA_TYPE_VIDEO, NULL, 0);
6904 
6905  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating Video ICE\n");
6906 
6908  v_engine->ice_in.ufrag,
6909  v_engine->ice_out.ufrag,
6910  v_engine->ice_out.pwd,
6911  v_engine->ice_in.pwd,
6912  IPR_RTP,
6913 #ifdef GOOGLE_ICE
6915  NULL
6916 #else
6917  switch_ice_direction(session) ==
6919  &v_engine->ice_in
6920 #endif
6921  );
6922 
6923 
6924  }
6925 
6926  if ((val = switch_channel_get_variable(session->channel, "rtcp_video_interval_msec")) || (val = smh->mparams->rtcp_video_interval_msec)) {
6927  const char *rport = switch_channel_get_variable(session->channel, "rtp_remote_video_rtcp_port");
6928  switch_port_t remote_port = v_engine->remote_rtcp_port;
6929 
6930  if (rport) {
6931  remote_port = (switch_port_t)atoi(rport);
6932  }
6933  if (!strcasecmp(val, "passthru")) {
6934  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating VIDEO RTCP PASSTHRU PORT %d\n", remote_port);
6935  switch_rtp_activate_rtcp(v_engine->rtp_session, -1, remote_port, v_engine->rtcp_mux > 0);
6936  } else {
6937  int interval = atoi(val);
6938  if (interval < 100 || interval > 500000) {
6940  "Invalid rtcp interval spec [%d] must be between 100 and 500000\n", interval);
6941  interval = 5000;
6942  }
6944  "Activating VIDEO RTCP PORT %d interval %d mux %d\n", remote_port, interval, v_engine->rtcp_mux);
6945  switch_rtp_activate_rtcp(v_engine->rtp_session, interval, remote_port, v_engine->rtcp_mux > 0);
6946 
6947  }
6948 
6949 
6950  if (v_engine->ice_in.cands[v_engine->ice_in.chosen[1]][1].ready) {
6951 
6952  if (v_engine->rtcp_mux > 0 && !strcmp(v_engine->ice_in.cands[v_engine->ice_in.chosen[1]][1].con_addr, v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].con_addr)
6953  && v_engine->ice_in.cands[v_engine->ice_in.chosen[1]][1].con_port == v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].con_port) {
6954  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Skipping VIDEO RTCP ICE (Same as VIDEO RTP)\n");
6955  } else {
6956 
6957  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating VIDEO RTCP ICE\n");
6959  v_engine->ice_in.ufrag,
6960  v_engine->ice_out.ufrag,
6961  v_engine->ice_out.pwd,
6962  v_engine->ice_in.pwd,
6963  IPR_RTCP,
6964 #ifdef GOOGLE_ICE
6966  NULL
6967 #else
6968  switch_ice_direction(session) ==
6970  &v_engine->ice_in
6971 #endif
6972  );
6973 
6974 
6975 
6976  }
6977 
6978  }
6979  }
6980 
6981  if (!zstr(v_engine->local_dtls_fingerprint.str) && switch_rtp_has_dtls() && dtls_ok(smh->session)) {
6982  dtls_type_t xtype,
6983  dtype = v_engine->dtls_controller ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
6984  xtype = DTLS_TYPE_RTP;
6985  if (v_engine->rtcp_mux > 0 && smh->mparams->rtcp_video_interval_msec) xtype |= DTLS_TYPE_RTCP;
6986 
6987  switch_rtp_add_dtls(v_engine->rtp_session, &v_engine->local_dtls_fingerprint, &v_engine->remote_dtls_fingerprint, dtype | xtype);
6988 
6989  if (v_engine->rtcp_mux < 1 && smh->mparams->rtcp_video_interval_msec) {
6990  xtype = DTLS_TYPE_RTCP;
6991  switch_rtp_add_dtls(v_engine->rtp_session, &v_engine->local_dtls_fingerprint, &v_engine->remote_dtls_fingerprint, dtype | xtype);
6992  }
6993  }
6994 
6995 
6996  if ((val = switch_channel_get_variable(session->channel, "rtp_manual_video_rtp_bugs"))) {
6997  switch_core_media_parse_rtp_bugs(&v_engine->rtp_bugs, val);
6998  }
6999 
7000  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
7002  }
7003 
7005 
7006  //XX
7007 
7008 
7009  switch_channel_set_variable_printf(session->channel, "rtp_use_video_pt", "%d", v_engine->cur_payload_map->agreed_pt);
7010  v_engine->ssrc = switch_rtp_get_ssrc(v_engine->rtp_session);
7011  switch_channel_set_variable_printf(session->channel, "rtp_use_video_ssrc", "%u", v_engine->ssrc);
7012 
7014 
7015 
7016  if (switch_channel_test_flag(session->channel, CF_ZRTP_PASSTHRU)) {
7017  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Activating video UDPTL mode\n");
7019  }
7020 
7021  } else {
7022  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", switch_str_nil(err));
7024  goto end;
7025  }
7026  }
7027 
7028  } else {
7029  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", switch_str_nil(err));
7031  status = SWITCH_STATUS_FALSE;
7032  goto end;
7033  }
7034 
7035  video_up:
7036 
7037  if (session && v_engine) {
7038  check_dtls_reinvite(session, v_engine);
7039  }
7040 
7041  status = SWITCH_STATUS_SUCCESS;
7042 
7043  end:
7044 
7045  switch_channel_clear_flag(session->channel, CF_REINVITE);
7046 
7047  switch_core_recovery_track(session);
7048 
7049  return status;
7050 
7051 }
7052 
7053 static const char *get_media_profile_name(switch_core_session_t *session, int secure)
7054 {
7055  switch_assert(session);
7056 
7057  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
7058  if (switch_channel_test_flag(session->channel, CF_DTLS) || secure) {
7059  if (switch_channel_test_flag(session->channel, CF_AVPF_MOZ)) {
7060  return "UDP/TLS/RTP/SAVPF";
7061  } else {
7062  return "RTP/SAVPF";
7063  }
7064  } else {
7065  if (switch_channel_test_flag(session->channel, CF_AVPF_MOZ)) {
7066  return "UDP/AVPF";
7067  } else {
7068  return "RTP/AVPF";
7069  }
7070  }
7071  }
7072 
7073  if (secure) {
7074  return "RTP/SAVP";
7075  }
7076 
7077  return "RTP/AVP";
7078 
7079 }
7080 
7082 {
7083 
7084  if (sdp_type == SDP_TYPE_REQUEST) {
7085  engine->dtls_controller = 0;
7086  engine->new_dtls = 1;
7087  engine->new_ice = 1;
7088  return "actpass";
7089  } else {
7090  return engine->dtls_controller ? "active" : "passive";
7091  }
7092 }
7093 
7094 
7095 //?
7096 static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
7097  switch_port_t port, const char *family, const char *ip,
7098  int cur_ptime, const char *append_audio, const char *sr, int use_cng, int cng_type, switch_event_t *map, int secure,
7099  switch_sdp_type_t sdp_type)
7100 {
7101  int i = 0;
7102  int rate;
7103  int already_did[128] = { 0 };
7104  int ptime = 0, noptime = 0;
7105  const char *local_sdp_audio_zrtp_hash;
7106  switch_media_handle_t *smh;
7107  switch_rtp_engine_t *a_engine;
7108 
7109  switch_assert(session);
7110 
7111  if (!(smh = session->media_handle)) {
7112  return;
7113  }
7114 
7115  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
7116 
7117  //switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d RTP/%sAVP%s",
7118  //port, secure ? "S" : "", switch_channel_test_flag(session->channel, CF_AVPF) ? "F" : "");
7119 
7120  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d %s", port,
7121  get_media_profile_name(session, secure || a_engine->crypto_type != CRYPTO_INVALID));
7122 
7123  for (i = 0; i < smh->mparams->num_codecs; i++) {
7124  const switch_codec_implementation_t *imp = smh->codecs[i];
7125  int this_ptime = (imp->microseconds_per_packet / 1000);
7126 
7127  if (!strcasecmp(imp->iananame, "ilbc") || !strcasecmp(imp->iananame, "isac") ) {
7128  this_ptime = 20;
7129  }
7130 
7131  if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
7132  continue;
7133  }
7134 
7135  if (!noptime) {
7136  if (!cur_ptime) {
7137  if (!ptime) {
7138  ptime = this_ptime;
7139  }
7140  } else {
7141  if (this_ptime != cur_ptime) {
7142  continue;
7143  }
7144  }
7145  }
7146 
7147  if (smh->ianacodes[i] < 128) {
7148  if (already_did[smh->ianacodes[i]]) {
7149  continue;
7150  }
7151 
7152  already_did[smh->ianacodes[i]] = 1;
7153  }
7154 
7155 
7156  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", smh->ianacodes[i]);
7157  }
7158 
7159  if (smh->mparams->dtmf_type == DTMF_2833 && smh->mparams->te > 95) {
7160  int i;
7161  for (i = 0; i < smh->num_rates; i++) {
7162  if (smh->dtmf_ianacodes[i]) {
7163  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", smh->dtmf_ianacodes[i]);
7164  }
7165  if (smh->cng_ianacodes[i] && !switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && cng_type && use_cng) {
7166  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", smh->cng_ianacodes[i]);
7167  }
7168  }
7169  }
7170 
7171  //if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && cng_type && use_cng) {
7172  //switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", cng_type);
7173  //}
7174 
7175  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "\r\n");
7176 
7177 
7178  memset(already_did, 0, sizeof(already_did));
7179 
7180 
7181  for (i = 0; i < smh->mparams->num_codecs; i++) {
7182  const switch_codec_implementation_t *imp = smh->codecs[i];
7183  char *fmtp = imp->fmtp;
7184  int this_ptime = imp->microseconds_per_packet / 1000;
7185 
7186  if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
7187  continue;
7188  }
7189 
7190  if (!strcasecmp(imp->iananame, "ilbc") || !strcasecmp(imp->iananame, "isac")) {
7191  this_ptime = 20;
7192  }
7193 
7194  if (!noptime) {
7195  if (!cur_ptime) {
7196  if (!ptime) {
7197  ptime = this_ptime;
7198  }
7199  } else {
7200  if (this_ptime != cur_ptime) {
7201  continue;
7202  }
7203  }
7204  }
7205 
7206  if (smh->ianacodes[i] < 128) {
7207  if (already_did[smh->ianacodes[i]]) {
7208  continue;
7209  }
7210 
7211  already_did[smh->ianacodes[i]] = 1;
7212  }
7213 
7214  rate = imp->samples_per_second;
7215 
7216  if (map) {
7217  char key[128] = "";
7218  char *check = NULL;
7219  switch_snprintf(key, sizeof(key), "%s:%u", imp->iananame, imp->bits_per_second);
7220 
7221  if ((check = switch_event_get_header(map, key)) || (check = switch_event_get_header(map, imp->iananame))) {
7222  fmtp = check;
7223  }
7224  }
7225 
7226  if (smh->fmtps[i]) {
7227  fmtp = smh->fmtps[i];
7228  }
7229 
7230  if (smh->ianacodes[i] > 95 || switch_channel_test_flag(session->channel, CF_VERBOSE_SDP)) {
7231  int channels = get_channels(imp->iananame, imp->number_of_channels);
7232 
7233  if (channels > 1) {
7234  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d/%d\r\n", smh->ianacodes[i], imp->iananame, rate, channels);
7235 
7236  } else {
7237  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d\r\n", smh->ianacodes[i], imp->iananame, rate);
7238  }
7239  }
7240 
7241  if (fmtp) {
7242  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=fmtp:%d %s\r\n", smh->ianacodes[i], fmtp);
7243  }
7244  }
7245 
7246 
7248  switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF)) && smh->mparams->te > 95) {
7249 
7250  for (i = 0; i < smh->num_rates; i++) {
7251  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
7252  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d telephone-event/%d\r\n",
7253  smh->dtmf_ianacodes[i], smh->rates[i]);
7254  } else {
7255  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d telephone-event/%d\r\na=fmtp:%d 0-16\r\n",
7256  smh->dtmf_ianacodes[i], smh->rates[i], smh->dtmf_ianacodes[i]);
7257  }
7258  }
7259  }
7260 
7261  if (!zstr(a_engine->local_dtls_fingerprint.type) && secure) {
7262  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=fingerprint:%s %s\na=setup:%s\r\n", a_engine->local_dtls_fingerprint.type,
7263  a_engine->local_dtls_fingerprint.str, get_setup(a_engine, session, sdp_type));
7264  }
7265 
7266  if (smh->mparams->rtcp_audio_interval_msec) {
7267  if (a_engine->rtcp_mux > 0) {
7268  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp-mux\r\n");
7269  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp:%d IN %s %s\r\n", port, family, ip);
7270  } else {
7271  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp:%d IN %s %s\r\n", port + 1, family, ip);
7272  }
7273  }
7274 
7275  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\r\n", a_engine->ssrc);
7276 
7277  if (a_engine->ice_out.cands[0][0].ready) {
7278  char tmp1[11] = "";
7279  char tmp2[11] = "";
7280  uint32_t c1 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 1);
7281  uint32_t c2 = c1 - 1;
7282 
7283  //uint32_t c2 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 2);
7284  //uint32_t c3 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 1);
7285  //uint32_t c4 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 2);
7286  ice_t *ice_out;
7287 
7288  tmp1[10] = '\0';
7289  tmp2[10] = '\0';
7290  switch_stun_random_string(tmp1, 10, "0123456789");
7291  switch_stun_random_string(tmp2, 10, "0123456789");
7292 
7293  gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, NULL, 0);
7294 
7295  ice_out = &a_engine->ice_out;
7296 
7297  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ssrc:%u cname:%s\r\n", a_engine->ssrc, smh->cname);
7298  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ssrc:%u msid:%s a0\r\n", a_engine->ssrc, smh->msid);
7299  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ssrc:%u mslabel:%s\r\n", a_engine->ssrc, smh->msid);
7300  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ssrc:%u label:%sa0\r\n", a_engine->ssrc, smh->msid);
7301 
7302 
7303  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ice-ufrag:%s\r\n", ice_out->ufrag);
7304  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ice-pwd:%s\r\n", ice_out->pwd);
7305 
7306 
7307  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
7308  tmp1, ice_out->cands[0][0].transport, c1,
7309  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
7310  );
7311 
7312  if (!zstr(a_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) &&
7313  strcmp(a_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
7314  && a_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
7315 
7316  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ srflx raddr %s rport %d generation 0\r\n",
7317  tmp2, ice_out->cands[0][0].transport, c2,
7318  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
7319  a_engine->local_sdp_ip, a_engine->local_sdp_port
7320  );
7321  }
7322 
7324 
7325 
7326  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
7327  tmp1, ice_out->cands[0][0].transport, c1,
7328  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
7329  );
7330 
7331  if (!zstr(a_engine->local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) &&
7332  strcmp(a_engine->local_sdp_ip, ice_out->cands[0][1].con_addr)
7333  && a_engine->local_sdp_port != ice_out->cands[0][1].con_port) {
7334 
7335  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx raddr %s rport %d generation 0\r\n",
7336  tmp2, ice_out->cands[0][0].transport, c2,
7337  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
7338  a_engine->local_sdp_ip, a_engine->local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
7339  );
7340  }
7341  }
7342 
7343 
7344 
7345 #ifdef GOOGLE_ICE
7346  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ice-options:google-ice\r\n");
7347 #endif
7348  }
7349 
7350 
7351  if (secure && !switch_channel_test_flag(session->channel, CF_DTLS)) {
7352  int i;
7353 
7354  for (i = 0; smh->crypto_suite_order[i] != CRYPTO_INVALID; i++) {
7356 
7357  if ((a_engine->crypto_type == j || a_engine->crypto_type == CRYPTO_INVALID) && !zstr(a_engine->ssec[j].local_crypto_key)) {
7358  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=crypto:%s\r\n", a_engine->ssec[j].local_crypto_key);
7359  }
7360  }
7361  //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\r\n");
7362  }
7363 
7364  if (cng_type) {
7365  for (i = 0; i < smh->num_rates; i++) {
7366  //if (smh->rates[i] == 8000) {
7367  // switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d CN/%d\r\n", cng_type, smh->rates[i]);
7368  //} else {
7369  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d CN/%d\r\n", smh->cng_ianacodes[i], smh->rates[i]);
7370  //}
7371  }
7372  } else {
7374  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=silenceSupp:off - - - -\r\n");
7375  }
7376  }
7377 
7378  if (append_audio) {
7379  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "%s%s", append_audio, end_of(append_audio) == '\n' ? "" : "\r\n");
7380  }
7381 
7382  if (!cur_ptime) {
7383  cur_ptime = ptime;
7384  }
7385 
7386  if (!noptime && cur_ptime) {
7387  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ptime:%d\r\n", cur_ptime);
7388  }
7389 
7390  local_sdp_audio_zrtp_hash = switch_core_media_get_zrtp_hash(session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_TRUE);
7391 
7392  if (local_sdp_audio_zrtp_hash) {
7393  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Adding audio a=zrtp-hash:%s\n", local_sdp_audio_zrtp_hash);
7394  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=zrtp-hash:%s\r\n", local_sdp_audio_zrtp_hash);
7395  }
7396 
7397  if (!zstr(sr)) {
7398  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=%s\r\n", sr);
7399  }
7400 }
7401 
7402 //?
7404 {
7405  const char *val;
7406  switch_media_handle_t *smh;
7407 
7408  switch_assert(session);
7409 
7410  if (!(smh = session->media_handle)) {
7411  return;
7412  }
7413 
7414  if ((val = switch_channel_get_variable(session->channel, "dtmf_type"))) {
7415  if (!strcasecmp(val, "rfc2833")) {
7416  smh->mparams->dtmf_type = DTMF_2833;
7417  } else if (!strcasecmp(val, "info")) {
7418  smh->mparams->dtmf_type = DTMF_INFO;
7419  } else if (!strcasecmp(val, "none")) {
7420  smh->mparams->dtmf_type = DTMF_NONE;
7421  }
7422  }
7423 }
7424 
7425 //?
7427 {
7428  sdp_media_t *m;
7429  sdp_parser_t *parser = NULL;
7430  sdp_session_t *sdp;
7431 
7432  if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
7433  return SWITCH_STATUS_FALSE;
7434  }
7435 
7436  if (!(sdp = sdp_session(parser))) {
7437  sdp_parser_free(parser);
7438  return SWITCH_STATUS_FALSE;
7439  }
7440 
7443 
7444  for (m = sdp->sdp_media; m; m = m->m_next) {
7445  if (m->m_proto == sdp_proto_rtp) {
7446  sdp_rtpmap_t *map;
7447 
7448  for (map = m->m_rtpmaps; map; map = map->rm_next) {
7449  if (map->rm_encoding) {
7450  char buf[25] = "";
7451  char key[128] = "";
7452  char *br = NULL;
7453 
7454  if (map->rm_fmtp) {
7455  if ((br = strstr(map->rm_fmtp, "bitrate="))) {
7456  br += 8;
7457  }
7458  }
7459 
7460  switch_snprintf(buf, sizeof(buf), "%d", map->rm_pt);
7461 
7462  if (br) {
7463  switch_snprintf(key, sizeof(key), "%s:%s", map->rm_encoding, br);
7464  } else {
7465  switch_snprintf(key, sizeof(key), "%s", map->rm_encoding);
7466  }
7467 
7469 
7470  if (map->rm_fmtp) {
7471  switch_event_add_header_string(*fmtp, SWITCH_STACK_BOTTOM, key, map->rm_fmtp);
7472  }
7473  }
7474  }
7475  }
7476  }
7477 
7478  sdp_parser_free(parser);
7479 
7480  return SWITCH_STATUS_SUCCESS;
7481 
7482 }
7483 
7484 //?
7486 {
7487  switch_media_handle_t *smh;
7488 
7489  switch_assert(session);
7490 
7491  if (!(smh = session->media_handle)) {
7492  return;
7493  }
7494 
7495  if (smh->sdp_mutex) switch_mutex_lock(smh->sdp_mutex);
7496  smh->mparams->local_sdp_str = dup ? switch_core_session_strdup(session, sdp_str) : (char *) sdp_str;
7497  switch_channel_set_variable(session->channel, "rtp_local_sdp_str", smh->mparams->local_sdp_str);
7498  if (smh->sdp_mutex) switch_mutex_unlock(smh->sdp_mutex);
7499 }
7500 
7501 static void add_fb(char *buf, uint32_t buflen, int pt, int fir, int nack, int pli, int tmmbr)
7502 {
7503  if (fir) {
7504  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp-fb:%d ccm fir\r\n", pt);
7505  }
7506 
7507  if (tmmbr) {
7508  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp-fb:%d ccm tmmbr\r\n", pt);
7509  }
7510 
7511  if (nack) {
7512  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp-fb:%d nack\r\n", pt);
7513  }
7514 
7515  if (pli) {
7516  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp-fb:%d nack pli\r\n", pt);
7517  }
7518 
7519 }
7520 
7521 //?
7522 #define SDPBUFLEN 65536
7523 SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *session, switch_sdp_type_t sdp_type, const char *ip, switch_port_t port, const char *sr, int force)
7524 {
7525  char *buf;
7526  int ptime = 0;
7527  uint32_t rate = 0;
7528  uint32_t v_port;
7529  int use_cng = 1;
7530  const char *val;
7531  const char *family;
7532  const char *pass_fmtp = switch_channel_get_variable(session->channel, "rtp_video_fmtp");
7533  const char *ov_fmtp = switch_channel_get_variable(session->channel, "rtp_force_video_fmtp");
7534  const char *append_audio = switch_channel_get_variable(session->channel, "rtp_append_audio_sdp");
7535  const char *append_video = switch_channel_get_variable(session->channel, "rtp_append_video_sdp");
7536  char srbuf[128] = "";
7537  const char *var_val;
7538  const char *username;
7539  const char *fmtp_out;
7540  const char *fmtp_out_var = switch_channel_get_variable(session->channel, "rtp_force_audio_fmtp");
7541  switch_event_t *map = NULL, *ptmap = NULL;
7542  //const char *b_sdp = NULL;
7543  //const char *local_audio_crypto_key = switch_core_session_local_crypto_key(session, SWITCH_MEDIA_TYPE_AUDIO);
7544  const char *local_sdp_audio_zrtp_hash = switch_core_media_get_zrtp_hash(session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_TRUE);
7545  const char *local_sdp_video_zrtp_hash = switch_core_media_get_zrtp_hash(session, SWITCH_MEDIA_TYPE_VIDEO, SWITCH_TRUE);
7546  const char *tmp;
7547  switch_rtp_engine_t *a_engine, *v_engine;
7548  switch_media_handle_t *smh;
7549  ice_t *ice_out;
7550  //int vp8 = 0;
7551  //int red = 0;
7552  payload_map_t *pmap;
7553  int is_outbound = switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND;
7554  const char *vbw;
7555  int bw = 256;
7556  uint8_t fir = 0, nack = 0, pli = 0, tmmbr = 0;
7557 
7558  switch_assert(session);
7559 
7560  if (!(smh = session->media_handle)) {
7561  return;
7562  }
7563 
7564  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
7565  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
7566 
7567  if (switch_true(switch_channel_get_variable(session->channel, "rtcp_mux"))) {
7568  a_engine->rtcp_mux = 1;
7569  v_engine->rtcp_mux = 1;
7570  }
7571 
7572  if (!smh->mparams->rtcp_audio_interval_msec) {
7573  smh->mparams->rtcp_audio_interval_msec = (char *)switch_channel_get_variable(session->channel, "rtcp_audio_interval_msec");
7574  }
7575 
7576  if (!smh->mparams->rtcp_video_interval_msec) {
7577  smh->mparams->rtcp_video_interval_msec = (char *)switch_channel_get_variable(session->channel, "rtcp_video_interval_msec");
7578  }
7579 
7580  if (dtls_ok(session) && (tmp = switch_channel_get_variable(smh->session->channel, "webrtc_enable_dtls")) && switch_false(tmp)) {
7583  }
7584 
7585  if (switch_channel_test_flag(session->channel, CF_PROXY_OFF) && (tmp = switch_channel_get_variable(smh->session->channel, "uuid_media_secure_media"))) {
7586  switch_channel_set_variable(smh->session->channel, "rtp_secure_media", tmp);
7589  }
7590 
7591  if (is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING) ||
7592  switch_channel_test_flag(session->channel, CF_3PCC)) {
7593  if (!switch_channel_test_flag(session->channel, CF_AVPF) &&
7594  switch_true(switch_channel_get_variable(session->channel, "media_webrtc"))) {
7595  switch_channel_set_flag(session->channel, CF_AVPF);
7596  switch_channel_set_flag(session->channel, CF_ICE);
7599  }
7600 
7601  if ( switch_rtp_has_dtls() && dtls_ok(session)) {
7602  if (switch_channel_test_flag(session->channel, CF_AVPF) ||
7603  switch_true(switch_channel_get_variable(smh->session->channel, "rtp_use_dtls"))) {
7607  }
7608  }
7611  }
7612 
7613  fmtp_out = a_engine->cur_payload_map->fmtp_out;
7614  username = smh->mparams->sdp_username;
7615 
7616 
7617  switch_zmalloc(buf, SDPBUFLEN);
7618 
7620 
7622  ((val = switch_channel_get_variable(session->channel, "supress_cng")) && switch_true(val)) ||
7623  ((val = switch_channel_get_variable(session->channel, "suppress_cng")) && switch_true(val))) {
7624  use_cng = 0;
7625  smh->mparams->cng_pt = 0;
7626  }
7627 
7628 
7629 
7630 
7631  if (!smh->payload_space) {
7632  int i;
7633 
7634  /* it could be 98 but chrome reserves 98 and 99 for some internal stuff even though they should not.
7635  Everyone expects dtmf to be at 101 and Its not worth the trouble so we'll start at 102 */
7636  smh->payload_space = 102;
7637  memset(smh->rates, 0, sizeof(smh->rates));
7638  smh->num_rates = 0;
7639 
7640  for (i = 0; i < smh->mparams->num_codecs; i++) {
7641  int j;
7642  smh->ianacodes[i] = smh->codecs[i]->ianacode;
7643 
7644  if (smh->codecs[i]->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
7645  continue;
7646  }
7647 
7648  if (sdp_type == SDP_TYPE_REQUEST) {
7649  for (j = 0; j < SWITCH_MAX_CODECS; j++) {
7650  if (smh->rates[j] == 0) {
7651  break;
7652  }
7653 
7654  if (smh->rates[j] == smh->codecs[i]->samples_per_second) {
7655  goto do_next;
7656  }
7657  }
7658 
7659  smh->rates[smh->num_rates++] = smh->codecs[i]->samples_per_second;
7660  }
7661 
7662  do_next:
7663  continue;
7664  }
7665 
7666  if (sdp_type == SDP_TYPE_REQUEST) {
7667  switch_core_session_t *orig_session = NULL;
7668 
7669  switch_core_session_get_partner(session, &orig_session);
7670 
7671  for (i = 0; i < smh->mparams->num_codecs; i++) {
7672  const switch_codec_implementation_t *imp = smh->codecs[i];
7673  switch_payload_t orig_pt = 0;
7674  char *orig_fmtp = NULL;
7675 
7676  //smh->ianacodes[i] = imp->ianacode;
7677 
7678  if (smh->ianacodes[i] > 64) {
7679  if (smh->mparams->dtmf_type == DTMF_2833 && smh->mparams->te > 95 && smh->mparams->te == smh->payload_space) {
7680  smh->payload_space++;
7681  }
7683  smh->mparams->cng_pt && use_cng && smh->mparams->cng_pt == smh->payload_space) {
7684  smh->payload_space++;
7685  }
7686 
7687  if (orig_session &&
7690  imp->iananame, imp->samples_per_second, &orig_pt, NULL, &orig_fmtp) == SWITCH_STATUS_SUCCESS) {
7691  if (orig_pt == smh->mparams->te) {
7692  smh->mparams->te = (switch_payload_t)smh->payload_space++;
7693  }
7694 
7695  smh->ianacodes[i] = orig_pt;
7696 
7697  if (orig_fmtp) {
7698  smh->fmtps[i] = switch_core_session_strdup(session, orig_fmtp);
7699  }
7700  } else {
7701  smh->ianacodes[i] = (switch_payload_t)smh->payload_space++;
7702  }
7703  }
7704 
7707  imp->iananame,
7708  imp->modname,
7709  NULL,
7710  sdp_type,
7711  smh->ianacodes[i],
7712  imp->samples_per_second,
7713  imp->microseconds_per_packet / 1000,
7714  imp->number_of_channels,
7715  SWITCH_FALSE);
7716  }
7717 
7718  for (i = 0; i < smh->num_rates; i++) {
7719  if (smh->rates[i] == 8000 || smh->num_rates == 1) {
7720  smh->dtmf_ianacodes[i] = smh->mparams->te;
7721  smh->cng_ianacodes[i] = smh->mparams->cng_pt;
7722  } else {
7723  int j = 0;
7724 
7725  for (j = 0; j < smh->mparams->num_codecs; j++) {
7726  if (smh->ianacodes[j] == smh->payload_space) {
7727  smh->payload_space++;
7728  break;
7729  }
7730  }
7731 
7732  smh->dtmf_ianacodes[i] = (switch_payload_t)smh->payload_space++;
7733  smh->cng_ianacodes[i] = (switch_payload_t)smh->payload_space++;
7734  }
7735  }
7736 
7737 
7738  if (orig_session) {
7739  switch_core_session_rwunlock(orig_session);
7740  }
7741  }
7742  }
7743 
7744  if (fmtp_out_var) {
7745  fmtp_out = fmtp_out_var;
7746  }
7747 
7748  val = switch_channel_get_variable(session->channel, "verbose_sdp");
7749 
7750  if (!val || switch_true(val)) {
7751  switch_channel_set_flag(session->channel, CF_VERBOSE_SDP);
7752  }
7753 
7754  if (!force && !ip && zstr(sr)
7755  && (switch_channel_test_flag(session->channel, CF_PROXY_MODE) || switch_channel_test_flag(session->channel, CF_PROXY_MEDIA))) {
7756  switch_safe_free(buf);
7757  return;
7758  }
7759 
7760  if (!ip) {
7761  if (!(ip = a_engine->adv_sdp_ip)) {
7762  ip = a_engine->proxy_sdp_ip;
7763  }
7764  }
7765 
7766  if (!ip) {
7768  switch_safe_free(buf);
7769  return;
7770  }
7771 
7772  if (!port) {
7773  if (!(port = a_engine->adv_sdp_port)) {
7774  port = a_engine->proxy_sdp_port;
7775  }
7776  }
7777 
7778  if (!port) {
7779  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%s NO PORT!\n", switch_channel_get_name(session->channel));
7780  switch_safe_free(buf);
7781  return;
7782  }
7783 
7784  //if (!a_engine->cur_payload_map->rm_encoding && (b_sdp = switch_channel_get_variable(session->channel, SWITCH_B_SDP_VARIABLE))) {
7785  //switch_core_media_sdp_map(b_sdp, &map, &ptmap);
7786  //}
7787 
7788  if (zstr(sr)) {
7789  if (a_engine->smode == SWITCH_MEDIA_FLOW_SENDONLY) {
7790  sr = "sendonly";
7791  } else if (a_engine->smode == SWITCH_MEDIA_FLOW_RECVONLY) {
7792  sr = "recvonly";
7793  } else {
7794  sr = "sendrecv";
7795  }
7796 
7797  if ((var_val = switch_channel_get_variable(session->channel, "origination_audio_mode"))) {
7798  if (!strcasecmp(sr, "sendonly") || !strcasecmp(sr, "recvonly") || !strcasecmp(sr, "sendrecv")) {
7799  sr = var_val;
7800  }
7801  switch_channel_set_variable(session->channel, "origination_audio_mode", NULL);
7802  }
7803 
7804  if (zstr(sr)) {
7805  sr = "sendrecv";
7806  }
7807  }
7808 
7809  if (!smh->owner_id) {
7810  smh->owner_id = (uint32_t) switch_epoch_time_now(NULL) - port;
7811  }
7812 
7813  if (!smh->session_id) {
7814  smh->session_id = smh->owner_id;
7815  }
7816 
7817  if (switch_true(switch_channel_get_variable_dup(session->channel, "drop_dtmf", SWITCH_FALSE, -1))) {
7818  switch_channel_set_flag(session->channel, CF_DROP_DTMF);
7819  }
7820 
7821  smh->session_id++;
7822 
7823  if ((smh->mparams->ndlb & SM_NDLB_SENDRECV_IN_SESSION) ||
7824  ((var_val = switch_channel_get_variable(session->channel, "ndlb_sendrecv_in_session")) && switch_true(var_val))) {
7825  if (!zstr(sr)) {
7826  switch_snprintf(srbuf, sizeof(srbuf), "a=%s\r\n", sr);
7827  }
7828  sr = NULL;
7829  }
7830 
7831  family = strchr(ip, ':') ? "IP6" : "IP4";
7833  "v=0\r\n"
7834  "o=%s %010u %010u IN %s %s\r\n"
7835  "s=%s\r\n"
7836  "c=IN %s %s\r\n"
7837  "t=0 0\r\n"
7838  "%s",
7839  username, smh->owner_id, smh->session_id, family, ip, username, family, ip, srbuf);
7840 
7841 
7842  if (a_engine->rmode == SWITCH_MEDIA_FLOW_DISABLED) {
7843  goto video;
7844  }
7845 
7847  gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, ip, port);
7848  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=msid-semantic: WMS %s\r\na=end-of-candidates\r\n", smh->msid);
7849  }
7850 
7851  if (a_engine->codec_negotiated) {
7852  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=audio %d %s", port,
7853  get_media_profile_name(session, !a_engine->no_crypto &&
7854  (switch_channel_test_flag(session->channel, CF_DTLS) || a_engine->crypto_type != CRYPTO_INVALID)));
7855 
7856 
7857  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", a_engine->cur_payload_map->pt);
7858 
7859 
7862  for (pmap = a_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
7863  if (pmap->pt != a_engine->cur_payload_map->pt) {
7864  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", pmap->pt);
7865  }
7866  }
7868  }
7869 
7871  switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF)) && smh->mparams->te > 95) {
7872  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", smh->mparams->te);
7873  }
7874 
7875  if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && smh->mparams->cng_pt && use_cng) {
7876  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", smh->mparams->cng_pt);
7877  }
7878 
7879  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\r\n");
7880 
7881 
7882  rate = a_engine->cur_payload_map->adv_rm_rate;
7883 
7884  if (!a_engine->cur_payload_map->adv_channels) {
7886  }
7887 
7888  if (a_engine->cur_payload_map->adv_channels > 1) {
7889  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\r\n",
7890  a_engine->cur_payload_map->agreed_pt, a_engine->cur_payload_map->rm_encoding, rate, a_engine->cur_payload_map->adv_channels);
7891  } else {
7892  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\r\n",
7893  a_engine->cur_payload_map->agreed_pt, a_engine->cur_payload_map->rm_encoding, rate);
7894  }
7895 
7896  if (fmtp_out) {
7897  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\r\n", a_engine->cur_payload_map->agreed_pt, fmtp_out);
7898  }
7899 
7902  for (pmap = a_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
7903  if (pmap->pt != a_engine->cur_payload_map->pt) {
7904  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\r\n",
7905  pmap->pt, pmap->iananame,
7906  pmap->rate);
7907  }
7908  }
7910  }
7911 
7912 
7913  if (a_engine->read_codec.implementation && !ptime) {
7914  ptime = a_engine->read_codec.implementation->microseconds_per_packet / 1000;
7915  }
7916 
7917 
7919  switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF))
7920  && smh->mparams->te > 95) {
7921 
7922  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
7923  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d telephone-event/%d\r\n",
7924  smh->mparams->te, smh->mparams->te_rate);
7925  } else {
7926  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d telephone-event/%d\na=fmtp:%d 0-16\r\n",
7927  smh->mparams->te, smh->mparams->te_rate, smh->mparams->te);
7928  }
7929  }
7930 
7932  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=silenceSupp:off - - - -\r\n");
7933  } else if (smh->mparams->cng_pt && use_cng) {
7934  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d CN/%lu\r\n", smh->mparams->cng_pt, smh->mparams->cng_rate);
7935 
7936  if (!a_engine->codec_negotiated) {
7937  smh->mparams->cng_pt = 0;
7938  }
7939  }
7940 
7941  if (append_audio) {
7942  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s%s", append_audio, end_of(append_audio) == '\n' ? "" : "\r\n");
7943  }
7944 
7945  if (ptime) {
7946  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ptime:%d\r\n", ptime);
7947  }
7948 
7949 
7950  if (local_sdp_audio_zrtp_hash) {
7951  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Adding audio a=zrtp-hash:%s\r\n",
7952  local_sdp_audio_zrtp_hash);
7953  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=zrtp-hash:%s\r\n",
7954  local_sdp_audio_zrtp_hash);
7955  }
7956 
7957  if (!zstr(sr)) {
7958  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=%s\r\n", sr);
7959  }
7960 
7961 
7962  if (!zstr(a_engine->local_dtls_fingerprint.type)) {
7963  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fingerprint:%s %s\na=setup:%s\r\n",
7964  a_engine->local_dtls_fingerprint.type,
7965  a_engine->local_dtls_fingerprint.str, get_setup(a_engine, session, sdp_type));
7966  }
7967 
7968  if (smh->mparams->rtcp_audio_interval_msec) {
7969  if (a_engine->rtcp_mux > 0) {
7970  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp-mux\r\n");
7971  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\r\n", port, family, ip);
7972  } else {
7973  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\r\n", port + 1, family, ip);
7974  }
7975  }
7976 
7977  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\r\n", a_engine->ssrc);
7978 
7979  if (a_engine->ice_out.cands[0][0].ready) {
7980  char tmp1[11] = "";
7981  char tmp2[11] = "";
7982  uint32_t c1 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 1);
7983  //uint32_t c2 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 2);
7984  //uint32_t c3 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 1);
7985  //uint32_t c4 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 2);
7986 
7987  uint32_t c2 = c1 - 1;
7988  uint32_t c3 = c1 - 2;
7989  uint32_t c4 = c1 - 3;
7990 
7991  tmp1[10] = '\0';
7992  tmp2[10] = '\0';
7993  switch_stun_random_string(tmp1, 10, "0123456789");
7994  switch_stun_random_string(tmp2, 10, "0123456789");
7995 
7996  ice_out = &a_engine->ice_out;
7997 
7998 
7999  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-ufrag:%s\r\n", ice_out->ufrag);
8000  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-pwd:%s\r\n", ice_out->pwd);
8001 
8002 
8003  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
8004  tmp1, ice_out->cands[0][0].transport, c1,
8005  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
8006  );
8007 
8008  if (!zstr(a_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) &&
8009  strcmp(a_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
8010  && a_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
8011 
8012  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ srflx raddr %s rport %d generation 0\r\n",
8013  tmp2, ice_out->cands[0][0].transport, c3,
8014  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
8015  a_engine->local_sdp_ip, a_engine->local_sdp_port
8016  );
8017  }
8018 
8019 
8020  if (a_engine->rtcp_mux < 1 || is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING)) {
8021 
8022  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
8023  tmp1, ice_out->cands[0][0].transport, c2,
8024  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
8025  );
8026 
8027 
8028 
8029  if (!zstr(a_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) &&
8030  strcmp(a_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
8031  && a_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
8032 
8033  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx raddr %s rport %d generation 0\r\n",
8034  tmp2, ice_out->cands[0][0].transport, c4,
8035  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
8036  a_engine->local_sdp_ip, a_engine->local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
8037  );
8038  }
8039  }
8040 
8041 
8042  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u cname:%s\r\n", a_engine->ssrc, smh->cname);
8043  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u msid:%s a0\r\n", a_engine->ssrc, smh->msid);
8044  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u mslabel:%s\r\n", a_engine->ssrc, smh->msid);
8045  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u label:%sa0\r\n", a_engine->ssrc, smh->msid);
8046 
8047 
8048 #ifdef GOOGLE_ICE
8049  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-options:google-ice\r\n");
8050 #endif
8051  }
8052 
8053  if (a_engine->crypto_type != CRYPTO_INVALID && !switch_channel_test_flag(session->channel, CF_DTLS) &&
8054  !zstr(a_engine->ssec[a_engine->crypto_type].local_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) {
8055 
8056  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\r\n", a_engine->ssec[a_engine->crypto_type].local_crypto_key);
8057  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=encryption:optional\r\n");
8058  }
8059 
8060  if (a_engine->reject_avp) {
8061  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=audio 0 RTP/AVP 19\r\n");
8062  }
8063 
8064  } else if (smh->mparams->num_codecs) {
8065  int i;
8066  int cur_ptime = 0, this_ptime = 0, cng_type = 0;
8067  const char *mult;
8068 
8069  if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && smh->mparams->cng_pt && use_cng) {
8070  cng_type = smh->mparams->cng_pt;
8071 
8072  if (!a_engine->codec_negotiated) {
8073  smh->mparams->cng_pt = 0;
8074  }
8075  }
8076 
8077  mult = switch_channel_get_variable(session->channel, "sdp_m_per_ptime");
8078 
8079  if (switch_channel_test_flag(session->channel, CF_AVPF) || (mult && switch_false(mult))) {
8080  char *bp = buf;
8081  int both = (switch_channel_test_flag(session->channel, CF_AVPF) || switch_channel_test_flag(session->channel, CF_DTLS)) ? 0 : 1;
8082 
8083  if ((!a_engine->no_crypto && switch_channel_test_flag(session->channel, CF_SECURE)) ||
8084  switch_channel_test_flag(session->channel, CF_DTLS)) {
8085  generate_m(session, buf, SDPBUFLEN, port, family, ip, 0, append_audio, sr, use_cng, cng_type, map, 1, sdp_type);
8086  bp = (buf + strlen(buf));
8087 
8088  if (smh->crypto_mode == CRYPTO_MODE_MANDATORY) {
8089  both = 0;
8090  }
8091 
8092  }
8093 
8094  if (both) {
8095  generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, 0, append_audio, sr, use_cng, cng_type, map, 0, sdp_type);
8096  }
8097 
8098  } else {
8099 
8100  for (i = 0; i < smh->mparams->num_codecs; i++) {
8101  const switch_codec_implementation_t *imp = smh->codecs[i];
8102 
8103  if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
8104  continue;
8105  }
8106 
8107  this_ptime = imp->microseconds_per_packet / 1000;
8108 
8109  if (!strcasecmp(imp->iananame, "ilbc") || !strcasecmp(imp->iananame, "isac")) {
8110  this_ptime = 20;
8111  }
8112 
8113  if (cur_ptime != this_ptime) {
8114  char *bp = buf;
8115  int both = 1;
8116 
8117  cur_ptime = this_ptime;
8118 
8119  if ((!a_engine->no_crypto && switch_channel_test_flag(session->channel, CF_SECURE)) ||
8120  switch_channel_test_flag(session->channel, CF_DTLS)) {
8121  generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, cur_ptime, append_audio, sr, use_cng, cng_type, map, 1, sdp_type);
8122  bp = (buf + strlen(buf));
8123 
8124  if (smh->crypto_mode == CRYPTO_MODE_MANDATORY) {
8125  both = 0;
8126  }
8127  }
8128 
8129  if (switch_channel_test_flag(session->channel, CF_AVPF) || switch_channel_test_flag(session->channel, CF_DTLS)) {
8130  both = 0;
8131  }
8132 
8133  if (both) {
8134  generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, cur_ptime, append_audio, sr, use_cng, cng_type, map, 0, sdp_type);
8135  }
8136  }
8137 
8138  }
8139  }
8140 
8141  }
8142 
8143  video:
8144 
8145  if (!switch_channel_test_flag(session->channel, CF_VIDEO_POSSIBLE)) {
8146  if (switch_channel_test_flag(session->channel, CF_VIDEO_SDP_RECVD)) {
8147  switch_channel_clear_flag(session->channel, CF_VIDEO_SDP_RECVD);
8148  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=video 0 %s 19\r\n",
8149  get_media_profile_name(session,
8150  (switch_channel_test_flag(session->channel, CF_SECURE)
8151  && switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) ||
8152  a_engine->crypto_type != CRYPTO_INVALID || switch_channel_test_flag(session->channel, CF_DTLS)));
8153  }
8154  } else {
8155  if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
8157  v_engine->no_crypto = 1;
8158  }
8159  }
8160 
8161 
8162  if (!v_engine->local_sdp_port) {
8164  }
8165 
8166  //if (switch_channel_test_flag(session->channel, CF_AVPF)) {
8167  // switch_media_handle_set_media_flag(smh, SCMF_MULTI_ANSWER_VIDEO);
8168  //}
8169 
8170  if ((v_port = v_engine->adv_sdp_port)) {
8171  int loops;
8172 
8173  for (loops = 0; loops < 2; loops++) {
8174 
8176  gen_ice(session, SWITCH_MEDIA_TYPE_VIDEO, ip, (switch_port_t)v_port);
8177  }
8178 
8179 
8180  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=video %d %s",
8181  v_port,
8182  get_media_profile_name(session,
8183  (loops == 0 && switch_channel_test_flag(session->channel, CF_SECURE)
8184  && switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND) ||
8185  a_engine->crypto_type != CRYPTO_INVALID || switch_channel_test_flag(session->channel, CF_DTLS)));
8186 
8187 
8188 
8189 
8190  /*****************************/
8191  if (v_engine->codec_negotiated) {
8192  payload_map_t *pmap;
8194  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", v_engine->cur_payload_map->agreed_pt);
8195 
8198  for (pmap = v_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
8199  if (pmap->pt != v_engine->cur_payload_map->pt && pmap->negotiated) {
8200  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", pmap->pt);
8201  }
8202  }
8204  }
8205 
8206  } else if (smh->mparams->num_codecs) {
8207  int i;
8208  int already_did[128] = { 0 };
8209  for (i = 0; i < smh->mparams->num_codecs; i++) {
8210  const switch_codec_implementation_t *imp = smh->codecs[i];
8211 
8212 
8213  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
8214  continue;
8215  }
8216 
8217  if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_INBOUND &&
8218  switch_channel_test_flag(session->channel, CF_NOVIDEO)) {
8219  continue;
8220  }
8221 
8222  if (smh->ianacodes[i] < 128) {
8223  if (already_did[smh->ianacodes[i]]) {
8224  continue;
8225  }
8226  already_did[smh->ianacodes[i]] = 1;
8227  }
8228 
8229  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", smh->ianacodes[i]);
8230 
8231  if (!ptime) {
8232  ptime = imp->microseconds_per_packet / 1000;
8233  }
8234  }
8235  }
8236 
8237  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\r\n");
8238 
8239 
8240  if (v_engine->codec_negotiated) {
8241  const char *of;
8242  payload_map_t *pmap;
8243 
8244  //if (!strcasecmp(v_engine->cur_payload_map->rm_encoding, "VP8")) {
8245  // vp8 = v_engine->cur_payload_map->pt;
8246  //}
8247 
8248  //if (!strcasecmp(v_engine->cur_payload_map->rm_encoding, "red")) {
8249  // red = v_engine->cur_payload_map->pt;
8250  //}
8251 
8252  rate = v_engine->cur_payload_map->rm_rate;
8253  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\r\n",
8254  v_engine->cur_payload_map->pt, v_engine->cur_payload_map->rm_encoding,
8255  v_engine->cur_payload_map->rm_rate);
8256 
8257 
8258  if (switch_channel_test_flag(session->channel, CF_RECOVERING)) {
8259  pass_fmtp = v_engine->cur_payload_map->rm_fmtp;
8260  } else {
8261 
8262  pass_fmtp = NULL;
8263 
8264  if (switch_channel_get_partner_uuid(session->channel)) {
8265  if ((of = switch_channel_get_variable_partner(session->channel, "rtp_video_fmtp"))) {
8266  pass_fmtp = of;
8267  }
8268  }
8269 
8270  if (ov_fmtp) {
8271  pass_fmtp = ov_fmtp;
8272  } else if (switch_true(switch_channel_get_variable_dup(session->channel, "rtp_mirror_fmtp", SWITCH_FALSE, -1))) {
8273  pass_fmtp = switch_channel_get_variable(session->channel, "rtp_video_fmtp");
8274  }
8275  }
8276 
8277  if (pass_fmtp) {
8278  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\r\n", v_engine->cur_payload_map->pt, pass_fmtp);
8279  }
8280 
8281 
8284  for (pmap = v_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
8285  if (pmap->pt != v_engine->cur_payload_map->pt && pmap->negotiated) {
8286  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\r\n",
8287  pmap->pt, pmap->iananame, pmap->rate);
8288 
8289  }
8290  }
8292  }
8293 
8294 
8295  if (append_video) {
8296  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s%s", append_video, end_of(append_video) == '\n' ? "" : "\r\n");
8297  }
8298 
8299  if (v_engine->smode == SWITCH_MEDIA_FLOW_SENDONLY) {
8300  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=sendonly\r\n");
8301  } else if (v_engine->smode == SWITCH_MEDIA_FLOW_RECVONLY) {
8302  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=recvonly\r\n");
8303  }
8304 
8305  } else if (smh->mparams->num_codecs) {
8306  int i;
8307  int already_did[128] = { 0 };
8308 
8309  for (i = 0; i < smh->mparams->num_codecs; i++) {
8310  const switch_codec_implementation_t *imp = smh->codecs[i];
8311  char *fmtp = NULL;
8312  uint32_t ianacode = smh->ianacodes[i];
8313  int channels;
8314 
8315  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
8316  continue;
8317  }
8318 
8319  if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_INBOUND &&
8320  switch_channel_test_flag(session->channel, CF_NOVIDEO)) {
8321  continue;
8322  }
8323 
8324  if (ianacode < 128) {
8325  if (already_did[ianacode]) {
8326  continue;
8327  }
8328  already_did[ianacode] = 1;
8329  }
8330 
8331  if (!rate) {
8332  rate = imp->samples_per_second;
8333  }
8334 
8335  channels = get_channels(imp->iananame, imp->number_of_channels);
8336 
8337  //if (!strcasecmp(imp->iananame, "VP8")) {
8338  // vp8 = ianacode;
8339  //}
8340 
8341  //if (!strcasecmp(imp->iananame, "red")) {
8342  // red = ianacode;
8343  //}
8344 
8345  if (channels > 1) {
8346  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\r\n", ianacode, imp->iananame,
8347  imp->samples_per_second, channels);
8348  } else {
8349  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\r\n", ianacode, imp->iananame,
8350  imp->samples_per_second);
8351  }
8352 
8353  if (!zstr(ov_fmtp)) {
8354  fmtp = (char *) ov_fmtp;
8355  } else {
8356 
8357  if (map) {
8358  fmtp = switch_event_get_header(map, imp->iananame);
8359  }
8360 
8361  if (smh->fmtps[i]) {
8362  fmtp = smh->fmtps[i];
8363  }
8364 
8365  if (zstr(fmtp)) fmtp = imp->fmtp;
8366 
8367  if (zstr(fmtp)) fmtp = (char *) pass_fmtp;
8368  }
8369 
8370  if (!zstr(fmtp) && strcasecmp(fmtp, "_blank_")) {
8371  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\r\n", ianacode, fmtp);
8372  }
8373  }
8374 
8375  }
8376 
8377  if ((is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING))
8380  }
8381 
8382 
8383  if (!zstr(v_engine->local_dtls_fingerprint.type)) {
8384  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fingerprint:%s %s\na=setup:%s\r\n", v_engine->local_dtls_fingerprint.type,
8385  v_engine->local_dtls_fingerprint.str, get_setup(v_engine, session, sdp_type));
8386  }
8387 
8388 
8389  if (smh->mparams->rtcp_video_interval_msec) {
8390  if (v_engine->rtcp_mux > 0) {
8391  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp-mux\r\n");
8392  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\r\n", v_port, family, ip);
8393  } else {
8394  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\r\n", v_port + 1, family, ip);
8395  }
8396  }
8397 
8398 
8399  if (!(vbw = switch_channel_get_variable(smh->session->channel, "rtp_video_max_bandwidth"))) {
8400  vbw = switch_channel_get_variable(smh->session->channel, "rtp_video_max_bandwidth_in");
8401  }
8402 
8403  if (!vbw) {
8404  vbw = "1mb";
8405  }
8406 
8408 
8409  if (bw > 0) {
8410  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "b=AS:%d\r\n", bw);
8411  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "b=TIAS:%d\r\n", bw);
8412  }
8413 
8414  if (sdp_type == SDP_TYPE_REQUEST) {
8415  fir++;
8416  pli++;
8417  nack++;
8418  tmmbr++;
8419  }
8420 
8421  /* DFF nack pli etc */
8422  //nack = v_engine->nack = 0;
8423  //pli = v_engine->pli = 0;
8424 
8425 
8426  if (v_engine->codec_negotiated) {
8427  add_fb(buf, SDPBUFLEN, v_engine->cur_payload_map->agreed_pt, v_engine->fir || fir,
8428  v_engine->nack || nack, v_engine->pli || pli, v_engine->tmmbr || tmmbr);
8429 
8432  for (pmap = v_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
8433  if (pmap->pt != v_engine->cur_payload_map->pt && pmap->negotiated) {
8434  add_fb(buf, SDPBUFLEN, pmap->pt, v_engine->fir || fir, v_engine->nack || nack, v_engine->pli || pli, v_engine->tmmbr || tmmbr);
8435  }
8436  }
8438  }
8439 
8440  } else if (smh->mparams->num_codecs) {
8441  int i;
8442  int already_did[128] = { 0 };
8443  for (i = 0; i < smh->mparams->num_codecs; i++) {
8444  const switch_codec_implementation_t *imp = smh->codecs[i];
8445 
8446 
8447  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
8448  continue;
8449  }
8450 
8451  if (switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_INBOUND &&
8452  switch_channel_test_flag(session->channel, CF_NOVIDEO)) {
8453  continue;
8454  }
8455 
8456  if (smh->ianacodes[i] < 128) {
8457  if (already_did[smh->ianacodes[i]]) {
8458  continue;
8459  }
8460  already_did[smh->ianacodes[i]] = 1;
8461  }
8462 
8463  add_fb(buf, SDPBUFLEN, smh->ianacodes[i], v_engine->fir || fir, v_engine->nack || nack, v_engine->pli || pli, v_engine->pli || pli);
8464  }
8465 
8466  }
8467 
8468  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\r\n", v_engine->ssrc);
8469 
8470  if (v_engine->ice_out.cands[0][0].ready) {
8471  char tmp1[11] = "";
8472  char tmp2[11] = "";
8473  uint32_t c1 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 1);
8474  //uint32_t c2 = (2^24)*126 + (2^8)*65535 + (2^0)*(256 - 2);
8475  //uint32_t c3 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 1);
8476  //uint32_t c4 = (2^24)*126 + (2^8)*65534 + (2^0)*(256 - 2);
8477 
8478  uint32_t c2 = c1 - 1;
8479  uint32_t c3 = c1 - 2;
8480  uint32_t c4 = c1 - 3;
8481 
8482  tmp1[10] = '\0';
8483  tmp2[10] = '\0';
8484  switch_stun_random_string(tmp1, 10, "0123456789");
8485  switch_stun_random_string(tmp2, 10, "0123456789");
8486 
8487  ice_out = &v_engine->ice_out;
8488 
8489 
8490  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u cname:%s\r\n", v_engine->ssrc, smh->cname);
8491  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u msid:%s v0\r\n", v_engine->ssrc, smh->msid);
8492  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u mslabel:%s\r\n", v_engine->ssrc, smh->msid);
8493  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u label:%sv0\r\n", v_engine->ssrc, smh->msid);
8494 
8495 
8496 
8497  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-ufrag:%s\r\n", ice_out->ufrag);
8498  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-pwd:%s\r\n", ice_out->pwd);
8499 
8500 
8501  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
8502  tmp1, ice_out->cands[0][0].transport, c1,
8503  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
8504  );
8505 
8506  if (!zstr(v_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) &&
8507  strcmp(v_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
8508  && v_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
8509 
8510  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ srflx raddr %s rport %d generation 0\r\n",
8511  tmp2, ice_out->cands[0][0].transport, c3,
8512  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
8513  v_engine->local_sdp_ip, v_engine->local_sdp_port
8514  );
8515  }
8516 
8517 
8518  if (v_engine->rtcp_mux < 1 || is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING)) {
8519 
8520  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
8521  tmp1, ice_out->cands[0][0].transport, c2,
8522  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
8523  );
8524 
8525 
8526  if (!zstr(v_engine->local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) &&
8527  strcmp(v_engine->local_sdp_ip, ice_out->cands[0][1].con_addr)
8528  && v_engine->local_sdp_port != ice_out->cands[0][1].con_port) {
8529 
8530  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx generation 0\r\n",
8531  tmp2, ice_out->cands[0][0].transport, c4,
8532  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1),
8533  v_engine->local_sdp_ip, v_engine->local_sdp_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
8534  );
8535  }
8536  }
8537 
8538 
8539 
8540 #ifdef GOOGLE_ICE
8541  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-options:google-ice\r\n");
8542 #endif
8543  }
8544 
8545 
8546 
8547  if (loops == 0 && switch_channel_test_flag(session->channel, CF_SECURE) && !switch_channel_test_flag(session->channel, CF_DTLS)) {
8548  int i;
8549 
8550  for (i = 0; smh->crypto_suite_order[i] != CRYPTO_INVALID; i++) {
8552 
8553  if ((a_engine->crypto_type == j || a_engine->crypto_type == CRYPTO_INVALID) && !zstr(a_engine->ssec[j].local_crypto_key)) {
8554  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\r\n", v_engine->ssec[j].local_crypto_key);
8555  }
8556  }
8557  //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\r\n");
8558  }
8559 
8560 
8561  if (local_sdp_video_zrtp_hash) {
8562  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Adding video a=zrtp-hash:%s\n", local_sdp_video_zrtp_hash);
8563  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=zrtp-hash:%s\r\n", local_sdp_video_zrtp_hash);
8564  }
8565 
8566 
8567  if (switch_channel_test_flag(session->channel, CF_DTLS) ||
8568  !switch_channel_test_flag(session->channel, CF_SECURE) ||
8570  break;
8571  }
8572  }
8573  }
8574 
8575  }
8576 
8577 
8578  if (map) {
8579  switch_event_destroy(&map);
8580  }
8581 
8582  if (ptmap) {
8583  switch_event_destroy(&ptmap);
8584  }
8585 
8587 
8588  switch_safe_free(buf);
8589 }
8590 
8591 
8592 
8593 //?
8595 {
8596  const char *sdp_str;
8597  switch_rtp_engine_t *a_engine;
8598  switch_media_handle_t *smh;
8599 
8600  switch_assert(session);
8601 
8602  if (!(smh = session->media_handle)) {
8603  return;
8604  }
8605 
8606  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
8607 
8608  if ((sdp_str = switch_channel_get_variable(session->channel, SWITCH_B_SDP_VARIABLE))) {
8609  sdp_parser_t *parser;
8610  sdp_session_t *sdp;
8611  sdp_media_t *m;
8612  sdp_connection_t *connection;
8613 
8614  if ((parser = sdp_parse(NULL, sdp_str, (int) strlen(sdp_str), 0))) {
8615  if ((sdp = sdp_session(parser))) {
8616  for (m = sdp->sdp_media; m; m = m->m_next) {
8617  if (m->m_type != sdp_media_audio || !m->m_port) {
8618  continue;
8619  }
8620 
8621  connection = sdp->sdp_connection;
8622  if (m->m_connections) {
8623  connection = m->m_connections;
8624  }
8625 
8626  if (connection) {
8627  a_engine->proxy_sdp_ip = switch_core_session_strdup(session, connection->c_address);
8628  }
8629  a_engine->proxy_sdp_port = (switch_port_t) m->m_port;
8630  if (a_engine->proxy_sdp_ip && a_engine->proxy_sdp_port) {
8631  break;
8632  }
8633  }
8634  }
8635  sdp_parser_free(parser);
8636  }
8637  switch_core_media_set_local_sdp(session, sdp_str, SWITCH_TRUE);
8638  }
8639 }
8640 
8641 
8642 //?
8644 {
8645  char buf[2048] = "";
8646  char max_buf[128] = "";
8647  char max_data[128] = "";
8648  const char *ip;
8649  uint32_t port;
8650  const char *family = "IP4";
8651  const char *username;
8652  const char *bit_removal_on = "a=T38FaxFillBitRemoval\r\n";
8653  const char *bit_removal_off = "";
8654 
8655  const char *mmr_on = "a=T38FaxTranscodingMMR\r\n";
8656  const char *mmr_off = "";
8657 
8658  const char *jbig_on = "a=T38FaxTranscodingJBIG\r\n";
8659  const char *jbig_off = "";
8660  const char *var;
8661  int broken_boolean;
8662  switch_media_handle_t *smh;
8663  switch_rtp_engine_t *a_engine;
8664 
8665  switch_assert(session);
8666 
8667  if (!(smh = session->media_handle)) {
8668  return;
8669  }
8670 
8671  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
8672 
8673 
8674  switch_assert(t38_options);
8675 
8676  ip = t38_options->local_ip;
8677  port = t38_options->local_port;
8678  username = smh->mparams->sdp_username;
8679 
8680  var = switch_channel_get_variable(session->channel, "t38_broken_boolean");
8681 
8682  broken_boolean = switch_true(var);
8683 
8684 
8685  if (!ip) {
8686  if (!(ip = a_engine->adv_sdp_ip)) {
8687  ip = a_engine->proxy_sdp_ip;
8688  }
8689  }
8690 
8691  if (!ip) {
8693  return;
8694  }
8695 
8696  if (!port) {
8697  if (!(port = a_engine->adv_sdp_port)) {
8698  port = a_engine->proxy_sdp_port;
8699  }
8700  }
8701 
8702  if (!port) {
8703  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%s NO PORT!\n", switch_channel_get_name(session->channel));
8704  return;
8705  }
8706 
8707  if (!smh->owner_id) {
8708  smh->owner_id = (uint32_t) switch_epoch_time_now(NULL) - port;
8709  }
8710 
8711  if (!smh->session_id) {
8712  smh->session_id = smh->owner_id;
8713  }
8714 
8715  smh->session_id++;
8716 
8717  family = strchr(ip, ':') ? "IP6" : "IP4";
8718 
8719 
8720  switch_snprintf(buf, sizeof(buf),
8721  "v=0\r\n"
8722  "o=%s %010u %010u IN %s %s\r\n"
8723  "s=%s\r\n" "c=IN %s %s\r\n" "t=0 0\r\n", username, smh->owner_id, smh->session_id, family, ip, username, family, ip);
8724 
8725  if (t38_options->T38FaxMaxBuffer) {
8726  switch_snprintf(max_buf, sizeof(max_buf), "a=T38FaxMaxBuffer:%d\r\n", t38_options->T38FaxMaxBuffer);
8727  };
8728 
8729  if (t38_options->T38FaxMaxDatagram) {
8730  switch_snprintf(max_data, sizeof(max_data), "a=T38FaxMaxDatagram:%d\r\n", t38_options->T38FaxMaxDatagram);
8731  };
8732 
8733 
8734 
8735 
8736  if (broken_boolean) {
8737  bit_removal_on = "a=T38FaxFillBitRemoval:1\r\n";
8738  bit_removal_off = "a=T38FaxFillBitRemoval:0\r\n";
8739 
8740  mmr_on = "a=T38FaxTranscodingMMR:1\r\n";
8741  mmr_off = "a=T38FaxTranscodingMMR:0\r\n";
8742 
8743  jbig_on = "a=T38FaxTranscodingJBIG:1\r\n";
8744  jbig_off = "a=T38FaxTranscodingJBIG:0\r\n";
8745 
8746  }
8747 
8748 
8749  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
8750  "m=image %d udptl t38\r\n"
8751  "a=T38FaxVersion:%d\r\n"
8752  "a=T38MaxBitRate:%d\r\n"
8753  "%s"
8754  "%s"
8755  "%s"
8756  "a=T38FaxRateManagement:%s\r\n"
8757  "%s"
8758  "%s"
8759  "a=T38FaxUdpEC:%s\r\n",
8760  //"a=T38VendorInfo:%s\r\n",
8761  port,
8762  t38_options->T38FaxVersion,
8763  t38_options->T38MaxBitRate,
8764  t38_options->T38FaxFillBitRemoval ? bit_removal_on : bit_removal_off,
8765  t38_options->T38FaxTranscodingMMR ? mmr_on : mmr_off,
8766  t38_options->T38FaxTranscodingJBIG ? jbig_on : jbig_off,
8767  t38_options->T38FaxRateManagement,
8768  max_buf,
8769  max_data,
8770  t38_options->T38FaxUdpEC
8771  //t38_options->T38VendorInfo ? t38_options->T38VendorInfo : "0 0 0"
8772  );
8773 
8774 
8775 
8776  if (insist) {
8777  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "m=audio 0 RTP/AVP 19\r\n");
8778  }
8779 
8781 
8782 
8783  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s image media sdp:\n%s\n",
8784  switch_channel_get_name(session->channel), smh->mparams->local_sdp_str);
8785 
8786 
8787 }
8788 
8789 
8790 
8791 //?
8793 {
8794  switch_size_t len;
8795  char *p, *q, *pe, *qe;
8796  int has_video = 0, has_audio = 0, has_ip = 0;
8797  char port_buf[25] = "";
8798  char vport_buf[25] = "";
8799  char *new_sdp;
8800  int bad = 0;
8801  switch_media_handle_t *smh;
8802  switch_rtp_engine_t *a_engine, *v_engine;
8803  payload_map_t *pmap;
8804 
8805  switch_assert(session);
8806 
8807  if (!(smh = session->media_handle)) {
8808  return;
8809  }
8810 
8811  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
8812  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
8813 
8814  if (zstr(smh->mparams->local_sdp_str)) {
8815  return;
8816  }
8817 
8818  len = strlen(smh->mparams->local_sdp_str) * 2;
8819 
8820  if (!(smh->mparams->ndlb & SM_NDLB_NEVER_PATCH_REINVITE)) {
8821  if (switch_channel_test_flag(session->channel, CF_ANSWERED) &&
8822  (switch_stristr("sendonly", smh->mparams->local_sdp_str) || switch_stristr("0.0.0.0", smh->mparams->local_sdp_str))) {
8823  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Skip patch on hold SDP\n");
8824  return;
8825  }
8826  }
8827 
8828  if (zstr(a_engine->local_sdp_ip) || !a_engine->local_sdp_port) {// || switch_channel_test_flag(session->channel, CF_PROXY_MEDIA)) {
8831  switch_channel_get_name(session->channel));
8832  return;
8833  }
8834 
8835  clear_pmaps(a_engine);
8836 
8837  pmap = switch_core_media_add_payload_map(session,
8839  "PROXY",
8840  NULL,
8841  NULL,
8843  0,
8844  8000,
8845  20,
8846  1,
8847  SWITCH_TRUE);
8848 
8849  a_engine->cur_payload_map = pmap;
8850 
8851  }
8852 
8853  new_sdp = switch_core_session_alloc(session, len);
8854  switch_snprintf(port_buf, sizeof(port_buf), "%u", a_engine->local_sdp_port);
8855 
8856 
8857  p = smh->mparams->local_sdp_str;
8858  q = new_sdp;
8859  pe = p + strlen(p);
8860  qe = q + len - 1;
8861 
8862 
8863  while (p && *p) {
8864  if (p >= pe) {
8865  bad = 1;
8866  goto end;
8867  }
8868 
8869  if (q >= qe) {
8870  bad = 2;
8871  goto end;
8872  }
8873 
8874  if (a_engine->local_sdp_ip && !strncmp("c=IN IP", p, 7)) {
8875  strncpy(q, p, 7);
8876  p += 7;
8877  q += 7;
8878  strncpy(q, strchr(a_engine->adv_sdp_ip, ':') ? "6 " : "4 ", 2);
8879  p +=2;
8880  q +=2;
8881  strncpy(q, a_engine->adv_sdp_ip, strlen(a_engine->adv_sdp_ip));
8882  q += strlen(a_engine->adv_sdp_ip);
8883 
8884  while (p && *p && ((*p >= '0' && *p <= '9') || *p == '.' || *p == ':' || (*p >= 'A' && *p <= 'F') || (*p >= 'a' && *p <= 'f'))) {
8885  if (p >= pe) {
8886  bad = 3;
8887  goto end;
8888  }
8889  p++;
8890  }
8891 
8892  has_ip++;
8893 
8894  } else if (!strncmp("o=", p, 2)) {
8895  char *oe = strchr(p, '\n');
8896  switch_size_t len;
8897 
8898  if (oe) {
8899  const char *family = "IP4";
8900  char o_line[1024] = "";
8901 
8902  if (oe >= pe) {
8903  bad = 5;
8904  goto end;
8905  }
8906 
8907  len = (oe - p);
8908  p += len;
8909 
8910 
8911  family = strchr(smh->mparams->sipip, ':') ? "IP6" : "IP4";
8912 
8913  if (!smh->owner_id) {
8914  smh->owner_id = (uint32_t) switch_epoch_time_now(NULL) * 31821U + 13849U;
8915  }
8916 
8917  if (!smh->session_id) {
8918  smh->session_id = smh->owner_id;
8919  }
8920 
8921  smh->session_id++;
8922 
8923 
8924  snprintf(o_line, sizeof(o_line), "o=%s %010u %010u IN %s %s\r\n",
8925  smh->mparams->sdp_username, smh->owner_id, smh->session_id, family, smh->mparams->sipip);
8926 
8927  strncpy(q, o_line, strlen(o_line));
8928  q += strlen(o_line) - 1;
8929 
8930  }
8931 
8932  } else if (!strncmp("s=", p, 2)) {
8933  char *se = strchr(p, '\n');
8934  switch_size_t len;
8935 
8936  if (se) {
8937  char s_line[1024] = "";
8938 
8939  if (se >= pe) {
8940  bad = 5;
8941  goto end;
8942  }
8943 
8944  len = (se - p);
8945  p += len;
8946 
8947  snprintf(s_line, sizeof(s_line), "s=%s\r\n", smh->mparams->sdp_username);
8948 
8949  strncpy(q, s_line, strlen(s_line));
8950  q += strlen(s_line) - 1;
8951 
8952  }
8953 
8954  } else if ((!strncmp("m=audio ", p, 8) && *(p + 8) != '0') || (!strncmp("m=image ", p, 8) && *(p + 8) != '0')) {
8955  strncpy(q, p, 8);
8956  p += 8;
8957 
8958  if (p >= pe) {
8959  bad = 4;
8960  goto end;
8961  }
8962 
8963 
8964  q += 8;
8965 
8966  if (q >= qe) {
8967  bad = 5;
8968  goto end;
8969  }
8970 
8971 
8972  strncpy(q, port_buf, strlen(port_buf));
8973  q += strlen(port_buf);
8974 
8975  if (q >= qe) {
8976  bad = 6;
8977  goto end;
8978  }
8979 
8980  while (p && *p && (*p >= '0' && *p <= '9')) {
8981  if (p >= pe) {
8982  bad = 7;
8983  goto end;
8984  }
8985  p++;
8986  }
8987 
8988  has_audio++;
8989 
8990  } else if (!strncmp("m=video ", p, 8) && *(p + 8) != '0') {
8991  if (!has_video) {
8993  clear_pmaps(v_engine);
8994  pmap = switch_core_media_add_payload_map(session,
8996  "PROXY-VID",
8997  NULL,
8998  NULL,
9000  0,
9001  90000,
9002  90000,
9003  1,
9004  SWITCH_TRUE);
9005  v_engine->cur_payload_map = pmap;
9006 
9007  switch_snprintf(vport_buf, sizeof(vport_buf), "%u", v_engine->adv_sdp_port);
9008 
9009  if (switch_channel_media_ready(session->channel) && !switch_rtp_ready(v_engine->rtp_session)) {
9010  switch_channel_set_flag(session->channel, CF_VIDEO_POSSIBLE);
9011  switch_channel_set_flag(session->channel, CF_REINVITE);
9013  }
9014 
9015  v_engine->codec_negotiated = 1;
9017  }
9018 
9019  strncpy(q, p, 8);
9020  p += 8;
9021 
9022  if (p >= pe) {
9023  bad = 8;
9024  goto end;
9025  }
9026 
9027  q += 8;
9028 
9029  if (q >= qe) {
9030  bad = 9;
9031  goto end;
9032  }
9033 
9034  strncpy(q, vport_buf, strlen(vport_buf));
9035  q += strlen(vport_buf);
9036 
9037  if (q >= qe) {
9038  bad = 10;
9039  goto end;
9040  }
9041 
9042  while (p && *p && (*p >= '0' && *p <= '9')) {
9043 
9044  if (p >= pe) {
9045  bad = 11;
9046  goto end;
9047  }
9048 
9049  p++;
9050  }
9051 
9052  has_video++;
9053  }
9054 
9055  while (p && *p && *p != '\n') {
9056 
9057  if (p >= pe) {
9058  bad = 12;
9059  goto end;
9060  }
9061 
9062  if (q >= qe) {
9063  bad = 13;
9064  goto end;
9065  }
9066 
9067  *q++ = *p++;
9068  }
9069 
9070  if (p >= pe) {
9071  bad = 14;
9072  goto end;
9073  }
9074 
9075  if (q >= qe) {
9076  bad = 15;
9077  goto end;
9078  }
9079 
9080  *q++ = *p++;
9081 
9082  }
9083 
9084  end:
9085 
9086  if (bad) {
9087  return;
9088  }
9089 
9090 
9091  if (switch_channel_down(session->channel)) {
9092  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s too late.\n", switch_channel_get_name(session->channel));
9093  return;
9094  }
9095 
9096 
9097  if (!has_ip && !has_audio) {
9098  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SDP has no audio in it.\n%s\n",
9099  switch_channel_get_name(session->channel), smh->mparams->local_sdp_str);
9100  return;
9101  }
9102 
9103 
9104  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Patched SDP\n---\n%s\n+++\n%s\n",
9105  switch_channel_get_name(session->channel), smh->mparams->local_sdp_str, new_sdp);
9106 
9107  switch_core_media_set_local_sdp(session, new_sdp, SWITCH_FALSE);
9108 
9109 }
9110 
9111 //?
9113 {
9114  switch_media_handle_t *smh;
9115  switch_rtp_engine_t *a_engine;
9116 
9117  switch_assert(session);
9118 
9119  if (!(smh = session->media_handle)) {
9120  return;
9121  }
9122 
9123  if (switch_channel_down(session->channel)) {
9124  return;
9125  }
9126 
9127  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
9128 
9129 
9130  if (switch_rtp_ready(a_engine->rtp_session)) {
9131  char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
9132  switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
9133  const char *err, *val;
9134 
9137 
9138  if (!t38_options || !t38_options->remote_ip) {
9139  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No remote address\n");
9140  return;
9141  }
9142 
9143  if (remote_host && remote_port && remote_port == t38_options->remote_port && !strcmp(remote_host, t38_options->remote_ip)) {
9144  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote address:port [%s:%d] has not changed.\n",
9145  t38_options->remote_ip, t38_options->remote_port);
9146  return;
9147  }
9148 
9149  if (switch_rtp_set_remote_address(a_engine->rtp_session, t38_options->remote_ip,
9150  t38_options->remote_port, 0, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
9151  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "IMAGE UDPTL REPORTS ERROR: [%s]\n", err);
9152  } else {
9153  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IMAGE UDPTL CHANGING DEST TO: [%s:%d]\n",
9154  t38_options->remote_ip, t38_options->remote_port);
9156  !((val = switch_channel_get_variable(session->channel, "disable_udptl_auto_adjust")) && switch_true(val))) {
9157  /* Reactivate the NAT buster flag. */
9159  }
9160  }
9161  }
9162 }
9163 
9164 //?
9166 {
9167  switch_core_session_message_t msg = { 0 };
9168 
9169  msg.from = __FILE__;
9170 
9172  msg.numeric_arg = on;
9173  switch_core_session_receive_message(session, &msg);
9174 }
9175 
9177 {
9179  int flags = 0;
9180  switch_status_t status;
9181 
9182  if (dtls_state == DS_READY || dtls_state >= DS_FAIL) return 0;
9183 
9184  status = switch_rtp_zerocopy_read_frame(engine->rtp_session, &engine->read_frame, flags);
9185 
9186  if (!SWITCH_READ_ACCEPTABLE(status)) {
9187  return 0;
9188  }
9189 
9190  return 1;
9191 }
9192 
9194 {
9195  switch_media_handle_t *smh;
9196  switch_rtp_engine_t *engine;
9197  int checking = 0;
9198 
9199  switch_assert(session);
9200 
9201  if (!(smh = session->media_handle)) {
9202  return SWITCH_FALSE;
9203  }
9204 
9205  if (!switch_channel_media_up(session->channel)) {
9206  return SWITCH_FALSE;
9207  }
9208 
9209  if (!switch_channel_test_flag(session->channel, CF_DTLS)) {
9210  return SWITCH_TRUE;
9211  }
9212 
9213  engine = &smh->engines[type];
9214 
9215  if (engine->rmode == SWITCH_MEDIA_FLOW_DISABLED) {
9216  return SWITCH_TRUE;
9217  }
9218 
9219  do {
9220  if (engine->rtp_session) checking = check_engine(engine);
9221  } while (switch_channel_ready(session->channel) && checking);
9222 
9223  if (!checking) {
9224  return SWITCH_TRUE;
9225  }
9226 
9227  return SWITCH_FALSE;
9228 }
9229 
9230 
9232 {
9233  switch_media_handle_t *smh;
9234  switch_rtp_engine_t *engine;
9236 
9237  if (!(smh = session->media_handle)) {
9238  return SWITCH_STATUS_FALSE;
9239  }
9240 
9241  if (switch_channel_down(session->channel)) {
9242  return SWITCH_STATUS_FALSE;
9243  }
9244 
9245  engine = &smh->engines[type];
9246 
9247  if (switch_core_codec_ready(&engine->write_codec)) {
9249  SCCT_INT, &bitrate, SCCT_NONE, NULL, NULL, NULL);
9250  }
9251 
9252  return status;
9253 }
9254 
9255 //?
9257 {
9258  switch_media_handle_t *smh;
9259  switch_rtp_engine_t *engine;
9260 
9261  switch_assert(session);
9262 
9263  if (!(smh = session->media_handle)) {
9264  return SWITCH_STATUS_FALSE;
9265  }
9266 
9267  engine = &smh->engines[type];
9268 
9269  if (switch_rtp_ready(engine->rtp_session)) {
9271  return SWITCH_STATUS_SUCCESS;
9272  }
9273 
9274  return SWITCH_STATUS_FALSE;
9275 }
9276 
9277 //?
9279 {
9280  switch_media_handle_t *smh;
9281  switch_rtp_engine_t *a_engine, *v_engine;
9283 
9284  switch_assert(session);
9285 
9286  if (!(smh = session->media_handle)) {
9287  return SWITCH_STATUS_FALSE;
9288  }
9289 
9290  if (switch_channel_down(session->channel)) {
9291  return SWITCH_STATUS_FALSE;
9292  }
9293 
9294  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
9295  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
9296 
9297  switch (msg->message_id) {
9298 
9300  {
9301  if (switch_rtp_ready(a_engine->rtp_session)) {
9302  switch_channel_audio_sync(session->channel);
9303  switch_rtp_reset_jb(a_engine->rtp_session);
9304  }
9305 
9306  if (switch_channel_test_flag(session->channel, CF_CONFERENCE)) {
9308  }
9309  }
9310  break;
9311 
9313  {
9314  if (v_engine->rtp_session) {
9317  }// else {
9320  }
9321  // }
9322  }
9323  }
9324 
9325  break;
9326 
9328  {
9329  if (switch_rtp_ready(a_engine->rtp_session)) {
9330  if (msg->numeric_arg) {
9332  } else {
9334  }
9335  }
9336  }
9337  break;
9338 
9340  {
9341  if (switch_rtp_ready(a_engine->rtp_session)) {
9342  check_jb(session, msg->string_arg, 0, 0, SWITCH_FALSE);
9343  }
9344  }
9345  break;
9346 
9348  if (a_engine->rtp_session) {
9349  if (session->bugs && msg->numeric_arg) {
9351  "%s has a media bug, hard mute not allowed.\n", switch_channel_get_name(session->channel));
9352  } else {
9353  if (msg->numeric_arg) {
9355  } else {
9357  }
9358 
9360  }
9361  }
9362 
9363  break;
9364 
9366  {
9367  if (v_engine->rtp_session) {
9368  switch_rtp_req_bitrate(v_engine->rtp_session, msg->numeric_arg);
9369  }
9370  }
9371  break;
9372 
9374  {
9375  if (v_engine->rtp_session) {
9376  switch_rtp_ack_bitrate(v_engine->rtp_session, msg->numeric_arg);
9377  }
9378  }
9379  break;
9380 
9382  {
9383  switch_rtp_engine_t *engine = &smh->engines[msg->numeric_reply];
9384  uint32_t level = (uint32_t) msg->numeric_arg;
9385 
9386  if (engine->rtp_session) {
9387  switch_core_codec_control(&engine->read_codec, SCC_DEBUG, SCCT_INT, (void *)&level, SCCT_NONE, NULL, NULL, NULL);
9388  switch_core_codec_control(&engine->write_codec, SCC_DEBUG, SCCT_INT, (void *)&level, SCCT_NONE, NULL, NULL, NULL);
9389  }
9390  }
9391  break;
9392 
9394  {
9395  switch_rtp_engine_t *engine;
9399  void *reply = NULL;
9400 
9401  if (!strcasecmp(msg->string_array_arg[0], "video")) {
9402  type = SWITCH_MEDIA_TYPE_VIDEO;
9403  }
9404 
9405  if (!strcasecmp(msg->string_array_arg[1], "write")) {
9406  iotype = SWITCH_IO_WRITE;
9407  }
9408 
9409  engine = &smh->engines[type];
9410 
9411  if (engine->rtp_session) {
9412  if (iotype == SWITCH_IO_READ) {
9414  SCCT_STRING, (void *)msg->string_array_arg[2],
9415  SCCT_STRING, (void *)msg->string_array_arg[3], &reply_type, &reply);
9416  } else {
9418  SCCT_STRING, (void *)msg->string_array_arg[2],
9419  SCCT_STRING, (void *)msg->string_array_arg[3], &reply_type, &reply);
9420  }
9421 
9422 
9423  if (reply_type == SCCT_STRING) {
9424  msg->string_array_arg[4] = (char *)reply;
9425  }
9426  }
9427  }
9428  break;
9429 
9431  {
9432  switch_rtp_t *rtp = a_engine->rtp_session;
9433  const char *direction = msg->string_array_arg[0];
9434 
9435  if (direction && *direction == 'v') {
9436  direction++;
9437  rtp = v_engine->rtp_session;
9438  }
9439 
9440  if (switch_rtp_ready(rtp) && !zstr(direction) && !zstr(msg->string_array_arg[1])) {
9442  int both = !strcasecmp(direction, "both");
9443  int set = 0;
9444 
9445  if (both || !strcasecmp(direction, "read")) {
9447  set++;
9448  }
9449 
9450  if (both || !strcasecmp(direction, "write")) {
9452  set++;
9453  }
9454 
9455  if (set) {
9456  if (switch_true(msg->string_array_arg[1])) {
9457  switch_rtp_set_flags(rtp, flags);
9458  } else {
9459  switch_rtp_clear_flags(rtp, flags);
9460  }
9461  } else {
9462  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Options\n");
9463  }
9464  }
9465  }
9466  goto end;
9469  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Pass 2833 mode may not work on a transcoded call.\n");
9470  }
9471  goto end;
9472 
9474  {
9475 
9476  if (switch_rtp_ready(a_engine->rtp_session)) {
9477  const char *val;
9478  int ok = 0;
9479 
9480  if (!switch_channel_test_flag(session->channel, CF_VIDEO) &&
9481  (!(val = switch_channel_get_variable(session->channel, "rtp_jitter_buffer_during_bridge")) || switch_false(val))) {
9482  if (switch_channel_test_flag(session->channel, CF_JITTERBUFFER) && switch_channel_test_cap_partner(session->channel, CC_FS_RTP)) {
9484  "%s PAUSE Jitterbuffer\n", switch_channel_get_name(session->channel));
9487  }
9488  }
9489 
9490  if (switch_channel_test_flag(session->channel, CF_PASS_RFC2833) && switch_channel_test_flag_partner(session->channel, CF_FS_RTP)) {
9493  "%s activate passthru 2833 mode.\n", switch_channel_get_name(session->channel));
9494  }
9495 
9496 
9497  if ((val = switch_channel_get_variable(session->channel, "rtp_notimer_during_bridge"))) {
9498  ok = switch_true(val);
9499  } else {
9501  }
9502 
9504  ok = 0;
9505  }
9506 
9507  if (ok) {
9509  //switch_rtp_clear_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
9511  }
9512 
9513  if (ok && switch_channel_test_flag(session->channel, CF_NOTIMER_DURING_BRIDGE)) {
9514  /* these are not compat */
9515  ok = 0;
9516  } else {
9517  if ((val = switch_channel_get_variable(session->channel, "rtp_autoflush_during_bridge"))) {
9518  ok = switch_true(val);
9519  } else {
9521  }
9522  }
9523 
9524  if (ok) {
9527  } else {
9529  }
9530 
9531  }
9532  }
9533  goto end;
9535  if (switch_rtp_ready(a_engine->rtp_session)) {
9536 
9537  if (switch_test_flag(smh, SMF_JB_PAUSED)) {
9539  if (switch_channel_test_flag(session->channel, CF_JITTERBUFFER)) {
9541  "%s RESUME Jitterbuffer\n", switch_channel_get_name(session->channel));
9543  }
9544  }
9545 
9546 
9548  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s deactivate passthru 2833 mode.\n",
9549  switch_channel_get_name(session->channel));
9551  }
9552 
9553  if (switch_channel_test_flag(session->channel, CF_NOTIMER_DURING_BRIDGE)) {
9557  //switch_rtp_set_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
9558  }
9560  }
9561 
9562  if (switch_channel_test_flag(session->channel, CF_AUTOFLUSH_DURING_BRIDGE)) {
9565  } else {
9567  }
9568 
9569  }
9570  goto end;
9572  if (switch_rtp_ready(a_engine->rtp_session)) {
9574  //switch_rtp_reset_jb(a_engine->rtp_session);
9575  }
9576  goto end;
9577 
9579  if (switch_rtp_ready(v_engine->rtp_session)) {
9580  switch_rtp_flush(v_engine->rtp_session);
9581  //switch_rtp_reset_jb(v_engine->rtp_session);
9582  }
9583  goto end;
9586  {
9587 
9588  a_engine->codec_negotiated = 0;
9589  v_engine->codec_negotiated = 0;
9590 
9591  if (session->track_duration) {
9592  switch_core_session_enable_heartbeat(session, session->track_duration);
9593  }
9594  }
9595  break;
9596 
9598  switch_channel_set_flag(session->channel, CF_PROXY_MODE);
9600  break;
9602  {
9603  const char *uuid;
9604  switch_core_session_t *other_session;
9605  switch_channel_t *other_channel;
9606  const char *ip = NULL, *port = NULL;
9607 
9608  switch_channel_set_flag(session->channel, CF_PROXY_MODE);
9609 
9611 
9612  if (switch_true(switch_channel_get_variable(session->channel, "bypass_keep_codec"))) {
9613  switch_channel_set_variable(session->channel, "absolute_codec_string", switch_channel_get_variable(session->channel, "ep_codec_string"));
9614  }
9615 
9616 
9617  if ((uuid = switch_channel_get_partner_uuid(session->channel))
9618  && (other_session = switch_core_session_locate(uuid))) {
9619  other_channel = switch_core_session_get_channel(other_session);
9622  switch_core_session_rwunlock(other_session);
9623 
9624  if (ip && port) {
9626  clear_pmaps(a_engine);
9627  clear_pmaps(v_engine);
9628  switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, ip, (switch_port_t)atoi(port), NULL, 1);
9629  }
9630  }
9631 
9632 
9633  if (!smh->mparams->local_sdp_str) {
9635  }
9636 
9637  if (session->track_duration) {
9638  switch_core_session_enable_heartbeat(session, session->track_duration);
9639  }
9640 
9641  }
9642  break;
9643 
9644 
9645  default:
9646  break;
9647  }
9648 
9649 
9650  if (smh->mutex) switch_mutex_lock(smh->mutex);
9651 
9652 
9653  if (switch_channel_down(session->channel)) {
9654  status = SWITCH_STATUS_FALSE;
9655  goto end_lock;
9656  }
9657 
9658  switch (msg->message_id) {
9660  {
9661  switch_core_session_t *nsession;
9662 
9663  if (msg->string_arg) {
9664  switch_channel_set_variable(session->channel, "absolute_codec_string", NULL);
9665  if (*msg->string_arg == '=') {
9666  switch_channel_set_variable(session->channel, "codec_string", msg->string_arg);
9667  } else {
9668  switch_channel_set_variable_printf(session->channel, "codec_string", "=%s%s%s,%s",
9669  v_engine->cur_payload_map->rm_encoding ? v_engine->cur_payload_map->rm_encoding : "",
9670  v_engine->cur_payload_map->rm_encoding ? "," : "",
9671  a_engine->cur_payload_map->rm_encoding, msg->string_arg);
9672  }
9673 
9674 
9675  a_engine->codec_negotiated = 0;
9676  v_engine->codec_negotiated = 0;
9677  smh->num_negotiated_codecs = 0;
9678  switch_channel_clear_flag(session->channel, CF_VIDEO_POSSIBLE);
9681  switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 1);
9682  }
9683 
9685 
9686  if (msg->numeric_arg && switch_core_session_get_partner(session, &nsession) == SWITCH_STATUS_SUCCESS) {
9687  msg->numeric_arg = 0;
9688  switch_core_session_receive_message(nsession, msg);
9689  switch_core_session_rwunlock(nsession);
9690  }
9691 
9692  }
9693  break;
9694 
9696  {
9697  if (switch_rtp_ready(a_engine->rtp_session)) {
9698  if (msg->numeric_arg) {
9699  if (switch_channel_test_flag(session->channel, CF_JITTERBUFFER)) {
9702  }
9703 
9705 
9706  } else {
9707  if (switch_test_flag(smh, SMF_JB_PAUSED)) {
9709  if (switch_channel_test_flag(session->channel, CF_JITTERBUFFER)) {
9711  }
9712  }
9713  }
9714  }
9715  }
9716  break;
9717 
9719  {
9720  switch_t38_options_t *t38_options = switch_channel_get_private(session->channel, "t38_options");
9721 
9722  if (t38_options) {
9723  switch_core_media_start_udptl(session, t38_options);
9724  }
9725 
9726  }
9727 
9728 
9729  default:
9730  break;
9731  }
9732 
9733 
9734  end_lock:
9735 
9736  if (smh->mutex) switch_mutex_unlock(smh->mutex);
9737 
9738  end:
9739 
9740  if (switch_channel_down(session->channel)) {
9741  status = SWITCH_STATUS_FALSE;
9742  }
9743 
9744  return status;
9745 
9746 }
9747 
9748 //?
9750 {
9751  switch_media_handle_t *smh;
9752 
9753  switch_assert(session);
9754 
9755  if (!(smh = session->media_handle)) {
9756  return;
9757  }
9758 
9759  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
9760  switch_rtp_break(smh->engines[type].rtp_session);
9761  }
9762 }
9763 
9764 //?
9766 {
9767  switch_media_handle_t *smh;
9768 
9769  switch_assert(session);
9770 
9771  if (!(smh = session->media_handle)) {
9772  return;
9773  }
9774 
9775  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
9777  }
9778 }
9779 
9780 //?
9782 {
9783  switch_media_handle_t *smh;
9784 
9785  switch_assert(session);
9786 
9787  if (!(smh = session->media_handle)) {
9788  return SWITCH_STATUS_FALSE;
9789  }
9790 
9791  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
9792  return switch_rtp_queue_rfc2833(smh->engines[type].rtp_session, dtmf);
9793  }
9794 
9795  return SWITCH_STATUS_FALSE;
9796 }
9797 
9798 //?
9800 {
9801  switch_media_handle_t *smh;
9802 
9803  switch_assert(session);
9804 
9805  if (!(smh = session->media_handle)) {
9806  return SWITCH_STATUS_FALSE;
9807  }
9808 
9809  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
9810  return switch_rtp_queue_rfc2833_in(smh->engines[type].rtp_session, dtmf);
9811  }
9812 
9813  return SWITCH_STATUS_FALSE;
9814 }
9815 
9816 //?
9818 {
9819  switch_media_handle_t *smh;
9820 
9821  switch_assert(session);
9822 
9823  if (!(smh = session->media_handle)) {
9824  return 0;
9825  }
9826 
9827  return switch_rtp_ready(smh->engines[type].rtp_session);
9828 }
9829 
9830 //?
9832 {
9833  switch_media_handle_t *smh;
9834 
9835  switch_assert(session);
9836 
9837  if (!(smh = session->media_handle)) {
9838  return;
9839  }
9840 
9841  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
9842  switch_rtp_set_flag(smh->engines[type].rtp_session, flag);
9843  }
9844 }
9845 
9846 //?
9848 {
9849  switch_media_handle_t *smh;
9850 
9851  switch_assert(session);
9852 
9853  if (!(smh = session->media_handle)) {
9854  return;
9855  }
9856 
9857  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
9858  switch_rtp_clear_flag(smh->engines[type].rtp_session, flag);
9859  }
9860 }
9861 
9862 //?
9864 {
9865  switch_media_handle_t *smh;
9866 
9867  switch_assert(session);
9868 
9869  if (!(smh = session->media_handle)) {
9870  return;
9871  }
9872 
9873  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
9875  }
9876 }
9877 
9878 //?
9880 {
9881  switch_media_handle_t *smh;
9882 
9883  switch_assert(session);
9884 
9885  if (!(smh = session->media_handle)) {
9886  return;
9887  }
9888 
9889  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
9891  }
9892 }
9893 
9894 //?
9896 {
9897  switch_media_handle_t *smh;
9898 
9899  switch_assert(session);
9900 
9901  if (!(smh = session->media_handle)) {
9902  return NULL;
9903  }
9904 
9905  if (smh->engines[type].rtp_session) {
9906  return switch_rtp_get_stats(smh->engines[type].rtp_session, pool);
9907  }
9908 
9909  return NULL;
9910 }
9911 
9912 //?
9914 {
9915  switch_media_handle_t *smh;
9916 
9917  switch_assert(session);
9918 
9919  if (!(smh = session->media_handle)) {
9920  return SWITCH_FALSE;
9921  }
9922 
9923  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
9925  }
9926 
9927  return SWITCH_FALSE;
9928 }
9929 
9930 //?
9932 {
9933  switch_media_handle_t *smh;
9934 
9935  switch_assert(session);
9936 
9937  if (!(smh = session->media_handle)) {
9938  return SWITCH_STATUS_FALSE;
9939  }
9940 
9941  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
9942  return switch_rtp_udptl_mode(smh->engines[type].rtp_session);
9943  }
9944 
9945  return SWITCH_STATUS_FALSE;
9946 }
9947 
9948 //?
9950 {
9951  switch_media_handle_t *smh;
9952 
9953  switch_assert(session);
9954 
9955  if (!(smh = session->media_handle)) {
9956  return NULL;
9957  }
9958 
9959  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
9961  }
9962 
9963  return NULL;
9964 }
9965 
9966 
9967 //?
9969 {
9970  sdp_parser_t *parser;
9971  sdp_session_t *sdp;
9972  switch_media_handle_t *smh;
9973 
9974  switch_assert(session);
9975 
9976  if (!(smh = session->media_handle)) {
9977  return;
9978  }
9979 
9980 
9981  if ((parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
9982 
9983  if ((sdp = sdp_session(parser))) {
9985  }
9986 
9987  sdp_parser_free(parser);
9988  }
9989 
9990 }
9991 
9992 
9993 static void add_audio_codec(sdp_rtpmap_t *map, const switch_codec_implementation_t *imp, int ptime, char *buf, switch_size_t buflen)
9994 {
9995  int codec_ms = ptime;
9996  uint32_t map_bit_rate = 0, map_channels = 1;
9997  char ptstr[20] = "";
9998  char ratestr[20] = "";
9999  char bitstr[20] = "";
10000  switch_codec_fmtp_t codec_fmtp = { 0 };
10001 
10002  if (!codec_ms) {
10003  codec_ms = switch_default_ptime(map->rm_encoding, map->rm_pt);
10004  }
10005 
10006  map_channels = map->rm_params ? atoi(map->rm_params) : 1;
10007  map_bit_rate = switch_known_bitrate((switch_payload_t)map->rm_pt);
10008 
10009  if (!ptime && !strcasecmp(map->rm_encoding, "g723")) {
10010  ptime = codec_ms = 30;
10011  }
10012 
10013  if (zstr(map->rm_fmtp)) {
10014  if (!strcasecmp(map->rm_encoding, "ilbc")) {
10015  ptime = codec_ms = 30;
10016  map_bit_rate = 13330;
10017  } else if (!strcasecmp(map->rm_encoding, "isac")) {
10018  ptime = codec_ms = 30;
10019  map_bit_rate = 32000;
10020  }
10021  } else {
10022  if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) {
10023  if (codec_fmtp.bits_per_second) {
10024  map_bit_rate = codec_fmtp.bits_per_second;
10025  }
10026  if (codec_fmtp.microseconds_per_packet) {
10027  codec_ms = (codec_fmtp.microseconds_per_packet / 1000);
10028  }
10029  }
10030  }
10031 
10032  if (map->rm_rate) {
10033  switch_snprintf(ratestr, sizeof(ratestr), "@%uh", (unsigned int) map->rm_rate);
10034  }
10035 
10036  if (codec_ms) {
10037  switch_snprintf(ptstr, sizeof(ptstr), "@%di", codec_ms);
10038  }
10039 
10040  if (map_bit_rate) {
10041  switch_snprintf(bitstr, sizeof(bitstr), "@%db", map_bit_rate);
10042  }
10043 
10044  if (map_channels > 1) {
10045  switch_snprintf(bitstr, sizeof(bitstr), "@%dc", map_channels);
10046  }
10047 
10048  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), ",%s.%s%s%s%s", imp->modname, map->rm_encoding, ratestr, ptstr, bitstr);
10049 
10050 }
10051 
10052 
10053 static void switch_core_media_set_r_sdp_codec_string(switch_core_session_t *session, const char *codec_string, sdp_session_t *sdp, switch_sdp_type_t sdp_type)
10054 {
10055  char buf[1024] = { 0 };
10056  sdp_media_t *m;
10057  sdp_attribute_t *attr;
10058  int ptime = 0, dptime = 0;
10059  sdp_connection_t *connection;
10060  sdp_rtpmap_t *map;
10061  short int match = 0;
10062  int i;
10063  int already_did[128] = { 0 };
10064  int num_codecs = 0;
10065  char *codec_order[SWITCH_MAX_CODECS];
10066  const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS] = { 0 };
10068  int prefer_sdp = 0;
10069  const char *var;
10070  switch_media_handle_t *smh;
10071 
10072  switch_assert(session);
10073 
10074  if (!(smh = session->media_handle)) {
10075  return;
10076  }
10077 
10078 
10079  if ((var = switch_channel_get_variable(channel, "ep_codec_prefer_sdp")) && switch_true(var)) {
10080  prefer_sdp = 1;
10081  }
10082 
10083  if (!zstr(codec_string)) {
10084  char *tmp_codec_string;
10085  if ((tmp_codec_string = strdup(codec_string))) {
10086  num_codecs = switch_separate_string(tmp_codec_string, ',', codec_order, SWITCH_MAX_CODECS);
10087  num_codecs = switch_loadable_module_get_codecs_sorted(codecs, SWITCH_MAX_CODECS, codec_order, num_codecs);
10088  switch_safe_free(tmp_codec_string);
10089  }
10090  } else {
10092  }
10093 
10094  if (!channel || !num_codecs) {
10095  return;
10096  }
10097 
10098  for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) {
10099  if (zstr(attr->a_name)) {
10100  continue;
10101  }
10102  if (!strcasecmp(attr->a_name, "ptime")) {
10103  dptime = atoi(attr->a_value);
10104  break;
10105  }
10106  }
10107 
10108  switch_core_media_find_zrtp_hash(session, sdp);
10110 
10111  for (m = sdp->sdp_media; m; m = m->m_next) {
10112  ptime = dptime;
10113 
10114  if ((m->m_type == sdp_media_audio || m->m_type == sdp_media_video) && m->m_port) {
10115  for (map = m->m_rtpmaps; map; map = map->rm_next) {
10116  for (attr = m->m_attributes; attr; attr = attr->a_next) {
10117  if (zstr(attr->a_name)) {
10118  continue;
10119  }
10120  if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
10121  ptime = atoi(attr->a_value);
10122  break;
10123  }
10124  }
10126  m->m_type == sdp_media_audio ? SWITCH_MEDIA_TYPE_AUDIO : SWITCH_MEDIA_TYPE_VIDEO,
10127  map->rm_encoding,
10128  NULL,
10129  map->rm_fmtp,
10130  sdp_type,
10131  map->rm_pt,
10132  map->rm_rate,
10133  ptime,
10134  map->rm_params ? atoi(map->rm_params) : 1,
10135  SWITCH_FALSE);
10136  }
10137  }
10138  }
10139 
10140  for (m = sdp->sdp_media; m; m = m->m_next) {
10141  ptime = dptime;
10142 
10143  if (m->m_type == sdp_media_image && m->m_port) {
10144  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",t38");
10145  } else if (m->m_type == sdp_media_audio && m->m_port) {
10146  for (attr = m->m_attributes; attr; attr = attr->a_next) {
10147  if (zstr(attr->a_name)) {
10148  continue;
10149  }
10150  if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
10151  ptime = atoi(attr->a_value);
10152  break;
10153  }
10154  }
10155  connection = sdp->sdp_connection;
10156  if (m->m_connections) {
10157  connection = m->m_connections;
10158  }
10159 
10160  if (!connection) {
10161  switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n");
10162  break;
10163  }
10164 
10165  if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND || prefer_sdp) {
10166  for (map = m->m_rtpmaps; map; map = map->rm_next) {
10167  if (map->rm_pt > 127 || already_did[map->rm_pt]) {
10168  continue;
10169  }
10170 
10171  for (i = 0; i < num_codecs; i++) {
10172  const switch_codec_implementation_t *imp = codecs[i];
10173 
10174  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
10175  match = (map->rm_pt == imp->ianacode) ? 1 : 0;
10176  } else {
10177  if (map->rm_encoding) {
10178  match = !strcasecmp(map->rm_encoding, imp->iananame) &&
10179  ((map->rm_pt < 96 && imp->ianacode < 96) || (map->rm_pt > 95 && imp->ianacode > 95));
10180  } else {
10181  match = 0;
10182  }
10183  }
10184 
10185  if (match) {
10186  add_audio_codec(map, imp, ptime, buf, sizeof(buf));
10187  break;
10188  }
10189 
10190  }
10191  }
10192 
10193  } else {
10194  for (i = 0; i < num_codecs; i++) {
10195  const switch_codec_implementation_t *imp = codecs[i];
10196  if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO || imp->ianacode > 127 || already_did[imp->ianacode]) {
10197  continue;
10198  }
10199  for (map = m->m_rtpmaps; map; map = map->rm_next) {
10200  if (map->rm_pt > 127 || already_did[map->rm_pt]) {
10201  continue;
10202  }
10203 
10204  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
10205  match = (map->rm_pt == imp->ianacode) ? 1 : 0;
10206  } else {
10207  if (map->rm_encoding) {
10208  match = !strcasecmp(map->rm_encoding, imp->iananame) &&
10209  ((map->rm_pt < 96 && imp->ianacode < 96) || (map->rm_pt > 95 && imp->ianacode > 95));
10210  } else {
10211  match = 0;
10212  }
10213  }
10214 
10215  if (match) {
10216  add_audio_codec(map, imp, ptime, buf, sizeof(buf));
10217  break;
10218  }
10219  }
10220  }
10221  }
10222 
10223  } else if (m->m_type == sdp_media_video && m->m_port) {
10224  connection = sdp->sdp_connection;
10225  if (m->m_connections) {
10226  connection = m->m_connections;
10227  }
10228 
10229  if (!connection) {
10230  switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_ERROR, "Cannot find a c= line in the sdp at media or session level!\n");
10231  break;
10232  }
10233  for (i = 0; i < num_codecs; i++) {
10234  const switch_codec_implementation_t *imp = codecs[i];
10235 
10236  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO || imp->ianacode > 127 || already_did[imp->ianacode]) {
10237  continue;
10238  }
10239 
10242  continue;
10243  }
10244 
10245  for (map = m->m_rtpmaps; map; map = map->rm_next) {
10246  if (map->rm_pt > 127 || already_did[map->rm_pt]) {
10247  continue;
10248  }
10249 
10250  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
10251  match = (map->rm_pt == imp->ianacode) ? 1 : 0;
10252  } else {
10253  if (map->rm_encoding) {
10254  match = !strcasecmp(map->rm_encoding, imp->iananame) &&
10255  ((map->rm_pt < 96 && imp->ianacode < 96) || (map->rm_pt > 95 && imp->ianacode > 95));
10256  } else {
10257  match = 0;
10258  }
10259  }
10260 
10261  if (match) {
10262  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s.%s", imp->modname, imp->iananame);
10263  already_did[imp->ianacode] = 1;
10264  break;
10265  }
10266  }
10267  }
10268  }
10269  }
10270  if (buf[0] == ',') {
10271  switch_channel_set_variable(channel, "ep_codec_string", buf + 1);
10272  }
10273 }
10274 
10275 //?
10277 {
10278  switch_rtp_engine_t *engine;
10279  switch_media_handle_t *smh;
10280 
10281  switch_assert(session);
10282 
10283  if (!(smh = session->media_handle)) {
10284  return SWITCH_STATUS_FALSE;
10285  }
10286 
10287  engine = &smh->engines[type];
10288 
10289  if (engine->cur_payload_map->iananame) {
10290  return SWITCH_STATUS_SUCCESS;
10291  }
10292 
10293  return SWITCH_STATUS_FALSE;
10294 }
10295 
10297 {
10298  switch_rtp_engine_t *a_engine, *v_engine;
10299  switch_media_handle_t *smh;
10300  int type;
10301 
10302  switch_assert(session);
10303 
10304  if (!(smh = session->media_handle)) {
10305  return;
10306  }
10307 
10308  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
10309  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
10310 
10311  if (switch_core_codec_ready(&v_engine->read_codec)) {
10312  type = 1;
10313  switch_core_codec_control(&v_engine->read_codec, SCC_VIDEO_RESET, SCCT_INT, (void *)&type, SCCT_NONE, NULL, NULL, NULL);
10314  }
10315 
10316  if (switch_core_codec_ready(&v_engine->write_codec)) {
10317  type = 2;
10318  switch_core_codec_control(&v_engine->write_codec, SCC_VIDEO_RESET, SCCT_INT, (void *)&type, SCCT_NONE, NULL, NULL, NULL);
10319  }
10320 
10321  if (a_engine->rtp_session) {
10322  switch_rtp_reset(a_engine->rtp_session);
10323  }
10324 
10325  if (v_engine->rtp_session) {
10326  switch_rtp_reset(v_engine->rtp_session);
10327  }
10328 
10329 
10330  smh->msid = NULL;
10331  smh->cname = NULL;
10332  v_engine->ice_out.ufrag = NULL;
10333  v_engine->ice_out.pwd = NULL;
10334  v_engine->ice_out.cands[0][0].foundation = NULL;
10335  v_engine->ice_out.cands[0][0].component_id = 0;
10336 
10337 
10338  a_engine->ice_out.ufrag = NULL;
10339  a_engine->ice_out.pwd = NULL;
10340  a_engine->ice_out.cands[0][0].foundation = NULL;
10341  a_engine->ice_out.cands[0][0].component_id = 0;
10342 
10343  if (v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].ready) {
10344  gen_ice(smh->session, SWITCH_MEDIA_TYPE_VIDEO, NULL, 0);
10345  }
10346 
10347  if (a_engine->ice_in.cands[a_engine->ice_in.chosen[0]][0].ready) {
10348  gen_ice(smh->session, SWITCH_MEDIA_TYPE_AUDIO, NULL, 0);
10349  }
10350 
10351  smh->owner_id = 0;
10352  smh->session_id = 0;
10353 
10354  a_engine->local_dtls_fingerprint.len = 0;
10355  v_engine->local_dtls_fingerprint.len = 0;
10356 
10357  a_engine->remote_ssrc = 0;
10358  v_engine->remote_ssrc = 0;
10359 
10363 }
10364 
10365 
10366 
10367 //?
10369 {
10370  switch_rtp_engine_t *a_engine, *v_engine;
10371  switch_media_handle_t *smh;
10372  const char *r_sdp = NULL;
10373  payload_map_t *pmap;
10374 
10375  switch_assert(session);
10376 
10377  if (!switch_channel_test_flag(o_session->channel, CF_PROXY_MEDIA)) {
10378  return;
10379  }
10380 
10381  if (!(smh = session->media_handle)) {
10382  return;
10383  }
10384 
10385  r_sdp = switch_channel_get_variable(o_session->channel, SWITCH_R_SDP_VARIABLE);
10386 
10387  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
10388  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
10389 
10390  switch_channel_set_flag(session->channel, CF_PROXY_MEDIA);
10391 
10392  clear_pmaps(a_engine);
10393  clear_pmaps(v_engine);
10394 
10395  pmap = switch_core_media_add_payload_map(session,
10397  "PROXY",
10398  NULL,
10399  NULL,
10401  0,
10402  8000,
10403  20,
10404  1,
10405  SWITCH_TRUE);
10406 
10407  a_engine->cur_payload_map = pmap;
10408 
10409  if (switch_stristr("m=video", r_sdp)) {
10411  pmap = switch_core_media_add_payload_map(session,
10413  "PROXY-VID",
10414  NULL,
10415  NULL,
10417  0,
10418  90000,
10419  90000,
10420  1,
10421  SWITCH_TRUE);
10422 
10423  v_engine->cur_payload_map = pmap;
10424 
10425  switch_channel_set_flag(session->channel, CF_VIDEO);
10426  switch_channel_set_flag(session->channel, CF_VIDEO_POSSIBLE);
10427  }
10428 }
10429 
10430 
10432 {
10433  const char *ip;
10434  const char *port;
10435  const char *a_ip;
10436  const char *r_ip;
10437  const char *r_port;
10438  const char *tmp;
10439  switch_rtp_engine_t *a_engine, *v_engine;
10440  switch_media_handle_t *smh;
10441 
10442  switch_assert(session);
10443 
10444  if (!(smh = session->media_handle)) {
10445  return;
10446  }
10447 
10450 
10451  if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) || !(ip && port)) {
10452  return;
10453  } else {
10457  }
10458 
10459  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
10460  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
10461 
10462  a_engine->cur_payload_map->iananame = a_engine->cur_payload_map->rm_encoding = (char *) switch_channel_get_variable(session->channel, "rtp_use_codec_name");
10463  a_engine->cur_payload_map->rm_fmtp = (char *) switch_channel_get_variable(session->channel, "rtp_use_codec_fmtp");
10464 
10465  if ((tmp = switch_channel_get_variable(session->channel, SWITCH_R_SDP_VARIABLE))) {
10466  smh->mparams->remote_sdp_str = switch_core_session_strdup(session, tmp);
10467  }
10468 
10469  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_timer_name"))) {
10470  smh->mparams->timer_name = switch_core_session_strdup(session, tmp);
10471  }
10472 
10473  if ((tmp = switch_channel_get_variable(session->channel, "rtp_last_audio_codec_string"))) {
10474  const char *vtmp = switch_channel_get_variable(session->channel, "rtp_last_video_codec_string");
10475  switch_channel_set_variable_printf(session->channel, "rtp_use_codec_string", "%s%s%s", tmp, vtmp ? "," : "", vtmp ? vtmp : "");
10476  }
10477 
10478  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_string"))) {
10479  char *tmp_codec_string = switch_core_session_strdup(smh->session, tmp);
10480  smh->codec_order_last = switch_separate_string(tmp_codec_string, ',', smh->codec_order, SWITCH_MAX_CODECS);
10482  }
10483 
10484  if ((tmp = switch_channel_get_variable(session->channel, "rtp_2833_send_payload"))) {
10485  smh->mparams->te = (switch_payload_t)atoi(tmp);
10486  }
10487 
10488  if ((tmp = switch_channel_get_variable(session->channel, "rtp_2833_recv_payload"))) {
10489  smh->mparams->recv_te = (switch_payload_t)atoi(tmp);
10490  }
10491 
10492  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_rate"))) {
10493  a_engine->cur_payload_map->rm_rate = atoi(tmp);
10494  a_engine->cur_payload_map->adv_rm_rate = a_engine->cur_payload_map->rm_rate;
10495  }
10496 
10497  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_ptime"))) {
10498  a_engine->cur_payload_map->codec_ms = atoi(tmp);
10499  }
10500 
10501  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_channels"))) {
10502  a_engine->cur_payload_map->channels = atoi(tmp);
10503  }
10504 
10505  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_pt"))) {
10506  a_engine->cur_payload_map->pt = a_engine->cur_payload_map->agreed_pt = (switch_payload_t)(smh->payload_space = atoi(tmp));
10507  }
10508 
10509  if ((tmp = switch_channel_get_variable(session->channel, "rtp_audio_recv_pt"))) {
10510  a_engine->cur_payload_map->recv_pt = (switch_payload_t)atoi(tmp);
10511  }
10512 
10513  switch_core_media_set_codec(session, 0, smh->mparams->codec_flags);
10514 
10515  a_engine->adv_sdp_ip = smh->mparams->extrtpip = (char *) ip;
10516  a_engine->adv_sdp_port = a_engine->local_sdp_port = (switch_port_t)atoi(port);
10517  a_engine->codec_negotiated = 1;
10518 
10519  if (!zstr(ip)) {
10520  a_engine->local_sdp_ip = switch_core_session_strdup(session, ip);
10521  smh->mparams->rtpip = a_engine->local_sdp_ip;
10522  }
10523 
10524  if (!zstr(a_ip)) {
10525  a_engine->adv_sdp_ip = switch_core_session_strdup(session, a_ip);
10526  }
10527 
10528  if (r_ip && r_port) {
10529  a_engine->cur_payload_map->remote_sdp_ip = (char *) r_ip;
10530  a_engine->cur_payload_map->remote_sdp_port = (switch_port_t)atoi(r_port);
10531  }
10532 
10533  if (switch_channel_test_flag(session->channel, CF_VIDEO)) {
10534  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_video_pt"))) {
10535  v_engine->cur_payload_map->pt = v_engine->cur_payload_map->agreed_pt = (switch_payload_t)atoi(tmp);
10536  }
10537 
10538  if ((tmp = switch_channel_get_variable(session->channel, "rtp_video_recv_pt"))) {
10539  v_engine->cur_payload_map->recv_pt = (switch_payload_t)atoi(tmp);
10540  }
10541 
10542  v_engine->cur_payload_map->rm_encoding = (char *) switch_channel_get_variable(session->channel, "rtp_use_video_codec_name");
10543  v_engine->cur_payload_map->rm_fmtp = (char *) switch_channel_get_variable(session->channel, "rtp_use_video_codec_fmtp");
10544  v_engine->codec_negotiated = 1;
10545 
10550 
10551  switch_channel_set_flag(session->channel, CF_VIDEO_POSSIBLE);
10552 
10553  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_video_codec_rate"))) {
10554  v_engine->cur_payload_map->rm_rate = atoi(tmp);
10555  v_engine->cur_payload_map->adv_rm_rate = v_engine->cur_payload_map->rm_rate;
10556  }
10557 
10558  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_video_codec_ptime"))) {
10559  v_engine->cur_payload_map->codec_ms = atoi(tmp);
10560  }
10561 
10562  v_engine->adv_sdp_port = v_engine->local_sdp_port = (switch_port_t)atoi(port);
10563  v_engine->local_sdp_ip = smh->mparams->rtpip;
10564 
10565  if (r_ip && r_port) {
10566  v_engine->cur_payload_map->remote_sdp_ip = (char *) r_ip;
10567  v_engine->cur_payload_map->remote_sdp_port = (switch_port_t)atoi(r_port);
10568  }
10569  }
10570 
10571  switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 1);
10573 
10575  return;
10576  }
10577 
10580 
10581 
10582  if ((tmp = switch_channel_get_variable(session->channel, "rtp_last_audio_local_crypto_key")) && a_engine->ssec[a_engine->crypto_type].remote_crypto_key) {
10583  int idx = atoi(tmp);
10584 
10585  a_engine->ssec[a_engine->crypto_type].local_crypto_key = switch_core_session_strdup(session, tmp);
10589 
10591  a_engine->crypto_type,
10592  a_engine->ssec[a_engine->crypto_type].local_raw_key,
10593  SUITES[a_engine->crypto_type].keylen);
10594 
10596  a_engine->ssec[a_engine->crypto_type].crypto_tag,
10597  a_engine->crypto_type,
10598  a_engine->ssec[a_engine->crypto_type].remote_raw_key,
10599  SUITES[a_engine->crypto_type].keylen);
10600  }
10601 
10602 
10606  }
10607 
10608 }
10609 
10610 
10612 {
10614 
10615  video_globals.cpu_count = switch_core_cpu_count();
10616  video_globals.cur_cpu = 0;
10617 
10618  switch_core_new_memory_pool(&video_globals.pool);
10619  switch_mutex_init(&video_globals.mutex, SWITCH_MUTEX_NESTED, video_globals.pool);
10620 
10621 }
10622 
10624 {
10625  switch_core_destroy_memory_pool(&video_globals.pool);
10626 }
10627 
10628 static int payload_number(const char *name)
10629 {
10630  if (!strcasecmp(name, "pcmu")) {
10631  return 0;
10632  }
10633 
10634  if (!strcasecmp(name, "pcma")) {
10635  return 8;
10636  }
10637 
10638  if (!strcasecmp(name, "gsm")) {
10639  return 3;
10640  }
10641 
10642  if (!strcasecmp(name, "g722")) {
10643  return 9;
10644  }
10645 
10646  if (!strcasecmp(name, "g729")) {
10647  return 18;
10648  }
10649 
10650  if (!strcasecmp(name, "dvi4")) {
10651  return 5;
10652  }
10653 
10654  if (!strcasecmp(name, "h261")) {
10655  return 31;
10656  }
10657 
10658  if (!strcasecmp(name, "h263")) {
10659  return 34;
10660  }
10661 
10662  return -1;
10663 }
10664 
10665 static int find_pt(const char *sdp, const char *name)
10666 {
10667  const char *p;
10668 
10669  if ((p = switch_stristr(name, sdp))) {
10670  if (p < end_of_p(sdp) && *(p+strlen(name)) == '/' && *(p-1) == ' ') {
10671  p -= 2;
10672 
10673  while(*p > 47 && *p < 58) {
10674  p--;
10675  }
10676  p++;
10677 
10678  if (p) {
10679  return atoi(p);
10680  }
10681  }
10682  }
10683 
10684  return -1;
10685 }
10686 
10687 
10688 SWITCH_DECLARE(char *) switch_core_media_filter_sdp(const char *sdp_str, const char *cmd, const char *arg)
10689 {
10690  char *new_sdp = NULL;
10691  int pt = -1, te = -1;
10692  switch_size_t len;
10693  const char *i;
10694  char *o;
10695  int in_m = 0, m_tally = 0, slash = 0;
10696  int number = 0, skip = 0;
10697  int remove = !strcasecmp(cmd, "remove");
10698  int only = !strcasecmp(cmd, "only");
10699  char *end = end_of_p((char *)sdp_str);
10700  int tst;
10701  end++;
10702 
10703 
10704  if (remove || only) {
10705  pt = payload_number(arg);
10706 
10707  if (pt < 0) {
10708  pt = find_pt(sdp_str, arg);
10709  }
10710  } else {
10711  return NULL;
10712  }
10713 
10714  if (only) {
10715  te = find_pt(sdp_str, "telephone-event");
10716  }
10717 
10718 
10719  len = strlen(sdp_str) + 2;
10720  new_sdp = malloc(len);
10721  o = new_sdp;
10722  i = sdp_str;
10723 
10724 
10725  while(i && *i && i < end) {
10726 
10727  if (*i == 'm' && *(i+1) == '=') {
10728  in_m = 1;
10729  m_tally++;
10730  }
10731 
10732  if (in_m) {
10733  if (*i == '\r' || *i == '\n') {
10734  in_m = 0;
10735  slash = 0;
10736  } else {
10737  if (*i == '/') {
10738  slash++;
10739  while(*i != ' ' && i < end) {
10740  *o++ = *i++;
10741  }
10742 
10743  *o++ = *i++;
10744  }
10745 
10746  if (slash && switch_is_leading_number(i)) {
10747 
10748 
10749  number = atoi(i);
10750 
10751  while(i < end && ((*i > 47 && *i < 58) || *i == ' ')) {
10752 
10753  if (remove) {
10754  tst = (number != pt);
10755  } else {
10756  tst = (number == pt || number == te);
10757  }
10758 
10759  if (tst) {
10760  *o++ = *i;
10761  }
10762  i++;
10763 
10764  if (*i == ' ') {
10765  break;
10766  }
10767 
10768  }
10769 
10770  if (remove) {
10771  tst = (number == pt);
10772  } else {
10773  tst = (number != pt && number != te);
10774  }
10775 
10776  if (tst) {
10777  skip++;
10778  }
10779  }
10780  }
10781  }
10782 
10783  while (i < end && !strncasecmp(i, "a=rtpmap:", 9)) {
10784  const char *t = i + 9;
10785 
10786  number = atoi(t);
10787 
10788  if (remove) {
10789  tst = (number == pt);
10790  } else {
10791  tst = (number != pt && number != te);
10792  }
10793 
10794  while(i < end && (*i != '\r' && *i != '\n')) {
10795  if (!tst) *o++ = *i;
10796  i++;
10797  }
10798 
10799  while(i < end && (*i == '\r' || *i == '\n')) {
10800  if (!tst) *o++ = *i;
10801  i++;
10802  }
10803  }
10804 
10805  while (i < end && !strncasecmp(i, "a=fmtp:", 7)) {
10806  const char *t = i + 7;
10807 
10808  number = atoi(t);
10809 
10810  if (remove) {
10811  tst = (number == pt);
10812  } else {
10813  tst = (number != pt && number != te);
10814  }
10815 
10816  while(i < end && (*i != '\r' && *i != '\n')) {
10817  if (!tst) *o++ = *i;
10818  i++;
10819  }
10820 
10821  while(i < end && (*i == '\r' || *i == '\n')) {
10822  if (!tst) *o++ = *i;
10823  i++;
10824  }
10825  }
10826 
10827  if (!skip) {
10828  *o++ = *i;
10829  }
10830 
10831  skip = 0;
10832 
10833  i++;
10834  }
10835 
10836  *o = '\0';
10837 
10838  return new_sdp;
10839 }
10840 
10842 {
10844  char *cmd = switch_core_session_strdup(session, cmd_buf);
10845  int argc = 0;
10846  char *argv[50];
10847  int x = 0;
10848  char *patched_sdp = NULL;
10849 
10850  argc = switch_split(cmd, '|', argv);
10851 
10852  for (x = 0; x < argc; x++) {
10853  char *command = argv[x];
10854  char *arg = strchr(command, '(');
10855 
10856  if (arg) {
10857  char *e = switch_find_end_paren(arg, '(', ')');
10858  *arg++ = '\0';
10859  if (e) *e = '\0';
10860  }
10861 
10862  if (zstr(command) || zstr(arg)) {
10863  switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "%s SDP FILTER PARSE ERROR\n", switch_channel_get_name(channel));
10864  } else {
10865  char *tmp_sdp = NULL;
10866 
10867  if (patched_sdp) {
10868  tmp_sdp = switch_core_media_filter_sdp(patched_sdp, command, arg);
10869  } else {
10870  tmp_sdp = switch_core_media_filter_sdp(sdp, command, arg);
10871  }
10872 
10873 
10875  "%s Filter command %s(%s)\nFROM:\n==========\n%s\nTO:\n==========\n%s\n\n",
10876  switch_channel_get_name(channel),
10877  command, arg, patched_sdp ? patched_sdp : sdp, tmp_sdp);
10878 
10879 
10880  if (tmp_sdp) {
10881  switch_safe_free(patched_sdp);
10882  patched_sdp = tmp_sdp;
10883  }
10884  }
10885  }
10886 
10887  return patched_sdp;
10888 
10889 }
10890 
10891 
10893 {
10894  switch_rtp_engine_t *engine = NULL;
10895  switch_media_handle_t *smh = NULL;
10896 
10897  switch_assert(session);
10898 
10899  if (!(smh = session->media_handle)) {
10900  return NULL;
10901  }
10902 
10903  if (!(engine = &smh->engines[mtype])) {
10904  return NULL;
10905  }
10906 
10907  return switch_rtp_get_media_timer(engine->rtp_session);
10908 
10909 }
10910 
10912 {
10914  switch_media_handle_t *smh = NULL;
10915 
10916  switch_assert(session);
10917 
10918  if (!(smh = session->media_handle)) {
10919  return SWITCH_STATUS_FALSE;
10920  }
10921 
10922  if (switch_channel_test_flag(channel, CF_VIDEO)) {
10923  switch_core_session_message_t msg = { 0 };
10925 
10927  return SWITCH_STATUS_BREAK;
10928  }
10929 
10930  smh->last_video_refresh_req = now;
10931 
10932  msg.from = __FILE__;
10934  switch_core_session_receive_message(session, &msg);
10935  return SWITCH_STATUS_SUCCESS;
10936  }
10937 
10938  return SWITCH_STATUS_FALSE;
10939 }
10940 
10942 {
10943  if (switch_channel_test_flag(session->channel, CF_VIDEO)) {
10946  return SWITCH_STATUS_SUCCESS;
10947  }
10948 
10949  return SWITCH_STATUS_FALSE;
10950 }
10951 
10952 
10954  switch_media_type_t mtype,
10955  switch_io_type_t iotype,
10958  void *cmd_data,
10960  void *cmd_arg,
10962  void **ret_data)
10963 {
10964  switch_rtp_engine_t *engine = NULL;
10965  switch_media_handle_t *smh = NULL;
10966  switch_codec_t *codec = NULL;
10967 
10968  switch_assert(session);
10969 
10970  if (!(smh = session->media_handle)) {
10971  return SWITCH_STATUS_FALSE;
10972  }
10973 
10974  if (!(engine = &smh->engines[mtype])) {
10975  return SWITCH_STATUS_NOTIMPL;
10976  }
10977 
10978  if (iotype == SWITCH_IO_READ) {
10979  codec = &engine->read_codec;
10980  } else {
10981  codec = &engine->write_codec;
10982  }
10983 
10984  if (!switch_core_codec_ready(codec)) {
10985  return SWITCH_STATUS_FALSE;
10986  }
10987 
10988  if (mtype == SWITCH_MEDIA_TYPE_VIDEO) {
10989  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
10990  return SWITCH_STATUS_FALSE;
10991  }
10992  }
10993 
10994  if (codec) {
10995  if (cmd == SCC_VIDEO_GEN_KEYFRAME) {
10997 
10998  if (smh->last_codec_refresh && (now - smh->last_codec_refresh) < VIDEO_REFRESH_FREQ) {
10999  return SWITCH_STATUS_BREAK;
11000  }
11001 
11002  smh->last_codec_refresh = now;
11003  switch_channel_set_flag(session->channel, CF_VIDEO_REFRESH_REQ);
11004  }
11005 
11006  return switch_core_codec_control(codec, cmd, ctype, cmd_data, atype, cmd_arg, rtype, ret_data);
11007  }
11008 
11009  return SWITCH_STATUS_FALSE;
11010 }
11011 
11012 
11014  switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
11015 {
11018 
11020  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG3, "Writing video to RECVONLY session\n");
11021  return SWITCH_STATUS_SUCCESS;
11022  }
11023 
11024  if (session->endpoint_interface->io_routines->write_video_frame) {
11025  if ((status = session->endpoint_interface->io_routines->write_video_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
11026  for (ptr = session->event_hooks.video_write_frame; ptr; ptr = ptr->next) {
11027  if ((status = ptr->video_write_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
11028  break;
11029  }
11030  }
11031  }
11032  }
11033 
11034  return status;
11035 }
11036 
11038 {
11039  switch_media_handle_t *smh;
11040  int type;
11041 
11042  switch_assert(session);
11043 
11044  if (!(smh = session->media_handle)) {
11045  return;
11046  }
11047 
11048  if (switch_channel_down(session->channel)) {
11049  return;
11050  }
11051 
11052  smh->video_init = 0;
11053  smh->video_last_key_time = 0;
11055 
11056  type = 1;
11059 
11060 }
11061 
11063  int stream_id)
11064 {
11068  switch_timer_t *timer;
11069  switch_media_handle_t *smh;
11070  switch_image_t *dup_img = NULL, *img = frame->img;
11071  switch_status_t encode_status;
11072  switch_frame_t write_frame = {0};
11073  //switch_rtp_engine_t *v_engine;
11074 
11075  switch_assert(session);
11076 
11077  if (!(smh = session->media_handle)) {
11078  return SWITCH_STATUS_FALSE;
11079  }
11080 
11081  if (switch_channel_down(session->channel)) {
11082  return SWITCH_STATUS_FALSE;
11083  }
11084 
11085  if (!codec) {
11086  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s has no video codec\n", switch_core_session_get_name(session));
11087  return SWITCH_STATUS_FALSE;
11088  }
11089 
11091  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG3, "Writing video to RECVONLY session\n");
11092  return SWITCH_STATUS_SUCCESS;
11093  }
11094 
11095  if (switch_channel_test_flag(session->channel, CF_VIDEO_PAUSE_WRITE)) {
11096  return SWITCH_STATUS_SUCCESS;
11097  }
11098 
11099  if (!(switch_channel_test_flag(session->channel, CF_VIDEO_READY) || (flags & SWITCH_IO_FLAG_FORCE))) {
11100  return SWITCH_STATUS_SUCCESS;
11101  }
11102 
11103  //v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
11105  /* return CNG, another thread is already writing */
11106  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s is already being written to for %s\n",
11108  return SWITCH_STATUS_INUSE;
11109  }
11110 
11111  if (!smh->video_init && smh->mparams->video_key_first && (now - smh->video_last_key_time) > smh->mparams->video_key_first) {
11113 
11114  if (smh->video_last_key_time) {
11115  smh->video_init = 1;
11116  }
11117 
11118  smh->video_last_key_time = now;
11119  }
11120 
11121  if (smh->mparams->video_key_freq && (now - smh->video_last_key_time) > smh->mparams->video_key_freq) {
11123  smh->video_last_key_time = now;
11124  }
11125 
11126  if (!img) {
11127  switch_status_t vstatus = switch_core_session_write_encoded_video_frame(session, frame, flags, stream_id);
11128  switch_goto_status(vstatus, done);
11129  }
11130 
11131 
11132  /* When desired, scale video to match the input signal (if output is bigger) */
11133  if (switch_channel_test_flag(session->channel, CF_VIDEO_READY) && smh->vid_params.width &&
11134  switch_channel_test_flag(session->channel, CF_VIDEO_MIRROR_INPUT) &&
11135  ((smh->vid_params.width != img->d_w) || (smh->vid_params.height != img->d_h))) {
11136 
11137  switch_img_letterbox(img, &dup_img, smh->vid_params.width, smh->vid_params.height, "#000000f");
11138 
11139  img = dup_img;
11140  }
11141 
11142  if (session->bugs) {
11143  switch_media_bug_t *bp;
11144  int prune = 0;
11145  int patched = 0;
11146 
11147  switch_thread_rwlock_rdlock(session->bug_rwlock);
11148  for (bp = session->bugs; bp; bp = bp->next) {
11150 
11152  continue;
11153  }
11154 
11156  continue;
11157  }
11158 
11159  if (switch_test_flag(bp, SMBF_PRUNE)) {
11160  prune++;
11161  continue;
11162  }
11163 
11165  switch_image_t *dimg = NULL;
11166 
11167  switch_img_copy(img, &dimg);
11169 
11172  patched = 1;
11173  }
11174 
11175  }
11176 
11177  if (bp->ready && img &&
11179  switch_frame_t bug_frame = { 0 };
11180 
11181  bug_frame.img = img;
11182 
11184  bp->video_ping_frame = &bug_frame;
11186  || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) {
11187  ok = SWITCH_FALSE;
11188  }
11189  bp->video_ping_frame = NULL;
11190  }
11191 
11194  }
11195 
11196 
11197  }
11198 
11199  if (ok == SWITCH_FALSE) {
11201  prune++;
11202  }
11203 
11204  }
11205 
11206  switch_thread_rwlock_unlock(session->bug_rwlock);
11207 
11208  if (prune) {
11209  switch_core_media_bug_prune(session);
11210  }
11211 
11212  }
11213 
11214  write_frame = *frame;
11215  frame = &write_frame;
11216  frame->img = img;
11217 
11219 
11220  if (!(timer = switch_core_media_get_timer(session, SWITCH_MEDIA_TYPE_VIDEO))) {
11221 
11222  if (!smh->video_timer.timer_interface) {
11223  switch_core_timer_init(&smh->video_timer, "soft", 1, 90, switch_core_session_get_pool(session));
11224  }
11226  timer = &smh->video_timer;
11227  }
11228 
11229  frame->timestamp = timer->samplecount;
11230  }
11231 
11233  frame->m = 0;
11234 
11235  do {
11236  frame->datalen = SWITCH_DEFAULT_VIDEO_SIZE;
11237  encode_status = switch_core_codec_encode_video(codec, frame);
11238 
11239  if (encode_status == SWITCH_STATUS_SUCCESS || encode_status == SWITCH_STATUS_MORE_DATA) {
11240 
11241  switch_assert((encode_status == SWITCH_STATUS_SUCCESS && frame->m) || !frame->m);
11242 
11243  if (frame->flags & SFF_PICTURE_RESET) {
11245  frame->flags &= ~SFF_PICTURE_RESET;
11246  }
11247 
11248  if (frame->datalen == 0) break;
11249 
11251  status = switch_core_session_write_encoded_video_frame(session, frame, flags, stream_id);
11252  }
11253 
11254  } while(status == SWITCH_STATUS_SUCCESS && encode_status == SWITCH_STATUS_MORE_DATA);
11255 
11256  done:
11257 
11260  }
11261 
11262  switch_img_free(&dup_img);
11263 
11264  return status;
11265 }
11266 
11268 {
11269  switch_media_handle_t *smh;
11270  switch_codec_implementation_t read_impl = { 0 };
11271  switch_rtp_engine_t *v_engine = NULL;
11272 
11273  switch_assert(session != NULL);
11274 
11275  if (!(smh = session->media_handle)) {
11276  return SWITCH_STATUS_FALSE;
11277  }
11278 
11279  if (!switch_channel_test_flag(session->channel, CF_VIDEO_DECODED_READ)) {
11280  return SWITCH_STATUS_GENERR;;
11281  }
11282 
11283  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
11284 
11285  if (v_engine->smode == SWITCH_MEDIA_FLOW_SENDONLY) {
11286  return SWITCH_STATUS_NOTIMPL;
11287  }
11288 
11289  switch_core_session_get_read_impl(session, &read_impl);
11290 
11291  while(switch_channel_ready(session->channel) && timeout_ms > 0) {
11292  switch_frame_t *read_frame;
11293  switch_status_t status;
11294 
11295  if (video_globals.synced &&
11296  switch_channel_test_flag(session->channel, CF_VIDEO_READY) && smh->vid_params.width && smh->vid_params.height && smh->vid_params.fps) {
11297  return SWITCH_STATUS_SUCCESS;
11298  }
11299 
11301  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
11302 
11303  if (!SWITCH_READ_ACCEPTABLE(status)) {
11304  return SWITCH_STATUS_FALSE;
11305  }
11306 
11307  timeout_ms -= (read_impl.microseconds_per_packet / 1000);
11308  }
11309 
11310  return SWITCH_STATUS_TIMEOUT;
11311 
11312 }
11313 
11315  int stream_id)
11316 {
11319  uint32_t loops = 0;
11320  switch_media_handle_t *smh;
11321 
11322  switch_assert(session != NULL);
11323 
11324  if (!(smh = session->media_handle)) {
11325  return SWITCH_STATUS_FALSE;
11326  }
11327 
11328  top:
11329 
11330  loops++;
11331 
11332  if (switch_channel_down_nosig(session->channel)) {
11333  return SWITCH_STATUS_FALSE;
11334  }
11335 
11336  if (session->endpoint_interface->io_routines->read_video_frame) {
11337  if ((status = session->endpoint_interface->io_routines->read_video_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
11338  for (ptr = session->event_hooks.video_read_frame; ptr; ptr = ptr->next) {
11339  if ((status = ptr->video_read_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
11340  break;
11341  }
11342  }
11343  }
11344  }
11345 
11346  if (switch_channel_test_flag(session->channel, CF_VIDEO_PAUSE_READ)) {
11347  *frame = &runtime.dummy_cng_frame;
11348  switch_cond_next();
11349  return SWITCH_STATUS_SUCCESS;
11350  }
11351 
11352  if (status == SWITCH_STATUS_INUSE) {
11353  *frame = &runtime.dummy_cng_frame;
11354  switch_cond_next();
11355  return SWITCH_STATUS_SUCCESS;
11356  }
11357 
11358  if (status != SWITCH_STATUS_SUCCESS) {
11359  goto done;
11360  }
11361 
11362  if (!(*frame)) {
11363  goto done;
11364  }
11365 
11366  if (switch_channel_test_flag(session->channel, CF_VIDEO_DEBUG_READ)) {
11367  if (switch_test_flag((*frame), SFF_CNG)) {
11369  } else {
11371  "VIDEO: seq: %d ts: %u len: %4d %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x mark: %d\n",
11372  (*frame)->seq, (*frame)->timestamp, (*frame)->datalen,
11373  *((uint8_t *)(*frame)->data), *((uint8_t *)(*frame)->data + 1),
11374  *((uint8_t *)(*frame)->data + 2), *((uint8_t *)(*frame)->data + 3),
11375  *((uint8_t *)(*frame)->data + 4), *((uint8_t *)(*frame)->data + 5),
11376  *((uint8_t *)(*frame)->data + 6), *((uint8_t *)(*frame)->data + 7),
11377  *((uint8_t *)(*frame)->data + 8), *((uint8_t *)(*frame)->data + 9),
11378  *((uint8_t *)(*frame)->data + 10), (*frame)->m);
11379  }
11380  }
11381 
11382 
11383  if (switch_test_flag(*frame, SFF_CNG)) {
11384  status = SWITCH_STATUS_SUCCESS;
11385  goto done;
11386  }
11387 
11388  if (switch_channel_test_flag(session->channel, CF_VIDEO_DECODED_READ) && (*frame)->img == NULL) {
11389  switch_status_t decode_status;
11390 
11391  (*frame)->img = NULL;
11392 
11393  decode_status = switch_core_codec_decode_video((*frame)->codec, *frame);
11394 
11395  if ((*frame)->img && switch_channel_test_flag(session->channel, CF_VIDEO_DEBUG_READ)) {
11396  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "IMAGE %dx%d %dx%d\n",
11397  (*frame)->img->w, (*frame)->img->h, (*frame)->img->d_w, (*frame)->img->d_h);
11398  }
11399 
11400  if ((*frame)->img && (*frame)->img->d_w && (*frame)->img->d_h) {
11401 
11402  if ((*frame)->img->d_w != smh->vid_params.width) {
11403  switch_channel_set_variable_printf(session->channel, "video_width", "%d", (*frame)->img->d_w);
11404  smh->vid_params.width = (*frame)->img->d_w;
11405  }
11406 
11407  if ((*frame)->img->d_h != smh->vid_params.height) {
11408  switch_channel_set_variable_printf(session->channel, "video_height", "%d", (*frame)->img->d_h);
11409  smh->vid_params.height = (*frame)->img->d_h;
11410  }
11411  }
11412 
11413  if (switch_test_flag((*frame), SFF_WAIT_KEY_FRAME)) {
11416 
11417  if (!(*frame)->img) {
11418  *frame = &runtime.dummy_cng_frame;
11419  switch_cond_next();
11420  return SWITCH_STATUS_SUCCESS;
11421  }
11422  }
11423 
11424  if (decode_status == SWITCH_STATUS_MORE_DATA || !(*frame)->img) {
11425  goto top;
11426  }
11427  }
11428 
11429  if (!switch_channel_test_flag(session->channel, CF_VIDEO_READY) && *frame) {
11430  if (((switch_channel_test_flag(session->channel, CF_VIDEO_DECODED_READ) && (*frame)->img) || (*frame)->m) && ++smh->ready_loops > 5) {
11431  switch_channel_set_flag(session->channel, CF_VIDEO_READY);
11432  }
11433  }
11434 
11435  done:
11436 
11437  if (session->bugs) {
11438  switch_media_bug_t *bp;
11439  int prune = 0;
11440  int patched = 0;
11441 
11442  switch_thread_rwlock_rdlock(session->bug_rwlock);
11443  for (bp = session->bugs; bp; bp = bp->next) {
11445 
11447  continue;
11448  }
11449 
11451  continue;
11452  }
11453 
11454  if (switch_test_flag(bp, SMBF_PRUNE)) {
11455  prune++;
11456  continue;
11457  }
11458 
11459  if (bp->ready && switch_test_flag(bp, SMBF_READ_VIDEO_STREAM)) {
11460  if ((*frame) && (*frame)->img) {
11461  switch_image_t *img = NULL;
11462  switch_img_copy((*frame)->img, &img);
11466  patched = 1;
11467  }
11468  }
11469  }
11470 
11471  if (bp->ready && (*frame) && (*frame)->img &&
11473 
11474 
11476  bp->video_ping_frame = *frame;
11478  || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) {
11479  ok = SWITCH_FALSE;
11480  }
11481  bp->video_ping_frame = NULL;
11482  }
11483 
11486  }
11487  }
11488 
11489  if (ok == SWITCH_FALSE) {
11491  prune++;
11492  }
11493  }
11494 
11495  switch_thread_rwlock_unlock(session->bug_rwlock);
11496 
11497  if (prune) {
11498  switch_core_media_bug_prune(session);
11499  }
11500  }
11501 
11502 
11503 
11504  if (status == SWITCH_STATUS_SUCCESS) {
11505  switch_core_session_video_read_callback(session, *frame);
11506  }
11507 
11508  return status;
11509 }
11510 
11512  switch_core_video_thread_callback_func_t func, void *user_data)
11513 {
11515  switch_media_handle_t *smh;
11516 
11517  if (!(smh = session->media_handle)) {
11518  return SWITCH_STATUS_FALSE;
11519  }
11520 
11522  if (!func) {
11523  session->video_read_callback = NULL;
11524  session->video_read_user_data = NULL;
11525  } else if (session->video_read_callback) {
11526  status = SWITCH_STATUS_FALSE;
11527  } else {
11528  session->video_read_callback = func;
11529  session->video_read_user_data = user_data;
11530  }
11531 
11534 
11535  return status;
11536 }
11537 
11539 {
11540  switch_media_handle_t *smh;
11542 
11543  if (!(smh = session->media_handle)) {
11544  return SWITCH_STATUS_FALSE;
11545  }
11546 
11548 
11549  if (session->video_read_callback) {
11550  status = session->video_read_callback(session, frame, session->video_read_user_data);
11551  }
11552 
11554 
11555  return status;
11556 }
11557 
11558 
11559 /* For Emacs:
11560  * Local Variables:
11561  * mode:c
11562  * indent-tabs-mode:t
11563  * tab-width:4
11564  * c-basic-offset:4
11565  * End:
11566  * For VIM:
11567  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
11568  */
11569 
struct switch_video_codec_settings video
switch_status_t switch_channel_set_variable_printf(switch_channel_t *channel, const char *varname, const char *fmt,...)
switch_status_t switch_core_codec_decode_video(switch_codec_t *codec, switch_frame_t *frame)
Decode video data using a codec handle.
switch_status_t switch_core_media_set_video_file(switch_core_session_t *session, switch_file_handle_t *fh, switch_rw_t rw)
#define SWITCH_MAX_CODECS
Definition: switch_types.h:558
char * generation
Definition: switch_rtp.h:98
switch_status_t switch_core_session_start_video_thread(switch_core_session_t *session)
switch_core_session_t * session
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:310
int cand_idx[2]
Definition: switch_rtp.h:106
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:412
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it's state machine to end.
#define switch_core_media_gen_key_frame(_session)
switch_status_t switch_channel_execute_on(switch_channel_t *channel, const char *variable_prefix)
switch_size_t flaws
Definition: switch_types.h:657
switch_status_t switch_core_media_reset_jb(switch_core_session_t *session, switch_media_type_t type)
switch_bool_t m
Definition: switch_frame.h:72
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core's master pool.
Definition: switch_core.h:631
void switch_channel_set_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
switch_status_t switch_thread_rwlock_unlock(switch_thread_rwlock_t *rwlock)
Definition: switch_apr.c:263
#define add_stat(_i, _s)
switch_status_t switch_rtp_activate_rtcp(switch_rtp_t *rtp_session, int send_rate, switch_port_t remote_port, switch_bool_t mux)
Activate sending RTCP Sender Reports (SR's)
Definition: switch_rtp.c:4186
char * switch_core_session_sprintf(_In_ switch_core_session_t *session, _In_z_ _Printf_format_string_ const char *fmt,...)
printf-style style printing routine. The data is output to a string allocated from the session ...
unsigned char remote_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN]
uint8_t allocated
switch_status_t switch_thread_cond_create(switch_thread_cond_t **cond, switch_memory_pool_t *pool)
Definition: switch_apr.c:350
switch_frame_t dummy_cng_frame
void switch_ivr_bg_media(const char *uuid, switch_media_flag_t flags, switch_bool_t on, switch_bool_t is3p, uint32_t delay)
Definition: switch_ivr.c:2014
#define SWITCH_CHANNEL_SESSION_LOG(x)
switch_status_t switch_core_codec_parse_fmtp(const char *codec_name, const char *fmtp, uint32_t rate, switch_codec_fmtp_t *codec_fmtp)
Image Descriptor.
Definition: switch_image.h:88
void switch_core_session_clear_crypto(switch_core_session_t *session)
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:631
switch_rtp_numbers_t inbound
Definition: switch_types.h:690
#define SWITCH_THREAD_FUNC
switch_core_media_flag_t media_flags[SCMF_MAX]
uint8_t switch_rtp_ready(switch_rtp_t *rtp_session)
Test if an RTP session is ready.
Definition: switch_rtp.c:4452
switch_status_t switch_core_timer_init(switch_timer_t *timer, const char *timer_name, int interval, int samples, switch_memory_pool_t *pool)
Request a timer handle using given time module.
static switch_t38_options_t * switch_core_media_process_udptl(switch_core_session_t *session, sdp_session_t *sdp, sdp_media_t *m)
switch_core_session_message_types_t message_id
Definition: switch_core.h:181
#define SWITCH_CHANNEL_LOG
void switch_core_session_reset(_In_ switch_core_session_t *session, switch_bool_t flush_dtmf, switch_bool_t reset_read_codec)
Reset the buffers and resampler on a session.
switch_rtp_crypto_key_type_t
switch_status_t switch_mutex_trylock(switch_mutex_t *lock)
Definition: switch_apr.c:295
switch_status_t switch_channel_set_variable_name_printf(switch_channel_t *channel, const char *val, const char *fmt,...)
switch_status_t switch_channel_queue_dtmf(_In_ switch_channel_t *channel, _In_ const switch_dtmf_t *dtmf)
Queue DTMF on a given channel.
uint32_t switch_channel_test_flag_partner(switch_channel_t *channel, switch_channel_flag_t flag)
switch_status_t switch_core_media_udptl_mode(switch_core_session_t *session, switch_media_type_t type)
static switch_media_flow_t sdp_media_flow(unsigned in)
static void switch_core_media_set_r_sdp_codec_string(switch_core_session_t *session, const char *codec_string, sdp_session_t *sdp, switch_sdp_type_t sdp_type)
static int payload_number(const char *name)
char * switch_find_end_paren(const char *s, char open, char close)
Definition: switch_utils.c:661
static char * get_setup(switch_rtp_engine_t *engine, switch_core_session_t *session, switch_sdp_type_t sdp_type)
switch_status_t switch_core_media_process_t38_passthru(switch_core_session_t *session, switch_core_session_t *other_session, switch_t38_options_t *t38_options)
const char * switch_core_session_local_crypto_key(switch_core_session_t *session, switch_media_type_t type)
void switch_img_free(switch_image_t **img)
Close an image descriptor.
void(* switch_video_function_t)(switch_core_session_t *session, void *user_data)
switch_status_t switch_core_media_set_video_codec(switch_core_session_t *session, int force)
const char * switch_channel_get_partner_uuid(switch_channel_t *channel)
switch_status_t switch_channel_set_private(switch_channel_t *channel, const char *key, const void *private_info)
Set private data on channel.
switch_status_t switch_core_session_set_video_read_callback(switch_core_session_t *session, switch_core_video_thread_callback_func_t func, void *user_data)
static switch_status_t check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_session_t *sdp, sdp_media_t *m)
void switch_rtp_reset(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:2789
void switch_media_handle_set_media_flags(switch_media_handle_t *smh, switch_core_media_flag_t flags[SCMF_MAX])
uint32_t switch_io_flag_t
char * switch_core_media_process_sdp_filter(const char *sdp, const char *cmd_buf, switch_core_session_t *session)
switch_video_function_t video_function
switch_status_t switch_rtp_ack_bitrate(switch_rtp_t *rtp_session, uint32_t bps)
Definition: switch_rtp.c:4351
switch_status_t(* switch_core_video_thread_callback_func_t)(switch_core_session_t *session, switch_frame_t *frame, void *user_data)
unsigned long rm_rate
switch_status_t switch_core_session_get_payload_code(switch_core_session_t *session, switch_media_type_t type, const char *iananame, uint32_t rate, switch_payload_t *ptP, switch_payload_t *recv_ptP, char **fmtpP)
switch_status_t switch_core_file_read_video(switch_file_handle_t *fh, switch_frame_t *frame, switch_video_read_flag_t flags)
uint8_t switch_core_media_ready(switch_core_session_t *session, switch_media_type_t type)
#define VIDEO_REFRESH_FREQ
int chosen[2]
Definition: switch_rtp.h:107
void switch_core_media_kill_socket(switch_core_session_t *session, switch_media_type_t type)
#define switch_channel_stop_broadcast(_channel)
switch_status_t switch_core_session_set_video_read_codec(_In_ switch_core_session_t *session, switch_codec_t *codec)
Assign the video_read codec to a given session.
#define switch_channel_up(_channel)
switch_call_direction_t
Definition: switch_types.h:293
void switch_core_media_pass_zrtp_hash2(switch_core_session_t *aleg_session, switch_core_session_t *bleg_session)
switch_status_t switch_core_media_choose_ports(switch_core_session_t *session, switch_bool_t audio, switch_bool_t video)
switch_bool_t switch_is_leading_number(const char *str)
unsigned long adv_rm_rate
static int get_channels(const char *name, int dft)
switch_bool_t
Definition: switch_types.h:405
uint32_t timestamp
Definition: switch_frame.h:69
#define switch_channel_presence(_a, _b, _c, _d)
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:729
switch_size_t largest_jb_size
Definition: switch_types.h:637
smh_flag_t
#define switch_split(_data, _delim, _array)
Definition: switch_utils.h:342
char * remote_sdp_ip
switch_status_t switch_core_session_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
int switch_core_media_check_nat(switch_media_handle_t *smh, const char *network_ip)
switch_status_t switch_core_media_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
unsigned long hash
switch_port_t remote_port
Definition: switch_rtp.c:398
switch_status_t switch_core_session_set_read_impl(switch_core_session_t *session, const switch_codec_implementation_t *impp)
char * foundation
Definition: switch_rtp.h:89
switch_status_t switch_ivr_broadcast(const char *uuid, const char *path, switch_media_flag_t flags)
Signal the session to broadcast audio.
switch_status_t switch_core_session_set_video_write_codec(_In_ switch_core_session_t *session, switch_codec_t *codec)
Assign the video_write codec to a given session.
switch_core_session_t * session
switch_status_t switch_threadattr_stacksize_set(switch_threadattr_t *attr, switch_size_t stacksize)
Definition: switch_apr.c:660
static void switch_core_session_apply_crypto(switch_core_session_t *session, switch_media_type_t type)
Node in which to store custom video_write_frame channel callback hooks.
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:640
#define SWITCH_LOCAL_VIDEO_IP_VARIABLE
Definition: switch_types.h:214
switch_memory_pool_t * pool
char * raddr
Definition: switch_rtp.h:96
Representation of an event.
Definition: switch_event.h:80
#define switch_channel_ready(_channel)
struct secure_settings_s switch_secure_settings_t
void switch_core_media_check_dtmf_type(switch_core_session_t *session)
switch_queue_t * read_video_queue
struct switch_io_event_hook_video_read_frame * next
struct switch_rtcp_report_block_frame reports[MAX_REPORT_BLOCKS]
switch_status_t switch_core_session_read_lock(_In_ switch_core_session_t *session)
Acquire a read lock on the session.
#define SWITCH_RTP_MAX_BUF_LEN
Definition: switch_rtp.h:44
switch_rtp_crypto_direction_t
Definition: switch_rtp.h:57
const char * switch_core_media_crypto_type2str(switch_rtp_crypto_key_type_t type)
static void generate_local_fingerprint(switch_media_handle_t *smh, switch_media_type_t type)
static void clear_pmaps(switch_rtp_engine_t *engine)
switch_media_flow_t smode
switch_status_t switch_rtp_pause_jitter_buffer(switch_rtp_t *rtp_session, switch_bool_t pause)
Definition: switch_rtp.c:4059
switch_status_t switch_core_media_ext_address_lookup(switch_core_session_t *session, char **ip, switch_port_t *port, const char *sourceip)
void switch_core_media_start_video_function(switch_core_session_t *session, switch_video_function_t video_function, void *user_data)
switch_bool_t T38FaxTranscodingMMR
switch_core_media_vflag_t vflags
#define switch_channel_media_ready(_channel)
const char * T38FaxRateManagement
Node in which to store custom read frame channel callback hooks.
dtls_state_t switch_rtp_dtls_state(switch_rtp_t *rtp_session, dtls_type_t type)
Definition: switch_rtp.c:3215
char str[MAX_FPSTRLEN]
Definition: switch_core.h:154
switch_status_t switch_core_session_video_read_callback(switch_core_session_t *session, switch_frame_t *frame)
switch_status_t switch_core_session_wait_for_video_input_params(switch_core_session_t *session, uint32_t timeout_ms)
switch_status_t switch_core_media_codec_control(switch_core_session_t *session, switch_media_type_t mtype, switch_io_type_t iotype, switch_codec_control_command_t cmd, switch_codec_control_type_t ctype, void *cmd_data, switch_codec_control_type_t atype, void *cmd_arg, switch_codec_control_type_t *rtype, void **ret_data)
switch_status_t switch_nat_add_mapping(switch_port_t port, switch_nat_ip_proto_t proto, switch_port_t *external_port, switch_bool_t sticky)
Maps a port through the NAT Traversal System.
Definition: switch_nat.c:619
unsigned int switch_ci_hashfunc_default(const char *char_key, switch_ssize_t *klen)
Definition: switch_apr.c:98
switch_status_t switch_rtp_set_payload_map(switch_rtp_t *rtp_session, payload_map_t **pmap)
Definition: switch_rtp.c:2454
switch_thread_cond_t * cond
void switch_core_session_lock_codec_read(_In_ switch_core_session_t *session)
switch_video_write_frame_hook_t video_write_frame
const char * switch_core_media_get_zrtp_hash(switch_core_session_t *session, switch_media_type_t type, switch_bool_t local)
const switch_codec_implementation_t * codecs[SWITCH_MAX_CODECS]
switch_codec_settings_t codec_settings
void switch_core_media_clear_rtp_flag(switch_core_session_t *session, switch_media_type_t type, switch_rtp_flag_t flag)
switch_status_t switch_rtp_add_crypto_key(switch_rtp_t *rtp_session, switch_rtp_crypto_direction_t direction, uint32_t index, switch_rtp_crypto_key_type_t type, unsigned char *key, switch_size_t keylen)
Definition: switch_rtp.c:3468
void switch_rtp_intentional_bugs(switch_rtp_t *rtp_session, switch_rtp_bug_flag_t bugs)
Definition: switch_rtp.c:2467
#define SDPBUFLEN
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
#define end_of(_s)
Definition: switch_utils.h:616
void switch_core_session_set_ice(switch_core_session_t *session)
switch_status_t switch_thread_cond_wait(switch_thread_cond_t *cond, switch_mutex_t *mutex)
Definition: switch_apr.c:355
const char * switch_channel_get_variable_dup(switch_channel_t *channel, const char *varname, switch_bool_t dup, int idx)
Retrieve a variable from a given channel.
#define switch_core_session_get_name(_s)
Definition: switch_core.h:271
struct switch_io_event_hook_video_write_frame * next
switch_rtp_crypto_mode_t crypto_mode
uint32_t switch_core_cpu_count(void)
Definition: switch_core.c:1042
static void gen_ice(switch_core_session_t *session, switch_media_type_t type, const char *ip, switch_port_t port)
void switch_core_media_parse_rtp_bugs(switch_rtp_bug_flag_t *flag_pole, const char *str)
switch_status_t switch_core_session_queue_message(_In_ switch_core_session_t *session, _In_ switch_core_session_message_t *message)
Queue a message on a session.
char * switch_stun_host_lookup(const char *host, switch_memory_pool_t *pool)
Definition: switch_stun.c:688
switch_bool_t T38FaxTranscodingJBIG
switch_size_t media_bytes
Definition: switch_types.h:628
#define SWITCH_LOCAL_VIDEO_PORT_VARIABLE
Definition: switch_types.h:215
static switch_srtp_crypto_suite_t SUITES[CRYPTO_INVALID]
switch_status_t switch_core_media_get_offered_pt(switch_core_session_t *session, const switch_codec_implementation_t *mimp, switch_payload_t *pt)
switch_status_t switch_core_media_set_codec(switch_core_session_t *session, int force, uint32_t codec_flags)
void switch_rtp_set_telephony_recv_event(switch_rtp_t *rtp_session, switch_payload_t te)
Definition: switch_rtp.c:4022
const switch_codec_implementation_t * negotiated_codecs[SWITCH_MAX_CODECS]
switch_status_t switch_core_media_bug_patch_spy_frame(switch_media_bug_t *bug, switch_image_t *img, switch_rw_t rw)
switch_payload_t ianacodes[SWITCH_MAX_CODECS]
void switch_core_media_reset_autofix(switch_core_session_t *session, switch_media_type_t type)
int32_t switch_media_handle_test_media_flag(switch_media_handle_t *smh, switch_core_media_flag_t flag)
Abstract handler to a timer module.
#define SWITCH_DEFAULT_VIDEO_SIZE
Definition: switch_types.h:233
switch_size_t dtmf_packet_count
Definition: switch_types.h:634
void switch_resample_destroy(switch_audio_resampler_t **resampler)
Destroy an existing resampler handle.
static switch_thread_t * thread
Definition: switch_log.c:279
int switch_snprintf(_Out_z_cap_(len) char *buf, _In_ switch_size_t len, _In_z_ _Printf_format_string_ const char *format,...)
struct switch_runtime runtime
Definition: switch_core.c:64
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
uint32_t switch_channel_test_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Test for presence of given flag on a given channel.
static int32_t switch_parse_bandwidth_string(const char *bwv)
switch_thread_id_t thread_id
switch_secure_settings_t ssec[CRYPTO_INVALID+1]
static void switch_core_session_parse_crypto_prefs(switch_core_session_t *session)
switch_size_t switch_b64_decode(char *in, char *out, switch_size_t olen)
Definition: switch_utils.c:929
char * type
Definition: switch_core.h:153
#define switch_check_network_list_ip(_ip_str, _list_name)
Definition: switch_core.h:2404
payload_map_t * payload_map
struct apr_thread_cond_t switch_thread_cond_t
Definition: switch_apr.h:463
void switch_core_media_break(switch_core_session_t *session, switch_media_type_t type)
switch_status_t switch_core_session_read_frame(_In_ switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
Read a frame from a session.
static uint32_t switch_known_bitrate(switch_payload_t payload)
Definition: switch_utils.h:418
switch_status_t switch_core_media_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id, switch_media_type_t type)
#define SWITCH_ADVERTISED_MEDIA_IP_VARIABLE
Definition: switch_types.h:209
switch_codec_t * codec
Definition: switch_frame.h:45
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:177
switch_rtp_bug_flag_t manual_video_rtp_bugs
switch_media_bug_callback_t callback
switch_image_t * switch_img_alloc(switch_image_t *img, switch_img_fmt_t fmt, unsigned int d_w, unsigned int d_h, unsigned int align)
Open a descriptor, allocating storage for the underlying image.
static void switch_core_session_parse_codec_settings(switch_core_session_t *session, switch_media_type_t type)
void switch_rtp_set_max_missed_packets(switch_rtp_t *rtp_session, uint32_t max)
Definition: switch_rtp.c:2753
switch_port_t switch_rtp_get_remote_port(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:2827
struct payload_map_s * next
switch_media_handle_t * media_handle
char * fmtps[SWITCH_MAX_CODECS]
void rtp_flush_read_buffer(switch_rtp_t *rtp_session, switch_rtp_flush_t flush)
Definition: switch_rtp.c:4940
switch_status_t switch_core_thread_set_cpu_affinity(int cpu)
Definition: switch_core.c:1723
struct core_video_globals_s core_video_globals_t
#define end_of_p(_s)
Definition: switch_utils.h:617
void switch_core_session_unset_write_codec(_In_ switch_core_session_t *session)
#define zstr(x)
Definition: switch_utils.h:281
switch_bool_t switch_core_media_check_udptl_mode(switch_core_session_t *session, switch_media_type_t type)
#define SWITCH_LOCAL_MEDIA_PORT_VARIABLE
Definition: switch_types.h:208
static int switch_safe_atoi(const char *nptr, int dft)
Turn a string into a number (default if NULL)
Definition: switch_utils.h:779
void switch_core_media_set_local_sdp(switch_core_session_t *session, const char *sdp_str, switch_bool_t dup)
switch_media_handle_t * switch_core_session_get_media_handle(switch_core_session_t *session)
switch_status_t switch_rtp_udptl_mode(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:2843
switch_thread_t * video_write_thread
switch_video_read_flag_t
void switch_rtp_reset_media_timer(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:2817
unsigned int d_w
Definition: switch_image.h:99
void switch_rtp_set_telephony_event(switch_rtp_t *rtp_session, switch_payload_t te)
Set the payload type to consider RFC2833 DTMF.
Definition: switch_rtp.c:4014
static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice)
Definition: switch_rtp.c:771
switch_queue_t * write_video_queue
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:290
switch_rtp_crypto_key_type_t crypto_suite_order[CRYPTO_INVALID+1]
static void *SWITCH_THREAD_FUNC video_write_thread(switch_thread_t *thread, void *obj)
switch_status_t switch_thread_rwlock_rdlock(switch_thread_rwlock_t *rwlock)
Definition: switch_apr.c:227
switch_status_t switch_thread_join(switch_status_t *retval, switch_thread_t *thd)
Definition: switch_apr.c:1255
switch_status_t switch_core_session_get_read_impl(switch_core_session_t *session, switch_codec_implementation_t *impp)
void switch_media_handle_clear_media_flag(switch_media_handle_t *smh, switch_core_media_flag_t flag)
switch_frame_t read_frame
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
switch_codec_control_command_t
void switch_rtp_destroy(switch_rtp_t **rtp_session)
Destroy an RTP session.
Definition: switch_rtp.c:4491
void switch_core_recovery_track(switch_core_session_t *session)
sdp_rtpmap_t * map
void switch_core_media_pause(switch_core_session_t *session)
static int find_pt(const char *sdp, const char *name)
switch_time_t last_codec_refresh
#define SWITCH_ORIGINATOR_CODEC_VARIABLE
Definition: switch_types.h:205
void switch_channel_clear_app_flag_key(const char *app, switch_channel_t *channel, uint32_t flags)
switch_status_t switch_core_media_codec_chosen(switch_core_session_t *session, switch_media_type_t type)
#define switch_clear_flag(obj, flag)
Clear a flag on an arbitrary object while locked.
Definition: switch_utils.h:655
unsigned char local_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN]
int switch_core_cert_gen_fingerprint(const char *prefix, dtls_fingerprint_t *fp)
void switch_channel_mark_hold(switch_channel_t *channel, switch_bool_t on)
void switch_core_media_check_video_codecs(switch_core_session_t *session)
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
#define SWITCH_RTCP_AUDIO_INTERVAL_MSEC
Definition: switch_types.h:234
switch_status_t switch_rtp_deactivate_jitter_buffer(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:4079
payload_map_t * switch_core_media_add_payload_map(switch_core_session_t *session, switch_media_type_t type, const char *name, const char *modname, const char *fmtp, switch_sdp_type_t sdp_type, uint32_t pt, uint32_t rate, uint32_t ptime, uint32_t channels, uint8_t negotiated)
switch_jb_t * switch_rtp_get_jitter_buffer(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:4050
void switch_core_session_enable_heartbeat(switch_core_session_t *session, uint32_t seconds)
switch_codec_t write_codec
switch_status_t switch_rtp_zerocopy_read_frame(switch_rtp_t *rtp_session, switch_frame_t *frame, switch_io_flag_t io_flags)
Read data from a given RTP session without copying.
Definition: switch_rtp.c:7036
switch_bool_t switch_core_session_in_video_thread(switch_core_session_t *session)
void switch_core_media_patch_sdp(switch_core_session_t *session)
switch_status_t switch_media_handle_create(switch_media_handle_t **smhp, switch_core_session_t *session, switch_core_media_params_t *params)
switch_memory_pool_t * pool
uint16_t seq
Definition: switch_frame.h:70
#define SWITCH_MAX_CAND_ACL
switch_rw_t
Definition: switch_types.h:565
switch_codec_control_type_t
switch_mutex_t * mutex
static const char * switch_media_type2str(switch_media_type_t type)
int64_t switch_time_t
Definition: switch_apr.h:188
const switch_codec_implementation_t * implementation
uint32_t buflen
Definition: switch_frame.h:59
#define SWITCH_REMOTE_MEDIA_IP_VARIABLE
Definition: switch_types.h:210
if((uint32_t)(unpack->cur-unpack->buf) > unpack->buflen)
switch_time_t last_video_refresh_req
switch_port_t remote_rtp_ice_port
switch_rtcp_numbers_t rtcp
Definition: switch_types.h:692
switch_byte_t switch_byte_t * buf
#define SWITCH_STUN_DEFAULT_PORT
Definition: switch_stun.h:41
switch_status_t switch_core_session_request_video_refresh(switch_core_session_t *session)
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:908
switch_status_t switch_core_media_set_outgoing_bitrate(switch_core_session_t *session, switch_media_type_t type, uint32_t bitrate)
uint32_t switch_core_media_bug_prune(switch_core_session_t *session)
#define switch_channel_audio_sync(_c)
unsigned int switch_separate_string(_In_ char *buf, char delim, _Post_count_(return) char **array, unsigned int arraylen)
Separate a string into an array based on a character delimiter.
switch_channel_t * channel
switch_rtp_t * rtp_session
switch_size_t raw_bytes
Definition: switch_types.h:627
void switch_stun_random_string(char *buf, uint16_t len, char *set)
Writes random characters into a buffer.
Definition: switch_stun.c:125
uint32_t datalen
Definition: switch_frame.h:57
int rates[SWITCH_MAX_CODECS]
const char * switch_channel_get_hold_music(switch_channel_t *channel)
switch_byte_t in
switch_rtp_crypto_mode_t
switch_timer_interface_t * timer_interface
void switch_core_media_set_sdp_codec_string(switch_core_session_t *session, const char *r_sdp, switch_sdp_type_t sdp_type)
void switch_core_media_gen_local_sdp(switch_core_session_t *session, switch_sdp_type_t sdp_type, const char *ip, switch_port_t port, const char *sr, int force)
uint32_t packetlen
Definition: switch_frame.h:51
switch_status_t switch_rtp_activate_jitter_buffer(switch_rtp_t *rtp_session, uint32_t queue_frames, uint32_t max_queue_frames, uint32_t samples_per_packet, uint32_t samples_per_second)
Acvite a jitter buffer on an RTP session.
Definition: switch_rtp.c:4146
int switch_rtp_has_dtls(void)
Definition: switch_rtp.c:3207
#define SWITCH_RTP_MAX_CRYPTO_LEN
Definition: switch_rtp.h:47
switch_status_t switch_core_session_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
switch_codec_t read_codec
switch_frame_flag_t flags
Definition: switch_frame.h:74
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:285
switch_media_flow_t rmode
switch_status_t switch_b64_encode(unsigned char *in, switch_size_t ilen, unsigned char *out, switch_size_t olen)
Definition: switch_utils.c:890
switch_status_t switch_rtp_get_video_buffer_size(switch_rtp_t *rtp_session, uint32_t *min_frame_len, uint32_t *max_frame_len, uint32_t *cur_frame_len, uint32_t *highest_frame_len)
Definition: switch_rtp.c:4091
switch_rtp_bug_flag_t
Definition: switch_types.h:771
static switch_status_t ip_choose_family(switch_media_handle_t *smh, const char *ip)
switch_status_t switch_core_media_read_lock_unlock(switch_core_session_t *session, switch_media_type_t type, switch_bool_t lock)
uint32_t switch_channel_test_cap_partner(switch_channel_t *channel, switch_channel_cap_t cap)
intptr_t switch_ssize_t
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:682
uint32_t rate
Definition: switch_frame.h:63
switch_status_t switch_rtp_activate_ice(switch_rtp_t *rtp_session, char *login, char *rlogin, const char *password, const char *rpassword, ice_proto_t proto, switch_core_media_ice_type_t type, ice_t *ice_params)
Acvite ICE on an RTP session.
Definition: switch_rtp.c:4241
#define switch_channel_get_variable(_c, _v)
#define SWITCH_THREAD_STACKSIZE
Definition: switch_types.h:551
#define switch_channel_video_sync(_c)
switch_mutex_t * file_write_mutex
void switch_core_media_recover_session(switch_core_session_t *session)
switch_core_session_t * session
void switch_rtp_set_flags(switch_rtp_t *rtp_session, switch_rtp_flag_t flags[SWITCH_RTP_FLAG_INVALID])
Definition: switch_rtp.c:4660
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
int next_cpu(void)
static void check_dtls_reinvite(switch_core_session_t *session, switch_rtp_engine_t *engine)
#define switch_zmalloc(ptr, len)
switch_core_media_params_t * switch_core_media_get_mparams(switch_media_handle_t *smh)
void switch_img_copy(switch_image_t *img, switch_image_t **new_img)
Copy image to a new image.
switch_media_flow_t switch_core_session_media_flow(switch_core_session_t *session, switch_media_type_t type)
payload_map_t * cur_payload_map
void switch_core_media_start_udptl(switch_core_session_t *session, switch_t38_options_t *t38_options)
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
switch_vid_params_t vid_params
switch_rtp_stats_t * switch_core_media_get_stats(switch_core_session_t *session, switch_media_type_t type, switch_memory_pool_t *pool)
switch_rtp_numbers_t outbound
Definition: switch_types.h:691
switch_core_media_dtmf_t dtmf_type
char * con_addr
Definition: switch_rtp.h:93
void switch_rtp_video_loss(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:4374
int switch_core_media_crypto_keylen(switch_rtp_crypto_key_type_t type)
dtls_fingerprint_t local_dtls_fingerprint
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:270
switch_status_t switch_rtp_set_remote_ssrc(switch_rtp_t *rtp_session, uint32_t ssrc)
Definition: switch_rtp.c:3733
switch_core_media_flag_t
switch_status_t switch_core_media_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id, switch_media_type_t type)
static core_video_globals_t video_globals
switch_image_t * switch_img_read_png(const char *file_name, switch_img_fmt_t img_fmt)
#define SWITCH_TIME_T_FMT
int switch_loadable_module_get_codecs(const switch_codec_implementation_t **array, int arraylen)
Retrieve the list of loaded codecs into an array.
void switch_core_media_init(void)
switch_status_t switch_rtp_set_ssrc(switch_rtp_t *rtp_session, uint32_t ssrc)
Definition: switch_rtp.c:3725
switch_payload_t dtmf_ianacodes[SWITCH_MAX_CODECS]
#define switch_channel_down_nosig(_channel)
char * cand_type
Definition: switch_rtp.h:95
switch_sdp_type_t sdp_type
void switch_core_media_end_video_function(switch_core_session_t *session)
An abstraction of a data frame.
Definition: switch_frame.h:43
char * options
Definition: switch_rtp.h:111
uintptr_t switch_size_t
uint8_t ready
Definition: switch_rtp.h:99
uint8_t negotiated
switch_frame_t * video_ping_frame
switch_sdp_type_t
switch_payload_t pt
#define switch_set_flag_locked(obj, flag)
Set a flag on an arbitrary object while locked.
Definition: switch_utils.h:638
uint16_t switch_port_t
uint32_t switch_default_ptime(const char *name, uint32_t number)
Definition: switch_core.c:2026
struct switch_media_bug * next
const char * T38VendorInfo
switch_codec_t * switch_core_session_get_video_write_codec(_In_ switch_core_session_t *session)
Retrieve the video_write codec from a given session.
switch_size_t switch_rtp_has_dtmf(switch_rtp_t *rtp_session)
Test for presence of DTMF on a given RTP session.
Definition: switch_rtp.c:6898
uint32_t ptime
switch_byte_t switch_byte_t uint32_t buflen
#define switch_core_codec_init(_codec, _codec_name, _modname, _fmtp, _rate, _ms, _channels, _flags, _codec_settings, _pool)
Initialize a codec handle.
Definition: switch_core.h:1602
switch_port_t local_sdp_port
pthread_t switch_thread_id_t
Definition: switch_apr.h:51
void switch_cond_next(void)
Definition: switch_time.c:638
void switch_core_media_set_rtp_session(switch_core_session_t *session, switch_media_type_t type, switch_rtp_t *rtp_session)
#define switch_core_session_get_partner(_session, _partner)
Definition: switch_core.h:1002
static void switch_core_media_find_zrtp_hash(switch_core_session_t *session, sdp_session_t *sdp)
switch_status_t switch_core_media_add_ice_acl(switch_core_session_t *session, switch_media_type_t type, const char *acl_name)
switch_status_t switch_img_letterbox(switch_image_t *img, switch_image_t **imgP, int width, int height, const char *color)
switch_status_t switch_core_session_send_and_request_video_refresh(switch_core_session_t *session)
int switch_core_media_toggle_hold(switch_core_session_t *session, int sendonly)
switch_payload_t agreed_pt
switch_mutex_t * control_mutex
char * switch_core_get_variable(_In_z_ const char *varname)
Retrieve a global variable from the core.
switch_status_t switch_nat_del_mapping(switch_port_t port, switch_nat_ip_proto_t proto)
Deletes a NAT mapping.
Definition: switch_nat.c:625
switch_size_t packet_count
Definition: switch_types.h:629
switch_file_handle_t * switch_core_media_get_video_file(switch_core_session_t *session, switch_rw_t rw)
static void greedy_sort(switch_media_handle_t *smh, struct matches *matches, int m_idx, const switch_codec_implementation_t **codec_array, int total_codecs)
switch_status_t switch_rtp_set_remote_address(switch_rtp_t *rtp_session, const char *host, switch_port_t port, switch_port_t remote_rtcp_port, switch_bool_t change_adv_addr, const char **err)
Assign a remote address to the RTP session.
Definition: switch_rtp.c:2913
switch_rtp_crypto_key_type_t switch_core_media_crypto_str2type(const char *str)
payload_map_t * pmap_tail
static void set_stats(switch_core_session_t *session, switch_media_type_t type, const char *prefix)
void switch_color_set_rgb(switch_rgb_color_t *color, const char *color_str)
Set RGB color with a string.
switch_status_t switch_core_media_lock_video_file(switch_core_session_t *session, switch_rw_t rw)
const char * T38FaxUdpEC
uint32_t bitrate
switch_status_t switch_core_timer_destroy(switch_timer_t *timer)
Destroy an allocated timer.
#define DTLS_SRTP_FNAME
Definition: switch_core.h:146
switch_media_type_t type
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1217
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
char * ufrag
Definition: switch_rtp.h:109
static void check_jb_sync(switch_core_session_t *session)
void switch_core_session_video_reset(switch_core_session_t *session)
char * switch_core_session_get_uuid(_In_ switch_core_session_t *session)
Retrieve the unique identifier from a session.
switch_status_t switch_core_media_activate_rtp(switch_core_session_t *session)
static void check_jb(switch_core_session_t *session, const char *input, int32_t jb_msec, int32_t maxlen, switch_bool_t silent)
switch_size_t jb_packet_count
Definition: switch_types.h:633
void switch_core_media_resume(switch_core_session_t *session)
#define SWITCH_RTCP_VIDEO_INTERVAL_MSEC
Definition: switch_types.h:235
switch_status_t switch_core_codec_encode_video(switch_codec_t *codec, switch_frame_t *frame)
Encode video data using a codec handle.
switch_size_t skip_packet_count
Definition: switch_types.h:632
switch_status_t switch_core_media_check_autoadj(switch_core_session_t *session)
void switch_rtp_set_cng_pt(switch_rtp_t *rtp_session, switch_payload_t pt)
Set the payload type for comfort noise.
Definition: switch_rtp.c:4030
dtls_type_t
Definition: switch_core.h:157
switch_rtp_bug_flag_t manual_rtp_bugs
void switch_channel_set_app_flag_key(const char *app, switch_channel_t *channel, uint32_t flags)
void switch_core_media_set_telephony_event(switch_core_session_t *session, switch_media_type_t type, switch_payload_t te)
#define SWITCH_LOCAL_MEDIA_IP_VARIABLE
Definition: switch_types.h:207
void switch_core_media_copy_t38_options(switch_t38_options_t *t38_options, switch_core_session_t *session)
#define switch_str_nil(s)
Make a null string a blank string instead.
Definition: switch_utils.h:903
char * transport
Definition: switch_rtp.h:91
switch_status_t switch_core_timer_next(switch_timer_t *timer)
Wait for one cycle on an existing timer.
#define RA_PTR_LEN
int switch_core_media_check_video_function(switch_core_session_t *session)
switch_status_t switch_core_session_media_handle_ready(switch_core_session_t *session)
switch_status_t switch_core_codec_init_with_bitrate(switch_codec_t *codec, const char *codec_name, const char *fmtp, const char *modname, uint32_t rate, int ms, int channels, uint32_t bitrate, uint32_t flags, const switch_codec_settings_t *codec_settings, switch_memory_pool_t *pool)
static void add_fb(char *buf, uint32_t buflen, int pt, int fir, int nack, int pli, int tmmbr)
int switch_thread_equal(switch_thread_id_t tid1, switch_thread_id_t tid2)
Compare two thread ids.
Definition: switch_apr.c:88
uint8_t switch_core_media_negotiate_sdp(switch_core_session_t *session, const char *r_sdp, uint8_t *proceed, switch_sdp_type_t sdp_type)
static void switch_core_session_get_recovery_crypto_key(switch_core_session_t *session, switch_media_type_t type)
void switch_rtp_clear_flag(switch_rtp_t *rtp_session, switch_rtp_flag_t flag)
Clear an RTP Flag.
Definition: switch_rtp.c:4747
const char * switch_channel_get_variable_partner(switch_channel_t *channel, const char *varname)
switch_core_video_thread_callback_func_t video_read_callback
switch_status_t switch_core_media_unlock_video_file(switch_core_session_t *session, switch_rw_t rw)
dtls_fingerprint_t remote_dtls_fingerprint
switch_port_t switch_rtp_request_port(const char *ip)
Request a new port to be used for media.
Definition: switch_rtp.c:2431
#define SWITCH_R_SDP_VARIABLE
Definition: switch_types.h:196
void * packet
Definition: switch_frame.h:49
void switch_rtp_set_flag(switch_rtp_t *rtp_session, switch_rtp_flag_t flag)
Set an RTP Flag.
Definition: switch_rtp.c:4702
#define switch_channel_down(_channel)
#define add_stat_double(_i, _s)
switch_call_direction_t switch_ice_direction(switch_core_session_t *session)
struct apr_thread_mutex_t switch_mutex_t
Definition: switch_apr.h:314
int switch_loadable_module_get_codecs_sorted(const switch_codec_implementation_t **array, int arraylen, char **prefs, int preflen)
Retrieve the list of loaded codecs into an array based on another array showing the sorted order...
char * switch_rtp_get_remote_host(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:2822
void switch_core_media_pass_zrtp_hash(switch_core_session_t *session)
switch_image_t * img
Definition: switch_frame.h:77
switch_status_t
Common return values.
switch_timer_t * switch_rtp_get_media_timer(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:4036
switch_rtp_engine_t engines[SWITCH_MEDIA_TYPE_TOTAL]
void * switch_channel_get_private(switch_channel_t *channel, const char *key)
Retrieve private from a given channel.
#define switch_goto_status(_status, _label)
Definition: switch_utils.h:256
uint32_t switch_rtp_get_ssrc(switch_rtp_t *rtp_session)
Retrieve the SSRC from a given RTP session.
Definition: switch_rtp.c:8089
dtls_state_t
Definition: switch_core.h:164
void switch_core_session_check_outgoing_crypto(switch_core_session_t *session)
switch_mutex_t * mutex
void switch_core_autobind_cpu(void)
switch_size_t switch_rtp_dequeue_dtmf(switch_rtp_t *rtp_session, switch_dtmf_t *dtmf)
Retrieve DTMF digits from a given RTP session.
Definition: switch_rtp.c:6911
void switch_rtp_flush(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:4331
switch_status_t switch_ivr_unhold(switch_core_session_t *session)
Signal the session with a protocol specific unhold message.
Definition: switch_ivr.c:1515
switch_status_t switch_core_session_write_encoded_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
const switch_codec_implementation_t * imp
switch_status_t switch_core_media_queue_rfc2833_in(switch_core_session_t *session, switch_media_type_t type, const switch_dtmf_t *dtmf)
void switch_core_session_lock_codec_write(_In_ switch_core_session_t *session)
void switch_media_handle_destroy(switch_core_session_t *session)
#define MAX_CAND
Definition: switch_rtp.h:102
static int dtls_ok(switch_core_session_t *session)
uint32_t len
Definition: switch_core.h:151
void switch_rtp_break(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:4385
void switch_rtp_reset_jb(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:2769
void switch_img_fill(switch_image_t *img, int x, int y, int w, int h, switch_rgb_color_t *color)
Fill image with color.
An abstraction of a rtcp frame.
struct apr_thread_t switch_thread_t
Definition: switch_apr.h:941
#define switch_core_session_locate(uuid_str)
Locate a session based on it's uuid.
Definition: switch_core.h:916
const char * remote_ip
void switch_core_session_video_reinit(switch_core_session_t *session)
switch_rtp_flag_t
RTP Related Flags.
Definition: switch_types.h:723
#define SWITCH_NO_CRYPTO_TAG
void switch_core_media_set_stats(switch_core_session_t *session)
char * pwd
Definition: switch_rtp.h:110
switch_status_t switch_core_media_queue_rfc2833(switch_core_session_t *session, switch_media_type_t type, const switch_dtmf_t *dtmf)
Main Library Header.
#define SWITCH_B_SDP_VARIABLE
Definition: switch_types.h:198
void switch_rtp_get_random(void *buf, uint32_t len)
Definition: switch_rtp.c:2338
switch_status_t switch_rtp_queue_rfc2833(switch_rtp_t *rtp_session, const switch_dtmf_t *dtmf)
Queue RFC2833 DTMF data into an RTP Session.
Definition: switch_rtp.c:6935
void switch_rtp_set_default_payload(switch_rtp_t *rtp_session, switch_payload_t payload)
Set the default payload number for a given RTP session.
Definition: switch_rtp.c:4645
int component_id
Definition: switch_rtp.h:90
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:383
char * cand_acl[SWITCH_MAX_CAND_ACL]
switch_size_t flush_packet_count
Definition: switch_types.h:636
switch_timer_t * switch_core_media_get_timer(switch_core_session_t *session, switch_media_type_t mtype)
switch_status_t switch_core_media_sdp_map(const char *r_sdp, switch_event_t **fmtp, switch_event_t **pt)
#define SWITCH_DECLARE(type)
switch_port_t adv_sdp_port
switch_status_t switch_rtp_add_dtls(switch_rtp_t *rtp_session, dtls_fingerprint_t *local_fp, dtls_fingerprint_t *remote_fp, dtls_type_t type)
Definition: switch_rtp.c:3294
uint32_t samples
Definition: switch_frame.h:61
switch_status_t switch_core_session_clear_media_handle(switch_core_session_t *session)
static switch_status_t switch_core_media_build_crypto(switch_media_handle_t *smh, switch_media_type_t type, int index, switch_rtp_crypto_key_type_t ctype, switch_rtp_crypto_direction_t direction, int force)
#define switch_event_get_header(_e, _h)
Definition: switch_event.h:172
switch_mutex_t * file_read_mutex
#define SWITCH_REMOTE_VIDEO_PORT_VARIABLE
Definition: switch_types.h:213
#define switch_channel_set_flag(_c, _f)
#define SWITCH_IMG_FMT_I420
Definition: switch_vpx.h:77
void switch_core_media_deinit(void)
switch_thread_t * media_thread
void switch_core_media_set_udptl_image_sdp(switch_core_session_t *session, switch_t38_options_t *t38_options, int insist)
#define SWITCH_MEDIA_TYPE_TOTAL
void switch_rtp_clear_flags(switch_rtp_t *rtp_session, switch_rtp_flag_t flags[SWITCH_RTP_FLAG_INVALID])
Definition: switch_rtp.c:4691
uint32_t channels
Definition: switch_frame.h:65
switch_bool_t switch_core_file_has_video(switch_file_handle_t *fh, switch_bool_t CHECK_OPEN)
int switch_rtp_write_frame(switch_rtp_t *rtp_session, switch_frame_t *frame)
Write data to a given RTP session.
Definition: switch_rtp.c:7726
switch_size_t media_packet_count
Definition: switch_types.h:631
switch_rtp_stats_t * switch_rtp_get_stats(switch_rtp_t *rtp_session, switch_memory_pool_t *pool)
Definition: switch_rtp.c:7928
switch_call_direction_t switch_channel_direction(switch_channel_t *channel)
switch_codec_implementation_t read_impl
#define switch_set_string(_dst, _src)
Definition: switch_utils.h:665
void switch_core_session_wake_video_thread(switch_core_session_t *session)
#define type2str(type)
#define SWITCH_REMOTE_MEDIA_PORT_VARIABLE
Definition: switch_types.h:211
switch_rtp_t * switch_rtp_new(const char *rx_host, switch_port_t rx_port, const char *tx_host, switch_port_t tx_port, switch_payload_t payload, uint32_t samples_per_interval, uint32_t ms_per_packet, switch_rtp_flag_t flags[], char *timer_name, const char **err, switch_memory_pool_t *pool)
prepare a new RTP session handle and fully initilize it
switch_status_t switch_rtp_set_video_buffer_size(switch_rtp_t *rtp_session, uint32_t frames, uint32_t max_frames)
Definition: switch_rtp.c:4101
switch_port_t remote_rtcp_port
switch_rtp_bug_flag_t auto_rtp_bugs
const char * switch_core_media_get_codec_string(switch_core_session_t *session)
switch_status_t switch_core_media_choose_port(switch_core_session_t *session, switch_media_type_t type, int force)
switch_status_t switch_rtp_change_interval(switch_rtp_t *rtp_session, uint32_t ms_per_packet, uint32_t samples_per_interval)
Definition: switch_rtp.c:3687
switch_payload_t cng_ianacodes[SWITCH_MAX_CODECS]
switch_payload_t agreed_pt
static const char * skip(const char *in)
Definition: switch_json.c:270
switch_status_t switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name)
Definition: switch_rtp.c:4126
switch_status_t switch_core_media_get_vid_params(switch_core_session_t *session, switch_vid_params_t *vid_params)
static void generate_m(switch_core_session_t *session, char *buf, size_t buflen, switch_port_t port, const char *family, const char *ip, int cur_ptime, const char *append_audio, const char *sr, int use_cng, int cng_type, switch_event_t *map, int secure, switch_sdp_type_t sdp_type)
static void _switch_core_media_pass_zrtp_hash2(switch_core_session_t *aleg_session, switch_core_session_t *bleg_session, switch_media_type_t type)
icand_t cands[MAX_CAND][2]
Definition: switch_rtp.h:105
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
Definition: switch_time.c:321
switch_rtp_bug_flag_t rtp_bugs
switch_file_handle_t * video_write_fh
switch_status_t switch_core_media_add_crypto(switch_secure_settings_t *ssec, const char *key_str, switch_rtp_crypto_direction_t direction)
switch_status_t switch_core_session_set_write_codec(_In_ switch_core_session_t *session, switch_codec_t *codec)
Assign the write codec to a given session.
switch_mutex_t * cond_mutex
int is_chosen[2]
Definition: switch_rtp.h:108
switch_core_media_NDLB_t ndlb
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session's pool.
Definition: switch_core.h:694
switch_media_flow_t
static const char * get_media_profile_name(switch_core_session_t *session, int secure)
switch_status_t switch_queue_push(switch_queue_t *queue, void *data)
Definition: switch_apr.c:1129
switch_payload_t payload
Definition: switch_frame.h:67
struct apr_pool_t switch_memory_pool_t
switch_status_t switch_rtp_enable_vad(switch_rtp_t *rtp_session, switch_core_session_t *session, switch_codec_t *codec, switch_vad_flag_t flags)
Enable VAD on an RTP Session.
Definition: switch_rtp.c:7669
switch_channel_t * channel
void switch_rtp_release_port(const char *ip, switch_port_t port)
Definition: switch_rtp.c:2415
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:624
switch_file_handle_t * video_read_fh
void switch_channel_clear_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
static switch_bool_t switch_core_codec_ready(switch_codec_t *codec)
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
switch_payload_t recv_pt
const char * switch_stristr(const char *instr, const char *str)
void switch_core_session_unset_read_codec(_In_ switch_core_session_t *session)
uint32_t switch_rtp_test_flag(switch_rtp_t *rtp_session, switch_rtp_flag_t flags)
Test an RTP Flag.
Definition: switch_rtp.c:4742
switch_status_t switch_threadattr_create(switch_threadattr_t **new_attr, switch_memory_pool_t *pool)
Definition: switch_apr.c:642
switch_status_t switch_thread_create(switch_thread_t **new_thread, switch_threadattr_t *attr, switch_thread_start_t func, void *data, switch_memory_pool_t *cont)
Definition: switch_apr.c:675
static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, void *obj)
A table of settings and callbacks that define a paticular implementation of a codec.
void switch_core_media_sync_stats(switch_core_session_t *session)
switch_bool_t T38FaxFillBitRemoval
switch_port_t remote_sdp_port
void switch_core_session_unlock_codec_write(_In_ switch_core_session_t *session)
static int switch_false(const char *expr)
Evaluate the falsefullness of a string expression.
Definition: switch_utils.h:482
switch_status_t switch_core_file_write_video(_In_ switch_file_handle_t *fh, switch_frame_t *frame)
Write media to a file handle.
static int check_engine(switch_rtp_engine_t *engine)
switch_status_t switch_core_media_proxy_remote_addr(switch_core_session_t *session, const char *sdp_str)
static void add_audio_codec(sdp_rtpmap_t *map, const switch_codec_implementation_t *imp, int ptime, char *buf, switch_size_t buflen)
uint32_t switch_core_media_bug_test_flag(_In_ switch_media_bug_t *bug, _In_ uint32_t flag)
Test for the existance of a flag on an media bug.
uint32_t priority
Definition: switch_rtp.h:92
#define switch_channel_up_nosig(_channel)
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session's pool.
Definition: switch_core.h:717
switch_thread_id_t switch_thread_self(void)
Definition: switch_apr.c:79
static switch_bool_t ip_possible(switch_media_handle_t *smh, const char *ip)
switch_io_type_t
void switch_event_destroy(switch_event_t **event)
Destroy an event.
#define MAX_CODEC_CHECK_FRAMES
switch_port_t remote_rtcp_ice_port
uint32_t switch_core_media_get_video_fps(switch_core_session_t *session)
switch_status_t switch_thread_cond_broadcast(switch_thread_cond_t *cond)
Definition: switch_apr.c:376
char * codec_order[SWITCH_MAX_CODECS]
switch_port_t proxy_sdp_port
switch_status_t switch_rtp_queue_rfc2833_in(switch_rtp_t *rtp_session, const switch_dtmf_t *dtmf)
Queue RFC2833 DTMF data into an RTP Session.
Definition: switch_rtp.c:6961
struct switch_rtp_engine_s switch_rtp_engine_t
void switch_rtp_kill_socket(switch_rtp_t *rtp_session)
Kill the socket on an existing RTP session.
Definition: switch_rtp.c:4425
unsigned int d_h
Definition: switch_image.h:100
int switch_core_gen_certs(const char *prefix)
char * switch_core_media_filter_sdp(const char *sdp_str, const char *cmd, const char *arg)
static uint32_t switch_round_to_step(uint32_t num, uint32_t step)
Definition: switch_utils.h:50
switch_status_t switch_channel_wait_for_flag(switch_channel_t *channel, switch_channel_flag_t want_flag, switch_bool_t pres, uint32_t to, switch_channel_t *super_channel)
switch_mutex_t * sdp_mutex
void switch_channel_clear_flag(switch_channel_t *channel, switch_channel_flag_t flag)
Clear given flag(s) from a channel.
struct media_helper mh
switch_timer_t video_timer
int switch_channel_test_app_flag_key(const char *app, switch_channel_t *channel, uint32_t flags)
#define switch_assert(expr)
switch_mutex_t * read_mutex[2]
void switch_core_session_stop_media(switch_core_session_t *session)
#define switch_channel_set_variable(_channel, _var, _val)
void switch_rtp_video_refresh(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:4362
switch_time_t switch_time_now(void)
Definition: switch_apr.c:302
const char * sdp_o_line
void switch_core_media_deactivate_rtp(switch_core_session_t *session)
switch_codec_implementation_t write_impl
switch_rtp_crypto_key_type_t crypto_type
void switch_core_media_clear_ice(switch_core_session_t *session)
#define MAX_MISMATCH_FRAMES
switch_status_t switch_channel_api_on(switch_channel_t *channel, const char *variable_prefix)
char * switch_channel_get_name(switch_channel_t *channel)
Retrieve the name of a given channel.
switch_status_t switch_ivr_hold_uuid(const char *uuid, const char *message, switch_bool_t moh)
Signal the session with a protocol specific hold message.
Definition: switch_ivr.c:1481
switch_status_t switch_rtp_req_bitrate(switch_rtp_t *rtp_session, uint32_t bps)
Definition: switch_rtp.c:4340
#define SWITCH_READ_ACCEPTABLE(status)
Definition: switch_utils.h:995
switch_status_t switch_stun_lookup(char **ip, switch_port_t *port, char *stunip, switch_port_t stunport, char **err, switch_memory_pool_t *pool)
Perform a stun lookup.
Definition: switch_stun.c:698
switch_status_t switch_rtcp_zerocopy_read_frame(switch_rtp_t *rtp_session, switch_rtcp_frame_t *frame)
Read RTCP data from a given RTP session without copying.
Definition: switch_rtp.c:7016
switch_bool_t switch_core_media_check_dtls(switch_core_session_t *session, switch_media_type_t type)
void switch_rtp_set_interdigit_delay(switch_rtp_t *rtp_session, uint32_t delay)
Definition: switch_rtp.c:4630
void switch_core_media_hard_mute(switch_core_session_t *session, switch_bool_t on)
switch_status_t switch_core_session_set_write_impl(switch_core_session_t *session, const switch_codec_implementation_t *impp)
memset(buf, 0, buflen)
#define switch_channel_media_up(_channel)
switch_jb_t * switch_core_media_get_jb(switch_core_session_t *session, switch_media_type_t type)
switch_status_t switch_rtp_sync_stats(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:4468
switch_core_media_params_t * mparams
#define SWITCH_CHANNEL_CHANNEL_LOG(x)
uint32_t codec_ms
switch_memory_pool_t * switch_core_session_get_pool(_In_ switch_core_session_t *session)
Retrieve the memory pool from a session.
switch_time_t video_last_key_time
void switch_core_media_set_telephony_recv_event(switch_core_session_t *session, switch_media_type_t type, switch_payload_t te)
void switch_core_session_unlock_codec_read(_In_ switch_core_session_t *session)
switch_media_type_t type
static void clear_ice(switch_core_session_t *session, switch_media_type_t type)
uint8_t switch_payload_t
void switch_core_media_prepare_codecs(switch_core_session_t *session, switch_bool_t force)
switch_t38_options_t * switch_core_media_extract_t38_options(switch_core_session_t *session, const char *r_sdp)
switch_mutex_t * write_mutex[2]
void switch_core_media_check_outgoing_proxy(switch_core_session_t *session, switch_core_session_t *o_session)
int switch_core_session_check_incoming_crypto(switch_core_session_t *session, const char *varname, switch_media_type_t type, const char *crypto, int crypto_tag, switch_sdp_type_t sdp_type)
#define SWITCH_REMOTE_VIDEO_IP_VARIABLE
Definition: switch_types.h:212
switch_status_t switch_core_codec_control(switch_codec_t *codec, switch_codec_control_command_t cmd, switch_codec_control_type_t ctype, void *cmd_data, switch_codec_control_type_t atype, void *cmd_arg, switch_codec_control_type_t *rtype, void **ret_data)
send control data using a codec handle
switch_status_t switch_core_session_set_real_read_codec(_In_ switch_core_session_t *session, switch_codec_t *codec)
Assign the original read codec to a given session. This is the read codec used by an endpoint...
switch_port_t con_port
Definition: switch_rtp.h:94
void switch_core_media_absorb_sdp(switch_core_session_t *session)
switch_status_t switch_core_timer_sync(switch_timer_t *timer)
void switch_core_media_set_rtp_flag(switch_core_session_t *session, switch_media_type_t type, switch_rtp_flag_t flag)
switch_size_t cng_packet_count
Definition: switch_types.h:635
switch_port_t rport
Definition: switch_rtp.h:97
void switch_media_handle_set_media_flag(switch_media_handle_t *smh, switch_core_media_flag_t flag)
switch_rtp_crypto_key_type_t type
Definition: switch_rtp.h:67
char * rm_encoding
switch_media_type_t
switch_rtp_crypto_key_type_t crypto_type