diff --git a/lib/talk/starChart/views/native/talk_view_native_decode_logic.dart b/lib/talk/starChart/views/native/talk_view_native_decode_logic.dart index e7570394..97522643 100644 --- a/lib/talk/starChart/views/native/talk_view_native_decode_logic.dart +++ b/lib/talk/starChart/views/native/talk_view_native_decode_logic.dart @@ -52,6 +52,15 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { int audioBufferSize = 2; // 音频默认缓冲2帧 + // 回绕阈值,动态调整,frameSeq较小时阈值也小 + int _getFrameSeqRolloverThreshold(int lastSeq) { + if (lastSeq > 2000) { + return 1000; + } else { + return (lastSeq / 2).round(); + } + } + // 定义音频帧缓冲和发送函数 final List _bufferedAudioFrames = []; @@ -163,28 +172,35 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { int frameSeqI, ScpMessage scpMessage, ) { - // 检测frameSeq回绕,且为I帧 + + // 动态回绕阈值判断,frameSeq较小时阈值也小 if (!_pendingStreamReset && _lastFrameSeq != null && frameType == TalkDataH264Frame_FrameTypeE.I && frameSeq < _lastFrameSeq!) { - // 检测到新流I帧,进入loading并重置所有本地状态 - AppLog.log( - '检测到新流I帧,frameSeq回绕,进入loading并重置: frameSeq=$frameSeq, lastFrameSeq=$_lastFrameSeq'); - Future.microtask(() => state.isLoading.value = true); - _pendingStreamReset = true; - // 先暂停帧处理定时器,防止竞态 - _stopFrameProcessTimer(); - // 先释放并重新初始化解码器 - _resetDecoderForNewStream(_pendingResetWidth, _pendingResetHeight); - // 重置所有本地状态 - _lastFrameSeq = null; - _decodedIFrames.clear(); - state.h264FrameBuffer.clear(); - // 再恢复帧处理定时器 - _startFrameProcessTimer(); - // 不return,直接用该I帧初始化解码器并解码 - // 继续往下执行 + int dynamicThreshold = _getFrameSeqRolloverThreshold(_lastFrameSeq!); + if ((_lastFrameSeq! - frameSeq) > dynamicThreshold) { + // 检测到新流I帧,frameSeq大幅回绕,进入loading并重置所有本地状态 + AppLog.log('检测到新流I帧,frameSeq大幅回绕,进入loading并重置: frameSeq=$frameSeq, lastFrameSeq=$_lastFrameSeq, 阈值=$dynamicThreshold'); + Future.microtask(() => state.isLoading.value = true); + _pendingStreamReset = true; + // 先暂停帧处理定时器,防止竞态 + _stopFrameProcessTimer(); + // 先释放并重新初始化解码器 + _resetDecoderForNewStream(_pendingResetWidth, _pendingResetHeight); + // 重置所有本地状态 + _lastFrameSeq = null; + _decodedIFrames.clear(); + state.h264FrameBuffer.clear(); + // 再恢复帧处理定时器 + _startFrameProcessTimer(); + // 不return,直接用该I帧初始化解码器并解码 + // 继续往下执行 + } else { + // 小幅度乱序,直接丢弃 + AppLog.log('检测到I帧乱序(未超过回绕阈值$dynamicThreshold),丢弃: frameSeq=$frameSeq, lastFrameSeq=$_lastFrameSeq'); + return; + } } // 如果处于pendingStreamReset,等待新I帧 if (_pendingStreamReset) {