Files
OpenMaidEngine/tools/movie-corpus-gate/Program.cs
2026-07-22 09:44:57 -04:00

61 lines
3.0 KiB
C#

using System.Text.Json;
using Age.Engine.Sys4;
static string? Option(string[] arguments, string name)
{
int index = Array.IndexOf(arguments, name);
return index >= 0 && index + 1 < arguments.Length ? arguments[index + 1] : null;
}
if (args.Contains("--help"))
{
Console.WriteLine("usage: dotnet run --project tools/movie-corpus-gate -- [--output <json>] [--native-dir <dir>] [--expected-count 213] [--max-item-ms 30000]");
return 0;
}
string output = Path.GetFullPath(Option(args, "--output")
?? Path.Combine(Paths.Build, "movie-corpus-ffmpeg.json"));
string nativeDirectory = Path.GetFullPath(Option(args, "--native-dir")
?? Path.Combine(Paths.Build, "native", "win-x64"));
int expectedCount = int.Parse(Option(args, "--expected-count") ?? "213");
long maximumItemMilliseconds = long.Parse(Option(args, "--max-item-ms") ?? "30000");
string nativeLibrary = Path.Combine(nativeDirectory, OperatingSystem.IsWindows()
? "age_movie_ffmpeg.dll" : OperatingSystem.IsMacOS()
? "libage_movie_ffmpeg.dylib" : "libage_movie_ffmpeg.so");
if (!File.Exists(nativeLibrary))
{
Console.Error.WriteLine($"native movie shim not found: {nativeLibrary}");
return 2;
}
Environment.SetEnvironmentVariable("AGE_FFMPEG_NATIVE_DIR", nativeDirectory);
var catalog = Sys4AssetCatalog.Load(Paths.Sys4Ini);
var store = new Sys4AssetStore(catalog, Paths.GameDir, Paths.GameDir);
var resources = new ResourceMap(catalog, store);
Console.WriteLine("discovering MPEG program streams from .AGF catalog entries...");
var discovered = MovieCorpusDiscovery.DiscoverMpegMovies(catalog, store);
var inputs = discovered.Select(packed => new MovieCorpusInput(
packed.PackedId, packed.Asset.Name, () => resources.ReadMovie(packed.Asset))).ToArray();
Console.WriteLine($"discovered {inputs.Length} movies; decoding every frame without presentation waits");
var gate = new MovieCorpusGate(payload => new FfmpegMovieSession(payload));
MovieCorpusReport report = gate.Run(inputs, expectedCount, maximumItemMilliseconds,
(index, count, item) => Console.WriteLine(
$"[{index,3}/{count}] {(item.Passed ? "PASS" : "FAIL")} {item.PackedIdHex,-10} {item.Name,-16} " +
$"{item.Width}x{item.Height} {item.FrameCount}f {item.StopTimeMs}ms decode={item.DecodeMilliseconds}ms" +
(item.Error == null ? "" : $" :: {item.Error}")));
string? parent = Path.GetDirectoryName(output);
if (!string.IsNullOrEmpty(parent)) Directory.CreateDirectory(parent);
var jsonOptions = new JsonSerializerOptions
{
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
};
File.WriteAllText(output, JsonSerializer.Serialize(report, jsonOptions));
Console.WriteLine($"summary: {report.PassedCount}/{report.CandidateCount} passed, " +
$"{report.FailedCount} failed in {report.ElapsedMilliseconds} ms");
foreach (string error in report.SelectionErrors) Console.Error.WriteLine("selection: " + error);
Console.WriteLine("report: " + output);
return report.Passed ? 0 : 1;