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