r793: Small API addon, so plugins can 'see' camera and projector automation
[cinelerra_cv/mob.git] / cinelerra / virtualvnode.C
blob4b61918720a41d7c05c13e51f2be51ca3973a4eb
1 #include "asset.h"
2 #include "automation.h"
3 #include "bcsignals.h"
4 #include "clip.h"
5 #include "edit.h"
6 #include "edits.h"
7 #include "edl.h"
8 #include "edlsession.h"
9 #include "fadeengine.h"
10 #include "floatauto.h"
11 #include "floatautos.h"
12 #include "intauto.h"
13 #include "intautos.h"
14 #include "maskengine.h"
15 #include "mwindow.h"
16 #include "module.h"
17 #include "overlayframe.h"
18 #include "playabletracks.h"
19 #include "plugin.h"
20 #include "preferences.h"
21 #include "renderengine.h"
22 #include "transition.h"
23 #include "transportque.h"
24 #include "vattachmentpoint.h"
25 #include "vedit.h"
26 #include "vframe.h"
27 #include "virtualvconsole.h"
28 #include "virtualvnode.h"
29 #include "vmodule.h"
30 #include "vrender.h"
31 #include "vtrack.h"
33 #include <string.h>
36 VirtualVNode::VirtualVNode(RenderEngine *renderengine, 
37                 VirtualConsole *vconsole, 
38                 Module *real_module, 
39                 Plugin *real_plugin,
40                 Track *track, 
41                 VirtualNode *parent_node)
42  : VirtualNode(renderengine, 
43                 vconsole, 
44                 real_module, 
45                 real_plugin,
46                 track, 
47                 parent_node)
49         VRender *vrender = ((VirtualVConsole*)vconsole)->vrender;
50         fader = new FadeEngine(renderengine->preferences->processors);
53 VirtualVNode::~VirtualVNode()
55         delete fader;
58 VirtualNode* VirtualVNode::create_module(Plugin *real_plugin, 
59                                                         Module *real_module, 
60                                                         Track *track)
62         return new VirtualVNode(renderengine, 
63                 vconsole, 
64                 real_module,
65                 0,
66                 track,
67                 this);
71 VirtualNode* VirtualVNode::create_plugin(Plugin *real_plugin)
73         return new VirtualVNode(renderengine, 
74                 vconsole, 
75                 0,
76                 real_plugin,
77                 track,
78                 this);
81 int VirtualVNode::read_data(VFrame *output_temp,
82         int64_t start_position,
83         double frame_rate)
85         VirtualNode *previous_plugin = 0;
86 SET_TRACE
88         if(!output_temp) printf("VirtualVNode::read_data output_temp=%p\n", output_temp);
89 SET_TRACE
91         if(vconsole->debug_tree) 
92                 printf("  VirtualVNode::read_data position=%lld rate=%f title=%s\n", 
93                         start_position,
94                         frame_rate,
95                         track->title);
97 // This is a plugin on parent module with a preceeding effect.
98 // Get data from preceeding effect on parent module.
99         if(parent_node && (previous_plugin = parent_node->get_previous_plugin(this)))
100         {
101                 return ((VirtualVNode*)previous_plugin)->render(output_temp,
102                         start_position,
103                         frame_rate);
104         }
105         else
106 // First plugin on parent module.
107 // Read data from parent module
108         if(parent_node)
109         {
110                 return ((VirtualVNode*)parent_node)->read_data(output_temp,
111                         start_position,
112                         frame_rate);
113         }
114         else
115         {
116 // This is the first node in the tree
117                 return ((VModule*)real_module)->render(output_temp,
118                         start_position,
119                         renderengine->command->get_direction(),
120                         frame_rate,
121                         0,
122                         vconsole->debug_tree);
123         }
124 SET_TRACE
126         return 0;
130 int VirtualVNode::render(VFrame *output_temp, 
131         int64_t start_position,
132         double frame_rate)
134         VRender *vrender = ((VirtualVConsole*)vconsole)->vrender;
135         if(real_module)
136         {
137 SET_TRACE
138                 render_as_module(vrender->video_out, 
139                         output_temp,
140                         start_position,
141                         frame_rate);
142 SET_TRACE
143         }
144         else
145         if(real_plugin)
146         {
147                 render_as_plugin(output_temp,
148                         start_position,
149                         frame_rate);
150         }
151         return 0;
154 void VirtualVNode::render_as_plugin(VFrame *output_temp, 
155         int64_t start_position,
156         double frame_rate)
158         if(!attachment ||
159                 !real_plugin ||
160                 !real_plugin->on) return;
163         if(vconsole->debug_tree) 
164                 printf("  VirtualVNode::render_as_plugin title=%s\n", track->title);
166         ((VAttachmentPoint*)attachment)->render(
167                 output_temp,
168                 plugin_buffer_number,
169                 start_position,
170                 frame_rate,
171                 vconsole->debug_tree);
175 int VirtualVNode::render_as_module(VFrame **video_out, 
176         VFrame *output_temp,
177         int64_t start_position,
178         double frame_rate)
181         int direction = renderengine->command->get_direction();
182         double edl_rate = renderengine->edl->session->frame_rate;
184         if(vconsole->debug_tree) 
185                 printf("  VirtualVNode::render_as_module title=%s\n", track->title);
186 SET_TRACE
188 // Process last subnode.  This propogates up the chain of subnodes and finishes
189 // the chain.
190         if(subnodes.total)
191         {
192                 VirtualVNode *node = (VirtualVNode*)subnodes.values[subnodes.total - 1];
193                 node->render(output_temp,
194                         start_position,
195                         frame_rate);
196         }
197         else
198 // Read data from previous entity
199         {
200                 read_data(output_temp,
201                         start_position,
202                         frame_rate);
203         }
204 SET_TRACE
206         render_fade(output_temp,
207                                 start_position,
208                                 frame_rate,
209                                 track->automation->autos[AUTOMATION_FADE],
210                                 direction);
211 SET_TRACE
213 // Apply mask to output
214         ((VModule *)real_module)->masker->do_mask(output_temp, 
215                 start_position,
216                 frame_rate,
217                 edl_rate,
218                 (MaskAutos*)track->automation->autos[AUTOMATION_MASK], 
219                 direction,
220                 0);      // we are not before plugins
221 SET_TRACE
224 // overlay on the final output
225 // Get mute status
226         int mute_constant;
227         int mute_fragment = 1;
228         int64_t mute_position = 0;
231 // Is frame muted?
232         get_mute_fragment(start_position,
233                         mute_constant, 
234                         mute_fragment, 
235                         (Autos*)((VTrack*)track)->automation->autos[AUTOMATION_MUTE],
236                         direction,
237                         0);
238 SET_TRACE
240         if(!mute_constant)
241         {
242 // Fragment is playable
243                 render_projector(output_temp,
244                         video_out,
245                         start_position,
246                         frame_rate);
247         }
248 SET_TRACE
250         Edit *edit = 0;
251         if(renderengine->show_tc)
252                 renderengine->vrender->insert_timecode(edit,
253                         start_position,
254                         output_temp);
256         return 0;
259 int VirtualVNode::render_fade(VFrame *output,        
260 // start of input fragment in project if forward / end of input fragment if reverse
261 // relative to requested frame rate
262                         int64_t start_position, 
263                         double frame_rate, 
264                         Autos *autos,
265                         int direction)
267         double slope, intercept;
268         int64_t slope_len = 1;
269         FloatAuto *previous = 0;
270         FloatAuto *next = 0;
271         double edl_rate = renderengine->edl->session->frame_rate;
272         int64_t start_position_project = (int64_t)(start_position * 
273                 edl_rate /
274                 frame_rate);
276         if(vconsole->debug_tree) 
277                 printf("  VirtualVNode::render_fade title=%s\n", track->title);
279         intercept = ((FloatAutos*)autos)->get_value(start_position_project, 
280                 direction,
281                 previous,
282                 next);
285 //      CLAMP(intercept, 0, 100);
288 // Can't use overlay here because overlayer blends the frame with itself.
289 // The fade engine can compensate for lack of alpha channels by reducing the 
290 // color components.
291         if(!EQUIV(intercept / 100, 1))
292         {
293                 fader->do_fade(output, output, intercept / 100);
294         }
296         return 0;
299 // Start of input fragment in project if forward.  End of input fragment if reverse.
300 int VirtualVNode::render_projector(VFrame *input,
301                         VFrame **output,
302                         int64_t start_position,
303                         double frame_rate)
305         float in_x1, in_y1, in_x2, in_y2;
306         float out_x1, out_y1, out_x2, out_y2;
307         double edl_rate = renderengine->edl->session->frame_rate;
308         int64_t start_position_project = (int64_t)(start_position * 
309                 edl_rate /
310                 frame_rate);
311         VRender *vrender = ((VirtualVConsole*)vconsole)->vrender;
312         if(vconsole->debug_tree) 
313                 printf("  VirtualVNode::render_projector title=%s\n", track->title);
315         for(int i = 0; i < MAX_CHANNELS; i++)
316         {
317                 if(output[i])
318                 {
319                         ((VTrack*)track)->calculate_output_transfer(i,
320                                 start_position_project,
321                                 renderengine->command->get_direction(),
322                                 in_x1, 
323                                 in_y1, 
324                                 in_x2, 
325                                 in_y2,
326                                 out_x1, 
327                                 out_y1, 
328                                 out_x2, 
329                                 out_y2);
331                         in_x2 += in_x1;
332                         in_y2 += in_y1;
333                         out_x2 += out_x1;
334                         out_y2 += out_y1;
336 //for(int j = 0; j < input->get_w() * 3 * 5; j++)
337 //      input->get_rows()[0][j] = 255;
338 // 
339                         if(out_x2 > out_x1 && 
340                                 out_y2 > out_y1 && 
341                                 in_x2 > in_x1 && 
342                                 in_y2 > in_y1)
343                         {
344                                 int direction = renderengine->command->get_direction();
345                                 IntAuto *mode_keyframe = 0;
346                                 mode_keyframe = 
347                                         (IntAuto*)track->automation->autos[AUTOMATION_MODE]->get_prev_auto(
348                                                 start_position_project, 
349                                                 direction,
350                                                 (Auto* &)mode_keyframe);
352                                 int mode = mode_keyframe->value;
354 // Fade is performed in render_fade so as to allow this module
355 // to be chained in another module, thus only 4 component colormodels
356 // can do dissolves, although a blend equation is still required for 3 component
357 // colormodels since fractional translation requires blending.
359 // If this is the only playable video track and the mode_keyframe is "normal"
360 // the mode keyframe may be overridden with "replace".  Replace is faster.
361                                 if(mode == TRANSFER_NORMAL &&
362                                         vconsole->total_entry_nodes == 1)
363                                         mode = TRANSFER_REPLACE;
366                                 vrender->overlayer->overlay(output[i], 
367                                         input,
368                                         in_x1, 
369                                         in_y1, 
370                                         in_x2, 
371                                         in_y2,
372                                         out_x1, 
373                                         out_y1, 
374                                         out_x2, 
375                                         out_y2, 
376                                         1,
377                                         mode, 
378                                         renderengine->edl->session->interpolation_type);
379                         }
380 // for(int j = 0; j < output[i]->get_w() * 3 * 5; j++)
381 //      output[i]->get_rows()[0][j] = 255;
382                 }
383         }
384         return 0;