r665: Merged the official release 2.0.
[cinelerra_cv.git] / cinelerra / vmodule.C
blob4eafbb278cbfe6c0bb068fa7830f37f8d524e885
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"
32 VModule::VModule(RenderEngine *renderengine, 
33         CommonRender *commonrender, 
34         PluginArray *plugin_array,
35         Track *track)
36  : Module(renderengine, commonrender, plugin_array, track)
38         data_type = TRACK_VIDEO;
39         overlay_temp = 0;
40         input_temp = 0;
41         transition_temp = 0;
44 VModule::~VModule()
46         if(overlay_temp) delete overlay_temp;
47         if(input_temp) delete input_temp;
48         if(transition_temp) delete transition_temp;
52 AttachmentPoint* VModule::new_attachment(Plugin *plugin)
54         return new VAttachmentPoint(renderengine, plugin);
57 int VModule::get_buffer_size()
59         return 1;
62 CICache* VModule::get_cache()
64         if(renderengine) 
65                 return renderengine->get_vcache();
66         else
67                 return cache;
70 int VModule::import_frame(VFrame *output,
71         VEdit *current_edit,
72         int64_t input_position,
73         double frame_rate,
74         int direction)
76         int64_t corrected_position;
77         int64_t corrected_position_project;
78 // Translation of edit
79         float in_x1;
80         float in_y1;
81         float in_w1;
82         float in_h1;
83         float out_x1;
84         float out_y1;
85         float out_w1;
86         float out_h1;
87         int result = 0;
88 SET_TRACE
89         double edl_rate = get_edl()->session->frame_rate;
90         int64_t input_position_project = (int64_t)(input_position * 
91                 edl_rate / 
92                 frame_rate + 
93                 0.001);
94         if(!output) printf("VModule::import_frame 10 output=%p\n", output);
96 SET_TRACE
97         corrected_position = input_position;
98         corrected_position_project = input_position_project;
99         if(direction == PLAY_REVERSE)
100         {
101                 corrected_position--;
102                 input_position_project--;
103         }
105 // Load frame into output
106         if(current_edit &&
107                 current_edit->asset)
108         {
109                 get_cache()->age();
110 SET_TRACE
111                 File *source = get_cache()->check_out(current_edit->asset);
112 SET_TRACE
113 //              get_cache()->dump();
115                 if(source)
116                 {
117                         int64_t edit_startproject = (int64_t)(current_edit->startproject * 
118                                 frame_rate / 
119                                 edl_rate);
120                         int64_t edit_startsource = (int64_t)(current_edit->startsource *
121                                 frame_rate /
122                                 edl_rate);
123                         uint64_t position = corrected_position - 
124                                 edit_startproject + 
125                                 edit_startsource;
126                         // if we hit the end of stream, freeze at last frame
127                         uint64_t max_position = source->get_video_length(frame_rate) - 1;
128                         if (position > max_position) position = max_position;
129                         source->set_video_position(position,
130                                 frame_rate);
131                         source->set_layer(current_edit->channel);
132 SET_TRACE
134                         ((VTrack*)track)->calculate_input_transfer(current_edit->asset, 
135                                 input_position_project, 
136                                 direction, 
137                                 in_x1, 
138                                 in_y1, 
139                                 in_w1, 
140                                 in_h1,
141                                 out_x1, 
142                                 out_y1, 
143                                 out_w1, 
144                                 out_h1);
147 //                      printf("VModule::import_frame 1 [ilace] Project: mode (%d) Asset: autofixoption (%d), mode (%d), method (%d)\n", 
148 //                      get_edl()->session->interlace_mode,
149 //                      current_edit->asset->interlace_autofixoption,
150 //                      current_edit->asset->interlace_mode,
151 //                      current_edit->asset->interlace_fixmethod);
153                         // Determine the interlacing method to use.
154                         int interlace_fixmethod = ilaceautofixmethod2(get_edl()->session->interlace_mode,
155                                         current_edit->asset->interlace_autofixoption,
156                                         current_edit->asset->interlace_mode,
157                                         current_edit->asset->interlace_fixmethod);
159 //                      char string[BCTEXTLEN];
160 //                      ilacefixmethod_to_text(string,interlace_fixmethod);
161 //                      printf("VModule::import_frame 1 [ilace] Compensating by using: '%s'\n",string);
163                         // Compensate for the said interlacing...
164                         switch (interlace_fixmethod) {
165                                 case BC_ILACE_FIXMETHOD_NONE:
166                                 
167                                 break;
168                                 case BC_ILACE_FIXMETHOD_UPONE:
169                                         out_y1--;
170                                 break;
171                                 case BC_ILACE_FIXMETHOD_DOWNONE:
172                                         out_y1++;
173                                 break;
174                                 default:
175                                         printf("vmodule::importframe WARNING - unknown fix method for interlacing, no compensation in effect\n");
176                         }
177 SET_TRACE
180 // file -> temp -> output
181                         if( !EQUIV(in_x1, 0) || 
182                                 !EQUIV(in_y1, 0) || 
183                                 !EQUIV(in_w1, track->track_w) || 
184                                 !EQUIV(in_h1, track->track_h) || 
185                                 !EQUIV(out_x1, 0) ||
186                                 !EQUIV(out_y1, 0) ||
187                                 !EQUIV(out_w1, track->track_w) ||
188                                 !EQUIV(out_h1, track->track_h) ||
189                                 !EQUIV(in_w1, current_edit->asset->width) ||
190                                 !EQUIV(in_h1, current_edit->asset->height))
191                         {
192 //printf("VModule::import_frame 1\n");
193 // Get temporary input buffer
194                                 VFrame **input = 0;
195 // Realtime playback
196                                 if(commonrender)
197                                 {
198                                         VRender *vrender = (VRender*)commonrender;
199                                         input = &vrender->input_temp;
200                                 }
201                                 else
202 // Menu effect
203                                 {
204                                         input = &input_temp;
205                                 }
208                                 if((*input) && 
209                                         ((*input)->get_w() != current_edit->asset->width ||
210                                         (*input)->get_h() != current_edit->asset->height))
211                                 {
212                                         delete (*input);
213                                         (*input) = 0;
214                                 }
220                                 if(!(*input))
221                                 {
222                                         (*input) = new VFrame(0,
223                                                 current_edit->asset->width,
224                                                 current_edit->asset->height,
225                                                 get_edl()->session->color_model,
226                                                 -1);
227                                 }
231 // file -> temp
232 // Cache for single frame only
233                                 if(renderengine && renderengine->command->single_frame())
234                                         source->set_cache_frames(1);
235 SET_TRACE
236                                 result = source->read_frame((*input));
237 SET_TRACE
238                                 if(renderengine && renderengine->command->single_frame())
239                                         source->set_cache_frames(0);
241 //printf("VModule::import_frame 1 %lld %f\n", input_position, frame_rate);
242                                 OverlayFrame *overlayer = 0;
243 // Realtime playback
244                                 if(commonrender)
245                                 {
246                                         VRender *vrender = (VRender*)commonrender;
247                                         overlayer = vrender->overlayer;
248                                 }
249                                 else
250 // Menu effect
251                                 {
252                                         if(!plugin_array)
253                                                 printf("VModule::import_frame neither plugin_array nor commonrender is defined.\n");
254                                         if(!overlay_temp)
255                                         {
256                                                 overlay_temp = new OverlayFrame(plugin_array->mwindow->preferences->processors);
257                                         }
259                                         overlayer = overlay_temp;
260                                 }
261 // printf("VModule::import_frame 1 %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f\n", 
262 //      in_x1, 
263 //      in_y1, 
264 //      in_w1, 
265 //      in_h1, 
266 //      out_x1, 
267 //      out_y1, 
268 //      out_w1, 
269 //      out_h1);
271 // temp -> output
272 // for(int j = 0; j < output->get_w() * 3 * 5; j++)
273 //      output->get_rows()[0][j] = 255;
275                                 output->clear_frame();
278 // get_cache()->check_in(current_edit->asset);
279 // return;
281                                 int mode = TRANSFER_REPLACE;
283                                 overlayer->overlay(output,
284                                         (*input), 
285                                         in_x1,
286                                         in_y1,
287                                         in_x1 + in_w1,
288                                         in_y1 + in_h1,
289                                         out_x1,
290                                         out_y1,
291                                         out_x1 + out_w1,
292                                         out_y1 + out_h1,
293                                         1,
294                                         mode,
295                                         get_edl()->session->interpolation_type);
296                                 result = 1;
297 //printf("VModule::import_frame 20\n");
298                         }
299                         else
300 // file -> output
301                         {
302 //printf("VModule::import_frame 30 %p\n", output);
303 // Cache single frames only
304                                 if(renderengine && renderengine->command->single_frame())
305                                         source->set_cache_frames(1);
306                                 result = source->read_frame(output);
307                                 if(renderengine && renderengine->command->single_frame())
308                                         source->set_cache_frames(0);
309 //printf("VModule::import_frame 40\n");
310                         }
311 SET_TRACE
313                         get_cache()->check_in(current_edit->asset);
314                 }
315                 else
316                 {
317                         output->clear_frame();
318                         result = 1;
319                 }
320         }
321         else
322 // Silence
323         {
324                 output->clear_frame();
325         }
327         return result;
332 int VModule::render(VFrame *output,
333         int64_t start_position,
334         int direction,
335         double frame_rate,
336         int use_nudge,
337         int debug_render)
339         int result = 0;
340         double edl_rate = get_edl()->session->frame_rate;
343         if(use_nudge) start_position += (int64_t)(track->nudge * 
344                 frame_rate / 
345                 edl_rate);
348         int64_t start_position_project = (int64_t)(start_position *
349                 edl_rate /
350                 frame_rate + 
351                 0.5);
353         if(debug_render)
354                 printf("    VModule::render %d %lld %s\n", 
355                         use_nudge, 
356                         start_position_project,
357                         track->title);
359         update_transition(start_position_project, 
360                 direction);
361 SET_TRACE
363         VEdit* current_edit = (VEdit*)track->edits->editof(start_position_project, 
364                 direction,
365                 0);
366 SET_TRACE
367         VEdit* previous_edit = 0;
369         if(!current_edit)
370         {
371                 output->clear_frame();
372                 return 0;
373         }
378 // Process transition
379         if(transition)
380         {
382 // Get temporary buffer
383                 VFrame **transition_input = 0;
384                 if(commonrender)
385                 {
386                         VRender *vrender = (VRender*)commonrender;
387                         transition_input = &vrender->transition_temp;
388                 }
389                 else
390                 {
391                         transition_input = &transition_temp;
392                 }
394                 if((*transition_input) &&
395                         ((*transition_input)->get_w() != track->track_w ||
396                         (*transition_input)->get_h() != track->track_h))
397                 {
398                         delete (*transition_input);
399                         (*transition_input) = 0;
400                 }
402 // Load incoming frame
403                 if(!(*transition_input))
404                 {
405                         (*transition_input) = new VFrame(0,
406                                 track->track_w,
407                                 track->track_h,
408                                 get_edl()->session->color_model,
409                                 -1);
410                 }
412                 result = import_frame((*transition_input), 
413                         current_edit, 
414                         start_position,
415                         frame_rate,
416                         direction);
419 // Load transition buffer
420                 previous_edit = (VEdit*)current_edit->previous;
422                 result |= import_frame(output, 
423                         previous_edit, 
424                         start_position,
425                         frame_rate,
426                         direction);
428 // Execute plugin with transition_input and output here
429                 transition_server->process_transition((*transition_input), 
430                         output,
431                         (direction == PLAY_FORWARD) ? 
432                                 (start_position_project - current_edit->startproject) :
433                                 (start_position_project - current_edit->startproject - 1),
434                         transition->length);
435         }
436         else
437         {
438 // Load output buffer
439 SET_TRACE
440                 result = import_frame(output, 
441                         current_edit, 
442                         start_position,
443                         frame_rate,
444                         direction);
445 SET_TRACE
446         }
449         return result;
457 void VModule::create_objects()
459         Module::create_objects();