X-Git-Url: https://git.cinelerra-gg.org/git/?p=goodguy%2Fcinelerra.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fplaybackengine.C;h=571afe2a83a174a3eaeeab536182258131839d2b;hp=16f6bd7a73c65bda3ffd6065186063eefe206f58;hb=45a8ba3455cf252332c03533a7590df5267ce9aa;hpb=45dd712aa4b2894f6b2390b4797262831dcdb47a diff --git a/cinelerra-5.1/cinelerra/playbackengine.C b/cinelerra-5.1/cinelerra/playbackengine.C index 16f6bd7a..571afe2a 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" @@ -32,6 +33,7 @@ #include "mwindowgui.h" #include "patchbay.h" #include "tracking.h" +#include "tracks.h" #include "playbackengine.h" #include "playtransport.h" #include "preferences.h" @@ -39,6 +41,8 @@ #include "mainsession.h" #include "trackcanvas.h" #include "transportque.h" +#include "videodevice.h" +#include "vdevicex11.h" #include "vrender.h" @@ -61,11 +65,13 @@ PlaybackEngine::PlaybackEngine(MWindow *mwindow, Canvas *output) 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"); + cache_lock = new Mutex("PlaybackEngine::cache_lock"); input_lock = new Condition(1, "PlaybackEngine::input_lock"); output_lock = new Condition(0, "PlaybackEngine::output_lock", 1); @@ -80,12 +86,15 @@ PlaybackEngine::~PlaybackEngine() Thread::join(); delete preferences; delete_render_engine(); - delete audio_cache; - delete video_cache; + if( audio_cache ) + audio_cache->remove_user(); + if( video_cache ) + video_cache->remove_user(); delete tracking_lock; delete tracking_done; delete pause_lock; delete start_lock; + delete cache_lock; delete renderengine_lock; delete command; delete next_command; @@ -128,7 +137,11 @@ int PlaybackEngine::create_render_engine() void PlaybackEngine::delete_render_engine() { renderengine_lock->lock("PlaybackEngine::delete_render_engine"); - delete render_engine; render_engine = 0; + if( render_engine ) { + render_engine->interrupt_playback(); + render_engine->wait_done(); + delete render_engine; render_engine = 0; + } renderengine_lock->unlock(); } @@ -153,10 +166,14 @@ void PlaybackEngine::wait_render_engine() void PlaybackEngine::create_cache() { - if(audio_cache) { delete audio_cache; audio_cache = 0; } - if(video_cache) { delete video_cache; video_cache = 0; } - if(!audio_cache) audio_cache = new CICache(preferences); - if(!video_cache) video_cache = new CICache(preferences); + cache_lock->lock("PlaybackEngine::create_cache"); + if( audio_cache ) + audio_cache->remove_user(); + if( video_cache ) + video_cache->remove_user(); + audio_cache = new CICache(preferences); + video_cache = new CICache(preferences); + cache_lock->unlock(); } @@ -249,8 +266,9 @@ void PlaybackEngine::init_tracking() init_meters(); } -void PlaybackEngine::stop_tracking() +void PlaybackEngine::stop_tracking(double position) { + tracking_position = position; tracking_active = 0; stop_cursor(); tracking_done->unlock(); @@ -358,10 +376,14 @@ void PlaybackEngine::run() // Wait for current command to finish output_lock->lock("PlaybackEngine::run"); if( done ) break; -//printf("sent command=%d\n", sent_command->command); // Read the new command + input_lock->lock("PlaybackEngine::run"); 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(); + if( !active ) continue; interrupt_playback(0); wait_render_engine(); @@ -389,19 +411,18 @@ void PlaybackEngine::run() // Dispatch the command start_render_engine(); break; - - case SINGLE_FRAME_FWD: - case SINGLE_FRAME_REWIND: // fall through default: is_playing_back = 1; + case REWIND: + case GOTO_END: 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_borders(); // Dispatch the command start_render_engine(); break; @@ -410,31 +431,63 @@ void PlaybackEngine::run() } } +void PlaybackEngine::clear_borders() +{ + EDL *edl = command->get_edl(); + PlaybackConfig *config = edl->session->playback_config; + if( config->vconfig->driver == PLAYBACK_X11_GL ) { + if( render_engine && render_engine->video ) { + VDeviceBase *vdriver = render_engine->video->get_output_base(); + ((VDeviceX11*)vdriver)->clear_output(); + return; + } + } + BC_WindowBase *window = output->get_canvas(); + if( !window ) return; + window->lock_window("PlaybackEngine::clear_output"); + output->clear_borders(edl); + window->unlock_window(); +} void PlaybackEngine::stop_playback(int wait_tracking) { 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(); } +int PlaybackEngine::get_direction() +{ + int curr_command = is_playing_back ? this->command->command : STOP; + return TransportCommand::get_direction(curr_command); +} + +void PlaybackEngine::update_preferences(Preferences *prefs) +{ + preferences->copy_from(prefs); + create_render_engine(); +} void PlaybackEngine::send_command(int command, EDL *edl, int wait_tracking, int use_inout) { //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 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 ) { + case STOP: + transport_stop(wait_tracking); + break; case FAST_REWIND: // Commands that play back case NORMAL_REWIND: case SLOW_REWIND: @@ -445,56 +498,56 @@ 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; + if( curr_command == command && !curr_single_frame && + curr_audio == next_audio ) { + transport_stop(wait_tracking); break; } // Resume or change direction switch( curr_command ) { - default: - transport_stop(0); - do_resume = 1; -// fall through + case REWIND: + case GOTO_END: case STOP: case COMMAND_NONE: case SINGLE_FRAME_FWD: case SINGLE_FRAME_REWIND: 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); +// already stopped + break; + default: + transport_stop(0); + next_command->resume = 1; break; } + next_command->realtime = 1; + transport_command(command, CHANGE_NONE, edl, use_inout); break; - -// Commands that stop - case STOP: case REWIND: case GOTO_END: - do_stop = 1; + transport_stop(1); + next_command->realtime = 1; + transport_command(command, CHANGE_NONE, edl, use_inout); + stop_tracking(this->command->playbackstart); break; } - - if( do_stop ) { - transport_stop(wait_tracking); - } } int PlaybackEngine::put_command(TransportCommand *command, int reset) { -// commands can deadlock updating tracking,meters,clock... - int mlocked = mwindow->gui->break_lock(); input_lock->lock("PlaybackEngine::put_command"); + int prev_change_type = sent_command->change_type; sent_command->copy_from(command); - if( reset ) - command->reset(); +// 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(); - if( mlocked ) - mwindow->gui->lock_window("PlaybackEngine::put_command"); + input_lock->unlock(); return 0; } @@ -517,15 +570,10 @@ int PlaybackEngine::transport_command(int command, int change_type, EDL *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 || change_type == CHANGE_ALL ) 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); }