(Code Snippet) Video reproduction using DirectShow

Discussion area about developing or extending OGRE, adding plugins for it or building applications on it. No newbie questions please, use the Help forum for that.
Post Reply
User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1
Contact:

Post by hmoraldo »

One detail...

You only need to create the directshow object, and to assign its texture to a material only once. After that, keep using loadMovie to switch from one movie to another (you don't even need to use unloadMovie; loadMovie manages it with no problems).

And anyway, I now imagine what can be the cause of your problem. If you set the dshow texture to a material, and then you destroy the dshow object (and so you destroy the dshow texture too), that material will be still pointing to a non-existent object. So, just before destroying the dshow object, you might need to remove that texture from the material.

And that's probably it.

Edit:

The code you need to undo the texture selection is this:

Code: Select all

	Ogre::String materialName="MyMaterial";
	if (Ogre::MaterialManager::getSingleton().resourceExists(materialName))
	{
		Ogre::MaterialPtr mat;
		Ogre::TextureUnitState* tex;

		mat=Ogre::MaterialManager::getSingleton().getByName(materialName);
		tex=mat->getTechnique(0)->getPass(0)->getTextureUnitState(0);
		tex->setTextureName(Ogre::String(""));
	}
Use that before destroying the dshow object (should I start managing this from inside the dshow object, so that the user code doesn't get this oscure? maybe...).
H. Hernan Moraldo
Personal website

wetzeljipi
Gnoblar
Posts: 2
Joined: Wed Jan 31, 2007 9:43 am

Post by wetzeljipi »

My program don't work, I think I do something wrong. When I compil my program I have this error message :
"
1>------ Début de la régénération globale : Projet : Demo_RenderToTexture, Configuration : Debug Win32 ------
1>Suppression des fichiers de sortie et des fichiers intermédiaires du projet 'Demo_RenderToTexture', configuration 'Debug|Win32'
1>Compilation en cours...
1>RenderToTexture.cpp
1>UtilsOgreDshow.cpp
1>c:\ogresdk\samples\scripts\utilsogredshow.cpp(357) : warning C4018: '<' : incompatibilité signed/unsigned
1>c:\ogresdk\samples\scripts\utilsogredshow.cpp(358) : warning C4267: '=' : conversion de 'size_t' en 'unsigned int', perte possible de données
1>c:\ogresdk\samples\scripts\utilsogredshow.cpp(409) : warning C4267: '=' : conversion de 'size_t' en 'unsigned int', perte possible de données
1>Génération de code en cours...
1>Compilation du manifeste en ressources en cours...
1>Édition des liens en cours...
1>UtilsOgreDshow.obj : error LNK2001: symbole externe non résolu _IID_IVideoWindow
1>UtilsOgreDshow.obj : error LNK2001: symbole externe non résolu _FORMAT_VideoInfo
1>UtilsOgreDshow.obj : error LNK2001: symbole externe non résolu _MEDIASUBTYPE_RGB24
1>UtilsOgreDshow.obj : error LNK2001: symbole externe non résolu _MEDIATYPE_Video
1>UtilsOgreDshow.obj : error LNK2001: symbole externe non résolu _IID_ISampleGrabber
1>UtilsOgreDshow.obj : error LNK2001: symbole externe non résolu _CLSID_SampleGrabber
1>UtilsOgreDshow.obj : error LNK2001: symbole externe non résolu _IID_IBaseFilter
1>UtilsOgreDshow.obj : error LNK2001: symbole externe non résolu _IID_IMediaSeeking
1>UtilsOgreDshow.obj : error LNK2001: symbole externe non résolu _IID_IMediaEvent
1>UtilsOgreDshow.obj : error LNK2001: symbole externe non résolu _IID_IMediaControl
1>UtilsOgreDshow.obj : error LNK2001: symbole externe non résolu _CLSID_FilterGraph
1>UtilsOgreDshow.obj : error LNK2001: symbole externe non résolu _IID_IGraphBuilder
1>..\..\bin\Debug/Demo_RenderToTexture.exe : fatal error LNK1120: 12 externes non résolus
1>Le journal de génération a été enregistré à l'emplacement "file://c:\OgreSDK\samples\obj\Debug\BuildLog.htm"
1>Demo_RenderToTexture - 13 erreur(s), 3 avertissement(s)

"
the error about the "<" are in this line
// go set all bits...
for (i=0; i<(dsdata->videoWidth*dsdata->videoHeight*3); i+=3){
idx=(x*4)+y*pixelBox.rowPitch*4;

I use VS2005

Thanks
Jean-Paul Wetzel

User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1
Contact:

Post by hmoraldo »

Hi Jean-Paul,

You need to link to Strmiids.lib. You do that by adding that name to the Linker / Input / Additional dependencies in your project properties (both for release and debug).

Also once you get this working, please check on the page in the wiki as I've updated the code a little yesterday, 'inspired' in some comments from odyeiop.
H. Hernan Moraldo
Personal website

User avatar
odyeiop
Halfling
Posts: 97
Joined: Fri Dec 22, 2006 4:56 am
Location: stoney creek

Post by odyeiop »

mat->unload();

That's all I needed and now it works fine =) Once again thank you! This works beautifully.
I'm Immortal as you are Divine.

User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1
Contact:

Post by hmoraldo »

Hmmm... or mat->reload()... any of these would work well. It's a somewhat easier than manually removing the texture from the material.

Thank you!
H. Hernan Moraldo
Personal website

User avatar
odyeiop
Halfling
Posts: 97
Joined: Fri Dec 22, 2006 4:56 am
Location: stoney creek

Post by odyeiop »

I just use the Mat->unload in the exit method of the state, as I only load 1 video when the state is in use. Then switch to another state.

Is there any way that I can retrieve the Position of the movie, and the length of the movie using dsdata?
I'm Immortal as you are Divine.

User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1
Contact:

Post by hmoraldo »

Today I'm not having too much time (I'm finishing a game for a client, and I'm out for a week starting on monday / tuesday)... so I can only give you some pointers.

You'd need to use (if I remember it right), getDuration as this:

Code: Select all

LONGLONG duration;

dsdata->pSeeking->GetDuration(&duration);

// duration now contains the video length
And then:

Code: Select all

LONGLONG position;

dsdata->pSeeking->GetCurrentPosition(&position);

// position now contains the current video position
This would be enough for calculating what is the proportion between played video and total duration of it.

If you need more (ie, to know how many milliseconds you still need to play until finishing a video), you have to use IMediaSeeking::SetTimeFormat (look for its documentation on the Microsoft website).

I hope that helps.
H. Hernan Moraldo
Personal website

User avatar
odyeiop
Halfling
Posts: 97
Joined: Fri Dec 22, 2006 4:56 am
Location: stoney creek

Post by odyeiop »

in UtilsOgreDshow.cpp
bool DirectShowMovieTexture::checkForDone()
{
LONGLONG duration;
LONGLONG position;

dsdata->pSeeking->GetDuration(&duration);
// duration now contains the video length

dsdata->pSeeking->GetCurrentPosition(&position);
// position now contains the current video position

if(position==duration)return true;
return false;
}
in UtilsOgreDshow.h
...
bool checkForDone();
...
in the Movie State
if(mMovie->checkForDone())
//exit state
else
mMovie->updateMovieTexture();
Works =) Once again, thank you so much.
I'm Immortal as you are Divine.

User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1
Contact:

Post by hmoraldo »

Thank you! When I'm back from my small vacations I'll add that to the code.
H. Hernan Moraldo
Personal website

User avatar
ahmedali
Gnome
Posts: 302
Joined: Fri Feb 20, 2004 8:52 pm
Location: Lahore, Pakistan

CRASH!!

Post by ahmedali »

The app is only workin ok with WMV files. It crashes with Mpeg2 and Xvid files.

My app crashes at line, the function GetConnectedMediaType does not return

// get video information
AM_MEDIA_TYPE mtt=mt;
->> hr=dsdata->pGrabber->GetConnectedMediaType(&mtt);

User avatar
odyeiop
Halfling
Posts: 97
Joined: Fri Dec 22, 2006 4:56 am
Location: stoney creek

Post by odyeiop »

I've only tried it with AVI files and they work fine.
I'm Immortal as you are Divine.

User avatar
ahmedali
Gnome
Posts: 302
Joined: Fri Feb 20, 2004 8:52 pm
Location: Lahore, Pakistan

Post by ahmedali »

odyeiop wrote:I've only tried it with AVI files and they work fine.
I tested AVI of both simple/cinepak? and xvid codecs. But the xvid avi crashes aslong with mpeg2.

It seems the code posted is not creating dshow filters suitable for installed codecs like mpeg2 and xvid.

User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1
Contact:

Post by hmoraldo »

I'm just coming back from vacations... I'll be fully back here in about a week.

Does your Windows Media Player play the same files the Dshow code is failing to play? In my experience, I haven't had any problems playing anything the installed Windows Media Player gets ok.
H. Hernan Moraldo
Personal website

User avatar
ahmedali
Gnome
Posts: 302
Joined: Fri Feb 20, 2004 8:52 pm
Location: Lahore, Pakistan

Post by ahmedali »

My Wmplayer can play both xvid and mpeg2. Both of these codecs are not preinstalled on windows. Can u play mpeg2/xvid files on ur wmplayer.

User avatar
ahmedali
Gnome
Posts: 302
Joined: Fri Feb 20, 2004 8:52 pm
Location: Lahore, Pakistan

Post by ahmedali »

I a newbie to DShow but after reading the docs I think you are using a more manual way to build filter graph. According to SDK docs there are some "intellegent" graph building ways, in which DS itself figures out which filters to use for some codecs.

I opened the xvid AVI file in GraphEdit and it connected these filters.

Image

And following when rendering mpeg2 files

Image

I think its the RenderStream function of CaptureGraphBuilder2 class that can build filters for all registered codecs.

User avatar
ahmedali
Gnome
Posts: 302
Joined: Fri Feb 20, 2004 8:52 pm
Location: Lahore, Pakistan

Post by ahmedali »

It seems I found the problem. I tried connecting Xvid/Mpeg2 filters output pins to the inputs of SampleGraber filter. But they cannot be connected as they are incompatible. I solved the xvid problem by turning the compatibility option on in its decoder properties. But the mpeg2 problem remains.

May be because there are some limitations with the SampleGraber filter. As docs say..
For video types, it requires a VIDEOINFOHEADER format. It cannot connect to filters that require other format types, such as VIDEOINFOHEADER2 or DVINFO. Therefore, it is not compatible with MPEG-2 or DV video, or with field-based video.
Is there any alternative to SampleGraber filter aproach ? (btw the source for grabber is provided)

User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Post by KungFooMasta »

First off, I'd like to say this DShow Addon is awesome! I was really excited to see a movie playing in OGRE! :D

I have some questions:

How do I get the movie to stretch to the size of the screen?

Image

My Code:

Code: Select all

mOverlayMaterial = Ogre::MaterialManager::getSingletonPtr()->create("MovieMaterial",Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
	mOverlayMaterial->getTechnique(0)->getPass(0)->createTextureUnitState();
	mOverlayMaterial->load();
	mDShowMovieTexture = new OgreUtils::DirectShowMovieTexture(mWindow->getWidth(), mWindow->getHeight());

	mOverlayMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(mDShowMovieTexture->getMovieTexture()->getName());

...

// Create Panel, Overlay, and Show the Overlay
	Ogre::OverlayManager* OM = Ogre::OverlayManager::getSingletonPtr(); 

	if( mOPanel == NULL )
	{
		// Create a panel 
		mOPanel = static_cast<Ogre::OverlayContainer*>( 
			OM->createOverlayElement("Panel", "MoviePanel")); 
	}

	mOPanel->setMetricsMode(Ogre::GMM_PIXELS); 
	mOPanel->setPosition(0, 0); 
	// Set Size to be the whole window
	mOPanel->setDimensions(mWindow->getWidth(), mWindow->getHeight());

	mOPanel->setColour(Ogre::ColourValue(1.0,1.0,1.0,1.0)); 

	mDShowMovieTexture->loadMovie(mMoviePath);

	mOPanel->setMaterialName(mOverlayMaterial.get()->getName());

	mDShowMovieTexture->playMovie();

	// Create an overlay, and add the panel 
	if( mOverlay == NULL )
		mOverlay = OM->create("MovieOverlay"); 

	mOverlay->add2D(mOPanel); 
	mOverlay->show(); 
I'm pretty sure my overlay is the right size, since applying a normal material covers the entire screen.

Also, can you load movies from relative paths, or even better, Resource locations?

Thanks in Advance,

KungFooMasta

genva
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 1603
Joined: Wed Oct 20, 2004 7:54 am
Location: Beijing, China

Post by genva »

How do I get the movie to stretch to the size of the screen?
I think should be add:

Code: Select all

mOPanel->setUV(0, 0,
 (Real) mWindow->getWidth() / mDShowMovieTexture->getMovieTexture()->getWidth(),
 (Real) mWindow->getHeight() / mDShowMovieTexture->getMovieTexture()->getHeight());

User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Post by KungFooMasta »

Weird.. I'm not seeing "setUV" as a function.

I checked the API docs and its there also. I grabbed from CVS and it doesn't seem to be showing up. When was this added? I'll have to look into this tomorrow.. maybe something is up with my libs and includes..

KungFooMasta

genva
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 1603
Joined: Wed Oct 20, 2004 7:54 am
Location: Beijing, China

Post by genva »

Sorry, it's need to cast mOPanel to PanelOverlayElement*. I was oversight in previous post.

User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1
Contact:

Post by hmoraldo »

Thank you for your comments! Sure you can do fullscreen, just by making the material cover the entire area, in this case the entire overlay (in the way genva explained in his post); and about the resource loading stuff, I guess that shouldn't be difficult to do, but I haven't checked it well.

About relative paths, that's easier, and I manage that just like this:

Code: Select all

	Ogre::String programPath;
	#ifdef _WINDOWS
		const int currentDirectorySize=400;
		char currentDirectory[currentDirectorySize];
		GetCurrentDirectory(currentDirectorySize, currentDirectory);
		programPath=currentDirectory;
	#else
		programPath=".\\";
	#endif
(the non-windows alterlative isn't the best, but it worked for the project this code was for)

----

And also:

I wanted to announce that for a while I'll be very busy with some other stuff, so I'm not sure I'll be coding new stuff for the 2d sprite manager (and the dshow stuff here) in some time. Please if you have questions or problems, ask them here and I'll try to see how I can help in my spare time.

Sorry for that :|
H. Hernan Moraldo
Personal website

User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Post by KungFooMasta »

Its not working for me. :(

Code: Select all

	// Create Panel, Overlay, and Show the Overlay
	Ogre::OverlayManager* OM = Ogre::OverlayManager::getSingletonPtr(); 

	if( mOPanel == NULL )
	{
		// Create a panel 
		mOPanel = static_cast<Ogre::OverlayContainer*>( 
			OM->createOverlayElement("Panel", "MoviePanel")); 
	}

	mOPanel->setColour(Ogre::ColourValue(1.0,1.0,1.0,1.0)); 

	mDShowMovieTexture->loadMovie(mMoviePath);

	mOPanel->setMaterialName(mOverlayMaterial.get()->getName());

	mDShowMovieTexture->playMovie();

	// Set Size to be the whole window
	dynamic_cast<Ogre::PanelOverlayElement*>(mOPanel)->setUV(0,0,
	(Ogre::Real) mWindow->getWidth() / mDShowMovieTexture->getMovieTexture()->getWidth(),
	(Ogre::Real) mWindow->getHeight() / mDShowMovieTexture->getMovieTexture()->getHeight());

	// Create an overlay, and add the panel 
	if( mOverlay == NULL )
		mOverlay = OM->create("MovieOverlay"); 

	mOverlay->add2D(mOPanel); 
	mOverlay->show();
I've tried moving the call to setUV around, but nothing changes. The movie just plays in the top left corner.

Any help is appreciated.

KungFooMasta

User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1
Contact:

Post by hmoraldo »

Actually, you need the overlay to cover the full screen, and the texture to cover the full overlay. So the overlay uv for the right bottom corner has to be 1, 1. However, maybe you are using it with dontModifyDimensions=false; and then your computer might be generating a texture that is bigger than what you use for playing the movie. In such a case, you have to make sure the uv values are smaller, so to make the borders of the movie coincide with those of the overlay. But I don't think this is your case.

Can you post your ogre.log here? (at least the lines starting with [DSHOW]) And can you do a simple test? Please set the window background color to something else, like red, so that you can be sure you are setting the overlay to the size it should has, and not to other. Then, if that's ok, test this too: what happens if you put another texture there, instead of the dshow one, what do you see then? Do you see the texture covering the full screen, or do you see it just as with the video?
H. Hernan Moraldo
Personal website

User avatar
KungFooMasta
OGRE Contributor
OGRE Contributor
Posts: 2087
Joined: Thu Mar 03, 2005 7:11 am
Location: WA, USA
x 16
Contact:

Post by KungFooMasta »

From the log:

Code: Select all

15:58:36: Viewport for camera 'System_Movie_Camera', actual dimensions L: 0 T: 0 W: 1280 H: 1016
15:58:36: [DSHOW] Loading movie named 'C:/Ugly.Betty.S01E14.HDTV.XviD-XOR.avi'.
15:58:36: [DSHOW] -> This movie has dimensions: 608x336.
(Ugly Betty is for my gf to watch! Although it is an interesting show :P )

I am re-using code from my splash window, but I went ahead and verified that applied another plan material (Just a jpg file) covered the whole screen correctly.

This is my code at the moment:

Code: Select all

	mOverlayMaterial = Ogre::MaterialManager::getSingletonPtr()->create("MovieMaterial",Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
	mOverlayMaterial->getTechnique(0)->getPass(0)->createTextureUnitState();
	mOverlayMaterial->load();
	mDShowMovieTexture = new OgreUtils::DirectShowMovieTexture(mWindow->getWidth(), mWindow->getHeight(), false);

	mOverlayMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(mDShowMovieTexture->getMovieTexture()->getName());

...

	// Create Panel, Overlay, and Show the Overlay
	Ogre::OverlayManager* OM = Ogre::OverlayManager::getSingletonPtr(); 

	if( mOPanel == NULL )
	{
		// Create a panel 
		mOPanel = static_cast<Ogre::OverlayContainer*>( 
			OM->createOverlayElement("Panel", "MoviePanel")); 
	}

	mOPanel->setPosition(0.0,0.0);
	mOPanel->setDimensions(1.0,1.0);
	mOPanel->setColour(Ogre::ColourValue(1.0,1.0,1.0,1.0)); 

	mDShowMovieTexture->loadMovie(mMoviePath);
	Ogre::Vector2 v2 = mDShowMovieTexture->getMovieDimensions();

	mOPanel->setMaterialName(mOverlayMaterial.get()->getName());
//	mOPanel->setMaterialName("UV_FirstSplash");

	mDShowMovieTexture->playMovie();

/*
	// Set Size to be the whole window
	dynamic_cast<Ogre::PanelOverlayElement*>(mOPanel)->setUV(0,0,
	(Ogre::Real) mWindow->getWidth() / mDShowMovieTexture->getMovieTexture()->getWidth(),
	(Ogre::Real) mWindow->getHeight() / mDShowMovieTexture->getMovieTexture()->getHeight());
*/
	// Create an overlay, and add the panel 
	if( mOverlay == NULL )
		mOverlay = OM->create("MovieOverlay"); 

	mOverlay->add2D(mOPanel); 
	mOverlay->show();
Also, I have a possible dumb question. I didn't install the Win 2003 SDK, instead I used required pieces I found from the wmv plugin which included dshow.h, and the lib I needed to link to. Could this be the problem?

The reason I did this is because I need to know exactly what libs/includes are used, as I update a personal SDK for others on my team to use. I'm unsure what the 2003 SDK installs, and it would seem difficult to browse through and figure out what bits belong to dshow and its dependencies. I could just force everybody to install this 2003 SDK..

KungFooMasta

-For reassurance, this 2003 R2 SDK is appropriate for winXP using VS2005SP1 + update?

User avatar
hmoraldo
OGRE Expert User
OGRE Expert User
Posts: 517
Joined: Tue Mar 07, 2006 11:22 pm
Location: Buenos Aires, Argentina
x 1
Contact:

Post by hmoraldo »

Don't you have a line starting with "[DSHOW] Creating texture with dimensions "? If you have it, please post it; otherwise, update your dshow code to the one in the wiki: http://www.ogre3d.org/wiki/index.php/Di ... re_texture as that might solve your problem (and if not, please post the log lines again after such change).

The last version of the the code has a line telling:

Code: Select all

#define __FILE_UTILSOGREDSHOW_VERSION "1-30-2007b"
in UtilsOgreDshow.h; check that before updating. Also update it if you find your code version is different to that one.

Hope that helps...

Edit: why did the page got so wide with this post?? I couldn't solve that even removing the code line.
H. Hernan Moraldo
Personal website

Post Reply