diff options
| author | Carl Hetherington <cth@carlh.net> | 2021-10-15 00:30:44 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2021-10-15 19:49:42 +0200 |
| commit | cdd2f62fe5dd2c54ab41d4b4de02eea77e833430 (patch) | |
| tree | c743f9499b0d10d7965b15102895790f7a49cd0e | |
| parent | 18ed20b9191d7122d78251d047f9ff7873c313d6 (diff) | |
Ignore audio streams that fall too far behind (#2101).
| -rw-r--r-- | src/lib/player.cc | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/src/lib/player.cc b/src/lib/player.cc index b93bf3f4a..dcc89bab9 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -743,10 +743,38 @@ Player::pass () /* Emit any audio that is ready */ /* Work out the time before which the audio is definitely all here. This is the earliest last_push_end of one - of our streams, or the position of the _silent. + of our streams, or the position of the _silent. First, though we choose only streams that are less than + ignore_streams_behind seconds behind the furthest ahead (we assume that if a stream has fallen that far + behind it has finished). This is so that we don't withhold audio indefinitely awaiting data from a stream + that will never come, causing bugs like #2101. */ - auto pull_to = _playback_length; + constexpr int ignore_streams_behind = 5; + + using state_pair = std::pair<AudioStreamPtr, StreamState>; + + /* Find the 'leading' stream (i.e. the one that pushed data most recently) */ + auto latest_last_push_end = std::max_element( + _stream_states.begin(), + _stream_states.end(), + [](state_pair const& a, state_pair const& b) { return a.second.last_push_end < b.second.last_push_end; } + ); + + if (latest_last_push_end != _stream_states.end()) { + LOG_DEBUG_PLAYER("Leading stream is in %1 at %2", latest_last_push_end->second.piece->content->path(0), to_string(latest_last_push_end->second.last_push_end)); + } + + /* Now make a list of those streams that are less than ignore_streams_behind behind the leader */ + std::map<AudioStreamPtr, StreamState> alive_stream_states; for (auto const& i: _stream_states) { + if ((latest_last_push_end->second.last_push_end - i.second.last_push_end) < dcpomatic::DCPTime::from_seconds(ignore_streams_behind)) { + alive_stream_states.insert(i); + } else { + LOG_DEBUG_PLAYER("Ignoring stream %1 because it is too far behind", i.second.piece->content->path(0)); + } + } + + auto pull_to = _playback_length; + for (auto const& i: alive_stream_states) { if (!i.second.piece->done && i.second.last_push_end < pull_to) { pull_to = i.second.last_push_end; } |
