falconia submitted this change.
codec: make osmo_hr_check_sid() more efficient
The operation of checking an HRv1 codec frame for the possibility
of a perfect, error-free SID entails checking the last 79 bits
out of 112, to see if they are all 1s. This operation can be done
much more efficiently without using bitvec.
This change also affects the logic of what osmo_hr_check_sid() does
when the payload length argument is 0, or otherwise less than the
expected 14. The old code had a surely-unintended effect of
returning true on a 0-length payload; the new version returns false
(the input is not a perfect SID frame) if the payload length is 0
or otherwise shorter than GSM_HR_BYTES.
Change-Id: Ib14204102c03c14d6c5aab42b0ffbef2c3dda3fd
---
M src/codec/gsm620.c
1 file changed, 42 insertions(+), 12 deletions(-)
diff --git a/src/codec/gsm620.c b/src/codec/gsm620.c
index ef1d3b9..49ee724 100644
--- a/src/codec/gsm620.c
+++ b/src/codec/gsm620.c
@@ -23,8 +23,6 @@
#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 */
@@ -270,21 +268,32 @@
* \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)
{
- struct bitvec bv = {
- .data = (uint8_t *)rtp_payload,
- .data_len = payload_len,
- };
+ static const uint8_t all_ff_bytes[9] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF};
- /* 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. */
- for (bv.cur_bit = 33; bv.cur_bit < bv.data_len * 8; bv.cur_bit++)
- if (bitvec_get_bit_pos(&bv, bv.cur_bit) != ONE)
- 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
To view, visit change 37227. To unsubscribe, or for help writing mail filters, visit settings.