The Machine Perception Toolbox

[Introduction]- [News]- [Download]- [Screenshots]- [Manual (pdf)]- [Forums]- [API Reference]- [Repository ]

 

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

MPBlinkDetectorFilter.cpp

Go to the documentation of this file.
00001 #include <streams.h>
00002 #include <initguid.h>
00003 #if (1100 > _MSC_VER)
00004 #include <olectlid.h>
00005 #else
00006 #include <olectl.h>
00007 #endif
00008 #include "DirectShow/MPUFilter_uids.h"
00009 #include "iMPBlinkDetectorFilter.h"
00010 #include "MPBlinkDetectorFilter.h"
00011 #include "resource.h"
00012 #include <ctime>
00013 
00014 // ================================================================
00015 
00016 // Setup information
00017 const AMOVIESETUP_MEDIATYPE sudPinTypes =
00018 {
00019         &MEDIATYPE_Video,      // Major type
00020                 &MEDIASUBTYPE_NULL      // Minor type
00021 };
00022 
00023 // ================================================================
00024 
00025 const AMOVIESETUP_PIN sudpPins[] =
00026 {
00027         { L"Input",            // Pins string name
00028                 FALSE,                // Is it rendered
00029                 FALSE,                // Is it an output
00030                 FALSE,                // Are we allowed none
00031                 FALSE,                // And allowed many
00032                 &CLSID_NULL,          // Connects to filter
00033                 NULL,                // Connects to pin
00034                 1,                    // Number of types
00035                 &sudPinTypes          // Pin information  
00036         },
00037         { L"Output",            // Pins string name
00038         FALSE,                // Is it rendered
00039         TRUE,                // Is it an output
00040         FALSE,                // Are we allowed none
00041         FALSE,                // And allowed many
00042         &CLSID_NULL,          // Connects to filter
00043         NULL,                // Connects to pin
00044         1,                    // Number of types
00045         &sudPinTypes          // Pin information
00046         }
00047 };
00048 
00049 // ================================================================
00050 
00051 const AMOVIESETUP_FILTER sudMPBlinkDetectorFilter =
00052 {
00053         &CLSID_MPBlinkDetectorFilter, // Filter CLSID
00054                 L"MPBlinkDetectorFilter",      // String name
00055                 MERIT_DO_NOT_USE,      // Filter merit
00056                 2,                      // Number of pins
00057                 sudpPins                // Pin information
00058 };
00059 
00060 // ================================================================
00061 
00062 // List of class IDs and creator functions for the class factory. This
00063 // provides the link between the OLE entry point in the DLL and an object
00064 // being created. The class factory will call the static CreateInstance
00065 CFactoryTemplate g_Templates[] = {
00066         { L"MPBlinkDetectorFilter"
00067                 , &CLSID_MPBlinkDetectorFilter
00068                 , MPBlinkDetectorFilter::CreateInstance
00069                 , NULL
00070                 , &sudMPBlinkDetectorFilter }
00071 };
00072 int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
00073 
00074 // ================================================================
00075 
00076 //
00077 // DllRegisterServer
00078 //
00079 // Handles sample registry and unregistry
00080 //
00081 STDAPI DllRegisterServer()
00082 {
00083         return AMovieDllRegisterServer2( TRUE );
00084         
00085 } // DllRegisterServer
00086 
00087 // ================================================================
00088 
00089 //
00090 // DllUnregisterServer
00091 //
00092 STDAPI DllUnregisterServer()
00093 {
00094         return AMovieDllRegisterServer2( FALSE );
00095 } // DllUnregisterServer
00096 
00097 // ================================================================
00098 
00099 //
00100 // Constructor
00101 //
00102 MPBlinkDetectorFilter::MPBlinkDetectorFilter(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr) 
00103 : CTransformFilter(tszName, punk, CLSID_MPBlinkDetectorFilter)
00104 , m_effect(IDC_RED)
00105 , m_lBufferRequest(1)
00106 , CPersistStream(punk, phr)
00107 {
00108         char sz[60];
00109         GetProfileStringA("Adaptability", "ResetInterval", "30.0", sz, 60);
00110         m_resetInterval = COARefTime(atof(sz));
00111         
00112         m_currentTime = COARefTime(0.0);     
00113         m_lastValidTime = COARefTime(0.0);
00114         
00116         
00117         srand( (unsigned)time( NULL ) );
00118 
00119 } // (Constructor)
00120 
00121 // ================================================================
00122 
00123 //
00124 // CreateInstance
00125 //
00126 // Provide the way for COM to create a MPBlinkDetectorFilter object
00127 //
00128 CUnknown *MPBlinkDetectorFilter::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
00129 {
00130         MPBlinkDetectorFilter *pNewObject = new MPBlinkDetectorFilter(NAME("Blink Detector MPLab"), punk, phr);
00131         if (pNewObject == NULL)
00132                 *phr = E_OUTOFMEMORY;
00133         return pNewObject;
00134 } // CreateInstance
00135 
00136 // ================================================================
00137 
00138 //
00139 // NonDelegatingQueryInterface
00140 //
00141 // Reveals IIPEffect and ISpecifyPropertyPages
00142 //
00143 STDMETHODIMP MPBlinkDetectorFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv)
00144 {
00145         CheckPointer(ppv,E_POINTER);
00146         return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
00147 } // NonDelegatingQueryInterface
00148 
00149 // ================================================================
00150 
00151 HRESULT MPBlinkDetectorFilter::StartStreaming(){
00152         return S_OK;
00153 }
00154 
00155 // ================================================================
00156 
00157 HRESULT MPBlinkDetectorFilter::StopStreaming(){
00158         return S_OK;
00159 }
00160 
00161 // ================================================================
00162 
00163 //
00164 // Transform
00165 //
00166 // Copy the input sample into the output sample - then transform the output
00167 // sample 'in place'. If we have all keyframes, then we shouldn't do a copy
00168 // If we have cinepak or indeo and are decompressing frame N it needs frame
00169 // decompressed frame N-1 available to calculate it, unless we are at a
00170 // keyframe. So with keyframed codecs, you can't get away with applying the
00171 // transform to change the frames in place, because you'll screw up the next
00172 // frames decompression. The runtime MPEG decoder does not have keyframes in
00173 // the same way so it can be done in place. We know if a sample is key frame
00174 // as we transform because the sync point property will be set on the sample
00175 //
00176 HRESULT MPBlinkDetectorFilter::Transform(IMediaSample *pIn, IMediaSample *pOut)
00177 {
00178         // Copy the properties across
00179         HRESULT hr = Copy(pIn, pOut);
00180         if (FAILED(hr)) {
00181                 return hr;
00182         }
00183         
00184         CRefTime temp;
00185         pIn->GetTime((REFERENCE_TIME *) &m_currentTime, (REFERENCE_TIME *)&temp);
00186         
00187         return Transform(pOut);
00188         
00189 } // Transform
00190 
00191 // ================================================================
00192 
00193 //
00194 // Copy
00195 //
00196 // Make destination an identical copy of source
00197 //
00198 HRESULT MPBlinkDetectorFilter::Copy(IMediaSample *pSource, IMediaSample *pDest)
00199 {
00200         // Copy the media type
00201         
00202         AM_MEDIA_TYPE *pmt;
00203         pSource->GetMediaType(&pmt);
00204         pDest->SetMediaType(pmt);
00205         DeleteMediaType(pmt);
00206         
00207         // Copy the sample data
00208 
00209         BYTE *pSourceBuffer, *pDestBuffer;
00210         long lSourceSize = pSource->GetActualDataLength();
00211         long lDestSize  = pDest->GetSize();
00212         
00213         ASSERT(lDestSize >= lSourceSize);
00214         
00215         pSource->GetPointer(&pSourceBuffer);
00216         pDest->GetPointer(&pDestBuffer);
00217 
00218         m_interface.printFrame((RGBTRIPLE*)pSourceBuffer, m_imgWidth, m_imgHeight);
00219         CopyMemory( (PVOID) pDestBuffer,(PVOID) pSourceBuffer,lSourceSize);
00220         
00221         // Copy the sample times
00222         
00223         REFERENCE_TIME TimeStart, TimeEnd;
00224         if (NOERROR == pSource->GetTime(&TimeStart, &TimeEnd)) {
00225                 pDest->SetTime(&TimeStart, &TimeEnd);
00226         }
00227         
00228         LONGLONG MediaStart, MediaEnd;
00229         if (pSource->GetMediaTime(&MediaStart,&MediaEnd) == NOERROR) {
00230                 pDest->SetMediaTime(&MediaStart,&MediaEnd);
00231         }
00232         
00233         // Copy the Sync point property
00234         
00235         HRESULT hr = pSource->IsSyncPoint();
00236         if (hr == S_OK) {
00237                 pDest->SetSyncPoint(TRUE);
00238         }
00239         else if (hr == S_FALSE) {
00240                 pDest->SetSyncPoint(FALSE);
00241         }
00242         else {  // an unexpected error has occured...
00243                 return E_UNEXPECTED;
00244         }
00245                 
00246         // Copy the preroll property
00247         
00248         hr = pSource->IsPreroll();
00249         if (hr == S_OK) {
00250                 pDest->SetPreroll(TRUE);
00251         }
00252         else if (hr == S_FALSE) {
00253                 pDest->SetPreroll(FALSE);
00254         }
00255         else {  // an unexpected error has occured...
00256                 return E_UNEXPECTED;
00257         }
00258         
00259         // Copy the discontinuity property
00260         hr = pSource->IsDiscontinuity();
00261         
00262         if (hr == S_OK)
00263                 pDest->SetDiscontinuity(TRUE);
00264         
00265         else if (hr == S_FALSE)
00266                 pDest->SetDiscontinuity(FALSE);
00267         
00268         else 
00269                 return E_UNEXPECTED; // an unexpected error has occured...
00270         
00271         // Copy the actual data length
00272         long lDataLength = pSource->GetActualDataLength();
00273         pDest->SetActualDataLength(lDataLength);
00274         
00275         return NOERROR;
00276 } // Copy
00277 
00278 // ================================================================
00279 
00280 // Implements face detector -- all the dirty details in here and helperfunctions.h
00281 HRESULT MPBlinkDetectorFilter::Transform(IMediaSample *pMediaSample)
00282 {
00283         AM_MEDIA_TYPE* pType = &m_pInput->CurrentMediaType();
00284         VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pType->pbFormat;
00285         
00286         BYTE *pData;                // Pointer to the actual image buffer
00287         pMediaSample->GetPointer(&pData);
00288 
00289         // Get the image properties from the BITMAPINFOHEADER
00290 
00291         m_imgWidth = pvi->bmiHeader.biWidth;
00292         m_imgHeight = pvi->bmiHeader.biHeight;
00293         
00294         m_interface.runInterface(pData, m_imgWidth, m_imgHeight); 
00295 
00297 // measure frame rate and output to file every 30 frames.
00298 // #define BENCHMARK
00299 #ifdef BENCHMARK
00300         const float alpha = .1f;
00301         static double avgtimeDiff = 60;
00302         static int count = 0;
00303         double curtimeDiff = m_currentTime.Millisecs() - m_lastValidTime.Millisecs();
00304         avgtimeDiff = curtimeDiff * alpha + avgtimeDiff * (1-alpha);
00305         if (count++ % 30 == 0) {
00306                 FILE *fid = fopen("benchmark.txt", "a");
00307                 fprintf(fid, "%.2f\n", 1000.0/avgtimeDiff);
00308                 fclose(fid);
00309         }
00310 #endif
00311 
00312 
00313         m_lastValidTime = m_currentTime;
00314 
00315         return NOERROR;
00316 }
00317 
00318 // ================================================================
00319 
00320 // Check the input type is OK - return an error otherwise
00321 HRESULT MPBlinkDetectorFilter::CheckInputType(const CMediaType *mtIn)
00322 {
00323         // check this is a VIDEOINFOHEADER type
00324         if (*mtIn->FormatType() != FORMAT_VideoInfo)
00325                 return E_INVALIDARG;
00326         // Can we transform this type
00327         if (CanPerformMPBlinkDetectorFilter(mtIn)) 
00328                 return NOERROR;
00329         return E_FAIL;
00330 }
00331 
00332 // ================================================================
00333 
00334 //
00335 // Checktransform
00336 //
00337 // Check a transform can be done between these formats
00338 //
00339 HRESULT MPBlinkDetectorFilter::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
00340 {
00341         if (CanPerformMPBlinkDetectorFilter(mtIn)) {
00342                 if (*mtIn == *mtOut)
00343                         return NOERROR;   
00344         }
00345         return E_FAIL;
00346 } // CheckTransform
00347 
00348 // ================================================================
00349 
00350 //
00351 // DecideBufferSize
00352 //
00353 // Tell the output pin's allocator what size buffers we
00354 // require. Can only do this when the input is connected
00355 //
00356 HRESULT MPBlinkDetectorFilter::DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties)
00357 {
00358         // Is the input pin connected
00359         if (m_pInput->IsConnected() == FALSE)
00360                 return E_UNEXPECTED;
00361         ASSERT(pAlloc);
00362         ASSERT(pProperties);
00363         HRESULT hr = NOERROR;
00364         pProperties->cBuffers = 1;
00365         pProperties->cbBuffer = m_pInput->CurrentMediaType().GetSampleSize();
00366         ASSERT(pProperties->cbBuffer);
00367         // Ask the allocator to reserve us some sample memory, NOTE the function
00368         // can succeed (that is return NOERROR) but still not have allocated the
00369         // memory that we requested, so we must check we got whatever we wanted
00370         ALLOCATOR_PROPERTIES Actual;
00371         hr = pAlloc->SetProperties(pProperties,&Actual);
00372         if (FAILED(hr))
00373                 return hr;
00374         ASSERT( Actual.cBuffers == 1 );
00375         if (pProperties->cBuffers > Actual.cBuffers ||
00376                 pProperties->cbBuffer > Actual.cbBuffer) {
00377                 return E_FAIL;  
00378         }
00379         return NOERROR;
00380 } // DecideBufferSize
00381 
00382 // ================================================================
00383 
00384 //
00385 // GetMediaType
00386 //
00387 // I support one type, namely the type of the input pin
00388 // This type is only available if my input is connected
00389 //
00390 HRESULT MPBlinkDetectorFilter::GetMediaType(int iPosition, CMediaType *pMediaType)
00391 {
00392         // Is the input pin connected
00393         if (m_pInput->IsConnected() == FALSE) 
00394                 return E_UNEXPECTED;
00395         // This should never happen
00396         if (iPosition < 0) 
00397                 return E_INVALIDARG;
00398         // Do we have more items to offer
00399         if (iPosition > 0)
00400                 return VFW_S_NO_MORE_ITEMS;
00401         *pMediaType = m_pInput->CurrentMediaType();
00402         return NOERROR;
00403 } // GetMediaType
00404 
00405 // ================================================================
00406 
00407 //
00408 // CanPerformMPBlinkDetectorFilter
00409 //
00410 // Check if this is a RGB24 true colour format
00411 //
00412 BOOL MPBlinkDetectorFilter::CanPerformMPBlinkDetectorFilter(const CMediaType *pMediaType) const
00413 {
00414         if (IsEqualGUID(*pMediaType->Type(), MEDIATYPE_Video)) {
00415                 if (IsEqualGUID(*pMediaType->Subtype(), MEDIASUBTYPE_RGB24)) {
00416                         VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pMediaType->Format();
00417                         return (pvi->bmiHeader.biBitCount == 24);
00418                 } 
00419         }
00420         return FALSE;
00421 } // CanPerformMPBlinkDetectorFilter
00422 
00423 // ================================================================
00424 
00425 #define WRITEOUT(var) hr = pStream->Write(&var, sizeof(var), NULL); \
00426 if (FAILED(hr)) return hr;
00427 
00428 #define READIN(var)   hr = pStream->Read(&var, sizeof(var), NULL); \
00429 if (FAILED(hr)) return hr;
00430 
00431 // ================================================================
00432 
00433 //
00434 // GetClassID
00435 //
00436 // This is the only method of IPersist
00437 //
00438 STDMETHODIMP MPBlinkDetectorFilter::GetClassID(CLSID *pClsid)
00439 {
00440         return CBaseFilter::GetClassID(pClsid);
00441 } // GetClassID
00442 
00443 // ================================================================
00444 
00445 //
00446 // ScribbleToStream
00447 //
00448 // Overriden to write our state into a stream
00449 //
00450 HRESULT MPBlinkDetectorFilter::ScribbleToStream(IStream *pStream)
00451 {
00452         HRESULT hr;
00453         WRITEOUT(m_effect);
00454         return NOERROR;
00455 } // ScribbleToStream
00456 
00457 // ================================================================
00458 
00459 //
00460 // ReadFromStream
00461 //
00462 // Likewise overriden to restore our state from a stream
00463 //
00464 HRESULT MPBlinkDetectorFilter::ReadFromStream(IStream *pStream)
00465 {
00466         HRESULT hr;
00467         READIN(m_effect);
00468         return NOERROR;
00469 } // ReadFromStream
00470 
00471 // ================================================================
00472 
00473 MPBlinkDetectorFilter::~MPBlinkDetectorFilter() {}
00474 
00475 // ================================================================

Generated on Mon Nov 8 17:07:42 2004 for MPT by  doxygen 1.3.9.1