From 293716f146ad47fd7b470e96c2aa7a7dc9a54c3a Mon Sep 17 00:00:00 2001 From: liyi Date: Mon, 23 Jun 2025 16:00:37 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E5=88=87=E6=8D=A2?= =?UTF-8?q?=E6=B8=85=E6=99=B0=E5=BA=A6=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../native/talk_view_native_decode_logic.dart | 52 ++++++++++++------- 1 file changed, 34 insertions(+), 18 deletions(-) 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) {