1
#define _IPECAMERA_IMAGE_C
13
#include <ufodecode.h>
22
// DS: Currently, on event_id overflow we are assuming the buffer is lost
23
static int ipecamera_resolve_event_id(ipecamera_t *ctx, pcilib_event_id_t evid) {
24
pcilib_event_id_t diff;
26
if (evid > ctx->event_id) {
27
diff = (((pcilib_event_id_t)-1) - ctx->event_id) + evid;
28
if (diff >= ctx->buffer_size) return -1;
30
diff = ctx->event_id - evid;
31
if (diff >= ctx->buffer_size) return -1;
34
// DS: Request buffer_size to be power of 2 and replace to shifts (just recompute in set_buffer_size)
35
return (evid - 1) % ctx->buffer_size;
38
inline static int ipecamera_decode_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) {
43
int buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
44
if (buf_ptr < 0) return PCILIB_ERROR_TIMEOUT;
46
if (ctx->frame[buf_ptr].event.image_ready) return 0;
48
if (ctx->frame[buf_ptr].event.info.flags&PCILIB_EVENT_INFO_FLAG_BROKEN) {
49
ctx->frame[buf_ptr].event.image_broken = 1;
50
err = PCILIB_ERROR_INVALID_DATA;
55
pixels = ctx->image + buf_ptr * ctx->image_size;
56
memset(ctx->cmask + ctx->buffer_pos * ctx->dim.height, 0, ctx->dim.height * sizeof(ipecamera_change_mask_t));
57
err = ufo_decoder_decode_frame(ctx->ipedec, ctx->buffer + buf_ptr * ctx->padded_size, ctx->raw_size, pixels, &tmp, &tmp, ctx->cmask + ctx->buffer_pos * ctx->dim.height);
59
ctx->frame[buf_ptr].event.image_broken = 1;
60
err = PCILIB_ERROR_FAILED;
64
ctx->frame[buf_ptr].event.image_broken = 0;
67
ctx->frame[buf_ptr].event.image_ready = 1;
69
if (ipecamera_resolve_event_id(ctx, event_id) < 0) {
70
ctx->frame[buf_ptr].event.image_ready = 0;
71
return PCILIB_ERROR_TIMEOUT;
77
static int ipecamera_get_next_buffer_to_process(ipecamera_t *ctx, pcilib_event_id_t *evid) {
80
if (ctx->preproc_id == ctx->event_id) return -1;
83
pthread_mutex_lock(&ctx->preproc_mutex);
85
if (ctx->preproc_id == ctx->event_id) {
87
pthread_mutex_unlock(&ctx->preproc_mutex);
91
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;
93
res = ctx->preproc_id%ctx->buffer_size;
95
if (pthread_rwlock_trywrlock(&ctx->frame[res].mutex)) {
96
pthread_mutex_unlock(&ctx->preproc_mutex);
100
*evid = ++ctx->preproc_id;
103
pthread_mutex_unlock(&ctx->preproc_mutex);
109
void *ipecamera_preproc_thread(void *user) {
111
pcilib_event_id_t evid;
113
ipecamera_preprocessor_t *preproc = (ipecamera_preprocessor_t*)user;
114
ipecamera_t *ctx = preproc->ipecamera;
116
while (ctx->run_preprocessors) {
117
buf_ptr = ipecamera_get_next_buffer_to_process(ctx, &evid);
119
usleep(IPECAMERA_NOFRAME_PREPROC_SLEEP);
123
ipecamera_decode_frame(ctx, evid);
125
pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
131
static int ipecamera_get_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) {
133
int buf_ptr = (event_id - 1) % ctx->buffer_size;
136
pthread_rwlock_rdlock(&ctx->frame[buf_ptr].mutex);
138
err = ipecamera_decode_frame(ctx, event_id);
141
pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
149
while (!ctx->frame[buf_ptr].event.image_ready) {
150
usleep(IPECAMERA_NOFRAME_PREPROC_SLEEP);
152
buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
153
if (buf_ptr < 0) return PCILIB_ERROR_OVERWRITTEN;
156
pthread_rwlock_rdlock(&ctx->frame[buf_ptr].mutex);
158
buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
159
if ((buf_ptr < 0)||(!ctx->frame[buf_ptr].event.image_ready)) {
160
pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
161
return PCILIB_ERROR_OVERWRITTEN;
169
We will lock the data for non-raw data to prevent ocasional overwritting. The
170
raw data will be overwritten by the reader thread anyway and we can't do
171
anything to prevent it for performance reasons.
173
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) {
177
ipecamera_t *ctx = (ipecamera_t*)vctx;
182
pcilib_error("IPECamera imaging is not initialized");
183
return PCILIB_ERROR_NOTINITIALIZED;
186
buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
187
if (buf_ptr < 0) return PCILIB_ERROR_OVERWRITTEN;
189
switch ((ipecamera_data_type_t)data_type) {
190
case IPECAMERA_RAW_DATA:
191
raw_size = ctx->frame[buf_ptr].event.raw_size;
193
if ((!size)||(*size < raw_size)) return PCILIB_ERROR_TOOBIG;
194
memcpy(data, ctx->buffer + buf_ptr * ctx->padded_size, raw_size);
195
if (ipecamera_resolve_event_id(ctx, event_id) < 0) return PCILIB_ERROR_OVERWRITTEN;
199
if (size) *size = raw_size;
200
*ret = ctx->buffer + buf_ptr * ctx->padded_size;
202
case IPECAMERA_IMAGE_DATA:
203
err = ipecamera_get_frame(ctx, event_id);
207
if ((!size)||(*size < ctx->image_size * sizeof(ipecamera_pixel_t))) return PCILIB_ERROR_TOOBIG;
208
memcpy(data, ctx->image + buf_ptr * ctx->image_size, ctx->image_size * sizeof(ipecamera_pixel_t));
209
pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
210
*size = ctx->image_size * sizeof(ipecamera_pixel_t);
214
if (size) *size = ctx->image_size * sizeof(ipecamera_pixel_t);
215
*ret = ctx->image + buf_ptr * ctx->image_size;
217
case IPECAMERA_CHANGE_MASK:
218
err = ipecamera_get_frame(ctx, event_id);
222
if ((!size)||(*size < ctx->dim.height * sizeof(ipecamera_change_mask_t))) return PCILIB_ERROR_TOOBIG;
223
memcpy(data, ctx->image + buf_ptr * ctx->dim.height, ctx->dim.height * sizeof(ipecamera_change_mask_t));
224
pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
225
*size = ctx->dim.height * sizeof(ipecamera_change_mask_t);
229
if (size) *size = ctx->dim.height * sizeof(ipecamera_change_mask_t);
230
*ret = ctx->cmask + buf_ptr * ctx->dim.height;
232
case IPECAMERA_DIMENSIONS:
233
if (size) *size = sizeof(ipecamera_image_dimensions_t);
234
ret = (void*)&ctx->dim;
236
case IPECAMERA_IMAGE_REGION:
237
case IPECAMERA_PACKED_IMAGE:
238
// Shall we return complete image or only changed parts?
239
case IPECAMERA_PACKED_LINE:
240
case IPECAMERA_PACKED_PAYLOAD:
241
pcilib_error("Support for data type (%li) is not implemented yet", data_type);
242
return PCILIB_ERROR_NOTSUPPORTED;
244
pcilib_error("Unknown data type (%li) is requested", data_type);
245
return PCILIB_ERROR_INVALID_REQUEST;
251
We will unlock non-raw data and check if the raw data is not overwritten yet
253
int ipecamera_return(pcilib_context_t *vctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, void *data) {
254
ipecamera_t *ctx = (ipecamera_t*)vctx;
257
pcilib_error("IPECamera imaging is not initialized");
258
return PCILIB_ERROR_NOTINITIALIZED;
262
if ((ipecamera_data_type_t)data_type == IPECAMERA_RAW_DATA) {
263
if (ipecamera_resolve_event_id(ctx, event_id) < 0) return PCILIB_ERROR_OVERWRITTEN;
265
int buf_ptr = (event_id - 1) % ctx->buffer_size;
266
pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);