introduce typedef for Frame numbers (see #882)

This commit is contained in:
Fischlurch 2013-11-18 00:01:43 +01:00
parent 608ae3efd8
commit a640283e4c
25 changed files with 170 additions and 138 deletions

View file

@ -91,6 +91,8 @@ enum JobFailureReason
PREREQUISITE_NOT_AVAILABLE ///////////////TODO
};
typedef int64_t FrameCnt;
/**
@ -110,7 +112,7 @@ typedef struct lumiera_jobClosure* LumieraJobClosure;
*/
union InvocationInstanceID
{
int64_t frameNumber;
FrameCnt frameNumber;
lumiera_uid luid;
struct {int a,b;}

View file

@ -95,13 +95,6 @@ extern "C" { /* ===================== C interface ======================== */
#endif
/**
* Formats a time value in H:MM:SS.mmm format into a temporary buffer.
* @return safeclib temporary buffer containing formatted time string
*/
char*
lumiera_tmpbuf_print_time (gavl_time_t time);
/**
* Quantise the given time into a fixed grid, relative to the origin.
* The time grid used for quantisation is comprised of equally spaced intervals,
@ -219,6 +212,16 @@ int
lumiera_time_ntsc_drop_hours (gavl_time_t time);
/**
* @internal Diagnostics helper: render time value in H:MM:SS.mmm format.
* @return `safeclib` temporary buffer containing formatted time string
* @note any time output for real should go through quantisation followed
* by rendering into a suitable timecode format.
*/
char*
lumiera_tmpbuf_print_time (gavl_time_t time);
#ifdef __cplusplus
}//extern "C"

View file

@ -317,7 +317,9 @@ namespace time {
typedef Digxel< int, digxel::SexaFormatter> SexaDigit; ///< for displaying time components (sexagesimal)
typedef Digxel<uint, digxel::HexaFormatter> HexaDigit; ///< for displaying a hex byte
typedef Digxel< int, digxel::HourFormatter> HourDigit; ///< for displaying hours in H:M.S
typedef Digxel<int64_t, digxel::CountFormatter> CountVal; ///< for displaying a counter ///////////TICKET #882 : should better use a typedef for frame counts
typedef int64_t FrameCnt;
typedef Digxel<FrameCnt, digxel::CountFormatter> CountVal; ///< for displaying a counter
/** special Digxel to show a sign.

View file

@ -62,9 +62,9 @@ namespace time {
virtual ~Grid(); ///< this is an Interface
virtual int64_t gridPoint (TimeValue const& raw) const =0;
virtual FrameCnt gridPoint (TimeValue const& raw) const =0;
virtual TimeValue gridAlign (TimeValue const& raw) const =0;
virtual TimeValue timeOf (int64_t gridPoint) const =0;
virtual TimeValue timeOf (FrameCnt gridPoint) const =0;
virtual TimeValue timeOf (FSecs gridTime, int=0) const =0;
};

View file

@ -177,8 +177,8 @@ namespace time {
Mutation::imposeChange (QuTime& target, int steps)
{
PQuant const& grid (target);
int64_t originalGridPoint = grid->gridPoint(target);
int64_t adjustedGridPoint = originalGridPoint + steps;
FrameCnt originalGridPoint = grid->gridPoint(target);
FrameCnt adjustedGridPoint = originalGridPoint + steps;
return imposeChange (target, grid->timeOf (adjustedGridPoint));
}
#endif

View file

@ -136,7 +136,7 @@ namespace time {
* range when converting back into a TimeValue.
* @see #lumiera_quantise_frames
*/
int64_t
FrameCnt
FixedFrameQuantiser::gridPoint (TimeValue const& rawTime) const
{
return lumiera_quantise_frames (_raw(rawTime), _raw(origin_), _raw(raster_));
@ -149,7 +149,7 @@ namespace time {
* valid range of lumiera::Time
*/
TimeValue
FixedFrameQuantiser::timeOf (int64_t gridPoint) const
FixedFrameQuantiser::timeOf (FrameCnt gridPoint) const
{
return TimeValue (lumiera_time_of_gridpoint (gridPoint, _raw(origin_), _raw(raster_)));
}

View file

@ -108,9 +108,9 @@ namespace time {
//------Grid-API----------------------------------------------
virtual int64_t gridPoint (TimeValue const& raw) const =0;
virtual FrameCnt gridPoint (TimeValue const& raw) const =0;
virtual TimeValue gridAlign (TimeValue const& raw) const =0;
virtual TimeValue timeOf (int64_t gridPoint) const =0;
virtual TimeValue timeOf (FrameCnt gridPoint) const =0;
virtual TimeValue timeOf (FSecs, int =0) const =0;
};
@ -137,10 +137,10 @@ namespace time {
FixedFrameQuantiser (FrameRate const& frames_per_second, TimeValue referencePoint =TimeValue(0));
FixedFrameQuantiser (Duration const& frame_duration, TimeValue referencePoint =TimeValue(0));
int64_t gridPoint (TimeValue const&) const;
TimeValue gridAlign (TimeValue const&) const;
TimeValue timeOf (int64_t gridPoint) const;
TimeValue timeOf (FSecs, int =0) const;
FrameCnt gridPoint (TimeValue const&) const;
TimeValue gridAlign (TimeValue const&) const;
TimeValue timeOf (FrameCnt gridPoint) const;
TimeValue timeOf (FSecs, int =0) const;
};

View file

@ -192,14 +192,14 @@ namespace time {
/** offset by the given number of frames. */
Offset::Offset (int64_t count, FrameRate const& fps)
Offset::Offset (FrameCnt count, FrameRate const& fps)
: TimeValue (count? (count<0? -1:+1) * lumiera_framecount_to_time (::abs(count), fps)
: _raw(Duration::NIL))
{ }
/** duration of the given number of frames.
* @note always positive; count used absolute */
Duration::Duration (int64_t count, FrameRate const& fps)
Duration::Duration (FrameCnt count, FrameRate const& fps)
: TimeValue (count? lumiera_framecount_to_time (abs(count), fps) : _raw(Duration::NIL))
{ }

View file

@ -70,7 +70,7 @@ namespace time {
static regex frameNr_parser ("(?<![\\.\\-\\d])(-?\\d+)#"); // no leading [.-\d], number+'#'
smatch match;
if (regex_search (frameNumber, match, frameNr_parser))
return frameGrid.timeOf (lexical_cast<int64_t> (match[1]));
return frameGrid.timeOf (lexical_cast<FrameCnt> (match[1]));
else
throw error::Invalid ("unable to parse framecount \""+frameNumber+"\""
, LUMIERA_ERROR_INVALID_TIMECODE);
@ -205,9 +205,9 @@ namespace time {
uint
Smpte::getFramerate (QuantR quantiser_, TimeValue const& rawTime)
{
int64_t refCnt = quantiser_.gridPoint(rawTime);
int64_t newCnt = quantiser_.gridPoint(Time(0,1) + rawTime);
int64_t effectiveFrames = newCnt - refCnt;
FrameCnt refCnt = quantiser_.gridPoint(rawTime);
FrameCnt newCnt = quantiser_.gridPoint(Time(0,1) + rawTime);
FrameCnt effectiveFrames = newCnt - refCnt;
ENSURE (1000 > effectiveFrames);
ENSURE (0 < effectiveFrames);
return uint(effectiveFrames);

View file

@ -181,6 +181,95 @@ namespace time {
/* ======= specific Time entities ==================== */
/** 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 use 64bit consistently.
* beware: \c long is 32bit on i386
* @note any conversion to frame numbers should go through
* time quantisation followed by conversion to FrameNr
*/
typedef int64_t FrameCnt;
/** rational representation of fractional seconds
* @warning do not mix up gavl_time_t and FSecs */
typedef boost::rational<long> FSecs;
/**
* Lumiera's internal time value datatype.
* This is a TimeValue, but now more specifically denoting
* a point in time, measured in reference to an internal
* (opaque) time scale.
*
* Lumiera Time provides some limited capabilities for
* direct manipulation; Time values can be created directly
* from \c (ms,sec,min,hour) specification and there is an
* string representation intended for internal use (reporting
* and debugging). Any real output, formatting and persistent
* storage should be based on the (quantised) timecode
* formats though, which can be generated from time values.
*
* Similar to TimeValue, also Time objects are considered
* immutable values. As convenience shortcut, some operators
* are provided, creating a TimVar for further calculations.
*/
class Time
: public TimeValue
{
/// direct assignment prohibited
Time& operator= (Time const);
/// suppress possible direct conversions
Time(int);
public:
static const Time MAX ;
static const Time MIN ;
static const Time ZERO;
static const Time ANYTIME; ///< border condition marker value. #ANYTIME <= any time value
static const Time NEVER; ///< border condition marker value. #NEVER >= any time value
explicit
Time (TimeValue const& val =TimeValue(0))
: TimeValue(val)
{ }
Time (TimeVar const& calcResult)
: TimeValue(calcResult)
{ }
explicit
Time (FSecs const& fractionalSeconds);
Time ( long millis
, uint secs
, uint mins =0
, uint hours=0
);
/** @internal diagnostics */
operator std::string () const;
/** convenience start for time calculations */
TimeVar operator+ (TimeValue const& tval) const { return TimeVar(*this) + tval; }
TimeVar operator- (TimeValue const& tval) const { return TimeVar(*this) - tval; }
TimeVar operator- () const { return -TimeVar(*this); }
};
/**
* Offset measures a distance in time.
* It may be used to relate two points in time,
@ -215,7 +304,7 @@ namespace time {
: TimeValue(TimeVar(target) -= origin)
{ }
Offset (int64_t count, FrameRate const& fps);
Offset (FrameCnt count, FrameRate const& fps);
static const Offset ZERO;
@ -277,77 +366,6 @@ namespace time {
/* ======= specific Time entities ==================== */
/** rational representation of fractional seconds
* @warning do not mix up gavl_time_t and FSecs */
typedef boost::rational<long> FSecs;
/**
* Lumiera's internal time value datatype.
* This is a TimeValue, but now more specifically denoting
* a point in time, measured in reference to an internal
* (opaque) time scale.
*
* Lumiera Time provides some limited capabilities for
* direct manipulation; Time values can be created directly
* from \c (ms,sec,min,hour) specification and there is an
* string representation intended for internal use (reporting
* and debugging). Any real output, formatting and persistent
* storage should be based on the (quantised) timecode
* formats though, which can be generated from time values.
*
* Similar to TimeValue, also Time objects are considered
* immutable values. As convenience shortcut, some operators
* are provided, creating a TimVar for further calculations.
*/
class Time
: public TimeValue
{
/// direct assignment prohibited
Time& operator= (Time const);
/// suppress possible direct conversions
Time(int);
public:
static const Time MAX ;
static const Time MIN ;
static const Time ZERO;
static const Time ANYTIME; ///< border condition marker value. #ANYTIME <= any time value
static const Time NEVER; ///< border condition marker value. #NEVER >= any time value
explicit
Time (TimeValue const& val =TimeValue(0))
: TimeValue(val)
{ }
Time (TimeVar const& calcResult)
: TimeValue(calcResult)
{ }
explicit
Time (FSecs const& fractionalSeconds);
Time ( long millis
, uint secs
, uint mins =0
, uint hours=0
);
/** @internal diagnostics */
operator std::string () const;
/** convenience start for time calculations */
TimeVar operator+ (TimeValue const& tval) const { return TimeVar(*this) + tval; }
TimeVar operator- (TimeValue const& tval) const { return TimeVar(*this) - tval; }
TimeVar operator- () const { return -TimeVar(*this); }
};
/**
* Duration is the internal Lumiera time metric.
@ -378,7 +396,7 @@ namespace time {
{ }
Duration (TimeSpan const& interval);
Duration (int64_t count, FrameRate const& fps);
Duration (FrameCnt count, FrameRate const& fps);
static const Duration NIL;

View file

@ -73,7 +73,7 @@ namespace engine {
Job
CalcPlanContinuation::prepareRenderPlanningFrom (int64_t startFrame)
CalcPlanContinuation::prepareRenderPlanningFrom (FrameCnt startFrame)
{
InvocationInstanceID invoKey;
invoKey.frameNumber = startFrame;
@ -84,7 +84,7 @@ namespace engine {
void
CalcPlanContinuation::performJobPlanningChunk(int64_t nextStartFrame)
CalcPlanContinuation::performJobPlanningChunk(FrameCnt nextStartFrame)
{
TimeAnchor refPoint(timings_, nextStartFrame);
JobPlanningSequence jobs = dispatcher_.onCalcStream(modelPort_, channel_)

View file

@ -44,6 +44,7 @@ namespace engine {
// using lib::time::TimeSpan;
// using lib::time::FSecs;
// using lib::time::Time;
using lib::time::FrameCnt;
/**
@ -107,11 +108,11 @@ namespace engine {
* @param startFrame where to begin rendering, relative to the nominal
* time grid implicitly related to the ModelPort to be pulled
*/
Job prepareRenderPlanningFrom (int64_t startFrame);
Job prepareRenderPlanningFrom (FrameCnt startFrame);
private:
void performJobPlanningChunk(int64_t nextStartFrame);
void performJobPlanningChunk(FrameCnt nextStartFrame);
Job buildFollowUpJobFrom (TimeAnchor const& refPoint);
};

View file

@ -41,6 +41,7 @@ namespace engine {
using std::tr1::function;
using mobject::ModelPort;
using lib::time::FrameCnt;
using lib::time::TimeSpan;
using lib::time::FSecs;
using lib::time::Time;
@ -100,7 +101,7 @@ namespace engine {
virtual FrameCoord locateRelative (FrameCoord, uint frameCountOffset) =0;
virtual FrameCoord locateRelative (TimeAnchor, uint frameCountOffset) =0; //////////TODO is this really an interface operation, or just a convenience shortcut?
virtual bool isEndOfChunk (int64_t, ModelPort port) =0;
virtual bool isEndOfChunk (FrameCnt, ModelPort port) =0;
////////TODO: API-1 = just get next frame, without limitations .... CHECK
////////TODO: API-2 = query limitation of planning chunk .... CHECK

View file

@ -36,6 +36,7 @@ namespace proc {
namespace engine {
using mobject::ModelPort;
using lib::time::FrameCnt;
using lib::time::TimeVar;
using lib::time::Time;
@ -59,8 +60,8 @@ namespace engine {
struct FrameCoord
{
TimeVar absoluteNominalTime;
int64_t absoluteFrameNumber;
TimeVar absoluteNominalTime;
FrameCnt absoluteFrameNumber;
TimeVar absoluteRealDeadline;
@ -71,7 +72,7 @@ namespace engine {
/** build an \em undefined frame location */
FrameCoord()
: absoluteNominalTime(Time::NEVER)
, absoluteFrameNumber(std::numeric_limits<int64_t>::max())
, absoluteFrameNumber(std::numeric_limits<FrameCnt>::max())
, modelPort() // unconnected
, channelNr(0)
{ }

View file

@ -308,7 +308,7 @@ namespace engine {
protected:
virtual JobTicket& accessJobTicket (ModelPort, TimeValue nominalTime) =0;
virtual bool isEndOfChunk (int64_t, ModelPort port) =0;
virtual bool isEndOfChunk (FrameCnt, ModelPort port) =0;
};

View file

@ -38,6 +38,7 @@ namespace engine {
using backend::RealClock;
using lib::time::Offset;
using lib::time::Duration;
using lib::time::FrameCnt;
using lib::time::TimeVar;
using lib::time::Time;
@ -84,11 +85,11 @@ namespace engine {
class TimeAnchor
{
play::Timings timings_;
int64_t anchorPoint_;
FrameCnt anchorPoint_;
Time relatedRealTime_;
static Time
expectedTimeofArival (play::Timings const& timings, int64_t startFrame, Offset startDelay)
expectedTimeofArival (play::Timings const& timings, FrameCnt startFrame, Offset startDelay)
{
Duration totalLatency = startDelay
+ timings.currentEngineLatency()
@ -110,7 +111,7 @@ namespace engine {
public:
TimeAnchor (play::Timings timings, int64_t startFrame, Offset startDelay =Offset::ZERO)
TimeAnchor (play::Timings timings, FrameCnt startFrame, Offset startDelay =Offset::ZERO)
: timings_(timings)
, anchorPoint_(startFrame)
, relatedRealTime_(expectedTimeofArival(timings,startFrame,startDelay))
@ -131,7 +132,7 @@ namespace engine {
* the previous planning chunk, resulting in a seamless
* coverage of the timeline
*/
int64_t
FrameCnt
getNextAnchorPoint() const
{
return timings_.establishNextPlanningChunkStart (this->anchorPoint_);
@ -150,7 +151,7 @@ namespace engine {
/** @return the frame at which any job planning
* for this planning chunk will start */
int64_t getStartFrame() const
FrameCnt getStartFrame() const
{
return anchorPoint_;
}
@ -160,7 +161,7 @@ namespace engine {
remainingRealTimeFor (FrameCoord plannedFrame)
//////////////////////////////////////////////////TODO break this into two sensible operations, using the deadline from the FrameCoord
{
int64_t frameOffset = plannedFrame.absoluteFrameNumber - anchorPoint_;
FrameCnt frameOffset = plannedFrame.absoluteFrameNumber - anchorPoint_;
return Offset(this->relatedRealTime_
+ timings_.getRealOffset(frameOffset)
- RealClock::now());

View file

@ -82,6 +82,7 @@ namespace play {
using proc::engine::BuffHandle;
using proc::engine::BufferProvider;
using lib::time::FrameCnt;
using lib::time::TimeValue;
using lib::time::Time;
@ -91,7 +92,7 @@ namespace play {
class DataSink;
typedef int64_t FrameID;
typedef FrameCnt FrameID;

View file

@ -35,6 +35,7 @@ namespace play {
using lib::time::PQuant;
using lib::time::Time;
using lib::time::TimeVar;
using lib::time::FrameCnt;
namespace { // hidden local details of the service implementation....
@ -85,7 +86,7 @@ namespace play {
Time
Timings::getFrameStartAt (int64_t frameNr) const
Timings::getFrameStartAt (FrameCnt frameNr) const
{
return Time(grid_->timeOf(frameNr));
}
@ -101,13 +102,13 @@ namespace play {
Duration
Timings::getFrameDurationAt (TimeValue refPoint) const
{
int64_t frameNr = grid_->gridPoint (refPoint);
FrameCnt frameNr = grid_->gridPoint (refPoint);
return getFrameDurationAt(frameNr);
}
Duration
Timings::getFrameDurationAt (int64_t refFrameNr) const
Timings::getFrameDurationAt (FrameCnt refFrameNr) const
{
return Offset (grid_->timeOf(refFrameNr), grid_->timeOf(refFrameNr + 1));
}
@ -128,7 +129,7 @@ namespace play {
Time
Timings::getTimeDue(int64_t frameOffset) const
Timings::getTimeDue(FrameCnt frameOffset) const
{
if (TIMEBOUND == playbackUrgency)
{
@ -142,7 +143,7 @@ namespace play {
Offset
Timings::getRealOffset (int64_t frameOffset) const
Timings::getRealOffset (FrameCnt frameOffset) const
{
Offset nominalOffset (grid_->timeOf(0), grid_->timeOf(frameOffset));
return isOriginalSpeed()? nominalOffset
@ -158,12 +159,12 @@ namespace play {
}
int64_t
Timings::establishNextPlanningChunkStart(int64_t currentAnchorFrame) const
FrameCnt
Timings::establishNextPlanningChunkStart(FrameCnt currentAnchorFrame) const
{
TimeVar breakingPoint = grid_->timeOf(currentAnchorFrame);
breakingPoint += getPlanningChunkDuration();
int64_t nextFrame = grid_->gridPoint (breakingPoint);
FrameCnt nextFrame = grid_->gridPoint (breakingPoint);
ASSERT (breakingPoint <= grid_->timeOf(nextFrame));
ASSERT (breakingPoint > grid_->timeOf(nextFrame-1));

View file

@ -66,6 +66,7 @@ namespace time{
namespace proc {
namespace play {
using lib::time::FrameCnt;
using lib::time::FrameRate;
using lib::time::TimeValue;
using lib::time::Duration;
@ -100,7 +101,7 @@ namespace play {
public:
PlaybackUrgency playbackUrgency;
boost::rational<int64_t> playbackSpeed; /////////////TICKET #902 we need a more generic representation for variable speed playback
boost::rational<FrameCnt> playbackSpeed; /////////////TICKET #902 we need a more generic representation for variable speed playback
Time scheduledDelivery;
Duration outputLatency;
@ -115,10 +116,10 @@ namespace play {
Time getOrigin() const;
Time getFrameStartAt (int64_t frameNr) const;
Time getFrameStartAt (FrameCnt frameNr) const;
Offset getFrameOffsetAt (TimeValue refPoint) const;
Duration getFrameDurationAt (TimeValue refPoint) const;
Duration getFrameDurationAt (int64_t refFrameNr) const;
Duration getFrameDurationAt (FrameCnt refFrameNr) const;
/** the frame spacing and duration remains constant for some time...
* @param startPoint looking from that time point into future
@ -136,7 +137,7 @@ namespace play {
* a relative offset, but expressed in real time scale values
* @see proc::engine::TimeAnchor for an absolutely anchored conversion
*/
Offset getRealOffset (int64_t frameOffset) const;
Offset getRealOffset (FrameCnt frameOffset) const;
/** real time deadline for the given frame, without any latency.
* This value is provided in case of scheduled time of delivery,
@ -149,7 +150,7 @@ namespace play {
* @warning not clear as of 1/13 if it is even possible to have such a function
* on the Timings record.
*/
Time getTimeDue(int64_t frameOffset) const;
Time getTimeDue(FrameCnt frameOffset) const;
/** the minimum time span to be covered by frame calculation jobs
* planned in one sway. The ongoing planning of additional jobs
@ -168,7 +169,7 @@ namespace play {
* the planning chunk duration into the future
* @remarks this value is used by the frame dispatcher to create a
* follow-up planning job */
int64_t establishNextPlanningChunkStart(int64_t currentAnchorFrame) const;
FrameCnt establishNextPlanningChunkStart(FrameCnt currentAnchorFrame) const;
/** reasonable guess of the current engine working delay.
* Frame calculation deadlines will be readjusted by that value,

View file

@ -85,7 +85,7 @@ namespace engine {
return Time::NEVER < nominalJobTime
&& 0 <= invoKey.metaInfo.a
&& invoKey.metaInfo.a < MAX_PARAM_A
&& -MAX_PARAM_B < invoKey.metaInfo.b
&& -MAX_PARAM_B <= invoKey.metaInfo.b
&& invoKey.metaInfo.b < MAX_PARAM_B;
}

View file

@ -96,7 +96,7 @@ namespace test {
}
bool
isEndOfChunk (int64_t, ModelPort port)
isEndOfChunk (FrameCnt, ModelPort port)
{
UNIMPLEMENTED ("determine when to finish a planning chunk");
}

View file

@ -78,7 +78,7 @@ namespace test {
// within the frame-calculation "loop"
// we perform a data exchange cycle
int64_t frameNr = 123;
FrameCnt frameNr = 123;
BuffHandle buff00 = sink1.lockBufferFor (frameNr);
BuffHandle buff10 = sink2.lockBufferFor (frameNr);

View file

@ -354,14 +354,14 @@ namespace test{
template<class TAR>
void
____verify_nudged (TAR const& target, TAR const& refState, int64_t offsetSteps)
____verify_nudged (TAR const& target, TAR const& refState, FrameCnt offsetSteps)
{
CHECK (target != refState || !offsetSteps);
CHECK (target == Time(refState)+Time(FSecs(offsetSteps)));
}
template<>
void
____verify_nudged (QuTime const& target, QuTime const& refState, int64_t offsetSteps)
____verify_nudged (QuTime const& target, QuTime const& refState, FrameCnt offsetSteps)
{
CHECK (target != refState || !offsetSteps);
CHECK (target == Time (materialise(refState))

View file

@ -52,12 +52,12 @@ namespace test{
using format::Smpte;
namespace{
const int64_t MAX_FRAME = 265*24*60*60*25;
const FrameCnt MAX_FRAME = 265*24*60*60*25;
string
generateRandomFrameNr()
{
int64_t frameNr(0); /////////TICKET #882 : better use a typedef for frame counts
FrameCnt frameNr(0);
while (!frameNr)
frameNr = rand() % (2*MAX_FRAME) - MAX_FRAME;

View file

@ -290,7 +290,7 @@ namespace test{
void
verify_fractionalOffset ()
{
typedef boost::rational<int64_t> Frac;
typedef boost::rational<FrameCnt> Frac;
Duration three (TimeValue(3)); // three micro seconds