summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Walton <mike@farsouthnet.com>2016-10-05 14:46:17 +1300
committerMichael Walton <mike@farsouthnet.com>2016-10-05 15:41:41 +1300
commit430f6e5388b6e18b31e1a08582112838f6cc7557 (patch)
treec1e2c6083a63fd15459e621854a372f92f194f6e
parentb0b106a473dcfe4c26ffd79908b7c4f1794f8987 (diff)
audiohooks: Remove redundant codec translations when using audiohooks
The main frame read and write handlers in main/channel.c don't use the optimum placement in the processing flow for calling audiohooks callbacks, as far as codec translation is concerned. This change places the audiohooks callback code: * After the channel read translation if the frame is not linear before the translation, thereby increasing the chance that the frame is linear as required by audiohooks * Before the channel write translation if the frame is linear at this point This prevents the audiohooks code from instantiating additional translation paths to/from linear where a linear frame format is already available, saving valuable CPU cycles ASTERISK-26419 Change-Id: I6edd5771f0740e758e7eb42558b953f046c01f8f
-rw-r--r--main/channel.c41
1 files changed, 38 insertions, 3 deletions
diff --git a/main/channel.c b/main/channel.c
index f3f79399f..c6cb925b8 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -3914,6 +3914,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
struct ast_frame *readq_tail = AST_LIST_LAST(ast_channel_readq(chan));
struct ast_control_read_action_payload *read_action_payload;
struct ast_party_connected_line connected;
+ int hooked = 0;
/* if the channel driver returned more than one frame, stuff the excess
into the readq for the next ast_read call
@@ -4191,15 +4192,22 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
break;
}
}
- /* Send frame to audiohooks if present */
- if (ast_channel_audiohooks(chan)) {
+ /*
+ * Send frame to audiohooks if present, if frametype is linear, to preserve
+ * functional compatibility with previous behavior. If not linear, hold off
+ * until transcoding is done where we are more likely to have a linear frame
+ */
+ if (ast_channel_audiohooks(chan) && ast_format_cache_is_slinear(f->subclass.format)) {
+ /* Place hooked after declaration */
struct ast_frame *old_frame = f;
+ hooked = 1;
f = ast_audiohook_write_list(chan, ast_channel_audiohooks(chan), AST_AUDIOHOOK_DIRECTION_READ, f);
if (old_frame != f) {
ast_frfree(old_frame);
}
}
+
if (ast_channel_monitor(chan) && ast_channel_monitor(chan)->read_stream) {
/* XXX what does this do ? */
#ifndef MONITOR_CONSTANT_DELAY
@@ -4242,6 +4250,16 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
}
}
+ /* Second chance at hooking a linear frame, also the last chance */
+ if (ast_channel_audiohooks(chan) && !hooked) {
+ struct ast_frame *old_frame = f;
+
+ f = ast_audiohook_write_list(chan, ast_channel_audiohooks(chan), AST_AUDIOHOOK_DIRECTION_READ, f);
+ if (old_frame != f) {
+ ast_frfree(old_frame);
+ }
+ }
+
/*
* It is possible for the translation process on the channel to have
* produced multiple frames from the single input frame we passed it; if
@@ -5032,6 +5050,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
int res = -1;
struct ast_frame *f = NULL;
int count = 0;
+ int hooked = 0;
/*Deadlock avoidance*/
while(ast_channel_trylock(chan)) {
@@ -5149,6 +5168,22 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
apply_plc(chan, fr);
}
+ /*
+ * Send frame to audiohooks if present, if frametype is linear (else, later as per
+ * previous behavior)
+ */
+ if (ast_channel_audiohooks(chan)) {
+ if (ast_format_cache_is_slinear(fr->subclass.format)) {
+ struct ast_frame *old_frame;
+ hooked = 1;
+ old_frame = fr;
+ fr = ast_audiohook_write_list(chan, ast_channel_audiohooks(chan), AST_AUDIOHOOK_DIRECTION_WRITE, fr);
+ if (old_frame != fr) {
+ ast_frfree(old_frame);
+ }
+ }
+ }
+
/* If the frame is in the raw write format, then it's easy... just use the frame - otherwise we will have to translate */
if (ast_format_cmp(fr->subclass.format, ast_channel_rawwriteformat(chan)) == AST_FORMAT_CMP_EQUAL) {
f = fr;
@@ -5186,7 +5221,7 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
break;
}
- if (ast_channel_audiohooks(chan)) {
+ if (ast_channel_audiohooks(chan) && !hooked) {
struct ast_frame *prev = NULL, *new_frame, *cur, *dup;
int freeoldlist = 0;