detect missing transitions, dont draw transitions if show off, obey audio transition...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / vmodule.C
index 3ef17f0436d714bf0aa4175ed9f6e292a3f1cf89..ce7ecadc59529194233ade5524569f8218d4ab90 100644 (file)
@@ -32,6 +32,7 @@
 #include "file.h"
 #include "filexml.h"
 #include "floatautos.h"
+#include "mainerror.h"
 #include "maskauto.h"
 #include "maskautos.h"
 #include "mwindow.h"
@@ -56,7 +57,6 @@
 #include "vplugin.h"
 #include "vtrack.h"
 #include <string.h>
-#include "interlacemodes.h"
 #include "maskengine.h"
 #include "automation.h"
 
@@ -75,9 +75,9 @@ VModule::VModule(RenderEngine *renderengine,
 
 VModule::~VModule()
 {
-       if(overlay_temp) delete overlay_temp;
-       if(input_temp) delete input_temp;
-       if(transition_temp) delete transition_temp;
+       if( overlay_temp ) delete overlay_temp;
+       if( input_temp ) delete input_temp;
+       if( transition_temp ) delete transition_temp;
        delete masker;
 }
 
@@ -94,17 +94,13 @@ int VModule::get_buffer_size()
 
 CICache* VModule::get_cache()
 {
-       if(renderengine)
+       if( renderengine )
                return renderengine->get_vcache();
        else
                return cache;
 }
 
 
-
-
-
-
 int VModule::import_frame(VFrame *output, VEdit *current_edit,
        int64_t input_position, double frame_rate, int direction, int use_opengl)
 {
@@ -119,95 +115,79 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit,
        int64_t input_position_project = Units::to_int64(input_position *
                edl_rate / frame_rate + 0.001);
 
-       if(!output) printf("VModule::import_frame %d output=%p\n", __LINE__, output);
+       if( !output ) printf("VModule::import_frame %d output=%p\n", __LINE__, output);
        //output->dump_params();
 
-       if(debug) printf("VModule::import_frame %d this=%p input_position=%lld direction=%d\n",
+       if( debug ) printf("VModule::import_frame %d this=%p input_position=%lld direction=%d\n",
                __LINE__, this, (long long)input_position, direction);
 
 // Convert to position corrected for direction
        direction_position = input_position;
-       if(direction == PLAY_REVERSE) {
+       if( direction == PLAY_REVERSE ) {
                if( direction_position > 0 ) direction_position--;
                if( input_position_project > 0 ) input_position_project--;
        }
-       if(!output) printf("VModule::import_frame %d output=%p\n", __LINE__, output);
+       if( !output ) printf("VModule::import_frame %d output=%p\n", __LINE__, output);
 
        VDeviceX11 *x11_device = 0;
-       if(use_opengl)
-       {
-               if(renderengine && renderengine->video)
-               {
+       if( use_opengl ) {
+               if( renderengine && renderengine->video ) {
                        x11_device = (VDeviceX11*)renderengine->video->get_output_base();
                        output->set_opengl_state(VFrame::RAM);
-                       if(!x11_device) use_opengl = 0;
+                       if( !x11_device ) use_opengl = 0;
                }
        }
 
-       if(!output) printf("VModule::import_frame %d output=%p x11_device=%p nested_edl=%p\n",
+       if( !output ) printf("VModule::import_frame %d output=%p x11_device=%p nested_edl=%p\n",
                __LINE__, output, x11_device, nested_edl);
 
-       if(debug) printf("VModule::import_frame %d current_edit=%p\n",
+       if( debug ) printf("VModule::import_frame %d current_edit=%p\n",
                __LINE__, current_edit);
 
 // Load frame into output
 
 // Create objects for nested EDL
-       if(current_edit && current_edit->nested_edl) {
+       if( current_edit && current_edit->nested_edl ) {
                int command;
-               if(debug) printf("VModule::import_frame %d nested_edl=%p current_edit->nested_edl=%p\n",
+               if( debug ) printf("VModule::import_frame %d nested_edl=%p current_edit->nested_edl=%p\n",
                        __LINE__, nested_edl, current_edit->nested_edl);
 
 // Convert requested direction to command
                if( renderengine->command->command == CURRENT_FRAME ||
-                   renderengine->command->command == LAST_FRAME )
-               {
+                   renderengine->command->command == LAST_FRAME ) {
                        command = renderengine->command->command;
                }
                else
-               if(direction == PLAY_REVERSE)
-               {
-                       if(renderengine->command->single_frame())
+               if( direction == PLAY_REVERSE ) {
+                       if( renderengine->command->single_frame() )
                                command = SINGLE_FRAME_REWIND;
                        else
                                command = NORMAL_REWIND;
                }
-               else
-               {
-                       if(renderengine->command->single_frame())
+               else {
+                       if( renderengine->command->single_frame() )
                                command = SINGLE_FRAME_FWD;
                        else
                                command = NORMAL_FWD;
                }
 
-               if(!nested_edl || nested_edl->id != current_edit->nested_edl->id)
-               {
+               if( !nested_edl || nested_edl->id != current_edit->nested_edl->id ) {
                        nested_edl = current_edit->nested_edl;
-                       if(nested_renderengine)
-                       {
+                       if( nested_renderengine ) {
                                delete nested_renderengine;
                                nested_renderengine = 0;
                        }
-
-                       if(!nested_command)
-                       {
+                       if( !nested_command )
                                nested_command = new TransportCommand;
-                       }
-
-
-                       if(!nested_renderengine)
-                       {
-                               nested_command->command = command;
-                               nested_command->get_edl()->copy_all(nested_edl);
-                               nested_command->change_type = CHANGE_ALL;
-                               nested_command->realtime = renderengine->command->realtime;
-                               nested_renderengine = new RenderEngine(0, get_preferences(), 0, 1);
-                               nested_renderengine->set_vcache(get_cache());
-                               nested_renderengine->arm_command(nested_command);
-                       }
+                       nested_command->command = command;
+                       nested_command->get_edl()->copy_all(nested_edl);
+                       nested_command->change_type = CHANGE_ALL;
+                       nested_command->realtime = renderengine->command->realtime;
+                       nested_renderengine = new RenderEngine(0, get_preferences(), 0, 1);
+                       nested_renderengine->set_vcache(get_cache());
+                       nested_renderengine->arm_command(nested_command);
                }
-               else
-               {
+               else {
 
 // Update nested command
                        nested_renderengine->command->command = command;
@@ -217,11 +197,10 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit,
 // Update nested video driver for opengl
                nested_renderengine->video = renderengine->video;
        }
-       else
-       {
+       else {
                nested_edl = 0;
        }
-       if(debug) printf("VModule::import_frame %d\n", __LINE__);
+       if( debug ) printf("VModule::import_frame %d\n", __LINE__);
 
        if( output ) {
                if( use_opengl )
@@ -232,86 +211,58 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit,
        else
                printf("VModule::import_frame %d output=%p\n", __LINE__, output);
 
-       if(current_edit &&
+       if( current_edit &&
                (current_edit->asset ||
-               (current_edit->nested_edl && nested_renderengine->vrender)))
-       {
+               (current_edit->nested_edl && nested_renderengine->vrender)) ) {
                File *file = 0;
 
 //printf("VModule::import_frame %d cache=%p\n", __LINE__, get_cache());
                if( current_edit->asset ) {
                        get_cache()->age();
-                       file = get_cache()->check_out(current_edit->asset,
-                               get_edl());
+                       file = get_cache()->check_out(current_edit->asset, get_edl());
 //                     get_cache()->dump();
                }
 
 // File found
-               if(file || nested_edl)
-               {
-// Make all positions based on requested frame rate.
-                       int64_t edit_startproject = Units::to_int64(current_edit->startproject *
-                               frame_rate /
-                               edl_rate);
-                       int64_t edit_startsource = Units::to_int64(current_edit->startsource *
-                               frame_rate /
-                               edl_rate);
-// Source position going forward
-                       uint64_t position = direction_position -
-                               edit_startproject +
-                               edit_startsource;
+               if( file || nested_edl ) {
                        int64_t nested_position = 0;
-
-
-
-
-
-// apply speed curve to source position so the timeline agrees with the playback
-                       if(track->has_speed())
-                       {
-// integrate position from start of edit.
-                               double speed_position = edit_startsource;
-                               FloatAutos *speed_autos = (FloatAutos*)track->automation->autos[AUTOMATION_SPEED];
-                               speed_position += speed_autos->automation_integral(edit_startproject,
-                                               direction_position-edit_startproject, PLAY_FORWARD);
-//printf("VModule::import_frame %d %lld %lld\n", __LINE__, position, (int64_t)speed_position);
-                               position = (int64_t)speed_position;
-                       }
-
-
-
-
-
-                       int asset_w;
-                       int asset_h;
-                       if(debug) printf("VModule::import_frame %d\n", __LINE__);
-
-
-// maybe apply speed curve here, so timeline reflects actual playback
-
-
-
-// if we hit the end of stream, freeze at last frame
-                       uint64_t max_position = 0;
-                       if(file)
-                       {
+// Source position going forward, in edl framerate
+                       int64_t pos = Units::to_int64((double)direction_position / frame_rate * edl_rate);
+                       int64_t len = pos - current_edit->startproject;
+                       FloatAutos *speed_autos = !track->has_speed() ? 0 :
+                               (FloatAutos*)track->automation->autos[AUTOMATION_SPEED];
+                       if( speed_autos && len > 0 )
+                               len = speed_autos->automation_integral(current_edit->startproject, len, PLAY_FORWARD);
+                       pos = current_edit->startsource + len;
+// Make positions based on requested frame rate.
+                       int64_t position = Units::to_int64((double)pos * frame_rate / edl_rate);
+
+                       int64_t max_position;
+                       int asset_w, asset_h;
+                       if( file ) {
+                               asset_w = current_edit->asset->width;
+                               asset_h = current_edit->asset->height;
                                max_position = Units::to_int64((double)file->get_video_length() *
-                                       frame_rate /
-                                       current_edit->asset->frame_rate - 1);
+                                       frame_rate / current_edit->asset->frame_rate - 1);
                        }
-                       else
-                       {
+                       else {
+                               asset_w = nested_edl->session->output_w;
+                               asset_h = nested_edl->session->output_h;
                                max_position = Units::to_int64(nested_edl->tracks->total_length() *
                                        frame_rate - 1);
                        }
+                       if( max_position < 0 ) max_position = 0;
+// if we hit the end of stream, freeze at last frame
+                       CLAMP(position, 0, max_position);
 
+                       VFrame *&input = commonrender ?
+                               ((VRender*)commonrender)->input_temp : // Realtime playback
+                               input_temp ; // Menu effect
+                       VFrame::get_temp(input, asset_w, asset_h, get_edl()->session->color_model);
 
-                       if(position > max_position) position = max_position;
-                       else
-                       if(position < 0) position = 0;
+                       int use_cache = renderengine->command->single_frame() ? 1 :
+                               renderengine->command->get_direction() == PLAY_REVERSE ? -1 : 0;
 
-                       int use_cache = renderengine &&
-                               renderengine->command->single_frame();
 //                     int use_asynchronous = !use_cache &&
 //                             renderengine &&
 // Try to make rendering go faster.
@@ -319,45 +270,71 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit,
 ////                           renderengine->command->realtime &&
 //                             renderengine->get_edl()->session->video_asynchronous;
 
-                       if(file)
-                       {
-                               if(debug) printf("VModule::import_frame %d\n", __LINE__);
-//                             if(use_asynchronous)
+                       if( file ) {
+                               if( debug ) printf("VModule::import_frame %d\n", __LINE__);
+//                             if( use_asynchronous )
 //                                     file->start_video_decode_thread();
 //                             else
                                        file->stop_video_thread();
 
-                               int64_t normalized_position = Units::to_int64(position *
-                                       current_edit->asset->frame_rate /
-                                       frame_rate);
-// printf("VModule::import_frame %d %lld %lld\n",
-// __LINE__,
-// position,
-// normalized_position);
+                               VEdit *vnext = (VEdit *)current_edit->next;
+                               pos = Units::to_int64((double)input_position / frame_rate * edl_rate);
+                               if( renderengine->preferences->cache_transitions && !use_cache &&
+// cache transitions, not caching and inside transition 
+                                   vnext && vnext->transition && vnext->transition->on &&
+                                   file->get_video_length() >= 0 && pos >= vnext->startproject &&
+                                   pos < vnext->startproject + vnext->transition->length ) {
+                                       file->set_cache_frames(0);
+                                       file->set_layer(current_edit->channel);
+                                       VEdit *vnext = (VEdit *)current_edit->next;
+                                       Track *track = current_edit->track;
+                                       FloatAutos *speed_autos = (FloatAutos*)(track->has_speed() ?
+                                               track->automation->autos[AUTOMATION_SPEED] : 0);
+                                       int64_t end = vnext->startproject + vnext->transition->length;
+                                       int first_frame = 1;
+                                       int count = renderengine->preferences->cache_size /
+                                               input->get_data_size() / 2;  // try to burn only 1/2 of cache
+                                       while( !result && pos < end && count > 0 ) {
+                                               int64_t curr_pos = pos - current_edit->startproject;
+                                               if( curr_pos > 0 && speed_autos )
+                                                       curr_pos = speed_autos->automation_integral(
+                                                               current_edit->startproject, curr_pos, PLAY_FORWARD);
+                                               curr_pos += current_edit->startsource;
+                                               int64_t norm_pos = Units::to_int64((double)curr_pos *
+                                                       current_edit->asset->frame_rate / edl_rate);
+                                               if( first_frame ) {
+                                                       if( file->get_cache_frame(input, norm_pos) )
+                                                               break;  // if inside a cache run
+                                                       first_frame = 0;
+                                                       file->purge_cache(); // start new run
+                                               }
+                                               file->set_cache_frames(1);
+                                               file->set_video_position(norm_pos, 0);
+                                               result = file->read_frame(input);
+                                               ++pos;  --count;
+                                       }
+                                       use_cache = 1;
+                               }
+
+                               int64_t normalized_position = Units::to_int64((double)position *
+                                       current_edit->asset->frame_rate / frame_rate);
+//printf("VModule::import_frame %d %lld %lld\n", __LINE__, position, normalized_position);
                                file->set_layer(current_edit->channel);
-                               file->set_video_position(normalized_position,
-                                       0);
-                               asset_w = current_edit->asset->width;
-                               asset_h = current_edit->asset->height;
-//printf("VModule::import_frame %d normalized_position=%lld\n", __LINE__, normalized_position);
+                               file->set_video_position(normalized_position, 0);
                        }
-                       else
-                       {
-                               if(debug) printf("VModule::import_frame %d\n", __LINE__);
-                               asset_w = nested_edl->session->output_w;
-                               asset_h = nested_edl->session->output_h;
+                       else {
+                               if( debug ) printf("VModule::import_frame %d\n", __LINE__);
 // Get source position in nested frame rate in direction of playback.
                                nested_position = Units::to_int64(position *
                                        nested_edl->session->frame_rate /
                                        frame_rate);
-                               if(direction == PLAY_REVERSE)
+                               if( direction == PLAY_REVERSE )
                                        nested_position++;
                        }
 
 
 // Auto scale if required
-                       if(output->get_params()->get("AUTOSCALE", 0))
-                       {
+                       if( output->get_params()->get("AUTOSCALE", 0) ) {
                                float autoscale_w = output->get_params()->get("AUTOSCALE_W", 1024);
                                float autoscale_h = output->get_params()->get("AUTOSCALE_H", 1024);
                                float x_scale = autoscale_w / asset_w;
@@ -369,13 +346,11 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit,
                                in_w = asset_w;
                                in_h = asset_h;
 
-                               if(x_scale < y_scale)
-                               {
+                               if( x_scale < y_scale ) {
                                        out_w = in_w * x_scale;
                                        out_h = in_h * x_scale;
                                }
-                               else
-                               {
+                               else {
                                        out_w = in_w * y_scale;
                                        out_h = in_h * y_scale;
                                }
@@ -383,61 +358,16 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit,
                                out_x = track->track_w / 2 - out_w / 2;
                                out_y = track->track_h / 2 - out_h / 2;
                        }
-                       else
+                       else {
 // Apply camera
-                       {
                                ((VTrack*)track)->calculate_input_transfer(asset_w,
-                                       asset_h,
-                                       input_position_project,
-                                       direction,
-                                       in_x,
-                                       in_y,
-                                       in_w,
-                                       in_h,
-                                       out_x,
-                                       out_y,
-                                       out_w,
-                                       out_h);
+                                       asset_h, input_position_project, direction,
+                                       in_x, in_y, in_w, in_h,
+                                       out_x, out_y, out_w, out_h);
                        }
 
 // printf("VModule::import_frame %d %f %d %f %d\n",
-// __LINE__,
-// in_w,
-// asset_w,
-// in_h,
-// asset_h);
-//
-//                     printf("VModule::import_frame 1 [ilace] Project: mode (%d) Asset: autofixoption (%d), mode (%d), method (%d)\n",
-//                     get_edl()->session->interlace_mode,
-//                     current_edit->asset->interlace_autofixoption,
-//                     current_edit->asset->interlace_mode,
-//                     current_edit->asset->interlace_fixmethod);
-
-                       // Determine the interlacing method to use.
-                       int interlace_fixmethod = !current_edit->asset ? ILACE_FIXMETHOD_NONE :
-                                ilaceautofixmethod2(get_edl()->session->interlace_mode,
-                                       current_edit->asset->interlace_autofixoption,
-                                       current_edit->asset->interlace_mode,
-                                       current_edit->asset->interlace_fixmethod);
-//
-//                     char string[BCTEXTLEN];
-//                     ilacefixmethod_to_text(string,interlace_fixmethod);
-//                     printf("VModule::import_frame 1 [ilace] Compensating by using: '%s'\n",string);
-
-                       // Compensate for the said interlacing...
-                       switch (interlace_fixmethod) {
-                               case ILACE_FIXMETHOD_NONE:
-
-                               break;
-                               case ILACE_FIXMETHOD_UPONE:
-                                       out_y--;
-                               break;
-                               case ILACE_FIXMETHOD_DOWNONE:
-                                       out_y++;
-                               break;
-                               default:
-                                       printf("vmodule::importframe WARNING - unknown fix method for interlacing, no compensation in effect\n");
-                       }
+// __LINE__, in_w, asset_w, in_h, asset_h);
 
 // file -> temp -> output
                        if( !EQUIV(in_x, 0) ||
@@ -449,68 +379,31 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit,
                                !EQUIV(out_w, track->track_w) ||
                                !EQUIV(out_h, track->track_h) ||
                                !EQUIV(in_w, asset_w) ||
-                               !EQUIV(in_h, asset_h))
-                       {
+                               !EQUIV(in_h, asset_h)) {
 //printf("VModule::import_frame %d file -> temp -> output\n", __LINE__);
-
-
-
-
 // Get temporary input buffer
-                               VFrame **input = 0;
-// Realtime playback
-                               if(commonrender)
-                               {
-                                       VRender *vrender = (VRender*)commonrender;
-//printf("VModule::import_frame %d vrender->input_temp=%p\n", __LINE__, vrender->input_temp);
-                                       input = &vrender->input_temp;
-                               }
-                               else
-// Menu effect
-                               {
-                                       input = &input_temp;
-                               }
-
-
-                               if((*input) &&
-                                       ((*input)->get_w() != asset_w ||
-                                       (*input)->get_h() != asset_h))
-                               {
-                                       delete (*input);
-                                       (*input) = 0;
-                               }
-
-
-
-
-
-                               if(!(*input))
-                               {
-                                       (*input) =
-                                               new VFrame(asset_w, asset_h,
-                                                       get_edl()->session->color_model);
-                               }
-
-
-
+                               VFrame **input = commonrender ?  // Realtime playback
+                                       &((VRender*)commonrender)->input_temp :
+                                       &input_temp ; // Menu effect
+                               VFrame::get_temp(*input, asset_w, asset_h,
+                                               get_edl()->session->color_model);
                                (*input)->copy_stacks(output);
-
 // file -> temp
-// Cache for single frame only
-                               if(file)
-                               {
-                                       if(debug) printf("VModule::import_frame %d this=%p file=%s\n",
+// Cache for single frame, reverse playback
+                               if( file ) {
+                                       if( debug ) printf("VModule::import_frame %d this=%p file=%s\n",
                                                __LINE__,
                                                this,
                                                current_edit->asset->path);
-                                       if(use_cache) file->set_cache_frames(1);
+                                       if( use_cache )
+                                               file->set_cache_frames(use_cache);
                                        result = file->read_frame((*input));
-                                       if(use_cache) file->set_cache_frames(0);
+                                       if( use_cache )
+                                               file->set_cache_frames(0);
                                        (*input)->set_opengl_state(VFrame::RAM);
                                }
                                else
-                               if(nested_edl)
-                               {
+                               if( nested_edl ) {
 // If the colormodels differ, change input to nested colormodel
                                        int nested_cmodel = nested_renderengine->get_edl()->session->color_model;
                                        int current_cmodel = output->get_color_model();
@@ -518,118 +411,67 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit,
                                        int output_h = output->get_h();
                                        VFrame *input2 = (*input);
 
-                                       if(nested_cmodel != current_cmodel)
-                                       {
+                                       if( nested_cmodel != current_cmodel ) {
 // If opengl, input -> input -> output
-                                               if(use_opengl)
-                                               {
-                                               }
-                                               else
-                                               {
+                                               if( use_opengl ) { }
+                                               else {
 // If software, input2 -> input -> output
 // Use output as a temporary.
                                                        input2 = output;
                                                }
 
-                                               if(debug) printf("VModule::import_frame %d this=%p nested_cmodel=%d\n",
+                                               if( debug ) printf("VModule::import_frame %d this=%p nested_cmodel=%d\n",
                                                        __LINE__,
                                                        this,
                                                        nested_cmodel);
                                                input2->dump();
-                                               input2->reallocate(0,
-                                                       -1,
-                                                       0,
-                                                       0,
-                                                       0,
-                                                       (*input)->get_w(),
-                                                       (*input)->get_h(),
-                                                       nested_cmodel,
-                                                       -1);
+                                               input2->reallocate(0, -1, 0, 0, 0,
+                                                       (*input)->get_w(), (*input)->get_h(),
+                                                       nested_cmodel, -1);
                                                input2->dump();
                                        }
 
 
-                                       if(debug) printf("VModule::import_frame %d this=%p nested_edl=%s input2=%p\n",
-                                               __LINE__,
-                                               this,
-                                               nested_edl->path,
-                                               input2);
+                                       if( debug ) printf("VModule::import_frame %d this=%p nested_edl=%s input2=%p\n",
+                                               __LINE__, this, nested_edl->path, input2);
 
                                        result = nested_renderengine->vrender->process_buffer(
-                                               input2,
-                                               nested_position,
-                                               use_opengl);
+                                               input2, nested_position, use_opengl);
 
-                                       if(debug) printf("VModule::import_frame %d this=%p nested_edl=%s\n",
+                                       if( debug ) printf("VModule::import_frame %d this=%p nested_edl=%s\n",
                                                __LINE__,
                                                this,
                                                nested_edl->path);
 
-                                       if(nested_cmodel != current_cmodel)
-                                       {
-                                               if(debug) printf("VModule::import_frame %d\n", __LINE__);
-                                               if(use_opengl)
-                                               {
+                                       if( nested_cmodel != current_cmodel ) {
+                                               if( debug ) printf("VModule::import_frame %d\n", __LINE__);
+                                               if( use_opengl ) {
 // Change colormodel in hardware.
-                                                       if(debug) printf("VModule::import_frame %d\n", __LINE__);
+                                                       if( debug ) printf("VModule::import_frame %d\n", __LINE__);
                                                        x11_device->convert_cmodel(input2,
                                                                current_cmodel);
 
 // The converted color model is now in hardware, so return the input2 buffer
 // to the expected color model.
-                                                       input2->reallocate(0,
-                                                               -1,
-                                                               0,
-                                                               0,
-                                                               0,
-                                                               (*input)->get_w(),
-                                                               (*input)->get_h(),
-                                                               current_cmodel,
-                                                               -1);
+                                                       input2->reallocate(0, -1, 0, 0, 0,
+                                                               (*input)->get_w(), (*input)->get_h(),
+                                                               current_cmodel, -1);
                                                }
-                                               else
-                                               {
+                                               else {
 // Transfer from input2 to input
-if(debug) printf("VModule::import_frame %d nested_cmodel=%d current_cmodel=%d input2=%p input=%p output=%p\n",
-__LINE__,
-nested_cmodel,
-current_cmodel,
-input2,
-(*input),
-output);
-                                                       BC_CModels::transfer((*input)->get_rows(),
-                                                               input2->get_rows(),
-                                                               0,
-                                                               0,
-                                                               0,
-                                                               0,
-                                                               0,
-                                                               0,
-                                                               0,
-                                                               0,
-                                                           input2->get_w(),
-                                                           input2->get_h(),
-                                                               0,
-                                                               0,
-                                                               (*input)->get_w(),
-                                                               (*input)->get_h(),
-                                                               nested_cmodel,
-                                                               current_cmodel,
-                                                               0,
-                                                               input2->get_w(),
-                                                               (*input)->get_w());
+if( debug ) printf("VModule::import_frame %d nested_cmodel=%d current_cmodel=%d input2=%p input=%p output=%p\n",
+  __LINE__, nested_cmodel, current_cmodel, input2, (*input), output);
+                                                       BC_CModels::transfer((*input)->get_rows(), input2->get_rows(),
+                                                               0, 0, 0, 0, 0, 0,
+                                                               0, 0, input2->get_w(), input2->get_h(),
+                                                               0, 0, (*input)->get_w(), (*input)->get_h(),
+                                                               nested_cmodel, current_cmodel, 0,
+                                                               input2->get_w(), (*input)->get_w());
 //printf("VModule::import_frame %d\n", __LINE__);
 
 // input2 was the output buffer, so it must be restored
-                                               input2->reallocate(0,
-                                                       -1,
-                                                       0,
-                                                       0,
-                                                       0,
-                                                       output_w,
-                                                       output_h,
-                                                       current_cmodel,
-                                                       -1);
+                                               input2->reallocate(0, -1, 0, 0, 0,
+                                                       output_w, output_h, current_cmodel, -1);
 //printf("VModule::import_frame %d\n", __LINE__);
                                                }
                                        }
@@ -640,92 +482,55 @@ output);
                                OverlayFrame *overlayer = 0;
 
 // OpenGL playback uses hardware
-                               if(use_opengl)
-                               {
+                               if( use_opengl ) {
 //printf("VModule::import_frame %d\n", __LINE__);
                                }
-                               else
+                               else if( commonrender ) {
 // Realtime playback
-                               if(commonrender)
-                               {
                                        VRender *vrender = (VRender*)commonrender;
                                        overlayer = vrender->overlayer;
                                }
-                               else
+                               else {
 // Menu effect
-                               {
-                                       if(!plugin_array)
+                                       if( !plugin_array )
                                                printf("VModule::import_frame neither plugin_array nor commonrender is defined.\n");
-                                       if(!overlay_temp)
-                                       {
+                                       if( !overlay_temp ) {
                                                overlay_temp = new OverlayFrame(plugin_array->mwindow->preferences->processors);
                                        }
 
                                        overlayer = overlay_temp;
                                }
 // printf("VModule::import_frame 1 %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f\n",
-//     in_x,
-//     in_y,
-//     in_w,
-//     in_h,
-//     out_x,
-//     out_y,
-//     out_w,
-//     out_h);
+//   in_x, in_y, in_w, in_h, out_x, out_y, out_w, out_h);
 
 // temp -> output
-// for(int j = 0; j < output->get_w() * 3 * 5; j++)
+// for( int j = 0; j < output->get_w() * 3 * 5; j++ )
 //     output->get_rows()[0][j] = 255;
 
-                               if(use_opengl)
-                               {
-                                       x11_device->do_camera(output,
-                                               (*input),
-                                               in_x,
-                                               in_y,
-                                               in_x + in_w,
-                                               in_y + in_h,
-                                               out_x,
-                                               out_y,
-                                               out_x + out_w,
-                                               out_y + out_h);
-if(debug) printf("VModule::import_frame %d %d %d\n",
-__LINE__,
-output->get_opengl_state(),
-(*input)->get_opengl_state());
+                               if( use_opengl ) {
+                                       x11_device->do_camera(output, (*input),
+                                               in_x, in_y, in_x + in_w, in_y + in_h,
+                                               out_x, out_y, out_x + out_w, out_y + out_h);
+if( debug ) printf("VModule::import_frame %d %d %d\n",
+ __LINE__, output->get_opengl_state(), (*input)->get_opengl_state());
                                }
-                               else
-                               {
-
-
-
+                               else {
                                        output->clear_frame();
-
-
 // get_cache()->check_in(current_edit->asset);
 // return;
 
 // TRANSFER_REPLACE is the fastest transfer mode but it has the disadvantage
 // of producing green borders in floating point translation of YUV
                                        int mode = TRANSFER_REPLACE;
-                                       if(get_edl()->session->interpolation_type != NEAREST_NEIGHBOR &&
-                                               BC_CModels::is_yuv(output->get_color_model()))
+                                       if( get_edl()->session->interpolation_type != NEAREST_NEIGHBOR &&
+                                               BC_CModels::is_yuv(output->get_color_model()) )
                                                mode = TRANSFER_NORMAL;
 
-                                       if(debug) printf("VModule::import_frame %d temp -> output\n", __LINE__);
-                                       overlayer->overlay(output,
-                                               (*input),
-                                               in_x,
-                                               in_y,
-                                               in_x + in_w,
-                                               in_y + in_h,
-                                               out_x,
-                                               out_y,
-                                               out_x + out_w,
-                                               out_y + out_h,
-                                               1,
-                                               mode,
-                                               get_edl()->session->interpolation_type);
+                                       if( debug ) printf("VModule::import_frame %d temp -> output\n", __LINE__);
+                                       overlayer->overlay(output, (*input),
+                                               in_x, in_y, in_x + in_w, in_y + in_h,
+                                               out_x, out_y, out_x + out_w, out_y + out_h,
+                                               1, mode, get_edl()->session->interpolation_type);
                                }
                                result = 1;
                                
@@ -736,148 +541,95 @@ output->get_opengl_state(),
 //(*input)->dump_params();
 //output->dump_params();
                        }
-                       else
+                       else {
 // file -> output
-                       {
-                               if(debug) printf("VModule::import_frame %d file -> output nested_edl=%p file=%p\n",
-                                       __LINE__,
-                                       nested_edl,
-                                       file);
-                               if(nested_edl)
-                               {
+                               if( debug ) printf("VModule::import_frame %d file -> output nested_edl=%p file=%p\n",
+                                       __LINE__, nested_edl, file);
+                               if( nested_edl ) {
                                        VFrame **input = &output;
 // If colormodels differ, reallocate output in nested colormodel.
                                        int nested_cmodel = nested_renderengine->get_edl()->session->color_model;
                                        int current_cmodel = output->get_color_model();
 
-if(debug) printf("VModule::import_frame %d nested_cmodel=%d current_cmodel=%d\n",
+if( debug ) printf("VModule::import_frame %d nested_cmodel=%d current_cmodel=%d\n",
 __LINE__,
 nested_cmodel,
 current_cmodel);
 
-                                       if(nested_cmodel != current_cmodel)
-                                       {
-                                               if(use_opengl)
-                                               {
-                                               }
-                                               else
-                                               {
-                                                       if(commonrender)
-                                                       {
+                                       if( nested_cmodel != current_cmodel ) {
+                                               if( use_opengl ) { }
+                                               else {
+                                                       if( commonrender ) {
                                                                input = &((VRender*)commonrender)->input_temp;
                                                        }
-                                                       else
-                                                       {
+                                                       else {
                                                                input = &input_temp;
                                                        }
 
-                                                       if(!(*input)) (*input) = new VFrame;
+                                                       if( !(*input) ) (*input) = new VFrame;
                                                }
 
-                                               (*input)->reallocate(0,
-                                                       -1,
-                                                       0,
-                                                       0,
-                                                       0,
-                                                       output->get_w(),
-                                                       output->get_h(),
-                                                       nested_cmodel,
-                                                       -1);
-if(debug) printf("VModule::import_frame %d\n",
-__LINE__);
+                                               (*input)->reallocate(0, -1, 0, 0, 0,
+                                                       output->get_w(), output->get_h(),
+                                                       nested_cmodel, -1);
+if( debug ) printf("VModule::import_frame %d\n", __LINE__);
 //(*input)->dump();
 //(*input)->clear_frame();
                                        }
 
-if(debug) printf("VModule::import_frame %d %p %p\n",
-__LINE__,
-(*input)->get_rows(),
-(*input));
+if( debug ) printf("VModule::import_frame %d %p %p\n",
+ __LINE__, (*input)->get_rows(), (*input));
                                        result = nested_renderengine->vrender->process_buffer(
-                                               (*input),
-                                               nested_position,
-                                               use_opengl);
-if(debug) printf("VModule::import_frame %d\n",
+                                               (*input), nested_position, use_opengl);
+if( debug ) printf("VModule::import_frame %d\n",
 __LINE__);
 
 // If colormodels differ, change colormodels in opengl if possible.
 // Swap output for temp if not possible.
-                                       if(nested_cmodel != current_cmodel)
-                                       {
-                                               if(use_opengl)
-                                               {
+                                       if( nested_cmodel != current_cmodel ) {
+                                               if( use_opengl ) {
                                                        x11_device->convert_cmodel(output,
                                                                current_cmodel);
 
 // The color model was changed in place, so return output buffer
-                                                       output->reallocate(0,
-                                                               -1,
-                                                               0,
-                                                               0,
-                                                               0,
-                                                               output->get_w(),
-                                                               output->get_h(),
-                                                               current_cmodel,
-                                                               -1);
+                                                       output->reallocate(0, -1, 0, 0, 0,
+                                                               output->get_w(), output->get_h(),
+                                                               current_cmodel, -1);
                                                }
-                                               else
-                                               {
+                                               else {
 // Transfer from temporary to output
-if(debug) printf("VModule::import_frame %d %d %d %d %d %d %d\n",
-__LINE__,
-(*input)->get_w(),
-(*input)->get_h(),
-output->get_w(),
-output->get_h(),
-nested_cmodel,
-current_cmodel);
-                                                       BC_CModels::transfer(output->get_rows(),
-                                                               (*input)->get_rows(),
-                                                               0,
-                                                               0,
-                                                               0,
-                                                               0,
-                                                               0,
-                                                               0,
-                                                               0,
-                                                               0,
-                                                               (*input)->get_w(),
-                                                               (*input)->get_h(),
-                                                               0,
-                                                               0,
-                                                               output->get_w(),
-                                                               output->get_h(),
-                                                               nested_cmodel,
-                                                               current_cmodel,
-                                                               0,
-                                                               (*input)->get_w(),
-                                                               output->get_w());
+if( debug ) printf("VModule::import_frame %d %d %d %d %d %d %d\n",
+  __LINE__, (*input)->get_w(), (*input)->get_h(),
+  output->get_w(), output->get_h(), nested_cmodel, current_cmodel);
+                                                       BC_CModels::transfer(output->get_rows(), (*input)->get_rows(),
+                                                               0, 0, 0, 0, 0, 0,
+                                                               0, 0, (*input)->get_w(), (*input)->get_h(),
+                                                               0, 0, output->get_w(), output->get_h(),
+                                                               nested_cmodel, current_cmodel, 0,
+                                                               (*input)->get_w(), output->get_w());
                                                }
 
                                        }
-
                                }
-                               else
-                               if(file)
-                               {
+                               else if( file ) {
 // Cache single frames
 //memset(output->get_rows()[0], 0xff, 1024);
-                                       if(use_cache) file->set_cache_frames(1);
+                                       if( use_cache )
+                                               file->set_cache_frames(use_cache);
                                        result = file->read_frame(output);
-                                       if(use_cache) file->set_cache_frames(0);
+                                       if( use_cache )
+                                               file->set_cache_frames(0);
                                        output->set_opengl_state(VFrame::RAM);
                                }
                        }
 
-                       if(file)
-                       {
+                       if( file ) {
                                get_cache()->check_in(current_edit->asset);
                                file = 0;
                        }
                }
-               else
+               else {
 // Source not found
-               {
                        result = 1;
                }
 
@@ -886,68 +638,52 @@ current_cmodel);
 //                     get_cache());
 
        }
-       else
+       else {
 // Source is silence
-       {
-               if(debug) printf("VModule::import_frame %d\n", __LINE__);
-               if(use_opengl)
-               {
+               if( debug ) printf("VModule::import_frame %d\n", __LINE__);
+               if( use_opengl ) {
                        x11_device->clear_input(output);
                }
-               else
-               {
+               else {
                        output->clear_frame();
                }
        }
 
-       if(debug) printf("VModule::import_frame %d done\n", __LINE__);
+       if( debug ) printf("VModule::import_frame %d done\n", __LINE__);
 
        return result;
 }
 
 
-
 int VModule::render(VFrame *output,
-       int64_t start_position,
-       int direction,
-       double frame_rate,
-       int use_nudge,
-       int debug_render,
-       int use_opengl)
+       int64_t start_position, int direction, double frame_rate,
+       int use_nudge, int debug_render, int use_opengl)
 {
        int result = 0;
        double edl_rate = get_edl()->session->frame_rate;
 
 //printf("VModule::render %d %ld\n", __LINE__, start_position);
 
-       if(use_nudge) start_position += Units::to_int64(track->nudge *
+       if( use_nudge ) start_position += Units::to_int64(track->nudge *
                frame_rate / edl_rate);
 
        int64_t start_position_project = Units::to_int64(start_position *
                edl_rate / frame_rate + 0.5);
 
-       update_transition(start_position_project,
-               direction);
+       update_transition(start_position_project, direction);
 
        VEdit* current_edit = (VEdit*)track->edits->editof(start_position_project,
-               direction,
-               0);
+               direction, 0);
        VEdit* previous_edit = 0;
 //printf("VModule::render %d %p %ld %d\n", __LINE__, current_edit, start_position_project, direction);
 
-       if(debug_render)
+       Plugin *transition = get_edl()->tracks->plugin_exists(transition_id);
+       if( debug_render )
                printf("    VModule::render %d %d %jd %s transition=%p opengl=%d current_edit=%p output=%p\n",
-                       __LINE__,
-                       use_nudge,
-                       start_position_project,
-                       track->title,
-                       transition,
-                       use_opengl,
-                       current_edit,
-                       output);
-
-       if(!current_edit)
-       {
+                       __LINE__, use_nudge, start_position_project, track->title,
+                       transition, use_opengl, current_edit, output);
+
+       if( !current_edit ) {
                output->clear_frame();
                // We do not apply mask here, since alpha is 0, and neither substracting nor multypling changes it
                // Another mask mode - "addition" should be added to be able to create mask from empty frames
@@ -959,32 +695,27 @@ int VModule::render(VFrame *output,
 
 
 // Process transition
-       if(transition && transition->on)
-       {
+       if( transition && transition->on ) {
 
 // Get temporary buffer
                VFrame **transition_input = 0;
-               if(commonrender)
-               {
+               if( commonrender ) {
                        VRender *vrender = (VRender*)commonrender;
                        transition_input = &vrender->transition_temp;
                }
-               else
-               {
+               else {
                        transition_input = &transition_temp;
                }
 
-               if((*transition_input) &&
+               if( (*transition_input) &&
                        ((*transition_input)->get_w() != track->track_w ||
-                       (*transition_input)->get_h() != track->track_h))
-               {
+                       (*transition_input)->get_h() != track->track_h) ) {
                        delete (*transition_input);
                        (*transition_input) = 0;
                }
 
 // Load incoming frame
-               if(!(*transition_input))
-               {
+               if( !(*transition_input) ) {
                        (*transition_input) =
                                new VFrame(track->track_w, track->track_h,
                                        get_edl()->session->color_model);
@@ -994,51 +725,38 @@ int VModule::render(VFrame *output,
 
 //printf("VModule::render %d\n", __LINE__);
                result = import_frame((*transition_input),
-                       current_edit,
-                       start_position,
-                       frame_rate,
-                       direction,
-                       use_opengl);
+                       current_edit, start_position, frame_rate,
+                       direction, use_opengl);
 
 
 // Load transition buffer
                previous_edit = (VEdit*)current_edit->previous;
 
                result |= import_frame(output,
-                       previous_edit,
-                       start_position,
-                       frame_rate,
-                       direction,
-                       use_opengl);
-//printf("VModule::render %d\n", __LINE__);
-
-// printf("VModule::render %d %p %p %p %p\n",
-// __LINE__,
-// (*transition_input),
-// (*transition_input)->get_pbuffer(),
-// output,
-// output->get_pbuffer());
-
+                       previous_edit, start_position, frame_rate,
+                       direction, use_opengl);
+//printf("VModule::render %d %p %p %p %p\n", __LINE__,
+// (*transition_input), (*transition_input)->get_pbuffer(),
+// output, output->get_pbuffer());
 
+               if( transition_server ) {
 // Execute plugin with transition_input and output here
-               if(renderengine)
-                       transition_server->set_use_opengl(use_opengl, renderengine->video);
-               transition_server->process_transition((*transition_input),
-                       output,
-                       (direction == PLAY_FORWARD) ?
-                               (start_position_project - current_edit->startproject) :
-                               (start_position_project - current_edit->startproject - 1),
-                       transition->length);
+                       if( renderengine )
+                               transition_server->set_use_opengl(use_opengl, renderengine->video);
+                       transition_server->process_transition((*transition_input), output,
+                               (direction == PLAY_FORWARD) ?
+                                       (start_position_project - current_edit->startproject) :
+                                       (start_position_project - current_edit->startproject - 1),
+                               transition->length);
+               }
+               else
+                       eprintf("missing transition plugin: %s\n", transition->title);
        }
-       else
-       {
+       else {
 // Load output buffer
                result = import_frame(output,
-                       current_edit,
-                       start_position,
-                       frame_rate,
-                       direction,
-                       use_opengl);
+                       current_edit, start_position, frame_rate,
+                       direction, use_opengl);
        }
 
        Auto *current = 0;
@@ -1049,12 +767,18 @@ int VModule::render(VFrame *output,
                MaskAuto *keyframe =
                (MaskAuto*)keyframe_set->get_prev_auto(mask_position, direction, current);
 
-       if( keyframe->apply_before_plugins ) {
+       if( keyframe->apply_before_plugins && keyframe->has_active_mask() ) {
                VDeviceX11 *x11_device = 0;
-               if(use_opengl && renderengine && renderengine->video) {
+               if( use_opengl && renderengine && renderengine->video ) {
                        x11_device = (VDeviceX11*)renderengine->video->get_output_base();
-                       if( !x11_device->can_mask(mask_position, keyframe_set) )
+                       if( !x11_device->can_mask(mask_position, keyframe_set) ) {
+                               if( output->get_opengl_state() != VFrame::RAM ) {
+                                       int w = output->get_w(), h = output->get_h();
+                                       x11_device->do_camera(output, output,
+                                               0,0,w,h, 0,0,w,h); // copy to ram
+                               }
                                use_opengl = 0;
+                       }
                }
                if( use_opengl && x11_device ) {
                        x11_device->do_mask(output, mask_position, keyframe_set,
@@ -1075,17 +799,8 @@ int VModule::render(VFrame *output,
 }
 
 
-
-
-
-
 void VModule::create_objects()
 {
        Module::create_objects();
 }
 
-
-
-
-
-