[asterisk-commits] dvossel: branch dvossel/fixtheworld_phase1_step3 r300679 - in /team/dvossel/f...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jan 5 19:29:34 UTC 2011


Author: dvossel
Date: Wed Jan  5 13:29:28 2011
New Revision: 300679

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=300679
Log:
updates to channel.c

Modified:
    team/dvossel/fixtheworld_phase1_step3/include/asterisk/format_cap.h
    team/dvossel/fixtheworld_phase1_step3/main/channel.c
    team/dvossel/fixtheworld_phase1_step3/main/format_cap.c

Modified: team/dvossel/fixtheworld_phase1_step3/include/asterisk/format_cap.h
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/fixtheworld_phase1_step3/include/asterisk/format_cap.h?view=diff&rev=300679&r1=300678&r2=300679
==============================================================================
--- team/dvossel/fixtheworld_phase1_step3/include/asterisk/format_cap.h (original)
+++ team/dvossel/fixtheworld_phase1_step3/include/asterisk/format_cap.h Wed Jan  5 13:29:28 2011
@@ -54,6 +54,18 @@
 void ast_cap_add(struct ast_cap *cap, struct ast_format *format);
 
 /*!
+ * \brief Append the formats in src to dst
+ */
+void ast_cap_append(struct ast_cap *src, struct ast_cap *dst);
+
+/*!
+ * \brief create a deep copy of an ast_cap structure
+ * \retval cap on success
+ * \retval NULL on failure
+ */
+struct ast_cap *ast_cap_copy(struct ast_cap *cap);
+
+/*!
  * \brief Remove format capability from capability structure.
  *
  * \Note format must match Exactly to format in ast_cap object in order
@@ -77,9 +89,14 @@
 int ast_cap_remove_byid(struct ast_cap *cap, enum ast_format_id id);
 
 /*!
+ * \brief Remove all formats matching a specific format type.
+ */
+void ast_cap_remove_bytype(struct ast_cap *cap, enum ast_format_type type);
+
+/*!
  * \brief Remove all format capabilities from capability structure
  */
-int ast_cap_remove_all(struct ast_cap *cap);
+void ast_cap_remove_all(struct ast_cap *cap);
 
 /*!
  * \brief Find if ast_format is within the capabilities of the ast_cap object.
@@ -114,6 +131,14 @@
  */
 struct ast_cap *ast_cap_get_type(struct ast_cap *cap, enum ast_format_type ftype);
 
+/*!
+ * \brief Find out if the capabilities structure has any formats
+ * of a specific type.
+ *
+ * \retval 1 true
+ * \retval 0 false, no formats of specific type.
+ */
+int ast_cap_has_type(struct ast_cap *cap, enum ast_format_type type);
 
 /*! \brief Start iterating formats */
 void ast_cap_iter_start(struct ast_cap *cap);

Modified: team/dvossel/fixtheworld_phase1_step3/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/fixtheworld_phase1_step3/main/channel.c?view=diff&rev=300679&r1=300678&r2=300679
==============================================================================
--- team/dvossel/fixtheworld_phase1_step3/main/channel.c (original)
+++ team/dvossel/fixtheworld_phase1_step3/main/channel.c Wed Jan  5 13:29:28 2011
@@ -5458,16 +5458,12 @@
 	return 0;
 }
 
-struct ast_channel *ast_request(const char *type, struct ast_cap *cap, const struct ast_channel *requestor, void *data, int *cause)
+struct ast_channel *ast_request(const char *type, struct ast_cap *request_cap, const struct ast_channel *requestor, void *data, int *cause)
 {
 	struct chanlist *chan;
 	struct ast_channel *c;
-	struct ast_cap *capabilities;
-	format_t fmt;
 	int res;
 	int foo;
-	format_t videoformat = format & AST_FORMAT_VIDEO_MASK;
-	format_t textformat = format & AST_FORMAT_TEXT_MASK;
 
 	if (!cause)
 		cause = &foo;
@@ -5479,21 +5475,26 @@
 	}
 
 	AST_RWLIST_TRAVERSE(&backends, chan, list) {
+		struct ast_cap *tmp_cap;
+		struct ast_format tmp_fmt;
+		struct ast_format best_audio_fmt;
+		struct ast_cap *joint_cap;
+
 		if (strcasecmp(type, chan->tech->type))
 			continue;
 
-		capabilities = chan->tech->capabilities;
-		fmt = format & AST_FORMAT_AUDIO_MASK;
-		if (fmt) {
+		/* find the best audio format to use */
+		if ((tmp_cap = ast_cap_get_type(request_cap, AST_FORMAT_TYPE_AUDIO))) {
 			/* We have audio - is it possible to connect the various calls to each other? 
 				(Avoid this check for calls without audio, like text+video calls)
 			*/
-			res = ast_translator_best_choice(&fmt, &capabilities);
+			res = ast_translator_best_choice(tmp_cap, chan->tech->capabilities, &tmp_fmt, &best_audio_fmt);
+			ast_cap_destroy(tmp_cap);
 			if (res < 0) {
 				char tmp1[256], tmp2[256];
 				ast_log(LOG_WARNING, "No translator path exists for channel type %s (native %s) to %s\n", type,
 					ast_getformatname_multiple(tmp1, sizeof(tmp1), chan->tech->capabilities),
-					ast_getformatname_multiple(tmp2, sizeof(tmp2), format));
+					ast_getformatname_multiple(tmp2, sizeof(tmp2), request_cap));
 				*cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
 				AST_RWLIST_UNLOCK(&backends);
 				return NULL;
@@ -5503,8 +5504,21 @@
 		if (!chan->tech->requester)
 			return NULL;
 
-		if (!(c = chan->tech->requester(type, capabilities | videoformat | textformat, requestor, data, cause)))
+		/* XXX Only the audio format calculated as being the best for translation
+		 * purposes is used for the request. This needs to be re-evaluated.  It may be
+		 * a better choice to send all the audio formats capable of being translated
+		 * during the request and allow the channel drivers to pick the best one. */
+		if (!(joint_cap = ast_cap_copy(request_cap))) {
 			return NULL;
+		}
+		ast_cap_remove_bytype(joint_cap, AST_FORMAT_TYPE_AUDIO);
+		ast_cap_add(joint_cap, &best_audio_fmt);
+
+		if (!(c = chan->tech->requester(type, joint_cap, requestor, data, cause))) {
+			ast_cap_destroy(joint_cap);
+			return NULL;
+		}
+		joint_cap = ast_cap_destroy(joint_cap);
 
 		if (set_security_requirements(requestor, c)) {
 			ast_log(LOG_WARNING, "Setting security requirements failed\n");
@@ -5685,7 +5699,10 @@
 /*! \brief Set up translation from one channel to another */
 static int ast_channel_make_compatible_helper(struct ast_channel *from, struct ast_channel *to)
 {
-	format_t src, dst;
+	struct ast_cap *src_cap = from->nativeformats; /* shallow copy, do not destroy */
+	struct ast_cap *dst_cap = to->nativeformats;   /* shallow copy, do not destroy */
+	struct ast_format best_src_fmt;
+	struct ast_format best_dst_fmt;
 	int use_slin;
 
 	/* See if the channel driver can natively make these two channels compatible */
@@ -5694,20 +5711,17 @@
 		return 0;
 	}
 
-	if (from->readformat == to->writeformat && from->writeformat == to->readformat) {
+	if ((ast_format_cmp(&from->readformat, &to->writeformat) != AST_FORMAT_CMP_NOT_EQUAL) &&
+		(ast_format_cmp(&from->writeformat, &to->readformat) != AST_FORMAT_CMP_NOT_EQUAL)) {
 		/* Already compatible!  Moving on ... */
 		return 0;
 	}
 
-	/* Set up translation from the 'from' channel to the 'to' channel */
-	src = from->nativeformats;
-	dst = to->nativeformats;
-
 	/* If there's no audio in this call, don't bother with trying to find a translation path */
-	if ((src & AST_FORMAT_AUDIO_MASK) == 0 || (dst & AST_FORMAT_AUDIO_MASK) == 0)
+	if (!ast_cap_has_type(src_cap, AST_FORMAT_TYPE_AUDIO) || !ast_cap_has_type(dst_cap, AST_FORMAT_TYPE_AUDIO))
 		return 0;
 
-	if (ast_translator_best_choice(&dst, &src) < 0) {
+	if (ast_translator_best_choice(dst_cap, src_cap, &best_src_fmt, &best_dst_fmt) < 0) {
 		ast_log(LOG_WARNING, "No path to translate from %s to %s\n", from->name, to->name);
 		return -1;
 	}
@@ -5718,16 +5732,20 @@
 	 * no direct conversion available. If generic PLC is
 	 * desired, then transcoding via SLINEAR is a requirement
 	 */
-	use_slin = (src == AST_FORMAT_SLINEAR || dst == AST_FORMAT_SLINEAR);
-	if ((src != dst) && (ast_opt_generic_plc || ast_opt_transcode_via_slin) &&
-	    (ast_translate_path_steps(dst, src) != 1 || use_slin))
-		dst = AST_FORMAT_SLINEAR;
-	if (ast_set_read_format(from, dst) < 0) {
-		ast_log(LOG_WARNING, "Unable to set read format on channel %s to %s\n", from->name, ast_getformatname(dst));
+	use_slin = (best_src_fmt.id == AST_FORMAT_SLINEAR || best_dst_fmt.id == AST_FORMAT_SLINEAR);
+	if ((ast_format_cmp(&best_src_fmt, &best_dst_fmt) == AST_FORMAT_CMP_NOT_EQUAL) &&
+		(ast_opt_generic_plc || ast_opt_transcode_via_slin) &&
+	    (ast_translate_path_steps(&best_dst_fmt, &best_src_fmt) != 1 || use_slin)) {
+
+		ast_format_set(&best_dst_fmt, AST_FORMAT_SLINEAR, 0);
+	}
+
+	if (ast_set_read_format(from, &best_dst_fmt) < 0) {
+		ast_log(LOG_WARNING, "Unable to set read format on channel %s to %s\n", from->name, ast_getformatname(&best_dst_fmt));
 		return -1;
 	}
-	if (ast_set_write_format(to, dst) < 0) {
-		ast_log(LOG_WARNING, "Unable to set write format on channel %s to %s\n", to->name, ast_getformatname(dst));
+	if (ast_set_write_format(to, &best_dst_fmt) < 0) {
+		ast_log(LOG_WARNING, "Unable to set write format on channel %s to %s\n", to->name, ast_getformatname(&best_dst_fmt));
 		return -1;
 	}
 	return 0;

Modified: team/dvossel/fixtheworld_phase1_step3/main/format_cap.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/fixtheworld_phase1_step3/main/format_cap.c?view=diff&rev=300679&r1=300678&r2=300679
==============================================================================
--- team/dvossel/fixtheworld_phase1_step3/main/format_cap.c (original)
+++ team/dvossel/fixtheworld_phase1_step3/main/format_cap.c Wed Jan  5 13:29:28 2011
@@ -102,6 +102,38 @@
 	ao2_ref(fnew, -1);
 }
 
+void ast_cap_append(struct ast_cap *src, struct ast_cap *dst)
+{
+	struct ast_format tmp_fmt;
+	/* for every format in src that is not in dst, add that
+	 * format to dst. */
+	ast_cap_iter_start(src);
+	while (!ast_cap_iter_next(src, &tmp_fmt)) {
+		if (!ast_cap_iscompatible(dst, &tmp_fmt)) {
+			ast_cap_add(dst, &tmp_fmt);
+		}
+	}
+	ast_cap_iter_end(src);
+}
+
+struct ast_cap *ast_cap_copy(struct ast_cap *cap)
+{
+	struct ast_cap *copy = ast_cap_alloc();
+	struct ast_format tmp_fmt;
+
+	if (!copy) {
+		return NULL;
+	}
+
+	ast_cap_iter_start(cap);
+	while (!ast_cap_iter_next(cap, &tmp_fmt)) {
+		ast_cap_add(copy, &tmp_fmt);
+	}
+	ast_cap_iter_end(cap);
+
+	return copy;
+}
+
 static int find_exact_cb(void *obj, void *arg, int flag)
 {
 	struct ast_format *format1 = (struct ast_format *) arg;
@@ -163,6 +195,23 @@
 	}
 
 	return -1;
+}
+
+void ast_cap_remove_bytype(struct ast_cap *cap, enum ast_format_type type)
+{
+	/* There is no benifit of using an ao2 callback here. Instead
+	 * the container is just interated over */
+	struct ao2_iterator it;
+	struct ast_format *tmp;
+
+	it = ao2_iterator_init(cap->formats, 0);
+	while ((tmp = ao2_iterator_next(&it))) {
+		if (AST_FORMAT_GET_TYPE(tmp->id) == type) {
+			ao2_unlink(cap, tmp);
+		}
+		ao2_ref(tmp, -1);
+	}
+	ao2_iterator_destroy(&it);
 }
 
 void ast_cap_remove_all(struct ast_cap *cap)
@@ -297,6 +346,26 @@
 	return NULL;
 }
 
+
+int ast_cap_has_type(struct ast_cap *cap, enum ast_format_type type)
+{
+	struct ao2_iterator it;
+	struct ast_format *tmp;
+
+	it = ao2_iterator_init(cap->formats, 0);
+	while ((tmp = ao2_iterator_next(&it))) {
+		if (AST_FORMATNEW_GET_TYPE(tmp->id) == ftype) {
+			ao2_ref(tmp, -1);
+			ao2_iterator_destroy(&it);
+			return 1;
+		}
+		ao2_ref(tmp, -1);
+	}
+	ao2_iterator_destroy(&it);
+
+	return 0;
+}
+
 void ast_cap_iter_start(struct ast_cap *cap)
 {
 	cap->it = ao2_iterator_init(cap->formats, 0);




More information about the asterisk-commits mailing list