aboutsummaryrefslogtreecommitdiffstats
path: root/src/egprs_rlc_compression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/egprs_rlc_compression.cpp')
-rw-r--r--src/egprs_rlc_compression.cpp286
1 files changed, 286 insertions, 0 deletions
diff --git a/src/egprs_rlc_compression.cpp b/src/egprs_rlc_compression.cpp
index c1baaa9..cb4c652 100644
--- a/src/egprs_rlc_compression.cpp
+++ b/src/egprs_rlc_compression.cpp
@@ -72,6 +72,161 @@ void egprs_compress::build_codewords(egprs_compress_node *root, const char *cdwd
}
}
+/*
+ * Terminating codes for uninterrupted sequences of 0 and 1 up to 64 bit length
+ * according to TS 44.060 9.1.10
+ */
+static const unsigned t4_term[2][64] = {
+ {
+ 0b0000110111,
+ 0b10,
+ 0b11,
+ 0b010,
+ 0b011,
+ 0b0011,
+ 0b0010,
+ 0b00011,
+ 0b000101,
+ 0b000100,
+ 0b0000100,
+ 0b0000101,
+ 0b0000111,
+ 0b00000100,
+ 0b00000111,
+ 0b000011000,
+ 0b0000010111,
+ 0b0000011000,
+ 0b0000001000,
+ 0b00001100111,
+ 0b00001101000,
+ 0b00001101100,
+ 0b000000101100,
+ 0b000001011010,
+ 0b000001100110,
+ 0b000001100111
+ },
+ {
+ 0b00110101,
+ 0b000111,
+ 0b0111,
+ 0b1000,
+ 0b1011,
+ 0b1100,
+ 0b1110,
+ 0b1111,
+ 0b10011,
+ 0b10100,
+ 0b00111,
+ 0b01000,
+ 0b001000,
+ 0b000011,
+ 0b110100,
+ 0b110101,
+ 0b101010,
+ 0b101011,
+ 0b0100111,
+ 0b0001100,
+ 0b0001000,
+ 0b0010111,
+ 0b0000011,
+ 0b0000100,
+ 0b0101000,
+ 0b0101011,
+ 0b0010011,
+ 0b0100100,
+ 0b0011000,
+ 0b00000010,
+ 0b00000011,
+ 0b00011010,
+ 0b00011011,
+ 0b00010010,
+ 0b00010011,
+ 0b00010100,
+ 0b00010101,
+ 0b00010110,
+ 0b00010111,
+ 0b00101000,
+ 0b00101001,
+ 0b00101010,
+ 0b00101011,
+ 0b00101100,
+ 0b00101101,
+ 0b00000100,
+ 0b00000101,
+ 0b00001010,
+ 0b00001011,
+ 0b01010010,
+ 0b01010011,
+ 0b01010100,
+ 0b01010101,
+ 0b00100100,
+ 0b00100101,
+ 0b01011000,
+ 0b01011001,
+ 0b01011010,
+ 0b01011011,
+ 0b01001010,
+ 0b01001011,
+ 0b00110010,
+ 0b00110011,
+ 0b00110100
+ }
+};
+static const unsigned t4_term_length[2][64] = {
+ {10, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 7, 8, 8, 9, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12},
+ {8, 6, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}
+};
+
+static const unsigned t4_min_term_length[] = {2, 4};
+static const unsigned t4_min_make_up_length[] = {10, 5};
+
+static const unsigned t4_max_term_length[] = {12, 8};
+static const unsigned t4_max_make_up_length[] = {13, 9};
+
+static const unsigned t4_make_up_length[2][15] = {
+ {10, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13},
+ {5, 5, 6, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9}
+};
+
+static const unsigned t4_make_up_ind[15] = {64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960};
+
+static const unsigned t4_make_up[2][15] = {
+ {
+ 0b0000001111,
+ 0b000011001000,
+ 0b000011001001,
+ 0b000001011011,
+ 0b000000110011,
+ 0b000000110100,
+ 0b000000110101,
+ 0b0000001101100,
+ 0b0000001101101,
+ 0b0000001001010,
+ 0b0000001001011,
+ 0b0000001001100,
+ 0b0000001001101,
+ 0b0000001110010,
+ 0b0000001110011
+ },
+ {
+ 0b11011,
+ 0b10010,
+ 0b010111,
+ 0b0110111,
+ 0b00110110,
+ 0b00110111,
+ 0b01100100,
+ 0b01100101,
+ 0b01101000,
+ 0b01100111,
+ 0b011001100,
+ 0b011001101,
+ 0b011010010,
+ 0b011010011,
+ 0b011010100
+ }
+};
+
/* The code words for one run length and zero
* run length are described in table 9.1.10.1
* of 3gpp 44.060
@@ -342,3 +497,134 @@ void egprs_compress::decode_tree_init()
build_codewords(ones_list, one_run_len_code_list);
build_codewords(zeros_list, zero_run_len_code_list);
}
+void compress_bitmap(
+ uint16_t *run_len_cnt, /* cnt: run length count */
+ uint16_t *codewrd_bitmap, /* code word */
+ int16_t *codewrd_len, /* number of bits in the code word */
+ bitvec *crbb_vec, /* bitmap buffer to put code word in */
+ uint8_t clr_code)
+{
+ int i = 0;
+ unsigned writeIndex = crbb_vec->cur_bit;
+
+ *codewrd_bitmap = 0;
+ *codewrd_len = 0;
+ if ((*run_len_cnt) >= 64) {
+ for (i = 0; i < 15; i++) {
+ if (t4_make_up_ind[i] == *run_len_cnt) {
+ *codewrd_bitmap = t4_make_up[clr_code][i];
+ *codewrd_len = t4_make_up_length[clr_code][i];
+ }
+ }
+ } else {
+ *codewrd_bitmap = t4_term[clr_code][*run_len_cnt];
+ *codewrd_len = t4_term_length[clr_code][*run_len_cnt];
+ }
+ bitvec_write_field(crbb_vec, writeIndex, (*codewrd_bitmap), (*codewrd_len));
+}
+
+int osmo_t4_compress(struct bitvec *bv)
+{
+ uint8_t crbb_len = 0;
+ uint8_t uclen_crbb = 0;
+ uint8_t crbb_bitmap[127] = {'\0'};
+ uint8_t color_code = (bv->data[0] & 0x80)>>7;
+ struct bitvec crbb_vec;
+
+ crbb_vec.data = crbb_bitmap;
+ crbb_vec.cur_bit = 0;
+ crbb_vec.data_len = 127;
+ bv->data_len = bv->cur_bit;
+ bv->cur_bit = 0;
+ if (compress_rbb(bv, &crbb_vec, &uclen_crbb, 23*8)) {
+ memcpy(bv->data, crbb_bitmap, (crbb_len+7)/8);
+ bv->cur_bit = crbb_len;
+ bv->data_len = (crbb_len+7)/8;
+ return color_code;
+ }
+ else
+ printf("Encode faled\n");
+ return -1;
+}
+
+/*! \brief compression algorithm using T4 encoding
+ * the compressed bitmap's are copied in crbb_bitmap
+ * \param[in] rbb_vec bit vector to be encoded
+ * \return 1 if compression is success or 0 for failure
+ */
+int compress_rbb(
+ struct bitvec *urbb_vec,
+ struct bitvec *crbb_vec,
+ uint8_t *uclen_crbb, /* Uncompressed bitmap len in CRBB */
+ uint8_t max_bits) /* max remaining bits */
+{
+ bool run_len_bit;
+ int buflen = urbb_vec->cur_bit;
+ int total_bits = urbb_vec->cur_bit;
+ uint16_t rlen;
+ uint16_t temprl = 0;
+ uint16_t cbmap = 0; /* Compressed code word */
+ int16_t nbits; /* Length of code word */
+ uint16_t uclen = 0;
+ int16_t clen = 0;
+ uint8_t clr_code = 0;
+
+ urbb_vec->cur_bit = 0;
+ run_len_bit = (urbb_vec->data[0] & 0x80)>>7;
+ while (buflen > 0) {
+ temprl = 0;
+ /* Find Run length */
+ if (run_len_bit == 1)
+ rlen = bitvec_rl_curbit(urbb_vec, true, total_bits);
+ else
+ rlen = bitvec_rl_curbit(urbb_vec, false, total_bits);
+ buflen = buflen - rlen;
+ /* if rlen> 64 need 2 code words */
+ /*Compress the bits */
+ if (run_len_bit == 0) {
+ clr_code = 0;
+ if (rlen >= 64) {
+ temprl = (rlen/64)*64;
+ compress_bitmap(&temprl, &cbmap, &nbits,
+ crbb_vec, clr_code);
+ clen = clen + nbits;
+ }
+ temprl = MOD64(rlen);
+ compress_bitmap(&temprl, &cbmap, &nbits,
+ crbb_vec, clr_code);
+ /* next time the run length will be Ones */
+ run_len_bit = 1;
+ } else {
+ clr_code = 1;
+ if (rlen >= 64) {
+ temprl = (rlen/64)*64;
+ compress_bitmap(&temprl, &cbmap, &nbits,
+ crbb_vec, clr_code);
+ clen = clen + nbits;
+ }
+ temprl = MOD64(rlen);
+ compress_bitmap(&temprl, &cbmap, &nbits,
+ crbb_vec, clr_code);
+
+ /* next time the run length will be Zeros */
+ run_len_bit = 0;
+ }
+ uclen = uclen + (rlen);
+ clen = clen + nbits;
+ /*compressed bitmap exceeds the buffer space */
+ if (clen > max_bits) {
+ uclen = uclen - rlen;
+ clen = clen - nbits;
+ break;
+ }
+ }
+ crbb_vec->cur_bit = clen;
+ *uclen_crbb = uclen;
+ if (clen >= uclen)
+ /* No Gain is observed, So no need to compress */
+ return 0;
+ else
+ /* Add compressed bitmap to final buffer */
+ return 1;
+}
+