Commit 46985ff5538ba29ff04f2b9298a49da1a483c4f3
1 parent
e9a774f1
Buffer management via scarcity
Rather than putting limits on the number of items in the buffers of individual processing stages of a stream, put a limit on the total number of frames actively being processed by the stream.
Showing
1 changed file
with
95 additions
and
51 deletions
sdk/plugins/stream.cpp
| ... | ... | @@ -29,7 +29,7 @@ public: |
| 29 | 29 | class SharedBuffer |
| 30 | 30 | { |
| 31 | 31 | public: |
| 32 | - SharedBuffer(int _maxItems = 200) : maxItems(_maxItems) {} | |
| 32 | + SharedBuffer(int _maxItems = 200000) : maxItems(_maxItems) {} | |
| 33 | 33 | virtual ~SharedBuffer() {} |
| 34 | 34 | |
| 35 | 35 | virtual void addItem(FrameData * input)=0; |
| ... | ... | @@ -49,7 +49,7 @@ protected: |
| 49 | 49 | class SingleBuffer : public SharedBuffer |
| 50 | 50 | { |
| 51 | 51 | public: |
| 52 | - SingleBuffer(unsigned _maxItems = 20) : SharedBuffer(_maxItems) { no_input = false; } | |
| 52 | + SingleBuffer(unsigned _maxItems = 20000) : SharedBuffer(_maxItems) { no_input = false; } | |
| 53 | 53 | |
| 54 | 54 | void stoppedInput() |
| 55 | 55 | { |
| ... | ... | @@ -119,40 +119,61 @@ private: |
| 119 | 119 | class DataSource |
| 120 | 120 | { |
| 121 | 121 | public: |
| 122 | - DataSource() {} | |
| 123 | - virtual ~DataSource() {} | |
| 122 | + DataSource(int maxFrames=100) | |
| 123 | + { | |
| 124 | + for (int i=0; i < maxFrames;i++) | |
| 125 | + { | |
| 126 | + allFrames.addItem(new FrameData()); | |
| 127 | + } | |
| 128 | + allFrames.startInput(); | |
| 129 | + } | |
| 130 | + | |
| 131 | + virtual ~DataSource() | |
| 132 | + { | |
| 133 | + allFrames.stoppedInput(); | |
| 134 | + while (true) | |
| 135 | + { | |
| 136 | + FrameData * frame = allFrames.getItem(); | |
| 137 | + if (frame == NULL) | |
| 138 | + break; | |
| 139 | + delete frame; | |
| 140 | + } | |
| 141 | + } | |
| 142 | + | |
| 143 | + FrameData * getFrame() | |
| 144 | + { | |
| 145 | + FrameData * aFrame = allFrames.getItem(); | |
| 146 | + aFrame->data.clear(); | |
| 147 | + aFrame->sequenceNumber = -1; | |
| 148 | + | |
| 149 | + bool res = getNext(*aFrame); | |
| 150 | + if (!res) { | |
| 151 | + allFrames.addItem(aFrame); | |
| 152 | + return NULL; | |
| 153 | + } | |
| 154 | + return aFrame; | |
| 155 | + } | |
| 156 | + | |
| 157 | + void returnFrame(FrameData * inputFrame) | |
| 158 | + { | |
| 159 | + allFrames.addItem(inputFrame); | |
| 160 | + } | |
| 124 | 161 | |
| 125 | - virtual FrameData * getNext() = 0; | |
| 126 | 162 | virtual void close() = 0; |
| 127 | - virtual bool open(Template & input) = 0; | |
| 163 | + virtual bool open(Template & output) = 0; | |
| 128 | 164 | virtual bool isOpen() = 0; |
| 165 | + | |
| 166 | + virtual bool getNext(FrameData & input) = 0; | |
| 167 | + | |
| 168 | +protected: | |
| 169 | + SingleBuffer allFrames; | |
| 129 | 170 | }; |
| 130 | 171 | |
| 131 | 172 | // Read a video frame by frame using cv::VideoCapture |
| 132 | 173 | class VideoDataSource : public DataSource |
| 133 | 174 | { |
| 134 | 175 | public: |
| 135 | - VideoDataSource() {} | |
| 136 | - | |
| 137 | - FrameData * getNext() | |
| 138 | - { | |
| 139 | - if (!isOpen()) | |
| 140 | - return NULL; | |
| 141 | - | |
| 142 | - FrameData * output = new FrameData(); | |
| 143 | - output->data.append(Template(basis.file)); | |
| 144 | - output->data.last().append(cv::Mat()); | |
| 145 | - | |
| 146 | - output->sequenceNumber = next_idx; | |
| 147 | - next_idx++; | |
| 148 | - | |
| 149 | - bool res = video.read(output->data.last().last()); | |
| 150 | - if (!res) { | |
| 151 | - delete output; | |
| 152 | - return NULL; | |
| 153 | - } | |
| 154 | - return output; | |
| 155 | - } | |
| 176 | + VideoDataSource(int maxFrames) : DataSource(maxFrames) {} | |
| 156 | 177 | |
| 157 | 178 | bool open(Template &input) |
| 158 | 179 | { |
| ... | ... | @@ -167,6 +188,24 @@ public: |
| 167 | 188 | void close() { video.release(); } |
| 168 | 189 | |
| 169 | 190 | private: |
| 191 | + bool getNext(FrameData & output) | |
| 192 | + { | |
| 193 | + if (!isOpen()) | |
| 194 | + return false; | |
| 195 | + | |
| 196 | + output.data.append(Template(basis.file)); | |
| 197 | + output.data.last().append(cv::Mat()); | |
| 198 | + | |
| 199 | + output.sequenceNumber = next_idx; | |
| 200 | + next_idx++; | |
| 201 | + | |
| 202 | + bool res = video.read(output.data.last().last()); | |
| 203 | + if (!res) { | |
| 204 | + return false; | |
| 205 | + } | |
| 206 | + return true; | |
| 207 | + } | |
| 208 | + | |
| 170 | 209 | cv::VideoCapture video; |
| 171 | 210 | Template basis; |
| 172 | 211 | int next_idx; |
| ... | ... | @@ -177,21 +216,9 @@ private: |
| 177 | 216 | class TemplateDataSource : public DataSource |
| 178 | 217 | { |
| 179 | 218 | public: |
| 180 | - TemplateDataSource() { current_idx = INT_MAX; } | |
| 181 | - | |
| 182 | - FrameData * getNext() | |
| 219 | + TemplateDataSource(int maxFrames) : DataSource(maxFrames) | |
| 183 | 220 | { |
| 184 | - if (!isOpen()) | |
| 185 | - return NULL; | |
| 186 | - | |
| 187 | - FrameData * output = new FrameData(); | |
| 188 | - output->data.append(basis[current_idx]); | |
| 189 | - current_idx++; | |
| 190 | - | |
| 191 | - output->sequenceNumber = next_sequence; | |
| 192 | - next_sequence++; | |
| 193 | - | |
| 194 | - return output; | |
| 221 | + current_idx = INT_MAX; | |
| 195 | 222 | } |
| 196 | 223 | |
| 197 | 224 | bool open(Template &input) |
| ... | ... | @@ -211,6 +238,20 @@ public: |
| 211 | 238 | } |
| 212 | 239 | |
| 213 | 240 | private: |
| 241 | + bool getNext(FrameData & output) | |
| 242 | + { | |
| 243 | + if (!isOpen()) | |
| 244 | + return false; | |
| 245 | + | |
| 246 | + output.data.append(basis[current_idx]); | |
| 247 | + current_idx++; | |
| 248 | + | |
| 249 | + output.sequenceNumber = next_sequence; | |
| 250 | + next_sequence++; | |
| 251 | + | |
| 252 | + return true; | |
| 253 | + } | |
| 254 | + | |
| 214 | 255 | Template basis; |
| 215 | 256 | int current_idx; |
| 216 | 257 | int next_sequence; |
| ... | ... | @@ -232,12 +273,6 @@ public: |
| 232 | 273 | close(); |
| 233 | 274 | } |
| 234 | 275 | |
| 235 | - FrameData * getNext() | |
| 236 | - { | |
| 237 | - if (!isOpen()) return NULL; | |
| 238 | - return actualSource->getNext(); | |
| 239 | - } | |
| 240 | - | |
| 241 | 276 | void close() |
| 242 | 277 | { |
| 243 | 278 | if (actualSource) { |
| ... | ... | @@ -253,13 +288,13 @@ public: |
| 253 | 288 | bool open_res = false; |
| 254 | 289 | // Input has no matrices? Its probably a video that hasn't been loaded yet |
| 255 | 290 | if (input.empty()) { |
| 256 | - actualSource = new VideoDataSource(); | |
| 291 | + actualSource = new VideoDataSource(0); | |
| 257 | 292 | open_res = actualSource->open(input); |
| 258 | 293 | qDebug("created video resource status %d", open_res); |
| 259 | 294 | } |
| 260 | 295 | else { |
| 261 | 296 | // create frame dealer |
| 262 | - actualSource = new TemplateDataSource(); | |
| 297 | + actualSource = new TemplateDataSource(0); | |
| 263 | 298 | open_res = actualSource->open(input); |
| 264 | 299 | } |
| 265 | 300 | if (!isOpen()) { |
| ... | ... | @@ -274,6 +309,11 @@ public: |
| 274 | 309 | |
| 275 | 310 | protected: |
| 276 | 311 | DataSource * actualSource; |
| 312 | + bool getNext(FrameData & output) | |
| 313 | + { | |
| 314 | + return actualSource->getNext(output); | |
| 315 | + } | |
| 316 | + | |
| 277 | 317 | }; |
| 278 | 318 | |
| 279 | 319 | class ProcessingStage : public QRunnable |
| ... | ... | @@ -347,7 +387,8 @@ public: |
| 347 | 387 | { |
| 348 | 388 | forever |
| 349 | 389 | { |
| 350 | - FrameData * aFrame = dataSource.getNext(); | |
| 390 | + //FrameData * aFrame = dataSource.getNext(); | |
| 391 | + FrameData * aFrame = dataSource.getFrame(); | |
| 351 | 392 | if (aFrame == NULL) |
| 352 | 393 | break; |
| 353 | 394 | outputBuffer->addItem(aFrame); |
| ... | ... | @@ -367,6 +408,7 @@ public: |
| 367 | 408 | private: |
| 368 | 409 | TemplateList collectedOutput; |
| 369 | 410 | public: |
| 411 | + DataSource * data; | |
| 370 | 412 | void run() |
| 371 | 413 | { |
| 372 | 414 | forever |
| ... | ... | @@ -377,7 +419,8 @@ public: |
| 377 | 419 | break; |
| 378 | 420 | // Just put the item on collectedOutput |
| 379 | 421 | collectedOutput.append(frame->data); |
| 380 | - delete frame; | |
| 422 | + // Return the frame to the input frame buffer | |
| 423 | + data->returnFrame(frame); | |
| 381 | 424 | } |
| 382 | 425 | this->markStop(); |
| 383 | 426 | } |
| ... | ... | @@ -505,6 +548,7 @@ public: |
| 505 | 548 | } |
| 506 | 549 | |
| 507 | 550 | collectionStage.inputBuffer = sharedBuffers.last(); |
| 551 | + collectionStage.data = &readStage.dataSource; | |
| 508 | 552 | collectionStage.stage_id = next_stage_id; |
| 509 | 553 | } |
| 510 | 554 | ... | ... |