LUMIERA.clone/tests/lib/time/time-formats-test.cpp
Ichthyostega b843546922 cumulated build/release fixes
up to corresponding debian/0.pre.01-3
- compile issue (digxel.hpp)
- SCons missing config dependency on test-only
- 32/64bit fixes
2011-03-31 18:43:50 +02:00

236 lines
8.7 KiB
C++

/*
TimeFormats(Test) - timecode handling and formatting
Copyright (C) Lumiera.org
2010, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
#include "lib/test/run.hpp"
//#include "lib/test/test-helper.hpp"
#include "proc/asset/meta/time-grid.hpp"
#include "lib/time/timequant.hpp"
#include "lib/time/timecode.hpp"
#include "lib/time/display.hpp"
#include "lib/util.hpp"
#include <boost/lexical_cast.hpp>
#include <iostream>
//#include <cstdlib>
using boost::lexical_cast;
using util::isnil;
//using std::rand;
using std::cout;
using std::endl;
namespace lib {
namespace time{
namespace test{
using asset::meta::TimeGrid;
/********************************************************
* @test verify handling of grid aligned timecode values.
* - full cycle from parsing to formatting
* - mutating the components of timecode
* - some formatting corner cases
* - formatting in various formats
*/
class TimeFormats_test : public Test
{
virtual void
run (Arg)
{
TimeGrid::build("pal0", FrameRate::PAL);
// checkTimecodeUsageCycle ();
// checkFrames ();
// checkSeconds ();
// checkHms ();
checkSmpte();
// checkDropFrame();
// checkCopyAssignments();
}
void
checkTimecodeUsageCycle ()
{
UNIMPLEMENTED ("full usage cycle for a timecode value");
}
template<class TC>
void
showTimeCode (TC timecode)
{
cout << timecode.describe()<<"=\""<<timecode<<"\" time = "<< timecode.getTime() << endl;
}
void
checkFrames ()
{
UNIMPLEMENTED ("verify frame count time format");
}
void
checkSeconds ()
{
UNIMPLEMENTED ("verify seconds as timecode format");
}
void
checkHms ()
{
UNIMPLEMENTED ("verify hour-minutes-seconds-millis timecode");
}
/** @test detailed coverage of SMPTE timecode representation.
* Using a scale grid with PAL framerate; this test doesn't
* cover the handling of drop-frame timecode.
* - creating a timecode representation causes frame quantisation
* - the components of SMPTE timecode can be accessed and manipulated
* - timecode can be incremented/decremented as a whole
* - we allow extension of the scale towards negative values
* - for these, the representation is flipped and the negative
* orientation only indicated through the sign field.
*/
void
checkSmpte ()
{
Time raw(555,23,42,5);
QuTime t1 (raw, "pal0");
SmpteTC smpte(t1);
showTimeCode(smpte);
CHECK (" 5:42:23:13" == string(smpte));
CHECK (raw - Time(35,0) == smpte.getTime()); // timecode value got quantised towards next lower frame
CHECK (13 == smpte.frames);
CHECK (23 == smpte.secs);
CHECK (42 == smpte.mins);
CHECK ( 5 == smpte.hours);
CHECK ( 1 == smpte.sgn);
CHECK ("SMPTE" == smpte.describe());
++smpte;
CHECK (" 5:42:23:14" == string(smpte));
smpte.frames += 12;
CHECK (" 5:42:24:01" == string(smpte));
smpte.secs = -120;
CHECK (" 5:40:00:01" == string(smpte));
CHECK (smpte.mins-- == 40);
CHECK (--smpte.mins == 38);
CHECK (" 5:38:00:01" == string(smpte));
TimeVar tx = smpte.getTime();
CHECK (tx == Time(0,0,38,5) + Time(FSecs(1,25)));
// Extended SMPTE: extension of the axis beyond origin towards negative values
smpte.hours -= 6;
CHECK ("- 0:21:59:24"== string(smpte)); // representation is symmetrical to origin
CHECK (tx - Time(0,0,0,6) == smpte.getTime()); // Continuous time axis
CHECK (-1 == smpte.sgn); // Note: for these negative (extended) SMPTE...
CHECK (smpte.mins > 0); // ...the representation is really flipped around zero
CHECK (smpte.secs > 0);
CHECK (smpte.frames > 0);
tx = smpte.getTime();
++smpte.frames; // now *increasing* the frame value
CHECK ("- 0:22:00:00"== string(smpte)); // means decreasing the resulting time
CHECK (smpte.getTime() == tx - Time(1000/25,0,0,0));
++smpte; // but the orientation of the increment on the *whole* TC values is unaltered
CHECK ("- 0:21:59:24"== string(smpte)); // so this actually *advanced* time by one frame
CHECK (tx == smpte.getTime());
CHECK (tx < TimeValue(0));
smpte.mins -= 2*60; // now lets flip the representation again...
CHECK (" 1:38:00:01"== string(smpte));
CHECK (+1 == smpte.sgn);
CHECK (smpte.getTime() > 0);
CHECK (tx + Time(0,0,0,2) == smpte.getTime());
smpte.secs -= 2*60*60; // and again...
CHECK (tx == smpte.getTime());
CHECK ("- 0:21:59:24"== string(smpte));
smpte.sgn += 123; // just flip the sign
CHECK (" 0:21:59:24"== string(smpte));
CHECK (tx == -smpte.getTime());
CHECK (+1 == smpte.sgn); // sign value is limited to +1 / -1
smpte.secs.setValueRaw(61); // set "wrong" value, bypassing normalisation
CHECK (smpte.secs == 61);
CHECK (smpte.getTime() == Time(1000*24/25, 01, 22));
CHECK (smpte.secs == 61); // calculated value is correct, but doesn't change state
CHECK (" 0:21:61:24"== string(smpte));
smpte.rebuild(); // but rebuilding the value includes normalisation
CHECK (smpte.secs == 1);
CHECK (smpte.mins == 22);
CHECK (" 0:22:01:24"== string(smpte));
smpte.frames.setValueRaw (25);
CHECK (" 0:22:01:25"== string(smpte));
smpte.hours = -1; // flipped representation handles denormalised values properly
CHECK ("- 0:37:58:00"== string(smpte));
smpte.mins.setValueRaw (59);
smpte.secs.setValueRaw (61);
smpte.frames.setValueRaw(-26); // provoke multiple over/underflows...
smpte.hours.setValueRaw (-2);
CHECK ("--2:59:61:-26"==string(smpte));
tx = smpte.getTime();
CHECK (tx == -1*(Time(0,61,59) - Time(0,0,0,2) - Time(FSecs(26,25))));
smpte.invertOrientation();
CHECK (" 1:00:00:01"== string(smpte));
CHECK (tx == smpte.getTime()); // applying invertOrientation() doesn't change the value
smpte.frames.setValueRaw(-1);
tx -= Time(FSecs(2,25));
CHECK (tx == smpte.getTime());
CHECK (" 1:00:00:-1"== string(smpte));
smpte.invertOrientation(); // invoking on positive should create double negated representation
CHECK ("--1:00:00:01"== string(smpte)); // and here especially also causes a series of overflows
CHECK (tx == smpte.getTime()); // but without affecting the overall value
}
void
checkDropFrame ()
{
UNIMPLEMENTED ("verify especially SMPTE-drop-frame timecode");
}
void
checkCopyAssignments ()
{
UNIMPLEMENTED ("verify Timecode values can be copied and assigned properly");
}
};
/** Register this test class... */
LAUNCHER (TimeFormats_test, "unit common");
}}} // namespace lib::time::test