blob: 397469560a1a58aa5cf8e4c7366ab1c874a90063 [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;
183 mgcp_free_endp(endp);
184
185 dst_end = &endp->bts_end;
186 dst_end->payload_type = audio_name_to_type(dstfmt);
187
188 src_end = &endp->net_end;
189 src_end->payload_type = audio_name_to_type(srcfmt);
190
191 if (out_samples) {
192 dst_end->frame_duration_den = dst_end->rate;
193 dst_end->frame_duration_num = out_samples;
194 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 {
346 /* from PCMA to GSM and wrong different ptime */
347 given_configured_endpoint(80, 160, "pcma", "gsm", &ctx, &endp);
348 state = endp->bts_end.rtp_process_data;
349
350 /* Add the first sample */
351 len = audio_packets_pcma[1].len;
352 memcpy(buf, audio_packets_pcma[1].data, len);
353 res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
354 OSMO_ASSERT(state->sample_cnt == 80);
Holger Hans Peter Freytherc8b29082014-07-02 22:02:15 +0200355 OSMO_ASSERT(state->next_time == 232640);
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200356 OSMO_ASSERT(res < 0);
357
358 /* Add the second sample and it should be consumable */
359 len = audio_packets_pcma[2].len;
360 memcpy(buf, audio_packets_pcma[2].data, len);
361 res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf));
362 OSMO_ASSERT(state->sample_cnt == 0);
Holger Hans Peter Freytherc8b29082014-07-02 22:02:15 +0200363 OSMO_ASSERT(state->next_time == 232640 + 80 + 160);
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200364 OSMO_ASSERT(res == sizeof(struct rtp_hdr));
365
366 talloc_free(ctx);
367 }
368}
369
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200370static int test_repacking(int in_samples, int out_samples, int no_transcode)
371{
372 char buf[4096] = {0x80, 0};
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200373 int cc;
374 struct mgcp_endpoint *endp;
375 void *ctx;
376
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200377 struct mgcp_process_rtp_state *state;
378 int in_cnt;
379 int out_size;
380 int in_size;
381 uint32_t ts = 0;
382 uint16_t seq = 0;
383 const char *srcfmt = "pcma";
384 const char *dstfmt = no_transcode ? "pcma" : "l16";
385
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200386 printf("== Transcoding test ==\n");
387 printf("converting %s -> %s\n", srcfmt, dstfmt);
388
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200389 given_configured_endpoint(in_samples, out_samples, srcfmt, dstfmt, &ctx, &endp);
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200390
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200391 state = endp->bts_end.rtp_process_data;
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200392 OSMO_ASSERT(state != NULL);
393
394 in_size = mgcp_transcoding_get_frame_size(state, in_samples, 0);
395 OSMO_ASSERT(sizeof(buf) >= in_size + 12);
396
397 out_size = mgcp_transcoding_get_frame_size(state, -1, 1);
398 OSMO_ASSERT(sizeof(buf) >= out_size + 12);
399
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200400 buf[1] = endp->net_end.payload_type;
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200401 *(uint16_t*)(buf+2) = htons(1);
402 *(uint32_t*)(buf+4) = htonl(0);
403 *(uint32_t*)(buf+8) = htonl(0xaabbccdd);
404
405 for (in_cnt = 0; in_cnt < 16; in_cnt++) {
406 int cont;
407 int len;
408
409 /* fake PCMA data */
410 printf("generating %d %s input samples\n", in_samples, srcfmt);
411 for (cc = 0; cc < in_samples; cc++)
412 buf[12+cc] = cc;
413
414 *(uint16_t*)(buf+2) = htonl(seq);
415 *(uint32_t*)(buf+4) = htonl(ts);
416
417 seq += 1;
418 ts += in_samples;
419
420 cc += 12; /* include RTP header */
421
422 len = cc;
423
424 do {
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200425 cont = mgcp_transcoding_process_rtp(endp, &endp->bts_end,
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200426 buf, &len, sizeof(buf));
427 if (cont == -EAGAIN) {
428 fprintf(stderr, "Got EAGAIN\n");
429 break;
430 }
431
Holger Hans Peter Freyther6041c8d2014-06-28 13:24:36 +0200432 if (cont < 0) {
433 printf("processing failed: %s", strerror(-cont));
434 abort();
435 }
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200436
437 len -= 12; /* ignore RTP header */
438
Holger Hans Peter Freyther4fb7e642014-06-28 00:10:10 +0200439 printf("got %d %s output frames (%d octets) count=%d\n",
440 len / out_size, dstfmt, len, cont);
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200441
442 len = cont;
443 } while (len > 0);
444 }
Holger Hans Peter Freyther83cbac22014-06-22 21:55:50 +0200445
446 talloc_free(ctx);
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200447 return 0;
448}
449
450int main(int argc, char **argv)
451{
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200452 int rc;
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200453 osmo_init_logging(&log_info);
454
455 printf("=== Transcoding Good Cases ===\n");
456
457 transcode_test("l16", "l16",
458 (uint8_t *)audio_packets_l16[0].data,
459 audio_packets_l16[0].len);
460 transcode_test("l16", "gsm",
461 (uint8_t *)audio_packets_l16[0].data,
462 audio_packets_l16[0].len);
463 transcode_test("l16", "pcma",
464 (uint8_t *)audio_packets_l16[0].data,
465 audio_packets_l16[0].len);
466 transcode_test("gsm", "l16",
467 (uint8_t *)audio_packets_gsm[0].data,
468 audio_packets_gsm[0].len);
469 transcode_test("gsm", "gsm",
470 (uint8_t *)audio_packets_gsm[0].data,
471 audio_packets_gsm[0].len);
472 transcode_test("gsm", "pcma",
473 (uint8_t *)audio_packets_gsm[0].data,
474 audio_packets_gsm[0].len);
475 transcode_test("pcma", "l16",
476 (uint8_t *)audio_packets_pcma[0].data,
477 audio_packets_pcma[0].len);
478 transcode_test("pcma", "gsm",
479 (uint8_t *)audio_packets_pcma[0].data,
480 audio_packets_pcma[0].len);
481 transcode_test("pcma", "pcma",
482 (uint8_t *)audio_packets_pcma[0].data,
483 audio_packets_pcma[0].len);
484
485 printf("=== Transcoding Bad Cases ===\n");
486
487 printf("Invalid size:\n");
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200488 rc = transcode_test("gsm", "pcma",
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200489 (uint8_t *)audio_packets_gsm_invalid_size[0].data,
490 audio_packets_gsm_invalid_size[0].len);
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200491 OSMO_ASSERT(rc < 0);
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200492
493 printf("Invalid data:\n");
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200494 rc = transcode_test("gsm", "pcma",
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200495 (uint8_t *)audio_packets_gsm_invalid_data[0].data,
496 audio_packets_gsm_invalid_data[0].len);
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200497 OSMO_ASSERT(rc < 0);
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200498
499 printf("Invalid payload type:\n");
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200500 rc = transcode_test("gsm", "pcma",
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200501 (uint8_t *)audio_packets_gsm_invalid_ptype[0].data,
502 audio_packets_gsm_invalid_ptype[0].len);
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200503 OSMO_ASSERT(rc == 0);
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200504
505 printf("=== Repacking ===\n");
506
507 test_repacking(160, 160, 0);
508 test_repacking(160, 160, 1);
509 test_repacking(160, 80, 0);
510 test_repacking(160, 80, 1);
511 test_repacking(160, 320, 0);
512 test_repacking(160, 320, 1);
513 test_repacking(160, 240, 0);
514 test_repacking(160, 240, 1);
515 test_repacking(160, 100, 0);
516 test_repacking(160, 100, 1);
Holger Hans Peter Freyther91eeeae2014-07-04 20:55:20 +0200517 test_rtp_seq_state();
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200518 test_transcode_result();
Jacob Erlbeck84a45cb2014-04-08 16:10:04 +0200519
520 return 0;
521}
522