[osg-users] playing AVI on Windows

Janusz janusz at 3dcalc.pl
Thu Sep 4 14:51:26 PDT 2008


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();
}


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openscenegraph.org/pipermail/osg-users-openscenegraph.org/attachments/20080904/650203cc/attachment-0002.htm>


More information about the osg-users mailing list