This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Unable to dequeue UserPointer DSS Buffer

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

  • My console output is:

    Queue the buffers
     queue buffer 0 to camera ring buffer
     queue buffer 1 to camera ring buffer
     queue buffer 2 to camera ring buffer
     queue buffer 3 to omapdss ring buffer
     queue buffer 4 to omapdss ring buffer
     queue buffer 5 to omapdss ring buffer
    Initialize Stream
    Entering Streaming Loop
    Select DSS buffer
     dequeue a buffer from DSS
     enqueue buffer 3 to Camera
    Select Camera buffer
     dequeue buffer from Camera
     enqueue buffer 0 to DSS
     reading keyboard events
    Select DSS buffer
     dequeue a buffer from DSS
     enqueue buffer 4 to Camera
    Select Camera buffer
     dequeue buffer from Camera
     enqueue buffer 1 to DSS
     reading keyboard events
    Select DSS buffer
     dequeue a buffer from DSS
    ---> Application stops