import 'dart:typed_data'; /// SPS/PPS/I帧依赖关系管理器 class FrameDependencyManager { Uint8List? _sps; Uint8List? _pps; final int windowSize = 10; final List _iFrameSeqWindow = []; // 丢帧自愈相关 int _dropCount = 0; final int dropThreshold = 10; // 可根据需要调整 /// 重置依赖管理器(自愈) void reset() { _iFrameSeqWindow.clear(); _dropCount = 0; } /// 更新SPS缓存 void updateSps(Uint8List? sps) { _sps = sps; } /// 更新PPS缓存 void updatePps(Uint8List? pps) { _pps = pps; } Uint8List? get sps => _sps; Uint8List? get pps => _pps; /// 判断是否有可用I帧 bool get hasIFrame => _iFrameSeqWindow.isNotEmpty; int? get lastIFrameSeq => _iFrameSeqWindow.isNotEmpty ? _iFrameSeqWindow.last : null; int get dropCount => _dropCount; int get dropThresholdValue => dropThreshold; void updateIFrameSeq(int seq) { _iFrameSeqWindow.add(seq); if (_iFrameSeqWindow.length > windowSize) { _iFrameSeqWindow.removeAt(0); } _dropCount = 0; // I帧解码时重置丢帧计数 // print('[FrameDependencyManager][调试] I帧解码成功,序号: $seq,当前I帧窗口: ${_iFrameSeqWindow.toString()}'); } /// 判断指定I帧序号是否在滑动窗口内 bool isIFrameDecoded(int? seq) { if (seq == null || !_iFrameSeqWindow.contains(seq)) { _dropCount++; // print('[FrameDependencyManager][调试] 当前I帧窗口: ${_iFrameSeqWindow.toString()},待查找I帧序号: $seq'); if (_dropCount >= dropThreshold) { print('[FrameDependencyManager][自愈] 连续丢帧$_dropCount次,自动reset依赖窗口'); reset(); } return false; } return true; } }