diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 5b042a96d9938c63534e6b8f1251b09eee87160a..106117de15a20cdf55d91dbd085d5b5008ad95e7 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 567d8c62140d4ca50cf6c42cbf32cde1c7037b7c..a9f0fbb34298cab0a7bc77c363c622cf0dc01d5c 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -3420,6 +3420,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 ffdbf1821d54c9331f26474893a4eb73b6630440..458f2544627d5ac5f188c056a2de0917e179df3b 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));
 		}