[svn-commits] oej: branch oej/teapot-1.8 r402885 - in /team/oej/teapot-1.8: ./ channels/ ch...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Nov 19 02:28:53 CST 2013


Author: oej
Date: Tue Nov 19 02:28:49 2013
New Revision: 402885

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=402885
Log:
Adding Pinefrog RTCP patch to the Teapot

Added:
    team/oej/teapot-1.8/patches/pinefrog-rtcp-1.8.diff   (with props)
Modified:
    team/oej/teapot-1.8/CREDITS
    team/oej/teapot-1.8/channels/chan_sip.c
    team/oej/teapot-1.8/channels/sip/dialplan_functions.c
    team/oej/teapot-1.8/channels/sip/include/sip.h
    team/oej/teapot-1.8/configs/extconfig.conf.sample
    team/oej/teapot-1.8/include/asterisk/logger.h
    team/oej/teapot-1.8/include/asterisk/rtp_engine.h
    team/oej/teapot-1.8/main/logger.c
    team/oej/teapot-1.8/main/rtp_engine.c
    team/oej/teapot-1.8/res/res_rtp_asterisk.c

Modified: team/oej/teapot-1.8/CREDITS
URL: http://svnview.digium.com/svn/asterisk/team/oej/teapot-1.8/CREDITS?view=diff&rev=402885&r1=402884&r2=402885
==============================================================================
--- team/oej/teapot-1.8/CREDITS (original)
+++ team/oej/teapot-1.8/CREDITS Tue Nov 19 02:28:49 2013
@@ -22,6 +22,9 @@
 
 Omnitor AB, Gunnar Hellström, for funding work with videocaps, T.140 RED,
 originate with video/text and many more contributions.
+
+Nordicom Norge AS, Kristiansand, Norway, for funding work with RTCP support
+and Call Quality Records.
 
 === WISHLIST CONTRIBUTERS ===
 Jeremy McNamara - SpeeX support
@@ -116,6 +119,7 @@
 	SIP presence support, SIP call state updates (dialog-info), 
 	QUEUE_EXISTS function, device state provider architecture,
 	multiparking (together with mvanbaak), meetme and parking device states,
+        RTCP improvements, Call Quality Records,
 	MiniVM - the small voicemail system, many documentation
 	updates/corrections, and many bug fixes.
 	oej(AT)edvina.net, http://edvina.net
@@ -217,7 +221,8 @@
 Viagenie, Canada - IPv6 support in socket layers and SIP implementation
 	Developers: Marc Blanchet, Simon Perreault and Jean-Philippe Dionne
 
-ClearIT AB, Sweden - res_mutestream, queue_exists and various other patches (developed by oej)
+ClearIT AB, Sweden - res_mutestream, queue_exists, RTCP improvements and various 
+        other patches (developed by oej)
 
 Despegar.com, Argentina - AstData API implementation, also sponsored by Google as part of the
 	gsoc/2009 program (developed by Eliel)

Modified: team/oej/teapot-1.8/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/teapot-1.8/channels/chan_sip.c?view=diff&rev=402885&r1=402884&r2=402885
==============================================================================
--- team/oej/teapot-1.8/channels/chan_sip.c (original)
+++ team/oej/teapot-1.8/channels/chan_sip.c Tue Nov 19 02:28:49 2013
@@ -276,6 +276,7 @@
 #include "asterisk/xml.h"
 #include "sip/include/dialog.h"
 #include "sip/include/dialplan_functions.h"
+#include "sip/include/rtcp.h"
 
 
 /*** DOCUMENTATION
@@ -673,7 +674,6 @@
 	{ AST_REDIRECTING_REASON_CALL_FWD_DTE, "unknown"}
 };
 
-
 /*! \name DefaultSettings
 	Default setttings are used as a channel setting and as a default when
 	configuring devices
@@ -6220,6 +6220,22 @@
 	if (dumphistory)
 		sip_dump_history(p);
 
+	AST_SCHED_DEL(sched, p->rtcpeventid);
+
+ 	if (p->audioqual) {
+ 		/* We have a quality report to write to realtime before we leave this world. */
+ 		qos_write_realtime(p, p->audioqual);
+ 		free(p->audioqual);
+ 		p->audioqual = NULL;
+ 	}
+ 	if (p->videoqual) {
+ 		/* We have a quality report to write to realtime before we leave this world. */
+ 		qos_write_realtime(p, p->videoqual);
+ 		free(p->videoqual);
+ 		p->videoqual = NULL;
+ 	}
+
+
 	if (p->options) {
 		if (p->options->outboundproxy) {
 			ao2_ref(p->options->outboundproxy, -1);
@@ -6785,6 +6801,7 @@
 		ast_rtp_instance_update_source(p->rtp);
 		res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, oldsdp, TRUE);
 		ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
+		start_rtcp_events(p, sched);
 	}
 	sip_pvt_unlock(p);
 	return res;
@@ -8048,8 +8065,10 @@
 		set_socket_transport(&p->socket, SIP_TRANSPORT_UDP);
 	}
 
+	p->sip_cfg = &sip_cfg;
 	p->socket.fd = -1;
 	p->method = intended_method;
+	p->rtcpeventid = -1;
 	p->initid = -1;
 	p->waitid = -1;
 	p->reinviteid = -1;
@@ -8111,6 +8130,14 @@
 		build_callid_pvt(p);
 	else
 		ast_string_field_set(p, callid, callid);
+
+	/* Set cnames for the RTCP SDES */
+	if (p->rtp) {
+		ast_rtp_instance_setcname(p->rtp, p->callid, strlen(p->callid));
+	}
+	if (p->vrtp) {
+		ast_rtp_instance_setcname(p->vrtp, p->callid, strlen(p->callid));
+	}
 	/* Assign default music on hold class */
 	ast_string_field_set(p, mohinterpret, default_mohinterpret);
 	ast_string_field_set(p, mohsuggest, default_mohsuggest);
@@ -9034,6 +9061,7 @@
 			      dialog->owner->uniqueid);
 	append_history(dialog, holdstate ? "Hold" : "Unhold", "%s", ast_str_buffer(req->data));
 	if (!holdstate) {	/* Put off remote hold */
+		ast_rtp_instance_hold(dialog->rtp, 0);	/* Turn off RTP hold */
 		ast_clear_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD);	/* Clear both flags */
 		return;
 	}
@@ -9802,9 +9830,9 @@
 		ast_queue_control_data(p->owner, AST_CONTROL_HOLD,
 				       S_OR(p->mohsuggest, NULL),
 				       !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
-		if (sendonly)
-			ast_rtp_instance_stop(p->rtp);
-		/* RTCP needs to go ahead, even if we're on hold!!! */
+		if (sendonly == 1 || sendonly == 2) {	/* sendonly (from the other side) or inactive */
+			ast_rtp_instance_hold(p->rtp, 1);
+		}
 		/* Activate a re-invite */
 		ast_queue_frame(p->owner, &ast_null_frame);
 		change_hold_state(p, req, TRUE, sendonly);
@@ -18144,8 +18172,10 @@
 	int x = 0, load_realtime;
 	format_t codec = 0;
 	int realtimepeers;
+	int realtimertpqos = FALSE;
 
 	realtimepeers = ast_check_realtime("sippeers");
+	realtimertpqos = ast_check_realtime("rtpcqr");
 
 	if (argc < 4)
 		return CLI_SHOWUSAGE;
@@ -18764,9 +18794,11 @@
 {
 	int realtimepeers;
 	int realtimeregs;
+	int realtimertpqos;
 	char codec_buf[SIPBUFSIZE];
 	const char *msg;	/* temporary msg pointer */
 	struct sip_auth_container *credentials;
+
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -18784,6 +18816,7 @@
 
 	realtimepeers = ast_check_realtime("sippeers");
 	realtimeregs = ast_check_realtime("sipregs");
+	realtimertpqos = ast_check_realtime("rtpcqr");
 
 	ast_mutex_lock(&authl_lock);
 	credentials = authl;
@@ -18854,6 +18887,8 @@
 	}
 	ast_cli(a->fd, "  Record SIP history:     %s\n", AST_CLI_ONOFF(recordhistory));
 	ast_cli(a->fd, "  Call Events:            %s\n", AST_CLI_ONOFF(sip_cfg.callevents));
+	ast_cli(a->fd, "  RTCP Events:            %s\n", AST_CLI_ONOFF(sip_cfg.rtcpevents));
+	ast_cli(a->fd, "  RTCP Event timer:       %d\n", sip_cfg.rtcptimer);
 	ast_cli(a->fd, "  Auth. Failure Events:   %s\n", AST_CLI_ONOFF(global_authfailureevents));
 
 	ast_cli(a->fd, "  T.38 support:           %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT)));
@@ -18863,6 +18898,7 @@
 		ast_cli(a->fd, "  SIP realtime:           Disabled\n" );
 	else
 		ast_cli(a->fd, "  SIP realtime:           Enabled\n" );
+	ast_cli(a->fd, "  QoS realtime reports:   %s\n", realtimertpqos ? "Enabled" : "Disabled" );
 	ast_cli(a->fd, "  Qualify Freq :          %d ms\n", global_qualifyfreq);
 	ast_cli(a->fd, "  Q.850 Reason header:    %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[1], SIP_PAGE2_Q850_REASON)));
 	ast_cli(a->fd, "  Store SIP_CAUSE:        %s\n", AST_CLI_YESNO(global_store_sip_cause));
@@ -20853,6 +20889,7 @@
 		if (!req->ignore && p->invitestate != INV_CANCELLED && sip_cancel_destroy(p))
 			ast_log(LOG_WARNING, "Unable to cancel SIP destruction.  Expect bad things.\n");
 		check_pendings(p);
+		start_rtcp_events(p, sched);
 		break;
 
 	case 180:	/* 180 Ringing */
@@ -21140,6 +21177,7 @@
 		ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
 		xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, TRUE);
 		check_pendings(p);
+		start_rtcp_events(p, sched);
 		break;
 
 	case 407: /* Proxy authentication */
@@ -21803,16 +21841,21 @@
 	}
 }
 
-/*! \brief Immediately stop RTP, VRTP and UDPTL as applicable */
+/*! \brief Immediately stop RTP, VRTP, TEXT and UDPTL as applicable */
 static void stop_media_flows(struct sip_pvt *p)
 {
 	/* Immediately stop RTP, VRTP and UDPTL as applicable */
-	if (p->rtp)
+	if (p->rtp && !ast_rtp_instance_isactive(p->rtp)) {
+		sip_rtcp_report(p, p->rtp, SDP_AUDIO, TRUE);
 		ast_rtp_instance_stop(p->rtp);
-	if (p->vrtp)
+	}
+	if (p->vrtp && !ast_rtp_instance_isactive(p->vrtp)) {
+		sip_rtcp_report(p, p->vrtp, SDP_VIDEO, TRUE);
 		ast_rtp_instance_stop(p->vrtp);
-	if (p->trtp)
+	}
+	if (p->trtp && !ast_rtp_instance_isactive(p->trtp)) {
 		ast_rtp_instance_stop(p->trtp);
+	}
 	if (p->udptl)
 		ast_udptl_stop(p->udptl);
 }
@@ -24839,6 +24882,7 @@
 
 
 		if (p->rtp && (quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
+			sip_rtcp_report(p, p->rtp, SDP_AUDIO, TRUE);
 			if (p->do_history) {
 				append_history(p, "RTCPaudio", "Quality:%s", quality);
 
@@ -24869,6 +24913,7 @@
 		}
 
 		if (p->vrtp && (quality = ast_rtp_instance_get_quality(p->vrtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
+			sip_rtcp_report(p, p->rtp, SDP_VIDEO, TRUE);
 			if (p->do_history) {
 				append_history(p, "RTCPvideo", "Quality:%s", quality);
 			}
@@ -29188,6 +29233,8 @@
 	/* Misc settings for the channel */
 	global_relaxdtmf = FALSE;
 	sip_cfg.callevents = DEFAULT_CALLEVENTS;
+	sip_cfg.rtcpevents = FALSE;
+	sip_cfg.rtcptimer = 0;	/* Only report at end of call (default) */
 	global_authfailureevents = FALSE;
 	global_t1 = DEFAULT_TIMER_T1;
 	global_timer_b = 64 * DEFAULT_TIMER_T1;
@@ -29616,6 +29663,13 @@
 			} else {
 				ast_log(LOG_WARNING, "Invalid qualifyfreq number '%s' at line %d of %s\n", v->value, v->lineno, config);
 				global_qualifyfreq = DEFAULT_QUALIFYFREQ;
+			}
+		} else if (!strcasecmp(v->name, "rtcpevents")) {
+			sip_cfg.rtcpevents = ast_true(v->value);
+		} else if (!strcasecmp(v->name, "rtcpeventtimer")) {
+			if (sscanf(v->value, "%30d", &sip_cfg.rtcptimer) != 1) {
+				ast_log(LOG_WARNING, "RTCP event timer needs to be value (seconds between reports) at line %d of sip.conf\n", v->lineno);
+				sip_cfg.rtcptimer = 0;
 			}
 		} else if (!strcasecmp(v->name, "callevents")) {
 			sip_cfg.callevents = ast_true(v->value);

Modified: team/oej/teapot-1.8/channels/sip/dialplan_functions.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/teapot-1.8/channels/sip/dialplan_functions.c?view=diff&rev=402885&r1=402884&r2=402885
==============================================================================
--- team/oej/teapot-1.8/channels/sip/dialplan_functions.c (original)
+++ team/oej/teapot-1.8/channels/sip/dialplan_functions.c Tue Nov 19 02:28:49 2013
@@ -140,7 +140,9 @@
 
 		snprintf(buf, buflen, "%s", ast_sockaddr_stringify(&sa));
 	} else if (!strcasecmp(args.param, "rtpqos")) {
+/* OEJ - Check this part, different from 1.4 */
 		struct ast_rtp_instance *rtp = NULL;
+		struct ast_rtp_quality *qos;
 
 		if (ast_strlen_zero(args.type)) {
 			args.type = "audio";
@@ -162,6 +164,11 @@
 			if (!ast_rtp_instance_get_quality(rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf))) {
 				return -1;
 			}
+#ifdef OEJ
+			if (!ast_rtp_instance_get_qualdata(rtp, ???, &qos)) {
+				this_needs_some_love;
+			}
+#endif
 
 			ast_copy_string(buf, quality_buf, buflen);
 			return res;

Modified: team/oej/teapot-1.8/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/teapot-1.8/channels/sip/include/sip.h?view=diff&rev=402885&r1=402884&r2=402885
==============================================================================
--- team/oej/teapot-1.8/channels/sip/include/sip.h (original)
+++ team/oej/teapot-1.8/channels/sip/include/sip.h Tue Nov 19 02:28:49 2013
@@ -706,6 +706,8 @@
 	int compactheaders;         /*!< send compact sip headers */
 	int allow_external_domains; /*!< Accept calls to external SIP domains? */
 	int callevents;             /*!< Whether we send manager events or not */
+	int rtcpevents;             /*!< Whether we send manager RTCP events or not */
+	int rtcptimer;		    /*!< How often, during a call, to report RTCP stats */
 	int regextenonqualify;      /*!< Whether to add/remove regexten when qualifying peers */
 	int legacy_useroption_parsing; /*!< Whether to strip useroptions in URI via semicolons */
 	int matchexternaddrlocally;   /*!< Match externaddr/externhost setting against localnet setting */
@@ -1096,6 +1098,7 @@
 	int waitid;                         /*!< Wait ID for scheduler after 491 or other delays */
 	int reinviteid;                     /*!< Reinvite in case of provisional, but no final response */
 	int autokillid;                     /*!< Auto-kill ID (scheduler) */
+	int rtcpeventid;                        /*!< Scheduler ID for RTCP Events */
 	int t38id;                          /*!< T.38 Response ID */
 	struct sip_refer *refer;            /*!< REFER: SIP transfer data structure */
 	enum subscriptiontype subscribed;   /*!< SUBSCRIBE: Is this dialog a subscription?  */
@@ -1151,6 +1154,12 @@
 	 * The large-scale changes would be a good idea for implementing during an SDP rewrite.
 	 */
 	struct offered_media offered_media[OFFERED_MEDIA_COUNT];
+	//struct ast_rtp_quality *audioqual;              /*!< Audio: The latest quality report, for realtime storage */
+	//struct ast_rtp_quality *videoqual;              /*!< Video: The latest quality report, for realtime storage */
+	struct ast_rtp_instance_stats *audioqual;              /*!< Audio: The latest quality report, for realtime storage */
+	struct ast_rtp_instance_stats *videoqual;              /*!< Video: The latest quality report, for realtime storage */
+	struct sip_settings *sip_cfg;			/*! Which sip_cfg is associated with this dialog */
+
 	struct ast_cc_config_params *cc_params;
 	struct sip_epa_entry *epa_entry;
 	int fromdomainport;                 /*!< Domain port to show in from field */

Modified: team/oej/teapot-1.8/configs/extconfig.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/oej/teapot-1.8/configs/extconfig.conf.sample?view=diff&rev=402885&r1=402884&r2=402885
==============================================================================
--- team/oej/teapot-1.8/configs/extconfig.conf.sample (original)
+++ team/oej/teapot-1.8/configs/extconfig.conf.sample Tue Nov 19 02:28:49 2013
@@ -80,6 +80,7 @@
 ;queue_members => odbc,asterisk
 ;musiconhold => mysql,general
 ;queue_log => mysql,general
+;rtpcqr => mysql,general	; RTP Call Quality Records
 ;
 ;
 ; While most dynamic realtime engines are automatically used when defined in

Modified: team/oej/teapot-1.8/include/asterisk/logger.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/teapot-1.8/include/asterisk/logger.h?view=diff&rev=402885&r1=402884&r2=402885
==============================================================================
--- team/oej/teapot-1.8/include/asterisk/logger.h (original)
+++ team/oej/teapot-1.8/include/asterisk/logger.h Tue Nov 19 02:28:49 2013
@@ -181,7 +181,18 @@
 #endif
 #define AST_LOG_DTMF    __LOG_DTMF, _A_
 
-#define NUMLOGLEVELS 32
+#ifdef LOG_CQR
+#undef LOG_CQR
+#endif
+#define __LOG_CQR  7
+#define LOG_CQR    __LOG_CQR, _A_
+
+#ifdef AST_LOG_CQR
+#undef AST_LOG_CQR
+#endif
+#define AST_LOG_CQR    __LOG_CQR, _A_
+
+#define NUMLOGLEVELS 64		/* Highest bit */
 
 /*!
  * \brief Get the debug level for a module

Modified: team/oej/teapot-1.8/include/asterisk/rtp_engine.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/teapot-1.8/include/asterisk/rtp_engine.h?view=diff&rev=402885&r1=402884&r2=402885
==============================================================================
--- team/oej/teapot-1.8/include/asterisk/rtp_engine.h (original)
+++ team/oej/teapot-1.8/include/asterisk/rtp_engine.h Tue Nov 19 02:28:49 2013
@@ -74,6 +74,7 @@
 #include "asterisk/netsock2.h"
 #include "asterisk/sched.h"
 #include "asterisk/res_srtp.h"
+#include "asterisk/channel.h"
 
 /* Maximum number of payloads supported */
 #define AST_RTP_MAX_PT 256
@@ -211,6 +212,14 @@
 	AST_RTP_INSTANCE_STAT_LOCAL_SSRC,
 	/*! Retrieve remote SSRC */
 	AST_RTP_INSTANCE_STAT_REMOTE_SSRC,
+	/*! Retrieve local CNAME */
+	AST_RTP_INSTANCE_STAT_LOCAL_CNAME,
+	/*! Retrieve remote SDES */
+	AST_RTP_INSTANCE_STAT_REMOTE_CNAME,
+	/*! Retrieve start time */
+	AST_RTP_INSTANCE_STAT_START,
+	/*! Retrieve IP Address */
+	AST_RTP_INSTANCE_STAT_IP,
 };
 
 /* Codes for RTP-specific data - not defined by our AST_FORMAT codes */
@@ -237,10 +246,12 @@
 	unsigned int txcount;
 	/*! Number of packets received */
 	unsigned int rxcount;
+
 	/*! Jitter on transmitted packets */
 	double txjitter;
 	/*! Jitter on received packets */
 	double rxjitter;
+
 	/*! Maximum jitter on remote side */
 	double remote_maxjitter;
 	/*! Minimum jitter on remote side */
@@ -291,6 +302,32 @@
 	unsigned int local_ssrc;
 	/*! Their SSRC */
 	unsigned int remote_ssrc;
+
+	/* --- Pinefrog additions */
+	/*! Remote: Number of packets transmitted */
+	unsigned int remote_txcount;
+	/*! Remote: Number of packets received */
+	unsigned int remote_rxcount;
+	char channel[AST_MAX_EXTENSION];	/*!< Name of channel */
+	char uniqueid[AST_MAX_EXTENSION];	/*!< uniqueid of channel */
+	char bridgedchannel[AST_MAX_EXTENSION];	/*!< Name of bridged channel */
+	char bridgeduniqueid[AST_MAX_EXTENSION];	/*!< uniqueid of bridged channel */
+	unsigned int numberofreports;	  /*!< Number of reports received from remote end */
+	int lasttxformat;		  /*!< Last used codec on transmitted stream */
+	int lastrxformat;		  /*!< Last used codec on received stream */
+	struct sockaddr_in them;	  /*!< The IP address used for media by remote end */
+	struct sockaddr_in us;	  	  /*!< The IP address used for media by our end */
+	char ourcname[255];		/*!< Our SDES RTP session name (CNAME) */
+	size_t ourcnamelength;		/*!< Length of CNAME (utf8) */
+	char theircname[255];		/*!< Their SDES RTP session name (CNAME) */
+	size_t theircnamelength;	/*!< Length of CNAME (utf8) */
+	struct timeval start;		  /*!< When the stream started */
+	struct timeval end;		  /*!< When the stream ended */
+	char writetranslator[80];	  /*!< Translator used when writing */
+	char readtranslator[80];		  /*!< Translator providing frames when reading */
+	int writecost;		  /*!< Cost in milliseconds for encoding/decoding 1 second of outbound media */
+	int readcost;		  /*!< Cost in milliseconds for encoding/decoding 1 second of inbound media */
+	int mediatype;			/*! Type of media */
 };
 
 #define AST_RTP_STAT_SET(current_stat, combined, placement, value) \
@@ -318,6 +355,9 @@
 	int (*destroy)(struct ast_rtp_instance *instance);
 	/*! Callback for writing out a frame */
 	int (*write)(struct ast_rtp_instance *instance, struct ast_frame *frame);
+	/*! Callback for stopping the outbound RTP media for an instance,
+	    but keeping the RTCP flow (and the RTP keepalives if needed) */
+	void (*hold)(struct ast_rtp_instance *instance, int status);
 	/*! Callback for stopping the RTP instance */
 	void (*stop)(struct ast_rtp_instance *instance);
 	/*! Callback for starting RFC2833 DTMF transmission */
@@ -377,6 +417,15 @@
 	format_t (*available_formats)(struct ast_rtp_instance *instance, format_t to_endpoint, format_t to_asterisk);
 	/*! Callback to send CNG */
 	int (*sendcng)(struct ast_rtp_instance *instance, int level);
+	/*! Callback to check if a media stram is active */
+	int (*isactive)(struct ast_rtp_instance *instance);
+	/*! Callback to set CNAME in rtcp  */
+	void (*setcname)(struct ast_rtp_instance *instance, const char *cname, size_t length);
+	/*! Callback to set information about bridged channel for CQR record */
+	void (*set_bridged_chan)(struct ast_rtp_instance *instance, const char *channel, const char *uniqueid, const char *bridgedchan, const char *bridgeduniqueid);
+	/*! Callback to set translation information for the CQR record */
+	void (*set_translator) (struct ast_rtp_instance *instance, const char *readtranslator, const int readcost, const char *writetranslator, const int writecost);
+	int (*rtcp_write_empty)(struct ast_rtp_instance *instance);
 	/*! Linked list information */
 	AST_RWLIST_ENTRY(ast_rtp_engine) entry;
 };
@@ -1311,6 +1360,26 @@
 int ast_rtp_instance_set_qos(struct ast_rtp_instance *instance, int tos, int cos, const char *desc);
 
 /*!
+ * \brief Stop the RTP outbound media in a stream, but keep the RTCP flow going
+ * 	  And propably RTP keepalives too.
+ *
+ * \param instance Instance that media is no longer going to at this time
+ *
+ * Example usage:
+ *
+ * \code
+ * ast_rtp_instance_stop(instance);
+ * \endcode
+ *
+ * This tells the RTP engine being used for the instance pointed to by instance
+ * that media is no longer going to it at this time, but may in the future.
+ * Keep the RTCP flow happy
+ *
+ * \since 1.42
+ */
+void ast_rtp_instance_hold(struct ast_rtp_instance *instance, int status);
+
+/*!
  * \brief Stop an RTP instance
  *
  * \param instance Instance that media is no longer going to at this time
@@ -1834,6 +1903,36 @@
 int ast_rtp_instance_sendcng(struct ast_rtp_instance *instance, int level);
 
 /*!
+ * \brief Send empty RTCP report
+ *
+ * \param instance The RTP instance
+ * \param fd File descriptor to use
+ *
+ * \retval 0 Success
+ * \retval non-zero Failure
+ */
+int ast_rtcp_write_empty(struct ast_rtp_instance *instance);
+
+
+/*!
+ * \brief Check if RTP stream is active
+ *
+ * \param instance The RTP instance
+ *
+ * \retval 0 Active (success)
+ * \retval -1 Not supported by RTP engine, 1 Not active
+ */
+int ast_rtp_instance_isactive(struct ast_rtp_instance *instance);
+
+/*!
+ * \brief Set the name of the RTP session (used in RTCP)
+ * \param cname Session name (UTF 8 possible)
+ * \param length Name of string (needed for UTF 8 always)
+ *
+ */
+int ast_rtp_instance_setcname(struct ast_rtp_instance *instance, const char *cname, size_t length);
+
+/*!
  * \brief Add or replace the SRTP policies for the given RTP instance
  *
  * \param instance the RTP instance
@@ -1854,6 +1953,22 @@
  */
 struct ast_srtp *ast_rtp_instance_get_srtp(struct ast_rtp_instance *instance);
 
+/*!
+ * \brief set the channel information for the CQR records
+ *
+ * \retval 0 on success
+ * \retval -1 not implemented by RTP engine
+ */
+int ast_rtp_instance_set_bridged_chan(struct ast_rtp_instance *instance, const char *channel, const char *uniqueid, const char *bridgedchan, const char *bridgeduniqueid);
+
+/*!
+ * \brief set the channel translator information for the CQR records
+ *
+ * \retval 0 on success
+ * \retval -1 not implemented by RTP engine
+ */
+int ast_rtp_instance_set_translator(struct ast_rtp_instance *instance, const char *readtranslator, const int readcost, const char *writetranslator, const int writecost);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

Modified: team/oej/teapot-1.8/main/logger.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/teapot-1.8/main/logger.c?view=diff&rev=402885&r1=402884&r2=402885
==============================================================================
--- team/oej/teapot-1.8/main/logger.c (original)
+++ team/oej/teapot-1.8/main/logger.c Tue Nov 19 02:28:49 2013
@@ -174,6 +174,7 @@
 	"ERROR",
 	"VERBOSE",
 	"DTMF",
+	"CQR",
 };
 
 /*! \brief Colors used in the console for logging */
@@ -185,7 +186,7 @@
 	COLOR_RED,
 	COLOR_GREEN,
 	COLOR_BRGREEN,
-	0,
+	COLOR_BRBLUE,
 	0,
 	0,
 	0,

Modified: team/oej/teapot-1.8/main/rtp_engine.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/teapot-1.8/main/rtp_engine.c?view=diff&rev=402885&r1=402884&r2=402885
==============================================================================
--- team/oej/teapot-1.8/main/rtp_engine.c (original)
+++ team/oej/teapot-1.8/main/rtp_engine.c Tue Nov 19 02:28:49 2013
@@ -21,6 +21,9 @@
  * \brief Pluggable RTP Architecture
  *
  * \author Joshua Colp <jcolp at digium.com>
+ *
+ * Improved RTCP support by
+ * \author Olle E. Johansson  <oej at edvina.net>
  */
 
 /*** MODULEINFO
@@ -776,6 +779,13 @@
 	return instance->engine->qos ? instance->engine->qos(instance, tos, cos, desc) : -1;
 }
 
+void ast_rtp_instance_hold(struct ast_rtp_instance *instance, int status)
+{
+	if (instance->engine->hold) {
+		instance->engine->hold(instance, status);
+	}
+}
+
 void ast_rtp_instance_stop(struct ast_rtp_instance *instance)
 {
 	if (instance->engine->stop) {
@@ -829,6 +839,7 @@
 		return AST_BRIDGE_FAILED_NOWARN;
 	}
 
+	/* Now let go of the channel locks and be on our way */
 	ast_channel_unlock(c0);
 	ast_channel_unlock(c1);
 
@@ -836,6 +847,10 @@
 	instance1->bridged = instance0;
 
 	ast_poll_channel_add(c0, c1);
+
+	/* Kick the RTCP stream going by sending one empty stupid little packet */
+	ast_rtcp_write_empty(instance0);
+	ast_rtcp_write_empty(instance1);
 
 	/* Hop into a loop waiting for a frame from either channel */
 	cs[0] = c0;
@@ -1836,11 +1851,58 @@
 	return instance->srtp;
 }
 
+int ast_rtp_instance_isactive(struct ast_rtp_instance *instance)
+{
+	if (instance->engine->isactive) {
+		return instance->engine->isactive(instance);
+	}
+
+	return -1;
+}
+
+int ast_rtcp_write_empty(struct ast_rtp_instance *instance)
+{
+	if (instance->engine->rtcp_write_empty) {
+		instance->engine->rtcp_write_empty(instance);
+		return 0;
+	}
+	return -1;
+}
+
 int ast_rtp_instance_sendcng(struct ast_rtp_instance *instance, int level)
 {
 	if (instance->engine->sendcng) {
 		return instance->engine->sendcng(instance, level);
 	}
-
 	return -1;
 }
+
+int ast_rtp_instance_setcname(struct ast_rtp_instance *instance, const char *cname, size_t length)
+{
+	if (instance->engine->setcname) {
+		instance->engine->setcname(instance, cname, length);
+		return 0;
+	}
+
+	return -1;	/* Function does not exist */
+}
+
+int ast_rtp_instance_set_bridged_chan(struct ast_rtp_instance *instance, const char *channel, const char *uniqueid, const char *bridgedchan, const char *bridgeduniqueid)
+{
+	if (instance->engine->set_bridged_chan) {
+		instance->engine->set_bridged_chan(instance, channel, uniqueid, bridgedchan, bridgeduniqueid);
+		return 0;
+	}
+
+	return -1;	/* Function does not exist */
+}
+
+int ast_rtp_instance_set_translator(struct ast_rtp_instance *instance, const char *readtranslator, const int readcost, const char *writetranslator, const int writecost)
+{
+	if (instance->engine->set_translator) {
+		instance->engine->set_translator(instance, readtranslator, readcost, writetranslator, writecost);
+		return 0;
+	}
+
+	return -1;	/* Function does not exist */
+}

Added: team/oej/teapot-1.8/patches/pinefrog-rtcp-1.8.diff
URL: http://svnview.digium.com/svn/asterisk/team/oej/teapot-1.8/patches/pinefrog-rtcp-1.8.diff?view=auto&rev=402885
==============================================================================
--- team/oej/teapot-1.8/patches/pinefrog-rtcp-1.8.diff (added)
+++ team/oej/teapot-1.8/patches/pinefrog-rtcp-1.8.diff Tue Nov 19 02:28:49 2013
@@ -1,0 +1,2651 @@
+Index: channels/chan_sip.c
+===================================================================
+--- channels/chan_sip.c	(.../branches/1.8)	(revision 402883)
++++ channels/chan_sip.c	(.../team/oej/pinefrog-rtcp-1.8)	(revision 402883)
+@@ -275,6 +275,7 @@
+ #include "asterisk/xml.h"
+ #include "sip/include/dialog.h"
+ #include "sip/include/dialplan_functions.h"
++#include "sip/include/rtcp.h"
+ 
+ 
+ /*** DOCUMENTATION
+@@ -670,7 +671,6 @@
+ 	{ AST_REDIRECTING_REASON_CALL_FWD_DTE, "unknown"}
+ };
+ 
+-
+ /*! \name DefaultSettings
+ 	Default setttings are used as a channel setting and as a default when
+ 	configuring devices
+@@ -6175,6 +6175,22 @@
+ 	if (dumphistory)
+ 		sip_dump_history(p);
+ 
++	AST_SCHED_DEL(sched, p->rtcpeventid);
++
++ 	if (p->audioqual) {
++ 		/* We have a quality report to write to realtime before we leave this world. */
++ 		qos_write_realtime(p, p->audioqual);
++ 		free(p->audioqual);
++ 		p->audioqual = NULL;
++ 	}
++ 	if (p->videoqual) {
++ 		/* We have a quality report to write to realtime before we leave this world. */
++ 		qos_write_realtime(p, p->videoqual);
++ 		free(p->videoqual);
++ 		p->videoqual = NULL;
++ 	}
++
++
+ 	if (p->options) {
+ 		if (p->options->outboundproxy) {
+ 			ao2_ref(p->options->outboundproxy, -1);
+@@ -6901,6 +6917,7 @@
+ 		ast_rtp_instance_update_source(p->rtp);
+ 		res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, oldsdp, TRUE);
+ 		ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
++		start_rtcp_events(p, sched);
+ 	}
+ 	sip_pvt_unlock(p);
+ 	return res;
+@@ -8156,8 +8173,10 @@
+ 		set_socket_transport(&p->socket, SIP_TRANSPORT_UDP);
+ 	}
+ 
++	p->sip_cfg = &sip_cfg;
+ 	p->socket.fd = -1;
+ 	p->method = intended_method;
++	p->rtcpeventid = -1;
+ 	p->initid = -1;
+ 	p->waitid = -1;
+ 	p->reinviteid = -1;
+@@ -8219,6 +8238,14 @@
+ 		build_callid_pvt(p);
+ 	else
+ 		ast_string_field_set(p, callid, callid);
++
++	/* Set cnames for the RTCP SDES */
++	if (p->rtp) {
++		ast_rtp_instance_setcname(p->rtp, p->callid, strlen(p->callid));
++	}
++	if (p->vrtp) {
++		ast_rtp_instance_setcname(p->vrtp, p->callid, strlen(p->callid));
++	}
+ 	/* Assign default music on hold class */
+ 	ast_string_field_set(p, mohinterpret, default_mohinterpret);
+ 	ast_string_field_set(p, mohsuggest, default_mohsuggest);
+@@ -9142,6 +9169,7 @@
+ 			      dialog->owner->uniqueid);
+ 	append_history(dialog, holdstate ? "Hold" : "Unhold", "%s", ast_str_buffer(req->data));
+ 	if (!holdstate) {	/* Put off remote hold */
++		ast_rtp_instance_hold(dialog->rtp, 0);	/* Turn off RTP hold */
+ 		ast_clear_flag(&dialog->flags[1], SIP_PAGE2_CALL_ONHOLD);	/* Clear both flags */
+ 		return;
+ 	}
+@@ -9910,9 +9938,9 @@
+ 		ast_queue_control_data(p->owner, AST_CONTROL_HOLD,
+ 				       S_OR(p->mohsuggest, NULL),
+ 				       !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
+-		if (sendonly)
+-			ast_rtp_instance_stop(p->rtp);
+-		/* RTCP needs to go ahead, even if we're on hold!!! */
++		if (sendonly == 1 || sendonly == 2) {	/* sendonly (from the other side) or inactive */
++			ast_rtp_instance_hold(p->rtp, 1);
++		}
+ 		/* Activate a re-invite */
+ 		ast_queue_frame(p->owner, &ast_null_frame);
+ 		change_hold_state(p, req, TRUE, sendonly);
+@@ -18148,8 +18176,10 @@
+ 	int x = 0, load_realtime;
+ 	format_t codec = 0;
+ 	int realtimepeers;
++	int realtimertpqos = FALSE;
+ 
+ 	realtimepeers = ast_check_realtime("sippeers");
++	realtimertpqos = ast_check_realtime("rtpcqr");
+ 
+ 	if (argc < 4)
+ 		return CLI_SHOWUSAGE;
+@@ -18764,10 +18794,12 @@
+ {
+ 	int realtimepeers;
+ 	int realtimeregs;
++	int realtimertpqos;
+ 	char codec_buf[SIPBUFSIZE];
+ 	const char *msg;	/* temporary msg pointer */
+ 	struct sip_auth_container *credentials;
+ 
++
+ 	switch (cmd) {
+ 	case CLI_INIT:
+ 		e->command = "sip show settings";
+@@ -18784,6 +18816,7 @@
+ 
+ 	realtimepeers = ast_check_realtime("sippeers");
+ 	realtimeregs = ast_check_realtime("sipregs");
++	realtimertpqos = ast_check_realtime("rtpcqr");
+ 
+ 	ast_mutex_lock(&authl_lock);
+ 	credentials = authl;
+@@ -18853,6 +18886,8 @@
+ 	}
+ 	ast_cli(a->fd, "  Record SIP history:     %s\n", AST_CLI_ONOFF(recordhistory));
+ 	ast_cli(a->fd, "  Call Events:            %s\n", AST_CLI_ONOFF(sip_cfg.callevents));
++	ast_cli(a->fd, "  RTCP Events:            %s\n", AST_CLI_ONOFF(sip_cfg.rtcpevents));
++	ast_cli(a->fd, "  RTCP Event timer:       %d\n", sip_cfg.rtcptimer);
+ 	ast_cli(a->fd, "  Auth. Failure Events:   %s\n", AST_CLI_ONOFF(global_authfailureevents));
+ 
+ 	ast_cli(a->fd, "  T.38 support:           %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[1], SIP_PAGE2_T38SUPPORT)));
+@@ -18862,6 +18897,7 @@
+ 		ast_cli(a->fd, "  SIP realtime:           Disabled\n" );
+ 	else
+ 		ast_cli(a->fd, "  SIP realtime:           Enabled\n" );
++	ast_cli(a->fd, "  QoS realtime reports:   %s\n", realtimertpqos ? "Enabled" : "Disabled" );
+ 	ast_cli(a->fd, "  Qualify Freq :          %d ms\n", global_qualifyfreq);
+ 	ast_cli(a->fd, "  Q.850 Reason header:    %s\n", AST_CLI_YESNO(ast_test_flag(&global_flags[1], SIP_PAGE2_Q850_REASON)));
+ 	ast_cli(a->fd, "  Store SIP_CAUSE:        %s\n", AST_CLI_YESNO(global_store_sip_cause));
+@@ -20803,6 +20839,7 @@
+ 		if (!req->ignore && p->invitestate != INV_CANCELLED && sip_cancel_destroy(p))
+ 			ast_log(LOG_WARNING, "Unable to cancel SIP destruction.  Expect bad things.\n");
+ 		check_pendings(p);
++		start_rtcp_events(p, sched);
+ 		break;
+ 
+ 	case 180:	/* 180 Ringing */
+@@ -21080,6 +21117,7 @@
+ 		ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED);
+ 		xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, TRUE);
+ 		check_pendings(p);
++		start_rtcp_events(p, sched);
+ 		break;
+ 
+ 	case 407: /* Proxy authentication */
+@@ -21730,16 +21768,21 @@
+ 	}
+ }
+ 
+-/*! \brief Immediately stop RTP, VRTP and UDPTL as applicable */
++/*! \brief Immediately stop RTP, VRTP, TEXT and UDPTL as applicable */
+ static void stop_media_flows(struct sip_pvt *p)
+ {
+ 	/* Immediately stop RTP, VRTP and UDPTL as applicable */
+-	if (p->rtp)
++	if (p->rtp && !ast_rtp_instance_isactive(p->rtp)) {
++		sip_rtcp_report(p, p->rtp, SDP_AUDIO, TRUE);
+ 		ast_rtp_instance_stop(p->rtp);
+-	if (p->vrtp)
++	}
++	if (p->vrtp && !ast_rtp_instance_isactive(p->vrtp)) {
++		sip_rtcp_report(p, p->vrtp, SDP_VIDEO, TRUE);
+ 		ast_rtp_instance_stop(p->vrtp);
+-	if (p->trtp)
++	}
++	if (p->trtp && !ast_rtp_instance_isactive(p->trtp)) {
+ 		ast_rtp_instance_stop(p->trtp);
++	}
+ 	if (p->udptl)
+ 		ast_udptl_stop(p->udptl);
+ }
+@@ -24660,6 +24703,7 @@
+ 
+ 
+ 		if (p->rtp && (quality = ast_rtp_instance_get_quality(p->rtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
++			sip_rtcp_report(p, p->rtp, SDP_AUDIO, TRUE);
+ 			if (p->do_history) {
+ 				append_history(p, "RTCPaudio", "Quality:%s", quality);
+ 
+@@ -24690,6 +24734,7 @@
+ 		}
+ 
+ 		if (p->vrtp && (quality = ast_rtp_instance_get_quality(p->vrtp, AST_RTP_INSTANCE_STAT_FIELD_QUALITY, quality_buf, sizeof(quality_buf)))) {
++			sip_rtcp_report(p, p->rtp, SDP_VIDEO, TRUE);
+ 			if (p->do_history) {
+ 				append_history(p, "RTCPvideo", "Quality:%s", quality);
+ 			}
+@@ -28999,6 +29044,8 @@
+ 	/* Misc settings for the channel */
+ 	global_relaxdtmf = FALSE;
+ 	sip_cfg.callevents = DEFAULT_CALLEVENTS;
++	sip_cfg.rtcpevents = FALSE;
++	sip_cfg.rtcptimer = 0;	/* Only report at end of call (default) */
+ 	global_authfailureevents = FALSE;
+ 	global_t1 = DEFAULT_TIMER_T1;
+ 	global_timer_b = 64 * DEFAULT_TIMER_T1;
+@@ -29426,6 +29473,13 @@
+ 				ast_log(LOG_WARNING, "Invalid qualifyfreq number '%s' at line %d of %s\n", v->value, v->lineno, config);
+ 				global_qualifyfreq = DEFAULT_QUALIFYFREQ;
+ 			}
++		} else if (!strcasecmp(v->name, "rtcpevents")) {
++			sip_cfg.rtcpevents = ast_true(v->value);
++		} else if (!strcasecmp(v->name, "rtcpeventtimer")) {
++			if (sscanf(v->value, "%30d", &sip_cfg.rtcptimer) != 1) {
++				ast_log(LOG_WARNING, "RTCP event timer needs to be value (seconds between reports) at line %d of sip.conf\n", v->lineno);
++				sip_cfg.rtcptimer = 0;
++			}
+ 		} else if (!strcasecmp(v->name, "callevents")) {
+ 			sip_cfg.callevents = ast_true(v->value);
+ 		} else if (!strcasecmp(v->name, "authfailureevents")) {
+Index: channels/sip/include/sip.h
+===================================================================
+--- channels/sip/include/sip.h	(.../branches/1.8)	(revision 402883)
++++ channels/sip/include/sip.h	(.../team/oej/pinefrog-rtcp-1.8)	(revision 402883)
+@@ -696,6 +696,8 @@
+ 	int compactheaders;         /*!< send compact sip headers */
+ 	int allow_external_domains; /*!< Accept calls to external SIP domains? */
+ 	int callevents;             /*!< Whether we send manager events or not */
++	int rtcpevents;             /*!< Whether we send manager RTCP events or not */
++	int rtcptimer;		    /*!< How often, during a call, to report RTCP stats */
+ 	int regextenonqualify;      /*!< Whether to add/remove regexten when qualifying peers */
+ 	int legacy_useroption_parsing; /*!< Whether to strip useroptions in URI via semicolons */
+ 	int matchexternaddrlocally;   /*!< Match externaddr/externhost setting against localnet setting */
+@@ -1080,6 +1082,7 @@
+ 	int waitid;                         /*!< Wait ID for scheduler after 491 or other delays */
+ 	int reinviteid;                     /*!< Reinvite in case of provisional, but no final response */
+ 	int autokillid;                     /*!< Auto-kill ID (scheduler) */
++	int rtcpeventid;                        /*!< Scheduler ID for RTCP Events */
+ 	int t38id;                          /*!< T.38 Response ID */
+ 	struct sip_refer *refer;            /*!< REFER: SIP transfer data structure */
+ 	enum subscriptiontype subscribed;   /*!< SUBSCRIBE: Is this dialog a subscription?  */
+@@ -1135,6 +1138,12 @@
+ 	 * The large-scale changes would be a good idea for implementing during an SDP rewrite.
+ 	 */
+ 	struct offered_media offered_media[OFFERED_MEDIA_COUNT];
++	//struct ast_rtp_quality *audioqual;              /*!< Audio: The latest quality report, for realtime storage */
++	//struct ast_rtp_quality *videoqual;              /*!< Video: The latest quality report, for realtime storage */
++	struct ast_rtp_instance_stats *audioqual;              /*!< Audio: The latest quality report, for realtime storage */
++	struct ast_rtp_instance_stats *videoqual;              /*!< Video: The latest quality report, for realtime storage */
++	struct sip_settings *sip_cfg;			/*! Which sip_cfg is associated with this dialog */
++
+ 	struct ast_cc_config_params *cc_params;
+ 	struct sip_epa_entry *epa_entry;
+ 	int fromdomainport;                 /*!< Domain port to show in from field */
+Index: channels/sip/include/rtcp.h
+===================================================================
+--- channels/sip/include/rtcp.h	(.../branches/1.8)	(revision 0)
++++ channels/sip/include/rtcp.h	(.../team/oej/pinefrog-rtcp-1.8)	(revision 402883)
+@@ -0,0 +1,50 @@
++/*
++ * Asterisk -- An open source telephony toolkit.
++ *
++ * Copyright (C) 2013 Olle E. Johansson, Edvina AB
++ *
++ * See http://www.asterisk.org for more information about
++ * the Asterisk project. Please do not directly contact
++ * any of the maintainers of this project for assistance;
++ * the project provides a web site, mailing lists and IRC
++ * channels for your use.
++ *
++ * This program is free software, distributed under the terms of
++ * the GNU General Public License Version 2. See the LICENSE file
++ * at the top of the source tree.
++ */
++
++/*! \file rtcp.h
++ *
++ * \brief RTCP additional functions
++ *
++ * \author Olle E. Johansson <oej at edvina.net>
++ */
++
++#include "asterisk.h"
++
++#include "asterisk/utils.h"
++#include "asterisk/rtp_engine.h"
++#include "sip.h"
++
++#ifndef _SIP_RTCP_H
++#define _SIP_RTCP_H
++
++/*! \brief Set various data items in the RTP structure, like channel identifier.
++ */
++void sip_rtcp_set_data(struct sip_pvt *dialog, struct ast_rtp_instance *instance, enum media_type type);
++
++int send_rtcp_events(const void *data);
++void start_rtcp_events(struct sip_pvt *dialog, struct sched_context *sched);
++/*
++# For 1.4:
++# static void sip_rtcp_report(struct sip_pvt *p, struct ast_rtp *rtp, enum media_type type, int reporttype);
++*/
++
++void sip_rtcp_report(struct sip_pvt *dialog, struct ast_rtp_instance *instance, enum media_type type, int reporttype);
++//void qos_write_realtime(struct sip_pvt *dialog, struct ast_rtp_quality *qual);
++void qos_write_realtime(struct sip_pvt *dialog, struct ast_rtp_instance_stats *qual);
++
++
++
++#endif /* _SIP_RTCP_H */
+
+Property changes on: channels/sip/include/rtcp.h
+___________________________________________________________________
+Added: svn:mime-type
+## -0,0 +1 ##
++text/plain
+\ No newline at end of property
+Added: svn:keywords
+## -0,0 +1 ##
++Author Date Id Revision
+\ No newline at end of property
+Added: svn:eol-style

[... 3614 lines stripped ...]



More information about the svn-commits mailing list