Dear all:
To play AVI from within OSG, I wrote a simple app. that plays (or should
play) AVI files in OSG. The app. proceeds frame by frame displaying the
AVI contents on a quad inside OSG.
My problem is that only the first frame is generated and shown on the
quad. As soon as the app. steps to another one, it breaks.
Shortly speaking, my sequence is as follows:
- open avi file, stream
- get the first frame
- create the quad, and apply the texture // so far, so good!
- init viewer
loop:
increase frame count
grab the bext frame
apply the texture // frame no. 2 - crash
....
end
It is inside the viewer's loop that the code breaks when I apply the AVI
data (at frame no. 2) to the new image through:
while (!viewer.done())
{
viewer.frame();
frame = ((frame+1)>lastframe) ? 0 : (frame+1);
GrabAVIFrame(frame);
image->allocateImage(256, 256, 1,
GL_RGB, GL_UNSIGNED_BYTE);
// BREAKS HERE
image->setImage(256,256,1,
GL_TEXTURE_2D,GL_RGB,
GL_UNSIGNED_BYTE, data,
osg::Image::USE_NEW_DELETE);
texture->setImage(0,image.get());
}
I have tracked the error down to deallocateData() in Image.cpp. I would
appreciate any advice on how to solve this. The source code that
recreates the error in a simple way is below.
The AVI part comes from the NeHe site.
Again, appreciate any reply on the cause of the problem here.
Rgds, Janusz
-----
/* Code where it breaks: Image.cpp
void Image::deallocateData()
{
if (_data) {
if (_allocationMode==USE_NEW_DELETE) delete [] _data;
else if (_allocationMode==USE_MALLOC_FREE) ::free(_data);
_data = 0;
}
}
*/
#include <windows.h>
#include <iostream>
#include <osgUtil/Optimizer>
#include <osgDB/ReadFile>
#include <osg/TexEnv>
#include <osg/TexGen>
#include <osg/Material>
#include <osg/Geode>
#include <osg/BlendFunc>
#include <osg/Depth>
#include <osg/Projection>
#include <osg/PolygonOffset>
#include <osg/MatrixTransform>
#include <osg/Camera>
#include <osg/FrontFace>
#include <osgText/Text>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/StateSetManipulator>
#include <osgViewer/ViewerEventHandlers>
#include <osgViewer/CompositeViewer>
#include <osg/io_utils>
#include <osg/Texture2D>
#include <osg/TextureRectangle>
#include <vfw.h>
#pragma comment( lib, "vfw32.lib" )
int frame=0;
AVISTREAMINFO psi;
PAVISTREAM pavi;
PGETFRAME pgf;
BITMAPINFOHEADER bmih;
long lastframe;
int width;
int height;
char *pdata;
HDRAWDIB hdd;
HBITMAP hBitmap;
HDC hdc = CreateCompatibleDC(0);
unsigned char* data = 0;
int mpf;
osg::ref_ptr<osg::Texture2D> texture;
osg::ref_ptr<osg::Image> image;
// Flips The Red And Blue Bytes (256x256)
void flipIt(void* buffer)
{
void* b = buffer;
__asm
{
mov ecx, 256*256
mov ebx, b
label:
mov al,[ebx+0]
mov ah,[ebx+2]
mov [ebx+2],al
mov [ebx+0],ah
add ebx,3
dec ecx
jnz label
}
}
void OpenAVI(LPCSTR szFile)
{
AVIFileInit();
hdd = DrawDibOpen();
// Opens The AVI Stream
if (AVIStreamOpenFromFile(&pavi, szFile, streamtypeVIDEO, 0,
OF_READ, NULL) !=0)
{
MessageBox (HWND_DESKTOP, "Failed To Open The AVI Stream",
"Error", MB_OK | MB_ICONEXCLAMATION);
}
AVIStreamInfo(pavi, &psi, sizeof(psi));
width=psi.rcFrame.right-psi.rcFrame.left;
height=psi.rcFrame.bottom-psi.rcFrame.top;
lastframe=AVIStreamLength(pavi);
mpf=AVIStreamSampleToTime(pavi,lastframe)/lastframe;
bmih.biSize = sizeof (BITMAPINFOHEADER);
bmih.biPlanes = 1;
bmih.biBitCount = 24;
bmih.biWidth = 256;
bmih.biHeight = 256;
hBitmap = CreateDIBSection (hdc, (BITMAPINFO*)(&bmih),
DIB_RGB_COLORS, (void**)(&data), NULL, NULL);
SelectObject (hdc, hBitmap);
pgf=AVIStreamGetFrameOpen(pavi, NULL);
if (pgf==NULL)
{
MessageBox (HWND_DESKTOP, "Failed To Open The AVI Frame",
"Error", MB_OK | MB_ICONEXCLAMATION);
}
}
void GrabAVIFrame(int frame)
{
LPBITMAPINFOHEADER lpbi;
lpbi = (LPBITMAPINFOHEADER)AVIStreamGetFrame(pgf, frame);
pdata=(char *)lpbi+lpbi->biSize+lpbi->biClrUsed * sizeof(RGBQUAD);
DrawDibDraw (hdd, hdc, 0, 0, 256, 256, lpbi, pdata, 0, 0, width,
height, 0);
flipIt(data);
}
void CloseAVI(void)
{
DeleteObject(hBitmap);
DrawDibClose(hdd);
AVIStreamGetFrameClose(pgf);
AVIStreamRelease(pavi);
AVIFileExit();
}
/*create a in-memory texture */
osg::StateSet* createInMemoryTextureFromAVI(osg::StateSet* stateset, int
imWidth, int imHeight)
{
unsigned int uiTextureId =0;
// texture mapping part - osg
if (data)
{
texture = new osg::Texture2D;
texture->setDataVariance(osg::Object::DYNAMIC);
texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
texture->setWrap( osg::Texture::WRAP_S,
osg::Texture::CLAMP_TO_BORDER );
texture->setWrap( osg::Texture::WRAP_T,
osg::Texture::CLAMP_TO_BORDER );
texture->setWrap( osg::Texture::WRAP_R,
osg::Texture::CLAMP_TO_BORDER);
texture->setBorderColor( osg::Vec4( 0.0, 0.0, 0.0, 0.0 ) );
texture->setInternalFormat(GL_RGB);
osg::TexEnv* texenv = new osg::TexEnv;
texenv->setMode(osg::TexEnv::BLEND);
image = new osg::Image();
image->setDataVariance(osg::Object::DYNAMIC);
image->allocateImage(imWidth, imHeight, 1,
GL_RGB, GL_UNSIGNED_BYTE);
image->setImage(imWidth,imHeight,1,
GL_TEXTURE_2D,GL_RGB,
GL_UNSIGNED_BYTE, data,
osg::Image::USE_NEW_DELETE);
texture->setUnRefImageDataAfterApply(false);
texture->setImage(uiTextureId,image.get());
stateset->setDataVariance(osg::Object::DYNAMIC);
stateset->setTextureAttribute(uiTextureId,
texenv,osg::StateAttribute::ON);
stateset->setTextureAttributeAndModes(uiTextureId,
texture.get(),osg::StateAttribute::ON);
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
}
return stateset;
}
// osgmovie stuff
osg::ref_ptr<osg::Geometry> myCreateTexturedQuadGeometry(const
osg::Vec3& pos,float width,float height,
bool useTextureRectangle, bool xyPlane, bool option_flip)
{
bool flip=option_flip;
osg::ref_ptr<osg::Geometry> pictureQuad =
osg::createTexturedQuadGeometry(pos,
osg::Vec3(width,0.0f,0.0f),
xyPlane ? osg::Vec3(0.0f,height,0.0f) : osg::Vec3(0.0f,0.0f,height),
0.0f, flip ? 1.0f : 0.0f , 1.0f, flip ? 0.0f : 1.0f);
pictureQuad->setStateSet(createInMemoryTextureFromAVI(pictureQuad->getOrCreateStateSet(),
256,256));
return pictureQuad;
}
int main(int argc, char* argv[])
{
osgViewer::Viewer viewer;
viewer.getCamera()->setClearColor(osg::Vec4f(0.5,0.5,0.5,1.0));
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new
osg::GraphicsContext::Traits;
traits->x = 100;
traits->y = 100;
traits->width = 800;
traits->height = 600;
traits->windowDecoration = true;
traits->doubleBuffer = true;
traits->sharedContext = 0;
osg::ref_ptr<osg::GraphicsContext> gc =
osg::GraphicsContext::createGraphicsContext(traits.get());
if (gc.valid())
{
osg::notify(osg::INFO)<<" GraphicsWindow has been created
successfully."<<std::endl;
gc->setClearColor(osg::Vec4f(0.2f,0.2f,0.6f,1.0f));
gc->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
viewer.getCamera()->setViewport(new osg::Viewport(0,0,
traits->width, traits->height));
viewer.getCamera()->setGraphicsContext(gc.get());
viewer.getCamera()->setDrawBuffer(GL_BACK);
viewer.getCamera()->setReadBuffer(GL_BACK);
viewer.setCameraManipulator(new osgGA::TrackballManipulator);
OpenAVI("c:\\libs\\openscenegraph-data\\movies\\Face2.avi");
// get first frame
frame = 0;
GrabAVIFrame(0);
osg::Geode* geode = new osg::Geode;
geode->addDrawable(
myCreateTexturedQuadGeometry(osg::Vec3f(0,0,0),256,256,false,
false, false).get());
viewer.setSceneData(geode);
viewer.realize();
while (!viewer.done())
{
viewer.frame();
frame = ((frame+1)>lastframe) ? 0 : (frame+1);
GrabAVIFrame(frame);
image->allocateImage(256, 256, 1,
GL_RGB, GL_UNSIGNED_BYTE);
image->setImage(256,256,1,
GL_TEXTURE_2D,GL_RGB,
GL_UNSIGNED_BYTE, data,
osg::Image::USE_NEW_DELETE);
texture->setImage(0,image.get());
}
CloseAVI();
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org