bug
This commit is contained in:
parent
ebe5b8a756
commit
e9f59c223f
@ -726,9 +726,13 @@ class LockDetailLogic extends BaseGetXController {
|
|||||||
// 判断是否为WiFi锁
|
// 判断是否为WiFi锁
|
||||||
final network = currentKeyInfo.network;
|
final network = currentKeyInfo.network;
|
||||||
if (network != null && (network.peerId != null && network.peerId!.isNotEmpty)){
|
if (network != null && (network.peerId != null && network.peerId!.isNotEmpty)){
|
||||||
|
showToast('wifi锁进行蓝牙透传开锁'.tr);
|
||||||
// 发送蓝牙透传开锁指令
|
// 发送蓝牙透传开锁指令
|
||||||
await _sendUnlockViaBluetooth();
|
await _sendUnlockViaBluetooth();
|
||||||
} else {
|
}
|
||||||
|
// 判断是否为网关锁
|
||||||
|
if (state.keyInfos.value.hasGateway == 1) {
|
||||||
|
showToast('网关锁进行远程开锁api开锁'.tr);
|
||||||
// 发送远程开锁API
|
// 发送远程开锁API
|
||||||
final LoginEntity entity = await ApiRepository.to.remoteOpenLock(lockId: lockId.toString(), timeOut: 60);
|
final LoginEntity entity = await ApiRepository.to.remoteOpenLock(lockId: lockId.toString(), timeOut: 60);
|
||||||
if (entity.errorCode!.codeIsSuccessful) {
|
if (entity.errorCode!.codeIsSuccessful) {
|
||||||
|
|||||||
@ -398,8 +398,6 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
|||||||
} else if (bufferLength > 40) {
|
} else if (bufferLength > 40) {
|
||||||
// 其他平台原有逻辑
|
// 其他平台原有逻辑
|
||||||
_dropOldPFrame();
|
_dropOldPFrame();
|
||||||
} else if (bufferLength > 30) {
|
|
||||||
_dropSomeBFrame();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void _dropOldFramesAggressively() {
|
void _dropOldFramesAggressively() {
|
||||||
@ -423,50 +421,63 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
|||||||
_invalidateFrameIndex();
|
_invalidateFrameIndex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _dropSomeBFrame() {
|
/// 仅保留关键帧(I帧和最近的P帧)以减少处理负载
|
||||||
// 如果存在B帧,丢弃部分旧的B帧
|
void _keepOnlyKeyFrames() {
|
||||||
final bFrameIndex = state.h264FrameBuffer.indexWhere((frame) =>
|
final List<Map<String, dynamic>> keyFrames = [];
|
||||||
frame['frameType'] == TalkDataH264Frame_FrameTypeE.I &&
|
int lastPFrameIndex = -1;
|
||||||
frame['frameSeq'] < (_lastFrameSeq ?? 0) - 30);
|
|
||||||
|
// 从后向前遍历,优先保留最新的帧
|
||||||
if (bFrameIndex != -1) {
|
for (int i = state.h264FrameBuffer.length - 1; i >= 0; i--) {
|
||||||
state.h264FrameBuffer.removeAt(bFrameIndex);
|
final frame = state.h264FrameBuffer[i];
|
||||||
|
final frameType = frame['frameType'];
|
||||||
|
|
||||||
|
if (frameType == TalkDataH264Frame_FrameTypeE.I) {
|
||||||
|
keyFrames.add(frame);
|
||||||
|
break; // 找到最新的I帧后停止
|
||||||
|
} else if (frameType == TalkDataH264Frame_FrameTypeE.P && lastPFrameIndex == -1) {
|
||||||
|
keyFrames.add(frame);
|
||||||
|
lastPFrameIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyFrames.isNotEmpty) {
|
||||||
|
// 只保留关键帧,反转顺序使其按时间顺序排列
|
||||||
|
state.h264FrameBuffer.clear();
|
||||||
|
state.h264FrameBuffer.addAll(keyFrames.reversed);
|
||||||
_invalidateFrameIndex();
|
_invalidateFrameIndex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 启动帧处理定时器
|
/// 启动帧处理定时器 - 优化版:动态帧率调整
|
||||||
void _startFrameProcessTimer() {
|
void _startFrameProcessTimer() {
|
||||||
// 取消已有定时器
|
// 取消已有定时器
|
||||||
_stopFrameProcessTimer();
|
_stopFrameProcessTimer();
|
||||||
|
|
||||||
// 计算定时器间隔,确保以目标帧率处理帧
|
// 初始间隔设置
|
||||||
// iOS平台使用更精确的定时器间隔
|
int baseIntervalMs = Platform.isIOS
|
||||||
final int intervalMs = Platform.isIOS
|
|
||||||
? max(16, min(33, (1000 / state.targetFps).round())) // iOS使用更严格的范围
|
? max(16, min(33, (1000 / state.targetFps).round())) // iOS使用更严格的范围
|
||||||
: max(16, min(40, (1000 / state.targetFps).round()));
|
: max(16, min(40, (1000 / state.targetFps).round()));
|
||||||
|
|
||||||
// 创建新定时器
|
// 创建新定时器
|
||||||
state.frameProcessTimer = Timer.periodic(Duration(milliseconds: intervalMs), (timer) {
|
state.frameProcessTimer = Timer.periodic(Duration(milliseconds: baseIntervalMs), (timer) {
|
||||||
_processNextFrameFromBuffer();
|
_processNextFrameFromBuffer();
|
||||||
});
|
});
|
||||||
AppLog.log('启动帧处理定时器,目标帧率: ${state.targetFps}fps,间隔: ${intervalMs}ms');
|
AppLog.log('启动帧处理定时器,目标帧率: ${state.targetFps}fps,初始间隔: ${baseIntervalMs}ms');
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 添加:快速清理缓冲区方法
|
/// 添加:快速清理缓冲区方法
|
||||||
void _clearFrameBufferQuickly() {
|
void _clearFrameBufferQuickly() {
|
||||||
// 只保留最新的少量帧,加快切换响应
|
// 完全清空帧缓冲区,避免旧帧影响新流
|
||||||
if (state.h264FrameBuffer.length > 3) {
|
state.h264FrameBuffer.clear();
|
||||||
// 保留最新的3帧
|
|
||||||
state.h264FrameBuffer.removeRange(0, state.h264FrameBuffer.length - 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重置帧序列状态
|
// 重置帧序列状态
|
||||||
_lastFrameSeq = null;
|
_lastFrameSeq = null;
|
||||||
lastDecodedIFrameSeq = null;
|
lastDecodedIFrameSeq = null;
|
||||||
_decodedIFrames.clear();
|
_decodedIFrames.clear();
|
||||||
state.isProcessingFrame = false;
|
state.isProcessingFrame = false;
|
||||||
|
_frameIndexDirty = true;
|
||||||
|
_frameIndexCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 停止帧处理定时器
|
/// 停止帧处理定时器
|
||||||
@ -575,8 +586,8 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
|||||||
return state.h264FrameBuffer.isNotEmpty ? 0 : -1;
|
return state.h264FrameBuffer.isNotEmpty ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 从缓冲区处理下一帧
|
/// 从缓冲区处理下一帧 - 优化版:简化逻辑和动态调整
|
||||||
void _processNextFrameFromBuffer() async {
|
Future<void> _processNextFrameFromBuffer() async {
|
||||||
final stopwatch = Stopwatch()..start();
|
final stopwatch = Stopwatch()..start();
|
||||||
_monitorFrameProcessingPerformance();
|
_monitorFrameProcessingPerformance();
|
||||||
final startTime = DateTime.now().microsecondsSinceEpoch;
|
final startTime = DateTime.now().microsecondsSinceEpoch;
|
||||||
@ -600,12 +611,23 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
|||||||
try {
|
try {
|
||||||
state.isProcessingFrame = true;
|
state.isProcessingFrame = true;
|
||||||
|
|
||||||
// 添加智能丢帧策略
|
// 智能丢帧策略:根据缓冲区大小动态调整
|
||||||
_implementSmartFrameDropping();
|
final bufferLength = state.h264FrameBuffer.length;
|
||||||
|
if (bufferLength > 50) {
|
||||||
|
// 缓冲区溢出,保留最新20帧
|
||||||
|
final newBuffer = state.h264FrameBuffer.sublist(max(0, bufferLength - 20));
|
||||||
|
state.h264FrameBuffer.clear();
|
||||||
|
state.h264FrameBuffer.addAll(newBuffer);
|
||||||
|
_invalidateFrameIndex();
|
||||||
|
} else if (bufferLength > 30 && Platform.isAndroid) {
|
||||||
|
// Android平台缓冲区较大时,只处理I帧和关键P帧
|
||||||
|
_keepOnlyKeyFrames();
|
||||||
|
} else {
|
||||||
|
// 正常智能丢帧
|
||||||
|
_implementSmartFrameDropping();
|
||||||
|
}
|
||||||
|
|
||||||
// 动态调整处理策略基于缓冲区长度
|
// 动态调整处理策略基于缓冲区长度
|
||||||
final bufferLength = state.h264FrameBuffer.length;
|
|
||||||
|
|
||||||
// 更智能的帧率调整策略
|
// 更智能的帧率调整策略
|
||||||
// iOS平台优化:更积极的缓冲区管理
|
// iOS平台优化:更积极的缓冲区管理
|
||||||
if (Platform.isIOS) {
|
if (Platform.isIOS) {
|
||||||
@ -1306,7 +1328,7 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
|||||||
AppLog.log(error.message!);
|
AppLog.log(error.message!);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 切换清晰度的方法,后续补充具体实现
|
// 切换清晰度的方法,优化切换速度
|
||||||
void onQualityChanged(String quality) async {
|
void onQualityChanged(String quality) async {
|
||||||
state.currentQuality.value = quality;
|
state.currentQuality.value = quality;
|
||||||
TalkExpectReq talkExpectReq = StartChartManage().getDefaultTalkExpect();
|
TalkExpectReq talkExpectReq = StartChartManage().getDefaultTalkExpect();
|
||||||
@ -1335,8 +1357,27 @@ class TalkViewNativeDecodeLogic extends BaseGetXController {
|
|||||||
/// 修改发送预期数据
|
/// 修改发送预期数据
|
||||||
StartChartManage().changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer(talkExpect: talkExpectReq);
|
StartChartManage().changeTalkExpectDataTypeAndReStartTalkExpectMessageTimer(talkExpect: talkExpectReq);
|
||||||
|
|
||||||
// 不立即loading,继续解码旧流帧,等待frameSeq回绕检测
|
// 立即切换清晰度:清理旧帧缓冲区并重新初始化解码器
|
||||||
// 仅重置frameSeq回绕检测标志
|
// 1. 停止当前帧处理
|
||||||
|
_stopFrameProcessTimer();
|
||||||
|
|
||||||
|
// 2. 立即清理旧的帧缓冲区
|
||||||
|
_clearFrameBufferQuickly();
|
||||||
|
|
||||||
|
// 3. 更新视频分辨率设置
|
||||||
|
StartChartManage().videoWidth = width;
|
||||||
|
StartChartManage().videoHeight = height;
|
||||||
|
|
||||||
|
// 4. 立即重新初始化解码器
|
||||||
|
await _resetDecoderForNewStream(width, height);
|
||||||
|
|
||||||
|
// 5. 启动帧处理
|
||||||
|
_startFrameProcessTimer();
|
||||||
|
|
||||||
|
// 6. 显示加载动画
|
||||||
|
Future.microtask(() => state.isLoading.value = true);
|
||||||
|
|
||||||
|
// 7. 重置帧序列相关状态
|
||||||
_pendingStreamReset = false;
|
_pendingStreamReset = false;
|
||||||
_pendingResetWidth = width;
|
_pendingResetWidth = width;
|
||||||
_pendingResetHeight = height;
|
_pendingResetHeight = height;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user