libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
framerate.h
Go to the documentation of this file.
1
9#pragma once
10
11
12#include <promeki/config.h>
13#if PROMEKI_ENABLE_CORE
14#include <promeki/namespace.h>
15#include <promeki/duration.h>
16#include <promeki/list.h>
17#include <promeki/rational.h>
18#include <promeki/result.h>
19#include <promeki/string.h>
20#include <promeki/datatype.h>
21
22PROMEKI_NAMESPACE_BEGIN
23
24class DataStream;
25
26#define PROMEKI_WELL_KNOWN_FRAME_RATES \
27 X(FPS_Invalid, "INV", 0, 1) \
28 X(FPS_120, "120", 120, 1) \
29 X(FPS_119_88, "119.88", 120000, 1001) \
30 X(FPS_100, "100", 100, 1) \
31 X(FPS_96, "96", 96, 1) \
32 X(FPS_95_90, "95.90", 96000, 1001) \
33 X(FPS_60, "60", 60, 1) \
34 X(FPS_59_94, "59.94", 60000, 1001) \
35 X(FPS_50, "50", 50, 1) \
36 X(FPS_48, "48", 48, 1) \
37 X(FPS_47_95, "47.95", 48000, 1001) \
38 X(FPS_30, "30", 30, 1) \
39 X(FPS_29_97, "29.97", 30000, 1001) \
40 X(FPS_25, "25", 25, 1) \
41 X(FPS_24, "24", 24, 1) \
42 X(FPS_23_98, "23.98", 24000, 1001)
43
110class FrameRate {
111 public:
112 PROMEKI_DATATYPE(FrameRate, DataTypeFrameRate, 1)
113
114
115 Error writeToStream(DataStream &s) const;
117 template <uint32_t V> static Result<FrameRate> readFromStream(DataStream &s);
118
120 using RationalType = Rational<unsigned int>;
121
122#define X(type, string, num, den) type,
124 enum WellKnownRate {
125 FPS_NotWellKnown = 0,
126 PROMEKI_WELL_KNOWN_FRAME_RATES
127 };
128#undef X
129
130 struct WellKnown;
131
151 static List<WellKnown> wellKnownRates();
152
154 FrameRate() = default;
155
160 FrameRate(WellKnownRate rate);
161
166 FrameRate(const RationalType &r);
167
172 bool isValid() const { return _fps.numerator() > 0; }
173
175 unsigned int numerator() const { return _fps.numerator(); }
176
178 unsigned int denominator() const { return _fps.denominator(); }
179
184 double toDouble() const { return _fps.toDouble(); }
185
205 static Result<FrameRate> fromDouble(double val);
206
223 Duration frameDuration() const {
224 if (!isValid()) return Duration();
225 // Period in ns = denom * 1e9 / num. Use 64-bit
226 // math so 1001 * 1e9 doesn't overflow.
227 int64_t num = static_cast<int64_t>(_fps.numerator());
228 int64_t den = static_cast<int64_t>(_fps.denominator());
229 int64_t ns = (den * INT64_C(1'000'000'000) + num / 2) / num;
230 return Duration::fromNanoseconds(ns);
231 }
232
284 int64_t cumulativeTicks(int64_t tickRate, int64_t frameIndex) const {
285 if (!isValid() || tickRate <= 0 || frameIndex < 0) return 0;
286 const int64_t num = static_cast<int64_t>(_fps.numerator());
287 const int64_t den = static_cast<int64_t>(_fps.denominator());
288 return (frameIndex * tickRate * den) / num;
289 }
290
314 size_t samplesPerFrame(int64_t sampleRate, int64_t frameIndex) const {
315 if (!isValid() || sampleRate <= 0 || frameIndex < 0) return 0;
316 const int64_t cumNow = cumulativeTicks(sampleRate, frameIndex);
317 const int64_t cumNext = cumulativeTicks(sampleRate, frameIndex + 1);
318 return static_cast<size_t>(cumNext - cumNow);
319 }
320
325 String toString() const { return _fps.toString(); }
326
331 bool isWellKnownRate() const { return wellKnownRate() != FPS_NotWellKnown; }
332
350 WellKnownRate wellKnownRate() const;
351
356 const RationalType &rational() const { return _fps; }
357
369 static Result<FrameRate> fromString(const String &str);
370
372 bool operator==(const FrameRate &other) const { return _fps == other._fps; }
373
375 bool operator!=(const FrameRate &other) const { return _fps != other._fps; }
376
377 private:
378 RationalType _fps;
379};
380
393struct FrameRate::WellKnown {
394 String label;
395 FrameRate rate;
396};
397
398PROMEKI_NAMESPACE_END
399
400PROMEKI_FORMAT_VIA_TOSTRING(promeki::FrameRate);
401
402#endif // PROMEKI_ENABLE_CORE