This allows us to get rid of effects that don't actually do anything
(like all the normalizers in the common case); in Movit, they tend
to burn a lot of memory bandwidth. We solve this by a new OptionalEffect
template, that can rewrite itself out of the graph if it sees it is
a no-op. We need to recreate the chain from scratch if this status
should change (e.g. the input resolution changed from one frame to the
next, and we thus suddenly need resizing after all), so we keep a
"fingerprint" string that contains all the unique IDs of the services
in use, as well as their disabled status, and compare against this frame.
Building the chain in one piece also opens up for transitions to be more
efficient; they are now built as part of one big Movit chain, instead of
bouncing to an 8-bit sRGB buffer and back.
* Change the mlt_glsl type.
Now, the mlt_glsl image type has a defined value, which is the
mlt_service pointer. Each filter is responsible for storing this input
service. This, together with the mlt_frame, enables us to actually
build the Movit chain based on the MLT relations, instead of just relying in
the order in which they are called and assuming everything has a single input.
As a special case, the value (mlt_service) -1 (which should never be a valid
pointer) means that we read the information from an input rather than an
effect. In this case, we take a copy of the pixel data we get in (since it
will soon be garbage collected), store it in an MltInput and then store that
MltInput for later use. This could probably be further simplified in the
future to get completely rid of MltInput and just use the regular
FlatInput/YCbCrInput instead.
This also requires us to change so that the chain is built and finalized at
the _end_ of the conversion steps (where it's logically needed), instead of at
the beginning as before. The beginning (conversion from * -> mlt_glsl) now
only stores the input as described below.
* Change Effect and EffectChain storage.
This changes the storage of Movit stuff as follows:
- The EffectChain (along with some associated information to be able
to more easily locate the services and Effect pointers; together,
called a GlslChain) is now stored on the output service, not on the input
producer. This allows us to have multiple EffectChains floating around.
- The Effect pointers no longer live permanently on the MLT graph, since
each MLT service can have more than one Effect. Instead, they live
temporarily on the frame (because the frame is not shared between
threads, giving us a poor man's version of thread-local storage),
until they reach the point where we decide if we need to rebuild the
EffectChain or not. At this point, they are either made part of the
chain (and owned by it), or disposed as unneeded.
- The MltInput also lives on the frame. (If we have multiple inputs,
we also have multiple frames.) As mentioned above, its use is signaled by
an mlt_service of -1.
* Change how Movit parameter setting works.
Services no longer set parameters directly on the Movit filters, since
they cannot know before the graph construction time whether the correct
destination is the newly created Effect, or a similar one in the EffectChain.
Instead, they set special properties (movit.parms.<type>.<name>[<index>]),
and then the convert filter uses these to set Movit parameters on the right
Effects.