Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
diagnostic-output-slot.hpp
Go to the documentation of this file.
1/*
2 DIAGNOSTIC-OUTPUT-SLOT.hpp - helper for testing against the OutputSlot interface
3
4 Copyright (C)
5 2011, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12*/
13
21#ifndef STEAM_PLAY_DIAGNOSTIC_OUTPUT_SLOT_H
22#define STEAM_PLAY_DIAGNOSTIC_OUTPUT_SLOT_H
23
24
25#include "lib/error.hpp"
26#include "lib/nocopy.hpp"
27#include "include/logging.h"
35#include "lib/iter-source.hpp"
36#include "lib/symbol.hpp"
37#include "lib/util.hpp"
38#include "common/advice.hpp"
40//#include "lib/sync.hpp"
41
42//#include <string>
43//#include <vector>
44#include <unordered_set>
45#include <memory>
46
47
48namespace steam {
49namespace play {
50
51//using std::string;
52 using lib::Symbol;
53 using util::unConst;
54 using util::contains;
61 namespace diagn = steam::engine::diagn;
62
63//using std::vector;
64 using std::shared_ptr;
65
66 namespace { // diagnostics & internals....
67
68 inline PGrid
70 {
71 Symbol gridID("DiagnosticOutputSlot-buffer-grid");
72 lumiera::advice::Request<PGrid> query4grid(gridID) ;
73 PGrid testGrid25 = query4grid.getAdvice();
74
75 if (!testGrid25)
76 testGrid25 = TimeGrid::build (gridID, FrameRate::PAL);
77
78 ENSURE (testGrid25);
79 return testGrid25;
80 }
81 }
82
83
92 {
93
94 typedef std::unordered_set<FrameID> FrameTrackingInfo;
95
96
99
102
104
105
107 trackFrame (FrameID frameNr, BuffHandle const& newBuffer)
108 {
109 TRACE (test, "Con=%p : track buffer %zu for frame-#%lu"
110 , this, newBuffer.entryID(), frameNr);
111 REQUIRE (!contains (frameTrackingIndex_,frameNr),
112 "attempt to lock already used frame %lu", frameNr);
113
114 frameTrackingIndex_.insert (frameNr);
115 return newBuffer;
116 }
117
120 {
121 // a real world implementation
122 // would offset by a latency here
123 return frameGrid_->timeOf (frameNr);
124 }
125
126
127
128
129 /* === Connection API === */
130
133 {
134 TRACE (test, "Con=%p : lock buffer for frame-#%lu", this, frameNr);
135 REQUIRE (!closed_);
136
137 return trackFrame (frameNr,
139 }
140
141
142 bool
143 isTimely (FrameID frameNr, TimeValue currentTime)
144 {
145 TRACE (test, "Con=%p : timely? frame-#%lu"
146 , this, frameNr);
147
148 if (Time::ANYTIME == currentTime)
149 return true;
150 else
151 return currentTime < deadlineFor (frameNr);
152 }
153
154 void
155 transfer (BuffHandle const& filledBuffer)
156 {
157 TRACE (test, "Con=%p : transfer buffer %zu"
158 , this, filledBuffer.entryID());
159 REQUIRE (!closed_);
160
161 pushout (filledBuffer);
162 }
163
164 void
165 pushout (BuffHandle const& data4output)
166 {
167 REQUIRE (!closed_);
168 buffProvider_.emitBuffer (data4output);
169 buffProvider_.releaseBuffer(data4output);
170 }
171
172 void
173 discard (BuffHandle const& superseededData)
174 {
175 REQUIRE (!closed_);
176 buffProvider_.releaseBuffer (superseededData);
177 }
178
179 void
181 {
182 closed_ = true;
183 }
184
185 public:
187 : buffProvider_()
188 , bufferType_(buffProvider_.getDescriptor<TestFrame>())
190 , frameGrid_(getTestTimeGrid())
191 , closed_(false)
192 {
193 INFO (engine_dbg, "building in-memory diagnostic output sequence (at %p)", this);
194 }
195
196 virtual
198 {
199 INFO (engine_dbg, "releasing diagnostic output sequence (at %p)", this);
200 }
201
202
203 /* === Diagnostic API === */
204
205 TestFrame const *
206 accessEmittedFrame (uint frameNr) const
207 {
208 if (frameNr < buffProvider_.emittedCnt())
209 return & accessFrame(frameNr);
210 else
211 return 0;
212 }
213
214 diagn::Block const *
215 accessEmittedBuffer (uint bufferNr) const
216 {
217 if (bufferNr < buffProvider_.emittedCnt())
218 return & accessBlock(bufferNr);
219 else
220 return 0;
221 }
222
223 bool
224 wasAllocated (uint frameNr) const
225 {
226 TRACE (test, "query wasAllocated. Con=%p", this);
227
228 return contains (frameTrackingIndex_, frameNr);
229 }
230
231 private:
232 TestFrame const&
233 accessFrame (uint frameNr) const
234 {
235 return unConst(this)->buffProvider_.accessAs<TestFrame> (frameNr);
236 }
237
238 diagn::Block const&
239 accessBlock (uint bufferNr) const
240 {
241 return unConst(this)->buffProvider_.access_emitted (bufferNr);
242 }
243 };
244
245
246
247
248
249
250
251
252
253 /****************************************************************/
267 : public OutputSlotImplBase
268 {
269
270 static const uint MAX_CHANNELS = 5;
271
275 uint
277 {
278 return MAX_CHANNELS;
279 }
280
281
288 : public ConnectionManager<TrackingInMemoryBlockSequence>
289 {
291
292 void
294 {
295 storage.create<TrackingInMemoryBlockSequence>();
296 }
297
298 public:
300 : _Base(numChannels)
301 {
302 init();
303 }
304 };
305
306
307
309 ConnectionState*
311 {
312 return new SimulatedOutputSequences(
314 }
315
319
325 {
326 REQUIRE (!isFree(), "diagnostic OutputSlot not (yet) connected");
327 REQUIRE (channel <= getOutputChannelCount());
328 return static_cast<TrackingInMemoryBlockSequence&> (state_->access (channel));
329 }
330
331
332 public:
336 static OutputSlot&
338 {
339 static lib::ScopedPtrVect<OutputSlot> diagnosticSlots;
340 return diagnosticSlots.manage(new DiagnosticOutputSlot);
341 }
342
344 access (OutputSlot& to_investigate)
345 {
346 return dynamic_cast<DiagnosticOutputSlot&> (to_investigate);
347 }
348
349
350
351 /* === diagnostics API === */
352
359 : public lib::IterSource<const TestFrame>
361 {
364
365
366 virtual Pos
367 firstResult () override
368 {
369 REQUIRE (0 == currentFrame_);
371 }
372
373 virtual void
374 nextResult (Pos& pos) override
375 {
378 }
379
380 public:
385 };
386
387 typedef OutputFramesLog::iterator OutFrames;
388
389
391 getChannel (uint channel)
392 {
393 REQUIRE (channel < MAX_CHANNELS);
395 new OutputFramesLog (
396 accessSequence(channel)));
397 }
398
399
400 bool
401 frame_was_allocated (uint channel, FrameID nominalFrame)
402 {
403 return accessSequence(channel)
404 .wasAllocated(nominalFrame);
405 }
406
407
408 bool
409 output_was_emitted (uint channel, FrameID outputFrame)
410 {
411 diagn::Block const *block = accessSequence(channel)
412 .accessEmittedBuffer(outputFrame);
413 return block
414 and block->was_used();
415 }
416
417
418 bool
419 output_was_closed (uint channel, FrameID outputFrame)
420 {
421 diagn::Block const *block = accessSequence(channel)
422 .accessEmittedBuffer(outputFrame);
423 return block
424 and block->was_closed();
425 }
426 };
427
428
429
430}} // namespace steam::play
431#endif
Expecting Advice and giving Advice: a cross-cutting collaboration of loosely coupled participants.
A front-end to support the buffer management within the render nodes.
Iteration source interface to abstract a data source, which then can be accessed through IterAdapter ...
static iterator build(IterSource &sourceImpl)
build an iterator frontend for the given source,
Customised refcounting smart pointer template, built upon std::shared_ptr, but forwarding type relati...
Definition p.hpp:77
Simple vector based collection of pointers, managing lifecycle of the pointed-to objects.
T & manage(T *obj)
take ownership of the given object, adding it at the end of the collection
Token or Atom with distinct identity.
Definition symbol.hpp:120
Framerate specified as frames per second.
basic constant internal time value.
static const Time ANYTIME
border condition marker value. ANYTIME <= any time value
Access point for the advised entity (client).
Definition advice.hpp:430
AD const & getAdvice() const
Definition advice.hpp:460
Interface: a grid and scale definition for time quantisation.
Definition time-grid.hpp:80
An opaque descriptor to identify the type and further properties of a data buffer.
Handle for a buffer for processing data, abstracting away the actual implementation.
void emitBuffer(BuffHandle const &)
BufferProvider API: state transition to emitted state.
BuffHandle lockBuffer(BuffDescr const &)
BufferProvider API: retrieve a single buffer for exclusive use.
void releaseBuffer(BuffHandle const &)
BufferProvider API: declare done and detach.
simple BufferProvider implementation with additional allocation tracking.
Helper for implementing a diagnostic BufferProvider: A block of heap allocated storage,...
Mock data frame for simulated rendering.
Definition testframe.hpp:69
diagnostic facility to verify test data frames written to this Test/Dummy "output".
virtual Pos firstResult() override
iteration start: prepare the first element.
OutputFramesLog(TrackingInMemoryBlockSequence const &bs)
virtual void nextResult(Pos &pos) override
iteration step: switch on to the next element.
Special diagnostic connection state implementation, establishing diagnostic output connections for ea...
void buildConnection(ConnectionStorage storage)
factory function to build the actual connection handling objects per channel
ConnectionManager< TrackingInMemoryBlockSequence > _Base
Helper for unit tests: Mock output sink.
TrackingInMemoryBlockSequence const & accessSequence(uint channel)
bool output_was_emitted(uint channel, FrameID outputFrame)
static OutputSlot & build()
build a new Diagnostic Output Slot instance, discard the existing one.
ConnectionState * buildState()
hook into the OutputSlot frontend
bool frame_was_allocated(uint channel, FrameID nominalFrame)
bool output_was_closed(uint channel, FrameID outputFrame)
static DiagnosticOutputSlot & access(OutputSlot &to_investigate)
Base for OutputSlot standard implementation.
Interface: Generic output sink.
unique_ptr< ConnectionState > state_
bool isFree() const
can this OutputSlot be allocated?
Diagnostic output connection for a single channel, allowing to track generated frames and verify the ...
void pushout(BuffHandle const &data4output)
TestFrame const & accessFrame(uint frameNr) const
bool isTimely(FrameID frameNr, TimeValue currentTime)
diagn::Block const * accessEmittedBuffer(uint bufferNr) const
void transfer(BuffHandle const &filledBuffer)
BuffHandle trackFrame(FrameID frameNr, BuffHandle const &newBuffer)
void discard(BuffHandle const &superseededData)
TestFrame const * accessEmittedFrame(uint frameNr) const
diagn::Block const & accessBlock(uint bufferNr) const
Any copy and copy construction prohibited.
Definition nocopy.hpp:38
Lumiera error handling (C++ interface).
unsigned int uint
Definition integral.hpp:29
Extension module to build an opaque data source, accessible as Lumiera Forward Iterator.
This header is for including and configuring NoBug.
FrameCnt FrameID
Steam-Layer implementation namespace root.
Test runner and basic definitions for tests.
bool contains(MAP &map, typename MAP::key_type const &key)
shortcut for containment test on a map
Definition util.hpp:230
OBJ * unConst(const OBJ *)
shortcut to save some typing when having to define const and non-const variants of member functions
Definition util.hpp:358
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Interface for concrete output implementations to talk to the OutputSlot frontend.
An (abstract) capability to send media data to an external output.
Managing lifecycle for a collection of objects.
Marker types to indicate a literal string and a Symbol.
Unit test helper to generate fake test data frames.
To establish a reference scale for quantised time values.
a family of time value like entities and their relationships.
Dummy implementation of the BufferProvider interface to support writing unit tests.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...