Gern, Rolf:
Okay, we need to come to some to decision as to what the ioctl's do. If the
answer is that VIDIOCMCAPTURE does *NOT* capture, then we have a new problem
because the API doc specifically states to start streaming data after a call
to VIDIOCMCAPTURE.
In fact if I read usbvideo.c right, any mini driver based on it will start
streaming after a call to VIDIOCMCAPTURE.
If you start streaming after a VIDIOCMCAPTURE ioctl, and block on VIDIOCSYNC
we have a problem. That would mean either a) The API doc is 100% WRONG and
VIDIOCSYNC does NOT indicate that a frame is free - in which case several
drivers and at least one well regarded application mis-use v4l - *or*
VIDIOCSYNC does free the frame for reuse in which case there is a chance that
the driver could be writing to the buffer while the application is trying to
read from it.
Now as far bttv, this is what I'm seeing in bttv-driver.c (this is in 2.4.17
with no patches applied):
case VIDIOCMCAPTURE:
{
struct video_mmap vm;
int ret;
if(copy_from_user((void *) &vm, (void *) arg, sizeof(vm)))
return -EFAULT;
down(&btv->lock);
ret = vgrab(btv, &vm);
up(&btv->lock);
return ret;
}
If I read that correctly, it looks like its MCAPTURE ioctl locks the device,
grabs a frame, then unlocks the device. I'm not 100% sure as vgrab was a
little confusing as to what it does. For bttv's VIDIOCSYNC:
case VIDIOCSYNC:
{
DECLARE_WAITQUEUE(wait, current);
if(copy_from_user((void *)&i,arg,sizeof(int)))
return -EFAULT;
if (i < 0 || i >= gbuffers)
return -EINVAL;
switch (btv->gbuf[i].stat) {
case GBUFFER_UNUSED:
ret = -EINVAL;
break;
case GBUFFER_GRABBING:
add_wait_queue(&btv->capq, &wait);
current->state = TASK_INTERRUPTIBLE;
while(btv->gbuf[i].stat==GBUFFER_GRABBING) {
if (bttv_debug)
printk("bttv%d: cap sync: sleep on %d\n",btv->nr,i);
schedule();
if(signal_pending(current)) {
remove_wait_queue(&btv->capq, &wait);
current->state = TASK_RUNNING;
return -EINTR;
}
}
remove_wait_queue(&btv->capq, &wait);
current->state = TASK_RUNNING;
/* fall throuth */
case GBUFFER_DONE:
case GBUFFER_ERROR:
ret = (btv->gbuf[i].stat == GBUFFER_ERROR) ? -EIO : 0;
if (bttv_debug)
printk("bttv%d: cap sync: buffer %d, retval
%d\n",btv->nr,i,ret);
btv->gbuf[i].stat = GBUFFER_UNUSED;
}
if (btv->needs_restart) {
down(&btv->lock);
bt848_restart(btv);
up(&btv->lock);
}
return ret;
}
Looks to me like the only time the VIDIOCSYNC ioctl will wait is if you are
trying to free the frame that is currently grabbing. If the frame has
already been grabbed (GBUFFER_DONE), the buffer is immediately marked as
unused and the function promptly returns. If the frame *was* grabbing, it
waits for the frame to be *done* grabbing then falls through at marks the
buffer unused.
So, if the answer is you call VIDIOCMCAPTURE to queue a frame to be read, and
you call VIDIOCSYNC to wait for the frame to come in... Then the API doc is
not just unclear but arguably completely incorrect, the bttv driver looks
like it is broken, and the zapping application looks like it is broken too.
_______________________________________________
Video4linux-list mailing list
[EMAIL PROTECTED]
https://listman.redhat.com/mailman/listinfo/video4linux-list