|
@@ -12,6 +12,17 @@
|
|
|
|
|
|
#define CHECKS
|
|
|
|
|
|
+#ifdef DEBUG
|
|
|
+# define SLOW_CHECKS
|
|
|
+# define ALL_CHECKS
|
|
|
+# define VERBOSE
|
|
|
+#endif /* DEBUG */
|
|
|
+
|
|
|
+#ifdef ALL_CHECKS
|
|
|
+# undef HAVE_SSE
|
|
|
+#endif /* ALL_CHECKS */
|
|
|
+
|
|
|
+
|
|
|
#define IPECAMERA_NUM_ROWS 1088
|
|
|
#define IPECAMERA_NUM_CHANNELS 16 /**< Number of channels per row */
|
|
|
#define IPECAMERA_PIXELS_PER_CHANNEL 128 /**< Number of pixels per channel */
|
|
@@ -35,7 +46,7 @@ typedef struct {
|
|
|
/**
|
|
|
* Check if value matches expected input.
|
|
|
*/
|
|
|
-#ifdef DEBUG
|
|
|
+#ifdef VERBOSE
|
|
|
# define CHECK_VALUE(value, expected) \
|
|
|
if (value != expected) { \
|
|
|
fprintf(stderr, "<%s:%i> 0x%x != 0x%x\n", __FILE__, __LINE__, value, expected); \
|
|
@@ -51,7 +62,7 @@ typedef struct {
|
|
|
/**
|
|
|
* Check that flag evaluates to non-zero.
|
|
|
*/
|
|
|
-#ifdef DEBUG
|
|
|
+#ifdef VERBOSE
|
|
|
# define CHECK_FLAG(flag, check, ...) \
|
|
|
if (!(check)) { \
|
|
|
fprintf(stderr, "<%s:%i> Unexpected value 0x%x of " flag "\n", __FILE__, __LINE__, __VA_ARGS__); \
|
|
@@ -136,7 +147,7 @@ ufo_decode_frame_channels_v0(UfoDecoder *decoder,
|
|
|
int pos = 0;
|
|
|
uint32_t data;
|
|
|
|
|
|
-#if defined(HAVE_SSE) && !defined(DEBUG)
|
|
|
+#ifdef HAVE_SSE
|
|
|
__m128i mask = _mm_set_epi32(0x3FF, 0x3FF, 0x3FF, 0x3FF);
|
|
|
__m128i packed;
|
|
|
__m128i tmp1, tmp2;
|
|
@@ -144,7 +155,7 @@ ufo_decode_frame_channels_v0(UfoDecoder *decoder,
|
|
|
#endif
|
|
|
|
|
|
if (cpi * channel_size > num_words) {
|
|
|
-#ifdef DEBUG
|
|
|
+#ifdef VERBOSE
|
|
|
fprintf(stderr, "Not enough data to decode frame, expected %lu bytes, but received %lu\n", cpi * channel_size * sizeof(uint32_t), num_words * sizeof(uint32_t));
|
|
|
#endif
|
|
|
return EILSEQ;
|
|
@@ -156,7 +167,7 @@ ufo_decode_frame_channels_v0(UfoDecoder *decoder,
|
|
|
int channel = info & 0x0F;
|
|
|
int pixels = (info >> 20) & 0xFF;
|
|
|
|
|
|
-#ifdef CHECKS
|
|
|
+#ifdef SLOW_CHECKS
|
|
|
int header = (info >> 30) & 0x03;
|
|
|
const int bpp = (info >> 16) & 0x0F;
|
|
|
int err;
|
|
@@ -177,12 +188,12 @@ ufo_decode_frame_channels_v0(UfoDecoder *decoder,
|
|
|
pixel_buffer[base] = 0;
|
|
|
/* base++; */
|
|
|
}
|
|
|
-#ifdef CHECKS
|
|
|
+#ifdef SLOW_CHECKS
|
|
|
else
|
|
|
CHECK_FLAG("number of pixels, %i is expected", pixels == IPECAMERA_PIXELS_PER_CHANNEL, pixels, IPECAMERA_PIXELS_PER_CHANNEL);
|
|
|
#endif
|
|
|
|
|
|
-#if defined(HAVE_SSE) && !defined(DEBUG)
|
|
|
+#ifdef HAVE_SSE
|
|
|
for (int i = 1 ; i < bytes-4; i += 4, base += 12) {
|
|
|
packed = _mm_set_epi32(raw[i], raw[i+1], raw[i+2], raw[i+3]);
|
|
|
|
|
@@ -224,12 +235,12 @@ ufo_decode_frame_channels_v0(UfoDecoder *decoder,
|
|
|
#else
|
|
|
for (int i = 1 ; i < bytes; i++) {
|
|
|
data = raw[i];
|
|
|
-#ifdef DEBUG
|
|
|
+# ifdef SLOW_CHECKS
|
|
|
header = (data >> 30) & 0x03;
|
|
|
CHECK_FLAG("raw data magic", header == 3, header);
|
|
|
if (err)
|
|
|
return err;
|
|
|
-#endif
|
|
|
+# endif
|
|
|
pixel_buffer[base++] = (data >> 20) & 0x3FF;
|
|
|
pixel_buffer[base++] = (data >> 10) & 0x3FF;
|
|
|
pixel_buffer[base++] = data & 0x3FF;
|
|
@@ -237,7 +248,7 @@ ufo_decode_frame_channels_v0(UfoDecoder *decoder,
|
|
|
#endif
|
|
|
|
|
|
data = raw[bytes];
|
|
|
-#ifdef DEBUG
|
|
|
+#ifdef SLOW_CHECKS
|
|
|
header = (data >> 30) & 0x03;
|
|
|
CHECK_FLAG("raw data magic", header == 3, header);
|
|
|
CHECK_FLAG("raw footer magic", (data & 0x3FF) == 0x55, (data & 0x3FF));
|
|
@@ -253,7 +264,7 @@ ufo_decode_frame_channels_v0(UfoDecoder *decoder,
|
|
|
raw += channel_size;
|
|
|
}
|
|
|
|
|
|
- *offset = pos;
|
|
|
+ *offset += pos;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -274,7 +285,7 @@ ufo_decode_frame_channels_v4(UfoDecoder *decoder,
|
|
|
int pos = 0;
|
|
|
uint32_t data;
|
|
|
|
|
|
-#if defined(HAVE_SSE) && !defined(DEBUG)
|
|
|
+#ifdef HAVE_SSE
|
|
|
__m128i mask = _mm_set_epi32(0x3FF, 0x3FF, 0x3FF, 0x3FF);
|
|
|
__m128i packed;
|
|
|
__m128i tmp1, tmp2;
|
|
@@ -282,28 +293,29 @@ ufo_decode_frame_channels_v4(UfoDecoder *decoder,
|
|
|
#endif
|
|
|
|
|
|
if (cpi * channel_size > num_words) {
|
|
|
-#ifdef DEBUG
|
|
|
+#ifdef VERBOSE
|
|
|
fprintf(stderr, "Not enough data to decode frame, expected %lu bytes, but received %lu\n", cpi * channel_size * sizeof(uint32_t), num_words * sizeof(uint32_t));
|
|
|
#endif
|
|
|
return EILSEQ;
|
|
|
}
|
|
|
|
|
|
for (size_t c = 0; c < cpi; c++) {
|
|
|
+ int err = 0;
|
|
|
const int info = raw[0];
|
|
|
int row = (info >> 4) & 0x7FF;
|
|
|
int channel = info & 0x0F;
|
|
|
int pixels = (info >> 20) & 0xFF;
|
|
|
|
|
|
-#ifdef DEBUG
|
|
|
- int err = 0;
|
|
|
+#ifdef SLOW_CHECKS
|
|
|
int header = (info >> 30) & 0x03;
|
|
|
const int bpp = (info >> 16) & 0x0F;
|
|
|
CHECK_FLAG("raw header magick", header == 2, header);
|
|
|
CHECK_FLAG("pixel size, only 10 bits are supported", bpp == 10, bpp);
|
|
|
- CHECK_FLAG("channel, limited by %zu output channels", channel < channels_per_row, channel, channels_per_row);
|
|
|
#endif
|
|
|
|
|
|
- if ((channel > channels_per_row) || (pixels > IPECAMERA_PIXELS_PER_CHANNEL))
|
|
|
+ CHECK_FLAG("pixels, only %u pixels per channel (offset: %zx)", pixels <= IPECAMERA_PIXELS_PER_CHANNEL, pixels, IPECAMERA_PIXELS_PER_CHANNEL, (*offset + pos));
|
|
|
+ CHECK_FLAG("channel, limited by %zu output channels (offset: %zx)", channel <= channels_per_row, channel, channels_per_row, (*offset + pos));
|
|
|
+ if (err)
|
|
|
return EILSEQ;
|
|
|
|
|
|
channel = channel_order[channel];
|
|
@@ -315,7 +327,7 @@ ufo_decode_frame_channels_v4(UfoDecoder *decoder,
|
|
|
/* base++; */
|
|
|
}
|
|
|
|
|
|
-#if defined(HAVE_SSE) && !defined(DEBUG)
|
|
|
+#ifdef HAVE_SSE
|
|
|
for (int i = 1 ; i < bytes-4; i += 4, base += 12) {
|
|
|
packed = _mm_set_epi32(raw[i], raw[i+1], raw[i+2], raw[i+3]);
|
|
|
|
|
@@ -357,12 +369,12 @@ ufo_decode_frame_channels_v4(UfoDecoder *decoder,
|
|
|
#else
|
|
|
for (int i = 1 ; i < bytes; i++) {
|
|
|
data = raw[i];
|
|
|
-#ifdef DEBUG
|
|
|
+# ifdef SLOW_CHECKS
|
|
|
header = (data >> 30) & 0x03;
|
|
|
- CHECK_FLAG("raw data magic", header == 3, header);
|
|
|
+ CHECK_FLAG("raw data magic (offset: 0x%zx, expected: 0x02)", header == 3, header, (*offset + pos + i)*sizeof(uint32_t));
|
|
|
if (err)
|
|
|
return err;
|
|
|
-#endif
|
|
|
+# endif
|
|
|
pixel_buffer[base++] = (data >> 20) & 0x3FF;
|
|
|
pixel_buffer[base++] = (data >> 10) & 0x3FF;
|
|
|
pixel_buffer[base++] = data & 0x3FF;
|
|
@@ -370,10 +382,10 @@ ufo_decode_frame_channels_v4(UfoDecoder *decoder,
|
|
|
#endif
|
|
|
|
|
|
data = raw[bytes];
|
|
|
-#ifdef DEBUG
|
|
|
+#ifdef SLOW_CHECKS
|
|
|
header = (data >> 30) & 0x03;
|
|
|
- CHECK_FLAG("raw data magic", header == 3, header);
|
|
|
- CHECK_FLAG("raw footer magic", (data & 0x3FF) == 0x55, (data & 0x3FF));
|
|
|
+ CHECK_FLAG("raw data magic (offset: 0x%zx, expected: 0x03)", header == 3, header, (*offset + pos + bytes)*sizeof(uint32_t));
|
|
|
+ CHECK_FLAG("raw footer magic (offset: 0x%zx, expected: 0x55)", (data & 0x3FF) == 0x55, (data & 0x3FF), (*offset + pos + bytes)*sizeof(uint32_t));
|
|
|
if (err)
|
|
|
return err;
|
|
|
#endif
|
|
@@ -386,7 +398,7 @@ ufo_decode_frame_channels_v4(UfoDecoder *decoder,
|
|
|
raw += channel_size;
|
|
|
}
|
|
|
|
|
|
- *offset = pos;
|
|
|
+ *offset += pos;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -460,7 +472,7 @@ ufo_decode_frame_channels_v5(UfoDecoder *decoder,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- *offset = base;
|
|
|
+ *offset += base;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -535,16 +547,20 @@ size_t ufo_decoder_decode_frame(UfoDecoder *decoder,
|
|
|
{
|
|
|
int err = 0;
|
|
|
size_t pos = 0;
|
|
|
- size_t advance = 0;
|
|
|
const size_t num_words = num_bytes / 4;
|
|
|
|
|
|
- if ((pixels == NULL) || (num_words < 16))
|
|
|
+ if ((pixels == NULL) || (num_words < 16)) {
|
|
|
+#ifdef VERBOSE
|
|
|
+ if (num_words < 16)
|
|
|
+ fprintf(stderr, "Not enough frame data, only %zu bytes supplied \n", num_bytes);
|
|
|
+#endif
|
|
|
return 0;
|
|
|
+ }
|
|
|
|
|
|
size_t rows_per_frame = decoder->height;
|
|
|
const int version = (raw[pos+6] >> 24) & 0xF;
|
|
|
|
|
|
-#ifdef DEBUG
|
|
|
+#ifdef CHECKS
|
|
|
CHECK_VALUE(raw[pos++], 0x51111111);
|
|
|
CHECK_VALUE(raw[pos++], 0x52222222);
|
|
|
CHECK_VALUE(raw[pos++], 0x53333333);
|
|
@@ -576,15 +592,17 @@ size_t ufo_decoder_decode_frame(UfoDecoder *decoder,
|
|
|
pos++;
|
|
|
|
|
|
if ((meta->output_mode != IPECAMERA_MODE_4_CHAN_IO) && (meta->output_mode != IPECAMERA_MODE_16_CHAN_IO)) {
|
|
|
-#ifdef DEBUG
|
|
|
+# ifdef VERBOSE
|
|
|
fprintf(stderr, "Output mode 0x%x is not supported\n", meta->output_mode);
|
|
|
-#endif
|
|
|
- return EILSEQ;
|
|
|
+# endif
|
|
|
+ return 0;
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
+# ifdef VERBOSE
|
|
|
fprintf(stderr, "Unsupported data format version %i detected\n", version);
|
|
|
+# endif
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -597,6 +615,7 @@ size_t ufo_decoder_decode_frame(UfoDecoder *decoder,
|
|
|
meta->time_stamp = raw[pos + 7] & 0xFFFFFFF;
|
|
|
break;
|
|
|
case 4:
|
|
|
+ meta->n_rows = rows_per_frame = raw[pos + 5] & 0x7FF;
|
|
|
case 5:
|
|
|
meta->frame_number = raw[pos + 6] & 0x1FFFFFF;
|
|
|
meta->time_stamp = raw[pos + 7] & 0xFFFFFF;
|
|
@@ -605,7 +624,9 @@ size_t ufo_decoder_decode_frame(UfoDecoder *decoder,
|
|
|
|
|
|
break;
|
|
|
default:
|
|
|
+# ifdef VERBOSE
|
|
|
fprintf(stderr, "Unsupported data format detected\n");
|
|
|
+# endif
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -614,13 +635,13 @@ size_t ufo_decoder_decode_frame(UfoDecoder *decoder,
|
|
|
|
|
|
switch (version) {
|
|
|
case 0:
|
|
|
- err = ufo_decode_frame_channels_v0(decoder, pixels, raw + pos, num_words - pos - 8, &advance);
|
|
|
+ err = ufo_decode_frame_channels_v0(decoder, pixels, raw + pos, num_words - pos - 8, &pos);
|
|
|
break;
|
|
|
case 4:
|
|
|
- err = ufo_decode_frame_channels_v4(decoder, pixels, raw + pos, num_words - pos - 8, rows_per_frame, &advance);
|
|
|
+ err = ufo_decode_frame_channels_v4(decoder, pixels, raw + pos, num_words - pos - 8, rows_per_frame, &pos);
|
|
|
break;
|
|
|
case 5:
|
|
|
- err = ufo_decode_frame_channels_v5(decoder, pixels, raw + pos, rows_per_frame, &advance, meta->output_mode);
|
|
|
+ err = ufo_decode_frame_channels_v5(decoder, pixels, raw + pos, rows_per_frame, &pos, meta->output_mode);
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
@@ -629,8 +650,6 @@ size_t ufo_decoder_decode_frame(UfoDecoder *decoder,
|
|
|
if (err)
|
|
|
return 0;
|
|
|
|
|
|
- pos += advance;
|
|
|
-
|
|
|
#ifdef CHECKS
|
|
|
CHECK_VALUE(raw[pos++], 0x0AAAAAAA);
|
|
|
|