Lumiera  0.pre.03
»edit your freedom«
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"
22 #include "lib/time/timequant.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 
30 using boost::lexical_cast;
31 using util::isnil;
32 using std::string;
33 
34 
35 namespace lib {
36 namespace time{
37 namespace 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
48  generateRandomFrameNr()
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 
124  q2.accept (Mutation::changeTime(v1));
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);
132  showTimeCode (q2.formatAs<Smpte>());
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
144  checkFrames ()
145  {
146  UNIMPLEMENTED ("verify frame count time format");
147  }
148 
149 
150  void
151  checkSeconds ()
152  {
153  UNIMPLEMENTED ("verify fractional seconds as timecode format");
154  }
155 
156 
157  void
158  checkHms ()
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
274  checkDropFrame ()
275  {
276  UNIMPLEMENTED ("verify especially SMPTE-drop-frame timecode");
277  }
278 
279 
280  void
281  checkCopyAssignments ()
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
static TimeValue parse(string const &, QuantR)
try to parse a frame number specification
Definition: timecode.cpp:65
a mutable time value, behaving like a plain number, allowing copy and re-accessing ...
Definition: timevalue.hpp:232
Interface: a grid and scale definition for time quantisation.
Definition: time-grid.hpp:77
Frame count as timecode format.
Definition: formats.hpp:75
Automatically use custom string conversion in C++ stream output.
Classical Timecode value reminiscent to SMPTE format.
Definition: timecode.hpp:141
Modifying time and timecode values.
static PQuant retrieve(Symbol gridID)
Access an existing grid definition or quantiser, known by the given symbolic ID.
static EncapsulatedMutation changeTime(Time)
Convenience factory to yield a simple Mutation changing the absolute start time.
Definition: mutation.cpp:285
Definition: run.hpp:40
Widely used standard media timecode format.
Definition: formats.hpp:90
int rani(uint bound=_iBOUND())
Definition: random.hpp:135
static PGrid build(FrameRate frames_per_second)
Definition: time-grid.cpp:158
void accept(Mutation const &)
receive change message, which might cause re-quantisation
Implementation namespace for support and library code.
Lumiera&#39;s internal time value datatype.
Definition: timevalue.hpp:299
format::Traits< FMT >::TimeCode formatAs() const
create new time code instance, then castInto
Definition: timequant.hpp:138
Timecode handling library This header defines the foundation interface TCode to represent a grid alig...
Simplistic test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
std::string toString(TY const &val) noexcept
get some string representation of any object, reliably.
Definition: format-obj.hpp:191
boost::rational< int64_t > FSecs
rational representation of fractional seconds
Definition: timevalue.hpp:220
Support library to represent grid-aligned time specifications This is part of Lumiera&#39;s time and time...
To establish a reference scale for quantised time values.
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
int64_t FrameCnt
relative framecount or frame number.
Definition: digxel.hpp:312
A frame counting timecode value.
Definition: timecode.hpp:96
basic constant internal time value.
Definition: timevalue.hpp:133
static const FrameRate PAL
predefined constant for PAL framerate
Definition: timevalue.hpp:671
grid aligned time specification, referring to a specific scale.
Definition: timequant.hpp:90