aboutsummaryrefslogtreecommitdiffstats
path: root/channels/h323
diff options
context:
space:
mode:
authorpcadach <pcadach@f38db490-d61c-443f-a65b-d21fe96a405b>2006-09-25 09:03:14 +0000
committerpcadach <pcadach@f38db490-d61c-443f-a65b-d21fe96a405b>2006-09-25 09:03:14 +0000
commit6afd11ca94cf42517b1b54d12d0a2bbec48f882d (patch)
treec2bae1e4c7c50f0fab245c5b0a3801def542495e /channels/h323
parent64ba076d80e754405820111bbca446695bc922fc (diff)
Support for negotiation and receiption of Cisco's RTP DTMF
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@43597 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/h323')
-rw-r--r--channels/h323/ast_h323.cxx123
-rw-r--r--channels/h323/ast_h323.h2
-rw-r--r--channels/h323/caps_h323.cxx13
-rw-r--r--channels/h323/chan_h323.h8
4 files changed, 111 insertions, 35 deletions
diff --git a/channels/h323/ast_h323.cxx b/channels/h323/ast_h323.cxx
index 61634aea9..be22ca64a 100644
--- a/channels/h323/ast_h323.cxx
+++ b/channels/h323/ast_h323.cxx
@@ -533,7 +533,7 @@ MyH323Connection::MyH323Connection(MyH323EndPoint & ep, unsigned callReference,
bridging = FALSE;
progressSetup = progressAlert = 0;
dtmfMode = 0;
- dtmfCodec = (RTP_DataFrame::PayloadTypes)0;
+ dtmfCodec[0] = dtmfCodec[1] = (RTP_DataFrame::PayloadTypes)0;
redirect_reason = -1;
#ifdef TUNNELLING
tunnelOptions = remoteTunnelOptions = 0;
@@ -664,7 +664,8 @@ void MyH323Connection::SetCallOptions(void *o, BOOL isIncoming)
progressSetup = opts->progress_setup;
progressAlert = opts->progress_alert;
- dtmfCodec = (RTP_DataFrame::PayloadTypes)opts->dtmfcodec;
+ dtmfCodec[0] = (RTP_DataFrame::PayloadTypes)opts->dtmfcodec[0];
+ dtmfCodec[1] = (RTP_DataFrame::PayloadTypes)opts->dtmfcodec[1];
dtmfMode = opts->dtmfmode;
if (isIncoming) {
@@ -1213,7 +1214,8 @@ void MyH323Connection::SendUserInputTone(char tone, unsigned duration, unsigned
void MyH323Connection::OnUserInputTone(char tone, unsigned duration, unsigned logicalChannel, unsigned rtpTimestamp)
{
- if ((dtmfMode & H323_DTMF_RFC2833)) {
+ /* Why we should check this? */
+ if ((dtmfMode & (H323_DTMF_CISCO | H323_DTMF_RFC2833 | H323_DTMF_SIGNAL)) != 0) {
if (h323debug) {
cout << "\t-- Received user input tone (" << tone << ") from remote" << endl;
}
@@ -1243,10 +1245,10 @@ void MyH323Connection::OnSendCapabilitySet(H245_TerminalCapabilitySet & pdu)
H245_Capability & cap = entry.m_capability;
if (cap.GetTag() == H245_Capability::e_receiveRTPAudioTelephonyEventCapability) {
H245_AudioTelephonyEventCapability & atec = cap;
- atec.m_dynamicRTPPayloadType = dtmfCodec;
-// on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)dtmfCodec);
+ atec.m_dynamicRTPPayloadType = dtmfCodec[0];
+// on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)dtmfCodec[0]);
if (h323debug) {
- cout << "\t-- Transmitting RFC2833 on payload " <<
+ cout << "\t-- Receiving RFC2833 on payload " <<
atec.m_dynamicRTPPayloadType << endl;
}
}
@@ -1299,21 +1301,12 @@ BOOL MyH323Connection::OnReceivedCapabilitySet(const H323Capabilities & remoteCa
};
#endif
struct ast_codec_pref prefs;
+ RTP_DataFrame::PayloadTypes pt;
if (!H323Connection::OnReceivedCapabilitySet(remoteCaps, muxCap, reject)) {
return FALSE;
}
- const H323Capability * cap = remoteCaps.FindCapability(H323_UserInputCapability::SubTypeNames[H323_UserInputCapability::SignalToneRFC2833]);
- if (cap != NULL) {
- RTP_DataFrame::PayloadTypes pt = ((H323_UserInputCapability*)cap)->GetPayloadType();
- on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)pt);
- if ((dtmfMode & H323_DTMF_RFC2833) && (sendUserInputMode == SendUserInputAsTone))
- sendUserInputMode = SendUserInputAsInlineRFC2833;
- if (h323debug) {
- cout << "\t-- Inbound RFC2833 on payload " << pt << endl;
- }
- }
memset(&prefs, 0, sizeof(prefs));
int peer_capabilities = 0;
for (int i = 0; i < remoteCapabilities.GetSize(); ++i) {
@@ -1346,6 +1339,32 @@ BOOL MyH323Connection::OnReceivedCapabilitySet(const H323Capabilities & remoteCa
}
}
break;
+ case H323Capability::e_Data:
+ if (!strcmp((const char *)remoteCapabilities[i].GetFormatName(), CISCO_DTMF_RELAY)) {
+ pt = remoteCapabilities[i].GetPayloadType();
+ if ((dtmfMode & H323_DTMF_CISCO) != 0) {
+ on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)pt, 1);
+// if (sendUserInputMode == SendUserInputAsTone)
+// sendUserInputMode = SendUserInputAsInlineRFC2833;
+ }
+ if (h323debug) {
+ cout << "\t-- Outbound Cisco RTP DTMF on payload " << pt << endl;
+ }
+ }
+ break;
+ case H323Capability::e_UserInput:
+ if (!strcmp((const char *)remoteCapabilities[i].GetFormatName(), H323_UserInputCapability::SubTypeNames[H323_UserInputCapability::SignalToneRFC2833])) {
+ pt = remoteCapabilities[i].GetPayloadType();
+ if ((dtmfMode & H323_DTMF_RFC2833) != 0) {
+ on_set_rfc2833_payload(GetCallReference(), (const char *)GetCallToken(), (int)pt, 0);
+// if (sendUserInputMode == SendUserInputAsTone)
+// sendUserInputMode = SendUserInputAsInlineRFC2833;
+ }
+ if (h323debug) {
+ cout << "\t-- Outbound RFC2833 on payload " << pt << endl;
+ }
+ }
+ break;
#if 0
case H323Capability::e_Video:
for (int x = 0; vcodecs[x].asterisk_codec > 0; ++x) {
@@ -1416,7 +1435,7 @@ BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
return connectionState != ShuttingDownConnection;
}
-void MyH323Connection::SetCapabilities(int cap, int dtmf_mode, void *_prefs, int pref_codec)
+void MyH323Connection::SetCapabilities(int caps, int dtmf_mode, void *_prefs, int pref_codec)
{
PINDEX lastcap = -1; /* last common capability index */
int alreadysent = 0;
@@ -1427,11 +1446,12 @@ void MyH323Connection::SetCapabilities(int cap, int dtmf_mode, void *_prefs, int
struct ast_format_list format;
int frames_per_packet;
int max_frames_per_packet;
+ H323Capability *cap;
localCapabilities.RemoveAll();
if (h323debug) {
- cout << "Setting capabilities to " << ast_getformatname_multiple(caps_str, sizeof(caps_str), cap) << endl;
+ cout << "Setting capabilities to " << ast_getformatname_multiple(caps_str, sizeof(caps_str), caps) << endl;
ast_codec_pref_string(prefs, caps_str, sizeof(caps_str));
cout << "Capabilities in preference order is " << caps_str << endl;
}
@@ -1449,7 +1469,7 @@ void MyH323Connection::SetCapabilities(int cap, int dtmf_mode, void *_prefs, int
y <<= 1;
codec = y;
}
- if (!(cap & codec) || (alreadysent & codec) || !(codec & AST_FORMAT_AUDIO_MASK))
+ if (!(caps & codec) || (alreadysent & codec) || !(codec & AST_FORMAT_AUDIO_MASK))
continue;
alreadysent |= codec;
format = ast_codec_pref_getsize(prefs, codec);
@@ -1518,23 +1538,64 @@ void MyH323Connection::SetCapabilities(int cap, int dtmf_mode, void *_prefs, int
}
}
- lastcap++;
- lastcap = localCapabilities.SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::HookFlashH245));
+ cap = new H323_UserInputCapability(H323_UserInputCapability::HookFlashH245);
+ if (cap && cap->IsUsable(*this)) {
+ lastcap++;
+ lastcap = localCapabilities.SetCapability(0, lastcap, cap);
+ } else if (cap)
+ delete cap; /* Capability is not usable */
- lastcap++;
dtmfMode = dtmf_mode;
- if ((dtmfMode & H323_DTMF_INBAND)) {
- localCapabilities.SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::BasicString));
- sendUserInputMode = SendUserInputAsString;
- } else {
- lastcap = localCapabilities.SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneRFC2833));
- /* Cisco sends DTMF only through h245-alphanumeric or h245-signal, no support for RFC2833 */
- lastcap = localCapabilities.SetCapability(0, lastcap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneH245));
- sendUserInputMode = SendUserInputAsTone; /* RFC2833 transmission handled at Asterisk level */
+ if (h323debug) {
+ cout << "DTMF mode is " << (int)dtmfMode << endl;
+ }
+ if (dtmfMode) {
+ lastcap++;
+ if (dtmfMode == H323_DTMF_INBAND) {
+ cap = new H323_UserInputCapability(H323_UserInputCapability::BasicString);
+ if (cap && cap->IsUsable(*this)) {
+ lastcap = localCapabilities.SetCapability(0, lastcap, cap);
+ } else if (cap)
+ delete cap; /* Capability is not usable */
+ sendUserInputMode = SendUserInputAsString;
+ } else {
+ if ((dtmfMode & H323_DTMF_RFC2833) != 0) {
+ cap = new H323_UserInputCapability(H323_UserInputCapability::SignalToneRFC2833);
+ if (cap && cap->IsUsable(*this))
+ lastcap = localCapabilities.SetCapability(0, lastcap, cap);
+ else {
+ dtmfMode |= H323_DTMF_SIGNAL;
+ if (cap)
+ delete cap; /* Capability is not usable */
+ }
+ }
+ if ((dtmfMode & H323_DTMF_CISCO) != 0) {
+ /* Try Cisco's RTP DTMF relay too, but prefer RFC2833 or h245-signal */
+ cap = new AST_CiscoDtmfCapability();
+ if (cap && cap->IsUsable(*this)) {
+ lastcap = localCapabilities.SetCapability(0, lastcap, cap);
+ /* We cannot send Cisco RTP DTMFs, use h245-signal instead */
+ dtmfMode |= H323_DTMF_SIGNAL;
+ } else {
+ dtmfMode |= H323_DTMF_SIGNAL;
+ if (cap)
+ delete cap; /* Capability is not usable */
+ }
+ }
+ if ((dtmfMode & H323_DTMF_SIGNAL) != 0) {
+ /* Cisco usually sends DTMF correctly only through h245-alphanumeric or h245-signal */
+ cap = new H323_UserInputCapability(H323_UserInputCapability::SignalToneH245);
+ if (cap && cap->IsUsable(*this))
+ lastcap = localCapabilities.SetCapability(0, lastcap, cap);
+ else if (cap)
+ delete cap; /* Capability is not usable */
+ }
+ sendUserInputMode = SendUserInputAsTone; /* RFC2833 transmission handled at Asterisk level */
+ }
}
if (h323debug) {
- cout << "Allowed Codecs:\n\t" << setprecision(2) << localCapabilities << endl;
+ cout << "Allowed Codecs for " << GetCallToken() << " (" << GetSignallingChannel()->GetLocalAddress() << "):\n\t" << setprecision(2) << localCapabilities << endl;
}
}
diff --git a/channels/h323/ast_h323.h b/channels/h323/ast_h323.h
index 4c85c2442..7199b0f34 100644
--- a/channels/h323/ast_h323.h
+++ b/channels/h323/ast_h323.h
@@ -112,7 +112,7 @@ public:
unsigned progressAlert;
int cause;
- RTP_DataFrame::PayloadTypes dtmfCodec;
+ RTP_DataFrame::PayloadTypes dtmfCodec[2];
int dtmfMode;
};
diff --git a/channels/h323/caps_h323.cxx b/channels/h323/caps_h323.cxx
index 1a14e2337..ebb90f3f2 100644
--- a/channels/h323/caps_h323.cxx
+++ b/channels/h323/caps_h323.cxx
@@ -18,6 +18,7 @@ H323_REGISTER_CAPABILITY(AST_G729Capability, OPAL_G729);
H323_REGISTER_CAPABILITY(AST_G729ACapability, OPAL_G729A);
H323_REGISTER_CAPABILITY(AST_GSM0610Capability, OPAL_GSM0610);
H323_REGISTER_CAPABILITY(AST_CiscoG726Capability, CISCO_G726r32);
+H323_REGISTER_CAPABILITY(AST_CiscoDtmfCapability, CISCO_DTMF_RELAY);
OPAL_MEDIA_FORMAT_DECLARE(OpalG711ALaw64kFormat,
OPAL_G711_ALAW_64K,
@@ -99,6 +100,18 @@ OPAL_MEDIA_FORMAT_DECLARE(OpalCiscoG726Format,
8, // 1 millisecond
OpalMediaFormat::AudioTimeUnits,
0);
+#if 0
+OPAL_MEDIA_FORMAT_DECLARE(OpalCiscoDTMFRelayFormat,
+ CISCO_DTMF_RELAY,
+ OpalMediaFormat::DefaultAudioSessionID,
+ (RTP_DataFrame::PayloadTypes)121, // Choose this for Cisco IOS compatibility
+ TRUE, // Needs jitter
+ 100, // bits/sec
+ 4, // bytes/frame
+ 8*150, // 150 millisecond
+ OpalMediaFormat::AudioTimeUnits,
+ 0);
+#endif
/*
* Capability: G.711
diff --git a/channels/h323/chan_h323.h b/channels/h323/chan_h323.h
index 8905e4eea..13296ed1a 100644
--- a/channels/h323/chan_h323.h
+++ b/channels/h323/chan_h323.h
@@ -52,7 +52,7 @@ typedef struct call_options {
int progress_setup;
int progress_alert;
int progress_audio;
- int dtmfcodec;
+ int dtmfcodec[2];
int dtmfmode;
int capability;
int bridge;
@@ -172,7 +172,7 @@ extern answer_call_cb on_answer_call;
/* This is a callback prototype function, called when
we know which RTP payload type RFC2833 will be
transmitted */
-typedef void (*rfc2833_cb)(unsigned, const char *, int);
+typedef void (*rfc2833_cb)(unsigned, const char *, int, int);
extern rfc2833_cb on_set_rfc2833_payload;
typedef void (*hangup_cb)(unsigned, const char *, int);
@@ -188,7 +188,9 @@ extern setpeercapabilities_cb on_setpeercapabilities;
extern int h323debug;
#define H323_DTMF_RFC2833 (1 << 0)
-#define H323_DTMF_INBAND (1 << 1)
+#define H323_DTMF_CISCO (1 << 1)
+#define H323_DTMF_SIGNAL (1 << 2)
+#define H323_DTMF_INBAND (1 << 3)
#define H323_DTMF_RFC2833_PT 101
#define H323_DTMF_CISCO_PT 121