UVC摄像头(3)应用层——webcam程序

完成UVC完成webcam.ko模块驱动后还需要一个程序带动驱动
需要的模组:

webcam.ko
dwc_otg.ko
wdt.ko

平台:海思某芯片

int main(int argc, char* argv[])
{
    struct uvc_device dev;
    system("insmod wdt.ko default_margin=5");
    venc_init();//VENC编码设置初始化,参考海思sample_comm_venc.c
    uvc_dev_init(&dev);
    while (!gFlagExit)
    {
        if (uvc_dev_pulgged(&dev))//检测设备插入
        {
            uvc_dev_connected(&dev);//插入
            uvc_dev_disconnected(&dev);//拔出
        }

        usleep(100 * 1000);
    }
    uvc_dev_deinit(&dev);
    venc_deinit();
    return 0;
}
int uvc_dev_connected(struct uvc_device* dev)
{
    int ret;

    system("insmod dwc_otg.ko");
    system("insmod webcam.ko");

    ret = uvc_open(dev);
    if (ret)
    {
        return -1;
    }

    uvc_events_init(dev);//时间初始化
    uvc_video_init(dev);

    while (!gFlagExit)
    {
        struct timeval tv;
        fd_set efds;
        fd_set wfds;

        FD_ZERO(&efds);
        FD_SET(dev->fd, &efds);
        FD_ZERO(&wfds);
        FD_SET(dev->fd, &wfds);

        tv.tv_sec = 0;
        tv.tv_usec = 100 * 1000;
        ret = select(dev->fd + 1, NULL, &wfds, &efds, &tv);
        if (ret < 0)
        {
            printf("select error\n");
            continue;
        }
        else if (ret == 0)
        {
             if (!uvc_dev_pulgged(dev))
                return 0;
        }
        else
        {
            if (FD_ISSET(dev->fd, &efds))
            {
                uvc_events_process(dev);//时间轮训
            }
            if (FD_ISSET(dev->fd, &wfds))
            {
                uvc_video_process(dev);//流轮训,操作buf
            }
        }
    }
    return 0;
}

这里主要就是3个方法

uvc_events_init
uvc_events_process
uvc_video_process

uvc_events_init填充uvc_device的probe和comit,然后就是将UVC事件的setup、data、streamon、streamoff,通过VIDIOC_SUBSCRIBE_EVENT设置到驱动里

uvc_events_init(struct uvc_device* dev)
{
    struct v4l2_event_subscription sub;

    uvc_fill_streaming_control(dev, &dev->probe, 0, 0);
    uvc_fill_streaming_control(dev, &dev->commit, 0, 0);

if (dev->bulk)
{
    /* FIXME Crude hack, must be negotiated with the driver. */
    dev->probe.dwMaxPayloadTransferSize = 16 * 1024;
    dev->commit.dwMaxPayloadTransferSize = 16 * 1024;
}

    memset(&sub, 0, sizeof sub);
    sub.type = UVC_EVENT_SETUP;
    ioctl(dev->fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
    sub.type = UVC_EVENT_DATA;
    ioctl(dev->fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
    sub.type = UVC_EVENT_STREAMON;
    ioctl(dev->fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
    sub.type = UVC_EVENT_STREAMOFF;
    ioctl(dev->fd, VIDIOC_SUBSCRIBE_EVENT, &sub);
    sub.type = UVC_EVENT_DISCONNECT;
    ioctl(dev->fd, VIDIOC_SUBSCRIBE_EVENT, &sub);

}```
uvc_events_process可以说是最核心的部分,处理事务

uvc_events_process(struct uvc_device* dev)
{
struct v4l2_event v4l2_event;
struct uvc_event* uvc_event = (struct uvc_event*)(void*)&v4l2_event.u.data;
struct uvc_request_data resp;
int ret;

ret = ioctl(dev->fd, VIDIOC_DQEVENT, &v4l2_event);

if (ret < 0)
{
    UVC_DEBUG(1, ("VIDIOC_DQEVENT failed: %s (%d)\n", strerror(errno),
           errno));
    return;
}

memset(&resp, 0, sizeof resp);
resp.length = 32;

switch (v4l2_event.type)
{
    case UVC_EVENT_CONNECT:
        UVC_DEBUG(1, ("\nUVC_ENENT_CONNECT\n"));
        return;

    case UVC_EVENT_DISCONNECT:
        UVC_DEBUG(1, ("\nUVC_EVENT_DISCONNECT\n"));
        return;

    case UVC_EVENT_SETUP:
        UVC_DEBUG(1, ("\nUVC_EVENT_SETUP Type=%02x Request=%02x Index=%04x Value=%04x\n",uvc_event->req.bRequestType ,uvc_event->req.bRequest, uvc_event->req.wIndex,uvc_event->req.wValue));
        uvc_events_process_setup(dev, &uvc_event->req, &resp);
        break;

    case UVC_EVENT_DATA:
        UVC_DEBUG(1, ("\nUVC_EVENT_DATA  len=%d\n",uvc_event->data.length));
        uvc_events_process_data(dev, &uvc_event->data);
        return;

    case UVC_EVENT_STREAMON:
        UVC_DEBUG(1, ("\nUVC_EVENT_STREAMON\n"));
        if (dev->bulk == 0)
        {
            if (dev->streaming)
            {
                uvc_video_stream(dev, 0);
                uvc_video_reqbufs(dev, 0);
                venc_stop();
            }
            venc_set_format(dev->width,dev->height,dev->fcc,10000000/dev->dwFrameInterval,dev->wCompQuality, dev->venc_profile);
            uvc_video_set_format(dev);
            uvc_video_reqbufs(dev, USING_WEBCAM_VIDEO_BUF_NUM);
            uvc_video_stream(dev, 1);
        }
        return;

    case UVC_EVENT_STREAMOFF:
    UVC_DEBUG(1, ("\nUVC_EVENT_STREAMOFF\n"));
        if (dev->bulk == 0)
        {
            if (dev->streaming)
            {
                uvc_video_stream(dev, 0);
                uvc_video_reqbufs(dev, 0);
                venc_stop();
            }
        }
        return;
}

ret = ioctl(dev->fd, UVCIOC_SEND_RESPONSE, &resp);

if (ret < 0)
{
    UVC_DEBUG(1, ("UVCIOC_S_EVENT failed: %s (%d)\n", strerror(errno), errno));
    return;
}

}
“`
UVC_EVENT_SETUP->uvc_events_process_setup->uvc_events_process_class获取生产者信息,主要是VC和VS事务之后UVC_EVENT_DATA用来消费
具体细分不写了,自行百度,这里只讲框架。
参考资料:
http://www.ee156.com/316.html

猜你喜欢

转载自blog.csdn.net/schumi2000/article/details/82048205