avcpp  2.0
Wrapper for the FFmpeg that simplify usage from C++ projects.
timestamp.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <chrono>
4 
5 #include "avutils.h"
6 #include "rational.h"
7 
8 namespace av {
9 
17 class Timestamp
18 {
19 public:
20  Timestamp() noexcept;
21  Timestamp(int64_t timestamp, const Rational &timebase) noexcept;
22 
30  template<typename Duration,
31  typename = typename Duration::period,
32  typename = std::enable_if_t<std::is_integral_v<typename Duration::rep>>>
33  constexpr Timestamp(const Duration& duration)
34  {
35  using Ratio = typename Duration::period;
36 
37  static_assert(Ratio::num <= INT_MAX, "To prevent precision lost, ratio numerator must be less then INT_MAX");
38  static_assert(Ratio::den <= INT_MAX, "To prevent precision lost, ratio denominator must be less then INT_MAX");
39 
40  m_timestamp = duration.count();
41  m_timebase = Rational(static_cast<int>(Ratio::num),
42  static_cast<int>(Ratio::den));
43  }
44 
52  template<typename Duration,
53  typename PrecisionPeriod,
54  typename = typename Duration::period,
55  typename = std::enable_if_t<std::is_floating_point_v<typename Duration::rep>>>
56  constexpr Timestamp(const Duration& duration, PrecisionPeriod)
57  : Timestamp(duration, Rational{static_cast<int>(PrecisionPeriod::num), static_cast<int>(PrecisionPeriod::den)})
58  {
59  using Ratio = typename Duration::period;
60  static_assert(Ratio::num <= INT_MAX, "To prevent precision lost, ratio numerator must be less then INT_MAX");
61  static_assert(Ratio::den <= INT_MAX, "To prevent precision lost, ratio denominator must be less then INT_MAX");
62  static_assert(PrecisionPeriod::num <= INT_MAX, "To prevent precision lost, ratio numerator must be less then INT_MAX");
63  static_assert(PrecisionPeriod::den <= INT_MAX, "To prevent precision lost, ratio denominator must be less then INT_MAX");
64  }
65 
71  template<typename Duration,
72  typename = typename Duration::period,
73  typename = std::enable_if_t<std::is_floating_point_v<typename Duration::rep>>>
74  constexpr Timestamp(const Duration& duration, const Rational& timebase)
75  : m_timebase(timebase)
76  {
77  using ValueType = typename Duration::rep;
78  using Ratio = typename Duration::period;
79 
80  static_assert(Ratio::num <= INT_MAX, "To prevent precision lost, ratio numerator must be less then INT_MAX");
81  static_assert(Ratio::den <= INT_MAX, "To prevent precision lost, ratio denominator must be less then INT_MAX");
82 
83  // rescale input ticks into integer one
84  // m_timestamp = ts * Raio / m_timebase
85  ValueType const b = static_cast<ValueType>(Ratio::num) * m_timebase.getDenominator();
86  ValueType const c = static_cast<ValueType>(Ratio::den) * m_timebase.getNumerator();
87 
88  m_timestamp = static_cast<int64_t>(duration.count() * b / c);
89  }
90 
91 
92  int64_t timestamp() const noexcept;
93  int64_t timestamp(const Rational &timebase) const noexcept;
94  const Rational& timebase() const noexcept;
95 
96  operator bool() const noexcept;
97  bool isValid() const noexcept;
98  bool isNoPts() const noexcept;
99 
100  operator double() const noexcept;
101  double seconds() const noexcept;
102 
109  template<typename Duration,
110  typename = typename Duration::period,
111  typename = typename Duration::rep>
112  constexpr Duration toDuration() const
113  {
114  using ValueType = typename Duration::rep;
115  using Ratio = typename Duration::period;
116 
117  static_assert(Ratio::num <= INT_MAX, "To prevent precision lost, ratio numerator must be less then INT_MAX");
118  static_assert(Ratio::den <= INT_MAX, "To prevent precision lost, ratio denominator must be less then INT_MAX");
119 
120  if constexpr (std::is_integral_v<ValueType>) {
121  Rational dstTimebase(static_cast<int>(Ratio::num),
122  static_cast<int>(Ratio::den));
123  auto ts = m_timebase.rescale(m_timestamp, dstTimebase);
124  return Duration(ts);
125  } else {
126  namespace dt = std::chrono;
127  // ts = m_timestamp * m_timebase / dstTimebase
128  ValueType const b = m_timebase.getNumerator() * static_cast<ValueType>(Ratio::den);
129  ValueType const c = m_timebase.getDenominator() * static_cast<ValueType>(Ratio::num);
130  ValueType const ts = static_cast<ValueType>(m_timestamp) * b / c;
131  return Duration{ts};
132  }
133  }
134 
135  Timestamp& operator+=(const Timestamp &other);
136  Timestamp& operator-=(const Timestamp &other);
137  Timestamp& operator*=(const Timestamp &other);
138  Timestamp& operator/=(const Timestamp &other);
139 
140 private:
141  int64_t m_timestamp = av::NoPts;
142  Rational m_timebase = av::TimeBaseQ;
143 };
144 
145 
146 //
147 // Comparation
148 //
149 
150 inline
151 bool operator>(const Timestamp& left, const Timestamp &right) noexcept
152 {
153  return av_compare_ts(left.timestamp(), left.timebase(),
154  right.timestamp(), right.timebase()) > 0;
155 }
156 
157 
158 inline
159 bool operator<(const Timestamp& left, const Timestamp &right) noexcept
160 {
161  return av_compare_ts(left.timestamp(), left.timebase(),
162  right.timestamp(), right.timebase()) < 0;
163 }
164 
165 
166 inline
167 bool operator==(const Timestamp& left, const Timestamp &right) noexcept
168 {
169  return av_compare_ts(left.timestamp(), left.timebase(),
170  right.timestamp(), right.timebase()) == 0;
171 }
172 
173 inline
174 bool operator!=(const Timestamp& left, const Timestamp &right) noexcept
175 {
176  return !operator==(left, right);
177 }
178 
179 inline
180 bool operator>=(const Timestamp& left, const Timestamp& right) noexcept
181 {
182  return av_compare_ts(left.timestamp(), left.timebase(),
183  right.timestamp(), right.timebase()) >= 0;
184 }
185 
186 inline
187 bool operator<=(const Timestamp& left, const Timestamp& right) noexcept
188 {
189  return av_compare_ts(left.timestamp(), left.timebase(),
190  right.timestamp(), right.timebase()) <= 0;
191 }
192 
193 //
194 // Math operations
195 //
196 
197 Timestamp operator+(const Timestamp& left, const Timestamp &right) noexcept;
198 Timestamp operator-(const Timestamp& left, const Timestamp &right) noexcept;
199 Timestamp operator*(const Timestamp& left, const Timestamp &right) noexcept;
200 Timestamp operator/(const Timestamp& left, const Timestamp &right) noexcept;
201 
202 //
203 // Output
204 //
205 inline
206 std::ostream& operator<<(std::ostream &ost, const Timestamp &ts)
207 {
208  if (ts.isNoPts()) {
209  ost << "NO_PTS";
210  } else {
211  ost << ts.timestamp() << '*' << ts.timebase();
212  }
213  return ost;
214 }
215 
216 } // ::av
217 
218 #ifdef __cpp_lib_format
219 #include <format>
220 
221 // std::format
222 template <typename CharT>
223 struct std::formatter<av::Timestamp, CharT>
224 {
225  template<typename ParseContext>
226  constexpr auto parse(ParseContext& ctx)
227  {
228  return ctx.begin();
229  }
230 
231  template<typename ParseContext>
232  auto format(const av::Timestamp& ts, ParseContext& ctx) const
233  {
234  if (ts.isNoPts()) {
235  return std::format_to(ctx.out(), "NO_PTS");
236  }
237  return std::format_to(ctx.out(), "{}*{}", ts.timestamp(), ts.timebase());
238  }
239 };
240 #endif
Definition: rational.h:26
int getDenominator() const noexcept
Definition: rational.h:41
int64_t rescale(int64_t srcValue, const Rational &dstBase) const noexcept
Definition: rational.cpp:36
int getNumerator() const noexcept
Definition: rational.h:40
The Timestamp class represents timestamp value and it timebase.
Definition: timestamp.h:18
bool isNoPts() const noexcept
Definition: timestamp.cpp:39
Timestamp() noexcept
Definition: timestamp.cpp:9
int64_t timestamp() const noexcept
Definition: timestamp.cpp:19
constexpr Timestamp(const Duration &duration)
Create AvCpp/FFmpeg compatible timestamp value from the std::chrono::duration/boost::chrono::duration...
Definition: timestamp.h:33
Timestamp & operator+=(const Timestamp &other)
Definition: timestamp.cpp:57
bool isValid() const noexcept
Definition: timestamp.cpp:34
constexpr Timestamp(const Duration &duration, PrecisionPeriod)
Create AvCpp/FFmpeg compatible timestamp value from the floating point std::chrono::duration/boost::c...
Definition: timestamp.h:56
double seconds() const noexcept
Definition: timestamp.cpp:49
const Rational & timebase() const noexcept
Definition: timestamp.cpp:29
constexpr Duration toDuration() const
Convert to the std::chrono::duration compatible value.
Definition: timestamp.h:112
Timestamp & operator/=(const Timestamp &other)
Definition: timestamp.cpp:78
Timestamp & operator-=(const Timestamp &other)
Definition: timestamp.cpp:64
Timestamp & operator*=(const Timestamp &other)
Definition: timestamp.cpp:71
constexpr Timestamp(const Duration &duration, const Rational &timebase)
Create AvCpp/FFmpeg compatible timestamp value from the floating point std::chrono::duration/boost::c...
Definition: timestamp.h:74
Definition: audioresampler.cpp:8
std::ostream & operator<<(std::ostream &stream, const Rational &value)
Definition: rational.h:117
bool operator<(const Timestamp &left, const Timestamp &right) noexcept
Definition: timestamp.h:159
Timestamp operator-(const Timestamp &left, const Timestamp &right) noexcept
Definition: timestamp.cpp:102
Timestamp operator+(const Timestamp &left, const Timestamp &right) noexcept
Definition: timestamp.cpp:90
bool operator>(const Timestamp &left, const Timestamp &right) noexcept
Definition: timestamp.h:151
bool operator<=(const Timestamp &left, const Timestamp &right) noexcept
Definition: timestamp.h:187
bool operator>=(const Timestamp &left, const Timestamp &right) noexcept
Definition: timestamp.h:180
Timestamp operator*(const Timestamp &left, const Timestamp &right) noexcept
Definition: timestamp.cpp:114
constexpr auto TimeBaseQ
Definition: avutils.h:38
bool operator==(const Dictionary::Entry &lhs, const Dictionary::Entry &rhs)
Definition: dictionary.cpp:382
bool operator!=(const Dictionary::Entry &lhs, const Dictionary::Entry &rhs)
Definition: dictionary.cpp:387
auto operator/(T num, Rational value) -> std::enable_if_t< std::is_floating_point_v< T >||std::is_integral_v< T >, Rational >
Definition: rational.h:104
constexpr auto NoPts
Definition: avutils.h:36