Root/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | #region License /* FNA - XNA4 Reimplementation for Desktop Platforms * Copyright 2009-2016 Ethan Lee and the MonoGame Team * * Released under the Microsoft Public License. * See LICENSE for details. */ #endregion #region Using Statements using System; using System.IO; using System.Threading; #endregion namespace Microsoft.Xna.Framework.Media { public sealed class Video { #region Public Properties public int Width { get ; private set ; } public int Height { get ; private set ; } public float FramesPerSecond { get ; internal set ; } public VideoSoundtrackType VideoSoundtrackType { get ; private set ; } // FIXME: This is hacked, look up "This is a part of the Duration hack!" public TimeSpan Duration { get ; internal set ; } #endregion #region Internal Properties internal bool IsDisposed { get ; private set ; } internal bool AttachedToPlayer { get ; set ; } #endregion #region Internal Variables: TheoraPlay internal IntPtr theoraDecoder; internal IntPtr videoStream; #endregion #region Private Variables private string fileName; #endregion #region Internal Constructors internal Video( string fileName) { this .fileName = fileName; // Set everything to NULL. Yes, this actually matters later. theoraDecoder = IntPtr.Zero; videoStream = IntPtr.Zero; // Initialize the decoder nice and early... IsDisposed = true ; AttachedToPlayer = false ; Initialize(); // FIXME: This is a part of the Duration hack! Duration = TimeSpan.MaxValue; } internal Video( string fileName, int durationMS, int width, int height, float framesPerSecond, VideoSoundtrackType soundtrackType ) : this (fileName) { /* 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 */ if (width != Width || height != Height) { throw new InvalidOperationException( "XNB/OGV width/height mismatch!" ); } if (Math.Abs(FramesPerSecond - framesPerSecond) >= 1.0f) { throw new InvalidOperationException( "XNB/OGV framesPerSecond mismatch!" ); } // FIXME: Oh, hey! I wish we had this info in TheoraPlay! Duration = TimeSpan.FromMilliseconds(durationMS); VideoSoundtrackType = soundtrackType; } #endregion #region Internal Dispose Method internal void Dispose() { if (AttachedToPlayer) { return ; // NOPE. VideoPlayer will do the honors. } // Stop and unassign the decoder. if (theoraDecoder != IntPtr.Zero) { TheoraPlay.THEORAPLAY_stopDecode(theoraDecoder); theoraDecoder = IntPtr.Zero; } // Free and unassign the video stream. if (videoStream != IntPtr.Zero) { TheoraPlay.THEORAPLAY_freeVideo(videoStream); videoStream = IntPtr.Zero; } IsDisposed = true ; } #endregion #region Internal TheoraPlay Initialization internal void Initialize() { if (!IsDisposed) { Dispose(); // We need to start from the beginning, don't we? :P } // Initialize the decoder. theoraDecoder = TheoraPlay.THEORAPLAY_startDecodeFile( fileName, 150, // Max frames to buffer. Arbitrarily set 5 seconds, assuming 30fps. TheoraPlay.THEORAPLAY_VideoFormat.THEORAPLAY_VIDFMT_IYUV ); // Wait until the decoder is ready. while (TheoraPlay.THEORAPLAY_isInitialized(theoraDecoder) == 0) { Thread.Sleep(10); } // Initialize the video stream pointer and get our first frame. if (TheoraPlay.THEORAPLAY_hasVideoStream(theoraDecoder) != 0) { while (videoStream == IntPtr.Zero) { videoStream = TheoraPlay.THEORAPLAY_getVideo(theoraDecoder); Thread.Sleep(10); } TheoraPlay.THEORAPLAY_VideoFrame frame = TheoraPlay.getVideoFrame(videoStream); // We get the FramesPerSecond from the first frame. FramesPerSecond = ( float ) frame.fps; Width = ( int ) frame.width; Height = ( int ) frame.height; } IsDisposed = false ; } #endregion } } |