From f575dc12821eb33c950cd996bb9a8609d11a3218 Mon Sep 17 00:00:00 2001 From: russell Date: Tue, 22 Apr 2008 21:14:55 +0000 Subject: [PATCH] I thought I was going to be able to leave 1.4 alone, but that was not the case. I ran into some problems with G.722 in 1.4, so I have merged in all of the fixes in this area that I have made in trunk/1.6.0, and things are happy again. git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@114550 614ede4d-c843-0410-af14-a771ab80d22e --- formats/format_pcm.c | 24 +++++++++++++++++------- main/channel.c | 14 ++++++++++++-- main/file.c | 21 ++++++++++++++++----- main/rtp.c | 19 +++++++++++++++---- 4 files changed, 60 insertions(+), 18 deletions(-) diff --git a/formats/format_pcm.c b/formats/format_pcm.c index 6facfcdcc..7b186e602 100644 --- a/formats/format_pcm.c +++ b/formats/format_pcm.c @@ -102,7 +102,10 @@ static struct ast_frame *pcm_read(struct ast_filestream *s, int *whennext) return NULL; } s->fr.datalen = res; - *whennext = s->fr.samples = res; + if (s->fmt->format == AST_FORMAT_G722) + *whennext = s->fr.samples = res * 2; + else + *whennext = s->fr.samples = res; return &s->fr; } @@ -380,24 +383,31 @@ static int au_rewrite(struct ast_filestream *s, const char *comment) static int au_seek(struct ast_filestream *fs, off_t sample_offset, int whence) { off_t min, max, cur; - long offset = 0, samples; - - samples = sample_offset; + long offset = 0, bytes; + + if (fs->fmt->format == AST_FORMAT_G722) + bytes = sample_offset / 2; + else + bytes = sample_offset; + min = AU_HEADER_SIZE; cur = ftello(fs->f); fseek(fs->f, 0, SEEK_END); max = ftello(fs->f); + if (whence == SEEK_SET) - offset = samples + min; + offset = bytes + min; else if (whence == SEEK_CUR || whence == SEEK_FORCECUR) - offset = samples + cur; + offset = bytes + cur; else if (whence == SEEK_END) - offset = max - samples; + offset = max - bytes; if (whence != SEEK_FORCECUR) { offset = (offset > max) ? max : offset; } + /* always protect the header space. */ offset = (offset < min) ? min : offset; + return fseeko(fs->f, offset, SEEK_SET); } diff --git a/main/channel.c b/main/channel.c index 91dd940c7..f61d365b7 100644 --- a/main/channel.c +++ b/main/channel.c @@ -1573,7 +1573,7 @@ static int generator_force(const void *data) if (!tmp || !generate) return 0; - res = generate(chan, tmp, 0, 160); + res = generate(chan, tmp, 0, ast_format_rate(chan->writeformat & AST_FORMAT_AUDIO_MASK) / 50); chan->generatordata = tmp; @@ -1889,6 +1889,7 @@ static void ast_read_generator_actions(struct ast_channel *chan, struct ast_fram void *tmp = chan->generatordata; int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples) = NULL; int res; + int samples; if (chan->timingfunc) { if (option_debug > 1) @@ -1897,6 +1898,15 @@ static void ast_read_generator_actions(struct ast_channel *chan, struct ast_fram } chan->generatordata = NULL; /* reset, to let writes go through */ + + if (f->subclass != chan->writeformat) { + float factor; + factor = ((float) ast_format_rate(chan->writeformat)) / ((float) ast_format_rate(f->subclass)); + samples = (int) ( ((float) f->samples) * factor ); + } else { + samples = f->samples; + } + if (chan->generator->generate) { generate = chan->generator->generate; } @@ -1909,7 +1919,7 @@ static void ast_read_generator_actions(struct ast_channel *chan, struct ast_fram * avoidance not to work in deeper functions */ ast_channel_unlock(chan); - res = generate(chan, tmp, f->datalen, f->samples); + res = generate(chan, tmp, f->datalen, samples); ast_channel_lock(chan); chan->generatordata = tmp; if (res) { diff --git a/main/file.c b/main/file.c index c44941b2b..340eb4ee3 100644 --- a/main/file.c +++ b/main/file.c @@ -680,11 +680,21 @@ static enum fsread_res ast_readaudio_callback(struct ast_filestream *s) } if (whennext != s->lasttimeout) { #ifdef HAVE_ZAPTEL - if (s->owner->timingfd > -1) - ast_settimeout(s->owner, whennext, ast_fsread_audio, s); - else + if (s->owner->timingfd > -1) { + int zap_timer_samples = whennext; + int rate; + /* whennext is in samples, but zaptel timers operate in 8 kHz samples. */ + if ((rate = ast_format_rate(s->fmt->format)) != 8000) { + float factor; + factor = ((float) rate) / ((float) 8000.0); + zap_timer_samples = (int) ( ((float) zap_timer_samples) / factor ); + } + ast_settimeout(s->owner, zap_timer_samples, ast_fsread_audio, s); + } else #endif - s->owner->streamid = ast_sched_add(s->owner->sched, whennext/8, ast_fsread_audio, s); + s->owner->streamid = ast_sched_add(s->owner->sched, + whennext / (ast_format_rate(s->fmt->format) / 1000), + ast_fsread_audio, s); s->lasttimeout = whennext; return FSREAD_SUCCESS_NOSCHED; } @@ -728,7 +738,8 @@ static enum fsread_res ast_readvideo_callback(struct ast_filestream *s) } if (whennext != s->lasttimeout) { - s->owner->vstreamid = ast_sched_add(s->owner->sched, whennext / 8, + s->owner->vstreamid = ast_sched_add(s->owner->sched, + whennext / (ast_format_rate(s->fmt->format) / 1000), ast_fsread_video, s); s->lasttimeout = whennext; return FSREAD_SUCCESS_NOSCHED; diff --git a/main/rtp.c b/main/rtp.c index 3621d3610..658bd0891 100644 --- a/main/rtp.c +++ b/main/rtp.c @@ -1313,7 +1313,7 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp) /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ ast_set_flag(&rtp->f, AST_FRFLAG_HAS_TIMING_INFO); rtp->f.ts = timestamp / 8; - rtp->f.len = rtp->f.samples / ( (ast_format_rate(rtp->f.subclass) == 16000) ? 16 : 8 ); + rtp->f.len = rtp->f.samples / (ast_format_rate(rtp->f.subclass) / 1000); } else { /* Video -- samples is # of samples vs. 90000 */ if (!rtp->lastividtimestamp) @@ -2795,17 +2795,28 @@ int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *_f) ast_smoother_feed(rtp->smoother, _f); } - while((f = ast_smoother_read(rtp->smoother)) && (f->data)) + while ((f = ast_smoother_read(rtp->smoother)) && (f->data)) { + if (f->subclass == AST_FORMAT_G722) { + /* G.722 is silllllllllllllly */ + f->samples /= 2; + } + ast_rtp_raw_write(rtp, f, codec); + } } else { - /* Don't buffer outgoing frames; send them one-per-packet: */ + /* Don't buffer outgoing frames; send them one-per-packet: */ if (_f->offset < hdrlen) { f = ast_frdup(_f); } else { f = _f; } - if (f->data) + if (f->data) { + if (f->subclass == AST_FORMAT_G722) { + /* G.722 is silllllllllllllly */ + f->samples /= 2; + } ast_rtp_raw_write(rtp, f, codec); + } if (f != _f) ast_frfree(f); } -- 2.11.4.GIT