Review at https://gerrit.osmocom.org/160
Add functions to detect HR/FR SID frames
Add functions which check if given FR or HR frame (packed in RTP) contains SID (SIlence Descriptor) and corresponding tests.
Related: OS#22 Change-Id: I4051e3c0d4fb9ee93d7e9e0ef4abaf9f18e227ca --- M include/osmocom/codec/codec.h M src/codec/gsm610.c M src/codec/gsm620.c M tests/codec/codec_test.c M tests/codec/codec_test.ok 5 files changed, 314 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/60/160/1
diff --git a/include/osmocom/codec/codec.h b/include/osmocom/codec/codec.h index b7bcc78..23c5e20 100644 --- a/include/osmocom/codec/codec.h +++ b/include/osmocom/codec/codec.h @@ -1,6 +1,7 @@ #pragma once
#include <stdint.h> +#include <stdbool.h>
#include <osmocom/core/utils.h>
@@ -41,6 +42,8 @@ AMR_GOOD = 1 };
+bool osmo_check_sid_fr(uint8_t *rtp_payload, size_t payload_len); +bool osmo_check_sid_hr(uint8_t *rtp_payload, size_t payload_len); 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 35f6011..8699253 100644 --- a/src/codec/gsm610.c +++ b/src/codec/gsm610.c @@ -22,6 +22,9 @@ */
#include <stdint.h> +#include <stdbool.h> + +#include <osmocom/core/bitvec.h>
/* GSM FR - subjective importance bit ordering */ /* This array encodes GSM 05.03 Table 2. @@ -292,3 +295,215 @@ 11, /* LARc1:0 */ 29, /* LARc5:0 */ }; + +/*! \brief Check whether RTP frame contains FR SID code word according to + * TS 101 318 §5.1.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 + */ +bool osmo_check_sid_fr(uint8_t *rtp_payload, size_t payload_len) +{ + struct bitvec bv; + + /* signature does not match Full Rate SID */ + if ((rtp_payload[0] >> 4) != 0xD) + return false; + + bv.data = rtp_payload; + bv.data_len = payload_len; + + /* code word is all 0 at given bits, numbered from 1 */ + if (bitvec_get_bit_pos(&bv, 59) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 60) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 62) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 63) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 65) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 66) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 68) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 69) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 71) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 72) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 74) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 75) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 77) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 78) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 80) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 81) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 83) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 84) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 86) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 87) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 89) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 90) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 92) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 93) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 95) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 96) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 115) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 116) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 118) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 119) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 121) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 122) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 124) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 125) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 127) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 128) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 130) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 131) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 133) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 134) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 136) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 137) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 139) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 140) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 142) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 143) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 145) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 146) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 148) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 149) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 151) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 152) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 171) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 172) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 174) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 175) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 177) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 178) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 180) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 181) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 183) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 184) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 186) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 187) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 189) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 190) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 192) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 193) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 195) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 196) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 198) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 199) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 201) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 202) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 204) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 205) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 207) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 208) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 227) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 228) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 230) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 231) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 233) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 234) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 236) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 237) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 239) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 242) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 245) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 248) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 251) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 254) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 257) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 260) != ZERO) + return false; + if (bitvec_get_bit_pos(&bv, 263) != ZERO) + return false; + + return true; +} diff --git a/src/codec/gsm620.c b/src/codec/gsm620.c index f4ac9ad..873913d 100644 --- a/src/codec/gsm620.c +++ b/src/codec/gsm620.c @@ -22,6 +22,9 @@ */
#include <stdint.h> +#include <stdbool.h> + +#include <osmocom/core/bitvec.h>
/* GSM HR unvoiced (mode=0) frames - subjective importance bit ordering */ /* This array encode mapping between GSM 05.03 Table 3a (bits @@ -260,3 +263,62 @@ 82, /* Code 3:6 */ 81, /* Code 3:7 */ }; + +/*! \brief 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 + */ +bool osmo_check_sid_hr(uint8_t *rtp_payload, size_t payload_len) +{ + struct bitvec bv; + bv.data = rtp_payload; + bv.data_len = payload_len; + + /* code word is all 1 at given bits, numbered from 1, MODE is always 3 */ + bv.cur_bit = 33; + if (bitvec_get_uint(&bv, 1) != 0x1) + return false; + + if (bitvec_get_uint(&bv, 2) != 0x3) + return false; + + if (bitvec_get_uint(&bv, 8) != 0xFF) + return false; + + if (bitvec_get_uint(&bv, 9) != 0x1FF) + return false; + + if (bitvec_get_uint(&bv, 5) != 0x1F) + return false; + + if (bitvec_get_uint(&bv, 4) != 0xF) + return false; + + if (bitvec_get_uint(&bv, 9) != 0x1FF) + return false; + + if (bitvec_get_uint(&bv, 5) != 0x1F) + return false; + + if (bitvec_get_uint(&bv, 4) != 0xF) + return false; + + if (bitvec_get_uint(&bv, 9) != 0x1FF) + return false; + + if (bitvec_get_uint(&bv, 5) != 0x1F) + return false; + + if (bitvec_get_uint(&bv, 4) != 0xF) + return false; + + if (bitvec_get_uint(&bv, 9) != 0x1FF) + return false; + + if (bitvec_get_uint(&bv, 5) != 0x1F) + return false; + + return true; +} diff --git a/tests/codec/codec_test.c b/tests/codec/codec_test.c index 4905dd3..1b278cb 100644 --- a/tests/codec/codec_test.c +++ b/tests/codec/codec_test.c @@ -20,6 +20,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <stdbool.h>
#include <osmocom/core/utils.h> #include <osmocom/codec/codec.h> @@ -68,6 +69,26 @@ cmpr(_cmr, cmr), cmpr(_ft, ft), cmpr(_bfi, bfi), cmi, sti); }
+uint8_t fr[] = {0xd8, 0xa9, 0xb5, 0x1d, 0xda, 0xa8, 0x82, 0xcc, 0xec, 0x52, + 0x29, 0x05, 0xa8, 0xc3, 0xe3, 0x0e, 0xb0, 0x89, 0x7a, 0xee, + 0x42, 0xca, 0xc4, 0x97, 0x22, 0xe6, 0x9e, 0xa8, 0xb8, 0xec, + 0x52, 0x26, 0xbd}; +uint8_t sid_fr[] = {0xd7, 0x27, 0x93, 0xe5, 0xe3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +uint8_t hr[] = {0x06, 0x46, 0x76, 0xb1, 0x8e, 0x48, 0x9a, 0x2f, 0x5e, 0x4c, + 0x22, 0x2b, 0x62, 0x25}; +uint8_t sid_hr[] = {0x03, 0x8e, 0xb6, 0xcb, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff}; + +static void test_sid_xr(uint8_t *t, size_t len, bool hr) +{ + printf("%s SID ? %s:: %d\n", hr ? "HR" : "FR", osmo_hexdump(t, len), + hr ? osmo_check_sid_hr(t, len) : osmo_check_sid_fr(t, len)); +} + int main(int argc, char **argv) { printf("AMR RTP payload decoder test:\n"); @@ -79,6 +100,13 @@ test_amr_rt(AMR_12_2, AMR_12_2, AMR_GOOD); test_amr_rt(AMR_7_40, AMR_7_40, AMR_BAD); test_amr_rt(AMR_7_40, AMR_7_40, AMR_GOOD); + printf("FR RTP payload SID test:\n"); + test_sid_xr(sid_fr, 33, false); + test_sid_xr(fr, 33, false); + + printf("HR RTP payload SID test:\n"); + test_sid_xr(sid_hr, 14, true); + test_sid_xr(hr, 14, true);
return 0; } diff --git a/tests/codec/codec_test.ok b/tests/codec/codec_test.ok index 0f76fef..2af7cc7 100644 --- a/tests/codec/codec_test.ok +++ b/tests/codec/codec_test.ok @@ -7,3 +7,9 @@ [33/33] AMR 12,2 kbit/s (GSM-EFR), CMR: OK, FT: OK, BFI: OK, CMI: -1, STI: -1 [21/21] AMR 7,40 kbit/s (TDMA-EFR), CMR: OK, FT: OK, BFI: OK, CMI: -1, STI: -1 [21/21] AMR 7,40 kbit/s (TDMA-EFR), CMR: OK, FT: OK, BFI: OK, CMI: -1, STI: -1 +FR RTP payload SID test: +FR SID ? d7 27 93 e5 e3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 :: 1 +FR SID ? d8 a9 b5 1d da a8 82 cc ec 52 29 05 a8 c3 e3 0e b0 89 7a ee 42 ca c4 97 22 e6 9e a8 b8 ec 52 26 bd :: 0 +HR RTP payload SID test: +HR SID ? 03 8e b6 cb ff ff ff ff ff ff ff ff ff ff :: 1 +HR SID ? 06 46 76 b1 8e 48 9a 2f 5e 4c 22 2b 62 25 :: 0
Patch Set 1: Code-Review-1
(2 comments)
https://gerrit.osmocom.org/#/c/160/1/include/osmocom/codec/codec.h File include/osmocom/codec/codec.h:
Line 46: bool osmo_check_sid_hr(uint8_t *rtp_payload, size_t payload_len); the other functions are calld osmo_<codec>_<something>, while your new functions are osmo_<something>_<codec>, which is a minor inconsistency. But let's ignore that.
https://gerrit.osmocom.org/#/c/160/1/src/codec/gsm610.c File src/codec/gsm610.c:
Line 320: return false; mh, this code doesn't really look very nice, like lots of copy+paste. why not have a 'const unsigned int sid_bits[] array with the bit numbers, and a nice for-loop to iterate over sid_bits?
Hello Harald Welte, Jenkins Builder,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/160
to look at the new patch set (#2).
Add functions to detect HR/FR SID frames
Add functions which check if given FR or HR frame (packed in RTP) contains SID (SIlence Descriptor) and corresponding tests.
Related: OS#22 Change-Id: I4051e3c0d4fb9ee93d7e9e0ef4abaf9f18e227ca --- M include/osmocom/codec/codec.h M src/codec/gsm610.c M src/codec/gsm620.c M tests/codec/codec_test.c M tests/codec/codec_test.ok 5 files changed, 108 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/60/160/2
diff --git a/include/osmocom/codec/codec.h b/include/osmocom/codec/codec.h index b7bcc78..f7a8ad9 100644 --- a/include/osmocom/codec/codec.h +++ b/include/osmocom/codec/codec.h @@ -1,6 +1,7 @@ #pragma once
#include <stdint.h> +#include <stdbool.h>
#include <osmocom/core/utils.h>
@@ -41,6 +42,8 @@ AMR_GOOD = 1 };
+bool osmo_fr_check_sid(uint8_t *rtp_payload, size_t payload_len); +bool osmo_hr_check_sid(uint8_t *rtp_payload, size_t payload_len); 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 35f6011..47faea2 100644 --- a/src/codec/gsm610.c +++ b/src/codec/gsm610.c @@ -22,6 +22,10 @@ */
#include <stdint.h> +#include <stdbool.h> + +#include <osmocom/core/bitvec.h> +#include <osmocom/core/utils.h>
/* GSM FR - subjective importance bit ordering */ /* This array encodes GSM 05.03 Table 2. @@ -292,3 +296,38 @@ 11, /* LARc1:0 */ 29, /* LARc5:0 */ }; + +/*! \brief Check whether RTP frame contains FR SID code word according to + * TS 101 318 §5.1.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 + */ +bool osmo_fr_check_sid(uint8_t *rtp_payload, size_t payload_len) +{ + struct bitvec bv; + uint16_t i, z_bits[] = { 59, 60, 62, 63, 65, 66, 68, 69, 71, 72, 74, 75, + 77, 78, 80, 81, 83, 84, 86, 87, 89, 90, 92, 93, + 95, 96, 115, 116, 118, 119, 121, 122, 124, 125, + 127, 128, 130, 131, 133, 134, 136, 137, 139, + 140, 142, 143, 145, 146, 148, 149, 151, 152, + 171, 172, 174, 175, 177, 178, 180, 181, 183, + 184, 186, 187, 189, 190, 192, 193, 195, 196, + 198, 199, 201, 202, 204, 205, 207, 208, 227, + 228, 230, 231, 233, 234, 236, 237, 239, 242, + 245, 248, 251, 254, 257, 260, 263 }; + + /* signature does not match Full Rate SID */ + if ((rtp_payload[0] >> 4) != 0xD) + return false; + + bv.data = rtp_payload; + bv.data_len = payload_len; + + /* code word is all 0 at given bits, numbered from 1 */ + for (i = 0; i < ARRAY_SIZE(z_bits); i++) + if (bitvec_get_bit_pos(&bv, z_bits[i]) != ZERO) + return false; + + return true; +} diff --git a/src/codec/gsm620.c b/src/codec/gsm620.c index f4ac9ad..6f1a95b 100644 --- a/src/codec/gsm620.c +++ b/src/codec/gsm620.c @@ -22,6 +22,10 @@ */
#include <stdint.h> +#include <stdbool.h> + +#include <osmocom/core/bitvec.h> +#include <osmocom/core/utils.h>
/* GSM HR unvoiced (mode=0) frames - subjective importance bit ordering */ /* This array encode mapping between GSM 05.03 Table 3a (bits @@ -260,3 +264,31 @@ 82, /* Code 3:6 */ 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; +} + +/*! \brief 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 + */ +bool osmo_hr_check_sid(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 = rtp_payload; + bv.data_len = payload_len; + bv.cur_bit = 33; + + /* 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; + + return true; +} diff --git a/tests/codec/codec_test.c b/tests/codec/codec_test.c index 4905dd3..5b934b1 100644 --- a/tests/codec/codec_test.c +++ b/tests/codec/codec_test.c @@ -20,6 +20,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <stdbool.h>
#include <osmocom/core/utils.h> #include <osmocom/codec/codec.h> @@ -68,6 +69,26 @@ cmpr(_cmr, cmr), cmpr(_ft, ft), cmpr(_bfi, bfi), cmi, sti); }
+uint8_t fr[] = {0xd8, 0xa9, 0xb5, 0x1d, 0xda, 0xa8, 0x82, 0xcc, 0xec, 0x52, + 0x29, 0x05, 0xa8, 0xc3, 0xe3, 0x0e, 0xb0, 0x89, 0x7a, 0xee, + 0x42, 0xca, 0xc4, 0x97, 0x22, 0xe6, 0x9e, 0xa8, 0xb8, 0xec, + 0x52, 0x26, 0xbd}; +uint8_t sid_fr[] = {0xd7, 0x27, 0x93, 0xe5, 0xe3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +uint8_t hr[] = {0x06, 0x46, 0x76, 0xb1, 0x8e, 0x48, 0x9a, 0x2f, 0x5e, 0x4c, + 0x22, 0x2b, 0x62, 0x25}; +uint8_t sid_hr[] = {0x03, 0x8e, 0xb6, 0xcb, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff}; + +static void test_sid_xr(uint8_t *t, size_t len, bool hr) +{ + printf("%s SID ? %s:: %d\n", hr ? "HR" : "FR", osmo_hexdump(t, len), + hr ? osmo_hr_check_sid(t, len) : osmo_fr_check_sid(t, len)); +} + int main(int argc, char **argv) { printf("AMR RTP payload decoder test:\n"); @@ -79,6 +100,13 @@ test_amr_rt(AMR_12_2, AMR_12_2, AMR_GOOD); test_amr_rt(AMR_7_40, AMR_7_40, AMR_BAD); test_amr_rt(AMR_7_40, AMR_7_40, AMR_GOOD); + printf("FR RTP payload SID test:\n"); + test_sid_xr(sid_fr, 33, false); + test_sid_xr(fr, 33, false); + + printf("HR RTP payload SID test:\n"); + test_sid_xr(sid_hr, 14, true); + test_sid_xr(hr, 14, true);
return 0; } diff --git a/tests/codec/codec_test.ok b/tests/codec/codec_test.ok index 0f76fef..2af7cc7 100644 --- a/tests/codec/codec_test.ok +++ b/tests/codec/codec_test.ok @@ -7,3 +7,9 @@ [33/33] AMR 12,2 kbit/s (GSM-EFR), CMR: OK, FT: OK, BFI: OK, CMI: -1, STI: -1 [21/21] AMR 7,40 kbit/s (TDMA-EFR), CMR: OK, FT: OK, BFI: OK, CMI: -1, STI: -1 [21/21] AMR 7,40 kbit/s (TDMA-EFR), CMR: OK, FT: OK, BFI: OK, CMI: -1, STI: -1 +FR RTP payload SID test: +FR SID ? d7 27 93 e5 e3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 :: 1 +FR SID ? d8 a9 b5 1d da a8 82 cc ec 52 29 05 a8 c3 e3 0e b0 89 7a ee 42 ca c4 97 22 e6 9e a8 b8 ec 52 26 bd :: 0 +HR RTP payload SID test: +HR SID ? 03 8e b6 cb ff ff ff ff ff ff ff ff ff ff :: 1 +HR SID ? 06 46 76 b1 8e 48 9a 2f 5e 4c 22 2b 62 25 :: 0
Patch Set 2: Code-Review+2
Harald Welte has submitted this change and it was merged.
Change subject: Add functions to detect HR/FR SID frames ......................................................................
Add functions to detect HR/FR SID frames
Add functions which check if given FR or HR frame (packed in RTP) contains SID (SIlence Descriptor) and corresponding tests.
Related: OS#22 Change-Id: I4051e3c0d4fb9ee93d7e9e0ef4abaf9f18e227ca Reviewed-on: https://gerrit.osmocom.org/160 Tested-by: Jenkins Builder Reviewed-by: Harald Welte laforge@gnumonks.org --- M include/osmocom/codec/codec.h M src/codec/gsm610.c M src/codec/gsm620.c M tests/codec/codec_test.c M tests/codec/codec_test.ok 5 files changed, 108 insertions(+), 0 deletions(-)
Approvals: Harald Welte: Looks good to me, approved Jenkins Builder: Verified
diff --git a/include/osmocom/codec/codec.h b/include/osmocom/codec/codec.h index b7bcc78..f7a8ad9 100644 --- a/include/osmocom/codec/codec.h +++ b/include/osmocom/codec/codec.h @@ -1,6 +1,7 @@ #pragma once
#include <stdint.h> +#include <stdbool.h>
#include <osmocom/core/utils.h>
@@ -41,6 +42,8 @@ AMR_GOOD = 1 };
+bool osmo_fr_check_sid(uint8_t *rtp_payload, size_t payload_len); +bool osmo_hr_check_sid(uint8_t *rtp_payload, size_t payload_len); 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 35f6011..47faea2 100644 --- a/src/codec/gsm610.c +++ b/src/codec/gsm610.c @@ -22,6 +22,10 @@ */
#include <stdint.h> +#include <stdbool.h> + +#include <osmocom/core/bitvec.h> +#include <osmocom/core/utils.h>
/* GSM FR - subjective importance bit ordering */ /* This array encodes GSM 05.03 Table 2. @@ -292,3 +296,38 @@ 11, /* LARc1:0 */ 29, /* LARc5:0 */ }; + +/*! \brief Check whether RTP frame contains FR SID code word according to + * TS 101 318 §5.1.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 + */ +bool osmo_fr_check_sid(uint8_t *rtp_payload, size_t payload_len) +{ + struct bitvec bv; + uint16_t i, z_bits[] = { 59, 60, 62, 63, 65, 66, 68, 69, 71, 72, 74, 75, + 77, 78, 80, 81, 83, 84, 86, 87, 89, 90, 92, 93, + 95, 96, 115, 116, 118, 119, 121, 122, 124, 125, + 127, 128, 130, 131, 133, 134, 136, 137, 139, + 140, 142, 143, 145, 146, 148, 149, 151, 152, + 171, 172, 174, 175, 177, 178, 180, 181, 183, + 184, 186, 187, 189, 190, 192, 193, 195, 196, + 198, 199, 201, 202, 204, 205, 207, 208, 227, + 228, 230, 231, 233, 234, 236, 237, 239, 242, + 245, 248, 251, 254, 257, 260, 263 }; + + /* signature does not match Full Rate SID */ + if ((rtp_payload[0] >> 4) != 0xD) + return false; + + bv.data = rtp_payload; + bv.data_len = payload_len; + + /* code word is all 0 at given bits, numbered from 1 */ + for (i = 0; i < ARRAY_SIZE(z_bits); i++) + if (bitvec_get_bit_pos(&bv, z_bits[i]) != ZERO) + return false; + + return true; +} diff --git a/src/codec/gsm620.c b/src/codec/gsm620.c index f4ac9ad..6f1a95b 100644 --- a/src/codec/gsm620.c +++ b/src/codec/gsm620.c @@ -22,6 +22,10 @@ */
#include <stdint.h> +#include <stdbool.h> + +#include <osmocom/core/bitvec.h> +#include <osmocom/core/utils.h>
/* GSM HR unvoiced (mode=0) frames - subjective importance bit ordering */ /* This array encode mapping between GSM 05.03 Table 3a (bits @@ -260,3 +264,31 @@ 82, /* Code 3:6 */ 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; +} + +/*! \brief 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 + */ +bool osmo_hr_check_sid(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 = rtp_payload; + bv.data_len = payload_len; + bv.cur_bit = 33; + + /* 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; + + return true; +} diff --git a/tests/codec/codec_test.c b/tests/codec/codec_test.c index 4905dd3..5b934b1 100644 --- a/tests/codec/codec_test.c +++ b/tests/codec/codec_test.c @@ -20,6 +20,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <stdbool.h>
#include <osmocom/core/utils.h> #include <osmocom/codec/codec.h> @@ -68,6 +69,26 @@ cmpr(_cmr, cmr), cmpr(_ft, ft), cmpr(_bfi, bfi), cmi, sti); }
+uint8_t fr[] = {0xd8, 0xa9, 0xb5, 0x1d, 0xda, 0xa8, 0x82, 0xcc, 0xec, 0x52, + 0x29, 0x05, 0xa8, 0xc3, 0xe3, 0x0e, 0xb0, 0x89, 0x7a, 0xee, + 0x42, 0xca, 0xc4, 0x97, 0x22, 0xe6, 0x9e, 0xa8, 0xb8, 0xec, + 0x52, 0x26, 0xbd}; +uint8_t sid_fr[] = {0xd7, 0x27, 0x93, 0xe5, 0xe3, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +uint8_t hr[] = {0x06, 0x46, 0x76, 0xb1, 0x8e, 0x48, 0x9a, 0x2f, 0x5e, 0x4c, + 0x22, 0x2b, 0x62, 0x25}; +uint8_t sid_hr[] = {0x03, 0x8e, 0xb6, 0xcb, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff}; + +static void test_sid_xr(uint8_t *t, size_t len, bool hr) +{ + printf("%s SID ? %s:: %d\n", hr ? "HR" : "FR", osmo_hexdump(t, len), + hr ? osmo_hr_check_sid(t, len) : osmo_fr_check_sid(t, len)); +} + int main(int argc, char **argv) { printf("AMR RTP payload decoder test:\n"); @@ -79,6 +100,13 @@ test_amr_rt(AMR_12_2, AMR_12_2, AMR_GOOD); test_amr_rt(AMR_7_40, AMR_7_40, AMR_BAD); test_amr_rt(AMR_7_40, AMR_7_40, AMR_GOOD); + printf("FR RTP payload SID test:\n"); + test_sid_xr(sid_fr, 33, false); + test_sid_xr(fr, 33, false); + + printf("HR RTP payload SID test:\n"); + test_sid_xr(sid_hr, 14, true); + test_sid_xr(hr, 14, true);
return 0; } diff --git a/tests/codec/codec_test.ok b/tests/codec/codec_test.ok index 0f76fef..2af7cc7 100644 --- a/tests/codec/codec_test.ok +++ b/tests/codec/codec_test.ok @@ -7,3 +7,9 @@ [33/33] AMR 12,2 kbit/s (GSM-EFR), CMR: OK, FT: OK, BFI: OK, CMI: -1, STI: -1 [21/21] AMR 7,40 kbit/s (TDMA-EFR), CMR: OK, FT: OK, BFI: OK, CMI: -1, STI: -1 [21/21] AMR 7,40 kbit/s (TDMA-EFR), CMR: OK, FT: OK, BFI: OK, CMI: -1, STI: -1 +FR RTP payload SID test: +FR SID ? d7 27 93 e5 e3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 :: 1 +FR SID ? d8 a9 b5 1d da a8 82 cc ec 52 29 05 a8 c3 e3 0e b0 89 7a ee 42 ca c4 97 22 e6 9e a8 b8 ec 52 26 bd :: 0 +HR RTP payload SID test: +HR SID ? 03 8e b6 cb ff ff ff ff ff ff ff ff ff ff :: 1 +HR SID ? 06 46 76 b1 8e 48 9a 2f 5e 4c 22 2b 62 25 :: 0