forked from h4tr3d/avcpp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtimestamp.h
168 lines (136 loc) · 4.54 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
#pragma once
#include <chrono>
#include "avutils.h"
#include "rational.h"
namespace av {
/**
* @brief The Timestamp class represents timestamp value and it timebase
*/
class Timestamp
{
public:
Timestamp() noexcept;
Timestamp(int64_t timestamp, const Rational &timebase) noexcept;
/**
* @brief Create AvCpp/FFmpeg compatible timestamp value from the std::chrono::duration/boost::chrono::duration
*/
template<typename Duration, typename = typename Duration::period>
Timestamp(const Duration& duration)
{
using Ratio = typename Duration::period;
static_assert(Ratio::num <= INT_MAX, "To prevent precision lost, ratio numerator must be less then INT_MAX");
static_assert(Ratio::den <= INT_MAX, "To prevent precision lost, ratio denominator must be less then INT_MAX");
m_timestamp = duration.count();
m_timebase = Rational(static_cast<int>(Ratio::num),
static_cast<int>(Ratio::den));
}
int64_t timestamp() const noexcept;
int64_t timestamp(const Rational &timebase) const noexcept;
const Rational& timebase() const noexcept;
operator bool() const noexcept;
bool isValid() const noexcept;
bool isNoPts() const noexcept;
operator double() const noexcept;
double seconds() const noexcept;
/**
* @brief Convert to the std::chrono::duration compatible value
*/
template<typename Duration>
Duration toDuration() const
{
using Ratio = typename Duration::period;
static_assert(Ratio::num <= INT_MAX, "To prevent precision lost, ratio numerator must be less then INT_MAX");
static_assert(Ratio::den <= INT_MAX, "To prevent precision lost, ratio denominator must be less then INT_MAX");
Rational dstTimebase(static_cast<int>(Ratio::num),
static_cast<int>(Ratio::den));
auto ts = m_timebase.rescale(m_timestamp, dstTimebase);
return Duration(ts);
}
Timestamp& operator+=(const Timestamp &other);
Timestamp& operator-=(const Timestamp &other);
Timestamp& operator*=(const Timestamp &other);
Timestamp& operator/=(const Timestamp &other);
private:
int64_t m_timestamp = av::NoPts;
Rational m_timebase = av::TimeBaseQ;
};
//
// Comparation
//
inline
bool operator>(const Timestamp& left, const Timestamp &right) noexcept
{
return av_compare_ts(left.timestamp(), left.timebase(),
right.timestamp(), right.timebase()) > 0;
}
inline
bool operator<(const Timestamp& left, const Timestamp &right) noexcept
{
return av_compare_ts(left.timestamp(), left.timebase(),
right.timestamp(), right.timebase()) < 0;
}
inline
bool operator==(const Timestamp& left, const Timestamp &right) noexcept
{
return av_compare_ts(left.timestamp(), left.timebase(),
right.timestamp(), right.timebase()) == 0;
}
inline
bool operator!=(const Timestamp& left, const Timestamp &right) noexcept
{
return !operator==(left, right);
}
inline
bool operator>=(const Timestamp& left, const Timestamp& right) noexcept
{
return av_compare_ts(left.timestamp(), left.timebase(),
right.timestamp(), right.timebase()) >= 0;
}
inline
bool operator<=(const Timestamp& left, const Timestamp& right) noexcept
{
return av_compare_ts(left.timestamp(), left.timebase(),
right.timestamp(), right.timebase()) <= 0;
}
//
// Math operations
//
Timestamp operator+(const Timestamp& left, const Timestamp &right) noexcept;
Timestamp operator-(const Timestamp& left, const Timestamp &right) noexcept;
Timestamp operator*(const Timestamp& left, const Timestamp &right) noexcept;
Timestamp operator/(const Timestamp& left, const Timestamp &right) noexcept;
//
// Output
//
inline
std::ostream& operator<<(std::ostream &ost, const Timestamp &ts)
{
if (ts.isNoPts()) {
ost << "NO_PTS";
} else {
ost << ts.timestamp() << '*' << ts.timebase();
}
return ost;
}
} // ::av
#ifdef __cpp_lib_format
#include <format>
// std::format
template <typename CharT>
struct std::formatter<av::Timestamp, CharT>
{
template<typename ParseContext>
constexpr auto parse(ParseContext& ctx)
{
return ctx.begin();
}
template<typename ParseContext>
auto format(const av::Timestamp& ts, ParseContext& ctx) const
{
if (ts.isNoPts()) {
return std::format_to(ctx.out(), "NO_PTS");
}
return std::format_to(ctx.out(), "{}*{}", ts.timestamp(), ts.timebase());
}
};
#endif