X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fdcpomatic_time.h;h=df9c46c7157651fff9759b8f6e342c18b563ce2f;hb=e60bb3e51bd1508b149e6b8f6608f09b5196ae26;hp=a0bbad06aeaeeed6530d214551fcbd82ab3a4d4d;hpb=d2137ac5db409e686b4d9b3fa567935a5e416d41;p=dcpomatic.git diff --git a/src/lib/dcpomatic_time.h b/src/lib/dcpomatic_time.h index a0bbad06a..df9c46c71 100644 --- a/src/lib/dcpomatic_time.h +++ b/src/lib/dcpomatic_time.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Carl Hetherington + Copyright (C) 2014-2015 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,21 +17,32 @@ */ +/** @file src/lib/dcpomatic_time.h + * @brief Types to describe time. + */ + #ifndef DCPOMATIC_TIME_H #define DCPOMATIC_TIME_H +#include "frame_rate_change.h" +#include "safe_stringstream.h" +#include "dcpomatic_assert.h" +#include #include #include #include #include -#include -#include "frame_rate_change.h" class dcpomatic_round_up_test; -class Time; - -/** A time in seconds, expressed as a number scaled up by Time::HZ. */ +/** A time in seconds, expressed as a number scaled up by Time::HZ. We want two different + * versions of this class, ContentTime and DCPTime, and we want it to be impossible to + * convert implicitly between the two. Hence there's this template hack. I'm not + * sure if it's the best way to do it. + * + * S is the name of `this' class and O is its opposite (see the typedefs below). + */ +template class Time { public: @@ -45,21 +56,87 @@ public: : _t (t) {} - virtual ~Time () {} + explicit Time (Type n, Type d) + : _t (n * HZ / d) + {} + + /* Explicit conversion from type O */ + Time (Time d, FrameRateChange f); Type get () const { return _t; } + bool operator< (Time const & o) const { + return _t < o._t; + } + + bool operator<= (Time const & o) const { + return _t <= o._t; + } + + bool operator== (Time const & o) const { + return _t == o._t; + } + + bool operator!= (Time const & o) const { + return _t != o._t; + } + + bool operator>= (Time const & o) const { + return _t >= o._t; + } + + bool operator> (Time const & o) const { + return _t > o._t; + } + + Time operator+ (Time const & o) const { + return Time (_t + o._t); + } + + Time & operator+= (Time const & o) { + _t += o._t; + return *this; + } + + Time operator- () const { + return Time (-_t); + } + + Time operator- (Time const & o) const { + return Time (_t - o._t); + } + + Time & operator-= (Time const & o) { + _t -= o._t; + return *this; + } + + /** Round up to the nearest sampling interval + * at some sampling rate. + * @param r Sampling rate. + */ + Time round_up (float r) { + Type const n = rint (HZ / r); + Type const a = _t + n - 1; + return Time (a - (a % n)); + } + double seconds () const { return double (_t) / HZ; } + Time abs () const { + return Time (std::abs (_t)); + } + template int64_t frames (T r) const { - return rint (_t * r / HZ); + return rint (double (_t) * r / HZ); } + /** @param r Frames per second */ template void split (T r, int& h, int& m, int& s, int& f) const { @@ -67,7 +144,7 @@ public: to a frame boundary at the start rather than the end. */ int64_t ff = frames (r); - + h = ff / (3600 * r); ff -= h * 3600 * r; m = ff / (60 * r); @@ -86,7 +163,7 @@ public: int f; split (r, h, m, s, f); - std::ostringstream o; + SafeStringStream o; o.width (2); o.fill ('0'); o << std::setw(2) << std::setfill('0') << h << ":" @@ -96,100 +173,57 @@ public: return o.str (); } -protected: - friend class dcptime_round_up_test; - - Type _t; - static const int HZ = 96000; -}; - -class DCPTime; - -class ContentTime : public Time -{ -public: - ContentTime () : Time () {} - explicit ContentTime (Type t) : Time (t) {} - ContentTime (Type n, Type d) : Time (n * HZ / d) {} - ContentTime (DCPTime d, FrameRateChange f); - - bool operator< (ContentTime const & o) const { - return _t < o._t; - } - - bool operator<= (ContentTime const & o) const { - return _t <= o._t; - } - bool operator== (ContentTime const & o) const { - return _t == o._t; + static Time from_seconds (double s) { + return Time (s * HZ); } - bool operator!= (ContentTime const & o) const { - return _t != o._t; - } - - bool operator>= (ContentTime const & o) const { - return _t >= o._t; - } - - bool operator> (ContentTime const & o) const { - return _t > o._t; + template + static Time from_frames (int64_t f, T r) { + DCPOMATIC_ASSERT (r > 0); + return Time (f * HZ / r); } - ContentTime operator+ (ContentTime const & o) const { - return ContentTime (_t + o._t); + static Time delta () { + return Time (1); } - ContentTime & operator+= (ContentTime const & o) { - _t += o._t; - return *this; + static Time min () { + return Time (-INT64_MAX); } - ContentTime operator- () const { - return ContentTime (-_t); + static Time max () { + return Time (INT64_MAX); } - ContentTime operator- (ContentTime const & o) const { - return ContentTime (_t - o._t); - } +private: + friend struct dcptime_round_up_test; - ContentTime & operator-= (ContentTime const & o) { - _t -= o._t; - return *this; - } + Type _t; + static const int HZ = 96000; +}; - /** Round up to the nearest sampling interval - * at some sampling rate. - * @param r Sampling rate. - */ - ContentTime round_up (float r) { - Type const n = rint (HZ / r); - Type const a = _t + n - 1; - return ContentTime (a - (a % n)); - } +class ContentTimeDifferentiator {}; +class DCPTimeDifferentiator {}; - static ContentTime from_seconds (double s) { - return ContentTime (s * HZ); - } +/* Specializations for the two allowed explicit conversions */ - template - static ContentTime from_frames (int64_t f, T r) { - assert (r > 0); - return ContentTime (f * HZ / r); - } +template<> +Time::Time (Time d, FrameRateChange f); - static ContentTime max () { - return ContentTime (INT64_MAX); - } -}; +template<> +Time::Time (Time d, FrameRateChange f); -std::ostream& operator<< (std::ostream& s, ContentTime t); +/** Time relative to the start or position of a piece of content in its native frame rate */ +typedef Time ContentTime; +/** Time relative to the start of the output DCP in its frame rate */ +typedef Time DCPTime; class ContentTimePeriod { public: ContentTimePeriod () {} + ContentTimePeriod (ContentTime f, ContentTime t) : from (f) , to (t) @@ -206,93 +240,8 @@ public: bool contains (ContentTime const & o) const; }; -class DCPTime : public Time -{ -public: - DCPTime () : Time () {} - explicit DCPTime (Type t) : Time (t) {} - DCPTime (ContentTime t, FrameRateChange c) : Time (rint (t.get() / c.speed_up)) {} - - bool operator< (DCPTime const & o) const { - return _t < o._t; - } - - bool operator<= (DCPTime const & o) const { - return _t <= o._t; - } - - bool operator== (DCPTime const & o) const { - return _t == o._t; - } - - bool operator!= (DCPTime const & o) const { - return _t != o._t; - } - - bool operator>= (DCPTime const & o) const { - return _t >= o._t; - } - - bool operator> (DCPTime const & o) const { - return _t > o._t; - } - - DCPTime operator+ (DCPTime const & o) const { - return DCPTime (_t + o._t); - } - - DCPTime & operator+= (DCPTime const & o) { - _t += o._t; - return *this; - } - - DCPTime operator- () const { - return DCPTime (-_t); - } - - DCPTime operator- (DCPTime const & o) const { - return DCPTime (_t - o._t); - } - - DCPTime & operator-= (DCPTime const & o) { - _t -= o._t; - return *this; - } - - /** Round up to the nearest sampling interval - * at some sampling rate. - * @param r Sampling rate. - */ - DCPTime round_up (float r) { - Type const n = rint (HZ / r); - Type const a = _t + n - 1; - return DCPTime (a - (a % n)); - } - - DCPTime abs () const { - return DCPTime (std::abs (_t)); - } - - static DCPTime from_seconds (double s) { - return DCPTime (s * HZ); - } - - template - static DCPTime from_frames (int64_t f, T r) { - assert (r > 0); - return DCPTime (f * HZ / r); - } - - static DCPTime delta () { - return DCPTime (1); - } - - static DCPTime max () { - return DCPTime (INT64_MAX); - } -}; - DCPTime min (DCPTime a, DCPTime b); +std::ostream& operator<< (std::ostream& s, ContentTime t); std::ostream& operator<< (std::ostream& s, DCPTime t); #endif