3

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).

Roman R.
  • 68,205
  • 6
  • 94
  • 158
Mark
  • 4,338
  • 7
  • 58
  • 120

1 Answers1

5

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:

Roman R.
  • 68,205
  • 6
  • 94
  • 158
  • Thanks. You answered to my similar question about one year ago but today I didn't realized the source of my issue was the same. I apologize for that. – Mark Mar 11 '18 at 17:19
  • What is the recommended technology nowadays to write a software cam device? I mean that shows something created from a piece of code rather than a physical sensor like a real webcam. – Mark Mar 11 '18 at 17:21
  • Yes, I just found that old answer and linked it. – Roman R. Mar 11 '18 at 17:21
  • Last question: does this apply also for audio capture devices? Like "fake" microphone, where the audio is generated by a software function? – Mark Mar 11 '18 at 17:23
  • Sadly, Microsoft did not offer any new API to supply a virtual video source. There is no solution even reduced to newer applications with Media Foundation API. So it's where it was: either you create a driver (red box) which APIs pull and create a normal video source around, or you apply app specific hooking and inject a video source that way. Both ways are not quite easy, to say the least. – Roman R. Mar 11 '18 at 17:26
  • Situation with audio sources is not any simpler. It is similar in terms that there are several APIs and no good entry point to supply your implementation and make it visible to existing application. The difference from video is that much much less applications use DirectShow for audio capture (and for good reason) so chances to find an app which can use a virtual audio source developed using the method in your question are even lower. – Roman R. Mar 11 '18 at 17:30