// ignore_for_file: avoid_print import 'dart:io'; import 'dart:typed_data'; import 'package:aves/services/cast/cast_fmp4_fragment_parser.dart'; Future main(List 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 { 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', ); } }