使用COM和Python通过DirectShow访问网络摄像头

时间:2018-08-14 14:11:42

标签: python pywin32 win32com python.net comtypes

我想使用DirectShow的webcam properties低级别访问IAMVideoProcAmp

在此上下文中使用了多个Python模块)pywin32pywintypescomtypeswin32compythoncom),它们似乎是相关的。但是我不知道从哪里开始。

我找到了一些示例(hereherehere),但我不知道如何获得IID / CLSID来使用

import win32com.client
clsid='{9BA05972-F6A8-11CF-A442-00A0C90A8F39}'
ShellWindows=win32com.client.Dispatch(clsid)

或具有清晰的名称,例如

import win32com.client
xl = win32com.client.Dispatch("Excel.Application")

from comtypes import client, GUID
graph = client.CreateObject(some_CLSID)
graph.QueryInterface(...)

有人可以帮我吗?

我找到了另一个示例(dshow.py),但是它具有一些我找不到的依赖项(interfacesuuids)。

Microsoft的

This页将过程列出为

  

在捕获过滤器上为IAMVideoProcAmp接口调用QueryInterface。

  

查询IAMCameraControl的捕获过滤器。

并为此声明一些C ++代码:

// Query the capture filter for the IAMVideoProcAmp interface.
IAMVideoProcAmp *pProcAmp = 0;
hr = pCap->QueryInterface(IID_IAMVideoProcAmp, (void**)&pProcAmp);
hr = m_pProcAmp->GetRange(VideoProcAmp_Brightness, &Min, &Max, &Step,
    &Default, &Flags);

编辑: 我终于找到了到目前为止看起来不错的一些代码:

jaraco

它似乎完全符合我的意图,并且使用了一些元素 DirectShow(see here):

from comtypes.gen.DirectShowLib import (FilterGraph, CaptureGraphBuilder2, ...)

jaraco.video声称是“使用ctypes和comtypes的纯Python中VideoCapture模块的端口。”

它正在使用DirectShow.tlb文件(无论是什么文件)来获取定义 进入comtypes

  

类型库(.tlb)是一个二进制文件,用于存储有关以下内容的信息:   COM或DCOM对象的属性和方法的形式为   在运行时可供其他应用程序访问。

2 个答案:

答案 0 :(得分:1)

确定复制代码所需的值

乍看一下文章结尾处的代码摘录,我意识到您仅需要IAMVideoProcAmp的IID而不是CLSID即可获取它的实例。

查看this source of strmif.h的第8733行,该行被记为该接口的必需标头,我发现IID_IAMVideoProcAmpC6E13360-30AC-11d0-A18C-00A0C9118956

在strmif.h的这一部分中,您可以标识哪些整数与tagVideoProcAmpProperty枚举中的哪些属性相对应,例如0代表VideoProcAmp_Brightness。在strmif.h的此部分下面,您可以确定IAMVideoProcAmpVtbl VTable中哪些整数对应于哪些函数,例如3的{​​{1}}。我不熟悉如何在Python中与COM对象进行交互,但是在Java中,您需要确定这些属性和函数索引,以便复制演示如何获取GetRange实例的C ++代码摘录。

获取IAmVideoProcAmp的实例

您可能已经注意到,C ++代码摘录在IAMVideoProcAmp上调用QueryInterface,并指出您需要“查询IAMVideoProcAmp接口的捕获过滤器”。 This sibling of the article you linked解释了如何做到这一点:

  

要为设备创建DirectShow捕获过滤器,请调用IMoniker :: BindToObject方法以获取IBaseFilter指针。然后调用IFilterGraph :: AddFilter将过滤器添加到过滤器图形中:

pCap

现在,您知道如何获取IBaseFilter *pCap = NULL; hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap); if (SUCCEEDED(hr)) { hr = m_pGraph->AddFilter(pCap, L"Capture Filter"); } ,您会发现需要一个名为pCap的东西,该东西在同一篇文章的前面已定义。代码相当长,因此我在这里省略了。

在Python中完成所有操作

正如我之前提到的,我从未使用过任何Python COM库,因此我不能轻易编写示例,但是您的目标应该是在Python中复制C ++示例中进行的函数调用以获取{{ 1}}并对其进行修改以适合您的需求。

答案 1 :(得分:0)

我终于找到了可以运行的示例库:

jaraco

它正是我要达到的目标,并使用了一些 DirectShow(see here):

from comtypes.gen.DirectShowLib import (FilterGraph, CaptureGraphBuilder2, ...)

jaraco.video声称是“使用ctypes和comtypes的纯Python中VideoCapture模块的端口。”

它正在使用DirectShow.tlb文件(无论是什么文件)来获取定义 进入comtypes

  

类型库(.tlb)是一个二进制文件,用于存储有关以下内容的信息:   COM或DCOM对象的属性和方法的形式为   在运行时可供其他应用程序访问。

导入是在__init__.py中自动生成的,并且可以轻松使用:

from api.objects import ..., IMediaControl, IAMVideoProcAmp, IAMCameraControl, ...

并且可以使用

def _get_camera_control(self):
    return self._get_graph_builder_interface(IAMCameraControl)

def get_camera_control_property(self, i):

    video_properties = self._get_camera_control()
    return video_properties.Get(i)

然后,您可以将这些功能与文档中所述的enum结合使用,例如

# CameraControl_Exposure = 4
print(d.get_camera_control_property(4))