clean-up: remove gavl_time_t as external dependency

Indeed — this change set is kind of sad.
Because I still admire the design of the GAVL library,
and would love to use it for processing of raw video.
However, up to now, we never got to the point of actually
doing so. For the future, I am not sure if there remains
room to rely on lib-GAVL, since FFmpeg roughly covers
a similar ground (and a lot beyond that). And providing
a plug-in for FFmpeg is unavoidable, practically speaking.

So I still retain the nominal dependency on lib-GAVL
in the Build system (since it is still packaged in Debian).

But it is pointless to rely on this library just for an
external type-def `gavl_time_t`. We owe much to this
inspiration, but it can be expected that we'll wrap
these raw time-values into a dedicated marker type
soon, and we certainly won't be exposing any C-style
interface for time calculations in future, since
we do not want anyone to side-step the Lumiera
time handling framework in favour of working
„just with plain numbers“


NOTE: lib-GAVL hompage has moved to Github:
      https://github.com/bplaum/gavl
This commit is contained in:
Fischlurch 2025-05-17 23:12:47 +02:00
parent ee6e720d00
commit d31d4295a4
22 changed files with 308 additions and 161 deletions

View file

@ -85,7 +85,7 @@ def configure(env):
if not conf.CheckPkgConfig('gavl', '1.4'): if not conf.CheckPkgConfig('gavl', '1.4'):
problems.append('Did not find Gmerlin Audio Video Lib [http://gmerlin.sourceforge.net/gavl.html].') problems.append('Did not find Gmerlin Audio Video Lib [https://github.com/bplaum/gavl].')
else: else:
conf.env.mergeConf('gavl') conf.env.mergeConf('gavl')

View file

@ -20,7 +20,7 @@ Description
* We use an uniform time type. Time is time, not frames, samples etc. * We use an uniform time type. Time is time, not frames, samples etc.
* All timings in Lumiera are based on integral datatypes * All timings in Lumiera are based on integral datatypes
* We use a fixed, very fine grid, something of the sort of microseconds * We use a fixed, very fine grid, something of the sort of microseconds
* The internal representation is based on a `typedef int64_t gavl_time_t` * The internal representation is based on a `using raw_time_64 = int64_t`
* We use a set of library routines and convenience-methods to * We use a set of library routines and convenience-methods to
- Get time in different formats (fractional seconds, frame counts) - Get time in different formats (fractional seconds, frame counts)
- Calculate with time values (overloaded operators) - Calculate with time values (overloaded operators)

View file

@ -493,10 +493,10 @@ NOTE: At the time when Lumiera project started, the standard library provided
Time Time
~~~~ ~~~~
Time values are represented by a family of opaque date types Time values are represented by a family of opaque date types
with overloaded operators. The implementation is based on `gavl_time_t`, with overloaded operators. The implementation was inspired by `gavl_time_t`
an integral (µsec) time tick value. Thus, the arithmetic on time values and is thus based on a µ-seccond time grid, represented as 64-bit integer.
and time spans is limited and any Time handling and conversion is Thus, the arithmetic on time values and time spans is limited and any Time
centralised in library routines. handling and conversion is centralised in library routines.
We distinguish between time values and a _quantisation_ into a frame We distinguish between time values and a _quantisation_ into a frame
or sample grid. In any case, quantisation has to be done once, explicitly or sample grid. In any case, quantisation has to be done once, explicitly

View file

@ -31,6 +31,12 @@
** this model are defined to be a special kind of timecode, and thus dependent on ** this model are defined to be a special kind of timecode, and thus dependent on
** a preceding time quantisation. ** a preceding time quantisation.
** **
** @deprecated 2025 this should not be a "simple" C library set aside from the Lumiera
** time handling framework, rather it should be clarified that these are
** implementation helpers and must not be used by any application code.
** It should be checked which of these functions actually need to be
** exposed through an interface header, since these are typically
** used to implement parts of the time handling framework.
** **
** @see lib::time::Time ** @see lib::time::Time
** @see timequant.hpp ** @see timequant.hpp
@ -43,11 +49,12 @@
#define LUMIERA_TIME_H #define LUMIERA_TIME_H
#include <inttypes.h> #include <inttypes.h>
#include <gavl/gavl.h>
#ifdef __cplusplus /*=================== C++ facilities ===================== */ #ifdef __cplusplus /*=================== C++ facilities ===================== */
#include "lib/time/timevalue.hpp" #include "lib/time/timevalue.hpp"
using lib::time::raw_time_64;
/** /**
* Converts a fraction of seconds to Lumiera's internal opaque time scale. * Converts a fraction of seconds to Lumiera's internal opaque time scale.
@ -56,7 +63,7 @@
* here negative fractional micro-ticks are truncated towards zero. * here negative fractional micro-ticks are truncated towards zero.
* This was deemed irrelevant in practice. * This was deemed irrelevant in practice.
*/ */
gavl_time_t raw_time_64
lumiera_rational_to_time (lib::time::FSecs const& fractionalSeconds); lumiera_rational_to_time (lib::time::FSecs const& fractionalSeconds);
@ -66,7 +73,7 @@ lumiera_rational_to_time (lib::time::FSecs const& fractionalSeconds);
* @note handles only positive frame counts and assumes the * @note handles only positive frame counts and assumes the
* origin to be at zero. * origin to be at zero.
*/ */
gavl_time_t raw_time_64
lumiera_framecount_to_time (uint64_t frameCount, lib::time::FrameRate const& fps); lumiera_framecount_to_time (uint64_t frameCount, lib::time::FrameRate const& fps);
@ -75,7 +82,7 @@ lumiera_framecount_to_time (uint64_t frameCount, lib::time::FrameRate const& fps
* @param framerate underlying framerate as rational number * @param framerate underlying framerate as rational number
* @throw error::Logic on zero framerate * @throw error::Logic on zero framerate
*/ */
gavl_time_t raw_time_64
lumiera_frame_duration (lib::time::FrameRate const& fps); lumiera_frame_duration (lib::time::FrameRate const& fps);
@ -91,15 +98,15 @@ extern "C" { /* ===================== C interface ======================== */
* The time grid used for quantisation is comprised of equally spaced intervals, * The time grid used for quantisation is comprised of equally spaced intervals,
* rooted at the given origin. The interval starting with the origin is numbered * rooted at the given origin. The interval starting with the origin is numbered
* as zero. Each interval includes its lower bound, but excludes its upper bound. * as zero. Each interval includes its lower bound, but excludes its upper bound.
* @param grid spacing of the grid intervals, measured in GAVL_TIME_SCALE * @param grid spacing of the grid intervals, measured in TimeValue::Scale (µ-ticks)
* @return number of the grid interval containing the given time. * @return number of the grid interval containing the given time.
* @warning the resulting value is limited to (Time::Min, Time::MAX) * @warning the resulting value is limited to (Time::Min, Time::MAX)
*/ */
int64_t int64_t
lumiera_quantise_frames (gavl_time_t time, gavl_time_t origin, gavl_time_t grid); lumiera_quantise_frames (raw_time_64 time, raw_time_64 origin, raw_time_64 grid);
int64_t int64_t
lumiera_quantise_frames_fps (gavl_time_t time, gavl_time_t origin, uint framerate); lumiera_quantise_frames_fps (raw_time_64 time, raw_time_64 origin, uint framerate);
/** /**
* Similar to #lumiera_quantise_frames, but returns a grid aligned _relative time_. * Similar to #lumiera_quantise_frames, but returns a grid aligned _relative time_.
@ -110,17 +117,17 @@ lumiera_quantise_frames_fps (gavl_time_t time, gavl_time_t origin, uint framerat
* origin = Time::MIN, then all original time values above zero will be * origin = Time::MIN, then all original time values above zero will be
* clipped, because the result, relative to origin, needs to be <= Time::MAX * clipped, because the result, relative to origin, needs to be <= Time::MAX
*/ */
gavl_time_t raw_time_64
lumiera_quantise_time (gavl_time_t time, gavl_time_t origin, gavl_time_t grid); lumiera_quantise_time (raw_time_64 time, raw_time_64 origin, raw_time_64 grid);
/** /**
* Calculate time of a grid point (frame start) * Calculate time of a grid point (frame start)
* @param nr index number of the grid point (0 is at origin) * @param nr index number of the grid point (0 is at origin)
* @param grid spacing of the grid intervals, measured in GAVL_TIME_SCALE * @param grid spacing of the grid intervals, measured in TimeValue::Scale (µ-ticks)
* @return time point (frame start) on the Lumiera internal time scale * @return time point (frame start) on the Lumiera internal time scale
*/ */
gavl_time_t raw_time_64
lumiera_time_of_gridpoint (int64_t nr, gavl_time_t origin, gavl_time_t grid); lumiera_time_of_gridpoint (int64_t nr, raw_time_64 origin, raw_time_64 grid);
/** /**
* Build a time value by summing up the given components. * Build a time value by summing up the given components.
@ -129,7 +136,7 @@ lumiera_time_of_gridpoint (int64_t nr, gavl_time_t origin, gavl_time_t grid);
* @param mins number of minutes * @param mins number of minutes
* @param hours number of hours * @param hours number of hours
*/ */
gavl_time_t raw_time_64
lumiera_build_time (long millis, uint secs, uint mins, uint hours); lumiera_build_time (long millis, uint secs, uint mins, uint hours);
/** /**
@ -140,7 +147,7 @@ lumiera_build_time (long millis, uint secs, uint mins, uint hours);
* @param mins number of minutes * @param mins number of minutes
* @param hours number of hours * @param hours number of hours
*/ */
gavl_time_t raw_time_64
lumiera_build_time_fps (uint fps, uint frames, uint secs, uint mins, uint hours); lumiera_build_time_fps (uint fps, uint frames, uint secs, uint mins, uint hours);
/** /**
@ -148,59 +155,59 @@ lumiera_build_time_fps (uint fps, uint frames, uint secs, uint mins, uint hours)
* The components are interpreted as a NTSC drop-frame timecode. * The components are interpreted as a NTSC drop-frame timecode.
* @warning take care not to specify time codes that are illegal NTSC drop-frame times. * @warning take care not to specify time codes that are illegal NTSC drop-frame times.
*/ */
gavl_time_t raw_time_64
lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours); lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours);
/** Extract the hour part of given time. */ /** Extract the hour part of given time. */
int int
lumiera_time_hours (gavl_time_t time); lumiera_time_hours (raw_time_64 time);
/** Extract the minute part of given time. */ /** Extract the minute part of given time. */
int int
lumiera_time_minutes (gavl_time_t time); lumiera_time_minutes (raw_time_64 time);
/** Extract the seconds part of given time. */ /** Extract the seconds part of given time. */
int int
lumiera_time_seconds (gavl_time_t time); lumiera_time_seconds (raw_time_64 time);
/** Extract the milliseconds part of given time. */ /** Extract the milliseconds part of given time. */
int int
lumiera_time_millis (gavl_time_t time); lumiera_time_millis (raw_time_64 time);
/** /**
* Extract the remaining frame part of given time. * Extract the remaining frame part of given time.
* @param fps frame rate (frames per second) * @param fps frame rate (frames per second)
*/ */
int int
lumiera_time_frames (gavl_time_t time, uint fps); lumiera_time_frames (raw_time_64 time, uint fps);
/** /**
* Extract the frame part of given time, using NTSC drop-frame timecode. * Extract the frame part of given time, using NTSC drop-frame timecode.
*/ */
int int
lumiera_time_ntsc_drop_frames (gavl_time_t time); lumiera_time_ntsc_drop_frames (raw_time_64 time);
/** /**
* Extract the second part of given time, using NTSC drop-frame timecode. * Extract the second part of given time, using NTSC drop-frame timecode.
*/ */
int int
lumiera_time_ntsc_drop_seconds (gavl_time_t time); lumiera_time_ntsc_drop_seconds (raw_time_64 time);
/** /**
* Extract the minute part of given time, using NTSC drop-frame timecode. * Extract the minute part of given time, using NTSC drop-frame timecode.
*/ */
int int
lumiera_time_ntsc_drop_minutes (gavl_time_t time); lumiera_time_ntsc_drop_minutes (raw_time_64 time);
/** /**
* Extract the hour part of given time, using NTSC drop-frame timecode. * Extract the hour part of given time, using NTSC drop-frame timecode.
*/ */
int int
lumiera_time_ntsc_drop_hours (gavl_time_t time); lumiera_time_ntsc_drop_hours (raw_time_64 time);
/** /**
@ -210,7 +217,7 @@ lumiera_time_ntsc_drop_hours (gavl_time_t time);
* by rendering into a suitable timecode format. * by rendering into a suitable timecode format.
*/ */
char* char*
lumiera_tmpbuf_print_time (gavl_time_t time); lumiera_tmpbuf_print_time (raw_time_64 time);

View file

@ -17,9 +17,9 @@
/** @file time.cpp /** @file time.cpp
** Lumiera time handling core implementation unit. ** Lumiera time handling core implementation unit.
** This translation unit generates code for the Lumiera internal time wrapper, ** This translation unit generates code for the Lumiera internal time wrapper,
** based on gavl_time_t, associated constants, marker classes for the derived ** based on 64bit integral µ-tick values, associated constants, marker classes
** time entities (TimeVar, Offset, Duration, TimeSpan, FrameRate) and for the ** for the derived time entities (TimeVar, Offset, Duration, TimeSpan, FrameRate)
** basic time and frame rate conversion functions. ** and for the basic time and frame rate conversion functions.
** **
** Client code includes either time.h (for basics and conversion functions) ** Client code includes either time.h (for basics and conversion functions)
** or timevalue.hpp (for the time entities), timequant.hpp for grid aligned ** or timevalue.hpp (for the time entities), timequant.hpp for grid aligned
@ -75,11 +75,11 @@ namespace meta {
namespace time { namespace time {
const gavl_time_t TimeValue::SCALE = GAVL_TIME_SCALE; const raw_time_64 TimeValue::SCALE = 1'000'000;
/** @note the allowed time range is explicitly limited to help overflow protection */ /** @note the allowed time range is explicitly limited to help overflow protection */
const Time Time::MAX ( TimeValue::buildRaw_(+std::numeric_limits<gavl_time_t>::max() / 30) ); const Time Time::MAX ( TimeValue::buildRaw_(+std::numeric_limits<raw_time_64>::max() / 30) );
const Time Time::MIN ( TimeValue::buildRaw_(-_raw(Time::MAX) ) ); const Time Time::MIN ( TimeValue::buildRaw_(-_raw(Time::MAX) ) );
const Time Time::ZERO; const Time Time::ZERO;
@ -94,8 +94,8 @@ namespace time {
/** scale factor _used locally within this implementation header_. /** scale factor _used locally within this implementation header_.
* GAVL_TIME_SCALE rsp. TimeValue::SCALE is the correct factor or dividend when using * TimeValue::SCALE (µ-ticks, i.e. 1e6) is the correct factor or dividend when using
* gavl_time_t for display on a scale with seconds. Since we want to use milliseconds, * raw_time_64 for display on a scale with seconds. Since we want to use milliseconds,
* we need to multiply or divide by 1000 to get correct results. */ * we need to multiply or divide by 1000 to get correct results. */
#define TIME_SCALE_MS (lib::time::TimeValue::SCALE / 1000) #define TIME_SCALE_MS (lib::time::TimeValue::SCALE / 1000)
@ -138,7 +138,7 @@ namespace time {
* of any "time-like" value, it is meant to be compact. */ * of any "time-like" value, it is meant to be compact. */
TimeValue::operator string() const TimeValue::operator string() const
{ {
gavl_time_t time = t_; raw_time_64 time = t_;
int64_t millis, seconds; int64_t millis, seconds;
bool negative = (time < 0); bool negative = (time < 0);
@ -163,7 +163,7 @@ namespace time {
*/ */
Time::operator string() const Time::operator string() const
{ {
gavl_time_t time = t_; raw_time_64 time = t_;
int millis, seconds, minutes, hours; int millis, seconds, minutes, hours;
bool negative = (time < 0); bool negative = (time < 0);
@ -233,7 +233,7 @@ namespace time {
/** @internal backdoor to sneak in a raw time value /** @internal backdoor to sneak in a raw time value
* bypassing any normalisation and limiting */ * bypassing any normalisation and limiting */
TimeValue TimeValue
TimeValue::buildRaw_ (gavl_time_t raw) TimeValue::buildRaw_ (raw_time_64 raw)
{ {
return reinterpret_cast<TimeValue const&> (raw); return reinterpret_cast<TimeValue const&> (raw);
} }
@ -326,7 +326,7 @@ namespace time {
{ {
boost::rational<int64_t> distance (this->t_); boost::rational<int64_t> distance (this->t_);
distance *= factor; distance *= factor;
gavl_time_t microTicks = floordiv (distance.numerator(), distance.denominator()); raw_time_64 microTicks = floordiv (distance.numerator(), distance.denominator());
return Offset{buildRaw_(microTicks)}; return Offset{buildRaw_(microTicks)};
} }
@ -337,7 +337,7 @@ namespace time {
{ {
double distance(this->t_); double distance(this->t_);
distance *= factor; distance *= factor;
gavl_time_t microTicks = floor (distance); raw_time_64 microTicks = floor (distance);
return Offset{buildRaw_(microTicks)}; return Offset{buildRaw_(microTicks)};
} }
@ -383,7 +383,7 @@ namespace util {
char* char*
lumiera_tmpbuf_print_time (gavl_time_t time) lumiera_tmpbuf_print_time (raw_time_64 time)
{ {
int milliseconds, seconds, minutes, hours; int milliseconds, seconds, minutes, hours;
bool negative = (time < 0); bool negative = (time < 0);
@ -409,7 +409,7 @@ lumiera_tmpbuf_print_time (gavl_time_t time)
/// @todo this utility function could be factored out into a `FSecs` or `RSec` class ///////////////////////TICKET #1262 /// @todo this utility function could be factored out into a `FSecs` or `RSec` class ///////////////////////TICKET #1262
gavl_time_t raw_time_64
lumiera_rational_to_time (FSecs const& fractionalSeconds) lumiera_rational_to_time (FSecs const& fractionalSeconds)
{ {
// avoid numeric wrap from values not representable as 64bit µ-ticks // avoid numeric wrap from values not representable as 64bit µ-ticks
@ -417,22 +417,22 @@ lumiera_rational_to_time (FSecs const& fractionalSeconds)
return (fractionalSeconds < 0? -1:+1) return (fractionalSeconds < 0? -1:+1)
* std::numeric_limits<int64_t>::max(); * std::numeric_limits<int64_t>::max();
return gavl_time_t(util::reQuant (fractionalSeconds.numerator() return raw_time_64(util::reQuant (fractionalSeconds.numerator()
,fractionalSeconds.denominator() ,fractionalSeconds.denominator()
,lib::time::TimeValue::SCALE ,lib::time::TimeValue::SCALE
)); ));
} }
gavl_time_t raw_time_64
lumiera_framecount_to_time (uint64_t frameCount, FrameRate const& fps) lumiera_framecount_to_time (uint64_t frameCount, FrameRate const& fps)
{ {
// convert to 64bit // convert to 64bit
boost::rational<uint64_t> framerate (fps.numerator(), fps.denominator()); boost::rational<uint64_t> framerate (fps.numerator(), fps.denominator());
return rational_cast<gavl_time_t> (lib::time::TimeValue::SCALE * frameCount / framerate); return rational_cast<raw_time_64> (lib::time::TimeValue::SCALE * frameCount / framerate);
} }
gavl_time_t raw_time_64
lumiera_frame_duration (FrameRate const& fps) lumiera_frame_duration (FrameRate const& fps)
{ {
if (!fps) if (!fps)
@ -447,20 +447,20 @@ lumiera_frame_duration (FrameRate const& fps)
namespace { // implementation: basic frame quantisation.... namespace { // implementation: basic frame quantisation....
inline int64_t inline int64_t
calculate_quantisation (gavl_time_t time, gavl_time_t origin, gavl_time_t grid) calculate_quantisation (raw_time_64 time, raw_time_64 origin, raw_time_64 grid)
{ {
time -= origin; time -= origin;
return floordiv (time,grid); return floordiv (time,grid);
} }
inline int64_t inline int64_t
calculate_quantisation (gavl_time_t time, gavl_time_t origin, uint framerate, uint framerate_divisor=1) calculate_quantisation (raw_time_64 time, raw_time_64 origin, uint framerate, uint framerate_divisor=1)
{ {
REQUIRE (framerate); REQUIRE (framerate);
REQUIRE (framerate_divisor); REQUIRE (framerate_divisor);
const int64_t limit_num = std::numeric_limits<gavl_time_t>::max() / framerate; const int64_t limit_num = std::numeric_limits<raw_time_64>::max() / framerate;
const int64_t limit_den = std::numeric_limits<gavl_time_t>::max() / framerate_divisor; const int64_t limit_den = std::numeric_limits<raw_time_64>::max() / framerate_divisor;
const int64_t microScale {lib::time::TimeValue::SCALE}; const int64_t microScale {lib::time::TimeValue::SCALE};
// protect against numeric overflow // protect against numeric overflow
@ -474,7 +474,7 @@ namespace { // implementation: basic frame quantisation....
{ {
// direct calculation will overflow. // direct calculation will overflow.
// use the less precise method instead... // use the less precise method instead...
gavl_time_t frameDuration = microScale / framerate; // truncated to µs raw_time_64 frameDuration = microScale / framerate; // truncated to µs
return calculate_quantisation (time,origin, frameDuration); return calculate_quantisation (time,origin, frameDuration);
} }
} }
@ -482,37 +482,37 @@ namespace { // implementation: basic frame quantisation....
int64_t int64_t
lumiera_quantise_frames (gavl_time_t time, gavl_time_t origin, gavl_time_t grid) lumiera_quantise_frames (raw_time_64 time, raw_time_64 origin, raw_time_64 grid)
{ {
return calculate_quantisation (time, origin, grid); return calculate_quantisation (time, origin, grid);
} }
int64_t int64_t
lumiera_quantise_frames_fps (gavl_time_t time, gavl_time_t origin, uint framerate) lumiera_quantise_frames_fps (raw_time_64 time, raw_time_64 origin, uint framerate)
{ {
return calculate_quantisation (time, origin, framerate); return calculate_quantisation (time, origin, framerate);
} }
gavl_time_t raw_time_64
lumiera_quantise_time (gavl_time_t time, gavl_time_t origin, gavl_time_t grid) lumiera_quantise_time (raw_time_64 time, raw_time_64 origin, raw_time_64 grid)
{ {
int64_t count = calculate_quantisation (time, origin, grid); int64_t count = calculate_quantisation (time, origin, grid);
gavl_time_t alignedTime = count * grid; raw_time_64 alignedTime = count * grid;
return alignedTime; return alignedTime;
} }
gavl_time_t raw_time_64
lumiera_time_of_gridpoint (int64_t nr, gavl_time_t origin, gavl_time_t grid) lumiera_time_of_gridpoint (int64_t nr, raw_time_64 origin, raw_time_64 grid)
{ {
gavl_time_t offset = nr * grid; raw_time_64 offset = nr * grid;
return origin + offset; return origin + offset;
} }
gavl_time_t raw_time_64
lumiera_build_time(long millis, uint secs, uint mins, uint hours) lumiera_build_time(long millis, uint secs, uint mins, uint hours)
{ {
gavl_time_t time = millis raw_time_64 time = millis
+ 1000 * secs + 1000 * secs
+ 1000 * 60 * mins + 1000 * 60 * mins
+ 1000 * 60 * 60 * hours; + 1000 * 60 * 60 * hours;
@ -520,10 +520,10 @@ lumiera_build_time(long millis, uint secs, uint mins, uint hours)
return time; return time;
} }
gavl_time_t raw_time_64
lumiera_build_time_fps (uint fps, uint frames, uint secs, uint mins, uint hours) lumiera_build_time_fps (uint fps, uint frames, uint secs, uint mins, uint hours)
{ {
gavl_time_t time = 1000LL * frames/fps raw_time_64 time = 1000LL * frames/fps
+ 1000 * secs + 1000 * secs
+ 1000 * 60 * mins + 1000 * 60 * mins
+ 1000 * 60 * 60 * hours; + 1000 * 60 * 60 * hours;
@ -532,31 +532,31 @@ lumiera_build_time_fps (uint fps, uint frames, uint secs, uint mins, uint hours)
} }
int int
lumiera_time_hours (gavl_time_t time) lumiera_time_hours (raw_time_64 time)
{ {
return time / TIME_SCALE_MS / 1000 / 60 / 60; return time / TIME_SCALE_MS / 1000 / 60 / 60;
} }
int int
lumiera_time_minutes (gavl_time_t time) lumiera_time_minutes (raw_time_64 time)
{ {
return (time / TIME_SCALE_MS / 1000 / 60) % 60; return (time / TIME_SCALE_MS / 1000 / 60) % 60;
} }
int int
lumiera_time_seconds (gavl_time_t time) lumiera_time_seconds (raw_time_64 time)
{ {
return (time / TIME_SCALE_MS / 1000) % 60; return (time / TIME_SCALE_MS / 1000) % 60;
} }
int int
lumiera_time_millis (gavl_time_t time) lumiera_time_millis (raw_time_64 time)
{ {
return (time / TIME_SCALE_MS) % 1000; return (time / TIME_SCALE_MS) % 1000;
} }
int int
lumiera_time_frames (gavl_time_t time, uint fps) lumiera_time_frames (raw_time_64 time, uint fps)
{ {
REQUIRE (fps < uint(std::numeric_limits<int>::max())); REQUIRE (fps < uint(std::numeric_limits<int>::max()));
return floordiv<int> (lumiera_time_millis(time) * int(fps), TIME_SCALE_MS); return floordiv<int> (lumiera_time_millis(time) * int(fps), TIME_SCALE_MS);
@ -581,7 +581,7 @@ namespace { // implementation helper
* @todo I doubt this works correct for negative times!! * @todo I doubt this works correct for negative times!!
*/ */
inline int64_t inline int64_t
calculate_drop_frame_number (gavl_time_t time) calculate_drop_frame_number (raw_time_64 time)
{ {
int64_t frameNr = calculate_quantisation (time, 0, 30000, 1001); int64_t frameNr = calculate_quantisation (time, 0, 30000, 1001);
@ -599,30 +599,30 @@ namespace { // implementation helper
} }
int int
lumiera_time_ntsc_drop_frames (gavl_time_t time) lumiera_time_ntsc_drop_frames (raw_time_64 time)
{ {
return calculate_drop_frame_number(time) % 30; return calculate_drop_frame_number(time) % 30;
} }
int int
lumiera_time_ntsc_drop_seconds (gavl_time_t time) lumiera_time_ntsc_drop_seconds (raw_time_64 time)
{ {
return calculate_drop_frame_number(time) / 30 % 60; return calculate_drop_frame_number(time) / 30 % 60;
} }
int int
lumiera_time_ntsc_drop_minutes (gavl_time_t time) lumiera_time_ntsc_drop_minutes (raw_time_64 time)
{ {
return calculate_drop_frame_number(time) / 30 / 60 % 60; return calculate_drop_frame_number(time) / 30 / 60 % 60;
} }
int int
lumiera_time_ntsc_drop_hours (gavl_time_t time) lumiera_time_ntsc_drop_hours (raw_time_64 time)
{ {
return calculate_drop_frame_number(time) / 30 / 60 / 60 % 24; return calculate_drop_frame_number(time) / 30 / 60 / 60 % 24;
} }
gavl_time_t raw_time_64
lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours) lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours)
{ {
uint64_t total_mins = 60 * hours + mins; uint64_t total_mins = 60 * hours + mins;
@ -631,7 +631,7 @@ lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours)
+ 30 * secs + 30 * secs
+ frames + frames
- 2 * (total_mins - total_mins / 10); - 2 * (total_mins - total_mins / 10);
gavl_time_t result = lumiera_framecount_to_time (total_frames, FrameRate::NTSC); raw_time_64 result = lumiera_framecount_to_time (total_frames, FrameRate::NTSC);
if (0 != result) // compensate for truncating down on conversion if (0 != result) // compensate for truncating down on conversion
result += 1; // without this adjustment the frame number result += 1; // without this adjustment the frame number

View file

@ -350,7 +350,7 @@ namespace time {
/** */ /** */
Secs::Secs (QuTime const& quantisedTime) Secs::Secs (QuTime const& quantisedTime)
: TCode(quantisedTime) : TCode(quantisedTime)
// : sec_(TimeVar(quantisedTime) / GAVL_TIME_SCALE) //////////////////////////////////////////////////////TICKET #736 implement Seconds format // : sec_(TimeVar(quantisedTime) / TimeValue::SCALE) /////////////////////////////////////////////////////TICKET #736 implement Seconds format
{ } { }

View file

@ -14,7 +14,8 @@
/** @file timevalue.hpp /** @file timevalue.hpp
** a family of time value like entities and their relationships. ** a family of time value like entities and their relationships.
** This is the foundation for the Lumiera time handling framework. On the implementation ** 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 ** level, time values are represented as 64bit integer values `raw_time_64`, similar to
** and inspired by `gavl_time_t` from the raw-video handling [Lib-GAVL]. But for the
** actual use, we create several kinds of time "values", based on their logical properties. ** 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 ** 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 ** created through some limited construction paths, and any time based calculation
@ -30,7 +31,7 @@
** way to retrieve such a value is by formatting it into a time code format. ** 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; ** 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 ** in fact it is implemented as a single 64bit µ-tick value (`raw_time_64`). The
** further time entities are implemented as value objects (without virtual functions): ** 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::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::TimeVar is a mutable time variable and can be used for calculations
@ -86,7 +87,8 @@
** @see time.h basic time calculation library functions ** @see time.h basic time calculation library functions
** @see timequant.hpp ** @see timequant.hpp
** @see TimeValue_test ** @see TimeValue_test
** **
** [Lib-GAVL]: https://github.com/bplaum/gavl
*/ */
@ -100,11 +102,6 @@
#include <cstdlib> #include <cstdlib>
#include <string> #include <string>
extern "C" {
#include <stdint.h>
#include <gavl/gavltime.h>
}
namespace lib { namespace lib {
namespace time { namespace time {
@ -118,11 +115,22 @@ namespace time {
class Mutation; class Mutation;
/**
* Raw µ-tick time representation used in Lumiera.
* @remark this representation was inspired by [Lib-GAVL].
* @todo 2025 a mere type alias is up to debate -- very likely we'll use a wrapper soon /////////////////TICKET #1258
* @warning application logic should avoid handling any raw time value
* directly and rather treat time data as an opaque entity.
* [Lib-GAVL]: https://github.com/bplaum/gavl
*/
using raw_time_64 = int64_t;
/** /**
* basic constant internal time value. * basic constant internal time value.
* These time values provide the implementation base * These time values provide the implementation base
* for all further time types. They can be created by * for all further time types. They can be created by
* wrapping up a raw micro tick value (gavl_time_t), * wrapping up a raw micro tick value (raw_time_64),
* are totally ordered, but besides that, * are totally ordered, but besides that,
* they are opaque and non-mutable. * they are opaque and non-mutable.
* @note clients should prefer to use Time instances, * @note clients should prefer to use Time instances,
@ -132,12 +140,12 @@ namespace time {
*/ */
class TimeValue class TimeValue
: boost::totally_ordered<TimeValue, : boost::totally_ordered<TimeValue,
boost::totally_ordered<TimeValue, gavl_time_t>> boost::totally_ordered<TimeValue, raw_time_64>>
{ {
protected: protected:
/** the raw (internal) time value /** the raw (internal) time value
* used to implement the time types */ * used to implement the time types */
gavl_time_t t_; raw_time_64 t_;
/** Assigning of time values is not allowed, /** Assigning of time values is not allowed,
@ -153,9 +161,9 @@ namespace time {
friend class Mutation; friend class Mutation;
/** explicit limit of allowed time range */ /** explicit limit of allowed time range */
static gavl_time_t limitedTime (gavl_time_t raw); static raw_time_64 limitedTime (raw_time_64 raw);
/** safe calculation of explicitly limited time offset */ /** safe calculation of explicitly limited time offset */
static gavl_time_t limitedDelta (gavl_time_t origin, gavl_time_t target); static raw_time_64 limitedDelta (raw_time_64 origin, raw_time_64 target);
/** @internal for Offset and Duration entities built on top */ /** @internal for Offset and Duration entities built on top */
TimeValue (TimeValue const& origin, TimeValue const& target) TimeValue (TimeValue const& origin, TimeValue const& target)
@ -164,11 +172,11 @@ namespace time {
public: public:
/** Number of micro ticks (µs) per second as basic time scale */ /** Number of micro ticks (µs) per second as basic time scale */
static const gavl_time_t SCALE; static const raw_time_64 SCALE;
explicit explicit
TimeValue (gavl_time_t val) ///< time given in µ ticks here TimeValue (raw_time_64 val) ///< time given in µ ticks here
: t_{limitedTime (val)} : t_{limitedTime (val)}
{ } { }
@ -178,9 +186,9 @@ namespace time {
{ } { }
/** @internal to pass Time values to C functions */ /** @internal to pass Time values to C functions */
friend gavl_time_t _raw (TimeValue const& time) { return time.t_; } friend raw_time_64 _raw (TimeValue const& time) { return time.t_; }
friend HashVal hash_value (TimeValue const&); friend HashVal hash_value (TimeValue const&);
static TimeValue buildRaw_(gavl_time_t); static TimeValue buildRaw_(raw_time_64);
/** @internal diagnostics */ /** @internal diagnostics */
operator std::string () const; operator std::string () const;
@ -190,10 +198,10 @@ namespace time {
// Supporting totally_ordered // Supporting totally_ordered
friend bool operator< (TimeValue const& t1, TimeValue const& t2) { return t1.t_ < t2.t_; } friend bool operator< (TimeValue const& t1, TimeValue const& t2) { return t1.t_ < t2.t_; }
friend bool operator< (TimeValue const& t1, gavl_time_t t2) { return t1.t_ < t2 ; } friend bool operator< (TimeValue const& t1, raw_time_64 t2) { return t1.t_ < t2 ; }
friend bool operator> (TimeValue const& t1, gavl_time_t t2) { return t1.t_ > t2 ; } friend bool operator> (TimeValue const& t1, raw_time_64 t2) { return t1.t_ > t2 ; }
friend bool operator== (TimeValue const& t1, TimeValue const& t2) { return t1.t_ == t2.t_; } friend bool operator== (TimeValue const& t1, TimeValue const& t2) { return t1.t_ == t2.t_; }
friend bool operator== (TimeValue const& t1, gavl_time_t t2) { return t1.t_ == t2 ; } friend bool operator== (TimeValue const& t1, raw_time_64 t2) { return t1.t_ == t2 ; }
}; };
@ -207,7 +215,7 @@ namespace time {
/** relative framecount or frame number. /** relative framecount or frame number.
* Used within the engine at places where the underlying * Used within the engine at places where the underlying
* grid and origin is obvious from the call context. * grid and origin is obvious from the call context.
* @warning do not mix up gavl_time_t and FrameCnt. * @warning do not mix up raw_time_64 and FrameCnt.
* @warning use 64bit consistently. * @warning use 64bit consistently.
* beware: `long` is 32bit on i386 * beware: `long` is 32bit on i386
* @note any conversion to frame numbers should go through * @note any conversion to frame numbers should go through
@ -216,7 +224,7 @@ namespace time {
using FrameCnt = int64_t; using FrameCnt = int64_t;
/** rational representation of fractional seconds /** rational representation of fractional seconds
* @warning do not mix up gavl_time_t and FSecs */ * @warning do not mix up raw_time_64 and FSecs */
using FSecs = boost::rational<int64_t>; using FSecs = boost::rational<int64_t>;
@ -226,7 +234,7 @@ namespace time {
* allowing copy and re-accessing * allowing copy and re-accessing
* @note supports scaling by a factor, * @note supports scaling by a factor,
* which _deliberately_ is chosen * which _deliberately_ is chosen
* as int, not gavl_time_t, because the * as int, not raw_time_64, because the
* multiplying of times is meaningless. * multiplying of times is meaningless.
*/ */
class TimeVar class TimeVar
@ -258,7 +266,7 @@ namespace time {
} }
/// Support mixing with plain 64bit int arithmetics /// Support mixing with plain 64bit int arithmetics
operator gavl_time_t() const { return t_; } operator raw_time_64() const { return t_; }
/// Support for micro-tick precise time arithmetics /// Support for micro-tick precise time arithmetics
operator FSecs() const { return FSecs{t_, TimeValue::SCALE}; } operator FSecs() const { return FSecs{t_, TimeValue::SCALE}; }
@ -708,8 +716,8 @@ namespace time {
return n; return n;
} }
inline gavl_time_t inline raw_time_64
symmetricLimit (gavl_time_t raw, TimeValue lim) symmetricLimit (raw_time_64 raw, TimeValue lim)
{ {
return raw > lim? _raw(lim) return raw > lim? _raw(lim)
: -raw > lim? -_raw(lim) : -raw > lim? -_raw(lim)
@ -744,21 +752,21 @@ namespace time {
* While Time entities are \c not a "safeInt" * While Time entities are \c not a "safeInt"
* implementation, we limit new values to * implementation, we limit new values to
* lower the likelihood of wrap-around */ * lower the likelihood of wrap-around */
inline gavl_time_t inline raw_time_64
TimeValue::limitedTime (gavl_time_t raw) TimeValue::limitedTime (raw_time_64 raw)
{ {
return symmetricLimit (raw, Time::MAX); return symmetricLimit (raw, Time::MAX);
} }
inline gavl_time_t inline raw_time_64
TimeValue::limitedDelta (gavl_time_t origin, gavl_time_t target) TimeValue::limitedDelta (raw_time_64 origin, raw_time_64 target)
{ {
if (0 > (origin^target)) if (0 > (origin^target))
{// prevent possible numeric wrap {// prevent possible numeric wrap
origin = symmetricLimit (origin, Duration::MAX); origin = symmetricLimit (origin, Duration::MAX);
target = symmetricLimit (target, Duration::MAX); target = symmetricLimit (target, Duration::MAX);
} }
gavl_time_t res = target - origin; raw_time_64 res = target - origin;
return symmetricLimit (res, Duration::MAX); return symmetricLimit (res, Duration::MAX);
} }

View file

@ -29,7 +29,7 @@
#include "stage/widget/timecode-widget.hpp" #include "stage/widget/timecode-widget.hpp"
#include "lib/time/timevalue.hpp"
#include "lib/time/diagnostics.hpp" ////////////TODO: temporary solution to get H:M:S components. Use TimeCode instead! #include "lib/time/diagnostics.hpp" ////////////TODO: temporary solution to get H:M:S components. Use TimeCode instead!
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
@ -40,9 +40,6 @@
#include <locale> #include <locale>
#include <string> #include <string>
#include <gavl/gavl.h>
#include <sigc++/bind.h>
using boost::lexical_cast; using boost::lexical_cast;
using sigc::mem_fun; using sigc::mem_fun;
@ -433,7 +430,7 @@ namespace widget {
// void // void
// TimeCode::smpte_offset_changed() // TimeCode::smpte_offset_changed()
// { // {
// gavl_time_t current; // raw_time_64 current;
// switch (_mode) { // switch (_mode) {
// case SMPTE: // case SMPTE:
@ -1278,7 +1275,7 @@ namespace widget {
Time Time
TimeCode::audio_time_from_display () const TimeCode::audio_time_from_display () const
{ {
gavl_time_t parsedAudioFrames = lexical_cast<int>(audio_frames_label.get_text()); raw_time_64 parsedAudioFrames = lexical_cast<int>(audio_frames_label.get_text());
return Time(TimeValue(parsedAudioFrames)); return Time(TimeValue(parsedAudioFrames));
} }

View file

@ -21,6 +21,10 @@
** the referenced libraries, though. This will be done with adapter implementations, ** the referenced libraries, though. This will be done with adapter implementations,
** where the interface MediaImplLip defines those aspects actually used and required ** where the interface MediaImplLip defines those aspects actually used and required
** by our internal processing. ** by our internal processing.
** @deprecated 2025 -- this is an architecture draft, and shows the direction to take
** for the integration with external libraries. Yet in reality, this task
** can not conceivably be thus simple; take everything here with a grain
** of salt (since this code is not yet actually used in any way).
*/ */

View file

@ -13,11 +13,31 @@
/** @file libgavl.hpp /** @file libgavl.hpp
** Concrete implementation of the MediaImplLib facade to work with `libGAVL` ** Concrete implementation of the MediaImplLib facade to work with [lib-GAVL],
** a library for handling basic raw video data formats.
** @todo a draft and placeholder code from 2008, at which time the intention was ** @todo a draft and placeholder code from 2008, at which time the intention was
** to rely on libGAVL for processing of raw media data. This seemed like a ** to rely on libGAVL for processing of raw media data. This seemed like a
** good idea at that time, but we should re-evaluate if libGAVL is maintained ** good idea at that time, but we should re-evaluate if libGAVL is maintained
** and in actual use, before we start really relying on it ** and in actual use, before we start really relying on it.
** @todo 2025 this code is a kind of _architecture placeholder_ it is clear that
** a solution can can not be _that simple_, but any viable solution will
** rely onto an approach like outlined here: provide a façade interface,
** which has to be implemented by any plug-in component to provide access
** to the processing capabilities of a specific library. The access point
** functions exposed on the facade however must be shaped by the specific
** way how the builder and the render engine interacts with and delegates
** back to the media-handling library. Such an interface can not be based
** on first principles alone.
** @todo 2025 I still retain the dependency on lib-GAVL for now, even while we
** never got into actually using it. Simply because I still consider this
** library exemplary, and would love to use it for real. Yet it remains
** to be seen if the project actually gets a chance to do so, simply
** because FFmpeg roughly covers the same ground. Presumably it turns
** out to be a basic requirement to ship a plug-in with FFmpeg binding.
** Furthermore, one especially tricky aspect is how to support displays
** with extended dynamic range -- a requirement which has the potential
** to blur the notion of »raw video«...
** [Lib-GAVL]: https://github.com/bplaum/gavl
*/ */

View file

@ -434,7 +434,7 @@ namespace gear {
adjustEpochStep (double factor) adjustEpochStep (double factor)
{ {
double stretched = _raw(epochStep_) * factor; double stretched = _raw(epochStep_) * factor;
gavl_time_t microTicks(floor (stretched)); raw_time_64 microTicks(floor (stretched));
epochStep_ = TimeValue{microTicks}; epochStep_ = TimeValue{microTicks};
} }

View file

@ -124,7 +124,7 @@ union InvocationInstanceID
*/ */
struct lumiera_jobParameter_struct struct lumiera_jobParameter_struct
{ {
gavl_time_t nominalTime; /////////////////////////////////////////////////////////////////////////TICKET #1295 job invocation parameter: framework to interpret this time raw_time_64 nominalTime; /////////////////////////////////////////////////////////////////////////TICKET #1295 job invocation parameter: framework to interpret this time
InvocationInstanceID invoKey; InvocationInstanceID invoKey;
//////////////////////////////////////////////////////////////TODO: place an additional parameter value here, or make the instanceID globally unique? //////////////////////////////////////////////////////////////TODO: place an additional parameter value here, or make the instanceID globally unique?
////////////////////////////////////////////////////////////////////////////////////TICKET #1293 job invocation identity ////////////////////////////////////////////////////////////////////////////////////TICKET #1293 job invocation identity
@ -166,7 +166,7 @@ typedef lumiera_jobDefinition* LumieraJobDefinition;
*/ */
struct lumiera_jobDescriptor_struct struct lumiera_jobDescriptor_struct
{ {
gavl_time_t deadline; ///< given in real wall clock time raw_time_64 deadline; ///< given in real wall clock time
JobState jobState; JobState jobState;
lumiera_jobDefinition jobDefinition; ///< of interest only to Steam-Layer lumiera_jobDefinition jobDefinition; ///< of interest only to Steam-Layer

View file

@ -362,7 +362,7 @@ namespace gear {
{ {
auto scatter = [&](Duration horizon) auto scatter = [&](Duration horizon)
{ {
gavl_time_t wrap = hash_value(now) % _raw(horizon); lib::time::raw_time_64 wrap = hash_value(now) % _raw(horizon);
ENSURE (0 <= wrap and wrap < _raw(horizon)); ENSURE (0 <= wrap and wrap < _raw(horizon));
return TimeValue{wrap}; return TimeValue{wrap};
}; };

View file

@ -101,7 +101,7 @@ namespace test{
CHECK (!(var < ref) ); CHECK (!(var < ref) );
CHECK ( (var > ref) ); CHECK ( (var > ref) );
gavl_time_t gat(var); raw_time_64 gat(var);
CHECK (!(gat == ref) ); CHECK (!(gat == ref) );
CHECK ( (gat != ref) ); CHECK ( (gat != ref) );
CHECK ( (gat >= ref) ); CHECK ( (gat >= ref) );

View file

@ -123,13 +123,13 @@ namespace test{
*/ */
class TimeControl_test : public Test class TimeControl_test : public Test
{ {
gavl_time_t raw_time_64
random_or_get (string arg) random_or_get (string arg)
{ {
if (isnil(arg)) if (isnil(arg))
return gavl_time_t(1 + rani (100000)) * TimeValue::SCALE; return raw_time_64(1 + rani (100000)) * TimeValue::SCALE;
else else
return lexical_cast<gavl_time_t> (arg); return lexical_cast<raw_time_64> (arg);
} }

View file

@ -61,13 +61,13 @@ namespace test{
*/ */
class TimeMutation_test : public Test class TimeMutation_test : public Test
{ {
gavl_time_t raw_time_64
random_or_get (string arg) random_or_get (string arg)
{ {
if (isnil(arg)) if (isnil(arg))
return gavl_time_t(1 + rani (100000)) * TimeValue::SCALE; return raw_time_64(1 + rani (100000)) * TimeValue::SCALE;
else else
return lexical_cast<gavl_time_t> (arg); return lexical_cast<raw_time_64> (arg);
} }
struct TestValues struct TestValues

View file

@ -44,7 +44,7 @@ namespace test{
*/ */
class TimeValue_test : public Test class TimeValue_test : public Test
{ {
gavl_time_t raw_time_64
random_or_get (Arg arg) random_or_get (Arg arg)
{ {
if (isnil(arg)) if (isnil(arg))
@ -53,7 +53,7 @@ namespace test{
return 1 + rani(10000); return 1 + rani(10000);
} }
else else
return lexical_cast<gavl_time_t> (arg[1]); return lexical_cast<raw_time_64> (arg[1]);
} }
@ -101,7 +101,7 @@ namespace test{
CHECK (val < max); CHECK (val < max);
// mixed comparisons with raw numeric time // mixed comparisons with raw numeric time
gavl_time_t g2 (-2); raw_time_64 g2 (-2);
CHECK (zero > g2); CHECK (zero > g2);
CHECK (one > g2); CHECK (one > g2);
CHECK (one >= g2); CHECK (one >= g2);
@ -142,7 +142,7 @@ namespace test{
CHECK (var < Time::MAX); CHECK (var < Time::MAX);
CHECK (var > Time::MIN); CHECK (var > Time::MIN);
gavl_time_t raw (var); raw_time_64 raw (var);
CHECK (raw == org); CHECK (raw == org);
CHECK (raw > org - two); CHECK (raw > org - two);

View file

@ -235,7 +235,7 @@ namespace test {
{ {
Time frame{pipeline.currPoint}; // can access the embedded PipeFrameTick core to get "currPoint" (nominal time) Time frame{pipeline.currPoint}; // can access the embedded PipeFrameTick core to get "currPoint" (nominal time)
Job job = pipeline->ticket().createJobFor(frame); // looking always at the second element, which is the current JobTicket Job job = pipeline->ticket().createJobFor(frame); // looking always at the second element, which is the current JobTicket
TimeValue nominalTime{job.parameter.nominalTime}; // job parameter holds the microseconds (gavl_time_t) TimeValue nominalTime{job.parameter.nominalTime}; // job parameter holds the microseconds (raw_time_64)
int32_t mark = job.parameter.invoKey.part.a; // the MockDispatcher places the given "mark" here int32_t mark = job.parameter.invoKey.part.a; // the MockDispatcher places the given "mark" here
return _Fmt{"J(%d|%s)"} % mark % nominalTime; return _Fmt{"J(%d|%s)"} % mark % nominalTime;
}; };
@ -309,7 +309,7 @@ namespace test {
auto visualise = [](auto& pipeline) -> string auto visualise = [](auto& pipeline) -> string
{ {
Job job = pipeline.buildJob(); // let the JobPlanning construct the »current job« Job job = pipeline.buildJob(); // let the JobPlanning construct the »current job«
TimeValue nominalTime{job.parameter.nominalTime}; // job parameter holds the microseconds (gavl_time_t) TimeValue nominalTime{job.parameter.nominalTime}; // job parameter holds the microseconds (raw_time_64)
int32_t mark = job.parameter.invoKey.part.a; // the MockDispatcher places the given "mark" here int32_t mark = job.parameter.invoKey.part.a; // the MockDispatcher places the given "mark" here
TimeValue deadline{pipeline.determineDeadline()}; TimeValue deadline{pipeline.determineDeadline()};
return _Fmt{"J(%d|%s⧐%s)"} return _Fmt{"J(%d|%s⧐%s)"}

View file

@ -20,13 +20,18 @@
#include "lib/test/test.h" #include "lib/test/test.h"
#include "lib/time.h"
#include <inttypes.h>
#include <ctype.h> #include <ctype.h>
#include <nobug.h> #include <nobug.h>
typedef int64_t raw_time_64; //////////////////////////////////////////////////////////////////////////////TICKET #1259 turn time.h in to a C++ implementation header
#include "lib/time.h" /////////////////////////////////////////////////////////////////////////////////////TICKET #1259 this should not be a general purpose library, but rather an implementation base
static int static int
calculate_framecount (gavl_time_t t, uint fps) calculate_framecount (raw_time_64 t, uint fps)
{ {
return lumiera_quantise_frames_fps (t,0,fps); return lumiera_quantise_frames_fps (t,0,fps);
} }
@ -48,9 +53,9 @@ const int FPS = 24;
TEST (basic) TEST (basic)
{ {
// Zero // Zero
gavl_time_t t = lumiera_build_time (0,0,0,0); raw_time_64 t = lumiera_build_time (0,0,0,0);
CHECK ((gavl_time_t) t == 0); CHECK ((raw_time_64) t == 0);
CHECK (lumiera_time_millis (t) == 0); CHECK (lumiera_time_millis (t) == 0);
CHECK (lumiera_time_seconds (t) == 0); CHECK (lumiera_time_seconds (t) == 0);
CHECK (lumiera_time_minutes (t) == 0); CHECK (lumiera_time_minutes (t) == 0);
@ -83,7 +88,7 @@ TEST (basic)
TEST (fps) TEST (fps)
{ {
gavl_time_t t = lumiera_build_time_fps (FPS, FRAMES, SECONDS, MINUTES, HOURS); raw_time_64 t = lumiera_build_time_fps (FPS, FRAMES, SECONDS, MINUTES, HOURS);
CHECK (lumiera_time_millis (t) == FRAMES * 1000 / FPS); CHECK (lumiera_time_millis (t) == FRAMES * 1000 / FPS);
CHECK (lumiera_time_seconds (t) == SECONDS); CHECK (lumiera_time_seconds (t) == SECONDS);
@ -102,9 +107,9 @@ TEST (fps)
TEST (ntsc_drop_frame) TEST (ntsc_drop_frame)
{ {
// Make sure frame 0 begins at 0 // Make sure frame 0 begins at 0
gavl_time_t t = lumiera_build_time_ntsc_drop (0, 0, 0, 0); raw_time_64 t = lumiera_build_time_ntsc_drop (0, 0, 0, 0);
CHECK ((gavl_time_t) t == 0); CHECK ((raw_time_64) t == 0);
CHECK (lumiera_time_millis (t) == 0); CHECK (lumiera_time_millis (t) == 0);
CHECK (lumiera_time_seconds (t) == 0); CHECK (lumiera_time_seconds (t) == 0);
CHECK (lumiera_time_minutes (t) == 0); CHECK (lumiera_time_minutes (t) == 0);

View file

@ -67,6 +67,7 @@ namespace stage{
namespace model{ namespace model{
namespace test { namespace test {
using lib::time::raw_time_64;
namespace { // simplified notation for expected results... namespace { // simplified notation for expected results...
@ -577,7 +578,7 @@ namespace test {
CHECK (2_r/3 < poison and poison < 1); // looks innocuous... CHECK (2_r/3 < poison and poison < 1); // looks innocuous...
CHECK (poison + Time::SCALE < 0); // simple calculations fail due to numeric overflow CHECK (poison + Time::SCALE < 0); // simple calculations fail due to numeric overflow
CHECK (poison * Time::SCALE < 0); CHECK (poison * Time::SCALE < 0);
CHECK (-6 == rational_cast<gavl_time_t>(poison * Time::SCALE)); // naive conversion to µ-ticks would lead to overflow CHECK (-6 == rational_cast<raw_time_64>(poison * Time::SCALE)); // naive conversion to µ-ticks would lead to overflow
CHECK (671453 == _raw(Time(FSecs(poison)))); // however the actual conversion routine is safeguarded CHECK (671453 == _raw(Time(FSecs(poison)))); // however the actual conversion routine is safeguarded
CHECK (671453.812f == rational_cast<float>(poison)*Time::SCALE); CHECK (671453.812f == rational_cast<float>(poison)*Time::SCALE);
@ -667,7 +668,7 @@ namespace test {
CHECK (win.overallSpan().duration() == TimeValue{307445734561825860}); // However, all base values turn out unaffected CHECK (win.overallSpan().duration() == TimeValue{307445734561825860}); // However, all base values turn out unaffected
CHECK (win.visible().duration() == TimeValue{856350691}); CHECK (win.visible().duration() == TimeValue{856350691});
TimeValue targetPos{gavl_time_t(_raw(win.overallSpan().duration()) // based on the overall span... TimeValue targetPos{raw_time_64(_raw(win.overallSpan().duration()) // based on the overall span...
* rational_cast<double> (poison))}; // the given toxic factor would point at that target position * rational_cast<double> (poison))}; // the given toxic factor would point at that target position
CHECK (targetPos == TimeValue{206435633551724864}); CHECK (targetPos == TimeValue{206435633551724864});

View file

@ -339,7 +339,7 @@ namespace test {
{ {
auto N = AVERAGE_EPOCHS; auto N = AVERAGE_EPOCHS;
auto averageTicks = double(_raw(old))*(N-1)/N + contribution/N; auto averageTicks = double(_raw(old))*(N-1)/N + contribution/N;
return TimeValue{gavl_time_t (floor (averageTicks))}; return TimeValue{raw_time_64 (floor (averageTicks))};
}; };
TimeVar step = bFlow.getEpochStep(); TimeVar step = bFlow.getEpochStep();
@ -396,8 +396,8 @@ namespace test {
{ {
const size_t FPS = 200; const size_t FPS = 200;
const size_t TICK_P_S = FPS * ACTIVITIES_P_FR; // Simulated throughput 200 frames per second const size_t TICK_P_S = FPS * ACTIVITIES_P_FR; // Simulated throughput 200 frames per second
const gavl_time_t STP = Time::SCALE / TICK_P_S; // Simulation stepping (here 2 steps per ms) const raw_time_64 STP = Time::SCALE / TICK_P_S; // Simulation stepping (here 2 steps per ms)
const gavl_time_t RUN = _raw(Time{0,0,3}); // nominal length of the simulation time axis const raw_time_64 RUN = _raw(Time{0,0,3}); // nominal length of the simulation time axis
Offset BASE_DEADLINE{FSecs{1,2}}; // base pre-roll before deadline Offset BASE_DEADLINE{FSecs{1,2}}; // base pre-roll before deadline
Offset SPREAD_DEAD{FSecs{2,100}}; // random spread of deadline around base Offset SPREAD_DEAD{FSecs{2,100}}; // random spread of deadline around base
const uint INVOKE_LAG = _raw(Time{250,0}) /STP; // „invoke“ the Activity after simulated 250ms (≙ 500 steps) const uint INVOKE_LAG = _raw(Time{250,0}) /STP; // „invoke“ the Activity after simulated 250ms (≙ 500 steps)

View file

@ -129698,8 +129698,8 @@ StM_bind(Builder&lt;R1&gt; b1, Extension&lt;R1,R2&gt; extension)
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1746196449003" ID="ID_1070775068" MODIFIED="1746196453932" TEXT="Video-Display"> <node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1746196449003" ID="ID_1070775068" MODIFIED="1746196453932" TEXT="Video-Display">
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1746196482500" ID="ID_1819581335" LINK="https://issues.lumiera.org/ticket/1403" MODIFIED="1747342428317" TEXT=" #1403 Invesitgate if XV displayer can be revived "> <node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1746196482500" ID="ID_1819581335" LINK="https://issues.lumiera.org/ticket/1403" MODIFIED="1747342428317" TEXT=" #1403 Invesitgate if XV displayer can be revived ">
<linktarget COLOR="#fefeb4" DESTINATION="ID_1819581335" ENDARROW="Default" ENDINCLINATION="-2783;152;" ID="Arrow_ID_1160980366" SOURCE="ID_1219347509" STARTARROW="None" STARTINCLINATION="-4870;297;"/>
<linktarget COLOR="#fdebca" DESTINATION="ID_1819581335" ENDARROW="Default" ENDINCLINATION="-2783;152;" ID="Arrow_ID_421873944" SOURCE="ID_150758489" STARTARROW="None" STARTINCLINATION="1417;60;"/> <linktarget COLOR="#fdebca" DESTINATION="ID_1819581335" ENDARROW="Default" ENDINCLINATION="-2783;152;" ID="Arrow_ID_421873944" SOURCE="ID_150758489" STARTARROW="None" STARTINCLINATION="1417;60;"/>
<linktarget COLOR="#fefeb4" DESTINATION="ID_1819581335" ENDARROW="Default" ENDINCLINATION="-2783;152;" ID="Arrow_ID_1160980366" SOURCE="ID_1219347509" STARTARROW="None" STARTINCLINATION="-4870;297;"/>
<icon BUILTIN="hourglass"/> <icon BUILTIN="hourglass"/>
<node COLOR="#338800" CREATED="1746196518190" ID="ID_411481779" MODIFIED="1747013174739" TEXT="Research-Setup"> <node COLOR="#338800" CREATED="1746196518190" ID="ID_411481779" MODIFIED="1747013174739" TEXT="Research-Setup">
<icon BUILTIN="button_ok"/> <icon BUILTIN="button_ok"/>
@ -159479,18 +159479,21 @@ unsigned int ThreadIdAsInt = *static_cast&lt;unsigned int*&gt;(static_cast&lt;vo
</html></richcontent> </html></richcontent>
<icon BUILTIN="yes"/> <icon BUILTIN="yes"/>
</node> </node>
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1742256149038" FOLDED="true" ID="ID_1347393646" MODIFIED="1742256644046" TEXT="welche Rolle k&#xf6;nnen andere Libraries hier noch spielen?"> <node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1742256149038" ID="ID_1347393646" MODIFIED="1747523933091" TEXT="welche Rolle k&#xf6;nnen andere Libraries hier noch spielen?">
<font NAME="SansSerif" SIZE="12"/> <font NAME="SansSerif" SIZE="12"/>
<icon BUILTIN="help"/> <icon BUILTIN="help"/>
<node CREATED="1742256164252" ID="ID_798828861" MODIFIED="1742256311817" TEXT="konkret: Gavl und Gmerlin"> <node CREATED="1742256164252" ID="ID_798828861" LINK="https://github.com/bplaum/gavl" MODIFIED="1747524023410" TEXT="konkret: Gavl und Gmerlin">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head/> <head>
</head>
<body> <body>
<p> <p>
Christian kannte bereits Burkart Pflaum, und hat uns auf dessen Libraries aufmerksam gemacht. Die Libraries sind vorbildlich in iherer Struktur und in dem beschr&#228;nkten Scope. Wahrscheinlich sind sie problemloser einzubinden als FFmpeg. Aber das Kernproblem bleibt: das ist eine one-Man-Show, und wir werden trotzdem auf FFmpeg nicht verzichten k&#246;nnen.... Christian kannte bereits Burkart Pflaum, und hat uns auf dessen Libraries aufmerksam gemacht. Die Libraries sind vorbildlich in iherer Struktur und in dem beschr&#228;nkten Scope. Wahrscheinlich sind sie problemloser einzubinden als FFmpeg. Aber das Kernproblem bleibt: das ist eine one-Man-Show, und wir werden trotzdem auf FFmpeg nicht verzichten k&#246;nnen....
</p> </p>
</body> </body>
</html></richcontent> </html>
</richcontent>
<node CREATED="1742256340945" ID="ID_457200888" MODIFIED="1742256484596" TEXT="denkbar als Erg&#xe4;nzung, sollte FFmpeg tats&#xe4;chliche Schw&#xe4;chen zeigen"> <node CREATED="1742256340945" ID="ID_457200888" MODIFIED="1742256484596" TEXT="denkbar als Erg&#xe4;nzung, sollte FFmpeg tats&#xe4;chliche Schw&#xe4;chen zeigen">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head/> <head/>
@ -162285,7 +162288,8 @@ Since then others have made contributions, see the log for the history.</font></
<icon BUILTIN="button_ok"/> <icon BUILTIN="button_ok"/>
</node> </node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1742168602576" ID="ID_871737890" MODIFIED="1742168698565" TEXT="Gmerlin"> <node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1742168602576" ID="ID_871737890" MODIFIED="1742168698565" TEXT="Gmerlin">
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1742249270854" ID="ID_1347801315" MODIFIED="1742249278755" TEXT="falsch! es ist Gavl"> <node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1742249270854" ID="ID_1347801315" MODIFIED="1747524127181" TEXT="falsch! es ist Gavl">
<arrowlink COLOR="#c95974" DESTINATION="ID_219954631" ENDARROW="Default" ENDINCLINATION="813;-128;" ID="Arrow_ID_889384701" STARTARROW="None" STARTINCLINATION="1093;150;"/>
<icon BUILTIN="broken-line"/> <icon BUILTIN="broken-line"/>
</node> </node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1742249279746" ID="ID_1189167261" MODIFIED="1742249293729" TEXT="Vorsicht: Upgrade auf Version-2"> <node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1742249279746" ID="ID_1189167261" MODIFIED="1742249293729" TEXT="Vorsicht: Upgrade auf Version-2">
@ -162713,8 +162717,7 @@ Since then others have made contributions, see the log for the history.</font></
man hat ein time::Control (was auch immer das in Zukunft sein wird), welches mit einem Change-Signal verbunden wird. GUI-seitig verdrahtet man dieses Signal mit dem Code, der die tats&#228;chliche &#196;nderung des Presentation-State macht man hat ein time::Control (was auch immer das in Zukunft sein wird), welches mit einem Change-Signal verbunden wird. GUI-seitig verdrahtet man dieses Signal mit dem Code, der die tats&#228;chliche &#196;nderung des Presentation-State macht
</p> </p>
</body> </body>
</html> </html></richcontent>
</richcontent>
<arrowlink COLOR="#7f6a74" DESTINATION="ID_1446567013" ENDARROW="Default" ENDINCLINATION="-1578;239;" ID="Arrow_ID_590507558" STARTARROW="None" STARTINCLINATION="-2460;177;"/> <arrowlink COLOR="#7f6a74" DESTINATION="ID_1446567013" ENDARROW="Default" ENDINCLINATION="-1578;239;" ID="Arrow_ID_590507558" STARTARROW="None" STARTINCLINATION="-2460;177;"/>
</node> </node>
</node> </node>
@ -162775,8 +162778,7 @@ Since then others have made contributions, see the log for the history.</font></
Abgesehen davon ist der Code inzwischen auch technologisch &#252;berholt und wird mit GTK-4 nicht mehr funktionieren Abgesehen davon ist der Code inzwischen auch technologisch &#252;berholt und wird mit GTK-4 nicht mehr funktionieren
</p> </p>
</body> </body>
</html> </html></richcontent>
</richcontent>
</node> </node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1747355273449" ID="ID_1703747958" MODIFIED="1747355286397" TEXT="ehrlich gesagt: wegwerfen und neuschreiben"> <node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1747355273449" ID="ID_1703747958" MODIFIED="1747355286397" TEXT="ehrlich gesagt: wegwerfen und neuschreiben">
<font ITALIC="true" NAME="SansSerif" SIZE="14"/> <font ITALIC="true" NAME="SansSerif" SIZE="14"/>
@ -162785,10 +162787,11 @@ Since then others have made contributions, see the log for the history.</font></
</node> </node>
</node> </node>
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1742249461535" ID="ID_1554376708" MODIFIED="1742256553530" TEXT="Rolle der lib-Gavl &#xfc;berpr&#xfc;fen"> <node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1742249461535" ID="ID_1554376708" MODIFIED="1747524255970" TEXT="Rolle der lib-Gavl &#xfc;berpr&#xfc;fen">
<linktarget COLOR="#a41b18" DESTINATION="ID_1554376708" ENDARROW="Default" ENDINCLINATION="440;-36;" ID="Arrow_ID_608156847" SOURCE="ID_1683248748" STARTARROW="None" STARTINCLINATION="193;12;"/> <linktarget COLOR="#a41b18" DESTINATION="ID_1554376708" ENDARROW="Default" ENDINCLINATION="440;-36;" ID="Arrow_ID_608156847" SOURCE="ID_1683248748" STARTARROW="None" STARTINCLINATION="193;12;"/>
<icon BUILTIN="flag-yellow"/> <linktarget COLOR="#4c3b8b" DESTINATION="ID_1554376708" ENDARROW="Default" ENDINCLINATION="219;519;" ID="Arrow_ID_589652743" SOURCE="ID_219954631" STARTARROW="None" STARTINCLINATION="326;-188;"/>
<node CREATED="1742256560103" ID="ID_1579484179" MODIFIED="1742266889152" TEXT="so traurig es ist: Gavl ist nicht erste Wahl"> <icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#95060e" CREATED="1742256560103" ID="ID_1579484179" MODIFIED="1747524214221" TEXT="so traurig es ist: Gavl ist nicht erste Wahl">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head/> <head/>
<body> <body>
@ -162801,8 +162804,9 @@ Since then others have made contributions, see the log for the history.</font></
</body> </body>
</html></richcontent> </html></richcontent>
<arrowlink COLOR="#592f6e" DESTINATION="ID_450633851" ENDARROW="Default" ENDINCLINATION="338;12;" ID="Arrow_ID_637755539" STARTARROW="None" STARTINCLINATION="466;0;"/> <arrowlink COLOR="#592f6e" DESTINATION="ID_450633851" ENDARROW="Default" ENDINCLINATION="338;12;" ID="Arrow_ID_637755539" STARTARROW="None" STARTINCLINATION="466;0;"/>
<icon BUILTIN="yes"/>
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1744719728307" ID="ID_1783840760" MODIFIED="1744719819653" TEXT="siehe steam/external/libgavl.hpp"> <node COLOR="#435e98" CREATED="1744719728307" ID="ID_1783840760" MODIFIED="1747524201441" TEXT="siehe steam/external/libgavl.hpp">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head/> <head/>
<body> <body>
@ -162812,6 +162816,98 @@ Since then others have made contributions, see the log for the history.</font></
</body> </body>
</html></richcontent> </html></richcontent>
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="flag-yellow"/>
<node CREATED="1747489068132" ID="ID_491604266" MODIFIED="1747489074061" TEXT="wird derzeit &#xfc;berhaupt nicht verwendet"/>
<node CREATED="1747489084369" ID="ID_1779252669" MODIFIED="1747489105751" TEXT="wohl auch gar nicht implementierbar"/>
<node CREATED="1747489074724" ID="ID_663261791" MODIFIED="1747489124777" TEXT="ist eine blo&#xdf;e leere H&#xfc;lle"/>
<node CREATED="1747489111527" ID="ID_229720543" MODIFIED="1747489130041" TEXT="zeigt aber die Richtung"/>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1747489138341" ID="ID_621636330" MODIFIED="1747489143519" TEXT="dokumentieren">
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
</node>
</node>
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#166d3d" CREATED="1747489147636" ID="ID_1626357015" MODIFIED="1747524236658" TEXT="gavl_time_t ersetzen">
<icon BUILTIN="yes"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1747489190149" ID="ID_395347682" LINK="https://issues.lumiera.org/ticket/1261" MODIFIED="1747489218934" TEXT="siehe Design-Skizze in #1261">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1747489228725" ID="ID_397750077" MODIFIED="1747489369180" TEXT="verwende einen Namen exakt gleicher L&#xe4;nge">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
raw_time_64
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1747489254856" ID="ID_971197875" MODIFIED="1747489345064" TEXT="danach k&#xf6;nnen alle Includes des C-Headers time.h weg">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
schon seit langem will ich von der &quot;C-Time-Library&quot; weg, denn diese ist gradezu eine Einladung, Timecode-Operationen ad-hoc zu implementieren
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1747489277561" ID="ID_1782395866" MODIFIED="1747489284084" TEXT="einzige Ausnahme: Time.cpp"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1747520420088" ID="ID_1585137684" MODIFIED="1747524248767" TEXT="C-Library f&#xfc;r Time-Handling aufl&#xf6;sen">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1747520433501" ID="ID_1627011016" MODIFIED="1747520503864" TEXT="die ist mir schon lange ein &#xbb;Dorn im Auge&#xab;">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
....weil eine solche Library gradezu dazu einl&#228;d, sich nicht mit den &#8222;m&#252;hsamen&#8220; Abstraktionen des Time-Handling-Frameworks herumzuschlagen, sondern stattessen <i>einfach mit Zahlen zu rechnen.</i>
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1747520507617" ID="ID_391130031" MODIFIED="1747520575548" TEXT="sollte die konkreten Verwendungen durchsehen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...m&#246;glicherweise lassen sich diese Funktionen n&#228;mlich in Gruppen einteilen und dann direkt in einen anonymen namespace in die jeweilige Translation-Unit schieben....
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1747520518579" ID="ID_1232667630" MODIFIED="1747520531129" TEXT="m&#xfc;&#xdf;te dann auch den C-Test (test-time) aufl&#xf6;sen">
<node CREATED="1747520690709" ID="ID_920147641" MODIFIED="1747520695437" TEXT="der ist eigentlich nicht lang"/>
<node CREATED="1747520696080" ID="ID_1610185152" MODIFIED="1747520880755" TEXT="und bei n&#xe4;herer Betrachtung ziemlich banal">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
Der Test t&#228;uscht: weil er in C geschrieben ist, sieht er so komplex aus. Dabei besteht die erste H&#228;lfte lediglich draus, eine Konstruktor-Funktion zu testen. Der sinnvolle Kern daran ist die decimator-Sequenz zum Herunterbrechen von Zeiten. Die wird hier aber nur oberfl&#228;chlich getestet. Da sollte man, wenn schon, wirklich auf die Grenzf&#228;lle losgehen &#10233; Test neu schreiben!
</p>
<p>
</p>
<p>
Der zweite Teil besteht im <i>Antesten</i>&#160;der drop-Frame-Umwandlung &#10233; auch das in eigenst&#228;ndigen neuen Test packen
</p>
</body>
</html>
</richcontent>
</node>
</node>
</node> </node>
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1746059853111" ID="ID_975342117" MODIFIED="1746059870062" TEXT="auch altes RenderNode-Framework zur&#xfc;ckbauen"> <node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1746059853111" ID="ID_975342117" MODIFIED="1746059870062" TEXT="auch altes RenderNode-Framework zur&#xfc;ckbauen">
@ -163898,6 +163994,15 @@ Since then others have made contributions, see the log for the history.</font></
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1742313583059" ID="ID_580462484" MODIFIED="1742313592747" TEXT="Dependency-Liste aktualisieren"> <node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1742313583059" ID="ID_580462484" MODIFIED="1742313592747" TEXT="Dependency-Liste aktualisieren">
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1747524067725" ID="ID_219954631" MODIFIED="1747524193833" TEXT="Abh&#xe4;ngigkeit GAVL">
<arrowlink COLOR="#4c3b8b" DESTINATION="ID_1554376708" ENDARROW="Default" ENDINCLINATION="219;519;" ID="Arrow_ID_589652743" STARTARROW="None" STARTINCLINATION="326;-188;"/>
<linktarget COLOR="#c95974" DESTINATION="ID_219954631" ENDARROW="Default" ENDINCLINATION="813;-128;" ID="Arrow_ID_889384701" SOURCE="ID_1347801315" STARTARROW="None" STARTINCLINATION="1093;150;"/>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1747524076555" ID="ID_1964951178" MODIFIED="1747524084106" TEXT="behalte das vorerst noch bei">
<icon BUILTIN="yes"/>
</node>
<node CREATED="1747524085359" ID="ID_976130232" LINK="https://github.com/bplaum/gavl" MODIFIED="1747524093250" TEXT="Achtung: umgezogen auf Gitub"/>
</node>
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1742313577420" ID="ID_527584176" MODIFIED="1742313592746" TEXT="Bau-Anleitung &#xfc;berarbeiten"> <node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1742313577420" ID="ID_527584176" MODIFIED="1742313592746" TEXT="Bau-Anleitung &#xfc;berarbeiten">
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="flag-yellow"/>