Lumiera  0.pre.03
»edit your freedom«
timevalue.hpp File Reference

Go to the source code of this file.

Description

a family of time value like entities and their relationships.

This is the foundation for the Lumiera time handling framework. On the implementation level, time values are represented as 64bit integer values gavl_time_t. But for the actual use, we create several kinds of time "values", based on their logical properties. These time values are considered to be fixed (immutable) values, which may only be created through some limited construction paths, and any time based calculation is forced to go through our time calculation library. This is prerequisite for the definition of frame aligned time values and time code representation implemented as display format based on these frame quantised time values.

Time entities

The value types defined in this header represent time points and time intervals based on an internal time scale (µs ticks) and not related to any known fixed time zone or time base; rather they are interpreted in usage context, and the intended way to retrieve such a value is by formatting it into a time code format.

The lib::time::TimeValue serves as foundation for all further time calculations; in fact it is implemented as a single 64bit µ-tick value (gavl_time_t). The further time entities are implemented as value objects (without virtual functions):

  • lib::time::Time represents a time instant and is the reference for any usage
  • lib::time::TimeVar is a mutable time variable and can be used for calculations
  • lib::time::Offset can be used to express a positive or negative shift on time scale
  • lib::time::Duration represents the extension or an amount of time
  • lib::time::TimeSpan represents a distinct interval, with start time and duration
  • lib::time::FrameRate can be used to mark a number to denote a frames-per-second spec
  • lib::time::FSecs is a rational number to represent seconds or fractions thereof

Manipulating time values

Time values are conceived as fixed, immutable entities, similar to numbers; you can't just change the number two, and likewise, two seconds are two seconds. However, for many use cases we have to combine time values to perform calculations

  • Time entities can be combined with operators, to form new time entities
  • the TimeVar can be used as accumulator or variable for ongoing calculations
  • since TimeSpan, Duration (and the grid-aligned, "quantised" flavours) will often represent some time-like property or entity, e.g. the temporal specification of a media Clip with start and duration, there is the concept of an explicit mutation, which is accepted by these entities. Notably the lib::time::Control can be attached to these entities, and can then receive manipulations (nudging, offset); moreover it is possible to attach as listener to such a "controller" and be notified by any manipulation; this setup is the base for running time display, playback cursors etc.

Quantised time

While these internal time values can be considered sufficiently precise, in practice any time specifications in the context of media handling will be aligned to some grid, and expressed in a time code format. Typically, we want to know the number of frames since playback started at the beginning of the timeline, and such a specification also relies on some implicitly known frame rate (24fps for film in US, 25fps for film and TV in Europe, ...). By deliberate choice, in Lumiera we do not incorporate such implicit assumptions into the actual time values. Rather, they need to be made explicitly in the relevant usage context. This is also the reason why the time entities defined in this header do not offer an API to get the "real" time (whatever this means). Rather, the user of these time entities should get used to the concept that these abstract opaque values are the real thing, and a concrete, human readable time code is only a derivation, and any such derivation also incurs information loss. To reiterate that, any time quantisation is a lossy information; grid aligned values are not "cleaner", they are just easier to handle for humans.

how can I extract a time value?
Taking the aforementioned into account, it depends on the context what to expect and to get
  • the standard path is to create a lib::time::QuTime by associating the internal time value with a pre-defined time grid. From there you can call QuTime::formatAs() to build an actual timecode instance, which can then be investigated or just printed.
  • for debugging purpose, lib::time::Time defines an operator string(), which breaks down the internal values into the format -hh:mm:ss.mss
  • advanced calculations with the need to access the implementation data in full precision should go through lib::time::TimeVar, which offers conversions to raw int64_t and the even more fine grained FSec, which is a rational (fraction) boost::rational<int64_t>
See also
time.h basic time calculation library functions
timequant.hpp
TimeValue_test

Definition in file timevalue.hpp.

#include "lib/error.hpp"
#include <boost/operators.hpp>
#include <boost/rational.hpp>
#include <cstdlib>
#include <string>
#include <stdint.h>
#include <gavl/gavltime.h>

Classes

class  Duration
 Duration is the internal Lumiera time metric. More...
 
class  FrameRate
 Framerate specified as frames per second. More...
 
class  Offset
 Offset measures a distance in time. More...
 
struct  StringConv< X, COND >
 failsafe invocation of custom string conversion. More...
 
struct  StringConv< lib::time::FSecs, void >
 specialisation: render fractional seconds (for diagnostics) More...
 
class  Time
 Lumiera's internal time value datatype. More...
 
class  TimeSpan
 A time interval anchored at a specific point in time. More...
 
class  TimeValue
 basic constant internal time value. More...
 
class  TimeVar
 a mutable time value, behaving like a plain number, allowing copy and re-accessing More...
 

Typedefs

using FSecs = boost::rational< int64_t >
 rational representation of fractional seconds More...
 

Functions

template<typename NUM >
NUM __ensure_nonzero (NUM n)
 
boost::rational< uint > __framerate_approximation (double fps)
 
boost::rational< uint > __framerate_approximation (size_t cnt, Duration timeReference)
 
HashVal hash_value (TimeValue const &time)
 derive a hash from the µ-tick value More...
 
bool isnil (lib::time::Duration const &dur)
 
template<typename FAC >
Offset operator* (Offset const &distance, FAC factor)
 
template<typename INT >
Offset operator* (INT factor, Offset const &o)
 
template<typename INTX >
Offset operator* (boost::rational< INTX > factor, Offset const &offset)
 
Offset operator* (double factor, Offset const &offset)
 
template<typename NUM >
Offset operator* (NUM factor, Duration const &dur)
 
template<typename NUM >
Offset operator* (Duration const &dur, NUM factor)
 
Offset operator+ (Offset const &start, Offset const &toChain)
 
Duration operator+ (Duration const &base, Duration const &toAdd)
 
Offset operator- (Offset const &start, Offset const &toSubtract)
 
Duration operator- (Duration const &base, Duration const &toRemove)
 
FSecs operator/ (int n, FrameRate rate)
 convenient conversion to duration in fractional seconds
 
gavl_time_t symmetricLimit (gavl_time_t raw, TimeValue lim)
 

Namespaces

 lib
 Implementation namespace for support and library code.
 

Typedef Documentation

◆ FSecs

using FSecs = boost::rational<int64_t>

rational representation of fractional seconds

Warning
do not mix up gavl_time_t and FSecs

Definition at line 229 of file timevalue.hpp.

Function Documentation

◆ hash_value()

HashVal lib::time::hash_value ( TimeValue const &  time)
inline

derive a hash from the µ-tick value

Returns
rotation of the raw value to produce a suitable spacing for consecutive time
Remarks
picked up by Boost-hash, or std. hashtables with the help of hash-standard.h
See also
https://stackoverflow.com/a/31488147

Definition at line 734 of file timevalue.hpp.

References TimeValue::_raw.

◆ __framerate_approximation() [1/2]

boost::rational< uint > __framerate_approximation ( size_t  cnt,
Duration  timeReference 
)

helper calculate the count per time span approximately, to the precision possible to represent as fractional uint.

Definition at line 317 of file time.cpp.

References lib::time::__framerate_approximation(), TimeValue::_raw, lib::time::RATE_LIMIT, and TimeValue::SCALE.

+ Here is the call graph for this function:

◆ __framerate_approximation() [2/2]

boost::rational< uint > __framerate_approximation ( double  fps)

helper to work around the limitations of uint.

Returns
a fractional number approximating the floating-point spec.
Todo:
imposing a quite coarse limitation. If this turns out to be a problem: we can do better, use lib::reQuant (rational.hpp)

Definition at line 286 of file time.cpp.

References lib::time::__framerate_approximation(), and lib::time::RATE_LIMIT.

Referenced by lib::time::__framerate_approximation().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: