fix:优化h264组装帧方法,增加调试日志
This commit is contained in:
parent
b59dafc37c
commit
43eeef237f
@ -56,7 +56,7 @@
|
||||
},
|
||||
flushingTime: 0, // 禁用自动刷新
|
||||
clearBuffer: false, // 保留解码缓存
|
||||
maxBufferLength: 2,
|
||||
fps:20,
|
||||
onReady: () => {
|
||||
console.log('播放器初始化完成');
|
||||
// 通知Flutter端准备就绪
|
||||
|
||||
@ -2,6 +2,7 @@ import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart';
|
||||
|
||||
import '../../../blue/io_reply.dart';
|
||||
import '../../lockMian/entity/lockListInfo_entity.dart';
|
||||
@ -9,7 +10,7 @@ import '../../lockMian/entity/lockListInfo_entity.dart';
|
||||
|
||||
class LockDetailState {
|
||||
Rx<LockListInfoItemEntity> keyInfos = LockListInfoItemEntity().obs;
|
||||
|
||||
final Rx<LockSetInfoData> lockSetInfoData = LockSetInfoData().obs;
|
||||
late StreamSubscription<Reply> replySubscription;
|
||||
StreamSubscription? lockSetOpenOrCloseCheckInRefreshLockDetailWithAttendanceEvent;
|
||||
StreamSubscription? LockSetChangeSetRefreshLockDetailWithTypeSubscription;
|
||||
|
||||
@ -160,6 +160,8 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle
|
||||
final TalkDataH264Frame talkDataH264Frame = TalkDataH264Frame();
|
||||
talkDataH264Frame.mergeFromBuffer(talkData.content);
|
||||
frameHandler.handleFrame(talkDataH264Frame);
|
||||
AppLog.log(
|
||||
"帧:${talkDataH264Frame.frameType},帧序号:${talkDataH264Frame.frameSeq},对应I帧序号:${talkDataH264Frame.frameSeqI}");
|
||||
}
|
||||
|
||||
/// 处理图片数据
|
||||
|
||||
@ -1,52 +1,51 @@
|
||||
import 'dart:collection';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:star_lock/app_settings/app_settings.dart';
|
||||
import '../../proto/talk_data_h264_frame.pb.dart';
|
||||
|
||||
class H264FrameHandler {
|
||||
final Map<int, TalkDataH264Frame> _frameBuffer = {};
|
||||
final LinkedHashMap<int, TalkDataH264Frame> _frameBuffer = LinkedHashMap();
|
||||
final void Function(List<int> frameData) onCompleteFrame;
|
||||
int _lastProcessedSeq = -1;
|
||||
|
||||
final LinkedHashMap<int, TalkDataH264Frame_FrameTypeE> _frameTypeIndex = LinkedHashMap();
|
||||
|
||||
H264FrameHandler({required this.onCompleteFrame});
|
||||
|
||||
void handleFrame(TalkDataH264Frame frame) {
|
||||
// 存储帧
|
||||
_frameBuffer[frame.frameSeq] = frame;
|
||||
_frameTypeIndex[frame.frameSeq] = frame.frameType;
|
||||
|
||||
// 检查是否可以组装完整的 GOP (Group of Pictures)
|
||||
_tryAssembleFrames(frame.frameSeq);
|
||||
}
|
||||
|
||||
void _tryAssembleFrames(int currentSeq) {
|
||||
// 找到连续的帧序列
|
||||
final List<int> sortedSeqs = _frameBuffer.keys.toList()..sort();
|
||||
final List<int> framesToProcess = [];
|
||||
int? startFrameSeq;
|
||||
|
||||
// 从当前帧开始向前找到最近的 I 帧或 P 帧
|
||||
int? startFrameSeq;
|
||||
for (var seq in sortedSeqs.reversed) {
|
||||
final frame = _frameBuffer[seq];
|
||||
if (frame?.frameType == TalkDataH264Frame_FrameTypeE.I) {
|
||||
for (int seq = currentSeq; seq >= 0; seq--) {
|
||||
final frameType = _frameTypeIndex[seq];
|
||||
if (frameType == null) continue;
|
||||
if (frameType == TalkDataH264Frame_FrameTypeE.I) {
|
||||
startFrameSeq = seq;
|
||||
break;
|
||||
} else if (frame?.frameType == TalkDataH264Frame_FrameTypeE.P) {
|
||||
// 检查 P 帧是否有对应的 I 帧
|
||||
if (_frameBuffer.containsKey(frame?.frameSeqI)) {
|
||||
} else if (frameType == TalkDataH264Frame_FrameTypeE.P) {
|
||||
if (_frameBuffer.containsKey(_frameBuffer[seq]!.frameSeqI)) {
|
||||
startFrameSeq = seq;
|
||||
break;
|
||||
} else {
|
||||
// 丢弃没有对应 I 帧的 P 帧
|
||||
_frameBuffer.remove(seq);
|
||||
_frameTypeIndex.remove(seq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (startFrameSeq != null) {
|
||||
// 收集从 I 帧或 P 帧开始的连续帧
|
||||
int expectedSeq = startFrameSeq;
|
||||
for (var seq in sortedSeqs.where((s) => s >= startFrameSeq!)) {
|
||||
if (seq != expectedSeq) break;
|
||||
for (int seq = startFrameSeq; _frameBuffer.containsKey(seq); seq++) {
|
||||
framesToProcess.add(seq);
|
||||
expectedSeq++;
|
||||
}
|
||||
|
||||
if (framesToProcess.isNotEmpty) {
|
||||
@ -57,28 +56,50 @@ class H264FrameHandler {
|
||||
}
|
||||
}
|
||||
|
||||
void _clearOldFrames(int currentSeq) {
|
||||
// 清理比当前帧序列旧的帧
|
||||
_frameBuffer.removeWhere((seq, frame) => seq < currentSeq - 200); // 调整阈值
|
||||
}
|
||||
|
||||
void _processFrames(List<int> frameSeqs) {
|
||||
// 按顺序组装帧数据
|
||||
final List<int> assembledData = [];
|
||||
// final List<int> assembledData = [];
|
||||
//
|
||||
// for (var seq in frameSeqs) {
|
||||
// final frame = _frameBuffer[seq]!;
|
||||
// assembledData.addAll(frame.frameData);
|
||||
//
|
||||
// // 处理完后从缓冲区移除
|
||||
// _frameBuffer.remove(seq);
|
||||
// }
|
||||
//
|
||||
// // 回调完整的帧数据
|
||||
// onCompleteFrame(assembledData);
|
||||
// Calculate the total length of the assembled data
|
||||
int totalLength = frameSeqs.fold(
|
||||
0, (sum, seq) => sum + _frameBuffer[seq]!.frameData.length);
|
||||
|
||||
// Allocate a buffer for the assembled data
|
||||
final assembledData = Uint8List(totalLength);
|
||||
int offset = 0;
|
||||
|
||||
for (var seq in frameSeqs) {
|
||||
final frame = _frameBuffer[seq]!;
|
||||
assembledData.addAll(frame.frameData);
|
||||
assembledData.setRange(
|
||||
offset, offset + frame.frameData.length, frame.frameData);
|
||||
offset += frame.frameData.length;
|
||||
|
||||
// 处理完后从缓冲区移除
|
||||
// Remove the frame from the buffer after processing
|
||||
_frameBuffer.remove(seq);
|
||||
_frameTypeIndex.remove(seq);
|
||||
}
|
||||
|
||||
// 回调完整的帧数据
|
||||
// Callback with the complete frame data
|
||||
onCompleteFrame(assembledData);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_frameBuffer.clear();
|
||||
}
|
||||
|
||||
void _clearOldFrames(int currentSeq) {
|
||||
// 清理比当前帧序列旧的帧
|
||||
_frameBuffer.removeWhere((seq, frame) => seq < currentSeq - 200); // 调整阈值
|
||||
_frameTypeIndex.removeWhere((seq, frameType) => seq < currentSeq - 200);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user