12
#include <ufodecode.h>
21
// DS: Currently, on event_id overflow we are assuming the buffer is lost
22
static int ipecamera_resolve_event_id(ipecamera_t *ctx, pcilib_event_id_t evid) {
23
pcilib_event_id_t diff;
25
if (evid > ctx->event_id) {
26
diff = (((pcilib_event_id_t)-1) - ctx->event_id) + evid;
27
if (diff >= ctx->buffer_size) return -1;
29
diff = ctx->event_id - evid;
30
if (diff >= ctx->buffer_size) return -1;
33
// DS: Request buffer_size to be power of 2 and replace to shifts (just recompute in set_buffer_size)
34
return (evid - 1) % ctx->buffer_size;
37
inline static int ipecamera_decode_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) {
42
int buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
43
if (buf_ptr < 0) return PCILIB_ERROR_TIMEOUT;
45
if (ctx->frame[buf_ptr].event.image_ready) return 0;
47
if (ctx->frame[buf_ptr].event.info.flags&PCILIB_EVENT_INFO_FLAG_BROKEN) {
48
err = PCILIB_ERROR_INVALID_DATA;
49
ctx->frame[buf_ptr].event.image_broken = err;
54
pixels = ctx->image + buf_ptr * ctx->image_size;
55
memset(ctx->cmask + ctx->buffer_pos * ctx->dim.height, 0, ctx->dim.height * sizeof(ipecamera_change_mask_t));
56
res = ufo_decoder_decode_frame(ctx->ipedec, ctx->buffer + buf_ptr * ctx->padded_size, ctx->raw_size, pixels, &ctx->frame[buf_ptr].event.meta);
58
err = PCILIB_ERROR_FAILED;
59
ctx->frame[buf_ptr].event.image_broken = err;
63
ctx->frame[buf_ptr].event.image_broken = 0;
66
ctx->frame[buf_ptr].event.image_ready = 1;
68
if (ipecamera_resolve_event_id(ctx, event_id) < 0) {
69
ctx->frame[buf_ptr].event.image_ready = 0;
70
return PCILIB_ERROR_TIMEOUT;
76
static int ipecamera_get_next_buffer_to_process(ipecamera_t *ctx, pcilib_event_id_t *evid) {
79
if (ctx->preproc_id == ctx->event_id) return -1;
82
pthread_mutex_lock(&ctx->preproc_mutex);
84
if (ctx->preproc_id == ctx->event_id) {
86
pthread_mutex_unlock(&ctx->preproc_mutex);
90
if ((ctx->event_id - ctx->preproc_id) > (ctx->buffer_size - IPECAMERA_RESERVE_BUFFERS)) ctx->preproc_id = ctx->event_id - (ctx->buffer_size - 1 - IPECAMERA_RESERVE_BUFFERS - 1);
92
res = ctx->preproc_id%ctx->buffer_size;
94
if (pthread_rwlock_trywrlock(&ctx->frame[res].mutex)) {
95
pthread_mutex_unlock(&ctx->preproc_mutex);
99
*evid = ++ctx->preproc_id;
102
pthread_mutex_unlock(&ctx->preproc_mutex);
108
void *ipecamera_preproc_thread(void *user) {
110
pcilib_event_id_t evid;
112
ipecamera_preprocessor_t *preproc = (ipecamera_preprocessor_t*)user;
113
ipecamera_t *ctx = preproc->ipecamera;
115
while (ctx->run_preprocessors) {
116
buf_ptr = ipecamera_get_next_buffer_to_process(ctx, &evid);
118
usleep(IPECAMERA_NOFRAME_PREPROC_SLEEP);
122
ipecamera_decode_frame(ctx, evid);
124
pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
130
static int ipecamera_get_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) {
132
int buf_ptr = (event_id - 1) % ctx->buffer_size;
135
if (ctx->frame[buf_ptr].event.image_broken)
136
return ctx->frame[buf_ptr].event.image_broken;
138
pthread_rwlock_rdlock(&ctx->frame[buf_ptr].mutex);
140
err = ipecamera_decode_frame(ctx, event_id);
143
pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
151
while (!ctx->frame[buf_ptr].event.image_ready) {
152
usleep(IPECAMERA_NOFRAME_PREPROC_SLEEP);
154
buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
155
if (buf_ptr < 0) return PCILIB_ERROR_OVERWRITTEN;
158
pthread_rwlock_rdlock(&ctx->frame[buf_ptr].mutex);
160
buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
161
if ((buf_ptr < 0)||(!ctx->frame[buf_ptr].event.image_ready)) {
162
pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
163
return PCILIB_ERROR_OVERWRITTEN;
171
We will lock the data for non-raw data to prevent ocasional overwritting. The
172
raw data will be overwritten by the reader thread anyway and we can't do
173
anything to prevent it for performance reasons.
175
int ipecamera_get(pcilib_context_t *vctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, size_t arg_size, void *arg, size_t *size, void **ret) {
179
ipecamera_t *ctx = (ipecamera_t*)vctx;
184
pcilib_error("IPECamera imaging is not initialized");
185
return PCILIB_ERROR_NOTINITIALIZED;
188
buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
189
if (buf_ptr < 0) return PCILIB_ERROR_OVERWRITTEN;
191
switch ((ipecamera_data_type_t)data_type) {
192
case IPECAMERA_RAW_DATA:
193
raw_size = ctx->frame[buf_ptr].event.raw_size;
195
if ((!size)||(*size < raw_size)) return PCILIB_ERROR_TOOBIG;
196
memcpy(data, ctx->buffer + buf_ptr * ctx->padded_size, raw_size);
197
if (ipecamera_resolve_event_id(ctx, event_id) < 0) return PCILIB_ERROR_OVERWRITTEN;
201
if (size) *size = raw_size;
202
*ret = ctx->buffer + buf_ptr * ctx->padded_size;
204
case IPECAMERA_IMAGE_DATA:
205
err = ipecamera_get_frame(ctx, event_id);
209
if ((!size)||(*size < ctx->image_size * sizeof(ipecamera_pixel_t))) return PCILIB_ERROR_TOOBIG;
210
memcpy(data, ctx->image + buf_ptr * ctx->image_size, ctx->image_size * sizeof(ipecamera_pixel_t));
211
pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
212
*size = ctx->image_size * sizeof(ipecamera_pixel_t);
216
if (size) *size = ctx->image_size * sizeof(ipecamera_pixel_t);
217
*ret = ctx->image + buf_ptr * ctx->image_size;
219
case IPECAMERA_CHANGE_MASK:
220
err = ipecamera_get_frame(ctx, event_id);
224
if ((!size)||(*size < ctx->dim.height * sizeof(ipecamera_change_mask_t))) return PCILIB_ERROR_TOOBIG;
225
memcpy(data, ctx->image + buf_ptr * ctx->dim.height, ctx->dim.height * sizeof(ipecamera_change_mask_t));
226
pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
227
*size = ctx->dim.height * sizeof(ipecamera_change_mask_t);
231
if (size) *size = ctx->dim.height * sizeof(ipecamera_change_mask_t);
232
*ret = ctx->cmask + buf_ptr * ctx->dim.height;
234
case IPECAMERA_DIMENSIONS:
235
if (size) *size = sizeof(ipecamera_image_dimensions_t);
236
ret = (void*)&ctx->dim;
238
case IPECAMERA_IMAGE_REGION:
239
case IPECAMERA_PACKED_IMAGE:
240
// Shall we return complete image or only changed parts?
241
case IPECAMERA_PACKED_LINE:
242
case IPECAMERA_PACKED_PAYLOAD:
243
pcilib_error("Support for data type (%li) is not implemented yet", data_type);
244
return PCILIB_ERROR_NOTSUPPORTED;
246
pcilib_error("Unknown data type (%li) is requested", data_type);
247
return PCILIB_ERROR_INVALID_REQUEST;
253
We will unlock non-raw data and check if the raw data is not overwritten yet
255
int ipecamera_return(pcilib_context_t *vctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, void *data) {
256
ipecamera_t *ctx = (ipecamera_t*)vctx;
259
pcilib_error("IPECamera imaging is not initialized");
260
return PCILIB_ERROR_NOTINITIALIZED;
264
if ((ipecamera_data_type_t)data_type == IPECAMERA_RAW_DATA) {
265
if (ipecamera_resolve_event_id(ctx, event_id) < 0) return PCILIB_ERROR_OVERWRITTEN;
267
int buf_ptr = (event_id - 1) % ctx->buffer_size;
268
pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);