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 LinkedHashMap _frameBuffer = LinkedHashMap(); final void Function(List frameData) onCompleteFrame; final LinkedHashMap _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 framesToProcess = []; int? startFrameSeq; // 从当前帧开始向前找到最近的 I 帧或 P 帧 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 (frameType == TalkDataH264Frame_FrameTypeE.P) { if (_frameBuffer.containsKey(_frameBuffer[seq]!.frameSeqI)) { startFrameSeq = seq; break; } else { _frameBuffer.remove(seq); _frameTypeIndex.remove(seq); } } } if (startFrameSeq != null) { for (int seq = startFrameSeq; _frameBuffer.containsKey(seq); seq++) { framesToProcess.add(seq); } if (framesToProcess.isNotEmpty) { _processFrames(framesToProcess); } } else { _clearOldFrames(currentSeq); } } void _processFrames(List frameSeqs) { // 按顺序组装帧数据 // final List 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.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); } }