Displaying a png frame sequence.

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
neil_123
Posts: 67
Joined: Wed Apr 07, 2010 8:50 pm

Displaying a png frame sequence.

Post by neil_123 »

I want to display a series of png images in order to simulate a video play. Here is what I am doing,

Code: Select all


ITexture       *images;
char            file_name[128];
int                num_frms, frm;

  frm = 0;
  
  while(device->run() && driver)
  {
     
    if(++frm >= num_frms)
      frm = 0;

    strcpy(file_name, SEQ_DIR);
    strcat(file_name, seq[frm]);

    images = driver->getTexture(file_name);
    
    driver->beginScene(true, true, SColor(255, 120, 102, 136) );

    driver->draw2DImage(images, position2d<s32>(0, 0), rect<s32>(0, 0, 448, 640), 0, SColor(255, 255, 255, 255), true);


    usleep(20*1000);
                                                    
    driver->endScene();

    
    device->yield();
  }

neil_123
Posts: 67
Joined: Wed Apr 07, 2010 8:50 pm

Post by neil_123 »

I am sorry, the above message got posted pre-maturely.

This program works,

But my question is, in this approach, shouldn't we be de-allocating memory for the texture generated from each png file? Other wise it seems to me, there is memory leak here, and there will be maximum limit on the number of frames that can be displayed in the sequence.

In SDL, you call SDL_FreeSurface after each "blit", is there a parellel method in irrlicht?

Any pointers will be appreciated.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Two things, no three: First of all put your usleep after endScene. Otherwise you get an off by one glitch, as the first image is rendered after the first wait (endScene is what makes the rendering appear on the screen).
Then, you should check the texture cache in Irrlicht. Since you use a method with 'add', you cannot drop that pointer. Instead, you can ask the texture cache to remove the texture in question.
Third, point two will introduce a heavy lag in your application. Simply because you ask the GPU to remove all the stuff and reallocate new textures each frame. It's better to lock the texture and render the image into the texture manually. This at least avoids all this overhead. A slight complication could occur because Irrlicht does not support 'write-only' textures. Hence, the old texture is also downloaded each time from GPU to CPU. You could check which method is faster for you.
neil_123
Posts: 67
Joined: Wed Apr 07, 2010 8:50 pm

Post by neil_123 »

Thanks hybrid,

I am afraid you over-estimated my knowledge of Irrlicht,

I didnt get what you meant by "Since you use a method with 'add', "

I am using draw2DImage() method.

Is this better to use IImage class in this kind of situations, since all I want is just load an image file and display it on screen, seems fairly simple operation.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Oh sorry, I thought you create the texture with addTexture. But getTexture basically does the same. The point is that a hardware texture is created each time this method is called with a new name. So you have to clean up afterwards.
You cannot render an image to the screen, it has to become a texture at some point (which is simply an image usable on the GPU).
Bate
Posts: 364
Joined: Sun Nov 01, 2009 11:39 pm
Location: Germany

Post by Bate »

Why not convert the sequence to a real video format? Then you can use this video player. If you don't wanna do that, you can still have a look into the source to get an idea of how to access and copy image data.
Never take advice from someone who likes to give advice, so take my advice and don't take it.
neil_123
Posts: 67
Joined: Wed Apr 07, 2010 8:50 pm

Post by neil_123 »

Thanks Bate,

Does this player work only on Windows or it can work on Linux also?
neil_123
Posts: 67
Joined: Wed Apr 07, 2010 8:50 pm

Post by neil_123 »

hybrid wrote:Oh sorry, I thought you create the texture with addTexture. But getTexture basically does the same. The point is that a hardware texture is created each time this method is called with a new name. So you have to clean up afterwards.
You cannot render an image to the screen, it has to become a texture at some point (which is simply an image usable on the GPU).

So Hybrid,

What you are saying is, there is no way I can display an image on the screen without first creating a texture out of it, and when I create a texture out of image, I will run into all kind of limitations.

Isnt there a way to display an image without involving textures and GPU? So that a series of images can be displayed in quick succession.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

No, of course not. Rendering happens on the GPU. If you want to draw an image pixel by pixel, each pixel goes from CPU to GPU. So it's much better to put the whole image to the GPU at once, and then draw the texture on the GPU.
The problem is that you want to reduce the amount of texture being used. You must optimize this in order to get a responsive app.
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

Last year for a robotics team I was in, I created an application that streamed video using TCP from the robot to an Irrlicht program on a laptop. Instead of creating a new texture for every frame, just lock the texture and memcpy the image onto the texture. You have to do it row-by-row in case the texture isn't the same size as the image (e.g. due to power of two limitations), but even then it's extremely fast and works like a charm.
neil_123
Posts: 67
Joined: Wed Apr 07, 2010 8:50 pm

Post by neil_123 »

Aha,

Thanks slavik262 & hybrid for helpful response. I will try these approaches and report back.

Regards
neil_123
Posts: 67
Joined: Wed Apr 07, 2010 8:50 pm

Post by neil_123 »

Hi slavik262,

This idea of copying pixels directly onto texture sounds interesting and promising. But I need some help in how to actually do it. I looked into the member data fields of ITexture class, but couldnt find any member where I can copy pixel data into.

I would appreciate if you could give me some further pointers as to how to actually do it.

Regards
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

No problem. I'll post the code later today when I get back from classes
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

Enjoy:

Code: Select all

bool TextureManipulator::copyImgToTexture(IImage* img, ITexture* txt)
{
	//We have to be the same color format
	if(img->getColorFormat() != txt->getColorFormat())
	{
		return false;
	}

	//compare dimensions
	dimension2d<u32> tDim = txt->getSize();
	dimension2d<u32> iDim = img->getDimension();

	if(tDim.Width < iDim.Width || tDim.Height < iDim.Height)
		return false;

	//Otherwise start copying
	u32 imgPitch = img->getBytesPerPixel() * iDim.Width;
	u32 txtPitch = txt->getPitch();
	char* txtPtr = (char*)txt->lock();
	char* imgPtr = (char*)img->lock();

	for(u32 c = 0; c < iDim.Height; c++)
	{
		memcpy(txtPtr, imgPtr, imgPitch);

		txtPtr += txtPitch;
		imgPtr += imgPitch;
	}

	txt->unlock();
	img->unlock();

	return true;
}
neil_123
Posts: 67
Joined: Wed Apr 07, 2010 8:50 pm

Post by neil_123 »

Thanks slavik262,
Looks like a good instructional material. I am hoping to learn quite a few things from this.
Post Reply