- DCPTime pull_to = *_film_length;
- for (map<AudioStreamPtr, StreamState>::const_iterator i = _stream_states.begin(); i != _stream_states.end(); ++i) {
- if (!i->second.piece->done && i->second.last_push_end < pull_to) {
- pull_to = i->second.last_push_end;
+ 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;