[asterisk-commits] oej: branch oej/videocaps r47884 - in
/team/oej/videocaps: apps/ channels/ co...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Tue Nov 21 07:15:40 MST 2006
Author: oej
Date: Tue Nov 21 08:15:40 2006
New Revision: 47884
URL: http://svn.digium.com/view/asterisk?view=rev&rev=47884
Log:
This branch includes a lot of different pieces of code by John Martin, Aupix.
- Video capabilities handling
- T.140 text support in RTP (realtime text)
- Fast update requests in rtcp or xml
The patches outside of videocaps will be moved out and separated at a later stage,
but right now we need to import all and automerge it up to current trunk
Modified:
team/oej/videocaps/apps/app_dial.c
team/oej/videocaps/apps/app_queue.c
team/oej/videocaps/channels/chan_agent.c
team/oej/videocaps/channels/chan_gtalk.c
team/oej/videocaps/channels/chan_h323.c
team/oej/videocaps/channels/chan_mgcp.c
team/oej/videocaps/channels/chan_sip.c
team/oej/videocaps/channels/chan_skinny.c
team/oej/videocaps/configs/sip.conf.sample
team/oej/videocaps/formats/format_h263.c
team/oej/videocaps/include/asterisk/channel.h
team/oej/videocaps/include/asterisk/frame.h
team/oej/videocaps/include/asterisk/rtp.h
team/oej/videocaps/main/channel.c
team/oej/videocaps/main/cli.c
team/oej/videocaps/main/frame.c
team/oej/videocaps/main/rtp.c
Modified: team/oej/videocaps/apps/app_dial.c
URL: http://svn.digium.com/view/asterisk/team/oej/videocaps/apps/app_dial.c?view=diff&rev=47884&r1=47883&r2=47884
==============================================================================
--- team/oej/videocaps/apps/app_dial.c (original)
+++ team/oej/videocaps/apps/app_dial.c Tue Nov 21 08:15:40 2006
@@ -456,8 +456,10 @@
c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
if (!c)
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
- else
+ else {
ast_channel_inherit_variables(in, o->chan);
+ ast_set_capabilities(o->chan, &in->channelcaps);
+ }
}
} else {
if (option_verbose > 2)
@@ -699,6 +701,10 @@
case AST_CONTROL_FLASH:
/* Ignore going off hook and flash */
break;
+ case AST_CONTROL_CAPABILITY:
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "Call on %s is indicating caps %d\n", o->chan->name, f->datalen);
+ ast_indicate_data(in, AST_CONTROL_CAPABILITY, f->data, f->datalen);
case -1:
if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_MUSICBACK)) {
if (option_verbose > 2)
@@ -709,7 +715,8 @@
break;
default:
if (option_debug)
- ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
+ ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
+ ast_verbose("Dunno what to do with control type %d\n", f->subclass);
}
} else if (single) {
/* XXX are we sure the logic is correct ? or we should just switch on f->frametype ? */
@@ -785,6 +792,7 @@
if (single && (f->frametype == AST_FRAME_CONTROL) &&
((f->subclass == AST_CONTROL_HOLD) ||
(f->subclass == AST_CONTROL_UNHOLD) ||
+ (f->subclass == AST_CONTROL_CAPABILITY) ||
(f->subclass == AST_CONTROL_VIDUPDATE))) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
@@ -1287,6 +1295,7 @@
chan->hangupcause = cause;
continue;
}
+ ast_set_capabilities(tmp->chan, &chan->channelcaps);
pbx_builtin_setvar_helper(tmp->chan, "DIALEDPEERNUMBER", numsubst);
if (!ast_strlen_zero(tmp->chan->call_forward)) {
char tmpchan[256];
@@ -1317,8 +1326,10 @@
}
if (!tmp->chan)
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
- else
+ else {
ast_channel_inherit_variables(chan, tmp->chan);
+ ast_set_capabilities(tmp->chan, &chan->channelcaps);
+ }
} else {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tmp->chan->name);
Modified: team/oej/videocaps/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/team/oej/videocaps/apps/app_queue.c?view=diff&rev=47884&r1=47883&r2=47884
==============================================================================
--- team/oej/videocaps/apps/app_queue.c (original)
+++ team/oej/videocaps/apps/app_queue.c Tue Nov 21 08:15:40 2006
@@ -1686,6 +1686,7 @@
tmp->chan->adsicpe = qe->chan->adsicpe;
/* Place the call, but don't wait on the answer */
+ pbx_builtin_setvar_helper(tmp->chan, "MEMBERNAME", tmp->member->membername);
if ((res = ast_call(tmp->chan, location, 0))) {
/* Again, keep going even if there's an error */
if (option_debug)
@@ -2005,6 +2006,7 @@
if (o->chan->cid.cid_rdnis)
free(o->chan->cid.cid_rdnis);
o->chan->cid.cid_rdnis = ast_strdup(S_OR(in->macroexten, in->exten));
+ pbx_builtin_setvar_helper(o->chan, "MEMBERNAME", o->member->membername);
if (ast_call(o->chan, tmpchan, 0)) {
ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
do_hang(o);
Modified: team/oej/videocaps/channels/chan_agent.c
URL: http://svn.digium.com/view/asterisk/team/oej/videocaps/channels/chan_agent.c?view=diff&rev=47884&r1=47883&r2=47884
==============================================================================
--- team/oej/videocaps/channels/chan_agent.c (original)
+++ team/oej/videocaps/channels/chan_agent.c Tue Nov 21 08:15:40 2006
@@ -450,9 +450,9 @@
status = pbx_builtin_getvar_helper(p->chan, "CHANLOCALSTATUS");
if (autologoffunavail && status && !strcasecmp(status, "CHANUNAVAIL")) {
long logintime = time(NULL) - p->loginstart;
- p->loginstart = 0;
ast_log(LOG_NOTICE, "Agent read: '%s' is not available now, auto logoff\n", p->name);
agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Chanunavail");
+ p->loginstart = 0;
}
ast_hangup(p->chan);
if (p->wrapuptime && p->acknowledged)
@@ -755,9 +755,9 @@
status = pbx_builtin_getvar_helper(p->chan, "CHANLOCALSTATUS");
if (autologoffunavail && status && !strcasecmp(status, "CHANUNAVAIL")) {
long logintime = time(NULL) - p->loginstart;
- p->loginstart = 0;
ast_log(LOG_NOTICE, "Agent hangup: '%s' is not available now, auto logoff\n", p->name);
agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Chanunavail");
+ p->loginstart = 0;
}
/* Recognize the hangup and pass it along immediately */
ast_hangup(p->chan);
@@ -767,9 +767,9 @@
ast_log(LOG_DEBUG, "Hungup, howlong is %d, autologoff is %d\n", howlong, p->autologoff);
if (howlong && p->autologoff && (howlong > p->autologoff)) {
long logintime = time(NULL) - p->loginstart;
- p->loginstart = 0;
ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong);
agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Autologoff");
+ p->loginstart = 0;
}
} else if (p->dead) {
ast_channel_lock(p->chan);
@@ -1464,6 +1464,7 @@
{
char *tmp = NULL;
char agent[AST_MAX_AGENT];
+ char temp_time[32];
if (!ast_strlen_zero(logcommand))
tmp = logcommand;
@@ -1489,7 +1490,9 @@
p->agent, tmp, loginchan, logintime);
}
- ast_queue_log("NONE", ast_strlen_zero(uniqueid) ? "NONE" : uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|%s", loginchan, logintime, tmp);
+ snprintf(temp_time, sizeof(temp_time), "%ld.0", (long)p->loginstart);
+ ast_verbose("Logging off with time of %s\n", temp_time);
+ ast_queue_log("NONE", temp_time, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|%s", loginchan, logintime, tmp);
set_agentbycallerid(p->logincallerid, NULL);
p->loginchan[0] ='\0';
p->logincallerid[0] = '\0';
@@ -1515,8 +1518,8 @@
}
ret = 0; /* found an agent => return 0 */
logintime = time(NULL) - p->loginstart;
+ agent_logoff_maintenance(p, p->loginchan, logintime, NULL, "CommandLogoff");
p->loginstart = 0;
- agent_logoff_maintenance(p, p->loginchan, logintime, NULL, "CommandLogoff");
break;
}
}
@@ -1687,7 +1690,10 @@
agent_status = 1;
online_agents++;
} else if (!ast_strlen_zero(p->loginchan)) {
- snprintf(location, sizeof(location) - 20, "available at '%s'", p->loginchan);
+ if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0 || !(p->lastdisc.tv_sec))
+ snprintf(location, sizeof(location) - 20, "available at '%s'", p->loginchan);
+ else
+ snprintf(location, sizeof(location) - 20, "wrapping up at '%s'", p->loginchan);
talkingto[0] = '\0';
agent_status = 1;
online_agents++;
@@ -1710,7 +1716,73 @@
return RESULT_SUCCESS;
}
-
+static int agent_show(int fd, int argc, char **argv)
+{
+ struct agent_pvt *p;
+ struct tm tm;
+ char dateformat[256] = "%b %e %T"; /* Original Asterisk Format */
+ char date[256];
+ int seconds;
+
+ if (argc != 3)
+ return RESULT_SHOWUSAGE;
+
+ if (!argv[2])
+ return RESULT_FAILURE;
+
+ AST_LIST_LOCK(&agents);
+ AST_LIST_TRAVERSE(&agents, p, list) {
+ /* Look for either the agent ID or... */
+ if (!strncasecmp(p->agent, argv[2], strlen(p->agent)))
+ break;
+ /* ... the agent name */
+ if (!strncasecmp(p->name, argv[2], strlen(p->name)))
+ break;
+ }
+ AST_LIST_UNLOCK(&agents);
+
+ if (!p) {
+ ast_verbose("Couldn't find agent %s\n", argv[2]);
+ return RESULT_FAILURE;
+ }
+
+ ast_cli(fd, "Lock: %08x\n",(unsigned int)&p->lock);
+ ast_cli(fd, "AgentID: %s\n", p->agent);
+ ast_cli(fd, "Password: %s\n", p->password);
+ ast_cli(fd, "AgentName: %s\n", p->name);
+
+ localtime_r(&p->loginstart, &tm);
+ strftime(date, sizeof(date), dateformat, &tm);
+ ast_cli(fd, "LoggedInAt: %s\n", p->loginstart ? date : "Not Logged In");
+
+ ast_cli(fd, "Dead: %d\n", p->dead);
+ ast_cli(fd, "Pending: %d\n", p->pending);
+ ast_cli(fd, "AboutToGrab: %d\n", p->abouttograb);
+ ast_cli(fd, "AutoLogoff: %d seconds\n", p->autologoff);
+ ast_cli(fd, "AckCall: %d\n", p->ackcall);
+
+ localtime_r(&p->start, &tm);
+ strftime(date, sizeof(date), dateformat, &tm);
+ ast_cli(fd, "Start: %s\n", p->start ? date : "Not in a call");
+ ast_cli(fd, "In a call for: %ld seconds\n", p->start ? time(NULL) - p->start : 0);
+
+ seconds = (p->lastdisc.tv_sec !=0) ? ast_tvdiff_ms(p->lastdisc, ast_tvnow())/1000 : 0;
+ ast_cli(fd, "Available In: %d\n", seconds > 0 ? seconds : 0);
+ ast_cli(fd, "WrapupTime: %d seconds\n", p->wrapuptime/1000);
+ //ast_group_t group
+ ast_cli(fd, "Group: %08x\n", (unsigned int)p->group);
+ ast_cli(fd, "Acknowledged: %d\n", p->acknowledged);
+ ast_cli(fd, "MOH: %s\n", p->moh);
+ ast_cli(fd, "App_Lock: %08x\n", (unsigned int)&p->app_lock);
+ //volatile pthread_t owning_app
+ //volatile int app_sleep_cond
+ ast_cli(fd, "Owner's name: %s\n", p->owner ? p->owner->name : "none");
+ ast_cli(fd, "LoginChannel: %s\n", p->loginchan);
+ ast_cli(fd, "LoginCallerID: %s\n", p->logincallerid);
+ //struct ast_channel *chan
+
+ return RESULT_SUCCESS;
+}
static char show_agents_usage[] =
"Usage: agent show\n"
@@ -1719,11 +1791,21 @@
static char show_agents_online_usage[] =
"Usage: agent show online\n"
" Provides a list of all online agents.\n";
+
+static char show_agent_usage[] =
+"Usage: show agent <agentid | agentname>\n"
+" Shows an agent's internals when given agentid or agentname.\n"
+" show agent 2000\n"
+" show agent \"John Smith\"\n";
static char agent_logoff_usage[] =
"Usage: agent logoff <channel> [soft]\n"
" Sets an agent as no longer logged in.\n"
" If 'soft' is specified, do not hangup existing calls.\n";
+
+static struct ast_cli_entry cli_show_agent = {
+ { "show", "agent", NULL }, agent_show,
+ "Show agent internals", show_agent_usage, NULL };
static struct ast_cli_entry cli_agents[] = {
{ { "agent", "show", NULL },
@@ -2000,9 +2082,8 @@
dump_agents();
} else {
logintime = time(NULL) - p->loginstart;
+ agent_logoff_maintenance(p, last_loginchan, logintime, chan->uniqueid, NULL);
p->loginstart = 0;
-
- agent_logoff_maintenance(p, last_loginchan, logintime, chan->uniqueid, NULL);
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged out\n", p->agent);
}
@@ -2480,6 +2561,7 @@
ast_manager_register2("AgentLogoff", EVENT_FLAG_AGENT, action_agent_logoff, "Sets an agent as no longer logged in", mandescr_agent_logoff);
/* CLI Commands */
+ ast_cli_register(&cli_show_agent);
ast_cli_register_multiple(cli_agents, sizeof(cli_agents) / sizeof(struct ast_cli_entry));
/* Dialplan Functions */
@@ -2504,6 +2586,7 @@
/* Unregister dialplan functions */
ast_custom_function_unregister(&agent_function);
/* Unregister CLI commands */
+ ast_cli_unregister(&cli_show_agent);
ast_cli_unregister_multiple(cli_agents, sizeof(cli_agents) / sizeof(struct ast_cli_entry));
/* Unregister dialplan applications */
ast_unregister_application(app);
Modified: team/oej/videocaps/channels/chan_gtalk.c
URL: http://svn.digium.com/view/asterisk/team/oej/videocaps/channels/chan_gtalk.c?view=diff&rev=47884&r1=47883&r2=47884
==============================================================================
--- team/oej/videocaps/channels/chan_gtalk.c (original)
+++ team/oej/videocaps/channels/chan_gtalk.c Tue Nov 21 08:15:40 2006
@@ -186,7 +186,7 @@
static int gtalk_show_channels(int fd, int argc, char **argv);
/*----- RTP interface functions */
static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp,
- struct ast_rtp *vrtp, int codecs, int nat_active);
+ struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active);
static enum ast_rtp_get_result gtalk_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
static int gtalk_get_codec(struct ast_channel *chan);
@@ -538,7 +538,7 @@
return p->peercapability;
}
-static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
+static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
{
struct gtalk_pvt *p;
Modified: team/oej/videocaps/channels/chan_h323.c
URL: http://svn.digium.com/view/asterisk/team/oej/videocaps/channels/chan_h323.c?view=diff&rev=47884&r1=47883&r2=47884
==============================================================================
--- team/oej/videocaps/channels/chan_h323.c (original)
+++ team/oej/videocaps/channels/chan_h323.c Tue Nov 21 08:15:40 2006
@@ -1915,6 +1915,7 @@
return info;
}
+#if 0
/**
* Definition taken from rtp.c for rtpPayloadType because we need it here.
*/
@@ -1922,6 +1923,7 @@
int isAstFormat; /* whether the following code is an AST_FORMAT */
int code;
};
+#endif
/**
* Call-back function passing remote ip/port information from H.323 to asterisk
Modified: team/oej/videocaps/channels/chan_mgcp.c
URL: http://svn.digium.com/view/asterisk/team/oej/videocaps/channels/chan_mgcp.c?view=diff&rev=47884&r1=47883&r2=47884
==============================================================================
--- team/oej/videocaps/channels/chan_mgcp.c (original)
+++ team/oej/videocaps/channels/chan_mgcp.c Tue Nov 21 08:15:40 2006
@@ -3959,7 +3959,7 @@
return AST_RTP_TRY_PARTIAL;
}
-static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
+static int mgcp_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
{
/* XXX Is there such thing as video support with MGCP? XXX */
struct mgcp_subchannel *sub;
Modified: team/oej/videocaps/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/oej/videocaps/channels/chan_sip.c?view=diff&rev=47884&r1=47883&r2=47884
==============================================================================
--- team/oej/videocaps/channels/chan_sip.c (original)
+++ team/oej/videocaps/channels/chan_sip.c Tue Nov 21 08:15:40 2006
@@ -152,7 +152,6 @@
#define TRUE 1
#endif
-#define VIDEO_CODEC_MASK 0x1fc0000 /*!< Video codecs from H.261 thru AST_FORMAT_MAX_VIDEO */
#ifndef IPTOS_MINCOST
#define IPTOS_MINCOST 0x02
#endif
@@ -497,6 +496,7 @@
#define DEFAULT_TOS_SIP 0 /*!< Call signalling packets should be marked as DSCP CS3, but the default is 0 to be compatible with previous versions. */
#define DEFAULT_TOS_AUDIO 0 /*!< Audio packets should be marked as DSCP EF (Expedited Forwarding), but the default is 0 to be compatible with previous versions. */
#define DEFAULT_TOS_VIDEO 0 /*!< Video packets should be marked as DSCP AF41, but the default is 0 to be compatible with previous versions. */
+#define DEFAULT_TOS_TEXT 0 /*!< Text packets should be marked as XXXX XXXX, but the default is 0 to be compatible with previous versions. */
#define DEFAULT_ALLOW_EXT_DOM TRUE
#define DEFAULT_REALM "asterisk"
#define DEFAULT_NOTIFYRINGING TRUE
@@ -504,11 +504,20 @@
#define DEFAULT_AUTOCREATEPEER FALSE
#define DEFAULT_QUALIFY FALSE
#define DEFAULT_T1MIN 100 /*!< 100 MS for minimal roundtrip time */
-#define DEFAULT_MAX_CALL_BITRATE (384) /*!< Max bitrate for video */
+#define DEFAULT_MAX_FRAMERATE (30)
+#define VIDEO_UPDATE_XML 1
+#define VIDEO_UPDATE_RTCP 2
+#define DEFAULT_VIDEO_UPDATE (VIDEO_UPDATE_XML)
#ifndef DEFAULT_USERAGENT
#define DEFAULT_USERAGENT "Asterisk PBX" /*!< Default Useragent: header unless re-defined in sip.conf */
#endif
+static int global_videoupdate = DEFAULT_VIDEO_UPDATE;
+/* We set default caps but make them invalid.
+ If a rtpmap comes in the we set valid.
+ If a fmtp comes in then we overwrite with new values.
+ */
+static struct ast_capabilities global_caps;
/* Default setttings are used as a channel setting and as a default when
configuring devices */
@@ -523,7 +532,6 @@
static char default_mohinterpret[MAX_MUSICCLASS]; /*!< Global setting for moh class to use when put on hold */
static char default_mohsuggest[MAX_MUSICCLASS]; /*!< Global setting for moh class to suggest when putting
* a bridged channel on hold */
-static int default_maxcallbitrate; /*!< Maximum bitrate for call */
static struct ast_codec_pref default_prefs; /*!< Default codec prefs */
/* Global settings only apply to the channel */
@@ -549,6 +557,7 @@
static unsigned int global_tos_sip; /*!< IP type of service for SIP packets */
static unsigned int global_tos_audio; /*!< IP type of service for audio RTP packets */
static unsigned int global_tos_video; /*!< IP type of service for video RTP packets */
+static unsigned int global_tos_text; /*!< IP type of service for text RTP packets */
static int compactheaders; /*!< send compact sip headers */
static int recordhistory; /*!< Record SIP history. Off by default */
static int dumphistory; /*!< Dump history to verbose before destroying SIP dialog */
@@ -779,9 +788,13 @@
#define SIP_PAGE2_CALL_ONHOLD_ONEDIR (1 << 23) /*!< 23: One directional hold */
#define SIP_PAGE2_CALL_ONHOLD_INACTIVE (1 << 24) /*!< 24: Inactive */
#define SIP_PAGE2_RFC2833_COMPENSATE (1 << 25)
+#define SIP_PAGE2_DEBUG_CAPS (1 << 27) /*!< 27: Debug Caps */
+#define SIP_PAGE2_NOTEXT (1 << 28) /*!< 28: Text not supported */
+#define SIP_PAGE2_TEXTSUPPORT (1 << 29) /*!< 29: Global text enable */
+#define SIP_PAGE2_DEBUG_TEXT (1 << 30) /*!< 30: Global text debug */
#define SIP_PAGE2_FLAGS_TO_COPY \
- (SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE)
+ (SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | SIP_PAGE2_T38SUPPORT | SIP_PAGE2_RFC2833_COMPENSATE | SIP_PAGE2_TEXTSUPPORT)
/* SIP packet flags */
#define SIP_PKT_DEBUG (1 << 0) /*!< Debug this packet */
@@ -817,6 +830,8 @@
#define sipdebug ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG)
#define sipdebug_config ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG_CONFIG)
#define sipdebug_console ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG_CONSOLE)
+#define sipdebug_caps ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG_CAPS)
+#define sipdebug_text ast_test_flag(&global_flags[1], SIP_PAGE2_DEBUG_TEXT)
/*! \brief T38 States for a call */
enum t38state {
@@ -941,10 +956,13 @@
int capability; /*!< Special capability (codec) */
int jointcapability; /*!< Supported capability at both ends (codecs) */
int peercapability; /*!< Supported peer capability */
+ int videoupdate; /*!< Defines which FU mechanism RTCP or INFO is used */
+ struct ast_capabilities caps; /*!< Supported video capapbilities for this peer/user */
+ struct ast_capabilities jointcaps; /*!< Supported video capapbilities at both ends */
+ struct ast_capabilities peercaps; /*!< Video capapbilities taken from the sdp */
int prefcodec; /*!< Preferred codec (outbound only) */
int noncodeccapability; /*!< DTMF RFC2833 telephony-event */
int redircodecs; /*!< Redirect codecs */
- int maxcallbitrate; /*!< Maximum Call Bitrate for Video Calls */
struct t38properties t38; /*!< T38 settings */
struct sockaddr_in udptlredirip; /*!< Where our T.38 UDPTL should be going if not to us */
struct ast_udptl *udptl; /*!< T.38 UDPTL session */
@@ -958,6 +976,7 @@
struct sockaddr_in sa; /*!< Our peer */
struct sockaddr_in redirip; /*!< Where our RTP should be going if not to us */
struct sockaddr_in vredirip; /*!< Where our Video RTP should be going if not to us */
+ struct sockaddr_in tredirip; /*!< Where our Text RTP should be going if not to us */
time_t lastrtprx; /*!< Last RTP received */
time_t lastrtptx; /*!< Last RTP sent */
int rtptimeout; /*!< RTP timeout time */
@@ -994,6 +1013,7 @@
struct sip_registry *registry; /*!< If this is a REGISTER dialog, to which registry */
struct ast_rtp *rtp; /*!< RTP Session */
struct ast_rtp *vrtp; /*!< Video RTP session */
+ struct ast_rtp *trtp; /*!< Text RTP session */
struct sip_pkt *packets; /*!< Packets scheduled for re-transmission */
struct sip_history_head *history; /*!< History of this SIP dialog */
struct ast_variable *chanvars; /*!< Channel variables to set for inbound call */
@@ -1061,13 +1081,14 @@
struct ast_flags flags[2]; /*!< SIP_ flags */
int amaflags; /*!< AMA flags for billing */
int callingpres; /*!< Calling id presentation */
+ struct ast_capabilities caps; /*!< User capability */
int capability; /*!< Codec capability */
int inUse; /*!< Number of calls in use */
int call_limit; /*!< Limit of concurrent calls */
enum transfermodes allowtransfer; /*! SIP Refer restriction scheme */
struct ast_ha *ha; /*!< ACL setting */
struct ast_variable *chanvars; /*!< Variables to set for channel created by user */
- int maxcallbitrate; /*!< Maximum Bitrate for a video call */
+ int videoupdate /*!< Defines use of XML or RTCP for video update */;
int autoframing;
};
@@ -1110,6 +1131,7 @@
struct ast_flags flags[2]; /*!< SIP_ flags */
int expire; /*!< When to expire this peer registration */
int capability; /*!< Codec capability */
+ struct ast_capabilities caps; /*!< Codec capability */
int rtptimeout; /*!< RTP timeout */
int rtpholdtimeout; /*!< RTP Hold Timeout */
int rtpkeepalive; /*!< Send RTP packets for keepalive */
@@ -1117,7 +1139,7 @@
ast_group_t pickupgroup; /*!< Pickup group */
struct ast_dnsmgr_entry *dnsmgr;/*!< DNS refresh manager for peer */
struct sockaddr_in addr; /*!< IP address of peer */
- int maxcallbitrate; /*!< Maximum Bitrate for a video call */
+ int videoupdate /*!< Defines use of XML or RTCP for video update */;
/* Qualification */
struct sip_pvt *call; /*!< Call pointer */
@@ -1225,6 +1247,7 @@
static int sip_answer(struct ast_channel *ast);
static struct ast_frame *sip_read(struct ast_channel *ast);
static int sip_write(struct ast_channel *ast, struct ast_frame *frame);
+static int sip_set_capabilities(struct ast_channel *ast, struct ast_capabilities *chancaps);
static int sip_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
static int sip_transfer(struct ast_channel *ast, const char *dest);
static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
@@ -1298,7 +1321,11 @@
static const char* get_sdp_iterate(int* start, struct sip_request *req, const char *name);
static const char *get_sdp(struct sip_request *req, const char *name);
static int find_sdp(struct sip_request *req);
+static int process_h2613_fmtp(const char *fmtstr, struct ast_h2613_video_cap *vidcap, unsigned int framerate);
+static int process_h264_fmtp(const char *fmtstr, struct ast_h264_video_cap *vidcap, int framerate);
static int process_sdp(struct sip_pvt *p, struct sip_request *req);
+static void ast_build_h2613_fmtp(char **buf, size_t *size, int rtp_code, struct ast_h2613_video_cap *video_cap);
+static void ast_build_h264_fmtp(char **buf, size_t *size, int rtp_code, struct ast_h264_video_cap *video_cap);
static void add_codec_to_sdp(const struct sip_pvt *p, int codec, int sample_rate,
char **m_buf, size_t *m_size, char **a_buf, size_t *a_size,
int debug, int *min_packet_size);
@@ -1537,9 +1564,10 @@
static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno);
/*----- RTP interface functions */
-static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active);
+static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active);
static enum ast_rtp_get_result sip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
static enum ast_rtp_get_result sip_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
+static enum ast_rtp_get_result sip_get_trtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
static int sip_get_codec(struct ast_channel *chan);
static struct ast_frame *sip_rtp_read(struct ast_channel *ast, struct sip_pvt *p, int *faxdetect);
@@ -1563,6 +1591,7 @@
.read = sip_read,
.write = sip_write,
.write_video = sip_write,
+ .write_text = sip_write,
.indicate = sip_indicate,
.transfer = sip_transfer,
.fixup = sip_fixup,
@@ -1571,6 +1600,7 @@
.bridge = ast_rtp_bridge,
.early_bridge = ast_rtp_early_bridge,
.send_text = sip_sendtext,
+ .set_capabilities = sip_set_capabilities,
};
/**--- some list management macros. **/
@@ -1587,6 +1617,7 @@
type: "SIP",
get_rtp_info: sip_get_rtp_peer,
get_vrtp_info: sip_get_vrtp_peer,
+ get_trtp_info: sip_get_trtp_peer,
set_rtp_peer: sip_set_rtp_peer,
get_codec: sip_get_codec,
};
@@ -2679,6 +2710,11 @@
ast_log(LOG_DEBUG, "Setting NAT on UDPTL to %s\n", mode);
ast_udptl_setnat(p->udptl, natflags);
}
+ if (p->trtp) {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Setting NAT on TRTP to %s\n", mode);
+ ast_rtp_setnat(p->trtp, natflags);
+ }
}
/*! \brief Create address structure from peer reference.
@@ -2699,6 +2735,10 @@
if ((!ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) || !(dialog->capability & AST_FORMAT_VIDEO_MASK)) && dialog->vrtp) {
ast_rtp_destroy(dialog->vrtp);
dialog->vrtp = NULL;
+ }
+ if (!ast_test_flag(&dialog->flags[1], SIP_PAGE2_TEXTSUPPORT) && dialog->trtp) {
+ ast_rtp_destroy(dialog->trtp);
+ dialog->trtp = NULL;
}
dialog->prefs = peer->prefs;
if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_T38SUPPORT)) {
@@ -2728,6 +2768,10 @@
if (dialog->vrtp) {
ast_rtp_setdtmf(dialog->vrtp, 0);
ast_rtp_setdtmfcompensate(dialog->vrtp, 0);
+ }
+ if (dialog->trtp) {
+ ast_rtp_setdtmf(dialog->trtp, 0);
+ ast_rtp_setdtmfcompensate(dialog->trtp, 0);
}
/* Set Frame packetization */
@@ -2775,8 +2819,9 @@
dialog->rtpholdtimeout = peer->rtpholdtimeout;
dialog->rtpkeepalive = peer->rtpkeepalive;
if (peer->call_limit)
- ast_set_flag(&dialog->flags[0], SIP_CALL_LIMIT);
- dialog->maxcallbitrate = peer->maxcallbitrate;
+ ast_set_flag(&dialog->flags[0], SIP_CALL_LIMIT);
+ ast_copy_capabilities(&dialog->caps, &peer->caps);
+ dialog->videoupdate = peer->videoupdate;
return 0;
}
@@ -2864,6 +2909,9 @@
struct ast_var_t *current;
const char *referer = NULL; /* SIP refererer */
+ if(sipdebug_caps)
+ ast_verbose("SIPCALL: entering with channel->nativeformats=%08x, p->capability=%08x, p->jointcaps=%08x\n", ast->nativeformats, p->capability, p->jointcapability);
+
p = ast->tech_pvt;
if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
ast_log(LOG_WARNING, "sip_call called on %s, neither down nor reserved\n", ast->name);
@@ -2921,6 +2969,13 @@
return res;
p->callingpres = ast->cid.cid_pres;
+ if(sipdebug_caps)
+ ast_verbose("SIPCALL: channel->nativeformats=%08x, p->capability=%08x, p->jointcaps=%08x\n", ast->nativeformats, p->capability, p->jointcapability);
+ if (ast->channelcaps.maxcallbitrate > 0 && ast->channelcaps.maxcallbitrate < p->caps.maxcallbitrate) {
+ p->caps.maxcallbitrate = ast->channelcaps.maxcallbitrate;
+ if(sipdebug_caps)
+ ast_verbose("SIPCALL: Setting sip_pvt call rate to %d for %s in sip_call()\n", p->caps.maxcallbitrate, p->username);
+ }
p->jointcapability = ast_translate_available_formats(p->capability, p->prefcodec);
/* If there are no audio formats left to offer, punt */
@@ -2997,6 +3052,8 @@
ast_rtp_destroy(p->rtp);
if (p->vrtp)
ast_rtp_destroy(p->vrtp);
+ if (p->trtp)
+ ast_rtp_destroy(p->trtp);
if (p->udptl)
ast_udptl_destroy(p->udptl);
if (p->refer)
@@ -3463,10 +3520,13 @@
if (!p->pendinginvite) {
char *audioqos = "";
char *videoqos = "";
+ char *textqos = "";
if (p->rtp)
audioqos = ast_rtp_get_quality(p->rtp);
if (p->vrtp)
videoqos = ast_rtp_get_quality(p->vrtp);
+ if (p->trtp)
+ textqos = ast_rtp_get_quality(p->trtp);
/* Send a hangup */
transmit_request_with_auth(p, SIP_BYE, 0, XMIT_RELIABLE, 1);
@@ -3476,11 +3536,15 @@
append_history(p, "RTCPaudio", "Quality:%s", audioqos);
if (p->vrtp)
append_history(p, "RTCPvideo", "Quality:%s", videoqos);
+ if (p->trtp)
+ append_history(p, "RTCPtext", "Quality:%s", textqos);
}
if (p->rtp && oldowner)
pbx_builtin_setvar_helper(oldowner, "RTPAUDIOQOS", audioqos);
if (p->vrtp && oldowner)
pbx_builtin_setvar_helper(oldowner, "RTPVIDEOQOS", videoqos);
+ if (p->trtp && oldowner)
+ pbx_builtin_setvar_helper(oldowner, "RTPTEXTQOS", textqos);
} else {
/* Note we will need a BYE when this all settles out
but we can't send one while we have "INVITE" outstanding. */
@@ -3595,6 +3659,23 @@
res = ast_rtp_write(p->vrtp, frame);
}
sip_pvt_unlock(p);
+ }
+ break;
+ case AST_FRAME_TEXT:
+ if (p) {
+ ast_mutex_lock(&p->lock);
+ if (p->trtp) {
+ /* Activate text early media */
+ if ((ast->_state != AST_STATE_UP) &&
+ !ast_test_flag(&p->flags[0], SIP_PROGRESS_SENT) &&
+ !ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
+ transmit_response_with_sdp(p, "183 Session Progress", &p->initreq, XMIT_UNRELIABLE);
+ ast_set_flag(&p->flags[0], SIP_PROGRESS_SENT);
+ }
+ p->lastrtptx = time(NULL);
+ res = ast_rtp_write(p->trtp, frame);
+ }
+ ast_mutex_unlock(&p->lock);
}
break;
case AST_FRAME_IMAGE:
@@ -3623,6 +3704,59 @@
return res;
}
+/*! \brief sip_set_capabilities: called when channel needs to have caps updated from another channel */
+/* When * is making an outgoing call, the confcaps will be set (sip_new has already been called) but
+ jointcaps and peer caps will be zero */
+/* On the REVERSE cap exchange we'll need to do a MIN(joint, chancap); */
+static int sip_set_capabilities(struct ast_channel *ast, struct ast_capabilities *chancaps)
+{
+ struct sip_pvt *p = ast->tech_pvt;
+ int res = 0;
+
+ if(sipdebug_caps)
+ {
+ ast_verbose("Calling sip_set_capabilities for %s\n", ast->name);
+
+ if (chancaps->maxcallbitrate) {
+ ast_verbose("SET_CAPABILITIES: Chancaps (%s)\n",ast->name);
+ ast_dump_caps(chancaps);
+ }
+ if (p->jointcaps.maxcallbitrate) {
+ ast_verbose("SET_CAPABILITIES: Jointcaps (%s)\n",ast->name);
+ ast_dump_caps(&p->jointcaps);
+ }
+ if (p->peercaps.maxcallbitrate) {
+ ast_verbose("SET_CAPABILITIES: Peercaps (%s)\n",ast->name);
+ ast_dump_caps(&p->peercaps);
+ }
+ if (p->caps.maxcallbitrate) {
+ ast_verbose("SET_CAPABILITIES: Caps (%s)\n",ast->name);
+ ast_dump_caps(&p->caps);
+ }
+ }
+
+ /* Jointcaps will be zero on entry for outbound calls */
+ if (ast_are_caps_zero(&p->jointcaps)) {
+ ast_copy_capabilities(&p->jointcaps, chancaps);
+ } else {
+ ast_resolve_capabilities(&p->jointcaps,&p->jointcaps, chancaps, sipdebug_caps);
+ }
+
+ if (chancaps->h264.rtpnum != 99)
+ p->jointcaps.h264.rtpnum = chancaps->h264.rtpnum;
+
+ ast_copy_capabilities(&ast->channelcaps, &p->jointcaps);
+
+ if(sipdebug_caps) {
+ if (p->jointcaps.maxcallbitrate) {
+ ast_verbose("SET_CAPABILITIES: New Jointcaps (%s)\n",ast->name);
+ ast_dump_caps(&p->jointcaps);
+ }
+ }
+
+ return res;
+}
+
/*! \brief sip_fixup: Fix up a channel: If a channel is consumed, this is called.
Basically update any ->owner links */
static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
@@ -3796,10 +3930,26 @@
break;
case AST_CONTROL_VIDUPDATE: /* Request a video frame update */
if (p->vrtp && !ast_test_flag(&p->flags[0], SIP_NOVIDEO)) {
- transmit_info_with_vidupdate(p);
- /* ast_rtcp_send_h261fur(p->vrtp); */
+ /* Can possibly send both! */
+ if ((p->videoupdate & VIDEO_UPDATE_XML) == VIDEO_UPDATE_XML)
+ transmit_info_with_vidupdate(p);
+ if ((p->videoupdate & VIDEO_UPDATE_RTCP) == VIDEO_UPDATE_RTCP)
+ ast_rtcp_send_h261fur(p->vrtp);
+ if (p->videoupdate && sipdebug)
+ ast_verbose("Sending %s FUR to %s\n", (p->videoupdate == 0) ? "none" : (p->videoupdate == VIDEO_UPDATE_XML) ? "XML" : (p->videoupdate == VIDEO_UPDATE_RTCP) ? "RTCP": "XML and RTCP", p->cid_num);
} else
res = -1;
+ break;
+ case AST_CONTROL_CAPABILITY:
+ if (datalen == sizeof(struct ast_capabilities)) {
+ ast_resolve_capabilities(&p->jointcaps, &p->jointcaps, (struct ast_capabilities*)data, sipdebug_caps);
+ p->jointcapability = p->jointcapability | (AST_FORMAT_VIDEO_MASK & ast_get_int_from_capabilities(&p->jointcaps));
+ if(sipdebug_caps) {
+ ast_verbose("SIP INDICATE: We got a new cap of (0x%08x):\n",p->jointcapability);
+ ast_dump_caps(&p->jointcaps);
+ }
+ }
+ res = -1;
break;
case -1:
res = -1;
@@ -3826,7 +3976,11 @@
struct ast_variable *v = NULL;
int fmt;
int what;
+ int video;
+ int text;
int needvideo = 0;
+ int needtext = 0;
+
{
const char *my_name; /* pick a good name */
@@ -3852,16 +4006,40 @@
/* Select our native format based on codec preference until we receive
something from another device to the contrary. */
- if (i->jointcapability) /* The joint capabilities of us and peer */
+ if (i->jointcapability) { /* The joint capabilities of us and peer */
what = i->jointcapability;
- else if (i->capability) /* Our configured capability for this peer */
+ video = i->jointcapability & AST_FORMAT_VIDEO_MASK;
+ text = i->jointcapability & AST_FORMAT_TEXT_MASK;
+ } else if (i->capability) { /* Our configured capability for this peer */
what = i->capability;
- else
+ video = i->capability & AST_FORMAT_VIDEO_MASK;
+ text = i->capability & AST_FORMAT_TEXT_MASK;
+ } else {
what = global_capability; /* Global codec support */
+ video = global_capability & AST_FORMAT_VIDEO_MASK;
+ text = global_capability & AST_FORMAT_TEXT_MASK;
+ }
/* Set the native formats for audio and merge in video */
- tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | (i->jointcapability & AST_FORMAT_VIDEO_MASK);
- if (option_debug > 2) {
+ tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | video | text;
+
+ if (!ast_are_caps_zero(&i->jointcaps)) {
+ if (sipdebug_caps) ast_verbose("SIP NEW: Chancaps(%s) = jointcaps\n",title ? title : i->fromdomain);
+ ast_copy_capabilities(&tmp->channelcaps, &i->jointcaps);
+ } else if (!ast_are_caps_zero(&i->caps)) {
+ if (sipdebug_caps) ast_verbose("SIP NEW: Chancaps(%s) = conf caps\n",title ? title : i->fromdomain);
+ ast_copy_capabilities(&tmp->channelcaps, &i->caps);
+ } else {
+ if (sipdebug_caps) ast_verbose("SIP NEW: Chancaps(%s) = global caps\n",title ? title : i->fromdomain);
+ ast_copy_capabilities(&tmp->channelcaps, &global_caps);
+ }
+
+ if(sipdebug_caps) {
+ ast_verbose("SIP NEW: Chancaps(%s) are now\n", title ? title : i->fromdomain);
+ ast_dump_caps(&tmp->channelcaps);
+ }
+
+ if (sipdebug) {
char buf[BUFSIZ];
ast_log(LOG_DEBUG, "*** Our native formats are %s \n", ast_getformatname_multiple(buf, BUFSIZ, tmp->nativeformats));
ast_log(LOG_DEBUG, "*** Joint capabilities are %s \n", ast_getformatname_multiple(buf, BUFSIZ, i->jointcapability));
@@ -3884,14 +4062,26 @@
else
needvideo = i->jointcapability & AST_FORMAT_VIDEO_MASK; /* Inbound call */
}
-
- if (option_debug > 2) {
+ if (i->trtp) {
+ if (i->prefcodec)
+ needtext = i->prefcodec & AST_FORMAT_TEXT_MASK; /* Outbound call */
+ else
+ needtext = i->jointcapability & AST_FORMAT_TEXT_MASK; /* Inbound call */
+ }
+
+ if (sipdebug_caps) {
if (needvideo)
ast_log(LOG_DEBUG, "This channel can handle video! HOLLYWOOD next!\n");
else
ast_log(LOG_DEBUG, "This channel will not be able to handle video.\n");
}
+ if (sipdebug_caps) {
+ if (needtext)
+ ast_log(LOG_DEBUG, "This channel can handle text! Shakespeare next!\n");
+ else
+ ast_log(LOG_DEBUG, "This channel will not be able to handle text.\n");
+ }
if (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) {
@@ -3907,6 +4097,9 @@
if (needvideo && i->vrtp) {
tmp->fds[2] = ast_rtp_fd(i->vrtp);
tmp->fds[3] = ast_rtcp_fd(i->vrtp);
+ }
+ if (needtext && i->trtp) {
+ tmp->fds[4] = ast_rtp_fd(i->trtp);
}
if (i->udptl) {
tmp->fds[5] = ast_udptl_fd(i->udptl);
@@ -4123,6 +4316,19 @@
case 3:
f = ast_rtcp_read(p->vrtp); /* RTCP Control Channel for video */
break;
+ case 4:
+ f = ast_rtp_read(p->trtp); /* RTP Text */
+ if (sipdebug_text) {
+ int i;
+ unsigned char* arr = f->data;
+ for (i=0; i < f->datalen; i++)
+ ast_verbose("%c", (arr[i] > ' ' && arr[i] < '}') ? arr[i] : '.');
+ ast_verbose(" -> ");
+ for (i=0; i < f->datalen; i++)
+ ast_verbose("%02X ", arr[i]);
+ ast_verbose("\n");
+ }
+ break;
case 5:
f = ast_udptl_read(p->udptl); /* UDPTL for T.38 */
break;
@@ -4140,7 +4346,7 @@
if (f->subclass != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) {
if (option_debug)
ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
- p->owner->nativeformats = (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass;
+ p->owner->nativeformats = (p->owner->nativeformats & (AST_FORMAT_VIDEO_MASK | AST_FORMAT_TEXT_MASK)) | f->subclass;
ast_set_read_format(p->owner, p->owner->readformat);
ast_set_write_format(p->owner, p->owner->writeformat);
}
@@ -4284,11 +4490,15 @@
/* If the global videosupport flag is on, we always create a RTP interface for video */
if (ast_test_flag(&p->flags[1], SIP_PAGE2_VIDEOSUPPORT))
p->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
+ if (ast_test_flag(&p->flags[1], SIP_PAGE2_TEXTSUPPORT))
+ p->trtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT))
[... 2390 lines stripped ...]
More information about the asterisk-commits
mailing list