private FFmpegMediaFrame SearchFrame(decimal renderTime)
{
lock (SyncLock)
{
var frameCount = Frames.Count;
// fast condition checking
if (frameCount <= 0) return null;
if (frameCount == 1) return Frames[0];
// variable setup
var lowIndex = 0;
var highIndex = frameCount - 1;
var midIndex = 1 + lowIndex + (highIndex - lowIndex) / 2;
// edge condition cheching
if (Frames[lowIndex].StartTime >= renderTime) return Frames[lowIndex];
if (Frames[highIndex].StartTime <= renderTime) return Frames[highIndex];
// First guess, very low cost, very fast
if (midIndex < highIndex && renderTime >= Frames[midIndex].StartTime && renderTime < Frames[midIndex + 1].StartTime)
return Frames[midIndex];
// binary search
while (highIndex - lowIndex > 1)
{
midIndex = lowIndex + (highIndex - lowIndex) / 2;
if (renderTime < Frames[midIndex].StartTime)
highIndex = midIndex;
else
lowIndex = midIndex;
}
// linear search
for (var i = highIndex; i >= lowIndex; i--)
{
if (Frames[i].StartTime <= renderTime)
return Frames[i];
}
return null;
}
}