-
Notifications
You must be signed in to change notification settings - Fork 5.2k
/
Copy pathtimestamp.h
317 lines (272 loc) · 12 KB
/
timestamp.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
// Copyright 2019 The MediaPipe Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Two classes: Timestamp and TimestampDiff for specifying timestamps
// within the CalculatorFramework (and mediapipe in general). MediaPipe
// timestamps are in units of _microseconds_.
//
// There are several special values (All these values must be constructed
// using the static methods provided):
// Unset: The default initialization value, not generally
// valid when a timestamp is required.
// Unstarted: The timestamp before any valid timestamps. This is
// the input timestamp during Open().
// PreStream: A value for specifying that a packet contains "header"
// data that should be processed before any other
// timestamp. Like PostStream, if this value is sent then
// it must be the only value that is sent on the stream.
// Min: The minimum range timestamp to see in Process().
// Any number of "range" timestamp can be sent over a
// stream, provided that they are sent in monotonically
// increasing order.
// Max: The maximum range timestamp to see in Process().
// PostStream: A value for specifying that a packet pertains to
// the entire stream. This "summary" timestamp occurs
// after all the "range" timestamps. If this timestamp
// is sent on a stream, it must be the only packet sent.
// OneOverPostStream:
// The value immediately following PostStream.
// This should only be used internally.
// Done: The timestamp after all valid timestamps.
// This is the input timestamp during Close().
#ifndef MEDIAPIPE_FRAMEWORK_TIMESTAMP_H_
#define MEDIAPIPE_FRAMEWORK_TIMESTAMP_H_
#include <cmath>
#include <string>
#include "mediapipe/framework/deps/safe_int.h"
#include "mediapipe/framework/port/integral_types.h"
#include "mediapipe/framework/port/logging.h"
namespace mediapipe {
// A safe int checks each arithmetic operation to make sure it will not
// have underflow/overflow etc. This type is used internally by Timestamp
// and TimestampDiff.
MEDIAPIPE_DEFINE_SAFE_INT_TYPE(TimestampBaseType, int64,
mediapipe::intops::LogFatalOnError);
class TimestampDiff;
// A class which represents a timestamp in the calculator framework.
// There are several special values which can only be created with the
// static functions provided in this class.
class Timestamp {
public:
Timestamp();
// Construction of Timestamp() is explicit (TimestampDiff is not explicit).
explicit Timestamp(int64 timestamp);
explicit Timestamp(TimestampBaseType timestamp);
// Timestamps are in microseconds.
static constexpr double kTimestampUnitsPerSecond = 1000000.0;
// Use the default copy constructor, assignment operator, and destructor.
// Get the underlying int64 value being used. This should generally be
// avoided, but may be necessary for things like serialization.
int64 Value() const { return timestamp_.value(); }
// Return the value in units of seconds (the underlying value is in
// microseconds).
double Seconds() const { return Value() / kTimestampUnitsPerSecond; }
// Return the value in units of microseconds. The underlying value is already
// in microseconds, but this function should be preferred over Value() in case
// the underlying representation changes.
int64 Microseconds() const { return Value(); }
// This provides a human readable string for the special values.
std::string DebugString() const;
// For use by framework. Clients or Calculator implementations should not call
// this.
static Timestamp CreateNoErrorChecking(int64 timestamp);
// Create a timestamp from a seconds value.
static Timestamp FromSeconds(double seconds) {
return Timestamp(
TimestampBaseType{std::round(seconds * kTimestampUnitsPerSecond)});
}
// Special values.
static Timestamp Unset();
static Timestamp Unstarted();
static Timestamp PreStream();
static Timestamp Min();
static Timestamp Max();
static Timestamp PostStream();
static Timestamp OneOverPostStream();
static Timestamp Done();
// A special value is any of the values which cannot be constructed directly
// but must be constructed using the helper functions given above.
bool IsSpecialValue() const { return *this <= Min() || *this >= Max(); }
// A range value is anything between Min() and Max() (inclusive).
// Any number of packets with range values can be sent over a
// stream as long as they are sent in monotonically increasing order.
// IsRangeValue() isn't quite the opposite of IsSpecialValue() since it
// is valid to start a stream at Timestamp::Min() and continue until
// Timestamp::Max() (both of which are special values). PreStream()
// and PostStream() are not considered a range value even though
// they can be sent over a stream (they are "summary" timestamps not
// "range" timestamps).
//
// Notice that arithmetic may only be performed if IsRangeValue()
// is true. Arithmetic on Min and Max is valid but is almost certainly
// bad design.
bool IsRangeValue() const { return *this >= Min() && *this <= Max(); }
// Returns true iff this can be the timestamp of a Packet in a
// stream. Any number of RangeValue timestamps may be in a stream
// (in monotonically increasing order). Also, exactly one PreStream,
// or one PostStream packet is allowed.
bool IsAllowedInStream() const {
// This is a simplified expression for
// IsRangeValue() or PreStream() or PostStream().
return *this >= PreStream() && *this <= PostStream();
}
// Common operators.
bool operator==(const Timestamp other) const {
return timestamp_ == other.timestamp_;
}
bool operator!=(const Timestamp other) const {
return !(timestamp_ == other.timestamp_);
}
bool operator<(const Timestamp other) const {
return timestamp_ < other.timestamp_;
}
bool operator<=(const Timestamp other) const {
return timestamp_ <= other.timestamp_;
}
bool operator>(const Timestamp other) const {
return timestamp_ > other.timestamp_;
}
bool operator>=(const Timestamp other) const {
return timestamp_ >= other.timestamp_;
}
// Addition and subtraction of Timestamp and TimestampDiff values.
// Notice that subtracting two Timestamp values gives a TimestampDiff
// while adding a TimestampDiff to a Timestamp gives a Timestamp.
// Note that no special values are allowed to be the result of these
// operations.
//
// The addition or subtraction of a TimestampDiff to a Timestamp is clamped
// within the valid range of values [Timestamp::Min(), Timestamp::Max()].
//
// Not all operations are allowed, in particular, you cannot add two
// Timestamps, and you cannot subtract a Timestamp from a TimestampDiff.
TimestampDiff operator-(const Timestamp other) const;
Timestamp operator+(const TimestampDiff other) const;
Timestamp operator-(const TimestampDiff other) const;
// Unary negation of a Timestamp is not allowed.
// Provided for convenience.
Timestamp operator+=(const TimestampDiff other);
Timestamp operator-=(const TimestampDiff other);
Timestamp operator++();
Timestamp operator--();
Timestamp operator++(int);
Timestamp operator--(int);
// Returns the next timestamp in the range [Min .. Max], or
// OneOverPostStream() if no Packets may follow one with this timestamp.
// CHECKs that this->IsAllowedInStream().
Timestamp NextAllowedInStream() const;
// Returns the previous timestamp in the range [Min .. Max], or
// Unstarted() if no Packets may preceed one with this timestamp.
Timestamp PreviousAllowedInStream() const;
private:
TimestampBaseType timestamp_;
};
// A class which represents the difference between two timestamps in the
// calculator framework.
class TimestampDiff {
public:
TimestampDiff() : timestamp_(0) {}
// This constructor is not explicit.
TimestampDiff(int64 timestamp) : timestamp_(timestamp) { // NOLINT
}
// This constructor is not explicit.
TimestampDiff(TimestampBaseType timestamp) // NOLINT
: timestamp_(timestamp) {}
// Use the default copy constructor, assignment operator, and destructor.
// Get the underlying int64 value being used. This should generally be
// avoided, but may be necessary for things like serialization.
int64 Value() const { return timestamp_.value(); }
// Return the value in units of seconds (the underlying value is in
// microseconds).
double Seconds() const {
return Value() / Timestamp::kTimestampUnitsPerSecond;
}
// Return the value in units of microseconds. The underlying value is already
// in microseconds, but this function should be preferred over Value() in case
// the underlying representation changes.
int64 Microseconds() const { return Value(); }
std::string DebugString() const;
bool operator==(const TimestampDiff other) const {
return timestamp_ == other.timestamp_;
}
bool operator!=(const TimestampDiff other) const {
return !(timestamp_ == other.timestamp_);
}
bool operator<(const TimestampDiff other) const {
return timestamp_ < other.timestamp_;
}
bool operator<=(const TimestampDiff other) const {
return timestamp_ <= other.timestamp_;
}
bool operator>(const TimestampDiff other) const {
return timestamp_ > other.timestamp_;
}
bool operator>=(const TimestampDiff other) const {
return timestamp_ >= other.timestamp_;
}
// Unary negation of a TimestampDiff is allowed.
const TimestampDiff operator-() const { return TimestampDiff(-timestamp_); }
// See the addition and subtraction functions in Timestamp for details.
TimestampDiff operator+(const TimestampDiff other) const;
TimestampDiff operator-(const TimestampDiff other) const;
Timestamp operator+(const Timestamp other) const;
// Special values.
static TimestampDiff Unset() {
return TimestampDiff(Timestamp::Unset().Value());
}
private:
TimestampBaseType timestamp_;
};
// Convenience functions which are equivalent to using arg.DebugString().
std::ostream& operator<<(std::ostream& os, Timestamp arg);
std::ostream& operator<<(std::ostream& os, TimestampDiff arg);
// Implementation details.
inline Timestamp::Timestamp() : timestamp_(kint64min) {}
inline Timestamp::Timestamp(int64 timestamp) : timestamp_(timestamp) {
CHECK(!IsSpecialValue())
<< "Cannot directly create a Timestamp with a special value: "
<< CreateNoErrorChecking(timestamp);
}
inline Timestamp::Timestamp(TimestampBaseType timestamp)
: timestamp_(timestamp) {
CHECK(!IsSpecialValue())
<< "Cannot directly create a Timestamp with a special value: "
<< CreateNoErrorChecking(timestamp.value());
}
inline Timestamp Timestamp::CreateNoErrorChecking(int64 timestamp) {
Timestamp tmp;
tmp.timestamp_ = TimestampBaseType(timestamp);
return tmp;
}
inline Timestamp Timestamp::Unset() { return Timestamp(); }
inline Timestamp Timestamp::Unstarted() {
return CreateNoErrorChecking(kint64min + 1);
}
inline Timestamp Timestamp::PreStream() {
return CreateNoErrorChecking(kint64min + 2);
}
inline Timestamp Timestamp::Min() {
return CreateNoErrorChecking(kint64min + 3);
}
inline Timestamp Timestamp::Max() {
return CreateNoErrorChecking(kint64max - 3);
}
inline Timestamp Timestamp::PostStream() {
return CreateNoErrorChecking(kint64max - 2);
}
inline Timestamp Timestamp::OneOverPostStream() {
return CreateNoErrorChecking(kint64max - 1);
}
inline Timestamp Timestamp::Done() { return CreateNoErrorChecking(kint64max); }
} // namespace mediapipe
#endif // MEDIAPIPE_FRAMEWORK_TIMESTAMP_H_