2023-12-27 17:16:58 +08:00

192 lines
6.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:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
import 'package:flutter_sound/flutter_sound.dart';
import 'package:star_lock/talk/call/g711.dart';
import 'package:star_lock/talk/call/iFrameInfo.dart';
import 'package:star_lock/talk/udp/udp_talkClass.dart';
import '../../tools/eventBusEventManage.dart';
class CallTalk {
static CallTalk? _manager;
static int POS_iframe_index = 63;
static int POS_alen = 65;
static int POS_blen = 73;
static int POS_bag_index = 71;
static int POS_bag_num = 69;
static int POS_data = 77;
static int ABUF_NUM = 100;
static int FIRSTINDEX = 1;
int status = 0; // 假设有这个成员变量
IframeInfo? iframe; // 假设有这个成员变量
var growableList;
bool getFirstFrame = false; //是否得到了第一帧
final FlutterSoundPlayer _audioPlayer = FlutterSoundPlayer();
List<int> allPcmData = [];
int _bufferSize = 400; // 设置缓冲区大小,根据需求调整
CallTalk._init() {
iframe = IframeInfo();
}
static CallTalk _share() {
_manager ??= CallTalk._init();
return _manager!;
}
factory CallTalk() => _share();
CallTalk get manager => _share();
Future<void> getAVData(Uint8List bb, int len) async {
// 音频数据
if (bb[61] == 1) {
Uint8List g711Data = bb.sublist(77, bb.length);
List<int> pcmBytes;
try {
// 将 ALaw 转为 Linear
pcmBytes = G711().convertList(g711Data);
allPcmData.addAll(pcmBytes);
// await Future.delayed(const Duration(seconds: 1));
_initializeAudioPlayer(allPcmData);
} catch (e) {
print('Error decoding G.711 to PCM: $e');
}
}
// 视频数据
else {
// 音视频数据开始下标
var bagLen = bb[POS_blen + 2] + bb[POS_blen + 3] * 256;
// print('音视频数据开始下标 bagLen$bagLen');
// 获取帧序号 63
int getIframeIndex =
bb[POS_iframe_index] + bb[POS_iframe_index + 1] * 256;
// print('获取帧序号 getIframeIndex$getIframeIndex');
// 获取帧长度 65
// int alen = bb[POS_alen] & 0xff;
// var alenList = bb.sublist(POS_alen, POS_alen + 4);
// int alen = ((0xff & alenList[(0)]) << 24 |
// (0xff & alenList[1]) << 16 |
// (0xff & alenList[2]) << 8 |
// (0xFF & alenList[3]));
// print('获取帧长度 alen$alen');
// 当前包号 71
int getBagIndex = bb[POS_bag_index] & 0xff;
// print('当前包号 getBagIndex$getBagIndex');
// 总包数 69
int getBagNum = bb[POS_bag_num] & 0xff;
// print('总包数 getBagNum$getBagNum');
// 数据长度 73
int blen = bb[POS_blen] + bb[POS_blen + 1] * 256;
// print('数据长度 blen$blen');
// 这里判断是否是同一帧,如果不是同一帧就重新创建一个 IframeInfo
if (getIframeIndex != iframe!.iframeIndex) {
iframe = IframeInfo();
iframe!.iframeIndex = getIframeIndex;
iframe!.bagNum = getBagNum;
// iframe!.cur_len = alen;
// iframe!.bb = Uint8List(alen);
growableList = iframe!.bb!.toList(growable: true);
}
iframe!.bagReceive++;
// 如果是同一帧就添加起来
if (getIframeIndex == iframe!.iframeIndex) {
var getList = bb.sublist(77, bb.length);
growableList.addAll(getList);
}
// print('iframe.bagNum: ${iframe!.bagNum} iframe.bagReceive: ${iframe!.bagReceive}');
// 如果收到的包数等于总包数,说明这一帧数据已经接收完毕
if (iframe!.bagNum == iframe!.bagReceive) {
// print('播放第${iframe!.iframeIndex}帧 一帧图片的hexStringData: ${Uint8List.fromList(growableList)}');
//判断第一帧是否接收到
if (iframe!.iframeIndex == 0) {
getFirstFrame = true;
eventBus.fire(GetFirstFrameGoPush(getFirstFrame));
}
eventBus.fire(GetTVDataRefreshUI(growableList));
}
}
}
//视频相关处理
void printByteArray(String printTitle, Uint8List byteArray) {
final int chunkSize = byteArray.length; // 每行显示的字节数
int length = byteArray.length;
for (int i = 0; i < length; i += chunkSize) {
int end = (i + chunkSize < length) ? i + chunkSize : length;
Uint8List chunk = byteArray.sublist(i, end);
String hexString =
chunk.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(' ');
debugPrint(hexString);
}
}
//音频相关处理
Future<void> _initializeAudioPlayer(List<int> audioData) async {
// _audioPlayer.closePlayer();
_audioPlayer.openPlayer();
// await _audioPlayer
// .setSubscriptionDuration(const Duration(milliseconds: 10));
if (audioData.isNotEmpty) {
// 在这里处理你的音频数据
print('转换pcmBytes数据长度为:${audioData.length}');
// _playRawData(audioData);
playAudioStream(audioData);
} else {
print('Failed to read audio data.');
}
}
Future<void> _playRawData(List<int> rawData) async {
print(
'啊啦啦啦啦啦数据长度为:${G711().convertToInt8ListLittleEndian(rawData).length}, 数据为 ${G711().convertToInt8ListLittleEndian(rawData)}');
await _audioPlayer.startPlayer(
fromDataBuffer: G711().convertToInt8ListLittleEndian(rawData),
codec: Codec.pcm16,
sampleRate: 8000,
numChannels: 1,
);
}
Future<void> playAudioStream(List<int> audioData) async {
await _audioPlayer
.setSubscriptionDuration(const Duration(milliseconds: 10));
// 启动播放器
await _audioPlayer.startPlayer(
codec: Codec.pcm16,
sampleRate: 8000,
numChannels: 1,
);
// 将音频数据逐步添加到缓冲区
for (int i = 0; i < audioData.length; i += 320) {
int chunkSize = 320;
if (i + chunkSize > audioData.length) {
chunkSize = audioData.length - i;
}
List<int> chunk = audioData.sublist(i, i + chunkSize);
await _audioPlayer
.feedFromStream(G711().convertToInt8ListLittleEndian(chunk));
}
// 停止播放器
await _audioPlayer.stopPlayer();
}
}