// ignore_for_file: avoid_print import 'dart:async'; import 'dart:io'; import 'package:aves/services/cast/cast_fmp4_fragment_parser.dart'; import 'package:aves/services/cast/cast_fmp4_progressive_reader.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 expectedFragments = 5; final fragments = []; late final CastFmp4ProgressiveReader reader; reader = CastFmp4ProgressiveReader( sourcePath: sourceFile.path, pollingInterval: const Duration( milliseconds: 20, ), onFragment: (fragment) async { final fragmentIndex = fragments.length; fragments.add(fragment); final audio = fragment.tracks.singleWhere( (track) => track.trackId == 1, ); final video = fragment.tracks.singleWhere( (track) => track.trackId == 2, ); print( 'FRAGMENT ' 'index=$fragmentIndex ' 'moofOffset=${fragment.moofOffset} ' 'mdatOffset=${fragment.mdatOffset} ' 'audioSamples=${audio.sampleCount} ' 'audioInitialDts=${audio.initialDecodeTime} ' 'audioNextDts=${audio.nextDecodeTime} ' 'videoSamples=${video.sampleCount} ' 'videoInitialDts=${video.initialDecodeTime} ' 'videoNextDts=${video.nextDecodeTime} ' 'videoSyncSamples=${video.syncSampleCount}', ); if (fragments.length >= expectedFragments) { reader.requestStop(); } }, ); await reader.start(); if (fragments.length != expectedFragments) { throw StateError( 'Numero frammenti inatteso: ' 'actual=${fragments.length} ' 'expected=$expectedFragments', ); } const expectedAudioNextDts = [ 166912, 311296, 454656, 599040, 743424, ]; const expectedVideoNextDts = [ 270000, 540000, 810000, 1080000, 1350000, ]; for (var index = 0; index < fragments.length; index++) { final fragment = fragments[index]; final audio = fragment.tracks.singleWhere( (track) => track.trackId == 1, ); final video = fragment.tracks.singleWhere( (track) => track.trackId == 2, ); _expectEqual( 'fragment[$index].audio.nextDts', audio.nextDecodeTime, expectedAudioNextDts[index], ); _expectEqual( 'fragment[$index].video.nextDts', video.nextDecodeTime, expectedVideoNextDts[index], ); _expectEqual( 'fragment[$index].video.sampleCount', video.sampleCount, 90, ); _expectEqual( 'fragment[$index].video.duration', video.totalDuration, 270000, ); if (!video.samples.first.isSync) { throw StateError( 'Il frammento $index non inizia con un keyframe', ); } if (index > 0) { final previous = fragments[index - 1]; final previousAudio = previous.tracks.singleWhere( (track) => track.trackId == 1, ); final previousVideo = previous.tracks.singleWhere( (track) => track.trackId == 2, ); _expectEqual( 'fragment[$index].audio.continuity', audio.initialDecodeTime, previousAudio.nextDecodeTime, ); _expectEqual( 'fragment[$index].video.continuity', video.initialDecodeTime, previousVideo.nextDecodeTime, ); } } _expectEqual( 'reader.fragmentCount', reader.fragmentCount, expectedFragments, ); _expectEqual( 'reader.audioDecodeTime', reader.decodeTimes[1] ?? -1, 743424, ); _expectEqual( 'reader.videoDecodeTime', reader.decodeTimes[2] ?? -1, 1350000, ); print(''); print( 'FMP4 PROGRESSIVE READER TEST: PASS ' 'fragments=${reader.fragmentCount} ' 'audioDts=${reader.decodeTimes[1]} ' 'videoDts=${reader.decodeTimes[2]}', ); } void _expectEqual( String name, int actual, int expected, ) { if (actual != expected) { throw StateError( '$name inatteso: ' 'actual=$actual ' 'expected=$expected', ); } }