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