Re: Corrupt images, when capturing images from multiple cameras using the V4L2 driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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;
> 			ioctl(fd[j], VIDIOC_QBUF, &buffer[j]);
check the return value
> 		}
> 
> 	} /* ### ### end of camera init ### ### */
> 
> 	/* ##################### STREAM ON ##################### */
> 	for (j = 0; j < numOfCameras; ++j) {
> 
> 		ioctl(fd[j], VIDIOC_STREAMON, &type);
> 	}
> 
> 
> 	/* ##################### GET FRAME ##################### */
> 
> 	k = 0;
> 	while (!kbhit()){
Instead of multiple frames, capture single frame and check the result.
> 		k ++;
> 
> 		for (j = 0; j < numOfCameras; j++) {
> 
    memset(buffer[j], 0, sizeof buffer[j]);
> 			buffer[j].type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
> 			buffer[j].memory = V4L2_MEMORY_MMAP;
> 			usleep(100000);
> 			ioctl(fd[j], VIDIOC_DQBUF, &buffer[j]);
> 			printf("\nBuffer {%p}, Buf. Index %d, Buf. bytes used %d\n",
> mem[j][buffer[j].index], buffer[j].index,  buffer[j].bytesused);
> 
> 			// 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);
> }
> 
> **********************************************************************
> Leibniz-Institut für Agrartechnik Potsdam-Bornim e.V.
> Max-Eyth-Allee 100
> D-14469 Potsdam
>  
> Vorstand: 
> Prof. Dr. Reiner Brunsch (Wissenschaftlicher Direktor)
> Dr. Martin Geyer (Stellvertreter des Wissenschaftlichen Direktors)
> Prof. Dr. Thomas Amon  (2. Stellvertreter des Wissenschaftlichen Direktors)
> Dr. Uta Tietz (Verwaltungsleiterin) 
> Amtsgericht Potsdam, VR 680 P, USt-ID DE811704150
> 
> **********************************************************************
> This email and any files transmitted with it are confidential and
> intended solely for the use of the individual or entity to whom they
> are addressed. If you have received this email in error please notify
> the system manager.
> 
> Scanned by the Clearswift SECURE Email Gateway.
> 
> www.clearswift.com
> **********************************************************************
> N�����r��y���b�X��ǧv�^�)޺{.n�+����{���bj)���w*jg��������ݢj/���z�ޖ��2�ޙ���&�)ߡ�a�����G���h��j:+v���w�٥
> 

Regards,
Alaganraj
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux