view mgw/dtmf_timer.c @ 150:529906fddcfa

mgw DTMF timing fix in the corner case of no speech arriving between the end of one DTMF and the start of next
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 11 Oct 2022 14:10:29 -0800
parents f062c32a5116
children
line wrap: on
line source

/*
 * In this module we implement the timer function of DTMF generation.
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <syslog.h>
#include "struct.h"
#include "int_defs.h"
#include "dtmf_defs.h"

extern struct timeval cur_event_time;
extern struct endpoint *dtmf_list_head;

int dtmf_timer_running;
struct timeval dtmf_next_time;

void
start_dtmf_timer()
{
	if (dtmf_timer_running)
		return;
	dtmf_next_time = cur_event_time;
	dtmf_timer_running = 1;
}

dtmf_timer_one(ep)
	struct endpoint *ep;
{
	struct rtp_packet pkt;
	socklen_t addrlen;
	unsigned frame_limit;

	pkt.v_p_x_cc = 0x80;
	pkt.m_pt = ep->pstn_payload_type;
	if (ep->dtmf_m_bit) {
		pkt.m_pt |= 0x80;
		ep->dtmf_m_bit = 0;
	}
	pkt.seq = htons(++ep->g2p_out_seq);
	ep->dtmf_last_ts += SAMPLES_PER_FRAME;
	pkt.tstamp = htonl(ep->dtmf_last_ts);
	pkt.ssrc = ep->g2p_ssrc;
	g711_encode_frame(ep->dtmf_sample_ptr, pkt.payload,
			  ep->pstn_payload_type);
	ep->dtmf_sample_ptr += SAMPLES_PER_FRAME;
	addrlen = sizeof(struct sockaddr_in);
	sendto(ep->rtp_pstn.rtp_fd, &pkt, RTP_PACKET_SIZE_PSTN, 0,
		(struct sockaddr *) &ep->rtp_pstn.remote_addr, addrlen);
	ep->dtmf_frames_sent++;
	ep->dtmf_last_time = cur_event_time;
	frame_limit = ep->dtmf_stop_req ? DTMF_MIN_FRAMES : DTMF_MAX_FRAMES;
	if (ep->dtmf_frames_sent >= frame_limit)
		return 1;
	else
		return 0;
}

void
dtmf_timer_process()
{
	struct endpoint *ep;
	int fin;

	for (ep = dtmf_list_head; ep; ep = ep->dtmf_next) {
		fin = dtmf_timer_one(ep);
		if (!fin)
			continue;
		ep->dtmf_aftermath = 1;
		*ep->dtmf_pp = ep->dtmf_next;
		if (ep->dtmf_next)
			ep->dtmf_next->dtmf_pp = ep->dtmf_pp;
		ep->dtmf_pp = 0;
		ep->dtmf_next = 0;
	}
	if (dtmf_list_head) {
		dtmf_next_time.tv_usec += 20000;
		if (dtmf_next_time.tv_usec >= 1000000) {
			dtmf_next_time.tv_usec -= 1000000;
			dtmf_next_time.tv_sec++;
		}
	} else
		dtmf_timer_running = 0;
}