您的位置:网站首页 / UVC摄像头开发问答

UVC摄像头扩单元功能的开发步骤是什么?

UVC摄像头开发问答 2021-01-23

UVC扩展单元的固件支持

要进行UVC摄像头扩展单元的开发,首先第一是需要摄像头的描述符中含有UVC扩展单元描述符.
关于UVC扩展单元描述符的详情见:http://usb.bytekits.com/uvc/uvc-extension-unit-descriptor.html

一个扩展单元描述符的示例:

BYTE  Length:            0x1a
BYTE  DescriptorType:    0x24
BYTE  DescriptorSubtype: 0x06
BYTE  bUnitID:           0x05
GUID  guidExtensionCode: xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx
BYTE  bNumControls:      0x03
BYTE  bNrInPins:         0x01
BYTE  baSourceID[0]:     0x01

说明:

  • bUnitID:不能和别的ID冲突。
  • guidExtensionCode:需要通过guidgen.exe生成一个惟一的ID标识。

其它要求:https://docs.microsoft.com/zh-cn/windows-hardware/drivers/stream/device-requirements-for-usb-video-class-extension-units

扩展单元的注册

扩展单元的注册可以使用INF文件进行注册,也可以吏用注册表进行注册,也可以使用DLL注册。

使用INF文件进行扩展单元注册

INF 文件可用于提供设备特定的名称或注册扩展插件单元。
详情可叁考:
https://docs.microsoft.com/zh-cn/windows-hardware/drivers/stream/providing-a-uvc-inf-file

使用注册表进行扩展单元进行注册:

HKLM
{
    NoRemove SYSTEM
    {
        NoRemove CurrentControlSet
        {
            NoRemove Control
            {
                NoRemove NodeInterfaces
                {
                    ForceRemove {xxxxxxxx-xxxx-xxxx-xxxx-
                       xxxxxxxxxxxx} = s 'Extension Unit
                       Property Set'
                    {
                        val IID = b 'yyyyyyyyyyyyyyyyyyy
                           yyyyyyyyyyyyy'
                        val CLSID = b 'zzzzzzzzzzzzzzzzz
                           zzzzzzzzzzzzzzz'
                    }
                }
            }
        }
    }
}

https://docs.microsoft.com/zh-cn/windows-hardware/drivers/stream/sample-registry-entry-for-uvc-extension-units
https://docs.microsoft.com/zh-cn/windows-hardware/drivers/stream/sample-extension-unit-plug-in-dll

使用插件DLL注册

使用DLL注册,需要先添加注册表项:

HKCR
{
    NoRemove CLSID
    {
         ForceRemove {zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz} = s 'CompanyName Extension Unit Interface'
        {
            InprocServer32 = s '%MODULE%'
                                                {
                                val ThreadingModel = s 'Both'
                                                }
        }

    }
}

示例详见:https://docs.microsoft.com/zh-cn/windows-hardware/drivers/stream/sample-extension-unit-plug-in-dll

UVC 扩展单元的示例应用程序

应用程序通过使用 IKsTopologyInfo::CreateNodeInstance ,然后调用节点对象上的 QueryInterface 以获取所需的 COM API 来访问接口。

// pUnkOuter is the unknown associated with the base filter
  hr = pUnkOuter->QueryInterface(__uuidof(IKsTopologyInfo),
                               (void **) &pKsTopologyInfo);
  if (!SUCCEEDED(hr))
  {
        printf("Unable to obtain IKsTopologyInfo %x\n", hr);
 goto errExit;
  }

  hr = FindExtensionNode(pKsTopologyInfo,
     GUID_EXTENSION_UNIT_DESCRIPTOR,
     &dwExtensionNode);
  if (FAILED(hr))
  {
        printf("Unable to find extension node : %x\n", hr);
 goto errExit;
  }

  hr = pKsTopologyInfo->CreateNodeInstance(
        dwExtensionNode,
   __uuidof(IExtensionUnit),
 (void **) &pExtensionUnit);
 if (FAILED(hr))
  {
        printf("Unable to create extension node instance : %x\n", hr);
 goto errExit;
  }

  hr = pExtensionUnit->get_PropertySize(1, &ulSize);
  if (FAILED(hr))
  {
        printf("Unable to find property size : %x\n", hr);
 goto errExit;
  }

  pbPropertyValue = new BYTE[ulSize];
  if (!pbPropertyValue)
  {
      printf("Unable to allocate memory for property value\n");
      goto errExit;
  }

  hr = pExtensionUnit->get_Property(1,ulSize, pbPropertyValue);
  if (FAILED(hr))
  {
      printf("Unable to get property value\n");
      goto errExit;
  }

  // assume the property value is an integer
  ASSERT(ulSize == 4);
  printf("The value of property 1 = %d\n", *((int *)
     pbPropertyValue));

编写 FindExtensionNode 函数的代码以查找必需的扩展单元节点并在 dwExtensionNode 中返回其 ID。 此 ID 在此示例代码中对 IKsTopologyInfo:: CreateNodeInstance 方法的后续调用中使用。

支持扩展单元的自动更新事件

hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!hEvent)
{
    printf("CreateEvent failed\n");
    goto errExit;
}
Event.Set = KSEVENTSETID_VIDCAPNotify;
Event.Id = KSEVENT_VIDCAP_AUTO_UPDATE;
Event.Flags = KSEVENT_TYPE_ENABLE;

EventData.NotificationType = KSEVENTF_EVENT_HANDLE;
EventData.EventHandle.Event = hEvent;
EventData.EventHandle.Reserved[0] = 0;
EventData.EventHandle.Reserved[1] = 0;

// register for autoupdate events
hr = m_pKsControl->KsEvent(
    &Event, 
 sizeof(KSEVENT), 
    &EventData, 
 sizeof(KSEVENTDATA), 
    &ulBytesReturned);
if (FAILED(hr))
{
    printf("Failed to register for auto-update event : %x\n", hr);
 goto errExit;
}

// Wait for event for 5 seconds 
dwError = WaitForSingleObject(hEvent, 5000);

// cancel further notifications
hr = m_pKsControl->KsEvent(
    NULL, 
    0, 
    &EventData, 
 sizeof(KSEVENTDATA), 
    &ulBytesReturned);
if (FAILED(hr))  printf("Cancel event returns : %x\n", hr);

if ((dwError == WAIT_FAILED) || 
   (dwError == WAIT_ABANDONED) ||
   (dwError == WAIT_TIMEOUT))
{
    printf("Wait failed : %d\n", dwError);
 goto errExit;
} 
printf("Wait returned : %d\n", dwError);

// handle the autoupdate event..

很赞哦!

文章评论

标签云

用户接口

站点信息

  • 建站时间:2019-07-24
  • 联系站长tsingchen2008@163.com
  • 加QQ群 :952873936