using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; namespace Assets.AR { public class VideoPoint { public float Distance { get; set; } public float Time { get; set; } } public class VideoPointsSync { private const float DefaultFps = 29.97f; protected float[] videoDistances; protected float[] videoTimes; protected float fps; public int Count => this.videoDistances.Length; public float LastVideoFrame => this.videoTimes[this.videoTimes.Length - 1] * this.fps; public VideoPointsSync(IEnumerable videoPoints, float fps = 29.97f) { List list = videoPoints.ToList(); list.Sort((Comparison)((x, y) => x.Distance.CompareTo(y.Distance))); VideoPoint videoPoint1 = list[0]; for (int index = 1; index < list.Count; ++index) { VideoPoint videoPoint2 = list[index]; if ((double)videoPoint2.Distance == (double)videoPoint1.Distance) { list.RemoveAt(index); --index; } else videoPoint1 = videoPoint2; } this.videoDistances = list.Select((Func)(x => x.Distance)).ToArray(); this.videoTimes = list.Select((Func)(x => x.Time)).ToArray(); this.fps = fps; } public float GetVideoSpeedAtDistance(float distance) { int index = this.IndexOfVideoPointForDistance(distance); return index == 0 || index == this.Count ? 0.0f : (float)(((double)this.videoDistances[index] - (double)this.videoDistances[index - 1]) / ((double)this.videoTimes[index] - (double)this.videoTimes[index - 1])); } public int IndexOfVideoPointForDistance(float distance) { int num = Array.BinarySearch(this.videoDistances, distance); return num < 0 ? ~num : num; } public int IndexOfVideoPointForTime(float time) { int num = Array.BinarySearch(this.videoTimes, time); return num < 0 ? ~num : num; } public float GetVideoFrameAtDistance(float distance) { int index = this.IndexOfVideoPointForDistance(distance); if (index == 0) return this.videoTimes[0] * this.fps; if (index == this.Count) return this.videoTimes[this.Count - 1] * this.fps; float t = Mathf.InverseLerp(this.videoDistances[index - 1], this.videoDistances[index], distance); return Mathf.Lerp(this.videoTimes[index - 1], this.videoTimes[index], t) * this.fps; } public float GetDistanceForVideoFrame(float frame) { float time = frame / this.fps; int index = this.IndexOfVideoPointForTime(time); if (index == 0) return this.videoDistances[0]; if (index == this.Count) return this.videoDistances[this.Count - 1]; float t = Mathf.InverseLerp(this.videoTimes[index - 1], this.videoTimes[index], time); return Mathf.Lerp(this.videoDistances[index - 1], this.videoDistances[index], t); } public float AverageVideoSpeed(float startFrame, float endFrame) => (double)startFrame == (double)endFrame ? this.GetVideoSpeedAtDistance(this.GetDistanceForVideoFrame(startFrame)) : (float)(((double)this.GetDistanceForVideoFrame(endFrame) - (double)this.GetDistanceForVideoFrame(startFrame)) * ((double)this.fps / ((double)endFrame - (double)startFrame))); } }