From 4157e4d432600b0bf7e3de9e381751154303e512 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Fri, 4 Jan 2019 11:54:18 +1100 Subject: [PATCH] potential fix for #240 --- dialogs/exportdialog.cpp | 88 ++++++++++---------- dialogs/speeddialog.cpp | 2 +- mainwindow.cpp | 50 ++++++------ panels/viewer.cpp | 22 ++--- playback/playback.cpp | 171 +++++++++++++++++++-------------------- playback/playback.h | 4 +- project/clip.cpp | 20 ++--- project/effect.cpp | 4 + project/effect.h | 1 + project/undo.cpp | 12 ++- ui/viewerwidget.cpp | 8 +- 11 files changed, 192 insertions(+), 190 deletions(-) diff --git a/dialogs/exportdialog.cpp b/dialogs/exportdialog.cpp index 39e788e12..7f4c433e0 100644 --- a/dialogs/exportdialog.cpp +++ b/dialogs/exportdialog.cpp @@ -57,7 +57,7 @@ enum ExportFormats { ExportDialog::ExportDialog(QWidget *parent) : QDialog(parent) { - setWindowTitle("Export \"" + sequence->name + "\""); + setWindowTitle("Export \"" + sequence->name + "\""); setup_ui(); rangeCombobox->setCurrentIndex(0); @@ -479,7 +479,7 @@ void ExportDialog::export_action() { connect(et, SIGNAL(finished()), this, SLOT(render_thread_finished())); connect(et, SIGNAL(progress_changed(int, qint64)), this, SLOT(update_progress_bar(int, qint64))); - closeActiveClips(sequence, true); + closeActiveClips(sequence); mainWindow->autorecover_interval(); @@ -603,40 +603,40 @@ void ExportDialog::setup_ui() { videoGroupbox->setFlat(false); videoGroupbox->setCheckable(true); - QGridLayout* videoGridLayout = new QGridLayout(videoGroupbox); + QGridLayout* videoGridLayout = new QGridLayout(videoGroupbox); - videoGridLayout->addWidget(new QLabel("Codec:"), 0, 0, 1, 1); - vcodecCombobox = new QComboBox(videoGroupbox); - videoGridLayout->addWidget(vcodecCombobox, 0, 1, 1, 1); + videoGridLayout->addWidget(new QLabel("Codec:"), 0, 0, 1, 1); + vcodecCombobox = new QComboBox(videoGroupbox); + videoGridLayout->addWidget(vcodecCombobox, 0, 1, 1, 1); - videoGridLayout->addWidget(new QLabel("Width:"), 1, 0, 1, 1); - widthSpinbox = new QSpinBox(videoGroupbox); - widthSpinbox->setMaximum(16777216); - videoGridLayout->addWidget(widthSpinbox, 1, 1, 1, 1); + videoGridLayout->addWidget(new QLabel("Width:"), 1, 0, 1, 1); + widthSpinbox = new QSpinBox(videoGroupbox); + widthSpinbox->setMaximum(16777216); + videoGridLayout->addWidget(widthSpinbox, 1, 1, 1, 1); - videoGridLayout->addWidget(new QLabel("Height:"), 2, 0, 1, 1); - heightSpinbox = new QSpinBox(videoGroupbox); - heightSpinbox->setMaximum(16777216); - videoGridLayout->addWidget(heightSpinbox, 2, 1, 1, 1); + videoGridLayout->addWidget(new QLabel("Height:"), 2, 0, 1, 1); + heightSpinbox = new QSpinBox(videoGroupbox); + heightSpinbox->setMaximum(16777216); + videoGridLayout->addWidget(heightSpinbox, 2, 1, 1, 1); - videoGridLayout->addWidget(new QLabel("Frame Rate:"), 3, 0, 1, 1); - framerateSpinbox = new QDoubleSpinBox(videoGroupbox); - framerateSpinbox->setMaximum(60); - framerateSpinbox->setValue(0); - videoGridLayout->addWidget(framerateSpinbox, 3, 1, 1, 1); + videoGridLayout->addWidget(new QLabel("Frame Rate:"), 3, 0, 1, 1); + framerateSpinbox = new QDoubleSpinBox(videoGroupbox); + framerateSpinbox->setMaximum(60); + framerateSpinbox->setValue(0); + videoGridLayout->addWidget(framerateSpinbox, 3, 1, 1, 1); - videoGridLayout->addWidget(new QLabel("Compression Type:"), 4, 0, 1, 1); + videoGridLayout->addWidget(new QLabel("Compression Type:"), 4, 0, 1, 1); compressionTypeCombobox = new QComboBox(videoGroupbox); compressionTypeCombobox->addItem("Quality-based (Constant Rate Factor)"); compressionTypeCombobox->addItem("File size-based (Two-Pass)"); - videoGridLayout->addWidget(compressionTypeCombobox, 4, 1, 1, 1); + videoGridLayout->addWidget(compressionTypeCombobox, 4, 1, 1, 1); - videoBitrateLabel = new QLabel(videoGroupbox); - videoGridLayout->addWidget(videoBitrateLabel, 5, 0, 1, 1); - videobitrateSpinbox = new QDoubleSpinBox(videoGroupbox); - videobitrateSpinbox->setMaximum(100); - videobitrateSpinbox->setValue(2); - videoGridLayout->addWidget(videobitrateSpinbox, 5, 1, 1, 1); + videoBitrateLabel = new QLabel(videoGroupbox); + videoGridLayout->addWidget(videoBitrateLabel, 5, 0, 1, 1); + videobitrateSpinbox = new QDoubleSpinBox(videoGroupbox); + videobitrateSpinbox->setMaximum(100); + videobitrateSpinbox->setValue(2); + videoGridLayout->addWidget(videobitrateSpinbox, 5, 1, 1, 1); verticalLayout->addWidget(videoGroupbox); @@ -644,60 +644,60 @@ void ExportDialog::setup_ui() { audioGroupbox->setTitle("Audio"); audioGroupbox->setCheckable(true); - QGridLayout* audioGridLayout = new QGridLayout(audioGroupbox); + QGridLayout* audioGridLayout = new QGridLayout(audioGroupbox); - audioGridLayout->addWidget(new QLabel("Codec:"), 0, 0, 1, 1); + audioGridLayout->addWidget(new QLabel("Codec:"), 0, 0, 1, 1); acodecCombobox = new QComboBox(audioGroupbox); - audioGridLayout->addWidget(acodecCombobox, 0, 1, 1, 1); + audioGridLayout->addWidget(acodecCombobox, 0, 1, 1, 1); - audioGridLayout->addWidget(new QLabel("Sampling Rate:"), 1, 0, 1, 1); + audioGridLayout->addWidget(new QLabel("Sampling Rate:"), 1, 0, 1, 1); samplingRateSpinbox = new QSpinBox(audioGroupbox); samplingRateSpinbox->setMaximum(96000); samplingRateSpinbox->setValue(0); - audioGridLayout->addWidget(samplingRateSpinbox, 1, 1, 1, 1); + audioGridLayout->addWidget(samplingRateSpinbox, 1, 1, 1, 1); - audioGridLayout->addWidget(new QLabel("Bitrate (Kbps/CBR):"), 3, 0, 1, 1); + audioGridLayout->addWidget(new QLabel("Bitrate (Kbps/CBR):"), 3, 0, 1, 1); audiobitrateSpinbox = new QSpinBox(audioGroupbox); audiobitrateSpinbox->setMaximum(320); audiobitrateSpinbox->setValue(256); - audioGridLayout->addWidget(audiobitrateSpinbox, 3, 1, 1, 1); + audioGridLayout->addWidget(audiobitrateSpinbox, 3, 1, 1, 1); verticalLayout->addWidget(audioGroupbox); - QHBoxLayout* progressLayout = new QHBoxLayout(); + QHBoxLayout* progressLayout = new QHBoxLayout(); progressBar = new QProgressBar(this); progressBar->setFormat("%p% (ETA: 0:00:00)"); progressBar->setEnabled(false); progressBar->setValue(0); - progressLayout->addWidget(progressBar); + progressLayout->addWidget(progressBar); renderCancel = new QPushButton(this); renderCancel->setText("x"); renderCancel->setEnabled(false); renderCancel->setMaximumSize(QSize(20, 16777215)); connect(renderCancel, SIGNAL(clicked(bool)), this, SLOT(cancel_render())); - progressLayout->addWidget(renderCancel); + progressLayout->addWidget(renderCancel); - verticalLayout->addLayout(progressLayout); + verticalLayout->addLayout(progressLayout); - QHBoxLayout* buttonLayout = new QHBoxLayout(); - buttonLayout->addStretch(); + QHBoxLayout* buttonLayout = new QHBoxLayout(); + buttonLayout->addStretch(); export_button = new QPushButton(this); export_button->setText("Export"); connect(export_button, SIGNAL(clicked(bool)), this, SLOT(export_action())); - buttonLayout->addWidget(export_button); + buttonLayout->addWidget(export_button); cancel_button = new QPushButton(this); cancel_button->setText("Cancel"); connect(cancel_button, SIGNAL(clicked(bool)), this, SLOT(reject())); - buttonLayout->addWidget(cancel_button); + buttonLayout->addWidget(cancel_button); - buttonLayout->addStretch(); + buttonLayout->addStretch(); - verticalLayout->addLayout(buttonLayout); + verticalLayout->addLayout(buttonLayout); connect(formatCombobox, SIGNAL(currentIndexChanged(int)), this, SLOT(format_changed(int))); connect(compressionTypeCombobox, SIGNAL(currentIndexChanged(int)), this, SLOT(comp_type_changed(int))); diff --git a/dialogs/speeddialog.cpp b/dialogs/speeddialog.cpp index c48baacd3..ff4c52a14 100644 --- a/dialogs/speeddialog.cpp +++ b/dialogs/speeddialog.cpp @@ -335,7 +335,7 @@ void SpeedDialog::accept() { for (int i=0;iopen) close_clip(c); + if (c->open) close_clip(c, true); if (c->track >= 0 && maintain_pitch->checkState() != Qt::PartiallyChecked diff --git a/mainwindow.cpp b/mainwindow.cpp index 42afa55d2..bffdf2169 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -80,13 +80,13 @@ void MainWindow::setup_layout(bool reset) { #endif // load panels from file - if (!reset) { + if (!reset) { QFile panel_config(get_data_path() + "/layout"); if (panel_config.exists() && panel_config.open(QFile::ReadOnly)) { restoreState(panel_config.readAll(), 0); panel_config.close(); } - } + } layout()->update(); } @@ -727,7 +727,7 @@ void MainWindow::setup_menus() { tools_menu->addAction("Preferences", this, SLOT(preferences()), QKeySequence("Ctrl+.")); #ifdef QT_DEBUG - tools_menu->addAction("Clear Undo", this, SLOT(clear_undo_stack())); + tools_menu->addAction("Clear Undo", this, SLOT(clear_undo_stack())); #endif // INITIALIZE HELP MENU @@ -762,11 +762,11 @@ void MainWindow::updateTitle(const QString& url) { void MainWindow::closeEvent(QCloseEvent *e) { if (can_close_project()) { panel_effect_controls->clear_effects(true); - panel_sequence_viewer->viewer_widget->delete_function(); - panel_footage_viewer->viewer_widget->delete_function(); set_sequence(NULL); + panel_footage_viewer->set_main_sequence(); + QString data_dir = get_data_path(); if (!data_dir.isEmpty() && !autorecovery_filename.isEmpty()) { if (QFile::exists(autorecovery_filename)) { @@ -824,10 +824,10 @@ void MainWindow::reset_layout() { } void MainWindow::go_to_start() { - if (panel_timeline->focused() - || panel_sequence_viewer->is_focused() - || panel_effect_controls->keyframe_focus() - || panel_graph_editor->view_is_focused()) { + if (panel_timeline->focused() + || panel_sequence_viewer->is_focused() + || panel_effect_controls->keyframe_focus() + || panel_graph_editor->view_is_focused()) { panel_sequence_viewer->go_to_start(); } else if (panel_footage_viewer->is_focused()) { panel_footage_viewer->go_to_start(); @@ -835,10 +835,10 @@ void MainWindow::go_to_start() { } void MainWindow::prev_frame() { - if (panel_timeline->focused() - || panel_sequence_viewer->is_focused() - || panel_effect_controls->keyframe_focus() - || panel_graph_editor->view_is_focused()) { + if (panel_timeline->focused() + || panel_sequence_viewer->is_focused() + || panel_effect_controls->keyframe_focus() + || panel_graph_editor->view_is_focused()) { panel_sequence_viewer->previous_frame(); } else if (panel_footage_viewer->is_focused()) { panel_footage_viewer->previous_frame(); @@ -846,10 +846,10 @@ void MainWindow::prev_frame() { } void MainWindow::next_frame() { - if (panel_timeline->focused() - || panel_sequence_viewer->is_focused() - || panel_effect_controls->keyframe_focus() - || panel_graph_editor->view_is_focused()) { + if (panel_timeline->focused() + || panel_sequence_viewer->is_focused() + || panel_effect_controls->keyframe_focus() + || panel_graph_editor->view_is_focused()) { panel_sequence_viewer->next_frame(); } else if (panel_footage_viewer->is_focused()) { panel_footage_viewer->next_frame(); @@ -857,10 +857,10 @@ void MainWindow::next_frame() { } void MainWindow::go_to_end() { - if (panel_timeline->focused() - || panel_sequence_viewer->is_focused() - || panel_effect_controls->keyframe_focus() - || panel_graph_editor->view_is_focused()) { + if (panel_timeline->focused() + || panel_sequence_viewer->is_focused() + || panel_effect_controls->keyframe_focus() + || panel_graph_editor->view_is_focused()) { panel_sequence_viewer->go_to_end(); } else if (panel_footage_viewer->is_focused()) { panel_footage_viewer->go_to_end(); @@ -868,10 +868,10 @@ void MainWindow::go_to_end() { } void MainWindow::playpause() { - if (panel_timeline->focused() - || panel_sequence_viewer->is_focused() - || panel_effect_controls->keyframe_focus() - || panel_graph_editor->view_is_focused()) { + if (panel_timeline->focused() + || panel_sequence_viewer->is_focused() + || panel_effect_controls->keyframe_focus() + || panel_graph_editor->view_is_focused()) { panel_sequence_viewer->toggle_play(); } else if (panel_footage_viewer->is_focused()) { panel_footage_viewer->toggle_play(); diff --git a/panels/viewer.cpp b/panels/viewer.cpp index 866c940dc..4d5a98d32 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -573,14 +573,14 @@ void Viewer::set_media(Media* m) { seq->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; + 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; Clip* c = new Clip(seq); c->media = media; - c->media_stream = video_stream.file_index; + c->media_stream = video_stream.file_index; c->timeline_in = 0; c->timeline_out = footage->get_length_in_frames(seq->frame_rate); if (c->timeline_out <= 0) c->timeline_out = 150; @@ -594,12 +594,12 @@ void Viewer::set_media(Media* m) { } if (footage->audio_tracks.size() > 0) { - const FootageStream& audio_stream = footage->audio_tracks.at(0); - seq->audio_frequency = audio_stream.audio_frequency; + const FootageStream& audio_stream = footage->audio_tracks.at(0); + seq->audio_frequency = audio_stream.audio_frequency; Clip* c = new Clip(seq); c->media = media; - c->media_stream = audio_stream.file_index; + c->media_stream = audio_stream.file_index; c->timeline_in = 0; c->timeline_out = footage->get_length_in_frames(seq->frame_rate); c->track = 0; @@ -610,7 +610,7 @@ void Viewer::set_media(Media* m) { if (footage->video_tracks.size() == 0) { viewer_widget->waveform = true; viewer_widget->waveform_clip = c; - viewer_widget->waveform_ms = &audio_stream; + viewer_widget->waveform_ms = &audio_stream; viewer_widget->update(); } } else { @@ -698,6 +698,10 @@ void Viewer::clean_created_seq() { void Viewer::set_sequence(bool main, Sequence *s) { reset_all_audio(); + if (seq != NULL) { + closeActiveClips(seq); + } + main_sequence = main; seq = (main) ? sequence : s; diff --git a/playback/playback.cpp b/playback/playback.cpp index 9dd4a399d..dfb67461a 100644 --- a/playback/playback.cpp +++ b/playback/playback.cpp @@ -37,39 +37,39 @@ bool texture_failed = false; bool rendering = false; bool clip_uses_cacher(Clip* clip) { - return (clip->media == NULL && clip->track >= 0) || (clip->media != NULL && clip->media->get_type() == MEDIA_TYPE_FOOTAGE); + return (clip->media == NULL && clip->track >= 0) || (clip->media != NULL && clip->media->get_type() == MEDIA_TYPE_FOOTAGE); } void open_clip(Clip* clip, bool multithreaded) { - if (clip_uses_cacher(clip)) { - clip->multithreaded = multithreaded; - if (multithreaded) { - if (clip->open_lock.tryLock()) { - // maybe keep cacher instance in memory while clip exists for performance? - clip->cacher = new Cacher(clip); - QObject::connect(clip->cacher, SIGNAL(finished()), clip->cacher, SLOT(deleteLater())); - clip->cacher->start((clip->track < 0) ? QThread::NormalPriority : QThread::TimeCriticalPriority); - } - } else { - clip->finished_opening = false; - clip->open = true; + if (clip_uses_cacher(clip)) { + clip->multithreaded = multithreaded; + if (multithreaded) { + if (clip->open_lock.tryLock()) { + // maybe keep cacher instance in memory while clip exists for performance? + clip->cacher = new Cacher(clip); + QObject::connect(clip->cacher, SIGNAL(finished()), clip->cacher, SLOT(deleteLater())); + clip->cacher->start((clip->track < 0) ? QThread::NormalPriority : QThread::TimeCriticalPriority); + } + } else { + clip->finished_opening = false; + clip->open = true; - open_clip_worker(clip); - } - } else { - clip->open = true; - } + open_clip_worker(clip); + } + } else { + clip->open = true; + } } -void close_clip(Clip* clip) { +void close_clip(Clip* clip, bool wait) { // destroy opengl texture in main thread - if (clip->texture != NULL) { + if (clip->texture != NULL) { delete clip->texture; clip->texture = NULL; } for (int i=0;ieffects.size();i++) { - clip->effects.at(i)->close(); + if (clip->effects.at(i)->is_open()) clip->effects.at(i)->close(); } if (clip->fbo != NULL) { @@ -79,29 +79,30 @@ void close_clip(Clip* clip) { clip->fbo = NULL; } - if (clip_uses_cacher(clip)) { - if (clip->multithreaded) { - clip->cacher->caching = false; - clip->can_cache.wakeAll(); - } else { - close_clip_worker(clip); - } - } else { - if (clip->media != NULL && clip->media->get_type() == MEDIA_TYPE_SEQUENCE) - closeActiveClips(clip->media->to_sequence(), false); + if (clip_uses_cacher(clip)) { + if (clip->multithreaded) { + clip->cacher->caching = false; + clip->can_cache.wakeAll(); + if (wait) clip->cacher->wait(); + } else { + close_clip_worker(clip); + } + } else { + if (clip->media != NULL && clip->media->get_type() == MEDIA_TYPE_SEQUENCE) + closeActiveClips(clip->media->to_sequence()); clip->open = false; - } + } } void cache_clip(Clip* clip, long playhead, bool reset, bool scrubbing, QVector& nests) { - if (clip_uses_cacher(clip)) { + if (clip_uses_cacher(clip)) { if (clip->multithreaded) { clip->cacher->playhead = playhead; clip->cacher->reset = reset; clip->cacher->nests = nests; - clip->cacher->scrubbing = scrubbing; - if (reset && clip->queue.size() > 0) clip->cacher->interrupt = true; + clip->cacher->scrubbing = scrubbing; + if (reset && clip->queue.size() > 0) clip->cacher->interrupt = true; clip->can_cache.wakeAll(); } else { @@ -111,16 +112,16 @@ void cache_clip(Clip* clip, long playhead, bool reset, bool scrubbing, QVectorget_timeline_in_with_transition()+c->get_clip_in_with_transition())/(double)c->sequence->frame_rate); + return ((double)(playhead-c->get_timeline_in_with_transition()+c->get_clip_in_with_transition())/(double)c->sequence->frame_rate); } void get_clip_frame(Clip* c, long playhead) { if (c->finished_opening) { - const FootageStream* ms = c->media->to_footage()->get_stream_from_file_index(c->track < 0, c->media_stream); + const FootageStream* ms = c->media->to_footage()->get_stream_from_file_index(c->track < 0, c->media_stream); - int64_t target_pts = qMax(static_cast(0), playhead_to_timestamp(c, playhead)); - int64_t second_pts = qRound64(av_q2d(av_inv_q(c->stream->time_base))); - if (ms->video_interlacing != VIDEO_PROGRESSIVE) { + int64_t target_pts = qMax(static_cast(0), playhead_to_timestamp(c, playhead)); + int64_t second_pts = qRound64(av_q2d(av_inv_q(c->stream->time_base))); + if (ms->video_interlacing != VIDEO_PROGRESSIVE) { target_pts *= 2; second_pts *= 2; } @@ -132,7 +133,7 @@ void get_clip_frame(Clip* c, long playhead) { c->queue_lock.lock(); if (c->queue.size() > 0) { - if (ms->infinite_length) { + if (ms->infinite_length) { target_frame = c->queue.at(0); #ifdef GCF_DEBUG dout << "GCF ==> USE PRECISE (INFINITE)"; @@ -192,14 +193,14 @@ void get_clip_frame(Clip* c, long playhead) { #endif c->reached_end = false; cache = false; - } else if (target_pts != c->last_invalid_ts && (target_pts < target_frame->pts || pts_diff > second_pts)) { + } else if (target_pts != c->last_invalid_ts && (target_pts < target_frame->pts || pts_diff > second_pts)) { #ifdef GCF_DEBUG dout << "GCF ==> RESET" << target_pts << "(" << target_frame->pts << "-" << target_frame->pts+target_frame->pkt_duration << ")"; #endif - if (!config.fast_seeking) target_frame = NULL; + if (!config.fast_seeking) target_frame = NULL; reset = true; - c->last_invalid_ts = target_pts; + c->last_invalid_ts = target_pts; } else { #ifdef GCF_DEBUG dout << "GCF ==> WAIT - target pts:" << target_pts << "closest frame:" << target_frame->pts; @@ -225,26 +226,26 @@ void get_clip_frame(Clip* c, long playhead) { int nb_components = av_pix_fmt_desc_get(static_cast(c->pix_fmt))->nb_components; glPixelStorei(GL_UNPACK_ROW_LENGTH, target_frame->linesize[0]/nb_components); - bool copied = false; - uint8_t* data = target_frame->data[0]; - int frame_size; + bool copied = false; + uint8_t* data = target_frame->data[0]; + int frame_size; - for (int i=0;ieffects.size();i++) { - Effect* e = c->effects.at(i); - if (e->enable_image) { - if (!copied) { - frame_size = target_frame->linesize[0]*target_frame->height; - data = new uint8_t[frame_size]; - memcpy(data, target_frame->data[0], frame_size); - copied = true; - } - e->process_image(get_timecode(c, playhead), data, frame_size); - } - } + for (int i=0;ieffects.size();i++) { + Effect* e = c->effects.at(i); + if (e->enable_image) { + if (!copied) { + frame_size = target_frame->linesize[0]*target_frame->height; + data = new uint8_t[frame_size]; + memcpy(data, target_frame->data[0], frame_size); + copied = true; + } + e->process_image(get_timecode(c, playhead), data, frame_size); + } + } c->texture->setData(0, get_gl_pix_fmt_from_av(c->pix_fmt), QOpenGLTexture::UInt8, data); - if (copied) delete [] data; + if (copied) delete [] data; glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } @@ -252,13 +253,13 @@ void get_clip_frame(Clip* c, long playhead) { c->queue_lock.unlock(); // get more frames - QVector empty; - if (cache) cache_clip(c, playhead, reset, false, empty); + QVector empty; + if (cache) cache_clip(c, playhead, reset, false, empty); } } long playhead_to_clip_frame(Clip* c, long playhead) { - return (qMax(0L, playhead - c->get_timeline_in_with_transition()) + c->get_clip_in_with_transition()); + return (qMax(0L, playhead - c->get_timeline_in_with_transition()) + c->get_clip_in_with_transition()); } double playhead_to_clip_seconds(Clip* c, long playhead) { @@ -278,11 +279,11 @@ int64_t playhead_to_timestamp(Clip* c, long playhead) { int retrieve_next_frame(Clip* c, AVFrame* f) { int result = 0; - int receive_ret; + int receive_ret; // do we need to retrieve a new packet for a new frame? av_frame_unref(f); - while ((receive_ret = avcodec_receive_frame(c->codecCtx, f)) == AVERROR(EAGAIN)) { + while ((receive_ret = avcodec_receive_frame(c->codecCtx, f)) == AVERROR(EAGAIN)) { int read_ret = 0; do { if (c->pkt_written) { @@ -293,15 +294,15 @@ int retrieve_next_frame(Clip* c, AVFrame* f) { if (read_ret >= 0) { c->pkt_written = true; } - } while (read_ret >= 0 && c->pkt->stream_index != c->media_stream); + } while (read_ret >= 0 && c->pkt->stream_index != c->media_stream); if (read_ret >= 0) { int send_ret = avcodec_send_packet(c->codecCtx, c->pkt); if (send_ret < 0) { dout << "[ERROR] Failed to send packet to decoder." << send_ret; - return send_ret; + return send_ret; } - } else { + } else { if (read_ret == AVERROR_EOF) { int send_ret = avcodec_send_packet(c->codecCtx, NULL); if (send_ret < 0) { @@ -323,32 +324,30 @@ int retrieve_next_frame(Clip* c, AVFrame* f) { } bool is_clip_active(Clip* c, long playhead) { - return c->enabled - && c->get_timeline_in_with_transition() < playhead + ceil(c->sequence->frame_rate*2) - && c->get_timeline_out_with_transition() > playhead - && playhead - c->get_timeline_in_with_transition() + c->get_clip_in_with_transition() < c->getMaximumLength(); + return c->enabled + && c->get_timeline_in_with_transition() < playhead + ceil(c->sequence->frame_rate*2) + && c->get_timeline_out_with_transition() > playhead + && playhead - c->get_timeline_in_with_transition() + c->get_clip_in_with_transition() < c->getMaximumLength(); } void set_sequence(Sequence* s) { - closeActiveClips(sequence, true); panel_effect_controls->clear_effects(true); - sequence = s; + sequence = s; panel_sequence_viewer->set_main_sequence(); - panel_timeline->update_sequence(); - panel_timeline->setFocus(); + panel_timeline->update_sequence(); + panel_timeline->setFocus(); } -void closeActiveClips(Sequence *s, bool wait) { +void closeActiveClips(Sequence *s) { if (s != NULL) { - for (int i=0;iclips.size();i++) { - Clip* c = s->clips.at(i); - if (c != NULL) { - if (c->media != NULL && c->media->get_type() == MEDIA_TYPE_SEQUENCE) { - closeActiveClips(c->media->to_sequence(), wait); - if (c->open) close_clip(c); - } else if (clip_uses_cacher(c) && c->open) { - close_clip(c); - if (c->multithreaded && wait) c->cacher->wait(); + for (int i=0;iclips.size();i++) { + Clip* c = s->clips.at(i); + if (c != NULL) { + if (c->media != NULL && c->media->get_type() == MEDIA_TYPE_SEQUENCE) { + closeActiveClips(c->media->to_sequence()); + if (c->open) close_clip(c, true); + } else if (c->open) { + close_clip(c, true); } } } diff --git a/playback/playback.h b/playback/playback.h index 67a18c6d4..db4a80600 100644 --- a/playback/playback.h +++ b/playback/playback.h @@ -15,7 +15,7 @@ extern bool rendering; bool clip_uses_cacher(Clip* clip); void open_clip(Clip* clip, bool multithreaded); void cache_clip(Clip* clip, long playhead, bool reset, bool scrubbing, QVector &nests); -void close_clip(Clip* clip); +void close_clip(Clip* clip, bool wait); void cache_audio_worker(Clip* c, bool write_A); void cache_video_worker(Clip* c, long playhead); void handle_media(Sequence* sequence, long playhead, bool multithreaded); @@ -32,6 +32,6 @@ int retrieve_next_frame(Clip* c, AVFrame* f); bool is_clip_active(Clip* c, long playhead); void get_next_audio(Clip* c, bool mix); void set_sequence(Sequence* s); -void closeActiveClips(Sequence* s, bool wait); +void closeActiveClips(Sequence* s); #endif // PLAYBACK_H diff --git a/project/clip.cpp b/project/clip.cpp index 2253b1ba4..05758928c 100644 --- a/project/clip.cpp +++ b/project/clip.cpp @@ -12,6 +12,7 @@ #include "project/media.h" #include "io/clipboard.h" #include "undo.h" +#include "debug.h" extern "C" { #include @@ -113,9 +114,9 @@ void Clip::refresh() { Footage* m = media->to_footage(); if (track < 0 && m->video_tracks.size() > 0) { - media_stream = m->video_tracks.at(0).file_index; + media_stream = m->video_tracks.at(0).file_index; } else if (track >= 0 && m->audio_tracks.size() > 0) { - media_stream = m->audio_tracks.at(0).file_index; + media_stream = m->audio_tracks.at(0).file_index; } } replaced = false; @@ -171,12 +172,7 @@ Transition* Clip::get_closing_transition() { Clip::~Clip() { if (open) { - close_clip(this); - - // make sure clip has closed before clip is destroyed - if (multithreaded && media != NULL && media->get_type() == MEDIA_TYPE_FOOTAGE) { - cacher->wait(); - } + close_clip(this, true); } if (opening_transition != -1) this->sequence->hard_delete_transition(this, TA_OPENING_TRANSITION); @@ -241,8 +237,8 @@ void Clip::recalculateMaxLength() { case MEDIA_TYPE_FOOTAGE: { Footage* m = media->to_footage(); - const FootageStream* ms = m->get_stream_from_file_index(track < 0, media_stream); - if (ms != NULL && ms->infinite_length) { + const FootageStream* ms = m->get_stream_from_file_index(track < 0, media_stream); + if (ms != NULL && ms->infinite_length) { calculated_length = LONG_MAX; } else { calculated_length = m->get_length_in_frames(fr); @@ -269,7 +265,7 @@ int Clip::getWidth() { switch (media->get_type()) { case MEDIA_TYPE_FOOTAGE: { - const FootageStream* ms = media->to_footage()->get_stream_from_file_index(track < 0, media_stream); + const FootageStream* ms = media->to_footage()->get_stream_from_file_index(track < 0, media_stream); if (ms != NULL) return ms->video_width; if (sequence != NULL) return sequence->width; } @@ -287,7 +283,7 @@ int Clip::getHeight() { switch (media->get_type()) { case MEDIA_TYPE_FOOTAGE: { - const FootageStream* ms = media->to_footage()->get_stream_from_file_index(track < 0, media_stream); + const FootageStream* ms = media->to_footage()->get_stream_from_file_index(track < 0, media_stream); if (ms != NULL) return ms->video_height; if (sequence != NULL) return sequence->height; } diff --git a/project/effect.cpp b/project/effect.cpp index fa6c4b878..d91019d79 100644 --- a/project/effect.cpp +++ b/project/effect.cpp @@ -749,6 +749,10 @@ void Effect::save(QXmlStreamWriter& stream) { } } +bool Effect::is_open() { + return isOpen; +} + void Effect::validate_meta_path() { if (!meta->path.isEmpty() || (vertPath.isEmpty() && fragPath.isEmpty())) return; QList effects_paths = get_effects_paths(); diff --git a/project/effect.h b/project/effect.h index 208ee18a0..a7210a3de 100644 --- a/project/effect.h +++ b/project/effect.h @@ -140,6 +140,7 @@ public: void save(QXmlStreamWriter& stream); // glsl handling + bool is_open(); void open(); void close(); virtual void startEffect(); diff --git a/project/undo.cpp b/project/undo.cpp index 010561b53..fae0bfc10 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -150,7 +150,7 @@ void DeleteClipAction::redo() { // remove ref to clip ref = seq->clips.at(index); if (ref->open) { - close_clip(ref); + close_clip(ref, true); } seq->clips[index] = NULL; @@ -493,7 +493,7 @@ void AddClipCommand::undo() { Clip* c = seq->clips.last(); panel_timeline->deselect_area(c->timeline_in, c->timeline_out, c->track); undone_clips.prepend(c); - if (c->open) close_clip(c); + if (c->open) close_clip(c, true); seq->clips.removeLast(); } mainWindow->setWindowModified(old_project_changed); @@ -587,8 +587,7 @@ void ReplaceMediaCommand::replace(QString& filename) { for (int j=0;jclips.size();j++) { Clip* c = s->clips.at(j); if (c != NULL && c->media == item && c->open) { - close_clip(c); - if (c->media != NULL && c->media->get_type() == MEDIA_TYPE_FOOTAGE) c->cacher->wait(); + close_clip(c, true); c->replaced = true; } } @@ -628,8 +627,7 @@ void ReplaceClipMediaCommand::replace(bool undo) { for (int i=0;iopen) { - close_clip(c); - if (c->media != NULL && c->media->get_type() == MEDIA_TYPE_FOOTAGE) c->cacher->wait(); + close_clip(c, true); } if (undo) { @@ -1102,7 +1100,7 @@ void CloseAllClipsCommand::undo() { } void CloseAllClipsCommand::redo() { - closeActiveClips(sequence, true); + closeActiveClips(sequence); } UpdateFootageTooltip::UpdateFootageTooltip(Media *i) : diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index 9a1681dc7..8481f90fa 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -72,7 +72,7 @@ void ViewerWidget::delete_function() { // destroy all textures as well if (viewer->seq != NULL) { makeCurrent(); - closeActiveClips(viewer->seq, true); + closeActiveClips(viewer->seq); doneCurrent(); } } @@ -485,7 +485,7 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) Footage* m = c->media->to_footage(); if (!m->invalid && !(c->track >= 0 && !is_audio_device_set())) { if (m->ready) { - const FootageStream* ms = m->get_stream_from_file_index(c->track < 0, c->media_stream); + const FootageStream* ms = m->get_stream_from_file_index(c->track < 0, c->media_stream); if (ms != NULL && is_clip_active(c, playhead)) { // if thread is already working, we don't want to touch this, // but we also don't want to hang the UI thread @@ -495,7 +495,7 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) clip_is_active = true; if (c->track >= 0) audio_track_count++; } else if (c->open) { - close_clip(c); + close_clip(c, false); } } else { //dout << "[WARNING] Media '" + m->name + "' was not ready, retrying..."; @@ -507,7 +507,7 @@ GLuint ViewerWidget::compose_sequence(QVector& nests, bool render_audio) if (!c->open) open_clip(c, !rendering); clip_is_active = true; } else if (c->open) { - close_clip(c); + close_clip(c, false); } } if (clip_is_active) {