diff --git a/codecs/codec_dahdi.c b/codecs/codec_dahdi.c index 442a101d1bd22ebdd48e8d87a9152b4c268a654e..c820cb0b42f23b3aa3e7aa16f34cdcb22d76be83 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); }