app-starlock/lib/talk/starChart/handle/other/h264_frame_handler.dart
2025-02-21 15:55:35 +08:00

85 lines
2.4 KiB
Dart

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 void Function(List<int> frameData) onCompleteFrame;
int _lastProcessedSeq = -1;
H264FrameHandler({required this.onCompleteFrame});
void handleFrame(TalkDataH264Frame frame) {
// 存储帧
_frameBuffer[frame.frameSeq] = frame;
// 检查是否可以组装完整的 GOP (Group of Pictures)
_tryAssembleFrames(frame.frameSeq);
}
void _tryAssembleFrames(int currentSeq) {
// 找到连续的帧序列
final List<int> sortedSeqs = _frameBuffer.keys.toList()..sort();
final List<int> framesToProcess = [];
// 从当前帧开始向前找到最近的 I 帧或 P 帧
int? startFrameSeq;
for (var seq in sortedSeqs.reversed) {
final frame = _frameBuffer[seq];
if (frame?.frameType == TalkDataH264Frame_FrameTypeE.I) {
startFrameSeq = seq;
break;
} else if (frame?.frameType == TalkDataH264Frame_FrameTypeE.P) {
// 检查 P 帧是否有对应的 I 帧
if (_frameBuffer.containsKey(frame?.frameSeqI)) {
startFrameSeq = seq;
break;
} else {
// 丢弃没有对应 I 帧的 P 帧
_frameBuffer.remove(seq);
}
}
}
if (startFrameSeq != null) {
// 收集从 I 帧或 P 帧开始的连续帧
int expectedSeq = startFrameSeq;
for (var seq in sortedSeqs.where((s) => s >= startFrameSeq!)) {
if (seq != expectedSeq) break;
framesToProcess.add(seq);
expectedSeq++;
}
if (framesToProcess.isNotEmpty) {
_processFrames(framesToProcess);
}
} else {
_clearOldFrames(currentSeq);
}
}
void _clearOldFrames(int currentSeq) {
// 清理比当前帧序列旧的帧
_frameBuffer.removeWhere((seq, frame) => seq < currentSeq - 200); // 调整阈值
}
void _processFrames(List<int> frameSeqs) {
// 按顺序组装帧数据
final List<int> assembledData = [];
for (var seq in frameSeqs) {
final frame = _frameBuffer[seq]!;
assembledData.addAll(frame.frameData);
// 处理完后从缓冲区移除
_frameBuffer.remove(seq);
}
// 回调完整的帧数据
onCompleteFrame(assembledData);
}
void clear() {
_frameBuffer.clear();
}
}