libosmocore[master]: Add functions to detect HR/FR SID frames
diff mbox

Message ID gerrit.1464699350739.I4051e3c0d4fb9ee93d7e9e0ef4abaf9f18e227ca@gerrit.osmocom.org
State New
Headers show

Commit Message

gerrit-no-reply@lists.osmocom.org May 31, 2016, 12:55 p.m. UTC
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

Comments

gerrit-no-reply@lists.osmocom.org June 1, 2016, 6:34 a.m. UTC | #1
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?
gerrit-no-reply@lists.osmocom.org June 1, 2016, 10:44 a.m. UTC | #2
Patch Set 2: Code-Review+2

Patch
diff mbox

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