Starting from the great example of Capture Source Filter here I wrote my own input capture device that works fine in Graph Studio Next, but it's not shown as a capture device (i.e. webcam) in application like Skype or similar.
Because I want to understand what's happening I ask you to help me to find out what those application need to show such a device.
Some relevant code:
dll.cpp
DEFINE_GUID(CLSID_VirtualCam, 0x8e14549a, 0xdb61, 0x4309, 0xaf, 0xa1, 0x35, 0x78, 0xe9, 0x27, 0xe9, 0x33);
const AMOVIESETUP_MEDIATYPE AMSMediaTypesVideo =
{
&MEDIATYPE_Video,
&MEDIASUBTYPE_NULL
};
const AMOVIESETUP_PIN AMSPinVCam[] =
{
{
L"Output", // Pin string name
FALSE, // Is it rendered
TRUE, // Is it an output
FALSE, // Can we have none
FALSE, // Can we have many
&CLSID_NULL, // Connects to filter
NULL, // Connects to pin
1, // Number of types
&AMSMediaTypesVideo // Pin Media types
}
};
const AMOVIESETUP_FILTER AMSFilterVCam =
{
&CLSID_VirtualCam, // Filter CLSID
FILTER_NAME, // String name
MERIT_PREFERRED, // Filter merit
1, // Number pins
AMSPinVCam // Pin details
};
CFactoryTemplate g_Templates[] =
{
{
FILTER_NAME,
&CLSID_VirtualCam,
CVCam::CreateInstance,
NULL,
&AMSFilterVCam
},
};
Filter.cpp
CVCam::CVCam(LPUNKNOWN lpunk, HRESULT *phr) : CSource(LPCSTR(FILTER_NAME), lpunk, CLSID_VirtualCam)
{
ASSERT(phr);
CAutoLock cAutoLock(&m_cStateLock);
m_paStreams = (CSourceStream **) new CVCamStream*[1];
m_paStreams[0] = new CVCamStream(phr, this, FILTER_NAME);
}
HRESULT CVCam::QueryInterface(REFIID riid, void **ppv)
{
if (riid == _uuidof(IAMStreamConfig) || riid == _uuidof(IKsPropertySet))
{
HRESULT hr;
hr = m_paStreams[0]->QueryInterface(riid, ppv);
if (hr != S_OK) return hr;
}
else return CSource::QueryInterface(riid, ppv);
return S_OK;
}
CVCamStream::CVCamStream(HRESULT *phr, CVCam *pParent, LPCWSTR pPinName) : CSourceStream(LPCSTR(FILTER_NAME),phr, pParent, pPinName), m_pParent(pParent)
{
hdc = GetDC(NULL);
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
screen_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
screen_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
GetMediaType(8, &m_mt);
}
CVCamStream::~CVCamStream()
{
Gdiplus::GdiplusShutdown(gdiplusToken);
DeleteDC(hdc);
}
HRESULT CVCamStream::QueryInterface(REFIID riid, void **ppv)
{
if(riid == _uuidof(IAMStreamConfig)) *ppv = (IAMStreamConfig*)this;
else if(riid == _uuidof(IKsPropertySet)) *ppv = (IKsPropertySet*)this;
else return CSourceStream::QueryInterface(riid, ppv);
AddRef();
return S_OK;
}
I omitted the other functions that are pretty the same of the example linked and I guess the configuration is made in these ones.
Do you see any evidence of my lack that leads the filter to be not recognized as a video capture device?
Of course the filter is registered (I see it in the DirectShow Filter Manager).
The DirectShow input device project you are refering to is not an API which is designed to take your camera-like implementation into any video capture enabled application, unfortunately.
The video source you developed will only be visible to application consuming video capture using DirectShow API and having a matching bitness with your filter. Even though quite so many applications out there are still using DirectShow, their rate tends to slowly go down with the time. For example, new Skype is not using DirectShow and Skype for Business is just a new name for former Lync meaning that there is little if any shared source code with Skype in terms of video capture.
I have more of technical details in this post: Applicability of Virtual DirectShow Sources and the picture from the post should give the idea for which applications your video source is "viisble" (green boxes):
See also: