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

142 lines
4.1 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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';
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
void handleReq(ScpMessage scpMessage) {}
@override
void handleResp(ScpMessage scpMessage) {}
@override
void handleInvalidReq(ScpMessage scpMessage) {}
@override
void handleRealTimeData(ScpMessage scpMessage) {
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 传递给解码器,或将视频帧渲染到屏幕上
}
}