Re: Corrupt images, when capturing images from multiple cameras using the V4L2 driver
Hi Karel, On Friday 05 September 2014 06:09 PM, Mácha, Karel wrote: Hello Alaganraj, thank you very much for your reply and your tips. I tried to improve my code as you suggested and also implemented several other things, which should improve the result. I set the cameras to 15fps using VIDIOC_S_PARM. This reduces the frequency of corrupt images. I zero fill any structs before using ioctl with the #define CLEAR(x) memset((x), 0, sizeof(x)) macro. I use select() before VIDIOC_DQBUF. I copy the buffer and create the resulting image from the copy, so I can put the original buffer back immediately. Instead of copy, increase no of buffers to 6 or 8 while REQBUFS. As you are storing as image, i think it's ok to have frame drops. I tested my code with valgrind and there are no memory leaks. However I still get corrupt images. If I use 4 cameras I gat almost no bad images, 6 cameras produces mostly good pictures, but 8 cams produces mostly not single one error-free set. Sometimes the buffer.bytesused returns less bytes then x-resolution x y-resolution and I get bad pictures, sometimes I get bad pictures even if the bytesused value is ok. The most surprising finding is, how significant the sleep() time, before every VIDIOC_STREAMON improves the result. If I wait 5 seconds, before I turn-on the next camera, I got following results. I don't know how this delay impacts the result. May be experts can guide you. Always cc to people, for example you've taken this code from Laurent's presentation, so cc to him to get attention. - first 8 images mostly corrupt - second 8 images: few of them bad - next 5-6 series! are clear - after the 7th, 8th image series (camera1 ... camera8) artifacts appear again. The longer the capture works, the more artifacts appears. I put the improved version of the code here: http://pastebin.mozilla.org/6330868 I really do not understand what is the source of my problems. Greetings - Karel Am Freitag, den 05.09.2014, 01:41 +0530 schrieb Alaganraj Sandhanam: Hi Karel, I suggest you to zero fill v4l2 structures before assign values also check the return value of all ioctl call. for example, struct v4l2_format fmt; memset(fmt, 0, sizeof fmt); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = xRes; ret = ioctl(fd, VIDIOC_S_FMT, fmt); if (ret 0) printf(VIDIOC_S_FMT failed: %d\n, ret); Please find comments in-line. On Tuesday 02 September 2014 05:36 PM, Mácha, Karel wrote: Hello, I would like to grab images from multiple cameras under using the V4L2 API. I followed the presentation under found on http://linuxtv.org/downloads/presentations/summit_jun_2010/20100206-fosdem.pdf used the code and adapted it sightly for my purpose. It works very well for 1 camera. However Once I begin to grab images from multiple cameras (successively) I get corrupt images. I uploaded an example image to http://www.directupload.net/file/d/3733/9c4jx3pv_png.htm Although I set the right resolution for the camera (744 x 480), the output of buffer.bytesused, after the VIDIOC_DQBUF does not correspond with the expected value (744x480 = 357120). This would probably explain the corrupt images. The more camera I use, the less buffer.bytesused I get and the more stripes are in the image. Could you please give me a hint, what am I doing wrong ? Thanks, Karel Here is the minimal C code I use for my application: int main() { /* # INIT # */ int numOfCameras = 6; As it works well for 1 camera, try with only 2 instead of 6 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]; //unsigned char **mem[8]; /* # OPEN DEVICE # */ for (j = 0; j numOfCameras; ++j) { fd[j] = open(devices[j], O_RDWR); ioctl(fd[j], VIDIOC_QUERYCAP, cap[j]); check the return value /* # CAM CONTROLL ### */ zero fill control[j] memset(control[j], 0, sizeof control[j]); 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;
Re: Corrupt images, when capturing images from multiple cameras using the V4L2 driver
Hello Alaganraj, thank you very much for your reply and your tips. I tried to improve my code as you suggested and also implemented several other things, which should improve the result. I set the cameras to 15fps using VIDIOC_S_PARM. This reduces the frequency of corrupt images. I zero fill any structs before using ioctl with the #define CLEAR(x) memset((x), 0, sizeof(x)) macro. I use select() before VIDIOC_DQBUF. I copy the buffer and create the resulting image from the copy, so I can put the original buffer back immediately. I tested my code with valgrind and there are no memory leaks. However I still get corrupt images. If I use 4 cameras I gat almost no bad images, 6 cameras produces mostly good pictures, but 8 cams produces mostly not single one error-free set. Sometimes the buffer.bytesused returns less bytes then x-resolution x y-resolution and I get bad pictures, sometimes I get bad pictures even if the bytesused value is ok. The most surprising finding is, how significant the sleep() time, before every VIDIOC_STREAMON improves the result. If I wait 5 seconds, before I turn-on the next camera, I got following results: - first 8 images mostly corrupt - second 8 images: few of them bad - next 5-6 series! are clear - after the 7th, 8th image series (camera1 ... camera8) artifacts appear again. The longer the capture works, the more artifacts appears. I put the improved version of the code here: http://pastebin.mozilla.org/6330868 I really do not understand what is the source of my problems. Greetings - Karel Am Freitag, den 05.09.2014, 01:41 +0530 schrieb Alaganraj Sandhanam: Hi Karel, I suggest you to zero fill v4l2 structures before assign values also check the return value of all ioctl call. for example, struct v4l2_format fmt; memset(fmt, 0, sizeof fmt); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = xRes; ret = ioctl(fd, VIDIOC_S_FMT, fmt); if (ret 0) printf(VIDIOC_S_FMT failed: %d\n, ret); Please find comments in-line. On Tuesday 02 September 2014 05:36 PM, Mácha, Karel wrote: Hello, I would like to grab images from multiple cameras under using the V4L2 API. I followed the presentation under found on http://linuxtv.org/downloads/presentations/summit_jun_2010/20100206-fosdem.pdf used the code and adapted it sightly for my purpose. It works very well for 1 camera. However Once I begin to grab images from multiple cameras (successively) I get corrupt images. I uploaded an example image to http://www.directupload.net/file/d/3733/9c4jx3pv_png.htm Although I set the right resolution for the camera (744 x 480), the output of buffer.bytesused, after the VIDIOC_DQBUF does not correspond with the expected value (744x480 = 357120). This would probably explain the corrupt images. The more camera I use, the less buffer.bytesused I get and the more stripes are in the image. Could you please give me a hint, what am I doing wrong ? Thanks, Karel Here is the minimal C code I use for my application: int main() { /* # INIT # */ int numOfCameras = 6; As it works well for 1 camera, try with only 2 instead of 6 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]; //unsigned char **mem[8]; /* # OPEN DEVICE # */ for (j = 0; j numOfCameras; ++j) { fd[j] = open(devices[j], O_RDWR); ioctl(fd[j], VIDIOC_QUERYCAP, cap[j]); check the return value /* # CAM CONTROLL ### */ zero fill control[j] memset(control[j], 0, sizeof control[j]); 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 # */ zero fill format[j] memset(format[j], 0, sizeof format[j]); ioctl(fd[j], VIDIOC_G_FMT, format[j]); format[j].type =
Re: Corrupt images, when capturing images from multiple cameras using the V4L2 driver
Hi Karel, I suggest you to zero fill v4l2 structures before assign values also check the return value of all ioctl call. for example, struct v4l2_format fmt; memset(fmt, 0, sizeof fmt); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = xRes; ret = ioctl(fd, VIDIOC_S_FMT, fmt); if (ret 0) printf(VIDIOC_S_FMT failed: %d\n, ret); Please find comments in-line. On Tuesday 02 September 2014 05:36 PM, Mácha, Karel wrote: Hello, I would like to grab images from multiple cameras under using the V4L2 API. I followed the presentation under found on http://linuxtv.org/downloads/presentations/summit_jun_2010/20100206-fosdem.pdf used the code and adapted it sightly for my purpose. It works very well for 1 camera. However Once I begin to grab images from multiple cameras (successively) I get corrupt images. I uploaded an example image to http://www.directupload.net/file/d/3733/9c4jx3pv_png.htm Although I set the right resolution for the camera (744 x 480), the output of buffer.bytesused, after the VIDIOC_DQBUF does not correspond with the expected value (744x480 = 357120). This would probably explain the corrupt images. The more camera I use, the less buffer.bytesused I get and the more stripes are in the image. Could you please give me a hint, what am I doing wrong ? Thanks, Karel Here is the minimal C code I use for my application: int main() { /* # INIT # */ int numOfCameras = 6; As it works well for 1 camera, try with only 2 instead of 6 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]; //unsigned char **mem[8]; /* # OPEN DEVICE # */ for (j = 0; j numOfCameras; ++j) { fd[j] = open(devices[j], O_RDWR); ioctl(fd[j], VIDIOC_QUERYCAP, cap[j]); check the return value /* # CAM CONTROLL ### */ zero fill control[j] memset(control[j], 0, sizeof control[j]); 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 # */ zero fill format[j] memset(format[j], 0, sizeof format[j]); 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 */ memset(req[j], 0, sizeof req[j]); 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) { memset(buffer[j], 0, sizeof buffer[j]); 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) { memset(buffer[j], 0, sizeof buffer[j]); buffer[j].type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer[j].memory = V4L2_MEMORY_MMAP; buffer[j].index = i;