From 9f0ff7f561f33704be01755193de1e5fab71ca64 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 1 Nov 2018 16:12:17 +1100 Subject: [PATCH] fixed #142 --- effects/effect.cpp | 13 +++++-- effects/effect.h | 8 +++++ io/previewgenerator.cpp | 4 +-- mainwindow.cpp | 6 ++-- panels/project.cpp | 24 +++++++++++-- panels/timeline.h | 4 ++- playback/audio.cpp | 2 ++ playback/cacher.cpp | 79 ++++++++++++++++++++--------------------- playback/playback.cpp | 3 +- project/clip.cpp | 3 +- project/clip.h | 1 + project/undo.cpp | 26 ++++++++++++++ project/undo.h | 13 +++++++ ui/timelinewidget.cpp | 3 +- 14 files changed, 136 insertions(+), 53 deletions(-) diff --git a/effects/effect.cpp b/effects/effect.cpp index c42ae81df..39c8fe45f 100644 --- a/effects/effect.cpp +++ b/effects/effect.cpp @@ -164,13 +164,22 @@ void load_vst_effects() { } void init_effects() { - dout << "Starting init effect (TODO: multithread this)"; + EffectInit* init_thread = new EffectInit(); + QObject::connect(init_thread, SIGNAL(finished()), init_thread, SLOT(deleteLater())); + init_thread->start(); +} + +EffectInit::EffectInit() { effects_loaded.lock(); +} + +void EffectInit::run() { + dout << "[INFO] Initializing effects..."; load_internal_effects(); load_shader_effects(); load_vst_effects(); effects_loaded.unlock(); - dout << "Completed init effect (TODO: multithread this)"; + dout << "[INFO] Finished initializing effects"; } double double_lerp(double a, double b, double t) { diff --git a/effects/effect.h b/effects/effect.h index a14ba272e..d719b1463 100644 --- a/effects/effect.h +++ b/effects/effect.h @@ -10,6 +10,7 @@ #include #include #include +#include class QLabel; class QWidget; class CollapsibleWidget; @@ -262,4 +263,11 @@ private: int get_index_in_clip(); }; +class EffectInit : public QThread { +public: + EffectInit(); +protected: + void run(); +}; + #endif // EFFECT_H diff --git a/io/previewgenerator.cpp b/io/previewgenerator.cpp index 49e69596a..f83b26bbb 100644 --- a/io/previewgenerator.cpp +++ b/io/previewgenerator.cpp @@ -66,11 +66,11 @@ void PreviewGenerator::parse_media() { && fmt_ctx->streams[i]->codecpar->width > 0 && fmt_ctx->streams[i]->codecpar->height > 0) { - /*dout << "avg_frame_rate was:" << fmt_ctx->streams[i]->avg_frame_rate.num << "/" << fmt_ctx->streams[i]->avg_frame_rate.den; + dout << "avg_frame_rate was:" << fmt_ctx->streams[i]->avg_frame_rate.num << "/" << fmt_ctx->streams[i]->avg_frame_rate.den; dout << "r_frame_rate was:" << fmt_ctx->streams[i]->r_frame_rate.num << "/" << fmt_ctx->streams[i]->r_frame_rate.den; dout << "codec_frame_rate was:" << fmt_ctx->streams[i]->codec->framerate.num << "/" << fmt_ctx->streams[i]->codec->framerate.den; dout << "nb_frames was:" << fmt_ctx->streams[i]->nb_frames; - dout << "duration was:" << fmt_ctx->streams[i]->duration << "OR fmt_ctx's duration is:" << fmt_ctx->duration;*/ + dout << "duration was:" << fmt_ctx->streams[i]->duration << "OR fmt_ctx's duration is:" << fmt_ctx->duration; if (fmt_ctx->streams[i]->avg_frame_rate.den == 0 && fmt_ctx->streams[i]->duration == AV_NOPTS_VALUE) { // source is LIKELY a still image diff --git a/mainwindow.cpp b/mainwindow.cpp index 6201be442..ad38b01d8 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -327,8 +327,10 @@ void MainWindow::editMenu_About_To_Be_Shown() { } void MainWindow::undo() { - undo_stack.undo(); - update_ui(true); + if (!panel_timeline->importing) { // workaround to prevent crash (and also users should never need to do this) + undo_stack.undo(); + update_ui(true); + } } void MainWindow::redo() { diff --git a/panels/project.cpp b/panels/project.cpp index eafb82844..3b83b317a 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -245,6 +245,18 @@ void Project::get_all_media_from_table(QList items, QListclip_clipboard.size();i++) { + Clip* c = panel_timeline->clip_clipboard.at(i); + if (c->media == m) { + ca->append(new RemoveClipsFromClipboard(i-delete_count)); + delete_count++; + } + } + return (delete_count > 0); +} + void Project::delete_selected_media() { ComboAction* ca = new ComboAction(); QList items = ui->treeWidget->selectedItems(); @@ -325,7 +337,11 @@ void Project::delete_selected_media() { } } } - } + } + if (confirm_delete) { + delete_clips_in_clipboard_with_media(ca, media); + } + } } @@ -638,10 +654,10 @@ void Project::delete_clips_using_selected_media() { } else { ComboAction* ca = new ComboAction(); bool deleted = false; + QList items = source_table->selectedItems(); for (int i=0;iclips.size();i++) { Clip* c = sequence->clips.at(i); if (c != NULL) { - QList items = source_table->selectedItems(); for (int j=0;jmedia == m) { @@ -651,6 +667,10 @@ void Project::delete_clips_using_selected_media() { } } } + for (int j=0;j clip_clipboard; + Ui::Timeline *ui; public slots: void repaint_timeline(); @@ -203,7 +206,6 @@ private: void decheck_tool_buttons(QObject* sender); void set_tool(int tool); long last_frame; - QVector clip_clipboard; int scroll; int default_track_height; diff --git a/playback/audio.cpp b/playback/audio.cpp index da96cba23..484e8f4c4 100644 --- a/playback/audio.cpp +++ b/playback/audio.cpp @@ -132,6 +132,8 @@ void AudioSenderThread::run() { // got all the bytes, write again written_bytes += send_audio_to_output(0, audio_ibuffer_size); } + + dout << "read to" << audio_ibuffer_read; } } lock.unlock(); diff --git a/playback/cacher.cpp b/playback/cacher.cpp index d62ab5599..58a4873bb 100644 --- a/playback/cacher.cpp +++ b/playback/cacher.cpp @@ -179,20 +179,25 @@ void cache_audio_worker(Clip* c, Clip* nest) { rev_frame->nb_samples += frame->nb_samples; -// if (c->frame->pts == c->rev_target) { if ((c->frame->pts >= c->reverse_target) || (ret == AVERROR_EOF)) { - /*dout << "time for the end of rev cache" << rev_frame->nb_samples << c->rev_target << c->frame->pts << c->frame->pkt_duration << c->frame->nb_samples; +/* +#ifdef AUDIOWARNINGS + dout << "time for the end of rev cache" << rev_frame->nb_samples << c->rev_target << c->frame->pts << c->frame->pkt_duration << c->frame->nb_samples; dout << "diff:" << (c->frame->pkt_pts + c->frame->pkt_duration) - c->rev_target; - int cutoff = qRound64 ((((c->frame->pkt_pts + c->frame->pkt_duration) - c->rev_target) * timebase) * c->sequence->audio_frequency); +#endif + int cutoff = qRound64((((c->frame->pkt_pts + c->frame->pkt_duration) - c->reverse_target) * timebase) * c->sequence->audio_frequency); if (cutoff > 0) { +#ifdef AUDIOWARNINGS dout << "cut off" << cutoff << "samples (rate:" << c->sequence->audio_frequency << ")"; +#endif rev_frame->nb_samples -= cutoff; - }*/ + } +*/ #ifdef AUDIOWARNINGS dout << "pre cutoff deets::: rev_frame.pts:" << rev_frame->pts << "rev_frame.nb_samples" << rev_frame->nb_samples << "rev_target:" << c->reverse_target; #endif - rev_frame->nb_samples = qRound64(static_cast(c->reverse_target - rev_frame->pts) / c->stream->codecpar->sample_rate * c->sequence->audio_frequency); + rev_frame->nb_samples = qRound64(static_cast(c->reverse_target - rev_frame->pts) / c->stream->codecpar->sample_rate * (c->sequence->audio_frequency / c->speed)); #ifdef AUDIOWARNINGS dout << "post cutoff deets::" << rev_frame->nb_samples; #endif @@ -337,6 +342,7 @@ void cache_audio_worker(Clip* c, Clip* nest) { #ifdef AUDIOWARNINGS if (c->audio_buffer_write >= buffer_timeline_out) dout << "timeline out at fsi" << c->frame_sample_index << "of frame ts" << c->frame->pts; #endif + audio_write_lock.unlock(); if (c->frame_sample_index == nb_bytes) { @@ -360,25 +366,20 @@ void cache_video_worker(Clip* c, long playhead) { int64_t target_pts = seconds_to_timestamp(c, playhead_to_clip_seconds(c, playhead)); int limit = c->max_queue_size; - if (c->reverse) limit *= 2; - /*if (c->reverse) { - bool found = false; - for (int i=0;iqueue.size();i++) { - if (target_pts > c->queue.at(i)->pts && target_pts <= c->queue.at(i)->pts + c->queue.at(i)->pkt_duration) { - found = true; - break; - } - } - if (!found) { - // we need like one more frame - limit = c->queue.size() + 1; - } - }*/ + if (c->ignore_reverse) { + // waiting for one frame + limit = c->queue.size() + 1; + } else if (c->reverse) { + limit *= 2; + } if (c->queue.size() < limit) { + bool reverse = (c->reverse && !c->ignore_reverse); + c->ignore_reverse = false; + int64_t eighth_second = av_q2d(av_inv_q(c->stream->time_base))*0.125; int64_t smallest_pts = INT64_MAX; - if (c->reverse && c->queue.size() > 0) { + if (reverse && c->queue.size() > 0) { int64_t quarter_sec = qRound64(av_q2d(av_inv_q(c->stream->time_base))) >> 2; for (int i=0;iqueue.size();i++) { smallest_pts = qMin(smallest_pts, c->queue.at(i)->pts); @@ -401,7 +402,7 @@ void cache_video_worker(Clip* c, long playhead) { if (read_ret >= 0) { bool send_it = false; - if (c->reverse) { + if (reverse) { send_it = true; } else if (send_frame->pts > target_pts - eighth_second) { send_it = true; @@ -438,7 +439,7 @@ void cache_video_worker(Clip* c, long playhead) { av_frame_free(&frame); break; } else { - if (c->reverse && ((smallest_pts == target_pts && frame->pts >= smallest_pts) || (smallest_pts != target_pts && frame->pts > smallest_pts))) { + if (reverse && ((smallest_pts == target_pts && frame->pts >= smallest_pts) || (smallest_pts != target_pts && frame->pts > smallest_pts))) { av_frame_free(&frame); break; } else { @@ -446,27 +447,23 @@ void cache_video_worker(Clip* c, long playhead) { c->queue_lock.lock(); c->queue.append(frame); - if (!c->reverse && c->queue.size() == limit) { -// if (rendering) { - // see if we got the frame we needed (used for speed ups primarily) - bool found = false; - for (int i=0;iqueue.size();i++) { - // TODO/NOTE: this will not work on clips that are sped up AND reversed - if (c->queue.at(i)->pts >= target_pts) { - found = true; - break; - } - } - if (found) { - c->queue_lock.unlock(); + if (!reverse && c->queue.size() == limit) { + // see if we got the frame we needed (used for speed ups primarily) + bool found = false; + for (int i=0;iqueue.size();i++) { + // TODO/NOTE: this will not work on clips that are sped up AND reversed + if (c->queue.at(i)->pts >= target_pts) { + found = true; break; - } else { - // remove earliest frame and loop to store another - c->queue_remove_earliest(); } -// } else { -// break; -// } + } + if (found) { + c->queue_lock.unlock(); + break; + } else { + // remove earliest frame and loop to store another + c->queue_remove_earliest(); + } } c->queue_lock.unlock(); } diff --git a/playback/playback.cpp b/playback/playback.cpp index d88ad52ab..09b418a70 100644 --- a/playback/playback.cpp +++ b/playback/playback.cpp @@ -197,7 +197,8 @@ void get_clip_frame(Clip* c, long playhead) { #ifdef GCF_DEBUG dout << "GCF ==> WAIT - target pts:" << target_pts << "closest frame:" << target_frame->pts; #endif - //if (c->queue.size() >= c->max_queue_size) c->queue_remove_earliest(); + if (c->queue.size() >= c->max_queue_size) c->queue_remove_earliest(); + c->ignore_reverse = true; target_frame = NULL; } } diff --git a/project/clip.cpp b/project/clip.cpp index 6d2bc4829..6f1f49b1b 100644 --- a/project/clip.cpp +++ b/project/clip.cpp @@ -35,7 +35,8 @@ Clip::Clip(Sequence* s) : autoscale(config.autoscale_by_default), maintain_audio_pitch(false), reverse(false), - use_existing_frame(false) + use_existing_frame(false), + ignore_reverse(false) { reset(); } diff --git a/project/clip.h b/project/clip.h index 559f325f3..6e43be8c2 100644 --- a/project/clip.h +++ b/project/clip.h @@ -94,6 +94,7 @@ struct Clip bool finished_opening; bool replaced; int skip_type; + bool ignore_reverse; // caching functions bool use_existing_frame; diff --git a/project/undo.cpp b/project/undo.cpp index d794730ff..bd8a92d50 100644 --- a/project/undo.cpp +++ b/project/undo.cpp @@ -1719,8 +1719,34 @@ MoveEffectCommand::MoveEffectCommand() : void MoveEffectCommand::undo() { clip->effects.move(to, from); + mainWindow->setWindowModified(old_project_changed); } void MoveEffectCommand::redo() { clip->effects.move(from, to); + mainWindow->setWindowModified(true); +} + +RemoveClipsFromClipboard::RemoveClipsFromClipboard(int index) : + pos(index), + old_project_changed(mainWindow->isWindowModified()), + done(false) +{} + +RemoveClipsFromClipboard::~RemoveClipsFromClipboard() { + if (done) { + delete clip; + } +} + +void RemoveClipsFromClipboard::undo() { + panel_timeline->clip_clipboard.insert(pos, clip); + done = false; +} + +void RemoveClipsFromClipboard::redo() { + qDebug() << "removed" << pos << "from clipboard"; + clip = panel_timeline->clip_clipboard.at(pos); + panel_timeline->clip_clipboard.removeAt(pos); + done = true; } diff --git a/project/undo.h b/project/undo.h index f5566d4c4..ae1242aa2 100644 --- a/project/undo.h +++ b/project/undo.h @@ -557,4 +557,17 @@ private: bool old_project_changed; }; +class RemoveClipsFromClipboard : public QUndoCommand { +public: + RemoveClipsFromClipboard(int index); + ~RemoveClipsFromClipboard(); + void undo(); + void redo(); +private: + int pos; + Clip* clip; + bool old_project_changed; + bool done; +}; + #endif // UNDO_H diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 41411cb3f..145735a95 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -235,7 +235,6 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { } if (config.enable_drag_files_to_timeline && event->mimeData()->hasUrls()) { - dout << "TODO get data for:"; QList urls = event->mimeData()->urls(); if (!urls.isEmpty()) { QStringList file_list; @@ -247,6 +246,8 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { panel_project->process_file_list(false, file_list, NULL, false); for (int i=0;ilast_imported_media.size();i++) { + // waits for media to have a duration + // TODO would be much nicer if this was multithreaded panel_project->last_imported_media.at(i)->ready_lock.lock(); panel_project->last_imported_media.at(i)->ready_lock.unlock();