A game framework written with osu! in mind.
at master 208 lines 7.2 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using NUnit.Framework; 5using osu.Framework.Allocation; 6using osu.Framework.Extensions.Color4Extensions; 7using osu.Framework.Graphics; 8using osu.Framework.Graphics.Containers; 9using osu.Framework.Graphics.Video; 10using osu.Framework.Testing; 11using osu.Framework.Timing; 12 13namespace osu.Framework.Tests.Visual.Sprites 14{ 15 public class TestSceneVideo : FrameworkTestScene 16 { 17 private Container videoContainer; 18 private TextFlowContainer timeText; 19 20 private ManualClock clock; 21 22 private TestVideo video; 23 24 private bool didDecode; 25 26 [BackgroundDependencyLoader] 27 private void load() 28 { 29 Children = new Drawable[] 30 { 31 videoContainer = new Container 32 { 33 RelativeSizeAxes = Axes.Both, 34 Clock = new FramedClock(clock = new ManualClock()), 35 }, 36 timeText = new TextFlowContainer(f => f.Font = FrameworkFont.Condensed) 37 { 38 RelativeSizeAxes = Axes.Both, 39 Text = "Video is loading...", 40 } 41 }; 42 } 43 44 [SetUpSteps] 45 public void SetUpSteps() 46 { 47 AddStep("Reset clock", () => 48 { 49 clock.CurrentTime = 0; 50 didDecode = false; 51 }); 52 loadNewVideo(); 53 AddUntilStep("Wait for video to load", () => video.IsLoaded); 54 AddStep("Reset clock", () => clock.CurrentTime = 0); 55 } 56 57 private void loadNewVideo() 58 { 59 AddStep("load video", () => 60 { 61 videoContainer.Child = video = new TestVideo 62 { 63 Loop = false, 64 }; 65 }); 66 } 67 68 [Test] 69 public void TestStartFromCurrentTime() 70 { 71 AddAssert("Video is near start", () => video.PlaybackPosition < 1000); 72 73 AddWaitStep("Wait some", 20); 74 75 loadNewVideo(); 76 77 AddAssert("Video is near start", () => video.PlaybackPosition < 1000); 78 } 79 80 [Test] 81 public void TestDecodingStopsWhenNotPresent() 82 { 83 AddStep("make video hidden", () => video.Hide()); 84 85 AddWaitStep("wait a bit", 10); 86 87 AddUntilStep("decoding stopped", () => video.State == VideoDecoder.DecoderState.Ready); 88 89 AddStep("reset decode state", () => didDecode = false); 90 91 AddWaitStep("wait a bit", 10); 92 AddAssert("decoding didn't run", () => !didDecode); 93 94 AddStep("make video visible", () => video.Show()); 95 AddUntilStep("decoding ran", () => didDecode); 96 } 97 98 [TestCase(false)] 99 [TestCase(true)] 100 public void TestDecodingStopsBeforeStartTime(bool looping) 101 { 102 AddStep("Set looping", () => video.Loop = looping); 103 104 AddStep("Jump back to before start time", () => clock.CurrentTime = -30000); 105 106 AddUntilStep("decoding stopped", () => video.State == VideoDecoder.DecoderState.Ready); 107 108 AddStep("reset decode state", () => didDecode = false); 109 110 AddWaitStep("wait a bit", 10); 111 AddAssert("decoding didn't run", () => !didDecode); 112 113 AddStep("seek close to start", () => clock.CurrentTime = -500); 114 AddUntilStep("decoding ran", () => didDecode); 115 } 116 117 [Test] 118 public void TestJumpForward() 119 { 120 AddStep("Jump ahead by 10 seconds", () => clock.CurrentTime += 10000); 121 AddUntilStep("Video seeked", () => video.PlaybackPosition >= 10000); 122 } 123 124 [Test] 125 public void TestJumpBack() 126 { 127 AddStep("Jump ahead by 30 seconds", () => clock.CurrentTime += 30000); 128 AddUntilStep("Video seeked", () => video.PlaybackPosition >= 30000); 129 AddStep("Jump back by 10 seconds", () => clock.CurrentTime -= 10000); 130 AddUntilStep("Video seeked", () => video.PlaybackPosition < 30000); 131 } 132 133 [Test] 134 public void TestJumpBackAfterEndOfPlayback() 135 { 136 AddStep("Jump ahead by 60 seconds", () => clock.CurrentTime += 60000); 137 138 AddUntilStep("Video seeked", () => video.PlaybackPosition >= 30000); 139 AddUntilStep("Reached end", () => video.State == VideoDecoder.DecoderState.EndOfStream); 140 AddStep("reset decode state", () => didDecode = false); 141 142 AddStep("Jump back to valid time", () => clock.CurrentTime = 20000); 143 AddUntilStep("decoding ran", () => didDecode); 144 } 145 146 [Test] 147 public void TestVideoDoesNotLoopIfDisabled() 148 { 149 AddStep("Seek to end", () => clock.CurrentTime = video.Duration); 150 AddUntilStep("Video seeked", () => video.PlaybackPosition >= video.Duration - 1000); 151 AddWaitStep("Wait for playback", 10); 152 AddAssert("Not looped", () => video.PlaybackPosition >= video.Duration - 1000); 153 } 154 155 [Test] 156 public void TestVideoLoopsIfEnabled() 157 { 158 AddStep("Set looping", () => video.Loop = true); 159 AddStep("Seek to end", () => clock.CurrentTime = video.Duration); 160 AddWaitStep("Wait for playback", 10); 161 AddUntilStep("Looped", () => video.PlaybackPosition < video.Duration - 1000); 162 } 163 164 [Test] 165 public void TestShader() 166 { 167 AddStep("Set colour", () => video.Colour = Color4Extensions.FromHex("#ea7948").Opacity(0.75f)); 168 AddStep("Use normal shader", () => video.UseRoundedShader = false); 169 AddStep("Use rounded shader", () => video.UseRoundedShader = true); 170 } 171 172 private int currentSecond; 173 private int fps; 174 private int lastFramesProcessed; 175 176 protected override void Update() 177 { 178 base.Update(); 179 180 if (clock != null) 181 clock.CurrentTime += Clock.ElapsedFrameTime; 182 183 if (video != null) 184 { 185 var newSecond = (int)(video.PlaybackPosition / 1000.0); 186 187 if (newSecond != currentSecond) 188 { 189 currentSecond = newSecond; 190 fps = video.FramesProcessed - lastFramesProcessed; 191 lastFramesProcessed = video.FramesProcessed; 192 } 193 194 if (timeText != null) 195 { 196 timeText.Text = $"aim time: {video.PlaybackPosition:N2}\n" 197 + $"video time: {video.CurrentFrameTime:N2}\n" 198 + $"duration: {video.Duration:N2}\n" 199 + $"buffered {video.AvailableFrames}\n" 200 + $"FPS: {fps}\n" 201 + $"State: {video.State}"; 202 } 203 204 didDecode |= video.State == VideoDecoder.DecoderState.Running; 205 } 206 } 207 } 208}