+ static const int HZ = 96000;
+
+private:
+ friend struct ::dcpomatic_time_ceil_test;
+ friend struct ::dcpomatic_time_floor_test;
+
+ Type _t;
+};
+
+
+class ContentTimeDifferentiator {};
+class DCPTimeDifferentiator {};
+
+
+/* Specializations for the two allowed explicit conversions */
+
+template<>
+Time<ContentTimeDifferentiator, DCPTimeDifferentiator>::Time (Time<DCPTimeDifferentiator, ContentTimeDifferentiator> d, FrameRateChange f);
+
+template<>
+Time<DCPTimeDifferentiator, ContentTimeDifferentiator>::Time (Time<ContentTimeDifferentiator, DCPTimeDifferentiator> d, FrameRateChange f);
+
+
+/** Time relative to the start or position of a piece of content in its native frame rate */
+typedef Time<ContentTimeDifferentiator, DCPTimeDifferentiator> ContentTime;
+/** Time relative to the start of the output DCP in its frame rate */
+typedef Time<DCPTimeDifferentiator, ContentTimeDifferentiator> DCPTime;
+
+template <class T>
+class TimePeriod
+{
+public:
+ TimePeriod () {}
+
+ TimePeriod (T f, T t)
+ : from (f)
+ , to (t)
+ {}
+
+ /** start time of sampling interval that the period is from */
+ T from;
+ /** start time of next sampling interval after the period */
+ T to;
+
+ T duration () const {
+ return to - from;
+ }
+
+ TimePeriod<T> operator+ (T const & o) const {
+ return TimePeriod<T> (from + o, to + o);
+ }
+
+ boost::optional<TimePeriod<T>> overlap (TimePeriod<T> const & other) const {
+ T const max_from = std::max (from, other.from);
+ T const min_to = std::min (to, other.to);
+
+ if (max_from >= min_to) {
+ return {};
+ }
+
+ return TimePeriod<T> (max_from, min_to);
+ }
+
+ bool contains (T const & other) const {
+ return (from <= other && other < to);
+ }
+
+ bool operator< (TimePeriod<T> const & o) const {
+ if (from != o.from) {
+ return from < o.from;
+ }
+ return to < o.to;