using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; namespace Assets.AR { public class ARVideoPlayerControl { private const float MinVideoPlaybackSpeedChangeInterval = 0.2f; private const float MaxPlaybackSpeed = 1.5f; private const float MaxCameraDistanceError = 200f; private DateTime lastPlaybackSpeedChange = DateTime.MinValue; private float fixedTimeFrame; private DateTime fixedTimeSeekFinished = DateTime.MinValue; private int lapCount = 1; private double lapLength; public float FixedVideoFrame => this.fixedTimeFrame; //public IDistanceSource RiderDistance { get; set; public AVProVideoPlayer VideoPlayer { get; private set; } //public ISpeedSource RiderSpeed { get; set; } public VideoPointsSync VideoSyncSource { get; set; } public ARRoute Route { get; set; } public int VideoFrameOffset { get; set; } public float CameraFollowDistance { get; set; } public bool AllowUpdate { get; set; } = true; public float CameraDistanceError { get; private set; } public bool IsTimeFixed { get; private set; } public float FrameIndexDistanceCorrection { get; private set; } public bool IsMultilap => this.lapCount > 1; public void SetVideoPlayer(AVProVideoPlayer player) => this.VideoPlayer = player; public void SetMultiLap(int lapCount, double lapLength) { this.lapCount = lapCount; this.lapLength = lapLength; } public void FixTimeByDistance(float distance) => this.FixTimeByFrame(this.VideoSyncSource.GetVideoFrameAtDistance(distance)); public void FixTimeByFrame(float frame) { this.IsTimeFixed = true; this.fixedTimeFrame = frame; this.fixedTimeSeekFinished = DateTime.MinValue; if (this.VideoPlayer.IsPaused) this.VideoPlayer.Resume(); this.VideoPlayer.SetPlaybackSpeed(0.25f); this.VideoPlayer.Seek((long)frame, true); } public void UnFixTime() { //this.IsTimeFixed = false; //float videoFrameAtDistance = this.VideoSyncSource.GetVideoFrameAtDistance(this.RiderDistance.LapDistance); //float num = this.VideoSyncSource.AverageVideoSpeed(videoFrameAtDistance, videoFrameAtDistance); //float playbackSpeed = (double)num != 0.0 ? this.RiderSpeed.Speed / num : 0.0f; //if (this.VideoPlayer.IsPaused) // this.VideoPlayer.Resume(); //this.VideoPlayer.SetPlaybackSpeed(playbackSpeed); //this.lastPlaybackSpeedChange = DateTime.UtcNow; //this.VideoPlayer.Seek((long)videoFrameAtDistance, true); } private void SkipVideoToDistance(float distance) => this.SkipVideoToFrame((long)this.VideoSyncSource.GetVideoFrameAtDistance(distance)); private void SkipVideoToFrame(long frame) => this.VideoPlayer.Seek(frame); private const float TimerInterval = 0.2f; public void UpdateVideoPlayRate(float speed, float routeDistance) { if (!this.AllowUpdate) return; if (this.IsTimeFixed) { if (this.VideoPlayer.IsSeeking) return; if (this.fixedTimeSeekFinished == DateTime.MinValue) this.fixedTimeSeekFinished = DateTime.UtcNow; if (DateTime.UtcNow.Subtract(this.fixedTimeSeekFinished).TotalSeconds < 0.25) return; if ((double)this.VideoPlayer.CurrentFrame > (double)this.fixedTimeFrame) this.VideoPlayer.Pause(); //if (this.VideoPlayer is RouvyVideoPlayer.RouvyVideoPlayer videoPlayer) // videoPlayer.TargetFrame = this.fixedTimeFrame; this.VideoPlayer.UpdateCurrentFrame(); this.FrameIndexDistanceCorrection = 0.0f; } else { var videoFrameAtDistance1 = this.VideoSyncSource.GetVideoFrameAtDistance(routeDistance); var val2 = routeDistance - this.CameraFollowDistance; //if (this.IsMultilap && (double)this.RiderDistance.RouteDistance > (double)this.RiderDistance.LapDistance && (double)val2 < 0.0) // val2 += (float)this.lapLength; var distance = Math.Max(0.0f, val2); var frame = this.VideoSyncSource.GetVideoFrameAtDistance(distance) + (float)this.VideoFrameOffset; if (this.Route != null && (double)this.Route.GetVisibility(frame) > 10.0) frame = (float)this.Route.GetFrameAtDistance(Math.Max(0.0, this.Route.GetDistanceForFrame((double)videoFrameAtDistance1) - (double)this.CameraFollowDistance)) + (float)this.VideoFrameOffset; //if (this.VideoPlayer is RouvyLib.Video.RouvyVideoPlayer.RouvyVideoPlayer videoPlayer) // videoPlayer.TargetFrame = frame; this.VideoPlayer.UpdateCurrentFrame(); var distanceForVideoFrame = this.VideoSyncSource.GetDistanceForVideoFrame(this.VideoPlayer.CurrentFrame - (float)this.VideoFrameOffset); float f; if (this.Route != null) { var frameAtDistance = this.Route.GetFrameAtDistance(this.Route.GetDistanceForFrame((double)this.VideoPlayer.CurrentFrame - (double)this.VideoFrameOffset) + (double)Mathf.Min(routeDistance, this.CameraFollowDistance)); f = videoFrameAtDistance1 - (float)frameAtDistance; } else f = frame - (this.VideoPlayer.CurrentFrame - (float)this.VideoFrameOffset); var num1 = Mathf.Clamp01(PFMath.Lerp(0.0f, 1f, 100f, 0.0f, Mathf.Abs(f))); this.FrameIndexDistanceCorrection = f * num1; this.CameraDistanceError = distance - distanceForVideoFrame; if (this.IsMultilap) { var num2 = distance - (distanceForVideoFrame + (float)this.lapLength); if ((double)Math.Abs(num2) < (double)Math.Abs(this.CameraDistanceError) && (double)Math.Abs(num2) < 200.0) return; } if ((double)Math.Abs(this.CameraDistanceError) > 200.0) { this.SkipVideoToDistance(distance); } else { var totalSeconds = DateTime.UtcNow.Subtract(this.lastPlaybackSpeedChange).TotalSeconds; if (totalSeconds >= 0.0 && totalSeconds < TimerInterval) return; var num3 = (float)totalSeconds; var num4 = num3 * speed; var offset = this.VideoSyncSource.GetDistanceForVideoFrame((float)((double)this.VideoPlayer.CurrentFrame - (double)this.VideoFrameOffset + (double)num3 * (double)this.VideoPlayer.PlaybackSpeed * (double)this.VideoPlayer.FrameRate)); var left = (double)Math.Abs(distance + num4 - offset); var right = (double)Math.Abs(this.CameraDistanceError); if (left <= right) return; var videoFrameAtDistance2 = this.VideoSyncSource.GetVideoFrameAtDistance(routeDistance + num4); var num5 = this.VideoSyncSource.AverageVideoSpeed(videoFrameAtDistance1, videoFrameAtDistance2); var ratio = ((double)num5 != 0.0 ? speed / num5 : 0.0f); var deltaRatio = (float)(((double)frame - ((double)this.VideoPlayer.CurrentFrame - (double)this.VideoFrameOffset)) / 2.0) / this.VideoPlayer.FrameRate; var playbackSpeed = Mathf.Clamp(ratio + deltaRatio, 0.0f, 1.5f); //Debug.Log(playbackSpeed); if ((double)playbackSpeed == (double)this.VideoPlayer.PlaybackSpeed || !this.VideoPlayer.SetPlaybackSpeed(playbackSpeed)) return; this.lastPlaybackSpeedChange = DateTime.UtcNow; } } } } }