falconia has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/libosmo-abis/+/37156?usp=email )


Change subject: TRAU->RTP: add support for TW-TS-001 & TW-TS-002
......................................................................

TRAU->RTP: add support for TW-TS-001 & TW-TS-002

The industry standard RTP payload formats of RFC 3551 and RFC 5993
drop valuable metadata from TRAU-UL frames of GSM 08.60 & 08.61,
and disallow transport of marked-bad frames.  Enhanced RTP transport
formats of TW-TS-001 (FR & EFR) and TW-TS-002 (HR) restore these
capabilities - however, because these formats are non-standard
outside of Osmocom+Themyscira GSM networks, their use can only be
optional.

Add rtp_extensions member to struct osmo_trau2rtp_state, specifying
the mask of RTP extensions to be used, just like we defined for
AoIP BSSMAP and Abis-IP RSL, and extend osmo_trau2rtp() to emit
these enhanced RTP formats when they are enabled.

Depends: I0eccfe5ddcf44f8f20440acb01e2d4870ec0cd91 (libosmocore)
Related: OS#6448
Change-Id: I7a6d13d406484c01210594bb6d2f0aff7c1341ab
---
M include/osmocom/trau/trau_rtp.h
M src/trau/trau_rtp_conv.c
2 files changed, 136 insertions(+), 35 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/libosmo-abis refs/changes/56/37156/1

diff --git a/include/osmocom/trau/trau_rtp.h b/include/osmocom/trau/trau_rtp.h
index f02d43e..6b2110f 100644
--- a/include/osmocom/trau/trau_rtp.h
+++ b/include/osmocom/trau/trau_rtp.h
@@ -24,6 +24,7 @@

 struct osmo_trau2rtp_state {
        enum osmo_trau_frame_type type;
+       uint8_t rtp_extensions;
 };


diff --git a/src/trau/trau_rtp_conv.c b/src/trau/trau_rtp_conv.c
index e4aa885..d92cc0d 100644
--- a/src/trau/trau_rtp_conv.c
+++ b/src/trau/trau_rtp_conv.c
@@ -26,6 +26,7 @@

 #include <osmocom/core/crc8gen.h>
 #include <osmocom/codec/codec.h>
+#include <osmocom/gsm/rtp_extensions.h>

 #include <osmocom/trau/trau_frame.h>
 #include <osmocom/trau/trau_rtp.h>
@@ -100,20 +101,34 @@
  *  \param[in] out_len length of out buffer in bytes
  *  \param[in] fr input TRAU frame in decoded form
  *  \returns number of bytes generated in 'out'; negative on error. */
-static int trau2rtp_fr(uint8_t *out, size_t out_len, const struct 
osmo_trau_frame *tf)
+static int trau2rtp_fr(uint8_t *out, size_t out_len, const struct 
osmo_trau_frame *tf, bool emit_twts001)
 {
+       size_t req_out_len = emit_twts001 ? GSM_FR_BYTES+1 : GSM_FR_BYTES;
        int i, j, k, l, o;
+       uint8_t hdr_byte;

        if (tf->type != OSMO_TRAU16_FT_FR)
                return -EINVAL;

+       if (out_len < req_out_len)
+               return -ENOSPC;
+
        /* FR Data Bits according to TS 48.060 Section 5.5.1.1.2 */

-       if (tf->c_bits[11]) /* BFI */
-               return 0;
+       /* Are we emitting TW-TS-001? If so, emit TRAU-like Extension Header */
+       if (emit_twts001) {
+               hdr_byte = 0xE0;
+               if (tf->c_bits[16])     /* DTXd */
+                       hdr_byte |= 0x08;
+               if (tf->c_bits[11])     /* BFI */
+                       hdr_byte |= 0x02;
+               if (tf->c_bits[14])     /* TAF */
+                       hdr_byte |= 0x01;
+               *out++ = hdr_byte;
+       }

-       if (out_len < GSM_FR_BYTES)
-               return -ENOSPC;
+       if (tf->c_bits[11] && !emit_twts001) /* BFI without TW-TS-001 */
+               return 0;

        out[0] = 0xd << 4;
        /* reassemble d-bits */
@@ -135,18 +150,30 @@
                j++;
        }

-       return GSM_FR_BYTES;
+       return req_out_len;
 }

-/* See Section 5.2 of RFC5993 */
-enum rtp_hr_ietf_ft {
-       FT_GOOD_SPEECH  = 0,
-       FT_GOOD_SID     = 2,
-       FT_NO_DATA      = 7,
+/* See Section 5.2 of RFC5993 and TW-TS-002 */
+enum super5993_ft {
+       FT_GOOD_SPEECH          = 0,
+       FT_INVALID_SID          = 1,
+       FT_GOOD_SID             = 2,
+       FT_BFI_WITH_DATA        = 6,
+       FT_NO_DATA              = 7,
 };

 static const uint8_t rtp_hr_sid[14] = { 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };

+static void twtw002_hr16_set_extra_flags(uint8_t *out, const struct 
osmo_trau_frame *tf)
+{
+       if (tf->c_bits[16])     /* DTXd */
+               out[0] |= 0x08;
+       if (tf->ufi)            /* UFI */
+               out[0] |= 0x02;
+       if (tf->c_bits[14])     /* TAF */
+               out[0] |= 0x01;
+}
+
 /*! Generate an RFC 5993 RTP payload for HR from a decoded 16k TRAU frame.
  *  We previously emitted TS 101 318 format; however, RFC 5993 is the format
  *  specified in TS 48.103 for AoIP, it can also be extended with TRAU-UL-like
@@ -156,7 +183,7 @@
  *  \param[in] out_len length of out buffer in bytes
  *  \param[in] tf input TRAU frame in decoded form
  *  \returns number of bytes generated in 'out'; negative on error. */
-static int trau2rtp_hr16(uint8_t *out, size_t out_len, const struct 
osmo_trau_frame *tf)
+static int trau2rtp_hr16(uint8_t *out, size_t out_len, const struct 
osmo_trau_frame *tf, bool emit_twts002)
 {
        enum osmo_gsm631_sid_class sidc;

@@ -175,26 +202,46 @@

        /* Plain RFC 5993 without TW-TS-002 extensions does not allow
         * BFI or invalid SID packets. */
-       if (tf->c_bits[11] || sidc == OSMO_GSM631_SID_CLASS_INVALID)
+       if (!emit_twts002 &&
+           (tf->c_bits[11] || sidc == OSMO_GSM631_SID_CLASS_INVALID))
                goto bad_frame;

+       /* BFI turns valid SID into invalid */
+       if (tf->c_bits[11] && sidc == OSMO_GSM631_SID_CLASS_VALID)
+               sidc = OSMO_GSM631_SID_CLASS_INVALID;
+
        /* RFC 5993 Frame Type is equal to GSM 06.41 SID classification,
-        * restricted to just speech or valid SID per above. */
+        * restricted to just speech or valid SID per above.  Or if we
+        * emit TW-TS-002, that restriction is lifted. */
        out[0] = sidc << 4;

+       if (emit_twts002) {
+               if (tf->c_bits[11] && sidc == OSMO_GSM631_SID_CLASS_SPEECH)
+                       out[0] = FT_BFI_WITH_DATA << 4;
+               twtw002_hr16_set_extra_flags(out, tf);
+               /* invalid SID frames are truncated in TW-TS-002 */
+               if (sidc == OSMO_GSM631_SID_CLASS_INVALID)
+                       return 1;
+       }
+
        /* TS 101 318 Section 5.2: The order of occurrence of the codec 
parameters in the buffer is
         * the same as order of occurrence over the Abis as defined in annex B 
of ETS 300 969
         * [which is 3GPP TS 46.020 */
        osmo_ubit2pbit(out + 1, tf->d_bits, 112);

        /* RFC 5993 requires SID frames to be perfect, error-free */
-       if (sidc == OSMO_GSM631_SID_CLASS_VALID)
+       if (!emit_twts002 && sidc == OSMO_GSM631_SID_CLASS_VALID)
                osmo_hr_sid_reset(out + 1);

        return GSM_HR_BYTES_RTP_RFC5993;

 bad_frame:
-       return 0;
+       if (emit_twts002) {
+               out[0] = FT_NO_DATA << 4;
+               twtw002_hr16_set_extra_flags(out, tf);
+               return 1;
+       } else
+               return 0;
 }

 /*! Generate the 31 bytes RTP payload for GSM-EFR from a decoded TRAU frame.
@@ -202,25 +249,37 @@
  *  \param[in] out_len length of out buffer in bytes
  *  \param[in] fr input TRAU frame in decoded form
  *  \returns number of bytes generated in 'out'; negative on error. */
-static int trau2rtp_efr(uint8_t *out, size_t out_len, const struct 
osmo_trau_frame *tf)
+static int trau2rtp_efr(uint8_t *out, size_t out_len, const struct 
osmo_trau_frame *tf, bool emit_twts001)
 {
+       size_t req_out_len = emit_twts001 ? GSM_EFR_BYTES+1 : GSM_EFR_BYTES;
        int i, j, rc;
        ubit_t check_bits[26];
+       uint8_t hdr_byte;
+       bool crc_bfi = false;
+
+       if (out_len < req_out_len)
+               return -ENOSPC;

        if (tf->type != OSMO_TRAU16_FT_EFR)
                return -EINVAL;

        /* FR Data Bits according to TS 48.060 Section 5.5.1.1.2 */

-       if (tf->c_bits[11]) /* BFI */
+       /* Are we emitting TW-TS-001? If so, emit TRAU-like Extension Header */
+       if (emit_twts001) {
+               hdr_byte = 0xE0;
+               if (tf->c_bits[16])     /* DTXd */
+                       hdr_byte |= 0x08;
+               if (tf->c_bits[11])     /* BFI */
+                       hdr_byte |= 0x02;
+               if (tf->c_bits[14])     /* TAF */
+                       hdr_byte |= 0x01;
+               *out++ = hdr_byte;
+       }
+
+       if (tf->c_bits[11] && !emit_twts001) /* BFI without TW-TS-001 */
                return 0;

-       if (out_len < GSM_EFR_BYTES)
-               return -ENOSPC;
-
-       if (tf->c_bits[11]) /* BFI */
-               goto bad_frame;
-
        out[0] = 0xc << 4;
        /* reassemble d-bits */
        for (i = 1, j = 4; i < 39; i++, j++)
@@ -229,39 +288,40 @@
        rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 26,
                        tf->d_bits + 39);
        if (rc)
-               goto bad_frame;
+               crc_bfi = true;
        for (i = 42, j = 42; i < 95; i++, j++)
                out[j/8] |= (tf->d_bits[i] << (7-(j%8)));
        efr_parity_bits_2(check_bits, tf->d_bits);
        rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 12,
                        tf->d_bits + 95);
        if (rc)
-               goto bad_frame;
+               crc_bfi = true;
        for (i = 98, j = 95; i < 148; i++, j++)
                out[j/8] |= (tf->d_bits[i] << (7-(j%8)));
        efr_parity_bits_3(check_bits, tf->d_bits);
        rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 8,
                        tf->d_bits + 148);
        if (rc)
-               goto bad_frame;
+               crc_bfi = true;
        for (i = 151, j = 145; i < 204; i++, j++)
                out[j/8] |= (tf->d_bits[i] << (7-(j%8)));
        efr_parity_bits_4(check_bits, tf->d_bits);
        rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 12,
                        tf->d_bits + 204);
        if (rc)
-               goto bad_frame;
+               crc_bfi = true;
        for (i = 207, j = 198; i < 257; i++, j++)
                out[j/8] |= (tf->d_bits[i] << (7-(j%8)));
        efr_parity_bits_5(check_bits, tf->d_bits);
        rc = osmo_crc8gen_check_bits(&gsm0860_efr_crc3, check_bits, 8,
                        tf->d_bits + 257);
        if (rc)
-               goto bad_frame;
+               crc_bfi = true;

-       return GSM_EFR_BYTES;
-bad_frame:
-       return 0;
+       if (crc_bfi && !emit_twts001)
+               return 0;
+
+       return req_out_len;
 }

 /* TS 48.060 Section 5.5.1.1.2 */
@@ -721,16 +781,32 @@
 }
 #endif

+static inline bool check_twts001(struct osmo_trau2rtp_state *st)
+{
+       if (st->rtp_extensions & OSMO_RTP_EXT_TWTS001)
+               return true;
+       else
+               return false;
+}
+
+static inline bool check_twts002(struct osmo_trau2rtp_state *st)
+{
+       if (st->rtp_extensions & OSMO_RTP_EXT_TWTS002)
+               return true;
+       else
+               return false;
+}
+
 int osmo_trau2rtp(uint8_t *out, size_t out_len, const struct osmo_trau_frame 
*tf,
                  struct osmo_trau2rtp_state *st)
 {
        switch (tf->type) {
        case OSMO_TRAU16_FT_FR:
-               return trau2rtp_fr(out, out_len, tf);
+               return trau2rtp_fr(out, out_len, tf, check_twts001(st));
        case OSMO_TRAU16_FT_EFR:
-               return trau2rtp_efr(out, out_len, tf);
+               return trau2rtp_efr(out, out_len, tf, check_twts001(st));
        case OSMO_TRAU16_FT_HR:
-               return trau2rtp_hr16(out, out_len, tf);
+               return trau2rtp_hr16(out, out_len, tf, check_twts002(st));
        default:
                return -EINVAL;
        }

--
To view, visit https://gerrit.osmocom.org/c/libosmo-abis/+/37156?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: libosmo-abis
Gerrit-Branch: master
Gerrit-Change-Id: I7a6d13d406484c01210594bb6d2f0aff7c1341ab
Gerrit-Change-Number: 37156
Gerrit-PatchSet: 1
Gerrit-Owner: falconia <fal...@freecalypso.org>
Gerrit-MessageType: newchange

Reply via email to