Update the changelog
[opencv] / filters / ProxyTrans / ProxyTrans.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41 #include <windows.h>
42 //#include <afxwin.h>
43 #include <cvstreams.h>
44 #include <initguid.h>
45 #include <olectl.h>
46 //#include <assert.h>
47 #if (1100 > _MSC_VER)
48 #include <olectlid.h>
49 #endif
50 //#include "IppCV.h"
51 #include "cxcore.h"
52 #include "iProxyTrans.h"
53 #include "ProxyTransprop.h"
54 #include "ProxyTrans.h"
55 #include "ProxyTransuids.h"
56
57 #define SafeRelease(p) { if( (p) != 0 ) { (p)->Release(); (p)= 0; } }
58 #define WM_GRAPHNOTIFY  WM_USER+13
59
60 //
61 // TODO: // Place the filter description here
62 //
63
64 // Files
65 //
66 // ProxyTransprop.cpp         Property page implementation
67 // ProxyTransprop.h           Class definition for the property page
68 // ProxyTransprop.rc          Dialog box template for the property page
69 // ProxyTrans.cpp             Main filter class implementation
70 // ProxyTrans.def             What APIs we import and export from this DLL
71 // ProxyTrans.h               Class definition for the filter
72 // ProxyTransuids.h           The filter CLSIDs
73 // iProxyTrans.h              Defines the custom filter interface
74 // resource.h               Resource file
75
76
77 // setup data
78 const AMOVIESETUP_MEDIATYPE sudPinTypes =
79 {
80     &MEDIATYPE_Video,       // Major type
81     &MEDIASUBTYPE_NULL      // Minor type
82 };
83
84 const AMOVIESETUP_PIN psudPins[] =
85 {
86     {
87         L"Input",           // String pin name
88         FALSE,              // Is it rendered
89         FALSE,              // Is it an output
90         FALSE,              // Allowed none
91         FALSE,              // Allowed many
92         &CLSID_NULL,        // Connects to filter
93         L"Output",          // Connects to pin
94         1,                  // Number of types
95         &sudPinTypes },     // The pin details
96       { L"Output",          // String pin name
97         FALSE,              // Is it rendered
98         TRUE,               // Is it an output
99         FALSE,              // Allowed none
100         FALSE,              // Allowed many
101         &CLSID_NULL,        // Connects to filter
102         L"Input",           // Connects to pin
103         1,                  // Number of types
104         &sudPinTypes        // The pin details
105     }
106 };
107
108
109 const AMOVIESETUP_FILTER sudProxyTransform =
110 {
111     &CLSID_ProxyTransform,        // Filter CLSID
112     L"ProxyTrans",                    // Filter name
113     MERIT_DO_NOT_USE,               // Its merit
114     2,                              // Number of pins
115     psudPins                        // Pin details
116 };
117
118
119 // List of class IDs and creator functions for the class factory. This
120 // provides the link between the OLE entry point in the DLL and an object
121 // being created. The class factory will call the static CreateInstance
122
123 CFactoryTemplate g_Templates[2] = {
124
125     { L"ProxyTrans"
126     , &CLSID_ProxyTransform
127     , ProxyTransform::CreateInstance
128     , NULL
129     , &sudProxyTransform }
130   ,
131     { L"ProxyTrans Property Page"
132     , &CLSID_ProxyTransformPropertyPage
133     , ProxyTransformProperties::CreateInstance }
134 };
135 int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
136
137
138
139 //
140 // Constructor
141 //
142 ProxyTransform::ProxyTransform(TCHAR *tszName,LPUNKNOWN punk,HRESULT *phr) :
143     CTransInPlaceFilter(tszName, punk, CLSID_ProxyTransform,phr),
144     m_transform(NULL),
145     m_SourceFilter(0), m_FilterGraph(0), m_GraphBuilder(0),
146     m_MediaControl(0), m_MediaEventEx(0), m_VideoWindow(0), m_ProxyTrans(0),
147     m_isDSRunning(0)
148 {
149     ASSERT(tszName);
150     ASSERT(phr);
151 } // ProxyTransform
152
153
154 //
155 // CreateInstance
156 //
157 // Provide the way for COM to create a ProxyTransform object
158 //
159 CUnknown * WINAPI ProxyTransform::CreateInstance(LPUNKNOWN punk, HRESULT *phr) {
160
161     ProxyTransform *pNewObject = new ProxyTransform("ProxyTrans", punk, phr);
162     if (pNewObject == NULL) {
163         *phr = E_OUTOFMEMORY;
164     }
165     return pNewObject;
166
167 } // CreateInstance
168
169
170 //
171 // NonDelegatingQueryInterface
172 //
173 // Reveals IProxyTransform and ISpecifyPropertyPages
174 //
175 STDMETHODIMP ProxyTransform::NonDelegatingQueryInterface(REFIID riid, void **ppv)
176 {
177     CheckPointer(ppv,E_POINTER);
178
179     if (riid == IID_IProxyTransform) {
180         return GetInterface((IProxyTransform *) this, ppv);
181     } else if (riid == IID_ISpecifyPropertyPages) {
182         return GetInterface((ISpecifyPropertyPages *) this, ppv);
183     } else {
184         return CTransInPlaceFilter::NonDelegatingQueryInterface(riid, ppv);
185     }
186
187 } // NonDelegatingQueryInterface
188
189
190 //
191 // Transform
192 // Transform the  sample 'in place'
193 //
194 HRESULT ProxyTransform::Transform(IMediaSample *pMediaSample)
195 {
196     BYTE*    pData;
197     IplImage image;
198     
199     pMediaSample->GetPointer(&pData);
200     
201     AM_MEDIA_TYPE* pType = &m_pInput->CurrentMediaType();
202     VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pType->pbFormat;
203     
204     if(pvi->bmiHeader.biBitCount != 24)
205     {
206         return NOERROR;
207     }
208
209     // Get the image properties from the BITMAPINFOHEADER
210     int cxImage    = pvi->bmiHeader.biWidth;
211     int cyImage    = abs(pvi->bmiHeader.biHeight);
212     int stride     = (cxImage * sizeof( RGBTRIPLE ) + 3) & -4;
213
214     // Initialize image header
215     cvInitImageHeader( &image, cvSize(cxImage, cyImage), 8, 3, IPL_ORIGIN_BL, 4 );
216     image.widthStep = stride;
217     // Copy the data
218 /*    if(1/*pvi->bmiHeader.biHeight < 0)
219     {*/
220         cvSetData( &image, pData, stride );
221 /*    }
222     else
223     {
224         int i;
225         image.imageData = (char*)malloc(image.widthStep*cyImage);
226         for(i = 0; i < cyImage; i++)
227             memcpy(image.imageData + i*image.widthStep, pData + (cyImage - 1 - i)*stride, cxImage*3);
228     }*/
229     
230     if(m_transform)
231     {
232         (*m_transform)(&image);
233     }
234
235 /*    if(0/*pvi->bmiHeader.biHeight > 0)
236     {
237         free(image.imageData);
238     }*/
239     
240     return NOERROR;
241 } // Transform
242
243
244 //
245 // CheckInputType
246 //
247 // Check the input type is OK, return an error otherwise
248 //
249 HRESULT ProxyTransform::CheckInputType(const CMediaType *mtIn)
250 {
251     // Check this is a VIDEOINFO type
252
253     if (*mtIn->FormatType() != FORMAT_VideoInfo)
254     {
255         return E_INVALIDARG;
256     }
257
258     VIDEOINFO* vi = (VIDEOINFO*)mtIn->Format();
259     if(vi->bmiHeader.biBitCount != 24)
260     {
261         return E_INVALIDARG;
262     }
263
264
265     return NOERROR;
266
267 } // CheckInputType
268
269
270
271 // CheckTransform
272 //
273 // To be able to transform the formats must be identical
274 //
275
276 HRESULT ProxyTransform::CheckTransform(const CMediaType *mtIn,const CMediaType *mtOut)
277 {
278     HRESULT hr;
279     if (FAILED(hr = CheckInputType(mtIn))) {
280     return hr;
281     }
282
283     // format must be a VIDEOINFOHEADER
284     if (*mtOut->FormatType() != FORMAT_VideoInfo) {
285     return E_INVALIDARG;
286     }
287     
288     // formats must be big enough 
289     if (mtIn->FormatLength() < sizeof(VIDEOINFOHEADER) ||
290     mtOut->FormatLength() < sizeof(VIDEOINFOHEADER))
291     return E_INVALIDARG;
292     
293     VIDEOINFO *pInput = (VIDEOINFO *) mtIn->Format();
294     VIDEOINFO *pOutput = (VIDEOINFO *) mtOut->Format();
295     if (memcmp(&pInput->bmiHeader,&pOutput->bmiHeader,sizeof(BITMAPINFOHEADER)) == 0) {
296     return NOERROR;
297     }
298
299     return E_INVALIDARG;
300 } // CheckTransform
301
302
303 //
304 // DecideBufferSize
305 //
306 // Tell the output pin's allocator what size buffers we
307 // require. Can only do this when the input is connected
308 //
309 HRESULT ProxyTransform::DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties)
310 {
311     // Is the input pin connected
312
313     if (m_pInput->IsConnected() == FALSE) {
314         return E_UNEXPECTED;
315     }
316
317     ASSERT(pAlloc);
318     ASSERT(pProperties);
319     return NOERROR;
320
321 } // DecideBufferSize
322
323
324 //
325 // GetMediaType
326 //
327 // I support one type, namely the type of the input pin
328 // We must be connected to support the single output type
329 //
330 HRESULT ProxyTransform::GetMediaType(int iPosition, CMediaType *pMediaType)
331 {
332     // Is the input pin connected
333
334     if (m_pInput->IsConnected() == FALSE) {
335         return E_UNEXPECTED;
336     }
337
338     // This should never happen
339
340     if (iPosition < 0) {
341         return E_INVALIDARG;
342     }
343
344     // Do we have more items to offer
345
346     if (iPosition > 0) {
347         return VFW_S_NO_MORE_ITEMS;
348     }
349
350     *pMediaType = m_pInput->CurrentMediaType();
351     return NOERROR;
352
353 } // GetMediaType
354
355 //
356 // get_Param
357 //
358 // Return the current Param
359 //
360 //DEL STDMETHODIMP ProxyTransform::get_Param(long* lParam)
361 //DEL {
362 //DEL     CAutoLock cAutoLock(&m_ProxyTransformLock);
363 //DEL     *lParam= m_lParam;
364 //DEL     return NOERROR;
365 //DEL } // get_Param
366
367 //
368 // set_Param
369 //
370 // Sets the Param
371 //
372 STDMETHODIMP ProxyTransform::set_transform(void (__cdecl *transform)(void*),
373                                            void (__cdecl **old_transform)(void*))
374 {
375     CAutoLock cAutoLock(&m_ProxyTransformLock);
376     if(old_transform) *old_transform = m_transform;
377     m_transform = transform;
378     return NOERROR;
379 } // set_transform
380
381
382 STDMETHODIMP ProxyTransform::SetCallBack(void (__cdecl *transform)(void*),
383                                          void (__cdecl **old_transform)(void*))
384 {
385     return set_transform(transform, old_transform);
386 } // set_transform
387
388
389 STDMETHODIMP ProxyTransform::CreateCamera()
390 {
391     ICreateDevEnum* pCreateDevEnum = 0;
392     IEnumMoniker*   pEnumMon = 0;
393     IMoniker*       pMon = 0;
394     ULONG           cFetched = 0;
395     
396     SafeRelease( m_SourceFilter );
397     
398     if(FAILED(CoCreateInstance( CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
399                       IID_ICreateDevEnum, (void**)&pCreateDevEnum )))
400     {
401         return FALSE;
402     }
403     
404     ASSERT(pCreateDevEnum);
405     /* Create capture device */
406     if(FAILED(pCreateDevEnum->CreateClassEnumerator( 
407                 CLSID_VideoInputDeviceCategory, &pEnumMon, 0)) || !pEnumMon)
408     {
409         SafeRelease(pCreateDevEnum);
410         return FALSE;
411     }
412
413     ASSERT(pEnumMon);
414     if(SUCCEEDED( pEnumMon->Next(1, &pMon, &cFetched)) && cFetched == 1 && pMon)
415     {
416         ASSERT(pMon);
417         pMon->BindToObject(0, 0, IID_IBaseFilter, (void **)&m_SourceFilter );
418         if(!m_SourceFilter)
419         {
420             SafeRelease(pCreateDevEnum);
421             SafeRelease(pEnumMon);
422             return FALSE;
423         }
424         FILTER_INFO info;
425         m_SourceFilter->QueryFilterInfo(&info);
426     }
427     else
428     {
429         SafeRelease(pCreateDevEnum);
430         SafeRelease(pEnumMon);
431         return FALSE;
432     }
433
434     // Create a proxy transform filter to enable scripts process images
435     if(FAILED(CoCreateInstance(CLSID_ProxyTransform, NULL, CLSCTX_INPROC_SERVER, 
436                     IID_IProxyTransform, (void**)&m_ProxyTrans)))
437     {
438         SafeRelease(pCreateDevEnum);
439         SafeRelease(pEnumMon);
440         SafeRelease(m_SourceFilter);
441         return FALSE;
442     }
443
444
445     SafeRelease( pMon );
446     SafeRelease( pEnumMon );
447     SafeRelease( pCreateDevEnum );
448
449     return TRUE;
450 }
451
452
453 static IPin* get_pin( IBaseFilter* pFilter, PIN_DIRECTION dir )
454 {
455     IEnumPins*  pEnumPins = 0;
456     IPin*       pPin = 0;
457
458     if( pFilter )
459     {
460         pFilter->EnumPins( &pEnumPins );
461         if( pEnumPins != 0 )
462         {
463             for(;;)
464             {
465                 ULONG  cFetched = 0;
466                 PIN_DIRECTION pinDir = PIN_DIRECTION(-1); 
467                 pPin = 0;
468
469                 pEnumPins->Next( 1, &pPin, &cFetched );
470                 if( cFetched == 1 && pPin != 0 )
471                 {
472                     pPin->QueryDirection( &pinDir );
473                     if( pinDir == dir ) break;
474                     pPin->Release();
475                 }
476                 else if(cFetched == 0)
477                 {
478                     return 0;
479                 }
480             }
481             pEnumPins->Release();
482         }
483     }
484
485     return pPin;
486 }
487
488
489 STDMETHODIMP ProxyTransform::CreateFilterGraph()
490 {
491     
492     if(FAILED(CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
493                       IID_IGraphBuilder, (void **)&m_GraphBuilder )))
494     {
495         SafeRelease(m_GraphBuilder);
496         return FALSE;
497     }
498
499     ASSERT(m_GraphBuilder);
500     m_GraphBuilder->QueryInterface(IID_IMediaControl,(void**)&m_MediaControl);
501     m_GraphBuilder->QueryInterface(IID_IMediaEventEx,(void**)&m_MediaEventEx);
502     m_GraphBuilder->QueryInterface(IID_IVideoWindow, (void**)&m_VideoWindow);
503     m_GraphBuilder->QueryInterface(IID_IFilterGraph, (void**)&m_FilterGraph);
504
505     IBaseFilter* pProxyTrans = 0;
506     m_ProxyTrans->QueryInterface(IID_IBaseFilter, (void**)&pProxyTrans);
507
508 /*    if( m_MediaEventEx )
509     {
510         // Have the graph signal event via window callbacks for performance
511         m_MediaEventEx->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0);
512     }*/
513
514     /* link filters */
515     if( m_FilterGraph )
516     {
517         HRESULT hr;
518         IPin* pSourceOut    = get_pin( m_SourceFilter, PINDIR_OUTPUT );
519
520         IPin* pProxyTransIn     = get_pin( pProxyTrans, PINDIR_INPUT );
521         IPin* pProxyTransOut    = get_pin( pProxyTrans, PINDIR_OUTPUT );
522     
523         if( pSourceOut && pProxyTransIn && pProxyTransOut )
524         {
525             hr = m_FilterGraph->AddFilter( m_SourceFilter, L"Video Source" );
526             hr = m_FilterGraph->AddFilter( pProxyTrans, L"Script processing");
527             hr = m_GraphBuilder->Connect(pSourceOut, pProxyTransIn);
528             hr = m_GraphBuilder->Render( pProxyTransOut );
529             AM_MEDIA_TYPE amt;
530             pSourceOut->ConnectionMediaType(&amt);
531             pProxyTransOut->ConnectionMediaType(&amt);
532             VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)amt.pbFormat;
533             if(!vih || vih->bmiHeader.biBitCount != 24)
534             {
535                 SafeRelease( pSourceOut );
536                 SafeRelease( pProxyTransIn );
537                 SafeRelease( pProxyTransOut );
538                 return FALSE;
539             }
540         }
541
542         SafeRelease( pSourceOut );
543         SafeRelease( pProxyTransIn );
544         SafeRelease( pProxyTransOut );
545     }
546     return TRUE;
547 }
548
549
550 STDMETHODIMP ProxyTransform::InitGraph()
551 {
552     // Initialize DirectShow
553     CoInitialize(0);
554     if(CreateCamera() && CreateFilterGraph())
555     {
556         //Camera video source is available
557         m_DSOn = TRUE;
558     }
559     else
560     {
561         m_DSOn = FALSE;
562     }
563
564     return NOERROR;
565 }
566
567
568 STDMETHODIMP ProxyTransform::StopGraph()
569 {
570     if( m_MediaControl )
571     {
572         m_MediaControl->StopWhenReady();
573         m_VideoWindow->put_Visible(OAFALSE);
574         m_VideoWindow->put_Owner(NULL);
575         m_VideoWindow->put_MessageDrain(0);
576         m_isDSRunning = FALSE;
577     }
578     return NOERROR;
579 }
580
581 STDMETHODIMP ProxyTransform::StartGraph(HWND hWnd)
582 {
583     if( m_MediaControl )
584     {
585         m_VideoWindow->put_Owner((OAHWND)hWnd);
586         long flags;
587         m_MediaEventEx->SetNotifyWindow((OAHWND)hWnd, WM_GRAPHNOTIFY, 0);
588         m_MediaEventEx->SetNotifyFlags(0x00);
589         m_MediaEventEx->CancelDefaultHandling(EC_COMPLETE);
590         m_VideoWindow->get_WindowStyle(&flags);
591         m_VideoWindow->put_WindowStyle(flags & (~WS_CAPTION) | WS_CHILD);
592         m_VideoWindow->put_MessageDrain((OAHWND)hWnd);
593
594         SetVideoWindowSize(hWnd); 
595         m_MediaControl->Run();
596         m_isDSRunning = TRUE;
597     }
598     return NOERROR;
599 }
600
601 STDMETHODIMP ProxyTransform::SetVideoWindowSize(HWND hWnd) 
602 {
603     RECT rc;
604     GetVideoWindowSize(hWnd, &rc);
605     if( m_VideoWindow )
606     {
607         m_VideoWindow->SetWindowPosition( rc.left, rc.top, rc.right, rc.bottom );
608     }
609     return NOERROR;
610 }
611
612 STDMETHODIMP ProxyTransform::GetVideoWindowSize(HWND hWnd, RECT* rect) 
613 {
614     RECT rc = {0, 0, 0, 0};
615     if(hWnd)
616     {
617 //        int width, height;
618 //        GetScaleFactor( width, height );
619
620         ::GetClientRect( hWnd, &rc );
621
622 //        rc.right  = rc.right * width / 100;
623 //        rc.bottom = rc.bottom * height / 100;
624     }
625     *rect = rc;
626
627     return NOERROR;
628 }
629
630
631 //
632 // set_Default
633 //
634 // Sets the Param to the Default Value
635 //
636 //DEL STDMETHODIMP ProxyTransform::set_Default()
637 //DEL {
638 //DEL     CAutoLock cAutoLock(&m_ProxyTransformLock);
639 //DEL     m_lParam=m_lDefault ;
640 //DEL     return NOERROR;
641 //DEL } // set_Default
642
643
644
645
646
647
648 //
649 // GetPages
650 //
651 // This is the sole member of ISpecifyPropertyPages
652 // Returns the clsid's of the property pages we support
653 //
654
655 STDMETHODIMP ProxyTransform::GetPages(CAUUID *pPages)
656 {
657     pPages->cElems = 1;
658     pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
659     if (pPages->pElems == NULL) {
660         return E_OUTOFMEMORY;
661     }
662     *(pPages->pElems) = CLSID_ProxyTransformPropertyPage;
663     return NOERROR;
664
665 } // GetPages
666
667
668
669 //
670 // DllRegisterServer
671 //
672 // Handle registration of this filter
673 //
674 STDAPI DllRegisterServer()
675 {
676     return AMovieDllRegisterServer2( TRUE );
677
678 } // DllRegisterServer
679
680
681 //
682 // DllUnregisterServer
683 //
684 STDAPI DllUnregisterServer()
685 {
686    return AMovieDllRegisterServer2( FALSE );
687
688 } // DllUnregisterServer
689
690 #if 0
691 int GetCameraList(CvCamera** cams)
692 {
693     UnInitialize();
694     num = 0;
695
696     for( int wIndex = 0; wIndex < 10; wIndex++ ) 
697     {
698         memset(&cameras[num].m_Caps, 0, sizeof(cameras[num].m_Caps));
699         if( capGetDriverDescription( wIndex, cameras[num].m_DeviceName,
700             sizeof (cameras[num].m_DeviceName),
701             cameras[num].m_DeviceVersion, sizeof (cameras[num].m_DeviceVersion))) 
702         {
703             cameras[num].m_CaptureWindow = capCreateCaptureWindow( 0, 0, 0, 0, 1, 1, 0, 0);
704             if( capDriverConnect(cameras[num].m_CaptureWindow, wIndex))
705             {
706                 DWORD threadId;
707
708                 capPreviewRate(cameras[num].m_CaptureWindow, 66);  // rate, in milliseconds
709                 memset(&cameras[num].m_Caps, 0, sizeof(cameras[num].m_Caps));
710                 capDriverGetCaps( cameras[num].m_CaptureWindow,
711                                   &cameras[num].m_Caps, sizeof(cameras[num].m_Caps));
712                 cameras[num].m_ThreadId = CreateThread( 0, 0, CameraCallBack,
713                                                         (void*)num, CREATE_SUSPENDED,
714                                                         &threadId );
715                 capSetUserData( cameras[num].m_CaptureWindow, (long)num );
716                 capSetCallbackOnFrame( cameras[num].m_CaptureWindow, FrameCallbackProc ); 
717
718                 num++;
719             }
720         }
721     }
722
723     if(cams) *cams = cameras;
724
725     return num;
726 }
727
728
729 int GetVideoFormat(int camera, BITMAPINFO* video_format, int size)
730 {
731     if(camera > num ||
732        !cameras[camera].m_CaptureWindow ||
733        !cameras[camera].m_Caps.fHasDlgVideoSource) return 0;
734     return capGetVideoFormat(cameras[camera].m_CaptureWindow, video_format, size);
735 }
736
737
738 int SetVideoFormat(int camera, int width, int height, int format)
739 {
740     if(camera > num) return 0;
741
742     BITMAPINFO bmi;
743     
744     memset( &bmi.bmiHeader, 0, sizeof(bmi.bmiHeader));
745     bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
746     bmi.bmiHeader.biBitCount = (unsigned short)(format == 0 ? 24 : 12);
747     bmi.bmiHeader.biWidth = width;
748     bmi.bmiHeader.biHeight = height;
749     bmi.bmiHeader.biPlanes = 1;
750     bmi.bmiHeader.biCompression = format;
751     bmi.bmiHeader.biSizeImage = ((bmi.bmiHeader.biWidth*
752                                   bmi.bmiHeader.biBitCount/8 + 3)&-4)*
753                                   bmi.bmiHeader.biHeight;
754     memset( &bmi.bmiColors, 0, sizeof(bmi.bmiColors) );
755     return capSetVideoFormat( cameras[camera].m_CaptureWindow, &bmi, sizeof(bmi)-4);
756 }
757 #endif
758
759 static IProxyTransform* ProxyTrans = 0;
760
761 __declspec(dllexport) int Initialize()
762 {
763     CoInitialize(0);
764     if(FAILED(CoCreateInstance(CLSID_ProxyTransform, NULL, CLSCTX_INPROC_SERVER, 
765                     IID_IProxyTransform, (void**)&ProxyTrans)))
766         return 0;
767
768     ProxyTrans->InitGraph();
769     return 1;
770 }
771
772
773 __declspec(dllexport) int UnInitialize()
774 {
775     return 1;
776 }
777
778 /*
779 int VideoFormatDlg(int camera)
780 {
781     if(camera > num ||
782        !cameras[camera].m_CaptureWindow ||
783        !cameras[camera].m_Caps.fHasDlgVideoFormat) return 0;
784     return capDlgVideoFormat( cameras[camera].m_CaptureWindow);
785 }
786
787
788 int VideoSourceDlg(int camera)
789 {
790     if(camera > num ||
791        !cameras[camera].m_CaptureWindow ||
792        !cameras[camera].m_Caps.fHasDlgVideoSource) return 0;
793     return capDlgVideoSource( cameras[camera].m_CaptureWindow);
794 }
795 */
796
797 __declspec(dllexport) int RunCamera(int camera, HWND wnd)
798 {
799     if(ProxyTrans) return ProxyTrans->StartGraph(wnd);
800     else return 0;
801 }
802
803
804 __declspec(dllexport) int StopCamera(int camera)
805 {
806     if(ProxyTrans) return ProxyTrans->StopGraph();
807     else return 0;
808 }
809
810
811 __declspec(dllexport) int SetCallBack( int camera, void (*transform)(void*),
812                                        void (**old_transform)(void*) )
813 {
814     if(ProxyTrans) return ProxyTrans->SetCallBack(transform, old_transform);
815     else return 0;
816 }