progress.setValue(0);
double total_length = compute_time_left(clips, { { 0, 0.0 } });
+ vector<Player::ClipWithRow> clips_with_row;
+ for (const Clip &clip : clips) {
+ clips_with_row.emplace_back(Player::ClipWithRow{ clip, 0 });
+ }
promise<void> done_promise;
future<void> done = done_promise.get_future();
player.set_progress_callback([¤t_value, &clips, total_length](const std::map<size_t, double> &player_progress) {
current_value = 1.0 - compute_time_left(clips, player_progress) / total_length;
});
- player.play(clips);
+ player.play(clips_with_row);
while (done.wait_for(std::chrono::milliseconds(100)) != future_status::ready && !progress.wasCanceled()) {
progress.setValue(lrint(100000.0 * current_value));
}
if (selected->hasSelection()) {
QModelIndex index = selected->currentIndex();
const Clip &clip = *playlist_clips->clip(index.row());
- preview_player->play({ clip });
+ preview_player->play(clip);
return;
}
}
QItemSelectionModel *selected = ui->clip_list->selectionModel();
if (!selected->hasSelection()) {
- preview_player->play({ *cliplist_clips->back() });
+ preview_player->play(*cliplist_clips->back());
return;
}
} else {
clip.stream_idx = ui->preview_display->get_stream_idx();
}
- preview_player->play({ clip });
+ preview_player->play(clip);
}
void MainWindow::preview_angle_clicked(unsigned stream_idx)
start_row = selected->selectedRows(0)[0].row();
}
- live_player_index_to_row.clear();
-
- vector<Clip> clips;
+ vector<Player::ClipWithRow> clips;
for (unsigned row = start_row; row < playlist_clips->size(); ++row) {
- live_player_index_to_row.emplace(clips.size(), row);
- clips.push_back(*playlist_clips->clip(row));
+ clips.emplace_back(Player::ClipWithRow{ *playlist_clips->clip(row), row });
}
live_player->play(clips);
playlist_clips->set_progress({ { start_row, 0.0f } });
fake_clip.pts_out = 0;
size_t last_row = playlist_clips->size() - 1;
playlist_clips->set_currently_playing(last_row, 0.0f);
- live_player_index_to_row.clear();
- live_player->play({ fake_clip });
+ live_player->play(fake_clip);
}
void MainWindow::live_player_clip_done()
void MainWindow::live_player_clip_progress(const map<size_t, double> &progress)
{
- map<size_t, double> converted_progress;
- for (const auto &it : progress) {
- if (live_player_index_to_row.count(it.first)) {
- converted_progress.emplace(live_player_index_to_row[it.first], it.second);
- }
- }
- playlist_clips->set_progress(converted_progress);
+ playlist_clips->set_progress(progress);
vector<Clip> clips;
for (size_t row = 0; row < playlist_clips->size(); ++row) {
Clip fake_clip;
fake_clip.pts_in = pts;
fake_clip.pts_out = pts + 1;
- preview_player->play({ fake_clip });
+ preview_player->play(fake_clip);
}
void MainWindow::playlist_selection_changed()
QLabel *disk_free_label;
std::unique_ptr<Player> preview_player, live_player;
- std::map<size_t, size_t> live_player_index_to_row;
DB db;
unsigned num_cameras;
void Player::play_playlist_once()
{
- vector<Clip> clip_list;
+ vector<ClipWithRow> clip_list;
bool clip_ready;
steady_clock::time_point before_sleep = steady_clock::now();
}
steady_clock::time_point origin = steady_clock::now(); // TODO: Add a 100 ms buffer for ramp-up?
- int64_t in_pts_origin = clip_list[0].pts_in;
+ int64_t in_pts_origin = clip_list[0].clip.pts_in;
for (size_t clip_idx = 0; clip_idx < clip_list.size(); ++clip_idx) {
- const Clip &clip = clip_list[clip_idx];
- const Clip *next_clip = (clip_idx + 1 < clip_list.size()) ? &clip_list[clip_idx + 1] : nullptr;
+ const Clip &clip = clip_list[clip_idx].clip;
+ const Clip *next_clip = (clip_idx + 1 < clip_list.size()) ? &clip_list[clip_idx + 1].clip : nullptr;
int64_t out_pts_origin = pts;
double next_clip_fade_time = -1.0;
if (progress_callback != nullptr) {
// NOTE: None of this will take into account any snapping done below.
- map<size_t, double> progress{ { clip_idx, calc_progress(clip, in_pts_for_progress) } };
+ map<size_t, double> progress{ { clip_list[clip_idx].row, calc_progress(clip, in_pts_for_progress) } };
if (next_clip != nullptr && time_left_this_clip <= next_clip_fade_time) {
- progress[clip_idx + 1] = calc_progress(*next_clip, in_pts_secondary_for_progress);
+ progress[clip_list[clip_idx + 1].row] = calc_progress(*next_clip, in_pts_secondary_for_progress);
}
progress_callback(progress);
}
player_thread.join();
}
-void Player::play(const vector<Clip> &clips)
+void Player::play(const vector<Player::ClipWithRow> &clips)
{
lock_guard<mutex> lock(queue_state_mu);
new_clip_ready = true;
lock_guard<mutex> lock(queue_state_mu);
if (new_clip_ready) {
assert(queued_clip_list.size() == 1);
- queued_clip_list[0].stream_idx = stream_idx;
+ queued_clip_list[0].clip.stream_idx = stream_idx;
return;
}
Player(JPEGFrameView *destination, StreamOutput stream_output, AVFormatContext *file_avctx = nullptr);
~Player();
- void play(const std::vector<Clip> &clips);
+ struct ClipWithRow {
+ Clip clip;
+ unsigned row; // Used for progress callback only.
+ };
+ void play(const Clip &clip)
+ {
+ play({ ClipWithRow{ clip, 0 } });
+ }
+ void play(const std::vector<ClipWithRow> &clips);
void override_angle(unsigned stream_idx); // Assumes one-clip playlist only.
// Not thread-safe to set concurrently with playing.
// Not thread-safe to set concurrently with playing.
// Will be called back from the player thread.
- // The keys in the given map are indexes in the vector given to play().
+ // The keys in the given map are row members in the vector given to play().
using progress_callback_func = std::function<void(const std::map<size_t, double> &progress)>;
void set_progress_callback(progress_callback_func cb) { progress_callback = cb; }
std::mutex queue_state_mu;
std::condition_variable new_clip_changed;
- std::vector<Clip> queued_clip_list; // Under queue_state_mu.
+ std::vector<ClipWithRow> queued_clip_list; // Under queue_state_mu.
bool new_clip_ready = false; // Under queue_state_mu.
bool playing = false; // Under queue_state_mu.
int override_stream_idx = -1; // Under queue_state_mu.