You can try this it works for me to start and stop the video and to switch between them.
The only hang up is that if i switch from one video to the other too fast.
It can stall up unless i wait to hit play i think i kinda bandaided it by loading it thru play then stopping it to initialize then new video but i dunno.
Not sure it really matters if you make the player static or not id rather not but im not to confident that things are working right underneath so i did it static to make it more strict to get a better grip on what was happening.
Instructions
Load videos thru the pipeline as normal.
Add a class file to your project and copy the below class into your project.
All this class is meant to do is to sort of baby the videoplayer the video player might recover this way from null textures and such when it can’t keep up ect.
using System;
//using System.Collections.Generic;
using System.Diagnostics;
//using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
//using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace Microsoft.Xna.Framework
{
public static class VideoController
{
public static Video video;
public static VideoPlayer player;
public static Texture2D videoFrameTexture;
public static Texture2D dotTexture;
public static bool isPlayerInitialized = false;
public static float videoFps = 1f / 24f;
public static float timeToNextFrame = 1f / 24f;
public static float failframe = 0;
public static float nextVideoPlayDelay = 3.0f;
private static bool newVideoLoaded = false;
public static void LoadVideoPlayer(GraphicsDevice device, Microsoft.Xna.Framework.Content.ContentManager content, string FileName)
{
if (isPlayerInitialized == false)
{
dotTexture = TextureDotCreate(Color.White, device);
videoFrameTexture = dotTexture;
video = content.Load<Video>(FileName);
videoFps = 1f / video.FramesPerSecond + .01f;
timeToNextFrame = videoFps;
}
else
{
newVideoLoaded = true;
player.Stop();
video = content.Load<Video>(FileName);
// let it pre initialize by loading it into the player thru play then immediately stoping it.
player.Play(video);
player.Stop();
videoFps = 1f / video.FramesPerSecond + .01f;
// set a longer then normal delay.
timeToNextFrame = videoFps + timeToNextFrame; // when swaping out a video after you reload one it needs to be stoped why i dunno.
}
GetInfo();
}
public static bool IsPlaying()
{
if (player.State == MediaState.Playing)
return true;
else
return false;
}
public static string GetInfo()
{
string msg = "";
if (video != null)
{
msg += "\n video.FileName: " + video.FileName.ToString();
msg += "\n video.FramesPerSecond: " + video.FramesPerSecond.ToString();
msg += "\n video.Width: " + video.Width.ToString();
msg += "\n video.Height: " + video.Height.ToString();
msg += "\n videoFps: " + videoFps.ToString();
}
if (player != null)
{
msg +=
"\n player.Video.FileName: " + player.Video.FileName.ToString() +
"\n player.Video.State: " + player.State.ToString() +
"\n player.PlayPosition: " + player.PlayPosition.ToString() +
"\n player.Video.FramesPerSecond: " + player.Video.FramesPerSecond.ToString() +
"\n player.Video.Width: " + player.Video.Width.ToString() +
"\n player.Video.Height: " + player.Video.Height.ToString()
;
}
Console.WriteLine(msg);
return msg;
}
public static void PlayOrResumeVideo()
{
GetInfo();
if (isPlayerInitialized == false)
{
timeToNextFrame = videoFps;
videoFrameTexture = dotTexture;
timeToNextFrame = videoFps;
player = new VideoPlayer();
isPlayerInitialized = true;
try
{
player.Play(video);
}
catch (InvalidOperationException e)
{
isPlayerInitialized = false;
Debug.Assert(false, "Video Cannot be started InvalidOperationException:\n" +e);
}
}
else
{
if (newVideoLoaded)
newVideoLoaded = false;
if (player.State == MediaState.Paused)
{
player.Resume();
// sometimes throws "cannot start video"
// An unhandled exception of type 'SharpDX.SharpDXException' occurred in SharpDX.dll
// Additional information: HRESULT: [0x80004003], Module: [General], ApiCode: [E_POINTER/Invalid pointer], Message: Invalid pointer
}
if (player.State == MediaState.Stopped)
{
player.Play(video); // throws "cannot start video" if the video doesn't load properly.
}
GetInfo();
Console.WriteLine();
}
}
public static void PauseVideo()
{
if (isPlayerInitialized)
{
if (player.State == MediaState.Playing)
{
GetInfo();
player.Pause();
}
Console.WriteLine();
}
}
public static void StopVideo()
{
if (isPlayerInitialized)
{
if (player.State == MediaState.Playing)
{
player.Stop();
GetInfo();
}
if (player.State == MediaState.Paused)
{
player.Stop();
GetInfo();
}
Console.WriteLine();
}
}
public static int PlayPosition()
{
if (isPlayerInitialized)
{
return player.PlayPosition.Seconds;
}
else
{
return 0;
}
}
public static bool CheckTimeDecrement(GameTime gameTime)
{
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
timeToNextFrame -= elapsed;
if (timeToNextFrame < 0f)
{
timeToNextFrame = videoFps;
return true;
}
else
{
return false;
}
}
public static Texture2D GetVideoFrame(GameTime gameTime)
{
if (isPlayerInitialized)
{
if (player.State == MediaState.Playing && CheckTimeDecrement(gameTime))
{
Texture2D tmp;
try
{
tmp = player.GetTexture();
}
catch (InvalidOperationException e)
{
failframe++;
Console.WriteLine(" failed frame number "+ failframe + " "+e.ToString());
tmp = dotTexture;
}
// An unhandled exception of type 'SharpDX.SharpDXException' occurred in SharpDX.dll
// Additional information: HRESULT: [0x8007000E], Module: [General], ApiCode: [E_OUTOFMEMORY/Out of memory], Message: Not enough storage is available to complete this operation.
if (tmp != null)
{
videoFrameTexture = tmp;
}
}
}
if(videoFrameTexture == null)
{
videoFrameTexture = dotTexture;
}
return videoFrameTexture;
}
public static void Draw(SpriteBatch spritebatch, Rectangle drawRectangle, GameTime gameTime)
{
if (isPlayerInitialized)
{
spritebatch.Draw(GetVideoFrame(gameTime), drawRectangle, new Rectangle(0, 0, videoFrameTexture.Width, videoFrameTexture.Height), Color.White, 0f, Vector2.Zero, SpriteEffects.None, 0f);
}
}
private static Texture2D TextureDotCreate(Color c, GraphicsDevice device)
{
Color[] data = new Color[1];
data[0] = c;
Texture2D result = new Texture2D(device, 1, 1);
result.SetData(data);
return result;
}
}
}
In game1 i do this in update(…){ to control it.
if (Keyboard.GetState().IsKeyDown(Keys.OemPlus))
VideoController.LoadVideoPlayer(GraphicsDevice, Content, "thorClip");
if (Keyboard.GetState().IsKeyDown(Keys.OemMinus))
VideoController.LoadVideoPlayer(GraphicsDevice, Content, "TestRun");
if (Keyboard.GetState().IsKeyDown(Keys.P))
VideoController.PlayOrResumeVideo();
if (Keyboard.GetState().IsKeyDown(Keys.S))
VideoController.StopVideo();
if (Keyboard.GetState().IsKeyDown(Keys.A)) // doesn't work right never did.
VideoController.PauseVideo();
One more note all that get info and console stuff will make garbage its in there for testing you can remove it or comment it out its not needed.
Related
vlc in monogame might eventually happen but that is on hold for now
Using ffmpeg scrpts to alter videos to make them small better or change format
Some stuff i went thru trying to get video to work on dx
Note there is no open gl video player at the moment.