www.pudn.com > FacialFeature.rar > 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  
#include  
#include "iProxyTrans.h" 
#include "ProxyTransuids.h" 
#include "iSyncFilter.h" 
#include "syncfilteruids.h" 
#include  
#include  
#include "afxres.h" 
#include "resource.h" 
#include "cvcamavi.h" 
#include "cvcam.h" 
 
#include  
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 
{ 
public: 
    SafeMoniker(const SafeMoniker& p)  
    { 
        m_pointer = p.m_pointer;m_pointer->AddRef(); 
    }; 
    SafeMoniker(IMoniker* p)  
    { 
        m_pointer = p; 
    } 
}; 
 
class SafeUnknown : public SafePointer 
{ 
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 _cvcamCreateDevEnum(NULL); 
static SafePointer   _cvcamEnumMon(NULL); 
static vector _cvcamMonikers; 
typedef SafePointer SafeFilter; 
static vector _cvcamSource(NULL); 
//static SafePointer _cvcamSource; 
static SafePointer _cvcamProxyTrans(NULL); 
static SafePointer _cvcamCvSync(NULL); 
static SafePointer _cvcamGraphBuilder(NULL); 
static SafePointer _cvcamMediaControl(NULL); 
static SafePointer _cvcamMediaEventEx(NULL); 
static SafePointer _cvcamVideoWindow(NULL); 
static SafePointer _cvcamVideoWindow2(NULL); 
//static SafePointer _cvcamFilterGraph; 
//typedef SafePointer SafeBindCtx; 
//static vector _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> _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()); 
    /* Create capture device enumerator*/ 
    if(!_cvcamEnumMon.is_valid()) 
    { 
        HRESULT hr = _cvcamCreateDevEnum->CreateClassEnumerator( CLSID_VideoInputDeviceCategory, 
                        &_cvcamEnumMon, 0); 
        if( hr != NOERROR) 
            return -1; 
    } 
 
 
    if(!_cvcamSource.size())//           [0]/*.is_valid()*/) 
    { 
        uint count = cvcam_properties.size(); 
        if(cvcam_properties.size() == 0) 
        { 
            /* Count the capture devices */ 
            unsigned long fetched = 1; 
            for(count = 0; fetched != 0; count++) 
            { 
                _cvcamEnumMon->Next(1, &_cvcamMon, &fetched); 
                if(fetched) 
                { 
                    _cvcamMonikers.push_back(_cvcamMon); 
 
 
                    SafePointer pIBF(NULL); 
 
                    _cvcamSource.push_back(pIBF); 
                } 
            } 
            count--; 
            _cam_properties prop; 
            cvcam_properties.assign(count, prop); 
        } 
 
 
        if(filter) 
        { 
            // find the user's camera selection 
            for(uint i = 0; i < cvcam_properties.size(); i++) 
            { 
                if(cvcam_properties[i]._enabled) 
                { 
                    camera_index = i; 
                } 
            } 
 
            if(camera_index < 0) 
            { 
                /* select a video source and return a pointer to it */ 
                for(uint i = 0; i < count; i++) 
                { 
                    _cvcamMonikers[i]->BindToObject(0, 0, IID_IBaseFilter,  
                                                    (void **)filter); 
                    if(filter) 
                    { 
                        cvcam_properties[i]._enabled = 1; 
                        _cvcamSource[i]=*filter; 
                        camera_index = i; 
                        return count; 
                    } 
                } 
            } 
            else 
            { 
                _cvcamMonikers[(uint)camera_index]->BindToObject(0, 0, IID_IBaseFilter, 
                                                                (void **)filter); 
                if(filter) 
                { 
                    _cvcamSource[(uint)camera_index]=*filter; 
                } 
            } 
 
            *filter = 0; 
            return 0; 
        } 
 
        return count; 
    } 
    else 
    { 
        if(!filter) 
            return cvcam_properties.size(); 
 
        for(uint i = 0; i < cvcam_properties.size(); i++) 
        { 
            if(cvcam_properties[i]._enabled) 
            { 
                /* Initialize the camera */ 
                _cvcamMonikers[i]->BindToObject(0, 0, IID_IBaseFilter, (void **)filter); 
                if(filter) 
                { 
                    _cvcamSource[i]=*filter; 
                    camera_index = i; 
                    return i; 
                } 
            } 
        } 
 
        /* No camera has been selected */ 
        *filter = 0; 
        return -1; 
    } 
} 
 
/* Creates a window for DS rendering */ 
HWND _cvcamCreateWindow() 
{ 
    cvNamedWindow("cvcam window", 0); 
    return (HWND)cvGetWindowHandle("cvcam window"); 
} 
 
/* Returns the actual number of currently available cameras */ 
CVCAM_API int cvcamGetCamerasCount() 
{ 
    int n = _cvcamInitVideoSource(0); 
    return (n>0)?n:0; 
} 
 
/* Summons the video format property page */ 
static void _cvcamSummonPinPropPage(int camera) 
{ 
    if(!cvcam_properties[camera]._enabled) 
        return; 
    //Find the output pit that is connected to the next filter... 
    CAUUID uuID; 
    ISpecifyPropertyPages* pspp = 0; 
     
    //***     
    int fcvcamInit = 0; 
    OAFilterState state = State_Stopped; 
    //if _cvcamMediaControl is valid, it means Graph has already been builded  
    //then we have to disconnect all filters first 
    if(_cvcamMediaControl.is_valid()) 
    { 
        fcvcamInit = 1; 
        //keep graph state before disconnect it, os we can restart from current state  
        _cvcamMediaControl->GetState(0, &state); 
        //disconnect graph 
        _cvcamTearDownGraph(); 
    } 
    //*** 
 
    IBaseFilter* filter = _cvcamSource[camera].value(); 
     
    IPin* pPin = get_source_pin(_cvcamSource[camera].value(), PINDIR_OUTPUT); 
    if(!pPin) 
        pPin=get_pin(filter, PINDIR_OUTPUT); 
 
    if(!pPin) 
        return; 
 
    pPin->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pspp); 
    if(!pspp) 
        return; 
         
    pspp->GetPages(&uuID); 
    pspp->Release(); 
 
 
    OleCreatePropertyFrame(NULL, 0, 0, L"Video Source", 1,  
        (IUnknown**)&pPin, uuID.cElems, uuID.pElems, 
        0, 0, NULL); 
 
    CoTaskMemFree(uuID.pElems); 
    pPin->Release(); 
 
 
    //*** take them back to where they were before they called this function 
    if(fcvcamInit) 
    { 
        cvcamInit(); 
        if(state == State_Running) 
            cvcamStart(); 
    } 
    //*** 
 
     
} 
 
/* Summons the video format property page */ 
static void _cvcamSummonFilterPropPage(int camera) 
{ 
    if(!cvcam_properties[camera]._enabled) 
        return; 
 
    //Find the output pit that is connected to the next filter... 
    CAUUID uuID; 
    ISpecifyPropertyPages* pspp = 0; 
    //IBaseFilter* filter =_cvcamSource[camera].value(); 
    //IMoniker* mon = _cvcamMonikers[camera].value(); 
    //_cvcamProxyTrans->QueryInterface(IID_IBaseFilter, (void**)&filter); 
    //IPin* pProxyPin = get_pin(filter, PINDIR_INPUT); 
    //pProxyPin->Disconnect(); 
    //_cvcamMonikers[0]->BindToObject(0, 0, IID_IBaseFilter, (void **)&filter); 
    //IMoniker* mon = _cvcamMonikers[camera].value(); 
    //IMoniker* pmon; 
    //_cvcamMonikers[camera]->QueryInterface(IID_IMoniker,(void**)&pmon); 
    //pmon->BindToStorage(0,0,IID_IBaseFilter, (void **)&filter); 
    //BindMoniker(mon,0,IID_IBaseFilter,(void **)&filter); 
    //filter= _cvcamSource.value; 
    /* 
    IPropertyBag *pBag; 
    HRESULT hr = mon->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag); 
    if(SUCCEEDED(hr)) { 
        VARIANT var; 
        var.vt = VT_BSTR; 
        hr = pBag->Read(L"FriendlyName", &var, NULL); 
        pBag->Release(); 
    } 
    */ 
    //BindMoniker(mon,0,IID_IBaseFilter,(void **)&filter); 
    //mon->BindToObject(0,0,IID_IBaseFilter, (void **)&filter); 
    //IPin* pPin = get_source_pin(_cvcamSource[camera].value(), PINDIR_OUTPUT); 
    //IPin* pPin = get_source_pin(filter, PINDIR_OUTPUT); 
    //if(!pPin) 
     //   pPin=get_pin(filter, PINDIR_OUTPUT); 
 
    //if(!pPin) 
     //   return; 
 
     
     
    IBaseFilter* bf = _cvcamSource[camera].value(); 
//    IUnknown** ppobject = (IUnknown**)&pPin; 
    bf->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pspp); 
    if(!pspp) 
        return; 
         
     
 
    pspp->GetPages(&uuID); 
    pspp->Release(); 
 
    /* Disconnect the pin to enable possible changes in the output format... */ 
    OAFilterState state = State_Stopped; 
    if(_cvcamMediaControl.is_valid()) 
        _cvcamMediaControl->GetState(0, &state); 
    if(state != State_Stopped) 
        cvcamStop(); 
 
/* 
    IPin* pTempPin =  
    if(pPin) 
*/ 
   // pPin->Disconnect(); 
    //IBaseFilter* pFilter; 
    //_cvcamProxyTrans->QueryInterface(IID_IBaseFilter, (void**)&pFilter); 
    //IPin* pProxyPin = get_pin(pFilter, PINDIR_INPUT); 
   // pProxyPin->Disconnect(); 
 
    OleCreatePropertyFrame(NULL, 0, 0, L"Video Source", 1,  
        (IUnknown**)&bf, uuID.cElems, uuID.pElems, 
        0, 0, NULL); 
    //_cvcamGraphBuilder->Connect(pSPin, pProxyPin); 
    if(state == State_Running) 
        //_cvcamMediaControl->Run(); 
        cvcamStart(); 
} 
 
 
#define CHECK_CAMERA(p) if((p) < 0 || (p) >= cvcam_properties.size()) return -1; 
#define CHECK_ZERO if(!value) return -1; 
#define CHECK_POSITIVE(p) if((p) < 0) return -1; 
 
/* get/set the property of the camera. returns 0 if the property is not supported */ 
CVCAM_API int cvcamGetProperty(int camera, const char* property, void* value) 
{ 
    if (camera>=AVIS_START)  
    { 
        return cvcamAVIGetProperty(camera,property,value); 
    } 
    CHECK_CAMERA((uint)camera); 
     
    if(strcmp(property, CVCAM_PROP_ENABLE) == 0) 
    { 
        CHECK_ZERO(value); 
        *(int*)value = cvcam_properties[(uint)camera]._enabled; 
        return 0; 
    } 
    else if(strcmp(property, CVCAM_PROP_RENDER) == 0) 
    { 
        CHECK_ZERO(value); 
        *(int*)value = cvcam_properties[(uint)camera].render; 
        return 0; 
    } 
    else if(strcmp(property, CVCAM_PROP_WINDOW) == 0) 
    { 
        CHECK_ZERO(value); 
        *(int*)value = cvcam_properties[(uint)camera].window; 
        return 0; 
    } 
    else if(strcmp(property, CVCAM_VIDEOFORMAT) == 0) 
    { 
        _cvcamSummonPinPropPage(camera); 
        return 0; 
    } 
     
    else if(strcmp(property, CVCAM_CAMERAPROPS) == 0) 
    { 
        _cvcamSummonFilterPropPage(camera); 
        return 0; 
    } 
 
    else if(strcmp(property, CVCAM_DESCRIPTION) == 0) 
    { 
        IPropertyBag *pBag; 
        HRESULT hr = _cvcamMonikers[camera]->BindToStorage 
                                (0, 0, IID_IPropertyBag, (void **)&pBag); 
         
        if(SUCCEEDED(hr))  
        { 
            VARIANT var; 
            var.vt = VT_BSTR; 
            hr = pBag->Read(L"FriendlyName", &var, NULL); 
            pBag->Release(); 
            char pcOut[100]; 
            strcpy (pcOut, ""); 
            int res = wcstombs(pcOut,var.bstrVal,100); 
            strcpy(((CameraDescription*)value)->DeviceDescription, pcOut); 
                 
            VariantClear(&var); 
             
            return (res>=0)-1; 
        } 
        else 
        { 
            strcpy(((CameraDescription*)value)->DeviceDescription,""); 
            return -1; 
  
        }//if(SUCCEEDED(hr))  
         
    } 
 
    return -2; 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
CVCAM_API int cvcamSetProperty(int camera, const char* property, void* value) 
{ 
    if (camera>=AVIS_START)  
    { 
        return cvcamAVISetProperty(camera,property,value); 
    } 
    if(strcmp(property, CVCAM_PROP_ENABLE) == 0) 
    { 
         
        int val = (int)value; 
 
        if(cvcam_properties[(uint)camera]._enabled && val) 
            return -3; 
 
        CHECK_POSITIVE(camera); 
        if((uint)camera >= cvcam_properties.size()) return 0; 
        cvcam_properties[(uint)camera]._enabled = val; 
        if(val) 
        { 
        //*** 
        /* 
            IBaseFilter* filter; 
            _cvcamMonikers[camera]->BindToObject(0,  
                                                 0, 
                                                 IID_IBaseFilter,  
                                                 (void **)&filter); 
            if(filter) 
            { 
             
                _cvcamSource[camera]=filter; 
 
            } 
            else 
                cvcam_properties[(uint)camera]._enabled = 0; 
        */ 
 
            if(_cvcamInitCapFilters(camera) < 0) 
                cvcam_properties[(uint)camera]._enabled = 0; 
        //*** 
        } 
 
        return 0; 
    } 
    else if (strcmp(property, CVCAM_PROP_RENDER) == 0) 
    { 
        int val = (int)value; 
        cvcam_properties[(uint)camera].render = val; 
        return 0; 
    } 
    else if (strcmp(property, CVCAM_PROP_WINDOW) == 0) 
    { 
        int val = *(int*)value; 
        cvcam_properties[camera].window = val; 
        return 0; 
    } 
    else if(strcmp(property, CVCAM_PROP_CALLBACK) == 0) 
    { 
        cvcam_properties[camera].callback = value; 
        return 0; 
    } 
 
    else if(strcmp(property, CVCAM_STEREO_CALLBACK) == 0) 
    { 
        stereo_callback = value; 
        return 0; 
    } 
 
    else if (strcmp(property, CVCAM_RNDWIDTH) == 0) 
    { 
        int val = *(int*)value; 
        OAFilterState state = State_Stopped; 
         
        if(_cvcamMediaControl.is_valid()) 
            _cvcamMediaControl->GetState(0, &state); 
        if(state != State_Stopped) 
            cvcamStop(); 
 
        cvcam_properties[camera].rndwidth = val; 
         
        if(state == State_Running) 
            cvcamStart(); 
        return 0; 
    } 
 
    else if (strcmp(property, CVCAM_RNDHEIGHT) == 0) 
    { 
        int val = *(int*)value; 
        OAFilterState state = State_Stopped; 
         
        if(_cvcamMediaControl.is_valid()) 
            _cvcamMediaControl->GetState(0, &state); 
        if(state != State_Stopped) 
            cvcamStop(); 
         
        cvcam_properties[camera].rndheight = val; 
        if(state == State_Running) 
            cvcamStart(); 
        return 0; 
    } 
 
 
 
    return -2; 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
/* gets all property names. the actual number of properties is returned. */ 
CVCAM_API int cvcamGetPropertiesList(int camera, const char** properties, int count) 
{ 
    CHECK_CAMERA((uint)camera); 
    if(count-- > 0) 
    { 
        properties[0] = CVCAM_PROP_ENABLE; 
    } 
    if(count-- > 0) 
    { 
        properties[1] = CVCAM_PROP_RENDER; 
    } 
    if(count-- > 0) 
    { 
        properties[2] = CVCAM_PROP_WINDOW; 
    } 
 
    return 3; 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
/* Prepares the currently enabled cameras for work */ 
CVCAM_API int cvcamInit() 
{ 
     
//    IBaseFilter* filter; 
    vector _objects; 
 
    //*** video source filter have already been created when user call  
    //cvcamSetProperty to enable camera. So we don't need to do it again. 
    // 
    /* Create a video source filter */ 
//  _cvcamInitVideoSource(&filter); 
 
    if(_cvcamNumberOfEnabled() == 2) 
        return _cvcamInit2Cams(); 
     
     
    /* Create a proxy transform filter */ 
    if(FAILED(CoCreateInstance(CLSID_ProxyTransform, NULL, CLSCTX_INPROC_SERVER,  
                    IID_IProxyTransform, (void**)&_cvcamProxyTrans))) 
    { 
        MessageBox(0,"ProxyTrans.ax is not registered.\nPlease run \"opencv\\bin\\registerall.bat\" to register it.\n" 
                   "Also, do not forget to add \"opencv\\bin\" to the system path.", "Error", MB_OK|MB_ICONERROR); 
        return 0; 
    } 
 
    _cvcamProxyTrans->set_transform( 
        (void(__cdecl*)(void*))cvcam_properties[camera_index].callback, 0); 
 
 
    //*** Again, we already have got one.  
    // 
    /* Create a filter graph object */ 
/*    if(FAILED(CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,  
                      IID_IGraphBuilder, (void **)&_cvcamGraphBuilder ))) 
    { 
        return 0; 
    } 
*/ 
    ASSERT(!_cvcamMediaControl.is_valid()); 
    _cvcamGraphBuilder->QueryInterface(IID_IMediaControl,(void**)&_cvcamMediaControl); 
    _cvcamGraphBuilder->QueryInterface(IID_IMediaEventEx,(void**)&_cvcamMediaEventEx); 
    _cvcamGraphBuilder->QueryInterface(IID_IVideoWindow, (void**)&_cvcamVideoWindow); 
 
    IBaseFilter* pProxyTrans = 0; 
    _cvcamProxyTrans->QueryInterface(IID_IBaseFilter, (void**)&pProxyTrans); 
    _objects.push_back(SafeUnknown(pProxyTrans)); 
 
    /* link all filters together*/ 
    if( _cvcamGraphBuilder.is_valid() ) 
    { 
        HRESULT hr; 
 
        //*** It's been added. 
//      hr = _cvcamGraphBuilder->AddFilter( (_cvcamSource[camera_index]).value(), L"Video Source" ); 
 
        hr = _cvcamGraphBuilder->AddFilter( pProxyTrans, L"Script processing"); 
 
         
        IPin* pSourceOut    = get_source_pin( _cvcamSource[camera_index].value(), 
                                              PINDIR_OUTPUT ); 
        IPin* pProxyTransIn     = get_pin( pProxyTrans, PINDIR_INPUT ); 
        IPin* pProxyTransOut    = get_pin( pProxyTrans, PINDIR_OUTPUT ); 
        _objects.push_back(SafeUnknown(pSourceOut)); 
        _objects.push_back(SafeUnknown(pProxyTransIn)); 
        _objects.push_back(SafeUnknown(pProxyTransOut)); 
     
        if( pSourceOut && pProxyTransIn && pProxyTransOut ) 
        { 
             
            hr = _cvcamGraphBuilder->Connect(pSourceOut, pProxyTransIn); 
 
            int render; 
            cvcamGetProperty(camera_index, CVCAM_PROP_RENDER, &render); 
            if(render) 
                hr = _cvcamGraphBuilder->Render( pProxyTransOut ); 
 
        } 
    } 
 
    return 1; 
} 
 
//*** I HAVE NOT YET TESTED WORKING WITH 2 CAMERAS. 
// 
///////////////////////////////////////////////////////////////////////////////////////// 
//Makes the graph from 2 cameras and cvSync filter 
static int _cvcamInit2Cams() 
{ 
    /* Create a cvSync filter */ 
    if(FAILED(CoCreateInstance(CLSID_SyncFilter, NULL, CLSCTX_INPROC_SERVER,  
                    IID_ISyncFilter, (void**)&_cvcamCvSync))) 
    { 
        return 0; 
    } 
 
    if(stereo_callback) 
        _cvcamCvSync->SetCallBack( (void(__cdecl*)(void*, void*))stereo_callback ); 
     
    //*** _cvcamGraphBuilder has already been created in _cvcamInitCapFilters. 
    // 
    /* Create a filter graph object */ 
/*    if(FAILED(CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,  
                      IID_IGraphBuilder, (void **)&_cvcamGraphBuilder ))) 
    { 
        _cvcamCvSync=NULL; 
        return 0; 
    } 
*/ 
    ASSERT(!_cvcamMediaControl.is_valid()); 
    _cvcamGraphBuilder->QueryInterface(IID_IMediaControl,(void**)&_cvcamMediaControl); 
    //_cvcamGraphBuilder->QueryInterface(IID_IMediaEventEx,(void**)&_cvcamMediaEventEx); 
    //_cvcamGraphBuilder->QueryInterface(IID_IVideoWindow, (void**)&_cvcamVideoWindow); 
//    _cvcamGraphBuilder->QueryInterface(IID_IFilterGraph, (void**)&_cvcamFilterGraph); 
 
    IBaseFilter* pSyncFilter = 0; 
    _cvcamCvSync->QueryInterface(IID_IBaseFilter, (void**)&pSyncFilter); 
     
 
    vector _objects; 
    _objects.push_back(SafeUnknown(pSyncFilter)); 
 
/* link all filters together*/ 
    if( _cvcamGraphBuilder.is_valid() ) 
    { 
        HRESULT hr; 
 
         
 
        vector indexes; 
         
        for(uint i = 0; i < cvcam_properties.size(); i++) 
        { 
            if(cvcam_properties[i]._enabled) 
            { 
                //*** All source filters should have been added in . 
/*                hr = _cvcamGraphBuilder->AddFilter( (_cvcamSource[i]).value(), 
                                                    L"Video Source" ); 
                if(FAILED(hr))  
                { 
                    //_cvcamGraphBuilder=NULL; 
                    //_cvcamCvSync=NULL; 
                    return 0; 
                } 
*/ 
                indexes.push_back(i); 
            } 
        } 
         
        hr = _cvcamGraphBuilder->AddFilter( pSyncFilter, L"Script processing"); 
        if(FAILED(hr)) 
        { 
            //_cvcamGraphBuilder=NULL; 
            //_cvcamCvSync=NULL; 
            return 0; 
        } 
 
         
        IPin* pSourceOut1 = get_source_pin( _cvcamSource[indexes[0] ].value(), 
                                            PINDIR_OUTPUT ); 
        if(!pSourceOut1) 
        { 
            //_cvcamGraphBuilder=NULL; 
            //_cvcamCvSync=NULL; 
            return 0; 
         
        } 
        IPin* pSourceOut2 = get_source_pin( _cvcamSource[indexes[1] ].value(), 
                                            PINDIR_OUTPUT ); 
        if(!pSourceOut2) 
        { 
            //_cvcamGraphBuilder=NULL; 
            //_cvcamCvSync=NULL; 
            return 0; 
         
        } 
         
 
        IPin* pSyncInput1; 
        IPin* pSyncInput2; 
        IPin* pSyncOutput1; 
        IPin* pSyncOutput2; 
        pSyncFilter->FindPin(L"Input1", &pSyncInput1); 
        pSyncFilter->FindPin(L"Input2", &pSyncInput2); 
        pSyncFilter->FindPin(L"Output1", &pSyncOutput1); 
        pSyncFilter->FindPin(L"Output2", &pSyncOutput2); 
 
         
         
        _objects.push_back(SafeUnknown(pSourceOut1)); 
        _objects.push_back(SafeUnknown(pSourceOut2)); 
        _objects.push_back(SafeUnknown(pSyncInput1)); 
        _objects.push_back(SafeUnknown(pSyncInput2)); 
        _objects.push_back(SafeUnknown(pSyncOutput1)); 
        _objects.push_back(SafeUnknown(pSyncOutput2)); 
         
         
        
     
        if( pSourceOut1 && pSyncInput1 && pSyncOutput1 ) 
        { 
             
            hr = _cvcamGraphBuilder->Connect(pSourceOut1, pSyncInput1); 
            if(FAILED(hr))  
            { 
                //_cvcamGraphBuilder=NULL; 
                //_cvcamCvSync=NULL; 
                return 0; 
            } 
            int render; 
            cvcamGetProperty(indexes[0], CVCAM_PROP_RENDER, &render); 
            if(render) 
                hr = _cvcamGraphBuilder->Render( pSyncOutput1 ); 
                if(FAILED(hr))  
                { 
                   // _cvcamGraphBuilder=NULL; 
                    //_cvcamCvSync=NULL; 
                    return 0; 
                } 
        } 
 
        if( pSourceOut2 && pSyncInput2 && pSyncOutput2 ) 
        { 
             
            hr = _cvcamGraphBuilder->Connect(pSourceOut2, pSyncInput2); 
            if(FAILED(hr))  
            { 
                //_cvcamGraphBuilder=NULL; 
                //_cvcamCvSync=NULL; 
                return 0; 
            } 
            int render; 
            cvcamGetProperty(indexes[1], CVCAM_PROP_RENDER, &render); 
             
            if(render) 
                hr = _cvcamGraphBuilder->Render( pSyncOutput2 ); 
                if(FAILED(hr))  
                { 
                    //_cvcamGraphBuilder=NULL; 
                    //_cvcamCvSync=NULL; 
                    return 0; 
                } 
        } 
     
    } 
 
 
    return 1; 
}; 
///////////////////////////////////////////////////////////////////////////////////////// 
int _cvcamStart2() 
{ 
     
    vector _objects; 
    IBaseFilter* pcvSync = 0; 
 
    vector indexes; 
         
        for(uint i = 0; i < cvcam_properties.size(); i++) 
        { 
            if(cvcam_properties[i]._enabled) 
            { 
                indexes.push_back(i); 
            } 
        } 
 
    if(!(_cvcamCvSync.is_valid())) 
        return -1; 
 
    //We'll adjust video windows parameters. As we've possibly got 2  
    //renderers and so 2 windows, we can't get the IVideoWindow interface 
    //from IGraphBuilder, so let's go directly to renderers; 
     
    if(cvcam_properties[indexes[0]].render||cvcam_properties[indexes[1]].render) 
    { 
     
        _cvcamCvSync->QueryInterface(IID_IBaseFilter, (void**)&pcvSync); 
        _objects.push_back(SafeUnknown(pcvSync)); 
 
        IPin* output1; 
        IPin* output2; 
 
        ASSERT(pcvSync); 
 
        pcvSync->FindPin(L"Output1", &output1); 
        pcvSync->FindPin(L"Output2", &output2); 
 
        _objects.push_back(SafeUnknown(output1)); 
        _objects.push_back(SafeUnknown(output2)); 
 
        ASSERT(output1&&output2); 
 
        if( !_cvcamMediaControl.is_valid() ) 
        { 
            return -1; 
        }//if( !_cvcamMediaControl.is_valid() ) 
 
        PIN_INFO PinInfo; 
        IBaseFilter* renderer; 
        IPin* pPin; 
 
        if(cvcam_properties[indexes[0]].render) 
        { 
 
            output1->ConnectedTo(&pPin); 
            if(!pPin) 
                return VFW_E_NOT_CONNECTED; 
            _objects.push_back(SafeUnknown(pPin)); 
 
            pPin->QueryPinInfo(&PinInfo); 
             
            renderer = PinInfo.pFilter; 
 
            _objects.push_back(SafeUnknown(renderer)); 
 
 
            //IVideoWindow* pVideoWindow; 
            renderer->QueryInterface(IID_IVideoWindow, (void**)&_cvcamVideoWindow); 
 
             
 
            HWND hWnd; 
         
            cvcamGetProperty(indexes[0], CVCAM_PROP_WINDOW, &hWnd); 
            if(!hWnd) 
            { 
                hWnd = _cvcamCreateWindow(); 
                cvcamSetProperty(indexes[0], CVCAM_PROP_WINDOW, &hWnd); 
            } 
             
            _cvcamVideoWindow->put_Owner((OAHWND)hWnd); 
 
            long flags; 
            _cvcamVideoWindow->get_WindowStyle(&flags); 
            _cvcamVideoWindow->put_WindowStyle(flags & (~WS_CAPTION) | WS_CHILD); 
            _cvcamVideoWindow->put_MessageDrain((OAHWND)hWnd); 
 
            // Get the rectangle dimensions and resize the client window 
            AM_MEDIA_TYPE amt; 
            pPin->ConnectionMediaType(&amt); 
            VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)amt.pbFormat; 
            if(!vih) 
            { 
                return -1; 
            } 
         
            int rndheight = cvcam_properties[indexes[0]].rndheight? 
            cvcam_properties[indexes[0]].rndheight: 
            vih->bmiHeader.biHeight; 
 
 
            int rndwidth = cvcam_properties[indexes[0]].rndwidth? 
            cvcam_properties[indexes[0]].rndwidth: 
            vih->bmiHeader.biWidth; 
             
 
            _cvcamVideoWindow->SetWindowPosition( 0, 0, rndwidth, rndheight ); 
            const char* name = cvGetWindowName(hWnd); 
            cvResizeWindow(name, rndwidth, rndheight); 
 
            //renderer->Release(); 
            //pPin->Release(); 
            //_cvcamVideoWindow = pVideoWindow; 
             
            //pVideoWindow->Release(); 
 
 
 
        }//if(cvcam_properties[indexes[0]].render) 
 
 
        if(cvcam_properties[indexes[1]].render) 
        { 
            output2->ConnectedTo(&pPin); 
            pPin->QueryPinInfo(&PinInfo); 
             
            renderer = PinInfo.pFilter; 
 
            _objects.push_back(SafeUnknown(pPin)); 
            _objects.push_back(SafeUnknown(renderer)); 
 
 
            IVideoWindow* pVideoWindow; 
            renderer->QueryInterface(IID_IVideoWindow, (void**)&pVideoWindow); 
 
            HWND hWnd; 
         
            cvcamGetProperty(indexes[1], CVCAM_PROP_WINDOW, &hWnd); 
            if(!hWnd) 
            { 
                hWnd = _cvcamCreateWindow(); 
                cvcamSetProperty(indexes[1], CVCAM_PROP_WINDOW, &hWnd); 
            } 
             
            pVideoWindow->put_Owner((OAHWND)hWnd); 
 
            long flags; 
            pVideoWindow->get_WindowStyle(&flags); 
            pVideoWindow->put_WindowStyle(flags & (~WS_CAPTION) | WS_CHILD); 
            pVideoWindow->put_MessageDrain((OAHWND)hWnd); 
 
            // Get the rectangle dimensions and resize the client window 
            AM_MEDIA_TYPE amt; 
            pPin->ConnectionMediaType(&amt); 
            VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)amt.pbFormat; 
            if(!vih) 
            { 
                return -1; 
            } 
         
            int rndheight = cvcam_properties[indexes[1]].rndheight? 
            cvcam_properties[indexes[1]].rndheight: 
            vih->bmiHeader.biHeight; 
 
 
            int rndwidth = cvcam_properties[indexes[1]].rndwidth? 
            cvcam_properties[indexes[1]].rndwidth: 
            vih->bmiHeader.biWidth; 
             
 
            pVideoWindow->SetWindowPosition( 0, 0, rndwidth, rndheight ); 
            const char* name = cvGetWindowName(hWnd); 
            cvResizeWindow(name, rndwidth, rndheight); 
 
             
            //renderer->Release(); 
            //pPin->Release(); 
 
            _cvcamVideoWindow2 = pVideoWindow; 
            //pVideoWindow->Release(); 
 
 
 
        }//if(cvcam_properties[indexes[0]].render) 
 
    }//if(cvcam_properties[indexes[0]].render||cvcam_properties[indexes[1]].render) 
 
   // MessageBox(NULL,"going run", NULL,MB_OK); 
    _cvcamMediaControl->Run(); 
   // MessageBox(NULL,"ran", NULL,MB_OK); 
 
    return 1; 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
/* Start the video */ 
CVCAM_API int cvcamStart() 
{ 
    if(_cvcamNumberOfEnabled() == 2) 
        return _cvcamStart2(); 
 
    vector _objects; 
    IBaseFilter* pProxyTrans = 0; 
    _cvcamProxyTrans->QueryInterface(IID_IBaseFilter, (void**)&pProxyTrans); 
    _objects.push_back(SafeUnknown(pProxyTrans)); 
    IPin* pProxyTransOut    = get_pin( pProxyTrans, PINDIR_OUTPUT ); 
    if(!pProxyTrans || !pProxyTransOut) 
    { 
        return -1; 
    } 
 
    if( !_cvcamMediaControl.is_valid() ) 
    { 
        return -1; 
    } 
 
    int render; 
    cvcamGetProperty(camera_index, CVCAM_PROP_RENDER, &render); 
    if(render) 
    { 
        /* Get the window */ 
        HWND hWnd; 
        cvcamGetProperty(camera_index, CVCAM_PROP_WINDOW, &hWnd); 
        if(!hWnd) 
        { 
            hWnd = _cvcamCreateWindow(); 
            cvcamSetProperty(camera_index, CVCAM_PROP_WINDOW, &hWnd); 
        } 
 
        HRESULT hres = _cvcamVideoWindow->put_Owner((OAHWND)hWnd); 
        long flags; 
        hres = _cvcamMediaEventEx->SetNotifyWindow((OAHWND)hWnd, WM_GRAPHNOTIFY, 0); 
        hres = _cvcamMediaEventEx->SetNotifyFlags(0x00); 
        hres = _cvcamMediaEventEx->CancelDefaultHandling(EC_COMPLETE); 
        hres = _cvcamVideoWindow->get_WindowStyle(&flags); 
        hres = _cvcamVideoWindow->put_WindowStyle(flags & (~WS_CAPTION) | WS_CHILD); 
        hres = _cvcamVideoWindow->put_MessageDrain((OAHWND)hWnd); 
 
        // Get the rectangle dimensions and resize the client window 
        AM_MEDIA_TYPE amt; 
        pProxyTransOut->ConnectionMediaType(&amt); 
        VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)amt.pbFormat; 
        if(!vih) 
        { 
            return -1; 
        } 
         
        int rndheight = cvcam_properties[camera_index].rndheight? 
            cvcam_properties[camera_index].rndheight: 
            vih->bmiHeader.biHeight; 
 
 
        int rndwidth = cvcam_properties[camera_index].rndwidth? 
            cvcam_properties[camera_index].rndwidth: 
            vih->bmiHeader.biWidth; 
             
 
        _cvcamVideoWindow->SetWindowPosition( 0, 0, rndwidth, rndheight ); 
        const char* name = cvGetWindowName(hWnd); 
        cvResizeWindow(name, rndwidth, rndheight); 
    } 
 
    _cvcamMediaControl->Run(); 
    return 0; 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
/* Stop the video */ 
CVCAM_API int cvcamStop() 
{ 
    if( _cvcamMediaControl.is_valid() ) 
    { 
        OAFilterState fs; 
        _cvcamMediaControl->GetState(0,&fs); 
        if(fs == State_Stopped) 
            return S_OK; 
         
         
        _cvcamMediaControl->StopWhenReady(); 
         
        
 
        if(_cvcamVideoWindow.is_valid() ) 
        { 
            _cvcamVideoWindow->put_Visible(OAFALSE); 
            _cvcamVideoWindow->put_Owner(NULL); 
            _cvcamVideoWindow->put_MessageDrain(0); 
             
        } 
         
        if(_cvcamVideoWindow2.is_valid() ) 
        { 
            _cvcamVideoWindow2->put_Visible(OAFALSE); 
            _cvcamVideoWindow2->put_Owner(NULL); 
            _cvcamVideoWindow2->put_MessageDrain(0); 
             
        } 
 
         
         
 
         
         
         
        return 0; 
    } 
    else 
    { 
        return -1; 
    } 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
/* Pause the video; should be used for preventing data changes during frame reading  
    using "frame" and other properties */ 
CVCAM_API int cvcamPause() 
{ 
    if( _cvcamMediaControl.is_valid() ) 
    { 
        OAFilterState fs; 
        _cvcamMediaControl->GetState(0,&fs); 
        if(fs == State_Stopped) 
            return S_OK; 
        _cvcamMediaControl->Pause(); 
    }    
     
    return 0; 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
/* Resume the video */ 
CVCAM_API int cvcamResume() 
{ 
    if( _cvcamMediaControl.is_valid() ) 
    { 
        OAFilterState fs; 
        _cvcamMediaControl->GetState(0,&fs); 
        if(fs == State_Stopped) 
            return S_OK; 
         
        _cvcamMediaControl->Run(); 
    } 
 
    return 0; 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
/* Frees all resources */ 
CVCAM_API int cvcamExit() 
{ 
    _cvcamSource.clear(); 
    _cvcamReset(); 
    _cvcamCreateDevEnum = 0; 
    _cvcamEnumMon = 0; 
    _cvcamMonikers.clear(); 
    cvcam_properties.clear(); 
 
     
 
    return 0; 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
 
CVCAM_API int cvcamBuildStereo() 
{ 
    return -1; 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
/*Procedure for camera selection dialog*/ 
BOOL CALLBACK SelectionDlgProc(HWND hwndDlg, UINT message, 
        WPARAM wParam, LPARAM lParam)  
{ 
    switch (message)  
    { 
        case WM_INITDIALOG: 
        { 
            int n = cvcamGetCamerasCount(); 
            CameraDescription descr; 
            HWND cbwnd = GetDlgItem(hwndDlg,IDC_COMBO1); 
 
             
 
            for(int k = 0; k < n; k++) 
            { 
                cvcamGetProperty(k, CVCAM_DESCRIPTION, (void*)&descr); 
                SendMessage(cbwnd,CB_ADDSTRING ,0,(LPARAM) descr.DeviceDescription); 
 
             
            } 
 
            return FALSE; 
        }//case WM_INITDIALOG: 
 
        case WM_COMMAND:  
        { 
            switch(LOWORD(wParam)) 
            { 
                case IDOK: 
                { 
                     
                    //get 1-st combo selection 
                    int firstcmb =  
                        SendDlgItemMessage(hwndDlg, IDC_COMBO1,CB_GETCURSEL,0,0); 
                     
                    if(firstcmb == -1)//nothing selected 
                    { 
                        EndDialog(hwndDlg, 0); 
                        DestroyWindow(hwndDlg); 
                        return TRUE; 
                     
                    }//if(firstcmb == -1) 
                     
                    //get 2-nd combo selection 
 
                    HWND checkwnd = GetDlgItem(hwndDlg,IDC_CHECK1); 
                    long ischecked = SendMessage(checkwnd,BM_GETCHECK,0,0); 
                    int secondcmb; 
                    if(ischecked == BST_CHECKED) 
                    { 
                        secondcmb = 
                        SendDlgItemMessage(hwndDlg, IDC_COMBO2,CB_GETCURSEL,0,0); 
                         
                        //consider we've deleted the 1-st combo selection 
                        //from the second one's list 
                        if(secondcmb>=firstcmb) secondcmb++; 
                     
                    }//if (ischecked == BST_CHECKED) 
                    else 
                        secondcmb = -1; 
 
                    //remember windows 
                    vector wnd; 
                    for(int i = 0; i< cvcamGetCamerasCount(); i++) 
                    { 
                        HWND wnd1; 
                        cvcamGetProperty(i, CVCAM_PROP_WINDOW, (void*)&wnd1); 
                        wnd.push_back(wnd1); 
                    } 
                     
                    //reset cvcam 
                    cvcamStop(); 
                    cvcamExit(); 
                    cvcamGetCamerasCount(); 
 
                    //apply settings 
                    cvcamSetProperty(firstcmb,CVCAM_PROP_ENABLE, (void*)CVCAMTRUE); 
                    cvcamSetProperty(firstcmb,CVCAM_PROP_RENDER, (void*)CVCAMTRUE); 
                     
 
                    if(secondcmb!=-1) 
                    { 
                        cvcamSetProperty(secondcmb,CVCAM_PROP_ENABLE, (void*)CVCAMTRUE); 
                        cvcamSetProperty(secondcmb,CVCAM_PROP_RENDER, (void*)CVCAMTRUE); 
                         
                                
                    } 
 
                    for(int j = 0; j< cvcamGetCamerasCount(); j++) 
                    cvcamSetProperty(j, CVCAM_PROP_WINDOW, (void*)&(wnd[j])); 
 
                    //init cvcam 
                    if(!cvcamInit() ) 
                    { 
                        MessageBox(0,"bad camera(s) or other error","cvcam error", 
                                    MB_OK|MB_ICONERROR); 
                         
                        return FALSE; 
                     
                    } 
 
                    //making the return value. HIWORD is  
                    //number of cams selected(1 or 2). 
                    //HIBYTE of LOWORD is 1-st cam index 
                    //LOBYTE of LOWORD is 2-nd cam index 
 
                    int ncams = (secondcmb==-1)?1:2; 
                    int result = MAKELONG(MAKEWORD(secondcmb,firstcmb),ncams); 
 
                    EndDialog(hwndDlg, result); 
                    //DestroyWindow(hwndDlg); 
                    return TRUE;     
                     
                } 
 
                case IDCANCEL: 
                { 
                    EndDialog(hwndDlg, 0); 
                    //DestroyWindow(hwndDlg); 
                    return TRUE; 
                 
                 
                } 
 
                case IDC_CHECK1://do we want a second camera? 
                { 
                    HWND checkwnd = GetDlgItem(hwndDlg,IDC_CHECK1); 
                    long ischecked = SendMessage(checkwnd,BM_GETCHECK,0,0); 
 
                    HWND secondcombo = GetDlgItem(hwndDlg, IDC_COMBO2); 
 
                    if(ischecked == BST_CHECKED) //we do 
                    { 
                        EnableWindow(secondcombo,TRUE); 
                         
                        //fill the second combo 
                        int n = cvcamGetCamerasCount(); 
                        CameraDescription descr; 
                        HWND cbwnd = GetDlgItem(hwndDlg,IDC_COMBO2); 
 
                        SendMessage(cbwnd,CB_RESETCONTENT ,0,0); 
                           
             
                        for(int k = 0; k < n; k++) 
                        { 
                            cvcamGetProperty(k, CVCAM_DESCRIPTION, (void*)&descr); 
                            SendMessage(cbwnd,CB_ADDSTRING ,0, 
                                        (LPARAM) descr.DeviceDescription); 
 
             
                        } 
 
                        //remove item selected in a first combo 
                        int selected = SendDlgItemMessage(hwndDlg, IDC_COMBO1, 
                                                          CB_GETCURSEL,0,0); 
                        SendMessage(cbwnd,CB_DELETESTRING ,(WPARAM)selected,0);                     
                     
                    } 
                    else if(ischecked == BST_UNCHECKED) 
                        EnableWindow(secondcombo,FALSE); 
 
                    return FALSE; 
 
 
                 
                 
                }//case IDC_CHECK1: 
 
                case IDC_COMBO1: 
                { 
                    if(HIWORD(wParam)==CBN_SELCHANGE) 
                    { 
                        //reset the second combo 
                        int n = cvcamGetCamerasCount(); 
                        CameraDescription descr; 
                        HWND cbwnd = GetDlgItem(hwndDlg,IDC_COMBO2); 
 
                        SendMessage(cbwnd,CB_RESETCONTENT ,0,0); 
                           
             
                        for(int k = 0; k < n; k++) 
                        { 
                            cvcamGetProperty(k, CVCAM_DESCRIPTION, (void*)&descr); 
                            SendMessage(cbwnd,CB_ADDSTRING ,0, 
                                        (LPARAM) descr.DeviceDescription); 
 
             
                        } 
 
                        //remove item selected in a first combo 
                        int selected = SendDlgItemMessage(hwndDlg, IDC_COMBO1, 
                                                          CB_GETCURSEL,0,0); 
                        SendMessage(cbwnd,CB_DELETESTRING ,(WPARAM)selected,0);  
 
                     
                     
                     
                    }//if(HIWORD(wParam)==CBN_SELCHANGE) 
 
                    return FALSE; 
                 
                 
                }//case IDC_COMBO1: 
             
             
             
             
             
             
            } 
         
        }//case WM_COMMAND: 
     
    }//switch (message) 
 
    return FALSE; 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
 
 
/*Pops up a camera(s) selection dialog 
Return value - number of cameras selected (0,1 or 2); 
Argument(out): an array of selected cameras numbers 
NULL if none selected. Should be released with free() when not needed. 
if NULL passed, not used. 
*/ 
int cvcamSelectCamera(int** out)   
{ 
     
       
    DWORD result = DialogBox( DLLhinst, MAKEINTRESOURCE(IDD_DIALOGBAR), 0, 
                              SelectionDlgProc ); 
 
         
     
    if((out) && (HIWORD(result))) 
    { 
        *out = (int*)malloc(HIWORD(result)*sizeof(int)); 
 
        (*out)[0] = (int)HIBYTE(LOWORD(result)); 
 
        if(HIWORD(result) == 2) 
            (*out)[1] = (int)LOBYTE(LOWORD(result)); 
     
    }//if((*out) && (HIWORD(result))) 
 
    return HIWORD(result); 
     
} 
///////////////////////////////////////////////////////////////////////////////////////// 
/*Plays a specified avi file into a specified window 
if file is NULL, file browser is opened. if window is 0, 
it is created. width and height mean output size's 0 means 
those of avi file are used. __cdecl (*callback)(IplImage*) would be 
called on every frame. NULL means no callback*/ 
CVCAM_API int cvcamPlayAVI(const char* file,  
                           void* window,  
                           int width,  
                           int height, 
                           void* callback) 
{ 
    //Get the file 
    char path[256]; 
    memset(path,0,256); 
    if(!file) 
    { 
        OPENFILENAME fn; 
        fn.lStructSize = sizeof(OPENFILENAME); 
        fn.hwndOwner = NULL; 
        fn.lpstrFilter = NULL; 
        fn.lpstrFile = path; 
        fn.nMaxFile = 256; 
        fn.lpstrFileTitle = NULL; 
        fn.lpstrInitialDir = NULL; 
        fn.lpstrTitle = NULL; 
        fn.Flags = NULL; 
        fn.lpstrDefExt = "avi"; 
        fn.hInstance = DLLhinst; 
        fn.lpfnHook = NULL; 
        fn.lpstrCustomFilter = NULL; 
        fn.lCustData = NULL; 
 
 
        if(!GetOpenFileName(&fn)) 
            return -1; 
         
     
    }//if(!file) 
    else 
        strcpy(path,file); 
 
    /* Get the window */ 
    HWND hWnd = *(HWND*)window; 
         
    if(!hWnd) 
    { 
        hWnd = _cvcamCreateWindow(); 
    } 
     
 
    SafePointer pGraph; 
    SafePointer pMediaControl; 
    SafePointer   pEvent; 
    SafePointer  pVideoWindow; 
    SafePointer pPin; 
    SafePointer pBasicVideo; 
    SafePointer pSFilter; 
    SafePointer pProxyTrans; 
    SafePointer pSourceOut, pProxyIn, pProxyOut; 
    SafePointer pEnumPins; 
    SafePointer pProxyBase; 
     
    //Initialise COM 
    cvcamUseCom Iusecom; 
 
    // Create the filter graph manager and query for interfaces. 
    CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,  
                        IID_IGraphBuilder, (void **)&pGraph); 
 
    // Build the graph. 
    wchar_t wpath[256]; 
    mbstowcs(wpath, path, strlen(path)+1); 
 
     
    HRESULT hres = pGraph->AddSourceFilter(wpath,L"source",&pSFilter); 
    if(FAILED(hres)) 
        return -1; 
 
    // Create a proxy transform filter  
    if(FAILED(CoCreateInstance(CLSID_ProxyTransform, NULL, CLSCTX_INPROC_SERVER,  
                    IID_IProxyTransform, (void**)&pProxyTrans))) 
    { 
        return -1; 
    } 
 
    //set callback 
    pProxyTrans->set_transform((void(__cdecl*)(void*))callback, 0); 
 
    //Get Source output pin 
    pSFilter->EnumPins(&pEnumPins); 
 
    unsigned long fetched(0); 
    pEnumPins->Next(1,&pSourceOut,&fetched); 
    if(!fetched) 
        return -1; 
 
    pEnumPins = NULL; 
     
    //Put ProxyTrans into graph 
    pProxyTrans->QueryInterface(IID_IBaseFilter,(void**)&pProxyBase); 
    pGraph->AddFilter(pProxyBase.value(),L"proxy"); 
     
    //Get ProxyTrans Pins 
    pProxyIn = get_pin( pProxyBase.value(), PINDIR_INPUT ); 
    pProxyOut= get_pin( pProxyBase.value(), PINDIR_OUTPUT ); 
 
    hres = pGraph->Connect(pSourceOut.value(),pProxyIn.value()); 
    if(FAILED(hres)) 
        return -1; 
    hres = pGraph->Render(pProxyOut.value()); 
    if(FAILED(hres)) 
        return -1; 
 
 
     
    //Gain additional interfaces 
    pGraph->QueryInterface(IID_IMediaControl, (void **)&pMediaControl); 
    pGraph->QueryInterface(IID_IMediaEventEx, (void **)&pEvent); 
    pGraph->QueryInterface(IID_IVideoWindow, (void **)&pVideoWindow); 
 
    if(!pMediaControl.is_valid() ||!pEvent.is_valid() ||!pVideoWindow.is_valid()) 
        return -1; 
 
    //Set up the window 
    hres = pVideoWindow->put_Owner((OAHWND)hWnd); 
    long flags; 
    hres = pEvent->SetNotifyWindow((OAHWND)hWnd, WM_GRAPHNOTIFY, 0); 
    hres = pEvent->SetNotifyFlags(0x00); 
    hres = pEvent->CancelDefaultHandling(EC_COMPLETE); 
    hres = pVideoWindow->get_WindowStyle(&flags); 
    hres = pVideoWindow->put_WindowStyle(flags & (~WS_CAPTION) | WS_CHILD); 
    hres = pVideoWindow->put_MessageDrain((OAHWND)hWnd); 
 
    // Get the rectangle dimensions and resize the client window 
    hres = pGraph->QueryInterface(IID_IBasicVideo,(void**)&pBasicVideo); 
    if(SUCCEEDED(hres)) 
    { 
        long left, top, w, h; 
        pBasicVideo->GetSourcePosition(&left, &top,&w,&h); 
        pBasicVideo->SetDestinationPosition(0, 0, width?width:w, height?height:h); 
        pVideoWindow->SetWindowPosition(0,0,width?width:w,height?height:h); 
        const char* name = cvGetWindowName(hWnd); 
        cvResizeWindow(name, width?width:w, height?height:h); 
    
    }//if(SUCCEEDED(hres)) 
     
     
    // Run the graph. 
    pMediaControl->Run(); 
 
    // Wait for completion.  
    long evCode; 
    pEvent->WaitForCompletion(INFINITE, &evCode); 
 
    if(pVideoWindow.is_valid() ) 
    { 
        pVideoWindow->put_Visible(OAFALSE); 
        pVideoWindow->put_Owner(NULL); 
        pVideoWindow->put_MessageDrain(0); 
             
    } 
     
     
     
    return 0; 
}  
 
///////////////////////////////////////////////////////////////////////////////////////// 
cvcamAVIFILE cvcamAVIOpenFile (char* file) 
{ 
    return theAvis.AddSource(file, NULL); 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
int cvcamAVICloseFile (cvcamAVIFILE file) 
{ 
    return theAvis.ReleaseSource(file); 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
int cvcamAVISetWindow (cvcamAVIFILE file, void* window) 
{ 
    return theAvis[file]->SetWindow(*(HWND*)window); 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
int cvcamAVISetCallback (cvcamAVIFILE file, void* callback) 
{ 
    return theAvis[file]->SetCallBack((void (__cdecl *)(void *))callback); 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
int cvcamAVISetSize (cvcamAVIFILE file, int width, int height) 
{ 
    if(width >= 0) 
        theAvis[file]->SetWidth(width); 
    if(height >= 0) 
        theAvis[file]->SetHeight(height); 
 
    return 0; 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
int cvcamAVIRun (cvcamAVIFILE file) 
{ 
    LONGLONG i = 0; 
    theAvis[file]->SetPosition(&i); 
    return theAvis[file]->Start(); 
} 
 
int cvcamAVIStop (cvcamAVIFILE file) 
{ 
    return theAvis[file]->Stop(); 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
int cvcamAVIPause (cvcamAVIFILE file) 
{ 
    return theAvis[file]->Pause(); 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
int cvcamAVIResume (cvcamAVIFILE file) 
{ 
    return theAvis[file]->Resume(); 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
int cvcamAVIWaitCompletion (cvcamAVIFILE file) 
{ 
 
    return theAvis[file]->WaitForCompletion(); 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
 
int cvcamAVIIsRunning (cvcamAVIFILE file) 
{ 
    return theAvis[file]->IsRunning(); 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
static int cvcamAVISetProperty(int source, const char* property, void* value) 
{ 
    if (strcmp(property,CVCAM_PROP_CALLBACK) == 0)  
    { 
        return cvcamAVISetCallback(source, value); 
    } 
    if (strcmp(property,CVCAM_PROP_WINDOW) == 0)  
    { 
        return cvcamAVISetWindow(source,value); 
    } 
    if (strcmp(property,CVCAM_RNDWIDTH) == 0)  
    { 
        return cvcamAVISetSize(source,(int)value,-1); 
         
    } 
    if (strcmp(property,CVCAM_RNDHEIGHT) == 0)  
    { 
        return cvcamAVISetSize(source,-1,(int)value); 
    } 
    if (strcmp(property,CVCAM_PROP_TIME_FORMAT) == 0)  
    { 
        return theAvis[source]->SetTimeFormat((int)value); 
    } 
    if (strcmp(property,CVCAM_PROP_POSITION) == 0)  
    { 
        return theAvis[source]->SetPosition((LONGLONG*)value); 
         
    } 
 
    return -1; 
 
} 
///////////////////////////////////////////////////////////////////////////////////////// 
static int cvcamAVIGetProperty(int source, const char* property, void* value) 
{ 
    if (strcmp(property,CVCAM_PROP_DURATION) == 0)  
    { 
        return theAvis[source]->GetDuration((LONGLONG*)value); 
    } 
    if (strcmp(property,CVCAM_PROP_POSITION) == 0)  
    { 
        return theAvis[source]->GetCurrentPosition((LONGLONG*)value); 
         
    } 
 
    return -1; 
} 
/////////////////////////////////////////////////////////////////////////////////////////