data.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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 "private.h"
  16. #include "data.h"
  17. // DS: Currently, on event_id overflow we are assuming the buffer is lost
  18. static int ipecamera_resolve_event_id(ipecamera_t *ctx, pcilib_event_id_t evid) {
  19. pcilib_event_id_t diff;
  20. if (evid > ctx->event_id) {
  21. diff = (((pcilib_event_id_t)-1) - ctx->event_id) + evid;
  22. if (diff >= ctx->buffer_size) return -1;
  23. } else {
  24. diff = ctx->event_id - evid;
  25. if (diff >= ctx->buffer_size) return -1;
  26. }
  27. // DS: Request buffer_size to be power of 2 and replace to shifts (just recompute in set_buffer_size)
  28. return (evid - 1) % ctx->buffer_size;
  29. }
  30. inline static int ipecamera_decode_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) {
  31. int err = 0;
  32. size_t res;
  33. uint16_t *pixels;
  34. int buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
  35. if (buf_ptr < 0) return PCILIB_ERROR_OVERWRITTEN;
  36. if (ctx->frame[buf_ptr].event.image_ready) return 0;
  37. if (ctx->frame[buf_ptr].event.info.flags&PCILIB_EVENT_INFO_FLAG_BROKEN) {
  38. err = PCILIB_ERROR_INVALID_DATA;
  39. ctx->frame[buf_ptr].event.image_broken = err;
  40. goto ready;
  41. }
  42. pixels = ctx->image + buf_ptr * ctx->image_size;
  43. memset(ctx->cmask + ctx->buffer_pos * ctx->dim.height, 0, ctx->dim.height * sizeof(ipecamera_change_mask_t));
  44. ipecamera_debug_buffer(RAW_FRAMES, ctx->frame[buf_ptr].event.raw_size, ctx->buffer + buf_ptr * ctx->padded_size, PCILIB_DEBUG_BUFFER_MKDIR, "raw_frame.%4lu", ctx->event_id);
  45. res = ufo_decoder_decode_frame(ctx->ipedec, ctx->buffer + buf_ptr * ctx->padded_size, ctx->frame[buf_ptr].event.raw_size, pixels, &ctx->frame[buf_ptr].event.meta);
  46. if (!res) {
  47. ipecamera_debug_buffer(BROKEN_FRAMES, ctx->frame[buf_ptr].event.raw_size, ctx->buffer + buf_ptr * ctx->padded_size, PCILIB_DEBUG_BUFFER_MKDIR, "broken_frame.%4lu", ctx->event_id);
  48. err = PCILIB_ERROR_INVALID_DATA;
  49. ctx->frame[buf_ptr].event.image_broken = err;
  50. goto ready;
  51. }
  52. ctx->frame[buf_ptr].event.image_broken = 0;
  53. ready:
  54. ctx->frame[buf_ptr].event.image_ready = 1;
  55. if (ipecamera_resolve_event_id(ctx, event_id) < 0) {
  56. ctx->frame[buf_ptr].event.image_ready = 0;
  57. return PCILIB_ERROR_OVERWRITTEN;
  58. }
  59. return err;
  60. }
  61. static int ipecamera_get_next_buffer_to_process(ipecamera_t *ctx, pcilib_event_id_t *evid) {
  62. int err, res;
  63. if (ctx->preproc_id == ctx->event_id) return -1;
  64. if (ctx->preproc)
  65. pthread_mutex_lock(&ctx->preproc_mutex);
  66. if (ctx->preproc_id == ctx->event_id) {
  67. if (ctx->preproc)
  68. pthread_mutex_unlock(&ctx->preproc_mutex);
  69. return -1;
  70. }
  71. if ((ctx->event_id - ctx->preproc_id) > (ctx->buffer_size - IPECAMERA_RESERVE_BUFFERS)) {
  72. size_t preproc_id = ctx->preproc_id;
  73. ctx->preproc_id = ctx->event_id - (ctx->buffer_size - 1 - IPECAMERA_RESERVE_BUFFERS - 1);
  74. ipecamera_debug(HARDWARE, "Skipping preprocessing of events %zu to %zu as decoding is not fast enough. We are currently %zu buffers beyond, but only %zu buffers are available and safety limit is %zu",
  75. preproc_id, ctx->preproc_id - 1, ctx->event_id - ctx->preproc_id, ctx->buffer_size, IPECAMERA_RESERVE_BUFFERS);
  76. }
  77. res = ctx->preproc_id%ctx->buffer_size;
  78. if ((err = pthread_rwlock_trywrlock(&ctx->frame[res].mutex)) != 0) {
  79. if (ctx->preproc)
  80. pthread_mutex_unlock(&ctx->preproc_mutex);
  81. ipecamera_debug(HARDWARE, "Can't lock buffer %i, errno %i", res, err);
  82. return -1;
  83. }
  84. *evid = ++ctx->preproc_id;
  85. if (ctx->preproc)
  86. pthread_mutex_unlock(&ctx->preproc_mutex);
  87. return res;
  88. }
  89. void *ipecamera_preproc_thread(void *user) {
  90. int err;
  91. int buf_ptr;
  92. pcilib_event_id_t evid;
  93. ipecamera_preprocessor_t *preproc = (ipecamera_preprocessor_t*)user;
  94. ipecamera_t *ctx = preproc->ipecamera;
  95. while (ctx->run_preprocessors) {
  96. buf_ptr = ipecamera_get_next_buffer_to_process(ctx, &evid);
  97. if (buf_ptr < 0) {
  98. usleep(IPECAMERA_NOFRAME_PREPROC_SLEEP);
  99. continue;
  100. }
  101. err = ipecamera_decode_frame(ctx, evid);
  102. pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
  103. #ifdef IPECAMERA_DEBUG_HARDWARE
  104. if (err) {
  105. switch (err) {
  106. case PCILIB_ERROR_OVERWRITTEN:
  107. ipecamera_debug(HARDWARE, "The frame (%zu) was overwritten while preprocessing", evid);
  108. break;
  109. case PCILIB_ERROR_INVALID_DATA:
  110. ipecamera_debug(HARDWARE, "The frame (%zu) is corrupted, decoding have failed", evid);
  111. break;
  112. default:
  113. ipecamera_debug(HARDWARE, "The frame (%zu) is corrupted, decoding have failed", evid);
  114. }
  115. }
  116. }
  117. #endif /* IPECAMERA_DEBUG_HARDWARE */
  118. return NULL;
  119. }
  120. static int ipecamera_get_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) {
  121. int err;
  122. int buf_ptr = (event_id - 1) % ctx->buffer_size;
  123. if (!ctx->preproc) {
  124. pthread_rwlock_rdlock(&ctx->frame[buf_ptr].mutex);
  125. err = ipecamera_decode_frame(ctx, event_id);
  126. if (err) {
  127. pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
  128. return err;
  129. }
  130. return 0;
  131. }
  132. while (!((volatile ipecamera_t*)ctx)->frame[buf_ptr].event.image_ready) {
  133. usleep(IPECAMERA_NOFRAME_PREPROC_SLEEP);
  134. buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
  135. if (buf_ptr < 0) return PCILIB_ERROR_OVERWRITTEN;
  136. }
  137. if (((volatile ipecamera_t*)ctx)->frame[buf_ptr].event.image_broken)
  138. return ctx->frame[buf_ptr].event.image_broken;
  139. pthread_rwlock_rdlock(&ctx->frame[buf_ptr].mutex);
  140. buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
  141. if ((buf_ptr < 0)||(!ctx->frame[buf_ptr].event.image_ready)) {
  142. pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
  143. return PCILIB_ERROR_OVERWRITTEN;
  144. }
  145. return 0;
  146. }
  147. /*
  148. We will lock the data for non-raw data to prevent ocasional overwritting. The
  149. raw data will be overwritten by the reader thread anyway and we can't do
  150. anything to prevent it for performance reasons.
  151. */
  152. 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) {
  153. int err;
  154. int buf_ptr;
  155. size_t raw_size;
  156. ipecamera_t *ctx = (ipecamera_t*)vctx;
  157. void *data = *ret;
  158. if (!ctx) {
  159. pcilib_error("IPECamera imaging is not initialized");
  160. return PCILIB_ERROR_NOTINITIALIZED;
  161. }
  162. ipecamera_debug(API, "ipecamera: get (data)");
  163. buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
  164. if (buf_ptr < 0) {
  165. ipecamera_debug(HARDWARE, "The data of the requested frame %zu has been meanwhile overwritten", event_id);
  166. return PCILIB_ERROR_OVERWRITTEN;
  167. }
  168. switch ((ipecamera_data_type_t)data_type) {
  169. case IPECAMERA_RAW_DATA:
  170. raw_size = ctx->frame[buf_ptr].event.raw_size;
  171. if (data) {
  172. if ((!size)||(*size < raw_size)) {
  173. pcilib_warning("The raw data associated with frame %zu is too big (%zu bytes) for user supplied buffer (%zu bytes)", event_id, raw_size, (size?*size:0));
  174. return PCILIB_ERROR_TOOBIG;
  175. }
  176. memcpy(data, ctx->buffer + buf_ptr * ctx->padded_size, raw_size);
  177. if (ipecamera_resolve_event_id(ctx, event_id) < 0) {
  178. ipecamera_debug(HARDWARE, "The data of requested frame %zu was overwritten while copying", event_id);
  179. return PCILIB_ERROR_OVERWRITTEN;
  180. }
  181. *size = raw_size;
  182. return 0;
  183. }
  184. if (size) *size = raw_size;
  185. *ret = ctx->buffer + buf_ptr * ctx->padded_size;
  186. return 0;
  187. case IPECAMERA_IMAGE_DATA:
  188. err = ipecamera_get_frame(ctx, event_id);
  189. if (err) {
  190. #ifdef IPECAMERA_DEBUG_HARDWARE
  191. switch (err) {
  192. case PCILIB_ERROR_OVERWRITTEN:
  193. ipecamera_debug(HARDWARE, "The requested frame (%zu) was overwritten", event_id);
  194. break;
  195. case PCILIB_ERROR_INVALID_DATA:
  196. ipecamera_debug(HARDWARE, "The requested frame (%zu) is corrupted", event_id);
  197. break;
  198. default:
  199. ipecamera_debug(HARDWARE, "Error getting the data associated with the requested frame (%zu), error %i", event_id, err);
  200. }
  201. #endif /* IPECAMERA_DEBUG_HARDWARE */
  202. return err;
  203. }
  204. if (data) {
  205. if ((!size)||(*size < ctx->image_size * sizeof(ipecamera_pixel_t))) {
  206. pcilib_warning("The image associated with frame %zu is too big (%zu bytes) for user supplied buffer (%zu bytes)", event_id, ctx->image_size * sizeof(ipecamera_pixel_t), (size?*size:0));
  207. return PCILIB_ERROR_TOOBIG;
  208. }
  209. memcpy(data, ctx->image + buf_ptr * ctx->image_size, ctx->image_size * sizeof(ipecamera_pixel_t));
  210. pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
  211. *size = ctx->image_size * sizeof(ipecamera_pixel_t);
  212. return 0;
  213. }
  214. if (size) *size = ctx->image_size * sizeof(ipecamera_pixel_t);
  215. *ret = ctx->image + buf_ptr * ctx->image_size;
  216. return 0;
  217. case IPECAMERA_CHANGE_MASK:
  218. err = ipecamera_get_frame(ctx, event_id);
  219. if (err) return err;
  220. if (data) {
  221. if ((!size)||(*size < ctx->dim.height * sizeof(ipecamera_change_mask_t))) return PCILIB_ERROR_TOOBIG;
  222. memcpy(data, ctx->image + buf_ptr * ctx->dim.height, ctx->dim.height * sizeof(ipecamera_change_mask_t));
  223. pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
  224. *size = ctx->dim.height * sizeof(ipecamera_change_mask_t);
  225. return 0;
  226. }
  227. if (size) *size = ctx->dim.height * sizeof(ipecamera_change_mask_t);
  228. *ret = ctx->cmask + buf_ptr * ctx->dim.height;
  229. return 0;
  230. case IPECAMERA_DIMENSIONS:
  231. if (size) *size = sizeof(ipecamera_image_dimensions_t);
  232. ret = (void*)&ctx->dim;
  233. return 0;
  234. case IPECAMERA_IMAGE_REGION:
  235. case IPECAMERA_PACKED_IMAGE:
  236. // Shall we return complete image or only changed parts?
  237. case IPECAMERA_PACKED_LINE:
  238. case IPECAMERA_PACKED_PAYLOAD:
  239. pcilib_error("Support for data type (%li) is not implemented yet", data_type);
  240. return PCILIB_ERROR_NOTSUPPORTED;
  241. default:
  242. pcilib_error("Unknown data type (%li) is requested", data_type);
  243. return PCILIB_ERROR_INVALID_REQUEST;
  244. }
  245. }
  246. /*
  247. We will unlock non-raw data and check if the raw data is not overwritten yet
  248. */
  249. int ipecamera_return(pcilib_context_t *vctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, void *data) {
  250. ipecamera_t *ctx = (ipecamera_t*)vctx;
  251. if (!ctx) {
  252. pcilib_error("IPECamera imaging is not initialized");
  253. return PCILIB_ERROR_NOTINITIALIZED;
  254. }
  255. if ((ipecamera_data_type_t)data_type == IPECAMERA_RAW_DATA) {
  256. if (ipecamera_resolve_event_id(ctx, event_id) < 0) return PCILIB_ERROR_OVERWRITTEN;
  257. } else {
  258. int buf_ptr = (event_id - 1) % ctx->buffer_size;
  259. pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
  260. }
  261. ipecamera_debug(API, "ipecamera: return (data)");
  262. return 0;
  263. }