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