static inline int v4l2_reset_crop (zbar_video_t *vdo) { /* check cropping */ struct v4l2_cropcap ccap; memset(&ccap, 0, sizeof(ccap)); ccap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(ioctl(vdo->fd, VIDIOC_CROPCAP, &ccap) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying crop support (VIDIOC_CROPCAP)")); zprintf(1, "crop bounds: %d x %d @ (%d, %d)\n", ccap.bounds.width, ccap.bounds.height, ccap.bounds.left, ccap.bounds.top); zprintf(1, "current crop win: %d x %d @ (%d, %d) aspect %d / %d\n", ccap.defrect.width, ccap.defrect.height, ccap.defrect.left, ccap.defrect.top, ccap.pixelaspect.numerator, ccap.pixelaspect.denominator); if(!vdo->width || !vdo->height) { vdo->width = ccap.defrect.width; vdo->height = ccap.defrect.height; } /* reset crop parameters */ struct v4l2_crop crop; memset(&crop, 0, sizeof(crop)); crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c = ccap.defrect; if(ioctl(vdo->fd, VIDIOC_S_CROP, &crop) < 0 && errno != EINVAL) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "setting default crop window (VIDIOC_S_CROP)")); return(0); }
int _zbar_processor_open (zbar_processor_t *proc, char *title, unsigned width, unsigned height) { HMODULE hmod = NULL; if(!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (void*)_zbar_processor_open, (HINSTANCE*)&hmod)) return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, "failed to obtain module handle")); ATOM wca = win_register_class(hmod); if(!wca) return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, "failed to register window class")); RECT r = { 0, 0, width, height }; AdjustWindowRectEx(&r, WIN_STYLE, 0, EXT_STYLE); proc->display = CreateWindowEx(EXT_STYLE, (LPCTSTR)(long)wca, "ZBar", WIN_STYLE, CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, NULL, NULL, hmod, proc); if(!proc->display) return(err_capture(proc, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, "failed to open window")); return(0); }
static int v4l2_set_format (zbar_video_t *vdo, uint32_t fmt) { struct v4l2_format vfmt; struct v4l2_pix_format *vpix = &vfmt.fmt.pix; memset(&vfmt, 0, sizeof(vfmt)); vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; vpix->width = vdo->width; vpix->height = vdo->height; vpix->pixelformat = fmt; vpix->field = V4L2_FIELD_NONE; int rc = 0; if((rc = ioctl(vdo->fd, VIDIOC_S_FMT, &vfmt)) < 0) { /* several broken drivers return an error if we request * no interlacing (NB v4l2 spec violation) * ...try again with an interlaced request */ zprintf(1, "VIDIOC_S_FMT returned %d(%d), trying interlaced...\n", rc, errno); /* FIXME this might be _ANY once we can de-interlace */ vpix->field = V4L2_FIELD_INTERLACED; if(ioctl(vdo->fd, VIDIOC_S_FMT, &vfmt) < 0) return(err_capture_int(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "setting format %x (VIDIOC_S_FMT)", fmt)); zprintf(0, "WARNING: broken driver returned error when non-interlaced" " format requested\n"); } struct v4l2_format newfmt; struct v4l2_pix_format *newpix = &newfmt.fmt.pix; memset(&newfmt, 0, sizeof(newfmt)); newfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(ioctl(vdo->fd, VIDIOC_G_FMT, &newfmt) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying format (VIDIOC_G_FMT)")); if(newpix->field != V4L2_FIELD_NONE) err_capture(vdo, SEV_WARNING, ZBAR_ERR_INVALID, __func__, "video driver only supports interlaced format," " vertical scanning may not work"); if(newpix->pixelformat != fmt /* FIXME bpl/bpp checks? */) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "video driver can't provide compatible format")); vdo->format = fmt; vdo->width = newpix->width; vdo->height = newpix->height; vdo->datalen = newpix->sizeimage; zprintf(1, "set new format: %.4s(%08x) %u x %u (0x%lx)\n", (char*)&vdo->format, vdo->format, vdo->width, vdo->height, vdo->datalen); return(0); }
int _zbar_v4l2_probe (zbar_video_t *vdo) { /* check capabilities */ struct v4l2_capability vcap; memset(&vcap, 0, sizeof(vcap)); if(ioctl(vdo->fd, VIDIOC_QUERYCAP, &vcap) < 0) return(err_capture(vdo, SEV_WARNING, ZBAR_ERR_UNSUPPORTED, __func__, "video4linux version 2 not supported (VIDIOC_QUERYCAP)")); zprintf(1, "%.32s on %.32s driver %.16s (version %u.%u.%u)\n", vcap.card, (vcap.bus_info[0]) ? (char*)vcap.bus_info : "<unknown>", vcap.driver, (vcap.version >> 16) & 0xff, (vcap.version >> 8) & 0xff, vcap.version & 0xff); zprintf(1, " capabilities:%s%s%s%s\n", (vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ? " CAPTURE" : "", (vcap.capabilities & V4L2_CAP_VIDEO_OVERLAY) ? " OVERLAY" : "", (vcap.capabilities & V4L2_CAP_READWRITE) ? " READWRITE" : "", (vcap.capabilities & V4L2_CAP_STREAMING) ? " STREAMING" : ""); if(!(vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE) || !(vcap.capabilities & (V4L2_CAP_READWRITE | V4L2_CAP_STREAMING))) return(err_capture(vdo, SEV_WARNING, ZBAR_ERR_UNSUPPORTED, __func__, "v4l2 device does not support usable CAPTURE")); if(v4l2_reset_crop(vdo)) /* ignoring errors (driver cropping support questionable) */; if(!vdo->width || !vdo->height) { /* fallback to large size, driver reduces to max available */ vdo->width = 640 * 64; vdo->height = 480 * 64; } if(v4l2_probe_formats(vdo)) return(-1); /* FIXME report error and fallback to readwrite? (if supported...) */ if(vdo->iomode != VIDEO_READWRITE && (vcap.capabilities & V4L2_CAP_STREAMING) && v4l2_probe_iomode(vdo)) return(-1); if(!vdo->iomode) vdo->iomode = VIDEO_READWRITE; zprintf(1, "using I/O mode: %s\n", (vdo->iomode == VIDEO_READWRITE) ? "READWRITE" : (vdo->iomode == VIDEO_MMAP) ? "MMAP" : (vdo->iomode == VIDEO_USERPTR) ? "USERPTR" : "<UNKNOWN>"); vdo->intf = VIDEO_V4L2; vdo->init = v4l2_init; vdo->cleanup = v4l2_cleanup; vdo->start = v4l2_start; vdo->stop = v4l2_stop; vdo->nq = v4l2_nq; vdo->dq = v4l2_dq; return(0); }
int zbar_video_get_fd (const zbar_video_t *vdo) { if(vdo->intf == VIDEO_INVALID) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "video device not opened")); if(vdo->intf != VIDEO_V4L2) return(err_capture(vdo, SEV_WARNING, ZBAR_ERR_UNSUPPORTED, __func__, "video driver does not support polling")); return(vdo->fd); }
static int vfw_set_format (zbar_video_t *vdo, uint32_t fmt) { const zbar_format_def_t *fmtdef = _zbar_format_lookup(fmt); if(!fmtdef->format) return(err_capture_int(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "unsupported vfw format: %x", fmt)); BITMAPINFOHEADER *bih = vdo->state->bih; assert(bih); bih->biWidth = vdo->width; bih->biHeight = vdo->height; switch(fmtdef->group) { case ZBAR_FMT_GRAY: bih->biBitCount = 8; break; case ZBAR_FMT_YUV_PLANAR: case ZBAR_FMT_YUV_PACKED: case ZBAR_FMT_YUV_NV: bih->biBitCount = 8 + (16 >> (fmtdef->p.yuv.xsub2 + fmtdef->p.yuv.ysub2)); break; case ZBAR_FMT_RGB_PACKED: bih->biBitCount = fmtdef->p.rgb.bpp * 8; break; default: bih->biBitCount = 0; } bih->biClrUsed = bih->biClrImportant = 0; bih->biCompression = fmt; zprintf(8, "seting format: %.4s(%08x) " BIH_FMT "\n", (char*)&fmt, fmt, BIH_FIELDS(bih)); if(!capSetVideoFormat(vdo->state->hwnd, bih, vdo->state->bi_size)) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "setting video format")); if(!capGetVideoFormat(vdo->state->hwnd, bih, vdo->state->bi_size)) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "getting video format")); if(bih->biCompression != fmt) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "video format set ignored")); vdo->format = fmt; vdo->width = bih->biWidth; vdo->height = bih->biHeight; vdo->datalen = bih->biSizeImage; zprintf(4, "set new format: %.4s(%08x) " BIH_FMT "\n", (char*)&fmt, fmt, BIH_FIELDS(bih)); return(0); }
int zbar_video_request_iomode (zbar_video_t *vdo, int iomode) { if(vdo->intf != VIDEO_INVALID) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "device already opened, unable to change iomode")); if(iomode < 0 || iomode > VIDEO_USERPTR) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "invalid iomode requested")); vdo->iomode = iomode; return(0); }
static int vfw_init (zbar_video_t *vdo, uint32_t fmt) { if(vfw_set_format(vdo, fmt)) return(-1); HWND hwnd = vdo->state->hwnd; CAPTUREPARMS cp; if(!capCaptureGetSetup(hwnd, &cp, sizeof(cp))) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, "retrieving capture parameters")); cp.dwRequestMicroSecPerFrame = 33333; cp.fMakeUserHitOKToCapture = 0; cp.wPercentDropForError = 90; cp.fYield = 1; cp.wNumVideoRequested = vdo->num_images; cp.fCaptureAudio = 0; cp.vKeyAbort = 0; cp.fAbortLeftMouse = 0; cp.fAbortRightMouse = 0; cp.fLimitEnabled = 0; if(!capCaptureSetSetup(hwnd, &cp, sizeof(cp))) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, "setting capture parameters")); if(!capCaptureGetSetup(hwnd, &cp, sizeof(cp))) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_WINAPI, __func__, "checking capture parameters")); /* ignore errors since we skipped checking fHasOverlay */ capOverlay(hwnd, 0); if(!capPreview(hwnd, 0) || !capPreviewScale(hwnd, 0)) err_capture(vdo, SEV_WARNING, ZBAR_ERR_WINAPI, __func__, "disabling preview"); if(!capSetCallbackOnVideoStream(hwnd, vfw_stream_cb) || !capSetCallbackOnError(hwnd, vfw_error_cb)) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_BUSY, __func__, "setting capture callbacks")); vdo->num_images = cp.wNumVideoRequested; vdo->iomode = VIDEO_MMAP; /* driver provides "locked" buffers */ zprintf(3, "initialized video capture: %d buffers %ldms/frame\n", vdo->num_images, cp.dwRequestMicroSecPerFrame); return(0); }
static int v4l2_mmap_buffers (zbar_video_t *vdo) { struct v4l2_requestbuffers rb; memset(&rb, 0, sizeof(rb)); rb.count = vdo->num_images; rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; rb.memory = V4L2_MEMORY_MMAP; if(ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "requesting video frame buffers (VIDIOC_REQBUFS)")); zprintf(1, "mapping %u buffers (of %d requested)\n", rb.count, vdo->num_images); if(!rb.count) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "driver returned 0 buffers")); if(vdo->num_images > rb.count) vdo->num_images = rb.count; struct v4l2_buffer vbuf; memset(&vbuf, 0, sizeof(vbuf)); vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; vbuf.memory = V4L2_MEMORY_MMAP; int i; for(i = 0; i < vdo->num_images; i++) { vbuf.index = i; if(ioctl(vdo->fd, VIDIOC_QUERYBUF, &vbuf) < 0) /* FIXME cleanup */ return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying video buffer (VIDIOC_QUERYBUF)")); if(vbuf.length < vdo->datalen) fprintf(stderr, "WARNING: insufficient v4l2 video buffer size:\n" "\tvbuf[%d].length=%x datalen=%lx image=%d x %d %.4s(%08x)\n", i, vbuf.length, vdo->datalen, vdo->width, vdo->height, (char*)&vdo->format, vdo->format); zbar_image_t *img = vdo->images[i]; img->datalen = vbuf.length; img->data = mmap(NULL, vbuf.length, PROT_READ | PROT_WRITE, MAP_SHARED, vdo->fd, vbuf.m.offset); if(img->data == MAP_FAILED) /* FIXME cleanup */ return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "mapping video frame buffers")); zprintf(2, " buf[%d] 0x%lx bytes @%p\n", i, img->datalen, img->data); } return(0); }
static inline int v4l1_probe_formats (zbar_video_t *vdo) { struct video_picture vpic; memset(&vpic, 0, sizeof(vpic)); if(ioctl(vdo->fd, VIDIOCGPICT, &vpic) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying format (VIDIOCGPICT)")); vdo->format = 0; if(vpic.palette <= VIDEO_PALETTE_YUV410P) vdo->format = v4l1_formats[vpic.palette].format; zprintf(1, "current format: %.4s(%08x) depth=%d palette=%d\n", (char*)&vdo->format, vdo->format, vpic.depth, vpic.palette); vdo->formats = calloc(16, sizeof(uint32_t)); if(!vdo->formats) return(err_capture(vdo, SEV_FATAL, ZBAR_ERR_NOMEM, __func__, "allocating format list")); int num_formats = 0; zprintf(2, "probing supported formats:\n"); int i; for(i = 1; i <= VIDEO_PALETTE_YUV410P; i++) { if(!v4l1_formats[i].format) continue; vpic.depth = v4l1_formats[i].bpp; vpic.palette = i; if(ioctl(vdo->fd, VIDIOCSPICT, &vpic) < 0) { zprintf(2, " [%02d] %.4s...no (set fails)\n", i, (char*)&v4l1_formats[i].format); continue; } if(ioctl(vdo->fd, VIDIOCGPICT, &vpic) < 0 || vpic.palette != i) { zprintf(2, " [%02d] %.4s...no (set ignored)\n", i, (char*)&v4l1_formats[i].format); continue; } zprintf(2, " [%02d] %.4s...yes\n", i, (char*)&v4l1_formats[i].format); vdo->formats[num_formats++] = v4l1_formats[i].format; } vdo->formats = realloc(vdo->formats, (num_formats + 1) * sizeof(uint32_t)); assert(vdo->formats); return(v4l1_set_format(vdo, vdo->format)); }
static inline int video_init_images (zbar_video_t *vdo) { int i; assert(vdo->datalen); if(vdo->iomode != VIDEO_MMAP) { assert(!vdo->buf); vdo->buflen = vdo->num_images * vdo->datalen; vdo->buf = calloc(1, vdo->buflen); if(!vdo->buf) return(err_capture(vdo, SEV_FATAL, ZBAR_ERR_NOMEM, __func__, "unable to allocate image buffers")); zprintf(1, "pre-allocated %d %s buffers size=0x%lx\n", vdo->num_images, (vdo->iomode == VIDEO_READWRITE) ? "READ" : "USERPTR", vdo->buflen); } for(i = 0; i < vdo->num_images; i++) { zbar_image_t *img = vdo->images[i]; img->format = vdo->format; zbar_image_set_size(img, vdo->width, vdo->height); if(vdo->iomode != VIDEO_MMAP) { unsigned long offset = i * vdo->datalen; img->datalen = vdo->datalen; img->data = (uint8_t*)vdo->buf + offset; zprintf(2, " [%02d] @%08lx\n", i, offset); } } return(0); }
int zbar_video_init (zbar_video_t *vdo, unsigned long fmt) { if(vdo->initialized) /* FIXME re-init different format? */ return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "already initialized, re-init unimplemented")); if(vdo->init(vdo, fmt)) return(-1); vdo->format = fmt; if(video_init_images(vdo)) return(-1); #ifdef HAVE_LIBJPEG const zbar_format_def_t *vidfmt = _zbar_format_lookup(fmt); if(vidfmt && vidfmt->group == ZBAR_FMT_JPEG) { /* prepare for decoding */ if(!vdo->jpeg) vdo->jpeg = _zbar_jpeg_decomp_create(); if(vdo->jpeg_img) zbar_image_destroy(vdo->jpeg_img); /* create intermediate image for decoder to use*/ zbar_image_t *img = vdo->jpeg_img = zbar_image_create(); img->format = fourcc('Y','8','0','0'); img->width = vdo->width; img->height = vdo->height; img->datalen = vdo->width * vdo->height; } #endif vdo->initialized = 1; return(0); }
int zbar_process_one (zbar_processor_t *proc, int timeout) { proc_enter(proc); int streaming = proc->streaming; _zbar_mutex_unlock(&proc->mutex); int rc = 0; if(!proc->video) { rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "video input not initialized"); goto done; } if(!streaming) { rc = zbar_processor_set_active(proc, 1); if(rc) goto done; } zbar_timer_t timer; rc = _zbar_processor_wait(proc, EVENT_OUTPUT, _zbar_timer_init(&timer, timeout)); if(!streaming && zbar_processor_set_active(proc, 0)) rc = -1; done: _zbar_mutex_lock(&proc->mutex); proc_leave(proc); return(rc); }
static int v4l2_nq (zbar_video_t *vdo, zbar_image_t *img) { if(vdo->iomode == VIDEO_READWRITE) return(video_nq_image(vdo, img)); if(video_unlock(vdo)) return(-1); struct v4l2_buffer vbuf; memset(&vbuf, 0, sizeof(vbuf)); vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(vdo->iomode == VIDEO_MMAP) { vbuf.memory = V4L2_MEMORY_MMAP; vbuf.index = img->srcidx; } else { vbuf.memory = V4L2_MEMORY_USERPTR; vbuf.m.userptr = (unsigned long)img->data; vbuf.length = img->datalen; vbuf.index = img->srcidx; /* FIXME workaround broken drivers */ } if(ioctl(vdo->fd, VIDIOC_QBUF, &vbuf) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "queuing video buffer (VIDIOC_QBUF)")); return(0); }
int _zbar_processor_handle_input (zbar_processor_t *proc, int input) { int event = EVENT_INPUT; switch(input) { case -1: event |= EVENT_CANCELED; _zbar_processor_set_visible(proc, 0); err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, "user closed display window"); break; case 'd': proc->dumping = 1; return(0); case '+': case '=': break; case '-': break; } _zbar_mutex_lock(&proc->mutex); proc->input = input; if(input == -1 && proc->visible && proc->streaming) /* also cancel outstanding output waiters */ event |= EVENT_OUTPUT; _zbar_processor_notify(proc, event); _zbar_mutex_unlock(&proc->mutex); return(input); }
int zbar_processor_init (zbar_processor_t *proc, const char *dev, int enable_display) { int rc, input_threaded; _zbar_mutex_lock(&proc->mutex); _zbar_thread_stop(&proc->input_thread, &proc->mutex); _zbar_processor_lock(proc); _zbar_mutex_unlock(&proc->mutex); rc = 0; if(!dev && !enable_display) /* nothing to do */ goto done; /* spawn input monitor thread */ input_threaded = proc->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; } done: _zbar_mutex_lock(&proc->mutex); proc_leave(proc); return(rc); }
static int v4l2_probe_iomode (zbar_video_t *vdo) { struct v4l2_requestbuffers rb; memset(&rb, 0, sizeof(rb)); rb.count = vdo->num_images; /* FIXME workaround broken drivers */ rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(vdo->iomode == VIDEO_MMAP) rb.memory = V4L2_MEMORY_MMAP; else rb.memory = V4L2_MEMORY_USERPTR; if(ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0) { if(vdo->iomode) return(err_capture_int(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "unsupported iomode requested (%d)", vdo->iomode)); else if(errno != EINVAL) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying streaming mode (VIDIOC_REQBUFS)")); #ifdef HAVE_SYS_MMAN_H vdo->iomode = VIDEO_MMAP; #endif } else { if(!vdo->iomode) vdo->iomode = VIDEO_USERPTR; if(rb.count) vdo->num_images = rb.count; } return(0); }
int zbar_processor_user_wait (zbar_processor_t *proc, int timeout) { int rc; proc_enter(proc); _zbar_mutex_unlock(&proc->mutex); rc = -1; if(proc->visible || proc->streaming || timeout >= 0) { zbar_timer_t timer; rc = _zbar_processor_wait(proc, EVENT_INPUT, _zbar_timer_init(&timer, timeout)); } if(!proc->visible) rc = err_capture(proc, SEV_WARNING, ZBAR_ERR_CLOSED, __func__, "display window not available for input"); if(rc > 0) rc = proc->input; _zbar_mutex_lock(&proc->mutex); proc_leave(proc); return(rc); }
int zbar_processor_set_visible (zbar_processor_t *proc, int visible) { proc_enter(proc); _zbar_mutex_unlock(&proc->mutex); int rc = 0; if(proc->window) { if(proc->video) rc = _zbar_processor_set_size(proc, zbar_video_get_width(proc->video), zbar_video_get_height(proc->video)); if(!rc) rc = _zbar_processor_set_visible(proc, visible); if(!rc) proc->visible = (visible != 0); } else if(visible) rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "processor display window not initialized"); _zbar_mutex_lock(&proc->mutex); proc_leave(proc); return(rc); }
static inline int v4l1_set_format (zbar_video_t *vdo, uint32_t fmt) { struct video_picture vpic; memset(&vpic, 0, sizeof(vpic)); if(ioctl(vdo->fd, VIDIOCGPICT, &vpic) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying video format (VIDIOCGPICT)")); vdo->palette = 0; int ifmt; for(ifmt = 1; ifmt <= VIDEO_PALETTE_YUV410P; ifmt++) if(v4l1_formats[ifmt].format == fmt) break; if(!fmt || ifmt >= VIDEO_PALETTE_YUV410P) return(err_capture_int(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "invalid v4l1 format: %x", fmt)); vpic.palette = ifmt; vpic.depth = v4l1_formats[ifmt].bpp; if(ioctl(vdo->fd, VIDIOCSPICT, &vpic) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "setting format (VIDIOCSPICT)")); memset(&vpic, 0, sizeof(vpic)); if(ioctl(vdo->fd, VIDIOCGPICT, &vpic) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying video format (VIDIOCGPICT)")); if(vpic.palette != ifmt || vpic.depth != v4l1_formats[ifmt].bpp) { fprintf(stderr, "WARNING: set v4l1 palette %d which should have depth %d bpp\n" " but probed palette %d with depth %d bpp?" " ...continuing anyway\n", ifmt, v4l1_formats[ifmt].bpp, vpic.palette, vpic.depth); err_capture_int(vdo, SEV_WARNING, ZBAR_ERR_INVALID, __func__, "driver format (%x) inconsistency", fmt); } vdo->format = fmt; vdo->palette = ifmt; vdo->datalen = (vdo->width * vdo->height * v4l1_formats[ifmt].bpp + 7) >> 3; zprintf(1, "set new format: %.4s(%08x) depth=%d palette=%d size=0x%lx\n", (char*)&vdo->format, vdo->format, vpic.depth, vdo->palette, vdo->datalen); return(0); }
static int vfw_start (zbar_video_t *vdo) { ResetEvent(vdo->state->captured); if(!capCaptureSequenceNoFile(vdo->state->hwnd)) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "starting video stream")); return(0); }
int zbar_video_request_interface (zbar_video_t *vdo, int ver) { if(vdo->intf != VIDEO_INVALID) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "device already opened, unable to change interface")); vdo->intf = (video_interface_t)ver; zprintf(1, "request interface version %d\n", vdo->intf); return(0); }
static inline int v4l1_init_window (zbar_video_t *vdo) { struct video_window vwin; memset(&vwin, 0, sizeof(vwin)); if(ioctl(vdo->fd, VIDIOCGWIN, &vwin) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying video window settings (VIDIOCGWIN)")); zprintf(1, "current window: %d x %d @(%d, %d)%s\n", vwin.width, vwin.height, vwin.x, vwin.y, (vwin.flags & 1) ? " INTERLACE" : ""); if(vwin.width == vdo->width && vwin.height == vdo->height) /* max window already set */ return(0); struct video_window maxwin; memcpy(&maxwin, &vwin, sizeof(maxwin)); maxwin.width = vdo->width; maxwin.height = vdo->height; zprintf(1, "setting max win: %d x %d @(%d, %d)%s\n", maxwin.width, maxwin.height, maxwin.x, maxwin.y, (maxwin.flags & 1) ? " INTERLACE" : ""); if(ioctl(vdo->fd, VIDIOCSWIN, &maxwin) < 0) { zprintf(1, "set FAILED...trying to recover original window\n"); /* ignore errors (driver broken anyway) */ ioctl(vdo->fd, VIDIOCSWIN, &vwin); } /* re-query resulting parameters */ memset(&vwin, 0, sizeof(vwin)); if(ioctl(vdo->fd, VIDIOCGWIN, &vwin) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying video window settings (VIDIOCGWIN)")); zprintf(1, " final window: %d x %d @(%d, %d)%s\n", vwin.width, vwin.height, vwin.x, vwin.y, (vwin.flags & 1) ? " INTERLACE" : ""); vdo->width = vwin.width; vdo->height = vwin.height; return(0); }
static int v4l1_mmap_buffers (zbar_video_t *vdo) { #ifdef HAVE_SYS_MMAN_H /* map camera image to memory */ struct video_mbuf vbuf; memset(&vbuf, 0, sizeof(vbuf)); if(ioctl(vdo->fd, VIDIOCGMBUF, &vbuf) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "querying video frame buffers (VIDIOCGMBUF)")); assert(vbuf.frames && vbuf.size); zprintf(1, "mapping %d buffers size=0x%x\n", vbuf.frames, vbuf.size); vdo->buflen = vbuf.size; vdo->buf = mmap(0, vbuf.size, PROT_READ | PROT_WRITE, MAP_SHARED, vdo->fd, 0); if(vdo->buf == MAP_FAILED) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "mapping video frame buffers")); int i; for(i = 0; i < vbuf.frames; i++) { zbar_image_t *img = vdo->images[i]; zprintf(2, " [%02d] @%08x\n", img->srcidx, vbuf.offsets[i]); img->data = vdo->buf + vbuf.offsets[i]; img->datalen = vdo->datalen; int next_offset = ((i + 1 < vdo->num_images) ? vbuf.offsets[i + 1] : vbuf.size); if(next_offset < vbuf.offsets[i] + vdo->datalen) fprintf(stderr, "WARNING: insufficient v4l1 video buffer size:\n" "\tvbuf[%d]=%x vbuf[%d]=%x datalen=%lx\n" "\timage=%d x %d %.4s(%08x) palette=%d\n", i, vbuf.offsets[i], i + 1, next_offset, vdo->datalen, vdo->width, vdo->height, (char*)&vdo->format, vdo->format, vdo->palette); } return(0); #else return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "memory mapping not supported")); #endif }
static int v4l2_stop (zbar_video_t *vdo) { if(vdo->iomode == VIDEO_READWRITE) return(0); enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(ioctl(vdo->fd, VIDIOC_STREAMOFF, &type) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__, "stopping video stream (VIDIOC_STREAMOFF)")); return(0); }
static int v4l2_cleanup (zbar_video_t *vdo) { if(vdo->iomode == VIDEO_READWRITE) return(0); struct v4l2_requestbuffers rb; memset(&rb, 0, sizeof(rb)); rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if(vdo->iomode == VIDEO_MMAP) { rb.memory = V4L2_MEMORY_MMAP; int i; for(i = 0; i < vdo->num_images; i++) { zbar_image_t *img = vdo->images[i]; if(img->data && munmap((void*)img->data, img->datalen)) err_capture(vdo, SEV_WARNING, ZBAR_ERR_SYSTEM, __func__, "unmapping video frame buffers"); img->data = NULL; img->datalen = 0; } } else rb.memory = V4L2_MEMORY_USERPTR; /* requesting 0 buffers * should implicitly disable streaming */ if(ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0) err_capture(vdo, SEV_WARNING, ZBAR_ERR_SYSTEM, __func__, "releasing video frame buffers (VIDIOC_REQBUFS)"); /* close open device */ if(vdo->fd >= 0) { close(vdo->fd); vdo->fd = -1; } return(0); }
int zbar_processor_set_visible (zbar_processor_t *proc, int visible) { int rc = 0; proc_enter(proc); _zbar_mutex_unlock(&proc->mutex); rc = err_capture(proc, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "processor display window not initialized"); _zbar_mutex_lock(&proc->mutex); proc_leave(proc); return(rc); }
int zbar_video_request_size (zbar_video_t *vdo, unsigned width, unsigned height) { if(vdo->initialized) /* FIXME re-init different format? */ return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "already initialized, unable to resize")); vdo->width = width; vdo->height = height; zprintf(1, "request size: %d x %d\n", width, height); return(0); }
static int vfw_stop (zbar_video_t *vdo) { video_state_t *state = vdo->state; if(!capCaptureAbort(state->hwnd)) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__, "stopping video stream")); _zbar_mutex_lock(&vdo->qlock); if(state->image) state->image = NULL; SetEvent(state->captured); _zbar_mutex_unlock(&vdo->qlock); return(0); }
static int _zbar_v4l1_probe (zbar_video_t *vdo) { /* check capabilities */ struct video_capability vcap; memset(&vcap, 0, sizeof(vcap)); if(ioctl(vdo->fd, VIDIOCGCAP, &vcap) < 0) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "video4linux version 1 not supported (VIDIOCGCAP)")); zprintf(1, "%s (%sCAPTURE) (%d x %d) - (%d x %d)\n", vcap.name, (vcap.type & VID_TYPE_CAPTURE) ? "" : "*NO* ", vcap.minwidth, vcap.minheight, vcap.maxwidth, vcap.maxheight); if(!(vcap.type & VID_TYPE_CAPTURE)) return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_UNSUPPORTED, __func__, "v4l1 device does not support CAPTURE")); if(!vdo->width || !vdo->height) { vdo->width = vcap.maxwidth; vdo->height = vcap.maxheight; } if(v4l1_init_window(vdo) || v4l1_probe_formats(vdo) || v4l1_probe_iomode(vdo)) return(-1); vdo->intf = VIDEO_V4L1; vdo->init = v4l1_init; vdo->cleanup = v4l1_cleanup; vdo->start = v4l1_start; vdo->stop = v4l1_stop; vdo->nq = v4l1_nq; vdo->dq = v4l1_dq; return(0); }