falconia has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmocore/+/33059 )
Change subject: codec: new functions osmo_{fr,efr}_sid_reset() ......................................................................
codec: new functions osmo_{fr,efr}_sid_reset()
In Iec5c1f2619a82499f61cb3e5a7cd03ff0f020ad8 we added osmo_{fr,efr}_sid_preen() functions that apply SID classification of GSM 06.31/06.81 section 6.1.1 (osmo_{fr,efr}_sid_classify()), reject invalid SID, and "rejuvenate" deemed-valid SID frames by resetting their SID code word, correcting the one bit error that may be present in a deemed-valid SID frame. However, the last operation (rejuvenation of a SID frame by resetting its SID field) should also be made available as its own function, as it may be more efficient in some applications: for example, an application may need to call osmo_{fr,efr}_sid_classify(), apply the rejuvenation to valid SID, but also use the classification result to drive other logic. Factor out these functions.
Change-Id: I1d6dd867a358bdda8850cd8c959d0f361c0a5b6d --- M include/osmocom/codec/codec.h M src/codec/gsm610.c M src/codec/gsm660.c 3 files changed, 94 insertions(+), 32 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/59/33059/1
diff --git a/include/osmocom/codec/codec.h b/include/osmocom/codec/codec.h index 731f169..4dbe129 100644 --- a/include/osmocom/codec/codec.h +++ b/include/osmocom/codec/codec.h @@ -130,6 +130,9 @@ bool osmo_fr_sid_preen(uint8_t *rtp_payload); bool osmo_efr_sid_preen(uint8_t *rtp_payload);
+void osmo_fr_sid_reset(uint8_t *rtp_payload); +void osmo_efr_sid_reset(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); int osmo_amr_rtp_dec(const uint8_t *payload, int payload_len, uint8_t *cmr, diff --git a/src/codec/gsm610.c b/src/codec/gsm610.c index 19c7aa4..5cc4f14 100644 --- a/src/codec/gsm610.c +++ b/src/codec/gsm610.c @@ -404,6 +404,35 @@ return OSMO_GSM631_SID_CLASS_VALID; }
+/*! Reset the SID field and the unused bits of a potentially corrupted, + * but still valid GSM-FR SID frame in RTP encoding to their pristine state. + * \param[in] rtp_payload Buffer with RTP payload - must be writable! + * + * Per GSM 06.12 section 5.2, a freshly minted SID frame carries 60 bits + * of comfort noise parameters (LARc and 4 times Xmaxc), while the remaining + * 200 bits are all zeros; the latter 200 all-0 bits further break down into + * 95 bits of SID field (checked by receivers to detect SID) and 105 unused + * bits which receivers are told to ignore. Network elements that receive + * SID frames from call leg A uplink and need to retransmit them on leg B + * downlink should "rejuvenate" received SID frames prior to retransmission; + * this function does the job. + */ +void osmo_fr_sid_reset(uint8_t *rtp_payload) +{ + uint8_t *p, sub; + + p = rtp_payload + 5; /* skip magic+LARc */ + for (sub = 0; sub < 4; sub++) { + *p++ = 0; + *p++ &= 0x1F; /* upper 5 bits of Xmaxc field */ + *p++ &= 0x80; /* and the lsb spilling into the next byte */ + *p++ = 0; + *p++ = 0; + *p++ = 0; + *p++ = 0; + } +} + /*! 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. @@ -413,7 +442,6 @@ 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) { @@ -422,20 +450,8 @@ 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; - } + /* "Rejuvenate" this SID frame, correcting any errors */ + osmo_fr_sid_reset(rtp_payload); return true; default: /* There are only 3 possible SID classifications per GSM 06.31 diff --git a/src/codec/gsm660.c b/src/codec/gsm660.c index 9b5c55a..b15bdf3 100644 --- a/src/codec/gsm660.c +++ b/src/codec/gsm660.c @@ -352,6 +352,42 @@ return OSMO_GSM631_SID_CLASS_VALID; }
+/*! Reset the SID field of a potentially corrupted, but still valid GSM-EFR + * SID frame in RTP encoding to its pristine state (full SID code word). + * \param[in] rtp_payload Buffer with RTP payload - must be writable! + * + * Per GSM 06.62 section 5.3, a freshly minted SID frame consists of 58 bits + * of comfort noise parameters (LSF and 4 times fixed codebook gain), 95 bits + * of SID code word (all 1s) and 91 unused bits (all 0s). Network elements + * that receive SID frames from call leg A uplink and need to retransmit them + * on leg B downlink should "rejuvenate" received SID frames prior to + * retransmission by resetting the SID field to its pristine state of all 1s; + * this function does the job. + * + * Potential TODO: it would be nice to also zero out the remaining 91 bits + * which the spec leaves as reserved, clearing out leg A radio bit errors - + * but do we really need to? + */ +void osmo_efr_sid_reset(uint8_t *rtp_payload) +{ + /* 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; +} + /*! 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. @@ -369,23 +405,8 @@ 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; + /* "Rejuvenate" this SID frame, correcting any errors */ + osmo_efr_sid_reset(rtp_payload); return true; default: /* There are only 3 possible SID classifications per GSM 06.81