From 780ae8ccd25dfcd2b3542d30be0edf1a55e36ee4 Mon Sep 17 00:00:00 2001 From: "sky.min" Date: Tue, 6 Jan 2026 11:13:26 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96iphone=E6=89=8B=E6=9C=BA?= =?UTF-8?q?=E7=AC=AC=E4=B8=80=E6=AC=A1=E7=82=B9=E5=87=BB=E7=9B=91=E6=8E=A7?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E6=8E=A5=E9=80=9A=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../native/talk_view_native_decode_logic.dart | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) 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 330f037f..a774acfd 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 @@ -40,6 +40,9 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { int bufferSize = 25; // 初始化为默认大小 int audioBufferSize = 20; // 音频默认缓冲2帧 + + // 添加一个计时器来监听videoWidth和videoHeight的变化 + Timer? _videoDimensionCheckTimer; // 回绕阈值,动态调整,frameSeq较小时阈值也小 int _getFrameSeqRolloverThreshold(int lastSeq) { @@ -93,6 +96,10 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { Future _initVideoDecoder() async { try { state.isLoading.value = true; + + // 等待videoWidth和videoHeight有效(非0) + await _waitForValidVideoDimensions(); + // 创建解码器配置 final config = VideoDecoderConfig( width: StartChartManage().videoWidth, @@ -125,6 +132,86 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { _initVideoDecoder(); // 重试初始化 } } + + // 等待有效的视频尺寸 + Future _waitForValidVideoDimensions() async { + int attempts = 0; + const maxAttempts = 20; // 最多等待10秒 (20次 * 500ms) + + while (attempts < maxAttempts) { + // 检查videoWidth和videoHeight是否有效(非0) + if (StartChartManage().videoWidth != 0 && StartChartManage().videoHeight != 0) { + AppLog.log('获取到有效的视频尺寸: ${StartChartManage().videoWidth}x${StartChartManage().videoHeight}'); + return; + } + + attempts++; + await Future.delayed(const Duration(milliseconds: 500)); + AppLog.log('等待有效的视频尺寸... 第 $attempts 次, 当前尺寸: ${StartChartManage().videoWidth}x${StartChartManage().videoHeight}'); + } + + // 如果等待超时,使用默认尺寸 + AppLog.log('等待视频尺寸超时,使用默认尺寸: 864x480'); + StartChartManage().videoWidth = 864; + StartChartManage().videoHeight = 480; + } + + // iOS平台专用的视频解码器初始化方法,带有多次尝试逻辑 + Future _attemptVideoDecoderInitialization(VideoDecoderConfig config, {int maxAttempts = 3}) async { + for (int attempt = 1; attempt <= maxAttempts; attempt++) { + try { + AppLog.log('视频解码器初始化第 $attempt 次尝试, 尺寸: ${config.width}x${config.height}'); + final textureId = await VideoDecodePlugin.initDecoder(config); + if (textureId != null) { + AppLog.log('视频解码器初始化第 $attempt 次尝试成功'); + return textureId; + } + + // 如果失败,等待一段时间再重试 + if (attempt < maxAttempts) { + await Future.delayed(Duration(milliseconds: 500 * attempt)); + } + } catch (e) { + AppLog.log('视频解码器初始化第 $attempt 次尝试出错: $e'); + if (attempt < maxAttempts) { + await Future.delayed(Duration(milliseconds: 500 * attempt)); + } + } + } + + // 如果使用实际尺寸初始化失败,尝试使用默认尺寸 + AppLog.log('使用实际尺寸初始化失败,尝试使用默认尺寸重新初始化'); + final defaultConfig = VideoDecoderConfig( + width: 864, + height: 480, + codecType: 'h264', + ); + + for (int attempt = 1; attempt <= maxAttempts; attempt++) { + try { + AppLog.log('使用默认尺寸进行视频解码器初始化第 $attempt 次尝试'); + final textureId = await VideoDecodePlugin.initDecoder(defaultConfig); + if (textureId != null) { + AppLog.log('使用默认尺寸视频解码器初始化第 $attempt 次尝试成功'); + // 更新StartChartManage中的尺寸值 + StartChartManage().videoWidth = 864; + StartChartManage().videoHeight = 480; + return textureId; + } + + if (attempt < maxAttempts) { + await Future.delayed(Duration(milliseconds: 500 * attempt)); + } + } catch (e) { + AppLog.log('使用默认尺寸视频解码器初始化第 $attempt 次尝试出错: $e'); + if (attempt < maxAttempts) { + await Future.delayed(Duration(milliseconds: 500 * attempt)); + } + } + } + + return null; + } /// 初始化音频播放器 void _initFlutterPcmSound() { @@ -555,6 +642,9 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { requestPermissions(); + // 启动视频尺寸监听器 + _startVideoDimensionListener(); + // 初始化视频解码器 _initVideoDecoder(); @@ -612,6 +702,11 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { _startProcessingAudioTimer?.cancel(); _startProcessingAudioTimer = null; _bufferedAudioFrames.clear(); + + // 取消视频尺寸监听器 + _videoDimensionCheckTimer?.cancel(); + _videoDimensionCheckTimer = null; + super.onClose(); } @@ -922,6 +1017,21 @@ class TalkViewNativeDecodeLogic extends BaseGetXController { } } + // 监听视频尺寸变化,当它们更新时尝试初始化解码器(如果尚未初始化) + void _startVideoDimensionListener() { + _videoDimensionCheckTimer = Timer.periodic(const Duration(milliseconds: 500), (timer) { + // 检查是否已经有有效的videoWidth和videoHeight,且解码器尚未初始化 + if (state.textureId.value == null && + StartChartManage().videoWidth != 0 && + StartChartManage().videoHeight != 0 ) { + // 尝试初始化解码器(如果尚未初始化) + if (state.textureId.value == null) { + _initVideoDecoder(); + } + } + }); + } + void _processFrame(TalkDataModel talkDataModel) { final talkData = talkDataModel.talkData; final talkDataH264Frame = talkDataModel.talkDataH264Frame;