在XNA中无缝播放视频

时间:2015-04-02 12:26:34

标签: c# multithreading xna

我已经编写了this source的代码,但是当我想循环播放视频时,它会稍微冻结一半左右。当我在互联网上搜索时,我在Here中看到了一些指南,例如制作一个帖子,并在那里做所有事情。我也写了一个Thread,但是当我编译项目时,它是一样的。有人还告诉我你的问题是你正在使用_videoThread.Join()。但当我删除它时,视频播放速度很慢,我不知道为什么,这是我的代码,如果有人帮助我,我将不胜感激:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Threading;

namespace VideoTest2
{
public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    Thread _videoThread;
    Rectangle screen;

    Video _video;
    Video _video2;
    VideoPlayer _videoPlayer;
    Texture2D _videoTexture;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    protected override void Initialize()
    {
        base.Initialize();
    }

    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        _video = Content.Load<Video>("My Movie");
        _video2 = Content.Load<Video>("My Movie2");
    }

    protected override void UnloadContent()
    {
        // TODO: Unload any non ContentManager content here
        _videoThread.Abort();
        _videoPlayer.Dispose();
    }


    private void DoVideoThread()
    {

        if (_videoPlayer == null)
        {
            _videoPlayer = new VideoPlayer();

            _videoPlayer.Play(_video);

        }

        if (_videoPlayer.State != MediaState.Stopped)
        {
            _videoTexture = _videoPlayer.GetTexture();
        }

        else //(_videoPlayer.State == MediaState.Stopped)
        {
            _videoPlayer.Play(_video);
        }
    }

    protected override void Update(GameTime gameTime)
    {
        if (Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Escape))
            this.Exit();

            _videoThread = new Thread(DoVideoThread) { IsBackground = true, Name = "VideoThread" };
            _videoThread.Start();
            _videoThread.Join();

        base.Update(gameTime);
    }


    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        // Drawing to the rectangle will stretch the  
        // video to fill the screen
        screen = new Rectangle(GraphicsDevice.Viewport.X,
            GraphicsDevice.Viewport.Y,
            GraphicsDevice.Viewport.Width,
            GraphicsDevice.Viewport.Height);

        // Draw the video, if we have a texture to draw.
        if (_videoTexture != null)
        {
            spriteBatch.Begin();
            spriteBatch.Draw(_videoTexture, screen, Color.White);
            spriteBatch.End();
        }

        base.Draw(gameTime);
    }
  }
}

由于

2 个答案:

答案 0 :(得分:2)

  

我还为此编写了一个Thread但是当我编译项目时,它是一样的。有人还告诉我你的问题是你正在使用_videoThread.Join()。但当我删除它时,视频播放速度很慢,我不知道为什么

_videoThread.Join()存在时,它会阻塞主线程(在本例中为XNA游戏循环线程),直到线程退出。

  

但是当我删除它时,视频播放速度很慢,我不知道为什么

那是因为当您删除_videoThread.Join()

  1. 一件好事 - 主UI线程不再等待子线程完成,所以理论上你的游戏不应该冻结

    < / LI>
  2. 坏事 - 因为当您在Update()期间生成线程时,不进行任何检查以查看线程是否正在运行而是生成新线程每一帧!

  3. 要解决您的问题,请更改此代码:

        protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Escape))
                this.Exit();
    
                _videoThread = new Thread(DoVideoThread) { IsBackground = true, Name = "VideoThread" };
                _videoThread.Start();
                _videoThread.Join();
    
            base.Update(gameTime);
        }
    

    ...为:

        protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Escape))
            {
                this.Exit();
            }
    
            if (_videoThread != null &&
                !_videoThread.IsAlive &&
                _videoPlayer.State == MediaState.Stopped)
            {
                _videoThread = new Thread(DoVideoThread) { IsBackground = true, Name = "VideoThread" };
                _videoThread.Start();
            }
    
           // Get the current video frame as a texture for this frame
           if (_videoPlayer.State != MediaState.Stopped)
           {
               _videoTexture = _videoPlayer.GetTexture();
           }
    
            base.Update(gameTime);
        }
    

    现在只会生成一个线程来播放视频。

    旁注

    我并不完全相信您需要一个仅用于媒体控制的线程,我们不会对音频执行此操作,并且您不负责解码视频。

答案 1 :(得分:0)

I modified it a bit, then its working fine, please do try like this below

protected override void Update(GameTime gameTime) {
        if (_videoThread == null &&
                       _videoPlayer.State == MediaState.Stopped)
        {
            _videoThread = new Thread(DoVideoThread) { IsBackground = true, Name = "VideoThread" };
            _videoThread.Start();
        }
}// modified draw
 protected override void Draw(GameTime gameTime)
    {         if (_videoThread != null &&    !_videoThread.IsAlive && _videoPlayer.State == MediaState.Stopped)
        {   _videoThread = new Thread(DoVideoThread) { IsBackground = true, Name = "VideoThread" };
            _videoThread.Start();}
        // Draw the video, if we have a texture to draw.
        if (_videoTexture != null)
        {
            spriteBatch.Begin();
            spriteBatch.Draw(_videoTexture, screen, Color.White);
            spriteBatch.End();
        }

        base.Draw(gameTime);
    }
  }
}

Thanks