2011-08-15 00:52:56 +02:00
|
|
|
|
/*
|
|
|
|
|
|
TIMINGS.hpp - timing specifications for a frame quantised data stream
|
|
|
|
|
|
|
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
|
|
|
|
Copyright (C)
|
|
|
|
|
|
2011, Hermann Vosseler <Ichthyostega@web.de>
|
2011-08-15 00:52:56 +02:00
|
|
|
|
|
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
|
|
|
|
**Lumiera** is free software; you can redistribute it and/or modify it
|
|
|
|
|
|
under the terms of the GNU General Public License as published by the
|
|
|
|
|
|
Free Software Foundation; either version 2 of the License, or (at your
|
|
|
|
|
|
option) any later version. See the file COPYING for further details.
|
2011-08-15 00:52:56 +02:00
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/** @file timings.hpp
|
|
|
|
|
|
** How to define a timing specification or constraint.
|
2012-04-18 03:46:21 +02:00
|
|
|
|
** A timing spec is used to anchor a data stream with relation to a time axis or frame grid.
|
2011-08-15 00:52:56 +02:00
|
|
|
|
** There are two kinds of timing specs:
|
|
|
|
|
|
** - nominal timing specifications relate to the nominal time values
|
|
|
|
|
|
** of the frames in a data stream, i.e. the "should be" time values.
|
|
|
|
|
|
** These might be values derived from a timecode or just values in
|
|
|
|
|
|
** in relation to the timeline axis, but without any connection to
|
|
|
|
|
|
** the real wall clock time
|
|
|
|
|
|
** - actual timing specifications are always connected or related to
|
|
|
|
|
|
** an external time source, typically just wall clock time. For example,
|
|
|
|
|
|
** actual timing specs dictate the constraints for real time frame
|
|
|
|
|
|
** delivery to an external output connection.
|
|
|
|
|
|
**
|
2026-03-10 23:12:30 +01:00
|
|
|
|
** @todo WIP-WIP-WIP 3/2026 although this class is around for many years now,
|
|
|
|
|
|
** its actual meaning is still not well defined; sometimes it appears as a specification,
|
|
|
|
|
|
** while at places it also plays the role of a constraint.
|
|
|
|
|
|
** @see dispatcher.hpp
|
|
|
|
|
|
** @see output-slot.hpp
|
2011-08-15 00:52:56 +02:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-03-10 23:12:30 +01:00
|
|
|
|
#ifndef VAULT_OUT_TIMINGS_H
|
|
|
|
|
|
#define VAULT_OUT_TIMINGS_H
|
2011-08-15 00:52:56 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "lib/error.hpp"
|
|
|
|
|
|
//#include "lib/handle.hpp"
|
|
|
|
|
|
#include "lib/time/timevalue.hpp"
|
2018-11-15 23:42:43 +01:00
|
|
|
|
//#include "steam/engine/buffer-provider.hpp"
|
2011-08-15 00:52:56 +02:00
|
|
|
|
//#include "lib/iter-source.hpp"
|
|
|
|
|
|
//#include "lib/sync.hpp"
|
|
|
|
|
|
|
|
|
|
|
|
//#include <string>
|
|
|
|
|
|
//#include <vector>
|
2013-01-11 18:12:40 +01:00
|
|
|
|
#include <boost/rational.hpp>
|
2014-04-03 22:42:48 +02:00
|
|
|
|
#include <memory>
|
2011-08-15 00:52:56 +02:00
|
|
|
|
|
2012-02-06 02:49:54 +01:00
|
|
|
|
namespace lib {
|
|
|
|
|
|
namespace time{
|
|
|
|
|
|
class Quantiser;
|
2014-04-03 22:42:48 +02:00
|
|
|
|
typedef std::shared_ptr<const Quantiser> PQuant;
|
2012-02-06 02:49:54 +01:00
|
|
|
|
}}
|
2011-08-15 00:52:56 +02:00
|
|
|
|
|
2026-03-10 23:12:30 +01:00
|
|
|
|
namespace vault {
|
|
|
|
|
|
namespace out {
|
2011-08-15 00:52:56 +02:00
|
|
|
|
|
2013-11-18 00:01:43 +01:00
|
|
|
|
using lib::time::FrameCnt;
|
2012-02-06 02:49:54 +01:00
|
|
|
|
using lib::time::FrameRate;
|
|
|
|
|
|
using lib::time::TimeValue;
|
2012-02-09 04:52:09 +01:00
|
|
|
|
using lib::time::Duration;
|
|
|
|
|
|
using lib::time::Offset;
|
2012-03-02 01:33:57 +01:00
|
|
|
|
using lib::time::Time;
|
2011-08-15 00:52:56 +02:00
|
|
|
|
//using std::string;
|
|
|
|
|
|
|
|
|
|
|
|
//using std::vector;
|
2014-04-03 22:42:48 +02:00
|
|
|
|
//using std::shared_ptr;
|
2011-08-15 00:52:56 +02:00
|
|
|
|
|
2012-02-06 02:49:54 +01:00
|
|
|
|
enum PlaybackUrgency {
|
|
|
|
|
|
ASAP,
|
|
|
|
|
|
NICE,
|
|
|
|
|
|
TIMEBOUND
|
|
|
|
|
|
};
|
2011-08-15 00:52:56 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-10-24 23:06:36 +02:00
|
|
|
|
/*************************************************************************//**
|
2012-01-16 04:50:21 +01:00
|
|
|
|
* Generic frame timing specification. Defines the expected delivery interval,
|
2013-05-21 04:35:25 +02:00
|
|
|
|
* optionally also the expected quality-of-service (urgency).
|
2011-08-15 00:52:56 +02:00
|
|
|
|
*
|
|
|
|
|
|
* @note copyable value class
|
|
|
|
|
|
*
|
|
|
|
|
|
* @todo write type comment
|
2012-02-25 00:27:50 +01:00
|
|
|
|
* /////////////////////////////////////////////////////////////////TODO: WIP seems to become some kind of abstracted Grid representation!
|
2011-08-15 00:52:56 +02:00
|
|
|
|
*/
|
|
|
|
|
|
class Timings
|
|
|
|
|
|
{
|
2012-02-09 04:52:09 +01:00
|
|
|
|
lib::time::PQuant grid_;
|
2012-02-06 02:49:54 +01:00
|
|
|
|
|
2011-08-15 00:52:56 +02:00
|
|
|
|
public:
|
2012-02-06 02:49:54 +01:00
|
|
|
|
PlaybackUrgency playbackUrgency;
|
2013-11-18 00:01:43 +01:00
|
|
|
|
boost::rational<FrameCnt> playbackSpeed; /////////////TICKET #902 we need a more generic representation for variable speed playback
|
2023-04-17 04:51:38 +02:00
|
|
|
|
Time scheduledDelivery; ///< a wall clock time corresponding to the Grid's origin. Can be Time::Never (=not time bound)
|
2023-06-21 03:55:09 +02:00
|
|
|
|
Duration outputLatency; ///////////////TICKET #802 this information is necessary, but it is not clear who maintains and updates the latency
|
|
|
|
|
|
Duration engineLatency; ///< reasonable guess at the scheduling and dispatch-delay of the render engine
|
2012-02-06 02:49:54 +01:00
|
|
|
|
|
2013-06-15 04:02:48 +02:00
|
|
|
|
explicit
|
2012-02-06 02:49:54 +01:00
|
|
|
|
Timings (FrameRate fps);
|
|
|
|
|
|
|
2023-06-16 04:09:38 +02:00
|
|
|
|
Timings (FrameRate fps, Time realTimeAnchor);
|
|
|
|
|
|
|
2012-02-06 02:49:54 +01:00
|
|
|
|
// default copy acceptable
|
|
|
|
|
|
|
2013-06-15 04:02:48 +02:00
|
|
|
|
|
|
|
|
|
|
/** marker for halted output */
|
|
|
|
|
|
static Timings DISABLED;
|
|
|
|
|
|
|
2013-08-18 03:16:49 +02:00
|
|
|
|
Time getOrigin() const;
|
2012-02-09 04:52:09 +01:00
|
|
|
|
|
2013-11-18 00:01:43 +01:00
|
|
|
|
Time getFrameStartAt (FrameCnt frameNr) const;
|
2013-08-18 03:16:49 +02:00
|
|
|
|
Duration getFrameDurationAt (TimeValue refPoint) const;
|
2013-11-18 00:01:43 +01:00
|
|
|
|
Duration getFrameDurationAt (FrameCnt refFrameNr) const;
|
2012-02-06 02:49:54 +01:00
|
|
|
|
|
2023-05-31 03:27:13 +02:00
|
|
|
|
/** the next grid point at or after the given reference time */
|
|
|
|
|
|
FrameCnt getBreakPointAfter (TimeValue refPoint) const;
|
|
|
|
|
|
|
2012-02-09 04:52:09 +01:00
|
|
|
|
/** the frame spacing and duration remains constant for some time...
|
|
|
|
|
|
* @param startPoint looking from that time point into future
|
|
|
|
|
|
* @return duration after this starting point, where it's safe
|
|
|
|
|
|
* to assume unaltered frame dimensions */
|
|
|
|
|
|
Duration constantFrameTimingsInterval (TimeValue startPoint) const;
|
2012-02-06 02:49:54 +01:00
|
|
|
|
|
2013-01-11 18:12:40 +01:00
|
|
|
|
/** calculate the given frame's distance from origin,
|
|
|
|
|
|
* but do so using the real time scale, including any
|
2013-02-11 03:19:24 +01:00
|
|
|
|
* playback speed factor and similar corrections.
|
2013-01-11 18:12:40 +01:00
|
|
|
|
* @param frameOffset frame number relative to the implicit grid
|
|
|
|
|
|
* @return real time value relative to the implicit grid's zero point
|
|
|
|
|
|
* @note since the Timings don't contain any information relating the
|
|
|
|
|
|
* nominal time scale to wall clock time, this result is just
|
|
|
|
|
|
* a relative offset, but expressed in real time scale values
|
2018-11-15 23:59:23 +01:00
|
|
|
|
* @see steam::engine::TimeAnchor for an absolutely anchored conversion
|
2013-01-11 18:12:40 +01:00
|
|
|
|
*/
|
2013-11-18 00:01:43 +01:00
|
|
|
|
Offset getRealOffset (FrameCnt frameOffset) const;
|
2013-01-11 18:12:40 +01:00
|
|
|
|
|
2013-01-12 08:36:35 +01:00
|
|
|
|
/** real time deadline for the given frame, without any latency.
|
|
|
|
|
|
* This value is provided in case of scheduled time of delivery,
|
2013-10-25 06:34:38 +02:00
|
|
|
|
* which is signalled by `playbackUrgency == TIMEBOUND`
|
2013-01-12 08:36:35 +01:00
|
|
|
|
* @return wall clock time to expect delivery of data
|
|
|
|
|
|
* corresponding to a frame specified relative
|
2023-05-29 04:43:10 +02:00
|
|
|
|
* to [time axis origin](\ref #getOrigin)
|
|
|
|
|
|
* @note for other playback urgencies `Time::NEVER` is returned
|
2025-06-07 23:59:57 +02:00
|
|
|
|
*
|
2013-02-11 03:19:24 +01:00
|
|
|
|
* @warning not clear as of 1/13 if it is even possible to have such a function
|
2025-06-07 23:59:57 +02:00
|
|
|
|
* on the Timings record.
|
2013-01-12 08:36:35 +01:00
|
|
|
|
*/
|
2013-11-18 00:01:43 +01:00
|
|
|
|
Time getTimeDue(FrameCnt frameOffset) const;
|
2013-01-12 08:36:35 +01:00
|
|
|
|
|
|
|
|
|
|
/** the minimum time span to be covered by frame calculation jobs
|
|
|
|
|
|
* planned in one sway. The ongoing planning of additional jobs
|
|
|
|
|
|
* proceeds in chunks of jobs added at once to the schedule.
|
|
|
|
|
|
* This setting defines the minimum time to plan ahead; after
|
|
|
|
|
|
* covering at least this time span with new jobs, the
|
|
|
|
|
|
* frame dispatcher concludes "enough for now" and emits
|
|
|
|
|
|
* a continuation job for the next planning chunk.
|
2012-04-20 04:05:41 +02:00
|
|
|
|
*/
|
2013-01-12 08:36:35 +01:00
|
|
|
|
Duration getPlanningChunkDuration() const;
|
2012-04-20 04:05:41 +02:00
|
|
|
|
|
2013-01-12 12:38:33 +01:00
|
|
|
|
/** establish the time point to anchor the next planning chunk,
|
|
|
|
|
|
* in accordance with #getPlanningChunkDuration
|
2023-05-29 04:43:10 +02:00
|
|
|
|
* @param anchorFrame frame number where the current planning chunk started
|
2013-01-12 12:38:33 +01:00
|
|
|
|
* @return number of the first frame, which is located strictly more than
|
|
|
|
|
|
* the planning chunk duration into the future
|
|
|
|
|
|
* @remarks this value is used by the frame dispatcher to create a
|
|
|
|
|
|
* follow-up planning job */
|
2023-05-29 04:43:10 +02:00
|
|
|
|
FrameCnt establishNextPlanningChunkStart(FrameCnt anchorFrame) const;
|
2013-01-12 12:38:33 +01:00
|
|
|
|
|
2012-04-20 04:05:41 +02:00
|
|
|
|
|
2013-01-11 18:12:40 +01:00
|
|
|
|
bool isOriginalSpeed() const;
|
2023-05-31 03:27:13 +02:00
|
|
|
|
bool isTimebound() const;
|
2013-01-11 18:12:40 +01:00
|
|
|
|
|
|
|
|
|
|
|
2013-11-18 02:25:27 +01:00
|
|
|
|
/** Consistency self-check */
|
|
|
|
|
|
bool isValid() const;
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-01-16 04:50:21 +01:00
|
|
|
|
//////////////TODO further accessor functions here
|
2011-12-17 04:45:42 +01:00
|
|
|
|
|
2012-03-02 01:33:57 +01:00
|
|
|
|
Timings constrainedBy (Timings additionalConditions);
|
|
|
|
|
|
|
2011-08-15 00:52:56 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-01-11 18:12:40 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
|
|
Timings::isOriginalSpeed() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return 1 == playbackSpeed;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-05-31 03:27:13 +02:00
|
|
|
|
inline bool
|
|
|
|
|
|
Timings::isTimebound() const
|
|
|
|
|
|
{
|
2026-03-10 23:12:30 +01:00
|
|
|
|
return out::TIMEBOUND == playbackUrgency;
|
2023-05-31 03:27:13 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2013-01-11 18:12:40 +01:00
|
|
|
|
|
|
|
|
|
|
|
2026-03-10 23:12:30 +01:00
|
|
|
|
}} // namespace vault::out
|
|
|
|
|
|
#endif /*VAULT_OUT_TIMINGS_H*/
|