r665: Merged the official release 2.0.
[cinelerra_cv.git] / cinelerra / virtualvnode.C
blob8007475a3f8611add6fe9bf7b62b75b23eb12b52
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);
51         masker = new MaskEngine(renderengine->preferences->processors);
54 VirtualVNode::~VirtualVNode()
56         delete fader;
57         delete masker;
60 VirtualNode* VirtualVNode::create_module(Plugin *real_plugin, 
61                                                         Module *real_module, 
62                                                         Track *track)
64         return new VirtualVNode(renderengine, 
65                 vconsole, 
66                 real_module,
67                 0,
68                 track,
69                 this);
73 VirtualNode* VirtualVNode::create_plugin(Plugin *real_plugin)
75         return new VirtualVNode(renderengine, 
76                 vconsole, 
77                 0,
78                 real_plugin,
79                 track,
80                 this);
83 int VirtualVNode::read_data(VFrame *output_temp,
84         int64_t start_position,
85         double frame_rate)
87         VirtualNode *previous_plugin = 0;
88 SET_TRACE
90         if(!output_temp) printf("VirtualVNode::read_data output_temp=%p\n", output_temp);
91 SET_TRACE
93         if(vconsole->debug_tree) 
94                 printf("  VirtualVNode::read_data position=%lld rate=%f title=%s\n", 
95                         start_position,
96                         frame_rate,
97                         track->title);
99 // This is a plugin on parent module with a preceeding effect.
100 // Get data from preceeding effect on parent module.
101         if(parent_node && (previous_plugin = parent_node->get_previous_plugin(this)))
102         {
103                 return ((VirtualVNode*)previous_plugin)->render(output_temp,
104                         start_position,
105                         frame_rate);
106         }
107         else
108 // First plugin on parent module.
109 // Read data from parent module
110         if(parent_node)
111         {
112                 return ((VirtualVNode*)parent_node)->read_data(output_temp,
113                         start_position,
114                         frame_rate);
115         }
116         else
117         {
118 // This is the first node in the tree
119                 return ((VModule*)real_module)->render(output_temp,
120                         start_position,
121                         renderengine->command->get_direction(),
122                         frame_rate,
123                         0,
124                         vconsole->debug_tree);
125         }
126 SET_TRACE
128         return 0;
132 int VirtualVNode::render(VFrame *output_temp, 
133         int64_t start_position,
134         double frame_rate)
136         VRender *vrender = ((VirtualVConsole*)vconsole)->vrender;
137         if(real_module)
138         {
139 SET_TRACE
140                 render_as_module(vrender->video_out, 
141                         output_temp,
142                         start_position,
143                         frame_rate);
144 SET_TRACE
145         }
146         else
147         if(real_plugin)
148         {
149                 render_as_plugin(output_temp,
150                         start_position,
151                         frame_rate);
152         }
153         return 0;
156 void VirtualVNode::render_as_plugin(VFrame *output_temp, 
157         int64_t start_position,
158         double frame_rate)
160         if(!attachment ||
161                 !real_plugin ||
162                 !real_plugin->on) return;
165         if(vconsole->debug_tree) 
166                 printf("  VirtualVNode::render_as_plugin title=%s\n", track->title);
168         ((VAttachmentPoint*)attachment)->render(
169                 output_temp,
170                 plugin_buffer_number,
171                 start_position,
172                 frame_rate,
173                 vconsole->debug_tree);
177 int VirtualVNode::render_as_module(VFrame **video_out, 
178         VFrame *output_temp,
179         int64_t start_position,
180         double frame_rate)
183         int direction = renderengine->command->get_direction();
184         double edl_rate = renderengine->edl->session->frame_rate;
186         if(vconsole->debug_tree) 
187                 printf("  VirtualVNode::render_as_module title=%s\n", track->title);
188 SET_TRACE
190 // Process last subnode.  This propogates up the chain of subnodes and finishes
191 // the chain.
192         if(subnodes.total)
193         {
194                 VirtualVNode *node = (VirtualVNode*)subnodes.values[subnodes.total - 1];
195                 node->render(output_temp,
196                         start_position,
197                         frame_rate);
198         }
199         else
200 // Read data from previous entity
201         {
202                 read_data(output_temp,
203                         start_position,
204                         frame_rate);
205         }
206 SET_TRACE
208         render_fade(output_temp,
209                                 start_position,
210                                 frame_rate,
211                                 track->automation->autos[AUTOMATION_FADE],
212                                 direction);
213 SET_TRACE
215 // Apply mask to output
216         masker->do_mask(output_temp, 
217                 start_position,
218                 frame_rate,
219                 edl_rate,
220                 (MaskAutos*)track->automation->autos[AUTOMATION_MASK], 
221                 direction);
222 SET_TRACE
225 // overlay on the final output
226 // Get mute status
227         int mute_constant;
228         int mute_fragment = 1;
229         int64_t mute_position = 0;
232 // Is frame muted?
233         get_mute_fragment(start_position,
234                         mute_constant, 
235                         mute_fragment, 
236                         (Autos*)((VTrack*)track)->automation->autos[AUTOMATION_MUTE],
237                         direction,
238                         0);
239 SET_TRACE
241         if(!mute_constant)
242         {
243 // Fragment is playable
244                 render_projector(output_temp,
245                         video_out,
246                         start_position,
247                         frame_rate);
248         }
249 SET_TRACE
251         Edit *edit = 0;
252         if(renderengine->show_tc)
253                 renderengine->vrender->insert_timecode(edit,
254                         start_position,
255                         output_temp);
257         return 0;
260 int VirtualVNode::render_fade(VFrame *output,        
261 // start of input fragment in project if forward / end of input fragment if reverse
262 // relative to requested frame rate
263                         int64_t start_position, 
264                         double frame_rate, 
265                         Autos *autos,
266                         int direction)
268         double slope, intercept;
269         int64_t slope_len = 1;
270         FloatAuto *previous = 0;
271         FloatAuto *next = 0;
272         double edl_rate = renderengine->edl->session->frame_rate;
273         int64_t start_position_project = (int64_t)(start_position * 
274                 edl_rate /
275                 frame_rate);
277         if(vconsole->debug_tree) 
278                 printf("  VirtualVNode::render_fade title=%s\n", track->title);
280         intercept = ((FloatAutos*)autos)->get_value(start_position_project, 
281                 direction,
282                 previous,
283                 next);
286 //      CLAMP(intercept, 0, 100);
289 // Can't use overlay here because overlayer blends the frame with itself.
290 // The fade engine can compensate for lack of alpha channels by reducing the 
291 // color components.
292         if(!EQUIV(intercept / 100, 1))
293         {
294                 fader->do_fade(output, output, intercept / 100);
295         }
297         return 0;
300 // Start of input fragment in project if forward.  End of input fragment if reverse.
301 int VirtualVNode::render_projector(VFrame *input,
302                         VFrame **output,
303                         int64_t start_position,
304                         double frame_rate)
306         float in_x1, in_y1, in_x2, in_y2;
307         float out_x1, out_y1, out_x2, out_y2;
308         double edl_rate = renderengine->edl->session->frame_rate;
309         int64_t start_position_project = (int64_t)(start_position * 
310                 edl_rate /
311                 frame_rate);
312         VRender *vrender = ((VirtualVConsole*)vconsole)->vrender;
313         if(vconsole->debug_tree) 
314                 printf("  VirtualVNode::render_projector title=%s\n", track->title);
316         for(int i = 0; i < MAX_CHANNELS; i++)
317         {
318                 if(output[i])
319                 {
320                         ((VTrack*)track)->calculate_output_transfer(i,
321                                 start_position_project,
322                                 renderengine->command->get_direction(),
323                                 in_x1, 
324                                 in_y1, 
325                                 in_x2, 
326                                 in_y2,
327                                 out_x1, 
328                                 out_y1, 
329                                 out_x2, 
330                                 out_y2);
332                         in_x2 += in_x1;
333                         in_y2 += in_y1;
334                         out_x2 += out_x1;
335                         out_y2 += out_y1;
337 //for(int j = 0; j < input->get_w() * 3 * 5; j++)
338 //      input->get_rows()[0][j] = 255;
339 // 
340                         if(out_x2 > out_x1 && 
341                                 out_y2 > out_y1 && 
342                                 in_x2 > in_x1 && 
343                                 in_y2 > in_y1)
344                         {
345                                 int direction = renderengine->command->get_direction();
346                                 IntAuto *mode_keyframe = 0;
347                                 mode_keyframe = 
348                                         (IntAuto*)track->automation->autos[AUTOMATION_MODE]->get_prev_auto(
349                                                 start_position_project, 
350                                                 direction,
351                                                 (Auto* &)mode_keyframe);
353                                 int mode = mode_keyframe->value;
355 // Fade is performed in render_fade so as to allow this module
356 // to be chained in another module, thus only 4 component colormodels
357 // can do dissolves, although a blend equation is still required for 3 component
358 // colormodels since fractional translation requires blending.
360 // If this is the only playable video track and the mode_keyframe is "normal"
361 // the mode keyframe may be overridden with "replace".  Replace is faster.
362                                 if(mode == TRANSFER_NORMAL &&
363                                         vconsole->total_entry_nodes == 1)
364                                         mode = TRANSFER_REPLACE;
367                                 vrender->overlayer->overlay(output[i], 
368                                         input,
369                                         in_x1, 
370                                         in_y1, 
371                                         in_x2, 
372                                         in_y2,
373                                         out_x1, 
374                                         out_y1, 
375                                         out_x2, 
376                                         out_y2, 
377                                         1,
378                                         mode, 
379                                         renderengine->edl->session->interpolation_type);
380                         }
381 // for(int j = 0; j < output[i]->get_w() * 3 * 5; j++)
382 //      output[i]->get_rows()[0][j] = 255;
383                 }
384         }
385         return 0;