Line data Source code
1 : /* Copyright (c) 2009 Maxim Makhinya
2 : *
3 : * This library is free software; you can redistribute it and/or modify it under
4 : * the terms of the GNU Lesser General Public License version 2.1 as published
5 : * by the Free Software Foundation.
6 : *
7 : * This library is distributed in the hope that it will be useful, but WITHOUT
8 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
10 : * details.
11 : *
12 : * You should have received a copy of the GNU Lesser General Public License
13 : * along with this library; if not, write to the Free Software Foundation, Inc.,
14 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
15 : */
16 :
17 : #include "roiTracker.h"
18 :
19 : namespace eq
20 : {
21 :
22 0 : ROITracker::Area::Area( const PixelViewport& pvp_,
23 : uint32_t lastSkip_,
24 : uint32_t skip_ )
25 : :pvp( pvp_ )
26 : ,lastSkip( lastSkip_ )
27 0 : ,skip( skip_ )
28 : {
29 0 : }
30 :
31 :
32 1 : ROITracker::ROITracker()
33 : : _needsUpdate( false )
34 1 : , _lastStage( 0 )
35 : {
36 1 : _ticket = reinterpret_cast< uint8_t* >( this );
37 1 : _prvFrame = new stde::hash_map< uint32_t, Stage >;
38 1 : _curFrame = new stde::hash_map< uint32_t, Stage >;
39 1 : }
40 :
41 :
42 1 : ROITracker::~ROITracker()
43 : {
44 1 : delete _prvFrame;
45 1 : delete _curFrame;
46 1 : _prvFrame = 0;
47 1 : _curFrame = 0;
48 1 : }
49 :
50 :
51 0 : bool ROITracker::_returnPositive( uint8_t*& ticket )
52 : {
53 0 : ticket = ++_ticket;
54 0 : _needsUpdate = true;
55 0 : return true;
56 : }
57 :
58 0 : bool ROITracker::useROIFinder( const PixelViewport& pvp,
59 : const uint32_t stage,
60 : const uint128_t& frameID,
61 : uint8_t*& ticket )
62 : {
63 0 : LBASSERT( !_needsUpdate );
64 0 : ticket = 0;
65 :
66 0 : const uint32_t pvpArea = pvp.getArea();
67 0 : if( pvpArea < 100 )
68 0 : return false;
69 :
70 0 : if( _lastFrameID != frameID ) // new frame
71 : {
72 0 : stde::hash_map< uint32_t, Stage >* tmp = _prvFrame;
73 0 : _prvFrame = _curFrame;
74 0 : _curFrame = tmp;
75 0 : _curFrame->clear();
76 0 : _lastFrameID = frameID;
77 : }
78 :
79 0 : _lastStage = stage;
80 :
81 0 : Stage& curStage = (*_curFrame)[ stage ];
82 :
83 : // check if proper stage is avaliable
84 0 : if( _prvFrame->find( stage ) == _prvFrame->end( )) // new stage
85 : {
86 0 : curStage.areas.push_back( Area( pvp ));
87 0 : return _returnPositive( ticket );
88 : }
89 : //else existing stage, try to find matching area
90 :
91 0 : const Area* match = 0;
92 0 : uint32_t bestArea = 0;
93 0 : const Stage& prvStage = (*_prvFrame)[ stage ];
94 0 : for( uint32_t i = 0; i < prvStage.areas.size(); i++ )
95 : {
96 0 : PixelViewport tmp = prvStage.areas[i].pvp;
97 0 : tmp.intersect( pvp );
98 0 : const uint32_t area = tmp.getArea();
99 0 : if( area > bestArea )
100 : {
101 0 : bestArea = area;
102 0 : match = &prvStage.areas[i];
103 0 : if( area == pvpArea ) // full match
104 0 : break;
105 : }
106 : }
107 :
108 0 : if( bestArea < pvpArea*2/3 ) // no proper match found, new area
109 : {
110 0 : curStage.areas.push_back( Area( pvp ));
111 0 : return _returnPositive( ticket );
112 : }
113 : // else good match
114 :
115 0 : if( match->skip == 0 ) // don't skip frame
116 : {
117 0 : curStage.areas.push_back( Area( pvp, match->lastSkip ));
118 0 : return _returnPositive( ticket );
119 : }
120 : //else skip frame
121 :
122 0 : curStage.areas.push_back( Area( pvp, match->lastSkip, match->skip-1 ));
123 0 : return false;
124 : }
125 :
126 :
127 0 : void ROITracker::updateDelay( const PixelViewports& pvps,
128 : const uint8_t* ticket )
129 : {
130 0 : LBASSERT( _needsUpdate );
131 0 : LBASSERTINFO( ticket == _ticket, "Wrong ticket" );
132 :
133 0 : if( ticket != _ticket )
134 : {
135 0 : LBERROR << "Wrong ticket" << std::endl;
136 0 : return;
137 : }
138 :
139 0 : uint32_t totalAreaFound = 0;
140 0 : for( uint32_t i = 0; i < pvps.size(); i++ )
141 0 : totalAreaFound += pvps[ i ].getArea();
142 :
143 0 : Area& area = (*_curFrame)[ _lastStage ].areas.back();
144 0 : if( totalAreaFound < area.pvp.getArea()*4/5 )
145 : {
146 : // ROI cutted enough, reset failure statistics
147 0 : area.lastSkip = 0;
148 : }else
149 : {
150 : // disable ROI for next frames, if it was failing before,
151 : // increase number of frames to skip
152 0 : area.lastSkip = LB_MIN( area.lastSkip*2 + 1, 64 );
153 0 : area.skip = area.lastSkip;
154 : }
155 0 : _needsUpdate = false;
156 : }
157 :
158 42 : }
159 :
160 :
|