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'):
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:
conf.env.mergeConf('gavl')

View file

@ -20,7 +20,7 @@ Description
* We use an uniform time type. Time is time, not frames, samples etc.
* All timings in Lumiera are based on integral datatypes
* 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
- Get time in different formats (fractional seconds, frame counts)
- 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 values are represented by a family of opaque date types
with overloaded operators. The implementation is based on `gavl_time_t`,
an integral (µsec) time tick value. Thus, the arithmetic on time values
and time spans is limited and any Time handling and conversion is
centralised in library routines.
with overloaded operators. The implementation was inspired by `gavl_time_t`
and is thus based on a µ-seccond time grid, represented as 64-bit integer.
Thus, the arithmetic on time values and time spans is limited and any Time
handling and conversion is centralised in library routines.
We distinguish between time values and a _quantisation_ into a frame
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
** 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 timequant.hpp
@ -43,11 +49,12 @@
#define LUMIERA_TIME_H
#include <inttypes.h>
#include <gavl/gavl.h>
#ifdef __cplusplus /*=================== C++ facilities ===================== */
#include "lib/time/timevalue.hpp"
using lib::time::raw_time_64;
/**
* 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.
* This was deemed irrelevant in practice.
*/
gavl_time_t
raw_time_64
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
* origin to be at zero.
*/
gavl_time_t
raw_time_64
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
* @throw error::Logic on zero framerate
*/
gavl_time_t
raw_time_64
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,
* 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.
* @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.
* @warning the resulting value is limited to (Time::Min, Time::MAX)
*/
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
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_.
@ -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
* clipped, because the result, relative to origin, needs to be <= Time::MAX
*/
gavl_time_t
lumiera_quantise_time (gavl_time_t time, gavl_time_t origin, gavl_time_t grid);
raw_time_64
lumiera_quantise_time (raw_time_64 time, raw_time_64 origin, raw_time_64 grid);
/**
* Calculate time of a grid point (frame start)
* @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
*/
gavl_time_t
lumiera_time_of_gridpoint (int64_t nr, gavl_time_t origin, gavl_time_t grid);
raw_time_64
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.
@ -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 hours number of hours
*/
gavl_time_t
raw_time_64
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 hours number of hours
*/
gavl_time_t
raw_time_64
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.
* @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);
/** Extract the hour part of given time. */
int
lumiera_time_hours (gavl_time_t time);
lumiera_time_hours (raw_time_64 time);
/** Extract the minute part of given time. */
int
lumiera_time_minutes (gavl_time_t time);
lumiera_time_minutes (raw_time_64 time);
/** Extract the seconds part of given time. */
int
lumiera_time_seconds (gavl_time_t time);
lumiera_time_seconds (raw_time_64 time);
/** Extract the milliseconds part of given time. */
int
lumiera_time_millis (gavl_time_t time);
lumiera_time_millis (raw_time_64 time);
/**
* Extract the remaining frame part of given time.
* @param fps frame rate (frames per second)
*/
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.
*/
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.
*/
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.
*/
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.
*/
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.
*/
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
** Lumiera time handling core implementation unit.
** This translation unit generates code for the Lumiera internal time wrapper,
** based on gavl_time_t, associated constants, marker classes for the derived
** time entities (TimeVar, Offset, Duration, TimeSpan, FrameRate) and for the
** basic time and frame rate conversion functions.
** based on 64bit integral µ-tick values, associated constants, marker classes
** for the derived time entities (TimeVar, Offset, Duration, TimeSpan, FrameRate)
** and for the basic time and frame rate 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
@ -75,11 +75,11 @@ namespace meta {
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 */
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::ZERO;
@ -94,8 +94,8 @@ namespace time {
/** scale factor _used locally within this implementation header_.
* GAVL_TIME_SCALE rsp. TimeValue::SCALE is the correct factor or dividend when using
* gavl_time_t for display on a scale with seconds. Since we want to use milliseconds,
* TimeValue::SCALE (µ-ticks, i.e. 1e6) is the correct factor or dividend when using
* 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. */
#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. */
TimeValue::operator string() const
{
gavl_time_t time = t_;
raw_time_64 time = t_;
int64_t millis, seconds;
bool negative = (time < 0);
@ -163,7 +163,7 @@ namespace time {
*/
Time::operator string() const
{
gavl_time_t time = t_;
raw_time_64 time = t_;
int millis, seconds, minutes, hours;
bool negative = (time < 0);
@ -233,7 +233,7 @@ namespace time {
/** @internal backdoor to sneak in a raw time value
* bypassing any normalisation and limiting */
TimeValue
TimeValue::buildRaw_ (gavl_time_t raw)
TimeValue::buildRaw_ (raw_time_64 raw)
{
return reinterpret_cast<TimeValue const&> (raw);
}
@ -326,7 +326,7 @@ namespace time {
{
boost::rational<int64_t> distance (this->t_);
distance *= factor;
gavl_time_t microTicks = floordiv (distance.numerator(), distance.denominator());
raw_time_64 microTicks = floordiv (distance.numerator(), distance.denominator());
return Offset{buildRaw_(microTicks)};
}
@ -337,7 +337,7 @@ namespace time {
{
double distance(this->t_);
distance *= factor;
gavl_time_t microTicks = floor (distance);
raw_time_64 microTicks = floor (distance);
return Offset{buildRaw_(microTicks)};
}
@ -383,7 +383,7 @@ namespace util {
char*
lumiera_tmpbuf_print_time (gavl_time_t time)
lumiera_tmpbuf_print_time (raw_time_64 time)
{
int milliseconds, seconds, minutes, hours;
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
gavl_time_t
raw_time_64
lumiera_rational_to_time (FSecs const& fractionalSeconds)
{
// 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)
* std::numeric_limits<int64_t>::max();
return gavl_time_t(util::reQuant (fractionalSeconds.numerator()
return raw_time_64(util::reQuant (fractionalSeconds.numerator()
,fractionalSeconds.denominator()
,lib::time::TimeValue::SCALE
));
}
gavl_time_t
raw_time_64
lumiera_framecount_to_time (uint64_t frameCount, FrameRate const& fps)
{
// convert to 64bit
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)
{
if (!fps)
@ -447,20 +447,20 @@ lumiera_frame_duration (FrameRate const& fps)
namespace { // implementation: basic frame quantisation....
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;
return floordiv (time,grid);
}
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_divisor);
const int64_t limit_num = std::numeric_limits<gavl_time_t>::max() / framerate;
const int64_t limit_den = std::numeric_limits<gavl_time_t>::max() / framerate_divisor;
const int64_t limit_num = std::numeric_limits<raw_time_64>::max() / framerate;
const int64_t limit_den = std::numeric_limits<raw_time_64>::max() / framerate_divisor;
const int64_t microScale {lib::time::TimeValue::SCALE};
// protect against numeric overflow
@ -474,7 +474,7 @@ namespace { // implementation: basic frame quantisation....
{
// direct calculation will overflow.
// 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);
}
}
@ -482,37 +482,37 @@ namespace { // implementation: basic frame quantisation....
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);
}
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);
}
gavl_time_t
lumiera_quantise_time (gavl_time_t time, gavl_time_t origin, gavl_time_t grid)
raw_time_64
lumiera_quantise_time (raw_time_64 time, raw_time_64 origin, raw_time_64 grid)
{
int64_t count = calculate_quantisation (time, origin, grid);
gavl_time_t alignedTime = count * grid;
raw_time_64 alignedTime = count * grid;
return alignedTime;
}
gavl_time_t
lumiera_time_of_gridpoint (int64_t nr, gavl_time_t origin, gavl_time_t grid)
raw_time_64
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;
}
gavl_time_t
raw_time_64
lumiera_build_time(long millis, uint secs, uint mins, uint hours)
{
gavl_time_t time = millis
raw_time_64 time = millis
+ 1000 * secs
+ 1000 * 60 * mins
+ 1000 * 60 * 60 * hours;
@ -520,10 +520,10 @@ lumiera_build_time(long millis, uint secs, uint mins, uint hours)
return time;
}
gavl_time_t
raw_time_64
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 * 60 * mins
+ 1000 * 60 * 60 * hours;
@ -532,31 +532,31 @@ lumiera_build_time_fps (uint fps, uint frames, uint secs, uint mins, uint hours)
}
int
lumiera_time_hours (gavl_time_t time)
lumiera_time_hours (raw_time_64 time)
{
return time / TIME_SCALE_MS / 1000 / 60 / 60;
}
int
lumiera_time_minutes (gavl_time_t time)
lumiera_time_minutes (raw_time_64 time)
{
return (time / TIME_SCALE_MS / 1000 / 60) % 60;
}
int
lumiera_time_seconds (gavl_time_t time)
lumiera_time_seconds (raw_time_64 time)
{
return (time / TIME_SCALE_MS / 1000) % 60;
}
int
lumiera_time_millis (gavl_time_t time)
lumiera_time_millis (raw_time_64 time)
{
return (time / TIME_SCALE_MS) % 1000;
}
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()));
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!!
*/
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);
@ -599,30 +599,30 @@ namespace { // implementation helper
}
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;
}
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;
}
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;
}
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;
}
gavl_time_t
raw_time_64
lumiera_build_time_ntsc_drop (uint frames, uint secs, uint mins, uint hours)
{
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
+ frames
- 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
result += 1; // without this adjustment the frame number

View file

@ -350,7 +350,7 @@ namespace time {
/** */
Secs::Secs (QuTime const& 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
** 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
** 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.
** 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
@ -30,7 +31,7 @@
** 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
** 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):
** - 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
@ -87,6 +88,7 @@
** @see timequant.hpp
** @see TimeValue_test
**
** [Lib-GAVL]: https://github.com/bplaum/gavl
*/
@ -100,11 +102,6 @@
#include <cstdlib>
#include <string>
extern "C" {
#include <stdint.h>
#include <gavl/gavltime.h>
}
namespace lib {
namespace time {
@ -118,11 +115,22 @@ namespace time {
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.
* These time values provide the implementation base
* 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,
* they are opaque and non-mutable.
* @note clients should prefer to use Time instances,
@ -132,12 +140,12 @@ namespace time {
*/
class TimeValue
: boost::totally_ordered<TimeValue,
boost::totally_ordered<TimeValue, gavl_time_t>>
boost::totally_ordered<TimeValue, raw_time_64>>
{
protected:
/** the raw (internal) time value
* used to implement the time types */
gavl_time_t t_;
raw_time_64 t_;
/** Assigning of time values is not allowed,
@ -153,9 +161,9 @@ namespace time {
friend class Mutation;
/** 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 */
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 */
TimeValue (TimeValue const& origin, TimeValue const& target)
@ -164,11 +172,11 @@ namespace time {
public:
/** Number of micro ticks (µs) per second as basic time scale */
static const gavl_time_t SCALE;
static const raw_time_64 SCALE;
explicit
TimeValue (gavl_time_t val) ///< time given in µ ticks here
TimeValue (raw_time_64 val) ///< time given in µ ticks here
: t_{limitedTime (val)}
{ }
@ -178,9 +186,9 @@ namespace time {
{ }
/** @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&);
static TimeValue buildRaw_(gavl_time_t);
static TimeValue buildRaw_(raw_time_64);
/** @internal diagnostics */
operator std::string () const;
@ -190,10 +198,10 @@ namespace time {
// Supporting totally_ordered
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, 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, 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, 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.
* Used within the engine at places where the underlying
* 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.
* beware: `long` is 32bit on i386
* @note any conversion to frame numbers should go through
@ -216,7 +224,7 @@ namespace time {
using FrameCnt = int64_t;
/** 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>;
@ -226,7 +234,7 @@ namespace time {
* allowing copy and re-accessing
* @note supports scaling by a factor,
* 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.
*/
class TimeVar
@ -258,7 +266,7 @@ namespace time {
}
/// 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
operator FSecs() const { return FSecs{t_, TimeValue::SCALE}; }
@ -708,8 +716,8 @@ namespace time {
return n;
}
inline gavl_time_t
symmetricLimit (gavl_time_t raw, TimeValue lim)
inline raw_time_64
symmetricLimit (raw_time_64 raw, TimeValue lim)
{
return raw > lim? _raw(lim)
: -raw > lim? -_raw(lim)
@ -744,21 +752,21 @@ namespace time {
* While Time entities are \c not a "safeInt"
* implementation, we limit new values to
* lower the likelihood of wrap-around */
inline gavl_time_t
TimeValue::limitedTime (gavl_time_t raw)
inline raw_time_64
TimeValue::limitedTime (raw_time_64 raw)
{
return symmetricLimit (raw, Time::MAX);
}
inline gavl_time_t
TimeValue::limitedDelta (gavl_time_t origin, gavl_time_t target)
inline raw_time_64
TimeValue::limitedDelta (raw_time_64 origin, raw_time_64 target)
{
if (0 > (origin^target))
{// prevent possible numeric wrap
origin = symmetricLimit (origin, Duration::MAX);
target = symmetricLimit (target, Duration::MAX);
}
gavl_time_t res = target - origin;
raw_time_64 res = target - origin;
return symmetricLimit (res, Duration::MAX);
}

View file

@ -29,7 +29,7 @@
#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 <boost/lexical_cast.hpp>
@ -40,9 +40,6 @@
#include <locale>
#include <string>
#include <gavl/gavl.h>
#include <sigc++/bind.h>
using boost::lexical_cast;
using sigc::mem_fun;
@ -433,7 +430,7 @@ namespace widget {
// void
// TimeCode::smpte_offset_changed()
// {
// gavl_time_t current;
// raw_time_64 current;
// switch (_mode) {
// case SMPTE:
@ -1278,7 +1275,7 @@ namespace widget {
Time
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));
}

View file

@ -21,6 +21,10 @@
** the referenced libraries, though. This will be done with adapter implementations,
** where the interface MediaImplLip defines those aspects actually used and required
** 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
** 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
** 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
** 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)
{
double stretched = _raw(epochStep_) * factor;
gavl_time_t microTicks(floor (stretched));
raw_time_64 microTicks(floor (stretched));
epochStep_ = TimeValue{microTicks};
}

View file

@ -124,7 +124,7 @@ union InvocationInstanceID
*/
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;
//////////////////////////////////////////////////////////////TODO: place an additional parameter value here, or make the instanceID globally unique?
////////////////////////////////////////////////////////////////////////////////////TICKET #1293 job invocation identity
@ -166,7 +166,7 @@ typedef lumiera_jobDefinition* LumieraJobDefinition;
*/
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;
lumiera_jobDefinition jobDefinition; ///< of interest only to Steam-Layer

View file

@ -362,7 +362,7 @@ namespace gear {
{
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));
return TimeValue{wrap};
};

View file

@ -101,7 +101,7 @@ namespace test{
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) );

View file

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

View file

@ -44,7 +44,7 @@ namespace test{
*/
class TimeValue_test : public Test
{
gavl_time_t
raw_time_64
random_or_get (Arg arg)
{
if (isnil(arg))
@ -53,7 +53,7 @@ namespace test{
return 1 + rani(10000);
}
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);
// mixed comparisons with raw numeric time
gavl_time_t g2 (-2);
raw_time_64 g2 (-2);
CHECK (zero > g2);
CHECK (one > g2);
CHECK (one >= g2);
@ -142,7 +142,7 @@ namespace test{
CHECK (var < Time::MAX);
CHECK (var > Time::MIN);
gavl_time_t raw (var);
raw_time_64 raw (var);
CHECK (raw == org);
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)
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
return _Fmt{"J(%d|%s)"} % mark % nominalTime;
};
@ -309,7 +309,7 @@ namespace test {
auto visualise = [](auto& pipeline) -> string
{
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
TimeValue deadline{pipeline.determineDeadline()};
return _Fmt{"J(%d|%s⧐%s)"}

View file

@ -20,13 +20,18 @@
#include "lib/test/test.h"
#include "lib/time.h"
#include <inttypes.h>
#include <ctype.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
calculate_framecount (gavl_time_t t, uint fps)
calculate_framecount (raw_time_64 t, uint fps)
{
return lumiera_quantise_frames_fps (t,0,fps);
}
@ -48,9 +53,9 @@ const int FPS = 24;
TEST (basic)
{
// 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_seconds (t) == 0);
CHECK (lumiera_time_minutes (t) == 0);
@ -83,7 +88,7 @@ TEST (basic)
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_seconds (t) == SECONDS);
@ -102,9 +107,9 @@ TEST (fps)
TEST (ntsc_drop_frame)
{
// 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_seconds (t) == 0);
CHECK (lumiera_time_minutes (t) == 0);

View file

@ -67,6 +67,7 @@ namespace stage{
namespace model{
namespace test {
using lib::time::raw_time_64;
namespace { // simplified notation for expected results...
@ -577,7 +578,7 @@ namespace test {
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);
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.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.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
CHECK (targetPos == TimeValue{206435633551724864});

View file

@ -339,7 +339,7 @@ namespace test {
{
auto N = AVERAGE_EPOCHS;
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();
@ -396,8 +396,8 @@ namespace test {
{
const size_t FPS = 200;
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 gavl_time_t RUN = _raw(Time{0,0,3}); // nominal length of the simulation time axis
const raw_time_64 STP = Time::SCALE / TICK_P_S; // Simulation stepping (here 2 steps per ms)
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 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)

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">
<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 ">
<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="#fefeb4" DESTINATION="ID_1819581335" ENDARROW="Default" ENDINCLINATION="-2783;152;" ID="Arrow_ID_1160980366" SOURCE="ID_1219347509" STARTARROW="None" STARTINCLINATION="-4870;297;"/>
<icon BUILTIN="hourglass"/>
<node COLOR="#338800" CREATED="1746196518190" ID="ID_411481779" MODIFIED="1747013174739" TEXT="Research-Setup">
<icon BUILTIN="button_ok"/>
@ -159479,18 +159479,21 @@ unsigned int ThreadIdAsInt = *static_cast&lt;unsigned int*&gt;(static_cast&lt;vo
</html></richcontent>
<icon BUILTIN="yes"/>
</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"/>
<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>
<head/>
<head>
</head>
<body>
<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....
</p>
</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">
<richcontent TYPE="NOTE"><html>
<head/>
@ -162285,7 +162288,8 @@ Since then others have made contributions, see the log for the history.</font></
<icon BUILTIN="button_ok"/>
</node>
<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"/>
</node>
<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
</p>
</body>
</html>
</richcontent>
</html></richcontent>
<arrowlink COLOR="#7f6a74" DESTINATION="ID_1446567013" ENDARROW="Default" ENDINCLINATION="-1578;239;" ID="Arrow_ID_590507558" STARTARROW="None" STARTINCLINATION="-2460;177;"/>
</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
</p>
</body>
</html>
</richcontent>
</html></richcontent>
</node>
<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"/>
@ -162785,10 +162787,11 @@ Since then others have made contributions, see the log for the history.</font></
</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;"/>
<icon BUILTIN="flag-yellow"/>
<node CREATED="1742256560103" ID="ID_1579484179" MODIFIED="1742266889152" TEXT="so traurig es ist: Gavl ist nicht erste Wahl">
<linktarget COLOR="#4c3b8b" DESTINATION="ID_1554376708" ENDARROW="Default" ENDINCLINATION="219;519;" ID="Arrow_ID_589652743" SOURCE="ID_219954631" STARTARROW="None" STARTINCLINATION="326;-188;"/>
<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>
<head/>
<body>
@ -162801,8 +162804,9 @@ Since then others have made contributions, see the log for the history.</font></
</body>
</html></richcontent>
<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 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>
<head/>
<body>
@ -162812,6 +162816,98 @@ Since then others have made contributions, see the log for the history.</font></
</body>
</html></richcontent>
<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 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 BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1742313583059" ID="ID_580462484" MODIFIED="1742313592747" TEXT="Dependency-Liste aktualisieren">
<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 BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1742313577420" ID="ID_527584176" MODIFIED="1742313592746" TEXT="Bau-Anleitung &#xfc;berarbeiten">
<icon BUILTIN="flag-yellow"/>