From a6d53858f68899776ca495ec791315c4d17347c9 Mon Sep 17 00:00:00 2001 From: sky_min Date: Mon, 10 Nov 2025 17:53:20 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96ios=E8=A7=86=E9=A2=91bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../native/talk_view_native_decode_logic.dart | 101 ++++++++++++------ 1 file changed, 71 insertions(+), 30 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 7b5963ec..72d9f6cf 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 @@ -61,21 +61,35 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { final actualRatio = _actualFps / targetFps; // 更加保守和稳定的调整策略 - if (actualRatio < 0.4) { - // 处理能力严重不足,大幅降低目标帧率 - state.targetFps = (targetFps * 0.6).round().clamp(15, 60); - _startFrameProcessTimer(); - } else if (actualRatio < 0.6) { - // 处理能力不足,中等幅度降低帧率 - state.targetFps = (targetFps * 0.8).round().clamp(15, 60); - _startFrameProcessTimer(); - } else if (actualRatio > 1.8 && targetFps < 25) { - // 处理能力充足,可以提高帧率 - state.targetFps = (targetFps * 1.15).round().clamp(15, 30); - _startFrameProcessTimer(); + // iOS平台使用更保守的调整策略 + if (Platform.isIOS) { + if (actualRatio < 0.25) { + // iOS处理能力严重不足,大幅降低目标帧率 + state.targetFps = (targetFps * 0.6).round().clamp(15, 60); + _startFrameProcessTimer(); + } else if (actualRatio < 0.45) { + // iOS处理能力不足,中等幅度降低帧率 + state.targetFps = (targetFps * 0.8).round().clamp(15, 60); + _startFrameProcessTimer(); + } else if (actualRatio > 2.5 && targetFps < 25) { + // iOS处理能力充足,可以提高帧率 + state.targetFps = (targetFps * 1.05).round().clamp(15, 30); + _startFrameProcessTimer(); + } + } else { + // Android平台原有逻辑 + if (actualRatio < 0.4) { + state.targetFps = (targetFps * 0.6).round().clamp(15, 60); + _startFrameProcessTimer(); + } else if (actualRatio < 0.6) { + state.targetFps = (targetFps * 0.8).round().clamp(15, 60); + _startFrameProcessTimer(); + } else if (actualRatio > 1.8 && targetFps < 25) { + state.targetFps = (targetFps * 1.15).round().clamp(15, 30); + _startFrameProcessTimer(); + } } - // 注意:避免过于积极地提高帧率,这可能导致卡顿 - } + }// 注意:避免过于积极地提高帧率,这可能导致卡顿 } // 回绕阈值,动态调整,frameSeq较小时阈值也小 @@ -139,7 +153,9 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { ); // 使用超时控制避免长时间等待 - final timeoutFuture = Future.delayed(const Duration(seconds: 3), () => null); + // iOS平台使用更短的超时时间 + final timeoutSeconds = Platform.isIOS ? 2 : 3; + final timeoutFuture = Future.delayed(Duration(seconds: timeoutSeconds), () => null); final decoderFuture = VideoDecodePlugin.initDecoder(config); // 初始化解码器并获取textureId @@ -163,9 +179,11 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { AppLog.log('初始化视频解码器错误: $e'); state.isLoading.value = false; // 如果初始化失败,延迟后重试 - await Future.delayed(const Duration(seconds: 1)); + // iOS平台使用更短的重试延迟 + final delaySeconds = Platform.isIOS ? 0.5 : 1; + await Future.delayed(Duration(milliseconds: (delaySeconds * 1000).toInt())); if (!Get.isRegistered()) { - return; // 如果控制器已经被销毁,不再重试 + return; } _initVideoDecoder(); // 重试初始化 } @@ -292,7 +310,10 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { _stopFrameProcessTimer(); // 计算定时器间隔,确保以目标帧率处理帧 - final int intervalMs = max(16, min(40, (1000 / state.targetFps).round())); + // iOS平台使用更精确的定时器间隔 + final int intervalMs = Platform.isIOS + ? max(16, min(33, (1000 / state.targetFps).round())) // iOS使用更严格的范围 + : max(16, min(40, (1000 / state.targetFps).round())); // 创建新定时器 state.frameProcessTimer = Timer.periodic(Duration(milliseconds: intervalMs), (timer) { @@ -368,12 +389,22 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { final bufferLength = state.h264FrameBuffer.length; // 更智能的帧率调整策略 - if (bufferLength > 50) { - // 缓冲区过长,临时提高处理频率 - _temporarilyIncreaseProcessFrequency(); - } else if (bufferLength < 5) { - // 缓冲区过短,降低处理频率节省资源 - _adjustFrameProcessFrequency((state.targetFps * 0.9).toDouble()); + // iOS平台优化:更积极的缓冲区管理 + if (Platform.isIOS) { + if (bufferLength > 40) { + // iOS缓冲区过长,临时提高处理频率 + _temporarilyIncreaseProcessFrequency(); + } else if (bufferLength < 3) { + // iOS缓冲区过短,降低处理频率节省资源 + _adjustFrameProcessFrequency((state.targetFps * 0.95).toDouble()); + } + } else { + // Android平台原有逻辑 + if (bufferLength > 50) { + _temporarilyIncreaseProcessFrequency(); + } else if (bufferLength < 5) { + _adjustFrameProcessFrequency((state.targetFps * 0.9).toDouble()); + } } // 查找最适合处理的帧 @@ -438,6 +469,8 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { // 异步发送帧,添加超时处理 try { + // iOS平台使用更短的超时时间 + final timeoutMs = Platform.isIOS ? 15 : 20; await VideoDecodePlugin.sendFrame( frameData: frameData, frameType: pluginFrameType, @@ -445,7 +478,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { timestamp: pts, splitNalFromIFrame: true, refIFrameSeq: frameSeqI, - ).timeout(const Duration(milliseconds: 20)); // 进一步缩短超时时间 + ).timeout(Duration(milliseconds: timeoutMs)); // 进一步缩短超时时间 // 更新最后解码的I帧序号 if (frameType == TalkDataH264Frame_FrameTypeE.I) { @@ -462,7 +495,9 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { final durationMs = (endTime - startTime) / 1000.0; // 性能监控 - 更宽松的阈值 - if (durationMs > 30) { + // iOS平台使用更严格的性能监控 + final thresholdMs = Platform.isIOS ? 25 : 30; + if (durationMs > thresholdMs) { AppLog.log('帧处理耗时过长: ${durationMs.toStringAsFixed(2)} ms, 缓冲区长度: ${state.h264FrameBuffer.length}'); } } @@ -482,7 +517,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { _adjustFrameProcessFrequency(tempFps.toDouble()); - // 3秒后恢复原频率 + // 2秒后恢复原频率 _tempAdjustTimer = Timer(const Duration(seconds: 2), () { _adjustFrameProcessFrequency(originalFps.toDouble()); _tempAdjustTimer = null; @@ -1012,7 +1047,9 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { if (state.textureId.value != null) { try { // 极短超时时间,避免阻塞 - await VideoDecodePlugin.releaseDecoder().timeout(const Duration(milliseconds: 300)); + // iOS平台使用更短的超时时间 + final timeoutMs = Platform.isIOS ? 200 : 300; + await VideoDecodePlugin.releaseDecoder().timeout(Duration(milliseconds: timeoutMs)); state.textureId.value = null; } catch (e) { AppLog.log('释放解码器超时或失败: $e'); @@ -1022,7 +1059,9 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { } // 最小化等待时间 - await Future.delayed(Duration(milliseconds: 2)); + // iOS平台使用更短的等待时间 + final delayMs = Platform.isIOS ? 0 : 1; + await Future.delayed(Duration(milliseconds: delayMs)); // 创建新的解码器配置 final config = VideoDecoderConfig( @@ -1034,8 +1073,10 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { // 初始化新解码器 try { // 使用较短超时时间 + // iOS平台使用更短的超时时间 + final timeoutMs = Platform.isIOS ? 1000 : 1500; final textureId = await VideoDecodePlugin.initDecoder(config) - .timeout(const Duration(milliseconds: 1500)); + .timeout(Duration(milliseconds: timeoutMs)); if (textureId != null) { state.textureId.value = textureId;