potential fix for #240
This commit is contained in:
+44
-44
@@ -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)));
|
||||
|
||||
@@ -335,7 +335,7 @@ void SpeedDialog::accept() {
|
||||
|
||||
for (int i=0;i<clips.size();i++) {
|
||||
Clip* c = clips.at(i);
|
||||
if (c->open) close_clip(c);
|
||||
if (c->open) close_clip(c, true);
|
||||
|
||||
if (c->track >= 0
|
||||
&& maintain_pitch->checkState() != Qt::PartiallyChecked
|
||||
|
||||
+25
-25
@@ -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();
|
||||
|
||||
+13
-9
@@ -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;
|
||||
|
||||
|
||||
+85
-86
@@ -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;i<clip->effects.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<Clip*>& 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, QVector<C
|
||||
}
|
||||
|
||||
double get_timecode(Clip* c, long playhead) {
|
||||
return ((double)(playhead-c->get_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<int64_t>(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<int64_t>(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<enum AVPixelFormat>(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;i<c->effects.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;i<c->effects.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<Clip*> empty;
|
||||
if (cache) cache_clip(c, playhead, reset, false, empty);
|
||||
QVector<Clip*> 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;i<s->clips.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;i<s->clips.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -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<Clip *> &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
|
||||
|
||||
+8
-12
@@ -12,6 +12,7 @@
|
||||
#include "project/media.h"
|
||||
#include "io/clipboard.h"
|
||||
#include "undo.h"
|
||||
#include "debug.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<QString> effects_paths = get_effects_paths();
|
||||
|
||||
@@ -140,6 +140,7 @@ public:
|
||||
void save(QXmlStreamWriter& stream);
|
||||
|
||||
// glsl handling
|
||||
bool is_open();
|
||||
void open();
|
||||
void close();
|
||||
virtual void startEffect();
|
||||
|
||||
+5
-7
@@ -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;j<s->clips.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;i<clips.size();i++) {
|
||||
Clip* c = clips.at(i);
|
||||
if (c->open) {
|
||||
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) :
|
||||
|
||||
+4
-4
@@ -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<Clip*>& 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<Clip*>& 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<Clip*>& 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) {
|
||||
|
||||
Reference in New Issue
Block a user