mirror of https://gerrit.osmocom.org/libosmocore
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
This commit is contained in:
parent
945f6cec0f
commit
2974a23c75
|
@ -130,6 +130,9 @@ static inline bool osmo_efr_is_any_sid(const uint8_t *rtp_payload)
|
|||
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,
|
||||
|
|
|
@ -404,6 +404,35 @@ enum osmo_gsm631_sid_class osmo_fr_sid_classify(const uint8_t *rtp_payload)
|
|||
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 @@ enum osmo_gsm631_sid_class osmo_fr_sid_classify(const uint8_t *rtp_payload)
|
|||
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 @@ bool osmo_fr_sid_preen(uint8_t *rtp_payload)
|
|||
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
|
||||
|
|
|
@ -352,6 +352,42 @@ enum osmo_gsm631_sid_class osmo_efr_sid_classify(const uint8_t *rtp_payload)
|
|||
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 @@ bool osmo_efr_sid_preen(uint8_t *rtp_payload)
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue