I want to get low level access to webcam properties using DirectShow's IAMVideoProcAmp.
There are several Python modules )pywin32
, pywintypes
, comtypes
, win32com
, pythoncom
) that are used in this context and they seem to be related somehow. But I have no clue where to start.
I found some examples (here, here, here) but I could not figure out how to get a IID / CLSID to use like
import win32com.client
clsid='{9BA05972-F6A8-11CF-A442-00A0C90A8F39}'
ShellWindows=win32com.client.Dispatch(clsid)
or with a clear name like
import win32com.client
xl = win32com.client.Dispatch("Excel.Application")
or
from comtypes import client, GUID
graph = client.CreateObject(some_CLSID)
graph.QueryInterface(...)
Can someone help me with this?
I found another example (dshow.py), but it has some dependencies that I could not find (interfaces
, uuids
).
This page from Microsoft lists the procedures as
Call QueryInterface on the capture filter for the IAMVideoProcAmp interface.
or
Query the capture filter for the IAMCameraControl.
and states some C++ code for this:
// 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);
Edit: I finally found some code that looks good so far:
jaraco
It seem to do exactly what I am trying to write and uses some elements from DirectShow (see here):
from comtypes.gen.DirectShowLib import (FilterGraph, CaptureGraphBuilder2, ...)
jaraco.video claims to be "a port of the VideoCapture module in pure Python using ctypes and comtypes."
It is using a DirectShow.tlb
file (whatever that is) to get the definitions
into comtypes
A type library (.tlb) is a binary file that stores information about a COM or DCOM object's properties and methods in a form that is accessible to other applications at runtime.
At a second glance at the code excerpt at the end of your post, I realize that you only need the IID and not the CLSID for IAMVideoProcAmp
in order to acquire an instance of it.
Looking at line 8733 of this source of strmif.h, noted as the required header for the interface, I found that IID_IAMVideoProcAmp
is C6E13360-30AC-11d0-A18C-00A0C9118956
.
Above this section of strmif.h, you can identify what integers correspond to which properties in the tagVideoProcAmpProperty
enum, such as 0
for VideoProcAmp_Brightness
. Below this section of strmif.h, you can identify what integers correspond to which functions in the IAMVideoProcAmpVtbl
VTable, such as 3
for GetRange
. I am unfamiliar with how to interact with COM objects in Python, but in Java you would need to determine these property and function indices in order to replicate the C++ code excerpts that demonstrate how to acquire an instance of IAmVideoProcAmp
.
IAMVideoProcAmp
As you may have noticed, the C++ code excerpt invokes QueryInterface
on something called pCap
and notes that you need to "Query the capture filter for the IAMVideoProcAmp interface." This sibling of the article you linked explains how to do this:
To create a DirectShow capture filter for the device, call the IMoniker::BindToObject method to get an IBaseFilter pointer. Then call IFilterGraph::AddFilter to add the filter to the filter graph:
IBaseFilter *pCap = NULL; hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap); if (SUCCEEDED(hr)) { hr = m_pGraph->AddFilter(pCap, L"Capture Filter"); }
Now that you know how to acquire pCap
, you notice you need something called pMoniker
, which is defined earlier in the same article. The code is fairly long so I omit it here.
As I noted earlier, I have never used any Python COM library, so I cannot easily whip up an example, but your goal should be to replicate in Python the function invocations made in the C++ examples to acquire an instance of IAMVideoProcAmp
and modifying them to suit your needs.
I finally found some example library that is working:
jaraco
It does exactly what I am trying to achive and uses some elements from DirectShow (see here):
from comtypes.gen.DirectShowLib import (FilterGraph, CaptureGraphBuilder2, ...)
jaraco.video claims to be "a port of the VideoCapture module in pure Python using ctypes and comtypes."
It is using a DirectShow.tlb
file (whatever that is) to get the definitions
into comtypes
A type library (.tlb) is a binary file that stores information about a COM or DCOM object's properties and methods in a form that is accessible to other applications at runtime.
The imports are auto-generated in __init__.py
and can be used easily:
from api.objects import ..., IMediaControl, IAMVideoProcAmp, IAMCameraControl, ...
and can be used
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)
Then you can use the functions in combination with the enum
stated in the docs, e.g.
# CameraControl_Exposure = 4
print(d.get_camera_control_property(4))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With