1. 程式人生 > >UVC攝像頭(3)應用層——webcam程式

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