falconia has submitted this change. ( https://gerrit.osmocom.org/c/libosmocore/+/32184 )
Change subject: codec: add SID preening functions for FR & EFR ......................................................................
codec: add SID preening functions for FR & EFR
Those network elements which receive a stream of codec frames that may come from the uplink of GSM call A and which are responsible for preparing the frame stream for the downlink of GSM call B (OsmoMGW feeding TRAU-DL, or OsmoBTS receiving RTP and feeding DL to its PHY) must be prepared for the possibility that their incoming frame stream may contain corrupted SID frames, presumably from bit errors on radio link A. Per the rules of section 6.1.1 of GSM 06.31 for FR and GSM 06.81 for EFR, SID frames with just one errored bit are still to be accepted as valid, whereas frames with more corrupted bits which are still recognizable as SID are classified as invalid SID.
In the case of a TrFO call, the entity switching from leg A UL to leg B DL is responsible for *not* transmitting invalid SID frames on the destination leg (they should be treated like BFIs), and any deemed-valid SID frames that are forwarded should be preened, correcting that one bit error they may exhibit. The functions added here provide that functionality.
Change-Id: Iec5c1f2619a82499f61cb3e5a7cd03ff0f020ad8 --- M include/osmocom/codec/codec.h M src/codec/gsm610.c M src/codec/gsm660.c 3 files changed, 114 insertions(+), 0 deletions(-)
Approvals: Jenkins Builder: Verified pespin: Looks good to me, but someone else must approve laforge: Looks good to me, approved
diff --git a/include/osmocom/codec/codec.h b/include/osmocom/codec/codec.h index 2bdae60..364385b 100644 --- a/include/osmocom/codec/codec.h +++ b/include/osmocom/codec/codec.h @@ -94,6 +94,8 @@
enum osmo_gsm631_sid_class osmo_fr_sid_classify(const uint8_t *rtp_payload); enum osmo_gsm631_sid_class osmo_efr_sid_classify(const uint8_t *rtp_payload); +bool osmo_fr_sid_preen(uint8_t *rtp_payload); +bool osmo_efr_sid_preen(uint8_t *rtp_payload);
int osmo_amr_rtp_enc(uint8_t *payload, uint8_t cmr, enum osmo_amr_type ft, enum osmo_amr_quality bfi); diff --git a/src/codec/gsm610.c b/src/codec/gsm610.c index d29d9cb..4731e9e 100644 --- a/src/codec/gsm610.c +++ b/src/codec/gsm610.c @@ -389,3 +389,44 @@ else return OSMO_GSM631_SID_CLASS_VALID; } + +/*! Preen potentially-SID FR codec frame in RTP format, ensuring that it is + * either a speech frame or a valid SID, and if the latter, making it a + * perfect, error-free SID frame. + * \param[in] rtp_payload Buffer with RTP payload - must be writable! + * \returns true if the frame is good, false otherwise + */ +bool osmo_fr_sid_preen(uint8_t *rtp_payload) +{ + enum osmo_gsm631_sid_class sidc; + uint8_t *p, sub; + + sidc = osmo_fr_sid_classify(rtp_payload); + switch (sidc) { + case OSMO_GSM631_SID_CLASS_SPEECH: + return true; + case OSMO_GSM631_SID_CLASS_INVALID: + return false; + case OSMO_GSM631_SID_CLASS_VALID: + /* "Rejuvenate" this SID frame, correcting any errors: + * zero out all bits that aren't LARc or Xmaxc, thereby + * clearing all SID code word bits and all unused/reserved + * bits. */ + p = rtp_payload + 5; /* skip magic+LARc */ + for (sub = 0; sub < 4; sub++) { + *p++ = 0; + *p++ &= 0x1F; + *p++ &= 0x80; + *p++ = 0; + *p++ = 0; + *p++ = 0; + *p++ = 0; + } + return true; + default: + /* There are only 3 possible SID classifications per GSM 06.31 + * section 6.1.1, thus any other return value is a grave error + * in the code. */ + OSMO_ASSERT(0); + } +} diff --git a/src/codec/gsm660.c b/src/codec/gsm660.c index c6e694c..9b5c55a 100644 --- a/src/codec/gsm660.c +++ b/src/codec/gsm660.c @@ -351,3 +351,46 @@ else return OSMO_GSM631_SID_CLASS_VALID; } + +/*! Preen potentially-SID EFR codec frame in RTP format, ensuring that it is + * either a speech frame or a valid SID, and if the latter, making it a + * perfect, error-free SID frame. + * \param[in] rtp_payload Buffer with RTP payload - must be writable! + * \returns true if the frame is good, false otherwise + */ +bool osmo_efr_sid_preen(uint8_t *rtp_payload) +{ + enum osmo_gsm631_sid_class sidc; + + sidc = osmo_efr_sid_classify(rtp_payload); + switch (sidc) { + case OSMO_GSM631_SID_CLASS_SPEECH: + return true; + case OSMO_GSM631_SID_CLASS_INVALID: + return false; + case OSMO_GSM631_SID_CLASS_VALID: + /* "Rejuvenate" this SID frame, correcting any errors: + * set all 95 SID code word bits to 1. */ + rtp_payload[6] |= 0x6F; + rtp_payload[7] = 0xFF; + rtp_payload[8] = 0xFF; + rtp_payload[9] |= 0x80; + rtp_payload[12] |= 0x3B; + rtp_payload[13] = 0xFF; + rtp_payload[14] = 0xFF; + rtp_payload[15] |= 0xE0; + rtp_payload[19] = 0xFF; + rtp_payload[20] = 0xFF; + rtp_payload[21] = 0xFF; + rtp_payload[25] = 0xFF; + rtp_payload[26] |= 0xFC; + rtp_payload[27] = 0xFF; + rtp_payload[28] |= 0xC0; + return true; + default: + /* There are only 3 possible SID classifications per GSM 06.81 + * section 6.1.1, thus any other return value is a grave error + * in the code. */ + OSMO_ASSERT(0); + } +}