aboutsummaryrefslogtreecommitdiffstats
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/channel.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/main/channel.c b/main/channel.c
index cb0c9f287..1ac9f3d5d 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -41,6 +41,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
+#include "asterisk/mod_format.h"
#include "asterisk/sched.h"
#include "asterisk/channel.h"
#include "asterisk/musiconhold.h"
@@ -2587,6 +2588,28 @@ static inline int should_skip_dtmf(struct ast_channel *chan)
return 0;
}
+/*!
+ * \brief calculates the number of samples to jump forward with in a monitor stream.
+
+ * \note When using ast_seekstream() with the read and write streams of a monitor,
+ * the number of samples to seek forward must be of the same sample rate as the stream
+ * or else the jump will not be calculated correctly.
+ *
+ * \retval number of samples to seek forward after rate conversion.
+ */
+static inline int calc_monitor_jump(int samples, int sample_rate, int seek_rate)
+{
+ int diff = sample_rate - seek_rate;
+
+ if (diff > 0) {
+ samples = samples / (float) (sample_rate / seek_rate);
+ } else if (diff < 0) {
+ samples = samples * (float) (seek_rate / sample_rate);
+ }
+
+ return samples;
+}
+
static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
{
struct ast_frame *f = NULL; /* the return value */
@@ -2976,18 +2999,18 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
#ifndef MONITOR_CONSTANT_DELAY
int jump = chan->outsmpl - chan->insmpl - 4 * f->samples;
if (jump >= 0) {
- jump = chan->outsmpl - chan->insmpl;
+ jump = calc_monitor_jump((chan->outsmpl - chan->insmpl), ast_format_rate(f->subclass), ast_format_rate(chan->monitor->read_stream->fmt->format));
if (ast_seekstream(chan->monitor->read_stream, jump, SEEK_FORCECUR) == -1)
ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
- chan->insmpl += jump + f->samples;
+ chan->insmpl += (chan->outsmpl - chan->insmpl) + f->samples;
} else
chan->insmpl+= f->samples;
#else
- int jump = chan->outsmpl - chan->insmpl;
+ int jump = calc_monitor_jump((chan->outsmpl - chan->insmpl), ast_format_rate(f->subclass), ast_format_rate(chan->monitor->read_stream->fmt->format));
if (jump - MONITOR_DELAY >= 0) {
if (ast_seekstream(chan->monitor->read_stream, jump - f->samples, SEEK_FORCECUR) == -1)
ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
- chan->insmpl += jump;
+ chan->insmpl += chan->outsmpl - chan->insmpl;
} else
chan->insmpl += f->samples;
#endif
@@ -3544,19 +3567,19 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
#ifndef MONITOR_CONSTANT_DELAY
int jump = chan->insmpl - chan->outsmpl - 4 * cur->samples;
if (jump >= 0) {
- jump = chan->insmpl - chan->outsmpl;
+ jump = calc_monitor_jump((chan->insmpl - chan->outsmpl), ast_format_rate(f->subclass), ast_format_rate(chan->monitor->read_stream->fmt->format));
if (ast_seekstream(chan->monitor->write_stream, jump, SEEK_FORCECUR) == -1)
ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
- chan->outsmpl += jump + cur->samples;
+ chan->outsmpl += (chan->insmpl - chan->outsmpl) + cur->samples;
} else {
chan->outsmpl += cur->samples;
}
#else
- int jump = chan->insmpl - chan->outsmpl;
+ int jump = calc_monitor_jump((chan->insmpl - chan->outsmpl), ast_format_rate(f->subclass), ast_format_rate(chan->monitor->read_stream->fmt->format));
if (jump - MONITOR_DELAY >= 0) {
if (ast_seekstream(chan->monitor->write_stream, jump - cur->samples, SEEK_FORCECUR) == -1)
ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");
- chan->outsmpl += jump;
+ chan->outsmpl += chan->insmpl - chan->outsmpl;
} else {
chan->outsmpl += cur->samples;
}