Hi Paulo, On Wednesday 01 October 2014 11:48:26 Paulo Assis wrote: > Laurent hi, > > 2014-09-30 23:31 GMT+01:00 Laurent Pinchart: > > Hi Paulo, > > > > Thank you for investigation this. > > > > On Tuesday 30 September 2014 13:56:15 Paulo Assis wrote: > > > >> Ok, > >> so I've set a workaround in guvcview, it now uses the length filed if > >> bytesused is set to zero. > >> Anyway I think this violates the v4l2 api: > >> http://linuxtv.org/downloads/v4l-dvb-apis/buffer.html > >> > >> bytesused - ..., Drivers must set this field when type refers to an > >> input stream, ... > >> > >> without this value we have no way of knowing the exact frame size for > >> compressed formats. > >> > >> And this was working in uvcvideo up until 3.16, I don't know how many > >> userspace apps rely on this value, but at least guvcview does, and > >> it's currently broken for uvcvideo devices in the latest kernels. > > > > It took me some time to debug the problem, and I think the problem is > > actually on guvcview's side. When dequeuing a video buffer, the > > application requeues it immediately before processing the buffer's > > contents. The VIDIOC_QBUF ioctl will reset the bytesused field to 0. > > > > While you could work around the problem by using a different struct > > v4l2_buffer instance for the VIDIOC_QBUF call, the V4L2 doesn't allow > > userspace application to access a queued buffer. You must process the > > buffer before requeuing it. > > I though this was why we requested multiple buffers. If this is true > then using just one buffer is enough, also using multiple threads to > process frame data seems useless in this case, since we need to > process the buffer before queueing the next one. > > I thought one could request 4 buffers for mmap and do: > > VIDIOC_DQBUF data->buf[0] > VIDIOC_QBUF driver queues->buf[1] > > process buf[0] > > VIDIOC_DQBUF data->buf[1] > VIDIOC_QBUF driver queues->buf[2] > > process buf[1] > > VIDIOC_DQBUF data->buf[2] > VIDIOC_QBUF driver queues->buf[3] > > process buf[2] > > VIDIOC_DQBUF data->buf[3] > VIDIOC_QBUF driver queues->buf[0] > > process buf[3]
That's certainly valid. However, if I'm not mistaken, after dequeuing buffer i you immediately requeue the same buffer, not buffer i+1. What you should do is queueing all buffers right before starting the stream (I think you're doing fine there, but I haven't double-checked), and then, when a buffer is available, perform the following sequence. VIDIOC_DQBUF() -> returns buffer i process buffer i VIDIOC_QBUF(buffer i) You can perform processing in a different thread if needed, the important part being not to requeue the buffer before userspace is done with it. The bug that caused guvcview to stop functioning is in v4l2_core.c. memset(&vd->buf, 0, sizeof(struct v4l2_buffer)); vd->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; vd->buf.memory = V4L2_MEMORY_MMAP; ret = xioctl(vd->fd, VIDIOC_DQBUF, &vd->buf); if(!ret) { /* * driver timestamp is unreliable * use monotonic system time */ vd->timestamp = ns_time_monotonic(); /* queue the buffers */ ret = xioctl(vd->fd, VIDIOC_QBUF, &vd->buf); ... } The VIDIOC_DQBUF call will return the correct bytesused value in vd- >buf.bytesused, but the VIDIOC_QBUF call then resets that value to 0. As a quick workaround while you fix the buffer processing sequence, you can copy vd->buf into a new local v4l2_buffer variable after calling VIDIOC_DQBUF, and use that local variable in the VIDIOC_QBUF call. Note that you will still violate the V4L2 API as you're not allowed to touch a buffer after requeuing it, but it should hide the problem and get guvcview to display images again. > Now if we need to process the buffer between VIDIOC_DQBUF and > VIDIOC_QBUF, whats the point in using more than one buffer ? -- Regards, Laurent Pinchart -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html