data.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. #define _BSD_SOURCE
  2. #define _GNU_SOURCE
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include <sys/time.h>
  8. #include <pthread.h>
  9. #include <assert.h>
  10. #include <ufodecode.h>
  11. #include <pcilib.h>
  12. #include <pcilib/tools.h>
  13. #include <pcilib/error.h>
  14. #include "private.h"
  15. #include "data.h"
  16. // DS: Currently, on event_id overflow we are assuming the buffer is lost
  17. static int ipecamera_resolve_event_id(ipecamera_t *ctx, pcilib_event_id_t evid) {
  18. pcilib_event_id_t diff;
  19. if (evid > ctx->event_id) {
  20. diff = (((pcilib_event_id_t)-1) - ctx->event_id) + evid;
  21. if (diff >= ctx->buffer_size) return -1;
  22. } else {
  23. diff = ctx->event_id - evid;
  24. if (diff >= ctx->buffer_size) return -1;
  25. }
  26. // DS: Request buffer_size to be power of 2 and replace to shifts (just recompute in set_buffer_size)
  27. return (evid - 1) % ctx->buffer_size;
  28. }
  29. inline static int ipecamera_decode_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) {
  30. int err = 0;
  31. size_t res;
  32. uint16_t *pixels;
  33. int buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
  34. if (buf_ptr < 0) return PCILIB_ERROR_TIMEOUT;
  35. if (ctx->frame[buf_ptr].event.image_ready) return 0;
  36. if (ctx->frame[buf_ptr].event.info.flags&PCILIB_EVENT_INFO_FLAG_BROKEN) {
  37. err = PCILIB_ERROR_INVALID_DATA;
  38. ctx->frame[buf_ptr].event.image_broken = err;
  39. goto ready;
  40. }
  41. pixels = ctx->image + buf_ptr * ctx->image_size;
  42. memset(ctx->cmask + ctx->buffer_pos * ctx->dim.height, 0, ctx->dim.height * sizeof(ipecamera_change_mask_t));
  43. 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);
  44. 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);
  45. if (!res) {
  46. 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);
  47. err = PCILIB_ERROR_FAILED;
  48. ctx->frame[buf_ptr].event.image_broken = err;
  49. goto ready;
  50. }
  51. ctx->frame[buf_ptr].event.image_broken = 0;
  52. ready:
  53. ctx->frame[buf_ptr].event.image_ready = 1;
  54. if (ipecamera_resolve_event_id(ctx, event_id) < 0) {
  55. ctx->frame[buf_ptr].event.image_ready = 0;
  56. return PCILIB_ERROR_TIMEOUT;
  57. }
  58. return err;
  59. }
  60. static int ipecamera_get_next_buffer_to_process(ipecamera_t *ctx, pcilib_event_id_t *evid) {
  61. int res;
  62. if (ctx->preproc_id == ctx->event_id) return -1;
  63. if (ctx->preproc)
  64. pthread_mutex_lock(&ctx->preproc_mutex);
  65. if (ctx->preproc_id == ctx->event_id) {
  66. if (ctx->preproc)
  67. pthread_mutex_unlock(&ctx->preproc_mutex);
  68. return -1;
  69. }
  70. 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);
  71. res = ctx->preproc_id%ctx->buffer_size;
  72. if (pthread_rwlock_trywrlock(&ctx->frame[res].mutex)) {
  73. pthread_mutex_unlock(&ctx->preproc_mutex);
  74. return -1;
  75. }
  76. *evid = ++ctx->preproc_id;
  77. if (ctx->preproc)
  78. pthread_mutex_unlock(&ctx->preproc_mutex);
  79. return res;
  80. }
  81. void *ipecamera_preproc_thread(void *user) {
  82. int buf_ptr;
  83. pcilib_event_id_t evid;
  84. ipecamera_preprocessor_t *preproc = (ipecamera_preprocessor_t*)user;
  85. ipecamera_t *ctx = preproc->ipecamera;
  86. while (ctx->run_preprocessors) {
  87. buf_ptr = ipecamera_get_next_buffer_to_process(ctx, &evid);
  88. if (buf_ptr < 0) {
  89. usleep(IPECAMERA_NOFRAME_PREPROC_SLEEP);
  90. continue;
  91. }
  92. ipecamera_decode_frame(ctx, evid);
  93. pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
  94. }
  95. return NULL;
  96. }
  97. static int ipecamera_get_frame(ipecamera_t *ctx, pcilib_event_id_t event_id) {
  98. int err;
  99. int buf_ptr = (event_id - 1) % ctx->buffer_size;
  100. if (ctx->preproc) {
  101. if (ctx->frame[buf_ptr].event.image_broken)
  102. return ctx->frame[buf_ptr].event.image_broken;
  103. } else {
  104. pthread_rwlock_rdlock(&ctx->frame[buf_ptr].mutex);
  105. err = ipecamera_decode_frame(ctx, event_id);
  106. if (err) {
  107. pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
  108. return err;
  109. }
  110. return 0;
  111. }
  112. while (!ctx->frame[buf_ptr].event.image_ready) {
  113. usleep(IPECAMERA_NOFRAME_PREPROC_SLEEP);
  114. buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
  115. if (buf_ptr < 0) return PCILIB_ERROR_OVERWRITTEN;
  116. }
  117. pthread_rwlock_rdlock(&ctx->frame[buf_ptr].mutex);
  118. buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
  119. if ((buf_ptr < 0)||(!ctx->frame[buf_ptr].event.image_ready)) {
  120. pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
  121. return PCILIB_ERROR_OVERWRITTEN;
  122. }
  123. return 0;
  124. }
  125. /*
  126. We will lock the data for non-raw data to prevent ocasional overwritting. The
  127. raw data will be overwritten by the reader thread anyway and we can't do
  128. anything to prevent it for performance reasons.
  129. */
  130. 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) {
  131. int err;
  132. int buf_ptr;
  133. size_t raw_size;
  134. ipecamera_t *ctx = (ipecamera_t*)vctx;
  135. void *data = *ret;
  136. if (!ctx) {
  137. pcilib_error("IPECamera imaging is not initialized");
  138. return PCILIB_ERROR_NOTINITIALIZED;
  139. }
  140. ipecamera_debug(API, "ipecamera: get (data)");
  141. buf_ptr = ipecamera_resolve_event_id(ctx, event_id);
  142. if (buf_ptr < 0) return PCILIB_ERROR_OVERWRITTEN;
  143. switch ((ipecamera_data_type_t)data_type) {
  144. case IPECAMERA_RAW_DATA:
  145. raw_size = ctx->frame[buf_ptr].event.raw_size;
  146. if (data) {
  147. if ((!size)||(*size < raw_size)) return PCILIB_ERROR_TOOBIG;
  148. memcpy(data, ctx->buffer + buf_ptr * ctx->padded_size, raw_size);
  149. if (ipecamera_resolve_event_id(ctx, event_id) < 0) return PCILIB_ERROR_OVERWRITTEN;
  150. *size = raw_size;
  151. return 0;
  152. }
  153. if (size) *size = raw_size;
  154. *ret = ctx->buffer + buf_ptr * ctx->padded_size;
  155. return 0;
  156. case IPECAMERA_IMAGE_DATA:
  157. err = ipecamera_get_frame(ctx, event_id);
  158. if (err) return err;
  159. if (data) {
  160. if ((!size)||(*size < ctx->image_size * sizeof(ipecamera_pixel_t))) return PCILIB_ERROR_TOOBIG;
  161. memcpy(data, ctx->image + buf_ptr * ctx->image_size, ctx->image_size * sizeof(ipecamera_pixel_t));
  162. pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
  163. *size = ctx->image_size * sizeof(ipecamera_pixel_t);
  164. return 0;
  165. }
  166. if (size) *size = ctx->image_size * sizeof(ipecamera_pixel_t);
  167. *ret = ctx->image + buf_ptr * ctx->image_size;
  168. return 0;
  169. case IPECAMERA_CHANGE_MASK:
  170. err = ipecamera_get_frame(ctx, event_id);
  171. if (err) return err;
  172. if (data) {
  173. if ((!size)||(*size < ctx->dim.height * sizeof(ipecamera_change_mask_t))) return PCILIB_ERROR_TOOBIG;
  174. memcpy(data, ctx->image + buf_ptr * ctx->dim.height, ctx->dim.height * sizeof(ipecamera_change_mask_t));
  175. pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
  176. *size = ctx->dim.height * sizeof(ipecamera_change_mask_t);
  177. return 0;
  178. }
  179. if (size) *size = ctx->dim.height * sizeof(ipecamera_change_mask_t);
  180. *ret = ctx->cmask + buf_ptr * ctx->dim.height;
  181. return 0;
  182. case IPECAMERA_DIMENSIONS:
  183. if (size) *size = sizeof(ipecamera_image_dimensions_t);
  184. ret = (void*)&ctx->dim;
  185. return 0;
  186. case IPECAMERA_IMAGE_REGION:
  187. case IPECAMERA_PACKED_IMAGE:
  188. // Shall we return complete image or only changed parts?
  189. case IPECAMERA_PACKED_LINE:
  190. case IPECAMERA_PACKED_PAYLOAD:
  191. pcilib_error("Support for data type (%li) is not implemented yet", data_type);
  192. return PCILIB_ERROR_NOTSUPPORTED;
  193. default:
  194. pcilib_error("Unknown data type (%li) is requested", data_type);
  195. return PCILIB_ERROR_INVALID_REQUEST;
  196. }
  197. }
  198. /*
  199. We will unlock non-raw data and check if the raw data is not overwritten yet
  200. */
  201. int ipecamera_return(pcilib_context_t *vctx, pcilib_event_id_t event_id, pcilib_event_data_type_t data_type, void *data) {
  202. ipecamera_t *ctx = (ipecamera_t*)vctx;
  203. if (!ctx) {
  204. pcilib_error("IPECamera imaging is not initialized");
  205. return PCILIB_ERROR_NOTINITIALIZED;
  206. }
  207. if ((ipecamera_data_type_t)data_type == IPECAMERA_RAW_DATA) {
  208. if (ipecamera_resolve_event_id(ctx, event_id) < 0) return PCILIB_ERROR_OVERWRITTEN;
  209. } else {
  210. int buf_ptr = (event_id - 1) % ctx->buffer_size;
  211. pthread_rwlock_unlock(&ctx->frame[buf_ptr].mutex);
  212. }
  213. ipecamera_debug(API, "ipecamera: return (data)");
  214. return 0;
  215. }