some musing about timing constraints and quantisation
This commit is contained in:
parent
a4e3383367
commit
2cb254365c
8 changed files with 123 additions and 9 deletions
|
|
@ -317,7 +317,7 @@ namespace time {
|
|||
typedef Digxel< int, digxel::SexaFormatter> SexaDigit; ///< for displaying time components (sexagesimal)
|
||||
typedef Digxel<uint, digxel::HexaFormatter> HexaDigit; ///< for displaying a hex byte
|
||||
typedef Digxel< int, digxel::HourFormatter> HourDigit; ///< for displaying hours in H:M.S
|
||||
typedef Digxel<long, digxel::CountFormatter> CountVal; ///< for displaying a counter
|
||||
typedef Digxel<long, digxel::CountFormatter> CountVal; ///< for displaying a counter ///////////TICKET #882 : outch!
|
||||
|
||||
|
||||
/** special Digxel to show a sign.
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ namespace time {
|
|||
FrameNr (QuTime const& quantisedTime);
|
||||
|
||||
using TCode::operator string;
|
||||
// CountVal implicitly convertible to long
|
||||
// CountVal implicitly convertible to long ///////////TICKET #882 : outch! should be a 64bit type!
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ namespace play {
|
|||
*
|
||||
* Invoking this function investigates the given exit nodes of the
|
||||
* render nodes network and retrieves actual output destinations
|
||||
* through the given OutputManager. The goal is to configure an
|
||||
* through the given OutputManager. The goal is to configure a
|
||||
* PlayProcess, based on the renderengine and the collection of
|
||||
* OutputSlot instances retrieved for each of the given exit nodes.
|
||||
* Running this PlayProcess will activate the render engine to deliver
|
||||
|
|
|
|||
|
|
@ -39,6 +39,10 @@ PLANNED "Engine calculation streams" CalcStream_test <<END
|
|||
END
|
||||
|
||||
|
||||
PLANNED "Frame Dispatcher Interface" DispatcherInterface_test <<END
|
||||
END
|
||||
|
||||
|
||||
PLANNED "Proc Node basics" NodeBasic_test <<END
|
||||
END
|
||||
|
||||
|
|
|
|||
|
|
@ -10,3 +10,8 @@ END
|
|||
TEST "Output Slot Protocol" OutputSlotProtocol_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
PLANNED "Timing constraints" TimingConstraints_test <<END
|
||||
return: 0
|
||||
END
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@
|
|||
|
||||
//#include "proc/engine/procnode.hpp"
|
||||
#include "proc/engine/dispatcher.hpp"
|
||||
#include "proc/play/timings.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
#include "lib/time/timequant.hpp"
|
||||
#include "lib/singleton.hpp"
|
||||
|
||||
//#include <boost/scoped_ptr.hpp>
|
||||
//#include <iostream>
|
||||
|
|
@ -38,7 +42,11 @@ using test::Test;
|
|||
namespace proc {
|
||||
namespace engine{
|
||||
namespace test {
|
||||
|
||||
|
||||
using lib::time::QuTime;
|
||||
using lib::time::FrameRate;
|
||||
using proc::play::Timings;
|
||||
|
||||
namespace { // used internally
|
||||
|
||||
|
||||
|
|
@ -49,6 +57,8 @@ namespace test {
|
|||
public:
|
||||
};
|
||||
|
||||
lib::Singleton<MockDispatcherTable> mockDispatcher;
|
||||
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #880
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #890
|
||||
|
||||
|
|
@ -81,9 +91,13 @@ namespace test {
|
|||
void
|
||||
verify_basicDispatch()
|
||||
{
|
||||
|
||||
Dispatcher& dispatcher = mockDispatcher();
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #880
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #890
|
||||
Timings timings (FrameRate::PAL);
|
||||
uint startFrame(10);
|
||||
|
||||
TimeAnchor refPoint = TimeAnchor::build (timings, startFrame);
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #880
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -96,7 +110,7 @@ namespace test {
|
|||
{
|
||||
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #880
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #890
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #880
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
77
tests/components/proc/play/timing-constraints-test.cpp
Normal file
77
tests/components/proc/play/timing-constraints-test.cpp
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
TimingConstraints(Test) - verify timing constraint specifications
|
||||
|
||||
Copyright (C) Lumiera.org
|
||||
2012, 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 "proc/play/timings.hpp"
|
||||
//#include "proc/engine/buffhandle.hpp"
|
||||
//#include "proc/engine/testframe.hpp"
|
||||
//#include "lib/time/control.hpp"
|
||||
|
||||
|
||||
|
||||
namespace proc {
|
||||
namespace play {
|
||||
namespace test {
|
||||
|
||||
namespace time = lib::time;
|
||||
|
||||
//using proc::engine::BuffHandle;
|
||||
//using proc::engine::test::testData;
|
||||
//using proc::engine::test::TestFrame;
|
||||
|
||||
//using lumiera::Play;
|
||||
|
||||
//typedef time::Control<time::Duration> DurationControl;
|
||||
//
|
||||
//typedef DummyPlayConnection<PlayTestFrames_Strategy> DummyPlayer;
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* @test document and verify the definition and combining of
|
||||
* timing constraints for playback and rendering.
|
||||
*/
|
||||
class TimingConstraints_test : public Test
|
||||
{
|
||||
virtual void
|
||||
run (Arg)
|
||||
{
|
||||
define_basicTimingConstraints();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
define_basicTimingConstraints()
|
||||
{
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #831
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #831
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Register this test class... */
|
||||
LAUNCHER (TimingConstraints_test, "unit player");
|
||||
|
||||
|
||||
|
||||
}}} // namespace proc::play::test
|
||||
|
|
@ -3476,7 +3476,7 @@ Thus the mapping is a copyable value object, using an associative array. It may
|
|||
First and foremost, mapping can be seen as a //functional abstraction.// As it's used at implementation level, encapsulation of detail types in't the primary concern, so it's a candidate for generic programming: For each of those use cases outlined above, a distinct mapping type is created by instantiating the {{{OutputMapping<DEF>}}} template with a specifically tailored definition context ({{{DEF}}}), which takes on the role of a strategy. Individual instances of this concrete mapping type may be default created and copied freely. This instantiation process includes picking up the concrete result type and building a functor object for resolving on the fly. Thus, in the way typical for generic programming, the more involved special details are moved out of sight, while being still in scope for the purpose of inlining. But there //is// a concern better to be encapsulated and concealed at the usage site, namely accessing the rules system. Thus mapping leads itself to the frequently used implementation pattern where there is a generic frontend as header, calling into opaque functions embedded within a separate compilation unit.
|
||||
</pre>
|
||||
</div>
|
||||
<div title="OutputSlot" modifier="Ichthyostega" modified="201112230113" created="201106162339" tags="def Concepts Player spec img" changecount="52">
|
||||
<div title="OutputSlot" modifier="Ichthyostega" modified="201202042235" created="201106162339" tags="def Concepts Player spec img" changecount="53">
|
||||
<pre>Within the Lumiera player and output subsystem, actually sending data to an external output requires to allocate an ''output slot''
|
||||
This is the central metaphor for the organisation of actual (system level) outputs; using this concept allows to separate and abstract the data calculation and the organisation of playback and rendering from the specifics of the actual output sink. Actual output possibilities (video in GUI window, video fullscreen, sound, Jack, rendering to file) can be added and removed dynamically from various components (backend, GUI), all using the same resolution and mapping mechanisms (&rarr; OutputManagement)
|
||||
|
||||
|
|
@ -3486,7 +3486,7 @@ Each OutputSlot is an unique and distinguishable entity. It corresponds explicit
|
|||
In order to be usable as //output sink,// an output slot needs to be //allocated,// i.e. tied to and locked for a specific client. At any time, there may be only a single client using a given output slot this way. To stress this point: output slots don't provide any kind of inherent mixing capability; any adaptation, mixing, overlaying and sharing needs to be done within the nodes network producing the output data fed to the slot. (in special cases, some external output capabilities -- e.g. the Jack audio connection system -- may still provide additional mixing capabilities, but that's beyond the scope of the Lumiera application)
|
||||
|
||||
[>img[Outputslot implementation structures|uml/fig151685.png]]
|
||||
Once allocated, the output slot returns a set of concrete ''sink handles'' (one for each physical channel expecting data). The calculating process feeds its results into those handles. Size and other characteristics of the data frames are assumed to be suitable, which typically won't be verified at that level anymore (but the sink handle provides a hook for assertions). Besides that, the allocation of an output slot reveals detailed ''timing expectations''. The client is required to comply to these timings when ''emitting'' data -- he's even required to provide a //current time specification,// alongside with the data. Based on this information, the output slot has the ability to handle timing failures gracefully; the concrete output slot implementation is expected to provide some kind of de-click or de-flicker facility, which kicks in automatically when a timing failure is detected.
|
||||
Once allocated, the output slot returns a set of concrete ''sink handles'' (one for each physical channel expecting data). The calculating process feeds its results into those handles. Size and other characteristics of the data frames are assumed to be suitable, which typically won't be verified at that level anymore (but the sink handle provides a hook for assertions). Besides that, the allocation of an output slot reveals detailed ''timing expectations''. The client is required to comply to these [[timings|Timings]] when ''emitting'' data -- he's even required to provide a //current time specification,// alongside with the data. Based on this information, the output slot has the ability to handle timing failures gracefully; the concrete output slot implementation is expected to provide some kind of de-click or de-flicker facility, which kicks in automatically when a timing failure is detected.
|
||||
|
||||
!!!usage and implementation
|
||||
Clients retrieve just a reference to an output slot by asking a suitable OutputManager for an output possibility supporting a specific format. Usually, they just "claim" this slot by invoking {{{allocate()}}}, which behind the scenes causes building of the actual output connections and mechanisms. For each such connection -- corresponding to a single channel within the media format handled by this ~OutputSlot -- the client gets a smart-handle {{{DataSink}}}. The concrete ~OutputSlot implementation performs operations quite specific to the kind of output and external interface in question. All tese specific handling is embodied within the concrete connection implementation used by the concrete ~OutputSlot
|
||||
|
|
@ -7466,6 +7466,20 @@ The Timeline owns a list of global [[pipes (busses)|Pipe]] which are used to col
|
|||
Actually, what the GUI creates and uses is the //view// of a given timeline. This makes no difference to start with, as the view is modelled to be a sub-concept of "timeline" and thus can stand-in. All different views of the //same// timeline also share one single play control instance, i.e. they all have one single playhead position. Doing it this way should be the default, because it's the least confusing. Anyway, it's also possible to create multiple //independent timelines// &mdash; in an extreme case even so when referring to the same top-level sequence. This configuration gives the ability to play the same arrangement in parallel with multiple independent play controllers (and thus independent playhead positions)
|
||||
|
||||
To complement this possibilities, I'd propose to give the //timeline view// the possibility to be re-linked to a sub-sequence. This way, it would stay connected to the main play control, but at the same time show a sub-sequence //in the way it will be treated as embedded// within the top-level sequence. This would be the default operation mode when a meta-clip is opened (and showed in a separate tab with such a linked timeline view). The reason for this proposed handling is again to give the user the least surprising behaviour. Because, when &mdash; on the contrary &mdash; the sub-sequence would be opened as //separate timeline,// a different absolute time position and a different signal routing may result; doing such should be reserved for advanced use, e.g. when multiple editors cooperate on a single project and a sequence has to be prepared in isolation prior to being integrated in the global sequence (featuring the whole movie).
|
||||
</pre>
|
||||
</div>
|
||||
<div title="Timings" modifier="Ichthyostega" created="201202042240" tags="spec draft Rendering Player" changecount="1">
|
||||
<pre>//Timing constraints of a render or playback process.//
|
||||
|
||||
!design quest {{red{WIP 1/2012}}}
|
||||
The Timings record is used at various places at the engine interface level. Up to now mostly as placeholder for future work.
|
||||
|
||||
* it is clear that a concrete frame grid needs to be part of the timings.
|
||||
* this defines time origin and framerate
|
||||
* additionally it's clear that the Timings record represents a //constraint// -- with the ability to specify additional constraining conditions
|
||||
* besides, it's clear that the Timings record is consulted to find out about latency
|
||||
* question: do we need a relation to wall-clock time?
|
||||
|
||||
</pre>
|
||||
</div>
|
||||
<div title="Track" modifier="Ichthyostega" modified="200911202133" created="200801062320" tags="def design decision" changecount="6">
|
||||
|
|
|
|||
Loading…
Reference in a new issue