From 2ea62619d20651be27bd1f3eec412c387d47daa3 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Thu, 30 May 2024 10:36:18 -0500 Subject: [PATCH 01/10] Target net8.0 in FNA.Core.csproj --- FNA.Core.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FNA.Core.csproj b/FNA.Core.csproj index e694f4134..4f7e1e0f3 100644 --- a/FNA.Core.csproj +++ b/FNA.Core.csproj @@ -1,6 +1,6 @@ - net7.0 + net8.0 false From da67fe2811dea22d8569e7716bd31425a3b4aa20 Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Sat, 1 Jun 2024 11:11:14 -0400 Subject: [PATCH 02/10] SDL2# update --- lib/SDL2-CS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/SDL2-CS b/lib/SDL2-CS index 1ef072adb..b1c4fdfd1 160000 --- a/lib/SDL2-CS +++ b/lib/SDL2-CS @@ -1 +1 @@ -Subproject commit 1ef072adb1653d3e79fa99586ebcb1797a54caca +Subproject commit b1c4fdfd10ac3e70c8b3d917029f247fda80855b From 0ca4078a64b270a9589d575a96bcd4937b5b8257 Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Sat, 1 Jun 2024 11:11:40 -0400 Subject: [PATCH 03/10] FAudio/FNA3D 24.06 --- lib/FAudio | 2 +- lib/FNA3D | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/FAudio b/lib/FAudio index 97707e9e7..8a05b08ad 160000 --- a/lib/FAudio +++ b/lib/FAudio @@ -1 +1 @@ -Subproject commit 97707e9e7ba895a53c31e96c82c06caaf763b31f +Subproject commit 8a05b08ad18e746b4258ad8ae87d2e2bd5eebd53 diff --git a/lib/FNA3D b/lib/FNA3D index ee3b0af95..7fe7e1465 160000 --- a/lib/FNA3D +++ b/lib/FNA3D @@ -1 +1 @@ -Subproject commit ee3b0af95e21679849a3ce4c977a682521d65706 +Subproject commit 7fe7e1465a81b796ec0d6e6c8a5da13f4e28869c From fc558a4f4d5f31a77ffd069794fad85efaa0affb Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Sat, 1 Jun 2024 11:11:58 -0400 Subject: [PATCH 04/10] 24.06 --- src/Properties/AssemblyInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Properties/AssemblyInfo.cs b/src/Properties/AssemblyInfo.cs index a940ebcf8..fcc0019f3 100644 --- a/src/Properties/AssemblyInfo.cs +++ b/src/Properties/AssemblyInfo.cs @@ -39,4 +39,4 @@ // Build Number // Revision // -[assembly: AssemblyVersion("24.05.0.0")] +[assembly: AssemblyVersion("24.06.0.0")] From e86dbccba022f5889a90f7e6ed197834650530bb Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Sun, 2 Jun 2024 21:12:01 -0400 Subject: [PATCH 05/10] Delay loading Video files as much as possible, to match XNA behavior --- src/Media/Xiph/Video.cs | 120 ++++++++----------------- src/Media/Xiph/VideoPlayer.cs | 162 ++++++++++++++++++++++++++++------ 2 files changed, 173 insertions(+), 109 deletions(-) diff --git a/src/Media/Xiph/Video.cs b/src/Media/Xiph/Video.cs index 49bf36bdc..2dfa641f9 100644 --- a/src/Media/Xiph/Video.cs +++ b/src/Media/Xiph/Video.cs @@ -22,26 +22,20 @@ public sealed class Video public int Width { - get - { - return yWidth; - } + get; + internal set; } public int Height { - get - { - return yHeight; - } + get; + internal set; } public float FramesPerSecond { - get - { - return (float) fps; - } + get; + internal set; } public VideoSoundtrackType VideoSoundtrackType @@ -69,14 +63,9 @@ internal GraphicsDevice GraphicsDevice #endregion - #region Internal Variables: Theorafile + #region Internal Variables - internal IntPtr theora; - internal int yWidth; - internal int yHeight; - internal int uvWidth; - internal int uvHeight; - internal double fps; + internal string handle; internal bool needsDurationHack; #endregion @@ -85,38 +74,20 @@ internal GraphicsDevice GraphicsDevice internal Video(string fileName, GraphicsDevice device) { + handle = fileName; GraphicsDevice = device; - Theorafile.th_pixel_fmt fmt; + /* This is the raw file constructor; unlike the XNB + * constructor we can be up front about files not + * existing, so let's do that! + */ + IntPtr theora; Theorafile.tf_fopen(fileName, out theora); - Theorafile.tf_videoinfo( - theora, - out yWidth, - out yHeight, - out fps, - out fmt - ); - if (fmt == Theorafile.th_pixel_fmt.TH_PF_420) - { - uvWidth = yWidth / 2; - uvHeight = yHeight / 2; - } - else if (fmt == Theorafile.th_pixel_fmt.TH_PF_422) + if (theora == IntPtr.Zero) { - uvWidth = yWidth / 2; - uvHeight = yHeight; - } - else if (fmt == Theorafile.th_pixel_fmt.TH_PF_444) - { - uvWidth = yWidth; - uvHeight = yHeight; - } - else - { - throw new NotSupportedException( - "Unrecognized YUV format!" - ); + throw new FileNotFoundException(fileName); } + Theorafile.tf_close(ref theora); // FIXME: This is a part of the Duration hack! Duration = TimeSpan.MaxValue; @@ -131,29 +102,18 @@ internal Video( int height, float framesPerSecond, VideoSoundtrackType soundtrackType - ) : this(fileName, device) { - /* If you got here, you've still got the XNB file! Well done! - * Except if you're running FNA, you're not using the WMV anymore. - * But surely it's the same video, right...? - * Well, consider this a check more than anything. If this bothers - * you, just remove the XNB file and we'll read the OGV straight up. - * -flibit + ) { + handle = fileName; + GraphicsDevice = device; + + /* This is the XNB constructor, which really just loads + * the metadata without actually loading the video. For + * accuracy's sake we have to wait until VideoPlayer + * tries to load this before throwing Exceptions. */ - if (width != Width || height != Height) - { - throw new InvalidOperationException( - "XNB/OGV width/height mismatch!" + - " Width: " + Width.ToString() + - " Height: " + Height.ToString() - ); - } - if (Math.Abs(FramesPerSecond - framesPerSecond) >= 1.0f) - { - throw new InvalidOperationException( - "XNB/OGV framesPerSecond mismatch!" + - " FPS: " + FramesPerSecond.ToString() - ); - } + Width = width; + Height = height; + FramesPerSecond = framesPerSecond; // FIXME: Oh, hey! I wish we had this info in Theora! Duration = TimeSpan.FromMilliseconds(durationMS); @@ -191,31 +151,23 @@ public static Video FromUriEXT(Uri uri, GraphicsDevice graphicsDevice) return new Video(path, graphicsDevice); } + // FIXME: These should be in VideoPlayer instead! + + internal VideoPlayer parent; // FIXME: Remove this when extension is replaced!!! + public void SetAudioTrackEXT(int track) { - if (theora != IntPtr.Zero) + if (parent != null) { - Theorafile.tf_setaudiotrack(theora, track); + parent.SetAudioTrackEXT(track); } } public void SetVideoTrackEXT(int track) { - if (theora != IntPtr.Zero) - { - Theorafile.tf_setvideotrack(theora, track); - } - } - - #endregion - - #region Destructor - - ~Video() - { - if (theora != IntPtr.Zero) + if (parent != null) { - Theorafile.tf_close(ref theora); + parent.SetVideoTrackEXT(track); } } diff --git a/src/Media/Xiph/VideoPlayer.cs b/src/Media/Xiph/VideoPlayer.cs index 3627f52d9..b8101e84d 100644 --- a/src/Media/Xiph/VideoPlayer.cs +++ b/src/Media/Xiph/VideoPlayer.cs @@ -401,6 +401,13 @@ public float Volume #region Private Member Data: Theorafile + private IntPtr theora; + private int yWidth; + private int yHeight; + private int uvWidth; + private int uvHeight; + private double fps; + private IntPtr yuvData; private int yuvDataLen; private int currentFrame; @@ -503,6 +510,11 @@ public void Dispose() yuvData = IntPtr.Zero; } + if (theora != IntPtr.Zero) + { + Theorafile.tf_close(ref theora); + } + // Okay, we out. IsDisposed = true; } @@ -518,19 +530,19 @@ public Texture2D GetTexture() // Be sure we can even get something from Theorafile... if ( State == MediaState.Stopped || - Video.theora == IntPtr.Zero || - Theorafile.tf_hasvideo(Video.theora) == 0 ) + theora == IntPtr.Zero || + Theorafile.tf_hasvideo(theora) == 0 ) { // Screw it, give them the old one. return videoTexture[0].RenderTarget as Texture2D; } - int thisFrame = (int) (timer.Elapsed.TotalMilliseconds / (1000.0 / Video.fps)); + int thisFrame = (int) (timer.Elapsed.TotalMilliseconds / (1000.0 / fps)); if (thisFrame > currentFrame) { // Only update the textures if we need to! if (Theorafile.tf_readvideo( - Video.theora, + theora, yuvData, thisFrame - currentFrame ) == 1 || currentFrame == -1) { @@ -540,7 +552,7 @@ public Texture2D GetTexture() } // Check for the end... - bool ended = Theorafile.tf_eos(Video.theora) == 1; + bool ended = Theorafile.tf_eos(theora) == 1; if (audioStream != null) { ended &= audioStream.PendingBufferCount == 0; @@ -566,7 +578,7 @@ public Texture2D GetTexture() } // Reset the stream no matter what happens next - Theorafile.tf_reset(Video.theora); + Theorafile.tf_reset(theora); // If looping, go back to the start. Otherwise, we'll be exiting. if (IsLooped) @@ -598,6 +610,14 @@ public void Play(Video video) // We need to assign this regardless of what happens next. Video = video; + Video.parent = this; // FIXME: Remove this when extension is replaced!!! + + // Again, no matter what happens this should be cleared! + if (theora != IntPtr.Zero) + { + Theorafile.tf_close(ref theora); + theora = IntPtr.Zero; + } // FIXME: This is a part of the Duration hack! if (Video.needsDurationHack) @@ -605,6 +625,75 @@ public void Play(Video video) Video.Duration = TimeSpan.MaxValue; } + Theorafile.th_pixel_fmt fmt; + Theorafile.tf_fopen(Video.handle, out theora); + if (theora == IntPtr.Zero) + { + throw new System.IO.FileNotFoundException(Video.handle); + } + Theorafile.tf_videoinfo( + theora, + out yWidth, + out yHeight, + out fps, + out fmt + ); + if (fmt == Theorafile.th_pixel_fmt.TH_PF_420) + { + uvWidth = yWidth / 2; + uvHeight = yHeight / 2; + } + else if (fmt == Theorafile.th_pixel_fmt.TH_PF_422) + { + uvWidth = yWidth / 2; + uvHeight = yHeight; + } + else if (fmt == Theorafile.th_pixel_fmt.TH_PF_444) + { + uvWidth = yWidth; + uvHeight = yHeight; + } + else + { + throw new NotSupportedException( + "Unrecognized YUV format!" + ); + } + + // Sanity checks for video metadata + if (Video.Width > 0 && Video.Height > 0) + { + if (Video.Width != yWidth || Video.Height != yHeight) + { + throw new InvalidOperationException( + "XNB/OGV width/height mismatch!" + + " Width: " + Video.Width.ToString() + + " Height: " + Video.Height.ToString() + ); + } + } + else + { + // Probably the raw path, fill it in + Video.Width = yWidth; + Video.Height = yHeight; + } + if (Video.FramesPerSecond > 0) + { + if (Math.Abs(Video.FramesPerSecond - fps) >= 1.0f) + { + throw new InvalidOperationException( + "XNB/OGV framesPerSecond mismatch!" + + " FPS: " + Video.FramesPerSecond.ToString() + ); + } + } + else + { + // Probably the raw path, fill it in + Video.FramesPerSecond = (float) fps; + } + // Check the player state before attempting anything. if (State != MediaState.Stopped) { @@ -620,8 +709,8 @@ public void Play(Video video) FNAPlatform.Free(yuvData); } yuvDataLen = ( - (Video.yWidth * Video.yHeight) + - (Video.uvWidth * Video.uvHeight * 2) + (yWidth * yHeight) + + (uvWidth * uvHeight * 2) ); yuvData = FNAPlatform.Malloc(yuvDataLen); @@ -629,7 +718,7 @@ public void Play(Video video) InitializeTheoraStream(); // Set up the texture data - if (Theorafile.tf_hasvideo(Video.theora) == 1) + if (Theorafile.tf_hasvideo(theora) == 1) { // The VideoPlayer will use the GraphicsDevice that is set now. if (currentDevice != Video.GraphicsDevice) @@ -643,8 +732,8 @@ public void Play(Video video) videoTexture[0] = new RenderTargetBinding( new RenderTarget2D( currentDevice, - Video.yWidth, - Video.yHeight, + yWidth, + yHeight, false, SurfaceFormat.Color, DepthFormat.None, @@ -657,10 +746,10 @@ public void Play(Video video) overlap.RenderTarget.Dispose(); } GL_setupTextures( - Video.yWidth, - Video.yHeight, - Video.uvWidth, - Video.uvHeight + yWidth, + yHeight, + uvWidth, + uvHeight ); } @@ -694,7 +783,7 @@ public void Stop() audioStream.Dispose(); audioStream = null; } - Theorafile.tf_reset(Video.theora); + Theorafile.tf_reset(theora); } public void Pause() @@ -741,12 +830,35 @@ public void Resume() #endregion + #region Internal Extensions + + // FIXME: These should replace the Video extensions! + // FIXME: Maybe store these to carry over to future videos? + + internal void SetAudioTrackEXT(int track) + { + if (theora != IntPtr.Zero) + { + Theorafile.tf_setaudiotrack(theora, track); + } + } + + internal void SetVideoTrackEXT(int track) + { + if (theora != IntPtr.Zero) + { + Theorafile.tf_setvideotrack(theora, track); + } + } + + #endregion + #region Private Theora Audio Stream Methods private void OnBufferRequest(object sender, EventArgs args) { int samples = Theorafile.tf_readaudio( - Video.theora, + theora, audioDataPtr, AUDIO_BUFFER_SIZE ); @@ -758,7 +870,7 @@ private void OnBufferRequest(object sender, EventArgs args) samples ); } - else if (Theorafile.tf_eos(Video.theora) == 1) + else if (Theorafile.tf_eos(theora) == 1) { // Okay, we ran out. No need for this! audioStream.BufferNeeded -= OnBufferRequest; @@ -777,10 +889,10 @@ private void UpdateTexture() yuvTextures[0].texture, yuvTextures[1].texture, yuvTextures[2].texture, - Video.yWidth, - Video.yHeight, - Video.uvWidth, - Video.uvHeight, + yWidth, + yHeight, + uvWidth, + uvHeight, yuvData, yuvDataLen ); @@ -802,13 +914,13 @@ private void UpdateTexture() private void InitializeTheoraStream() { // Grab the first video frame ASAP. - while (Theorafile.tf_readvideo(Video.theora, yuvData, 1) == 0); + while (Theorafile.tf_readvideo(theora, yuvData, 1) == 0); // Grab the first bit of audio. We're trying to start the decoding ASAP. - if (Theorafile.tf_hasaudio(Video.theora) == 1) + if (Theorafile.tf_hasaudio(theora) == 1) { int channels, samplerate; - Theorafile.tf_audioinfo(Video.theora, out channels, out samplerate); + Theorafile.tf_audioinfo(theora, out channels, out samplerate); audioStream = new DynamicSoundEffectInstance( samplerate, (AudioChannels) channels From 65f98a8f99a01a3548ed0e01c3782e402cd2176a Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Sun, 2 Jun 2024 21:18:08 -0400 Subject: [PATCH 06/10] Don't throw in SongReader/VideoReader if XNB path doesn't normalize. Thanks to @redmcg for identifying this inaccuracy! --- src/Content/ContentReaders/SongReader.cs | 6 +++--- src/Content/ContentReaders/VideoReader.cs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Content/ContentReaders/SongReader.cs b/src/Content/ContentReaders/SongReader.cs index 501733486..aa7b5617b 100644 --- a/src/Content/ContentReaders/SongReader.cs +++ b/src/Content/ContentReaders/SongReader.cs @@ -39,10 +39,10 @@ protected internal override Song Read(ContentReader input, Song existingInstance /* The path string includes the ".wma" extension. Let's see if this * file exists in a format we actually support... */ - path = Normalize(path.Substring(0, path.Length - 4)); - if (String.IsNullOrEmpty(path)) + string realPath = Normalize(path.Substring(0, path.Length - 4)); + if (!String.IsNullOrEmpty(realPath)) { - throw new ContentLoadException(); + path = realPath; } int durationMs = input.ReadInt32(); diff --git a/src/Content/ContentReaders/VideoReader.cs b/src/Content/ContentReaders/VideoReader.cs index 1c1863c53..5d652ce30 100644 --- a/src/Content/ContentReaders/VideoReader.cs +++ b/src/Content/ContentReaders/VideoReader.cs @@ -41,10 +41,10 @@ Video existingInstance /* The path string includes the ".wmv" extension. Let's see if this * file exists in a format we actually support... */ - path = Normalize(path.Substring(0, path.Length - 4)); - if (String.IsNullOrEmpty(path)) + string realPath = Normalize(path.Substring(0, path.Length - 4)); + if (!String.IsNullOrEmpty(realPath)) { - throw new ContentLoadException(); + path = realPath; } int durationMS = input.ReadObject(); From c158e9b753b11462af9222d26be953da5a2e11bf Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Sun, 2 Jun 2024 21:24:57 -0400 Subject: [PATCH 07/10] VideoPlayer: Reduce the storage scope of yuv width/height parse data --- src/Media/Xiph/VideoPlayer.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Media/Xiph/VideoPlayer.cs b/src/Media/Xiph/VideoPlayer.cs index b8101e84d..7a3e56074 100644 --- a/src/Media/Xiph/VideoPlayer.cs +++ b/src/Media/Xiph/VideoPlayer.cs @@ -402,10 +402,6 @@ public float Volume #region Private Member Data: Theorafile private IntPtr theora; - private int yWidth; - private int yHeight; - private int uvWidth; - private int uvHeight; private double fps; private IntPtr yuvData; @@ -626,6 +622,11 @@ public void Play(Video video) } Theorafile.th_pixel_fmt fmt; + int yWidth; + int yHeight; + int uvWidth; + int uvHeight; + Theorafile.tf_fopen(Video.handle, out theora); if (theora == IntPtr.Zero) { @@ -889,10 +890,10 @@ private void UpdateTexture() yuvTextures[0].texture, yuvTextures[1].texture, yuvTextures[2].texture, - yWidth, - yHeight, - uvWidth, - uvHeight, + yuvTextures[0].Width, + yuvTextures[0].Height, + yuvTextures[1].Width, + yuvTextures[1].Height, yuvData, yuvDataLen ); From 5ba3d8bcb9ec3481bd01296b96be95ac1c62baf4 Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Sun, 2 Jun 2024 23:17:46 -0400 Subject: [PATCH 08/10] Fix Video track settings before a VideoPlayer opens the file --- src/Media/Xiph/Video.cs | 6 +++++- src/Media/Xiph/VideoPlayer.cs | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Media/Xiph/Video.cs b/src/Media/Xiph/Video.cs index 2dfa641f9..8e3a9a4a5 100644 --- a/src/Media/Xiph/Video.cs +++ b/src/Media/Xiph/Video.cs @@ -153,10 +153,13 @@ public static Video FromUriEXT(Uri uri, GraphicsDevice graphicsDevice) // FIXME: These should be in VideoPlayer instead! - internal VideoPlayer parent; // FIXME: Remove this when extension is replaced!!! + internal int audioTrack = -1; + internal int videoTrack = -1; + internal VideoPlayer parent; public void SetAudioTrackEXT(int track) { + audioTrack = track; if (parent != null) { parent.SetAudioTrackEXT(track); @@ -165,6 +168,7 @@ public void SetAudioTrackEXT(int track) public void SetVideoTrackEXT(int track) { + videoTrack = track; if (parent != null) { parent.SetVideoTrackEXT(track); diff --git a/src/Media/Xiph/VideoPlayer.cs b/src/Media/Xiph/VideoPlayer.cs index 7a3e56074..1813c5e99 100644 --- a/src/Media/Xiph/VideoPlayer.cs +++ b/src/Media/Xiph/VideoPlayer.cs @@ -695,6 +695,16 @@ out fmt Video.FramesPerSecond = (float) fps; } + // Per-video track settings should always take priority + if (Video.audioTrack >= 0) + { + SetAudioTrackEXT(Video.audioTrack); + } + if (Video.videoTrack >= 0) + { + SetVideoTrackEXT(Video.videoTrack); + } + // Check the player state before attempting anything. if (State != MediaState.Stopped) { From 6f23d9a7bf3db5f9c3e902640edff36a5d6fd884 Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Sun, 2 Jun 2024 23:29:35 -0400 Subject: [PATCH 09/10] Raw Video metadata can be queried at construction time --- src/Media/Xiph/Video.cs | 20 +++++++++++++++--- src/Media/Xiph/VideoPlayer.cs | 39 ++++++++++------------------------- 2 files changed, 28 insertions(+), 31 deletions(-) diff --git a/src/Media/Xiph/Video.cs b/src/Media/Xiph/Video.cs index 8e3a9a4a5..773177cf2 100644 --- a/src/Media/Xiph/Video.cs +++ b/src/Media/Xiph/Video.cs @@ -23,19 +23,19 @@ public sealed class Video public int Width { get; - internal set; + private set; } public int Height { get; - internal set; + private set; } public float FramesPerSecond { get; - internal set; + private set; } public VideoSoundtrackType VideoSoundtrackType @@ -87,6 +87,20 @@ internal Video(string fileName, GraphicsDevice device) { throw new FileNotFoundException(fileName); } + int width; + int height; + double fps; + Theorafile.th_pixel_fmt fmt; + Theorafile.tf_videoinfo( + theora, + out width, + out height, + out fps, + out fmt + ); + Width = width; + Height = height; + FramesPerSecond = (float) fps; Theorafile.tf_close(ref theora); // FIXME: This is a part of the Duration hack! diff --git a/src/Media/Xiph/VideoPlayer.cs b/src/Media/Xiph/VideoPlayer.cs index 1813c5e99..5b36a6975 100644 --- a/src/Media/Xiph/VideoPlayer.cs +++ b/src/Media/Xiph/VideoPlayer.cs @@ -662,37 +662,20 @@ out fmt } // Sanity checks for video metadata - if (Video.Width > 0 && Video.Height > 0) + if (Video.Width != yWidth || Video.Height != yHeight) { - if (Video.Width != yWidth || Video.Height != yHeight) - { - throw new InvalidOperationException( - "XNB/OGV width/height mismatch!" + - " Width: " + Video.Width.ToString() + - " Height: " + Video.Height.ToString() - ); - } - } - else - { - // Probably the raw path, fill it in - Video.Width = yWidth; - Video.Height = yHeight; - } - if (Video.FramesPerSecond > 0) - { - if (Math.Abs(Video.FramesPerSecond - fps) >= 1.0f) - { - throw new InvalidOperationException( - "XNB/OGV framesPerSecond mismatch!" + - " FPS: " + Video.FramesPerSecond.ToString() - ); - } + throw new InvalidOperationException( + "XNB/OGV width/height mismatch!" + + " Width: " + Video.Width.ToString() + + " Height: " + Video.Height.ToString() + ); } - else + if (Math.Abs(Video.FramesPerSecond - fps) >= 1.0f) { - // Probably the raw path, fill it in - Video.FramesPerSecond = (float) fps; + throw new InvalidOperationException( + "XNB/OGV framesPerSecond mismatch!" + + " FPS: " + Video.FramesPerSecond.ToString() + ); } // Per-video track settings should always take priority From a72fe7b24a965d9b65bae07990b90cf4b945c87f Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Sun, 2 Jun 2024 23:33:09 -0400 Subject: [PATCH 10/10] Consolidate Video's use of Theorafile API --- src/Media/Xiph/Video.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Media/Xiph/Video.cs b/src/Media/Xiph/Video.cs index 773177cf2..60e6f87e4 100644 --- a/src/Media/Xiph/Video.cs +++ b/src/Media/Xiph/Video.cs @@ -81,16 +81,17 @@ internal Video(string fileName, GraphicsDevice device) * constructor we can be up front about files not * existing, so let's do that! */ - IntPtr theora; - Theorafile.tf_fopen(fileName, out theora); - if (theora == IntPtr.Zero) + if (!File.Exists(fileName)) { throw new FileNotFoundException(fileName); } + + IntPtr theora; int width; int height; double fps; Theorafile.th_pixel_fmt fmt; + Theorafile.tf_fopen(fileName, out theora); Theorafile.tf_videoinfo( theora, out width, @@ -98,10 +99,11 @@ internal Video(string fileName, GraphicsDevice device) out fps, out fmt ); + Theorafile.tf_close(ref theora); + Width = width; Height = height; FramesPerSecond = (float) fps; - Theorafile.tf_close(ref theora); // FIXME: This is a part of the Duration hack! Duration = TimeSpan.MaxValue;