bzr branch
http://suren.me/webbzr/alps/ufodecode
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
1 |
#include <stdio.h> |
2 |
#include <stdlib.h> |
|
3 |
#include <string.h> |
|
4 |
#include <errno.h> |
|
9
by Matthias Vogelgesang
Rename to `ufodecode` |
5 |
#include "ufodecode.h" |
6 |
#include "ufodecode-private.h" |
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
7 |
#include "config.h" |
9
by Matthias Vogelgesang
Rename to `ufodecode` |
8 |
|
9 |
#ifdef HAVE_SSE
|
|
8
by Matthias Vogelgesang
Add: optional SSE intrinsics |
10 |
#include <xmmintrin.h> |
9
by Matthias Vogelgesang
Rename to `ufodecode` |
11 |
#endif
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
12 |
|
11.1.7
by Suren A. Chilingaryan
Introduce quiete checking of frame consistencies |
13 |
#define CHECKS
|
14 |
||
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
15 |
#ifdef DEBUG
|
16 |
# define SLOW_CHECKS
|
|
17 |
# define ALL_CHECKS
|
|
18 |
# define VERBOSE
|
|
19 |
#endif /* DEBUG */ |
|
20 |
||
21 |
#ifdef ALL_CHECKS
|
|
22 |
# undef HAVE_SSE
|
|
23 |
#endif /* ALL_CHECKS */ |
|
24 |
||
25 |
||
31
by Matthias Vogelgesang
Clean up source a bit |
26 |
#define IPECAMERA_NUM_ROWS 1088
|
27 |
#define IPECAMERA_NUM_CHANNELS 16 /**< Number of channels per row */ |
|
28 |
#define IPECAMERA_PIXELS_PER_CHANNEL 128 /**< Number of pixels per channel */ |
|
10
by Matthias Vogelgesang
Add documentation and split CMakeLists |
29 |
#define IPECAMERA_WIDTH (IPECAMERA_NUM_CHANNELS * IPECAMERA_PIXELS_PER_CHANNEL) /**< Total pixel width of row */ |
30 |
||
41
by Suren A. Chilingaryan
Black magick from Michele |
31 |
#define IPECAMERA_MODE_16_CHAN_IO 0
|
32 |
#define IPECAMERA_MODE_4_CHAN_IO 2
|
|
33 |
||
34 |
#define IPECAMERA_MODE_12_BIT_ADC 2
|
|
35 |
#define IPECAMERA_MODE_11_BIT_ADC 1
|
|
36 |
#define IPECAMERA_MODE_10_BIT_ADC 0
|
|
37 |
||
18
by Matthias Vogelgesang
Implement frame version 5 |
38 |
typedef struct { |
39 |
unsigned int pixel_number : 8; |
|
40 |
unsigned int row_number : 12; |
|
41 |
unsigned int pixel_size : 4; |
|
42 |
unsigned int magic : 8; |
|
43 |
} payload_header_v5; |
|
44 |
||
10
by Matthias Vogelgesang
Add documentation and split CMakeLists |
45 |
|
46 |
/**
|
|
47 |
* Check if value matches expected input.
|
|
48 |
*/
|
|
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
49 |
#ifdef VERBOSE
|
11.1.7
by Suren A. Chilingaryan
Introduce quiete checking of frame consistencies |
50 |
# define CHECK_VALUE(value, expected) \
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
51 |
if (value != expected) { \
|
52 |
fprintf(stderr, "<%s:%i> 0x%x != 0x%x\n", __FILE__, __LINE__, value, expected); \
|
|
53 |
err = 1; \
|
|
54 |
}
|
|
11.1.7
by Suren A. Chilingaryan
Introduce quiete checking of frame consistencies |
55 |
#else
|
56 |
# define CHECK_VALUE(value, expected) \
|
|
57 |
if (value != expected) { \
|
|
58 |
err = 1; \
|
|
59 |
}
|
|
60 |
#endif
|
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
61 |
|
10
by Matthias Vogelgesang
Add documentation and split CMakeLists |
62 |
/**
|
63 |
* Check that flag evaluates to non-zero.
|
|
64 |
*/
|
|
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
65 |
#ifdef VERBOSE
|
11.1.7
by Suren A. Chilingaryan
Introduce quiete checking of frame consistencies |
66 |
# define CHECK_FLAG(flag, check, ...) \
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
67 |
if (!(check)) { \
|
68 |
fprintf(stderr, "<%s:%i> Unexpected value 0x%x of " flag "\n", __FILE__, __LINE__, __VA_ARGS__); \
|
|
69 |
err = 1; \
|
|
70 |
}
|
|
11.1.7
by Suren A. Chilingaryan
Introduce quiete checking of frame consistencies |
71 |
#else
|
72 |
# define CHECK_FLAG(flag, check, ...) \
|
|
73 |
if (!(check)) { \
|
|
74 |
err = 1; \
|
|
75 |
}
|
|
76 |
#endif
|
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
77 |
|
78 |
/**
|
|
79 |
* \brief Setup a new decoder instance
|
|
80 |
*
|
|
16
by Matthias Vogelgesang
Add version 4 frame decoding |
81 |
* \param height Number of rows that are expected in the data stream. Set this
|
82 |
* smaller 0 to let the decoder figure out the number of rows.
|
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
83 |
* \param raw The data stream from the camera or NULL if set later with
|
9
by Matthias Vogelgesang
Rename to `ufodecode` |
84 |
* ufo_decoder_set_raw_data.
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
85 |
* \param num_bytes Size of the data stream buffer in bytes
|
86 |
*
|
|
87 |
* \return A new decoder instance that can be used to iterate over the frames
|
|
9
by Matthias Vogelgesang
Rename to `ufodecode` |
88 |
* using ufo_decoder_get_next_frame.
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
89 |
*/
|
32
by Matthias Vogelgesang
Commit version 0.2 of libufodecode |
90 |
UfoDecoder * |
31
by Matthias Vogelgesang
Clean up source a bit |
91 |
ufo_decoder_new (int32_t height, uint32_t width, uint32_t *raw, size_t num_bytes) |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
92 |
{
|
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
93 |
if (width % IPECAMERA_PIXELS_PER_CHANNEL) |
94 |
return NULL; |
|
11.1.1
by Suren A. Chilingaryan
Add width support and few consistency checks |
95 |
|
32
by Matthias Vogelgesang
Commit version 0.2 of libufodecode |
96 |
UfoDecoder *decoder = malloc(sizeof(UfoDecoder)); |
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
97 |
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
98 |
if (decoder == NULL) |
99 |
return NULL; |
|
100 |
||
11.1.1
by Suren A. Chilingaryan
Add width support and few consistency checks |
101 |
decoder->width = width; |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
102 |
decoder->height = height; |
9
by Matthias Vogelgesang
Rename to `ufodecode` |
103 |
ufo_decoder_set_raw_data(decoder, raw, num_bytes); |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
104 |
return decoder; |
105 |
}
|
|
106 |
||
107 |
/**
|
|
108 |
* \brief Release decoder instance
|
|
109 |
*
|
|
32
by Matthias Vogelgesang
Commit version 0.2 of libufodecode |
110 |
* \param decoder An UfoDecoder instance
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
111 |
*/
|
31
by Matthias Vogelgesang
Clean up source a bit |
112 |
void
|
32
by Matthias Vogelgesang
Commit version 0.2 of libufodecode |
113 |
ufo_decoder_free(UfoDecoder *decoder) |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
114 |
{
|
115 |
free(decoder); |
|
116 |
}
|
|
117 |
||
118 |
/**
|
|
119 |
* \brief Set raw data stream
|
|
120 |
*
|
|
32
by Matthias Vogelgesang
Commit version 0.2 of libufodecode |
121 |
* \param decoder An UfoDecoder instance
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
122 |
* \param raw Raw data stream
|
123 |
* \param num_bytes Size of data stream buffer in bytes
|
|
124 |
*/
|
|
31
by Matthias Vogelgesang
Clean up source a bit |
125 |
void
|
32
by Matthias Vogelgesang
Commit version 0.2 of libufodecode |
126 |
ufo_decoder_set_raw_data(UfoDecoder *decoder, uint32_t *raw, size_t num_bytes) |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
127 |
{
|
128 |
decoder->raw = raw; |
|
129 |
decoder->num_bytes = num_bytes; |
|
130 |
decoder->current_pos = 0; |
|
131 |
}
|
|
132 |
||
31
by Matthias Vogelgesang
Clean up source a bit |
133 |
static int |
41
by Suren A. Chilingaryan
Black magick from Michele |
134 |
ufo_decode_frame_channels_v0(UfoDecoder *decoder, |
135 |
uint16_t *pixel_buffer, |
|
136 |
uint32_t *raw, |
|
137 |
size_t num_words, |
|
31
by Matthias Vogelgesang
Clean up source a bit |
138 |
size_t *offset) |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
139 |
{
|
140 |
static int channel_order[IPECAMERA_NUM_CHANNELS] = { 15, 13, 14, 12, 10, 8, 11, 7, 9, 6, 5, 2, 4, 3, 0, 1 }; |
|
11.1.1
by Suren A. Chilingaryan
Add width support and few consistency checks |
141 |
static int channel_size = (2 + IPECAMERA_PIXELS_PER_CHANNEL / 3); |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
142 |
|
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
143 |
const int bytes = channel_size - 1; |
144 |
const int num_rows = decoder->height; |
|
145 |
const size_t cpl = (decoder->width / IPECAMERA_PIXELS_PER_CHANNEL); |
|
11.1.1
by Suren A. Chilingaryan
Add width support and few consistency checks |
146 |
const size_t cpi = num_rows * cpl; |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
147 |
int pos = 0; |
148 |
uint32_t data; |
|
149 |
||
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
150 |
#ifdef HAVE_SSE
|
9
by Matthias Vogelgesang
Rename to `ufodecode` |
151 |
__m128i mask = _mm_set_epi32(0x3FF, 0x3FF, 0x3FF, 0x3FF); |
8
by Matthias Vogelgesang
Add: optional SSE intrinsics |
152 |
__m128i packed; |
153 |
__m128i tmp1, tmp2; |
|
154 |
uint32_t result[4] __attribute__ ((aligned (16))) = {0}; |
|
155 |
#endif
|
|
156 |
||
11.1.4
by Suren A. Chilingaryan
Support new footer |
157 |
if (cpi * channel_size > num_words) { |
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
158 |
#ifdef VERBOSE
|
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
159 |
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)); |
11.1.4
by Suren A. Chilingaryan
Support new footer |
160 |
#endif
|
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
161 |
return EILSEQ; |
11.1.4
by Suren A. Chilingaryan
Support new footer |
162 |
}
|
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
163 |
|
164 |
for (size_t c = 0; c < cpi; c++) { |
|
165 |
const int info = raw[0]; |
|
166 |
int row = (info >> 4) & 0x7FF; |
|
167 |
int channel = info & 0x0F; |
|
168 |
int pixels = (info >> 20) & 0xFF; |
|
11.1.1
by Suren A. Chilingaryan
Add width support and few consistency checks |
169 |
|
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
170 |
#ifdef SLOW_CHECKS
|
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
171 |
int header = (info >> 30) & 0x03; |
172 |
const int bpp = (info >> 16) & 0x0F; |
|
39.1.8
by Matthias Vogelgesang
Undo last commit |
173 |
int err; |
11.1.4
by Suren A. Chilingaryan
Support new footer |
174 |
CHECK_FLAG("raw header magick", header == 2, header); |
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
175 |
CHECK_FLAG("row number, only %i rows requested", row < num_rows, row, num_rows); |
11.1.4
by Suren A. Chilingaryan
Support new footer |
176 |
CHECK_FLAG("pixel size, only 10 bits are supported", bpp == 10, bpp); |
11.1.8
by Suren A. Chilingaryan
Fix printf type |
177 |
CHECK_FLAG("channel, limited by %zu output channels", channel < cpl, channel, cpl); |
11.1.4
by Suren A. Chilingaryan
Support new footer |
178 |
#endif
|
179 |
||
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
180 |
if ((row > num_rows) || (channel > cpl) || (pixels > IPECAMERA_PIXELS_PER_CHANNEL)) |
181 |
return EILSEQ; |
|
182 |
||
11.1.7
by Suren A. Chilingaryan
Introduce quiete checking of frame consistencies |
183 |
channel = channel_order[channel]; |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
184 |
int base = row * IPECAMERA_WIDTH + channel * IPECAMERA_PIXELS_PER_CHANNEL; |
185 |
||
186 |
/* "Correct" missing pixel */
|
|
187 |
if ((row < 2) && (pixels == (IPECAMERA_PIXELS_PER_CHANNEL - 1))) { |
|
188 |
pixel_buffer[base] = 0; |
|
8
by Matthias Vogelgesang
Add: optional SSE intrinsics |
189 |
/* base++; */
|
190 |
}
|
|
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
191 |
#ifdef SLOW_CHECKS
|
41
by Suren A. Chilingaryan
Black magick from Michele |
192 |
else
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
193 |
CHECK_FLAG("number of pixels, %i is expected", pixels == IPECAMERA_PIXELS_PER_CHANNEL, pixels, IPECAMERA_PIXELS_PER_CHANNEL); |
194 |
#endif
|
|
195 |
||
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
196 |
#ifdef HAVE_SSE
|
8
by Matthias Vogelgesang
Add: optional SSE intrinsics |
197 |
for (int i = 1 ; i < bytes-4; i += 4, base += 12) { |
198 |
packed = _mm_set_epi32(raw[i], raw[i+1], raw[i+2], raw[i+3]); |
|
199 |
||
200 |
tmp1 = _mm_srli_epi32(packed, 20); |
|
9
by Matthias Vogelgesang
Rename to `ufodecode` |
201 |
tmp2 = _mm_and_si128(tmp1, mask); |
8
by Matthias Vogelgesang
Add: optional SSE intrinsics |
202 |
_mm_storeu_si128((__m128i*) result, tmp2); |
12
by Matthias Vogelgesang
Fix: wrong order of pixels when using SSE |
203 |
|
204 |
pixel_buffer[base+0] = result[3]; |
|
205 |
pixel_buffer[base+3] = result[2]; |
|
206 |
pixel_buffer[base+6] = result[1]; |
|
207 |
pixel_buffer[base+9] = result[0]; |
|
8
by Matthias Vogelgesang
Add: optional SSE intrinsics |
208 |
|
209 |
tmp1 = _mm_srli_epi32(packed, 10); |
|
9
by Matthias Vogelgesang
Rename to `ufodecode` |
210 |
tmp2 = _mm_and_si128(tmp1, mask); |
8
by Matthias Vogelgesang
Add: optional SSE intrinsics |
211 |
_mm_storeu_si128((__m128i*) result, tmp2); |
12
by Matthias Vogelgesang
Fix: wrong order of pixels when using SSE |
212 |
pixel_buffer[base+1] = result[3]; |
213 |
pixel_buffer[base+4] = result[2]; |
|
214 |
pixel_buffer[base+7] = result[1]; |
|
215 |
pixel_buffer[base+10] = result[0]; |
|
8
by Matthias Vogelgesang
Add: optional SSE intrinsics |
216 |
|
9
by Matthias Vogelgesang
Rename to `ufodecode` |
217 |
tmp1 = _mm_and_si128(packed, mask); |
8
by Matthias Vogelgesang
Add: optional SSE intrinsics |
218 |
_mm_storeu_si128((__m128i*) result, tmp1); |
12
by Matthias Vogelgesang
Fix: wrong order of pixels when using SSE |
219 |
pixel_buffer[base+2] = result[3]; |
220 |
pixel_buffer[base+5] = result[2]; |
|
221 |
pixel_buffer[base+8] = result[1]; |
|
222 |
pixel_buffer[base+11] = result[0]; |
|
8
by Matthias Vogelgesang
Add: optional SSE intrinsics |
223 |
}
|
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
224 |
|
12
by Matthias Vogelgesang
Fix: wrong order of pixels when using SSE |
225 |
/* Compute last pixels by hand */
|
226 |
data = raw[41]; |
|
227 |
pixel_buffer[base++] = (data >> 20) & 0x3FF; |
|
228 |
pixel_buffer[base++] = (data >> 10) & 0x3FF; |
|
229 |
pixel_buffer[base++] = data & 0x3FF; |
|
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
230 |
|
12
by Matthias Vogelgesang
Fix: wrong order of pixels when using SSE |
231 |
data = raw[42]; |
232 |
pixel_buffer[base++] = (data >> 20) & 0x3FF; |
|
233 |
pixel_buffer[base++] = (data >> 10) & 0x3FF; |
|
234 |
pixel_buffer[base++] = data & 0x3FF; |
|
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
235 |
#else
|
8
by Matthias Vogelgesang
Add: optional SSE intrinsics |
236 |
for (int i = 1 ; i < bytes; i++) { |
237 |
data = raw[i]; |
|
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
238 |
# ifdef SLOW_CHECKS
|
41
by Suren A. Chilingaryan
Black magick from Michele |
239 |
header = (data >> 30) & 0x03; |
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
240 |
CHECK_FLAG("raw data magic", header == 3, header); |
41
by Suren A. Chilingaryan
Black magick from Michele |
241 |
if (err) |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
242 |
return err; |
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
243 |
# endif
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
244 |
pixel_buffer[base++] = (data >> 20) & 0x3FF; |
245 |
pixel_buffer[base++] = (data >> 10) & 0x3FF; |
|
246 |
pixel_buffer[base++] = data & 0x3FF; |
|
247 |
}
|
|
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
248 |
#endif
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
249 |
|
250 |
data = raw[bytes]; |
|
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
251 |
#ifdef SLOW_CHECKS
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
252 |
header = (data >> 30) & 0x03; |
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
253 |
CHECK_FLAG("raw data magic", header == 3, header); |
254 |
CHECK_FLAG("raw footer magic", (data & 0x3FF) == 0x55, (data & 0x3FF)); |
|
41
by Suren A. Chilingaryan
Black magick from Michele |
255 |
if (err) |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
256 |
return err; |
257 |
#endif
|
|
258 |
||
259 |
int ppw = pixels >> 6; |
|
260 |
for (int j = 0; j < ppw; j++) |
|
261 |
pixel_buffer[base++] = (data >> (10 * (ppw - j))) & 0x3FF; |
|
262 |
||
11.1.1
by Suren A. Chilingaryan
Add width support and few consistency checks |
263 |
pos += channel_size; |
264 |
raw += channel_size; |
|
265 |
}
|
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
266 |
|
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
267 |
*offset += pos; |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
268 |
return 0; |
269 |
}
|
|
270 |
||
31
by Matthias Vogelgesang
Clean up source a bit |
271 |
static int |
32
by Matthias Vogelgesang
Commit version 0.2 of libufodecode |
272 |
ufo_decode_frame_channels_v4(UfoDecoder *decoder, |
41
by Suren A. Chilingaryan
Black magick from Michele |
273 |
uint16_t *pixel_buffer, |
274 |
uint32_t *raw, |
|
275 |
size_t num_words, |
|
276 |
size_t num_rows, |
|
31
by Matthias Vogelgesang
Clean up source a bit |
277 |
size_t *offset) |
16
by Matthias Vogelgesang
Add version 4 frame decoding |
278 |
{
|
279 |
static const int channel_order[IPECAMERA_NUM_CHANNELS] = { 15, 13, 14, 12, 10, 8, 11, 7, 9, 6, 5, 2, 4, 3, 0, 1 }; |
|
280 |
static const int channel_size = (2 + IPECAMERA_PIXELS_PER_CHANNEL / 3); |
|
281 |
||
282 |
const int bytes = channel_size - 1; |
|
283 |
const size_t channels_per_row = (decoder->width / IPECAMERA_PIXELS_PER_CHANNEL); |
|
284 |
const size_t cpi = num_rows * channels_per_row; |
|
285 |
int pos = 0; |
|
286 |
uint32_t data; |
|
287 |
||
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
288 |
#ifdef HAVE_SSE
|
16
by Matthias Vogelgesang
Add version 4 frame decoding |
289 |
__m128i mask = _mm_set_epi32(0x3FF, 0x3FF, 0x3FF, 0x3FF); |
290 |
__m128i packed; |
|
291 |
__m128i tmp1, tmp2; |
|
292 |
uint32_t result[4] __attribute__ ((aligned (16))) = {0}; |
|
293 |
#endif
|
|
294 |
||
295 |
if (cpi * channel_size > num_words) { |
|
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
296 |
#ifdef VERBOSE
|
16
by Matthias Vogelgesang
Add version 4 frame decoding |
297 |
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)); |
298 |
#endif
|
|
299 |
return EILSEQ; |
|
300 |
}
|
|
301 |
||
302 |
for (size_t c = 0; c < cpi; c++) { |
|
303 |
int err = 0; |
|
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
304 |
const int info = raw[0]; |
305 |
int row = (info >> 4) & 0x7FF; |
|
306 |
int channel = info & 0x0F; |
|
307 |
int pixels = (info >> 20) & 0xFF; |
|
308 |
||
309 |
#ifdef SLOW_CHECKS
|
|
16
by Matthias Vogelgesang
Add version 4 frame decoding |
310 |
int header = (info >> 30) & 0x03; |
311 |
const int bpp = (info >> 16) & 0x0F; |
|
312 |
CHECK_FLAG("raw header magick", header == 2, header); |
|
313 |
CHECK_FLAG("pixel size, only 10 bits are supported", bpp == 10, bpp); |
|
314 |
#endif
|
|
315 |
||
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
316 |
CHECK_FLAG("pixels, only %u pixels per channel (offset: %zx)", pixels <= IPECAMERA_PIXELS_PER_CHANNEL, pixels, IPECAMERA_PIXELS_PER_CHANNEL, (*offset + pos)); |
317 |
CHECK_FLAG("channel, limited by %zu output channels (offset: %zx)", channel <= channels_per_row, channel, channels_per_row, (*offset + pos)); |
|
318 |
if (err) |
|
16
by Matthias Vogelgesang
Add version 4 frame decoding |
319 |
return EILSEQ; |
320 |
||
321 |
channel = channel_order[channel]; |
|
322 |
int base = row * IPECAMERA_WIDTH + channel * IPECAMERA_PIXELS_PER_CHANNEL; |
|
323 |
||
324 |
/* "Correct" missing pixel */
|
|
325 |
if ((row < 2) && (pixels == (IPECAMERA_PIXELS_PER_CHANNEL - 1))) { |
|
326 |
pixel_buffer[base] = 0; |
|
327 |
/* base++; */
|
|
328 |
}
|
|
329 |
||
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
330 |
#ifdef HAVE_SSE
|
16
by Matthias Vogelgesang
Add version 4 frame decoding |
331 |
for (int i = 1 ; i < bytes-4; i += 4, base += 12) { |
332 |
packed = _mm_set_epi32(raw[i], raw[i+1], raw[i+2], raw[i+3]); |
|
333 |
||
334 |
tmp1 = _mm_srli_epi32(packed, 20); |
|
335 |
tmp2 = _mm_and_si128(tmp1, mask); |
|
336 |
_mm_storeu_si128((__m128i*) result, tmp2); |
|
337 |
||
338 |
pixel_buffer[base+0] = result[3]; |
|
339 |
pixel_buffer[base+3] = result[2]; |
|
340 |
pixel_buffer[base+6] = result[1]; |
|
341 |
pixel_buffer[base+9] = result[0]; |
|
342 |
||
343 |
tmp1 = _mm_srli_epi32(packed, 10); |
|
344 |
tmp2 = _mm_and_si128(tmp1, mask); |
|
345 |
_mm_storeu_si128((__m128i*) result, tmp2); |
|
346 |
pixel_buffer[base+1] = result[3]; |
|
347 |
pixel_buffer[base+4] = result[2]; |
|
348 |
pixel_buffer[base+7] = result[1]; |
|
349 |
pixel_buffer[base+10] = result[0]; |
|
350 |
||
351 |
tmp1 = _mm_and_si128(packed, mask); |
|
352 |
_mm_storeu_si128((__m128i*) result, tmp1); |
|
353 |
pixel_buffer[base+2] = result[3]; |
|
354 |
pixel_buffer[base+5] = result[2]; |
|
355 |
pixel_buffer[base+8] = result[1]; |
|
356 |
pixel_buffer[base+11] = result[0]; |
|
357 |
}
|
|
358 |
||
359 |
/* Compute last pixels by hand */
|
|
360 |
data = raw[41]; |
|
361 |
pixel_buffer[base++] = (data >> 20) & 0x3FF; |
|
362 |
pixel_buffer[base++] = (data >> 10) & 0x3FF; |
|
363 |
pixel_buffer[base++] = data & 0x3FF; |
|
364 |
||
365 |
data = raw[42]; |
|
366 |
pixel_buffer[base++] = (data >> 20) & 0x3FF; |
|
367 |
pixel_buffer[base++] = (data >> 10) & 0x3FF; |
|
368 |
pixel_buffer[base++] = data & 0x3FF; |
|
369 |
#else
|
|
370 |
for (int i = 1 ; i < bytes; i++) { |
|
371 |
data = raw[i]; |
|
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
372 |
# ifdef SLOW_CHECKS
|
41
by Suren A. Chilingaryan
Black magick from Michele |
373 |
header = (data >> 30) & 0x03; |
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
374 |
CHECK_FLAG("raw data magic (offset: 0x%zx, expected: 0x02)", header == 3, header, (*offset + pos + i)*sizeof(uint32_t)); |
41
by Suren A. Chilingaryan
Black magick from Michele |
375 |
if (err) |
16
by Matthias Vogelgesang
Add version 4 frame decoding |
376 |
return err; |
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
377 |
# endif
|
16
by Matthias Vogelgesang
Add version 4 frame decoding |
378 |
pixel_buffer[base++] = (data >> 20) & 0x3FF; |
379 |
pixel_buffer[base++] = (data >> 10) & 0x3FF; |
|
380 |
pixel_buffer[base++] = data & 0x3FF; |
|
381 |
}
|
|
382 |
#endif
|
|
383 |
||
384 |
data = raw[bytes]; |
|
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
385 |
#ifdef SLOW_CHECKS
|
16
by Matthias Vogelgesang
Add version 4 frame decoding |
386 |
header = (data >> 30) & 0x03; |
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
387 |
CHECK_FLAG("raw data magic (offset: 0x%zx, expected: 0x03)", header == 3, header, (*offset + pos + bytes)*sizeof(uint32_t)); |
388 |
CHECK_FLAG("raw footer magic (offset: 0x%zx, expected: 0x55)", (data & 0x3FF) == 0x55, (data & 0x3FF), (*offset + pos + bytes)*sizeof(uint32_t)); |
|
41
by Suren A. Chilingaryan
Black magick from Michele |
389 |
if (err) |
16
by Matthias Vogelgesang
Add version 4 frame decoding |
390 |
return err; |
391 |
#endif
|
|
392 |
||
393 |
int ppw = pixels >> 6; |
|
394 |
for (int j = 0; j < ppw; j++) |
|
395 |
pixel_buffer[base++] = (data >> (10 * (ppw - j))) & 0x3FF; |
|
396 |
||
397 |
pos += channel_size; |
|
398 |
raw += channel_size; |
|
399 |
}
|
|
400 |
||
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
401 |
*offset += pos; |
16
by Matthias Vogelgesang
Add version 4 frame decoding |
402 |
return 0; |
403 |
}
|
|
404 |
||
31
by Matthias Vogelgesang
Clean up source a bit |
405 |
static int |
41
by Suren A. Chilingaryan
Black magick from Michele |
406 |
ufo_decode_frame_channels_v5(UfoDecoder *decoder, |
407 |
uint16_t *pixel_buffer, |
|
408 |
uint32_t *raw, |
|
409 |
size_t num_rows, |
|
410 |
size_t *offset, |
|
411 |
uint8_t output_mode) |
|
18
by Matthias Vogelgesang
Implement frame version 5 |
412 |
{
|
35
by Matthias Vogelgesang
Correctly implement 12 bit mode |
413 |
payload_header_v5 *header; |
18
by Matthias Vogelgesang
Implement frame version 5 |
414 |
size_t base = 0, index = 0; |
35
by Matthias Vogelgesang
Correctly implement 12 bit mode |
415 |
|
416 |
header = (payload_header_v5 *) &raw[base]; |
|
417 |
||
41
by Suren A. Chilingaryan
Black magick from Michele |
418 |
if (output_mode == IPECAMERA_MODE_4_CHAN_IO) { |
39.1.2
by Matthias Vogelgesang
Return errcode != 0 if frame could not be decoded |
419 |
size_t off = 0; |
420 |
||
35
by Matthias Vogelgesang
Correctly implement 12 bit mode |
421 |
while (raw[base] != 0xAAAAAAA) { |
422 |
header = (payload_header_v5 *) &raw[base]; |
|
18
by Matthias Vogelgesang
Implement frame version 5 |
423 |
index = header->row_number * IPECAMERA_WIDTH + header->pixel_number; |
30
by Matthias Vogelgesang
Update for 12 bits |
424 |
|
35
by Matthias Vogelgesang
Correctly implement 12 bit mode |
425 |
/* Skip header + one zero-filled words */
|
426 |
base += 2; |
|
427 |
||
428 |
if ((header->magic != 0xe0) && (header->magic != 0xc0)) { |
|
39
by Matthias Vogelgesang
Fix 12 bit decoding |
429 |
pixel_buffer[index + (0+off)*IPECAMERA_PIXELS_PER_CHANNEL] = 0xfff & (raw[base+5] >> 12); |
430 |
pixel_buffer[index + (4+off)*IPECAMERA_PIXELS_PER_CHANNEL] = 0xfff & (raw[base+4] >> 4); |
|
35
by Matthias Vogelgesang
Correctly implement 12 bit mode |
431 |
pixel_buffer[index + (8+off)*IPECAMERA_PIXELS_PER_CHANNEL] = ((0xf & raw[base+1]) << 8) | (raw[base+2] >> 24); |
39
by Matthias Vogelgesang
Fix 12 bit decoding |
432 |
pixel_buffer[index + (12+off)*IPECAMERA_PIXELS_PER_CHANNEL] = 0xfff & (raw[base+1] >> 16); |
30
by Matthias Vogelgesang
Update for 12 bits |
433 |
}
|
434 |
else { |
|
41
by Suren A. Chilingaryan
Black magick from Michele |
435 |
off++; |
35
by Matthias Vogelgesang
Correctly implement 12 bit mode |
436 |
|
437 |
if (header->magic == 0xc0) |
|
438 |
off = 0; |
|
30
by Matthias Vogelgesang
Update for 12 bits |
439 |
}
|
440 |
||
35
by Matthias Vogelgesang
Correctly implement 12 bit mode |
441 |
base += 6; |
442 |
}
|
|
443 |
}
|
|
39.1.2
by Matthias Vogelgesang
Return errcode != 0 if frame could not be decoded |
444 |
else { |
35
by Matthias Vogelgesang
Correctly implement 12 bit mode |
445 |
while (raw[base] != 0xAAAAAAA) { |
446 |
header = (payload_header_v5 *) &raw[base]; |
|
447 |
index = header->row_number * IPECAMERA_WIDTH + header->pixel_number; |
|
448 |
||
449 |
/* Skip header + two zero-filled words */
|
|
41
by Suren A. Chilingaryan
Black magick from Michele |
450 |
base += 2; |
451 |
||
452 |
if (header->magic != 0xc0) { |
|
453 |
pixel_buffer[index + 15*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base] >> 20); |
|
454 |
pixel_buffer[index + 13*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base] >> 8); |
|
39.1.6
by Matthias Vogelgesang
Fix 10 bit decoding |
455 |
pixel_buffer[index + 14*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (((0xff & raw[base]) << 4) | (raw[base+1] >> 28)); |
41
by Suren A. Chilingaryan
Black magick from Michele |
456 |
pixel_buffer[index + 12*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+1] >> 16); |
457 |
pixel_buffer[index + 10*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+1] >> 4); |
|
39.1.6
by Matthias Vogelgesang
Fix 10 bit decoding |
458 |
pixel_buffer[index + 8*IPECAMERA_PIXELS_PER_CHANNEL] = ((0x3 & raw[base+1]) << 8) | (raw[base+2] >> 24); |
41
by Suren A. Chilingaryan
Black magick from Michele |
459 |
pixel_buffer[index + 11*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+2] >> 12); |
460 |
pixel_buffer[index + 7*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & raw[base+2]; |
|
461 |
pixel_buffer[index + 9*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+3] >> 20); |
|
462 |
pixel_buffer[index + 6*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+3] >> 8); |
|
39.1.6
by Matthias Vogelgesang
Fix 10 bit decoding |
463 |
pixel_buffer[index + 5*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (((0xff & raw[base+3]) << 4) | (raw[base+4] >> 28)); |
41
by Suren A. Chilingaryan
Black magick from Michele |
464 |
pixel_buffer[index + 2*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+4] >> 16); |
465 |
pixel_buffer[index + 4*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+4] >> 4); |
|
39.1.6
by Matthias Vogelgesang
Fix 10 bit decoding |
466 |
pixel_buffer[index + 3*IPECAMERA_PIXELS_PER_CHANNEL] = ((0x3 & raw[base+4]) << 8) | (raw[base+5] >> 24); |
41
by Suren A. Chilingaryan
Black magick from Michele |
467 |
pixel_buffer[index + 0*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & (raw[base+5] >> 12); |
468 |
pixel_buffer[index + 1*IPECAMERA_PIXELS_PER_CHANNEL] = 0x3ff & raw[base+5]; |
|
469 |
}
|
|
470 |
||
471 |
base += 6; |
|
18
by Matthias Vogelgesang
Implement frame version 5 |
472 |
}
|
473 |
}
|
|
474 |
||
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
475 |
*offset += base; |
18
by Matthias Vogelgesang
Implement frame version 5 |
476 |
return 0; |
477 |
}
|
|
39.1.2
by Matthias Vogelgesang
Return errcode != 0 if frame could not be decoded |
478 |
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
479 |
/**
|
480 |
* \brief Deinterlace by interpolating between two rows
|
|
481 |
*
|
|
482 |
* \param in Input frame
|
|
483 |
* \param out Destination of interpolated frame
|
|
484 |
* \param width Width of frame in pixels
|
|
10
by Matthias Vogelgesang
Add documentation and split CMakeLists |
485 |
* \param height Height of frame in pixels
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
486 |
*/
|
9
by Matthias Vogelgesang
Rename to `ufodecode` |
487 |
void ufo_deinterlace_interpolate(const uint16_t *in, uint16_t *out, int width, int height) |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
488 |
{
|
489 |
const size_t row_size_bytes = width * sizeof(uint16_t); |
|
490 |
||
491 |
for (int row = 0; row < height; row++) { |
|
492 |
/* Copy one line */
|
|
493 |
memcpy(out, in + row*width, row_size_bytes); |
|
494 |
out += width; |
|
495 |
||
41
by Suren A. Chilingaryan
Black magick from Michele |
496 |
/* Interpolate between source row and row+1 */
|
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
497 |
for (int x = 0; x < width; x++) |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
498 |
out[x] = (int) (0.5 * in[row*width + x] + 0.5 * in[(row+1)*width + x]); |
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
499 |
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
500 |
out += width; |
501 |
}
|
|
502 |
||
503 |
/* Copy last row */
|
|
504 |
memcpy(out, in + width * (height - 1), row_size_bytes); |
|
505 |
}
|
|
506 |
||
507 |
/**
|
|
508 |
* \brief Deinterlace by "weaving" the rows of two frames
|
|
509 |
*
|
|
510 |
* \param in1 First frame
|
|
511 |
* \param in2 Second frame
|
|
512 |
* \param out Destination of weaved frame
|
|
513 |
* \param width Width of frame in pixels
|
|
10
by Matthias Vogelgesang
Add documentation and split CMakeLists |
514 |
* \param height Height of frame in pixels
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
515 |
*/
|
9
by Matthias Vogelgesang
Rename to `ufodecode` |
516 |
void ufo_deinterlace_weave(const uint16_t *in1, const uint16_t *in2, uint16_t *out, int width, int height) |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
517 |
{
|
518 |
const size_t row_size_bytes = width * sizeof(uint16_t); |
|
519 |
for (int row = 0; row < height; row++) { |
|
41
by Suren A. Chilingaryan
Black magick from Michele |
520 |
memcpy(out, in1 + row*width, row_size_bytes); |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
521 |
out += width; |
41
by Suren A. Chilingaryan
Black magick from Michele |
522 |
memcpy(out, in2 + row*width, row_size_bytes); |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
523 |
out += width; |
524 |
}
|
|
525 |
}
|
|
526 |
||
527 |
/**
|
|
11.1.6
by Suren A. Chilingaryan
Introduce thread-safe ufo_decoder_decode_frame function |
528 |
* \brief Decodes frame
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
529 |
*
|
11.1.6
by Suren A. Chilingaryan
Introduce thread-safe ufo_decoder_decode_frame function |
530 |
* This function tries to decode the supplied data
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
531 |
*
|
32
by Matthias Vogelgesang
Commit version 0.2 of libufodecode |
532 |
* \param decoder An UfoDecoder instance
|
11.1.6
by Suren A. Chilingaryan
Introduce thread-safe ufo_decoder_decode_frame function |
533 |
* \param raw Raw data stream
|
534 |
* \param num_bytes Size of data stream buffer in bytes
|
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
535 |
* \param pixels If pointer with NULL content is passed, a new buffer is
|
536 |
* allocated otherwise, this user-supplied buffer is used.
|
|
537 |
* \param frame_number Frame number as reported in the header
|
|
538 |
* \param time_stamp Time stamp of the frame as reported in the header
|
|
539 |
*
|
|
11.1.6
by Suren A. Chilingaryan
Introduce thread-safe ufo_decoder_decode_frame function |
540 |
* \return number of decoded bytes or 0 in case of error
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
541 |
*/
|
32
by Matthias Vogelgesang
Commit version 0.2 of libufodecode |
542 |
size_t ufo_decoder_decode_frame(UfoDecoder *decoder, |
41
by Suren A. Chilingaryan
Black magick from Michele |
543 |
uint32_t *raw, |
544 |
size_t num_bytes, |
|
545 |
uint16_t *pixels, |
|
32
by Matthias Vogelgesang
Commit version 0.2 of libufodecode |
546 |
UfoDecoderMeta *meta) |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
547 |
{
|
548 |
int err = 0; |
|
11.1.6
by Suren A. Chilingaryan
Introduce thread-safe ufo_decoder_decode_frame function |
549 |
size_t pos = 0; |
550 |
const size_t num_words = num_bytes / 4; |
|
551 |
||
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
552 |
if ((pixels == NULL) || (num_words < 16)) { |
553 |
#ifdef VERBOSE
|
|
554 |
if (num_words < 16) |
|
555 |
fprintf(stderr, "Not enough frame data, only %zu bytes supplied \n", num_bytes); |
|
556 |
#endif
|
|
11.1.6
by Suren A. Chilingaryan
Introduce thread-safe ufo_decoder_decode_frame function |
557 |
return 0; |
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
558 |
}
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
559 |
|
16
by Matthias Vogelgesang
Add version 4 frame decoding |
560 |
size_t rows_per_frame = decoder->height; |
561 |
const int version = (raw[pos+6] >> 24) & 0xF; |
|
562 |
||
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
563 |
#ifdef CHECKS
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
564 |
CHECK_VALUE(raw[pos++], 0x51111111); |
565 |
CHECK_VALUE(raw[pos++], 0x52222222); |
|
566 |
CHECK_VALUE(raw[pos++], 0x53333333); |
|
567 |
CHECK_VALUE(raw[pos++], 0x54444444); |
|
568 |
CHECK_VALUE(raw[pos++], 0x55555555); |
|
16
by Matthias Vogelgesang
Add version 4 frame decoding |
569 |
|
570 |
switch (version) { |
|
39.1.2
by Matthias Vogelgesang
Return errcode != 0 if frame could not be decoded |
571 |
case 0: |
572 |
CHECK_VALUE(raw[pos++], 0x56666666); |
|
573 |
CHECK_VALUE(raw[pos] >> 28, 0x5); |
|
574 |
meta->frame_number = raw[pos++] & 0xFFFFFFF; |
|
575 |
CHECK_VALUE(raw[pos] >> 28, 0x5); |
|
576 |
meta->time_stamp = raw[pos++] & 0xFFFFFFF; |
|
577 |
break; |
|
578 |
||
579 |
case 4: |
|
580 |
case 5: |
|
581 |
CHECK_VALUE(raw[pos] >> 28, 0x5); |
|
582 |
meta->cmosis_start_address = (raw[pos] >> 21) & 0x1FF; |
|
583 |
meta->n_skipped_rows = (raw[pos] >> 15) & 0x3F; |
|
584 |
meta->n_rows = rows_per_frame = raw[pos] & 0x7FF; |
|
585 |
pos++; |
|
586 |
||
587 |
meta->frame_number = raw[pos++] & 0x1FFFFFF; |
|
588 |
CHECK_VALUE(raw[pos] >> 28, 0x5); |
|
589 |
meta->time_stamp = raw[pos] & 0xFFFFFF; |
|
590 |
meta->output_mode = (raw[pos] >> 24) & 0x3; |
|
591 |
meta->adc_resolution = (raw[pos] >> 26) & 0x3; |
|
592 |
pos++; |
|
593 |
||
39.1.3
by Matthias Vogelgesang
Output version number if wrong |
594 |
if ((meta->output_mode != IPECAMERA_MODE_4_CHAN_IO) && (meta->output_mode != IPECAMERA_MODE_16_CHAN_IO)) { |
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
595 |
# ifdef VERBOSE
|
39.1.5
by Matthias Vogelgesang
Add --print-num-rows and fix debug output |
596 |
fprintf(stderr, "Output mode 0x%x is not supported\n", meta->output_mode); |
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
597 |
# endif
|
598 |
return 0; |
|
39.1.2
by Matthias Vogelgesang
Return errcode != 0 if frame could not be decoded |
599 |
}
|
600 |
break; |
|
41
by Suren A. Chilingaryan
Black magick from Michele |
601 |
|
39.1.2
by Matthias Vogelgesang
Return errcode != 0 if frame could not be decoded |
602 |
default: |
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
603 |
# ifdef VERBOSE
|
39.1.3
by Matthias Vogelgesang
Output version number if wrong |
604 |
fprintf(stderr, "Unsupported data format version %i detected\n", version); |
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
605 |
# endif
|
39.1.2
by Matthias Vogelgesang
Return errcode != 0 if frame could not be decoded |
606 |
return 0; |
16
by Matthias Vogelgesang
Add version 4 frame decoding |
607 |
}
|
608 |
||
41
by Suren A. Chilingaryan
Black magick from Michele |
609 |
if (err) |
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
610 |
return 0; |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
611 |
#else
|
16
by Matthias Vogelgesang
Add version 4 frame decoding |
612 |
switch (version) { |
39.1.2
by Matthias Vogelgesang
Return errcode != 0 if frame could not be decoded |
613 |
case 0: |
614 |
meta->frame_number = raw[pos + 6] & 0xFFFFFFF; |
|
615 |
meta->time_stamp = raw[pos + 7] & 0xFFFFFFF; |
|
616 |
break; |
|
617 |
case 4: |
|
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
618 |
meta->n_rows = rows_per_frame = raw[pos + 5] & 0x7FF; |
39.1.2
by Matthias Vogelgesang
Return errcode != 0 if frame could not be decoded |
619 |
case 5: |
620 |
meta->frame_number = raw[pos + 6] & 0x1FFFFFF; |
|
621 |
meta->time_stamp = raw[pos + 7] & 0xFFFFFF; |
|
622 |
meta->output_mode = (raw[pos + 7] >> 24) & 0x3; |
|
623 |
meta->adc_resolution = (raw[pos + 7] >> 26) & 0x3; |
|
41
by Suren A. Chilingaryan
Black magick from Michele |
624 |
|
39.1.2
by Matthias Vogelgesang
Return errcode != 0 if frame could not be decoded |
625 |
break; |
626 |
default: |
|
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
627 |
# ifdef VERBOSE
|
39.1.2
by Matthias Vogelgesang
Return errcode != 0 if frame could not be decoded |
628 |
fprintf(stderr, "Unsupported data format detected\n"); |
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
629 |
# endif
|
39.1.2
by Matthias Vogelgesang
Return errcode != 0 if frame could not be decoded |
630 |
return 0; |
16
by Matthias Vogelgesang
Add version 4 frame decoding |
631 |
}
|
632 |
||
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
633 |
pos += 8; |
634 |
#endif
|
|
635 |
||
16
by Matthias Vogelgesang
Add version 4 frame decoding |
636 |
switch (version) { |
39.1.2
by Matthias Vogelgesang
Return errcode != 0 if frame could not be decoded |
637 |
case 0: |
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
638 |
err = ufo_decode_frame_channels_v0(decoder, pixels, raw + pos, num_words - pos - 8, &pos); |
39.1.2
by Matthias Vogelgesang
Return errcode != 0 if frame could not be decoded |
639 |
break; |
640 |
case 4: |
|
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
641 |
err = ufo_decode_frame_channels_v4(decoder, pixels, raw + pos, num_words - pos - 8, rows_per_frame, &pos); |
39.1.2
by Matthias Vogelgesang
Return errcode != 0 if frame could not be decoded |
642 |
break; |
643 |
case 5: |
|
45
by Suren A. Chilingaryan
Few bug fixes and more coherent debug flags |
644 |
err = ufo_decode_frame_channels_v5(decoder, pixels, raw + pos, rows_per_frame, &pos, meta->output_mode); |
39.1.2
by Matthias Vogelgesang
Return errcode != 0 if frame could not be decoded |
645 |
break; |
646 |
default: |
|
647 |
break; |
|
16
by Matthias Vogelgesang
Add version 4 frame decoding |
648 |
}
|
649 |
||
24
by Matthias Vogelgesang
Decode frames after encountering corrupted ones |
650 |
if (err) |
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
651 |
return 0; |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
652 |
|
11.1.7
by Suren A. Chilingaryan
Introduce quiete checking of frame consistencies |
653 |
#ifdef CHECKS
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
654 |
CHECK_VALUE(raw[pos++], 0x0AAAAAAA); |
32
by Matthias Vogelgesang
Commit version 0.2 of libufodecode |
655 |
|
656 |
meta->status1.bits = raw[pos++]; |
|
657 |
meta->status2.bits = raw[pos++]; |
|
658 |
meta->status3.bits = raw[pos++]; |
|
19
by Matthias Vogelgesang
Adapt tail |
659 |
pos++; |
660 |
pos++; |
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
661 |
CHECK_VALUE(raw[pos++], 0x00000000); |
662 |
CHECK_VALUE(raw[pos++], 0x01111111); |
|
11.1.6
by Suren A. Chilingaryan
Introduce thread-safe ufo_decoder_decode_frame function |
663 |
|
41
by Suren A. Chilingaryan
Black magick from Michele |
664 |
if (err) |
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
665 |
return 0; |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
666 |
#else
|
667 |
pos += 8; |
|
668 |
#endif
|
|
669 |
||
11.1.6
by Suren A. Chilingaryan
Introduce thread-safe ufo_decoder_decode_frame function |
670 |
return pos; |
671 |
}
|
|
672 |
||
673 |
/**
|
|
674 |
* \brief Iterate and decode next frame
|
|
675 |
*
|
|
676 |
* This function tries to decode the next frame in the currently set raw data
|
|
41
by Suren A. Chilingaryan
Black magick from Michele |
677 |
* stream.
|
11.1.6
by Suren A. Chilingaryan
Introduce thread-safe ufo_decoder_decode_frame function |
678 |
*
|
32
by Matthias Vogelgesang
Commit version 0.2 of libufodecode |
679 |
* \param decoder An UfoDecoder instance
|
11.1.6
by Suren A. Chilingaryan
Introduce thread-safe ufo_decoder_decode_frame function |
680 |
* \param pixels If pointer with NULL content is passed, a new buffer is
|
681 |
* allocated otherwise, this user-supplied buffer is used.
|
|
16
by Matthias Vogelgesang
Add version 4 frame decoding |
682 |
* \param num_rows Number of actual decoded rows
|
11.1.6
by Suren A. Chilingaryan
Introduce thread-safe ufo_decoder_decode_frame function |
683 |
* \param frame_number Frame number as reported in the header
|
684 |
* \param time_stamp Time stamp of the frame as reported in the header
|
|
685 |
*
|
|
24
by Matthias Vogelgesang
Decode frames after encountering corrupted ones |
686 |
* \return 0 in case of no error, EIO if end of stream was reached, ENOMEM if
|
11.1.6
by Suren A. Chilingaryan
Introduce thread-safe ufo_decoder_decode_frame function |
687 |
* NULL was passed but no memory could be allocated, EILSEQ if data stream is
|
688 |
* corrupt and EFAULT if pixels is a NULL-pointer.
|
|
689 |
*/
|
|
41
by Suren A. Chilingaryan
Black magick from Michele |
690 |
int ufo_decoder_get_next_frame(UfoDecoder *decoder, |
691 |
uint16_t **pixels, |
|
32
by Matthias Vogelgesang
Commit version 0.2 of libufodecode |
692 |
UfoDecoderMeta *meta) |
11.1.6
by Suren A. Chilingaryan
Introduce thread-safe ufo_decoder_decode_frame function |
693 |
{
|
694 |
uint32_t *raw = decoder->raw; |
|
695 |
size_t pos = decoder->current_pos; |
|
696 |
size_t advance; |
|
697 |
const size_t num_words = decoder->num_bytes / 4; |
|
698 |
||
699 |
if (pixels == NULL) |
|
700 |
return 0; |
|
701 |
||
702 |
if (pos >= num_words) |
|
41
by Suren A. Chilingaryan
Black magick from Michele |
703 |
return EIO; |
11.1.6
by Suren A. Chilingaryan
Introduce thread-safe ufo_decoder_decode_frame function |
704 |
|
705 |
if (num_words < 16) |
|
706 |
return EILSEQ; |
|
707 |
||
708 |
if (*pixels == NULL) { |
|
709 |
*pixels = (uint16_t *) malloc(IPECAMERA_WIDTH * decoder->height * sizeof(uint16_t)); |
|
710 |
if (*pixels == NULL) |
|
711 |
return ENOMEM; |
|
712 |
}
|
|
14
by Matthias Vogelgesang
Fix: formatting (whitespace, indentation) |
713 |
|
24
by Matthias Vogelgesang
Decode frames after encountering corrupted ones |
714 |
while ((pos < num_words) && (raw[pos] != 0x51111111)) |
15
by Matthias Vogelgesang
Fix wrong address access and skip till first valid header |
715 |
pos++; |
716 |
||
32
by Matthias Vogelgesang
Commit version 0.2 of libufodecode |
717 |
advance = ufo_decoder_decode_frame(decoder, raw + pos, decoder->num_bytes - pos, *pixels, meta); |
16
by Matthias Vogelgesang
Add version 4 frame decoding |
718 |
|
24
by Matthias Vogelgesang
Decode frames after encountering corrupted ones |
719 |
/*
|
720 |
* On error, advance is 0 but we have to advance at least a bit to net get
|
|
721 |
* caught in an infinite loop when trying to decode subsequent frames.
|
|
722 |
*/
|
|
723 |
pos += advance == 0 ? 1 : advance; |
|
11.1.6
by Suren A. Chilingaryan
Introduce thread-safe ufo_decoder_decode_frame function |
724 |
|
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
725 |
/* if bytes left and we see fill bytes, skip them */
|
11.1.1
by Suren A. Chilingaryan
Add width support and few consistency checks |
726 |
if (((pos + 2) < num_words) && ((raw[pos] == 0x0) && (raw[pos+1] == 0x1111111))) { |
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
727 |
pos += 2; |
728 |
while ((pos < num_words) && ((raw[pos] == 0x89abcdef) || (raw[pos] == 0x1234567))) |
|
729 |
pos++; |
|
730 |
}
|
|
731 |
||
732 |
decoder->current_pos = pos; |
|
24
by Matthias Vogelgesang
Decode frames after encountering corrupted ones |
733 |
|
734 |
if (!advance) |
|
735 |
return EILSEQ; |
|
736 |
||
4
by Matthias Vogelgesang
Make ipedec a lib and executable |
737 |
return 0; |
738 |
}
|
|
739 |