2009-08-24 11:58:41 +00:00
|
|
|
/**
|
|
|
|
* parser.cpp
|
|
|
|
* This file is part of the YATE Project http://YATE.null.ro
|
|
|
|
*
|
|
|
|
* SDP media handling
|
|
|
|
*
|
|
|
|
* Yet Another Telephony Engine - a fully featured software PBX and IVR
|
2014-02-05 11:42:17 +00:00
|
|
|
* Copyright (C) 2004-2014 Null Team
|
2009-08-24 11:58:41 +00:00
|
|
|
*
|
2013-08-06 13:38:10 +00:00
|
|
|
* This software is distributed under multiple licenses;
|
|
|
|
* see the COPYING file in the main directory for licensing
|
|
|
|
* information for this specific distribution.
|
|
|
|
*
|
|
|
|
* This use of this software may be subject to additional restrictions.
|
|
|
|
* See the LEGAL file in the main directory for details.
|
2009-08-24 11:58:41 +00:00
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2013-08-06 13:38:10 +00:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
2009-08-24 11:58:41 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <yatesdp.h>
|
|
|
|
|
|
|
|
namespace TelEngine {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SDPParser
|
|
|
|
*/
|
|
|
|
// Yate Payloads for the AV profile
|
|
|
|
const TokenDict SDPParser::s_payloads[] = {
|
|
|
|
{ "mulaw", 0 },
|
|
|
|
{ "alaw", 8 },
|
|
|
|
{ "gsm", 3 },
|
|
|
|
{ "lpc10", 7 },
|
2021-04-19 10:02:58 +00:00
|
|
|
{ "2*slin", 10 },
|
2009-08-24 11:58:41 +00:00
|
|
|
{ "slin", 11 },
|
|
|
|
{ "g726", 2 },
|
2019-11-06 18:31:54 +00:00
|
|
|
{ "g722/16000", 9 },
|
2009-08-24 11:58:41 +00:00
|
|
|
{ "g722", 9 },
|
|
|
|
{ "g723", 4 },
|
|
|
|
{ "g728", 15 },
|
|
|
|
{ "g729", 18 },
|
2009-09-14 09:11:57 +00:00
|
|
|
{ "mpa", 14 },
|
2009-08-24 11:58:41 +00:00
|
|
|
{ "ilbc", 98 },
|
|
|
|
{ "ilbc20", 98 },
|
|
|
|
{ "ilbc30", 98 },
|
|
|
|
{ "amr", 96 },
|
|
|
|
{ "amr-o", 96 },
|
|
|
|
{ "amr/16000", 99 },
|
|
|
|
{ "amr-o/16000", 99 },
|
|
|
|
{ "speex", 102 },
|
|
|
|
{ "speex/16000", 103 },
|
|
|
|
{ "speex/32000", 104 },
|
2012-03-02 17:39:00 +00:00
|
|
|
{ "isac/16000", 105 },
|
|
|
|
{ "isac/32000", 106 },
|
2015-02-26 10:26:51 +00:00
|
|
|
{ "gsm-efr", 107 },
|
2009-09-14 09:11:57 +00:00
|
|
|
{ "mjpeg", 26 },
|
2009-08-24 11:58:41 +00:00
|
|
|
{ "h261", 31 },
|
|
|
|
{ "h263", 34 },
|
2017-02-01 14:07:43 +00:00
|
|
|
{ "h263-1998", 111 },
|
|
|
|
{ "h263-2000", 112 },
|
2017-09-11 13:19:00 +00:00
|
|
|
{ "h264", 114 },
|
2017-02-01 14:07:43 +00:00
|
|
|
{ "vp8", 113 },
|
2019-09-04 10:29:00 +00:00
|
|
|
{ "vp9", 115 },
|
2009-08-24 11:58:41 +00:00
|
|
|
{ "mpv", 32 },
|
2009-09-14 09:11:57 +00:00
|
|
|
{ "mp2t", 33 },
|
2017-02-01 14:07:43 +00:00
|
|
|
{ "mp4v", 110 },
|
2021-04-19 10:02:58 +00:00
|
|
|
// Stereo
|
|
|
|
{ "2*mulaw", 117 },
|
|
|
|
{ "2*alaw", 118 },
|
2017-02-01 14:07:43 +00:00
|
|
|
{ 0, 0 },
|
2009-08-24 11:58:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// SDP Payloads for the AV profile
|
|
|
|
const TokenDict SDPParser::s_rtpmap[] = {
|
2017-02-01 14:07:43 +00:00
|
|
|
{ "PCMU/8000", 0 },
|
|
|
|
{ "PCMA/8000", 8 },
|
|
|
|
{ "GSM/8000", 3 },
|
|
|
|
{ "LPC/8000", 7 },
|
2021-04-19 10:02:58 +00:00
|
|
|
{ "L16/8000/2", 10 },
|
2017-02-01 14:07:43 +00:00
|
|
|
{ "L16/8000", 11 },
|
|
|
|
{ "G726-32/8000", 2 },
|
|
|
|
{ "G722/8000", 9 },
|
|
|
|
{ "G723/8000", 4 },
|
|
|
|
{ "G728/8000", 15 },
|
|
|
|
{ "G729/8000", 18 },
|
|
|
|
{ "G729A/8000", 18 },
|
|
|
|
{ "MPA/90000", 14 },
|
|
|
|
{ "iLBC/8000", 98 },
|
|
|
|
{ "AMR/8000", 96 },
|
|
|
|
{ "AMR-WB/16000", 99 },
|
|
|
|
{ "SPEEX/8000", 102 },
|
|
|
|
{ "SPEEX/16000", 103 },
|
|
|
|
{ "SPEEX/32000", 104 },
|
|
|
|
{ "iSAC/16000", 105 },
|
|
|
|
{ "iSAC/32000", 106 },
|
|
|
|
{ "GSM-EFR/8000", 107 },
|
|
|
|
{ "JPEG/90000", 26 },
|
|
|
|
{ "H261/90000", 31 },
|
|
|
|
{ "H263/90000", 34 },
|
|
|
|
{ "H263-1998/90000", 111 },
|
|
|
|
{ "H263-2000/90000", 112 },
|
2017-09-11 13:19:00 +00:00
|
|
|
{ "H264/90000", 114 },
|
2017-02-01 14:07:43 +00:00
|
|
|
{ "VP8/90000", 113 },
|
2019-09-04 10:29:00 +00:00
|
|
|
{ "VP9/90000", 115 },
|
2017-02-01 14:07:43 +00:00
|
|
|
{ "MPV/90000", 32 },
|
|
|
|
{ "MP2T/90000", 33 },
|
|
|
|
{ "MP4V-ES/90000", 110 },
|
2021-04-19 10:02:58 +00:00
|
|
|
// Stereo, dynamic payloads
|
|
|
|
{ "PCMU/8000/2", 117 },
|
|
|
|
{ "PCMA/8000/2", 118 },
|
2017-02-01 14:07:43 +00:00
|
|
|
{ 0, 0 },
|
2009-08-24 11:58:41 +00:00
|
|
|
};
|
|
|
|
|
2017-05-23 13:23:24 +00:00
|
|
|
enum SdpFormat
|
|
|
|
{
|
|
|
|
SdpFmtUnknown = 0,
|
|
|
|
SdpIlbc,
|
|
|
|
SdpG729,
|
|
|
|
SdpAmr
|
|
|
|
};
|
|
|
|
|
|
|
|
// We need to check parameters (fmtp line) for these formats to detect variants
|
|
|
|
static const TokenDict s_sdpFmtParamsCheck[] = {
|
|
|
|
{ "g729", SdpG729 },
|
|
|
|
{ "ilbc", SdpIlbc },
|
|
|
|
{ "ilbc20", SdpIlbc },
|
|
|
|
{ "ilbc30", SdpIlbc },
|
|
|
|
{ "amr", SdpAmr },
|
|
|
|
{ "amr-o", SdpAmr },
|
|
|
|
{ "amr/16000", SdpAmr },
|
|
|
|
{ "amr-o/16000", SdpAmr },
|
|
|
|
{ 0, 0 },
|
|
|
|
};
|
|
|
|
|
2020-05-20 11:19:12 +00:00
|
|
|
// Utility used in SDPParser::parse
|
|
|
|
// Retrieve a SDP line 'param<payload>' contents
|
|
|
|
// Trim contents spaces
|
|
|
|
static inline String& getPayloadLine(String& buf, ObjList& list, int payload, const char* param)
|
|
|
|
{
|
|
|
|
ObjList* o = list.skipNull();
|
|
|
|
if (!o)
|
|
|
|
return buf;
|
|
|
|
String match;
|
|
|
|
match << param << payload;
|
|
|
|
for (; o; o = o->skipNext()) {
|
|
|
|
const NamedString* ns = static_cast<NamedString*>(o->get());
|
|
|
|
if (!ns->startsWith(match,true))
|
|
|
|
continue;
|
|
|
|
buf = ns->substr(match.length() + 1);
|
|
|
|
buf.trimSpaces();
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2009-08-24 11:58:41 +00:00
|
|
|
// Parse a received SDP body
|
|
|
|
ObjList* SDPParser::parse(const MimeSdpBody& sdp, String& addr, ObjList* oldMedia,
|
2011-05-28 12:28:35 +00:00
|
|
|
const String& media, bool force)
|
2009-08-24 11:58:41 +00:00
|
|
|
{
|
2011-05-28 12:28:35 +00:00
|
|
|
DDebug(DebugAll,"SDPParser::parse(%p,%s,%p,'%s',%s)",
|
|
|
|
&sdp,addr.c_str(),oldMedia,media.safe(),String::boolText(force));
|
2009-08-24 11:58:41 +00:00
|
|
|
const NamedString* c = sdp.getLine("c");
|
|
|
|
if (c) {
|
|
|
|
String tmp(*c);
|
|
|
|
if (tmp.startSkip("IN IP4")) {
|
|
|
|
tmp.trimBlanks();
|
|
|
|
// Handle the case media is muted
|
2013-10-18 18:27:45 +00:00
|
|
|
if (tmp == SocketAddr::ipv4NullAddr())
|
|
|
|
tmp.clear();
|
|
|
|
addr = tmp;
|
|
|
|
}
|
|
|
|
else if (tmp.startSkip("IN IP6")) {
|
|
|
|
tmp.trimBlanks();
|
|
|
|
// Handle the case media is muted
|
|
|
|
if (tmp == SocketAddr::ipv6NullAddr())
|
2009-08-24 11:58:41 +00:00
|
|
|
tmp.clear();
|
|
|
|
addr = tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Lock lock(this);
|
|
|
|
ObjList* lst = 0;
|
|
|
|
bool defcodecs = m_codecs.getBoolValue("default",true);
|
|
|
|
c = sdp.getLine("m");
|
|
|
|
for (; c; c = sdp.getNextLine(c)) {
|
|
|
|
String tmp(*c);
|
|
|
|
int sep = tmp.find(' ');
|
|
|
|
if (sep < 1)
|
|
|
|
continue;
|
|
|
|
String type = tmp.substr(0,sep);
|
|
|
|
tmp >> " ";
|
|
|
|
if (media && (type != media))
|
|
|
|
continue;
|
|
|
|
int port = 0;
|
|
|
|
tmp >> port >> " ";
|
|
|
|
sep = tmp.find(' ');
|
|
|
|
if (sep < 1)
|
|
|
|
continue;
|
|
|
|
bool rtp = true;
|
|
|
|
String trans(tmp,sep);
|
|
|
|
tmp = tmp.c_str() + sep;
|
|
|
|
if ((trans &= "RTP/AVP") || (trans &= "RTP/SAVP") ||
|
|
|
|
(trans &= "RTP/AVPF") || (trans &= "RTP/SAVPF"))
|
|
|
|
trans.toUpper();
|
|
|
|
else if ((trans &= "udptl") || (trans &= "tcp")) {
|
|
|
|
trans.toLower();
|
|
|
|
rtp = false;
|
|
|
|
}
|
2011-05-28 12:28:35 +00:00
|
|
|
else if (!force) {
|
2009-08-24 11:58:41 +00:00
|
|
|
Debug(this,DebugWarn,"Unknown SDP transport '%s' for media '%s'",
|
|
|
|
trans.c_str(),type.c_str());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
String fmt;
|
|
|
|
String aux;
|
|
|
|
String mappings;
|
|
|
|
String crypto;
|
2018-02-07 10:27:43 +00:00
|
|
|
ObjList dups;
|
2009-08-24 11:58:41 +00:00
|
|
|
ObjList params;
|
2012-09-19 10:59:42 +00:00
|
|
|
ObjList* dest = ¶ms;
|
2009-08-24 11:58:41 +00:00
|
|
|
bool first = true;
|
|
|
|
int ptime = 0;
|
|
|
|
int rfc2833 = -1;
|
2020-05-20 11:19:12 +00:00
|
|
|
// Remember format related lines
|
|
|
|
ObjList fmtLines;
|
|
|
|
ObjList* fmtA = &fmtLines;
|
|
|
|
ObjList* o = sdp.lines().find(c);
|
|
|
|
for (o ? o = o->skipNext() : 0; o; o = o->skipNext()) {
|
|
|
|
const NamedString* ns = static_cast<NamedString*>(o->get());
|
|
|
|
if (ns->name() == YSTRING("a")) {
|
|
|
|
if (ns->startsWith("fmtp:") || ns->startsWith("gpmd:")) {
|
|
|
|
fmtA = fmtA->append(ns);
|
|
|
|
fmtA->setDelete(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (ns->name() == YSTRING("m"))
|
|
|
|
break;
|
|
|
|
}
|
2009-08-24 11:58:41 +00:00
|
|
|
while (tmp[0] == ' ') {
|
|
|
|
int var = -1;
|
|
|
|
tmp >> " " >> var;
|
|
|
|
if (var < 0) {
|
|
|
|
if (rtp || fmt || aux || tmp.null())
|
|
|
|
continue;
|
|
|
|
// brutal but effective
|
|
|
|
for (char* p = const_cast<char*>(tmp.c_str()); *p; p++) {
|
|
|
|
if (*p == ' ')
|
|
|
|
*p = ',';
|
|
|
|
}
|
|
|
|
Debug(this,DebugInfo,"Assuming format list '%s' for media '%s'",
|
|
|
|
tmp.c_str(),type.c_str());
|
|
|
|
fmt = tmp;
|
|
|
|
tmp.clear();
|
|
|
|
}
|
|
|
|
int mode = 0;
|
|
|
|
bool annexB = m_codecs.getBoolValue("g729_annexb",false);
|
|
|
|
bool amrOctet = m_codecs.getBoolValue("amr_octet",false);
|
|
|
|
int defmap = -1;
|
|
|
|
String payload(lookup(var,s_payloads));
|
|
|
|
|
|
|
|
const ObjList* l = sdp.lines().find(c);
|
|
|
|
while (l && (l = l->skipNext())) {
|
|
|
|
const NamedString* s = static_cast<NamedString*>(l->get());
|
|
|
|
if (s->name() == "m")
|
|
|
|
break;
|
2016-03-09 17:41:35 +00:00
|
|
|
if (s->name() == "b") {
|
|
|
|
if (first) {
|
|
|
|
int pos = s->find(':');
|
|
|
|
if (pos >= 0)
|
|
|
|
dest = dest->append(new NamedString("BW-" + s->substr(0,pos),s->substr(pos+1)));
|
|
|
|
else
|
|
|
|
dest = dest->append(new NamedString("BW-" + *s));
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2009-08-24 11:58:41 +00:00
|
|
|
if (s->name() != "a")
|
|
|
|
continue;
|
2020-05-20 11:19:12 +00:00
|
|
|
if (s->startsWith("fmtp:") || s->startsWith("gpmd:"))
|
|
|
|
continue;
|
2009-08-24 11:58:41 +00:00
|
|
|
String line(*s);
|
|
|
|
if (line.startSkip("ptime:",false))
|
|
|
|
line >> ptime;
|
|
|
|
else if (line.startSkip("rtpmap:",false)) {
|
|
|
|
int num = var - 1;
|
|
|
|
line >> num >> " ";
|
|
|
|
if (num == var) {
|
|
|
|
line.trimBlanks().toUpper();
|
|
|
|
if (line.startsWith("G729B/")) {
|
|
|
|
// some devices add a second map for same payload
|
|
|
|
annexB = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (line.startsWith("TELEPHONE-EVENT/")) {
|
|
|
|
rfc2833 = var;
|
2011-04-11 15:43:51 +00:00
|
|
|
payload.clear();
|
2009-08-24 11:58:41 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const char* pload = 0;
|
|
|
|
for (const TokenDict* map = s_rtpmap; map->token; map++) {
|
|
|
|
if (line.startsWith(map->token,false,true)) {
|
|
|
|
defmap = map->value;
|
|
|
|
pload = lookup(defmap,s_payloads);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
payload = pload;
|
2018-09-14 09:39:28 +00:00
|
|
|
if (amrOctet) {
|
|
|
|
if (payload == YSTRING("amr"))
|
|
|
|
payload = "amr-o";
|
|
|
|
else if (payload == YSTRING("amr/16000"))
|
|
|
|
payload = "amr-o/16000";
|
|
|
|
}
|
2009-08-24 11:58:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (first) {
|
|
|
|
if (line.startSkip("crypto:",false)) {
|
|
|
|
if (crypto.null())
|
|
|
|
crypto = line;
|
|
|
|
else
|
|
|
|
Debug(this,DebugMild,"Ignoring SDES: '%s'",line.c_str());
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
int pos = line.find(':');
|
|
|
|
if (pos >= 0)
|
2012-09-19 10:59:42 +00:00
|
|
|
dest = dest->append(new NamedString(line.substr(0,pos),line.substr(pos+1)));
|
2009-08-24 11:58:41 +00:00
|
|
|
else
|
2012-09-19 10:59:42 +00:00
|
|
|
dest = dest->append(new NamedString(line));
|
2009-08-24 11:58:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (var < 0)
|
|
|
|
break;
|
|
|
|
first = false;
|
|
|
|
|
2020-05-20 11:19:12 +00:00
|
|
|
String fmtp;
|
|
|
|
if (payload) {
|
|
|
|
// Process 'fmtp' lines: they may change payload name
|
|
|
|
if (getPayloadLine(fmtp,fmtLines,var,"fmtp:")) {
|
|
|
|
bool found = false;
|
|
|
|
ObjList* fmtps = 0;
|
|
|
|
int checkParams = lookup(payload,s_sdpFmtParamsCheck);
|
|
|
|
if (checkParams) {
|
|
|
|
fmtps = fmtp.split(';',false);
|
|
|
|
for (ObjList* o = fmtps->skipNull(); o; o = o->skipNext()) {
|
|
|
|
String& s = *static_cast<String*>(o->get());
|
|
|
|
switch (checkParams) {
|
|
|
|
case SdpIlbc:
|
|
|
|
if (!s.startSkip("mode=",false))
|
|
|
|
continue;
|
|
|
|
s >> mode;
|
|
|
|
break;
|
|
|
|
case SdpG729:
|
|
|
|
if (!s.startSkip("annexb=",false))
|
|
|
|
continue;
|
|
|
|
s >> annexB;
|
|
|
|
break;
|
|
|
|
case SdpAmr:
|
|
|
|
if (s.startSkip("octet-align=",false)) {
|
|
|
|
int val = 0;
|
|
|
|
s >> val;
|
|
|
|
amrOctet = (0 != val);
|
|
|
|
if (amrOctet) {
|
|
|
|
if (payload == YSTRING("amr"))
|
|
|
|
payload = "amr-o";
|
|
|
|
else if (payload == YSTRING("amr/16000"))
|
|
|
|
payload = "amr-o/16000";
|
|
|
|
}
|
|
|
|
else if (payload == YSTRING("amr-o"))
|
|
|
|
payload = "amr";
|
|
|
|
else if (payload == YSTRING("amr-o/16000"))
|
|
|
|
payload = "amr/16000";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
found = true;
|
|
|
|
o->set(0);
|
|
|
|
// Done: we are searching for a single parameter
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
XDebug(this,DebugAll,"%s fmtp '%s' (%d) '%s'",
|
|
|
|
(checkParams ? (found ? "Found" : "Checked") : "Parsed"),
|
|
|
|
payload.c_str(),var,fmtp.c_str());
|
|
|
|
if (found) {
|
|
|
|
fmtp.clear();
|
|
|
|
if (fmtps && fmtps->skipNull())
|
|
|
|
fmtp.append(fmtps,";");
|
|
|
|
}
|
|
|
|
TelEngine::destruct(fmtps);
|
|
|
|
}
|
|
|
|
if (payload == YSTRING("ilbc")) {
|
|
|
|
const char* forced = m_hacks.getValue(YSTRING("ilbc_forced"));
|
|
|
|
if (forced)
|
|
|
|
payload = forced;
|
|
|
|
else if (mode == 20)
|
|
|
|
payload = "ilbc20";
|
|
|
|
else if (mode == 30)
|
|
|
|
payload = "ilbc30";
|
|
|
|
else if ((ptime % 30) && !(ptime % 20))
|
|
|
|
payload = "ilbc20";
|
|
|
|
else if ((ptime % 20) && !(ptime % 30))
|
|
|
|
payload = "ilbc30";
|
|
|
|
else
|
|
|
|
payload = m_hacks.getValue(YSTRING("ilbc_default"),"ilbc30");
|
|
|
|
}
|
2009-08-24 11:58:41 +00:00
|
|
|
}
|
|
|
|
|
2018-02-07 10:27:43 +00:00
|
|
|
XDebug(this,DebugAll,"Payload %d format '%s'%s",var,payload.c_str(),
|
|
|
|
(dups.find(payload) ? " (duplicated)" : ""));
|
|
|
|
if (payload.null() || dups.find(payload))
|
|
|
|
continue;
|
|
|
|
dups.append(new String(payload));
|
|
|
|
if (m_codecs.getBoolValue(payload,defcodecs && DataTranslator::canConvert(payload))) {
|
2009-08-24 11:58:41 +00:00
|
|
|
if (fmt)
|
|
|
|
fmt << ",";
|
|
|
|
fmt << payload;
|
|
|
|
if (var != defmap) {
|
|
|
|
if (mappings)
|
|
|
|
mappings << ",";
|
|
|
|
mappings << payload << "=" << var;
|
|
|
|
}
|
2020-05-20 11:19:12 +00:00
|
|
|
String gpmd;
|
|
|
|
if (getPayloadLine(gpmd,fmtLines,var,"gpmd:")) {
|
|
|
|
XDebug(this,DebugAll,"Found 'gpmd:%d' format='%s' value='%s'",
|
|
|
|
var,payload.c_str(),gpmd.c_str());
|
|
|
|
dest = dest->append(new NamedString("gpmd:" + payload,gpmd));
|
|
|
|
}
|
|
|
|
if (fmtp)
|
|
|
|
dest = dest->append(new NamedString("fmtp:" + payload,fmtp));
|
2011-06-03 13:03:53 +00:00
|
|
|
if ((payload == "g729") && m_hacks.getBoolValue(YSTRING("g729_annexb"),annexB))
|
2009-08-24 11:58:41 +00:00
|
|
|
aux << ",g729b";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fmt += aux;
|
|
|
|
DDebug(this,DebugAll,"Formats '%s' mappings '%s'",fmt.c_str(),mappings.c_str());
|
|
|
|
SDPMedia* net = 0;
|
|
|
|
// try to take the media descriptor from the old list
|
|
|
|
if (oldMedia) {
|
|
|
|
ObjList* om = oldMedia->find(type);
|
|
|
|
if (om)
|
|
|
|
net = static_cast<SDPMedia*>(om->remove(false));
|
|
|
|
}
|
|
|
|
bool append = false;
|
|
|
|
if (net)
|
2011-05-28 12:28:35 +00:00
|
|
|
net->update(fmt,port,-1,force);
|
2009-08-24 11:58:41 +00:00
|
|
|
else {
|
|
|
|
net = new SDPMedia(type,trans,fmt,port);
|
|
|
|
append = true;
|
|
|
|
}
|
|
|
|
while (NamedString* par = static_cast<NamedString*>(params.remove(false)))
|
|
|
|
net->parameter(par,append);
|
|
|
|
net->setModified(false);
|
|
|
|
net->mappings(mappings);
|
|
|
|
net->rfc2833(rfc2833);
|
|
|
|
net->crypto(crypto,true);
|
|
|
|
if (!lst)
|
|
|
|
lst = new ObjList;
|
|
|
|
lst->append(net);
|
|
|
|
// found media - get out
|
|
|
|
if (media)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return lst;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update configuration
|
|
|
|
void SDPParser::initialize(const NamedList* codecs, const NamedList* hacks, const NamedList* general)
|
|
|
|
{
|
|
|
|
Lock lock(this);
|
2010-02-15 13:53:18 +00:00
|
|
|
m_codecs.clearParams();
|
|
|
|
m_hacks.clearParams();
|
2009-08-24 11:58:41 +00:00
|
|
|
if (codecs)
|
|
|
|
m_codecs.copyParams(*codecs);
|
|
|
|
if (hacks)
|
|
|
|
m_hacks.copyParams(*hacks);
|
|
|
|
bool defcodecs = m_codecs.getBoolValue("default",true);
|
2021-04-19 10:02:58 +00:00
|
|
|
bool stereo = m_codecs.getBoolValue("default_stereo");
|
2009-08-24 11:58:41 +00:00
|
|
|
m_audioFormats = "";
|
|
|
|
String audio = "audio";
|
|
|
|
for (const TokenDict* dict = s_payloads; dict->token; dict++) {
|
|
|
|
DataFormat fmt(dict->token);
|
|
|
|
const FormatInfo* info = fmt.getInfo();
|
|
|
|
if (info && (audio == info->type)) {
|
2021-04-19 10:02:58 +00:00
|
|
|
bool defVal = (2 != info->numChannels) ? defcodecs : stereo;
|
|
|
|
if (m_codecs.getBoolValue(fmt,defVal && DataTranslator::canConvert(fmt)))
|
2009-08-24 11:58:41 +00:00
|
|
|
m_audioFormats.append(fmt,",");
|
|
|
|
}
|
|
|
|
}
|
2013-08-06 08:35:00 +00:00
|
|
|
if (m_audioFormats)
|
|
|
|
Debug(this,DebugAll,"Initialized audio codecs: %s",m_audioFormats.c_str());
|
|
|
|
else {
|
2009-08-24 11:58:41 +00:00
|
|
|
m_audioFormats = "alaw,mulaw";
|
2013-08-06 08:35:00 +00:00
|
|
|
Debug(this,DebugWarn,"No default audio codecs, using defaults: %s",
|
|
|
|
m_audioFormats.c_str());
|
2009-08-24 11:58:41 +00:00
|
|
|
}
|
|
|
|
m_ignorePort = m_hacks.getBoolValue("ignore_sdp_port",false);
|
2011-04-12 15:41:49 +00:00
|
|
|
m_rfc2833 = 101;
|
2009-08-24 11:58:41 +00:00
|
|
|
m_secure = false;
|
|
|
|
m_sdpForward = false;
|
|
|
|
if (general) {
|
2011-04-12 15:41:49 +00:00
|
|
|
if (general->getBoolValue("rfc2833",true)) {
|
|
|
|
m_rfc2833 = general->getIntValue("rfc2833",m_rfc2833);
|
|
|
|
if (m_rfc2833 < 96 || m_rfc2833 > 127)
|
|
|
|
m_rfc2833 = 101;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m_rfc2833 = -1;
|
2009-08-24 11:58:41 +00:00
|
|
|
m_secure = general->getBoolValue("secure",m_secure);
|
|
|
|
m_sdpForward = general->getBoolValue("forward_sdp",m_sdpForward);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}; // namespace TelEngine
|
|
|
|
|
|
|
|
/* vi: set ts=8 sw=4 sts=4 noet: */
|