fix:优化h264组装帧方法,增加调试日志

This commit is contained in:
liyi 2025-02-24 17:03:31 +08:00
parent b59dafc37c
commit 43eeef237f
4 changed files with 52 additions and 28 deletions

View File

@ -56,7 +56,7 @@
}, },
flushingTime: 0, // 禁用自动刷新 flushingTime: 0, // 禁用自动刷新
clearBuffer: false, // 保留解码缓存 clearBuffer: false, // 保留解码缓存
maxBufferLength: 2, fps:20,
onReady: () => { onReady: () => {
console.log('播放器初始化完成'); console.log('播放器初始化完成');
// 通知Flutter端准备就绪 // 通知Flutter端准备就绪

View File

@ -2,6 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/lockSet/lockSet/lockSetInfo_entity.dart';
import '../../../blue/io_reply.dart'; import '../../../blue/io_reply.dart';
import '../../lockMian/entity/lockListInfo_entity.dart'; import '../../lockMian/entity/lockListInfo_entity.dart';
@ -9,7 +10,7 @@ import '../../lockMian/entity/lockListInfo_entity.dart';
class LockDetailState { class LockDetailState {
Rx<LockListInfoItemEntity> keyInfos = LockListInfoItemEntity().obs; Rx<LockListInfoItemEntity> keyInfos = LockListInfoItemEntity().obs;
final Rx<LockSetInfoData> lockSetInfoData = LockSetInfoData().obs;
late StreamSubscription<Reply> replySubscription; late StreamSubscription<Reply> replySubscription;
StreamSubscription? lockSetOpenOrCloseCheckInRefreshLockDetailWithAttendanceEvent; StreamSubscription? lockSetOpenOrCloseCheckInRefreshLockDetailWithAttendanceEvent;
StreamSubscription? LockSetChangeSetRefreshLockDetailWithTypeSubscription; StreamSubscription? LockSetChangeSetRefreshLockDetailWithTypeSubscription;

View File

@ -160,6 +160,8 @@ class UdpTalkDataHandler extends ScpMessageBaseHandle
final TalkDataH264Frame talkDataH264Frame = TalkDataH264Frame(); final TalkDataH264Frame talkDataH264Frame = TalkDataH264Frame();
talkDataH264Frame.mergeFromBuffer(talkData.content); talkDataH264Frame.mergeFromBuffer(talkData.content);
frameHandler.handleFrame(talkDataH264Frame); frameHandler.handleFrame(talkDataH264Frame);
AppLog.log(
"帧:${talkDataH264Frame.frameType},帧序号:${talkDataH264Frame.frameSeq},对应I帧序号${talkDataH264Frame.frameSeqI}");
} }
/// ///

View File

@ -1,52 +1,51 @@
import 'dart:collection';
import 'dart:typed_data';
import 'package:star_lock/app_settings/app_settings.dart'; import 'package:star_lock/app_settings/app_settings.dart';
import '../../proto/talk_data_h264_frame.pb.dart'; import '../../proto/talk_data_h264_frame.pb.dart';
class H264FrameHandler { class H264FrameHandler {
final Map<int, TalkDataH264Frame> _frameBuffer = {}; final LinkedHashMap<int, TalkDataH264Frame> _frameBuffer = LinkedHashMap();
final void Function(List<int> frameData) onCompleteFrame; final void Function(List<int> frameData) onCompleteFrame;
int _lastProcessedSeq = -1;
final LinkedHashMap<int, TalkDataH264Frame_FrameTypeE> _frameTypeIndex = LinkedHashMap();
H264FrameHandler({required this.onCompleteFrame}); H264FrameHandler({required this.onCompleteFrame});
void handleFrame(TalkDataH264Frame frame) { void handleFrame(TalkDataH264Frame frame) {
// //
_frameBuffer[frame.frameSeq] = frame; _frameBuffer[frame.frameSeq] = frame;
_frameTypeIndex[frame.frameSeq] = frame.frameType;
// GOP (Group of Pictures) // GOP (Group of Pictures)
_tryAssembleFrames(frame.frameSeq); _tryAssembleFrames(frame.frameSeq);
} }
void _tryAssembleFrames(int currentSeq) { void _tryAssembleFrames(int currentSeq) {
//
final List<int> sortedSeqs = _frameBuffer.keys.toList()..sort();
final List<int> framesToProcess = []; final List<int> framesToProcess = [];
int? startFrameSeq;
// I P // I P
int? startFrameSeq; for (int seq = currentSeq; seq >= 0; seq--) {
for (var seq in sortedSeqs.reversed) { final frameType = _frameTypeIndex[seq];
final frame = _frameBuffer[seq]; if (frameType == null) continue;
if (frame?.frameType == TalkDataH264Frame_FrameTypeE.I) { if (frameType == TalkDataH264Frame_FrameTypeE.I) {
startFrameSeq = seq; startFrameSeq = seq;
break; break;
} else if (frame?.frameType == TalkDataH264Frame_FrameTypeE.P) { } else if (frameType == TalkDataH264Frame_FrameTypeE.P) {
// P I if (_frameBuffer.containsKey(_frameBuffer[seq]!.frameSeqI)) {
if (_frameBuffer.containsKey(frame?.frameSeqI)) {
startFrameSeq = seq; startFrameSeq = seq;
break; break;
} else { } else {
// I P
_frameBuffer.remove(seq); _frameBuffer.remove(seq);
_frameTypeIndex.remove(seq);
} }
} }
} }
if (startFrameSeq != null) { if (startFrameSeq != null) {
// I P for (int seq = startFrameSeq; _frameBuffer.containsKey(seq); seq++) {
int expectedSeq = startFrameSeq;
for (var seq in sortedSeqs.where((s) => s >= startFrameSeq!)) {
if (seq != expectedSeq) break;
framesToProcess.add(seq); framesToProcess.add(seq);
expectedSeq++;
} }
if (framesToProcess.isNotEmpty) { 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) { 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) { for (var seq in frameSeqs) {
final frame = _frameBuffer[seq]!; 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); _frameBuffer.remove(seq);
_frameTypeIndex.remove(seq);
} }
// // Callback with the complete frame data
onCompleteFrame(assembledData); onCompleteFrame(assembledData);
} }
void clear() { void clear() {
_frameBuffer.clear(); _frameBuffer.clear();
} }
void _clearOldFrames(int currentSeq) {
//
_frameBuffer.removeWhere((seq, frame) => seq < currentSeq - 200); //
_frameTypeIndex.removeWhere((seq, frameType) => seq < currentSeq - 200);
}
} }