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.
Once I begin to grab images from multiple cameras (successively) I get corrupt images. 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);
}