intermittent can not play video error

Hello

I am very close to finishing my game, however I am getting to following problem

I have 2 videos in my game, one plays at the start and then another one if you win/finish the game

This videos always plays first time around, however the second (sometimes works), or 3rd 4th time I play the videos, i get the error

“can not play video”

I have tried creating and disposing the object of player and video in many different ways

I have reused one player to play both videos

i have used static player etc

I have tried having multi copys of the same video, its the player which faults

I see this was spoken about on the web a year of so ago, but nothing seemed to happen

any ideas ?

or does anyone know of another media player i can use with monogame

thanks

error details

  •   $exception	{"cannot start video"}	System.InvalidOperationException
    
  •   Data	{System.Collections.ListDictionaryInternal}	System.Collections.IDictionary {System.Collections.ListDictionaryInternal}
    
      HResult	-2146233079	int
    
  •   TargetSite	{Void Play(Microsoft.Xna.Framework.Media.Video)}	System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}

@willmotil has a couple of posts on this lately, check his profile for the fastest way to find them.

Seems to be a major issue which I think MG needs rectifying asap…

I have seen his hosted video post, I have found an awful work around, you can use multi players, but this is hard to code as you have to referance it in draw and update, so local declare is not really am option, so you need many static players, which you can only use once

Can you share some of your code? It’ll be easier to diagnose the issue. Additionally, which platform(s) are you developing for and which MonoGame version are you using?

Latest stable monogame 3.7.1

Windows game

I do not have my code to hand, however it’s a copy of this guys

http://rbwhitaker.wikidot.com/video-playback

Windows 10, vs2019 c#

I shall post my code in the morning cheers

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.

1 Like

never expected such a detailed answer, thank you very much, i shall try this when home, and let you know., cheers

I have placed the class in and reworked my other code to use this, so in my project it is only using this video player now, however unfortunately i am getting bad results

I find the first video works great, then the second video sometimes works, however the 2nd play of any of them never works

My code is below

I have 2 game states that play video, (both in update and draw)

DRAW

GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();

else if (gameState == GameState.IntroVideo)
{
VideoController.Draw(spriteBatch, new Rectangle(0, 0, 1920, 1080), gameTime);
}

else if (gameState == GameState.IntroVideo)
{
VideoController.Draw(spriteBatch, new Rectangle(0, 0, 1920, 1080), gameTime);
}

spriteBatch.End();
base.Draw(gameTime);

UPDATE

     else if (gameState == GameState.IntroVideo)
        {
            if (bolFinalVideoStartBeenPlayed == false)
            {
                bolFinalVideoStartBeenPlayed = true;
                try
                {
                    VideoController.LoadVideoPlayer(GraphicsDevice, Content, "Untitled");
                }
                catch
                {

                }
            }
            if (Keyboard.GetState().IsKeyDown(Keys.P))
            {
                VideoController.PlayOrResumeVideo();
            }
            if (Keyboard.GetState().IsKeyDown(Keys.Space))
            {
                VideoController.StopVideo();
                gameState = GameState.LoadingLevel1;
            }

else if (gameState == GameState.WonGameVideo)
{
if (bolFinalVideoGameWonBeenPlayed == false)
{
bolFinalVideoGameWonBeenPlayed = true;

try
{
VideoController.LoadVideoPlayer(GraphicsDevice, Content, “endgamewon”);
VideoController.PlayOrResumeVideo();

                }
                catch
                {
                }
                
            }

sorry i do not know why the code is not indented in this editor

you will see i have tried the play the video in 2 ways, 1 way is instantly and 1 way, allows me to delay the .play

same results :frowning2:

Any ideas please

I am going to try monogame extended i believe

otherwise I shall have to just accept, sometimes the videos plays and sometimes not

1 Like

I found that monogame.extended does not seem to do video, and I found a monogame extended2 that someone has done, but it has not been updated for a year or so, I have simply made the video play if it can and carry on if not,its not a big issue, big shame monogame have not sorted this, otherwise it would be a fantastic platform/engine

Yes even if you get them working on your machine there is no guarantee they will not fail else were anyways.

How i got mine to work was to reformat them from mp4 to a simpler version of mp4 or even re-record them thru vlc. (mp4 is completely broken as far as i can tell at least on my machine.) then convert them thru ffmpeg to WMV using the script show in the example on the posted link for converting files via ffmpeg. I was also playing and stopping it manually which obviously introduced some additional delay.

Hopefully we can get the vlc player libs in monogame the one guy does have a example of how to do it with winforms which i suppose isn’t too far away from doing it with monogame and as he stated the new vlc libs aren’t stable enough yet to commit to it.

If one had the time to concentrate on it or one was already knowledgeable on how to do it quickly you could probably get a basic version working, i am unfortunately not.