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 0 : ROITracker::Area::Area(const PixelViewport& pvp_, uint32_t lastSkip_,
22 0 : uint32_t skip_)
23 : : pvp(pvp_)
24 : , lastSkip(lastSkip_)
25 0 : , skip(skip_)
26 : {
27 0 : }
28 :
29 2 : ROITracker::ROITracker()
30 : : _needsUpdate(false)
31 2 : , _lastStage(0)
32 : {
33 2 : _ticket = reinterpret_cast<uint8_t*>(this);
34 2 : _prvFrame = new std::unordered_map<uint32_t, Stage>;
35 2 : _curFrame = new std::unordered_map<uint32_t, Stage>;
36 2 : }
37 :
38 4 : ROITracker::~ROITracker()
39 : {
40 2 : delete _prvFrame;
41 2 : delete _curFrame;
42 2 : _prvFrame = 0;
43 2 : _curFrame = 0;
44 2 : }
45 :
46 0 : bool ROITracker::_returnPositive(uint8_t*& ticket)
47 : {
48 0 : ticket = ++_ticket;
49 0 : _needsUpdate = true;
50 0 : return true;
51 : }
52 :
53 0 : bool ROITracker::useROIFinder(const PixelViewport& pvp, const uint32_t stage,
54 : const uint128_t& frameID, uint8_t*& ticket)
55 : {
56 0 : LBASSERT(!_needsUpdate);
57 0 : ticket = 0;
58 :
59 0 : const uint32_t pvpArea = pvp.getArea();
60 0 : if (pvpArea < 100)
61 0 : return false;
62 :
63 0 : if (_lastFrameID != frameID) // new frame
64 : {
65 0 : std::unordered_map<uint32_t, Stage>* tmp = _prvFrame;
66 0 : _prvFrame = _curFrame;
67 0 : _curFrame = tmp;
68 0 : _curFrame->clear();
69 0 : _lastFrameID = frameID;
70 : }
71 :
72 0 : _lastStage = stage;
73 :
74 0 : Stage& curStage = (*_curFrame)[stage];
75 :
76 : // check if proper stage is avaliable
77 0 : if (_prvFrame->find(stage) == _prvFrame->end()) // new stage
78 : {
79 0 : curStage.areas.push_back(Area(pvp));
80 0 : return _returnPositive(ticket);
81 : }
82 : // else existing stage, try to find matching area
83 :
84 0 : const Area* match = 0;
85 0 : uint32_t bestArea = 0;
86 0 : const Stage& prvStage = (*_prvFrame)[stage];
87 0 : for (uint32_t i = 0; i < prvStage.areas.size(); i++)
88 : {
89 0 : PixelViewport tmp = prvStage.areas[i].pvp;
90 0 : tmp.intersect(pvp);
91 0 : const uint32_t area = tmp.getArea();
92 0 : if (area > bestArea)
93 : {
94 0 : bestArea = area;
95 0 : match = &prvStage.areas[i];
96 0 : if (area == pvpArea) // full match
97 0 : break;
98 : }
99 : }
100 :
101 0 : if (bestArea < pvpArea * 2 / 3) // no proper match found, new area
102 : {
103 0 : curStage.areas.push_back(Area(pvp));
104 0 : return _returnPositive(ticket);
105 : }
106 : // else good match
107 :
108 0 : if (match->skip == 0) // don't skip frame
109 : {
110 0 : curStage.areas.push_back(Area(pvp, match->lastSkip));
111 0 : return _returnPositive(ticket);
112 : }
113 : // else skip frame
114 :
115 0 : curStage.areas.push_back(Area(pvp, match->lastSkip, match->skip - 1));
116 0 : return false;
117 : }
118 :
119 0 : void ROITracker::updateDelay(const PixelViewports& pvps, const uint8_t* ticket)
120 : {
121 0 : LBASSERT(_needsUpdate);
122 0 : LBASSERTINFO(ticket == _ticket, "Wrong ticket");
123 :
124 0 : if (ticket != _ticket)
125 : {
126 0 : LBERROR << "Wrong ticket" << std::endl;
127 0 : return;
128 : }
129 :
130 0 : uint32_t totalAreaFound = 0;
131 0 : for (uint32_t i = 0; i < pvps.size(); i++)
132 0 : totalAreaFound += pvps[i].getArea();
133 :
134 0 : Area& area = (*_curFrame)[_lastStage].areas.back();
135 0 : if (totalAreaFound < area.pvp.getArea() * 4 / 5)
136 : {
137 : // ROI cutted enough, reset failure statistics
138 0 : area.lastSkip = 0;
139 : }
140 : else
141 : {
142 : // disable ROI for next frames, if it was failing before,
143 : // increase number of frames to skip
144 0 : area.lastSkip = LB_MIN(area.lastSkip * 2 + 1, 64);
145 0 : area.skip = area.lastSkip;
146 : }
147 0 : _needsUpdate = false;
148 : }
149 30 : }
|