Re: Re: ioctl parameters

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



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.





[Index of Archives]     [Linux DVB]     [Video Disk Recorder]     [Asterisk]     [Photo]     [DCCP]     [Netdev]     [Xorg]     [Util Linux NG]     [Xfree86]     [Free Photo Albums]     [Fedora Users]     [Fedora Women]     [ALSA Users]     [ALSA Devel]     [Linux USB]

Powered by Linux