pure sdk for main
This commit is contained in:
@@ -0,0 +1,440 @@
|
||||
/*------------------------------------------------------------------------
|
||||
* Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
|
||||
*
|
||||
* This file is part of the ZBar Bar Code Reader.
|
||||
*
|
||||
* The ZBar Bar Code Reader is free software; you can redistribute it
|
||||
* and/or modify it under the terms of the GNU Lesser Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* The ZBar Bar Code Reader is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser Public License
|
||||
* along with the ZBar Bar Code Reader; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
* http://sourceforge.net/projects/zbar
|
||||
*------------------------------------------------------------------------*/
|
||||
|
||||
#include "video.h"
|
||||
#include "image.h"
|
||||
|
||||
|
||||
#ifdef HAVE_LIBJPEG
|
||||
extern struct jpeg_decompress_struct *_zbar_jpeg_decomp_create(void);
|
||||
extern void _zbar_jpeg_decomp_destroy(struct jpeg_decompress_struct *cinfo);
|
||||
#endif
|
||||
|
||||
static void _zbar_video_recycle_image (zbar_image_t *img)
|
||||
{
|
||||
zbar_video_t *vdo = img->src;
|
||||
assert(vdo);
|
||||
assert(img->srcidx >= 0);
|
||||
video_lock(vdo);
|
||||
if(vdo->images[img->srcidx] != img)
|
||||
vdo->images[img->srcidx] = img;
|
||||
if(vdo->active)
|
||||
vdo->nq(vdo, img);
|
||||
else
|
||||
video_unlock(vdo);
|
||||
}
|
||||
|
||||
static void _zbar_video_recycle_shadow (zbar_image_t *img)
|
||||
{
|
||||
zbar_video_t *vdo = img->src;
|
||||
assert(vdo);
|
||||
assert(img->srcidx == -1);
|
||||
video_lock(vdo);
|
||||
img->next = vdo->shadow_image;
|
||||
vdo->shadow_image = img;
|
||||
video_unlock(vdo);
|
||||
}
|
||||
|
||||
zbar_video_t *zbar_video_create ()
|
||||
{
|
||||
zbar_video_t *vdo = calloc(1, sizeof(zbar_video_t));
|
||||
int i;
|
||||
if(!vdo)
|
||||
return(NULL);
|
||||
err_init(&vdo->err, ZBAR_MOD_VIDEO);
|
||||
vdo->fd = -1;
|
||||
|
||||
(void)_zbar_mutex_init(&vdo->qlock);
|
||||
|
||||
/* pre-allocate images */
|
||||
vdo->num_images = ZBAR_VIDEO_IMAGES_MAX;
|
||||
vdo->images = calloc(ZBAR_VIDEO_IMAGES_MAX, sizeof(zbar_image_t*));
|
||||
if(!vdo->images) {
|
||||
zbar_video_destroy(vdo);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
for(i = 0; i < ZBAR_VIDEO_IMAGES_MAX; i++) {
|
||||
zbar_image_t *img = vdo->images[i] = zbar_image_create();
|
||||
if(!img) {
|
||||
zbar_video_destroy(vdo);
|
||||
return(NULL);
|
||||
}
|
||||
img->refcnt = 0;
|
||||
img->cleanup = _zbar_video_recycle_image;
|
||||
img->srcidx = i;
|
||||
img->src = vdo;
|
||||
}
|
||||
|
||||
return(vdo);
|
||||
}
|
||||
|
||||
void zbar_video_destroy (zbar_video_t *vdo)
|
||||
{
|
||||
if(vdo->intf != VIDEO_INVALID)
|
||||
zbar_video_open(vdo, NULL);
|
||||
if(vdo->images) {
|
||||
int i;
|
||||
for(i = 0; i < ZBAR_VIDEO_IMAGES_MAX; i++)
|
||||
if(vdo->images[i])
|
||||
_zbar_image_free(vdo->images[i]);
|
||||
free(vdo->images);
|
||||
}
|
||||
while(vdo->shadow_image) {
|
||||
zbar_image_t *img = vdo->shadow_image;
|
||||
vdo->shadow_image = img->next;
|
||||
free((void*)img->data);
|
||||
img->data = NULL;
|
||||
free(img);
|
||||
}
|
||||
if(vdo->buf)
|
||||
free(vdo->buf);
|
||||
if(vdo->formats)
|
||||
free(vdo->formats);
|
||||
if(vdo->emu_formats)
|
||||
free(vdo->emu_formats);
|
||||
|
||||
if(vdo->free)
|
||||
vdo->free(vdo);
|
||||
|
||||
err_cleanup(&vdo->err);
|
||||
_zbar_mutex_destroy(&vdo->qlock);
|
||||
|
||||
#ifdef HAVE_LIBJPEG
|
||||
if(vdo->jpeg_img) {
|
||||
zbar_image_destroy(vdo->jpeg_img);
|
||||
vdo->jpeg_img = NULL;
|
||||
}
|
||||
if(vdo->jpeg) {
|
||||
_zbar_jpeg_decomp_destroy(vdo->jpeg);
|
||||
vdo->jpeg = NULL;
|
||||
}
|
||||
#endif
|
||||
free(vdo);
|
||||
}
|
||||
|
||||
int zbar_video_open (zbar_video_t *vdo,
|
||||
const char *dev)
|
||||
{
|
||||
char *ldev = NULL;
|
||||
int rc;
|
||||
zbar_video_enable(vdo, 0);
|
||||
video_lock(vdo);
|
||||
if(vdo->intf != VIDEO_INVALID) {
|
||||
if(vdo->cleanup) {
|
||||
vdo->cleanup(vdo);
|
||||
vdo->cleanup = NULL;
|
||||
}
|
||||
zprintf(1, "closed camera (fd=%d)\n", vdo->fd);
|
||||
vdo->intf = VIDEO_INVALID;
|
||||
}
|
||||
video_unlock(vdo);
|
||||
|
||||
if(!dev)
|
||||
return(0);
|
||||
|
||||
if((unsigned char)dev[0] < 0x10) {
|
||||
/* default linux device, overloaded for other platforms */
|
||||
int id = dev[0];
|
||||
dev = ldev = strdup("/dev/video0");
|
||||
ldev[10] = '0' + id;
|
||||
}
|
||||
|
||||
rc = _zbar_video_open(vdo, dev);
|
||||
|
||||
if(ldev)
|
||||
free(ldev);
|
||||
return(rc);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int zbar_video_get_width (const zbar_video_t *vdo)
|
||||
{
|
||||
return(vdo->width);
|
||||
}
|
||||
|
||||
int zbar_video_get_height (const zbar_video_t *vdo)
|
||||
{
|
||||
return(vdo->height);
|
||||
}
|
||||
|
||||
uint32_t zbar_video_get_format (const zbar_video_t *vdo)
|
||||
{
|
||||
return(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)
|
||||
{
|
||||
#ifdef HAVE_LIBJPEG
|
||||
const zbar_format_def_t *vidfmt;
|
||||
#endif
|
||||
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
|
||||
vidfmt = _zbar_format_lookup(fmt);
|
||||
if(vidfmt && vidfmt->group == ZBAR_FMT_JPEG) {
|
||||
zbar_image_t *img;
|
||||
/* 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*/
|
||||
img = vdo->jpeg_img = zbar_image_create();
|
||||
img->format = fourcc('Y','8','0','0');
|
||||
zbar_image_set_size(img, vdo->width, vdo->height);
|
||||
img->datalen = vdo->width * vdo->height;
|
||||
}
|
||||
#endif
|
||||
vdo->initialized = 1;
|
||||
return(0);
|
||||
}
|
||||
|
||||
int zbar_video_enable (zbar_video_t *vdo,
|
||||
int enable)
|
||||
{
|
||||
if(vdo->active == enable)
|
||||
return(0);
|
||||
|
||||
if(enable) {
|
||||
if(vdo->intf == VIDEO_INVALID)
|
||||
return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__,
|
||||
"video device not opened"));
|
||||
|
||||
if(!vdo->initialized &&
|
||||
zbar_negotiate_format(vdo, NULL))
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if(video_lock(vdo))
|
||||
return(-1);
|
||||
vdo->active = enable;
|
||||
if(enable) {
|
||||
/* enqueue all buffers */
|
||||
int i;
|
||||
for(i = 0; i < vdo->num_images; i++)
|
||||
if(vdo->nq(vdo, vdo->images[i]) ||
|
||||
((i + 1 < vdo->num_images) && video_lock(vdo)))
|
||||
return(-1);
|
||||
|
||||
return(vdo->start(vdo));
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
for(i = 0; i < vdo->num_images; i++)
|
||||
vdo->images[i]->next = NULL;
|
||||
vdo->nq_image = vdo->dq_image = NULL;
|
||||
if(video_unlock(vdo))
|
||||
return(-1);
|
||||
|
||||
return(vdo->stop(vdo));
|
||||
}
|
||||
}
|
||||
|
||||
zbar_image_t *zbar_video_next_image (zbar_video_t *vdo)
|
||||
{
|
||||
unsigned frame;
|
||||
zbar_image_t *img;
|
||||
|
||||
if(video_lock(vdo))
|
||||
return(NULL);
|
||||
if(!vdo->active) {
|
||||
video_unlock(vdo);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
frame = vdo->frame++;
|
||||
img = vdo->dq(vdo);
|
||||
if(img) {
|
||||
img->seq = frame;
|
||||
if(vdo->num_images < 2) {
|
||||
/* return a *copy* of the video image and immediately recycle
|
||||
* the driver's buffer to avoid deadlocking the resources
|
||||
*/
|
||||
zbar_image_t *tmp = img;
|
||||
video_lock(vdo);
|
||||
img = vdo->shadow_image;
|
||||
vdo->shadow_image = (img) ? img->next : NULL;
|
||||
video_unlock(vdo);
|
||||
|
||||
if(!img) {
|
||||
img = zbar_image_create();
|
||||
assert(img);
|
||||
img->refcnt = 0;
|
||||
img->src = vdo;
|
||||
/* recycle the shadow images */
|
||||
|
||||
img->format = vdo->format;
|
||||
zbar_image_set_size(img, vdo->width, vdo->height);
|
||||
img->datalen = vdo->datalen;
|
||||
img->data = malloc(vdo->datalen);
|
||||
}
|
||||
img->cleanup = _zbar_video_recycle_shadow;
|
||||
img->seq = frame;
|
||||
memcpy((void*)img->data, tmp->data, img->datalen);
|
||||
_zbar_video_recycle_image(tmp);
|
||||
}
|
||||
else
|
||||
img->cleanup = _zbar_video_recycle_image;
|
||||
_zbar_image_refcnt(img, 1);
|
||||
}
|
||||
return(img);
|
||||
}
|
||||
|
||||
/** @brief return if fun unsupported, otherwise continue */
|
||||
#define return_if_not_supported(fun, name) \
|
||||
{ \
|
||||
if(!(fun)) { \
|
||||
zprintf(1, "video driver does not implement %s\n", name); \
|
||||
return ZBAR_ERR_UNSUPPORTED; \
|
||||
} \
|
||||
}
|
||||
#define return_if_non_zero(a) { int rv=a; if (rv!=0) return(rv); }
|
||||
|
||||
int zbar_video_set_control (zbar_video_t *vdo,
|
||||
const char *control_name,
|
||||
int value)
|
||||
{
|
||||
int loc_value, rv;
|
||||
return_if_not_supported(vdo->set_control, "set_control");
|
||||
loc_value = value;
|
||||
|
||||
rv = vdo->set_control(vdo, control_name, &loc_value);
|
||||
|
||||
if(rv==0)
|
||||
zprintf(1, "value of %s set to: %d\n", control_name, loc_value);
|
||||
return(rv);
|
||||
}
|
||||
|
||||
int zbar_video_get_control (zbar_video_t *vdo,
|
||||
const char *control_name,
|
||||
int *value)
|
||||
{
|
||||
return_if_not_supported(vdo->get_control, "get_control");
|
||||
return(vdo->get_control(vdo, control_name, value));
|
||||
}
|
||||
|
||||
struct video_controls_s *zbar_video_get_controls (const zbar_video_t *vdo,
|
||||
int index)
|
||||
{
|
||||
int i = 0;
|
||||
struct video_controls_s *p = vdo->controls;
|
||||
|
||||
while (p && i != index) {
|
||||
i++;
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
return p;
|
||||
}
|
||||
Reference in New Issue
Block a user