mediapipe/mediapipe/framework/timestamp.h
MediaPipe Team cc6a2f7af6 Project import generated by Copybara.
GitOrigin-RevId: 73d686c40057684f8bfaca285368bf1813f9fc26
2022-03-21 12:12:39 -07:00

318 lines
12 KiB
C++

// 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_