Index: channels/chan_iax2.c =================================================================== --- channels/chan_iax2.c (revision 94396) +++ channels/chan_iax2.c (working copy) @@ -1935,7 +1935,7 @@ the IAX thread with the iaxsl lock held. */ struct iax_frame *fr = data; fr->retrans = -1; - fr->af.has_timing_info = 0; + fr->af.flags &= ~AST_FRFLAG_HAS_TIMING_INFO; if (iaxs[fr->callno] && !ast_test_flag(iaxs[fr->callno], IAX_ALREADYGONE)) iax2_queue_frame(fr->callno, &fr->af); /* Free our iax frame */ Index: include/asterisk/frame.h =================================================================== --- include/asterisk/frame.h (revision 94396) +++ include/asterisk/frame.h (working copy) @@ -122,6 +122,16 @@ }; #define AST_FRAME_DTMF AST_FRAME_DTMF_END +/* Frame contains timing information */ +#define AST_FRFLAG_HAS_TIMING_INFO 1 +/* Frame was already read from ast_read. Autoservice sets this flag + * on all frames it queues back to the channel to make sure ast_read + * won't do any special processing (like DTMF emulation) based on this + * frame. This is because the frame itself can be already a rusult + * of such a processing + */ +#define AST_FRFLAG_READ 2 + /*! \brief Data structure associated with a single frame of data */ struct ast_frame { @@ -147,8 +157,8 @@ struct timeval delivery; /*! For placing in a linked list */ AST_LIST_ENTRY(ast_frame) frame_list; - /*! Timing data flag */ - int has_timing_info; + /*! Frame flags */ + int flags; /*! Timestamp in milliseconds */ long ts; /*! Length in milliseconds */ Index: main/channel.c =================================================================== --- main/channel.c (revision 94396) +++ main/channel.c (working copy) @@ -2231,6 +2231,17 @@ ast_frfree(f); f = NULL; } + + if (f->flags & AST_FRFLAG_READ) { + /* This frame was already read from us by autoservice so we do not need + do any processing on it because it may be actually a result of + such a processing (emulated DTMF_BEGIN for example). + However, reset AST_FRFLAG_READ to make sure the frame may be queued to another + channel and read from there with all necessary processing */ + f->flags &= ~AST_FRFLAG_READ; + goto done; + } + } else { chan->blocker = pthread_self(); if (ast_test_flag(chan, AST_FLAG_EXCEPTION)) { Index: main/translate.c =================================================================== --- main/translate.c (revision 94396) +++ main/translate.c (working copy) @@ -147,7 +147,7 @@ int samples = pvt->samples; /* initial value */ /* Copy the last in jb timing info to the pvt */ - pvt->f.has_timing_info = f->has_timing_info; + pvt->f.flags = f->flags; pvt->f.ts = f->ts; pvt->f.len = f->len; pvt->f.seqno = f->seqno; @@ -290,12 +290,12 @@ struct ast_trans_pvt *p = path; struct ast_frame *out = f; struct timeval delivery; - int has_timing_info; + int flags; long ts; long len; int seqno; - has_timing_info = f->has_timing_info; + flags = f->flags; ts = f->ts; len = f->len; seqno = f->seqno; @@ -345,8 +345,8 @@ path->nextout = ast_tvadd(path->nextout, ast_samp2tv( out->samples, 8000)); } else { out->delivery = ast_tv(0, 0); - out->has_timing_info = has_timing_info; - if (has_timing_info) { + out->flags = flags; + if (flags & AST_FRFLAG_HAS_TIMING_INFO) { out->ts = ts; out->len = len; out->seqno = seqno; Index: main/rtp.c =================================================================== --- main/rtp.c (revision 94396) +++ main/rtp.c (working copy) @@ -1579,7 +1579,7 @@ ast_frame_byteswap_be(&rtp->f); calc_rxstamp(&rtp->f.delivery, rtp, timestamp, mark); /* Add timing data to let ast_generic_bridge() put the frame into a jitterbuf */ - rtp->f.has_timing_info = 1; + rtp->f.flags |= AST_FRFLAG_HAS_TIMING_INFO; rtp->f.ts = timestamp / 8; rtp->f.len = rtp->f.samples / 8; } else if(rtp->f.subclass & AST_FORMAT_VIDEO_MASK) { @@ -3024,7 +3024,7 @@ if (rtp->lastts > rtp->lastdigitts) rtp->lastdigitts = rtp->lastts; - if (f->has_timing_info) + if (f->flags & AST_FRFLAG_HAS_TIMING_INFO) rtp->lastts = f->ts * 8; /* Get a pointer to the header */ Index: main/abstract_jb.c =================================================================== --- main/abstract_jb.c (revision 94396) +++ main/abstract_jb.c (working copy) @@ -312,10 +312,10 @@ } /* We consider an enabled jitterbuffer should receive frames with valid timing info. */ - if (!f->has_timing_info || f->len < 2 || f->ts < 0) { + if (!(f->flags & AST_FRFLAG_HAS_TIMING_INFO) || f->len < 2 || f->ts < 0) { ast_log(LOG_WARNING, "%s received frame with invalid timing info: " "has_timing_info=%d, len=%ld, ts=%ld, src=%s\n", - chan->name, f->has_timing_info, f->len, f->ts, f->src); + chan->name, (f->flags & AST_FRFLAG_HAS_TIMING_INFO) != 0, f->len, f->ts, f->src); return -1; } Index: main/autoservice.c =================================================================== --- main/autoservice.c (revision 94396) +++ main/autoservice.c (working copy) @@ -229,6 +229,9 @@ usleep(1000); while ((f = AST_LIST_REMOVE_HEAD(&dtmf_frames, frame_list))) { + /* Mark frame as already read so ast_read will not do any + additional processing (like DTMF emulation) with it */ + f->flags |= AST_FRFLAG_READ; ast_queue_frame(chan, f); ast_frfree(f); } Index: main/frame.c =================================================================== --- main/frame.c (revision 94396) +++ main/frame.c (working copy) @@ -377,9 +377,9 @@ out->samples = fr->samples; out->offset = fr->offset; out->data = fr->data; + out->flags = fr->flags; /* Copy the timing data */ - out->has_timing_info = fr->has_timing_info; - if (fr->has_timing_info) { + if (fr->flags & AST_FRFLAG_HAS_TIMING_INFO) { out->ts = fr->ts; out->len = fr->len; out->seqno = fr->seqno; @@ -483,7 +483,7 @@ /* Must have space since we allocated for it */ strcpy((char *)out->src, f->src); } - out->has_timing_info = f->has_timing_info; + out->flags = f->flags; out->ts = f->ts; out->len = f->len; out->seqno = f->seqno;