Lumiera  0.pre.03
»edityourfreedom«
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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) Lumiera.org
5  2011, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
30 #ifndef PROC_PLAY_DIAGNOSTIC_OUTPUT_SLOT_H
31 #define PROC_PLAY_DIAGNOSTIC_OUTPUT_SLOT_H
32 
33 
34 #include "lib/error.hpp"
35 #include "lib/nocopy.hpp"
36 #include "include/logging.h"
42 #include "lib/time/timevalue.hpp"
43 #include "lib/scoped-ptrvect.hpp"
44 #include "lib/iter-source.hpp"
45 #include "lib/symbol.hpp"
46 #include "lib/util.hpp"
47 #include "common/advice.hpp"
49 //#include "lib/sync.hpp"
50 
51 //#include <string>
52 //#include <vector>
53 #include <unordered_set>
54 #include <memory>
55 
56 
57 namespace proc {
58 namespace play {
59 
60 //using std::string;
61  using lib::Symbol;
62  using util::unConst;
63  using util::contains;
70  namespace diagn = proc::engine::diagn;
71 
72 //using std::vector;
73  using std::shared_ptr;
74 
75  namespace { // diagnostics & internals....
76 
77  inline PGrid
78  getTestTimeGrid()
79  {
80  Symbol gridID("DiagnosticOutputSlot-buffer-grid");
81  lumiera::advice::Request<PGrid> query4grid(gridID) ;
82  PGrid testGrid25 = query4grid.getAdvice();
83 
84  if (!testGrid25)
85  testGrid25 = TimeGrid::build (gridID, FrameRate::PAL);
86 
87  ENSURE (testGrid25);
88  return testGrid25;
89  }
90  }
91 
92 
99  : public OutputSlot::Connection
101  {
102 
103  typedef std::unordered_set<FrameID> FrameTrackingInfo;
104 
105 
108 
109  FrameTrackingInfo frameTrackingIndex_;
111 
112  bool closed_;
113 
114 
115  BuffHandle
116  trackFrame (FrameID frameNr, BuffHandle const& newBuffer)
117  {
118  TRACE (test, "Con=%p : track buffer %zu for frame-#%lu"
119  , this, newBuffer.entryID(), frameNr);
120  REQUIRE (!contains (frameTrackingIndex_,frameNr),
121  "attempt to lock already used frame %lu", frameNr);
122 
123  frameTrackingIndex_.insert (frameNr);
124  return newBuffer;
125  }
126 
127  TimeValue
129  {
130  // a real world implementation
131  // would offset by a latency here
132  return frameGrid_->timeOf (frameNr);
133  }
134 
135 
136 
137 
138  /* === Connection API === */
139 
140  BuffHandle
142  {
143  TRACE (test, "Con=%p : lock buffer for frame-#%lu", this, frameNr);
144  REQUIRE (!closed_);
145 
146  return trackFrame (frameNr,
147  buffProvider_.lockBuffer (bufferType_));
148  }
149 
150 
151  bool
152  isTimely (FrameID frameNr, TimeValue currentTime)
153  {
154  TRACE (test, "Con=%p : timely? frame-#%lu"
155  , this, frameNr);
156 
157  if (Time::ANYTIME == currentTime)
158  return true;
159  else
160  return currentTime < deadlineFor (frameNr);
161  }
162 
163  void
164  transfer (BuffHandle const& filledBuffer)
165  {
166  TRACE (test, "Con=%p : transfer buffer %zu"
167  , this, filledBuffer.entryID());
168  REQUIRE (!closed_);
169 
170  pushout (filledBuffer);
171  }
172 
173  void
174  pushout (BuffHandle const& data4output)
175  {
176  REQUIRE (!closed_);
177  buffProvider_.emitBuffer (data4output);
178  buffProvider_.releaseBuffer(data4output);
179  }
180 
181  void
182  discard (BuffHandle const& superseededData)
183  {
184  REQUIRE (!closed_);
185  buffProvider_.releaseBuffer (superseededData);
186  }
187 
188  void
190  {
191  closed_ = true;
192  }
193 
194  public:
196  : buffProvider_()
197  , bufferType_(buffProvider_.getDescriptor<TestFrame>())
198  , frameTrackingIndex_()
199  , frameGrid_(getTestTimeGrid())
200  , closed_(false)
201  {
202  INFO (engine_dbg, "building in-memory diagnostic output sequence (at %p)", this);
203  }
204 
205  virtual
207  {
208  INFO (engine_dbg, "releasing diagnostic output sequence (at %p)", this);
209  }
210 
211 
212  /* === Diagnostic API === */
213 
214  TestFrame const *
215  accessEmittedFrame (uint frameNr) const
216  {
217  if (frameNr < buffProvider_.emittedCnt())
218  return & accessFrame(frameNr);
219  else
220  return 0;
221  }
222 
223  diagn::Block const *
224  accessEmittedBuffer (uint bufferNr) const
225  {
226  if (bufferNr < buffProvider_.emittedCnt())
227  return & accessBlock(bufferNr);
228  else
229  return 0;
230  }
231 
232  bool
233  wasAllocated (uint frameNr) const
234  {
235  TRACE (test, "query wasAllocated. Con=%p", this);
236 
237  return contains (frameTrackingIndex_, frameNr);
238  }
239 
240  private:
241  TestFrame const&
242  accessFrame (uint frameNr) const
243  {
244  return unConst(this)->buffProvider_.accessAs<TestFrame> (frameNr);
245  }
246 
247  diagn::Block const&
248  accessBlock (uint bufferNr) const
249  {
250  return unConst(this)->buffProvider_.access_emitted (bufferNr);
251  }
252  };
253 
254 
255 
256 
257 
258 
259 
260 
261 
262  /****************************************************************/
276  : public OutputSlotImplBase
277  {
278 
279  static const uint MAX_CHANNELS = 5;
280 
284  uint
286  {
287  return MAX_CHANNELS;
288  }
289 
290 
297  : public ConnectionManager<TrackingInMemoryBlockSequence>
298  {
299  typedef ConnectionManager<TrackingInMemoryBlockSequence> _Base;
300 
301  void
302  buildConnection(ConnectionStorage storage)
303  {
304  storage.create<TrackingInMemoryBlockSequence>();
305  }
306 
307  public:
308  SimulatedOutputSequences (uint numChannels)
309  : _Base(numChannels)
310  {
311  init();
312  }
313  };
314 
315 
316 
318  ConnectionState*
320  {
321  return new SimulatedOutputSequences(
323  }
324 
328 
333  accessSequence (uint channel)
334  {
335  REQUIRE (!isFree(), "diagnostic OutputSlot not (yet) connected");
336  REQUIRE (channel <= getOutputChannelCount());
337  return static_cast<TrackingInMemoryBlockSequence&> (state_->access (channel));
338  }
339 
340 
341  public:
345  static OutputSlot&
347  {
348  static lib::ScopedPtrVect<OutputSlot> diagnosticSlots;
349  return diagnosticSlots.manage(new DiagnosticOutputSlot);
350  }
351 
352  static DiagnosticOutputSlot&
353  access (OutputSlot& to_investigate)
354  {
355  return dynamic_cast<DiagnosticOutputSlot&> (to_investigate);
356  }
357 
358 
359 
360  /* === diagnostics API === */
361 
368  : public lib::IterSource<const TestFrame>
370  {
373 
374 
375  virtual Pos
376  firstResult () override
377  {
378  REQUIRE (0 == currentFrame_);
379  return outSeq_.accessEmittedFrame (currentFrame_);
380  }
381 
382  virtual void
383  nextResult (Pos& pos) override
384  {
385  ++currentFrame_;
386  pos = outSeq_.accessEmittedFrame(currentFrame_);
387  }
388 
389  public:
391  : outSeq_(bs)
392  , currentFrame_(0)
393  { }
394  };
395 
397 
398 
399  OutFrames
400  getChannel (uint channel)
401  {
402  REQUIRE (channel < MAX_CHANNELS);
403  return OutputFramesLog::build(
404  new OutputFramesLog (
405  accessSequence(channel)));
406  }
407 
408 
409  bool
410  frame_was_allocated (uint channel, FrameID nominalFrame)
411  {
412  return accessSequence(channel)
413  .wasAllocated(nominalFrame);
414  }
415 
416 
417  bool
418  output_was_emitted (uint channel, FrameID outputFrame)
419  {
420  diagn::Block const *block = accessSequence(channel)
421  .accessEmittedBuffer(outputFrame);
422  return block
423  && block->was_used();
424  }
425 
426 
427  bool
428  output_was_closed (uint channel, FrameID outputFrame)
429  {
430  diagn::Block const *block = accessSequence(channel)
431  .accessEmittedBuffer(outputFrame);
432  return block
433  && block->was_closed();
434  }
435  };
436 
437 
438 
439 }} // namespace proc::play
440 #endif
simple BufferProvider implementation with additional allocation tracking.
static const Time ANYTIME
border condition marker value. ANYTIME <= any time value
Definition: timevalue.hpp:240
diagn::Block const & accessBlock(uint bufferNr) const
Helper for implementing a diagnostic BufferProvider: A block of heap allocated storage, with the capability to store some additional tracking information.
An (abstract) capability to send media data to an external output.
Access point for the advised entity (client).
Definition: advice.hpp:426
bool isTimely(FrameID frameNr, TimeValue currentTime)
ConnectionState * buildState()
hook into the OutputSlot frontend
Definition: run.hpp:49
Framerate specified as frames per second.
Definition: timevalue.hpp:547
std::shared_ptr< const Grid > PGrid
Definition: grid.hpp:78
static PGrid build(Symbol gridID, FrameRate frames_per_second)
Definition: time-grid.cpp:164
TestFrame const & accessFrame(uint frameNr) const
Any copy and copy construction prohibited.
Definition: nocopy.hpp:46
An opaque descriptor to identify the type and further properties of a data buffer.
Definition: buffhandle.hpp:81
virtual void nextResult(Pos &pos) override
iteration step: switch on to the next element.
ConnectionManager< TrackingInMemoryBlockSequence > _Base
typename meta::Strip< CON >::TypeReferred::iterator iterator
This header is for including and configuring NoBug.
Managing lifecycle for a collection of objects.
diagnostic facility to verify test data frames written to this Test/Dummy "output".
bool output_was_emitted(uint channel, FrameID outputFrame)
Diagnostic output connection for a single channel, allowing to track generated frames and verify the ...
Simple vector based collection of pointers, managing lifecycle of the pointed-to objects.
diagn::Block const * accessEmittedBuffer(uint bufferNr) const
Handle for a buffer for processing data, abstracting away the actual implementation.
Definition: buffhandle.hpp:111
lib::P< TimeGrid > PGrid
Definition: time-grid.hpp:71
TRACE(test,"inserted %d", data)
bool output_was_closed(uint channel, FrameID outputFrame)
TestFrame const * accessEmittedFrame(uint frameNr) const
Mock data frame for simulated rendering.
Definition: testframe.hpp:60
Token or Atom with distinct identity.
Definition: symbol.hpp:116
Iteration source interface to abstract a data source, which then can be accessed through IterAdapter ...
Definition: iter-source.hpp:88
void releaseBuffer(BuffHandle const &)
BufferProvider API: declare done and detach.
Mix-Ins to allow or prohibit various degrees of copying and cloning.
bool contains(MAP &map, typename MAP::key_type const &key)
shortcut for containment test on a map
Definition: util.hpp:205
Expecting Advice and giving Advice: a cross-cutting collaboration of loosely coupled participants...
Interface: a grid and scale definition for time quantisation.
Definition: time-grid.hpp:85
unique_ptr< ConnectionState > state_
Marker types to indicate a literal string and a Symbol.
TrackingInMemoryBlockSequence const & accessSequence(uint channel)
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...
HashVal entryID() const
Definition: buffhandle.hpp:162
Helper for unit tests: Mock output sink.
void transfer(BuffHandle const &filledBuffer)
bool frame_was_allocated(uint channel, FrameID nominalFrame)
virtual Pos firstResult() override
iteration start: prepare the first element.
Interface: Generic output sink.
Interface for concrete output implementations to talk to the OutputSlot frontend. ...
Special diagnostic connection state implementation, establishing diagnostic output connections for ea...
A front-end to support the buffer management within the render nodes.
bool isFree() const
can this OutputSlot be allocated?
Definition: output-slot.cpp:61
Lumiera error handling (C++ interface).
BuffHandle lockBuffer(BufferDescriptor const &)
BufferProvider API: retrieve a single buffer for exclusive use.
OBJ * unConst(const OBJ *o)
shortcut to save some typing when having to define const and non-const variants of member functions ...
Definition: util.hpp:319
void pushout(BuffHandle const &data4output)
static iterator build(IterSource &sourceImpl)
build an iterator frontend for the given source,
BuffHandle trackFrame(FrameID frameNr, BuffHandle const &newBuffer)
Establishing a reference scale for quantised time values.
static OutputSlot & build()
build a new Diagnostic Output Slot instance, discard the existing one.
OutputFramesLog(TrackingInMemoryBlockSequence const &bs)
void emitBuffer(BuffHandle const &)
BufferProvider API: state transition to emitted state.
Base for OutputSlot standard implementation.
void discard(BuffHandle const &superseededData)
Proc-Layer implementation namespace root.
Definition: id-scheme.hpp:63
a family of time value like entities and their relationships.
Unit test helper to generate fake test data frames.
Extension module to build an opaque data source, accessible as Lumiera Forward Iterator.
basic constant internal time value.
Definition: timevalue.hpp:80
ENSURE(r==&pq)
T & manage(T *obj)
take ownership of the given object, adding it at the end of the collection
static DiagnosticOutputSlot & access(OutputSlot &to_investigate)
static const FrameRate PAL
predefined constant for PAL framerate
Definition: timevalue.hpp:561
FrameCnt FrameID
Definition: output-slot.hpp:93