X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fvmodule.C;h=ce7ecadc59529194233ade5524569f8218d4ab90;hp=bdf0c7d8f729d5523d346696f31e6abe6778f835;hb=13a039ef755e81e65c9479b4b615fd89bfe3e038;hpb=9fed7535470aa37781733db836068da3b4c17a0d diff --git a/cinelerra-5.1/cinelerra/vmodule.C b/cinelerra-5.1/cinelerra/vmodule.C index bdf0c7d8..ce7ecadc 100644 --- a/cinelerra-5.1/cinelerra/vmodule.C +++ b/cinelerra-5.1/cinelerra/vmodule.C @@ -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 -#include "interlacemodes.h" #include "maskengine.h" #include "automation.h" @@ -177,21 +177,15 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit, 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 { @@ -225,73 +219,50 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit, //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; 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; +// 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 { + 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. @@ -306,24 +277,53 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit, // 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; // Get source position in nested frame rate in direction of playback. nested_position = Units::to_int64(position * nested_edl->session->frame_rate / @@ -368,38 +368,6 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit, // 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"); - } // file -> temp -> output if( !EQUIV(in_x, 0) || @@ -414,43 +382,24 @@ int VModule::import_frame(VFrame *output, VEdit *current_edit, !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 +// 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 @@ -665,9 +614,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); } } @@ -726,6 +677,7 @@ int VModule::render(VFrame *output, VEdit* previous_edit = 0; //printf("VModule::render %d %p %ld %d\n", __LINE__, current_edit, start_position_project, direction); + 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, @@ -787,14 +739,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 @@ -815,8 +771,14 @@ int VModule::render(VFrame *output, VDeviceX11 *x11_device = 0; 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,