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.
44 #include <cvstreams.h>
47 #include "syncfilter.h"
48 #include "syncfilteruids.h"
49 #include "isyncfilter.h"
51 const AMOVIESETUP_MEDIATYPE sudPinTypes =
53 &MEDIATYPE_Video, // major type
54 &MEDIASUBTYPE_NULL // minor type
57 const AMOVIESETUP_PIN sudpPins[] =
60 L"Input1", // String pin name
61 FALSE, // Is it rendered
62 FALSE, // Is it an output
63 FALSE, // Allowed none
64 FALSE, // Allowed many
65 &CLSID_NULL, // Connects to filter
66 L"Output1", // Connects to pin
68 &sudPinTypes // The pin details
71 L"Input2", // String pin name
72 FALSE, // Is it rendered
73 FALSE, // Is it an output
74 FALSE, // Allowed none
75 FALSE, // Allowed many
76 &CLSID_NULL, // Connects to filter
77 L"Output2", // Connects to pin
79 &sudPinTypes // The pin details
82 L"Input3", // String pin name
83 FALSE, // Is it rendered
84 FALSE, // Is it an output
85 FALSE, // Allowed none
86 FALSE, // Allowed many
87 &CLSID_NULL, // Connects to filter
88 L"Output3", // Connects to pin
90 &sudPinTypes // The pin details
93 L"Input4", // String pin name
94 FALSE, // Is it rendered
95 FALSE, // Is it an output
96 FALSE, // Allowed none
97 FALSE, // Allowed many
98 &CLSID_NULL, // Connects to filter
99 L"Output4", // Connects to pin
100 1, // Number of types
101 &sudPinTypes // The pin details
105 L"Output1", // String pin name
106 TRUE, // Is it rendered
107 TRUE, // Is it an output
108 FALSE, // Allowed none
109 FALSE, // Allowed many
110 &CLSID_NULL, // Connects to filter
111 L"Input1", // Connects to pin
112 1, // Number of types
113 &sudPinTypes // The pin details
116 L"Output2", // String pin name
117 TRUE, // Is it rendered
118 TRUE, // Is it an output
119 FALSE, // Allowed none
120 FALSE, // Allowed many
121 &CLSID_NULL, // Connects to filter
122 L"Input2", // Connects to pin
123 1, // Number of types
124 &sudPinTypes // The pin details
127 L"Output3", // String pin name
128 TRUE, // Is it rendered
129 TRUE, // Is it an output
130 FALSE, // Allowed none
131 FALSE, // Allowed many
132 &CLSID_NULL, // Connects to filter
133 L"Input3", // Connects to pin
134 1, // Number of types
135 &sudPinTypes // The pin details
138 L"Output4", // String pin name
139 TRUE, // Is it rendered
140 TRUE, // Is it an output
141 FALSE, // Allowed none
142 FALSE, // Allowed many
143 &CLSID_NULL, // Connects to filter
144 L"Input4", // Connects to pin
145 1, // Number of types
146 &sudPinTypes // The pin details
150 const AMOVIESETUP_FILTER sudMyFilter =
152 &CLSID_SyncFilter // clsID
153 , L"VideoSync Extended Filter for OpenCV" // strName
154 , MERIT_DO_NOT_USE // dwMerit
159 SyncFilter::SyncFilter(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr)
160 :m_csFilter(), CBaseFilter(tszName, punk, &m_csFilter, CLSID_SyncFilter), m_NbConnected(0), m_callback2(NULL), m_callback3(NULL), m_callback4(NULL)
162 m_ip[0] = new cvSyncInputPin(NAME ( "1-st input pin"),
167 m_ip[1] = new cvSyncInputPin(NAME ( "2-nd input pin"),
172 m_ip[2] = new cvSyncInputPin(NAME ( "3-rd input pin"),
177 m_ip[3] = new cvSyncInputPin(NAME ( "4-th input pin"),
183 m_op[0] = new cvSyncOutputPin(NAME("1-st output pin"),
188 m_op[1] = new cvSyncOutputPin(NAME("2-nd output pin"),
193 m_op[2] = new cvSyncOutputPin(NAME("3-rd output pin"),
198 m_op[3] = new cvSyncOutputPin(NAME("4-th output pin"),
204 for (int i=0;i<4;i++)
206 m_ip[i]->m_op = m_op[i];
207 m_op[i]->m_ip = m_ip[i];
211 CUnknown * WINAPI SyncFilter::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
213 SyncFilter *pNewObject = new SyncFilter(NAME("VideoSync Extended Filter for OpenCV"), punk, phr );
215 if (pNewObject == NULL)
217 *phr = E_OUTOFMEMORY;
223 int SyncFilter::GetPinCount(void)
228 CBasePin* SyncFilter::GetPin(int n)
250 HRESULT cvSyncOutputPin::CheckMediaType(const CMediaType* pmt)
252 // Check this is a VIDEOINFO type
254 if (*pmt->FormatType() != FORMAT_VideoInfo)
259 VIDEOINFO* vi = (VIDEOINFO*)pmt->Format();
260 if(vi->bmiHeader.biBitCount != 24)
268 CFactoryTemplate g_Templates[]=
273 , SyncFilter::CreateInstance // function called by class factory
275 , &sudMyFilter } // address of the AMOVIESETUP_FILTER structure,
276 // or NULL if no structure exists
279 int g_cTemplates = sizeof(g_Templates)/sizeof(g_Templates[0]);
284 // Handle registration of this filter
286 STDAPI DllRegisterServer()
288 return AMovieDllRegisterServer2( TRUE );
290 } // DllRegisterServer
293 // DllUnregisterServer
295 STDAPI DllUnregisterServer()
297 return AMovieDllRegisterServer2( FALSE );
299 } // DllUnregisterServer
301 SyncFilter::~SyncFilter()
303 for (int i=0;i<4;i++)
310 HRESULT cvSyncInputPin::BeginFlush()
312 CAutoLock lock_it(m_pLock);
313 HRESULT hr = NOERROR;
314 hr = m_op->DeliverBeginFlush();
318 return CBaseInputPin::BeginFlush();
321 HRESULT cvSyncInputPin::BreakConnect()
323 // Release any allocator that we are holding
327 m_pAllocator->Release();
335 HRESULT cvSyncInputPin::CompleteConnect(IPin *pReceivePin)
337 HRESULT hr = CBaseInputPin::CompleteConnect(pReceivePin);
344 if (m_op->m_Connected != NULL)
346 if (m_mt != m_op->m_mt)
347 m_pFilter->ReconnectPin(m_op, &m_mt);
354 m_Connected->QueryInterface(IID_IAMStreamConfig,(void**)&m_pVSC);
356 if(!(m_pVSC.is_valid()))
362 HRESULT cvSyncInputPin::EndFlush()
364 CAutoLock lock_it(m_pLock);
365 HRESULT hr = NOERROR;
366 hr = m_op->DeliverEndFlush();
370 return CBaseInputPin::EndFlush();
373 HRESULT cvSyncInputPin::EndOfStream()
375 CAutoLock lock_it(m_pLock);
376 HRESULT hr = NOERROR;
378 hr = m_op->DeliverEndOfStream();
385 HRESULT cvSyncInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
387 CAutoLock lock_it(m_pLock);
388 HRESULT hr = NOERROR;
389 hr = m_op->DeliverNewSegment(tStart, tStop, dRate);
392 return CBaseInputPin::NewSegment(tStart, tStop, dRate);
395 STDMETHODIMP cvSyncInputPin::Receive(IMediaSample *pSample)
397 CAutoLock lock_it(m_pLock);
399 // Check that all is well with the base class
401 if(m_pSample.value() == NULL)
407 HRESULT hr = NOERROR;
409 hr = CBaseInputPin::Receive(pSample);
414 m_pFilter->Receive();
419 STDMETHODIMP cvSyncInputPin::NotifyAllocator(IMemAllocator *pAllocator, BOOL bReadOnly)
421 CAutoLock lock_it(m_pLock);
422 if (pAllocator == NULL)
425 // Free the old allocator if any
428 m_pAllocator->Release();
432 // Store away the new allocator
434 pAllocator->AddRef();
435 m_pAllocator = pAllocator;
437 // Notify the base class about the allocator
438 return CBaseInputPin::NotifyAllocator(pAllocator,bReadOnly);
441 HRESULT cvSyncOutputPin::Active()
443 CAutoLock lock_it(m_pLock);
444 //CAutoLock lock_it_to(m_ip->m_pFilter->m_pLock);
445 HRESULT hr = NOERROR;
447 // Make sure that the pin is connected
448 if (m_Connected == NULL)
451 // Create the output queue if we have to
452 if ((!(HIWORD(m_pOutputQueue))||(LOWORD(m_pOutputQueue))))
455 m_pOutputQueue = new COutputQueue(m_Connected, &hr, TRUE, FALSE);
456 if (m_pOutputQueue == NULL)
457 return E_OUTOFMEMORY;
459 // Make sure that the constructor did not return any error
462 delete m_pOutputQueue;
463 m_pOutputQueue = NULL;
468 // Pass the call on to the base class
469 CBaseOutputPin::Active();
473 HRESULT cvSyncOutputPin::CompleteConnect(IPin *pReceivePin)
475 CAutoLock lock_it(m_pLock);
476 ASSERT(m_Connected == pReceivePin);
477 HRESULT hr = NOERROR;
479 hr = CBaseOutputPin::CompleteConnect(pReceivePin);
483 // If the type is not the same as that stored for the input
484 // pin then force the input pins peer to be reconnected
486 if (m_mt != m_ip->m_mt)
488 hr = m_ip->m_pFilter->ReconnectPin(m_ip->m_Connected, &m_mt);
499 HRESULT cvSyncOutputPin::DecideAllocator(IMemInputPin *pPin, IMemAllocator **ppAlloc)
503 // Tell the pin about our allocator, set by the input pin.
504 HRESULT hr = NOERROR;
505 hr = pPin->NotifyAllocator(m_ip->m_pAllocator,FALSE);
509 // Return the allocator
510 *ppAlloc = m_ip->m_pAllocator;
511 m_ip->m_pAllocator->AddRef();
515 HRESULT cvSyncOutputPin::Deliver(IMediaSample *pMediaSample)
517 CAutoLock lock_it(m_pLock);
518 pMediaSample->AddRef();
520 // Make sure that we have an output queue
521 if (!((HIWORD(m_pOutputQueue))&&(LOWORD(m_pOutputQueue))))
523 //MessageBox(NULL,"we have queue","", MB_OK);
525 HRESULT hr =m_pOutputQueue->Receive(pMediaSample);
530 HRESULT cvSyncOutputPin::DeliverBeginFlush()
532 // Make sure that we have an output queue
533 if (!((HIWORD(m_pOutputQueue))&&(LOWORD(m_pOutputQueue))))
536 m_pOutputQueue->BeginFlush();
540 HRESULT cvSyncOutputPin::DeliverNewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
542 // Make sure that we have an output queue
543 if (!((HIWORD(m_pOutputQueue))&&(LOWORD(m_pOutputQueue))))
546 m_pOutputQueue->NewSegment(tStart, tStop, dRate);
550 HRESULT cvSyncOutputPin::SetMediaType(const CMediaType *pmt)
552 // Make sure that we have an input connected
553 if (m_ip->m_Connected == NULL)
554 return VFW_E_NOT_CONNECTED;
556 // Make sure that the base class likes it
557 HRESULT hr = NOERROR;
558 hr = CBaseOutputPin::SetMediaType(pmt);
565 STDMETHODIMP cvSyncOutputPin::EnumMediaTypes(IEnumMediaTypes **ppEnum)
567 CAutoLock lock_it(m_pLock);
570 // Make sure that we are connected
571 if (m_ip->m_Connected == NULL)
572 return VFW_E_NOT_CONNECTED;
574 // We will simply return the enumerator of our input pin's peer
575 return m_ip->m_Connected->EnumMediaTypes(ppEnum);
579 HRESULT cvSyncOutputPin::DeliverEndFlush()
581 // Make sure that we have an output queue
582 if (!((HIWORD(m_pOutputQueue))&&(LOWORD(m_pOutputQueue))))
585 m_pOutputQueue->EndFlush();
589 HRESULT cvSyncOutputPin::DeliverEndOfStream()
591 // Make sure that we have an output queue
592 if (!((HIWORD(m_pOutputQueue))&&(LOWORD(m_pOutputQueue))))
595 m_pOutputQueue->EOS();
600 HRESULT cvSyncOutputPin::Inactive()
602 CAutoLock lock_it(m_pLock);
603 //CAutoLock lock_it_to(m_ip->m_pFilter->m_pLock);
605 // Delete the output queus associated with the pin.
606 if ((HIWORD(m_pOutputQueue))&&(LOWORD(m_pOutputQueue)))
608 //m_pOutputQueue->FreeSamples();
610 delete m_pOutputQueue;
611 m_pOutputQueue = NULL;
614 CBaseOutputPin::Inactive();
619 cvSyncInputPin::~cvSyncInputPin()
624 HRESULT SyncFilter::Receive()
626 CAutoLock lock_it(m_pLock);
627 REFERENCE_TIME te[4], ts[4]; //timestamps
628 static REFERENCE_TIME MediaTime1, MediaTime2 = 1;
629 IMediaSample *pims[4];
630 HRESULT hr = NOERROR;
633 for (i=0;i<m_NbConnected;i++)
634 if(!m_ip[i]->m_pSample.is_valid())
637 for (i=0;i<m_NbConnected;i++)
639 hr = m_ip[i]->m_pSample->GetTime(&ts[i], &te[i]);
643 m_ip[i]->m_pSample=NULL;
648 for (i=0;i<m_NbConnected;i++)
650 hr = m_ip[i]->m_pSample->SetMediaTime(&MediaTime1,&MediaTime2);
653 m_ip[i]->m_pSample=NULL;
658 for (i=0;i<m_NbConnected;i++)
659 pims[i]=m_ip[i]->m_pSample.value();
662 for (i=0;i<m_NbConnected;i++)
664 hr = m_op[i]->Deliver(m_ip[i]->m_pSample.value());
666 m_ip[i]->m_pSample = NULL;
672 for (i=0;i<m_NbConnected;i++)
673 m_ip[i]->m_pSample = NULL;
678 STDMETHODIMP SyncFilter::Stop()
680 CAutoLock lock_it(m_pLock);
683 m_State = State_Stopped;
688 STDMETHODIMP SyncFilter::Pause()
690 CAutoLock cObjectLock(m_pLock);
691 HRESULT hr = CBaseFilter::Pause();
692 bool NotConnected=false;
695 for (i=0;i<m_NbConnected;i++)
696 if (m_ip[i]->IsConnected() == FALSE)
703 for (i=0;i<m_NbConnected;i++)
704 m_ip[0]->EndOfStream();
706 for (i=0;i<m_NbConnected;i++)
707 m_ip[i]->m_pSample = NULL;
712 STDMETHODIMP SyncFilter::Run(REFERENCE_TIME tStart)
714 CAutoLock cObjectLock(m_pLock);
715 HRESULT hr = CBaseFilter::Run(tStart);
716 bool NotConnected=false;
719 for (i=0;i<m_NbConnected;i++)
720 if (m_ip[i]->IsConnected() == FALSE)
727 for (i=0;i<m_NbConnected;i++)
728 m_ip[0]->EndOfStream();
733 HRESULT cvSyncInputPin::Inactive()
737 return CBaseInputPin::Inactive();
740 STDMETHODIMP SyncFilter::SetCallBack(void (__cdecl *func)(void *,void *))
742 return SetCallBack2(func);
745 STDMETHODIMP SyncFilter::SetCallBack2(void (__cdecl *func)(void *,void *))
752 STDMETHODIMP SyncFilter::SetCallBack3(void (__cdecl *func)(void *,void *,void *))
759 STDMETHODIMP SyncFilter::SetCallBack4(void (__cdecl *func)(void *,void *,void *,void *))
766 STDMETHODIMP SyncFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv)
768 CheckPointer(ppv,E_POINTER);
770 if (riid == IID_ISyncFilter)
772 return GetInterface((ISyncFilter *) this, ppv);
776 return CBaseFilter::NonDelegatingQueryInterface(riid, ppv);
780 HRESULT SyncFilter::Transform(IMediaSample *pims[4])
784 AM_MEDIA_TYPE* pType[4];
785 VIDEOINFOHEADER *pvi[4];
790 for (int i=0;i<m_NbConnected;i++)
792 pims[i]->GetPointer(&pData[i]);
793 pType[i] = &m_ip[i]->m_mt;
794 pvi[i] = (VIDEOINFOHEADER *) pType[i]->pbFormat;
796 if (pvi[i]->bmiHeader.biBitCount != 24)
799 cxImage[i] = pvi[i]->bmiHeader.biWidth;
800 cyImage[i] = abs(pvi[i]->bmiHeader.biHeight);
801 stride[i] = (cxImage[i] * sizeof( RGBTRIPLE ) + 3) & -4;
803 cvInitImageHeader( &image[i], cvSize(cxImage[i], cyImage[i]), 8, 3, IPL_ORIGIN_BL, 4 );
804 image[i].widthStep = stride[i];
806 cvSetImageData( &image[i], pData[i], stride[i] );
809 if (2==m_NbConnected)
810 m_callback2(&image[0], &image[1]);
811 else if (3==m_NbConnected)
812 m_callback3(&image[0], &image[1], &image[2]);
813 else if (4==m_NbConnected)
814 m_callback4(&image[0], &image[1], &image[2], &image[3]);