[asterisk-commits] russell: branch russell/iax2_media r116977 - in /team/russell/iax2_media: cha...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sun May 18 22:40:32 CDT 2008
Author: russell
Date: Sun May 18 22:40:31 2008
New Revision: 116977
URL: http://svn.digium.com/view/asterisk?view=rev&rev=116977
Log:
Check in a work in progress. While half awake one night I got to thinking
about media handling in chan_iax2. The way frames get sent up to the core
from the IAX2 processing threads is by queueing frames onto the ast_channel.
However, it's very expensive as it requires malloc'ing a new frame and
expensive locking with deadlock avoidance (accessing an ast_channel from a
channel driver is usually pretty ugly, as Asterisk locking rules require
that you get the ast_channel lock _before_ the channel's pvt lock, and coming
from the channel driver, you usually have the pvt before the channel.)
So, anyway, I started playing around with ways to pass audio to the core by
queueing the audio on to the pvt struct, and allowing the core to use the
iax2_read callback to get it. So far, I have avoided the nasty deadlock
avoidance that had to be done when queueing frames, and it appears to have
some performance improvements already. However, I still have more I want to
do to reduce how many times frames are malloc'd and copied around within
chan_iax2 ...
Modified:
team/russell/iax2_media/channels/chan_iax2.c
team/russell/iax2_media/channels/iax2-parser.c
team/russell/iax2_media/channels/iax2-parser.h
team/russell/iax2_media/formats/format_pcm.c
team/russell/iax2_media/include/asterisk/channel.h
team/russell/iax2_media/include/asterisk/linkedlists.h
team/russell/iax2_media/main/channel.c
team/russell/iax2_media/main/sched.c
team/russell/iax2_media/main/slinfactory.c
Modified: team/russell/iax2_media/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/team/russell/iax2_media/channels/chan_iax2.c?view=diff&rev=116977&r1=116976&r2=116977
==============================================================================
--- team/russell/iax2_media/channels/chan_iax2.c (original)
+++ team/russell/iax2_media/channels/chan_iax2.c Sun May 18 22:40:31 2008
@@ -464,8 +464,6 @@
int dropped;
int ooo;
};
-
-struct iax2_pvt_ref;
struct chan_iax2_pvt {
/*! Socket to send/receive on for this call */
@@ -642,6 +640,9 @@
int frames_dropped;
/*! received frame count: (just for stats) */
int frames_received;
+
+ AST_LIST_HEAD_NOLOCK(, iax_frame) audio_q;
+ AST_LIST_HEAD_NOLOCK(, iax_frame) used_audio_q;
};
/*!
@@ -1381,6 +1382,7 @@
{
struct chan_iax2_pvt *pvt = obj;
struct iax_frame *cur = NULL;
+ jb_frame frame;
iax2_destroy_helper(pvt);
@@ -1400,19 +1402,23 @@
pvt->reg->callno = 0;
}
- if (!pvt->owner) {
- jb_frame frame;
- if (pvt->vars) {
- ast_variables_destroy(pvt->vars);
- pvt->vars = NULL;
- }
-
- while (jb_getall(pvt->jb, &frame) == JB_OK) {
- iax2_frame_free(frame.data);
- }
-
- jb_destroy(pvt->jb);
- ast_string_field_free_memory(pvt);
+ if (pvt->vars) {
+ ast_variables_destroy(pvt->vars);
+ pvt->vars = NULL;
+ }
+
+ while (jb_getall(pvt->jb, &frame) == JB_OK) {
+ iax2_frame_free(frame.data);
+ }
+
+ jb_destroy(pvt->jb);
+ ast_string_field_free_memory(pvt);
+
+ while ((cur = AST_LIST_REMOVE_HEAD(&pvt->used_audio_q, pvt_q_entry))) {
+ iax2_frame_free(cur);
+ }
+ while ((cur = AST_LIST_REMOVE_HEAD(&pvt->audio_q, pvt_q_entry))) {
+ iax2_frame_free(cur);
}
}
@@ -1430,7 +1436,7 @@
tmp = NULL;
return NULL;
}
-
+
tmp->prefs = prefs;
tmp->pingid = -1;
tmp->lagid = -1;
@@ -1450,6 +1456,8 @@
jb_setconf(tmp->jb,&jbconf);
AST_LIST_HEAD_INIT_NOLOCK(&tmp->dpentries);
+ AST_LIST_HEAD_INIT_NOLOCK(&tmp->audio_q);
+ AST_LIST_HEAD_INIT_NOLOCK(&tmp->used_audio_q);
return tmp;
}
@@ -2078,25 +2086,42 @@
}
/*!
+ * \note called with call_num locked
+ */
+static void iax2_queue_audio(uint16_t call_num, struct iax_frame *fr)
+{
+ struct chan_iax2_pvt *pvt = iaxs[call_num];
+
+ ast_assert(pvt->owner != NULL);
+
+ AST_LIST_INSERT_TAIL(&pvt->audio_q, fr, pvt_q_entry);
+
+ while (AST_LIST_FIRST(&pvt->used_audio_q) &&
+ AST_LIST_NEXT(AST_LIST_FIRST(&pvt->used_audio_q), pvt_q_entry) &&
+ (fr = AST_LIST_REMOVE_HEAD(&pvt->used_audio_q, pvt_q_entry))) {
+ iax2_frame_free(fr);
+ }
+
+ ast_channel_alert(pvt->owner);
+}
+
+/*!
+ * Just deliver the packet by using queueing.
+ *
* \note This function assumes that iaxsl[callno] is locked when called.
- *
- * \note IMPORTANT NOTE!!! Any time this function is used, even if iaxs[callno]
- * was valid before calling it, it may no longer be valid after calling it.
- * This function calls iax2_queue_frame(), which may unlock and lock the mutex
- * associated with this callno, meaning that another thread may grab it and destroy the call.
*/
-static int __do_deliver(void *data)
-{
- /* Just deliver the packet by using queueing. This is called by
- the IAX thread with the iaxsl lock held. */
- struct iax_frame *fr = data;
+static int deliver_audio_frame(struct iax_frame *fr)
+{
fr->retrans = -1;
+
ast_clear_flag(&fr->af, AST_FRFLAG_HAS_TIMING_INFO);
- if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE))
- iax2_queue_frame(fr->callno, &fr->af);
- /* Free our iax frame */
- iax2_frame_free(fr);
- /* And don't run again */
+
+ if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE)) {
+ iax2_queue_audio(fr->callno, fr);
+ } else {
+ iax2_frame_free(fr);
+ }
+
return 0;
}
@@ -2852,29 +2877,28 @@
switch(ret) {
case JB_OK:
fr = frame.data;
- __do_deliver(fr);
- /* __do_deliver() can cause the call to disappear */
- pvt = iaxs[callno];
+ deliver_audio_frame(fr);
+ fr = NULL;
break;
case JB_INTERP:
{
- struct ast_frame af = { 0, };
-
+ struct iax_frame *iaxfr;
+
+ if (!(iaxfr = iax_frame_new(DIRECTION_INGRESS, 1024, 1))) {
+ break;
+ }
+
/* create an interpolation frame */
- af.frametype = AST_FRAME_VOICE;
- af.subclass = pvt->voiceformat;
- af.samples = frame.ms * 8;
- af.src = "IAX2 JB interpolation";
- af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000));
- af.offset = AST_FRIENDLY_OFFSET;
-
- /* queue the frame: For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame,
- * which we'd need to malloc, and then it would free it. That seems like a drag */
- if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) {
- iax2_queue_frame(callno, &af);
- /* iax2_queue_frame() could cause the call to disappear */
- pvt = iaxs[callno];
- }
+ /* XXX Umm ... setting number of samples but with no audio data? O.o */
+ iaxfr->af.frametype = AST_FRAME_VOICE;
+ iaxfr->af.subclass = pvt->voiceformat;
+ iaxfr->af.samples = frame.ms * 8;
+ iaxfr->af.src = "IAX2 JB interpolation";
+ iaxfr->af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000));
+ iaxfr->af.offset = AST_FRIENDLY_OFFSET;
+
+ deliver_audio_frame(iaxfr);
+ iaxfr = NULL;
}
break;
case JB_DROP:
@@ -2943,7 +2967,8 @@
if ( (!ast_test_flag(iaxs[fr->callno], IAX_USEJITTERBUF)) ) {
if (tsout)
*tsout = fr->ts;
- __do_deliver(fr);
+ deliver_audio_frame(fr);
+ fr = NULL;
return -1;
}
@@ -2957,10 +2982,7 @@
/* deliver any frames in the jb */
while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) {
- __do_deliver(frame.data);
- /* __do_deliver() can make the call disappear */
- if (!iaxs[fr->callno])
- return -1;
+ deliver_audio_frame(frame.data);
}
jb_reset(iaxs[fr->callno]->jb);
@@ -2970,7 +2992,8 @@
/* deliver this frame now */
if (tsout)
*tsout = fr->ts;
- __do_deliver(fr);
+ deliver_audio_frame(fr);
+ fr = NULL;
return -1;
}
@@ -3723,8 +3746,33 @@
static struct ast_frame *iax2_read(struct ast_channel *c)
{
- ast_log(LOG_NOTICE, "I should never be called!\n");
- return &ast_null_frame;
+ struct ast_frame *fr;
+ unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
+ struct iax_frame *iax_fr;
+ struct chan_iax2_pvt *pvt;
+
+ ast_mutex_lock(&iaxsl[callno]);
+
+ pvt = iaxs[callno];
+
+ ast_assert(pvt != NULL);
+ if (!pvt) {
+ ast_mutex_unlock(&iaxsl[callno]);
+ return &ast_null_frame;
+ }
+
+ if (!(iax_fr = AST_LIST_REMOVE_HEAD(&pvt->audio_q, pvt_q_entry))) {
+ ast_mutex_unlock(&iaxsl[callno]);
+ return &ast_null_frame;
+ }
+
+ fr = &iax_fr->af;
+
+ AST_LIST_INSERT_TAIL(&pvt->used_audio_q, iax_fr, pvt_q_entry);
+
+ ast_mutex_unlock(&iaxsl[callno]);
+
+ return fr;
}
static int iax2_start_transfer(unsigned short callno0, unsigned short callno1, int mediaonly)
@@ -7822,7 +7870,7 @@
struct iax_frame *duped_fr;
/* Common things */
- f.src = "IAX2";
+ f.src = "IAX2-1";
f.mallocd = 0;
f.offset = 0;
if (f.datalen && (f.frametype == AST_FRAME_VOICE))
@@ -7955,7 +8003,7 @@
/* allocate an iax_frame with 4096 bytes of data buffer */
fr = alloca(sizeof(*fr) + 4096);
- fr->callno = 0;
+ memset(fr, 0, sizeof(*fr));
fr->afdatalen = 4096; /* From alloca() above */
/* Copy frequently used parameters to the stack */
@@ -9465,7 +9513,7 @@
return 1;
}
/* Common things */
- f.src = "IAX2";
+ f.src = "IAX2-2";
f.mallocd = 0;
f.offset = 0;
f.len = 0;
Modified: team/russell/iax2_media/channels/iax2-parser.c
URL: http://svn.digium.com/view/asterisk/team/russell/iax2_media/channels/iax2-parser.c?view=diff&rev=116977&r1=116976&r2=116977
==============================================================================
--- team/russell/iax2_media/channels/iax2-parser.c (original)
+++ team/russell/iax2_media/channels/iax2-parser.c Sun May 18 22:40:31 2008
@@ -968,6 +968,7 @@
fr->af.delivery.tv_usec = 0;
fr->af.data = fr->afdata;
fr->af.len = f->len;
+ fr->af.flags = 0;
if (fr->af.datalen) {
size_t copy_len = fr->af.datalen;
if (copy_len > fr->afdatalen) {
@@ -999,7 +1000,7 @@
if (fr->afdatalen >= datalen) {
size_t afdatalen = fr->afdatalen;
AST_LIST_REMOVE_CURRENT(list);
- memset(fr, 0, sizeof(*fr));
+ memset(fr, 0, sizeof(*fr) + afdatalen);
fr->afdatalen = afdatalen;
break;
}
Modified: team/russell/iax2_media/channels/iax2-parser.h
URL: http://svn.digium.com/view/asterisk/team/russell/iax2_media/channels/iax2-parser.h?view=diff&rev=116977&r1=116976&r2=116977
==============================================================================
--- team/russell/iax2_media/channels/iax2-parser.h (original)
+++ team/russell/iax2_media/channels/iax2-parser.h Sun May 18 22:40:31 2008
@@ -125,6 +125,7 @@
int retrans;
/* Easy linking */
AST_LIST_ENTRY(iax_frame) list;
+ AST_LIST_ENTRY(iax_frame) pvt_q_entry;
/* Actual, isolated frame header */
struct ast_frame af;
/*! Amount of space _allocated_ for data */
Modified: team/russell/iax2_media/formats/format_pcm.c
URL: http://svn.digium.com/view/asterisk/team/russell/iax2_media/formats/format_pcm.c?view=diff&rev=116977&r1=116976&r2=116977
==============================================================================
--- team/russell/iax2_media/formats/format_pcm.c (original)
+++ team/russell/iax2_media/formats/format_pcm.c Sun May 18 22:40:31 2008
@@ -82,6 +82,7 @@
s->fr.frametype = AST_FRAME_VOICE;
s->fr.subclass = s->fmt->format;
s->fr.mallocd = 0;
+ s->fr.flags = 0;
AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE);
if ((res = fread(s->fr.data, 1, s->fr.datalen, s->f)) < 1) {
if (res)
Modified: team/russell/iax2_media/include/asterisk/channel.h
URL: http://svn.digium.com/view/asterisk/team/russell/iax2_media/include/asterisk/channel.h?view=diff&rev=116977&r1=116976&r2=116977
==============================================================================
--- team/russell/iax2_media/include/asterisk/channel.h (original)
+++ team/russell/iax2_media/include/asterisk/channel.h Sun May 18 22:40:31 2008
@@ -1636,6 +1636,7 @@
AST_LIST_ENTRY(ast_group_info) list;
};
+int ast_channel_alert(struct ast_channel *chan);
#if defined(__cplusplus) || defined(c_plusplus)
}
Modified: team/russell/iax2_media/include/asterisk/linkedlists.h
URL: http://svn.digium.com/view/asterisk/team/russell/iax2_media/include/asterisk/linkedlists.h?view=diff&rev=116977&r1=116976&r2=116977
==============================================================================
--- team/russell/iax2_media/include/asterisk/linkedlists.h (original)
+++ team/russell/iax2_media/include/asterisk/linkedlists.h Sun May 18 22:40:31 2008
@@ -762,8 +762,9 @@
if (cur) { \
(head)->first = cur->field.next; \
cur->field.next = NULL; \
- if ((head)->last == cur) \
+ if ((head)->last == cur) { \
(head)->last = NULL; \
+ } \
} \
cur; \
})
Modified: team/russell/iax2_media/main/channel.c
URL: http://svn.digium.com/view/asterisk/team/russell/iax2_media/main/channel.c?view=diff&rev=116977&r1=116976&r2=116977
==============================================================================
--- team/russell/iax2_media/main/channel.c (original)
+++ team/russell/iax2_media/main/channel.c Sun May 18 22:40:31 2008
@@ -956,7 +956,6 @@
{
struct ast_frame *f;
struct ast_frame *cur;
- int blah = 1;
int qlen = 0;
/* Build us a copy and free the original one */
@@ -991,17 +990,9 @@
}
}
AST_LIST_INSERT_TAIL(&chan->readq, f, frame_list);
- if (chan->alertpipe[1] > -1) {
- if (write(chan->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah))
- ast_log(LOG_WARNING, "Unable to write to alert pipe on %s, frametype/subclass %d/%d (qlen = %d): %s!\n",
- chan->name, f->frametype, f->subclass, qlen, strerror(errno));
-#ifdef HAVE_ZAPTEL
- } else if (chan->timingfd > -1) {
- ioctl(chan->timingfd, ZT_TIMERPING, &blah);
-#endif
- } else if (ast_test_flag(chan, AST_FLAG_BLOCKING)) {
- pthread_kill(chan->blocker, SIGURG);
- }
+
+ ast_channel_alert(chan);
+
ast_channel_unlock(chan);
return 0;
}
@@ -2456,6 +2447,7 @@
the channel driver and f would be only a single frame)
*/
if (AST_LIST_NEXT(f, frame_list)) {
+ ast_log(LOG_ERROR, "Got a frame with a next set?\n");
AST_LIST_HEAD_SET_NOLOCK(&chan->readq, AST_LIST_NEXT(f, frame_list));
AST_LIST_NEXT(f, frame_list) = NULL;
}
@@ -5115,3 +5107,27 @@
return ast_say_digit_str_full(chan, buf, ints, lang, audiofd, ctrlfd);
}
+
+int ast_channel_alert(struct ast_channel *chan)
+{
+ int res = 0;
+ int blah = 0;
+
+ if (chan->alertpipe[1] > -1) {
+ if (write(chan->alertpipe[1], &blah, sizeof(blah)) != sizeof(blah)) {
+ ast_channel_lock(chan);
+ ast_log(LOG_WARNING, "Unable to write to alert pipe on %s: %s!\n",
+ chan->name, strerror(errno));
+ ast_channel_unlock(chan);
+ res = -1;
+ }
+#ifdef HAVE_ZAPTEL
+ } else if (chan->timingfd > -1) {
+ ioctl(chan->timingfd, ZT_TIMERPING, &blah);
+#endif
+ } else if (ast_test_flag(chan, AST_FLAG_BLOCKING)) {
+ pthread_kill(chan->blocker, SIGURG);
+ }
+
+ return res;
+}
Modified: team/russell/iax2_media/main/sched.c
URL: http://svn.digium.com/view/asterisk/team/russell/iax2_media/main/sched.c?view=diff&rev=116977&r1=116976&r2=116977
==============================================================================
--- team/russell/iax2_media/main/sched.c (original)
+++ team/russell/iax2_media/main/sched.c Sun May 18 22:40:31 2008
@@ -373,7 +373,6 @@
if (!s) {
ast_debug(1, "Attempted to delete nonexistent schedule entry %d!\n", id);
- ast_assert(0);
return -1;
}
Modified: team/russell/iax2_media/main/slinfactory.c
URL: http://svn.digium.com/view/asterisk/team/russell/iax2_media/main/slinfactory.c?view=diff&rev=116977&r1=116976&r2=116977
==============================================================================
--- team/russell/iax2_media/main/slinfactory.c (original)
+++ team/russell/iax2_media/main/slinfactory.c Sun May 18 22:40:31 2008
@@ -31,6 +31,7 @@
#include "asterisk/frame.h"
#include "asterisk/slinfactory.h"
#include "asterisk/translate.h"
+#include "asterisk/utils.h"
/*!
* \brief Initialize an slinfactory
More information about the asterisk-commits
mailing list