From: Steinar H. Gunderson Date: Fri, 14 Dec 2018 23:39:05 +0000 (+0100) Subject: Support exporting multiple clips of a playlist, with fades and all. X-Git-Tag: 1.8.0~19 X-Git-Url: https://git.sesse.net/?p=nageru;a=commitdiff_plain;h=9725acd82ef5fd6ee02761fc4f50ba57d10c18dc Support exporting multiple clips of a playlist, with fades and all. --- diff --git a/futatabi/export.cpp b/futatabi/export.cpp index a653f01..fe713b4 100644 --- a/futatabi/export.cpp +++ b/futatabi/export.cpp @@ -197,7 +197,7 @@ void export_multitrack_clip(const string &filename, const Clip &clip) progress.setValue(frames_written); } -void export_interpolated_clip(const string &filename, const Clip &clip) +void export_interpolated_clip(const string &filename, const vector &clips) { AVFormatContext *avctx = nullptr; avformat_alloc_output_context2(&avctx, NULL, NULL, filename.c_str()); @@ -224,19 +224,30 @@ void export_interpolated_clip(const string &filename, const Clip &clip) progress.setMaximum(100000); progress.setValue(0); + double total_length = compute_time_left(clips, {{0, 0.0}}); + promise done_promise; future done = done_promise.get_future(); std::atomic current_value{0.0}; + size_t clip_idx = 0; Player player(/*destination=*/nullptr, Player::FILE_STREAM_OUTPUT, closer.release()); - player.set_done_callback([&done_promise] { - done_promise.set_value(); + player.set_done_callback([&done_promise, &clip_idx, &clips] { + if (clip_idx >= clips.size()) { + done_promise.set_value(); + } + }); + player.set_next_clip_callback([&clip_idx, &clips]() -> pair { + if (++clip_idx >= clips.size()) { + return make_pair(Clip(), -1); + } else { + return make_pair(clips[clip_idx], clip_idx); + } }); - player.set_progress_callback([¤t_value] (const std::map &player_progress) { - assert(player_progress.size() == 1); - current_value = player_progress.begin()->second; + player.set_progress_callback([¤t_value, &clips, total_length] (const std::map &player_progress) { + current_value = 1.0 - compute_time_left(clips, player_progress) / total_length; }); - player.play_clip(clip, /*clip_idx=*/0, clip.stream_idx); + player.play_clip(clips[0], clip_idx, clips[0].stream_idx); while (done.wait_for(std::chrono::milliseconds(100)) != future_status::ready && !progress.wasCanceled()) { progress.setValue(lrint(100000.0 * current_value)); } diff --git a/futatabi/export.h b/futatabi/export.h index 934937c..0397749 100644 --- a/futatabi/export.h +++ b/futatabi/export.h @@ -2,8 +2,9 @@ #define _EXPORT_H 1 #include +#include void export_multitrack_clip(const std::string &filename, const Clip &clip); -void export_interpolated_clip(const std::string &filename, const Clip &clip); +void export_interpolated_clip(const std::string &filename, const std::vector &clips); #endif diff --git a/futatabi/mainwindow.cpp b/futatabi/mainwindow.cpp index 7455cac..7cc27b4 100644 --- a/futatabi/mainwindow.cpp +++ b/futatabi/mainwindow.cpp @@ -796,8 +796,6 @@ void MainWindow::export_playlist_clip_interpolated_triggered() return; } - QModelIndex index = selected->currentIndex(); - Clip clip = *playlist_clips->clip(index.row()); QString filename = QFileDialog::getSaveFileName(this, "Export interpolated clip", QString(), tr("Matroska video files (*.mkv)")); if (filename.isNull()) { @@ -807,7 +805,13 @@ void MainWindow::export_playlist_clip_interpolated_triggered() if (!filename.endsWith(".mkv")) { filename += ".mkv"; } - export_interpolated_clip(filename.toStdString(), clip); + + vector clips; + QModelIndexList rows = selected->selectedRows(); + for (QModelIndex index : rows) { + clips.push_back(*playlist_clips->clip(index.row())); + } + export_interpolated_clip(filename.toStdString(), clips); } void MainWindow::manual_triggered() diff --git a/futatabi/mainwindow.ui b/futatabi/mainwindow.ui index 81167d8..2950e67 100644 --- a/futatabi/mainwindow.ui +++ b/futatabi/mainwindow.ui @@ -492,7 +492,7 @@ - Selected playlist clip as &interpolated single track… + Selected playlist clip(s) as &interpolated single track…