[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