/alps/pcitool

To get this branch, use:
bzr branch http://suren.me/webbzr/alps/pcitool

« back to all changes in this revision

Viewing changes to ipecamera/data.c

  • Committer: Suren A. Chilingaryan
  • Date: 2015-04-20 20:01:04 UTC
  • Revision ID: csa@suren.me-20150420200104-b5xny65io8lvoz3w
Big redign of model structures

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#define _BSD_SOURCE
2
 
#define _GNU_SOURCE
3
 
 
4
 
#include <stdio.h>
5
 
#include <stdlib.h>
6
 
#include <unistd.h>
7
 
#include <string.h>
8
 
#include <sys/time.h>
9
 
#include <pthread.h>
10
 
#include <assert.h>
11
 
 
12
 
#include <ufodecode.h>
13
 
 
14
 
#include "../tools.h"
15
 
#include "../error.h"
16
 
 
17
 
#include "pcilib.h"
18
 
#include "private.h"
19
 
#include "data.h"
20
 
 
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;
24
 
 
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;
28
 
    } else {
29
 
        diff = ctx->event_id - evid;
30
 
        if (diff >= ctx->buffer_size) return -1;
31
 
    }
32
 
    
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;
35
 
}
36
 
 
37
 
inline static int ipecamera_decode_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) {
38
 
    int err = 0;
39
 
    size_t res;
40
 
    uint16_t *pixels;
41
 
    
42
 
    int buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
43
 
    if (buf_ptr < 0) return PCILIB_ERROR_TIMEOUT;
44
 
    
45
 
    if (ctx->frame[buf_ptr].event.image_ready) return 0;
46
 
    
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;
50
 
        goto ready;
51
 
    }
52
 
        
53
 
                
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);
57
 
    if (!res) {
58
 
        err = PCILIB_ERROR_FAILED;
59
 
        ctx->frame[buf_ptr].event.image_broken = err;
60
 
        goto ready;
61
 
    }
62
 
            
63
 
    ctx->frame[buf_ptr].event.image_broken = 0;
64
 
 
65
 
ready:
66
 
    ctx->frame[buf_ptr].event.image_ready = 1;
67
 
 
68
 
    if (ipecamera_resolve_event_id(ctx, event_id) < 0) {
69
 
        ctx->frame[buf_ptr].event.image_ready = 0;
70
 
        return PCILIB_ERROR_TIMEOUT;
71
 
    }
72
 
    
73
 
    return err;
74
 
}
75
 
 
76
 
static int ipecamera_get_next_buffer_to_process(ipecamera_t *ctx, pcilib_event_id_t *evid) {
77
 
    int res;
78
 
 
79
 
    if (ctx->preproc_id == ctx->event_id) return -1;
80
 
    
81
 
    if (ctx->preproc) 
82
 
        pthread_mutex_lock(&ctx->preproc_mutex);
83
 
        
84
 
    if (ctx->preproc_id == ctx->event_id) {
85
 
        if (ctx->preproc)
86
 
            pthread_mutex_unlock(&ctx->preproc_mutex);
87
 
        return -1;
88
 
    }
89
 
 
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);
91
 
 
92
 
    res = ctx->preproc_id%ctx->buffer_size;
93
 
 
94
 
    if (pthread_rwlock_trywrlock(&ctx->frame[res].mutex)) {
95
 
        pthread_mutex_unlock(&ctx->preproc_mutex);
96
 
        return -1;
97
 
    }
98
 
    
99
 
    *evid = ++ctx->preproc_id;
100
 
 
101
 
    if (ctx->preproc)
102
 
        pthread_mutex_unlock(&ctx->preproc_mutex);
103
 
 
104
 
    return res;
105
 
}
106
 
 
107
 
 
108
 
void *ipecamera_preproc_thread(void *user) {
109
 
    int buf_ptr;
110
 
    pcilib_event_id_t evid;
111
 
    
112
 
    ipecamera_preprocessor_t *preproc = (ipecamera_preprocessor_t*)user;
113
 
    ipecamera_t *ctx = preproc->ipecamera;
114
 
    
115
 
    while (ctx->run_preprocessors) {
116
 
        buf_ptr = ipecamera_get_next_buffer_to_process(ctx, &evid);
117
 
        if (buf_ptr < 0) {
118
 
            usleep(IPECAMERA_NOFRAME_PREPROC_SLEEP);
119
 
            continue;
120
 
        }
121
 
        
122
 
        ipecamera_decode_frame(ctx, evid);
123
 
        
124
 
        pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
125
 
    }
126
 
 
127
 
    return NULL;
128
 
}
129
 
 
130
 
static int ipecamera_get_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) {
131
 
    int err;
132
 
    int buf_ptr = (event_id - 1) % ctx->buffer_size;
133
 
    
134
 
    if (ctx->preproc) { 
135
 
        if (ctx->frame[buf_ptr].event.image_broken)
136
 
                return ctx->frame[buf_ptr].event.image_broken;
137
 
    } else {
138
 
        pthread_rwlock_rdlock(&ctx->frame[buf_ptr].mutex);
139
 
 
140
 
        err = ipecamera_decode_frame(ctx, event_id);
141
 
 
142
 
        if (err) {
143
 
            pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
144
 
            return err;
145
 
        }
146
 
        
147
 
        return 0;
148
 
    }
149
 
    
150
 
    
151
 
    while (!ctx->frame[buf_ptr].event.image_ready) {
152
 
        usleep(IPECAMERA_NOFRAME_PREPROC_SLEEP);
153
 
 
154
 
        buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
155
 
        if (buf_ptr < 0) return PCILIB_ERROR_OVERWRITTEN;
156
 
    }   
157
 
 
158
 
    pthread_rwlock_rdlock(&ctx->frame[buf_ptr].mutex);
159
 
    
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;
164
 
    }
165
 
    
166
 
    return 0;    
167
 
}
168
 
 
169
 
 
170
 
/*
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.
174
 
*/
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) {
176
 
    int err;
177
 
    int buf_ptr;
178
 
    size_t raw_size;
179
 
    ipecamera_t *ctx = (ipecamera_t*)vctx;
180
 
 
181
 
    void *data = *ret;
182
 
 
183
 
    if (!ctx) {
184
 
        pcilib_error("IPECamera imaging is not initialized");
185
 
        return PCILIB_ERROR_NOTINITIALIZED;
186
 
    }
187
 
 
188
 
    buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
189
 
    if (buf_ptr < 0) return PCILIB_ERROR_OVERWRITTEN;
190
 
    
191
 
    switch ((ipecamera_data_type_t)data_type) {
192
 
        case IPECAMERA_RAW_DATA:
193
 
            raw_size = ctx->frame[buf_ptr].event.raw_size;
194
 
            if (data) {
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;
198
 
                *size = raw_size;
199
 
                return 0;
200
 
            }
201
 
            if (size) *size = raw_size;
202
 
            *ret = ctx->buffer + buf_ptr * ctx->padded_size;
203
 
            return 0;
204
 
        case IPECAMERA_IMAGE_DATA:
205
 
            err = ipecamera_get_frame(ctx, event_id);
206
 
            if (err) return err;
207
 
 
208
 
            if (data) {
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);
213
 
                return 0;
214
 
            }
215
 
        
216
 
            if (size) *size = ctx->image_size * sizeof(ipecamera_pixel_t);
217
 
            *ret = ctx->image + buf_ptr * ctx->image_size;
218
 
            return 0;
219
 
        case IPECAMERA_CHANGE_MASK:
220
 
            err = ipecamera_get_frame(ctx, event_id);
221
 
            if (err) return err;
222
 
 
223
 
            if (data) {
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);
228
 
                return 0;
229
 
            }
230
 
 
231
 
            if (size) *size = ctx->dim.height * sizeof(ipecamera_change_mask_t);
232
 
            *ret = ctx->cmask + buf_ptr * ctx->dim.height;
233
 
            return 0;
234
 
        case IPECAMERA_DIMENSIONS:
235
 
            if (size) *size = sizeof(ipecamera_image_dimensions_t);
236
 
            ret = (void*)&ctx->dim;
237
 
            return 0;
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;
245
 
        default:
246
 
            pcilib_error("Unknown data type (%li) is requested", data_type);
247
 
            return PCILIB_ERROR_INVALID_REQUEST;
248
 
    }
249
 
}
250
 
 
251
 
 
252
 
/*
253
 
 We will unlock non-raw data and check if the raw data is not overwritten yet
254
 
*/
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;
257
 
 
258
 
    if (!ctx) {
259
 
        pcilib_error("IPECamera imaging is not initialized");
260
 
        return PCILIB_ERROR_NOTINITIALIZED;
261
 
 
262
 
    }
263
 
 
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;
266
 
    } else {
267
 
        int buf_ptr = (event_id - 1) % ctx->buffer_size;
268
 
        pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
269
 
    }
270
 
 
271
 
    return 0;
272
 
}