summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/asterisk/channel.h5
-rw-r--r--main/channel.c24
-rw-r--r--main/file.c2
3 files changed, 30 insertions, 1 deletions
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 5b042a96d..106117de1 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -929,6 +929,10 @@ enum {
* publish.
*/
AST_FLAG_SNAPSHOT_STAGE = (1 << 25),
+ /*!
+ * The data on chan->timingdata is an astobj2 object.
+ */
+ AST_FLAG_TIMINGDATA_IS_AO2_OBJ = (1 << 26),
};
/*! \brief ast_bridge_config flags */
@@ -2275,6 +2279,7 @@ int ast_autoservice_ignore(struct ast_channel *chan, enum ast_frame_type ftype);
* \version 1.6.1 changed samples parameter to rate, accomodates new timing methods
*/
int ast_settimeout(struct ast_channel *c, unsigned int rate, int (*func)(const void *data), void *data);
+int ast_settimeout_full(struct ast_channel *c, unsigned int rate, int (*func)(const void *data), void *data, unsigned int is_ao2_obj);
/*!
* \brief Transfer a channel (if supported).
diff --git a/main/channel.c b/main/channel.c
index 567d8c621..a9f0fbb34 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -3421,6 +3421,11 @@ int ast_waitfordigit(struct ast_channel *c, int ms)
int ast_settimeout(struct ast_channel *c, unsigned int rate, int (*func)(const void *data), void *data)
{
+ return ast_settimeout_full(c, rate, func, data, 0);
+}
+
+int ast_settimeout_full(struct ast_channel *c, unsigned int rate, int (*func)(const void *data), void *data, unsigned int is_ao2_obj)
+{
int res;
unsigned int real_rate = rate, max_rate;
@@ -3444,9 +3449,20 @@ int ast_settimeout(struct ast_channel *c, unsigned int rate, int (*func)(const v
res = ast_timer_set_rate(ast_channel_timer(c), real_rate);
+ if (ast_channel_timingdata(c) && ast_test_flag(ast_channel_flags(c), AST_FLAG_TIMINGDATA_IS_AO2_OBJ)) {
+ ao2_ref(ast_channel_timingdata(c), -1);
+ }
+
ast_channel_timingfunc_set(c, func);
ast_channel_timingdata_set(c, data);
+ if (data && is_ao2_obj) {
+ ao2_ref(data, 1);
+ ast_set_flag(ast_channel_flags(c), AST_FLAG_TIMINGDATA_IS_AO2_OBJ);
+ } else {
+ ast_clear_flag(ast_channel_flags(c), AST_FLAG_TIMINGDATA_IS_AO2_OBJ);
+ }
+
if (func == NULL && rate == 0 && ast_channel_fdno(c) == AST_TIMING_FD) {
/* Clearing the timing func and setting the rate to 0
* means that we don't want to be reading from the timingfd
@@ -3795,9 +3811,17 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
/* save a copy of func/data before unlocking the channel */
ast_timing_func_t func = ast_channel_timingfunc(chan);
void *data = ast_channel_timingdata(chan);
+ int got_ref = 0;
+ if (data && ast_test_flag(ast_channel_flags(chan), AST_FLAG_TIMINGDATA_IS_AO2_OBJ)) {
+ ao2_ref(data, 1);
+ got_ref = 1;
+ }
ast_channel_fdno_set(chan, -1);
ast_channel_unlock(chan);
func(data);
+ if (got_ref) {
+ ao2_ref(data, -1);
+ }
} else {
ast_timer_set_rate(ast_channel_timer(chan), 0);
ast_channel_fdno_set(chan, -1);
diff --git a/main/file.c b/main/file.c
index ffdbf1821..458f25446 100644
--- a/main/file.c
+++ b/main/file.c
@@ -902,7 +902,7 @@ static enum fsread_res ast_readaudio_callback(struct ast_filestream *s)
rate = (unsigned int) roundf(samp_rate / ((float) whennext));
- ast_settimeout(s->owner, rate, ast_fsread_audio, s);
+ ast_settimeout_full(s->owner, rate, ast_fsread_audio, s, 1);
} else {
ast_channel_streamid_set(s->owner, ast_sched_add(ast_channel_sched(s->owner), whennext / (ast_format_rate(&s->fmt->format) / 1000), ast_fsread_audio, s));
}