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


Change subject: trau_rtp_conv: add support for HRv1 in 8k format
......................................................................

trau_rtp_conv: add support for HRv1 in 8k format

GSM 08.61 defines two alternative Abis transport formats for
HRv1 codec, using either 16 kbit/s or 8 kbit/s submultiplexing,
as chosen by each BSS hardware manufacturer.  libosmotrau previously
supported TRAU<->RTP conversion only for 16k format - add support
for HRv1 in 8k submux format.

Change-Id: I8ee01b73360501ca380a8695cbc7070ceaaba1be
---
M src/trau/trau_rtp_conv.c
1 file changed, 188 insertions(+), 0 deletions(-)



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

diff --git a/src/trau/trau_rtp_conv.c b/src/trau/trau_rtp_conv.c
index 91bf228..0dcd1b0 100644
--- a/src/trau/trau_rtp_conv.c
+++ b/src/trau/trau_rtp_conv.c
@@ -249,6 +249,112 @@
                return 0;
 }

+static bool hr8_xc_bits_good_parity(const ubit_t *xc_bits)
+{
+       int i;
+       unsigned int sum = 0;
+
+       for (i = 0; i < 6; i++) {
+               if (xc_bits[i])
+                       sum++;
+       }
+       if (sum & 1)
+               return true;    /* odd sum good */
+       else
+               return false;   /* even sum bad */
+}
+
+static void twts002_hr8_set_extra_flags(uint8_t *out, const struct 
osmo_trau_frame *tf)
+{
+       if (tf->c_bits[8])      /* DTXd */
+               out[0] |= 0x08;
+       if (tf->xc_bits[4])     /* UFI */
+               out[0] |= 0x02;
+}
+
+/*! Generate an RFC 5993 or TW-TS-002 RTP payload for HRv1
+ *  from a decoded 8k TRAU frame.
+ *  \param[out] out caller-provided output buffer
+ *  \param[in] out_len length of out buffer in bytes
+ *  \param[in] tf input TRAU frame in decoded form
+ *  \param[in] emit_twts002 self-explanatory
+ *  \returns number of bytes generated in 'out'; negative on error. */
+static int trau2rtp_hr8(uint8_t *out, size_t out_len,
+                       const struct osmo_trau_frame *tf, bool emit_twts002)
+{
+       unsigned xc1_4;
+
+       /* function interface preliminaries */
+       if (tf->type != OSMO_TRAU8_SPEECH)
+               return -EINVAL;
+       if (out_len < GSM_HR_BYTES_RTP_RFC5993)
+               return -ENOSPC;
+
+       /* Before considering anything else, if we have bad parity in
+        * frame classification bits or bad CRC in payload bits,
+        * we treat this frame as totally invalid: BFI with no data. */
+       if (!hr8_xc_bits_good_parity(tf->xc_bits) ||
+           osmo_crc8gen_check_bits(&gsm0860_efr_crc3, tf->d_bits, 44,
+                                   tf->crc_bits))
+               goto bad_frame;
+
+       /* classify this frame per XC1..XC4 */
+       xc1_4 = (tf->xc_bits[0] << 3) | (tf->xc_bits[1] << 2) |
+               (tf->xc_bits[2] << 1) | (tf->xc_bits[3] << 0);
+       switch (xc1_4) {
+       case 0:
+               /* good speech frame (BFI=0, SID=0) */
+               out[0] = FT_GOOD_SPEECH << 4;
+               if (emit_twts002)
+                       twts002_hr8_set_extra_flags(out, tf);
+               osmo_ubit2pbit(out + 1, tf->d_bits, 112);
+               return GSM_HR_BYTES_RTP_RFC5993;
+       case 1:
+               /* valid SID frame (BFI=0, SID=2) */
+               out[0] = FT_GOOD_SID << 4;
+               if (emit_twts002)
+                       twts002_hr8_set_extra_flags(out, tf);
+               osmo_ubit2pbit(out + 1, tf->d_bits, 112);
+               /* RFC 5993 requires SID frames to be perfect, error-free */
+               if (!emit_twts002)
+                       osmo_hr_sid_reset(out + 1);
+               return GSM_HR_BYTES_RTP_RFC5993;
+       case 4:
+       case 5:
+               /* invalid SID frame (multiple BFI/SID combinations) */
+               /* can be represented only in TW-TS-002, not in RFC 5993 */
+               if (!emit_twts002)
+                       return 0;
+               out[0] = FT_INVALID_SID << 4;
+               twts002_hr8_set_extra_flags(out, tf);
+               /* XC4 is TAF with this frame type */
+               if (tf->xc_bits[3])
+                       out[0] |= 0x01;
+               return 1;       /* short format per TW-TS-002 */
+       case 6:
+       case 7:
+               /* bad speech frame (BFI=1, SID=0) */
+               if (!emit_twts002)
+                       return 0;
+               out[0] = FT_BFI_WITH_DATA << 4;
+               twts002_hr8_set_extra_flags(out, tf);
+               /* XC4 is TAF with this frame type */
+               if (tf->xc_bits[3])
+                       out[0] |= 0x01;
+               osmo_ubit2pbit(out + 1, tf->d_bits, 112);
+               return GSM_HR_BYTES_RTP_RFC5993;
+       default:
+       bad_frame:
+               /* received garbage, emit BFI with no data */
+               if (emit_twts002) {
+                       out[0] = FT_NO_DATA << 4;
+                       twts002_hr8_set_extra_flags(out, tf);
+                       return 1;
+               } else
+                       return 0;
+       }
+}
+
 /*! Generate the 31 bytes RTP payload for GSM-EFR from a decoded TRAU frame.
  *  \param[out] out caller-provided output buffer
  *  \param[in] out_len length of out buffer in bytes
@@ -524,6 +630,69 @@
        return 0;
 }

+static int rtp2trau_hr8(struct osmo_trau_frame *tf, const uint8_t *data, 
size_t data_len)
+{
+       /* accept both TS 101 318 and RFC 5993 payloads */
+       switch (data_len) {
+       case GSM_HR_BYTES:
+               break;
+       case GSM_HR_BYTES_RTP_RFC5993:
+               data++;
+               data_len--;
+               break;
+       case 0:
+               /* accept no-data input */
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* FIXME: implement TRAU-UL frame generation if and when
+        * someone actually needs it in a program that uses
+        * this library. */
+       if (tf->dir != OSMO_TRAU_DIR_DL)
+               return -ENOTSUP;
+
+       tf->type = OSMO_TRAU8_SPEECH;
+
+       /* C1..C5 */
+       tf->c_bits[0] = 0;
+       tf->c_bits[1] = 0;
+       tf->c_bits[2] = 0;
+       tf->c_bits[3] = 1;      /* UFE: good uplink */
+       tf->c_bits[4] = 0;      /* odd parity */
+       /* C6..C9: spare bits */
+       memset(tf->c_bits + 5, 1, 4);
+
+       /* XC1..XC6 */
+       if (osmo_hr_check_sid(data, data_len)) {
+               tf->xc_bits[0] = 0;
+               tf->xc_bits[1] = 0;
+               tf->xc_bits[2] = 0;
+               tf->xc_bits[3] = 1;
+               tf->xc_bits[4] = 0;
+               tf->xc_bits[5] = 0;     /* odd parity */
+       } else {
+               tf->xc_bits[0] = 0;
+               tf->xc_bits[1] = 0;
+               tf->xc_bits[2] = 0;
+               tf->xc_bits[3] = 0;
+               tf->xc_bits[4] = 0;
+               tf->xc_bits[5] = 1;     /* odd parity */
+       }
+
+       memset(&tf->t_bits[0], 1, 2);
+
+       if (data_len)
+               osmo_pbit2ubit(tf->d_bits, data, GSM_HR_BYTES * 8);
+       else
+               memset(tf->d_bits, 0, GSM_HR_BYTES * 8);
+       /* CRC is *not* computed by TRAU frame encoder - we have to do it */
+       osmo_crc8gen_set_bits(&gsm0860_efr_crc3, tf->d_bits, 44, tf->crc_bits);
+
+       return 0;
+}
+
 /* TS 48.060 Section 5.5.1.1.2 */
 static int rtp2trau_efr(struct osmo_trau_frame *tf, const uint8_t *data, 
size_t data_len)
 {
@@ -801,6 +970,8 @@
                return trau2rtp_efr(out, out_len, tf, check_twts001(st));
        case OSMO_TRAU16_FT_HR:
                return trau2rtp_hr16(out, out_len, tf, check_twts002(st));
+       case OSMO_TRAU8_SPEECH:
+               return trau2rtp_hr8(out, out_len, tf, check_twts002(st));
        default:
                return -EINVAL;
        }
@@ -816,6 +987,8 @@
                return rtp2trau_efr(tf, rtp, rtp_len);
        case OSMO_TRAU16_FT_HR:
                return rtp2trau_hr16(tf, rtp, rtp_len);
+       case OSMO_TRAU8_SPEECH:
+               return rtp2trau_hr8(tf, rtp, rtp_len);
        default:
                return -EINVAL;
        }

--
To view, visit https://gerrit.osmocom.org/c/libosmo-abis/+/37287?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: I8ee01b73360501ca380a8695cbc7070ceaaba1be
Gerrit-Change-Number: 37287
Gerrit-PatchSet: 1
Gerrit-Owner: falconia <fal...@freecalypso.org>
Gerrit-MessageType: newchange

Reply via email to