Credit Andrew - fix vorbis audio which was scratchy and ensure aging plugin does...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / vmodule.C
index f3cc19c6874dc8f92a64988295f480c7ebc6ff98..1829c404a2b9522cd73a8c10e1a03704316bc19e 100644 (file)
@@ -2,6 +2,7 @@
 /*
  * CINELERRA
  * Copyright (C) 2009-2013 Adam Williams <broadcast at earthling dot net>
+ * Copyright (C) 2003-2016 Cinelerra CV contributors
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,6 +33,7 @@
 #include "file.h"
 #include "filexml.h"
 #include "floatautos.h"
+#include "mainerror.h"
 #include "maskauto.h"
 #include "maskautos.h"
 #include "mwindow.h"
@@ -103,10 +105,10 @@ CICache* VModule::get_cache()
 int VModule::import_frame(VFrame *output, VEdit *current_edit,
        int64_t input_position, double frame_rate, int direction, int use_opengl)
 {
-       int64_t direction_position;
+       int64_t direction_position=0;
 // Translation of edit
-       float in_x, in_y, in_w, in_h;
-       float out_x, out_y, out_w, out_h;
+       float in_x=0.0, in_y=0.0, in_w=0.0, in_h=0.0;
+       float out_x=0.0, out_y=0.0, out_w=0.0, out_h=0.0;
        int result = 0;
        const int debug = 0;
        double edl_rate = get_edl()->session->frame_rate;
@@ -177,7 +179,7 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit,
                                nested_renderengine = 0;
                        }
                        if( !nested_command )
-                               nested_command = new TransportCommand;
+                               nested_command = new TransportCommand(get_preferences());
                        nested_command->command = command;
                        nested_command->get_edl()->copy_all(nested_edl);
                        nested_command->change_type = CHANGE_ALL;
@@ -236,32 +238,26 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit,
 // Make positions based on requested frame rate.
                        int64_t position = Units::to_int64((double)pos * frame_rate / edl_rate);
 
-                       int64_t max_position;
+                       int64_t video_length;
                        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);
+                               video_length = file->get_video_length();
                        }
                        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);
+                               video_length = nested_edl->tracks->total_length();
                        }
-                       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);
 
-                       int use_cache = renderengine &&
-                               ( renderengine->command->single_frame() ||
-                                 renderengine->command->get_direction() == PLAY_REVERSE );
+                       int use_cache = renderengine->command->single_frame() ? 1 :
+                               renderengine->command->get_direction() == PLAY_REVERSE ? -1 : 0;
 
 //                     int use_asynchronous = !use_cache &&
 //                             renderengine &&
@@ -277,12 +273,11 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit,
 //                             else
                                        file->stop_video_thread();
 
-// cache transitions
                                VEdit *vnext = (VEdit *)current_edit->next;
                                pos = Units::to_int64((double)input_position / frame_rate * edl_rate);
-                               if( renderengine && renderengine->preferences->cache_transitions &&
-                                   renderengine->command->get_direction() == PLAY_FORWARD &&
-                                   current_edit->next && current_edit->next->transition &&
+                               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);
@@ -303,15 +298,19 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit,
                                                curr_pos += current_edit->startsource;
                                                int64_t norm_pos = Units::to_int64((double)curr_pos *
                                                        current_edit->asset->frame_rate / edl_rate);
-                                               VFrame *cache_frame = file->new_cache_frame(input, norm_pos, first_frame);
-                                               if( cache_frame ) {
-                                                       file->set_video_position(norm_pos, 0);
-                                                       result = file->read_frame(cache_frame);
-                                                       file->put_cache_frame();
+                                               if( norm_pos < 0 || video_length < 0 )
+                                                       norm_pos = 0;
+                                               else if( norm_pos >= video_length )
+                                                       norm_pos = video_length-1;
+                                               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
                                                }
-                                               else if( first_frame ) // already loaded
-                                                       break;
-                                               first_frame = 0;
+                                               file->set_cache_frames(1);
+                                               file->set_video_position(norm_pos, 0);
+                                               result = file->read_frame(input);
                                                ++pos;  --count;
                                        }
                                        use_cache = 1;
@@ -319,6 +318,10 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit,
 
                                int64_t normalized_position = Units::to_int64((double)position *
                                        current_edit->asset->frame_rate / frame_rate);
+                               if( normalized_position < 0 || video_length < 0 )
+                                       normalized_position = 0;
+                               else if( normalized_position >= video_length )
+                                       normalized_position = video_length-1;
 //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);
@@ -396,9 +399,11 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit,
                                                __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
@@ -613,9 +618,11 @@ if( debug ) printf("VModule::import_frame %d %d %d %d %d %d %d\n",
                                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);
                                }
                        }
@@ -736,14 +743,18 @@ int VModule::render(VFrame *output,
 // (*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 {
 // Load output buffer