优化视频对讲 优化

This commit is contained in:
sky_min 2025-11-11 16:15:16 +08:00
parent f51a3abcb0
commit 705ba72e31
3 changed files with 159 additions and 54 deletions

View File

@ -804,6 +804,8 @@ class LockDetailLogic extends BaseGetXController {
} }
} }
//
int _networkQualityScore = 5; // 1-55
/// ///
void sendMonitorMessage() async { void sendMonitorMessage() async {
final catEyeConfig = state.keyInfos.value.lockSetting?.catEyeConfig ?? []; final catEyeConfig = state.keyInfos.value.lockSetting?.catEyeConfig ?? [];
@ -817,6 +819,30 @@ class LockDetailLogic extends BaseGetXController {
return; return;
} }
} }
//
switch (_networkQualityScore) {
case 1:
state.networkQualityMessage.value = '很差';
break;
case 2:
state.networkQualityMessage.value = '较差';
break;
case 3:
state.networkQualityMessage.value = '一般';
break;
case 4:
state.networkQualityMessage.value = '良好';
break;
case 5:
state.networkQualityMessage.value = '优秀';
break;
default:
state.networkQualityMessage.value = '';
}
//
if (_networkQualityScore < 4) {
showToast('网络质量'.tr + ':${state.networkQualityMessage.value}');
}
if (catEyeConfig.isNotEmpty && catEyeConfig.length > 0 && catEyeConfig[0].catEyeMode != 0) { if (catEyeConfig.isNotEmpty && catEyeConfig.length > 0 && catEyeConfig[0].catEyeMode != 0) {
if (network == null || network?.peerId == null || network?.peerId == '') { if (network == null || network?.peerId == null || network?.peerId == '') {
showToast('设备未配网'.tr); showToast('设备未配网'.tr);

View File

@ -17,6 +17,9 @@ class LockDetailState {
StreamSubscription? DetailLockInfo; StreamSubscription? DetailLockInfo;
StreamSubscription? SuccessfulDistributionNetworkEvent; StreamSubscription? SuccessfulDistributionNetworkEvent;
//
final RxInt networkQualityScore = 1.obs; // 1-55
final RxString networkQualityMessage = ''.obs; //
String lockNetToken = '0'; String lockNetToken = '0';
int differentialTime = 0; // int differentialTime = 0; //
bool isHaveNetwork = true; bool isHaveNetwork = true;

View File

@ -68,6 +68,15 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
final targetFps = state.targetFps.toDouble(); final targetFps = state.targetFps.toDouble();
final actualRatio = _actualFps / targetFps; final actualRatio = _actualFps / targetFps;
//
if (actualRatio < 0.3) {
state.targetFps = (targetFps * 0.5).round().clamp(15, 60);
_startFrameProcessTimer();
} else if (actualRatio < 0.5) {
state.targetFps = (targetFps * 0.7).round().clamp(15, 60);
_startFrameProcessTimer();
}
// //
// iOS平台使用更保守的调整策略 // iOS平台使用更保守的调整策略
if (Platform.isIOS) { if (Platform.isIOS) {
@ -85,7 +94,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
_startFrameProcessTimer(); _startFrameProcessTimer();
} }
} else { } else {
// Android平台原有逻辑 // Android平台
if (actualRatio < 0.4) { if (actualRatio < 0.4) {
state.targetFps = (targetFps * 0.6).round().clamp(15, 60); state.targetFps = (targetFps * 0.6).round().clamp(15, 60);
_startFrameProcessTimer(); _startFrameProcessTimer();
@ -108,13 +117,13 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
: 0.0; : 0.0;
// //
if (dropRate > 0.3) { if (dropRate > 0.25) {
_networkQualityScore = 1; // _networkQualityScore = 1; //
} else if (dropRate > 0.2) { } else if (dropRate > 0.15) {
_networkQualityScore = 2; // _networkQualityScore = 2; //
} else if (dropRate > 0.1) { } else if (dropRate > 0.08) {
_networkQualityScore = 3; // _networkQualityScore = 3; //
} else if (dropRate > 0.05) { } else if (dropRate > 0.03) {
_networkQualityScore = 4; // _networkQualityScore = 4; //
} else { } else {
_networkQualityScore = 5; // _networkQualityScore = 5; //
@ -269,9 +278,8 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
final startTime = DateTime.now().millisecondsSinceEpoch; final startTime = DateTime.now().millisecondsSinceEpoch;
// 使 // 使
// iOS平台使用更短的超时时间 // 500ms
final timeoutSeconds = Platform.isIOS ? 1 : 1; final timeoutFuture = Future.delayed(Duration(milliseconds: 500), () => null);
final timeoutFuture = Future.delayed(Duration(seconds: timeoutSeconds), () => null);
final decoderFuture = VideoDecodePlugin.initDecoder(config); final decoderFuture = VideoDecodePlugin.initDecoder(config);
// textureId // textureId
@ -296,16 +304,14 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
} }
// //
// //
Future.delayed(Duration(milliseconds: 100), () { Future.delayed(Duration(milliseconds: 50), () {
_startFrameProcessTimer(); _startFrameProcessTimer();
}); });
} catch (e) { } catch (e) {
AppLog.log('初始化视频解码器错误: $e'); AppLog.log('初始化视频解码器错误: $e');
state.isLoading.value = false; state.isLoading.value = false;
// // --
// iOS平台使用更短的重试延迟 await Future.delayed(Duration(milliseconds: 300));
final delaySeconds = Platform.isIOS ? 0.5 : 1;
await Future.delayed(Duration(milliseconds: (delaySeconds * 1000).toInt()));
if (!Get.isRegistered<TalkViewNativeDecodeLogic>()) { if (!Get.isRegistered<TalkViewNativeDecodeLogic>()) {
return; return;
} }
@ -537,8 +543,25 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
} }
} }
// // -- I帧以加速首帧显示
int frameIndex = -1; int frameIndex = -1;
// I帧
final iFrames = state.h264FrameBuffer
.where((f) => f['frameType'] == TalkDataH264Frame_FrameTypeE.I)
.toList()
..sort((a, b) => (a['frameSeq'] as int).compareTo(b['frameSeq'] as int));
if (iFrames.isNotEmpty) {
final minIFrame = iFrames.first;
frameIndex = state.h264FrameBuffer.indexWhere(
(f) =>
f['frameType'] == TalkDataH264Frame_FrameTypeE.I &&
f['frameSeq'] == minIFrame['frameSeq'],
);
} else {
// I帧
frameIndex = 0;
}
// I帧相关的P帧 // I帧相关的P帧
if (lastDecodedIFrameSeq != null) { if (lastDecodedIFrameSeq != null) {
@ -897,44 +920,103 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
@override @override
void onClose() { void onClose() {
try {
//
_stopAllProcessing();
//
_releaseVideoResources();
//
_releaseAudioResources();
//
_releaseNetworkAndStateResources();
//
_cancelAllTimersAndSubscriptions();
} catch (e, stackTrace) {
AppLog.log('资源释放过程中出现错误: $e\n$stackTrace');
} finally {
super.onClose();
}
}
///
void _stopAllProcessing() {
// //
_stopFrameProcessTimer(); _stopFrameProcessTimer();
_stopPlayG711Data(); // //
state.audioBuffer.clear(); //
state.oneMinuteTimeTimer?.cancel();
state.oneMinuteTimeTimer = null;
//
stopProcessingAudio(); stopProcessingAudio();
state.oneMinuteTimeTimer?.cancel(); // //
state.oneMinuteTimeTimer = null; // _stopPlayG711Data();
state.oneMinuteTime.value = 0; }
// ///
_releaseVideoDecoderAsync(); void _releaseVideoResources() {
try {
//
_releaseVideoDecoderAsync();
} catch (e) {
AppLog.log('释放视频解码器资源失败: $e');
}
}
// ///
_streamSubscription?.cancel(); void _releaseAudioResources() {
_isListening = false; try {
//
_stopPlayG711Data();
// //
StartChartManage().reSetDefaultTalkExpect(); state.audioBuffer.clear();
StartChartManage().stopTalkExpectMessageTimer();
// //
_batchProcessTimer?.cancel(); _bufferedAudioFrames.clear();
_batchProcessTimer = null; } catch (e) {
AppLog.log('释放音频资源失败: $e');
}
}
// I帧集合 ///
_decodedIFrames.clear(); void _releaseNetworkAndStateResources() {
_startProcessingAudioTimer?.cancel(); try {
_startProcessingAudioTimer = null; //
_bufferedAudioFrames.clear(); StartChartManage().reSetDefaultTalkExpect();
super.onClose(); StartChartManage().stopTalkExpectMessageTimer();
// I帧集合
_decodedIFrames.clear();
//
state.oneMinuteTimeTimer?.cancel();
state.oneMinuteTimeTimer = null;
state.oneMinuteTime.value = 0;
} catch (e) {
AppLog.log('释放网络和状态资源失败: $e');
}
}
///
void _cancelAllTimersAndSubscriptions() {
try {
//
_streamSubscription?.cancel();
_isListening = false;
//
_batchProcessTimer?.cancel();
_batchProcessTimer = null;
//
_startProcessingAudioTimer?.cancel();
_startProcessingAudioTimer = null;
} catch (e) {
AppLog.log('取消定时器和订阅失败: $e');
}
} }
/// ///
Future<void> _releaseVideoDecoderAsync() async { Future<void> _releaseVideoDecoderAsync() async {
@ -1191,14 +1273,14 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
_pendingResetWidth = width; _pendingResetWidth = width;
_pendingResetHeight = height; _pendingResetHeight = height;
// // ---使
await Future.wait([ await Future.wait([
// //
_resetDecoderForNewStream(width, height), _resetDecoderForNewStream(width, height),
// //
Future.microtask(() => Future.microtask(() =>
StartChartManage().changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer(talkExpect: talkExpectReq)) StartChartManage().changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer(talkExpect: talkExpectReq))
]).timeout(const Duration(seconds: 2)); // ]).timeout(const Duration(milliseconds: 1500)); //
} }
void _initHdOptions() { void _initHdOptions() {
@ -1222,13 +1304,11 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
// //
_clearFrameBufferQuickly(); _clearFrameBufferQuickly();
// - 使 // - 使 -
if (state.textureId.value != null) { if (state.textureId.value != null) {
try { try {
// //
// iOS平台使用更短的超时时间 await VideoDecodePlugin.releaseDecoder().timeout(Duration(milliseconds: 100));
final timeoutMs = Platform.isIOS ? 200 : 300;
await VideoDecodePlugin.releaseDecoder().timeout(Duration(milliseconds: timeoutMs));
state.textureId.value = null; state.textureId.value = null;
} catch (e) { } catch (e) {
AppLog.log('释放解码器超时或失败: $e'); AppLog.log('释放解码器超时或失败: $e');
@ -1238,9 +1318,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
} }
// //
// iOS平台使用更短的等待时间 await Future.delayed(Duration(milliseconds: 0));
final delayMs = Platform.isIOS ? 0 : 1;
await Future.delayed(Duration(milliseconds: delayMs));
// //
final config = VideoDecoderConfig( final config = VideoDecoderConfig(
@ -1252,10 +1330,8 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
// //
try { try {
// 使 // 使
// iOS平台使用更短的超时时间
final timeoutMs = Platform.isIOS ? 1000 : 1500;
final textureId = await VideoDecodePlugin.initDecoder(config) final textureId = await VideoDecodePlugin.initDecoder(config)
.timeout(Duration(milliseconds: timeoutMs)); .timeout(Duration(milliseconds: 800));
if (textureId != null) { if (textureId != null) {
state.textureId.value = textureId; state.textureId.value = textureId;