优化视频对讲 优化

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 {
final catEyeConfig = state.keyInfos.value.lockSetting?.catEyeConfig ?? [];
@ -817,6 +819,30 @@ class LockDetailLogic extends BaseGetXController {
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 (network == null || network?.peerId == null || network?.peerId == '') {
showToast('设备未配网'.tr);

View File

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

View File

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