fix mask vframe setup, add unshared vframe constructor
[goodguy/history.git] / cinelerra-5.1 / cinelerra / vmodule.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2009-2013 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "asset.h"
23 #include "bchash.h"
24 #include "bcpbuffer.h"
25 #include "bcsignals.h"
26 #include "cache.h"
27 #include "clip.h"
28 #include "commonrender.h"
29 #include "edits.h"
30 #include "edl.h"
31 #include "edlsession.h"
32 #include "file.h"
33 #include "filexml.h"
34 #include "floatautos.h"
35 #include "maskauto.h"
36 #include "maskautos.h"
37 #include "mwindow.h"
38 #include "overlayframe.h"
39 #include "patch.h"
40 #include "pluginarray.h"
41 #include "preferences.h"
42 #include "renderengine.h"
43 #include "sharedlocation.h"
44 #include "tracks.h"
45 #include "transition.h"
46 #include "transportque.h"
47 #include "units.h"
48 #include "vattachmentpoint.h"
49 #include "vdevicex11.h"
50 #include "vedit.h"
51 #include "vframe.h"
52 #include "videodevice.h"
53 #include "virtualvconsole.h"
54 #include "vmodule.h"
55 #include "vrender.h"
56 #include "vplugin.h"
57 #include "vtrack.h"
58 #include <string.h>
59 #include "interlacemodes.h"
60 #include "maskengine.h"
61 #include "automation.h"
62
63 VModule::VModule(RenderEngine *renderengine,
64         CommonRender *commonrender,
65         PluginArray *plugin_array,
66         Track *track)
67  : Module(renderengine, commonrender, plugin_array, track)
68 {
69         data_type = TRACK_VIDEO;
70         overlay_temp = 0;
71         input_temp = 0;
72         transition_temp = 0;
73         masker = 0;
74 }
75
76 VModule::~VModule()
77 {
78         if(overlay_temp) delete overlay_temp;
79         if(input_temp) delete input_temp;
80         if(transition_temp) delete transition_temp;
81         delete masker;
82 }
83
84
85 AttachmentPoint* VModule::new_attachment(Plugin *plugin)
86 {
87         return new VAttachmentPoint(renderengine, plugin);
88 }
89
90 int VModule::get_buffer_size()
91 {
92         return 1;
93 }
94
95 CICache* VModule::get_cache()
96 {
97         if(renderengine)
98                 return renderengine->get_vcache();
99         else
100                 return cache;
101 }
102
103
104
105
106
107
108 int VModule::import_frame(VFrame *output, VEdit *current_edit,
109         int64_t input_position, double frame_rate, int direction, int use_opengl)
110 {
111         int64_t direction_position;
112 // Translation of edit
113         float in_x, in_y, in_w, in_h;
114         float out_x, out_y, out_w, out_h;
115         int result = 0;
116         const int debug = 0;
117         double edl_rate = get_edl()->session->frame_rate;
118
119         int64_t input_position_project = Units::to_int64(input_position *
120                 edl_rate / frame_rate + 0.001);
121
122         if(!output) printf("VModule::import_frame %d output=%p\n", __LINE__, output);
123         //output->dump_params();
124
125         if(debug) printf("VModule::import_frame %d this=%p input_position=%lld direction=%d\n",
126                 __LINE__, this, (long long)input_position, direction);
127
128 // Convert to position corrected for direction
129         direction_position = input_position;
130         if(direction == PLAY_REVERSE) {
131                 if( direction_position > 0 ) direction_position--;
132                 if( input_position_project > 0 ) input_position_project--;
133         }
134         if(!output) printf("VModule::import_frame %d output=%p\n", __LINE__, output);
135
136         VDeviceX11 *x11_device = 0;
137         if(use_opengl)
138         {
139                 if(renderengine && renderengine->video)
140                 {
141                         x11_device = (VDeviceX11*)renderengine->video->get_output_base();
142                         output->set_opengl_state(VFrame::RAM);
143                         if(!x11_device) use_opengl = 0;
144                 }
145         }
146
147         if(!output) printf("VModule::import_frame %d output=%p x11_device=%p nested_edl=%p\n",
148                 __LINE__, output, x11_device, nested_edl);
149
150         if(debug) printf("VModule::import_frame %d current_edit=%p\n",
151                 __LINE__, current_edit);
152
153 // Load frame into output
154
155 // Create objects for nested EDL
156         if(current_edit && current_edit->nested_edl) {
157                 int command;
158                 if(debug) printf("VModule::import_frame %d nested_edl=%p current_edit->nested_edl=%p\n",
159                         __LINE__, nested_edl, current_edit->nested_edl);
160
161 // Convert requested direction to command
162                 if(renderengine->command->command == CURRENT_FRAME)
163                 {
164                         command = CURRENT_FRAME;
165                 }
166                 else
167                 if(direction == PLAY_REVERSE)
168                 {
169                         if(renderengine->command->single_frame())
170                                 command = SINGLE_FRAME_REWIND;
171                         else
172                                 command = NORMAL_REWIND;
173                 }
174                 else
175                 {
176                         if(renderengine->command->single_frame())
177                                 command = SINGLE_FRAME_FWD;
178                         else
179                                 command = NORMAL_FWD;
180                 }
181
182                 if(!nested_edl || nested_edl->id != current_edit->nested_edl->id)
183                 {
184                         nested_edl = current_edit->nested_edl;
185                         if(nested_renderengine)
186                         {
187                                 delete nested_renderengine;
188                                 nested_renderengine = 0;
189                         }
190
191                         if(!nested_command)
192                         {
193                                 nested_command = new TransportCommand;
194                         }
195
196
197                         if(!nested_renderengine)
198                         {
199                                 nested_command->command = command;
200                                 nested_command->get_edl()->copy_all(nested_edl);
201                                 nested_command->change_type = CHANGE_ALL;
202                                 nested_command->realtime = renderengine->command->realtime;
203                                 nested_renderengine = new RenderEngine(0, get_preferences(), 0, 1);
204                                 nested_renderengine->set_vcache(get_cache());
205                                 nested_renderengine->arm_command(nested_command);
206                         }
207                 }
208                 else
209                 {
210
211 // Update nested command
212                         nested_renderengine->command->command = command;
213                         nested_command->realtime = renderengine->command->realtime;
214                 }
215
216 // Update nested video driver for opengl
217                 nested_renderengine->video = renderengine->video;
218         }
219         else
220         {
221                 nested_edl = 0;
222         }
223         if(debug) printf("VModule::import_frame %d\n", __LINE__);
224
225         if(!output) printf("VModule::import_frame %d output=%p\n", __LINE__, output);
226
227         if(current_edit &&
228                 (current_edit->asset ||
229                 (current_edit->nested_edl && nested_renderengine->vrender)))
230         {
231                 File *file = 0;
232
233 //printf("VModule::import_frame %d cache=%p\n", __LINE__, get_cache());
234                 if( current_edit->asset ) {
235                         get_cache()->age();
236                         file = get_cache()->check_out(current_edit->asset,
237                                 get_edl());
238 //                      get_cache()->dump();
239                 }
240
241 // File found
242                 if(file || nested_edl)
243                 {
244 // Make all positions based on requested frame rate.
245                         int64_t edit_startproject = Units::to_int64(current_edit->startproject *
246                                 frame_rate /
247                                 edl_rate);
248                         int64_t edit_startsource = Units::to_int64(current_edit->startsource *
249                                 frame_rate /
250                                 edl_rate);
251 // Source position going forward
252                         uint64_t position = direction_position -
253                                 edit_startproject +
254                                 edit_startsource;
255                         int64_t nested_position = 0;
256
257
258
259
260
261 // apply speed curve to source position so the timeline agrees with the playback
262                         if(track->has_speed())
263                         {
264 // integrate position from start of edit.
265                                 double speed_position = edit_startsource;
266                                 FloatAutos *speed_autos = (FloatAutos*)track->automation->autos[AUTOMATION_SPEED];
267                                 speed_position += speed_autos->automation_integral(edit_startproject,
268                                                 direction_position-edit_startproject, PLAY_FORWARD);
269 //printf("VModule::import_frame %d %lld %lld\n", __LINE__, position, (int64_t)speed_position);
270                                 position = (int64_t)speed_position;
271                         }
272
273
274
275
276
277                         int asset_w;
278                         int asset_h;
279                         if(debug) printf("VModule::import_frame %d\n", __LINE__);
280
281
282 // maybe apply speed curve here, so timeline reflects actual playback
283
284
285
286 // if we hit the end of stream, freeze at last frame
287                         uint64_t max_position = 0;
288                         if(file)
289                         {
290                                 max_position = Units::to_int64((double)file->get_video_length() *
291                                         frame_rate /
292                                         current_edit->asset->frame_rate - 1);
293                         }
294                         else
295                         {
296                                 max_position = Units::to_int64(nested_edl->tracks->total_length() *
297                                         frame_rate - 1);
298                         }
299
300
301                         if(position > max_position) position = max_position;
302                         else
303                         if(position < 0) position = 0;
304
305                         int use_cache = renderengine &&
306                                 renderengine->command->single_frame();
307 //                      int use_asynchronous = !use_cache &&
308 //                              renderengine &&
309 // Try to make rendering go faster.
310 // But converts some formats to YUV420, which may degrade input format.
311 ////                            renderengine->command->realtime &&
312 //                              renderengine->get_edl()->session->video_asynchronous;
313
314                         if(file)
315                         {
316                                 if(debug) printf("VModule::import_frame %d\n", __LINE__);
317 //                              if(use_asynchronous)
318 //                                      file->start_video_decode_thread();
319 //                              else
320                                         file->stop_video_thread();
321
322                                 int64_t normalized_position = Units::to_int64(position *
323                                         current_edit->asset->frame_rate /
324                                         frame_rate);
325 // printf("VModule::import_frame %d %lld %lld\n",
326 // __LINE__,
327 // position,
328 // normalized_position);
329                                 file->set_layer(current_edit->channel);
330                                 file->set_video_position(normalized_position,
331                                         0);
332                                 asset_w = current_edit->asset->width;
333                                 asset_h = current_edit->asset->height;
334 //printf("VModule::import_frame %d normalized_position=%lld\n", __LINE__, normalized_position);
335                         }
336                         else
337                         {
338                                 if(debug) printf("VModule::import_frame %d\n", __LINE__);
339                                 asset_w = nested_edl->session->output_w;
340                                 asset_h = nested_edl->session->output_h;
341 // Get source position in nested frame rate in direction of playback.
342                                 nested_position = Units::to_int64(position *
343                                         nested_edl->session->frame_rate /
344                                         frame_rate);
345                                 if(direction == PLAY_REVERSE)
346                                         nested_position++;
347                         }
348
349
350 // Auto scale if required
351                         if(output->get_params()->get("AUTOSCALE", 0))
352                         {
353                                 float autoscale_w = output->get_params()->get("AUTOSCALE_W", 1024);
354                                 float autoscale_h = output->get_params()->get("AUTOSCALE_H", 1024);
355                                 float x_scale = autoscale_w / asset_w;
356                                 float y_scale = autoscale_h / asset_h;
357
358 // Overriding camera
359                                 in_x = 0;
360                                 in_y = 0;
361                                 in_w = asset_w;
362                                 in_h = asset_h;
363
364                                 if(x_scale < y_scale)
365                                 {
366                                         out_w = in_w * x_scale;
367                                         out_h = in_h * x_scale;
368                                 }
369                                 else
370                                 {
371                                         out_w = in_w * y_scale;
372                                         out_h = in_h * y_scale;
373                                 }
374
375                                 out_x = track->track_w / 2 - out_w / 2;
376                                 out_y = track->track_h / 2 - out_h / 2;
377                         }
378                         else
379 // Apply camera
380                         {
381                                 ((VTrack*)track)->calculate_input_transfer(asset_w,
382                                         asset_h,
383                                         input_position_project,
384                                         direction,
385                                         in_x,
386                                         in_y,
387                                         in_w,
388                                         in_h,
389                                         out_x,
390                                         out_y,
391                                         out_w,
392                                         out_h);
393                         }
394
395 // printf("VModule::import_frame %d %f %d %f %d\n",
396 // __LINE__,
397 // in_w,
398 // asset_w,
399 // in_h,
400 // asset_h);
401 //
402 //                      printf("VModule::import_frame 1 [ilace] Project: mode (%d) Asset: autofixoption (%d), mode (%d), method (%d)\n",
403 //                      get_edl()->session->interlace_mode,
404 //                      current_edit->asset->interlace_autofixoption,
405 //                      current_edit->asset->interlace_mode,
406 //                      current_edit->asset->interlace_fixmethod);
407
408                         // Determine the interlacing method to use.
409                         int interlace_fixmethod = !current_edit->asset ? ILACE_FIXMETHOD_NONE :
410                                  ilaceautofixmethod2(get_edl()->session->interlace_mode,
411                                         current_edit->asset->interlace_autofixoption,
412                                         current_edit->asset->interlace_mode,
413                                         current_edit->asset->interlace_fixmethod);
414 //
415 //                      char string[BCTEXTLEN];
416 //                      ilacefixmethod_to_text(string,interlace_fixmethod);
417 //                      printf("VModule::import_frame 1 [ilace] Compensating by using: '%s'\n",string);
418
419                         // Compensate for the said interlacing...
420                         switch (interlace_fixmethod) {
421                                 case ILACE_FIXMETHOD_NONE:
422
423                                 break;
424                                 case ILACE_FIXMETHOD_UPONE:
425                                         out_y--;
426                                 break;
427                                 case ILACE_FIXMETHOD_DOWNONE:
428                                         out_y++;
429                                 break;
430                                 default:
431                                         printf("vmodule::importframe WARNING - unknown fix method for interlacing, no compensation in effect\n");
432                         }
433
434 // file -> temp -> output
435                         if( !EQUIV(in_x, 0) ||
436                                 !EQUIV(in_y, 0) ||
437                                 !EQUIV(in_w, track->track_w) ||
438                                 !EQUIV(in_h, track->track_h) ||
439                                 !EQUIV(out_x, 0) ||
440                                 !EQUIV(out_y, 0) ||
441                                 !EQUIV(out_w, track->track_w) ||
442                                 !EQUIV(out_h, track->track_h) ||
443                                 !EQUIV(in_w, asset_w) ||
444                                 !EQUIV(in_h, asset_h))
445                         {
446 //printf("VModule::import_frame %d file -> temp -> output\n", __LINE__);
447
448
449
450
451 // Get temporary input buffer
452                                 VFrame **input = 0;
453 // Realtime playback
454                                 if(commonrender)
455                                 {
456                                         VRender *vrender = (VRender*)commonrender;
457 //printf("VModule::import_frame %d vrender->input_temp=%p\n", __LINE__, vrender->input_temp);
458                                         input = &vrender->input_temp;
459                                 }
460                                 else
461 // Menu effect
462                                 {
463                                         input = &input_temp;
464                                 }
465
466
467                                 if((*input) &&
468                                         ((*input)->get_w() != asset_w ||
469                                         (*input)->get_h() != asset_h))
470                                 {
471                                         delete (*input);
472                                         (*input) = 0;
473                                 }
474
475
476
477
478
479                                 if(!(*input))
480                                 {
481                                         (*input) =
482                                                 new VFrame(asset_w, asset_h,
483                                                         get_edl()->session->color_model);
484                                 }
485
486
487
488                                 (*input)->copy_stacks(output);
489
490 // file -> temp
491 // Cache for single frame only
492                                 if(file)
493                                 {
494                                         if(debug) printf("VModule::import_frame %d this=%p file=%s\n",
495                                                 __LINE__,
496                                                 this,
497                                                 current_edit->asset->path);
498                                         if(use_cache) file->set_cache_frames(1);
499                                         result = file->read_frame((*input));
500                                         if(use_cache) file->set_cache_frames(0);
501                                         (*input)->set_opengl_state(VFrame::RAM);
502                                 }
503                                 else
504                                 if(nested_edl)
505                                 {
506 // If the colormodels differ, change input to nested colormodel
507                                         int nested_cmodel = nested_renderengine->get_edl()->session->color_model;
508                                         int current_cmodel = output->get_color_model();
509                                         int output_w = output->get_w();
510                                         int output_h = output->get_h();
511                                         VFrame *input2 = (*input);
512
513                                         if(nested_cmodel != current_cmodel)
514                                         {
515 // If opengl, input -> input -> output
516                                                 if(use_opengl)
517                                                 {
518                                                 }
519                                                 else
520                                                 {
521 // If software, input2 -> input -> output
522 // Use output as a temporary.
523                                                         input2 = output;
524                                                 }
525
526                                                 if(debug) printf("VModule::import_frame %d this=%p nested_cmodel=%d\n",
527                                                         __LINE__,
528                                                         this,
529                                                         nested_cmodel);
530                                                 input2->dump();
531                                                 input2->reallocate(0,
532                                                         -1,
533                                                         0,
534                                                         0,
535                                                         0,
536                                                         (*input)->get_w(),
537                                                         (*input)->get_h(),
538                                                         nested_cmodel,
539                                                         -1);
540                                                 input2->dump();
541                                         }
542
543
544                                         if(debug) printf("VModule::import_frame %d this=%p nested_edl=%s input2=%p\n",
545                                                 __LINE__,
546                                                 this,
547                                                 nested_edl->path,
548                                                 input2);
549
550                                         result = nested_renderengine->vrender->process_buffer(
551                                                 input2,
552                                                 nested_position,
553                                                 use_opengl);
554
555                                         if(debug) printf("VModule::import_frame %d this=%p nested_edl=%s\n",
556                                                 __LINE__,
557                                                 this,
558                                                 nested_edl->path);
559
560                                         if(nested_cmodel != current_cmodel)
561                                         {
562                                                 if(debug) printf("VModule::import_frame %d\n", __LINE__);
563                                                 if(use_opengl)
564                                                 {
565 // Change colormodel in hardware.
566                                                         if(debug) printf("VModule::import_frame %d\n", __LINE__);
567                                                         x11_device->convert_cmodel(input2,
568                                                                 current_cmodel);
569
570 // The converted color model is now in hardware, so return the input2 buffer
571 // to the expected color model.
572                                                         input2->reallocate(0,
573                                                                 -1,
574                                                                 0,
575                                                                 0,
576                                                                 0,
577                                                                 (*input)->get_w(),
578                                                                 (*input)->get_h(),
579                                                                 current_cmodel,
580                                                                 -1);
581                                                 }
582                                                 else
583                                                 {
584 // Transfer from input2 to input
585 if(debug) printf("VModule::import_frame %d nested_cmodel=%d current_cmodel=%d input2=%p input=%p output=%p\n",
586 __LINE__,
587 nested_cmodel,
588 current_cmodel,
589 input2,
590 (*input),
591 output);
592                                                         BC_CModels::transfer((*input)->get_rows(),
593                                                                 input2->get_rows(),
594                                                                 0,
595                                                                 0,
596                                                                 0,
597                                                                 0,
598                                                                 0,
599                                                                 0,
600                                                                 0,
601                                                                 0,
602                                                             input2->get_w(),
603                                                             input2->get_h(),
604                                                                 0,
605                                                                 0,
606                                                                 (*input)->get_w(),
607                                                                 (*input)->get_h(),
608                                                                 nested_cmodel,
609                                                                 current_cmodel,
610                                                                 0,
611                                                                 input2->get_w(),
612                                                                 (*input)->get_w());
613 //printf("VModule::import_frame %d\n", __LINE__);
614
615 // input2 was the output buffer, so it must be restored
616                                                 input2->reallocate(0,
617                                                         -1,
618                                                         0,
619                                                         0,
620                                                         0,
621                                                         output_w,
622                                                         output_h,
623                                                         current_cmodel,
624                                                         -1);
625 //printf("VModule::import_frame %d\n", __LINE__);
626                                                 }
627                                         }
628
629                                 }
630
631 // Find an overlayer object to perform the camera transformation
632                                 OverlayFrame *overlayer = 0;
633
634 // OpenGL playback uses hardware
635                                 if(use_opengl)
636                                 {
637 //printf("VModule::import_frame %d\n", __LINE__);
638                                 }
639                                 else
640 // Realtime playback
641                                 if(commonrender)
642                                 {
643                                         VRender *vrender = (VRender*)commonrender;
644                                         overlayer = vrender->overlayer;
645                                 }
646                                 else
647 // Menu effect
648                                 {
649                                         if(!plugin_array)
650                                                 printf("VModule::import_frame neither plugin_array nor commonrender is defined.\n");
651                                         if(!overlay_temp)
652                                         {
653                                                 overlay_temp = new OverlayFrame(plugin_array->mwindow->preferences->processors);
654                                         }
655
656                                         overlayer = overlay_temp;
657                                 }
658 // printf("VModule::import_frame 1 %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f\n",
659 //      in_x,
660 //      in_y,
661 //      in_w,
662 //      in_h,
663 //      out_x,
664 //      out_y,
665 //      out_w,
666 //      out_h);
667
668 // temp -> output
669 // for(int j = 0; j < output->get_w() * 3 * 5; j++)
670 //      output->get_rows()[0][j] = 255;
671
672                                 if(use_opengl)
673                                 {
674                                         x11_device->do_camera(output,
675                                                 (*input),
676                                                 in_x,
677                                                 in_y,
678                                                 in_x + in_w,
679                                                 in_y + in_h,
680                                                 out_x,
681                                                 out_y,
682                                                 out_x + out_w,
683                                                 out_y + out_h);
684 if(debug) printf("VModule::import_frame %d %d %d\n",
685 __LINE__,
686 output->get_opengl_state(),
687 (*input)->get_opengl_state());
688                                 }
689                                 else
690                                 {
691
692
693
694                                         output->clear_frame();
695
696
697 // get_cache()->check_in(current_edit->asset);
698 // return;
699
700 // TRANSFER_REPLACE is the fastest transfer mode but it has the disadvantage
701 // of producing green borders in floating point translation of YUV
702                                         int mode = TRANSFER_REPLACE;
703                                         if(get_edl()->session->interpolation_type != NEAREST_NEIGHBOR &&
704                                                 BC_CModels::is_yuv(output->get_color_model()))
705                                                 mode = TRANSFER_NORMAL;
706
707                                         if(debug) printf("VModule::import_frame %d temp -> output\n", __LINE__);
708                                         overlayer->overlay(output,
709                                                 (*input),
710                                                 in_x,
711                                                 in_y,
712                                                 in_x + in_w,
713                                                 in_y + in_h,
714                                                 out_x,
715                                                 out_y,
716                                                 out_x + out_w,
717                                                 out_y + out_h,
718                                                 1,
719                                                 mode,
720                                                 get_edl()->session->interpolation_type);
721                                 }
722                                 result = 1;
723                                 
724                                 output->copy_stacks((*input));
725                                 
726                                 
727 //printf("VModule::import_frame %d\n", __LINE__); 
728 //(*input)->dump_params();
729 //output->dump_params();
730                         }
731                         else
732 // file -> output
733                         {
734                                 if(debug) printf("VModule::import_frame %d file -> output nested_edl=%p file=%p\n",
735                                         __LINE__,
736                                         nested_edl,
737                                         file);
738                                 if(nested_edl)
739                                 {
740                                         VFrame **input = &output;
741 // If colormodels differ, reallocate output in nested colormodel.
742                                         int nested_cmodel = nested_renderengine->get_edl()->session->color_model;
743                                         int current_cmodel = output->get_color_model();
744
745 if(debug) printf("VModule::import_frame %d nested_cmodel=%d current_cmodel=%d\n",
746 __LINE__,
747 nested_cmodel,
748 current_cmodel);
749
750                                         if(nested_cmodel != current_cmodel)
751                                         {
752                                                 if(use_opengl)
753                                                 {
754                                                 }
755                                                 else
756                                                 {
757                                                         if(commonrender)
758                                                         {
759                                                                 input = &((VRender*)commonrender)->input_temp;
760                                                         }
761                                                         else
762                                                         {
763                                                                 input = &input_temp;
764                                                         }
765
766                                                         if(!(*input)) (*input) = new VFrame;
767                                                 }
768
769                                                 (*input)->reallocate(0,
770                                                         -1,
771                                                         0,
772                                                         0,
773                                                         0,
774                                                         output->get_w(),
775                                                         output->get_h(),
776                                                         nested_cmodel,
777                                                         -1);
778 if(debug) printf("VModule::import_frame %d\n",
779 __LINE__);
780 //(*input)->dump();
781 //(*input)->clear_frame();
782                                         }
783
784 if(debug) printf("VModule::import_frame %d %p %p\n",
785 __LINE__,
786 (*input)->get_rows(),
787 (*input));
788                                         result = nested_renderengine->vrender->process_buffer(
789                                                 (*input),
790                                                 nested_position,
791                                                 use_opengl);
792 if(debug) printf("VModule::import_frame %d\n",
793 __LINE__);
794
795 // If colormodels differ, change colormodels in opengl if possible.
796 // Swap output for temp if not possible.
797                                         if(nested_cmodel != current_cmodel)
798                                         {
799                                                 if(use_opengl)
800                                                 {
801                                                         x11_device->convert_cmodel(output,
802                                                                 current_cmodel);
803
804 // The color model was changed in place, so return output buffer
805                                                         output->reallocate(0,
806                                                                 -1,
807                                                                 0,
808                                                                 0,
809                                                                 0,
810                                                                 output->get_w(),
811                                                                 output->get_h(),
812                                                                 current_cmodel,
813                                                                 -1);
814                                                 }
815                                                 else
816                                                 {
817 // Transfer from temporary to output
818 if(debug) printf("VModule::import_frame %d %d %d %d %d %d %d\n",
819 __LINE__,
820 (*input)->get_w(),
821 (*input)->get_h(),
822 output->get_w(),
823 output->get_h(),
824 nested_cmodel,
825 current_cmodel);
826                                                         BC_CModels::transfer(output->get_rows(),
827                                                                 (*input)->get_rows(),
828                                                                 0,
829                                                                 0,
830                                                                 0,
831                                                                 0,
832                                                                 0,
833                                                                 0,
834                                                                 0,
835                                                                 0,
836                                                                 (*input)->get_w(),
837                                                                 (*input)->get_h(),
838                                                                 0,
839                                                                 0,
840                                                                 output->get_w(),
841                                                                 output->get_h(),
842                                                                 nested_cmodel,
843                                                                 current_cmodel,
844                                                                 0,
845                                                                 (*input)->get_w(),
846                                                                 output->get_w());
847                                                 }
848
849                                         }
850
851                                 }
852                                 else
853                                 if(file)
854                                 {
855 // Cache single frames
856 //memset(output->get_rows()[0], 0xff, 1024);
857                                         if(use_cache) file->set_cache_frames(1);
858                                         result = file->read_frame(output);
859                                         if(use_cache) file->set_cache_frames(0);
860                                         output->set_opengl_state(VFrame::RAM);
861                                 }
862                         }
863
864                         if(file)
865                         {
866                                 get_cache()->check_in(current_edit->asset);
867                                 file = 0;
868                         }
869                 }
870                 else
871 // Source not found
872                 {
873                         if(debug) printf("VModule::import_frame %d\n", __LINE__);
874                         if(use_opengl)
875                         {
876                                 x11_device->clear_input(output);
877                         }
878                         else
879                         {
880                                 output->clear_frame();
881                         }
882                         result = 1;
883                 }
884
885 //              printf("VModule::import_frame %d cache=%p\n", 
886 //                      __LINE__,
887 //                      get_cache());
888
889         }
890         else
891 // Source is silence
892         {
893                 if(debug) printf("VModule::import_frame %d\n", __LINE__);
894                 if(use_opengl)
895                 {
896                         x11_device->clear_input(output);
897                 }
898                 else
899                 {
900                         output->clear_frame();
901                 }
902         }
903
904         if(debug) printf("VModule::import_frame %d done\n", __LINE__);
905
906         return result;
907 }
908
909
910
911 int VModule::render(VFrame *output,
912         int64_t start_position,
913         int direction,
914         double frame_rate,
915         int use_nudge,
916         int debug_render,
917         int use_opengl)
918 {
919         int result = 0;
920         double edl_rate = get_edl()->session->frame_rate;
921
922 //printf("VModule::render %d %ld\n", __LINE__, start_position);
923
924         if(use_nudge) start_position += Units::to_int64(track->nudge *
925                 frame_rate / edl_rate);
926
927         int64_t start_position_project = Units::to_int64(start_position *
928                 edl_rate / frame_rate + 0.5);
929
930         update_transition(start_position_project,
931                 direction);
932
933         VEdit* current_edit = (VEdit*)track->edits->editof(start_position_project,
934                 direction,
935                 0);
936         VEdit* previous_edit = 0;
937 //printf("VModule::render %d %p %ld %d\n", __LINE__, current_edit, start_position_project, direction);
938
939         if(debug_render)
940                 printf("    VModule::render %d %d %jd %s transition=%p opengl=%d current_edit=%p output=%p\n",
941                         __LINE__,
942                         use_nudge,
943                         start_position_project,
944                         track->title,
945                         transition,
946                         use_opengl,
947                         current_edit,
948                         output);
949
950         if(!current_edit)
951         {
952                 output->clear_frame();
953                 // We do not apply mask here, since alpha is 0, and neither substracting nor multypling changes it
954                 // Another mask mode - "addition" should be added to be able to create mask from empty frames
955                 // in this case we would call masking here too...
956                 return 0;
957         }
958
959
960
961
962 // Process transition
963         if(transition && transition->on)
964         {
965
966 // Get temporary buffer
967                 VFrame **transition_input = 0;
968                 if(commonrender)
969                 {
970                         VRender *vrender = (VRender*)commonrender;
971                         transition_input = &vrender->transition_temp;
972                 }
973                 else
974                 {
975                         transition_input = &transition_temp;
976                 }
977
978                 if((*transition_input) &&
979                         ((*transition_input)->get_w() != track->track_w ||
980                         (*transition_input)->get_h() != track->track_h))
981                 {
982                         delete (*transition_input);
983                         (*transition_input) = 0;
984                 }
985
986 // Load incoming frame
987                 if(!(*transition_input))
988                 {
989                         (*transition_input) =
990                                 new VFrame(track->track_w, track->track_h,
991                                         get_edl()->session->color_model);
992                 }
993
994                 (*transition_input)->copy_stacks(output);
995
996 //printf("VModule::render %d\n", __LINE__);
997                 result = import_frame((*transition_input),
998                         current_edit,
999                         start_position,
1000                         frame_rate,
1001                         direction,
1002                         use_opengl);
1003
1004
1005 // Load transition buffer
1006                 previous_edit = (VEdit*)current_edit->previous;
1007
1008                 result |= import_frame(output,
1009                         previous_edit,
1010                         start_position,
1011                         frame_rate,
1012                         direction,
1013                         use_opengl);
1014 //printf("VModule::render %d\n", __LINE__);
1015
1016 // printf("VModule::render %d %p %p %p %p\n",
1017 // __LINE__,
1018 // (*transition_input),
1019 // (*transition_input)->get_pbuffer(),
1020 // output,
1021 // output->get_pbuffer());
1022
1023
1024 // Execute plugin with transition_input and output here
1025                 if(renderengine)
1026                         transition_server->set_use_opengl(use_opengl, renderengine->video);
1027                 transition_server->process_transition((*transition_input),
1028                         output,
1029                         (direction == PLAY_FORWARD) ?
1030                                 (start_position_project - current_edit->startproject) :
1031                                 (start_position_project - current_edit->startproject - 1),
1032                         transition->length);
1033         }
1034         else
1035         {
1036 // Load output buffer
1037                 result = import_frame(output,
1038                         current_edit,
1039                         start_position,
1040                         frame_rate,
1041                         direction,
1042                         use_opengl);
1043         }
1044
1045         Auto *current = 0;
1046         MaskAutos *keyframe_set =
1047                 (MaskAutos*)track->automation->autos[AUTOMATION_MASK];
1048         int64_t mask_position = !renderengine ? start_position :
1049                 renderengine->vrender->current_position;
1050         MaskAuto *keyframe =
1051                 (MaskAuto*)keyframe_set->get_prev_auto(mask_position, direction, current);
1052
1053         if( keyframe->apply_before_plugins ) {
1054                 VDeviceX11 *x11_device = 0;
1055                 if(use_opengl && renderengine && renderengine->video) {
1056                         x11_device = (VDeviceX11*)renderengine->video->get_output_base();
1057                         if( !x11_device->can_mask(mask_position, keyframe_set) )
1058                                 use_opengl = 0;
1059                 }
1060                 if( use_opengl && x11_device ) {
1061                         x11_device->do_mask(output, mask_position, keyframe_set,
1062                                         keyframe, keyframe);
1063                 }
1064                 else {
1065                         if( !masker ) {
1066                                 int cpus = renderengine ?
1067                                         renderengine->preferences->processors :
1068                                         plugin_array->mwindow->preferences->processors;
1069                                 masker = new MaskEngine(cpus);
1070                         }
1071                         masker->do_mask(output, mask_position, keyframe_set, keyframe, keyframe);
1072                 }
1073         }
1074
1075         return result;
1076 }
1077
1078
1079
1080
1081
1082
1083 void VModule::create_objects()
1084 {
1085         Module::create_objects();
1086 }
1087
1088
1089
1090
1091
1092