app-starlock/lib/talk/startChart/handle/impl/udp_talk_data_handler.dart

142 lines
4.1 KiB
Dart
Raw Normal View History

2024-12-09 15:57:41 +08:00
import 'dart:typed_data';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:star_lock/talk/startChart/entity/scp_message.dart';
import 'package:star_lock/talk/startChart/handle/scp_message_base_handle.dart';
import 'package:star_lock/talk/startChart/handle/scp_message_handle.dart';
import 'package:star_lock/talk/startChart/proto/gateway_reset.pb.dart';
import 'package:star_lock/talk/startChart/proto/generic.pb.dart';
2024-12-09 15:57:41 +08:00
import 'package:star_lock/talk/startChart/proto/talk_data.pb.dart';
import 'package:star_lock/talk/startChart/proto/talk_data.pbserver.dart';
import '../../start_chart_manage.dart';
class UdpTalkDataHandler extends ScpMessageBaseHandle
implements ScpMessageHandler {
@override
2024-12-09 13:44:57 +08:00
void handleReq(ScpMessage scpMessage) {}
@override
2024-12-09 13:44:57 +08:00
void handleResp(ScpMessage scpMessage) {}
@override
2024-12-09 13:44:57 +08:00
void handleInvalidReq(ScpMessage scpMessage) {}
@override
void handleRealTimeData(ScpMessage scpMessage) {
2024-12-09 15:57:41 +08:00
print('收到音视频数据:$scpMessage');
if (scpMessage.Payload != null) {
final TalkData talkData = scpMessage.Payload;
// 处理音视频数据
_handleTalkData(talkData: talkData);
// 收到数据后调用更新,防止定时器超时
talkDataOverTimeTimerManager.receiveMessage();
}
}
void _handleTalkData({required TalkData talkData}) {
if (talkData == null) return;
final contentType = talkData.contentType;
switch (contentType) {
case TalkData_ContentTypeE.H264:
_handleVideoH264(talkData);
break;
case TalkData_ContentTypeE.Image:
_handleVideoImage(talkData);
break;
case TalkData_ContentTypeE.G711:
_handleVideoG711(talkData);
break;
default:
print('❌未知的TalkData--->contentType类型');
break;
}
}
void _handleVideoH264(TalkData talkData) {
final List<int> content = talkData.content;
// 解析 H.264 NALU
_parseH264Nalus(content);
}
void _handleVideoImage(TalkData talkData) {}
void _handleVideoG711(TalkData talkData) {}
// 解析 H.264 NALU
void _parseH264Nalus(List<int> h264Stream) {
print('开始解析 H.264 NALU...');
int index = 0;
while (index < h264Stream.length) {
// 查找下一个 NALU 的起始码
int nextStartCodeIndex = findNextStartCode(h264Stream, index);
if (nextStartCodeIndex == -1) {
// 如果没有找到更多的起始码,结束解析
break;
}
// 提取当前 NALU
Uint8List naluData =
Uint8List.fromList(h264Stream.sublist(index, nextStartCodeIndex));
// 解析 NALU 头部
int naluType = naluData[0] & 0x1F; // NALU 类型位于第一个字节的低 5 位
print('找到 NALU类型: $naluType,长度: ${naluData.length}');
// 根据 NALU 类型进行处理
handleNalu(naluType, naluData);
// 更新索引到下一个 NALU 的起始位置
index = nextStartCodeIndex;
}
}
// 查找下一个 NALU 的起始码
int findNextStartCode(List<int> data, int startIndex) {
for (int i = startIndex; i < data.length - 3; i++) {
// 检查 3 字节起始码
if (data[i] == 0x00 && data[i + 1] == 0x00 && data[i + 2] == 0x01) {
return i;
}
// 检查 4 字节起始码
if (i < data.length - 4 &&
data[i] == 0x00 &&
data[i + 1] == 0x00 &&
data[i + 2] == 0x00 &&
data[i + 3] == 0x01) {
return i;
}
}
// 如果没有找到更多的起始码,返回 -1
return -1;
}
// 处理 NALU
void handleNalu(int naluType, Uint8List naluData) {
switch (naluType) {
case 5:
print('IDR 帧 (关键帧)');
break;
case 1:
print('非 IDR 帧 (P 帧)');
break;
case 7:
print('SPS (序列参数集)');
break;
case 8:
print('PPS (图像参数集)');
break;
default:
print('其他 NALU 类型: $naluType');
}
// 你可以在这里根据 NALU 类型进行进一步处理
// 例如,将 SPS 和 PPS 传递给解码器,或将视频帧渲染到屏幕上
}
}