Click here to Skip to main content
Click here to Skip to main content

VideoTexture Class and Webcam Application for XNA

By , 31 Jul 2007
 

Screenshot - XnaWebcamScreenshot.jpg

Figure 1. Screenshot of the xnaVideoViewer application in action

Introduction

"Video textures" are an important class of multimedia objects with interesting uses in video conferencing, visualization, gaming, robotics and image analysis. The most obvious use -- and therefore the usage that I have focused on in this project -- is to map streaming video from a webcam onto a Texture2D object. This is then applied to a sprite and presented as a live video window within an XNA application. In addition to consuming live video from any of your DirectX video devices, the VideoTexture class is also able to consume AVI, MPEG and WMV format video clips.

The VideoTexture class exposes a property called VideoTexture2D, which is intended to be usable wherever a normal Texture2D object might be used within XNA. This means that it can be used to apply a dynamic video texture onto both sprites and geometric meshes/models. It can also be manipulated by pixel, vertex and geometry shaders, just like any other texture.

Using the code

To use the VideoTexture class, you should:

  1. Copy the VideoTexture.cs file into your own project.
  2. Change the namespace in the VideoTexture.cs file to the name of your project namespace.
  3. Add a reference to DirectShowLib-2005.dll from the DirectShow.NET library.
  4. Compile it. The VideoTexture class should now be available in your project.

The XnaVideoViewer application demonstrates the usage of VideoComponent, which in turn demonstrates the usage of the VideoTexture class.

Points of interest

  • The VideoTexture class depends upon the managed DirectShow.NET library.
  • The VideoTexture.VideoTexture2D property can be polled by other classes to get the most current frame of video. This is what happens, for example, in the VideoComponent.Draw() method. Alternatively, classes that want to use VideoTexture can subscribe to VideoTexture.NewVideoTextureEvent and have the current frame of video pushed to them in NewVideoTextureEventArgs each time a new frame is grabbed from the video stream.
  • VideoComponent automatically registers itself as a service within the game application that uses it. It can be referenced through the Services collection via any other components used by the application.
  • Due to framework limitations within XNA -- specifically, the absence of the System.Windows namespace -- the desired source of video input (i.e. cameras or files) needs to be coded manually in the xnaVideoViewer application. This is done in the LoadComponents() method.
  • The xnaVideoViewer application maps the following commands to the XBox 360 controller: Run = A (Green); Pause = Y (Yellow); Stop = B (Red); Exit = Back.
  • The VideoTexture class has been used to provide the video stream for an experimental HUD application. It has recently been used to stream video textures through vertex shaders to correct lens distortions in real-time as a prelude to stitching the streams into a video mosaic.

History

  • 30 July 2007 - Version 1.1.0.0 uploaded to CodeProject. Changes include renaming and significant refactoring of the xnaVideoViewer, VideoComponent and VideoTexture classes. Support for AVI, MPEG and WMV video files was added. Support for Run, Pause and Stop was added. Support for Looping video clips was added. Two separate methods for capturing and handling DirectShow Filter Graph events were added. Additional error handling code was added.
  • 21 July 2007 - Version 1.0.0.0 uploaded to CodeProject.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Stephen Bogner
Engineer Defence R&D Canada
Canada Canada
Member
Stephen Bogner is a Senior Research Engineer with Defence R&D Canada. As the Head Autonomous Applications Group, Autonomous Intelligent Systems Section, he only programs when it can't be avoided, and then only in C#.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralTinting a region...memberb0iNg4 Sep '10 - 3:41 
If i would say want to tint only one particular region of the texture obtained from VideoTexture.cs, how would I go about doing that?
GeneralWebcam problem: A first chance exception of type 'System.InvalidOperationException' occurred in Microsoft.Xna.Framework.dllmemberjrbosch20 Nov '09 - 22:48 
Hi everyone,
 
When I run the code with this initialization (for the webcam):
 
this.webCam = new VideoComponent(this, 0);
 
I see only a black screen in the game window. But if look at the visual studio output text window, I see this error message, appearing continiously:
 
A first chance exception of type 'System.InvalidOperationException' occurred in Microsoft.Xna.Framework.dll
 
¿Someone knows how to solve that problem? Thanks
GeneralRe: Webcam problem: A first chance exception of type 'System.InvalidOperationException' occurred in Microsoft.Xna.Framework.dllmemberbarcsik18 Dec '09 - 12:52 
Somebody fixed it below...
 
In this reply: Re: VS2008, XNA 3.0, DirectShow.NET 2.0 ... almost working MrDytmire 8:55 31 Jan '09
 
Again, the fix is:
 
-Inside of Videocomponent.cs
-Change:
 
public override void Draw(GameTime gameTime)
{
this.videoSprite.Begin();
...
}
 
-To this:
 
public override void Draw(GameTime gameTime)
{
this.videoSprite.Begin(SpriteBlendMode.None, SpriteSortMode.Deferred, SaveStateMode.SaveState);
...
}
GeneralFramerate issues on a Macbook Pro running XP (boot-camp)memberYossi Landesman26 Aug '09 - 7:25 
Hey Stephen,
 
First, I'd like to thank you for sharing your code. It is very clear and helpful, and I've learnt a lot from it over the last week. I've used some of the code for an interactive art prototype based on webcam capture, and a colleague of mine is trying to use it overseas. He is running it on his new Macbook Pro (obviously running XP with reasonable resources). For some reason we're facing some framerate problems with our prototype.
 
We've decided to test with the original demo app that you've created, and we still experience very low framerate (always under 2fps). This is running with the motion detection mode set to none, and using is webcam. Using the webcam on other applications (such as Skype) works great (high framerates, reasonable resolution).
 
Do you have an idea what could be the cause for this problem??
 
Again, in any case, much gratitude for your effort.
Yossi
QuestionHow to make a webcam texture?memberKim Seonghyune29 Jul '09 - 19:27 
First, Sorry to my English.
But I was wondering about the this code for making texture.
 
yesterday I had try to this way
 
//
foreach (ModelMesh mesh in modeling.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.PreferPerPixelLighting = true;
effect.World = Matrix.CreateScale(scale) * Matrix.CreateTranslation(position);

effect.TextureEnabled = true;
effect.Texture = webCam.VideoTexture.VideoTexture2D; <<<<<<<<<<<<<<<<<<<<<<< write like this
 
effect.Projection = cameraProjectionMatrix;
effect.View = cameraViewMatrix;
}
mesh.Draw();
//
 
but that code just make a paused picture, that's not a movie;
 
please, Could Anyone help me? T_T
GeneralVideo in 3Dmemberoleksii.mdr10 Mar '09 - 2:35 
Hi Stephen,
 
First of all let me thank you for this nice article and source code.
I was playing around and tried to move towards 3D. Here is my draw method
public VertexPositionTexture[] quadVerts { get; set; }
public Vector3 quadPosition { get; set; }
public Matrix quadMatrix { get; set; }
public Texture2D quadTexture { get; set; }
public BasicEffect effect { get; set; }        
public Transformation CameraTransformation { get; set; }
 
public override void Draw(GameTime gameTime)
        {
            quadTexture = VideoTexture.VideoTexture2D;
            effect.Texture = quadTexture;
 
            effect.World = CameraTransformation.Matrix;
            effect.View = cameraManager.ActiveCamera.View;
            effect.Projection = cameraManager.ActiveCamera.Projection;
            
            effect.Begin();
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Begin();
                GraphicsDevice.DrawUserPrimitives<vertexpositiontexture>(PrimitiveType.TriangleStrip,
                                                                         quadVerts, 0, 2);
                pass.End();
            }
            effect.End();
            
            //videoSprite.Begin(SpriteBlendMode.None, SpriteSortMode.Deferred, SaveStateMode.SaveState);
            //videoSprite.Draw(VideoTexture.VideoTexture2D, DestinationRectangle, SourceRectangle, ModulationColor,
            //                 Rotation, Origin, SpriteFlip, LayerDepth);
            //videoSprite.End();
        }
</vertexpositiontexture>
Where videoSprite methods draw the video just in front of the camera, hiding all models behind and GraphicsDevice.DrawUserPrimitives method draws the first Texture2D in a correct place in 3D world.
 
What do I need to do in order to play video, not the first picture from it?
Probably there are some other ways to move video into 3D space?
 
Thanks,
Alex.
GeneralVS2008, XNA 3.0, DirectShow.NET 2.0 ... almost workingmemberajdto2342 Jan '09 - 5:24 
I just downloaded it and really quickly made a vs2008 solution with the necessary changes (only two actually)
 
first when creating the 2d videotexture (some parameter that was absolete in 3.0) and
second changing the types for eventParam1, eventParam2 in the HandleGraphEvents method in VideoTexture.cs from int to IntPtr
 
I can only grab one frame then I'll get a bunch of exceptions for the rest of the frames for some reason.
 
You can get my version at http://ajden.towfeek.se/xnaVideoTexture.rar
 
Feel free to email me at ajden.towfeek [at sign] gmail.com if anybode solves the mistery, I'm not going to put too much effort into it.
 
Happy new year! Wink | ;-)
GeneralRe: VS2008, XNA 3.0, DirectShow.NET 2.0 ... almost workingmemberMrDytmire31 Jan '09 - 2:55 
Hey I fixed it!
 
Here's the solution: Inside of Videocomponent.cs
 
Change:
public override void Draw(GameTime gameTime)
{
this.videoSprite.Begin();
this.videoSprite.Draw(this.videoTexture.VideoTexture2D, this.destinationRectangle, this.sourceRectangle, this.modulationColor, this.rotation, this.origin, this.spriteFlip, this.layerDepth);
this.videoSprite.End();
}
 
to this:
 
public override void Draw(GameTime gameTime)
{
this.videoSprite.Begin(SpriteBlendMode.None, SpriteSortMode.Deferred, SaveStateMode.SaveState);
this.videoSprite.Draw(this.videoTexture.VideoTexture2D, this.destinationRectangle, this.sourceRectangle, this.modulationColor, this.rotation, this.origin, this.spriteFlip, this.layerDepth);
this.videoSprite.End();
}
 
and it all works fine. Thanks for updating things to XNA 3.0!
QuestionHow to dump a Frame?memberyipling14 Oct '08 - 4:09 
hi, May I know how to get a frame or frames from the buffer of video stream captured from the camera using your component?
 
Thanks.
 
L
GeneralDirectShowLib-2005.dll Heeeeelpmembersashdude7 Jul '08 - 16:30 
Hi
 
I cannot find the right Dshow dll anywhere.
 
Anyone got this file???
 
thanks

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 31 Jul 2007
Article Copyright 2007 by Stephen Bogner
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid