blob: ebbdbef4008bed0935cb03439e19a9f091e0edf1 [file] [log] [blame]
Harald Weltecd90ed22020-05-14 14:58:52 +02001/* TRAU frame to RTP conversion */
2
3/* (C) 2009,2020 by Harald Welte <laforge@gnumonks.org>
4 * All Rights Reserved
5 *
6 * SPDX-License-Identifier: GPL-2.0+
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#include <errno.h>
24#include <stdlib.h>
25#include <string.h>
26
27#include <osmocom/core/crc8gen.h>
28#include <osmocom/codec/codec.h>
29
30#include <osmocom/trau/trau_frame.h>
31#include <osmocom/trau/trau_rtp.h>
32
33/* this corresponds to the bit-lengths of the individual codec
34 * parameters as indicated in Table 1.1 of TS 46.010 */
35static const uint8_t gsm_fr_map[] = {
36 6, 6, 5, 5, 4, 4, 3, 3,
37 7, 2, 2, 6, 3, 3, 3, 3,
38 3, 3, 3, 3, 3, 3, 3, 3,
39 3, 7, 2, 2, 6, 3, 3, 3,
40 3, 3, 3, 3, 3, 3, 3, 3,
41 3, 3, 7, 2, 2, 6, 3, 3,
42 3, 3, 3, 3, 3, 3, 3, 3,
43 3, 3, 3, 7, 2, 2, 6, 3,
44 3, 3, 3, 3, 3, 3, 3, 3,
45 3, 3, 3, 3
46};
47
48
49/*
50 * EFR TRAU parity
51 *
52 * g(x) = x^3 + x^1 + 1
53 */
54static const struct osmo_crc8gen_code gsm0860_efr_crc3 = {
55 .bits = 3,
56 .poly = 0x3,
57 .init = 0x0,
58 .remainder = 0x7,
59};
60
61/* re-combine EFR parity bits */
62static inline void efr_parity_bits_1(ubit_t *check_bits, const ubit_t *d_bits)
63{
64 memcpy(check_bits + 0 , d_bits + 0, 22);
65 memcpy(check_bits + 22 , d_bits + 24, 3);
66 check_bits[25] = d_bits[28];
67}
68
69static inline void efr_parity_bits_2(ubit_t *check_bits, const ubit_t *d_bits)
70{
71 memcpy(check_bits + 0 , d_bits + 42, 10);
72 memcpy(check_bits + 10 , d_bits + 90, 2);
73}
74
75static inline void efr_parity_bits_3(ubit_t *check_bits, const ubit_t *d_bits)
76{
77 memcpy(check_bits + 0 , d_bits + 98, 5);
78 check_bits[5] = d_bits[104];
79 memcpy(check_bits + 6 , d_bits + 143, 2);
80}
81
82static inline void efr_parity_bits_4(ubit_t *check_bits, const ubit_t *d_bits)
83{
84 memcpy(check_bits + 0 , d_bits + 151, 10);
85 memcpy(check_bits + 10 , d_bits + 199, 2);
86}
87
88static inline void efr_parity_bits_5(ubit_t *check_bits, const ubit_t *d_bits)
89{
90 memcpy(check_bits + 0 , d_bits + 207, 5);
91 check_bits[5] = d_bits[213];
92 memcpy(check_bits + 6 , d_bits + 252, 2);
93}
94
95//static const uint8_t c_bits_check_fr[] = { 0, 0, 0, 1, 0 };
96//static const uint8_t c_bits_check_efr[] = { 1, 1, 0, 1, 0 };
97
98/*! Generate the 33 bytes RTP payload for GSM-FR from a decoded TRAU frame.
99 * \param[out] out caller-provided output buffer
100 * \param[in] out_len length of out buffer in bytes
101 * \param[in] fr input TRAU frame in decoded form
102 * \returns number of bytes generated in 'out'; negative on error. */
103static int trau2rtp_fr(uint8_t *out, size_t out_len, const struct osmo_trau_frame *tf)
104{
105 int i, j, k, l, o;
106
107 if (tf->type != OSMO_TRAU16_FT_FR)
108 return -EINVAL;
109
110 /* FR Data Bits according to TS 48.060 Section 5.5.1.1.2 */
111
112 if (tf->c_bits[11]) /* BFI */
113 return 0;
114
115 if (out_len < GSM_FR_BYTES)
116 return -ENOSPC;
117
118 out[0] = 0xd << 4;
119 /* reassemble d-bits */
120 i = 0; /* counts bits */
121 j = 4; /* counts output bits */
122 k = gsm_fr_map[0]-1; /* current number bit in element */
123 l = 0; /* counts element bits */
124 o = 0; /* offset input bits */
125 while (i < 260) {
126 out[j/8] |= (tf->d_bits[k+o] << (7-(j%8)));
127 /* to avoid out-of-bounds access in gsm_fr_map[++l] */
128 if (i == 259)
129 break;
130 if (--k < 0) {
131 o += gsm_fr_map[l];
132 k = gsm_fr_map[++l]-1;
133 }
134 i++;
135 j++;
136 }
137
138 return GSM_FR_BYTES;
139}
140
141/* See Section 5.2 of RFC5993 */
142enum rtp_hr_ietf_ft {
143 FT_GOOD_SPEECH = 0,
144 FT_GOOD_SID = 2,
145 FT_NO_DATA = 7,
146};
147
148static const uint8_t rtp_hr_sid[14] = { 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
149
150/*! Generate the 14 bytes ETSI TS 101 318 RTP payload for HR from a decoded 16k TRAU frame.
151 * Note that thsi differs from the IETF RFC5993 format. However, as OsmoBTS implements
152 * the TS 101 318 format, we also use the same format here. osmo-mgw can convert them.
153 * \param[out] out caller-provided output buffer
154 * \param[in] out_len length of out buffer in bytes
155 * \param[in] tf input TRAU frame in decoded form
156 * \returns number of bytes generated in 'out'; negative on error. */
157static int trau2rtp_hr16(uint8_t *out, size_t out_len, const struct osmo_trau_frame *tf)
158{
159 unsigned int i;
160
161 if (tf->type != OSMO_TRAU16_FT_HR)
162 return -EINVAL;
163
164 /* HR Data Bits according to TS 48.061 Section 5.1.4.1.1 */
165
166 if (tf->dir == OSMO_TRAU_DIR_UL && tf->c_bits[11]) /* C12: BFI */
167 goto bad_frame;
168
169 if (out_len < GSM_HR_BYTES)
170 return -ENOSPC;
171
172 /* TS 101 318 Section 5.2: The order of occurrence of the codec parameters in the buffer is
173 * the same as order of occurrence over the Abis as defined in annex B of ETS 300 969
174 * [which is 3GPP TS 46.020 */
175 osmo_ubit2pbit(out, tf->d_bits, 112);
176
177 if (tf->c_bits[12] || tf->c_bits[13]) {
178 /* Generate SID frame as per TS 101 318 Section 5.2.2 */
179 for (i = 0; i < sizeof(rtp_hr_sid); i++)
180 out[i] = out[i] | rtp_hr_sid[i];
181 }
182
183 return GSM_HR_BYTES;
184
185bad_frame:
186 return 0;
187}
188
189/*! Generate the 31 bytes RTP payload for GSM-EFR from a decoded TRAU frame.
190 * \param[out] out caller-provided output buffer
191 * \param[in] out_len length of out buffer in bytes
192 * \param[in] fr input TRAU frame in decoded form
193 * \returns number of bytes generated in 'out'; negative on error. */
194static int trau2rtp_efr(uint8_t *out, size_t out_len, const struct osmo_trau_frame *tf)
195{
196 int i, j, rc;
197 ubit_t check_bits[26];
198
199 if (tf->type != OSMO_TRAU16_FT_EFR)
200 return -EINVAL;
201
202 /* FR Data Bits according to TS 48.060 Section 5.5.1.1.2 */
203
204 if (tf->c_bits[11]) /* BFI */
205 return 0;
206
207 if (out_len < GSM_EFR_BYTES)
208 return -ENOSPC;
209
210 if (tf->c_bits[11]) /* BFI */
211 goto bad_frame;
212
213 out[0] = 0xc << 4;
214 /* reassemble d-bits */
215 for (i = 1, j = 4; i < 39; i++, j++)
216 out[j/8] |= (tf->d_bits[i] << (7-(j%8)));
217 efr_parity_bits_1(check_bits, tf->d_bits);
218 rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 26,
219 tf->d_bits + 39);
220 if (rc)
221 goto bad_frame;
222 for (i = 42, j = 42; i < 95; i++, j++)
223 out[j/8] |= (tf->d_bits[i] << (7-(j%8)));
224 efr_parity_bits_2(check_bits, tf->d_bits);
225 rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 12,
226 tf->d_bits + 95);
227 if (rc)
228 goto bad_frame;
229 for (i = 98, j = 95; i < 148; i++, j++)
230 out[j/8] |= (tf->d_bits[i] << (7-(j%8)));
231 efr_parity_bits_3(check_bits, tf->d_bits);
232 rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 8,
233 tf->d_bits + 148);
234 if (rc)
235 goto bad_frame;
236 for (i = 151, j = 145; i < 204; i++, j++)
237 out[j/8] |= (tf->d_bits[i] << (7-(j%8)));
238 efr_parity_bits_4(check_bits, tf->d_bits);
239 rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 12,
240 tf->d_bits + 204);
241 if (rc)
242 goto bad_frame;
243 for (i = 207, j = 198; i < 257; i++, j++)
244 out[j/8] |= (tf->d_bits[i] << (7-(j%8)));
245 efr_parity_bits_5(check_bits, tf->d_bits);
246 rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 8,
247 tf->d_bits + 257);
248 if (rc)
249 goto bad_frame;
250
251 return GSM_EFR_BYTES;
252bad_frame:
253 return 0;
254}
255
256/* TS 48.060 Section 5.5.1.1.2 */
257static int rtp2trau_fr(struct osmo_trau_frame *tf, const uint8_t *data, size_t data_len)
258{
259 int i, j, k, l, o;
260
261 /* data_len == 0 for BFI frame */
262 if (data_len < GSM_FR_BYTES && data_len != 0)
263 return -EINVAL;
264
265 if (data_len && data[0] >> 4 != 0xd)
266 return -EINVAL;
267
268 tf->type = OSMO_TRAU16_FT_FR;
269
270 /* FR Data Bits according to TS 48.060 Section 5.5.1.1.2 */
271
272 /* FIXME: Generate SID frames? */
273
274 /* set c-bits and t-bits */
275 if (tf->dir == OSMO_TRAU_DIR_UL) {
276 /* C1 .. C5 */
277 tf->c_bits[0] = 0;
278 tf->c_bits[1] = 0;
279 tf->c_bits[2] = 0;
280 tf->c_bits[3] = 1;
281 tf->c_bits[4] = 0;
282 } else {
283 /* C1 .. C5 */
284 tf->c_bits[0] = 1;
285 tf->c_bits[1] = 1;
286 tf->c_bits[2] = 1;
287 tf->c_bits[3] = 0;
288 tf->c_bits[4] = 0;
289 }
290 memset(&tf->c_bits[5], 0, 6); /* C6 .. C11: Time Alignment */
291 if (tf->dir == OSMO_TRAU_DIR_UL) {
292 if (data_len == 0)
293 tf->c_bits[11] = 1; /* C12: BFI */
294 else
295 tf->c_bits[11] = 0; /* C12: BFI */
296 tf->c_bits[12] = 0; /* C13: SID=0 */
297 tf->c_bits[13] = 0; /* C14: SID=0 */
298 tf->c_bits[14] = 0; /* C15: TAF (SACCH or not) */
299 tf->c_bits[15] = 1; /* C16: spare */
300 tf->c_bits[16] = 0; /* C17: DTXd not applied */
301 } else {
302 memset(&tf->c_bits[11], 1, 10); /* C12 .. C15: spare */
303 tf->c_bits[15] = 1; /* C16: SP=1 */
304 }
305 memset(&tf->c_bits[17], 1, 4); /* C18 .. C12: spare */
306 memset(&tf->t_bits[0], 1, 4);
307
308 if (!data_len)
309 return 0;
310
311 /* reassemble d-bits */
312 i = 0; /* counts bits */
313 j = 4; /* counts input bits */
314 k = gsm_fr_map[0]-1; /* current number bit in element */
315 l = 0; /* counts element bits */
316 o = 0; /* offset output bits */
317 while (i < 260) {
318 tf->d_bits[k+o] = (data[j/8] >> (7-(j%8))) & 1;
319 /* to avoid out-of-bounds access in gsm_fr_map[++l] */
320 if (i == 259)
321 break;
322 if (--k < 0) {
323 o += gsm_fr_map[l];
324 k = gsm_fr_map[++l]-1;
325 }
326 i++;
327 j++;
328 }
329
330 return 0;
331}
332
333/* does the RTP HR payload resemble a SID frame or not */
334static bool is_rtp_hr_sid(const uint8_t *data, const uint8_t data_len)
335{
336 int i;
337
338 if (data_len < GSM_HR_BYTES)
339 return false;
340
341 for (i = 0; i < GSM_HR_BYTES; i++) {
342 if ((data[i] & rtp_hr_sid[i]) != rtp_hr_sid[i])
343 return false;
344 }
345 return true;
346}
347
348static int rtp2trau_hr16(struct osmo_trau_frame *tf, const uint8_t *data, size_t data_len)
349{
350 if (data_len < GSM_HR_BYTES && data_len != 0)
351 return -EINVAL;
352
353 tf->type = OSMO_TRAU16_FT_HR;
354
355 if (tf->dir == OSMO_TRAU_DIR_UL) {
356 /* C1 .. C5 */
357 tf->c_bits[0] = 0;
358 tf->c_bits[1] = 0;
359 tf->c_bits[2] = 0;
360 tf->c_bits[3] = 1;
361 tf->c_bits[4] = 1;
362 } else {
363 /* C1 .. C5 */
364 tf->c_bits[0] = 1;
365 tf->c_bits[1] = 1;
366 tf->c_bits[2] = 1;
367 tf->c_bits[3] = 0;
368 tf->c_bits[4] = 1;
369 }
370 /* C6.. C11: Time Alignment */
371 memset(tf->c_bits + 5, 0, 6);
372 if (tf->dir == OSMO_TRAU_DIR_UL) {
373 /* BFI */
374 if (data_len == 0)
375 tf->c_bits[11] = 1;
376 else
377 tf->c_bits[11] = 0;
378 if (is_rtp_hr_sid(data, data_len)) {
379 /* SID=2 is a valid SID frame */
380 tf->c_bits[12] = 1;
381 tf->c_bits[13] = 0;
382 } else {
383 tf->c_bits[12] = 0;
384 tf->c_bits[13] = 0;
385 }
386 /* FIXME: C15: TAF */
387 tf->c_bits[15] = 0; /* C16: SP */
388 tf->c_bits[16] = 0; /* C17: DTXd shall not be applied */
389 } else {
390 tf->c_bits[11] = 0; /* C12: UFE */
391 tf->c_bits[12] = 1; /* C13: spare */
392 tf->c_bits[13] = 1; /* C14: spare */
393 tf->c_bits[14] = 1; /* C15: spare */
394 if (is_rtp_hr_sid(data, data_len))
395 tf->c_bits[15] = 0; /* C16: SP */
396 else
397 tf->c_bits[15] = 1; /* C16: SP */
398 tf->c_bits[16] = 1; /* C17: spare */
399 }
400 memset(tf->c_bits+17, 1, 4); /* C18..C21: spare */
401 memset(&tf->t_bits[0], 1, 4);
402 if (tf->dir == OSMO_TRAU_DIR_UL)
403 tf->ufi = 0;
404 else
405 tf->ufi = 1;
406 /* CRC is computed by TRAU frame encoder */
407 if (data_len)
408 memcpy(tf->d_bits, data, GSM_HR_BYTES);
409
410 return 0;
411}
412
413/* TS 48.060 Section 5.5.1.1.2 */
414static int rtp2trau_efr(struct osmo_trau_frame *tf, const uint8_t *data, size_t data_len)
415{
416 int i, j;
417 ubit_t check_bits[26];
418
419 /* data_len == 0 for BFI frame */
420 if (data_len < GSM_EFR_BYTES && data_len != 0)
421 return -EINVAL;
422
423 if (data_len && data[0] >> 4 != 0xc)
424 return -EINVAL;
425
426 tf->type = OSMO_TRAU16_FT_EFR;
427
428 /* FR Data Bits according to TS 48.060 Section 5.5.1.1.2 */
429
430 /* set c-bits and t-bits */
431 tf->c_bits[0] = 1;
432 tf->c_bits[1] = 1;
433 tf->c_bits[2] = 0;
434 tf->c_bits[3] = 1;
435 tf->c_bits[4] = 0;
436
437 memset(&tf->c_bits[5], 0, 6); /* C6 .. C11: Time Alignment */
438 if (tf->dir == OSMO_TRAU_DIR_UL) {
439 if (data_len == 0)
440 tf->c_bits[11] = 1; /* C12: BFI=1 */
441 else
442 tf->c_bits[11] = 0; /* C12: BFI=1 */
443 /* FIXME: Generate SID frames? */
444 tf->c_bits[12] = 0; /* C13: SID=0 */
445 tf->c_bits[13] = 0; /* C14: SID=0 */
446 tf->c_bits[14] = 0; /* C15: TAF (SACCH) */
447 tf->c_bits[15] = 1; /* C16: spare */
448 tf->c_bits[16] = 0; /* C17: DTXd applied */
449 } else {
450 tf->c_bits[11] = 1; /* C12: UFE (good uplink) */
451 memset(&tf->c_bits[12], 1, 3); /* C13 .. C15: spare */
452 tf->c_bits[15] = 1; /* C16: SP=1 */
453 tf->c_bits[16] = 1; /* C17: spare */
454 }
455 memset(&tf->c_bits[17], 1, 4); /* C18 .. C21: spare */
456 memset(&tf->t_bits[0], 1, 4);
457
458 if (data_len == 0)
459 return 0;
460
461 /* reassemble d-bits */
462 tf->d_bits[0] = 1;
463 for (i = 1, j = 4; i < 39; i++, j++)
464 tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
465 efr_parity_bits_1(check_bits, tf->d_bits);
466 osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 26,
467 tf->d_bits + 39);
468 for (i = 42, j = 42; i < 95; i++, j++)
469 tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
470 efr_parity_bits_2(check_bits, tf->d_bits);
471 osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 12,
472 tf->d_bits + 95);
473 for (i = 98, j = 95; i < 148; i++, j++)
474 tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
475 efr_parity_bits_3(check_bits, tf->d_bits);
476 osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 8,
477 tf->d_bits + 148);
478 for (i = 151, j = 145; i < 204; i++, j++)
479 tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
480 efr_parity_bits_4(check_bits, tf->d_bits);
481 osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 12,
482 tf->d_bits + 204);
483 for (i = 207, j = 198; i < 257; i++, j++)
484 tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
485 efr_parity_bits_5(check_bits, tf->d_bits);
486 osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 8,
487 tf->d_bits + 257);
488
489 return 0;
490}
491
492#if 0
493static inline memcpy_inc(uint8_t *out, const uint8_t *in, size_t len, unsigned int *idx)
494{
495 memcpy_inc(out, in, len);
496 *idx += len;
497}
498
499static int amr_speech_extract_sbits(ubit_t *s_bits, const struct osmo_trau_frame *tf,
500 enum osmo_amr_mode mode)
501{
502 unsigned int s_idx = 0;
503
504 switch (mode) {
505 case AMR_4_75:
506 memcpy_inc(s_bits + s_idx, tf->d_bits + 44, 67 - 44, &s_idx);
507 memcpy_inc(s_bits + s_idx, tf->d_bits + 67, 92 - 67, &s_idx);
508 memcpy_inc(s_bits + s_idx, tf->d_bits + 95, 108 - 95, &s_idx);
509 memcpy_inc(s_bits + s_idx, tf->d_bits + 111, 132 - 111, &s_idx);
510 memcpy_inc(s_bits + s_idx, tf->d_bits + 135, 148 - 135, &s_idx);
511 break;
512 case AMR_5_15:
513 memcpy_inc(s_bits + s_idx, tf->d_bits + 46, 96 - 46, &s_idx);
514 memcpy_inc(s_bits + s_idx, tf->d_bits + 69, 92 - 69, &s_idx);
515 memcpy_inc(s_bits + s_idx, tf->d_bits + 95, 114 - 95, &s_idx);
516 memcpy_inc(s_bits + s_idx, tf->d_bits + 117, 136 - 117, &s_idx);
517 memcpy_inc(s_bits + s_idx, tf->d_bits + 139, 158 - 139, &s_idx);
518 break;
519 case AMR_5_90:
520 memcpy_inc(s_bits + s_idx, tf->d_bits + 41, 67 - 41, &s_idx);
521 memcpy_inc(s_bits + s_idx, tf->d_bits + 67, 92 - 67, &s_idx);
522 memcpy_inc(s_bits + s_idx, tf->d_bits + 95, 116 - 95, &s_idx);
523 memcpy_inc(s_bits + s_idx, tf->d_bits + 119, 144 - 119, &s_idx);
524 memcpy_inc(s_bits + s_idx, tf->d_bits + 147, 168 - 147, &s_idx);
525 break;
526 case AMR_6_70:
527 memcpy_inc(s_bits + s_idx, tf->d_bits + 37, 63 - 37, &s_idx);
528 memcpy_inc(s_bits + s_idx, tf->d_bits + 63, 92 - 63, &s_idx);
529 memcpy_inc(s_bits + s_idx, tf->d_bits + 95, 120 - 95, &s_idx);
530 memcpy_inc(s_bits + s_idx, tf->d_bits + 123, 152 - 123, &s_idx);
531 memcpy_inc(s_bits + s_idx, tf->d_bits + 155, 180 - 155, &s_idx);
532 break;
533 case AMR_7_40:
534 memcpy_inc(s_bits + s_idx, tf->d_bits + 34, 60 - 34, &s_idx);
535 memcpy_inc(s_bits + s_idx, tf->d_bits + 60, 92 - 60, &s_idx);
536 memcpy_inc(s_bits + s_idx, tf->d_bits + 95, 124 - 95, &s_idx);
537 memcpy_inc(s_bits + s_idx, tf->d_bits + 127, 159 - 127, &s_idx);
538 memcpy_inc(s_bits + s_idx, tf->d_bits + 162, 191 - 162, &s_idx);
539 break;
540 case AMR_7_95:
541 memcpy_inc(s_bits + s_idx, tf->d_bits + 31, 58 - 31, &s_idx);
542 memcpy_inc(s_bits + s_idx, tf->d_bits + 58, 92 - 58, &s_idx);
543 memcpy_inc(s_bits + s_idx, tf->d_bits + 95, 127 - 95, &s_idx);
544 memcpy_inc(s_bits + s_idx, tf->d_bits + 130, 164 - 130, &s_idx);
545 memcpy_inc(s_bits + s_idx, tf->d_bits + 167, 199 - 167, &s_idx);
546 break;
547 case AMR_10_2:
548 memcpy_inc(s_bits + s_idx, tf->d_bits + 20, 46 - 20, &s_idx); /* D21..D46 */
549 memcpy_inc(s_bits + s_idx, tf->d_bits + 46, 92 - 46, &s_idx);
550 memcpy_inc(s_bits + s_idx, tf->d_bits + 95, 138 - 95, &s_idx);
551 memcpy_inc(s_bits + s_idx, tf->d_bits + 141, 187 - 141, &s_idx);
552 memcpy_inc(s_bits + s_idx, tf->d_bits + 190, 233 - 190, &s_idx);
553 break;
554 case AMR_12_2:
555 memcpy_inc(s_bits + s_idx, tf->d_bits + 0, 38 - 0, &s_idx); /* D1..D38 */
556 memcpy_inc(s_bits + s_idx, tf->d_bits + 38, 91 - 38, &s_idx); /* D39..D91 */
557 memcpy_inc(s_bits + s_idx, tf->d_bits + 94, 144 - 94, &s_idx); /* D95..D144 */
558 memcpy_inc(s_bits + s_idx, tf->d_bits + 147, 200 - 147, &s_idx);/* D148..D200 */
559 memcpy_inc(s_bits + s_idx, tf->d_bits + 203, 253 - 203, &s_idx);/* D204..D253 */
560 break;
561 }
562
563 return s_idx;
564}
565
566/* TS 48.060 Section 5.5.1.2.2 */
567static int trau2rtp_16(uint8_t *out, const struct osmo_trau_frame *tf, enum osmo_amr_mode last_cmi)
568{
569 enum osmo_amr_mode mode = last_cmi;
570 uint8_t frame_class = tf->c_bits[21] << 1 | tf->c_bits[20];
571 uint8_t cmr_cmi = tf->c_bits[23] << 2 | tf->c_bits[24] << 1 | tf->cb_bits[25];
572 uint8_t no_speech_cls;
573 uint8_t s_bits[242];
574 uint8_t d_bits[242];
575 unsigned int s_idx = 0;
576 ubit_t rif = FIXME;
577
578 if (tf->type != OSMO_TRAU16_FT_AMR)
579 return -EINVAL;
580
581 if (rif == 0)
582 mode = cmr_cmi;
583
584 switch (frame_class) {
585 case 0: // no speech
586 no_speech_cls = tf->d_bits[32] << 2 | tf->d_bits[33] << 1 | tf->d_bits[34];
587 cmi_abs = tf->d_bits[35] << 2 | tf->d_bits[36] < 1 || tf->d_bits[37];
588 cmr_abs = tf->d_bits[38] << 2 | tf->d_bits[39] < 1 || tf->d_bits[40];
589 switch (no_speech_cls) {
590 case 7: // sid first
591 break;
592 case 6: // onset
593 break;
594 case 5: // sid_update
595 break;
596 case 4: // sid_bad
597 break;
598 case 0: // no_data
599 break;
600 }
601 break;
602 case 1: // speech bad
603 break;
604 case 2:
605 case 3:
606 /* Extract the s-bits from the TRAU frame */
607 amr_speech_extract_sbits(s_bits, tf, mode);
608 /* Convert the s-bits to d-bits */
609 osmo_amr_s_to_d(d_bits, s_bits, mode);
610 break;
611 }
612}
613
614int trau2rtp_amr(uint8_t *out, const struct osmo_trau_frame *tf, enum osmo_amr_mode last_cmi))
615{
616 switch (tf->type) {
617 case OSMO_TRAU16_FT_AMR:
618 return trau2rtp_16(out, tf, last_cmi);
619 case OSMO_TRAU8_AMR_LOW:
620 case OSMO_TRAU8_AMR_6k7:
621 case OSMO_TRAU8_AMR_7k4:
622 default:
623 return -EINVAL;
624 }
625}
626#endif
627
628int osmo_trau2rtp(uint8_t *out, size_t out_len, const struct osmo_trau_frame *tf,
629 struct osmo_trau2rtp_state *st)
630{
631 switch (tf->type) {
632 case OSMO_TRAU16_FT_FR:
633 return trau2rtp_fr(out, out_len, tf);
634 case OSMO_TRAU16_FT_EFR:
635 return trau2rtp_efr(out, out_len, tf);
636 case OSMO_TRAU16_FT_HR:
637 return trau2rtp_hr16(out, out_len, tf);
638 default:
639 return -EINVAL;
640 }
641}
642
643int osmo_rtp2trau(struct osmo_trau_frame *tf, const uint8_t *rtp, size_t rtp_len,
644 struct osmo_trau2rtp_state *st)
645{
646 switch (st->type) {
647 case OSMO_TRAU16_FT_FR:
648 return rtp2trau_fr(tf, rtp, rtp_len);
649 case OSMO_TRAU16_FT_EFR:
650 return rtp2trau_efr(tf, rtp, rtp_len);
651 case OSMO_TRAU16_FT_HR:
652 return rtp2trau_hr16(tf, rtp, rtp_len);
653 default:
654 return -EINVAL;
655 }
656}