lists.osmocom.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

gerrit-log

Thread Start a new thread
Download
Threads by month
  • ----- 2026 -----
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2025 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
gerrit-log@lists.osmocom.org

October 2025

  • 1 participants
  • 631 discussions
[M] Change in libosmo-abis[master]: trau_frame: add support for config frames of 3GPP Rel5+
by falconia 08 Oct '25

08 Oct '25
falconia has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmo-abis/+/41210?usp=email ) Change subject: trau_frame: add support for config frames of 3GPP Rel5+ ...................................................................... trau_frame: add support for config frames of 3GPP Rel5+ 3GPP Rel5 introduced Generic Config Frame format for TFO, defined in TS 28.062 Annex H (globally interoperable interface), and also defined equivalent Speech Codec Configuration Exchange frames on Abis (treated mostly as vendor-private interface by this point), added to TS 48.060 and 48.061. These Generic Config Frames are mandatory for AMR-WB codec, which not only requires TFO in order to be useful (in the absence of all-IP TrFO), but also lacks the ability to stuff TFO config parameters into regular speech frames in the way that was specified in 3GPP Rel4 for AMR-NB. Support for these GCFs on Abis is necessary in order to support TFO-AMR with some vendors' E1 BTS. Some vendors of TDM-based GSM BSS felt no interest in TFO-AMR for its own sake, and only implemented TFO support for AMR (both NB and WB) when forced to do so by AMR-WB market demand; these vendors (Nokia is one known case) skipped 3GPP Rel4 version of TFO-AMR and went directly for Rel5 version, using Generic Config Frames on Abis for both AMR-NB and AMR-WB. Change-Id: Ifbde07e4a3fb80e4faa0b6a6b32938ed98371c5b --- M include/osmocom/trau/trau_frame.h M src/trau/trau_frame.c 2 files changed, 178 insertions(+), 14 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmo-abis refs/changes/10/41210/1 diff --git a/include/osmocom/trau/trau_frame.h b/include/osmocom/trau/trau_frame.h index dd14f27..9048dca 100644 --- a/include/osmocom/trau/trau_frame.h +++ b/include/osmocom/trau/trau_frame.h @@ -62,6 +62,7 @@ #define TRAU_FT_EDATA 0x1f /* 1 1 1 1 1 - 3.5.4 */ #define TRAU_FT_IDLE_UP 0x10 /* 1 0 0 0 0 - 3.5.5 */ #define TRAU_FT_IDLE_DOWN 0x0e /* 0 1 1 1 0 - 3.5.5 */ +#define TRAU_FT_CONFIG_EXCH 0x1e /* 1 1 1 1 0 - TS 48.060 5.5.1.5 */ /* 8k sub-slot types: Bits C1..C5*/ #define TRAU8_FT_SPEECH_UP 0x02 /* 0 0 0 1 P - TS 08.61 5.2.4.1.1 */ @@ -94,6 +95,10 @@ OSMO_TRAU8_AMR_LOW, OSMO_TRAU8_AMR_6k7, OSMO_TRAU8_AMR_7k4, + + /* new types at the end, for ABI compatibility */ + OSMO_TRAU16_FT_CONFIG, + OSMO_TRAU8_CONFIG, }; extern const struct value_string osmo_trau_frame_type_names[]; diff --git a/src/trau/trau_frame.c b/src/trau/trau_frame.c index d0cf3d1..896bc20 100644 --- a/src/trau/trau_frame.c +++ b/src/trau/trau_frame.c @@ -61,12 +61,14 @@ { OSMO_TRAU16_FT_D145_SYNC, "D145_SYNC" }, { OSMO_TRAU16_FT_DATA_HR, "DATA_HR" }, { OSMO_TRAU16_FT_IDLE, "IDLE" }, + { OSMO_TRAU16_FT_CONFIG, "CONFIG" }, { OSMO_TRAU8_SPEECH, "8SPEECH" }, { OSMO_TRAU8_DATA, "8DATA" }, { OSMO_TRAU8_OAM, "8OAM" }, { OSMO_TRAU8_AMR_LOW, "8AMR_LOW" }, { OSMO_TRAU8_AMR_6k7, "8AMR_6k7" }, { OSMO_TRAU8_AMR_7k4, "8AMR_7k4" }, + { OSMO_TRAU8_CONFIG, "8CONFIG" }, { 0, NULL } }; @@ -763,6 +765,57 @@ return 40 * 8; } +/* TS 48.060 sections 5.1.5 and 5.5.1.5: generic configuration frames */ + +static int decode16_gcf(struct osmo_trau_frame *fr, const ubit_t *trau_bits, + enum osmo_trau_frame_direction dir) +{ + int i, d_idx; + + /* C1 .. C5 */ + memcpy(fr->c_bits, trau_bits + 17, 5); + + /* D1 .. D10 */ + memcpy(fr->d_bits, trau_bits + 22, 10); + d_idx = 10; + /* D11 .. D265 */ + for (i = 32; i < 304; i += 16) { + memcpy(fr->d_bits + d_idx, trau_bits + i + 1, 15); + d_idx += 15; + } + /* D266 .. D276 */ + memcpy(fr->d_bits + d_idx, trau_bits + 305, 11); + + /* T1 .. T4 */ + memcpy(fr->t_bits, trau_bits + 316, 4); + + return 0; +} + +static int encode16_gcf(ubit_t *trau_bits, const struct osmo_trau_frame *fr) +{ + int i, d_idx; + + encode_sync16(trau_bits); + + /* C1 .. C5 */ + memcpy(trau_bits + 17, fr->c_bits, 5); + /* D1 .. D10 */ + memcpy(trau_bits + 22, fr->d_bits, 10); + + /* D11 .. D276 */ + for (i = 32, d_idx = 10; i <= 315; i += 16, d_idx += 15) { + trau_bits[i] = 1; + memcpy(trau_bits + i + 1, fr->d_bits + d_idx, 15); + } + + /* T1 .. T4 */ + memcpy(trau_bits + 316, fr->t_bits, 4); + + /* handle timing adjustment */ + return encode16_handle_ta(trau_bits, fr); +} + /* TS 08.61 Section 5.2.1.1 */ static int decode8_hr(struct osmo_trau_frame *fr, const ubit_t *trau_bits, enum osmo_trau_frame_direction dir) @@ -1229,6 +1282,70 @@ return 20 * 8; } +/* TS 48.061 section 5.2.1.3: generic configuration frames */ + +static int decode8_gcf(struct osmo_trau_frame *fr, const ubit_t *trau_bits, + enum osmo_trau_frame_direction dir) +{ + int i, d_idx = 0; + + /* C1 .. C5 */ + memcpy(fr->c_bits, trau_bits + 1 * 8 + 1, 5); + /* D1 .. D2 */ + memcpy(fr->d_bits + d_idx, trau_bits + 1 * 8 + 6, 2); + d_idx += 2; + /* D3 .. D8 */ + memcpy(fr->d_bits + d_idx, trau_bits + 2 * 8 + 2, 6); + d_idx += 6; + /* D9 .. D120 */ + for (i = 3; i < 19; i++) { + memcpy(fr->d_bits + d_idx, trau_bits + i * 8 + 1, 7); + d_idx += 7; + } + /* D121 .. D125 */ + memcpy(fr->d_bits + d_idx, trau_bits + 19 * 8 + 1, 5); + + /* T1 .. T2 */ + memcpy(fr->t_bits, trau_bits + 19 * 8 + 6, 2); + + return 0; +} + +static int encode8_gcf(ubit_t *trau_bits, const struct osmo_trau_frame *fr) +{ + int i, d_idx = 0; + + /* sync pattern */ + memset(trau_bits, 0, 8); + trau_bits[1 * 8 + 0] = 1; + trau_bits[2 * 8 + 0] = 0; + trau_bits[2 * 8 + 1] = 1; + for (i = 3; i < 20; i++) + trau_bits[i * 8] = 1; + + /* C1 .. C5 */ + memcpy(trau_bits + 1 * 8 + 1, fr->c_bits, 5); + /* D1 .. D2 */ + memcpy(trau_bits + 1 * 8 + 6, fr->d_bits + d_idx, 2); + d_idx += 2; + /* D3 .. D8 */ + memcpy(trau_bits + 2 * 8 + 2, fr->d_bits + d_idx, 6); + d_idx += 6; + /* D9 .. D120 */ + for (i = 3; i < 19; i++) { + memcpy(trau_bits + i * 8 + 1, fr->d_bits + d_idx, 7); + d_idx += 7; + } + /* D121 .. D125 */ + memcpy(trau_bits + 19 * 8 + 1, fr->d_bits + d_idx, 5); + + /* T1 .. T2 */ + memcpy(trau_bits + 19 * 8 + 6, fr->t_bits, 2); + + /* handle timing adjustment */ + return encode8_handle_ta(trau_bits, fr); +} + /*! Encode a TRAU frame from its decoded representation to a sequence of unpacked bits. * \param[out] bits caller-allocated buffer for unpacked output bits @@ -1250,17 +1367,18 @@ * The following list summarizes the behavior of the present function with * regard to C1..C5 bits for different frame types: * - * - For all TRAU-16k frame types in both UL and DL directions, and for - * OSMO_TRAU8_SPEECH (TRAU-8k for HRv1 speech) in UL direction, the first 5 - * bits of fr->c_bits[] are ignored and replaced with internally supplied - * constant values. + * - For all TRAU-16k frame types in both UL and DL directions, with the + * exception of newly added OSMO_TRAU16_FT_CONFIG, and for OSMO_TRAU8_SPEECH + * (TRAU-8k for HRv1 speech) in UL direction, the first 5 bits of fr->c_bits[] + * are ignored and replaced with internally supplied constant values. * * - For OSMO_TRAU8_SPEECH in DL direction, only fr->c_bits[3] is used to set * C4; constant values for C1..C3 and odd parity value for C5 are fixed * by the function. * - * - For OSMO_TRAU8_DATA, OSMO_TRAU8_OAM and all AMR-8k frame types, - * user-supplied fr->c_bits[] are always used. + * - For OSMO_TRAU8_DATA, OSMO_TRAU8_OAM and all AMR-8k frame types, as well as + * newly added OSMO_TRAU16_FT_CONFIG and OSMO_TRAU8_CONFIG, user-supplied + * fr->c_bits[] are always used. * * This unfortunate manipulation applies only to C1..C5 as listed above; * for control bits C6 and higher (for frame types that have them), @@ -1277,6 +1395,7 @@ case OSMO_TRAU16_FT_HR: case OSMO_TRAU16_FT_AMR: case OSMO_TRAU16_FT_IDLE: + case OSMO_TRAU16_FT_CONFIG: /* timing alignment may happen: increased space requirement */ if (fr->dir == OSMO_TRAU_DIR_DL && fr->dl_ta_usec > 0) space_req = 2 * 40 * 8 - 1; @@ -1294,6 +1413,7 @@ case OSMO_TRAU8_AMR_LOW: case OSMO_TRAU8_AMR_6k7: case OSMO_TRAU8_AMR_7k4: + case OSMO_TRAU8_CONFIG: /* timing alignment may happen: increased space requirement */ if (fr->dir == OSMO_TRAU_DIR_DL && fr->dl_ta_usec > 0) space_req = 2 * 20 * 8 - 1; @@ -1330,6 +1450,8 @@ return encode16_d145_sync(bits, fr); case OSMO_TRAU16_FT_EDATA: return encode16_edata(bits, fr); + case OSMO_TRAU16_FT_CONFIG: + return encode16_gcf(bits, fr); case OSMO_TRAU8_SPEECH: return encode8_hr(bits, fr, false); case OSMO_TRAU8_DATA: @@ -1342,6 +1464,8 @@ return encode8_amr_67(bits, fr); case OSMO_TRAU8_AMR_7k4: return encode8_amr_74(bits, fr); + case OSMO_TRAU8_CONFIG: + return encode8_gcf(bits, fr); default: return -EINVAL; } @@ -1371,6 +1495,7 @@ case OSMO_TRAU16_FT_FR: case OSMO_TRAU16_FT_EFR: case OSMO_TRAU16_FT_AMR: + case OSMO_TRAU16_FT_CONFIG: if (n_bits < 1 * 40 * 8) return -ENOSPC; break; @@ -1378,6 +1503,7 @@ case OSMO_TRAU8_AMR_LOW: case OSMO_TRAU8_AMR_6k7: case OSMO_TRAU8_AMR_7k4: + case OSMO_TRAU8_CONFIG: if (n_bits < 1 * 20 * 8) return -ENOSPC; break; @@ -1391,6 +1517,8 @@ return encode16_fr(bits, fr, true); case OSMO_TRAU16_FT_AMR: return encode16_amr(bits, fr, true); + case OSMO_TRAU16_FT_CONFIG: + return encode16_gcf(bits, fr); case OSMO_TRAU8_SPEECH: return encode8_hr(bits, fr, true); case OSMO_TRAU8_AMR_LOW: @@ -1399,6 +1527,8 @@ return encode8_amr_67(bits, fr); case OSMO_TRAU8_AMR_7k4: return encode8_amr_74(bits, fr); + case OSMO_TRAU8_CONFIG: + return encode8_gcf(bits, fr); default: return -EINVAL; } @@ -1455,6 +1585,9 @@ case TRAU_FT_D145_SYNC: fr->type = OSMO_TRAU16_FT_D145_SYNC; return decode16_data(fr, bits, dir); + case TRAU_FT_CONFIG_EXCH: + fr->type = OSMO_TRAU16_FT_CONFIG; + return decode16_gcf(fr, bits, dir); default: return -EINVAL; @@ -1499,6 +1632,9 @@ case 0xB: /* OHR_AMR */ fr->type = OSMO_TRAU16_FT_AMR; return decode16_amr(fr, bits, fr->dir); + case TRAU_FT_CONFIG_EXCH >> 1: + fr->type = OSMO_TRAU16_FT_CONFIG; + return decode16_gcf(fr, bits, fr->dir); default: return -EINVAL; } @@ -1617,6 +1753,9 @@ case 0x0B: fr->type = OSMO_TRAU8_OAM; return decode8_oam(fr, bits, dir); + case 0x1F: + fr->type = OSMO_TRAU8_CONFIG; + return decode8_gcf(fr, bits, dir); } } else { /* Downlink */ @@ -1630,6 +1769,9 @@ case 2: fr->type = OSMO_TRAU8_OAM; return decode8_oam(fr, bits, dir); + case 7: + fr->type = OSMO_TRAU8_CONFIG; + return decode8_gcf(fr, bits, dir); } } } else if (is_amr_low(bits)) { @@ -1665,18 +1807,31 @@ * no need to distinguish between HRv1 and AMR-8k frames by their respective * sync patterns: per TS 28.062, these two TFO frame types never occur * in the same bit position in TFO-superimposed PCM speech octets. - * Because HRv1 is the only TFO frame type that can occur in the configuration - * of TS 28.062 section 5.3 (only the one lsb in each PCM speech octet is - * overwritten), this function skips all attempts at frame type classification: - * the TFO application is responsible for detecting the presence of valid - * TFO frames for the negotiated codec type. + * + * Frame type bits C1..C4 are checked only to distinguish between regular + * HRv1 speech frames and Generic Configuration Frames of TS 28.062 Annex H: + * Rel5+ versions of TFO spec allow these GCFs to be used with all codecs + * if both ends of TFO connection implement Rel5+ version of TFO. */ int osmo_trau_frame_decode_tfo_hr1(struct osmo_trau_frame *fr, const ubit_t *bits) { - fr->type = OSMO_TRAU8_SPEECH; + uint8_t cbits4 = get_bits(bits, 9, 4); + /* We don't look at bit C5 because it is EMBED bit in TFO frames */ + + fr->type = OSMO_TRAU_FT_NONE; fr->dir = OSMO_TRAU_DIR_UL; /* TFO frames are modified TRAU-UL */ fr->dl_ta_usec = 0; - return decode8_hr(fr, bits, fr->dir); + + switch (cbits4) { + case 0x01: + fr->type = OSMO_TRAU8_SPEECH; + return decode8_hr(fr, bits, fr->dir); + case 0x0F: + fr->type = OSMO_TRAU8_CONFIG; + return decode8_gcf(fr, bits, fr->dir); + default: + return -EINVAL; + } } /*! Decode/parse an AMR_TFO_8+8k frame from unpacked bits to decoded format. @@ -1690,7 +1845,8 @@ * The second lsb extracted from PCM samples is the entity being decoded here. * Compared to osmo_trau_frame_decode_8k(), the present function requires * the direction to be TRAU-UL (as always the case in TFO) and accepts - * only AMR-8k frame types. + * only AMR-8k frame types, or Generic Configuration Frames of TS 28.062 + * Annex H that are used in Rel5+ version of TFO. */ int osmo_trau_frame_decode_tfo_amr_8k(struct osmo_trau_frame *fr, const ubit_t *bits) { @@ -1707,6 +1863,9 @@ } else if (is_amr_74(bits)) { fr->type = OSMO_TRAU8_AMR_7k4; return decode8_amr_74(fr, bits, fr->dir); + } else if (is_hr(bits) && get_bits(bits, 9, 4) == 0x0F) { + fr->type = OSMO_TRAU8_CONFIG; + return decode8_gcf(fr, bits, fr->dir); } return -EINVAL; -- To view, visit https://gerrit.osmocom.org/c/libosmo-abis/+/41210?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: newchange Gerrit-Project: libosmo-abis Gerrit-Branch: master Gerrit-Change-Id: Ifbde07e4a3fb80e4faa0b6a6b32938ed98371c5b Gerrit-Change-Number: 41210 Gerrit-PatchSet: 1 Gerrit-Owner: falconia <falcon(a)freecalypso.org>
1 0
0 0
[M] Change in libosmo-abis[master]: trau2rtp CSD: add option to emit TW-TS-007 payloads
by falconia 08 Oct '25

08 Oct '25
falconia has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-abis/+/41164?usp=email ) Change subject: trau2rtp CSD: add option to emit TW-TS-007 payloads ...................................................................... trau2rtp CSD: add option to emit TW-TS-007 payloads Setting OSMO_RTP_EXT_TWTS007 bit in st->rtp_extensions switches CSD RTP output format from standard but inefficient CLEARMODE to the compressed-CSD RTP payload format of TW-TS-007. This new mechanism is fully symmetric with already implemented mechanism that enables or disables TW-TS-001 and TW-TS-002 RTP output for FR/HR/EFR speech codecs. Depends: I2cc2c9340f9fa5c7111447a6beef49c335fa1107 (libosmocore) Change-Id: I86d628c65104a119ef0fb9f27f5835c9a1769971 --- M TODO-RELEASE M src/trau/trau_rtp_conv.c 2 files changed, 91 insertions(+), 1 deletion(-) Approvals: falconia: Looks good to me, approved osmith: Looks good to me, but someone else must approve laforge: Looks good to me, but someone else must approve Jenkins Builder: Verified diff --git a/TODO-RELEASE b/TODO-RELEASE index 32849fa..ffa6ecf 100644 --- a/TODO-RELEASE +++ b/TODO-RELEASE @@ -8,3 +8,4 @@ # If any interfaces have been removed or changed since the last public release: c:r:0. #library what description / commit summary line libosmo-netif >1.6.0 stream OSMO_STREAM_{CLI,SRV}_TCP_SOCKOPT_* +libosmogsm >1.11.0 OSMO_RTP_EXT_TWTS007 definition in rtp_extensions.h diff --git a/src/trau/trau_rtp_conv.c b/src/trau/trau_rtp_conv.c index 156b57a..9d23065 100644 --- a/src/trau/trau_rtp_conv.c +++ b/src/trau/trau_rtp_conv.c @@ -1260,6 +1260,7 @@ /* * CSD support: converting TRAU frames of type 'data' to 64 kbit/s * like the RA part of TRAU, using RTP clearmode representation. + * Alternatively, emit compressed-CSD RTP payload format of TW-TS-007. */ static int trau2rtp_data_fr(uint8_t *out, size_t out_len, @@ -1286,6 +1287,34 @@ return OSMO_CLEARMODE_20MS; } +static int trau2rtp_data_fr_ccsd(uint8_t *out, size_t out_len, + const struct osmo_trau_frame *tf) +{ + int len; + + /* function interface preliminaries */ + if (tf->type != OSMO_TRAU16_FT_DATA) + return -EINVAL; + if (out_len < OSMO_CCSD_PL_LEN_9k6) + return -ENOSPC; + + /* Is it TCH/F9.6 with 16 kbit/s IR, + * or TCH/F4.8 or TCH/F2.4 with 8 kbit/s IR? */ + if (tf->c_bits[5]) { + osmo_ccsd_pack_v110_frame(out, tf->d_bits); + osmo_ccsd_pack_v110_frame(out + 8, tf->d_bits + 63); + osmo_ccsd_pack_v110_frame(out + 16, tf->d_bits + 63 * 2); + osmo_ccsd_pack_v110_frame(out + 24, tf->d_bits + 63 * 3); + len = OSMO_CCSD_PL_LEN_9k6; + } else { + osmo_ccsd_pack_v110_frame(out, tf->d_bits); + osmo_ccsd_pack_v110_frame(out + 8, tf->d_bits + 63 * 2); + len = OSMO_CCSD_PL_LEN_4k8; + } + + return len; +} + static int trau2rtp_data_hr16(uint8_t *out, size_t out_len, const struct osmo_trau_frame *tf) { @@ -1305,8 +1334,27 @@ return OSMO_CLEARMODE_20MS; } +static int trau2rtp_data_hr16_ccsd(uint8_t *out, size_t out_len, + const struct osmo_trau_frame *tf) +{ + /* function interface preliminaries */ + if (tf->type != OSMO_TRAU16_FT_DATA_HR) + return -EINVAL; + if (out_len < OSMO_CCSD_PL_LEN_4k8) + return -ENOSPC; + + /* Note that Osmocom trau_frame decoding and encoding API + * puts the second reduced V.110 frame at d_bits position 63, + * unlike 8 kbit/s IR in FR-data frame type where it resides + * at d_bits position 63 * 2. */ + osmo_ccsd_pack_v110_frame(out, tf->d_bits); + osmo_ccsd_pack_v110_frame(out + 8, tf->d_bits + 63); + + return OSMO_CCSD_PL_LEN_4k8; +} + static int trau2rtp_data_hr8(uint8_t *out, size_t out_len, - const struct osmo_trau_frame *tf) + const struct osmo_trau_frame *tf) { /* function interface preliminaries */ if (tf->type != OSMO_TRAU8_DATA) @@ -1320,6 +1368,21 @@ return OSMO_CLEARMODE_20MS; } +static int trau2rtp_data_hr8_ccsd(uint8_t *out, size_t out_len, + const struct osmo_trau_frame *tf) +{ + /* function interface preliminaries */ + if (tf->type != OSMO_TRAU8_DATA) + return -EINVAL; + if (out_len < OSMO_CCSD_PL_LEN_4k8) + return -ENOSPC; + + osmo_ccsd_pack_v110_frame(out, tf->d_bits); + osmo_ccsd_pack_v110_frame(out + 8, tf->d_bits + 63); + + return OSMO_CCSD_PL_LEN_4k8; +} + static int trau2rtp_edata(uint8_t *out, size_t out_len, const struct osmo_trau_frame *tf) { @@ -1337,6 +1400,24 @@ return OSMO_CLEARMODE_20MS; } +static int trau2rtp_edata_ccsd(uint8_t *out, size_t out_len, + const struct osmo_trau_frame *tf) +{ + /* function interface preliminaries */ + if (tf->type != OSMO_TRAU16_FT_EDATA) + return -EINVAL; + if (out_len < OSMO_CCSD_PL_LEN_14k4) + return -ENOSPC; + + /* Per TS 48.020 section 11.1: + * A-TRAU bit C4 is always 1 in BSS->IWF direction + * A-TRAU bit C5 comes from E-TRAU bit C6 */ + osmo_ccsd_pack_atrau_frame(out, tf->m_bits, tf->d_bits, 1, + tf->c_bits[5]); + + return OSMO_CCSD_PL_LEN_14k4; +} + /* * CSD in the opposite direction: from clearmode RTP input * to TRAU frame output. @@ -1700,14 +1781,22 @@ case OSMO_TRAU16_FT_HR: return trau2rtp_hr16(out, out_len, tf, check_twts002(st), ufe); case OSMO_TRAU16_FT_DATA: + if (st->rtp_extensions & OSMO_RTP_EXT_TWTS007) + return trau2rtp_data_fr_ccsd(out, out_len, tf); return trau2rtp_data_fr(out, out_len, tf); case OSMO_TRAU16_FT_DATA_HR: + if (st->rtp_extensions & OSMO_RTP_EXT_TWTS007) + return trau2rtp_data_hr16_ccsd(out, out_len, tf); return trau2rtp_data_hr16(out, out_len, tf); case OSMO_TRAU16_FT_EDATA: + if (st->rtp_extensions & OSMO_RTP_EXT_TWTS007) + return trau2rtp_edata_ccsd(out, out_len, tf); return trau2rtp_edata(out, out_len, tf); case OSMO_TRAU8_SPEECH: return trau2rtp_hr8(out, out_len, tf, check_twts002(st), ufe); case OSMO_TRAU8_DATA: + if (st->rtp_extensions & OSMO_RTP_EXT_TWTS007) + return trau2rtp_data_hr8_ccsd(out, out_len, tf); return trau2rtp_data_hr8(out, out_len, tf); default: return -EINVAL; -- To view, visit https://gerrit.osmocom.org/c/libosmo-abis/+/41164?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: merged Gerrit-Project: libosmo-abis Gerrit-Branch: master Gerrit-Change-Id: I86d628c65104a119ef0fb9f27f5835c9a1769971 Gerrit-Change-Number: 41164 Gerrit-PatchSet: 2 Gerrit-Owner: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
1 0
0 0
[M] Change in libosmo-abis[master]: trau/clearmode.h: add OSMO_CLEARMODE_20MS definition
by falconia 08 Oct '25

08 Oct '25
falconia has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-abis/+/41158?usp=email ) Change subject: trau/clearmode.h: add OSMO_CLEARMODE_20MS definition ...................................................................... trau/clearmode.h: add OSMO_CLEARMODE_20MS definition RFC4040_RTP_PLEN was previously defined privately in OsmoBTS and in trau_rtp_conv.c module in this library, but there was no official definition in any of Osmocom headers. Add <osmocom/trau/clearmode.h> header with OSMO_CLEARMODE_20MS definition. Change-Id: I4b2e49b085574336820468dc8cfb8e32377788bf --- M include/Makefile.am A include/osmocom/trau/clearmode.h M src/trau/trau_rtp_conv.c 3 files changed, 38 insertions(+), 16 deletions(-) Approvals: Jenkins Builder: Verified fixeria: Looks good to me, but someone else must approve laforge: Looks good to me, approved diff --git a/include/Makefile.am b/include/Makefile.am index e9820c8..565e3cb 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -24,6 +24,7 @@ osmocom/abis/trau_frame.h \ osmocom/abis/unixsocket_proto.h \ osmocom/abis/version.h \ + osmocom/trau/clearmode.h \ osmocom/trau/csd_ra2.h \ osmocom/trau/csd_raa_prime.h \ osmocom/trau/tfo_frame.h \ diff --git a/include/osmocom/trau/clearmode.h b/include/osmocom/trau/clearmode.h new file mode 100644 index 0000000..60fbc5a --- /dev/null +++ b/include/osmocom/trau/clearmode.h @@ -0,0 +1,23 @@ +/* + * This header file contains some definitions for CSD in CLEARMODE RTP + * representation. + * + * Author: Mychaela N. Falconia <falcon(a)freecalypso.org>, 2025 - however, + * Mother Mychaela's contributions are NOT subject to copyright. + * No rights reserved, all rights relinquished. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +/* RFC4040 CLEARMODE RTP payload length for 20 ms as specified in TS 48.103 */ +#define OSMO_CLEARMODE_20MS 160 diff --git a/src/trau/trau_rtp_conv.c b/src/trau/trau_rtp_conv.c index f2e0022..f670578 100644 --- a/src/trau/trau_rtp_conv.c +++ b/src/trau/trau_rtp_conv.c @@ -30,12 +30,10 @@ #include <osmocom/trau/trau_frame.h> #include <osmocom/trau/trau_rtp.h> +#include <osmocom/trau/clearmode.h> #include <osmocom/trau/csd_ra2.h> #include <osmocom/trau/csd_raa_prime.h> -/* RFC4040 "clearmode" RTP payload length */ -#define RFC4040_RTP_PLEN 160 - /* this corresponds to the bit-lengths of the individual codec * parameters as indicated in Table 1.1 of TS 46.010 */ static const uint8_t gsm_fr_map[] = { @@ -1304,7 +1302,7 @@ /* function interface preliminaries */ if (tf->type != OSMO_TRAU16_FT_DATA) return -EINVAL; - if (out_len < RFC4040_RTP_PLEN) + if (out_len < OSMO_CLEARMODE_20MS) return -ENOSPC; /* Is it TCH/F9.6 with 16 kbit/s IR, @@ -1319,7 +1317,7 @@ trau2v110_ir8(out + 80, tf->d_bits + 63 * 2); } - return RFC4040_RTP_PLEN; + return OSMO_CLEARMODE_20MS; } static int trau2rtp_data_hr16(uint8_t *out, size_t out_len, @@ -1328,7 +1326,7 @@ /* function interface preliminaries */ if (tf->type != OSMO_TRAU16_FT_DATA_HR) return -EINVAL; - if (out_len < RFC4040_RTP_PLEN) + if (out_len < OSMO_CLEARMODE_20MS) return -ENOSPC; /* Note that Osmocom trau_frame decoding and encoding API @@ -1338,7 +1336,7 @@ trau2v110_ir8(out, tf->d_bits); trau2v110_ir8(out + 80, tf->d_bits + 63); - return RFC4040_RTP_PLEN; + return OSMO_CLEARMODE_20MS; } static int trau2rtp_data_hr8(uint8_t *out, size_t out_len, @@ -1347,13 +1345,13 @@ /* function interface preliminaries */ if (tf->type != OSMO_TRAU8_DATA) return -EINVAL; - if (out_len < RFC4040_RTP_PLEN) + if (out_len < OSMO_CLEARMODE_20MS) return -ENOSPC; trau2v110_ir8(out, tf->d_bits); trau2v110_ir8(out + 80, tf->d_bits + 63); - return RFC4040_RTP_PLEN; + return OSMO_CLEARMODE_20MS; } static int trau2rtp_edata(uint8_t *out, size_t out_len, @@ -1362,7 +1360,7 @@ /* function interface preliminaries */ if (tf->type != OSMO_TRAU16_FT_EDATA) return -EINVAL; - if (out_len < RFC4040_RTP_PLEN) + if (out_len < OSMO_CLEARMODE_20MS) return -ENOSPC; /* Per TS 48.020 section 11.1: @@ -1370,7 +1368,7 @@ * A-TRAU bit C5 comes from E-TRAU bit C6 */ osmo_csd144_to_atrau_ra2(out, tf->m_bits, tf->d_bits, 1, tf->c_bits[5]); - return RFC4040_RTP_PLEN; + return OSMO_CLEARMODE_20MS; } /* @@ -1436,11 +1434,11 @@ { ubit_t ra_bits[80 * 2]; - if (data_len != RFC4040_RTP_PLEN) + if (data_len != OSMO_CLEARMODE_20MS) goto idle_fill; /* reverse RA2 first */ - osmo_csd_ra2_8k_unpack(ra_bits, data, RFC4040_RTP_PLEN); + osmo_csd_ra2_8k_unpack(ra_bits, data, OSMO_CLEARMODE_20MS); /* enforce two properly aligned V.110 frames */ if (!check_v110_align(ra_bits)) @@ -1464,11 +1462,11 @@ { ubit_t ra_bits[80 * 4]; - if (data_len != RFC4040_RTP_PLEN) + if (data_len != OSMO_CLEARMODE_20MS) goto idle_fill; /* reverse RA2 first */ - osmo_csd_ra2_16k_unpack(ra_bits, data, RFC4040_RTP_PLEN); + osmo_csd_ra2_16k_unpack(ra_bits, data, OSMO_CLEARMODE_20MS); /* enforce 4 properly aligned V.110 frames */ if (!check_v110_align(ra_bits)) @@ -1606,7 +1604,7 @@ /* set C6=0: indicate good reception of TRAU-UL frames */ tf->c_bits[5] = 0; - if (data_len == RFC4040_RTP_PLEN && + if (data_len == OSMO_CLEARMODE_20MS && osmo_csd144_from_atrau_ra2(tf->m_bits, tf->d_bits, &atrau_c4, NULL, data) >= 0) { /* We got good A-TRAU input. 3GPP specs define the following -- To view, visit https://gerrit.osmocom.org/c/libosmo-abis/+/41158?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: merged Gerrit-Project: libosmo-abis Gerrit-Branch: master Gerrit-Change-Id: I4b2e49b085574336820468dc8cfb8e32377788bf Gerrit-Change-Number: 41158 Gerrit-PatchSet: 1 Gerrit-Owner: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
1 0
0 0
[M] Change in libosmo-abis[master]: trau: factor out V.110 frame conversion functions
by falconia 08 Oct '25

08 Oct '25
falconia has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-abis/+/41159?usp=email ) Change subject: trau: factor out V.110 frame conversion functions ...................................................................... trau: factor out V.110 frame conversion functions Implementation of CSD conversion between TRAU frames and CLEARMODE inside osmo_trau2rtp() and osmo_rtp2trau() contains lower-level functions for conversion of individual V.110 frames and for alignment checking. Factor these functions out into API, as they are useful for other applications besides TRAU<->RTP conversion: * Compression and decompression functions that convert between standard (but inefficient) CLEARMODE and compressed-CSD RTP format of TW-TS-007; * Implementations of IWFs that terminate CSD RTP streams at the CN and support both CLEARMODE and TW-TS-007. Change-Id: I3f51254b4b985a0f8499c375b61069ca24f77ae8 --- M include/Makefile.am A include/osmocom/trau/csd_v110.h M src/Makefile.am A src/trau/csd_v110.c 4 files changed, 160 insertions(+), 0 deletions(-) Approvals: laforge: Looks good to me, approved fixeria: Looks good to me, but someone else must approve Jenkins Builder: Verified diff --git a/include/Makefile.am b/include/Makefile.am index 565e3cb..862292e 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -27,6 +27,7 @@ osmocom/trau/clearmode.h \ osmocom/trau/csd_ra2.h \ osmocom/trau/csd_raa_prime.h \ + osmocom/trau/csd_v110.h \ osmocom/trau/tfo_frame.h \ osmocom/trau/trau_frame.h \ osmocom/trau/trau_pcu_ericsson.h \ diff --git a/include/osmocom/trau/csd_v110.h b/include/osmocom/trau/csd_v110.h new file mode 100644 index 0000000..05d4ed5 --- /dev/null +++ b/include/osmocom/trau/csd_v110.h @@ -0,0 +1,40 @@ +/* + * This header file defines the public API for some helper functions that + * work with CSD V.110 frames represented in the standard 64 kbit/s CLEARMODE + * format of 3GPP TS 48.103, _without_ compression per TW-TS-007, but _with_ + * Osmocom-introduced constraint that the pair or quadruple of V.110 frames + * in RA2 encoding has to be naturally aligned within each 20 ms RTP packet. + * + * Author: Mychaela N. Falconia <falcon(a)freecalypso.org>, 2025 - however, + * Mother Mychaela's contributions are NOT subject to copyright. + * No rights reserved, all rights relinquished. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#include <stdint.h> +#include <stdbool.h> +#include <osmocom/core/bits.h> + +/* conversion from distilled 63-bit format (as used in TRAU frames) to full + * 80-bit V.110 format, with or without RA2. */ + +void osmo_csd_63bits_to_v110_bits(ubit_t *out, const ubit_t *in); +void osmo_csd_63bits_to_v110_ir8(uint8_t *out, const ubit_t *in); +void osmo_csd_63bits_to_v110_ir16(uint8_t *out, const ubit_t *in); + +/* functions to verify V.110 frame alignment after RA2 decoding, and to convert + * to our distilled 63-bit format. */ + +bool osmo_csd_check_v110_align(const ubit_t *ra_bits); +void osmo_csd_v110_to_63bits(ubit_t *out, const ubit_t *ra_bits); diff --git a/src/Makefile.am b/src/Makefile.am index fc5b59b..6683d44 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -53,6 +53,7 @@ $(NULL) libosmotrau_la_LIBADD = $(COMMONLIBS) $(LIBOSMOCODEC_LIBS) $(ORTP_LIBS) libosmotrau_la_SOURCES = trau/csd_ra2.c \ + trau/csd_v110.c \ trau/raa_prime_decode.c \ trau/raa_prime_encode.c \ trau/tfo_frame.c \ diff --git a/src/trau/csd_v110.c b/src/trau/csd_v110.c new file mode 100644 index 0000000..431073c --- /dev/null +++ b/src/trau/csd_v110.c @@ -0,0 +1,118 @@ +/* + * This C module contains the implementation of CSD V.110 helper functions + * for CLEARMODE defined in <osmocom/trau/csd_v110.h>. + * + * Author: Mychaela N. Falconia <falcon(a)freecalypso.org>, 2025 - however, + * Mother Mychaela's contributions are NOT subject to copyright. + * No rights reserved, all rights relinquished. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <stdint.h> +#include <stdbool.h> +#include <string.h> + +#include <osmocom/core/bits.h> +#include <osmocom/trau/csd_ra2.h> +#include <osmocom/trau/csd_v110.h> + +/*! Convert V.110 frame from distilled 63-bit form (as it appears in TRAU + * frames) to full 80-bit form by adding sync pattern bits. + * \param[out] out buffer of size 80 ubit_t + * \param[in] in 63-bit distilled V.110 frame + */ +void osmo_csd_63bits_to_v110_bits(ubit_t *out, const ubit_t *in) +{ + int i; + + /* the first 8 bits are sync zeros */ + memset(out, 0, 8); + out += 8; + /* for the rest, we have to expand 63 bits into 72 */ + for (i = 0; i < 9; i++) { + *out++ = 1; + memcpy(out, in, 7); + in += 7; + out += 7; + } +} + +/*! Convert V.110 frame from distilled 63-bit form (as it appears in TRAU + * frames) to external octet form (RA2 with 8 kbit/s IR) form by adding + * sync pattern bits and applying RA2. + * \param[out] out buffer of size 80 octets + * \param[in] in 63-bit distilled V.110 frame + */ +void osmo_csd_63bits_to_v110_ir8(uint8_t *out, const ubit_t *in) +{ + ubit_t ra_bits[80]; + + osmo_csd_63bits_to_v110_bits(ra_bits, in); + /* RA2: 1 bit per output byte */ + osmo_csd_ra2_8k_pack(out, ra_bits, 80); +} + +/*! Convert V.110 frame from distilled 63-bit form (as it appears in TRAU + * frames) to external octet form (RA2 with 16 kbit/s IR) form by adding + * sync pattern bits and applying RA2. + * \param[out] out buffer of size 40 octets + * \param[in] in 63-bit distilled V.110 frame + */ +void osmo_csd_63bits_to_v110_ir16(uint8_t *out, const ubit_t *in) +{ + ubit_t ra_bits[80]; + + osmo_csd_63bits_to_v110_bits(ra_bits, in); + /* RA2: 2 bits per output byte */ + osmo_csd_ra2_16k_pack(out, ra_bits, 40); +} + +/*! Check alignment of unpacked 80-bit V.110 frame. + * \param[in] ra_bits candidate V.110 frame in standard 80-bit form + * \returns true if V.110 alignment pattern is correct, false otherwise + */ +bool osmo_csd_check_v110_align(const ubit_t *ra_bits) +{ + int i; + + for (i = 0; i < 8; i++) { + if (ra_bits[i]) + return false; + } + for (i = 1; i < 10; i++) { + if (!ra_bits[i * 8]) + return false; + } + return true; +} + +/*! Convert V.110 frame from standard 80-bit form (unpacked) to + * our distilled 63-bit form (as it appears in TRAU frames). + * \param[out] out buffer of size 63 ubit_t + * \param[in] in 80-bit standard V.110 frame + * + * This function ignores all 17 sync pattern bits and assumes that the + * V.110 frame is correctly aligned. Therefore, this function should + * be called after osmo_csd_check_v110_align(). + */ +void osmo_csd_v110_to_63bits(ubit_t *out, const ubit_t *ra_bits) +{ + memcpy(out, ra_bits + 9, 7); + memcpy(out + 7, ra_bits + 17, 7); + memcpy(out + 14, ra_bits + 25, 7); + memcpy(out + 21, ra_bits + 33, 7); + memcpy(out + 28, ra_bits + 41, 7); + memcpy(out + 35, ra_bits + 49, 7); + memcpy(out + 42, ra_bits + 57, 7); + memcpy(out + 49, ra_bits + 65, 7); + memcpy(out + 56, ra_bits + 73, 7); +} -- To view, visit https://gerrit.osmocom.org/c/libosmo-abis/+/41159?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: merged Gerrit-Project: libosmo-abis Gerrit-Branch: master Gerrit-Change-Id: I3f51254b4b985a0f8499c375b61069ca24f77ae8 Gerrit-Change-Number: 41159 Gerrit-PatchSet: 1 Gerrit-Owner: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
1 0
0 0
[M] Change in libosmo-abis[master]: trau_rtp_conv: use factored-out V.110 functions
by falconia 08 Oct '25

08 Oct '25
falconia has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-abis/+/41160?usp=email ) Change subject: trau_rtp_conv: use factored-out V.110 functions ...................................................................... trau_rtp_conv: use factored-out V.110 functions In the previous patch we factored out V.110 frame conversion functions into API. Now use these new API functions in the implementation of osmo_trau2rtp() and osmo_rtp2trau(). Change-Id: I375311ff9be1b10d27ac94e2e9bd227e7241e7f0 --- M src/trau/trau_rtp_conv.c 1 file changed, 23 insertions(+), 86 deletions(-) Approvals: laforge: Looks good to me, approved Jenkins Builder: Verified fixeria: Looks good to me, but someone else must approve diff --git a/src/trau/trau_rtp_conv.c b/src/trau/trau_rtp_conv.c index f670578..a7184fb 100644 --- a/src/trau/trau_rtp_conv.c +++ b/src/trau/trau_rtp_conv.c @@ -33,6 +33,7 @@ #include <osmocom/trau/clearmode.h> #include <osmocom/trau/csd_ra2.h> #include <osmocom/trau/csd_raa_prime.h> +#include <osmocom/trau/csd_v110.h> /* this corresponds to the bit-lengths of the individual codec * parameters as indicated in Table 1.1 of TS 46.010 */ @@ -1260,42 +1261,6 @@ * like the RA part of TRAU, using RTP clearmode representation. */ -static void trau2v110_bits(ubit_t *out, const ubit_t *in) -{ - int i; - - /* the first 8 bits are sync zeros */ - memset(out, 0, 8); - out += 8; - /* for the rest, we have to expand 63 bits into 72 */ - for (i = 0; i < 9; i++) { - *out++ = 1; - memcpy(out, in, 7); - in += 7; - out += 7; - } -} - -/* intermediate rate 8 kbit/s */ -static void trau2v110_ir8(uint8_t *out, const ubit_t *in) -{ - ubit_t ra_bits[80]; - - trau2v110_bits(ra_bits, in); - /* RA2: 1 bit per output byte */ - osmo_csd_ra2_8k_pack(out, ra_bits, 80); -} - -/* intermediate rate 16 kbit/s */ -static void trau2v110_ir16(uint8_t *out, const ubit_t *in) -{ - ubit_t ra_bits[80]; - - trau2v110_bits(ra_bits, in); - /* RA2: 2 bits per output byte */ - osmo_csd_ra2_16k_pack(out, ra_bits, 40); -} - static int trau2rtp_data_fr(uint8_t *out, size_t out_len, const struct osmo_trau_frame *tf) { @@ -1308,13 +1273,13 @@ /* Is it TCH/F9.6 with 16 kbit/s IR, * or TCH/F4.8 or TCH/F2.4 with 8 kbit/s IR? */ if (tf->c_bits[5]) { - trau2v110_ir16(out, tf->d_bits); - trau2v110_ir16(out + 40, tf->d_bits + 63); - trau2v110_ir16(out + 80, tf->d_bits + 63 * 2); - trau2v110_ir16(out + 120, tf->d_bits + 63 * 3); + osmo_csd_63bits_to_v110_ir16(out, tf->d_bits); + osmo_csd_63bits_to_v110_ir16(out + 40, tf->d_bits + 63); + osmo_csd_63bits_to_v110_ir16(out + 80, tf->d_bits + 63 * 2); + osmo_csd_63bits_to_v110_ir16(out + 120, tf->d_bits + 63 * 3); } else { - trau2v110_ir8(out, tf->d_bits); - trau2v110_ir8(out + 80, tf->d_bits + 63 * 2); + osmo_csd_63bits_to_v110_ir8(out, tf->d_bits); + osmo_csd_63bits_to_v110_ir8(out + 80, tf->d_bits + 63 * 2); } return OSMO_CLEARMODE_20MS; @@ -1333,8 +1298,8 @@ * puts the second reduced V.110 frame at d_bits position 63, * unlike 8 kbit/s IR in FR-data frame type where it resides * at d_bits position 63 * 2. */ - trau2v110_ir8(out, tf->d_bits); - trau2v110_ir8(out + 80, tf->d_bits + 63); + osmo_csd_63bits_to_v110_ir8(out, tf->d_bits); + osmo_csd_63bits_to_v110_ir8(out + 80, tf->d_bits + 63); return OSMO_CLEARMODE_20MS; } @@ -1348,8 +1313,8 @@ if (out_len < OSMO_CLEARMODE_20MS) return -ENOSPC; - trau2v110_ir8(out, tf->d_bits); - trau2v110_ir8(out + 80, tf->d_bits + 63); + osmo_csd_63bits_to_v110_ir8(out, tf->d_bits); + osmo_csd_63bits_to_v110_ir8(out + 80, tf->d_bits + 63); return OSMO_CLEARMODE_20MS; } @@ -1400,34 +1365,6 @@ * how traditional TRAUs do it. */ -static bool check_v110_align(const ubit_t *ra_bits) -{ - int i; - - for (i = 0; i < 8; i++) { - if (ra_bits[i]) - return false; - } - for (i = 1; i < 10; i++) { - if (!ra_bits[i * 8]) - return false; - } - return true; -} - -static void v110_to_63bits(ubit_t *out, const ubit_t *ra_bits) -{ - memcpy(out, ra_bits + 9, 7); - memcpy(out + 7, ra_bits + 17, 7); - memcpy(out + 14, ra_bits + 25, 7); - memcpy(out + 21, ra_bits + 33, 7); - memcpy(out + 28, ra_bits + 41, 7); - memcpy(out + 35, ra_bits + 49, 7); - memcpy(out + 42, ra_bits + 57, 7); - memcpy(out + 49, ra_bits + 65, 7); - memcpy(out + 56, ra_bits + 73, 7); -} - /* intermediate rate 8 kbit/s */ static void rtp2trau_data_ir8(struct osmo_trau_frame *tf, const uint8_t *data, size_t data_len, unsigned second_offset) @@ -1441,14 +1378,14 @@ osmo_csd_ra2_8k_unpack(ra_bits, data, OSMO_CLEARMODE_20MS); /* enforce two properly aligned V.110 frames */ - if (!check_v110_align(ra_bits)) + if (!osmo_csd_check_v110_align(ra_bits)) goto idle_fill; - if (!check_v110_align(ra_bits + 80)) + if (!osmo_csd_check_v110_align(ra_bits + 80)) goto idle_fill; /* all checks passed - copy the payload */ - v110_to_63bits(tf->d_bits, ra_bits); - v110_to_63bits(tf->d_bits + second_offset, ra_bits + 80); + osmo_csd_v110_to_63bits(tf->d_bits, ra_bits); + osmo_csd_v110_to_63bits(tf->d_bits + second_offset, ra_bits + 80); return; idle_fill: @@ -1469,20 +1406,20 @@ osmo_csd_ra2_16k_unpack(ra_bits, data, OSMO_CLEARMODE_20MS); /* enforce 4 properly aligned V.110 frames */ - if (!check_v110_align(ra_bits)) + if (!osmo_csd_check_v110_align(ra_bits)) goto idle_fill; - if (!check_v110_align(ra_bits + 80)) + if (!osmo_csd_check_v110_align(ra_bits + 80)) goto idle_fill; - if (!check_v110_align(ra_bits + 80 * 2)) + if (!osmo_csd_check_v110_align(ra_bits + 80 * 2)) goto idle_fill; - if (!check_v110_align(ra_bits + 80 * 3)) + if (!osmo_csd_check_v110_align(ra_bits + 80 * 3)) goto idle_fill; /* all checks passed - copy the payload */ - v110_to_63bits(tf->d_bits, ra_bits); - v110_to_63bits(tf->d_bits + 63, ra_bits + 80); - v110_to_63bits(tf->d_bits + 63 * 2, ra_bits + 80 * 2); - v110_to_63bits(tf->d_bits + 63 * 3, ra_bits + 80 * 3); + osmo_csd_v110_to_63bits(tf->d_bits, ra_bits); + osmo_csd_v110_to_63bits(tf->d_bits + 63, ra_bits + 80); + osmo_csd_v110_to_63bits(tf->d_bits + 63 * 2, ra_bits + 80 * 2); + osmo_csd_v110_to_63bits(tf->d_bits + 63 * 3, ra_bits + 80 * 3); return; idle_fill: -- To view, visit https://gerrit.osmocom.org/c/libosmo-abis/+/41160?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: merged Gerrit-Project: libosmo-abis Gerrit-Branch: master Gerrit-Change-Id: I375311ff9be1b10d27ac94e2e9bd227e7241e7f0 Gerrit-Change-Number: 41160 Gerrit-PatchSet: 1 Gerrit-Owner: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
1 0
0 0
[M] Change in libosmo-abis[master]: rtp2trau CSD: accept both CLEARMODE and TW-TS-007 payloads
by falconia 08 Oct '25

08 Oct '25
falconia has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-abis/+/41163?usp=email ) Change subject: rtp2trau CSD: accept both CLEARMODE and TW-TS-007 payloads ...................................................................... rtp2trau CSD: accept both CLEARMODE and TW-TS-007 payloads Change-Id: Ide89de89ed43df5762a091f1577a8b8e84b55738 --- M src/trau/trau_rtp_conv.c 1 file changed, 90 insertions(+), 45 deletions(-) Approvals: laforge: Looks good to me, but someone else must approve osmith: Looks good to me, but someone else must approve Jenkins Builder: Verified falconia: Looks good to me, approved diff --git a/src/trau/trau_rtp_conv.c b/src/trau/trau_rtp_conv.c index a7184fb..156b57a 100644 --- a/src/trau/trau_rtp_conv.c +++ b/src/trau/trau_rtp_conv.c @@ -34,6 +34,7 @@ #include <osmocom/trau/csd_ra2.h> #include <osmocom/trau/csd_raa_prime.h> #include <osmocom/trau/csd_v110.h> +#include <osmocom/trau/twts007.h> /* this corresponds to the bit-lengths of the individual codec * parameters as indicated in Table 1.1 of TS 46.010 */ @@ -1370,23 +1371,34 @@ size_t data_len, unsigned second_offset) { ubit_t ra_bits[80 * 2]; + int rc; - if (data_len != OSMO_CLEARMODE_20MS) + switch (data_len) { + case OSMO_CLEARMODE_20MS: + /* reverse RA2 first */ + osmo_csd_ra2_8k_unpack(ra_bits, data, OSMO_CLEARMODE_20MS); + /* enforce two properly aligned V.110 frames */ + if (!osmo_csd_check_v110_align(ra_bits)) + goto idle_fill; + if (!osmo_csd_check_v110_align(ra_bits + 80)) + goto idle_fill; + /* all checks passed - copy the payload */ + osmo_csd_v110_to_63bits(tf->d_bits, ra_bits); + osmo_csd_v110_to_63bits(tf->d_bits + second_offset, + ra_bits + 80); + return; + case OSMO_CCSD_PL_LEN_4k8: + rc = osmo_ccsd_unpack_v110_frame(tf->d_bits, data); + if (rc < 0) + goto idle_fill; + rc = osmo_ccsd_unpack_v110_frame(tf->d_bits + second_offset, + data + 8); + if (rc < 0) + goto idle_fill; + return; + default: goto idle_fill; - - /* reverse RA2 first */ - osmo_csd_ra2_8k_unpack(ra_bits, data, OSMO_CLEARMODE_20MS); - - /* enforce two properly aligned V.110 frames */ - if (!osmo_csd_check_v110_align(ra_bits)) - goto idle_fill; - if (!osmo_csd_check_v110_align(ra_bits + 80)) - goto idle_fill; - - /* all checks passed - copy the payload */ - osmo_csd_v110_to_63bits(tf->d_bits, ra_bits); - osmo_csd_v110_to_63bits(tf->d_bits + second_offset, ra_bits + 80); - return; + } idle_fill: memset(tf->d_bits, 1, 63); @@ -1398,29 +1410,46 @@ size_t data_len) { ubit_t ra_bits[80 * 4]; + int rc; - if (data_len != OSMO_CLEARMODE_20MS) + switch (data_len) { + case OSMO_CLEARMODE_20MS: + /* reverse RA2 first */ + osmo_csd_ra2_16k_unpack(ra_bits, data, OSMO_CLEARMODE_20MS); + /* enforce 4 properly aligned V.110 frames */ + if (!osmo_csd_check_v110_align(ra_bits)) + goto idle_fill; + if (!osmo_csd_check_v110_align(ra_bits + 80)) + goto idle_fill; + if (!osmo_csd_check_v110_align(ra_bits + 80 * 2)) + goto idle_fill; + if (!osmo_csd_check_v110_align(ra_bits + 80 * 3)) + goto idle_fill; + /* all checks passed - copy the payload */ + osmo_csd_v110_to_63bits(tf->d_bits, ra_bits); + osmo_csd_v110_to_63bits(tf->d_bits + 63, ra_bits + 80); + osmo_csd_v110_to_63bits(tf->d_bits + 63 * 2, ra_bits + 80 * 2); + osmo_csd_v110_to_63bits(tf->d_bits + 63 * 3, ra_bits + 80 * 3); + return; + case OSMO_CCSD_PL_LEN_9k6: + rc = osmo_ccsd_unpack_v110_frame(tf->d_bits, data); + if (rc < 0) + goto idle_fill; + rc = osmo_ccsd_unpack_v110_frame(tf->d_bits + 63, data + 8); + if (rc < 0) + goto idle_fill; + rc = osmo_ccsd_unpack_v110_frame(tf->d_bits + 63 * 2, + data + 8 * 2); + if (rc < 0) + goto idle_fill; + rc = osmo_ccsd_unpack_v110_frame(tf->d_bits + 63 * 3, + data + 8 * 3); + if (rc < 0) + goto idle_fill; + return; + default: goto idle_fill; - - /* reverse RA2 first */ - osmo_csd_ra2_16k_unpack(ra_bits, data, OSMO_CLEARMODE_20MS); - - /* enforce 4 properly aligned V.110 frames */ - if (!osmo_csd_check_v110_align(ra_bits)) - goto idle_fill; - if (!osmo_csd_check_v110_align(ra_bits + 80)) - goto idle_fill; - if (!osmo_csd_check_v110_align(ra_bits + 80 * 2)) - goto idle_fill; - if (!osmo_csd_check_v110_align(ra_bits + 80 * 3)) - goto idle_fill; - - /* all checks passed - copy the payload */ - osmo_csd_v110_to_63bits(tf->d_bits, ra_bits); - osmo_csd_v110_to_63bits(tf->d_bits + 63, ra_bits + 80); - osmo_csd_v110_to_63bits(tf->d_bits + 63 * 2, ra_bits + 80 * 2); - osmo_csd_v110_to_63bits(tf->d_bits + 63 * 3, ra_bits + 80 * 3); - return; + } idle_fill: memset(tf->d_bits, 1, 63 * 4); @@ -1532,6 +1561,7 @@ size_t data_len) { ubit_t atrau_c4; + int rc; tf->type = OSMO_TRAU16_FT_EDATA; @@ -1541,9 +1571,12 @@ /* set C6=0: indicate good reception of TRAU-UL frames */ tf->c_bits[5] = 0; - if (data_len == OSMO_CLEARMODE_20MS && - osmo_csd144_from_atrau_ra2(tf->m_bits, tf->d_bits, &atrau_c4, NULL, - data) >= 0) { + switch (data_len) { + case OSMO_CLEARMODE_20MS: + rc = osmo_csd144_from_atrau_ra2(tf->m_bits, tf->d_bits, + &atrau_c4, NULL, data); + if (rc < 0) + goto idle_fill; /* We got good A-TRAU input. 3GPP specs define the following * mapping for DL direction only: * @@ -1551,14 +1584,26 @@ * Spec references: TS 48.020 section 11.1, TS 48.060 * section 6.5.1. */ tf->c_bits[6] = !atrau_c4; - } else { - /* We did not get good A-TRAU input: generate idle fill. */ - memset(tf->m_bits, 1, 2); - memset(tf->d_bits, 1, 288); - /* C7=1 means idle */ - tf->c_bits[6] = 1; + return 0; + case OSMO_CCSD_PL_LEN_14k4: + rc = osmo_ccsd_unpack_atrau_frame(tf->m_bits, tf->d_bits, + &atrau_c4, NULL, data); + if (rc < 0) + goto idle_fill; + /* Semantics remains strictly unchanged between CLEARMODE + * and compressed CSD. */ + tf->c_bits[6] = !atrau_c4; + return 0; + default: + goto idle_fill; } +idle_fill: + /* We did not get good A-TRAU input: generate idle fill. */ + memset(tf->m_bits, 1, 2); + memset(tf->d_bits, 1, 288); + /* C7=1 means idle */ + tf->c_bits[6] = 1; return 0; } -- To view, visit https://gerrit.osmocom.org/c/libosmo-abis/+/41163?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: merged Gerrit-Project: libosmo-abis Gerrit-Branch: master Gerrit-Change-Id: Ide89de89ed43df5762a091f1577a8b8e84b55738 Gerrit-Change-Number: 41163 Gerrit-PatchSet: 2 Gerrit-Owner: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
1 0
0 0
[M] Change in libosmo-abis[master]: trau: add TW-TS-007 packing and unpacking functions
by falconia 08 Oct '25

08 Oct '25
falconia has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-abis/+/41161?usp=email ) Change subject: trau: add TW-TS-007 packing and unpacking functions ...................................................................... trau: add TW-TS-007 packing and unpacking functions TW-TS-007 packing and unpacking functions in <osmocom/trau/twts007.h> are symmetric, as much as feasible, with their CLEARMODE counterparts in <osmocom/trau/csd_v110.h>, <osmocom/trau/csd_ra2.h> and <osmocom/trau/csd_raa_prime.h>. This symmetry is intended to aid implementation of CSD RTP endpoints (TRAU<->RTP functions and IWFs in the CN) that support both payload formats, and it will also serve as a building block for dedicated format conversion functions. Change-Id: Ie81280d2b90f69fbdde9fa968f747a35ea123f79 --- M include/Makefile.am A include/osmocom/trau/twts007.h M src/Makefile.am A src/trau/twts007.c 4 files changed, 173 insertions(+), 1 deletion(-) Approvals: laforge: Looks good to me, but someone else must approve osmith: Looks good to me, but someone else must approve Jenkins Builder: Verified falconia: Looks good to me, approved diff --git a/include/Makefile.am b/include/Makefile.am index 862292e..7c00ccc 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -33,6 +33,7 @@ osmocom/trau/trau_pcu_ericsson.h \ osmocom/trau/trau_rtp.h \ osmocom/trau/trau_sync.h \ + osmocom/trau/twts007.h \ $(NULL) if ENABLE_ORTP diff --git a/include/osmocom/trau/twts007.h b/include/osmocom/trau/twts007.h new file mode 100644 index 0000000..f991379 --- /dev/null +++ b/include/osmocom/trau/twts007.h @@ -0,0 +1,42 @@ +/* + * This header file defines the public API for working with compressed-CSD + * RTP format of TW-TS-007: + * + * https://www.freecalypso.org/specs/tw-ts-007-v010001.txt + * + * Author: Mychaela N. Falconia <falcon(a)freecalypso.org>, 2025 - however, + * Mother Mychaela's contributions are NOT subject to copyright. + * No rights reserved, all rights relinquished. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#pragma once + +#include <stdint.h> +#include <osmocom/core/bits.h> + +/* RTP payload lengths for different modes of compressed CSD */ +#define OSMO_CCSD_PL_LEN_4k8 16 /* TW-TS-007 section 7.2 */ +#define OSMO_CCSD_PL_LEN_9k6 32 /* TW-TS-007 section 7.3 */ +#define OSMO_CCSD_PL_LEN_14k4 37 /* TW-TS-007 section 7.4 */ + +/* low-level CSD frame packing and unpacking functions */ + +void osmo_ccsd_pack_v110_frame(uint8_t *out_bytes, const ubit_t *bits_63); +void osmo_ccsd_pack_atrau_frame(uint8_t *out_bytes, const ubit_t *m_bits, + const ubit_t *d_bits, ubit_t atrau_c4, + ubit_t atrau_c5); + +int osmo_ccsd_unpack_v110_frame(ubit_t *bits_63, const uint8_t *ccsd_bytes); +int osmo_ccsd_unpack_atrau_frame(ubit_t *m_bits, ubit_t *d_bits, + ubit_t *atrau_c4, ubit_t *atrau_c5, + const uint8_t *ccsd_bytes); diff --git a/src/Makefile.am b/src/Makefile.am index 6683d44..b30ebfc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -60,7 +60,8 @@ trau/trau_frame.c \ trau/trau_pcu_ericsson.c \ trau/trau_sync.c \ - trau/trau_rtp_conv.c + trau/trau_rtp_conv.c \ + trau/twts007.c if ENABLE_ORTP libosmotrau_la_SOURCES += trau/osmo_ortp.c diff --git a/src/trau/twts007.c b/src/trau/twts007.c new file mode 100644 index 0000000..255dca7 --- /dev/null +++ b/src/trau/twts007.c @@ -0,0 +1,128 @@ +/* + * This C module contains the implementation of TW-TS-007 compressed CSD + * functions defined in <osmocom/trau/twts007.h>. + * + * Author: Mychaela N. Falconia <falcon(a)freecalypso.org>, 2025 - however, + * Mother Mychaela's contributions are NOT subject to copyright. + * No rights reserved, all rights relinquished. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <stdint.h> +#include <string.h> +#include <errno.h> + +#include <osmocom/core/bits.h> +#include <osmocom/trau/twts007.h> + +/*! Pack V.110 frame content (distilled 63-bit form) into compressed form + * of TW-TS-007 section 7.1. + * \param[out] out_bytes buffer of size 8 bytes + * \param[in] bits_63 63-bit distilled V.110 frame + * + * This function may seem wasteful, doing a memcpy of 63 ubit_t only to + * add a single constant bit and then call osmo_ubit2pbit(). However, + * this data movement path is necessary when converting from TRAU frames + * (struct osmo_trau_frame) to TW-TS-007 compressed format: the 63-bit + * frame has to be mem'copied out of TRAU d_bits into a staging buffer + * of 64 ubit_t before it can be packed into octets. + */ +void osmo_ccsd_pack_v110_frame(uint8_t *out_bytes, const ubit_t *bits_63) +{ + ubit_t bits_64[64]; + + bits_64[0] = 1; + memcpy(bits_64 + 1, bits_63, 63); + osmo_ubit2pbit(out_bytes, bits_64, 64); +} + +/*! Pack A-TRAU frame content (M-bits, D-bits, C4 and C5 metadata flags) + * into compressed form of TW-TS-007 section 7.4. + * \param[out] out_bytes buffer of size 37 bytes + * \param[in] m_bits 2 M-bits associated with this 20 ms CSD frame + * \param[in] d_bits 288 user data bits in this 20 ms CSD frame + * \param[in] atrau_c4 value to be put into A-TRAU frame bit C4 + * \param[in] atrau_c5 value to be put into A-TRAU frame bit C5 + * + * This function is API-symmetric with osmo_csd144_to_atrau_ra2(), + * presenting two alternate ways to represent the same CSD frame + * in RTP, markedly contrasting in efficiency of both payload size + * and encoding/decoding logic. + */ +void osmo_ccsd_pack_atrau_frame(uint8_t *out_bytes, const ubit_t *m_bits, + const ubit_t *d_bits, ubit_t atrau_c4, + ubit_t atrau_c5) +{ + uint8_t head_byte; + + head_byte = 0xB0; + head_byte |= (atrau_c4 << 3); + head_byte |= (atrau_c5 << 2); + head_byte |= (m_bits[0] << 1); + head_byte |= (m_bits[1] << 0); + out_bytes[0] = head_byte; + osmo_ubit2pbit(out_bytes + 1, d_bits, 288); +} + +/*! Extract V.110 frame content (distilled 63-bit form) from compressed form + * of TW-TS-007 section 7.1. + * \param[out] bits_63 buffer of size 63 ubit_t + * \param[in] ccsd_bytes 8-octet compressed V.110 frame of TW-TS-007 + * section 7.1 + * \returns 0 if compressed V.110 frame is good; negative if it is invalid + * + * The same considerations and questions of potential wastefulness that are + * covered above for osmo_ccsd_pack_v110_frame() also apply here. In the + * opposite direction of RTP input to TRAU frames, when a TW-TS-007 compressed + * representation of a V.110 frame is to be unpacked into its corresponding + * 63-bit slot in d_bits of struct osmo_trau_frame, an intermediate unpacking + * step into a temporary buffer of 64 ubit_t, followed by memcpy into TRAU + * d_bits, is unavoidably necessary. + */ +int osmo_ccsd_unpack_v110_frame(ubit_t *bits_63, const uint8_t *ccsd_bytes) +{ + ubit_t bits_64[64]; + + osmo_pbit2ubit(bits_64, ccsd_bytes, 64); + if (!bits_64[0]) + return -EINVAL; + memcpy(bits_63, bits_64 + 1, 63); + return 0; +} + +/*! Extract A-TRAU frame content from compressed form of TW-TS-007 section 7.4. + * \param[out] m_bits caller-provided buffer for 2 M-bits + * \param[out] d_bits caller-provided buffer for 288 user data bits + * \param[out] atrau_c4 return of A-TRAU frame bit C4 (NULL pointer OK) + * \param[out] atrau_c5 return of A-TRAU frame bit C5 (NULL pointer OK) + * \param[in] ccsd_bytes 37-octet compressed V.110 frame of TW-TS-007 + * section 7.4 + * \returns 0 if compressed A-TRAU frame is good; negative if it is invalid + * + * This function is API-symmetric with osmo_csd144_from_atrau_ra2(); + * see comments for osmo_ccsd_pack_atrau_frame(). + */ +int osmo_ccsd_unpack_atrau_frame(ubit_t *m_bits, ubit_t *d_bits, + ubit_t *atrau_c4, ubit_t *atrau_c5, + const uint8_t *ccsd_bytes) +{ + if ((ccsd_bytes[0] & 0xF0) != 0xB0) + return -EINVAL; + if (atrau_c4) + *atrau_c4 = (ccsd_bytes[0] >> 3) & 1; + if (atrau_c5) + *atrau_c5 = (ccsd_bytes[0] >> 2) & 1; + m_bits[0] = (ccsd_bytes[0] >> 1) & 1; + m_bits[1] = (ccsd_bytes[0] >> 0) & 1; + osmo_pbit2ubit(d_bits, ccsd_bytes + 1, 288); + return 0; +} -- To view, visit https://gerrit.osmocom.org/c/libosmo-abis/+/41161?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: merged Gerrit-Project: libosmo-abis Gerrit-Branch: master Gerrit-Change-Id: Ie81280d2b90f69fbdde9fa968f747a35ea123f79 Gerrit-Change-Number: 41161 Gerrit-PatchSet: 2 Gerrit-Owner: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
1 0
0 0
[M] Change in libosmo-abis[master]: trau: add TW-TS-007 compression and decompression functions
by falconia 08 Oct '25

08 Oct '25
falconia has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-abis/+/41162?usp=email ) Change subject: trau: add TW-TS-007 compression and decompression functions ...................................................................... trau: add TW-TS-007 compression and decompression functions These are high-level functions that convert a CSD RTP payload between CLEARMODE and TW-TS-007 formats. Change-Id: I10a86f5e4a7323cf06fb1d2624757c34bd23218f --- M include/osmocom/trau/twts007.h M src/trau/twts007.c 2 files changed, 186 insertions(+), 0 deletions(-) Approvals: Jenkins Builder: Verified falconia: Looks good to me, approved laforge: Looks good to me, but someone else must approve osmith: Looks good to me, but someone else must approve diff --git a/include/osmocom/trau/twts007.h b/include/osmocom/trau/twts007.h index f991379..8a96d13 100644 --- a/include/osmocom/trau/twts007.h +++ b/include/osmocom/trau/twts007.h @@ -40,3 +40,11 @@ int osmo_ccsd_unpack_atrau_frame(ubit_t *m_bits, ubit_t *d_bits, ubit_t *atrau_c4, ubit_t *atrau_c5, const uint8_t *ccsd_bytes); + +/* compression and decompression functions: conversion between CLEARMODE + * and TW-TS-007 formats */ + +int osmo_ccsd_compress(uint8_t *outbuf, size_t outbuf_size, + const uint8_t *input_pl, size_t input_pl_len); +int osmo_ccsd_decompress(uint8_t *outbuf, size_t outbuf_size, + const uint8_t *input_pl, size_t input_pl_len); diff --git a/src/trau/twts007.c b/src/trau/twts007.c index 255dca7..ad09524 100644 --- a/src/trau/twts007.c +++ b/src/trau/twts007.c @@ -22,6 +22,10 @@ #include <errno.h> #include <osmocom/core/bits.h> +#include <osmocom/trau/clearmode.h> +#include <osmocom/trau/csd_ra2.h> +#include <osmocom/trau/csd_raa_prime.h> +#include <osmocom/trau/csd_v110.h> #include <osmocom/trau/twts007.h> /*! Pack V.110 frame content (distilled 63-bit form) into compressed form @@ -126,3 +130,177 @@ osmo_pbit2ubit(d_bits, ccsd_bytes + 1, 288); return 0; } + +static void compress_v110_frame(uint8_t *out, const ubit_t *ra_bits) +{ + ubit_t bits_64[64]; + + /* Do an inline equivalent of osmo_ccsd_pack_v110_frame() + * to save the memcpy of 63 ubit_t. */ + bits_64[0] = 1; + osmo_csd_v110_to_63bits(bits_64 + 1, ra_bits); + osmo_ubit2pbit(out, bits_64, 64); +} + +static int compress_v110_ir8(uint8_t *outbuf, size_t outbuf_size, + const uint8_t *input_pl) +{ + ubit_t ra_bits[80 * 2]; + + if (outbuf_size < OSMO_CCSD_PL_LEN_4k8) + return -ENOSPC; + + /* reverse RA2 first */ + osmo_csd_ra2_8k_unpack(ra_bits, input_pl, OSMO_CLEARMODE_20MS); + + /* enforce two properly aligned V.110 frames */ + if (!osmo_csd_check_v110_align(ra_bits)) + return -EINVAL; + if (!osmo_csd_check_v110_align(ra_bits + 80)) + return -EINVAL; + + /* all checks passed - perform the conversion */ + compress_v110_frame(outbuf, ra_bits); + compress_v110_frame(outbuf + 8, ra_bits + 80); + return OSMO_CCSD_PL_LEN_4k8; +} + +static int compress_v110_ir16(uint8_t *outbuf, size_t outbuf_size, + const uint8_t *input_pl) +{ + ubit_t ra_bits[80 * 4]; + + if (outbuf_size < OSMO_CCSD_PL_LEN_9k6) + return -ENOSPC; + + /* reverse RA2 first */ + osmo_csd_ra2_16k_unpack(ra_bits, input_pl, OSMO_CLEARMODE_20MS); + + /* enforce four properly aligned V.110 frames */ + if (!osmo_csd_check_v110_align(ra_bits)) + return -EINVAL; + if (!osmo_csd_check_v110_align(ra_bits + 80)) + return -EINVAL; + if (!osmo_csd_check_v110_align(ra_bits + 80 * 2)) + return -EINVAL; + if (!osmo_csd_check_v110_align(ra_bits + 80 * 3)) + return -EINVAL; + + /* all checks passed - perform the conversion */ + compress_v110_frame(outbuf, ra_bits); + compress_v110_frame(outbuf + 8, ra_bits + 80); + compress_v110_frame(outbuf + 8 * 2, ra_bits + 80 * 2); + compress_v110_frame(outbuf + 8 * 3, ra_bits + 80 * 3); + return OSMO_CCSD_PL_LEN_9k6; +} + +static int compress_atrau(uint8_t *outbuf, size_t outbuf_size, + const uint8_t *input_pl) +{ + ubit_t d_bits[288], m_bits[2], atrau_c4, atrau_c5; + int rc; + + if (outbuf_size < OSMO_CCSD_PL_LEN_14k4) + return -ENOSPC; + rc = osmo_csd144_from_atrau_ra2(m_bits, d_bits, &atrau_c4, &atrau_c5, + input_pl); + if (rc < 0) + return rc; + osmo_ccsd_pack_atrau_frame(outbuf, m_bits, d_bits, atrau_c4, atrau_c5); + return OSMO_CCSD_PL_LEN_14k4; +} + +/*! Compression function of TW-TS-007 section 8.1: convert RTP payload + * from standard-but-aligned CLEARMODE to compressed CSD. + * \param[out] outbuf Caller-provided buffer for compressed CSD payload + * \param[in] outbuf_size Space available in \ref outbuf + * \param[in] input_pl Received CLEARMODE payload + * \param[in] input_pl_len Length of received payload + * \returns output payload length if successful, negative on errors + */ +int osmo_ccsd_compress(uint8_t *outbuf, size_t outbuf_size, + const uint8_t *input_pl, size_t input_pl_len) +{ + if (input_pl_len != OSMO_CLEARMODE_20MS) + return -EINVAL; + /* format autodetection per TW-TS-007 section 8.1.1 */ + if (input_pl[0] & 0x40) + return compress_v110_ir8(outbuf, outbuf_size, input_pl); + if (input_pl[4] & 0x80) + return compress_v110_ir16(outbuf, outbuf_size, input_pl); + return compress_atrau(outbuf, outbuf_size, input_pl); +} + +static int decompress_v110_ir8(uint8_t *outbuf, const uint8_t *input_pl) +{ + int i; + ubit_t bits_64[64]; + + for (i = 0; i < 2; i++) { + /* Do an inline equivalent of osmo_ccsd_unpack_v110_frame() + * to save the memcpy of 63 ubit_t. */ + osmo_pbit2ubit(bits_64, input_pl, 64); + if (!bits_64[0]) + return -EINVAL; + osmo_csd_63bits_to_v110_ir8(outbuf, bits_64 + 1); + input_pl += 8; + outbuf += 80; + } + return OSMO_CLEARMODE_20MS; +} + +static int decompress_v110_ir16(uint8_t *outbuf, const uint8_t *input_pl) +{ + int i; + ubit_t bits_64[64]; + + for (i = 0; i < 4; i++) { + /* Do an inline equivalent of osmo_ccsd_unpack_v110_frame() + * to save the memcpy of 63 ubit_t. */ + osmo_pbit2ubit(bits_64, input_pl, 64); + if (!bits_64[0]) + return -EINVAL; + osmo_csd_63bits_to_v110_ir16(outbuf, bits_64 + 1); + input_pl += 8; + outbuf += 40; + } + return OSMO_CLEARMODE_20MS; +} + +static int decompress_atrau(uint8_t *outbuf, const uint8_t *input_pl) +{ + ubit_t d_bits[288], m_bits[2], atrau_c4, atrau_c5; + int rc; + + rc = osmo_ccsd_unpack_atrau_frame(m_bits, d_bits, &atrau_c4, &atrau_c5, + input_pl); + if (rc < 0) + return rc; + osmo_csd144_to_atrau_ra2(outbuf, m_bits, d_bits, atrau_c4, atrau_c5); + return OSMO_CLEARMODE_20MS; +} + +/*! Decompression function of TW-TS-007 section 8.2: convert RTP payload + * from compressed CSD to standard CLEARMODE. + * \param[out] outbuf Caller-provided buffer for CLEARMODE payload + * \param[in] outbuf_size Space available in \ref outbuf + * \param[in] input_pl Received compressed CSD payload + * \param[in] input_pl_len Length of received payload + * \returns output payload length if successful, negative on errors + */ +int osmo_ccsd_decompress(uint8_t *outbuf, size_t outbuf_size, + const uint8_t *input_pl, size_t input_pl_len) +{ + if (outbuf_size < OSMO_CLEARMODE_20MS) + return -ENOSPC; + switch (input_pl_len) { + case OSMO_CCSD_PL_LEN_4k8: + return decompress_v110_ir8(outbuf, input_pl); + case OSMO_CCSD_PL_LEN_9k6: + return decompress_v110_ir16(outbuf, input_pl); + case OSMO_CCSD_PL_LEN_14k4: + return decompress_atrau(outbuf, input_pl); + default: + return -EINVAL; + } +} -- To view, visit https://gerrit.osmocom.org/c/libosmo-abis/+/41162?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: merged Gerrit-Project: libosmo-abis Gerrit-Branch: master Gerrit-Change-Id: I10a86f5e4a7323cf06fb1d2624757c34bd23218f Gerrit-Change-Number: 41162 Gerrit-PatchSet: 2 Gerrit-Owner: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
1 0
0 0
[M] Change in libosmo-abis[master]: trau2rtp CSD: add option to emit TW-TS-007 payloads
by falconia 08 Oct '25

08 Oct '25
falconia has posted comments on this change by falconia. ( https://gerrit.osmocom.org/c/libosmo-abis/+/41164?usp=email ) Change subject: trau2rtp CSD: add option to emit TW-TS-007 payloads ...................................................................... Patch Set 2: Code-Review+2 -- To view, visit https://gerrit.osmocom.org/c/libosmo-abis/+/41164?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: comment Gerrit-Project: libosmo-abis Gerrit-Branch: master Gerrit-Change-Id: I86d628c65104a119ef0fb9f27f5835c9a1769971 Gerrit-Change-Number: 41164 Gerrit-PatchSet: 2 Gerrit-Owner: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: osmith <osmith(a)sysmocom.de> Gerrit-Comment-Date: Wed, 08 Oct 2025 14:13:08 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes
1 0
0 0
[M] Change in libosmo-abis[master]: rtp2trau CSD: accept both CLEARMODE and TW-TS-007 payloads
by falconia 08 Oct '25

08 Oct '25
falconia has posted comments on this change by falconia. ( https://gerrit.osmocom.org/c/libosmo-abis/+/41163?usp=email ) Change subject: rtp2trau CSD: accept both CLEARMODE and TW-TS-007 payloads ...................................................................... Patch Set 2: Code-Review+2 -- To view, visit https://gerrit.osmocom.org/c/libosmo-abis/+/41163?usp=email To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email Gerrit-MessageType: comment Gerrit-Project: libosmo-abis Gerrit-Branch: master Gerrit-Change-Id: Ide89de89ed43df5762a091f1577a8b8e84b55738 Gerrit-Change-Number: 41163 Gerrit-PatchSet: 2 Gerrit-Owner: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: falconia <falcon(a)freecalypso.org> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: osmith <osmith(a)sysmocom.de> Gerrit-Comment-Date: Wed, 08 Oct 2025 14:13:00 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • ...
  • 64
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.