81 lines
2.4 KiB
Dart
81 lines
2.4 KiB
Dart
/// NALU相关工具类与结构体
|
|
import 'dart:typed_data';
|
|
|
|
/// NALU单元结构体
|
|
class NaluUnit {
|
|
final int type; // NALU类型
|
|
final List<int> data;
|
|
NaluUnit(this.type, this.data);
|
|
}
|
|
|
|
class NaluUtils {
|
|
/// 分离一帧数据中的所有NALU单元
|
|
static List<NaluUnit> splitNalus(List<int> data) {
|
|
final List<NaluUnit> nalus = [];
|
|
int i = 0;
|
|
List<int> startCodes = [];
|
|
// 先找到所有起始码位置
|
|
while (i < data.length - 3) {
|
|
if (i < data.length - 4 &&
|
|
data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 0 && data[i + 3] == 1) {
|
|
startCodes.add(i);
|
|
i += 4;
|
|
} else if (data[i] == 0 && data[i + 1] == 0 && data[i + 2] == 1) {
|
|
startCodes.add(i);
|
|
i += 3;
|
|
} else {
|
|
i++;
|
|
}
|
|
}
|
|
// 补上结尾
|
|
startCodes.add(data.length);
|
|
// 分割NALU
|
|
int nalusTotalLen = 0;
|
|
for (int idx = 0; idx < startCodes.length - 1; idx++) {
|
|
int start = startCodes[idx];
|
|
int next = startCodes[idx + 1];
|
|
int skip = (data[start] == 0 && data[start + 1] == 0 && data[start + 2] == 0 && data[start + 3] == 1) ? 4 : 3;
|
|
int naluStart = start + skip;
|
|
if (naluStart < next) {
|
|
final nalu = data.sublist(start, next);
|
|
nalusTotalLen += nalu.length;
|
|
if (nalu.isNotEmpty) {
|
|
nalus.add(NaluUnit(getNaluType(nalu), nalu));
|
|
}
|
|
}
|
|
}
|
|
if (nalus.isEmpty && data.isNotEmpty) {
|
|
nalus.add(NaluUnit(getNaluType(data), data));
|
|
} else if (nalusTotalLen < data.length) {
|
|
nalus.add(NaluUnit(getNaluType(data.sublist(nalusTotalLen)), data.sublist(nalusTotalLen)));
|
|
}
|
|
return nalus;
|
|
}
|
|
|
|
/// 获取NALU类型
|
|
static int getNaluType(List<int> nalu) {
|
|
if (nalu.isEmpty) return -1;
|
|
int offset = 0;
|
|
if (nalu.length >= 4 && nalu[0] == 0x00 && nalu[1] == 0x00) {
|
|
if (nalu[2] == 0x01)
|
|
offset = 3;
|
|
else if (nalu[2] == 0x00 && nalu[3] == 0x01)
|
|
offset = 4;
|
|
}
|
|
if (nalu.length > offset) {
|
|
return nalu[offset] & 0x1F;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/// 提取所有指定type的NALU并拼接返回
|
|
static List<int> filterNalusByType(List<int> frameData, int type) {
|
|
final nalus = splitNalus(frameData);
|
|
final filtered = nalus.where((nalu) => nalu.type == type).toList();
|
|
final result = <int>[];
|
|
for (final nalu in filtered) {
|
|
result.addAll(nalu.data);
|
|
}
|
|
return result;
|
|
}
|
|
} |