1

I would like to grab images from multiple cameras under linux. I followed this presentation used the code and enhanced it for my purpose. It works very well for 1 camera.

Saved image from the carema using v4l2 and libpng Once I begin to grab images from multiple cameras (successively) I get corrupt images. Corrupt image when grabbing picture from multiple cameras The more cameras I sue the more artefacts/stripes in the images appear. It does not make any difference if I save the images as BMP using another code. So I assume the problem has nothing to do with the storing routine. The resolution is also right (744 * 480).

The result is the same on two different computers running Fedora and Debian. I am absolutely baffled and can not find any clue what is going wrong. Could me please someone give some hints ?

Here is my code

int main()
{
    /* #################### INIT #################### */

    int numOfCameras = 1;
    int xRes = 744;
    int yRes = 480;
    int exposure = 2000;
    unsigned int timeBetweenSnapshots = 2; // in sec
    char fileName[sizeof "./output/image 000 from camera 0.PNG"];

    static const char *devices[] = { "/dev/video0", "/dev/video1", "/dev/video2", "/dev/video3", "/dev/video4", "/dev/video5", "/dev/video6", "/dev/video7" };

    struct v4l2_capability cap[8];
    struct v4l2_control control[8];
    struct v4l2_format format[8];
    struct v4l2_requestbuffers req[8];
    struct v4l2_buffer buffer[8];

    int type = V4L2_BUF_TYPE_VIDEO_CAPTURE; // had to declare the type here because of the loop

    unsigned int i;
    unsigned int j;
    unsigned int k;

    int fd[8];
    void **mem[8];

    /* #################### OPEN DEVICE #################### */

    for (j = 0; j < numOfCameras; ++j) {

        fd[j] = open(devices[j], O_RDWR);
        ioctl(fd[j], VIDIOC_QUERYCAP, &cap[j]);


        /* #################### CAM CONTROLL #################### */

        control[j].id = V4L2_CID_EXPOSURE_AUTO;
        control[j].value = V4L2_EXPOSURE_SHUTTER_PRIORITY;
        ioctl(fd[j], VIDIOC_S_CTRL, &control[j]);

        control[j].id = V4L2_CID_EXPOSURE_ABSOLUTE;
        control[j].value = exposure;
        ioctl(fd[j], VIDIOC_S_CTRL, &control[j]);

        /* #################### FORMAT #################### */

        ioctl(fd[j], VIDIOC_G_FMT, &format[j]);
        format[j].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        format[j].fmt.pix.width = xRes;
        format[j].fmt.pix.height = yRes;
        //format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
        format[j].fmt.pix.pixelformat = V4L2_PIX_FMT_GREY;
        ioctl(fd[j], VIDIOC_S_FMT, &format[j]);

        /* #################### REQ BUF #################### */

        req[j].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        req[j].count = 4;
        req[j].memory = V4L2_MEMORY_MMAP;
        ioctl(fd[j], VIDIOC_REQBUFS, &req[j]);
        mem[j] = malloc(req[j].count * sizeof(*mem));

        /* #################### MMAP #################### */

        for (i = 0; i < req[j].count; ++i) {
            buffer[j].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            buffer[j].memory = V4L2_MEMORY_MMAP;
            buffer[j].index = i;
            ioctl(fd[j], VIDIOC_QUERYBUF, &buffer[j]);
            mem[j][i] = mmap(0, buffer[j].length,
                    PROT_READ|PROT_WRITE,
                    MAP_SHARED, fd[j], buffer[j].m.offset);
        }

        /* #################### CREATE QUEUE #################### */

        for (i = 0; i < req[j].count; ++i) {
            buffer[j].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            buffer[j].memory = V4L2_MEMORY_MMAP;
            buffer[j].index = i;
            ioctl(fd[j], VIDIOC_QBUF, &buffer[j]);
        }

    } /* ### ### end of camera init ### ### */

    /* ##################### STREAM ON #################### */
    for (j = 0; j < numOfCameras; ++j) {

        ioctl(fd[j], VIDIOC_STREAMON, &type);
    }


    /* ##################### GET FRAME ##################### */

    k = 0;
    while (!kbhit()){
        k ++;

        for (j = 0; j < numOfCameras; j++) {

            buffer[j].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            buffer[j].memory = V4L2_MEMORY_MMAP;
            usleep(100000);
            ioctl(fd[j], VIDIOC_DQBUF, &buffer[j]);

            // create filename
            sprintf(fileName, "./output/image %03d from camera %d.PNG", k, j);
            // save as PNG file
            saveToPng(mem[j][buffer[j].index], fileName, xRes, yRes);

            ioctl(fd[j], VIDIOC_QBUF, &buffer[j]);

            sleep(timeBetweenSnapshots);
        }
    }

    /* ##################### STREAM OFF ##################### */
    for (j = 0; j < numOfCameras; ++j) {

        ioctl(fd[j], VIDIOC_STREAMOFF, &type);
    }

    /* ##################### CLEANUP ##################### */

    for (j = 0; j < numOfCameras; ++j) {

        close(fd[j]);
        free(mem[j]);
    }

    return (0);
}
2
  • 1
    This is a very borderline question for this SE, anything programming related should be asked on StackOverflow instead.
    – timonsku
    Sep 2, 2014 at 18:39
  • Are you sure that the frame rate and frame dimensions are uniform between the cameras? That looks suspiciously like improper line timing, which would result from having the wrong height and width and/or frame rate.
    – AJ Henderson
    Sep 2, 2014 at 20:09

2 Answers 2

1

Your issue is probably that you don't have enough USB bandwidth available, if your webcams support it switch to MJPEG instead of uncompressed frames. Usually any webcam supports MJPEG encoding to deliver frames to your PC.

Here a similar question on SO https://stackoverflow.com/questions/9781770/capturing-multiple-webcams-uvcvideo-with-opencv-on-linux

0

I am fairly certain you are getting the corruption because of the usleep(100000); - This is based on the fact I have achieved similar corruption using one webcam by adding usleep(100000) to my code.

My usleep(100000); is substitution for running an opencl kernel, meaning this point I know the problem is that the usleep(100000) affects the video frame delivery in some way (this happens in my code if I strip out all other code, and just save the frames to disk as ppm files).

What I don't know is why ....

I can put the usleep anywhere in my code, the affect is always the same.

Perhaps the video4linux webcam code needs to be on a different pthread ..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.