Help!
The OMAP DSS V4L2 driver does not flag buffers in user pointer mode correctly!
I am using the OMAP DSS V4L2 driver in user pointer mode. The pointer access unqueued memory mapped usb camera buffers. My application dequeues a display buffer and enqueues it to camera buffers and vice versa.
With this method I expect a smaller delay between camera and display.
Enqueuing the cameras mmapped buffers to display buffers queue works fine for the first time, but as soon dss gets a buffer which had been queued to camera before, the game is over. In other words, the dss v4l2 driver does not set the V4L2_BUF_FLAG_DONE flag. Querrying the dds buffers shows that all dss buffers are either not queued ( flag 0 ) which means that they are queued to camera mmapped, or the dss buffers are flagged as queued to dss, but not ready to be unqueued.
I beleave that this is a bug in V4L2 driver, but to be on the save side I add my code.
My code is:
// INIT STREAM
unsigned int i;
struct v4l2_buffer buf;
PRINT("Queue the buffers\n");
for (i = 0; i < BUFFERCOUNTCAM; ++i)
{
PRINT(" queue buffer %i to camera ring buffer\n", i);
CLEAR (buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
CTL(camera.fd, VIDIOC_QBUF, &buf);
}
for (i = BUFFERCOUNT-BUFFERCOUNTCAM; i < BUFFERCOUNT; ++i)
{
PRINT(" queue buffer %i to omapdss ring buffer\n", i);
CLEAR (buf);
buf.index = i;
buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
buf.memory = V4L2_MEMORY_USERPTR;
buf.m.userptr = (unsigned long) camera.buff[i].start;
buf.length = camera.buff[i].length;
CTL(omapdss.fd_v4l, VIDIOC_QBUF, &buf);
}
PRINT("Initialize Stream\n");
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
CTL(camera.fd, VIDIOC_STREAMON, &type);
type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
CTL(omapdss.fd_v4l, VIDIOC_STREAMON, &type);
// LOOP:
goto_dss:
FD_ZERO (&fds);
FD_SET (omapdss.fd_v4l, &fds);
tv.tv_sec = 2; tv.tv_usec = 0;
CLEAR(buffer);
buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
buffer.memory = V4L2_MEMORY_USERPTR;
PRINT("Select DSS buffer\n");
select_return = select (omapdss.fd_v4l + 1, &fds, NULL, NULL, &tv);
if (select_return == 0) ERROR_EXIT("select timeout dss buffer");
// Dequeue buffer from dss and enqueue buffer to camera
PRINT(" dequeue a buffer from DSS\n");
CTL(omapdss.fd_v4l, VIDIOC_DQBUF, &buffer);
for (i = 0; i < BUFFERCOUNT; ++i)
if (buffer.m.userptr == (unsigned long) camera.buff[i].start) break;
assert(i < BUFFERCOUNT);
CLEAR(buffer);
buffer.index = i;
buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buffer.memory = V4L2_MEMORY_MMAP;
PRINT(" enqueue buffer %i to Camera\n", i);
CTL(camera.fd, VIDIOC_QBUF, &buffer);
// Wait for Camera buffer ready to be dequeued
FD_ZERO (&fds);
FD_SET (camera.fd, &fds);
tv.tv_sec = 2; tv.tv_usec = 0;
CLEAR(buffer);
buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buffer.memory = V4L2_MEMORY_MMAP;
PRINT("Select Camera buffer\n");
select_return = select (camera.fd + 1, &fds, NULL, NULL, &tv);
// Dequeue buffer from camera and enqueue buffer to dss
PRINT(" dequeue buffer from Camera\n");
CTL(camera.fd, VIDIOC_DQBUF, &buffer);
i = buffer.index; // camera mmap returns correct index
PRINT(" enqueue buffer %i to DSS\n", i);
CLEAR(buffer);
buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
buffer.memory = V4L2_MEMORY_USERPTR;
buffer.index = i;
buffer.m.userptr = (unsigned long) camera.buff[i].start;
buffer.length = camera.buff[i].length;
CTL(omapdss.fd_v4l, VIDIOC_QBUF, &buffer);
// BACK TO LOOP