1/*
2 * Copyright (C) 2012 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#pragma once
30
31#include <wtf/FastMalloc.h>
32#include <wtf/JSONValues.h>
33#include <wtf/text/WTFString.h>
34
35#include <cmath>
36#include <limits>
37#include <math.h>
38#include <stdint.h>
39
40namespace WTF {
41
42class PrintStream;
43
44class WTF_EXPORT_PRIVATE MediaTime final {
45 WTF_MAKE_FAST_ALLOCATED;
46public:
47 enum {
48 Valid = 1 << 0,
49 HasBeenRounded = 1 << 1,
50 PositiveInfinite = 1 << 2,
51 NegativeInfinite = 1 << 3,
52 Indefinite = 1 << 4,
53 DoubleValue = 1 << 5,
54 };
55
56 MediaTime();
57 MediaTime(int64_t value, uint32_t scale, uint8_t flags = Valid);
58 MediaTime(const MediaTime& rhs);
59 ~MediaTime();
60
61 static MediaTime createWithFloat(float floatTime);
62 static MediaTime createWithFloat(float floatTime, uint32_t timeScale);
63 static MediaTime createWithDouble(double doubleTime);
64 static MediaTime createWithDouble(double doubleTime, uint32_t timeScale);
65
66 float toFloat() const;
67 double toDouble() const;
68
69 MediaTime& operator=(const MediaTime& rhs);
70 MediaTime& operator+=(const MediaTime& rhs) { return *this = *this + rhs; }
71 MediaTime& operator-=(const MediaTime& rhs) { return *this = *this - rhs; }
72 MediaTime operator+(const MediaTime& rhs) const;
73 MediaTime operator-(const MediaTime& rhs) const;
74 MediaTime operator-() const;
75 MediaTime operator*(int32_t) const;
76 bool operator<(const MediaTime& rhs) const { return compare(rhs) == LessThan; }
77 bool operator>(const MediaTime& rhs) const { return compare(rhs) == GreaterThan; }
78 bool operator!=(const MediaTime& rhs) const { return compare(rhs) != EqualTo; }
79 bool operator==(const MediaTime& rhs) const { return compare(rhs) == EqualTo; }
80 bool operator>=(const MediaTime& rhs) const { return compare(rhs) >= EqualTo; }
81 bool operator<=(const MediaTime& rhs) const { return compare(rhs) <= EqualTo; }
82 bool operator!() const;
83 explicit operator bool() const;
84
85 typedef enum {
86 LessThan = -1,
87 EqualTo = 0,
88 GreaterThan = 1,
89 } ComparisonFlags;
90
91 ComparisonFlags compare(const MediaTime& rhs) const;
92 bool isBetween(const MediaTime&, const MediaTime&) const;
93
94 bool isValid() const { return m_timeFlags & Valid; }
95 bool isInvalid() const { return !isValid(); }
96 bool hasBeenRounded() const { return m_timeFlags & HasBeenRounded; }
97 bool isPositiveInfinite() const { return m_timeFlags & PositiveInfinite; }
98 bool isNegativeInfinite() const { return m_timeFlags & NegativeInfinite; }
99 bool isIndefinite() const { return m_timeFlags & Indefinite; }
100 bool hasDoubleValue() const { return m_timeFlags & DoubleValue; }
101 uint8_t timeFlags() const { return m_timeFlags; }
102
103 static const MediaTime& zeroTime();
104 static const MediaTime& invalidTime();
105 static const MediaTime& positiveInfiniteTime();
106 static const MediaTime& negativeInfiniteTime();
107 static const MediaTime& indefiniteTime();
108
109 const int64_t& timeValue() const { return m_timeValue; }
110 const uint32_t& timeScale() const { return m_timeScale; }
111
112 void dump(PrintStream& out) const;
113 String toString() const;
114 String toJSONString() const;
115 Ref<JSON::Object> toJSONObject() const;
116
117 // Make the following casts errors:
118 operator double() const = delete;
119 MediaTime(double) = delete;
120 operator int() const = delete;
121 MediaTime(int) = delete;
122
123 friend WTF_EXPORT_PRIVATE MediaTime abs(const MediaTime& rhs);
124
125 static const uint32_t DefaultTimeScale = 10000000;
126 static const uint32_t MaximumTimeScale;
127
128 enum class RoundingFlags {
129 HalfAwayFromZero = 0,
130 TowardZero,
131 AwayFromZero,
132 TowardPositiveInfinity,
133 TowardNegativeInfinity,
134 };
135
136 MediaTime toTimeScale(uint32_t, RoundingFlags = RoundingFlags::HalfAwayFromZero) const;
137
138 template<class Encoder> void encode(Encoder&) const;
139 template<class Decoder> static bool decode(Decoder&, MediaTime&);
140
141private:
142 void setTimeScale(uint32_t, RoundingFlags = RoundingFlags::HalfAwayFromZero);
143
144 union {
145 int64_t m_timeValue;
146 double m_timeValueAsDouble;
147 };
148 uint32_t m_timeScale;
149 uint8_t m_timeFlags;
150};
151
152inline MediaTime operator*(int32_t lhs, const MediaTime& rhs) { return rhs.operator*(lhs); }
153
154WTF_EXPORT_PRIVATE extern MediaTime abs(const MediaTime& rhs);
155
156struct WTF_EXPORT_PRIVATE MediaTimeRange {
157 WTF_MAKE_STRUCT_FAST_ALLOCATED;
158
159 String toJSONString() const;
160
161 const MediaTime start;
162 const MediaTime end;
163};
164
165template<class Encoder>
166void MediaTime::encode(Encoder& encoder) const
167{
168 encoder << m_timeValue << m_timeScale << m_timeFlags;
169}
170
171template<class Decoder>
172bool MediaTime::decode(Decoder& decoder, MediaTime& time)
173{
174 return decoder.decode(time.m_timeValue)
175 && decoder.decode(time.m_timeScale)
176 && decoder.decode(time.m_timeFlags);
177}
178
179template<typename Type>
180struct LogArgument;
181
182template <>
183struct LogArgument<MediaTime> {
184 static String toString(const MediaTime& time)
185 {
186 return time.toJSONString();
187 }
188};
189
190template <>
191struct LogArgument<MediaTimeRange> {
192 static String toString(const MediaTimeRange& range)
193 {
194 return range.toJSONString();
195 }
196};
197
198}
199
200using WTF::MediaTime;
201using WTF::MediaTimeRange;
202using WTF::abs;
203