diff --git a/src/channels/chan_voicemngr.c b/src/channels/chan_voicemngr.c index 024ba01c462795e4a1f217b1cb654ed72a0c8a85..725462786d9f60b297bd725810dd247e17e14f4f 100644 --- a/src/channels/chan_voicemngr.c +++ b/src/channels/chan_voicemngr.c @@ -736,6 +736,10 @@ static void endpt_connection_data(int line, int id, const char *action, const st if (data->mask & UBUS_DATA_PTIME_BIT){ blobmsg_add_u32(&bb, "ptime", data->ptime); } + if (data->mask & UBUS_DATA_DTMF_BIT){ + blobmsg_add_u32(&bb, "dtmf_mode", data->dtmf_mode); + ast_log(LOG_NOTICE, "connection parm_update, dtmf_mode: %d", data->dtmf_mode); + } } req = ast_calloc(1, sizeof(struct ubus_request)); @@ -815,6 +819,7 @@ static void chan_voicemngr_modify_codec(struct chan_voicemngr_subchannel *sub) { ast_channel_lock(sub->owner); ast_channel_codec_set(sub->owner, !ast_strlen_zero(ast_channel_codec_get(bridged_chan)) ? ast_channel_codec_get(bridged_chan) : ast_format_get_name(ast_channel_writeformat(bridged_chan))); + ast_channel_dtmf_mode_set(sub->owner, ast_channel_dtmf_mode_get(bridged_chan)); ast_channel_unlock(sub->owner); } ast_channel_unref(bridged_chan); @@ -851,9 +856,18 @@ static void chan_voicemngr_modify_codec(struct chan_voicemngr_subchannel *sub) { } data.ptime = sub->period; data.mask = data.mask|UBUS_DATA_PTIME_BIT; + /* DTMF mode */ + if (ast_channel_dtmf_mode_get(sub->owner) != AST_SIP_DTMF_NONE){ + sub->dtmf_mode = ast_channel_dtmf_mode_get(sub->owner); + } + if (sub->dtmf_mode != AST_SIP_DTMF_RFC_4733){ + data.dtmf_mode = sub->dtmf_mode; + data.mask = data.mask|UBUS_DATA_DTMF_BIT; + } + /* push parm_update to voicemngr */ endpt_connection_data(sub->parent->line_id, sub->call_id, "parm_update", &data); - ast_log(LOG_NOTICE, "connection parm_update, codec: %d, ptime: %d",data.codec, data.ptime); + ast_log(LOG_NOTICE, "connection parm_update, codec: %d, ptime: %d\n",data.codec, data.ptime); if (data.mask & UBUS_DATA_CODEC_BIT) { sub->updated_codec = 1; @@ -1718,6 +1732,7 @@ static int chan_voicemngr_classify_rtp_packet(int payload_type) { case RTCP_SR: return CHAN_VOICEMNGR_RTCP_SR; case RTCP_RR: return CHAN_VOICEMNGR_RTCP_RR; case RTP_PT_CN: return CHAN_VOICEMNGR_AUDIO; + case RTP_PT_DTMF: return CHAN_VOICEMNGR_AUDIO; } for (int i=0; i<VOICEMNGR_CODECS_NUM; i++) @@ -3104,7 +3119,7 @@ static void handle_dtmf(enum LINE_EVENT event, if (p->dtmf_first < 0) { p->dtmf_first = dtmf_button; ast_debug(9,"Pressed DTMF %s\n", dtmfMap->name); - if (owner && chan_voicemngr_should_relay_dtmf(sub)) { + if (owner && chan_voicemngr_should_relay_dtmf(sub) && (sub->dtmf_mode == AST_SIP_DTMF_INFO || sub->conference_initiator == 1)) { // INCALL send_outgoing_dtmf(owner, dtmf_button, AST_FRAME_DTMF_BEGIN); } @@ -3156,7 +3171,7 @@ static void handle_dtmf(enum LINE_EVENT event, ast_queue_frame(owner, &f); } } else { - if (owner) { + if (owner && (sub->dtmf_mode == AST_SIP_DTMF_INFO || sub->conference_initiator == 1)) { // INCALL send_outgoing_dtmf(owner, dtmf_button, AST_FRAME_DTMF_END); } @@ -3207,7 +3222,7 @@ static struct ast_format *map_rtpname_to_format(char* name) { if (!strcmp(voicemngr_codecs[i].name,name)) return *voicemngr_codecs[i].ast_format; - ast_verbose("Warning: unknown RTP payload_type %s is received. Treated it as PCMU\n", name); + ast_verbose("Warning: unknown RTP payload_type name %s is received. Treated it as PCMU\n", name); return ast_format_ulaw; } @@ -3223,7 +3238,7 @@ static void audio_packet_handler(pe_packet_t *p) { unsigned int* packet_buf32 = (unsigned int*)ap->rtp; // Clear the RTP marker bit - if ((payload_type & RTP_MARKER_BIT) && payload_type < RTCP_SR) + if ((payload_type & RTP_MARKER_BIT) && (payload_type < RTCP_SR || payload_type > RTCP_XR)) payload_type &= (~RTP_MARKER_BIT); packet_type = chan_voicemngr_classify_rtp_packet(payload_type); @@ -3254,9 +3269,15 @@ static void audio_packet_handler(pe_packet_t *p) { frame.frametype = AST_FRAME_CNG; frame.subclass.integer = ap->rtp[12]; } else if (sub->channel_state == OFFHOOK - || sub->channel_state == DIALING - || (owner && !ast_strlen_zero(ast_channel_codec_get(owner)) && strcmp(chan_voicemngr_get_codec_string(payload_type),ast_channel_codec_get(owner)))){ + || sub->channel_state == DIALING){ drop_frame=1; + } else if(payload_type == RTP_PT_DTMF) { + frame.frametype = AST_FRAME_DTMF_BYPASS; + frame.subclass.integer = ap->rtp[1]; //payload_type + ast_debug(3, "DTMF rtp_event for digit: %d, with payload_type: %d \n", ap->rtp[12], ap->rtp[1]); + if (sub->conference_initiator == 1) { + drop_frame=1; + } } else { struct ast_format *format = map_rtptype_to_format(payload_type); if (format) { @@ -3855,6 +3876,7 @@ static struct chan_voicemngr_pvt *chan_voicemngr_allocate_pvt(void) sub->congestion_timer_id = -1; sub->sip_client_id = -1; sub->period = default_ptime; // 20 ms + sub->dtmf_mode = AST_SIP_DTMF_RFC_4733; sub->conference_initiator = 0; tmp->sub[i] = sub; sub->ingressRtcpPackets = 0; diff --git a/src/channels/chan_voicemngr.h b/src/channels/chan_voicemngr.h index 173747d802e10d3440a7953923577a126797d104..a024544b93251552c178f3923d726e4a2830ee80 100644 --- a/src/channels/chan_voicemngr.h +++ b/src/channels/chan_voicemngr.h @@ -164,6 +164,7 @@ struct chan_voicemngr_subchannel { uint16_t sequence_number; /* Endpoint RTP sequence number state */ unsigned int time_stamp; /* Endpoint RTP time stamp state */ unsigned int period; /* Endpoint RTP period */ + enum ast_sip_dtmf_mode dtmf_mode; int codec; /* Used codec */ struct chan_voicemngr_pvt *parent; /* chan_voicemngr_line owning this subchannel */ int cw_timer_id; /* Current call waiting timer id, -1 if no active timer */