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.

Trying to poll capture device before blocking on Capture_get()

So, dmai Capture_get() blocks if there's not a frame already available.  I'm trying to figure out how to do polling, so that I can determine whether or not a frame is available.

I got a clue from http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/100/t/7706.aspx , but that doesn't provide complete info.

I have tried using both select() and poll() to no avail.  Specifically, I have identified that Capture_create() is creating a Capture_Handle with fd=12.  I pass that variable (not hard coded 12) to either select() or poll() and I always get a return value of 0, indicating that no data is available.  Meanwhile, I try this substituting fileno(stdin) for the file number, and the code works as expected in response to pressing enter on the keyboard.  Also, I know that there IS data available, because a test call to Capture_get() returns that data successfully without blocking.

What's wrong?  How do I do this correctly?  Am I trying the polling at the wrong "level" in the underlying software?  I know my code itself is correct for what I'm trying to do, but I'm obviously not trying the correct thing.

struct pollfd fds[1];
while (TRUE) {
fds[0].fd = hCap->fd;
fds[0].events = 0xFF;//POLLIN;
fds[0].revents = 0;
poll(&fds, 1, 1/*ms*/);
if (fds[0].revents & POLLIN) {
printf("_____G_____");fflush(stdout);
Capture_get(hCap, &hCapBuf);
Capture_put(hCap, hCapBuf);
} else {
printf("%x;",fds[0].events);fflush(stdout);
??Capture_get(hCap, &hCapBuf);
??Capture_put(hCap, hCapBuf);

Consider the code snippet above.  I've overridden the desired events with 0xFF, assuming that will ask for all possible events.  I never get the POLLIN match and always to to the else clause.  The printf always prints "0;", so there are NO events at all returned.  Just to prove that there will be at some time, I optionally include the Capture_get() and Capture_put() lines.  With neither present, I get a large number of "0;" outputs per second.  This means there's no blocking, and no events getting returned.  If I include both the Capture_get() and Capture_put() lines, I get approximately 30 "0;" outputs per second, exactly what's expected from Capture_get() blocking me down to the 30Hz input frame rate.  If I include ONLY the Capture_get() and not the Capture_put(), then I get exactly 4 "0;" outputs, because my capture buftab has only 4 buffers and thus this proves that the Capture_put() really is necessary and that the dmai capture routing won't roll around in a circle ahead of me.  (I realize that while the Capture_get() is included, my poll could always get no data then Capture_get() block until the data is there.  But with Capture_get() omitted, which I've tried, the poll never says there's data.)

So, I've learned a little about the definite need for Capture_put().  I've established that my input is working and data is becoming available.  Using fileno(stdin) and the enter key, I've established that the above code structure should work.  I'm simply NOT getting back an indication that an event has occurred, the expected event being that data is available for Capture_get() to be called without blocking.

Argh!!!!!!!!!

Thanks,

Helmut

 

 

  • Not familiar with the device driver you are using. Speaking in general terms. polling and blocking have to be supported by the deviice driver. It doesn't come automatically as part of the kernel driver framework. People usually use poll() if they have a single threaded app waiting on more than one fd. If only one fd is involved, non blocking reads is alternative. Others use blocking reads in another thread to avoid blocking. But multi-threading brings in a lot of baggage like semaphores, mutexs, etc.

  • Thanks, Norman.  Between when I posted and just reading your response, I finally found a solution that works for me.

    dmai Capture_create() calls open() with flag O_RDWR.  I found that if I or into that O_NONBLOCK, then Capture_get() won't block anymore.  So I renamed Capture_create() to Capture_create_blocksmart(), added a third parameter as "int nonblocking", used that to optionally include O_NONBLOCK in the open call, then created a replacement Capture_create() that calls Capture_create_blocksmart() with the third parameter 0 (blocking) for backward compatibility of Capture_create().  Next, I change my current version of my application to call Capture_create_blocksmart() with the third parameter 1 (nonblocking).  Next, I write a cover function in my application that calls the newly nonblocking Capture_get() in a loop, doing what I need.  FYI, what I needed was to get only the most recent frame, dropping any additional queue frames, and indeed blocking if no frames were available.  That is, if no frames are available, it will block.  If one frame is available, it will return that one.  If multiple frames are available (because some other process in my application slowed me down), then it will return only the most recent frame, dropping all the prior ones.