diff options
Diffstat (limited to 'src/codec/gsm620.c')
-rw-r--r-- | src/codec/gsm620.c | 72 |
1 files changed, 50 insertions, 22 deletions
diff --git a/src/codec/gsm620.c b/src/codec/gsm620.c index 282781fd..49ee7243 100644 --- a/src/codec/gsm620.c +++ b/src/codec/gsm620.c @@ -17,17 +17,12 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * */ #include <stdint.h> #include <stdbool.h> +#include <string.h> -#include <osmocom/core/bitvec.h> -#include <osmocom/core/utils.h> #include <osmocom/codec/codec.h> /* GSM HR unvoiced (mode=0) frames - subjective importance bit ordering */ @@ -268,30 +263,63 @@ const uint16_t gsm620_voiced_bitorder[112] = { 81, /* Code 3:7 */ }; -static inline uint16_t mask(const uint8_t msb) -{ - const uint16_t m = (uint16_t)1 << (msb - 1); - return (m - 1) ^ m; -} - /*! Check whether RTP frame contains HR SID code word according to * TS 101 318 ยง5.2.2 * \param[in] rtp_payload Buffer with RTP payload * \param[in] payload_len Length of payload * \returns true if code word is found, false otherwise + * + * Note that this function checks only for a perfect, error-free SID. + * Unlike GSM 06.31 for FR or GSM 06.81 for EFR, GSM 06.41 spec for HR + * does not prescribe exact bit counting rules, hence detection of + * partially corrupted SID frames in downstream network elements + * without out-of-band indication is not possible. */ bool osmo_hr_check_sid(const uint8_t *rtp_payload, size_t payload_len) { - uint8_t i, bits[] = { 1, 2, 8, 9, 5, 4, 9, 5, 4, 9, 5, 4, 9, 5 }; - struct bitvec bv; - bv.data = (uint8_t *) rtp_payload; - bv.data_len = payload_len; - bv.cur_bit = 33; + static const uint8_t all_ff_bytes[9] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF}; - /* code word is all 1 at given bits, numbered from 1, MODE is always 3 */ - for (i = 0; i < ARRAY_SIZE(bits); i++) - if (bitvec_get_uint(&bv, bits[i]) != mask(bits[i])) - return false; + if (payload_len < GSM_HR_BYTES) + return false; - return true; + /* A SID frame is identified by a SID codeword consisting of 79 bits + * which are all 1, so we basically check if all bits in range + * r34..r112 (inclusive) are 1. However, given the position of + * these bits in the frame, the most efficient way to perform + * this check does not use any bit-level operations. */ + if ((rtp_payload[4] & 0x7F) != 0x7F) + return false; + if (memcmp(rtp_payload + 5, all_ff_bytes, 9) == 0) + return true; + else + return false; +} + +/*! Reset the SID field of a potentially corrupted, but still valid GSM-HR + * SID frame in TS 101 318 format to its pristine state (full SID codeword). + * \param[in] rtp_payload Buffer with RTP payload - must be writable! + * + * Per GSM 06.22 section 5.3, a freshly minted SID frame consists of 33 bits + * of comfort noise parameters and 79 bits of SID codeword (all 1s). 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. + * + * Important note: because of HR-specific quirks (lack of exact bit counting + * rules in GSM 06.41 spec compared to 06.31 & 06.81, plus the fact that such + * bit counting can only be done efficiently in the GSM 05.03 channel decoder + * prior to bit reordering based on voiced or unvoiced mode), a generic + * (usable from any network element) SID classification function similar to + * osmo_{fr,efr}_sid_classify() unfortunately cannot exist for HR. Therefore, + * the triggering condition for invoking this SID rejuvenation/reset function + * can only be an out-of-band SID indication, as in GSM 08.61 TRAU frames + * or RFC 5993 ToC octet. + */ +void osmo_hr_sid_reset(uint8_t *rtp_payload) +{ + /* set all 79 SID codeword bits to 1 */ + rtp_payload[4] |= 0x7F; + memset(rtp_payload + 5, 0xFF, 9); } |