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