From 22b208143be1f50078c61dbb977826057946f174 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Fri, 22 Mar 2019 03:33:18 +1100 Subject: [PATCH] correct threading around clearing the viewer sequences --- panels/viewer.cpp | 63 ++++++++++++++++++++++---------------- project/projectmodel.cpp | 4 +-- rendering/renderthread.cpp | 16 ++++++++++ rendering/renderthread.h | 2 +- ui/viewerwidget.cpp | 9 +++--- ui/viewerwidget.h | 2 +- 6 files changed, 62 insertions(+), 34 deletions(-) diff --git a/panels/viewer.cpp b/panels/viewer.cpp index 9b1685bb5..911df3376 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -120,7 +120,6 @@ bool Viewer::is_main_sequence() { } void Viewer::set_main_sequence() { - clean_created_seq(); set_sequence(true, olive::ActiveSequence); } @@ -720,7 +719,8 @@ void Viewer::set_media(Media* m) { main_sequence = false; media = m; - clean_created_seq(); + SequencePtr new_sequence = nullptr; + if (media != nullptr) { switch (media->get_type()) { case MEDIA_TYPE_FOOTAGE: @@ -729,30 +729,32 @@ void Viewer::set_media(Media* m) { marker_ref = &footage->markers; - seq = std::make_shared(); + new_sequence = std::make_shared(); created_sequence = true; - seq->wrapper_sequence = true; - seq->name = footage->name; + new_sequence->wrapper_sequence = true; + new_sequence->name = footage->name; - seq->using_workarea = footage->using_inout; + new_sequence->using_workarea = footage->using_inout; if (footage->using_inout) { - seq->workarea_in = footage->in; - seq->workarea_out = footage->out; + new_sequence->workarea_in = footage->in; + new_sequence->workarea_out = footage->out; } // FIXME: Move this magic number to Config - seq->frame_rate = 30; + new_sequence->frame_rate = 30; if (footage->video_tracks.size() > 0) { const FootageStream& video_stream = footage->video_tracks.at(0); - seq->width = video_stream.video_width; - seq->height = video_stream.video_height; - if (video_stream.video_frame_rate > 0 && !video_stream.infinite_length) seq->frame_rate = video_stream.video_frame_rate * footage->speed; + new_sequence->width = video_stream.video_width; + new_sequence->height = video_stream.video_height; + if (video_stream.video_frame_rate > 0 && !video_stream.infinite_length) { + new_sequence->frame_rate = video_stream.video_frame_rate * footage->speed; + } - ClipPtr c = std::make_shared(seq.get()); + ClipPtr c = std::make_shared(new_sequence.get()); c->set_media(media, video_stream.file_index); c->set_timeline_in(0); - c->set_timeline_out(footage->get_length_in_frames(seq->frame_rate)); + c->set_timeline_out(footage->get_length_in_frames(new_sequence->frame_rate)); if (c->timeline_out() <= 0) { // FIXME: Move this magic number to Config c->set_timeline_out(150); @@ -760,25 +762,25 @@ void Viewer::set_media(Media* m) { c->set_track(-1); c->set_clip_in(0); c->refresh(); - seq->clips.append(c); + new_sequence->clips.append(c); } else { // FIXME: Move this magic number to Config - seq->width = 1920; - seq->height = 1080; + new_sequence->width = 1920; + new_sequence->height = 1080; } if (footage->audio_tracks.size() > 0) { const FootageStream& audio_stream = footage->audio_tracks.at(0); - seq->audio_frequency = audio_stream.audio_frequency; + new_sequence->audio_frequency = audio_stream.audio_frequency; - ClipPtr c = std::make_shared(seq.get()); + ClipPtr c = std::make_shared(new_sequence.get()); c->set_media(media, audio_stream.file_index); c->set_timeline_in(0); - c->set_timeline_out(footage->get_length_in_frames(seq->frame_rate)); + c->set_timeline_out(footage->get_length_in_frames(new_sequence->frame_rate)); c->set_track(0); c->set_clip_in(0); c->refresh(); - seq->clips.append(c); + new_sequence->clips.append(c); if (footage->video_tracks.size() == 0) { viewer_widget->waveform = true; @@ -788,18 +790,19 @@ void Viewer::set_media(Media* m) { } } else { // FIXME: Move this magic number to Config - seq->audio_frequency = 48000; + new_sequence->audio_frequency = 48000; } - seq->audio_layout = AV_CH_LAYOUT_STEREO; + new_sequence->audio_layout = AV_CH_LAYOUT_STEREO; } break; case MEDIA_TYPE_SEQUENCE: - seq = media->to_sequence(); + new_sequence = media->to_sequence(); break; } } - set_sequence(false, seq); + + set_sequence(false, new_sequence); } void Viewer::update_playhead() { @@ -861,7 +864,9 @@ void Viewer::clean_created_seq() { } */ + // Delete the current sequence seq.reset(); + created_sequence = false; } } @@ -871,13 +876,19 @@ void Viewer::set_sequence(bool main, SequencePtr s) { reset_all_audio(); - main_sequence = main; + viewer_widget->wait_until_render_is_paused(); // If we had a current sequence open, close it if (seq != nullptr) { close_active_clips(seq.get()); } + clean_created_seq(); + + main_sequence = main; + + + seq = (main) ? olive::ActiveSequence : s; bool null_sequence = (seq == nullptr); diff --git a/project/projectmodel.cpp b/project/projectmodel.cpp index 80e87c8d0..56caa3672 100644 --- a/project/projectmodel.cpp +++ b/project/projectmodel.cpp @@ -44,10 +44,10 @@ void ProjectModel::make_root() { void ProjectModel::destroy_root() { if (panel_sequence_viewer != nullptr) { - panel_sequence_viewer->viewer_widget->delete_function(); + panel_sequence_viewer->set_media(nullptr); } if (panel_footage_viewer != nullptr) { - panel_footage_viewer->viewer_widget->delete_function(); + panel_footage_viewer->set_media(nullptr); } root_item_ = std::make_shared(); diff --git a/rendering/renderthread.cpp b/rendering/renderthread.cpp index 1fb88308c..c8d822f56 100644 --- a/rendering/renderthread.cpp +++ b/rendering/renderthread.cpp @@ -273,6 +273,22 @@ void RenderThread::cancel() { wait(); } +void RenderThread::wait_until_paused() +{ + + // Wait for thread to finish whatever it's doing before proceeding. + // + // FIXME: This is slow. Perhaps there's a better way... + + if (wait_lock_.tryLock()) { + wait_lock_.unlock(); + return; + } else { + wait_lock_.lock(); + wait_lock_.unlock(); + } +} + void RenderThread::delete_buffers() { front_buffer_1.Destroy(); front_buffer_2.Destroy(); diff --git a/rendering/renderthread.h b/rendering/renderthread.h index 1f89d3043..b0ce750f6 100644 --- a/rendering/renderthread.h +++ b/rendering/renderthread.h @@ -60,7 +60,7 @@ public: int idivider = 0); bool did_texture_fail(); void cancel(); - + void wait_until_paused(); public slots: // cleanup functions diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index ee2de87b3..6fcdf8d74 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -90,10 +90,6 @@ ViewerWidget::~ViewerWidget() { delete renderer; } -void ViewerWidget::delete_function() { - close_active_clips(viewer->seq.get()); -} - void ViewerWidget::set_waveform_scroll(int s) { if (waveform) { waveform_scroll = s; @@ -381,6 +377,11 @@ void ViewerWidget::close_window() { window->hide(); } +void ViewerWidget::wait_until_render_is_paused() +{ + renderer->wait_until_paused(); +} + void ViewerWidget::draw_waveform_func() { QPainter p(this); if (viewer->seq->using_workarea) { diff --git a/ui/viewerwidget.h b/ui/viewerwidget.h index f01ae7063..0a5fdbbbd 100644 --- a/ui/viewerwidget.h +++ b/ui/viewerwidget.h @@ -48,8 +48,8 @@ public: ViewerWidget(QWidget *parent = nullptr); ~ViewerWidget(); - void delete_function(); void close_window(); + void wait_until_render_is_paused(); void paintGL(); void initializeGL();