events.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #define _DEFAULT_SOURCE
  2. #define _BSD_SOURCE
  3. #define _GNU_SOURCE
  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. #include <ufodecode.h>
  12. #include <pcilib.h>
  13. #include <pcilib/tools.h>
  14. #include <pcilib/error.h>
  15. #include <pcilib/timing.h>
  16. #include "ipecamera.h"
  17. #include "private.h"
  18. #include "events.h"
  19. #define LOCK(lock_name) \
  20. err = pcilib_lock(ctx->lock_name##_lock); \
  21. if (err) { \
  22. pcilib_error("IPECamera is busy"); \
  23. return PCILIB_ERROR_BUSY; \
  24. } \
  25. ctx->lock_name##_locked = 1;
  26. #define UNLOCK(lock_name) \
  27. if (ctx->lock_name##_locked) { \
  28. pcilib_unlock(ctx->lock_name##_lock); \
  29. ctx->lock_name##_locked = 0; \
  30. }
  31. int ipecamera_stream(pcilib_context_t *vctx, pcilib_event_callback_t callback, void *user) {
  32. int run_flag = 1;
  33. int res, err = 0;
  34. int do_stop = 0;
  35. ipecamera_event_info_t info;
  36. ipecamera_t *ctx = (ipecamera_t*)vctx;
  37. if (!ctx) {
  38. pcilib_error("IPECamera imaging is not initialized");
  39. return PCILIB_ERROR_NOTINITIALIZED;
  40. }
  41. ipecamera_debug(API, "ipecamera: start streaming");
  42. LOCK(stream);
  43. ctx->streaming = 1;
  44. ctx->run_streamer = 1;
  45. if (!ctx->started) {
  46. err = ipecamera_start(vctx, PCILIB_EVENTS_ALL, PCILIB_EVENT_FLAGS_DEFAULT);
  47. if (err) {
  48. ctx->streaming = 0;
  49. return err;
  50. }
  51. do_stop = 1;
  52. }
  53. if (ctx->parse_data) {
  54. // This loop iterates while the generation
  55. while ((run_flag)&&((ctx->run_streamer)||(ctx->reported_id != ctx->event_id))) {
  56. #ifdef IPECAMERA_ANNOUNCE_READY
  57. while (((!ctx->preproc)&&(ctx->reported_id != ctx->event_id))||((ctx->preproc)&&(ctx->reported_id != ctx->preproc_id))) {
  58. #else /* IPECAMERA_ANNOUNCE_READY */
  59. while (ctx->reported_id != ctx->event_id) {
  60. #endif /* IPECAMERA_ANNOUNCE_READY */
  61. if ((ctx->event_id - ctx->reported_id) > (ctx->buffer_size - IPECAMERA_RESERVE_BUFFERS)) {
  62. 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",
  63. 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);
  64. ctx->reported_id = ctx->event_id - (ctx->buffer_size - 1 - IPECAMERA_RESERVE_BUFFERS);
  65. } else ++ctx->reported_id;
  66. memcpy(&info, ctx->frame + ((ctx->reported_id-1)%ctx->buffer_size), sizeof(ipecamera_event_info_t));
  67. if ((ctx->event_id - ctx->reported_id) < ctx->buffer_size) {
  68. res = callback(ctx->reported_id, (pcilib_event_info_t*)&info, user);
  69. if (res <= 0) {
  70. if (res < 0) err = -res;
  71. run_flag = 0;
  72. break;
  73. }
  74. }
  75. }
  76. usleep(IPECAMERA_NOFRAME_SLEEP);
  77. }
  78. } else {
  79. while ((run_flag)&&(ctx->run_streamer)) {
  80. usleep(IPECAMERA_NOFRAME_SLEEP);
  81. }
  82. }
  83. ctx->streaming = 0;
  84. UNLOCK(stream);
  85. ipecamera_debug(API, "ipecamera: streaming finished");
  86. if (do_stop) {
  87. ipecamera_stop(vctx, PCILIB_EVENT_FLAGS_DEFAULT);
  88. }
  89. return err;
  90. }
  91. 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) {
  92. int err;
  93. struct timeval tv;
  94. ipecamera_t *ctx = (ipecamera_t*)vctx;
  95. if (!ctx) {
  96. pcilib_error("IPECamera imaging is not initialized");
  97. return PCILIB_ERROR_NOTINITIALIZED;
  98. }
  99. if (!ctx->started) {
  100. pcilib_error("IPECamera is not in grabbing mode");
  101. return PCILIB_ERROR_INVALID_REQUEST;
  102. }
  103. if (!ctx->parse_data) {
  104. pcilib_error("RAWData only mode is requested");
  105. return PCILIB_ERROR_INVALID_REQUEST;
  106. }
  107. ipecamera_debug(API, "ipecamera: next_event");
  108. LOCK(stream);
  109. #ifdef IPECAMERA_ANNOUNCE_READY
  110. if (((!ctx->preproc)&&(ctx->reported_id == ctx->event_id))||((ctx->preproc)&&(ctx->reported_id == ctx->preproc_id))) {
  111. #else /* IPECAMERA_ANNOUNCE_READY */
  112. if (ctx->reported_id == ctx->event_id) {
  113. #endif /* IPECAMERA_ANNOUNCE_READY */
  114. if (timeout) {
  115. if (timeout == PCILIB_TIMEOUT_INFINITE) {
  116. #ifdef IPECAMERA_ANNOUNCE_READY
  117. while ((ctx->started)&&(((!ctx->preproc)&&(ctx->reported_id == ctx->event_id))||((ctx->preproc)&&(ctx->reported_id == ctx->preproc_id)))) {
  118. #else /* IPECAMERA_ANNOUNCE_READY */
  119. while ((ctx->started)&&(ctx->reported_id == ctx->event_id)) {
  120. #endif /* IPECAMERA_ANNOUNCE_READY */
  121. usleep(IPECAMERA_NOFRAME_SLEEP);
  122. }
  123. } else {
  124. pcilib_calc_deadline(&tv, timeout);
  125. #ifdef IPECAMERA_ANNOUNCE_READY
  126. 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)))) {
  127. #else /* IPECAMERA_ANNOUNCE_READY */
  128. while ((ctx->started)&&(pcilib_calc_time_to_deadline(&tv) > 0)&&(ctx->reported_id == ctx->event_id)) {
  129. #endif /* IPECAMERA_ANNOUNCE_READY */
  130. usleep(IPECAMERA_NOFRAME_SLEEP);
  131. }
  132. }
  133. }
  134. if (ctx->reported_id == ctx->event_id) {
  135. UNLOCK(stream);
  136. ipecamera_debug(API, "ipecamera: next_event timed out");
  137. return PCILIB_ERROR_TIMEOUT;
  138. }
  139. }
  140. retry:
  141. if ((ctx->event_id - ctx->reported_id) > (ctx->buffer_size - IPECAMERA_RESERVE_BUFFERS)) {
  142. 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",
  143. 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);
  144. ctx->reported_id = ctx->event_id - (ctx->buffer_size - 1 - IPECAMERA_RESERVE_BUFFERS);
  145. } else ++ctx->reported_id;
  146. if (evid) *evid = ctx->reported_id;
  147. if (info) {
  148. if (info_size >= sizeof(ipecamera_event_info_t))
  149. memcpy(info, ctx->frame + ((ctx->reported_id-1)%ctx->buffer_size), sizeof(ipecamera_event_info_t));
  150. else if (info_size >= sizeof(pcilib_event_info_t))
  151. memcpy(info, ctx->frame + ((ctx->reported_id-1)%ctx->buffer_size), sizeof(pcilib_event_info_t));
  152. else {
  153. UNLOCK(stream);
  154. ipecamera_debug(API, "ipecamera: next_event returned a error");
  155. return PCILIB_ERROR_INVALID_ARGUMENT;
  156. }
  157. }
  158. if ((ctx->event_id - ctx->reported_id) >= ctx->buffer_size) goto retry;
  159. UNLOCK(stream);
  160. ipecamera_debug(API, "ipecamera: next_event returned");
  161. return 0;
  162. }
  163. pcilib_event_id_t ipecamera_get_last_event_id(ipecamera_t *ctx) {
  164. return ctx->event_id;
  165. }