SimpleUnit.cpp

Go to the documentation of this file.
00001 /*
00002 *       This file contains simple working unit from that may be simply derived others units.
00003 *
00004 *       Author:
00005 *                       Tomas Mrkvicka
00006 *                       xmrkvi03@stud.fit.vutbr.cz
00007 *
00008 */
00009 
00010 #include <cassert>
00011 
00012 #include "pipeline/SimpleUnit.h"
00013 
00014 ////////////////////////////////////////////////////////////////////////////////
00015 ////////////////////////////////////////////////////////////////////////////////
00016 ////////////////////////////////////////////////////////////////////////////////
00017 // TSimpleUnit
00018 
00019 /** Tato staticka metoda tvori telo vlakna ve kterem jednotka
00020 *       zpracovava snimky
00021 *
00022 *       \param  ptr     [in] ukazatel na jednotku typu TSimpleUnit
00023 */
00024 DWORD WINAPI TSimpleUnit::TSimpleUnitThread(void* ptr)
00025 {
00026         TSimpleUnit * simple_unit = (TSimpleUnit*)ptr;
00027 
00028         /** Smycka bezi dokud vlakno nezastavi.
00029         */
00030         while( simple_unit->GetState() != ENUM_UNIT_STOP )
00031         {
00032                 simple_unit->Loop();
00033         };
00034 
00035         return 0;
00036 }
00037 //OK 2007-08-25 18:42:47 B04-315B\Tom
00038 
00039 /** Konstruktor.
00040 *       Vytvori jednotku, ktera musi byt nasledne spustena pomoci metody Start.
00041 *
00042 *       \param  dispatcher      [in] rozhrani na objekt pro ziskavani novych snimku z kamery
00043 *       \param  unit            [in] rozhrani vlastni zpracovavajici jednotky - objekt je jednotkou automaticky
00044 *                                               znicen v destruktoru
00045 *       \param  lockFrame       [in] tento parametr urcuje zda bude jednotka zamykat snimky
00046 *                                               Zamknutim snimku jednotka neumozni zobrazit snimek dokud neni kompletne zpracovan.
00047 */
00048 TSimpleUnit::TSimpleUnit(
00049         TDispatcherInterface* dispatcher,
00050         TSimpleUnitProcessingInterface * unit,
00051         BOOL lockFrame)
00052 {
00053         m_thread                = NULL;
00054 
00055         m_state                 = ENUM_UNIT_LOADFRAME;
00056 
00057         m_dispatcher    = dispatcher;
00058         m_unit                  = unit;
00059 
00060         m_lockFrame             = lockFrame;
00061         m_frame                 = NULL;
00062 
00063         m_interval              = 0;
00064 }
00065 //OK 2007-08-25 18:42:50 B04-315B\Tom
00066 
00067 /** Destruktor
00068 *
00069 *       Destruktor smi byt volan pouze po radnem zastaveni jednotky metodou Stop!!!
00070 *       To zajisti, ze jednotka nebude udrzovat reference na zadne snimky.
00071 */
00072 TSimpleUnit::~TSimpleUnit(void)
00073 {
00074         //snimek musi byt odstranen pred znicenim - toho je docileno zastavenim jednotky
00075         assert( m_frame == NULL );
00076 
00077         delete m_unit;
00078         m_unit = NULL;
00079 }
00080 //OK 2007-08-25 18:42:52 B04-315B\Tom
00081 
00082 /** Zniceni objektu.
00083 *
00084 *       Neni zde zadne pocitani referenci, takze jednotka se znici okamzite.
00085 *
00086 *       Metoda smi byt volana v okamziku kdy jiz jednotka nebezi.
00087 *
00088 *       Tato metoda musi byt reimplementovana v odvozene tride !!!
00089 */
00090 void TSimpleUnit::Release(void)
00091 {
00092         delete this;
00093 }
00094 //OK 2007-08-25 18:42:54 B04-315B\Tom
00095 
00096 /** Spusteni jednotky.
00097 *
00098 *       Vraci TRUE pokud byla jednotka spustena nebo jiz bezi.
00099 *
00100 *       FALSE vraci pri kriticke chybe, kdyz napr. neni mozne vytvorit vlakno apod.
00101 *       V takovem pripade je nutne okmazite ukoncit aplikaci.
00102 */
00103 BOOL TSimpleUnit::Start(void)
00104 {
00105         if( ! m_thread )
00106         {
00107                 //jednotka nebezi
00108 
00109                 //nastavime jednotce pocatecni stav
00110                 SetState(ENUM_UNIT_LOADFRAME);
00111 
00112                 //spustime vypocetni vlakno
00113                 m_thread = new TThread;
00114                 BOOL res = m_thread->Run( (FUNC_PTR)TSimpleUnitThread,(void*)this);
00115 
00116                 if ( res )
00117                 {
00118                         return TRUE;
00119                 }
00120                 else
00121                 {
00122                         //nejaka chyba
00123                         delete m_thread;
00124                         m_thread  = NULL;
00125                         return FALSE;
00126                 }
00127         }
00128         else
00129         {
00130                 //jednotka uz bezi
00131                 return TRUE;
00132         }
00133 }
00134 //OK 2007-08-25 18:43:10 B04-315B\Tom
00135 
00136 /** Zastaveni jednotky.
00137 *
00138 *       Vraci TRUE pokud se jednotku podarilo zastavit.
00139 */
00140 BOOL TSimpleUnit::Stop(void)
00141 {
00142         if( m_thread )
00143         {
00144                 //jednotka byla spustena
00145 
00146                 if( m_thread->IsTerminated() )
00147                 {
00148                         //vlakno uz bylo ukonceno - pouze uklidime
00149                         m_thread->Finish();     //zde metoda uspeje
00150                         delete m_thread;
00151                         m_thread = NULL;
00152                 }
00153                 else
00154                 {
00155                         //vlakno stale bezi - pokusime se ho ukoncit standardni cestou
00156                         //zajistime ze vlakno jednotky nezmeni stav
00157                         m_critical.Enter();
00158                                 if(m_state == ENUM_UNIT_STOP)
00159                                 {
00160                                         //jednotka jiz stoji, bude brzy ukoncena v ramci sveho vlakna
00161                                 }
00162                                 else
00163                                 {
00164                                         switch(m_state)
00165                                         {
00166                                                 //jednotka pracuje - dame ji pokyn ze po dokonceni uz nema pokracovat
00167                                                 case ENUM_UNIT_WORK:
00168                                                 case ENUM_UNIT_LOADFRAME:
00169                                                         m_state = ENUM_UNIT_FINISHWORK;
00170                                                 break;
00171 
00172                                                 //jednotka dokoncuje ulohu
00173                                                 case ENUM_UNIT_FINISHWORK:
00174                                                         //jednotka se brzy sama zastavi
00175                                                 break;
00176 
00177                                                 default:
00178                                                         //nejaka chyba
00179                                                         m_state = ENUM_UNIT_FINISHWORK;
00180                                                         assert(false);
00181                                                 break;
00182                                         }               
00183                                 }                               
00184                         m_critical.Leave();
00185 
00186                         //nyni cekame na ukonceni jednotky
00187                         //todo - tady muze pri zavazne chybe vzniknout nekonecny cyklus - zatim nevyresene
00188                         while( ! m_thread->IsTerminated() )
00189                         {
00190                                 Sleep(20);
00191                         };
00192 
00193                         //nyni jednotka stoji - ukoncime ji
00194                         m_thread->Finish(); //metoda uspeje
00195                         delete m_thread;
00196                         m_thread = NULL;
00197                 }
00198 
00199                 //odstranime zbyvajici snimek - pokud existuje
00200                 if( m_frame )
00201                 {
00202                         m_frame->Release();
00203 
00204                         //odstranime zamek - pokud jednotka zamyka snimky
00205                         if(m_lockFrame)
00206                         {
00207                                 m_frame->ReleaseLock();
00208                         }
00209                         m_frame = NULL;
00210                 }
00211 
00212                 return TRUE;
00213         }
00214         else
00215         {
00216                 //jednotka neni spustena
00217                 return TRUE;
00218         }
00219 }
00220 //OK 2007-08-25 18:43:29 B04-315B\Tom
00221 
00222 /** Hlavni smycka jednotky.
00223 *
00224 *       Je volana ze staticke metody TSimpleUnit::Run() a obsahuje ridici logiku cele jednotky.
00225 */
00226 void TSimpleUnit::Loop(void)
00227 {
00228         //pouzijime kopii aktualniho stavu - kvuli synchronizaci vlaken
00229         m_critical.Enter();
00230                 EnumUnitState actState = m_state;
00231         m_critical.Leave();
00232 
00233         //zde uz externi vlakno muze menit stav jednotky, to se projevi pripadne v dalsim kroku iterace
00234 
00235         switch(actState)
00236         {
00237                 //jednotka nic nedela - k tomuto by teoreticky nemelo dojit, protoze tento stav znamena ukonceni
00238                 //hlavni smycky vlakna - viz staticka metoda TSimpleUnitThread
00239                 case ENUM_UNIT_STOP:
00240                 {
00241                 }
00242                 break;
00243 
00244                 //nacteni noveho snimku         
00245                 case ENUM_UNIT_LOADFRAME:
00246                 {
00247                         //nacteme novy snimek
00248                         TFrame * frame = NULL;
00249                         if( m_lockFrame )
00250                         {
00251                                 //musime ziskat zamceny snimek
00252                                 frame = m_dispatcher->GetLockedFrame();
00253                         }
00254                         else
00255                         {
00256                                 //jednotka snimky nezamyka
00257                                 frame = m_dispatcher->GetFrame();
00258                         }                       
00259 
00260                         if(frame)
00261                         {
00262                                 //ziskali jsme snimek
00263                                 //pokud existuje nejaky predchozi snimek zjistime zda se nejedna o identicke snimky
00264                                 if(m_frame)
00265                                 {
00266                                         //zjistime zda se jedna o novejsi snimek
00267                                         if( frame->GetTimestamp() != m_frame->GetTimestamp() )
00268                                         {
00269                                                 //ano - toto je novejsi (jiny) snimek
00270                                                 
00271                                                 //rozdil mezi ID snimkku
00272                                                 DWORD lastID = m_frame->GetTimestamp().GetID();
00273                                                 DWORD newID = frame->GetTimestamp().GetID();
00274 
00275                                                 //spocitame interval zahozenych snimku
00276                                                 if ( newID > lastID )
00277                                                 {
00278                                                         m_interval = newID - lastID;
00279                                                 }
00280                                                 else
00281                                                 {
00282                                                         //pravdepodobne preteceni
00283                                                         m_interval = 0;
00284                                                 }
00285 
00286                                                 //predchozi uvolnime
00287                                                 if( m_lockFrame )
00288                                                 {
00289                                                         //jednotka drzi zamek
00290                                                         m_frame->ReleaseLock();
00291                                                         m_frame->Release();                                                     
00292                                                 }
00293                                                 else
00294                                                 {
00295                                                         //pouze reference
00296                                                         m_frame->Release();                                                     
00297                                                 }
00298                                                 //ulozime novy snimek - referenci uz mame (vcetne pripadneho zamku) z metody
00299                                                 //dispatcheru
00300                                                 m_frame = frame;
00301 
00302                                                 //pokud mame novy snimek tak prejdeme znovu do stavu zpracovavani snimku
00303                                                 //musi platit aktualni stav ENUM_UNIT_LOADFRAME abychom mohli prejit do ENUM_UNIT_WORK
00304                                                 //toto se muze zmenit pomoci metody Stop ktera zmeni stav na ENUM_UNIT_FINISHWORK
00305                                                 m_critical.Enter();
00306                                                         if ( m_state == ENUM_UNIT_LOADFRAME ) 
00307                                                         {
00308                                                                 m_state = ENUM_UNIT_WORK;
00309                                                         }
00310                                                 m_critical.Leave();
00311                                         }
00312                                         else
00313                                         {
00314                                                 //ne - snimky jsou stejne - pokracujeme v nacitani snimku
00315                                                 //uvolnime referenci na ziskany snimek
00316                                                 if(m_lockFrame)
00317                                                 {
00318                                                         frame->ReleaseLock();
00319                                                         frame->Release();                                                       
00320                                                 }
00321                                                 else
00322                                                 {                                                       
00323                                                         frame->Release();                                                       
00324                                                 }
00325 
00326                                                 //todo - mozna pridat nejaky cekaci stav
00327                                                 Sleep(10);
00328                                         }
00329                                 }
00330                                 else // if ( m_frame )
00331                                 {
00332                                         //novy snimek (pravdepodobne prvni)
00333                                         m_frame = frame;
00334 
00335                                         //prechod do noveho stavu pokud jednotka nechce skoncit
00336                                         m_critical.Enter();
00337                                                 if ( m_state == ENUM_UNIT_LOADFRAME )
00338                                                 {
00339                                                         // ok - jednotka ma stale pracovat
00340                                                         m_state = ENUM_UNIT_WORK;
00341                                                 }
00342                                         m_critical.Leave();
00343 
00344                                         // predchozi snimek nebyl k dispozici a interval je tedy 0
00345                                         m_interval = 0;
00346                                 }
00347                         }
00348                         else // if ( frame )
00349                         {
00350                                 //zadny snimek neprisel
00351                         }
00352                 }
00353                 break;
00354 
00355                 //procesor zpracovava snimek
00356                 case ENUM_UNIT_WORK:
00357                 {
00358                         //virtualni metoda zpracuje snimek tak jak je reimplementovana
00359                         //zde musi byt vzdy nacten snimek !!!
00360                         this->m_unit->ProcessFrame( m_frame );
00361 
00362                         //snimek bude uvolnen bud pri nacitani dalsiho snimku nebo pri zastaveni jednotky
00363                         //snimek potrebujeme pro porovnani s dalsim nactenym snimkem, proto ho zde nemuze uvolnit
00364 
00365                         //musime znovu nacist snimek pokud nebyla volana metoda Stop 
00366                         //podminene tedy prechazime do stavu ENUM_UNIT_LOADFRAME
00367                         //Volani stop by zpusobilo zmenu stavu na ENUM_UNIT_FINISHWORK a tim by byla v pristim cyklu
00368                         //prace jednotka dokoncena
00369                         m_critical.Enter();
00370                                 if( m_state == ENUM_UNIT_WORK )
00371                                 {
00372                                         m_state = ENUM_UNIT_LOADFRAME;
00373                                 }
00374                         m_critical.Leave();
00375                 }
00376                 break;
00377 
00378                 //ukonceni veskere cinnosti a prechod do stavu ENUM_UNIT_STOP
00379                 //tento stav nastane po zavolani metody Stop behem ENUM_UNIT_LOADFRAME nebo ENUM_UNIT_WORK
00380                 case ENUM_UNIT_FINISHWORK:
00381                 {               
00382                         m_critical.Enter();
00383                                 m_state = ENUM_UNIT_STOP;
00384                         m_critical.Leave();
00385                 }
00386                 break;
00387 
00388                 //k tomuto by nemelo nikdy dojit
00389                 default:
00390                 {
00391                         //jen pojistka
00392                         assert(false);
00393 
00394                         m_critical.Enter();
00395                                 m_state = ENUM_UNIT_STOP;
00396                         m_critical.Leave();
00397                 }
00398                 break;
00399         }
00400 }
00401 //OK 2007-08-25 18:44:43 B04-315B\Tom
00402 
00403 // TSimpleUnit
00404 ////////////////////////////////////////////////////////////////////////////////
00405 ////////////////////////////////////////////////////////////////////////////////
00406 ////////////////////////////////////////////////////////////////////////////////

Generated on Sat Nov 17 16:23:26 2007 for Image Processing Pipeline by  doxygen 1.4.6-NO