Aves_mio0.88/integration_test/fmp4_first_ts_segment_test.dart
2026-10-03 12:51:15 +02:00

231 lines
4.8 KiB
Dart

// ignore_for_file: avoid_print
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:path_provider/path_provider.dart';
import 'package:aves/services/cast/cast_fmp4_fragment_parser.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
const channel = MethodChannel(
'aves/cast_video_optimizer',
);
testWidgets(
'genera il primo segmento TS dal fragmented MP4',
(tester) async {
final cacheDirectory = await getApplicationCacheDirectory();
final inputFile = File(
'${cacheDirectory.path}/stream_test.fmp4',
);
final outputFile = File(
'${cacheDirectory.path}/segment_00000.ts',
);
expect(
await inputFile.exists(),
isTrue,
reason: 'Copia prima stream_test.fmp4 nella cache Android',
);
expect(
await inputFile.length(),
greaterThan(2344107),
);
if (await outputFile.exists()) {
await outputFile.delete();
}
final partialOutput = File(
'${outputFile.path}.part',
);
if (await partialOutput.exists()) {
await partialOutput.delete();
}
const moofOffset = 1684;
const moofSize = 3164;
const mdatOffset = 4848;
const mdatSize = 2339259;
const mdatHeaderSize = 8;
final source = await inputFile.open(
mode: FileMode.read,
);
late final List<int> moofBytes;
try {
await source.setPosition(
moofOffset,
);
moofBytes = await source.read(
moofSize,
);
} finally {
await source.close();
}
expect(
moofBytes.length,
moofSize,
);
const parser = CastFmp4FragmentParser();
final fragment = parser.parse(
moofBytes: Uint8List.fromList(
moofBytes,
),
moofOffset: moofOffset,
mdatOffset: mdatOffset,
mdatSize: mdatSize,
mdatHeaderSize: mdatHeaderSize,
initialDecodeTimes: const <int, int>{
1: 0,
2: 0,
},
);
final audioTrack = fragment.tracks.singleWhere(
(track) => track.trackId == 1,
);
final videoTrack = fragment.tracks.singleWhere(
(track) => track.trackId == 2,
);
final audioSamples = audioTrack.samples
.where(
(sample) => sample.decodeTime < 144000,
)
.map(_sampleToMap)
.toList(growable: false);
final videoSamples = videoTrack.samples
.where(
(sample) => sample.decodeTime < 270000,
)
.map(_sampleToMap)
.toList(growable: false);
expect(
audioSamples.length,
inInclusiveRange(140, 143),
);
expect(
videoSamples.length,
90,
);
expect(
videoTrack.samples.first.isSync,
isTrue,
);
print(
'FMP4 TOOL INPUT '
'input=${inputFile.path} '
'audioSamples=${audioSamples.length} '
'videoSamples=${videoSamples.length}',
);
final report = await channel.invokeMapMethod<String, dynamic>(
'writeFmp4FirstTsSegmentTest',
<String, dynamic>{
'inputPath': inputFile.path,
'outputPath': outputFile.path,
'audioSamples': audioSamples,
'videoSamples': videoSamples,
},
);
expect(
report,
isNotNull,
);
expect(
report!['success'],
isTrue,
);
expect(
report['videoSamples'],
90,
);
expect(
report['audioSamples'],
inInclusiveRange(140, 143),
);
expect(
report['keyframes'],
3,
);
expect(
report['accessUnitDelimiterCount'],
90,
);
expect(
await outputFile.exists(),
isTrue,
);
final outputBytes = await outputFile.length();
expect(
outputBytes,
greaterThan(0),
);
expect(
outputBytes % 188,
0,
);
print(
'FMP4 FIRST TS TOOL PASS '
'output=${outputFile.path} '
'bytes=$outputBytes '
'report=$report',
);
print(
'FILE READY FOR ADB COPY '
'path=${outputFile.path} '
'waitingSeconds=120',
);
await Future<void>.delayed(
const Duration(minutes: 2),
);
},
);
}
Map<String, dynamic> _sampleToMap(
Fmp4SampleInfo sample,
) {
return <String, dynamic>{
'offset': sample.absoluteOffset,
'size': sample.size,
'dts': sample.decodeTime,
'pts': sample.presentationTime,
'duration': sample.duration,
'sync': sample.isSync,
};
}