FreeCalypso > hg > themwi-interim
view mtctest/rtp_play.c @ 10:395c56969bc4
mtctest: implement guts of RTP play mechanism
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 09 Jun 2024 04:24:53 +0000 |
parents | |
children | aa2ba9b432af |
line wrap: on
line source
/* * In this module we implement RTP play command, emitting a test sequence * of encoded speech frames toward the MS. */ #include <sys/types.h> #include <sys/file.h> #include <sys/stat.h> #include <sys/socket.h> #include <sys/time.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <unistd.h> #include <themwi/rtp/rtp_defs.h> #include <themwi/rtp/rtp_alloc_simple.h> extern struct rtp_alloc_simple rtp_info; extern int got_msc_rtp_info; extern struct sockaddr_storage msc_rtp_addr; extern uint8_t rtp_payload_type; extern struct timeval cur_event_time; int rtp_play_active; static uint8_t play_buffer[33*50*30]; /* max 30 s of GSM-FR play */ static uint32_t rtp_ssrc; static uint32_t rtp_out_ts; static uint16_t rtp_out_seq; static unsigned play_frame_len; static unsigned play_buf_nframes, play_buf_ptr; static int play_loop; static void assign_rtpout_ssrc() { rtp_ssrc = cur_event_time.tv_sec ^ cur_event_time.tv_usec ^ getpid(); } static void fill_with_play(outbuf) uint8_t *outbuf; { memcpy(outbuf, play_buffer + play_buf_ptr * play_frame_len, play_frame_len); play_buf_ptr++; if (play_buf_ptr < play_buf_nframes) return; play_buf_ptr = 0; if (!play_loop) rtp_play_active = 0; } void generate_rtp_packet() { struct rtp_packet pkt; socklen_t addrlen; pkt.v_p_x_cc = 0x80; pkt.m_pt = rtp_payload_type; pkt.seq = htons(rtp_out_seq++); pkt.tstamp = htonl(rtp_out_ts); rtp_out_ts += 160; pkt.ssrc = rtp_ssrc; fill_with_play(pkt.payload); addrlen = sizeof(struct sockaddr_in); sendto(rtp_info.gsm_rtp_fd, &pkt, RTP_PACKET_HDR_SIZE + play_frame_len, 0, (struct sockaddr *) &msc_rtp_addr, addrlen); } void play_file_cmdop(filename, frame_len, loop) unsigned frame_len; char *filename; { int fd; struct stat st; if (rtp_play_active) { fprintf(stderr, "error: file play already in progress\n"); return; } if (!got_msc_rtp_info) { fprintf(stderr, "error: no RTP info received from MSC\n"); return; } fd = open(filename, O_RDONLY); if (fd < 0) { perror(filename); return; } fstat(fd, &st); if (!S_ISREG(st.st_mode)) { close(fd); fprintf(stderr, "error: %s is not a regular file\n", filename); return; } if (!st.st_size) { close(fd); fprintf(stderr, "error: %s is an empty file\n", filename); return; } if (st.st_size % frame_len) { close(fd); fprintf(stderr, "error: size of %s is not a multiple of %u bytes\n", filename, frame_len); return; } if (st.st_size > sizeof play_buffer) { close(fd); fprintf(stderr, "error: size of %s exceeds compiled-in buffer size\n", filename); return; } read(fd, play_buffer, st.st_size); close(fd); play_buf_nframes = st.st_size / frame_len; play_buf_ptr = 0; play_frame_len = frame_len; play_loop = loop; assign_rtpout_ssrc(); rtp_out_ts = 0; rtp_out_seq = 0; rtp_play_active = 1; } void play_file_stop() { rtp_play_active = 0; }