int zbar_processor_set_active (zbar_processor_t *proc, int active) { proc_enter(proc); int rc; if(!proc->video) { rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "video input not initialized"); goto done; } _zbar_mutex_unlock(&proc->mutex); zbar_image_scanner_enable_cache(proc->scanner, active); rc = zbar_video_enable(proc->video, active); if(!rc) { _zbar_mutex_lock(&proc->mutex); proc->streaming = active; _zbar_mutex_unlock(&proc->mutex); rc = _zbar_processor_enable(proc); } else err_copy(proc, proc->video); if(!proc->streaming && proc->window) { if(zbar_window_draw(proc->window, NULL) && !rc) rc = err_copy(proc, proc->window); _zbar_processor_invalidate(proc); } _zbar_mutex_lock(&proc->mutex); if(proc->video_thread.started) _zbar_event_trigger(&proc->video_thread.notify); done: proc_leave(proc); return(rc); }
/* lock is already held */ static inline int process_image (zebra_processor_t *proc, zebra_image_t *img) { if(img) { uint32_t format = zebra_image_get_format(img); zprintf(16, "processing: %.4s(%08" PRIx32 ") %dx%d @%p\n", (char*)&format, format, zebra_image_get_width(img), zebra_image_get_height(img), zebra_image_get_data(img)); /* FIXME locking all other interfaces while processing is conservative * but easier for now and we don't expect this to take long... */ int nsyms = zebra_scan_image(proc->scanner, img); if(nsyms < 0) return(err_capture(proc, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, __func__, "unknown image format")); if(_zebra_verbosity >= 8) { const zebra_symbol_t *sym = zebra_image_first_symbol(img); while(sym) { zebra_symbol_type_t type = zebra_symbol_get_type(sym); int count = zebra_symbol_get_count(sym); zprintf(8, "%s%s: %s (%s)\n", zebra_get_symbol_name(type), zebra_get_addon_name(type), zebra_symbol_get_data(sym), (count < 0) ? "uncertain" : (count > 0) ? "duplicate" : "new"); sym = zebra_symbol_next(sym); } } if(nsyms) { emit(proc, EVENT_OUTPUT); if(proc->handler) /* FIXME only call after filtering (unlocked...?) */ proc->handler(img, proc->userdata); } if(proc->force_output) { img = zebra_image_convert(img, proc->force_output); if(!img) return(err_capture(proc, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, __func__, "unknown image format")); } } /* display to window if enabled */ if(proc->window && (zebra_window_draw(proc->window, img) || _zebra_window_invalidate(proc->window))) return(err_copy(proc, proc->window)); #if 0 /* FIXME still don't understand why we need this */ if(proc->window && _zebra_window_handle_events(proc, 0)) return(-1); #endif if(proc->force_output && img) zebra_image_destroy(img); return(0); }
int zebra_processor_init (zebra_processor_t *proc, const char *dev, int enable_display) { if(proc_lock(proc) < 0) return(-1); proc_destroy_thread(proc->video_thread, &proc->video_started); proc_destroy_thread(proc->input_thread, &proc->input_started); proc->video_started = proc->input_started = 0; int rc = 0; if(proc->video) { if(dev) zebra_video_open(proc->video, NULL); else { zebra_video_destroy(proc->video); proc->video = NULL; } } if(proc->window) { zebra_window_destroy(proc->window); proc->window = NULL; _zebra_window_close(proc); } if(!dev && !enable_display) /* nothing to do */ goto done; if(enable_display) { proc->window = zebra_window_create(); if(!proc->window) { rc = err_copy(proc, proc->window); goto done; } } if(dev) { proc->video = zebra_video_create(); if(!proc->video || zebra_video_open(proc->video, dev)) { rc = err_copy(proc, proc->video); goto done; } if(zebra_video_get_fd(proc->video) < 0 && proc->threaded) { #ifdef HAVE_LIBPTHREAD /* spawn blocking video thread */ if((rc = pthread_create(&proc->video_thread, NULL, proc_video_thread, proc))) { rc = err_capture_num(proc, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, "spawning video thread", rc); goto done; } proc->video_started = 1; zprintf(4, "spawned video thread\n"); #endif } } #ifdef HAVE_LIBPTHREAD if(proc->threaded && (proc->window || (proc->video && !proc->video_started))) { /* spawn input monitor thread */ if((rc = pthread_create(&proc->input_thread, NULL, proc_input_thread, proc))) { rc = err_capture_num(proc, SEV_ERROR, ZEBRA_ERR_SYSTEM, __func__, "spawning input thread", rc); goto done; } proc->input_started = 1; zprintf(4, "spawned input thread\n"); } #endif if(proc->window) { /* arbitrary default */ int width = 640, height = 480; if(proc->video) { width = zebra_video_get_width(proc->video); height = zebra_video_get_height(proc->video); } if(_zebra_window_open(proc, "zebra barcode reader", width, height)) { rc = -1; goto done; } else if(zebra_window_attach(proc->window, proc->display, proc->xwin)) { rc = err_copy(proc, proc->window); goto done; } } if(proc->video && proc->force_input) { if(zebra_video_init(proc->video, proc->force_input)) rc = err_copy(proc, proc->video); } else if(proc->video) while(zebra_negotiate_format(proc->video, proc->window)) { if(proc->video && proc->window) { fprintf(stderr, "WARNING: no compatible input to output format\n" "...trying again with output disabled\n"); zebra_window_destroy(proc->window); proc->window = NULL; } else { zprintf(1, "ERROR: no compatible %s format\n", (proc->video) ? "video input" : "window output"); rc = err_capture(proc, SEV_ERROR, ZEBRA_ERR_UNSUPPORTED, __func__, "no compatible image format"); goto done; } } done: proc_unlock(proc); return(rc); }
/* API lock is already held */ int _zbar_process_image (zbar_processor_t *proc, zbar_image_t *img) { uint32_t force_fmt = proc->force_output; if(img) { if(proc->dumping) { zbar_image_write(proc->window->image, "zbar"); proc->dumping = 0; } uint32_t format = zbar_image_get_format(img); zprintf(16, "processing: %.4s(%08" PRIx32 ") %dx%d @%p\n", (char*)&format, format, zbar_image_get_width(img), zbar_image_get_height(img), zbar_image_get_data(img)); /* FIXME locking all other interfaces while processing is conservative * but easier for now and we don't expect this to take long... */ zbar_image_t *tmp = zbar_image_convert(img, fourcc('Y','8','0','0')); if(!tmp) goto error; if(proc->syms) { zbar_symbol_set_ref(proc->syms, -1); proc->syms = NULL; } zbar_image_scanner_recycle_image(proc->scanner, img); int nsyms = zbar_scan_image(proc->scanner, tmp); _zbar_image_swap_symbols(img, tmp); zbar_image_destroy(tmp); tmp = NULL; if(nsyms < 0) goto error; proc->syms = zbar_image_scanner_get_results(proc->scanner); if(proc->syms) zbar_symbol_set_ref(proc->syms, 1); if(_zbar_verbosity >= 8) { const zbar_symbol_t *sym = zbar_image_first_symbol(img); while(sym) { zbar_symbol_type_t type = zbar_symbol_get_type(sym); int count = zbar_symbol_get_count(sym); zprintf(8, "%s: %s (%d pts) (dir=%d) (q=%d) (%s)\n", zbar_get_symbol_name(type), zbar_symbol_get_data(sym), zbar_symbol_get_loc_size(sym), zbar_symbol_get_orientation(sym), zbar_symbol_get_quality(sym), (count < 0) ? "uncertain" : (count > 0) ? "duplicate" : "new"); sym = zbar_symbol_next(sym); } } if(nsyms) { /* FIXME only call after filtering */ _zbar_mutex_lock(&proc->mutex); _zbar_processor_notify(proc, EVENT_OUTPUT); _zbar_mutex_unlock(&proc->mutex); if(proc->handler) proc->handler(img, proc->userdata); } if(force_fmt) { zbar_symbol_set_t *syms = img->syms; img = zbar_image_convert(img, force_fmt); if(!img) goto error; img->syms = syms; zbar_symbol_set_ref(syms, 1); } } /* display to window if enabled */ int rc = 0; if(proc->window) { if((rc = zbar_window_draw(proc->window, img))) err_copy(proc, proc->window); _zbar_processor_invalidate(proc); } if(force_fmt && img) zbar_image_destroy(img); return(rc); error: return(err_capture(proc, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "unknown image format")); }
int zbar_processor_init (zbar_processor_t *proc, const char *dev, int enable_display) { if(proc->video) zbar_processor_set_active(proc, 0); if(proc->window && !proc->input_thread.started) _zbar_processor_close(proc); _zbar_mutex_lock(&proc->mutex); _zbar_thread_stop(&proc->input_thread, &proc->mutex); _zbar_thread_stop(&proc->video_thread, &proc->mutex); _zbar_processor_lock(proc); _zbar_mutex_unlock(&proc->mutex); if(proc->window) { zbar_window_destroy(proc->window); proc->window = NULL; } int rc = 0; if(proc->video) { zbar_video_destroy(proc->video); proc->video = NULL; } if(!dev && !enable_display) /* nothing to do */ goto done; if(enable_display) { proc->window = zbar_window_create(); if(!proc->window) { rc = err_capture(proc, SEV_FATAL, ZBAR_ERR_NOMEM, __func__, "allocating window resources"); goto done; } } if(dev) { proc->video = zbar_video_create(); if(!proc->video) { rc = err_capture(proc, SEV_FATAL, ZBAR_ERR_NOMEM, __func__, "allocating video resources"); goto done; } if(proc->req_width || proc->req_height) zbar_video_request_size(proc->video, proc->req_width, proc->req_height); if(proc->req_intf) zbar_video_request_interface(proc->video, proc->req_intf); if((proc->req_iomode && zbar_video_request_iomode(proc->video, proc->req_iomode)) || zbar_video_open(proc->video, dev)) { rc = err_copy(proc, proc->video); goto done; } } /* spawn blocking video thread */ int video_threaded = (proc->threaded && proc->video && zbar_video_get_fd(proc->video) < 0); if(video_threaded && _zbar_thread_start(&proc->video_thread, proc_video_thread, proc, &proc->mutex)) { rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "spawning video thread"); goto done; } /* spawn input monitor thread */ int input_threaded = (proc->threaded && (proc->window || (proc->video && !video_threaded))); if(input_threaded && _zbar_thread_start(&proc->input_thread, proc_input_thread, proc, &proc->mutex)) { rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "spawning input thread"); goto done; } if(proc->window && !input_threaded && (rc = proc_open(proc))) goto done; if(proc->video && proc->force_input) { if(zbar_video_init(proc->video, proc->force_input)) rc = err_copy(proc, proc->video); } else if(proc->video) { int retry = -1; if(proc->window) { retry = zbar_negotiate_format(proc->video, proc->window); if(retry) fprintf(stderr, "WARNING: no compatible input to output format\n" "...trying again with output disabled\n"); } if(retry) retry = zbar_negotiate_format(proc->video, NULL); if(retry) { zprintf(1, "ERROR: no compatible %s format\n", (proc->video) ? "video input" : "window output"); rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "no compatible image format"); } } done: _zbar_mutex_lock(&proc->mutex); proc_leave(proc); return(rc); }