X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fplaybackengine.C;h=71126cf82810c6fce05b7c2a1aa9dae7ce4c273b;hp=aff5e579a729389f4dfed9366ff5e8ab4ff91858;hb=aa9374b902768107ebda0cffe739325ffed372f6;hpb=3bf30d220f7855b995b887dc10812ae3780e6805;ds=sidebyside diff --git a/cinelerra-5.1/cinelerra/playbackengine.C b/cinelerra-5.1/cinelerra/playbackengine.C index aff5e579..71126cf8 100644 --- a/cinelerra-5.1/cinelerra/playbackengine.C +++ b/cinelerra-5.1/cinelerra/playbackengine.C @@ -22,6 +22,7 @@ #include "bchash.h" #include "bcsignals.h" #include "cache.h" +#include "canvas.h" #include "condition.h" #include "edl.h" #include "edlsession.h" @@ -56,16 +57,19 @@ PlaybackEngine::PlaybackEngine(MWindow *mwindow, Canvas *output) command->command = STOP; next_command = new TransportCommand(); next_command->change_type = CHANGE_ALL; - curr_command = new TransportCommand(); stop_command = new TransportCommand(); stop_command->command = STOP; + stop_command->realtime = 1; + sent_command = new TransportCommand(); + sent_command->command = -1; + send_active = 0; tracking_lock = new Mutex("PlaybackEngine::tracking_lock"); renderengine_lock = new Mutex("PlaybackEngine::renderengine_lock"); tracking_done = new Condition(1, "PlaybackEngine::tracking_done"); pause_lock = new Condition(0, "PlaybackEngine::pause_lock"); start_lock = new Condition(0, "PlaybackEngine::start_lock"); - input_lock = new Condition(1, "PlaybackEngine::input_lock"); - output_lock = new Condition(0, "PlaybackEngine::output_lock", 1); + input_lock = new Condition(1, "PlaybackEngine::input_lock"); + output_lock = new Condition(0, "PlaybackEngine::output_lock", 1); render_engine = 0; debug = 0; @@ -74,9 +78,7 @@ PlaybackEngine::PlaybackEngine(MWindow *mwindow, Canvas *output) PlaybackEngine::~PlaybackEngine() { done = 1; - transport_stop(); - interrupt_playback(); - + output_lock->unlock(); Thread::join(); delete preferences; delete_render_engine(); @@ -89,10 +91,10 @@ PlaybackEngine::~PlaybackEngine() delete renderengine_lock; delete command; delete next_command; - delete curr_command; delete stop_command; - delete input_lock; - delete output_lock; + delete sent_command; + delete input_lock; + delete output_lock; } void PlaybackEngine::create_objects() @@ -128,26 +130,25 @@ int PlaybackEngine::create_render_engine() void PlaybackEngine::delete_render_engine() { renderengine_lock->lock("PlaybackEngine::delete_render_engine"); - delete render_engine; - render_engine = 0; + delete render_engine; render_engine = 0; renderengine_lock->unlock(); } void PlaybackEngine::arm_render_engine() { - if(render_engine) + if( render_engine ) render_engine->arm_command(command); } void PlaybackEngine::start_render_engine() { - if(render_engine) render_engine->start_command(); + if( render_engine ) + render_engine->start_command(); } void PlaybackEngine::wait_render_engine() { - if(command->realtime && render_engine) - { + if( command->realtime && render_engine ) { render_engine->join(); } } @@ -163,16 +164,14 @@ void PlaybackEngine::create_cache() void PlaybackEngine::perform_change() { - switch( command->change_type ) - { + switch( command->change_type ) { case CHANGE_ALL: create_cache(); case CHANGE_EDL: create_render_engine(); + break; case CHANGE_PARAMS: - if(command->change_type != CHANGE_EDL && - (uint32_t)command->change_type != CHANGE_ALL) - render_engine->get_edl()->synchronize_params(command->get_edl()); + render_engine->get_edl()->synchronize_params(command->get_edl()); case CHANGE_NONE: break; } @@ -182,14 +181,14 @@ void PlaybackEngine::sync_parameters(EDL *edl) { // TODO: lock out render engine from keyframe deletions command->get_edl()->synchronize_params(edl); - if(render_engine) render_engine->get_edl()->synchronize_params(edl); + if( render_engine ) + render_engine->get_edl()->synchronize_params(edl); } - void PlaybackEngine::interrupt_playback(int wait_tracking) { renderengine_lock->lock("PlaybackEngine::interrupt_playback"); - if(render_engine) + if( render_engine ) render_engine->interrupt_playback(); renderengine_lock->unlock(); @@ -197,22 +196,19 @@ void PlaybackEngine::interrupt_playback(int wait_tracking) pause_lock->unlock(); // Wait for tracking to finish if it is running - if(wait_tracking) - { + if( wait_tracking ) { tracking_done->lock("PlaybackEngine::interrupt_playback"); tracking_done->unlock(); } } - // Return 1 if levels exist int PlaybackEngine::get_output_levels(double *levels, long position) { int result = 0; - if(render_engine && render_engine->do_audio) - { - result = 1; + if( render_engine && render_engine->do_audio ) { render_engine->get_output_levels(levels, position); + result = 1; } return result; } @@ -221,10 +217,9 @@ int PlaybackEngine::get_output_levels(double *levels, long position) int PlaybackEngine::get_module_levels(ArrayList *module_levels, long position) { int result = 0; - if(render_engine && render_engine->do_audio) - { - result = 1; + if( render_engine && render_engine->do_audio ) { render_engine->get_module_levels(module_levels, position); + result = 1; } return result; } @@ -289,10 +284,8 @@ double PlaybackEngine::get_tracking_position() // Don't interpolate when every frame is played. - if(command->get_edl()->session->video_every_frame && - render_engine && - render_engine->do_video) - { + if( command->get_edl()->session->video_every_frame && + render_engine && render_engine->do_video ) { result = tracking_position; } else @@ -366,14 +359,18 @@ void PlaybackEngine::run() while( !done ) { // Wait for current command to finish output_lock->lock("PlaybackEngine::run"); - wait_render_engine(); - + if( done ) break; // Read the new command input_lock->lock("PlaybackEngine::run"); - if( done ) return; - command->copy_from(curr_command); + command->copy_from(sent_command); +//printf("sent command=%d\n", sent_command->command); + int active = this->send_active; + this->send_active = 0; input_lock->unlock(); -//printf("PlaybackEngine::run 1 %d\n", command->command); + if( !active ) continue; + + interrupt_playback(0); + wait_render_engine(); switch( command->command ) { // Parameter change only @@ -404,32 +401,38 @@ void PlaybackEngine::run() // fall through default: is_playing_back = 1; - perform_change(); arm_render_engine(); // Start tracking after arming so the tracking position doesn't change. // The tracking for a single frame command occurs during PAUSE init_tracking(); - + clear_output(); // Dispatch the command start_render_engine(); break; } - - //printf("PlaybackEngine::run 100\n"); } } +void PlaybackEngine::clear_output() +{ + BC_WindowBase *cwdw = output->get_canvas(); + if( !cwdw ) return; + cwdw->lock_window("PlaybackEngine::clear_output"); + output->clear(); + cwdw->unlock_window(); +} -void PlaybackEngine::stop_playback(int wait) +void PlaybackEngine::stop_playback(int wait_tracking) { - transport_stop(); - interrupt_playback(wait); + transport_stop(wait_tracking); renderengine_lock->lock("PlaybackEngine::stop_playback"); - if(render_engine) + if( render_engine ) { + render_engine->interrupt_playback(); render_engine->wait_done(); + } renderengine_lock->unlock(); } @@ -438,13 +441,14 @@ void PlaybackEngine::send_command(int command, EDL *edl, int wait_tracking, int { //printf("PlaybackEngine::send_command 1 %d\n", command); // Stop requires transferring the output buffer to a refresh buffer. - int do_stop = 0, do_resume = 0; - int curr_command = this->command->command; + int do_stop = 0; + int curr_command = is_playing_back ? this->command->command : STOP; int curr_single_frame = TransportCommand::single_frame(curr_command); int curr_audio = this->command->toggle_audio ? !curr_single_frame : curr_single_frame; int single_frame = TransportCommand::single_frame(command); int next_audio = next_command->toggle_audio ? !single_frame : single_frame; + float next_speed = next_command->speed; // Dispatch command switch( command ) { @@ -458,18 +462,17 @@ void PlaybackEngine::send_command(int command, EDL *edl, int wait_tracking, int case FAST_FWD: case CURRENT_FRAME: case LAST_FRAME: - if( curr_command == command && !next_command->speed && - !curr_single_frame && curr_audio == next_audio ) { +// run shuttle as no prev command + if( next_speed ) curr_command = COMMAND_NONE; // Same direction pressed twice, not shuttle, and no change in audio state, Stop - do_stop = 1; - break; - } + if( curr_command == command && !curr_single_frame && + curr_audio == next_audio ) { do_stop = 1; break; } + // Resume or change direction switch( curr_command ) { default: - transport_stop(); - interrupt_playback(wait_tracking); - do_resume = 1; + transport_stop(0); + next_command->resume = 1; // fall through case STOP: case COMMAND_NONE: @@ -478,7 +481,6 @@ void PlaybackEngine::send_command(int command, EDL *edl, int wait_tracking, int case CURRENT_FRAME: case LAST_FRAME: next_command->realtime = 1; - next_command->resume = do_resume; // Start from scratch transport_command(command, CHANGE_NONE, edl, use_inout); break; @@ -494,45 +496,58 @@ void PlaybackEngine::send_command(int command, EDL *edl, int wait_tracking, int } if( do_stop ) { - transport_stop(); - interrupt_playback(wait_tracking); + transport_stop(wait_tracking); } } -int PlaybackEngine::transport_stop() +int PlaybackEngine::put_command(TransportCommand *command, int reset) { - input_lock->lock("PlaybackEngine::transport_stop 1"); - curr_command->copy_from(stop_command); - input_lock->unlock(); + input_lock->lock("PlaybackEngine::put_command"); + int prev_change_type = sent_command->change_type; + sent_command->copy_from(command); +// run only last command, sum change type + if( send_active ) + sent_command->change_type |= prev_change_type; + send_active = 1; + if( reset ) command->reset(); output_lock->unlock(); + input_lock->unlock(); + return 0; +} + +int PlaybackEngine::transport_stop(int wait_tracking) +{ + put_command(stop_command, 0); + if( wait_tracking ) { + tracking_done->lock("PlaybackEngine::transport_stop"); + tracking_done->unlock(); + } +//printf("send: %d (STOP) 0\n", STOP); return 0; } int PlaybackEngine::transport_command(int command, int change_type, EDL *new_edl, int use_inout) { - input_lock->lock("PlaybackEngine::transport_command 1"); next_command->command = command; next_command->change_type |= change_type; if( new_edl ) { // Just change the EDL if the change requires it because renderengine // structures won't point to the new EDL otherwise and because copying the // EDL for every cursor movement is slow. - switch( change_type ) { - case CHANGE_EDL: - case CHANGE_ALL: + if( change_type & CHANGE_EDL ) next_command->get_edl()->copy_all(new_edl); - break; - case CHANGE_PARAMS: + else if( change_type & CHANGE_PARAMS ) next_command->get_edl()->synchronize_params(new_edl); - break; - } next_command->set_playback_range(new_edl, use_inout, preferences->forward_render_displacement); } - curr_command->copy_from(next_command); - next_command->reset(); - input_lock->unlock(); - output_lock->unlock(); + put_command(next_command, 1); +//static const char *types[] = { "NONE", +// "FRAME_FWD", "NORMAL_FWD", "FAST_FWD", "FRAME_REV", "NORMAL_REV", "FAST_REV", +// "STOP", "PAUSE", "SLOW_FWD", "SLOW_REV", "REWIND", "GOTO_END", "CURRENT_FRAME", +// "LAST_FRAME" }; +//printf("send= %d (%s) %d\n", sent_command->command, +// types[sent_command->command], sent_command->locked); return 0; }