--- asterisk-11.5.0.o/formats/format_g729.c 2012-04-29 21:50:57.000000000 +0200 +++ asterisk-11.5.0/formats/format_g729.c 2013-08-07 21:10:51.760016214 +0200 @@ -42,9 +42,16 @@ /* Portions of the conversion code are by guido@sienanet.it */ -#define BUF_SIZE 20 /* two G729 frames */ +#define G729A_FRAME_SIZE 10 +#define BUF_SIZE (G729A_FRAME_SIZE * 2) /* two G729 frames */ +#define G729A_CNG_SIZE 2 #define G729A_SAMPLES 160 +struct ast_g729_pvt +{ + int detected_vad; /* simple flag indicating whether or not we detected and reported on VAD on this stream yet or not */ +}; + static struct ast_frame *g729_read(struct ast_filestream *s, int *whennext) { int res; @@ -55,7 +62,7 @@ s->fr.samples = G729A_SAMPLES; AST_FRAME_SET_BUFFER(&s->fr, s->buf, AST_FRIENDLY_OFFSET, BUF_SIZE); if ((res = fread(s->fr.data.ptr, 1, s->fr.datalen, s->f)) != s->fr.datalen) { - if (res && (res != 10)) /* XXX what for ? */ + if (res && (res != G729A_FRAME_SIZE)) /* XXX what for ? */ ast_log(LOG_WARNING, "Short read (%d) (%s)!\n", res, strerror(errno)); return NULL; } @@ -65,7 +72,8 @@ static int g729_write(struct ast_filestream *fs, struct ast_frame *f) { - int res; + struct ast_g729_pvt* pvt = fs->_private; + int res, writelen = f->datalen; if (f->frametype != AST_FRAME_VOICE) { ast_log(LOG_WARNING, "Asked to write non-voice frame!\n"); return -1; @@ -74,12 +82,20 @@ ast_log(LOG_WARNING, "Asked to write non-G729 frame (%s)!\n", ast_getformatname(&f->subclass.format)); return -1; } - if (f->datalen % 10) { - ast_log(LOG_WARNING, "Invalid data length, %d, should be multiple of 10\n", f->datalen); + if (f->datalen % G729A_FRAME_SIZE) { + if (f->datalen % G729A_FRAME_SIZE == G729A_CNG_SIZE) { + writelen -= G729A_CNG_SIZE; + if (!pvt->detected_vad) { + ast_log(LOG_WARNING, "Probable CNG parameter update detected, this is a bug in the sender who should not be sending CNG updates - try and switch off Voice Activity Detected (VAD) or Silence Suppression on the sender.\n"); + pvt->detected_vad = 1; + } + } else { + ast_log(LOG_WARNING, "Invalid data length, %d, should be multiple of %d\n", f->datalen, G729A_FRAME_SIZE); return -1; } - if ((res = fwrite(f->data.ptr, 1, f->datalen, fs->f)) != f->datalen) { - ast_log(LOG_WARNING, "Bad write (%d/10): %s\n", res, strerror(errno)); + } + if ((res = fwrite(f->data.ptr, 1, writelen, fs->f)) != writelen) { + ast_log(LOG_WARNING, "Bad write (%d/%d): %s\n", res, writelen, strerror(errno)); return -1; } return 0; @@ -143,6 +159,7 @@ .tell = g729_tell, .read = g729_read, .buf_size = BUF_SIZE + AST_FRIENDLY_OFFSET, + .desc_size = sizeof(struct ast_g729_pvt), }; static int load_module(void)