11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
23PROMEKI_NAMESPACE_BEGIN
64 PROMEKI_DATATYPE(MediaDuration, DataTypeMediaDuration, 1)
67 Error writeToStream(DataStream &s) const;
69 template <uint32_t V> static Result<MediaDuration> readFromStream(DataStream &s);
94 using iterator_category = std::forward_iterator_tag;
95 using value_type = FrameNumber;
96 using difference_type = std::ptrdiff_t;
97 using pointer =
const FrameNumber *;
98 using reference =
const FrameNumber &;
100 Iterator() =
default;
101 explicit Iterator(
const FrameNumber &v) : _cur(v) {}
103 reference operator*()
const {
return _cur; }
104 pointer operator->()
const {
return &_cur; }
105 Iterator &operator++() {
109 Iterator operator++(
int) {
114 bool operator==(
const Iterator &other)
const {
115 return _cur == other._cur;
117 bool operator!=(
const Iterator &other)
const {
118 return _cur != other._cur;
126 FrameRange() =
default;
131 FrameRange(
const FrameNumber &s,
const FrameNumber &e) : start(s), end(e) {}
134 bool isValid()
const {
135 return start.isValid() && end.isValid() && end.value() >= start.value();
144 FrameCount count()
const {
145 if (!isValid())
return FrameCount::unknown();
146 return FrameCount(end.value() - start.value() + 1);
158 bool contains(
const FrameNumber &frame)
const {
159 if (!isValid() || !frame.isValid())
return false;
160 return frame.value() >= start.value() && frame.value() <= end.value();
164 bool operator==(
const FrameRange &other)
const {
165 return start == other.start && end == other.end;
168 bool operator!=(
const FrameRange &other)
const {
return !(*
this == other); }
182 FrameRange &shift(int64_t n) {
189 FrameRange &operator+=(int64_t n) {
return shift(n); }
191 FrameRange &operator-=(int64_t n) {
return shift(-n); }
194 friend FrameRange operator+(FrameRange r, int64_t n) {
199 friend FrameRange operator-(FrameRange r, int64_t n) {
213 friend Iterator begin(
const FrameRange &r) {
return Iterator(r.start); }
222 friend Iterator end(
const FrameRange &r) {
223 if (!r.isValid())
return Iterator(r.start);
224 return Iterator(FrameNumber(r.end.value() + 1));
242 static Result<MediaDuration> fromString(
const String &str);
250 static MediaDuration fromFrameRange(
const FrameRange &range) {
251 return MediaDuration(range.start, range.count());
255 MediaDuration() =
default;
260 MediaDuration(
const FrameNumber &start,
const FrameCount &length) : _start(start), _length(length) {}
268 bool isValid()
const {
return _start.isValid() && _length.isValid(); }
271 bool isUnknown()
const {
return _start.isUnknown() || _length.isUnknown(); }
274 bool isInfinite()
const {
return _length.isInfinite(); }
277 bool isEmpty()
const {
return _length.isEmpty(); }
280 const FrameNumber &start()
const {
return _start; }
283 const FrameCount &length()
const {
return _length; }
287 void setStart(
const FrameNumber &s) { _start = s; }
291 void setLength(
const FrameCount &c) { _length = c; }
303 void setEnd(
const FrameNumber &e);
315 FrameNumber end()
const;
330 bool contains(
const FrameNumber &frame)
const;
336 void addToStart(int64_t n) { _start += n; }
342 void addToEnd(int64_t n) { _length += n; }
345 MediaDuration &operator+=(
const FrameCount &c) {
350 MediaDuration &operator-=(
const FrameCount &c) {
367 Result<FrameRange> toFrameRange()
const;
370 bool operator==(
const MediaDuration &other)
const {
371 return _start == other._start && _length == other._length;
374 bool operator!=(
const MediaDuration &other)
const {
return !(*
this == other); }
391 bool operator<(
const MediaDuration &other)
const {
392 if (isUnknown() || other.isUnknown())
return false;
393 if (_start != other._start)
return _start < other._start;
394 return _length < other._length;
403 bool operator<=(
const MediaDuration &other)
const {
404 if (isUnknown() || other.isUnknown())
return false;
405 return *
this == other || *
this < other;
408 bool operator>(
const MediaDuration &other)
const {
return other < *
this; }
410 bool operator>=(
const MediaDuration &other)
const {
411 if (isUnknown() || other.isUnknown())
return false;
412 return *
this == other || other < *
this;
428 bool contains(
const MediaDuration &other)
const;
431 bool overlaps(
const MediaDuration &other)
const;
449 MediaDuration intersect(
const MediaDuration &other)
const;
464 bool canAppend(
const MediaDuration &other)
const;
480 Error append(
const MediaDuration &other);
495 bool canPrepend(
const MediaDuration &other)
const;
510 Error prepend(
const MediaDuration &other);
518 String toString()
const;
521 operator String()
const {
return toString(); }
529inline MediaDuration operator+(MediaDuration d,
const FrameCount &c) {
534inline MediaDuration operator-(MediaDuration d,
const FrameCount &c) {
541PROMEKI_FORMAT_VIA_TOSTRING(promeki::MediaDuration);
550template <>
struct std::hash<promeki::MediaDuration> {
551 size_t operator()(
const promeki::MediaDuration &v)
const noexcept {
552 size_t h = std::hash<promeki::FrameNumber>()(v.start());
553 size_t k = std::hash<promeki::FrameCount>()(v.length());
555 return h ^ (k + 0x9e3779b97f4a7c15ULL + (h << 6) + (h >> 2));
562template <>
struct std::hash<promeki::MediaDuration::FrameRange> {
563 size_t operator()(
const promeki::MediaDuration::FrameRange &v)
const noexcept {
564 size_t h = std::hash<promeki::FrameNumber>()(v.start);
565 size_t k = std::hash<promeki::FrameNumber>()(v.end);
566 return h ^ (k + 0x9e3779b97f4a7c15ULL + (h << 6) + (h >> 2));