Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
time-formats-test.cpp
Go to the documentation of this file.
1/*
2 TimeFormats(Test) - timecode handling and formatting
3
4 Copyright (C)
5 2010, Hermann Vosseler <Ichthyostega@web.de>
6
7  **Lumiera** is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License as published by the
9  Free Software Foundation; either version 2 of the License, or (at your
10  option) any later version. See the file COPYING for further details.
11
12* *****************************************************************/
13
19#include "lib/test/run.hpp"
20//#include "lib/test/test-helper.hpp"
23#include "lib/time/timecode.hpp"
24#include "lib/time/mutation.hpp"
25#include "lib/format-cout.hpp"
26#include "lib/util.hpp"
27
28#include <string>
29
30using boost::lexical_cast;
31using util::isnil;
32using std::string;
33
34
35namespace lib {
36namespace time{
37namespace test{
38
40 using util::toString;
41 using format::Frames;
42 using format::Smpte;
43
44 namespace{
45 const FrameCnt MAX_FRAME = 265*24*60*60*25;
46
47 string
49 {
50 FrameCnt frameNr(0);
51 while (!frameNr)
52 frameNr = rani(2*MAX_FRAME) - MAX_FRAME;
53
54 return toString(frameNr)+"#";
55 }
56 }
57
58
59
60 /****************************************************/
67 class TimeFormats_test : public Test
68 {
69 virtual void
70 run (Arg)
71 {
72 seedRand();
74
76// checkFrames ();
77// checkSeconds ();
78// checkHms ();
79 checkSmpte();
80// checkDropFrame();
81// checkCopyAssignments();
82 }
83
84
95 void
97 {
98 string srcCode = generateRandomFrameNr();
99 PQuant refScale = Quantiser::retrieve("pal0");
100
101 // get internal (raw) time value
102 TimeValue t1 = format::Frames::parse (srcCode, *refScale);
103 ENSURE (0 != t1);
104
105 // manipulating
106 TimeVar v1(t1);
107 v1 += Time(FSecs(6,5));
108 CHECK (t1 < v1);
109
110 // quantising into an external grid
111 QuTime q1 (t1, "pal0");
112 CHECK (q1 == t1);
113
114 // further mutations (here nudge by +5 grid steps)
115 QuTime q2 = q1;
116 q2.accept (Mutation::nudge(+5));
117 CHECK (q1 < q2);
118
119 // converting (back) into a timecode format
120 FrameNr frames1(q1);
121 FrameNr frames2(q2);
122 CHECK (5 == frames2 - frames1);
123
125 CHECK (30 == q2.formatAs<Frames>() - frames1); // q2 == v1 == t1 + (6*5)/(5*5)sec
126
127 CHECK (srcCode == string(frames1));
128 CHECK (srcCode != string(frames2));
129
130 showTimeCode (frames1);
131 showTimeCode (frames2);
133 }
134
135
136 template<class TC>
137 void
138 showTimeCode (TC timecode)
139 {
140 cout << timecode.describe()<<"=\""<<timecode<<"\" time = "<< timecode.getTime() << endl;
141 }
142
143 void
145 {
146 UNIMPLEMENTED ("verify frame count time format");
147 }
148
149
150 void
152 {
153 UNIMPLEMENTED ("verify fractional seconds as timecode format");
154 }
155
156
157 void
159 {
160 UNIMPLEMENTED ("verify hour-minutes-seconds-millis timecode");
161 }
162
163
174 void
176 {
177 Time raw(555,23,42,5);
178 QuTime t1 (raw, "pal0");
179 SmpteTC smpte(t1);
180
181 cout << "----SMPTE-----" << endl;
182 showTimeCode(smpte);
183 CHECK (" 5:42:23:13" == string(smpte));
184 CHECK (raw - Time(35,0) == smpte.getTime()); // timecode value got quantised towards next lower frame
185 CHECK (13 == smpte.frames);
186 CHECK (23 == smpte.secs);
187 CHECK (42 == smpte.mins);
188 CHECK ( 5 == smpte.hours);
189 CHECK ( 1 == smpte.sgn);
190 CHECK ("SMPTE" == smpte.describe());
191
192 ++smpte;
193 CHECK (" 5:42:23:14" == string(smpte));
194 smpte.frames += 12;
195 CHECK (" 5:42:24:01" == string(smpte));
196 smpte.secs = -120;
197 CHECK (" 5:40:00:01" == string(smpte));
198 CHECK (smpte.mins-- == 40);
199 CHECK (--smpte.mins == 38);
200 CHECK (" 5:38:00:01" == string(smpte));
201
202 TimeVar tx = smpte.getTime();
203 CHECK (tx == Time(0,0,38,5) + Time(FSecs(1,25)));
204
205 // Extended SMPTE: extension of the axis beyond origin towards negative values
206 smpte.hours -= 6;
207 CHECK ("- 0:21:59:24"== string(smpte)); // representation is symmetrical to origin
208 CHECK (tx - Time(0,0,0,6) == smpte.getTime()); // Continuous time axis
209
210 CHECK (-1 == smpte.sgn); // Note: for these negative (extended) SMPTE...
211 CHECK (smpte.mins > 0); // ...the representation is really flipped around zero
212 CHECK (smpte.secs > 0);
213 CHECK (smpte.frames > 0);
214 tx = smpte.getTime();
215 ++smpte.frames; // now *increasing* the frame value
216 CHECK ("- 0:22:00:00"== string(smpte)); // means decreasing the resulting time
217 CHECK (smpte.getTime() == tx - Time(1000/25,0,0,0));
218 ++smpte; // but the orientation of the increment on the *whole* TC values is unaltered
219 CHECK ("- 0:21:59:24"== string(smpte)); // so this actually *advanced* time by one frame
220 CHECK (tx == smpte.getTime());
221 CHECK (tx < TimeValue(0));
222
223 smpte.mins -= 2*60; // now lets flip the representation again...
224 CHECK (" 1:38:00:01"== string(smpte));
225 CHECK (+1 == smpte.sgn);
226 CHECK (smpte.getTime() > 0);
227 CHECK (tx + Time(0,0,0,2) == smpte.getTime());
228 smpte.secs -= 2*60*60; // and again...
229 CHECK (tx == smpte.getTime());
230 CHECK ("- 0:21:59:24"== string(smpte));
231
232 smpte.sgn += 123; // just flip the sign
233 CHECK (" 0:21:59:24"== string(smpte));
234 CHECK (tx == -smpte.getTime());
235 CHECK (+1 == smpte.sgn); // sign value is limited to +1 / -1
236
237 smpte.secs.setValueRaw(61); // set "wrong" value, bypassing normalisation
238 CHECK (smpte.secs == 61);
239 CHECK (smpte.getTime() == Time(1000*24/25, 01, 22));
240 CHECK (smpte.secs == 61); // calculated value is correct, but doesn't change state
241 CHECK (" 0:21:61:24"== string(smpte));
242 smpte.rebuild(); // but rebuilding the value includes normalisation
243 CHECK (smpte.secs == 1);
244 CHECK (smpte.mins == 22);
245 CHECK (" 0:22:01:24"== string(smpte));
246
247 smpte.frames.setValueRaw (25);
248 CHECK (" 0:22:01:25"== string(smpte));
249 smpte.hours = -1; // flipped representation handles denormalised values properly
250 CHECK ("- 0:37:58:00"== string(smpte));
251
252 smpte.mins.setValueRaw (59);
253 smpte.secs.setValueRaw (61);
254 smpte.frames.setValueRaw(-26); // provoke multiple over/underflows...
255 smpte.hours.setValueRaw (-2);
256 CHECK ("--2:59:61:-26"==string(smpte));
257 tx = smpte.getTime();
258 CHECK (tx == -1*(Time(0,61,59) - Time(0,0,0,2) - Time(FSecs(26,25))));
259 smpte.invertOrientation();
260 CHECK (" 1:00:00:01"== string(smpte));
261 CHECK (tx == smpte.getTime()); // applying invertOrientation() doesn't change the value
262
263 smpte.frames.setValueRaw(-1);
264 tx -= Time(FSecs(2,25));
265 CHECK (tx == smpte.getTime());
266 CHECK (" 1:00:00:-1"== string(smpte));
267 smpte.invertOrientation(); // invoking on positive should create double negated representation
268 CHECK ("--1:00:00:01"== string(smpte)); // and here especially also causes a series of overflows
269 CHECK (tx == smpte.getTime()); // but without affecting the overall value
270 }
271
272
273 void
275 {
276 UNIMPLEMENTED ("verify especially SMPTE-drop-frame timecode");
277 }
278
279
280 void
282 {
283 UNIMPLEMENTED ("verify Timecode values can be copied and assigned properly");
284 }
285 };
286
287
289 LAUNCHER (TimeFormats_test, "unit common");
290
291
292
293}}} // namespace lib::time::test
void setValueRaw(NUM newVal)
Definition digxel.hpp:279
A frame counting timecode value.
Definition timecode.hpp:99
static const FrameRate PAL
predefined constant for PAL framerate
static EncapsulatedMutation nudge(int adjustment)
build a time mutation to nudge the target time value by an offset, defined as number of steps on an i...
Definition mutation.cpp:336
static EncapsulatedMutation changeTime(Time)
Convenience factory to yield a simple Mutation changing the absolute start time.
Definition mutation.cpp:285
grid aligned time specification, referring to a specific scale.
Definition timequant.hpp:91
void accept(Mutation const &)
receive change message, which might cause re-quantisation
format::Traits< FMT >::TimeCode formatAs() const
create new time code instance, then castInto
static PQuant retrieve(Symbol gridID)
Access an existing grid definition or quantiser, known by the given symbolic ID.
Classical Timecode value reminiscent to SMPTE format.
Definition timecode.hpp:147
void invertOrientation()
flip the orientation of min, sec, and frames.
Definition timecode.cpp:388
Time getTime() const
Definition timecode.hpp:64
string describe() const
Definition timecode.hpp:63
basic constant internal time value.
a mutable time value, behaving like a plain number, allowing copy and re-accessing
Lumiera's internal time value datatype.
Interface: a grid and scale definition for time quantisation.
Definition time-grid.hpp:80
static PGrid build(FrameRate frames_per_second)
Automatically use custom string conversion in C++ stream output.
Modifying time and timecode values.
int64_t FrameCnt
relative framecount or frame number.
Definition digxel.hpp:310
std::shared_ptr< const Quantiser > PQuant
Definition formats.hpp:58
boost::rational< int64_t > FSecs
rational representation of fractional seconds
Implementation namespace for support and library code.
int rani(uint bound=_iBOUND())
Definition random.hpp:135
Test runner and basic definitions for tests.
std::string toString(TY const &val) noexcept
get some string representation of any object, reliably.
bool isnil(lib::time::Duration const &dur)
Simplistic test class runner.
#define LAUNCHER(_TEST_CLASS_, _GROUPS_)
Definition run.hpp:116
Frame count as timecode format.
Definition formats.hpp:77
static TimeValue parse(string const &, QuantR)
try to parse a frame number specification
Definition timecode.cpp:64
Widely used standard media timecode format.
Definition formats.hpp:92
To establish a reference scale for quantised time values.
Timecode handling library This header defines the foundation interface TCode to represent a grid alig...
Support library to represent grid-aligned time specifications This is part of Lumiera's time and time...
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...