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_TYPE_RESPONSE) {
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_TYPE_REQUEST && 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_TYPE_REQUEST ? "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_TYPE_REQUEST || !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_TYPE_REQUEST || !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_TYPE_REQUEST ? "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_TYPE_REQUEST) {
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 
3625 
3627 
3628  if (!(smh = session->media_handle)) {
3630  }
3631  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
3632 
3633  if (!a_engine->cur_payload_map->iananame) {
3634  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No audio codec available\n");
3636  }
3637 
3638  if (switch_core_codec_ready(&a_engine->read_codec)) {
3639  if (!force) {
3641  }
3642 
3643  if (strcasecmp(a_engine->read_impl.iananame, a_engine->cur_payload_map->iananame) ||
3644  (uint32_t) a_engine->read_impl.microseconds_per_packet / 1000 != a_engine->cur_payload_map->codec_ms ||
3645  a_engine->read_impl.samples_per_second != a_engine->cur_payload_map->rm_rate ) {
3646 
3647  switch_core_session_reset(session, 0, 0);
3648 
3650 
3652  "Changing Codec from %s@%dms@%dhz to %s@%dms@%luhz\n",
3653  a_engine->read_impl.iananame,
3654  a_engine->read_impl.microseconds_per_packet / 1000,
3656 
3657  a_engine->cur_payload_map->iananame,
3658  a_engine->cur_payload_map->codec_ms,
3659  a_engine->cur_payload_map->rm_rate);
3660 
3661  resetting = 1;
3666  } else {
3667  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Already using %s\n", a_engine->read_impl.iananame);
3669  }
3670  }
3671 
3672 
3674 
3676  a_engine->cur_payload_map->iananame,
3677  a_engine->cur_payload_map->modname,
3678  a_engine->cur_payload_map->rm_fmtp,
3679  a_engine->cur_payload_map->rm_rate,
3680  a_engine->cur_payload_map->codec_ms,
3681  a_engine->cur_payload_map->channels,
3682  a_engine->cur_payload_map->bitrate,
3685  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
3688  }
3689 
3690  a_engine->read_codec.session = session;
3691 
3692 
3694  a_engine->cur_payload_map->iananame,
3695  a_engine->cur_payload_map->modname,
3696  a_engine->cur_payload_map->rm_fmtp,
3697  a_engine->cur_payload_map->rm_rate,
3698  a_engine->cur_payload_map->codec_ms,
3699  a_engine->cur_payload_map->channels,
3700  a_engine->cur_payload_map->bitrate,
3703  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
3706  }
3707 
3708  a_engine->write_codec.session = session;
3709 
3710  if (switch_rtp_ready(a_engine->rtp_session)) {
3712  switch_rtp_reset_jb(a_engine->rtp_session);
3713  }
3714 
3715  switch_channel_set_variable(session->channel, "rtp_use_codec_name", a_engine->cur_payload_map->iananame);
3716  switch_channel_set_variable(session->channel, "rtp_use_codec_fmtp", a_engine->cur_payload_map->rm_fmtp);
3717  switch_channel_set_variable_printf(session->channel, "rtp_use_codec_rate", "%d", a_engine->cur_payload_map->rm_rate);
3718  switch_channel_set_variable_printf(session->channel, "rtp_use_codec_ptime", "%d", a_engine->cur_payload_map->codec_ms);
3719  switch_channel_set_variable_printf(session->channel, "rtp_use_codec_channels", "%d", a_engine->cur_payload_map->channels);
3720  switch_channel_set_variable_printf(session->channel, "rtp_last_audio_codec_string", "%s@%dh@%di@%dc",
3721  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);
3722 
3725 
3726  a_engine->read_impl = *a_engine->read_codec.implementation;
3727  a_engine->write_impl = *a_engine->write_codec.implementation;
3728 
3731 
3732  if (switch_rtp_ready(a_engine->rtp_session)) {
3734 
3740  }
3741  }
3742 
3743  a_engine->read_frame.rate = a_engine->cur_payload_map->rm_rate;
3744 
3745  if (!switch_core_codec_ready(&a_engine->read_codec)) {
3746  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't load codec?\n");
3748  }
3749 
3750  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",
3752  a_engine->cur_payload_map->codec_ms,
3754  a_engine->read_frame.codec = &a_engine->read_codec;
3755  a_engine->read_frame.channels = a_engine->read_impl.number_of_channels;
3756  a_engine->write_codec.agreed_pt = a_engine->cur_payload_map->pt;
3757  a_engine->read_codec.agreed_pt = a_engine->cur_payload_map->pt;
3758 
3759  if (force != 2) {
3761  switch_core_session_set_write_codec(session, &a_engine->write_codec);
3762  }
3763 
3764  a_engine->cur_payload_map->fmtp_out = switch_core_session_strdup(session, a_engine->write_codec.fmtp_out);
3765 
3766  if (switch_rtp_ready(a_engine->rtp_session)) {
3768  }
3769 
3770  end:
3771 
3772  if (resetting) {
3773  switch_channel_execute_on(session->channel, "execute_on_audio_change");
3774  }
3775 
3777 
3780 
3781  return status;
3782 }
3784 {
3785  switch_media_handle_t *smh;
3786  switch_rtp_engine_t *engine;
3787 
3788  switch_assert(session);
3789 
3790  if (!(smh = session->media_handle)) {
3791  return;
3792  }
3793 
3794  engine = &smh->engines[type];
3795 
3796  engine->ice_in.chosen[0] = 0;
3797  engine->ice_in.chosen[1] = 0;
3798  engine->ice_in.is_chosen[0] = 0;
3799  engine->ice_in.is_chosen[1] = 0;
3800  engine->ice_in.cand_idx[0] = 0;
3801  engine->ice_in.cand_idx[1] = 0;
3802  memset(&engine->ice_in, 0, sizeof(engine->ice_in));
3803  engine->remote_rtcp_port = 0;
3804 
3805  if (engine->rtp_session) {
3806  switch_rtp_reset(engine->rtp_session);
3807  }
3808 
3809 }
3810 
3811 //?
3813 {
3816 
3817 }
3818 
3820 {
3821  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
3822  switch_media_handle_t *smh;
3823 
3824  switch_assert(session);
3825 
3826  if (!(smh = session->media_handle)) {
3827  return;
3828  }
3829 
3830  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
3831  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
3832  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
3833 
3834  if (a_engine->rtp_session) {
3836  }
3837 
3838  if (v_engine->rtp_session) {
3840  }
3841 
3842  if (t_engine->rtp_session) {
3844  }
3845 }
3846 
3848 {
3849  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
3850  switch_media_handle_t *smh;
3851 
3852  switch_assert(session);
3853 
3854  if (!(smh = session->media_handle)) {
3855  return;
3856  }
3857 
3858  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
3859  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
3860  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
3861 
3862  if (a_engine->rtp_session) {
3864  }
3865 
3866  if (v_engine->rtp_session) {
3868  }
3869 
3870  if (t_engine->rtp_session) {
3872  }
3873 }
3874 
3875 
3876 //?
3878 {
3879  switch_media_handle_t *smh;
3880  switch_rtp_engine_t *engine;
3881 
3882  switch_assert(session);
3883 
3884  if (!(smh = session->media_handle)) {
3885  return SWITCH_STATUS_FALSE;
3886  }
3887 
3888  engine = &smh->engines[type];
3889 
3890  if (engine->cand_acl_count < SWITCH_MAX_CAND_ACL) {
3891  engine->cand_acl[engine->cand_acl_count++] = switch_core_session_strdup(session, acl_name);
3892  return SWITCH_STATUS_SUCCESS;
3893  }
3894 
3895  return SWITCH_STATUS_FALSE;
3896 }
3897 
3898 //?
3900 {
3901  switch_media_handle_t *smh;
3902 
3903  switch_assert(session);
3904 
3905  if (!(smh = session->media_handle)) {
3906  return;
3907  }
3908 
3910  int i;
3911  smh->video_count = 0;
3912  for (i = 0; i < smh->mparams->num_codecs; i++) {
3913 
3914  if (smh->codecs[i]->codec_type == SWITCH_CODEC_TYPE_VIDEO) {
3917  continue;
3918  }
3919  smh->video_count++;
3920  }
3921  }
3922  if (smh->video_count) {
3924  }
3925  }
3926 }
3927 
3928 //?
3930 {
3931  switch_rtp_engine_t *engine = &smh->engines[type];
3932 
3933  if (!engine->local_dtls_fingerprint.len) {
3934  if (engine->remote_dtls_fingerprint.type) {
3936  } else {
3937  engine->local_dtls_fingerprint.type = "sha-256";
3938  }
3940  }
3941 }
3942 
3943 //?
3944 static int dtls_ok(switch_core_session_t *session)
3945 {
3946  return switch_channel_test_flag(session->channel, CF_DTLS_OK);
3947 }
3948 
3949 #ifdef _MSC_VER
3950 /* remove this if the break is removed from the following for loop which causes unreachable code loop */
3951 /* for (i = 0; i < engine->cand_acl_count; i++) { */
3952 #pragma warning(push)
3953 #pragma warning(disable:4702)
3954 #endif
3955 
3956 //?
3958 {
3960  switch_media_handle_t *smh;
3961 
3962  switch_assert(session);
3963 
3964  if (!(smh = session->media_handle)) {
3966  }
3967 
3968  if (switch_channel_test_flag(session->channel, CF_3PCC)) {
3970  }
3971 
3972  if (switch_rtp_has_dtls() && dtls_ok(smh->session)) {
3974  } else {
3976  && switch_channel_test_flag(session->channel, CF_AVPF)) {
3978  }
3979  }
3980 
3981  return r;
3982 }
3983 
3986 
3987  if (switch_channel_var_true(session->channel, "ice_lite")) {
3988  ice_type |= ICE_CONTROLLED;
3989  ice_type |= ICE_LITE;
3990  } else {
3991  switch_call_direction_t direction = switch_ice_direction(engine, session);
3992  if (direction == SWITCH_CALL_DIRECTION_INBOUND) {
3993  ice_type |= ICE_CONTROLLED;
3994  }
3995  }
3996 
3997  return ice_type;
3998 }
3999 
4000 //?
4002 {
4004 
4005  if (zstr(ip)) {
4006  return status;
4007  }
4008 
4009  if (strchr(ip, ':')) {
4010  if (!zstr(smh->mparams->rtpip6)) {
4011  smh->mparams->rtpip = smh->mparams->rtpip6;
4012  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s choosing family v6\n",
4014  status = SWITCH_STATUS_SUCCESS;
4015  }
4016  } else {
4017  if (!zstr(smh->mparams->rtpip4)) {
4018  smh->mparams->rtpip = smh->mparams->rtpip4;
4019  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s choosing family v4\n",
4021  status = SWITCH_STATUS_SUCCESS;
4022  }
4023  }
4024 
4025  return status;
4026 }
4027 
4028 //?
4030 {
4032 
4033  if (zstr(ip)) {
4034  return r;
4035  }
4036 
4037  if (strchr(ip, ':')) {
4038  r = (switch_bool_t) !zstr(smh->mparams->rtpip6);
4039  } else {
4040  r = (switch_bool_t) !zstr(smh->mparams->rtpip4);
4041  }
4042 
4043  return r;
4044 }
4045 
4046 //?
4047 static switch_status_t check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_session_t *sdp, sdp_media_t *m)
4048 {
4049  switch_rtp_engine_t *engine = &smh->engines[type];
4050  sdp_attribute_t *attr = NULL, *attrs[2] = { 0 };
4051  int i = 0, got_rtcp_mux = 0;
4052  const char *val;
4053  int ice_seen = 0, cid = 0, ai = 0, attr_idx = 0, cand_seen = 0, relay_ok = 0;
4054  char con_addr[256];
4055  int ice_resolve = 0;
4056  ip_t ip;
4057 
4058  if (switch_true(switch_channel_get_variable_dup(smh->session->channel, "ignore_sdp_ice", SWITCH_FALSE, -1))) {
4059  return SWITCH_STATUS_BREAK;
4060  }
4061 
4062  //if (engine->ice_in.is_chosen[0] && engine->ice_in.is_chosen[1]) {
4063  //return SWITCH_STATUS_SUCCESS;
4064  //}
4065 
4066  engine->ice_in.chosen[0] = 0;
4067  engine->ice_in.chosen[1] = 0;
4068  engine->ice_in.is_chosen[0] = 0;
4069  engine->ice_in.is_chosen[1] = 0;
4070  engine->ice_in.cand_idx[0] = 0;
4071  engine->ice_in.cand_idx[1] = 0;
4072  engine->remote_ssrc = 0;
4073 
4074  if (m) {
4075  attrs[0] = m->m_attributes;
4076  attrs[1] = sdp->sdp_attributes;
4077  } else {
4078  attrs[0] = sdp->sdp_attributes;
4079  }
4080 
4081  ice_resolve = switch_core_media_has_resolveice();
4082 
4083  for (attr_idx = 0; attr_idx < 2 && !(ice_seen && cand_seen); attr_idx++) {
4084  for (attr = attrs[attr_idx]; attr; attr = attr->a_next) {
4085  char *data;
4086  char *fields[32] = {0};
4087  int argc = 0, j = 0;
4088 
4089  if (zstr(attr->a_name)) {
4090  continue;
4091  }
4092 
4093  if (!strcasecmp(attr->a_name, "ice-ufrag")) {
4094  if (engine->ice_in.ufrag && !strcmp(engine->ice_in.ufrag, attr->a_value)) {
4095  engine->new_ice = 0;
4096  } else {
4097  engine->ice_in.ufrag = switch_core_session_strdup(smh->session, attr->a_value);
4098  engine->new_ice = 1;
4099  }
4100  ice_seen++;
4101  } else if (!strcasecmp(attr->a_name, "ice-pwd")) {
4102  if (!engine->ice_in.pwd || strcmp(engine->ice_in.pwd, attr->a_value)) {
4103  engine->ice_in.pwd = switch_core_session_strdup(smh->session, attr->a_value);
4104  }
4105  } else if (!strcasecmp(attr->a_name, "ice-options")) {
4106  engine->ice_in.options = switch_core_session_strdup(smh->session, attr->a_value);
4107  } else if (!strcasecmp(attr->a_name, "setup")) {
4108  if (!strcasecmp(attr->a_value, "passive") ||
4109  (!strcasecmp(attr->a_value, "actpass") && !switch_channel_test_flag(smh->session->channel, CF_REINVITE))) {
4110  if (!engine->dtls_controller) {
4111  engine->new_dtls = 1;
4112  engine->new_ice = 1;
4113  }
4114  engine->dtls_controller = 1;
4115  } else if (!strcasecmp(attr->a_value, "active")) {
4116  if (engine->dtls_controller) {
4117  engine->new_dtls = 1;
4118  engine->new_ice = 1;
4119  }
4120  engine->dtls_controller = 0;
4121  }
4122  } else if (switch_rtp_has_dtls() && dtls_ok(smh->session) && !strcasecmp(attr->a_name, "fingerprint") && !zstr(attr->a_value)) {
4123  char *p;
4124 
4125  engine->remote_dtls_fingerprint.type = switch_core_session_strdup(smh->session, attr->a_value);
4126 
4127  if ((p = strchr(engine->remote_dtls_fingerprint.type, ' '))) {
4128  *p++ = '\0';
4129 
4131  !zstr(engine->remote_dtls_fingerprint.str) && !strcmp(engine->remote_dtls_fingerprint.str, p)) {
4132  engine->new_dtls = 0;
4133  } else {
4135  engine->new_dtls = 1;
4136  engine->new_ice = 1;
4137  }
4138  }
4139 
4140 
4141  //if (strcasecmp(engine->remote_dtls_fingerprint.type, "sha-256")) {
4142  // switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_WARNING, "Unsupported fingerprint type.\n");
4143  //engine->local_dtls_fingerprint.type = NULL;
4144  //engine->remote_dtls_fingerprint.type = NULL;
4145  //}
4146 
4147 
4148  generate_local_fingerprint(smh, type);
4150 
4151  } else if (!engine->remote_ssrc && !strcasecmp(attr->a_name, "ssrc") && attr->a_value) {
4152  engine->remote_ssrc = (uint32_t) atol(attr->a_value);
4153 
4154  if (engine->rtp_session && engine->remote_ssrc) {
4156  }
4157 
4158 
4159 #ifdef RTCP_MUX
4160  } else if (!strcasecmp(attr->a_name, "rtcp-mux")) {
4161  engine->rtcp_mux = SWITCH_TRUE;
4163  got_rtcp_mux++;
4164 
4165  if (!smh->mparams->rtcp_audio_interval_msec) {
4167  }
4168 #endif
4169  } else if (!strcasecmp(attr->a_name, "candidate")) {
4171 
4172  if (!engine->cand_acl_count) {
4173  engine->cand_acl[engine->cand_acl_count++] = "wan.auto";
4174  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_WARNING, "NO candidate ACL defined, Defaulting to wan.auto\n");
4175  }
4176 
4177 
4178  if (!switch_stristr(" udp ", attr->a_value)) {
4179  continue;
4180  }
4181 
4182  data = switch_core_session_strdup(smh->session, attr->a_value);
4183 
4184  argc = switch_split(data, ' ', fields);
4185 
4186  if (argc < 6 || !switch_is_uint_in_range(fields[1], 1, MAX_CAND_IDX_COUNT)) {
4188  continue;
4189  }
4190 
4191  cid = fields[1] ? atoi(fields[1]) - 1 : 0;
4192 
4193  if (engine->ice_in.cand_idx[cid] >= MAX_CAND - 1) {
4195  continue;
4196  }
4197 
4198  for (i = 0; i < argc; i++) {
4199  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG1, "CAND %d [%s]\n", i, fields[i]);
4200  }
4201 
4202  if (fields[4] && (switch_inet_pton(AF_INET, fields[4], &ip) || switch_inet_pton(AF_INET6, fields[4], &ip))) {
4203  switch_copy_string(con_addr, fields[4], sizeof(con_addr));
4204  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG1, "Is an IP address: %s\n", con_addr);
4205  } else if (fields[4] && ice_resolve) {
4206  if (switch_resolve_host(fields[4], con_addr, sizeof(con_addr)) == SWITCH_STATUS_SUCCESS) {
4207  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "Resolved %s to %s\n", fields[4], con_addr);
4208  } else {
4210  "Drop %s Candidate cid: %d proto: %s type: %s addr: %s:%s (cannot resolve)\n",
4211  type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
4212  cid+1, fields[2], fields[7], fields[4], fields[5]);
4213  continue;
4214  }
4215  } else {
4217  "Drop %s Candidate cid: %d proto: %s type: %s addr: %s:%s (not an IP address)\n",
4218  type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
4219  cid+1, fields[2], fields[7], fields[4] ? fields[4] : "(null)", fields[5]);
4220  continue;
4221  }
4222 
4223  if (!ip_possible(smh, con_addr)) {
4225  "Drop %s Candidate cid: %d proto: %s type: %s addr: %s:%s (no network path)\n",
4226  type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
4227  cid+1, fields[2], fields[7] ? fields[7] : "N/A", con_addr, fields[5]);
4228  continue;
4229  } else {
4231  "Save %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n",
4232  type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio",
4233  cid+1, fields[2], fields[7] ? fields[7] : "N/A", con_addr, fields[5]);
4234  }
4235 
4236 
4237  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].foundation = switch_core_session_strdup(smh->session, fields[0]);
4238  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].component_id = atoi(fields[1]);
4239  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].transport = switch_core_session_strdup(smh->session, fields[2]);
4240  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].priority = atol(fields[3]);
4241  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].con_addr = switch_core_session_strdup(smh->session, con_addr);
4242  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].con_port = (switch_port_t)atoi(fields[5]);
4243 
4244  j = 6;
4245 
4246  while(j < argc && j <= sizeof(fields)/sizeof(char*) && fields[j+1] && engine->ice_in.cand_idx[cid] < MAX_CAND - 1) {
4247  if (!strcasecmp(fields[j], "typ")) {
4248  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].cand_type = switch_core_session_strdup(smh->session, fields[j+1]);
4249  } else if (!strcasecmp(fields[j], "raddr")) {
4250  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].raddr = switch_core_session_strdup(smh->session, fields[j+1]);
4251  } else if (!strcasecmp(fields[j], "rport")) {
4252  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].rport = (switch_port_t)atoi(fields[j+1]);
4253  } else if (!strcasecmp(fields[j], "generation")) {
4254  engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].generation = switch_core_session_strdup(smh->session, fields[j+1]);
4255  }
4256 
4257  j += 2;
4258  }
4259 
4260  cand_seen++;
4261  engine->ice_in.cand_idx[cid]++;
4262  }
4263  }
4264  }
4265 
4266  if (!ice_seen) {
4267  return SWITCH_STATUS_SUCCESS;
4268  }
4269 
4270  relay_ok = 0;
4271 
4272  relay:
4273 
4274  for (cid = 0; cid < MAX_CAND_IDX_COUNT; cid++) {
4275  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Searching for %s candidate.\n", cid ? "rtcp" : "rtp");
4276 
4277  for (ai = 0; ai < engine->cand_acl_count; ai++) {
4278  for (i = 0; i < engine->ice_in.cand_idx[cid]; i++) {
4279  int is_relay = engine->ice_in.cands[i][cid].cand_type && !strcmp(engine->ice_in.cands[i][cid].cand_type, "relay");
4280 
4281  if (relay_ok != is_relay) continue;
4282 
4283  if (switch_check_network_list_ip(engine->ice_in.cands[i][cid].con_addr, engine->cand_acl[ai])) {
4285  "Choose %s candidate, index %d, %s:%d\n", cid ? "rtcp" : "rtp", i,
4286  engine->ice_in.cands[i][cid].con_addr, engine->ice_in.cands[i][cid].con_port);
4287 
4288  engine->ice_in.chosen[cid] = i;
4289  engine->ice_in.is_chosen[cid] = 1;
4290  engine->ice_in.cands[i][cid].ready++;
4291  ip_choose_family(smh, engine->ice_in.cands[i][cid].con_addr);
4292 
4293  if (cid == 0 && got_rtcp_mux && engine->ice_in.cand_idx[1] < MAX_CAND) {
4294 
4296  "Choose same candidate, index %d, for rtcp based on rtcp-mux attribute %s:%d\n", engine->ice_in.cand_idx[1],
4297  engine->ice_in.cands[i][cid].con_addr, engine->ice_in.cands[i][cid].con_port);
4298 
4299 
4300  engine->ice_in.cands[engine->ice_in.cand_idx[1]][1] = engine->ice_in.cands[i][0];
4301  engine->ice_in.chosen[1] = engine->ice_in.cand_idx[1];
4302  engine->ice_in.is_chosen[1] = 1;
4303  engine->ice_in.cand_idx[1]++;
4304 
4305  goto done_choosing;
4306  }
4307 
4308  goto next_cid;
4309  }
4310  }
4311  }
4312 
4313  next_cid:
4314 
4315  continue;
4316  }
4317 
4318  done_choosing:
4319 
4321  engine->ice_in.is_chosen[0] = 1;
4322  }
4323 
4324  if (!engine->ice_in.is_chosen[0]) {
4325  if (!relay_ok) {
4326  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Look for Relay Candidates as last resort\n");
4327  relay_ok = 1;
4328  goto relay;
4329  }
4330 
4331  /* PUNT */
4332  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s no suitable candidates found.\n",
4334  return SWITCH_STATUS_FALSE;
4335  }
4336 
4337  for (i = 0; i < 2; i++) {
4338  if (engine->ice_in.cands[engine->ice_in.chosen[i]][i].ready) {
4339  if (zstr(engine->ice_in.ufrag) || zstr(engine->ice_in.pwd)) {
4340  engine->ice_in.cands[engine->ice_in.chosen[i]][i].ready = 0;
4341  }
4342  }
4343  }
4344 
4345 
4346  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) {
4347  char tmp[80] = "";
4348  const char *media_varname = NULL, *port_varname = NULL;
4349 
4350  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);
4352  "setting remote %s ice addr to index %d %s:%d based on candidate\n", type2str(type), engine->ice_in.chosen[0],
4353  engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port);
4354  engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++;
4355 
4356  engine->remote_rtp_ice_port = (switch_port_t) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port;
4357  engine->remote_rtp_ice_addr = switch_core_session_strdup(smh->session, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
4358 
4359  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);
4360  engine->cur_payload_map->remote_sdp_port = (switch_port_t) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port;
4361 
4362  if (!smh->mparams->remote_ip) {
4364  }
4365 
4366  if (engine->type == SWITCH_MEDIA_TYPE_VIDEO) {
4367  media_varname = "remote_video_ip";
4368  port_varname = "remote_video_port";
4369  } else if (engine->type == SWITCH_MEDIA_TYPE_AUDIO) {
4370  media_varname = "remote_audio_ip";
4371  port_varname = "remote_audio_port";
4372  } else if (engine->type == SWITCH_MEDIA_TYPE_TEXT) {
4373  media_varname = "remote_text_ip";
4374  port_varname = "remote_text_port";
4375  }
4376 
4377  switch_snprintf(tmp, sizeof(tmp), "%d", engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port);
4378  switch_channel_set_variable(smh->session->channel, media_varname, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr);
4379  switch_channel_set_variable(smh->session->channel, port_varname, tmp);
4380  }
4381 
4382  if (engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port) {
4383  const char *media_varname = NULL, *port_varname = NULL;
4384  char tmp[35] = "";
4385 
4387  "Setting remote rtcp %s addr to %s:%d based on candidate\n", type2str(type),
4388  engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port);
4389  engine->remote_rtcp_ice_port = engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port;
4390  engine->remote_rtcp_ice_addr = switch_core_session_strdup(smh->session, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr);
4391 
4392  engine->remote_rtcp_port = engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port;
4393 
4394 
4395  if (engine->type == SWITCH_MEDIA_TYPE_VIDEO) {
4396  media_varname = "remote_video_rtcp_ip";
4397  port_varname = "remote_video_rtcp_port";
4398  } else if (engine->type == SWITCH_MEDIA_TYPE_AUDIO) {
4399  media_varname = "remote_audio_rtcp_ip";
4400  port_varname = "remote_audio_rtcp_port";
4401  } else if (engine->type == SWITCH_MEDIA_TYPE_TEXT) {
4402  media_varname = "remote_text_rtcp_ip";
4403  port_varname = "remote_text_rtcp_port";
4404  }
4405 
4406  switch_snprintf(tmp, sizeof(tmp), "%d", engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port);
4407  switch_channel_set_variable(smh->session->channel, media_varname, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr);
4408  switch_channel_set_variable(smh->session->channel, port_varname, tmp);
4409 
4410  }
4411 
4412 
4413  if (m && !got_rtcp_mux) {
4414  engine->rtcp_mux = -1;
4415  }
4416 
4417  if (engine->new_ice) {
4418  if (switch_rtp_ready(engine->rtp_session) && engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready) {
4419  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "RE-Activating %s ICE\n", type2str(type));
4420 
4422  engine->ice_in.ufrag,
4423  engine->ice_out.ufrag,
4424  engine->ice_out.pwd,
4425  engine->ice_in.pwd,
4426  IPR_RTP,
4427 #ifdef GOOGLE_ICE
4429  NULL
4430 #else
4431  switch_determine_ice_type(engine, smh->session),
4432  &engine->ice_in
4433 #endif
4434  );
4435 
4436 
4437  engine->new_ice = 0;
4438  }
4439 
4440 
4441  if (engine->rtp_session && ((val = switch_channel_get_variable(smh->session->channel,
4442  type == SWITCH_MEDIA_TYPE_VIDEO ?
4443  "rtcp_video_interval_msec" : "rtcp_audio_interval_msec"))
4444  || (val = type == SWITCH_MEDIA_TYPE_VIDEO ?
4446 
4447  switch_port_t remote_rtcp_port = engine->remote_rtcp_port;
4448 
4449  if (remote_rtcp_port) {
4450  if (!strcasecmp(val, "passthru")) {
4451  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "Activating %s RTCP PASSTHRU PORT %d\n",
4452  type2str(type), remote_rtcp_port);
4453  switch_rtp_activate_rtcp(engine->rtp_session, -1, remote_rtcp_port, engine->rtcp_mux > 0);
4454  } else {
4455  int interval = atoi(val);
4456  if (interval < 100 || interval > 500000) {
4458  "Invalid rtcp interval spec [%d] must be between 100 and 500000\n", interval);
4459  interval = 5000;
4460  }
4461 
4462  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "Activating %s RTCP PORT %d\n", type2str(type), remote_rtcp_port);
4463  switch_rtp_activate_rtcp(engine->rtp_session, interval, remote_rtcp_port, engine->rtcp_mux > 0);
4464  }
4465  }
4466  }
4467 
4468  if (engine->rtp_session && engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready) {
4469  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)
4470  && engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port == engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port) {
4471  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "Skipping %s RTCP ICE (Same as RTP)\n", type2str(type));
4472  } else {
4473  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_INFO, "Activating %s RTCP ICE\n", type2str(type));
4474 
4476  engine->ice_in.ufrag,
4477  engine->ice_out.ufrag,
4478  engine->ice_out.pwd,
4479  engine->ice_in.pwd,
4480  IPR_RTCP,
4481 #ifdef GOOGLE_ICE
4483  NULL
4484 #else
4485  switch_determine_ice_type(engine, smh->session),
4486  &engine->ice_in
4487 #endif
4488  );
4489  }
4490 
4491  }
4492 
4493  }
4494 
4495  return ice_seen ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_BREAK;
4496 }
4497 #ifdef _MSC_VER
4498 #pragma warning(pop)
4499 #endif
4500 
4502 {
4503  switch_media_handle_t *smh;
4504 
4505  switch_assert(session);
4506 
4507  if (!(smh = session->media_handle)) {
4508  return;
4509  }
4510 
4516 
4517 }
4518 
4519 #define MAX_MATCHES 30
4520 struct matches {
4522  sdp_rtpmap_t *map;
4523  int rate;
4525 };
4526 
4527 #ifndef MIN
4528 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
4529 #endif
4530 
4531 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)
4532 {
4533  int j = 0, f = 0, g;
4534  struct matches mtmp[MAX_MATCHES] = { { 0 } };
4535 
4536  m_idx = MIN(m_idx, MAX_MATCHES);
4537 
4538  for(j = 0; j < m_idx; j++) {
4539  *&mtmp[j] = *&matches[j];
4540  }
4541 
4542  for (g = 0; g < smh->mparams->num_codecs && g < total_codecs && f < MAX_MATCHES; g++) {
4543  const switch_codec_implementation_t *imp = codec_array[g];
4544 
4545  for(j = 0; j < m_idx; j++) {
4546  if (mtmp[j].imp && mtmp[j].imp == imp) {
4547  *&matches[f++] = *&mtmp[j];
4548  mtmp[j].imp = NULL;
4549  }
4550  }
4551  }
4552 }
4553 
4554 static void clear_pmaps(switch_rtp_engine_t *engine)
4555 {
4556  payload_map_t *pmap;
4557 
4558  for (pmap = engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) {
4559  pmap->negotiated = 0;
4560  pmap->current = 0;
4561  }
4562 }
4563 
4565 {
4566  payload_map_t *pmap;
4567  int top = 0;
4568 
4569  for (pmap = engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) {
4570  pmap->negotiated = 1;
4571  if (!top++) pmap->current = 1;
4572  }
4573 }
4574 
4575 static const char *media_flow_varname(switch_media_type_t type)
4576 {
4577  const char *varname = "invalid";
4578 
4579  switch(type) {
4581  varname = "audio_media_flow";
4582  break;
4584  varname = "video_media_flow";
4585  break;
4587  varname = "text_media_flow";
4588  break;
4589  }
4590 
4591  return varname;
4592 }
4593 
4595 {
4596  const char *varname = "invalid";
4597 
4598  switch(type) {
4600  varname = "remote_audio_media_flow";
4601  break;
4603  varname = "remote_video_media_flow";
4604  break;
4606  varname = "remote_text_media_flow";
4607  break;
4608  }
4609 
4610  return varname;
4611 }
4612 
4613 static void media_flow_get_mode(switch_media_flow_t smode, const char **mode_str, switch_media_flow_t *opp_mode)
4614 {
4615  const char *smode_str = "";
4616  switch_media_flow_t opp_smode = smode;
4617 
4618  switch(smode) {
4620  opp_smode = SWITCH_MEDIA_FLOW_RECVONLY;
4621  smode_str = "sendonly";
4622  break;
4624  opp_smode = SWITCH_MEDIA_FLOW_SENDONLY;
4625  smode_str = "recvonly";
4626  break;
4628  smode_str = "inactive";
4629  break;
4631  smode_str = "disabled";
4632  break;
4634  smode_str = "sendrecv";
4635  break;
4636  }
4637 
4638  *mode_str = smode_str;
4639  *opp_mode = opp_smode;
4640 
4641 }
4642 
4643 static void check_stream_changes(switch_core_session_t *session, const char *r_sdp, switch_sdp_type_t sdp_type)
4644 {
4645  switch_core_session_t *other_session = NULL;
4648 
4649  status = switch_core_session_get_partner(session, &other_session);
4650  (void)status;
4651 
4654 
4655  if (other_session) {
4658 
4659  if (sdp_type == SDP_TYPE_REQUEST && r_sdp) {
4660  const char *filter_codec_string = switch_channel_get_variable(session->channel, "filter_codec_string");
4661 
4662  switch_channel_set_variable(session->channel, "codec_string", NULL);
4663  switch_core_media_merge_sdp_codec_string(session, r_sdp, sdp_type, filter_codec_string);
4664  }
4665 
4666  if (switch_channel_test_flag(session->channel, CF_SECURE)) {
4667  other_session->media_handle->crypto_mode = session->media_handle->crypto_mode;
4669  }
4670 
4671  msg = switch_core_session_alloc(other_session, sizeof(*msg));
4673  msg->string_arg = switch_core_session_sprintf(other_session, "=%s", switch_channel_get_variable(session->channel, "ep_codec_string"));
4674  msg->from = __FILE__;
4675  switch_core_session_queue_message(other_session, msg);
4676  }
4677  }
4678 
4679  if (other_session) {
4682 
4684  uint8_t proceed = 1;
4685  const char *sdp_in, *other_ep;
4686  uint8_t res = 0;
4687 
4688  if ((other_ep = switch_channel_get_variable(session->channel, "ep_codec_string"))) {
4689  switch_channel_set_variable(other_session->channel, "codec_string", other_ep);
4690  }
4691 
4692  sdp_in = switch_channel_get_variable(other_session->channel, SWITCH_R_SDP_VARIABLE);
4693  res = switch_core_media_negotiate_sdp(other_session, sdp_in, &proceed, SDP_TYPE_REQUEST);
4694  (void)res;
4695  switch_core_media_activate_rtp(other_session);
4696  msg = switch_core_session_alloc(other_session, sizeof(*msg));
4698  msg->from = __FILE__;
4699 
4701  switch_core_session_queue_message(other_session, msg);
4702  }
4703  }
4704 
4705  switch_core_session_rwunlock(other_session);
4706  }
4707 }
4708 
4710 {
4711  switch_media_handle_t *smh;
4712  switch_rtp_engine_t *engine;
4713  const char *varname = NULL, *smode_str = NULL;
4714  switch_media_flow_t old_smode, opp_smode = smode;
4715  switch_core_session_t *other_session;
4716  int pass_codecs = 0;
4717 
4718  if (!(smh = session->media_handle)) {
4719  return;
4720  }
4721 
4722  engine = &smh->engines[type];
4723 
4724  varname = media_flow_varname(type);
4725 
4726  media_flow_get_mode(smode, &smode_str, &opp_smode);
4727 
4728  old_smode = engine->smode;
4729 
4730  engine->smode = smode;
4731 
4732  switch_channel_set_variable(session->channel, varname, smode_str);
4733 
4734  if (switch_channel_var_true(session->channel, "rtp_pass_codecs_on_reinvite") || engine->pass_codecs) {
4735  pass_codecs = 1;
4736  }
4737 
4738  engine->pass_codecs = 0;
4739 
4740  if (switch_channel_var_true(session->channel, "rtp_pass_codecs_on_stream_change")) {
4741  if (sdp_type == SDP_TYPE_REQUEST && switch_channel_test_flag(session->channel, CF_REINVITE) &&
4742  switch_channel_media_up(session->channel) && (pass_codecs || old_smode != smode)) {
4743 
4744  if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
4745  switch_core_media_set_smode(other_session, type, opp_smode, SDP_TYPE_REQUEST);
4747  switch_core_session_rwunlock(other_session);
4748  }
4749  }
4750  }
4751 }
4752 
4754 {
4755  switch_media_handle_t *smh;
4756  switch_rtp_engine_t *engine;
4757  const char *varname = NULL, *rmode_str = NULL;
4758  switch_media_flow_t opp_rmode = rmode;
4759  switch_core_session_t *other_session = NULL;
4760 
4761  if (!(smh = session->media_handle)) {
4762  return;
4763  }
4764 
4765  engine = &smh->engines[type];
4766 
4767  varname = remote_media_flow_varname(type);
4768  media_flow_get_mode(rmode, &rmode_str, &opp_rmode);
4769 
4770  if (engine->rmode != rmode) {
4771  engine->pass_codecs = 1;
4772  }
4773 
4774  engine->rmode = rmode;
4775 
4776  if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
4777 
4779  switch_core_media_set_smode(other_session, type, rmode, sdp_type);
4780  }
4781 
4782  switch_core_session_rwunlock(other_session);
4783  }
4784 
4785  switch_channel_set_variable(session->channel, varname, rmode_str);
4786 }
4787 
4788 //?
4789 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)
4790 {
4791  uint8_t match = 0, vmatch = 0, almost_vmatch = 0, tmatch = 0, fmatch = 0;
4792  switch_payload_t best_te = 0, cng_pt = 0;
4793  unsigned long best_te_rate = 8000, cng_rate = 8000;
4794  sdp_media_t *m;
4795  sdp_attribute_t *attr;
4796  int ptime = 0, dptime = 0, maxptime = 0, dmaxptime = 0;
4797  int sendonly = 0, recvonly = 0, inactive = 0;
4798  int greedy = 0, x = 0, skip = 0;
4800  const char *val;
4801  const char *crypto = NULL;
4802  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;
4803  int scrooge = 0;
4804  sdp_parser_t *parser = NULL;
4805  sdp_session_t *sdp;
4806  const switch_codec_implementation_t **codec_array;
4807  int total_codecs;
4808  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
4809  switch_media_handle_t *smh;
4810  uint32_t near_rate = 0;
4811  const switch_codec_implementation_t *mimp = NULL, *near_match = NULL;
4812  sdp_rtpmap_t *mmap = NULL, *near_map = NULL;
4813  struct matches matches[MAX_MATCHES] = { { 0 } };
4814  struct matches near_matches[MAX_MATCHES] = { { 0 } };
4815  int codec_ms = 0;
4816  uint32_t remote_codec_rate = 0, fmtp_remote_codec_rate = 0;
4817  const char *tmp;
4818  int m_idx = 0, skip_rtcp = 0, skip_video_rtcp = 0, got_rtcp_mux = 0, got_video_rtcp_mux = 0;
4819  int nm_idx = 0;
4820  int vmatch_pt = 1, consider_video_fmtp = 1;
4821  int rtcp_auto_audio = 0, rtcp_auto_video = 0;
4822  int got_audio_rtcp = 0, got_video_rtcp = 0;
4823  switch_port_t audio_port = 0, video_port = 0;
4824 
4825  switch_assert(session);
4826 
4827  if (!r_sdp) {
4828  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Tried to negotiate a blank SDP?\n");
4829  return 0;
4830  }
4831 
4832  if (!(smh = session->media_handle)) {
4833  return 0;
4834  }
4835 
4836  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
4837  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
4838  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
4839 
4840  smh->mparams->num_codecs = 0;
4841  smh->num_negotiated_codecs = 0;
4843  codec_array = smh->codecs;
4844  total_codecs = smh->mparams->num_codecs;
4845 
4846  if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
4847  return 0;
4848  }
4849 
4850  if (!(sdp = sdp_session(parser))) {
4851  sdp_parser_free(parser);
4852  return 0;
4853  }
4854 
4857 
4858  if (dtls_ok(session) && (tmp = switch_channel_get_variable(smh->session->channel, "webrtc_enable_dtls")) && switch_false(tmp)) {
4861  }
4862 
4863  if (switch_true(switch_channel_get_variable_dup(session->channel, "rtp_assume_rtcp", SWITCH_FALSE, -1))) {
4864  rtcp_auto_video = 1;
4865  rtcp_auto_audio = 1;
4866  }
4867 
4868  v_engine->new_dtls = 1;
4869  v_engine->new_ice = 1;
4870  a_engine->new_dtls = 1;
4871  a_engine->new_ice = 1;
4872  a_engine->reject_avp = 0;
4873 
4875 
4877 
4878  clear_pmaps(a_engine);
4879  clear_pmaps(v_engine);
4880 
4881  if (proceed) *proceed = 1;
4882 
4885 
4886  if ((val = switch_channel_get_variable(channel, "rtp_codec_negotiation"))) {
4887  if (!strcasecmp(val, "generous")) {
4888  greedy = 0;
4889  scrooge = 0;
4890  } else if (!strcasecmp(val, "greedy")) {
4891  greedy = 1;
4892  scrooge = 0;
4893  } else if (!strcasecmp(val, "scrooge")) {
4894  scrooge = 1;
4895  greedy = 1;
4896  } else {
4897  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "rtp_codec_negotiation ignored invalid value : '%s' \n", val );
4898  }
4899  }
4900 
4901  if ((smh->origin = switch_core_session_strdup(session, (char *) sdp->sdp_origin->o_username))) {
4902 
4904 
4905  if (strstr(smh->origin, "CiscoSystemsSIP-GW-UserAgent")) {
4907  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Activate Buggy RFC2833 Mode!\n");
4908  }
4909  }
4910 
4912  if (strstr(smh->origin, "Sonus_UAC")) {
4915  "Hello,\nI see you have a Sonus!\n"
4916  "FYI, Sonus cannot follow the RFC on the proper way to send DTMF.\n"
4917  "Sadly, my creator had to spend several hours figuring this out so I thought you'd like to know that!\n"
4918  "Don't worry, DTMF will work but you may want to ask them to fix it......\n");
4919  }
4920  }
4921  }
4922 
4923  /* check dtmf_type variable */
4925 
4926  if ((val = switch_channel_get_variable(session->channel, "rtp_liberal_dtmf")) && switch_true(val)) {
4928  }
4929 
4930  if (switch_stristr("T38FaxFillBitRemoval:", r_sdp) || switch_stristr("T38FaxTranscodingMMR:", r_sdp) ||
4931  switch_stristr("T38FaxTranscodingJBIG:", r_sdp)) {
4932  switch_channel_set_variable(session->channel, "t38_broken_boolean", "true");
4933  }
4934 
4935  check_ice(smh, SWITCH_MEDIA_TYPE_AUDIO, sdp, NULL);
4936  check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, NULL);
4937  check_ice(smh, SWITCH_MEDIA_TYPE_TEXT, sdp, NULL);
4938 
4939  if ((sdp->sdp_connection && sdp->sdp_connection->c_address && !strcmp(sdp->sdp_connection->c_address, "0.0.0.0"))) {
4940  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");
4941  sendonly = 2; /* global sendonly always wins */
4942  }
4943 
4944  memset(smh->rejected_streams, 0, sizeof(smh->rejected_streams));
4945  smh->rej_idx = 0;
4946 
4949 
4950  for (m = sdp->sdp_media; m; m = m->m_next) {
4951  sdp_connection_t *connection;
4952  switch_core_session_t *other_session;
4953 
4954  if (!m->m_port && smh->rej_idx < MAX_REJ_STREAMS - 1) {
4955 
4956  switch(m->m_type) {
4957  case sdp_media_audio:
4958  smh->rejected_streams[smh->rej_idx++] = sdp_media_audio;
4959  continue;
4960  case sdp_media_video:
4961  smh->rejected_streams[smh->rej_idx++] = sdp_media_video;
4962  continue;
4963  case sdp_media_image:
4964  smh->rejected_streams[smh->rej_idx++] = sdp_media_image;
4965  continue;
4966  default:
4967  break;
4968  }
4969  }
4970 
4971  if (m->m_type == sdp_media_audio) {
4972  saw_audio = 1;
4973  }
4974 
4975  if (m->m_type == sdp_media_video) {
4976  saw_video = 1;
4977  }
4978 
4979  ptime = dptime;
4980  maxptime = dmaxptime;
4981 
4982  if (m->m_proto == sdp_proto_extended_srtp || m->m_proto == sdp_proto_extended_rtp) {
4983  got_webrtc++;
4984  switch_core_session_set_ice(session);
4985  }
4986 
4987  if (m->m_proto_name && !strcasecmp(m->m_proto_name, "UDP/TLS/RTP/SAVPF")) {
4989  }
4990 
4991  if (m->m_proto_name && !strcasecmp(m->m_proto_name, "UDP/RTP/AVPF")) {
4993  }
4994 
4995  if (m->m_proto == sdp_proto_srtp || m->m_proto == sdp_proto_extended_srtp) {
4996  if (m->m_type == sdp_media_audio) {
4997  got_savp++;
4998  }
4999  } else if (m->m_proto == sdp_proto_rtp) {
5000  if (m->m_type == sdp_media_audio) {
5001  got_avp++;
5002  }
5003  } else if (m->m_proto == sdp_proto_udptl) {
5004  got_udptl++;
5005  } else if (m->m_proto == sdp_proto_msrp || m->m_proto == sdp_proto_msrps){
5006  got_msrp++;
5007  }
5008 
5009  if (got_msrp && m->m_type == sdp_media_message) {
5010  if (!smh->msrp_session) {
5011  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);
5012  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "MSRP session created %s\n", smh->msrp_session->call_id);
5013  }
5014 
5016 
5017  for (attr = m->m_attributes; attr; attr = attr->a_next) {
5018  // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[%s]=[%s]\n", attr->a_name, attr->a_value);
5019  if (!strcasecmp(attr->a_name, "path") && attr->a_value) {
5020  smh->msrp_session->remote_path = switch_core_session_strdup(session, attr->a_value);
5021  switch_channel_set_variable(session->channel, "sip_msrp_remote_path", attr->a_value);
5022  } else if (!strcasecmp(attr->a_name, "accept-types") && attr->a_value) {
5023  smh->msrp_session->remote_accept_types = switch_core_session_strdup(session, attr->a_value);
5024  switch_channel_set_variable(session->channel, "sip_msrp_remote_accept_types", attr->a_value);
5025  } else if (!strcasecmp(attr->a_name, "accept-wrapped-types") && attr->a_value) {
5027  switch_channel_set_variable(session->channel, "sip_msrp_remote_accept_wrapped_types", attr->a_value);
5028  } else if (!strcasecmp(attr->a_name, "setup") && attr->a_value) {
5029  smh->msrp_session->remote_setup = switch_core_session_strdup(session, attr->a_value);
5030  switch_channel_set_variable(session->channel, "sip_msrp_remote_setup", attr->a_value);
5031  if (!strcmp(attr->a_value, "passive")) {
5032  smh->msrp_session->active = 1;
5033  }
5034  } else if (!strcasecmp(attr->a_name, "file-selector") && attr->a_value) {
5035  char *tmp = switch_mprintf("%s", attr->a_value);
5036  char *argv[4] = { 0 };
5037  int argc;
5038  int i;
5039 
5040  smh->msrp_session->remote_file_selector = switch_core_session_strdup(session, attr->a_value);
5041  switch_channel_set_variable(session->channel, "sip_msrp_remote_file_selector", attr->a_value);
5042 
5043  argc = switch_separate_string(tmp, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
5044 
5045  for(i = 0; i<argc; i++) {
5047  if (zstr(argv[i])) {
5049  continue;
5050  }
5051  if (!strncasecmp(argv[i], "name:", 5)) {
5052  char *p = argv[i] + 5;
5053  int len = strlen(p);
5054 
5055  if (*p == '"') {
5056  *(p + len - 1) = '\0';
5057  p++;
5058  }
5059  switch_channel_set_variable(session->channel, "sip_msrp_file_name", p);
5060  } else if (!strncasecmp(argv[i], "type:", 5)) {
5061  switch_channel_set_variable(session->channel, "sip_msrp_file_type", argv[i] + 5);
5062  }
5063  if (!strncasecmp(argv[i], "size:", 5)) {
5064  switch_channel_set_variable(session->channel, "sip_msrp_file_size", argv[i] + 5);
5065  }
5066  if (!strncasecmp(argv[i], "hash:", 5)) {
5067  switch_channel_set_variable(session->channel, "sip_msrp_file_hash", argv[i] + 5);
5068  }
5069  }
5070  switch_safe_free(tmp);
5071  } else if (!strcasecmp(attr->a_name, "file-transfer-id") && attr->a_value) {
5072  switch_channel_set_variable(session->channel, "sip_msrp_file_transfer_id", attr->a_value);
5073  } else if (!strcasecmp(attr->a_name, "file-disposition") && attr->a_value) {
5074  switch_channel_set_variable(session->channel, "sip_msrp_file_disposition", attr->a_value);
5075  } else if (!strcasecmp(attr->a_name, "file-date") && attr->a_value) {
5076  switch_channel_set_variable(session->channel, "sip_msrp_file_date", attr->a_value);
5077  } else if (!strcasecmp(attr->a_name, "file-icon") && attr->a_value) {
5078  switch_channel_set_variable(session->channel, "sip_msrp_file_icon", attr->a_value);
5079  } else if (!strcasecmp(attr->a_name, "file-range") && attr->a_value) {
5080  switch_channel_set_variable(session->channel, "sip_msrp_file_range", attr->a_value);
5081  }
5082  }
5083 
5087 
5092 
5093  if (m->m_proto == sdp_proto_msrps) {
5095  }
5096 
5097  if (smh->msrp_session->active) {
5098  const char *ip = switch_msrp_listen_ip();
5099 
5101  "msrp%s://%s:%d/%s;tcp",
5102  smh->msrp_session->secure ? "s" : "",
5103  ip, smh->msrp_session->local_port, smh->msrp_session->call_id);
5104 
5106  }
5107 
5109  tmatch = 1;
5110  }
5111 
5112  if (got_udptl && m->m_type == sdp_media_image) {
5114 
5115  if (m->m_port) {
5117  fmatch = 1;
5118  goto done;
5119  }
5120 
5121  if (switch_channel_var_true(channel, "refuse_t38") || !switch_channel_var_true(channel, "fax_enable_t38")) {
5123  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 REFUSE on %s\n",
5124  switch_channel_get_name(channel),
5125  sdp_type == SDP_TYPE_RESPONSE ? "response" : "request");
5126 
5127  restore_pmaps(a_engine);
5128  fmatch = 0;
5129 
5130  goto t38_done;
5131  } else {
5132  switch_t38_options_t *t38_options = switch_core_media_process_udptl(session, sdp, m);
5133  const char *var = switch_channel_get_variable(channel, "t38_passthru");
5135 
5136  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 ACCEPT on %s\n",
5137  switch_channel_get_name(channel),
5138  sdp_type == SDP_TYPE_RESPONSE ? "response" : "request");
5139 
5140  if (switch_channel_test_app_flag_key("T38", session->channel, CF_APP_T38)) {
5141  if (proceed) *proceed = 0;
5142  }
5143 
5144  if (var) {
5145  if (!(pass = switch_true(var))) {
5146  if (!strcasecmp(var, "once")) {
5147  pass = 2;
5148  }
5149  }
5150  }
5151 
5152  if ((pass == 2 && switch_channel_test_flag(smh->session->channel, CF_T38_PASSTHRU))
5153  || !switch_channel_test_flag(session->channel, CF_REINVITE) ||
5154 
5157  !switch_rtp_ready(a_engine->rtp_session)) {
5158  pass = 0;
5159  }
5160 
5161  if (pass && switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
5162  switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
5164  char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
5165  switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
5166  char tmp[32] = "";
5167 
5168 
5169  if (!switch_channel_test_flag(other_channel, CF_ANSWERED)) {
5171  SWITCH_LOG_WARNING, "%s Error Passing T.38 to unanswered channel %s\n",
5172  switch_channel_get_name(session->channel), switch_channel_get_name(other_channel));
5173  switch_core_session_rwunlock(other_session);
5174 
5175  match = 0;
5176  fmatch = 0;
5177  goto done;
5178  }
5179 
5182 
5183  if (switch_true(switch_channel_get_variable(session->channel, "t38_broken_boolean")) &&
5184  switch_true(switch_channel_get_variable(session->channel, "t38_pass_broken_boolean"))) {
5185  switch_channel_set_variable(other_channel, "t38_broken_boolean", "true");
5186  }
5187 
5188  a_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, t38_options->remote_ip);
5189  a_engine->cur_payload_map->remote_sdp_port = t38_options->remote_port;
5190 
5191  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) {
5192  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n",
5193  switch_channel_get_name(session->channel));
5194  } else {
5195  const char *err = NULL;
5196 
5197  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n",
5198  switch_channel_get_name(session->channel),
5199  remote_host, remote_port, a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
5200 
5201  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
5204 
5207  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
5209  }
5210 
5212  switch_channel_execute_on(session->channel, "execute_on_audio_change");
5213  }
5214 
5215 
5216 
5217  switch_core_media_copy_t38_options(t38_options, other_session);
5218 
5221 
5222  msg = switch_core_session_alloc(other_session, sizeof(*msg));
5224  msg->from = __FILE__;
5225  msg->string_arg = switch_core_session_strdup(other_session, r_sdp);
5226  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing T38 req to other leg.\n%s\n", r_sdp);
5227  switch_core_session_queue_message(other_session, msg);
5228  switch_core_session_rwunlock(other_session);
5229  }
5230  }
5231 
5232  /* do nothing here, mod_fax will trigger a response (if it's listening =/) */
5234  fmatch = 1;
5235  } else {
5236 
5237  fmatch = 0;
5238  }
5239 
5240  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 %s POSSIBLE on %s\n",
5241  switch_channel_get_name(channel),
5242  fmatch ? "IS" : "IS NOT",
5243  sdp_type == SDP_TYPE_RESPONSE ? "response" : "request");
5244 
5245 
5246  goto done;
5247  }
5248  } else if (m->m_type == sdp_media_audio && m->m_port && got_audio && got_savp) {
5249  a_engine->reject_avp = 1;
5250  } else if (m->m_type == sdp_media_audio && m->m_port && !got_audio) {
5251  sdp_rtpmap_t *map;
5252  int ice = 0;
5253 
5254  nm_idx = 0;
5255  m_idx = 0;
5256  memset(matches, 0, sizeof(matches[0]) * MAX_MATCHES);
5257  memset(near_matches, 0, sizeof(near_matches[0]) * MAX_MATCHES);
5258 
5259  audio_port = m->m_port;
5260 
5261  if (!sendonly && (m->m_mode == sdp_sendonly || m->m_mode == sdp_inactive)) {
5262  sendonly = 1;
5263  if (m->m_mode == sdp_inactive) {
5264  inactive = 1;
5265  }
5266  }
5267 
5268  if (!sendonly && m->m_connections && m->m_connections->c_address && !strcmp(m->m_connections->c_address, "0.0.0.0")) {
5269  sendonly = 1;
5270  }
5271 
5272 
5274 
5275  if (sdp_type == SDP_TYPE_REQUEST) {
5276  switch(a_engine->rmode) {
5279  break;
5282  break;
5285  break;
5286  default:
5288  break;
5289  }
5290  }
5291 
5292  for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) {
5293  if (zstr(attr->a_name)) {
5294  continue;
5295  }
5296 
5297 
5298  if (!strncasecmp(attr->a_name, "ice", 3)) {
5299  ice++;
5300  } else if (sendonly < 2 && !strcasecmp(attr->a_name, "sendonly")) {
5301  sendonly = 1;
5302  switch_channel_set_variable(session->channel, "media_audio_mode", "recvonly");
5303  } else if (sendonly < 2 && !strcasecmp(attr->a_name, "inactive")) {
5304  switch_channel_set_variable(session->channel, "media_audio_mode", "inactive");
5305  } else if (!strcasecmp(attr->a_name, "recvonly")) {
5306  switch_channel_set_variable(session->channel, "media_audio_mode", "sendonly");
5307  recvonly = 1;
5308 
5309  a_engine->media_timeout = 0;
5310  a_engine->media_hold_timeout = 0;
5311 
5312  if (switch_rtp_ready(a_engine->rtp_session)) {
5314  a_engine->max_missed_hold_packets = 0;
5315  a_engine->max_missed_packets = 0;
5317  } else {
5318  switch_channel_set_variable(session->channel, "media_timeout_audio", "0");
5319  switch_channel_set_variable(session->channel, "media_hold_timeout_audio", "0");
5320  switch_channel_set_variable(session->channel, "rtp_timeout_sec", "0");
5321  switch_channel_set_variable(session->channel, "rtp_hold_timeout_sec", "0");
5322  }
5323  } else if (sendonly < 2 && !strcasecmp(attr->a_name, "sendrecv")) {
5324  sendonly = 0;
5325  } else if (!strcasecmp(attr->a_name, "ptime")) {
5326  ptime = dptime = atoi(attr->a_value);
5327  } else if (!strcasecmp(attr->a_name, "maxptime")) {
5328  maxptime = dmaxptime = atoi(attr->a_value);
5329  }
5330  }
5331 
5332  if (sendonly == 2 && ice) {
5333  sendonly = 0;
5334  }
5335 
5336 
5337  if (sendonly != 1 && recvonly != 1 && inactive != 1) {
5338  switch_channel_set_variable(session->channel, "media_audio_mode", NULL);
5339  }
5340 
5341  if (sdp_type == SDP_TYPE_RESPONSE) {
5342  if (inactive) {
5343  // When freeswitch had previously sent inactive in sip request. it should remain inactive otherwise smode should be sendrecv
5344  if (a_engine->smode==SWITCH_MEDIA_FLOW_INACTIVE) {
5346  } else {
5348  }
5349  } else if (sendonly) {
5351  } else if (recvonly) {
5353  }
5354  }
5355 
5356 
5358  || ((val = switch_channel_get_variable(session->channel, "rtp_disable_hold"))
5359  && switch_true(val)))
5360  && !smh->mparams->hold_laps) {
5361  smh->mparams->hold_laps++;
5362  switch_core_media_toggle_hold(session, sendonly);
5363  }
5364 
5365 
5366  if (switch_rtp_has_dtls() && dtls_ok(session)) {
5367  for (attr = m->m_attributes; attr; attr = attr->a_next) {
5368 
5369  if (!strcasecmp(attr->a_name, "fingerprint") && !zstr(attr->a_value)) {
5370  got_crypto = 1;
5371  }
5372  }
5373  }
5374 
5375  skip_rtcp = 0;
5376  got_rtcp_mux = 0;
5377  for (attr = m->m_attributes; attr; attr = attr->a_next) {
5378  if (!strcasecmp(attr->a_name, "rtcp-mux")) {
5379  got_rtcp_mux = 1;
5380  skip_rtcp = 1;
5381  if (!smh->mparams->rtcp_video_interval_msec) {
5383  }
5384  } else if (!strcasecmp(attr->a_name, "ice-ufrag")) {
5385  skip_rtcp = 1;
5386  }
5387  }
5388 
5389  if (!got_rtcp_mux) {
5390  a_engine->rtcp_mux = -1;
5391  }
5392 
5393  for (attr = m->m_attributes; attr; attr = attr->a_next) {
5394  if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value && !skip_rtcp) {
5395  a_engine->remote_rtcp_port = (switch_port_t)atoi(attr->a_value);
5396  switch_channel_set_variable_printf(session->channel, "rtp_remote_audio_rtcp_port", "%d", a_engine->remote_rtcp_port);
5397 
5398  if (!smh->mparams->rtcp_audio_interval_msec) {
5400  }
5401  got_audio_rtcp = 1;
5402  } else if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
5403  ptime = atoi(attr->a_value);
5404  } else if (!strcasecmp(attr->a_name, "maxptime") && attr->a_value) {
5405  maxptime = atoi(attr->a_value);
5406  } else if (got_crypto < 1 && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) {
5407  int crypto_tag;
5408 
5409  if (!(smh->mparams->ndlb & SM_NDLB_ALLOW_CRYPTO_IN_AVP) &&
5410  !switch_true(switch_channel_get_variable(session->channel, "rtp_allow_crypto_in_avp"))) {
5411  if (m->m_proto != sdp_proto_srtp && !got_webrtc) {
5412  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "a=crypto in RTP/AVP, refer to rfc3711\n");
5413  match = 0;
5414  goto done;
5415  }
5416  }
5417 
5418  crypto = attr->a_value;
5419  crypto_tag = atoi(crypto);
5420  got_crypto = switch_core_session_check_incoming_crypto(session,
5421  "rtp_has_crypto", SWITCH_MEDIA_TYPE_AUDIO, crypto, crypto_tag, sdp_type);
5422 
5423  }
5424  }
5425 
5426  if (got_crypto == -1 && got_savp && !got_avp && !got_webrtc) {
5427  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Received invite with SAVP but secure media is administratively disabled\n");
5428  match = 0;
5429  continue;
5430  }
5431 
5432  connection = sdp->sdp_connection;
5433  if (m->m_connections) {
5434  connection = m->m_connections;
5435  }
5436 
5437  if (!connection) {
5438  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");
5439  match = 0;
5440  break;
5441  }
5442 
5443  x = 0;
5444 
5445  for (map = m->m_rtpmaps; map; map = map->rm_next) {
5446  int32_t i;
5447  const char *rm_encoding;
5448  uint32_t map_bit_rate = 0;
5449  switch_codec_fmtp_t codec_fmtp = { 0 };
5450  int map_channels = map->rm_params ? atoi(map->rm_params) : 1;
5451 
5452  if (!(rm_encoding = map->rm_encoding)) {
5453  rm_encoding = "";
5454  }
5455 
5456 
5457  if (!strcasecmp(rm_encoding, "telephone-event")) {
5458  if (!best_te || map->rm_rate == a_engine->cur_payload_map->rm_rate) {
5459  best_te = (switch_payload_t) map->rm_pt;
5460  best_te_rate = map->rm_rate;
5461  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set telephone-event payload to %u@%ld\n", best_te, best_te_rate);
5462  }
5463  continue;
5464  }
5465 
5466  if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && !cng_pt && !strcasecmp(rm_encoding, "CN")) {
5467  cng_pt = (switch_payload_t) map->rm_pt;
5468  if (a_engine->rtp_session) {
5469  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u\n", cng_pt);
5470  switch_rtp_set_cng_pt(a_engine->rtp_session, cng_pt);
5471  }
5472  continue;
5473  }
5474 
5475 
5476  if (x++ < skip) {
5477  continue;
5478  }
5479 
5480  if (match) {
5481  continue;
5482  }
5483 
5484  codec_ms = ptime;
5485 
5486  if (switch_channel_get_variable(session->channel, "rtp_h_X-Broken-PTIME") && a_engine->read_impl.microseconds_per_packet) {
5487  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);
5488  codec_ms = a_engine->read_impl.microseconds_per_packet / 1000;
5489  }
5490 
5491  if (maxptime && (!codec_ms || codec_ms > maxptime)) {
5492  codec_ms = maxptime;
5493  }
5494 
5495  if (!codec_ms) {
5496  codec_ms = switch_default_ptime(rm_encoding, map->rm_pt);
5497  }
5498 
5499  map_bit_rate = switch_known_bitrate((switch_payload_t)map->rm_pt);
5500 
5501  if (!ptime && !strcasecmp(map->rm_encoding, "g723")) {
5502  codec_ms = 30;
5503  }
5504 
5505  remote_codec_rate = map->rm_rate;
5506  fmtp_remote_codec_rate = 0;
5507  memset(&codec_fmtp, 0, sizeof(codec_fmtp));
5508 
5509  if (zstr(map->rm_fmtp)) {
5510  if (!strcasecmp(map->rm_encoding, "ilbc")) {
5511  codec_ms = 30;
5512  map_bit_rate = 13330;
5513  } else if (!strcasecmp(map->rm_encoding, "isac")) {
5514  codec_ms = 30;
5515  map_bit_rate = 32000;
5516  }
5517  } else {
5518  if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) {
5519  if (codec_fmtp.bits_per_second) {
5520  map_bit_rate = codec_fmtp.bits_per_second;
5521  }
5522  if (codec_fmtp.microseconds_per_packet) {
5523  codec_ms = (codec_fmtp.microseconds_per_packet / 1000);
5524  }
5525  if (codec_fmtp.actual_samples_per_second) {
5526  fmtp_remote_codec_rate = codec_fmtp.actual_samples_per_second;
5527  }
5528  if (codec_fmtp.stereo) {
5529  map_channels = 2;
5530  } else if (!strcasecmp(map->rm_encoding, "opus")) {
5531  map_channels = 1;
5532  }
5533 
5534  if (codec_fmtp.max_ptime) {
5535  maxptime = codec_fmtp.max_ptime;
5536  }
5537  }
5538  }
5539 
5540  for (i = 0; i < smh->mparams->num_codecs && i < total_codecs; i++) {
5541  const switch_codec_implementation_t *imp = codec_array[i];
5542  uint32_t bit_rate = imp->bits_per_second;
5543  uint32_t codec_rate = imp->samples_per_second;
5544 
5545  if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
5546  continue;
5547  }
5548 
5549  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",
5550  rm_encoding, map->rm_pt, (int) remote_codec_rate, codec_ms, map_bit_rate, map_channels,
5551  imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate, imp->number_of_channels);
5552  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
5553  match = (map->rm_pt == imp->ianacode) ? 1 : 0;
5554  } else {
5555  match = (!strcasecmp(rm_encoding, imp->iananame) &&
5556  ((map->rm_pt < 96 && imp->ianacode < 96) || (map->rm_pt > 95 && imp->ianacode > 95)) &&
5557  (remote_codec_rate == codec_rate || fmtp_remote_codec_rate == imp->actual_samples_per_second)) ? 1 : 0;
5558  if (fmtp_remote_codec_rate) {
5559  remote_codec_rate = fmtp_remote_codec_rate;
5560  }
5561  }
5562 
5563  if (match && bit_rate && map_bit_rate && map_bit_rate != bit_rate && strcasecmp(map->rm_encoding, "ilbc") &&
5564  strcasecmp(map->rm_encoding, "isac")) {
5565  /* if a bit rate is specified and doesn't match, this is not a codec match, except for ILBC */
5566  match = 0;
5567  }
5568 
5569  if (match && remote_codec_rate && codec_rate && remote_codec_rate != codec_rate && (!strcasecmp(map->rm_encoding, "pcma") ||
5570  !strcasecmp(map->rm_encoding, "pcmu"))) {
5571  /* if the sampling rate is specified and doesn't match, this is not a codec match for G.711 */
5572  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "sampling rates have to match for G.711\n");
5573  match = 0;
5574  }
5575 
5576  if (match) {
5577  if (scrooge) {
5579  "Bah HUMBUG! Sticking with %s@%uh@%ui\n",
5580  imp->iananame, imp->samples_per_second, imp->microseconds_per_packet / 1000);
5581  } else if ((ptime && codec_ms && codec_ms * 1000 != imp->microseconds_per_packet) || remote_codec_rate != codec_rate) {
5582  /* ptime does not match */
5583  match = 0;
5584 
5585  if (nm_idx >= MAX_MATCHES) {
5587  "Audio Codec Compare [%s:%d:%u:%u:%d:%u:%d] was not saved as a near-match. Too many. Ignoring.\n",
5588  imp->iananame, imp->ianacode, codec_rate, imp->actual_samples_per_second, imp->microseconds_per_packet / 1000, bit_rate, imp->number_of_channels);
5589  continue;
5590  }
5591 
5593  "Audio Codec Compare [%s:%d:%u:%d:%u:%d] is saved as a near-match\n",
5594  imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate, imp->number_of_channels);
5595 
5596  near_matches[nm_idx].codec_idx = i;
5597  near_matches[nm_idx].rate = remote_codec_rate;
5598  near_matches[nm_idx].imp = imp;
5599  near_matches[nm_idx].map = map;
5600  nm_idx++;
5601 
5602  continue;
5603  }
5604 
5605  matches[m_idx].codec_idx = i;
5606  matches[m_idx].rate = codec_rate;
5607  matches[m_idx].imp = imp;
5608  matches[m_idx].map = map;
5609  m_idx++;
5610 
5612  "Audio Codec Compare [%s:%d:%u:%d:%u:%d] ++++ is saved as a match\n",
5613  imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate, imp->number_of_channels);
5614 
5615  if (m_idx >= MAX_MATCHES) {
5616  break;
5617  }
5618 
5619  match = 0;
5620  }
5621  }
5622 
5623  if (m_idx >= MAX_MATCHES) {
5624  break;
5625  }
5626  }
5627 
5628  if (smh->crypto_mode == CRYPTO_MODE_MANDATORY && got_crypto < 1) {
5629  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Crypto not negotiated but required.\n");
5630  match = 0;
5631  m_idx = nm_idx = 0;
5632  }
5633 
5634 
5635  if (!m_idx && nm_idx) {
5636  int j;
5637 
5638  for(j = 0; j < nm_idx; j++) {
5639  const switch_codec_implementation_t *search[1];
5640  char *prefs[1];
5641  char tmp[80];
5642  char fmtp[SWITCH_MAX_CODECS][MAX_FMTP_LEN];
5643  int num;
5644  const switch_codec_implementation_t *timp = NULL;
5645 
5646  near_rate = near_matches[j].rate;
5647  near_match = near_matches[j].imp;
5648  near_map = near_matches[j].map;
5649 
5650  switch_snprintf(tmp, sizeof(tmp), "%s@%uh@%ui%dc", near_match->iananame, near_rate ? near_rate : near_match->samples_per_second,
5651  codec_ms, near_match->number_of_channels);
5652 
5653  prefs[0] = tmp;
5654  num = switch_loadable_module_get_codecs_sorted(search, fmtp, 1, prefs, 1);
5655 
5656  if (num) {
5657  timp = search[0];
5658  } else {
5659  timp = near_match;
5660  }
5661 
5662  if (!maxptime || timp->microseconds_per_packet / 1000 <= maxptime) {
5663  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Substituting codec %s@%ui@%uh@%dc\n",
5665  match = 1;
5666 
5667  matches[m_idx].codec_idx = near_matches[j].codec_idx;
5668  matches[m_idx].rate = near_rate;
5669  matches[m_idx].imp = timp;
5670  matches[m_idx].map = near_map;
5671  m_idx++;
5672 
5673  break;
5674  }
5675  }
5676  }
5677 
5678  if (m_idx) {
5679  int j;
5680 
5681  if (greedy) { /* sort in favor of mine */
5682  greedy_sort(smh, matches, m_idx, codec_array, total_codecs);
5683  }
5684 
5685  match = 1;
5686  a_engine->codec_negotiated = 1;
5687 
5688  for(j = 0; j < m_idx && smh->num_negotiated_codecs < SWITCH_MAX_CODECS; j++) {
5691  matches[j].map->rm_encoding,
5692  matches[j].imp->modname,
5693  matches[j].map->rm_fmtp,
5694  sdp_type,
5695  matches[j].map->rm_pt,
5696  matches[j].imp->samples_per_second,
5697  matches[j].imp->microseconds_per_packet / 1000,
5698  matches[j].imp->number_of_channels,
5699  SWITCH_TRUE);
5700 
5701  mimp = matches[j].imp;
5702  mmap = matches[j].map;
5703 
5704  if (j == 0) {
5705  a_engine->cur_payload_map = pmap;
5706  a_engine->cur_payload_map->current = 1;
5707  if (a_engine->rtp_session) {
5708  switch_rtp_set_default_payload(a_engine->rtp_session, pmap->pt);
5709  }
5710  }
5711 
5712  pmap->rm_encoding = switch_core_session_strdup(session, (char *) mmap->rm_encoding);
5713  pmap->iananame = switch_core_session_strdup(session, (char *) mimp->iananame);
5714  pmap->recv_pt = (switch_payload_t) mmap->rm_pt;
5715  pmap->rm_rate = mimp->samples_per_second;
5716  pmap->adv_rm_rate = mimp->samples_per_second;
5717  if (strcasecmp(mimp->iananame, "g722")) {
5718  pmap->rm_rate = mimp->actual_samples_per_second;
5719  }
5720  pmap->codec_ms = mimp->microseconds_per_packet / 1000;
5721  pmap->bitrate = mimp->bits_per_second;
5722  pmap->channels = mmap->rm_params ? atoi(mmap->rm_params) : 1;
5723 
5724  if (!strcasecmp((char *) mmap->rm_encoding, "opus")) {
5725  if (pmap->channels == 1) {
5726  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid SDP for opus. Don't ask.. but it needs a /2\n");
5727  pmap->adv_channels = 1;
5728  } else {
5729  pmap->adv_channels = 2; /* IKR ???*/
5730  }
5731  if (!zstr((char *) mmap->rm_fmtp) && switch_stristr("stereo=1", (char *) mmap->rm_fmtp)) {
5732  uint32_t allow_channels = switch_core_max_audio_channels(0);
5733  if (!allow_channels || allow_channels >= 2) { /*default*/
5734  pmap->channels = 2;
5735  } else { /* allow_channels == 1 */
5736  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Opus: setting 1 audio channel via config.\n");
5737  pmap->channels = 1;
5738  }
5739  } else {
5740  pmap->channels = 1;
5741  }
5742  } else {
5743  pmap->adv_channels = pmap->channels;
5744  }
5745 
5746  pmap->remote_sdp_ip = switch_core_session_strdup(session, (char *) connection->c_address);
5747  pmap->remote_sdp_port = (switch_port_t) m->m_port;
5748  pmap->rm_fmtp = switch_core_session_strdup(session, (char *) mmap->rm_fmtp);
5749 
5750  smh->negotiated_codecs[smh->num_negotiated_codecs++] = mimp;
5751  pmap->recv_pt = (switch_payload_t)mmap->rm_pt;
5752 
5753  }
5754  }
5755 
5756  if (match) {
5757  char tmp[50];
5758  //const char *mirror = switch_channel_get_variable(session->channel, "rtp_mirror_remote_audio_codec_payload");
5759 
5760 
5761  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
5764 
5765 
5766  if (a_engine->cur_payload_map->pt == smh->mparams->te) {
5767  switch_payload_t pl = 0;
5768  payload_map_t *pmap;
5769 
5771  for (pmap = a_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
5772  if (pmap->pt > pl) {
5773  pl = pmap->pt;
5774  }
5775  }
5777 
5778  smh->mparams->te = (switch_payload_t) ++pl;
5779  }
5780 
5781 
5782 
5783  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->recv_pt);
5784  switch_channel_set_variable(session->channel, "rtp_audio_recv_pt", tmp);
5785 
5786  if (a_engine->read_impl.iananame) {
5787  if (!switch_core_codec_ready(&a_engine->read_codec) ||
5788  ((strcasecmp(matches[0].imp->iananame, a_engine->read_impl.iananame) ||
5789  matches[0].imp->microseconds_per_packet != a_engine->read_impl.microseconds_per_packet ||
5790  matches[0].imp->samples_per_second != a_engine->read_impl.samples_per_second
5791  ))) {
5792 
5793  a_engine->reset_codec = 1;
5794  }
5795  } else if (switch_core_media_set_codec(session, 0, smh->mparams->codec_flags) != SWITCH_STATUS_SUCCESS) {
5796  match = 0;
5797  }
5798 
5799  if (match) {
5800  if (check_ice(smh, SWITCH_MEDIA_TYPE_AUDIO, sdp, m) == SWITCH_STATUS_FALSE) {
5801  match = 0;
5802  got_audio = 0;
5803  } else {
5804  got_audio = 1;
5805  }
5806  }
5807 
5808  }
5809 
5810  for (map = m->m_rtpmaps; map; map = map->rm_next) {
5811  const char *rm_encoding;
5812 
5813  if (!(rm_encoding = map->rm_encoding)) {
5814  rm_encoding = "";
5815  }
5816 
5817  if (!strcasecmp(rm_encoding, "telephone-event")) {
5818  if (!best_te || map->rm_rate == a_engine->cur_payload_map->adv_rm_rate) {
5819  best_te = (switch_payload_t) map->rm_pt;
5820  best_te_rate = map->rm_rate;
5821  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set telephone-event payload to %u@%lu\n", best_te, best_te_rate);
5822  }
5823  continue;
5824  }
5825 
5826  if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && !strcasecmp(rm_encoding, "CN")) {
5827 
5828  if (!cng_pt || map->rm_rate == a_engine->cur_payload_map->adv_rm_rate) {
5829  cng_pt = (switch_payload_t) map->rm_pt;
5830  cng_rate = map->rm_rate;
5831 
5832  if (a_engine->rtp_session) {
5833  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u@%lu\n", cng_pt, cng_rate);
5834  switch_rtp_set_cng_pt(a_engine->rtp_session, cng_pt);
5835  }
5836  }
5837  continue;
5838  }
5839  }
5840 
5841  if (cng_rate != a_engine->cur_payload_map->adv_rm_rate) {
5842  cng_rate = 8000;
5843  }
5844 
5845  if (best_te_rate != a_engine->cur_payload_map->adv_rm_rate) {
5846  best_te_rate = 8000;
5847  }
5848 
5849  if (!best_te && (switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF))) {
5851  "No 2833 in SDP. Liberal DTMF mode adding %d as telephone-event.\n", smh->mparams->te);
5852  best_te = smh->mparams->te;
5853  }
5854 
5855  if (best_te) {
5856  smh->mparams->te_rate = best_te_rate;
5857 
5858  if (smh->mparams->dtmf_type == DTMF_AUTO || smh->mparams->dtmf_type == DTMF_2833 ||
5860  if (sdp_type == SDP_TYPE_REQUEST) {
5861  smh->mparams->te = smh->mparams->recv_te = (switch_payload_t) best_te;
5862  switch_channel_set_variable(session->channel, "dtmf_type", "rfc2833");
5863  smh->mparams->dtmf_type = DTMF_2833;
5864  } else {
5865  smh->mparams->te = (switch_payload_t) best_te;
5866  switch_channel_set_variable(session->channel, "dtmf_type", "rfc2833");
5867  smh->mparams->dtmf_type = DTMF_2833;
5868  }
5869  }
5870 
5871  if (a_engine->rtp_session) {
5873  switch_channel_set_variable_printf(session->channel, "rtp_2833_send_payload", "%d", smh->mparams->te);
5875  switch_channel_set_variable_printf(session->channel, "rtp_2833_recv_payload", "%d", smh->mparams->recv_te);
5876  }
5877 
5878 
5879  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Set 2833 dtmf send payload to %u recv payload to %u\n",
5880  switch_channel_get_name(session->channel), smh->mparams->te, smh->mparams->recv_te);
5881 
5882 
5883  } else {
5884  /* by default, use SIP INFO if 2833 is not in the SDP */
5885  if (!switch_false(switch_channel_get_variable(channel, "rtp_info_when_no_2833"))) {
5886  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No 2833 in SDP. Disable 2833 dtmf and switch to INFO\n");
5887  switch_channel_set_variable(session->channel, "dtmf_type", "info");
5888  smh->mparams->dtmf_type = DTMF_INFO;
5889  smh->mparams->recv_te = smh->mparams->te = 0;
5890  } else {
5891  switch_channel_set_variable(session->channel, "dtmf_type", "none");
5892  smh->mparams->dtmf_type = DTMF_NONE;
5893  smh->mparams->recv_te = smh->mparams->te = 0;
5894  }
5895  }
5896 
5897  } else if (!got_text && m->m_type == sdp_media_text && m->m_port) {
5898  sdp_rtpmap_t *map;
5899  payload_map_t *red_pmap = NULL;
5900 
5902 
5903  connection = sdp->sdp_connection;
5904  if (m->m_connections) {
5905  connection = m->m_connections;
5906  }
5907 
5908  if (!connection) {
5909  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");
5910  match = 0;
5911  break;
5912  }
5913 
5914  switch_channel_set_variable(session->channel, "text_possible", "true");
5917 
5918  got_text++;
5919 
5920  for (map = m->m_rtpmaps; map; map = map->rm_next) {
5921  payload_map_t *pmap;
5922 
5923  pmap = switch_core_media_add_payload_map(session,
5925  map->rm_encoding,
5926  NULL,
5927  NULL,
5929  map->rm_pt,
5930  1000,
5931  0,
5932  1,
5933  SWITCH_TRUE);
5934 
5935 
5936  pmap->remote_sdp_ip = switch_core_session_strdup(session, (char *) connection->c_address);
5937  pmap->remote_sdp_port = (switch_port_t) m->m_port;
5938  if (map->rm_fmtp) {
5939  pmap->rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp);
5940  }
5941 
5942 
5943  t_engine->cur_payload_map = pmap;
5944 
5945  if (!strcasecmp(map->rm_encoding, "red")) {
5946  red_pmap = pmap;
5947  }
5948  }
5949 
5950  if (red_pmap) {
5951  t_engine->cur_payload_map = red_pmap;
5952  }
5953 
5954  for (attr = m->m_attributes; attr; attr = attr->a_next) {
5955  if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value) {
5956  switch_channel_set_variable(session->channel, "sip_remote_text_rtcp_port", attr->a_value);
5957 
5958  } else if (!got_text_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) {
5959  int crypto_tag;
5960 
5961  if (!(smh->mparams->ndlb & SM_NDLB_ALLOW_CRYPTO_IN_AVP) &&
5962  !switch_true(switch_channel_get_variable(session->channel, "rtp_allow_crypto_in_avp"))) {
5963  if (m->m_proto != sdp_proto_srtp && !got_webrtc) {
5964  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "a=crypto in RTP/AVP, refer to rfc3711\n");
5965  match = 0;
5966  goto done;
5967  }
5968  }
5969 
5970  crypto = attr->a_value;
5971  crypto_tag = atoi(crypto);
5972 
5973  got_text_crypto = switch_core_session_check_incoming_crypto(session,
5974  "rtp_has_text_crypto",
5975  SWITCH_MEDIA_TYPE_TEXT, crypto, crypto_tag, sdp_type);
5976 
5977  }
5978  }
5979 
5980 
5981  //map->rm_encoding
5982  //map->rm_fmtp
5983  //map->rm_pt
5984  //t_engine->cur_payload_map = pmap;
5985 
5986  t_engine->codec_negotiated = 1;
5987  tmatch = 1;
5988 
5989 
5990  if (!t_engine->local_sdp_port) {
5992  }
5993 
5994  check_ice(smh, SWITCH_MEDIA_TYPE_TEXT, sdp, m);
5995  //parse rtt
5996 
5997  } else if (m->m_type == sdp_media_video) {
5998  sdp_rtpmap_t *map;
5999  const char *rm_encoding;
6000  const switch_codec_implementation_t *mimp = NULL;
6001  int i;
6002  const char *inherit_video_fmtp = NULL;
6003 
6005 
6006  if (sdp_type == SDP_TYPE_REQUEST) {
6007  sdp_bandwidth_t *bw;
6008  int tias = 0;
6009 
6010  for (bw = m->m_bandwidths; bw; bw = bw->b_next) {
6011  if (bw->b_modifier == sdp_bw_as && !tias) {
6012  v_engine->sdp_bw = bw->b_value;
6013  } else if (bw->b_modifier == sdp_bw_tias) {
6014  tias = 1;
6015  v_engine->sdp_bw = bw->b_value / 1024;
6016  }
6017  }
6018 
6019  switch(v_engine->rmode) {
6023  break;
6026  break;
6029  break;
6030  default:
6032  break;
6033  }
6034  }
6035 
6036  if (!m->m_port) {
6037  goto endsdp;
6038  }
6039 
6040  vmatch = 0;
6041  almost_vmatch = 0;
6042  m_idx = 0;
6043  memset(matches, 0, sizeof(matches[0]) * MAX_MATCHES);
6044  memset(near_matches, 0, sizeof(near_matches[0]) * MAX_MATCHES);
6045 
6046  switch_channel_set_variable(session->channel, "video_possible", "true");
6049 
6050  connection = sdp->sdp_connection;
6051  if (m->m_connections) {
6052  connection = m->m_connections;
6053  }
6054 
6055  if (!connection) {
6056  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");
6057  match = 0;
6058  break;
6059  }
6060 
6061 
6062 
6063  skip_video_rtcp = 0;
6064  got_video_rtcp_mux = 0;
6065  for (attr = m->m_attributes; attr; attr = attr->a_next) {
6066  if (!strcasecmp(attr->a_name, "rtcp-mux")) {
6067  got_video_rtcp_mux = 1;
6068  skip_video_rtcp = 1;
6069  } else if (!strcasecmp(attr->a_name, "ice-ufrag")) {
6070  skip_video_rtcp = 1;
6071  }
6072  }
6073 
6074  if (!got_video_rtcp_mux) {
6075  v_engine->rtcp_mux = -1;
6076  }
6077 
6078  for (attr = m->m_attributes; attr; attr = attr->a_next) {
6079  if (!strcasecmp(attr->a_name, "framerate") && attr->a_value) {
6080  //framerate = atoi(attr->a_value);
6081  } else if (!strcasecmp(attr->a_name, "rtcp-fb")) {
6082  if (!zstr(attr->a_value)) {
6083  if (switch_stristr("fir", attr->a_value)) {
6084  v_engine->fir++;
6085  }
6086 
6087  if (switch_stristr("pli", attr->a_value)) {
6088  v_engine->pli++;
6089  }
6090 
6091  if (switch_stristr("nack", attr->a_value)) {
6092  v_engine->nack++;
6093  }
6094 
6095  if (switch_stristr("tmmbr", attr->a_value)) {
6096  v_engine->tmmbr++;
6097  }
6098 
6099  rtcp_auto_video = 1;
6101  }
6102  } else if (!strcasecmp(attr->a_name, "rtcp") && attr->a_value && !skip_video_rtcp) {
6103  v_engine->remote_rtcp_port = (switch_port_t)atoi(attr->a_value);
6104  switch_channel_set_variable_printf(session->channel, "rtp_remote_video_rtcp_port", "%d", v_engine->remote_rtcp_port);
6105  if (!smh->mparams->rtcp_video_interval_msec) {
6107  }
6108  got_video_rtcp = 1;
6109  } else if (!got_video_crypto && !strcasecmp(attr->a_name, "crypto") && !zstr(attr->a_value)) {
6110  int crypto_tag;
6111 
6112  if (!(smh->mparams->ndlb & SM_NDLB_ALLOW_CRYPTO_IN_AVP) &&
6113  !switch_true(switch_channel_get_variable(session->channel, "rtp_allow_crypto_in_avp"))) {
6114  if (m->m_proto != sdp_proto_srtp && !got_webrtc) {
6115  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "a=crypto in RTP/AVP, refer to rfc3711\n");
6116  match = 0;
6117  goto done;
6118  }
6119  }
6120 
6121  crypto = attr->a_value;
6122  crypto_tag = atoi(crypto);
6123 
6124  got_video_crypto = switch_core_session_check_incoming_crypto(session,
6125  "rtp_has_video_crypto",
6126  SWITCH_MEDIA_TYPE_VIDEO, crypto, crypto_tag, sdp_type);
6127 
6128  }
6129  }
6130 
6131 
6132  if (switch_true(switch_channel_get_variable_dup(session->channel, "inherit_codec", SWITCH_FALSE, -1))) {
6133  vmatch_pt = 1;
6134  }
6135 
6136  compare:
6137 
6138  for (map = m->m_rtpmaps; map; map = map->rm_next) {
6139 
6140  if (switch_rtp_has_dtls() && dtls_ok(session)) {
6141  for (attr = m->m_attributes; attr; attr = attr->a_next) {
6142  if (!strcasecmp(attr->a_name, "fingerprint") && !zstr(attr->a_value)) {
6143  got_video_crypto = 1;
6144  }
6145  }
6146  }
6147 
6148  if (!(rm_encoding = map->rm_encoding)) {
6149  rm_encoding = "";
6150  }
6151 
6152  for (i = 0; i < total_codecs; i++) {
6153  const switch_codec_implementation_t *imp = codec_array[i];
6154 
6155  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
6156  continue;
6157  }
6158 
6161  continue;
6162  }
6163 
6164  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video Codec Compare [%s:%d]/[%s:%d]\n",
6165  rm_encoding, map->rm_pt, imp->iananame, imp->ianacode);
6166  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
6167  vmatch = (map->rm_pt == imp->ianacode) ? 1 : 0;
6168  } else {
6169  vmatch = strcasecmp(rm_encoding, imp->iananame) ? 0 : 1;
6170  }
6171 
6172  if (sdp_type == SDP_TYPE_RESPONSE && consider_video_fmtp && vmatch && !zstr(map->rm_fmtp) && !zstr(smh->fmtps[i])) {
6173  almost_vmatch = 1;
6174  vmatch = !strcasecmp(smh->fmtps[i], map->rm_fmtp);
6175  }
6176 
6177  if (vmatch && vmatch_pt) {
6178  const char *other_pt = switch_channel_get_variable_partner(channel, "rtp_video_pt");
6179 
6180  if (other_pt) {
6181  int opt = atoi(other_pt);
6182  if (map->rm_pt != opt) {
6183  vmatch = 0;
6184  } else {
6185  if (switch_channel_var_true(channel, "inherit_video_fmtp")) {
6186  inherit_video_fmtp = switch_channel_get_variable_partner(channel, "rtp_video_fmtp");
6187  }
6188  }
6189  }
6190  }
6191 
6192  if (vmatch) {
6193  matches[m_idx].imp = imp;
6194  matches[m_idx].map = map;
6195 
6196  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video Codec Compare [%s:%d] +++ is saved as a match\n",
6197  imp->iananame, map->rm_pt);
6198 
6199  m_idx++;
6200 
6201  if (m_idx >= MAX_MATCHES) {
6202  break;
6203  }
6204  }
6205 
6206  vmatch = 0;
6207  }
6208 
6209  if (m_idx >= MAX_MATCHES) {
6210  break;
6211  }
6212  }
6213 
6214  if (consider_video_fmtp && (!m_idx || almost_vmatch)) {
6215  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No matches with FTMP, fallback to ignoring FMTP\n");
6216  almost_vmatch = 0;
6217  m_idx = 0;
6218  consider_video_fmtp = 0;
6219  goto compare;
6220  }
6221 
6222  if (vmatch_pt && !m_idx) {
6223  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No matches with inherit_codec, fallback to ignoring PT\n");
6224  vmatch_pt = 0;
6225  goto compare;
6226  }
6227 
6228  if (smh->crypto_mode == CRYPTO_MODE_MANDATORY && got_video_crypto < 1) {
6229  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Crypto not negotiated but required.\n");
6230  vmatch = 0;
6231  m_idx = 0;
6232  }
6233 
6234  if (m_idx) {
6235  char tmp[50];
6236  //const char *mirror = switch_channel_get_variable(session->channel, "rtp_mirror_remote_video_codec_payload");
6237  int j = 0;
6238 
6239  if (greedy) { /* sort in favor of mine */
6240  greedy_sort(smh, matches, m_idx, codec_array, total_codecs);
6241  }
6242 
6243  vmatch = 1;
6244  v_engine->codec_negotiated = 1;
6245  v_engine->payload_map = NULL;
6246 
6247  for(j = 0; j < m_idx && smh->num_negotiated_codecs < SWITCH_MAX_CODECS; j++) {
6250  matches[j].map->rm_encoding,
6251  matches[j].imp->modname,
6252  consider_video_fmtp ? matches[j].map->rm_fmtp : NULL,
6253  sdp_type,
6254  matches[j].map->rm_pt,
6255  matches[j].imp->samples_per_second,
6256  matches[j].imp->microseconds_per_packet / 1000,
6257  matches[j].imp->number_of_channels,
6258  SWITCH_TRUE);
6259 
6260  if (j == 0) {
6261  v_engine->cur_payload_map = pmap;
6262  v_engine->cur_payload_map->current = 1;
6263  if (v_engine->rtp_session) {
6264  switch_rtp_set_default_payload(v_engine->rtp_session, pmap->pt);
6265  }
6266  }
6267 
6268  mimp = matches[j].imp;
6269  map = matches[j].map;
6270 
6271  pmap->rm_encoding = switch_core_session_strdup(session, (char *) map->rm_encoding);
6272  pmap->recv_pt = (switch_payload_t) map->rm_pt;
6273  pmap->rm_rate = map->rm_rate;
6274  pmap->codec_ms = mimp->microseconds_per_packet / 1000;
6275 
6276 
6277  pmap->remote_sdp_ip = switch_core_session_strdup(session, (char *) connection->c_address);
6278  pmap->remote_sdp_port = (switch_port_t) m->m_port;
6279  pmap->rm_fmtp = switch_core_session_strdup(session, (char *) inherit_video_fmtp ? inherit_video_fmtp : map->rm_fmtp);
6280  smh->negotiated_codecs[smh->num_negotiated_codecs++] = mimp;
6281 
6282 #if 0
6283  if (j == 0 && (!switch_true(mirror) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND)) {
6284  switch_core_media_get_offered_pt(session, mimp, &pmap->recv_pt);
6285  }
6286 #endif
6287  }
6288 
6289  switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->cur_payload_map->remote_sdp_port);
6292  switch_channel_set_variable(session->channel, "rtp_video_fmtp", v_engine->cur_payload_map->rm_fmtp);
6293  switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->cur_payload_map->pt);
6294  switch_channel_set_variable(session->channel, "rtp_video_pt", tmp);
6296  switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->cur_payload_map->recv_pt);
6297  switch_channel_set_variable(session->channel, "rtp_video_recv_pt", tmp);
6298 
6299  if (switch_core_codec_ready(&v_engine->read_codec) && strcasecmp(matches[0].imp->iananame, v_engine->read_codec.implementation->iananame)) {
6300  v_engine->reset_codec = 1;
6301  }
6302 
6304  if (check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, m) == SWITCH_STATUS_FALSE) {
6305  vmatch = 0;
6306  }
6307  }
6308  }
6309 
6310  video_port = m->m_port;
6311  }
6312  }
6313 
6314  endsdp:
6315 
6316  if (rtcp_auto_audio || rtcp_auto_video) {
6317  if (rtcp_auto_audio && !skip_rtcp && !got_audio_rtcp && audio_port) {
6318  switch_channel_set_variable_printf(session->channel, "rtp_remote_audio_rtcp_port", "%d", audio_port + 1);
6319  a_engine->remote_rtcp_port = audio_port + 1;
6320 
6321  if (!smh->mparams->rtcp_audio_interval_msec) {
6323  }
6324  }
6325  if (rtcp_auto_video && !skip_video_rtcp && !got_video_rtcp && video_port) {
6326  switch_channel_set_variable_printf(session->channel, "rtp_remote_video_rtcp_port", "%d", video_port + 1);
6327  v_engine->remote_rtcp_port = video_port + 1;
6328  if (!smh->mparams->rtcp_video_interval_msec) {
6330  }
6331  }
6332  }
6333 
6334 
6335  if (!saw_audio) {
6336  payload_map_t *pmap;
6337 
6338  a_engine->rmode = SWITCH_MEDIA_FLOW_DISABLED;
6339  switch_channel_set_variable(smh->session->channel, "audio_media_flow", "inactive");
6340 
6341 
6342  pmap = switch_core_media_add_payload_map(session,
6344  "L16",
6345  NULL,
6346  NULL,
6348  97,
6349  8000,
6350  20,
6351  1,
6352  SWITCH_TRUE);
6353 
6354  pmap->remote_sdp_ip = "127.0.0.1";
6355  pmap->remote_sdp_port = 9999;
6356  pmap->pt = 97;
6357  pmap->recv_pt = 97;
6358  pmap->codec_ms = 20;
6359  a_engine->cur_payload_map = pmap;
6362  }
6363 
6364  done:
6365 
6366  if (v_engine->rtp_session) {
6367  if (v_engine->fir) {
6369  } else {
6371  }
6372 
6373  if (v_engine->pli) {
6375  } else {
6377  }
6378 
6379  if (v_engine->nack) {
6381  } else {
6383  }
6384 
6385  if (v_engine->tmmbr) {
6387  } else {
6389  }
6390  }
6391 
6392  if (match) {
6394  } else {
6396  }
6397 
6398  if (vmatch) {
6400  } else {
6401  if (switch_channel_test_flag(channel, CF_VIDEO) && !saw_video) {
6402  //switch_core_media_set_rmode(smh->session, SWITCH_MEDIA_TYPE_VIDEO, SWITCH_MEDIA_FLOW_INACTIVE, sdp_type);
6403 
6404  if (sdp_type == SDP_TYPE_REQUEST) {
6406  }
6407  }
6408  }
6409 
6410  if (tmatch) {
6412  } else {
6414  }
6415 
6416  if (fmatch) {
6419  } else {
6421  }
6422 
6423  t38_done:
6424 
6425  if (parser) {
6426  sdp_parser_free(parser);
6427  }
6428 
6429  smh->mparams->cng_pt = cng_pt;
6430  smh->mparams->cng_rate = cng_rate;
6431 
6432  check_stream_changes(session, r_sdp, sdp_type);
6433 
6434  return match || vmatch || tmatch || fmatch;
6435 }
6436 
6437 //?
6439 {
6440  switch_rtp_engine_t *a_engine;
6441  switch_media_handle_t *smh;
6443 
6444  switch_assert(session);
6445 
6446  if (!(smh = session->media_handle)) {
6447  return;
6448  }
6449 
6450  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
6451 
6452  restore_pmaps(a_engine);
6453 
6454  switch_channel_set_private(channel, "t38_options", NULL);
6459 }
6460 
6461 //?
6462 
6464 {
6465  int changed = 0;
6466  switch_rtp_engine_t *a_engine, *v_engine;
6467  switch_media_handle_t *smh;
6468  switch_core_session_t *b_session = NULL;
6469  switch_channel_t *b_channel = NULL;
6470 
6471  switch_assert(session);
6472 
6473  if (!(smh = session->media_handle)) {
6474  return 0;
6475  }
6476 
6477  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
6478  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
6479 
6480 
6481  if (switch_core_session_get_partner(session, &b_session) == SWITCH_STATUS_SUCCESS) {
6482  b_channel = switch_core_session_get_channel(b_session);
6483  }
6484 
6485  if (sendonly && switch_channel_test_flag(session->channel, CF_ANSWERED)) {
6487  const char *stream;
6488  const char *msg = "hold";
6489  const char *info;
6490 
6492  (!b_channel || switch_channel_test_flag(b_channel, CF_EVENT_LOCK_PRI))) {
6493  switch_channel_mark_hold(session->channel, sendonly);
6495  changed = 0;
6496  goto end;
6497  }
6498 
6499  info = switch_channel_get_variable(session->channel, "presence_call_info");
6500 
6501  if (info) {
6502  if (switch_stristr("private", info)) {
6503  msg = "hold-private";
6504  }
6505  }
6506 
6507  if (a_engine->rtp_session) {
6509  }
6510 
6511  if (v_engine->rtp_session) {
6513  }
6514 
6517  switch_channel_presence(session->channel, "unknown", msg, NULL);
6518  changed = 1;
6519 
6520  if (a_engine->max_missed_hold_packets && a_engine->rtp_session) {
6522  }
6523 
6524  if (a_engine->media_hold_timeout) {
6526  }
6527 
6528  if (v_engine->media_hold_timeout) {
6530  }
6531 
6532 
6533  if (!(stream = switch_channel_get_hold_music(session->channel))) {
6534  stream = "local_stream://moh";
6535  }
6536 
6537 
6538  if (stream && strcasecmp(stream, "silence") && (!b_channel || !switch_channel_test_flag(b_channel, CF_EVENT_LOCK_PRI))) {
6539  if (!strcasecmp(stream, "indicate_hold")) {
6543  } else {
6546  switch_yield(250000);
6547  }
6548  }
6549 
6550  }
6551  } else {
6555 
6556  if (a_engine->rtp_session) {
6558  }
6559 
6560  if (v_engine->rtp_session) {
6562  }
6563 
6564  changed = 1;
6565  }
6566 
6568 
6570  int media_on_hold_a = switch_true(switch_channel_get_variable_dup(session->channel, "bypass_media_resume_on_hold", SWITCH_FALSE, -1));
6571  int bypass_after_hold_a = 0;
6572  int bypass_after_hold_b = 0;
6573 
6574  if (media_on_hold_a) {
6575  bypass_after_hold_a = switch_true(switch_channel_get_variable_dup(session->channel, "bypass_media_after_hold", SWITCH_FALSE, -1));
6576  }
6577 
6578  if (b_channel) {
6579  if (switch_true(switch_channel_get_variable_dup(b_channel, "bypass_media_resume_on_hold", SWITCH_FALSE, -1))) {
6580  bypass_after_hold_b = switch_true(switch_channel_get_variable_dup(b_channel, "bypass_media_after_hold", SWITCH_FALSE, -1));
6581  }
6582  }
6583 
6584  switch_yield(250000);
6585 
6586  if (b_channel && (switch_channel_test_flag(session->channel, CF_BYPASS_MEDIA_AFTER_HOLD) ||
6587  switch_channel_test_flag(b_channel, CF_BYPASS_MEDIA_AFTER_HOLD) || bypass_after_hold_a || bypass_after_hold_b)) {
6588  /* try to stay out from media stream */
6590  }
6591 
6592  if (a_engine->rtp_session) {
6594 
6595  if (a_engine->max_missed_packets) {
6597  }
6598 
6599  if (a_engine->media_hold_timeout) {
6601  }
6602  }
6603 
6604  if (v_engine->rtp_session) {
6606 
6607  if (v_engine->media_hold_timeout) {
6609  }
6610  }
6611 
6612  if (b_channel) {
6613  if (switch_channel_test_flag(session->channel, CF_HOLD)) {
6614  switch_ivr_unhold(b_session);
6617  } else {
6618  switch_channel_stop_broadcast(b_channel);
6619  switch_channel_wait_for_flag(b_channel, CF_BROADCAST, SWITCH_FALSE, 5000, NULL);
6620  }
6621  }
6622 
6624 
6627  switch_channel_presence(session->channel, "unknown", "unhold", NULL);
6628 
6629  if (a_engine->rtp_session) {
6631  }
6632 
6633  if (v_engine->rtp_session) {
6635  }
6636 
6637  changed = 1;
6638  }
6639  }
6640 
6641 
6642  end:
6644 
6645 
6646  if (b_session) {
6648  switch_core_session_rwunlock(b_session);
6649  }
6650 
6651 
6652  return changed;
6653 }
6654 
6655 
6657 {
6658  switch_media_handle_t *smh;
6659  switch_rtp_engine_t *v_engine;
6661 
6662  switch_assert(session);
6663 
6664  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
6665  return NULL;
6666  }
6667 
6668  if (!(smh = session->media_handle)) {
6669  return NULL;
6670  }
6671 
6672  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
6673 
6674 
6675 
6676  if (rw == SWITCH_RW_READ) {
6678  fh = smh->video_read_fh;
6680  } else {
6682  fh = smh->video_write_fh;
6684  }
6685 
6686 
6687 
6688  return fh;
6689 }
6690 
6692 {
6693  switch_frame_t fr = { 0 };
6694  int i = 0;
6695  switch_rgb_color_t bgcolor = { 0 };
6697  unsigned char buf[SWITCH_RTP_MAX_BUF_LEN];
6698  switch_media_handle_t *smh;
6699  switch_image_t *blank_img = NULL;
6700  uint32_t frames = 0, frame_ms = 0;
6701  uint32_t fps, width, height;
6702  switch_assert(session != NULL);
6703 
6704  if (!(smh = session->media_handle)) {
6705  return;
6706  }
6707 
6708  fps = smh->vid_params.fps;
6709  width = smh->vid_params.width;
6710  height = smh->vid_params.height;
6711 
6712  if (!width) width = 352;
6713  if (!height) height = 288;
6714  if (!fps) fps = 15;
6715 
6716  fr.packet = buf;
6717  fr.packetlen = buflen;
6718  fr.data = buf + 12;
6719  fr.buflen = buflen - 12;
6720 
6721 
6722  blank_img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, width, height, 1);
6723  switch_color_set_rgb(&bgcolor, "#000000");
6724  switch_img_fill(blank_img, 0, 0, blank_img->d_w, blank_img->d_h, &bgcolor);
6725 
6726  if (fps < 15) fps = 15;
6727  frame_ms = (uint32_t) 1000 / fps;
6728  if (frame_ms <= 0) frame_ms = 66;
6729  frames = (uint32_t) ms / frame_ms;
6730 
6732  for (i = 0; i < frames; i++) {
6733  fr.img = blank_img;
6735  switch_yield(frame_ms * 1000);
6736  }
6738 
6739  switch_img_free(&blank_img);
6740 
6741 }
6742 
6744 {
6745  switch_core_session_t *session = (switch_core_session_t *) obj;
6746  switch_media_handle_t *smh;
6747  unsigned char *buf = NULL;
6748  switch_frame_t fr = { 0 };
6749  switch_rtp_engine_t *v_engine;
6751  switch_timer_t timer = { 0 };
6752  switch_video_read_flag_t read_flags = SVR_FLUSH;
6753  switch_core_session_t *b_session = NULL;
6754  switch_fps_t fps_data = { 0 };
6755  float fps = 15.0f;
6756  switch_image_t *last_frame = NULL;
6757  int last_w = 0, last_h = 0, kps = 0;
6758  switch_status_t res;
6759 
6761  return NULL;
6762  }
6763 
6764  if (!(smh = session->media_handle)) {
6766 
6767  return NULL;
6768  }
6769 
6770  res = switch_core_session_get_partner(session, &b_session);
6771  (void)res;
6772 
6774 
6775  if (b_session) {
6777  }
6778 
6779  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
6780 
6782  v_engine->thread_write_lock = switch_thread_self();
6783 
6784 
6785  buf = switch_core_session_alloc(session, buflen);
6786  fr.packet = buf;
6787  fr.packetlen = buflen;
6788  fr.data = buf + 12;
6789  fr.buflen = buflen - 12;
6791 
6792  if (smh->video_write_fh) {
6793  if (smh->video_write_fh->mm.fps) {
6794  fps = smh->video_write_fh->mm.fps;
6795  } else if (smh->video_write_fh->mm.source_fps) {
6796  fps = smh->video_write_fh->mm.source_fps;
6797  }
6798  } else if (video_globals.fps) {
6799  fps = video_globals.fps;
6800  }
6801  switch_calc_video_fps(&fps_data, fps);
6802 
6803  switch_core_timer_init(&timer, "soft", fps_data.ms, fps_data.samples, switch_core_session_get_pool(session));
6804 
6805  if (smh->video_write_fh && smh->video_write_fh->mm.source_kps) {
6806  int min = 0, max = 10000000;
6807  const char *var;
6808 
6809  kps = smh->video_write_fh->mm.source_kps;
6810 
6811  if ((var = switch_channel_get_variable(session->channel, "video_file_min_kps"))) {
6812  min = atoi(var);
6813  if (min < 0) min = 0;
6814  }
6815 
6816  if ((var = switch_channel_get_variable(session->channel, "video_file_max_kps"))) {
6817  max = atoi(var);
6818  if (max < 0) max = 10000000;
6819  }
6820 
6821  if (min && kps < min) kps = min;
6822  if (max != 10000000 && kps > max) kps = max;
6823 
6825  }
6826 
6827  while (smh->video_write_thread_running > 0 &&
6830 
6831  switch_core_timer_next(&timer);
6832 
6834 
6835  //if (smh->video_write_fh && smh->video_write_fh->mm.source_fps && smh->video_write_fh->mm.source_fps != fps) {
6836  // switch_core_timer_destroy(&timer);
6837  // switch_calc_video_fps(&fps_data, fps);
6838  // switch_core_timer_init(&timer, "soft", fps_data.ms, fps_data.samples, switch_core_session_get_pool(session));
6839  //}
6840 
6842  wstatus = switch_core_file_read_video(smh->video_write_fh, &fr, read_flags);
6843 
6844  if (wstatus == SWITCH_STATUS_BREAK) {
6845  switch_core_timer_sync(&timer);
6846  }
6847 
6848  if (wstatus == SWITCH_STATUS_SUCCESS) {
6849  if (!kps && fr.img && (last_w != fr.img->d_w || last_h != fr.img->d_h)) {
6850  kps = switch_calc_bitrate(fr.img->d_w, fr.img->d_h, 1, fps);
6852  last_w = fr.img->d_w;
6853  last_h = fr.img->d_h;
6854  }
6855 
6856  fr.timestamp = timer.samplecount;
6858 
6859  if (fr.img && smh->vid_params.d_width && smh->vid_params.d_height) {
6861  }
6862 
6864 
6865  switch_img_free(&last_frame);
6866  last_frame = fr.img;
6867  fr.img = NULL;
6868 
6869  } else if (wstatus != SWITCH_STATUS_BREAK && wstatus != SWITCH_STATUS_IGNORE) {
6871  }
6872  }
6873 
6875  }
6876 
6877  if (last_frame) {
6878  int x = 0;
6879  switch_rgb_color_t bgcolor;
6880 
6881  switch_color_set_rgb(&bgcolor, "#000000");
6882  switch_img_fill(last_frame, 0, 0, last_frame->d_w, last_frame->d_h, &bgcolor);
6883  fr.img = last_frame;
6884 
6885  for (x = 0; x < (int)(fps_data.fps / 2); x++) {
6886  switch_core_timer_next(&timer);
6887  fr.timestamp = timer.samplecount;
6890  }
6891 
6894  switch_img_free(&last_frame);
6895  }
6896 
6897  switch_core_timer_destroy(&timer);
6898 
6900 
6901  if (b_session) {
6903  switch_core_session_rwunlock(b_session);
6904  }
6905 
6906  v_engine->thread_write_lock = 0;
6908 
6910  smh->video_write_thread_running = 0;
6911 
6912  return NULL;
6913 }
6914 
6916 {
6917  switch_media_handle_t *smh;
6918  switch_rtp_engine_t *v_engine;
6919 
6920  switch_assert(session);
6921 
6922  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
6923  return SWITCH_STATUS_FALSE;
6924  }
6925 
6926  if (!(smh = session->media_handle)) {
6927  return SWITCH_STATUS_FALSE;
6928  }
6929 
6930  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
6931 
6932  if (rw == SWITCH_RW_READ) {
6934  } else {
6936  }
6937 
6938  return SWITCH_STATUS_SUCCESS;
6939 
6940 }
6941 
6943 {
6944  switch_media_handle_t *smh;
6945  switch_rtp_engine_t *v_engine;
6946 
6947  switch_assert(session);
6948 
6949  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
6950  return SWITCH_STATUS_FALSE;
6951  }
6952 
6953  if (!(smh = session->media_handle)) {
6954  return SWITCH_STATUS_FALSE;
6955  }
6956 
6957  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
6958 
6959  if (rw == SWITCH_RW_READ) {
6961  } else {
6963  }
6964 
6965  return SWITCH_STATUS_SUCCESS;
6966 }
6967 
6969 {
6970  switch_media_handle_t *smh;
6971  switch_rtp_engine_t *v_engine;
6972 
6973  switch_assert(session);
6974 
6975  if (!(smh = session->media_handle)) {
6976  return SWITCH_STATUS_FALSE;
6977  }
6978 
6979  if (!smh->video_read_fh && !smh->video_write_fh && !switch_channel_test_flag(session->channel, CF_VIDEO)) {
6980  return SWITCH_STATUS_FALSE;
6981  }
6982 
6983  if (fh && !switch_core_file_has_video(fh, SWITCH_TRUE)) {
6984  return SWITCH_STATUS_FALSE;
6985  }
6986 
6987  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
6988 
6990 
6991  //if (!v_engine->media_thread) {
6992  // return SWITCH_STATUS_FALSE;
6993  //}
6994 
6995 
6996 
6997  if (rw == SWITCH_RW_READ) {
6999 
7000  if (fh && smh->video_read_fh) {
7001  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "File is already open\n");
7003  return SWITCH_STATUS_FALSE;
7004  }
7005 
7006 
7007  if (fh) {
7010  } else if (smh->video_read_fh) {
7013  }
7014 
7015  if (!fh) {
7017  }
7018 
7019  smh->video_read_fh = fh;
7020 
7022 
7023  } else {
7024  if (!fh && smh->video_write_thread) {
7025  if (smh->video_write_thread_running > 0) {
7026  smh->video_write_thread_running = -1;
7027  }
7028  }
7029 
7031 
7032  if (fh && smh->video_write_fh) {
7033  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "File is already open\n");
7034  smh->video_write_fh = fh;
7036  return SWITCH_STATUS_SUCCESS;
7037  }
7038 
7039  if (fh) {
7041  } else {
7043  }
7044 
7047 
7048  if (fh) {
7049  switch_threadattr_t *thd_attr = NULL;
7050  //switch_core_session_write_blank_video(session, 500);
7053  smh->video_write_thread_running = 1;
7055  }
7056 
7057  if (!fh && smh->video_write_thread) {
7058  switch_status_t st;
7059 
7060  if (smh->video_write_thread_running > 0) {
7061  smh->video_write_thread_running = -1;
7062  }
7066  smh->video_write_thread = NULL;
7067  //switch_core_session_write_blank_video(session, 500);
7068  }
7069 
7070  smh->video_write_fh = fh;
7071 
7073  }
7074 
7075  if (!fh) switch_channel_video_sync(session->channel);
7076 
7078 
7079 
7080  return SWITCH_STATUS_SUCCESS;
7081 }
7082 
7083 int next_cpu(void)
7084 {
7085  int x = 0;
7086 
7087  switch_mutex_lock(video_globals.mutex);
7088  x = video_globals.cur_cpu++;
7089  if (video_globals.cur_cpu == video_globals.cpu_count) {
7090  video_globals.cur_cpu = 0;
7091  }
7092  switch_mutex_unlock(video_globals.mutex);
7093  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Binding to CPU %d\n", x);
7094 
7095  return x;
7096 }
7097 
7099 {
7100  if (video_globals.cpu_count > 1) {
7102  }
7103 }
7104 
7106 {
7109  switch_media_handle_t *smh;
7110 
7111  switch_assert(session != NULL);
7112 
7113  if ((smh = session->media_handle)) {
7115 
7116  if (a_engine && a_engine->write_fb && !(flags & SWITCH_IO_FLAG_QUEUED)) {
7117  switch_frame_t *dupframe = NULL;
7118 
7119  if (switch_frame_buffer_dup(a_engine->write_fb, frame, &dupframe) == SWITCH_STATUS_SUCCESS) {
7120  switch_frame_buffer_push(a_engine->write_fb, dupframe);
7121  dupframe = NULL;
7122  return SWITCH_STATUS_SUCCESS;
7123  }
7124  }
7125  }
7126 
7127  if (session->bugs && !(frame->flags & SFF_NOT_AUDIO)) {
7128  switch_media_bug_t *bp;
7130  int prune = 0;
7131 
7133 
7134  for (bp = session->bugs; bp; bp = bp->next) {
7135  ok = SWITCH_TRUE;
7136 
7138  continue;
7139  }
7140 
7142  continue;
7143  }
7144  if (switch_test_flag(bp, SMBF_PRUNE)) {
7145  prune++;
7146  continue;
7147  }
7148 
7149  if (bp->ready) {
7151  if (bp->callback) {
7152  bp->native_write_frame = frame;
7154  bp->native_write_frame = NULL;
7155  }
7156  }
7157  }
7158 
7159  if ((bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) || ok == SWITCH_FALSE) {
7161  prune++;
7162  }
7163  }
7165 
7166  if (prune) {
7167  switch_core_media_bug_prune(session);
7168  }
7169  }
7170 
7171 
7172  if (session->endpoint_interface->io_routines->write_frame) {
7173  if ((status = session->endpoint_interface->io_routines->write_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
7174  for (ptr = session->event_hooks.write_frame; ptr; ptr = ptr->next) {
7175  if ((status = ptr->write_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
7176  break;
7177  }
7178  }
7179  }
7180  }
7181 
7182  return status;
7183 }
7184 
7185 
7187 {
7188  struct media_helper *mh = obj;
7190  switch_media_handle_t *smh;
7191  switch_rtp_engine_t *a_engine = NULL;
7192  switch_codec_implementation_t write_impl;
7193  switch_timer_t timer = {0};
7194 
7196  return NULL;
7197  }
7198 
7199  if (!(smh = session->media_handle)) {
7201  return NULL;
7202  }
7203 
7204  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
7205  a_engine->thread_id = switch_thread_self();
7206 
7207 
7208  write_impl = session->write_impl;
7209 
7210  switch_core_timer_init(&timer, "soft", write_impl.microseconds_per_packet / 1000,
7211  write_impl.samples_per_packet, switch_core_session_get_pool(session));
7212 
7213  mh->up = 1;
7214 
7215  switch_frame_buffer_create(&a_engine->write_fb, 500);
7216 
7217  while(switch_channel_up_nosig(session->channel) && mh->up == 1) {
7218  void *pop;
7219 
7220  if (session->write_impl.microseconds_per_packet != write_impl.microseconds_per_packet ||
7221  session->write_impl.samples_per_packet != write_impl.samples_per_packet) {
7222 
7223 
7224  write_impl = session->write_impl;
7225  switch_core_timer_destroy(&timer);
7226  switch_core_timer_init(&timer, "soft", write_impl.microseconds_per_packet / 1000,
7227  write_impl.samples_per_packet, switch_core_session_get_pool(session));
7228 
7229  }
7230 
7231  switch_core_timer_next(&timer);
7232 
7233  if (switch_frame_buffer_trypop(a_engine->write_fb, &pop) == SWITCH_STATUS_SUCCESS && pop) {
7234  switch_frame_t *frame = (switch_frame_t *)pop;
7235 
7236  if ((switch_size_t)pop == 1) {
7237  break;
7238  }
7239 
7240  perform_write(session, frame, SWITCH_IO_FLAG_QUEUED, 0);
7241  switch_frame_buffer_free(a_engine->write_fb, &frame);
7242  }
7243  }
7244 
7246  mh->up = 0;
7248 
7249  switch_core_timer_destroy(&timer);
7250 
7252  return NULL;
7253 }
7254 
7256 {
7257  switch_threadattr_t *thd_attr = NULL;
7259  switch_rtp_engine_t *a_engine = NULL;
7260  switch_media_handle_t *smh;
7261 
7262  if (!switch_channel_test_flag(session->channel, CF_AUDIO)) {
7263  return SWITCH_STATUS_NOTIMPL;
7264  }
7265 
7266  if (!(smh = session->media_handle)) {
7267  return SWITCH_STATUS_FALSE;
7268  }
7269 
7270  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
7271 
7272  if (a_engine->media_thread) {
7273  return SWITCH_STATUS_INUSE;
7274  }
7275 
7277 
7278  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Starting Audio write thread\n", switch_core_session_get_name(session));
7279 
7280  a_engine->mh.session = session;
7281  switch_threadattr_create(&thd_attr, pool);
7283 
7284  switch_thread_cond_create(&a_engine->mh.cond, pool);
7286  switch_thread_create(&a_engine->media_thread, thd_attr, audio_write_thread, &a_engine->mh, switch_core_session_get_pool(session));
7287 
7289  return SWITCH_STATUS_SUCCESS;
7290 }
7291 
7292 
7293 
7295 {
7296  struct media_helper *mh = obj;
7298  switch_channel_t *channel;
7299  switch_status_t status;
7300  switch_frame_t *read_frame = NULL;
7301  switch_media_handle_t *smh;
7302  switch_rtp_engine_t *t_engine = NULL;
7303  unsigned char CR[] = TEXT_UNICODE_LINEFEED;
7304  switch_frame_t cr_frame = { 0 };
7305 
7306 
7307  session = mh->session;
7308 
7310  mh->ready = -1;
7311  return NULL;
7312  }
7313 
7314  if (!(smh = session->media_handle)) {
7316  mh->ready = -1;
7317  return NULL;
7318  }
7319 
7320  mh->ready = 1;
7321 
7322  channel = switch_core_session_get_channel(session);
7323 
7324  if (switch_channel_var_true(session->channel, "fire_text_events")) {
7326  }
7327 
7328  cr_frame.data = CR;
7329  cr_frame.datalen = 3;
7330 
7331  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
7332  t_engine->thread_id = switch_thread_self();
7333 
7334  mh->up = 1;
7335 
7337 
7338  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Text thread started.\n", switch_channel_get_name(session->channel));
7339 
7340  if (!switch_channel_test_flag(channel, CF_MSRP)) {
7341  switch_core_session_write_text_frame(session, &cr_frame, 0, 0);
7342  }
7343 
7344  while (switch_channel_up_nosig(channel)) {
7345 
7346  if (t_engine->engine_function) {
7347  int run = 0;
7348 
7350  if (t_engine->engine_function_running == 0) {
7351  t_engine->engine_function_running = 1;
7352  run = 1;
7353  }
7355 
7356  if (run) {
7357  t_engine->engine_function(session, t_engine->engine_user_data);
7359  t_engine->engine_function = NULL;
7360  t_engine->engine_user_data = NULL;
7361  t_engine->engine_function_running = 0;
7363  }
7364  }
7365 
7367 
7368  status = switch_core_session_read_text_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
7369 
7370  if (!SWITCH_READ_ACCEPTABLE(status)) {
7371  switch_cond_next();
7372  continue;
7373  }
7374 
7375  if (!switch_test_flag(read_frame, SFF_CNG)) {
7377  switch_core_session_write_text_frame(session, read_frame, 0, 0);
7378  }
7379  }
7380  }
7381 
7382  switch_core_session_write_text_frame(session, NULL, 0, 0);
7383 
7384 
7385  }
7386 
7388 
7390 
7391  mh->up = 0;
7392  return NULL;
7393 }
7394 
7395 
7397 {
7398  switch_threadattr_t *thd_attr = NULL;
7400  switch_rtp_engine_t *t_engine = NULL;
7401  switch_media_handle_t *smh;
7402 
7403  if (!switch_channel_test_flag(session->channel, CF_HAS_TEXT)) {
7404  return SWITCH_STATUS_NOTIMPL;
7405  }
7406 
7407  if (!(smh = session->media_handle)) {
7408  return SWITCH_STATUS_FALSE;
7409  }
7410 
7411  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
7412 
7414 
7415  if (t_engine->media_thread) {
7417  return SWITCH_STATUS_FALSE;
7418  }
7419 
7420  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Starting Text thread\n", switch_core_session_get_name(session));
7421 
7422  if (t_engine->rtp_session) {
7424  }
7425 
7426  t_engine->mh.session = session;
7427  switch_threadattr_create(&thd_attr, pool);
7429 
7430  switch_thread_cond_create(&t_engine->mh.cond, pool);
7432  //switch_mutex_init(&t_engine->mh.file_read_mutex, SWITCH_MUTEX_NESTED, pool);
7433  //switch_mutex_init(&t_engine->mh.file_write_mutex, SWITCH_MUTEX_NESTED, pool);
7434  //switch_mutex_init(&smh->read_mutex[SWITCH_MEDIA_TYPE_TEXT], SWITCH_MUTEX_NESTED, pool);
7435  //switch_mutex_init(&smh->write_mutex[SWITCH_MEDIA_TYPE_TEXT], SWITCH_MUTEX_NESTED, pool);
7436 
7437  t_engine->mh.ready = 0;
7438 
7439  if (switch_thread_create(&t_engine->media_thread, thd_attr, text_helper_thread, &t_engine->mh,
7441  while(!t_engine->mh.ready) {
7442  switch_cond_next();
7443  }
7444  }
7445 
7447  return SWITCH_STATUS_SUCCESS;
7448 }
7449 
7451 {
7452  struct media_helper *mh = obj;
7454  switch_channel_t *channel;
7455  switch_status_t status;
7456  switch_frame_t *read_frame = NULL;
7457  switch_media_handle_t *smh;
7458  uint32_t loops = 0, xloops = 0;
7459  switch_image_t *blank_img = NULL;
7460  switch_frame_t fr = { 0 };
7461  unsigned char *buf = NULL;
7462  switch_rgb_color_t bgcolor;
7463  switch_rtp_engine_t *v_engine = NULL;
7464  const char *var;
7466  int blank_enabled = 1;
7467 
7468  session = mh->session;
7469 
7471  mh->ready = -1;
7472  return NULL;
7473  }
7474 
7475  if (!(smh = session->media_handle)) {
7477  mh->ready = -1;
7478  return NULL;
7479  }
7480 
7481  mh->ready = 1;
7482 
7483  channel = switch_core_session_get_channel(session);
7484 
7486 
7487  if ((var = switch_channel_get_variable(session->channel, "core_video_blank_image"))) {
7488  if (switch_false(var)) {
7489  blank_enabled = 0;
7490  } else {
7491  blank_img = switch_img_read_png(var, SWITCH_IMG_FMT_I420);
7492  }
7493  }
7494 
7495  if (!blank_img) {
7496  switch_color_set_rgb(&bgcolor, "#000000");
7497  if ((blank_img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, 352, 288, 1))) {
7498  switch_img_fill(blank_img, 0, 0, blank_img->d_w, blank_img->d_h, &bgcolor);
7499  }
7500  }
7501 
7502 
7503 
7504  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
7505  v_engine->thread_id = switch_thread_self();
7506 
7507  mh->up = 1;
7509 
7511 
7512  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread started. Echo is %s\n",
7513  switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
7515 
7516  buf = switch_core_session_alloc(session, buflen);
7517  fr.packet = buf;
7518  fr.packetlen = buflen;
7519  fr.data = buf + 12;
7520  fr.buflen = buflen - 12;
7521 
7523 
7524  while (switch_channel_up_nosig(channel)) {
7525  int send_blank = 0;
7526 
7527  if (!switch_channel_test_flag(channel, CF_VIDEO)) {
7528  if ((++loops % 100) == 0) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Waiting for video......\n");
7529  switch_yield(20000);
7530  continue;
7531  }
7532 
7533  if (!switch_channel_test_flag(channel, CF_VIDEO_READY) &&
7536  }
7537 
7539  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread paused. Echo is %s\n",
7540  switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
7542  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Video thread resumed Echo is %s\n",
7543  switch_channel_get_name(session->channel), switch_channel_test_flag(channel, CF_VIDEO_ECHO) ? "on" : "off");
7545  }
7546 
7548  continue;
7549  }
7550 
7551  if (!switch_channel_media_up(session->channel)) {
7552  switch_yield(10000);
7553  continue;
7554  }
7555 
7556  if (v_engine->engine_function) {
7557  int run = 0;
7558 
7560  if (v_engine->engine_function_running == 0) {
7561  v_engine->engine_function_running = 1;
7562  run = 1;
7563  }
7565 
7566  if (run) {
7567  v_engine->engine_function(session, v_engine->engine_user_data);
7569  v_engine->engine_function = NULL;
7570  v_engine->engine_user_data = NULL;
7571  v_engine->engine_function_running = 0;
7573  }
7574  }
7575 
7576  status = switch_core_session_read_video_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
7577 
7578  if (!SWITCH_READ_ACCEPTABLE(status)) {
7579  switch_cond_next();
7580  continue;
7581  }
7582 
7583  send_blank = blank_enabled || switch_channel_test_flag(channel, CF_VIDEO_ECHO);
7584 
7585  if (switch_channel_test_flag(channel, CF_VIDEO_READY) && !switch_test_flag(read_frame, SFF_CNG)) {
7587  if (smh->video_read_fh && switch_test_flag(smh->video_read_fh, SWITCH_FILE_OPEN) && read_frame->img) {
7588  smh->video_read_fh->mm.fps = smh->vid_params.fps;
7589  switch_core_file_write_video(smh->video_read_fh, read_frame);
7590  }
7592  }
7593 
7595  send_blank = 0;
7596  }
7597 
7598  if (send_blank) {
7599  if (read_frame && (switch_channel_test_flag(channel, CF_VIDEO_ECHO))) {
7601  } else if (blank_img) {
7602  fr.img = blank_img;
7603  switch_yield(10000);
7605  }
7606  }
7607  }
7608 
7609  switch_img_free(&blank_img);
7610 
7612 
7615 
7616  mh->up = 0;
7617  return NULL;
7618 }
7619 
7621 {
7622  switch_threadattr_t *thd_attr = NULL;
7624  switch_rtp_engine_t *v_engine = NULL;
7625  switch_media_handle_t *smh;
7626 
7627  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
7628  return SWITCH_STATUS_NOTIMPL;
7629  }
7630 
7631  if (!(smh = session->media_handle)) {
7632  return SWITCH_STATUS_FALSE;
7633  }
7634 
7635  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
7636 
7638 
7639  if (v_engine->media_thread) {
7641  return SWITCH_STATUS_FALSE;
7642  }
7643 
7644  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Starting Video thread\n", switch_core_session_get_name(session));
7645 
7646  if (v_engine->rtp_session) {
7648  }
7649 
7650  v_engine->mh.session = session;
7651  switch_threadattr_create(&thd_attr, pool);
7653 
7654  switch_thread_cond_create(&v_engine->mh.cond, pool);
7660  v_engine->mh.ready = 0;
7661 
7662  if (switch_thread_create(&v_engine->media_thread, thd_attr, video_helper_thread, &v_engine->mh,
7664  while(!v_engine->mh.ready) {
7665  switch_cond_next();
7666  }
7667  }
7668 
7670  return SWITCH_STATUS_SUCCESS;
7671 }
7672 
7674 {
7675  switch_media_handle_t *smh;
7676  switch_rtp_engine_t *engine;
7677 
7678  if (!(smh = session->media_handle)) {
7679  return;
7680  }
7681 
7682  engine = &smh->engines[type];
7683 
7684  if (type == SWITCH_MEDIA_TYPE_VIDEO) {
7686  }
7687 
7688  if (type == SWITCH_MEDIA_TYPE_TEXT) {
7690  }
7691 
7693  if (!engine->engine_function_running) {
7694  engine->engine_function = engine_function;
7695  engine->engine_user_data = user_data;
7697  }
7699 }
7700 
7702 {
7703  switch_media_handle_t *smh;
7704  int r;
7705  switch_rtp_engine_t *engine;
7706 
7707  if (!(smh = session->media_handle)) {
7708  return 0;
7709  }
7710 
7711  engine = &smh->engines[type];
7712 
7714  r = (engine->engine_function_running > 0);
7716 
7717  return r;
7718 }
7719 
7721 {
7722  switch_media_handle_t *smh;
7723  switch_rtp_engine_t *engine;
7724 
7725  if (!(smh = session->media_handle)) {
7726  return;
7727  }
7728 
7729  engine = &smh->engines[type];
7730 
7732  if (engine->engine_function_running > 0) {
7733  engine->engine_function_running = -1;
7734  }
7736 
7737  while(engine->engine_function_running != 0) {
7738  switch_yield(10000);
7739  }
7740 }
7741 
7743 {
7744  switch_rtp_engine_t *v_engine;
7745  switch_media_handle_t *smh;
7746 
7747  switch_assert(session);
7748 
7749  if (!(smh = session->media_handle)) {
7750  return SWITCH_FALSE;
7751  }
7752 
7753  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
7754 
7756 }
7757 
7758 
7760 {
7761  const char *var;
7762  switch_media_handle_t *smh;
7763 
7764  if (!(smh = session->media_handle)) {
7765  return;
7766  }
7767 
7768  if ((var = switch_channel_get_variable(session->channel, "rtp_media_autofix_timing"))) {
7769  if (switch_true(var)) {
7771  } else {
7773  }
7774  }
7775 }
7776 
7777 //?
7778 #define RA_PTR_LEN 512
7780 {
7781  const char *err;
7782  char rip[RA_PTR_LEN] = "";
7783  char rp[RA_PTR_LEN] = "";
7784  char rvp[RA_PTR_LEN] = "";
7785  char rtp[RA_PTR_LEN] = "";
7786  char *p, *ip_ptr = NULL, *port_ptr = NULL, *vid_port_ptr = NULL, *text_port_ptr = NULL, *pe;
7787  int x;
7788  const char *val;
7790  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
7791  switch_media_handle_t *smh;
7792 
7793  switch_assert(session);
7794 
7795  if (!(smh = session->media_handle)) {
7796  return SWITCH_STATUS_FALSE;
7797  }
7798 
7799  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
7800  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
7801  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
7802 
7803  if (zstr(sdp_str)) {
7804  sdp_str = smh->mparams->remote_sdp_str;
7805  }
7806 
7807  if (zstr(sdp_str)) {
7808  goto end;
7809  }
7810 
7811  if ((p = (char *) switch_stristr("c=IN IP4 ", sdp_str)) || (p = (char *) switch_stristr("c=IN IP6 ", sdp_str))) {
7812  ip_ptr = p + 9;
7813  }
7814 
7815  if ((p = (char *) switch_stristr("m=audio ", sdp_str))) {
7816  port_ptr = p + 8;
7817  }
7818 
7819  if ((p = (char *) switch_stristr("m=image ", sdp_str))) {
7820  char *tmp = p + 8;
7821 
7822  if (tmp && atoi(tmp)) {
7823  port_ptr = tmp;
7824  }
7825  }
7826 
7827  if ((p = (char *) switch_stristr("m=video ", sdp_str))) {
7828  vid_port_ptr = p + 8;
7829  }
7830 
7831  if ((p = (char *) switch_stristr("m=text ", sdp_str))) {
7832  text_port_ptr = p + 7;
7833  }
7834 
7835  if (!(ip_ptr && port_ptr)) {
7836  goto end;
7837  }
7838 
7839  p = ip_ptr;
7840  pe = p + strlen(p);
7841  x = 0;
7842  while (x < sizeof(rip) - 1 && p && *p && ((*p >= '0' && *p <= '9') || *p == '.' || *p == ':' || (*p >= 'a' && *p <= 'f') || (*p >= 'A' && *p <= 'F'))) {
7843  rip[x++] = *p;
7844  p++;
7845  if (p >= pe) {
7846  goto end;
7847  }
7848  }
7849 
7850  if (port_ptr) {
7851  p = port_ptr;
7852  x = 0;
7853  while (x < sizeof(rp) - 1 && p && *p && (*p >= '0' && *p <= '9')) {
7854  rp[x++] = *p;
7855  p++;
7856  if (p >= pe) {
7857  goto end;
7858  }
7859  }
7860  }
7861 
7862  if (vid_port_ptr) {
7863  p = vid_port_ptr;
7864  x = 0;
7865  while (x < sizeof(rvp) - 1 && p && *p && (*p >= '0' && *p <= '9')) {
7866  rvp[x++] = *p;
7867  p++;
7868  if (p >= pe) {
7869  goto end;
7870  }
7871  }
7872  }
7873 
7874  if (text_port_ptr) {
7875  p = text_port_ptr;
7876  x = 0;
7877  while (x < sizeof(rtp) - 1 && p && *p && (*p >= '0' && *p <= '9')) {
7878  rtp[x++] = *p;
7879  p++;
7880  if (p >= pe) {
7881  goto end;
7882  }
7883  }
7884  }
7885 
7886  if (!(*rip && *rp)) {
7888  goto end;
7889  }
7890 
7891  a_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, rip);
7892  a_engine->cur_payload_map->remote_sdp_port = (switch_port_t) atoi(rp);
7893 
7894  if (*rvp) {
7895  v_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, rip);
7896  v_engine->cur_payload_map->remote_sdp_port = (switch_port_t) atoi(rvp);
7899  }
7900 
7901  if (*rtp) {
7902  t_engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(session, rip);
7903  t_engine->cur_payload_map->remote_sdp_port = (switch_port_t) atoi(rtp);
7906  }
7907 
7908  if (v_engine->cur_payload_map && v_engine->cur_payload_map->remote_sdp_ip && v_engine->cur_payload_map->remote_sdp_port) {
7909  if (!strcmp(v_engine->cur_payload_map->remote_sdp_ip, rip) && atoi(rvp) == v_engine->cur_payload_map->remote_sdp_port) {
7910  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote video address:port [%s:%d] has not changed.\n",
7912  } else {
7915  if (switch_rtp_ready(v_engine->rtp_session)) {
7916  const char *rport = NULL;
7917  switch_port_t remote_rtcp_port = v_engine->remote_rtcp_port;
7918 
7919  if (!remote_rtcp_port) {
7920  if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_video_rtcp_port"))) {
7921  remote_rtcp_port = (switch_port_t)atoi(rport);
7922  }
7923  }
7924 
7925 
7927  v_engine->cur_payload_map->remote_sdp_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
7928  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", err);
7929  } else {
7930  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "VIDEO RTP CHANGING DEST TO: [%s:%d]\n",
7933  v_engine->check_frames = 0;
7934  }
7935  }
7936  }
7937  }
7939  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
7940  v_engine->rtp_session &&
7942  /* Reactivate the NAT buster flag. */
7944  }
7945  }
7946 
7947  if (t_engine->cur_payload_map && t_engine->cur_payload_map->remote_sdp_ip && t_engine->cur_payload_map->remote_sdp_port) {
7948  if (!strcmp(t_engine->cur_payload_map->remote_sdp_ip, rip) && atoi(rvp) == t_engine->cur_payload_map->remote_sdp_port) {
7949  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote text address:port [%s:%d] has not changed.\n",
7951  } else {
7954  if (switch_rtp_ready(t_engine->rtp_session)) {
7955  const char *rport = NULL;
7956  switch_port_t remote_rtcp_port = t_engine->remote_rtcp_port;
7957 
7958  if (!remote_rtcp_port) {
7959  if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_text_rtcp_port"))) {
7960  remote_rtcp_port = (switch_port_t)atoi(rport);
7961  }
7962  }
7963 
7964 
7966  t_engine->cur_payload_map->remote_sdp_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
7967  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "TEXT RTP REPORTS ERROR: [%s]\n", err);
7968  } else {
7969  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "TEXT RTP CHANGING DEST TO: [%s:%d]\n",
7972  t_engine->check_frames = 0;
7973  }
7974  }
7975  }
7976  }
7978  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
7979  t_engine->rtp_session &&
7981  /* Reactivate the NAT buster flag. */
7983  }
7984  }
7985 
7986  if (switch_rtp_ready(a_engine->rtp_session)) {
7987  char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
7988  switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
7989  const char *rport = NULL;
7990  switch_port_t remote_rtcp_port = 0;
7991 
7992  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) {
7993  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote address:port [%s:%d] has not changed.\n",
7996  } else if (remote_host && ( (strcmp(remote_host, "0.0.0.0") == 0) ||
7997  (strcmp(a_engine->cur_payload_map->remote_sdp_ip, "0.0.0.0") == 0))) {
7998 
8000  "Remote address changed from [%s] to [%s]. Ignoring...\n",
8001  a_engine->cur_payload_map->remote_sdp_ip, remote_host);
8003  }
8004 
8005  if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_audio_rtcp_port"))) {
8006  remote_rtcp_port = (switch_port_t)atoi(rport);
8007  }
8008 
8009 
8011  a_engine->cur_payload_map->remote_sdp_port, remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
8012  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
8013  status = SWITCH_STATUS_GENERR;
8014  } else {
8015  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n",
8018  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
8020  /* Reactivate the NAT buster flag. */
8022  }
8024  a_engine->check_frames = 0;
8025  }
8026  status = SWITCH_STATUS_SUCCESS;
8027  }
8028  }
8029 
8030  end:
8031 
8032  return status;
8033 }
8034 
8035 //?
8037 {
8038  switch_assert(network_ip);
8039 
8040  return (smh->mparams->extsipip &&
8041  !switch_check_network_list_ip(network_ip, "loopback.auto") &&
8042  !switch_check_network_list_ip(network_ip, smh->mparams->local_network));
8043 }
8044 
8045 //?
8047 
8048 {
8049  char *error = "";
8051  int x;
8052  switch_port_t myport = *port;
8054  char *stun_ip = NULL;
8055  switch_media_handle_t *smh;
8057 
8058  switch_assert(session);
8059 
8060  if (!(smh = session->media_handle)) {
8061  return SWITCH_STATUS_FALSE;
8062  }
8063 
8064  if (!sourceip) {
8065  return status;
8066  }
8067 
8068  if (!strncasecmp(sourceip, "host:", 5)) {
8069  status = (*ip = switch_stun_host_lookup(sourceip + 5, pool)) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
8070  } else if (!strncasecmp(sourceip, "stun:", 5)) {
8071  char *p;
8072 
8073  stun_ip = strdup(sourceip + 5);
8074 
8075  if ((p = strchr(stun_ip, ':'))) {
8076  int iport;
8077  *p++ = '\0';
8078  iport = atoi(p);
8079  if (iport > 0 && iport < 0xFFFF) {
8080  stun_port = (switch_port_t) iport;
8081  }
8082  }
8083 
8084  if (zstr(stun_ip)) {
8085  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! NO STUN SERVER\n");
8086  goto out;
8087  }
8088 
8089  for (x = 0; x < 5; x++) {
8090  if ((status = switch_stun_lookup(ip, port, stun_ip, stun_port, &error, pool)) != SWITCH_STATUS_SUCCESS) {
8091  switch_yield(100000);
8092  } else {
8093  break;
8094  }
8095  }
8096  if (status != SWITCH_STATUS_SUCCESS) {
8097  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! %s:%d [%s]\n", stun_ip, stun_port, error);
8098  goto out;
8099  }
8100  if (!*ip) {
8101  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! No IP returned\n");
8102  goto out;
8103  }
8104  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "STUN Success [%s]:[%d]\n", *ip, *port);
8105  status = SWITCH_STATUS_SUCCESS;
8106 
8107  if (myport == *port && !strcmp(*ip, smh->mparams->rtpip)) {
8108  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "STUN Not Required ip and port match. [%s]:[%d]\n", *ip, *port);
8109  } else {
8110  smh->mparams->stun_ip = switch_core_session_strdup(session, stun_ip);
8111  smh->mparams->stun_port = stun_port;
8112  smh->mparams->stun_flags |= STUN_FLAG_SET;
8113  }
8114  } else {
8115  *ip = (char *) sourceip;
8116  status = SWITCH_STATUS_SUCCESS;
8117  }
8118 
8119  out:
8120 
8121  switch_safe_free(stun_ip);
8122 
8123  return status;
8124 }
8125 
8126 //?
8128 {
8129  switch_rtp_engine_t *engine;
8130  switch_media_handle_t *smh;
8131 
8132  switch_assert(session);
8133 
8134  if (!(smh = session->media_handle)) {
8135  return;
8136  }
8137 
8138  engine = &smh->engines[type];
8139 
8140  engine->check_frames = 0;
8141  engine->last_ts = 0;
8142  engine->last_seq = 0;
8143 }
8144 
8145 
8146 
8147 //?
8149 {
8150  char *lookup_rtpip; /* Pointer to externally looked up address */
8151  switch_port_t sdp_port; /* The external port to be sent in the SDP */
8152  const char *use_ip = NULL; /* The external IP to be sent in the SDP */
8153  switch_rtp_engine_t *engine;
8154  switch_media_handle_t *smh;
8155  const char *tstr = switch_media_type2str(type);
8156  char vname[128] = "";
8157 
8158  switch_assert(session);
8159 
8160  if (!(smh = session->media_handle)) {
8161  return SWITCH_STATUS_FALSE;
8162  }
8163 
8164  engine = &smh->engines[type];
8165 
8166  lookup_rtpip = smh->mparams->rtpip;
8167 
8168  if (!lookup_rtpip) {
8169  return SWITCH_STATUS_FALSE;
8170  }
8171 
8172  /* Don't do anything if we're in proxy mode or if a (remote) port already has been found */
8173  if (!force) {
8176  return SWITCH_STATUS_SUCCESS;
8177  }
8178  }
8179 
8180  /* Always too late when RTP has already started */
8181  if (engine->rtp_session) {
8182  return SWITCH_STATUS_SUCCESS;
8183  }
8184 
8185  /* Release the local sdp port */
8186  if (engine->local_sdp_port) {
8188  }
8189 
8190  /* Request a local port from the core's allocator */
8191  if (!(engine->local_sdp_port = switch_rtp_request_port(smh->mparams->rtpip))) {
8192  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "No %s RTP ports available!\n", tstr);
8193  return SWITCH_STATUS_FALSE;
8194  }
8195 
8196  engine->local_sdp_ip = smh->mparams->rtpip;
8197 
8198 
8199  sdp_port = engine->local_sdp_port;
8200 
8201  /* Check if NAT is detected */
8202  if (!zstr(smh->mparams->remote_ip) && switch_core_media_check_nat(smh, smh->mparams->remote_ip)) {
8203  /* Yes, map the port through switch_nat */
8205 
8206  switch_snprintf(vname, sizeof(vname), "rtp_adv_%s_ip", tstr);
8207 
8208  /* Find an IP address to use */
8209  if (!(use_ip = switch_channel_get_variable(session->channel, vname))
8210  && !zstr(smh->mparams->extrtpip)) {
8211  use_ip = smh->mparams->extrtpip;
8212  }
8213 
8214  if (use_ip) {
8215  if (switch_core_media_ext_address_lookup(session, &lookup_rtpip, &sdp_port, use_ip) != SWITCH_STATUS_SUCCESS) {
8216  /* Address lookup was required and fail (external ip was "host:..." or "stun:...") */
8217  return SWITCH_STATUS_FALSE;
8218  } else {
8219  /* Address properly resolved, use it as external ip */
8220  use_ip = lookup_rtpip;
8221  }
8222  } else {
8223  /* No external ip found, use the profile's rtp ip */
8224  use_ip = smh->mparams->rtpip;
8225  }
8226  } else {
8227  /* No NAT traversal required, use the profile's rtp ip */
8228  use_ip = smh->mparams->rtpip;
8229  }
8230 
8231  if (zstr(smh->mparams->remote_ip)) { /* no remote_ip, we're originating */
8232  if (!zstr(smh->mparams->extrtpip)) { /* and we've got an ext-rtp-ip, eg, from verto config */
8233  use_ip = smh->mparams->extrtpip; /* let's use it for composing local sdp to send to client */
8234  /*
8235  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,
8236  "%s will use %s instead of %s in SDP, because we're originating and we have an ext-rtp-ip setting\n",
8237  switch_channel_get_name(smh->session->channel), smh->mparams->extrtpip, smh->mparams->rtpip);
8238  */
8239  }
8240  }
8241  engine->adv_sdp_port = sdp_port;
8242  engine->adv_sdp_ip = smh->mparams->adv_sdp_audio_ip = smh->mparams->extrtpip = switch_core_session_strdup(session, use_ip);
8243 
8244  if (type == SWITCH_MEDIA_TYPE_AUDIO) {
8248  } else if (type == SWITCH_MEDIA_TYPE_VIDEO) {
8251  } else if (type == SWITCH_MEDIA_TYPE_TEXT) {
8254  }
8255 
8256 
8257  return SWITCH_STATUS_SUCCESS;
8258 }
8259 
8261 {
8263  switch_media_handle_t *smh;
8264 
8265  if (!(smh = session->media_handle)) {
8266  return SWITCH_STATUS_FALSE;
8267  }
8268 
8269  if (zstr(smh->mparams->rtpip)) {
8270 
8271  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no media ip\n",
8274 
8275  return SWITCH_STATUS_FALSE;
8276  }
8277 
8278  if (audio && (status = switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_AUDIO, 0)) == SWITCH_STATUS_SUCCESS) {
8279  if (video) {
8283  }
8284  }
8285  }
8286 
8287  return status;
8288 }
8289 
8290 
8291 
8292 //?
8294 {
8295  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
8296  switch_media_handle_t *smh;
8297 
8298  switch_assert(session);
8299 
8300  if (!(smh = session->media_handle)) {
8301  return;
8302  }
8303 
8304  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
8305  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
8306  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
8307 
8308  if (t_engine->tf) {
8309  switch_rtp_text_factory_destroy(&t_engine->tf);
8310  }
8311 
8312  if (a_engine->media_thread) {
8313  switch_status_t st;
8314 
8316  if (a_engine->mh.up && a_engine->write_fb) {
8317  switch_frame_buffer_push(a_engine->write_fb, (void *) 1);
8318  }
8319  a_engine->mh.up = 0;
8321 
8322  switch_thread_join(&st, a_engine->media_thread);
8323  a_engine->media_thread = NULL;
8324  }
8325 
8326  if (v_engine->media_thread) {
8327  switch_status_t st;
8329 
8330  v_engine->mh.up = 0;
8331  switch_thread_join(&st, v_engine->media_thread);
8332  v_engine->media_thread = NULL;
8333  }
8334 
8335  if (v_engine->rtp_session) {
8336  switch_rtp_destroy(&v_engine->rtp_session);
8337  } else if (v_engine->local_sdp_port) {
8339  }
8340 
8341 
8342  if (v_engine->local_sdp_port > 0 && !zstr(smh->mparams->remote_ip) &&
8346  }
8347 
8348 
8349  if (t_engine->media_thread) {
8350  switch_status_t st;
8351 
8352  t_engine->mh.up = 0;
8353  switch_thread_join(&st, t_engine->media_thread);
8354  t_engine->media_thread = NULL;
8355  }
8356 
8357 
8358  if (t_engine->rtp_session) {
8359  switch_rtp_destroy(&t_engine->rtp_session);
8360  } else if (t_engine->local_sdp_port) {
8362  }
8363 
8364 
8365  if (t_engine->local_sdp_port > 0 && !zstr(smh->mparams->remote_ip) &&
8369  }
8370 
8371 
8372  if (a_engine->rtp_session) {
8373  switch_rtp_destroy(&a_engine->rtp_session);
8374  } else if (a_engine->local_sdp_port) {
8376  }
8377 
8378  if (a_engine->local_sdp_port > 0 && !zstr(smh->mparams->remote_ip) &&
8382  }
8383 
8384 }
8385 
8386 
8387 //?
8389 {
8390  switch_media_handle_t *smh;
8391  switch_rtp_engine_t *engine;
8392  char tmp[33] = "";
8393 
8394  switch_assert(session);
8395 
8396  if (!(smh = session->media_handle)) {
8397  return;
8398  }
8399 
8400  engine = &smh->engines[type];
8401 
8402  //#ifdef RTCP_MUX
8403  //if (!engine->rtcp_mux) {// && type == SWITCH_MEDIA_TYPE_AUDIO) {
8404  // engine->rtcp_mux = SWITCH_TRUE;
8405  //}
8406  //#endif
8407 
8408  if (!smh->msid) {
8409  switch_stun_random_string(tmp, 32, NULL);
8410  tmp[32] = '\0';
8411  smh->msid = switch_core_session_strdup(session, tmp);
8412  }
8413 
8414  if (!smh->cname) {
8415  switch_stun_random_string(tmp, 16, NULL);
8416  tmp[16] = '\0';
8417  smh->cname = switch_core_session_strdup(session, tmp);
8418  }
8419 
8420  if (type == SWITCH_MEDIA_TYPE_VIDEO && switch_channel_var_true(switch_core_session_get_channel(session), "video_use_audio_ice")) {
8421  switch_rtp_engine_t *audio_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
8422 
8423  if (audio_engine->ice_out.ufrag) {
8424  engine->ice_out.ufrag = switch_core_session_strdup(session, audio_engine->ice_out.ufrag);
8425  }
8426 
8427  if (audio_engine->ice_out.pwd) {
8428  engine->ice_out.pwd = switch_core_session_strdup(session, audio_engine->ice_out.pwd);
8429  }
8430  }
8431 
8432  if (!engine->ice_out.ufrag) {
8433  switch_stun_random_string(tmp, 16, NULL);
8434  tmp[16] = '\0';
8435  engine->ice_out.ufrag = switch_core_session_strdup(session, tmp);
8436  }
8437 
8438  if (!engine->ice_out.pwd) {
8439  switch_stun_random_string(tmp, 24, NULL);
8440  tmp[24] = '\0';
8441  engine->ice_out.pwd = switch_core_session_strdup(session, tmp);
8442  }
8443 
8444  if (!engine->ice_out.cands[0][0].foundation) {
8445  switch_stun_random_string(tmp, 10, "0123456789");
8446  tmp[10] = '\0';
8447  engine->ice_out.cands[0][0].foundation = switch_core_session_strdup(session, tmp);
8448  }
8449 
8450  engine->ice_out.cands[0][0].transport = "udp";
8451 
8452  if (!engine->ice_out.cands[0][0].component_id) {
8453  engine->ice_out.cands[0][0].component_id = 1;
8454  engine->ice_out.cands[0][0].priority = (1<<24)*126 + (1<<8)*65535 + (1<<0)*(256 - engine->ice_out.cands[0][0].component_id);
8455  }
8456 
8457  if (!zstr(ip)) {
8458  engine->ice_out.cands[0][0].con_addr = switch_core_session_strdup(session, ip);
8459  }
8460 
8461  if (port) {
8462  engine->ice_out.cands[0][0].con_port = port;
8463  }
8464 
8465  engine->ice_out.cands[0][0].generation = "0";
8466  //add rport stuff later
8467 
8468  engine->ice_out.cands[0][0].ready = 1;
8469 
8470 
8471 }
8472 
8474 {
8475  switch_media_handle_t *smh;
8476  switch_rtp_engine_t *v_engine;
8477 
8478  if (!(smh = session->media_handle)) {
8479  return;
8480  }
8481 
8482  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
8483 
8484  if ((!smh->mparams->external_video_source) && (!v_engine->rtp_session)) {
8485  return;
8486  }
8487 
8488  if (!v_engine->media_thread) {
8489  return;
8490  }
8491 
8492  if (!v_engine->mh.cond_mutex) {
8493  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Channel %s has no cond?\n",
8494  switch_channel_get_name(session->channel));
8495  return;
8496  }
8497 
8500  switch_mutex_unlock(v_engine->mh.cond_mutex);
8501  }
8502 }
8503 
8505 {
8506  if (switch_channel_test_flag(session->channel, CF_REINVITE) && engine->new_dtls) {
8507 
8508  if (!zstr(engine->local_dtls_fingerprint.str) && switch_rtp_has_dtls() && dtls_ok(session)) {
8509 
8510 #ifdef HAVE_OPENSSL_DTLSv1_2_method
8511  uint8_t want_DTLSv1_2 = 1;
8512 #else
8513  uint8_t want_DTLSv1_2 = 0;
8514 #endif // HAVE_OPENSSL_DTLSv1_2_method
8515 
8516  dtls_type_t xtype, dtype = engine->dtls_controller ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
8517 
8518  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "RE-SETTING %s DTLS\n", type2str(engine->type));
8519 
8520  xtype = DTLS_TYPE_RTP;
8521  if (engine->rtcp_mux > 0) xtype |= DTLS_TYPE_RTCP;
8522 
8523  if (switch_channel_var_true(session->channel, "legacyDTLS")) {
8525  want_DTLSv1_2 = 0;
8526  }
8527 
8528  switch_rtp_add_dtls(engine->rtp_session, &engine->local_dtls_fingerprint, &engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2);
8529 
8530  if (engine->rtcp_mux < 1) {
8531  xtype = DTLS_TYPE_RTCP;
8532  switch_rtp_add_dtls(engine->rtp_session, &engine->local_dtls_fingerprint, &engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2);
8533  }
8534 
8535  }
8536  engine->new_dtls = 0;
8537  }
8538 }
8539 
8540 //?
8542 
8543 {
8544  const char *err = NULL;
8545  const char *val = NULL;
8548  char tmp[50];
8549  char *timer_name = NULL;
8550  const char *var;
8551  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
8552  switch_media_handle_t *smh;
8553  int is_reinvite = 0;
8554 
8555 #ifdef HAVE_OPENSSL_DTLSv1_2_method
8556  uint8_t want_DTLSv1_2 = 1;
8557 #else
8558  uint8_t want_DTLSv1_2 = 0;
8559 #endif
8560 
8561  switch_assert(session);
8562 
8563  if (!(smh = session->media_handle)) {
8564  return SWITCH_STATUS_FALSE;
8565  }
8566 
8567  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
8568  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
8569  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
8570 
8571  if (a_engine->rtp_session || v_engine->rtp_session || t_engine->rtp_session || switch_channel_test_flag(session->channel, CF_REINVITE)) {
8572  is_reinvite = 1;
8573  }
8574 
8575 
8576  if (switch_channel_down(session->channel)) {
8577  return SWITCH_STATUS_FALSE;
8578  }
8579 
8581 
8582  if (switch_rtp_ready(a_engine->rtp_session)) {
8584  check_media_timeout_params(session, a_engine);
8585  check_media_timeout_params(session, v_engine);
8586  }
8587 
8588  if (a_engine->crypto_type != CRYPTO_INVALID) {
8590  }
8591 
8592  if (want_DTLSv1_2) {
8594  }
8595 
8597  status = SWITCH_STATUS_SUCCESS;
8598  goto end;
8599  }
8600 
8601  if (switch_channel_var_true(session->channel, "fire_rtcp_events")) {
8604  switch_channel_var_true(session->channel, "rtp_video_send_rtcp_message_event")) {
8606  }
8607  }
8608 
8609  if (!is_reinvite) {
8610  if (switch_rtp_ready(a_engine->rtp_session)) {
8612  goto text;
8613  }
8614 
8616  goto video;
8617  }
8618 
8619  status = SWITCH_STATUS_SUCCESS;
8620  goto end;
8621  }
8622  }
8623 
8624  if ((status = switch_core_media_set_codec(session, 0, smh->mparams->codec_flags)) != SWITCH_STATUS_SUCCESS) {
8625  goto end;
8626  }
8627 
8629 
8630  flags[SWITCH_RTP_FLAG_DATAWAIT]++;
8631 
8633  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
8634  flags[SWITCH_RTP_FLAG_AUTOADJ]++;
8635  }
8636 
8638  || ((val = switch_channel_get_variable(session->channel, "pass_rfc2833")) && switch_true(val))) {
8640  }
8641 
8642 
8644  || ((val = switch_channel_get_variable(session->channel, "rtp_autoflush")) && switch_true(val))) {
8645  flags[SWITCH_RTP_FLAG_AUTOFLUSH]++;
8646  }
8647 
8649  ((val = switch_channel_get_variable(session->channel, "rtp_rewrite_timestamps")) && switch_true(val)))) {
8650  flags[SWITCH_RTP_FLAG_RAW_WRITE]++;
8651  }
8652 
8654  smh->mparams->cng_pt = 0;
8655  } else if (smh->mparams->cng_pt) {
8656  flags[SWITCH_RTP_FLAG_AUTO_CNG]++;
8657  }
8658 
8659 #if __BYTE_ORDER == __LITTLE_ENDIAN
8660  if (!strcasecmp(a_engine->read_impl.iananame, "L16")) {
8661  flags[SWITCH_RTP_FLAG_BYTESWAP]++;
8662  }
8663 #endif
8664 
8665  if ((flags[SWITCH_RTP_FLAG_BYTESWAP]) && (val = switch_channel_get_variable(session->channel, "rtp_disable_byteswap")) && switch_true(val)) {
8666  flags[SWITCH_RTP_FLAG_BYTESWAP] = 0;
8667  }
8668 
8669  if (a_engine->rtp_session && is_reinvite) {
8670  //const char *ip = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
8671  //const char *port = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
8672  char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
8673  switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
8674 
8675  if (remote_host && remote_port && !strcmp(remote_host, a_engine->cur_payload_map->remote_sdp_ip) &&
8676  remote_port == a_engine->cur_payload_map->remote_sdp_port) {
8677  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params are unchanged for %s.\n",
8678  switch_channel_get_name(session->channel));
8679  a_engine->cur_payload_map->negotiated = 1;
8680  //XX
8681  goto video;
8682  } else {
8683  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio params changed for %s from %s:%d to %s:%d\n",
8684  switch_channel_get_name(session->channel),
8685  remote_host, remote_port, a_engine->cur_payload_map->remote_sdp_ip, a_engine->cur_payload_map->remote_sdp_port);
8686 
8687  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
8690  switch_channel_execute_on(session->channel, "execute_on_audio_change");
8691  }
8692  }
8693 
8695  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",
8696  switch_channel_get_name(session->channel),
8697  a_engine->local_sdp_ip,
8698  a_engine->local_sdp_port,
8699  a_engine->cur_payload_map->remote_sdp_ip,
8700  a_engine->cur_payload_map->remote_sdp_port, a_engine->cur_payload_map->pt, a_engine->read_impl.microseconds_per_packet / 1000);
8701 
8702  //XX
8703  }
8704 
8705  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->local_sdp_port);
8709 
8710  if (a_engine->rtp_session && is_reinvite) {
8711  const char *rport = NULL;
8712  switch_port_t remote_rtcp_port = a_engine->remote_rtcp_port;
8713 
8714  if (!remote_rtcp_port) {
8715  if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_audio_rtcp_port"))) {
8716  remote_rtcp_port = (switch_port_t)atoi(rport);
8717  }
8718  }
8719 
8721  remote_rtcp_port, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
8722  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", err);
8723  } else {
8724  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP CHANGING DEST TO: [%s:%d]\n",
8726 
8727  //if (switch_channel_test_flag(session->channel, CF_PROTO_HOLD) && strcmp(a_engine->cur_payload_map->remote_sdp_ip, "0.0.0.0")) {
8728  // switch_core_media_toggle_hold(session, 0);
8729  //}
8730 
8731 
8733  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
8735  /* Reactivate the NAT buster flag. */
8737  }
8738  }
8739 
8740  if (session && a_engine) {
8741  check_dtls_reinvite(session, a_engine);
8742  }
8743 
8744  goto video;
8745  }
8746 
8748  switch_core_media_proxy_remote_addr(session, NULL);
8749 
8750  memset(flags, 0, sizeof(flags));
8751  flags[SWITCH_RTP_FLAG_DATAWAIT]++;
8752  flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++;
8753 
8755  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
8756  flags[SWITCH_RTP_FLAG_AUTOADJ]++;
8757  }
8758 
8759  timer_name = NULL;
8760 
8762  "PROXY AUDIO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
8763  switch_channel_get_name(session->channel),
8764  a_engine->cur_payload_map->remote_sdp_ip,
8765  a_engine->cur_payload_map->remote_sdp_port,
8766  a_engine->cur_payload_map->remote_sdp_ip,
8767  a_engine->cur_payload_map->remote_sdp_port, a_engine->cur_payload_map->pt, a_engine->read_impl.microseconds_per_packet / 1000);
8768 
8769  if (switch_rtp_ready(a_engine->rtp_session)) {
8771  }
8772 
8773  } else {
8774  timer_name = smh->mparams->timer_name;
8775 
8776  if ((var = switch_channel_get_variable(session->channel, "rtp_timer_name"))) {
8777  timer_name = (char *) var;
8778  }
8779  }
8780 
8781 
8782  if (switch_channel_up(session->channel)) {
8783  switch_channel_set_variable(session->channel, "rtp_use_timer_name", timer_name);
8784 
8785  a_engine->rtp_session = switch_rtp_new(a_engine->local_sdp_ip,
8786  a_engine->local_sdp_port,
8787  a_engine->cur_payload_map->remote_sdp_ip,
8788  a_engine->cur_payload_map->remote_sdp_port,
8789  a_engine->cur_payload_map->pt,
8790  strcasecmp("opus", a_engine->read_impl.iananame) ? a_engine->read_impl.samples_per_packet :
8791  a_engine->read_impl.samples_per_second * (a_engine->read_impl.microseconds_per_packet / 1000) / 1000,
8792  a_engine->cur_payload_map->codec_ms * 1000,
8793  flags, timer_name, &err, switch_core_session_get_pool(session),
8794  0, 0);
8795 
8796  if (switch_rtp_ready(a_engine->rtp_session)) {
8797  switch_rtp_set_payload_map(a_engine->rtp_session, &a_engine->payload_map);
8798  }
8799  }
8800 
8801  if (switch_rtp_ready(a_engine->rtp_session)) {
8802  uint8_t vad_in = (smh->mparams->vflags & VAD_IN);
8803  uint8_t vad_out = (smh->mparams->vflags & VAD_OUT);
8805  const char *ssrc;
8806 
8809 
8810  //switch_core_media_set_rtp_session(session, SWITCH_MEDIA_TYPE_AUDIO, a_engine->rtp_session);
8811 
8812  if ((ssrc = switch_channel_get_variable(session->channel, "rtp_use_ssrc"))) {
8813  uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10);
8814  switch_rtp_set_ssrc(a_engine->rtp_session, ssrc_ul);
8815  a_engine->ssrc = ssrc_ul;
8816  } else {
8817  switch_rtp_set_ssrc(a_engine->rtp_session, a_engine->ssrc);
8818  }
8819 
8820  if (a_engine->remote_ssrc) {
8821  switch_rtp_set_remote_ssrc(a_engine->rtp_session, a_engine->remote_ssrc);
8822  }
8823 
8824  check_media_timeout_params(session, a_engine);
8825 
8827 
8828  switch_channel_set_variable_printf(session->channel, "rtp_use_pt", "%d", a_engine->cur_payload_map->pt);
8829 
8830  if ((val = switch_channel_get_variable(session->channel, "rtp_enable_vad_in")) && switch_true(val)) {
8831  vad_in = 1;
8832  }
8833  if ((val = switch_channel_get_variable(session->channel, "rtp_enable_vad_out")) && switch_true(val)) {
8834  vad_out = 1;
8835  }
8836 
8837  if ((val = switch_channel_get_variable(session->channel, "rtp_disable_vad_in")) && switch_true(val)) {
8838  vad_in = 0;
8839  }
8840  if ((val = switch_channel_get_variable(session->channel, "rtp_disable_vad_out")) && switch_true(val)) {
8841  vad_out = 0;
8842  }
8843 
8844 
8845  a_engine->ssrc = switch_rtp_get_ssrc(a_engine->rtp_session);
8846  switch_channel_set_variable_printf(session->channel, "rtp_use_ssrc", "%u", a_engine->ssrc);
8847 
8848 
8849 
8851  a_engine->rtp_bugs |= RTP_BUG_IGNORE_MARK_BIT;
8852  }
8853 
8854  if ((val = switch_channel_get_variable(session->channel, "rtp_manual_rtp_bugs"))) {
8855  switch_core_media_parse_rtp_bugs(&a_engine->rtp_bugs, val);
8856  }
8857 
8858  //if (switch_channel_test_flag(session->channel, CF_AVPF)) {
8859  // smh->mparams->manual_rtp_bugs = RTP_BUG_SEND_LINEAR_TIMESTAMPS;
8860  //}
8861 
8863 
8864  if ((vad_in && inb) || (vad_out && !inb)) {
8866 
8867  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "AUDIO RTP Engage VAD for %s ( %s %s )\n",
8868  switch_channel_get_name(switch_core_session_get_channel(session)), vad_in ? "in" : "", vad_out ? "out" : "");
8869  }
8870 
8871 
8872  if (a_engine->ice_in.cands[a_engine->ice_in.chosen[0]][0].ready) {
8873 
8874  gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, NULL, 0);
8875 
8876  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating Audio ICE\n");
8877 
8879  a_engine->ice_in.ufrag,
8880  a_engine->ice_out.ufrag,
8881  a_engine->ice_out.pwd,
8882  a_engine->ice_in.pwd,
8883  IPR_RTP,
8884 #ifdef GOOGLE_ICE
8886  NULL
8887 #else
8888  switch_determine_ice_type(a_engine, session),
8889  &a_engine->ice_in
8890 #endif
8891  );
8892 
8893 
8894 
8895  }
8896 
8897  if ((val = switch_channel_get_variable(session->channel, "rtcp_audio_interval_msec")) || (val = smh->mparams->rtcp_audio_interval_msec)) {
8898  const char *rport = switch_channel_get_variable(session->channel, "rtp_remote_audio_rtcp_port");
8899  switch_port_t remote_rtcp_port = a_engine->remote_rtcp_port;
8900 
8901  if (!remote_rtcp_port && rport) {
8902  remote_rtcp_port = (switch_port_t)atoi(rport);
8903  }
8904 
8905  if (!strcasecmp(val, "passthru")) {
8906  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating RTCP PASSTHRU PORT %d\n", remote_rtcp_port);
8907  switch_rtp_activate_rtcp(a_engine->rtp_session, -1, remote_rtcp_port, a_engine->rtcp_mux > 0);
8908  } else {
8909  int interval = atoi(val);
8910  if (interval < 100 || interval > 500000) {
8912  "Invalid rtcp interval spec [%d] must be between 100 and 500000\n", interval);
8913  interval = 5000;
8914  }
8915 
8916  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Activating RTCP PORT %d\n", remote_rtcp_port);
8917  switch_rtp_activate_rtcp(a_engine->rtp_session, interval, remote_rtcp_port, a_engine->rtcp_mux > 0);
8918 
8919  }
8920 
8921  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 &&
8922  !zstr(a_engine->ice_in.cands[a_engine->ice_in.chosen[1]][1].con_addr) &&
8923  !zstr(a_engine->ice_in.cands[a_engine->ice_in.chosen[0]][0].con_addr)) {
8924  if (a_engine->rtcp_mux > 0 &&
8925  !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)
8926  && 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) {
8927  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Skipping RTCP ICE (Same as RTP)\n");
8928  } else {
8929  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating RTCP ICE\n");
8930 
8932  a_engine->ice_in.ufrag,
8933  a_engine->ice_out.ufrag,
8934  a_engine->ice_out.pwd,
8935  a_engine->ice_in.pwd,
8936  IPR_RTCP,
8937 #ifdef GOOGLE_ICE
8939  NULL
8940 #else
8941  switch_determine_ice_type(a_engine, session),
8942  &a_engine->ice_in
8943 #endif
8944  );
8945  }
8946 
8947  }
8948  }
8949 
8950  if (!zstr(a_engine->local_dtls_fingerprint.str) && switch_rtp_has_dtls() && dtls_ok(smh->session)) {
8951  dtls_type_t xtype, dtype = a_engine->dtls_controller ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
8952 
8953  //if (switch_channel_test_flag(smh->session->channel, CF_3PCC)) {
8954  // dtype = (dtype == DTLS_TYPE_CLIENT) ? DTLS_TYPE_SERVER : DTLS_TYPE_CLIENT;
8955  //}
8956 
8957  xtype = DTLS_TYPE_RTP;
8958  if (a_engine->rtcp_mux > 0 && smh->mparams->rtcp_audio_interval_msec) xtype |= DTLS_TYPE_RTCP;
8959 
8960  if (switch_channel_var_true(session->channel, "legacyDTLS")) {
8962  want_DTLSv1_2 = 0;
8963  }
8964 
8965  switch_rtp_add_dtls(a_engine->rtp_session, &a_engine->local_dtls_fingerprint, &a_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2);
8966 
8967  if (a_engine->rtcp_mux < 1 && smh->mparams->rtcp_audio_interval_msec) {
8968  xtype = DTLS_TYPE_RTCP;
8969  switch_rtp_add_dtls(a_engine->rtp_session, &a_engine->local_dtls_fingerprint, &a_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2);
8970  }
8971 
8972  }
8973 
8974  check_jb(session, NULL, 0, 0, SWITCH_FALSE);
8975 
8976  if ((val = switch_channel_get_variable(session->channel, "rtp_timeout_sec"))) {
8977  int v = atoi(val);
8978  if (v >= 0) {
8980  "rtp_timeout_sec deprecated use media_timeout variable.\n");
8981  smh->mparams->rtp_timeout_sec = v;
8982  }
8983  }
8984 
8985  if ((val = switch_channel_get_variable(session->channel, "rtp_hold_timeout_sec"))) {
8986  int v = atoi(val);
8987  if (v >= 0) {
8989  "rtp_hold_timeout_sec deprecated use media_hold_timeout variable.\n");
8990  smh->mparams->rtp_hold_timeout_sec = v;
8991  }
8992  }
8993 
8994  if (smh->mparams->rtp_timeout_sec) {
8996 
8998  if (!smh->mparams->rtp_hold_timeout_sec) {
9000  }
9001  }
9002 
9003  if (smh->mparams->rtp_hold_timeout_sec) {
9005  }
9006 
9007  if (smh->mparams->te) {
9008  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Set 2833 dtmf send payload to %u\n",
9009  switch_channel_get_name(session->channel), smh->mparams->te);
9011  switch_channel_set_variable_printf(session->channel, "rtp_2833_send_payload", "%d", smh->mparams->te);
9012  }
9013 
9014  if (smh->mparams->recv_te) {
9015  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Set 2833 dtmf receive payload to %u\n",
9016  switch_channel_get_name(session->channel), smh->mparams->recv_te);
9018  switch_channel_set_variable_printf(session->channel, "rtp_2833_recv_payload", "%d", smh->mparams->recv_te);
9019  }
9020 
9021  //XX
9022 
9024  ((val = switch_channel_get_variable(session->channel, "supress_cng")) && switch_true(val)) ||
9025  ((val = switch_channel_get_variable(session->channel, "suppress_cng")) && switch_true(val))) {
9026  smh->mparams->cng_pt = 0;
9027  }
9028 
9029  if (((val = switch_channel_get_variable(session->channel, "rtp_digit_delay")))) {
9030  int delayi = atoi(val);
9031  if (delayi < 0) delayi = 0;
9032  smh->mparams->dtmf_delay = (uint32_t) delayi;
9033  }
9034 
9035 
9036  if (smh->mparams->dtmf_delay) {
9039  "%s Set rtp dtmf delay to %u\n", switch_channel_get_name(session->channel), smh->mparams->dtmf_delay);
9040 
9041  }
9042 
9044  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set comfort noise payload to %u\n", smh->mparams->cng_pt);
9045  switch_rtp_set_cng_pt(a_engine->rtp_session, smh->mparams->cng_pt);
9046  }
9047 
9049 
9050  switch_snprintf(tmp, sizeof(tmp), "%d", a_engine->cur_payload_map->remote_sdp_port);
9053 
9054 
9055  text:
9056 
9057  //if (switch_channel_test_flag(session->channel, CF_MSRP)) { // skip RTP RTT
9058  // goto video;
9059  //}
9060 
9061  if (!t_engine->cur_payload_map) {
9062  goto text_up;
9063  }
9064 
9066  /******************************************************************************************/
9067  if (t_engine->rtp_session && is_reinvite) {
9068  //const char *ip = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
9069  //const char *port = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
9070  char *remote_host = switch_rtp_get_remote_host(t_engine->rtp_session);
9071  switch_port_t remote_port = switch_rtp_get_remote_port(t_engine->rtp_session);
9072 
9073 
9074 
9075  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) {
9076  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Text params are unchanged for %s.\n",
9077  switch_channel_get_name(session->channel));
9078  t_engine->cur_payload_map->negotiated = 1;
9079  goto text_up;
9080  } else {
9081  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Text params changed for %s from %s:%d to %s:%d\n",
9082  switch_channel_get_name(session->channel),
9083  remote_host, remote_port, t_engine->cur_payload_map->remote_sdp_ip, t_engine->cur_payload_map->remote_sdp_port);
9084  }
9085  }
9086 
9088  if (switch_rtp_ready(t_engine->rtp_session)) {
9090  "TEXT RTP [%s] %s port %d -> %s port %d codec: %u\n", switch_channel_get_name(session->channel),
9091  t_engine->local_sdp_ip, t_engine->local_sdp_port, t_engine->cur_payload_map->remote_sdp_ip,
9092  t_engine->cur_payload_map->remote_sdp_port, t_engine->cur_payload_map->pt);
9093 
9095  }
9096  }
9097 
9098  switch_snprintf(tmp, sizeof(tmp), "%d", t_engine->local_sdp_port);
9101 
9102 
9103  if (t_engine->rtp_session && is_reinvite) {
9104  const char *rport = NULL;
9105  switch_port_t remote_rtcp_port = t_engine->remote_rtcp_port;
9106 
9107  //switch_channel_clear_flag(session->channel, CF_REINVITE);
9108 
9109  if (!remote_rtcp_port) {
9110  if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_text_rtcp_port"))) {
9111  remote_rtcp_port = (switch_port_t)atoi(rport);
9112  }
9113  }
9114 
9116  (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,
9117  &err) != SWITCH_STATUS_SUCCESS) {
9118  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "TEXT RTP REPORTS ERROR: [%s]\n", err);
9119  } else {
9120  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "TEXT RTP CHANGING DEST TO: [%s:%d]\n",
9123  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
9124  /* Reactivate the NAT buster flag. */
9126  }
9127 
9128  }
9129  goto text_up;
9130  }
9131 
9133  switch_core_media_proxy_remote_addr(session, NULL);
9134 
9135  memset(flags, 0, sizeof(flags));
9136  flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++;
9137  flags[SWITCH_RTP_FLAG_DATAWAIT]++;
9138 
9140  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
9141  flags[SWITCH_RTP_FLAG_AUTOADJ]++;
9142  }
9143 
9145  "PROXY TEXT RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
9146  switch_channel_get_name(session->channel),
9147  a_engine->cur_payload_map->remote_sdp_ip,
9148  t_engine->local_sdp_port,
9149  t_engine->cur_payload_map->remote_sdp_ip,
9150  t_engine->cur_payload_map->remote_sdp_port, t_engine->cur_payload_map->pt, t_engine->read_impl.microseconds_per_packet / 1000);
9151 
9152  if (switch_rtp_ready(t_engine->rtp_session)) {
9154  }
9155  }
9156 
9157  /******************************************************************************************/
9158 
9159  if (t_engine->rtp_session) {
9160  goto text_up;
9161  }
9162 
9163 
9164  if (!t_engine->local_sdp_port) {
9166  }
9167 
9168  memset(flags, 0, sizeof(flags));
9169  flags[SWITCH_RTP_FLAG_DATAWAIT]++;
9170  flags[SWITCH_RTP_FLAG_RAW_WRITE]++;
9171 
9173  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
9175  flags[SWITCH_RTP_FLAG_AUTOADJ]++;
9176  }
9177 
9179  flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++;
9180  }
9181  //TEXT switch_core_media_set_text_codec(session, 0);
9182 
9183  flags[SWITCH_RTP_FLAG_USE_TIMER] = 1;
9184  flags[SWITCH_RTP_FLAG_NOBLOCK] = 0;
9185  flags[SWITCH_RTP_FLAG_TEXT]++;
9186  //flags[SWITCH_RTP_FLAG_VIDEO]++;
9187 
9188  t_engine->rtp_session = switch_rtp_new(a_engine->local_sdp_ip,
9189  t_engine->local_sdp_port,
9190  t_engine->cur_payload_map->remote_sdp_ip,
9191  t_engine->cur_payload_map->remote_sdp_port,
9192  t_engine->cur_payload_map->pt,
9193  TEXT_TIMER_SAMPLES, TEXT_TIMER_MS * 1000, flags, NULL, &err, switch_core_session_get_pool(session),
9194  0, 0);
9195 
9196 
9197  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%sTEXT RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n",
9198  switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) ? "PROXY " : "",
9199  switch_channel_get_name(session->channel),
9200  a_engine->local_sdp_ip,
9201  t_engine->local_sdp_port,
9202  t_engine->cur_payload_map->remote_sdp_ip,
9203  t_engine->cur_payload_map->remote_sdp_port, t_engine->cur_payload_map->pt,
9204  0, switch_rtp_ready(t_engine->rtp_session) ? "SUCCESS" : err);
9205 
9206 
9207  if (switch_rtp_ready(t_engine->rtp_session)) {
9208  const char *ssrc;
9209 
9210 
9211  if (!t_engine->tf) {
9213  }
9214 
9215  switch_rtp_set_video_buffer_size(t_engine->rtp_session, 2, 2048);
9216 
9217  switch_rtp_set_payload_map(t_engine->rtp_session, &t_engine->payload_map);
9220 
9221  if ((ssrc = switch_channel_get_variable(session->channel, "rtp_use_text_ssrc"))) {
9222  uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10);
9223  switch_rtp_set_ssrc(t_engine->rtp_session, ssrc_ul);
9224  t_engine->ssrc = ssrc_ul;
9225  } else {
9226  switch_rtp_set_ssrc(t_engine->rtp_session, t_engine->ssrc);
9227  }
9228 
9229  if (t_engine->remote_ssrc) {
9230  switch_rtp_set_remote_ssrc(t_engine->rtp_session, t_engine->remote_ssrc);
9231  }
9232 
9233  if (t_engine->ice_in.cands[t_engine->ice_in.chosen[0]][0].ready) {
9234 
9235  gen_ice(session, SWITCH_MEDIA_TYPE_TEXT, NULL, 0);
9236 
9237  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating Text ICE\n");
9238 
9240  t_engine->ice_in.ufrag,
9241  t_engine->ice_out.ufrag,
9242  t_engine->ice_out.pwd,
9243  t_engine->ice_in.pwd,
9244  IPR_RTP,
9245 #ifdef GOOGLE_ICE
9247  NULL
9248 #else
9249  switch_determine_ice_type(t_engine, session),
9250  &t_engine->ice_in
9251 #endif
9252  );
9253 
9254 
9255  }
9256 
9257  if ((val = switch_channel_get_variable(session->channel, "rtcp_text_interval_msec")) || (val = smh->mparams->rtcp_text_interval_msec)) {
9258  const char *rport = switch_channel_get_variable(session->channel, "rtp_remote_text_rtcp_port");
9259  switch_port_t remote_port = t_engine->remote_rtcp_port;
9260 
9261  if (rport) {
9262  remote_port = (switch_port_t)atoi(rport);
9263  }
9264  if (!strcasecmp(val, "passthru")) {
9265  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating TEXT RTCP PASSTHRU PORT %d\n", remote_port);
9266  switch_rtp_activate_rtcp(t_engine->rtp_session, -1, remote_port, t_engine->rtcp_mux > 0);
9267  } else {
9268  int interval = atoi(val);
9269  if (interval < 100 || interval > 500000) {
9271  "Invalid rtcp interval spec [%d] must be between 100 and 500000\n", interval);
9272  interval = 5000;
9273  }
9275  "Activating TEXT RTCP PORT %d interval %d mux %d\n", remote_port, interval, t_engine->rtcp_mux);
9276  switch_rtp_activate_rtcp(t_engine->rtp_session, interval, remote_port, t_engine->rtcp_mux > 0);
9277 
9278  }
9279 
9280 
9281  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 &&
9282  !zstr(t_engine->ice_in.cands[t_engine->ice_in.chosen[1]][1].con_addr) &&
9283  !zstr(t_engine->ice_in.cands[t_engine->ice_in.chosen[0]][0].con_addr)) {
9284  if (t_engine->rtcp_mux > 0 && !strcmp(t_engine->ice_in.cands[t_engine->ice_in.chosen[1]][1].con_addr,
9285  t_engine->ice_in.cands[t_engine->ice_in.chosen[0]][0].con_addr) &&
9286  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) {
9287  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Skipping TEXT RTCP ICE (Same as TEXT RTP)\n");
9288  } else {
9289  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating TEXT RTCP ICE\n");
9291  t_engine->ice_in.ufrag,
9292  t_engine->ice_out.ufrag,
9293  t_engine->ice_out.pwd,
9294  t_engine->ice_in.pwd,
9295  IPR_RTCP,
9296 #ifdef GOOGLE_ICE
9298  NULL
9299 #else
9300  switch_determine_ice_type(t_engine, session),
9301  &t_engine->ice_in
9302 #endif
9303  );
9304 
9305 
9306 
9307  }
9308 
9309  }
9310  }
9311 
9312  if (!zstr(t_engine->local_dtls_fingerprint.str) && switch_rtp_has_dtls() && dtls_ok(smh->session)) {
9313  dtls_type_t xtype,
9314  dtype = t_engine->dtls_controller ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
9315  xtype = DTLS_TYPE_RTP;
9316  if (t_engine->rtcp_mux > 0 && smh->mparams->rtcp_text_interval_msec) xtype |= DTLS_TYPE_RTCP;
9317 
9318  if (switch_channel_var_true(session->channel, "legacyDTLS")) {
9320  want_DTLSv1_2 = 0;
9321  }
9322 
9323  switch_rtp_add_dtls(t_engine->rtp_session, &t_engine->local_dtls_fingerprint, &t_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2);
9324 
9325  if (t_engine->rtcp_mux < 1 && smh->mparams->rtcp_text_interval_msec) {
9326  xtype = DTLS_TYPE_RTCP;
9327  switch_rtp_add_dtls(t_engine->rtp_session, &t_engine->local_dtls_fingerprint, &t_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2);
9328  }
9329  }
9330 
9331 
9332  if ((val = switch_channel_get_variable(session->channel, "rtp_manual_text_rtp_bugs"))) {
9333  switch_core_media_parse_rtp_bugs(&t_engine->rtp_bugs, val);
9334  }
9335 
9336 
9337  //if (switch_channel_test_flag(session->channel, CF_AVPF)) {
9338  //smh->mparams->manual_video_rtp_bugs = RTP_BUG_SEND_LINEAR_TIMESTAMPS;
9339  //}
9340 
9342 
9343  //XX
9344 
9345 
9346  switch_channel_set_variable_printf(session->channel, "rtp_use_text_pt", "%d", t_engine->cur_payload_map->pt);
9347  t_engine->ssrc = switch_rtp_get_ssrc(t_engine->rtp_session);
9348  switch_channel_set_variable_printf(session->channel, "rtp_use_text_ssrc", "%u", t_engine->ssrc);
9349 
9351 
9352  } else {
9353  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "TEXT RTP REPORTS ERROR: [%s]\n", switch_str_nil(err));
9355  goto end;
9356  }
9357  }
9358 
9359 
9360  text_up:
9361  video:
9362 
9365  }
9366 
9368  /******************************************************************************************/
9369  if (v_engine->rtp_session && is_reinvite) {
9370  //const char *ip = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE);
9371  //const char *port = switch_channel_get_variable(session->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
9372  char *remote_host = switch_rtp_get_remote_host(v_engine->rtp_session);
9373  switch_port_t remote_port = switch_rtp_get_remote_port(v_engine->rtp_session);
9374 
9375 
9376 
9377  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) {
9378  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video params are unchanged for %s.\n",
9379  switch_channel_get_name(session->channel));
9380  v_engine->cur_payload_map->negotiated = 1;
9381  goto video_up;
9382  } else {
9383  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Video params changed for %s from %s:%d to %s:%d\n",
9384  switch_channel_get_name(session->channel),
9385  remote_host, remote_port, v_engine->cur_payload_map->remote_sdp_ip, v_engine->cur_payload_map->remote_sdp_port);
9386  }
9387  }
9388 
9390  if (switch_rtp_ready(v_engine->rtp_session)) {
9392  "VIDEO RTP [%s] %s port %d -> %s port %d codec: %u\n", switch_channel_get_name(session->channel),
9393  v_engine->local_sdp_ip, v_engine->local_sdp_port, v_engine->cur_payload_map->remote_sdp_ip,
9394  v_engine->cur_payload_map->remote_sdp_port, v_engine->cur_payload_map->pt);
9395 
9397  }
9398  }
9399 
9400  switch_snprintf(tmp, sizeof(tmp), "%d", v_engine->local_sdp_port);
9403 
9404 
9405  if (v_engine->rtp_session && is_reinvite) {
9406  const char *rport = NULL;
9407  switch_port_t remote_rtcp_port = v_engine->remote_rtcp_port;
9408 
9409  //switch_channel_clear_flag(session->channel, CF_REINVITE);
9410 
9411  if (!remote_rtcp_port) {
9412  if ((rport = switch_channel_get_variable(session->channel, "rtp_remote_video_rtcp_port"))) {
9413  remote_rtcp_port = (switch_port_t)atoi(rport);
9414  }
9415  }
9416 
9418  (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,
9419  &err) != SWITCH_STATUS_SUCCESS) {
9420  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", err);
9421  } else {
9422  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "VIDEO RTP CHANGING DEST TO: [%s:%d]\n",
9425  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
9426  /* Reactivate the NAT buster flag. */
9428  }
9429 
9430  }
9431  goto video_up;
9432  }
9433 
9435  switch_core_media_proxy_remote_addr(session, NULL);
9436 
9437  memset(flags, 0, sizeof(flags));
9438  flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++;
9439  flags[SWITCH_RTP_FLAG_DATAWAIT]++;
9440 
9442  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val))) {
9443  flags[SWITCH_RTP_FLAG_AUTOADJ]++;
9444  }
9445 
9447  "PROXY VIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d\n",
9448  switch_channel_get_name(session->channel),
9449  a_engine->cur_payload_map->remote_sdp_ip,
9450  v_engine->local_sdp_port,
9451  v_engine->cur_payload_map->remote_sdp_ip,
9452  v_engine->cur_payload_map->remote_sdp_port, v_engine->cur_payload_map->pt, v_engine->read_impl.microseconds_per_packet / 1000);
9453 
9454  if (switch_rtp_ready(v_engine->rtp_session)) {
9456  }
9457  }
9458 
9459  /******************************************************************************************/
9460 
9461  if (v_engine->rtp_session) {
9462  goto video_up;
9463  }
9464 
9465 
9466  if (!v_engine->local_sdp_port) {
9468  }
9469 
9470  memset(flags, 0, sizeof(flags));
9471  flags[SWITCH_RTP_FLAG_DATAWAIT]++;
9472  flags[SWITCH_RTP_FLAG_RAW_WRITE]++;
9473 
9475  !((val = switch_channel_get_variable(session->channel, "disable_rtp_auto_adjust")) && switch_true(val)) &&
9477  flags[SWITCH_RTP_FLAG_AUTOADJ]++;
9478  }
9479 
9481  flags[SWITCH_RTP_FLAG_PROXY_MEDIA]++;
9482  }
9484 
9485  flags[SWITCH_RTP_FLAG_USE_TIMER] = 0;
9486  flags[SWITCH_RTP_FLAG_NOBLOCK] = 0;
9487  flags[SWITCH_RTP_FLAG_VIDEO]++;
9488 
9489  if (v_engine->fir) {
9490  flags[SWITCH_RTP_FLAG_FIR]++;
9491  }
9492 
9493  if (v_engine->pli) {
9494  flags[SWITCH_RTP_FLAG_PLI]++;
9495  }
9496 
9497  if ((v_engine->nack) && !switch_channel_var_true(session->channel, "rtp_video_nack_disable")) {
9498  flags[SWITCH_RTP_FLAG_NACK]++;
9499  }
9500 
9501  if (v_engine->tmmbr) {
9502  flags[SWITCH_RTP_FLAG_TMMBR]++;
9503  }
9504 
9505  v_engine->rtp_session = switch_rtp_new(a_engine->local_sdp_ip,
9506  v_engine->local_sdp_port,
9507  v_engine->cur_payload_map->remote_sdp_ip,
9508  v_engine->cur_payload_map->remote_sdp_port,
9509  v_engine->cur_payload_map->pt,
9510  1, 90000, flags, NULL, &err, switch_core_session_get_pool(session),
9511  0, 0);
9512 
9513 
9514  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%sVIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n",
9515  switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) ? "PROXY " : "",
9516  switch_channel_get_name(session->channel),
9517  a_engine->local_sdp_ip,
9518  v_engine->local_sdp_port,
9519  v_engine->cur_payload_map->remote_sdp_ip,
9520  v_engine->cur_payload_map->remote_sdp_port, v_engine->cur_payload_map->pt,
9521  0, switch_rtp_ready(v_engine->rtp_session) ? "SUCCESS" : err);
9522 
9523 
9524  if (switch_rtp_ready(v_engine->rtp_session)) {
9525  const char *ssrc;
9526 
9527  if (v_engine->fir) {
9529  }
9530 
9531  if (v_engine->pli) {
9533  }
9534 
9535  switch_rtp_set_payload_map(v_engine->rtp_session, &v_engine->payload_map);
9538 
9540  if ((ssrc = switch_channel_get_variable(session->channel, "rtp_use_video_ssrc"))) {
9541  uint32_t ssrc_ul = (uint32_t) strtoul(ssrc, NULL, 10);
9542  switch_rtp_set_ssrc(v_engine->rtp_session, ssrc_ul);
9543  v_engine->ssrc = ssrc_ul;
9544  } else {
9545  switch_rtp_set_ssrc(v_engine->rtp_session, v_engine->ssrc);
9546  }
9547 
9548  if (v_engine->remote_ssrc) {
9549  switch_rtp_set_remote_ssrc(v_engine->rtp_session, v_engine->remote_ssrc);
9550  }
9551 
9552  check_media_timeout_params(session, v_engine);
9553 
9554  if (v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].ready) {
9555 
9556  gen_ice(session, SWITCH_MEDIA_TYPE_VIDEO, NULL, 0);
9557 
9558  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating Video ICE\n");
9559 
9561  v_engine->ice_in.ufrag,
9562  v_engine->ice_out.ufrag,
9563  v_engine->ice_out.pwd,
9564  v_engine->ice_in.pwd,
9565  IPR_RTP,
9566 #ifdef GOOGLE_ICE
9568  NULL
9569 #else
9570  switch_determine_ice_type(v_engine, session),
9571  &v_engine->ice_in
9572 #endif
9573  );
9574 
9575 
9576  }
9577 
9578  if ((val = switch_channel_get_variable(session->channel, "rtcp_video_interval_msec")) || (val = smh->mparams->rtcp_video_interval_msec)) {
9579  const char *rport = switch_channel_get_variable(session->channel, "rtp_remote_video_rtcp_port");
9580  switch_port_t remote_port = v_engine->remote_rtcp_port;
9581 
9582  if (rport) {
9583  remote_port = (switch_port_t)atoi(rport);
9584  }
9585  if (!strcasecmp(val, "passthru")) {
9586  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating VIDEO RTCP PASSTHRU PORT %d\n", remote_port);
9587  switch_rtp_activate_rtcp(v_engine->rtp_session, -1, remote_port, v_engine->rtcp_mux > 0);
9588  } else {
9589  int interval = atoi(val);
9590  if (interval < 100 || interval > 500000) {
9592  "Invalid rtcp interval spec [%d] must be between 100 and 500000\n", interval);
9593  interval = 5000;
9594  }
9596  "Activating VIDEO RTCP PORT %d interval %d mux %d\n", remote_port, interval, v_engine->rtcp_mux);
9597  switch_rtp_activate_rtcp(v_engine->rtp_session, interval, remote_port, v_engine->rtcp_mux > 0);
9598 
9599  }
9600 
9601 
9602  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 &&
9603  !zstr(v_engine->ice_in.cands[v_engine->ice_in.chosen[1]][1].con_addr) &&
9604  !zstr(v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].con_addr)) {
9605 
9606  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)
9607  && 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) {
9608  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Skipping VIDEO RTCP ICE (Same as VIDEO RTP)\n");
9609  } else {
9610 
9611  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating VIDEO RTCP ICE\n");
9613  v_engine->ice_in.ufrag,
9614  v_engine->ice_out.ufrag,
9615  v_engine->ice_out.pwd,
9616  v_engine->ice_in.pwd,
9617  IPR_RTCP,
9618 #ifdef GOOGLE_ICE
9620  NULL
9621 #else
9622  switch_determine_ice_type(v_engine, session),
9623  &v_engine->ice_in
9624 #endif
9625  );
9626 
9627 
9628 
9629  }
9630 
9631  }
9632  }
9633 
9634  if (!zstr(v_engine->local_dtls_fingerprint.str) && switch_rtp_has_dtls() && dtls_ok(smh->session)) {
9635  dtls_type_t xtype,
9636  dtype = v_engine->dtls_controller ? DTLS_TYPE_CLIENT : DTLS_TYPE_SERVER;
9637  xtype = DTLS_TYPE_RTP;
9638  if (v_engine->rtcp_mux > 0 && smh->mparams->rtcp_video_interval_msec) xtype |= DTLS_TYPE_RTCP;
9639 
9640 
9641  if (switch_channel_var_true(session->channel, "legacyDTLS")) {
9643  want_DTLSv1_2 = 0;
9644  }
9645 
9646  switch_rtp_add_dtls(v_engine->rtp_session, &v_engine->local_dtls_fingerprint, &v_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2);
9647 
9648  if (v_engine->rtcp_mux < 1 && smh->mparams->rtcp_video_interval_msec) {
9649  xtype = DTLS_TYPE_RTCP;
9650  switch_rtp_add_dtls(v_engine->rtp_session, &v_engine->local_dtls_fingerprint, &v_engine->remote_dtls_fingerprint, dtype | xtype, want_DTLSv1_2);
9651  }
9652  }
9653 
9654 
9655  if ((val = switch_channel_get_variable(session->channel, "rtp_manual_video_rtp_bugs"))) {
9656  switch_core_media_parse_rtp_bugs(&v_engine->rtp_bugs, val);
9657  }
9658 
9659  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
9661  }
9662 
9664 
9665  //XX
9666 
9667 
9668  switch_channel_set_variable_printf(session->channel, "rtp_use_video_pt", "%d", v_engine->cur_payload_map->pt);
9669  v_engine->ssrc = switch_rtp_get_ssrc(v_engine->rtp_session);
9670  switch_channel_set_variable_printf(session->channel, "rtp_use_video_ssrc", "%u", v_engine->ssrc);
9671 
9673 
9674 
9675  } else {
9676  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "VIDEO RTP REPORTS ERROR: [%s]\n", switch_str_nil(err));
9678  goto end;
9679  }
9680  }
9681 
9682  } else {
9683  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "AUDIO RTP REPORTS ERROR: [%s]\n", switch_str_nil(err));
9685  status = SWITCH_STATUS_FALSE;
9686  goto end;
9687  }
9688 
9689  video_up:
9690 
9691  if (session && v_engine) {
9692  check_dtls_reinvite(session, v_engine);
9693  }
9694 
9695  status = SWITCH_STATUS_SUCCESS;
9696 
9697  end:
9698 
9700 
9701  switch_core_recovery_track(session);
9702 
9703  return status;
9704 
9705 }
9706 
9708 {
9709  switch_assert(session);
9710 
9711  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
9712  if (switch_channel_test_flag(session->channel, CF_DTLS) || secure) {
9713  if (switch_channel_test_flag(session->channel, CF_AVPF_MOZ)) {
9714  return "UDP/TLS/RTP/SAVPF";
9715  } else {
9716  return "RTP/SAVPF";
9717  }
9718  } else {
9719  if (switch_channel_test_flag(session->channel, CF_AVPF_MOZ)) {
9720  return "UDP/AVPF";
9721  } else {
9722  return "RTP/AVPF";
9723  }
9724  }
9725  }
9726 
9727  if (secure) {
9728  switch (avp) {
9729  case AVP_NO_SECURE:
9730  break;
9731  case AVP_SECURE:
9732  case AVP_UNDEFINED:
9733  return "RTP/SAVP";
9734  default:
9735  break;
9736  }
9737  }
9738 
9739  return "RTP/AVP";
9740 
9741 }
9742 
9744 {
9745 
9746  if (sdp_type == SDP_TYPE_REQUEST) {
9747  engine->dtls_controller = 0;
9748  engine->new_dtls = 1;
9749  engine->new_ice = 1;
9750  return "actpass";
9751  } else {
9752  return engine->dtls_controller ? "active" : "passive";
9753  }
9754 }
9755 
9756 
9757 //?
9758 static void generate_m(switch_core_session_t *session, char *buf, size_t buflen,
9759  switch_port_t port, const char *family, const char *ip,
9760  int cur_ptime, const char *append_audio, const char *sr, int use_cng, int cng_type, switch_event_t *map, int secure,
9761  switch_sdp_type_t sdp_type)
9762 {
9763  int i = 0;
9764  int rate;
9765  int already_did[128] = { 0 };
9766  int ptime = 0, noptime = 0;
9767  switch_media_handle_t *smh;
9768  switch_rtp_engine_t *a_engine;
9769  int include_external;
9771 
9772  switch_assert(session);
9773 
9774  if (!(smh = session->media_handle)) {
9775  return;
9776  }
9777 
9778  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
9779 
9780  //switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d RTP/%sAVP%s",
9781  //port, secure ? "S" : "", switch_channel_test_flag(session->channel, CF_AVPF) ? "F" : "");
9782 
9783  /* Check if there is a crypto */
9784  if (secure && !switch_channel_test_flag(session->channel, CF_DTLS)) {
9785  int i;
9786 
9787  for (i = 0; smh->crypto_suite_order[i] != CRYPTO_INVALID; i++) {
9789 
9790  if ((a_engine->crypto_type == j || a_engine->crypto_type == CRYPTO_INVALID) && !zstr(a_engine->ssec[j].local_crypto_key)) {
9791  avp_secure = AVP_SECURE;
9792  break;
9793  }
9794  }
9795  }
9796 
9797  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "m=audio %d %s", port,
9798  get_media_profile_name(session, secure || a_engine->crypto_type != CRYPTO_INVALID, avp_secure));
9799 
9800  include_external = switch_channel_var_true(session->channel, "include_external_ip");
9801 
9802  for (i = 0; i < smh->mparams->num_codecs; i++) {
9803  const switch_codec_implementation_t *imp = smh->codecs[i];
9804  int this_ptime = (imp->microseconds_per_packet / 1000);
9805  payload_map_t *pmap;
9806 
9807  if (!strcasecmp(imp->iananame, "ilbc") || !strcasecmp(imp->iananame, "isac") ) {
9808  this_ptime = 20;
9809  }
9810 
9811  if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
9812  continue;
9813  }
9814 
9815  if (!noptime) {
9816  if (!cur_ptime) {
9817  if (!ptime) {
9818  ptime = this_ptime;
9819  }
9820  } else {
9821  if (this_ptime != cur_ptime) {
9822  continue;
9823  }
9824  }
9825  }
9826 
9827  if (smh->ianacodes[i] >= 128 || already_did[smh->ianacodes[i]]) {
9828  continue;
9829  }
9830 
9831 
9833  for (pmap = a_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
9834  if (pmap->negotiated && !strcasecmp(imp->iananame, pmap->iananame)) {
9835  smh->ianacodes[i] = pmap->pt;
9836  break;
9837  }
9838  }
9840 
9841  already_did[smh->ianacodes[i]] = 1;
9842 
9843  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", smh->ianacodes[i]);
9844  }
9845 
9846  if (smh->mparams->dtmf_type == DTMF_2833 && smh->mparams->te > 95) {
9847  if (sdp_type == SDP_TYPE_RESPONSE) {
9849  if (a_engine) {
9850  payload_map_t *pmap;
9851  for (pmap = a_engine->payload_map; pmap; pmap = pmap->next) {
9852  if (pmap->pt >= 128 || already_did[pmap->pt]) {
9853  continue;
9854  }
9855 
9856  if (!strncasecmp(pmap->iananame, "telephone-event", 15)) {
9857  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", pmap->pt);
9858  already_did[pmap->pt] = 1;
9859  }
9860  }
9861  }
9862  } else {
9863  int i;
9864 
9865  for (i = 0; i < smh->num_rates; i++) {
9866  if (smh->dtmf_ianacodes[i] < 128 && !already_did[smh->dtmf_ianacodes[i]]) {
9867  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", smh->dtmf_ianacodes[i]);
9868  already_did[smh->dtmf_ianacodes[i]] = 1;
9869  }
9870  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) {
9871  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", smh->cng_ianacodes[i]);
9872  already_did[smh->cng_ianacodes[i]] = 1;
9873  }
9874  }
9875  }
9876  }
9877 
9878  //if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && cng_type && use_cng) {
9879  //switch_snprintf(buf + strlen(buf), buflen - strlen(buf), " %d", cng_type);
9880  //}
9881 
9882  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "\r\n");
9883 
9884 
9885  memset(already_did, 0, sizeof(already_did));
9886 
9887 
9888  for (i = 0; i < smh->mparams->num_codecs; i++) {
9889  const switch_codec_implementation_t *imp = smh->codecs[i];
9890  char *fmtp = imp->fmtp;
9891  int this_ptime = imp->microseconds_per_packet / 1000;
9892 
9893  if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
9894  continue;
9895  }
9896 
9897  if (!strcasecmp(imp->iananame, "ilbc") || !strcasecmp(imp->iananame, "isac")) {
9898  this_ptime = 20;
9899  }
9900 
9901  if (!noptime) {
9902  if (!cur_ptime) {
9903  if (!ptime) {
9904  ptime = this_ptime;
9905  }
9906  } else {
9907  if (this_ptime != cur_ptime) {
9908  continue;
9909  }
9910  }
9911  }
9912 
9913  if (smh->ianacodes[i] >= 128 || already_did[smh->ianacodes[i]]) {
9914  continue;
9915  }
9916 
9917  already_did[smh->ianacodes[i]] = 1;
9918  rate = imp->samples_per_second;
9919 
9920  if (map) {
9921  char key[128] = "";
9922  char *check = NULL;
9923  switch_snprintf(key, sizeof(key), "%s:%u", imp->iananame, imp->bits_per_second);
9924 
9925  if ((check = switch_event_get_header(map, key)) || (check = switch_event_get_header(map, imp->iananame))) {
9926  fmtp = check;
9927  }
9928  }
9929 
9930  if (smh->fmtps[i]) {
9931  fmtp = smh->fmtps[i];
9932  }
9933 
9934 
9935  if (smh->ianacodes[i] > 95 || switch_channel_test_flag(session->channel, CF_VERBOSE_SDP)) {
9936  int channels = get_channels(imp->iananame, imp->number_of_channels);
9937 
9938  if (channels > 1) {
9939  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d/%d\r\n", smh->ianacodes[i], imp->iananame, rate, channels);
9940 
9941  } else {
9942  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d %s/%d\r\n", smh->ianacodes[i], imp->iananame, rate);
9943  }
9944  }
9945 
9946  if (fmtp) {
9947  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=fmtp:%d %s\r\n", smh->ianacodes[i], fmtp);
9948  }
9949  }
9950 
9951 
9952  if ((smh->mparams->dtmf_type == DTMF_2833 || switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF)) && smh->mparams->te > 95) {
9953  if (smh->mparams->dtmf_type == DTMF_2833 && sdp_type == SDP_TYPE_RESPONSE) {
9955  if (a_engine) {
9956  payload_map_t *pmap;
9957  for (pmap = a_engine->payload_map; pmap; pmap = pmap->next) {
9958  if (!strncasecmp(pmap->iananame, "telephone-event", 15)) {
9959  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d telephone-event/%d\r\n",
9960  pmap->pt, pmap->rate);
9961  }
9962  }
9963  }
9964  } else {
9965  uint8_t NDLB_line_flash_16 = switch_channel_var_true(session->channel, "NDLB_line_flash_16");
9966 
9967  for (i = 0; i < smh->num_rates; i++) {
9968  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
9969  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d telephone-event/%d\r\n",
9970  smh->dtmf_ianacodes[i], smh->rates[i]);
9971  }
9972  else {
9973  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d telephone-event/%d\r\na=fmtp:%d 0-%d\r\n",
9974  smh->dtmf_ianacodes[i], smh->rates[i], smh->dtmf_ianacodes[i], (NDLB_line_flash_16 ? 16 : 15));
9975  }
9976  }
9977  }
9978  }
9979 
9980  if (!zstr(a_engine->local_dtls_fingerprint.type) && secure) {
9981  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=fingerprint:%s %s\r\na=setup:%s\r\n", a_engine->local_dtls_fingerprint.type,
9982  a_engine->local_dtls_fingerprint.str, get_setup(a_engine, session, sdp_type));
9983  }
9984 
9985  if (smh->mparams->rtcp_audio_interval_msec) {
9986  if (a_engine->rtcp_mux > 0) {
9987  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp-mux\r\n");
9988  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp:%d IN %s %s\r\n", port, family, ip);
9989  } else {
9990  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp:%d IN %s %s\r\n", port + 1, family, ip);
9991  }
9992  }
9993 
9994  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\r\n", a_engine->ssrc);
9995 
9996  if (a_engine->ice_out.cands[0][0].ready) {
9997  char tmp1[11] = "";
9998  char tmp2[11] = "";
9999  char tmp3[11] = "";
10000  uint32_t c1 = (1<<24)*126 + (1<<8)*65535 + (1<<0)*(256 - 1);
10001  uint32_t c2 = c1 - 1;
10002  ice_t *ice_out;
10003 
10004  tmp1[10] = '\0';
10005  tmp2[10] = '\0';
10006  tmp3[10] = '\0';
10007  switch_stun_random_string(tmp1, 10, "0123456789");
10008  switch_stun_random_string(tmp2, 10, "0123456789");
10009  switch_stun_random_string(tmp3, 10, "0123456789");
10010 
10011  gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, NULL, 0);
10012 
10013  ice_out = &a_engine->ice_out;
10014 
10015  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ssrc:%u cname:%s\r\n", a_engine->ssrc, smh->cname);
10016  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ssrc:%u msid:%s a0\r\n", a_engine->ssrc, smh->msid);
10017  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ssrc:%u mslabel:%s\r\n", a_engine->ssrc, smh->msid);
10018  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ssrc:%u label:%sa0\r\n", a_engine->ssrc, smh->msid);
10019 
10020 
10021  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ice-ufrag:%s\r\n", ice_out->ufrag);
10022  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ice-pwd:%s\r\n", ice_out->pwd);
10023 
10024 
10025  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
10026  tmp1, ice_out->cands[0][0].transport, c1,
10027  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
10028  );
10029 
10030  if (include_external && !zstr(smh->mparams->extsipip)) {
10031  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
10032  tmp3, ice_out->cands[0][0].transport, c1,
10033  smh->mparams->extsipip, ice_out->cands[0][0].con_port
10034  );
10035  }
10036 
10037  if (!zstr(a_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) &&
10038  strcmp(a_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
10039  && a_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
10040 
10041  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",
10042  tmp2, ice_out->cands[0][0].transport, c2,
10043  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
10044  a_engine->local_sdp_ip, a_engine->local_sdp_port
10045  );
10046  }
10047 
10049 
10050 
10051  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
10052  tmp1, ice_out->cands[0][0].transport, c1,
10053  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
10054  );
10055 
10056  if (include_external && !zstr(smh->mparams->extsipip)) {
10057  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
10058  tmp3, ice_out->cands[0][0].transport, c1,
10059  smh->mparams->extsipip, ice_out->cands[0][0].con_port
10060  );
10061  }
10062 
10063  if (!zstr(a_engine->local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) &&
10064  strcmp(a_engine->local_sdp_ip, ice_out->cands[0][1].con_addr)
10065  && a_engine->local_sdp_port != ice_out->cands[0][1].con_port) {
10066 
10067  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",
10068  tmp2, ice_out->cands[0][0].transport, c2,
10069  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
10070  a_engine->local_sdp_ip, a_engine->local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
10071  );
10072  }
10073  }
10074 
10075 
10076 
10077 #ifdef GOOGLE_ICE
10078  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ice-options:google-ice\r\n");
10079 #endif
10080  }
10081 
10082 
10083  if (secure && !switch_channel_test_flag(session->channel, CF_DTLS)) {
10084  int i;
10085 
10086  for (i = 0; smh->crypto_suite_order[i] != CRYPTO_INVALID; i++) {
10088 
10089  if ((a_engine->crypto_type == j || a_engine->crypto_type == CRYPTO_INVALID) && !zstr(a_engine->ssec[j].local_crypto_key)) {
10090  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=crypto:%s\r\n", a_engine->ssec[j].local_crypto_key);
10091  }
10092  }
10093  //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\r\n");
10094  }
10095 
10096  if (cng_type) {
10097  for (i = 0; i < smh->num_rates; i++) {
10098  //if (smh->rates[i] == 8000) {
10099  // switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d CN/%d\r\n", cng_type, smh->rates[i]);
10100  //} else {
10101  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtpmap:%d CN/%d\r\n", smh->cng_ianacodes[i], smh->rates[i]);
10102  //}
10103  }
10104  } else {
10106  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=silenceSupp:off - - - -\r\n");
10107  }
10108  }
10109 
10110  if (append_audio) {
10111  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "%s%s", append_audio, end_of(append_audio) == '\n' ? "" : "\r\n");
10112  }
10113 
10114  if (!cur_ptime) {
10115  cur_ptime = ptime;
10116  }
10117 
10118  if (!noptime && cur_ptime) {
10119  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=ptime:%d\r\n", cur_ptime);
10120  }
10121 
10122  if (!zstr(sr)) {
10123  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=%s\r\n", sr);
10124  }
10125 }
10126 
10127 //?
10129 {
10130  const char *val;
10131  switch_media_handle_t *smh;
10132 
10133  switch_assert(session);
10134 
10135  if (!(smh = session->media_handle)) {
10136  return;
10137  }
10138 
10139  if ((val = switch_channel_get_variable(session->channel, "dtmf_type"))) {
10140  if (!strcasecmp(val, "rfc2833")) {
10141  smh->mparams->dtmf_type = DTMF_2833;
10142  } else if (!strcasecmp(val, "info")) {
10143  smh->mparams->dtmf_type = DTMF_INFO;
10144  } else if (!strcasecmp(val, "none")) {
10145  smh->mparams->dtmf_type = DTMF_NONE;
10146  }
10147  }
10148 }
10149 
10150 //?
10152 {
10153  sdp_media_t *m;
10154  sdp_parser_t *parser = NULL;
10155  sdp_session_t *sdp;
10156 
10157  if (!(parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
10158  return SWITCH_STATUS_FALSE;
10159  }
10160 
10161  if (!(sdp = sdp_session(parser))) {
10162  sdp_parser_free(parser);
10163  return SWITCH_STATUS_FALSE;
10164  }
10165 
10168 
10169  for (m = sdp->sdp_media; m; m = m->m_next) {
10170  if (m->m_proto == sdp_proto_rtp) {
10171  sdp_rtpmap_t *map;
10172 
10173  for (map = m->m_rtpmaps; map; map = map->rm_next) {
10174  if (map->rm_encoding) {
10175  char buf[25] = "";
10176  char key[128] = "";
10177  char *br = NULL;
10178 
10179  if (map->rm_fmtp) {
10180  if ((br = strstr(map->rm_fmtp, "bitrate="))) {
10181  br += 8;
10182  }
10183  }
10184 
10185  switch_snprintf(buf, sizeof(buf), "%d", map->rm_pt);
10186 
10187  if (br) {
10188  switch_snprintf(key, sizeof(key), "%s:%s", map->rm_encoding, br);
10189  } else {
10190  switch_snprintf(key, sizeof(key), "%s", map->rm_encoding);
10191  }
10192 
10194 
10195  if (map->rm_fmtp) {
10196  switch_event_add_header_string(*fmtp, SWITCH_STACK_BOTTOM, key, map->rm_fmtp);
10197  }
10198  }
10199  }
10200  }
10201  }
10202 
10203  sdp_parser_free(parser);
10204 
10205  return SWITCH_STATUS_SUCCESS;
10206 
10207 }
10208 
10209 //?
10211 {
10212  switch_media_handle_t *smh;
10213 
10214  switch_assert(session);
10215 
10216  if (!(smh = session->media_handle)) {
10217  return;
10218  }
10219 
10220  if (smh->sdp_mutex) switch_mutex_lock(smh->sdp_mutex);
10221  smh->mparams->local_sdp_str = dup ? switch_core_session_strdup(session, sdp_str) : (char *) sdp_str;
10222  switch_channel_set_variable(session->channel, "rtp_local_sdp_str", smh->mparams->local_sdp_str);
10223  if (smh->sdp_mutex) switch_mutex_unlock(smh->sdp_mutex);
10224 }
10225 
10226 static void add_fb(char *buf, uint32_t buflen, int pt, int fir, int nack, int pli, int tmmbr)
10227 {
10228  if (fir) {
10229  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp-fb:%d ccm fir\r\n", pt);
10230  }
10231 
10232  if (tmmbr) {
10233  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp-fb:%d ccm tmmbr\r\n", pt);
10234  }
10235 
10236  if (nack) {
10237  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp-fb:%d nack\r\n", pt);
10238  }
10239 
10240  if (pli) {
10241  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), "a=rtcp-fb:%d nack pli\r\n", pt);
10242  }
10243 
10244 }
10245 
10246 //?
10247 #define SDPBUFLEN 65536
10249 {
10250  char *buf;
10251  int ptime = 0;
10252  uint32_t rate = 0;
10253  uint32_t v_port, t_port;
10254  int use_cng = 1;
10255  const char *val;
10256  const char *family;
10257  const char *pass_fmtp = switch_channel_get_variable(session->channel, "rtp_video_fmtp");
10258  const char *ov_fmtp = switch_channel_get_variable(session->channel, "rtp_force_video_fmtp");
10259  const char *append_audio = switch_channel_get_variable(session->channel, "rtp_append_audio_sdp");
10260  const char *append_video = switch_channel_get_variable(session->channel, "rtp_append_video_sdp");
10261  char srbuf[128] = "";
10262  const char *var_val;
10263  const char *username;
10264  const char *fmtp_out;
10265  const char *fmtp_out_var = switch_channel_get_variable(session->channel, "rtp_force_audio_fmtp");
10266  switch_event_t *map = NULL, *ptmap = NULL;
10267  //const char *b_sdp = NULL;
10268  //const char *local_audio_crypto_key = switch_core_session_local_crypto_key(session, SWITCH_MEDIA_TYPE_AUDIO);
10269  const char *tmp;
10270  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
10271  switch_media_handle_t *smh;
10272  ice_t *ice_out;
10273  //int vp8 = 0;
10274  //int red = 0;
10275  payload_map_t *pmap;
10276  int is_outbound = switch_channel_direction(session->channel) == SWITCH_CALL_DIRECTION_OUTBOUND;
10277  const char *vbw;
10278  int bw = 256, i = 0;
10279  uint8_t fir = 0, nack = 0, pli = 0, tmmbr = 0, has_vid = 0;
10280  const char *use_rtcp_mux = NULL;
10281  int include_external;
10282 
10283  switch_assert(session);
10284 
10285  if (!(smh = session->media_handle)) {
10286  return;
10287  }
10288 
10289  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
10290  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
10291  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
10292 
10293  include_external = switch_channel_var_true(session->channel, "include_external_ip");
10294 
10295  use_rtcp_mux = switch_channel_get_variable(session->channel, "rtcp_mux");
10296 
10297  if (use_rtcp_mux && switch_false(use_rtcp_mux)) {
10298  a_engine->rtcp_mux = -1;
10299  v_engine->rtcp_mux = -1;
10300  }
10301 
10302  if ((a_engine->rtcp_mux != -1 && v_engine->rtcp_mux != -1) && (sdp_type == SDP_TYPE_REQUEST)) {
10303  a_engine->rtcp_mux = 1;
10304  v_engine->rtcp_mux = 1;
10305  }
10306 
10307  if (!smh->mparams->rtcp_audio_interval_msec) {
10308  smh->mparams->rtcp_audio_interval_msec = (char *)switch_channel_get_variable(session->channel, "rtcp_audio_interval_msec");
10309  }
10310 
10311  if (!smh->mparams->rtcp_video_interval_msec) {
10312  smh->mparams->rtcp_video_interval_msec = (char *)switch_channel_get_variable(session->channel, "rtcp_video_interval_msec");
10313  }
10314 
10315  if (dtls_ok(session) && (tmp = switch_channel_get_variable(smh->session->channel, "webrtc_enable_dtls")) && switch_false(tmp)) {
10318  }
10319 
10320  if (switch_channel_test_flag(session->channel, CF_PROXY_OFF) && (tmp = switch_channel_get_variable(smh->session->channel, "uuid_media_secure_media"))) {
10321  switch_channel_set_variable(smh->session->channel, "rtp_secure_media", tmp);
10324  }
10325 
10326  if (is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING) ||
10328  if (!switch_channel_test_flag(session->channel, CF_AVPF) &&
10329  switch_true(switch_channel_get_variable(session->channel, "media_webrtc"))) {
10334  }
10335 
10336  if (switch_true(switch_channel_get_variable(session->channel, "add_ice_candidates"))) {
10338  }
10339 
10340  if ( switch_rtp_has_dtls() && dtls_ok(session)) {
10341  if (switch_channel_test_flag(session->channel, CF_AVPF) ||
10342  switch_true(switch_channel_get_variable(smh->session->channel, "rtp_use_dtls"))) {
10346  }
10347  }
10350  }
10351 
10352  fmtp_out = a_engine->cur_payload_map->fmtp_out;
10353  username = smh->mparams->sdp_username;
10354 
10355 
10356  switch_zmalloc(buf, SDPBUFLEN);
10357 
10359 
10361  ((val = switch_channel_get_variable(session->channel, "supress_cng")) && switch_true(val)) ||
10362  ((val = switch_channel_get_variable(session->channel, "suppress_cng")) && switch_true(val))) {
10363  use_cng = 0;
10364  smh->mparams->cng_pt = 0;
10365  }
10366 
10367 
10368 
10369 
10370  if (!smh->payload_space) {
10371  /* it could be 98 but chrome reserves 98 and 99 for some internal stuff even though they should not.
10372  Everyone expects dtmf to be at 101 and Its not worth the trouble so we'll start at 102 */
10373  smh->payload_space = 102;
10374  memset(smh->rates, 0, sizeof(smh->rates));
10375  smh->num_rates = 0;
10376 
10377  for (i = 0; i < smh->mparams->num_codecs; i++) {
10378  int j;
10379  smh->ianacodes[i] = smh->codecs[i]->ianacode;
10380 
10381  if (smh->codecs[i]->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
10382  continue;
10383  }
10384 
10385  if (sdp_type == SDP_TYPE_REQUEST) {
10386  for (j = 0; j < SWITCH_MAX_CODECS; j++) {
10387  if (smh->rates[j] == 0) {
10388  break;
10389  }
10390 
10391  if (smh->rates[j] == smh->codecs[i]->samples_per_second) {
10392  goto do_next;
10393  }
10394  }
10395 
10396  smh->rates[smh->num_rates++] = smh->codecs[i]->samples_per_second;
10397  }
10398 
10399  do_next:
10400  continue;
10401  }
10402 
10403  if (sdp_type == SDP_TYPE_REQUEST) {
10404  switch_core_session_t *orig_session = NULL;
10405 
10406  switch_core_session_get_partner(session, &orig_session);
10407 
10408  if (orig_session && !switch_channel_test_flag(session->channel, CF_ANSWERED)) {
10413  }
10414 
10415  for (i = 0; i < smh->mparams->num_codecs; i++) {
10416  const switch_codec_implementation_t *imp = smh->codecs[i];
10417  switch_payload_t orig_pt = 0;
10418  char *orig_fmtp = NULL;
10419 
10420  if (smh->ianacodes[i] > 64) {
10421  if (smh->mparams->dtmf_type == DTMF_2833 && smh->mparams->te > 95 && smh->mparams->te == smh->payload_space) {
10422  smh->payload_space++;
10423  }
10425  smh->mparams->cng_pt && use_cng && smh->mparams->cng_pt == smh->payload_space) {
10426  smh->payload_space++;
10427  }
10428 
10429  if (orig_session &&
10432  imp->iananame, imp->samples_per_second, smh->fmtp[i], &orig_pt, NULL, &orig_fmtp) == SWITCH_STATUS_SUCCESS) {
10433 
10434  if (orig_pt == smh->mparams->te) {
10435  smh->mparams->te = (switch_payload_t)smh->payload_space++;
10436  }
10437 
10438  smh->ianacodes[i] = orig_pt;
10439 
10440  if (!zstr(orig_fmtp)) {
10441  smh->fmtps[i] = switch_core_session_strdup(session, orig_fmtp);
10442  }
10443  } else {
10444  smh->ianacodes[i] = (switch_payload_t)smh->payload_space++;
10445  }
10446  }
10447 
10450  imp->iananame,
10451  imp->modname,
10452  smh->fmtps[i],
10453  sdp_type,
10454  smh->ianacodes[i],
10455  imp->samples_per_second,
10456  imp->microseconds_per_packet / 1000,
10457  imp->number_of_channels,
10458  SWITCH_FALSE);
10459  }
10460 
10461  for (i = 0; i < smh->num_rates; i++) {
10462  if (smh->rates[i] == 8000 || smh->num_rates == 1) {
10463  smh->dtmf_ianacodes[i] = smh->mparams->te;
10464  smh->cng_ianacodes[i] = smh->mparams->cng_pt;
10465  } else {
10466  int j = 0;
10467 
10468  for (j = 0; j < smh->mparams->num_codecs; j++) {
10469  if (smh->ianacodes[j] == smh->payload_space) {
10470  smh->payload_space++;
10471  break;
10472  }
10473  }
10474 
10475  smh->dtmf_ianacodes[i] = (switch_payload_t)smh->payload_space++;
10476  smh->cng_ianacodes[i] = (switch_payload_t)smh->payload_space++;
10477  }
10478  }
10479 
10480 
10481  if (orig_session) {
10482  switch_core_session_rwunlock(orig_session);
10483  }
10484  }
10485  }
10486 
10487  if (fmtp_out_var) {
10488  fmtp_out = fmtp_out_var;
10489  }
10490 
10491  val = switch_channel_get_variable(session->channel, "verbose_sdp");
10492 
10493  if (!val || switch_true(val)) {
10495  }
10496 
10497  if (!force && !ip && zstr(sr)
10499  switch_safe_free(buf);
10500  return;
10501  }
10502 
10503  if (!ip) {
10504  if (!(ip = a_engine->adv_sdp_ip)) {
10505  ip = a_engine->proxy_sdp_ip;
10506  }
10507  }
10508 
10509  if (!ip) {
10511  switch_safe_free(buf);
10512  return;
10513  }
10514 
10515  if (!port) {
10516  if (!(port = a_engine->adv_sdp_port)) {
10517  port = a_engine->proxy_sdp_port;
10518  }
10519  }
10520 
10521  if (!port) {
10523  switch_safe_free(buf);
10524  return;
10525  }
10526 
10527  //if (!a_engine->cur_payload_map->rm_encoding && (b_sdp = switch_channel_get_variable(session->channel, SWITCH_B_SDP_VARIABLE))) {
10528  //switch_core_media_sdp_map(b_sdp, &map, &ptmap);
10529  //}
10530 
10531  for (i = 0; i < smh->mparams->num_codecs; i++) {
10532  const switch_codec_implementation_t *imp = smh->codecs[i];
10533 
10536  break;
10537  }
10538  }
10539 
10540  if (zstr(sr)) {
10541  if (a_engine->smode == SWITCH_MEDIA_FLOW_SENDONLY) {
10542  sr = "sendonly";
10543  } else if (a_engine->smode == SWITCH_MEDIA_FLOW_RECVONLY) {
10544  sr = "recvonly";
10545  } else if (a_engine->smode == SWITCH_MEDIA_FLOW_INACTIVE) {
10546  sr = "inactive";
10547  } else {
10548  sr = "sendrecv";
10549  }
10550 
10551  if ((var_val = switch_channel_get_variable(session->channel, "origination_audio_mode"))) {
10552  if (!strcasecmp(sr, "sendonly") || !strcasecmp(sr, "recvonly") || !strcasecmp(sr, "sendrecv") || !strcasecmp(sr, "inactive")) {
10553  sr = var_val;
10554  }
10555  switch_channel_set_variable(session->channel, "origination_audio_mode", NULL);
10556  }
10557 
10558  if (zstr(sr)) {
10559  sr = "sendrecv";
10560  }
10561  }
10562 
10563  if (!smh->owner_id) {
10564  smh->owner_id = (uint32_t)(switch_time_t)switch_epoch_time_now(NULL) - port;
10565  }
10566 
10567  if (!smh->session_id) {
10568  smh->session_id = smh->owner_id;
10569  }
10570 
10571  if (switch_true(switch_channel_get_variable_dup(session->channel, "drop_dtmf", SWITCH_FALSE, -1))) {
10573  }
10574 
10575  smh->session_id++;
10576 
10577  if ((smh->mparams->ndlb & SM_NDLB_SENDRECV_IN_SESSION) ||
10578  ((var_val = switch_channel_get_variable(session->channel, "ndlb_sendrecv_in_session")) && switch_true(var_val))) {
10579  if (!zstr(sr)) {
10580  switch_snprintf(srbuf, sizeof(srbuf), "a=%s\r\n", sr);
10581  }
10582  sr = NULL;
10583  }
10584 
10585  family = strchr(ip, ':') ? "IP6" : "IP4";
10587  "v=0\r\n"
10588  "o=%s %010u %010u IN %s %s\r\n"
10589  "s=%s\r\n"
10590  "c=IN %s %s\r\n"
10591  "t=0 0\r\n"
10592  "%s",
10593  username, smh->owner_id, smh->session_id, family, ip, username, family, ip, srbuf);
10594 
10595  if (switch_channel_test_flag(smh->session->channel, CF_ICE) && switch_channel_var_true(session->channel, "ice_lite")) {
10596  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-lite\r\n");
10597  }
10598 
10599  if (a_engine->rmode == SWITCH_MEDIA_FLOW_DISABLED) {
10600  goto video;
10601  }
10602 
10604  gen_ice(session, SWITCH_MEDIA_TYPE_AUDIO, ip, port);
10605  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=msid-semantic: WMS %s\r\n", smh->msid);
10606  }
10607 
10608  if (a_engine->codec_negotiated && !switch_channel_test_flag(session->channel, CF_NOSDP_REINVITE)) {
10609  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=audio %d %s", port,
10610  get_media_profile_name(session, !a_engine->no_crypto &&
10612 
10613 
10614  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", a_engine->cur_payload_map->pt);
10615 
10616 
10619  for (pmap = a_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
10620  if (pmap->pt != a_engine->cur_payload_map->pt) {
10621  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", pmap->pt);
10622  }
10623  }
10625  }
10626 
10627  if ((smh->mparams->dtmf_type == DTMF_2833 || switch_channel_test_flag(session->channel, CF_LIBERAL_DTMF)) && smh->mparams->te > 95) {
10628  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", smh->mparams->te);
10629  }
10630 
10631  if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && smh->mparams->cng_pt && use_cng) {
10632  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", smh->mparams->cng_pt);
10633  }
10634 
10635  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\r\n");
10636 
10637 
10638  rate = a_engine->cur_payload_map->adv_rm_rate;
10639 
10640  if (!a_engine->cur_payload_map->adv_channels) {
10642  }
10643 
10644  if (a_engine->cur_payload_map->adv_channels > 1) {
10645  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\r\n",
10646  a_engine->cur_payload_map->pt, a_engine->cur_payload_map->rm_encoding, rate, a_engine->cur_payload_map->adv_channels);
10647  } else {
10648  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\r\n",
10649  a_engine->cur_payload_map->pt, a_engine->cur_payload_map->rm_encoding, rate);
10650  }
10651 
10652  if (fmtp_out) {
10653  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\r\n", a_engine->cur_payload_map->pt, fmtp_out);
10654  }
10655 
10658  for (pmap = a_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
10659  if (pmap->pt != a_engine->cur_payload_map->pt) {
10660  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\r\n",
10661  pmap->pt, pmap->iananame,
10662  pmap->rate);
10663  }
10664  }
10666  }
10667 
10668 
10669  if (a_engine->read_codec.implementation && !ptime) {
10670  ptime = a_engine->read_codec.implementation->microseconds_per_packet / 1000;
10671  }
10672 
10673 
10675  && smh->mparams->te > 95) {
10676 
10677  if (switch_channel_test_flag(session->channel, CF_AVPF)) {
10678  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d telephone-event/%d\r\n",
10679  smh->mparams->te, smh->mparams->te_rate);
10680  } else {
10681  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d telephone-event/%d\r\na=fmtp:%d 0-%d\r\n",
10682  smh->mparams->te, smh->mparams->te_rate, smh->mparams->te, (switch_channel_var_true(session->channel, "NDLB_line_flash_16") ? 16 : 15));
10683  }
10684  }
10685 
10687  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=silenceSupp:off - - - -\r\n");
10688  } else if (smh->mparams->cng_pt && use_cng) {
10689  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d CN/%lu\r\n", smh->mparams->cng_pt, smh->mparams->cng_rate);
10690 
10691  if (!a_engine->codec_negotiated) {
10692  smh->mparams->cng_pt = 0;
10693  }
10694  }
10695 
10696  if (append_audio) {
10697  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s%s", append_audio, end_of(append_audio) == '\n' ? "" : "\r\n");
10698  }
10699 
10700  if (ptime) {
10701  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ptime:%d\r\n", ptime);
10702  }
10703 
10704 
10705  if (!zstr(sr)) {
10706  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=%s\r\n", sr);
10707  }
10708 
10709 
10710  if (!zstr(a_engine->local_dtls_fingerprint.type)) {
10711  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fingerprint:%s %s\r\na=setup:%s\r\n",
10712  a_engine->local_dtls_fingerprint.type,
10713  a_engine->local_dtls_fingerprint.str, get_setup(a_engine, session, sdp_type));
10714  }
10715 
10716  if (smh->mparams->rtcp_audio_interval_msec) {
10717  if (a_engine->rtcp_mux > 0) {
10718  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp-mux\r\n");
10719  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\r\n", port, family, ip);
10720  } else {
10721  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\r\n", port + 1, family, ip);
10722  }
10723  }
10724 
10725  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\r\n", a_engine->ssrc);
10726 
10727  if (a_engine->ice_out.cands[0][0].ready) {
10728  char tmp1[11] = "";
10729  char tmp2[11] = "";
10730  char tmp3[11] = "";
10731  uint32_t c1 = (1<<24)*126 + (1<<8)*65535 + (1<<0)*(256 - 1);
10732  uint32_t c2 = c1 - 1;
10733  uint32_t c3 = c1 - 2;
10734  uint32_t c4 = c1 - 3;
10735 
10736  tmp1[10] = '\0';
10737  tmp2[10] = '\0';
10738  tmp3[10] = '\0';
10739  switch_stun_random_string(tmp1, 10, "0123456789");
10740  switch_stun_random_string(tmp2, 10, "0123456789");
10741  switch_stun_random_string(tmp3, 10, "0123456789");
10742 
10743  ice_out = &a_engine->ice_out;
10744 
10745 
10746  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-ufrag:%s\r\n", ice_out->ufrag);
10747  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-pwd:%s\r\n", ice_out->pwd);
10748 
10749 
10750  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
10751  tmp1, ice_out->cands[0][0].transport, c1,
10752  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
10753  );
10754 
10755  if (include_external && !zstr(smh->mparams->extsipip)) {
10756  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
10757  tmp3, ice_out->cands[0][0].transport, c1,
10758  smh->mparams->extsipip, ice_out->cands[0][0].con_port
10759  );
10760  }
10761 
10762  if (!zstr(a_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) &&
10763  strcmp(a_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
10764  && a_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
10765 
10766  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",
10767  tmp2, ice_out->cands[0][0].transport, c3,
10768  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
10769  a_engine->local_sdp_ip, a_engine->local_sdp_port
10770  );
10771  }
10772 
10773 
10774  if (a_engine->rtcp_mux < 1 || is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING)) {
10775 
10776  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
10777  tmp1, ice_out->cands[0][0].transport, c2,
10778  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
10779  );
10780 
10781  if (include_external && !zstr(smh->mparams->extsipip)) {
10782  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
10783  tmp3, ice_out->cands[0][0].transport, c2,
10784  smh->mparams->extsipip, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
10785  );
10786  }
10787 
10788 
10789 
10790  if (!zstr(a_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) &&
10791  strcmp(a_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
10792  && a_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
10793 
10794  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",
10795  tmp2, ice_out->cands[0][0].transport, c4,
10796  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (a_engine->rtcp_mux > 0 ? 0 : 1),
10797  a_engine->local_sdp_ip, a_engine->local_sdp_port + (a_engine->rtcp_mux > 0 ? 0 : 1)
10798  );
10799  }
10800  }
10801 
10802  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=end-of-candidates\r\n");
10803 
10804  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u cname:%s\r\n", a_engine->ssrc, smh->cname);
10805  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u msid:%s a0\r\n", a_engine->ssrc, smh->msid);
10806  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u mslabel:%s\r\n", a_engine->ssrc, smh->msid);
10807  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u label:%sa0\r\n", a_engine->ssrc, smh->msid);
10808 
10809 
10810 #ifdef GOOGLE_ICE
10811  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-options:google-ice\r\n");
10812 #endif
10813  }
10814 
10815  if (a_engine->crypto_type != CRYPTO_INVALID && !switch_channel_test_flag(session->channel, CF_DTLS) &&
10816  !zstr(a_engine->ssec[a_engine->crypto_type].local_crypto_key) && switch_channel_test_flag(session->channel, CF_SECURE)) {
10817 
10818  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\r\n", a_engine->ssec[a_engine->crypto_type].local_crypto_key);
10819  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=encryption:optional\r\n");
10820  }
10821 
10822  if (a_engine->reject_avp) {
10823  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=audio 0 RTP/AVP 19\r\n");
10824  }
10825 
10826  } else if (smh->mparams->num_codecs) {
10827  int cur_ptime = 0, this_ptime = 0, cng_type = 0;
10828  const char *mult;
10829 
10830 
10831  if (!switch_media_handle_test_media_flag(smh, SCMF_SUPPRESS_CNG) && smh->mparams->cng_pt && use_cng) {
10832  cng_type = smh->mparams->cng_pt;
10833 
10834  if (!a_engine->codec_negotiated) {
10835  smh->mparams->cng_pt = 0;
10836  }
10837  }
10838 
10839  mult = switch_channel_get_variable(session->channel, "sdp_m_per_ptime");
10840 
10841  if (switch_channel_test_flag(session->channel, CF_AVPF) || (mult && switch_false(mult))) {
10842  char *bp = buf;
10843  int both = (switch_channel_test_flag(session->channel, CF_AVPF) || switch_channel_test_flag(session->channel, CF_DTLS)) ? 0 : 1;
10844 
10845  if ((!a_engine->no_crypto && switch_channel_test_flag(session->channel, CF_SECURE)) ||
10847  generate_m(session, buf, SDPBUFLEN, port, family, ip, 0, append_audio, sr, use_cng, cng_type, map, 1, sdp_type);
10848  bp = (buf + strlen(buf));
10849 
10850  if (smh->crypto_mode == CRYPTO_MODE_MANDATORY) {
10851  both = 0;
10852  }
10853 
10854  }
10855 
10856  if (both) {
10857  generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, 0, append_audio, sr, use_cng, cng_type, map, 0, sdp_type);
10858  }
10859 
10860  } else {
10861 
10862  for (i = 0; i < smh->mparams->num_codecs; i++) {
10863  const switch_codec_implementation_t *imp = smh->codecs[i];
10864 
10865  if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
10866  continue;
10867  }
10868 
10869  this_ptime = imp->microseconds_per_packet / 1000;
10870 
10871  if (!strcasecmp(imp->iananame, "ilbc") || !strcasecmp(imp->iananame, "isac")) {
10872  this_ptime = 20;
10873  }
10874 
10875  if (cur_ptime != this_ptime) {
10876  char *bp = buf;
10877  int both = 1;
10878 
10879  cur_ptime = this_ptime;
10880 
10881  if ((!a_engine->no_crypto && switch_channel_test_flag(session->channel, CF_SECURE)) ||
10883  generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, cur_ptime, append_audio, sr, use_cng, cng_type, map, 1, sdp_type);
10884  bp = (buf + strlen(buf));
10885 
10886  if (smh->crypto_mode == CRYPTO_MODE_MANDATORY) {
10887  both = 0;
10888  }
10889  }
10890 
10892  both = 0;
10893  }
10894 
10895  if (both) {
10896  generate_m(session, bp, SDPBUFLEN - strlen(buf), port, family, ip, cur_ptime, append_audio, sr, use_cng, cng_type, map, 0, sdp_type);
10897  }
10898  }
10899 
10900  }
10901  }
10902 
10903  }
10904 
10906  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=image 0 UDPTL T38\r\n", SWITCH_VA_NONE);
10907 
10908  }
10909 
10910 
10911  video:
10912 
10913 
10915  has_vid = 0;
10916  } else {
10917  for (i = 0; i < smh->mparams->num_codecs; i++) {
10918  const switch_codec_implementation_t *imp = smh->codecs[i];
10919 
10920 
10921  if (imp->codec_type == SWITCH_CODEC_TYPE_VIDEO) {
10922  has_vid = 1;
10923  break;
10924  }
10925  }
10926 
10927  }
10928 
10929 
10930  if (!has_vid) {
10933  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=video 0 %s 19\r\n",
10934  get_media_profile_name(session,
10938  }
10939  } else {
10942  v_engine->no_crypto = 1;
10943  }
10944  }
10945 
10946 
10947  if (!v_engine->local_sdp_port) {
10949  }
10950 
10951  //if (switch_channel_test_flag(session->channel, CF_AVPF)) {
10952  // switch_media_handle_set_media_flag(smh, SCMF_MULTI_ANSWER_VIDEO);
10953  //}
10954 
10955  if ((v_port = v_engine->adv_sdp_port)) {
10956  int loops;
10957  int got_vid = 0;
10958 
10959  for (loops = 0; loops < 2; loops++) {
10960 
10962  gen_ice(session, SWITCH_MEDIA_TYPE_VIDEO, ip, (switch_port_t)v_port);
10963  }
10964 
10965 
10966  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=video %d %s",
10967  v_port,
10968  get_media_profile_name(session,
10969  (loops == 0 && switch_channel_test_flag(session->channel, CF_SECURE)
10972 
10973 
10974 
10975 
10976  /*****************************/
10977  if (v_engine->codec_negotiated) {
10978  payload_map_t *pmap;
10980  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", v_engine->cur_payload_map->pt);
10981 
10984  for (pmap = v_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
10985  if (pmap->pt != v_engine->cur_payload_map->pt && pmap->negotiated) {
10986  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", pmap->pt);
10987  }
10988  }
10990  }
10991 
10992  } else if (smh->mparams->num_codecs) {
10993  int already_did[128] = { 0 };
10994  for (i = 0; i < smh->mparams->num_codecs; i++) {
10995  const switch_codec_implementation_t *imp = smh->codecs[i];
10996 
10997 
10998  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
10999  continue;
11000  }
11001 
11004  continue;
11005  }
11006 
11007  if (smh->ianacodes[i] >= 128 || already_did[smh->ianacodes[i]]) {
11008  continue;
11009  }
11010 
11012  for (pmap = v_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
11013  if (pmap->negotiated && !strcasecmp(imp->iananame, pmap->iananame)) {
11014  smh->ianacodes[i] = pmap->pt;
11015  break;
11016  }
11017  }
11019 
11020  already_did[smh->ianacodes[i]] = 1;
11021 
11022  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", smh->ianacodes[i]);
11023 
11024  if (!ptime) {
11025  ptime = imp->microseconds_per_packet / 1000;
11026  }
11027 
11028  got_vid++;
11029  }
11030  }
11031  if (got_vid && v_engine->smode == SWITCH_MEDIA_FLOW_DISABLED) {
11033  }
11034 
11035  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\r\n");
11036 
11037 
11038  if (!(vbw = switch_channel_get_variable(smh->session->channel, "rtp_video_max_bandwidth"))) {
11039  vbw = switch_channel_get_variable(smh->session->channel, "rtp_video_max_bandwidth_in");
11040  }
11041 
11042  if (!vbw) {
11043  vbw = "1mb";
11044  }
11045 
11047 
11048  if (bw > 0) {
11049  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "b=AS:%d\r\n", bw);
11050  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "b=TIAS:%d\r\n", bw);
11051  }
11052 
11053 
11054 
11055  if (v_engine->codec_negotiated) {
11056  payload_map_t *pmap;
11057 
11058  //if (!strcasecmp(v_engine->cur_payload_map->rm_encoding, "VP8")) {
11059  // vp8 = v_engine->cur_payload_map->pt;
11060  //}
11061 
11062  //if (!strcasecmp(v_engine->cur_payload_map->rm_encoding, "red")) {
11063  // red = v_engine->cur_payload_map->pt;
11064  //}
11065 
11066  rate = v_engine->cur_payload_map->rm_rate;
11067  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\r\n",
11068  v_engine->cur_payload_map->pt, v_engine->cur_payload_map->rm_encoding,
11069  v_engine->cur_payload_map->rm_rate);
11070 
11072  pass_fmtp = v_engine->cur_payload_map->rm_fmtp;
11073  } else {
11074 
11075  pass_fmtp = NULL;
11076 
11077  if (ov_fmtp) {
11078  pass_fmtp = ov_fmtp;
11079  } else {
11080 
11081  pass_fmtp = v_engine->cur_payload_map->fmtp_out;
11082 
11083  if (!pass_fmtp || switch_true(switch_channel_get_variable_dup(session->channel, "rtp_mirror_fmtp", SWITCH_FALSE, -1))) {
11084  pass_fmtp = switch_channel_get_variable(session->channel, "rtp_video_fmtp");
11085  }
11086  }
11087  }
11088 
11089 
11090  if (pass_fmtp) {
11091  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\r\n", v_engine->cur_payload_map->pt, pass_fmtp);
11092  }
11093 
11094 
11097  for (pmap = v_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
11098  if (pmap->pt != v_engine->cur_payload_map->pt && pmap->negotiated) {
11099  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\r\n",
11100  pmap->pt, pmap->iananame, pmap->rate);
11101  }
11102  }
11104  }
11105 
11106 
11107  if (append_video) {
11108  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s%s", append_video, end_of(append_video) == '\n' ? "" : "\r\n");
11109  }
11110 
11111  } else if (smh->mparams->num_codecs) {
11112  int already_did[128] = { 0 };
11113 
11114  for (i = 0; i < smh->mparams->num_codecs; i++) {
11115  const switch_codec_implementation_t *imp = smh->codecs[i];
11116  char *fmtp = NULL;
11117  uint32_t ianacode = smh->ianacodes[i];
11118  int channels;
11119 
11120  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
11121  continue;
11122  }
11123 
11126  continue;
11127  }
11128 
11129  if (ianacode < 128) {
11130  if (already_did[ianacode]) {
11131  continue;
11132  }
11133  already_did[ianacode] = 1;
11134  }
11135 
11136  if (!rate) {
11137  rate = imp->samples_per_second;
11138  }
11139 
11140  channels = get_channels(imp->iananame, imp->number_of_channels);
11141 
11142  //if (!strcasecmp(imp->iananame, "VP8")) {
11143  // vp8 = ianacode;
11144  //}
11145 
11146  //if (!strcasecmp(imp->iananame, "red")) {
11147  // red = ianacode;
11148  //}
11149 
11150  if (channels > 1) {
11151  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d/%d\r\n", ianacode, imp->iananame,
11152  imp->samples_per_second, channels);
11153  } else {
11154  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%d\r\n", ianacode, imp->iananame,
11155  imp->samples_per_second);
11156  }
11157 
11158 
11159 
11160  if (!zstr(ov_fmtp)) {
11161  fmtp = (char *) ov_fmtp;
11162  } else {
11163 
11164  if (map) {
11165  fmtp = switch_event_get_header(map, imp->iananame);
11166  }
11167 
11168  if (!zstr(smh->fmtp[i])) {
11169  fmtp = smh->fmtp[i];
11170  } else if (smh->fmtps[i]) {
11171  fmtp = smh->fmtps[i];
11172  }
11173 
11174  if (zstr(fmtp)) fmtp = imp->fmtp;
11175 
11176  if (zstr(fmtp)) fmtp = (char *) pass_fmtp;
11177  }
11178 
11179  if (!zstr(fmtp) && strcasecmp(fmtp, "_blank_")) {
11180  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fmtp:%d %s\r\n", ianacode, fmtp);
11181  }
11182  }
11183 
11184  }
11185 
11186  if (v_engine->smode == SWITCH_MEDIA_FLOW_SENDRECV) {
11187  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=sendrecv\r\n");
11188  } else if (v_engine->smode == SWITCH_MEDIA_FLOW_SENDONLY) {
11189  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=sendonly\r\n");
11190  } else if (v_engine->smode == SWITCH_MEDIA_FLOW_RECVONLY) {
11191  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=recvonly\r\n");
11192  } else if (v_engine->smode == SWITCH_MEDIA_FLOW_INACTIVE) {
11193  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=inactive\r\n");
11194  }
11195 
11196 
11197  if ((is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING))
11200  }
11201 
11202 
11203  if (!zstr(v_engine->local_dtls_fingerprint.type)) {
11204  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fingerprint:%s %s\r\na=setup:%s\r\n",
11205  v_engine->local_dtls_fingerprint.type, v_engine->local_dtls_fingerprint.str, get_setup(v_engine, session, sdp_type));
11206  }
11207 
11208 
11209  if (smh->mparams->rtcp_video_interval_msec) {
11210  if (v_engine->rtcp_mux > 0) {
11211  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp-mux\r\n");
11212  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\r\n", v_port, family, ip);
11213  } else {
11214  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\r\n", v_port + 1, family, ip);
11215  }
11216  }
11217 
11218  if (sdp_type == SDP_TYPE_REQUEST) {
11219  fir++;
11220  pli++;
11221  nack++;
11222  tmmbr++;
11223  }
11224 
11225  /* DFF nack pli etc */
11226  //nack = v_engine->nack = 0;
11227  //pli = v_engine->pli = 0;
11228 
11229 
11230  if (v_engine->codec_negotiated) {
11231  add_fb(buf, SDPBUFLEN, v_engine->cur_payload_map->pt, v_engine->fir || fir,
11232  v_engine->nack || nack, v_engine->pli || pli, v_engine->tmmbr || tmmbr);
11233 
11236  for (pmap = v_engine->cur_payload_map; pmap && pmap->allocated; pmap = pmap->next) {
11237  if (pmap->pt != v_engine->cur_payload_map->pt && pmap->negotiated) {
11238  add_fb(buf, SDPBUFLEN, pmap->pt, v_engine->fir || fir, v_engine->nack || nack, v_engine->pli || pli, v_engine->tmmbr || tmmbr);
11239  }
11240  }
11242  }
11243 
11244  } else if (smh->mparams->num_codecs) {
11245  int already_did[128] = { 0 };
11246  for (i = 0; i < smh->mparams->num_codecs; i++) {
11247  const switch_codec_implementation_t *imp = smh->codecs[i];
11248 
11249 
11250  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO) {
11251  continue;
11252  }
11253 
11256  continue;
11257  }
11258 
11259  if (smh->ianacodes[i] < 128) {
11260  if (already_did[smh->ianacodes[i]]) {
11261  continue;
11262  }
11263  already_did[smh->ianacodes[i]] = 1;
11264  }
11265 
11266  add_fb(buf, SDPBUFLEN, smh->ianacodes[i], v_engine->fir || fir, v_engine->nack || nack, v_engine->pli || pli, v_engine->pli || pli);
11267  }
11268 
11269  }
11270 
11271  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\r\n", v_engine->ssrc);
11272 
11273  if (v_engine->ice_out.cands[0][0].ready) {
11274  char tmp1[11] = "";
11275  char tmp2[11] = "";
11276  char tmp3[11] = "";
11277  uint32_t c1 = (1<<24)*126 + (1<<8)*65535 + (1<<0)*(256 - 1);
11278  uint32_t c2 = c1 - 1;
11279  uint32_t c3 = c1 - 2;
11280  uint32_t c4 = c1 - 3;
11281 
11282  tmp1[10] = '\0';
11283  tmp2[10] = '\0';
11284  tmp3[10] = '\0';
11285  switch_stun_random_string(tmp1, 10, "0123456789");
11286  switch_stun_random_string(tmp2, 10, "0123456789");
11287  switch_stun_random_string(tmp3, 10, "0123456789");
11288 
11289  ice_out = &v_engine->ice_out;
11290 
11291 
11292  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u cname:%s\r\n", v_engine->ssrc, smh->cname);
11293  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u msid:%s v0\r\n", v_engine->ssrc, smh->msid);
11294  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u mslabel:%s\r\n", v_engine->ssrc, smh->msid);
11295  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u label:%sv0\r\n", v_engine->ssrc, smh->msid);
11296 
11297 
11298 
11299  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-ufrag:%s\r\n", ice_out->ufrag);
11300  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-pwd:%s\r\n", ice_out->pwd);
11301 
11302 
11303  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
11304  tmp1, ice_out->cands[0][0].transport, c1,
11305  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
11306  );
11307 
11308  if (include_external && !zstr(smh->mparams->extsipip)) {
11309  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
11310  tmp3, ice_out->cands[0][0].transport, c1,
11311  smh->mparams->extsipip, ice_out->cands[0][0].con_port
11312  );
11313  }
11314 
11315  if (!zstr(v_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) &&
11316  strcmp(v_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
11317  && v_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
11318 
11319  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",
11320  tmp2, ice_out->cands[0][0].transport, c3,
11321  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
11322  v_engine->local_sdp_ip, v_engine->local_sdp_port
11323  );
11324  }
11325 
11326 
11327  if (v_engine->rtcp_mux < 1 || is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING)) {
11328 
11329  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
11330  tmp1, ice_out->cands[0][0].transport, c2,
11331  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
11332  );
11333 
11334  if (include_external && !zstr(smh->mparams->extsipip)) {
11335  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
11336  tmp3, ice_out->cands[0][0].transport, c2,
11337  smh->mparams->extsipip, ice_out->cands[0][0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
11338  );
11339  }
11340 
11341 
11342  if (!zstr(v_engine->local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) &&
11343  strcmp(v_engine->local_sdp_ip, ice_out->cands[0][1].con_addr)
11344  && v_engine->local_sdp_port != ice_out->cands[0][1].con_port) {
11345 
11346  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx generation 0\r\n",
11347  tmp2, ice_out->cands[0][0].transport, c4,
11348  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (v_engine->rtcp_mux > 0 ? 0 : 1),
11349  v_engine->local_sdp_ip, v_engine->local_sdp_port + (v_engine->rtcp_mux > 0 ? 0 : 1)
11350  );
11351  }
11352  }
11353 
11354 
11355 
11356 #ifdef GOOGLE_ICE
11357  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-options:google-ice\r\n");
11358 #endif
11359  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=end-of-candidates\r\n");
11360 
11361  }
11362 
11363 
11364 
11365  if (loops == 0 && switch_channel_test_flag(session->channel, CF_SECURE) && !switch_channel_test_flag(session->channel, CF_DTLS)) {
11366 
11367  for (i = 0; smh->crypto_suite_order[i] != CRYPTO_INVALID; i++) {
11369 
11370  if ((a_engine->crypto_type == j || a_engine->crypto_type == CRYPTO_INVALID) && !zstr(a_engine->ssec[j].local_crypto_key)) {
11371  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\r\n", v_engine->ssec[j].local_crypto_key);
11372  }
11373  }
11374  //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\r\n");
11375  }
11376 
11377 
11378  if (switch_channel_test_flag(session->channel, CF_DTLS) ||
11381  break;
11382  }
11383  }
11384  }
11385 
11386  }
11387 
11388  if (switch_channel_test_cap(session->channel, CC_MSRP) && !smh->msrp_session) {
11389  int want_msrp = switch_channel_var_true(session->channel, "sip_enable_msrp");
11390  int want_msrps = switch_channel_var_true(session->channel, "sip_enable_msrps");
11391 
11392  if (!want_msrp) {
11393  want_msrp = switch_channel_test_flag(session->channel, CF_WANT_MSRP);
11394  }
11395 
11396  if (!want_msrps) {
11397  want_msrps = switch_channel_test_flag(session->channel, CF_WANT_MSRPS);
11398  }
11399 
11400  if (want_msrp || want_msrps) {
11402 
11404  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "MSRP session created %s\n", smh->msrp_session->call_id);
11405 
11410 
11411  if (want_msrps) {
11413  }
11414 
11416  }
11417  }
11418 
11419  if (smh->msrp_session) {
11420  switch_msrp_session_t *msrp_session = smh->msrp_session;
11421 
11422  if (!zstr(msrp_session->remote_path)) {
11423  if (zstr(msrp_session->local_path)) {
11424  msrp_session->local_path = switch_core_session_sprintf(session,
11425  "msrp%s://%s:%d/%s;tcp",
11426  msrp_session->secure ? "s" : "",
11427  ip, msrp_session->local_port, msrp_session->call_id);
11428  }
11429 
11430  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf),
11431  "m=message %d TCP/%sMSRP *\r\n"
11432  "a=path:%s\r\n"
11433  "a=accept-types:%s\r\n"
11434  "a=accept-wrapped-types:%s\r\n"
11435  "a=setup:%s\r\n",
11436  msrp_session->local_port,
11437  msrp_session->secure ? "TLS/" : "",
11438  msrp_session->local_path,
11439  msrp_session->local_accept_types,
11440  msrp_session->local_accept_wrapped_types,
11441  msrp_session->active ? "active" : "passive");
11442  } else {
11443  char *uuid = switch_core_session_get_uuid(session);
11444  const char *file_selector = switch_channel_get_variable(session->channel, "sip_msrp_local_file_selector");
11445  const char *msrp_offer_active = switch_channel_get_variable(session->channel, "sip_msrp_offer_active");
11446 
11447  if (switch_true(msrp_offer_active)) {
11448  msrp_session->active = 1;
11449  // switch_msrp_start_client(msrp_session);
11450  }
11451 
11452  if (zstr(msrp_session->local_path)) {
11453  msrp_session->local_path = switch_core_session_sprintf(session,
11454  "msrp%s://%s:%d/%s;tcp",
11455  msrp_session->secure ? "s" : "",
11456  ip, msrp_session->local_port, uuid);
11457  }
11458 
11459  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf),
11460  "m=message %d TCP/%sMSRP *\r\n"
11461  "a=path:%s\r\n"
11462  "a=accept-types:message/cpim text/* application/im-iscomposing+xml\r\n"
11463  "a=accept-wrapped-types:*\r\n"
11464  "a=setup:%s\r\n",
11465  msrp_session->local_port,
11466  msrp_session->secure ? "TLS/" : "",
11467  msrp_session->local_path,
11468  msrp_session->active ? "active" : "passive");
11469 
11470  if (!zstr(file_selector)) {
11471  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf),
11472  "a=sendonly\r\na=file-selector:%s\r\n", file_selector);
11473  }
11474  }
11475  }
11476 
11477  // RTP TEXT
11478 
11479  if (sdp_type == SDP_TYPE_RESPONSE && !switch_channel_test_flag(session->channel, CF_RTT)) {
11482  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=text 0 %s 19\r\n",
11483  get_media_profile_name(session,
11487  }
11488  } else if ((switch_channel_test_flag(session->channel, CF_WANT_RTT) || switch_channel_test_flag(session->channel, CF_RTT) ||
11489  switch_channel_var_true(session->channel, "rtp_enable_text")) &&
11491  t_engine->t140_pt = 0;
11492  t_engine->red_pt = 0;
11493 
11494  if (sdp_type == SDP_TYPE_REQUEST) {
11495  t_engine->t140_pt = 96;
11496  t_engine->red_pt = 97;
11497 
11500  "red",
11501  NULL,
11502  NULL,
11504  t_engine->red_pt,
11505  1000,
11506  0,
11507  1,
11508  SWITCH_TRUE);
11509 
11512  "t140",
11513  NULL,
11514  NULL,
11516  t_engine->t140_pt,
11517  1000,
11518  0,
11519  1,
11520  SWITCH_TRUE);
11521 
11522  t_engine->codec_negotiated = 1;
11523  }
11524 
11527  t_engine->no_crypto = 1;
11528  }
11529  }
11530 
11531 
11532  if (!t_engine->local_sdp_port) {
11534  }
11535 
11536  if ((t_port = t_engine->adv_sdp_port)) {
11537  int loops;
11538 
11539  for (loops = 0; loops < 2; loops++) {
11540 
11542  gen_ice(session, SWITCH_MEDIA_TYPE_TEXT, ip, (switch_port_t)t_port);
11543  }
11544 
11545 
11546  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "m=text %d %s",
11547  t_port,
11548  get_media_profile_name(session,
11549  (loops == 0 && switch_channel_test_flag(session->channel, CF_SECURE)
11552 
11553 
11554  /*****************************/
11555  if (t_engine->codec_negotiated) {
11556 
11558  for (pmap = t_engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) {
11559 
11560  if (pmap->type != SWITCH_MEDIA_TYPE_TEXT || !pmap->negotiated) {
11561  continue;
11562  }
11563 
11564  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), " %d", pmap->pt);
11565 
11566  }
11568  } else {
11570  }
11571 
11572  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "\r\n");
11573 
11574  if (t_engine->codec_negotiated) {
11576  for (pmap = t_engine->payload_map; pmap && pmap->allocated; pmap = pmap->next) {
11577 
11578  if (pmap->type != SWITCH_MEDIA_TYPE_TEXT || !pmap->negotiated) {
11579  continue;
11580  }
11581 
11582  if (!strcasecmp(pmap->iananame, "t140")) {
11583  t_engine->t140_pt = pmap->pt;
11584  }
11585 
11586  if (!strcasecmp(pmap->iananame, "red")) {
11587  t_engine->red_pt = pmap->pt;
11588  }
11589 
11590  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtpmap:%d %s/%ld\r\n",
11591  pmap->pt, pmap->iananame, pmap->rate);
11592 
11593  }
11595 
11596 
11597  if (t_engine->t140_pt && t_engine->red_pt) {
11598  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);
11599  }
11600 
11601 
11602  if (t_engine->smode == SWITCH_MEDIA_FLOW_SENDONLY) {
11603  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=sendonly\r\n");
11604  } else if (t_engine->smode == SWITCH_MEDIA_FLOW_RECVONLY) {
11605  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "%s", "a=recvonly\r\n");
11606  }
11607 
11608  }
11609 
11610  if ((is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING))
11613  }
11614 
11615 
11616  if (!zstr(t_engine->local_dtls_fingerprint.type)) {
11617  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=fingerprint:%s %s\r\na=setup:%s\r\n", t_engine->local_dtls_fingerprint.type,
11618  t_engine->local_dtls_fingerprint.str, get_setup(t_engine, session, sdp_type));
11619  }
11620 
11621 
11622  if (smh->mparams->rtcp_text_interval_msec) {
11623  if (t_engine->rtcp_mux > 0) {
11624  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp-mux\r\n");
11625  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\r\n", t_port, family, ip);
11626  } else {
11627  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=rtcp:%d IN %s %s\r\n", t_port + 1, family, ip);
11628  }
11629  }
11630 
11631  //switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u\r\n", t_engine->ssrc);
11632 
11633  if (t_engine->ice_out.cands[0][0].ready) {
11634  char tmp1[11] = "";
11635  char tmp2[11] = "";
11636  uint32_t c1 = (1<<24)*126 + (1<<8)*65535 + (1<<0)*(256 - 1);
11637  uint32_t c2 = c1 - 1;
11638  uint32_t c3 = c1 - 2;
11639  uint32_t c4 = c1 - 3;
11640 
11641  tmp1[10] = '\0';
11642  tmp2[10] = '\0';
11643  switch_stun_random_string(tmp1, 10, "0123456789");
11644  switch_stun_random_string(tmp2, 10, "0123456789");
11645 
11646  ice_out = &t_engine->ice_out;
11647 
11648 
11649  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u cname:%s\r\n", t_engine->ssrc, smh->cname);
11650  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u msid:%s v0\r\n", t_engine->ssrc, smh->msid);
11651  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u mslabel:%s\r\n", t_engine->ssrc, smh->msid);
11652  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ssrc:%u label:%sv0\r\n", t_engine->ssrc, smh->msid);
11653 
11654 
11655 
11656  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-ufrag:%s\r\n", ice_out->ufrag);
11657  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-pwd:%s\r\n", ice_out->pwd);
11658 
11659 
11660  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 1 %s %u %s %d typ host generation 0\r\n",
11661  tmp1, ice_out->cands[0][0].transport, c1,
11662  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port
11663  );
11664 
11665  if (!zstr(t_engine->local_sdp_ip) && !zstr(ice_out->cands[0][0].con_addr) &&
11666  strcmp(t_engine->local_sdp_ip, ice_out->cands[0][0].con_addr)
11667  && t_engine->local_sdp_port != ice_out->cands[0][0].con_port) {
11668 
11669  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",
11670  tmp2, ice_out->cands[0][0].transport, c3,
11671  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port,
11672  t_engine->local_sdp_ip, t_engine->local_sdp_port
11673  );
11674  }
11675 
11676 
11677  if (t_engine->rtcp_mux < 1 || is_outbound || switch_channel_test_flag(session->channel, CF_RECOVERING)) {
11678 
11679  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ host generation 0\r\n",
11680  tmp1, ice_out->cands[0][0].transport, c2,
11681  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (t_engine->rtcp_mux > 0 ? 0 : 1)
11682  );
11683 
11684 
11685  if (!zstr(t_engine->local_sdp_ip) && !zstr(ice_out->cands[0][1].con_addr) &&
11686  strcmp(t_engine->local_sdp_ip, ice_out->cands[0][1].con_addr)
11687  && t_engine->local_sdp_port != ice_out->cands[0][1].con_port) {
11688 
11689  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=candidate:%s 2 %s %u %s %d typ srflx generation 0\r\n",
11690  tmp2, ice_out->cands[0][0].transport, c4,
11691  ice_out->cands[0][0].con_addr, ice_out->cands[0][0].con_port + (t_engine->rtcp_mux > 0 ? 0 : 1),
11692  t_engine->local_sdp_ip, t_engine->local_sdp_port + (t_engine->rtcp_mux > 0 ? 0 : 1)
11693  );
11694  }
11695  }
11696 
11697 
11698 
11699 #ifdef GOOGLE_ICE
11700  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=ice-options:google-ice\r\n");
11701 #endif
11702  }
11703 
11704 
11705 
11706  if (loops == 0 && switch_channel_test_flag(session->channel, CF_SECURE) && !switch_channel_test_flag(session->channel, CF_DTLS)) {
11707 
11708  for (i = 0; smh->crypto_suite_order[i] != CRYPTO_INVALID; i++) {
11710 
11711  if ((t_engine->crypto_type == j || t_engine->crypto_type == CRYPTO_INVALID) && !zstr(t_engine->ssec[j].local_crypto_key)) {
11712  switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf), "a=crypto:%s\r\n", t_engine->ssec[j].local_crypto_key);
11713  }
11714  }
11715  //switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=encryption:optional\r\n");
11716  }
11717 
11718 
11719  if (switch_channel_test_flag(session->channel, CF_DTLS) ||
11722  break;
11723  }
11724  }
11725  }
11726 
11727  }
11728 
11729  if (map) {
11730  switch_event_destroy(&map);
11731  }
11732 
11733  if (ptmap) {
11734  switch_event_destroy(&ptmap);
11735  }
11736 
11738 
11739  check_stream_changes(session, NULL, sdp_type);
11740 
11741  switch_safe_free(buf);
11742 }
11743 
11744 
11745 
11746 //?
11748 {
11749  const char *sdp_str;
11750  switch_rtp_engine_t *a_engine;
11751  switch_media_handle_t *smh;
11752 
11753  switch_assert(session);
11754 
11755  if (!(smh = session->media_handle)) {
11756  return;
11757  }
11758 
11759  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
11760 
11761  if ((sdp_str = switch_channel_get_variable(session->channel, SWITCH_B_SDP_VARIABLE))) {
11762  sdp_parser_t *parser;
11763  sdp_session_t *sdp;
11764  sdp_media_t *m;
11765  sdp_connection_t *connection;
11766 
11767  if ((parser = sdp_parse(NULL, sdp_str, (int) strlen(sdp_str), 0))) {
11768  if ((sdp = sdp_session(parser))) {
11769  for (m = sdp->sdp_media; m; m = m->m_next) {
11770  if (m->m_type != sdp_media_audio || !m->m_port) {
11771  continue;
11772  }
11773 
11774  connection = sdp->sdp_connection;
11775  if (m->m_connections) {
11776  connection = m->m_connections;
11777  }
11778 
11779  if (connection) {
11780  a_engine->proxy_sdp_ip = switch_core_session_strdup(session, connection->c_address);
11781  }
11782  a_engine->proxy_sdp_port = (switch_port_t) m->m_port;
11783  if (a_engine->proxy_sdp_ip && a_engine->proxy_sdp_port) {
11784  break;
11785  }
11786  }
11787  }
11788  sdp_parser_free(parser);
11789  }
11790  switch_core_media_set_local_sdp(session, sdp_str, SWITCH_TRUE);
11791  }
11792 }
11793 
11795 {
11796  int x;
11797 
11798  for (x = 0; x < smh->rej_idx; x++) {
11799  if (smh->rejected_streams[x] == st) {
11800  return SWITCH_TRUE;
11801  }
11802  }
11803 
11804  return SWITCH_FALSE;
11805 }
11806 
11807 //?
11809 {
11810  char buf[2048] = "";
11811  char max_buf[128] = "";
11812  char max_data[128] = "";
11813  const char *ip;
11814  uint32_t port;
11815  const char *family = "IP4";
11816  const char *username;
11817  const char *bit_removal_on = "a=T38FaxFillBitRemoval\r\n";
11818  const char *bit_removal_off = "";
11819 
11820  const char *mmr_on = "a=T38FaxTranscodingMMR\r\n";
11821  const char *mmr_off = "";
11822 
11823  const char *jbig_on = "a=T38FaxTranscodingJBIG\r\n";
11824  const char *jbig_off = "";
11825  const char *var;
11826  int broken_boolean;
11827  switch_media_handle_t *smh;
11828  switch_rtp_engine_t *a_engine;
11829 
11830  switch_assert(session);
11831 
11832  if (!(smh = session->media_handle)) {
11833  return;
11834  }
11835 
11836  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
11837 
11839 
11840  switch_assert(t38_options);
11841 
11842  ip = t38_options->local_ip;
11843  port = t38_options->local_port;
11844  username = smh->mparams->sdp_username;
11845 
11846  var = switch_channel_get_variable(session->channel, "t38_broken_boolean");
11847 
11848  broken_boolean = switch_true(var);
11849 
11850 
11851  if (!ip) {
11852  if (!(ip = a_engine->adv_sdp_ip)) {
11853  ip = a_engine->proxy_sdp_ip;
11854  }
11855  }
11856 
11857  if (!ip) {
11859  return;
11860  }
11861 
11862  if (!port) {
11863  if (!(port = a_engine->adv_sdp_port)) {
11864  port = a_engine->proxy_sdp_port;
11865  }
11866  }
11867 
11868  if (!port) {
11870  return;
11871  }
11872 
11873  if (!smh->owner_id) {
11874  smh->owner_id = (uint32_t)(switch_time_t)switch_epoch_time_now(NULL) - port;
11875  }
11876 
11877  if (!smh->session_id) {
11878  smh->session_id = smh->owner_id;
11879  }
11880 
11881  smh->session_id++;
11882 
11883  family = strchr(ip, ':') ? "IP6" : "IP4";
11884 
11885 
11886  switch_snprintf(buf, sizeof(buf),
11887  "v=0\r\n"
11888  "o=%s %010u %010u IN %s %s\r\n"
11889  "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);
11890 
11891  if (t38_options->T38FaxMaxBuffer) {
11892  switch_snprintf(max_buf, sizeof(max_buf), "a=T38FaxMaxBuffer:%d\r\n", t38_options->T38FaxMaxBuffer);
11893  };
11894 
11895  if (t38_options->T38FaxMaxDatagram) {
11896  switch_snprintf(max_data, sizeof(max_data), "a=T38FaxMaxDatagram:%d\r\n", t38_options->T38FaxMaxDatagram);
11897  };
11898 
11899 
11900 
11901 
11902  if (broken_boolean) {
11903  bit_removal_on = "a=T38FaxFillBitRemoval:1\r\n";
11904  bit_removal_off = "a=T38FaxFillBitRemoval:0\r\n";
11905 
11906  mmr_on = "a=T38FaxTranscodingMMR:1\r\n";
11907  mmr_off = "a=T38FaxTranscodingMMR:0\r\n";
11908 
11909  jbig_on = "a=T38FaxTranscodingJBIG:1\r\n";
11910  jbig_off = "a=T38FaxTranscodingJBIG:0\r\n";
11911 
11912  }
11913 
11914  if (stream_rejected(smh, sdp_media_audio)) {
11915  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
11916  "m=audio 0 RTP/AVP 0\r\n");
11917  }
11918 
11919  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
11920  "m=image %d udptl t38\r\n"
11921  "a=T38FaxVersion:%d\r\n"
11922  "a=T38MaxBitRate:%d\r\n"
11923  "%s"
11924  "%s"
11925  "%s"
11926  "a=T38FaxRateManagement:%s\r\n"
11927  "%s"
11928  "%s"
11929  "a=T38FaxUdpEC:%s\r\n",
11930  //"a=T38VendorInfo:%s\r\n",
11931  port,
11932  t38_options->T38FaxVersion,
11933  t38_options->T38MaxBitRate,
11934  t38_options->T38FaxFillBitRemoval ? bit_removal_on : bit_removal_off,
11935  t38_options->T38FaxTranscodingMMR ? mmr_on : mmr_off,
11936  t38_options->T38FaxTranscodingJBIG ? jbig_on : jbig_off,
11937  t38_options->T38FaxRateManagement,
11938  max_buf,
11939  max_data,
11940  t38_options->T38FaxUdpEC
11941  //t38_options->T38VendorInfo ? t38_options->T38VendorInfo : "0 0 0"
11942  );
11943 
11944 
11945 
11946  if (insist) {
11947  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "m=audio 0 RTP/AVP 19\r\n");
11948  }
11949 
11951 
11952 
11953  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s image media sdp:\n%s\n",
11955 
11956 
11957 }
11958 
11959 
11960 
11961 //?
11963 {
11964  switch_size_t len;
11965  char *p, *q, *pe, *qe;
11966  int has_video = 0, has_audio = 0, has_text = 0, has_ip = 0;
11967  char port_buf[25] = "";
11968  char vport_buf[25] = "";
11969  char tport_buf[25] = "";
11970  char *new_sdp;
11971  int bad = 0;
11972  switch_media_handle_t *smh;
11973  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
11974  payload_map_t *pmap;
11975 
11976  switch_assert(session);
11977 
11978  if (!(smh = session->media_handle)) {
11979  return;
11980  }
11981 
11982  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
11983  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
11984  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
11985 
11986  if (zstr(smh->mparams->local_sdp_str)) {
11987  return;
11988  }
11989 
11990  len = strlen(smh->mparams->local_sdp_str) * 2;
11991 
11992  if (!(smh->mparams->ndlb & SM_NDLB_NEVER_PATCH_REINVITE)) {
11993  if (switch_channel_test_flag(session->channel, CF_ANSWERED) &&
11994  (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))) {
11995  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Skip patch on hold SDP\n");
11996  return;
11997  }
11998  }
11999 
12000  if (zstr(a_engine->local_sdp_ip) || !a_engine->local_sdp_port) {// || switch_channel_test_flag(session->channel, CF_PROXY_MEDIA)) {
12003  switch_channel_get_name(session->channel));
12004  return;
12005  }
12006 
12007  clear_pmaps(a_engine);
12008 
12010 
12011  pmap = switch_core_media_add_payload_map(session,
12013  "PROXY",
12014  NULL,
12015  NULL,
12017  0,
12018  8000,
12019  20,
12020  1,
12021  SWITCH_TRUE);
12022 
12023  a_engine->cur_payload_map = pmap;
12024 
12025  }
12026 
12027  new_sdp = switch_core_session_alloc(session, len);
12028  switch_snprintf(port_buf, sizeof(port_buf), "%u", a_engine->local_sdp_port);
12029 
12030 
12031  p = smh->mparams->local_sdp_str;
12032  q = new_sdp;
12033  pe = p + strlen(p);
12034  qe = q + len - 1;
12035 
12036 
12037  while (p && *p) {
12038  if (p >= pe) {
12039  bad = 1;
12040  goto end;
12041  }
12042 
12043  if (q >= qe) {
12044  bad = 2;
12045  goto end;
12046  }
12047 
12048  if (a_engine->local_sdp_ip && !strncmp("c=IN IP", p, 7)) {
12049  strncpy(q, p, 7);
12050  p += 7;
12051  q += 7;
12052  memcpy(q, strchr(a_engine->adv_sdp_ip, ':') ? "6 " : "4 ", 2);
12053  p +=2;
12054  q +=2;
12055  snprintf(q, qe - q, "%s", a_engine->adv_sdp_ip);
12056  q += strlen(a_engine->adv_sdp_ip);
12057 
12058  while (p && *p && ((*p >= '0' && *p <= '9') || *p == '.' || *p == ':' || (*p >= 'A' && *p <= 'F') || (*p >= 'a' && *p <= 'f'))) {
12059  if (p >= pe) {
12060  bad = 3;
12061  goto end;
12062  }
12063  p++;
12064  }
12065 
12066  has_ip++;
12067 
12068  } else if (!strncmp("o=", p, 2)) {
12069  char *oe = strchr(p, '\n');
12070  switch_size_t len;
12071 
12072  if (oe) {
12073  const char *family = "IP4";
12074  char o_line[1024] = "";
12075 
12076  if (oe >= pe) {
12077  bad = 4;
12078  goto end;
12079  }
12080 
12081  len = (oe - p);
12082  p += len;
12083 
12084 
12085  family = strchr(smh->mparams->sipip, ':') ? "IP6" : "IP4";
12086 
12087  if (!smh->owner_id) {
12088  smh->owner_id = (uint32_t)(switch_time_t) switch_epoch_time_now(NULL) * 31821U + 13849U;
12089  }
12090 
12091  if (!smh->session_id) {
12092  smh->session_id = smh->owner_id;
12093  }
12094 
12095  smh->session_id++;
12096 
12097 
12098  snprintf(o_line, sizeof(o_line), "o=%s %010u %010u IN %s %s\r\n",
12099  smh->mparams->sdp_username, smh->owner_id, smh->session_id, family, smh->mparams->sipip);
12100 
12101  snprintf(q, qe-q, "%s", o_line);
12102  q += strlen(o_line) - 1;
12103 
12104  }
12105 
12106  } else if (!strncmp("s=", p, 2)) {
12107  char *se = strchr(p, '\n');
12108  switch_size_t len;
12109 
12110  if (se) {
12111  char s_line[1024] = "";
12112 
12113  if (se >= pe) {
12114  bad = 5;
12115  goto end;
12116  }
12117 
12118  len = (se - p);
12119  p += len;
12120 
12121  snprintf(s_line, sizeof(s_line), "s=%s\r\n", smh->mparams->sdp_username);
12122  snprintf(q, qe-q, "%s", s_line);
12123 
12124  q += strlen(s_line) - 1;
12125 
12126  }
12127 
12128  } else if ((!strncmp("m=audio ", p, 8) && *(p + 8) != '0') || (!strncmp("m=image ", p, 8) && *(p + 8) != '0')) {
12129  strncpy(q, p, 8);
12130  p += 8;
12131 
12132  if (p >= pe) {
12133  bad = 6;
12134  goto end;
12135  }
12136 
12137 
12138  q += 8;
12139 
12140  if (q >= qe) {
12141  bad = 7;
12142  goto end;
12143  }
12144 
12145 
12146  snprintf(q, qe - q, "%s", port_buf);
12147  q += strlen(port_buf);
12148 
12149  if (q >= qe) {
12150  bad = 8;
12151  goto end;
12152  }
12153 
12154  while (p && *p && (*p >= '0' && *p <= '9')) {
12155  if (p >= pe) {
12156  bad = 9;
12157  goto end;
12158  }
12159  p++;
12160  }
12161 
12162  has_audio++;
12163 
12164  } else if (!strncmp("m=video ", p, 8) && *(p + 8) != '0') {
12165  if (!has_video) {
12167  clear_pmaps(v_engine);
12168  pmap = switch_core_media_add_payload_map(session,
12170  "PROXY-VID",
12171  NULL,
12172  NULL,
12174  0,
12175  90000,
12176  90000,
12177  1,
12178  SWITCH_TRUE);
12179  v_engine->cur_payload_map = pmap;
12180 
12181  switch_snprintf(vport_buf, sizeof(vport_buf), "%u", v_engine->adv_sdp_port);
12182 
12183  if (switch_channel_media_ready(session->channel) && !switch_rtp_ready(v_engine->rtp_session)) {
12187  }
12188 
12189  v_engine->codec_negotiated = 1;
12191  }
12192 
12193  strncpy(q, p, 8);
12194  p += 8;
12195 
12196  if (p >= pe) {
12197  bad = 10;
12198  goto end;
12199  }
12200 
12201  q += 8;
12202 
12203  if (q >= qe) {
12204  bad = 11;
12205  goto end;
12206  }
12207 
12208  snprintf(q, qe-q, "%s", vport_buf);
12209  q += strlen(vport_buf);
12210 
12211  if (q >= qe) {
12212  bad = 12;
12213  goto end;
12214  }
12215 
12216  while (p && *p && (*p >= '0' && *p <= '9')) {
12217 
12218  if (p >= pe) {
12219  bad = 13;
12220  goto end;
12221  }
12222 
12223  p++;
12224  }
12225 
12226  has_video++;
12227  } else if (!strncmp("m=text ", p, 7) && *(p + 7) != '0') {
12228  if (!has_text) {
12230  clear_pmaps(t_engine);
12231  pmap = switch_core_media_add_payload_map(session,
12233  "PROXY-TXT",
12234  NULL,
12235  NULL,
12237  0,
12238  90000,
12239  90000,
12240  1,
12241  SWITCH_TRUE);
12242  t_engine->cur_payload_map = pmap;
12243 
12244  switch_snprintf(tport_buf, sizeof(tport_buf), "%u", t_engine->adv_sdp_port);
12245 
12246  if (switch_channel_media_ready(session->channel) && !switch_rtp_ready(t_engine->rtp_session)) {
12250  }
12251 
12252  t_engine->codec_negotiated = 1;
12253  //TEXT switch_core_media_set_text_codec(session, SWITCH_FALSE);
12254  }
12255 
12256  strncpy(q, p, 7);
12257  p += 7;
12258 
12259  if (p >= pe) {
12260  bad = 14;
12261  goto end;
12262  }
12263 
12264  q += 7;
12265 
12266  if (q >= qe) {
12267  bad = 15;
12268  goto end;
12269  }
12270 
12271  snprintf(q, qe-q, "%s", tport_buf);
12272  q += strlen(tport_buf);
12273 
12274  if (q >= qe) {
12275  bad = 16;
12276  goto end;
12277  }
12278 
12279  while (p && *p && (*p >= '0' && *p <= '9')) {
12280 
12281  if (p >= pe) {
12282  bad = 17;
12283  goto end;
12284  }
12285 
12286  p++;
12287  }
12288 
12289  has_text++;
12290  }
12291 
12292 
12293  while (p && *p && *p != '\n') {
12294 
12295  if (p >= pe) {
12296  bad = 18;
12297  goto end;
12298  }
12299 
12300  if (q >= qe) {
12301  bad = 19;
12302  goto end;
12303  }
12304 
12305  *q++ = *p++;
12306  }
12307 
12308  if (p >= pe) {
12309  bad = 20;
12310  goto end;
12311  }
12312 
12313  if (q >= qe) {
12314  bad = 21;
12315  goto end;
12316  }
12317 
12318  *q++ = *p++;
12319 
12320  }
12321 
12322  end:
12323 
12324  if (bad) {
12325  return;
12326  }
12327 
12328 
12329  if (switch_channel_down(session->channel)) {
12331  return;
12332  }
12333 
12334 
12335  if (!has_ip && !has_audio) {
12336  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SDP has no audio in it.\n%s\n",
12338  return;
12339  }
12340 
12341 
12342  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Patched SDP\n---\n%s\n+++\n%s\n",
12343  switch_channel_get_name(session->channel), smh->mparams->local_sdp_str, new_sdp);
12344 
12345  switch_core_media_set_local_sdp(session, new_sdp, SWITCH_FALSE);
12346 
12347 }
12348 
12349 //?
12351 {
12352  switch_media_handle_t *smh;
12353  switch_rtp_engine_t *a_engine;
12354 
12355  switch_assert(session);
12356 
12357  if (!(smh = session->media_handle)) {
12358  return;
12359  }
12360 
12361  if (switch_channel_down(session->channel)) {
12362  return;
12363  }
12364 
12365  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
12366 
12367 
12368  if (switch_rtp_ready(a_engine->rtp_session)) {
12369  char *remote_host = switch_rtp_get_remote_host(a_engine->rtp_session);
12370  switch_port_t remote_port = switch_rtp_get_remote_port(a_engine->rtp_session);
12371  const char *err, *val;
12372 
12375 
12376  if (!t38_options || !t38_options->remote_ip) {
12377  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No remote address\n");
12378  return;
12379  }
12380 
12381  if (remote_host && remote_port && remote_port == t38_options->remote_port && !strcmp(remote_host, t38_options->remote_ip)) {
12382  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote address:port [%s:%d] has not changed.\n",
12383  t38_options->remote_ip, t38_options->remote_port);
12384  return;
12385  }
12386 
12387  if (switch_rtp_set_remote_address(a_engine->rtp_session, t38_options->remote_ip,
12388  t38_options->remote_port, 0, SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) {
12389  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "IMAGE UDPTL REPORTS ERROR: [%s]\n", err);
12390  } else {
12391  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IMAGE UDPTL CHANGING DEST TO: [%s:%d]\n",
12392  t38_options->remote_ip, t38_options->remote_port);
12394  !((val = switch_channel_get_variable(session->channel, "disable_udptl_auto_adjust")) && switch_true(val))) {
12395  /* Reactivate the NAT buster flag. */
12397  }
12398  }
12399  }
12400 }
12401 
12402 //?
12404 {
12405  switch_core_session_message_t msg = { 0 };
12406 
12407  msg.from = __FILE__;
12408 
12410  msg.numeric_arg = on;
12411  switch_core_session_receive_message(session, &msg);
12412 }
12413 
12414 SWITCH_DECLARE(cJSON *) switch_core_media_gen_json_constraint(float min, float ideal, float max)
12415 {
12416  cJSON *ret = NULL, *n = NULL;
12417 
12418  if ((!ideal && !max)) {
12419  ret = cJSON_CreateNumber(min);
12420  } else {
12421  ret = cJSON_CreateObject();
12422  n = cJSON_CreateNumber(min);
12423  cJSON_AddItemToObject(ret, "min", n);
12424 
12425  if (ideal) {
12426  n = cJSON_CreateNumber(ideal);
12427  cJSON_AddItemToObject(ret, "ideal", n);
12428  }
12429 
12430  if (max) {
12431  n = cJSON_CreateNumber(max);
12432  cJSON_AddItemToObject(ret, "max", n);
12433  }
12434  }
12435 
12436  return ret;
12437 }
12438 
12439 static cJSON *parse_val(char *str) {
12440  char *argv[3];
12441  int argc = 0;
12442  float min = 0, ideal = 0, max = 0;
12443 
12444  argc = switch_separate_string(str, ':', argv, (sizeof(argv) / sizeof(argv[0])));
12445 
12446  if (argc > 0) {
12447  min = atof(argv[0]);
12448  }
12449 
12450  if (argc > 1) {
12451  ideal = atof(argv[1]);
12452  }
12453 
12454  if (argc > 2) {
12455  max = atof(argv[2]);
12456  }
12457 
12458  return switch_core_media_gen_json_constraint(min, ideal, max);
12459 
12460 }
12461 
12463 {
12464  switch_core_session_message_t msg = { 0 };
12465  char *parse = NULL;
12466  char *argv[25];
12467  int argc = 0, i;
12469  cJSON *obj = NULL;
12470  char *aspect = NULL, *fps = NULL, *width = NULL, *height = NULL, *jtmp = NULL;
12471 
12472 
12474  return SWITCH_STATUS_INUSE;
12475  }
12476 
12477  if (switch_stristr("=", json)) {
12478  char *name, *val;
12479  cJSON *video, *p;
12480  int vid = 0;
12481 
12482  parse = strdup(json);
12483  argc = switch_separate_string(parse, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
12484 
12485  for(i = 0; i < argc; i++) {
12486  name = argv[i];
12487  if ((val = strchr(name, '='))) {
12488  *val++ = '\0';
12489  }
12490 
12491  if (val) {
12492  if (!strcmp(name, "aspect")) {
12493  aspect = val;
12494  vid++;
12495  } else if (!strcmp(name, "fps")) {
12496  fps = val;
12497  vid++;
12498  } else if (!strcmp(name, "width")) {
12499  width = val;
12500  vid++;
12501  } else if (!strcmp(name, "height")) {
12502  height = val;
12503  vid++;
12504  }
12505  }
12506  }
12507 
12508  obj = cJSON_CreateObject();
12509 
12510  if (vid) {
12511  video = cJSON_CreateObject();
12512 
12513  if (fps) {
12514  p = parse_val(fps);
12515  cJSON_AddItemToObject(video, "frameRate", p);
12516  }
12517 
12518  if (width) {
12519  p = parse_val(width);
12520  cJSON_AddItemToObject(video, "width", p);
12521  }
12522 
12523  if (height) {
12524  p = parse_val(height);
12525  cJSON_AddItemToObject(video, "height", p);
12526  }
12527 
12528  if (aspect) {
12529  p = cJSON_CreateNumber(atof(aspect));
12530  cJSON_AddItemToObject(video, "aspectRatio", p);
12531  }
12532 
12533  cJSON_AddItemToObject(obj, "video", video);
12534  }
12535 
12536  jtmp = cJSON_PrintUnformatted(obj);
12537  json = jtmp;
12538  }
12539 
12540 
12541 
12542  msg.from = __FILE__;
12543 
12545  msg.string_arg = json;
12546  r = switch_core_session_receive_message(session, &msg);
12547 
12548  switch_safe_free(parse);
12549  switch_safe_free(jtmp);
12550  if (obj) {
12551  cJSON_Delete(obj);
12552  }
12553 
12554  return r;
12555 }
12556 
12558 {
12560  int flags = 0;
12561  switch_status_t status;
12562 
12563  if (dtls_state == DS_READY || dtls_state >= DS_FAIL) return 0;
12564 
12565  status = switch_rtp_zerocopy_read_frame(engine->rtp_session, &engine->read_frame, flags);
12566 
12567  if (!SWITCH_READ_ACCEPTABLE(status)) {
12568  return 0;
12569  }
12570 
12571  return 1;
12572 }
12573 
12575 {
12576  switch_media_handle_t *smh;
12577  switch_rtp_engine_t *engine;
12578  int checking = 0;
12579 
12580  switch_assert(session);
12581 
12582  if (!(smh = session->media_handle)) {
12583  return SWITCH_FALSE;
12584  }
12585 
12586  if (!switch_channel_media_up(session->channel)) {
12587  return SWITCH_FALSE;
12588  }
12589 
12590  if (!switch_channel_test_flag(session->channel, CF_DTLS)) {
12591  return SWITCH_TRUE;
12592  }
12593 
12594  engine = &smh->engines[type];
12595 
12596  if (engine->rmode == SWITCH_MEDIA_FLOW_DISABLED) {
12597  return SWITCH_TRUE;
12598  }
12599 
12600  do {
12601  if (engine->rtp_session) checking = check_engine(engine);
12602  } while (switch_channel_ready(session->channel) && checking);
12603 
12604  if (!checking) {
12605  return SWITCH_TRUE;
12606  }
12607 
12608  return SWITCH_FALSE;
12609 }
12610 
12612 {
12613  switch_media_handle_t *smh;
12614  switch_rtp_engine_t *engine;
12615 
12616  if (!(smh = session->media_handle)) {
12617  return 0;
12618  }
12619 
12620  if (switch_channel_down(session->channel)) {
12621  return 0;
12622  }
12623 
12624  engine = &smh->engines[type];
12625 
12626  if (engine) {
12627  return engine->orig_bitrate;
12628  } else {
12629  return 0;
12630  }
12631 }
12632 
12634 {
12635  switch_media_handle_t *smh;
12636  switch_rtp_engine_t *engine;
12638  uint32_t new_bitrate;
12639 
12640  if (!(smh = session->media_handle)) {
12641  return SWITCH_STATUS_FALSE;
12642  }
12643 
12644  if (switch_channel_down(session->channel)) {
12645  return SWITCH_STATUS_FALSE;
12646  }
12647 
12648  engine = &smh->engines[type];
12649 
12650  new_bitrate = bitrate - bitrate * engine->bw_mult;
12651  if (switch_core_codec_ready(&engine->write_codec)) {
12653  SCCT_INT, &new_bitrate, SCCT_NONE, NULL, NULL, NULL);
12654  }
12655  engine->orig_bitrate = bitrate;
12656 
12657  return status;
12658 }
12659 
12661 {
12662  switch_media_handle_t *smh;
12663  switch_rtp_engine_t *engine;
12664 
12665  if (!(smh = session->media_handle)) {
12666  return 0;
12667  }
12668 
12669  if (switch_channel_down(session->channel)) {
12670  return 0;
12671  }
12672 
12673  engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
12674 
12675  if (engine) {
12676  return engine->bw_mult;
12677  }
12678  return 0;
12679 }
12680 
12682 {
12683  switch_media_handle_t *smh;
12684  switch_rtp_engine_t *engine;
12685 
12686  if (!(smh = session->media_handle)) {
12687  return;
12688  }
12689 
12690  if (switch_channel_down(session->channel)) {
12691  return;
12692  }
12693 
12694  engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
12695 
12696  if (engine) {
12697  engine->bw_mult = mult;
12698  }
12699 }
12700 
12701 //?
12703 {
12704  switch_media_handle_t *smh;
12705  switch_rtp_engine_t *engine;
12706 
12707  switch_assert(session);
12708 
12709  if (!(smh = session->media_handle)) {
12710  return SWITCH_STATUS_FALSE;
12711  }
12712 
12713  engine = &smh->engines[type];
12714 
12715  if (switch_rtp_ready(engine->rtp_session)) {
12717  return SWITCH_STATUS_SUCCESS;
12718  }
12719 
12720  return SWITCH_STATUS_FALSE;
12721 }
12722 
12723 //?
12725 {
12726  switch_media_handle_t *smh;
12727  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
12729 
12730  switch_assert(session);
12731 
12732  if (!(smh = session->media_handle)) {
12733  return SWITCH_STATUS_FALSE;
12734  }
12735 
12736  if (switch_channel_down(session->channel)) {
12737  return SWITCH_STATUS_FALSE;
12738  }
12739 
12740  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
12741  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
12742  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
12743 
12744  switch (msg->message_id) {
12745 
12747  {
12748  if (switch_rtp_ready(a_engine->rtp_session)) {
12750  switch_rtp_reset_jb(a_engine->rtp_session);
12751  }
12752 
12755  }
12756  }
12757  break;
12758 
12760  {
12761  if (a_engine && a_engine->rtp_session) {
12764  }
12765 
12766  if (v_engine && v_engine->rtp_session) {
12768  }
12769  }
12770  break;
12771 
12773  {
12774  if (a_engine && a_engine->rtp_session) {
12777  }
12778 
12779  if (v_engine && v_engine->rtp_session) {
12781  }
12782  }
12783  break;
12784 
12786  {
12787  if (v_engine->rtp_session) {
12791  }// else {
12794  }
12795  //}
12796  }
12797  }
12798  }
12799 
12800  break;
12801 
12803  {
12804  if (switch_rtp_ready(a_engine->rtp_session)) {
12805  if (msg->numeric_arg) {
12807  } else {
12809  }
12810  }
12811  }
12812  break;
12813 
12815  {
12816  if (switch_rtp_ready(a_engine->rtp_session)) {
12817  check_jb(session, msg->string_arg, 0, 0, SWITCH_FALSE);
12818  }
12819  }
12820  break;
12821 
12823  if (a_engine->rtp_session) {
12824  a_engine->last_seq = 0;
12825 
12826  if (session->bugs && msg->numeric_arg) {
12828  "%s has a media bug, hard mute not allowed.\n", switch_channel_get_name(session->channel));
12829  } else {
12830  if (msg->numeric_arg) {
12832  } else {
12834  }
12835 
12837  }
12838  }
12839 
12840  break;
12841 
12843  {
12844  if (v_engine->rtp_session) {
12846  }
12847  }
12848  break;
12849 
12851  {
12852  if (v_engine->rtp_session) {
12854  }
12855  }
12856  break;
12857 
12859  {
12860  switch_rtp_engine_t *engine = &smh->engines[msg->numeric_reply];
12861  uint32_t level = (uint32_t) msg->numeric_arg;
12862 
12863  if (engine->rtp_session) {
12864  switch_core_codec_control(&engine->read_codec, SCC_DEBUG, SCCT_INT, (void *)&level, SCCT_NONE, NULL, NULL, NULL);
12865  switch_core_codec_control(&engine->write_codec, SCC_DEBUG, SCCT_INT, (void *)&level, SCCT_NONE, NULL, NULL, NULL);
12866  }
12867  }
12868  break;
12869 
12871  {
12872  switch_rtp_engine_t *engine;
12876  void *reply = NULL;
12877 
12878  if (!strcasecmp(msg->string_array_arg[0], "video")) {
12879  type = SWITCH_MEDIA_TYPE_VIDEO;
12880  }
12881 
12882  if (!strcasecmp(msg->string_array_arg[1], "write")) {
12883  iotype = SWITCH_IO_WRITE;
12884  }
12885 
12886  engine = &smh->engines[type];
12887 
12888  if (engine->rtp_session) {
12889  if (iotype == SWITCH_IO_READ) {
12891  SCCT_STRING, (void *)msg->string_array_arg[2],
12892  SCCT_STRING, (void *)msg->string_array_arg[3], &reply_type, &reply);
12893  } else {
12895  SCCT_STRING, (void *)msg->string_array_arg[2],
12896  SCCT_STRING, (void *)msg->string_array_arg[3], &reply_type, &reply);
12897  }
12898 
12899 
12900  if (reply_type == SCCT_STRING) {
12901  msg->string_array_arg[4] = (char *)reply;
12902  }
12903  }
12904  }
12905  break;
12906 
12908  {
12909  switch_rtp_t *rtp = a_engine->rtp_session;
12910  const char *direction = msg->string_array_arg[0];
12911 
12912  if (direction && *direction == 'v') {
12913  direction++;
12914  rtp = v_engine->rtp_session;
12915  } else if (direction && *direction == 't' && t_engine) {
12916  direction++;
12917  rtp = t_engine->rtp_session;
12918  }
12919 
12920  if (switch_rtp_ready(rtp) && !zstr(direction) && !zstr(msg->string_array_arg[1])) {
12922  int both = !strcasecmp(direction, "both");
12923  int set = 0;
12924 
12925  if (both || !strcasecmp(direction, "read")) {
12927  set++;
12928  }
12929 
12930  if (both || !strcasecmp(direction, "write")) {
12932  set++;
12933  }
12934 
12935  if (set) {
12936  if (switch_true(msg->string_array_arg[1])) {
12937  switch_rtp_set_flags(rtp, flags);
12938  } else {
12939  switch_rtp_clear_flags(rtp, flags);
12940  }
12941  } else {
12942  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Options\n");
12943  }
12944  }
12945  }
12946  goto end;
12949  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Pass 2833 mode may not work on a transcoded call.\n");
12950  }
12951  goto end;
12952 
12954  {
12955 
12956 #if 0
12957  if (switch_rtp_ready(v_engine->rtp_session)) {
12958  const char *val;
12959 
12960  if ((!(val = switch_channel_get_variable(session->channel, "rtp_jitter_buffer_during_bridge")) || switch_false(val))) {
12963  "%s PAUSE Jitterbuffer\n", switch_channel_get_name(session->channel));
12966  }
12967  }
12968  }
12969 #endif
12970 
12971  if (switch_rtp_ready(a_engine->rtp_session)) {
12972  const char *val;
12973  int ok = 0;
12974 
12975  if (!switch_channel_test_flag(session->channel, CF_VIDEO_READY) &&
12976  (!(val = switch_channel_get_variable(session->channel, "rtp_jitter_buffer_during_bridge")) || switch_false(val))) {
12979  "%s PAUSE Jitterbuffer\n", switch_channel_get_name(session->channel));
12982  }
12983  }
12984 
12988  "%s activate passthru 2833 mode.\n", switch_channel_get_name(session->channel));
12989  }
12990 
12991 
12992  if ((val = switch_channel_get_variable(session->channel, "rtp_notimer_during_bridge"))) {
12993  ok = switch_true(val);
12994  } else {
12996  }
12997 
12999  ok = 0;
13000  }
13001 
13002  if (ok) {
13004  //switch_rtp_clear_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
13006  }
13007 
13009  /* these are not compat */
13010  ok = 0;
13011  } else {
13012  if ((val = switch_channel_get_variable(session->channel, "rtp_autoflush_during_bridge"))) {
13013  ok = switch_true(val);
13014  } else {
13016  }
13017  }
13018 
13019  if (ok) {
13022  } else {
13024  }
13025 
13026  }
13027  }
13028  goto end;
13030 
13031 #if 0
13032  if (switch_rtp_ready(v_engine->rtp_session)) {
13033 
13034  if (switch_test_flag(smh, SMF_VB_PAUSED)) {
13037  "%s RESUME Video Jitterbuffer\n", switch_channel_get_name(session->channel));
13039 
13040  }
13041  }
13042 #endif
13043 
13044  if (switch_rtp_ready(a_engine->rtp_session)) {
13045 
13046  if (switch_test_flag(smh, SMF_JB_PAUSED)) {
13050  "%s RESUME Jitterbuffer\n", switch_channel_get_name(session->channel));
13052  }
13053  }
13054 
13055 
13057  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s deactivate passthru 2833 mode.\n",
13058  switch_channel_get_name(session->channel));
13060  }
13061 
13066  //switch_rtp_set_flag(a_engine->rtp_session, SWITCH_RTP_FLAG_NOBLOCK);
13067  }
13069  }
13070 
13074  } else {
13076  }
13077 
13078  }
13079  goto end;
13081  if (switch_rtp_ready(a_engine->rtp_session)) {
13082  switch_rtp_reset_jb(a_engine->rtp_session);
13084  }
13085  goto end;
13086 
13088  if (switch_rtp_ready(v_engine->rtp_session)) {
13089  switch_rtp_reset_jb(v_engine->rtp_session);
13090  switch_rtp_flush(v_engine->rtp_session);
13091  }
13092  goto end;
13095  {
13096 
13097  a_engine->codec_negotiated = 0;
13098  v_engine->codec_negotiated = 0;
13099 
13100  if (session->track_duration) {
13102  }
13103  }
13104  break;
13105 
13109  break;
13111  {
13112  const char *uuid;
13113  switch_core_session_t *other_session;
13114  switch_channel_t *other_channel;
13115  const char *ip = NULL, *port = NULL;
13116 
13118 
13120 
13121  if (switch_true(switch_channel_get_variable(session->channel, "bypass_keep_codec"))) {
13122  switch_channel_set_variable(session->channel, "absolute_codec_string", switch_channel_get_variable(session->channel, "ep_codec_string"));
13123  }
13124 
13125 
13126  if ((uuid = switch_channel_get_partner_uuid(session->channel))
13127  && (other_session = switch_core_session_locate(uuid))) {
13128  other_channel = switch_core_session_get_channel(other_session);
13131  switch_core_session_rwunlock(other_session);
13132 
13133  if (ip && port) {
13135  clear_pmaps(a_engine);
13136  clear_pmaps(v_engine);
13137  switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, ip, (switch_port_t)atoi(port), NULL, 1);
13138  }
13139  }
13140 
13141 
13142  if (!smh->mparams->local_sdp_str) {
13144  }
13145 
13146  if (session->track_duration) {
13148  }
13149 
13150  }
13151  break;
13152 
13153 
13154  default:
13155  break;
13156  }
13157 
13158 
13159  if (smh->mutex) switch_mutex_lock(smh->mutex);
13160 
13161 
13162  if (switch_channel_down(session->channel)) {
13163  status = SWITCH_STATUS_FALSE;
13164  goto end_lock;
13165  }
13166 
13167  switch (msg->message_id) {
13169  {
13170  switch_core_session_t *nsession;
13171 
13172  if (msg->string_arg) {
13173  switch_channel_set_variable(session->channel, "absolute_codec_string", NULL);
13174 
13175  if (*msg->string_arg == '=') {
13176  switch_channel_set_variable(session->channel, "codec_string", msg->string_arg);
13177  } else {
13179  "codec_string", "=%s", switch_channel_get_variable(session->channel, "ep_codec_string"));
13180  }
13181 
13182  a_engine->codec_negotiated = 0;
13183  v_engine->codec_negotiated = 0;
13184  smh->num_negotiated_codecs = 0;
13188 
13189  switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 1);
13190  }
13191 
13192  if (msg->numeric_arg && switch_core_session_get_partner(session, &nsession) == SWITCH_STATUS_SUCCESS) {
13193  msg->numeric_arg = 0;
13194  switch_core_session_receive_message(nsession, msg);
13195  switch_core_session_rwunlock(nsession);
13196  }
13197 
13198  }
13199  break;
13200 
13202  {
13203  if (switch_rtp_ready(a_engine->rtp_session)) {
13204  if (msg->numeric_arg) {
13208  }
13209 
13211 
13212  } else {
13213  if (switch_test_flag(smh, SMF_JB_PAUSED)) {
13217  }
13218  }
13219  }
13220  }
13221  }
13222  break;
13223 
13225  {
13226  switch_t38_options_t *t38_options = switch_channel_get_private(session->channel, "t38_options");
13227 
13228  if (t38_options) {
13229  switch_core_media_start_udptl(session, t38_options);
13230  }
13231 
13232  }
13233 
13234 
13235  default:
13236  break;
13237  }
13238 
13239 
13240  end_lock:
13241 
13242  if (smh->mutex) switch_mutex_unlock(smh->mutex);
13243 
13244  end:
13245 
13246  if (switch_channel_down(session->channel)) {
13247  status = SWITCH_STATUS_FALSE;
13248  }
13249 
13250  return status;
13251 
13252 }
13253 
13254 //?
13256 {
13257  switch_media_handle_t *smh;
13258 
13259  switch_assert(session);
13260 
13261  if (!(smh = session->media_handle)) {
13262  return;
13263  }
13264 
13265  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13266  switch_rtp_break(smh->engines[type].rtp_session);
13267  }
13268 }
13269 
13270 //?
13272 {
13273  switch_media_handle_t *smh;
13274 
13275  switch_assert(session);
13276 
13277  if (!(smh = session->media_handle)) {
13278  return;
13279  }
13280 
13281  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13283  }
13284 }
13285 
13286 //?
13288 {
13289  switch_media_handle_t *smh;
13290 
13291  switch_assert(session);
13292 
13293  if (!(smh = session->media_handle)) {
13294  return SWITCH_STATUS_FALSE;
13295  }
13296 
13297  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13298  return switch_rtp_queue_rfc2833(smh->engines[type].rtp_session, dtmf);
13299  }
13300 
13301  return SWITCH_STATUS_FALSE;
13302 }
13303 
13304 //?
13306 {
13307  switch_media_handle_t *smh;
13308 
13309  switch_assert(session);
13310 
13311  if (!(smh = session->media_handle)) {
13312  return SWITCH_STATUS_FALSE;
13313  }
13314 
13315  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13316  return switch_rtp_queue_rfc2833_in(smh->engines[type].rtp_session, dtmf);
13317  }
13318 
13319  return SWITCH_STATUS_FALSE;
13320 }
13321 
13322 //?
13324 {
13325  switch_media_handle_t *smh;
13326 
13327  switch_assert(session);
13328 
13329  if (!(smh = session->media_handle)) {
13330  return 0;
13331  }
13332 
13333  return switch_rtp_ready(smh->engines[type].rtp_session);
13334 }
13335 
13336 //?
13338 {
13339  switch_media_handle_t *smh;
13340 
13341  switch_assert(session);
13342 
13343  if (!(smh = session->media_handle)) {
13344  return;
13345  }
13346 
13347  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13348  switch_rtp_set_flag(smh->engines[type].rtp_session, flag);
13349  }
13350 }
13351 
13352 //?
13354 {
13355  switch_media_handle_t *smh;
13356 
13357  switch_assert(session);
13358 
13359  if (!(smh = session->media_handle)) {
13360  return;
13361  }
13362 
13363  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13364  switch_rtp_clear_flag(smh->engines[type].rtp_session, flag);
13365  }
13366 }
13367 
13368 //?
13370 {
13371  switch_media_handle_t *smh;
13372 
13373  switch_assert(session);
13374 
13375  if (!(smh = session->media_handle)) {
13376  return;
13377  }
13378 
13379  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13381  }
13382 }
13383 
13384 //?
13386 {
13387  switch_media_handle_t *smh;
13388 
13389  switch_assert(session);
13390 
13391  if (!(smh = session->media_handle)) {
13392  return;
13393  }
13394 
13395  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13397  }
13398 }
13399 
13400 //?
13402 {
13403  switch_media_handle_t *smh;
13404 
13405  switch_assert(session);
13406 
13407  if (!(smh = session->media_handle)) {
13408  return NULL;
13409  }
13410 
13411  if (smh->engines[type].rtp_session) {
13412  return switch_rtp_get_stats(smh->engines[type].rtp_session, pool);
13413  }
13414 
13415  return NULL;
13416 }
13417 
13418 //?
13420 {
13421  switch_media_handle_t *smh;
13422 
13423  switch_assert(session);
13424 
13425  if (!(smh = session->media_handle)) {
13426  return SWITCH_FALSE;
13427  }
13428 
13429  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13431  }
13432 
13433  return SWITCH_FALSE;
13434 }
13435 
13436 //?
13438 {
13439  switch_media_handle_t *smh;
13440 
13441  switch_assert(session);
13442 
13443  if (!(smh = session->media_handle)) {
13444  return SWITCH_STATUS_FALSE;
13445  }
13446 
13447  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13448  return switch_rtp_udptl_mode(smh->engines[type].rtp_session);
13449  }
13450 
13451  return SWITCH_STATUS_FALSE;
13452 }
13453 
13454 //?
13456 {
13457  switch_media_handle_t *smh;
13458 
13459  switch_assert(session);
13460 
13461  if (!(smh = session->media_handle)) {
13462  return NULL;
13463  }
13464 
13465  if (switch_rtp_ready(smh->engines[type].rtp_session)) {
13467  }
13468 
13469  return NULL;
13470 }
13471 
13472 
13473 //?
13475 {
13477 }
13478 
13480  switch_sdp_type_t sdp_type, const char *codec_string)
13481 {
13482  sdp_parser_t *parser;
13483  sdp_session_t *sdp;
13484 
13485  switch_assert(session);
13486 
13487  if (!session->media_handle) {
13488  return;
13489  }
13490 
13491  if (!r_sdp) {
13492  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Setting NULL SDP is invalid\n");
13493  return;
13494  }
13495 
13496  if (zstr(codec_string)) {
13497  codec_string = switch_core_media_get_codec_string(session);
13498  }
13499 
13500  if ((parser = sdp_parse(NULL, r_sdp, (int) strlen(r_sdp), 0))) {
13501 
13502  if ((sdp = sdp_session(parser))) {
13503  switch_core_media_set_r_sdp_codec_string(session, codec_string, sdp, sdp_type);
13504  }
13505 
13506  sdp_parser_free(parser);
13507  }
13508 }
13509 
13510 
13511 static void add_audio_codec(sdp_rtpmap_t *map, const switch_codec_implementation_t *imp, int ptime, char *buf, switch_size_t buflen)
13512 {
13513  int codec_ms = ptime;
13514  uint32_t map_bit_rate = 0, map_channels = 1;
13515  char ptstr[20] = "";
13516  char ratestr[20] = "";
13517  char bitstr[20] = "";
13518  switch_codec_fmtp_t codec_fmtp = { 0 };
13519 
13520  if (!codec_ms) {
13521  codec_ms = switch_default_ptime(map->rm_encoding, map->rm_pt);
13522  }
13523 
13524  map_channels = map->rm_params ? atoi(map->rm_params) : 1;
13525  map_bit_rate = switch_known_bitrate((switch_payload_t)map->rm_pt);
13526 
13527  if (!ptime && !strcasecmp(map->rm_encoding, "g723")) {
13528  codec_ms = 30;
13529  }
13530 
13531  if (zstr(map->rm_fmtp)) {
13532  if (!strcasecmp(map->rm_encoding, "ilbc")) {
13533  codec_ms = 30;
13534  map_bit_rate = 13330;
13535  } else if (!strcasecmp(map->rm_encoding, "isac")) {
13536  codec_ms = 30;
13537  map_bit_rate = 32000;
13538  }
13539  } else {
13540  if ((switch_core_codec_parse_fmtp(map->rm_encoding, map->rm_fmtp, map->rm_rate, &codec_fmtp)) == SWITCH_STATUS_SUCCESS) {
13541  if (codec_fmtp.bits_per_second) {
13542  map_bit_rate = codec_fmtp.bits_per_second;
13543  }
13544  if (codec_fmtp.microseconds_per_packet) {
13545  codec_ms = (codec_fmtp.microseconds_per_packet / 1000);
13546  }
13547  }
13548  }
13549 
13550  if (map->rm_rate) {
13551  switch_snprintf(ratestr, sizeof(ratestr), "@%uh", (unsigned int) map->rm_rate);
13552  }
13553 
13554  if (codec_ms) {
13555  switch_snprintf(ptstr, sizeof(ptstr), "@%di", codec_ms);
13556  }
13557 
13558  if (map_bit_rate) {
13559  switch_snprintf(bitstr, sizeof(bitstr), "@%db", map_bit_rate);
13560  }
13561 
13562  if (map_channels > 1) {
13563  switch_snprintf(bitstr, sizeof(bitstr), "@%dc", map_channels);
13564  }
13565 
13566  switch_snprintf(buf + strlen(buf), buflen - strlen(buf), ",%s.%s%s%s%s", imp->modname, map->rm_encoding, ratestr, ptstr, bitstr);
13567 
13568 }
13569 
13570 
13571 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)
13572 {
13573  char buf[1024] = { 0 };
13574  sdp_media_t *m;
13575  sdp_attribute_t *attr;
13576  int ptime = 0, dptime = 0;
13577  sdp_connection_t *connection;
13578  sdp_rtpmap_t *map;
13579  short int match = 0;
13580  int i;
13581  int already_did[128] = { 0 };
13582  int num_codecs = 0;
13583  char *codec_order[SWITCH_MAX_CODECS];
13584  const switch_codec_implementation_t *codecs[SWITCH_MAX_CODECS] = { 0 };
13585  char fmtp[SWITCH_MAX_CODECS][MAX_FMTP_LEN];
13586 
13588  int prefer_sdp = 0;
13589  const char *var;
13590  switch_media_handle_t *smh;
13591 
13592  switch_assert(session);
13593 
13594  if (!(smh = session->media_handle)) {
13595  return;
13596  }
13597 
13598 
13599  if ((var = switch_channel_get_variable(channel, "ep_codec_prefer_sdp")) && switch_true(var)) {
13600  prefer_sdp = 1;
13601  }
13602 
13603 
13604  if (!zstr(codec_string)) {
13605  char *tmp_codec_string;
13606 
13607  if (*codec_string == '=') codec_string++;
13608 
13609  if ((tmp_codec_string = strdup(codec_string))) {
13610  num_codecs = switch_separate_string(tmp_codec_string, ',', codec_order, SWITCH_MAX_CODECS);
13611  num_codecs = switch_loadable_module_get_codecs_sorted(codecs, fmtp, SWITCH_MAX_CODECS, codec_order, num_codecs);
13612  switch_safe_free(tmp_codec_string);
13613  }
13614  } else {
13616  }
13617 
13618  if (!channel || !num_codecs) {
13619  return;
13620  }
13621 
13622  for (attr = sdp->sdp_attributes; attr; attr = attr->a_next) {
13623  if (zstr(attr->a_name)) {
13624  continue;
13625  }
13626 
13627  if (!strcasecmp(attr->a_name, "ptime")) {
13628  dptime = atoi(attr->a_value);
13629  break;
13630  }
13631  }
13632 
13633  for (m = sdp->sdp_media; m; m = m->m_next) {
13634  ptime = dptime;
13635 
13636  if ((m->m_type == sdp_media_audio || m->m_type == sdp_media_video) && m->m_port) {
13637  for (map = m->m_rtpmaps; map; map = map->rm_next) {
13638  int found = 0;
13639 
13640  for (attr = m->m_attributes; attr && found < 2; attr = attr->a_next) {
13641  if (zstr(attr->a_name)) {
13642  continue;
13643  }
13644 
13645  if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
13646  ptime = atoi(attr->a_value);
13647  found++;
13648  }
13649 
13650  if (!strcasecmp(attr->a_name, "rtcp-mux")) {
13651  if (switch_channel_var_true(channel, "rtcp_mux_auto_detect")) {
13652  switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "setting rtcp-mux from sdp\n");
13653  switch_channel_set_variable(channel, "rtcp_mux", "true");
13654  }
13655 
13656  found++;
13657  }
13658  }
13659 
13661  m->m_type == sdp_media_audio ? SWITCH_MEDIA_TYPE_AUDIO : SWITCH_MEDIA_TYPE_VIDEO,
13662  map->rm_encoding,
13663  NULL,
13664  map->rm_fmtp,
13665  sdp_type,
13666  map->rm_pt,
13667  map->rm_rate,
13668  ptime,
13669  map->rm_params ? atoi(map->rm_params) : 1,
13670  SWITCH_FALSE);
13671  }
13672  }
13673  }
13674 
13675  for (m = sdp->sdp_media; m; m = m->m_next) {
13676  ptime = dptime;
13677 
13678  if (m->m_type == sdp_media_image && m->m_port) {
13679  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",t38");
13680  } else if (m->m_type == sdp_media_audio && m->m_port) {
13681  for (attr = m->m_attributes; attr; attr = attr->a_next) {
13682  if (zstr(attr->a_name)) {
13683  continue;
13684  }
13685 
13686  if (!strcasecmp(attr->a_name, "ptime") && attr->a_value) {
13687  ptime = atoi(attr->a_value);
13688  break;
13689  }
13690  }
13691 
13692  connection = sdp->sdp_connection;
13693  if (m->m_connections) {
13694  connection = m->m_connections;
13695  }
13696 
13697  if (!connection) {
13698  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");
13699  break;
13700  }
13701 
13702  if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND || prefer_sdp) {
13703  for (map = m->m_rtpmaps; map; map = map->rm_next) {
13704 
13705  if (already_did[map->rm_pt]) {
13706  continue;
13707  }
13708 
13709  for (i = 0; i < num_codecs; i++) {
13710  const switch_codec_implementation_t *imp = codecs[i];
13711 
13712  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
13713  match = (map->rm_pt == imp->ianacode) ? 1 : 0;
13714  } else {
13715  if (map->rm_encoding) {
13716  match = !strcasecmp(map->rm_encoding, imp->iananame) &&
13717  ((map->rm_pt < 96 && imp->ianacode < 96) || (map->rm_pt > 95 && imp->ianacode > 95));
13718  } else {
13719  match = 0;
13720  }
13721  }
13722 
13723  if (match) {
13724  add_audio_codec(map, imp, ptime, buf, sizeof(buf));
13725  }
13726  }
13727  }
13728 
13729  } else {
13730  for (i = 0; i < num_codecs; i++) {
13731  const switch_codec_implementation_t *imp = codecs[i];
13732 
13733  if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO || imp->ianacode > 127 || already_did[imp->ianacode]) {
13734  continue;
13735  }
13736 
13737  for (map = m->m_rtpmaps; map; map = map->rm_next) {
13738 
13739  if (already_did[map->rm_pt]) {
13740  continue;
13741  }
13742 
13743  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
13744  match = (map->rm_pt == imp->ianacode) ? 1 : 0;
13745  } else {
13746  if (map->rm_encoding) {
13747  match = !strcasecmp(map->rm_encoding, imp->iananame) &&
13748  ((map->rm_pt < 96 && imp->ianacode < 96) || (map->rm_pt > 95 && imp->ianacode > 95));
13749  } else {
13750  match = 0;
13751  }
13752  }
13753 
13754  if (match) {
13755  add_audio_codec(map, imp, ptime, buf, sizeof(buf));
13756  }
13757  }
13758  }
13759  }
13760 
13761  } else if (m->m_type == sdp_media_video && m->m_port) {
13762  connection = sdp->sdp_connection;
13763  if (m->m_connections) {
13764  connection = m->m_connections;
13765  }
13766 
13767  if (!connection) {
13768  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");
13769  break;
13770  }
13771 
13772  if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND || prefer_sdp) {
13773  for (map = m->m_rtpmaps; map; map = map->rm_next) {
13774 
13775  if (already_did[map->rm_pt]) {
13776  continue;
13777  }
13778 
13779  for (i = 0; i < num_codecs; i++) {
13780  const switch_codec_implementation_t *imp = codecs[i];
13781 
13782  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
13783  match = (map->rm_pt == imp->ianacode) ? 1 : 0;
13784  } else {
13785  if (map->rm_encoding) {
13786  match = !strcasecmp(map->rm_encoding, imp->iananame) &&
13787  ((map->rm_pt < 96 && imp->ianacode < 96) || (map->rm_pt > 95 && imp->ianacode > 95));
13788  } else {
13789  match = 0;
13790  }
13791  }
13792 
13793  if (match) {
13794  if (map->rm_fmtp) {
13795  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s.%s~%s", imp->modname, imp->iananame, map->rm_fmtp);
13796  } else {
13797  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s.%s", imp->modname, imp->iananame);
13798  }
13799 
13800  already_did[imp->ianacode] = 1;
13801  }
13802  }
13803  }
13804  } else {
13805  for (i = 0; i < num_codecs; i++) {
13806  const switch_codec_implementation_t *imp = codecs[i];
13807 
13808  if (imp->codec_type != SWITCH_CODEC_TYPE_VIDEO || imp->ianacode > 127 || already_did[imp->ianacode]) {
13809  continue;
13810  }
13811 
13814  continue;
13815  }
13816 
13817  for (map = m->m_rtpmaps; map; map = map->rm_next) {
13818 
13819  if (already_did[map->rm_pt]) {
13820  continue;
13821  }
13822 
13823  if ((zstr(map->rm_encoding) || (smh->mparams->ndlb & SM_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
13824  match = (map->rm_pt == imp->ianacode) ? 1 : 0;
13825  } else {
13826  if (map->rm_encoding) {
13827  match = !strcasecmp(map->rm_encoding, imp->iananame) &&
13828  ((map->rm_pt < 96 && imp->ianacode < 96) || (map->rm_pt > 95 && imp->ianacode > 95));
13829  } else {
13830  match = 0;
13831  }
13832  }
13833 
13834  if (match) {
13835  if (map->rm_fmtp) {
13836  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s.%s~%s", imp->modname, imp->iananame, map->rm_fmtp);
13837  } else {
13838  switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s.%s", imp->modname, imp->iananame);
13839  }
13840 
13841  already_did[imp->ianacode] = 1;
13842  }
13843  }
13844  }
13845  }
13846  } else if (m->m_proto == sdp_proto_msrp) {
13848  } else if (m->m_proto == sdp_proto_msrps) {
13850  } else if (m->m_type == sdp_media_text) {
13852  }
13853  }
13854 
13855  if (buf[0] == ',') {
13856  switch_channel_set_variable(channel, "ep_codec_string", buf + 1);
13857  }
13858 }
13859 
13860 //?
13862 {
13863  switch_rtp_engine_t *engine;
13864  switch_media_handle_t *smh;
13865 
13866  switch_assert(session);
13867 
13868  if (!(smh = session->media_handle)) {
13869  return SWITCH_STATUS_FALSE;
13870  }
13871 
13872  engine = &smh->engines[type];
13873 
13874  if (engine->cur_payload_map->iananame) {
13875  return SWITCH_STATUS_SUCCESS;
13876  }
13877 
13878  return SWITCH_STATUS_FALSE;
13879 }
13880 
13882 {
13883  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
13884  switch_media_handle_t *smh;
13885  int type;
13886 
13887  switch_assert(session);
13888 
13889  if (!(smh = session->media_handle)) {
13890  return;
13891  }
13892 
13893  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
13894  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
13895  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
13896 
13897  if (switch_core_codec_ready(&v_engine->read_codec)) {
13898  type = 1;
13899  switch_core_codec_control(&v_engine->read_codec, SCC_VIDEO_RESET, SCCT_INT, (void *)&type, SCCT_NONE, NULL, NULL, NULL);
13900  }
13901 
13902  if (switch_core_codec_ready(&v_engine->write_codec)) {
13903  type = 2;
13904  switch_core_codec_control(&v_engine->write_codec, SCC_VIDEO_RESET, SCCT_INT, (void *)&type, SCCT_NONE, NULL, NULL, NULL);
13905  }
13906 
13907  if (a_engine->rtp_session) {
13908  switch_rtp_reset(a_engine->rtp_session);
13909  }
13910 
13911  if (v_engine->rtp_session) {
13912  switch_rtp_reset(v_engine->rtp_session);
13913  }
13914 
13915  if (t_engine->rtp_session) {
13916  switch_rtp_reset(t_engine->rtp_session);
13917  }
13918 
13919 
13920  smh->msid = NULL;
13921  smh->cname = NULL;
13922  v_engine->ice_out.ufrag = NULL;
13923  v_engine->ice_out.pwd = NULL;
13924  v_engine->ice_out.cands[0][0].foundation = NULL;
13925  v_engine->ice_out.cands[0][0].component_id = 0;
13926 
13927  t_engine->ice_out.ufrag = NULL;
13928  t_engine->ice_out.pwd = NULL;
13929  t_engine->ice_out.cands[0][0].foundation = NULL;
13930  t_engine->ice_out.cands[0][0].component_id = 0;
13931 
13932 
13933  a_engine->ice_out.ufrag = NULL;
13934  a_engine->ice_out.pwd = NULL;
13935  a_engine->ice_out.cands[0][0].foundation = NULL;
13936  a_engine->ice_out.cands[0][0].component_id = 0;
13937 
13938  if (v_engine->ice_in.cands[v_engine->ice_in.chosen[0]][0].ready) {
13939  gen_ice(smh->session, SWITCH_MEDIA_TYPE_VIDEO, NULL, 0);
13940  }
13941 
13942  if (t_engine->ice_in.cands[t_engine->ice_in.chosen[0]][0].ready) {
13943  gen_ice(smh->session, SWITCH_MEDIA_TYPE_TEXT, NULL, 0);
13944  }
13945 
13946  if (a_engine->ice_in.cands[a_engine->ice_in.chosen[0]][0].ready) {
13947  gen_ice(smh->session, SWITCH_MEDIA_TYPE_AUDIO, NULL, 0);
13948  }
13949 
13950  smh->owner_id = 0;
13951  smh->session_id = 0;
13952 
13953  a_engine->local_dtls_fingerprint.len = 0;
13954  v_engine->local_dtls_fingerprint.len = 0;
13955  t_engine->local_dtls_fingerprint.len = 0;
13956 
13957  a_engine->remote_ssrc = 0;
13958  v_engine->remote_ssrc = 0;
13959  t_engine->remote_ssrc = 0;
13960 
13964 }
13965 
13966 
13967 
13968 //?
13970 {
13971  switch_rtp_engine_t *a_engine, *v_engine, *t_engine;
13972  switch_media_handle_t *smh;
13973  const char *r_sdp = NULL;
13974  payload_map_t *pmap;
13975 
13976  switch_assert(session);
13977 
13978  if (!switch_channel_test_flag(o_session->channel, CF_PROXY_MEDIA)) {
13979  return;
13980  }
13981 
13982  if (!(smh = session->media_handle)) {
13983  return;
13984  }
13985 
13987 
13988  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
13989  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
13990  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
13991 
13993 
13994  clear_pmaps(a_engine);
13995  clear_pmaps(v_engine);
13996 
13997  pmap = switch_core_media_add_payload_map(session,
13999  "PROXY",
14000  NULL,
14001  NULL,
14003  0,
14004  8000,
14005  20,
14006  1,
14007  SWITCH_TRUE);
14008 
14009  a_engine->cur_payload_map = pmap;
14010 
14011  if (switch_stristr("m=video", r_sdp)) {
14013  pmap = switch_core_media_add_payload_map(session,
14015  "PROXY-VID",
14016  NULL,
14017  NULL,
14019  0,
14020  90000,
14021  90000,
14022  1,
14023  SWITCH_TRUE);
14024 
14025  v_engine->cur_payload_map = pmap;
14026 
14029  }
14030 
14031 
14032  if (switch_stristr("m=text", r_sdp)) {
14034  pmap = switch_core_media_add_payload_map(session,
14036  "PROXY-TXT",
14037  NULL,
14038  NULL,
14040  0,
14041  1000,
14042  1000,
14043  1,
14044  SWITCH_TRUE);
14045 
14046  t_engine->cur_payload_map = pmap;
14047 
14050  }
14051 }
14052 
14053 
14055 {
14056  const char *ip;
14057  const char *port;
14058  const char *a_ip;
14059  const char *r_ip;
14060  const char *r_port;
14061  const char *tmp;
14062  switch_rtp_engine_t *a_engine, *v_engine;
14063  switch_media_handle_t *smh;
14064 
14065  switch_assert(session);
14066 
14067  if (!(smh = session->media_handle)) {
14068  return;
14069  }
14070 
14073 
14074  if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) || !(ip && port)) {
14075  return;
14076  } else {
14080  }
14081 
14082  a_engine = &smh->engines[SWITCH_MEDIA_TYPE_AUDIO];
14083  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
14084 
14085  a_engine->cur_payload_map->iananame = a_engine->cur_payload_map->rm_encoding = (char *) switch_channel_get_variable(session->channel, "rtp_use_codec_name");
14086  a_engine->cur_payload_map->rm_fmtp = (char *) switch_channel_get_variable(session->channel, "rtp_use_codec_fmtp");
14087 
14089  smh->mparams->remote_sdp_str = switch_core_session_strdup(session, tmp);
14090  }
14091 
14092  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_timer_name"))) {
14093  smh->mparams->timer_name = switch_core_session_strdup(session, tmp);
14094  }
14095 
14096  if ((tmp = switch_channel_get_variable(session->channel, "rtp_last_audio_codec_string"))) {
14097  const char *vtmp = switch_channel_get_variable(session->channel, "rtp_last_video_codec_string");
14098  switch_channel_set_variable_printf(session->channel, "rtp_use_codec_string", "%s%s%s", tmp, vtmp ? "," : "", vtmp ? vtmp : "");
14099  }
14100 
14101  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_string"))) {
14102  char *tmp_codec_string = switch_core_session_strdup(smh->session, tmp);
14103  smh->codec_order_last = switch_separate_string(tmp_codec_string, ',', smh->codec_order, SWITCH_MAX_CODECS);
14105  }
14106 
14107  if ((tmp = switch_channel_get_variable(session->channel, "rtp_2833_send_payload"))) {
14108  smh->mparams->te = (switch_payload_t)atoi(tmp);
14109  }
14110 
14111  if ((tmp = switch_channel_get_variable(session->channel, "rtp_2833_recv_payload"))) {
14112  smh->mparams->recv_te = (switch_payload_t)atoi(tmp);
14113  }
14114 
14115  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_rate"))) {
14116  a_engine->cur_payload_map->rm_rate = atoi(tmp);
14117  a_engine->cur_payload_map->adv_rm_rate = a_engine->cur_payload_map->rm_rate;
14118  }
14119 
14120  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_ptime"))) {
14121  a_engine->cur_payload_map->codec_ms = atoi(tmp);
14122  }
14123 
14124  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_codec_channels"))) {
14125  a_engine->cur_payload_map->channels = atoi(tmp);
14126  }
14127 
14128  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_pt"))) {
14129  a_engine->cur_payload_map->pt = (switch_payload_t)(smh->payload_space = atoi(tmp));
14130  }
14131 
14132  if ((tmp = switch_channel_get_variable(session->channel, "rtp_audio_recv_pt"))) {
14133  a_engine->cur_payload_map->recv_pt = (switch_payload_t)atoi(tmp);
14134  }
14135 
14136  switch_core_media_set_codec(session, 0, smh->mparams->codec_flags);
14137 
14138  a_engine->adv_sdp_ip = smh->mparams->extrtpip = (char *) ip;
14139  a_engine->adv_sdp_port = a_engine->local_sdp_port = (switch_port_t)atoi(port);
14140  a_engine->codec_negotiated = 1;
14141 
14142  if (!zstr(ip)) {
14143  a_engine->local_sdp_ip = switch_core_session_strdup(session, ip);
14144  smh->mparams->rtpip = a_engine->local_sdp_ip;
14145  }
14146 
14147  if (!zstr(a_ip)) {
14148  a_engine->adv_sdp_ip = switch_core_session_strdup(session, a_ip);
14149  }
14150 
14151  if (r_ip && r_port) {
14152  a_engine->cur_payload_map->remote_sdp_ip = (char *) r_ip;
14153  a_engine->cur_payload_map->remote_sdp_port = (switch_port_t)atoi(r_port);
14154  }
14155 
14156  if (switch_channel_test_flag(session->channel, CF_VIDEO)) {
14157  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_video_pt"))) {
14158  v_engine->cur_payload_map->pt = (switch_payload_t)atoi(tmp);
14159  }
14160 
14161  if ((tmp = switch_channel_get_variable(session->channel, "rtp_video_recv_pt"))) {
14162  v_engine->cur_payload_map->recv_pt = (switch_payload_t)atoi(tmp);
14163  }
14164 
14165  v_engine->cur_payload_map->rm_encoding = (char *) switch_channel_get_variable(session->channel, "rtp_use_video_codec_name");
14166  v_engine->cur_payload_map->rm_fmtp = (char *) switch_channel_get_variable(session->channel, "rtp_use_video_codec_fmtp");
14167  v_engine->codec_negotiated = 1;
14168 
14172 
14174 
14175  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_video_codec_rate"))) {
14176  v_engine->cur_payload_map->rm_rate = atoi(tmp);
14177  v_engine->cur_payload_map->adv_rm_rate = v_engine->cur_payload_map->rm_rate;
14178  }
14179 
14180  if ((tmp = switch_channel_get_variable(session->channel, "rtp_use_video_codec_ptime"))) {
14181  v_engine->cur_payload_map->codec_ms = atoi(tmp);
14182  }
14183 
14184  v_engine->adv_sdp_port = v_engine->local_sdp_port = (switch_port_t)atoi(port);
14185  v_engine->local_sdp_ip = smh->mparams->rtpip;
14186 
14187  if (r_ip && r_port) {
14188  v_engine->cur_payload_map->remote_sdp_ip = (char *) r_ip;
14189  v_engine->cur_payload_map->remote_sdp_port = (switch_port_t)atoi(r_port);
14190  }
14191  }
14192 
14193  switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 1);
14195 
14197  return;
14198  }
14199 
14202 
14203 
14204  if ((tmp = switch_channel_get_variable(session->channel, "rtp_last_audio_local_crypto_key")) && a_engine->ssec[a_engine->crypto_type].remote_crypto_key) {
14205  int idx = atoi(tmp);
14206 
14207  a_engine->ssec[a_engine->crypto_type].local_crypto_key = switch_core_session_strdup(session, tmp);
14208  switch_core_media_add_crypto(session, &a_engine->ssec[a_engine->crypto_type],SWITCH_RTP_CRYPTO_SEND);
14209  switch_core_media_add_crypto(session, &a_engine->ssec[a_engine->crypto_type],SWITCH_RTP_CRYPTO_RECV);
14211 
14212  switch_rtp_add_crypto_key(a_engine->rtp_session, SWITCH_RTP_CRYPTO_SEND, idx, &a_engine->ssec[a_engine->crypto_type]);
14213 
14214  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]);
14215  }
14216 
14217 
14221  }
14222 
14223 }
14224 
14225 
14227 {
14230  }
14231 
14232  video_globals.cpu_count = switch_core_cpu_count();
14233  video_globals.cur_cpu = 0;
14234 
14235  switch_core_new_memory_pool(&video_globals.pool);
14236  switch_mutex_init(&video_globals.mutex, SWITCH_MUTEX_NESTED, video_globals.pool);
14237 
14238 }
14239 
14241 {
14242  if (video_globals.pool) {
14243  switch_core_destroy_memory_pool(&video_globals.pool);
14244  }
14245 }
14246 
14247 static int payload_number(const char *name)
14248 {
14249  if (!strcasecmp(name, "pcmu")) {
14250  return 0;
14251  }
14252 
14253  if (!strcasecmp(name, "pcma")) {
14254  return 8;
14255  }
14256 
14257  if (!strcasecmp(name, "gsm")) {
14258  return 3;
14259  }
14260 
14261  if (!strcasecmp(name, "g722")) {
14262  return 9;
14263  }
14264 
14265  if (!strcasecmp(name, "g729")) {
14266  return 18;
14267  }
14268 
14269  if (!strcasecmp(name, "dvi4")) {
14270  return 5;
14271  }
14272 
14273  if (!strcasecmp(name, "h261")) {
14274  return 31;
14275  }
14276 
14277  if (!strcasecmp(name, "h263")) {
14278  return 34;
14279  }
14280 
14281  return -1;
14282 }
14283 
14284 static int find_pt(const char *sdp, const char *name)
14285 {
14286  const char *p;
14287 
14288  if ((p = switch_stristr(name, sdp))) {
14289  if (p < end_of_p(sdp) && *(p+strlen(name)) == '/' && *(p-1) == ' ') {
14290  p -= 2;
14291 
14292  while(*p > 47 && *p < 58) {
14293  p--;
14294  }
14295  p++;
14296 
14297  if (p) {
14298  return atoi(p);
14299  }
14300  }
14301  }
14302 
14303  return -1;
14304 }
14305 
14306 
14307 SWITCH_DECLARE(char *) switch_core_media_filter_sdp(const char *sdp_str, const char *cmd, const char *arg)
14308 {
14309  char *new_sdp = NULL;
14310  int pt = -1, te = -1;
14311  switch_size_t len;
14312  const char *i;
14313  char *o;
14314  int in_m = 0, slash = 0;
14315  int number = 0, skip = 0;
14316  int remove = !strcasecmp(cmd, "remove");
14317  int only = !strcasecmp(cmd, "only");
14318  char *end = end_of_p((char *)sdp_str);
14319  int tst;
14320  end++;
14321 
14322 
14323  if (remove || only) {
14324  pt = payload_number(arg);
14325 
14326  if (pt < 0) {
14327  pt = find_pt(sdp_str, arg);
14328  }
14329  } else {
14330  return NULL;
14331  }
14332 
14333  if (only) {
14334  te = find_pt(sdp_str, "telephone-event");
14335  }
14336 
14337 
14338  len = strlen(sdp_str) + 2;
14339  new_sdp = malloc(len);
14340  o = new_sdp;
14341  i = sdp_str;
14342 
14343 
14344  while(i && *i && i < end) {
14345 
14346  if (*i == 'm' && *(i+1) == '=') {
14347  in_m = 1;
14348  }
14349 
14350  if (in_m) {
14351  if (*i == '\r' || *i == '\n') {
14352  in_m = 0;
14353  slash = 0;
14354  } else {
14355  if (*i == '/') {
14356  slash++;
14357  while(*i != ' ' && i < end) {
14358  *o++ = *i++;
14359  }
14360 
14361  *o++ = *i++;
14362  }
14363 
14364  if (slash && switch_is_leading_number(i)) {
14365 
14366 
14367  number = atoi(i);
14368 
14369  while(i < end && ((*i > 47 && *i < 58) || *i == ' ')) {
14370 
14371  if (remove) {
14372  tst = (number != pt);
14373  } else {
14374  tst = (number == pt || number == te);
14375  }
14376 
14377  if (tst) {
14378  *o++ = *i;
14379  }
14380  i++;
14381 
14382  if (*i == ' ') {
14383  break;
14384  }
14385 
14386  }
14387 
14388  if (remove) {
14389  tst = (number == pt);
14390  } else {
14391  tst = (number != pt && number != te);
14392  }
14393 
14394  if (tst) {
14395  skip++;
14396  }
14397  }
14398  }
14399  }
14400 
14401  while (i < end && !strncasecmp(i, "a=rtpmap:", 9)) {
14402  const char *t = i + 9;
14403 
14404  number = atoi(t);
14405 
14406  if (remove) {
14407  tst = (number == pt);
14408  } else {
14409  tst = (number != pt && number != te);
14410  }
14411 
14412  while(i < end && (*i != '\r' && *i != '\n')) {
14413  if (!tst) *o++ = *i;
14414  i++;
14415  }
14416 
14417  while(i < end && (*i == '\r' || *i == '\n')) {
14418  if (!tst) *o++ = *i;
14419  i++;
14420  }
14421  }
14422 
14423  while (i < end && !strncasecmp(i, "a=fmtp:", 7)) {
14424  const char *t = i + 7;
14425 
14426  number = atoi(t);
14427 
14428  if (remove) {
14429  tst = (number == pt);
14430  } else {
14431  tst = (number != pt && number != te);
14432  }
14433 
14434  while(i < end && (*i != '\r' && *i != '\n')) {
14435  if (!tst) *o++ = *i;
14436  i++;
14437  }
14438 
14439  while(i < end && (*i == '\r' || *i == '\n')) {
14440  if (!tst) *o++ = *i;
14441  i++;
14442  }
14443  }
14444 
14445  if (!skip) {
14446  *o++ = *i;
14447  }
14448 
14449  skip = 0;
14450 
14451  i++;
14452  }
14453 
14454  *o = '\0';
14455 
14456  return new_sdp;
14457 }
14458 
14460 {
14462  char *cmd = switch_core_session_strdup(session, cmd_buf);
14463  int argc = 0;
14464  char *argv[50];
14465  int x = 0;
14466  char *patched_sdp = NULL;
14467 
14468  argc = switch_split(cmd, '|', argv);
14469 
14470  for (x = 0; x < argc; x++) {
14471  char *command = argv[x];
14472  char *arg = strchr(command, '(');
14473 
14474  if (arg) {
14475  char *e = switch_find_end_paren(arg, '(', ')');
14476  *arg++ = '\0';
14477  if (e) *e = '\0';
14478  }
14479 
14480  if (zstr(command) || zstr(arg)) {
14481  switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "%s SDP FILTER PARSE ERROR\n", switch_channel_get_name(channel));
14482  } else {
14483  char *tmp_sdp = NULL;
14484 
14485  if (patched_sdp) {
14486  tmp_sdp = switch_core_media_filter_sdp(patched_sdp, command, arg);
14487  } else {
14488  tmp_sdp = switch_core_media_filter_sdp(sdp, command, arg);
14489  }
14490 
14491 
14493  "%s Filter command %s(%s)\nFROM:\n==========\n%s\nTO:\n==========\n%s\n\n",
14494  switch_channel_get_name(channel),
14495  command, arg, patched_sdp ? patched_sdp : sdp, tmp_sdp);
14496 
14497 
14498  if (tmp_sdp) {
14499  switch_safe_free(patched_sdp);
14500  patched_sdp = tmp_sdp;
14501  }
14502  }
14503  }
14504 
14505  return patched_sdp;
14506 
14507 }
14508 
14509 
14511 {
14512  switch_rtp_engine_t *engine = NULL;
14513  switch_media_handle_t *smh = NULL;
14514 
14515  switch_assert(session);
14516 
14517  if (!(smh = session->media_handle)) {
14518  return NULL;
14519  }
14520 
14521  if (!(engine = &smh->engines[mtype])) {
14522  return NULL;
14523  }
14524 
14525  return switch_rtp_get_media_timer(engine->rtp_session);
14526 
14527 }
14528 
14530 {
14532  switch_media_handle_t *smh = NULL;
14533 
14534  switch_assert(session);
14535 
14536  if (!(smh = session->media_handle)) {
14537  return SWITCH_STATUS_FALSE;
14538  }
14539 
14540  if (switch_channel_media_up(channel) && switch_channel_test_flag(channel, CF_VIDEO)) {
14541  switch_core_session_message_t msg = { 0 };
14543 
14544  if (!force && (smh->last_video_refresh_req && (now - smh->last_video_refresh_req) < VIDEO_REFRESH_FREQ)) {
14545  return SWITCH_STATUS_BREAK;
14546  }
14547 
14548  smh->last_video_refresh_req = now;
14549 
14550  if (force) {
14551  msg.numeric_arg = 1;
14552  }
14553 
14554  msg._file = file;
14555  msg._func = func;
14556  msg._line = line;
14558  SWITCH_LOG_DEBUG1, "%s Video refresh requested.\n", switch_channel_get_name(session->channel));
14559  msg.from = __FILE__;
14561  switch_core_session_receive_message(session, &msg);
14562  return SWITCH_STATUS_SUCCESS;
14563  }
14564 
14565  return SWITCH_STATUS_FALSE;
14566 }
14567 
14569 {
14570  if (switch_channel_test_flag(session->channel, CF_VIDEO)) {
14573  return SWITCH_STATUS_SUCCESS;
14574  }
14575 
14576  return SWITCH_STATUS_FALSE;
14577 }
14578 
14579 
14581  switch_media_type_t mtype,
14582  switch_io_type_t iotype,
14585  void *cmd_data,
14587  void *cmd_arg,
14589  void **ret_data)
14590 {
14591  switch_rtp_engine_t *engine = NULL;
14592  switch_media_handle_t *smh = NULL;
14593  switch_codec_t *codec = NULL;
14594 
14595  switch_assert(session);
14596 
14597  if (!(smh = session->media_handle)) {
14598  return SWITCH_STATUS_FALSE;
14599  }
14600 
14601  if (!(engine = &smh->engines[mtype])) {
14602  return SWITCH_STATUS_NOTIMPL;
14603  }
14604 
14605  if (iotype == SWITCH_IO_READ) {
14606  codec = &engine->read_codec;
14607  } else {
14608  codec = &engine->write_codec;
14609  }
14610 
14611  if (!switch_core_codec_ready(codec)) {
14612  return SWITCH_STATUS_FALSE;
14613  }
14614 
14615  if (mtype == SWITCH_MEDIA_TYPE_VIDEO) {
14616  if (!switch_channel_test_flag(session->channel, CF_VIDEO)) {
14617  return SWITCH_STATUS_FALSE;
14618  }
14619  }
14620 
14621  if (codec) {
14622  return switch_core_codec_control(codec, cmd, ctype, cmd_data, atype, cmd_arg, rtype, ret_data);
14623  }
14624 
14625  return SWITCH_STATUS_FALSE;
14626 }
14627 
14629  switch_media_type_t mtype,
14630  switch_codec_flag_t flag) {
14631  switch_rtp_engine_t *engine = NULL;
14632  switch_media_handle_t *smh = NULL;
14633  switch_codec_t *codec = NULL;
14634 
14635  switch_assert(session);
14636 
14637  if (!(smh = session->media_handle)) {
14638  return SWITCH_FALSE;
14639  }
14640 
14641  if (!(engine = &smh->engines[mtype])) {
14642  return SWITCH_FALSE;
14643  }
14644 
14645  codec = &engine->write_codec;
14646 
14647  if (!switch_core_codec_ready(codec)) {
14648  return SWITCH_FALSE;
14649  }
14650 
14651  if (switch_test_flag(codec, flag)){
14652  return SWITCH_TRUE;
14653  }
14654 
14655  return SWITCH_FALSE;
14656 }
14657 
14659  switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
14660 {
14663 
14665  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG3, "Writing video to RECVONLY/INACTIVE session\n");
14666  return SWITCH_STATUS_SUCCESS;
14667  }
14668 
14670  if ((status = session->endpoint_interface->io_routines->write_video_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
14671  for (ptr = session->event_hooks.video_write_frame; ptr; ptr = ptr->next) {
14672  if ((status = ptr->video_write_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
14673  break;
14674  }
14675  }
14676  }
14677  }
14678 
14679  return status;
14680 }
14681 
14683 {
14684  switch_media_handle_t *smh;
14685  int type;
14686 
14687  switch_assert(session);
14688 
14689  if (!(smh = session->media_handle)) {
14690  return;
14691  }
14692 
14693  if (switch_channel_down(session->channel)) {
14694  return;
14695  }
14696 
14697  smh->video_init = 0;
14698  smh->video_last_key_time = 0;
14700 
14701  type = 1;
14704 
14705 }
14706 
14708  int stream_id)
14709 {
14713  switch_timer_t *timer;
14714  switch_media_handle_t *smh;
14715  switch_image_t *dup_img = NULL, *img = frame->img;
14716  switch_status_t encode_status;
14717  switch_frame_t write_frame = {0};
14718  switch_rtp_engine_t *v_engine = NULL;
14719  switch_bool_t need_free = SWITCH_FALSE;
14720  switch_assert(session);
14721 
14722  if (!(smh = session->media_handle)) {
14723  return SWITCH_STATUS_FALSE;
14724  }
14725 
14726  if (switch_channel_down(session->channel)) {
14727  return SWITCH_STATUS_FALSE;
14728  }
14729 
14730  if (!codec) {
14731  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s has no video codec\n", switch_core_session_get_name(session));
14732  return SWITCH_STATUS_FALSE;
14733  }
14734 
14735 
14737  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG3, "Writing video to RECVONLY/INACTIVE session\n");
14738  return SWITCH_STATUS_SUCCESS;
14739  }
14740 
14742  return SWITCH_STATUS_SUCCESS;
14743  }
14744 
14745  if (!(switch_channel_test_flag(session->channel, CF_VIDEO_READY) || (flags & SWITCH_IO_FLAG_FORCE))) {
14746  return SWITCH_STATUS_SUCCESS;
14747  }
14748 
14750  /* return CNG, another thread is already writing */
14751  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s is already being written to for %s\n",
14753  return SWITCH_STATUS_INUSE;
14754  }
14755 
14756  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
14757  if (v_engine->thread_write_lock && v_engine->thread_write_lock != switch_thread_self()) {
14759  }
14760 
14761  if (!smh->video_init && smh->mparams->video_key_first && (now - smh->video_last_key_time) > smh->mparams->video_key_first) {
14763 
14764  if (smh->video_last_key_time) {
14765  smh->video_init = 1;
14766  }
14767 
14768  smh->video_last_key_time = now;
14769  }
14770 
14771  if (smh->mparams->video_key_freq && (now - smh->video_last_key_time) > smh->mparams->video_key_freq) {
14773  smh->video_last_key_time = now;
14774  }
14775 
14776  if (!img) {
14777  switch_status_t vstatus;
14778 
14779  vstatus = switch_core_session_write_encoded_video_frame(session, frame, flags, stream_id);
14780  switch_goto_status(vstatus, done);
14781  }
14782 
14783 
14784  /* When desired, scale video to match the input signal (if output is bigger) */
14787  switch_vid_params_t vid_params = { 0 };
14788 
14789  switch_core_media_get_vid_params(session, &vid_params);
14790 
14791  if (vid_params.width && vid_params.height && ((vid_params.width != img->d_w) || (vid_params.height != img->d_h))) {
14792  switch_img_letterbox(img, &dup_img, vid_params.width, vid_params.height, "#000000f");
14793  if (!(img = dup_img)) {
14795  }
14796  }
14797  }
14798 
14800  smh->vid_params.d_width = img->d_w;
14801  smh->vid_params.d_height = img->d_h;
14802  }
14803 
14804  if (session->bugs) {
14805  switch_media_bug_t *bp;
14806  int prune = 0;
14807  int patched = 0;
14808 
14810  for (bp = session->bugs; bp; bp = bp->next) {
14812 
14814  continue;
14815  }
14816 
14818  continue;
14819  }
14820 
14821  if (switch_test_flag(bp, SMBF_PRUNE)) {
14822  prune++;
14823  continue;
14824  }
14825 
14827  switch_image_t *dimg = NULL;
14828 
14829  switch_img_copy(img, &dimg);
14831 
14834  patched = 1;
14835  }
14836 
14837  }
14838 
14839  if (bp->ready && img &&
14841  switch_frame_t bug_frame = { 0 };
14842 
14843  bug_frame.img = img;
14844 
14846  bp->video_ping_frame = &bug_frame;
14848  || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) {
14849  ok = SWITCH_FALSE;
14850  }
14851  bp->video_ping_frame = NULL;
14852  }
14853 
14854  if (bug_frame.img && bug_frame.img != img) {
14855  need_free = SWITCH_TRUE;
14856  img = bug_frame.img;
14857  }
14858 
14861  }
14862 
14863 
14864  }
14865 
14866  if (ok == SWITCH_FALSE) {
14868  prune++;
14869  }
14870 
14871  }
14872 
14874 
14875  if (prune) {
14876  switch_core_media_bug_prune(session);
14877  }
14878 
14879  }
14880 
14881  write_frame = *frame;
14882  frame = &write_frame;
14883  frame->img = img;
14884 
14886 
14887  if (!(timer = switch_core_media_get_timer(session, SWITCH_MEDIA_TYPE_VIDEO))) {
14888 
14889  if (!smh->video_timer.timer_interface) {
14890  switch_core_timer_init(&smh->video_timer, "soft", 1, 90, switch_core_session_get_pool(session));
14891  }
14893  timer = &smh->video_timer;
14894  }
14895 
14896  frame->timestamp = timer->samplecount;
14897  }
14898 
14900  frame->m = 0;
14901 
14902  do {
14904  encode_status = switch_core_codec_encode_video(codec, frame);
14905 
14906  if (encode_status == SWITCH_STATUS_SUCCESS || encode_status == SWITCH_STATUS_MORE_DATA) {
14907 
14908  switch_assert((encode_status == SWITCH_STATUS_SUCCESS && frame->m) || !frame->m);
14909 
14910  if (frame->flags & SFF_PICTURE_RESET) {
14912  frame->flags &= ~SFF_PICTURE_RESET;
14913  }
14914 
14915  if (frame->datalen == 0) break;
14916 
14918  status = switch_core_session_write_encoded_video_frame(session, frame, flags, stream_id);
14919  }
14920 
14921  } while(status == SWITCH_STATUS_SUCCESS && encode_status == SWITCH_STATUS_MORE_DATA);
14922 
14923  done:
14924 
14927  }
14928 
14929  switch_img_free(&dup_img);
14930 
14931  if (need_free) {
14932  switch_img_free(&frame->img);
14933  }
14934 
14935  return status;
14936 }
14937 
14939 {
14940  switch_media_handle_t *smh;
14941  switch_codec_implementation_t read_impl = { 0 };
14942  switch_rtp_engine_t *v_engine = NULL;
14943 
14944  switch_assert(session != NULL);
14945 
14946  if (!(smh = session->media_handle)) {
14947  return SWITCH_STATUS_FALSE;
14948  }
14949 
14951  return SWITCH_STATUS_GENERR;
14952  }
14953 
14954  v_engine = &smh->engines[SWITCH_MEDIA_TYPE_VIDEO];
14955 
14956  if (v_engine->smode == SWITCH_MEDIA_FLOW_SENDONLY) {
14957  return SWITCH_STATUS_NOTIMPL;
14958  }
14959 
14960  switch_core_session_get_read_impl(session, &read_impl);
14961 
14962  while(switch_channel_ready(session->channel) && timeout_ms > 0) {
14963  switch_frame_t *read_frame;
14964  switch_status_t status;
14965 
14966  if (video_globals.synced &&
14968  return SWITCH_STATUS_SUCCESS;
14969  }
14970 
14972  status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0);
14973 
14974  if (!SWITCH_READ_ACCEPTABLE(status)) {
14975  return SWITCH_STATUS_FALSE;
14976  }
14977 
14978  timeout_ms -= (read_impl.microseconds_per_packet / 1000);
14979  }
14980 
14981  return SWITCH_STATUS_TIMEOUT;
14982 
14983 }
14984 
14986 {
14987  switch_bool_t transcoding = SWITCH_FALSE;
14988 
14989  switch(type) {
14991  {
14992  switch_codec_implementation_t read_impl_a = { 0 }, read_impl_b = { 0 };
14993 
14994  switch_core_session_get_read_impl(session_a, &read_impl_a);
14995  switch_core_session_get_read_impl(session_b, &read_impl_b);
14996 
14997  if (read_impl_a.impl_id && read_impl_b.impl_id) {
14998  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);
14999  }
15000  }
15001  break;
15003  transcoding = (switch_channel_test_flag(session_a->channel, CF_VIDEO_DECODED_READ) ||
15005  break;
15006  default:
15007  break;
15008  }
15009 
15010  return transcoding;
15011 
15012 }
15013 
15015 {
15016  switch_rtp_engine_t *engine;
15017 
15018  if (!session->media_handle) return;
15019 
15020  engine = &session->media_handle->engines[type];
15021 
15022 
15023  if (switch_rtp_ready(engine->rtp_session)) {
15024  char var[50] = "";
15025  switch_snprintf(var, sizeof(var), "disable_%s_jb_during_passthru", type2str(type));
15026 
15027  if (switch_channel_var_true(session->channel, var)) {
15028  if (on) {
15030  } else {
15032  }
15033  }
15034 
15035  if (type == SWITCH_MEDIA_TYPE_VIDEO) {
15037  if (!on) {
15039  }
15040  }
15041 
15042  }
15043 
15044 }
15045 
15047  int stream_id)
15048 {
15051  switch_media_handle_t *smh;
15052  int is_keyframe = 0;
15053 
15054  switch_assert(session != NULL);
15055 
15056  if (!(smh = session->media_handle)) {
15057  return SWITCH_STATUS_FALSE;
15058  }
15059 
15060  top:
15061 
15062  if (switch_channel_down_nosig(session->channel)) {
15063  return SWITCH_STATUS_FALSE;
15064  }
15065 
15067  if ((status = session->endpoint_interface->io_routines->read_video_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
15068  for (ptr = session->event_hooks.video_read_frame; ptr; ptr = ptr->next) {
15069  if ((status = ptr->video_read_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
15070  break;
15071  }
15072  }
15073  }
15074  }
15075 
15077  *frame = &runtime.dummy_cng_frame;
15078  switch_cond_next();
15079  return SWITCH_STATUS_SUCCESS;
15080  }
15081 
15082  if (status == SWITCH_STATUS_INUSE) {
15083  *frame = &runtime.dummy_cng_frame;
15084  switch_cond_next();
15085  return SWITCH_STATUS_SUCCESS;
15086  }
15087 
15088  if (status != SWITCH_STATUS_SUCCESS) {
15089  goto done;
15090  }
15091 
15092  if (!(*frame)) {
15093  goto done;
15094  }
15095 
15097  if (switch_test_flag((*frame), SFF_CNG)) {
15099  } else {
15101  "VIDEO: seq: %d ts: %u len: %4d %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x mark: %d\n",
15102  (*frame)->seq, (*frame)->timestamp, (*frame)->datalen,
15103  *((uint8_t *)(*frame)->data), *((uint8_t *)(*frame)->data + 1),
15104  *((uint8_t *)(*frame)->data + 2), *((uint8_t *)(*frame)->data + 3),
15105  *((uint8_t *)(*frame)->data + 4), *((uint8_t *)(*frame)->data + 5),
15106  *((uint8_t *)(*frame)->data + 6), *((uint8_t *)(*frame)->data + 7),
15107  *((uint8_t *)(*frame)->data + 8), *((uint8_t *)(*frame)->data + 9),
15108  *((uint8_t *)(*frame)->data + 10), (*frame)->m);
15109  }
15110  }
15111 
15112 
15113  if (switch_test_flag(*frame, SFF_CNG)) {
15114  status = SWITCH_STATUS_SUCCESS;
15115  goto done;
15116  }
15117 
15118  if (switch_channel_test_flag(session->channel, CF_VIDEO_DECODED_READ) && (*frame)->img == NULL) {
15119  switch_status_t decode_status;
15120 
15121  (*frame)->img = NULL;
15122 
15123  decode_status = switch_core_codec_decode_video((*frame)->codec, *frame);
15124  if (switch_test_flag(*frame, SFF_IS_KEYFRAME)) {
15125  is_keyframe++;
15126  }
15127  if ((*frame)->img && switch_channel_test_flag(session->channel, CF_VIDEO_DEBUG_READ)) {
15128  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "IMAGE %dx%d %dx%d\n",
15129  (*frame)->img->w, (*frame)->img->h, (*frame)->img->d_w, (*frame)->img->d_h);
15130  }
15131 
15132  if ((*frame)->img && (*frame)->img->d_w && (*frame)->img->d_h) {
15133  int new_w = 0, new_h = 0;
15134 
15135  if ((*frame)->img->d_w != smh->vid_params.width || (*frame)->img->d_h != smh->vid_params.height) {
15136  new_w = (*frame)->img->d_w;
15137  new_h = (*frame)->img->d_h;
15138 
15139  if (new_w && new_h) {
15141  smh->vid_params.width = new_w;
15142  smh->vid_params.height = new_h;
15143  switch_channel_set_variable_printf(session->channel, "video_width", "%d", new_w);
15144  switch_channel_set_variable_printf(session->channel, "video_height", "%d", new_h);
15146  }
15147  }
15148  }
15149 
15150  if (switch_test_flag((*frame), SFF_WAIT_KEY_FRAME)) {
15153 
15154  if (!(*frame)->img) {
15155  *frame = &runtime.dummy_cng_frame;
15156  switch_cond_next();
15157  return SWITCH_STATUS_SUCCESS;
15158  }
15159  }
15160 
15161  if (decode_status == SWITCH_STATUS_MORE_DATA || !(*frame)->img) {
15162  goto top;
15163  }
15164  }
15165 
15166  if (!switch_channel_test_flag(session->channel, CF_VIDEO_READY) && *frame) {
15168  if ((*frame)->img) {
15170  }
15171  } else if ((*frame)->m || ++smh->ready_loops > 5) {
15173  }
15174  }
15175 
15176  done:
15177 
15178  if (*frame && is_keyframe) {
15180  }
15181 
15182  if (session->bugs) {
15183  switch_media_bug_t *bp;
15184  int prune = 0;
15185  int patched = 0;
15186 
15188  for (bp = session->bugs; bp; bp = bp->next) {
15190 
15192  continue;
15193  }
15194 
15196  continue;
15197  }
15198 
15199  if (switch_test_flag(bp, SMBF_PRUNE)) {
15200  prune++;
15201  continue;
15202  }
15203 
15204  if (bp->ready && switch_test_flag(bp, SMBF_READ_VIDEO_STREAM)) {
15205  if ((*frame) && (*frame)->img) {
15206  switch_image_t *img = NULL;
15207  switch_img_copy((*frame)->img, &img);
15211  patched = 1;
15212  }
15213  }
15214  }
15215 
15216  if (bp->ready && (*frame) && (*frame)->img &&
15218 
15219 
15221  bp->video_ping_frame = *frame;
15222 
15224  || (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL))) {
15225  ok = SWITCH_FALSE;
15226  }
15227  bp->video_ping_frame = NULL;
15228  }
15229 
15232  }
15233  }
15234 
15235  if (ok == SWITCH_FALSE) {
15237  prune++;
15238  }
15239  }
15240 
15242 
15243  if (prune) {
15244  switch_core_media_bug_prune(session);
15245  }
15246  }
15247 
15248  if ((*frame) && (*frame)->codec) {
15249  (*frame)->pmap = NULL;
15250  }
15251 
15252  if (status == SWITCH_STATUS_SUCCESS) {
15253  switch_core_session_video_read_callback(session, *frame);
15254  }
15255 
15256  return status;
15257 }
15258 
15259 
15261  switch_core_video_thread_callback_func_t func, void *user_data)
15262 {
15264  switch_media_handle_t *smh;
15265 
15266  if (!(smh = session->media_handle)) {
15267  return SWITCH_STATUS_FALSE;
15268  }
15269 
15271  if (!func) {
15272  session->video_read_callback = NULL;
15273  session->video_read_user_data = NULL;
15274  } else if (session->video_read_callback) {
15275  status = SWITCH_STATUS_FALSE;
15276  } else {
15277  session->video_read_callback = func;
15278  session->video_read_user_data = user_data;
15279  }
15280 
15283 
15284  return status;
15285 }
15286 
15288 {
15289  switch_media_handle_t *smh;
15291 
15292  if (!(smh = session->media_handle)) {
15293  return SWITCH_STATUS_FALSE;
15294  }
15295 
15297 
15298  if (session->video_read_callback) {
15299  status = session->video_read_callback(session, frame, session->video_read_user_data);
15300  }
15301 
15303 
15304  return status;
15305 }
15306 
15307 
15308 
15310  switch_core_text_thread_callback_func_t func, void *user_data)
15311 {
15313  switch_media_handle_t *smh;
15314 
15315  if (!(smh = session->media_handle)) {
15316  return SWITCH_STATUS_FALSE;
15317  }
15318 
15320  if (!func) {
15321  session->text_read_callback = NULL;
15322  session->text_read_user_data = NULL;
15323  } else if (session->text_read_callback) {
15324  status = SWITCH_STATUS_FALSE;
15325  } else {
15326  session->text_read_callback = func;
15327  session->text_read_user_data = user_data;
15328  }
15329 
15332 
15333  return status;
15334 }
15335 
15336 
15337 
15339 {
15340  switch_media_handle_t *smh;
15342 
15343  if (!(smh = session->media_handle)) {
15344  return SWITCH_STATUS_FALSE;
15345  }
15346 
15348 
15349  if (session->text_read_callback) {
15350  status = session->text_read_callback(session, frame, session->text_read_user_data);
15351  }
15352 
15354 
15355  return status;
15356 }
15357 
15358 
15359 
15361  int stream_id)
15362 {
15365  switch_media_handle_t *smh;
15366  switch_io_read_text_frame_t read_text_frame = NULL;
15367  switch_time_t now;
15368 
15369  switch_assert(session != NULL);
15370 
15371  if (!(smh = session->media_handle)) {
15372  return SWITCH_STATUS_FALSE;
15373  }
15374 
15375  if (switch_channel_down_nosig(session->channel)) {
15376  return SWITCH_STATUS_FALSE;
15377  }
15378 
15379  if (!(read_text_frame = session->endpoint_interface->io_routines->read_text_frame)) {
15380  if (session->io_override) {
15381  read_text_frame = session->io_override->read_text_frame;
15382  }
15383  }
15384 
15385  if (read_text_frame) {
15386  if ((status = read_text_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
15387  for (ptr = session->event_hooks.text_read_frame; ptr; ptr = ptr->next) {
15388  if ((status = ptr->text_read_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
15389  break;
15390  }
15391  }
15392  }
15393  }
15394 
15395  if (status == SWITCH_STATUS_INUSE) {
15396  *frame = &runtime.dummy_cng_frame;
15397  switch_cond_next();
15398  return SWITCH_STATUS_SUCCESS;
15399  }
15400 
15401  if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
15402  goto done;
15403  }
15404 
15405  if (!(*frame)) {
15406  goto done;
15407  }
15408 
15409  now = switch_micro_time_now();
15410 
15411  if (switch_test_flag((*frame), SFF_CNG)) {
15412  if (smh->last_text_frame && now - smh->last_text_frame > TEXT_PERIOD_TIMEOUT * 1000) {
15415  smh->last_text_frame = 0;
15416  }
15417  } else {
15418  unsigned char *p = (*frame)->data;
15419 
15420  smh->last_text_frame = now;
15423 
15424  while(p && *p) {
15425  if (*p == '\r' || *p == '\n') {
15427  break;
15428  }
15429 
15430  if (*p == 0xE2 && *(p+1) == 0x80 && *(p+2) == 0xA8) {
15432  break;
15433  }
15434 
15435  p++;
15436  }
15437  }
15438 
15439  if ((*frame)->data && (*frame)->datalen && !((*frame)->flags & SFF_CNG)) {
15440  if (!session->text_buffer) {
15442  switch_buffer_create_dynamic(&session->text_buffer, 512, 1024, 0);
15443  }
15444  switch_buffer_write(session->text_buffer, (*frame)->data, (*frame)->datalen);
15445  }
15446 
15447  if (session->bugs) {
15448  switch_media_bug_t *bp;
15449  int prune = 0;
15450 
15452  for (bp = session->bugs; bp; bp = bp->next) {
15454 
15456  continue;
15457  }
15458 
15460  continue;
15461  }
15462 
15463  if (switch_test_flag(bp, SMBF_PRUNE)) {
15464  prune++;
15465  continue;
15466  }
15467 
15468  if (bp->ready && switch_test_flag(bp, SMBF_READ_TEXT_STREAM)) {
15469  int bytes = 0;
15470 
15471  if ((*frame)) {
15472  switch_size_t inuse = 0;
15473 
15474  if ((*frame)->data && (*frame)->datalen && !((*frame)->flags & SFF_CNG)) {
15475  switch_mutex_lock(session->text_mutex);
15476  switch_buffer_write(bp->text_buffer, (char *)(*frame)->data, (*frame)->datalen);
15477  switch_mutex_unlock(session->text_mutex);
15478  }
15479 
15480  inuse = switch_buffer_inuse(bp->text_buffer);
15481 
15482  if (zstr(bp->text_framedata) && inuse &&
15484 
15485  if (inuse + 1 > bp->text_framesize) {
15486  void *tmp = malloc(inuse + 1024);
15487  memcpy(tmp, bp->text_framedata, bp->text_framesize);
15488 
15489  switch_assert(tmp);
15490 
15491  bp->text_framesize = inuse + 1024;
15492 
15493  free(bp->text_framedata);
15494  bp->text_framedata = tmp;
15495 
15496  }
15497 
15498 
15499  bytes = switch_buffer_read(bp->text_buffer, bp->text_framedata, inuse);
15500  *(bp->text_framedata + bytes) = '\0';
15501 
15502  ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_READ_TEXT);
15503  bp->text_framedata[0] = '\0';
15504  } else ok = SWITCH_TRUE;
15505  }
15506  }
15507 
15508  if (ok == SWITCH_FALSE) {
15510  prune++;
15511  }
15512  }
15513 
15515 
15516  if (prune) {
15517  switch_core_media_bug_prune(session);
15518  }
15519  }
15520 
15521  if (status == SWITCH_STATUS_SUCCESS || status == SWITCH_STATUS_BREAK) {
15523  (*frame)->datalen && !switch_test_flag((*frame), SFF_CNG)) {
15524  int ok = 1;
15525  switch_event_t *event;
15526  void *data = (*frame)->data;
15527  char eof[1] = {'\0'};
15528 
15529  //uint32_t datalen = (*frame)->datalen;
15530 
15532  if (!session->text_line_buffer) {
15533  switch_buffer_create_dynamic(&session->text_line_buffer, 512, 1024, 0);
15534  }
15535  switch_buffer_write(session->text_line_buffer, (*frame)->data, (*frame)->datalen);
15536 
15537 
15539  switch_buffer_write(session->text_line_buffer, eof, 1);
15541  //datalen = strlen((char *)smh->line_text_frame.data);
15542  } else {
15543  ok = 0;
15544  }
15545  }
15546 
15547 
15548  if (ok) {
15550  switch_channel_event_set_data(session->channel, event);
15551 
15552  switch_event_add_body(event, "%s", (char *)data);
15553 
15555  switch_event_t *q_event = NULL;
15556 
15558  switch_event_dup(&q_event, event);
15559  } else {
15560  q_event = event;
15561  event = NULL;
15562  }
15563 
15564  switch_core_session_queue_event(session, &q_event);
15565  }
15566 
15568  switch_event_fire(&event);
15569  }
15570  }
15571  if (session->text_line_buffer) {
15573  }
15574  }
15575  }
15576  switch_core_session_text_read_callback(session, *frame);
15577  }
15578 
15579  done:
15580 
15581  return status;
15582 }
15583 
15585 {
15586  int pos;
15587  switch_frame_t *frame = &t_engine->tf->text_write_frame;
15588  switch_byte_t *buf = (switch_byte_t *) frame->data;
15589  uint32_t plen = 0, loops = 0;
15590  uint16_t *u16;
15591 
15592  pos = t_engine->tf->red_pos + 1;
15593 
15594  if (pos == t_engine->tf->red_max) pos = 0;
15595 
15596  for (;;) {
15597  uint16_t ts = frame->timestamp - t_engine->tf->red_ts[pos];
15598  uint16_t len = t_engine->tf->red_buflen[pos];
15599 
15600  loops++;
15601 
15602  //1
15603  *buf = t_engine->t140_pt & 0x7f;
15604 
15605  if (pos != t_engine->tf->red_pos) {
15606  *buf |= 0x80;
15607 
15608  buf++; //2
15609  u16 = (uint16_t *) buf;
15610  *u16 = htons(ts << 2);
15611  buf++;//3
15612  *buf += (len & 0x300) >> 8;
15613  buf++;//4
15614  *buf = len & 0xff;
15615  }
15616 
15617  buf++;
15618 
15619  if (pos == t_engine->tf->red_pos) break;
15620 
15621 
15622  pos++;
15623 
15624  if (pos == t_engine->tf->red_max) pos = 0;
15625  }
15626 
15627 
15628  plen = ((loops - 1) * 4) + 1;
15629  pos = t_engine->tf->red_pos + 1;
15630 
15631  if (pos == t_engine->tf->red_max) pos = 0;
15632 
15633  for (;;) {
15634  if (t_engine->tf->red_buflen[pos]) {
15635  memcpy(buf, t_engine->tf->red_buf[pos], t_engine->tf->red_buflen[pos]);
15636  plen += t_engine->tf->red_buflen[pos];
15637  buf += t_engine->tf->red_buflen[pos];
15638  }
15639 
15640  if (pos == t_engine->tf->red_pos) break;
15641 
15642  pos++;
15643 
15644  if (pos == t_engine->tf->red_max) pos = 0;
15645  }
15646 
15647 
15648  buf = frame->data;
15649  *(buf+plen) = '\0';
15650 
15651  frame->datalen = plen;
15652  frame->payload = t_engine->red_pt;
15653 }
15654 
15656  int stream_id)
15657 {
15659  switch_media_handle_t *smh;
15661  switch_rtp_engine_t *t_engine;
15662  switch_io_write_text_frame_t write_text_frame = NULL;
15663  int is_msrp = switch_channel_test_flag(session->channel, CF_MSRP);
15664 
15665  switch_assert(session);
15666 
15667  if (!(smh = session->media_handle)) {
15668  return SWITCH_STATUS_FALSE;
15669  }
15670 
15671  if (switch_channel_down(session->channel)) {
15672  return SWITCH_STATUS_FALSE;
15673  }
15674 
15676  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG3, "Writing text to RECVONLY/INACTIVE session\n");
15677  return SWITCH_STATUS_SUCCESS;
15678  }
15679 
15680  //if (switch_channel_test_flag(session->channel, CF_TEXT_PAUSE_WRITE)) {
15681  // return SWITCH_STATUS_SUCCESS;
15682  //}
15683 
15685  /* return CNG, another thread is already writing */
15686  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "%s is already being written to for %s\n",
15688  goto done;
15689  }
15690 
15691  t_engine = &smh->engines[SWITCH_MEDIA_TYPE_TEXT];
15692 
15693  if (!is_msrp && switch_channel_test_cap(session->channel, CC_RTP_RTT)) {
15694 
15695  if (!t_engine || !t_engine->tf) {
15696  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "text engine not available for processing\n");
15698  }
15699 
15700  if (frame) {
15701  char *str = (char *) frame->data;
15702  switch_buffer_write(t_engine->tf->write_buffer, str, frame->datalen);
15703  }
15704 
15705  if (!switch_buffer_inuse(t_engine->tf->write_buffer)) {
15706  t_engine->tf->write_empty++;
15708  }
15709 
15710  frame = &t_engine->tf->text_write_frame;
15711  switch_core_timer_sync(&t_engine->tf->timer);
15712  frame->timestamp = t_engine->tf->timer.samplecount;
15713 
15714  if (t_engine->red_pt) {
15715  t_engine->tf->red_ts[t_engine->tf->red_pos] = frame->timestamp;
15716 
15717  if (t_engine->tf->write_empty > TEXT_PERIOD_TIMEOUT / TEXT_TIMER_MS) {
15718  int pos;
15719 
15720  for(pos = 0; pos < t_engine->tf->red_max; pos++) {
15721  t_engine->tf->red_ts[pos] = 0;
15722  t_engine->tf->red_buf[pos][0] = '\0';
15723  t_engine->tf->red_buflen[pos] = 0;
15724  }
15725 
15726  frame->m = 1;
15727  t_engine->tf->write_empty = 0;
15728 
15729  } else {
15730  frame->m = 0;
15731  }
15732 
15733  t_engine->tf->red_buflen[t_engine->tf->red_pos] =
15734  switch_buffer_read(t_engine->tf->write_buffer, t_engine->tf->red_buf[t_engine->tf->red_pos], RED_PACKET_SIZE);
15735 
15736  *(t_engine->tf->red_buf[t_engine->tf->red_pos] + t_engine->tf->red_buflen[t_engine->tf->red_pos]) = '\0';
15737 
15738  build_red_packet(t_engine);
15739  } else {
15741  frame->payload = t_engine->t140_pt;
15742  }
15743  }
15744 
15745  if (!(write_text_frame = session->endpoint_interface->io_routines->write_text_frame)) {
15746  if (session->io_override) {
15747  write_text_frame = session->io_override->write_text_frame;
15748  }
15749  }
15750 
15751  if (write_text_frame) {
15752  if ((status = write_text_frame(session, frame, flags, stream_id)) == SWITCH_STATUS_SUCCESS) {
15753  for (ptr = session->event_hooks.text_write_frame; ptr; ptr = ptr->next) {
15754  if ((status = ptr->text_write_frame(session, frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
15755  break;
15756  }
15757  }
15758  }
15759  }
15760 
15761 
15762  if (!is_msrp && switch_channel_test_cap(session->channel, CC_RTP_RTT)) {
15763  if (!t_engine || (t_engine->red_pt && !t_engine->tf)) {
15764  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "text engine not available for processing\n");
15766  }
15767 
15768  if (t_engine->red_pt) {
15769  t_engine->tf->red_pos++;
15770  if (t_engine->tf->red_pos == t_engine->tf->red_max) {
15771  t_engine->tf->red_pos = 0;
15772  }
15773  }
15774  }
15775 
15776  done:
15777 
15778  if (smh->write_mutex[SWITCH_MEDIA_TYPE_TEXT]) {
15780  }
15781 
15782  return status;
15783 }
15784 
15786 {
15787  char *data = NULL;
15788  int ret = 0;
15789  va_list ap;
15790  switch_frame_t frame = { 0 };
15791  unsigned char CR[] = TEXT_UNICODE_LINEFEED;
15792 
15793  va_start(ap, fmt);
15794  ret = switch_vasprintf(&data, fmt, ap);
15795  va_end(ap);
15796 
15797  if (ret == -1) {
15798  abort();
15799  }
15800 
15801  frame.data = data;
15802  frame.datalen = strlen(data);
15803 
15804  switch_core_session_write_text_frame(session, &frame, 0, 0);
15805 
15806  frame.data = CR;
15807  frame.datalen = 3;
15808 
15809  switch_core_session_write_text_frame(session, &frame, 0, 0);
15810 
15811  switch_safe_free(data);
15812 
15813  return SWITCH_STATUS_SUCCESS;
15814 }
15815 
15816 
15818 {
15819  switch_frame_t frame = { 0 };
15820 
15821  if (!switch_channel_test_flag(session->channel, CF_HAS_TEXT)) {
15822  return SWITCH_STATUS_NOTIMPL;
15823  }
15824 
15825  frame.data = (char *) data;
15826  frame.datalen = strlen(data);
15827 
15828  switch_core_session_write_text_frame(session, &frame, 0, 0);
15829 
15830  return SWITCH_STATUS_SUCCESS;
15831 }
15832 
15834 {
15835  if (!session->media_handle) return NULL;
15836 
15837  return session->media_handle->msrp_session;
15838 }
15839 
15840 
15842  int stream_id)
15843 {
15844 
15846  switch_frame_t *enc_frame = NULL, *write_frame = frame;
15847  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;
15848  int did_write_resample = 0;
15849 
15850  switch_assert(session != NULL);
15851  switch_assert(frame != NULL);
15852 
15853  if (!switch_channel_up_nosig(session->channel)) {
15854  return SWITCH_STATUS_FALSE;
15855  }
15856 
15859  } else {
15860  return SWITCH_STATUS_SUCCESS;
15861  }
15862 
15863  if (switch_test_flag(frame, SFF_CNG)) {
15865  pass_cng = 1;
15866  } else {
15867  return SWITCH_STATUS_SUCCESS;
15868  }
15869  }
15870 
15872  return SWITCH_STATUS_SUCCESS;
15873  }
15874 
15875  if (!(session->write_codec && switch_core_codec_ready(session->write_codec)) && !pass_cng) {
15876  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no write codec.\n", switch_channel_get_name(session->channel));
15878  return SWITCH_STATUS_FALSE;
15879  }
15880 
15881  if (switch_channel_test_flag(session->channel, CF_HOLD)) {
15882  return SWITCH_STATUS_SUCCESS;
15883  }
15884 
15885  if (switch_test_flag(frame, SFF_PROXY_PACKET) || pass_cng) {
15886  /* Fast PASS! */
15888  status = perform_write(session, frame, flag, stream_id);
15890  return status;
15891  }
15892 
15894 
15895  if (!(frame->codec && frame->codec->implementation)) {
15896  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has received a bad frame with no codec!\n",
15897  switch_channel_get_name(session->channel));
15900  return SWITCH_STATUS_FALSE;
15901  }
15902 
15903  switch_assert(frame->codec != NULL);
15904  switch_assert(frame->codec->implementation != NULL);
15905 
15906  if (!(switch_core_codec_ready(session->write_codec) && frame->codec) ||
15909  return SWITCH_STATUS_FALSE;
15910  }
15911 
15912  switch_mutex_lock(session->write_codec->mutex);
15913  switch_mutex_lock(frame->codec->mutex);
15914 
15915  if (!(switch_core_codec_ready(session->write_codec) && switch_core_codec_ready(frame->codec))) goto error;
15916 
15917  if (frame->codec && session->write_codec->implementation != frame->codec->implementation) {
15918  if (session->write_impl.codec_id == frame->codec->implementation->codec_id ||
15920  ptime_mismatch = TRUE;
15921 
15924  status = perform_write(session, frame, flags, stream_id);
15925  goto error;
15926  }
15927 
15930  }
15931  }
15932  need_codec = TRUE;
15933  }
15934 
15935  if (session->write_codec && !frame->codec) {
15936  need_codec = TRUE;
15937  }
15938 
15939  if (session->bugs && !need_codec && !switch_test_flag(session, SSF_MEDIA_BUG_TAP_ONLY)) {
15940  do_bugs = TRUE;
15941  need_codec = TRUE;
15942  }
15943 
15945  need_codec = TRUE;
15946  do_resample = TRUE;
15947  }
15948 
15949 
15950  if ((frame->flags & SFF_NOT_AUDIO)) {
15951  do_resample = 0;
15952  do_bugs = 0;
15953  need_codec = 0;
15954  }
15955 
15956  if (switch_test_flag(session, SSF_WRITE_TRANSCODE) && !need_codec && switch_core_codec_ready(session->write_codec)) {
15957  switch_core_session_t *other_session;
15959 
15960  if (uuid && (other_session = switch_core_session_locate(uuid))) {
15961  switch_set_flag(other_session, SSF_READ_CODEC_RESET);
15962  switch_set_flag(other_session, SSF_READ_CODEC_RESET);
15963  switch_set_flag(other_session, SSF_WRITE_CODEC_RESET);
15964  switch_core_session_rwunlock(other_session);
15965  }
15966 
15968  }
15969 
15970 
15971  if (switch_test_flag(session, SSF_WRITE_CODEC_RESET)) {
15974  }
15975 
15976  if (!need_codec) {
15977  do_write = TRUE;
15978  write_frame = frame;
15979  goto done;
15980  }
15981 
15982  if (!switch_test_flag(session, SSF_WARN_TRANSCODE)) {
15983  switch_core_session_message_t msg = { 0 };
15984 
15986  switch_core_session_receive_message(session, &msg);
15988  }
15989 
15990  if (frame->codec) {
15991  session->raw_write_frame.datalen = session->raw_write_frame.buflen;
15992  frame->codec->cur_frame = frame;
15993  session->write_codec->cur_frame = frame;
15994  status = switch_core_codec_decode(frame->codec,
15995  session->write_codec,
15996  frame->data,
15997  frame->datalen,
15999  session->raw_write_frame.data, &session->raw_write_frame.datalen, &session->raw_write_frame.rate, &frame->flags);
16000  frame->codec->cur_frame = NULL;
16001  session->write_codec->cur_frame = NULL;
16002  if (do_resample && status == SWITCH_STATUS_SUCCESS) {
16003  status = SWITCH_STATUS_RESAMPLE;
16004  }
16005 
16006  /* mux or demux to match */
16008  uint32_t rlen = session->raw_write_frame.datalen / 2 / frame->codec->implementation->number_of_channels;
16009  switch_mux_channels((int16_t *) session->raw_write_frame.data, rlen,
16011  session->raw_write_frame.datalen = rlen * 2 * session->write_impl.number_of_channels;
16012  }
16013 
16014  switch (status) {
16016  resample++;
16017  write_frame = &session->raw_write_frame;
16018  write_frame->rate = frame->codec->implementation->actual_samples_per_second;
16019  if (!session->write_resampler) {
16021  status = switch_resample_create(&session->write_resampler,
16025 
16026 
16028  if (status != SWITCH_STATUS_SUCCESS) {
16029  goto done;
16030  } else {
16031  switch_core_session_message_t msg = { 0 };
16032  msg.numeric_arg = 1;
16034  switch_core_session_receive_message(session, &msg);
16035 
16036  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Activating write resampler\n");
16037  }
16038  }
16039  break;
16040  case SWITCH_STATUS_SUCCESS:
16041  session->raw_write_frame.samples = session->raw_write_frame.datalen / sizeof(int16_t) / session->write_impl.number_of_channels;
16043  session->raw_write_frame.timestamp = frame->timestamp;
16044  session->raw_write_frame.rate = frame->rate;
16045  session->raw_write_frame.m = frame->m;
16046  session->raw_write_frame.ssrc = frame->ssrc;
16047  session->raw_write_frame.seq = frame->seq;
16048  session->raw_write_frame.payload = frame->payload;
16049  session->raw_write_frame.flags = 0;
16050  if (switch_test_flag(frame, SFF_PLC)) {
16051  session->raw_write_frame.flags |= SFF_PLC;
16052  }
16053 
16054  write_frame = &session->raw_write_frame;
16055  break;
16056  case SWITCH_STATUS_BREAK:
16057  status = SWITCH_STATUS_SUCCESS;
16058  goto error;
16059  case SWITCH_STATUS_NOOP:
16060  if (session->write_resampler) {
16063  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating write resampler\n");
16065 
16066  {
16067  switch_core_session_message_t msg = { 0 };
16068  msg.numeric_arg = 0;
16070  switch_core_session_receive_message(session, &msg);
16071  }
16072 
16073  }
16074  write_frame = frame;
16075  status = SWITCH_STATUS_SUCCESS;
16076  break;
16077  default:
16078 
16079  if (status == SWITCH_STATUS_NOT_INITALIZED) {
16080  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n");
16081  goto error;
16082  }
16083  if (ptime_mismatch && status != SWITCH_STATUS_GENERR) {
16084  perform_write(session, frame, flags, stream_id);
16085  status = SWITCH_STATUS_SUCCESS;
16086  goto error;
16087  }
16088 
16089  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s decoder error!\n",
16091  goto error;
16092  }
16093  }
16094 
16095 
16096 
16097  if (session->write_resampler) {
16098  short *data = write_frame->data;
16099 
16101  if (session->write_resampler) {
16102 
16104  write_frame->datalen / 2 / session->write_resampler->channels) > SWITCH_RECOMMENDED_BUFFER_SIZE) {
16105 
16106  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "%s not enough buffer space for required resample operation!\n",
16107  switch_channel_get_name(session->channel));
16110  goto error;
16111  }
16112 
16113 
16114  switch_resample_process(session->write_resampler, data, write_frame->datalen / 2 / session->write_resampler->channels);
16115 
16116  memcpy(data, session->write_resampler->to, session->write_resampler->to_len * 2 * session->write_resampler->channels);
16117 
16118  write_frame->samples = session->write_resampler->to_len;
16119  write_frame->channels = session->write_resampler->channels;
16120  write_frame->datalen = write_frame->samples * 2 * session->write_resampler->channels;
16121 
16122  write_frame->rate = session->write_resampler->to_rate;
16123 
16124  did_write_resample = 1;
16125  }
16127  }
16128 
16129 
16130 
16131  if (session->bugs) {
16132  switch_media_bug_t *bp;
16133  int prune = 0;
16134 
16136  for (bp = session->bugs; bp; bp = bp->next) {
16138 
16139  if (!bp->ready) {
16140  continue;
16141  }
16142 
16144  continue;
16145  }
16146 
16148  continue;
16149  }
16150 
16151  if (switch_test_flag(bp, SMBF_PRUNE)) {
16152  prune++;
16153  continue;
16154  }
16155 
16158  switch_buffer_write(bp->raw_write_buffer, write_frame->data, write_frame->datalen);
16160 
16161  if (bp->callback) {
16162  ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE);
16163  }
16164  }
16165 
16167  do_bugs = 0;
16168  if (bp->callback) {
16169  bp->write_replace_frame_in = write_frame;
16170  bp->write_replace_frame_out = write_frame;
16171  if ((ok = bp->callback(bp, bp->user_data, SWITCH_ABC_TYPE_WRITE_REPLACE)) == SWITCH_TRUE) {
16172  write_frame = bp->write_replace_frame_out;
16173  }
16174  }
16175  }
16176 
16177  if (bp->stop_time && bp->stop_time <= switch_epoch_time_now(NULL)) {
16178  ok = SWITCH_FALSE;
16179  }
16180 
16181 
16182  if (ok == SWITCH_FALSE) {
16184  prune++;
16185  }
16186  }
16188  if (prune) {
16189  switch_core_media_bug_prune(session);
16190  }
16191  }
16192 
16193  if (do_bugs) {
16194  do_write = TRUE;
16195  write_frame = frame;
16196  goto done;
16197  }
16198 
16199  if (session->write_codec) {
16200  if (!ptime_mismatch && write_frame->codec && write_frame->codec->implementation &&
16201  write_frame->codec->implementation->decoded_bytes_per_packet == session->write_impl.decoded_bytes_per_packet) {
16202  perfect = TRUE;
16203  }
16204 
16205 
16206 
16207  if (perfect) {
16208 
16209  if (write_frame->datalen < session->write_impl.decoded_bytes_per_packet) {
16210  memset(write_frame->data, 255, session->write_impl.decoded_bytes_per_packet - write_frame->datalen);
16211  write_frame->datalen = session->write_impl.decoded_bytes_per_packet;
16212  }
16213 
16214  enc_frame = write_frame;
16215  session->enc_write_frame.datalen = session->enc_write_frame.buflen;
16216  session->write_codec->cur_frame = frame;
16217  frame->codec->cur_frame = frame;
16220  status = switch_core_codec_encode(session->write_codec,
16221  frame->codec,
16222  enc_frame->data,
16223  enc_frame->datalen,
16225  session->enc_write_frame.data, &session->enc_write_frame.datalen, &session->enc_write_frame.rate, &flag);
16226 
16228 
16229  session->write_codec->cur_frame = NULL;
16230  frame->codec->cur_frame = NULL;
16231  switch (status) {
16233  resample++;
16234  /* switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Fixme 2\n"); */
16235  case SWITCH_STATUS_SUCCESS:
16236  session->enc_write_frame.codec = session->write_codec;
16237  session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t) / session->write_impl.number_of_channels;
16240  session->enc_write_frame.timestamp = 0;
16241  } else {
16242  session->enc_write_frame.timestamp = frame->timestamp;
16243  }
16244  session->enc_write_frame.payload = session->write_impl.ianacode;
16245  session->enc_write_frame.m = frame->m;
16246  session->enc_write_frame.ssrc = frame->ssrc;
16247  session->enc_write_frame.seq = frame->seq;
16248  session->enc_write_frame.flags = 0;
16249  write_frame = &session->enc_write_frame;
16250  break;
16251  case SWITCH_STATUS_NOOP:
16252  enc_frame->codec = session->write_codec;
16253  enc_frame->samples = enc_frame->datalen / sizeof(int16_t) / session->write_impl.number_of_channels;
16254  enc_frame->channels = session->write_impl.number_of_channels;
16255  enc_frame->timestamp = frame->timestamp;
16256  enc_frame->m = frame->m;
16257  enc_frame->seq = frame->seq;
16258  enc_frame->ssrc = frame->ssrc;
16259  enc_frame->payload = enc_frame->codec->implementation->ianacode;
16260  write_frame = enc_frame;
16261  break;
16263  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n");
16264  write_frame = NULL;
16265  goto error;
16266  default:
16267  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s encoder error!\n",
16269  write_frame = NULL;
16270  goto error;
16271  }
16272  if (flag & SFF_CNG) {
16273  switch_set_flag(write_frame, SFF_CNG);
16274  }
16275 
16276  status = perform_write(session, write_frame, flags, stream_id);
16277  goto error;
16278  } else {
16279  if (!session->raw_write_buffer) {
16280  switch_size_t bytes_per_packet = session->write_impl.decoded_bytes_per_packet;
16282  "Engaging Write Buffer at %u bytes to accommodate %u->%u\n",
16283  (uint32_t) bytes_per_packet, write_frame->datalen, session->write_impl.decoded_bytes_per_packet);
16284  if ((status = switch_buffer_create_dynamic(&session->raw_write_buffer,
16285  bytes_per_packet * SWITCH_BUFFER_BLOCK_FRAMES,
16286  bytes_per_packet * SWITCH_BUFFER_START_FRAMES, 0)) != SWITCH_STATUS_SUCCESS) {
16287  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Write Buffer Failed!\n");
16288  goto error;
16289  }
16290 
16291  /* Need to retrain the recording data */
16293  }
16294 
16295  if (!(switch_buffer_write(session->raw_write_buffer, write_frame->data, write_frame->datalen))) {
16296  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Write Buffer %u bytes Failed!\n", write_frame->datalen);
16297  status = SWITCH_STATUS_MEMERR;
16298  goto error;
16299  }
16300 
16301  status = SWITCH_STATUS_SUCCESS;
16302 
16304  int rate;
16305 
16306  if (switch_channel_down(session->channel) || !session->raw_write_buffer) {
16307  goto error;
16308  }
16309  if ((session->raw_write_frame.datalen = (uint32_t)
16311  goto error;
16312  }
16313 
16314  enc_frame = &session->raw_write_frame;
16316  session->enc_write_frame.datalen = session->enc_write_frame.buflen;
16317  session->enc_write_frame.timestamp = 0;
16318 
16319 
16320  if (frame->codec && frame->codec->implementation && switch_core_codec_ready(frame->codec)) {
16322  } else {
16323  rate = session->write_impl.actual_samples_per_second;
16324  }
16325 
16326  session->write_codec->cur_frame = frame;
16327  frame->codec->cur_frame = frame;
16330  status = switch_core_codec_encode(session->write_codec,
16331  frame->codec,
16332  enc_frame->data,
16333  enc_frame->datalen,
16334  rate,
16335  session->enc_write_frame.data, &session->enc_write_frame.datalen, &session->enc_write_frame.rate, &flag);
16336 
16338 
16339  session->write_codec->cur_frame = NULL;
16340  frame->codec->cur_frame = NULL;
16341  switch (status) {
16343  resample++;
16344  session->enc_write_frame.codec = session->write_codec;
16345  session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t) / session->write_impl.number_of_channels;
16347  session->enc_write_frame.m = frame->m;
16348  session->enc_write_frame.ssrc = frame->ssrc;
16349  session->enc_write_frame.payload = session->write_impl.ianacode;
16350  write_frame = &session->enc_write_frame;
16351  if (!session->write_resampler) {
16353  if (!session->write_resampler) {
16354  status = switch_resample_create(&session->write_resampler,
16358  session->write_impl.number_of_channels);
16359  }
16361 
16362 
16363 
16364  if (status != SWITCH_STATUS_SUCCESS) {
16365  goto done;
16366  } else {
16367  switch_core_session_message_t msg = { 0 };
16368  msg.numeric_arg = 1;
16370  switch_core_session_receive_message(session, &msg);
16371 
16372 
16373  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Activating write resampler\n");
16374  }
16375  }
16376  break;
16377  case SWITCH_STATUS_SUCCESS:
16378  session->enc_write_frame.codec = session->write_codec;
16379  session->enc_write_frame.samples = enc_frame->datalen / sizeof(int16_t) / session->write_impl.number_of_channels;
16381  session->enc_write_frame.m = frame->m;
16382  session->enc_write_frame.ssrc = frame->ssrc;
16383  session->enc_write_frame.payload = session->write_impl.ianacode;
16384  session->enc_write_frame.flags = 0;
16385  write_frame = &session->enc_write_frame;
16386  break;
16387  case SWITCH_STATUS_NOOP:
16388  if (session->write_resampler) {
16389  switch_core_session_message_t msg = { 0 };
16390  int ok = 0;
16391 
16393  if (session->write_resampler) {
16395  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Deactivating write resampler\n");
16396  ok = 1;
16397  }
16399 
16400  if (ok) {
16401  msg.numeric_arg = 0;
16403  switch_core_session_receive_message(session, &msg);
16404  }
16405 
16406  }
16407  enc_frame->codec = session->write_codec;
16408  enc_frame->samples = enc_frame->datalen / sizeof(int16_t) / session->read_impl.number_of_channels;
16409  enc_frame->channels = session->read_impl.number_of_channels;
16410  enc_frame->m = frame->m;
16411  enc_frame->ssrc = frame->ssrc;
16412  enc_frame->payload = enc_frame->codec->implementation->ianacode;
16413  write_frame = enc_frame;
16414  break;
16416  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec init error!\n");
16417  write_frame = NULL;
16418  goto error;
16419  default:
16420  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec %s encoder error %d!\n",
16421  session->read_codec->codec_interface->interface_name, status);
16422  write_frame = NULL;
16423  goto error;
16424  }
16425 
16426  if (!did_write_resample && session->read_resampler) {
16427  short *data = write_frame->data;
16429  if (session->read_resampler) {
16430  switch_resample_process(session->read_resampler, data, write_frame->datalen / 2 / session->read_resampler->channels);
16431  memcpy(data, session->read_resampler->to, session->read_resampler->to_len * 2 * session->read_resampler->channels);
16432  write_frame->samples = session->read_resampler->to_len;
16433  write_frame->channels = session->read_resampler->channels;
16434  write_frame->datalen = session->read_resampler->to_len * 2 * session->read_resampler->channels;
16435  write_frame->rate = session->read_resampler->to_rate;
16436  }
16438 
16439  }
16440 
16441  if (flag & SFF_CNG) {
16442  switch_set_flag(write_frame, SFF_CNG);
16443  }
16444 
16445  if (ptime_mismatch || resample) {
16446  write_frame->timestamp = 0;
16447  }
16448 
16449  if ((status = perform_write(session, write_frame, flags, stream_id)) != SWITCH_STATUS_SUCCESS) {
16450  break;
16451  }
16452 
16453  }
16454 
16455  goto error;
16456  }
16457  }
16458 
16459 
16460 
16461 
16462 
16463  done:
16464 
16465  if (ptime_mismatch || resample) {
16466  write_frame->timestamp = 0;
16467  }
16468 
16469  if (do_write) {
16470  status = perform_write(session, write_frame, flags, stream_id);
16471  }
16472 
16473  error:
16474 
16476  switch_mutex_unlock(frame->codec->mutex);
16478 
16479  return status;
16480 }
16481 
16483 {
16484  if (!session) return NULL;
16485 
16486  return &session->media_handle->engines[media_type];
16487 }
16488 
16490 {
16491  switch_rtp_engine_t *engine = switch_core_media_get_engine(session, type);
16492 
16493  if (!engine) return NULL;
16494 
16495  return &engine->read_codec;
16496 }
16497 
16498 /* For Emacs:
16499  * Local Variables:
16500  * mode:c
16501  * indent-tabs-mode:t
16502  * tab-width:4
16503  * c-basic-offset:4
16504  * End:
16505  * For VIM:
16506  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
16507  */
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:591
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)
switch_size_t flaws
Definition: switch_types.h:712
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:4875
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:2951
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:760
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:5147
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:3000
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:5045
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:4623
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:303
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:590
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:437
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:692
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:4735
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:3705
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:2649
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.
void switch_core_session_lock_codec_read(_In_ switch_core_session_t *session)
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:2662
#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:695
#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:683
#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:4698
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:689
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:2519
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:2963
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:3039
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:5635
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:3055
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:3028
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:4690
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:5186
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:4761
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:4726
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:8192
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:598
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:762
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:682
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:4834
int switch_rtp_has_dtls(void)
Definition: switch_rtp.c:3697
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:4773
switch_rtp_bug_flag_t
Definition: switch_types.h:848
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:2881
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:4930
#define switch_channel_get_variable(_c, _v)
int index
Definition: switch_cJSON.h:160
#define SWITCH_THREAD_STACKSIZE
Definition: switch_types.h:584
#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:5350
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:761
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_rtp_video_loss(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:5068
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:4466
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:4458
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:3813
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:8051
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:684
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:3125
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:688
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:687
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:4706
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:5431
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:2626
#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:5372
#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:3034
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:4712
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:9223
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:8064
void switch_rtp_flush(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:5025
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)
void switch_core_session_lock_codec_write(_In_ switch_core_session_t *session)
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:5080
void switch_rtp_reset_jb(switch_rtp_t *rtp_session)
Definition: switch_rtp.c:2979
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:793
#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:2542
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:8091
#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:5335
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:691
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:5361
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:8887
switch_size_t media_packet_count
Definition: switch_types.h:686
switch_rtp_stats_t * switch_rtp_get_stats(switch_rtp_t *rtp_session, switch_memory_pool_t *pool)
Definition: switch_rtp.c:9080
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:4783
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:4414
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:4814
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:8830
switch_channel_t * channel
void switch_rtp_release_port(const char *ip, switch_port_t port)
Definition: switch_rtp.c:2610
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:5426
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
void switch_core_session_unlock_codec_write(_In_ switch_core_session_t *session)
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:8117
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:5120
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:5056
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:853
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:5034
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:708
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:8172
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:5320
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:5163
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:4059
#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)
void switch_core_session_unlock_codec_read(_In_ switch_core_session_t *session)
switch_media_type_t type
static void clear_ice(switch_core_session_t *session, switch_media_type_t type)
uint8_t switch_payload_t
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:690
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