How to use DirectShow and webcam to preview an image - c++

I'm trying to use C++ and DirectShow to display my webcam... but I'm having some troubles.
The following code gives me a segmentation fault on:
m_pDF->EnumPins(&pinEnum);
my cpp code:
#include <tchar.h>
#include <strsafe.h>
#include <dshow.h>
#include <atlbase.h>
#include <d3d9.h>
#include <vmr9.h>
#pragma comment(lib,"Strmiids.lib")
#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum)
{
// Create the System Device Enumerator.
ICreateDevEnum *pDevEnum; // Video and Audio interface object
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum)); // Creates the system device enumerator
if (SUCCEEDED(hr))
{
// Create an enumerator for the category.
hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0); // Enumeration of 'category' objects
if (hr == S_FALSE)
{
hr = VFW_E_NOT_FOUND; // The category is empty. Treat as an error.
}
pDevEnum->Release(); // Deletes Enumeration object
}
return hr;
}
void main(void)
{
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL; // contains methods for stopping and starting the graph
IMediaEvent *pEvent = NULL; // methods for getting events from the Filter Graph Manager
IPin *m_pCamOutPin;
IBaseFilter *m_pDF=NULL;
IMoniker *pM;
IEnumMoniker *pEnum; // Enumerator object
// Initialize the COM library.
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
printf("ERROR - Could not initialize COM library");
return;
}
// Create the filter graph manager and query for interfaces.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr))
{
printf("ERROR - Could not create the Filter Graph Manager.");
return;
}
// Bind
hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
pEnum->Next(1, &pM, NULL);
pM->BindToObject(0, 0, IID_IBaseFilter, (void**)m_pDF);
pM->Release();
hr=pGraph->AddFilter(m_pDF, L"Video Capture");
CComPtr<IEnumPins> pinEnum;
m_pDF->EnumPins(&pinEnum);
hr = pinEnum->Reset();
hr = pinEnum->Next(1, &m_pCamOutPin, NULL);
if (FAILED(hr))
return;
// control
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Build the graph. IMPORTANT: Change this string to a file on your system.
hr = pGraph->Render(m_pCamOutPin);
if (SUCCEEDED(hr))
{
// Run the graph.
hr = pControl->Run();
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely.
}
}
SAFE_RELEASE(pControl);
SAFE_RELEASE(pEvent);
SAFE_RELEASE(pGraph);
CoUninitialize();
}
Any ideas on what am I doing wrong and what do I have to do to get this to work?

m_pDF is a pointer to IBaseFilter:
IBaseFilter *m_pDF=NULL;
BindToObject last parameter is a pointer to a pointer. Which means this functioncall is wrong:
pM->BindToObject(0, 0, IID_IBaseFilter, (void**)m_pDF);
Instead you need to pass the address of m_pDF to get a pointer to a pointer:
pM->BindToObject(0, 0, IID_IBaseFilter, (void**)&m_pDF);
It is not a problem to cast IBaseFilter** to void**, but you can't cast IBaseFilter* to void**.

The crash should be related m_pDF, it not be a valid pointer.
you should add check for pM->BindToObject(0, 0, IID_IBaseFilter, (void**)m_pDF); to know that m_pDF is initialize sucess or not.
and you should also check hr=pGraph->AddFilter(m_pDF, L"Video Capture"); hr is ok or not.
if fail, you can get the error code know the reason.

Related

Directshow cant start capture twice

I am trying to follow through the DirectShow examples on the windows dev center to make my own application that can capture screen and audio to video: Capturing Video to an AVI File
The first time capture starts all is ok, but at the second nothing happens, the file with video not appearing. Is it possible that I forgot to uninitialize sometfing?
UPDATE
The problem seems not to be in missing releasing. The second time stream writes the file 1.avi is creating but it empty and when the pMediaControl->Stop(); is done it automatically deletes
UPDATE2
At the second time I found that:
hr = pBuild->RenderStream(
&PIN_CATEGORY_CAPTURE, // Pin category.
&MEDIATYPE_Video, // Media type.
pCap, // Capture filter.
NULL, // Intermediate filter (optional).
pMux); // Mux or file sink filter.
returns E_INVALIDARG. So I added (using this):
if (a == 1) {
CComPtr<IPin> sourcePin;
CComPtr<IPin> dumpPin;
sourcePin = GetPin(pMux, PINDIR_OUTPUT);
dumpPin = GetPin(pCap, PINDIR_INPUT);
hr = ppGraph->Connect(sourcePin, dumpPin);
}
And I found thaht on the second time the dumpPin value is NULL .The hr = ppGraph->AddFilter(pCap, L"Capture Filter"); runs ok. Where can I dig next to find error?
(code is updated)
My code:
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <dshow.h>
#include <atlbase.h>
#include <dshow.h>
#include <vector>
#include <string>
#pragma comment(lib, "strmiids")
IPin *GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir)
{
BOOL bFound = FALSE;
IEnumPins *pEnum;
IPin *pPin;
pFilter->EnumPins(&pEnum);
while (pEnum->Next(1, &pPin, 0) == S_OK)
{
PIN_DIRECTION PinDirThis;
pPin->QueryDirection(&PinDirThis);
if (bFound = (PinDir == PinDirThis))
break;
pPin->Release();
}
pEnum->Release();
return (bFound ? pPin : 0);
}
HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum)
{
// Create the System Device Enumerator.
ICreateDevEnum *pDevEnum;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
if (SUCCEEDED(hr))
{
// Create an enumerator for the category.
hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0);
if (hr == S_FALSE)
{
hr = VFW_E_NOT_FOUND; // The category is empty. Treat as an error.
}
pDevEnum->Release();
}
return hr;
}
HRESULT InitCaptureGraphBuilder(
IGraphBuilder **ppGraph, // Receives the pointer.
ICaptureGraphBuilder2 **ppBuild // Receives the pointer.
)
{
if (!ppGraph || !ppBuild)
{
return E_POINTER;
}
IGraphBuilder *pGraph = NULL;
ICaptureGraphBuilder2 *pBuild = NULL;
// Create the Capture Graph Builder.
HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild);
if (SUCCEEDED(hr))
{
// Create the Filter Graph Manager.
hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void**)&pGraph);
if (SUCCEEDED(hr))
{
// Initialize the Capture Graph Builder.
pBuild->SetFiltergraph(pGraph);
// Return both interface pointers to the caller.
*ppBuild = pBuild;
*ppGraph = pGraph; // The caller must release both interfaces.
return S_OK;
}
else
{
pBuild->Release();
}
}
return hr; // Failed
}
struct Capture {
IPropertyBag *pPropBag;
IGraphBuilder *ppGraph;
IBaseFilter *pCap;
ICaptureGraphBuilder2 *pBuild;
};
void DisplayDeviceInformation(IEnumMoniker *pEnum,int a)
{
IMoniker *pMoniker = NULL;
std::vector<Capture> captures;
while (pEnum->Next(1, &pMoniker, NULL) == S_OK)
{
IPropertyBag *pPropBag;
HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
if (FAILED(hr))
{
pMoniker->Release();
continue;
}
VARIANT var;
VariantInit(&var);
hr = pPropBag->Read(L"DevicePath", &var, 0);
if (SUCCEEDED(hr))
{
// The device path is not intended for display.
printf("Device path: %S\n", var.bstrVal);
VariantClear(&var);
}
IGraphBuilder *ppGraph;
ICaptureGraphBuilder2 *pBuild; // Capture Graph Builder
hr = InitCaptureGraphBuilder(&ppGraph, &pBuild);
IBaseFilter *pCap; // Video capture filter.
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
if (SUCCEEDED(hr))
{
std::wstring name = std::wstring(L"C:\\a\\") + std::to_wstring(a) + std::wstring(L".avi");
const wchar_t *cname = name.c_str();
hr = ppGraph->AddFilter(pCap, L"Capture Filter");
if (SUCCEEDED(hr)) {
IBaseFilter *pMux;
hr = pBuild->SetOutputFileName(
&MEDIASUBTYPE_Avi, // Specifies AVI for the target file.
cname, // File name.
&pMux, // Receives a pointer to the mux.
NULL); // (Optional) Receives a pointer to the file sink.
if (a == 1) {
CComPtr<IPin> sourcePin;
CComPtr<IPin> dumpPin;
sourcePin = GetPin(pMux, PINDIR_OUTPUT);
dumpPin = GetPin(pCap, PINDIR_INPUT);
hr = ppGraph->Connect(sourcePin, dumpPin);
}
hr = pBuild->RenderStream(
&PIN_CATEGORY_CAPTURE, // Pin category.
&MEDIATYPE_Video, // Media type.
pCap, // Capture filter.
NULL, // Intermediate filter (optional).
pMux); // Mux or file sink filter.
// Release the mux filter.
pMux->Release();
IConfigAviMux *pConfigMux = NULL;
hr = pMux->QueryInterface(IID_IConfigAviMux, (void**)&pConfigMux);
if (SUCCEEDED(hr))
{
pConfigMux->SetMasterStream(0);
pConfigMux->Release();
}
IConfigInterleaving *pInterleave = NULL;
hr = pMux->QueryInterface(IID_IConfigInterleaving, (void**)&pInterleave);
if (SUCCEEDED(hr))
{
pInterleave->put_Mode(INTERLEAVE_CAPTURE);
pInterleave->Release();
}
pMux->Release();
}
}
Capture capt;
capt.ppGraph = ppGraph;
capt.pPropBag = pPropBag;
capt.pCap = pCap;
capt.pBuild = pBuild;
captures.push_back(capt);
}
for (auto cap : captures)
{
IMediaControl* pMediaControl;
cap.ppGraph->QueryInterface(&pMediaControl);
pMediaControl->Run();
}
Sleep(5000);
for (auto cap : captures)
{
IMediaControl* pMediaControl;
cap.ppGraph->QueryInterface(&pMediaControl);
pMediaControl->Stop();
pMediaControl->Release();
cap.pCap->Release();
cap.ppGraph->Release();
cap.pBuild->Release();
cap.pPropBag->Release();
}
pMoniker->Release();
}
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
for (int a = 0; a <= 1; a++) {
if (SUCCEEDED(hr))
{
IEnumMoniker *pEnum;
hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
if (SUCCEEDED(hr))
{
DisplayDeviceInformation(pEnum,a);
pEnum->Release();
}
}
}
if (SUCCEEDED(hr))
{
CoUninitialize();
}
int i;
std::cin >> i;
return 0;
}
You might need to Release ppGraph, pBuild, pMediaControl and pCap at the end of DisplayDeviceInformation function and pMux at the end of the cycle. It will be better to use some sort of smart pointers instead.
I didn't figure out how too resolve this, so I just used spawn of external process.

Create borderless DirectShow Window

I am referring to this simple video player using DirectShow example provided here.
The code runs and builds however I need to make the video player window borderless.
I could not find a parameter to set in the CoCreateInstance function or the CoInitialize function which I can set to make the window borderless.
Here is my complete code for reference:
#include <dshow.h>
#pragma comment (lib, "strmiids.lib")
void main(void)
{
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
// Initialize the COM library.
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
printf("ERROR - Could not initialize COM library");
return;
}
// Create the filter graph manager and query for interfaces.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr))
{
printf("ERROR - Could not create the Filter Graph Manager.");
return;
}
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Build the graph. IMPORTANT: Change this string to a file on your system.
hr = pGraph->RenderFile(L"D:\\dfs.avi", NULL);
if (SUCCEEDED(hr))
{
// Run the graph.
hr = pControl->Run();
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely.
}
}
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
}
What additional piece of code do I need to add in order to achieve this?
I found this code here which does the job!
#pragma comment(lib, "strmiids.lib")
#pragma comment(lib, "quartz.lib")
#include <string>
#include <dshow.h>
int PlayVideo(const std::string& pFile)
{
IGraphBuilder* pGraph = NULL;
IVideoWindow* pWin = NULL;
IMediaControl* pControl = NULL;
IMediaEvent* pEvent = NULL;
// Initialize the COM library.
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr)) return 1;
// Create the filter graph manager and query for interfaces.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr)) return 1;
// Get interfaces
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
hr = pGraph->QueryInterface(IID_IVideoWindow, (void **)&pWin);
// Build the graph (convert unicode filename)
size_t _size = mbstowcs(NULL,pFile.c_str(),2); // Add 2 for ZT
wchar_t* _wfile = new wchar_t[_size + 2];
_size = mbstowcs(_wfile, pFile.c_str(), pFile.length() + 1); // Add 1 for ZT
hr = pGraph->RenderFile(_wfile, NULL);
delete[] _wfile;
// Uncomment next line for borderless window display
pWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
// For fullscreen play, get Windows screen parameters and replace
pWin->SetWindowPosition(0, 0, 800, 600);
if (SUCCEEDED(hr))
{
hr = pControl->Run();
if (SUCCEEDED(hr))
{
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
}
}
pControl->Release();
pEvent->Release();
pWin->Release();
pGraph->Release();
CoUninitialize();
return 0;
}
int main()
{
PlayVideo("D:\\dfs.avi"); // play any format Windows can handle, avi/mpg etc.
return 0;
}

Play Audio Stream Using Windows APIs in C++

To play an .mp3 file in Windows using (in this case) DirectShow you only need:
#include <dshow.h>
#include <cstdio>
// For IID_IGraphBuilder, IID_IMediaControl, IID_IMediaEvent
#pragma comment(lib, "strmiids.lib")
const wchar_t* filePath = L"C:/Users/Public/Music/Sample Music/Sleep Away.mp3";
int main()
{
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
// Initialize the COM library.
HRESULT hr = ::CoInitialize(NULL);
if (FAILED(hr))
{
::printf("ERROR - Could not initialize COM library");
return 0;
}
// Create the filter graph manager and query for interfaces.
hr = ::CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr))
{
::printf("ERROR - Could not create the Filter Graph Manager.");
return 0;
}
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Build the graph.
hr = pGraph->RenderFile(filePath, NULL);
if (SUCCEEDED(hr))
{
// Run the graph.
hr = pControl->Run();
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely.
}
}
// Clean up in reverse order.
pEvent->Release();
pControl->Release();
pGraph->Release();
::CoUninitialize();
}
I can't find a way to have something like this, but to be able to play an .asx instead, like for example: http://listen.radiotunes.com/public5/solopiano.asx
In MSDN I can only find ways to do this in C# making a Forms application and inserting a WindowsMediaPlayer control in a form.
Any ideas?
An .asx file is actually a playlist. See here some information about the format.
.asx is not supported by DirectShow. See here for the supported formats.
You might parse the file, as it is XML, and find the actual URL of the stream, and then play it, or you could use the Windows Media Player SDK. You can see some sample code for WM SDK here.
OK, got it to work with this example taken from here and adding this extra line: hr = spPlayer->put_URL(L"http://listen.radiotunes.com/public5/solopiano.asx");:
#include "atlbase.h"
#include "atlwin.h"
#include "wmp.h"
#include <cstdio>
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
HRESULT hr = S_OK;
CComBSTR bstrVersionInfo; // Contains the version string.
CComPtr<IWMPPlayer> spPlayer; // Smart pointer to IWMPPlayer interface.
hr = spPlayer.CoCreateInstance(__uuidof(WindowsMediaPlayer), 0, CLSCTX_INPROC_SERVER);
if (SUCCEEDED(hr))
{
hr = spPlayer->get_versionInfo(&bstrVersionInfo);
hr = spPlayer->put_URL(L"http://listen.radiotunes.com/public5/solopiano.asx");
}
if (SUCCEEDED(hr))
{
// Show the version in a message box.
COLE2T pStr(bstrVersionInfo);
MessageBox(NULL, (LPCSTR)pStr, _T("Windows Media Player Version"), MB_OK);
}
// Clean up.
spPlayer.Release();
CoUninitialize();
return 0;
}

How to write an avi file with DirectShow

I'm trying to write an avi video file based on the streaming of my Decklink SDI card, after looking in the internet and here I wrote this code by my problem is that the program doesn't write the file here 's the code:
#include <Windows.h>
#include <DShow.h>
#include <iostream>
int main(void)
{
IGraphBuilder* pGraph = NULL;
ICaptureGraphBuilder2* pBuild = NULL;
IMediaControl* pControl = NULL;
ICreateDevEnum* pDevEnum = NULL;
IEnumMoniker* pEnum = NULL;
IMoniker *pMoniker = NULL;
IMoniker* goodMoniker = NULL;
IBaseFilter* pCap;
HRESULT hr;
//Initialize pGraph
hr = CoInitialize(NULL);
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **) &pGraph);
if(FAILED(hr))
{
printf("ERROR - Could not initialize COM library");
return 1;
}
//Initialize pBuild
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**) &pBuild);
if(FAILED(hr))
{
printf("ERROR - Could not create the Filter Graph Manager.");
return 2;
}
pBuild->SetFiltergraph(pGraph);
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast<void**>(&pDevEnum));
if(SUCCEEDED(hr))
{
hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
}
HWND hList;
while(pEnum->Next(1, &pMoniker, NULL) == S_OK)
{
IPropertyBag* pPropBag;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag));
if(FAILED(hr))
{
pMoniker->Release();
continue;
}
VARIANT varName;
VariantInit(&varName);
hr = pPropBag->Read(L"Description", &varName, 0);
if(FAILED(hr))
{
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
}
if(SUCCEEDED(hr))
{
for(int i=0;i<20;i++)
{
std::cout<<(char)*(varName.bstrVal + i);
}
char yn;
std::cin>>yn;
if(yn=='Y')
{
std::cout<<"SUCCESSFUL"<<std::endl;
goodMoniker = pMoniker;
VariantClear(&varName);
}
}
pPropBag->Release();
if(pMoniker != goodMoniker)
{
pMoniker->Release();
}
}
hr = goodMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)(&pCap));
if(SUCCEEDED(hr))
{
hr = pGraph->AddFilter(pCap, L"Capture Filter");
}
IBaseFilter *pMux = NULL;
// hr = pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap, NULL, NULL);
hr = pBuild->SetOutputFileName(
&MEDIASUBTYPE_Avi, // Specifies AVI for the target file.
L"C:\\stuff.avi", // File name.
&pCap, // Receives a pointer to the mux.
NULL); // (Optional) Receives a pointer to the file sink.
hr =pBuild->RenderStream(
&PIN_CATEGORY_CAPTURE, // Pin category.
&MEDIATYPE_Video, // Media type.
pCap, // Capture filter.
NULL, // Intermediate filter (optional).
pMux); // Mux or file sink filter.
hr = pCap->QueryInterface(IID_IMediaControl,(void**) pControl);
printf("START ");
hr = pControl->Run();
Sleep(100000);
hr = pControl->Stop();
CoUninitialize();
pGraph->Release();
pBuild->Release();
pCap->Release();
}
here is the error message that I get when I try to debbug it :
Unhandled exception at 0x776015de in STREAMMMMM.exe: 0xC0000005: Access violation reading location 0x00000000.
the program crashes in this line :
r = pCap->QueryInterface(IID_IMediaControl,(void**) pControl);
There are tens, if not hundreds, of examples on how to write into AVI with DirectShow on Internet.
This particular code snippet does not even start writing. It only prepares the pipeline and you are not even doing IMediaControl::Run, what you are supposed to do. Further on, you should wait until you wrote enough, and then stop recording and only then release the interface pointers.
Have a look at this Q: Using a DirectShow filter without registering it, via a private CoCreateInstance on what you are missing to start actual capture and writing (IMediaControl::Run and Sleep in particular).

Using a DirectShow filter without registering it, via a private CoCreateInstance

So basiclly I read this, http://www.gdcl.co.uk/2011/June/UnregisteredFilters.htm.
Which tells you how to use filters without registering them. There are two methods, new and using a private CoCreateInstance. Im trying to use the CoCreateInstance method.
In the sample from the site the code is listed as,
IUnknownPtr pUnk;
HRESULT hr = CreateObjectFromPath(TEXT("c:\\path\\to\\myfilter.dll"), IID_MyFilter, &pUnk);
if (SUCCEEDED(hr))
{
IBaseFilterPtr pFilter = pUnk;
pGraph->AddFilter(pFilter, L"Private Filter");
pGraph->RenderFile(pMediaClip, NULL);
}
My code as follows,
IUnknownPtr pUnk;
HRESULT hr = CreateObjectFromPath(TEXT("c:\\filters\\mp4demux.dll"), IID_BaseFilter, &pUnk);
if (SUCCEEDED(hr))
{
//add functionality
}
I'm guessing IID_BaseFilter is what Im supposed to use, its what I use for other filters. But I'm given the error 'ClassFactory cannot supply requested class'.
Am I missing something here? Any help would be greatly appreciated. Thanks in advance!
EDIT: code
IBaseFilter *pSrc = NULL, *pSrc2 = NULL, *pWaveDest = NULL, *pWriter = NULL;
IFileSinkFilter *pSink= NULL;
IGraphBuilder *pGraph;
ICaptureGraphBuilder2 *pBuild;
IMediaControl *pControl = NULL;
// This example omits error handling.
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER,
IID_ICaptureGraphBuilder2, (void**)&pBuild);
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph);
//Initialize the Capture Graph Builder
hr = pBuild->SetFiltergraph(pGraph);
// Not shown: Use the System Device Enumerator to create the
// audio capture filter.
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pSrc);
hr = pGraph->AddFilter(pSrc, L"VideooCap");
hr = pMoniker2->BindToObject(0, 0, IID_IBaseFilter, (void**)&pSrc2);
hr = pGraph->AddFilter(pSrc2, L"AudioCap");
IBaseFilter *pMux;
//IFileSinkFilter *pSink;
hr = pBuild->SetOutputFileName(
&MEDIASUBTYPE_Avi, // Specifies AVI for the target file.
L"C:\\wav\\Example2.mp4", // File name.
&pMux, // Receives a pointer to the mux.
NULL); // (Optional) Receives a pointer to the file sink.
IUnknownPtr pUnk;
//static CLSID const clsid = { 0x025BE2E4, 0x1787, 0x4DA4, { 0xA5,0x85,0xC5,0xB2,0xB9,0xEE,0xB5,0x7C } };
static CLSID const clsid = { 0x5FD85181, 0xE542, 0x4e52, { 0x8D,0x9D,0x5D,0x61,0x3C,0x30,0x13,0x1B } };
//5FD85181-E542-4e52-8D9D5D613C30131B
HRESULT hr = CreateObjectFromPath(TEXT("c:\\filters\\mp4mux.dll"), clsid, &pUnk);
if (SUCCEEDED(hr))
{
IBaseFilterPtr pFilter = pUnk;
HRESULT hr = pGraph->AddFilter(pFilter, L"Private Filter");
}
hr = pBuild->RenderStream(
NULL,//NULL,//&PIN_CATEGORY_CAPTURE, // Pin category.
NULL,//&MEDIATYPE_Interleaved,//NULL,//&MEDIATYPE_Audio, // Media type.
pSrc, // Capture filter.
NULL, // Intermediate filter (optional).
pMux); // Mux or file sink filter.
hr = pBuild->RenderStream(
NULL,//NULL,//&PIN_CATEGORY_CAPTURE, // Pin category.
NULL,//&MEDIATYPE_Interleaved,//NULL,//&MEDIATYPE_Audio, // Media type.
pSrc2, // Capture filter.
NULL, // Intermediate filter (optional).
pMux); // Mux or file sink filter.
IMediaControl *pMC = NULL;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pMC);
printf("START");
hr = pMC->Run();
Sleep(4000);
hr = pMC->Stop();
printf("END");
CoUninitialize();
}
}
You should re-read Using Filters Without Registration. The second parameter is CLSID, the class identifier, not interface identifier (IBaseFilter).
For the GDCL MPEG-4 Demultiplexer, it is like this:
class __declspec(uuid("025BE2E4-1787-4DA4-A585-C5B2B9EEB57C")) GdclMp4Demux; // GDCL Mpeg-4 Demultiplexor
... = CreateObjectFromPath(..., __uuidof(GdclMp4Demux), ...);