diff --git a/lib/include/chiaki/fec.h b/lib/include/chiaki/fec.h index 105d3e7..658c7c0 100644 --- a/lib/include/chiaki/fec.h +++ b/lib/include/chiaki/fec.h @@ -31,7 +31,7 @@ extern "C" { #define CHIAKI_FEC_WORDSIZE 8 -CHIAKI_EXPORT ChiakiErrorCode chiaki_fec_decode(uint8_t *frame_buf, size_t unit_size, unsigned int k, unsigned int m, const unsigned int *erasures, size_t erasures_count); +CHIAKI_EXPORT ChiakiErrorCode chiaki_fec_decode(uint8_t *frame_buf, size_t unit_size, size_t stride, unsigned int k, unsigned int m, const unsigned int *erasures, size_t erasures_count); #ifdef __cplusplus } diff --git a/lib/include/chiaki/frameprocessor.h b/lib/include/chiaki/frameprocessor.h index aae7172..f296e02 100644 --- a/lib/include/chiaki/frameprocessor.h +++ b/lib/include/chiaki/frameprocessor.h @@ -37,6 +37,7 @@ typedef struct chiaki_frame_processor_t uint8_t *frame_buf; size_t frame_buf_size; size_t buf_size_per_unit; + size_t buf_stride_per_unit; unsigned int units_source_expected; unsigned int units_fec_expected; unsigned int units_source_received; diff --git a/lib/src/fec.c b/lib/src/fec.c index ea72c76..c797e68 100644 --- a/lib/src/fec.c +++ b/lib/src/fec.c @@ -28,8 +28,10 @@ int *create_matrix(unsigned int k, unsigned int m) return cauchy_original_coding_matrix(k, m, CHIAKI_FEC_WORDSIZE); } -CHIAKI_EXPORT ChiakiErrorCode chiaki_fec_decode(uint8_t *frame_buf, size_t unit_size, unsigned int k, unsigned int m, const unsigned int *erasures, size_t erasures_count) +CHIAKI_EXPORT ChiakiErrorCode chiaki_fec_decode(uint8_t *frame_buf, size_t unit_size, size_t stride, unsigned int k, unsigned int m, const unsigned int *erasures, size_t erasures_count) { + if(stride < unit_size) + return CHIAKI_ERR_INVALID_DATA; int *matrix = create_matrix(k, m); if(!matrix) return CHIAKI_ERR_MEMORY; @@ -61,7 +63,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_fec_decode(uint8_t *frame_buf, size_t unit_ for(size_t i=0; ilog = log; frame_processor->frame_buf = NULL; frame_processor->frame_buf_size = 0; + frame_processor->buf_size_per_unit = 0; + frame_processor->buf_stride_per_unit = 0; frame_processor->units_source_expected = 0; frame_processor->units_fec_expected = 0; frame_processor->unit_slots = NULL; @@ -77,6 +79,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_frame_processor_alloc_frame(ChiakiFrameProc } frame_processor->buf_size_per_unit += ntohs(((chiaki_unaligned_uint16_t *)packet->data)[0]); } + frame_processor->buf_stride_per_unit = ((frame_processor->buf_size_per_unit + 0xf) / 0x10) * 0x10; if(frame_processor->buf_size_per_unit == 0) { @@ -116,9 +119,9 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_frame_processor_alloc_frame(ChiakiFrameProc } memset(frame_processor->unit_slots, 0, frame_processor->unit_slots_size * sizeof(ChiakiFrameUnit)); - if(frame_processor->unit_slots_size > SIZE_MAX / frame_processor->buf_size_per_unit) + if(frame_processor->unit_slots_size > SIZE_MAX / frame_processor->buf_stride_per_unit) return CHIAKI_ERR_OVERFLOW; - size_t frame_buf_size_required = frame_processor->unit_slots_size * frame_processor->buf_size_per_unit; + size_t frame_buf_size_required = frame_processor->unit_slots_size * frame_processor->buf_stride_per_unit; if(frame_processor->frame_buf_size < frame_buf_size_required) { free(frame_processor->frame_buf); @@ -163,7 +166,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_frame_processor_put_unit(ChiakiFrameProcess } unit->data_size = packet->data_size; - memcpy(frame_processor->frame_buf + packet->unit_index * frame_processor->buf_size_per_unit, + memcpy(frame_processor->frame_buf + packet->unit_index * frame_processor->buf_stride_per_unit, packet->data, packet->data_size); @@ -206,7 +209,8 @@ static ChiakiErrorCode chiaki_frame_processor_fec(ChiakiFrameProcessor *frame_pr } assert(erasure_index == erasures_count); - ChiakiErrorCode err = chiaki_fec_decode(frame_processor->frame_buf, frame_processor->buf_size_per_unit, + ChiakiErrorCode err = chiaki_fec_decode(frame_processor->frame_buf, + frame_processor->buf_size_per_unit, frame_processor->buf_stride_per_unit, frame_processor->units_source_expected, frame_processor->units_fec_received, erasures, erasures_count); @@ -224,7 +228,7 @@ static ChiakiErrorCode chiaki_frame_processor_fec(ChiakiFrameProcessor *frame_pr for(size_t i=0; iunits_source_expected; i++) { ChiakiFrameUnit *slot = frame_processor->unit_slots + i; - uint8_t *buf_ptr = frame_processor->frame_buf + frame_processor->buf_size_per_unit * i; + uint8_t *buf_ptr = frame_processor->frame_buf + frame_processor->buf_stride_per_unit * i; uint16_t padding = ntohs(*((chiaki_unaligned_uint16_t *)buf_ptr)); if(padding >= frame_processor->buf_size_per_unit) { @@ -272,7 +276,7 @@ CHIAKI_EXPORT ChiakiFrameProcessorFlushResult chiaki_frame_processor_flush(Chiak continue; } size_t part_size = unit->data_size - 2; - uint8_t *buf_ptr = frame_processor->frame_buf + i*frame_processor->buf_size_per_unit; + uint8_t *buf_ptr = frame_processor->frame_buf + i*frame_processor->buf_stride_per_unit; memmove(frame_processor->frame_buf + cur, buf_ptr + 2, part_size); cur += part_size; } diff --git a/test/fec.c b/test/fec.c index 44848fe..d58107b 100644 --- a/test/fec.c +++ b/test/fec.c @@ -34,17 +34,20 @@ typedef struct fec_test_case_t static MunitResult test_fec_case(FECTestCase *test_case) { size_t b64len = strlen(test_case->frame_buffer_b64); - size_t frame_buffer_size = b64len; - - uint8_t *frame_buffer_ref = malloc(frame_buffer_size); + uint8_t *frame_buffer_ref = malloc(b64len); munit_assert_not_null(frame_buffer_ref); + + size_t stride = ((test_case->unit_size + 0xf) / 0x10) * 0x10; + size_t frame_buffer_size = stride * (test_case->k + test_case->m); uint8_t *frame_buffer = malloc(frame_buffer_size); munit_assert_not_null(frame_buffer); - ChiakiErrorCode err = chiaki_base64_decode(test_case->frame_buffer_b64, b64len, frame_buffer_ref, &frame_buffer_size); + ChiakiErrorCode err = chiaki_base64_decode(test_case->frame_buffer_b64, b64len, frame_buffer_ref, &b64len); munit_assert_int(err, ==, CHIAKI_ERR_SUCCESS); - munit_assert_size(frame_buffer_size, ==, test_case->unit_size * (test_case->k + test_case->m)); - memcpy(frame_buffer, frame_buffer_ref, frame_buffer_size); + munit_assert_size(b64len, ==, test_case->unit_size * (test_case->k + test_case->m)); + + for(size_t i=0; ik + test_case->m; i++) + memcpy(frame_buffer + i * stride, frame_buffer_ref + i * test_case->unit_size, test_case->unit_size); size_t erasures_count = 0; for(const int *e = test_case->erasures; *e >= 0; e++, erasures_count++); @@ -54,13 +57,14 @@ static MunitResult test_fec_case(FECTestCase *test_case) { unsigned int e = test_case->erasures[i]; munit_assert_uint(e, <, test_case->k + test_case->m); - memset(frame_buffer + test_case->unit_size * e, 0x42, test_case->unit_size); + memset(frame_buffer + stride * e, 0x42, test_case->unit_size); } - err = chiaki_fec_decode(frame_buffer, test_case->unit_size, test_case->k, test_case->m, (const unsigned int *)test_case->erasures, erasures_count); + err = chiaki_fec_decode(frame_buffer, test_case->unit_size, stride, test_case->k, test_case->m, (const unsigned int *)test_case->erasures, erasures_count); munit_assert_int(err, ==, CHIAKI_ERR_SUCCESS); - munit_assert_memory_equal(test_case->k * test_case->unit_size, frame_buffer, frame_buffer_ref); + for(size_t i=0; ik; i++) + munit_assert_memory_equal(test_case->unit_size, frame_buffer + i * stride, frame_buffer_ref + i * test_case->unit_size); free(frame_buffer); free(frame_buffer_ref); @@ -88,4 +92,4 @@ MunitTest tests_fec[] = { fec_params }, { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } -}; \ No newline at end of file +};