r793: Small API addon, so plugins can 'see' camera and projector automation
[cinelerra_cv/mob.git] / cinelerra / vmodule.C
blob4b11771b1d5bc56cfb3468a2b6941d33fbd170b6
1 #include "asset.h"
2 #include "bcsignals.h"
3 #include "cache.h"
4 #include "clip.h"
5 #include "commonrender.h"
6 #include "edits.h"
7 #include "edl.h"
8 #include "edlsession.h"
9 #include "file.h"
10 #include "filexml.h"
11 #include "floatautos.h"
12 #include "mwindow.h"
13 #include "overlayframe.h"
14 #include "patch.h"
15 #include "pluginarray.h"
16 #include "preferences.h"
17 #include "renderengine.h"
18 #include "sharedlocation.h"
19 #include "transition.h"
20 #include "transportque.h"
21 #include "units.h"
22 #include "vattachmentpoint.h"
23 #include "vedit.h"
24 #include "vframe.h"
25 #include "vmodule.h"
26 #include "vrender.h"
27 #include "vplugin.h"
28 #include "vtrack.h"
29 #include <string.h>
30 #include "interlacemodes.h"
31 #include "maskengine.h"
32 #include "automation.h"
34 VModule::VModule(RenderEngine *renderengine, 
35         CommonRender *commonrender, 
36         PluginArray *plugin_array,
37         Track *track)
38  : Module(renderengine, commonrender, plugin_array, track)
40         data_type = TRACK_VIDEO;
41         overlay_temp = 0;
42         input_temp = 0;
43         transition_temp = 0;
44         if (renderengine)
45                 masker = new MaskEngine(renderengine->preferences->processors);
46         else
47                 masker = new MaskEngine(plugin_array->mwindow->preferences->processors);
48         
51 VModule::~VModule()
53         if(overlay_temp) delete overlay_temp;
54         if(input_temp) delete input_temp;
55         if(transition_temp) delete transition_temp;
56         delete masker;
60 AttachmentPoint* VModule::new_attachment(Plugin *plugin)
62         return new VAttachmentPoint(renderengine, plugin);
65 int VModule::get_buffer_size()
67         return 1;
70 CICache* VModule::get_cache()
72         if(renderengine) 
73                 return renderengine->get_vcache();
74         else
75                 return cache;
78 int VModule::import_frame(VFrame *output,
79         VEdit *current_edit,
80         int64_t input_position,
81         double frame_rate,
82         int direction)
84         int64_t corrected_position;
85         int64_t corrected_position_project;
86 // Translation of edit
87         float in_x1;
88         float in_y1;
89         float in_w1;
90         float in_h1;
91         float out_x1;
92         float out_y1;
93         float out_w1;
94         float out_h1;
95         int result = 0;
96 SET_TRACE
97         double edl_rate = get_edl()->session->frame_rate;
98         int64_t input_position_project = (int64_t)(input_position * 
99                 edl_rate / 
100                 frame_rate + 
101                 0.001);
102         if(!output) printf("VModule::import_frame 10 output=%p\n", output);
104 SET_TRACE
105         corrected_position = input_position;
106         corrected_position_project = input_position_project;
107         if(direction == PLAY_REVERSE)
108         {
109                 corrected_position--;
110                 input_position_project--;
111         }
113 // Load frame into output
114         if(current_edit &&
115                 current_edit->asset)
116         {
117                 get_cache()->age();
118 SET_TRACE
119                 File *source = get_cache()->check_out(current_edit->asset);
120 SET_TRACE
121 //              get_cache()->dump();
123                 if(source)
124                 {
125                         int64_t edit_startproject = (int64_t)(current_edit->startproject * 
126                                 frame_rate / 
127                                 edl_rate);
128                         int64_t edit_startsource = (int64_t)(current_edit->startsource *
129                                 frame_rate /
130                                 edl_rate);
131                         uint64_t position = corrected_position - 
132                                 edit_startproject + 
133                                 edit_startsource;
134                         // if we hit the end of stream, freeze at last frame
135                         uint64_t max_position = source->get_video_length(frame_rate) - 1;
136                         if (position > max_position) position = max_position;
137                         source->set_video_position(position,
138                                 frame_rate);
139                         source->set_layer(current_edit->channel);
140 SET_TRACE
142                         ((VTrack*)track)->calculate_input_transfer(current_edit->asset, 
143                                 input_position_project, 
144                                 direction, 
145                                 in_x1, 
146                                 in_y1, 
147                                 in_w1, 
148                                 in_h1,
149                                 out_x1, 
150                                 out_y1, 
151                                 out_w1, 
152                                 out_h1);
155 //                      printf("VModule::import_frame 1 [ilace] Project: mode (%d) Asset: autofixoption (%d), mode (%d), method (%d)\n", 
156 //                      get_edl()->session->interlace_mode,
157 //                      current_edit->asset->interlace_autofixoption,
158 //                      current_edit->asset->interlace_mode,
159 //                      current_edit->asset->interlace_fixmethod);
161                         // Determine the interlacing method to use.
162                         int interlace_fixmethod = ilaceautofixmethod2(get_edl()->session->interlace_mode,
163                                         current_edit->asset->interlace_autofixoption,
164                                         current_edit->asset->interlace_mode,
165                                         current_edit->asset->interlace_fixmethod);
167 //                      char string[BCTEXTLEN];
168 //                      ilacefixmethod_to_text(string,interlace_fixmethod);
169 //                      printf("VModule::import_frame 1 [ilace] Compensating by using: '%s'\n",string);
171                         // Compensate for the said interlacing...
172                         switch (interlace_fixmethod) {
173                                 case BC_ILACE_FIXMETHOD_NONE:
174                                 
175                                 break;
176                                 case BC_ILACE_FIXMETHOD_UPONE:
177                                         out_y1--;
178                                 break;
179                                 case BC_ILACE_FIXMETHOD_DOWNONE:
180                                         out_y1++;
181                                 break;
182                                 default:
183                                         printf("vmodule::importframe WARNING - unknown fix method for interlacing, no compensation in effect\n");
184                         }
185 SET_TRACE
188 // file -> temp -> output
189                         if( !EQUIV(in_x1, 0) || 
190                                 !EQUIV(in_y1, 0) || 
191                                 !EQUIV(in_w1, track->track_w) || 
192                                 !EQUIV(in_h1, track->track_h) || 
193                                 !EQUIV(out_x1, 0) ||
194                                 !EQUIV(out_y1, 0) ||
195                                 !EQUIV(out_w1, track->track_w) ||
196                                 !EQUIV(out_h1, track->track_h) ||
197                                 !EQUIV(in_w1, current_edit->asset->width) ||
198                                 !EQUIV(in_h1, current_edit->asset->height))
199                         {
200 //printf("VModule::import_frame 1\n");
201 // Get temporary input buffer
202                                 VFrame **input = 0;
203 // Realtime playback
204                                 if(commonrender)
205                                 {
206                                         VRender *vrender = (VRender*)commonrender;
207                                         input = &vrender->input_temp;
208                                 }
209                                 else
210 // Menu effect
211                                 {
212                                         input = &input_temp;
213                                 }
216                                 if((*input) && 
217                                         ((*input)->get_w() != current_edit->asset->width ||
218                                         (*input)->get_h() != current_edit->asset->height))
219                                 {
220                                         delete (*input);
221                                         (*input) = 0;
222                                 }
228                                 if(!(*input))
229                                 {
230                                         (*input) = new VFrame(0,
231                                                 current_edit->asset->width,
232                                                 current_edit->asset->height,
233                                                 get_edl()->session->color_model,
234                                                 -1);
235                                 }
239 // file -> temp
240 // Cache for single frame only
241 //                              if(renderengine && renderengine->command->single_frame())
242                                         source->set_cache_frames(1);
243 SET_TRACE
244                                 result = source->read_frame((*input));
245 SET_TRACE
246 //                              if(renderengine && renderengine->command->single_frame())
247                                         source->set_cache_frames(0);
249 //printf("VModule::import_frame 1 %lld %f\n", input_position, frame_rate);
250                                 OverlayFrame *overlayer = 0;
251 // Realtime playback
252                                 if(commonrender)
253                                 {
254                                         VRender *vrender = (VRender*)commonrender;
255                                         overlayer = vrender->overlayer;
256                                 }
257                                 else
258 // Menu effect
259                                 {
260                                         if(!plugin_array)
261                                                 printf("VModule::import_frame neither plugin_array nor commonrender is defined.\n");
262                                         if(!overlay_temp)
263                                         {
264                                                 overlay_temp = new OverlayFrame(plugin_array->mwindow->preferences->processors);
265                                         }
267                                         overlayer = overlay_temp;
268                                 }
269 // printf("VModule::import_frame 1 %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f\n", 
270 //      in_x1, 
271 //      in_y1, 
272 //      in_w1, 
273 //      in_h1, 
274 //      out_x1, 
275 //      out_y1, 
276 //      out_w1, 
277 //      out_h1);
279 // temp -> output
280 // for(int j = 0; j < output->get_w() * 3 * 5; j++)
281 //      output->get_rows()[0][j] = 255;
283                                 output->clear_frame();
286 // get_cache()->check_in(current_edit->asset);
287 // return;
289                                 int mode = TRANSFER_REPLACE;
291                                 overlayer->overlay(output,
292                                         (*input), 
293                                         in_x1,
294                                         in_y1,
295                                         in_x1 + in_w1,
296                                         in_y1 + in_h1,
297                                         out_x1,
298                                         out_y1,
299                                         out_x1 + out_w1,
300                                         out_y1 + out_h1,
301                                         1,
302                                         mode,
303                                         get_edl()->session->interpolation_type);
304                                 result = 1;
305 //printf("VModule::import_frame 20\n");
306                         }
307                         else
308 // file -> output
309                         {
310 //printf("VModule::import_frame 30 %p\n", output);
311 // Cache single frames only
312 //                              if(renderengine && renderengine->command->single_frame())
313                                         source->set_cache_frames(1);
314                                 result = source->read_frame(output);
315 //                              if(renderengine && renderengine->command->single_frame())
316                                         source->set_cache_frames(0);
317 //printf("VModule::import_frame 40\n");
318                         }
319 SET_TRACE
321                         get_cache()->check_in(current_edit->asset);
322                 }
323                 else
324                 {
325                         output->clear_frame();
326                         result = 1;
327                 }
328         }
329         else
330 // Silence
331         {
332                 output->clear_frame();
333         }
335         return result;
340 int VModule::render(VFrame *output,
341         int64_t start_position,
342         int direction,
343         double frame_rate,
344         int use_nudge,
345         int debug_render)
347         int result = 0;
348         double edl_rate = get_edl()->session->frame_rate;
350         if(use_nudge) start_position += (int64_t)(track->nudge * 
351                 frame_rate / 
352                 edl_rate);
355         int64_t start_position_project = (int64_t)(start_position *
356                 edl_rate /
357                 frame_rate + 
358                 0.5);
360         if(debug_render)
361                 printf("    VModule::render %d %lld %s\n", 
362                         use_nudge, 
363                         start_position_project,
364                         track->title);
366         update_transition(start_position_project, 
367                 direction);
368 SET_TRACE
370         VEdit* current_edit = (VEdit*)track->edits->editof(start_position_project, 
371                 direction,
372                 0);
373 SET_TRACE
374         VEdit* previous_edit = 0;
376         if(!current_edit)
377         {
378                 output->clear_frame();
379                 // We do not apply mask here, since alpha is 0, and neither substracting nor multypling changes it
380                 // Another mask mode - "addition" should be added to be able to create mask from empty frames
381                 // in this case we would call masking here too...
382                 return 0;
383         }
388 // Process transition
389         if(transition)
390         {
392 // Get temporary buffer
393                 VFrame **transition_input = 0;
394                 if(commonrender)
395                 {
396                         VRender *vrender = (VRender*)commonrender;
397                         transition_input = &vrender->transition_temp;
398                 }
399                 else
400                 {
401                         transition_input = &transition_temp;
402                 }
404                 if((*transition_input) &&
405                         ((*transition_input)->get_w() != track->track_w ||
406                         (*transition_input)->get_h() != track->track_h))
407                 {
408                         delete (*transition_input);
409                         (*transition_input) = 0;
410                 }
412 // Load incoming frame
413                 if(!(*transition_input))
414                 {
415                         (*transition_input) = new VFrame(0,
416                                 track->track_w,
417                                 track->track_h,
418                                 get_edl()->session->color_model,
419                                 -1);
420                 }
422                 result = import_frame((*transition_input), 
423                         current_edit, 
424                         start_position,
425                         frame_rate,
426                         direction);
429 // Load transition buffer
430                 previous_edit = (VEdit*)current_edit->previous;
432                 result |= import_frame(output, 
433                         previous_edit, 
434                         start_position,
435                         frame_rate,
436                         direction);
438 // Execute plugin with transition_input and output here
439                 transition_server->process_transition((*transition_input), 
440                         output,
441                         (direction == PLAY_FORWARD) ? 
442                                 (start_position_project - current_edit->startproject) :
443                                 (start_position_project - current_edit->startproject - 1),
444                         transition->length);
445         }
446         else
447         {
448 // Load output buffer
449 SET_TRACE
450                 result = import_frame(output, 
451                         current_edit, 
452                         start_position,
453                         frame_rate,
454                         direction);
455 SET_TRACE
456         }
457         
458         int64_t mask_position;
459         if (renderengine)
460                 mask_position = renderengine->vrender->current_position;
461         else 
462                 mask_position = start_position;
463         masker->do_mask(output, 
464                 mask_position,
465                 edl_rate,
466                 edl_rate,
467                 (MaskAutos*)track->automation->autos[AUTOMATION_MASK], 
468                 direction,
469                 1);      // we are calling before plugins
472         return result;
480 void VModule::create_objects()
482         Module::create_objects();