summaryrefslogtreecommitdiff
path: root/codecs
diff options
context:
space:
mode:
authorJonathan Rose <jrose@digium.com>2012-05-09 19:28:47 +0000
committerJonathan Rose <jrose@digium.com>2012-05-09 19:28:47 +0000
commit6f6af213833e0c4bcc33cc4de2d6b457d259687c (patch)
tree2ebfb067354b4fbc1b4b9cc52db6d4c4d4b8db1b /codecs
parent879f6417c6339228bfd66883ddf8f3bb5a921daf (diff)
Block on frameout if the hardware has enough samples to complete a frame.
Fixes some problems with skipping audio in elaborate scenarios involving multiple codecs by making codec_dahdi operate in a more synchronous fashion similar to codec_g729. This change also fixes the use of file conversion tools from Asterisk's CLI. This change may cause the thread responsible for transcoding audio to block briefly (Shaun Ruffell describes this as 'several milliseconds') while waiting for the hardware transcoder. (closes issue ASTERISK-19643) reported by: Shaun Ruffell Patches: 0001-codec_dahdi-Block-on-frameout-the-hardware-has-enoug.patch uploaded by Shaun Ruffell (license 5417) ........ Merged revisions 365989 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 365990 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@366007 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'codecs')
-rw-r--r--codecs/codec_dahdi.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/codecs/codec_dahdi.c b/codecs/codec_dahdi.c
index 442a101d1..c820cb0b4 100644
--- a/codecs/codec_dahdi.c
+++ b/codecs/codec_dahdi.c
@@ -55,6 +55,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define G723_SAMPLES 240
#define G729_SAMPLES 160
+#define ULAW_SAMPLES 160
#ifndef DAHDI_FORMAT_MAX_AUDIO
#define DAHDI_FORMAT_G723_1 (1 << 0)
@@ -102,6 +103,7 @@ struct codec_dahdi_pvt {
unsigned int fake:2;
uint16_t required_samples;
uint16_t samples_in_buffer;
+ uint16_t samples_written_to_hardware;
uint8_t ulaw_buffer[1024];
};
@@ -173,7 +175,6 @@ static char *handle_cli_transcoder_show(struct ast_cli_entry *e, int cmd, struct
static void dahdi_write_frame(struct codec_dahdi_pvt *dahdip, const uint8_t *buffer, const ssize_t count)
{
int res;
- struct pollfd p = {0};
if (!count) return;
res = write(dahdip->fd, buffer, count);
if (-1 == res) {
@@ -182,9 +183,6 @@ static void dahdi_write_frame(struct codec_dahdi_pvt *dahdip, const uint8_t *buf
if (count != res) {
ast_log(LOG_ERROR, "Requested write of %zd bytes, but only wrote %d bytes.\n", count, res);
}
- p.fd = dahdip->fd;
- p.events = POLLOUT;
- res = poll(&p, 1, 50);
}
static int dahdi_encoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
@@ -217,8 +215,9 @@ static int dahdi_encoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
dahdip->samples_in_buffer += f->samples;
}
- while (dahdip->samples_in_buffer > dahdip->required_samples) {
+ while (dahdip->samples_in_buffer >= dahdip->required_samples) {
dahdi_write_frame(dahdip, dahdip->ulaw_buffer, dahdip->required_samples);
+ dahdip->samples_written_to_hardware += dahdip->required_samples;
dahdip->samples_in_buffer -= dahdip->required_samples;
if (dahdip->samples_in_buffer) {
/* Shift any remaining bytes down. */
@@ -231,6 +230,14 @@ static int dahdi_encoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
return -1;
}
+static void dahdi_wait_for_packet(int fd)
+{
+ struct pollfd p = {0};
+ p.fd = fd;
+ p.events = POLLIN;
+ poll(&p, 1, 10);
+}
+
static struct ast_frame *dahdi_encoder_frameout(struct ast_trans_pvt *pvt)
{
struct codec_dahdi_pvt *dahdip = pvt->pvt;
@@ -254,6 +261,10 @@ static struct ast_frame *dahdi_encoder_frameout(struct ast_trans_pvt *pvt)
return NULL;
}
+ if (dahdip->samples_written_to_hardware >= dahdip->required_samples) {
+ dahdi_wait_for_packet(dahdip->fd);
+ }
+
res = read(dahdip->fd, pvt->outbuf.c + pvt->datalen, pvt->t->buf_size - pvt->datalen);
if (-1 == res) {
if (EWOULDBLOCK == errno) {
@@ -273,6 +284,10 @@ static struct ast_frame *dahdi_encoder_frameout(struct ast_trans_pvt *pvt)
pvt->f.data.ptr = pvt->outbuf.c;
pvt->f.samples = ast_codec_get_samples(&pvt->f);
+ dahdip->samples_written_to_hardware =
+ (dahdip->samples_written_to_hardware >= pvt->f.samples) ?
+ dahdip->samples_written_to_hardware - pvt->f.samples : 0;
+
pvt->samples = 0;
pvt->datalen = 0;
return ast_frisolate(&pvt->f);
@@ -299,6 +314,7 @@ static int dahdi_decoder_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
}
}
dahdi_write_frame(dahdip, f->data.ptr, f->datalen);
+ dahdip->samples_written_to_hardware += f->samples;
pvt->samples += f->samples;
pvt->datalen = 0;
return -1;
@@ -326,6 +342,10 @@ static struct ast_frame *dahdi_decoder_frameout(struct ast_trans_pvt *pvt)
return NULL;
}
+ if (dahdip->samples_written_to_hardware >= ULAW_SAMPLES) {
+ dahdi_wait_for_packet(dahdip->fd);
+ }
+
/* Let's check to see if there is a new frame for us.... */
if (dahdip->softslin) {
res = read(dahdip->fd, dahdip->ulaw_buffer, sizeof(dahdip->ulaw_buffer));
@@ -357,6 +377,9 @@ static struct ast_frame *dahdi_decoder_frameout(struct ast_trans_pvt *pvt)
pvt->f.data.ptr = pvt->outbuf.c;
pvt->f.samples = res;
pvt->samples = 0;
+ dahdip->samples_written_to_hardware =
+ (dahdip->samples_written_to_hardware >= res) ?
+ dahdip->samples_written_to_hardware - res : 0;
return ast_frisolate(&pvt->f);
}