Last active
March 2, 2016 13:55
-
-
Save bcachet/9887801 to your computer and use it in GitHub Desktop.
MFC application to connect to DirectShow's camera and display properties panel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "stdafx.h" | |
#include <atlstr.h> | |
#include <dshow.h> | |
//#include <afxwin.h> | |
#include <string> | |
using namespace std; | |
#define CHECK(err)\ | |
if (FAILED((err))) { \ | |
goto error; \ | |
} | |
#define FREE_PTR_IF_NEEDED(pobj)\ | |
if ((pobj) != NULL) {\ | |
pobj->Release();\ | |
pobj = NULL;\ | |
} | |
HRESULT GetMonicker(IMoniker* & pMoniker, CString deviceName) | |
{ | |
ICreateDevEnum *pSystemDeviceEnumerator= NULL; | |
IEnumMoniker *pVideoInputDeviceEnumerator= NULL; | |
HRESULT status = S_OK; | |
FREE_PTR_IF_NEEDED(pMoniker); | |
CHECK(CoCreateInstance( CLSID_SystemDeviceEnum, | |
NULL, | |
CLSCTX_INPROC, | |
IID_ICreateDevEnum, | |
(void**)&pSystemDeviceEnumerator)); | |
CHECK(pSystemDeviceEnumerator->CreateClassEnumerator( CLSID_VideoInputDeviceCategory, | |
&pVideoInputDeviceEnumerator, | |
0)); | |
while( pVideoInputDeviceEnumerator->Next( 1, &pMoniker, NULL) == S_OK ) { | |
VARIANT var; | |
VariantInit(&var); | |
IPropertyBag *pPropBag= NULL; | |
if (SUCCEEDED(pMoniker->BindToStorage( 0, 0, IID_IPropertyBag, (void**)&pPropBag))) { | |
pPropBag->AddRef(); | |
if (SUCCEEDED(pPropBag->Read( L"FriendlyName", &var, 0))) { | |
CString sTemp(var.bstrVal); | |
if (sTemp.Find(deviceName) != string::npos) { | |
FREE_PTR_IF_NEEDED(pPropBag); | |
break; | |
} | |
} | |
} | |
FREE_PTR_IF_NEEDED(pPropBag); | |
VariantClear(&var); | |
} | |
goto clean; | |
error: | |
status = -1; | |
FREE_PTR_IF_NEEDED(pMoniker); | |
clean: | |
FREE_PTR_IF_NEEDED(pSystemDeviceEnumerator); | |
FREE_PTR_IF_NEEDED(pVideoInputDeviceEnumerator); | |
return status; | |
} | |
HRESULT CreateGraph(IBaseFilter* & pSource, IMoniker* pMoniker) | |
{ | |
ICaptureGraphBuilder2 *pCaptureGraph = NULL; | |
IGraphBuilder* pFilterGraph = NULL; | |
HRESULT status = S_OK; | |
CHECK(pMoniker->BindToObject( 0, 0, IID_IBaseFilter, (void**)&pSource)); | |
CHECK(CoCreateInstance( CLSID_CaptureGraphBuilder2, | |
NULL, | |
CLSCTX_INPROC, | |
IID_ICaptureGraphBuilder2, | |
(void**)&pCaptureGraph)); | |
CHECK(CoCreateInstance( CLSID_FilterGraph, | |
NULL, | |
CLSCTX_INPROC, | |
IID_IGraphBuilder, | |
(void **)&pFilterGraph)); | |
CHECK(pCaptureGraph->SetFiltergraph(pFilterGraph)); | |
CHECK(pFilterGraph->AddFilter(pSource, L"Video Capture")); | |
CHECK(pCaptureGraph->RenderStream( &PIN_CATEGORY_CAPTURE, | |
&MEDIATYPE_Video, | |
pSource, | |
NULL, | |
NULL)); | |
goto clean; | |
error: | |
if (pFilterGraph != NULL) { | |
pFilterGraph->RemoveFilter(pSource); | |
} | |
FREE_PTR_IF_NEEDED(pSource); | |
status = -1; | |
clean: | |
FREE_PTR_IF_NEEDED(pFilterGraph); | |
FREE_PTR_IF_NEEDED(pCaptureGraph); | |
return status; | |
} | |
HRESULT GetPin( IPin* &pPin, | |
IBaseFilter* pFilter, | |
PIN_DIRECTION pinDirection, | |
const GUID* pMajorMediaType = NULL, | |
const GUID* pPinCategory= NULL) | |
{ | |
ICaptureGraphBuilder2 *pCaptureGraph = NULL; | |
HRESULT status = S_OK; | |
CHECK(CoCreateInstance( CLSID_CaptureGraphBuilder2, | |
NULL, | |
CLSCTX_INPROC, | |
IID_ICaptureGraphBuilder2, | |
(void**)&pCaptureGraph)); | |
CHECK(pCaptureGraph->FindPin(pFilter, pinDirection, pPinCategory, pMajorMediaType, false, 0, &pPin)); | |
goto clean; | |
error: | |
status = -1; | |
clean: | |
FREE_PTR_IF_NEEDED(pCaptureGraph); | |
return status; | |
} | |
HRESULT GetCaptureVideoPin(IPin* &pPin, IBaseFilter* pFilter) | |
{ | |
return GetPin(pPin, pFilter, PINDIR_OUTPUT, &MEDIATYPE_Video, &PIN_CATEGORY_CAPTURE); | |
} | |
HRESULT DisplayPropertyPages(IUnknown* Source) | |
{ | |
HRESULT status = S_OK; | |
ISpecifyPropertyPages* pSpecifyPropertyPages= NULL; | |
CAUUID cauuid= { 0, NULL}; | |
CHECK(Source->QueryInterface( IID_ISpecifyPropertyPages, (void**)&pSpecifyPropertyPages)); | |
CHECK(pSpecifyPropertyPages->GetPages( &cauuid)); | |
CHECK(OleCreatePropertyFrame( NULL, | |
0, | |
0, | |
OLESTR("uEye Capture Device Pin"), | |
1, | |
(IUnknown**)&Source, | |
cauuid.cElems, | |
(GUID*)cauuid.pElems, | |
0, | |
0, | |
NULL)); | |
goto clean; | |
error: | |
status = -1; | |
clean: | |
FREE_PTR_IF_NEEDED(pSpecifyPropertyPages); | |
CoTaskMemFree( cauuid.pElems); | |
cauuid.pElems= NULL; | |
cauuid.cElems= 0; | |
return status; | |
} | |
int _tmain(int argc, _TCHAR* argv[]) | |
{ | |
IMoniker *pMoniker= NULL; | |
IBaseFilter *pSource = NULL; | |
IPin *pPin = NULL; | |
HRESULT status = S_OK; | |
CHECK(CoInitialize(NULL)); | |
CHECK(GetMonicker(pMoniker, L"UI231")); | |
CHECK(CreateGraph(pSource, pMoniker)); | |
CHECK(DisplayPropertyPages(pSource)); | |
CHECK(GetCaptureVideoPin(pPin, pSource)); | |
CHECK(DisplayPropertyPages(pPin)); | |
goto clean; | |
error: | |
status = -1; | |
clean: | |
FREE_PTR_IF_NEEDED(pMoniker); | |
FREE_PTR_IF_NEEDED(pSource); | |
CoUninitialize(); | |
return status; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
To compile the C++ project, you will need to create a MFC console application and to link to Strmiids.lib (Project Options > Linker > Input > Additional Dependencies) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
unit DS; | |
interface | |
uses | |
SysUtils, | |
DirectShow9, | |
ActiveX; | |
type | |
EFailedStatus = class(Exception); | |
procedure CHECK(err : HRESULT; err_msg : string = ''); | |
function GetMonicker(var AMoniker : IMoniker) : HRESULT; | |
function CreateGraph(var ASource : IBaseFilter; AMoniker : IMoniker) : HRESULT; | |
function GetPin(var APin : IPin; ASource : IBaseFilter; ADesiredPinDirection : PIN_DIRECTION; const ApMajorMediaType : pGuiD = nil; const ApPinCategory : pGUID = nil) : HRESULT; overload; | |
function DisplayPropertyPages(AFilter : IUnknown) : HRESULT; | |
implementation | |
procedure CHECK(err : HRESULT; err_msg : string); | |
begin | |
if (FAILED(err)) then begin | |
raise EFailedStatus.Create(err_msg); | |
end; | |
end; | |
function GetMonicker(var AMoniker : IMoniker) : HRESULT; | |
var | |
pSystemDeviceEnumerator : ICreateDevEnum; | |
pVideoInputDeviceEnumerator : IEnumMoniker; | |
pPropertyBag : IPropertyBag; | |
v : OLEVariant; | |
begin | |
Result := S_OK; | |
pSystemDeviceEnumerator := nil; | |
pVideoInputDeviceEnumerator := nil; | |
try | |
try | |
CHECK(CoCreateInstance(CLSID_SystemDeviceEnum, nil, CLSCTX_INPROC, ICreateDevEnum, pSystemDeviceEnumerator), 'Creating System Device Enumerator'); | |
CHECK(pSystemDeviceEnumerator.CreateClassEnumerator(CLSID_VideoInputDeviceCategory, pVideoInputDeviceEnumerator,0), 'Creating Video Input Device Enumerator'); | |
while(pVideoInputDeviceEnumerator.Next(1, AMoniker, nil) = S_OK) do begin | |
VariantInit(v); | |
if (SUCCEEDED(AMoniker.BindToStorage(nil, nil, IPropertyBag, pPropertyBag)))then begin | |
if (SUCCEEDED(pPropertyBag.Read('FriendlyName', v, nil))) then begin | |
Break; | |
end; | |
end; | |
VariantClear(v); | |
end; | |
except | |
on EFailedStatus do begin | |
Result := S_FALSE; | |
end; | |
end; | |
finally | |
VariantClear(v); | |
pSystemDeviceEnumerator := nil; | |
pVideoInputDeviceEnumerator := nil; | |
pPropertyBag := nil; | |
end; | |
end; | |
function CreateGraph(var ASource : IBaseFilter; AMoniker : IMoniker) : HRESULT; | |
var | |
pCut, pTyp : pGuiD; | |
ACaptureGraph : ICaptureGraphBuilder2; | |
AFilterGraph : IGraphBuilder; | |
begin | |
try | |
try | |
Result := S_OK; | |
CHECK(AMoniker.BindToObject(nil, nil, IBaseFilter, ASource)); | |
CHECK(CoCreateInstance(CLSID_CaptureGraphBuilder2, nil, CLSCTX_INPROC, ICaptureGraphBuilder2, ACaptureGraph)); | |
CHECK(CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC, IGraphBuilder, AFilterGraph)); | |
CHECK(ACaptureGraph.SetFiltergraph(AFilterGraph)); | |
CHECK(AFilterGraph.AddFilter(ASource, 'Video Capture')); | |
New(pCut); pCut^ := PIN_CATEGORY_CAPTURE; | |
New(pTyp); pTyp^ := MEDIATYPE_Video; | |
CHECK(ACaptureGraph.RenderStream(pCut, pTyp, ASource, nil, nil)); | |
except | |
on EFailedStatus do begin | |
Result := S_FALSE; | |
end; | |
end; | |
finally | |
ACaptureGraph := nil; | |
AFilterGraph := nil; | |
end; | |
end; | |
function GetPin(var APin : IPin; ASource : IBaseFilter; ADesiredPinDirection : PIN_DIRECTION; const ApMajorMediaType : pGuiD = nil; const ApPinCategory : pGUID = nil) : HRESULT; overload; | |
var | |
ACaptureGraph : ICaptureGraphBuilder2; | |
begin | |
Result := S_OK; | |
try | |
try | |
CHECK(CoCreateInstance(CLSID_CaptureGraphBuilder2, nil, CLSCTX_INPROC, ICaptureGraphBuilder2, ACaptureGraph)); | |
CHECK(ACaptureGraph.FindPin(ASource, ADesiredPinDirection, ApPinCategory, | |
ApMajorMediaType, False, 0, APin)); | |
except | |
on EFailedStatus do begin | |
Result := S_FALSE; | |
end; | |
end; | |
finally | |
ACaptureGraph := nil; | |
end; | |
end; | |
function DisplayPropertyPages(AFilter : IUnknown) : HRESULT; | |
var | |
SpecifyPropertyPages : ISpecifyPropertyPages; | |
CAUUID : TCAGUID; | |
begin | |
Result := S_OK; | |
SpecifyPropertyPages := nil; | |
try | |
try | |
CHECK(AFilter.QueryInterface(ISpecifyPropertyPages, SpecifyPropertyPages)); | |
CHECK(SpecifyPropertyPages.GetPages(CAUUID)); | |
CHECK(OleCreatePropertyFrame(0, 0, 0, 'Properties', 1, @AFilter, cauuid.cElems, CAUUID.pElems, 0, 0, nil)); | |
except | |
on EFailedStatus do begin | |
Result := S_FALSE; | |
end; | |
end; | |
finally | |
CoTaskMemFree(CAUUID.pElems); | |
SpecifyPropertyPages := nil; | |
end; | |
end; | |
end. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
program TestDS; | |
{$APPTYPE CONSOLE} | |
uses | |
SysUtils, | |
DirectShow9, ActiveX, | |
DS in 'DS.pas'; | |
var | |
Moniker : IMoniker; | |
Source : IBaseFilter; | |
Pin : IPin; | |
pCut, pTyp : pGuiD; | |
begin | |
try | |
CoInitialize(nil); | |
try | |
CHECK(GetMonicker(Moniker)); | |
CHECK(CreateGraph(Source, Moniker)); | |
// CHECK(DisplayPropertyPages(Source)); | |
New(pCut); pCut^ := PIN_CATEGORY_CAPTURE; | |
New(pTyp); pTyp^ := MEDIATYPE_Video; | |
CHECK(GetPin(Pin, Source, PINDIR_OUTPUT, pTyp, pCut)); | |
CHECK(DisplayPropertyPages(Pin)); | |
finally | |
CoUninitialize(); | |
end; | |
except | |
on E: EFailedStatus do begin | |
Writeln(E.ClassName, ': ', E.Message); | |
end; | |
on E: Exception do | |
Writeln(E.ClassName, ': ', E.Message); | |
end; | |
end. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
IID_ISpecifyPropertyPages OMG an unresolved Desaster beetwen VMR Windowless and IMediaControl
No Human can Control grab Memory Frames with Property and 30 Hz..
only VMR9 Windowless with 3Hz is possible with property page
THE BEST CHOISE IS USE VFW AND ALL IS FINDE DAMED DXSHOW