blob: 92c19cf2ad90c723927c4cc2b1807a3356d44417 [file] [log] [blame]
b.liud440f9f2025-04-18 10:44:31 +08001#include <stdio.h>
2#include <errno.h>
3#include <pthread.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <fcntl.h>
7#include <sys/types.h>
8#include <sys/socket.h>
9#include <sys/un.h>
10#include <netinet/in.h>
11#include <sys/epoll.h>
12#include <arpa/inet.h>
13#include <sys/ioctl.h>
14#include <signal.h>
15#include <stdbool.h>
16#include <sys/stat.h>
17
18//#include "mbtk_log.h"
19//#include "mbtk_utils.h"
20// #include "audio_if_api.h"
21//#include "mbtk_audio2.h"
22
23#define RTP_UDP_SER_PORT_DEFAULT 53248
24#define RTP_UDP_CLI_PORT_DEFAULT 55555
25
26
27#define BUFF_SIZE 4096
28
29#define ID_RIFF 0x46464952
30#define ID_WAVE 0x45564157
31#define ID_FMT 0x20746d66
32#define ID_DATA 0x61746164
33#define FORMAT_PCM 1
34
35#ifndef FALSE
36#define FALSE 0
37#endif
38
39#ifndef TRUE
40#define TRUE 1
41#endif
42
43#ifndef UNUSED
44#define UNUSED(a) (void)(a)
45#endif
46
47typedef unsigned int uint32; /* Unsigned 32 bit value */
48
49struct riff_wave_header {
50 unsigned int riff_id;
51 unsigned int riff_sz;
52 unsigned int wave_id;
53};
54
55struct chunk_header {
56 unsigned int id;
57 unsigned int sz;
58};
59
60struct chunk_fmt {
61 unsigned short audio_format;
62 unsigned short num_channels;
63 unsigned int sample_rate;
64 unsigned int byte_rate;
65 unsigned short block_align;
66 unsigned short bits_per_sample;
67};
68
69struct wav_header {
70 unsigned int riff_id;
71 unsigned int riff_sz;
72 unsigned int riff_fmt;
73 unsigned int fmt_id;
74 unsigned int fmt_sz;
75 unsigned short audio_format;
76 unsigned short num_channels;
77 unsigned int sample_rate;
78 unsigned int byte_rate;
79 unsigned short block_align;
80 unsigned short bits_per_sample;
81 unsigned int data_id;
82 unsigned int data_sz;
83};
84
85
86#define PCM_WB_BUF_SIZE 640
87#define PCM_NARROW_BUF_SIZE 320
88
89static int record_fd = -1;
90static int send_fd = -1;
91static bool running = FALSE;
92
93
94static void voip_playback_run(void *arg)
95{
96 int rc, len, fd, frames = 0;
97 int pack_size = 320;
98 //char buf[MBTK_PCM_WB_BUF_SIZE];
99 char buf[BUFF_SIZE];
100 char *path = "/data/voip_playback.wav";
101 struct stat st;
102 struct riff_wave_header riff_wave_header;
103 struct chunk_header chunk_header;
104 struct chunk_fmt chunk_fmt = {0};
105 unsigned int more_chunks = 1;
106 uint32 header[4];
107
108 if(send_fd < 0) {
109 printf("Client socket not open.");
110 return;
111 }
112
113 /* Check and open source file */
114 if (access(path, F_OK) || stat(path, &st)) {
115 printf("%s: error reading from file %s\n", __FUNCTION__, path);
116 return;
117 }
118
119 if (!st.st_size) {
120 printf("%s: empty file %s\n", __FUNCTION__, path);
121 return;
122 }
123
124 fd = open(path, O_RDONLY);
125 if (fd < 0) {
126 printf("%s: error opening file %s\n", __FUNCTION__, path);
127 return;
128 }
129
130 lseek(fd, sizeof(struct wav_header), SEEK_SET);
131 uint32 sequence = 1;
132 uint32 timestamp = 0;
133 while (running) {
134 /* Playback loop */
135 memset(buf, 0x00, sizeof(buf));
136 len = read(fd, buf + 16, pack_size);
137 if (len == -1) {
138 printf("%s: error reading from file\n", __FUNCTION__);
139 break;
140 }
141
142 if (len == 0) {
143 /* reached EOF */
144 printf("%s: nothing to read\n", __FUNCTION__);
145 break;
146 }
147
148
149 header[0] = htonl(((uint32_t) 2 << 30) | ((uint32_t) 1 << 24) | ((uint32_t) 0x60 << 16) | ((uint32_t) sequence));
150 header[1] = htonl(timestamp);
151 header[2] = htonl(0xFFFF0000);
152 header[3] = htonl(0xFFFF0000);
153 memcpy(buf, &header, sizeof(header));
154
155 if((rc = sendto(send_fd, buf, len + 16, 0, NULL, 0)) < len + 16) {
156 printf("Send data fail: %d/%d\n", rc, len);
157 break;
158 } else {
159 printf("SEND : %d / %d\n", rc, len);
160 }
161
162 sequence++;
163 timestamp += len / 2;
164
165 ++frames;
166 //printf("%s: No.%d frame playback[len - %d]\n", __FUNCTION__, ++frames, len);
167 usleep(21000);
168 }
169
170 printf("playback_thread exit.\n");
171}
172
173static void sig_handler(int sig)
174{
175 running = FALSE;
176
177 printf("Success exit by signal...\n");
178
179 sleep(1);
180
181 exit(0);
182}
183
184static int rtp_udp_ser_open(const char *local_addr, int local_port)
185{
186 // No set local addr.
187 UNUSED(local_addr);
188
189 int fd = socket(AF_INET, SOCK_DGRAM, 0);
190 if(fd < 0){
191 printf("socket() fail.[%d]\n", errno);
192 return -1;
193 }
194
195 struct sockaddr_in servaddr;
196 memset(&servaddr, 0, sizeof(servaddr));
197 servaddr.sin_family = AF_INET;
198 servaddr.sin_port = htons(local_port);
199 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
200
201 if (bind(fd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in)) < 0) {
202 printf("bind() failed: %d\n", errno);
203 goto result_fail_with_close;
204 }
205
206 return fd;
207result_fail_with_close:
208 close(fd);
209 fd = -1;
210 printf("mbtk_sock_open() end:fail\n");
211 return -1;
212}
213
214static int rtp_udp_cli_open(const char *remote_addr, int remote_port)
215{
216 struct sockaddr_in dst_sa4, src_sa4;
217 if (inet_pton(AF_INET, "0.0.0.0", &src_sa4.sin_addr) > 0) {
218 src_sa4.sin_family = AF_INET;
219 src_sa4.sin_port = htons(0);
220 memset(&src_sa4.sin_zero, 0, sizeof(src_sa4.sin_zero));
221 } else {
222 printf("Set src addr fail.\n");
223 return -1;
224 }
225
226 if (inet_pton(AF_INET, remote_addr, &dst_sa4.sin_addr) > 0) {
227 dst_sa4.sin_family = AF_INET;
228 dst_sa4.sin_port = htons(remote_port);
229 memset(&dst_sa4.sin_zero, 0, sizeof(dst_sa4.sin_zero));
230 } else {
231 printf("Set dst addr fail.\n");
232 return -1;
233 }
234
235 int fd = socket(AF_INET, SOCK_DGRAM, 0);
236 if(fd < 0){
237 printf("socket() fail.[%d]\n", errno);
238 return -1;
239 }
240
241 if (bind(fd, (struct sockaddr*) &src_sa4, sizeof(src_sa4)) < 0) {
242 printf("bind() failed: %d\n", errno);
243 goto result_fail_with_close;
244 }
245
246 if (connect(fd, (struct sockaddr*) &dst_sa4, sizeof(dst_sa4)) < 0) {
247 printf("connect() failed: %d\n", errno);
248 goto result_fail_with_close;
249 }
250
251#if 0
252 if(socket_noblock(fd)) {
253 goto result_fail_with_close;
254 }
255#endif
256
257 return fd;
258result_fail_with_close:
259 close(fd);
260 fd = -1;
261 printf("mbtk_sock_open() end:fail\n");
262 return -1;
263}
264
265int main(int argc, char *argv[])
266{
267 if(argc != 2) {
268 printf("mbtk_rtp_udp_cli <IP>\n");
269 return -1;
270 }
271
272 // mbtk_log_init("radio", "RTP_TEST");
273
274 signal(SIGINT, sig_handler);
275 signal(SIGTERM, sig_handler);
276
277
278 int ser_fd = rtp_udp_ser_open(NULL, RTP_UDP_SER_PORT_DEFAULT);
279 if(ser_fd < 0) {
280 printf("rtp_udp_ser_open() fail.\n");
281 return -1;
282 }
283
284 send_fd = rtp_udp_cli_open(argv[1], RTP_UDP_CLI_PORT_DEFAULT);
285 if(send_fd < 0) {
286 printf("rtp_udp_cli_open() fail.\n");
287 // return -1;
288 }
289
290 struct wav_header header;
291 int rc = 0;
292 char *path = "/data/voip_record.wav";
293
294 header.riff_id = ID_RIFF;
295 header.riff_sz = 0;
296 header.riff_fmt = ID_WAVE;
297 header.fmt_id = ID_FMT;
298 header.fmt_sz = 16;
299 header.audio_format = 1; //FORMAT_PCM;
300 header.num_channels = 1; //Modem ONLY support mono recording
301 header.sample_rate = 8000;
302 header.bits_per_sample = 16; //PCM_SAMPLEBITS_S16_LE;
303 header.byte_rate = (header.bits_per_sample / 8) * header.num_channels * header.sample_rate;
304 header.block_align = header.num_channels * (header.bits_per_sample / 8);
305 header.data_id = ID_DATA;
306
307 record_fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
308 if (record_fd < 0) {
309 printf("%s: error opening file %s!\n", __FUNCTION__, path);
310 return -1;
311 }
312
313 lseek(record_fd, 0, SEEK_SET);
314 write(record_fd, &header, sizeof(struct wav_header));
315
316 //leave enough room for header
317 lseek(record_fd, sizeof(struct wav_header), SEEK_SET);
318
319 char buff[2048];
320 int len_recv;
321 int len_send;
322 running = TRUE;
323 bool is_first = TRUE;
324 while(running) {
325 len_recv = recvfrom(ser_fd, buff, sizeof(buff), 0, NULL, NULL);
326 if(len_recv < 0) {
327 printf("recvfrom() ret is %d,errno - %d\n", len_recv, errno);
328 continue;
329 } else if(len_recv == 0) {
330 printf("ret is 0\n");
331 } else if(len_recv > 16){
332 printf("RECV:len - %d\n", len_recv);
333 write(record_fd, buff + 16, len_recv - 16);
334
335 if(is_first) {
336 pthread_t playabck_thread/*, record_thread*/;
337 rc = pthread_create(&playabck_thread, NULL, (void *)&voip_playback_run, NULL);
338 if (rc < 0) {
339 printf("error creating thread_start!");
340 break;
341 }
342 is_first = FALSE;
343 }
344
345#if 0
346 if(cli_fd < 0) {
347 cli_fd = rtp_udp_cli_open(argv[1], RTP_UDP_CLI_PORT_DEFAULT);
348 if(cli_fd < 0) {
349 printf("rtp_udp_cli_open() fail.\n");
350 // return -1;
351 } else {
352 printf("rtp_udp_cli_open() success.\n");
353 }
354 }
355
356 if(cli_fd > 0) {
357 len_send = sendto(cli_fd, buff, len_recv, 0, NULL, 0);
358 printf("SEND : %d / %d\n", len_send, len_recv);
359 }
360#endif
361 } else {
362 printf("RTP Header error.\n");
363 }
364 }
365
366 close(record_fd);
367
368 close(ser_fd);
369
370 return 0;
371}
372
373