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

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

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