diff --git a/main/frame.c b/main/frame.c index b5815851b10737749fb46f516ffd7b8fd387d304..d04df12f466e778ef99bb982825e916be952a391 100644 --- a/main/frame.c +++ b/main/frame.c @@ -419,7 +419,7 @@ char *ast_frame_subclass2str(struct ast_frame *f, char *subclass, size_t slen, c subclass[1] = '\0'; } break; - case AST_FRAME_CNG: + case AST_FRAME_CNG: if (slen > 1) { subclass[0] = f->subclass.integer; subclass[1] = '\0'; @@ -735,6 +735,9 @@ char *ast_frame_type2str(enum ast_frame_type frame_type, char *ftype, size_t len case AST_FRAME_RTCP: ast_copy_string(ftype, "RTCP", len); break; + case AST_FRAME_DTMF_BYPASS: + ast_copy_string(ftype, "DTMF Bypass", len); + break; default: snprintf(ftype, len, "Unknown Frametype '%u'", frame_type); break; diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index 9ee13caba270495ecf4556281121c24d8767e778..cbcc54450162ff38a82551ec0a38ae2671fa90ca 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -5923,6 +5923,37 @@ static void process_dtmf_rfc2833(struct ast_rtp_instance *instance, unsigned cha return; } +static struct ast_frame *bypass_dtmf_rfc4733(struct ast_rtp_instance *instance, unsigned char *data, int len, + unsigned int seqno, unsigned int timestamp, int payloadtype, long ssrc, int hdrlen) +{ + struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); + + rtp->f.frametype = AST_FRAME_DTMF_BYPASS; + rtp->f.subclass.integer = payloadtype; + rtp->f.subclass.format = ao2_bump(ast_format_none); + rtp->f.datalen = len; + rtp->f.samples = 0; + rtp->f.mallocd = 0; + rtp->f.mallocd_hdr_len = 0; + rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; + rtp->f.src = "RTP"; + rtp->f.data.ptr = data; + rtp->f.flags = 0; + rtp->f.ts = timestamp; + rtp->f.len = 0; + rtp->f.ssrc = ssrc; + ast_set_flag(&rtp->f, AST_FRFLAG_HAS_SEQUENCE_NUMBER); + rtp->f.seqno = seqno; + rtp->f.stream_num = rtp->stream_num; + + if (ast_debug_rtp_packet_is_allowed) { + ast_debug(0, "RTP for Telephone Event: payload type = %d, len = %d, event = %hhu, timestamp = %ld, seqno = %d\n", + rtp->f.subclass.integer, rtp->f.datalen, *(unsigned char *)rtp->f.data.ptr, rtp->f.ts, rtp->f.seqno); + } + + return &rtp->f; +} + static struct ast_frame *process_dtmf_cisco(struct ast_rtp_instance *instance, unsigned char *data, int len, unsigned int seqno, unsigned int timestamp, int payloadtype, int mark) { struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); @@ -7822,11 +7853,8 @@ static struct ast_frame *ast_rtp_interpret(struct ast_rtp_instance *instance, st if (!payload->asterisk_format) { struct ast_frame *f = NULL; if (payload->rtp_code == AST_RTP_DTMF) { - /* process_dtmf_rfc2833 may need to return multiple frames. We do this - * by passing the pointer to the frame list to it so that the method - * can append frames to the list as needed. - */ - process_dtmf_rfc2833(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark, &frames); + /* Forward the RTP event frame for DTMF and hook flash transparently without interpretation */ + f = bypass_dtmf_rfc4733(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, ssrc, hdrlen); } else if (payload->rtp_code == AST_RTP_CISCO_DTMF) { f = process_dtmf_cisco(instance, read_area + hdrlen, res - hdrlen, seqno, timestamp, payloadtype, mark); } else if (payload->rtp_code == AST_RTP_CN) {