public void Terminate()
        {
            // 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;
            }
            _currentVideo = new TheoraPlay.THEORAPLAY_VideoFrame();
            _nextVideo    = new TheoraPlay.THEORAPLAY_VideoFrame();
            TheoraPlay.THEORAPLAY_freeVideo(_previousFrame);
            _previousFrame = IntPtr.Zero;
            _videoStream   = IntPtr.Zero;
            _disposed      = true;
        }
Beispiel #2
0
        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;
        }
Beispiel #3
0
        public void Play(Video video)
        {
            checkDisposed();

            // We need to assign this regardless of what happens next.
            Video = video;
            video.AttachedToPlayer = true;

            // FIXME: This is a part of the Duration hack!
            Video.Duration = TimeSpan.MaxValue;

            // Check the player state before attempting anything.
            if (State != MediaState.Stopped)
            {
                return;
            }

            // Update the player state now, for the thread we're about to make.
            State = MediaState.Playing;

            // Start the video if it hasn't been yet.
            if (Video.IsDisposed)
            {
                video.Initialize();
            }

            // Grab the first bit of audio. We're trying to start the decoding ASAP.
            if (TheoraPlay.THEORAPLAY_hasAudioStream(Video.theoraDecoder) != 0)
            {
                InitAudioStream();
            }

            // Grab the first bit of video, set up the texture.
            if (TheoraPlay.THEORAPLAY_hasVideoStream(Video.theoraDecoder) != 0)
            {
                currentVideo  = TheoraPlay.getVideoFrame(Video.videoStream);
                previousFrame = Video.videoStream;
                do
                {
                    // The decoder miiight not be ready yet.
                    Video.videoStream = TheoraPlay.THEORAPLAY_getVideo(Video.theoraDecoder);
                } while (Video.videoStream == IntPtr.Zero);
                nextVideo = TheoraPlay.getVideoFrame(Video.videoStream);

                Texture2D overlap = videoTexture;
                videoTexture = new Texture2D(
                    currentDevice,
                    (int)currentVideo.width,
                    (int)currentVideo.height,
                    false,
                    SurfaceFormat.Color
                    );
                overlap.Dispose();
#if VIDEOPLAYER_OPENGL
                GL_setupTargets(
                    (int)currentVideo.width,
                    (int)currentVideo.height
                    );
#endif
            }

            // Initialize the thread!
            System.Console.Write("Starting Theora player...");
            timer.Start();
            if (audioStream != null)
            {
                audioStream.Play();
            }
            System.Console.WriteLine(" Done!");
        }
Beispiel #4
0
        public Texture2D GetTexture()
        {
            checkDisposed();

            // Be sure we can even get something from TheoraPlay...
            if (State == MediaState.Stopped ||
                Video.theoraDecoder == IntPtr.Zero ||
                TheoraPlay.THEORAPLAY_isInitialized(Video.theoraDecoder) == 0 ||
                TheoraPlay.THEORAPLAY_hasVideoStream(Video.theoraDecoder) == 0)
            {
                return(videoTexture);                // Screw it, give them the old one.
            }

            // Get the latest video frames.
            bool missedFrame = false;

            while (nextVideo.playms <= timer.ElapsedMilliseconds && !missedFrame)
            {
                currentVideo = nextVideo;
                IntPtr nextFrame = TheoraPlay.THEORAPLAY_getVideo(Video.theoraDecoder);
                if (nextFrame != IntPtr.Zero)
                {
                    TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
                    previousFrame     = Video.videoStream;
                    Video.videoStream = nextFrame;
                    nextVideo         = TheoraPlay.getVideoFrame(Video.videoStream);
                    missedFrame       = false;
                }
                else
                {
                    // Don't mind me, just ignoring that complete failure above!
                    missedFrame = true;
                }

                if (TheoraPlay.THEORAPLAY_isDecoding(Video.theoraDecoder) == 0)
                {
                    // FIXME: This is part of the Duration hack!
                    Video.Duration = new TimeSpan(0, 0, 0, 0, (int)currentVideo.playms);

                    // Stop and reset the timer. If we're looping, the loop will start it again.
                    timer.Stop();
                    timer.Reset();

                    // If looping, go back to the start. Otherwise, we'll be exiting.
                    if (IsLooped && State == MediaState.Playing)
                    {
                        // Kill the audio, no matter what.
                        if (audioStream != null)
                        {
                            audioStream.Stop();
                            audioStream.Dispose();
                            audioStream = null;
                        }

                        // Free everything and start over.
                        TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
                        previousFrame          = IntPtr.Zero;
                        Video.AttachedToPlayer = false;
                        Video.Dispose();
                        Video.AttachedToPlayer = true;
                        Video.Initialize();

                        // Grab the initial audio again.
                        if (TheoraPlay.THEORAPLAY_hasAudioStream(Video.theoraDecoder) != 0)
                        {
                            InitAudioStream();
                        }

                        // Grab the initial video again.
                        if (TheoraPlay.THEORAPLAY_hasVideoStream(Video.theoraDecoder) != 0)
                        {
                            currentVideo  = TheoraPlay.getVideoFrame(Video.videoStream);
                            previousFrame = Video.videoStream;
                            do
                            {
                                // The decoder miiight not be ready yet.
                                Video.videoStream = TheoraPlay.THEORAPLAY_getVideo(Video.theoraDecoder);
                            } while (Video.videoStream == IntPtr.Zero);
                            nextVideo = TheoraPlay.getVideoFrame(Video.videoStream);
                        }

                        // Start! Again!
                        timer.Start();
                        if (audioStream != null)
                        {
                            audioStream.Play();
                        }
                    }
                    else
                    {
                        // Stop everything, clean up. We out.
                        State = MediaState.Stopped;
                        if (audioStream != null)
                        {
                            audioStream.Stop();
                            audioStream.Dispose();
                            audioStream = null;
                        }
                        TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
                        Video.AttachedToPlayer = false;
                        Video.Dispose();

                        // We're done, so give them the last frame.
                        return(videoTexture);
                    }
                }
            }

#if VIDEOPLAYER_OPENGL
            // Set up an environment to muck about in.
            GL_pushState();

            // Bind our shader program.
            currentDevice.GLDevice.glUseProgram(shaderProgram);

            // We're using client-side arrays like CAVEMEN
            currentDevice.GLDevice.BindVertexBuffer(OpenGLDevice.OpenGLVertexBuffer.NullBuffer);

            // Set up the vertex pointers/arrays.
            currentDevice.GLDevice.AttributeEnabled[0] = true;
            currentDevice.GLDevice.AttributeEnabled[1] = true;
            for (int i = 2; i < currentDevice.GLDevice.AttributeEnabled.Length; i += 1)
            {
                currentDevice.GLDevice.AttributeEnabled[i] = false;
            }
            currentDevice.GLDevice.FlushGLVertexAttributes();
            currentDevice.GLDevice.VertexAttribPointer(
                0,
                2,
                VertexElementFormat.Single,
                false,
                2 * sizeof(float),
                vertPosPtr
                );
            currentDevice.GLDevice.VertexAttribPointer(
                1,
                2,
                VertexElementFormat.Single,
                false,
                2 * sizeof(float),
                vertTexPtr
                );

            // Bind our target framebuffer.
            currentDevice.GLDevice.BindDrawFramebuffer(rgbaFramebuffer);

            // Prepare YUV GL textures with our current frame data
            currentDevice.GLDevice.glActiveTexture(
                OpenGLDevice.GLenum.GL_TEXTURE0
                );
            currentDevice.GLDevice.glBindTexture(
                OpenGLDevice.GLenum.GL_TEXTURE_2D,
                yuvTextures[0]
                );
            currentDevice.GLDevice.glTexSubImage2D(
                OpenGLDevice.GLenum.GL_TEXTURE_2D,
                0,
                0,
                0,
                (int)currentVideo.width,
                (int)currentVideo.height,
                OpenGLDevice.GLenum.GL_LUMINANCE,
                OpenGLDevice.GLenum.GL_UNSIGNED_BYTE,
                currentVideo.pixels
                );
            currentDevice.GLDevice.glActiveTexture(
                OpenGLDevice.GLenum.GL_TEXTURE0 + 1
                );
            currentDevice.GLDevice.glBindTexture(
                OpenGLDevice.GLenum.GL_TEXTURE_2D,
                yuvTextures[1]
                );
            currentDevice.GLDevice.glTexSubImage2D(
                OpenGLDevice.GLenum.GL_TEXTURE_2D,
                0,
                0,
                0,
                (int)(currentVideo.width / 2),
                (int)(currentVideo.height / 2),
                OpenGLDevice.GLenum.GL_LUMINANCE,
                OpenGLDevice.GLenum.GL_UNSIGNED_BYTE,
                new IntPtr(
                    currentVideo.pixels.ToInt64() +
                    (currentVideo.width * currentVideo.height)
                    )
                );
            currentDevice.GLDevice.glActiveTexture(
                OpenGLDevice.GLenum.GL_TEXTURE0 + 2
                );
            currentDevice.GLDevice.glBindTexture(
                OpenGLDevice.GLenum.GL_TEXTURE_2D,
                yuvTextures[2]
                );
            currentDevice.GLDevice.glTexSubImage2D(
                OpenGLDevice.GLenum.GL_TEXTURE_2D,
                0,
                0,
                0,
                (int)(currentVideo.width / 2),
                (int)(currentVideo.height / 2),
                OpenGLDevice.GLenum.GL_LUMINANCE,
                OpenGLDevice.GLenum.GL_UNSIGNED_BYTE,
                new IntPtr(
                    currentVideo.pixels.ToInt64() +
                    (currentVideo.width * currentVideo.height) +
                    (currentVideo.width / 2 * currentVideo.height / 2)
                    )
                );

            // Flip the viewport, because loldirectx
            currentDevice.GLDevice.glViewport(
                0,
                0,
                (int)currentVideo.width,
                (int)currentVideo.height
                );

            // Draw the YUV textures to the framebuffer with our shader.
            currentDevice.GLDevice.glDrawArrays(
                OpenGLDevice.GLenum.GL_TRIANGLE_STRIP,
                0,
                4
                );

            // Clean up after ourselves.
            GL_popState();
#else
            // Just copy it to an array, since it's RGBA anyway.
            try
            {
                byte[] theoraPixels = TheoraPlay.getPixels(
                    currentVideo.pixels,
                    (int)currentVideo.width * (int)currentVideo.height * 4
                    );

                // TexImage2D.
                videoTexture.SetData <byte>(theoraPixels);
            }
            catch (Exception e)
            {
                // I hope we've still got something in videoTexture!
                System.Console.WriteLine(
                    "WARNING: THEORA FRAME COPY FAILED: " +
                    e.Message
                    );
            }
#endif

            return(videoTexture);
        }
Beispiel #5
0
        public Texture2D GetTexture()
        {
            checkDisposed();

            if (Video == null)
            {
                throw new InvalidOperationException();
            }

            // Be sure we can even get something from TheoraPlay...
            if (State == MediaState.Stopped ||
                Video.theoraDecoder == IntPtr.Zero ||
                TheoraPlay.THEORAPLAY_isInitialized(Video.theoraDecoder) == 0 ||
                TheoraPlay.THEORAPLAY_hasVideoStream(Video.theoraDecoder) == 0)
            {
                // Screw it, give them the old one.
                return(videoTexture[0].RenderTarget as Texture2D);
            }

            // Get the latest video frames.
            bool hasFrames = true;

            while (nextVideo.playms <= timer.ElapsedMilliseconds && hasFrames)
            {
                currentVideo = nextVideo;
                hasFrames    = TheoraPlay.THEORAPLAY_availableVideo(Video.theoraDecoder) > 0;
                if (hasFrames)
                {
                    IntPtr nextFrame = TheoraPlay.THEORAPLAY_getVideo(Video.theoraDecoder);
                    TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
                    previousFrame     = Video.videoStream;
                    Video.videoStream = nextFrame;
                    nextVideo         = TheoraPlay.getVideoFrame(Video.videoStream);
                }
            }

            // Check for the end...
            if (TheoraPlay.THEORAPLAY_isDecoding(Video.theoraDecoder) == 0)
            {
                // FIXME: This is part of the Duration hack!
                if (Video.needsDurationHack)
                {
                    Video.Duration = new TimeSpan(0, 0, 0, 0, (int)currentVideo.playms);
                }

                // 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;
                }
                TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
                Video.AttachedToPlayer = false;
                Video.Dispose();

                // If looping, go back to the start. Otherwise, we'll be exiting.
                if (IsLooped && State == MediaState.Playing)
                {
                    // Starting over!
                    Video.AttachedToPlayer = true;
                    InitializeTheoraStream();

                    // Start! Again!
                    timer.Start();
                    if (audioStream != null)
                    {
                        audioStream.Play();
                    }
                }
                else
                {
                    // We out, give them the last frame.
                    State = MediaState.Stopped;
                    return(videoTexture[0].RenderTarget as Texture2D);
                }
            }

            // Set up an environment to muck about in.
            GL_pushState();

            // Prepare YUV GL textures with our current frame data
            currentDevice.GLDevice.SetTextureData2DPointer(
                yuvTextures[0],
                currentVideo.pixels
                );
            currentDevice.GLDevice.SetTextureData2DPointer(
                yuvTextures[1],
                new IntPtr(
                    currentVideo.pixels.ToInt64() +
                    (currentVideo.width * currentVideo.height)
                    )
                );
            currentDevice.GLDevice.SetTextureData2DPointer(
                yuvTextures[2],
                new IntPtr(
                    currentVideo.pixels.ToInt64() +
                    (currentVideo.width * currentVideo.height) +
                    (currentVideo.width / 2 * currentVideo.height / 2)
                    )
                );

            // Draw the YUV textures to the framebuffer with our shader.
            currentDevice.DrawPrimitives(
                PrimitiveType.TriangleStrip,
                0,
                2
                );

            // Clean up after ourselves.
            GL_popState();

            // Finally.
            return(videoTexture[0].RenderTarget as Texture2D);
        }
Beispiel #6
0
        public Texture2D GetTexture()
        {
            checkDisposed();

            // Be sure we can even get something from TheoraPlay...
            if (State == MediaState.Stopped ||
                Video.theoraDecoder == IntPtr.Zero ||
                TheoraPlay.THEORAPLAY_isInitialized(Video.theoraDecoder) == 0 ||
                TheoraPlay.THEORAPLAY_hasVideoStream(Video.theoraDecoder) == 0)
            {
                // Screw it, give them the old one.
                return(videoTexture[0].RenderTarget as Texture2D);
            }

            // Get the latest video frames.
            bool missedFrame = false;

            while (nextVideo.playms <= timer.ElapsedMilliseconds && !missedFrame)
            {
                currentVideo = nextVideo;
                IntPtr nextFrame = TheoraPlay.THEORAPLAY_getVideo(Video.theoraDecoder);
                if (nextFrame != IntPtr.Zero)
                {
                    TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
                    previousFrame     = Video.videoStream;
                    Video.videoStream = nextFrame;
                    nextVideo         = TheoraPlay.getVideoFrame(Video.videoStream);
                    missedFrame       = false;
                }
                else
                {
                    // Don't mind me, just ignoring that complete failure above!
                    missedFrame = true;
                }

                if (TheoraPlay.THEORAPLAY_isDecoding(Video.theoraDecoder) == 0)
                {
                    // FIXME: This is part of the Duration hack!
                    Video.Duration = new TimeSpan(0, 0, 0, 0, (int)currentVideo.playms);

                    // Stop and reset the timer. If we're looping, the loop will start it again.
                    timer.Stop();
                    timer.Reset();

                    // If looping, go back to the start. Otherwise, we'll be exiting.
                    if (IsLooped && State == MediaState.Playing)
                    {
                        // Kill the audio, no matter what.
                        if (audioStream != null)
                        {
                            audioStream.Stop();
                            audioStream.Dispose();
                            audioStream = null;
                        }

                        // Free everything and start over.
                        TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
                        previousFrame          = IntPtr.Zero;
                        Video.AttachedToPlayer = false;
                        Video.Dispose();
                        Video.AttachedToPlayer = true;
                        Video.Initialize();

                        // Grab the initial audio again.
                        if (TheoraPlay.THEORAPLAY_hasAudioStream(Video.theoraDecoder) != 0)
                        {
                            InitAudioStream();
                        }

                        // Grab the initial video again.
                        if (TheoraPlay.THEORAPLAY_hasVideoStream(Video.theoraDecoder) != 0)
                        {
                            currentVideo  = TheoraPlay.getVideoFrame(Video.videoStream);
                            previousFrame = Video.videoStream;
                            do
                            {
                                // The decoder miiight not be ready yet.
                                Video.videoStream = TheoraPlay.THEORAPLAY_getVideo(Video.theoraDecoder);
                            } while (Video.videoStream == IntPtr.Zero);
                            nextVideo = TheoraPlay.getVideoFrame(Video.videoStream);
                        }

                        // Start! Again!
                        timer.Start();
                        if (audioStream != null)
                        {
                            audioStream.Play();
                        }
                    }
                    else
                    {
                        // Stop everything, clean up. We out.
                        State = MediaState.Stopped;
                        if (audioStream != null)
                        {
                            audioStream.Stop();
                            audioStream.Dispose();
                            audioStream = null;
                        }
                        TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
                        Video.AttachedToPlayer = false;
                        Video.Dispose();

                        // We're done, so give them the last frame.
                        return(videoTexture[0].RenderTarget as Texture2D);
                    }
                }
            }

            // Set up an environment to muck about in.
            GL_pushState();

            // Prepare YUV GL textures with our current frame data
            currentDevice.GLDevice.SetTextureData2DPointer(
                yuvTextures[0],
                currentVideo.pixels
                );
            currentDevice.GLDevice.SetTextureData2DPointer(
                yuvTextures[1],
                new IntPtr(
                    currentVideo.pixels.ToInt64() +
                    (currentVideo.width * currentVideo.height)
                    )
                );
            currentDevice.GLDevice.SetTextureData2DPointer(
                yuvTextures[2],
                new IntPtr(
                    currentVideo.pixels.ToInt64() +
                    (currentVideo.width * currentVideo.height) +
                    (currentVideo.width / 2 * currentVideo.height / 2)
                    )
                );

            // Draw the YUV textures to the framebuffer with our shader.
            currentDevice.DrawPrimitives(
                PrimitiveType.TriangleStrip,
                0,
                2
                );

            // Clean up after ourselves.
            GL_popState();

            // Finally.
            return(videoTexture[0].RenderTarget as Texture2D);
        }
Beispiel #7
0
        public void Play(Video video)
        {
            checkDisposed();

            // We need to assign this regardless of what happens next.
            Video = video;
            video.AttachedToPlayer = true;

            // FIXME: This is a part of the Duration hack!
            Video.Duration = TimeSpan.MaxValue;

            // Check the player state before attempting anything.
            if (State != MediaState.Stopped)
            {
                return;
            }

            // Update the player state now, for the thread we're about to make.
            State = MediaState.Playing;

            // Start the video if it hasn't been yet.
            if (Video.IsDisposed)
            {
                video.Initialize();
            }

            // Grab the first bit of audio. We're trying to start the decoding ASAP.
            if (TheoraPlay.THEORAPLAY_hasAudioStream(Video.theoraDecoder) != 0)
            {
                InitAudioStream();
            }

            // Grab the first bit of video, set up the texture.
            if (TheoraPlay.THEORAPLAY_hasVideoStream(Video.theoraDecoder) != 0)
            {
                currentVideo  = TheoraPlay.getVideoFrame(Video.videoStream);
                previousFrame = Video.videoStream;
                do
                {
                    // The decoder miiight not be ready yet.
                    Video.videoStream = TheoraPlay.THEORAPLAY_getVideo(Video.theoraDecoder);
                } while (Video.videoStream == IntPtr.Zero);
                nextVideo = TheoraPlay.getVideoFrame(Video.videoStream);

                // 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,
                        (int)currentVideo.width,
                        (int)currentVideo.height,
                        false,
                        SurfaceFormat.Color,
                        DepthFormat.None,
                        0,
                        RenderTargetUsage.PreserveContents
                        )
                    );
                if (overlap.RenderTarget != null)
                {
                    overlap.RenderTarget.Dispose();
                }
                GL_setupTextures(
                    (int)currentVideo.width,
                    (int)currentVideo.height
                    );
            }

            // Initialize the thread!
            FNAPlatform.Log("Starting Theora player...");
            timer.Start();
            if (audioStream != null)
            {
                audioStream.Play();
            }
            FNAPlatform.Log("Started!");
        }
        public void Play(OgvComponent video)
        {
            checkDisposed();

            // We need to assign this regardless of what happens next.
            Video = video;

            // FIXME: This is a part of the Duration hack!
            Video.Duration = TimeSpan.MaxValue;

            // Check the player state before attempting anything.
            if (State != MediaState.Stopped)
            {
                return;
            }

            // In rare cases, the thread might still be going. Wait until it's done.
            if (audioDecoderThread != null && audioDecoderThread.IsAlive)
            {
                Stop();
            }

            // Create new Thread instances in case we use this player multiple times.
            audioDecoderThread = new Thread(new ThreadStart(this.DecodeAudio));

            // Update the player state now, for the thread we're about to make.
            State = MediaState.Playing;

            // Start the video if it hasn't been yet.
            if (Video.IsDisposed)
            {
                video.Initialize();
            }

            // Grab the first bit of audio. We're trying to start the decoding ASAP.
            if (TheoraPlay.THEORAPLAY_hasAudioStream(Video.TheoraDecoder) != 0)
            {
                audioDecoderThread.Start();
            }
            else
            {
                audioStarted = true; // Welp.
            }

            // Grab the first bit of video, set up the texture.
            if (TheoraPlay.THEORAPLAY_hasVideoStream(Video.TheoraDecoder) != 0)
            {
                currentVideo = TheoraPlay.getVideoFrame(Video.VideoStream);
                previousFrame = Video.VideoStream;
                do
                {
                    // The decoder miiight not be ready yet.
                    Video.VideoStream = TheoraPlay.THEORAPLAY_getVideo(Video.TheoraDecoder);
                } while (Video.VideoStream == IntPtr.Zero);
                nextVideo = TheoraPlay.getVideoFrame(Video.VideoStream);

                Texture overlap = videoTexture;
                videoTexture = new Texture(
//                    Game.Instance.GraphicsDevice,
//                    (int)currentVideo.width,
//                    (int)currentVideo.height,
//                    false,
//                    SurfaceFormat.Color
                );
                overlap.Dispose();
#if VIDEOPLAYER_OPENGL
                GL_setupTargets(
                    (int)currentVideo.width,
                    (int)currentVideo.height
                );
#endif
            }

            // Initialize the thread!
            Log.Editor.Write("Starting Theora player...");
            while (!audioStarted) ;
            timer.Start();
            if (audioSourceIndex != -1)
            {
                AL.SourcePlay(audioSourceIndex);
            }
            Log.Editor.Write(" Done starting Theora player!");
        }
Beispiel #9
0
		public void Play(Video video)
		{
			checkDisposed();

			// We need to assign this regardless of what happens next.
			Video = video;
			video.AttachedToPlayer = true;

			// FIXME: This is a part of the Duration hack!
			Video.Duration = TimeSpan.MaxValue;

			// Check the player state before attempting anything.
			if (State != MediaState.Stopped)
			{
				return;
			}

			// Update the player state now, for the thread we're about to make.
			State = MediaState.Playing;

			// Start the video if it hasn't been yet.
			if (Video.IsDisposed)
			{
				video.Initialize();
			}

			// Grab the first bit of audio. We're trying to start the decoding ASAP.
			if (TheoraPlay.THEORAPLAY_hasAudioStream(Video.theoraDecoder) != 0)
			{
				InitAudioStream();
			}

			// Grab the first bit of video, set up the texture.
			if (TheoraPlay.THEORAPLAY_hasVideoStream(Video.theoraDecoder) != 0)
			{
				currentVideo = TheoraPlay.getVideoFrame(Video.videoStream);
				previousFrame = Video.videoStream;
				do
				{
					// The decoder miiight not be ready yet.
					Video.videoStream = TheoraPlay.THEORAPLAY_getVideo(Video.theoraDecoder);
				} while (Video.videoStream == IntPtr.Zero);
				nextVideo = TheoraPlay.getVideoFrame(Video.videoStream);

				// The VideoPlayer will use the GraphicsDevice that is set now.
				if (currentDevice != Video.GraphicsDevice)
				{
					if (currentDevice != null)
					{
						GL_dispose();
					}
					currentDevice = Video.GraphicsDevice;
					GL_initialize();
				}

				RenderTargetBinding overlap = videoTexture[0];
				videoTexture[0] = new RenderTargetBinding(
					new RenderTarget2D(
						currentDevice,
						(int) currentVideo.width,
						(int) currentVideo.height,
						false,
						SurfaceFormat.Color,
						DepthFormat.None,
						0,
						RenderTargetUsage.PreserveContents
					)
				);
				if (overlap.RenderTarget != null)
				{
					overlap.RenderTarget.Dispose();
				}
				GL_setupTextures(
					(int) currentVideo.width,
					(int) currentVideo.height
				);
			}

			// Initialize the thread!
			FNAPlatform.Log("Starting Theora player...");
			timer.Start();
			if (audioStream != null)
			{
				audioStream.Play();
			}
			FNAPlatform.Log("Started!");
		}
Beispiel #10
0
		public Texture2D GetTexture()
		{
			checkDisposed();

			if (Video == null)
			{
				throw new InvalidOperationException();
			}

			// Be sure we can even get something from TheoraPlay...
			if (	State == MediaState.Stopped ||
				Video.theoraDecoder == IntPtr.Zero ||
				TheoraPlay.THEORAPLAY_isInitialized(Video.theoraDecoder) == 0 ||
				TheoraPlay.THEORAPLAY_hasVideoStream(Video.theoraDecoder) == 0	)
			{
				 // Screw it, give them the old one.
				return videoTexture[0].RenderTarget as Texture2D;
			}

			// Get the latest video frames.
			bool missedFrame = false;
			while (nextVideo.playms <= timer.ElapsedMilliseconds && !missedFrame)
			{
				currentVideo = nextVideo;
				IntPtr nextFrame = TheoraPlay.THEORAPLAY_getVideo(Video.theoraDecoder);
				if (nextFrame != IntPtr.Zero)
				{
					TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
					previousFrame = Video.videoStream;
					Video.videoStream = nextFrame;
					nextVideo = TheoraPlay.getVideoFrame(Video.videoStream);
					missedFrame = false;
				}
				else
				{
					// Don't mind me, just ignoring that complete failure above!
					missedFrame = true;
				}

				if (TheoraPlay.THEORAPLAY_isDecoding(Video.theoraDecoder) == 0)
				{
					// FIXME: This is part of the Duration hack!
					Video.Duration = new TimeSpan(0, 0, 0, 0, (int) currentVideo.playms);

					// Stop and reset the timer. If we're looping, the loop will start it again.
					timer.Stop();
					timer.Reset();

					// If looping, go back to the start. Otherwise, we'll be exiting.
					if (IsLooped && State == MediaState.Playing)
					{
						// Kill the audio, no matter what.
						if (audioStream != null)
						{
							audioStream.Stop();
							audioStream.Dispose();
							audioStream = null;
						}

						// Free everything and start over.
						TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
						previousFrame = IntPtr.Zero;
						Video.AttachedToPlayer = false;
						Video.Dispose();
						Video.AttachedToPlayer = true;
						Video.Initialize();

						// Grab the initial audio again.
						if (TheoraPlay.THEORAPLAY_hasAudioStream(Video.theoraDecoder) != 0)
						{
							InitAudioStream();
						}

						// Grab the initial video again.
						if (TheoraPlay.THEORAPLAY_hasVideoStream(Video.theoraDecoder) != 0)
						{
							currentVideo = TheoraPlay.getVideoFrame(Video.videoStream);
							previousFrame = Video.videoStream;
							do
							{
								// The decoder miiight not be ready yet.
								Video.videoStream = TheoraPlay.THEORAPLAY_getVideo(Video.theoraDecoder);
							} while (Video.videoStream == IntPtr.Zero);
							nextVideo = TheoraPlay.getVideoFrame(Video.videoStream);
						}

						// Start! Again!
						timer.Start();
						if (audioStream != null)
						{
							audioStream.Play();
						}
					}
					else
					{
						// Stop everything, clean up. We out.
						State = MediaState.Stopped;
						if (audioStream != null)
						{
							audioStream.Stop();
							audioStream.Dispose();
							audioStream = null;
						}
						TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
						Video.AttachedToPlayer = false;
						Video.Dispose();

						// We're done, so give them the last frame.
						return videoTexture[0].RenderTarget as Texture2D;
					}
				}
			}

			// Set up an environment to muck about in.
			GL_pushState();

			// Prepare YUV GL textures with our current frame data
			currentDevice.GLDevice.SetTextureData2DPointer(
				yuvTextures[0],
				currentVideo.pixels
			);
			currentDevice.GLDevice.SetTextureData2DPointer(
				yuvTextures[1],
				new IntPtr(
					currentVideo.pixels.ToInt64() +
					(currentVideo.width * currentVideo.height)
				)
			);
			currentDevice.GLDevice.SetTextureData2DPointer(
				yuvTextures[2],
				new IntPtr(
					currentVideo.pixels.ToInt64() +
					(currentVideo.width * currentVideo.height) +
					(currentVideo.width / 2 * currentVideo.height / 2)
				)
			);

			// Draw the YUV textures to the framebuffer with our shader.
			currentDevice.DrawPrimitives(
				PrimitiveType.TriangleStrip,
				0,
				2
			);

			// Clean up after ourselves.
			GL_popState();

			// Finally.
			return videoTexture[0].RenderTarget as Texture2D;
		}
Beispiel #11
0
        private void RunVideo()
        {
            // FIXME: Maybe use an actual thread synchronization technique.
            while (!audioStarted && State != MediaState.Stopped)
            {
                ;
            }

            while (State != MediaState.Stopped)
            {
                // Someone needs to look at their memory management...
                if (Game.Instance == null)
                {
                    System.Console.WriteLine("Game exited before video player! Halting...");
                    State = MediaState.Stopped;
                }

                // Sleep when paused, update the video state when playing.
                if (State == MediaState.Paused)
                {
                    // Pause the OpenAL source.
                    if (AL.GetSourceState(audioSourceIndex) == ALSourceState.Playing)
                    {
                        AL.SourcePause(audioSourceIndex);
                    }

                    // Stop the timer in here so we know when we really stopped.
                    if (timer.IsRunning)
                    {
                        timer.Stop();
                    }

                    // Arbitrarily 1 frame in a 30fps movie.
                    Thread.Sleep(33);
                }
                else
                {
                    // Start the timer, whether we're starting or unpausing.
                    if (!timer.IsRunning)
                    {
                        timer.Start();
                    }

                    // If we're getting here, we should be playing the audio...
                    if (TheoraPlay.THEORAPLAY_hasAudioStream(Video.theoraDecoder) != 0)
                    {
                        if (AL.GetSourceState(audioSourceIndex) != ALSourceState.Playing)
                        {
                            AL.SourcePlay(audioSourceIndex);
                        }
                    }

                    // Get the next video from from the decoder, if a stream exists.
                    if (TheoraPlay.THEORAPLAY_hasVideoStream(Video.theoraDecoder) != 0)
                    {
                        // Only step when it's time to do so.
                        if (nextVideo.playms <= timer.ElapsedMilliseconds)
                        {
                            // Wait until GetTexture() is done.

                            // FIXME: Maybe use an actual thread synchronization technique.
                            while (frameLocked)
                            {
                                ;
                            }

                            // Assign the new currentVideo, free the old one.
                            currentVideo = nextVideo;

                            // Get the next frame ready, free the old one.
                            IntPtr oldestFrame = previousFrame;
                            previousFrame     = Video.videoStream;
                            Video.videoStream = TheoraPlay.THEORAPLAY_getVideo(Video.theoraDecoder);
                            if (Video.videoStream != IntPtr.Zero)
                            {
                                // Assign next frame, if it exists.
                                nextVideo = TheoraPlay.getVideoFrame(Video.videoStream);

                                // Then free the _really_ old frame.
                                TheoraPlay.THEORAPLAY_freeVideo(oldestFrame);
                            }
                        }
                    }

                    // If we're done decoding, we hit the end.
                    if (TheoraPlay.THEORAPLAY_isDecoding(Video.theoraDecoder) == 0)
                    {
                        // FIXME: This is a part of the Duration hack!
                        Video.Duration = new TimeSpan(0, 0, 0, 0, (int)currentVideo.playms);

                        // Stop and reset the timer.
                        // If we're looping, the loop will start it again.
                        timer.Stop();
                        timer.Reset();

                        // If looping, go back to the start. Otherwise, we'll be exiting.
                        if (IsLooped && State == MediaState.Playing)
                        {
                            // Wait for the audio thread to end.
                            State = MediaState.Stopped;
                            audioDecoderThread.Join();

                            // Now we pretend we're playing again.
                            State = MediaState.Playing;

                            // Free everything and start over.
                            TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
                            previousFrame = IntPtr.Zero;
                            Video.Dispose();
                            Video.Initialize();

                            // Grab the initial audio again.
                            if (TheoraPlay.THEORAPLAY_hasAudioStream(Video.theoraDecoder) != 0)
                            {
                                currentAudio       = TheoraPlay.getAudioPacket(Video.audioStream);
                                audioDecoderThread = new Thread(new ThreadStart(DecodeAudio));
                                audioDecoderThread.Start();
                            }
                            else
                            {
                                audioStarted = true; // Welp.
                            }

                            // Grab the initial video again.
                            if (TheoraPlay.THEORAPLAY_hasVideoStream(Video.theoraDecoder) != 0)
                            {
                                currentVideo  = TheoraPlay.getVideoFrame(Video.videoStream);
                                previousFrame = Video.videoStream;
                                do
                                {
                                    // The decoder miiight not be ready yet.
                                    Video.videoStream = TheoraPlay.THEORAPLAY_getVideo(Video.theoraDecoder);
                                } while (Video.videoStream == IntPtr.Zero);
                                nextVideo = TheoraPlay.getVideoFrame(Video.videoStream);
                            }

                            // FIXME: Maybe use an actual thread synchronization technique.
                            while (!audioStarted && State != MediaState.Stopped)
                            {
                                ;
                            }
                        }
                        else
                        {
                            State = MediaState.Stopped;
                        }
                    }
                }
            }

            // Reset the video timer.
            timer.Stop();
            timer.Reset();

            // Stop the decoding, we don't need it anymore.
            audioDecoderThread.Join();

            // We're desperately trying to keep this until the very end.
            TheoraPlay.THEORAPLAY_freeVideo(previousFrame);

            // We're not playing any video anymore.
            Video.Dispose();
        }
        public void UpdateVideo(float elapsedFrameTime)
        {
            while (_currentVideo.playms <= elapsedFrameTime && TheoraPlay.THEORAPLAY_availableVideo(_theoraDecoder)!=0)
            {
                _currentVideo = _nextVideo;

                var nextFrame = TheoraPlay.THEORAPLAY_getVideo(_theoraDecoder);

                if (nextFrame != IntPtr.Zero)
                {
                    TheoraPlay.THEORAPLAY_freeVideo(_previousFrame);
                    _previousFrame = _videoStream;
                    _videoStream = nextFrame;
                    _nextVideo = GetVideoFrame(_videoStream);

                }
            }
            IsFinished = TheoraPlay.THEORAPLAY_isDecoding(_theoraDecoder) == 0;
        }
        public void Terminate()
        {
            // 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;
            }
            _currentVideo = new TheoraPlay.THEORAPLAY_VideoFrame();
            _nextVideo = new TheoraPlay.THEORAPLAY_VideoFrame();
            TheoraPlay.THEORAPLAY_freeVideo(_previousFrame);
            _previousFrame = IntPtr.Zero;
            _videoStream = IntPtr.Zero;
            _disposed = true;
        }
Beispiel #14
0
		public void Play(Video video)
		{
			checkDisposed();

			// We need to assign this regardless of what happens next.
			Video = video;
			video.AttachedToPlayer = true;

			// FIXME: This is a part of the Duration hack!
			Video.Duration = TimeSpan.MaxValue;

			// Check the player state before attempting anything.
			if (State != MediaState.Stopped)
			{
				return;
			}

			// Update the player state now, for the thread we're about to make.
			State = MediaState.Playing;

			// Start the video if it hasn't been yet.
			if (Video.IsDisposed)
			{
				video.Initialize();
			}

			// Grab the first bit of audio. We're trying to start the decoding ASAP.
			if (TheoraPlay.THEORAPLAY_hasAudioStream(Video.theoraDecoder) != 0)
			{
				InitAudioStream();
			}

			// Grab the first bit of video, set up the texture.
			if (TheoraPlay.THEORAPLAY_hasVideoStream(Video.theoraDecoder) != 0)
			{
				currentVideo = TheoraPlay.getVideoFrame(Video.videoStream);
				previousFrame = Video.videoStream;
				do
				{
					// The decoder miiight not be ready yet.
					Video.videoStream = TheoraPlay.THEORAPLAY_getVideo(Video.theoraDecoder);
				} while (Video.videoStream == IntPtr.Zero);
				nextVideo = TheoraPlay.getVideoFrame(Video.videoStream);

				Texture2D overlap = videoTexture;
				videoTexture = new Texture2D(
					currentDevice,
					(int) currentVideo.width,
					(int) currentVideo.height,
					false,
					SurfaceFormat.Color
				);
				overlap.Dispose();
#if VIDEOPLAYER_OPENGL
				GL_setupTargets(
					(int) currentVideo.width,
					(int) currentVideo.height
				);
#endif
			}

			// Initialize the thread!
			System.Console.Write("Starting Theora player...");
			timer.Start();
			if (audioStream != null)
			{
				audioStream.Play();
			}
			System.Console.WriteLine(" Done!");
		}
Beispiel #15
0
		public Texture2D GetTexture()
		{
			checkDisposed();

			// Be sure we can even get something from TheoraPlay...
			if (	State == MediaState.Stopped ||
				Video.theoraDecoder == IntPtr.Zero ||
				TheoraPlay.THEORAPLAY_isInitialized(Video.theoraDecoder) == 0 ||
				TheoraPlay.THEORAPLAY_hasVideoStream(Video.theoraDecoder) == 0	)
			{
				return videoTexture; // Screw it, give them the old one.
			}

			// Get the latest video frames.
			bool missedFrame = false;
			while (nextVideo.playms <= timer.ElapsedMilliseconds && !missedFrame)
			{
				currentVideo = nextVideo;
				IntPtr nextFrame = TheoraPlay.THEORAPLAY_getVideo(Video.theoraDecoder);
				if (nextFrame != IntPtr.Zero)
				{
					TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
					previousFrame = Video.videoStream;
					Video.videoStream = nextFrame;
					nextVideo = TheoraPlay.getVideoFrame(Video.videoStream);
					missedFrame = false;
				}
				else
				{
					// Don't mind me, just ignoring that complete failure above!
					missedFrame = true;
				}

				if (TheoraPlay.THEORAPLAY_isDecoding(Video.theoraDecoder) == 0)
				{
					// FIXME: This is part of the Duration hack!
					Video.Duration = new TimeSpan(0, 0, 0, 0, (int) currentVideo.playms);

					// Stop and reset the timer. If we're looping, the loop will start it again.
					timer.Stop();
					timer.Reset();

					// If looping, go back to the start. Otherwise, we'll be exiting.
					if (IsLooped && State == MediaState.Playing)
					{
						// Kill the audio, no matter what.
						if (audioStream != null)
						{
							audioStream.Stop();
							audioStream.Dispose();
							audioStream = null;
						}

						// Free everything and start over.
						TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
						previousFrame = IntPtr.Zero;
						Video.AttachedToPlayer = false;
						Video.Dispose();
						Video.AttachedToPlayer = true;
						Video.Initialize();

						// Grab the initial audio again.
						if (TheoraPlay.THEORAPLAY_hasAudioStream(Video.theoraDecoder) != 0)
						{
							InitAudioStream();
						}

						// Grab the initial video again.
						if (TheoraPlay.THEORAPLAY_hasVideoStream(Video.theoraDecoder) != 0)
						{
							currentVideo = TheoraPlay.getVideoFrame(Video.videoStream);
							previousFrame = Video.videoStream;
							do
							{
								// The decoder miiight not be ready yet.
								Video.videoStream = TheoraPlay.THEORAPLAY_getVideo(Video.theoraDecoder);
							} while (Video.videoStream == IntPtr.Zero);
							nextVideo = TheoraPlay.getVideoFrame(Video.videoStream);
						}

						// Start! Again!
						timer.Start();
						if (audioStream != null)
						{
							audioStream.Play();
						}
					}
					else
					{
						// Stop everything, clean up. We out.
						State = MediaState.Stopped;
						if (audioStream != null)
						{
							audioStream.Stop();
							audioStream.Dispose();
							audioStream = null;
						}
						TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
						Video.AttachedToPlayer = false;
						Video.Dispose();

						// We're done, so give them the last frame.
						return videoTexture;
					}
				}
			}

#if VIDEOPLAYER_OPENGL
			// Set up an environment to muck about in.
			GL_pushState();

			// Bind our shader program.
			currentDevice.GLDevice.glUseProgram(shaderProgram);

			// We're using client-side arrays like CAVEMEN
			currentDevice.GLDevice.BindVertexBuffer(OpenGLDevice.OpenGLVertexBuffer.NullBuffer);

			// Set up the vertex pointers/arrays.
			currentDevice.GLDevice.AttributeEnabled[0] = true;
			currentDevice.GLDevice.AttributeEnabled[1] = true;
			for (int i = 2; i < currentDevice.GLDevice.AttributeEnabled.Length; i += 1)
			{
				currentDevice.GLDevice.AttributeEnabled[i] = false;
			}
			currentDevice.GLDevice.FlushGLVertexAttributes();
			currentDevice.GLDevice.VertexAttribPointer(
				0,
				2,
				VertexElementFormat.Single,
				false,
				2 * sizeof(float),
				vertPosPtr
			);
			currentDevice.GLDevice.VertexAttribPointer(
				1,
				2,
				VertexElementFormat.Single,
				false,
				2 * sizeof(float),
				vertTexPtr
			);

			// Bind our target framebuffer.
			currentDevice.GLDevice.BindDrawFramebuffer(rgbaFramebuffer);

			// Prepare YUV GL textures with our current frame data
			currentDevice.GLDevice.glActiveTexture(
				OpenGLDevice.GLenum.GL_TEXTURE0
			);
			currentDevice.GLDevice.glBindTexture(
				OpenGLDevice.GLenum.GL_TEXTURE_2D,
				yuvTextures[0]
			);
			currentDevice.GLDevice.glTexSubImage2D(
				OpenGLDevice.GLenum.GL_TEXTURE_2D,
				0,
				0,
				0,
				(int) currentVideo.width,
				(int) currentVideo.height,
				OpenGLDevice.GLenum.GL_LUMINANCE,
				OpenGLDevice.GLenum.GL_UNSIGNED_BYTE,
				currentVideo.pixels
			);
			currentDevice.GLDevice.glActiveTexture(
				OpenGLDevice.GLenum.GL_TEXTURE0 + 1
			);
			currentDevice.GLDevice.glBindTexture(
				OpenGLDevice.GLenum.GL_TEXTURE_2D,
				yuvTextures[1]
			);
			currentDevice.GLDevice.glTexSubImage2D(
				OpenGLDevice.GLenum.GL_TEXTURE_2D,
				0,
				0,
				0,
				(int) (currentVideo.width / 2),
				(int) (currentVideo.height / 2),
				OpenGLDevice.GLenum.GL_LUMINANCE,
				OpenGLDevice.GLenum.GL_UNSIGNED_BYTE,
				new IntPtr(
					currentVideo.pixels.ToInt64() +
					(currentVideo.width * currentVideo.height)
				)
			);
			currentDevice.GLDevice.glActiveTexture(
				OpenGLDevice.GLenum.GL_TEXTURE0 + 2
			);
			currentDevice.GLDevice.glBindTexture(
				OpenGLDevice.GLenum.GL_TEXTURE_2D,
				yuvTextures[2]
			);
			currentDevice.GLDevice.glTexSubImage2D(
				OpenGLDevice.GLenum.GL_TEXTURE_2D,
				0,
				0,
				0,
				(int) (currentVideo.width / 2),
				(int) (currentVideo.height / 2),
				OpenGLDevice.GLenum.GL_LUMINANCE,
				OpenGLDevice.GLenum.GL_UNSIGNED_BYTE,
				new IntPtr(
					currentVideo.pixels.ToInt64() +
					(currentVideo.width * currentVideo.height) +
					(currentVideo.width / 2 * currentVideo.height / 2)
				)
			);

			// Flip the viewport, because loldirectx
			currentDevice.GLDevice.glViewport(
				0,
				0,
				(int) currentVideo.width,
				(int) currentVideo.height
			);

			// Draw the YUV textures to the framebuffer with our shader.
			currentDevice.GLDevice.glDrawArrays(
				OpenGLDevice.GLenum.GL_TRIANGLE_STRIP,
				0,
				4
			);

			// Clean up after ourselves.
			GL_popState();
#else
			// Just copy it to an array, since it's RGBA anyway.
			try
			{
				byte[] theoraPixels = TheoraPlay.getPixels(
					currentVideo.pixels,
					(int) currentVideo.width * (int) currentVideo.height * 4
				);

				// TexImage2D.
				videoTexture.SetData<byte>(theoraPixels);
			}
			catch(Exception e)
			{
				// I hope we've still got something in videoTexture!
				System.Console.WriteLine(
					"WARNING: THEORA FRAME COPY FAILED: " +
					e.Message
				);
			}
#endif

			return videoTexture;
		}
Beispiel #16
0
        public Texture GetTexture()
        {
            checkDisposed();

            // Be sure we can even get something from TheoraPlay...
            if (State == MediaState.Stopped ||
                Video.TheoraDecoder == IntPtr.Zero ||
                TheoraPlay.THEORAPLAY_isInitialized(Video.TheoraDecoder) == 0 ||
                TheoraPlay.THEORAPLAY_hasVideoStream(Video.TheoraDecoder) == 0)
            {
                return(videoTexture); // Screw it, give them the old one.
            }

            // Get the latest video frames.
            bool missedFrame = false;

            while (nextVideo.playms <= timer.ElapsedMilliseconds && !missedFrame)
            {
                currentVideo = nextVideo;
                IntPtr nextFrame = TheoraPlay.THEORAPLAY_getVideo(Video.TheoraDecoder);
                if (nextFrame != IntPtr.Zero)
                {
                    TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
                    previousFrame     = Video.VideoStream;
                    Video.VideoStream = nextFrame;
                    nextVideo         = TheoraPlay.getVideoFrame(Video.VideoStream);
                    missedFrame       = false;
                }
                else
                {
                    // Don't mind me, just ignoring that complete failure above!
                    missedFrame = true;
                }

                if (TheoraPlay.THEORAPLAY_isDecoding(Video.TheoraDecoder) == 0)
                {
                    // FIXME: This is part of the Duration hack!
                    Video.Duration = new TimeSpan(0, 0, 0, 0, (int)currentVideo.playms);

                    // Stop and reset the timer. If we're looping, the loop will start it again.
                    timer.Stop();
                    timer.Reset();

                    // If looping, go back to the start. Otherwise, we'll be exiting.
                    if (IsLooped && State == MediaState.Playing)
                    {
                        // Wait for the audio thread to end.
                        State = MediaState.Stopped;
                        if (audioDecoderThread.ThreadState != System.Threading.ThreadState.Unstarted && audioDecoderThread.IsAlive == true)
                        {
                            audioDecoderThread.Join();
                        }

                        // Now we pretend we're playing again.
                        State = MediaState.Playing;

                        // Free everything and start over.
                        TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
                        previousFrame = IntPtr.Zero;
                        Video.Dispose();
                        Video.Initialize();

                        // Grab the initial audio again.
                        if (TheoraPlay.THEORAPLAY_hasAudioStream(Video.TheoraDecoder) != 0)
                        {
                            audioDecoderThread = new Thread(new ThreadStart(DecodeAudio));
                            audioDecoderThread.Start();
                        }
                        else
                        {
                            audioStarted = true; // Welp.
                        }

                        // Grab the initial video again.
                        if (TheoraPlay.THEORAPLAY_hasVideoStream(Video.TheoraDecoder) != 0)
                        {
                            currentVideo  = TheoraPlay.getVideoFrame(Video.VideoStream);
                            previousFrame = Video.VideoStream;
                            do
                            {
                                // The decoder miiight not be ready yet.
                                Video.VideoStream = TheoraPlay.THEORAPLAY_getVideo(Video.TheoraDecoder);
                            } while (Video.VideoStream == IntPtr.Zero);
                            nextVideo = TheoraPlay.getVideoFrame(Video.VideoStream);
                        }

                        // FIXME: Maybe use an actual thread synchronization technique.
                        while (!audioStarted)
                        {
                            ;
                        }

                        // Start! Again!
                        timer.Start();
                        if (audioSourceIndex != -1)
                        {
                            AL.SourcePlay(audioSourceIndex);
                        }
                    }
                    else
                    {
                        // Stop everything, clean up. We out.
                        State = MediaState.Stopped;
                        if (audioDecoderThread.ThreadState != System.Threading.ThreadState.Unstarted && audioDecoderThread.IsAlive == true)
                        {
                            audioDecoderThread.Join();
                        }
                        TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
                        Video.Dispose();

                        // We're done, so give them the last frame.
                        return(videoTexture);
                    }
                }
            }

#if VIDEOPLAYER_OPENGL
            // Set up an environment to muck about in.
            GL_pushState();

            // Bind our shader program.
            GL.UseProgram(shaderProgram);

            // Set uniform values.
            GL.Uniform1(
                GL.GetUniformLocation(shaderProgram, "samp0"),
                0
                );
            GL.Uniform1(
                GL.GetUniformLocation(shaderProgram, "samp1"),
                1
                );
            GL.Uniform1(
                GL.GetUniformLocation(shaderProgram, "samp2"),
                2
                );

            // Set up the vertex pointers/arrays.
            GL.VertexAttribPointer(
                0,
                2,
                VertexAttribPointerType.Float,
                false,
                2 * sizeof(float),
                vert_pos
                );
            GL.VertexAttribPointer(
                1,
                2,
                VertexAttribPointerType.Float,
                false,
                2 * sizeof(float),
                vert_tex
                );
            GL.EnableVertexAttribArray(0);
            GL.EnableVertexAttribArray(1);

            // Bind our target framebuffer.
            GL.BindFramebuffer(FramebufferTarget.Framebuffer, rgbaFramebuffer);

            // Prepare YUV GL textures with our current frame data
            GL.ActiveTexture(TextureUnit.Texture0);
            GL.BindTexture(TextureTarget.Texture2D, yuvTextures[0]);
            GL.TexSubImage2D(
                TextureTarget.Texture2D,
                0,
                0,
                0,
                (int)currentVideo.width,
                (int)currentVideo.height,
                PixelFormat.Luminance,
                PixelType.UnsignedByte,
                currentVideo.pixels
                );
            GL.ActiveTexture(TextureUnit.Texture1);
            GL.BindTexture(TextureTarget.Texture2D, yuvTextures[1]);
            GL.TexSubImage2D(
                TextureTarget.Texture2D,
                0,
                0,
                0,
                (int)currentVideo.width / 2,
                (int)currentVideo.height / 2,
                PixelFormat.Luminance,
                PixelType.UnsignedByte,
                new IntPtr(
                    currentVideo.pixels.ToInt64() +
                    (currentVideo.width * currentVideo.height)
                    )
                );
            GL.ActiveTexture(TextureUnit.Texture2);
            GL.BindTexture(TextureTarget.Texture2D, yuvTextures[2]);
            GL.TexSubImage2D(
                TextureTarget.Texture2D,
                0,
                0,
                0,
                (int)currentVideo.width / 2,
                (int)currentVideo.height / 2,
                PixelFormat.Luminance,
                PixelType.UnsignedByte,
                new IntPtr(
                    currentVideo.pixels.ToInt64() +
                    (currentVideo.width * currentVideo.height) +
                    (currentVideo.width / 2 * currentVideo.height / 2)
                    )
                );

            // Flip the viewport, because loldirectx
            GL.Viewport(
                0,
                0,
                (int)currentVideo.width,
                (int)currentVideo.height
                );

            // Draw the YUV textures to the framebuffer with our shader.
            GL.DrawArrays(BeginMode.TriangleStrip, 0, 4);

            // Clean up after ourselves.
            GL_popState();
#else
            // Just copy it to an array, since it's RGBA anyway.
            try
            {
                byte[] theoraPixels = TheoraPlay.getPixels(
                    currentVideo.pixels,
                    (int)currentVideo.width * (int)currentVideo.height * 4
                    );

                // TexImage2D.
                videoTexture.SetData <byte>(theoraPixels);
            }
            catch (Exception e)
            {
                System.Console.WriteLine(
                    "WARNING: THEORA FRAME COPY FAILED: " +
                    e.Message
                    );
                frameLocked = false;
                return(videoTexture); // Hope this still has something in it...
            }
#endif

            return(videoTexture);
        }
Beispiel #17
0
        public void Play(OgvComponent video)
        {
            checkDisposed();

            // We need to assign this regardless of what happens next.
            Video = video;

            // FIXME: This is a part of the Duration hack!
            Video.Duration = TimeSpan.MaxValue;

            // Check the player state before attempting anything.
            if (State != MediaState.Stopped)
            {
                return;
            }

            // In rare cases, the thread might still be going. Wait until it's done.
            if (audioDecoderThread != null && audioDecoderThread.IsAlive)
            {
                Stop();
            }

            // Create new Thread instances in case we use this player multiple times.
            audioDecoderThread = new Thread(new ThreadStart(this.DecodeAudio));

            // Update the player state now, for the thread we're about to make.
            State = MediaState.Playing;

            // Start the video if it hasn't been yet.
            if (Video.IsDisposed)
            {
                video.Initialize();
            }

            // Grab the first bit of audio. We're trying to start the decoding ASAP.
            if (TheoraPlay.THEORAPLAY_hasAudioStream(Video.TheoraDecoder) != 0)
            {
                audioDecoderThread.Start();
            }
            else
            {
                audioStarted = true; // Welp.
            }

            // Grab the first bit of video, set up the texture.
            if (TheoraPlay.THEORAPLAY_hasVideoStream(Video.TheoraDecoder) != 0)
            {
                currentVideo  = TheoraPlay.getVideoFrame(Video.VideoStream);
                previousFrame = Video.VideoStream;
                do
                {
                    // The decoder miiight not be ready yet.
                    Video.VideoStream = TheoraPlay.THEORAPLAY_getVideo(Video.TheoraDecoder);
                } while (Video.VideoStream == IntPtr.Zero);
                nextVideo = TheoraPlay.getVideoFrame(Video.VideoStream);

                Texture overlap = videoTexture;
                videoTexture = new Texture(
//                    Game.Instance.GraphicsDevice,
//                    (int)currentVideo.width,
//                    (int)currentVideo.height,
//                    false,
//                    SurfaceFormat.Color
                    );
                overlap.Dispose();
#if VIDEOPLAYER_OPENGL
                GL_setupTargets(
                    (int)currentVideo.width,
                    (int)currentVideo.height
                    );
#endif
            }

            // Initialize the thread!
            Log.Editor.Write("Starting Theora player...");
            while (!audioStarted)
            {
                ;
            }
            timer.Start();
            if (audioSourceIndex != -1)
            {
                AL.SourcePlay(audioSourceIndex);
            }
            Log.Editor.Write(" Done starting Theora player!");
        }
        public Texture GetTexture()
        {
			checkDisposed();

            // Be sure we can even get something from TheoraPlay...
            if (State == MediaState.Stopped ||
                    Video.TheoraDecoder == IntPtr.Zero ||
                    TheoraPlay.THEORAPLAY_isInitialized(Video.TheoraDecoder) == 0 ||
                    TheoraPlay.THEORAPLAY_hasVideoStream(Video.TheoraDecoder) == 0)
            {
                return videoTexture; // Screw it, give them the old one.
            }

            // Get the latest video frames.
            bool missedFrame = false;
            while (nextVideo.playms <= timer.ElapsedMilliseconds && !missedFrame)
            {
                currentVideo = nextVideo;
                IntPtr nextFrame = TheoraPlay.THEORAPLAY_getVideo(Video.TheoraDecoder);
                if (nextFrame != IntPtr.Zero)
                {
                    TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
                    previousFrame = Video.VideoStream;
                    Video.VideoStream = nextFrame;
                    nextVideo = TheoraPlay.getVideoFrame(Video.VideoStream);
                    missedFrame = false;
                }
                else
                {
                    // Don't mind me, just ignoring that complete failure above!
                    missedFrame = true;
                }

                if (TheoraPlay.THEORAPLAY_isDecoding(Video.TheoraDecoder) == 0)
                {
                    // FIXME: This is part of the Duration hack!
                    Video.Duration = new TimeSpan(0, 0, 0, 0, (int)currentVideo.playms);

                    // Stop and reset the timer. If we're looping, the loop will start it again.
                    timer.Stop();
                    timer.Reset();

                    // If looping, go back to the start. Otherwise, we'll be exiting.
                    if (IsLooped && State == MediaState.Playing)
                    {
                        // Wait for the audio thread to end.
                        State = MediaState.Stopped;
                        if (audioDecoderThread.ThreadState != System.Threading.ThreadState.Unstarted && audioDecoderThread.IsAlive == true)
                            audioDecoderThread.Join();

                        // Now we pretend we're playing again.
                        State = MediaState.Playing;

                        // Free everything and start over.
                        TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
                        previousFrame = IntPtr.Zero;
                        Video.Dispose();
                        Video.Initialize();

                        // Grab the initial audio again.
                        if (TheoraPlay.THEORAPLAY_hasAudioStream(Video.TheoraDecoder) != 0)
                        {
                            audioDecoderThread = new Thread(new ThreadStart(DecodeAudio));
                            audioDecoderThread.Start();
                        }
                        else
                        {
                            audioStarted = true; // Welp.
                        }

                        // Grab the initial video again.
                        if (TheoraPlay.THEORAPLAY_hasVideoStream(Video.TheoraDecoder) != 0)
                        {
                            currentVideo = TheoraPlay.getVideoFrame(Video.VideoStream);
                            previousFrame = Video.VideoStream;
                            do
                            {
                                // The decoder miiight not be ready yet.
                                Video.VideoStream = TheoraPlay.THEORAPLAY_getVideo(Video.TheoraDecoder);
                            } while (Video.VideoStream == IntPtr.Zero);
                            nextVideo = TheoraPlay.getVideoFrame(Video.VideoStream);
                        }

                        // FIXME: Maybe use an actual thread synchronization technique.
                        while (!audioStarted) ;

                        // Start! Again!
                        timer.Start();
                        if (audioSourceIndex != -1)
                        {
                            AL.SourcePlay(audioSourceIndex);
                        }
                    }
                    else
                    {
                        // Stop everything, clean up. We out.
                        State = MediaState.Stopped;
                        if (audioDecoderThread.ThreadState != System.Threading.ThreadState.Unstarted && audioDecoderThread.IsAlive == true)
                            audioDecoderThread.Join();
                        TheoraPlay.THEORAPLAY_freeVideo(previousFrame);
                        Video.Dispose();

                        // We're done, so give them the last frame.
                        return videoTexture;
                    }
                }
            }

#if VIDEOPLAYER_OPENGL
            // Set up an environment to muck about in.
            GL_pushState();

            // Bind our shader program.
            GL.UseProgram(shaderProgram);

            // Set uniform values.
            GL.Uniform1(
                GL.GetUniformLocation(shaderProgram, "samp0"),
                0
            );
            GL.Uniform1(
                GL.GetUniformLocation(shaderProgram, "samp1"),
                1
            );
            GL.Uniform1(
                GL.GetUniformLocation(shaderProgram, "samp2"),
                2
            );

            // Set up the vertex pointers/arrays.
            GL.VertexAttribPointer(
                0,
                2,
                VertexAttribPointerType.Float,
                false,
                2 * sizeof(float),
                vert_pos
            );
            GL.VertexAttribPointer(
                1,
                2,
                VertexAttribPointerType.Float,
                false,
                2 * sizeof(float),
                vert_tex
            );
            GL.EnableVertexAttribArray(0);
            GL.EnableVertexAttribArray(1);

            // Bind our target framebuffer.
            GL.BindFramebuffer(FramebufferTarget.Framebuffer, rgbaFramebuffer);

            // Prepare YUV GL textures with our current frame data
            GL.ActiveTexture(TextureUnit.Texture0);
            GL.BindTexture(TextureTarget.Texture2D, yuvTextures[0]);
            GL.TexSubImage2D(
                TextureTarget.Texture2D,
                0,
                0,
                0,
                (int)currentVideo.width,
                (int)currentVideo.height,
                PixelFormat.Luminance,
                PixelType.UnsignedByte,
                currentVideo.pixels
            );
            GL.ActiveTexture(TextureUnit.Texture1);
            GL.BindTexture(TextureTarget.Texture2D, yuvTextures[1]);
            GL.TexSubImage2D(
                TextureTarget.Texture2D,
                0,
                0,
                0,
                (int)currentVideo.width / 2,
                (int)currentVideo.height / 2,
                PixelFormat.Luminance,
                PixelType.UnsignedByte,
                new IntPtr(
                    currentVideo.pixels.ToInt64() +
                    (currentVideo.width * currentVideo.height)
                )
            );
            GL.ActiveTexture(TextureUnit.Texture2);
            GL.BindTexture(TextureTarget.Texture2D, yuvTextures[2]);
            GL.TexSubImage2D(
                TextureTarget.Texture2D,
                0,
                0,
                0,
                (int)currentVideo.width / 2,
                (int)currentVideo.height / 2,
                PixelFormat.Luminance,
                PixelType.UnsignedByte,
                new IntPtr(
                    currentVideo.pixels.ToInt64() +
                    (currentVideo.width * currentVideo.height) +
                    (currentVideo.width / 2 * currentVideo.height / 2)
                )
            );

            // Flip the viewport, because loldirectx
            GL.Viewport(
                0,
                0,
                (int)currentVideo.width,
                (int)currentVideo.height
            );

            // Draw the YUV textures to the framebuffer with our shader.
            GL.DrawArrays(BeginMode.TriangleStrip, 0, 4);

            // Clean up after ourselves.
            GL_popState();
#else
            // Just copy it to an array, since it's RGBA anyway.
            try
            {
                byte[] theoraPixels = TheoraPlay.getPixels(
                    currentVideo.pixels,
                    (int) currentVideo.width * (int) currentVideo.height * 4
                );
                
                // TexImage2D.
                videoTexture.SetData<byte>(theoraPixels);
            }
            catch(Exception e)
            {
                System.Console.WriteLine(
                    "WARNING: THEORA FRAME COPY FAILED: " +
                    e.Message
                );
                frameLocked = false;
                return videoTexture; // Hope this still has something in it...
            }
#endif

            return videoTexture;
        }