blob: 079f62ebaa2f7628b19e3d31eccbefb8cdc3ce7a [file] [log] [blame]
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +02001#include <stdlib.h>
2#include <unistd.h>
3#include <stdio.h>
4#include <string.h>
5#include <err.h>
6
7#include <osmocom/core/talloc.h>
8#include <osmocom/core/application.h>
9
10#include <openbsc/debug.h>
11#include <openbsc/gsm_data.h>
12#include <openbsc/mgcp.h>
13#include <openbsc/mgcp_internal.h>
Holger Hans Peter Freyther91eeeae2014-07-04 20:55:20 +020014#include <openbsc/rtp.h>
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +020015
16#include "bscconfig.h"
17#ifndef BUILD_MGCP_TRANSCODING
18#error "Requires MGCP transcoding enabled (see --enable-mgcp-transcoding)"
19#endif
20
Jacob Erlbeck909fac62014-05-08 14:08:37 +020021#include "openbsc/mgcp_transcode.h"
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +020022
23uint8_t *audio_frame_l16[] = {
24};
25
26struct rtp_packets {
27 float t;
28 int len;
29 char *data;
30};
31
32struct rtp_packets audio_packets_l16[] = {
33 /* RTP: SeqNo=1, TS=160 */
34 {0.020000, 332,
35 "\x80\x0B\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
36 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
37 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
38 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
39 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
40 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
41 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
42 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
43 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
44 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
45 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
46 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
47 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
48 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
49 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
50 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
51 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
52 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
53 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
54 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
55 "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED"
56 },
57};
58
59struct rtp_packets audio_packets_gsm[] = {
60 /* RTP: SeqNo=1, TS=160 */
61 {0.020000, 45,
62 "\x80\x03\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
63 "\xD4\x7C\xE3\xE9\x62\x50\x39\xF0\xF8\xB4\x68\xEA\x6C\x0E\x81\x1B"
64 "\x56\x2A\xD5\xBC\x69\x9C\xD1\xF0\x66\x7A\xEC\x49\x7A\x33\x3D\x0A"
65 "\xDE"
66 },
67};
68
69struct rtp_packets audio_packets_gsm_invalid_size[] = {
70 /* RTP: SeqNo=1, TS=160 */
71 {0.020000, 41,
72 "\x80\x03\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
73 "\xD4\x7C\xE3\xE9\x62\x50\x39\xF0\xF8\xB4\x68\xEA\x6C\x0E\x81\x1B"
74 "\x56\x2A\xD5\xBC\x69\x9C\xD1\xF0\x66\x7A\xEC\x49\x7A\x33\x3D\x0A"
75 "\xDE"
76 },
77};
78
79struct rtp_packets audio_packets_gsm_invalid_data[] = {
80 /* RTP: SeqNo=1, TS=160 */
81 {0.020000, 45,
82 "\x80\x03\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
83 "\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE"
84 "\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE"
85 "\xEE"
86 },
87};
88
89struct rtp_packets audio_packets_gsm_invalid_ptype[] = {
90 /* RTP: SeqNo=1, TS=160 */
91 {0.020000, 45,
92 "\x80\x08\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
93 "\xD4\x7C\xE3\xE9\x62\x50\x39\xF0\xF8\xB4\x68\xEA\x6C\x0E\x81\x1B"
94 "\x56\x2A\xD5\xBC\x69\x9C\xD1\xF0\x66\x7A\xEC\x49\x7A\x33\x3D\x0A"
95 "\xDE"
96 },
97};
98
99struct rtp_packets audio_packets_g729[] = {
100 /* RTP: SeqNo=1, TS=160 */
101 {0.020000, 32,
102 "\x80\x12\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
103 "\xAF\xC2\x81\x40\x00\xFA\xCE\xA4\x21\x7C\xC5\xC3\x4F\xA5\x98\xF5"
104 "\xB2\x95\xC4\xAD"
105 },
106};
107
108struct rtp_packets audio_packets_pcma[] = {
109 /* RTP: SeqNo=1, TS=160 */
110 {0.020000, 172,
111 "\x80\x08\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44"
112 "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
113 "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
114 "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
115 "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
116 "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
117 "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
118 "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
119 "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
120 "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
121 "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25"
122 },
Holger Hans Peter Freytherc8b29082014-07-02 22:02:15 +0200123 /* RTP: SeqNo=26527, TS=232640 */
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200124 {0.020000, 92,
Holger Hans Peter Freytherc8b29082014-07-02 22:02:15 +0200125 "\x80\x08\x67\x9f\x00\x03\x8c\xc0\x04\xaa\x67\x9f\xd5\xd5\xd5\xd5"
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200126 "\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5"
127 "\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5"
128 "\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5"
129 "\xd5\xd5\xd5\xd5\xd5\xd5\x55\x55\xd5\xd5\x55\x55\xd5\xd5\x55\x55"
130 "\xd5\xd5\xd5\x55\x55\xd5\xd5\xd5\x55\x55\xd5\xd5"
131 },
Holger Hans Peter Freytherc8b29082014-07-02 22:02:15 +0200132 /* RTP: SeqNo=26528, TS=232720 */
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200133 {0.020000, 92,
Holger Hans Peter Freytherc8b29082014-07-02 22:02:15 +0200134 "\x80\x08\x67\xa0\x00\x03\x8d\x10\x04\xaa\x67\x9f\x55\xd5\xd5\x55"
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200135 "\xd5\x55\xd5\xd5\xd5\x55\xd5\x55\xd5\xd5\x55\xd5\x55\xd5\x55\xd5"
136 "\x55\x55\xd5\x55\xd5\xd5\x55\x55\x55\x55\x55\xd5\xd5\x55\xd5\xd5"
137 "\xd5\x55\xd5\xd5\xd5\x55\x54\x55\xd5\xd5\x55\xd5\xd5\xd5\xd5\x55"
138 "\x54\x55\xd5\x55\xd5\x55\x55\x55\x55\x55\xd5\xd5\xd5\xd5\xd5\xd4"
139 "\xd5\x54\x55\xd5\xd4\xd5\x54\xd5\x55\xd5\xd5\xd5"
140 },
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200141};
142
143
144
145static int audio_name_to_type(const char *name)
146{
147 if (!strcasecmp(name, "gsm"))
148 return 3;
149#ifdef HAVE_BCG729
150 else if (!strcasecmp(name, "g729"))
151 return 18;
152#endif
153 else if (!strcasecmp(name, "pcma"))
154 return 8;
155 else if (!strcasecmp(name, "l16"))
156 return 11;
157 return -1;
158}
159
160int mgcp_get_trans_frame_size(void *state_, int nsamples, int dst);
161
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200162static int given_configured_endpoint(int in_samples, int out_samples,
163 const char *srcfmt, const char *dstfmt,
164 void **out_ctx, struct mgcp_endpoint **out_endp)
165{
166 int rc;
167 struct mgcp_rtp_end *dst_end;
168 struct mgcp_rtp_end *src_end;
169 struct mgcp_config *cfg;
170 struct mgcp_trunk_config *tcfg;
171 struct mgcp_endpoint *endp;
172
173 cfg = mgcp_config_alloc();
174 tcfg = talloc_zero(cfg, struct mgcp_trunk_config);
175 endp = talloc_zero(tcfg, struct mgcp_endpoint);
176
177
178 tcfg->endpoints = endp;
179 tcfg->number_endpoints = 1;
180 tcfg->cfg = cfg;
181 endp->tcfg = tcfg;
182 endp->cfg = cfg;
Holger Hans Peter Freythercb6ad702014-07-22 15:00:52 +0200183 mgcp_initialize_endp(endp);
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200184
185 dst_end = &endp->bts_end;
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +0200186 dst_end->codec.payload_type = audio_name_to_type(dstfmt);
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200187
188 src_end = &endp->net_end;
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +0200189 src_end->codec.payload_type = audio_name_to_type(srcfmt);
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200190
191 if (out_samples) {
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +0200192 dst_end->codec.frame_duration_den = dst_end->codec.rate;
193 dst_end->codec.frame_duration_num = out_samples;
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200194 dst_end->frames_per_packet = 1;
195 dst_end->force_output_ptime = 1;
196 }
197
198 rc = mgcp_transcoding_setup(endp, dst_end, src_end);
Holger Hans Peter Freyther6041c8d2014-06-28 13:24:36 +0200199 if (rc < 0) {
200 printf("setup failed: %s", strerror(-rc));
201 abort();
202 }
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200203
204 *out_ctx = cfg;
205 *out_endp = endp;
206 return 0;
207}
208
209
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200210static int transcode_test(const char *srcfmt, const char *dstfmt,
211 uint8_t *src_pkts, size_t src_pkt_size)
212{
213 char buf[4096] = {0x80, 0};
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200214 void *ctx;
215
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200216 struct mgcp_rtp_end *dst_end;
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200217 struct mgcp_process_rtp_state *state;
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200218 struct mgcp_endpoint *endp;
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200219 int in_size;
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200220 const int in_samples = 160;
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200221 int len, cont;
222
223 printf("== Transcoding test ==\n");
224 printf("converting %s -> %s\n", srcfmt, dstfmt);
225
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200226 given_configured_endpoint(in_samples, 0, srcfmt, dstfmt, &ctx, &endp);
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200227
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200228 dst_end = &endp->bts_end;
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200229 state = dst_end->rtp_process_data;
230 OSMO_ASSERT(state != NULL);
231
232 in_size = mgcp_transcoding_get_frame_size(state, in_samples, 0);
233 OSMO_ASSERT(sizeof(buf) >= in_size + 12);
234
235 memcpy(buf, src_pkts, src_pkt_size);
236
237 len = src_pkt_size;
238
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200239 cont = mgcp_transcoding_process_rtp(endp, dst_end,
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200240 buf, &len, sizeof(buf));
Holger Hans Peter Freyther6041c8d2014-06-28 13:24:36 +0200241 if (cont < 0) {
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200242 printf("Nothing encoded due: %s\n", strerror(-cont));
243 talloc_free(ctx);
244 return -1;
Holger Hans Peter Freyther6041c8d2014-06-28 13:24:36 +0200245 }
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200246
247 if (len < 24) {
248 printf("encoded: %s\n", osmo_hexdump((unsigned char *)buf, len));
249 } else {
250 const char *str = osmo_hexdump((unsigned char *)buf, len);
251 int i = 0;
252 const int prefix = 4;
253 const int cutlen = 48;
254 int nchars = 0;
255
256 printf("encoded:\n");
257 do {
258 nchars = printf("%*s%-.*s", prefix, "", cutlen, str + i);
259 i += nchars - prefix;
260 printf("\n");
261 } while (nchars - prefix >= cutlen);
262 }
Holger Hans Peter Freyther4fb7e642014-06-28 00:10:10 +0200263 printf("counted: %d\n", cont);
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200264 talloc_free(ctx);
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200265 return 0;
266}
267
Holger Hans Peter Freyther91eeeae2014-07-04 20:55:20 +0200268static void test_rtp_seq_state(void)
269{
270 char buf[4096];
271 int len;
272 int cont;
273 void *ctx;
274 struct mgcp_endpoint *endp;
275 struct mgcp_process_rtp_state *state;
276 struct rtp_hdr *hdr;
277 uint32_t ts_no;
278 uint16_t seq_no;
279
280 given_configured_endpoint(160, 0, "pcma", "l16", &ctx, &endp);
281 state = endp->bts_end.rtp_process_data;
282 OSMO_ASSERT(!state->is_running);
283 OSMO_ASSERT(state->next_seq == 0);
284 OSMO_ASSERT(state->next_time == 0);
285
286 /* initialize packet */
287 len = audio_packets_pcma[0].len;
288 memcpy(buf, audio_packets_pcma[0].data, len);
289 cont = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, len);
290 OSMO_ASSERT(cont >= 0);
291 OSMO_ASSERT(state->is_running);
292 OSMO_ASSERT(state->next_seq == 2);
293 OSMO_ASSERT(state->next_time = 240);
294
295 /* verify that the right timestamp was written */
296 OSMO_ASSERT(len == audio_packets_pcma[0].len);
297 hdr = (struct rtp_hdr *) &buf[0];
298
299 memcpy(&ts_no, &hdr->timestamp, sizeof(ts_no));
300 OSMO_ASSERT(htonl(ts_no) == 160);
301 memcpy(&seq_no, &hdr->sequence, sizeof(seq_no));
302 OSMO_ASSERT(htons(seq_no) == 1);
303 /* Check the right sequence number is written */
304 state->next_seq = 1234;
305 len = audio_packets_pcma[0].len;
306 memcpy(buf, audio_packets_pcma[0].data, len);
307 cont = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, len);
308 OSMO_ASSERT(cont >= 0);
309 OSMO_ASSERT(len == audio_packets_pcma[0].len);
310 hdr = (struct rtp_hdr *) &buf[0];
311
312 memcpy(&seq_no, &hdr->sequence, sizeof(seq_no));
313 OSMO_ASSERT(htons(seq_no) == 1234);
314
315 talloc_free(ctx);
316}
317
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200318static void test_transcode_result(void)
319{
320 char buf[4096];
321 int len, res;
322 void *ctx;
323 struct mgcp_endpoint *endp;
324 struct mgcp_process_rtp_state *state;
325
326 {
327 /* from GSM to PCMA and same ptime */
328 given_configured_endpoint(160, 0, "gsm", "pcma", &ctx, &endp);
329 state = endp->bts_end.rtp_process_data;
330
331 /* result */
332 len = audio_packets_gsm[0].len;
333 memcpy(buf, audio_packets_gsm[0].data, len);
334 res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
335 OSMO_ASSERT(res == sizeof(struct rtp_hdr));
336 OSMO_ASSERT(state->sample_cnt == 0);
337
338 len = res;
339 res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
340 OSMO_ASSERT(res == -ENOMSG);
341
342 talloc_free(ctx);
343 }
344
345 {
Holger Hans Peter Freyther4c18d792014-07-04 08:13:53 +0200346 /* from GSM to PCMA and same ptime */
347 given_configured_endpoint(160, 160, "gsm", "pcma", &ctx, &endp);
348 state = endp->bts_end.rtp_process_data;
349
350 /* result */
351 len = audio_packets_gsm[0].len;
352 memcpy(buf, audio_packets_gsm[0].data, len);
353 res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
354 OSMO_ASSERT(res == sizeof(struct rtp_hdr));
355 OSMO_ASSERT(state->sample_cnt == 0);
356
357 len = res;
358 res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
359 OSMO_ASSERT(res == -EAGAIN);
360
361 talloc_free(ctx);
362 }
363
364 {
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200365 /* from PCMA to GSM and wrong different ptime */
366 given_configured_endpoint(80, 160, "pcma", "gsm", &ctx, &endp);
367 state = endp->bts_end.rtp_process_data;
368
369 /* Add the first sample */
370 len = audio_packets_pcma[1].len;
371 memcpy(buf, audio_packets_pcma[1].data, len);
372 res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
373 OSMO_ASSERT(state->sample_cnt == 80);
Holger Hans Peter Freytherc8b29082014-07-02 22:02:15 +0200374 OSMO_ASSERT(state->next_time == 232640);
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200375 OSMO_ASSERT(res < 0);
376
377 /* Add the second sample and it should be consumable */
378 len = audio_packets_pcma[2].len;
379 memcpy(buf, audio_packets_pcma[2].data, len);
380 res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
381 OSMO_ASSERT(state->sample_cnt == 0);
Holger Hans Peter Freytherc8b29082014-07-02 22:02:15 +0200382 OSMO_ASSERT(state->next_time == 232640 + 80 + 160);
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200383 OSMO_ASSERT(res == sizeof(struct rtp_hdr));
384
385 talloc_free(ctx);
386 }
Holger Hans Peter Freytherb9362782014-07-04 20:55:20 +0200387
388 {
389 /* from PCMA to GSM with a big time jump */
390 struct rtp_hdr *hdr;
391 uint32_t ts;
392
393 given_configured_endpoint(80, 160, "pcma", "gsm", &ctx, &endp);
394 state = endp->bts_end.rtp_process_data;
395
396 /* Add the first sample */
397 len = audio_packets_pcma[1].len;
398 memcpy(buf, audio_packets_pcma[1].data, len);
399 res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
400 OSMO_ASSERT(state->sample_cnt == 80);
401 OSMO_ASSERT(state->next_time == 232640);
402 OSMO_ASSERT(state->next_seq == 26527);
403 OSMO_ASSERT(res < 0);
404
405 /* Add a skip to the packet to force a 'resync' */
406 len = audio_packets_pcma[2].len;
407 memcpy(buf, audio_packets_pcma[2].data, len);
408 hdr = (struct rtp_hdr *) &buf[0];
409 /* jump the time and add alignment error */
410 ts = ntohl(hdr->timestamp) + 123 * 80 + 2;
411 hdr->timestamp = htonl(ts);
412 res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
413 OSMO_ASSERT(res < 0);
414 OSMO_ASSERT(state->sample_cnt == 80);
415 OSMO_ASSERT(state->next_time == ts);
416 OSMO_ASSERT(state->next_seq == 26527);
417 /* TODO: this can create alignment errors */
418
419
420 /* Now attempt to consume 160 samples */
421 len = audio_packets_pcma[2].len;
422 memcpy(buf, audio_packets_pcma[2].data, len);
423 hdr = (struct rtp_hdr *) &buf[0];
424 ts += 80;
425 hdr->timestamp = htonl(ts);
426 res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
427 OSMO_ASSERT(res == 12);
428 OSMO_ASSERT(state->sample_cnt == 0);
429 OSMO_ASSERT(state->next_time == ts + 160);
430 OSMO_ASSERT(state->next_seq == 26528);
431
432 talloc_free(ctx);
433 }
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200434}
435
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200436static int test_repacking(int in_samples, int out_samples, int no_transcode)
437{
438 char buf[4096] = {0x80, 0};
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200439 int cc;
440 struct mgcp_endpoint *endp;
441 void *ctx;
442
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200443 struct mgcp_process_rtp_state *state;
444 int in_cnt;
445 int out_size;
446 int in_size;
447 uint32_t ts = 0;
448 uint16_t seq = 0;
449 const char *srcfmt = "pcma";
450 const char *dstfmt = no_transcode ? "pcma" : "l16";
451
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200452 printf("== Transcoding test ==\n");
453 printf("converting %s -> %s\n", srcfmt, dstfmt);
454
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200455 given_configured_endpoint(in_samples, out_samples, srcfmt, dstfmt, &ctx, &endp);
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200456
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200457 state = endp->bts_end.rtp_process_data;
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200458 OSMO_ASSERT(state != NULL);
459
460 in_size = mgcp_transcoding_get_frame_size(state, in_samples, 0);
461 OSMO_ASSERT(sizeof(buf) >= in_size + 12);
462
463 out_size = mgcp_transcoding_get_frame_size(state, -1, 1);
464 OSMO_ASSERT(sizeof(buf) >= out_size + 12);
465
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +0200466 buf[1] = endp->net_end.codec.payload_type;
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200467 *(uint16_t*)(buf+2) = htons(1);
468 *(uint32_t*)(buf+4) = htonl(0);
469 *(uint32_t*)(buf+8) = htonl(0xaabbccdd);
470
471 for (in_cnt = 0; in_cnt < 16; in_cnt++) {
472 int cont;
473 int len;
474
475 /* fake PCMA data */
476 printf("generating %d %s input samples\n", in_samples, srcfmt);
477 for (cc = 0; cc < in_samples; cc++)
478 buf[12+cc] = cc;
479
480 *(uint16_t*)(buf+2) = htonl(seq);
481 *(uint32_t*)(buf+4) = htonl(ts);
482
483 seq += 1;
484 ts += in_samples;
485
486 cc += 12; /* include RTP header */
487
488 len = cc;
489
490 do {
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200491 cont = mgcp_transcoding_process_rtp(endp, &endp->bts_end,
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200492 buf, &len, sizeof(buf));
493 if (cont == -EAGAIN) {
494 fprintf(stderr, "Got EAGAIN\n");
495 break;
496 }
497
Holger Hans Peter Freyther6041c8d2014-06-28 13:24:36 +0200498 if (cont < 0) {
499 printf("processing failed: %s", strerror(-cont));
500 abort();
501 }
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200502
503 len -= 12; /* ignore RTP header */
504
Holger Hans Peter Freyther4fb7e642014-06-28 00:10:10 +0200505 printf("got %d %s output frames (%d octets) count=%d\n",
506 len / out_size, dstfmt, len, cont);
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200507
508 len = cont;
509 } while (len > 0);
510 }
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200511
512 talloc_free(ctx);
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200513 return 0;
514}
515
516int main(int argc, char **argv)
517{
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200518 int rc;
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200519 osmo_init_logging(&log_info);
520
521 printf("=== Transcoding Good Cases ===\n");
522
523 transcode_test("l16", "l16",
524 (uint8_t *)audio_packets_l16[0].data,
525 audio_packets_l16[0].len);
526 transcode_test("l16", "gsm",
527 (uint8_t *)audio_packets_l16[0].data,
528 audio_packets_l16[0].len);
529 transcode_test("l16", "pcma",
530 (uint8_t *)audio_packets_l16[0].data,
531 audio_packets_l16[0].len);
532 transcode_test("gsm", "l16",
533 (uint8_t *)audio_packets_gsm[0].data,
534 audio_packets_gsm[0].len);
535 transcode_test("gsm", "gsm",
536 (uint8_t *)audio_packets_gsm[0].data,
537 audio_packets_gsm[0].len);
538 transcode_test("gsm", "pcma",
539 (uint8_t *)audio_packets_gsm[0].data,
540 audio_packets_gsm[0].len);
541 transcode_test("pcma", "l16",
542 (uint8_t *)audio_packets_pcma[0].data,
543 audio_packets_pcma[0].len);
544 transcode_test("pcma", "gsm",
545 (uint8_t *)audio_packets_pcma[0].data,
546 audio_packets_pcma[0].len);
547 transcode_test("pcma", "pcma",
548 (uint8_t *)audio_packets_pcma[0].data,
549 audio_packets_pcma[0].len);
550
551 printf("=== Transcoding Bad Cases ===\n");
552
553 printf("Invalid size:\n");
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200554 rc = transcode_test("gsm", "pcma",
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200555 (uint8_t *)audio_packets_gsm_invalid_size[0].data,
556 audio_packets_gsm_invalid_size[0].len);
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200557 OSMO_ASSERT(rc < 0);
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200558
559 printf("Invalid data:\n");
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200560 rc = transcode_test("gsm", "pcma",
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200561 (uint8_t *)audio_packets_gsm_invalid_data[0].data,
562 audio_packets_gsm_invalid_data[0].len);
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200563 OSMO_ASSERT(rc < 0);
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200564
565 printf("Invalid payload type:\n");
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200566 rc = transcode_test("gsm", "pcma",
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200567 (uint8_t *)audio_packets_gsm_invalid_ptype[0].data,
568 audio_packets_gsm_invalid_ptype[0].len);
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200569 OSMO_ASSERT(rc == 0);
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200570
571 printf("=== Repacking ===\n");
572
573 test_repacking(160, 160, 0);
574 test_repacking(160, 160, 1);
575 test_repacking(160, 80, 0);
576 test_repacking(160, 80, 1);
577 test_repacking(160, 320, 0);
578 test_repacking(160, 320, 1);
579 test_repacking(160, 240, 0);
580 test_repacking(160, 240, 1);
581 test_repacking(160, 100, 0);
582 test_repacking(160, 100, 1);
Holger Hans Peter Freyther91eeeae2014-07-04 20:55:20 +0200583 test_rtp_seq_state();
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200584 test_transcode_result();
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200585
586 return 0;
587}
588