diff --git a/OpenRA.Mods.Common/Widgets/VideoPlayerWidget.cs b/OpenRA.Mods.Common/Widgets/VideoPlayerWidget.cs index 3deae2681a..dae1f05990 100644 --- a/OpenRA.Mods.Common/Widgets/VideoPlayerWidget.cs +++ b/OpenRA.Mods.Common/Widgets/VideoPlayerWidget.cs @@ -10,6 +10,7 @@ #endregion using System; +using System.Diagnostics; using System.IO; using System.Threading.Tasks; using OpenRA.Graphics; @@ -26,7 +27,7 @@ namespace OpenRA.Mods.Common.Widgets public bool DrawOverlay = true; public bool Skippable = true; - public bool Paused { get; private set; } + public bool Paused => !playTime.IsRunning; public IVideo Video { get; private set; } = null; Sprite videoSprite, overlaySprite; @@ -36,7 +37,7 @@ namespace OpenRA.Mods.Common.Widgets float2 videoOrigin, videoSize; float2 overlayOrigin, overlaySize; float overlayScale; - bool stopped; + readonly Stopwatch playTime = new(); int textureWidth; int textureHeight; @@ -69,7 +70,7 @@ namespace OpenRA.Mods.Common.Widgets cachedVideoFileName = filename; - if (!stopped) + if (Video != null) CloseVideo(); Task.Run(() => @@ -114,8 +115,7 @@ namespace OpenRA.Mods.Common.Widgets if (video == null) return; - stopped = true; - Paused = true; + playTime.Reset(); Game.Sound.StopVideo(); onComplete = () => { }; @@ -150,13 +150,13 @@ namespace OpenRA.Mods.Common.Widgets if (Video == null) return; - if (!stopped && !Paused) + if (!Paused) { int nextFrame; if (Video.HasAudio && !Game.Sound.DummyEngine) nextFrame = (int)float2.Lerp(0, Video.FrameCount, Game.Sound.VideoSeekPosition * invLength); else - nextFrame = Video.CurrentFrameIndex + 1; + nextFrame = (int)float2.Lerp(0, Video.FrameCount, (float)playTime.Elapsed.TotalSeconds * invLength); // Without the 2nd check the sound playback sometimes ends before the final frame is displayed which causes the player to be stuck on the first frame if (nextFrame > Video.FrameCount || nextFrame < Video.CurrentFrameIndex) @@ -169,10 +169,12 @@ namespace OpenRA.Mods.Common.Widgets while (nextFrame > Video.CurrentFrameIndex) { Video.AdvanceFrame(); - videoSprite.Sheet.GetTexture().SetData(Video.CurrentFrameData, textureWidth, textureHeight); skippedFrames++; } + if (skippedFrames > 0) + videoSprite.Sheet.GetTexture().SetData(Video.CurrentFrameData, textureWidth, textureHeight); + if (skippedFrames > 1) Log.Write("perf", $"{nameof(VideoPlayerWidget)}: {cachedVideoFileName} skipped {skippedFrames} frames at position {Video.CurrentFrameIndex}"); } @@ -258,30 +260,29 @@ namespace OpenRA.Mods.Common.Widgets return; onComplete = after; - if (stopped && Video.HasAudio) + if (playTime.ElapsedTicks == 0 && Video.HasAudio) Game.Sound.PlayVideo(Video.AudioData, Video.AudioChannels, Video.SampleBits, Video.SampleRate); else Game.Sound.PlayVideo(); - stopped = Paused = false; + playTime.Start(); } public void Pause() { - if (stopped || Paused || Video == null) + if (Paused || Video == null) return; - Paused = true; + playTime.Stop(); Game.Sound.PauseVideo(); } public void Stop() { - if (stopped || Video == null) + if (Video == null) return; - stopped = true; - Paused = true; + playTime.Reset(); Game.Sound.StopVideo(); Video.Reset(); videoSprite.Sheet.GetTexture().SetData(Video.CurrentFrameData, textureWidth, textureHeight);