diff --git a/src/proc/engine/calc-plan-continuation.cpp b/src/proc/engine/calc-plan-continuation.cpp index 549feaa56..9c72a0629 100644 --- a/src/proc/engine/calc-plan-continuation.cpp +++ b/src/proc/engine/calc-plan-continuation.cpp @@ -58,10 +58,12 @@ namespace engine { bool CalcPlanContinuation::verify (Time nominalTime, InvocationInstanceID invoKey) const { - UNIMPLEMENTED ("verify the planning coordinates"); - return false; + return timings_.isValid() + && Time::MIN < nominalTime && nominalTime < Time::MAX + && nominalTime == timings_.getFrameStartAt (invoKey.frameNumber); } + size_t CalcPlanContinuation::hashOfInstance (InvocationInstanceID invoKey) const { diff --git a/src/proc/engine/calc-plan-continuation.hpp b/src/proc/engine/calc-plan-continuation.hpp index c75fd3adf..19b4ab8a9 100644 --- a/src/proc/engine/calc-plan-continuation.hpp +++ b/src/proc/engine/calc-plan-continuation.hpp @@ -59,7 +59,6 @@ namespace engine { */ class CalcPlanContinuation : public JobClosure - , boost::noncopyable { play::Timings const& timings_; diff --git a/src/proc/engine/dispatch-table.cpp b/src/proc/engine/dispatch-table.cpp index 7b5a5bb82..ef92d2236 100644 --- a/src/proc/engine/dispatch-table.cpp +++ b/src/proc/engine/dispatch-table.cpp @@ -31,6 +31,23 @@ namespace proc { namespace engine { /** */ + FrameCoord + DispatchTable::locateRelative (FrameCoord const&, FrameCnt frameOffset) + { + UNIMPLEMENTED ("real implementation of the core dispatch operation"); + } + + bool + DispatchTable::isEndOfChunk (FrameCnt, ModelPort port) + { + UNIMPLEMENTED ("determine when to finish a planning chunk"); + } + + JobTicket& + DispatchTable::accessJobTicket (ModelPort, TimeValue nominalTime) + { + UNIMPLEMENTED ("hook into the real implementation of the model backbone / segmentation"); + } diff --git a/src/proc/engine/dispatch-table.hpp b/src/proc/engine/dispatch-table.hpp index 1c428542c..57b3324e7 100644 --- a/src/proc/engine/dispatch-table.hpp +++ b/src/proc/engine/dispatch-table.hpp @@ -44,6 +44,14 @@ namespace engine { class DispatchTable : public Dispatcher { + + /* ==== Dispatcher interface ==== */ + + FrameCoord locateRelative (FrameCoord const&, FrameCnt frameOffset); + bool isEndOfChunk (FrameCnt, ModelPort port); + JobTicket& accessJobTicket (ModelPort, TimeValue nominalTime); + + protected: /** timerange covered by this RenderGraph */ TimeSpan segment_; diff --git a/src/proc/engine/dispatcher.cpp b/src/proc/engine/dispatcher.cpp index 463d2124b..f79042c9e 100644 --- a/src/proc/engine/dispatcher.cpp +++ b/src/proc/engine/dispatcher.cpp @@ -38,15 +38,24 @@ namespace engine { Dispatcher::JobBuilder Dispatcher::onCalcStream (ModelPort modelPort, uint channel) { - UNIMPLEMENTED ("build coordinates of frame to render"); + JobBuilder builder = {this, modelPort,channel}; + return builder; } /** */ FrameCoord - Dispatcher::JobBuilder::relativeFrameLocation (TimeAnchor& refPoint, uint frameCountOffset) + Dispatcher::JobBuilder::relativeFrameLocation (TimeAnchor& refPoint, FrameCnt frameOffset) { - UNIMPLEMENTED ("build coordinates of frame to render"); + FrameCoord frame; + frame.absoluteNominalTime = refPoint; + frame.absoluteFrameNumber = refPoint.getStartFrame(); + frame.absoluteRealDeadline = refPoint.establishDeadlineFor (frameOffset); + frame.modelPort = this->modelPort_; + frame.channelNr = this->channel_; + + ENSURE (frame.isDefined()); + return dispatcher_->locateRelative (frame, frameOffset); } diff --git a/src/proc/engine/dispatcher.hpp b/src/proc/engine/dispatcher.hpp index 902cbfd2e..0d8c7f7ee 100644 --- a/src/proc/engine/dispatcher.hpp +++ b/src/proc/engine/dispatcher.hpp @@ -75,18 +75,18 @@ namespace engine { { struct JobBuilder { - Dispatcher& dispatcher_; + Dispatcher* dispatcher_; ModelPort modelPort_; uint channel_; - FrameCoord relativeFrameLocation (TimeAnchor& refPoint, uint frameCountOffset =0); + FrameCoord relativeFrameLocation (TimeAnchor& refPoint, FrameCnt frameCountOffset =0); JobPlanningSequence establishNextJobs (TimeAnchor& refPoint) { return JobPlanningSequence( relativeFrameLocation(refPoint), - dispatcher_); + *dispatcher_); } }; @@ -98,10 +98,14 @@ namespace engine { protected: - virtual FrameCoord locateRelative (FrameCoord, uint frameCountOffset) =0; - virtual FrameCoord locateRelative (TimeAnchor, uint frameCountOffset) =0; //////////TODO is this really an interface operation, or just a convenience shortcut? + /** core dispatcher operation: based on the coordinates of a reference point, + * establish binding frame number, nominal time and real (wall clock) deadline. + * @return new FrameCoord record (copy), with the nominal time, frame number + * and deadline adjusted in accordance to the given frame offset. + */ + virtual FrameCoord locateRelative (FrameCoord const&, FrameCnt frameOffset) =0; - virtual bool isEndOfChunk (FrameCnt, ModelPort port) =0; + virtual bool isEndOfChunk (FrameCnt, ModelPort port) =0; ////////TODO: API-1 = just get next frame, without limitations .... CHECK ////////TODO: API-2 = query limitation of planning chunk .... CHECK diff --git a/src/proc/engine/frame-coord.hpp b/src/proc/engine/frame-coord.hpp index 8aabee8a4..49a9550c5 100644 --- a/src/proc/engine/frame-coord.hpp +++ b/src/proc/engine/frame-coord.hpp @@ -73,6 +73,7 @@ namespace engine { FrameCoord() : absoluteNominalTime(Time::NEVER) , absoluteFrameNumber(std::numeric_limits::max()) + , absoluteRealDeadline(Time::NEVER) , modelPort() // unconnected , channelNr(0) { } @@ -113,7 +114,7 @@ namespace engine { } protected: - virtual FrameCoord locateRelative (FrameCoord, uint frameCountOffset) =0; + virtual FrameCoord locateRelative (FrameCoord const&, FrameCnt frameOffset) =0; }; diff --git a/src/proc/engine/time-anchor.hpp b/src/proc/engine/time-anchor.hpp index 994bec648..2cded87ea 100644 --- a/src/proc/engine/time-anchor.hpp +++ b/src/proc/engine/time-anchor.hpp @@ -157,14 +157,32 @@ namespace engine { } + /** define the deadline for a grid point relative to this reference point. + * Since a TimeAnchor represents the definitive link between nominal time + * and ongoing wall clock time, and since all of the current output stream + * related timing information is available -- including the engine and the + * output latency -- this is the place to do the final decision. + * @param frameOffset frame count offset relative to this TimeAnchor point + * @return the latest real absolute wall clock time at which this frame + * has to be delivered to the OutputSlot. This deadline is exclusive, + * i.e. time < deadline is required. + */ + Time + establishDeadlineFor (FrameCnt frameOffset) + { + return this->relatedRealTime_ + + timings_.getRealOffset(frameOffset); + } + + + /** convenience shortcut, employing the deadline calculation in relation + * to current wall clock time */ Offset remainingRealTimeFor (FrameCoord plannedFrame) - //////////////////////////////////////////////////TODO break this into two sensible operations, using the deadline from the FrameCoord { FrameCnt frameOffset = plannedFrame.absoluteFrameNumber - anchorPoint_; - return Offset(this->relatedRealTime_ - + timings_.getRealOffset(frameOffset) - - RealClock::now()); + return Offset(RealClock::now() + ,establishDeadlineFor(frameOffset)); } }; diff --git a/src/proc/play/timings.cpp b/src/proc/play/timings.cpp index 8293ee020..de12984d6 100644 --- a/src/proc/play/timings.cpp +++ b/src/proc/play/timings.cpp @@ -78,6 +78,20 @@ namespace play { Timings Timings::DISABLED(FrameRate::HALTED); + + /** @internal typically invoked from assertions */ + bool + Timings::isValid() const + { + return bool(grid_) + && (( (ASAP == playbackUrgency || NICE == playbackUrgency) + && Time::NEVER == scheduledDelivery) + || + (TIMEBOUND == playbackUrgency + && Time::MIN < scheduledDelivery && scheduledDelivery < Time::MAX) + ); + } + Time Timings::getOrigin() const { diff --git a/src/proc/play/timings.hpp b/src/proc/play/timings.hpp index efd6e1c2a..6a2870bdd 100644 --- a/src/proc/play/timings.hpp +++ b/src/proc/play/timings.hpp @@ -180,6 +180,10 @@ namespace play { bool isOriginalSpeed() const; + /** Consistency self-check */ + bool isValid() const; + + //////////////TODO further accessor functions here Timings constrainedBy (Timings additionalConditions); diff --git a/tests/core/proc/engine/dispatcher-interface-test.cpp b/tests/core/proc/engine/dispatcher-interface-test.cpp index c78551cea..a024092ae 100644 --- a/tests/core/proc/engine/dispatcher-interface-test.cpp +++ b/tests/core/proc/engine/dispatcher-interface-test.cpp @@ -80,17 +80,7 @@ namespace test { /* == mock Dispatcher implementation == */ FrameCoord - locateFrameNext (uint frameCountOffset, TimeAnchor refPoint) - { - UNIMPLEMENTED ("dummy implementation of the core dispatch operation"); - } - FrameCoord - locateRelative (FrameCoord, uint frameCountOffset) - { - UNIMPLEMENTED ("dummy implementation of the core dispatch operation"); - } - FrameCoord - locateRelative (TimeAnchor, uint frameCountOffset) + locateRelative (FrameCoord const&, FrameCnt frameOffset) { UNIMPLEMENTED ("dummy implementation of the core dispatch operation"); }