RTS API Documentation  1.10.11
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-2021, 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  * Seven Du <dujinfang@gmail.com>
28  *
29  * switch_core_media.c -- Core Media
30  *
31  */
32 
33 #include <switch.h>
34 #include <switch_ssl.h>
35 #include <switch_stun.h>
36 #include <switch_nat.h>
38 #include "private/switch_apr_pvt.h"
39 #include <switch_curl.h>
40 #include <errno.h>
41 #include <sofia-sip/sdp.h>
42 #include <sofia-sip/su.h>
43 
44 #include <stdbool.h>
45 
46 static switch_t38_options_t * switch_core_media_process_udptl(switch_core_session_t *session, sdp_session_t *sdp, sdp_media_t *m);
47 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);
48 static void gen_ice(switch_core_session_t *session, switch_media_type_t type, const char *ip, switch_port_t port);
49 //#define GOOGLE_ICE
50 #define RTCP_MUX
51 #define MAX_CODEC_CHECK_FRAMES 50//x:mod_sofia.h
52 #define MAX_MISMATCH_FRAMES 5//x:mod_sofia.h
53 #define type2str(type) type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : (type == SWITCH_MEDIA_TYPE_AUDIO ? "audio" : "text")
54 #define VIDEO_REFRESH_FREQ 1000000
55 
56 #define TEXT_TIMER_MS 100
57 #define TEXT_TIMER_SAMPLES 10
58 #define TEXT_PERIOD_TIMEOUT 3000
59 #define MAX_RED_FRAMES 25
60 #define RED_PACKET_SIZE 100
61 
62 typedef enum {
63  SMF_INIT = (1 << 0),
64  SMF_READY = (1 << 1),
65  SMF_JB_PAUSED = (1 << 2),
66  SMF_VB_PAUSED = (1 << 3)
67 } smh_flag_t;
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  int ready;
88 };
89 
90 typedef enum {
95 
99  int red_level;
106  int red_buflen[MAX_RED_FRAMES];
107  uint32_t red_ts[MAX_RED_FRAMES];
108  int red_pos;
109  int red_max;
111 };
112 
113 
117 
119 
124 
127 
130  uint32_t check_frames;
131  uint32_t mismatch_count;
132  uint32_t last_codec_ms;
136  uint32_t media_timeout;
138  uint32_t ssrc;
139  uint32_t remote_ssrc;
142 
143 
146  char *adv_sdp_ip;
150 
151 
155 
156  uint32_t timestamp_send;
157 
158  char *cand_acl[SWITCH_MAX_CAND_ACL];
160 
163 
164  int8_t rtcp_mux;
165 
168 
171 
174 
175  struct media_helper mh;
177 
178 
179  uint8_t reset_codec;
181 
182  uint8_t fir;
183  uint8_t pli;
184  uint8_t nack;
185  uint8_t tmmbr;
186  uint8_t no_crypto;
188  uint8_t pass_codecs;
194  uint8_t new_ice;
195  uint8_t new_dtls;
196  uint32_t sdp_bw;
197  uint32_t orig_bitrate;
198  float bw_mult;
199  uint8_t reject_avp;
200  int t140_pt;
201  int red_pt;
203 
208 };
209 
210 #define MAX_REJ_STREAMS 10
211 
221  char *codec_order[SWITCH_MAX_CODECS];
226  char *origin;
227 
228  sdp_media_e rejected_streams[MAX_REJ_STREAMS];
229  int rej_idx;
230 
234 
240  char *fmtps[SWITCH_MAX_CODECS];
242 
243  int rates[SWITCH_MAX_CODECS];
244  uint32_t num_rates;
245 
246  uint32_t owner_id;
247  uint32_t session_id;
248 
250 
251  char *msid;
252  char *cname;
253 
254  switch_rtp_crypto_mode_t crypto_mode;
261 
262 
266 
267  uint64_t vid_frames;
268  time_t vid_started;
270 
273 
275 
276 };
277 
279  { "AEAD_AES_256_GCM_8", "", AEAD_AES_256_GCM_8, 44, 12},
280  { "AEAD_AES_256_GCM", "", AEAD_AES_256_GCM, 44, 12},
281  { "AEAD_AES_128_GCM_8", "", AEAD_AES_128_GCM_8, 28, 12},
282  { "AEAD_AES_128_GCM", "", AEAD_AES_128_GCM, 28, 12},
283  { "AES_256_CM_HMAC_SHA1_80", "AES_CM_256_HMAC_SHA1_80", AES_CM_256_HMAC_SHA1_80, 46, 14},
284  { "AES_192_CM_HMAC_SHA1_80", "AES_CM_192_HMAC_SHA1_80", AES_CM_192_HMAC_SHA1_80, 38, 14},
285  { "AES_CM_128_HMAC_SHA1_80", "", AES_CM_128_HMAC_SHA1_80, 30, 14},
286  { "AES_256_CM_HMAC_SHA1_32", "AES_CM_256_HMAC_SHA1_32", AES_CM_256_HMAC_SHA1_32, 46, 14},
287  { "AES_192_CM_HMAC_SHA1_32", "AES_CM_192_HMAC_SHA1_32", AES_CM_192_HMAC_SHA1_32, 38, 14},
288  { "AES_CM_128_HMAC_SHA1_32", "", AES_CM_128_HMAC_SHA1_32, 30, 14},
289  { "AES_CM_128_NULL_AUTH", "", AES_CM_128_NULL_AUTH, 30, 14}
290 };
291 
293 
295 {
296  ice_resolve_candidate = resolve_ice;
297 }
298 
300 {
301  return ice_resolve_candidate;
302 }
303 
304 
306 {
307  int i;
308 
309  for (i = 0; i < CRYPTO_INVALID; i++) {
310  if (!strncasecmp(str, SUITES[i].name, strlen(SUITES[i].name)) || (SUITES[i].alias && strlen(SUITES[i].alias) && !strncasecmp(str, SUITES[i].alias, strlen(SUITES[i].alias)))) {
311  return SUITES[i].type;
312  }
313  }
314 
315  return CRYPTO_INVALID;
316 }
317 
318 
320 {
322  return SUITES[type].name;
323 }
324 
325 
327 {
329  return SUITES[type].keysalt_len;
330 }
331 
333 {
335  return SUITES[type].salt_len;
336 }
337 
339  [CRYPTO_KEY_PARAM_METHOD_INLINE] = "inline",
340 };
341 
342 static inline switch_media_flow_t sdp_media_flow(unsigned in)
343 {
344  switch(in) {
345  case sdp_sendonly:
347  case sdp_recvonly:
349  case sdp_sendrecv:
351  case sdp_inactive:
353  }
354 
356 }
357 
358 static int get_channels(const char *name, int dft)
359 {
360 
361  if (!zstr(name) && !switch_true(switch_core_get_variable("NDLB_broken_opus_sdp")) && !strcasecmp(name, "opus")) {
362  return 2; /* IKR???*/
363  }
364 
365  return dft ? dft : 1;
366 }
367 
369 {
371  time_t now;
372  uint32_t fps, elapsed = 0;
373 
374  switch_assert(session);
375 
376  if (!(smh = session->media_handle)) {
377  return SWITCH_STATUS_FALSE;
378  }
379 
380  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
381  return 0;
382  }
383 
384  now = switch_epoch_time_now(NULL);
385 
386  elapsed = now - smh->vid_started;
387 
388  if (!(smh->vid_started && smh->vid_frames && elapsed > 0)) {
389  return 0;
390  }
391 
392  fps = switch_round_to_step(smh->vid_frames / (elapsed), 5);
393 
394  if (smh->vid_frames > 1000) {
395  smh->vid_started = switch_epoch_time_now(NULL);
396  smh->vid_frames = 1;
397  }
398 
399  if (fps > 0) {
400  video_globals.fps = fps;
401 
402  if (smh->vid_params.fps != fps) {
403  switch_channel_set_variable_printf(session->channel, "video_fps", "%d", fps);
404  smh->vid_params.fps = fps;
405  }
406  }
407 
408  return fps;
409 }
410 
411 static switch_t38_options_t * switch_core_media_process_udptl(switch_core_session_t *session, sdp_session_t *sdp, sdp_media_t *m)
412 {
413  switch_t38_options_t *t38_options = switch_channel_get_private(session->channel, "t38_options");
414  sdp_attribute_t *attr;
415 
416  switch_assert(sdp);
417 
418  if (!t38_options) {
419  t38_options = switch_core_session_alloc(session, sizeof(switch_t38_options_t));
420 
421  // set some default value
422  t38_options->T38FaxVersion = 0;
423  t38_options->T38MaxBitRate = 14400;
424  t38_options->T38FaxRateManagement = switch_core_session_strdup(session, "transferredTCF");
425  t38_options->T38FaxUdpEC = switch_core_session_strdup(session, "t38UDPRedundancy");
426  t38_options->T38FaxMaxBuffer = 500;
427  t38_options->T38FaxMaxDatagram = 500;
428  }
429 
430  t38_options->remote_port = (switch_port_t)m->m_port;
431 
432  if (sdp->sdp_origin) {
433  t38_options->sdp_o_line = switch_core_session_strdup(session, sdp->sdp_origin->o_username);
434  } else {
435  t38_options->sdp_o_line = "unknown";
436  }
437 
438  if (m->m_connections && m->m_connections->c_address) {
439  t38_options->remote_ip = switch_core_session_strdup(session, m->m_connections->c_address);
440  } else if (sdp->sdp_connection && sdp->sdp_connection->c_address) {
441  t38_options->remote_ip = switch_core_session_strdup(session, sdp->sdp_connection->c_address);
442  }
443 
444  for (attr = m->m_attributes; attr; attr = attr->a_next) {
445  if (!strcasecmp(attr->a_name, "T38FaxVersion") && attr->a_value) {
446  t38_options->T38FaxVersion = (uint16_t) atoi(attr->a_value);
447  } else if (!strcasecmp(attr->a_name, "T38MaxBitRate") && attr->a_value) {
448  t38_options->T38MaxBitRate = (uint32_t) atoi(attr->a_value);
449  } else if (!strcasecmp(attr->a_name, "T38FaxFillBitRemoval")) {
450  t38_options->T38FaxFillBitRemoval = switch_safe_atoi(attr->a_value, 1);
451  } else if (!strcasecmp(attr->a_name, "T38FaxTranscodingMMR")) {
452  t38_options->T38FaxTranscodingMMR = switch_safe_atoi(attr->a_value, 1);
453  } else if (!strcasecmp(attr->a_name, "T38FaxTranscodingJBIG")) {
454  t38_options->T38FaxTranscodingJBIG = switch_safe_atoi(attr->a_value, 1);
455  } else if (!strcasecmp(attr->a_name, "T38FaxRateManagement") && attr->a_value) {
456  t38_options->T38FaxRateManagement = switch_core_session_strdup(session, attr->a_value);
457  } else if (!strcasecmp(attr->a_name, "T38FaxMaxBuffer") && attr->a_value) {
458  t38_options->T38FaxMaxBuffer = (uint32_t) atoi(attr->a_value);
459  } else if (!strcasecmp(attr->a_name, "T38FaxMaxDatagram") && attr->a_value) {
460  t38_options->T38FaxMaxDatagram = (uint32_t) atoi(attr->a_value);
461  } else if (!strcasecmp(attr->a_name, "T38FaxUdpEC") && attr->a_value) {
462  t38_options->T38FaxUdpEC = switch_core_session_strdup(session, attr->a_value);
463  } else if (!strcasecmp(attr->a_name, "T38VendorInfo") && attr->a_value) {
464  t38_options->T38VendorInfo = switch_core_session_strdup(session, attr->a_value);
465  }
466  }
467 
468  switch_channel_set_variable(session->channel, "has_t38", "true");
469  switch_channel_set_private(session->channel, "t38_options", t38_options);
471 
472  switch_channel_execute_on(session->channel, "sip_execute_on_image");
473  switch_channel_api_on(session->channel, "sip_api_on_image");
474 
475  return t38_options;
476 }
477 
479 {
480  switch_rtp_engine_t *a_engine;
481  switch_rtp_engine_t *v_engine;
482  switch_rtp_engine_t *t_engine;
484  const char *val;
485  int x = 0;
486 
487  switch_assert(session);
488 
489  if (!(smh = session->media_handle)) {
490  return SWITCH_STATUS_FALSE;
491  }
492 
493  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
494  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
495  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
496 
498  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
500  /* Reactivate the NAT buster flag. */
501 
502  if (a_engine->rtp_session) {
504  x++;
505  }
506 
507  if (v_engine->rtp_session) {
509  x++;
510  }
511 
512  if (t_engine->rtp_session) {
514  x++;
515  }
516  }
517 
519 }
520 
522 {
524 
525  switch_assert(session);
526 
527  if (!(smh = session->media_handle)) {
528  return SWITCH_STATUS_FALSE;
529  }
530 
532  *vid_params = smh->vid_params;
534 
535  return SWITCH_STATUS_SUCCESS;
536 }
537 
539 {
540  sdp_media_t *m;
541  sdp_parser_t *parser = NULL;
542  sdp_session_t *sdp;
543  switch_t38_options_t *t38_options = NULL;
544 
545  if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
546  return NULL;
547  }
548 
549  if (!(sdp = sdp_session(parser))) {
550  sdp_parser_free(parser);
551  return NULL;
552  }
553 
554  for (m = sdp->sdp_media; m; m = m->m_next) {
555  if (m->m_proto == sdp_proto_udptl && m->m_type == sdp_media_image && m->m_port) {
556  t38_options = switch_core_media_process_udptl(session, sdp, m);
557  break;
558  }
559  }
560 
561  sdp_parser_free(parser);
562 
563  return t38_options;
564 
565 }
566 
567 
568 
569 //?
571  switch_core_session_t *other_session, switch_t38_options_t *t38_options)
572 {
573  char *remote_host;
574  switch_port_t remote_port;
575  char tmp[32] = "";
576  switch_rtp_engine_t *a_engine;
578 
579  switch_assert(session);
580 
581  if (!(smh = session->media_handle)) {
582  return SWITCH_STATUS_FALSE;
583  }
584 
585  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
586 
587  remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
588  remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
589 
590  a_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, t38_options->remote_ip);
591  a_engine->cur_payload_map->remote_sdp_port = t38_options->remote_port;
592 
593  if (remote_host && remote_port && !strcmp(remote_host, a_engine->cur_payload_map->remote_sdp_ip) &&
594  remote_port == a_engine->cur_payload_map->remote_sdp_port) {
596  "Audio params are unchanged for %s.\n",
597  switch_channel_get_name(session->channel));
598  } else {
599  const char *err = NULL;
600 
602  "Audio params changed for %s from %s:%d to %s:%d\n",
604  remote_host, remote_port, a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
605 
606  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
611  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
613  }
614  switch_channel_execute_on(session->channel, "execute_on_audio_change");
615  }
616 
617  switch_core_media_copy_t38_options(t38_options, other_session);
618 
619  return SWITCH_STATUS_SUCCESS;
620 
621 }
622 
624  switch_media_type_t type,
625  const char *iananame,
626  uint32_t rate,
627  const char *fmtp_in,
628  switch_payload_t *ptP,
629  switch_payload_t *recv_ptP,
630  char **fmtpP)
631 {
632  payload_map_t *pmap;
634  switch_rtp_engine_t *engine;
635  switch_payload_t pt = 0, recv_pt = 0;
636  int found = 0;
637  char *fmtp = NULL;
638 
639  switch_assert(session);
640 
641  if (!(smh = session->media_handle)) {
642  return SWITCH_STATUS_FALSE;
643  }
644 
645  engine = &smh->engines[type];
646 
648  for (pmap = engine->payload_map; pmap ; pmap = pmap->next) {
649  char *fmtp_a = pmap->rm_fmtp;
650 
651  if (!pmap->allocated) continue;
652 
653  if (!fmtp_a) fmtp_a = "";
654  if (!fmtp_in) fmtp_in = "";
655 
656 
657  if (!strcasecmp(pmap->iananame, iananame) && !strcasecmp(fmtp_a, fmtp_in) && (!rate || (rate == pmap->rate))) {
658  pt = pmap->pt;
659  recv_pt = pmap->recv_pt;
660  fmtp = pmap->rm_fmtp;
661  found++;
662  break;
663  }
664  }
666 
667  if (found) {
668  if (ptP) {
669  *ptP = pt;
670  }
671  if (recv_ptP) {
672  *recv_ptP = recv_pt;
673  }
674 
675  if (!zstr(fmtp) && fmtpP) {
676  *fmtpP = fmtp;
677  }
678 
679  return SWITCH_STATUS_SUCCESS;
680  }
681 
682  return SWITCH_STATUS_FALSE;
683 
684 }
685 
686 
688  switch_media_type_t type,
689  const char *name,
690  const char *modname,
691  const char *fmtp,
692  switch_sdp_type_t sdp_type,
693  uint32_t pt,
694  uint32_t rate,
695  uint32_t ptime,
696  uint32_t channels,
697  uint8_t negotiated)
698 {
699  payload_map_t *pmap;
700  int exists = 0;
702  switch_rtp_engine_t *engine;
703 
704  switch_assert(session);
705 
706  if (!(smh = session->media_handle)) {
707  return NULL;
708  }
709 
710  engine = &smh->engines[type];
711 
713 
714 
715  for (pmap = engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) {
716 
717  if (sdp_type == SDP_ANSWER) {
718  switch(type) {
720  exists = (type == pmap->type && !strcasecmp(name, pmap->iananame));
721  break;
723  exists = (type == pmap->type && !strcasecmp(name, pmap->iananame) && pmap->pt == pt && (!pmap->rate || rate == pmap->rate) && (!pmap->ptime || pmap->ptime == ptime));
724  break;
726  exists = (pmap->sdp_type == SDP_OFFER && type == pmap->type && !strcasecmp(name, pmap->iananame));
727 
728  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "CHECK PMAP %s:%s %d %s:%s %d ... %d\n",
729  name, "RES", pt,
730  pmap->iananame, pmap->sdp_type == SDP_OFFER ? "REQ" : "RES", pmap->pt, exists);
731 
732 
733  break;
734  }
735 
736  if (exists) {
737 
738  if (!zstr(fmtp) && !zstr(pmap->rm_fmtp)) {
739  if (strcmp(pmap->rm_fmtp, fmtp)) {
740  exists = 0;
741  continue;
742  }
743  }
744 
745  break;
746  }
747 
748  } else {
749  if (type == SWITCH_MEDIA_TYPE_TEXT) {
750  exists = (type == pmap->type && !strcasecmp(name, pmap->iananame) && pmap->pt == pt);
751  } else {
752  exists = (type == pmap->type && !strcasecmp(name, pmap->iananame) && pmap->pt == pt && (!pmap->rate || rate == pmap->rate) && (!pmap->ptime || pmap->ptime == ptime));
753  }
754 
755  if (exists) {
756  if (type != SWITCH_MEDIA_TYPE_TEXT && !zstr(fmtp) && !zstr(pmap->rm_fmtp)) {
757  if (strcmp(pmap->rm_fmtp, fmtp)) {
758  exists = 0;
759  continue;
760  }
761  }
762 
763  break;
764  }
765  }
766  }
767 
768  if (!exists) {
769  switch_ssize_t hlen = -1;
770 
771  if (engine->payload_map && !engine->payload_map->allocated) {
772  pmap = engine->payload_map;
773  } else {
774  pmap = switch_core_alloc(session->pool, sizeof(*pmap));
775  }
776 
777  pmap->type = type;
778  pmap->iananame = switch_core_strdup(session->pool, name);
779  pmap->rm_encoding = pmap->iananame;
780  pmap->hash = switch_ci_hashfunc_default(pmap->iananame, &hlen);
781  pmap->channels = 1;
782  }
783 
784  if (ptime) {
785  pmap->ptime = ptime;
786  }
787 
788  if (rate) {
789  pmap->rate = rate;
790  }
791 
792  if (channels) {
793  pmap->channels = channels;
794  }
795 
796  if (modname) {
797  pmap->modname = switch_core_strdup(session->pool, modname);
798  }
799 
800  if (!zstr(fmtp)) {
801  if (sdp_type == SDP_OFFER || !exists) {
802  pmap->rm_fmtp = switch_core_strdup(session->pool, fmtp);
803  }
804  }
805 
806  pmap->allocated = 1;
807 
808  pmap->recv_pt = (switch_payload_t) pt;
809 
810 
811  if (sdp_type == SDP_OFFER || !exists) {
812  pmap->pt = (switch_payload_t) pt;
813  }
814 
815  if (negotiated) {
816  pmap->negotiated = negotiated;
817  }
818 
819  if (!exists) {
820  pmap->sdp_type = sdp_type;
821 
822  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "ADD PMAP %s %s %d\n", sdp_type == SDP_OFFER ? "REQ" : "RES", name, pt);
823 
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) {
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  "srtp_remote_text_crypto_key",
886  "srtp_remote_text_crypto_tag",
887  "srtp_remote_text_crypto_type",
888  "rtp_secure_media",
889  "rtp_secure_media_inbound",
890  "rtp_secure_media_outbound",
891  NULL};
892 
893  for(i = 0; vars[i] ;i++) {
894  switch_channel_set_variable(session->channel, vars[i], NULL);
895  }
896 
897  if (!(smh = session->media_handle)) {
898  return;
899  }
900  for (i = 0; i < CRYPTO_INVALID; i++) {
904  }
905 
906 }
907 
909 {
910  if (!session->media_handle) {
911  return NULL;
912  }
913 
914  return session->media_handle->engines[type].ssec[session->media_handle->engines[type].crypto_type].local_crypto_key;
915 }
916 
917 
918 
920 {
921 
922  if (switch_stristr("clear", str)) {
923  *flag_pole = 0;
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("~CISCO_SKIP_MARK_BIT_2833", str)) {
931  *flag_pole &= ~RTP_BUG_CISCO_SKIP_MARK_BIT_2833;
932  }
933 
934  if (switch_stristr("SONUS_SEND_INVALID_TIMESTAMP_2833", str)) {
936  }
937 
938  if (switch_stristr("~SONUS_SEND_INVALID_TIMESTAMP_2833", str)) {
940  }
941 
942  if (switch_stristr("IGNORE_MARK_BIT", str)) {
943  *flag_pole |= RTP_BUG_IGNORE_MARK_BIT;
944  }
945 
946  if (switch_stristr("~IGNORE_MARK_BIT", str)) {
947  *flag_pole &= ~RTP_BUG_IGNORE_MARK_BIT;
948  }
949 
950  if (switch_stristr("SEND_LINEAR_TIMESTAMPS", str)) {
951  *flag_pole |= RTP_BUG_SEND_LINEAR_TIMESTAMPS;
952  }
953 
954  if (switch_stristr("~SEND_LINEAR_TIMESTAMPS", str)) {
955  *flag_pole &= ~RTP_BUG_SEND_LINEAR_TIMESTAMPS;
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("~START_SEQ_AT_ZERO", str)) {
963  *flag_pole &= ~RTP_BUG_START_SEQ_AT_ZERO;
964  }
965 
966  if (switch_stristr("NEVER_SEND_MARKER", str)) {
967  *flag_pole |= RTP_BUG_NEVER_SEND_MARKER;
968  }
969 
970  if (switch_stristr("~NEVER_SEND_MARKER", str)) {
971  *flag_pole &= ~RTP_BUG_NEVER_SEND_MARKER;
972  }
973 
974  if (switch_stristr("IGNORE_DTMF_DURATION", str)) {
975  *flag_pole |= RTP_BUG_IGNORE_DTMF_DURATION;
976  }
977 
978  if (switch_stristr("~IGNORE_DTMF_DURATION", str)) {
979  *flag_pole &= ~RTP_BUG_IGNORE_DTMF_DURATION;
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_PACKETS", str)) {
987  *flag_pole &= ~RTP_BUG_ACCEPT_ANY_PACKETS;
988  }
989 
990  if (switch_stristr("ACCEPT_ANY_PAYLOAD", str)) {
991  *flag_pole |= RTP_BUG_ACCEPT_ANY_PAYLOAD;
992  }
993 
994  if (switch_stristr("~ACCEPT_ANY_PAYLOAD", str)) {
995  *flag_pole &= ~RTP_BUG_ACCEPT_ANY_PAYLOAD;
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("~GEN_ONE_GEN_ALL", str)) {
1003  *flag_pole &= ~RTP_BUG_GEN_ONE_GEN_ALL;
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("~CHANGE_SSRC_ON_MARKER", str)) {
1011  *flag_pole &= ~RTP_BUG_CHANGE_SSRC_ON_MARKER;
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("~FLUSH_JB_ON_DTMF", str)) {
1019  *flag_pole &= ~RTP_BUG_FLUSH_JB_ON_DTMF;
1020  }
1021 
1022  if (switch_stristr("ALWAYS_AUTO_ADJUST", str)) {
1024  }
1025 
1026  if (switch_stristr("~ALWAYS_AUTO_ADJUST", str)) {
1028  }
1029 }
1030 
1031 /**
1032  * If @use_alias != 0 then send crypto with alias name instead of name.
1033  */
1035  switch_media_type_t type,
1036  int index, switch_rtp_crypto_key_type_t ctype, switch_rtp_crypto_direction_t direction, int force, int use_alias)
1037 {
1038  unsigned char b64_key[512] = "";
1039  unsigned char *key;
1040  const char *val;
1041  switch_channel_t *channel;
1042  char *p;
1043  switch_rtp_engine_t *engine;
1044 
1045  switch_assert(smh);
1046  channel = switch_core_session_get_channel(smh->session);
1047 
1048  engine = &smh->engines[type];
1049 
1050  if (!force && engine->ssec[ctype].local_raw_key[0]) {
1051  return SWITCH_STATUS_SUCCESS;
1052  }
1053 
1054 //#define SAME_KEY
1055 #ifdef SAME_KEY
1056  if (switch_channel_test_flag(channel, CF_AVPF) && type == SWITCH_MEDIA_TYPE_VIDEO) {
1057  if (direction == SWITCH_RTP_CRYPTO_SEND) {
1058  memcpy(engine->ssec[ctype].local_raw_key, smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec.local_raw_key, SUITES[ctype].keysalt_len);
1059  key = engine->ssec[ctype].local_raw_key;
1060  } else {
1061  memcpy(engine->ssec[ctype].remote_raw_key, smh->engines[SWITCH_MEDIA_TYPE_AUDIO].ssec.remote_raw_key, SUITES[ctype].keysalt_len);
1062  key = engine->ssec[ctype].remote_raw_key;
1063  }
1064  } else {
1065 #endif
1066  if (direction == SWITCH_RTP_CRYPTO_SEND) {
1067  key = engine->ssec[ctype].local_raw_key;
1068  } else {
1069  key = engine->ssec[ctype].remote_raw_key;
1070  }
1071 
1072  switch_rtp_get_random(key, SUITES[ctype].keysalt_len);
1073 #ifdef SAME_KEY
1074  }
1075 #endif
1076 
1077  switch_b64_encode(key, SUITES[ctype].keysalt_len, b64_key, sizeof(b64_key));
1078  if (switch_channel_var_false(channel, "rtp_pad_srtp_keys")) {
1079  p = strrchr((char *) b64_key, '=');
1080 
1081  while (p && *p && *p == '=') {
1082  *p-- = '\0';
1083  }
1084  }
1085 
1086  if (index == SWITCH_NO_CRYPTO_TAG) index = ctype + 1;
1087 
1088  if (switch_channel_var_true(channel, "rtp_secure_media_mki")) {
1089  engine->ssec[ctype].local_crypto_key = switch_core_session_sprintf(smh->session, "%d %s inline:%s|2^31|1:1", index, (use_alias ? SUITES[ctype].alias : SUITES[ctype].name), b64_key);
1090  } else {
1091  engine->ssec[ctype].local_crypto_key = switch_core_session_sprintf(smh->session, "%d %s inline:%s", index, (use_alias ? SUITES[ctype].alias : SUITES[ctype].name), b64_key);
1092  }
1093 
1094  switch_channel_set_variable_name_printf(smh->session->channel, engine->ssec[ctype].local_crypto_key, "rtp_last_%s_local_crypto_key", type2str(type));
1096 
1097  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Set Local %s crypto Key [%s]\n",
1098  type2str(type),
1099  engine->ssec[ctype].local_crypto_key);
1100 
1101  if (!(smh->mparams->ndlb & SM_NDLB_DISABLE_SRTP_AUTH) &&
1102  !((val = switch_channel_get_variable(channel, "NDLB_support_asterisk_missing_srtp_auth")) && switch_true(val))) {
1103  engine->ssec[ctype].crypto_type = ctype;
1104  } else {
1105  engine->ssec[ctype].crypto_type = AES_CM_128_NULL_AUTH;
1106  }
1107 
1108  return SWITCH_STATUS_SUCCESS;
1109 }
1110 
1111 #define CRYPTO_KEY_MATERIAL_LIFETIME_MKI_ERR 0x0u
1112 #define CRYPTO_KEY_MATERIAL_MKI 0x1u
1113 #define CRYPTO_KEY_MATERIAL_LIFETIME 0x2u
1114 
1115 #define RAW_BITS_PER_64_ENCODED_CHAR 6
1116 
1117 /* Return uint32_t which contains all the info about the field found:
1118  * XXXXXXXa | YYYYYYYY | YYYYYYYY | ZZZZZZZZ
1119  * where:
1120  * a - CRYPTO_KEY_MATERIAL_LIFETIME if LIFETIME, CRYPTO_KEY_MATERIAL_MKI if MKI
1121  * YYYYYYYY and ZZZZZZZZ - depend on 'a':
1122  * if a is LIFETIME then YYYYYYYY is decimal Base, ZZZZZZZZ is decimal Exponent
1123  * if a is MKI, then YYYYYYYY is decimal MKI_ID, ZZZZZZZZ is decimal MKI_SIZE
1124  */
1125 static uint32_t parse_lifetime_mki(const char **p, const char *end)
1126 {
1127  const char *field_begin;
1128  const char *field_end;
1129  const char *sep, *space;
1130  uint32_t res = 0;
1131 
1132  uint32_t val = 0;
1133  int i;
1134 
1135  switch_assert(*p != NULL);
1136  switch_assert(end != NULL);
1137 
1138  field_begin = strchr(*p, '|');
1139 
1140  if (field_begin && (field_begin + 1 < end)) {
1141  space = strchr(field_begin, ' ');
1142  field_end = strchr(field_begin + 2, '|');
1143 
1144  if (!field_end) {
1145  field_end = end;
1146  }
1147 
1148  if (space) {
1149  if ((field_end == NULL) || (space < field_end)) {
1150  field_end = space;
1151  }
1152  }
1153 
1154  if (field_end) {
1155  /* Closing '|' found. */
1156  sep = strchr(field_begin, ':'); /* The lifetime field never includes a colon, whereas the third field always does. (RFC 4568) */
1157  if (sep && (sep + 1 < field_end) && isdigit(*(sep + 1))) {
1158  res |= (CRYPTO_KEY_MATERIAL_MKI << 24);
1159 
1160  for (i = 1, *p = sep - 1; *p != field_begin; --(*p), i *= 10) {
1161  val += ((**p) - '0') * i;
1162  }
1163 
1164  res |= ((val << 8) & 0x00ffff00); /* MKI_ID */
1165 
1166  val = 0;
1167  for (i = 1, *p = field_end - 1; *p != sep; --(*p), i *= 10) {
1168  val += ((**p) - '0') * i;
1169  }
1170  res |= (val & 0x000000ff); /* MKI_SIZE */
1171  } else if (isdigit(*(field_begin + 1)) && (*(field_begin + 2) == '^') && isdigit(*(field_begin + 3))) {
1172  res |= (CRYPTO_KEY_MATERIAL_LIFETIME << 24);
1173  val = ((uint32_t) (*(field_begin + 1) - '0')) << 8;
1174  res |= val; /* LIFETIME base. */
1175 
1176  val = 0;
1177  for (i = 1, *p = field_end - 1; *p != (field_begin + 2); --(*p), i *= 10) {
1178  val += ((**p) - '0') * i;
1179  }
1180 
1181  res |= (val & 0x000000ff); /* LIFETIME exponent. */
1182  }
1183  }
1184 
1185  *p = field_end;
1186  }
1187 
1188  return res;
1189 }
1190 
1192  switch_core_session_t *session,
1195  unsigned char raw_key[SWITCH_RTP_MAX_CRYPTO_LEN],
1196  int raw_key_len,
1197  const char *key_material,
1198  int key_material_len,
1199  uint64_t lifetime,
1200  unsigned int mki_id,
1201  unsigned int mki_size)
1202 {
1203  struct switch_crypto_key_material_s *new_key_material;
1204 
1205  new_key_material = switch_core_session_alloc(session, (sizeof(*new_key_material)));
1206  if (new_key_material == NULL) {
1207  return NULL;
1208  }
1209 
1210  new_key_material->method = method;
1211  memcpy(new_key_material->raw_key, raw_key, raw_key_len);
1212  new_key_material->crypto_key = switch_core_session_strdup(session, key_material);
1213  new_key_material->lifetime = lifetime;
1214  new_key_material->mki_id = mki_id;
1215  new_key_material->mki_size = mki_size;
1216 
1217  new_key_material->next = tail;
1218 
1219  return new_key_material;
1220 }
1221 
1222 /*
1223  * Skip all space and return pointer to the '\0' terminator of the char string candidate to be a key-material
1224  * or pointer to first ' ' in the candidate string.
1225  */
1227 {
1228  const char *end = NULL;
1229 
1230  switch_assert(p != NULL);
1231 
1232  if (p) {
1233  end = strchr(p, ' '); /* find the end of the continuous string of characters in the candidate string */
1234  if (end == NULL)
1235  end = p + strlen(p);
1236  }
1237 
1238  return end;
1239 }
1240 
1242 {
1243  unsigned char key[SWITCH_RTP_MAX_CRYPTO_LEN];
1245 
1246  const char *p, *delimit;
1247  const char *key_material_begin;
1248  const char *key_material_end = NULL; /* begin and end of the current key material candidate */
1249  int method_len;
1250  int keysalt_len;
1251 
1252  const char *opts;
1253  uint32_t opt_field; /* LIFETIME or MKI */
1255  uint64_t lifetime = 0;
1256  uint16_t lifetime_base = 0;
1257  uint16_t lifetime_exp = 0;
1258  uint16_t mki_id = 0;
1259  uint16_t mki_size = 0;
1260  switch_crypto_key_material_t *key_material = NULL;
1261  unsigned long *key_material_n = NULL;
1262 
1263  bool multiple_keys = false;
1264 
1265  const char *key_param;
1266 
1267 
1268  if (direction == SWITCH_RTP_CRYPTO_SEND || direction == SWITCH_RTP_CRYPTO_SEND_RTCP) {
1269  key_param = ssec->local_crypto_key;
1270  key_material = ssec->local_key_material_next;
1271  key_material_n = &ssec->local_key_material_n;
1272  } else {
1273  key_param = ssec->remote_crypto_key;
1274  key_material = ssec->remote_key_material_next;
1275  key_material_n = &ssec->remote_key_material_n;
1276  }
1277 
1278  if (zstr(key_param)) {
1279  goto no_crypto_found;
1280  }
1281 
1282  *key_material_n = 0;
1283 
1284  p = strchr(key_param, ' ');
1285 
1286  if (!(p && *p && *(p + 1))) {
1287  goto no_crypto_found;
1288  }
1289 
1290  p++;
1291 
1293 
1294  if (type == CRYPTO_INVALID) {
1295  goto bad_crypto;
1296  }
1297 
1298  p = strchr(p, ' '); /* skip the crypto suite description */
1299  if (p == NULL) {
1300  goto bad_crypto;
1301  }
1302 
1303  do {
1304  if (*key_material_n == SWITCH_CRYPTO_MKI_MAX) {
1305  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Skipping excess of MKIs due to max number of suppoerted MKIs %d exceeded\n", SWITCH_CRYPTO_MKI_MAX);
1306  break;
1307  }
1308 
1309  p = switch_strip_spaces((char*) p, 0);
1310  if (!p) {
1311  break;
1312  }
1313 
1314  key_material_begin = p;
1316 
1317  /* Parsing the key material candidate within [begin, end). */
1318 
1319  if ((delimit = strchr(p, ':')) == NULL) {
1320  goto bad_error_parsing_near;
1321  }
1322 
1323  method_len = delimit - p;
1324 
1325  if (strncasecmp(p, CRYPTO_KEY_PARAM_METHOD[CRYPTO_KEY_PARAM_METHOD_INLINE], method_len)) {
1326  goto bad_key_param_method;
1327  }
1328 
1330 
1331  /* Valid key-material found. Save as default key in secure_settings_s. */
1332 
1333  p = delimit + 1; /* skip ':' */
1334  if (!(p && *p && *(p + 1))) {
1335  goto bad_keysalt;
1336  }
1337 
1338  /* Check if '|' is present in currently considered key-material. */
1339  if ((opts = strchr(p, '|')) && (opts < key_material_end)) {
1340  keysalt_len = opts - p;
1341  } else {
1342  keysalt_len = key_material_end - p;
1343  }
1344 
1345  if (keysalt_len > sizeof(key)) {
1346  goto bad_keysalt_len;
1347  }
1348 
1349  switch_b64_decode(p, (char *) key, keysalt_len);
1350 
1351  if (!multiple_keys) { /* First key becomes default (used in case no MKI is found). */
1352  if (direction == SWITCH_RTP_CRYPTO_SEND) {
1353  memcpy(ssec->local_raw_key, key, SUITES[type].keysalt_len);
1354  } else {
1355  memcpy(ssec->remote_raw_key, key, SUITES[type].keysalt_len);
1356  }
1357  multiple_keys = true;
1358  }
1359 
1360  p += keysalt_len;
1361 
1362  if (!(p < key_material_end)) {
1363  continue;
1364  }
1365 
1366  if (opts) { /* if opts != NULL then opts points to first '|' in current key-material cadidate, parse it as LIFETIME or MKI */
1367 
1368  lifetime = 0;
1369  mki_id = 0;
1370  mki_size = 0;
1371 
1372  for (int i = 0; i < 2 && (*opts == '|'); ++i) {
1373 
1374  opt_field = parse_lifetime_mki(&opts, key_material_end);
1375 
1376  switch ((opt_field >> 24) & 0x3) {
1377 
1379 
1380  lifetime_base = ((opt_field & 0x00ffff00) >> 8) & 0xffff;
1381  lifetime_exp = (opt_field & 0x000000ff) & 0xffff;
1382  lifetime = pow(lifetime_base, lifetime_exp);
1383  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "LIFETIME found in %s, base %u exp %u\n", p, lifetime_base, lifetime_exp);
1384  break;
1385 
1387 
1388  mki_id = ((opt_field & 0x00ffff00) >> 8) & 0xffff;
1389  mki_size = (opt_field & 0x000000ff) & 0xffff;
1390  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "MKI found in %s, id %u size %u\n", p, mki_id, mki_size);
1391  break;
1392 
1393  default:
1394  goto bad_key_lifetime_or_mki;
1395  }
1396  }
1397 
1398  if (mki_id == 0 && lifetime == 0) {
1399  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Bad MKI found in %s, (parsed as: id %u size %u lifetime base %u exp %u\n", p, mki_id, mki_size, lifetime_base, lifetime_exp);
1400  return SWITCH_STATUS_FALSE;
1401  } else if (mki_id == 0 || lifetime == 0) {
1402  if (mki_id == 0) {
1403  if (key_material)
1404  goto bad_key_no_mki_index;
1405 
1406  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Skipping MKI due to empty index\n");
1407  } else {
1408  if (mki_size == 0)
1409  goto bad_key_no_mki_size;
1410 
1411  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Skipping MKI due to empty lifetime\n");
1412  }
1413  continue;
1414  }
1415  }
1416 
1417  if (key_material) {
1418  if (mki_id == 0) {
1419  goto bad_key_no_mki_index;
1420  }
1421 
1422  if (mki_size != key_material->mki_size) {
1423  goto bad_key_mki_size;
1424  }
1425  }
1426 
1427  key_material = switch_core_media_crypto_append_key_material(session, key_material, method, (unsigned char*) key,
1428  SUITES[type].keysalt_len, (char*) key_material_begin, key_material_end - key_material_begin, lifetime, mki_id, mki_size);
1429  *key_material_n = *key_material_n + 1;
1430  } while ((p = switch_strip_spaces((char*) key_material_end, 0)) && (*p != '\0'));
1431 
1432  if (direction == SWITCH_RTP_CRYPTO_SEND || direction == SWITCH_RTP_CRYPTO_SEND_RTCP) {
1433  ssec->local_key_material_next = key_material;
1434  } else {
1435  ssec->remote_key_material_next = key_material;
1436  }
1437 
1438  return SWITCH_STATUS_SUCCESS;
1439 
1440 
1441 no_crypto_found:
1442  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error! No crypto to parse\n");
1443  return SWITCH_STATUS_FALSE;
1444 
1445 bad_error_parsing_near:
1446  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! Parsing near %s\n", p);
1447  return SWITCH_STATUS_FALSE;
1448 
1449 bad_crypto:
1450  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! SRTP: Invalid format of crypto attribute %s\n", key_param);
1451  return SWITCH_STATUS_FALSE;
1452 
1453 bad_keysalt:
1454  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! SRTP: Invalid keysalt in the crypto attribute %s\n", key_param);
1455  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! Parsing near %s\n", p);
1456  return SWITCH_STATUS_FALSE;
1457 
1458 bad_keysalt_len:
1459  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! SRTP: Invalid keysalt length in the crypto attribute %s\n", key_param);
1460  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! Parsing near %s\n", p);
1461  return SWITCH_STATUS_FALSE;
1462 
1463 bad_key_lifetime_or_mki:
1464  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! SRTP: Invalid key param MKI or LIFETIME in the crypto attribute %s\n", key_param);
1465  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! Parsing near %s\n", p);
1466  return SWITCH_STATUS_FALSE;
1467 
1468 bad_key_no_mki_index:
1469  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Crypto invalid: multiple keys in a single crypto MUST all have MKI indices, %s\n", key_param);
1470  return SWITCH_STATUS_FALSE;
1471 
1472 bad_key_no_mki_size:
1473  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Crypto invalid: MKI index with no MKI size in %s\n", key_param);
1474  return SWITCH_STATUS_FALSE;
1475 
1476 bad_key_mki_size:
1477  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Crypto invalid: MKI sizes differ in %s\n", key_param);
1478  return SWITCH_STATUS_FALSE;
1479 
1480 bad_key_param_method:
1481  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! SRTP: Invalid key param method type in %s\n", key_param);
1482  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error! Parsing near %s\n", p);
1483  return SWITCH_STATUS_FALSE;
1484 }
1485 
1487 {
1488  switch_rtp_engine_t *engine;
1489  if (!session->media_handle) return;
1490  engine = &session->media_handle->engines[type];
1491  engine->rtp_session = rtp_session;
1492  engine->type = type;
1493 }
1494 
1496 {
1497  switch_assert(session);
1498  if (!session->media_handle) return NULL;
1499  return session->media_handle->engines[type].rtp_session;
1500 }
1501 
1503 {
1504  const char *tmp;
1505  switch_rtp_engine_t *engine;
1506  char *keyvar, *tagvar, *ctypevar;
1507 
1508  if (!session->media_handle) return;
1509  engine = &session->media_handle->engines[type];
1510 
1511  if (type == SWITCH_MEDIA_TYPE_AUDIO) {
1512  keyvar = "srtp_remote_audio_crypto_key";
1513  tagvar = "srtp_remote_audio_crypto_tag";
1514  ctypevar = "srtp_remote_audio_crypto_type";
1515  } else if (type == SWITCH_MEDIA_TYPE_VIDEO) {
1516  keyvar = "srtp_remote_video_crypto_key";
1517  tagvar = "srtp_remote_video_crypto_tag";
1518  ctypevar = "srtp_remote_video_crypto_type";
1519  } else if (type == SWITCH_MEDIA_TYPE_TEXT) {
1520  keyvar = "srtp_remote_text_crypto_key";
1521  tagvar = "srtp_remote_text_crypto_tag";
1522  ctypevar = "srtp_remote_text_crypto_type";
1523  } else return;
1524 
1525  if ((tmp = switch_channel_get_variable(session->channel, keyvar))) {
1526  const char *ct;
1527  if ((ct = switch_channel_get_variable(session->channel, ctypevar))) {
1529  }
1530 
1531  engine->ssec[engine->crypto_type].remote_crypto_key = switch_core_session_strdup(session, tmp);
1532 
1533  if ((tmp = switch_channel_get_variable(session->channel, tagvar))) {
1534  int tv = atoi(tmp);
1535  engine->ssec[engine->crypto_type].crypto_tag = tv;
1536  } else {
1537  engine->ssec[engine->crypto_type].crypto_tag = 1;
1538  }
1539 
1541  }
1542 }
1543 
1544 
1546 {
1547  switch_rtp_engine_t *engine;
1548  const char *varname;
1549 
1550  if (type == SWITCH_MEDIA_TYPE_AUDIO) {
1551  varname = "rtp_secure_audio_confirmed";
1552  } else if (type == SWITCH_MEDIA_TYPE_VIDEO) {
1553  varname = "rtp_secure_video_confirmed";
1554  } else if (type == SWITCH_MEDIA_TYPE_TEXT) {
1555  varname = "rtp_secure_text_confirmed";
1556  } else {
1557  return;
1558  }
1559 
1560  if (!session->media_handle) return;
1561 
1562  engine = &session->media_handle->engines[type];
1563 
1565  return;
1566  }
1567 
1568  if (engine->ssec[engine->crypto_type].remote_crypto_key && switch_channel_test_flag(session->channel, CF_SECURE)) {
1569 
1570  if (switch_channel_var_true(session->channel, "rtp_secure_media_mki"))
1572 
1574 
1575 
1577 
1579 
1580  switch_channel_set_variable(session->channel, varname, "true");
1581 
1582 
1583  switch_channel_set_variable(session->channel, "rtp_secure_media_negotiated", SUITES[engine->crypto_type].name);
1584 
1585  }
1586 
1587 }
1588 
1590 {
1591  const char *var = NULL;
1592  const char *val = NULL;
1593  char *suites = NULL;
1594  switch_media_handle_t *smh;
1595  char *fields[CRYPTO_INVALID+1];
1596  int argc = 0, i = 0, j = 0, k = 0;
1597 
1598  if (!(smh = session->media_handle)) {
1599  return;
1600  }
1601 
1602  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
1603  return;
1604  }
1605 
1607  var = "rtp_secure_media_inbound";
1608  } else {
1609  var = "rtp_secure_media_outbound";
1610  }
1611 
1612  if (!(val = switch_channel_get_variable(session->channel, var))) {
1613  var = "rtp_secure_media";
1614  val = switch_channel_get_variable(session->channel, var);
1615  }
1616 
1617  if (!zstr(val) && (suites = strchr(val, ':'))) {
1618  *suites++ = '\0';
1619  }
1620 
1621  if (zstr(suites)) {
1622  suites = (char *) switch_channel_get_variable(session->channel, "rtp_secure_media_suites");
1623  }
1624 
1625  if (zstr(val)) {
1627  val = "optional";
1628  } else {
1629  val = "forbidden";
1630  }
1631  }
1632 
1633  if (!strcasecmp(val, "optional")) {
1635  } else if (switch_true(val) || !strcasecmp(val, "mandatory")) {
1637  } else {
1639  if (!switch_false(val) && strcasecmp(val, "forbidden")) {
1640  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "INVALID VALUE FOR %s defaulting to 'forbidden'\n", var);
1641  }
1642  }
1643 
1644  if (smh->crypto_mode != CRYPTO_MODE_FORBIDDEN && !zstr(suites)) {
1645  argc = switch_split((char *)suites, ':', fields);
1646 
1647  for (i = 0; i < argc; i++) {
1648  int ok = 0;
1649 
1650  for (j = 0; j < CRYPTO_INVALID; j++) {
1651  if (!strcasecmp(fields[i], SUITES[j].name)) {
1652  smh->crypto_suite_order[k++] = SUITES[j].type;
1653  ok++;
1654  break;
1655  }
1656  }
1657 
1658  if (!ok) {
1659  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "INVALID SUITE SUPPLIED\n");
1660  }
1661 
1662  }
1663  } else {
1664  for (i = 0; i < CRYPTO_INVALID; i++) {
1665  smh->crypto_suite_order[k++] = SUITES[i].type;
1666  }
1667  }
1668 }
1669 
1671  const char *varname,
1672  switch_media_type_t type, const char *crypto, int crypto_tag, switch_sdp_type_t sdp_type)
1673 {
1674  int got_crypto = 0;
1675  int i = 0;
1676  int ctype = 0;
1677  const char *vval = NULL;
1678  int use_alias = 0;
1679  switch_rtp_engine_t *engine;
1680  switch_media_handle_t *smh;
1681 
1682  if (!(smh = session->media_handle)) {
1683  return 0;
1684  }
1685 
1686  if (smh->crypto_mode == CRYPTO_MODE_FORBIDDEN) {
1687  return -1;
1688  }
1689 
1690  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
1691  return 0;
1692  }
1693 
1694  if (!crypto) {
1695  return 0;
1696  }
1697  engine = &session->media_handle->engines[type];
1698 
1699  for (i = 0; smh->crypto_suite_order[i] != CRYPTO_INVALID; i++) {
1701 
1702  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "looking for crypto suite [%s]alias=[%s] in [%s]\n", SUITES[j].name, SUITES[j].alias, crypto);
1703 
1704  if (switch_stristr(SUITES[j].alias, crypto)) {
1705  use_alias = 1;
1706  }
1707 
1708  if (use_alias || switch_stristr(SUITES[j].name, crypto)) {
1709  ctype = SUITES[j].type;
1710  vval = use_alias ? SUITES[j].alias : SUITES[j].name;
1711  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Found suite %s\n", vval);
1712  switch_channel_set_variable(session->channel, "rtp_secure_media_negotiated", vval);
1713  break;
1714  }
1715 
1716  use_alias = 0;
1717  }
1718 
1719  if (engine->ssec[engine->crypto_type].remote_crypto_key && switch_rtp_ready(engine->rtp_session)) {
1720  /* Compare all the key. The tag may remain the same even if key changed */
1721  if (engine->crypto_type != CRYPTO_INVALID && !strcmp(crypto, engine->ssec[engine->crypto_type].remote_crypto_key)) {
1722  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Existing key is still valid.\n");
1723  got_crypto = 1;
1724  } else {
1725  const char *a = switch_stristr("AE", engine->ssec[engine->crypto_type].remote_crypto_key);
1726  const char *b = switch_stristr("AE", crypto);
1727 
1728  if (sdp_type == SDP_OFFER) {
1729  if (!vval) {
1730  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Unsupported Crypto [%s]\n", crypto);
1731  goto end;
1732  }
1733  switch_channel_set_variable(session->channel, varname, vval);
1734 
1735  switch_core_media_build_crypto(session->media_handle, type, crypto_tag, ctype, SWITCH_RTP_CRYPTO_SEND, 1, use_alias);
1736  switch_rtp_add_crypto_key(engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, atoi(crypto), &engine->ssec[engine->crypto_type]);
1737  }
1738 
1739  if (a && b && !strncasecmp(a, b, 23)) {
1740  engine->crypto_type = ctype;
1741 
1742  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Change Remote key to [%s]\n", crypto);
1743  engine->ssec[engine->crypto_type].remote_crypto_key = switch_core_session_strdup(session, crypto);
1744 
1745  if (engine->type == SWITCH_MEDIA_TYPE_AUDIO) {
1746  switch_channel_set_variable(session->channel, "srtp_remote_audio_crypto_key", crypto);
1747  switch_channel_set_variable_printf(session->channel, "srtp_remote_audio_crypto_tag", "%d", crypto_tag);
1748  switch_channel_set_variable_printf(session->channel, "srtp_remote_audio_crypto_type", "%s", switch_core_media_crypto_type2str(ctype));
1749  } else if (engine->type == SWITCH_MEDIA_TYPE_VIDEO) {
1750  switch_channel_set_variable(session->channel, "srtp_remote_video_crypto_key", crypto);
1751  switch_channel_set_variable_printf(session->channel, "srtp_remote_video_crypto_tag", "%d", crypto_tag);
1752  switch_channel_set_variable_printf(session->channel, "srtp_remote_video_crypto_type", "%s", switch_core_media_crypto_type2str(ctype));
1753  } else if (engine->type == SWITCH_MEDIA_TYPE_TEXT) {
1754  switch_channel_set_variable(session->channel, "srtp_remote_text_crypto_key", crypto);
1755  switch_channel_set_variable_printf(session->channel, "srtp_remote_text_crypto_tag", "%d", crypto_tag);
1756  switch_channel_set_variable_printf(session->channel, "srtp_remote_text_crypto_type", "%s", switch_core_media_crypto_type2str(ctype));
1757  }
1758 
1759  engine->ssec[engine->crypto_type].crypto_tag = crypto_tag;
1760 
1761 
1765  }
1766  got_crypto++;
1767 
1768  } else {
1769  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Ignoring unacceptable key\n");
1770  }
1771  }
1772  } else if (!switch_rtp_ready(engine->rtp_session)) {
1773 
1774  if (!vval) {
1775  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Unsupported Crypto [%s]\n", crypto);
1776  goto end;
1777  }
1778 
1779  engine->crypto_type = ctype;
1780  engine->ssec[engine->crypto_type].remote_crypto_key = switch_core_session_strdup(session, crypto);
1781  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set Remote Key [%s]\n", engine->ssec[engine->crypto_type].remote_crypto_key);
1782  if (engine->type == SWITCH_MEDIA_TYPE_AUDIO) {
1783  switch_channel_set_variable(session->channel, "srtp_remote_audio_crypto_key", crypto);
1784  switch_channel_set_variable_printf(session->channel, "srtp_remote_audio_crypto_type", "%s", switch_core_media_crypto_type2str(ctype));
1785  } else if (engine->type == SWITCH_MEDIA_TYPE_VIDEO) {
1786  switch_channel_set_variable(session->channel, "srtp_remote_video_crypto_key", crypto);
1787  switch_channel_set_variable_printf(session->channel, "srtp_remote_video_crypto_type", "%s", switch_core_media_crypto_type2str(ctype));
1788  } else if (engine->type == SWITCH_MEDIA_TYPE_TEXT) {
1789  switch_channel_set_variable(session->channel, "srtp_remote_text_crypto_key", crypto);
1790  switch_channel_set_variable_printf(session->channel, "srtp_remote_text_crypto_type", "%s", switch_core_media_crypto_type2str(ctype));
1791  }
1792 
1793  engine->ssec[engine->crypto_type].crypto_tag = crypto_tag;
1794  got_crypto++;
1795 
1796  switch_channel_set_variable(session->channel, varname, vval);
1798 
1799  if (zstr(engine->ssec[engine->crypto_type].local_crypto_key)) {
1800  switch_core_media_build_crypto(session->media_handle, type, crypto_tag, ctype, SWITCH_RTP_CRYPTO_SEND, 1, use_alias);
1801  }
1802  }
1803 
1804  end:
1805 
1806  return got_crypto;
1807 }
1808 
1809 
1811 {
1813  switch_media_handle_t *smh;
1814  int i;
1815 
1817  return;
1818  }
1819 
1820  if (!(smh = session->media_handle)) {
1821  return;
1822  }
1823 
1825  return;
1826  }
1827 
1828  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
1829  return;
1830  }
1831 
1833 
1834  for (i = 0; smh->crypto_suite_order[i] != CRYPTO_INVALID; i++) {
1837 
1840 
1843  }
1844 
1845 }
1846 
1847 #define add_stat(_i, _s) \
1848  switch_snprintf(var_name, sizeof(var_name), "rtp_%s_%s", switch_str_nil(prefix), _s) ; \
1849  switch_snprintf(var_val, sizeof(var_val), "%" SWITCH_SIZE_T_FMT, _i); \
1850  switch_channel_set_variable(channel, var_name, var_val)
1851 
1852 #define add_stat_double(_i, _s) \
1853  switch_snprintf(var_name, sizeof(var_name), "rtp_%s_%s", switch_str_nil(prefix), _s) ; \
1854  switch_snprintf(var_val, sizeof(var_val), "%0.2f", _i); \
1855  switch_channel_set_variable(channel, var_name, var_val)
1856 
1857 static void set_stats(switch_core_session_t *session, switch_media_type_t type, const char *prefix)
1858 {
1859  switch_rtp_stats_t *stats = switch_core_media_get_stats(session, type, NULL);
1861 
1862  char var_name[256] = "", var_val[35] = "";
1863 
1864  if (stats) {
1865  stats->inbound.std_deviation = sqrt(stats->inbound.variance);
1866 
1867  add_stat(stats->inbound.raw_bytes, "in_raw_bytes");
1868  add_stat(stats->inbound.media_bytes, "in_media_bytes");
1869  add_stat(stats->inbound.packet_count, "in_packet_count");
1870  add_stat(stats->inbound.media_packet_count, "in_media_packet_count");
1871  add_stat(stats->inbound.skip_packet_count, "in_skip_packet_count");
1872  add_stat(stats->inbound.jb_packet_count, "in_jitter_packet_count");
1873  add_stat(stats->inbound.dtmf_packet_count, "in_dtmf_packet_count");
1874  add_stat(stats->inbound.cng_packet_count, "in_cng_packet_count");
1875  add_stat(stats->inbound.flush_packet_count, "in_flush_packet_count");
1876  add_stat(stats->inbound.largest_jb_size, "in_largest_jb_size");
1877  add_stat_double(stats->inbound.min_variance, "in_jitter_min_variance");
1878  add_stat_double(stats->inbound.max_variance, "in_jitter_max_variance");
1879  add_stat_double(stats->inbound.lossrate, "in_jitter_loss_rate");
1880  add_stat_double(stats->inbound.burstrate, "in_jitter_burst_rate");
1881  add_stat_double(stats->inbound.mean_interval, "in_mean_interval");
1882  add_stat(stats->inbound.flaws, "in_flaw_total");
1883  add_stat_double(stats->inbound.R, "in_quality_percentage");
1884  add_stat_double(stats->inbound.mos, "in_mos");
1885 
1886 
1887  add_stat(stats->outbound.raw_bytes, "out_raw_bytes");
1888  add_stat(stats->outbound.media_bytes, "out_media_bytes");
1889  add_stat(stats->outbound.packet_count, "out_packet_count");
1890  add_stat(stats->outbound.media_packet_count, "out_media_packet_count");
1891  add_stat(stats->outbound.skip_packet_count, "out_skip_packet_count");
1892  add_stat(stats->outbound.dtmf_packet_count, "out_dtmf_packet_count");
1893  add_stat(stats->outbound.cng_packet_count, "out_cng_packet_count");
1894 
1895  add_stat(stats->rtcp.packet_count, "rtcp_packet_count");
1896  add_stat(stats->rtcp.octet_count, "rtcp_octet_count");
1897 
1898  }
1899 }
1900 
1902 {
1903  switch_media_handle_t *smh;
1904  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
1905 
1906  switch_assert(session);
1907 
1908  if (!(smh = session->media_handle)) {
1909  return;
1910  }
1911 
1912  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
1913  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
1914  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
1915 
1916  if (a_engine->rtp_session) {
1918  }
1919 
1920  if (v_engine->rtp_session) {
1922  }
1923 
1924  if (t_engine->rtp_session) {
1926  }
1927 
1928 }
1929 
1931 {
1932 
1933  if (!session->media_handle) {
1934  return;
1935  }
1936 
1938 
1939  set_stats(session, SWITCH_MEDIA_TYPE_AUDIO, "audio");
1940  set_stats(session, SWITCH_MEDIA_TYPE_VIDEO, "video");
1941  set_stats(session, SWITCH_MEDIA_TYPE_TEXT, "text");
1942 }
1943 
1944 
1945 
1947 {
1948  switch_media_handle_t *smh;
1949  switch_rtp_engine_t *a_engine, *v_engine;//, *t_engine;
1950 
1951  switch_assert(session);
1952 
1953  if (!(smh = session->media_handle)) {
1954  return;
1955  }
1956 
1957  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
1958  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
1959  //t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
1960 
1961 
1962  if (smh->video_timer.timer_interface) {
1964  }
1965 
1966  if (switch_core_codec_ready(&a_engine->read_codec)) {
1968  }
1969 
1970  if (switch_core_codec_ready(&a_engine->write_codec)) {
1972  }
1973 
1974  if (switch_core_codec_ready(&v_engine->read_codec)) {
1976  }
1977 
1978  if (switch_core_codec_ready(&v_engine->write_codec)) {
1980  }
1981 
1985 
1986  if (a_engine->write_fb) switch_frame_buffer_destroy(&a_engine->write_fb);
1987 
1989 }
1990 
1991 
1993 {
1995  switch_media_handle_t *smh = NULL;
1996  int i;
1997 
1998  *smhp = NULL;
1999 
2000  if (zstr(params->sdp_username)) {
2001  params->sdp_username = "FreeSWITCH";
2002  }
2003 
2004 
2005  if ((session->media_handle = switch_core_session_alloc(session, (sizeof(*smh))))) {
2006  session->media_handle->session = session;
2007 
2008 
2009  *smhp = session->media_handle;
2011  session->media_handle->media_flags[SCMF_RUNNING] = 1;
2012 
2016 
2017  for (i = 0; i < CRYPTO_INVALID; i++) {
2019  }
2020 
2021 
2022 
2026 
2027  for (i = 0; i < CRYPTO_INVALID; i++) {
2029  }
2030 
2031 
2032 
2036 
2037 
2038  switch_channel_set_variable(session->channel, "video_media_flow", "disabled");
2039  switch_channel_set_variable(session->channel, "audio_media_flow", "disabled");
2040  switch_channel_set_variable(session->channel, "text_media_flow", "disabled");
2041 
2045 
2046  for (i = 0; i < CRYPTO_INVALID; i++) {
2048  }
2049 
2050  session->media_handle->mparams = params;
2051 
2052  //if (!session->media_handle->mparams->video_key_freq) {
2053  // session->media_handle->mparams->video_key_freq = 10000000;
2054  //}
2055 
2056  if (!session->media_handle->mparams->video_key_first) {
2057  session->media_handle->mparams->video_key_first = 1000000;
2058  }
2059 
2060 
2061  for (i = 0; i <= CRYPTO_INVALID; i++) {
2063  }
2064 
2068 
2070  (uint32_t) ((intptr_t) &session->media_handle->engines[SWITCH_MEDIA_TYPE_AUDIO] + (switch_time_t) time(NULL));
2071 
2073  (uint32_t) ((intptr_t) &session->media_handle->engines[SWITCH_MEDIA_TYPE_VIDEO] + (switch_time_t) time(NULL) / 2);
2074 
2076  (uint32_t) ((intptr_t) &session->media_handle->engines[SWITCH_MEDIA_TYPE_TEXT] + (switch_time_t) time(NULL) / 2);
2077 
2078 
2079 
2083 
2088 
2089 
2093 
2095 
2096  status = SWITCH_STATUS_SUCCESS;
2097  }
2098 
2099 
2100  return status;
2101 }
2102 
2104 {
2105  switch_assert(smh);
2106 
2107  smh->media_flags[flag] = 1;
2108 
2109 }
2110 
2112 {
2113  int i;
2114  switch_assert(smh);
2115 
2116  for(i = 0; i < SCMF_MAX; i++) {
2117  if (flags[i]) {
2118  smh->media_flags[i] = flags[i];
2119  }
2120  }
2121 
2122 }
2123 
2125 {
2126  switch_assert(smh);
2127 
2128  smh->media_flags[flag] = 0;
2129 }
2130 
2132 {
2133  switch_assert(smh);
2134  return smh->media_flags[flag];
2135 }
2136 
2138 {
2140  switch_media_handle_t *smh;
2141  switch_rtp_engine_t *engine = NULL;
2142 
2143  switch_assert(session);
2144 
2145  if (!(smh = session->media_handle)) {
2146  goto end;
2147  }
2148 
2149  if (!smh->media_flags[SCMF_RUNNING]) {
2150  goto end;
2151  }
2152 
2153  engine = &smh->engines[type];
2154  flow = engine->smode;
2155 
2156  end:
2157 
2158  return flow;
2159 }
2160 
2161 
2163 {
2165  switch_media_handle_t *smh;
2166  switch_rtp_engine_t *engine = NULL;
2167 
2168  switch_assert(session);
2169 
2170  if (!(smh = session->media_handle)) {
2171  goto end;
2172  }
2173 
2174  if (!smh->media_flags[SCMF_RUNNING]) {
2175  goto end;
2176  }
2177 
2178  engine = &smh->engines[type];
2179  flow = engine->rmode;
2180 
2181  end:
2182 
2183  return flow;
2184 }
2185 
2187 {
2188  if (session->media_handle && switch_test_flag(session->media_handle, SMF_INIT)) {
2189  return SWITCH_STATUS_SUCCESS;
2190  }
2191 
2192  return SWITCH_STATUS_FALSE;
2193 }
2194 
2195 
2196 
2198 {
2199  switch_rtp_engine_t *engine = &session->media_handle->engines[type];
2200 
2201  if (!engine) return 0;
2202 
2203  return engine->cur_payload_map->pt;
2204 }
2205 
2207 {
2208  switch_rtp_engine_t *engine = &session->media_handle->engines[type];
2209 
2210  if (!engine) return NULL;
2211 
2212  return engine->rtp_session;
2213 }
2214 
2216 {
2218  return session->media_handle;
2219  }
2220 
2221  return NULL;
2222 }
2223 
2225 {
2226  if (!session->media_handle) {
2227  return SWITCH_STATUS_FALSE;
2228  }
2229 
2230  return SWITCH_STATUS_SUCCESS;
2231 }
2232 
2234 {
2235  switch_assert(smh);
2236  return smh->mparams;
2237 }
2238 
2240 {
2241  const char *abs, *codec_string = NULL;
2242  const char *ocodec = NULL, *val;
2243  switch_media_handle_t *smh;
2244  char *tmp_codec_string;
2245 
2246  switch_assert(session);
2247 
2248  if (!(smh = session->media_handle)) {
2249  return SWITCH_STATUS_FALSE;
2250  }
2251 
2253  return SWITCH_STATUS_FALSE;
2254  }
2255 
2256  if (force) {
2257  smh->mparams->num_codecs = 0;
2258  }
2259 
2260  if (smh->mparams->num_codecs) {
2261  return SWITCH_STATUS_FALSE;
2262  }
2263 
2265 
2266  smh->payload_space = 0;
2267 
2268  switch_assert(smh->session != NULL);
2269 
2270  if ((abs = switch_channel_get_variable(session->channel, "absolute_codec_string"))) {
2271  codec_string = abs;
2272  goto ready;
2273  }
2274 
2275  val = switch_channel_get_variable_dup(session->channel, "media_mix_inbound_outbound_codecs", SWITCH_FALSE, -1);
2276 
2277  if (!switch_channel_test_flag(session->channel, CF_ANSWERED) && (!val || !switch_true(val) || smh->media_flags[SCMF_DISABLE_TRANSCODING]) && ocodec) {
2278  codec_string = ocodec;
2279  goto ready;
2280  }
2281 
2282  if (!(codec_string = switch_channel_get_variable(session->channel, "codec_string"))) {
2283  codec_string = switch_core_media_get_codec_string(smh->session);
2284  }
2285 
2286  if (codec_string && *codec_string == '=') {
2287  codec_string++;
2288  goto ready;
2289  }
2290 
2291  if (ocodec) {
2292  codec_string = switch_core_session_sprintf(smh->session, "%s,%s", ocodec, codec_string);
2293  }
2294 
2295  ready:
2296 
2297  if (!codec_string) {
2298  codec_string = "PCMU@20i,PCMA@20i,speex@20i";
2299  }
2300 
2301  tmp_codec_string = switch_core_session_strdup(smh->session, codec_string);
2302  switch_channel_set_variable(session->channel, "rtp_use_codec_string", codec_string);
2303  smh->codec_order_last = switch_separate_string(tmp_codec_string, ',', smh->codec_order, SWITCH_MAX_CODECS);
2305  return SWITCH_STATUS_SUCCESS;
2306 }
2307 
2308 static void check_jb(switch_core_session_t *session, const char *input, int32_t jb_msec, int32_t maxlen, switch_bool_t silent)
2309 {
2310  const char *val;
2311  switch_media_handle_t *smh;
2312  switch_rtp_engine_t *a_engine = NULL, *v_engine = NULL, *t_engine = NULL;
2313 
2314  switch_assert(session);
2315 
2316  if (!(smh = session->media_handle)) {
2317  return;
2318  }
2319 
2320  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
2321  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
2322  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
2323 
2324 
2325  if (!zstr(input)) {
2326  const char *s;
2327  if (a_engine->rtp_session) {
2328  if (!strcasecmp(input, "pause")) {
2330  return;
2331  } else if (!strcasecmp(input, "resume")) {
2333  return;
2334  } else if (!strcasecmp(input, "stop")) {
2336  return;
2337  } else if (!strncasecmp(input, "debug:", 6)) {
2338  s = input + 6;
2339  if (s && !strcmp(s, "off")) {
2340  s = NULL;
2341  }
2343  return;
2344  }
2345 
2346  switch_channel_set_variable(session->channel, "jitterbuffer_msec", input);
2347  }
2348 
2349  if (v_engine->rtp_session) {
2350  if (!strncasecmp(input, "vbsize:", 7)) {
2351  int frames = 0, max_frames = 0;
2352  s = input + 7;
2353 
2354  frames = atoi(s);
2355 
2356  if ((s = strchr(s, ':')) && *(s+1) != '\0') {
2357  max_frames = atoi(s+1);
2358  }
2359 
2360  if (frames > 0) {
2361  switch_rtp_set_video_buffer_size(v_engine->rtp_session, frames, max_frames);
2362  } else {
2363  switch_rtp_deactivate_jitter_buffer(v_engine->rtp_session);
2364  }
2365  return;
2366  } else if (!strncasecmp(input, "vdebug:", 7)) {
2367  s = input + 7;
2368 
2369  if (s && !strcmp(s, "off")) {
2370  s = NULL;
2371  }
2372  switch_rtp_debug_jitter_buffer(v_engine->rtp_session, s);
2373  return;
2374  }
2375  }
2376 
2377  if (t_engine->rtp_session) {
2378  if (!strncasecmp(input, "tbsize:", 7)) {
2379  int frames = 0, max_frames = 0;
2380  s = input + 7;
2381 
2382  frames = atoi(s);
2383 
2384  if ((s = strchr(s, ':')) && *(s+1) != '\0') {
2385  max_frames = atoi(s+1);
2386  }
2387 
2388  if (frames > 0) {
2389  switch_rtp_set_video_buffer_size(t_engine->rtp_session, frames, max_frames);
2390  }
2391  return;
2392  } else if (!strncasecmp(input, "tdebug:", 7)) {
2393  s = input + 7;
2394 
2395  if (s && !strcmp(s, "off")) {
2396  s = NULL;
2397  }
2398  switch_rtp_debug_jitter_buffer(t_engine->rtp_session, s);
2399  return;
2400  }
2401  }
2402  }
2403 
2404 
2405  if (jb_msec || (val = switch_channel_get_variable(session->channel, "jitterbuffer_msec")) || (val = smh->mparams->jb_msec)) {
2406  char *p;
2407 
2408  if (!jb_msec) {
2409  jb_msec = atoi(val);
2410 
2411  if (strchr(val, 'p') && jb_msec > 0) {
2412  jb_msec *= -1;
2413  if (!maxlen) maxlen = jb_msec * 50;
2414  }
2415 
2416  if ((p = strchr(val, ':'))) {
2417  p++;
2418  maxlen = atoi(p);
2419 
2420  if (strchr(p, 'p') && maxlen > 0) {
2421  maxlen *= -1;
2422  }
2423  }
2424  }
2425 
2426  if (!maxlen) maxlen = jb_msec * 50;
2427 
2428  if (jb_msec < 0 && jb_msec > -1000) {
2429  jb_msec = (a_engine->read_codec.implementation->microseconds_per_packet / 1000) * abs(jb_msec);
2430  }
2431 
2432  if (maxlen < 0 && maxlen > -1000) {
2433  maxlen = (a_engine->read_codec.implementation->microseconds_per_packet / 1000) * abs(maxlen);
2434  }
2435 
2436 
2437  if (jb_msec < 10 || jb_msec > 10000) {
2438  //switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
2439  //"Invalid Jitterbuffer spec [%d] must be between 10 and 10000\n", jb_msec);
2440  jb_msec = (a_engine->read_codec.implementation->microseconds_per_packet / 1000) * 1;
2441  maxlen = jb_msec * 100;
2442  }
2443 
2444  if (jb_msec && maxlen) {
2445  int qlen, maxqlen = 50;
2446 
2447  qlen = jb_msec / (a_engine->read_impl.microseconds_per_packet / 1000);
2448 
2449  if (maxlen) {
2450  maxqlen = maxlen / (a_engine->read_impl.microseconds_per_packet / 1000);
2451  }
2452 
2453  if (maxqlen < qlen) {
2454  maxqlen = qlen * 5;
2455  }
2456  if (switch_rtp_activate_jitter_buffer(a_engine->rtp_session, qlen, maxqlen,
2457  a_engine->read_impl.samples_per_packet,
2459  if (!silent) {
2461  SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames) (%d max frames)\n",
2462  jb_msec, qlen, maxqlen);
2463  }
2465  if (!switch_false(switch_channel_get_variable(session->channel, "rtp_jitter_buffer_plc"))) {
2467  }
2468  } else if (!silent) {
2470  SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", jb_msec, qlen);
2471  }
2472 
2473  }
2474  }
2475 
2476 }
2477 
2479 {
2480  int32_t jb_sync_msec = 0;
2481  uint32_t fps = 0, frames = 0;
2482  uint32_t min_frames = 0;
2483  uint32_t max_frames = 0;
2484  uint32_t cur_frames = 0;
2485  switch_media_handle_t *smh;
2486  switch_rtp_engine_t *v_engine = NULL;
2487  int sync_audio = 0;
2488 
2489  const char *var;
2490 
2491  switch_assert(session);
2492 
2493  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
2494  return;
2495  }
2496 
2497  if (!(smh = session->media_handle)) {
2498  return;
2499  }
2500 
2501  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
2502 
2503  if ((var = switch_channel_get_variable_dup(session->channel, "jb_av_sync_msec", SWITCH_FALSE, -1))) {
2504  int tmp;
2505  char *p;
2506 
2507  if (!strcasecmp(var, "disabled")) {
2508  return;
2509  }
2510 
2511  tmp = atol(var);
2512 
2513  if (tmp && tmp > -50 && tmp < 10000) {
2514  jb_sync_msec = tmp;
2515  }
2516 
2517  if ((p = strchr(var, ':'))) {
2518  p++;
2519  frames = atoi(p);
2520  }
2521  }
2522 
2523  switch_rtp_get_video_buffer_size(v_engine->rtp_session, &min_frames, &max_frames, &cur_frames, NULL);
2524 
2525  fps = video_globals.fps;
2526 
2527  if (fps < 15) return;
2528 
2529  sync_audio = 1;
2530 
2531  if (!frames) {
2532  if (cur_frames && min_frames && cur_frames >= min_frames) {
2533  frames = cur_frames;
2534  } else if (min_frames) {
2535  frames = min_frames;
2536  } else {
2537  frames = 0;
2538  sync_audio = 0;
2539  }
2540  }
2541 
2542  if (!jb_sync_msec && frames) {
2543  jb_sync_msec = ((double)1000 / fps) * frames;
2544  }
2545 
2547  SWITCH_LOG_DEBUG1, "%s %s \"%s\" Sync A/V JB to %dms %u VFrames, FPS %u a:%s sync_ms:%d\n",
2549  switch_channel_get_name(session->channel),
2550  switch_channel_get_variable_dup(session->channel, "caller_id_name", SWITCH_FALSE, -1),
2551  jb_sync_msec, frames, video_globals.fps, sync_audio ? "yes" : "no", jb_sync_msec);
2552 
2553  if (sync_audio) {
2554  check_jb(session, NULL, jb_sync_msec, jb_sync_msec * 2, SWITCH_TRUE);
2555  }
2556 
2557  video_globals.synced++;
2558 }
2559 
2560 
2561 //?
2563 {
2564  switch_rtp_engine_t *engine;
2565  switch_media_handle_t *smh;
2566 
2567  switch_assert(session);
2568 
2569  if (!(smh = session->media_handle)) {
2570  return SWITCH_STATUS_FALSE;
2571  }
2572 
2573  if (!smh->media_flags[SCMF_RUNNING]) {
2574  return SWITCH_STATUS_FALSE;
2575  }
2576 
2577  engine = &smh->engines[type];
2578 
2579  if (!engine->read_codec.implementation || !switch_core_codec_ready(&engine->read_codec)) {
2580  return SWITCH_STATUS_FALSE;
2581  }
2582 
2583  switch_assert(engine->rtp_session != NULL);
2584 
2585 
2587  return SWITCH_STATUS_FALSE;
2588  }
2589 
2590  if (lock) {
2591  if (smh->read_mutex[type] && switch_mutex_trylock(smh->read_mutex[type]) != SWITCH_STATUS_SUCCESS) {
2592  /* return CNG, another thread is already reading */
2593  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s is already being read for %s\n",
2594  switch_channel_get_name(session->channel), type2str(type));
2595  return SWITCH_STATUS_INUSE;
2596  }
2597  } else {
2598  switch_mutex_unlock(smh->read_mutex[type]);
2599  }
2600 
2601  return SWITCH_STATUS_SUCCESS;
2602 }
2603 
2604 
2605 
2606 
2607 //?
2609 {
2610  int x;
2611 
2612  *tfP = switch_core_alloc(pool, sizeof(**tfP));
2613 
2614  switch_buffer_create_dynamic(&(*tfP)->write_buffer, 512, 1024, 0);
2615  (*tfP)->pool = pool;
2616  (*tfP)->text_write_frame_data = switch_core_alloc(pool, SWITCH_RTP_MAX_BUF_LEN);
2617  (*tfP)->text_write_frame.packet = (*tfP)->text_write_frame_data;
2618  (*tfP)->text_write_frame.data = (switch_byte_t *)(*tfP)->text_write_frame.packet + 12;
2619  (*tfP)->text_write_frame.buflen = SWITCH_RTP_MAX_BUF_LEN - 12;
2620 
2621  (*tfP)->red_max = 5;
2622  (*tfP)->red_bufsize = SWITCH_RTP_MAX_BUF_LEN;
2623 
2624  switch_core_timer_init(&(*tfP)->timer, "soft", TEXT_TIMER_MS, TEXT_TIMER_SAMPLES, pool);
2625 
2626  for(x = 0; x < (*tfP)->red_max; x++) {
2627  (*tfP)->red_buf[x] = switch_core_alloc(pool, SWITCH_RTP_MAX_BUF_LEN);
2628  }
2629 
2630  return SWITCH_STATUS_SUCCESS;
2631 }
2632 
2634 {
2635  switch_core_timer_destroy(&(*tfP)->timer);
2636  switch_buffer_destroy(&(*tfP)->write_buffer);
2637 
2638  return SWITCH_STATUS_SUCCESS;;
2639 }
2640 
2641 #include <wchar.h>
2642 
2643 static int get_rtt_red_seq(int want_seq, void *data, switch_size_t datalen, int seq, switch_payload_t *new_payload, void *new_data, uint32_t *new_datalen)
2644 {
2645  unsigned char *buf = data;
2646  int count = 0;
2647  unsigned char *e = (buf + datalen);
2648 
2649  int len[MAX_RED_FRAMES] = { 0 };
2650  int pt[MAX_RED_FRAMES] = { 0 };
2651  int idx = 0, x = 0;
2652 
2653  *new_datalen = datalen;
2654 
2655  *(buf + datalen) = '\0';
2656 
2657  while (*buf & 0x80) {
2658  if (buf + 3 > e) {
2659  *new_datalen = 0;
2660  return 0;
2661  }
2662 
2663  pt[count] = *buf & 0x7F;
2664  len[count] = (ntohs(*(uint16_t *)(buf + 2)) & 0x03ff);
2665  buf += 4;
2666  count++;
2667  }
2668 
2669  buf++;
2670 
2671  idx = count - (seq - want_seq);
2672 
2673  if (idx < 0) {
2674  *new_datalen = 0;
2675  return 0;
2676  }
2677 
2678  if (!len[idx]) {
2679  *new_datalen = len[idx];
2680  return 0;
2681  }
2682 
2683  for(x = 0; x < idx; x++) {
2684  buf += len[x];
2685  }
2686 
2687  *new_datalen = len[idx];
2688  *new_payload = pt[idx];
2689 
2690  memcpy(new_data, buf, len[idx]);
2691 
2692  *(((char *)new_data) + len[idx]) = '\0';
2693 
2694  return 1;
2695 
2696 }
2697 
2698 static void *get_rtt_payload(void *data, switch_size_t datalen, switch_payload_t *new_payload, uint32_t *new_datalen, int *red_level)
2699 {
2700  unsigned char *buf = data;
2701  int bytes = 0, count = 0, pt = 0, len = 0;//, ts = 0;
2702  unsigned char *e = (buf + datalen);
2703 
2704  *new_datalen = datalen;
2705  *red_level = 1;
2706 
2707  while (*buf & 0x80) {
2708  if (buf + 3 > e) {
2709  *new_datalen = 0;
2710  return NULL;
2711  }
2712  count++;
2713  pt = *buf & 0x7F;
2714  //ts = ntohs(*(uint16_t *)(buf + 1)) >> 2;
2715  len = (ntohs(*(uint16_t *)(buf + 2)) & 0x03ff);
2716  buf += 4;
2717  bytes += len;
2718  }
2719 
2720  *new_datalen = datalen - bytes - 1 - (count *4);
2721  *new_payload = pt;
2722  buf += bytes + 1;
2723 
2724  if (buf > e) {
2725  *new_datalen = 0;
2726  return NULL;
2727  }
2728 
2729  return buf;
2730 }
2731 
2732 //?
2733 
2735 {
2736  switch_media_type_t type = engine->type;
2737  const char *val;
2738 
2739  if ((val = switch_channel_get_variable(session->channel, "media_hold_timeout"))) {
2740  engine->media_hold_timeout = atoi(val);
2741  }
2742 
2743  if ((val = switch_channel_get_variable(session->channel, "media_timeout"))) {
2744  engine->media_timeout = atoi(val);
2745  }
2746 
2747  if (type == SWITCH_MEDIA_TYPE_VIDEO) {
2748  if ((val = switch_channel_get_variable(session->channel, "media_hold_timeout_video"))) {
2749  engine->media_hold_timeout = atoi(val);
2750  }
2751 
2752  if ((val = switch_channel_get_variable(session->channel, "media_timeout_video"))) {
2753  engine->media_timeout = atoi(val);
2754  }
2755  } else {
2756 
2757  if ((val = switch_channel_get_variable(session->channel, "media_hold_timeout_audio"))) {
2758  engine->media_hold_timeout = atoi(val);
2759  }
2760 
2761  if ((val = switch_channel_get_variable(session->channel, "media_timeout_audio"))) {
2762  engine->media_timeout = atoi(val);
2763  }
2764  }
2765 
2766  if (switch_rtp_ready(engine->rtp_session) && engine->media_timeout) {
2768  if (engine->type == SWITCH_MEDIA_TYPE_AUDIO) {
2769  /* the values are in milliseconds, not in seconds as the deprecated rtp_timeout_sec */
2770  engine->max_missed_packets = (engine->read_impl.samples_per_second * engine->media_timeout / 1000) / engine->read_impl.samples_per_packet;
2771 
2773  if (!engine->media_hold_timeout) {
2774  engine->media_hold_timeout = engine->media_timeout * 10;
2775  }
2776 
2778  }
2779  }
2780 }
2781 
2783  switch_io_flag_t flags, int stream_id, switch_media_type_t type)
2784 {
2785  switch_rtcp_frame_t rtcp_frame;
2786  switch_rtp_engine_t *engine;
2787  switch_status_t status;
2788  switch_media_handle_t *smh;
2789  int do_cng = 0;
2790 
2791  switch_assert(session);
2792 
2793  if (!(smh = session->media_handle)) {
2794  return SWITCH_STATUS_FALSE;
2795  }
2796 
2797  if (!smh->media_flags[SCMF_RUNNING]) {
2798  return SWITCH_STATUS_FALSE;
2799  }
2800 
2801  engine = &smh->engines[type];
2802 
2803  if (type == SWITCH_MEDIA_TYPE_AUDIO && ! switch_channel_test_flag(session->channel, CF_AUDIO)) {
2804  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s Reading audio from a non-audio session.\n", switch_channel_get_name(session->channel));
2805  switch_yield(50000);
2806  return SWITCH_STATUS_INUSE;
2807  }
2808 
2809  if (type != SWITCH_MEDIA_TYPE_TEXT && (!engine->read_codec.implementation || !switch_core_codec_ready(&engine->read_codec))) {
2810  switch_yield(50000);
2811  return SWITCH_STATUS_FALSE;
2812  }
2813 
2815  switch_yield(50000);
2816  return SWITCH_STATUS_FALSE;
2817  }
2818 
2819  if (smh->read_mutex[type] && switch_mutex_trylock(smh->read_mutex[type]) != SWITCH_STATUS_SUCCESS) {
2820  /* return CNG, another thread is already reading */
2821  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s is already being read for %s\n",
2822  switch_channel_get_name(session->channel), type2str(type));
2823  return SWITCH_STATUS_INUSE;
2824  }
2825 
2826 
2827  engine->read_frame.datalen = 0;
2828  engine->read_frame.flags = SFF_NONE;
2829  engine->read_frame.m = SWITCH_FALSE;
2830  engine->read_frame.img = NULL;
2831  engine->read_frame.payload = 0;
2832 
2833  while (smh->media_flags[SCMF_RUNNING] && engine->read_frame.datalen == 0) {
2834  engine->read_frame.flags = SFF_NONE;
2835  status = switch_rtp_zerocopy_read_frame(engine->rtp_session, &engine->read_frame, flags);
2836 
2837 
2838  if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
2839  if (status == SWITCH_STATUS_TIMEOUT) {
2840 
2841  if (switch_channel_get_variable(session->channel, "execute_on_media_timeout")) {
2842  *frame = &engine->read_frame;
2843  switch_set_flag((*frame), SFF_CNG);
2844  (*frame)->datalen = engine->read_impl.encoded_bytes_per_packet;
2845  memset((*frame)->data, 0, (*frame)->datalen);
2846  switch_channel_execute_on(session->channel, "execute_on_media_timeout");
2848  }
2849 
2850 
2852  }
2853  goto end;
2854  }
2855 
2857  status = SWITCH_STATUS_INUSE;
2858  goto end;
2859  }
2860 
2861  if (status == SWITCH_STATUS_BREAK) {
2862  goto end;
2863  }
2864 
2865  if (type == SWITCH_MEDIA_TYPE_VIDEO) {
2866  if (engine->read_frame.m) {
2867  if (!smh->vid_started) {
2868  smh->vid_started = switch_epoch_time_now(NULL);
2869  }
2870  smh->vid_frames++;
2871 
2872  if ((smh->vid_frames % 5) == 0) {
2874  }
2875 
2876  if (video_globals.fps && (!video_globals.synced || ((smh->vid_frames % 300) == 0))) {
2877  check_jb_sync(session);
2878  }
2879  }
2880  }
2881 
2882  /* re-set codec if necessary */
2883  if (type != SWITCH_MEDIA_TYPE_TEXT && engine->reset_codec > 0) {
2884  const char *val;
2885  int rtp_timeout_sec = 0;
2886  int rtp_hold_timeout_sec = 0;
2887 
2888  engine->reset_codec = 0;
2889 
2890  if (switch_rtp_ready(engine->rtp_session)) {
2891 
2892  check_media_timeout_params(session, engine);
2893 
2894  if (type == SWITCH_MEDIA_TYPE_VIDEO) {
2896  } else {
2897 
2899  *frame = NULL;
2901  }
2902  }
2903 
2904  if (type == SWITCH_MEDIA_TYPE_AUDIO && engine->read_impl.samples_per_second) {
2905  if ((val = switch_channel_get_variable(session->channel, "rtp_timeout_sec"))) {
2906  int v = atoi(val);
2907  if (v >= 0) {
2909  "rtp_timeout_sec deprecated use media_timeout variable.\n");
2910  rtp_timeout_sec = v;
2911  }
2912  }
2913 
2914  if ((val = switch_channel_get_variable(session->channel, "rtp_hold_timeout_sec"))) {
2915  int v = atoi(val);
2916  if (v >= 0) {
2918  "rtp_hold_timeout_sec deprecated use media_timeout variable.\n");
2919  rtp_hold_timeout_sec = v;
2920  }
2921  }
2922 
2923  if (rtp_timeout_sec) {
2924  engine->max_missed_packets = (engine->read_impl.samples_per_second * rtp_timeout_sec) /
2925  engine->read_impl.samples_per_packet;
2926 
2928  if (!rtp_hold_timeout_sec) {
2929  rtp_hold_timeout_sec = rtp_timeout_sec * 10;
2930  }
2931  }
2932 
2933  if (rtp_hold_timeout_sec) {
2934  engine->max_missed_hold_packets = (engine->read_impl.samples_per_second * rtp_hold_timeout_sec) /
2935  engine->read_impl.samples_per_packet;
2936  }
2937  }
2938  }
2939 
2940  check_jb(session, NULL, 0, 0, SWITCH_FALSE);
2941 
2942  engine->check_frames = 0;
2943  engine->last_ts = 0;
2944  engine->last_seq = 0;
2945 
2946  do_cng = 1;
2947  }
2948 
2949 
2950  if (do_cng) {
2951  /* return CNG for now */
2952  *frame = &engine->read_frame;
2953  switch_set_flag((*frame), SFF_CNG);
2954  (*frame)->datalen = engine->read_impl.encoded_bytes_per_packet;
2955  memset((*frame)->data, 0, (*frame)->datalen);
2957  }
2958 
2959 
2960  /* Try to read an RTCP frame, if successful raise an event */
2961  if (switch_rtcp_zerocopy_read_frame(engine->rtp_session, &rtcp_frame) == SWITCH_STATUS_SUCCESS) {
2962  switch_event_t *event;
2963 
2965  char value[30];
2966  char header[50];
2967  int i;
2968 
2969  char *uuid = switch_core_session_get_uuid(session);
2970  if (uuid) {
2972  }
2973 
2974  snprintf(value, sizeof(value), "%.8x", rtcp_frame.ssrc);
2975  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SSRC", value);
2976 
2977  snprintf(value, sizeof(value), "%u", rtcp_frame.ntp_msw);
2978  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Most-Significant-Word", value);
2979 
2980  snprintf(value, sizeof(value), "%u", rtcp_frame.ntp_lsw);
2981  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "NTP-Least-Significant-Word", value);
2982 
2983  snprintf(value, sizeof(value), "%u", rtcp_frame.timestamp);
2984  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Timestamp", value);
2985 
2986  snprintf(value, sizeof(value), "%u", rtcp_frame.packet_count);
2987  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sender-Packet-Count", value);
2988 
2989  snprintf(value, sizeof(value), "%u", rtcp_frame.octect_count);
2990  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Octect-Packet-Count", value);
2991 
2992  snprintf(value, sizeof(value), "%u", engine->read_frame.timestamp);
2993  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Last-RTP-Timestamp", value);
2994 
2995  snprintf(value, sizeof(value), "%u", engine->read_frame.rate);
2996  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTP-Rate", value);
2997 
2998  snprintf(value, sizeof(value), "%" SWITCH_TIME_T_FMT, switch_time_now());
2999  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Capture-Time", value);
3000 
3001  // Add sources info
3002  for (i = 0; i < rtcp_frame.report_count; i++) {
3003  snprintf(header, sizeof(header), "Source%u-SSRC", i);
3004  snprintf(value, sizeof(value), "%.8x", rtcp_frame.reports[i].ssrc);
3005  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
3006  snprintf(header, sizeof(header), "Source%u-Fraction", i);
3007  snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].fraction);
3008  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
3009  snprintf(header, sizeof(header), "Source%u-Lost", i);
3010  snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].lost);
3011  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
3012  snprintf(header, sizeof(header), "Source%u-Loss-Avg", i);
3013  snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].loss_avg);
3014  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
3015  snprintf(header, sizeof(header), "Source%u-Highest-Sequence-Number-Received", i);
3016  snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].highest_sequence_number_received);
3017  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
3018  snprintf(header, sizeof(header), "Source%u-Jitter", i);
3019  snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].jitter);
3020  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
3021  snprintf(header, sizeof(header), "Source%u-LSR", i);
3022  snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].lsr);
3023  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
3024  snprintf(header, sizeof(header), "Source%u-DLSR", i);
3025  snprintf(value, sizeof(value), "%u", rtcp_frame.reports[i].dlsr);
3026  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
3027  snprintf(header, sizeof(header), "Rtt%u-Avg", i);
3028  snprintf(value, sizeof(value), "%f", rtcp_frame.reports[i].rtt_avg);
3029  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, header, value);
3030  }
3031 
3032  switch_event_fire(&event);
3033  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "Dispatched RTCP event\n");
3034  }
3035  }
3036 
3037  /* Fast PASS! */
3038  if (switch_test_flag((&engine->read_frame), SFF_PROXY_PACKET)) {
3039  *frame = &engine->read_frame;
3041  }
3042 
3043  if (switch_rtp_has_dtmf(engine->rtp_session)) {
3044  switch_dtmf_t dtmf = { 0 };
3045  switch_rtp_dequeue_dtmf(engine->rtp_session, &dtmf);
3046  switch_channel_queue_dtmf(session->channel, &dtmf);
3047  }
3048 
3049  if (type != SWITCH_MEDIA_TYPE_TEXT && engine->read_frame.datalen > 0) {
3050  uint32_t bytes = 0;
3051  int frames = 1;
3052 
3053  /* autofix timing */
3054  if (!switch_test_flag((&engine->read_frame), SFF_CNG)) {
3055  if (!engine->read_codec.implementation || !switch_core_codec_ready(&engine->read_codec)) {
3056  *frame = NULL;
3058  }
3059 
3060  /* check for timing issues */
3062  char is_vbr;
3063  is_vbr = engine->read_impl.encoded_bytes_per_packet?0:1;
3064 
3065  engine->check_frames++;
3066  /* CBR */
3067  if ((smh->media_flags[SCMF_AUTOFIX_TIMING] && (engine->read_frame.datalen % 10) == 0)
3068  && (engine->check_frames < MAX_CODEC_CHECK_FRAMES) && !is_vbr) {
3069  engine->check_frames++;
3070 
3071  if (engine->last_ts && engine->read_frame.datalen != engine->read_impl.encoded_bytes_per_packet) {
3072 
3073  uint32_t codec_ms = (int) (engine->read_frame.timestamp -
3074  engine->last_ts) / (engine->read_impl.samples_per_second / 1000);
3075  if (engine->last_seq && (int) (engine->read_frame.seq - engine->last_seq) > 1) {
3076  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "[CBR]: 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));
3077  codec_ms = codec_ms / (int) (engine->read_frame.seq - engine->last_seq);
3078  }
3079 
3080  if ((codec_ms % 10) != 0 || codec_ms > engine->read_impl.samples_per_packet * 10) {
3081  engine->last_ts = 0;
3082  engine->last_seq = 0;
3083  goto skip;
3084  }
3085 
3086  if (engine->last_codec_ms && engine->last_codec_ms == codec_ms) {
3087  engine->mismatch_count++;
3088  } else {
3089  engine->mismatch_count = 0;
3090  }
3091 
3092  engine->last_codec_ms = codec_ms;
3093 
3094  if (engine->mismatch_count > MAX_MISMATCH_FRAMES) {
3095  if (codec_ms != engine->cur_payload_map->codec_ms) {
3096 
3097  if (codec_ms > 120) { /* yeah right */
3099  "[CBR]: Your phone is trying to send timestamps that suggest an increment of %dms per packet\n"
3100  "That seems hard to believe so I am going to go on ahead and um ignore that, mmkay?\n",
3101  (int) codec_ms);
3103  goto skip;
3104  }
3105 
3106  engine->read_frame.datalen = 0;
3107 
3108  if (codec_ms != engine->cur_payload_map->codec_ms) {
3110  "[CBR]: Asynchronous PTIME not supported, changing our end from %d to %d\n",
3111  (int) engine->cur_payload_map->codec_ms,
3112  (int) codec_ms
3113  );
3114 
3115  switch_channel_set_variable_printf(session->channel, "rtp_h_X-Broken-PTIME", "Adv=%d;Sent=%d",
3116  (int) engine->cur_payload_map->codec_ms, (int) codec_ms);
3117 
3118  engine->cur_payload_map->codec_ms = codec_ms;
3119 
3120  /* mark to re-set codec */
3121  engine->reset_codec = 2;
3122  }
3123  }
3124  }
3125 
3126  } else {
3127  engine->mismatch_count = 0;
3128  }
3129 
3130  engine->last_ts = engine->read_frame.timestamp;
3131  engine->last_seq = engine->read_frame.seq;
3132 
3133  } else if (smh->media_flags[SCMF_AUTOFIX_TIMING] && is_vbr && switch_rtp_get_jitter_buffer(engine->rtp_session)
3134  && type == SWITCH_MEDIA_TYPE_AUDIO
3135  && engine->read_frame.timestamp && engine->read_frame.seq && engine->read_impl.samples_per_second) {
3136  uint32_t codec_ms = (int) (engine->read_frame.timestamp -
3137  engine->last_ts) / (engine->read_impl.samples_per_second / 1000);
3138 
3139  if (engine->last_seq && (int) (engine->read_frame.seq - engine->last_seq) > 1) {
3140  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "[VBR]: 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));
3141  codec_ms = codec_ms / (int) (engine->read_frame.seq - engine->last_seq);
3142  }
3143 
3144  if (codec_ms && codec_ms != engine->cur_payload_map->codec_ms) {
3145  if (engine->last_codec_ms && engine->last_codec_ms == codec_ms) {
3146  engine->mismatch_count++;
3147  }
3148  } else {
3149  engine->mismatch_count = 0;
3150  }
3151 
3152  engine->last_codec_ms = codec_ms;
3153 
3154  if (engine->mismatch_count > MAX_MISMATCH_FRAMES) {
3155 
3156  if (codec_ms > 120) {
3157  /*will show too many times with packet loss*/
3159  "[VBR]: Remote party is trying to send timestamps that suggest an increment of [%d] ms per packet, which is too high. Ignoring.\n",
3160  (int) codec_ms);
3161  engine->last_ts = engine->read_frame.timestamp;
3162  engine->last_seq = engine->read_frame.seq;
3163  goto skip;
3164  }
3165 
3166  if (codec_ms != engine->cur_payload_map->codec_ms) {
3168  "[VBR]: Packet size change detected. Remote PTIME changed from [%d] to [%d]\n",
3169  (int) engine->cur_payload_map->codec_ms,
3170  (int) codec_ms
3171  );
3172  engine->cur_payload_map->codec_ms = codec_ms;
3173  engine->reset_codec = 2;
3174 
3177  }
3178  }
3179  }
3180 
3181  engine->last_ts = engine->read_frame.timestamp;
3182  engine->last_seq = engine->read_frame.seq;
3183 
3184  } else {
3185  engine->mismatch_count = 0;
3186  engine->last_ts = 0;
3187  engine->last_seq = 0;
3188  }
3189  }
3190 
3191  /* autofix payload type */
3192 
3193  if (!engine->reset_codec &&
3194  engine->codec_negotiated &&
3195  (!smh->mparams->cng_pt || engine->read_frame.payload != smh->mparams->cng_pt) &&
3196  (!smh->mparams->recv_te || engine->read_frame.payload != smh->mparams->recv_te) &&
3197  (!smh->mparams->te || engine->read_frame.payload != smh->mparams->te) &&
3198  !switch_test_flag((&engine->read_frame), SFF_CNG) &&
3199  !switch_test_flag((&engine->read_frame), SFF_PLC) &&
3200  engine->read_frame.payload != engine->cur_payload_map->recv_pt &&
3201  engine->read_frame.payload != engine->cur_payload_map->pt) {
3202 
3203  payload_map_t *pmap;
3204 
3205 
3207  "alternate payload received (received %d, expecting %d)\n",
3208  (int) engine->read_frame.payload, (int) engine->cur_payload_map->pt);
3209 
3210 
3211  /* search for payload type */
3213  for (pmap = engine->payload_map; pmap; pmap = pmap->next) {
3214  if (engine->read_frame.payload == pmap->recv_pt && pmap->negotiated) {
3215  engine->cur_payload_map = pmap;
3216  engine->cur_payload_map->current = 1;
3218  "Changing current codec to %s (payload type %d).\n",
3219  pmap->iananame, pmap->pt);
3220 
3221  /* mark to re-set codec */
3222  engine->reset_codec = 1;
3223  break;
3224  }
3225  }
3227 
3228  if (!engine->reset_codec) {
3230  "Could not change to payload type %d, ignoring...\n",
3231  (int) engine->read_frame.payload);
3232  }
3233  }
3234 
3235  skip:
3236 
3237  if ((bytes = engine->read_impl.encoded_bytes_per_packet)) {
3238  frames = (engine->read_frame.datalen / bytes);
3239  }
3240  engine->read_frame.samples = (int) (frames * engine->read_impl.samples_per_packet);
3241 
3242  if (engine->read_frame.datalen == 0) {
3243  continue;
3244  }
3245  }
3246  break;
3247  }
3248  }
3249 
3250  if (engine->read_frame.datalen == 0) {
3251  *frame = NULL;
3252  }
3253 
3254 
3255  if (type == SWITCH_MEDIA_TYPE_TEXT && !switch_test_flag((&engine->read_frame), SFF_CNG)) {
3256  if (engine->red_pt) {
3257  unsigned char *p = engine->read_frame.data;
3258 
3259  *(p + engine->read_frame.datalen) = '\0';
3260  engine->tf->text_frame = engine->read_frame;
3261 
3262  if (switch_test_flag((&engine->read_frame), SFF_PLC)) {
3264  int i = 0;
3265 
3266  engine->tf->text_frame.datalen = 0;
3267 
3268  for (i = 1; i < 3; i++) {
3269  switch_frame_t frame = { 0 };
3270  uint8_t buf[SWITCH_RTP_MAX_BUF_LEN];
3271  frame.data = buf;
3272  frame.buflen = sizeof(buf);
3273 
3274  if (switch_jb_peek_frame(jb, 0, engine->read_frame.seq, i, &frame) == SWITCH_STATUS_SUCCESS) {
3275  if (get_rtt_red_seq(engine->read_frame.seq,
3276  frame.data,
3277  frame.datalen,
3278  frame.seq,
3279  &engine->tf->text_frame.payload,
3280  engine->tf->text_frame.data,
3281  &engine->tf->text_frame.datalen)) {
3282  break;
3283 
3284  }
3285  }
3286 
3287  }
3288 
3289  if (engine->tf->text_frame.datalen == 0) {
3290  engine->tf->text_frame.data = "� ";
3291  engine->tf->text_frame.datalen = strlen(engine->tf->text_frame.data);
3292  }
3293 
3294  } else {
3295  if (!(engine->tf->text_frame.data = get_rtt_payload(engine->read_frame.data,
3296  engine->tf->text_frame.datalen,
3297  &engine->tf->text_frame.payload,
3298  &engine->tf->text_frame.datalen,
3299  &engine->tf->red_level))) {
3300  engine->tf->text_frame.datalen = 0;
3301  }
3302  }
3303 
3304  *frame = &engine->tf->text_frame;
3305 
3306  if ((*frame)->datalen == 0) {
3307  (*frame)->flags |= SFF_CNG;
3308  (*frame)->data = "";
3309  }
3310  }
3311 
3312  } else {
3313  *frame = &engine->read_frame;
3314  }
3315 
3316  status = SWITCH_STATUS_SUCCESS;
3317 
3318  end:
3319 
3320  if (smh->read_mutex[type]) {
3321  switch_mutex_unlock(smh->read_mutex[type]);
3322  }
3323 
3324  return status;
3325 }
3326 
3327 //?
3329  switch_frame_t *frame, switch_io_flag_t flags, int stream_id, switch_media_type_t type)
3330 {
3332  int bytes = 0, samples = 0, frames = 0;
3333  switch_rtp_engine_t *engine;
3334  switch_media_handle_t *smh;
3335 
3336  switch_assert(session);
3337 
3338  if (!(smh = session->media_handle)) {
3339  return SWITCH_STATUS_FALSE;
3340  }
3341 
3342  if (!smh->media_flags[SCMF_RUNNING]) {
3343  return SWITCH_STATUS_FALSE;
3344  }
3345 
3346  engine = &smh->engines[type];
3347 
3348  if (type == SWITCH_MEDIA_TYPE_VIDEO) {
3349  if (engine->thread_write_lock && engine->thread_write_lock != switch_thread_self()) {
3350  return SWITCH_STATUS_SUCCESS;
3351  }
3352  }
3353 
3354  if (type == SWITCH_MEDIA_TYPE_AUDIO) {
3356 
3357  if (audio_flow != SWITCH_MEDIA_FLOW_SENDRECV && audio_flow != SWITCH_MEDIA_FLOW_SENDONLY) {
3358  return SWITCH_STATUS_SUCCESS;
3359  }
3360  }
3361 
3362  if (type != SWITCH_MEDIA_TYPE_TEXT) {
3363 
3364  while (!(engine->read_codec.implementation && switch_rtp_ready(engine->rtp_session))) {
3365  if (switch_channel_ready(session->channel)) {
3366  switch_yield(10000);
3367  } else {
3368  return SWITCH_STATUS_GENERR;
3369  }
3370  }
3371 
3372  if (!engine->read_codec.implementation || !switch_core_codec_ready(&engine->read_codec)) {
3373  return SWITCH_STATUS_GENERR;
3374  }
3375 
3376  if (!switch_test_flag(frame, SFF_CNG) && !switch_test_flag(frame, SFF_PROXY_PACKET)) {
3377  if (engine->read_impl.encoded_bytes_per_packet) {
3378  bytes = engine->read_impl.encoded_bytes_per_packet;
3379  frames = ((int) frame->datalen / bytes);
3380  } else
3381  frames = 1;
3382 
3383  samples = frames * engine->read_impl.samples_per_packet;
3384  }
3385  }
3386 
3387  engine->timestamp_send += samples;
3388 
3389  if (switch_rtp_write_frame(engine->rtp_session, frame) < 0) {
3390  status = SWITCH_STATUS_FALSE;
3391  }
3392 
3393 
3394  return status;
3395 }
3396 
3397 
3398 //?
3400 {
3402  switch_t38_options_t *local_t38_options = switch_channel_get_private(channel, "t38_options");
3403 
3404  switch_assert(t38_options);
3405 
3406  if (!local_t38_options) {
3407  local_t38_options = switch_core_session_alloc(session, sizeof(switch_t38_options_t));
3408  }
3409 
3410  local_t38_options->T38MaxBitRate = t38_options->T38MaxBitRate;
3411  local_t38_options->T38FaxFillBitRemoval = t38_options->T38FaxFillBitRemoval;
3412  local_t38_options->T38FaxTranscodingMMR = t38_options->T38FaxTranscodingMMR;
3413  local_t38_options->T38FaxTranscodingJBIG = t38_options->T38FaxTranscodingJBIG;
3414  local_t38_options->T38FaxRateManagement = switch_core_session_strdup(session, t38_options->T38FaxRateManagement);
3415  local_t38_options->T38FaxMaxBuffer = t38_options->T38FaxMaxBuffer;
3416  local_t38_options->T38FaxMaxDatagram = t38_options->T38FaxMaxDatagram;
3417  local_t38_options->T38FaxUdpEC = switch_core_session_strdup(session, t38_options->T38FaxUdpEC);
3418  local_t38_options->T38VendorInfo = switch_core_session_strdup(session, t38_options->T38VendorInfo);
3419  local_t38_options->remote_ip = switch_core_session_strdup(session, t38_options->remote_ip);
3420  local_t38_options->remote_port = t38_options->remote_port;
3421 
3422 
3423  switch_channel_set_private(channel, "t38_options", local_t38_options);
3424 
3425 }
3426 
3427 //?
3429 {
3430  int i = 0;
3431  switch_media_handle_t *smh;
3432 
3433  switch_assert(session);
3434 
3435  if (!(smh = session->media_handle) || !mimp) {
3436  return SWITCH_STATUS_FALSE;
3437  }
3438 
3439 
3440  for (i = 0; i < smh->mparams->num_codecs; i++) {
3441  const switch_codec_implementation_t *imp = smh->codecs[i];
3442 
3443  if (!strcasecmp(imp->iananame, mimp->iananame) && imp->actual_samples_per_second == mimp->actual_samples_per_second) {
3444  *pt = smh->ianacodes[i];
3445 
3446  return SWITCH_STATUS_SUCCESS;
3447  }
3448  }
3449 
3450  return SWITCH_STATUS_FALSE;
3451 }
3452 
3453 //#define get_int_value(_var, _set) { const char *__v = switch_channel_get_variable(session->channel, _var); if (__v) { _set = atol(__v);} }
3454 //?
3456 {
3457  switch_media_handle_t *smh;
3458  switch_rtp_engine_t *engine;
3459 
3460  switch_assert(session);
3461 
3462  if (!(smh = session->media_handle)) {
3463  return;
3464  }
3465 
3466  if (!(engine = &smh->engines[type])) return;
3467 
3468  switch(type) {
3470  break;
3471  case SWITCH_MEDIA_TYPE_VIDEO: {
3472  uint32_t system_bw = 0;
3473  const char *var = NULL, *bwv;
3474 
3475  if ((var = switch_channel_get_variable(session->channel, "video_try_hardware_encoder"))) {
3477  }
3478 
3479  if (!(bwv = switch_channel_get_variable(session->channel, "rtp_video_max_bandwidth"))) {
3480  bwv = switch_channel_get_variable(session->channel, "rtp_video_max_bandwidth_out");
3481  }
3482 
3483  if (!bwv) {
3484  bwv = "1mb";
3485  }
3486 
3487  system_bw = switch_parse_bandwidth_string(bwv);
3488 
3489  if (engine->sdp_bw && engine->sdp_bw <= system_bw) {
3490  engine->codec_settings.video.bandwidth = engine->sdp_bw;
3491  } else {
3492  engine->codec_settings.video.bandwidth = system_bw;
3493  }
3494  }
3495  break;
3496  default:
3497  break;
3498  }
3499 }
3500 
3501 //?
3503 {
3505  switch_media_handle_t *smh;
3506  switch_rtp_engine_t *v_engine;
3507 
3508  switch_assert(session);
3509 
3511 
3512  if (!(smh = session->media_handle)) {
3514  }
3515  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
3516 
3517 
3518  if (!v_engine->codec_negotiated) {
3520  }
3521 
3522  if (v_engine->read_codec.implementation && switch_core_codec_ready(&v_engine->read_codec)) {
3523  if (!force) {
3525  }
3526  if (strcasecmp(v_engine->read_codec.implementation->iananame, v_engine->cur_payload_map->rm_encoding) ||
3528 
3529  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Changing Codec from %s to %s\n",
3533  } else {
3534  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Already using %s\n",
3535  v_engine->read_codec.implementation->iananame);
3537  }
3538  }
3539 
3541 
3542  if (switch_core_codec_init(&v_engine->read_codec,
3543  v_engine->cur_payload_map->rm_encoding,
3544  v_engine->cur_payload_map->modname,
3545  v_engine->cur_payload_map->rm_fmtp,
3546  v_engine->cur_payload_map->rm_rate,
3547  0,
3548  1,
3551  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
3553  } else {
3554  if (switch_core_codec_init(&v_engine->write_codec,
3555  v_engine->cur_payload_map->rm_encoding,
3556  v_engine->cur_payload_map->modname,
3557  v_engine->cur_payload_map->rm_fmtp,
3558  v_engine->cur_payload_map->rm_rate,
3559  0,
3560  1,
3563  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
3565  } else {
3566  v_engine->read_frame.rate = v_engine->cur_payload_map->rm_rate;
3567  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set VIDEO Codec %s %s/%ld %d ms\n",
3569  v_engine->cur_payload_map->rm_rate, v_engine->cur_payload_map->codec_ms);
3570  v_engine->read_frame.codec = &v_engine->read_codec;
3571 
3572  v_engine->write_codec.fmtp_out = switch_core_session_strdup(session, v_engine->write_codec.fmtp_out);
3573 
3574  v_engine->write_codec.agreed_pt = v_engine->cur_payload_map->pt;
3575  v_engine->read_codec.agreed_pt = v_engine->cur_payload_map->pt;
3578 
3579 
3580  switch_channel_set_variable_printf(session->channel, "rtp_last_video_codec_string", "%s@%dh",
3581  v_engine->cur_payload_map->rm_encoding, v_engine->cur_payload_map->rm_rate);
3582 
3583 
3584  if (switch_rtp_ready(v_engine->rtp_session)) {
3585  switch_core_session_message_t msg = { 0 };
3586 
3587  msg.from = __FILE__;
3589 
3591 
3592  //XX
3593 
3594  switch_core_session_receive_message(session, &msg);
3595 
3596 
3597  }
3598 
3599  switch_channel_set_variable(session->channel, "rtp_use_video_codec_name", v_engine->cur_payload_map->rm_encoding);
3600  switch_channel_set_variable(session->channel, "rtp_use_video_codec_fmtp", v_engine->cur_payload_map->rm_fmtp);
3601  switch_channel_set_variable_printf(session->channel, "rtp_use_video_codec_rate", "%d", v_engine->cur_payload_map->rm_rate);
3602  switch_channel_set_variable_printf(session->channel, "rtp_use_video_codec_ptime", "%d", 0);
3603  }
3604  }
3605 
3606 end:
3608 
3609  return status;
3610 }
3611 
3612 
3613 //?
3615 {
3617  int resetting = 0;
3618  switch_media_handle_t *smh;
3619  switch_rtp_engine_t *a_engine;
3620 
3621  switch_assert(session);
3622 
3623  switch_core_codec_lock_full(session);
3624 
3626 
3627  if (!(smh = session->media_handle)) {
3629  }
3630  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
3631 
3632  if (!a_engine->cur_payload_map->iananame) {
3633  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No audio codec available\n");
3635  }
3636 
3637  if (switch_core_codec_ready(&a_engine->read_codec)) {
3638  if (!force) {
3640  }
3641 
3642  if (strcasecmp(a_engine->read_impl.iananame, a_engine->cur_payload_map->iananame) ||
3643  (uint32_t) a_engine->read_impl.microseconds_per_packet / 1000 != a_engine->cur_payload_map->codec_ms ||
3644  a_engine->read_impl.samples_per_second != a_engine->cur_payload_map->rm_rate ) {
3645 
3646  switch_core_session_reset(session, 0, 0);
3647 
3649 
3651  "Changing Codec from %s@%dms@%dhz to %s@%dms@%luhz\n",
3652  a_engine->read_impl.iananame,
3653  a_engine->read_impl.microseconds_per_packet / 1000,
3655 
3656  a_engine->cur_payload_map->iananame,
3657  a_engine->cur_payload_map->codec_ms,
3658  a_engine->cur_payload_map->rm_rate);
3659 
3660  resetting = 1;
3665  } else {
3666  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Already using %s\n", a_engine->read_impl.iananame);
3668  }
3669  }
3670 
3671 
3673 
3675  a_engine->cur_payload_map->iananame,
3676  a_engine->cur_payload_map->modname,
3677  a_engine->cur_payload_map->rm_fmtp,
3678  a_engine->cur_payload_map->rm_rate,
3679  a_engine->cur_payload_map->codec_ms,
3680  a_engine->cur_payload_map->channels,
3681  a_engine->cur_payload_map->bitrate,
3684  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
3687  }
3688 
3689  a_engine->read_codec.session = session;
3690 
3691 
3693  a_engine->cur_payload_map->iananame,
3694  a_engine->cur_payload_map->modname,
3695  a_engine->cur_payload_map->rm_fmtp,
3696  a_engine->cur_payload_map->rm_rate,
3697  a_engine->cur_payload_map->codec_ms,
3698  a_engine->cur_payload_map->channels,
3699  a_engine->cur_payload_map->bitrate,
3702  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
3705  }
3706 
3707  a_engine->write_codec.session = session;
3708 
3709  if (switch_rtp_ready(a_engine->rtp_session)) {
3711  switch_rtp_reset_jb(a_engine->rtp_session);
3712  }
3713 
3714  switch_channel_set_variable(session->channel, "rtp_use_codec_name", a_engine->cur_payload_map->iananame);
3715  switch_channel_set_variable(session->channel, "rtp_use_codec_fmtp", a_engine->cur_payload_map->rm_fmtp);
3716  switch_channel_set_variable_printf(session->channel, "rtp_use_codec_rate", "%d", a_engine->cur_payload_map->rm_rate);
3717  switch_channel_set_variable_printf(session->channel, "rtp_use_codec_ptime", "%d", a_engine->cur_payload_map->codec_ms);
3718  switch_channel_set_variable_printf(session->channel, "rtp_use_codec_channels", "%d", a_engine->cur_payload_map->channels);
3719  switch_channel_set_variable_printf(session->channel, "rtp_last_audio_codec_string", "%s@%dh@%di@%dc",
3720  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);
3721 
3724 
3725  a_engine->read_impl = *a_engine->read_codec.implementation;
3726  a_engine->write_impl = *a_engine->write_codec.implementation;
3727 
3730 
3731  if (switch_rtp_ready(a_engine->rtp_session)) {
3733 
3739  }
3740  }
3741 
3742  a_engine->read_frame.rate = a_engine->cur_payload_map->rm_rate;
3743 
3744  if (!switch_core_codec_ready(&a_engine->read_codec)) {
3745  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
3747  }
3748 
3749  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",
3751  a_engine->cur_payload_map->codec_ms,
3753  a_engine->read_frame.codec = &a_engine->read_codec;
3754  a_engine->read_frame.channels = a_engine->read_impl.number_of_channels;
3755  a_engine->write_codec.agreed_pt = a_engine->cur_payload_map->pt;
3756  a_engine->read_codec.agreed_pt = a_engine->cur_payload_map->pt;
3757 
3758  if (force != 2) {
3760  switch_core_session_set_write_codec(session, &a_engine->write_codec);
3761  }
3762 
3763  a_engine->cur_payload_map->fmtp_out = switch_core_session_strdup(session, a_engine->write_codec.fmtp_out);
3764 
3765  if (switch_rtp_ready(a_engine->rtp_session)) {
3767  }
3768 
3769  end:
3770 
3771  if (resetting) {
3772  switch_channel_execute_on(session->channel, "execute_on_audio_change");
3773  }
3774 
3776 
3778 
3779  return status;
3780 }
3782 {
3783  switch_media_handle_t *smh;
3784  switch_rtp_engine_t *engine;
3785 
3786  switch_assert(session);
3787 
3788  if (!(smh = session->media_handle)) {
3789  return;
3790  }
3791 
3792  engine = &smh->engines[type];
3793 
3794  engine->ice_in.chosen[0] = 0;
3795  engine->ice_in.chosen[1] = 0;
3796  engine->ice_in.is_chosen[0] = 0;
3797  engine->ice_in.is_chosen[1] = 0;
3798  engine->ice_in.cand_idx[0] = 0;
3799  engine->ice_in.cand_idx[1] = 0;
3800  memset(&engine->ice_in, 0, sizeof(engine->ice_in));
3801  engine->remote_rtcp_port = 0;
3802 
3803  if (engine->rtp_session) {
3804  switch_rtp_reset(engine->rtp_session);
3805  }
3806 
3807 }
3808 
3809 //?
3811 {
3814 
3815 }
3816 
3818 {
3819  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
3820  switch_media_handle_t *smh;
3821 
3822  switch_assert(session);
3823 
3824  if (!(smh = session->media_handle)) {
3825  return;
3826  }
3827 
3828  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
3829  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
3830  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
3831 
3832  if (a_engine->rtp_session) {
3834  }
3835 
3836  if (v_engine->rtp_session) {
3838  }
3839 
3840  if (t_engine->rtp_session) {
3842  }
3843 }
3844 
3846 {
3847  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
3848  switch_media_handle_t *smh;
3849 
3850  switch_assert(session);
3851 
3852  if (!(smh = session->media_handle)) {
3853  return;
3854  }
3855 
3856  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
3857  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
3858  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
3859 
3860  if (a_engine->rtp_session) {
3862  }
3863 
3864  if (v_engine->rtp_session) {
3866  }
3867 
3868  if (t_engine->rtp_session) {
3870  }
3871 }
3872 
3873 
3874 //?
3876 {
3877  switch_media_handle_t *smh;
3878  switch_rtp_engine_t *engine;
3879 
3880  switch_assert(session);
3881 
3882  if (!(smh = session->media_handle)) {
3883  return SWITCH_STATUS_FALSE;
3884  }
3885 
3886  engine = &smh->engines[type];
3887 
3888  if (engine->cand_acl_count < SWITCH_MAX_CAND_ACL) {
3889  engine->cand_acl[engine->cand_acl_count++] = switch_core_session_strdup(session, acl_name);
3890  return SWITCH_STATUS_SUCCESS;
3891  }
3892 
3893  return SWITCH_STATUS_FALSE;
3894 }
3895 
3896 //?
3898 {
3899  switch_media_handle_t *smh;
3900 
3901  switch_assert(session);
3902 
3903  if (!(smh = session->media_handle)) {
3904  return;
3905  }
3906 
3908  int i;
3909  smh->video_count = 0;
3910  for (i = 0; i < smh->mparams->num_codecs; i++) {
3911 
3912  if (smh->codecs[i]->codec_type == SWITCH_CODEC_TYPE_VIDEO) {
3915  continue;
3916  }
3917  smh->video_count++;
3918  }
3919  }
3920  if (smh->video_count) {
3922  }
3923  }
3924 }
3925 
3926 //?
3928 {
3929  switch_rtp_engine_t *engine = &smh->engines[type];
3930 
3931  if (!engine->local_dtls_fingerprint.len) {
3932  if (engine->remote_dtls_fingerprint.type) {
3934  } else {
3935  engine->local_dtls_fingerprint.type = "sha-256";
3936  }
3938  }
3939 }
3940 
3941 //?
3942 static int dtls_ok(switch_core_session_t *session)
3943 {
3944  return switch_channel_test_flag(session->channel, CF_DTLS_OK);
3945 }
3946 
3947 #ifdef _MSC_VER
3948 /* remove this if the break is removed from the following for loop which causes unreachable code loop */
3949 /* for (i = 0; i < engine->cand_acl_count; i++) { */
3950 #pragma warning(push)
3951 #pragma warning(disable:4702)
3952 #endif
3953 
3954 //?
3956 {
3958  switch_media_handle_t *smh;
3959 
3960  switch_assert(session);
3961 
3962  if (!(smh = session->media_handle)) {
3964  }
3965 
3966  if (switch_channel_test_flag(session->channel, CF_3PCC)) {
3968  }
3969 
3970  if (switch_rtp_has_dtls() && dtls_ok(smh->session)) {
3972  } else {
3974  && switch_channel_test_flag(session->channel, CF_AVPF)) {
3976  }
3977  }
3978 
3979  return r;
3980 }
3981 
3984 
3985  if (switch_channel_var_true(session->channel, "ice_lite")) {
3986  ice_type |= ICE_CONTROLLED;
3987  ice_type |= ICE_LITE;
3988  } else {
3989  switch_call_direction_t direction = switch_ice_direction(engine, session);
3990  if (direction == SWITCH_CALL_DIRECTION_INBOUND) {
3991  ice_type |= ICE_CONTROLLED;
3992  }
3993  }
3994 
3995  return ice_type;
3996 }
3997 
3998 //?
4000 {
4002 
4003  if (zstr(ip)) {
4004  return status;
4005  }
4006 
4007  if (strchr(ip, ':')) {
4008  if (!zstr(smh->mparams->rtpip6)) {
4009  smh->mparams->rtpip = smh->mparams->rtpip6;
4010  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s choosing family v6\n",
4012  status = SWITCH_STATUS_SUCCESS;
4013  }
4014  } else {
4015  if (!zstr(smh->mparams->rtpip4)) {
4016  smh->mparams->rtpip = smh->mparams->rtpip4;
4017  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s choosing family v4\n",
4019  status = SWITCH_STATUS_SUCCESS;
4020  }
4021  }
4022 
4023  return status;
4024 }
4025 
4026 //?
4028 {
4030 
4031  if (zstr(ip)) {
4032  return r;
4033  }
4034 
4035  if (strchr(ip, ':')) {
4036  r = (switch_bool_t) !zstr(smh->mparams->rtpip6);
4037  } else {
4038  r = (switch_bool_t) !zstr(smh->mparams->rtpip4);
4039  }
4040 
4041  return r;
4042 }
4043 
4044 //?
4045 static switch_status_t check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_session_t *sdp, sdp_media_t *m)
4046 {
4047  switch_rtp_engine_t *engine = &smh->engines[type];
4048  sdp_attribute_t *attr = NULL, *attrs[2] = { 0 };
4049  int i = 0, got_rtcp_mux = 0;
4050  const char *val;
4051  int ice_seen = 0, cid = 0, ai = 0, attr_idx = 0, cand_seen = 0, relay_ok = 0;
4052  char con_addr[256];
4053  int ice_resolve = 0;
4054  ip_t ip;
4055 
4056  if (switch_true(switch_channel_get_variable_dup(smh->session->channel, "ignore_sdp_ice", SWITCH_FALSE, -1))) {
4057  return SWITCH_STATUS_BREAK;
4058  }
4059 
4060  //if (engine->ice_in.is_chosen[0] && engine->ice_in.is_chosen[1]) {
4061  //return SWITCH_STATUS_SUCCESS;
4062  //}
4063 
4064  engine->ice_in.chosen[0] = 0;
4065  engine->ice_in.chosen[1] = 0;
4066  engine->ice_in.is_chosen[0] = 0;
4067  engine->ice_in.is_chosen[1] = 0;
4068  engine->ice_in.cand_idx[0] = 0;
4069  engine->ice_in.cand_idx[1] = 0;
4070  engine->remote_ssrc = 0;
4071 
4072  if (m) {
4073  attrs[0] = m->m_attributes;
4074  attrs[1] = sdp->sdp_attributes;
4075  } else {
4076  attrs[0] = sdp->sdp_attributes;
4077  }
4078 
4079  ice_resolve = switch_core_media_has_resolveice();
4080 
4081  for (attr_idx = 0; attr_idx < 2 && !(ice_seen && cand_seen); attr_idx++) {
4082  for (attr = attrs[attr_idx]; attr; attr = attr->a_next) {
4083  char *data;
4084  char *fields[32] = {0};
4085  int argc = 0, j = 0;
4086 
4087  if (zstr(attr->a_name)) {
4088  continue;
4089  }
4090 
4091  if (!strcasecmp(attr->a_name, "ice-ufrag")) {
4092  if (engine->ice_in.ufrag && !strcmp(engine->ice_in.ufrag, attr->a_value)) {
4093  engine->new_ice = 0;
4094  } else {
4095  engine->ice_in.ufrag = switch_core_session_strdup(smh->session, attr->a_value);
4096  engine->new_ice = 1;
4097  }
4098  ice_seen++;
4099  } else if (!strcasecmp(attr->a_name, "ice-pwd")) {
4100  if (!engine->ice_in.pwd || strcmp(engine->ice_in.pwd, attr->a_value)) {
4101  engine->ice_in.pwd = switch_core_session_strdup(smh->session, attr->a_value);
4102  }
4103  } else if (!strcasecmp(attr->a_name, "ice-options")) {
4104  engine->ice_in.options = switch_core_session_strdup(smh->session, attr->a_value);
4105  } else if (!strcasecmp(attr->a_name, "setup")) {
4106  if (!strcasecmp(attr->a_value, "passive") ||
4107  (!strcasecmp(attr->a_value, "actpass") && !switch_channel_test_flag(smh->session->channel, CF_REINVITE))) {
4108  if (!engine->dtls_controller) {
4109  engine->new_dtls = 1;
4110  engine->new_ice = 1;
4111  }
4112  engine->dtls_controller = 1;
4113  } else if (!strcasecmp(attr->a_value, "active")) {
4114  if (engine->dtls_controller) {
4115  engine->new_dtls = 1;
4116  engine->new_ice = 1;
4117  }
4118  engine->dtls_controller = 0;
4119  }
4120  } else if (switch_rtp_has_dtls() && dtls_ok(smh->session) && !strcasecmp(attr->a_name, "fingerprint") && !zstr(attr->a_value)) {
4121  char *p;
4122 
4123  engine->remote_dtls_fingerprint.type = switch_core_session_strdup(smh->session, attr->a_value);
4124 
4125  if ((p = strchr(engine->remote_dtls_fingerprint.type, ' '))) {
4126  *p++ = '\0';
4127 
4129  !zstr(engine->remote_dtls_fingerprint.str) && !strcmp(engine->remote_dtls_fingerprint.str, p)) {
4130  engine->new_dtls = 0;
4131  } else {
4133  engine->new_dtls = 1;
4134  engine->new_ice = 1;
4135  }
4136  }
4137 
4138 
4139  //if (strcasecmp(engine->remote_dtls_fingerprint.type, "sha-256")) {
4140  // switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_WARNING, "Unsupported fingerprint type.\n");
4141  //engine->local_dtls_fingerprint.type = NULL;
4142  //engine->remote_dtls_fingerprint.type = NULL;
4143  //}
4144 
4145 
4146  generate_local_fingerprint(smh, type);
4148 
4149  } else if (!engine->remote_ssrc && !strcasecmp(attr->a_name, "ssrc") && attr->a_value) {
4150  engine->remote_ssrc = (uint32_t) atol(attr->a_value);
4151 
4152  if (engine->rtp_session && engine->remote_ssrc) {
4154  }
4155 
4156 
4157 #ifdef RTCP_MUX
4158  } else if (!strcasecmp(attr->a_name, "rtcp-mux")) {
4159  engine->rtcp_mux = SWITCH_TRUE;
4161  got_rtcp_mux++;
4162 
4163  if (!smh->mparams->rtcp_audio_interval_msec) {
4165  }
4166 #endif
4167  } else if (!strcasecmp(attr->a_name, "candidate")) {
4169 
4170  if (!engine->cand_acl_count) {
4171  engine->cand_acl[engine->cand_acl_count++] = "wan.auto";
4172  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_WARNING, "NO candidate ACL defined, Defaulting to wan.auto\n");
4173  }
4174 
4175 
4176  if (!switch_stristr(" udp ", attr->a_value)) {
4177  continue;
4178  }
4179 
4180  data = switch_core_session_strdup(smh->session, attr->a_value);
4181 
4182  argc = switch_split(data, ' ', fields);
4183 
4184  if (argc < 6 || !switch_is_uint_in_range(fields[1], 1, MAX_CAND_IDX_COUNT)) {
4186  continue;
4187  }
4188 
4189  cid = fields[1] ? atoi(fields[1]) - 1 : 0;
4190 
4191  if (engine->ice_in.cand_idx[cid] >= MAX_CAND - 1) {
4193  continue;
4194  }
4195 
4196  for (i = 0; i < argc; i++) {
4197  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG1, "CAND %d [%s]\n", i, fields[i]);
4198  }
4199 
4200  if (fields[4] && (switch_inet_pton(AF_INET, fields[4], &ip) || switch_inet_pton(AF_INET6, fields[4], &ip))) {
4201  switch_copy_string(con_addr, fields[4], sizeof(con_addr));
4202  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG1, "Is an IP address: %s\n", con_addr);
4203  } else if (fields[4] && ice_resolve) {
4204  if (switch_resolve_host(fields[4], con_addr, sizeof(con_addr)) == SWITCH_STATUS_SUCCESS) {
4205  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "Resolved %s to %s\n", fields[4], con_addr);
4206  } else {
4208  "Drop %s Candidate cid: %d proto: %s type: %s addr: %s:%s (cannot resolve)\n",
4209  type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
4210  cid+1, fields[2], fields[7], fields[4], fields[5]);
4211  continue;
4212  }
4213  } else {
4215  "Drop %s Candidate cid: %d proto: %s type: %s addr: %s:%s (not an IP address)\n",
4216  type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
4217  cid+1, fields[2], fields[7], fields[4] ? fields[4] : "(null)", fields[5]);
4218  continue;
4219  }
4220 
4221  if (!ip_possible(smh, con_addr)) {
4223  "Drop %s Candidate cid: %d proto: %s type: %s addr: %s:%s (no network path)\n",
4224  type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
4225  cid+1, fields[2], fields[7] ? fields[7] : "N/A", con_addr, fields[5]);
4226  continue;
4227  } else {
4229  "Save %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n",
4230  type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
4231  cid+1, fields[2], fields[7] ? fields[7] : "N/A", con_addr, fields[5]);
4232  }
4233 
4234 
4235  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].foundation = switch_core_session_strdup(smh->session, fields[0]);
4236  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].component_id = atoi(fields[1]);
4237  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].transport = switch_core_session_strdup(smh->session, fields[2]);
4238  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].priority = atol(fields[3]);
4239  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].con_addr = switch_core_session_strdup(smh->session, con_addr);
4240  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].con_port = (switch_port_t)atoi(fields[5]);
4241 
4242  j = 6;
4243 
4244  while(j < argc && j <= sizeof(fields)/sizeof(char*) && fields[j+1] && engine->ice_in.cand_idx[cid] < MAX_CAND - 1) {
4245  if (!strcasecmp(fields[j], "typ")) {
4246  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].cand_type = switch_core_session_strdup(smh->session, fields[j+1]);
4247  } else if (!strcasecmp(fields[j], "raddr")) {
4248  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].raddr = switch_core_session_strdup(smh->session, fields[j+1]);
4249  } else if (!strcasecmp(fields[j], "rport")) {
4250  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].rport = (switch_port_t)atoi(fields[j+1]);
4251  } else if (!strcasecmp(fields[j], "generation")) {
4252  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].generation = switch_core_session_strdup(smh->session, fields[j+1]);
4253  }
4254 
4255  j += 2;
4256  }
4257 
4258  cand_seen++;
4259  engine->ice_in.cand_idx[cid]++;
4260  }
4261  }
4262  }
4263 
4264  if (!ice_seen) {
4265  return SWITCH_STATUS_SUCCESS;
4266  }
4267 
4268  relay_ok = 0;
4269 
4270  relay:
4271 
4272  for (cid = 0; cid < MAX_CAND_IDX_COUNT; cid++) {
4273  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Searching for %s candidate.\n", cid ? "rtcp" : "rtp");
4274 
4275  for (ai = 0; ai < engine->cand_acl_count; ai++) {
4276  for (i = 0; i < engine->ice_in.cand_idx[cid]; i++) {
4277  int is_relay = engine->ice_in.cands[i][cid].cand_type && !strcmp(engine->ice_in.cands[i][cid].cand_type, "relay");
4278 
4279  if (relay_ok != is_relay) continue;
4280 
4281  if (switch_check_network_list_ip(engine->ice_in.cands[i][cid].con_addr, engine->cand_acl[ai])) {
4283  "Choose %s candidate, index %d, %s:%d\n", cid ? "rtcp" : "rtp", i,
4284  engine->ice_in.cands[i][cid].con_addr, engine->ice_in.cands[i][cid].con_port);
4285 
4286  engine->ice_in.chosen[cid] = i;
4287  engine->ice_in.is_chosen[cid] = 1;
4288  engine->ice_in.cands[i][cid].ready++;
4289  ip_choose_family(smh, engine->ice_in.cands[i][cid].con_addr);
4290 
4291  if (cid == 0 && got_rtcp_mux && engine->ice_in.cand_idx[1] < MAX_CAND) {
4292 
4294  "Choose same candidate, index %d, for rtcp based on rtcp-mux attribute %s:%d\n", engine->ice_in.cand_idx[1],
4295  engine->ice_in.cands[i][cid].con_addr, engine->ice_in.cands[i][cid].con_port);
4296 
4297 
4298  engine->ice_in.cands[engine->ice_in.cand_idx[1]][1] = engine->ice_in.cands[i][0];
4299  engine->ice_in.chosen[1] = engine->ice_in.cand_idx[1];
4300  engine->ice_in.is_chosen[1] = 1;
4301  engine->ice_in.cand_idx[1]++;
4302 
4303  goto done_choosing;
4304  }
4305 
4306  goto next_cid;
4307  }
4308  }
4309  }
4310 
4311  next_cid:
4312 
4313  continue;
4314  }
4315 
4316  done_choosing:
4317 
4319  engine->ice_in.is_chosen[0] = 1;
4320  }
4321 
4322  if (!engine->ice_in.is_chosen[0]) {
4323  if (!relay_ok) {
4324  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Look for Relay Candidates as last resort\n");
4325  relay_ok = 1;
4326  goto relay;
4327  }
4328 
4329  /* PUNT */
4330  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s no suitable candidates found.\n",
4332  return SWITCH_STATUS_FALSE;
4333  }
4334 
4335  for (i = 0; i < 2; i++) {
4336  if (engine->ice_in.cands[engine->ice_in.chosen[i]][i].ready) {
4337  if (zstr(engine->ice_in.ufrag) || zstr(engine->ice_in.pwd)) {
4338  engine->ice_in.cands[engine->ice_in.chosen[i]][i].ready = 0;
4339  }
4340  }
4341  }
4342 
4343 
4344  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) {
4345  char tmp[80] = "";
4346  const char *media_varname = NULL, *port_varname = NULL;
4347 
4348  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);
4350  "setting remote %s ice addr to index %d %s:%d based on candidate\n", type2str(type), engine->ice_in.chosen[0],
4351  engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port);
4352  engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++;
4353 
4354  engine->remote_rtp_ice_port = (switch_port_t) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port;
4355  engine->remote_rtp_ice_addr = switch_core_session_strdup(smh->session, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
4356 
4357  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);
4358  engine->cur_payload_map->remote_sdp_port = (switch_port_t) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port;
4359 
4360  if (!smh->mparams->remote_ip) {
4362  }
4363 
4364  if (engine->type == SWITCH_MEDIA_TYPE_VIDEO) {
4365  media_varname = "remote_video_ip";
4366  port_varname = "remote_video_port";
4367  } else if (engine->type == SWITCH_MEDIA_TYPE_AUDIO) {
4368  media_varname = "remote_audio_ip";
4369  port_varname = "remote_audio_port";
4370  } else if (engine->type == SWITCH_MEDIA_TYPE_TEXT) {
4371  media_varname = "remote_text_ip";
4372  port_varname = "remote_text_port";
4373  }
4374 
4375  switch_snprintf(tmp, sizeof(tmp), "%d", engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port);
4376  switch_channel_set_variable(smh->session->channel, media_varname, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
4377  switch_channel_set_variable(smh->session->channel, port_varname, tmp);
4378  }
4379 
4380  if (engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port) {
4381  const char *media_varname = NULL, *port_varname = NULL;
4382  char tmp[35] = "";
4383 
4385  "Setting remote rtcp %s addr to %s:%d based on candidate\n", type2str(type),
4386  engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port);
4387  engine->remote_rtcp_ice_port = engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port;
4388  engine->remote_rtcp_ice_addr = switch_core_session_strdup(smh->session, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr);
4389 
4390  engine->remote_rtcp_port = engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port;
4391 
4392 
4393  if (engine->type == SWITCH_MEDIA_TYPE_VIDEO) {
4394  media_varname = "remote_video_rtcp_ip";
4395  port_varname = "remote_video_rtcp_port";
4396  } else if (engine->type == SWITCH_MEDIA_TYPE_AUDIO) {
4397  media_varname = "remote_audio_rtcp_ip";
4398  port_varname = "remote_audio_rtcp_port";
4399  } else if (engine->type == SWITCH_MEDIA_TYPE_TEXT) {
4400  media_varname = "remote_text_rtcp_ip";
4401  port_varname = "remote_text_rtcp_port";
4402  }
4403 
4404  switch_snprintf(tmp, sizeof(tmp), "%d", engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port);
4405  switch_channel_set_variable(smh->session->channel, media_varname, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr);
4406  switch_channel_set_variable(smh->session->channel, port_varname, tmp);
4407 
4408  }
4409 
4410 
4411  if (m && !got_rtcp_mux) {
4412  engine->rtcp_mux = -1;
4413  }
4414 
4415  if (engine->new_ice) {
4416  if (switch_rtp_ready(engine->rtp_session) && engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready) {
4417  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "RE-Activating %s ICE\n", type2str(type));
4418 
4420  engine->ice_in.ufrag,
4421  engine->ice_out.ufrag,
4422  engine->ice_out.pwd,
4423  engine->ice_in.pwd,
4424  IPR_RTP,
4425 #ifdef GOOGLE_ICE
4427  NULL
4428 #else
4429  switch_determine_ice_type(engine, smh->session),
4430  &engine->ice_in
4431 #endif
4432  );
4433 
4434 
4435  engine->new_ice = 0;
4436  }
4437 
4438 
4439  if (engine->rtp_session && ((val = switch_channel_get_variable(smh->session->channel,
4440  type == SWITCH_MEDIA_TYPE_VIDEO ?
4441  "rtcp_video_interval_msec" : "rtcp_audio_interval_msec"))
4442  || (val = type == SWITCH_MEDIA_TYPE_VIDEO ?
4444 
4445  switch_port_t remote_rtcp_port = engine->remote_rtcp_port;
4446 
4447  if (remote_rtcp_port) {
4448  if (!strcasecmp(val, "passthru")) {
4449  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "Activating %s RTCP PASSTHRU PORT %d\n",
4450  type2str(type), remote_rtcp_port);
4451  switch_rtp_activate_rtcp(engine->rtp_session, -1, remote_rtcp_port, engine->rtcp_mux > 0);
4452  } else {
4453  int interval = atoi(val);
4454  if (interval < 100 || interval > 500000) {
4456  "Invalid rtcp interval spec [%d] must be between 100 and 500000\n", interval);
4457  interval = 5000;
4458  }
4459 
4460  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "Activating %s RTCP PORT %d\n", type2str(type), remote_rtcp_port);
4461  switch_rtp_activate_rtcp(engine->rtp_session, interval, remote_rtcp_port, engine->rtcp_mux > 0);
4462  }
4463  }
4464  }
4465 
4466  if (engine->rtp_session && engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready) {
4467  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)
4468  && engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port == engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port) {
4469  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "Skipping %s RTCP ICE (Same as RTP)\n", type2str(type));
4470  } else {
4471  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "Activating %s RTCP ICE\n", type2str(type));
4472 
4474  engine->ice_in.ufrag,
4475  engine->ice_out.ufrag,
4476  engine->ice_out.pwd,
4477  engine->ice_in.pwd,
4478  IPR_RTCP,
4479 #ifdef GOOGLE_ICE
4481  NULL
4482 #else
4483  switch_determine_ice_type(engine, smh->session),
4484  &engine->ice_in
4485 #endif
4486  );
4487  }
4488 
4489  }
4490 
4491  }
4492 
4493  return ice_seen ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_BREAK;
4494 }
4495 #ifdef _MSC_VER
4496 #pragma warning(pop)
4497 #endif
4498 
4500 {
4501  switch_media_handle_t *smh;
4502 
4503  switch_assert(session);
4504 
4505  if (!(smh = session->media_handle)) {
4506  return;
4507  }
4508 
4514 
4515 }
4516 
4517 #define MAX_MATCHES 30
4518 struct matches {
4520  sdp_rtpmap_t *map;
4521  int rate;
4523 };
4524 
4525 #ifndef MIN
4526 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
4527 #endif
4528 
4529 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)
4530 {
4531  int j = 0, f = 0, g;
4532  struct matches mtmp[MAX_MATCHES] = { { 0 } };
4533 
4534  m_idx = MIN(m_idx, MAX_MATCHES);
4535 
4536  for(j = 0; j < m_idx; j++) {
4537  *&mtmp[j] = *&matches[j];
4538  }
4539 
4540  for (g = 0; g < smh->mparams->num_codecs && g < total_codecs && f < MAX_MATCHES; g++) {
4541  const switch_codec_implementation_t *imp = codec_array[g];
4542 
4543  for(j = 0; j < m_idx; j++) {
4544  if (mtmp[j].imp && mtmp[j].imp == imp) {
4545  *&matches[f++] = *&mtmp[j];
4546  mtmp[j].imp = NULL;
4547  }
4548  }
4549  }
4550 }
4551 
4552 static void clear_pmaps(switch_rtp_engine_t *engine)
4553 {
4554  payload_map_t *pmap;
4555 
4556  for (pmap = engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) {
4557  pmap->negotiated = 0;
4558  pmap->current = 0;
4559  }
4560 }
4561 
4563 {
4564  payload_map_t *pmap;
4565  int top = 0;
4566 
4567  for (pmap = engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) {
4568  pmap->negotiated = 1;
4569  if (!top++) pmap->current = 1;
4570  }
4571 }
4572 
4573 static const char *media_flow_varname(switch_media_type_t type)
4574 {
4575  const char *varname = "invalid";
4576 
4577  switch(type) {
4579  varname = "audio_media_flow";
4580  break;
4582  varname = "video_media_flow";
4583  break;
4585  varname = "text_media_flow";
4586  break;
4587  }
4588 
4589  return varname;
4590 }
4591 
4593 {
4594  const char *varname = "invalid";
4595 
4596  switch(type) {
4598  varname = "remote_audio_media_flow";
4599  break;
4601  varname = "remote_video_media_flow";
4602  break;
4604  varname = "remote_text_media_flow";
4605  break;
4606  }
4607 
4608  return varname;
4609 }
4610 
4611 static void media_flow_get_mode(switch_media_flow_t smode, const char **mode_str, switch_media_flow_t *opp_mode)
4612 {
4613  const char *smode_str = "";
4614  switch_media_flow_t opp_smode = smode;
4615 
4616  switch(smode) {
4618  opp_smode = SWITCH_MEDIA_FLOW_RECVONLY;
4619  smode_str = "sendonly";
4620  break;
4622  opp_smode = SWITCH_MEDIA_FLOW_SENDONLY;
4623  smode_str = "recvonly";
4624  break;
4626  smode_str = "inactive";
4627  break;
4629  smode_str = "disabled";
4630  break;
4632  smode_str = "sendrecv";
4633  break;
4634  }
4635 
4636  *mode_str = smode_str;
4637  *opp_mode = opp_smode;
4638 
4639 }
4640 
4641 static void check_stream_changes(switch_core_session_t *session, const char *r_sdp, switch_sdp_type_t sdp_type)
4642 {
4643  switch_core_session_t *other_session = NULL;
4646 
4647  status = switch_core_session_get_partner(session, &other_session);
4648  (void)status;
4649 
4652 
4653  if (other_session) {
4656 
4657  if (sdp_type == SDP_OFFER && r_sdp) {
4658  const char *filter_codec_string = switch_channel_get_variable(session->channel, "filter_codec_string");
4659 
4660  switch_channel_set_variable(session->channel, "codec_string", NULL);
4661  switch_core_media_merge_sdp_codec_string(session, r_sdp, sdp_type, filter_codec_string);
4662  }
4663 
4664  if (switch_channel_test_flag(session->channel, CF_SECURE)) {
4665  other_session->media_handle->crypto_mode = session->media_handle->crypto_mode;
4667  }
4668 
4669  msg = switch_core_session_alloc(other_session, sizeof(*msg));
4671  msg->string_arg = switch_core_session_sprintf(other_session, "=%s", switch_channel_get_variable(session->channel, "ep_codec_string"));
4672  msg->from = __FILE__;
4673  switch_core_session_queue_message(other_session, msg);
4674  }
4675  }
4676 
4677  if (other_session) {
4680 
4682  uint8_t proceed = 1;
4683  const char *sdp_in, *other_ep;
4684  uint8_t res = 0;
4685 
4686  if ((other_ep = switch_channel_get_variable(session->channel, "ep_codec_string"))) {
4687  switch_channel_set_variable(other_session->channel, "codec_string", other_ep);
4688  }
4689 
4690  sdp_in = switch_channel_get_variable(other_session->channel, SWITCH_R_SDP_VARIABLE);
4691  res = switch_core_media_negotiate_sdp(other_session, sdp_in, &proceed, SDP_OFFER);
4692  (void)res;
4693  switch_core_media_activate_rtp(other_session);
4694  msg = switch_core_session_alloc(other_session, sizeof(*msg));
4696  msg->from = __FILE__;
4697 
4699  switch_core_session_queue_message(other_session, msg);
4700  }
4701  }
4702 
4703  switch_core_session_rwunlock(other_session);
4704  }
4705 }
4706 
4708 {
4709  switch_media_handle_t *smh;
4710  switch_rtp_engine_t *engine;
4711  const char *varname = NULL, *smode_str = NULL;
4712  switch_media_flow_t old_smode, opp_smode = smode;
4713  switch_core_session_t *other_session;
4714  int pass_codecs = 0;
4715 
4716  if (!(smh = session->media_handle)) {
4717  return;
4718  }
4719 
4720  engine = &smh->engines[type];
4721 
4722  varname = media_flow_varname(type);
4723 
4724  media_flow_get_mode(smode, &smode_str, &opp_smode);
4725 
4726  old_smode = engine->smode;
4727 
4728  engine->smode = smode;
4729 
4730  switch_channel_set_variable(session->channel, varname, smode_str);
4731 
4732  if (switch_channel_var_true(session->channel, "rtp_pass_codecs_on_reinvite") || engine->pass_codecs) {
4733  pass_codecs = 1;
4734  }
4735 
4736  engine->pass_codecs = 0;
4737 
4738  if (switch_channel_var_true(session->channel, "rtp_pass_codecs_on_stream_change")) {
4739  if (sdp_type == SDP_OFFER && switch_channel_test_flag(session->channel, CF_REINVITE) &&
4740  switch_channel_media_up(session->channel) && (pass_codecs || old_smode != smode)) {
4741 
4742  if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
4743  switch_core_media_set_smode(other_session, type, opp_smode, SDP_OFFER);
4745  switch_core_session_rwunlock(other_session);
4746  }
4747  }
4748  }
4749 }
4750 
4752 {
4753  switch_media_handle_t *smh;
4754  switch_rtp_engine_t *engine;
4755  const char *varname = NULL, *rmode_str = NULL;
4756  switch_media_flow_t opp_rmode = rmode;
4757  switch_core_session_t *other_session = NULL;
4758 
4759  if (!(smh = session->media_handle)) {
4760  return;
4761  }
4762 
4763  engine = &smh->engines[type];
4764 
4765  varname = remote_media_flow_varname(type);
4766  media_flow_get_mode(rmode, &rmode_str, &opp_rmode);
4767 
4768  if (engine->rmode != rmode) {
4769  engine->pass_codecs = 1;
4770  }
4771 
4772  engine->rmode = rmode;
4773 
4774  if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
4775 
4777  switch_core_media_set_smode(other_session, type, rmode, sdp_type);
4778  }
4779 
4780  switch_core_session_rwunlock(other_session);
4781  }
4782 
4783  switch_channel_set_variable(session->channel, varname, rmode_str);
4784 }
4785 
4786 //?
4787 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)
4788 {
4789  uint8_t match = 0, vmatch = 0, almost_vmatch = 0, tmatch = 0, fmatch = 0;
4790  switch_payload_t best_te = 0, cng_pt = 0;
4791  unsigned long best_te_rate = 8000, cng_rate = 8000;
4792  sdp_media_t *m;
4793  sdp_attribute_t *attr;
4794  int ptime = 0, dptime = 0, maxptime = 0, dmaxptime = 0;
4795  int sendonly = 0, recvonly = 0, inactive = 0;
4796  int greedy = 0, x = 0, skip = 0;
4798  const char *val;
4799  const char *crypto = NULL;
4800  int got_crypto = 0, got_video_crypto = 0, got_audio = 0, saw_audio = 0, saw_video = 0, got_avp = 0, got_savp = 0, got_udptl = 0, got_webrtc = 0, got_text = 0, got_text_crypto = 0, got_msrp = 0;
4801  int scrooge = 0;
4802  sdp_parser_t *parser = NULL;
4803  sdp_session_t *sdp;
4804  const switch_codec_implementation_t **codec_array;
4805  int total_codecs;
4806  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
4807  switch_media_handle_t *smh;
4808  uint32_t near_rate = 0;
4809  const switch_codec_implementation_t *mimp = NULL, *near_match = NULL;
4810  sdp_rtpmap_t *mmap = NULL, *near_map = NULL;
4811  struct matches matches[MAX_MATCHES] = { { 0 } };
4812  struct matches near_matches[MAX_MATCHES] = { { 0 } };
4813  int codec_ms = 0;
4814  uint32_t remote_codec_rate = 0, fmtp_remote_codec_rate = 0;
4815  const char *tmp;
4816  int m_idx = 0, skip_rtcp = 0, skip_video_rtcp = 0, got_rtcp_mux = 0, got_video_rtcp_mux = 0;
4817  int nm_idx = 0;
4818  int vmatch_pt = 1, consider_video_fmtp = 1;
4819  int rtcp_auto_audio = 0, rtcp_auto_video = 0;
4820  int got_audio_rtcp = 0, got_video_rtcp = 0;
4821  switch_port_t audio_port = 0, video_port = 0;
4822 
4823  switch_assert(session);
4824 
4825  if (!r_sdp) {
4826  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Tried to negotiate a blank SDP?\n");
4827  return 0;
4828  }
4829 
4830  if (!(smh = session->media_handle)) {
4831  return 0;
4832  }
4833 
4834  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
4835  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
4836  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
4837 
4838  smh->mparams->num_codecs = 0;
4839  smh->num_negotiated_codecs = 0;
4841  codec_array = smh->codecs;
4842  total_codecs = smh->mparams->num_codecs;
4843 
4844  if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
4845  return 0;
4846  }
4847 
4848  if (!(sdp = sdp_session(parser))) {
4849  sdp_parser_free(parser);
4850  return 0;
4851  }
4852 
4855 
4856  if (dtls_ok(session) && (tmp = switch_channel_get_variable(smh->session->channel, "webrtc_enable_dtls")) && switch_false(tmp)) {
4859  }
4860 
4861  if (switch_true(switch_channel_get_variable_dup(session->channel, "rtp_assume_rtcp", SWITCH_FALSE, -1))) {
4862  rtcp_auto_video = 1;
4863  rtcp_auto_audio = 1;
4864  }
4865 
4866  v_engine->new_dtls = 1;
4867  v_engine->new_ice = 1;
4868  a_engine->new_dtls = 1;
4869  a_engine->new_ice = 1;
4870  a_engine->reject_avp = 0;
4871 
4873 
4875 
4876  clear_pmaps(a_engine);
4877  clear_pmaps(v_engine);
4878 
4879  if (proceed) *proceed = 1;
4880 
4883 
4884  if ((val = switch_channel_get_variable(channel, "rtp_codec_negotiation"))) {
4885  if (!strcasecmp(val, "generous")) {
4886  greedy = 0;
4887  scrooge = 0;
4888  } else if (!strcasecmp(val, "greedy")) {
4889  greedy = 1;
4890  scrooge = 0;
4891  } else if (!strcasecmp(val, "scrooge")) {
4892  scrooge = 1;
4893  greedy = 1;
4894  } else {
4895  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "rtp_codec_negotiation ignored invalid value : '%s' \n", val );
4896  }
4897  }
4898 
4899  if ((smh->origin = switch_core_session_strdup(session, (char *) sdp->sdp_origin->o_username))) {
4900 
4902 
4903  if (strstr(smh->origin, "CiscoSystemsSIP-GW-UserAgent")) {
4905  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Activate Buggy RFC2833 Mode!\n");
4906  }
4907  }
4908 
4910  if (strstr(smh->origin, "Sonus_UAC")) {
4913  "Hello,\nI see you have a Sonus!\n"
4914  "FYI, Sonus cannot follow the RFC on the proper way to send DTMF.\n"
4915  "Sadly, my creator had to spend several hours figuring this out so I thought you'd like to know that!\n"
4916  "Don't worry, DTMF will work but you may want to ask them to fix it......\n");
4917  }
4918  }
4919  }
4920 
4921  /* check dtmf_type variable */
4923 
4924  if ((val = switch_channel_get_variable(session->channel, "rtp_liberal_dtmf")) && switch_true(val)) {
4926  }
4927 
4928  if (switch_stristr("T38FaxFillBitRemoval:", r_sdp) || switch_stristr("T38FaxTranscodingMMR:", r_sdp) ||
4929  switch_stristr("T38FaxTranscodingJBIG:", r_sdp)) {
4930  switch_channel_set_variable(session->channel, "t38_broken_boolean", "true");
4931  }
4932 
4933  check_ice(smh, SWITCH_MEDIA_TYPE_AUDIO, sdp, NULL);
4934  check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, NULL);
4935  check_ice(smh, SWITCH_MEDIA_TYPE_TEXT, sdp, NULL);
4936 
4937  if ((sdp->sdp_connection && sdp->sdp_connection->c_address && !strcmp(sdp->sdp_connection->c_address, "0.0.0.0"))) {
4938  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");
4939  sendonly = 2; /* global sendonly always wins */
4940  }
4941 
4942  memset(smh->rejected_streams, 0, sizeof(smh->rejected_streams));
4943  smh->rej_idx = 0;
4944 
4947 
4948  for (m = sdp->sdp_media; m; m = m->m_next) {
4949  sdp_connection_t *connection;
4950  switch_core_session_t *other_session;
4951 
4952  if (!m->m_port && smh->rej_idx < MAX_REJ_STREAMS - 1) {
4953 
4954  switch(m->m_type) {
4955  case sdp_media_audio:
4956  smh->rejected_streams[smh->rej_idx++] = sdp_media_audio;
4957  continue;
4958  case sdp_media_video:
4959  smh->rejected_streams[smh->rej_idx++] = sdp_media_video;
4960  continue;
4961  case sdp_media_image:
4962  smh->rejected_streams[smh->rej_idx++] = sdp_media_image;
4963  continue;
4964  default:
4965  break;
4966  }
4967  }
4968 
4969  if (m->m_type == sdp_media_audio) {
4970  saw_audio = 1;
4971  }
4972 
4973  if (m->m_type == sdp_media_video) {
4974  saw_video = 1;
4975  }
4976 
4977  ptime = dptime;
4978  maxptime = dmaxptime;
4979 
4980  if (m->m_proto == sdp_proto_extended_srtp || m->m_proto == sdp_proto_extended_rtp) {
4981  got_webrtc++;
4982  switch_core_session_set_ice(session);
4983  }
4984 
4985  if (m->m_proto_name && !strcasecmp(m->m_proto_name, "UDP/TLS/RTP/SAVPF")) {
4987  }
4988 
4989  if (m->m_proto_name && !strcasecmp(m->m_proto_name, "UDP/RTP/AVPF")) {
4991  }
4992 
4993  if (m->m_proto == sdp_proto_srtp || m->m_proto == sdp_proto_extended_srtp) {
4994  if (m->m_type == sdp_media_audio) {
4995  got_savp++;
4996  }
4997  } else if (m->m_proto == sdp_proto_rtp) {
4998  if (m->m_type == sdp_media_audio) {
4999  got_avp++;
5000  }
5001  } else if (m->m_proto == sdp_proto_udptl) {
5002  got_udptl++;
5003  } else if (m->m_proto == sdp_proto_msrp || m->m_proto == sdp_proto_msrps){
5004  got_msrp++;
5005  }
5006 
5007  if (got_msrp && m->m_type == sdp_media_message) {
5008  if (!smh->msrp_session) {
5009  smh->msrp_session = switch_msrp_session_new(switch_core_session_get_pool(session), switch_core_session_get_uuid(session), m->m_proto == sdp_proto_msrps);
5010  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "MSRP session created %s\n", smh->msrp_session->call_id);
5011  }
5012 
5014 
5015  for (attr = m->m_attributes; attr; attr = attr->a_next) {
5016  // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[%s]=[%s]\n", attr->a_name, attr->a_value);
5017  if (!strcasecmp(attr->a_name, "path") && attr->a_value) {
5018  smh->msrp_session->remote_path = switch_core_session_strdup(session, attr->a_value);
5019  switch_channel_set_variable(session->channel, "sip_msrp_remote_path", attr->a_value);
5020  } else if (!strcasecmp(attr->a_name, "accept-types") && attr->a_value) {
5021  smh->msrp_session->remote_accept_types = switch_core_session_strdup(session, attr->a_value);
5022  switch_channel_set_variable(session->channel, "sip_msrp_remote_accept_types", attr->a_value);
5023  } else if (!strcasecmp(attr->a_name, "accept-wrapped-types") && attr->a_value) {
5025  switch_channel_set_variable(session->channel, "sip_msrp_remote_accept_wrapped_types", attr->a_value);
5026  } else if (!strcasecmp(attr->a_name, "setup") && attr->a_value) {
5027  smh->msrp_session->remote_setup = switch_core_session_strdup(session, attr->a_value);
5028  switch_channel_set_variable(session->channel, "sip_msrp_remote_setup", attr->a_value);
5029  if (!strcmp(attr->a_value, "passive")) {
5030  smh->msrp_session->active = 1;
5031  }
5032  } else if (!strcasecmp(attr->a_name, "file-selector") && attr->a_value) {
5033  char *tmp = switch_mprintf("%s", attr->a_value);
5034  char *argv[4] = { 0 };
5035  int argc;
5036  int i;
5037 
5038  smh->msrp_session->remote_file_selector = switch_core_session_strdup(session, attr->a_value);
5039  switch_channel_set_variable(session->channel, "sip_msrp_remote_file_selector", attr->a_value);
5040 
5041  argc = switch_separate_string(tmp, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
5042 
5043  for(i = 0; i<argc; i++) {
5045  if (zstr(argv[i])) {
5047  continue;
5048  }
5049  if (!strncasecmp(argv[i], "name:", 5)) {
5050  char *p = argv[i] + 5;
5051  int len = strlen(p);
5052 
5053  if (*p == '"') {
5054  *(p + len - 1) = '\0';
5055  p++;
5056  }
5057  switch_channel_set_variable(session->channel, "sip_msrp_file_name", p);
5058  } else if (!strncasecmp(argv[i], "type:", 5)) {
5059  switch_channel_set_variable(session->channel, "sip_msrp_file_type", argv[i] + 5);
5060  }
5061  if (!strncasecmp(argv[i], "size:", 5)) {
5062  switch_channel_set_variable(session->channel, "sip_msrp_file_size", argv[i] + 5);
5063  }
5064  if (!strncasecmp(argv[i], "hash:", 5)) {
5065  switch_channel_set_variable(session->channel, "sip_msrp_file_hash", argv[i] + 5);
5066  }
5067  }
5068  switch_safe_free(tmp);
5069  } else if (!strcasecmp(attr->a_name, "file-transfer-id") && attr->a_value) {
5070  switch_channel_set_variable(session->channel, "sip_msrp_file_transfer_id", attr->a_value);
5071  } else if (!strcasecmp(attr->a_name, "file-disposition") && attr->a_value) {
5072  switch_channel_set_variable(session->channel, "sip_msrp_file_disposition", attr->a_value);
5073  } else if (!strcasecmp(attr->a_name, "file-date") && attr->a_value) {
5074  switch_channel_set_variable(session->channel, "sip_msrp_file_date", attr->a_value);
5075  } else if (!strcasecmp(attr->a_name, "file-icon") && attr->a_value) {
5076  switch_channel_set_variable(session->channel, "sip_msrp_file_icon", attr->a_value);
5077  } else if (!strcasecmp(attr->a_name, "file-range") && attr->a_value) {
5078  switch_channel_set_variable(session->channel, "sip_msrp_file_range", attr->a_value);
5079  }
5080  }
5081 
5085 
5090 
5091  if (m->m_proto == sdp_proto_msrps) {
5093  }
5094 
5095  if (smh->msrp_session->active) {
5096  const char *ip = switch_msrp_listen_ip();
5097 
5099  "msrp%s://%s:%d/%s;tcp",
5100  smh->msrp_session->secure ? "s" : "",
5101  ip, smh->msrp_session->local_port, smh->msrp_session->call_id);
5102 
5104  }
5105 
5107  tmatch = 1;
5108  }
5109 
5110  if (got_udptl && m->m_type == sdp_media_image) {
5112 
5113  if (m->m_port) {
5115  fmatch = 1;
5116  goto done;
5117  }
5118 
5119  if (switch_channel_var_true(channel, "refuse_t38") || !switch_channel_var_true(channel, "fax_enable_t38")) {
5121  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 REFUSE on %s\n",
5122  switch_channel_get_name(channel),
5123  sdp_type == SDP_ANSWER ? "response" : "request");
5124 
5125  restore_pmaps(a_engine);
5126  fmatch = 0;
5127 
5128  goto t38_done;
5129  } else {
5130  switch_t38_options_t *t38_options = switch_core_media_process_udptl(session, sdp, m);
5131  const char *var = switch_channel_get_variable(channel, "t38_passthru");
5133 
5134  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 ACCEPT on %s\n",
5135  switch_channel_get_name(channel),
5136  sdp_type == SDP_ANSWER ? "response" : "request");
5137 
5138  if (switch_channel_test_app_flag_key("T38", session->channel, CF_APP_T38)) {
5139  if (proceed) *proceed = 0;
5140  }
5141 
5142  if (var) {
5143  if (!(pass = switch_true(var))) {
5144  if (!strcasecmp(var, "once")) {
5145  pass = 2;
5146  }
5147  }
5148  }
5149 
5150  if ((pass == 2 && switch_channel_test_flag(smh->session->channel, CF_T38_PASSTHRU))
5151  || !switch_channel_test_flag(session->channel, CF_REINVITE) ||
5152 
5155  !switch_rtp_ready(a_engine->rtp_session)) {
5156  pass = 0;
5157  }
5158 
5159  if (pass && switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
5160  switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
5162  char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
5163  switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
5164  char tmp[32] = "";
5165 
5166 
5167  if (!switch_channel_test_flag(other_channel, CF_ANSWERED)) {
5169  SWITCH_LOG_WARNING, "%s Error Passing T.38 to unanswered channel %s\n",
5170  switch_channel_get_name(session->channel), switch_channel_get_name(other_channel));
5171  switch_core_session_rwunlock(other_session);
5172 
5173  match = 0;
5174  fmatch = 0;
5175  goto done;
5176  }
5177 
5180 
5181  if (switch_true(switch_channel_get_variable(session->channel, "t38_broken_boolean")) &&
5182  switch_true(switch_channel_get_variable(session->channel, "t38_pass_broken_boolean"))) {
5183  switch_channel_set_variable(other_channel, "t38_broken_boolean", "true");
5184  }
5185 
5186  a_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, t38_options->remote_ip);
5187  a_engine->cur_payload_map->remote_sdp_port = t38_options->remote_port;
5188 
5189  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) {
5190  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n",
5191  switch_channel_get_name(session->channel));
5192  } else {
5193  const char *err = NULL;
5194 
5195  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n",
5196  switch_channel_get_name(session->channel),
5197  remote_host, remote_port, a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
5198 
5199  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
5202 
5205  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
5207  }
5208 
5210  switch_channel_execute_on(session->channel, "execute_on_audio_change");
5211  }
5212 
5213 
5214 
5215  switch_core_media_copy_t38_options(t38_options, other_session);
5216 
5219 
5220  msg = switch_core_session_alloc(other_session, sizeof(*msg));
5222  msg->from = __FILE__;
5223  msg->string_arg = switch_core_session_strdup(other_session, r_sdp);
5224  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing T38 req to other leg.\n%s\n", r_sdp);
5225  switch_core_session_queue_message(other_session, msg);
5226  switch_core_session_rwunlock(other_session);
5227  }
5228  }
5229 
5230  /* do nothing here, mod_fax will trigger a response (if it's listening =/) */
5232  fmatch = 1;
5233  } else {
5234 
5235  fmatch = 0;
5236  }
5237 
5238  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 %s POSSIBLE on %s\n",
5239  switch_channel_get_name(channel),
5240  fmatch ? "IS" : "IS NOT",
5241  sdp_type == SDP_ANSWER ? "response" : "request");
5242 
5243 
5244  goto done;
5245  }
5246  } else if (m->m_type == sdp_media_audio && m->m_port && got_audio && got_savp) {
5247  a_engine->reject_avp = 1;
5248  } else if (m->m_type == sdp_media_audio && m->m_port && !got_audio) {
5249  sdp_rtpmap_t *map;
5250  int ice = 0;
5251 
5252  nm_idx = 0;
5253  m_idx = 0;
5254  memset(matches, 0, sizeof(matches[0]) * MAX_MATCHES);
5255  memset(near_matches, 0, sizeof(near_matches[0]) * MAX_MATCHES);
5256 
5257  audio_port = m->m_port;
5258 
5259  if (!sendonly && (m->m_mode == sdp_sendonly || m->m_mode == sdp_inactive)) {
5260  sendonly = 1;
5261  if (m->m_mode == sdp_inactive) {
5262  inactive = 1;
5263  }
5264  }
5265 
5266  if (!sendonly && m->m_connections && m->m_connections->c_address && !strcmp(m->m_connections->c_address, "0.0.0.0")) {
5267  sendonly = 1;
5268  }
5269 
5270 
5272 
5273  if (sdp_type == SDP_OFFER) {
5274  switch(a_engine->rmode) {
5277  break;
5280  break;
5283  break;
5284  default:
5286  break;
5287  }
5288  }
5289 
5290  for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) {
5291  if (zstr(attr->a_name)) {
5292  continue;
5293  }
5294 
5295 
5296  if (!strncasecmp(attr->a_name, "ice", 3)) {
5297  ice++;
5298  } else if (sendonly < 2 && !strcasecmp(attr->a_name, "sendonly")) {
5299  sendonly = 1;
5300  switch_channel_set_variable(session->channel, "media_audio_mode", "recvonly");
5301  } else if (sendonly < 2 && !strcasecmp(attr->a_name, "inactive")) {
5302  switch_channel_set_variable(session->channel, "media_audio_mode", "inactive");
5303  } else if (!strcasecmp(attr->a_name, "recvonly")) {
5304  switch_channel_set_variable(session->channel, "media_audio_mode", "sendonly");
5305  recvonly = 1;
5306 
5307  a_engine->media_timeout = 0;
5308  a_engine->media_hold_timeout = 0;
5309 
5310  if (switch_rtp_ready(a_engine->rtp_session)) {
5312  a_engine->max_missed_hold_packets = 0;
5313  a_engine->max_missed_packets = 0;
5315  } else {
5316  switch_channel_set_variable(session->channel, "media_timeout_audio", "0");
5317  switch_channel_set_variable(session->channel, "media_hold_timeout_audio", "0");
5318  switch_channel_set_variable(session->channel, "rtp_timeout_sec", "0");
5319  switch_channel_set_variable(session->channel, "rtp_hold_timeout_sec", "0");
5320  }
5321  } else if (sendonly < 2 && !strcasecmp(attr->a_name, "sendrecv")) {
5322  sendonly = 0;
5323  } else if (!strcasecmp(attr->a_name, "ptime")) {
5324  ptime = dptime = atoi(attr->a_value);
5325  } else if (!strcasecmp(attr->a_name, "maxptime")) {
5326  maxptime = dmaxptime = atoi(attr->a_value);
5327  }
5328  }
5329 
5330  if (sendonly == 2 && ice) {
5331  sendonly = 0;
5332  }
5333 
5334 
5335  if (sendonly != 1 && recvonly != 1 && inactive != 1) {
5336  switch_channel_set_variable(session->channel, "media_audio_mode", NULL);
5337  }
5338 
5339  if (sdp_type == SDP_ANSWER) {
5340  if (inactive) {
5341  // When freeswitch had previously sent inactive in sip request. it should remain inactive otherwise smode should be sendrecv
5342  if (a_engine->smode==SWITCH_MEDIA_FLOW_INACTIVE) {
5344  } else {
5346  }
5347  } else if (sendonly) {
5349  } else if (recvonly) {
5351  }
5352  }
5353 
5354 
5356  || ((val = switch_channel_get_variable(session->channel, "rtp_disable_hold"))
5357  && switch_true(val)))
5358  && !smh->mparams->hold_laps) {
5359  smh->mparams->hold_laps++;
5360  switch_core_media_toggle_hold(session, sendonly);
5361  }
5362 
5363 
5364  if (switch_rtp_has_dtls() && dtls_ok(session)) {
5365  for (attr = m->m_attributes; attr; attr = attr->a_next) {
5366 
5367  if (!strcasecmp(attr->a_name, "fingerprint") && !zstr(attr->a_value)) {
5368  got_crypto = 1;
5369  }
5370  }
5371  }
5372 
5373  skip_rtcp = 0;
5374  got_rtcp_mux = 0;
5375  for (attr = m->m_attributes; attr; attr = attr->a_next) {
5376  if (!strcasecmp(attr->a_name, "rtcp-mux")) {
5377  got_rtcp_mux = 1;
5378  skip_rtcp = 1;
5379  if (!smh->mparams->rtcp_video_interval_msec) {
5381  }
5382  } else if (!strcasecmp(attr->a_name, "ice-ufrag")) {
5383  skip_rtcp = 1;
5384  }
5385  }
5386 
5387  if (!got_rtcp_mux) {
5388  a_engine->rtcp_mux = -1;
5389  }
5390 
5391  for (attr = m->m_attributes; attr; attr = attr->a_next) {
5392  if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value && !skip_rtcp) {
5393  a_engine->remote_rtcp_port = (switch_port_t)atoi(attr->a_value);
5394  switch_channel_set_variable_printf(session->channel, "rtp_remote_audio_rtcp_port", "%d", a_engine->remote_rtcp_port);
5395 
5396  if (!smh->mparams->rtcp_audio_interval_msec) {
5398  }
5399  got_audio_rtcp = 1;
5400  } else if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
5401  ptime = atoi(attr->a_value);
5402  } else if (!strcasecmp(attr->a_name, "maxptime") && attr->a_value) {
5403  maxptime = atoi(attr->a_value);
5404  } else if (got_crypto < 1 && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) {
5405  int crypto_tag;
5406 
5407  if (!(smh->mparams->ndlb & SM_NDLB_ALLOW_CRYPTO_IN_AVP) &&
5408  !switch_true(switch_channel_get_variable(session->channel, "rtp_allow_crypto_in_avp"))) {
5409  if (m->m_proto != sdp_proto_srtp && !got_webrtc) {
5410  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "a=crypto in RTP/AVP, refer to rfc3711\n");
5411  match = 0;
5412  goto done;
5413  }
5414  }
5415 
5416  crypto = attr->a_value;
5417  crypto_tag = atoi(crypto);
5418  got_crypto = switch_core_session_check_incoming_crypto(session,
5419  "rtp_has_crypto", SWITCH_MEDIA_TYPE_AUDIO, crypto, crypto_tag, sdp_type);
5420 
5421  }
5422  }
5423 
5424  if (got_crypto == -1 && got_savp && !got_avp && !got_webrtc) {
5425  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Received invite with SAVP but secure media is administratively disabled\n");
5426  match = 0;
5427  continue;
5428  }
5429 
5430  connection = sdp->sdp_connection;
5431  if (m->m_connections) {
5432  connection = m->m_connections;
5433  }
5434 
5435  if (!connection) {
5436  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");
5437  match = 0;
5438  break;
5439  }
5440 
5441  x = 0;
5442 
5443  for (map = m->m_rtpmaps; map; map = map->rm_next) {
5444  int32_t i;
5445  const char *rm_encoding;
5446  uint32_t map_bit_rate = 0;
5447  switch_codec_fmtp_t codec_fmtp = { 0 };
5448  int map_channels = map->rm_params ? atoi(map->rm_params) : 1;
5449 
5450  if (!(rm_encoding = map->rm_encoding)) {
5451  rm_encoding = "";
5452  }
5453 
5454 
5455  if (!strcasecmp(rm_encoding, "telephone-event")) {
5456  if (!best_te || map->rm_rate == a_engine->cur_payload_map->rm_rate) {
5457  best_te = (switch_payload_t) map->rm_pt;
5458  best_te_rate = map->rm_rate;
5459  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set telephone-event payload to %u@%ld\n", best_te, best_te_rate);
5460  }
5461  continue;
5462  }
5463 
5464  if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && !cng_pt && !strcasecmp(rm_encoding, "CN")) {
5465  cng_pt = (switch_payload_t) map->rm_pt;
5466  if (a_engine->rtp_session) {
5467  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u\n", cng_pt);
5468  switch_rtp_set_cng_pt(a_engine->rtp_session, cng_pt);
5469  }
5470  continue;
5471  }
5472 
5473 
5474  if (x++ < skip) {
5475  continue;
5476  }
5477 
5478  if (match) {
5479  continue;
5480  }
5481 
5482  codec_ms = ptime;
5483 
5484  if (switch_channel_get_variable(session->channel, "rtp_h_X-Broken-PTIME") && a_engine->read_impl.microseconds_per_packet) {
5485  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);
5486  codec_ms = a_engine->read_impl.microseconds_per_packet / 1000;
5487  }
5488 
5489  if (maxptime && (!codec_ms || codec_ms > maxptime)) {
5490  codec_ms = maxptime;
5491  }
5492 
5493  if (!codec_ms) {
5494  codec_ms = switch_default_ptime(rm_encoding, map->rm_pt);
5495  }
5496 
5497  map_bit_rate = switch_known_bitrate((switch_payload_t)map->rm_pt);
5498 
5499  if (!ptime && !strcasecmp(map->rm_encoding, "g723")) {
5500  codec_ms = 30;
5501  }
5502 
5503  remote_codec_rate = map->rm_rate;
5504  fmtp_remote_codec_rate = 0;
5505  memset(&codec_fmtp, 0, sizeof(codec_fmtp));
5506 
5507  if (zstr(map->rm_fmtp)) {
5508  if (!strcasecmp(map->rm_encoding, "ilbc")) {
5509  codec_ms = 30;
5510  map_bit_rate = 13330;
5511  } else if (!strcasecmp(map->rm_encoding, "isac")) {
5512  codec_ms = 30;
5513  map_bit_rate = 32000;
5514  }
5515  } else {
5516  if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) {
5517  if (codec_fmtp.bits_per_second) {
5518  map_bit_rate = codec_fmtp.bits_per_second;
5519  }
5520  if (codec_fmtp.microseconds_per_packet) {
5521  codec_ms = (codec_fmtp.microseconds_per_packet / 1000);
5522  }
5523  if (codec_fmtp.actual_samples_per_second) {
5524  fmtp_remote_codec_rate = codec_fmtp.actual_samples_per_second;
5525  }
5526  if (codec_fmtp.stereo) {
5527  map_channels = 2;
5528  } else if (!strcasecmp(map->rm_encoding, "opus")) {
5529  map_channels = 1;
5530  }
5531 
5532  if (codec_fmtp.max_ptime) {
5533  maxptime = codec_fmtp.max_ptime;
5534  }
5535  }
5536  }
5537 
5538  for (i = 0; i < smh->mparams->num_codecs && i < total_codecs; i++) {
5539  const switch_codec_implementation_t *imp = codec_array[i];
5540  uint32_t bit_rate = imp->bits_per_second;
5541  uint32_t codec_rate = imp->samples_per_second;
5542 
5543  if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
5544  continue;
5545  }
5546 
5547  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",
5548  rm_encoding, map->rm_pt, (int) remote_codec_rate, codec_ms, map_bit_rate, map_channels,
5549  imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate, imp->number_of_channels);
5550  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
5551  match = (map->rm_pt == imp->ianacode) ? 1 : 0;
5552  } else {
5553  match = (!strcasecmp(rm_encoding, imp->iananame) &&
5554  ((map->rm_pt < 96 && imp->ianacode < 96) || (map->rm_pt > 95 && imp->ianacode > 95)) &&
5555  (remote_codec_rate == codec_rate || fmtp_remote_codec_rate == imp->actual_samples_per_second)) ? 1 : 0;
5556  if (fmtp_remote_codec_rate) {
5557  remote_codec_rate = fmtp_remote_codec_rate;
5558  }
5559  }
5560 
5561  if (match && bit_rate && map_bit_rate && map_bit_rate != bit_rate && strcasecmp(map->rm_encoding, "ilbc") &&
5562  strcasecmp(map->rm_encoding, "isac")) {
5563  /* if a bit rate is specified and doesn't match, this is not a codec match, except for ILBC */
5564  match = 0;
5565  }
5566 
5567  if (match && remote_codec_rate && codec_rate && remote_codec_rate != codec_rate && (!strcasecmp(map->rm_encoding, "pcma") ||
5568  !strcasecmp(map->rm_encoding, "pcmu"))) {
5569  /* if the sampling rate is specified and doesn't match, this is not a codec match for G.711 */
5570  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sampling rates have to match for G.711\n");
5571  match = 0;
5572  }
5573 
5574  if (match) {
5575  if (scrooge) {
5577  "Bah HUMBUG! Sticking with %s@%uh@%ui\n",
5578  imp->iananame, imp->samples_per_second, imp->microseconds_per_packet / 1000);
5579  } else if ((ptime && codec_ms && codec_ms * 1000 != imp->microseconds_per_packet) || remote_codec_rate != codec_rate) {
5580  /* ptime does not match */
5581  match = 0;
5582 
5583  if (nm_idx >= MAX_MATCHES) {
5585  "Audio Codec Compare [%s:%d:%u:%u:%d:%u:%d] was not saved as a near-match. Too many. Ignoring.\n",
5586  imp->iananame, imp->ianacode, codec_rate, imp->actual_samples_per_second, imp->microseconds_per_packet / 1000, bit_rate, imp->number_of_channels);
5587  continue;
5588  }
5589 
5591  "Audio Codec Compare [%s:%d:%u:%d:%u:%d] is saved as a near-match\n",
5592  imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate, imp->number_of_channels);
5593 
5594  near_matches[nm_idx].codec_idx = i;
5595  near_matches[nm_idx].rate = remote_codec_rate;
5596  near_matches[nm_idx].imp = imp;
5597  near_matches[nm_idx].map = map;
5598  nm_idx++;
5599 
5600  continue;
5601  }
5602 
5603  matches[m_idx].codec_idx = i;
5604  matches[m_idx].rate = codec_rate;
5605  matches[m_idx].imp = imp;
5606  matches[m_idx].map = map;
5607  m_idx++;
5608 
5610  "Audio Codec Compare [%s:%d:%u:%d:%u:%d] ++++ is saved as a match\n",
5611  imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate, imp->number_of_channels);
5612 
5613  if (m_idx >= MAX_MATCHES) {
5614  break;
5615  }
5616 
5617  match = 0;
5618  }
5619  }
5620 
5621  if (m_idx >= MAX_MATCHES) {
5622  break;
5623  }
5624  }
5625 
5626  if (smh->crypto_mode == CRYPTO_MODE_MANDATORY && got_crypto < 1) {
5627  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Crypto not negotiated but required.\n");
5628  match = 0;
5629  m_idx = nm_idx = 0;
5630  }
5631 
5632 
5633  if (!m_idx && nm_idx) {
5634  int j;
5635 
5636  for(j = 0; j < nm_idx; j++) {
5637  const switch_codec_implementation_t *search[1];
5638  char *prefs[1];
5639  char tmp[80];
5640  char fmtp[SWITCH_MAX_CODECS][MAX_FMTP_LEN];
5641  int num;
5642  const switch_codec_implementation_t *timp = NULL;
5643 
5644  near_rate = near_matches[j].rate;
5645  near_match = near_matches[j].imp;
5646  near_map = near_matches[j].map;
5647 
5648  switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui%dc", near_match->iananame, near_rate ? near_rate : near_match->samples_per_second,
5649  codec_ms, near_match->number_of_channels);
5650 
5651  prefs[0] = tmp;
5652  num = switch_loadable_module_get_codecs_sorted(search, fmtp, 1, prefs, 1);
5653 
5654  if (num) {
5655  timp = search[0];
5656  } else {
5657  timp = near_match;
5658  }
5659 
5660  if (!maxptime || timp->microseconds_per_packet / 1000 <= maxptime) {
5661  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Substituting codec %s@%ui@%uh@%dc\n",
5663  match = 1;
5664 
5665  matches[m_idx].codec_idx = near_matches[j].codec_idx;
5666  matches[m_idx].rate = near_rate;
5667  matches[m_idx].imp = timp;
5668  matches[m_idx].map = near_map;
5669  m_idx++;
5670 
5671  break;
5672  }
5673  }
5674  }
5675 
5676  if (m_idx) {
5677  int j;
5678 
5679  if (greedy) { /* sort in favor of mine */
5680  greedy_sort(smh, matches, m_idx, codec_array, total_codecs);
5681  }
5682 
5683  match = 1;
5684  a_engine->codec_negotiated = 1;
5685 
5686  for(j = 0; j < m_idx && smh->num_negotiated_codecs < SWITCH_MAX_CODECS; j++) {
5689  matches[j].map->rm_encoding,
5690  matches[j].imp->modname,
5691  matches[j].map->rm_fmtp,
5692  sdp_type,
5693  matches[j].map->rm_pt,
5694  matches[j].imp->samples_per_second,
5695  matches[j].imp->microseconds_per_packet / 1000,
5696  matches[j].imp->number_of_channels,
5697  SWITCH_TRUE);
5698 
5699  mimp = matches[j].imp;
5700  mmap = matches[j].map;
5701 
5702  if (j == 0) {
5703  a_engine->cur_payload_map = pmap;
5704  a_engine->cur_payload_map->current = 1;
5705  if (a_engine->rtp_session) {
5706  switch_rtp_set_default_payload(a_engine->rtp_session, pmap->pt);
5707  }
5708  }
5709 
5710  pmap->rm_encoding = switch_core_session_strdup(session, (char *) mmap->rm_encoding);
5711  pmap->iananame = switch_core_session_strdup(session, (char *) mimp->iananame);
5712  pmap->recv_pt = (switch_payload_t) mmap->rm_pt;
5713  pmap->rm_rate = mimp->samples_per_second;
5714  pmap->adv_rm_rate = mimp->samples_per_second;
5715  if (strcasecmp(mimp->iananame, "g722")) {
5716  pmap->rm_rate = mimp->actual_samples_per_second;
5717  }
5718  pmap->codec_ms = mimp->microseconds_per_packet / 1000;
5719  pmap->bitrate = mimp->bits_per_second;
5720  pmap->channels = mmap->rm_params ? atoi(mmap->rm_params) : 1;
5721 
5722  if (!strcasecmp((char *) mmap->rm_encoding, "opus")) {
5723  if (pmap->channels == 1) {
5724  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid SDP for opus. Don't ask.. but it needs a /2\n");
5725  pmap->adv_channels = 1;
5726  } else {
5727  pmap->adv_channels = 2; /* IKR ???*/
5728  }
5729  if (!zstr((char *) mmap->rm_fmtp) && switch_stristr("stereo=1", (char *) mmap->rm_fmtp)) {
5730  uint32_t allow_channels = switch_core_max_audio_channels(0);
5731  if (!allow_channels || allow_channels >= 2) { /*default*/
5732  pmap->channels = 2;
5733  } else { /* allow_channels == 1 */
5734  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Opus: setting 1 audio channel via config.\n");
5735  pmap->channels = 1;
5736  }
5737  } else {
5738  pmap->channels = 1;
5739  }
5740  } else {
5741  pmap->adv_channels = pmap->channels;
5742  }
5743 
5744  pmap->remote_sdp_ip = switch_core_session_strdup(session, (char *) connection->c_address);
5745  pmap->remote_sdp_port = (switch_port_t) m->m_port;
5746  pmap->rm_fmtp = switch_core_session_strdup(session, (char *) mmap->rm_fmtp);
5747 
5748  smh->negotiated_codecs[smh->num_negotiated_codecs++] = mimp;
5749  pmap->recv_pt = (switch_payload_t)mmap->rm_pt;
5750 
5751  }
5752  }
5753 
5754  if (match) {
5755  char tmp[50];
5756  //const char *mirror = switch_channel_get_variable(session->channel, "rtp_mirror_remote_audio_codec_payload");
5757 
5758 
5759  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
5762 
5763 
5764  if (a_engine->cur_payload_map->pt == smh->mparams->te) {
5765  switch_payload_t pl = 0;
5766  payload_map_t *pmap;
5767 
5769  for (pmap = a_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
5770  if (pmap->pt > pl) {
5771  pl = pmap->pt;
5772  }
5773  }
5775 
5776  smh->mparams->te = (switch_payload_t) ++pl;
5777  }
5778 
5779 
5780 
5781  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->recv_pt);
5782  switch_channel_set_variable(session->channel, "rtp_audio_recv_pt", tmp);
5783 
5784  if (a_engine->read_impl.iananame) {
5785  if (!switch_core_codec_ready(&a_engine->read_codec) ||
5786  ((strcasecmp(matches[0].imp->iananame, a_engine->read_impl.iananame) ||
5787  matches[0].imp->microseconds_per_packet != a_engine->read_impl.microseconds_per_packet ||
5788  matches[0].imp->samples_per_second != a_engine->read_impl.samples_per_second
5789  ))) {
5790 
5791  a_engine->reset_codec = 1;
5792  }
5793  } else if (switch_core_media_set_codec(session, 0, smh->mparams->codec_flags) != SWITCH_STATUS_SUCCESS) {
5794  match = 0;
5795  }
5796 
5797  if (match) {
5798  if (check_ice(smh, SWITCH_MEDIA_TYPE_AUDIO, sdp, m) == SWITCH_STATUS_FALSE) {
5799  match = 0;
5800  got_audio = 0;
5801  } else {
5802  got_audio = 1;
5803  }
5804  }
5805 
5806  }
5807 
5808  for (map = m->m_rtpmaps; map; map = map->rm_next) {
5809  const char *rm_encoding;
5810 
5811  if (!(rm_encoding = map->rm_encoding)) {
5812  rm_encoding = "";
5813  }
5814 
5815  if (!strcasecmp(rm_encoding, "telephone-event")) {
5816  if (!best_te || map->rm_rate == a_engine->cur_payload_map->adv_rm_rate) {
5817  best_te = (switch_payload_t) map->rm_pt;
5818  best_te_rate = map->rm_rate;
5819  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set telephone-event payload to %u@%lu\n", best_te, best_te_rate);
5820  }
5821  continue;
5822  }
5823 
5824  if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && !strcasecmp(rm_encoding, "CN")) {
5825 
5826  if (!cng_pt || map->rm_rate == a_engine->cur_payload_map->adv_rm_rate) {
5827  cng_pt = (switch_payload_t) map->rm_pt;
5828  cng_rate = map->rm_rate;
5829 
5830  if (a_engine->rtp_session) {
5831  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u@%lu\n", cng_pt, cng_rate);
5832  switch_rtp_set_cng_pt(a_engine->rtp_session, cng_pt);
5833  }
5834  }
5835  continue;
5836  }
5837  }
5838 
5839  if (cng_rate != a_engine->cur_payload_map->adv_rm_rate) {
5840  cng_rate = 8000;
5841  }
5842 
5843  if (best_te_rate != a_engine->cur_payload_map->adv_rm_rate) {
5844  best_te_rate = 8000;
5845  }
5846 
5847  if (!best_te && (switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF))) {
5849  "No 2833 in SDP. Liberal DTMF mode adding %d as telephone-event.\n", smh->mparams->te);
5850  best_te = smh->mparams->te;
5851  }
5852 
5853  if (best_te) {
5854  smh->mparams->te_rate = best_te_rate;
5855 
5856  if (smh->mparams->dtmf_type == DTMF_AUTO || smh->mparams->dtmf_type == DTMF_2833 ||
5858  if (sdp_type == SDP_OFFER) {
5859  smh->mparams->te = smh->mparams->recv_te = (switch_payload_t) best_te;
5860  switch_channel_set_variable(session->channel, "dtmf_type", "rfc2833");
5861  smh->mparams->dtmf_type = DTMF_2833;
5862  } else {
5863  smh->mparams->te = (switch_payload_t) best_te;
5864  switch_channel_set_variable(session->channel, "dtmf_type", "rfc2833");
5865  smh->mparams->dtmf_type = DTMF_2833;
5866  }
5867  }
5868 
5869  if (a_engine->rtp_session) {
5871  switch_channel_set_variable_printf(session->channel, "rtp_2833_send_payload", "%d", smh->mparams->te);
5873  switch_channel_set_variable_printf(session->channel, "rtp_2833_recv_payload", "%d", smh->mparams->recv_te);
5874  }
5875 
5876 
5877  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Set 2833 dtmf send payload to %u recv payload to %u\n",
5878  switch_channel_get_name(session->channel), smh->mparams->te, smh->mparams->recv_te);
5879 
5880 
5881  } else {
5882  /* by default, use SIP INFO if 2833 is not in the SDP */
5883  if (!switch_false(switch_channel_get_variable(channel, "rtp_info_when_no_2833"))) {
5884  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No 2833 in SDP. Disable 2833 dtmf and switch to INFO\n");
5885  switch_channel_set_variable(session->channel, "dtmf_type", "info");
5886  smh->mparams->dtmf_type = DTMF_INFO;
5887  smh->mparams->recv_te = smh->mparams->te = 0;
5888  } else {
5889  switch_channel_set_variable(session->channel, "dtmf_type", "none");
5890  smh->mparams->dtmf_type = DTMF_NONE;
5891  smh->mparams->recv_te = smh->mparams->te = 0;
5892  }
5893  }
5894 
5895  } else if (!got_text && m->m_type == sdp_media_text && m->m_port) {
5896  sdp_rtpmap_t *map;
5897  payload_map_t *red_pmap = NULL;
5898 
5900 
5901  connection = sdp->sdp_connection;
5902  if (m->m_connections) {
5903  connection = m->m_connections;
5904  }
5905 
5906  if (!connection) {
5907  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");
5908  match = 0;
5909  break;
5910  }
5911 
5912  switch_channel_set_variable(session->channel, "text_possible", "true");
5915 
5916  got_text++;
5917 
5918  for (map = m->m_rtpmaps; map; map = map->rm_next) {
5919  payload_map_t *pmap;
5920 
5921  pmap = switch_core_media_add_payload_map(session,
5923  map->rm_encoding,
5924  NULL,
5925  NULL,
5926  SDP_OFFER,
5927  map->rm_pt,
5928  1000,
5929  0,
5930  1,
5931  SWITCH_TRUE);
5932 
5933 
5934  pmap->remote_sdp_ip = switch_core_session_strdup(session, (char *) connection->c_address);
5935  pmap->remote_sdp_port = (switch_port_t) m->m_port;
5936  if (map->rm_fmtp) {
5937  pmap->rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp);
5938  }
5939 
5940 
5941  t_engine->cur_payload_map = pmap;
5942 
5943  if (!strcasecmp(map->rm_encoding, "red")) {
5944  red_pmap = pmap;
5945  }
5946  }
5947 
5948  if (red_pmap) {
5949  t_engine->cur_payload_map = red_pmap;
5950  }
5951 
5952  for (attr = m->m_attributes; attr; attr = attr->a_next) {
5953  if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value) {
5954  switch_channel_set_variable(session->channel, "sip_remote_text_rtcp_port", attr->a_value);
5955 
5956  } else if (!got_text_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) {
5957  int crypto_tag;
5958 
5959  if (!(smh->mparams->ndlb & SM_NDLB_ALLOW_CRYPTO_IN_AVP) &&
5960  !switch_true(switch_channel_get_variable(session->channel, "rtp_allow_crypto_in_avp"))) {
5961  if (m->m_proto != sdp_proto_srtp && !got_webrtc) {
5962  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "a=crypto in RTP/AVP, refer to rfc3711\n");
5963  match = 0;
5964  goto done;
5965  }
5966  }
5967 
5968  crypto = attr->a_value;
5969  crypto_tag = atoi(crypto);
5970 
5971  got_text_crypto = switch_core_session_check_incoming_crypto(session,
5972  "rtp_has_text_crypto",
5973  SWITCH_MEDIA_TYPE_TEXT, crypto, crypto_tag, sdp_type);
5974 
5975  }
5976  }
5977 
5978 
5979  //map->rm_encoding
5980  //map->rm_fmtp
5981  //map->rm_pt
5982  //t_engine->cur_payload_map = pmap;
5983 
5984  t_engine->codec_negotiated = 1;
5985  tmatch = 1;
5986 
5987 
5988  if (!t_engine->local_sdp_port) {
5990  }
5991 
5992  check_ice(smh, SWITCH_MEDIA_TYPE_TEXT, sdp, m);
5993  //parse rtt
5994 
5995  } else if (m->m_type == sdp_media_video) {
5996  sdp_rtpmap_t *map;
5997  const char *rm_encoding;
5998  const switch_codec_implementation_t *mimp = NULL;
5999  int i;
6000  const char *inherit_video_fmtp = NULL;
6001 
6003 
6004  if (sdp_type == SDP_OFFER) {
6005  sdp_bandwidth_t *bw;
6006  int tias = 0;
6007 
6008  for (bw = m->m_bandwidths; bw; bw = bw->b_next) {
6009  if (bw->b_modifier == sdp_bw_as && !tias) {
6010  v_engine->sdp_bw = bw->b_value;
6011  } else if (bw->b_modifier == sdp_bw_tias) {
6012  tias = 1;
6013  v_engine->sdp_bw = bw->b_value / 1024;
6014  }
6015  }
6016 
6017  switch(v_engine->rmode) {
6021  break;
6024  break;
6027  break;
6028  default:
6030  break;
6031  }
6032  }
6033 
6034  if (!m->m_port) {
6035  goto endsdp;
6036  }
6037 
6038  vmatch = 0;
6039  almost_vmatch = 0;
6040  m_idx = 0;
6041  memset(matches, 0, sizeof(matches[0]) * MAX_MATCHES);
6042  memset(near_matches, 0, sizeof(near_matches[0]) * MAX_MATCHES);
6043 
6044  switch_channel_set_variable(session->channel, "video_possible", "true");
6047 
6048  connection = sdp->sdp_connection;
6049  if (m->m_connections) {
6050  connection = m->m_connections;
6051  }
6052 
6053  if (!connection) {
6054  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");
6055  match = 0;
6056  break;
6057  }
6058 
6059 
6060 
6061  skip_video_rtcp = 0;
6062  got_video_rtcp_mux = 0;
6063  for (attr = m->m_attributes; attr; attr = attr->a_next) {
6064  if (!strcasecmp(attr->a_name, "rtcp-mux")) {
6065  got_video_rtcp_mux = 1;
6066  skip_video_rtcp = 1;
6067  } else if (!strcasecmp(attr->a_name, "ice-ufrag")) {
6068  skip_video_rtcp = 1;
6069  }
6070  }
6071 
6072  if (!got_video_rtcp_mux) {
6073  v_engine->rtcp_mux = -1;
6074  }
6075 
6076  for (attr = m->m_attributes; attr; attr = attr->a_next) {
6077  if (!strcasecmp(attr->a_name, "framerate") && attr->a_value) {
6078  //framerate = atoi(attr->a_value);
6079  } else if (!strcasecmp(attr->a_name, "rtcp-fb")) {
6080  if (!zstr(attr->a_value)) {
6081  if (switch_stristr("fir", attr->a_value)) {
6082  v_engine->fir++;
6083  }
6084 
6085  if (switch_stristr("pli", attr->a_value)) {
6086  v_engine->pli++;
6087  }
6088 
6089  if (switch_stristr("nack", attr->a_value)) {
6090  v_engine->nack++;
6091  }
6092 
6093  if (switch_stristr("tmmbr", attr->a_value)) {
6094  v_engine->tmmbr++;
6095  }
6096 
6097  rtcp_auto_video = 1;
6099  }
6100  } else if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value && !skip_video_rtcp) {
6101  v_engine->remote_rtcp_port = (switch_port_t)atoi(attr->a_value);
6102  switch_channel_set_variable_printf(session->channel, "rtp_remote_video_rtcp_port", "%d", v_engine->remote_rtcp_port);
6103  if (!smh->mparams->rtcp_video_interval_msec) {
6105  }
6106  got_video_rtcp = 1;
6107  } else if (!got_video_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) {
6108  int crypto_tag;
6109 
6110  if (!(smh->mparams->ndlb & SM_NDLB_ALLOW_CRYPTO_IN_AVP) &&
6111  !switch_true(switch_channel_get_variable(session->channel, "rtp_allow_crypto_in_avp"))) {
6112  if (m->m_proto != sdp_proto_srtp && !got_webrtc) {
6113  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "a=crypto in RTP/AVP, refer to rfc3711\n");
6114  match = 0;
6115  goto done;
6116  }
6117  }
6118 
6119  crypto = attr->a_value;
6120  crypto_tag = atoi(crypto);
6121 
6122  got_video_crypto = switch_core_session_check_incoming_crypto(session,
6123  "rtp_has_video_crypto",
6124  SWITCH_MEDIA_TYPE_VIDEO, crypto, crypto_tag, sdp_type);
6125 
6126  }
6127  }
6128 
6129 
6130  if (switch_true(switch_channel_get_variable_dup(session->channel, "inherit_codec", SWITCH_FALSE, -1))) {
6131  vmatch_pt = 1;
6132  }
6133 
6134  compare:
6135 
6136  for (map = m->m_rtpmaps; map; map = map->rm_next) {
6137 
6138  if (switch_rtp_has_dtls() && dtls_ok(session)) {
6139  for (attr = m->m_attributes; attr; attr = attr->a_next) {
6140  if (!strcasecmp(attr->a_name, "fingerprint") && !zstr(attr->a_value)) {
6141  got_video_crypto = 1;
6142  }
6143  }
6144  }
6145 
6146  if (!(rm_encoding = map->rm_encoding)) {
6147  rm_encoding = "";
6148  }
6149 
6150  for (i = 0; i < total_codecs; i++) {
6151  const switch_codec_implementation_t *imp = codec_array[i];
6152 
6153  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
6154  continue;
6155  }
6156 
6159  continue;
6160  }
6161 
6162  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video Codec Compare [%s:%d]/[%s:%d]\n",
6163  rm_encoding, map->rm_pt, imp->iananame, imp->ianacode);
6164  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
6165  vmatch = (map->rm_pt == imp->ianacode) ? 1 : 0;
6166  } else {
6167  vmatch = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1;
6168  }
6169 
6170  if (sdp_type == SDP_ANSWER && consider_video_fmtp && vmatch && !zstr(map->rm_fmtp) && !zstr(smh->fmtps[i])) {
6171  almost_vmatch = 1;
6172  vmatch = !strcasecmp(smh->fmtps[i], map->rm_fmtp);
6173  }
6174 
6175  if (vmatch && vmatch_pt) {
6176  const char *other_pt = switch_channel_get_variable_partner(channel, "rtp_video_pt");
6177 
6178  if (other_pt) {
6179  int opt = atoi(other_pt);
6180  if (map->rm_pt != opt) {
6181  vmatch = 0;
6182  } else {
6183  if (switch_channel_var_true(channel, "inherit_video_fmtp")) {
6184  inherit_video_fmtp = switch_channel_get_variable_partner(channel, "rtp_video_fmtp");
6185  }
6186  }
6187  }
6188  }
6189 
6190  if (vmatch) {
6191  matches[m_idx].imp = imp;
6192  matches[m_idx].map = map;
6193 
6194  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video Codec Compare [%s:%d] +++ is saved as a match\n",
6195  imp->iananame, map->rm_pt);
6196 
6197  m_idx++;
6198 
6199  if (m_idx >= MAX_MATCHES) {
6200  break;
6201  }
6202  }
6203 
6204  vmatch = 0;
6205  }
6206 
6207  if (m_idx >= MAX_MATCHES) {
6208  break;
6209  }
6210  }
6211 
6212  if (consider_video_fmtp && (!m_idx || almost_vmatch)) {
6213  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No matches with FTMP, fallback to ignoring FMTP\n");
6214  almost_vmatch = 0;
6215  m_idx = 0;
6216  consider_video_fmtp = 0;
6217  goto compare;
6218  }
6219 
6220  if (vmatch_pt && !m_idx) {
6221  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No matches with inherit_codec, fallback to ignoring PT\n");
6222  vmatch_pt = 0;
6223  goto compare;
6224  }
6225 
6226  if (smh->crypto_mode == CRYPTO_MODE_MANDATORY && got_video_crypto < 1) {
6227  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Crypto not negotiated but required.\n");
6228  vmatch = 0;
6229  m_idx = 0;
6230  }
6231 
6232  if (m_idx) {
6233  char tmp[50];
6234  //const char *mirror = switch_channel_get_variable(session->channel, "rtp_mirror_remote_video_codec_payload");
6235  int j = 0;
6236 
6237  if (greedy) { /* sort in favor of mine */
6238  greedy_sort(smh, matches, m_idx, codec_array, total_codecs);
6239  }
6240 
6241  vmatch = 1;
6242  v_engine->codec_negotiated = 1;
6243  v_engine->payload_map = NULL;
6244 
6245  for(j = 0; j < m_idx && smh->num_negotiated_codecs < SWITCH_MAX_CODECS; j++) {
6248  matches[j].map->rm_encoding,
6249  matches[j].imp->modname,
6250  consider_video_fmtp ? matches[j].map->rm_fmtp : NULL,
6251  sdp_type,
6252  matches[j].map->rm_pt,
6253  matches[j].imp->samples_per_second,
6254  matches[j].imp->microseconds_per_packet / 1000,
6255  matches[j].imp->number_of_channels,
6256  SWITCH_TRUE);
6257 
6258  if (j == 0) {
6259  v_engine->cur_payload_map = pmap;
6260  v_engine->cur_payload_map->current = 1;
6261  if (v_engine->rtp_session) {
6262  switch_rtp_set_default_payload(v_engine->rtp_session, pmap->pt);
6263  }
6264  }
6265 
6266  mimp = matches[j].imp;
6267  map = matches[j].map;
6268 
6269  pmap->rm_encoding = switch_core_session_strdup(session, (char *) map->rm_encoding);
6270  pmap->recv_pt = (switch_payload_t) map->rm_pt;
6271  pmap->rm_rate = map->rm_rate;
6272  pmap->codec_ms = mimp->microseconds_per_packet / 1000;
6273 
6274 
6275  pmap->remote_sdp_ip = switch_core_session_strdup(session, (char *) connection->c_address);
6276  pmap->remote_sdp_port = (switch_port_t) m->m_port;
6277  pmap->rm_fmtp = switch_core_session_strdup(session, (char *) inherit_video_fmtp ? inherit_video_fmtp : map->rm_fmtp);
6278  smh->negotiated_codecs[smh->num_negotiated_codecs++] = mimp;
6279 
6280 #if 0
6281  if (j == 0 && (!switch_true(mirror) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND)) {
6282  switch_core_media_get_offered_pt(session, mimp, &pmap->recv_pt);
6283  }
6284 #endif
6285  }
6286 
6287  switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->cur_payload_map->remote_sdp_port);
6290  switch_channel_set_variable(session->channel, "rtp_video_fmtp", v_engine->cur_payload_map->rm_fmtp);
6291  switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->cur_payload_map->pt);
6292  switch_channel_set_variable(session->channel, "rtp_video_pt", tmp);
6294  switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->cur_payload_map->recv_pt);
6295  switch_channel_set_variable(session->channel, "rtp_video_recv_pt", tmp);
6296 
6297  if (switch_core_codec_ready(&v_engine->read_codec) && strcasecmp(matches[0].imp->iananame, v_engine->read_codec.implementation->iananame)) {
6298  v_engine->reset_codec = 1;
6299  }
6300 
6302  if (check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, m) == SWITCH_STATUS_FALSE) {
6303  vmatch = 0;
6304  }
6305  }
6306  }
6307 
6308  video_port = m->m_port;
6309  }
6310  }
6311 
6312  endsdp:
6313 
6314  if (rtcp_auto_audio || rtcp_auto_video) {
6315  if (rtcp_auto_audio && !skip_rtcp && !got_audio_rtcp && audio_port) {
6316  switch_channel_set_variable_printf(session->channel, "rtp_remote_audio_rtcp_port", "%d", audio_port + 1);
6317  a_engine->remote_rtcp_port = audio_port + 1;
6318 
6319  if (!smh->mparams->rtcp_audio_interval_msec) {
6321  }
6322  }
6323  if (rtcp_auto_video && !skip_video_rtcp && !got_video_rtcp && video_port) {
6324  switch_channel_set_variable_printf(session->channel, "rtp_remote_video_rtcp_port", "%d", video_port + 1);
6325  v_engine->remote_rtcp_port = video_port + 1;
6326  if (!smh->mparams->rtcp_video_interval_msec) {
6328  }
6329  }
6330  }
6331 
6332 
6333  if (!saw_audio) {
6334  payload_map_t *pmap;
6335 
6336  a_engine->rmode = SWITCH_MEDIA_FLOW_DISABLED;
6337  switch_channel_set_variable(smh->session->channel, "audio_media_flow", "inactive");
6338 
6339 
6340  pmap = switch_core_media_add_payload_map(session,
6342  "L16",
6343  NULL,
6344  NULL,
6345  SDP_OFFER,
6346  97,
6347  8000,
6348  20,
6349  1,
6350  SWITCH_TRUE);
6351 
6352  pmap->remote_sdp_ip = "127.0.0.1";
6353  pmap->remote_sdp_port = 9999;
6354  pmap->pt = 97;
6355  pmap->recv_pt = 97;
6356  pmap->codec_ms = 20;
6357  a_engine->cur_payload_map = pmap;
6360  }
6361 
6362  done:
6363 
6364  if (v_engine->rtp_session) {
6365  if (v_engine->fir) {
6367  } else {
6369  }
6370 
6371  if (v_engine->pli) {
6373  } else {
6375  }
6376 
6377  if (v_engine->nack) {
6379  } else {
6381  }
6382 
6383  if (v_engine->tmmbr) {
6385  } else {
6387  }
6388  }
6389 
6390  if (match) {
6392  } else {
6394  }
6395 
6396  if (vmatch) {
6398  } else {
6399  if (switch_channel_test_flag(channel, CF_VIDEO) && !saw_video) {
6400  //switch_core_media_set_rmode(smh->session, SWITCH_MEDIA_TYPE_VIDEO, SWITCH_MEDIA_FLOW_INACTIVE, sdp_type);
6401 
6402  if (sdp_type == SDP_OFFER) {
6404  }
6405  }
6406  }
6407 
6408  if (tmatch) {
6410  } else {
6412  }
6413 
6414  if (fmatch) {
6417  } else {
6419  }
6420 
6421  t38_done:
6422 
6423  if (parser) {
6424  sdp_parser_free(parser);
6425  }
6426 
6427  smh->mparams->cng_pt = cng_pt;
6428  smh->mparams->cng_rate = cng_rate;
6429 
6430  check_stream_changes(session, r_sdp, sdp_type);
6431 
6432  return match || vmatch || tmatch || fmatch;
6433 }
6434 
6435 //?
6437 {
6438  switch_rtp_engine_t *a_engine;
6439  switch_media_handle_t *smh;
6441 
6442  switch_assert(session);
6443 
6444  if (!(smh = session->media_handle)) {
6445  return;
6446  }
6447 
6448  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
6449 
6450  restore_pmaps(a_engine);
6451 
6452  switch_channel_set_private(channel, "t38_options", NULL);
6457 }
6458 
6459 //?
6460 
6462 {
6463  int changed = 0;
6464  switch_rtp_engine_t *a_engine, *v_engine;
6465  switch_media_handle_t *smh;
6466  switch_core_session_t *b_session = NULL;
6467  switch_channel_t *b_channel = NULL;
6468 
6469  switch_assert(session);
6470 
6471  if (!(smh = session->media_handle)) {
6472  return 0;
6473  }
6474 
6475  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
6476  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
6477 
6478 
6479  if (switch_core_session_get_partner(session, &b_session) == SWITCH_STATUS_SUCCESS) {
6480  b_channel = switch_core_session_get_channel(b_session);
6481  }
6482 
6483  if (sendonly && switch_channel_test_flag(session->channel, CF_ANSWERED)) {
6485  const char *stream;
6486  const char *msg = "hold";
6487  const char *info;
6488 
6490  (!b_channel || switch_channel_test_flag(b_channel, CF_EVENT_LOCK_PRI))) {
6491  switch_channel_mark_hold(session->channel, sendonly);
6493  changed = 0;
6494  goto end;
6495  }
6496 
6497  info = switch_channel_get_variable(session->channel, "presence_call_info");
6498 
6499  if (info) {
6500  if (switch_stristr("private", info)) {
6501  msg = "hold-private";
6502  }
6503  }
6504 
6505  if (a_engine->rtp_session) {
6507  }
6508 
6509  if (v_engine->rtp_session) {
6511  }
6512 
6515  switch_channel_presence(session->channel, "unknown", msg, NULL);
6516  changed = 1;
6517 
6518  if (a_engine->max_missed_hold_packets && a_engine->rtp_session) {
6520  }
6521 
6522  if (a_engine->media_hold_timeout) {
6524  }
6525 
6526  if (v_engine->media_hold_timeout) {
6528  }
6529 
6530 
6531  if (!(stream = switch_channel_get_hold_music(session->channel))) {
6532  stream = "local_stream://moh";
6533  }
6534 
6535 
6536  if (stream && strcasecmp(stream, "silence") && (!b_channel || !switch_channel_test_flag(b_channel, CF_EVENT_LOCK_PRI))) {
6537  if (!strcasecmp(stream, "indicate_hold")) {
6541  } else {
6544  switch_yield(250000);
6545  }
6546  }
6547 
6548  }
6549  } else {
6553 
6554  if (a_engine->rtp_session) {
6556  }
6557 
6558  if (v_engine->rtp_session) {
6560  }
6561 
6562  changed = 1;
6563  }
6564 
6566 
6568  int media_on_hold_a = switch_true(switch_channel_get_variable_dup(session->channel, "bypass_media_resume_on_hold", SWITCH_FALSE, -1));
6569  int bypass_after_hold_a = 0;
6570  int bypass_after_hold_b = 0;
6571 
6572  if (media_on_hold_a) {
6573  bypass_after_hold_a = switch_true(switch_channel_get_variable_dup(session->channel, "bypass_media_after_hold", SWITCH_FALSE, -1));
6574  }
6575 
6576  if (b_channel) {
6577  if (switch_true(switch_channel_get_variable_dup(b_channel, "bypass_media_resume_on_hold", SWITCH_FALSE, -1))) {
6578  bypass_after_hold_b = switch_true(switch_channel_get_variable_dup(b_channel, "bypass_media_after_hold", SWITCH_FALSE, -1));
6579  }
6580  }
6581 
6582  switch_yield(250000);
6583 
6584  if (b_channel && (switch_channel_test_flag(session->channel, CF_BYPASS_MEDIA_AFTER_HOLD) ||
6585  switch_channel_test_flag(b_channel, CF_BYPASS_MEDIA_AFTER_HOLD) || bypass_after_hold_a || bypass_after_hold_b)) {
6586  /* try to stay out from media stream */
6588  }
6589 
6590  if (a_engine->rtp_session) {
6592 
6593  if (a_engine->max_missed_packets) {
6595  }
6596 
6597  if (a_engine->media_hold_timeout) {
6599  }
6600  }
6601 
6602  if (v_engine->rtp_session) {
6604 
6605  if (v_engine->media_hold_timeout) {
6607  }
6608  }
6609 
6610  if (b_channel) {
6611  if (switch_channel_test_flag(session->channel, CF_HOLD)) {
6612  switch_ivr_unhold(b_session);
6615  } else {
6616  switch_channel_stop_broadcast(b_channel);
6617  switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
6618  }
6619  }
6620 
6622 
6625  switch_channel_presence(session->channel, "unknown", "unhold", NULL);
6626 
6627  if (a_engine->rtp_session) {
6629  }
6630 
6631  if (v_engine->rtp_session) {
6633  }
6634 
6635  changed = 1;
6636  }
6637  }
6638 
6639 
6640  end:
6642 
6643 
6644  if (b_session) {
6646  switch_core_session_rwunlock(b_session);
6647  }
6648 
6649 
6650  return changed;
6651 }
6652 
6653 
6655 {
6656  switch_media_handle_t *smh;
6657  switch_rtp_engine_t *v_engine;
6659 
6660  switch_assert(session);
6661 
6662  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
6663  return NULL;
6664  }
6665 
6666  if (!(smh = session->media_handle)) {
6667  return NULL;
6668  }
6669 
6670  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
6671 
6672 
6673 
6674  if (rw == SWITCH_RW_READ) {
6676  fh = smh->video_read_fh;
6678  } else {
6680  fh = smh->video_write_fh;
6682  }
6683 
6684 
6685 
6686  return fh;
6687 }
6688 
6690 {
6691  switch_frame_t fr = { 0 };
6692  int i = 0;
6693  switch_rgb_color_t bgcolor = { 0 };
6695  unsigned char buf[SWITCH_RTP_MAX_BUF_LEN];
6696  switch_media_handle_t *smh;
6697  switch_image_t *blank_img = NULL;
6698  uint32_t frames = 0, frame_ms = 0;
6699  uint32_t fps, width, height;
6700  switch_assert(session != NULL);
6701 
6702  if (!(smh = session->media_handle)) {
6703  return;
6704  }
6705 
6706  fps = smh->vid_params.fps;
6707  width = smh->vid_params.width;
6708  height = smh->vid_params.height;
6709 
6710  if (!width) width = 352;
6711  if (!height) height = 288;
6712  if (!fps) fps = 15;
6713 
6714  fr.packet = buf;
6715  fr.packetlen = buflen;
6716  fr.data = buf + 12;
6717  fr.buflen = buflen - 12;
6718 
6719 
6720  blank_img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, width, height, 1);
6721  switch_color_set_rgb(&bgcolor, "#000000");
6722  switch_img_fill(blank_img, 0, 0, blank_img->d_w, blank_img->d_h, &bgcolor);
6723 
6724  if (fps < 15) fps = 15;
6725  frame_ms = (uint32_t) 1000 / fps;
6726  if (frame_ms <= 0) frame_ms = 66;
6727  frames = (uint32_t) ms / frame_ms;
6728 
6730  for (i = 0; i < frames; i++) {
6731  fr.img = blank_img;
6733  switch_yield(frame_ms * 1000);
6734  }
6736 
6737  switch_img_free(&blank_img);
6738 
6739 }
6740 
6742 {
6743  switch_core_session_t *session = (switch_core_session_t *) obj;
6744  switch_media_handle_t *smh;
6745  unsigned char *buf = NULL;
6746  switch_frame_t fr = { 0 };
6747  switch_rtp_engine_t *v_engine;
6749  switch_timer_t timer = { 0 };
6750  switch_video_read_flag_t read_flags = SVR_FLUSH;
6751  switch_core_session_t *b_session = NULL;
6752  switch_fps_t fps_data = { 0 };
6753  float fps = 15.0f;
6754  switch_image_t *last_frame = NULL;
6755  int last_w = 0, last_h = 0, kps = 0;
6756  switch_status_t res;
6757 
6759  return NULL;
6760  }
6761 
6762  if (!(smh = session->media_handle)) {
6764 
6765  return NULL;
6766  }
6767 
6768  res = switch_core_session_get_partner(session, &b_session);
6769  (void)res;
6770 
6772 
6773  if (b_session) {
6775  }
6776 
6777  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
6778 
6780  v_engine->thread_write_lock = switch_thread_self();
6781 
6782 
6783  buf = switch_core_session_alloc(session, buflen);
6784  fr.packet = buf;
6785  fr.packetlen = buflen;
6786  fr.data = buf + 12;
6787  fr.buflen = buflen - 12;
6789 
6790  if (smh->video_write_fh) {
6791  if (smh->video_write_fh->mm.fps) {
6792  fps = smh->video_write_fh->mm.fps;
6793  } else if (smh->video_write_fh->mm.source_fps) {
6794  fps = smh->video_write_fh->mm.source_fps;
6795  }
6796  } else if (video_globals.fps) {
6797  fps = video_globals.fps;
6798  }
6799  switch_calc_video_fps(&fps_data, fps);
6800 
6801  switch_core_timer_init(&timer, "soft", fps_data.ms, fps_data.samples, switch_core_session_get_pool(session));
6802 
6803  if (smh->video_write_fh && smh->video_write_fh->mm.source_kps) {
6804  int min = 0, max = 10000000;
6805  const char *var;
6806 
6807  kps = smh->video_write_fh->mm.source_kps;
6808 
6809  if ((var = switch_channel_get_variable(session->channel, "video_file_min_kps"))) {
6810  min = atoi(var);
6811  if (min < 0) min = 0;
6812  }
6813 
6814  if ((var = switch_channel_get_variable(session->channel, "video_file_max_kps"))) {
6815  max = atoi(var);
6816  if (max < 0) max = 10000000;
6817  }
6818 
6819  if (min && kps < min) kps = min;
6820  if (max != 10000000 && kps > max) kps = max;
6821 
6823  }
6824 
6825  while (smh->video_write_thread_running > 0 &&
6828 
6829  switch_core_timer_next(&timer);
6830 
6832 
6833  //if (smh->video_write_fh && smh->video_write_fh->mm.source_fps && smh->video_write_fh->mm.source_fps != fps) {
6834  // switch_core_timer_destroy(&timer);
6835  // switch_calc_video_fps(&fps_data, fps);
6836  // switch_core_timer_init(&timer, "soft", fps_data.ms, fps_data.samples, switch_core_session_get_pool(session));
6837  //}
6838 
6840  wstatus = switch_core_file_read_video(smh->video_write_fh, &fr, read_flags);
6841 
6842  if (wstatus == SWITCH_STATUS_BREAK) {
6843  switch_core_timer_sync(&timer);
6844  }
6845 
6846  if (wstatus == SWITCH_STATUS_SUCCESS) {
6847  if (!kps && fr.img && (last_w != fr.img->d_w || last_h != fr.img->d_h)) {
6848  kps = switch_calc_bitrate(fr.img->d_w, fr.img->d_h, 1, fps);
6850  last_w = fr.img->d_w;
6851  last_h = fr.img->d_h;
6852  }
6853 
6854  fr.timestamp = timer.samplecount;
6856 
6857  if (fr.img && smh->vid_params.d_width && smh->vid_params.d_height) {
6859  }
6860 
6862 
6863  switch_img_free(&last_frame);
6864  last_frame = fr.img;
6865  fr.img = NULL;
6866 
6867  } else if (wstatus != SWITCH_STATUS_BREAK && wstatus != SWITCH_STATUS_IGNORE) {
6869  }
6870  }
6871 
6873  }
6874 
6875  if (last_frame) {
6876  int x = 0;
6877  switch_rgb_color_t bgcolor;
6878 
6879  switch_color_set_rgb(&bgcolor, "#000000");
6880  switch_img_fill(last_frame, 0, 0, last_frame->d_w, last_frame->d_h, &bgcolor);
6881  fr.img = last_frame;
6882 
6883  for (x = 0; x < (int)(fps_data.fps / 2); x++) {
6884  switch_core_timer_next(&timer);
6885  fr.timestamp = timer.samplecount;
6888  }
6889 
6892  switch_img_free(&last_frame);
6893  }
6894 
6895  switch_core_timer_destroy(&timer);
6896 
6898 
6899  if (b_session) {
6901  switch_core_session_rwunlock(b_session);
6902  }
6903 
6904  v_engine->thread_write_lock = 0;
6906 
6908  smh->video_write_thread_running = 0;
6909 
6910  return NULL;
6911 }
6912 
6914 {
6915  switch_media_handle_t *smh;
6916  switch_rtp_engine_t *v_engine;
6917 
6918  switch_assert(session);
6919 
6920  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
6921  return SWITCH_STATUS_FALSE;
6922  }
6923 
6924  if (!(smh = session->media_handle)) {
6925  return SWITCH_STATUS_FALSE;
6926  }
6927 
6928  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
6929 
6930  if (rw == SWITCH_RW_READ) {
6932  } else {
6934  }
6935 
6936  return SWITCH_STATUS_SUCCESS;
6937 
6938 }
6939 
6941 {
6942  switch_media_handle_t *smh;
6943  switch_rtp_engine_t *v_engine;
6944 
6945  switch_assert(session);
6946 
6947  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
6948  return SWITCH_STATUS_FALSE;
6949  }
6950 
6951  if (!(smh = session->media_handle)) {
6952  return SWITCH_STATUS_FALSE;
6953  }
6954 
6955  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
6956 
6957  if (rw == SWITCH_RW_READ) {
6959  } else {
6961  }
6962 
6963  return SWITCH_STATUS_SUCCESS;
6964 }
6965 
6967 {
6968  switch_media_handle_t *smh;
6969  switch_rtp_engine_t *v_engine;
6970 
6971  switch_assert(session);
6972 
6973  if (!(smh = session->media_handle)) {
6974  return SWITCH_STATUS_FALSE;
6975  }
6976 
6977  if (!smh->video_read_fh && !smh->video_write_fh && !switch_channel_test_flag(session->channel, CF_VIDEO)) {
6978  return SWITCH_STATUS_FALSE;
6979  }
6980 
6981  if (fh && !switch_core_file_has_video(fh, SWITCH_TRUE)) {
6982  return SWITCH_STATUS_FALSE;
6983  }
6984 
6985  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
6986 
6988 
6989  //if (!v_engine->media_thread) {
6990  // return SWITCH_STATUS_FALSE;
6991  //}
6992 
6993 
6994 
6995  if (rw == SWITCH_RW_READ) {
6997 
6998  if (fh && smh->video_read_fh) {
6999  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "File is already open\n");
7001  return SWITCH_STATUS_FALSE;
7002  }
7003 
7004 
7005  if (fh) {
7008  } else if (smh->video_read_fh) {
7011  }
7012 
7013  if (!fh) {
7015  }
7016 
7017  smh->video_read_fh = fh;
7018 
7020 
7021  } else {
7022  if (!fh && smh->video_write_thread) {
7023  if (smh->video_write_thread_running > 0) {
7024  smh->video_write_thread_running = -1;
7025  }
7026  }
7027 
7029 
7030  if (fh && smh->video_write_fh) {
7031  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "File is already open\n");
7032  smh->video_write_fh = fh;
7034  return SWITCH_STATUS_SUCCESS;
7035  }
7036 
7037  if (fh) {
7039  } else {
7041  }
7042 
7045 
7046  if (fh) {
7047  switch_threadattr_t *thd_attr = NULL;
7048  //switch_core_session_write_blank_video(session, 500);
7051  smh->video_write_thread_running = 1;
7053  }
7054 
7055  if (!fh && smh->video_write_thread) {
7056  switch_status_t st;
7057 
7058  if (smh->video_write_thread_running > 0) {
7059  smh->video_write_thread_running = -1;
7060  }
7064  smh->video_write_thread = NULL;
7065  //switch_core_session_write_blank_video(session, 500);
7066  }
7067 
7068  smh->video_write_fh = fh;
7069 
7071  }
7072 
7073  if (!fh) switch_channel_video_sync(session->channel);
7074 
7076 
7077 
7078  return SWITCH_STATUS_SUCCESS;
7079 }
7080 
7081 int next_cpu(void)
7082 {
7083  int x = 0;
7084 
7085  switch_mutex_lock(video_globals.mutex);
7086  x = video_globals.cur_cpu++;
7087  if (video_globals.cur_cpu == video_globals.cpu_count) {
7088  video_globals.cur_cpu = 0;
7089  }
7090  switch_mutex_unlock(video_globals.mutex);
7091  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Binding to CPU %d\n", x);
7092 
7093  return x;
7094 }
7095 
7097 {
7098  if (video_globals.cpu_count > 1) {
7100  }
7101 }
7102 
7104 {
7107  switch_media_handle_t *smh;
7108 
7109  switch_assert(session != NULL);
7110 
7111  if ((smh = session->media_handle)) {
7113 
7114  if (a_engine && a_engine->write_fb && !(flags & SWITCH_IO_FLAG_QUEUED)) {
7115  switch_frame_t *dupframe = NULL;
7116 
7117  if (switch_frame_buffer_dup(a_engine->write_fb, frame, &dupframe) == SWITCH_STATUS_SUCCESS) {
7118  switch_frame_buffer_push(a_engine->write_fb, dupframe);
7119  dupframe = NULL;
7120  return SWITCH_STATUS_SUCCESS;
7121  }
7122  }
7123  }
7124 
7125  if (session->bugs && !(frame->flags & SFF_NOT_AUDIO)) {
7126  switch_media_bug_t *bp;
7128  int prune = 0;
7129 
7131 
7132  for (bp = session->bugs; bp; bp = bp->next) {
7133  ok = SWITCH_TRUE;
7134 
7136  continue;
7137  }
7138 
7140  continue;
7141  }
7142  if (switch_test_flag(bp, SMBF_PRUNE)) {
7143  prune++;
7144  continue;
7145  }
7146 
7147  if (bp->ready) {
7149  if (bp->callback) {
7150  bp->native_write_frame = frame;
7152  bp->native_write_frame = NULL;
7153  }
7154  }
7155  }
7156 
7157  if ((bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) || ok == SWITCH_FALSE) {
7159  prune++;
7160  }
7161  }
7163 
7164  if (prune) {
7165  switch_core_media_bug_prune(session);
7166  }
7167  }
7168 
7169 
7170  if (session->endpoint_interface->io_routines->write_frame) {
7171  if ((status = session->endpoint_interface->io_routines->write_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
7172  for (ptr = session->event_hooks.write_frame; ptr; ptr = ptr->next) {
7173  if ((status = ptr->write_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
7174  break;
7175  }
7176  }
7177  }
7178  }
7179 
7180  return status;
7181 }
7182 
7183 
7185 {
7186  struct media_helper *mh = obj;
7188  switch_media_handle_t *smh;
7189  switch_rtp_engine_t *a_engine = NULL;
7190  switch_codec_implementation_t write_impl;
7191  switch_timer_t timer = {0};
7192 
7194  return NULL;
7195  }
7196 
7197  if (!(smh = session->media_handle)) {
7199  return NULL;
7200  }
7201 
7202  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
7203  a_engine->thread_id = switch_thread_self();
7204 
7205 
7206  write_impl = session->write_impl;
7207 
7208  switch_core_timer_init(&timer, "soft", write_impl.microseconds_per_packet / 1000,
7209  write_impl.samples_per_packet, switch_core_session_get_pool(session));
7210 
7211  mh->up = 1;
7212 
7213  switch_frame_buffer_create(&a_engine->write_fb, 500);
7214 
7215  while(switch_channel_up_nosig(session->channel) && mh->up == 1) {
7216  void *pop;
7217 
7218  if (session->write_impl.microseconds_per_packet != write_impl.microseconds_per_packet ||
7219  session->write_impl.samples_per_packet != write_impl.samples_per_packet) {
7220 
7221 
7222  write_impl = session->write_impl;
7223  switch_core_timer_destroy(&timer);
7224  switch_core_timer_init(&timer, "soft", write_impl.microseconds_per_packet / 1000,
7225  write_impl.samples_per_packet, switch_core_session_get_pool(session));
7226 
7227  }
7228 
7229  switch_core_timer_next(&timer);
7230 
7231  if (switch_frame_buffer_trypop(a_engine->write_fb, &pop) == SWITCH_STATUS_SUCCESS && pop) {
7232  switch_frame_t *frame = (switch_frame_t *)pop;
7233 
7234  if ((switch_size_t)pop == 1) {
7235  break;
7236  }
7237 
7238  perform_write(session, frame, SWITCH_IO_FLAG_QUEUED, 0);
7239  switch_frame_buffer_free(a_engine->write_fb, &frame);
7240  }
7241  }
7242 
7244  mh->up = 0;
7246 
7247  switch_core_timer_destroy(&timer);
7248 
7250  return NULL;
7251 }
7252 
7254 {
7255  switch_threadattr_t *thd_attr = NULL;
7257  switch_rtp_engine_t *a_engine = NULL;
7258  switch_media_handle_t *smh;
7259 
7260  if (!switch_channel_test_flag(session->channel, CF_AUDIO)) {
7261  return SWITCH_STATUS_NOTIMPL;
7262  }
7263 
7264  if (!(smh = session->media_handle)) {
7265  return SWITCH_STATUS_FALSE;
7266  }
7267 
7268  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
7269 
7270  if (a_engine->media_thread) {
7271  return SWITCH_STATUS_INUSE;
7272  }
7273 
7275 
7276  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Starting Audio write thread\n", switch_core_session_get_name(session));
7277 
7278  a_engine->mh.session = session;
7279  switch_threadattr_create(&thd_attr, pool);
7281 
7282  switch_thread_cond_create(&a_engine->mh.cond, pool);
7284  switch_thread_create(&a_engine->media_thread, thd_attr, audio_write_thread, &a_engine->mh, switch_core_session_get_pool(session));
7285 
7287  return SWITCH_STATUS_SUCCESS;
7288 }
7289 
7290 
7291 
7293 {
7294  struct media_helper *mh = obj;
7296  switch_channel_t *channel;
7297  switch_status_t status;
7298  switch_frame_t *read_frame = NULL;
7299  switch_media_handle_t *smh;
7300  switch_rtp_engine_t *t_engine = NULL;
7301  unsigned char CR[] = TEXT_UNICODE_LINEFEED;
7302  switch_frame_t cr_frame = { 0 };
7303 
7304 
7305  session = mh->session;
7306 
7308  mh->ready = -1;
7309  return NULL;
7310  }
7311 
7312  if (!(smh = session->media_handle)) {
7314  mh->ready = -1;
7315  return NULL;
7316  }
7317 
7318  mh->ready = 1;
7319 
7320  channel = switch_core_session_get_channel(session);
7321 
7322  if (switch_channel_var_true(session->channel, "fire_text_events")) {
7324  }
7325 
7326  cr_frame.data = CR;
7327  cr_frame.datalen = 3;
7328 
7329  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
7330  t_engine->thread_id = switch_thread_self();
7331 
7332  mh->up = 1;
7333 
7335 
7336  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Text thread started.\n", switch_channel_get_name(session->channel));
7337 
7338  if (!switch_channel_test_flag(channel, CF_MSRP)) {
7339  switch_core_session_write_text_frame(session, &cr_frame, 0, 0);
7340  }
7341 
7342  while (switch_channel_up_nosig(channel)) {
7343 
7344  if (t_engine->engine_function) {
7345  int run = 0;
7346 
7348  if (t_engine->engine_function_running == 0) {
7349  t_engine->engine_function_running = 1;
7350  run = 1;
7351  }
7353 
7354  if (run) {
7355  t_engine->engine_function(session, t_engine->engine_user_data);
7357  t_engine->engine_function = NULL;
7358  t_engine->engine_user_data = NULL;
7359  t_engine->engine_function_running = 0;
7361  }
7362  }
7363 
7365 
7366  status = switch_core_session_read_text_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
7367 
7368  if (!SWITCH_READ_ACCEPTABLE(status)) {
7369  switch_cond_next();
7370  continue;
7371  }
7372 
7373  if (!switch_test_flag(read_frame, SFF_CNG)) {
7375  switch_core_session_write_text_frame(session, read_frame, 0, 0);
7376  }
7377  }
7378  }
7379 
7380  switch_core_session_write_text_frame(session, NULL, 0, 0);
7381 
7382 
7383  }
7384 
7386 
7388 
7389  mh->up = 0;
7390  return NULL;
7391 }
7392 
7393 
7395 {
7396  switch_threadattr_t *thd_attr = NULL;
7398  switch_rtp_engine_t *t_engine = NULL;
7399  switch_media_handle_t *smh;
7400 
7401  if (!switch_channel_test_flag(session->channel, CF_HAS_TEXT)) {
7402  return SWITCH_STATUS_NOTIMPL;
7403  }
7404 
7405  if (!(smh = session->media_handle)) {
7406  return SWITCH_STATUS_FALSE;
7407  }
7408 
7409  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
7410 
7412 
7413  if (t_engine->media_thread) {
7415  return SWITCH_STATUS_FALSE;
7416  }
7417 
7418  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Starting Text thread\n", switch_core_session_get_name(session));
7419 
7420  if (t_engine->rtp_session) {
7422  }
7423 
7424  t_engine->mh.session = session;
7425  switch_threadattr_create(&thd_attr, pool);
7427 
7428  switch_thread_cond_create(&t_engine->mh.cond, pool);
7430  //switch_mutex_init(&t_engine->mh.file_read_mutex, SWITCH_MUTEX_NESTED, pool);
7431  //switch_mutex_init(&t_engine->mh.file_write_mutex, SWITCH_MUTEX_NESTED, pool);
7432  //switch_mutex_init(&smh->read_mutex[SWITCH_MEDIA_TYPE_TEXT], SWITCH_MUTEX_NESTED, pool);
7433  //switch_mutex_init(&smh->write_mutex[SWITCH_MEDIA_TYPE_TEXT], SWITCH_MUTEX_NESTED, pool);
7434 
7435  t_engine->mh.ready = 0;
7436 
7437  if (switch_thread_create(&t_engine->media_thread, thd_attr, text_helper_thread, &t_engine->mh,
7439  while(!t_engine->mh.ready) {
7440  switch_cond_next();
7441  }
7442  }
7443 
7445  return SWITCH_STATUS_SUCCESS;
7446 }
7447 
7449 {
7450  struct media_helper *mh = obj;
7452  switch_channel_t *channel;
7453  switch_status_t status;
7454  switch_frame_t *read_frame = NULL;
7455  switch_media_handle_t *smh;
7456  uint32_t loops = 0, xloops = 0;
7457  switch_image_t *blank_img = NULL;
7458  switch_frame_t fr = { 0 };
7459  unsigned char *buf = NULL;
7460  switch_rgb_color_t bgcolor;
7461  switch_rtp_engine_t *v_engine = NULL;
7462  const char *var;
7464  int blank_enabled = 1;
7465 
7466  session = mh->session;
7467 
7469  mh->ready = -1;
7470  return NULL;
7471  }
7472 
7473  if (!(smh = session->media_handle)) {
7475  mh->ready = -1;
7476  return NULL;
7477  }
7478 
7479  mh->ready = 1;
7480 
7481  channel = switch_core_session_get_channel(session);
7482 
7484 
7485  if ((var = switch_channel_get_variable(session->channel, "core_video_blank_image"))) {
7486  if (switch_false(var)) {
7487  blank_enabled = 0;
7488  } else {
7489  blank_img = switch_img_read_png(var, SWITCH_IMG_FMT_I420);
7490  }
7491  }
7492 
7493  if (!blank_img) {
7494  switch_color_set_rgb(&bgcolor, "#000000");
7495  if ((blank_img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, 352, 288, 1))) {
7496  switch_img_fill(blank_img, 0, 0, blank_img->d_w, blank_img->d_h, &bgcolor);
7497  }
7498  }
7499 
7500 
7501 
7502  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
7503  v_engine->thread_id = switch_thread_self();
7504 
7505  mh->up = 1;
7507 
7509 
7510  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread started. Echo is %s\n",
7511  switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
7513 
7514  buf = switch_core_session_alloc(session, buflen);
7515  fr.packet = buf;
7516  fr.packetlen = buflen;
7517  fr.data = buf + 12;
7518  fr.buflen = buflen - 12;
7519 
7521 
7522  while (switch_channel_up_nosig(channel)) {
7523  int send_blank = 0;
7524 
7525  if (!switch_channel_test_flag(channel, CF_VIDEO)) {
7526  if ((++loops % 100) == 0) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Waiting for video......\n");
7527  switch_yield(20000);
7528  continue;
7529  }
7530 
7531  if (!switch_channel_test_flag(channel, CF_VIDEO_READY) &&
7534  }
7535 
7537  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread paused. Echo is %s\n",
7538  switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
7540  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread resumed Echo is %s\n",
7541  switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
7543  }
7544 
7546  continue;
7547  }
7548 
7549  if (!switch_channel_media_up(session->channel)) {
7550  switch_yield(10000);
7551  continue;
7552  }
7553 
7554  if (v_engine->engine_function) {
7555  int run = 0;
7556 
7558  if (v_engine->engine_function_running == 0) {
7559  v_engine->engine_function_running = 1;
7560  run = 1;
7561  }
7563 
7564  if (run) {
7565  v_engine->engine_function(session, v_engine->engine_user_data);
7567  v_engine->engine_function = NULL;
7568  v_engine->engine_user_data = NULL;
7569  v_engine->engine_function_running = 0;
7571  }
7572  }
7573 
7574  status = switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
7575 
7576  if (!SWITCH_READ_ACCEPTABLE(status)) {
7577  switch_cond_next();
7578  continue;
7579  }
7580 
7581  send_blank = blank_enabled || switch_channel_test_flag(channel, CF_VIDEO_ECHO);
7582 
7583  if (switch_channel_test_flag(channel, CF_VIDEO_READY) && !switch_test_flag(read_frame, SFF_CNG)) {
7585  if (smh->video_read_fh && switch_test_flag(smh->video_read_fh, SWITCH_FILE_OPEN) && read_frame->img) {
7586  smh->video_read_fh->mm.fps = smh->vid_params.fps;
7587  switch_core_file_write_video(smh->video_read_fh, read_frame);
7588  }
7590  }
7591 
7593  send_blank = 0;
7594  }
7595 
7596  if (send_blank) {
7597  if (read_frame && (switch_channel_test_flag(channel, CF_VIDEO_ECHO))) {
7599  } else if (blank_img) {
7600  fr.img = blank_img;
7601  switch_yield(10000);
7603  }
7604  }
7605  }
7606 
7607  switch_img_free(&blank_img);
7608 
7610 
7613 
7614  mh->up = 0;
7615  return NULL;
7616 }
7617 
7619 {
7620  switch_threadattr_t *thd_attr = NULL;
7622  switch_rtp_engine_t *v_engine = NULL;
7623  switch_media_handle_t *smh;
7624 
7625  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
7626  return SWITCH_STATUS_NOTIMPL;
7627  }
7628 
7629  if (!(smh = session->media_handle)) {
7630  return SWITCH_STATUS_FALSE;
7631  }
7632 
7633  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
7634 
7636 
7637  if (v_engine->media_thread) {
7639  return SWITCH_STATUS_FALSE;
7640  }
7641 
7642  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Starting Video thread\n", switch_core_session_get_name(session));
7643 
7644  if (v_engine->rtp_session) {
7646  }
7647 
7648  v_engine->mh.session = session;
7649  switch_threadattr_create(&thd_attr, pool);
7651 
7652  switch_thread_cond_create(&v_engine->mh.cond, pool);
7658  v_engine->mh.ready = 0;
7659 
7660  if (switch_thread_create(&v_engine->media_thread, thd_attr, video_helper_thread, &v_engine->mh,
7662  while(!v_engine->mh.ready) {
7663  switch_cond_next();
7664  }
7665  }
7666 
7668  return SWITCH_STATUS_SUCCESS;
7669 }
7670 
7672 {
7673  switch_media_handle_t *smh;
7674  switch_rtp_engine_t *engine;
7675 
7676  if (!(smh = session->media_handle)) {
7677  return;
7678  }
7679 
7680  engine = &smh->engines[type];
7681 
7682  if (type == SWITCH_MEDIA_TYPE_VIDEO) {
7684  }
7685 
7686  if (type == SWITCH_MEDIA_TYPE_TEXT) {
7688  }
7689 
7691  if (!engine->engine_function_running) {
7692  engine->engine_function = engine_function;
7693  engine->engine_user_data = user_data;
7695  }
7697 }
7698 
7700 {
7701  switch_media_handle_t *smh;
7702  int r;
7703  switch_rtp_engine_t *engine;
7704 
7705  if (!(smh = session->media_handle)) {
7706  return 0;
7707  }
7708 
7709  engine = &smh->engines[type];
7710 
7712  r = (engine->engine_function_running > 0);
7714 
7715  return r;
7716 }
7717 
7719 {
7720  switch_media_handle_t *smh;
7721  switch_rtp_engine_t *engine;
7722 
7723  if (!(smh = session->media_handle)) {
7724  return;
7725  }
7726 
7727  engine = &smh->engines[type];
7728 
7730  if (engine->engine_function_running > 0) {
7731  engine->engine_function_running = -1;
7732  }
7734 
7735  while(engine->engine_function_running != 0) {
7736  switch_yield(10000);
7737  }
7738 }
7739 
7741 {
7742  switch_rtp_engine_t *v_engine;
7743  switch_media_handle_t *smh;
7744 
7745  switch_assert(session);
7746 
7747  if (!(smh = session->media_handle)) {
7748  return SWITCH_FALSE;
7749  }
7750 
7751  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
7752 
7754 }
7755 
7756 
7758 {
7759  const char *var;
7760  switch_media_handle_t *smh;
7761 
7762  if (!(smh = session->media_handle)) {
7763  return;
7764  }
7765 
7766  if ((var = switch_channel_get_variable(session->channel, "rtp_media_autofix_timing"))) {
7767  if (switch_true(var)) {
7769  } else {
7771  }
7772  }
7773 }
7774 
7775 //?
7776 #define RA_PTR_LEN 512
7778 {
7779  const char *err;
7780  char rip[RA_PTR_LEN] = "";
7781  char rp[RA_PTR_LEN] = "";
7782  char rvp[RA_PTR_LEN] = "";
7783  char rtp[RA_PTR_LEN] = "";
7784  char *p, *ip_ptr = NULL, *port_ptr = NULL, *vid_port_ptr = NULL, *text_port_ptr = NULL, *pe;
7785  int x;
7786  const char *val;
7788  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
7789  switch_media_handle_t *smh;
7790 
7791  switch_assert(session);
7792 
7793  if (!(smh = session->media_handle)) {
7794  return SWITCH_STATUS_FALSE;
7795  }
7796 
7797  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
7798  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
7799  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
7800 
7801  if (zstr(sdp_str)) {
7802  sdp_str = smh->mparams->remote_sdp_str;
7803  }
7804 
7805  if (zstr(sdp_str)) {
7806  goto end;
7807  }
7808 
7809  if ((p = (char *) switch_stristr("c=IN IP4 ", sdp_str)) || (p = (char *) switch_stristr("c=IN IP6 ", sdp_str))) {
7810  ip_ptr = p + 9;
7811  }
7812 
7813  if ((p = (char *) switch_stristr("m=audio ", sdp_str))) {
7814  port_ptr = p + 8;
7815  }
7816 
7817  if ((p = (char *) switch_stristr("m=image ", sdp_str))) {
7818  char *tmp = p + 8;
7819 
7820  if (tmp && atoi(tmp)) {
7821  port_ptr = tmp;
7822  }
7823  }
7824 
7825  if ((p = (char *) switch_stristr("m=video ", sdp_str))) {
7826  vid_port_ptr = p + 8;
7827  }
7828 
7829  if ((p = (char *) switch_stristr("m=text ", sdp_str))) {
7830  text_port_ptr = p + 7;
7831  }
7832 
7833  if (!(ip_ptr && port_ptr)) {
7834  goto end;
7835  }
7836 
7837  p = ip_ptr;
7838  pe = p + strlen(p);
7839  x = 0;
7840  while (x < sizeof(rip) - 1 && p && *p && ((*p >= '0' && *p <= '9') || *p == '.' || *p == ':' || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F'))) {
7841  rip[x++] = *p;
7842  p++;
7843  if (p >= pe) {
7844  goto end;
7845  }
7846  }
7847 
7848  if (port_ptr) {
7849  p = port_ptr;
7850  x = 0;
7851  while (x < sizeof(rp) - 1 && p && *p && (*p >= '0' && *p <= '9')) {
7852  rp[x++] = *p;
7853  p++;
7854  if (p >= pe) {
7855  goto end;
7856  }
7857  }
7858  }
7859 
7860  if (vid_port_ptr) {
7861  p = vid_port_ptr;
7862  x = 0;
7863  while (x < sizeof(rvp) - 1 && p && *p && (*p >= '0' && *p <= '9')) {
7864  rvp[x++] = *p;
7865  p++;
7866  if (p >= pe) {
7867  goto end;
7868  }
7869  }
7870  }
7871 
7872  if (text_port_ptr) {
7873  p = text_port_ptr;
7874  x = 0;
7875  while (x < sizeof(rtp) - 1 && p && *p && (*p >= '0' && *p <= '9')) {
7876  rtp[x++] = *p;
7877  p++;
7878  if (p >= pe) {
7879  goto end;
7880  }
7881  }
7882  }
7883 
7884  if (!(*rip && *rp)) {
7886  goto end;
7887  }
7888 
7889  a_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, rip);
7890  a_engine->cur_payload_map->remote_sdp_port = (switch_port_t) atoi(rp);
7891 
7892  if (*rvp) {
7893  v_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, rip);
7894  v_engine->cur_payload_map->remote_sdp_port = (switch_port_t) atoi(rvp);
7897  }
7898 
7899  if (*rtp) {
7900  t_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, rip);
7901  t_engine->cur_payload_map->remote_sdp_port = (switch_port_t) atoi(rtp);
7904  }
7905 
7906  if (v_engine->cur_payload_map && v_engine->cur_payload_map->remote_sdp_ip && v_engine->cur_payload_map->remote_sdp_port) {
7907  if (!strcmp(v_engine->cur_payload_map->remote_sdp_ip, rip) && atoi(rvp) == v_engine->cur_payload_map->remote_sdp_port) {
7908  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote video address:port [%s:%d] has not changed.\n",
7910  } else {
7913  if (switch_rtp_ready(v_engine->rtp_session)) {
7914  const char *rport = NULL;
7915  switch_port_t remote_rtcp_port = v_engine->remote_rtcp_port;
7916 
7917  if (!remote_rtcp_port) {
7918  if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_video_rtcp_port"))) {
7919  remote_rtcp_port = (switch_port_t)atoi(rport);
7920  }
7921  }
7922 
7923 
7925  v_engine->cur_payload_map->remote_sdp_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
7926  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", err);
7927  } else {
7928  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "VIDEO RTP CHANGING DEST TO: [%s:%d]\n",
7931  v_engine->check_frames = 0;
7932  }
7933  }
7934  }
7935  }
7937  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
7938  v_engine->rtp_session &&
7940  /* Reactivate the NAT buster flag. */
7942  }
7943  }
7944 
7945  if (t_engine->cur_payload_map && t_engine->cur_payload_map->remote_sdp_ip && t_engine->cur_payload_map->remote_sdp_port) {
7946  if (!strcmp(t_engine->cur_payload_map->remote_sdp_ip, rip) && atoi(rvp) == t_engine->cur_payload_map->remote_sdp_port) {
7947  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote text address:port [%s:%d] has not changed.\n",
7949  } else {
7952  if (switch_rtp_ready(t_engine->rtp_session)) {
7953  const char *rport = NULL;
7954  switch_port_t remote_rtcp_port = t_engine->remote_rtcp_port;
7955 
7956  if (!remote_rtcp_port) {
7957  if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_text_rtcp_port"))) {
7958  remote_rtcp_port = (switch_port_t)atoi(rport);
7959  }
7960  }
7961 
7962 
7964  t_engine->cur_payload_map->remote_sdp_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
7965  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "TEXT RTP REPORTS ERROR: [%s]\n", err);
7966  } else {
7967  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "TEXT RTP CHANGING DEST TO: [%s:%d]\n",
7970  t_engine->check_frames = 0;
7971  }
7972  }
7973  }
7974  }
7976  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
7977  t_engine->rtp_session &&
7979  /* Reactivate the NAT buster flag. */
7981  }
7982  }
7983 
7984  if (switch_rtp_ready(a_engine->rtp_session)) {
7985  char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
7986  switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
7987  const char *rport = NULL;
7988  switch_port_t remote_rtcp_port = 0;
7989 
7990  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) {
7991  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote address:port [%s:%d] has not changed.\n",
7994  } else if (remote_host && ( (strcmp(remote_host, "0.0.0.0") == 0) ||
7995  (strcmp(a_engine->cur_payload_map->remote_sdp_ip, "0.0.0.0") == 0))) {
7996 
7998  "Remote address changed from [%s] to [%s]. Ignoring...\n",
7999  a_engine->cur_payload_map->remote_sdp_ip, remote_host);
8001  }
8002 
8003  if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_audio_rtcp_port"))) {
8004  remote_rtcp_port = (switch_port_t)atoi(rport);
8005  }
8006 
8007 
8009  a_engine->cur_payload_map->remote_sdp_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
8010  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
8011  status = SWITCH_STATUS_GENERR;
8012  } else {
8013  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n",
8016  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
8018  /* Reactivate the NAT buster flag. */
8020  }
8022  a_engine->check_frames = 0;
8023  }
8024  status = SWITCH_STATUS_SUCCESS;
8025  }
8026  }
8027 
8028  end:
8029 
8030  return status;
8031 }
8032 
8033 //?
8035 {
8036  switch_assert(network_ip);
8037 
8038  return (smh->mparams->extsipip &&
8039  !switch_check_network_list_ip(network_ip, "loopback.auto") &&
8040  !switch_check_network_list_ip(network_ip, smh->mparams->local_network));
8041 }
8042 
8043 //?
8045 
8046 {
8047  char *error = "";
8049  int x;
8050  switch_port_t myport = *port;
8052  char *stun_ip = NULL;
8053  switch_media_handle_t *smh;
8055 
8056  switch_assert(session);
8057 
8058  if (!(smh = session->media_handle)) {
8059  return SWITCH_STATUS_FALSE;
8060  }
8061 
8062  if (!sourceip) {
8063  return status;
8064  }
8065 
8066  if (!strncasecmp(sourceip, "host:", 5)) {
8067  status = (*ip = switch_stun_host_lookup(sourceip + 5, pool)) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
8068  } else if (!strncasecmp(sourceip, "stun:", 5)) {
8069  char *p;
8070 
8071  stun_ip = strdup(sourceip + 5);
8072 
8073  if ((p = strchr(stun_ip, ':'))) {
8074  int iport;
8075  *p++ = '\0';
8076  iport = atoi(p);
8077  if (iport > 0 && iport < 0xFFFF) {
8078  stun_port = (switch_port_t) iport;
8079  }
8080  }
8081 
8082  if (zstr(stun_ip)) {
8083  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! NO STUN SERVER\n");
8084  goto out;
8085  }
8086 
8087  for (x = 0; x < 5; x++) {
8088  if ((status = switch_stun_lookup(ip, port, stun_ip, stun_port, &error, pool)) != SWITCH_STATUS_SUCCESS) {
8089  switch_yield(100000);
8090  } else {
8091  break;
8092  }
8093  }
8094  if (status != SWITCH_STATUS_SUCCESS) {
8095  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! %s:%d [%s]\n", stun_ip, stun_port, error);
8096  goto out;
8097  }
8098  if (!*ip) {
8099  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! No IP returned\n");
8100  goto out;
8101  }
8102  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "STUN Success [%s]:[%d]\n", *ip, *port);
8103  status = SWITCH_STATUS_SUCCESS;
8104 
8105  if (myport == *port && !strcmp(*ip, smh->mparams->rtpip)) {
8106  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "STUN Not Required ip and port match. [%s]:[%d]\n", *ip, *port);
8107  } else {
8108  smh->mparams->stun_ip = switch_core_session_strdup(session, stun_ip);
8109  smh->mparams->stun_port = stun_port;
8110  smh->mparams->stun_flags |= STUN_FLAG_SET;
8111  }
8112  } else {
8113  *ip = (char *) sourceip;
8114  status = SWITCH_STATUS_SUCCESS;
8115  }
8116 
8117  out:
8118 
8119  switch_safe_free(stun_ip);
8120 
8121  return status;
8122 }
8123 
8124 //?
8126 {
8127  switch_rtp_engine_t *engine;
8128  switch_media_handle_t *smh;
8129 
8130  switch_assert(session);
8131 
8132  if (!(smh = session->media_handle)) {
8133  return;
8134  }
8135 
8136  engine = &smh->engines[type];
8137 
8138  engine->check_frames = 0;
8139  engine->last_ts = 0;
8140  engine->last_seq = 0;
8141 }
8142 
8143 
8144 
8145 //?
8147 {
8148  char *lookup_rtpip; /* Pointer to externally looked up address */
8149  switch_port_t sdp_port; /* The external port to be sent in the SDP */
8150  const char *use_ip = NULL; /* The external IP to be sent in the SDP */
8151  switch_rtp_engine_t *engine;
8152  switch_media_handle_t *smh;
8153  const char *tstr = switch_media_type2str(type);
8154  char vname[128] = "";
8155 
8156  switch_assert(session);
8157 
8158  if (!(smh = session->media_handle)) {
8159  return SWITCH_STATUS_FALSE;
8160  }
8161 
8162  engine = &smh->engines[type];
8163 
8164  lookup_rtpip = smh->mparams->rtpip;
8165 
8166  if (!lookup_rtpip) {
8167  return SWITCH_STATUS_FALSE;
8168  }
8169 
8170  /* Don't do anything if we're in proxy mode or if a (remote) port already has been found */
8171  if (!force) {
8174  return SWITCH_STATUS_SUCCESS;
8175  }
8176  }
8177 
8178  /* Always too late when RTP has already started */
8179  if (engine->rtp_session) {
8180  return SWITCH_STATUS_SUCCESS;
8181  }
8182 
8183  /* Release the local sdp port */
8184  if (engine->local_sdp_port) {
8186  }
8187 
8188  /* Request a local port from the core's allocator */
8189  if (!(engine->local_sdp_port = switch_rtp_request_port(smh->mparams->rtpip))) {
8190  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "No %s RTP ports available!\n", tstr);
8191  return SWITCH_STATUS_FALSE;
8192  }
8193 
8194  engine->local_sdp_ip = smh->mparams->rtpip;
8195 
8196 
8197  sdp_port = engine->local_sdp_port;
8198 
8199  /* Check if NAT is detected */
8200  if (!zstr(smh->mparams->remote_ip) && switch_core_media_check_nat(smh, smh->mparams->remote_ip)) {
8201  /* Yes, map the port through switch_nat */
8203 
8204  switch_snprintf(vname, sizeof(vname), "rtp_adv_%s_ip", tstr);
8205 
8206  /* Find an IP address to use */
8207  if (!(use_ip = switch_channel_get_variable(session->channel, vname))
8208  && !zstr(smh->mparams->extrtpip)) {
8209  use_ip = smh->mparams->extrtpip;
8210  }
8211 
8212  if (use_ip) {
8213  if (switch_core_media_ext_address_lookup(session, &lookup_rtpip, &sdp_port, use_ip) != SWITCH_STATUS_SUCCESS) {
8214  /* Address lookup was required and fail (external ip was "host:..." or "stun:...") */
8215  return SWITCH_STATUS_FALSE;
8216  } else {
8217  /* Address properly resolved, use it as external ip */
8218  use_ip = lookup_rtpip;
8219  }
8220  } else {
8221  /* No external ip found, use the profile's rtp ip */
8222  use_ip = smh->mparams->rtpip;
8223  }
8224  } else {
8225  /* No NAT traversal required, use the profile's rtp ip */
8226  use_ip = smh->mparams->rtpip;
8227  }
8228 
8229  if (zstr(smh->mparams->remote_ip)) { /* no remote_ip, we're originating */
8230  if (!zstr(smh->mparams->extrtpip)) { /* and we've got an ext-rtp-ip, eg, from verto config */
8231  use_ip = smh->mparams->extrtpip; /* let's use it for composing local sdp to send to client */
8232  /*
8233  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
8234  "%s will use %s instead of %s in SDP, because we're originating and we have an ext-rtp-ip setting\n",
8235  switch_channel_get_name(smh->session->channel), smh->mparams->extrtpip, smh->mparams->rtpip);
8236  */
8237  }
8238  }
8239  engine->adv_sdp_port = sdp_port;
8240  engine->adv_sdp_ip = smh->mparams->adv_sdp_audio_ip = smh->mparams->extrtpip = switch_core_session_strdup(session, use_ip);
8241 
8242  if (type == SWITCH_MEDIA_TYPE_AUDIO) {
8246  } else if (type == SWITCH_MEDIA_TYPE_VIDEO) {
8249  } else if (type == SWITCH_MEDIA_TYPE_TEXT) {
8252  }
8253 
8254 
8255  return SWITCH_STATUS_SUCCESS;
8256 }
8257 
8259 {
8261  switch_media_handle_t *smh;
8262 
8263  if (!(smh = session->media_handle)) {
8264  return SWITCH_STATUS_FALSE;
8265  }
8266 
8267  if (zstr(smh->mparams->rtpip)) {
8268 
8269  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no media ip\n",
8272 
8273  return SWITCH_STATUS_FALSE;
8274  }
8275 
8276  if (audio && (status = switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_AUDIO, 0)) == SWITCH_STATUS_SUCCESS) {
8277  if (video) {
8281  }
8282  }
8283  }
8284 
8285  return status;
8286 }
8287 
8288 
8289 
8290 //?
8292 {
8293  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
8294  switch_media_handle_t *smh;
8295 
8296  switch_assert(session);
8297 
8298  if (!(smh = session->media_handle)) {
8299  return;
8300  }
8301 
8302  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
8303  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
8304  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
8305 
8306  if (t_engine->tf) {
8307  switch_rtp_text_factory_destroy(&t_engine->tf);
8308  }
8309 
8310  if (a_engine->media_thread) {
8311  switch_status_t st;
8312 
8314  if (a_engine->mh.up && a_engine->write_fb) {
8315  switch_frame_buffer_push(a_engine->write_fb, (void *) 1);
8316  }
8317  a_engine->mh.up = 0;
8319 
8320  switch_thread_join(&st, a_engine->media_thread);
8321  a_engine->media_thread = NULL;
8322  }
8323 
8324  if (v_engine->media_thread) {
8325  switch_status_t st;
8327 
8328  v_engine->mh.up = 0;
8329  switch_thread_join(&st, v_engine->media_thread);
8330  v_engine->media_thread = NULL;
8331  }
8332 
8333  if (v_engine->rtp_session) {
8334  switch_rtp_destroy(&v_engine->rtp_session);
8335  } else if (v_engine->local_sdp_port) {
8337  }
8338 
8339 
8340  if (v_engine->local_sdp_port > 0 && !zstr(smh->mparams->remote_ip) &&
8344  }
8345 
8346 
8347  if (t_engine->media_thread) {
8348  switch_status_t st;
8349 
8350  t_engine->mh.up = 0;
8351  switch_thread_join(&st, t_engine->media_thread);
8352  t_engine->media_thread = NULL;
8353  }
8354 
8355 
8356  if (t_engine->rtp_session) {
8357  switch_rtp_destroy(&t_engine->rtp_session);
8358  } else if (t_engine->local_sdp_port) {
8360  }
8361 
8362 
8363  if (t_engine->local_sdp_port > 0 && !zstr(smh->mparams->remote_ip) &&
8367  }
8368 
8369 
8370  if (a_engine->rtp_session) {
8371  switch_rtp_destroy(&a_engine->rtp_session);
8372  } else if (a_engine->local_sdp_port) {
8374  }
8375 
8376  if (a_engine->local_sdp_port > 0 && !zstr(smh->mparams->remote_ip) &&
8380  }
8381 
8382 }
8383 
8384 
8385 //?
8387 {
8388  switch_media_handle_t *smh;
8389  switch_rtp_engine_t *engine;
8390  char tmp[33] = "";
8391 
8392  switch_assert(session);
8393 
8394  if (!(smh = session->media_handle)) {
8395  return;
8396  }
8397 
8398  engine = &smh->engines[type];
8399 
8400  //#ifdef RTCP_MUX
8401  //if (!engine->rtcp_mux) {// && type == SWITCH_MEDIA_TYPE_AUDIO) {
8402  // engine->rtcp_mux = SWITCH_TRUE;
8403  //}
8404  //#endif
8405 
8406  if (!smh->msid) {
8407  switch_stun_random_string(tmp, 32, NULL);
8408  tmp[32] = '\0';
8409  smh->msid = switch_core_session_strdup(session, tmp);
8410  }
8411 
8412  if (!smh->cname) {
8413  switch_stun_random_string(tmp, 16, NULL);
8414  tmp[16] = '\0';
8415  smh->cname = switch_core_session_strdup(session, tmp);
8416  }
8417 
8418  if (type == SWITCH_MEDIA_TYPE_VIDEO && switch_channel_var_true(switch_core_session_get_channel(session), "video_use_audio_ice")) {
8419  switch_rtp_engine_t *audio_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
8420 
8421  if (audio_engine->ice_out.ufrag) {
8422  engine->ice_out.ufrag = switch_core_session_strdup(session, audio_engine->ice_out.ufrag);
8423  }
8424 
8425  if (audio_engine->ice_out.pwd) {
8426  engine->ice_out.pwd = switch_core_session_strdup(session, audio_engine->ice_out.pwd);
8427  }
8428  }
8429 
8430  if (!engine->ice_out.ufrag) {
8431  switch_stun_random_string(tmp, 16, NULL);
8432  tmp[16] = '\0';
8433  engine->ice_out.ufrag = switch_core_session_strdup(session, tmp);
8434  }
8435 
8436  if (!engine->ice_out.pwd) {
8437  switch_stun_random_string(tmp, 24, NULL);
8438  tmp[24] = '\0';
8439  engine->ice_out.pwd = switch_core_session_strdup(session, tmp);
8440  }
8441 
8442  if (!engine->ice_out.cands[0][0].foundation) {
8443  switch_stun_random_string(tmp, 10, "0123456789");
8444  tmp[10] = '\0';
8445  engine->ice_out.cands[0][0].foundation = switch_core_session_strdup(session, tmp);
8446  }
8447 
8448  engine->ice_out.cands[0][0].transport = "udp";
8449 
8450  if (!engine->ice_out.cands[0][0].component_id) {
8451  engine->ice_out.cands[0][0].component_id = 1;
8452  engine->ice_out.cands[0][0].priority = (1<<24)*126 + (1<<8)*65535 + (1<<0)*(256 - engine->ice_out.cands[0][0].component_id);
8453  }
8454 
8455  if (!zstr(ip)) {
8456  engine->ice_out.cands[0][0].con_addr = switch_core_session_strdup(session, ip);
8457  }
8458 
8459  if (port) {
8460  engine->ice_out.cands[0][0].con_port = port;
8461  }
8462 
8463  engine->ice_out.cands[0][0].generation = "0";
8464  //add rport stuff later
8465 
8466  engine->ice_out.cands[0][0].ready = 1;
8467 
8468 
8469 }
8470 
8472 {
8473  switch_media_handle_t *smh;
8474  switch_rtp_engine_t *v_engine;
8475 
8476  if (!(smh = session->media_handle)) {
8477  return;
8478  }
8479 
8480  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
8481 
8482  if ((!smh->mparams->external_video_source) && (!v_engine->rtp_session)) {
8483  return;
8484  }
8485 
8486  if (!v_engine->media_thread) {
8487  return;
8488  }
8489 
8490  if (!v_engine->mh.cond_mutex) {
8491  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Channel %s has no cond?\n",
8492  switch_channel_get_name(session->channel));
8493  return;
8494  }
8495 
8498  switch_mutex_unlock(v_engine->mh.cond_mutex);
8499  }
8500 }
8501 
8503 {
8504  if (switch_channel_test_flag(session->channel, CF_REINVITE) && engine->new_dtls) {
8505 
8506  if (!zstr(engine->local_dtls_fingerprint.str) && switch_rtp_has_dtls() && dtls_ok(session)) {
8507 
8508 #ifdef HAVE_OPENSSL_DTLSv1_2_method
8509  uint8_t want_DTLSv1_2 = 1;
8510 #else
8511  uint8_t want_DTLSv1_2 = 0;
8512 #endif // HAVE_OPENSSL_DTLSv1_2_method
8513 
8514  dtls_type_t xtype, dtype = engine->dtls_controller ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
8515 
8516  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "RE-SETTING %s DTLS\n", type2str(engine->type));
8517 
8518  xtype = DTLS_TYPE_RTP;
8519  if (engine->rtcp_mux > 0) xtype |= DTLS_TYPE_RTCP;
8520 
8521  if (switch_channel_var_true(session->channel, "legacyDTLS")) {
8523  want_DTLSv1_2 = 0;
8524  }
8525 
8526  switch_rtp_add_dtls(engine->rtp_session, &engine->local_dtls_fingerprint, &engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2);
8527 
8528  if (engine->rtcp_mux < 1) {
8529  xtype = DTLS_TYPE_RTCP;
8530  switch_rtp_add_dtls(engine->rtp_session, &engine->local_dtls_fingerprint, &engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2);
8531  }
8532 
8533  }
8534  engine->new_dtls = 0;
8535  }
8536 }
8537 
8538 //?
8540 
8541 {
8542  const char *err = NULL;
8543  const char *val = NULL;
8546  char tmp[50];
8547  char *timer_name = NULL;
8548  const char *var;
8549  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
8550  switch_media_handle_t *smh;
8551  int is_reinvite = 0;
8552 
8553 #ifdef HAVE_OPENSSL_DTLSv1_2_method
8554  uint8_t want_DTLSv1_2 = 1;
8555 #else
8556  uint8_t want_DTLSv1_2 = 0;
8557 #endif
8558 
8559  switch_assert(session);
8560 
8561  if (!(smh = session->media_handle)) {
8562  return SWITCH_STATUS_FALSE;
8563  }
8564 
8565  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
8566  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
8567  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
8568 
8569  if (a_engine->rtp_session || v_engine->rtp_session || t_engine->rtp_session || switch_channel_test_flag(session->channel, CF_REINVITE)) {
8570  is_reinvite = 1;
8571  }
8572 
8573 
8574  if (switch_channel_down(session->channel)) {
8575  return SWITCH_STATUS_FALSE;
8576  }
8577 
8579 
8580  if (switch_rtp_ready(a_engine->rtp_session)) {
8582  check_media_timeout_params(session, a_engine);
8583  check_media_timeout_params(session, v_engine);
8584  }
8585 
8586  if (a_engine->crypto_type != CRYPTO_INVALID) {
8588  }
8589 
8590  if (want_DTLSv1_2) {
8592  }
8593 
8595  status = SWITCH_STATUS_SUCCESS;
8596  goto end;
8597  }
8598 
8599  if (switch_channel_var_true(session->channel, "fire_rtcp_events")) {
8602  switch_channel_var_true(session->channel, "rtp_video_send_rtcp_message_event")) {
8604  }
8605  }
8606 
8607  if (!is_reinvite) {
8608  if (switch_rtp_ready(a_engine->rtp_session)) {
8610  goto text;
8611  }
8612 
8614  goto video;
8615  }
8616 
8617  status = SWITCH_STATUS_SUCCESS;
8618  goto end;
8619  }
8620  }
8621 
8622  if ((status = switch_core_media_set_codec(session, 0, smh->mparams->codec_flags)) != SWITCH_STATUS_SUCCESS) {
8623  goto end;
8624  }
8625 
8627 
8628  flags[SWITCH_RTP_FLAG_DATAWAIT]++;
8629 
8631  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
8632  flags[SWITCH_RTP_FLAG_AUTOADJ]++;
8633  }
8634 
8636  || ((val = switch_channel_get_variable(session->channel, "pass_rfc2833")) && switch_true(val))) {
8638  }
8639 
8640 
8642  || ((val = switch_channel_get_variable(session->channel, "rtp_autoflush")) && switch_true(val))) {
8643  flags[SWITCH_RTP_FLAG_AUTOFLUSH]++;
8644  }
8645 
8647  ((val = switch_channel_get_variable(session->channel, "rtp_rewrite_timestamps")) && switch_true(val)))) {
8648  flags[SWITCH_RTP_FLAG_RAW_WRITE]++;
8649  }
8650 
8652  smh->mparams->cng_pt = 0;
8653  } else if (smh->mparams->cng_pt) {
8654  flags[SWITCH_RTP_FLAG_AUTO_CNG]++;
8655  }
8656 
8657 #if __BYTE_ORDER == __LITTLE_ENDIAN
8658  if (!strcasecmp(a_engine->read_impl.iananame, "L16")) {
8659  flags[SWITCH_RTP_FLAG_BYTESWAP]++;
8660  }
8661 #endif
8662 
8663  if ((flags[SWITCH_RTP_FLAG_BYTESWAP]) && (val = switch_channel_get_variable(session->channel, "rtp_disable_byteswap")) && switch_true(val)) {
8664  flags[SWITCH_RTP_FLAG_BYTESWAP] = 0;
8665  }
8666 
8667  if (a_engine->rtp_session && is_reinvite) {
8668  //const char *ip = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
8669  //const char *port = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
8670  char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
8671  switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
8672 
8673  if (remote_host && remote_port && !strcmp(remote_host, a_engine->cur_payload_map->remote_sdp_ip) &&
8674  remote_port == a_engine->cur_payload_map->remote_sdp_port) {
8675  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n",
8676  switch_channel_get_name(session->channel));
8677  a_engine->cur_payload_map->negotiated = 1;
8678  //XX
8679  goto video;
8680  } else {
8681  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n",
8682  switch_channel_get_name(session->channel),
8683  remote_host, remote_port, a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
8684 
8685  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
8688  switch_channel_execute_on(session->channel, "execute_on_audio_change");
8689  }
8690  }
8691 
8693  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",
8694  switch_channel_get_name(session->channel),
8695  a_engine->local_sdp_ip,
8696  a_engine->local_sdp_port,
8697  a_engine->cur_payload_map->remote_sdp_ip,
8698  a_engine->cur_payload_map->remote_sdp_port, a_engine->cur_payload_map->pt, a_engine->read_impl.microseconds_per_packet / 1000);
8699 
8700  //XX
8701  }
8702 
8703  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->local_sdp_port);
8707 
8708  if (a_engine->rtp_session && is_reinvite) {
8709  const char *rport = NULL;
8710  switch_port_t remote_rtcp_port = a_engine->remote_rtcp_port;
8711 
8712  if (!remote_rtcp_port) {
8713  if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_audio_rtcp_port"))) {
8714  remote_rtcp_port = (switch_port_t)atoi(rport);
8715  }
8716  }
8717 
8719  remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
8720  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
8721  } else {
8722  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n",
8724 
8725  //if (switch_channel_test_flag(session->channel, CF_PROTO_HOLD) && strcmp(a_engine->cur_payload_map->remote_sdp_ip, "0.0.0.0")) {
8726  // switch_core_media_toggle_hold(session, 0);
8727  //}
8728 
8729 
8731  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
8733  /* Reactivate the NAT buster flag. */
8735  }
8736  }
8737 
8738  if (session && a_engine) {
8739  check_dtls_reinvite(session, a_engine);
8740  }
8741 
8742  goto video;
8743  }
8744 
8746  switch_core_media_proxy_remote_addr(session, NULL);
8747 
8748  memset(flags, 0, sizeof(flags));
8749  flags[SWITCH_RTP_FLAG_DATAWAIT]++;
8750  flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++;
8751 
8753  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
8754  flags[SWITCH_RTP_FLAG_AUTOADJ]++;
8755  }
8756 
8757  timer_name = NULL;
8758 
8760  "PROXY AUDIO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
8761  switch_channel_get_name(session->channel),
8762  a_engine->cur_payload_map->remote_sdp_ip,
8763  a_engine->cur_payload_map->remote_sdp_port,
8764  a_engine->cur_payload_map->remote_sdp_ip,
8765  a_engine->cur_payload_map->remote_sdp_port, a_engine->cur_payload_map->pt, a_engine->read_impl.microseconds_per_packet / 1000);
8766 
8767  if (switch_rtp_ready(a_engine->rtp_session)) {
8769  }
8770 
8771  } else {
8772  timer_name = smh->mparams->timer_name;
8773 
8774  if ((var = switch_channel_get_variable(session->channel, "rtp_timer_name"))) {
8775  timer_name = (char *) var;
8776  }
8777  }
8778 
8779 
8780  if (switch_channel_up(session->channel)) {
8781  switch_channel_set_variable(session->channel, "rtp_use_timer_name", timer_name);
8782 
8783  a_engine->rtp_session = switch_rtp_new(a_engine->local_sdp_ip,
8784  a_engine->local_sdp_port,
8785  a_engine->cur_payload_map->remote_sdp_ip,
8786  a_engine->cur_payload_map->remote_sdp_port,
8787  a_engine->cur_payload_map->pt,
8788  strcasecmp("opus", a_engine->read_impl.iananame) ? a_engine->read_impl.samples_per_packet :
8789  a_engine->read_impl.samples_per_second * (a_engine->read_impl.microseconds_per_packet / 1000) / 1000,
8790  a_engine->cur_payload_map->codec_ms * 1000,
8791  flags, timer_name, &err, switch_core_session_get_pool(session),
8792  0, 0);
8793 
8794  if (switch_rtp_ready(a_engine->rtp_session)) {
8795  switch_rtp_set_payload_map(a_engine->rtp_session, &a_engine->payload_map);
8796  }
8797  }
8798 
8799  if (switch_rtp_ready(a_engine->rtp_session)) {
8800  uint8_t vad_in = (smh->mparams->vflags & VAD_IN);
8801  uint8_t vad_out = (smh->mparams->vflags & VAD_OUT);
8803  const char *ssrc;
8804 
8807 
8808  //switch_core_media_set_rtp_session(session, SWITCH_MEDIA_TYPE_AUDIO, a_engine->rtp_session);
8809 
8810  if ((ssrc = switch_channel_get_variable(session->channel, "rtp_use_ssrc"))) {
8811  uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10);
8812  switch_rtp_set_ssrc(a_engine->rtp_session, ssrc_ul);
8813  a_engine->ssrc = ssrc_ul;
8814  } else {
8815  switch_rtp_set_ssrc(a_engine->rtp_session, a_engine->ssrc);
8816  }
8817 
8818  if (a_engine->remote_ssrc) {
8819  switch_rtp_set_remote_ssrc(a_engine->rtp_session, a_engine->remote_ssrc);
8820  }
8821 
8822  check_media_timeout_params(session, a_engine);
8823 
8825 
8826  switch_channel_set_variable_printf(session->channel, "rtp_use_pt", "%d", a_engine->cur_payload_map->pt);
8827 
8828  if ((val = switch_channel_get_variable(session->channel, "rtp_enable_vad_in")) && switch_true(val)) {
8829  vad_in = 1;
8830  }
8831  if ((val = switch_channel_get_variable(session->channel, "rtp_enable_vad_out")) && switch_true(val)) {
8832  vad_out = 1;
8833  }
8834 
8835  if ((val = switch_channel_get_variable(session->channel, "rtp_disable_vad_in")) && switch_true(val)) {
8836  vad_in = 0;
8837  }
8838  if ((val = switch_channel_get_variable(session->channel, "rtp_disable_vad_out")) && switch_true(val)) {
8839  vad_out = 0;
8840  }
8841 
8842 
8843  a_engine->ssrc = switch_rtp_get_ssrc(a_engine->rtp_session);
8844  switch_channel_set_variable_printf(session->channel, "rtp_use_ssrc", "%u", a_engine->ssrc);
8845 
8846 
8847 
8849  a_engine->rtp_bugs |= RTP_BUG_IGNORE_MARK_BIT;
8850  }
8851 
8852  if ((val = switch_channel_get_variable(session->channel, "rtp_manual_rtp_bugs"))) {
8853  switch_core_media_parse_rtp_bugs(&a_engine->rtp_bugs, val);
8854  }
8855 
8856  //if (switch_channel_test_flag(session->channel, CF_AVPF)) {
8857  // smh->mparams->manual_rtp_bugs = RTP_BUG_SEND_LINEAR_TIMESTAMPS;
8858  //}
8859 
8861 
8862  if ((vad_in && inb) || (vad_out && !inb)) {
8864 
8865  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP Engage VAD for %s ( %s %s )\n",
8866  switch_channel_get_name(switch_core_session_get_channel(session)), vad_in ? "in" : "", vad_out ? "out" : "");
8867  }
8868 
8869 
8870  if (a_engine->ice_in.cands[a_engine->ice_in.chosen[0]][0].ready) {
8871 
8872  gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, NULL, 0);
8873 
8874  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating Audio ICE\n");
8875 
8877  a_engine->ice_in.ufrag,
8878  a_engine->ice_out.ufrag,
8879  a_engine->ice_out.pwd,
8880  a_engine->ice_in.pwd,
8881  IPR_RTP,
8882 #ifdef GOOGLE_ICE
8884  NULL
8885 #else
8886  switch_determine_ice_type(a_engine, session),
8887  &a_engine->ice_in
8888 #endif
8889  );
8890 
8891 
8892 
8893  }
8894 
8895  if ((val = switch_channel_get_variable(session->channel, "rtcp_audio_interval_msec")) || (val = smh->mparams->rtcp_audio_interval_msec)) {
8896  const char *rport = switch_channel_get_variable(session->channel, "rtp_remote_audio_rtcp_port");
8897  switch_port_t remote_rtcp_port = a_engine->remote_rtcp_port;
8898 
8899  if (!remote_rtcp_port && rport) {
8900  remote_rtcp_port = (switch_port_t)atoi(rport);
8901  }
8902 
8903  if (!strcasecmp(val, "passthru")) {
8904  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating RTCP PASSTHRU PORT %d\n", remote_rtcp_port);
8905  switch_rtp_activate_rtcp(a_engine->rtp_session, -1, remote_rtcp_port, a_engine->rtcp_mux > 0);
8906  } else {
8907  int interval = atoi(val);
8908  if (interval < 100 || interval > 500000) {
8910  "Invalid rtcp interval spec [%d] must be between 100 and 500000\n", interval);
8911  interval = 5000;
8912  }
8913 
8914  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Activating RTCP PORT %d\n", remote_rtcp_port);
8915  switch_rtp_activate_rtcp(a_engine->rtp_session, interval, remote_rtcp_port, a_engine->rtcp_mux > 0);
8916 
8917  }
8918 
8919  if (a_engine->ice_in.cands[a_engine->ice_in.chosen[1]][1].ready && a_engine->ice_in.cands[a_engine->ice_in.chosen[0]][0].ready &&
8920  !zstr(a_engine->ice_in.cands[a_engine->ice_in.chosen[1]][1].con_addr) &&
8921  !zstr(a_engine->ice_in.cands[a_engine->ice_in.chosen[0]][0].con_addr)) {
8922  if (a_engine->rtcp_mux > 0 &&
8923  !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)
8924  && 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) {
8925  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Skipping RTCP ICE (Same as RTP)\n");
8926  } else {
8927  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating RTCP ICE\n");
8928 
8930  a_engine->ice_in.ufrag,
8931  a_engine->ice_out.ufrag,
8932  a_engine->ice_out.pwd,
8933  a_engine->ice_in.pwd,
8934  IPR_RTCP,
8935 #ifdef GOOGLE_ICE
8937  NULL
8938 #else
8939  switch_determine_ice_type(a_engine, session),
8940  &a_engine->ice_in
8941 #endif
8942  );
8943  }
8944 
8945  }
8946  }
8947 
8948  if (!zstr(a_engine->local_dtls_fingerprint.str) && switch_rtp_has_dtls() && dtls_ok(smh->session)) {
8949  dtls_type_t xtype, dtype = a_engine->dtls_controller ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
8950 
8951  //if (switch_channel_test_flag(smh->session->channel, CF_3PCC)) {
8952  // dtype = (dtype == DTLS_TYPE_CLIENT) ? DTLS_TYPE_SERVER : DTLS_TYPE_CLIENT;
8953  //}
8954 
8955  xtype = DTLS_TYPE_RTP;
8956  if (a_engine->rtcp_mux > 0 && smh->mparams->rtcp_audio_interval_msec) xtype |= DTLS_TYPE_RTCP;
8957 
8958  if (switch_channel_var_true(session->channel, "legacyDTLS")) {
8960  want_DTLSv1_2 = 0;
8961  }
8962 
8963  switch_rtp_add_dtls(a_engine->rtp_session, &a_engine->local_dtls_fingerprint, &a_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2);
8964 
8965  if (a_engine->rtcp_mux < 1 && smh->mparams->rtcp_audio_interval_msec) {
8966  xtype = DTLS_TYPE_RTCP;
8967  switch_rtp_add_dtls(a_engine->rtp_session, &a_engine->local_dtls_fingerprint, &a_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2);
8968  }
8969 
8970  }
8971 
8972  check_jb(session, NULL, 0, 0, SWITCH_FALSE);
8973 
8974  if ((val = switch_channel_get_variable(session->channel, "rtp_timeout_sec"))) {
8975  int v = atoi(val);
8976  if (v >= 0) {
8978  "rtp_timeout_sec deprecated use media_timeout variable.\n");
8979  smh->mparams->rtp_timeout_sec = v;
8980  }
8981  }
8982 
8983  if ((val = switch_channel_get_variable(session->channel, "rtp_hold_timeout_sec"))) {
8984  int v = atoi(val);
8985  if (v >= 0) {
8987  "rtp_hold_timeout_sec deprecated use media_hold_timeout variable.\n");
8988  smh->mparams->rtp_hold_timeout_sec = v;
8989  }
8990  }
8991 
8992  if (smh->mparams->rtp_timeout_sec) {
8994 
8996  if (!smh->mparams->rtp_hold_timeout_sec) {
8998  }
8999  }
9000 
9001  if (smh->mparams->rtp_hold_timeout_sec) {
9003  }
9004 
9005  if (smh->mparams->te) {
9006  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Set 2833 dtmf send payload to %u\n",
9007  switch_channel_get_name(session->channel), smh->mparams->te);
9009  switch_channel_set_variable_printf(session->channel, "rtp_2833_send_payload", "%d", smh->mparams->te);
9010  }
9011 
9012  if (smh->mparams->recv_te) {
9013  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Set 2833 dtmf receive payload to %u\n",
9014  switch_channel_get_name(session->channel), smh->mparams->recv_te);
9016  switch_channel_set_variable_printf(session->channel, "rtp_2833_recv_payload", "%d", smh->mparams->recv_te);
9017  }
9018 
9019  //XX
9020 
9022  ((val = switch_channel_get_variable(session->channel, "supress_cng")) && switch_true(val)) ||
9023  ((val = switch_channel_get_variable(session->channel, "suppress_cng")) && switch_true(val))) {
9024  smh->mparams->cng_pt = 0;
9025  }
9026 
9027  if (((val = switch_channel_get_variable(session->channel, "rtp_digit_delay")))) {
9028  int delayi = atoi(val);
9029  if (delayi < 0) delayi = 0;
9030  smh->mparams->dtmf_delay = (uint32_t) delayi;
9031  }
9032 
9033 
9034  if (smh->mparams->dtmf_delay) {
9037  "%s Set rtp dtmf delay to %u\n", switch_channel_get_name(session->channel), smh->mparams->dtmf_delay);
9038 
9039  }
9040 
9042  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u\n", smh->mparams->cng_pt);
9043  switch_rtp_set_cng_pt(a_engine->rtp_session, smh->mparams->cng_pt);
9044  }
9045 
9047 
9048  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
9051 
9052 
9053  text:
9054 
9055  //if (switch_channel_test_flag(session->channel, CF_MSRP)) { // skip RTP RTT
9056  // goto video;
9057  //}
9058 
9059  if (!t_engine->cur_payload_map) {
9060  goto text_up;
9061  }
9062 
9064  /******************************************************************************************/
9065  if (t_engine->rtp_session && is_reinvite) {
9066  //const char *ip = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
9067  //const char *port = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
9068  char *remote_host = switch_rtp_get_remote_host(t_engine->rtp_session);
9069  switch_port_t remote_port = switch_rtp_get_remote_port(t_engine->rtp_session);
9070 
9071 
9072 
9073  if (remote_host && remote_port && !strcmp(remote_host, t_engine->cur_payload_map->remote_sdp_ip) && remote_port == t_engine->cur_payload_map->remote_sdp_port) {
9074  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Text params are unchanged for %s.\n",
9075  switch_channel_get_name(session->channel));
9076  t_engine->cur_payload_map->negotiated = 1;
9077  goto text_up;
9078  } else {
9079  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Text params changed for %s from %s:%d to %s:%d\n",
9080  switch_channel_get_name(session->channel),
9081  remote_host, remote_port, t_engine->cur_payload_map->remote_sdp_ip, t_engine->cur_payload_map->remote_sdp_port);
9082  }
9083  }
9084 
9086  if (switch_rtp_ready(t_engine->rtp_session)) {
9088  "TEXT RTP [%s] %s port %d -> %s port %d codec: %u\n", switch_channel_get_name(session->channel),
9089  t_engine->local_sdp_ip, t_engine->local_sdp_port, t_engine->cur_payload_map->remote_sdp_ip,
9090  t_engine->cur_payload_map->remote_sdp_port, t_engine->cur_payload_map->pt);
9091 
9093  }
9094  }
9095 
9096  switch_snprintf(tmp, sizeof(tmp), "%d", t_engine->local_sdp_port);
9099 
9100 
9101  if (t_engine->rtp_session && is_reinvite) {
9102  const char *rport = NULL;
9103  switch_port_t remote_rtcp_port = t_engine->remote_rtcp_port;
9104 
9105  //switch_channel_clear_flag(session->channel, CF_REINVITE);
9106 
9107  if (!remote_rtcp_port) {
9108  if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_text_rtcp_port"))) {
9109  remote_rtcp_port = (switch_port_t)atoi(rport);
9110  }
9111  }
9112 
9114  (t_engine->rtp_session, t_engine->cur_payload_map->remote_sdp_ip, t_engine->cur_payload_map->remote_sdp_port, remote_rtcp_port, SWITCH_TRUE,
9115  &err) != SWITCH_STATUS_SUCCESS) {
9116  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "TEXT RTP REPORTS ERROR: [%s]\n", err);
9117  } else {
9118  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "TEXT RTP CHANGING DEST TO: [%s:%d]\n",
9121  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
9122  /* Reactivate the NAT buster flag. */
9124  }
9125 
9126  }
9127  goto text_up;
9128  }
9129 
9131  switch_core_media_proxy_remote_addr(session, NULL);
9132 
9133  memset(flags, 0, sizeof(flags));
9134  flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++;
9135  flags[SWITCH_RTP_FLAG_DATAWAIT]++;
9136 
9138  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
9139  flags[SWITCH_RTP_FLAG_AUTOADJ]++;
9140  }
9141 
9143  "PROXY TEXT RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
9144  switch_channel_get_name(session->channel),
9145  a_engine->cur_payload_map->remote_sdp_ip,
9146  t_engine->local_sdp_port,
9147  t_engine->cur_payload_map->remote_sdp_ip,
9148  t_engine->cur_payload_map->remote_sdp_port, t_engine->cur_payload_map->pt, t_engine->read_impl.microseconds_per_packet / 1000);
9149 
9150  if (switch_rtp_ready(t_engine->rtp_session)) {
9152  }
9153  }
9154 
9155  /******************************************************************************************/
9156 
9157  if (t_engine->rtp_session) {
9158  goto text_up;
9159  }
9160 
9161 
9162  if (!t_engine->local_sdp_port) {
9164  }
9165 
9166  memset(flags, 0, sizeof(flags));
9167  flags[SWITCH_RTP_FLAG_DATAWAIT]++;
9168  flags[SWITCH_RTP_FLAG_RAW_WRITE]++;
9169 
9171  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
9173  flags[SWITCH_RTP_FLAG_AUTOADJ]++;
9174  }
9175 
9177  flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++;
9178  }
9179  //TEXT switch_core_media_set_text_codec(session, 0);
9180 
9181  flags[SWITCH_RTP_FLAG_USE_TIMER] = 1;
9182  flags[SWITCH_RTP_FLAG_NOBLOCK] = 0;
9183  flags[SWITCH_RTP_FLAG_TEXT]++;
9184  //flags[SWITCH_RTP_FLAG_VIDEO]++;
9185 
9186  t_engine->rtp_session = switch_rtp_new(a_engine->local_sdp_ip,
9187  t_engine->local_sdp_port,
9188  t_engine->cur_payload_map->remote_sdp_ip,
9189  t_engine->cur_payload_map->remote_sdp_port,
9190  t_engine->cur_payload_map->pt,
9191  TEXT_TIMER_SAMPLES, TEXT_TIMER_MS * 1000, flags, NULL, &err, switch_core_session_get_pool(session),
9192  0, 0);
9193 
9194 
9195  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%sTEXT RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n",
9196  switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) ? "PROXY " : "",
9197  switch_channel_get_name(session->channel),
9198  a_engine->local_sdp_ip,
9199  t_engine->local_sdp_port,
9200  t_engine->cur_payload_map->remote_sdp_ip,
9201  t_engine->cur_payload_map->remote_sdp_port, t_engine->cur_payload_map->pt,
9202  0, switch_rtp_ready(t_engine->rtp_session) ? "SUCCESS" : err);
9203 
9204 
9205  if (switch_rtp_ready(t_engine->rtp_session)) {
9206  const char *ssrc;
9207 
9208 
9209  if (!t_engine->tf) {
9211  }
9212 
9213  switch_rtp_set_video_buffer_size(t_engine->rtp_session, 2, 2048);
9214 
9215  switch_rtp_set_payload_map(t_engine->rtp_session, &t_engine->payload_map);
9218 
9219  if ((ssrc = switch_channel_get_variable(session->channel, "rtp_use_text_ssrc"))) {
9220  uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10);
9221  switch_rtp_set_ssrc(t_engine->rtp_session, ssrc_ul);
9222  t_engine->ssrc = ssrc_ul;
9223  } else {
9224  switch_rtp_set_ssrc(t_engine->rtp_session, t_engine->ssrc);
9225  }
9226 
9227  if (t_engine->remote_ssrc) {
9228  switch_rtp_set_remote_ssrc(t_engine->rtp_session, t_engine->remote_ssrc);
9229  }
9230 
9231  if (t_engine->ice_in.cands[t_engine->ice_in.chosen[0]][0].ready) {
9232 
9233  gen_ice(session, SWITCH_MEDIA_TYPE_TEXT, NULL, 0);
9234 
9235  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating Text ICE\n");
9236 
9238  t_engine->ice_in.ufrag,
9239  t_engine->ice_out.ufrag,
9240  t_engine->ice_out.pwd,
9241  t_engine->ice_in.pwd,
9242  IPR_RTP,
9243 #ifdef GOOGLE_ICE
9245  NULL
9246 #else
9247  switch_determine_ice_type(t_engine, session),
9248  &t_engine->ice_in
9249 #endif
9250  );
9251 
9252 
9253  }
9254 
9255  if ((val = switch_channel_get_variable(session->channel, "rtcp_text_interval_msec")) || (val = smh->mparams->rtcp_text_interval_msec)) {
9256  const char *rport = switch_channel_get_variable(session->channel, "rtp_remote_text_rtcp_port");
9257  switch_port_t remote_port = t_engine->remote_rtcp_port;
9258 
9259  if (rport) {
9260  remote_port = (switch_port_t)atoi(rport);
9261  }
9262  if (!strcasecmp(val, "passthru")) {
9263  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating TEXT RTCP PASSTHRU PORT %d\n", remote_port);
9264  switch_rtp_activate_rtcp(t_engine->rtp_session, -1, remote_port, t_engine->rtcp_mux > 0);
9265  } else {
9266  int interval = atoi(val);
9267  if (interval < 100 || interval > 500000) {
9269  "Invalid rtcp interval spec [%d] must be between 100 and 500000\n", interval);
9270  interval = 5000;
9271  }
9273  "Activating TEXT RTCP PORT %d interval %d mux %d\n", remote_port, interval, t_engine->rtcp_mux);
9274  switch_rtp_activate_rtcp(t_engine->rtp_session, interval, remote_port, t_engine->rtcp_mux > 0);
9275 
9276  }
9277 
9278 
9279  if (t_engine->ice_in.cands[t_engine->ice_in.chosen[1]][1].ready && t_engine->ice_in.cands[t_engine->ice_in.chosen[0]][0].ready &&
9280  !zstr(t_engine->ice_in.cands[t_engine->ice_in.chosen[1]][1].con_addr) &&
9281  !zstr(t_engine->ice_in.cands[t_engine->ice_in.chosen[0]][0].con_addr)) {
9282  if (t_engine->rtcp_mux > 0 && !strcmp(t_engine->ice_in.cands[t_engine->ice_in.chosen[1]][1].con_addr,
9283  t_engine->ice_in.cands[t_engine->ice_in.chosen[0]][0].con_addr) &&
9284  t_engine->ice_in.cands[t_engine->ice_in.chosen[1]][1].con_port == t_engine->ice_in.cands[t_engine->ice_in.chosen[0]][0].con_port) {
9285  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Skipping TEXT RTCP ICE (Same as TEXT RTP)\n");
9286  } else {
9287  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating TEXT RTCP ICE\n");
9289  t_engine->ice_in.ufrag,
9290  t_engine->ice_out.ufrag,
9291  t_engine->ice_out.pwd,
9292  t_engine->ice_in.pwd,
9293  IPR_RTCP,
9294 #ifdef GOOGLE_ICE
9296  NULL
9297 #else
9298  switch_determine_ice_type(t_engine, session),
9299  &t_engine->ice_in
9300 #endif
9301  );
9302 
9303 
9304 
9305  }
9306 
9307  }
9308  }
9309 
9310  if (!zstr(t_engine->local_dtls_fingerprint.str) && switch_rtp_has_dtls() && dtls_ok(smh->session)) {
9311  dtls_type_t xtype,
9312  dtype = t_engine->dtls_controller ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
9313  xtype = DTLS_TYPE_RTP;
9314  if (t_engine->rtcp_mux > 0 && smh->mparams->rtcp_text_interval_msec) xtype |= DTLS_TYPE_RTCP;
9315 
9316  if (switch_channel_var_true(session->channel, "legacyDTLS")) {
9318  want_DTLSv1_2 = 0;
9319  }
9320 
9321  switch_rtp_add_dtls(t_engine->rtp_session, &t_engine->local_dtls_fingerprint, &t_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2);
9322 
9323  if (t_engine->rtcp_mux < 1 && smh->mparams->rtcp_text_interval_msec) {
9324  xtype = DTLS_TYPE_RTCP;
9325  switch_rtp_add_dtls(t_engine->rtp_session, &t_engine->local_dtls_fingerprint, &t_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2);
9326  }
9327  }
9328 
9329 
9330  if ((val = switch_channel_get_variable(session->channel, "rtp_manual_text_rtp_bugs"))) {
9331  switch_core_media_parse_rtp_bugs(&t_engine->rtp_bugs, val);
9332  }
9333 
9334 
9335  //if (switch_channel_test_flag(session->channel, CF_AVPF)) {
9336  //smh->mparams->manual_video_rtp_bugs = RTP_BUG_SEND_LINEAR_TIMESTAMPS;
9337  //}
9338 
9340 
9341  //XX
9342 
9343 
9344  switch_channel_set_variable_printf(session->channel, "rtp_use_text_pt", "%d", t_engine->cur_payload_map->pt);
9345  t_engine->ssrc = switch_rtp_get_ssrc(t_engine->rtp_session);
9346  switch_channel_set_variable_printf(session->channel, "rtp_use_text_ssrc", "%u", t_engine->ssrc);
9347 
9349 
9350  } else {
9351  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "TEXT RTP REPORTS ERROR: [%s]\n", switch_str_nil(err));
9353  goto end;
9354  }
9355  }
9356 
9357 
9358  text_up:
9359  video:
9360 
9363  }
9364 
9366  /******************************************************************************************/
9367  if (v_engine->rtp_session && is_reinvite) {
9368  //const char *ip = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
9369  //const char *port = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
9370  char *remote_host = switch_rtp_get_remote_host(v_engine->rtp_session);
9371  switch_port_t remote_port = switch_rtp_get_remote_port(v_engine->rtp_session);
9372 
9373 
9374 
9375  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) {
9376  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video params are unchanged for %s.\n",
9377  switch_channel_get_name(session->channel));
9378  v_engine->cur_payload_map->negotiated = 1;
9379  goto video_up;
9380  } else {
9381  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video params changed for %s from %s:%d to %s:%d\n",
9382  switch_channel_get_name(session->channel),
9383  remote_host, remote_port, v_engine->cur_payload_map->remote_sdp_ip, v_engine->cur_payload_map->remote_sdp_port);
9384  }
9385  }
9386 
9388  if (switch_rtp_ready(v_engine->rtp_session)) {
9390  "VIDEO RTP [%s] %s port %d -> %s port %d codec: %u\n", switch_channel_get_name(session->channel),
9391  v_engine->local_sdp_ip, v_engine->local_sdp_port, v_engine->cur_payload_map->remote_sdp_ip,
9392  v_engine->cur_payload_map->remote_sdp_port, v_engine->cur_payload_map->pt);
9393 
9395  }
9396  }
9397 
9398  switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->local_sdp_port);
9401 
9402 
9403  if (v_engine->rtp_session && is_reinvite) {
9404  const char *rport = NULL;
9405  switch_port_t remote_rtcp_port = v_engine->remote_rtcp_port;
9406 
9407  //switch_channel_clear_flag(session->channel, CF_REINVITE);
9408 
9409  if (!remote_rtcp_port) {
9410  if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_video_rtcp_port"))) {
9411  remote_rtcp_port = (switch_port_t)atoi(rport);
9412  }
9413  }
9414 
9416  (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,
9417  &err) != SWITCH_STATUS_SUCCESS) {
9418  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", err);
9419  } else {
9420  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "VIDEO RTP CHANGING DEST TO: [%s:%d]\n",
9423  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
9424  /* Reactivate the NAT buster flag. */
9426  }
9427 
9428  }
9429  goto video_up;
9430  }
9431 
9433  switch_core_media_proxy_remote_addr(session, NULL);
9434 
9435  memset(flags, 0, sizeof(flags));
9436  flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++;
9437  flags[SWITCH_RTP_FLAG_DATAWAIT]++;
9438 
9440  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
9441  flags[SWITCH_RTP_FLAG_AUTOADJ]++;
9442  }
9443 
9445  "PROXY VIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
9446  switch_channel_get_name(session->channel),
9447  a_engine->cur_payload_map->remote_sdp_ip,
9448  v_engine->local_sdp_port,
9449  v_engine->cur_payload_map->remote_sdp_ip,
9450  v_engine->cur_payload_map->remote_sdp_port, v_engine->cur_payload_map->pt, v_engine->read_impl.microseconds_per_packet / 1000);
9451 
9452  if (switch_rtp_ready(v_engine->rtp_session)) {
9454  }
9455  }
9456 
9457  /******************************************************************************************/
9458 
9459  if (v_engine->rtp_session) {
9460  goto video_up;
9461  }
9462 
9463 
9464  if (!v_engine->local_sdp_port) {
9466  }
9467 
9468  memset(flags, 0, sizeof(flags));
9469  flags[SWITCH_RTP_FLAG_DATAWAIT]++;
9470  flags[SWITCH_RTP_FLAG_RAW_WRITE]++;
9471 
9473  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
9475  flags[SWITCH_RTP_FLAG_AUTOADJ]++;
9476  }
9477 
9479  flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++;
9480  }
9482 
9483  flags[SWITCH_RTP_FLAG_USE_TIMER] = 0;
9484  flags[SWITCH_RTP_FLAG_NOBLOCK] = 0;
9485  flags[SWITCH_RTP_FLAG_VIDEO]++;
9486 
9487  if (v_engine->fir) {
9488  flags[SWITCH_RTP_FLAG_FIR]++;
9489  }
9490 
9491  if (v_engine->pli) {
9492  flags[SWITCH_RTP_FLAG_PLI]++;
9493  }
9494 
9495  if ((v_engine->nack) && !switch_channel_var_true(session->channel, "rtp_video_nack_disable")) {
9496  flags[SWITCH_RTP_FLAG_NACK]++;
9497  }
9498 
9499  if (v_engine->tmmbr) {
9500  flags[SWITCH_RTP_FLAG_TMMBR]++;
9501  }
9502 
9503  v_engine->rtp_session = switch_rtp_new(a_engine->local_sdp_ip,
9504  v_engine->local_sdp_port,
9505  v_engine->cur_payload_map->remote_sdp_ip,
9506  v_engine->cur_payload_map->remote_sdp_port,
9507  v_engine->cur_payload_map->pt,
9508  1, 90000, flags, NULL, &err, switch_core_session_get_pool(session),
9509  0, 0);
9510 
9511 
9512  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%sVIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n",
9513  switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) ? "PROXY " : "",
9514  switch_channel_get_name(session->channel),
9515  a_engine->local_sdp_ip,
9516  v_engine->local_sdp_port,
9517  v_engine->cur_payload_map->remote_sdp_ip,
9518  v_engine->cur_payload_map->remote_sdp_port, v_engine->cur_payload_map->pt,
9519  0, switch_rtp_ready(v_engine->rtp_session) ? "SUCCESS" : err);
9520 
9521 
9522  if (switch_rtp_ready(v_engine->rtp_session)) {
9523  const char *ssrc;
9524 
9525  if (v_engine->fir) {
9527  }
9528 
9529  if (v_engine->pli) {
9531  }
9532 
9533  switch_rtp_set_payload_map(v_engine->rtp_session, &v_engine->payload_map);
9536 
9538  if ((ssrc = switch_channel_get_variable(session->channel, "rtp_use_video_ssrc"))) {
9539  uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10);
9540  switch_rtp_set_ssrc(v_engine->rtp_session, ssrc_ul);
9541  v_engine->ssrc = ssrc_ul;
9542  } else {
9543  switch_rtp_set_ssrc(v_engine->rtp_session, v_engine->ssrc);
9544  }
9545 
9546  if (v_engine->remote_ssrc) {
9547  switch_rtp_set_remote_ssrc(v_engine->rtp_session, v_engine->remote_ssrc);
9548  }
9549 
9550  check_media_timeout_params(session, v_engine);
9551 
9552  if (v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].ready) {
9553 
9554  gen_ice(session, SWITCH_MEDIA_TYPE_VIDEO, NULL, 0);
9555 
9556  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating Video ICE\n");
9557 
9559  v_engine->ice_in.ufrag,
9560  v_engine->ice_out.ufrag,
9561  v_engine->ice_out.pwd,
9562  v_engine->ice_in.pwd,
9563  IPR_RTP,
9564 #ifdef GOOGLE_ICE
9566  NULL
9567 #else
9568  switch_determine_ice_type(v_engine, session),
9569  &v_engine->ice_in
9570 #endif
9571  );
9572 
9573 
9574  }
9575 
9576  if ((val = switch_channel_get_variable(session->channel, "rtcp_video_interval_msec")) || (val = smh->mparams->rtcp_video_interval_msec)) {
9577  const char *rport = switch_channel_get_variable(session->channel, "rtp_remote_video_rtcp_port");
9578  switch_port_t remote_port = v_engine->remote_rtcp_port;
9579 
9580  if (rport) {
9581  remote_port = (switch_port_t)atoi(rport);
9582  }
9583  if (!strcasecmp(val, "passthru")) {
9584  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating VIDEO RTCP PASSTHRU PORT %d\n", remote_port);
9585  switch_rtp_activate_rtcp(v_engine->rtp_session, -1, remote_port, v_engine->rtcp_mux > 0);
9586  } else {
9587  int interval = atoi(val);
9588  if (interval < 100 || interval > 500000) {
9590  "Invalid rtcp interval spec [%d] must be between 100 and 500000\n", interval);
9591  interval = 5000;
9592  }
9594  "Activating VIDEO RTCP PORT %d interval %d mux %d\n", remote_port, interval, v_engine->rtcp_mux);
9595  switch_rtp_activate_rtcp(v_engine->rtp_session, interval, remote_port, v_engine->rtcp_mux > 0);
9596 
9597  }
9598 
9599 
9600  if (v_engine->ice_in.cands[v_engine->ice_in.chosen[1]][1].ready && v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].ready &&
9601  !zstr(v_engine->ice_in.cands[v_engine->ice_in.chosen[1]][1].con_addr) &&
9602  !zstr(v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].con_addr)) {
9603 
9604  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)
9605  && 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) {
9606  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Skipping VIDEO RTCP ICE (Same as VIDEO RTP)\n");
9607  } else {
9608 
9609  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating VIDEO RTCP ICE\n");
9611  v_engine->ice_in.ufrag,
9612  v_engine->ice_out.ufrag,
9613  v_engine->ice_out.pwd,
9614  v_engine->ice_in.pwd,
9615  IPR_RTCP,
9616 #ifdef GOOGLE_ICE
9618  NULL
9619 #else
9620  switch_determine_ice_type(v_engine, session),
9621  &v_engine->ice_in
9622 #endif
9623  );
9624 
9625 
9626 
9627  }
9628 
9629  }
9630  }
9631 
9632  if (!zstr(v_engine->local_dtls_fingerprint.str) && switch_rtp_has_dtls() && dtls_ok(smh->session)) {
9633  dtls_type_t xtype,
9634  dtype = v_engine->dtls_controller ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
9635  xtype = DTLS_TYPE_RTP;
9636  if (v_engine->rtcp_mux > 0 && smh->mparams->rtcp_video_interval_msec) xtype |= DTLS_TYPE_RTCP;
9637 
9638 
9639  if (switch_channel_var_true(session->channel, "legacyDTLS")) {
9641  want_DTLSv1_2 = 0;
9642  }
9643 
9644  switch_rtp_add_dtls(v_engine->rtp_session, &v_engine->local_dtls_fingerprint, &v_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2);
9645 
9646  if (v_engine->rtcp_mux < 1 && smh->mparams->rtcp_video_interval_msec) {
9647  xtype = DTLS_TYPE_RTCP;
9648  switch_rtp_add_dtls(v_engine->rtp_session, &v_engine->local_dtls_fingerprint, &v_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2);
9649  }
9650  }
9651 
9652 
9653  if ((val = switch_channel_get_variable(session->channel, "rtp_manual_video_rtp_bugs"))) {
9654  switch_core_media_parse_rtp_bugs(&v_engine->rtp_bugs, val);
9655  }
9656 
9657  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
9659  }
9660 
9662 
9663  //XX
9664 
9665 
9666  switch_channel_set_variable_printf(session->channel, "rtp_use_video_pt", "%d", v_engine->cur_payload_map->pt);
9667  v_engine->ssrc = switch_rtp_get_ssrc(v_engine->rtp_session);
9668  switch_channel_set_variable_printf(session->channel, "rtp_use_video_ssrc", "%u", v_engine->ssrc);
9669 
9671 
9672 
9673  } else {
9674  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", switch_str_nil(err));
9676  goto end;
9677  }
9678  }
9679 
9680  } else {
9681  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", switch_str_nil(err));
9683  status = SWITCH_STATUS_FALSE;
9684  goto end;
9685  }
9686 
9687  video_up:
9688 
9689  if (session && v_engine) {
9690  check_dtls_reinvite(session, v_engine);
9691  }
9692 
9693  status = SWITCH_STATUS_SUCCESS;
9694 
9695  end:
9696 
9698 
9699  switch_core_recovery_track(session);
9700 
9701  return status;
9702 
9703 }
9704 
9706 {
9707  switch_assert(session);
9708 
9709  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
9710  if (switch_channel_test_flag(session->channel, CF_DTLS) || secure) {
9711  if (switch_channel_test_flag(session->channel, CF_AVPF_MOZ)) {
9712  return "UDP/TLS/RTP/SAVPF";
9713  } else {
9714  return "RTP/SAVPF";
9715  }
9716  } else {
9717  if (switch_channel_test_flag(session->channel, CF_AVPF_MOZ)) {
9718  return "UDP/AVPF";
9719  } else {
9720  return "RTP/AVPF";
9721  }
9722  }
9723  }
9724 
9725  if (secure) {
9726  switch (avp) {
9727  case AVP_NO_SECURE:
9728  break;
9729  case AVP_SECURE:
9730  case AVP_UNDEFINED:
9731  return "RTP/SAVP";
9732  default:
9733  break;
9734  }
9735  }
9736 
9737  return "RTP/AVP";
9738 
9739 }
9740 
9742 {
9743 
9744  if (sdp_type == SDP_OFFER) {
9745  engine->dtls_controller = 0;
9746  engine->new_dtls = 1;
9747  engine->new_ice = 1;
9748  return "actpass";
9749  } else {
9750  return engine->dtls_controller ? "active" : "passive";
9751  }
9752 }
9753 
9754 
9755 //?
9756 static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
9757  switch_port_t port, const char *family, const char *ip,
9758  int cur_ptime, const char *append_audio, const char *sr, int use_cng, int cng_type, switch_event_t *map, int secure,
9759  switch_sdp_type_t sdp_type)
9760 {
9761  int i = 0;
9762  int rate;
9763  int already_did[128] = { 0 };
9764  int ptime = 0, noptime = 0;
9765  switch_media_handle_t *smh;
9766  switch_rtp_engine_t *a_engine;
9767  int include_external;
9769 
9770  switch_assert(session);
9771 
9772  if (!(smh = session->media_handle)) {
9773  return;
9774  }
9775 
9776  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
9777 
9778  //switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d RTP/%sAVP%s",
9779  //port, secure ? "S" : "", switch_channel_test_flag(session->channel, CF_AVPF) ? "F" : "");
9780 
9781  /* Check if there is a crypto */
9782  if (secure && !switch_channel_test_flag(session->channel, CF_DTLS)) {
9783  int i;
9784 
9785  for (i = 0; smh->crypto_suite_order[i] != CRYPTO_INVALID; i++) {
9787 
9788  if ((a_engine->crypto_type == j || a_engine->crypto_type == CRYPTO_INVALID) && !zstr(a_engine->ssec[j].local_crypto_key)) {
9789  avp_secure = AVP_SECURE;
9790  break;
9791  }
9792  }
9793  }
9794 
9795  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d %s", port,
9796  get_media_profile_name(session, secure || a_engine->crypto_type != CRYPTO_INVALID, avp_secure));
9797 
9798  include_external = switch_channel_var_true(session->channel, "include_external_ip");
9799 
9800  for (i = 0; i < smh->mparams->num_codecs; i++) {
9801  const switch_codec_implementation_t *imp = smh->codecs[i];
9802  int this_ptime = (imp->microseconds_per_packet / 1000);
9803  payload_map_t *pmap;
9804 
9805  if (!strcasecmp(imp->iananame, "ilbc") || !strcasecmp(imp->iananame, "isac") ) {
9806  this_ptime = 20;
9807  }
9808 
9809  if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
9810  continue;
9811  }
9812 
9813  if (!noptime) {
9814  if (!cur_ptime) {
9815  if (!ptime) {
9816  ptime = this_ptime;
9817  }
9818  } else {
9819  if (this_ptime != cur_ptime) {
9820  continue;
9821  }
9822  }
9823  }
9824 
9825  if (smh->ianacodes[i] >= 128 || already_did[smh->ianacodes[i]]) {
9826  continue;
9827  }
9828 
9829 
9831  for (pmap = a_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
9832  if (pmap->negotiated && !strcasecmp(imp->iananame, pmap->iananame)) {
9833  smh->ianacodes[i] = pmap->pt;
9834  break;
9835  }
9836  }
9838 
9839  already_did[smh->ianacodes[i]] = 1;
9840 
9841  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", smh->ianacodes[i]);
9842  }
9843 
9844  if (smh->mparams->dtmf_type == DTMF_2833 && smh->mparams->te > 95) {
9845  if (sdp_type == SDP_ANSWER) {
9847  if (a_engine) {
9848  payload_map_t *pmap;
9849  for (pmap = a_engine->payload_map; pmap; pmap = pmap->next) {
9850  if (pmap->pt >= 128 || already_did[pmap->pt]) {
9851  continue;
9852  }
9853 
9854  if (!strncasecmp(pmap->iananame, "telephone-event", 15)) {
9855  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", pmap->pt);
9856  already_did[pmap->pt] = 1;
9857  }
9858  }
9859  }
9860  } else {
9861  int i;
9862 
9863  for (i = 0; i < smh->num_rates; i++) {
9864  if (smh->dtmf_ianacodes[i] < 128 && !already_did[smh->dtmf_ianacodes[i]]) {
9865  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", smh->dtmf_ianacodes[i]);
9866  already_did[smh->dtmf_ianacodes[i]] = 1;
9867  }
9868  if (smh->cng_ianacodes[i] < 128 && !already_did[smh->cng_ianacodes[i]] && !switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && cng_type && use_cng) {
9869  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", smh->cng_ianacodes[i]);
9870  already_did[smh->cng_ianacodes[i]] = 1;
9871  }
9872  }
9873  }
9874  }
9875 
9876  //if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && cng_type && use_cng) {
9877  //switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", cng_type);
9878  //}
9879 
9880  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "\r\n");
9881 
9882 
9883  memset(already_did, 0, sizeof(already_did));
9884 
9885 
9886  for (i = 0; i < smh->mparams->num_codecs; i++) {
9887  const switch_codec_implementation_t *imp = smh->codecs[i];
9888  char *fmtp = imp->fmtp;
9889  int this_ptime = imp->microseconds_per_packet / 1000;
9890 
9891  if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
9892  continue;
9893  }
9894 
9895  if (!strcasecmp(imp->iananame, "ilbc") || !strcasecmp(imp->iananame, "isac")) {
9896  this_ptime = 20;
9897  }
9898 
9899  if (!noptime) {
9900  if (!cur_ptime) {
9901  if (!ptime) {
9902  ptime = this_ptime;
9903  }
9904  } else {
9905  if (this_ptime != cur_ptime) {
9906  continue;
9907  }
9908  }
9909  }
9910 
9911  if (smh->ianacodes[i] >= 128 || already_did[smh->ianacodes[i]]) {
9912  continue;
9913  }
9914 
9915  already_did[smh->ianacodes[i]] = 1;
9916  rate = imp->samples_per_second;
9917 
9918  if (map) {
9919  char key[128] = "";
9920  char *check = NULL;
9921  switch_snprintf(key, sizeof(key), "%s:%u", imp->iananame, imp->bits_per_second);
9922 
9923  if ((check = switch_event_get_header(map, key)) || (check = switch_event_get_header(map, imp->iananame))) {
9924  fmtp = check;
9925  }
9926  }
9927 
9928  if (smh->fmtps[i]) {
9929  fmtp = smh->fmtps[i];
9930  }
9931 
9932 
9933  if (smh->ianacodes[i] > 95 || switch_channel_test_flag(session->channel, CF_VERBOSE_SDP)) {
9934  int channels = get_channels(imp->iananame, imp->number_of_channels);
9935 
9936  if (channels > 1) {
9937  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d/%d\r\n", smh->ianacodes[i], imp->iananame, rate, channels);
9938 
9939  } else {
9940  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d\r\n", smh->ianacodes[i], imp->iananame, rate);
9941  }
9942  }
9943 
9944  if (fmtp) {
9945  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=fmtp:%d %s\r\n", smh->ianacodes[i], fmtp);
9946  }
9947  }
9948 
9949 
9950  if ((smh->mparams->dtmf_type == DTMF_2833 || switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF)) && smh->mparams->te > 95) {
9951  if (smh->mparams->dtmf_type == DTMF_2833 && sdp_type == SDP_ANSWER) {
9953  if (a_engine) {
9954  payload_map_t *pmap;
9955  for (pmap = a_engine->payload_map; pmap; pmap = pmap->next) {
9956  if (!strncasecmp(pmap->iananame, "telephone-event", 15)) {
9957  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d telephone-event/%d\r\n",
9958  pmap->pt, pmap->rate);
9959  }
9960  }
9961  }
9962  } else {
9963  uint8_t NDLB_line_flash_16 = switch_channel_var_true(session->channel, "NDLB_line_flash_16");
9964 
9965  for (i = 0; i < smh->num_rates; i++) {
9966  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
9967  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d telephone-event/%d\r\n",
9968  smh->dtmf_ianacodes[i], smh->rates[i]);
9969  }
9970  else {
9971  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d telephone-event/%d\r\na=fmtp:%d 0-%d\r\n",
9972  smh->dtmf_ianacodes[i], smh->rates[i], smh->dtmf_ianacodes[i], (NDLB_line_flash_16 ? 16 : 15));
9973  }
9974  }
9975  }
9976  }
9977 
9978  if (!zstr(a_engine->local_dtls_fingerprint.type) && secure) {
9979  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=fingerprint:%s %s\r\na=setup:%s\r\n", a_engine->local_dtls_fingerprint.type,
9980  a_engine->local_dtls_fingerprint.str, get_setup(a_engine, session, sdp_type));
9981  }
9982 
9983  if (smh->mparams->rtcp_audio_interval_msec) {
9984  if (a_engine->rtcp_mux > 0) {
9985  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp-mux\r\n");
9986  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp:%d IN %s %s\r\n", port, family, ip);
9987  } else {
9988  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp:%d IN %s %s\r\n", port + 1, family, ip);
9989  }
9990  }
9991 
9992  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\r\n", a_engine->ssrc);
9993 
9994  if (a_engine->ice_out.cands[0][0].ready) {
9995  char tmp1[11] = "";
9996  char tmp2[11] = "";
9997  char tmp3[11] = "";
9998  uint32_t c1 = (1<<24)*126 + (1<<8)*65535 + (1<<0)*(256 - 1);
9999  uint32_t c2 = c1 - 1;
10000  ice_t *ice_out;
10001 
10002  tmp1[10] = '\0';
10003  tmp2[10] = '\0';
10004  tmp3[10] = '\0';
10005  switch_stun_random_string(tmp1, 10, "0123456789");
10006  switch_stun_random_string(tmp2, 10, "0123456789");
10007  switch_stun_random_string(tmp3, 10, "0123456789");
10008 
10009  gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, NULL, 0);
10010 
10011  ice_out = &a_engine->ice_out;
10012 
10013  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ssrc:%u cname:%s\r\n", a_engine->ssrc, smh->cname);
10014  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ssrc:%u msid:%s a0\r\n", a_engine->ssrc, smh->msid);
10015  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ssrc:%u mslabel:%s\r\n", a_engine->ssrc, smh->msid);
10016  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ssrc:%u label:%sa0\r\n", a_engine->ssrc, smh->msid);
10017 
10018 
10019  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ice-ufrag:%s\r\n", ice_out->ufrag);
10020  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ice-pwd:%s\r\n", ice_out->pwd);
10021 
10022 
10023  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
10024  tmp1, ice_out->cands[0][0].transport, c1,
10025  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
10026  );
10027 
10028  if (include_external && !zstr(smh->mparams->extsipip)) {
10029  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
10030  tmp3, ice_out->cands[0][0].transport, c1,
10031  smh->mparams->extsipip, ice_out->cands[0][0].con_port
10032  );
10033  }
10034 
10035  if (!zstr(a_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) &&
10036  strcmp(a_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
10037  && a_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
10038 
10039  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",
10040  tmp2, ice_out->cands[0][0].transport, c2,
10041  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
10042  a_engine->local_sdp_ip, a_engine->local_sdp_port
10043  );
10044  }
10045 
10047 
10048 
10049  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
10050  tmp1, ice_out->cands[0][0].transport, c1,
10051  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
10052  );
10053 
10054  if (include_external && !zstr(smh->mparams->extsipip)) {
10055  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
10056  tmp3, ice_out->cands[0][0].transport, c1,
10057  smh->mparams->extsipip, ice_out->cands[0][0].con_port
10058  );
10059  }
10060 
10061  if (!zstr(a_engine->local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) &&
10062  strcmp(a_engine->local_sdp_ip, ice_out->cands[0][1].con_addr)
10063  && a_engine->local_sdp_port != ice_out->cands[0][1].con_port) {
10064 
10065  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",
10066  tmp2, ice_out->cands[0][0].transport, c2,
10067  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
10068  a_engine->local_sdp_ip, a_engine->local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
10069  );
10070  }
10071  }
10072 
10073 
10074 
10075 #ifdef GOOGLE_ICE
10076  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ice-options:google-ice\r\n");
10077 #endif
10078  }
10079 
10080 
10081  if (secure && !switch_channel_test_flag(session->channel, CF_DTLS)) {
10082  int i;
10083 
10084  for (i = 0; smh->crypto_suite_order[i] != CRYPTO_INVALID; i++) {
10086 
10087  if ((a_engine->crypto_type == j || a_engine->crypto_type == CRYPTO_INVALID) && !zstr(a_engine->ssec[j].local_crypto_key)) {
10088  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=crypto:%s\r\n", a_engine->ssec[j].local_crypto_key);
10089  }
10090  }
10091  //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\r\n");
10092  }
10093 
10094  if (cng_type) {
10095  for (i = 0; i < smh->num_rates; i++) {
10096  //if (smh->rates[i] == 8000) {
10097  // switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d CN/%d\r\n", cng_type, smh->rates[i]);
10098  //} else {
10099  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d CN/%d\r\n", smh->cng_ianacodes[i], smh->rates[i]);
10100  //}
10101  }
10102  } else {
10104  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=silenceSupp:off - - - -\r\n");
10105  }
10106  }
10107 
10108  if (append_audio) {
10109  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "%s%s", append_audio, end_of(append_audio) == '\n' ? "" : "\r\n");
10110  }
10111 
10112  if (!cur_ptime) {
10113  cur_ptime = ptime;
10114  }
10115 
10116  if (!noptime && cur_ptime) {
10117  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ptime:%d\r\n", cur_ptime);
10118  }
10119 
10120  if (!zstr(sr)) {
10121  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=%s\r\n", sr);
10122  }
10123 }
10124 
10125 //?
10127 {
10128  const char *val;
10129  switch_media_handle_t *smh;
10130 
10131  switch_assert(session);
10132 
10133  if (!(smh = session->media_handle)) {
10134  return;
10135  }
10136 
10137  if ((val = switch_channel_get_variable(session->channel, "dtmf_type"))) {
10138  if (!strcasecmp(val, "rfc2833")) {
10139  smh->mparams->dtmf_type = DTMF_2833;
10140  } else if (!strcasecmp(val, "info")) {
10141  smh->mparams->dtmf_type = DTMF_INFO;
10142  } else if (!strcasecmp(val, "none")) {
10143  smh->mparams->dtmf_type = DTMF_NONE;
10144  }
10145  }
10146 }
10147 
10148 //?
10150 {
10151  sdp_media_t *m;
10152  sdp_parser_t *parser = NULL;
10153  sdp_session_t *sdp;
10154 
10155  if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
10156  return SWITCH_STATUS_FALSE;
10157  }
10158 
10159  if (!(sdp = sdp_session(parser))) {
10160  sdp_parser_free(parser);
10161  return SWITCH_STATUS_FALSE;
10162  }
10163 
10166 
10167  for (m = sdp->sdp_media; m; m = m->m_next) {
10168  if (m->m_proto == sdp_proto_rtp) {
10169  sdp_rtpmap_t *map;
10170 
10171  for (map = m->m_rtpmaps; map; map = map->rm_next) {
10172  if (map->rm_encoding) {
10173  char buf[25] = "";
10174  char key[128] = "";
10175  char *br = NULL;
10176 
10177  if (map->rm_fmtp) {
10178  if ((br = strstr(map->rm_fmtp, "bitrate="))) {
10179  br += 8;
10180  }
10181  }
10182 
10183  switch_snprintf(buf, sizeof(buf), "%d", map->rm_pt);
10184 
10185  if (br) {
10186  switch_snprintf(key, sizeof(key), "%s:%s", map->rm_encoding, br);
10187  } else {
10188  switch_snprintf(key, sizeof(key), "%s", map->rm_encoding);
10189  }
10190 
10192 
10193  if (map->rm_fmtp) {
10194  switch_event_add_header_string(*fmtp, SWITCH_STACK_BOTTOM, key, map->rm_fmtp);
10195  }
10196  }
10197  }
10198  }
10199  }
10200 
10201  sdp_parser_free(parser);
10202 
10203  return SWITCH_STATUS_SUCCESS;
10204 
10205 }
10206 
10207 //?
10209 {
10210  switch_media_handle_t *smh;
10211 
10212  switch_assert(session);
10213 
10214  if (!(smh = session->media_handle)) {
10215  return;
10216  }
10217 
10218  if (smh->sdp_mutex) switch_mutex_lock(smh->sdp_mutex);
10219  smh->mparams->local_sdp_str = dup ? switch_core_session_strdup(session, sdp_str) : (char *) sdp_str;
10220  switch_channel_set_variable(session->channel, "rtp_local_sdp_str", smh->mparams->local_sdp_str);
10221  if (smh->sdp_mutex) switch_mutex_unlock(smh->sdp_mutex);
10222 }
10223 
10224 static void add_fb(char *buf, uint32_t buflen, int pt, int fir, int nack, int pli, int tmmbr)
10225 {
10226  if (fir) {
10227  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp-fb:%d ccm fir\r\n", pt);
10228  }
10229 
10230  if (tmmbr) {
10231  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp-fb:%d ccm tmmbr\r\n", pt);
10232  }
10233 
10234  if (nack) {
10235  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp-fb:%d nack\r\n", pt);
10236  }
10237 
10238  if (pli) {
10239  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp-fb:%d nack pli\r\n", pt);
10240  }
10241 
10242 }
10243 
10244 //?
10245 #define SDPBUFLEN 65536
10247 {
10248  char *buf;
10249  int ptime = 0;
10250  uint32_t rate = 0;
10251  uint32_t v_port, t_port;
10252  int use_cng = 1;
10253  const char *val;
10254  const char *family;
10255  const char *pass_fmtp = switch_channel_get_variable(session->channel, "rtp_video_fmtp");
10256  const char *ov_fmtp = switch_channel_get_variable(session->channel, "rtp_force_video_fmtp");
10257  const char *append_audio = switch_channel_get_variable(session->channel, "rtp_append_audio_sdp");
10258  const char *append_video = switch_channel_get_variable(session->channel, "rtp_append_video_sdp");
10259  char srbuf[128] = "";
10260  const char *var_val;
10261  const char *username;
10262  const char *fmtp_out;
10263  const char *fmtp_out_var = switch_channel_get_variable(session->channel, "rtp_force_audio_fmtp");
10264  switch_event_t *map = NULL, *ptmap = NULL;
10265  //const char *b_sdp = NULL;
10266  //const char *local_audio_crypto_key = switch_core_session_local_crypto_key(session, SWITCH_MEDIA_TYPE_AUDIO);
10267  const char *tmp;
10268  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
10269  switch_media_handle_t *smh;
10270  ice_t *ice_out;
10271  //int vp8 = 0;
10272  //int red = 0;
10273  payload_map_t *pmap;
10274  int is_outbound = switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND;
10275  const char *vbw;
10276  int bw = 256, i = 0;
10277  uint8_t fir = 0, nack = 0, pli = 0, tmmbr = 0, has_vid = 0;
10278  const char *use_rtcp_mux = NULL;
10279  int include_external;
10280 
10281  switch_assert(session);
10282 
10283  if (!(smh = session->media_handle)) {
10284  return;
10285  }
10286 
10287  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
10288  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
10289  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
10290 
10291  include_external = switch_channel_var_true(session->channel, "include_external_ip");
10292 
10293  use_rtcp_mux = switch_channel_get_variable(session->channel, "rtcp_mux");
10294 
10295  if (use_rtcp_mux && switch_false(use_rtcp_mux)) {
10296  a_engine->rtcp_mux = -1;
10297  v_engine->rtcp_mux = -1;
10298  }
10299 
10300  if ((a_engine->rtcp_mux != -1 && v_engine->rtcp_mux != -1) && (sdp_type == SDP_OFFER)) {
10301  a_engine->rtcp_mux = 1;
10302  v_engine->rtcp_mux = 1;
10303  }
10304 
10305  if (!smh->mparams->rtcp_audio_interval_msec) {
10306  smh->mparams->rtcp_audio_interval_msec = (char *)switch_channel_get_variable(session->channel, "rtcp_audio_interval_msec");
10307  }
10308 
10309  if (!smh->mparams->rtcp_video_interval_msec) {
10310  smh->mparams->rtcp_video_interval_msec = (char *)switch_channel_get_variable(session->channel, "rtcp_video_interval_msec");
10311  }
10312 
10313  if (dtls_ok(session) && (tmp = switch_channel_get_variable(smh->session->channel, "webrtc_enable_dtls")) && switch_false(tmp)) {
10316  }
10317 
10318  if (switch_channel_test_flag(session->channel, CF_PROXY_OFF) && (tmp = switch_channel_get_variable(smh->session->channel, "uuid_media_secure_media"))) {
10319  switch_channel_set_variable(smh->session->channel, "rtp_secure_media", tmp);
10322  }
10323 
10324  if (is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING) ||
10326  if (!switch_channel_test_flag(session->channel, CF_AVPF) &&
10327  switch_true(switch_channel_get_variable(session->channel, "media_webrtc"))) {
10332  }
10333 
10334  if (switch_true(switch_channel_get_variable(session->channel, "add_ice_candidates"))) {
10336  }
10337 
10338  if ( switch_rtp_has_dtls() && dtls_ok(session)) {
10339  if (switch_channel_test_flag(session->channel, CF_AVPF) ||
10340  switch_true(switch_channel_get_variable(smh->session->channel, "rtp_use_dtls"))) {
10344  }
10345  }
10348  }
10349 
10350  fmtp_out = a_engine->cur_payload_map->fmtp_out;
10351  username = smh->mparams->sdp_username;
10352 
10353 
10354  switch_zmalloc(buf, SDPBUFLEN);
10355 
10357 
10359  ((val = switch_channel_get_variable(session->channel, "supress_cng")) && switch_true(val)) ||
10360  ((val = switch_channel_get_variable(session->channel, "suppress_cng")) && switch_true(val))) {
10361  use_cng = 0;
10362  smh->mparams->cng_pt = 0;
10363  }
10364 
10365 
10366 
10367 
10368  if (!smh->payload_space) {
10369  /* it could be 98 but chrome reserves 98 and 99 for some internal stuff even though they should not.
10370  Everyone expects dtmf to be at 101 and Its not worth the trouble so we'll start at 102 */
10371  smh->payload_space = 102;
10372  memset(smh->rates, 0, sizeof(smh->rates));
10373  smh->num_rates = 0;
10374 
10375  for (i = 0; i < smh->mparams->num_codecs; i++) {
10376  int j;
10377  smh->ianacodes[i] = smh->codecs[i]->ianacode;
10378 
10379  if (smh->codecs[i]->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
10380  continue;
10381  }
10382 
10383  if (sdp_type == SDP_OFFER) {
10384  for (j = 0; j < SWITCH_MAX_CODECS; j++) {
10385  if (smh->rates[j] == 0) {
10386  break;
10387  }
10388 
10389  if (smh->rates[j] == smh->codecs[i]->samples_per_second) {
10390  goto do_next;
10391  }
10392  }
10393 
10394  smh->rates[smh->num_rates++] = smh->codecs[i]->samples_per_second;
10395  }
10396 
10397  do_next:
10398  continue;
10399  }
10400 
10401  if (sdp_type == SDP_OFFER) {
10402  switch_core_session_t *orig_session = NULL;
10403 
10404  switch_core_session_get_partner(session, &orig_session);
10405 
10406  if (orig_session && !switch_channel_test_flag(session->channel, CF_ANSWERED)) {
10411  }
10412 
10413  for (i = 0; i < smh->mparams->num_codecs; i++) {
10414  const switch_codec_implementation_t *imp = smh->codecs[i];
10415  switch_payload_t orig_pt = 0;
10416  char *orig_fmtp = NULL;
10417 
10418  if (smh->ianacodes[i] > 64) {
10419  if (smh->mparams->dtmf_type == DTMF_2833 && smh->mparams->te > 95 && smh->mparams->te == smh->payload_space) {
10420  smh->payload_space++;
10421  }
10423  smh->mparams->cng_pt && use_cng && smh->mparams->cng_pt == smh->payload_space) {
10424  smh->payload_space++;
10425  }
10426 
10427  if (orig_session &&
10430  imp->iananame, imp->samples_per_second, smh->fmtp[i], &orig_pt, NULL, &orig_fmtp) == SWITCH_STATUS_SUCCESS) {
10431 
10432  if (orig_pt == smh->mparams->te) {
10433  smh->mparams->te = (switch_payload_t)smh->payload_space++;
10434  }
10435 
10436  smh->ianacodes[i] = orig_pt;
10437 
10438  if (!zstr(orig_fmtp)) {
10439  smh->fmtps[i] = switch_core_session_strdup(session, orig_fmtp);
10440  }
10441  } else {
10442  smh->ianacodes[i] = (switch_payload_t)smh->payload_space++;
10443  }
10444  }
10445 
10448  imp->iananame,
10449  imp->modname,
10450  smh->fmtps[i],
10451  sdp_type,
10452  smh->ianacodes[i],
10453  imp->samples_per_second,
10454  imp->microseconds_per_packet / 1000,
10455  imp->number_of_channels,
10456  SWITCH_FALSE);
10457  }
10458 
10459  for (i = 0; i < smh->num_rates; i++) {
10460  if (smh->rates[i] == 8000 || smh->num_rates == 1) {
10461  smh->dtmf_ianacodes[i] = smh->mparams->te;
10462  smh->cng_ianacodes[i] = smh->mparams->cng_pt;
10463  } else {
10464  int j = 0;
10465 
10466  for (j = 0; j < smh->mparams->num_codecs; j++) {
10467  if (smh->ianacodes[j] == smh->payload_space) {
10468  smh->payload_space++;
10469  break;
10470  }
10471  }
10472 
10473  smh->dtmf_ianacodes[i] = (switch_payload_t)smh->payload_space++;
10474  smh->cng_ianacodes[i] = (switch_payload_t)smh->payload_space++;
10475  }
10476  }
10477 
10478 
10479  if (orig_session) {
10480  switch_core_session_rwunlock(orig_session);
10481  }
10482  }
10483  }
10484 
10485  if (fmtp_out_var) {
10486  fmtp_out = fmtp_out_var;
10487  }
10488 
10489  val = switch_channel_get_variable(session->channel, "verbose_sdp");
10490 
10491  if (!val || switch_true(val)) {
10493  }
10494 
10495  if (!force && !ip && zstr(sr)
10497  switch_safe_free(buf);
10498  return;
10499  }
10500 
10501  if (!ip) {
10502  if (!(ip = a_engine->adv_sdp_ip)) {
10503  ip = a_engine->proxy_sdp_ip;
10504  }
10505  }
10506 
10507  if (!ip) {
10509  switch_safe_free(buf);
10510  return;
10511  }
10512 
10513  if (!port) {
10514  if (!(port = a_engine->adv_sdp_port)) {
10515  port = a_engine->proxy_sdp_port;
10516  }
10517  }
10518 
10519  if (!port) {
10521  switch_safe_free(buf);
10522  return;
10523  }
10524 
10525  //if (!a_engine->cur_payload_map->rm_encoding && (b_sdp = switch_channel_get_variable(session->channel, SWITCH_B_SDP_VARIABLE))) {
10526  //switch_core_media_sdp_map(b_sdp, &map, &ptmap);
10527  //}
10528 
10529  for (i = 0; i < smh->mparams->num_codecs; i++) {
10530  const switch_codec_implementation_t *imp = smh->codecs[i];
10531 
10534  break;
10535  }
10536  }
10537 
10538  if (zstr(sr)) {
10539  if (a_engine->smode == SWITCH_MEDIA_FLOW_SENDONLY) {
10540  sr = "sendonly";
10541  } else if (a_engine->smode == SWITCH_MEDIA_FLOW_RECVONLY) {
10542  sr = "recvonly";
10543  } else if (a_engine->smode == SWITCH_MEDIA_FLOW_INACTIVE) {
10544  sr = "inactive";
10545  } else {
10546  sr = "sendrecv";
10547  }
10548 
10549  if ((var_val = switch_channel_get_variable(session->channel, "origination_audio_mode"))) {
10550  if (!strcasecmp(sr, "sendonly") || !strcasecmp(sr, "recvonly") || !strcasecmp(sr, "sendrecv") || !strcasecmp(sr, "inactive")) {
10551  sr = var_val;
10552  }
10553  switch_channel_set_variable(session->channel, "origination_audio_mode", NULL);
10554  }
10555 
10556  if (zstr(sr)) {
10557  sr = "sendrecv";
10558  }
10559  }
10560 
10561  if (!smh->owner_id) {
10562  smh->owner_id = (uint32_t)(switch_time_t)switch_epoch_time_now(NULL) - port;
10563  }
10564 
10565  if (!smh->session_id) {
10566  smh->session_id = smh->owner_id;
10567  }
10568 
10569  if (switch_true(switch_channel_get_variable_dup(session->channel, "drop_dtmf", SWITCH_FALSE, -1))) {
10571  }
10572 
10573  smh->session_id++;
10574 
10575  if ((smh->mparams->ndlb & SM_NDLB_SENDRECV_IN_SESSION) ||
10576  ((var_val = switch_channel_get_variable(session->channel, "ndlb_sendrecv_in_session")) && switch_true(var_val))) {
10577  if (!zstr(sr)) {
10578  switch_snprintf(srbuf, sizeof(srbuf), "a=%s\r\n", sr);
10579  }
10580  sr = NULL;
10581  }
10582 
10583  family = strchr(ip, ':') ? "IP6" : "IP4";
10585  "v=0\r\n"
10586  "o=%s %010u %010u IN %s %s\r\n"
10587  "s=%s\r\n"
10588  "c=IN %s %s\r\n"
10589  "t=0 0\r\n"
10590  "%s",
10591  username, smh->owner_id, smh->session_id, family, ip, username, family, ip, srbuf);
10592 
10593  if (switch_channel_test_flag(smh->session->channel, CF_ICE) && switch_channel_var_true(session->channel, "ice_lite")) {
10594  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-lite\r\n");
10595  }
10596 
10597  if (a_engine->rmode == SWITCH_MEDIA_FLOW_DISABLED) {
10598  goto video;
10599  }
10600 
10602  gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, ip, port);
10603  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=msid-semantic: WMS %s\r\n", smh->msid);
10604  }
10605 
10606  if (a_engine->codec_negotiated && !switch_channel_test_flag(session->channel, CF_NOSDP_REINVITE)) {
10607  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=audio %d %s", port,
10608  get_media_profile_name(session, !a_engine->no_crypto &&
10610 
10611 
10612  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", a_engine->cur_payload_map->pt);
10613 
10614 
10617  for (pmap = a_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
10618  if (pmap->pt != a_engine->cur_payload_map->pt) {
10619  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", pmap->pt);
10620  }
10621  }
10623  }
10624 
10625  if ((smh->mparams->dtmf_type == DTMF_2833 || switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF)) && smh->mparams->te > 95) {
10626  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", smh->mparams->te);
10627  }
10628 
10629  if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && smh->mparams->cng_pt && use_cng) {
10630  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", smh->mparams->cng_pt);
10631  }
10632 
10633  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\r\n");
10634 
10635 
10636  rate = a_engine->cur_payload_map->adv_rm_rate;
10637 
10638  if (!a_engine->cur_payload_map->adv_channels) {
10640  }
10641 
10642  if (a_engine->cur_payload_map->adv_channels > 1) {
10643  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\r\n",
10644  a_engine->cur_payload_map->pt, a_engine->cur_payload_map->rm_encoding, rate, a_engine->cur_payload_map->adv_channels);
10645  } else {
10646  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\r\n",
10647  a_engine->cur_payload_map->pt, a_engine->cur_payload_map->rm_encoding, rate);
10648  }
10649 
10650  if (fmtp_out) {
10651  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\r\n", a_engine->cur_payload_map->pt, fmtp_out);
10652  }
10653 
10656  for (pmap = a_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
10657  if (pmap->pt != a_engine->cur_payload_map->pt) {
10658  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\r\n",
10659  pmap->pt, pmap->iananame,
10660  pmap->rate);
10661  }
10662  }
10664  }
10665 
10666 
10667  if (a_engine->read_codec.implementation && !ptime) {
10668  ptime = a_engine->read_codec.implementation->microseconds_per_packet / 1000;
10669  }
10670 
10671 
10673  && smh->mparams->te > 95) {
10674 
10675  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
10676  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d telephone-event/%d\r\n",
10677  smh->mparams->te, smh->mparams->te_rate);
10678  } else {
10679  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d telephone-event/%d\r\na=fmtp:%d 0-%d\r\n",
10680  smh->mparams->te, smh->mparams->te_rate, smh->mparams->te, (switch_channel_var_true(session->channel, "NDLB_line_flash_16") ? 16 : 15));
10681  }
10682  }
10683 
10685  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=silenceSupp:off - - - -\r\n");
10686  } else if (smh->mparams->cng_pt && use_cng) {
10687  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d CN/%lu\r\n", smh->mparams->cng_pt, smh->mparams->cng_rate);
10688 
10689  if (!a_engine->codec_negotiated) {
10690  smh->mparams->cng_pt = 0;
10691  }
10692  }
10693 
10694  if (append_audio) {
10695  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s%s", append_audio, end_of(append_audio) == '\n' ? "" : "\r\n");
10696  }
10697 
10698  if (ptime) {
10699  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ptime:%d\r\n", ptime);
10700  }
10701 
10702 
10703  if (!zstr(sr)) {
10704  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=%s\r\n", sr);
10705  }
10706 
10707 
10708  if (!zstr(a_engine->local_dtls_fingerprint.type)) {
10709  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fingerprint:%s %s\r\na=setup:%s\r\n",
10710  a_engine->local_dtls_fingerprint.type,
10711  a_engine->local_dtls_fingerprint.str, get_setup(a_engine, session, sdp_type));
10712  }
10713 
10714  if (smh->mparams->rtcp_audio_interval_msec) {
10715  if (a_engine->rtcp_mux > 0) {
10716  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp-mux\r\n");
10717  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\r\n", port, family, ip);
10718  } else {
10719  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\r\n", port + 1, family, ip);
10720  }
10721  }
10722 
10723  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\r\n", a_engine->ssrc);
10724 
10725  if (a_engine->ice_out.cands[0][0].ready) {
10726  char tmp1[11] = "";
10727  char tmp2[11] = "";
10728  char tmp3[11] = "";
10729  uint32_t c1 = (1<<24)*126 + (1<<8)*65535 + (1<<0)*(256 - 1);
10730  uint32_t c2 = c1 - 1;
10731  uint32_t c3 = c1 - 2;
10732  uint32_t c4 = c1 - 3;
10733 
10734  tmp1[10] = '\0';
10735  tmp2[10] = '\0';
10736  tmp3[10] = '\0';
10737  switch_stun_random_string(tmp1, 10, "0123456789");
10738  switch_stun_random_string(tmp2, 10, "0123456789");
10739  switch_stun_random_string(tmp3, 10, "0123456789");
10740 
10741  ice_out = &a_engine->ice_out;
10742 
10743 
10744  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-ufrag:%s\r\n", ice_out->ufrag);
10745  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-pwd:%s\r\n", ice_out->pwd);
10746 
10747 
10748  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
10749  tmp1, ice_out->cands[0][0].transport, c1,
10750  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
10751  );
10752 
10753  if (include_external && !zstr(smh->mparams->extsipip)) {
10754  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
10755  tmp3, ice_out->cands[0][0].transport, c1,
10756  smh->mparams->extsipip, ice_out->cands[0][0].con_port
10757  );
10758  }
10759 
10760  if (!zstr(a_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) &&
10761  strcmp(a_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
10762  && a_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
10763 
10764  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",
10765  tmp2, ice_out->cands[0][0].transport, c3,
10766  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
10767  a_engine->local_sdp_ip, a_engine->local_sdp_port
10768  );
10769  }
10770 
10771 
10772  if (a_engine->rtcp_mux < 1 || is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING)) {
10773 
10774  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
10775  tmp1, ice_out->cands[0][0].transport, c2,
10776  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
10777  );
10778 
10779  if (include_external && !zstr(smh->mparams->extsipip)) {
10780  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
10781  tmp3, ice_out->cands[0][0].transport, c2,
10782  smh->mparams->extsipip, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
10783  );
10784  }
10785 
10786 
10787 
10788  if (!zstr(a_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) &&
10789  strcmp(a_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
10790  && a_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
10791 
10792  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",
10793  tmp2, ice_out->cands[0][0].transport, c4,
10794  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
10795  a_engine->local_sdp_ip, a_engine->local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
10796  );
10797  }
10798  }
10799 
10800  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=end-of-candidates\r\n");
10801 
10802  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u cname:%s\r\n", a_engine->ssrc, smh->cname);
10803  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u msid:%s a0\r\n", a_engine->ssrc, smh->msid);
10804  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u mslabel:%s\r\n", a_engine->ssrc, smh->msid);
10805  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u label:%sa0\r\n", a_engine->ssrc, smh->msid);
10806 
10807 
10808 #ifdef GOOGLE_ICE
10809  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-options:google-ice\r\n");
10810 #endif
10811  }
10812 
10813  if (a_engine->crypto_type != CRYPTO_INVALID && !switch_channel_test_flag(session->channel, CF_DTLS) &&
10814  !zstr(a_engine->ssec[a_engine->crypto_type].local_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) {
10815 
10816  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\r\n", a_engine->ssec[a_engine->crypto_type].local_crypto_key);
10817  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=encryption:optional\r\n");
10818  }
10819 
10820  if (a_engine->reject_avp) {
10821  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=audio 0 RTP/AVP 19\r\n");
10822  }
10823 
10824  } else if (smh->mparams->num_codecs) {
10825  int cur_ptime = 0, this_ptime = 0, cng_type = 0;
10826  const char *mult;
10827 
10828 
10829  if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && smh->mparams->cng_pt && use_cng) {
10830  cng_type = smh->mparams->cng_pt;
10831 
10832  if (!a_engine->codec_negotiated) {
10833  smh->mparams->cng_pt = 0;
10834  }
10835  }
10836 
10837  mult = switch_channel_get_variable(session->channel, "sdp_m_per_ptime");
10838 
10839  if (switch_channel_test_flag(session->channel, CF_AVPF) || (mult && switch_false(mult))) {
10840  char *bp = buf;
10841  int both = (switch_channel_test_flag(session->channel, CF_AVPF) || switch_channel_test_flag(session->channel, CF_DTLS)) ? 0 : 1;
10842 
10843  if ((!a_engine->no_crypto && switch_channel_test_flag(session->channel, CF_SECURE)) ||
10845  generate_m(session, buf, SDPBUFLEN, port, family, ip, 0, append_audio, sr, use_cng, cng_type, map, 1, sdp_type);
10846  bp = (buf + strlen(buf));
10847 
10848  if (smh->crypto_mode == CRYPTO_MODE_MANDATORY) {
10849  both = 0;
10850  }
10851 
10852  }
10853 
10854  if (both) {
10855  generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, 0, append_audio, sr, use_cng, cng_type, map, 0, sdp_type);
10856  }
10857 
10858  } else {
10859 
10860  for (i = 0; i < smh->mparams->num_codecs; i++) {
10861  const switch_codec_implementation_t *imp = smh->codecs[i];
10862 
10863  if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
10864  continue;
10865  }
10866 
10867  this_ptime = imp->microseconds_per_packet / 1000;
10868 
10869  if (!strcasecmp(imp->iananame, "ilbc") || !strcasecmp(imp->iananame, "isac")) {
10870  this_ptime = 20;
10871  }
10872 
10873  if (cur_ptime != this_ptime) {
10874  char *bp = buf;
10875  int both = 1;
10876 
10877  cur_ptime = this_ptime;
10878 
10879  if ((!a_engine->no_crypto && switch_channel_test_flag(session->channel, CF_SECURE)) ||
10881  generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, cur_ptime, append_audio, sr, use_cng, cng_type, map, 1, sdp_type);
10882  bp = (buf + strlen(buf));
10883 
10884  if (smh->crypto_mode == CRYPTO_MODE_MANDATORY) {
10885  both = 0;
10886  }
10887  }
10888 
10890  both = 0;
10891  }
10892 
10893  if (both) {
10894  generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, cur_ptime, append_audio, sr, use_cng, cng_type, map, 0, sdp_type);
10895  }
10896  }
10897 
10898  }
10899  }
10900 
10901  }
10902 
10904  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=image 0 UDPTL T38\r\n", SWITCH_VA_NONE);
10905 
10906  }
10907 
10908 
10909  video:
10910 
10911 
10913  has_vid = 0;
10914  } else {
10915  for (i = 0; i < smh->mparams->num_codecs; i++) {
10916  const switch_codec_implementation_t *imp = smh->codecs[i];
10917 
10918 
10919  if (imp->codec_type == SWITCH_CODEC_TYPE_VIDEO) {
10920  has_vid = 1;
10921  break;
10922  }
10923  }
10924 
10925  }
10926 
10927 
10928  if (!has_vid) {
10931  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=video 0 %s 19\r\n",
10932  get_media_profile_name(session,
10936  }
10937  } else {
10940  v_engine->no_crypto = 1;
10941  }
10942  }
10943 
10944 
10945  if (!v_engine->local_sdp_port) {
10947  }
10948 
10949  //if (switch_channel_test_flag(session->channel, CF_AVPF)) {
10950  // switch_media_handle_set_media_flag(smh, SCMF_MULTI_ANSWER_VIDEO);
10951  //}
10952 
10953  if ((v_port = v_engine->adv_sdp_port)) {
10954  int loops;
10955  int got_vid = 0;
10956 
10957  for (loops = 0; loops < 2; loops++) {
10958 
10960  gen_ice(session, SWITCH_MEDIA_TYPE_VIDEO, ip, (switch_port_t)v_port);
10961  }
10962 
10963 
10964  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=video %d %s",
10965  v_port,
10966  get_media_profile_name(session,
10967  (loops == 0 && switch_channel_test_flag(session->channel, CF_SECURE)
10970 
10971 
10972 
10973 
10974  /*****************************/
10975  if (v_engine->codec_negotiated) {
10976  payload_map_t *pmap;
10978  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", v_engine->cur_payload_map->pt);
10979 
10982  for (pmap = v_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
10983  if (pmap->pt != v_engine->cur_payload_map->pt && pmap->negotiated) {
10984  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", pmap->pt);
10985  }
10986  }
10988  }
10989 
10990  } else if (smh->mparams->num_codecs) {
10991  int already_did[128] = { 0 };
10992  for (i = 0; i < smh->mparams->num_codecs; i++) {
10993  const switch_codec_implementation_t *imp = smh->codecs[i];
10994 
10995 
10996  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
10997  continue;
10998  }
10999 
11002  continue;
11003  }
11004 
11005  if (smh->ianacodes[i] >= 128 || already_did[smh->ianacodes[i]]) {
11006  continue;
11007  }
11008 
11010  for (pmap = v_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
11011  if (pmap->negotiated && !strcasecmp(imp->iananame, pmap->iananame)) {
11012  smh->ianacodes[i] = pmap->pt;
11013  break;
11014  }
11015  }
11017 
11018  already_did[smh->ianacodes[i]] = 1;
11019 
11020  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", smh->ianacodes[i]);
11021 
11022  if (!ptime) {
11023  ptime = imp->microseconds_per_packet / 1000;
11024  }
11025 
11026  got_vid++;
11027  }
11028  }
11029  if (got_vid && v_engine->smode == SWITCH_MEDIA_FLOW_DISABLED) {
11031  }
11032 
11033  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\r\n");
11034 
11035 
11036  if (!(vbw = switch_channel_get_variable(smh->session->channel, "rtp_video_max_bandwidth"))) {
11037  vbw = switch_channel_get_variable(smh->session->channel, "rtp_video_max_bandwidth_in");
11038  }
11039 
11040  if (!vbw) {
11041  vbw = "1mb";
11042  }
11043 
11045 
11046  if (bw > 0) {
11047  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "b=AS:%d\r\n", bw);
11048  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "b=TIAS:%d\r\n", bw);
11049  }
11050 
11051 
11052 
11053  if (v_engine->codec_negotiated) {
11054  payload_map_t *pmap;
11055 
11056  //if (!strcasecmp(v_engine->cur_payload_map->rm_encoding, "VP8")) {
11057  // vp8 = v_engine->cur_payload_map->pt;
11058  //}
11059 
11060  //if (!strcasecmp(v_engine->cur_payload_map->rm_encoding, "red")) {
11061  // red = v_engine->cur_payload_map->pt;
11062  //}
11063 
11064  rate = v_engine->cur_payload_map->rm_rate;
11065  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\r\n",
11066  v_engine->cur_payload_map->pt, v_engine->cur_payload_map->rm_encoding,
11067  v_engine->cur_payload_map->rm_rate);
11068 
11070  pass_fmtp = v_engine->cur_payload_map->rm_fmtp;
11071  } else {
11072 
11073  pass_fmtp = NULL;
11074 
11075  if (ov_fmtp) {
11076  pass_fmtp = ov_fmtp;
11077  } else {
11078 
11079  pass_fmtp = v_engine->cur_payload_map->fmtp_out;
11080 
11081  if (!pass_fmtp || switch_true(switch_channel_get_variable_dup(session->channel, "rtp_mirror_fmtp", SWITCH_FALSE, -1))) {
11082  pass_fmtp = switch_channel_get_variable(session->channel, "rtp_video_fmtp");
11083  }
11084  }
11085  }
11086 
11087 
11088  if (pass_fmtp) {
11089  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\r\n", v_engine->cur_payload_map->pt, pass_fmtp);
11090  }
11091 
11092 
11095  for (pmap = v_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
11096  if (pmap->pt != v_engine->cur_payload_map->pt && pmap->negotiated) {
11097  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\r\n",
11098  pmap->pt, pmap->iananame, pmap->rate);
11099  }
11100  }
11102  }
11103 
11104 
11105  if (append_video) {
11106  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s%s", append_video, end_of(append_video) == '\n' ? "" : "\r\n");
11107  }
11108 
11109  } else if (smh->mparams->num_codecs) {
11110  int already_did[128] = { 0 };
11111 
11112  for (i = 0; i < smh->mparams->num_codecs; i++) {
11113  const switch_codec_implementation_t *imp = smh->codecs[i];
11114  char *fmtp = NULL;
11115  uint32_t ianacode = smh->ianacodes[i];
11116  int channels;
11117 
11118  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
11119  continue;
11120  }
11121 
11124  continue;
11125  }
11126 
11127  if (ianacode < 128) {
11128  if (already_did[ianacode]) {
11129  continue;
11130  }
11131  already_did[ianacode] = 1;
11132  }
11133 
11134  if (!rate) {
11135  rate = imp->samples_per_second;
11136  }
11137 
11138  channels = get_channels(imp->iananame, imp->number_of_channels);
11139 
11140  //if (!strcasecmp(imp->iananame, "VP8")) {
11141  // vp8 = ianacode;
11142  //}
11143 
11144  //if (!strcasecmp(imp->iananame, "red")) {
11145  // red = ianacode;
11146  //}
11147 
11148  if (channels > 1) {
11149  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\r\n", ianacode, imp->iananame,
11150  imp->samples_per_second, channels);
11151  } else {
11152  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\r\n", ianacode, imp->iananame,
11153  imp->samples_per_second);
11154  }
11155 
11156 
11157 
11158  if (!zstr(ov_fmtp)) {
11159  fmtp = (char *) ov_fmtp;
11160  } else {
11161 
11162  if (map) {
11163  fmtp = switch_event_get_header(map, imp->iananame);
11164  }
11165 
11166  if (!zstr(smh->fmtp[i])) {
11167  fmtp = smh->fmtp[i];
11168  } else if (smh->fmtps[i]) {
11169  fmtp = smh->fmtps[i];
11170  }
11171 
11172  if (zstr(fmtp)) fmtp = imp->fmtp;
11173 
11174  if (zstr(fmtp)) fmtp = (char *) pass_fmtp;
11175  }
11176 
11177  if (!zstr(fmtp) && strcasecmp(fmtp, "_blank_")) {
11178  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\r\n", ianacode, fmtp);
11179  }
11180  }
11181 
11182  }
11183 
11184  if (v_engine->smode == SWITCH_MEDIA_FLOW_SENDRECV) {
11185  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=sendrecv\r\n");
11186  } else if (v_engine->smode == SWITCH_MEDIA_FLOW_SENDONLY) {
11187  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=sendonly\r\n");
11188  } else if (v_engine->smode == SWITCH_MEDIA_FLOW_RECVONLY) {
11189  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=recvonly\r\n");
11190  } else if (v_engine->smode == SWITCH_MEDIA_FLOW_INACTIVE) {
11191  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=inactive\r\n");
11192  }
11193 
11194 
11195  if ((is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING))
11198  }
11199 
11200 
11201  if (!zstr(v_engine->local_dtls_fingerprint.type)) {
11202  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fingerprint:%s %s\r\na=setup:%s\r\n",
11203  v_engine->local_dtls_fingerprint.type, v_engine->local_dtls_fingerprint.str, get_setup(v_engine, session, sdp_type));
11204  }
11205 
11206 
11207  if (smh->mparams->rtcp_video_interval_msec) {
11208  if (v_engine->rtcp_mux > 0) {
11209  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp-mux\r\n");
11210  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\r\n", v_port, family, ip);
11211  } else {
11212  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\r\n", v_port + 1, family, ip);
11213  }
11214  }
11215 
11216  if (sdp_type == SDP_OFFER) {
11217  fir++;
11218  pli++;
11219  nack++;
11220  tmmbr++;
11221  }
11222 
11223  /* DFF nack pli etc */
11224  //nack = v_engine->nack = 0;
11225  //pli = v_engine->pli = 0;
11226 
11227 
11228  if (v_engine->codec_negotiated) {
11229  add_fb(buf, SDPBUFLEN, v_engine->cur_payload_map->pt, v_engine->fir || fir,
11230  v_engine->nack || nack, v_engine->pli || pli, v_engine->tmmbr || tmmbr);
11231 
11234  for (pmap = v_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
11235  if (pmap->pt != v_engine->cur_payload_map->pt && pmap->negotiated) {
11236  add_fb(buf, SDPBUFLEN, pmap->pt, v_engine->fir || fir, v_engine->nack || nack, v_engine->pli || pli, v_engine->tmmbr || tmmbr);
11237  }
11238  }
11240  }
11241 
11242  } else if (smh->mparams->num_codecs) {
11243  int already_did[128] = { 0 };
11244  for (i = 0; i < smh->mparams->num_codecs; i++) {
11245  const switch_codec_implementation_t *imp = smh->codecs[i];
11246 
11247 
11248  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
11249  continue;
11250  }
11251 
11254  continue;
11255  }
11256 
11257  if (smh->ianacodes[i] < 128) {
11258  if (already_did[smh->ianacodes[i]]) {
11259  continue;
11260  }
11261  already_did[smh->ianacodes[i]] = 1;
11262  }
11263 
11264  add_fb(buf, SDPBUFLEN, smh->ianacodes[i], v_engine->fir || fir, v_engine->nack || nack, v_engine->pli || pli, v_engine->pli || pli);
11265  }
11266 
11267  }
11268 
11269  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\r\n", v_engine->ssrc);
11270 
11271  if (v_engine->ice_out.cands[0][0].ready) {
11272  char tmp1[11] = "";
11273  char tmp2[11] = "";
11274  char tmp3[11] = "";
11275  uint32_t c1 = (1<<24)*126 + (1<<8)*65535 + (1<<0)*(256 - 1);
11276  uint32_t c2 = c1 - 1;
11277  uint32_t c3 = c1 - 2;
11278  uint32_t c4 = c1 - 3;
11279 
11280  tmp1[10] = '\0';
11281  tmp2[10] = '\0';
11282  tmp3[10] = '\0';
11283  switch_stun_random_string(tmp1, 10, "0123456789");
11284  switch_stun_random_string(tmp2, 10, "0123456789");
11285  switch_stun_random_string(tmp3, 10, "0123456789");
11286 
11287  ice_out = &v_engine->ice_out;
11288 
11289 
11290  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u cname:%s\r\n", v_engine->ssrc, smh->cname);
11291  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u msid:%s v0\r\n", v_engine->ssrc, smh->msid);
11292  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u mslabel:%s\r\n", v_engine->ssrc, smh->msid);
11293  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u label:%sv0\r\n", v_engine->ssrc, smh->msid);
11294 
11295 
11296 
11297  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-ufrag:%s\r\n", ice_out->ufrag);
11298  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-pwd:%s\r\n", ice_out->pwd);
11299 
11300 
11301  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
11302  tmp1, ice_out->cands[0][0].transport, c1,
11303  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
11304  );
11305 
11306  if (include_external && !zstr(smh->mparams->extsipip)) {
11307  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
11308  tmp3, ice_out->cands[0][0].transport, c1,
11309  smh->mparams->extsipip, ice_out->cands[0][0].con_port
11310  );
11311  }
11312 
11313  if (!zstr(v_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) &&
11314  strcmp(v_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
11315  && v_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
11316 
11317  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",
11318  tmp2, ice_out->cands[0][0].transport, c3,
11319  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
11320  v_engine->local_sdp_ip, v_engine->local_sdp_port
11321  );
11322  }
11323 
11324 
11325  if (v_engine->rtcp_mux < 1 || is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING)) {
11326 
11327  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
11328  tmp1, ice_out->cands[0][0].transport, c2,
11329  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
11330  );
11331 
11332  if (include_external && !zstr(smh->mparams->extsipip)) {
11333  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
11334  tmp3, ice_out->cands[0][0].transport, c2,
11335  smh->mparams->extsipip, ice_out->cands[0][0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
11336  );
11337  }
11338 
11339 
11340  if (!zstr(v_engine->local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) &&
11341  strcmp(v_engine->local_sdp_ip, ice_out->cands[0][1].con_addr)
11342  && v_engine->local_sdp_port != ice_out->cands[0][1].con_port) {
11343 
11344  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx generation 0\r\n",
11345  tmp2, ice_out->cands[0][0].transport, c4,
11346  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1),
11347  v_engine->local_sdp_ip, v_engine->local_sdp_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
11348  );
11349  }
11350  }
11351 
11352 
11353 
11354 #ifdef GOOGLE_ICE
11355  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-options:google-ice\r\n");
11356 #endif
11357  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=end-of-candidates\r\n");
11358 
11359  }
11360 
11361 
11362 
11363  if (loops == 0 && switch_channel_test_flag(session->channel, CF_SECURE) && !switch_channel_test_flag(session->channel, CF_DTLS)) {
11364 
11365  for (i = 0; smh->crypto_suite_order[i] != CRYPTO_INVALID; i++) {
11367 
11368  if ((a_engine->crypto_type == j || a_engine->crypto_type == CRYPTO_INVALID) && !zstr(a_engine->ssec[j].local_crypto_key)) {
11369  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\r\n", v_engine->ssec[j].local_crypto_key);
11370  }
11371  }
11372  //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\r\n");
11373  }
11374 
11375 
11376  if (switch_channel_test_flag(session->channel, CF_DTLS) ||
11379  break;
11380  }
11381  }
11382  }
11383 
11384  }
11385 
11386  if (switch_channel_test_cap(session->channel, CC_MSRP) && !smh->msrp_session) {
11387  int want_msrp = switch_channel_var_true(session->channel, "sip_enable_msrp");
11388  int want_msrps = switch_channel_var_true(session->channel, "sip_enable_msrps");
11389 
11390  if (!want_msrp) {
11391  want_msrp = switch_channel_test_flag(session->channel, CF_WANT_MSRP);
11392  }
11393 
11394  if (!want_msrps) {
11395  want_msrps = switch_channel_test_flag(session->channel, CF_WANT_MSRPS);
11396  }
11397 
11398  if (want_msrp || want_msrps) {
11400 
11402  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "MSRP session created %s\n", smh->msrp_session->call_id);
11403 
11408 
11409  if (want_msrps) {
11411  }
11412 
11414  }
11415  }
11416 
11417  if (smh->msrp_session) {
11418  switch_msrp_session_t *msrp_session = smh->msrp_session;
11419 
11420  if (!zstr(msrp_session->remote_path)) {
11421  if (zstr(msrp_session->local_path)) {
11422  msrp_session->local_path = switch_core_session_sprintf(session,
11423  "msrp%s://%s:%d/%s;tcp",
11424  msrp_session->secure ? "s" : "",
11425  ip, msrp_session->local_port, msrp_session->call_id);
11426  }
11427 
11428  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf),
11429  "m=message %d TCP/%sMSRP *\r\n"
11430  "a=path:%s\r\n"
11431  "a=accept-types:%s\r\n"
11432  "a=accept-wrapped-types:%s\r\n"
11433  "a=setup:%s\r\n",
11434  msrp_session->local_port,
11435  msrp_session->secure ? "TLS/" : "",
11436  msrp_session->local_path,
11437  msrp_session->local_accept_types,
11438  msrp_session->local_accept_wrapped_types,
11439  msrp_session->active ? "active" : "passive");
11440  } else {
11441  char *uuid = switch_core_session_get_uuid(session);
11442  const char *file_selector = switch_channel_get_variable(session->channel, "sip_msrp_local_file_selector");
11443  const char *msrp_offer_active = switch_channel_get_variable(session->channel, "sip_msrp_offer_active");
11444 
11445  if (switch_true(msrp_offer_active)) {
11446  msrp_session->active = 1;
11447  // switch_msrp_start_client(msrp_session);
11448  }
11449 
11450  if (zstr(msrp_session->local_path)) {
11451  msrp_session->local_path = switch_core_session_sprintf(session,
11452  "msrp%s://%s:%d/%s;tcp",
11453  msrp_session->secure ? "s" : "",
11454  ip, msrp_session->local_port, uuid);
11455  }
11456 
11457  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf),
11458  "m=message %d TCP/%sMSRP *\r\n"
11459  "a=path:%s\r\n"
11460  "a=accept-types:message/cpim text/* application/im-iscomposing+xml\r\n"
11461  "a=accept-wrapped-types:*\r\n"
11462  "a=setup:%s\r\n",
11463  msrp_session->local_port,
11464  msrp_session->secure ? "TLS/" : "",
11465  msrp_session->local_path,
11466  msrp_session->active ? "active" : "passive");
11467 
11468  if (!zstr(file_selector)) {
11469  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf),
11470  "a=sendonly\r\na=file-selector:%s\r\n", file_selector);
11471  }
11472  }
11473  }
11474 
11475  // RTP TEXT
11476 
11477  if (sdp_type == SDP_ANSWER && !switch_channel_test_flag(session->channel, CF_RTT)) {
11480  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=text 0 %s 19\r\n",
11481  get_media_profile_name(session,
11485  }
11486  } else if ((switch_channel_test_flag(session->channel, CF_WANT_RTT) || switch_channel_test_flag(session->channel, CF_RTT) ||
11487  switch_channel_var_true(session->channel, "rtp_enable_text")) &&
11489  t_engine->t140_pt = 0;
11490  t_engine->red_pt = 0;
11491 
11492  if (sdp_type == SDP_OFFER) {
11493  t_engine->t140_pt = 96;
11494  t_engine->red_pt = 97;
11495 
11498  "red",
11499  NULL,
11500  NULL,
11501  SDP_OFFER,
11502  t_engine->red_pt,
11503  1000,
11504  0,
11505  1,
11506  SWITCH_TRUE);
11507 
11510  "t140",
11511  NULL,
11512  NULL,
11513  SDP_OFFER,
11514  t_engine->t140_pt,
11515  1000,
11516  0,
11517  1,
11518  SWITCH_TRUE);
11519 
11520  t_engine->codec_negotiated = 1;
11521  }
11522 
11525  t_engine->no_crypto = 1;
11526  }
11527  }
11528 
11529 
11530  if (!t_engine->local_sdp_port) {
11532  }
11533 
11534  if ((t_port = t_engine->adv_sdp_port)) {
11535  int loops;
11536 
11537  for (loops = 0; loops < 2; loops++) {
11538 
11540  gen_ice(session, SWITCH_MEDIA_TYPE_TEXT, ip, (switch_port_t)t_port);
11541  }
11542 
11543 
11544  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=text %d %s",
11545  t_port,
11546  get_media_profile_name(session,
11547  (loops == 0 && switch_channel_test_flag(session->channel, CF_SECURE)
11550 
11551 
11552  /*****************************/
11553  if (t_engine->codec_negotiated) {
11554 
11556  for (pmap = t_engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) {
11557 
11558  if (pmap->type != SWITCH_MEDIA_TYPE_TEXT || !pmap->negotiated) {
11559  continue;
11560  }
11561 
11562  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", pmap->pt);
11563 
11564  }
11566  } else {
11568  }
11569 
11570  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\r\n");
11571 
11572  if (t_engine->codec_negotiated) {
11574  for (pmap = t_engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) {
11575 
11576  if (pmap->type != SWITCH_MEDIA_TYPE_TEXT || !pmap->negotiated) {
11577  continue;
11578  }
11579 
11580  if (!strcasecmp(pmap->iananame, "t140")) {
11581  t_engine->t140_pt = pmap->pt;
11582  }
11583 
11584  if (!strcasecmp(pmap->iananame, "red")) {
11585  t_engine->red_pt = pmap->pt;
11586  }
11587 
11588  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\r\n",
11589  pmap->pt, pmap->iananame, pmap->rate);
11590 
11591  }
11593 
11594 
11595  if (t_engine->t140_pt && t_engine->red_pt) {
11596  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %d/%d/%d\r\n", t_engine->red_pt, t_engine->t140_pt, t_engine->t140_pt, t_engine->t140_pt);
11597  }
11598 
11599 
11600  if (t_engine->smode == SWITCH_MEDIA_FLOW_SENDONLY) {
11601  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=sendonly\r\n");
11602  } else if (t_engine->smode == SWITCH_MEDIA_FLOW_RECVONLY) {
11603  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=recvonly\r\n");
11604  }
11605 
11606  }
11607 
11608  if ((is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING))
11611  }
11612 
11613 
11614  if (!zstr(t_engine->local_dtls_fingerprint.type)) {
11615  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fingerprint:%s %s\r\na=setup:%s\r\n", t_engine->local_dtls_fingerprint.type,
11616  t_engine->local_dtls_fingerprint.str, get_setup(t_engine, session, sdp_type));
11617  }
11618 
11619 
11620  if (smh->mparams->rtcp_text_interval_msec) {
11621  if (t_engine->rtcp_mux > 0) {
11622  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp-mux\r\n");
11623  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\r\n", t_port, family, ip);
11624  } else {
11625  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\r\n", t_port + 1, family, ip);
11626  }
11627  }
11628 
11629  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\r\n", t_engine->ssrc);
11630 
11631  if (t_engine->ice_out.cands[0][0].ready) {
11632  char tmp1[11] = "";
11633  char tmp2[11] = "";
11634  uint32_t c1 = (1<<24)*126 + (1<<8)*65535 + (1<<0)*(256 - 1);
11635  uint32_t c2 = c1 - 1;
11636  uint32_t c3 = c1 - 2;
11637  uint32_t c4 = c1 - 3;
11638 
11639  tmp1[10] = '\0';
11640  tmp2[10] = '\0';
11641  switch_stun_random_string(tmp1, 10, "0123456789");
11642  switch_stun_random_string(tmp2, 10, "0123456789");
11643 
11644  ice_out = &t_engine->ice_out;
11645 
11646 
11647  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u cname:%s\r\n", t_engine->ssrc, smh->cname);
11648  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u msid:%s v0\r\n", t_engine->ssrc, smh->msid);
11649  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u mslabel:%s\r\n", t_engine->ssrc, smh->msid);
11650  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u label:%sv0\r\n", t_engine->ssrc, smh->msid);
11651 
11652 
11653 
11654  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-ufrag:%s\r\n", ice_out->ufrag);
11655  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-pwd:%s\r\n", ice_out->pwd);
11656 
11657 
11658  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
11659  tmp1, ice_out->cands[0][0].transport, c1,
11660  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
11661  );
11662 
11663  if (!zstr(t_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) &&
11664  strcmp(t_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
11665  && t_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
11666 
11667  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",
11668  tmp2, ice_out->cands[0][0].transport, c3,
11669  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
11670  t_engine->local_sdp_ip, t_engine->local_sdp_port
11671  );
11672  }
11673 
11674 
11675  if (t_engine->rtcp_mux < 1 || is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING)) {
11676 
11677  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
11678  tmp1, ice_out->cands[0][0].transport, c2,
11679  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (t_engine->rtcp_mux > 0 ? 0 : 1)
11680  );
11681 
11682 
11683  if (!zstr(t_engine->local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) &&
11684  strcmp(t_engine->local_sdp_ip, ice_out->cands[0][1].con_addr)
11685  && t_engine->local_sdp_port != ice_out->cands[0][1].con_port) {
11686 
11687  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx generation 0\r\n",
11688  tmp2, ice_out->cands[0][0].transport, c4,
11689  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (t_engine->rtcp_mux > 0 ? 0 : 1),
11690  t_engine->local_sdp_ip, t_engine->local_sdp_port + (t_engine->rtcp_mux > 0 ? 0 : 1)
11691  );
11692  }
11693  }
11694 
11695 
11696 
11697 #ifdef GOOGLE_ICE
11698  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-options:google-ice\r\n");
11699 #endif
11700  }
11701 
11702 
11703 
11704  if (loops == 0 && switch_channel_test_flag(session->channel, CF_SECURE) && !switch_channel_test_flag(session->channel, CF_DTLS)) {
11705 
11706  for (i = 0; smh->crypto_suite_order[i] != CRYPTO_INVALID; i++) {
11708 
11709  if ((t_engine->crypto_type == j || t_engine->crypto_type == CRYPTO_INVALID) && !zstr(t_engine->ssec[j].local_crypto_key)) {
11710  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\r\n", t_engine->ssec[j].local_crypto_key);
11711  }
11712  }
11713  //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\r\n");
11714  }
11715 
11716 
11717  if (switch_channel_test_flag(session->channel, CF_DTLS) ||
11720  break;
11721  }
11722  }
11723  }
11724 
11725  }
11726 
11727  if (map) {
11728  switch_event_destroy(&map);
11729  }
11730 
11731  if (ptmap) {
11732  switch_event_destroy(&ptmap);
11733  }
11734 
11736 
11737  check_stream_changes(session, NULL, sdp_type);
11738 
11739  switch_safe_free(buf);
11740 }
11741 
11742 
11743 
11744 //?
11746 {
11747  const char *sdp_str;
11748  switch_rtp_engine_t *a_engine;
11749  switch_media_handle_t *smh;
11750 
11751  switch_assert(session);
11752 
11753  if (!(smh = session->media_handle)) {
11754  return;
11755  }
11756 
11757  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
11758 
11759  if ((sdp_str = switch_channel_get_variable(session->channel, SWITCH_B_SDP_VARIABLE))) {
11760  sdp_parser_t *parser;
11761  sdp_session_t *sdp;
11762  sdp_media_t *m;
11763  sdp_connection_t *connection;
11764 
11765  if ((parser = sdp_parse(NULL, sdp_str, (int) strlen(sdp_str), 0))) {
11766  if ((sdp = sdp_session(parser))) {
11767  for (m = sdp->sdp_media; m; m = m->m_next) {
11768  if (m->m_type != sdp_media_audio || !m->m_port) {
11769  continue;
11770  }
11771 
11772  connection = sdp->sdp_connection;
11773  if (m->m_connections) {
11774  connection = m->m_connections;
11775  }
11776 
11777  if (connection) {
11778  a_engine->proxy_sdp_ip = switch_core_session_strdup(session, connection->c_address);
11779  }
11780  a_engine->proxy_sdp_port = (switch_port_t) m->m_port;
11781  if (a_engine->proxy_sdp_ip && a_engine->proxy_sdp_port) {
11782  break;
11783  }
11784  }
11785  }
11786  sdp_parser_free(parser);
11787  }
11788  switch_core_media_set_local_sdp(session, sdp_str, SWITCH_TRUE);
11789  }
11790 }
11791 
11793 {
11794  int x;
11795 
11796  for (x = 0; x < smh->rej_idx; x++) {
11797  if (smh->rejected_streams[x] == st) {
11798  return SWITCH_TRUE;
11799  }
11800  }
11801 
11802  return SWITCH_FALSE;
11803 }
11804 
11805 //?
11807 {
11808  char buf[2048] = "";
11809  char max_buf[128] = "";
11810  char max_data[128] = "";
11811  const char *ip;
11812  uint32_t port;
11813  const char *family = "IP4";
11814  const char *username;
11815  const char *bit_removal_on = "a=T38FaxFillBitRemoval\r\n";
11816  const char *bit_removal_off = "";
11817 
11818  const char *mmr_on = "a=T38FaxTranscodingMMR\r\n";
11819  const char *mmr_off = "";
11820 
11821  const char *jbig_on = "a=T38FaxTranscodingJBIG\r\n";
11822  const char *jbig_off = "";
11823  const char *var;
11824  int broken_boolean;
11825  switch_media_handle_t *smh;
11826  switch_rtp_engine_t *a_engine;
11827 
11828  switch_assert(session);
11829 
11830  if (!(smh = session->media_handle)) {
11831  return;
11832  }
11833 
11834  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
11835 
11837 
11838  switch_assert(t38_options);
11839 
11840  ip = t38_options->local_ip;
11841  port = t38_options->local_port;
11842  username = smh->mparams->sdp_username;
11843 
11844  var = switch_channel_get_variable(session->channel, "t38_broken_boolean");
11845 
11846  broken_boolean = switch_true(var);
11847 
11848 
11849  if (!ip) {
11850  if (!(ip = a_engine->adv_sdp_ip)) {
11851  ip = a_engine->proxy_sdp_ip;
11852  }
11853  }
11854 
11855  if (!ip) {
11857  return;
11858  }
11859 
11860  if (!port) {
11861  if (!(port = a_engine->adv_sdp_port)) {
11862  port = a_engine->proxy_sdp_port;
11863  }
11864  }
11865 
11866  if (!port) {
11868  return;
11869  }
11870 
11871  if (!smh->owner_id) {
11872  smh->owner_id = (uint32_t)(switch_time_t)switch_epoch_time_now(NULL) - port;
11873  }
11874 
11875  if (!smh->session_id) {
11876  smh->session_id = smh->owner_id;
11877  }
11878 
11879  smh->session_id++;
11880 
11881  family = strchr(ip, ':') ? "IP6" : "IP4";
11882 
11883 
11884  switch_snprintf(buf, sizeof(buf),
11885  "v=0\r\n"
11886  "o=%s %010u %010u IN %s %s\r\n"
11887  "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);
11888 
11889  if (t38_options->T38FaxMaxBuffer) {
11890  switch_snprintf(max_buf, sizeof(max_buf), "a=T38FaxMaxBuffer:%d\r\n", t38_options->T38FaxMaxBuffer);
11891  };
11892 
11893  if (t38_options->T38FaxMaxDatagram) {
11894  switch_snprintf(max_data, sizeof(max_data), "a=T38FaxMaxDatagram:%d\r\n", t38_options->T38FaxMaxDatagram);
11895  };
11896 
11897 
11898 
11899 
11900  if (broken_boolean) {
11901  bit_removal_on = "a=T38FaxFillBitRemoval:1\r\n";
11902  bit_removal_off = "a=T38FaxFillBitRemoval:0\r\n";
11903 
11904  mmr_on = "a=T38FaxTranscodingMMR:1\r\n";
11905  mmr_off = "a=T38FaxTranscodingMMR:0\r\n";
11906 
11907  jbig_on = "a=T38FaxTranscodingJBIG:1\r\n";
11908  jbig_off = "a=T38FaxTranscodingJBIG:0\r\n";
11909 
11910  }
11911 
11912  if (stream_rejected(smh, sdp_media_audio)) {
11913  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
11914  "m=audio 0 RTP/AVP 0\r\n");
11915  }
11916 
11917  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
11918  "m=image %d udptl t38\r\n"
11919  "a=T38FaxVersion:%d\r\n"
11920  "a=T38MaxBitRate:%d\r\n"
11921  "%s"
11922  "%s"
11923  "%s"
11924  "a=T38FaxRateManagement:%s\r\n"
11925  "%s"
11926  "%s"
11927  "a=T38FaxUdpEC:%s\r\n",
11928  //"a=T38VendorInfo:%s\r\n",
11929  port,
11930  t38_options->T38FaxVersion,
11931  t38_options->T38MaxBitRate,
11932  t38_options->T38FaxFillBitRemoval ? bit_removal_on : bit_removal_off,
11933  t38_options->T38FaxTranscodingMMR ? mmr_on : mmr_off,
11934  t38_options->T38FaxTranscodingJBIG ? jbig_on : jbig_off,
11935  t38_options->T38FaxRateManagement,
11936  max_buf,
11937  max_data,
11938  t38_options->T38FaxUdpEC
11939  //t38_options->T38VendorInfo ? t38_options->T38VendorInfo : "0 0 0"
11940  );
11941 
11942 
11943 
11944  if (insist) {
11945  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "m=audio 0 RTP/AVP 19\r\n");
11946  }
11947 
11949 
11950 
11951  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s image media sdp:\n%s\n",
11953 
11954 
11955 }
11956 
11957 
11958 
11959 //?
11961 {
11962  switch_size_t len;
11963  char *p, *q, *pe, *qe;
11964  int has_video = 0, has_audio = 0, has_text = 0, has_ip = 0;
11965  char port_buf[25] = "";
11966  char vport_buf[25] = "";
11967  char tport_buf[25] = "";
11968  char *new_sdp;
11969  int bad = 0;
11970  switch_media_handle_t *smh;
11971  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
11972  payload_map_t *pmap;
11973 
11974  switch_assert(session);
11975 
11976  if (!(smh = session->media_handle)) {
11977  return;
11978  }
11979 
11980  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
11981  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
11982  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
11983 
11984  if (zstr(smh->mparams->local_sdp_str)) {
11985  return;
11986  }
11987 
11988  len = strlen(smh->mparams->local_sdp_str) * 2;
11989 
11990  if (!(smh->mparams->ndlb & SM_NDLB_NEVER_PATCH_REINVITE)) {
11991  if (switch_channel_test_flag(session->channel, CF_ANSWERED) &&
11992  (switch_stristr("sendonly", smh->mparams->local_sdp_str) || switch_stristr("inactive", smh->mparams->local_sdp_str) || switch_stristr("0.0.0.0", smh->mparams->local_sdp_str))) {
11993  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Skip patch on hold SDP\n");
11994  return;
11995  }
11996  }
11997 
11998  if (zstr(a_engine->local_sdp_ip) || !a_engine->local_sdp_port) {// || switch_channel_test_flag(session->channel, CF_PROXY_MEDIA)) {
12001  switch_channel_get_name(session->channel));
12002  return;
12003  }
12004 
12005  clear_pmaps(a_engine);
12006 
12008 
12009  pmap = switch_core_media_add_payload_map(session,
12011  "PROXY",
12012  NULL,
12013  NULL,
12014  SDP_ANSWER,
12015  0,
12016  8000,
12017  20,
12018  1,
12019  SWITCH_TRUE);
12020 
12021  a_engine->cur_payload_map = pmap;
12022 
12023  }
12024 
12025  new_sdp = switch_core_session_alloc(session, len);
12026  switch_snprintf(port_buf, sizeof(port_buf), "%u", a_engine->local_sdp_port);
12027 
12028 
12029  p = smh->mparams->local_sdp_str;
12030  q = new_sdp;
12031  pe = p + strlen(p);
12032  qe = q + len - 1;
12033 
12034 
12035  while (p && *p) {
12036  if (p >= pe) {
12037  bad = 1;
12038  goto end;
12039  }
12040 
12041  if (q >= qe) {
12042  bad = 2;
12043  goto end;
12044  }
12045 
12046  if (a_engine->local_sdp_ip && !strncmp("c=IN IP", p, 7)) {
12047  strncpy(q, p, 7);
12048  p += 7;
12049  q += 7;
12050  memcpy(q, strchr(a_engine->adv_sdp_ip, ':') ? "6 " : "4 ", 2);
12051  p +=2;
12052  q +=2;
12053  snprintf(q, qe - q, "%s", a_engine->adv_sdp_ip);
12054  q += strlen(a_engine->adv_sdp_ip);
12055 
12056  while (p && *p && ((*p >= '0' && *p <= '9') || *p == '.' || *p == ':' || (*p >= 'A' && *p <= 'F') || (*p >= 'a' && *p <= 'f'))) {
12057  if (p >= pe) {
12058  bad = 3;
12059  goto end;
12060  }
12061  p++;
12062  }
12063 
12064  has_ip++;
12065 
12066  } else if (!strncmp("o=", p, 2)) {
12067  char *oe = strchr(p, '\n');
12068  switch_size_t len;
12069 
12070  if (oe) {
12071  const char *family = "IP4";
12072  char o_line[1024] = "";
12073 
12074  if (oe >= pe) {
12075  bad = 4;
12076  goto end;
12077  }
12078 
12079  len = (oe - p);
12080  p += len;
12081 
12082 
12083  family = strchr(smh->mparams->sipip, ':') ? "IP6" : "IP4";
12084 
12085  if (!smh->owner_id) {
12086  smh->owner_id = (uint32_t)(switch_time_t) switch_epoch_time_now(NULL) * 31821U + 13849U;
12087  }
12088 
12089  if (!smh->session_id) {
12090  smh->session_id = smh->owner_id;
12091  }
12092 
12093  smh->session_id++;
12094 
12095 
12096  snprintf(o_line, sizeof(o_line), "o=%s %010u %010u IN %s %s\r\n",
12097  smh->mparams->sdp_username, smh->owner_id, smh->session_id, family, smh->mparams->sipip);
12098 
12099  snprintf(q, qe-q, "%s", o_line);
12100  q += strlen(o_line) - 1;
12101 
12102  }
12103 
12104  } else if (!strncmp("s=", p, 2)) {
12105  char *se = strchr(p, '\n');
12106  switch_size_t len;
12107 
12108  if (se) {
12109  char s_line[1024] = "";
12110 
12111  if (se >= pe) {
12112  bad = 5;
12113  goto end;
12114  }
12115 
12116  len = (se - p);
12117  p += len;
12118 
12119  snprintf(s_line, sizeof(s_line), "s=%s\r\n", smh->mparams->sdp_username);
12120  snprintf(q, qe-q, "%s", s_line);
12121 
12122  q += strlen(s_line) - 1;
12123 
12124  }
12125 
12126  } else if ((!strncmp("m=audio ", p, 8) && *(p + 8) != '0') || (!strncmp("m=image ", p, 8) && *(p + 8) != '0')) {
12127  strncpy(q, p, 8);
12128  p += 8;
12129 
12130  if (p >= pe) {
12131  bad = 6;
12132  goto end;
12133  }
12134 
12135 
12136  q += 8;
12137 
12138  if (q >= qe) {
12139  bad = 7;
12140  goto end;
12141  }
12142 
12143 
12144  snprintf(q, qe - q, "%s", port_buf);
12145  q += strlen(port_buf);
12146 
12147  if (q >= qe) {
12148  bad = 8;
12149  goto end;
12150  }
12151 
12152  while (p && *p && (*p >= '0' && *p <= '9')) {
12153  if (p >= pe) {
12154  bad = 9;
12155  goto end;
12156  }
12157  p++;
12158  }
12159 
12160  has_audio++;
12161 
12162  } else if (!strncmp("m=video ", p, 8) && *(p + 8) != '0') {
12163  if (!has_video) {
12165  clear_pmaps(v_engine);
12166  pmap = switch_core_media_add_payload_map(session,
12168  "PROXY-VID",
12169  NULL,
12170  NULL,
12171  SDP_ANSWER,
12172  0,
12173  90000,
12174  90000,
12175  1,
12176  SWITCH_TRUE);
12177  v_engine->cur_payload_map = pmap;
12178 
12179  switch_snprintf(vport_buf, sizeof(vport_buf), "%u", v_engine->adv_sdp_port);
12180 
12181  if (switch_channel_media_ready(session->channel) && !switch_rtp_ready(v_engine->rtp_session)) {
12185  }
12186 
12187  v_engine->codec_negotiated = 1;
12189  }
12190 
12191  strncpy(q, p, 8);
12192  p += 8;
12193 
12194  if (p >= pe) {
12195  bad = 10;
12196  goto end;
12197  }
12198 
12199  q += 8;
12200 
12201  if (q >= qe) {
12202  bad = 11;
12203  goto end;
12204  }
12205 
12206  snprintf(q, qe-q, "%s", vport_buf);
12207  q += strlen(vport_buf);
12208 
12209  if (q >= qe) {
12210  bad = 12;
12211  goto end;
12212  }
12213 
12214  while (p && *p && (*p >= '0' && *p <= '9')) {
12215 
12216  if (p >= pe) {
12217  bad = 13;
12218  goto end;
12219  }
12220 
12221  p++;
12222  }
12223 
12224  has_video++;
12225  } else if (!strncmp("m=text ", p, 7) && *(p + 7) != '0') {
12226  if (!has_text) {
12228  clear_pmaps(t_engine);
12229  pmap = switch_core_media_add_payload_map(session,
12231  "PROXY-TXT",
12232  NULL,
12233  NULL,
12234  SDP_ANSWER,
12235  0,
12236  90000,
12237  90000,
12238  1,
12239  SWITCH_TRUE);
12240  t_engine->cur_payload_map = pmap;
12241 
12242  switch_snprintf(tport_buf, sizeof(tport_buf), "%u", t_engine->adv_sdp_port);
12243 
12244  if (switch_channel_media_ready(session->channel) && !switch_rtp_ready(t_engine->rtp_session)) {
12248  }
12249 
12250  t_engine->codec_negotiated = 1;
12251  //TEXT switch_core_media_set_text_codec(session, SWITCH_FALSE);
12252  }
12253 
12254  strncpy(q, p, 7);
12255  p += 7;
12256 
12257  if (p >= pe) {
12258  bad = 14;
12259  goto end;
12260  }
12261 
12262  q += 7;
12263 
12264  if (q >= qe) {
12265  bad = 15;
12266  goto end;
12267  }
12268 
12269  snprintf(q, qe-q, "%s", tport_buf);
12270  q += strlen(tport_buf);
12271 
12272  if (q >= qe) {
12273  bad = 16;
12274  goto end;
12275  }
12276 
12277  while (p && *p && (*p >= '0' && *p <= '9')) {
12278 
12279  if (p >= pe) {
12280  bad = 17;
12281  goto end;
12282  }
12283 
12284  p++;
12285  }
12286 
12287  has_text++;
12288  }
12289 
12290 
12291  while (p && *p && *p != '\n') {
12292 
12293  if (p >= pe) {
12294  bad = 18;
12295  goto end;
12296  }
12297 
12298  if (q >= qe) {
12299  bad = 19;
12300  goto end;
12301  }
12302 
12303  *q++ = *p++;
12304  }
12305 
12306  if (p >= pe) {
12307  bad = 20;
12308  goto end;
12309  }
12310 
12311  if (q >= qe) {
12312  bad = 21;
12313  goto end;
12314  }
12315 
12316  *q++ = *p++;
12317 
12318  }
12319 
12320  end:
12321 
12322  if (bad) {
12323  return;
12324  }
12325 
12326 
12327  if (switch_channel_down(session->channel)) {
12329  return;
12330  }
12331 
12332 
12333  if (!has_ip && !has_audio) {
12334  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SDP has no audio in it.\n%s\n",
12336  return;
12337  }
12338 
12339 
12340  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Patched SDP\n---\n%s\n+++\n%s\n",
12341  switch_channel_get_name(session->channel), smh->mparams->local_sdp_str, new_sdp);
12342 
12343  switch_core_media_set_local_sdp(session, new_sdp, SWITCH_FALSE);
12344 
12345 }
12346 
12347 //?
12349 {
12350  switch_media_handle_t *smh;
12351  switch_rtp_engine_t *a_engine;
12352 
12353  switch_assert(session);
12354 
12355  if (!(smh = session->media_handle)) {
12356  return;
12357  }
12358 
12359  if (switch_channel_down(session->channel)) {
12360  return;
12361  }
12362 
12363  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
12364 
12365 
12366  if (switch_rtp_ready(a_engine->rtp_session)) {
12367  char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
12368  switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
12369  const char *err, *val;
12370 
12373 
12374  if (!t38_options || !t38_options->remote_ip) {
12375  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No remote address\n");
12376  return;
12377  }
12378 
12379  if (remote_host && remote_port && remote_port == t38_options->remote_port && !strcmp(remote_host, t38_options->remote_ip)) {
12380  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote address:port [%s:%d] has not changed.\n",
12381  t38_options->remote_ip, t38_options->remote_port);
12382  return;
12383  }
12384 
12385  if (switch_rtp_set_remote_address(a_engine->rtp_session, t38_options->remote_ip,
12386  t38_options->remote_port, 0, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
12387  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "IMAGE UDPTL REPORTS ERROR: [%s]\n", err);
12388  } else {
12389  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IMAGE UDPTL CHANGING DEST TO: [%s:%d]\n",
12390  t38_options->remote_ip, t38_options->remote_port);
12392  !((val = switch_channel_get_variable(session->channel, "disable_udptl_auto_adjust")) && switch_true(val))) {
12393  /* Reactivate the NAT buster flag. */
12395  }
12396  }
12397  }
12398 }
12399 
12400 //?
12402 {
12403  switch_core_session_message_t msg = { 0 };
12404 
12405  msg.from = __FILE__;
12406 
12408  msg.numeric_arg = on;
12409  switch_core_session_receive_message(session, &msg);
12410 }
12411 
12412 SWITCH_DECLARE(cJSON *) switch_core_media_gen_json_constraint(float min, float ideal, float max)
12413 {
12414  cJSON *ret = NULL, *n = NULL;
12415 
12416  if ((!ideal && !max)) {
12417  ret = cJSON_CreateNumber(min);
12418  } else {
12419  ret = cJSON_CreateObject();
12420  n = cJSON_CreateNumber(min);
12421  cJSON_AddItemToObject(ret, "min", n);
12422 
12423  if (ideal) {
12424  n = cJSON_CreateNumber(ideal);
12425  cJSON_AddItemToObject(ret, "ideal", n);
12426  }
12427 
12428  if (max) {
12429  n = cJSON_CreateNumber(max);
12430  cJSON_AddItemToObject(ret, "max", n);
12431  }
12432  }
12433 
12434  return ret;
12435 }
12436 
12437 static cJSON *parse_val(char *str) {
12438  char *argv[3];
12439  int argc = 0;
12440  float min = 0, ideal = 0, max = 0;
12441 
12442  argc = switch_separate_string(str, ':', argv, (sizeof(argv) / sizeof(argv[0])));
12443 
12444  if (argc > 0) {
12445  min = atof(argv[0]);
12446  }
12447 
12448  if (argc > 1) {
12449  ideal = atof(argv[1]);
12450  }
12451 
12452  if (argc > 2) {
12453  max = atof(argv[2]);
12454  }
12455 
12456  return switch_core_media_gen_json_constraint(min, ideal, max);
12457 
12458 }
12459 
12461 {
12462  switch_core_session_message_t msg = { 0 };
12463  char *parse = NULL;
12464  char *argv[25];
12465  int argc = 0, i;
12467  cJSON *obj = NULL;
12468  char *aspect = NULL, *fps = NULL, *width = NULL, *height = NULL, *jtmp = NULL;
12469 
12470 
12472  return SWITCH_STATUS_INUSE;
12473  }
12474 
12475  if (switch_stristr("=", json)) {
12476  char *name, *val;
12477  cJSON *video, *p;
12478  int vid = 0;
12479 
12480  parse = strdup(json);
12481  argc = switch_separate_string(parse, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
12482 
12483  for(i = 0; i < argc; i++) {
12484  name = argv[i];
12485  if ((val = strchr(name, '='))) {
12486  *val++ = '\0';
12487  }
12488 
12489  if (val) {
12490  if (!strcmp(name, "aspect")) {
12491  aspect = val;
12492  vid++;
12493  } else if (!strcmp(name, "fps")) {
12494  fps = val;
12495  vid++;
12496  } else if (!strcmp(name, "width")) {
12497  width = val;
12498  vid++;
12499  } else if (!strcmp(name, "height")) {
12500  height = val;
12501  vid++;
12502  }
12503  }
12504  }
12505 
12506  obj = cJSON_CreateObject();
12507 
12508  if (vid) {
12509  video = cJSON_CreateObject();
12510 
12511  if (fps) {
12512  p = parse_val(fps);
12513  cJSON_AddItemToObject(video, "frameRate", p);
12514  }
12515 
12516  if (width) {
12517  p = parse_val(width);
12518  cJSON_AddItemToObject(video, "width", p);
12519  }
12520 
12521  if (height) {
12522  p = parse_val(height);
12523  cJSON_AddItemToObject(video, "height", p);
12524  }
12525 
12526  if (aspect) {
12527  p = cJSON_CreateNumber(atof(aspect));
12528  cJSON_AddItemToObject(video, "aspectRatio", p);
12529  }
12530 
12531  cJSON_AddItemToObject(obj, "video", video);
12532  }
12533 
12534  jtmp = cJSON_PrintUnformatted(obj);
12535  json = jtmp;
12536  }
12537 
12538 
12539 
12540  msg.from = __FILE__;
12541 
12543  msg.string_arg = json;
12544  r = switch_core_session_receive_message(session, &msg);
12545 
12546  switch_safe_free(parse);
12547  switch_safe_free(jtmp);
12548  if (obj) {
12549  cJSON_Delete(obj);
12550  }
12551 
12552  return r;
12553 }
12554 
12556 {
12558  int flags = 0;
12559  switch_status_t status;
12560 
12561  if (dtls_state == DS_READY || dtls_state >= DS_FAIL) return 0;
12562 
12563  status = switch_rtp_zerocopy_read_frame(engine->rtp_session, &engine->read_frame, flags);
12564 
12565  if (!SWITCH_READ_ACCEPTABLE(status)) {
12566  return 0;
12567  }
12568 
12569  return 1;
12570 }
12571 
12573 {
12574  switch_media_handle_t *smh;
12575  switch_rtp_engine_t *engine;
12576  int checking = 0;
12577 
12578  switch_assert(session);
12579 
12580  if (!(smh = session->media_handle)) {
12581  return SWITCH_FALSE;
12582  }
12583 
12584  if (!switch_channel_media_up(session->channel)) {
12585  return SWITCH_FALSE;
12586  }
12587 
12588  if (!switch_channel_test_flag(session->channel, CF_DTLS)) {
12589  return SWITCH_TRUE;
12590  }
12591 
12592  engine = &smh->engines[type];
12593 
12594  if (engine->rmode == SWITCH_MEDIA_FLOW_DISABLED) {
12595  return SWITCH_TRUE;
12596  }
12597 
12598  do {
12599  if (engine->rtp_session) checking = check_engine(engine);
12600  } while (switch_channel_ready(session->channel) && checking);
12601 
12602  if (!checking) {
12603  return SWITCH_TRUE;
12604  }
12605 
12606  return SWITCH_FALSE;
12607 }
12608 
12610 {
12611  switch_media_handle_t *smh;
12612  switch_rtp_engine_t *engine;
12613 
12614  if (!(smh = session->media_handle)) {
12615  return 0;
12616  }
12617 
12618  if (switch_channel_down(session->channel)) {
12619  return 0;
12620  }
12621 
12622  engine = &smh->engines[type];
12623 
12624  if (engine) {
12625  return engine->orig_bitrate;
12626  } else {
12627  return 0;
12628  }
12629 }
12630 
12632 {
12633  switch_media_handle_t *smh;
12634  switch_rtp_engine_t *engine;
12636  uint32_t new_bitrate;
12637 
12638  if (!(smh = session->media_handle)) {
12639  return SWITCH_STATUS_FALSE;
12640  }
12641 
12642  if (switch_channel_down(session->channel)) {
12643  return SWITCH_STATUS_FALSE;
12644  }
12645 
12646  engine = &smh->engines[type];
12647 
12648  new_bitrate = bitrate - bitrate * engine->bw_mult;
12649  if (switch_core_codec_ready(&engine->write_codec)) {
12651  SCCT_INT, &new_bitrate, SCCT_NONE, NULL, NULL, NULL);
12652  }
12653  engine->orig_bitrate = bitrate;
12654 
12655  return status;
12656 }
12657 
12659 {
12660  switch_media_handle_t *smh;
12661  switch_rtp_engine_t *engine;
12662 
12663  if (!(smh = session->media_handle)) {
12664  return 0;
12665  }
12666 
12667  if (switch_channel_down(session->channel)) {
12668  return 0;
12669  }
12670 
12671  engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
12672 
12673  if (engine) {
12674  return engine->bw_mult;
12675  }
12676  return 0;
12677 }
12678 
12680 {
12681  switch_media_handle_t *smh;
12682  switch_rtp_engine_t *engine;
12683 
12684  if (!(smh = session->media_handle)) {
12685  return;
12686  }
12687 
12688  if (switch_channel_down(session->channel)) {
12689  return;
12690  }
12691 
12692  engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
12693 
12694  if (engine) {
12695  engine->bw_mult = mult;
12696  }
12697 }
12698 
12699 //?
12701 {
12702  switch_media_handle_t *smh;
12703  switch_rtp_engine_t *engine;
12704 
12705  switch_assert(session);
12706 
12707  if (!(smh = session->media_handle)) {
12708  return SWITCH_STATUS_FALSE;
12709  }
12710 
12711  engine = &smh->engines[type];
12712 
12713  if (switch_rtp_ready(engine->rtp_session)) {
12715  return SWITCH_STATUS_SUCCESS;
12716  }
12717 
12718  return SWITCH_STATUS_FALSE;
12719 }
12720 
12721 //?
12723 {
12724  switch_media_handle_t *smh;
12725  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
12727 
12728  switch_assert(session);
12729 
12730  if (!(smh = session->media_handle)) {
12731  return SWITCH_STATUS_FALSE;
12732  }
12733 
12734  if (switch_channel_down(session->channel)) {
12735  return SWITCH_STATUS_FALSE;
12736  }
12737 
12738  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
12739  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
12740  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
12741 
12742  switch (msg->message_id) {
12743 
12745  {
12746  if (switch_rtp_ready(a_engine->rtp_session)) {
12748  switch_rtp_reset_jb(a_engine->rtp_session);
12749  }
12750 
12753  }
12754  }
12755  break;
12756 
12758  {
12759  if (a_engine && a_engine->rtp_session) {
12762  }
12763 
12764  if (v_engine && v_engine->rtp_session) {
12766  }
12767  }
12768  break;
12769 
12771  {
12772  if (a_engine && a_engine->rtp_session) {
12775  }
12776 
12777  if (v_engine && v_engine->rtp_session) {
12779  }
12780  }
12781  break;
12782 
12784  {
12785  if (v_engine->rtp_session) {
12789  }// else {
12792  }
12793  //}
12794  }
12795  }
12796  }
12797 
12798  break;
12799 
12801  {
12802  if (switch_rtp_ready(a_engine->rtp_session)) {
12803  if (msg->numeric_arg) {
12805  } else {
12807  }
12808  }
12809  }
12810  break;
12811 
12813  {
12814  if (switch_rtp_ready(a_engine->rtp_session)) {
12815  check_jb(session, msg->string_arg, 0, 0, SWITCH_FALSE);
12816  }
12817  }
12818  break;
12819 
12821  if (a_engine->rtp_session) {
12822  a_engine->last_seq = 0;
12823 
12824  if (session->bugs && msg->numeric_arg) {
12826  "%s has a media bug, hard mute not allowed.\n", switch_channel_get_name(session->channel));
12827  } else {
12828  if (msg->numeric_arg) {
12830  } else {
12832  }
12833 
12835  }
12836  }
12837 
12838  break;
12839 
12841  {
12842  if (v_engine->rtp_session) {
12844  }
12845  }
12846  break;
12847 
12849  {
12850  if (v_engine->rtp_session) {
12852  }
12853  }
12854  break;
12855 
12857  {
12858  switch_rtp_engine_t *engine = &smh->engines[msg->numeric_reply];
12859  uint32_t level = (uint32_t) msg->numeric_arg;
12860 
12861  if (engine->rtp_session) {
12862  switch_core_codec_control(&engine->read_codec, SCC_DEBUG, SCCT_INT, (void *)&level, SCCT_NONE, NULL, NULL, NULL);
12863  switch_core_codec_control(&engine->write_codec, SCC_DEBUG, SCCT_INT, (void *)&level, SCCT_NONE, NULL, NULL, NULL);
12864  }
12865  }
12866  break;
12867 
12869  {
12870  switch_rtp_engine_t *engine;
12874  void *reply = NULL;
12875 
12876  if (!strcasecmp(msg->string_array_arg[0], "video")) {
12877  type = SWITCH_MEDIA_TYPE_VIDEO;
12878  }
12879 
12880  if (!strcasecmp(msg->string_array_arg[1], "write")) {
12881  iotype = SWITCH_IO_WRITE;
12882  }
12883 
12884  engine = &smh->engines[type];
12885 
12886  if (engine->rtp_session) {
12887  if (iotype == SWITCH_IO_READ) {
12889  SCCT_STRING, (void *)msg->string_array_arg[2],
12890  SCCT_STRING, (void *)msg->string_array_arg[3], &reply_type, &reply);
12891  } else {
12893  SCCT_STRING, (void *)msg->string_array_arg[2],
12894  SCCT_STRING, (void *)msg->string_array_arg[3], &reply_type, &reply);
12895  }
12896 
12897 
12898  if (reply_type == SCCT_STRING) {
12899  msg->string_array_arg[4] = (char *)reply;
12900  }
12901  }
12902  }
12903  break;
12904 
12906  {
12907  switch_rtp_t *rtp = a_engine->rtp_session;
12908  const char *direction = msg->string_array_arg[0];
12909 
12910  if (direction && *direction == 'v') {
12911  direction++;
12912  rtp = v_engine->rtp_session;
12913  } else if (direction && *direction == 't' && t_engine) {
12914  direction++;
12915  rtp = t_engine->rtp_session;
12916  }
12917 
12918  if (switch_rtp_ready(rtp) && !zstr(direction) && !zstr(msg->string_array_arg[1])) {
12920  int both = !strcasecmp(direction, "both");
12921  int set = 0;
12922 
12923  if (both || !strcasecmp(direction, "read")) {
12925  set++;
12926  }
12927 
12928  if (both || !strcasecmp(direction, "write")) {
12930  set++;
12931  }
12932 
12933  if (set) {
12934  if (switch_true(msg->string_array_arg[1])) {
12935  switch_rtp_set_flags(rtp, flags);
12936  } else {
12937  switch_rtp_clear_flags(rtp, flags);
12938  }
12939  } else {
12940  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Options\n");
12941  }
12942  }
12943  }
12944  goto end;
12947  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Pass 2833 mode may not work on a transcoded call.\n");
12948  }
12949  goto end;
12950 
12952  {
12953 
12954 #if 0
12955  if (switch_rtp_ready(v_engine->rtp_session)) {
12956  const char *val;
12957 
12958  if ((!(val = switch_channel_get_variable(session->channel, "rtp_jitter_buffer_during_bridge")) || switch_false(val))) {
12961  "%s PAUSE Jitterbuffer\n", switch_channel_get_name(session->channel));
12964  }
12965  }
12966  }
12967 #endif
12968 
12969  if (switch_rtp_ready(a_engine->rtp_session)) {
12970  const char *val;
12971  int ok = 0;
12972 
12973  if (!switch_channel_test_flag(session->channel, CF_VIDEO_READY) &&
12974  (!(val = switch_channel_get_variable(session->channel, "rtp_jitter_buffer_during_bridge")) || switch_false(val))) {
12977  "%s PAUSE Jitterbuffer\n", switch_channel_get_name(session->channel));
12980  }
12981  }
12982 
12986  "%s activate passthru 2833 mode.\n", switch_channel_get_name(session->channel));
12987  }
12988 
12989 
12990  if ((val = switch_channel_get_variable(session->channel, "rtp_notimer_during_bridge"))) {
12991  ok = switch_true(val);
12992  } else {
12994  }
12995 
12997  ok = 0;
12998  }
12999 
13000  if (ok) {
13002  //switch_rtp_clear_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
13004  }
13005 
13007  /* these are not compat */
13008  ok = 0;
13009  } else {
13010  if ((val = switch_channel_get_variable(session->channel, "rtp_autoflush_during_bridge"))) {
13011  ok = switch_true(val);
13012  } else {
13014  }
13015  }
13016 
13017  if (ok) {
13020  } else {
13022  }
13023 
13024  }
13025  }
13026  goto end;
13028 
13029 #if 0
13030  if (switch_rtp_ready(v_engine->rtp_session)) {
13031 
13032  if (switch_test_flag(smh, SMF_VB_PAUSED)) {
13035  "%s RESUME Video Jitterbuffer\n", switch_channel_get_name(session->channel));
13037 
13038  }
13039  }
13040 #endif
13041 
13042  if (switch_rtp_ready(a_engine->rtp_session)) {
13043 
13044  if (switch_test_flag(smh, SMF_JB_PAUSED)) {
13048  "%s RESUME Jitterbuffer\n", switch_channel_get_name(session->channel));
13050  }
13051  }
13052 
13053 
13055  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s deactivate passthru 2833 mode.\n",
13056  switch_channel_get_name(session->channel));
13058  }
13059 
13064  //switch_rtp_set_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
13065  }
13067  }
13068 
13072  } else {
13074  }
13075 
13076  }
13077  goto end;
13079  if (switch_rtp_ready(a_engine->rtp_session)) {
13080  switch_rtp_reset_jb(a_engine->rtp_session);
13082  }
13083  goto end;
13084 
13086  if (switch_rtp_ready(v_engine->rtp_session)) {
13087  switch_rtp_reset_jb(v_engine->rtp_session);
13088  switch_rtp_flush(v_engine->rtp_session);
13089  }
13090  goto end;
13093  {
13094 
13095  a_engine->codec_negotiated = 0;
13096  v_engine->codec_negotiated = 0;
13097 
13098  if (session->track_duration) {
13100  }
13101  }
13102  break;
13103 
13107  break;
13109  {
13110  const char *uuid;
13111  switch_core_session_t *other_session;
13112  switch_channel_t *other_channel;
13113  const char *ip = NULL, *port = NULL;
13114 
13116 
13118 
13119  if (switch_true(switch_channel_get_variable(session->channel, "bypass_keep_codec"))) {
13120  switch_channel_set_variable(session->channel, "absolute_codec_string", switch_channel_get_variable(session->channel, "ep_codec_string"));
13121  }
13122 
13123 
13124  if ((uuid = switch_channel_get_partner_uuid(session->channel))
13125  && (other_session = switch_core_session_locate(uuid))) {
13126  other_channel = switch_core_session_get_channel(other_session);
13129  switch_core_session_rwunlock(other_session);
13130 
13131  if (ip && port) {
13133  clear_pmaps(a_engine);
13134  clear_pmaps(v_engine);
13135  switch_core_media_gen_local_sdp(session, SDP_OFFER, ip, (switch_port_t)atoi(port), NULL, 1);
13136  }
13137  }
13138 
13139 
13140  if (!smh->mparams->local_sdp_str) {
13142  }
13143 
13144  if (session->track_duration) {
13146  }
13147 
13148  }
13149  break;
13150 
13151 
13152  default:
13153  break;
13154  }
13155 
13156 
13157  if (smh->mutex) switch_mutex_lock(smh->mutex);
13158 
13159 
13160  if (switch_channel_down(session->channel)) {
13161  status = SWITCH_STATUS_FALSE;
13162  goto end_lock;
13163  }
13164 
13165  switch (msg->message_id) {
13167  {
13168  switch_core_session_t *nsession;
13169 
13170  if (msg->string_arg) {
13171  switch_channel_set_variable(session->channel, "absolute_codec_string", NULL);
13172 
13173  if (*msg->string_arg == '=') {
13174  switch_channel_set_variable(session->channel, "codec_string", msg->string_arg);
13175  } else {
13177  "codec_string", "=%s", switch_channel_get_variable(session->channel, "ep_codec_string"));
13178  }
13179 
13180  a_engine->codec_negotiated = 0;
13181  v_engine->codec_negotiated = 0;
13182  smh->num_negotiated_codecs = 0;
13186 
13187  switch_core_media_gen_local_sdp(session, SDP_OFFER, NULL, 0, NULL, 1);
13188  }
13189 
13190  if (msg->numeric_arg && switch_core_session_get_partner(session, &nsession) == SWITCH_STATUS_SUCCESS) {
13191  msg->numeric_arg = 0;
13192  switch_core_session_receive_message(nsession, msg);
13193  switch_core_session_rwunlock(nsession);
13194  }
13195 
13196  }
13197  break;
13198 
13200  {
13201  if (switch_rtp_ready(a_engine->rtp_session)) {
13202  if (msg->numeric_arg) {
13206  }
13207 
13209 
13210  } else {
13211  if (switch_test_flag(smh, SMF_JB_PAUSED)) {
13215  }
13216  }
13217  }
13218  }
13219  }
13220  break;
13221 
13223  {
13224  switch_t38_options_t *t38_options = switch_channel_get_private(session->channel, "t38_options");
13225 
13226  if (t38_options) {
13227  switch_core_media_start_udptl(session, t38_options);
13228  }
13229 
13230  }
13231 
13232 
13233  default:
13234  break;
13235  }
13236 
13237 
13238  end_lock:
13239 
13240  if (smh->mutex) switch_mutex_unlock(smh->mutex);
13241 
13242  end:
13243 
13244  if (switch_channel_down(session->channel)) {
13245  status = SWITCH_STATUS_FALSE;
13246  }
13247 
13248  return status;
13249 
13250 }
13251 
13252 //?
13254 {
13255  switch_media_handle_t *smh;
13256 
13257  switch_assert(session);
13258 
13259  if (!(smh = session->media_handle)) {
13260  return;
13261  }
13262 
13263  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13264  switch_rtp_break(smh->engines[type].rtp_session);
13265  }
13266 }
13267 
13268 //?
13270 {
13271  switch_media_handle_t *smh;
13272 
13273  switch_assert(session);
13274 
13275  if (!(smh = session->media_handle)) {
13276  return;
13277  }
13278 
13279  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13281  }
13282 }
13283 
13284 //?
13286 {
13287  switch_media_handle_t *smh;
13288 
13289  switch_assert(session);
13290 
13291  if (!(smh = session->media_handle)) {
13292  return SWITCH_STATUS_FALSE;
13293  }
13294 
13295  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13296  return switch_rtp_queue_rfc2833(smh->engines[type].rtp_session, dtmf);
13297  }
13298 
13299  return SWITCH_STATUS_FALSE;
13300 }
13301 
13302 //?
13304 {
13305  switch_media_handle_t *smh;
13306 
13307  switch_assert(session);
13308 
13309  if (!(smh = session->media_handle)) {
13310  return SWITCH_STATUS_FALSE;
13311  }
13312 
13313  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13314  return switch_rtp_queue_rfc2833_in(smh->engines[type].rtp_session, dtmf);
13315  }
13316 
13317  return SWITCH_STATUS_FALSE;
13318 }
13319 
13320 //?
13322 {
13323  switch_media_handle_t *smh;
13324 
13325  switch_assert(session);
13326 
13327  if (!(smh = session->media_handle)) {
13328  return 0;
13329  }
13330 
13331  return switch_rtp_ready(smh->engines[type].rtp_session);
13332 }
13333 
13334 //?
13336 {
13337  switch_media_handle_t *smh;
13338 
13339  switch_assert(session);
13340 
13341  if (!(smh = session->media_handle)) {
13342  return;
13343  }
13344 
13345  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13346  switch_rtp_set_flag(smh->engines[type].rtp_session, flag);
13347  }
13348 }
13349 
13350 //?
13352 {
13353  switch_media_handle_t *smh;
13354 
13355  switch_assert(session);
13356 
13357  if (!(smh = session->media_handle)) {
13358  return;
13359  }
13360 
13361  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13362  switch_rtp_clear_flag(smh->engines[type].rtp_session, flag);
13363  }
13364 }
13365 
13366 //?
13368 {
13369  switch_media_handle_t *smh;
13370 
13371  switch_assert(session);
13372 
13373  if (!(smh = session->media_handle)) {
13374  return;
13375  }
13376 
13377  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13379  }
13380 }
13381 
13382 //?
13384 {
13385  switch_media_handle_t *smh;
13386 
13387  switch_assert(session);
13388 
13389  if (!(smh = session->media_handle)) {
13390  return;
13391  }
13392 
13393  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13395  }
13396 }
13397 
13398 //?
13400 {
13401  switch_media_handle_t *smh;
13402 
13403  switch_assert(session);
13404 
13405  if (!(smh = session->media_handle)) {
13406  return NULL;
13407  }
13408 
13409  if (smh->engines[type].rtp_session) {
13410  return switch_rtp_get_stats(smh->engines[type].rtp_session, pool);
13411  }
13412 
13413  return NULL;
13414 }
13415 
13416 //?
13418 {
13419  switch_media_handle_t *smh;
13420 
13421  switch_assert(session);
13422 
13423  if (!(smh = session->media_handle)) {
13424  return SWITCH_FALSE;
13425  }
13426 
13427  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13429  }
13430 
13431  return SWITCH_FALSE;
13432 }
13433 
13434 //?
13436 {
13437  switch_media_handle_t *smh;
13438 
13439  switch_assert(session);
13440 
13441  if (!(smh = session->media_handle)) {
13442  return SWITCH_STATUS_FALSE;
13443  }
13444 
13445  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13446  return switch_rtp_udptl_mode(smh->engines[type].rtp_session);
13447  }
13448 
13449  return SWITCH_STATUS_FALSE;
13450 }
13451 
13452 //?
13454 {
13455  switch_media_handle_t *smh;
13456 
13457  switch_assert(session);
13458 
13459  if (!(smh = session->media_handle)) {
13460  return NULL;
13461  }
13462 
13463  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13465  }
13466 
13467  return NULL;
13468 }
13469 
13470 
13471 //?
13473 {
13475 }
13476 
13478  switch_sdp_type_t sdp_type, const char *codec_string)
13479 {
13480  sdp_parser_t *parser;
13481  sdp_session_t *sdp;
13482 
13483  switch_assert(session);
13484 
13485  if (!session->media_handle) {
13486  return;
13487  }
13488 
13489  if (!r_sdp) {
13490  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Setting NULL SDP is invalid\n");
13491  return;
13492  }
13493 
13494  if (zstr(codec_string)) {
13495  codec_string = switch_core_media_get_codec_string(session);
13496  }
13497 
13498  if ((parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
13499 
13500  if ((sdp = sdp_session(parser))) {
13501  switch_core_media_set_r_sdp_codec_string(session, codec_string, sdp, sdp_type);
13502  }
13503 
13504  sdp_parser_free(parser);
13505  }
13506 }
13507 
13508 
13509 static void add_audio_codec(sdp_rtpmap_t *map, const switch_codec_implementation_t *imp, int ptime, char *buf, switch_size_t buflen)
13510 {
13511  int codec_ms = ptime;
13512  uint32_t map_bit_rate = 0, map_channels = 1;
13513  char ptstr[20] = "";
13514  char ratestr[20] = "";
13515  char bitstr[20] = "";
13516  switch_codec_fmtp_t codec_fmtp = { 0 };
13517 
13518  if (!codec_ms) {
13519  codec_ms = switch_default_ptime(map->rm_encoding, map->rm_pt);
13520  }
13521 
13522  map_channels = map->rm_params ? atoi(map->rm_params) : 1;
13523  map_bit_rate = switch_known_bitrate((switch_payload_t)map->rm_pt);
13524 
13525  if (!ptime && !strcasecmp(map->rm_encoding, "g723")) {
13526  codec_ms = 30;
13527  }
13528 
13529  if (zstr(map->rm_fmtp)) {
13530  if (!strcasecmp(map->rm_encoding, "ilbc")) {
13531  codec_ms = 30;
13532  map_bit_rate = 13330;
13533  } else if (!strcasecmp(map->rm_encoding, "isac")) {
13534  codec_ms = 30;
13535  map_bit_rate = 32000;
13536  }
13537  } else {
13538  if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) {
13539  if (codec_fmtp.bits_per_second) {
13540  map_bit_rate = codec_fmtp.bits_per_second;
13541  }
13542  if (codec_fmtp.microseconds_per_packet) {
13543  codec_ms = (codec_fmtp.microseconds_per_packet / 1000);
13544  }
13545  }
13546  }
13547 
13548  if (map->rm_rate) {
13549  switch_snprintf(ratestr, sizeof(ratestr), "@%uh", (unsigned int) map->rm_rate);
13550  }
13551 
13552  if (codec_ms) {
13553  switch_snprintf(ptstr, sizeof(ptstr), "@%di", codec_ms);
13554  }
13555 
13556  if (map_bit_rate) {
13557  switch_snprintf(bitstr, sizeof(bitstr), "@%db", map_bit_rate);
13558  }
13559 
13560  if (map_channels > 1) {
13561  switch_snprintf(bitstr, sizeof(bitstr), "@%dc", map_channels);
13562  }
13563 
13564  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), ",%s.%s%s%s%s", imp->modname, map->rm_encoding, ratestr, ptstr, bitstr);
13565 
13566 }
13567 
13568 
13569 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)
13570 {
13571  char buf[1024] = { 0 };
13572  sdp_media_t *m;
13573  sdp_attribute_t *attr;
13574  int ptime = 0, dptime = 0;
13575  sdp_connection_t *connection;
13576  sdp_rtpmap_t *map;
13577  short int match = 0;
13578  int i;
13579  int already_did[128] = { 0 };
13580  int num_codecs = 0;
13581  char *codec_order[SWITCH_MAX_CODECS];
13582  const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS] = { 0 };
13583  char fmtp[SWITCH_MAX_CODECS][MAX_FMTP_LEN];
13584 
13586  int prefer_sdp = 0;
13587  const char *var;
13588  switch_media_handle_t *smh;
13589 
13590  switch_assert(session);
13591 
13592  if (!(smh = session->media_handle)) {
13593  return;
13594  }
13595 
13596 
13597  if ((var = switch_channel_get_variable(channel, "ep_codec_prefer_sdp")) && switch_true(var)) {
13598  prefer_sdp = 1;
13599  }
13600 
13601 
13602  if (!zstr(codec_string)) {
13603  char *tmp_codec_string;
13604 
13605  if (*codec_string == '=') codec_string++;
13606 
13607  if ((tmp_codec_string = strdup(codec_string))) {
13608  num_codecs = switch_separate_string(tmp_codec_string, ',', codec_order, SWITCH_MAX_CODECS);
13609  num_codecs = switch_loadable_module_get_codecs_sorted(codecs, fmtp, SWITCH_MAX_CODECS, codec_order, num_codecs);
13610  switch_safe_free(tmp_codec_string);
13611  }
13612  } else {
13614  }
13615 
13616  if (!channel || !num_codecs) {
13617  return;
13618  }
13619 
13620  for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) {
13621  if (zstr(attr->a_name)) {
13622  continue;
13623  }
13624 
13625  if (!strcasecmp(attr->a_name, "ptime")) {
13626  dptime = atoi(attr->a_value);
13627  break;
13628  }
13629  }
13630 
13631  for (m = sdp->sdp_media; m; m = m->m_next) {
13632  ptime = dptime;
13633 
13634  if ((m->m_type == sdp_media_audio || m->m_type == sdp_media_video) && m->m_port) {
13635  for (map = m->m_rtpmaps; map; map = map->rm_next) {
13636  int found = 0;
13637 
13638  for (attr = m->m_attributes; attr && found < 2; attr = attr->a_next) {
13639  if (zstr(attr->a_name)) {
13640  continue;
13641  }
13642 
13643  if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
13644  ptime = atoi(attr->a_value);
13645  found++;
13646  }
13647 
13648  if (!strcasecmp(attr->a_name, "rtcp-mux")) {
13649  if (switch_channel_var_true(channel, "rtcp_mux_auto_detect")) {
13650  switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "setting rtcp-mux from sdp\n");
13651  switch_channel_set_variable(channel, "rtcp_mux", "true");
13652  }
13653 
13654  found++;
13655  }
13656  }
13657 
13659  m->m_type == sdp_media_audio ? SWITCH_MEDIA_TYPE_AUDIO : SWITCH_MEDIA_TYPE_VIDEO,
13660  map->rm_encoding,
13661  NULL,
13662  map->rm_fmtp,
13663  sdp_type,
13664  map->rm_pt,
13665  map->rm_rate,
13666  ptime,
13667  map->rm_params ? atoi(map->rm_params) : 1,
13668  SWITCH_FALSE);
13669  }
13670  }
13671  }
13672 
13673  for (m = sdp->sdp_media; m; m = m->m_next) {
13674  ptime = dptime;
13675 
13676  if (m->m_type == sdp_media_image && m->m_port) {
13677  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",t38");
13678  } else if (m->m_type == sdp_media_audio && m->m_port) {
13679  for (attr = m->m_attributes; attr; attr = attr->a_next) {
13680  if (zstr(attr->a_name)) {
13681  continue;
13682  }
13683 
13684  if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
13685  ptime = atoi(attr->a_value);
13686  break;
13687  }
13688  }
13689 
13690  connection = sdp->sdp_connection;
13691  if (m->m_connections) {
13692  connection = m->m_connections;
13693  }
13694 
13695  if (!connection) {
13696  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");
13697  break;
13698  }
13699 
13700  if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND || prefer_sdp) {
13701  for (map = m->m_rtpmaps; map; map = map->rm_next) {
13702 
13703  if (already_did[map->rm_pt]) {
13704  continue;
13705  }
13706 
13707  for (i = 0; i < num_codecs; i++) {
13708  const switch_codec_implementation_t *imp = codecs[i];
13709 
13710  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
13711  match = (map->rm_pt == imp->ianacode) ? 1 : 0;
13712  } else {
13713  if (map->rm_encoding) {
13714  match = !strcasecmp(map->rm_encoding, imp->iananame) &&
13715  ((map->rm_pt < 96 && imp->ianacode < 96) || (map->rm_pt > 95 && imp->ianacode > 95));
13716  } else {
13717  match = 0;
13718  }
13719  }
13720 
13721  if (match) {
13722  add_audio_codec(map, imp, ptime, buf, sizeof(buf));
13723  }
13724  }
13725  }
13726 
13727  } else {
13728  for (i = 0; i < num_codecs; i++) {
13729  const switch_codec_implementation_t *imp = codecs[i];
13730 
13731  if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO || imp->ianacode > 127 || already_did[imp->ianacode]) {
13732  continue;
13733  }
13734 
13735  for (map = m->m_rtpmaps; map; map = map->rm_next) {
13736 
13737  if (already_did[map->rm_pt]) {
13738  continue;
13739  }
13740 
13741  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
13742  match = (map->rm_pt == imp->ianacode) ? 1 : 0;
13743  } else {
13744  if (map->rm_encoding) {
13745  match = !strcasecmp(map->rm_encoding, imp->iananame) &&
13746  ((map->rm_pt < 96 && imp->ianacode < 96) || (map->rm_pt > 95 && imp->ianacode > 95));
13747  } else {
13748  match = 0;
13749  }
13750  }
13751 
13752  if (match) {
13753  add_audio_codec(map, imp, ptime, buf, sizeof(buf));
13754  }
13755  }
13756  }
13757  }
13758 
13759  } else if (m->m_type == sdp_media_video && m->m_port) {
13760  connection = sdp->sdp_connection;
13761  if (m->m_connections) {
13762  connection = m->m_connections;
13763  }
13764 
13765  if (!connection) {
13766  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");
13767  break;
13768  }
13769 
13770  if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND || prefer_sdp) {
13771  for (map = m->m_rtpmaps; map; map = map->rm_next) {
13772 
13773  if (already_did[map->rm_pt]) {
13774  continue;
13775  }
13776 
13777  for (i = 0; i < num_codecs; i++) {
13778  const switch_codec_implementation_t *imp = codecs[i];
13779 
13780  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
13781  match = (map->rm_pt == imp->ianacode) ? 1 : 0;
13782  } else {
13783  if (map->rm_encoding) {
13784  match = !strcasecmp(map->rm_encoding, imp->iananame) &&
13785  ((map->rm_pt < 96 && imp->ianacode < 96) || (map->rm_pt > 95 && imp->ianacode > 95));
13786  } else {
13787  match = 0;
13788  }
13789  }
13790 
13791  if (match) {
13792  if (map->rm_fmtp) {
13793  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s.%s~%s", imp->modname, imp->iananame, map->rm_fmtp);
13794  } else {
13795  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s.%s", imp->modname, imp->iananame);
13796  }
13797 
13798  already_did[imp->ianacode] = 1;
13799  }
13800  }
13801  }
13802  } else {
13803  for (i = 0; i < num_codecs; i++) {
13804  const switch_codec_implementation_t *imp = codecs[i];
13805 
13806  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO || imp->ianacode > 127 || already_did[imp->ianacode]) {
13807  continue;
13808  }
13809 
13812  continue;
13813  }
13814 
13815  for (map = m->m_rtpmaps; map; map = map->rm_next) {
13816 
13817  if (already_did[map->rm_pt]) {
13818  continue;
13819  }
13820 
13821  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
13822  match = (map->rm_pt == imp->ianacode) ? 1 : 0;
13823  } else {
13824  if (map->rm_encoding) {
13825  match = !strcasecmp(map->rm_encoding, imp->iananame) &&
13826  ((map->rm_pt < 96 && imp->ianacode < 96) || (map->rm_pt > 95 && imp->ianacode > 95));
13827  } else {
13828  match = 0;
13829  }
13830  }
13831 
13832  if (match) {
13833  if (map->rm_fmtp) {
13834  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s.%s~%s", imp->modname, imp->iananame, map->rm_fmtp);
13835  } else {
13836  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s.%s", imp->modname, imp->iananame);
13837  }
13838 
13839  already_did[imp->ianacode] = 1;
13840  }
13841  }
13842  }
13843  }
13844  } else if (m->m_proto == sdp_proto_msrp) {
13846  } else if (m->m_proto == sdp_proto_msrps) {
13848  } else if (m->m_type == sdp_media_text) {
13850  }
13851  }
13852 
13853  if (buf[0] == ',') {
13854  switch_channel_set_variable(channel, "ep_codec_string", buf + 1);
13855  }
13856 }
13857 
13858 //?
13860 {
13861  switch_rtp_engine_t *engine;
13862  switch_media_handle_t *smh;
13863 
13864  switch_assert(session);
13865 
13866  if (!(smh = session->media_handle)) {
13867  return SWITCH_STATUS_FALSE;
13868  }
13869 
13870  engine = &smh->engines[type];
13871 
13872  if (engine->cur_payload_map->iananame) {
13873  return SWITCH_STATUS_SUCCESS;
13874  }
13875 
13876  return SWITCH_STATUS_FALSE;
13877 }
13878 
13880 {
13881  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
13882  switch_media_handle_t *smh;
13883  int type;
13884 
13885  switch_assert(session);
13886 
13887  if (!(smh = session->media_handle)) {
13888  return;
13889  }
13890 
13891  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
13892  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
13893  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
13894 
13895  if (switch_core_codec_ready(&v_engine->read_codec)) {
13896  type = 1;
13897  switch_core_codec_control(&v_engine->read_codec, SCC_VIDEO_RESET, SCCT_INT, (void *)&type, SCCT_NONE, NULL, NULL, NULL);
13898  }
13899 
13900  if (switch_core_codec_ready(&v_engine->write_codec)) {
13901  type = 2;
13902  switch_core_codec_control(&v_engine->write_codec, SCC_VIDEO_RESET, SCCT_INT, (void *)&type, SCCT_NONE, NULL, NULL, NULL);
13903  }
13904 
13905  if (a_engine->rtp_session) {
13906  switch_rtp_reset(a_engine->rtp_session);
13907  }
13908 
13909  if (v_engine->rtp_session) {
13910  switch_rtp_reset(v_engine->rtp_session);
13911  }
13912 
13913  if (t_engine->rtp_session) {
13914  switch_rtp_reset(t_engine->rtp_session);
13915  }
13916 
13917 
13918  smh->msid = NULL;
13919  smh->cname = NULL;
13920  v_engine->ice_out.ufrag = NULL;
13921  v_engine->ice_out.pwd = NULL;
13922  v_engine->ice_out.cands[0][0].foundation = NULL;
13923  v_engine->ice_out.cands[0][0].component_id = 0;
13924 
13925  t_engine->ice_out.ufrag = NULL;
13926  t_engine->ice_out.pwd = NULL;
13927  t_engine->ice_out.cands[0][0].foundation = NULL;
13928  t_engine->ice_out.cands[0][0].component_id = 0;
13929 
13930 
13931  a_engine->ice_out.ufrag = NULL;
13932  a_engine->ice_out.pwd = NULL;
13933  a_engine->ice_out.cands[0][0].foundation = NULL;
13934  a_engine->ice_out.cands[0][0].component_id = 0;
13935 
13936  if (v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].ready) {
13937  gen_ice(smh->session, SWITCH_MEDIA_TYPE_VIDEO, NULL, 0);
13938  }
13939 
13940  if (t_engine->ice_in.cands[t_engine->ice_in.chosen[0]][0].ready) {
13941  gen_ice(smh->session, SWITCH_MEDIA_TYPE_TEXT, NULL, 0);
13942  }
13943 
13944  if (a_engine->ice_in.cands[a_engine->ice_in.chosen[0]][0].ready) {
13945  gen_ice(smh->session, SWITCH_MEDIA_TYPE_AUDIO, NULL, 0);
13946  }
13947 
13948  smh->owner_id = 0;
13949  smh->session_id = 0;
13950 
13951  a_engine->local_dtls_fingerprint.len = 0;
13952  v_engine->local_dtls_fingerprint.len = 0;
13953  t_engine->local_dtls_fingerprint.len = 0;
13954 
13955  a_engine->remote_ssrc = 0;
13956  v_engine->remote_ssrc = 0;
13957  t_engine->remote_ssrc = 0;
13958 
13962 }
13963 
13964 
13965 
13966 //?
13968 {
13969  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
13970  switch_media_handle_t *smh;
13971  const char *r_sdp = NULL;
13972  payload_map_t *pmap;
13973 
13974  switch_assert(session);
13975 
13976  if (!switch_channel_test_flag(o_session->channel, CF_PROXY_MEDIA)) {
13977  return;
13978  }
13979 
13980  if (!(smh = session->media_handle)) {
13981  return;
13982  }
13983 
13985 
13986  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
13987  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
13988  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
13989 
13991 
13992  clear_pmaps(a_engine);
13993  clear_pmaps(v_engine);
13994 
13995  pmap = switch_core_media_add_payload_map(session,
13997  "PROXY",
13998  NULL,
13999  NULL,
14000  SDP_ANSWER,
14001  0,
14002  8000,
14003  20,
14004  1,
14005  SWITCH_TRUE);
14006 
14007  a_engine->cur_payload_map = pmap;
14008 
14009  if (switch_stristr("m=video", r_sdp)) {
14011  pmap = switch_core_media_add_payload_map(session,
14013  "PROXY-VID",
14014  NULL,
14015  NULL,
14016  SDP_ANSWER,
14017  0,
14018  90000,
14019  90000,
14020  1,
14021  SWITCH_TRUE);
14022 
14023  v_engine->cur_payload_map = pmap;
14024 
14027  }
14028 
14029 
14030  if (switch_stristr("m=text", r_sdp)) {
14032  pmap = switch_core_media_add_payload_map(session,
14034  "PROXY-TXT",
14035  NULL,
14036  NULL,
14037  SDP_ANSWER,
14038  0,
14039  1000,
14040  1000,
14041  1,
14042  SWITCH_TRUE);
14043 
14044  t_engine->cur_payload_map = pmap;
14045 
14048  }
14049 }
14050 
14051 
14053 {
14054  const char *ip;
14055  const char *port;
14056  const char *a_ip;
14057  const char *r_ip;
14058  const char *r_port;
14059  const char *tmp;
14060  switch_rtp_engine_t *a_engine, *v_engine;
14061  switch_media_handle_t *smh;
14062 
14063  switch_assert(session);
14064 
14065  if (!(smh = session->media_handle)) {
14066  return;
14067  }
14068 
14071 
14072  if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) || !(ip && port)) {
14073  return;
14074  } else {
14078  }
14079 
14080  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
14081  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
14082 
14083  a_engine->cur_payload_map->iananame = a_engine->cur_payload_map->rm_encoding = (char *) switch_channel_get_variable(session->channel, "rtp_use_codec_name");
14084  a_engine->cur_payload_map->rm_fmtp = (char *) switch_channel_get_variable(session->channel, "rtp_use_codec_fmtp");
14085 
14087  smh->mparams->remote_sdp_str = switch_core_session_strdup(session, tmp);
14088  }
14089 
14090  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_timer_name"))) {
14091  smh->mparams->timer_name = switch_core_session_strdup(session, tmp);
14092  }
14093 
14094  if ((tmp = switch_channel_get_variable(session->channel, "rtp_last_audio_codec_string"))) {
14095  const char *vtmp = switch_channel_get_variable(session->channel, "rtp_last_video_codec_string");
14096  switch_channel_set_variable_printf(session->channel, "rtp_use_codec_string", "%s%s%s", tmp, vtmp ? "," : "", vtmp ? vtmp : "");
14097  }
14098 
14099  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_string"))) {
14100  char *tmp_codec_string = switch_core_session_strdup(smh->session, tmp);
14101  smh->codec_order_last = switch_separate_string(tmp_codec_string, ',', smh->codec_order, SWITCH_MAX_CODECS);
14103  }
14104 
14105  if ((tmp = switch_channel_get_variable(session->channel, "rtp_2833_send_payload"))) {
14106  smh->mparams->te = (switch_payload_t)atoi(tmp);
14107  }
14108 
14109  if ((tmp = switch_channel_get_variable(session->channel, "rtp_2833_recv_payload"))) {
14110  smh->mparams->recv_te = (switch_payload_t)atoi(tmp);
14111  }
14112 
14113  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_rate"))) {
14114  a_engine->cur_payload_map->rm_rate = atoi(tmp);
14115  a_engine->cur_payload_map->adv_rm_rate = a_engine->cur_payload_map->rm_rate;
14116  }
14117 
14118  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_ptime"))) {
14119  a_engine->cur_payload_map->codec_ms = atoi(tmp);
14120  }
14121 
14122  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_channels"))) {
14123  a_engine->cur_payload_map->channels = atoi(tmp);
14124  }
14125 
14126  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_pt"))) {
14127  a_engine->cur_payload_map->pt = (switch_payload_t)(smh->payload_space = atoi(tmp));
14128  }
14129 
14130  if ((tmp = switch_channel_get_variable(session->channel, "rtp_audio_recv_pt"))) {
14131  a_engine->cur_payload_map->recv_pt = (switch_payload_t)atoi(tmp);
14132  }
14133 
14134  switch_core_media_set_codec(session, 0, smh->mparams->codec_flags);
14135 
14136  a_engine->adv_sdp_ip = smh->mparams->extrtpip = (char *) ip;
14137  a_engine->adv_sdp_port = a_engine->local_sdp_port = (switch_port_t)atoi(port);
14138  a_engine->codec_negotiated = 1;
14139 
14140  if (!zstr(ip)) {
14141  a_engine->local_sdp_ip = switch_core_session_strdup(session, ip);
14142  smh->mparams->rtpip = a_engine->local_sdp_ip;
14143  }
14144 
14145  if (!zstr(a_ip)) {
14146  a_engine->adv_sdp_ip = switch_core_session_strdup(session, a_ip);
14147  }
14148 
14149  if (r_ip && r_port) {
14150  a_engine->cur_payload_map->remote_sdp_ip = (char *) r_ip;
14151  a_engine->cur_payload_map->remote_sdp_port = (switch_port_t)atoi(r_port);
14152  }
14153 
14154  if (switch_channel_test_flag(session->channel, CF_VIDEO)) {
14155  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_video_pt"))) {
14156  v_engine->cur_payload_map->pt = (switch_payload_t)atoi(tmp);
14157  }
14158 
14159  if ((tmp = switch_channel_get_variable(session->channel, "rtp_video_recv_pt"))) {
14160  v_engine->cur_payload_map->recv_pt = (switch_payload_t)atoi(tmp);
14161  }
14162 
14163  v_engine->cur_payload_map->rm_encoding = (char *) switch_channel_get_variable(session->channel, "rtp_use_video_codec_name");
14164  v_engine->cur_payload_map->rm_fmtp = (char *) switch_channel_get_variable(session->channel, "rtp_use_video_codec_fmtp");
14165  v_engine->codec_negotiated = 1;
14166 
14170 
14172 
14173  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_video_codec_rate"))) {
14174  v_engine->cur_payload_map->rm_rate = atoi(tmp);
14175  v_engine->cur_payload_map->adv_rm_rate = v_engine->cur_payload_map->rm_rate;
14176  }
14177 
14178  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_video_codec_ptime"))) {
14179  v_engine->cur_payload_map->codec_ms = atoi(tmp);
14180  }
14181 
14182  v_engine->adv_sdp_port = v_engine->local_sdp_port = (switch_port_t)atoi(port);
14183  v_engine->local_sdp_ip = smh->mparams->rtpip;
14184 
14185  if (r_ip && r_port) {
14186  v_engine->cur_payload_map->remote_sdp_ip = (char *) r_ip;
14187  v_engine->cur_payload_map->remote_sdp_port = (switch_port_t)atoi(r_port);
14188  }
14189  }
14190 
14191  switch_core_media_gen_local_sdp(session, SDP_OFFER, NULL, 0, NULL, 1);
14193 
14195  return;
14196  }
14197 
14200 
14201 
14202  if ((tmp = switch_channel_get_variable(session->channel, "rtp_last_audio_local_crypto_key")) && a_engine->ssec[a_engine->crypto_type].remote_crypto_key) {
14203  int idx = atoi(tmp);
14204 
14205  a_engine->ssec[a_engine->crypto_type].local_crypto_key = switch_core_session_strdup(session, tmp);
14206  switch_core_media_add_crypto(session, &a_engine->ssec[a_engine->crypto_type],SWITCH_RTP_CRYPTO_SEND);
14207  switch_core_media_add_crypto(session, &a_engine->ssec[a_engine->crypto_type],SWITCH_RTP_CRYPTO_RECV);
14209 
14210  switch_rtp_add_crypto_key(a_engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, idx, &a_engine->ssec[a_engine->crypto_type]);
14211 
14212  switch_rtp_add_crypto_key(a_engine->rtp_session, SWITCH_RTP_CRYPTO_RECV, a_engine->ssec[a_engine->crypto_type].crypto_tag, &a_engine->ssec[a_engine->crypto_type]);
14213  }
14214 
14215 
14219  }
14220 
14221 }
14222 
14223 
14225 {
14228  }
14229 
14230  video_globals.cpu_count = switch_core_cpu_count();
14231  video_globals.cur_cpu = 0;
14232 
14233  switch_core_new_memory_pool(&video_globals.pool);
14234  switch_mutex_init(&video_globals.mutex, SWITCH_MUTEX_NESTED, video_globals.pool);
14235 
14236 }
14237 
14239 {
14240  if (video_globals.pool) {
14241  switch_core_destroy_memory_pool(&video_globals.pool);
14242  }
14243 }
14244 
14245 static int payload_number(const char *name)
14246 {
14247  if (!strcasecmp(name, "pcmu")) {
14248  return 0;
14249  }
14250 
14251  if (!strcasecmp(name, "pcma")) {
14252  return 8;
14253  }
14254 
14255  if (!strcasecmp(name, "gsm")) {
14256  return 3;
14257  }
14258 
14259  if (!strcasecmp(name, "g722")) {
14260  return 9;
14261  }
14262 
14263  if (!strcasecmp(name, "g729")) {
14264  return 18;
14265  }
14266 
14267  if (!strcasecmp(name, "dvi4")) {
14268  return 5;
14269  }
14270 
14271  if (!strcasecmp(name, "h261")) {
14272  return 31;
14273  }
14274 
14275  if (!strcasecmp(name, "h263")) {
14276  return 34;
14277  }
14278 
14279  return -1;
14280 }
14281 
14282 static int find_pt(const char *sdp, const char *name)
14283 {
14284  const char *p;
14285 
14286  if ((p = switch_stristr(name, sdp))) {
14287  if (p < end_of_p(sdp) && *(p+strlen(name)) == '/' && *(p-1) == ' ') {
14288  p -= 2;
14289 
14290  while(*p > 47 && *p < 58) {
14291  p--;
14292  }
14293  p++;
14294 
14295  if (p) {
14296  return atoi(p);
14297  }
14298  }
14299  }
14300 
14301  return -1;
14302 }
14303 
14304 
14305 SWITCH_DECLARE(char *) switch_core_media_filter_sdp(const char *sdp_str, const char *cmd, const char *arg)
14306 {
14307  char *new_sdp = NULL;
14308  int pt = -1, te = -1;
14309  switch_size_t len;
14310  const char *i;
14311  char *o;
14312  int in_m = 0, slash = 0;
14313  int number = 0, skip = 0;
14314  int remove = !strcasecmp(cmd, "remove");
14315  int only = !strcasecmp(cmd, "only");
14316  char *end = end_of_p((char *)sdp_str);
14317  int tst;
14318  end++;
14319 
14320 
14321  if (remove || only) {
14322  pt = payload_number(arg);
14323 
14324  if (pt < 0) {
14325  pt = find_pt(sdp_str, arg);
14326  }
14327  } else {
14328  return NULL;
14329  }
14330 
14331  if (only) {
14332  te = find_pt(sdp_str, "telephone-event");
14333  }
14334 
14335 
14336  len = strlen(sdp_str) + 2;
14337  new_sdp = malloc(len);
14338  o = new_sdp;
14339  i = sdp_str;
14340 
14341 
14342  while(i && *i && i < end) {
14343 
14344  if (*i == 'm' && *(i+1) == '=') {
14345  in_m = 1;
14346  }
14347 
14348  if (in_m) {
14349  if (*i == '\r' || *i == '\n') {
14350  in_m = 0;
14351  slash = 0;
14352  } else {
14353  if (*i == '/') {
14354  slash++;
14355  while(*i != ' ' && i < end) {
14356  *o++ = *i++;
14357  }
14358 
14359  *o++ = *i++;
14360  }
14361 
14362  if (slash && switch_is_leading_number(i)) {
14363 
14364 
14365  number = atoi(i);
14366 
14367  while(i < end && ((*i > 47 && *i < 58) || *i == ' ')) {
14368 
14369  if (remove) {
14370  tst = (number != pt);
14371  } else {
14372  tst = (number == pt || number == te);
14373  }
14374 
14375  if (tst) {
14376  *o++ = *i;
14377  }
14378  i++;
14379 
14380  if (*i == ' ') {
14381  break;
14382  }
14383 
14384  }
14385 
14386  if (remove) {
14387  tst = (number == pt);
14388  } else {
14389  tst = (number != pt && number != te);
14390  }
14391 
14392  if (tst) {
14393  skip++;
14394  }
14395  }
14396  }
14397  }
14398 
14399  while (i < end && !strncasecmp(i, "a=rtpmap:", 9)) {
14400  const char *t = i + 9;
14401 
14402  number = atoi(t);
14403 
14404  if (remove) {
14405  tst = (number == pt);
14406  } else {
14407  tst = (number != pt && number != te);
14408  }
14409 
14410  while(i < end && (*i != '\r' && *i != '\n')) {
14411  if (!tst) *o++ = *i;
14412  i++;
14413  }
14414 
14415  while(i < end && (*i == '\r' || *i == '\n')) {
14416  if (!tst) *o++ = *i;
14417  i++;
14418  }
14419  }
14420 
14421  while (i < end && !strncasecmp(i, "a=fmtp:", 7)) {
14422  const char *t = i + 7;
14423 
14424  number = atoi(t);
14425 
14426  if (remove) {
14427  tst = (number == pt);
14428  } else {
14429  tst = (number != pt && number != te);
14430  }
14431 
14432  while(i < end && (*i != '\r' && *i != '\n')) {
14433  if (!tst) *o++ = *i;
14434  i++;
14435  }
14436 
14437  while(i < end && (*i == '\r' || *i == '\n')) {
14438  if (!tst) *o++ = *i;
14439  i++;
14440  }
14441  }
14442 
14443  if (!skip) {
14444  *o++ = *i;
14445  }
14446 
14447  skip = 0;
14448 
14449  i++;
14450  }
14451 
14452  *o = '\0';
14453 
14454  return new_sdp;
14455 }
14456 
14458 {
14460  char *cmd = switch_core_session_strdup(session, cmd_buf);
14461  int argc = 0;
14462  char *argv[50];
14463  int x = 0;
14464  char *patched_sdp = NULL;
14465 
14466  argc = switch_split(cmd, '|', argv);
14467 
14468  for (x = 0; x < argc; x++) {
14469  char *command = argv[x];
14470  char *arg = strchr(command, '(');
14471 
14472  if (arg) {
14473  char *e = switch_find_end_paren(arg, '(', ')');
14474  *arg++ = '\0';
14475  if (e) *e = '\0';
14476  }
14477 
14478  if (zstr(command) || zstr(arg)) {
14479  switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "%s SDP FILTER PARSE ERROR\n", switch_channel_get_name(channel));
14480  } else {
14481  char *tmp_sdp = NULL;
14482 
14483  if (patched_sdp) {
14484  tmp_sdp = switch_core_media_filter_sdp(patched_sdp, command, arg);
14485  } else {
14486  tmp_sdp = switch_core_media_filter_sdp(sdp, command, arg);
14487  }
14488 
14489 
14491  "%s Filter command %s(%s)\nFROM:\n==========\n%s\nTO:\n==========\n%s\n\n",
14492  switch_channel_get_name(channel),
14493  command, arg, patched_sdp ? patched_sdp : sdp, tmp_sdp);
14494 
14495 
14496  if (tmp_sdp) {
14497  switch_safe_free(patched_sdp);
14498  patched_sdp = tmp_sdp;
14499  }
14500  }
14501  }
14502 
14503  return patched_sdp;
14504 
14505 }
14506 
14507 
14509 {
14510  switch_rtp_engine_t *engine = NULL;
14511  switch_media_handle_t *smh = NULL;
14512 
14513  switch_assert(session);
14514 
14515  if (!(smh = session->media_handle)) {
14516  return NULL;
14517  }
14518 
14519  if (!(engine = &smh->engines[mtype])) {
14520  return NULL;
14521  }
14522 
14523  return switch_rtp_get_media_timer(engine->rtp_session);
14524 
14525 }
14526 
14528 {
14530  switch_media_handle_t *smh = NULL;
14531 
14532  switch_assert(session);
14533 
14534  if (!(smh = session->media_handle)) {
14535  return SWITCH_STATUS_FALSE;
14536  }
14537 
14538  if (switch_channel_media_up(channel) && switch_channel_test_flag(channel, CF_VIDEO)) {
14539  switch_core_session_message_t msg = { 0 };
14541 
14542  if (!force && (smh->last_video_refresh_req && (now - smh->last_video_refresh_req) < VIDEO_REFRESH_FREQ)) {
14543  return SWITCH_STATUS_BREAK;
14544  }
14545 
14546  smh->last_video_refresh_req = now;
14547 
14548  if (force) {
14549  msg.numeric_arg = 1;
14550  }
14551 
14552  msg._file = file;
14553  msg._func = func;
14554  msg._line = line;
14556  SWITCH_LOG_DEBUG1, "%s Video refresh requested.\n", switch_channel_get_name(session->channel));
14557  msg.from = __FILE__;
14559  switch_core_session_receive_message(session, &msg);
14560  return SWITCH_STATUS_SUCCESS;
14561  }
14562 
14563  return SWITCH_STATUS_FALSE;
14564 }
14565 
14567 {
14568  if (switch_channel_test_flag(session->channel, CF_VIDEO)) {
14571  return SWITCH_STATUS_SUCCESS;
14572  }
14573 
14574  return SWITCH_STATUS_FALSE;
14575 }
14576 
14577 
14579  switch_media_type_t mtype,
14580  switch_io_type_t iotype,
14583  void *cmd_data,
14585  void *cmd_arg,
14587  void **ret_data)
14588 {
14589  switch_rtp_engine_t *engine = NULL;
14590  switch_media_handle_t *smh = NULL;
14591  switch_codec_t *codec = NULL;
14592 
14593  switch_assert(session);
14594 
14595  if (!(smh = session->media_handle)) {
14596  return SWITCH_STATUS_FALSE;
14597  }
14598 
14599  if (!(engine = &smh->engines[mtype])) {
14600  return SWITCH_STATUS_NOTIMPL;
14601  }
14602 
14603  if (iotype == SWITCH_IO_READ) {
14604  codec = &engine->read_codec;
14605  } else {
14606  codec = &engine->write_codec;
14607  }
14608 
14609  if (!switch_core_codec_ready(codec)) {
14610  return SWITCH_STATUS_FALSE;
14611  }
14612 
14613  if (mtype == SWITCH_MEDIA_TYPE_VIDEO) {
14614  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
14615  return SWITCH_STATUS_FALSE;
14616  }
14617  }
14618 
14619  if (codec) {
14620  return switch_core_codec_control(codec, cmd, ctype, cmd_data, atype, cmd_arg, rtype, ret_data);
14621  }
14622 
14623  return SWITCH_STATUS_FALSE;
14624 }
14625 
14627  switch_media_type_t mtype,
14628  switch_codec_flag_t flag) {
14629  switch_rtp_engine_t *engine = NULL;
14630  switch_media_handle_t *smh = NULL;
14631  switch_codec_t *codec = NULL;
14632 
14633  switch_assert(session);
14634 
14635  if (!(smh = session->media_handle)) {
14636  return SWITCH_FALSE;
14637  }
14638 
14639  if (!(engine = &smh->engines[mtype])) {
14640  return SWITCH_FALSE;
14641  }
14642 
14643  codec = &engine->write_codec;
14644 
14645  if (!switch_core_codec_ready(codec)) {
14646  return SWITCH_FALSE;
14647  }
14648 
14649  if (switch_test_flag(codec, flag)){
14650  return SWITCH_TRUE;
14651  }
14652 
14653  return SWITCH_FALSE;
14654 }
14655 
14657  switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
14658 {
14661 
14663  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG3, "Writing video to RECVONLY/INACTIVE session\n");
14664  return SWITCH_STATUS_SUCCESS;
14665  }
14666 
14668  if ((status = session->endpoint_interface->io_routines->write_video_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
14669  for (ptr = session->event_hooks.video_write_frame; ptr; ptr = ptr->next) {
14670  if ((status = ptr->video_write_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
14671  break;
14672  }
14673  }
14674  }
14675  }
14676 
14677  return status;
14678 }
14679 
14681 {
14682  switch_media_handle_t *smh;
14683  int type;
14684 
14685  switch_assert(session);
14686 
14687  if (!(smh = session->media_handle)) {
14688  return;
14689  }
14690 
14691  if (switch_channel_down(session->channel)) {
14692  return;
14693  }
14694 
14695  smh->video_init = 0;
14696  smh->video_last_key_time = 0;
14698 
14699  type = 1;
14702 
14703 }
14704 
14706  int stream_id)
14707 {
14711  switch_timer_t *timer;
14712  switch_media_handle_t *smh;
14713  switch_image_t *dup_img = NULL, *img = frame->img;
14714  switch_status_t encode_status;
14715  switch_frame_t write_frame = {0};
14716  switch_rtp_engine_t *v_engine = NULL;
14717  switch_bool_t need_free = SWITCH_FALSE;
14718  switch_assert(session);
14719 
14720  if (!(smh = session->media_handle)) {
14721  return SWITCH_STATUS_FALSE;
14722  }
14723 
14724  if (switch_channel_down(session->channel)) {
14725  return SWITCH_STATUS_FALSE;
14726  }
14727 
14728  if (!codec) {
14729  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s has no video codec\n", switch_core_session_get_name(session));
14730  return SWITCH_STATUS_FALSE;
14731  }
14732 
14733 
14735  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG3, "Writing video to RECVONLY/INACTIVE session\n");
14736  return SWITCH_STATUS_SUCCESS;
14737  }
14738 
14740  return SWITCH_STATUS_SUCCESS;
14741  }
14742 
14743  if (!(switch_channel_test_flag(session->channel, CF_VIDEO_READY) || (flags & SWITCH_IO_FLAG_FORCE))) {
14744  return SWITCH_STATUS_SUCCESS;
14745  }
14746 
14748  /* return CNG, another thread is already writing */
14749  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s is already being written to for %s\n",
14751  return SWITCH_STATUS_INUSE;
14752  }
14753 
14754  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
14755  if (v_engine->thread_write_lock && v_engine->thread_write_lock != switch_thread_self()) {
14757  }
14758 
14759  if (!smh->video_init && smh->mparams->video_key_first && (now - smh->video_last_key_time) > smh->mparams->video_key_first) {
14761 
14762  if (smh->video_last_key_time) {
14763  smh->video_init = 1;
14764  }
14765 
14766  smh->video_last_key_time = now;
14767  }
14768 
14769  if (smh->mparams->video_key_freq && (now - smh->video_last_key_time) > smh->mparams->video_key_freq) {
14771  smh->video_last_key_time = now;
14772  }
14773 
14774  if (!img) {
14775  switch_status_t vstatus;
14776 
14777  vstatus = switch_core_session_write_encoded_video_frame(session, frame, flags, stream_id);
14778  switch_goto_status(vstatus, done);
14779  }
14780 
14781 
14782  /* When desired, scale video to match the input signal (if output is bigger) */
14785  switch_vid_params_t vid_params = { 0 };
14786 
14787  switch_core_media_get_vid_params(session, &vid_params);
14788 
14789  if (vid_params.width && vid_params.height && ((vid_params.width != img->d_w) || (vid_params.height != img->d_h))) {
14790  switch_img_letterbox(img, &dup_img, vid_params.width, vid_params.height, "#000000f");
14791  if (!(img = dup_img)) {
14793  }
14794  }
14795  }
14796 
14798  smh->vid_params.d_width = img->d_w;
14799  smh->vid_params.d_height = img->d_h;
14800  }
14801 
14802  if (session->bugs) {
14803  switch_media_bug_t *bp;
14804  int prune = 0;
14805  int patched = 0;
14806 
14808  for (bp = session->bugs; bp; bp = bp->next) {
14810 
14812  continue;
14813  }
14814 
14816  continue;
14817  }
14818 
14819  if (switch_test_flag(bp, SMBF_PRUNE)) {
14820  prune++;
14821  continue;
14822  }
14823 
14825  switch_image_t *dimg = NULL;
14826 
14827  switch_img_copy(img, &dimg);
14829 
14832  patched = 1;
14833  }
14834 
14835  }
14836 
14837  if (bp->ready && img &&
14839  switch_frame_t bug_frame = { 0 };
14840 
14841  bug_frame.img = img;
14842 
14844  bp->video_ping_frame = &bug_frame;
14846  || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) {
14847  ok = SWITCH_FALSE;
14848  }
14849  bp->video_ping_frame = NULL;
14850  }
14851 
14852  if (bug_frame.img && bug_frame.img != img) {
14853  need_free = SWITCH_TRUE;
14854  img = bug_frame.img;
14855  }
14856 
14859  }
14860 
14861 
14862  }
14863 
14864  if (ok == SWITCH_FALSE) {
14866  prune++;
14867  }
14868 
14869  }
14870 
14872 
14873  if (prune) {
14874  switch_core_media_bug_prune(session);
14875  }
14876 
14877  }
14878 
14879  write_frame = *frame;
14880  frame = &write_frame;
14881  frame->img = img;
14882 
14884 
14885  if (!(timer = switch_core_media_get_timer(session, SWITCH_MEDIA_TYPE_VIDEO))) {
14886 
14887  if (!smh->video_timer.timer_interface) {
14888  switch_core_timer_init(&smh->video_timer, "soft", 1, 90, switch_core_session_get_pool(session));
14889  }
14891  timer = &smh->video_timer;
14892  }
14893 
14894  frame->timestamp = timer->samplecount;
14895  }
14896 
14898  frame->m = 0;
14899 
14900  do {
14902  encode_status = switch_core_codec_encode_video(codec, frame);
14903 
14904  if (encode_status == SWITCH_STATUS_SUCCESS || encode_status == SWITCH_STATUS_MORE_DATA) {
14905 
14906  switch_assert((encode_status == SWITCH_STATUS_SUCCESS && frame->m) || !frame->m);
14907 
14908  if (frame->flags & SFF_PICTURE_RESET) {
14910  frame->flags &= ~SFF_PICTURE_RESET;
14911  }
14912 
14913  if (frame->datalen == 0) break;
14914 
14916  status = switch_core_session_write_encoded_video_frame(session, frame, flags, stream_id);
14917  }
14918 
14919  } while(status == SWITCH_STATUS_SUCCESS && encode_status == SWITCH_STATUS_MORE_DATA);
14920 
14921  done:
14922 
14925  }
14926 
14927  switch_img_free(&dup_img);
14928 
14929  if (need_free) {
14930  switch_img_free(&frame->img);
14931  }
14932 
14933  return status;
14934 }
14935 
14937 {
14938  switch_media_handle_t *smh;
14939  switch_codec_implementation_t read_impl = { 0 };
14940  switch_rtp_engine_t *v_engine = NULL;
14941 
14942  switch_assert(session != NULL);
14943 
14944  if (!(smh = session->media_handle)) {
14945  return SWITCH_STATUS_FALSE;
14946  }
14947 
14949  return SWITCH_STATUS_GENERR;
14950  }
14951 
14952  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
14953 
14954  if (v_engine->smode == SWITCH_MEDIA_FLOW_SENDONLY) {
14955  return SWITCH_STATUS_NOTIMPL;
14956  }
14957 
14958  switch_core_session_get_read_impl(session, &read_impl);
14959 
14960  while(switch_channel_ready(session->channel) && timeout_ms > 0) {
14961  switch_frame_t *read_frame;
14962  switch_status_t status;
14963 
14964  if (video_globals.synced &&
14966  return SWITCH_STATUS_SUCCESS;
14967  }
14968 
14970  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
14971 
14972  if (!SWITCH_READ_ACCEPTABLE(status)) {
14973  return SWITCH_STATUS_FALSE;
14974  }
14975 
14976  timeout_ms -= (read_impl.microseconds_per_packet / 1000);
14977  }
14978 
14979  return SWITCH_STATUS_TIMEOUT;
14980 
14981 }
14982 
14984 {
14985  switch_bool_t transcoding = SWITCH_FALSE;
14986 
14987  switch(type) {
14989  {
14990  switch_codec_implementation_t read_impl_a = { 0 }, read_impl_b = { 0 };
14991 
14992  switch_core_session_get_read_impl(session_a, &read_impl_a);
14993  switch_core_session_get_read_impl(session_b, &read_impl_b);
14994 
14995  if (read_impl_a.impl_id && read_impl_b.impl_id) {
14996  transcoding = (read_impl_a.impl_id != read_impl_b.impl_id || read_impl_a.decoded_bytes_per_packet != read_impl_b.decoded_bytes_per_packet);
14997  }
14998  }
14999  break;
15001  transcoding = (switch_channel_test_flag(session_a->channel, CF_VIDEO_DECODED_READ) ||
15003  break;
15004  default:
15005  break;
15006  }
15007 
15008  return transcoding;
15009 
15010 }
15011 
15013 {
15014  switch_rtp_engine_t *engine;
15015 
15016  if (!session->media_handle) return;
15017 
15018  engine = &session->media_handle->engines[type];
15019 
15020 
15021  if (switch_rtp_ready(engine->rtp_session)) {
15022  char var[50] = "";
15023  switch_snprintf(var, sizeof(var), "disable_%s_jb_during_passthru", type2str(type));
15024 
15025  if (switch_channel_var_true(session->channel, var)) {
15026  if (on) {
15028  } else {
15030  }
15031  }
15032 
15033  if (type == SWITCH_MEDIA_TYPE_VIDEO) {
15035  if (!on) {
15037  }
15038  }
15039 
15040  }
15041 
15042 }
15043 
15045  int stream_id)
15046 {
15049  switch_media_handle_t *smh;
15050  int is_keyframe = 0;
15051 
15052  switch_assert(session != NULL);
15053 
15054  if (!(smh = session->media_handle)) {
15055  return SWITCH_STATUS_FALSE;
15056  }
15057 
15058  top:
15059 
15060  if (switch_channel_down_nosig(session->channel)) {
15061  return SWITCH_STATUS_FALSE;
15062  }
15063 
15065  if ((status = session->endpoint_interface->io_routines->read_video_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
15066  for (ptr = session->event_hooks.video_read_frame; ptr; ptr = ptr->next) {
15067  if ((status = ptr->video_read_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
15068  break;
15069  }
15070  }
15071  }
15072  }
15073 
15075  *frame = &runtime.dummy_cng_frame;
15076  switch_cond_next();
15077  return SWITCH_STATUS_SUCCESS;
15078  }
15079 
15080  if (status == SWITCH_STATUS_INUSE) {
15081  *frame = &runtime.dummy_cng_frame;
15082  switch_cond_next();
15083  return SWITCH_STATUS_SUCCESS;
15084  }
15085 
15086  if (status != SWITCH_STATUS_SUCCESS) {
15087  goto done;
15088  }
15089 
15090  if (!(*frame)) {
15091  goto done;
15092  }
15093 
15095  if (switch_test_flag((*frame), SFF_CNG)) {
15097  } else {
15099  "VIDEO: seq: %d ts: %u len: %4d %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x mark: %d\n",
15100  (*frame)->seq, (*frame)->timestamp, (*frame)->datalen,
15101  *((uint8_t *)(*frame)->data), *((uint8_t *)(*frame)->data + 1),
15102  *((uint8_t *)(*frame)->data + 2), *((uint8_t *)(*frame)->data + 3),
15103  *((uint8_t *)(*frame)->data + 4), *((uint8_t *)(*frame)->data + 5),
15104  *((uint8_t *)(*frame)->data + 6), *((uint8_t *)(*frame)->data + 7),
15105  *((uint8_t *)(*frame)->data + 8), *((uint8_t *)(*frame)->data + 9),
15106  *((uint8_t *)(*frame)->data + 10), (*frame)->m);
15107  }
15108  }
15109 
15110 
15111  if (switch_test_flag(*frame, SFF_CNG)) {
15112  status = SWITCH_STATUS_SUCCESS;
15113  goto done;
15114  }
15115 
15116  if (switch_channel_test_flag(session->channel, CF_VIDEO_DECODED_READ) && (*frame)->img == NULL) {
15117  switch_status_t decode_status;
15118 
15119  (*frame)->img = NULL;
15120 
15121  decode_status = switch_core_codec_decode_video((*frame)->codec, *frame);
15122  if (switch_test_flag(*frame, SFF_IS_KEYFRAME)) {
15123  is_keyframe++;
15124  }
15125  if ((*frame)->img && switch_channel_test_flag(session->channel, CF_VIDEO_DEBUG_READ)) {
15126  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "IMAGE %dx%d %dx%d\n",
15127  (*frame)->img->w, (*frame)->img->h, (*frame)->img->d_w, (*frame)->img->d_h);
15128  }
15129 
15130  if ((*frame)->img && (*frame)->img->d_w && (*frame)->img->d_h) {
15131  int new_w = 0, new_h = 0;
15132 
15133  if ((*frame)->img->d_w != smh->vid_params.width || (*frame)->img->d_h != smh->vid_params.height) {
15134  new_w = (*frame)->img->d_w;
15135  new_h = (*frame)->img->d_h;
15136 
15137  if (new_w && new_h) {
15139  smh->vid_params.width = new_w;
15140  smh->vid_params.height = new_h;
15141  switch_channel_set_variable_printf(session->channel, "video_width", "%d", new_w);
15142  switch_channel_set_variable_printf(session->channel, "video_height", "%d", new_h);
15144  }
15145  }
15146  }
15147 
15148  if (switch_test_flag((*frame), SFF_WAIT_KEY_FRAME)) {
15151 
15152  if (!(*frame)->img) {
15153  *frame = &runtime.dummy_cng_frame;
15154  switch_cond_next();
15155  return SWITCH_STATUS_SUCCESS;
15156  }
15157  }
15158 
15159  if (decode_status == SWITCH_STATUS_MORE_DATA || !(*frame)->img) {
15160  goto top;
15161  }
15162  }
15163 
15164  if (!switch_channel_test_flag(session->channel, CF_VIDEO_READY) && *frame) {
15166  if ((*frame)->img) {
15168  }
15169  } else if ((*frame)->m || ++smh->ready_loops > 5) {
15171  }
15172  }
15173 
15174  done:
15175 
15176  if (*frame && is_keyframe) {
15178  }
15179 
15180  if (session->bugs) {
15181  switch_media_bug_t *bp;
15182  int prune = 0;
15183  int patched = 0;
15184 
15186  for (bp = session->bugs; bp; bp = bp->next) {
15188 
15190  continue;
15191  }
15192 
15194  continue;
15195  }
15196 
15197  if (switch_test_flag(bp, SMBF_PRUNE)) {
15198  prune++;
15199  continue;
15200  }
15201 
15202  if (bp->ready && switch_test_flag(bp, SMBF_READ_VIDEO_STREAM)) {
15203  if ((*frame) && (*frame)->img) {
15204  switch_image_t *img = NULL;
15205  switch_img_copy((*frame)->img, &img);
15209  patched = 1;
15210  }
15211  }
15212  }
15213 
15214  if (bp->ready && (*frame) && (*frame)->img &&
15216 
15217 
15219  bp->video_ping_frame = *frame;
15220 
15222  || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) {
15223  ok = SWITCH_FALSE;
15224  }
15225  bp->video_ping_frame = NULL;
15226  }
15227 
15230  }
15231  }
15232 
15233  if (ok == SWITCH_FALSE) {
15235  prune++;
15236  }
15237  }
15238 
15240 
15241  if (prune) {
15242  switch_core_media_bug_prune(session);
15243  }
15244  }
15245 
15246  if ((*frame) && (*frame)->codec) {
15247  (*frame)->pmap = NULL;
15248  }
15249 
15250  if (status == SWITCH_STATUS_SUCCESS) {
15251  switch_core_session_video_read_callback(session, *frame);
15252  }
15253 
15254  return status;
15255 }
15256 
15257 
15259  switch_core_video_thread_callback_func_t func, void *user_data)
15260 {
15262  switch_media_handle_t *smh;
15263 
15264  if (!(smh = session->media_handle)) {
15265  return SWITCH_STATUS_FALSE;
15266  }
15267 
15269  if (!func) {
15270  session->video_read_callback = NULL;
15271  session->video_read_user_data = NULL;
15272  } else if (session->video_read_callback) {
15273  status = SWITCH_STATUS_FALSE;
15274  } else {
15275  session->video_read_callback = func;
15276  session->video_read_user_data = user_data;
15277  }
15278 
15281 
15282  return status;
15283 }
15284 
15286 {
15287  switch_media_handle_t *smh;
15289 
15290  if (!(smh = session->media_handle)) {
15291  return SWITCH_STATUS_FALSE;
15292  }
15293 
15295 
15296  if (session->video_read_callback) {
15297  status = session->video_read_callback(session, frame, session->video_read_user_data);
15298  }
15299 
15301 
15302  return status;
15303 }
15304 
15305 
15306 
15308  switch_core_text_thread_callback_func_t func, void *user_data)
15309 {
15311  switch_media_handle_t *smh;
15312 
15313  if (!(smh = session->media_handle)) {
15314  return SWITCH_STATUS_FALSE;
15315  }
15316 
15318  if (!func) {
15319  session->text_read_callback = NULL;
15320  session->text_read_user_data = NULL;
15321  } else if (session->text_read_callback) {
15322  status = SWITCH_STATUS_FALSE;
15323  } else {
15324  session->text_read_callback = func;
15325  session->text_read_user_data = user_data;
15326  }
15327 
15330 
15331  return status;
15332 }
15333 
15334 
15335 
15337 {
15338  switch_media_handle_t *smh;
15340 
15341  if (!(smh = session->media_handle)) {
15342  return SWITCH_STATUS_FALSE;
15343  }
15344 
15346 
15347  if (session->text_read_callback) {
15348  status = session->text_read_callback(session, frame, session->text_read_user_data);
15349  }
15350 
15352 
15353  return status;
15354 }
15355 
15356 
15357 
15359  int stream_id)
15360 {
15363  switch_media_handle_t *smh;
15364  switch_io_read_text_frame_t read_text_frame = NULL;
15365  switch_time_t now;
15366 
15367  switch_assert(session != NULL);
15368 
15369  if (!(smh = session->media_handle)) {
15370  return SWITCH_STATUS_FALSE;
15371  }
15372 
15373  if (switch_channel_down_nosig(session->channel)) {
15374  return SWITCH_STATUS_FALSE;
15375  }
15376 
15377  if (!(read_text_frame = session->endpoint_interface->io_routines->read_text_frame)) {
15378  if (session->io_override) {
15379  read_text_frame = session->io_override->read_text_frame;
15380  }
15381  }
15382 
15383  if (read_text_frame) {
15384  if ((status = read_text_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
15385  for (ptr = session->event_hooks.text_read_frame; ptr; ptr = ptr->next) {
15386  if ((status = ptr->text_read_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
15387  break;
15388  }
15389  }
15390  }
15391  }
15392 
15393  if (status == SWITCH_STATUS_INUSE) {
15394  *frame = &runtime.dummy_cng_frame;
15395  switch_cond_next();
15396  return SWITCH_STATUS_SUCCESS;
15397  }
15398 
15399  if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
15400  goto done;
15401  }
15402 
15403  if (!(*frame)) {
15404  goto done;
15405  }
15406 
15407  now = switch_micro_time_now();
15408 
15409  if (switch_test_flag((*frame), SFF_CNG)) {
15410  if (smh->last_text_frame && now - smh->last_text_frame > TEXT_PERIOD_TIMEOUT * 1000) {
15413  smh->last_text_frame = 0;
15414  }
15415  } else {
15416  unsigned char *p = (*frame)->data;
15417 
15418  smh->last_text_frame = now;
15421 
15422  while(p && *p) {
15423  if (*p == '\r' || *p == '\n') {
15425  break;
15426  }
15427 
15428  if (*p == 0xE2 && *(p+1) == 0x80 && *(p+2) == 0xA8) {
15430  break;
15431  }
15432 
15433  p++;
15434  }
15435  }
15436 
15437  if ((*frame)->data && (*frame)->datalen && !((*frame)->flags & SFF_CNG)) {
15438  if (!session->text_buffer) {
15440  switch_buffer_create_dynamic(&session->text_buffer, 512, 1024, 0);
15441  }
15442  switch_buffer_write(session->text_buffer, (*frame)->data, (*frame)->datalen);
15443  }
15444 
15445  if (session->bugs) {
15446  switch_media_bug_t *bp;
15447  int prune = 0;
15448 
15450  for (bp = session->bugs; bp; bp = bp->next) {
15452 
15454  continue;
15455  }
15456 
15458  continue;
15459  }
15460 
15461  if (switch_test_flag(bp, SMBF_PRUNE)) {
15462  prune++;
15463  continue;
15464  }
15465 
15466  if (bp->ready && switch_test_flag(bp, SMBF_READ_TEXT_STREAM)) {
15467  int bytes = 0;
15468 
15469  if ((*frame)) {
15470  switch_size_t inuse = 0;
15471 
15472  if ((*frame)->data && (*frame)->datalen && !((*frame)->flags & SFF_CNG)) {
15473  switch_mutex_lock(session->text_mutex);
15474  switch_buffer_write(bp->text_buffer, (char *)(*frame)->data, (*frame)->datalen);
15475  switch_mutex_unlock(session->text_mutex);
15476  }
15477 
15478  inuse = switch_buffer_inuse(bp->text_buffer);
15479 
15480  if (zstr(bp->text_framedata) && inuse &&
15482 
15483  if (inuse + 1 > bp->text_framesize) {
15484  void *tmp = malloc(inuse + 1024);
15485  memcpy(tmp, bp->text_framedata, bp->text_framesize);
15486 
15487  switch_assert(tmp);
15488 
15489  bp->text_framesize = inuse + 1024;
15490 
15491  free(bp->text_framedata);
15492  bp->text_framedata = tmp;
15493 
15494  }
15495 
15496 
15497  bytes = switch_buffer_read(bp->text_buffer, bp->text_framedata, inuse);
15498  *(bp->text_framedata + bytes) = '\0';
15499 
15500  ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_TEXT);
15501  bp->text_framedata[0] = '\0';
15502  } else ok = SWITCH_TRUE;
15503  }
15504  }
15505 
15506  if (ok == SWITCH_FALSE) {
15508  prune++;
15509  }
15510  }
15511 
15513 
15514  if (prune) {
15515  switch_core_media_bug_prune(session);
15516  }
15517  }
15518 
15519  if (status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK) {
15521  (*frame)->datalen && !switch_test_flag((*frame), SFF_CNG)) {
15522  int ok = 1;
15523  switch_event_t *event;
15524  void *data = (*frame)->data;
15525  char eof[1] = {'\0'};
15526 
15527  //uint32_t datalen = (*frame)->datalen;
15528 
15530  if (!session->text_line_buffer) {
15531  switch_buffer_create_dynamic(&session->text_line_buffer, 512, 1024, 0);
15532  }
15533  switch_buffer_write(session->text_line_buffer, (*frame)->data, (*frame)->datalen);
15534 
15535 
15537  switch_buffer_write(session->text_line_buffer, eof, 1);
15539  //datalen = strlen((char *)smh->line_text_frame.data);
15540  } else {
15541  ok = 0;
15542  }
15543  }
15544 
15545 
15546  if (ok) {
15548  switch_channel_event_set_data(session->channel, event);
15549 
15550  switch_event_add_body(event, "%s", (char *)data);
15551 
15553  switch_event_t *q_event = NULL;
15554 
15556  switch_event_dup(&q_event, event);
15557  } else {
15558  q_event = event;
15559  event = NULL;
15560  }
15561 
15562  switch_core_session_queue_event(session, &q_event);
15563  }
15564 
15566  switch_event_fire(&event);
15567  }
15568  }
15569  if (session->text_line_buffer) {
15571  }
15572  }
15573  }
15574  switch_core_session_text_read_callback(session, *frame);
15575  }
15576 
15577  done:
15578 
15579  return status;
15580 }
15581 
15583 {
15584  int pos;
15585  switch_frame_t *frame = &t_engine->tf->text_write_frame;
15586  switch_byte_t *buf = (switch_byte_t *) frame->data;
15587  uint32_t plen = 0, loops = 0;
15588  uint16_t *u16;
15589 
15590  pos = t_engine->tf->red_pos + 1;
15591 
15592  if (pos == t_engine->tf->red_max) pos = 0;
15593 
15594  for (;;) {
15595  uint16_t ts = frame->timestamp - t_engine->tf->red_ts[pos];
15596  uint16_t len = t_engine->tf->red_buflen[pos];
15597 
15598  loops++;
15599 
15600  //1
15601  *buf = t_engine->t140_pt & 0x7f;
15602 
15603  if (pos != t_engine->tf->red_pos) {
15604  *buf |= 0x80;
15605 
15606  buf++; //2
15607  u16 = (uint16_t *) buf;
15608  *u16 = htons(ts << 2);
15609  buf++;//3
15610  *buf += (len & 0x300) >> 8;
15611  buf++;//4
15612  *buf = len & 0xff;
15613  }
15614 
15615  buf++;
15616 
15617  if (pos == t_engine->tf->red_pos) break;
15618 
15619 
15620  pos++;
15621 
15622  if (pos == t_engine->tf->red_max) pos = 0;
15623  }
15624 
15625 
15626  plen = ((loops - 1) * 4) + 1;
15627  pos = t_engine->tf->red_pos + 1;
15628 
15629  if (pos == t_engine->tf->red_max) pos = 0;
15630 
15631  for (;;) {
15632  if (t_engine->tf->red_buflen[pos]) {
15633  memcpy(buf, t_engine->tf->red_buf[pos], t_engine->tf->red_buflen[pos]);
15634  plen += t_engine->tf->red_buflen[pos];
15635  buf += t_engine->tf->red_buflen[pos];
15636  }
15637 
15638  if (pos == t_engine->tf->red_pos) break;
15639 
15640  pos++;
15641 
15642  if (pos == t_engine->tf->red_max) pos = 0;
15643  }
15644 
15645 
15646  buf = frame->data;
15647  *(buf+plen) = '\0';
15648 
15649  frame->datalen = plen;
15650  frame->payload = t_engine->red_pt;
15651 }
15652 
15654  int stream_id)
15655 {
15657  switch_media_handle_t *smh;
15659  switch_rtp_engine_t *t_engine;
15660  switch_io_write_text_frame_t write_text_frame = NULL;
15661  int is_msrp = switch_channel_test_flag(session->channel, CF_MSRP);
15662 
15663  switch_assert(session);
15664 
15665  if (!(smh = session->media_handle)) {
15666  return SWITCH_STATUS_FALSE;
15667  }
15668 
15669  if (switch_channel_down(session->channel)) {
15670  return SWITCH_STATUS_FALSE;
15671  }
15672 
15674  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG3, "Writing text to RECVONLY/INACTIVE session\n");
15675  return SWITCH_STATUS_SUCCESS;
15676  }
15677 
15678  //if (switch_channel_test_flag(session->channel, CF_TEXT_PAUSE_WRITE)) {
15679  // return SWITCH_STATUS_SUCCESS;
15680  //}
15681 
15683  /* return CNG, another thread is already writing */
15684  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s is already being written to for %s\n",
15686  goto done;
15687  }
15688 
15689  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
15690 
15691  if (!is_msrp && switch_channel_test_cap(session->channel, CC_RTP_RTT)) {
15692 
15693  if (!t_engine || !t_engine->tf) {
15694  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "text engine not available for processing\n");
15696  }
15697 
15698  if (frame) {
15699  char *str = (char *) frame->data;
15700  switch_buffer_write(t_engine->tf->write_buffer, str, frame->datalen);
15701  }
15702 
15703  if (!switch_buffer_inuse(t_engine->tf->write_buffer)) {
15704  t_engine->tf->write_empty++;
15706  }
15707 
15708  frame = &t_engine->tf->text_write_frame;
15709  switch_core_timer_sync(&t_engine->tf->timer);
15710  frame->timestamp = t_engine->tf->timer.samplecount;
15711 
15712  if (t_engine->red_pt) {
15713  t_engine->tf->red_ts[t_engine->tf->red_pos] = frame->timestamp;
15714 
15715  if (t_engine->tf->write_empty > TEXT_PERIOD_TIMEOUT / TEXT_TIMER_MS) {
15716  int pos;
15717 
15718  for(pos = 0; pos < t_engine->tf->red_max; pos++) {
15719  t_engine->tf->red_ts[pos] = 0;
15720  t_engine->tf->red_buf[pos][0] = '\0';
15721  t_engine->tf->red_buflen[pos] = 0;
15722  }
15723 
15724  frame->m = 1;
15725  t_engine->tf->write_empty = 0;
15726 
15727  } else {
15728  frame->m = 0;
15729  }
15730 
15731  t_engine->tf->red_buflen[t_engine->tf->red_pos] =
15732  switch_buffer_read(t_engine->tf->write_buffer, t_engine->tf->red_buf[t_engine->tf->red_pos], RED_PACKET_SIZE);
15733 
15734  *(t_engine->tf->red_buf[t_engine->tf->red_pos] + t_engine->tf->red_buflen[t_engine->tf->red_pos]) = '\0';
15735 
15736  build_red_packet(t_engine);
15737  } else {
15739  frame->payload = t_engine->t140_pt;
15740  }
15741  }
15742 
15743  if (!(write_text_frame = session->endpoint_interface->io_routines->write_text_frame)) {
15744  if (session->io_override) {
15745  write_text_frame = session->io_override->write_text_frame;
15746  }
15747  }
15748 
15749  if (write_text_frame) {
15750  if ((status = write_text_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
15751  for (ptr = session->event_hooks.text_write_frame; ptr; ptr = ptr->next) {
15752  if ((status = ptr->text_write_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
15753  break;
15754  }
15755  }
15756  }
15757  }
15758 
15759 
15760  if (!is_msrp && switch_channel_test_cap(session->channel, CC_RTP_RTT)) {
15761  if (!t_engine || (t_engine->red_pt && !t_engine->tf)) {
15762  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "text engine not available for processing\n");
15764  }
15765 
15766  if (t_engine->red_pt) {
15767  t_engine->tf->red_pos++;
15768  if (t_engine->tf->red_pos == t_engine->tf->red_max) {
15769  t_engine->tf->red_pos = 0;
15770  }
15771  }
15772  }
15773 
15774  done:
15775 
15776  if (smh->write_mutex[SWITCH_MEDIA_TYPE_TEXT]) {
15778  }
15779 
15780  return status;
15781 }
15782 
15784 {
15785  char *data = NULL;
15786  int ret = 0;
15787  va_list ap;
15788  switch_frame_t frame = { 0 };
15789  unsigned char CR[] = TEXT_UNICODE_LINEFEED;
15790 
15791  va_start(ap, fmt);
15792  ret = switch_vasprintf(&data, fmt, ap);
15793  va_end(ap);
15794 
15795  if (ret == -1) {
15796  abort();
15797  }
15798 
15799  frame.data = data;
15800  frame.datalen = strlen(data);
15801 
15802  switch_core_session_write_text_frame(session, &frame, 0, 0);
15803 
15804  frame.data = CR;
15805  frame.datalen = 3;
15806 
15807  switch_core_session_write_text_frame(session, &frame, 0, 0);
15808 
15809  switch_safe_free(data);
15810 
15811  return SWITCH_STATUS_SUCCESS;
15812 }
15813 
15814 
15816 {
15817  switch_frame_t frame = { 0 };
15818 
15819  if (!switch_channel_test_flag(session->channel, CF_HAS_TEXT)) {
15820  return SWITCH_STATUS_NOTIMPL;
15821  }
15822 
15823  frame.data = (char *) data;
15824  frame.datalen = strlen(data);
15825 
15826  switch_core_session_write_text_frame(session, &frame, 0, 0);
15827 
15828  return SWITCH_STATUS_SUCCESS;
15829 }
15830 
15832 {
15833  if (!session->media_handle) return NULL;
15834 
15835  return session->media_handle->msrp_session;
15836 }
15837 
15838 
15840  int stream_id)
15841 {
15842 
15844  switch_frame_t *enc_frame = NULL, *write_frame = frame;
15845  unsigned int flag = 0, need_codec = 0, perfect = 0, do_bugs = 0, do_write = 0, do_resample = 0, ptime_mismatch = 0, pass_cng = 0, resample = 0;
15846  int did_write_resample = 0;
15847 
15848  switch_assert(session != NULL);
15849  switch_assert(frame != NULL);
15850 
15851  if (!switch_channel_up_nosig(session->channel)) {
15852  return SWITCH_STATUS_FALSE;
15853  }
15854 
15857  } else {
15858  return SWITCH_STATUS_SUCCESS;
15859  }
15860 
15861  if (switch_test_flag(frame, SFF_CNG)) {
15863  pass_cng = 1;
15864  } else {
15865  return SWITCH_STATUS_SUCCESS;
15866  }
15867  }
15868 
15870  return SWITCH_STATUS_SUCCESS;
15871  }
15872 
15873  if (!(session->write_codec && switch_core_codec_ready(session->write_codec)) && !pass_cng) {
15874  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no write codec.\n", switch_channel_get_name(session->channel));
15876  return SWITCH_STATUS_FALSE;
15877  }
15878 
15879  if (switch_channel_test_flag(session->channel, CF_HOLD)) {
15880  return SWITCH_STATUS_SUCCESS;
15881  }
15882 
15883  if (switch_test_flag(frame, SFF_PROXY_PACKET) || pass_cng) {
15884  /* Fast PASS! */
15886  status = perform_write(session, frame, flag, stream_id);
15888  return status;
15889  }
15890 
15892 
15893  if (!(frame->codec && frame->codec->implementation)) {
15894  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has received a bad frame with no codec!\n",
15895  switch_channel_get_name(session->channel));
15898  return SWITCH_STATUS_FALSE;
15899  }
15900 
15901  switch_assert(frame->codec != NULL);
15902  switch_assert(frame->codec->implementation != NULL);
15903 
15904  if (!(switch_core_codec_ready(session->write_codec) && frame->codec) ||
15907  return SWITCH_STATUS_FALSE;
15908  }
15909 
15910  switch_mutex_lock(session->write_codec->mutex);
15911  switch_mutex_lock(frame->codec->mutex);
15912 
15913  if (!(switch_core_codec_ready(session->write_codec) && switch_core_codec_ready(frame->codec))) goto error;
15914 
15915  if (frame->codec && session->write_codec->implementation != frame->codec->implementation) {
15916  if (session->write_impl.codec_id == frame->codec->implementation->codec_id ||
15918  ptime_mismatch = TRUE;
15919 
15922  status = perform_write(session, frame, flags, stream_id);
15923  goto error;
15924  }
15925 
15928  }
15929  }
15930  need_codec = TRUE;
15931  }
15932 
15933  if (session->write_codec && !frame->codec) {
15934  need_codec = TRUE;
15935  }
15936 
15937  if (session->bugs && !need_codec && !switch_test_flag(session, SSF_MEDIA_BUG_TAP_ONLY)) {
15938  do_bugs = TRUE;
15939  need_codec = TRUE;
15940  }
15941 
15943  need_codec = TRUE;
15944  do_resample = TRUE;
15945  }
15946 
15947 
15948  if ((frame->flags & SFF_NOT_AUDIO)) {
15949  do_resample = 0;
15950  do_bugs = 0;
15951  need_codec = 0;
15952  }
15953 
15954  if (switch_test_flag(session, SSF_WRITE_TRANSCODE) && !need_codec && switch_core_codec_ready(session->write_codec)) {
15955  switch_core_session_t *other_session;
15957 
15958  if (uuid && (other_session = switch_core_session_locate(uuid))) {
15959  switch_set_flag(other_session, SSF_READ_CODEC_RESET);
15960  switch_set_flag(other_session, SSF_READ_CODEC_RESET);
15961  switch_set_flag(other_session, SSF_WRITE_CODEC_RESET);
15962  switch_core_session_rwunlock(other_session);
15963  }
15964 
15966  }
15967 
15968 
15969  if (switch_test_flag(session, SSF_WRITE_CODEC_RESET)) {
15972  }
15973 
15974  if (!need_codec) {
15975  do_write = TRUE;
15976  write_frame = frame;
15977  goto done;
15978  }
15979 
15980  if (!switch_test_flag(session, SSF_WARN_TRANSCODE)) {
15981  switch_core_session_message_t msg = { 0 };
15982 
15984  switch_core_session_receive_message(session, &msg);
15986  }
15987 
15988  if (frame->codec) {
15989  session->raw_write_frame.datalen = session->raw_write_frame.buflen;
15990  frame->codec->cur_frame = frame;
15991  session->write_codec->cur_frame = frame;
15992  status = switch_core_codec_decode(frame->codec,
15993  session->write_codec,
15994  frame->data,
15995  frame->datalen,
15997  session->raw_write_frame.data, &session->raw_write_frame.datalen, &session->raw_write_frame.rate, &frame->flags);
15998  frame->codec->cur_frame = NULL;
15999  session->write_codec->cur_frame = NULL;
16000  if (do_resample && status == SWITCH_STATUS_SUCCESS) {
16001  status = SWITCH_STATUS_RESAMPLE;
16002  }
16003 
16004  /* mux or demux to match */
16006  uint32_t rlen = session->raw_write_frame.datalen / 2 / frame->codec->implementation->number_of_channels;
16007  switch_mux_channels((int16_t *) session->raw_write_frame.data, rlen,
16009  session->raw_write_frame.datalen = rlen * 2 * session->write_impl.number_of_channels;
16010  }
16011 
16012  switch (status) {
16014  resample++;
16015  write_frame = &session->raw_write_frame;
16016  write_frame->rate = frame->codec->implementation->actual_samples_per_second;
16017  if (!session->write_resampler) {
16019  status = switch_resample_create(&session->write_resampler,
16023 
16024 
16026  if (status != SWITCH_STATUS_SUCCESS) {
16027  goto done;
16028  } else {
16029  switch_core_session_message_t msg = { 0 };
16030  msg.numeric_arg = 1;
16032  switch_core_session_receive_message(session, &msg);
16033 
16034  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Activating write resampler\n");
16035  }
16036  }
16037  break;
16038  case SWITCH_STATUS_SUCCESS:
16039  session->raw_write_frame.samples = session->raw_write_frame.datalen / sizeof(int16_t) / session->write_impl.number_of_channels;
16041  session->raw_write_frame.timestamp = frame->timestamp;
16042  session->raw_write_frame.rate = frame->rate;
16043  session->raw_write_frame.m = frame->m;
16044  session->raw_write_frame.ssrc = frame->ssrc;
16045  session->raw_write_frame.seq = frame->seq;
16046  session->raw_write_frame.payload = frame->payload;
16047  session->raw_write_frame.flags = 0;
16048  if (switch_test_flag(frame, SFF_PLC)) {
16049  session->raw_write_frame.flags |= SFF_PLC;
16050  }
16051 
16052  write_frame = &session->raw_write_frame;
16053  break;
16054  case SWITCH_STATUS_BREAK:
16055  status = SWITCH_STATUS_SUCCESS;
16056  goto error;
16057  case SWITCH_STATUS_NOOP:
16058  if (session->write_resampler) {
16061  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating write resampler\n");
16063 
16064  {
16065  switch_core_session_message_t msg = { 0 };
16066  msg.numeric_arg = 0;
16068  switch_core_session_receive_message(session, &msg);
16069  }
16070 
16071  }
16072  write_frame = frame;
16073  status = SWITCH_STATUS_SUCCESS;
16074  break;
16075  default:
16076 
16077  if (status == SWITCH_STATUS_NOT_INITALIZED) {
16078  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n");
16079  goto error;
16080  }
16081  if (ptime_mismatch && status != SWITCH_STATUS_GENERR) {
16082  perform_write(session, frame, flags, stream_id);
16083  status = SWITCH_STATUS_SUCCESS;
16084  goto error;
16085  }
16086 
16087  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s decoder error!\n",
16089  goto error;
16090  }
16091  }
16092 
16093 
16094 
16095  if (session->write_resampler) {
16096  short *data = write_frame->data;
16097 
16099  if (session->write_resampler) {
16100 
16102  write_frame->datalen / 2 / session->write_resampler->channels) > SWITCH_RECOMMENDED_BUFFER_SIZE) {
16103 
16104  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "%s not enough buffer space for required resample operation!\n",
16105  switch_channel_get_name(session->channel));
16108  goto error;
16109  }
16110 
16111 
16112  switch_resample_process(session->write_resampler, data, write_frame->datalen / 2 / session->write_resampler->channels);
16113 
16114  memcpy(data, session->write_resampler->to, session->write_resampler->to_len * 2 * session->write_resampler->channels);
16115 
16116  write_frame->samples = session->write_resampler->to_len;
16117  write_frame->channels = session->write_resampler->channels;
16118  write_frame->datalen = write_frame->samples * 2 * session->write_resampler->channels;
16119 
16120  write_frame->rate = session->write_resampler->to_rate;
16121 
16122  did_write_resample = 1;
16123  }
16125  }
16126 
16127 
16128 
16129  if (session->bugs) {
16130  switch_media_bug_t *bp;
16131  int prune = 0;
16132 
16134  for (bp = session->bugs; bp; bp = bp->next) {
16136 
16137  if (!bp->ready) {
16138  continue;
16139  }
16140 
16142  continue;
16143  }
16144 
16146  continue;
16147  }
16148 
16149  if (switch_test_flag(bp, SMBF_PRUNE)) {
16150  prune++;
16151  continue;
16152  }
16153 
16156  switch_buffer_write(bp->raw_write_buffer, write_frame->data, write_frame->datalen);
16158 
16159  if (bp->callback) {
16160  ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE);
16161  }
16162  }
16163 
16165  do_bugs = 0;
16166  if (bp->callback) {
16167  bp->write_replace_frame_in = write_frame;
16168  bp->write_replace_frame_out = write_frame;
16169  if ((ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE_REPLACE)) == SWITCH_TRUE) {
16170  write_frame = bp->write_replace_frame_out;
16171  }
16172  }
16173  }
16174 
16175  if (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) {
16176  ok = SWITCH_FALSE;
16177  }
16178 
16179 
16180  if (ok == SWITCH_FALSE) {
16182  prune++;
16183  }
16184  }
16186  if (prune) {
16187  switch_core_media_bug_prune(session);
16188  }
16189  }
16190 
16191  if (do_bugs) {
16192  do_write = TRUE;
16193  write_frame = frame;
16194  goto done;
16195  }
16196 
16197  if (session->write_codec) {
16198  if (!ptime_mismatch && write_frame->codec && write_frame->codec->implementation &&
16199  write_frame->codec->implementation->decoded_bytes_per_packet == session->write_impl.decoded_bytes_per_packet) {
16200  perfect = TRUE;
16201  }
16202 
16203 
16204 
16205  if (perfect) {
16206 
16207  if (write_frame->datalen < session->write_impl.decoded_bytes_per_packet) {
16208  memset(write_frame->data, 255, session->write_impl.decoded_bytes_per_packet - write_frame->datalen);
16209  write_frame->datalen = session->write_impl.decoded_bytes_per_packet;
16210  }
16211 
16212  enc_frame = write_frame;
16213  session->enc_write_frame.datalen = session->enc_write_frame.buflen;
16214  session->write_codec->cur_frame = frame;
16215  frame->codec->cur_frame = frame;
16218  status = switch_core_codec_encode(session->write_codec,
16219  frame->codec,
16220  enc_frame->data,
16221  enc_frame->datalen,
16223  session->enc_write_frame.data, &session->enc_write_frame.datalen, &session->enc_write_frame.rate, &flag);
16224 
16226 
16227  session->write_codec->cur_frame = NULL;
16228  frame->codec->cur_frame = NULL;
16229  switch (status) {
16231  resample++;
16232  /* switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fixme 2\n"); */
16233  case SWITCH_STATUS_SUCCESS:
16234  session->enc_write_frame.codec = session->write_codec;
16235  session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t) / session->write_impl.number_of_channels;
16238  session->enc_write_frame.timestamp = 0;
16239  } else {
16240  session->enc_write_frame.timestamp = frame->timestamp;
16241  }
16242  session->enc_write_frame.payload = session->write_impl.ianacode;
16243  session->enc_write_frame.m = frame->m;
16244  session->enc_write_frame.ssrc = frame->ssrc;
16245  session->enc_write_frame.seq = frame->seq;
16246  session->enc_write_frame.flags = 0;
16247  write_frame = &session->enc_write_frame;
16248  break;
16249  case SWITCH_STATUS_NOOP:
16250  enc_frame->codec = session->write_codec;
16251  enc_frame->samples = enc_frame->datalen / sizeof(int16_t) / session->write_impl.number_of_channels;
16252  enc_frame->channels = session->write_impl.number_of_channels;
16253  enc_frame->timestamp = frame->timestamp;
16254  enc_frame->m = frame->m;
16255  enc_frame->seq = frame->seq;
16256  enc_frame->ssrc = frame->ssrc;
16257  enc_frame->payload = enc_frame->codec->implementation->ianacode;
16258  write_frame = enc_frame;
16259  break;
16261  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n");
16262  write_frame = NULL;
16263  goto error;
16264  default:
16265  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s encoder error!\n",
16267  write_frame = NULL;
16268  goto error;
16269  }
16270  if (flag & SFF_CNG) {
16271  switch_set_flag(write_frame, SFF_CNG);
16272  }
16273 
16274  status = perform_write(session, write_frame, flags, stream_id);
16275  goto error;
16276  } else {
16277  if (!session->raw_write_buffer) {
16278  switch_size_t bytes_per_packet = session->write_impl.decoded_bytes_per_packet;
16280  "Engaging Write Buffer at %u bytes to accommodate %u->%u\n",
16281  (uint32_t) bytes_per_packet, write_frame->datalen, session->write_impl.decoded_bytes_per_packet);
16282  if ((status = switch_buffer_create_dynamic(&session->raw_write_buffer,
16283  bytes_per_packet * SWITCH_BUFFER_BLOCK_FRAMES,
16284  bytes_per_packet * SWITCH_BUFFER_START_FRAMES, 0)) != SWITCH_STATUS_SUCCESS) {
16285  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Write Buffer Failed!\n");
16286  goto error;
16287  }
16288 
16289  /* Need to retrain the recording data */
16291  }
16292 
16293  if (!(switch_buffer_write(session->raw_write_buffer, write_frame->data, write_frame->datalen))) {
16294  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Write Buffer %u bytes Failed!\n", write_frame->datalen);
16295  status = SWITCH_STATUS_MEMERR;
16296  goto error;
16297  }
16298 
16299  status = SWITCH_STATUS_SUCCESS;
16300 
16302  int rate;
16303 
16304  if (switch_channel_down(session->channel) || !session->raw_write_buffer) {
16305  goto error;
16306  }
16307  if ((session->raw_write_frame.datalen = (uint32_t)
16309  goto error;
16310  }
16311 
16312  enc_frame = &session->raw_write_frame;
16314  session->enc_write_frame.datalen = session->enc_write_frame.buflen;
16315  session->enc_write_frame.timestamp = 0;
16316 
16317 
16318  if (frame->codec && frame->codec->implementation && switch_core_codec_ready(frame->codec)) {
16320  } else {
16321  rate = session->write_impl.actual_samples_per_second;
16322  }
16323 
16324  session->write_codec->cur_frame = frame;
16325  frame->codec->cur_frame = frame;
16328  status = switch_core_codec_encode(session->write_codec,
16329  frame->codec,
16330  enc_frame->data,
16331  enc_frame->datalen,
16332  rate,
16333  session->enc_write_frame.data, &session->enc_write_frame.datalen, &session->enc_write_frame.rate, &flag);
16334 
16336 
16337  session->write_codec->cur_frame = NULL;
16338  frame->codec->cur_frame = NULL;
16339  switch (status) {
16341  resample++;
16342  session->enc_write_frame.codec = session->write_codec;
16343  session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t) / session->write_impl.number_of_channels;
16345  session->enc_write_frame.m = frame->m;
16346  session->enc_write_frame.ssrc = frame->ssrc;
16347  session->enc_write_frame.payload = session->write_impl.ianacode;
16348  write_frame = &session->enc_write_frame;
16349  if (!session->write_resampler) {
16351  if (!session->write_resampler) {
16352  status = switch_resample_create(&session->write_resampler,
16356  session->write_impl.number_of_channels);
16357  }
16359 
16360 
16361 
16362  if (status != SWITCH_STATUS_SUCCESS) {
16363  goto done;
16364  } else {
16365  switch_core_session_message_t msg = { 0 };
16366  msg.numeric_arg = 1;
16368  switch_core_session_receive_message(session, &msg);
16369 
16370 
16371  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Activating write resampler\n");
16372  }
16373  }
16374  break;
16375  case SWITCH_STATUS_SUCCESS:
16376  session->enc_write_frame.codec = session->write_codec;
16377  session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t) / session->write_impl.number_of_channels;
16379  session->enc_write_frame.m = frame->m;
16380  session->enc_write_frame.ssrc = frame->ssrc;
16381  session->enc_write_frame.payload = session->write_impl.ianacode;
16382  session->enc_write_frame.flags = 0;
16383  write_frame = &session->enc_write_frame;
16384  break;
16385  case SWITCH_STATUS_NOOP:
16386  if (session->write_resampler) {
16387  switch_core_session_message_t msg = { 0 };
16388  int ok = 0;
16389 
16391  if (session->write_resampler) {
16393  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating write resampler\n");
16394  ok = 1;
16395  }
16397 
16398  if (ok) {
16399  msg.numeric_arg = 0;
16401  switch_core_session_receive_message(session, &msg);
16402  }
16403 
16404  }
16405  enc_frame->codec = session->write_codec;
16406  enc_frame->samples = enc_frame->datalen / sizeof(int16_t) / session->read_impl.number_of_channels;
16407  enc_frame->channels = session->read_impl.number_of_channels;
16408  enc_frame->m = frame->m;
16409  enc_frame->ssrc = frame->ssrc;
16410  enc_frame->payload = enc_frame->codec->implementation->ianacode;
16411  write_frame = enc_frame;
16412  break;
16414  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n");
16415  write_frame = NULL;
16416  goto error;
16417  default:
16418  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s encoder error %d!\n",
16419  session->read_codec->codec_interface->interface_name, status);
16420  write_frame = NULL;
16421  goto error;
16422  }
16423 
16424  if (!did_write_resample && session->read_resampler) {
16425  short *data = write_frame->data;
16427  if (session->read_resampler) {
16428  switch_resample_process(session->read_resampler, data, write_frame->datalen / 2 / session->read_resampler->channels);
16429  memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2 * session->read_resampler->channels);
16430  write_frame->samples = session->read_resampler->to_len;
16431  write_frame->channels = session->read_resampler->channels;
16432  write_frame->datalen = session->read_resampler->to_len * 2 * session->read_resampler->channels;
16433  write_frame->rate = session->read_resampler->to_rate;
16434  }
16436 
16437  }
16438 
16439  if (flag & SFF_CNG) {
16440  switch_set_flag(write_frame, SFF_CNG);
16441  }
16442 
16443  if (ptime_mismatch || resample) {
16444  write_frame->timestamp = 0;
16445  }
16446 
16447  if ((status = perform_write(session, write_frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
16448  break;
16449  }
16450 
16451  }
16452 
16453  goto error;
16454  }
16455  }
16456 
16457 
16458 
16459 
16460 
16461  done:
16462 
16463  if (ptime_mismatch || resample) {
16464  write_frame->timestamp = 0;
16465  }
16466 
16467  if (do_write) {
16468  status = perform_write(session, write_frame, flags, stream_id);
16469  }
16470 
16471  error:
16472 
16474  switch_mutex_unlock(frame->codec->mutex);
16476 
16477  return status;
16478 }
16479 
16481 {
16482  if (!session) return NULL;
16483 
16484  return &session->media_handle->engines[media_type];
16485 }
16486 
16488 {
16489  switch_rtp_engine_t *engine = switch_core_media_get_engine(session, type);
16490 
16491  if (!engine) return NULL;
16492 
16493  return &engine->read_codec;
16494 }
16495 
16496 /* For Emacs:
16497  * Local Variables:
16498  * mode:c
16499  * indent-tabs-mode:t
16500  * tab-width:4
16501  * c-basic-offset:4
16502  * End:
16503  * For VIM:
16504  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
16505  */
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_mutex_t * codec_init_mutex
switch_status_t switch_core_codec_decode_video(switch_codec_t *codec, switch_frame_t *frame)
Decode video data using a codec handle.
switch_codec_t * switch_core_media_get_codec(switch_core_session_t *session, switch_media_type_t type)
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:595
switch_frame_t * write_replace_frame_out
char * generation
Definition: switch_rtp.h:104
switch_status_t switch_core_session_start_video_thread(switch_core_session_t *session)
switch_core_session_t * session
static void *SWITCH_THREAD_FUNC audio_write_thread(switch_thread_t *thread, void *obj)
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:311
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:413
#define switch_channel_hangup(channel, hangup_cause)
Hangup a channel flagging it&#39;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)
void switch_core_codec_unlock_full(switch_core_session_t *session)
Unlock codec read mutex and codec write mutex.
switch_size_t flaws
Definition: switch_types.h:723
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:83
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core&#39;s master pool.
Definition: switch_core.h:633
void switch_channel_set_flag_recursive(switch_channel_t *channel, switch_channel_flag_t flag)
switch_status_t switch_core_media_media_params(switch_core_session_t *session, const char *json)
switch_status_t switch_thread_rwlock_unlock(switch_thread_rwlock_t *rwlock)
Definition: switch_apr.c:286
#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&#39;s)
Definition: switch_rtp.c:4878
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 ...
#define TEXT_TIMER_SAMPLES
unsigned char remote_raw_key[SWITCH_RTP_MAX_CRYPTO_LEN]
switch_status_t switch_msrp_session_destroy(switch_msrp_session_t **ms)
Definition: switch_msrp.c:392
uint8_t allocated
switch_status_t switch_thread_cond_create(switch_thread_cond_t **cond, switch_memory_pool_t *pool)
Definition: switch_apr.c:373
switch_audio_resampler_t * write_resampler
static switch_bool_t stream_rejected(switch_media_handle_t *smh, sdp_media_e st)
switch_frame_t dummy_cng_frame
#define SWITCH_BUFFER_START_FRAMES
static switch_bool_t switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:519
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:2121
#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)
void switch_rtp_set_media_timeout(switch_rtp_t *rtp_session, uint32_t ms)
Definition: switch_rtp.c:2954
Image Descriptor.
Definition: switch_image.h:88
#define RED_PACKET_SIZE
void switch_core_session_clear_crypto(switch_core_session_t *session)
switch_thread_rwlock_t * bug_rwlock
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:700
switch_rtp_numbers_t inbound
Definition: switch_types.h:771
static void media_flow_get_mode(switch_media_flow_t smode, const char **mode_str, switch_media_flow_t *opp_mode)
#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:5150
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:183
switch_status_t switch_frame_buffer_free(switch_frame_buffer_t *fb, switch_frame_t **frameP)
Definition: switch_utils.c:217
#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_size_t switch_buffer_read(_In_ switch_buffer_t *buffer, _In_ void *data, _In_ switch_size_t datalen)
Read data from a switch_buffer_t up to the ammount of datalen if it is available. Remove read data fr...
switch_rtp_crypto_key_type_t
void switch_core_session_passthru(switch_core_session_t *session, switch_media_type_t type, switch_bool_t on)
switch_status_t switch_mutex_trylock(switch_mutex_t *lock)
Definition: switch_apr.c:318
switch_status_t switch_channel_set_variable_name_printf(switch_channel_t *channel, const char *val, const char *fmt,...)
const char *const const double number
Definition: switch_cJSON.h:254
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)
struct switch_io_event_hook_text_write_frame * next
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:796
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_core_media_set_media_bw_mult(switch_core_session_t *session, float mult)
void switch_img_free(switch_image_t **img)
Close an image descriptor.
switch_rtp_t * switch_core_session_get_rtp_session(switch_core_session_t *session, switch_media_type_t type)
const char * switch_msrp_listen_ip(void)
Definition: switch_msrp.c:289
switch_mutex_t * codec_write_mutex
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:3003
switch_status_t switch_buffer_create_dynamic(_Out_ switch_buffer_t **buffer, _In_ switch_size_t blocksize, _In_ switch_size_t start_len, _In_ switch_size_t max_len)
Allocate a new dynamic switch_buffer.
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)
char fmtp[SWITCH_MAX_CODECS][MAX_FMTP_LEN]
switch_status_t switch_rtp_ack_bitrate(switch_rtp_t *rtp_session, uint32_t bps)
Definition: switch_rtp.c:5048
switch_video_write_frame_hook_t text_write_frame
unsigned long rm_rate
static const char * remote_media_flow_varname(switch_media_type_t type)
uint8_t switch_core_session_get_rtp_pt(switch_core_session_t *session, switch_media_type_t type)
void switch_core_media_reset_t38(switch_core_session_t *session)
int switch_loadable_module_get_codecs_sorted(const switch_codec_implementation_t **array, char fmtp_array[SWITCH_MAX_CODECS][MAX_FMTP_LEN], int arraylen, char **prefs, int preflen)
Retrieve the list of loaded codecs into an array based on another array showing the sorted order...
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, const char *fmtp_in, switch_payload_t *ptP, switch_payload_t *recv_ptP, char **fmtpP)
switch_size_t switch_b64_decode(const char *in, char *out, switch_size_t olen)
switch_buffer_t * raw_write_buffer
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
switch_status_t switch_core_session_text_read_callback(switch_core_session_t *session, switch_frame_t *frame)
switch_status_t switch_frame_buffer_trypop(switch_frame_buffer_t *fb, void **ptr)
Definition: switch_utils.c:282
switch_status_t switch_rtp_text_factory_destroy(switch_rtp_text_factory_t **tfP)
void switch_core_media_kill_socket(switch_core_session_t *session, switch_media_type_t type)
#define switch_channel_stop_broadcast(_channel)
switch_rtp_engine_t * switch_core_media_get_engine(switch_core_session_t *session, int media_type)
static void check_stream_changes(switch_core_session_t *session, const char *r_sdp, switch_sdp_type_t sdp_type)
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.
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[SWITCH_RTP_FLAG_INVALID], char *timer_name, const char **err, switch_memory_pool_t *pool, switch_port_t bundle_internal_ports, switch_port_t bundle_external_port)
prepare a new RTP session handle and fully initilize it
Definition: switch_rtp.c:4626
switch_status_t switch_core_session_printf(switch_core_session_t *session, const char *fmt,...)
#define switch_channel_up(_channel)
switch_call_direction_t
Definition: switch_types.h:307
switch_status_t switch_core_media_choose_ports(switch_core_session_t *session, switch_bool_t audio, switch_bool_t video)
#define SWITCH_RECOMMENDED_BUFFER_SIZE
Definition: switch_types.h:594
switch_status_t switch_jb_peek_frame(switch_jb_t *jb, uint32_t ts, uint16_t seq, int peek, switch_frame_t *frame)
void switch_channel_event_set_data(_In_ switch_channel_t *channel, _In_ switch_event_t *event)
Add information about a given channel to an event object.
switch_bool_t switch_is_leading_number(const char *str)
unsigned long adv_rm_rate
static int get_channels(const char *name, int dft)
static const char * media_flow_varname(switch_media_type_t type)
switch_bool_t
Definition: switch_types.h:441
uint32_t timestamp
Definition: switch_frame.h:80
#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:733
const cJSON *const b
Definition: switch_cJSON.h:243
switch_status_t switch_core_codec_encode(switch_codec_t *codec, switch_codec_t *other_codec, void *decoded_data, uint32_t decoded_data_len, uint32_t decoded_rate, void *encoded_data, uint32_t *encoded_data_len, uint32_t *encoded_rate, unsigned int *flag)
Encode data using a codec handle.
switch_size_t largest_jb_size
Definition: switch_types.h:703
smh_flag_t
#define switch_split(_data, _delim, _array)
Definition: switch_utils.h:375
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)
switch_status_t switch_core_session_print(switch_core_session_t *session, const char *data)
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_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:95
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.
#define TEXT_UNICODE_LINEFEED
Definition: switch_types.h:244
switch_thread_id_t thread_write_lock
switch_core_session_t * session
switch_status_t switch_threadattr_stacksize_set(switch_threadattr_t *attr, switch_size_t stacksize)
Definition: switch_apr.c:683
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.
switch_status_t switch_core_media_bug_flush_all(_In_ switch_core_session_t *session)
Flush the read/write buffers for all media bugs on the session.
switch_bool_t switch_is_uint_in_range(const char *str, unsigned int from, unsigned int to)
Check if a 32 bit unsigned number is in a range.
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:642
#define SWITCH_LOCAL_VIDEO_IP_VARIABLE
Definition: switch_types.h:215
char * raddr
Definition: switch_rtp.h:102
static void *SWITCH_THREAD_FUNC text_helper_thread(switch_thread_t *thread, void *obj)
switch_codec_t * read_codec
Representation of an event.
Definition: switch_event.h:80
Node in which to store custom read frame channel callback hooks.
#define switch_channel_ready(_channel)
switch_status_t switch_event_add_body(switch_event_t *event, const char *fmt,...) PRINTF_FUNCTION(2
Add a body to an event.
switch_frame_t * cur_frame
switch_io_routines_t * io_routines
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]
const char *const const char *const const cJSON *const value
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:45
switch_rtp_crypto_direction_t
Definition: switch_rtp.h:62
const char * switch_core_media_crypto_type2str(switch_rtp_crypto_key_type_t type)
static int switch_channel_var_false(switch_channel_t *channel, const char *variable)
switch_core_media_avp_secure_t
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_buffer_t * write_buffer
switch_status_t switch_rtp_pause_jitter_buffer(switch_rtp_t *rtp_session, switch_bool_t pause)
Definition: switch_rtp.c:4738
switch_status_t switch_core_media_ext_address_lookup(switch_core_session_t *session, char **ip, switch_port_t *port, const char *sourceip)
switch_bool_t T38FaxTranscodingMMR
switch_core_media_vflag_t vflags
#define switch_channel_media_ready(_channel)
switch_rtp_crypto_key_param_method_type_t
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:3708
char str[MAX_FPSTRLEN]
Definition: switch_core.h:156
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:121
switch_status_t switch_rtp_set_payload_map(switch_rtp_t *rtp_session, payload_map_t **pmap)
Definition: switch_rtp.c:2652
switch_thread_cond_t * cond
switch_buffer_t * raw_write_buffer
switch_engine_function_t engine_function
switch_status_t switch_core_codec_decode(switch_codec_t *codec, switch_codec_t *other_codec, void *encoded_data, uint32_t encoded_data_len, uint32_t encoded_rate, void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag)
Decode data using a codec handle.
switch_status_t switch_core_session_set_text_read_callback(switch_core_session_t *session, switch_core_text_thread_callback_func_t func, void *user_data)
#define SWITCH_RESAMPLE_QUALITY
switch_video_write_frame_hook_t video_write_frame
const switch_codec_implementation_t * codecs[SWITCH_MAX_CODECS]
void switch_core_media_parse_media_flags(switch_core_session_t *session)
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_core_media_add_crypto(switch_core_session_t *session, switch_secure_settings_t *ssec, switch_rtp_crypto_direction_t direction)
switch_codec_implementation_t read_impl
void switch_rtp_intentional_bugs(switch_rtp_t *rtp_session, switch_rtp_bug_flag_t bugs)
Definition: switch_rtp.c:2665
#define SDPBUFLEN
switch_buffer_t * text_buffer
switch_status_t switch_core_codec_destroy(switch_codec_t *codec)
Destroy an initalized codec handle.
#define end_of(_s)
Definition: switch_utils.h:685
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:378
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.
const char * string_array_arg[MESSAGE_STRING_ARG_MAX]
Definition: switch_core.h:211
#define switch_calc_video_fps(fpsP, fps)
#define switch_core_session_get_name(_s)
Definition: switch_core.h:265
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:1055
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:699
#define switch_resample_calc_buffer_size(_to, _from, _srclen)
switch_bool_t T38FaxTranscodingJBIG
switch_frame_buffer_t * write_fb
switch_size_t media_bytes
Definition: switch_types.h:694
#define SWITCH_LOCAL_VIDEO_PORT_VARIABLE
Definition: switch_types.h:216
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:4701
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)
struct switch_crypto_key_material_s * local_key_material_next
switch_status_t switch_event_dup(switch_event_t **event, switch_event_t *todup)
Duplicate an event.
static int32_t switch_calc_bitrate(int w, int h, float quality, double fps)
icand_t cands[MAX_CAND][MAX_CAND_IDX_COUNT]
Definition: switch_rtp.h:114
switch_payload_t ianacodes[SWITCH_MAX_CODECS]
uint32_t ssrc
Definition: switch_frame.h:82
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:240
switch_size_t dtmf_packet_count
Definition: switch_types.h:700
void switch_resample_destroy(switch_audio_resampler_t **resampler)
Destroy an existing resampler handle.
static switch_thread_t * thread
Definition: switch_log.c:486
int switch_snprintf(_Out_z_cap_(len) char *buf, _In_ switch_size_t len, _In_z_ _Printf_format_string_ const char *format,...)
switch_size_t switch_buffer_write(_In_ switch_buffer_t *buffer, _In_bytecount_(datalen) const void *data, _In_ switch_size_t datalen)
Write data into a switch_buffer_t up to the length of datalen.
static switch_crypto_key_material_t * switch_core_media_crypto_append_key_material(switch_core_session_t *session, switch_crypto_key_material_t *tail, switch_rtp_crypto_key_param_method_type_t method, unsigned char raw_key[SWITCH_RTP_MAX_CRYPTO_LEN], int raw_key_len, const char *key_material, int key_material_len, uint64_t lifetime, unsigned int mki_id, unsigned int mki_size)
struct switch_runtime runtime
Definition: switch_core.c:86
switch_msrp_session_t * switch_core_media_get_msrp_session(switch_core_session_t *session)
switch_status_t switch_frame_buffer_dup(switch_frame_buffer_t *fb, switch_frame_t *orig, switch_frame_t **clone)
Definition: switch_utils.c:250
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_mutex_t * write_mutex[SWITCH_MEDIA_TYPE_TOTAL]
struct switch_crypto_key_material_s * next
switch_thread_id_t thread_id
switch_secure_settings_t ssec[CRYPTO_INVALID+1]
switch_media_flow_t switch_core_session_remote_media_flow(switch_core_session_t *session, switch_media_type_t type)
static void switch_core_session_parse_crypto_prefs(switch_core_session_t *session)
char * type
Definition: switch_core.h:155
#define switch_check_network_list_ip(_ip_str, _list_name)
Definition: switch_core.h:2530
payload_map_t * payload_map
switch_status_t switch_frame_buffer_destroy(switch_frame_buffer_t **fbP)
Definition: switch_utils.c:292
switch_status_t(* switch_io_write_text_frame_t)(switch_core_session_t *, switch_frame_t *, switch_io_flag_t, int)
switch_io_read_text_frame_t read_text_frame
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.
switch_bool_t switch_core_media_codec_get_cap(switch_core_session_t *session, switch_media_type_t mtype, switch_codec_flag_t flag)
static uint32_t switch_known_bitrate(switch_payload_t payload)
Definition: switch_utils.h:479
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)
switch_buffer_t * text_buffer
#define SWITCH_ADVERTISED_MEDIA_IP_VARIABLE
Definition: switch_types.h:210
switch_codec_t * codec
Definition: switch_frame.h:56
A message object designed to allow unlike technologies to exchange data.
Definition: switch_core.h:179
switch_rtp_bug_flag_t manual_video_rtp_bugs
uint8_t switch_byte_t
Definition: switch_types.h:256
switch_media_bug_callback_t callback
float source_fps
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.
Node in which to store custom write_frame channel callback hooks.
static void switch_core_session_parse_codec_settings(switch_core_session_t *session, switch_media_type_t type)
#define SWITCH_LOCAL_TEXT_PORT_VARIABLE
Definition: switch_types.h:218
void switch_rtp_set_max_missed_packets(switch_rtp_t *rtp_session, uint32_t max)
Definition: switch_rtp.c:2966
static int get_rtt_red_seq(int want_seq, void *data, switch_size_t datalen, int seq, switch_payload_t *new_payload, void *new_data, uint32_t *new_datalen)
switch_port_t switch_rtp_get_remote_port(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:3042
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:5638
switch_status_t switch_core_thread_set_cpu_affinity(int cpu)
Definition: switch_core.c:1763
struct core_video_globals_s core_video_globals_t
#define end_of_p(_s)
Definition: switch_utils.h:686
void switch_core_session_unset_write_codec(_In_ switch_core_session_t *session)
#define zstr(x)
Definition: switch_utils.h:314
switch_bool_t switch_core_media_check_udptl_mode(switch_core_session_t *session, switch_media_type_t type)
int cJSON_bool fmt
Definition: switch_cJSON.h:150
#define SWITCH_LOCAL_MEDIA_PORT_VARIABLE
Definition: switch_types.h:209
static int switch_safe_atoi(const char *nptr, int dft)
Turn a string into an integer (default if NULL)
Definition: switch_utils.h:851
void switch_core_media_set_local_sdp(switch_core_session_t *session, const char *sdp_str, switch_bool_t dup)
uint32_t switch_codec_flag_t
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:3058
switch_status_t switch_resolve_host(const char *host, char *buf, size_t buflen)
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:3031
unsigned int d_w
Definition: switch_image.h:99
int switch_core_media_crypto_keysalt_len(switch_rtp_crypto_key_type_t type)
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:4693
switch_status_t switch_core_codec_reset(switch_codec_t *codec)
switch_queue_t * write_video_queue
switch_io_event_hooks_t event_hooks
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
#define MAX_MATCHES
switch_rtp_crypto_key_type_t crypto_suite_order[CRYPTO_INVALID+1]
struct switch_io_event_hook_text_read_frame * next
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:250
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.
static const char * get_media_profile_name(switch_core_session_t *session, int secure, switch_core_media_avp_secure_t avp)
switch_codec_control_command_t
void switch_rtp_destroy(switch_rtp_t **rtp_session)
Destroy an RTP session.
Definition: switch_rtp.c:5189
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:206
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:724
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)
switch_codec_implementation_t write_impl
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:241
switch_status_t switch_rtp_deactivate_jitter_buffer(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:4764
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)
uint32_t switch_core_media_get_orig_bitrate(switch_core_session_t *session, switch_media_type_t type)
switch_jb_t * switch_rtp_get_jitter_buffer(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:4729
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:8195
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:81
#define SWITCH_MAX_CAND_ACL
switch_rw_t
Definition: switch_types.h:609
switch_codec_control_type_t
switch_mutex_t * mutex
static const char * switch_media_type2str(switch_media_type_t type)
Definition: cJSON.c:68
void(* switch_engine_function_t)(switch_core_session_t *session, void *user_data)
int64_t switch_time_t
Definition: switch_apr.h:188
const switch_codec_implementation_t * implementation
uint32_t buflen
Definition: switch_frame.h:70
#define SWITCH_REMOTE_MEDIA_IP_VARIABLE
Definition: switch_types.h:211
switch_time_t last_video_refresh_req
switch_port_t remote_rtp_ice_port
switch_rtcp_numbers_t rtcp
Definition: switch_types.h:773
switch_byte_t switch_byte_t * buf
switch_mutex_t * read_mutex[SWITCH_MEDIA_TYPE_TOTAL]
#define SWITCH_STUN_DEFAULT_PORT
Definition: switch_stun.h:41
if((uint32_t)(unpack->cur - unpack->buf) > unpack->buflen)
#define switch_yield(ms)
Wait a desired number of microseconds and yield the CPU.
Definition: switch_utils.h:998
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_write_frame_hook_t write_frame
switch_size_t raw_bytes
Definition: switch_types.h:693
switch_audio_resampler_t * read_resampler
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:68
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_codec_interface_t * codec_interface
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:62
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:4837
int switch_rtp_has_dtls(void)
Definition: switch_rtp.c:3700
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)
int switch_core_media_crypto_salt_len(switch_rtp_crypto_key_type_t type)
switch_byte_t * data
Definition: switch_buffer.c:43
switch_codec_t read_codec
switch_frame_flag_t flags
Definition: switch_frame.h:85
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
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)
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:4776
switch_rtp_bug_flag_t
Definition: switch_types.h:859
uint32_t red_ts[MAX_RED_FRAMES]
static switch_status_t ip_choose_family(switch_media_handle_t *smh, const char *ip)
#define switch_core_session_request_video_refresh(_s)
Definition: switch_core.h:2892
switch_status_t switch_core_media_read_lock_unlock(switch_core_session_t *session, switch_media_type_t type, switch_bool_t lock)
unsigned long local_key_material_n
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:684
uint32_t rate
Definition: switch_frame.h:74
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:4933
#define switch_channel_get_variable(_c, _v)
int index
Definition: switch_cJSON.h:160
#define SWITCH_THREAD_STACKSIZE
Definition: switch_types.h:588
#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:5353
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_status_t switch_core_session_write_text_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
char * remote_accept_wrapped_types
Definition: switch_msrp.h:97
switch_status_t switch_core_session_read_text_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
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
#define SWITCH_RTP_MAX_CRYPTO_LEN
switch_codec_t * write_codec
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:885
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:772
switch_rtp_t * switch_core_media_get_rtp_session(switch_core_session_t *session, switch_media_type_t type)
switch_core_media_dtmf_t dtmf_type
switch_status_t switch_img_fit(switch_image_t **srcP, int width, int height, switch_img_fit_t fit)
switch_frame_t * write_replace_frame_in
switch_core_video_thread_callback_func_t text_read_callback
float switch_core_media_get_media_bw_mult(switch_core_session_t *session)
char * con_addr
Definition: switch_rtp.h:99
void switch_core_codec_lock_full(switch_core_session_t *session)
Lock codec read mutex and codec write mutex using trylock in an infinite loop.
void switch_rtp_video_loss(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:5071
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:293
switch_status_t switch_rtp_set_remote_ssrc(switch_rtp_t *rtp_session, uint32_t ssrc)
Definition: switch_rtp.c:4469
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_rtp_text_factory_t * tf
switch_status_t switch_thread_join(switch_status_t *retval, switch_thread_t *thd)
Definition: switch_apr.c:1379
switch_status_t switch_rtp_text_factory_create(switch_rtp_text_factory_t **tfP, switch_memory_pool_t *pool)
switch_image_t * switch_img_read_png(const char *file_name, switch_img_fmt_t img_fmt)
switch_media_bug_t * bugs
#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:4461
void switch_buffer_zero(_In_ switch_buffer_t *buffer)
Remove all data from the buffer.
switch_payload_t dtmf_ianacodes[SWITCH_MAX_CODECS]
switch_mutex_t * resample_mutex
#define switch_channel_down_nosig(_channel)
char * cand_type
Definition: switch_rtp.h:101
switch_bool_t switch_core_media_has_resolveice(void)
switch_sdp_type_t sdp_type
#define MAX_RED_FRAMES
switch_mutex_t * text_mutex
uint32_t switch_core_max_audio_channels(uint32_t limit)
Definition: switch_core.c:2642
switch_io_routines_t * io_override
An abstraction of a data frame.
Definition: switch_frame.h:54
char * options
Definition: switch_rtp.h:120
int switch_core_media_check_engine_function(switch_core_session_t *session, switch_media_type_t type)
uintptr_t switch_size_t
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, uint8_t want_DTLSv1_2)
Definition: switch_rtp.c:3816
uint8_t ready
Definition: switch_rtp.h:105
uint8_t negotiated
int switch_vasprintf(_Out_opt_ char **buf, _In_z_ _Printf_format_string_ const char *format, _In_ va_list ap)
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:707
switch_time_t last_text_frame
#define CRYPTO_KEY_MATERIAL_LIFETIME
uint16_t switch_port_t
#define CRYPTO_KEY_MATERIAL_MKI
uint32_t switch_default_ptime(const char *name, uint32_t number)
Definition: switch_core.c:2022
switch_status_t switch_channel_wait_for_app_flag(switch_channel_t *channel, uint32_t app_flag, const char *key, switch_bool_t pres, uint32_t to)
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:8054
uint32_t ptime
static const char * switch_core_media_crypto_find_key_material_candidate_end(const char *p)
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:1693
switch_port_t local_sdp_port
pthread_t switch_thread_id_t
Definition: switch_apr.h:51
int switch_inet_pton(int af, const char *src, void *dst)
Definition: inet_pton.c:74
void switch_cond_next(void)
Definition: switch_time.c:658
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:1028
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)
static uint32_t parse_lifetime_mki(const char **p, const char *end)
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.
char * switch_copy_string(_Out_z_cap_(dst_size) char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size)
switch_status_t switch_core_session_start_text_thread(switch_core_session_t *session)
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:695
switch_status_t switch_core_session_queue_event(_In_ switch_core_session_t *session, _Inout_ switch_event_t **event)
Queue an event on a given session.
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:3128
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)
switch_memory_pool_t * pool
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
void switch_core_media_merge_sdp_codec_string(switch_core_session_t *session, const char *r_sdp, switch_sdp_type_t sdp_type, const char *codec_string)
unsigned long remote_key_material_n
switch_status_t switch_core_timer_destroy(switch_timer_t *timer)
Destroy an allocated timer.
#define DTLS_SRTP_FNAME
Definition: switch_core.h:148
static cJSON * parse_val(char *str)
int cand_idx[MAX_CAND_IDX_COUNT]
Definition: switch_rtp.h:115
switch_media_type_t type
#define switch_core_session_receive_message(_session, _message)
Definition: switch_core.h:1247
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:118
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.
cJSON * switch_core_media_gen_json_constraint(float min, float ideal, float max)
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:699
void switch_core_media_resume(switch_core_session_t *session)
#define SWITCH_RTCP_VIDEO_INTERVAL_MSEC
Definition: switch_types.h:242
#define TEXT_PERIOD_TIMEOUT
uint32_t switch_channel_test_cap(switch_channel_t *channel, switch_channel_cap_t cap)
switch_msrp_session_t * msrp_session
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:698
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:4709
dtls_type_t
Definition: switch_core.h:159
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)
void switch_core_media_set_smode(switch_core_session_t *session, switch_media_type_t type, switch_media_flow_t smode, switch_sdp_type_t sdp_type)
#define SWITCH_LOCAL_MEDIA_IP_VARIABLE
Definition: switch_types.h:208
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:993
char * transport
Definition: switch_rtp.h:97
struct fspr_thread_mutex_t switch_mutex_t
Definition: switch_apr.h:314
void switch_mux_channels(int16_t *data, switch_size_t samples, uint32_t orig_channels, uint32_t channels)
switch_status_t switch_core_timer_next(switch_timer_t *timer)
Wait for one cycle on an existing timer.
switch_bool_t switch_core_session_transcoding(switch_core_session_t *session_a, switch_core_session_t *session_b, switch_media_type_t type)
static int switch_channel_var_true(switch_channel_t *channel, const char *variable)
#define RA_PTR_LEN
switch_status_t switch_core_session_media_handle_ready(switch_core_session_t *session)
void switch_core_media_set_resolveice(switch_bool_t resolve_ice)
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:111
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:5434
const char * switch_channel_get_variable_partner(switch_channel_t *channel, const char *varname)
switch_core_video_thread_callback_func_t video_read_callback
char * ip
Definition: switch_msrp.c:60
switch_status_t switch_core_media_unlock_video_file(switch_core_session_t *session, switch_rw_t rw)
switch_frame_t * native_write_frame
dtls_fingerprint_t remote_dtls_fingerprint
switch_status_t switch_frame_buffer_push(switch_frame_buffer_t *fb, void *ptr)
Definition: switch_utils.c:267
switch_port_t switch_rtp_request_port(const char *ip)
Request a new port to be used for media.
Definition: switch_rtp.c:2629
#define SWITCH_R_SDP_VARIABLE
Definition: switch_types.h:197
switch_io_write_frame_t write_frame
void * packet
Definition: switch_frame.h:60
void switch_rtp_set_flag(switch_rtp_t *rtp_session, switch_rtp_flag_t flag)
Set an RTP Flag.
Definition: switch_rtp.c:5375
#define switch_channel_down(_channel)
switch_status_t switch_core_session_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
#define add_stat_double(_i, _s)
switch_status_t _switch_core_session_request_video_refresh(switch_core_session_t *session, int force, const char *file, const char *func, int line)
#define SWITCH_CRYPTO_MKI_MAX
char * switch_rtp_get_remote_host(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:3037
switch_memory_pool_t * pool
switch_image_t * img
Definition: switch_frame.h:88
char * local_accept_wrapped_types
Definition: switch_msrp.h:102
switch_status_t
Common return values.
switch_timer_t * switch_rtp_get_media_timer(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:4715
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:287
uint32_t switch_rtp_get_ssrc(switch_rtp_t *rtp_session)
Retrieve the SSRC from a given RTP session.
Definition: switch_rtp.c:9226
dtls_state_t
Definition: switch_core.h:166
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:8067
void switch_rtp_flush(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:5028
switch_status_t switch_ivr_unhold(switch_core_session_t *session)
Signal the session with a protocol specific unhold message.
Definition: switch_ivr.c:1603
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)
switch_status_t switch_frame_buffer_create(switch_frame_buffer_t **fbP, switch_size_t qlen)
Definition: switch_utils.c:303
void switch_media_handle_destroy(switch_core_session_t *session)
#define MAX_CAND
Definition: switch_rtp.h:110
static int dtls_ok(switch_core_session_t *session)
uint32_t len
Definition: switch_core.h:153
static switch_core_media_ice_type_t switch_determine_ice_type(switch_rtp_engine_t *engine, switch_core_session_t *session)
void switch_rtp_break(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:5083
void switch_rtp_reset_jb(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:2982
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.
#define switch_core_session_locate(uuid_str)
Locate a session based on it&#39;s uuid.
Definition: switch_core.h:932
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:804
#define SWITCH_NO_CRYPTO_TAG
void switch_core_media_set_stats(switch_core_session_t *session)
char * pwd
Definition: switch_rtp.h:119
static switch_call_direction_t switch_ice_direction(switch_rtp_engine_t *engine, switch_core_session_t *session)
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:199
void switch_rtp_get_random(void *buf, uint32_t len)
Definition: switch_rtp.c:2545
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:8094
#define MAX_CAND_IDX_COUNT
Definition: switch_rtp.h:111
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:5338
int component_id
Definition: switch_rtp.h:96
#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:384
char * cand_acl[SWITCH_MAX_CAND_ACL]
switch_size_t flush_packet_count
Definition: switch_types.h:702
void switch_core_media_start_engine_function(switch_core_session_t *session, switch_media_type_t type, switch_engine_function_t engine_function, void *user_data)
switch_byte_t * text_write_frame_data
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)
Node in which to store custom video_write_frame channel callback hooks.
#define SWITCH_DECLARE(type)
switch_port_t adv_sdp_port
switch_frame_t enc_write_frame
uint32_t samples
Definition: switch_frame.h:72
switch_status_t switch_core_session_clear_media_handle(switch_core_session_t *session)
struct fspr_thread_cond_t switch_thread_cond_t
Definition: switch_apr.h:463
static void restore_pmaps(switch_rtp_engine_t *engine)
static const char * CRYPTO_KEY_PARAM_METHOD[CRYPTO_KEY_PARAM_METHOD_INVALID]
#define switch_event_get_header(_e, _h)
Definition: switch_event.h:172
switch_status_t switch_core_media_prepare_codecs(switch_core_session_t *session, switch_bool_t force)
switch_mutex_t * file_read_mutex
#define SWITCH_REMOTE_VIDEO_PORT_VARIABLE
Definition: switch_types.h:214
#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:5364
uint32_t channels
Definition: switch_frame.h:76
switch_bool_t switch_core_file_has_video(switch_file_handle_t *fh, switch_bool_t CHECK_OPEN)
switch_status_t(* switch_core_video_thread_callback_func_t)(switch_core_session_t *session, switch_frame_t *frame, void *user_data)
#define MAX_REJ_STREAMS
switch_io_read_video_frame_t read_video_frame
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:8890
switch_size_t media_packet_count
Definition: switch_types.h:697
switch_rtp_stats_t * switch_rtp_get_stats(switch_rtp_t *rtp_session, switch_memory_pool_t *pool)
Definition: switch_rtp.c:9083
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:734
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:212
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:4786
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_text_thread_callback_func_t)(switch_core_session_t *session, switch_frame_t *frame, void *user_data)
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:4417
switch_payload_t cng_ianacodes[SWITCH_MAX_CODECS]
struct switch_io_event_hook_write_frame * next
int is_chosen[MAX_CAND_IDX_COUNT]
Definition: switch_rtp.h:117
switch_status_t switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name)
Definition: switch_rtp.c:4817
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)
time_t switch_epoch_time_now(time_t *t)
Get the current epoch time.
Definition: switch_time.c:322
switch_rtp_bug_flag_t rtp_bugs
switch_file_handle_t * video_write_fh
void switch_core_media_end_engine_function(switch_core_session_t *session, switch_media_type_t type)
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
switch_core_media_NDLB_t ndlb
char * key
Definition: switch_msrp.c:64
#define switch_core_session_alloc(_session, _memory)
Allocate memory from a session&#39;s pool.
Definition: switch_core.h:696
switch_media_flow_t
switch_status_t switch_queue_push(switch_queue_t *queue, void *data)
Definition: switch_apr.c:1253
switch_payload_t payload
Definition: switch_frame.h:78
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:8833
switch_channel_t * channel
void switch_rtp_release_port(const char *ip, switch_port_t port)
Definition: switch_rtp.c:2613
static void switch_core_media_set_rmode(switch_core_session_t *session, switch_media_type_t type, switch_media_flow_t rmode, switch_sdp_type_t sdp_type)
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:693
switch_file_handle_t * video_read_fh
#define MAX_FMTP_LEN
Definition: switch_types.h:245
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
#define SWITCH_VA_NONE
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:5429
switch_status_t switch_threadattr_create(switch_threadattr_t **new_attr, switch_memory_pool_t *pool)
Definition: switch_apr.c:665
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:698
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.
switch_rtp_bug_flag_t manual_text_rtp_bugs
switch_io_write_video_frame_t write_video_frame
void switch_core_media_sync_stats(switch_core_session_t *session)
#define TEXT_TIMER_MS
switch_msrp_session_t * switch_msrp_session_new(switch_memory_pool_t *pool, const char *call_id, switch_bool_t secure)
Definition: switch_msrp.c:378
switch_bool_t T38FaxFillBitRemoval
switch_port_t remote_sdp_port
switch_endpoint_interface_t * endpoint_interface
unsigned char raw_key[SWITCH_RTP_MAX_CRYPTO_LEN]
static int switch_false(const char *expr)
Evaluate the falsefullness of a string expression.
Definition: switch_utils.h:551
switch_status_t switch_core_file_write_video(_In_ switch_file_handle_t *fh, switch_frame_t *frame)
Write media to a file handle.
switch_mutex_t * mutex
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)
int count
Definition: switch_cJSON.h:204
static void add_audio_codec(sdp_rtpmap_t *map, const switch_codec_implementation_t *imp, int ptime, char *buf, switch_size_t buflen)
static switch_status_t perform_write(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
struct fspr_pool_t switch_memory_pool_t
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.
#define MIN(a, b)
uint32_t priority
Definition: switch_rtp.h:98
const char *const name
Definition: switch_cJSON.h:250
#define switch_channel_up_nosig(_channel)
#define switch_core_session_strdup(_session, _todup)
Copy a string using memory allocation from a session&#39;s pool.
Definition: switch_core.h:719
int chosen[MAX_CAND_IDX_COUNT]
Definition: switch_rtp.h:116
switch_thread_id_t switch_thread_self(void)
Definition: switch_apr.c:102
#define TRUE
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
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, int use_alias)
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:399
char * codec_order[SWITCH_MAX_CODECS]
int red_buflen[MAX_RED_FRAMES]
switch_port_t proxy_sdp_port
switch_bool_t switch_core_check_dtls_pem(const char *file)
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:8120
sdp_media_e rejected_streams[MAX_REJ_STREAMS]
switch_rtp_crypto_key_param_method_type_t method
void switch_core_session_write_blank_video(switch_core_session_t *session, uint32_t ms)
void switch_rtp_kill_socket(switch_rtp_t *rtp_session)
Kill the socket on an existing RTP session.
Definition: switch_rtp.c:5123
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:81
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
static void build_red_packet(switch_rtp_engine_t *t_engine)
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
switch_core_media_ice_type_t
int switch_channel_test_app_flag_key(const char *app, switch_channel_t *channel, uint32_t flags)
#define switch_assert(expr)
struct fspr_thread_t switch_thread_t
Definition: switch_apr.h:941
#define SWITCH_LOCAL_TEXT_IP_VARIABLE
Definition: switch_types.h:217
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:5059
switch_time_t switch_time_now(void)
Definition: switch_apr.c:325
switch_frame_t raw_write_frame
const char * sdp_o_line
static switch_status_t ice_out(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, switch_bool_t force)
Definition: switch_rtp.c:857
char * switch_strip_spaces(char *str, switch_bool_t dup)
switch_mutex_t * write_mutex
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
#define SWITCH_BUFFER_BLOCK_FRAMES
void switch_core_media_clear_ice(switch_core_session_t *session)
switch_size_t switch_buffer_inuse(_In_ switch_buffer_t *buffer)
Get the in use amount of a switch_buffer_t.
#define MAX_MISMATCH_FRAMES
switch_status_t switch_channel_api_on(switch_channel_t *channel, const char *variable_prefix)
void switch_buffer_destroy(switch_buffer_t **buffer)
Destroy the buffer.
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:1567
switch_status_t switch_rtp_req_bitrate(switch_rtp_t *rtp_session, uint32_t bps)
Definition: switch_rtp.c:5037
SWITCH_BEGIN_EXTERN_C char * switch_mprintf(const char *zFormat,...)
static void * get_rtt_payload(void *data, switch_size_t datalen, switch_payload_t *new_payload, uint32_t *new_datalen, int *red_level)
#define SWITCH_READ_ACCEPTABLE(status)
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:712
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:8175
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:5323
switch_status_t(* switch_io_read_text_frame_t)(switch_core_session_t *, switch_frame_t **, switch_io_flag_t, int)
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)
void * switch_buffer_get_head_pointer(switch_buffer_t *buffer)
Definition: switch_buffer.c:57
switch_status_t switch_rtp_sync_stats(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:5166
switch_core_media_params_t * mparams
switch_buffer_t * text_line_buffer
#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_status_t switch_rtp_add_crypto_key(switch_rtp_t *rtp_session, switch_rtp_crypto_direction_t direction, uint32_t index, switch_secure_settings_t *ssec)
Definition: switch_rtp.c:4062
#define switch_resample_create(_n, _fr, _tr, _ts, _q, _c)
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)
switch_media_type_t type
static void clear_ice(switch_core_session_t *session, switch_media_type_t type)
uint8_t switch_payload_t
uint32_t switch_resample_process(switch_audio_resampler_t *resampler, int16_t *src, uint32_t srclen)
Resample one float buffer into another using specifications of a given handle.
const char * local_ip
static void check_media_timeout_params(switch_core_session_t *session, switch_rtp_engine_t *engine)
switch_t38_options_t * switch_core_media_extract_t38_options(switch_core_session_t *session, const char *r_sdp)
static switch_bool_t ice_resolve_candidate
switch_status_t switch_msrp_start_client(switch_msrp_session_t *msrp_session)
Definition: switch_msrp.c:1488
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)
switch_io_write_text_frame_t write_text_frame
#define SWITCH_REMOTE_VIDEO_IP_VARIABLE
Definition: switch_types.h:213
switch_byte_t * red_buf[MAX_RED_FRAMES]
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:100
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:701
switch_port_t rport
Definition: switch_rtp.h:103
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:73
char * rm_encoding
switch_jb_t * switch_core_session_get_jb(switch_core_session_t *session, switch_media_type_t type)
switch_media_type_t
switch_rtp_crypto_key_type_t crypto_type
switch_status_t switch_core_session_start_audio_write_thread(switch_core_session_t *session)
struct switch_crypto_key_material_s * remote_key_material_next