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