Files
sm-emby-share/lib/features/player/session/stall_detector.dart
T
2026-07-14 11:11:36 +08:00

78 lines
2.0 KiB
Dart

class StallDetector {
StallDetector({this.threshold = const Duration(seconds: 15)})
: assert(threshold > Duration.zero);
final Duration threshold;
Duration? _lastPos;
Duration? _lastBuffer;
int? _lastBytes;
Duration _lastAdvanceAt = Duration.zero;
bool _fired = false;
bool update({
required Duration position,
required Duration bufferedPosition,
required int? bytesDownloaded,
required bool isActivelyPlaying,
required Duration now,
}) {
if (!isActivelyPlaying) {
_lastPos = position;
_lastBuffer = bufferedPosition;
_lastBytes = bytesDownloaded;
_lastAdvanceAt = now;
return false;
}
if (_lastPos == null) {
_lastPos = position;
_lastBuffer = bufferedPosition;
_lastBytes = bytesDownloaded;
_lastAdvanceAt = now;
return false;
}
final positionAdvanced = position != _lastPos;
final bytesBecameAvailable = bytesDownloaded != null && _lastBytes == null;
final hasComparableByteSamples =
bytesDownloaded != null && _lastBytes != null;
final bytesAdvanced =
hasComparableByteSamples && bytesDownloaded != _lastBytes;
final bufferAdvanced = bufferedPosition != _lastBuffer;
final hasBufferedMedia =
bufferedPosition - position > const Duration(seconds: 2);
final transportAdvanced = bytesBecameAvailable ||
(hasComparableByteSamples
? bytesAdvanced
: bufferAdvanced || hasBufferedMedia);
final progressed = positionAdvanced || transportAdvanced;
_lastPos = position;
_lastBuffer = bufferedPosition;
_lastBytes = bytesDownloaded;
if (progressed) {
_lastAdvanceAt = now;
_fired = false;
return false;
}
if (_fired) return false;
if (now - _lastAdvanceAt >= threshold) {
_fired = true;
return true;
}
return false;
}
void reset() {
_lastPos = null;
_lastBuffer = null;
_lastBytes = null;
_lastAdvanceAt = Duration.zero;
_fired = false;
}
}