/alps/ipecamera

To get this branch, use:
bzr branch http://darksoft.org/webbzr/alps/ipecamera
277 by Suren A. Chilingaryan
Build RPM
1
#define _DEFAULT_SOURCE
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
2
#define _BSD_SOURCE
3
#define _GNU_SOURCE
4
5
#include <stdio.h>
6
#include <stdlib.h>
7
#include <unistd.h>
8
#include <string.h>
9
#include <sys/time.h>
10
#include <pthread.h>
11
#include <assert.h>
12
13
#include <ufodecode.h>
14
245 by Suren A. Chilingaryan
First stand-alone ipecamera implementation
15
#include <pcilib.h>
16
#include <pcilib/tools.h>
17
#include <pcilib/error.h>
276 by Suren A. Chilingaryan
Update to new version of pcitool
18
#include <pcilib/timing.h>
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
19
245 by Suren A. Chilingaryan
First stand-alone ipecamera implementation
20
#include "ipecamera.h"
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
21
#include "private.h"
22
#include "events.h"
23
265 by Suren A. Chilingaryan
Use new locking subsystem to ensure integrity
24
#define LOCK(lock_name) \
25
    err = pcilib_lock(ctx->lock_name##_lock); \
26
    if (err) { \
27
	pcilib_error("IPECamera is busy"); \
28
	return PCILIB_ERROR_BUSY; \
29
    } \
30
    ctx->lock_name##_locked = 1;
31
32
#define UNLOCK(lock_name) \
33
    if (ctx->lock_name##_locked) { \
34
	pcilib_unlock(ctx->lock_name##_lock); \
35
	ctx->lock_name##_locked = 0; \
36
    }
37
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
38
int ipecamera_stream(pcilib_context_t *vctx, pcilib_event_callback_t callback, void *user) {
132 by Suren A. Chilingaryan
Minor fixes and improvements
39
    int run_flag = 1;
128 by Suren A. Chilingaryan
Fix handling of return values from frame decoder and event callback
40
    int res, err = 0;
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
41
    int do_stop = 0;
42
    
43
    ipecamera_event_info_t info;
44
    ipecamera_t *ctx = (ipecamera_t*)vctx;
45
46
    if (!ctx) {
47
	pcilib_error("IPECamera imaging is not initialized");
48
	return PCILIB_ERROR_NOTINITIALIZED;
49
    }
50
262 by Suren A. Chilingaryan
Introduce API debugging
51
    ipecamera_debug(API, "ipecamera: start streaming");
52
265 by Suren A. Chilingaryan
Use new locking subsystem to ensure integrity
53
    LOCK(stream);
54
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
55
    ctx->streaming = 1;
56
    ctx->run_streamer = 1;
57
58
    if (!ctx->started) {
59
	err = ipecamera_start(vctx, PCILIB_EVENTS_ALL, PCILIB_EVENT_FLAGS_DEFAULT);
60
	if (err) {
61
	    ctx->streaming = 0;
62
	    return err;
63
	}
64
	
65
	do_stop = 1;
66
    }
67
    
144 by Suren A. Chilingaryan
Do not call the normall callback in the raw-data-only mode
68
    if (ctx->parse_data) {
69
	    // This loop iterates while the generation
70
	while ((run_flag)&&((ctx->run_streamer)||(ctx->reported_id != ctx->event_id))) {
133 by Suren A. Chilingaryan
In preprocessing mode, announce the events only after reconstruction is done
71
#ifdef IPECAMERA_ANNOUNCE_READY
144 by Suren A. Chilingaryan
Do not call the normall callback in the raw-data-only mode
72
	    while (((!ctx->preproc)&&(ctx->reported_id != ctx->event_id))||((ctx->preproc)&&(ctx->reported_id != ctx->preproc_id))) {
133 by Suren A. Chilingaryan
In preprocessing mode, announce the events only after reconstruction is done
73
#else /* IPECAMERA_ANNOUNCE_READY */
144 by Suren A. Chilingaryan
Do not call the normall callback in the raw-data-only mode
74
	    while (ctx->reported_id != ctx->event_id) {
133 by Suren A. Chilingaryan
In preprocessing mode, announce the events only after reconstruction is done
75
#endif /* IPECAMERA_ANNOUNCE_READY */
270 by Suren A. Chilingaryan
More lost event debugging
76
		if ((ctx->event_id - ctx->reported_id) > (ctx->buffer_size - IPECAMERA_RESERVE_BUFFERS)) {
77
		    ipecamera_debug(HARDWARE, "Skipping events %zu to %zu as preprocessing is too slow. We are currently %zu buffers beyond, but only %zu buffers are available and safety limit is %zu",
78
			ctx->reported_id, ctx->event_id - (ctx->buffer_size - 1 - IPECAMERA_RESERVE_BUFFERS), ctx->event_id - ctx->reported_id, ctx->buffer_size, IPECAMERA_RESERVE_BUFFERS);
79
		    ctx->reported_id = ctx->event_id - (ctx->buffer_size - 1 - IPECAMERA_RESERVE_BUFFERS);
80
		} else ++ctx->reported_id;
144 by Suren A. Chilingaryan
Do not call the normall callback in the raw-data-only mode
81
82
		memcpy(&info, ctx->frame + ((ctx->reported_id-1)%ctx->buffer_size), sizeof(ipecamera_event_info_t));
83
84
		if ((ctx->event_id - ctx->reported_id) < ctx->buffer_size) {
85
		    res = callback(ctx->reported_id, (pcilib_event_info_t*)&info, user);
86
		    if (res <= 0) {
87
			if (res < 0) err = -res;
88
			run_flag = 0;
89
			break;
90
		    }
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
91
		}
92
	    }
144 by Suren A. Chilingaryan
Do not call the normall callback in the raw-data-only mode
93
	    usleep(IPECAMERA_NOFRAME_SLEEP);
94
	}
95
    } else {
96
	while ((run_flag)&&(ctx->run_streamer)) {
97
	    usleep(IPECAMERA_NOFRAME_SLEEP);
98
	}
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
99
    }
100
101
    ctx->streaming = 0;
102
265 by Suren A. Chilingaryan
Use new locking subsystem to ensure integrity
103
    UNLOCK(stream);
104
262 by Suren A. Chilingaryan
Introduce API debugging
105
    ipecamera_debug(API, "ipecamera: streaming finished");
106
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
107
    if (do_stop) {
108
	ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
109
    }
110
111
    return err;
112
}
113
114
int ipecamera_next_event(pcilib_context_t *vctx, pcilib_timeout_t timeout, pcilib_event_id_t *evid, size_t info_size, pcilib_event_info_t *info) {
265 by Suren A. Chilingaryan
Use new locking subsystem to ensure integrity
115
    int err;
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
116
    struct timeval tv;
117
    ipecamera_t *ctx = (ipecamera_t*)vctx;
118
119
    if (!ctx) {
120
	pcilib_error("IPECamera imaging is not initialized");
121
	return PCILIB_ERROR_NOTINITIALIZED;
122
    }
123
124
    if (!ctx->started) {
125
	pcilib_error("IPECamera is not in grabbing mode");
126
	return PCILIB_ERROR_INVALID_REQUEST;
127
    }
144 by Suren A. Chilingaryan
Do not call the normall callback in the raw-data-only mode
128
    
129
    if (!ctx->parse_data) {
130
	pcilib_error("RAWData only mode is requested");
131
	return PCILIB_ERROR_INVALID_REQUEST;
132
    }
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
133
262 by Suren A. Chilingaryan
Introduce API debugging
134
    ipecamera_debug(API, "ipecamera: next_event");
135
265 by Suren A. Chilingaryan
Use new locking subsystem to ensure integrity
136
    LOCK(stream);
137
133 by Suren A. Chilingaryan
In preprocessing mode, announce the events only after reconstruction is done
138
#ifdef IPECAMERA_ANNOUNCE_READY
139
    if (((!ctx->preproc)&&(ctx->reported_id == ctx->event_id))||((ctx->preproc)&&(ctx->reported_id == ctx->preproc_id))) {
140
#else /* IPECAMERA_ANNOUNCE_READY */
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
141
    if (ctx->reported_id == ctx->event_id) {
133 by Suren A. Chilingaryan
In preprocessing mode, announce the events only after reconstruction is done
142
#endif /* IPECAMERA_ANNOUNCE_READY */
143
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
144
	if (timeout) {
154 by Suren A. Chilingaryan
Support infinite timeouts in the get_next_frame
145
	    if (timeout == PCILIB_TIMEOUT_INFINITE) {
146
#ifdef IPECAMERA_ANNOUNCE_READY
244 by Suren A. Chilingaryan
Check if camera still started if INFINITE timeout is passed to ipecamera_get_next_event
147
		while ((ctx->started)&&(((!ctx->preproc)&&(ctx->reported_id == ctx->event_id))||((ctx->preproc)&&(ctx->reported_id == ctx->preproc_id)))) {
154 by Suren A. Chilingaryan
Support infinite timeouts in the get_next_frame
148
#else /* IPECAMERA_ANNOUNCE_READY */
244 by Suren A. Chilingaryan
Check if camera still started if INFINITE timeout is passed to ipecamera_get_next_event
149
		while ((ctx->started)&&(ctx->reported_id == ctx->event_id)) {
154 by Suren A. Chilingaryan
Support infinite timeouts in the get_next_frame
150
#endif /* IPECAMERA_ANNOUNCE_READY */
151
		usleep(IPECAMERA_NOFRAME_SLEEP);
152
		}
240 by Suren A. Chilingaryan
Fix frame size computation in ipecamera and few debuging options
153
	    } else {
154 by Suren A. Chilingaryan
Support infinite timeouts in the get_next_frame
154
		pcilib_calc_deadline(&tv, timeout);
133 by Suren A. Chilingaryan
In preprocessing mode, announce the events only after reconstruction is done
155
156
#ifdef IPECAMERA_ANNOUNCE_READY
173 by Suren A. Chilingaryan
Bail out from ipecamera_get_next_event if camera is stopped during the wait
157
		while ((ctx->started)&&(pcilib_calc_time_to_deadline(&tv) > 0)&&(((!ctx->preproc)&&(ctx->reported_id == ctx->event_id))||((ctx->preproc)&&(ctx->reported_id == ctx->preproc_id)))) {
133 by Suren A. Chilingaryan
In preprocessing mode, announce the events only after reconstruction is done
158
#else /* IPECAMERA_ANNOUNCE_READY */
173 by Suren A. Chilingaryan
Bail out from ipecamera_get_next_event if camera is stopped during the wait
159
		while ((ctx->started)&&(pcilib_calc_time_to_deadline(&tv) > 0)&&(ctx->reported_id == ctx->event_id)) {
133 by Suren A. Chilingaryan
In preprocessing mode, announce the events only after reconstruction is done
160
#endif /* IPECAMERA_ANNOUNCE_READY */
173 by Suren A. Chilingaryan
Bail out from ipecamera_get_next_event if camera is stopped during the wait
161
		    usleep(IPECAMERA_NOFRAME_SLEEP);
154 by Suren A. Chilingaryan
Support infinite timeouts in the get_next_frame
162
		}
133 by Suren A. Chilingaryan
In preprocessing mode, announce the events only after reconstruction is done
163
	    }
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
164
	}
165
	
173 by Suren A. Chilingaryan
Bail out from ipecamera_get_next_event if camera is stopped during the wait
166
	if (ctx->reported_id == ctx->event_id) {
265 by Suren A. Chilingaryan
Use new locking subsystem to ensure integrity
167
	    UNLOCK(stream);
262 by Suren A. Chilingaryan
Introduce API debugging
168
	    ipecamera_debug(API, "ipecamera: next_event timed out");
173 by Suren A. Chilingaryan
Bail out from ipecamera_get_next_event if camera is stopped during the wait
169
	    return PCILIB_ERROR_TIMEOUT;
170
	}
154 by Suren A. Chilingaryan
Support infinite timeouts in the get_next_frame
171
	
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
172
    }
173
174
retry:
270 by Suren A. Chilingaryan
More lost event debugging
175
    if ((ctx->event_id - ctx->reported_id) > (ctx->buffer_size - IPECAMERA_RESERVE_BUFFERS)) {
176
	ipecamera_debug(HARDWARE, "Skipping events %zu to %zu as preprocessing is too slow. We are currently %zu buffers beyond, but only %zu buffers are available and safety limit is %zu",
177
	    ctx->reported_id, ctx->event_id - (ctx->buffer_size - 1 - IPECAMERA_RESERVE_BUFFERS), ctx->event_id - ctx->reported_id, ctx->buffer_size, IPECAMERA_RESERVE_BUFFERS);
178
	ctx->reported_id = ctx->event_id - (ctx->buffer_size - 1 - IPECAMERA_RESERVE_BUFFERS);
179
    } else ++ctx->reported_id;
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
180
181
    if (evid) *evid = ctx->reported_id;
182
183
    if (info) {
184
	if (info_size >= sizeof(ipecamera_event_info_t))
185
	    memcpy(info, ctx->frame + ((ctx->reported_id-1)%ctx->buffer_size), sizeof(ipecamera_event_info_t));
186
	else if (info_size >= sizeof(pcilib_event_info_t))
187
	    memcpy(info, ctx->frame + ((ctx->reported_id-1)%ctx->buffer_size), sizeof(pcilib_event_info_t));
262 by Suren A. Chilingaryan
Introduce API debugging
188
	else {
265 by Suren A. Chilingaryan
Use new locking subsystem to ensure integrity
189
	    UNLOCK(stream);
262 by Suren A. Chilingaryan
Introduce API debugging
190
	    ipecamera_debug(API, "ipecamera: next_event returned a error");
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
191
	    return PCILIB_ERROR_INVALID_ARGUMENT;
262 by Suren A. Chilingaryan
Introduce API debugging
192
	}
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
193
    }
190.1.2 by Suren A. Chilingaryan
Fix lock-up under the frame-flood, when the frame rate is significantly faster than processing
194
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
195
    if ((ctx->event_id - ctx->reported_id) >= ctx->buffer_size) goto retry;
190.1.2 by Suren A. Chilingaryan
Fix lock-up under the frame-flood, when the frame rate is significantly faster than processing
196
265 by Suren A. Chilingaryan
Use new locking subsystem to ensure integrity
197
    UNLOCK(stream);
198
262 by Suren A. Chilingaryan
Introduce API debugging
199
    ipecamera_debug(API, "ipecamera: next_event returned");
200
126 by Suren A. Chilingaryan
multithread preprocessing of ipecamera frames and code reorganization
201
    return 0;
202
}
203
283 by Suren A. Chilingaryan
Added ipecamera_get_last_event_id() to public API
204
pcilib_event_id_t ipecamera_get_last_event_id(ipecamera_t *ctx) {
205
    return ctx->event_id;
206
}