EDIT: Updated the code and the application calling the DLL no longer crashes.
I want the video being played by DirectShow to keep its aspect ratio when the fourth argument of show_video() is set to true. Here's my DLL's source:
#include <windows.h>
#include <dshow.h>
#pragma comment (lib, "strmiids.lib")
#define DLL extern "C" _declspec(dllexport)
wchar_t *convertCharArrayToLPCWSTR(const char* charArray) {
wchar_t* wString = new wchar_t[4096];
MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096);
return wString;
}
DLL void show_video(double window1, HWND window2, char *fname, double keep_aspect_ratio) {
CoInitialize(NULL);
HRESULT hr = S_OK;
IGraphBuilder *pGraph = NULL;
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
hr = pGraph->RenderFile(convertCharArrayToLPCWSTR(fname), NULL);
IBaseFilter *pVideoRenderer = NULL;
hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pVideoRenderer);
IVMRAspectRatioControl *pAspectRatio = NULL;
hr = pVideoRenderer->QueryInterface(IID_IVMRAspectRatioControl, (void**)&pAspectRatio);
if ((bool)keep_aspect_ratio == true) {
hr = pAspectRatio->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX);
}
else {
hr = pAspectRatio->SetAspectRatioMode(VMR_ARMODE_NONE);
}
IVideoWindow *pVidWin = NULL;
hr = pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVidWin);
RECT rect;
if ((HWND)(DWORD)window1 != NULL) {
SetWindowLong((HWND)(DWORD)window1, GWL_STYLE, GetWindowLong((HWND)(DWORD)window1, GWL_STYLE) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
hr = pVidWin->put_Owner((OAHWND)(HWND)(DWORD)window1);
GetClientRect((HWND)(DWORD)window1, &rect);
}
else {
SetWindowLong(window2, GWL_STYLE, GetWindowLong(window2, GWL_STYLE) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
hr = pVidWin->put_Owner((OAHWND)window2);
GetClientRect(window2, &rect);
}
hr = pVidWin->SetWindowPosition(0, 0, rect.right - rect.left, rect.bottom - rect.top);
hr = pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
hr = pVidWin->SetWindowForeground(OATRUE);
hr = pVidWin->HideCursor(OATRUE);
IMediaControl *pControl = NULL;
hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
hr = pControl->Run();
IMediaEvent *pEvent = NULL;
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
long evCode;
hr = pEvent->WaitForCompletion(INFINITE, &evCode);
hr = pControl->Stop();
hr = pVidWin->put_Visible(OAFALSE);
hr = pVidWin->put_Owner(NULL);
pEvent->Release();
pControl->Release();
pVidWin->Release();
pAspectRatio->Release();
pVideoRenderer->Release();
pGraph->Release();
CoUninitialize();
}
As it stands, calling the DLL from my application, the video I selected for the third argument plays fine, but the video does not keep its original aspect ratio. Does anyone know what I'm doing wrong?
Found the solution. After initializing pVideoRenderer, I needed to add the following line:
pGraph->FindFilterByName(L"Video Renderer", &pVideoRenderer);
So the resulting code looks like this:
#include <windows.h>
#include <dshow.h>
#pragma comment (lib, "strmiids.lib")
#define DLL extern "C" _declspec(dllexport)
wchar_t *convertCharArrayToLPCWSTR(const char* charArray) {
wchar_t* wString = new wchar_t[4096];
MultiByteToWideChar(CP_ACP, 0, charArray, -1, wString, 4096);
return wString;
}
DLL void show_video(double window1, HWND window2, char *fname, double keep_aspect_ratio) {
CoInitialize(NULL);
HRESULT hr = S_OK;
IGraphBuilder *pGraph = NULL;
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
hr = pGraph->RenderFile(convertCharArrayToLPCWSTR(fname), NULL);
IBaseFilter *pVideoRenderer = NULL;
hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pVideoRenderer);
pGraph->FindFilterByName(L"Video Renderer", &pVideoRenderer);
IVMRAspectRatioControl *pAspectRatio = NULL;
hr = pVideoRenderer->QueryInterface(IID_IVMRAspectRatioControl, (void**)&pAspectRatio);
if ((bool)keep_aspect_ratio == true) {
hr = pAspectRatio->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX);
}
else {
hr = pAspectRatio->SetAspectRatioMode(VMR_ARMODE_NONE);
}
IVideoWindow *pVidWin = NULL;
hr = pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVidWin);
RECT rect;
if ((HWND)(DWORD)window1 != NULL) {
SetWindowLong((HWND)(DWORD)window1, GWL_STYLE, GetWindowLong((HWND)(DWORD)window1, GWL_STYLE) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
hr = pVidWin->put_Owner((OAHWND)(HWND)(DWORD)window1);
GetClientRect((HWND)(DWORD)window1, &rect);
}
else {
SetWindowLong(window2, GWL_STYLE, GetWindowLong(window2, GWL_STYLE) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
hr = pVidWin->put_Owner((OAHWND)window2);
GetClientRect(window2, &rect);
}
hr = pVidWin->SetWindowPosition(0, 0, rect.right - rect.left, rect.bottom - rect.top);
hr = pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
hr = pVidWin->SetWindowForeground(OATRUE);
hr = pVidWin->HideCursor(OATRUE);
IMediaControl *pControl = NULL;
hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
hr = pControl->Run();
IMediaEvent *pEvent = NULL;
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
long evCode;
hr = pEvent->WaitForCompletion(INFINITE, &evCode);
hr = pControl->Stop();
hr = pVidWin->put_Visible(OAFALSE);
hr = pVidWin->put_Owner(NULL);
pEvent->Release();
pControl->Release();
pVidWin->Release();
pAspectRatio->Release();
pVideoRenderer->Release();
pGraph->Release();
CoUninitialize();
}
Problem solved! :D
...the process calling the DLL now crashes.
A process crash supposes that you can provide additional details like crash point, exception details etc.
The likely cause is E_NOINTERFACE failure on the preceding QueryInterface call and absence of IVMRAspectRatioControl pointer.
Filter Graph Manager is not supposed to implement IVMRAspectRatioControl. If you have a Video Mixing Renderer filter in your filter graph, QueryInterface directly from it.
UPD. The solution in a another answer is an example of how things should not be done. If you do CoCreateInstance for VR, you should add it to the graph and include it to the rendering process. Otherwise, you don't need CoCreateInstance at all, and you should rather not locate filter by name - enumerate the filters instead and identify your VR by finding the filter which implements interface in question.
Related
I used this tutorial and i always got an error that says "wicFactory was nullptr". I'm using windows 7 and this code doesn't make it work. I've read that you should use CLSID_WICImagingfactory1 But it doesn't work.
this is my code:
HRESULT hr;
bmp = nullptr;
IWICBitmapDecoder *pDecoder = NULL;
IWICBitmapFrameDecode *pSource = NULL;
IWICFormatConverter *pConverter = NULL;
//Creating a factory
IWICImagingFactory *wicFactory = NULL;
CoCreateInstance(
CLSID_WICImagingFactory1,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
(LPVOID*)&wicFactory);
MessageBox(NULL, (LPCWSTR)wicFactory, NULL, MB_OK);
//Creating a decoder
hr = wicFactory->CreateDecoderFromFilename(
filename,
NULL,
GENERIC_READ,
WICDecodeMetadataCacheOnLoad,
&pDecoder);
//Read Frame from image
if (SUCCEEDED(hr)) {
// Create the initial frame.
hr = pDecoder->GetFrame(0, &pSource);
}
//Creating a Converter
if (SUCCEEDED(hr)) {
// Convert the image format to 32bppPBGRA
// (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED).
hr = wicFactory->CreateFormatConverter(&pConverter);
}
//Setup the converter
if (SUCCEEDED(hr)) {
hr = pConverter->Initialize(
pSource,
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
NULL,
0.0f,
WICBitmapPaletteTypeMedianCut
);
}
//Use the converter to create an D2D1Bitmap
//ID2D1Bitmap* bmp;
if (SUCCEEDED(hr))
{
hr = d2dg->pRT->CreateBitmapFromWicBitmap(
pConverter,
NULL,
&bmp
);
}
if (wicFactory)wicFactory->Release();
if (pDecoder)pDecoder->Release();
if (pConverter)pConverter->Release();
if (pSource)pSource->Release();
Can anyone Identify the issue here? I cant find any more information about that problem other then define _WIN32_WINNT to 0x0600 or 0x0601, still that wont help...
As noted in the comments, you need to call CoInitializeEx before you can call CoCreateInstance.
BTW, here's some robust code for creating a WIC factory that handles the "WIC2" vs. "WIC1" down-level scenario for Windows 7 with or without the KB2670838 update:
namespace
{
bool g_WIC2 = false;
BOOL WINAPI InitializeWICFactory(PINIT_ONCE, PVOID, PVOID *ifactory) noexcept
{
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory2,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory2),
ifactory
);
if (SUCCEEDED(hr))
{
// WIC2 is available on Windows 10, Windows 8.x, and Windows 7 SP1 with KB 2670838 installed
g_WIC2 = true;
return TRUE;
}
else
{
g_WIC2 = false;
hr = CoCreateInstance(
CLSID_WICImagingFactory1,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
ifactory
);
return SUCCEEDED(hr) ? TRUE : FALSE;
}
#else
g_WIC2 = false;
return SUCCEEDED(CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
ifactory)) ? TRUE : FALSE;
#endif
}
}
IWICImagingFactory* GetWICFactory(bool& iswic2) noexcept
{
static INIT_ONCE s_initOnce = INIT_ONCE_STATIC_INIT;
IWICImagingFactory* factory = nullptr;
if (!InitOnceExecuteOnce(&s_initOnce,
InitializeWICFactory,
nullptr,
reinterpret_cast<LPVOID*>(&factory)))
{
return nullptr;
}
iswic2 = g_WIC2;
return factory;
}
For details on what's in WIC2, see Microsoft Docs. I support both in DirectXTex to get 32bpp BMP with alpha (BITMAPV5HEADER) and support for 96bp TIFF (GUID_WICPixelFormat96bppRGBFloat) when WIC2 is installed.
You can use WIC2 on Windows 7 if installed, which you enable by building with /D_WIN32_WINNT=0x0601 /D_WIN7_PLATFORM_UPDATE.
yesterday I asked this question about DirectShow programming and eventually was able to solve the problem on my own. Once solved, another problem arose: When I play the video it pops up into another window, and I'd like to display it inside my hWnd window. Plus I'd like to make my video play fullscreen and so I typed this code:
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
IVideoWindow* window = NULL;
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
return -1;
}
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr))
{
return -1;
}
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
if (FAILED(hr)) {
MessageBoxW(GetActiveWindow(), L"Errore IMediaControl", L"Attenzione", MB_ICONERROR);
return -1;
}
hr = pGraph->QueryInterface(IID_IVideoWindow, (void **)&window);
if (FAILED(hr)) {
MessageBoxW(GetActiveWindow(), L"Errore I video window", L"Attenzione", MB_ICONERROR);
return -1;
}
window->put_Owner((OAHWND)GetActiveWindow());
window->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_MAXIMIZEBOX);
RECT rc;
window->put_FullScreenMode(OATRUE);
window->HideCursor(OATRUE);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void**)&pEvent);
if (FAILED(hr)) {
MessageBoxW(GetActiveWindow(), L"Errore IMediaEvent", L"Attenzione", MB_ICONERROR);
return -1;
}
hr = pGraph->RenderFile(L"C:\\Users\\Chuck norris\\Desktop\\Equilibrium.avi", NULL);
if (FAILED(hr)) {
MessageBoxW(GetActiveWindow(), L"Errore IMediaControl", L"Attenzione", MB_ICONERROR);
return -1;
}
else {
hr = pControl->Run();
}
window->Release();
pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();
but still, even if everything compiles fine, I won't achieve the desired results. I even tried to test if IVideoWindow methods worked by putting
window->HideCursor(OATRUE);
but my cursor still appears and even other methods won't have any effect.
What could cause this weird behaviour, and how could I solve?
Thanks in advance!
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;
}
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).
EDIT
Just tested playcap.cpp and I'm also getting the same error so I know it's a not a fault with my code.
--
EDIT 2
Edited my code to preserve the goodMoniker pointer. Same error, however.
+if(pMoniker != goodMoniker)
+{
pMoniker->Release();
+}
--
Having a problem with getting my webcam to work with DirectShow. This line:
hr = goodMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)(&pCap));
returns the following error from MSVC++ 2010 EE:
First-chance exception at 0x777ff9d2 in WebcamControlTest.exe: 0xC0000008: An invalid handle was specified.
Full code here (ripped almost completely from MSDN):
#include <DShow.h>
#include <iostream>
int main(void)
{
IGraphBuilder* pGraph = NULL;
ICaptureGraphBuilder2* pBuild = NULL;
HRESULT hr;
//Initialize pGraph
hr = CoInitialize(NULL);
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**) &pBuild);
if(FAILED(hr))
{
printf("ERROR - Could not initialize COM library");
return 1;
}
//Initialize pBuild
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 2;
}
pBuild->SetFiltergraph(pGraph);
//Initialize pCap
ICreateDevEnum* pDevEnum = NULL;
IEnumMoniker* pEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast<void**>(&pDevEnum));
if(SUCCEEDED(hr))
{
hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
}
IMoniker* goodMoniker = NULL;
HWND hList;
IMoniker *pMoniker = NULL;
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<8;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();
}
}
IBaseFilter* pCap;
hr = goodMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)(&pCap));
if(SUCCEEDED(hr))
{
hr = pGraph->AddFilter(pCap, L"Capture Filter");
}
hr = pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap, NULL, NULL);
while(SUCCEEDED(hr));
pGraph->Release();
pBuild->Release();
pCap->Release();
}
It might be a driver problem as there is one device that works (a virtual driver for screencapping and not actual webcam input) but I've updated, uninstalled and reinstalled to no luck. Any ideas?
After saving a pointer in goodMoniker you release the object a couple of lines below (pMoniker->Release() ). Now goodMoniker points to a released object. You should have increased its reference count.