Playing movie in texture

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
funcdoobiest
Posts: 48
Joined: Thu Jun 15, 2006 6:35 pm

Post by funcdoobiest »

thanks for all the video stuff guys, its very useful but I am having one or two problems I am hoping you can help with.

I wanted to draw simple fullscreen movies as 2d images (rather than messing around trying to align the camera and a quad).

So I created my own class which extends the TMovieMesh class created by Emil in this http://www.irrforge.org/index.php/Playi ... in_texture example.

All I have done is overide the render() function, my class looks like so:

(TMovieMesh has been renamed MovieMesh)

Code: Select all

class FSMovie : public MovieMesh
{
public:
	FSMovie(irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id): MovieMesh(parent, mgr, id)
	{

	}
private:

	virtual void render()
	{   
		DrawMovie(0,0,Material.Texture1);
		irr::video::IVideoDriver* driver = SceneManager->getVideoDriver(); 

		//take the movie part of the texture
		irr::core::rect<s32> texrect;
		texrect.UpperLeftCorner.X=0;
		texrect.UpperLeftCorner.Y=0;
		texrect.LowerRightCorner.X=MovieWidth();
		texrect.LowerRightCorner.Y=MovieHeight();

		//get the veiwport dimensions to render to
		core::rect<s32> viewrect(driver->getViewPort());
		//core::rect<s32> viewrect(0,0,256,256);

		//use full colour and opacity
		video::SColor colours[4];
		colours[0].set(255,255,255,255);
		colours[1].set(255,255,255,255);
		colours[2].set(255,255,255,255);
		colours[3].set(255,255,255,255);

		char tmp[255];
		//core::vector3df pos = device->getSceneManager()->getActiveCamera()->getAbsolutePosition();
		sprintf_s(tmp, sizeof(tmp), "VP Dimensions: ULX %d, ULY %d, LRX %d, LRY %d\n", viewrect.UpperLeftCorner.X, viewrect.UpperLeftCorner.Y, viewrect.LowerRightCorner.X, viewrect.LowerRightCorner.Y);
		//sceneStartTime - device->getTimer()->getTime());
		OutputDebugString(tmp);

		//function doesn't work with software rendering
		driver->draw2DImage(Material.Texture1,viewrect,texrect,0,0,false);
	}
};
when I run the movie in a windowed app it works fine but whne I try and run it in fullscreen it displays the video squashed in to the left half of the screen and the colours look as if somebody has applied a thermal imaging filter(or something similar) to them! The video plays from start to finish and the sound is fine.

I have run the fullscreen (and windowed version) at resolutions from 640x480 - 1280x1024 and always get the same results.
funcdoobiest
Posts: 48
Joined: Thu Jun 15, 2006 6:35 pm

Post by funcdoobiest »

Right well i figured after that maybe my problem was due to a difference between the colour format used in windowed and fullscreen modes (windowed adopts the format currently specified, fullscreen changes it to the one specifed in createDevice) and that that it was maybe causing half my information to be lost (32 being truncated to 16 for example) in the memcopy taking place in DrawMovie().

Code: Select all

	void DrawMovie(int x,int y,irr::video::ITexture* Buf)
	{   
		void* pBits = Buf->lock();
		LONG  Pitch = Buf->getPitch(); 
		DDSURFACEDESC  ddsd; 
		ddsd.dwSize=sizeof(DDSURFACEDESC);
		pSurface->Lock( NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT , NULL); 
		int wmin=(Pitch<ddsd.lPitch)?Pitch:ddsd.lPitch;
		for(int h=0; h<ddsd.dwHeight; h++) 
			memcpy((BYTE*)pBits+((y+h)*Pitch)+x*4,(BYTE*)ddsd.lpSurface+h*ddsd.lPitch,wmin);
		pSurface->Unlock(NULL);
		Buf->unlock();
}
but it turns out that my fullscreen is being set to use 32 bits, just as my desktop and therefore my winodwed app. however if I change my desktop to 16 bit I get the exact same effect as I the problem I am having when I go fullscreen?

Also when I check the various values used in DrawMovie, I am getting all the same values out of the texture buffer and surface in windowed and full screen, except for the surface pitch which is SMALLER in fullscreen. I get 1280 in windowed and 640 in fullscreen!? which I would maybe expect if my window used 32 bits and my fullscreen 16 but they are both supposed to be using 32!? Anyone have any ideas?
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Hehe, yeah Emil refused to use the color format information given by the textures which also broke his library with Irrlicht 1.1 for the first. Just check the color format and you'll know how many bytes per pixel (there are methods for such informations) and how long a line is etc.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Irrlicht should probably expose some functions for converting from one raw image format to the other [similar to what is in the CColorConverter class already]. It gets very old seeing people trying to write the same color format conversion code over and over again.
evo
Posts: 96
Joined: Mon Jun 27, 2005 6:46 pm
Location: The Netherlands

Post by evo »

funcdoobiest wrote:Right well i figured after that maybe my problem was due to a difference between the colour format used in windowed and fullscreen modes (windowed adopts the format currently specified, fullscreen changes it to the one specifed in createDevice)
It should not matter which color mode you choose for you irr-device. Only the colorformat of the ITexture that the movieplayer uses to copy images onto. So force the texture to 32-bit.

Code: Select all

video::ITexture* movTxtr = irrVideo->addTexture(core::dimension2d<s32>(xres,yres), "movie", video::ECF_A8R8G8B8);
funcdoobiest
Posts: 48
Joined: Thu Jun 15, 2006 6:35 pm

Post by funcdoobiest »

Well I meant the difference bewtween the directdraw surface and the texture, rather than 2 textures (all my textures are 32-bit), I assumed directx would set the surface to the same colour mode as the irr-device.

Anyway i have looked around and it seems that I am getting a 16-bit surface when I go into fullscreen mode. I thought maybe this was becasue the surface is never actually created with IDirectDrawSurface::CreateSurface(), and is just used without being 'initialised' here:

Code: Select all

pSample->GetSurface(&pSurface,&Movie_rect);
so i changed it to do all the surface creation stuff first and set the RGBBitCount to 32 and then called the function above. But after the GetSurface() call the RGBBitCount of pSurface seems to have been reset to 16 and I have no idea why. (in fact if I set the RGBBitCount to something other than 32-bit in window mode it resets it to 32). i have no idea wether you are meant to initialise the surfce first in this situation but i do know I am getting a 16-bit surface when I need a 32-bit and I don't know how to fix it!?
funcdoobiest
Posts: 48
Joined: Thu Jun 15, 2006 6:35 pm

Post by funcdoobiest »

PS - thanks for your replies
evo
Posts: 96
Joined: Mon Jun 27, 2005 6:46 pm
Location: The Netherlands

Post by evo »

evo wrote:To be continued ... after some vacation time :D
Evo
Well, here is the continuing story. I have added functionality for playing sound, using Audiere (tested with 1.9.4).
I have tried to implement some kind of buffering of the sound data (load and play 1 second at a time), but got crappy results. So I used the next best thing: loading all of the sound data at once. This obviously has it's drawbacks in use of memory. (My 30Mb test avi loads quick enough though)
The advantage is near perfect synchronization of audio and video.

I did have to modify the GetNextFrame and SetMovieFPS function to get the video timing right. The previous version was very inaccurate. Emil: this is likely to be the case in the DirectShow code aswell !

Another change I made was the interface. The ouput ITexture is now created by the movieplayer. The textures x/y dimensions are taken from the avi file and round up to the next power of 2.
The video-framerate is now calculated from the avi file, but may be set by the user.

You can download the class here: http://home.wanadoo.nl/iherweij/download/AVIPlayer.zip as allways, try again later in case of 403 errors due to my limited download quota.
Emil_halim
Posts: 518
Joined: Tue Mar 29, 2005 9:02 pm
Location: Alex,Egypt
Contact:

Post by Emil_halim »

@funcdoobiest

did you take a look for DirectShow in help file and see if it allows to specify the depth of the surface or not, if i have time i will dig and see how to solve that problem.


@evo

welcome back ,hope you got some funy times.

actually in may last version of magic Library { ver 1.1 } i have changed the LoadMovie function so that allows to play the movie with sound , here the prototype of the function

virtual void LoadMovie(char* filename,bool useCLOCK =false, bool useAUDIO = false);

useCLOCK allows to play movie with it's orignal FPS then SetMovieFPS function will be useless

useAUDIO allows to play movie with the sound in the Orignal FPS

see the PlayingMovie demo it playes MPEG movie with sound " see how dogs love to smoke :lol: "

here is the demo

Code: Select all

/************************************
         how to play movie
            with sound
           By Emil Halim
*************************************/


#include <MagicIncludes.h>


// global declration of Irrlicht interfaces
IrrlichtDevice* device;
IVideoDriver*   driver;
ISceneManager*  smgr;

bool ProgramRun;

#define TextureWidth  1024
#define TextureHeight 1024

class CSampleSceneNode : public ISceneNode
{
    aabbox3d<f32> Box;
    SMaterial Material;

   public:
    S3DVertex Vertices[4];

    CSampleSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,f32 u, f32 v): ISceneNode(parent, mgr, id)
    {
        Material.Wireframe = false;
        Material.Lighting = false;
        Vertices[0] = S3DVertex(-10,-10,0, 0,0,0,SColor(255,255,255,255),0,v);
        Vertices[1] = S3DVertex( 10,-10,0, 0,0,0,SColor(255,255,255,255),u,v);
        Vertices[2] = S3DVertex( 10, 10,0, 0,0,0,SColor(255,255,255,255),u,0);
        Vertices[3] = S3DVertex(-10, 10,0, 0,0,0,SColor(255,255,255,255),0,0);

        Box.reset(Vertices[0].Pos);
        for (s32 i=1; i<4; ++i)  Box.addInternalPoint(Vertices[i].Pos);
    }

    virtual void OnPreRender()
    {
        if (IsVisible)    SceneManager->registerNodeForRendering(this);
        ISceneNode::OnPreRender();
    }

    virtual void render()
    {
        u16 indices[] = { 0,1,3, 3,1,2, 1,0,2, 2,0,3 };
        IVideoDriver* driver = SceneManager->getVideoDriver();
        driver->setMaterial(Material);
        SetBlend(ALPHABLEND);
        driver->setTransform(ETS_WORLD, AbsoluteTransformation);
        driver->drawIndexedTriangleList(&Vertices[0], 4, &indices[0], 4);
    }

    virtual const aabbox3d<f32>& getBoundingBox() const
    {
        return Box;
    }

    virtual s32 getMaterialCount()
    {
        return 1;
    }

    virtual SMaterial& getMaterial(s32 i)
    {
        return Material;
    }
};

int main()
{
    device = createDevice(EDT_OPENGL, dimension2d<s32>(640, 480), 32);
    bool rslt = InitMagic(device);
    if(rslt == false)
          printf("Magic Library will only work with OpenGL driver");

	driver = device->getVideoDriver();
	smgr = device->getSceneManager();

    TMovie* movie=new TMovie;
    movie->LoadMovie("../../MagicLibrary/media/dog.DAT",true,true);
   // movie->SetMovieFPS(10);
    movie->SetLooped(true);

    driver->setTextureCreationFlag(ETCF_ALWAYS_32_BIT,TRUE);
    driver->setTextureCreationFlag(ETCF_CREATE_MIP_MAPS,FALSE);
    ITexture* movTxtr = driver->addTexture(dimension2d<s32>(TextureWidth,TextureHeight),"",ECF_A8R8G8B8);
    smgr->addCameraSceneNode(0,vector3df(0,0,-30),vector3df(0,0,0));
    f32 U = (f32)movie->MovieWidth() / (f32)TextureWidth;
    f32 V = (f32)movie->MovieHeight() / (f32)TextureHeight;
    CSampleSceneNode* myNode=new CSampleSceneNode(smgr->getRootSceneNode(),smgr,666,U,V);
    myNode->setMaterialTexture(0,movTxtr);
    myNode->setMaterialType(EMT_TRANSPARENT_VERTEX_ALPHA);
    myNode->setPosition(vector3df(0,5,0));
    myNode->setScale(vector3df(2.5,0.75f,0));

    ProgramRun = true;
    int lastFPS = -1;

	while(device->run()&& ProgramRun)
	{

		driver->beginScene(true, true, SColor(0,200,0,0));

                 if(KeyDown(KEY_ESCAPE))ProgramRun=false;

                 movie->NextMovieFrame();
                 movie->DrawMovie(0,0,movTxtr);

                 smgr->drawAll();

		driver->endScene();
		int fps = driver->getFPS();
         if (lastFPS != fps)
         {
            wchar_t tmp[1024];
            swprintf(tmp, 1024, L"how to play movie Example (%s)(fps:%d)",driver->getName(), fps);
            device->setWindowCaption(tmp);
            lastFPS = fps;
         }
	}

	device->drop();

	return 0;
}

the only drawback is when you use the movie with sound you are limit to 25 FPS for your entire scene.
evo
Posts: 96
Joined: Mon Jun 27, 2005 6:46 pm
Location: The Netherlands

Post by evo »

welcome back ,hope you got some funy times.
Thanks. Vacation had a bit of a bad start, but it ended OK.
actually in may last version of magic Library { ver 1.1 } i have changed the LoadMovie function so that allows to play the movie with sound , here the prototype of the function
That is good news. I tried the example. Odd thing is that I only got sound and no images. Also I had to copy the .exe to the folder 'Examples' in order for it to find the media files. Funny dog indeed.

The mirror example is also very nice. The 'Play_3_Movies' example only gets ~7 FPS. Why is that?


I will develop my avi wrapper a bit further untill it meets my needs and plan to release a demo (much) later.
Emil_halim
Posts: 518
Joined: Tue Mar 29, 2005 9:02 pm
Location: Alex,Egypt
Contact:

Post by Emil_halim »

I tried the example. Odd thing is that I only got sound and no images. Also I had to copy the .exe to the folder 'Examples' in order for it to find the media files. Funny dog indeed.
very strange, i think that no images displayed may be because some thing with directshow in your system.

you have to copy the exe file in the bin folder of irrlicht where irrlicht dll existes , it will find the correct path of media files.
The 'Play_3_Movies' example only gets ~7 FPS. Why is that?
in my system i got 40 FPS , P4 2.4 GH - Gforce 5200fx.
BTW, in this demo did you see the entire three movie or like the previous
demo no images.


I will develop my avi wrapper a bit further untill it meets my needs and plan to release a demo (much) later.
waitting for that wrapper, hope you do it sooner.
funcdoobiest
Posts: 48
Joined: Thu Jun 15, 2006 6:35 pm

Post by funcdoobiest »

Hi Emil,

Not yet I haven't had much time to look at any movie stuff sonce my last post but I will, the movie stuff is going on the backburner momentarily unitl I get some more pressing stuff out the way!!

Evo, thanks for the class, I haven't taken aproper look yet but will when I get back to the movie stuff.
evo
Posts: 96
Joined: Mon Jun 27, 2005 6:46 pm
Location: The Netherlands

Post by evo »

Emil_halim wrote:very strange, i think that no images displayed may be because some thing with directshow in your system.

in my system i got 40 FPS , P4 2.4 GH - Gforce 5200fx.
BTW, in this demo did you see the entire three movie or like the previous
demo no images.
Strange indeed. The dog video plays fine in mediaplayer (V10). DShow uses the same codec's as mediaplayer ??

In all other examples the video's were perfectly visible.
funcdoobiest
Posts: 48
Joined: Thu Jun 15, 2006 6:35 pm

Post by funcdoobiest »

Okay so I made the foolish assumption that my problem when using Emil's class was caused by the call to GetSurface() but after some more playing around I have found that my D3D device actually seems to be using 16 bit colour

Code: Select all

	//Create game device
	device = createDevice(driverType, core::dimension2d<s32>(1280, 1024), 32, fullscreen, shadows, vsync, this);
			
	char tmp[255];
	IDirect3DDevice9* D3DDev = device->getVideoDriver()->getExposedVideoData().D3D9.D3DDev9;
	D3DDISPLAYMODE displayMode;
	D3DDev->GetDisplayMode(0, &displayMode);
	sprintf_s(tmp, sizeof(tmp), "Display Mode Format %d\n", displayMode.Format);
	OutputDebugString(tmp);
the above code tells me in the output that the display mode format is 16 bit, even immediately after I have created the device (ie. as far as I can tell I can't have done anything to change it yet). I have looked at the creation of the device in the engine and can see no reason I would not get the device as requested, I have aslo checked my dislpay adaptor in the DX Caps Viewer just to make sure the resolution and pixel format are supposrted (as expected, they are). As before the same thing happens in reverse with the windowed app - I get a 32 bit device no matter what I ask (doesn't Irrlicht ignore request for a 32-bit format if its windowed?).

Any suggestions where I may be going wrong?

I am using the April 06 DX SDK and Irrlicht 1.0 (only just noticed this, should try an upgrade eh?!)

P.S. It works fine if I use OpenGL
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Windows take the depth of the desktop AFAIK. For Windows Fullscreen I don't know.
Post Reply