From: Steinar H. Gunderson Date: Fri, 28 Dec 2018 11:33:53 +0000 (+0100) Subject: Move estimation of time left into Player. X-Git-Tag: 1.8.1~17 X-Git-Url: https://git.sesse.net/?p=nageru;a=commitdiff_plain;h=4d7015171fbd6c36c480d1d7992b76bbb45410c5 Move estimation of time left into Player. --- diff --git a/futatabi/export.cpp b/futatabi/export.cpp index 2b9f531..1aea044 100644 --- a/futatabi/export.cpp +++ b/futatabi/export.cpp @@ -223,11 +223,11 @@ void export_interpolated_clip(const string &filename, const vector &clips) progress.setMaximum(100000); progress.setValue(0); - double total_length = compute_time_left(clips, { { 0, 0.0 } }); vector clips_with_row; for (const Clip &clip : clips) { clips_with_row.emplace_back(Player::ClipWithRow{ clip, 0 }); } + double total_length = compute_total_time(clips_with_row); promise done_promise; future done = done_promise.get_future(); @@ -240,8 +240,8 @@ void export_interpolated_clip(const string &filename, const vector &clips) done_promise.set_value(); } }); - 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.set_progress_callback([¤t_value, &clips, total_length](const std::map &player_progress, double time_remaining) { + current_value = 1.0 - time_remaining / total_length; }); player.play(clips_with_row); while (done.wait_for(std::chrono::milliseconds(100)) != future_status::ready && !progress.wasCanceled()) { diff --git a/futatabi/mainwindow.cpp b/futatabi/mainwindow.cpp index 5cbfb13..bbaa5a4 100644 --- a/futatabi/mainwindow.cpp +++ b/futatabi/mainwindow.cpp @@ -189,9 +189,9 @@ MainWindow::MainWindow() live_player_clip_done(); }); }); - live_player->set_progress_callback([this](const map &progress) { - post_to_main_thread([this, progress] { - live_player_clip_progress(progress); + live_player->set_progress_callback([this](const map &progress, double time_remaining) { + post_to_main_thread([this, progress, time_remaining] { + live_player_clip_progress(progress, time_remaining); }); }); set_output_status("paused"); @@ -558,16 +558,10 @@ static string format_duration(double t) return buf; } -void MainWindow::live_player_clip_progress(const map &progress) +void MainWindow::live_player_clip_progress(const map &progress, double time_remaining) { playlist_clips->set_progress(progress); - - vector clips; - for (size_t row = 0; row < playlist_clips->size(); ++row) { - clips.push_back(*playlist_clips->clip(row)); - } - double remaining = compute_time_left(clips, progress); - set_output_status(format_duration(remaining) + " left"); + set_output_status(format_duration(time_remaining) + " left"); } void MainWindow::resizeEvent(QResizeEvent *event) @@ -849,11 +843,11 @@ void MainWindow::playlist_selection_changed() if (!any_selected) { set_output_status("paused"); } else { - vector clips; - for (size_t row = 0; row < playlist_clips->size(); ++row) { - clips.push_back(*playlist_clips->clip(row)); + vector clips; + for (size_t row = selected->selectedRows().front().row(); row < playlist_clips->size(); ++row) { + clips.emplace_back(Player::ClipWithRow{ *playlist_clips->clip(row), row }); } - double remaining = compute_time_left(clips, { { selected->selectedRows().front().row(), 0.0 } }); + double remaining = compute_total_time(clips); set_output_status(format_duration(remaining) + " ready"); } } diff --git a/futatabi/mainwindow.h b/futatabi/mainwindow.h index 33a510e..67e46dd 100644 --- a/futatabi/mainwindow.h +++ b/futatabi/mainwindow.h @@ -104,7 +104,7 @@ private: void stop_clicked(); void live_player_clip_done(); std::pair live_player_get_next_clip(); - void live_player_clip_progress(const std::map &progress); + void live_player_clip_progress(const std::map &progress, double time_remaining); void set_output_status(const std::string &status); void playlist_duplicate(); void playlist_remove(); diff --git a/futatabi/player.cpp b/futatabi/player.cpp index a82b16e..3545eb1 100644 --- a/futatabi/player.cpp +++ b/futatabi/player.cpp @@ -179,11 +179,17 @@ void Player::play_playlist_once() if (progress_callback != nullptr) { // NOTE: None of this will take into account any snapping done below. - map progress{ { clip_list[clip_idx].row, calc_progress(clip, in_pts_for_progress) } }; + double clip_progress = calc_progress(clip, in_pts_for_progress); + map progress{ { clip_list[clip_idx].row, clip_progress } }; + double time_remaining; if (next_clip != nullptr && time_left_this_clip <= next_clip_fade_time) { - progress[clip_list[clip_idx + 1].row] = calc_progress(*next_clip, in_pts_secondary_for_progress); + double next_clip_progress = calc_progress(*next_clip, in_pts_secondary_for_progress); + progress[clip_list[clip_idx + 1].row] = next_clip_progress; + time_remaining = compute_time_left(clip_list, clip_idx + 1, next_clip_progress); + } else { + time_remaining = compute_time_left(clip_list, clip_idx, clip_progress); } - progress_callback(progress); + progress_callback(progress, time_remaining); } FrameOnDisk frame_lower, frame_upper; @@ -480,20 +486,17 @@ void Player::release_queue_spot() new_clip_changed.notify_all(); } -double compute_time_left(const vector &clips, const map &progress) +double compute_time_left(const vector &clips, size_t currently_playing_idx, double progress_currently_playing) { // Look at the last clip and then start counting from there. - assert(!progress.empty()); - auto last_it = progress.end(); - --last_it; double remaining = 0.0; double last_fade_time_seconds = 0.0; - for (size_t row = last_it->first; row < clips.size(); ++row) { - const Clip &clip = clips[row]; + for (size_t row = currently_playing_idx; row < clips.size(); ++row) { + const Clip &clip = clips[row].clip; double clip_length = double(clip.pts_out - clip.pts_in) / TIMEBASE / clip.speed; - if (row == last_it->first) { + if (row == currently_playing_idx) { // A clip we're playing: Subtract the part we've already played. - remaining = clip_length * (1.0 - last_it->second); + remaining = clip_length * (1.0 - progress_currently_playing); } else { // A clip we haven't played yet: Subtract the part that's overlapping // with a previous clip (due to fade). diff --git a/futatabi/player.h b/futatabi/player.h index a581a54..c8ed083 100644 --- a/futatabi/player.h +++ b/futatabi/player.h @@ -20,8 +20,6 @@ class VideoStream; class QSurface; class QSurfaceFormat; -double compute_time_left(const std::vector &clips, const std::map &progress); - class Player : public QueueInterface { public: enum StreamOutput { @@ -34,7 +32,7 @@ public: struct ClipWithRow { Clip clip; - unsigned row; // Used for progress callback only. + size_t row; // Used for progress callback only. }; void play(const Clip &clip) { @@ -51,7 +49,7 @@ public: // Not thread-safe to set concurrently with playing. // Will be called back from the player thread. // The keys in the given map are row members in the vector given to play(). - using progress_callback_func = std::function &progress)>; + using progress_callback_func = std::function &progress, double time_remaining)>; void set_progress_callback(progress_callback_func cb) { progress_callback = cb; } // QueueInterface. @@ -107,4 +105,11 @@ private: const StreamOutput stream_output; }; +double compute_time_left(const std::vector &clips, size_t currently_playing_idx, double progress_currently_playing); + +static inline double compute_total_time(const std::vector &clips) +{ + return compute_time_left(clips, 0, 0.0); +} + #endif // !defined(_PLAYER_H)