Hello guys and gals. I had some problems getting my really cheap sn9c102-based webcam to function with the otherwise fine work of Nicola Orru' on pwlib's V4L2-plugin. After some debugging and a (very short) time trying to figure out the V4L2-API, I found that my cheap camera didn't handle mmap with multiple buffers. I dug around a bit and discovered that the normal V4L-plugin only use one buffer for mmap, so I decided to try this for V4L2 as well. I cleaned it up a bit, removed all references to multiple buffers and it worked flawlessly. I've both streamed from my webcam as well as CNN from my bttv-card on the V4L2-plugin today ....without any hiccups. Beware tho'. I've got almost 10 years of Linux-experience, but this is my first attempt at programming devices. I would appreciate if as many as possible could review and test this. I'm not even sure if it's frowned upon, or if I broke something else by using only one videobuffer. I might even have done something totally stupid :) As far as I can tell, 2 things still needs to be done with the V4L2-plugin: - better device-detection, which Nicola is working on - "Test Settings" in the druid hangs indefinitely. Someone(tm) needs to look into which functions that needs. Now I need to get back to my Master's thesis on the semantic web :) -- Cheers, Heikki
diff -ru pwlib-cvs-20041102.CVS/plugins/vidinput_v4l2/vidinput_v4l2.cxx pwlib-cvs-20041102.CVS.hh/plugins/vidinput_v4l2/vidinput_v4l2.cxx --- pwlib-cvs-20041102.CVS/plugins/vidinput_v4l2/vidinput_v4l2.cxx 2004-10-27 12:02:54.000000000 +0200 +++ pwlib-cvs-20041102.CVS.hh/plugins/vidinput_v4l2/vidinput_v4l2.cxx 2004-11-04 00:19:23.000000000 +0100 @@ -197,12 +197,12 @@ struct v4l2_buffer buf; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.index = 0; + buf.memory = V4L2_MEMORY_MMAP; if (::ioctl(videoFd, VIDIOC_QBUF, &buf) < 0) { PTRACE(3,"PVidInDev\tVIDIOC_QBUF failed : " << ::strerror(errno)); return FALSE; } - buf.index = 0; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (::ioctl(videoFd, VIDIOC_STREAMON, &buf.type) < 0) { @@ -211,14 +211,6 @@ } started = TRUE; - // requeue all buffers - for (buf.index = 0; buf.index < videoBufferCount; buf.index++) { - PTRACE(3,"PVidInDev\tQBUF for index:" << buf.index); - if (::ioctl(videoFd, VIDIOC_QBUF, &buf) < 0) { - PTRACE(3,"PVidInDev\tQBUF failed : " << ::strerror(errno)); - return FALSE; - } - } } return TRUE; @@ -579,37 +571,32 @@ return FALSE; struct v4l2_requestbuffers reqbuf; - reqbuf.count = 2; // we shouldn't need more + reqbuf.count = 1; // Some cameras don't handle more, and we don't need it anyway. reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; reqbuf.memory = V4L2_MEMORY_MMAP; - if (::ioctl(videoFd, VIDIOC_REQBUFS, &reqbuf) < 0 || - reqbuf.count < 2 || - reqbuf.count > NUM_VIDBUF) { + if (::ioctl(videoFd, VIDIOC_REQBUFS, &reqbuf) < 0) { PTRACE(3,"PVidInDev\tREQBUFS failed : " << ::strerror(errno)); return FALSE; } struct v4l2_buffer buf; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = 0; + if (::ioctl(videoFd, VIDIOC_QUERYBUF, &buf) < 0) { + PTRACE(3,"PVidInDev\tQUERYBUF failed : " << ::strerror(errno)); + return FALSE; + } - videoBufferCount = reqbuf.count; - for (buf.index = 0; buf.index < videoBufferCount; buf.index++) { - if (::ioctl(videoFd, VIDIOC_QUERYBUF, &buf) < 0) { - PTRACE(3,"PVidInDev\tQUERYBUF failed : " << ::strerror(errno)); - return FALSE; - } - - if ((videoBuffer[buf.index] = (BYTE *)::mmap(0, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, videoFd, buf.m.offset)) == MAP_FAILED) { - PTRACE(3,"PVidInDev\tmmap failed : " << ::strerror(errno)); - return FALSE; - } + if ((videoBuffer = (BYTE *)::mmap(0, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, videoFd, buf.m.offset)) == MAP_FAILED) { + PTRACE(3,"PVidInDev\tmmap failed : " << ::strerror(errno)); + return FALSE; } isMapped = TRUE; - PTRACE(7,"PVidInDev\tset mapping for " << videoBufferCount << " buffers, fd=" << videoFd); - + PTRACE(7,"PVidInDev\tset mapping for 1 buffer, fd=" << videoFd); return TRUE; } @@ -621,13 +608,14 @@ return; struct v4l2_buffer buf; + buf.index = 0; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; for (buf.index = 0; ; buf.index++) { if (::ioctl(videoFd, VIDIOC_QUERYBUF, &buf) < 0) break; - - ::munmap(videoBuffer[buf.index], buf.length); + ::munmap(videoBuffer, buf.length); } isMapped = FALSE; @@ -714,9 +702,9 @@ // If converting on the fly do it from frame store to output buffer, // otherwise do straight copy. if (converter != NULL) - converter->Convert(videoBuffer[buf.index], buffer, bytesReturned); + converter->Convert(videoBuffer, buffer, bytesReturned); else { - memcpy(buffer, videoBuffer[buf.index], buf.bytesused); + memcpy(buffer, videoBuffer, buf.bytesused); if (bytesReturned != NULL) *bytesReturned = buf.bytesused; } diff -ru pwlib-cvs-20041102.CVS/plugins/vidinput_v4l2/vidinput_v4l2.h pwlib-cvs-20041102.CVS.hh/plugins/vidinput_v4l2/vidinput_v4l2.h --- pwlib-cvs-20041102.CVS/plugins/vidinput_v4l2/vidinput_v4l2.h 2004-10-27 12:02:54.000000000 +0200 +++ pwlib-cvs-20041102.CVS.hh/plugins/vidinput_v4l2/vidinput_v4l2.h 2004-11-04 00:17:22.000000000 +0100 @@ -91,9 +91,7 @@ BOOL canSelect; BOOL canSetFrameRate; BOOL isMapped; -#define NUM_VIDBUF 4 - BYTE * videoBuffer[NUM_VIDBUF]; - uint videoBufferCount; + BYTE * videoBuffer; int videoFd; int frameBytes;
Attachment:
signature.asc
Description: Dette er en digitalt signert meldingsdel