HandVuFilter.cpp
上传用户:lijia5631
上传日期:2008-11-10
资源大小:1214k
文件大小:22k
源码类别:

视频捕捉/采集

开发平台:

MultiPlatform

  1. /**   * HandVu - a library for computer vision-based hand gesture   * recognition.   * Copyright (C) 2004 Mathias Kolsch, matz@cs.ucsb.edu   *   * This program is free software; you can redistribute it and/or   * modify it under the terms of the GNU General Public License   * as published by the Free Software Foundation; either version 2   * of the License, or (at your option) any later version.   *   * This program is distributed in the hope that it will be useful,   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   * GNU General Public License for more details.   *   * You should have received a copy of the GNU General Public License   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330,    * Boston, MA  02111-1307, USA.   *   * $Id: HandVuFilter.cpp,v 1.22 2005/10/30 23:00:43 matz Exp $ **/ #include "StdAfx.h"
  2. #include <initguid.h>
  3. #if (1100 > _MSC_VER)
  4. #include <olectlid.h>
  5. #else
  6. #include <olectl.h>
  7. #endif
  8. //#define USE_FDL
  9. #include "HandVuFilterGUIDs.h"
  10. #include "Common.h"
  11. #include "HandVuFilter.h"
  12. #include "HandVuFilterProp.h"
  13. #include "MaintenanceApp.h"
  14. #ifdef USE_FDL
  15. #include "FrameDataLib.h"
  16. #endif USE_FDL
  17. #ifdef HAVE_USER_STUDY
  18. #include "../hv_UserStudy/UserStudyA.h"
  19. #include "../hv_UserStudy/UserStudyB.h"
  20. #endif HAVE_USER_STUDY
  21. #include "HandVu.h"
  22. // wrong #define causes a warning in ipl.h ... annoying:
  23. //#undef _VXWORKS
  24. #include <CV.h>
  25. #include "resource.h"
  26. #ifndef M_PI
  27. #define M_PI 3.141592653589793
  28. #endif /* M_PI */
  29. // Setup information
  30. const AMOVIESETUP_MEDIATYPE sudPinTypes =
  31.   {
  32.     &MEDIATYPE_Video,       // Major type
  33.     &MEDIASUBTYPE_NULL      // Minor type
  34.   };
  35. const AMOVIESETUP_PIN sudpPins[] =
  36.   {
  37.     { L"Input",             // Pins string name
  38.       FALSE,                // Is it rendered
  39.       FALSE,                // Is it an output
  40.       FALSE,                // Are we allowed none
  41.       FALSE,                // And allowed many
  42.       &CLSID_NULL,          // Connects to filter
  43.       NULL,                 // Connects to pin
  44.       1,                    // Number of types
  45.       &sudPinTypes          // Pin information
  46.     },
  47.     { L"Output",            // Pins string name
  48.       FALSE,                // Is it rendered
  49.       TRUE,                 // Is it an output
  50.       FALSE,                // Are we allowed none
  51.       FALSE,                // And allowed many
  52.       &CLSID_NULL,          // Connects to filter
  53.       NULL,                 // Connects to pin
  54.       1,                    // Number of types
  55.       &sudPinTypes          // Pin information
  56.     }
  57.   };
  58. const AMOVIESETUP_FILTER sudHandVuFilter =
  59.   {
  60.     &CLSID_HandVuFilter,         // Filter CLSID
  61.     L"HandVuFilter",         // String name
  62.     MERIT_DO_NOT_USE,       // Filter merit
  63.     2,                      // Number of pins
  64.     sudpPins                // Pin information
  65.   };
  66. // List of class IDs and creator functions for the class factory. This
  67. // provides the link between the OLE entry point in the DLL and an object
  68. // being created. The class factory will call the static CreateInstance
  69. CFactoryTemplate g_Templates[] = {
  70.   { L"HandVuFilter (Filter)"
  71.     , &CLSID_HandVuFilter
  72.     , CHandVuFilter::CreateInstance
  73.     , NULL
  74.     , &sudHandVuFilter }
  75.   ,
  76.   { L"HandVuFilter (Property Page)"
  77.     , &CLSID_HandVuFilterPropertyPage
  78.     , CHandVuFilterProperties::CreateInstance }
  79. };
  80. int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
  81. //
  82. // DllRegisterServer
  83. //
  84. // Handles sample registry and unregistry
  85. //
  86. STDAPI DllRegisterServer()
  87. {
  88.   return AMovieDllRegisterServer2( TRUE );
  89. } // DllRegisterServer
  90. //
  91. // DllUnregisterServer
  92. //
  93. STDAPI DllUnregisterServer()
  94. {
  95.   return AMovieDllRegisterServer2( FALSE );
  96. } // DllUnregisterServer
  97. //
  98. // Constructor
  99. //
  100. CHandVuFilter::CHandVuFilter(TCHAR *tszName,
  101.                                LPUNKNOWN punk,
  102.                                HRESULT *phr,
  103.                                bool bModifiesData /* = true */)
  104. : CTransInPlaceFilter(tszName, punk, CLSID_HandVuFilter, phr, bModifiesData),
  105.   m_img_bottom_up(false),
  106.   m_cxImage(-1),
  107.   m_cyImage(-1),
  108.   m_show_maintenanceapp(false),
  109.   m_FDL_only(false),
  110.   m_take_one_snapshot(false),
  111.   m_is_initialized(false),
  112.   m_FDL_is_initialized(false),
  113.   m_pColorHeader(NULL),
  114.   m_pOverlay(NULL),
  115. #ifdef HAVE_USER_STUDY
  116.   m_pUserStudyA(NULL),
  117.   m_pUserStudyB(NULL),
  118. #endif
  119.   CPersistStream(punk, phr)
  120. {
  121.   string root_dir("C:\hv_tmp");
  122.   _mkdir(root_dir.c_str());
  123.   string fname_root(root_dir + "\hvsnap_");   hvSetSaveFilenameRoot(fname_root);
  124.   m_params.immediate_apply = true;
  125.   // debugging:
  126.   DbgSetModuleLevel(LOG_CUSTOM1, 3);
  127. } // (Constructor)
  128. CHandVuFilter::~CHandVuFilter()
  129. {
  130.   hvUninitialize();
  131. }
  132. //
  133. // CreateInstance
  134. //
  135. // Provide the way for COM to create a HandVuFilter object
  136. //
  137. CUnknown *CHandVuFilter::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
  138. {
  139.   CHandVuFilter *pNewObject =
  140.     new CHandVuFilter(NAME("HandVuFilter"), punk, phr);
  141.   if (pNewObject == NULL) {
  142.     *phr = E_OUTOFMEMORY;
  143.   }
  144.   return pNewObject;
  145. } // CreateInstance
  146. //
  147. // NonDelegatingQueryInterface
  148. //
  149. // Reveals IHandVuFilter and ISpecifyPropertyPages
  150. //
  151. STDMETHODIMP CHandVuFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv)
  152. {
  153.   CheckPointer(ppv,E_POINTER);
  154.   if (riid == IID_IHandVuFilter) {
  155.     return GetInterface((IHandVuFilter *) this, ppv);
  156.   } else if (riid == IID_ISpecifyPropertyPages) {
  157.     return GetInterface((ISpecifyPropertyPages *) this, ppv);
  158.   } else {
  159.     return CTransInPlaceFilter::NonDelegatingQueryInterface(riid, ppv);
  160.   }
  161. } // NonDelegatingQueryInterface
  162. //
  163. // Transform (in place)
  164. //
  165. HRESULT CHandVuFilter::Transform(IMediaSample *pMediaSample)
  166. {
  167. #if 0
  168.   static dropme = false;
  169.   if (dropme) {
  170.     dropme = false;
  171.     m_bSampleSkipped = true;
  172.     return S_FALSE;
  173.   } else {
  174.     dropme = true;
  175.   }
  176. #endif //0 
  177.   CAutoLock lock(&m_HandVuFilterLock);
  178.   AM_MEDIA_TYPE* pType = &m_pInput->CurrentMediaType();
  179.   VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pType->pbFormat;
  180.   BYTE *pData;                // Pointer to the actual image buffer
  181.   long lDataLen;              // Holds length of any given sample
  182.   pMediaSample->GetPointer(&pData);
  183.   lDataLen = pMediaSample->GetSize();
  184.   m_bSampleSkipped = false;
  185.   if (!m_is_initialized) {
  186.     VERBOSE0(3, "HandVuFilter: init during playback");
  187.     // Get the image properties from the BITMAPINFOHEADER
  188.     int iPixelSize = pvi->bmiHeader.biBitCount / 8;
  189.     int width      = pvi->bmiHeader.biWidth;
  190.     int height     = pvi->bmiHeader.biHeight;
  191.     
  192.     HRESULT hr = Initialize(width, height, iPixelSize, NULL);
  193.     if (!SUCCEEDED(hr)) {
  194.       throw HVException("HandVuFilter: concurrent initialization");
  195.     }
  196.   }
  197.   { // test if change from initialization
  198.     int width      = pvi->bmiHeader.biWidth;
  199.     int height     = pvi->bmiHeader.biHeight;
  200.     bool img_bottom_up = true;
  201.     if (height<0) {
  202.       // norm for RGB images
  203.       img_bottom_up = false;
  204.       height = -height;
  205.     }
  206.     if (width!=m_cxImage || height!=m_cyImage || img_bottom_up!=m_img_bottom_up) {
  207.       VERBOSE0(1, "HandVuFilter: format changed!");
  208.       throw HVException("HandVuFilter: format changed!");
  209.     }
  210.   }
  211.   m_pColorHeader->imageData = (char*) pData;
  212.   m_pColorHeader->imageSize = lDataLen;
  213.   REFERENCE_TIME st_start, st_end;
  214.   pMediaSample->GetTime(&st_start, &st_end);
  215.   m_t_sample = st_start/10;
  216. #ifdef HAVE_USER_STUDY
  217.   // check DV input for marks
  218.   if (m_pUserStudyB) {
  219.     if (!m_pIAMTCReader) {
  220.       AfxMessageBox("need time code reader for StudyHV2");
  221.     } else {
  222.       m_pUserStudyB->AtTimecode(GetTimecode());
  223.     }
  224.   }
  225. #endif
  226.   if (m_img_bottom_up) {
  227.     cvMirror(m_pColorHeader, NULL, 0); // flip on horizontal axis
  228.   }
  229.   // ------- main library call ---------
  230.   VERBOSE0(5, "HandVuFilter: will process frame");   hvAction action = HV_INVALID_ACTION;
  231.   action = hvProcessFrame(m_pColorHeader);
  232.   VERBOSE0(5, "HandVuFilter: HandVu finished processing frame");   // -------
  233.   for (int i=0; i<(int)m_HVFListenerPtrs.size(); i++) {
  234.     m_HVFListenerPtrs[i]->FrameTransformed(action!=HV_DROP_FRAME);
  235.   }
  236.   if (action==HV_DROP_FRAME) {
  237.     // HandVu recommends dropping the frame entirely
  238. #ifdef HAVE_USER_STUDY
  239.     if (m_pUserStudyA) {
  240.       m_pUserStudyA->DontDraw(m_pColorHeader);
  241.     }
  242. #endif
  243.     m_bSampleSkipped = true;
  244.     VERBOSE0(3, "HandVuFilter: dropping frame");
  245.     return S_FALSE;
  246.   } else if (action==HV_SKIP_FRAME) {
  247.     // HandVu recommends displaying the frame, but not doing any further
  248.     // processing on it - keep going
  249.   } else if (action==HV_PROCESS_FRAME) {
  250.     // full processing was done and is recommended for following steps;
  251.     // keep going
  252.   } else {
  253.     ASSERT(0); // unknown action
  254.   }
  255.   if (m_show_maintenanceapp) {
  256.     ASSERT(m_pOverlay);
  257.     //
  258.     // overlay
  259.     //
  260.     hvState state;
  261.     hvGetState(0, state);     COverlayEvent event;
  262.     event.m_ptr1_tracked = state.tracked;
  263.     event.m_ptr1_recognized = state.recognized;
  264.     event.m_ptr1_x = state.center_xpos;
  265.     event.m_ptr1_y = state.center_ypos;
  266.     event.m_ptr1_type = state.posture;
  267.     m_pOverlay->Tracked(event);     m_pOverlay->Draw(m_pColorHeader);
  268.   }
  269. #ifdef HAVE_USER_STUDY
  270.   if (m_pUserStudyA) {
  271.     hvVState state;
  272.     hvGetState(0, state);     COverlayEvent event;
  273.     event.m_ptr1_tracked = state.tracked;
  274.     event.m_ptr1_recognized = state.recognized;
  275.     event.m_ptr1_x = state.center_xpos;
  276.     event.m_ptr1_y = state.center_ypos;
  277.     event.m_ptr1_type = state.posture;
  278.     m_pUserStudyA->Tracked(event);
  279.     m_pUserStudyA->Draw(m_pColorHeader);
  280.   }
  281.   if (m_pUserStudyB) {
  282.     hvState state;
  283.     hvGetState(0, state);     COverlayEvent event;
  284.     event.m_ptr1_tracked = state.tracked;
  285.     event.m_ptr1_recognized = state.recognized;
  286.     event.m_ptr1_x = state.center_xpos;
  287.     event.m_ptr1_y = state.center_ypos;
  288.     event.m_ptr1_type = state.posture;
  289.     m_pUserStudyB->Tracked(event);
  290.     m_pUserStudyB->Draw(m_pColorHeader);
  291.   }
  292. #endif
  293.   if (m_take_one_snapshot) {
  294.     m_take_one_snapshot = false;
  295.     SaveImageArea(m_pColorHeader);
  296.   }
  297. #ifdef USE_FDL
  298.   if (m_FDL_only && action==HV_PROCESS_FRAME) {
  299.     if (!m_FDL_is_initialized) {
  300.       int iPixelSize = pvi->bmiHeader.biBitCount / 8;
  301.       FDL_Initialize(m_cxImage, m_cyImage, iPixelSize);
  302.       m_FDL_is_initialized = true;
  303.     }
  304.     FDL_PutImage((BYTE*) m_pColorHeader->imageData);
  305.     m_bSampleSkipped = true;
  306.     VERBOSE0(4, "HandVuFilter: frame sent to FDL, no display");
  307.     return S_FALSE;
  308.   }
  309. #endif USE_FDL
  310.   if (m_img_bottom_up) {
  311.     cvMirror(m_pColorHeader, NULL, 0); // flip on horizontal axis
  312.   }
  313.   VERBOSE0(3, "HandVuFilter: processed frame");
  314.   return NOERROR;
  315. } // Transform (in place)
  316. RefTime CHandVuFilter::GetSampleTimeUsec() const
  317. {
  318.   return m_t_sample;
  319. }
  320. RefTime CHandVuFilter::GetCurrentTimeUsec() const
  321. {
  322.   if (m_tStart.m_time==0) {
  323.     return 0;
  324.   }
  325.   CRefTime t_curr;
  326.   ((CHandVuFilter*)this)->StreamTime(t_curr);
  327.   return t_curr.m_time/10;
  328. }
  329. // Check the input type is OK - return an error otherwise
  330. HRESULT CHandVuFilter::CheckInputType(const CMediaType *mtIn)
  331. {
  332.   // check this is a VIDEOINFOHEADER type
  333.   if (*mtIn->FormatType() != FORMAT_VideoInfo) {
  334.     return E_INVALIDARG;
  335.   }
  336.   // Can we transform this type
  337.   if (CanPerformHandVuFilter(mtIn)) {
  338.     return NOERROR;
  339.   }
  340.   return E_FAIL;
  341. }
  342. //
  343. // Checktransform
  344. //
  345. // Check a transform can be done between these formats
  346. //
  347. HRESULT CHandVuFilter::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
  348. {
  349.   if (CanPerformHandVuFilter(mtIn)) {
  350.     if (*mtIn == *mtOut) {
  351.       return NOERROR;
  352.     }
  353.   }
  354.   return E_FAIL;
  355. } // CheckTransform
  356. //
  357. // DecideBufferSize
  358. //
  359. // Tell the output pin's allocator what size buffers we
  360. // require. Can only do this when the input is connected
  361. //
  362. HRESULT CHandVuFilter::DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties)
  363. {
  364.   // Is the input pin connected
  365.   if (m_pInput->IsConnected() == FALSE) {
  366.     return E_UNEXPECTED;
  367.   }
  368.   ASSERT(pAlloc);
  369.   ASSERT(pProperties);
  370.   HRESULT hr = NOERROR;
  371.   pProperties->cBuffers = 1;
  372.   pProperties->cbBuffer = m_pInput->CurrentMediaType().GetSampleSize();
  373.   ASSERT(pProperties->cbBuffer);
  374.   // Ask the allocator to reserve us some sample memory, NOTE the function
  375.   // can succeed (that is return NOERROR) but still not have allocated the
  376.   // memory that we requested, so we must check we got whatever we wanted
  377.   ALLOCATOR_PROPERTIES Actual;
  378.   hr = pAlloc->SetProperties(pProperties,&Actual);
  379.   if (FAILED(hr)) {
  380.     return hr;
  381.   }
  382.   ASSERT( Actual.cBuffers == 1 );
  383.   if (pProperties->cBuffers > Actual.cBuffers ||
  384.       pProperties->cbBuffer > Actual.cbBuffer) {
  385.     return E_FAIL;
  386.   }
  387.   return NOERROR;
  388. } // DecideBufferSize
  389. //
  390. // GetMediaType
  391. //
  392. // I support one type, namely the type of the input pin
  393. // This type is only available if my input is connected
  394. //
  395. HRESULT CHandVuFilter::GetMediaType(int iPosition, CMediaType *pMediaType)
  396. {
  397.   // Is the input pin connected
  398.   if (m_pInput->IsConnected() == FALSE) {
  399.     return E_UNEXPECTED;
  400.   }
  401.   // This should never happen
  402.   if (iPosition < 0) {
  403.     return E_INVALIDARG;
  404.   }
  405.   // Do we have more items to offer
  406.   if (iPosition > 0) {
  407.     return VFW_S_NO_MORE_ITEMS;
  408.   }
  409.   *pMediaType = m_pInput->CurrentMediaType();
  410.   return NOERROR;
  411. } // GetMediaType
  412. //
  413. // CanPerformHandVuFilter
  414. //
  415. // Check if this is a RGB24 true colour format
  416. //
  417. BOOL CHandVuFilter::CanPerformHandVuFilter(const CMediaType *pMediaType) const
  418. {
  419.   if (IsEqualGUID(*pMediaType->Type(), MEDIATYPE_Video)) {
  420.     if (IsEqualGUID(*pMediaType->Subtype(), MEDIASUBTYPE_RGB24)) {
  421.       VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pMediaType->Format();
  422.       return (pvi->bmiHeader.biBitCount == 24);
  423.     }
  424.   }
  425.   return FALSE;
  426. } // CanPerformHandVuFilter
  427. #define WRITEOUT(var)  hr = pStream->Write(&var, sizeof(var), NULL); 
  428.        if (FAILED(hr)) return hr;
  429. #define READIN(var)    hr = pStream->Read(&var, sizeof(var), NULL); 
  430.        if (FAILED(hr)) return hr;
  431. //
  432. // GetClassID
  433. //
  434. // This is the only method of IPersist
  435. //
  436. STDMETHODIMP CHandVuFilter::GetClassID(CLSID *pClsid)
  437. {
  438.   return CBaseFilter::GetClassID(pClsid);
  439. } // GetClassID
  440. //
  441. // ScribbleToStream
  442. //
  443. // Overriden to write our state into a stream
  444. //
  445. HRESULT CHandVuFilter::ScribbleToStream(IStream *pStream)
  446. {
  447.   return NOERROR;
  448. } // ScribbleToStream
  449. //
  450. // ReadFromStream
  451. //
  452. // Likewise overriden to restore our state from a stream
  453. //
  454. HRESULT CHandVuFilter::ReadFromStream(IStream *pStream)
  455. {
  456.   return NOERROR;
  457. } // ReadFromStream
  458. //
  459. // GetPages
  460. //
  461. // Returns the clsid's of the property pages we support
  462. //
  463. STDMETHODIMP CHandVuFilter::GetPages(CAUUID *pPages)
  464. {
  465.   pPages->cElems = 1;
  466.   pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
  467.   if (pPages->pElems == NULL) {
  468.     return E_OUTOFMEMORY;
  469.   }
  470.   *(pPages->pElems) = CLSID_HandVuFilterPropertyPage;
  471.   return NOERROR;
  472. } // GetPages
  473. //
  474. // GetHandVuFilterParams
  475. //
  476. STDMETHODIMP
  477. CHandVuFilter::GetHandVuFilterParams(HandVuFilterParams& params) const
  478. {
  479.   CAutoLock cAutolock(&m_HandVuFilterLock);
  480.   params = m_params;
  481.   return NOERROR;
  482. } // GetHandVuFilterParams
  483. //
  484. // SetHandVuFilterParams
  485. //
  486. STDMETHODIMP
  487. CHandVuFilter::SetHandVuFilterParams(const HandVuFilterParams& params)
  488. {
  489.   CAutoLock cAutolock(&m_HandVuFilterLock);
  490.   m_params = params;
  491.   SetDirty(TRUE);
  492.   return NOERROR;
  493. } // SetHandVuFilterParams
  494. STDMETHODIMP CHandVuFilter::Initialize(int img_width, int img_height, int iPixelSize, CameraController* pCamCon)
  495. {
  496.   CAutoLock lock(&m_HandVuFilterLock);
  497.   if (m_is_initialized) {
  498.     return E_UNEXPECTED;
  499.   }
  500.   m_cxImage = img_width;
  501.   if (img_height<0) {
  502.     // norm for RGB images
  503.     m_img_bottom_up = false;
  504.     m_cyImage = -img_height;
  505.   } else {
  506.     m_img_bottom_up = true;
  507.     m_cyImage = img_height;
  508.   }
  509.   ASSERT(m_pColorHeader==NULL);
  510.   m_pColorHeader = cvCreateImageHeader(cvSize(m_cxImage, m_cyImage), IPL_DEPTH_8U, 3);
  511.   hvInitialize(m_cxImage, m_cyImage);
  512.   m_is_initialized = true;
  513.   return NOERROR;
  514. }
  515. STDMETHODIMP CHandVuFilter::LoadConductor(const string& filename)
  516. {
  517.   CAutoLock lock(&m_HandVuFilterLock);
  518.   hvLoadConductor(filename);
  519.   return NOERROR;
  520. }
  521. STDMETHODIMP CHandVuFilter::ConductorLoaded(bool* pLoaded)
  522. {
  523.   *pLoaded = hvConductorLoaded();
  524.   return NOERROR;
  525. }
  526. STDMETHODIMP CHandVuFilter::StartRecognition(int obj_id)
  527. {
  528.   CAutoLock lock(&m_HandVuFilterLock);
  529.   hvStartRecognition(obj_id);
  530.   return NOERROR;
  531. }
  532. STDMETHODIMP CHandVuFilter::StopRecognition(int obj_id)
  533. {
  534.   CAutoLock lock(&m_HandVuFilterLock);
  535.   hvStopRecognition(obj_id);
  536.   return NOERROR;
  537. }
  538. STDMETHODIMP CHandVuFilter::IsActive(bool* pActive)
  539. {
  540.   *pActive = hvIsActive();
  541.   return NOERROR;
  542. }
  543. STDMETHODIMP CHandVuFilter::GetState(int obj_id, hvState& state)
  544. {
  545.   hvGetState(obj_id, state);
  546.   return NOERROR;
  547. }
  548. STDMETHODIMP CHandVuFilter::SetOverlayLevel(int level)
  549. {
  550.   hvSetOverlayLevel(level);
  551.   return NOERROR;
  552. }
  553. STDMETHODIMP CHandVuFilter::GetOverlayLevel(int* pLevel)
  554. {
  555.   *pLevel = hvGetOverlayLevel();
  556.   return NOERROR;
  557. }
  558. STDMETHODIMP CHandVuFilter::CorrectDistortion(bool enable)
  559. {
  560.   hvCorrectDistortion(enable);
  561.   return NOERROR;
  562. }
  563. STDMETHODIMP CHandVuFilter::CanCorrectDistortion(bool* pPossible)
  564. {
  565.   *pPossible = hvCanCorrectDistortion();
  566.   return NOERROR;
  567. }
  568. STDMETHODIMP CHandVuFilter::IsCorrectingDistortion(bool* pOn)
  569. {
  570.   *pOn = hvIsCorrectingDistortion();
  571.   return NOERROR;
  572. }
  573. STDMETHODIMP CHandVuFilter::SetDetectionArea(int left, int top, int right, int bottom)
  574. {
  575.   hvSetDetectionArea(left, top, right, bottom);
  576.   return NOERROR;
  577. }
  578. STDMETHODIMP CHandVuFilter::RecomputeNormalLatency()
  579. {
  580.   hvRecomputeNormalLatency();
  581.   return NOERROR;
  582. }
  583. STDMETHODIMP CHandVuFilter::SetAdjustExposure(bool enable)
  584. {
  585.   hvSetAdjustExposure(enable);
  586.   return NOERROR;
  587. }
  588. STDMETHODIMP CHandVuFilter::CanAdjustExposure(bool* pPossible)
  589. {
  590.   *pPossible = hvCanAdjustExposure();
  591.   return NOERROR;
  592. }
  593. STDMETHODIMP CHandVuFilter::IsAdjustingExposure(bool* pEnabled)
  594. {
  595.   *pEnabled = hvIsAdjustingExposure();
  596.   return NOERROR;
  597. }
  598. STDMETHODIMP CHandVuFilter::AddListener(HVFilterEventListener* pHVFListener)
  599. {
  600.   CAutoLock lock(&m_HandVuFilterLock);
  601.   m_HVFListenerPtrs.push_back(pHVFListener);
  602.   return NOERROR;
  603. }
  604. STDMETHODIMP CHandVuFilter::RemoveListener(HVFilterEventListener* pHVFListener)
  605. {
  606.   CAutoLock lock(&m_HandVuFilterLock);
  607.   bool found = false;
  608.   int old_size = (int)m_HVFListenerPtrs.size();
  609.   for (int i=0; i<old_size; i++) {
  610.     if (m_HVFListenerPtrs[i]==pHVFListener) {
  611.       found = true;
  612.     }
  613.     if (found && i+1<old_size) {
  614.       m_HVFListenerPtrs[i] = m_HVFListenerPtrs[i+1];
  615.     }
  616.   }
  617.   if (found) {
  618.     m_HVFListenerPtrs.resize(old_size-1);
  619.     return NOERROR;
  620.   } else {
  621.     return E_INVALIDARG;
  622.   }
  623. }
  624. STDMETHODIMP CHandVuFilter::ToggleMaintenanceApp()
  625. {
  626.   CAutoLock lock(&m_HandVuFilterLock);
  627.   if (!m_pOverlay) {
  628.     VERBOSE0(3, "HandVuFilter: loading MaintenanceApp");
  629.     m_pOverlay = new CMaintenanceApp();
  630.     m_pOverlay->Initialize(m_cxImage, m_cyImage);
  631.     // $IT_DATA environmet variable, NULL if not set
  632.     const char *it_data = getenv("IT_DATA");
  633.     string filename = string(it_data)+"\config\default.conductor";
  634.     try {
  635.       hvLoadConductor(filename);
  636.       hvStartRecognition();
  637.       hvSetOverlayLevel(0);
  638.     } catch (HVException& hve) {
  639.       AfxMessageBox(hve.GetMessage().c_str());
  640.       delete m_pOverlay;
  641.       m_pOverlay = NULL;
  642.       return S_FALSE;
  643.     }
  644.   }
  645.   m_show_maintenanceapp = !m_show_maintenanceapp;
  646.   return NOERROR;
  647. }
  648. STDMETHODIMP CHandVuFilter::ToggleFDLOnly()
  649. {
  650.   m_FDL_only = !m_FDL_only;
  651.   return NOERROR;
  652. }
  653. #if !defined(HAVE_USER_STUDY)
  654. STDMETHODIMP CHandVuFilter::OnMouseMove(UINT nFlags, double x, double y)
  655. {
  656.   return NOERROR;
  657. }
  658. STDMETHODIMP CHandVuFilter::OnLButtonUp(UINT nFlags, double x, double y)
  659. {
  660.   return NOERROR;
  661. }
  662. #endif // ! HAVE_USER_STUDY
  663. STDMETHODIMP CHandVuFilter::SetTimecodeReader(IUnknown* tcr)
  664. {
  665.   ASSERT(tcr);
  666.   HRESULT hr;
  667.   hr = tcr->QueryInterface(IID_IAMTimecodeReader, (void **) &m_pIAMTCReader);
  668.   if (!SUCCEEDED(hr)) {
  669.     VERBOSE0(1, "HVF: got corrupt DV TimecodeReader");
  670.     m_pIAMTCReader = NULL;
  671.     return hr;
  672.   }
  673.   return NOERROR;
  674. }
  675. string CHandVuFilter::GetTimecode()
  676. {
  677.   ASSERT(m_pIAMTCReader);
  678.   TIMECODE_SAMPLE TimecodeSample;
  679.   TimecodeSample.timecode.dwFrames = 0;
  680.   static DWORD i1 = 0, i2 = 0, i3 = 0;
  681.   TimecodeSample.dwFlags = ED_DEVCAP_TIMECODE_READ;
  682.   // Query the TimeCode sample data
  683.   HRESULT hr = m_pIAMTCReader->GetTimecode(&TimecodeSample);
  684.   ASSERT(SUCCEEDED(hr));
  685.   const int tcodelen = 64;
  686.   TCHAR tcode[tcodelen];
  687.   wsprintf(tcode, "%.2x:%.2x:%.2x:%.2x",
  688. //  StringCbPrintf(tcode, tcodelen*sizeof(TCHAR), "%.2x:%.2x:%.2x:%.2x",
  689.     ((TimecodeSample.timecode.dwFrames & 0xff000000) >> 24),
  690.     ((TimecodeSample.timecode.dwFrames & 0x00ff0000) >> 16),
  691.     ((TimecodeSample.timecode.dwFrames & 0x0000ff00) >>  8),
  692.     (TimecodeSample.timecode.dwFrames & 0x000000ff));
  693.   return string(tcode);
  694. STDMETHODIMP CHandVuFilter::TakeSnapshot() {
  695.   CAutoLock lock(&m_HandVuFilterLock);
  696.   if (m_pColorHeader==NULL) {
  697.     return E_UNEXPECTED;
  698.   }
  699.   m_take_one_snapshot = true;
  700.   return NOERROR;
  701. }
  702. void CHandVuFilter::SaveImageArea(IplImage* pImg)
  703. {
  704.   ASSERT(m_is_initialized);
  705.   string picfile = "";
  706.   hvSaveImageArea(pImg, 0, 0, INT_MAX, INT_MAX, picfile);
  707.   VERBOSE1(3, "HandVuFilter: saved image in file %s", picfile.c_str());
  708. }
  709. STDMETHODIMP CHandVuFilter::SetVerbosity(int level, const string& logfilename)
  710. {
  711.   CAutoLock lock(&m_HandVuFilterLock);
  712.   if (logfilename=="") {
  713.     g_verbose = level;
  714.     return NOERROR;
  715.   }
  716.   g_ostream = fopen(logfilename.c_str(), "a+");
  717.   if (g_ostream==NULL) {
  718.     return E_FAIL;
  719.   }
  720.   g_verbose = level;
  721.   return NOERROR;
  722. }
  723. STDMETHODIMP CHandVuFilter::GetVersion(string& version)
  724. {
  725.   if (!m_is_initialized) {
  726.     return E_UNEXPECTED;
  727.   }
  728.   version = "HandVuFilter CVS id: $Id: HandVuFilter.cpp,v 1.22 2005/10/30 23:00:43 matz Exp $";
  729.   version = version + ", built on "__DATE__" at "__TIME__;   string handvu_version;
  730.   hvGetVersion(handvu_version, 3);
  731.   version = version + "n" + handvu_version;
  732.   return NOERROR;
  733. }