ZBar Source Analysis - video.c | 2021SC@SDUSC

Keywords: C github

Catalog

I. Video modules

2. Code Analysis

3. Summary

I. Video modules

We know that ZBar is not always provided with static pictures when scanning, but may also be dynamic videos. For example, the micro-scanner that we call in our daily life also provides video video, so we need Zbar to analyze the video and scan it dynamically.

The Video module is a ZBar module that enables scanning analysis of read-in videos. The core code consists of video.h and video.c. Video.h includes the declaration of some key variables and the definition of the structure. It is also the calling interface (header file) of other parts to the Video module. The specific function code is implemented in video.c.

2. Code Analysis

In a ZBar project, each feature's implementation usually has functions to initialize, increase, and free memory for that part, which are different from a new object in Java and the set(), get() function.

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);
}

Video module is no exception, first analyze _ Zbar_ Video_ Recycle_ The image (zbar_image_t *img) function, as the name implies, is a function of the Video module to frame-by-frame loop the images of the input video.

Before analyzing this function, here's a look at zbar_ Image_ The structure of T is supplemented.

struct zbar_image_s {
    uint32_t format;            /* fourcc image format code */
    unsigned width, height;     /* image size */
    const void *data;           /* image sample data */
    unsigned long datalen;      /* allocated/mapped size of data */
    unsigned crop_x, crop_y;    /* crop rectangle */
    unsigned crop_w, crop_h;
    void *userdata;             /* user specified data associated w/image */

    /* cleanup handler */
    zbar_image_cleanup_handler_t *cleanup;
    refcnt_t refcnt;            /* reference count */
    zbar_video_t *src;          /* originator */
    int srcidx;                 /* index used by originator */
    zbar_image_t *next;         /* internal image lists */

    unsigned seq;               /* page/frame sequence number */
    zbar_symbol_set_t *syms;    /* decoded result set */
};

uint32_t format; /* fourcc Image Format Code*/

Note: FourCC, full name Four-Character Codes, stands for four character code, it is a 32-bit identifier, in fact, typedef unsigned int FOURCC; It is a four-character code that independently identifies the video data stream format.

Video playback software queries the FourCC code and finds the one associated with the FourCC code Video Decoder To play a specific Video Stream . For example: DIV3 = DivX Low-Motion, DIV4 = DivX Fast-Motion, DIVX = DivX4, FFDS = FFDShow, and so on. For example, the label headers of RIFF files such as wav and avi indicate that there are also a large number of FOURCC equal to IDP3 in the model file. md3 of Quake 3.

unsigned width, height;/* Image Size*/

const void *data;/* Image Sample Data*/

  unsigned long datalen;      /* Allocated/Mapped Data Size*/  

unsigned crop_x, crop_y;    /* Clipping Rectangle*/

unsigned crop_w, crop_h;

void*userdata;/* User-specified data associated with images*/

refcnt_t refcnt; /* Reference Count*/

zbar_video_t*src;/* Generator*/

int srcidx;/* Index used by generator*/

zbar_image_t *next;/* Internal image list*/

unsigned seq; /* Page/Frame Sequence Number*/

zbar_symbol_set_t*syms;/* Decoding Result Set*/

And zbar_video_s is supplemented by the structure of the incoming video structure.

struct zbar_video_s {
    errinfo_t err;              /* error reporting */
    int fd;                     /* open camera device */
    unsigned width, height;     /* video frame size */

    video_interface_t intf;     /* input interface type */
    video_iomode_t iomode;      /* video data transfer mode */
    unsigned initialized : 1;   /* format selected and images mapped */
    unsigned active      : 1;   /* current streaming state */

    uint32_t format;            /* selected fourcc */
    unsigned palette;           /* v4l1 format index corresponding to format */
    uint32_t *formats;          /* 0 terminated list of supported formats */

    unsigned long datalen;      /* size of image data for selected format */
    unsigned long buflen;       /* total size of image data buffer */
    void *buf;                  /* image data buffer */

    unsigned frame;             /* frame count */

    zbar_mutex_t qlock;         /* lock image queue */
    int num_images;             /* number of allocated images */
    zbar_image_t **images;      /* indexed list of images */
    zbar_image_t *nq_image;     /* last image enqueued */
    zbar_image_t *dq_image;     /* first image to dequeue (when ordered) */
    zbar_image_t *shadow_image; /* special case internal double buffering */

    video_state_t *state;       /* platform/interface specific state */

#ifdef HAVE_LIBJPEG
    struct jpeg_decompress_struct *jpeg; /* JPEG decompressor */
    zbar_image_t *jpeg_img;    /* temporary image */
#endif

    /* interface dependent methods */
    int (*init)(zbar_video_t*, uint32_t);
    int (*cleanup)(zbar_video_t*);
    int (*start)(zbar_video_t*);
    int (*stop)(zbar_video_t*);
    int (*nq)(zbar_video_t*, zbar_image_t*);
    zbar_image_t* (*dq)(zbar_video_t*);
};

In _ Zbar_ Video_ Recycle_ The assert assertion function is also called in the image (zbar_image_t *img) function.

Simply put, an assertion is a check of some assumption. In C, assertions are defined as macros (assert. express (ion)), not a function, whose prototype is defined in the <assert.h> file. Where assert determines whether the execution program needs to be terminated by checking the value of the expression. That is, if the expression value is false (that is, 0), it will first print an error message to stderr, the standard error stream, and then terminate the program by calling the abort function. Otherwise, assert has no effect.

By default, assert macros only work in Debug (internal debug version) and are ignored in Release (release version).

As we cycle through the frame-by-frame images of the video, we can see that ZBar makes a series of judgments to ensure the reliability of the program. First, when each frame of image is locked, it is necessary to determine whether the current video object exists and the index of the current locked image. If it does not meet the requirements, the assertion function will terminate the program.

When an image is locked, it is assigned and preprocessed, then unlocked.

Below are functions for locking, unlocking, and preprocessing images in video.h.

/* video.next_image and video.recycle_image have to be thread safe
 * wrt/other apis
 */
static inline int video_lock (zbar_video_t *vdo)
{
    int rc = 0;
    if((rc = _zbar_mutex_lock(&vdo->qlock))) {
        err_capture(vdo, SEV_FATAL, ZBAR_ERR_LOCKING, __func__,
                    "unable to acquire lock");
        vdo->err.errnum = rc;
        return(-1);
    }
    return(0);
}

static inline int video_unlock (zbar_video_t *vdo)
{
    int rc = 0;
    if((rc = _zbar_mutex_unlock(&vdo->qlock))) {
        err_capture(vdo, SEV_FATAL, ZBAR_ERR_LOCKING, __func__,
                    "unable to release lock");
        vdo->err.errnum = rc;
        return(-1);
    }
    return(0);
}

static inline int video_nq_image (zbar_video_t *vdo,
                                  zbar_image_t *img)
{
    /* maintains queued buffers in order */
    img->next = NULL;
    if(vdo->nq_image)
        vdo->nq_image->next = img;
    vdo->nq_image = img;
    if(!vdo->dq_image)
        vdo->dq_image = img;
    return(video_unlock(vdo));
}

Thread security must be guaranteed when locking and unlocking images, that is, mutually exclusive situations are not allowed, that is, more than one image enters the critical zone at the same time. In short, multiple images are not allowed to be locked in the same video stream.

and   video_nq_image (zbar_video_t *vdo, zbar_image_t *img) is responsible for image preprocessing, that is, simple cyclic processing. Its main work involves handing over the resources occupied by the previous locked image to the next one that will be locked.

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);
}

In the process of video processing, not only do you need to cycle the images frame by frame, but also the shadows in the video frame by frame to filter out useful scanned areas.

Processing logic for shadows and _ Zbar_ Video_ Recycle_ The image (zbar_image_t *img) function has approximately the same logic. Assertion functions are used to determine whether the current incoming video image exists and to make reasonable judgments about the image subscripts, followed by locking, cycling, and unlocking shadows.

3. Summary

This blog analyzes several key functions of the Video module of the ZBar scanner. If there are any deficiencies, please correct them.

Posted by ManWithNoName on Sun, 07 Nov 2021 09:00:00 -0800