public TestResult FindDarkFramesTest(string filename)
{
FileInfo inputFile = AvailableFiles[filename];
var inputFileObject = new InputFileObject(AvailableFiles[filename]);
Logger.Info("-------------");
Logger.Info("Running dark frame test on " + inputFile.FullName);
Logger.Info("Processing: " + inputFile.FullName);
DateTime startScanTime = DateTime.Now;
MainModel.IgnoreEarlyHighlights = false;
MainModel.UseCaptureOffset = false;
MainModel.HighlightObjects.Clear();
var scanWorker = new ScanWorker(inputFileObject);
scanWorker.RunWorkerAsync();
while (scanWorker.IsBusy)
{
System.Threading.Thread.Sleep(500);
}
Logger.Info("Results for " + inputFile.FullName);
DateTime endScanTime = DateTime.Now;
TimeSpan scanTimeSpan = endScanTime - startScanTime;
Logger.Info("Video duration: " + Math.Round(inputFileObject.VideoDurationInSeconds, 2) + "s");
Logger.Info("Scan time: " + Math.Round(scanTimeSpan.TotalSeconds, 2) + "s");
Debug.Assert(inputFileObject.FramesPerSecond > 0);
Debug.Assert(inputFileObject.VideoDurationInSeconds > 0);
var tr = new TestResult
{
InputFile = inputFile,
ActualScore = 0,
DarkTimesFound = new List<string>(),
DarkTimesExpected = new List<string>(),
FalsePositives = new List<string>(),
Matched = new List<string>(),
Missing = new List<string>(),
ScanTime = scanTimeSpan
};
#region Look up expected dark times
string expectedDarkTimesFilePath = inputFile.FullName + ".txt";
var expectedDarkTimes = new string[] { };
if (File.Exists(expectedDarkTimesFilePath))
{
var sr = new StreamReader(expectedDarkTimesFilePath);
expectedDarkTimes = sr.ReadToEnd().Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
}
tr.MaxScore = expectedDarkTimes.Length * (int)ScanResultScore.Found;
tr.DarkTimesExpected = expectedDarkTimes.ToList<string>();
#endregion
#region Convert dark times to dark spots
var expectedMarkTimeSpans = new List<TimeSpan>();
foreach (string s in expectedDarkTimes)
{
TimeSpan ts = TimeSpan.Parse(s); // ex. 0:06
//expectedMarkTimeSpans.Add((long)(ts.TotalSeconds * inputFileObject.FramesPerSecond));
expectedMarkTimeSpans.Add(ts);
}
Logger.Info("Expected dark times and frames:");
foreach (var ts in expectedMarkTimeSpans)
{
var frame = Math.Round(ts.TotalSeconds * inputFileObject.FramesPerSecond, 0);
Logger.Info("- " + ts.ToString("c") + " => " + frame);
}
#endregion
Logger.Info("Found dark times and frames:");
foreach (var highlightObject in MainModel.HighlightObjects)
{
tr.DarkTimesFound.Add(highlightObject.BookmarkTime.ToString("c"));
var frame = Math.Round(highlightObject.BookmarkTime.TotalSeconds * inputFileObject.FramesPerSecond, 0);
Logger.Info("- " + highlightObject.BookmarkTime.ToString("c") + " => " + frame);
}
// If we have any failures at all, the entire test fails. But when debugging, we'll want to know where and how it failed.
bool testFail = false;
#region Make sure expected dark spots are near actual dark frames
Logger.Info("Comparing expected spots with actual spots");
var scanSummary = new SortedDictionary<TimeSpan, ScanResultScore>();
const int toleranceInSeconds = 4; // our expected dark frame must be within 3 seconds of actual dark frames
//var toleranceInFrames = (int)(toleranceInSeconds * inputFileObject.FramesPerSecond);
foreach (var expectedMarkTimeSpan in expectedMarkTimeSpans)
{
var isFound = false;
foreach (var highlightObject in MainModel.HighlightObjects)
{
if (Math.Abs(highlightObject.BookmarkTime.TotalSeconds - expectedMarkTimeSpan.TotalSeconds) <= toleranceInSeconds)
{
if (scanSummary.ContainsKey(expectedMarkTimeSpan) == false)
{
var frame = Math.Round(expectedMarkTimeSpan.TotalSeconds * inputFileObject.FramesPerSecond, 0);
Logger.Info("- Success: Found dark spot near " + expectedMarkTimeSpan.ToString("c") + " => frame " + frame);
scanSummary.Add(expectedMarkTimeSpan, ScanResultScore.Found);
tr.Matched.Add(expectedMarkTimeSpan.ToString("c"));
isFound = true;
}
else
{ // there's a false positive here. two found bookmarks were near an expected bookmark
testFail = true;
scanSummary.Add(highlightObject.BookmarkTime, ScanResultScore.FalsePositive);
tr.FalsePositives.Add(highlightObject.BookmarkTime.ToString("c"));
var frame = Math.Round(highlightObject.BookmarkTime.TotalSeconds * inputFileObject.FramesPerSecond, 0);
Logger.Info("- Found false positive at " + highlightObject.BookmarkTime.ToString("c") + " => frame " + frame);
}
break;
}
}
if (isFound == false)
{
scanSummary.Add(expectedMarkTimeSpan, ScanResultScore.Missing);
testFail = true;
tr.Missing.Add(expectedMarkTimeSpan.ToString("c"));
var frame = Math.Round(expectedMarkTimeSpan.TotalSeconds * inputFileObject.FramesPerSecond, 0);
Logger.Info("- Error! Could not find dark spot near " + expectedMarkTimeSpan.ToString("c") + " => frame " + frame);
}
}
// find the false positives
foreach (var highlightObject in MainModel.HighlightObjects)
{
bool isFound = false;
foreach (var expectedMarkTimeSpan in expectedMarkTimeSpans)
{
if (Math.Abs(highlightObject.BookmarkTime.TotalSeconds - expectedMarkTimeSpan.TotalSeconds) <= toleranceInSeconds)
{
isFound = true;
break;
}
}
if (isFound == false)
{
testFail = true;
scanSummary.Add(highlightObject.BookmarkTime, ScanResultScore.FalsePositive);
tr.FalsePositives.Add(highlightObject.BookmarkTime.ToString("c"));
var frame = Math.Round(highlightObject.BookmarkTime.TotalSeconds * inputFileObject.FramesPerSecond, 0);
Logger.Info("- Found false positive at " + highlightObject.BookmarkTime.ToString("c") + " => frame " + frame);
}
}
#endregion
#region Print summary
Logger.Info("-------------");
Logger.Info("Test results summary:");
foreach (var kvp in scanSummary)
{
var frame = Math.Round(kvp.Key.TotalSeconds * inputFileObject.FramesPerSecond, 0);
Logger.Info("- Time " + kvp.Key.ToString("c") + " (frame " + frame + "): " + kvp.Value.ToString());
tr.ActualScore += (int)kvp.Value;
}
Logger.Info("Max score: " + tr.MaxScore);
Logger.Info("Actual score: " + tr.ActualScore);
Logger.Info("Found count: " + tr.Matched.Count);
Logger.Info("False positive count: " + tr.FalsePositives.Count);
Logger.Info("Missing count: " + tr.Missing.Count);
#endregion
if (testFail)
{
tr.Failed = true;
Logger.Info("Test failed. See debug log for details.");
}
return tr;
}