[svn-commits] file: trunk r370055 - in /trunk: channels/ include/asterisk/ main/ res/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Jul 13 11:49:47 CDT 2012


Author: file
Date: Fri Jul 13 11:49:40 2012
New Revision: 370055

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=370055
Log:
Add support for parsing SDP attributes, generating SDP attributes, and passing it through.

This support includes codecs such as H.263, H.264, SILK, and CELT. You are able to set up a call and have attribute information pass. This should help considerably with video calls.

Review: https://reviewboard.asterisk.org/r/2005/

Modified:
    trunk/channels/chan_sip.c
    trunk/include/asterisk/format.h
    trunk/main/format.c
    trunk/main/translate.c
    trunk/res/res_format_attr_celt.c
    trunk/res/res_format_attr_silk.c

Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=370055&r1=370054&r2=370055
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Fri Jul 13 11:49:40 2012
@@ -10175,7 +10175,7 @@
 	int found = FALSE;
 	int codec;
 	char mimeSubtype[128];
-	char fmtp_string[64];
+	char fmtp_string[256];
 	unsigned int sample_rate;
 	int debug = sip_debug_test_pvt(p);
 
@@ -10222,12 +10222,17 @@
 			if (debug)
 				ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec);
 		}
-	} else if (sscanf(a, "fmtp: %30u %63s", &codec, fmtp_string) == 2) {
+	} else if (sscanf(a, "fmtp: %30u %255s", &codec, fmtp_string) == 2) {
 		struct ast_format *format;
 
 		if ((format = ast_rtp_codecs_get_payload_format(newaudiortp, codec))) {
 			unsigned int bit_rate;
-			int val = 0;
+
+			if (!ast_format_sdp_parse(format, fmtp_string)) {
+				found = TRUE;
+			} else {
+				ast_rtp_codecs_payloads_unset(newaudiortp, NULL, codec);
+			}
 
 			switch ((int) format->id) {
 			case AST_FORMAT_SIREN7:
@@ -10260,21 +10265,6 @@
 					}
 				}
 				break;
-			case AST_FORMAT_CELT:
-				if (sscanf(fmtp_string, "framesize=%30u", &val) == 1) {
-					ast_format_append(format, CELT_ATTR_KEY_FRAME_SIZE, val, AST_FORMAT_ATTR_END);
-				}
-			case AST_FORMAT_SILK:
-				if (sscanf(fmtp_string, "maxaveragebitrate=%30u", &val) == 1) {
-					ast_format_append(format, SILK_ATTR_KEY_MAX_BITRATE, val, AST_FORMAT_ATTR_END);
-				}
-				if (sscanf(fmtp_string, "usedtx=%30u", &val) == 1) {
-					ast_format_append(format, SILK_ATTR_KEY_DTX, val ? 1 : 0, AST_FORMAT_ATTR_END);
-				}
-				if (sscanf(fmtp_string, "useinbandfec=%30u", &val) == 1) {
-					ast_format_append(format, SILK_ATTR_KEY_FEC, val ? 1 : 0, AST_FORMAT_ATTR_END);
-				}
-				break;
 			}
 		}
 	}
@@ -10289,6 +10279,7 @@
 	char mimeSubtype[128];
 	unsigned int sample_rate;
 	int debug = sip_debug_test_pvt(p);
+	char fmtp_string[256];
 
 	if (sscanf(a, "rtpmap: %30u %127[^/]/%30u", &codec, mimeSubtype, &sample_rate) == 3) {
 		/* We have a rtpmap to handle */
@@ -10310,6 +10301,16 @@
 		} else {
 			if (debug)
 				ast_verbose("Discarded description format %s for ID %d\n", mimeSubtype, codec);
+		}
+	} else if (sscanf(a, "fmtp: %30u %255s", &codec, fmtp_string) == 2) {
+		struct ast_format *format;
+
+		if ((format = ast_rtp_codecs_get_payload_format(newvideortp, codec))) {
+			if (!ast_format_sdp_parse(format, fmtp_string)) {
+				found = TRUE;
+			} else {
+				ast_rtp_codecs_payloads_unset(newvideortp, NULL, codec);
+			}
 		}
 	}
 
@@ -11747,7 +11748,6 @@
 {
 	int rtp_code;
 	struct ast_format_list fmt;
-	int val = 0;
 
 	if (debug)
 		ast_verbose("Adding codec %d (%s) to SDP\n", format->id, ast_getformatname(format));
@@ -11764,6 +11764,8 @@
 		rtp_code,
 		ast_rtp_lookup_mime_subtype2(1, format, 0, ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0),
 		ast_rtp_lookup_sample_rate2(1, format, 0));
+
+	ast_format_sdp_generate(format, rtp_code, a_buf);
 
 	switch ((int) format->id) {
 	case AST_FORMAT_G729A:
@@ -11790,22 +11792,6 @@
 		/* Indicate that we only expect 64Kbps */
 		ast_str_append(a_buf, 0, "a=fmtp:%d bitrate=64000\r\n", rtp_code);
 		break;
-	case AST_FORMAT_CELT:
-		if (!ast_format_get_value(format, CELT_ATTR_KEY_FRAME_SIZE, &val) && val > 0) {
-			ast_str_append(a_buf, 0, "a=fmtp:%d framesize=%u\r\n", rtp_code, val);
-		}
-		break;
-	case AST_FORMAT_SILK:
-		if (!ast_format_get_value(format, SILK_ATTR_KEY_MAX_BITRATE, &val) && val > 5000 && val < 40000) {
-			ast_str_append(a_buf, 0, "a=fmtp:%d maxaveragebitrate=%u\r\n", rtp_code, val);
-		}
-		if (!ast_format_get_value(format, SILK_ATTR_KEY_DTX, &val)) {
-			ast_str_append(a_buf, 0, "a=fmtp:%d usedtx=%u\r\n", rtp_code, val ? 1 : 0);
-		}
-		if (!ast_format_get_value(format, SILK_ATTR_KEY_FEC, &val)) {
-			ast_str_append(a_buf, 0, "a=fmtp:%d useinbandfec=%u\r\n", rtp_code, val ? 1 : 0);
-		}
-		break;
 	}
 
 	if (fmt.cur_ms && (fmt.cur_ms < *min_packet_size))
@@ -11837,7 +11823,8 @@
 	ast_str_append(a_buf, 0, "a=rtpmap:%d %s/%d\r\n", rtp_code,
 		       ast_rtp_lookup_mime_subtype2(1, format, 0, 0),
 		       ast_rtp_lookup_sample_rate2(1, format, 0));
-	/* Add fmtp code here */
+
+	ast_format_sdp_generate(format, rtp_code, a_buf);
 }
 
 /*! \brief Add text codec offer to SDP offer/answer body in INVITE or 200 OK */
@@ -12262,10 +12249,12 @@
 
 		/* Start by sending our preferred audio/video codecs */
 		for (x = 0; x < AST_CODEC_PREF_SIZE; x++) {
-			if (!(ast_codec_pref_index(&p->prefs, x, &tmp_fmt)))
+			struct ast_format pref;
+
+			if (!(ast_codec_pref_index(&p->prefs, x, &pref)))
 				break;
 
-			if (!(ast_format_cap_iscompatible(tmpcap, &tmp_fmt)))
+			if (!ast_format_cap_get_compatible_format(tmpcap, &pref, &tmp_fmt))
 				continue;
 
 			if (ast_format_cap_iscompatible(alreadysent, &tmp_fmt))

Modified: trunk/include/asterisk/format.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/format.h?view=diff&rev=370055&r1=370054&r2=370055
==============================================================================
--- trunk/include/asterisk/format.h (original)
+++ trunk/include/asterisk/format.h Fri Jul 13 11:49:40 2012
@@ -131,7 +131,7 @@
 /*! \brief This structure contains the buffer used for format attributes */
 struct ast_format_attr {
 	/*! The buffer formats can use to represent attributes */
-	uint8_t format_attr[AST_FORMAT_ATTR_SIZE];
+	uint32_t format_attr[AST_FORMAT_ATTR_SIZE];
 	/*! If a format's payload needs to pass through that a new marker is required
 	 * for RTP, this variable will be set. */
 	uint8_t rtp_marker_bit;
@@ -219,7 +219,45 @@
 	 * \retval -1 failure, Value was either not found, or not allowed to be accessed.
 	 */
 	int (* const format_attr_get_val)(const struct ast_format_attr *format_attr, int key, void *val);
-};
+
+	/*
+	 * \brief Parse SDP attribute information, interpret it, and store it in ast_format_attr structure.
+	 *
+	 * \retval 0 Success, values were valid
+	 * \retval -1 Failure, some values were not acceptable
+	 */
+	int (* const format_attr_sdp_parse)(struct ast_format_attr *format_attr, const char *attributes);
+
+	/*!
+	 * \brief Generate SDP attribute information from an ast_format_attr structure.
+	 *
+	 * \note This callback should generate a full fmtp line using the provided payload number.
+	 */
+	void (* const format_attr_sdp_generate)(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str);
+};
+
+/*!
+ * \brief This function is used to have a media format aware module parse and interpret
+ * SDP attribute information. Once interpreted this information is stored on the format
+ * itself using Asterisk format attributes.
+ *
+ * \param format to set
+ * \param attributes string containing the fmtp line from the SDP
+ *
+ * \retval 0 success, attribute values were valid
+ * \retval -1 failure, values were not acceptable
+ */
+int ast_format_sdp_parse(struct ast_format *format, const char *attributes);
+
+/*!
+ * \brief This function is used to produce an fmtp SDP line for an Asterisk format. The
+ * attributes present on the Asterisk format are translated into the SDP equivalent.
+ *
+ * \param format to generate an fmtp line for
+ * \param payload numerical payload for the fmtp line
+ * \param str structure that the fmtp line will be appended to
+ */
+void ast_format_sdp_generate(const struct ast_format *format, unsigned int payload, struct ast_str **str);
 
 /*!
  * \brief This function is used to set an ast_format object to represent a media format

Modified: trunk/main/format.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/format.c?view=diff&rev=370055&r1=370054&r2=370055
==============================================================================
--- trunk/main/format.c (original)
+++ trunk/main/format.c Fri Jul 13 11:49:40 2012
@@ -117,6 +117,51 @@
 	}
 	ao2_ref(wrapper, -1);
 	return 1;
+}
+
+int ast_format_sdp_parse(struct ast_format *format, const char *attributes)
+{
+	struct interface_ao2_wrapper *wrapper;
+	int res;
+
+	if (!(wrapper = find_interface(format))) {
+		return 0;
+	}
+
+	ao2_rdlock(wrapper);
+	if (!(wrapper->interface || !wrapper->interface->format_attr_sdp_parse)) {
+		ao2_unlock(wrapper);
+		ao2_ref(wrapper, -1);
+		return 0;
+	}
+
+	res = wrapper->interface->format_attr_sdp_parse(&format->fattr, attributes);
+
+	ao2_unlock(wrapper);
+	ao2_ref(wrapper, -1);
+
+	return res;
+}
+
+void ast_format_sdp_generate(const struct ast_format *format, unsigned int payload, struct ast_str **str)
+{
+	struct interface_ao2_wrapper *wrapper;
+
+	if (!(wrapper = find_interface(format))) {
+		return;
+	}
+
+	ao2_rdlock(wrapper);
+	if (!(wrapper->interface || !wrapper->interface->format_attr_sdp_generate)) {
+		ao2_unlock(wrapper);
+		ao2_ref(wrapper, -1);
+		return;
+	}
+
+	wrapper->interface->format_attr_sdp_generate(&format->fattr, payload, str);
+
+	ao2_unlock(wrapper);
+	ao2_ref(wrapper, -1);
 }
 
 /*! \internal

Modified: trunk/main/translate.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/translate.c?view=diff&rev=370055&r1=370054&r2=370055
==============================================================================
--- trunk/main/translate.c (original)
+++ trunk/main/translate.c Fri Jul 13 11:49:40 2012
@@ -1286,12 +1286,22 @@
 void ast_translate_available_formats(struct ast_format_cap *dest, struct ast_format_cap *src, struct ast_format_cap *result)
 {
 	struct ast_format tmp_fmt;
-	struct ast_format cur_src;
+	struct ast_format cur_dest, cur_src;
 	int src_audio = 0;
 	int src_video = 0;
 	int index;
 
-	ast_format_cap_copy(result, dest);
+	ast_format_cap_iter_start(dest);
+	while (!ast_format_cap_iter_next(dest, &cur_dest)) {
+		/* We give preference to a joint format structure if possible */
+		if (ast_format_cap_get_compatible_format(src, &cur_dest, &tmp_fmt)) {
+			ast_format_cap_add(result, &tmp_fmt);
+		} else {
+			/* Otherwise we just use the destination format */
+			ast_format_cap_add(result, &cur_dest);
+		}
+	}
+	ast_format_cap_iter_end(dest);
 
 	/* if we don't have a source format, we just have to try all
 	   possible destination formats */

Modified: trunk/res/res_format_attr_celt.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_format_attr_celt.c?view=diff&rev=370055&r1=370054&r2=370055
==============================================================================
--- trunk/res/res_format_attr_celt.c (original)
+++ trunk/res/res_format_attr_celt.c Fri Jul 13 11:49:40 2012
@@ -44,6 +44,29 @@
 	unsigned int maxbitrate;
 	unsigned int framesize;
 };
+
+static int celt_sdp_parse(struct ast_format_attr *format_attr, const char *attributes)
+{
+	struct celt_attr *attr = (struct celt_attr *) format_attr;
+	unsigned int val;
+
+	if (sscanf(attributes, "framesize=%30u", &val) == 1) {
+		attr->framesize = val;
+	}
+
+	return 0;
+}
+
+static void celt_sdp_generate(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str)
+{
+	struct celt_attr *attr = (struct celt_attr *) format_attr;
+
+	if (!attr->framesize) {
+		return;
+	}
+
+	ast_str_append(str, 0, "a=fmtp:%d framesize=%d\r\n", payload, attr->framesize);
+}
 
 static enum ast_format_cmp_res celt_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2)
 {
@@ -161,6 +184,8 @@
 	.format_attr_set = celt_set,
 	.format_attr_isset = celt_isset,
 	.format_attr_get_val = celt_get_val,
+	.format_attr_sdp_parse = celt_sdp_parse,
+	.format_attr_sdp_generate = celt_sdp_generate,
 };
 
 static int load_module(void)

Modified: trunk/res/res_format_attr_silk.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_format_attr_silk.c?view=diff&rev=370055&r1=370054&r2=370055
==============================================================================
--- trunk/res/res_format_attr_silk.c (original)
+++ trunk/res/res_format_attr_silk.c Fri Jul 13 11:49:40 2012
@@ -47,6 +47,36 @@
 	unsigned int packetloss_percentage;
 };
 
+static int silk_sdp_parse(struct ast_format_attr *format_attr, const char *attributes)
+{
+	struct silk_attr *attr = (struct silk_attr *) format_attr;
+	unsigned int val;
+
+	if (sscanf(attributes, "maxaveragebitrate=%30u", &val) == 1) {
+		attr->maxbitrate = val;
+	}
+	if (sscanf(attributes, "usedtx=%30u", &val) == 1) {
+		attr->dtx = val;
+	}
+	if (sscanf(attributes, "useinbandfec=%30u", &val) == 1) {
+		attr->fec = val;
+	}
+
+	return 0;
+}
+
+static void silk_sdp_generate(const struct ast_format_attr *format_attr, unsigned int payload, struct ast_str **str)
+{
+	struct silk_attr *attr = (struct silk_attr *) format_attr;
+
+	if ((attr->maxbitrate > 5000) && (attr->maxbitrate < 40000)) { 
+		ast_str_append(str, 0, "a=fmtp:%d maxaveragebitrate=%d\r\n", payload, attr->maxbitrate);
+	}
+
+	ast_str_append(str, 0, "a=fmtp:%d usedtx=%d\r\n", payload, attr->dtx);
+	ast_str_append(str, 0, "a=fmtp:%d useinbandfec=%d\r\n", payload, attr->fec);
+}
+
 static enum ast_format_cmp_res silk_cmp(const struct ast_format_attr *fattr1, const struct ast_format_attr *fattr2)
 {
 	struct silk_attr *attr1 = (struct silk_attr *) fattr1;
@@ -195,6 +225,8 @@
 	.format_attr_set = silk_set,
 	.format_attr_isset = silk_isset,
 	.format_attr_get_val = silk_get_val,
+	.format_attr_sdp_parse = silk_sdp_parse,
+	.format_attr_sdp_generate = silk_sdp_generate,
 };
 
 static int load_module(void)




More information about the svn-commits mailing list