1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
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.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
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.
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.
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.
43 #include <cvstreams.h>
52 #include "iProxyTrans.h"
53 #include "ProxyTransprop.h"
54 #include "ProxyTrans.h"
55 #include "ProxyTransuids.h"
57 #define SafeRelease(p) { if( (p) != 0 ) { (p)->Release(); (p)= 0; } }
58 #define WM_GRAPHNOTIFY WM_USER+13
61 // TODO: // Place the filter description here
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
78 const AMOVIESETUP_MEDIATYPE sudPinTypes =
80 &MEDIATYPE_Video, // Major type
81 &MEDIASUBTYPE_NULL // Minor type
84 const AMOVIESETUP_PIN psudPins[] =
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
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
109 const AMOVIESETUP_FILTER sudProxyTransform =
111 &CLSID_ProxyTransform, // Filter CLSID
112 L"ProxyTrans", // Filter name
113 MERIT_DO_NOT_USE, // Its merit
115 psudPins // Pin details
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
123 CFactoryTemplate g_Templates[2] = {
126 , &CLSID_ProxyTransform
127 , ProxyTransform::CreateInstance
129 , &sudProxyTransform }
131 { L"ProxyTrans Property Page"
132 , &CLSID_ProxyTransformPropertyPage
133 , ProxyTransformProperties::CreateInstance }
135 int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
142 ProxyTransform::ProxyTransform(TCHAR *tszName,LPUNKNOWN punk,HRESULT *phr) :
143 CTransInPlaceFilter(tszName, punk, CLSID_ProxyTransform,phr),
145 m_SourceFilter(0), m_FilterGraph(0), m_GraphBuilder(0),
146 m_MediaControl(0), m_MediaEventEx(0), m_VideoWindow(0), m_ProxyTrans(0),
157 // Provide the way for COM to create a ProxyTransform object
159 CUnknown * WINAPI ProxyTransform::CreateInstance(LPUNKNOWN punk, HRESULT *phr) {
161 ProxyTransform *pNewObject = new ProxyTransform("ProxyTrans", punk, phr);
162 if (pNewObject == NULL) {
163 *phr = E_OUTOFMEMORY;
171 // NonDelegatingQueryInterface
173 // Reveals IProxyTransform and ISpecifyPropertyPages
175 STDMETHODIMP ProxyTransform::NonDelegatingQueryInterface(REFIID riid, void **ppv)
177 CheckPointer(ppv,E_POINTER);
179 if (riid == IID_IProxyTransform) {
180 return GetInterface((IProxyTransform *) this, ppv);
181 } else if (riid == IID_ISpecifyPropertyPages) {
182 return GetInterface((ISpecifyPropertyPages *) this, ppv);
184 return CTransInPlaceFilter::NonDelegatingQueryInterface(riid, ppv);
187 } // NonDelegatingQueryInterface
192 // Transform the sample 'in place'
194 HRESULT ProxyTransform::Transform(IMediaSample *pMediaSample)
199 pMediaSample->GetPointer(&pData);
201 AM_MEDIA_TYPE* pType = &m_pInput->CurrentMediaType();
202 VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pType->pbFormat;
204 if(pvi->bmiHeader.biBitCount != 24)
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;
214 // Initialize image header
215 cvInitImageHeader( &image, cvSize(cxImage, cyImage), 8, 3, IPL_ORIGIN_BL, 4 );
216 image.widthStep = stride;
218 /* if(1/*pvi->bmiHeader.biHeight < 0)
220 cvSetData( &image, pData, stride );
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);
232 (*m_transform)(&image);
235 /* if(0/*pvi->bmiHeader.biHeight > 0)
237 free(image.imageData);
247 // Check the input type is OK, return an error otherwise
249 HRESULT ProxyTransform::CheckInputType(const CMediaType *mtIn)
251 // Check this is a VIDEOINFO type
253 if (*mtIn->FormatType() != FORMAT_VideoInfo)
258 VIDEOINFO* vi = (VIDEOINFO*)mtIn->Format();
259 if(vi->bmiHeader.biBitCount != 24)
273 // To be able to transform the formats must be identical
276 HRESULT ProxyTransform::CheckTransform(const CMediaType *mtIn,const CMediaType *mtOut)
279 if (FAILED(hr = CheckInputType(mtIn))) {
283 // format must be a VIDEOINFOHEADER
284 if (*mtOut->FormatType() != FORMAT_VideoInfo) {
288 // formats must be big enough
289 if (mtIn->FormatLength() < sizeof(VIDEOINFOHEADER) ||
290 mtOut->FormatLength() < sizeof(VIDEOINFOHEADER))
293 VIDEOINFO *pInput = (VIDEOINFO *) mtIn->Format();
294 VIDEOINFO *pOutput = (VIDEOINFO *) mtOut->Format();
295 if (memcmp(&pInput->bmiHeader,&pOutput->bmiHeader,sizeof(BITMAPINFOHEADER)) == 0) {
306 // Tell the output pin's allocator what size buffers we
307 // require. Can only do this when the input is connected
309 HRESULT ProxyTransform::DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties)
311 // Is the input pin connected
313 if (m_pInput->IsConnected() == FALSE) {
321 } // DecideBufferSize
327 // I support one type, namely the type of the input pin
328 // We must be connected to support the single output type
330 HRESULT ProxyTransform::GetMediaType(int iPosition, CMediaType *pMediaType)
332 // Is the input pin connected
334 if (m_pInput->IsConnected() == FALSE) {
338 // This should never happen
344 // Do we have more items to offer
347 return VFW_S_NO_MORE_ITEMS;
350 *pMediaType = m_pInput->CurrentMediaType();
358 // Return the current Param
360 //DEL STDMETHODIMP ProxyTransform::get_Param(long* lParam)
362 //DEL CAutoLock cAutoLock(&m_ProxyTransformLock);
363 //DEL *lParam= m_lParam;
364 //DEL return NOERROR;
372 STDMETHODIMP ProxyTransform::set_transform(void (__cdecl *transform)(void*),
373 void (__cdecl **old_transform)(void*))
375 CAutoLock cAutoLock(&m_ProxyTransformLock);
376 if(old_transform) *old_transform = m_transform;
377 m_transform = transform;
382 STDMETHODIMP ProxyTransform::SetCallBack(void (__cdecl *transform)(void*),
383 void (__cdecl **old_transform)(void*))
385 return set_transform(transform, old_transform);
389 STDMETHODIMP ProxyTransform::CreateCamera()
391 ICreateDevEnum* pCreateDevEnum = 0;
392 IEnumMoniker* pEnumMon = 0;
396 SafeRelease( m_SourceFilter );
398 if(FAILED(CoCreateInstance( CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
399 IID_ICreateDevEnum, (void**)&pCreateDevEnum )))
404 ASSERT(pCreateDevEnum);
405 /* Create capture device */
406 if(FAILED(pCreateDevEnum->CreateClassEnumerator(
407 CLSID_VideoInputDeviceCategory, &pEnumMon, 0)) || !pEnumMon)
409 SafeRelease(pCreateDevEnum);
414 if(SUCCEEDED( pEnumMon->Next(1, &pMon, &cFetched)) && cFetched == 1 && pMon)
417 pMon->BindToObject(0, 0, IID_IBaseFilter, (void **)&m_SourceFilter );
420 SafeRelease(pCreateDevEnum);
421 SafeRelease(pEnumMon);
425 m_SourceFilter->QueryFilterInfo(&info);
429 SafeRelease(pCreateDevEnum);
430 SafeRelease(pEnumMon);
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)))
438 SafeRelease(pCreateDevEnum);
439 SafeRelease(pEnumMon);
440 SafeRelease(m_SourceFilter);
446 SafeRelease( pEnumMon );
447 SafeRelease( pCreateDevEnum );
453 static IPin* get_pin( IBaseFilter* pFilter, PIN_DIRECTION dir )
455 IEnumPins* pEnumPins = 0;
460 pFilter->EnumPins( &pEnumPins );
466 PIN_DIRECTION pinDir = PIN_DIRECTION(-1);
469 pEnumPins->Next( 1, &pPin, &cFetched );
470 if( cFetched == 1 && pPin != 0 )
472 pPin->QueryDirection( &pinDir );
473 if( pinDir == dir ) break;
476 else if(cFetched == 0)
481 pEnumPins->Release();
489 STDMETHODIMP ProxyTransform::CreateFilterGraph()
492 if(FAILED(CoCreateInstance( CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
493 IID_IGraphBuilder, (void **)&m_GraphBuilder )))
495 SafeRelease(m_GraphBuilder);
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);
505 IBaseFilter* pProxyTrans = 0;
506 m_ProxyTrans->QueryInterface(IID_IBaseFilter, (void**)&pProxyTrans);
508 /* if( m_MediaEventEx )
510 // Have the graph signal event via window callbacks for performance
511 m_MediaEventEx->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0);
518 IPin* pSourceOut = get_pin( m_SourceFilter, PINDIR_OUTPUT );
520 IPin* pProxyTransIn = get_pin( pProxyTrans, PINDIR_INPUT );
521 IPin* pProxyTransOut = get_pin( pProxyTrans, PINDIR_OUTPUT );
523 if( pSourceOut && pProxyTransIn && pProxyTransOut )
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 );
530 pSourceOut->ConnectionMediaType(&amt);
531 pProxyTransOut->ConnectionMediaType(&amt);
532 VIDEOINFOHEADER* vih = (VIDEOINFOHEADER*)amt.pbFormat;
533 if(!vih || vih->bmiHeader.biBitCount != 24)
535 SafeRelease( pSourceOut );
536 SafeRelease( pProxyTransIn );
537 SafeRelease( pProxyTransOut );
542 SafeRelease( pSourceOut );
543 SafeRelease( pProxyTransIn );
544 SafeRelease( pProxyTransOut );
550 STDMETHODIMP ProxyTransform::InitGraph()
552 // Initialize DirectShow
554 if(CreateCamera() && CreateFilterGraph())
556 //Camera video source is available
568 STDMETHODIMP ProxyTransform::StopGraph()
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;
581 STDMETHODIMP ProxyTransform::StartGraph(HWND hWnd)
585 m_VideoWindow->put_Owner((OAHWND)hWnd);
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);
594 SetVideoWindowSize(hWnd);
595 m_MediaControl->Run();
596 m_isDSRunning = TRUE;
601 STDMETHODIMP ProxyTransform::SetVideoWindowSize(HWND hWnd)
604 GetVideoWindowSize(hWnd, &rc);
607 m_VideoWindow->SetWindowPosition( rc.left, rc.top, rc.right, rc.bottom );
612 STDMETHODIMP ProxyTransform::GetVideoWindowSize(HWND hWnd, RECT* rect)
614 RECT rc = {0, 0, 0, 0};
617 // int width, height;
618 // GetScaleFactor( width, height );
620 ::GetClientRect( hWnd, &rc );
622 // rc.right = rc.right * width / 100;
623 // rc.bottom = rc.bottom * height / 100;
634 // Sets the Param to the Default Value
636 //DEL STDMETHODIMP ProxyTransform::set_Default()
638 //DEL CAutoLock cAutoLock(&m_ProxyTransformLock);
639 //DEL m_lParam=m_lDefault ;
640 //DEL return NOERROR;
641 //DEL } // set_Default
651 // This is the sole member of ISpecifyPropertyPages
652 // Returns the clsid's of the property pages we support
655 STDMETHODIMP ProxyTransform::GetPages(CAUUID *pPages)
658 pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
659 if (pPages->pElems == NULL) {
660 return E_OUTOFMEMORY;
662 *(pPages->pElems) = CLSID_ProxyTransformPropertyPage;
672 // Handle registration of this filter
674 STDAPI DllRegisterServer()
676 return AMovieDllRegisterServer2( TRUE );
678 } // DllRegisterServer
682 // DllUnregisterServer
684 STDAPI DllUnregisterServer()
686 return AMovieDllRegisterServer2( FALSE );
688 } // DllUnregisterServer
691 int GetCameraList(CvCamera** cams)
696 for( int wIndex = 0; wIndex < 10; wIndex++ )
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)))
703 cameras[num].m_CaptureWindow = capCreateCaptureWindow( 0, 0, 0, 0, 1, 1, 0, 0);
704 if( capDriverConnect(cameras[num].m_CaptureWindow, wIndex))
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,
715 capSetUserData( cameras[num].m_CaptureWindow, (long)num );
716 capSetCallbackOnFrame( cameras[num].m_CaptureWindow, FrameCallbackProc );
723 if(cams) *cams = cameras;
729 int GetVideoFormat(int camera, BITMAPINFO* video_format, int size)
732 !cameras[camera].m_CaptureWindow ||
733 !cameras[camera].m_Caps.fHasDlgVideoSource) return 0;
734 return capGetVideoFormat(cameras[camera].m_CaptureWindow, video_format, size);
738 int SetVideoFormat(int camera, int width, int height, int format)
740 if(camera > num) return 0;
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);
759 static IProxyTransform* ProxyTrans = 0;
761 __declspec(dllexport) int Initialize()
764 if(FAILED(CoCreateInstance(CLSID_ProxyTransform, NULL, CLSCTX_INPROC_SERVER,
765 IID_IProxyTransform, (void**)&ProxyTrans)))
768 ProxyTrans->InitGraph();
773 __declspec(dllexport) int UnInitialize()
779 int VideoFormatDlg(int camera)
782 !cameras[camera].m_CaptureWindow ||
783 !cameras[camera].m_Caps.fHasDlgVideoFormat) return 0;
784 return capDlgVideoFormat( cameras[camera].m_CaptureWindow);
788 int VideoSourceDlg(int camera)
791 !cameras[camera].m_CaptureWindow ||
792 !cameras[camera].m_Caps.fHasDlgVideoSource) return 0;
793 return capDlgVideoSource( cameras[camera].m_CaptureWindow);
797 __declspec(dllexport) int RunCamera(int camera, HWND wnd)
799 if(ProxyTrans) return ProxyTrans->StartGraph(wnd);
804 __declspec(dllexport) int StopCamera(int camera)
806 if(ProxyTrans) return ProxyTrans->StopGraph();
811 __declspec(dllexport) int SetCallBack( int camera, void (*transform)(void*),
812 void (**old_transform)(void*) )
814 if(ProxyTrans) return ProxyTrans->SetCallBack(transform, old_transform);