[svn-commits] oej: branch oej/videocaps-ng2 r99841 - in /team/oej/videocaps-ng2: apps/ chan...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Jan 23 04:57:19 CST 2008


Author: oej
Date: Wed Jan 23 04:57:18 2008
New Revision: 99841

URL: http://svn.digium.com/view/asterisk?view=rev&rev=99841
Log:
Ok, a videocaps branch that compiles - based on an old version of Asterisk trunk.
Let's see if automerge can do a bit of magic here and restore this to latest release
over lunch...

Modified:
    team/oej/videocaps-ng2/apps/app_dial.c
    team/oej/videocaps-ng2/channels/chan_h323.c
    team/oej/videocaps-ng2/channels/chan_sip.c
    team/oej/videocaps-ng2/configs/sip.conf.sample
    team/oej/videocaps-ng2/formats/format_h263.c
    team/oej/videocaps-ng2/include/asterisk/channel.h
    team/oej/videocaps-ng2/include/asterisk/frame.h
    team/oej/videocaps-ng2/include/asterisk/rtp.h
    team/oej/videocaps-ng2/main/channel.c
    team/oej/videocaps-ng2/main/cli.c
    team/oej/videocaps-ng2/main/frame.c
    team/oej/videocaps-ng2/main/rtp.c

Change Statistics:
 0 files changed

Modified: team/oej/videocaps-ng2/apps/app_dial.c
URL: http://svn.digium.com/view/asterisk/team/oej/videocaps-ng2/apps/app_dial.c?view=diff&rev=99841&r1=99840&r2=99841
==============================================================================
--- team/oej/videocaps-ng2/apps/app_dial.c (original)
+++ team/oej/videocaps-ng2/apps/app_dial.c Wed Jan 23 04:57:18 2008
@@ -466,6 +466,7 @@
 				if (single)
 					ast_channel_make_compatible(o->chan, in);
 				ast_channel_inherit_variables(in, o->chan);
+				ast_set_capabilities(o->chan, &in->channelcaps);
 			} else
 				ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
 		}
@@ -709,6 +710,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)
@@ -719,7 +724,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 ? */
@@ -795,6 +801,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);
@@ -1323,6 +1330,7 @@
 			free(tmp);
 			continue;
 		}
+		ast_set_capabilities(tc, &chan->channelcaps);
 		pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", numsubst);
 		if (!ast_strlen_zero(tc->call_forward)) {
 			char tmpchan[256];
@@ -1356,8 +1364,10 @@
 				}
 				if (!tc)
 					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, tc);
+					ast_set_capabilities(tmp->chan, &chan->channelcaps);
+				}
 			} else {
 				if (option_verbose > 2)
 					ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tc->name);

Modified: team/oej/videocaps-ng2/channels/chan_h323.c
URL: http://svn.digium.com/view/asterisk/team/oej/videocaps-ng2/channels/chan_h323.c?view=diff&rev=99841&r1=99840&r2=99841
==============================================================================
--- team/oej/videocaps-ng2/channels/chan_h323.c (original)
+++ team/oej/videocaps-ng2/channels/chan_h323.c Wed Jan 23 04:57:18 2008
@@ -1938,6 +1938,7 @@
 	return info;
 }
 
+#if 0
 /*! \brief
  * Definition taken from rtp.c for rtpPayloadType because we need it here.
  */
@@ -1945,6 +1946,7 @@
 	int isAstFormat;	/* whether the following code is an AST_FORMAT */
 	int code;
 };
+#endif
 
 /*! \brief
   * Call-back function passing remote ip/port information from H.323 to asterisk

Modified: team/oej/videocaps-ng2/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/oej/videocaps-ng2/channels/chan_sip.c?view=diff&rev=99841&r1=99840&r2=99841
==============================================================================
--- team/oej/videocaps-ng2/channels/chan_sip.c (original)
+++ team/oej/videocaps-ng2/channels/chan_sip.c Wed Jan 23 04:57:18 2008
@@ -1,3 +1,5 @@
+/* TIAS support seems half done...
+*/
 /*
  * Asterisk -- An open source telephony toolkit.
  *
@@ -528,11 +530,20 @@
 #define DEFAULT_QUALIFY		FALSE
 #define DEFAULT_REGEXTENONQUALIFY 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 */
@@ -547,7 +558,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 */
@@ -817,6 +827,7 @@
 #define SIP_PAGE2_TEXTSUPPORT		(1 << 28)	/*!< 28: Global text enable */
 #define SIP_PAGE2_DEBUG_TEXT		(1 << 29)	/*!< 29: Global text debug */
 #define SIP_PAGE2_OUTGOING_CALL         (1 << 30)       /*!< 30: Is this an outgoing call? */
+#define SIP_PAGE2_DEBUG_CAPS		(1 << 31)	/*!< 31: Debug Caps  */
 
 #define SIP_PAGE2_FLAGS_TO_COPY \
 	(SIP_PAGE2_ALLOWSUBSCRIBE | SIP_PAGE2_ALLOWOVERLAP | SIP_PAGE2_VIDEOSUPPORT | \
@@ -857,6 +868,7 @@
 #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 */
@@ -982,11 +994,14 @@
 	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 jointnoncodeccapability;            /*!< Joint Non codec capability */
 	int redircodecs;			/*!< Redirect codecs */
-	int maxcallbitrate;			/*!< Maximum Call Bitrate for Video Calls */	
 	struct sip_proxy *outboundproxy;	/*!< Outbound proxy for this dialog */
 	struct t38properties t38;		/*!< T38 settings */
 	struct sockaddr_in udptlredirip;	/*!< Where our T.38 UDPTL should be going if not to us */
@@ -1104,13 +1119,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;
 };
 
@@ -1153,6 +1169,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 */
@@ -1161,7 +1178,7 @@
 	struct sip_proxy *outboundproxy;	/*!< Outbound proxy for this peer */
 	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 */
@@ -1268,6 +1285,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);
@@ -1340,7 +1358,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);
@@ -1611,6 +1633,7 @@
 	.bridge = ast_rtp_bridge,
 	.early_bridge = ast_rtp_early_bridge,
 	.send_text = sip_sendtext,
+	.set_capabilities = sip_set_capabilities,
 	.func_channel_read = acf_channel_read,
 };
 
@@ -3028,8 +3051,9 @@
 	ast_string_field_set(dialog, context, peer->context);
 	dialog->rtptimeout = peer->rtptimeout;
 	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;
 }
@@ -3129,11 +3153,15 @@
 	struct ast_var_t *current;
 	const char *referer = NULL;   /* SIP referrer */	
 
+	
 	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);
 		return -1;
 	}
+
+	if(sipdebug_caps)
+		ast_verbose("SIPCALL: entering with channel->nativeformats=%08x, p->capability=%08x, p->jointcaps=%08x\n", ast->nativeformats, p->capability, p->jointcapability);
 
 	/* Check whether there is vxml_url, distinctive ring variables */
 	headp=&ast->varshead;
@@ -3186,6 +3214,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);
 	p->jointnoncodeccapability = p->noncodeccapability;
 
@@ -3929,6 +3964,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)
@@ -4107,10 +4195,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;
@@ -4185,7 +4289,24 @@
 
 	/* Set the native formats for audio  and merge in video */
 	tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | video | text;
-	if (option_debug > 2) {
+
+	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 && option_debug > 2) {
 		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));
@@ -4208,7 +4329,6 @@
  		else
 			needvideo = i->jointcapability & AST_FORMAT_VIDEO_MASK;	/* Inbound call */
 	}
-
 	if (i->trtp) {
 		if (i->prefcodec)
 			needtext = i->prefcodec & AST_FORMAT_TEXT_MASK;	/* Outbound call */
@@ -4216,13 +4336,26 @@
 			needtext = i->jointcapability & AST_FORMAT_TEXT_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 &&option_debug > 2) {
 		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) {
+		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) {
@@ -4687,7 +4820,8 @@
 		}
 		if (p->udptl)
 			ast_udptl_setqos(p->udptl, global_tos_audio, global_cos_audio);
-		p->maxcallbitrate = default_maxcallbitrate;
+		p->videoupdate = global_videoupdate;
+		ast_copy_capabilities(&p->caps, &global_caps);
 	}
 
 	if (useglobal_nat && sin) {
@@ -4708,6 +4842,7 @@
 	ast_string_field_set(p, mohinterpret, default_mohinterpret);
 	ast_string_field_set(p, mohsuggest, default_mohsuggest);
 	p->capability = global_capability;
+	ast_set_capabilities_from_int(&p->caps, p->capability);
 	p->allowtransfer = global_allowtransfer;
 	if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
 	    (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
@@ -5125,6 +5260,159 @@
 	return 0;
 }
 
+/* Returns bitrate if found else -1 */
+static int process_h2613_fmtp(const char *fmtstr, struct ast_h2613_video_cap *vidcap, unsigned int framerate)
+{
+	char *parse, *loop_str, *equals, *value_str;
+	char *sep = " ;:/,";
+	int len;
+	int i;
+	unsigned int tmp;
+	int found=0;
+	
+	memset(vidcap, 0, sizeof(struct ast_h2613_video_cap));
+	
+	parse = ast_strdupa(fmtstr);
+	/* Get the fmtp: and payload type out of the way */
+	for ((loop_str = strsep(&parse, sep)); loop_str; (loop_str = strsep(&parse, sep)) != NULL) {
+		if((equals = strchr(loop_str, '='))==NULL)
+			return -1;
+		found = 0;
+		len = equals - loop_str;
+		value_str = loop_str+len+1;
+		if (!strncasecmp(loop_str, "maxbr", len)){
+			if(sscanf(value_str, "%d", &tmp))	{
+				found = 1;
+			 	vidcap->maxbr = tmp*100; /* Convert from *100 to *1 */
+				vidcap->valid = 1;
+				/* ast_verbose("MaxBR=%d\n", vidcap->maxbr); */
+			}
+			else
+				ast_verbose("Failed to parse maxbr in process_h261_h261_fmtp()\n");
+		} else if (len == 1 && loop_str[0] >= 'A' && loop_str[0] <= 'Z') { /* this is an annex */
+			vidcap->annexes |= (1 << (loop_str[0] - 'A'));
+			found = 1;
+			ast_verbose("Found annex %c, we now have %08x\n", loop_str[0], vidcap->annexes);
+		}	else {  /* Check video sizes */
+			for (i = 0; i < MAX_VIDEO_SIZES; i++) {
+				if (strlen(videoSizes[i].type) == len && !strncasecmp(loop_str, videoSizes[i].type, len)) {
+					if (sscanf(value_str, "%d", &tmp)){
+						found = 1;
+						vidcap->maxfr[i] = framerate < (30 / tmp) ? framerate : (30 /tmp);
+						vidcap->valid = 1;
+					}
+					/* ast_verbose("%s->FR=%d, len=%d, string=%s\n", videoSizes[i].type, vidcap->maxfr[i], len, loop_str); */
+				}
+			}
+		}
+		if (!found)
+			ast_verbose("Unable to parse %s in fmtp\n", loop_str);
+	}
+	
+	if (vidcap->valid && vidcap->maxbr)
+		return vidcap->maxbr;
+	else
+		return -1;
+}
+
+/* Returns 0 on success else -1 */
+static int process_h264_fmtp(const char *fmtstr, struct ast_h264_video_cap *vidcap, int framerate)
+{
+	char *parse, *loop_str, *equals, *value_str;
+	char *sep = " ;:/,";
+	int len;
+	struct videoSize myVideoSizes[MAX_VIDEO_SIZES];
+	int found=0;
+	int maxbr = 0; 
+	int level_maxbr = 0;
+	int maxmbps = 0;
+	int level_maxmbps = 0;
+	int profile = 0;
+	int level = 0;
+	int constraint = 0;
+	int packetmode = 0;
+	
+	/* "a=fmtp:%d profile-level-id=42800C; packetization-mode=0; max-br=384; max-mbps=7128\r\n" */
+	
+	memcpy(myVideoSizes, videoSizes, sizeof(myVideoSizes));
+	
+	parse = ast_strdupa(fmtstr);
+	
+	/* Get the fmtp: and payload type out of the way */
+	for ((loop_str = strsep(&parse, sep)); loop_str; (loop_str = strsep(&parse, sep)) != NULL) {
+		if (loop_str[0] == '\0') {
+			loop_str++;
+			continue;
+		}
+		if((equals = strchr(loop_str, '='))==NULL)
+			return -1;
+		found = 0;
+		len = equals - loop_str;
+		value_str = loop_str+len+1;
+		/* Now check other parameters than can appear in a video fmtp */
+		if (!strncasecmp(loop_str, "max-br", len)) {
+			if(sscanf(value_str, "%d", &maxbr))
+				found = 1;
+			else
+				ast_verbose("Failed to parse max-br in process_h264_fmtp()\n");
+		} else if (!strncasecmp(loop_str, "max-mbps", len)) {
+			if(sscanf(value_str, "%d", &maxmbps))
+				found = 1;
+			else
+				ast_verbose("Failed to parse max-mbps in process_h264_fmtp()\n");
+		} else if (!strncasecmp(loop_str, "profile-level-id", len)) {
+			if(sscanf(value_str, "%02x%02x%02x", &profile, &constraint, &level))
+				found = 1;
+			else
+				ast_verbose("Failed to parse profile-level-id in process_h264_fmtp()\n");
+		} else if (!strncasecmp(loop_str, "packetization-mode", len)) {
+			if(sscanf(value_str, "%d", &packetmode))
+				found = 1;
+			else
+				ast_verbose("Failed to parse packetization-mode in process_h264_fmtp()\n");
+		}
+		if (!found)
+			ast_verbose("Unable to parse %s in fmtp\n", loop_str);
+	}
+
+	/* Work out picture sizes from supplied level */
+	switch (level) {
+    case level_1   : level_maxbr =   64000; level_maxmbps = 1485; break;
+    case level_1_1 : level_maxbr =   64000; level_maxmbps = 3000; break;
+    case level_1_2 : level_maxbr =  128000; level_maxmbps = 6000; break;
+    case level_1_3 : level_maxbr =  384000; level_maxmbps = 11880; break;
+    case level_2   : level_maxbr =  768000; level_maxmbps = 11880; break;
+    default        : level_maxbr = 2000000; level_maxmbps = 11880; break;
+	}
+	
+	maxbr = maxbr * 1000;
+
+	if (maxbr > level_maxbr)
+		vidcap->maxbr = maxbr;
+	else
+		vidcap->maxbr = level_maxbr;
+	
+	if (maxmbps > level_maxmbps)
+		vidcap->maxmbps = maxmbps;
+	else
+		vidcap->maxmbps = level_maxmbps;
+	
+	vidcap->profile = profile;
+	vidcap->level = level;
+	vidcap->constraint = constraint;
+	vidcap->valid = 1;
+	
+	if (sipdebug_caps)
+		ast_verbose("SIP PROCESS SDP: H264:%02x, L:%02x, C:%02x, BR:%d, MB:%d\n",
+	  	vidcap->profile,
+			vidcap->level,
+			vidcap->constraint,
+			vidcap->maxbr,
+			vidcap->maxmbps);
+	
+	return 0;
+}
+
 /*! \brief Process SIP SDP offer, select formats and activate RTP channels
 	If offer is rejected, we will not change any properties of the call
  	Return 0 on success, a negative value on errors.
@@ -5135,6 +5423,7 @@
 	const char *m;		/* SDP media offer */
 	const char *c;
 	const char *a;
+	const char *b;
 	char host[258];
 	int len = -1;
 	int portno = -1;		/*!< RTP Audio port number */
@@ -5165,12 +5454,15 @@
 	int iterator;
 	int sendonly = -1;
 	int numberofports;
+	int ct, as, tias;
 	struct ast_rtp *newaudiortp, *newvideortp, *newtextrtp;	/* Buffers for codec handling */
 	int newjointcapability;				/* Negotiated capability */
 	int newpeercapability;
 	int newnoncodeccapability;
 	int numberofmediastreams = 0;
 	int debug = sip_debug_test_pvt(p);
+	struct rtpPayloadType payloadType;
+	int framerate = 30;
 		
 	int found_rtpmap_codecs[32];
 	int last_rtpmap_codec=0;
@@ -5215,6 +5507,27 @@
 		return -1;
 	}
 
+	
+	/* Get the b= bandwidths, this should really be performed with a notion of scope at session and media level */
+	iterator = req->sdp_start;
+	ct = as = tias = -1; /* indicates we didn't find one */
+	while ((b = get_sdp_iterate(&iterator, req, "b"))[0] != '\0') {
+		if (sscanf(b,"CT:%d", &ct) == 1) {
+			ct *= 1000;
+			p->peercaps.maxcallbitrate = ct;
+		} else if (sscanf(b,"AS:%d", &as) == 1) {
+			as *= 1000;
+			p->peercaps.maxvideobitrate = as;
+		} else
+			/* OUCH CLEAR THIS UP */
+			if (sscanf(b,"TIAS:%d", &tias) == 1);
+			else
+				ast_verbose("Unable to parse b=%s in process_sdp\n", b);
+	}
+
+	if(sipdebug_caps)	
+		ast_verbose("SIP PROCESS SDP: CT=%d, AS=%d, TIAS=%d\n", ct, as, tias);
+	
 	/* XXX This could block for a long time, and block the main thread! XXX */
 	hp = ast_gethostbyname(host, &audiohp);
 	if (!hp) {
@@ -5231,6 +5544,9 @@
 	if (p->vrtp)
 		ast_rtp_pt_clear(newvideortp);  /* Must be cleared in case no m=video line exists */
  
+	if (p->trtp)
+		ast_rtp_pt_clear(newtextrtp);  /* Must be cleared in case no m=text line exists */
+
 	if (p->trtp)
 		ast_rtp_pt_clear(newtextrtp);  /* Must be cleared in case no m=text line exists */
 
@@ -5372,7 +5688,6 @@
 		}
 	}
 
-		
 	if (p->rtp) {
 		if (portno > 0) {
 			sin.sin_port = htons(portno);
@@ -5421,11 +5736,6 @@
 				if (debug)
 					ast_verbose("Got unsupported a:fmtp in SDP offer \n");
 				breakout = TRUE;
-			} else if (!strncasecmp(a, "framerate:", (size_t) 10)) {
-				/* Video stuff:  Not supported */
-				if (debug)
-					ast_verbose("Got unsupported a:framerate in SDP offer \n");
-				breakout = TRUE;
 			} else if (!strncasecmp(a, "maxprate:", (size_t) 9)) {
 				/* Video stuff:  Not supported */
 				if (debug)
@@ -5451,6 +5761,12 @@
 		}  else if (!strcasecmp(a, "sendrecv")) {
 			if (sendonly == -1)
 				sendonly = 0;
+			continue;
+		} else if (!strncasecmp(a, "framerate:", (size_t) 10)) {
+			if (sscanf(a, "framerate: %u", &framerate) != 1)
+				framerate = 0;
+			if (debug)
+				ast_verbose("Found framerate %d\n", framerate);
 			continue;
 		} else if (strlen(a) > 5 && !strncasecmp(a, "ptime", 5)) {
 			char *tmp = strrchr(a, ':');
@@ -5490,10 +5806,27 @@
 			found_rtpmap_codecs[last_rtpmap_codec] = codec;
 			last_rtpmap_codec++;
 
+			/* Note: This should all be done in the context of the m= above */
 			/* Note: should really look at the 'freq' and '#chans' params too */
-			/* Note: This should all be done in the context of the m= above */
 			if (!strncasecmp(mimeSubtype, "H26",3)) {         /* Video */
-				/* Not going to do anything here for the moment, but we will soon */
+				if (p->vrtp) {
+					ast_rtp_set_rtpmap_type(newvideortp, codec, "video", mimeSubtype, 0);
+					switch(mimeSubtype[3]) {
+						case '1' :
+							/*ast_verbose("Found a H.261 media type\n"); */
+					  	p->peercaps.h261.valid = 1;
+							break;
+						case '3' :
+							/* ast_verbose("Found a H.263 media type\n");*/
+							p->peercaps.h263.valid = 1;
+							break;
+						case '4' :
+							/* ast_verbose("Found a H.264 media type\n"); */
+							p->peercaps.h264.valid = 1;
+							p->peercaps.h264.rtpnum = codec;
+							break;
+					}
+				}
 			} else if (!strncasecmp(mimeSubtype, "T140",4)) { /* Text */
 				if (p->trtp) {
 					/* ast_verbose("Adding t140 mimeSubtype to textrtp struct\n"); */
@@ -5506,6 +5839,41 @@
 		}
 	}
 	
+	/* Next, scan through each "a=fmtp:" line, noting each
+	 */
+	/* XXX This needs to be done per media stream, since it's media stream specific */
+	iterator = req->sdp_start;
+	while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
+		if (sscanf(a, "fmtp: %u %n", &codec, &len) == 1) {
+			/* Note: This is used for codec parameters, like bitrate for
+				G722 and video formats for H263 and H264 
+				See RFC2327 for an example */
+			if (p->vrtp) {
+				payloadType = ast_rtp_lookup_pt(newvideortp, codec);
+				switch(payloadType.code) {
+				case AST_FORMAT_H261:
+					a += len;
+					process_h2613_fmtp(a, &p->peercaps.h261, framerate);
+					break;
+				case AST_FORMAT_H263:
+					a += len;
+					process_h2613_fmtp(a, &p->peercaps.h263, framerate);
+					break;
+				case AST_FORMAT_H264:
+					a += len;
+					process_h264_fmtp(a, &p->peercaps.h264, framerate);
+					break;
+				default:
+					if (option_debug > 1) {
+						if (debug)
+							ast_verbose("Got unsupported a:fmtp %u in SDP offer\n", codec);
+					}
+					break;
+				}
+			}
+		}
+	}
+
 	if (udptlportno != -1) {
 		int found = 0, x;
 		
@@ -5616,6 +5984,47 @@
 			ast_log(LOG_DEBUG, "T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
 	}
 
+  	if(sipdebug_caps) {	
+		ast_verbose("SIP PROCESS SDP: Peercaps: \n");	
+		ast_dump_caps(&p->peercaps);
+		ast_verbose("SIP PROCESS SDP: Caps: \n");	
+		ast_dump_caps(&p->caps);
+	}
+
+  	/* The peercaps are now in. There will be videocap.valid=1 if there was an RTPMAP entry and there
+	   will be codec information in the videocap if there was an fmtp. We now need to reconcile all these
+		 caps... it is possible that a peer does not set CT for instance and we need to generate it */
+	/* It may be better to do this on the joint cap... rather than pollute the peercap with elements that
+	   are not actually from the peer. */
+	check_set_video_bitrates(&p->peercaps, sipdebug_caps);
+
+	/* We now have a four way set of caps to resolve:
+		 caps:        come from the conf file
+	   peercaps:    come from the sdp
+		 jointcaps:   are the min of caps, peercaps and owner caps
+		 owner->caps: are a copy of the new jointcaps */
+	ast_copy_capabilities(&p->jointcaps, &p->peercaps);
+	if(p->owner) {
+		ast_resolve_capabilities(&p->jointcaps, &p->owner->channelcaps, &p->jointcaps, sipdebug_caps);
+		if(sipdebug_caps) {	
+			ast_verbose("SIP PROCESS SDP: Joint = Min(Owner, Joint)...\n");
+			ast_dump_caps(&p->jointcaps);
+		}
+	}
+	ast_resolve_capabilities(&p->jointcaps, &p->jointcaps, &p->caps, sipdebug_caps);
+  if(sipdebug_caps) {	
+		ast_verbose("SIP PROCESS SDP: Joint = Min(Joint, ConfCaps)...\n");
+		ast_dump_caps(&p->jointcaps);
+	}
+	if(p->owner) {
+		ast_copy_capabilities(&p->owner->channelcaps, &p->jointcaps);
+		if(sipdebug_caps) {	
+			ast_verbose("SIP PROCESS SDP: Owner = Joint...\n");
+			ast_dump_caps(&p->jointcaps);
+			ast_verbose("\n");
+		}
+	}
+
 	/* Now gather all of the codecs that we are asked for: */
 	ast_rtp_get_current_formats(newaudiortp, &peercapability, &peernoncodeccapability);
 	ast_rtp_get_current_formats(newvideortp, &vpeercapability, &vpeernoncodeccapability);
@@ -5626,7 +6035,7 @@
 	newnoncodeccapability = p->noncodeccapability & peernoncodeccapability;
 		
 		
-	if (debug) {
+	if (sipdebug_caps) {
 		/* shame on whoever coded this.... */
 		char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ], s4[BUFSIZ], s5[BUFSIZ];
 
@@ -5768,6 +6177,10 @@
 			sip_peer_hold(p, TRUE);
 	}
 	
+	/* Tell the other end of the call what our cap is */
+	/* XXX This needs to be changed to pass back the complex cap not just the simple cap */
+  ast_queue_control_data(p->owner, AST_CONTROL_CAPABILITY, &p->jointcaps, sizeof(p->jointcaps));
+
 	return 0;
 }
 
@@ -6415,6 +6828,40 @@
 	return 0;
 }
 
+static void ast_build_h2613_fmtp(char **buf, size_t *size, int rtp_code, struct ast_h2613_video_cap *video_cap)
+{
+	int i;
+	
+	if(video_cap->valid) {
+	  ast_build_string(buf, size, "a=fmtp:%d ",rtp_code);
+	  for (i = 0; i < MAX_VIDEO_SIZES; i++) {
+	  	if (video_cap->maxfr[i] > 0)
+	  		ast_build_string(buf, size, "%s=%d ", videoSizes[i].type, 30/video_cap->maxfr[i]);
+	  }
+	  if (video_cap->maxbr > 0)
+	  	ast_build_string(buf, size, "maxbr=%d",video_cap->maxbr/100);
+	  ast_build_string(buf, size, "\r\n");
+	} else {
+		ast_verbose("WARNING Video cap is not valid but have been asked to add fmtp\n");
+		ast_build_string(buf, size, "a=fmtp:%d;CIF=1;QCIF=1;maxbr=3840\r\n", rtp_code);
+	}
+}
+
+static void ast_build_h264_fmtp(char **buf, size_t *size, int rtp_code, struct ast_h264_video_cap *video_cap)
+{
+	/* ast_build_string(a_buf, a_size, "a=fmtp:%d profile-level-id=42800C; packetization-mode=0; max-br=384; max-mbps=10000\r\n", rtp_code); */
+	
+	if(video_cap->valid) {
+	  ast_build_string(buf, size, "a=fmtp:%d ",rtp_code);
+	  ast_build_string(buf, size, "profile-level-id=42800C; packetization-mode=0; ");
+	  if (video_cap->maxmbps > 0)
+	  	ast_build_string(buf, size, "max-mbps=%d; ",video_cap->maxmbps);
+	  if (video_cap->maxbr > 0)
+	  	ast_build_string(buf, size, "max-br=%d",video_cap->maxbr/1000);
+	  ast_build_string(buf, size, "\r\n");
+	}
+}
+
 /*! \brief Add codec offer to SDP offer/answer body in INVITE or 200 OK */
 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,
@@ -6456,7 +6903,6 @@
 }
 
 /*! \brief Add video codec offer to SDP offer/answer body in INVITE or 200 OK */
-/* This is different to the audio one now so we can add more caps later */
 static void add_vcodec_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)
@@ -6475,7 +6921,21 @@
 	ast_build_string(m_buf, m_size, " %d", rtp_code);
 	ast_build_string(a_buf, a_size, "a=rtpmap:%d %s/%d\r\n", rtp_code,
 			 ast_rtp_lookup_mime_subtype(1, codec, 0), sample_rate);
-	/* Add fmtp code here */
+	if (codec == AST_FORMAT_H261) {
+		if (sipdebug_caps)
+			ast_verbose("Adding h261 fmtp\n");
+		ast_build_h2613_fmtp(a_buf, a_size, rtp_code, (struct ast_h2613_video_cap*)&p->jointcaps.h261);
+	} else if (codec == AST_FORMAT_H263) {
+		if (sipdebug_caps)
+			ast_verbose("Adding h263 fmtp\n");
+		ast_build_h2613_fmtp(a_buf, a_size, rtp_code, (struct ast_h2613_video_cap*)&p->jointcaps.h263);
+	}	else if (codec == AST_FORMAT_H264) {
+		if (sipdebug_caps) {
+			ast_verbose("Adding h264 fmtp with rtpnum %d\n",p->jointcaps.h264.rtpnum);
+		}
+		ast_build_h264_fmtp(a_buf, a_size, rtp_code, (struct ast_h264_video_cap*)&p->jointcaps.h264);
+	}
+
 }
 
 /*! \brief Add text codec offer to SDP offer/answer body in INVITE or 200 OK */
@@ -6733,6 +7193,8 @@
 
 	int x;
 	int capability;
+	int videocapability=0;
+	int textcapability=0;
 	int needvideo = FALSE;
 	int needtext = FALSE;
 	int debug = sip_debug_test_pvt(p);
@@ -6795,10 +7257,37 @@
 		ast_build_string(&m_video_next, &m_video_left, "m=video %d RTP/AVP", ntohs(vdest.sin_port));
 
 		/* Build max bitrate string */
-		if (p->maxcallbitrate)
-			snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate);
+		if (p->jointcaps.maxcallbitrate)
+			snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->jointcaps.maxcallbitrate/1000);
+		else if (p->caps.maxcallbitrate)
+			snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->caps.maxcallbitrate/1000);
 		if (debug) 
 			ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(vsin.sin_port));	
+#if 0
+		/* For video, we can't negotiate video offers. Let's compare the incoming call with what we got. */
+		if (p->prefcodec) {
+			videocapability = (capability & p->prefcodec) & AST_FORMAT_VIDEO_MASK; /* Outbound call */
+		
+			/*! \todo XXX We need to select one codec, not many, since there's no transcoding */
+
+			/* Now, merge this video capability into capability while removing unsupported codecs */
+			if (!videocapability) {
+				needvideo = FALSE;
+				if (sipdebug_caps)
+					ast_log(LOG_DEBUG, "** No compatible video codecs... Disabling video.\n");
+			} 
+
+			/* Replace video capabilities with the new videocapability */
+			capability = (capability & AST_FORMAT_AUDIO_MASK) | (capability & AST_FORMAT_TEXT_MASK) | videocapability;
+
+			if (sipdebug_caps) {
+				char codecbuf[BUFSIZ];
+				if (videocapability)
+					ast_log(LOG_DEBUG, "** Our video codec selection is: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), videocapability));
+				ast_log(LOG_DEBUG, "** Capability now set to : %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), capability));
+			}
+		}
+#endif
 	}
 
 	/* Check if we need text in this call */
@@ -6857,7 +7346,7 @@
 	/* Prefer the audio codec we were requested to use, first, no matter what 
 		Note that p->prefcodec can include video codecs, so mask them out
 	 */
-	if (capability & p->prefcodec) {
+	if ((capability & AST_FORMAT_AUDIO_MASK) & p->prefcodec) {
 		int codec = p->prefcodec & AST_FORMAT_AUDIO_MASK;
 
 		add_codec_to_sdp(p, codec, SDP_SAMPLE_RATE(codec),
@@ -6926,8 +7415,38 @@
 	if (option_debug > 2)
 		ast_log(LOG_DEBUG, "-- Done with adding codecs to SDP\n");
 
-	if (!p->owner || !ast_internal_timing_enabled(p->owner))
-		ast_build_string(&a_audio_next, &a_audio_left, "a=silenceSupp:off - - - -\r\n");
+ 	/* if(!p->owner || !ast_internal_timing_enabled(p->owner))
+ 		ast_build_string(&a_audio_next, &a_audio_left, "a=silenceSupp:off - - - -\r\n"); */
+  
+  	if (min_audio_packet_size)
+  		ast_build_string(&a_audio_next, &a_audio_left, "a=ptime:%d\r\n", min_audio_packet_size);
+  
+ 	/* XXX don't think you can have ptime for video */
+  	if (min_video_packet_size)
+  		ast_build_string(&a_video_next, &a_video_left, "a=ptime:%d\r\n", min_video_packet_size);
+  
+ 	/* XXX don't think you can have ptime for text */
+ 	if (min_text_packet_size)
+ 		ast_build_string(&a_text_next, &a_text_left, "a=ptime:%d\r\n", min_text_packet_size);
+ 
+ 	if ((m_audio_left < 2) || (m_video_left < 2) || (m_text_left < 2) || 
+ 		  (a_audio_left == 0) || (a_video_left == 0) || (a_text_left == 0))
+  		ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n");
+  
+ 	if (p->jointcaps.maxvideobitrate > 0)
+ 		ast_build_string(&m_video_next, &m_video_left, "\r\nb=AS:%d", p->jointcaps.maxvideobitrate/1000);
+ 
+  	//ast_build_string(&m_audio_next, &m_audio_left, "\r\n");
+  	//if (needvideo)
+  		//ast_build_string(&m_video_next, &m_video_left, "\r\n");
+ 	//if (needtext)
+ 		//ast_build_string(&m_text_next, &m_text_left, "\r\n");
+  
+  	len = strlen(version) + strlen(subject) + strlen(owner) + strlen(connection) + strlen(stime) + strlen(m_audio) + strlen(a_audio) + strlen(hold);
+  	if (needvideo) /* only if video response is appropriate */
+  		len += strlen(m_video) + strlen(a_video) + strlen(bandwidth) + strlen(hold);
+ 	if (needtext) /* only if text response is appropriate */
+ 		len += strlen(m_text) + strlen(a_text) + strlen(hold);
 
 	if (min_audio_packet_size)
 		ast_build_string(&a_audio_next, &a_audio_left, "a=ptime:%d\r\n", min_audio_packet_size);
@@ -7385,6 +7904,8 @@
 static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init)
 {

[... 732 lines stripped ...]



More information about the svn-commits mailing list