FreeCalypso > hg > sipout-test-utils
view test-fsk/rtp_rx.c @ 10:3c5734b88c20
sipout-test-v22 put together
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 07 Mar 2024 02:33:49 -0800 |
parents | eaf0e8f81a22 |
children |
line wrap: on
line source
/* * In this module we implement our RTP handling: obtaining a PSTN-side * RTP endpoint from themwi-rtp-mgr, then handling read select on RTP * and RTCP UDP sockets. */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include "../include/tmgw_const.h" #include "../include/rtp_defs.h" #include "../include/pstn_defs.h" #include "../librtpalloc/rtp_alloc_simple.h" extern const uint16_t pcmu_decode_table[256]; extern const uint16_t pcma_decode_table[256]; extern int rtp_out_enable; /* misusing the flag :-( */ struct sockaddr_in rtp_local_addr; int rtp_udp_fd, rtcp_udp_fd; static int rtp_start_flag, rtp_bad_flag, rtp_ssrc_chg_flag; static int rtp_seq_brk_flag, rtp_seq_zero_flag, rtp_seq_neg_flag; static int rtp_ts_brk_flag; static uint32_t rtp_ssrc; static uint32_t rtp_last_ts; static uint16_t rtp_last_seq; static int got_some_rtcp; void obtain_rtp_endp() { int rc; struct rtp_alloc_simple res; rc = rtp_alloc_simple(TMGW_EP_TYPE_PSTN_ONLY, &res); if (rc < 0) exit(1); /* error msg already printed */ bcopy(&res.pstn_addr, &rtp_local_addr, sizeof(struct sockaddr_in)); rtp_udp_fd = res.pstn_rtp_fd; rtcp_udp_fd = res.pstn_rtcp_fd; } void rtp_rx_select() { struct rtp_packet pkt; struct sockaddr_in sin_from; socklen_t addrlen; int16_t seq_delta; int32_t ts_delta; const uint16_t *pcm_dec_table; int16_t pcm_samples[FRAME_20MS]; unsigned n; int rc; addrlen = sizeof(struct sockaddr_in); rc = recvfrom(rtp_udp_fd, &pkt, sizeof pkt, 0, (struct sockaddr *) &sin_from, &addrlen); if (rc < 0) return; if (rc != RTP_PACKET_SIZE_PSTN) { bad_rtp_pkt: if (!rtp_bad_flag) { printf("Got a bad RTP packet\n"); rtp_bad_flag = 1; } return; } if (pkt.v_p_x_cc != 0x80) goto bad_rtp_pkt; switch (pkt.m_pt & 0x7F) { case PSTN_CODEC_PCMU: pcm_dec_table = pcmu_decode_table; break; case PSTN_CODEC_PCMA: pcm_dec_table = pcma_decode_table; break; default: goto bad_rtp_pkt; } if (rtp_start_flag && pkt.ssrc != rtp_ssrc) { if (!rtp_ssrc_chg_flag) { printf("Rx RTP stream changed SSRC\n"); rtp_ssrc_chg_flag = 1; } } else if (rtp_start_flag) { seq_delta = ntohs(pkt.seq) - rtp_last_seq; ts_delta = ntohl(pkt.tstamp) - rtp_last_ts; if (seq_delta == 0) { if (!rtp_seq_zero_flag) { printf("Rx RTP seq zero increment\n"); rtp_seq_zero_flag = 1; } return; } if (seq_delta < 0) { if (!rtp_seq_neg_flag) { printf("Rx RTP seq negative increment\n"); rtp_seq_neg_flag = 1; } return; } if (seq_delta != 1) { if (!rtp_seq_brk_flag) { printf("Rx RTP stream seq break\n"); rtp_seq_brk_flag = 1; } } else if (ts_delta != 160) { if (!rtp_ts_brk_flag) { printf("Rx RTP stream tstamp break\n"); rtp_ts_brk_flag = 1; } } } rtp_ssrc = pkt.ssrc; rtp_last_ts = ntohl(pkt.tstamp); rtp_last_seq = ntohs(pkt.seq); if (!rtp_start_flag) { printf("Rx RTP stream begins with seq=%u ts=%u\n", rtp_last_seq, rtp_last_ts); rtp_start_flag = 1; } /* ignore early RTP during ringing, before answer supervision */ if (!rtp_out_enable) return; /* feed samples to modem Rx */ for (n = 0; n < FRAME_20MS; n++) pcm_samples[n] = pcm_dec_table[pkt.payload[n]]; process_rx_frame(pcm_samples); } void rtcp_rx_select() { u_char buf[512]; recv(rtcp_udp_fd, buf, sizeof buf, 0); if (!got_some_rtcp) { printf("Got some RTCP\n"); got_some_rtcp = 1; } }