aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
authoroej <oej@f38db490-d61c-443f-a65b-d21fe96a405b>2007-02-16 13:35:44 +0000
committeroej <oej@f38db490-d61c-443f-a65b-d21fe96a405b>2007-02-16 13:35:44 +0000
commit4e2960819ad733e4113779c148bd12cfc261a312 (patch)
tree896555baaa9bfecc19177b5773ace97b5092f7dc /main
parentbfa699873067bdb5da1d13e475fc8882946b03ec (diff)
Adding Realtime Text support (T.140) to Asterisk
T.140/RFC 2793 is a live communication channel, originally created for IP based text phones for hearing impaired. Feels very much like the old Unix talk application. This code is developed and disclaimed by John Martin of Aupix, UK. Tested for interoperability by myself and Omnitor in Sweden, the company that wrote most of the specifications. A big thank you to everyone involved in this. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@54838 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main')
-rw-r--r--main/channel.c12
-rw-r--r--main/rtp.c118
2 files changed, 95 insertions, 35 deletions
diff --git a/main/channel.c b/main/channel.c
index 94e21d082..0405a7ab5 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -2569,8 +2569,13 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
CHECK_BLOCKING(chan);
break;
case AST_FRAME_TEXT:
- res = (chan->tech->send_text == NULL) ? 0 :
- chan->tech->send_text(chan, (char *) fr->data);
+ if (fr->subclass == AST_FORMAT_T140) {
+ res = (chan->tech->write_text == NULL) ? 0 :
+ chan->tech->write_text(chan, fr);
+ } else {
+ res = (chan->tech->send_text == NULL) ? 0 :
+ chan->tech->send_text(chan, (char *) fr->data);
+ }
break;
case AST_FRAME_HTML:
res = (chan->tech->send_html == NULL) ? 0 :
@@ -2898,6 +2903,7 @@ struct ast_channel *ast_request(const char *type, int format, void *data, int *c
int res;
int foo;
int videoformat = format & AST_FORMAT_VIDEO_MASK;
+ int textformat = format & AST_FORMAT_TEXT_MASK;
if (!cause)
cause = &foo;
@@ -2924,7 +2930,7 @@ struct ast_channel *ast_request(const char *type, int format, void *data, int *c
if (!chan->tech->requester)
return NULL;
- if (!(c = chan->tech->requester(type, capabilities | videoformat, data, cause)))
+ if (!(c = chan->tech->requester(type, capabilities | videoformat | textformat, data, cause)))
return NULL;
/* no need to generate a Newchannel event here; it is done in the channel_alloc call */
diff --git a/main/rtp.c b/main/rtp.c
index 21310e1e7..afb5c256a 100644
--- a/main/rtp.c
+++ b/main/rtp.c
@@ -118,6 +118,8 @@ struct ast_rtp {
unsigned int lastrxts;
unsigned int lastividtimestamp;
unsigned int lastovidtimestamp;
+ unsigned int lastitexttimestamp;
+ unsigned int lastotexttimestamp;
unsigned int lasteventseqn;
int lastrxseqno; /*!< Last received sequence number */
unsigned short seedrxseqno; /*!< What sequence number did they start with?*/
@@ -1333,7 +1335,7 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
return f ? f : &ast_null_frame;
}
rtp->lastrxformat = rtp->f.subclass = rtpPT.code;
- rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : AST_FRAME_VIDEO;
+ rtp->f.frametype = (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) ? AST_FRAME_VOICE : (rtp->f.subclass < AST_FORMAT_MAX_VIDEO) ? AST_FRAME_VIDEO : AST_FRAME_TEXT;
if (!rtp->lastrxts)
rtp->lastrxts = timestamp;
@@ -1357,7 +1359,7 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
rtp->f.ts = timestamp / 8;
rtp->f.len = rtp->f.samples / 8;
rtp->f.seqno = seqno;
- } else {
+ } else if(rtp->f.subclass < AST_FORMAT_MAX_VIDEO) {
/* Video -- samples is # of samples vs. 90000 */
if (!rtp->lastividtimestamp)
rtp->lastividtimestamp = timestamp;
@@ -1367,7 +1369,14 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
rtp->f.delivery.tv_usec = 0;
if (mark)
rtp->f.subclass |= 0x1;
-
+ } else {
+ /* TEXT -- samples is # of samples vs. 1000 */
+ if (!rtp->lastitexttimestamp)
+ rtp->lastitexttimestamp = timestamp;
+ rtp->f.samples = timestamp - rtp->lastitexttimestamp;
+ rtp->lastitexttimestamp = timestamp;
+ rtp->f.delivery.tv_sec = 0;
+ rtp->f.delivery.tv_usec = 0;
}
rtp->f.src = "RTP";
return &rtp->f;
@@ -1524,9 +1533,10 @@ int ast_rtp_early_bridge(struct ast_channel *c0, struct ast_channel *c1)
// dest = c0, src = c1
struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */
struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */
+ struct ast_rtp *tdestp = NULL, *tsrcp = NULL; /* Text RTP channels */
struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
- enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
- enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED;
+ enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED, text_dest_res = AST_RTP_GET_FAILED;
+ enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED, text_src_res = AST_RTP_GET_FAILED;
int srccodec, nat_active = 0;
/* Lock channels */
@@ -1560,12 +1570,14 @@ int ast_rtp_early_bridge(struct ast_channel *c0, struct ast_channel *c1)
return -1;
}
- /* Get audio and video interface (if native bridge is possible) */
+ /* Get audio, video and text interface (if native bridge is possible) */
audio_dest_res = destpr->get_rtp_info(c0, &destp);
video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(c0, &vdestp) : AST_RTP_GET_FAILED;
+ text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(c0, &tdestp) : AST_RTP_GET_FAILED;
if (srcpr) {
audio_src_res = srcpr->get_rtp_info(c1, &srcp);
video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(c1, &vsrcp) : AST_RTP_GET_FAILED;
+ text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(c1, &tsrcp) : AST_RTP_GET_FAILED;
}
/* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
@@ -1586,7 +1598,7 @@ int ast_rtp_early_bridge(struct ast_channel *c0, struct ast_channel *c1)
if (srcp && (srcp->nat || ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
nat_active = 1;
/* Bridge media early */
- if (destpr->set_rtp_peer(c0, srcp, vsrcp, srccodec, nat_active))
+ if (destpr->set_rtp_peer(c0, srcp, vsrcp, tsrcp, srccodec, nat_active))
ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", c0->name, c1 ? c1->name : "<unspecified>");
ast_channel_unlock(c0);
if (c1)
@@ -1600,9 +1612,10 @@ int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src, i
{
struct ast_rtp *destp = NULL, *srcp = NULL; /* Audio RTP Channels */
struct ast_rtp *vdestp = NULL, *vsrcp = NULL; /* Video RTP channels */
+ struct ast_rtp *tdestp = NULL, *tsrcp = NULL; /* Text RTP channels */
struct ast_rtp_protocol *destpr = NULL, *srcpr = NULL;
- enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED;
- enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED;
+ enum ast_rtp_get_result audio_dest_res = AST_RTP_GET_FAILED, video_dest_res = AST_RTP_GET_FAILED, text_dest_res = AST_RTP_GET_FAILED;
+ enum ast_rtp_get_result audio_src_res = AST_RTP_GET_FAILED, video_src_res = AST_RTP_GET_FAILED, text_src_res = AST_RTP_GET_FAILED;
int srccodec;
/* Lock channels */
@@ -1632,8 +1645,10 @@ int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src, i
/* Get audio and video interface (if native bridge is possible) */
audio_dest_res = destpr->get_rtp_info(dest, &destp);
video_dest_res = destpr->get_vrtp_info ? destpr->get_vrtp_info(dest, &vdestp) : AST_RTP_GET_FAILED;
+ text_dest_res = destpr->get_trtp_info ? destpr->get_trtp_info(dest, &tdestp) : AST_RTP_GET_FAILED;
audio_src_res = srcpr->get_rtp_info(src, &srcp);
video_src_res = srcpr->get_vrtp_info ? srcpr->get_vrtp_info(src, &vsrcp) : AST_RTP_GET_FAILED;
+ text_src_res = srcpr->get_trtp_info ? srcpr->get_trtp_info(src, &tsrcp) : AST_RTP_GET_FAILED;
/* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
if (audio_dest_res != AST_RTP_TRY_NATIVE || audio_src_res != AST_RTP_TRY_NATIVE) {
@@ -1645,13 +1660,15 @@ int ast_rtp_make_compatible(struct ast_channel *dest, struct ast_channel *src, i
ast_rtp_pt_copy(destp, srcp);
if (vdestp && vsrcp)
ast_rtp_pt_copy(vdestp, vsrcp);
+ if (tdestp && tsrcp)
+ ast_rtp_pt_copy(tdestp, tsrcp);
if (srcpr->get_codec)
srccodec = srcpr->get_codec(src);
else
srccodec = 0;
if (media) {
/* Bridge early */
- if (destpr->set_rtp_peer(dest, srcp, vsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
+ if (destpr->set_rtp_peer(dest, srcp, vsrcp, tsrcp, srccodec, ast_test_flag(srcp, FLAG_NAT_ACTIVE)))
ast_log(LOG_WARNING, "Channel '%s' failed to setup early bridge to '%s'\n", dest->name, src->name);
}
ast_channel_unlock(dest);
@@ -2080,6 +2097,8 @@ void ast_rtp_reset(struct ast_rtp *rtp)
rtp->lastrxts = 0;
rtp->lastividtimestamp = 0;
rtp->lastovidtimestamp = 0;
+ rtp->lastitexttimestamp = 0;
+ rtp->lastotexttimestamp = 0;
rtp->lasteventseqn = 0;
rtp->lasteventendseqn = 0;
rtp->lasttxformat = 0;
@@ -2627,7 +2646,7 @@ static int ast_rtp_raw_write(struct ast_rtp *rtp, struct ast_frame *f, int codec
mark = 1;
}
}
- } else {
+ } else if(f->subclass < AST_FORMAT_MAX_VIDEO) {
mark = f->subclass & 0x1;
pred = rtp->lastovidtimestamp + f->samples;
/* Re-calculate last TS */
@@ -2643,6 +2662,21 @@ static int ast_rtp_raw_write(struct ast_rtp *rtp, struct ast_frame *f, int codec
rtp->lastovidtimestamp = rtp->lastts;
}
}
+ } else {
+ pred = rtp->lastotexttimestamp + f->samples;
+ /* Re-calculate last TS */
+ rtp->lastts = rtp->lastts + ms * 90;
+ /* If it's close to our prediction, go for it */
+ if (ast_tvzero(f->delivery)) {
+ if (abs(rtp->lastts - pred) < 7200) {
+ rtp->lastts = pred;
+ rtp->lastotexttimestamp += f->samples;
+ } else {
+ if (option_debug > 2)
+ ast_log(LOG_DEBUG, "Difference is %d, ms is %d (%d), pred/ts/samples %d/%d/%d\n", abs(rtp->lastts - pred), ms, ms * 90, rtp->lastts, pred, f->samples);
+ rtp->lastotexttimestamp = rtp->lastts;
+ }
+ }
}
/* If the timestamp for non-digit packets has moved beyond the timestamp
for digits, update the digit timestamp.
@@ -2736,11 +2770,12 @@ int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *_f)
return 0;
/* Make sure we have enough space for RTP header */
- if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO)) {
- ast_log(LOG_WARNING, "RTP can only send voice and video\n");
+ if ((_f->frametype != AST_FRAME_VOICE) && (_f->frametype != AST_FRAME_VIDEO) && (_f->frametype != AST_FRAME_TEXT)) {
+ ast_log(LOG_WARNING, "RTP can only send voice, video and text\n");
return -1;
}
+ /* The bottom bit of a video subclass contains the marker bit */
subclass = _f->subclass;
if (_f->frametype == AST_FRAME_VIDEO)
subclass &= ~0x1;
@@ -2825,29 +2860,33 @@ int ast_rtp_proto_register(struct ast_rtp_protocol *proto)
}
/*! \brief Bridge loop for true native bridge (reinvite) */
-static enum ast_bridge_result bridge_native_loop(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, struct ast_rtp *vp0, struct ast_rtp *vp1, struct ast_rtp_protocol *pr0, struct ast_rtp_protocol *pr1, int codec0, int codec1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
+static enum ast_bridge_result bridge_native_loop(struct ast_channel *c0, struct ast_channel *c1, struct ast_rtp *p0, struct ast_rtp *p1, struct ast_rtp *vp0, struct ast_rtp *vp1, struct ast_rtp *tp0, struct ast_rtp *tp1, struct ast_rtp_protocol *pr0, struct ast_rtp_protocol *pr1, int codec0, int codec1, int timeoutms, int flags, struct ast_frame **fo, struct ast_channel **rc, void *pvt0, void *pvt1)
{
struct ast_frame *fr = NULL;
struct ast_channel *who = NULL, *other = NULL, *cs[3] = {NULL, };
int oldcodec0 = codec0, oldcodec1 = codec1;
- struct sockaddr_in ac1 = {0,}, vac1 = {0,}, ac0 = {0,}, vac0 = {0,};
- struct sockaddr_in t1 = {0,}, vt1 = {0,}, t0 = {0,}, vt0 = {0,};
+ struct sockaddr_in ac1 = {0,}, vac1 = {0,}, tac1 = {0,}, ac0 = {0,}, vac0 = {0,}, tac0 = {0,};
+ struct sockaddr_in t1 = {0,}, vt1 = {0,}, tt1 = {0,}, t0 = {0,}, vt0 = {0,}, tt0 = {0,};
/* Set it up so audio goes directly between the two endpoints */
/* Test the first channel */
- if (!(pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) {
+ if (!(pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))) {
ast_rtp_get_peer(p1, &ac1);
if (vp1)
ast_rtp_get_peer(vp1, &vac1);
+ if (tp1)
+ ast_rtp_get_peer(tp1, &tac1);
} else
ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
/* Test the second channel */
- if (!(pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) {
+ if (!(pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))) {
ast_rtp_get_peer(p0, &ac0);
if (vp0)
ast_rtp_get_peer(vp0, &vac0);
+ if (tp0)
+ ast_rtp_get_peer(tp0, &tac0);
} else
ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c1->name, c0->name);
@@ -2867,10 +2906,10 @@ static enum ast_bridge_result bridge_native_loop(struct ast_channel *c0, struct
if (option_debug)
ast_log(LOG_DEBUG, "Oooh, something is weird, backing out\n");
if (c0->tech_pvt == pvt0)
- if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
+ if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
if (c1->tech_pvt == pvt1)
- if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
+ if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
return AST_BRIDGE_RETRY;
}
@@ -2879,44 +2918,56 @@ static enum ast_bridge_result bridge_native_loop(struct ast_channel *c0, struct
ast_rtp_get_peer(p1, &t1);
if (vp1)
ast_rtp_get_peer(vp1, &vt1);
+ if (tp1)
+ ast_rtp_get_peer(tp1, &tt1);
if (pr1->get_codec)
codec1 = pr1->get_codec(c1);
ast_rtp_get_peer(p0, &t0);
if (vp0)
ast_rtp_get_peer(vp0, &vt0);
+ if (tp0)
+ ast_rtp_get_peer(tp0, &tt0);
if (pr0->get_codec)
codec0 = pr0->get_codec(c0);
if ((inaddrcmp(&t1, &ac1)) ||
(vp1 && inaddrcmp(&vt1, &vac1)) ||
+ (tp1 && inaddrcmp(&tt1, &tac1)) ||
(codec1 != oldcodec1)) {
if (option_debug > 1) {
ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port), codec1);
ast_log(LOG_DEBUG, "Oooh, '%s' changed end vaddress to %s:%d (format %d)\n",
c1->name, ast_inet_ntoa(vt1.sin_addr), ntohs(vt1.sin_port), codec1);
+ ast_log(LOG_DEBUG, "Oooh, '%s' changed end taddress to %s:%d (format %d)\n",
+ c1->name, ast_inet_ntoa(tt1.sin_addr), ntohs(tt1.sin_port), codec1);
ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port), oldcodec1);
ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
c1->name, ast_inet_ntoa(vac1.sin_addr), ntohs(vac1.sin_port), oldcodec1);
+ ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
+ c1->name, ast_inet_ntoa(tac1.sin_addr), ntohs(tac1.sin_port), oldcodec1);
}
- if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))
+ if (pr0->set_rtp_peer(c0, t1.sin_addr.s_addr ? p1 : NULL, vt1.sin_addr.s_addr ? vp1 : NULL, tt1.sin_addr.s_addr ? tp1 : NULL, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE)))
ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c0->name, c1->name);
memcpy(&ac1, &t1, sizeof(ac1));
memcpy(&vac1, &vt1, sizeof(vac1));
+ memcpy(&tac1, &tt1, sizeof(tac1));
oldcodec1 = codec1;
}
if ((inaddrcmp(&t0, &ac0)) ||
- (vp0 && inaddrcmp(&vt0, &vac0))) {
+ (vp0 && inaddrcmp(&vt0, &vac0)) ||
+ (tp0 && inaddrcmp(&tt0, &tac0))) {
if (option_debug > 1) {
ast_log(LOG_DEBUG, "Oooh, '%s' changed end address to %s:%d (format %d)\n",
c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port), codec0);
ast_log(LOG_DEBUG, "Oooh, '%s' was %s:%d/(format %d)\n",
c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port), oldcodec0);
}
- if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))
+ if (pr1->set_rtp_peer(c1, t0.sin_addr.s_addr ? p0 : NULL, vt0.sin_addr.s_addr ? vp0 : NULL, tt0.sin_addr.s_addr ? tp0 : NULL, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE)))
ast_log(LOG_WARNING, "Channel '%s' failed to update to '%s'\n", c1->name, c0->name);
memcpy(&ac0, &t0, sizeof(ac0));
memcpy(&vac0, &vt0, sizeof(vac0));
+ memcpy(&tac0, &tt0, sizeof(tac0));
oldcodec0 = codec0;
}
@@ -2941,10 +2992,10 @@ static enum ast_bridge_result bridge_native_loop(struct ast_channel *c0, struct
if (option_debug)
ast_log(LOG_DEBUG, "Oooh, got a %s\n", fr ? "digit" : "hangup");
if (c0->tech_pvt == pvt0)
- if (pr0->set_rtp_peer(c0, NULL, NULL, 0, 0))
+ if (pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0))
ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c0->name);
if (c1->tech_pvt == pvt1)
- if (pr1->set_rtp_peer(c1, NULL, NULL, 0, 0))
+ if (pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0))
ast_log(LOG_WARNING, "Channel '%s' failed to break RTP bridge\n", c1->name);
return AST_BRIDGE_COMPLETE;
} else if ((fr->frametype == AST_FRAME_CONTROL) && !(flags & AST_BRIDGE_IGNORE_SIGS)) {
@@ -2954,15 +3005,15 @@ static enum ast_bridge_result bridge_native_loop(struct ast_channel *c0, struct
if (fr->subclass == AST_CONTROL_HOLD) {
/* If we someone went on hold we want the other side to reinvite back to us */
if (who == c0)
- pr1->set_rtp_peer(c1, NULL, NULL, 0, 0);
+ pr1->set_rtp_peer(c1, NULL, NULL, NULL, 0, 0);
else
- pr0->set_rtp_peer(c0, NULL, NULL, 0, 0);
+ pr0->set_rtp_peer(c0, NULL, NULL, NULL, 0, 0);
} else if (fr->subclass == AST_CONTROL_UNHOLD) {
/* If they went off hold they should go back to being direct */
if (who == c0)
- pr1->set_rtp_peer(c1, p0, vp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE));
+ pr1->set_rtp_peer(c1, p0, vp0, tp0, codec0, ast_test_flag(p0, FLAG_NAT_ACTIVE));
else
- pr0->set_rtp_peer(c0, p1, vp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE));
+ pr0->set_rtp_peer(c0, p1, vp1, tp1, codec1, ast_test_flag(p1, FLAG_NAT_ACTIVE));
}
ast_indicate_data(other, fr->subclass, fr->data, fr->datalen);
ast_frfree(fr);
@@ -3260,9 +3311,10 @@ enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel
{
struct ast_rtp *p0 = NULL, *p1 = NULL; /* Audio RTP Channels */
struct ast_rtp *vp0 = NULL, *vp1 = NULL; /* Video RTP channels */
+ struct ast_rtp *tp0 = NULL, *tp1 = NULL; /* Text RTP channels */
struct ast_rtp_protocol *pr0 = NULL, *pr1 = NULL;
- enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED;
- enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED;
+ enum ast_rtp_get_result audio_p0_res = AST_RTP_GET_FAILED, video_p0_res = AST_RTP_GET_FAILED, text_p0_res = AST_RTP_GET_FAILED;
+ enum ast_rtp_get_result audio_p1_res = AST_RTP_GET_FAILED, video_p1_res = AST_RTP_GET_FAILED, text_p1_res = AST_RTP_GET_FAILED;
enum ast_bridge_result res = AST_BRIDGE_FAILED;
int codec0 = 0, codec1 = 0;
void *pvt0 = NULL, *pvt1 = NULL;
@@ -3296,8 +3348,10 @@ enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel
/* Get audio and video interface (if native bridge is possible) */
audio_p0_res = pr0->get_rtp_info(c0, &p0);
video_p0_res = pr0->get_vrtp_info ? pr0->get_vrtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
+ text_p0_res = pr0->get_trtp_info ? pr0->get_trtp_info(c0, &vp0) : AST_RTP_GET_FAILED;
audio_p1_res = pr1->get_rtp_info(c1, &p1);
video_p1_res = pr1->get_vrtp_info ? pr1->get_vrtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
+ text_p1_res = pr1->get_trtp_info ? pr1->get_trtp_info(c1, &vp1) : AST_RTP_GET_FAILED;
/* If we are carrying video, and both sides are not reinviting... then fail the native bridge */
if (video_p0_res != AST_RTP_GET_FAILED && (audio_p0_res != AST_RTP_TRY_NATIVE || video_p0_res != AST_RTP_TRY_NATIVE))
@@ -3384,7 +3438,7 @@ enum ast_bridge_result ast_rtp_bridge(struct ast_channel *c0, struct ast_channel
} else {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
- res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
+ res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, tp0, tp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
}
return res;