tao-cameras.h 65.3 KB
Newer Older
1
2
3
/*
 * tao-cameras.h --
 *
Éric Thiébaut's avatar
Éric Thiébaut committed
4
 * Definitions and API for cameras in TAO.
5
6
7
 *
 *-----------------------------------------------------------------------------
 *
8
9
 * This file if part of TAO real-time software licensed under the MIT license
 * (https://git-cral.univ-lyon1.fr/tao/tao-rt).
10
 *
11
 * Copyright (C) 2019-2021, Éric Thiébaut.
12
13
14
15
16
17
 */

#ifndef _TAO_CAMERAS_H_
#define _TAO_CAMERAS_H_ 1

#include <limits.h>
Éric Thiébaut's avatar
Éric Thiébaut committed
18
#include <tao-shared.h>
19
#include <tao-options.h>
20
21
22
23
24
25

_TAO_BEGIN_DECLS

/**
 * @addtogroup Cameras
 *
26
 * There are several kinds of objects to manage cameras in TAO:
27
 *
28
 * - `tao_framegrabber_t` emulates a virtual frame grabber.
29
 *
Éric Thiébaut's avatar
Éric Thiébaut committed
30
 * - `tao_camera_t` provides a unified interface to a camera device.
31
 *
32
33
 * - `tao_shared_camera_t` stores the current state of a camera in shared
 *   memory.
34
35
36
37
 *
 * @{
 */

38
39
40
41
42
43
44
45
46
47
48
/*---------------------------------------------------------------------------*/
/* COMMON TYPES AND METHODS */

/**
 * @addtogroup CamerasCommon
 *
 * Common types and methods for cameras.
 *
 * @{
 */

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/**
 * Region of interest on a camera.
 */
typedef struct _tao_camera_roi {
    long   xbin;/**< Horizontal binning (in physical pixels). */
    long   ybin;/**< Vertical binning (in physical pixels). */
    long   xoff;/**< Horizontal offset of the acquired images with respect to
                     the left border of the detector (in physical pixels). */
    long   yoff;/**< Vertical offset of the acquired images with respect to the
                     bottom border of the detector (in physical pixels). */
    long  width;/**< Number of pixels per line of the acquired images (in
                     macro-pixels). */
    long height;/**< Number of lines of pixels in the acquired images (in
                     macro-pixels). */
} tao_camera_roi_t;

/**
 * Copy the settings of a region of interest.
 *
 * This function copies the settings of the source @b src into the destination
 * @b dest and returns @b dest.
 *
 * @param dest   Address of destination.
 * @param  src   Address of source.
 *
 * @return The destination @b dest.
 *
 * @see tao_camera_roi_t, tao_check_camera_roi(),
 * tao_define_camera_roi().
 */
79
80
extern tao_camera_roi_t* tao_copy_camera_roi(tao_camera_roi_t* dest,
                                             const tao_camera_roi_t* src);
81
82
83
84
85
86
87

/**
 * Set a region of interest.
 *
 * This function set the members of @b roi and returns @b roi.
 *
 * @param   dest   Address of region of interest.
88
89
90
91
 * @param   xbin   Horizontal binning (in physical pixels).
 * @param   ybin   Vertical binning (in physical pixels).
 * @param   xoff   Horizontal offset of ROI (in physical pixels).
 * @param   yoff   Vertical offset of ROI (in physical pixels).
92
93
94
95
96
97
98
99
 * @param  width   Horizontal size of ROI (in macro-pixels).
 * @param height   Vertical size of ROI (in macro-pixels).
 *
 * @return The region of interest @b roi.
 *
 * @see tao_camera_roi_t, tao_copy_camera_roi(),
 * tao_check_camera_roi().
 */
100
101
102
103
extern tao_camera_roi_t* tao_define_camera_roi(tao_camera_roi_t* roi,
                                               long xbin, long ybin,
                                               long xoff, long yoff,
                                               long width, long height);
104
105
106
107
108
109
110
111
112
113
114
115

/**
 * Check a region of interest.
 *
 * This function check whether the region of interest settings in @b roi are
 * valid and compatible with the sensor dimensions given by @b sensorwidth and
 * @b sensorheight.
 *
 * @param          roi   Address of the region of interest to check.
 * @param  sensorwidth   Horizontal size of detector (in pixels).
 * @param sensorheight   Vertical size of detector (in pixels).
 *
116
 * @return @ref TAO_OK if the ROI is valid, @ref TAO_ERROR otherwise.
117
118
119
120
 *
 * @see tao_camera_roi_t, tao_copy_camera_roi(),
 * tao_define_camera_roi().
 */
121
122
123
extern tao_status_t tao_check_camera_roi(const tao_camera_roi_t* roi,
                                         long sensorwidth,
                                         long sensorheight);
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

/**
 * Possible states of a remote camera.
 *
 * These represent the tasks that are currently been executed by the
 * frame-grabber thread in charge of the acquisition of images.  The meanings
 * of the different states are as follow:
 *
 * - @b initializing: the tread is not yet ready;
 * - @b sleeping: acquisition has not yet started, setting configuration
 *      parameters is possible;
 * - @b starting: acquisition is about to start;
 * - @b acquiring: acquisition of images is running;
 * - @b stopping: acquisition is about to stop;
 * - @b aborting: acquisition is about to abort;
139
 * - @b finished: thread is about to quit or no longer reachable.
140
141
142
143
144
145
146
147
 */
typedef enum {
    TAO_CAMERA_STATE_INITIALIZING = 0,
    TAO_CAMERA_STATE_SLEEPING     = 1,
    TAO_CAMERA_STATE_STARTING     = 2,
    TAO_CAMERA_STATE_ACQUIRING    = 3,
    TAO_CAMERA_STATE_STOPPING     = 4,
    TAO_CAMERA_STATE_ABORTING     = 5,
148
    TAO_CAMERA_STATE_FINISHED     = 6,
149
150
151
152
153
154
155
156
157
} tao_camera_state_t;

/**
 * Yield the literal name of a camera state.
 *
 * @param state   A camera state value.
 *
 * @return The literal name of the camera state or `"unknown"`.
 */
158
extern const char* tao_get_camera_state_name(tao_camera_state_t state);
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

/**
 * Pending events for a camera.
 *
 * Pending events are given as a combination of bits.  The following events
 * are implemented:
 *
 * - @b TAO_EVENT_START: Start acquisition.
 * - @b TAO_EVENT_FRAME: A new frame is available.
 * - @b TAO_EVENT_ERROR: Some (recoverable) error occured.
 * - @b TAO_EVENT_STOP: Stop acquisition.
 * - @b TAO_EVENT_ABORT: Abort acquisition.
 * - @b TAO_EVENT_QUIT: Acquisition thread must quit.
 */
typedef unsigned int tao_event_t;

175
176
177
#define TAO_EVENT_COMMAND (((tao_event_t)1) << 0) /* Command sent */
#define TAO_EVENT_FRAME   (((tao_event_t)1) << 1) /* New frame available */
#define TAO_EVENT_ERROR   (((tao_event_t)1) << 2) /* Some error occured */
178
179
180
181
182
183
184
185
186
187

/**
 * Common camera configuration.
 *
 * This structure contains the (usually) configurable parameters common to any
 * kind of camera.
 */
typedef struct _tao_camera_config {
    tao_camera_roi_t          roi;/**< Region of interest on the detector. */
    tao_eltype_t        pixeltype;/**< Pixel type in pre-processed images. */
Éric Thiébaut's avatar
Éric Thiébaut committed
188
189
    tao_encoding_t sensorencoding;/**< Pixel encoding in images acquired by the
                                       sensor. */
190
191
192
193
194
195
196
197
198
199
    tao_encoding_t bufferencoding;/**< Pixel encoding for acquisition
                                       buffers. */
    int                   buffers;/**< Number of acquisition buffers. */
    double              framerate;/**< Acquisition rate in frames per
                                       second. */
    double           exposuretime;/**< Exposure time in seconds. */
    bool                 weighted;/**< True if pre-processed images have
                                       associated weights. */
} tao_camera_config_t;

200
201
202
203
204
205
/**
 * Print camera configuration.
 *
 * @param out   The output file stream where to print.
 * @param cfg   Address of camera configuration structure.
 *
206
207
 * @return @ref TAO_OK on success; @ref TAO_ERROR in case of failure.
 *
208
209
 * @see tao_print_camera_information().
 */
210
211
extern tao_status_t tao_print_camera_configuration(FILE* out,
                                                   const tao_camera_config_t* cfg);
212

213
214
215
216
217
218
219
220
221
222
/**
 * Common camera information.
 *
 * This structure contains the parameters common to any kind of camera.
 */
typedef struct _tao_camera_info {
    long           sensorwidth;/**< Number of physical pixels per row of the
                                    detector. */
    long          sensorheight;/**< Number of physical pixels per column of the
                                    detector. */
223
    tao_camera_config_t config;/**< Configurable parameters. */
224
225
    tao_camera_state_t   state;/**< State of the camera. */
    double         temperature;/**< Camera temperature (in degrees Celsius). */
226
    tao_time_t          origin;/**< Origin of time. */
227
228
229
230
231
232
233
234
235
    int64_t             frames;/**< Number of frames received so far. */
    int64_t           overruns;/**< Number of frames lost so far because of
                                    overruns. */
    int64_t         lostframes;/**< Number of lost frames. */
    int64_t          overflows;/**< Number of overflows. */
    int64_t          lostsyncs;/**< Number of synchronization losts so far. */
    int64_t           timeouts;/**< Number of timeouts so far. */
} tao_camera_info_t;

236
237
238
239
240
241
242
243
244
/**
 * Print camera configuration.
 *
 * This function prints the contents of a given camera information and calls
 * tao_print_camera_configuration() to print the configuration part.
 *
 * @param out   The output file stream where to print.
 * @param inf   Address of camera information structure.
 *
245
246
 * @return @ref TAO_OK on success; @ref TAO_ERROR in case of failure.
 *
247
248
 * @see tao_print_camera_configuration().
 */
249
250
extern tao_status_t tao_print_camera_information(FILE* out,
                                                 const tao_camera_info_t* inf);
251
252


253
254
255
256
257
258
259
260
261
262
263
264
/** @} */

/*---------------------------------------------------------------------------*/
/* REMOTE CAMERAS */

/**
 * @addtogroup RemoteCameras
 *
 * Remote/shared cameras.
 *
 * A TAO remote, or shared, camera is a structure stored in shared memory which
 * contains the current camera settings and which can be used to obtain an
Éric Thiébaut's avatar
Éric Thiébaut committed
265
 * image from the remote camera.
266
267
268
269
 *
 * @{
 */

270
271
272
273
274
275
276
277
278
279
280
/**
 * Shared camera information.
 *
 * This structure describes the shared data storing the resources of a remote
 * camera.  After querying the shared memory identifier to the server (the
 * frame grabber), clients can attach this shared data part with
 * tao_attach_shared_camera().  When a client no longer needs this shared data,
 * it shall call tao_detach_shared_camera().
 *
 * This structure **must** be considered as read-only by the clients and
 * information provided by this structure is only valid as long as the client
281
282
283
284
 * locks this shared structure by calling tao_rdlock_shared_camera() and until
 * the client unlock the structure by calling tao_unlock_shared_camera().
 * Beware to not call tao_detach_shared_camera() while the shared data is
 * locked by the caller.
285
286
287
288
289
290
291
292
 *
 * If @n counter > 0, the index in the list of shared arrays memorized by the
 * virtual frame-grabber owning the shared camera is given by:
 *
 * ```.c
 * index = (counter - 1) % length
 *```
 *
293
 */
294
struct _tao_shared_camera {
295
    tao_shared_object_t base;/**< Shared object backing storage of the
Éric Thiébaut's avatar
Éric Thiébaut committed
296
                                  structure. */
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
    tao_camera_info_t   info;/**< Camera information. */
    const uint64_t    length;/**< Lenght of the list of shared arrays memorized
                                  by the virtual frame-grabber owning the
                                  shared camera. */
    volatile
    uint64_t         counter;/**< Number of images posted by virtual
                                  frame-grabber since its creation.  It is a
                                  unique, monotically increasing number,
                                  starting at 1 (0 means no images have been
                                  provided yet).  This value can be used to
                                  determine the index of the corresponding
                                  shared image in the cyclic list of
                                  frame-grabber shared arrays. */
    volatile
    tao_shmid_t    lastframe;/**< Identifier of the shared array backing the
                                  storage of the last acquired image, -1 means
                                  unused or invalid. */
    volatile
    tao_shmid_t    nextframe;/**< Identifier of the shared array backing the
                                  storage of the next acquired image, -1 means
                                  unused or invalid. */
318
};
319
320
321
322
323
324
325
326
327
328
329
330
331

/**
 * Attach an existing shared camera to the address space of the caller.
 *
 * This function attaches an existing shared camera to the address space of the
 * caller.  As a result, the number of attachments of the shared camera is
 * incremented by one.  When the camera is no longer used by the caller, the
 * caller must call tao_detach_shared_camera() to detach the camera from its
 * address space, decrement its number of attachments by one and eventually
 * free the shared memory associated with the camera.
 *
 * @warning The same process must not attach a shared camera more than once.
 *
332
 * @param shmid  Unique identifier of the shared object.
333
334
335
336
 *
 * @return The address of the shared camera in the address space of the caller;
 * `NULL` on failure.
 *
337
 * @see tao_detach_shared_camera, tao_get_shared_camera_shmid.
338
 */
339
extern tao_shared_camera_t* tao_attach_shared_camera(tao_shmid_t shmid);
340
341
342
343
344
345
346
347
348
349
350
351
352
353

/**
 * Detach a shared camera.
 *
 * Detach a shared camera from the address space of the caller and decrement
 * the number of attachments of the shared camera.
 *
 * @warning Detaching a shared camera does not detach shared arrays backing the
 * storage of the images acquired by this camera.  They have to be explicitly
 * detached.
 *
 * @param cam    Pointer to a shared camera attached to the address space of
 *               the caller.
 *
354
 * @return @ref TAO_OK on success; @ref TAO_ERROR on failure.
355
356
357
 *
 * @see tao_attach_shared_camera.
 */
358
extern tao_status_t tao_detach_shared_camera(tao_shared_camera_t* cam);
359
360
361
362
363
364
365
366
367

/**
 * Get the identifier of shared camera data.
 *
 * @param cam    Pointer to a shared camera attached to the address space of
 *               the caller and locked by the caller.
 *
 * @return The identifier of the shared camera data.  This value can be used
 *         by another process to attach to its address space the shared camera.
Éric Thiébaut's avatar
Éric Thiébaut committed
368
 *         `TAO_BAD_SHMID` is returned if @a cam is `NULL`.
369
370
371
 *
 * @see tao_attach_shared_camera.
 */
372
extern tao_shmid_t tao_get_shared_camera_shmid(const tao_shared_camera_t* cam);
373
374
375
376
377
378
379
380
381

/**
 * Get the name of the owner/creator of a shared camera.
 *
 * @param cam    Pointer to a shared camera attached to the address space of
 *               the caller.
 *
 * @return The name of the shared camera owner.
 */
382
extern const char* tao_get_shared_camera_owner(const tao_shared_camera_t* cam);
383
384

/**
Éric Thiébaut's avatar
Éric Thiébaut committed
385
 * Get the accesspoint of the server owning a shared camera.
386
387
388
389
 *
 * @param cam    Pointer to a shared camera attached to the address space of
 *               the caller.
 *
Éric Thiébaut's avatar
Éric Thiébaut committed
390
391
 * @return The name of the shared camera owner.
 */
392
extern const char* tao_get_shared_camera_accesspoint(const tao_shared_camera_t* cam);
Éric Thiébaut's avatar
Éric Thiébaut committed
393
394
395
396
397
398
399

/**
 * Lock a shared camera for reading or writing.
 *
 * Lock a shared camera for read-only or read-write access.  The caller is
 * responsible for eventually releasing the lock with
 * tao_unlock_shared_camera().
400
 *
Éric Thiébaut's avatar
Éric Thiébaut committed
401
402
403
404
405
 * @param cam    Pointer to a shared camera attached to the address space of
 *               the caller.
 * @param access The requested access mode: `TAO_READ_ACCESS` or
 *               `TAO_WRITE_ACCESS`.
 *
406
 * @return @ref TAO_OK on success; @ref TAO_ERROR on failure.
407
 */
408
extern tao_status_t tao_rdlock_shared_camera(tao_shared_camera_t* cam);
409
410

/**
Éric Thiébaut's avatar
Éric Thiébaut committed
411
412
413
414
415
 * Attempt to lock a shared camera for reading or writing.
 *
 * Try to lock a shared camera for read-only or read-write access without
 * blocking.  The caller is responsible for eventually releasing the lock with
 * tao_unlock_shared_camera().
416
417
418
419
 *
 * @param cam    Pointer to a shared camera attached to the address space of
 *               the caller.
 *
Éric Thiébaut's avatar
Éric Thiébaut committed
420
421
 * @param access The requested access mode: `TAO_READ_ACCESS` or
 *               `TAO_WRITE_ACCESS`.
422
 *
423
424
 * @return @ref TAO_OK on success, @ref TAO_TIMEOUT if the lock cannot be
 *         immediately acquired or @ref TAO_ERROR on failure.
425
 */
426
extern tao_status_t tao_try_rdlock_shared_camera(tao_shared_camera_t* cam);
427

Éric Thiébaut's avatar
Éric Thiébaut committed
428
429
430
431
432
433
434
435
436
437
438
439
440
441
/**
 * Lock a shared camera for reading or writing with a timeout.
 *
 * Try to lock a shared camera for read-only or read-write access without
 * blocking more than a given duration.  The caller is responsible for
 * eventually releasing the lock with tao_unlock_shared_camera().
 *
 * @param cam    Pointer to a shared camera attached to the address space of
 *               the caller.
 *
 * @param access The requested access mode: `TAO_READ_ACCESS` or
 *               `TAO_WRITE_ACCESS`.
 *
 * @param secs   Maximum time to wait (in seconds).  If this amount of time is
442
 *               very large, e.g. more than @ref TAO_MAX_TIME_SECONDS, the
443
 *               effect is the same as calling tao_rdlock_shared_camera().  If
Éric Thiébaut's avatar
Éric Thiébaut committed
444
 *               this amount of time is very short, the effect is the same as
445
 *               calling tao_try_rdlock_shared_camera().
Éric Thiébaut's avatar
Éric Thiébaut committed
446
 *
447
448
449
 * @return @ref TAO_OK if the lock has been locked by the caller before the
 *         specified number of seconds, @ref TAO_TIMEOUT if timeout occured
 *         before or @ref TAO_ERROR in case of error.
Éric Thiébaut's avatar
Éric Thiébaut committed
450
 */
451
extern tao_status_t tao_abstimed_rdlock_shared_camera(tao_shared_camera_t* cam,
452
                                                      const tao_time_t* abstime);
453
454
455
456
457
458
459
460
461

extern tao_status_t tao_timed_rdlock_shared_camera(tao_shared_camera_t* cam,
                                                   double secs);

extern tao_status_t tao_wrlock_shared_camera(tao_shared_camera_t* cam);

extern tao_status_t tao_try_wrlock_shared_camera(tao_shared_camera_t* cam);

extern tao_status_t tao_abstimed_wrlock_shared_camera(tao_shared_camera_t* cam,
462
                                                      const tao_time_t* abstime);
463
464
465

extern tao_status_t tao_timed_wrlock_shared_camera(tao_shared_camera_t* cam,
                                                   double secs);
466
467
468
469
470
471
/**
 * Unlock a shared camera.
 *
 * @param cam    Pointer to a shared camera attached to the address space of
 *               the caller.
 *
472
 * @return @ref TAO_OK on success; @ref TAO_ERROR on failure.
473
474
475
 *
 * @see tao_unlock_shared_object.
 */
476
extern tao_status_t tao_unlock_shared_camera(tao_shared_camera_t* cam);
477
478
479
480
481
482
483
484
485
486

/**
 * Get the current state of the camera.
 *
 * @param cam   Address of shared camera in address space of caller.
 *
 * @return `-1` if @a cam is `NULL`; otherwise, `0` if device not yet open, `1`
 *         if device open but no acquisition is running, `2` if acquisition is
 *         running.
 */
487
extern tao_camera_state_t tao_get_shared_camera_state(const tao_shared_camera_t* cam);
488
489
490
491
492
493
494
495
496

/**
 * Get the pixel type for the captured images after pre-processing.
 *
 * @param cam   Address of shared camera in address space of caller.
 *
 * @return The pixel type for the captured images after pre-processing, `-1`
 *         if @a cam is `NULL`.
 */
497
extern tao_eltype_t tao_get_shared_camera_pixeltype(const tao_shared_camera_t* cam);
498
499
500
501
502
503
504
505
506

/**
 * Get the encoding of pixels in images sent by the camera.
 *
 * @param cam   Address of shared camera in address space of caller.
 *
 * @return The encoding of pixels in the raw captured images,
 *         `TAO_ENCODING_UNKNOWN` if @a cam is `NULL`.
 */
507
extern tao_encoding_t tao_get_shared_camera_sensorencoding(const tao_shared_camera_t* cam);
508
509
510
511
512
513
514
515
516

/**
 * Get the encoding of pixels in acquisition buffers.
 *
 * @param cam   Address of shared camera in address space of caller.
 *
 * @return The encoding of pixels in acquisition buffers,
 *         `TAO_ENCODING_UNKNOWN` if @a cam is `NULL`.
 */
517
extern tao_encoding_t tao_get_shared_camera_bufferencoding(const tao_shared_camera_t* cam);
518
519
520
521
522
523
524
525
526
527
528
529

/**
 * Get the width of the detector.
 *
 * This function yields the number of pixels per line of the detector which is
 * the maximum width for captured iamges.
 *
 * @param cam   Address of shared camera in address space of caller.
 *
 * @return The number of pixels per line of the detector, `0` if @a cam is
 *         `NULL`.
 */
530
extern long tao_get_shared_camera_sensorwidth(const tao_shared_camera_t* cam);
531
532
533
534
535
536
537
538
539
540
541
542

/**
 * Get the height of the detector.
 *
 * This function yields the number of lines of pixels of the detector which is
 * the maximum height for captured iamges.
 *
 * @param cam   Address of shared camera in address space of caller.
 *
 * @return The number of lines of pixels of the detector, `0` if @a cam is
 *         `NULL`.
 */
543
extern long tao_get_shared_camera_sensorheight(const tao_shared_camera_t* cam);
544
545
546
547
548
549
550
551
552

/**
 * Get the horizontal binning factor.
 *
 * @param cam   Address of shared camera in address space of caller.
 *
 * @return The horizontal binning factor in physical pixels, `0` if
 *         @a cam is `NULL`.
 */
553
extern long tao_get_shared_camera_xbin(const tao_shared_camera_t* cam);
554
555
556
557
558
559
560
561
562

/**
 * Get the vertical binning factor.
 *
 * @param cam   Address of shared camera in address space of caller.
 *
 * @return The vertical binning factor in physical pixels, `0` if
 *         @a cam is `NULL`.
 */
563
extern long tao_get_shared_camera_ybin(const tao_shared_camera_t* cam);
564
565
566
567
568
569
570
571
572

/**
 * Get the horizontal offset of captured images.
 *
 * @param cam   Address of shared camera in address space of caller.
 *
 * @return The horizontal offset in physical pixels of the region of interest
 *         set for the captured images, `0` if @a cam is `NULL`.
 */
573
extern long tao_get_shared_camera_xoff(const tao_shared_camera_t* cam);
574
575
576
577
578
579
580
581
582

/**
 * Get the vertical offset of captured images.
 *
 * @param cam   Address of shared camera in address space of caller.
 *
 * @return The vertical offset in physical pixels of the region of interest
 *         set for the captured images, `0` if @a cam is `NULL`.
 */
583
extern long tao_get_shared_camera_yoff(const tao_shared_camera_t* cam);
584
585
586
587
588
589
590
591
592
593
594
595
596

/**
 * Get the width of the captured images.
 *
 * This function yields the number of macro-pixels per line of the captured
 * images.  If no sub-sampling nor re-binning of physical pixels is used a
 * macro-pixel corresponds to a physical pixel.
 *
 * @param cam   Address of shared camera in address space of caller.
 *
 * @return The number of macro-pixels per line of the captured images, `0` if
 *         @a cam is `NULL`.
 */
597
extern long tao_get_shared_camera_width(const tao_shared_camera_t* cam);
598
599
600
601
602
603
604
605
606
607
608
609
610

/**
 * Get the height of the captured images.
 *
 * This function yields the number of lines of macro-pixels in the captured
 * images.  If no sub-sampling nor re-binning of physical pixels is used a
 * macro-pixel corresponds to a physical pixel.
 *
 * @param cam   Address of shared camera in address space of caller.
 *
 * @return The number of lines of macro-pixels in the captured images, `0` if
 *         @a cam is `NULL`.
 */
611
extern long tao_get_shared_camera_height(const tao_shared_camera_t* cam);
612
613
614
615
616
617
618
619

/**
 * Get the frame rate.
 *
 * @param cam   Address of shared camera in address space of caller.
 *
 * @return The number of frame per seconds, `0` if @a cam is `NULL`.
 */
620
extern double tao_get_shared_camera_framerate(const tao_shared_camera_t* cam);
621
622
623
624
625
626
627
628
629

/**
 * Get the duration of the exposure.
 *
 * @param cam   Address of shared camera in address space of caller.
 *
 * @return The exposure time in seconds for the captured images, `0` if @a cam
 *         is `NULL`.
 */
630
extern double tao_get_shared_camera_exposuretime(const tao_shared_camera_t* cam);
631
632

/**
633
634
 * Get the length of the list of shared arrays memorized by the owner of
 * a shared camera.
635
 *
636
637
 * @param cam    Pointer to a shared camera attached to the address space of
 *               the caller and locked by the caller.
638
 *
639
640
 * @note The length of the list is immutable, the caller does not have to lock
 * the shared camera to insure consistency of the result.
641
 *
642
643
 * @return The length of the list of shared arrays memorized by the owner of
 * the shared camera, `0` if @a cam is `NULL`.
644
 *
645
 * @see tao_rdlock_shared_camera.
646
 */
647
extern uint64_t tao_get_image_list_length(const tao_shared_camera_t* cam);
648
649

/**
650
 * Get the number of posted images.
651
 *
652
653
 * @param cam    Pointer to a shared camera attached to the address space of
 *               the caller and locked by the caller.
654
 *
655
656
657
 * @warning Since the last image may change (because acquisition is running),
 * the caller must have locked the shared camera.  For efficiency reasons, this
 * function does not perform error checking.
658
 *
659
660
 * @return The the number of images posted by the owner of the shared camera
 * `0` if none or if @a cam is `NULL`.
661
 *
662
 * @see tao_rdlock_shared_camera.
663
 */
664
extern uint64_t tao_get_last_image_counter(const tao_shared_camera_t* cam);
665

666
/**
667
 * Get the identifier of the last acquired image.
668
 *
669
670
671
672
 * This function yields the shared memory identifier of the last image acquired
 * by a remote camera.  Since the last image may change (because acquisition is
 * running), the caller is assumed to have locked the shared camera, at least
 * for read-only access.
673
 *
674
675
 * @param cam    Pointer to a shared camera attached to the address space of
 *               the caller and locked by the caller.
676
 *
677
678
679
680
681
 * @return The identifier of the last acquired image or @ref TAO_BAD_SHMID if
 *         none or if @a cam is `NULL`.
 *
 * @see tao_rdlock_shared_camera, tao_attach_last_image.
 */
682
extern tao_shmid_t tao_get_last_image_shmid(const tao_shared_camera_t* cam);
683
684
685
686
687
688
689
690
691
692

/**
 * Get the identifier of the next acquired image.
 *
 * @param cam    Pointer to a shared camera attached to the address space of
 *               the caller and locked by the caller.
 *
 * @warning Since the next image may change (because acquisition is running),
 *          the caller is assumed to have locked the shared camera, at least
 *          for read-only access.
693
 *
694
695
 * @return The identifier of the last acquired image or @ref TAO_BAD_SHMID if
 *         none or if @a cam is `NULL`.
696
 *
697
 * @see tao_rdlock_shared_camera.
698
 */
699
extern tao_shmid_t tao_get_next_image_shmid(const tao_shared_camera_t* cam);
700

701
/**
702
 * Attach the last acquired image to the address space of the caller.
703
 *
704
705
706
 * This function attaches the last image acquired by a frame grabber to the
 * address space of the caller.  The caller is responsible of calling
 * tao_detach_shared_array() to detach the image from its address space.
707
 *
708
709
710
711
 * Since the last image may change (because acquisition is running), the caller
 * is assumed to have locked the shared camera, at least for read-only access.
 * It is the caller responsability to lock the returned image to make sure it
 * is not overwritten while reading its contents.
712
 *
713
 * @param cam    Address of a shared camera attached to the address space of
714
715
 *               the caller.
 *
716
717
 * The following example shows how to retrieve the last image data provided
 * the image counter has increased since previous image:
718
 *
719
720
721
722
723
724
725
726
727
728
729
730
731
732
 * ```.c
 * tao_shared_camera_t* cam = ...;
 * uint64_t previous_counter = ...;
 * tao_shared_array_t* arr = NULL;
 * tao_rdlock_shared_camera(NULL, cam);
 * {
 *     uint64_t last_counter = tao_get_last_image_counter(cam);
 *     if (last_counter > previous_counter) {
 *         arr = tao_attach_last_image(NULL, cam);
 *         previous_counter = last_counter;
 *     }
 * }
 * tao_unlock_shared_camera(NULL, cam);
 * ```
733
 *
734
735
736
 * Note the use of braces to emphasizes the block of statements protected by
 * the lock.  Also note that `NULL` is passed as the address of the variable to
 * track errors so any error will be considered as fatal in this example.
737
 *
738
 * The same example without tao_attach_last_image():
739
 *
740
741
742
743
744
745
746
747
 * ```.c
 * tao_shared_camera_t* cam = ...;
 * uint64_t previous_counter = ...;
 * tao_shared_array_t* arr = NULL;
 * tao_rdlock_shared_camera(NULL, cam);
 * {
 *     uint64_t last_counter = tao_get_last_image_counter(cam);
 *     if (last_counter > previous_counter) {
748
749
750
 *         tao_shmid_t shmid = tao_get_last_image_shmid(cam);
 *         if (shmid != TAO_BAD_SHMID) {
 *             arr = tao_attach_shared_array(NULL, shmid);
751
752
753
754
755
756
757
758
759
 *             previous_counter = last_counter;
 *         }
 *     }
 * }
 * tao_unlock_shared_camera(NULL, cam);
 * ```
 *
 * @return The address of the shared camera in the address space of the caller;
 *         `NULL` on failure or if there is no valid last image.
760
 *
761
 * @see tao_get_last_image_shmid, tao_get_last_image_counter,
762
 *      tao_attach_next_image.
763
 */
764
extern tao_shared_array_t* tao_attach_last_image(tao_shared_camera_t* cam);
765
766

/**
767
 * Attach the next acquired image to the address space of the caller.
768
 *
769
770
771
772
 * This function attaches the next image that will be acquired by a frame
 * grabber to the address space of the caller.  The caller is responsible of
 * calling tao_detach_shared_array() to detach the image from its address
 * space.
773
 *
774
775
 * Since the next image may change (because acquisition is running), the caller
 * is assumed to have locked the shared camera, at least for read-only access.
776
 *
777
778
779
780
781
782
 * The next image is locked for writing by the camera server until the next
 * image is acquired and pre-processed.  In order to wait for the acquisition
 * to complete, the caller shall attempt to lock the returned image for reading
 * (possibly with a timeout) this also ensure it is not overwritten while
 * reading its contents.  Note that the frame counter of the shared image is
 * updated by the camera server just before unlocking the image.
783
 *
784
785
 * @param cam    Address of a shared camera attached to the address space of
 *               the caller.
786
 *
787
788
789
 * The following example shows how to retrieve the next images data while
 * acquisition is running and making sure the image counter does increase
 * between successive images:
790
 *
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
 * ```.c
 * tao_shared_camera_t* cam = ...;
 * uint64_t previous_counter = 0;
 * tao_shared_array_t* arr = NULL;
 * bool acquiring = true;
 * while (acquiring) {
 *     tao_rdlock_shared_camera(NULL, cam);
 *     {
 *         arr = tao_attach_next_image(NULL, cam);
 *     }
 *     tao_unlock_shared_camera(NULL, cam);
 *     tao_rdlock_shared_array(NULL, arr); // block until acquisition done
 *     {
 *         uint64_t counter = tao_get_shared_array_counter(arr);
 *         if (counter > previous_counter) {
 *             ...; // do something with the image data
 *             previous_counter = counter;
 *         } else if (counter == 0) {
 *             // acquisition has been stopped
 *             acquiring = false;
 *         }
 *     }
 *     tao_unlock_shared_array(NULL, arr);
 *     tao_detach_shared_array(NULL, arr);
 * }
 * ```
817
 *
818
819
820
821
822
823
824
 * Note the use of braces to emphasizes the block of statements protected by
 * the lock.  Also note that `NULL` is passed as the address of the variable to
 * track errors so any error will be considered as fatal in this example.
 *
 * @return The address of the shared camera in the address space of the caller;
 *         `NULL` on failure or if there is no valid last image.
 *
825
 * @see tao_get_next_image_shmid, tao_attach_last_image.
826
 */
827
extern tao_shared_array_t* tao_attach_next_image(tao_shared_camera_t* cam);
828
829
830
831

/** @} */

/*---------------------------------------------------------------------------*/
Éric Thiébaut's avatar
Éric Thiébaut committed
832
/* UNIFIED INTERFACE FOR CAMERA DEVICES */
833
834
835
836
837
838
839
840
841
842

/**
 * @addtogroup UnifiedCameras
 *
 * Unified cameras.
 *
 * TAO provides generic structures and functions to operate real cameras.
 *
 * The @ref tao_camera_t structure has its own error stack which is used by
 * most functions operating on this class of cameras to store error
Éric Thiébaut's avatar
Éric Thiébaut committed
843
844
 * information.  This is needed because the camera device may be operated by
 * another thread.
845
846
847
848
849
850
 *
 * @{
 */

/**
 * Acquisition buffer information.
851
 *
Éric Thiébaut's avatar
Éric Thiébaut committed
852
 * This structure is used to store all needed information about an acquisition
853
854
855
856
857
858
859
860
861
 * buffer returned by tao_wait_camera().  The contents is considered as purely
 * informative by the high-level interface.  For instance the high-level
 * interface does not attempt to alloc or free the acquisition buffer data,
 * these tasks are performed by the low-level interface (e.g. by the "start"
 * and "finalize" virtual methods).
 *
 * A valid buffer counter should be equal to the corresponding frame counter
 * which is greater or equal 1.  When acquisition is started by
 * tao_acquisition_start(), all buffer counters are set to 0.
862
863
864
 */
typedef struct _tao_acquisition_buffer {
    void*                   data;/**< Address of buffer data. */
865
    long                    size;/**< Number of bytes in buffer. */
866
867
868
869
870
871
    long                  offset;/**< Offset (in bytes) of first pixel in
                                      ROI. */
    long                   width;/**< Number of pixel per line in ROI. */
    long                  height;/**< Number of lines in ROI. */
    long                  stride;/**< Bytes per line in buffer. */
    tao_encoding_t      encoding;/**< Pixel encoding in buffer. */
872
    uint64_t        frame_number;/**< Number of frames so far. */
873
874
875
    tao_time_t       frame_start;/**< Start time of frame. */
    tao_time_t         frame_end;/**< End time of frame. */
    tao_time_t      buffer_ready;/**< Buffer ready time. */
876
877
878
879
880
881
882
883
884
885
886
887
888
} tao_acquisition_buffer_t;

/**
 * Opaque camera structure.
 */
typedef struct _tao_camera tao_camera_t;

/**
 * Table of virtual methods for a camera.
 *
 * An instance of this structure is specific to each combination of camera
 * model and frame-grabber.
 *
Éric Thiébaut's avatar
Éric Thiébaut committed
889
 * Camera @b run-level has only 5 levels: @b 0 when initialization is not
890
891
892
893
 * complete, @b 1 when initialized but acquisition not started, @b 2 when
 * acquiring, @b 3 if an error occured that requires an explicit reset to
 * return to run-level 1 or @b 4 if camera is no longer usable and can only be
 * finalized (e.g. upon unrecoverable error).
894
 *
895
 * The following transitions are possible:
896
 *
897
898
899
 *    0 -> 1  is done when successfully calling the "initialize" virtual method
 *            which is only called once during the lifetime of the camera
 *            instance; so `runlevel != 0` means camera has been initialized;
900
 *
Éric Thiébaut's avatar
Éric Thiébaut committed
901
 *    1 -> 2 is done when successfully calling the "start" virtual method;
902
 *
903
 *    2 -> 1  is done when successfully calling the "stop" virtual method;
904
 *
905
 *    3 -> 1  is done when successfully calling the "reset" virtual method;
906
 *
907
 *    x -> 3  (with x neither 0, nor 4) may result from a recoverable error
908
 *            that requires an explicit reset;
909
 *
910
911
912
913
914
 *    x -> 4  (with x not 0) may result from an unrecoverable error.
 *
 * Except in case of errors (and when explicitly indicated), the virtual
 * methods are not allowed to change the camera run-level.  Changing the
 * run-level is done by the higher level TAO functions which call virtual
Éric Thiébaut's avatar
Éric Thiébaut committed
915
916
917
918
 * methods as needed and which also ensure that the camera is in a proper
 * run-level before calling a specific virtual method.  These rules are to
 * simplify the writting of virtual methods and to implement a common and
 * consistent behavior.
919
 *
Éric Thiébaut's avatar
Éric Thiébaut committed
920
921
922
 * Virtual methods must be all implemented (provided a `NULL` address is not
 * allowed).  If some method makes no sense for a specific kind of camera, the
 * implemented method shall returns an error.
923
 *
924
 * Initialization failure results in run-level being stuck at 0, subsequent
Éric Thiébaut's avatar
Éric Thiébaut committed
925
 * operations on the camera yield @ref TAO_NOT_READY error code.
926
927
928
929
 */
typedef struct _tao_camera_ops {
    const char* name; /**< Camera model/family name */

Éric Thiébaut's avatar
Éric Thiébaut committed
930
    tao_status_t (*initialize)(tao_camera_t* cam);
Éric Thiébaut's avatar
Éric Thiébaut committed
931
932
933
934
935
936
    /**< Initialize the members of this structure (including the
         configuration).  This method is only called once during the lifetime
         of the camera instance.  It shall return @ref TAO_OK on success or @ref
         TAO_ERROR on failure.  It is assumed that any allocated specific
         resources are destroyed in case of failure (the `finalize` method is
         not called if initialization fails). */
937

938
    void (*finalize)(tao_camera_t* cam);
Éric Thiébaut's avatar
Éric Thiébaut committed
939
940
941
942
    /**< Free device resources.  This method is only called once at the end of
         the lifetime of the camera instance.  This method is not called by the
         generic constructor tao_create_camera() in case of errors during the
         construction. */
943

Éric Thiébaut's avatar
Éric Thiébaut committed
944
    tao_status_t (*reset)(tao_camera_t* cam);
945
946
947
948
    /**< Reset camera to run-level 1 (sleeping) in case of recoverable error.
         This method shall only be called when the camera run-level is 3.  On
         success, the method shall set the run-level to 1 and return TAO_OK;
         otherwise it shall return @ref TAO_ERROR to indicate a failure. */
949

Éric Thiébaut's avatar
Éric Thiébaut committed
950
    tao_status_t (*update_config)(tao_camera_t* cam);
Éric Thiébaut's avatar
Éric Thiébaut committed
951
952
953
    /**< Retrieve camera current device settings, never called while
         acquisition is running.  It shall return @ref TAO_OK on success or
         @ref TAO_ERROR on failure. */
954

Éric Thiébaut's avatar
Éric Thiébaut committed
955
956
    tao_status_t (*check_config)(tao_camera_t* cam,
                                 const tao_camera_config_t* cfg);
Éric Thiébaut's avatar
Éric Thiébaut committed
957
958
959
    /**< Check camera settings.  Camera error stack may be used to report which
         parameters are invalid.  It shall return @ref TAO_OK on success or
         @ref TAO_ERROR on failure. */
960

Éric Thiébaut's avatar
Éric Thiébaut committed
961
962
    tao_status_t (*set_config)(tao_camera_t* cam,
                               const tao_camera_config_t* cfg);
Éric Thiébaut's avatar
Éric Thiébaut committed
963
964
965
    /**< Set camera settings.  This method is called to set the camera
         configuration.  It is never called while acquitring.  It shall return
         @ref TAO_OK on success or @ref TAO_ERROR on failure. */
966

Éric Thiébaut's avatar
Éric Thiébaut committed
967
    tao_status_t (*start)(tao_camera_t* cam);
Éric Thiébaut's avatar
Éric Thiébaut committed
968
969
970
    /**< Start acquisition.  This method is only called after initialization
         and if the camera is not acquiring.  It shall return @ref TAO_OK on
         success or @ref TAO_ERROR on failure. */
971

Éric Thiébaut's avatar
Éric Thiébaut committed
972
    tao_status_t (*stop)(tao_camera_t* cam);
Éric Thiébaut's avatar
Éric Thiébaut committed
973
974
975
976
    /**< Stop acquisition.  This method shall stop acquisition immediately,
         without waiting for the current frame. This method is only called when
         the camera is acquiring.  It shall return @ref TAO_OK on success or
         @ref TAO_ERROR on failure. */
977

Éric Thiébaut's avatar
Éric Thiébaut committed
978
    tao_status_t (*wait_buffer)(tao_camera_t* cam, double secs);
Éric Thiébaut's avatar
Éric Thiébaut committed
979
980
981
982
983
    /**< Wait for the next frame.  This method is only called when the camera
         is acquiring.  It shall not wait more than `secs` seconds.  It shall
         return @ref TAO_OK on success, @ref TAO_TIMEOUT on timeout or @ref
         TAO_ERROR on failure.  This method may assume that arguments have been
         checked for correctness.  This method shall update `cam->last` and
Éric Thiébaut's avatar
Éric Thiébaut committed
984
         `cam->pending`. */
985

Éric Thiébaut's avatar
Éric Thiébaut committed
986
    tao_status_t (*release_buffer)(tao_camera_t* cam);
Éric Thiébaut's avatar
Éric Thiébaut committed
987
988
989
990
    /**< Release the first pending acquisition buffer.  This method is only
         called when the camera is acquiring.  It shall return @ref TAO_OK on
         success or @ref TAO_ERROR on failure.  This method shall update
         `cam->last` and `cam->pending`. */
991
} tao_camera_ops_t;
992
993

/**
994
 * Generic camera.
995
 *
996
997
998
 * A camera has its own mutex and condition variable because it is often
 * necessary to operate the camera in separate threads.  However these threads
 * belongs to the same process so the mutex and condition variable associated
999
1000
 * to a camera are not sharable between processes.
 *
For faster browsing, not all history is shown. View entire blame