4 // A Scene is an equivalent of an EffectChain, but each part is not a single
5 // Effect. (The name itself does not carry any specific meaning above that
6 // of what an EffectChain is; it was just chosen as a more intuitive name than
7 // an EffectChain when we had to change anyway.) Instead, it is a “block”,
8 // which can hold one or more effect alternatives, e.g., one block could hold
9 // ResizeEffect or IdentityEffect (effectively doing nothing), or many
10 // different input types. On finalization, every different combination of
11 // block alternatives are tried, and one EffectChain is generated for each.
12 // This also goes for whether the scene is destined for preview outputs
13 // (directly to screen, RGBA) or live (Y'CbCr output).
24 struct EffectBlueprint;
28 class LiveInputWrapper;
39 // Index into the parent Scene's list of blocks.
43 // Each instantiation is indexed by the chosen alternative for each block.
44 // These are combined into one big variable-base number, ranging from 0
45 // to (B_0*B_1*B_2*...*B_n)-1, where B_i is the number of alternatives for
46 // block number i and n is the index of the last block.
48 // The actual index, given alternatives A_0, A_1, A_2, ..., is given as
50 // A_0 + B_0 * (A_1 + B_1 * (A_2 + B_2 * (...)))
52 // where each A_i can of course range from 0 to B_i-1. In other words,
53 // the first block gets the lowest “bits” (or trits, or quats...) of the
54 // index number, the second block gets the ones immediately above,
55 // and so on. Thus, there are no holes in the sequence.
57 // Expanding the formula above gives the equivalent index
59 // A_0 + A_1 * B_0 + A_2 * B_0 * B_1 + A_3 * ...
63 // A_0 * C_0 + A_1 * C_1 + A_2 * C_2 + A_3 * ...
65 // where C_0 = 0 and C_(i+1) = C_i * B_i. In other words, C_i is
66 // the product of the cardinalities of each previous effect; if we
67 // are e.g. at the third index and there have been C_2 = 3 * 5 = 15
68 // different alternatives for constructing the scene so far
69 // (with possible indexes 0..14), it is only logical that if we
70 // want three new options (B_2 = 3), we must add 0, 15 or 30 to
71 // the index. (Then the local possible indexes become 0..44 and
72 // C_3 = 45, of course.) Given an index number k, we can then get our
73 // own local “bits” of the index, giving the alternative for this
74 // block, by doing (k / 15) % 3.
76 // This specific member contains the value of C_i for this block.
77 // (B_i is alternatives.size().) Not set before finalize() has run.
78 size_t cardinality_base = 0;
80 // Find the chosen alternative for this block in a given instance.
81 int chosen_alternative(size_t chain_idx) const {
82 if (chain_idx == size_t(-1)) {
83 return currently_chosen_alternative;
85 return (chain_idx / cardinality_base) % alternatives.size();
89 std::vector<EffectBlueprint *> alternatives; // Must all have the same amount of inputs. Pointers to make things easier for Lua.
90 std::vector<Index> inputs; // One for each input of alternatives[0] (ie., typically 0 or 1, occasionally 2).
91 std::vector<Index> disablers; // If any of these are disabled (IdentityEffect chosen), so should this one.
92 int currently_chosen_alternative = 0;
93 // What alternative to use if the block is disabled.
94 // Points to an alternative with IDENTITY_EFFECT if it exists
95 // (to disable as much as possible), otherwise 0.
96 int canonical_alternative = 0;
97 bool is_input = false;
99 // For LIVE_INPUT* only. We can't just always populate signal_to_connect,
100 // since when we set this, CEF and video signals may not have numbers yet.
101 // FIXME: Perhaps it would be simpler if they just did?
102 enum { CONNECT_NONE, CONNECT_SIGNAL, CONNECT_CEF, CONNECT_VIDEO } signal_type_to_connect = CONNECT_NONE;
103 int signal_to_connect = 0; // For CONNECT_SIGNAL.
105 CEFCapture *cef_to_connect = nullptr; // For CONNECT_CEF.
107 FFmpegCapture *video_to_connect = nullptr; // For CONNECT_VIDEO.
109 std::string pathname; // For IMAGE_INPUT only.
111 // Parameters to set on the effect prior to render.
112 // Will be set _before_ the ones from the EffectBlueprint, so that
113 // the latter takes priority.
114 std::map<std::string, int> int_parameters;
115 std::map<std::string, float> float_parameters;
116 std::map<std::string, std::array<float, 3>> vec3_parameters;
117 std::map<std::string, std::array<float, 4>> vec4_parameters;
119 std::string declaration_point; // For error messages.
122 int Block_display(lua_State* L);
123 int Block_choose(lua_State* L);
124 int Block_enable(lua_State *L);
125 int Block_enable_if(lua_State *L);
126 int Block_disable(lua_State *L);
127 int Block_always_disable_if_disabled(lua_State *L);
128 int Block_set_int(lua_State *L);
129 int Block_set_float(lua_State *L);
130 int Block_set_vec3(lua_State *L);
131 int Block_set_vec4(lua_State *L);
135 std::vector<Block *> blocks; // The last one represents the output node (after finalization). Pointers to make things easier for Lua.
136 struct Instantiation {
137 std::unique_ptr<movit::EffectChain> chain;
138 std::map<Block::Index, movit::Effect *> effects; // So that we can set parameters.
139 std::map<Block::Index, LiveInputWrapper *> inputs; // So that we can connect signals.
140 std::map<Block::Index, ImageInput *> image_inputs; // So that we can connect signals.
142 std::vector<Instantiation> chains; // Indexed by combination of each block's chosen alternative. See Block for information.
145 float aspect_nom, aspect_denom;
146 movit::ResourcePool *resource_pool;
148 movit::Effect *instantiate_effects(const Block *block, size_t chain_idx, Instantiation *instantiation);
149 size_t compute_chain_number_for_block(size_t block_idx, const std::bitset<256> &disabled) const;
150 static void find_inputs_for_block(lua_State *L, Scene *scene, Block *block);
152 // Find out which blocks (indexed by position in the “blocks” array),
153 // if any, are disabled in a given instantiation. A disabled block is
154 // one that will not be instantiated at all, because it is a secondary
155 // (ie., not the first) input of some multi-input effect that was replaced
156 // with IdentityEffect in the given instantiation.
158 // Set chain_idx to size_t(-1) to use whatever is in each block's
159 // currently_chosen_alternative.
160 std::bitset<256> find_disabled_blocks(size_t chain_idx) const;
161 void find_disabled_blocks(size_t chain_idx, size_t block_idx, bool currently_disabled, std::bitset<256> *disabled) const;
163 // If a block is disabled, it should always have canonical_alternative chosen,
164 // so that we don't instantiate a bunch of irrelevant duplicates that
165 // differ only in disabled blocks. You can check this property with
166 // is_noncanonical_chain() and then avoid instantiating the ones where
168 bool is_noncanonical_chain(size_t chain_idx) const;
171 Scene(Theme *theme, float aspect_nom, float aspect_denom);
172 size_t compute_chain_number(bool is_main_chain) const;
174 std::pair<movit::EffectChain *, std::function<void()>>
175 get_chain(Theme *theme, lua_State *L, unsigned num, const InputState &input_state);
177 static int add_input(lua_State *L);
178 static int add_effect(lua_State *L);
179 static int add_optional_effect(lua_State *L);
180 static int finalize(lua_State *L);
183 #endif // !defined(_SCENE_H)