summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/app_mixmonitor.c2
-rw-r--r--include/asterisk/audiohook.h3
-rw-r--r--main/audiohook.c49
3 files changed, 39 insertions, 15 deletions
diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c
index 012af01c5..066103b3b 100644
--- a/apps/app_mixmonitor.c
+++ b/apps/app_mixmonitor.c
@@ -253,7 +253,7 @@ static void launch_monitor_thread(struct ast_channel *chan, const char *filename
return;
}
- ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_WRITE);
+ ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_SYNC);
if (readvol)
mixmonitor->audiohook.options.read_volume = readvol;
diff --git a/include/asterisk/audiohook.h b/include/asterisk/audiohook.h
index 5ef0ac294..ba5d3b899 100644
--- a/include/asterisk/audiohook.h
+++ b/include/asterisk/audiohook.h
@@ -57,6 +57,7 @@ enum ast_audiohook_flags {
AST_AUDIOHOOK_TRIGGER_READ = (1 << 0), /*!< Audiohook wants to be triggered when reading audio in */
AST_AUDIOHOOK_TRIGGER_WRITE = (2 << 0), /*!< Audiohook wants to be triggered when writing audio out */
AST_AUDIOHOOK_WANTS_DTMF = (1 << 1), /*!< Audiohook also wants to receive DTMF frames */
+ AST_AUDIOHOOK_TRIGGER_SYNC = (1 << 2), /*!< Audiohook wants to be triggered when both sides have combined audio available */
};
struct ast_audiohook;
@@ -86,6 +87,8 @@ struct ast_audiohook {
unsigned int flags; /*!< Flags on the audiohook */
struct ast_slinfactory read_factory; /*!< Factory where frames read from the channel, or read from the whisper source will go through */
struct ast_slinfactory write_factory; /*!< Factory where frames written to the channel will go through */
+ struct timeval read_time; /*!< Last time read factory was fed */
+ struct timeval write_time; /*!< Last time write factory was fed */
int format; /*!< Format translation path is setup as */
struct ast_trans_pvt *trans_pvt; /*!< Translation path for reading frames */
ast_audiohook_manipulate_callback manipulate_callback; /*!< Manipulation callback */
diff --git a/main/audiohook.c b/main/audiohook.c
index a612e2067..5581037d7 100644
--- a/main/audiohook.c
+++ b/main/audiohook.c
@@ -121,22 +121,21 @@ int ast_audiohook_destroy(struct ast_audiohook *audiohook)
int ast_audiohook_write_frame(struct ast_audiohook *audiohook, enum ast_audiohook_direction direction, struct ast_frame *frame)
{
struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
+ struct timeval *time = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_time : &audiohook->write_time);
/* Write frame out to respective factory */
ast_slinfactory_feed(factory, frame);
+ /* Update last fed time for the above factory */
+ *time = ast_tvnow();
+
/* If we need to notify the respective handler of this audiohook, do so */
- switch (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_MODE)) {
- case AST_AUDIOHOOK_TRIGGER_READ:
- if (direction == AST_AUDIOHOOK_DIRECTION_READ)
- ast_cond_signal(&audiohook->trigger);
- break;
- case AST_AUDIOHOOK_TRIGGER_WRITE:
- if (direction == AST_AUDIOHOOK_DIRECTION_WRITE)
- ast_cond_signal(&audiohook->trigger);
- break;
- default:
- break;
+ if ((ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_MODE) == AST_AUDIOHOOK_TRIGGER_READ) && (direction == AST_AUDIOHOOK_DIRECTION_READ)) {
+ ast_cond_signal(&audiohook->trigger);
+ } else if ((ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_MODE) == AST_AUDIOHOOK_TRIGGER_WRITE) && (direction == AST_AUDIOHOOK_DIRECTION_WRITE)) {
+ ast_cond_signal(&audiohook->trigger);
+ } else if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC)) {
+ ast_cond_signal(&audiohook->trigger);
}
return 0;
@@ -172,7 +171,7 @@ static struct ast_frame *audiohook_read_frame_single(struct ast_audiohook *audio
static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audiohook, size_t samples)
{
- int i = 0;
+ int i = 0, usable_read, usable_write;
short buf1[samples], buf2[samples], *read_buf = NULL, *write_buf = NULL, *final_buf = NULL, *data1 = NULL, *data2 = NULL;
struct ast_frame frame = {
.frametype = AST_FRAME_VOICE,
@@ -182,8 +181,30 @@ static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audioho
.samples = samples,
};
+ /* Make sure both factories have the required samples */
+ usable_read = (ast_slinfactory_available(&audiohook->read_factory) >= samples ? 1 : 0);
+ usable_write = (ast_slinfactory_available(&audiohook->write_factory) >= samples ? 1 : 0);
+
+ if (!usable_read && !usable_write) {
+ /* If both factories are unusable bail out */
+ ast_debug(1, "Read factory %p and write factory %p both fail to provide %zd samples\n", &audiohook->read_factory, &audiohook->write_factory, samples);
+ return NULL;
+ }
+
+ /* If we want to provide only a read factory make sure we aren't waiting for other audio */
+ if (usable_read && !usable_write && (ast_tvdiff_ms(ast_tvnow(), audiohook->write_time) < (samples/8)*2)) {
+ ast_debug(1, "Write factory %p was pretty quick last time, waiting for them.\n", &audiohook->write_factory);
+ return NULL;
+ }
+
+ /* If we want to provide only a write factory make sure we aren't waiting for other audio */
+ if (usable_write && !usable_read && (ast_tvdiff_ms(ast_tvnow(), audiohook->write_time) < (samples/8)*2)) {
+ ast_debug(1, "Read factory %p was pretty quick last time, waiting for them.\n", &audiohook->read_factory);
+ return NULL;
+ }
+
/* Start with the read factory... if there are enough samples, read them in */
- if (ast_slinfactory_available(&audiohook->read_factory) >= samples) {
+ if (usable_read && ast_slinfactory_available(&audiohook->read_factory) >= samples) {
if (ast_slinfactory_read(&audiohook->read_factory, buf1, samples)) {
read_buf = buf1;
/* Adjust read volume if need be */
@@ -202,7 +223,7 @@ static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audioho
ast_log(LOG_DEBUG, "Failed to get %d samples from read factory %p\n", (int)samples, &audiohook->read_factory);
/* Move on to the write factory... if there are enough samples, read them in */
- if (ast_slinfactory_available(&audiohook->write_factory) >= samples) {
+ if (usable_write && ast_slinfactory_available(&audiohook->write_factory) >= samples) {
if (ast_slinfactory_read(&audiohook->write_factory, buf2, samples)) {
write_buf = buf2;
/* Adjust write volume if need be */