To: video4linux-list@xxxxxxxxxx 
Subject: v4l2 + select() + read() 
From: Gerd Knorr <kraxel@xxxxxxxxxxx> 
Date: 15 May 2001 09:02:39 GMT 
Delivered-to: video4linux-list@xxxxxxxxxxxxxxxxxx 
Newsgroups: lists.linux.video4linux 
Organization: [x] network byte order 
User-agent: slrn/0.9.7.0 (Linux) 

Yet another v4l2 API comment / update request.

The current specification for capture read() and for non-blocking
I/O is somewhat unclear.  How this is supposed to work in detail?

For non-blocking I/O using read() the driver has to capture data
into a kernel bounce buffer and then just copy_to_user the image
data (because it does not know the destination address yet at the
time the capture is started).

How such a capture is triggered?  Should the application call read()
once (which would make the driver start capture and return -EAGAIN)?
What about select()?  Does that also trigger a capture (very ugly side
effect IMHO)?  What happens when a frame was returned by the read()
call?  Should the driver automagically schedule the next capture or
not?

Somehow I feel non-blocking I/O via read() isn't a good idea for
video frames ...


A related problem:  The API document allows drivers to refuse read()
calls with sizes smaller than a full frame ("a partial frame may be
[ ... ] impractical or inefficient to implement").  Which doesn't
make sense to me, assuming we require the drivers to support
non-blocking I/O via read().  The driver needs a bounce buffer
for the video data anyway (see above) and it is absolutely no
problem to copy_to_user data in small pieces then.

  Gerd

-- 
Gerd Knorr <kraxel@xxxxxxxxxxx>  --  SuSE Labs, Außenstelle Berlin

To: video4linux-list@xxxxxxxxxx 
Subject: Re: v4l2 + select() + read() 
From: Bill Dirks <bdirks@xxxxxxxxxx> 
Date: Tue, 29 May 2001 14:09:30 -0700 
Delivered-to: video4linux-list@xxxxxxxxxxxxxxxxxx 
Organization: Rendition 

Gerd Knorr wrote:
> 
> Yet another v4l2 API comment / update request.
> 
> The current specification for capture read() and for non-blocking
> I/O is somewhat unclear.  How this is supposed to work in detail?

It's up to the driver writer. I really don't think this needs to be
dictated.

If I recall correctly, the way I made my driver work is:
When a read() call comes in:
     if there is no data in the throw buffer, or the data in the throw
buffer is "too old" then initiate a new frame capture. If it was a
blocking read() then sleep, else return an error code (I forget which).
     if there is good data, then copy it to the user buffer, and
initiate a new frame capture before returning from read().

select() will initiate a new frame capture as a side effect if there is
no (good) data ready. Otherwise it will sleep forever.

I guess for non-blocking read() capture, the driver would have to
automatically initiate a capture on a read() call or else implement
blocking read() and non-blocking read() the same way. That latter is not
as bad as it sounds, because the video source produces frames
continuously, so, in a sense, there is always data to be read. So what
if it takes a few milliseconds to gather it up? If for some reason the
hardware can't do asynch capture.


> A related problem:  The API document allows drivers to refuse read()
> calls with sizes smaller than a full frame ("a partial frame may be
> [ ... ] impractical or inefficient to implement").  Which doesn't
> make sense to me, assuming we require the drivers to support

Hmmm. Maybe you're right. Am I giving too much discretion to the driver
writer?

Bill.

To: video4linux-list@xxxxxxxxxx 
Subject: Re: v4l2 + select() + read() 
From: Alan Cox <alan@xxxxxxxxxx> 
Date: Tue, 29 May 2001 17:51:37 -0400 (EDT) 
Delivered-to: video4linux-list@xxxxxxxxxxxxxxxxxx 
In-reply-to: <3B14100A.29610B76@xxxxxxxxxx> 
from "Bill Dirks" at May 29, 2001 02:09:30 PM 

> select() will initiate a new frame capture as a side effect if there is
> no (good) data ready. Otherwise it will sleep forever.

So for a dumb interface select() would effectively be 'wait for a vblank'
and read non block would return one frame then -EWOULDBLOCK until the vblank ?

> > A related problem:  The API document allows drivers to refuse read()
> > calls with sizes smaller than a full frame ("a partial frame may be
> > [ ... ] impractical or inefficient to implement").  Which doesn't
> > make sense to me, assuming we require the drivers to support
> 
> Hmmm. Maybe you're right. Am I giving too much discretion to the driver
> writer?

I'd rather we allowed partial reads, but Im not sure how hard it impacts the
drivers which are DMA based - I guess this is one for folks like Gerd Knorr

To: video4linux-list@xxxxxxxxxx 
Subject: Re: v4l2 + select() + read() 
From: Gerd Knorr < kraxel@xxxxxxxxxxx> 
Date: 30 May 2001 08:20:54 GMT 
Delivered-to: video4linux-list@xxxxxxxxxxxxxxxxxx 
Newsgroups: lists.linux.video4linux 
Organization: [x] network byte order 
User-agent: slrn/0.9.7.0 (Linux) 

> > > A related problem:  The API document allows drivers to refuse read()
> > > calls with sizes smaller than a full frame ("a partial frame may be
> > > [ ... ] impractical or inefficient to implement").  Which doesn't
> > > make sense to me, assuming we require the drivers to support
> > 
> > Hmmm. Maybe you're right. Am I giving too much discretion to the driver
> > writer?
>  
>  I'd rather we allowed partial reads, but Im not sure how hard it impacts the
>  drivers which are DMA based - I guess this is one for folks like Gerd Knorr

It's a tradeoff.  I have two choices to implement that:

 (1) dma to userspace.  This is what the current devel bttv versions
     (0.8.x) do.  It's the most efficient way to do it, but the drawback
     is that neither non-blocking reads nor partial reads can be handled
     this way.
 (2) dma to a kernel bounce buffer and copy_to_user() data.  No problem
     to do non-blocking I/O and partial reads then, but its inefficient
     because I need a extra copy for the video data.

The current v4l2 specs says drivers should support non-blocking reads but
may refuse partial reads if it is "inefficient to implement".  This
combination simply doesn't make sense to me.  IMHO we should pick one
of the more useful combinations:  make partial reads mandatory or drop
non-blocking I/O support for read().

  Gerd

-- 
Gerd Knorr <kraxel@xxxxxxxxxxx>  --  SuSE Labs, Außenstelle Berlin