video.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /*------------------------------------------------------------------------
  2. * Copyright 2007-2009 (c) Jeff Brown <spadix@users.sourceforge.net>
  3. *
  4. * This file is part of the ZBar Bar Code Reader.
  5. *
  6. * The ZBar Bar Code Reader is free software; you can redistribute it
  7. * and/or modify it under the terms of the GNU Lesser Public License as
  8. * published by the Free Software Foundation; either version 2.1 of
  9. * the License, or (at your option) any later version.
  10. *
  11. * The ZBar Bar Code Reader is distributed in the hope that it will be
  12. * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  13. * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Lesser Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser Public License
  17. * along with the ZBar Bar Code Reader; if not, write to the Free
  18. * Software Foundation, Inc., 51 Franklin St, Fifth Floor,
  19. * Boston, MA 02110-1301 USA
  20. *
  21. * http://sourceforge.net/projects/zbar
  22. *------------------------------------------------------------------------*/
  23. #include "video.h"
  24. #include "image.h"
  25. #ifdef HAVE_LIBJPEG
  26. extern struct jpeg_decompress_struct *_zbar_jpeg_decomp_create(void);
  27. extern void _zbar_jpeg_decomp_destroy(struct jpeg_decompress_struct *cinfo);
  28. #endif
  29. static void _zbar_video_recycle_image (zbar_image_t *img)
  30. {
  31. zbar_video_t *vdo = img->src;
  32. assert(vdo);
  33. assert(img->srcidx >= 0);
  34. video_lock(vdo);
  35. if(vdo->images[img->srcidx] != img)
  36. vdo->images[img->srcidx] = img;
  37. if(vdo->active)
  38. vdo->nq(vdo, img);
  39. else
  40. video_unlock(vdo);
  41. }
  42. static void _zbar_video_recycle_shadow (zbar_image_t *img)
  43. {
  44. zbar_video_t *vdo = img->src;
  45. assert(vdo);
  46. assert(img->srcidx == -1);
  47. video_lock(vdo);
  48. img->next = vdo->shadow_image;
  49. vdo->shadow_image = img;
  50. video_unlock(vdo);
  51. }
  52. zbar_video_t *zbar_video_create ()
  53. {
  54. zbar_video_t *vdo = calloc(1, sizeof(zbar_video_t));
  55. if(!vdo)
  56. return(NULL);
  57. err_init(&vdo->err, ZBAR_MOD_VIDEO);
  58. vdo->fd = -1;
  59. (void)_zbar_mutex_init(&vdo->qlock);
  60. /* pre-allocate images */
  61. vdo->num_images = ZBAR_VIDEO_IMAGES_MAX;
  62. vdo->images = calloc(ZBAR_VIDEO_IMAGES_MAX, sizeof(zbar_image_t*));
  63. if(!vdo->images) {
  64. zbar_video_destroy(vdo);
  65. return(NULL);
  66. }
  67. int i;
  68. for(i = 0; i < ZBAR_VIDEO_IMAGES_MAX; i++) {
  69. zbar_image_t *img = vdo->images[i] = zbar_image_create();
  70. if(!img) {
  71. zbar_video_destroy(vdo);
  72. return(NULL);
  73. }
  74. img->refcnt = 0;
  75. img->cleanup = _zbar_video_recycle_image;
  76. img->srcidx = i;
  77. img->src = vdo;
  78. }
  79. return(vdo);
  80. }
  81. void zbar_video_destroy (zbar_video_t *vdo)
  82. {
  83. if(vdo->intf != VIDEO_INVALID)
  84. zbar_video_open(vdo, NULL);
  85. if(vdo->images) {
  86. int i;
  87. for(i = 0; i < ZBAR_VIDEO_IMAGES_MAX; i++)
  88. if(vdo->images[i])
  89. free(vdo->images[i]);
  90. free(vdo->images);
  91. }
  92. while(vdo->shadow_image) {
  93. zbar_image_t *img = vdo->shadow_image;
  94. vdo->shadow_image = img->next;
  95. free((void*)img->data);
  96. img->data = NULL;
  97. free(img);
  98. }
  99. if(vdo->buf)
  100. free(vdo->buf);
  101. if(vdo->formats)
  102. free(vdo->formats);
  103. err_cleanup(&vdo->err);
  104. _zbar_mutex_destroy(&vdo->qlock);
  105. #ifdef HAVE_LIBJPEG
  106. if(vdo->jpeg_img) {
  107. zbar_image_destroy(vdo->jpeg_img);
  108. vdo->jpeg_img = NULL;
  109. }
  110. if(vdo->jpeg) {
  111. _zbar_jpeg_decomp_destroy(vdo->jpeg);
  112. vdo->jpeg = NULL;
  113. }
  114. #endif
  115. free(vdo);
  116. }
  117. int zbar_video_open (zbar_video_t *vdo,
  118. const char *dev)
  119. {
  120. zbar_video_enable(vdo, 0);
  121. video_lock(vdo);
  122. if(vdo->intf != VIDEO_INVALID) {
  123. if(vdo->cleanup) {
  124. vdo->cleanup(vdo);
  125. vdo->cleanup = NULL;
  126. }
  127. zprintf(1, "closed camera (fd=%d)\n", vdo->fd);
  128. vdo->intf = VIDEO_INVALID;
  129. }
  130. video_unlock(vdo);
  131. if(!dev)
  132. return(0);
  133. char *ldev = NULL;
  134. if((unsigned char)dev[0] < 0x10) {
  135. /* default linux device, overloaded for other platforms */
  136. int id = dev[0];
  137. dev = ldev = strdup("/dev/video0");
  138. ldev[10] = '0' + id;
  139. }
  140. int rc = _zbar_video_open(vdo, dev);
  141. if(ldev)
  142. free(ldev);
  143. return(rc);
  144. }
  145. int zbar_video_get_fd (const zbar_video_t *vdo)
  146. {
  147. if(vdo->intf == VIDEO_INVALID)
  148. return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__,
  149. "video device not opened"));
  150. if(vdo->intf != VIDEO_V4L2)
  151. return(err_capture(vdo, SEV_WARNING, ZBAR_ERR_UNSUPPORTED, __func__,
  152. "video driver does not support polling"));
  153. return(vdo->fd);
  154. }
  155. int zbar_video_request_size (zbar_video_t *vdo,
  156. unsigned width,
  157. unsigned height)
  158. {
  159. if(vdo->initialized)
  160. /* FIXME re-init different format? */
  161. return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__,
  162. "already initialized, unable to resize"));
  163. vdo->width = width;
  164. vdo->height = height;
  165. zprintf(1, "request size: %d x %d\n", width, height);
  166. return(0);
  167. }
  168. int zbar_video_request_interface (zbar_video_t *vdo,
  169. int ver)
  170. {
  171. if(vdo->intf != VIDEO_INVALID)
  172. return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__,
  173. "device already opened, unable to change interface"));
  174. vdo->intf = (video_interface_t)ver;
  175. zprintf(1, "request interface version %d\n", vdo->intf);
  176. return(0);
  177. }
  178. int zbar_video_request_iomode (zbar_video_t *vdo,
  179. int iomode)
  180. {
  181. if(vdo->intf != VIDEO_INVALID)
  182. return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__,
  183. "device already opened, unable to change iomode"));
  184. if(iomode < 0 || iomode > VIDEO_USERPTR)
  185. return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__,
  186. "invalid iomode requested"));
  187. vdo->iomode = iomode;
  188. return(0);
  189. }
  190. int zbar_video_get_width (const zbar_video_t *vdo)
  191. {
  192. return(vdo->width);
  193. }
  194. int zbar_video_get_height (const zbar_video_t *vdo)
  195. {
  196. return(vdo->height);
  197. }
  198. uint32_t zbar_video_get_format (const zbar_video_t *vdo)
  199. {
  200. return(vdo->format);
  201. }
  202. static inline int video_init_images (zbar_video_t *vdo)
  203. {
  204. assert(vdo->datalen);
  205. if(vdo->iomode != VIDEO_MMAP) {
  206. assert(!vdo->buf);
  207. vdo->buflen = vdo->num_images * vdo->datalen;
  208. vdo->buf = malloc(vdo->buflen);
  209. if(!vdo->buf)
  210. return(err_capture(vdo, SEV_FATAL, ZBAR_ERR_NOMEM, __func__,
  211. "unable to allocate image buffers"));
  212. zprintf(1, "pre-allocated %d %s buffers size=0x%lx\n", vdo->num_images,
  213. (vdo->iomode == VIDEO_READWRITE) ? "READ" : "USERPTR",
  214. vdo->buflen);
  215. }
  216. int i;
  217. for(i = 0; i < vdo->num_images; i++) {
  218. zbar_image_t *img = vdo->images[i];
  219. img->format = vdo->format;
  220. img->width = vdo->width;
  221. img->height = vdo->height;
  222. if(vdo->iomode != VIDEO_MMAP) {
  223. img->datalen = vdo->datalen;
  224. unsigned long offset = i * vdo->datalen;
  225. img->data = vdo->buf + offset;
  226. zprintf(2, " [%02d] @%08lx\n", i, offset);
  227. }
  228. }
  229. return(0);
  230. }
  231. int zbar_video_init (zbar_video_t *vdo,
  232. unsigned long fmt)
  233. {
  234. if(vdo->initialized)
  235. /* FIXME re-init different format? */
  236. return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__,
  237. "already initialized, re-init unimplemented"));
  238. if(vdo->init(vdo, fmt))
  239. return(-1);
  240. vdo->format = fmt;
  241. if(video_init_images(vdo))
  242. return(-1);
  243. #ifdef HAVE_LIBJPEG
  244. const zbar_format_def_t *vidfmt = _zbar_format_lookup(fmt);
  245. if(vidfmt && vidfmt->group == ZBAR_FMT_JPEG) {
  246. /* prepare for decoding */
  247. if(!vdo->jpeg)
  248. vdo->jpeg = _zbar_jpeg_decomp_create();
  249. if(vdo->jpeg_img)
  250. zbar_image_destroy(vdo->jpeg_img);
  251. /* create intermediate image for decoder to use*/
  252. zbar_image_t *img = vdo->jpeg_img = zbar_image_create();
  253. img->format = fourcc('Y','8','0','0');
  254. img->width = vdo->width;
  255. img->height = vdo->height;
  256. img->datalen = vdo->width * vdo->height;
  257. }
  258. #endif
  259. vdo->initialized = 1;
  260. return(0);
  261. }
  262. int zbar_video_enable (zbar_video_t *vdo,
  263. int enable)
  264. {
  265. if(vdo->active == enable)
  266. return(0);
  267. if(enable) {
  268. if(vdo->intf == VIDEO_INVALID)
  269. return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__,
  270. "video device not opened"));
  271. if(!vdo->initialized &&
  272. zbar_negotiate_format(vdo, NULL))
  273. return(-1);
  274. }
  275. if(video_lock(vdo))
  276. return(-1);
  277. vdo->active = enable;
  278. if(enable) {
  279. /* enqueue all buffers */
  280. int i;
  281. for(i = 0; i < vdo->num_images; i++)
  282. if(vdo->nq(vdo, vdo->images[i]) ||
  283. ((i + 1 < vdo->num_images) && video_lock(vdo)))
  284. return(-1);
  285. return(vdo->start(vdo));
  286. }
  287. else {
  288. int i;
  289. for(i = 0; i < vdo->num_images; i++)
  290. vdo->images[i]->next = NULL;
  291. vdo->nq_image = vdo->dq_image = NULL;
  292. if(video_unlock(vdo))
  293. return(-1);
  294. return(vdo->stop(vdo));
  295. }
  296. }
  297. zbar_image_t *zbar_video_next_image (zbar_video_t *vdo)
  298. {
  299. if(video_lock(vdo))
  300. return(NULL);
  301. if(!vdo->active) {
  302. video_unlock(vdo);
  303. return(NULL);
  304. }
  305. unsigned frame = vdo->frame++;
  306. zbar_image_t *img = vdo->dq(vdo);
  307. if(img) {
  308. img->seq = frame;
  309. if(vdo->num_images < 2) {
  310. /* return a *copy* of the video image and immediately recycle
  311. * the driver's buffer to avoid deadlocking the resources
  312. */
  313. zbar_image_t *tmp = img;
  314. video_lock(vdo);
  315. img = vdo->shadow_image;
  316. vdo->shadow_image = (img) ? img->next : NULL;
  317. video_unlock(vdo);
  318. if(!img) {
  319. img = zbar_image_create();
  320. assert(img);
  321. img->refcnt = 0;
  322. img->src = vdo;
  323. /* recycle the shadow images */
  324. img->format = vdo->format;
  325. img->width = vdo->width;
  326. img->height = vdo->height;
  327. img->datalen = vdo->datalen;
  328. img->data = malloc(vdo->datalen);
  329. }
  330. img->cleanup = _zbar_video_recycle_shadow;
  331. img->seq = frame;
  332. memcpy((void*)img->data, tmp->data, img->datalen);
  333. _zbar_video_recycle_image(tmp);
  334. }
  335. else
  336. img->cleanup = _zbar_video_recycle_image;
  337. _zbar_image_refcnt(img, 1);
  338. }
  339. return(img);
  340. }