Timehandling: choose safer representation for fractional seconds (closes #939)
When drafting the time handling framework some years ago, I foresaw the possible danger of mixing up numbers relating to fractional seconds, with other plain numbers intended as frame counts or as micro ticks. Thus I deliberately picked an incompatible integer type for FSecs = boost::rational<long> However, using long is problematic in itself, since its actual bit length is not fixed, and especially on 32bit platforms long is quite surprisingly defined to be the same as int. However, meanwhile, using the new C++ features, I have blocked pretty much any possible implicit conversion path, requiring explicit conversions in the relevant ctor invocations. So, after weighting in the alternatives, FSecs is now defined as boost::rational<int64_t>.
This commit is contained in:
parent
8867ae55ad
commit
38837da65e
7 changed files with 214 additions and 48 deletions
|
|
@ -24,7 +24,7 @@
|
|||
/** @file grid.hpp
|
||||
** definition of a time grid abstraction for time and timecode handling.
|
||||
** This interface is the foundation to deal with _quantised_ (grid aligned)
|
||||
** time values, as is essential for handling of timecode data.
|
||||
** time values, which is essential for handling of timecode data.
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -43,12 +43,13 @@ namespace time {
|
|||
/**
|
||||
* Abstraction of a value alignment grid.
|
||||
* Such a grid has an underlying scale (origin and measurement)
|
||||
* and is comprised of distinct grid intervals, which can be addressed
|
||||
* by a ordering number, centred at origin with interval number zero.
|
||||
* The typical example is a 25fps time frame grid, but indeed the
|
||||
* spacing of the intervals is not necessarily constant. An entity
|
||||
* defining such a grid provides functions to calculate the
|
||||
* grid coordinates and to convert back to plain values.
|
||||
* and is comprised of consecutive grid intervals, joined at the
|
||||
* _grid points._ These can be addressed by an ordering number,
|
||||
* centred at origin with grid point number zero.
|
||||
* The classical example is a 25fps time frame grid, but in fact
|
||||
* the length of the intervals is not necessarily constant. An
|
||||
* entity defining such a grid provides functions to calculate
|
||||
* the grid coordinates and to convert back to plain values.
|
||||
* This includes a way of rounding to the next lower
|
||||
* grid point, usable for grid aligning values.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ extern "C" {
|
|||
#include <math.h>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <boost/rational.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
|
|
@ -73,6 +74,9 @@ namespace error = lumiera::error;
|
|||
|
||||
|
||||
namespace lib {
|
||||
namespace meta {
|
||||
extern const std::string FAILURE_INDICATOR;
|
||||
}
|
||||
namespace time {
|
||||
|
||||
|
||||
|
|
@ -175,17 +179,30 @@ namespace time {
|
|||
}
|
||||
|
||||
|
||||
namespace {
|
||||
template<typename INT>
|
||||
string
|
||||
renderFraction (INT const& frac, Literal postfx) noexcept
|
||||
try {
|
||||
std::ostringstream buffer;
|
||||
if (1 == frac.denominator() or 0 == frac.numerator())
|
||||
buffer << frac.numerator() << postfx;
|
||||
else
|
||||
buffer << frac <<postfx;
|
||||
return buffer.str();
|
||||
}
|
||||
catch(...)
|
||||
{ return meta::FAILURE_INDICATOR; }
|
||||
}
|
||||
|
||||
/** visual framerate representation (for diagnostics) */
|
||||
FrameRate::operator string() const
|
||||
{
|
||||
return 1==denominator() ? lexical_cast<string> (numerator())+"FPS"
|
||||
: lexical_cast<string> (numerator())
|
||||
+ "/"
|
||||
+ lexical_cast<string> (denominator())
|
||||
+ "FPS";
|
||||
return renderFraction (*this, "FPS");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** @internal backdoor to sneak in a raw time value
|
||||
* bypassing any normalisation and limiting */
|
||||
TimeValue
|
||||
|
|
@ -247,6 +264,13 @@ namespace time {
|
|||
|
||||
}} // namespace lib::Time
|
||||
|
||||
namespace util {
|
||||
string
|
||||
StringConv<lib::time::FSecs, void>::invoke (lib::time::FSecs val) noexcept
|
||||
{
|
||||
return lib::time::renderFraction (val, "sec");
|
||||
}
|
||||
} // namespace util
|
||||
|
||||
|
||||
|
||||
|
|
@ -285,7 +309,7 @@ lumiera_tmpbuf_print_time (gavl_time_t time)
|
|||
gavl_time_t
|
||||
lumiera_rational_to_time (FSecs const& fractionalSeconds)
|
||||
{
|
||||
return rational_cast<gavl_time_t> (lib::time::TimeValue::SCALE * fractionalSeconds);
|
||||
return rational_cast<gavl_time_t> (fractionalSeconds * int{lib::time::TimeValue::SCALE});
|
||||
}
|
||||
|
||||
gavl_time_t
|
||||
|
|
@ -304,7 +328,7 @@ lumiera_frame_duration (FrameRate const& fps)
|
|||
throw error::Logic ("Impossible to quantise to an zero spaced frame grid"
|
||||
, error::LUMIERA_ERROR_BOTTOM_VALUE);
|
||||
|
||||
FSecs duration = rational_cast<FSecs> (1/fps);
|
||||
FSecs duration = 1 / fps;
|
||||
return lumiera_rational_to_time (duration);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -122,14 +122,14 @@ namespace time {
|
|||
static regex fracSecs_parser ("(?:^|[^\\./\\d\\-])(\\-?\\d+)(?:([\\-\\+]\\d+)?/(\\d+))?sec");
|
||||
//__no leading[./-\d] number [+-] number '/' number 'sec'
|
||||
|
||||
#define SUB_EXPR(N) lexical_cast<long> (match[N])
|
||||
#define SUB_EXPR(N) lexical_cast<int> (match[N])
|
||||
smatch match;
|
||||
if (regex_search (seconds, match, fracSecs_parser))
|
||||
if (match[2].matched)
|
||||
{
|
||||
// complete spec with all parts
|
||||
FSecs fractionalPart (SUB_EXPR(2), SUB_EXPR(3));
|
||||
long fullSeconds (SUB_EXPR(1));
|
||||
int fullSeconds (SUB_EXPR(1));
|
||||
return grid.timeOf (fullSeconds + fractionalPart);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ namespace time {
|
|||
|
||||
/** rational representation of fractional seconds
|
||||
* @warning do not mix up gavl_time_t and FSecs */
|
||||
typedef boost::rational<long> FSecs;
|
||||
typedef boost::rational<int64_t> FSecs;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -550,12 +550,10 @@ namespace time {
|
|||
class FrameRate
|
||||
: public boost::rational<uint>
|
||||
{
|
||||
typedef boost::rational<uint> IFrac;
|
||||
|
||||
public:
|
||||
FrameRate (uint fps) ;
|
||||
FrameRate (uint num, uint denom);
|
||||
FrameRate (IFrac const& fractionalRate);
|
||||
FrameRate (boost::rational<uint> const& fractionalRate);
|
||||
|
||||
// standard copy acceptable;
|
||||
|
||||
|
|
@ -576,7 +574,7 @@ namespace time {
|
|||
inline FSecs
|
||||
operator/ (int n, FrameRate rate)
|
||||
{
|
||||
return n / boost::rational_cast<FSecs> (rate);
|
||||
return FSecs{ n*rate.denominator(), rate.numerator()};
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -621,17 +619,17 @@ namespace time {
|
|||
|
||||
inline
|
||||
FrameRate::FrameRate (uint fps)
|
||||
: IFrac (__ensure_nonzero(fps))
|
||||
: boost::rational<uint> (__ensure_nonzero(fps))
|
||||
{ }
|
||||
|
||||
inline
|
||||
FrameRate::FrameRate (uint num, uint denom)
|
||||
: IFrac (__ensure_nonzero(num), denom)
|
||||
: boost::rational<uint> (__ensure_nonzero(num), denom)
|
||||
{ }
|
||||
|
||||
inline
|
||||
FrameRate::FrameRate (IFrac const& fractionalRate)
|
||||
: IFrac (__ensure_nonzero(fractionalRate))
|
||||
FrameRate::FrameRate (boost::rational<uint> const& fractionalRate)
|
||||
: boost::rational<uint> (__ensure_nonzero(fractionalRate))
|
||||
{ }
|
||||
|
||||
inline double
|
||||
|
|
@ -654,5 +652,16 @@ namespace util {
|
|||
return 0 == dur;
|
||||
}
|
||||
|
||||
// repeated or forward declaration, see meta/util.hpp
|
||||
template<typename X, typename COND>
|
||||
struct StringConv;
|
||||
|
||||
/** specialisation: render fractional seconds (for diagnostics) */
|
||||
template<>
|
||||
struct StringConv<lib::time::FSecs, void>
|
||||
{
|
||||
static std::string
|
||||
invoke (lib::time::FSecs) noexcept;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
#endif /*LIB_TIME_TIMEVALUE_H*/
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ namespace test{
|
|||
|
||||
namespace {
|
||||
|
||||
const uint MAX_FRAMES = 25*500;
|
||||
const uint DIRT_GRAIN = 50;
|
||||
const int MAX_FRAMES = 25*500;
|
||||
const int DIRT_GRAIN = 50;
|
||||
|
||||
const FSecs F25(1,25); // duration of one PAL frame
|
||||
|
||||
|
|
@ -91,10 +91,10 @@ namespace test{
|
|||
{
|
||||
FixedFrameQuantiser fixQ(25);
|
||||
|
||||
uint frames = (rand() % MAX_FRAMES);
|
||||
int frames = (rand() % MAX_FRAMES);
|
||||
FSecs dirt = (F25 / (2 + rand() % DIRT_GRAIN));
|
||||
|
||||
Time rawTime = Time(frames*F25) + Duration(dirt); ////////////////TICKET #939 : should better use 64bit base type for FSecs ??
|
||||
Time rawTime = Time(frames*F25) + Duration(dirt);
|
||||
|
||||
CHECK (Time( frames *F25) <= rawTime);
|
||||
CHECK (Time((frames+1)*F25) > rawTime);
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ namespace test {
|
|||
|
||||
namespace { // Test definitions...
|
||||
|
||||
const Time testOrigin (12,34);
|
||||
const FrameRate testFps (5,6);
|
||||
const Time TEST_ORIGIN (12,34);
|
||||
const FrameRate TEST_FPS (5,6);
|
||||
|
||||
const uint MAX_FRAMES = 1000;
|
||||
const uint DIRT_GRAIN = 50;
|
||||
|
|
@ -89,8 +89,8 @@ namespace test {
|
|||
CHECK ( spec.origin == TimeValue(0));
|
||||
CHECK (!spec.predecessor);
|
||||
|
||||
spec.fps = testFps;
|
||||
spec.origin = testOrigin;
|
||||
spec.fps = TEST_FPS;
|
||||
spec.origin = TEST_ORIGIN;
|
||||
|
||||
PGrid myGrid = spec.commit();
|
||||
CHECK (myGrid);
|
||||
|
|
@ -101,15 +101,15 @@ namespace test {
|
|||
int randomFrame = (rand() % MAX_FRAMES);
|
||||
|
||||
Time point (myGrid->timeOf (randomFrame));
|
||||
CHECK (point == testOrigin + randomFrame * testFps.duration());
|
||||
CHECK (point == TEST_ORIGIN + randomFrame * TEST_FPS.duration());
|
||||
|
||||
uint fract = 2 + rand() % DIRT_GRAIN;
|
||||
FSecs dirt = rational_cast<FSecs> (1 / testFps / fract);
|
||||
ASSERT (Time(dirt) < testFps.duration());
|
||||
int fract = 2 + rand() % DIRT_GRAIN;
|
||||
FSecs dirt = (1/TEST_FPS) / fract;
|
||||
ASSERT (Time(dirt) < TEST_FPS.duration());
|
||||
ASSERT (0 < dirt);
|
||||
|
||||
Time dirty(point + Time(dirt));
|
||||
CHECK (point == testOrigin + myGrid->gridAlign(dirty));
|
||||
CHECK (point == TEST_ORIGIN + myGrid->gridAlign(dirty));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -44967,8 +44967,7 @@
|
|||
früher war das so eine typische "nörgel"-Warnung, die man unter den Teppich kehren konnte: 'ey, der Compiler bekommt es ja trotzdem richtig hin.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="clanbomber"/>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -44989,8 +44988,7 @@
|
|||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
<icon BUILTIN="bell"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1439644368572" ID="ID_688656048" MODIFIED="1581813253348" TEXT="Doku: Referenz-System">
|
||||
|
|
@ -45363,9 +45361,144 @@
|
|||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1581740733368" ID="ID_1726260734" MODIFIED="1581740740712" TEXT="TICKET #939 : should better use 64bit base type for FSecs?">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1581740750350" ID="ID_1497724243" MODIFIED="1581740764240" TEXT="macht sich als 32bit vs 64bit-Problematik bemerkbar"/>
|
||||
<node COLOR="#338800" CREATED="1581740733368" ID="ID_1726260734" MODIFIED="1581903029633" TEXT="TICKET #939 : should better use 64bit base type for FSecs?">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1581740750350" ID="ID_1497724243" MODIFIED="1581819702167" TEXT="macht sich als 32bit vs 64bit-Problematik bemerkbar">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
als "workaround" hatte ich boost::rational<long> genommen
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1581819704923" ID="ID_1047068236" MODIFIED="1581819708983" TEXT="was ist die Gefahr?">
|
||||
<node CREATED="1581819714050" ID="ID_314031332" MODIFIED="1581819747785" TEXT="wenn FSecs == rational<int64_t>"/>
|
||||
<node CREATED="1581819818091" ID="ID_135964502" MODIFIED="1581819829735" TEXT="könnte dann...">
|
||||
<node CREATED="1581819830610" ID="ID_1892644470" MODIFIED="1581819869673" TEXT="ein gavl_time_t als FSecs reinrutschen?"/>
|
||||
<node CREATED="1581819875124" ID="ID_1881211496" MODIFIED="1581819926345" TEXT="ein FrameCnt (==int64_t) als FSecs reinrutschen"/>
|
||||
</node>
|
||||
<node CREATED="1581830913676" ID="ID_1851233163" MODIFIED="1581831276538" TEXT="möglicherweise">
|
||||
<icon BUILTIN="smiley-neutral"/>
|
||||
<node CREATED="1581830921543" ID="ID_1634734053" MODIFIED="1581830932821" TEXT="FixedFramesQuantiser-ctor">
|
||||
<node CREATED="1581830948928" ID="ID_1558541350" MODIFIED="1581831146865" TEXT="Framerate">
|
||||
<node CREATED="1581831157480" ID="ID_425744081" MODIFIED="1581831161915" TEXT="via uint fps">
|
||||
<node CREATED="1581833787784" ID="ID_208241204" MODIFIED="1581833800782" TEXT="hat Vorfahrt bei einfachen Zahlen">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1581831174129" ID="ID_283797015" MODIFIED="1581831181172" TEXT="via rational<uint>"/>
|
||||
</node>
|
||||
<node CREATED="1581830970509" ID="ID_892094269" MODIFIED="1581831262411" TEXT="via Duration">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1581831241536" ID="ID_1150857436" MODIFIED="1581831259798" TEXT="keine Gefahr"/>
|
||||
<node CREATED="1581831244519" ID="ID_270912881" MODIFIED="1581833828374" TEXT="ctor via FSecs ist explicit"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1581831295432" ID="ID_897252634" MODIFIED="1581831298540" TEXT="Grid::timeOf">
|
||||
<node CREATED="1581831305831" ID="ID_775298577" MODIFIED="1581831317561" TEXT="FrameCnt gridPoint"/>
|
||||
<node CREATED="1581831336819" ID="ID_742904480" MODIFIED="1581831547730" TEXT="FSecs [, offset]">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1581831549990" ID="ID_1767803348" MODIFIED="1581831553618" TEXT="keine Gefahr"/>
|
||||
<node CREATED="1581831554078" ID="ID_292991581" MODIFIED="1581831588989" TEXT="da stets der direkte Match auf FrameCnt bevorzugt wird"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1581833987508" ID="ID_1945258109" MODIFIED="1581834001127" TEXT="die sonstiten TimeValues sind bereits "wasserdicht"">
|
||||
<node CREATED="1581834003850" ID="ID_1726640094" MODIFIED="1581834011693" TEXT="alle gefährlichen ctor sind explicit"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1581834016097" ID="ID_943401392" MODIFIED="1581834026595" TEXT="Lösungs-Alternativen">
|
||||
<node COLOR="#338800" CREATED="1581834028399" ID="ID_1290001374" MODIFIED="1581905054869" TEXT="FSecs := rational<int64_t>">
|
||||
<icon BUILTIN="back"/>
|
||||
<node CREATED="1581834219506" ID="ID_1492786906" MODIFIED="1581834235727" TEXT="erlaubt Einstieg mit maximal großen Sekundenbeträgen"/>
|
||||
<node CREATED="1581904944430" ID="ID_95309143" MODIFIED="1581905174089">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
und wir brauchen die <b>definitiv</b> zum sinnvollen Rechenen mit Zeiten auf micro-Scala
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
Der kritsche Fall ist nämlich, wenn wir mit FSecs anfangen, und dann irgendwo in der Rechnung mal Time::SCALE multiplizieren, um auf die µ-Skala zu wechseln. Am Ende der Rechnung würde dann typischerweise ein rational_cast stehen. Damit das funktioniert, muß vor allem der Zähler des Bruches die volle Zeitskala unterstützen. Daher sind <b>64bit zwingend</b>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<linktarget COLOR="#265a98" DESTINATION="ID_95309143" ENDARROW="Default" ENDINCLINATION="389;0;" ID="Arrow_ID_1170592297" SOURCE="ID_38565900" STARTARROW="None" STARTINCLINATION="670;0;"/>
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1581834047228" ID="ID_622470274" MODIFIED="1581905031525" TEXT="FSecs := rational<int>">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1581834077245" ID="ID_897585288" MODIFIED="1581834173627" TEXT="hätte den Charme, daß weder ein FrameCnt, noch eine gavl-Time direkt reinrutschen kann">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
weil 64bit -> 32bit eine <i>narrowing conversion</i> ist, die zumindest eine Warnung erzeugt
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1581834174595" ID="ID_1571757083" MODIFIED="1581902077277" TEXT="TODO: ist dieses Argument stichhaltig?">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1581902078156" ID="ID_1759780689" MODIFIED="1581902089742" TEXT="ja... durch Experiment geprüft"/>
|
||||
<node CREATED="1581902090474" ID="ID_355415579" MODIFIED="1581902102205" TEXT="aber ohnehin ist lib::Time schon sehr gut abgedichtet"/>
|
||||
</node>
|
||||
<node CREATED="1581905033868" ID="ID_1903781960" MODIFIED="1581905047679" TEXT="aber die Genauigkeit reicht nicht">
|
||||
<icon BUILTIN="stop-sign"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1581834243675" ID="ID_1426215906" MODIFIED="1581902070280" TEXT="FSecs-ctor explicit machen">
|
||||
<icon BUILTIN="button_cancel"/>
|
||||
<node CREATED="1581834266215" ID="ID_221160071" MODIFIED="1581834285216" TEXT="man würde damit ein "Schlupfloch" schließen"/>
|
||||
<node CREATED="1581834285684" ID="ID_1178771813" MODIFIED="1581834312204" TEXT="im Moment kann man schreiben Time(12L) (und bekommt 12 Sekunden)"/>
|
||||
<node CREATED="1581834377896" ID="ID_897382203" MODIFIED="1581834390340" TEXT="geplant: Integration mit std::chrono">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1581834393889" ID="ID_220525990" MODIFIED="1581834410119" TEXT="das würde wieder eine bequeme Notation bieten"/>
|
||||
<node CREATED="1581834411251" ID="ID_509607126" MODIFIED="1581834424225" TEXT="wobei, "FSecs(12)" ist jetzt nicht sooo schlecht"/>
|
||||
<node CREATED="1581834424753" ID="ID_1621101278" MODIFIED="1581834434707" TEXT="und außerdem mache ich es in der Praxis ohnehin so"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1581834553800" ID="ID_1858355977" MODIFIED="1581834582609" TEXT="erscheint mir als die sauberste Variante">
|
||||
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
<node CREATED="1581902038450" ID="ID_676891454" MODIFIED="1581902066045" TEXT="nicht einfach realisierbar">
|
||||
<icon BUILTIN="stop-sign"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1581834456924" ID="ID_515357939" MODIFIED="1581834461008" TEXT="Typ-Fragen">
|
||||
<node CREATED="1581834461832" ID="ID_1605358591" MODIFIED="1581834471551" TEXT="warum ist der FrameCnt ein signed integer?">
|
||||
<node CREATED="1581883352929" ID="ID_1846298026" MODIFIED="1581883367592" TEXT="FrameCnt kann ein spezieller Timecode sein"/>
|
||||
<node CREATED="1581883325779" ID="ID_573587391" MODIFIED="1581883342672" TEXT="weil es sich um eine Koordinate handelt"/>
|
||||
<node CREATED="1581883343219" ID="ID_613888469" MODIFIED="1581883351652" TEXT="FrameCnt ist bisweilen negativ"/>
|
||||
<node COLOR="#338800" CREATED="1581883360863" ID="ID_1550240767" MODIFIED="1581883366505" TEXT="also OK">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1581834473819" ID="ID_38565900" MODIFIED="1581905067507" TEXT="brauchen / wollen wir 64bit für die FSecs?">
|
||||
<arrowlink COLOR="#265a98" DESTINATION="ID_95309143" ENDARROW="Default" ENDINCLINATION="389;0;" ID="Arrow_ID_1170592297" STARTARROW="None" STARTINCLINATION="670;0;"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1581813859601" ID="ID_728753164" MODIFIED="1581813869304" TEXT="auf C++17 heben">
|
||||
|
|
@ -45406,8 +45539,7 @@
|
|||
<font color="#d40222">WICHTIG</font>: keine vorgreifende Infos publizieren!!!!!
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1446482445325" ID="ID_1134936512" MODIFIED="1581813646885" TEXT="Build-Tutorial">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
|
|
|
|||
Loading…
Reference in a new issue