Aves_mio0.88/tool/cast/test_fmp4_fragment_parser.dart
2026-10-03 12:51:15 +02:00

200 lines
4.3 KiB
Dart

// ignore_for_file: avoid_print
import 'dart:io';
import 'dart:typed_data';
import 'package:aves/services/cast/cast_fmp4_fragment_parser.dart';
Future<void> main(List<String> arguments) async {
final sourcePath = arguments.isNotEmpty ? arguments.first : 'stream_test.fmp4';
final sourceFile = File(sourcePath);
if (!await sourceFile.exists()) {
throw StateError(
'File fMP4 non trovato: ${sourceFile.absolute.path}',
);
}
const moofOffset = 1684;
const moofSize = 3164;
const mdatOffset = 4848;
const mdatSize = 2339259;
const mdatHeaderSize = 8;
final source = await sourceFile.open(
mode: FileMode.read,
);
try {
await source.setPosition(moofOffset);
final moofData = await source.read(
moofSize,
);
if (moofData.length != moofSize) {
throw StateError(
'Lettura moof incompleta: '
'actual=${moofData.length} '
'expected=$moofSize',
);
}
const parser = CastFmp4FragmentParser();
final fragment = parser.parse(
moofBytes: Uint8List.fromList(moofData),
moofOffset: moofOffset,
mdatOffset: mdatOffset,
mdatSize: mdatSize,
mdatHeaderSize: mdatHeaderSize,
initialDecodeTimes: const <int, int>{
1: 0,
2: 0,
},
);
print(
'FRAGMENT '
'moofOffset=${fragment.moofOffset} '
'moofSize=${fragment.moofSize} '
'mdatOffset=${fragment.mdatOffset} '
'mdatSize=${fragment.mdatSize} '
'mdatPayloadOffset=${fragment.mdatPayloadOffset} '
'mdatPayloadSize=${fragment.mdatPayloadSize}',
);
for (final track in fragment.tracks) {
print(
'TRACK '
'trackId=${track.trackId} '
'sampleCount=${track.sampleCount} '
'initialDecodeTime=${track.initialDecodeTime} '
'nextDecodeTime=${track.nextDecodeTime} '
'totalDuration=${track.totalDuration} '
'totalSampleBytes=${track.totalSampleBytes} '
'syncSampleCount=${track.syncSampleCount} '
'firstSampleOffset=${track.firstSampleAbsoluteOffset}',
);
for (final sample in track.samples.take(3)) {
print(
' SAMPLE '
'index=${sample.index} '
'offset=${sample.absoluteOffset} '
'size=${sample.size} '
'duration=${sample.duration} '
'dts=${sample.decodeTime} '
'pts=${sample.presentationTime} '
'flags=0x${sample.flags.toRadixString(16).padLeft(8, '0')} '
'sync=${sample.isSync}',
);
}
}
final audio = fragment.tracks.singleWhere(
(track) => track.trackId == 1,
);
final video = fragment.tracks.singleWhere(
(track) => track.trackId == 2,
);
_expectEqual(
'audio.sampleCount',
audio.sampleCount,
163,
);
_expectEqual(
'audio.totalDuration',
audio.totalDuration,
166912,
);
_expectEqual(
'audio.totalSampleBytes',
audio.totalSampleBytes,
88272,
);
_expectEqual(
'audio.syncSampleCount',
audio.syncSampleCount,
163,
);
_expectEqual(
'audio.firstSampleOffset',
audio.firstSampleAbsoluteOffset,
4856,
);
_expectEqual(
'video.sampleCount',
video.sampleCount,
90,
);
_expectEqual(
'video.totalDuration',
video.totalDuration,
270000,
);
_expectEqual(
'video.totalSampleBytes',
video.totalSampleBytes,
2250979,
);
_expectEqual(
'video.syncSampleCount',
video.syncSampleCount,
3,
);
_expectEqual(
'video.firstSampleOffset',
video.firstSampleAbsoluteOffset,
93128,
);
_expectEqual(
'video.firstSample.size',
video.samples.first.size,
72134,
);
if (!video.samples.first.isSync) {
throw StateError(
'Il primo sample video non è sync',
);
}
_expectEqual(
'mdatPayloadSize',
fragment.mdatPayloadSize,
audio.totalSampleBytes + video.totalSampleBytes,
);
print('FMP4 FRAGMENT PARSER TEST: PASS');
} finally {
await source.close();
}
}
void _expectEqual(
String name,
int actual,
int expected,
) {
if (actual != expected) {
throw StateError(
'$name inatteso: '
'actual=$actual '
'expected=$expected',
);
}
}