?? cvcam.cpp
字號:
/*M//////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
//#include "windows.h"
//#include "AFXPRIV.H"
#include "highgui.h"
#include <cvstreams.h>
#include <initguid.h>
#include "iProxyTrans.h"
#include "ProxyTransuids.h"
#include "iSyncFilter.h"
#include "syncfilteruids.h"
#include <windows.h>
#include <objbase.h>
#include "afxres.h"
#include "resource.h"
#include "cvcamavi.h"
#include "cvcam.h"
#include <vector>
using namespace std;
#define WM_GRAPHNOTIFY WM_USER+13
struct _cam_properties
{
int _enabled;
int render;
int window;
void* callback;
int rndwidth;
int rndheight;
_cam_properties() : _enabled(0), render(1), window(0), callback(0), rndwidth(0),
rndheight(0) {};
};
static void* stereo_callback;
static vector<_cam_properties> cvcam_properties;
class SafeMoniker : public SafePointer<IMoniker>
{
public:
SafeMoniker(const SafeMoniker& p)
{
m_pointer = p.m_pointer;m_pointer->AddRef();
};
SafeMoniker(IMoniker* p)
{
m_pointer = p;
}
};
class SafeUnknown : public SafePointer<IUnknown>
{
public:
SafeUnknown(const SafeUnknown& p)
{
m_pointer = p.m_pointer;
if(m_pointer)
{
m_pointer->AddRef();
}
};
SafeUnknown(IUnknown* p)
{
m_pointer = p;
}
};
static IMoniker* _cvcamMon = 0;
static IBindCtx* _cvcamBCtx=0;
static SafePointer<ICreateDevEnum> _cvcamCreateDevEnum(NULL);
static SafePointer<IEnumMoniker> _cvcamEnumMon(NULL);
static vector<SafeMoniker> _cvcamMonikers;
typedef SafePointer<IBaseFilter> SafeFilter;
static vector<SafeFilter> _cvcamSource(NULL);
//static SafePointer<IBaseFilter> _cvcamSource;
static SafePointer<IProxyTransform> _cvcamProxyTrans(NULL);
static SafePointer<ISyncFilter> _cvcamCvSync(NULL);
static SafePointer<IGraphBuilder> _cvcamGraphBuilder(NULL);
static SafePointer<IMediaControl> _cvcamMediaControl(NULL);
static SafePointer<IMediaEventEx> _cvcamMediaEventEx(NULL);
static SafePointer<IVideoWindow> _cvcamVideoWindow(NULL);
static SafePointer<IVideoWindow> _cvcamVideoWindow2(NULL);
//static SafePointer<IFilterGraph> _cvcamFilterGraph;
//typedef SafePointer<IBindCtx> SafeBindCtx;
//static vector<SafeBindCtx> _cvcamBindCtx;
static int camera_index = -1;
static cvcamAVIs theAvis;
/* Resets all the filters */
static void _cvcamReset()
{
_cvcamSource.clear();
_cvcamProxyTrans = NULL;
_cvcamMediaControl = NULL;
_cvcamMediaEventEx = NULL;
_cvcamVideoWindow = NULL;
_cvcamVideoWindow2 = NULL;
_cvcamCvSync = NULL;
_cvcamGraphBuilder = NULL;
}
HINSTANCE DLLhinst;
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to the DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpvReserved // reserved
)
{
DLLhinst = hinstDLL;
//*** it works, putting CoInitialize(0) and CoUninitialize() here
//although I'm not quite sure that this is a good place.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
CoInitialize(0);
break;
case DLL_PROCESS_DETACH:
CoUninitialize();
break;
}
return TRUE;
}
static int _cvcamInitVideoSource(IBaseFilter** filter);
static int _cvcamInit2Cams();
static int cvcamAVISetProperty(int camera, const char* property, void* value);
static int cvcamAVIGetProperty(int camera, const char* property, void* value);
static int _cvcamNumberOfEnabled()
{
int j = 0;
for(uint i = 0; i < cvcam_properties.size(); i++)
{
if(cvcam_properties[i]._enabled)
j++;
}
return j;
}
static IPin* get_source_pin( IBaseFilter* pFilter, PIN_DIRECTION dir )
{
ICaptureGraphBuilder2* cgb2;
IPin* pPin =0;
if(FAILED(CoCreateInstance( CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC_SERVER,
IID_ICaptureGraphBuilder2, (void **)&cgb2 )))
{
return 0;
}
cgb2->FindPin(pFilter, dir, &PIN_CATEGORY_CAPTURE ,
&MEDIATYPE_Video, FALSE, 0, &pPin);
cgb2->Release();
return pPin;
}
IPin* get_pin( IBaseFilter* pFilter, PIN_DIRECTION dir )
{
IEnumPins* pEnumPins = 0;
IPin* pPin = 0;
if( pFilter )
{
pFilter->EnumPins( &pEnumPins );
if( pEnumPins != 0 )
{
for(;;)
{
ULONG cFetched = 0;
PIN_DIRECTION pinDir = PIN_DIRECTION(-1);
pPin = 0;
pEnumPins->Next( 1, &pPin, &cFetched );
if( cFetched == 1 && pPin != 0 )
{
pPin->QueryDirection( &pinDir );
if( pinDir == dir ) break;
pPin->Release();
}
else if(cFetched == 0)
{
return 0;
}
}
pEnumPins->Release();
}
}
return pPin;
}
//*** This function is actually taken from AMCAP,a DirectShow sample program.
//Its original name was NukeDownstream, pretty cool. But I think this name make more sense.
static void _cvcamDisconnectAllFilter(IBaseFilter *pf)
{
IPin *pP, *pTo;
ULONG u;
IEnumPins *pins = NULL;
PIN_INFO pininfo;
HRESULT hr = pf->EnumPins(&pins);
pins->Reset();
while(hr == NOERROR) {
hr = pins->Next(1, &pP, &u);
if(hr >= 0 && pP) {
pP->ConnectedTo(&pTo);
if(pTo) {
hr = pTo->QueryPinInfo(&pininfo);
if(hr == NOERROR) {
if(pininfo.dir == PINDIR_INPUT) {
_cvcamDisconnectAllFilter(pininfo.pFilter);
_cvcamGraphBuilder->Disconnect(pTo);
_cvcamGraphBuilder->Disconnect(pP);
_cvcamGraphBuilder->RemoveFilter(pininfo.pFilter);
}
pininfo.pFilter->Release();
}
pTo->Release();
}
pP->Release();
}
}
if(pins)
pins->Release();
}
//*** The main idea and name of this function is also taken from AMCAP.
//Basicly it just puts everything back to its initial state(before cvcamInit was called)
static void _cvcamTearDownGraph()
{
cvcamStop();
if(_cvcamVideoWindow.is_valid() )
{
_cvcamVideoWindow->put_Visible(OAFALSE);
_cvcamVideoWindow->put_Owner(NULL);
_cvcamVideoWindow = NULL;
}
if(_cvcamVideoWindow2.is_valid() )
{
_cvcamVideoWindow2->put_Visible(OAFALSE);
_cvcamVideoWindow2->put_Owner(NULL);
_cvcamVideoWindow2 = NULL;
}
_cvcamMediaControl = NULL;
_cvcamMediaEventEx = NULL;
// disconnect the graph and release all filter, except _cvcamSource anyway
for(int i = 0; i < _cvcamSource.size(); i++)
if(_cvcamSource[i].is_valid())
_cvcamDisconnectAllFilter(_cvcamSource[i].value());
}
//*** Make a builder graph object
static int _cvcamMakeGraph()
{
// we have one already
if(_cvcamGraphBuilder.is_valid())
return 1;
HRESULT hr = CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&_cvcamGraphBuilder );
return (hr == NOERROR) ? 1 : 0;
}
//*** connect source filter and add it to graph builder so we are ready to call the video source Property Page
static int _cvcamInitCapFilters(int camera)
{
//camera_index will point to the last source filter
camera_index = camera;
HRESULT hr;
if(!_cvcamMakeGraph())
return -1;
IBaseFilter* filter;
hr = _cvcamMonikers[camera]->BindToObject(0, 0, IID_IBaseFilter, (void **)&filter);
if(hr >= 0)
_cvcamSource[camera]=filter;
else
{
cvcam_properties[(uint)camera]._enabled = 0;
return -2;
}
hr = _cvcamGraphBuilder->AddFilter(_cvcamSource[camera].value(), L"Video Source");
if(hr < 0)
return -3;
return 1;
}
/* The function creates a video source enumerator */
static int _cvcamInitVideoSourceEnum()
{
//***
// CoInitialize(0);
vector<SafeUnknown>> _objects;
if(FAILED(CoCreateInstance( CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void**)&_cvcamCreateDevEnum )) ||
!_cvcamCreateDevEnum.is_valid())
{
return -1;
}
return 0;
}
/* The function iterates through all video sources and returns the number of them;
if the input argument is nonzero, returns the pointer to IBaseFilter of the source
that was selected previously. If no source has been selected, selects the first one.
The interface that is returned, should not be released by the user; it will be released
automatically.*/
static int _cvcamInitVideoSource(IBaseFilter** filter)
{
//*** I think it is better idea to let user do
//both CoInitialize and CoUninitialize in their code
//Anyway I can find CoUninitialize anywhere in this file!!
// CoInitialize(0);
if(!_cvcamCreateDevEnum.is_valid())
{
int ret = _cvcamInitVideoSourceEnum();
if(ret < 0)
return ret;
}
ASSERT(_cvcamCreateDevEnum.is_valid());
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -