summaryrefslogtreecommitdiff
path: root/src/lib/dcpomatic_time.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/dcpomatic_time.cc')
-rw-r--r--src/lib/dcpomatic_time.cc294
1 files changed, 271 insertions, 23 deletions
diff --git a/src/lib/dcpomatic_time.cc b/src/lib/dcpomatic_time.cc
index 60fc5342a..a969f4c19 100644
--- a/src/lib/dcpomatic_time.cc
+++ b/src/lib/dcpomatic_time.cc
@@ -20,10 +20,13 @@
#include "dcpomatic_time.h"
+#include <dcp/raw_convert.h>
+#include <boost/algorithm/string.hpp>
#include <inttypes.h>
using std::string;
+using std::vector;
using namespace dcpomatic;
@@ -47,14 +50,6 @@ dcpomatic::operator<=(HMSF const& a, HMSF const& b)
template <>
-Time<ContentTimeDifferentiator, DCPTimeDifferentiator>::Time (DCPTime d, FrameRateChange f)
- : _t (llrint(d.get() * f.speed_up))
-{
-
-}
-
-
-template <>
Time<DCPTimeDifferentiator, ContentTimeDifferentiator>::Time (ContentTime d, FrameRateChange f)
: _t (llrint(d.get() / f.speed_up))
{
@@ -119,27 +114,280 @@ dcpomatic::to_string (ContentTime t)
}
+DCPTime::DCPTime(Type num)
+ : _num(num)
+ , _den(96000)
+{
+
+}
+
+
+DCPTime::DCPTime(Type num, Type den)
+ : _num(num)
+ , _den(den)
+{
+ DCPOMATIC_ASSERT(_den);
+}
+
+
+DCPTime::DCPTime(ContentTime time, FrameRateChange frc)
+ : _num(llrint(time.get() / frc.speed_up))
+ , _den(ContentTime::HZ)
+{
+
+}
+
+
+DCPTime::DCPTime(string const& serializable_string)
+{
+ vector<string> parts;
+ boost::algorithm::split(parts, serializable_string, boost::is_any_of("_"));
+ if (parts.size() == 1) {
+ _num = dcp::raw_convert<int64_t>(parts[0]);
+ _den = 96000;
+ } else {
+ _num = dcp::raw_convert<int64_t>(parts[0]);
+ _den = dcp::raw_convert<int64_t>(parts[1]);
+ }
+}
+
+
+DCPTime::DCPTime(HMSF const& hmsf, float fps)
+{
+ *this = from_seconds(hmsf.h * 3600)
+ + from_seconds(hmsf.m * 60)
+ + from_seconds(hmsf.s)
+ + DCPTime(hmsf.f * 1000, fps * 1000);
+}
+
+
string
-dcpomatic::to_string (DCPTime t)
+DCPTime::to_serialisable_string() const
{
- char buffer[64];
-#ifdef DCPOMATIC_WINDOWS
- __mingw_snprintf (buffer, sizeof(buffer), "[DCP %" PRId64 " %fs]", t.get(), t.seconds());
-#else
- snprintf (buffer, sizeof(buffer), "[DCP %" PRId64 " %fs]", t.get(), t.seconds());
-#endif
- return buffer;
+ return fmt::format("{}_{}", _num, _den);
}
string
-dcpomatic::to_string (DCPTimePeriod p)
+DCPTime::to_debug_string() const
{
- char buffer[64];
-#ifdef DCPOMATIC_WINDOWS
- __mingw_snprintf (buffer, sizeof(buffer), "[DCP %" PRId64 " %fs -> %" PRId64 " %fs]", p.from.get(), p.from.seconds(), p.to.get(), p.to.seconds());
-#else
- snprintf (buffer, sizeof(buffer), "[DCP %" PRId64 " %fs -> %" PRId64 " %fs]", p.from.get(), p.from.seconds(), p.to.get(), p.to.seconds());
-#endif
+ return fmt::format("[{}/{} {}]", _num, _den, seconds());
+}
+
+
+double
+DCPTime::seconds() const
+{
+ return static_cast<double>(_num) / _den;
+}
+
+bool
+DCPTime::operator<(DCPTime const& o) const
+{
+ DCPOMATIC_ASSERT(_den == o._den);
+ return _num < o._num;
+}
+
+
+bool
+DCPTime::operator<=(DCPTime const& o) const
+{
+ DCPOMATIC_ASSERT(_den == o._den);
+ return _num <= o._num;
+}
+
+
+bool
+DCPTime::operator==(DCPTime const& o) const
+{
+ DCPOMATIC_ASSERT(_den == o._den);
+ return _num == o._num;
+}
+
+
+bool
+DCPTime::operator!=(DCPTime const& o) const
+{
+ DCPOMATIC_ASSERT(_den == o._den);
+ return _num != o._num;
+}
+
+
+bool
+DCPTime::operator>=(DCPTime const& o) const
+{
+ DCPOMATIC_ASSERT(_den == o._den);
+ return _num >= o._num;
+}
+
+
+bool
+DCPTime::operator>(DCPTime const& o) const
+{
+ DCPOMATIC_ASSERT(_den == o._den);
+ return _num > o._num;
+}
+
+
+int64_t
+DCPTime::frames_floor(int r) const
+{
+ return (_num * r) / _den;
+}
+
+
+int64_t
+DCPTime::frames_round(int r) const
+{
+ return ((_num * r) + (r / 2)) / _den;
+}
+
+
+int64_t
+DCPTime::frames_ceil(int r) const
+{
+ return ((_num + 1) * r) / _den;
+}
+
+
+DCPTime
+DCPTime::operator+(DCPTime const& o) const
+{
+ DCPOMATIC_ASSERT(_den == o._den);
+ return DCPTime(_num + o._num, _den);
+}
+
+
+DCPTime&
+DCPTime::operator+=(DCPTime const& o)
+{
+ DCPOMATIC_ASSERT(_den == o._den);
+ _num += o._num;
+ return *this;
+}
+
+
+DCPTime
+DCPTime::operator-(DCPTime const& o) const
+{
+ DCPOMATIC_ASSERT(_den == o._den);
+ return DCPTime(_num - o._num, _den);
+}
+
+
+DCPTime
+DCPTime::operator-() const
+{
+ return DCPTime(-_num, _den);
+}
+
+
+DCPTime&
+DCPTime::operator-=(DCPTime const& o)
+{
+ DCPOMATIC_ASSERT(_den == o._den);
+ _num -= o._num;
+ return *this;
+}
+
+
+DCPTime
+DCPTime::operator*(int o) const
+{
+ return DCPTime(_num * o, _den);
+}
+
+
+DCPTime
+DCPTime::operator/(int o) const
+{
+ return DCPTime(_num, _den * o);
+}
+
+
+DCPTime::operator bool() const
+{
+ return _num != 0;
+}
+
+
+DCPTime
+DCPTime::max() const
+{
+ return DCPTime(INT64_MAX, _den);
+}
+
+
+DCPTime
+DCPTime::from_seconds(double s)
+{
+ return DCPTime(s * 96000, 96000);
+}
+
+
+DCPTime
+DCPTime::floor(int r) const
+{
+ return DCPTime(frames_floor(r), r);
+}
+
+
+DCPTime
+DCPTime::round(int r) const
+{
+ return DCPTime(frames_round(r), r);
+}
+
+
+DCPTime
+DCPTime::ceil(int r) const
+{
+ return DCPTime(frames_ceil(r), r);
+}
+
+
+DCPTime
+DCPTime::abs() const
+{
+ return DCPTime(std::abs(_num), _den);
+}
+
+
+HMSF
+DCPTime::splitX(int r) const
+{
+ /* Do this calculation with frames so that we can round
+ to a frame boundary at the start rather than the end.
+ */
+ auto ff = frames_round(r);
+ HMSF hmsf;
+
+ hmsf.h = ff / (3600 * r);
+ ff -= static_cast<int64_t>(hmsf.h) * 3600 * r;
+ hmsf.m = ff / (60 * r);
+ ff -= static_cast<int64_t>(hmsf.m) * 60 * r;
+ hmsf.s = ff / r;
+ ff -= static_cast<int64_t>(hmsf.s) * r;
+
+ hmsf.f = static_cast<int>(ff);
+ return hmsf;
+}
+
+
+string
+DCPTime::timecodeX(int r) const
+{
+ auto hmsf = splitX(r);
+
+ char buffer[128];
+ snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d:%02d", hmsf.h, hmsf.m, hmsf.s, hmsf.f);
return buffer;
}
+
+
+ContentTime
+DCPTime::content_time(FrameRateChange frc) const
+{
+ return ContentTime(frames_round(ContentTime::HZ) * frc.speed_up);
+}
+