public void SetVideoTrackEXT(int track) { if (theora != IntPtr.Zero) { Theorafile.tf_setvideotrack(theora, track); } }
private void InitializeTheoraStream() { // Grab the first video frame ASAP. while (Theorafile.tf_readvideo(Video.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) { int channels, samplerate; Theorafile.tf_audioinfo(Video.theora, out channels, out samplerate); audioStream = new DynamicSoundEffectInstance( samplerate, (AudioChannels)channels ); audioStream.BufferNeeded += OnBufferRequest; UpdateVolume(); // Fill and queue the buffers. for (int i = 0; i < 4; i += 1) { OnBufferRequest(audioStream, EventArgs.Empty); if (audioStream.PendingBufferCount == i) { break; } } } currentFrame = -1; }
public void SetAudioTrackEXT(int track) { if (theora != IntPtr.Zero) { Theorafile.tf_setaudiotrack(theora, track); } }
internal Video(string fileName, GraphicsDevice device) { GraphicsDevice = device; Theorafile.tf_fopen(fileName, out theora); int width, height; double fps; Theorafile.tf_videoinfo(theora, out width, out height, out fps); Width = width; Height = height; FramesPerSecond = (float)fps; // FIXME: This is a part of the Duration hack! Duration = TimeSpan.MaxValue; needsDurationHack = true; }
internal Video(string fileName, GraphicsDevice device) { GraphicsDevice = device; Theorafile.tf_fopen(fileName, out theora); Theorafile.tf_videoinfo( theora, out yWidth, out yHeight, out fps ); uvWidth = yWidth / 2; uvHeight = yHeight / 2; // FIXME: This is a part of the Duration hack! Duration = TimeSpan.MaxValue; needsDurationHack = true; }
private void OnBufferRequest(object sender, EventArgs args) { int samples = Theorafile.tf_readaudio( Video.theora, audioDataPtr, AUDIO_BUFFER_SIZE ); if (samples > 0) { audioStream.SubmitFloatBufferEXT( audioData, 0, samples ); } else if (Theorafile.tf_eos(Video.theora) == 1) { // Okay, we ran out. No need for this! audioStream.BufferNeeded -= OnBufferRequest; } }
internal Video(string fileName, GraphicsDevice device) { GraphicsDevice = device; Theorafile.th_pixel_fmt fmt; 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) { 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!" ); } // FIXME: This is a part of the Duration hack! Duration = TimeSpan.MaxValue; needsDurationHack = true; }
public void Stop() { checkDisposed(); // Check the player state before attempting anything. if (State == MediaState.Stopped) { return; } // Update the player state. State = MediaState.Stopped; // Wait for the player to end if it's still going. timer.Stop(); timer.Reset(); if (audioStream != null) { audioStream.Stop(); audioStream.Dispose(); audioStream = null; } Theorafile.tf_reset(Video.theora); }
public void Play(Video video) { checkDisposed(); // We need to assign this regardless of what happens next. Video = video; // FIXME: This is a part of the Duration hack! if (Video.needsDurationHack) { Video.Duration = TimeSpan.MaxValue; } // Check the player state before attempting anything. if (State != MediaState.Stopped) { return; } // Update the player state now, before initializing State = MediaState.Playing; // Carve out YUV buffer before doing any decoder work if (yuvData != IntPtr.Zero) { Marshal.FreeHGlobal(yuvData); } yuvData = Marshal.AllocHGlobal( (Video.yWidth * Video.yHeight) + (Video.uvWidth * Video.uvHeight * 2) ); // Hook up the decoder to this player InitializeTheoraStream(); // Set up the texture data if (Theorafile.tf_hasvideo(Video.theora) == 1) { // The VideoPlayer will use the GraphicsDevice that is set now. if (currentDevice != Video.GraphicsDevice) { GL_dispose(); currentDevice = Video.GraphicsDevice; GL_initialize(); } RenderTargetBinding overlap = videoTexture[0]; videoTexture[0] = new RenderTargetBinding( new RenderTarget2D( currentDevice, Video.yWidth, Video.yHeight, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents ) ); if (overlap.RenderTarget != null) { overlap.RenderTarget.Dispose(); } GL_setupTextures( Video.yWidth, Video.yHeight, Video.uvWidth, Video.uvHeight ); } // The player can finally start now! timer.Start(); if (audioStream != null) { audioStream.Play(); } }
public Texture2D GetTexture() { checkDisposed(); if (Video == null) { throw new InvalidOperationException(); } // Be sure we can even get something from Theorafile... if (State == MediaState.Stopped || Video.theora == IntPtr.Zero || Theorafile.tf_hasvideo(Video.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)); if (thisFrame > currentFrame) { // Only update the textures if we need to! if (Theorafile.tf_readvideo( Video.theora, yuvData, thisFrame - currentFrame ) == 1 || currentFrame == -1) { UpdateTexture(); } currentFrame = thisFrame; } // Check for the end... bool ended = Theorafile.tf_eos(Video.theora) == 1; if (audioStream != null) { ended &= audioStream.PendingBufferCount == 0; } if (ended) { // FIXME: This is part of the Duration hack! if (Video.needsDurationHack) { Video.Duration = timer.Elapsed; // FIXME: Frames * FPS? -flibit } // Stop and reset the timer. If we're looping, the loop will start it again. timer.Stop(); timer.Reset(); // Kill whatever audio/video we've got if (audioStream != null) { audioStream.Stop(); audioStream.Dispose(); audioStream = null; } // Reset the stream no matter what happens next Theorafile.tf_reset(Video.theora); // If looping, go back to the start. Otherwise, we'll be exiting. if (IsLooped) { // Starting over! InitializeTheoraStream(); // Start! Again! timer.Start(); if (audioStream != null) { audioStream.Play(); } } else { // We out State = MediaState.Stopped; } } // Finally. return(videoTexture[0].RenderTarget as Texture2D); }