[osg-users] Framerate Drop in Rendering Multiple 1080p videos in OsgViewer

22 views
Skip to first unread message

Balajee.R.C

unread,
Sep 16, 2013, 5:12:14 AM9/16/13
to osg-...@lists.openscenegraph.org
Hi,

I have an application where I have to show multiple 1080p AVI videos rendering at the same time. I have implemented this using FFMPEG plugin with the code shown below. Most of the code is from osgmovie sample.

Upto 3 videos, the framerate is constant and shows no drop. However, I notice a significant frame rate drop for every subsequent video source added. With 3 video sources, the framerate peaks at around 480 fps (60 fps with Vsync on) while with 6 videos, the frame rate drops to less than 80 (less than 20 fps with VSync turned on).

Note that CPU utilization never goes over 30% throughout the entire process.

I also find that when the view shows only 3 videos, then the frame rate is at maximum (since presumably, the other 3 videos are getting culled out). When all 5 videos become visible however, the frame rate drops as described above.

This looks to me like a rendering issue. Am I doing something wrong? Essentially, osg is rendering 6 textured quads (its the plugins that update the textures) and hence musn't show frame rate drops. Could someone please give me some hints as to how I can improve rendering performance?

Thank you!

Cheers,
Balajee.R.C

TestBed:
Intel Core i7 (3.07 GHz)
4GB RAM
AMD Radeon HD 6800

Windows 7
Visual Studio 2008
OpenScenegraph 3.2.0 Release


Code:

osg::Geometry* CreateTexturedQuadGeometry(const osg::Vec3& pos,float width,float height, osg::Image* image, bool useTextureRectangle, bool xyPlane, bool option_flip)
{
bool flip = image->getOrigin()==osg::Image::TOP_LEFT;
if (option_flip) flip = !flip;

if (useTextureRectangle)
{
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 ? image->t() : 0.0, image->s(), flip ? 0.0 : image->t());

osg::ref_ptr<osg::TextureRectangle> texture = new osg::TextureRectangle(image);
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);


pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
texture,
osg::StateAttribute::ON);

return pictureQuad;
}
else
{
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);

osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D(image);
texture->setResizeNonPowerOfTwoHint(false);
texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);

pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
texture,
osg::StateAttribute::ON);

return pictureQuad;
}
}

osg::ref_ptr<osg::Node>
addAviVideo(const std::string& filepath, const float& xPos, const float& yPos, float& width, float& height)
{
bool useTextureRectangle = false;
bool xyPlane = false;
bool flip = false;

osg::ref_ptr<osg::Image> image = osgDB::readImageFile(filepath.c_str(), osgDB::Registry::instance()->getOptions());
osg::ref_ptr<osg::ImageStream> imagestream = dynamic_cast<osg::ImageStream*>(image.get());
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
if (imagestream)
{
osg::ImageStream::AudioStreams& audioStreams = imagestream->getAudioStreams();
imagestream->play();
}

if (image)
{
osg::notify(osg::NOTICE)<<"image->s()"<<image->s()<<" image-t()="<<image->t()<<" aspectRatio="<<image->getPixelAspectRatio()<<std::endl;

float width = image->s() * image->getPixelAspectRatio();
float height = image->t();

osg::ref_ptr<osg::Drawable> drawable = CreateTexturedQuadGeometry(osg::Vec3f(0.f, 0.f, 0.f), width, height,image, useTextureRectangle, xyPlane, flip);

if (image->isImageTranslucent())
{
osg::notify(osg::NOTICE)<<"Transparent movie, enabling blending."<<std::endl;

drawable->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
drawable->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
}

geode->addDrawable(drawable.get());
}
else
{
std::cout<<"Unable to read file "<<filepath.c_str()<<std::endl;
}

osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform();
transform->addChild(geode);

osg::Matrix m;
m.makeRotate(3.14f, osg::Vec3f(0.f, 1.f, 0.f));
m.setTrans(osg::Vec3(xPos, yPos, 0.f));
transform->asMatrixTransform()->setMatrix(m);


width = geode->getBoundingBox().xMax() - geode->getBoundingBox().xMin();
height = geode->getBoundingBox().zMax() - geode->getBoundingBox().zMin();

return transform.get();
}

int main(int argc, char *argv[] )
{
//osg::setNotifyLevel(osg::DEBUG_INFO);
long int numVideos = 0;
if(argc < 2)
{
printf("No of video files to be loaded are not given as argument! Terminating!\n");
exit(1);
}
else
{
numVideos = strtol(argv[1], NULL, 10);
}

/// parent node for all video sources
osg::ref_ptr<osg::MatrixTransform> trans = new osg::MatrixTransform();

const char* aviFolderPath = "data/";

float xPos = 0.f;
float zPos = 0.f;
for (int i = 0; i < numVideos; ++i)
{
float width, height;
char filename[1024];
sprintf(filename, "%s%d.avi", aviFolderPath, i+1);
osg::ref_ptr<osg::Node> aviVideoNode = addAviVideo(std::string(filename), xPos, zPos, width, height);
trans->addChild(aviVideoNode);

xPos = xPos + width;
}

/// run the osg::Viewer using our tree
osg::ref_ptr<osg::Group> m_osg_root = new osg::Group;
m_osg_root->addChild(trans);

osg::ref_ptr<osg::Node> nodePtr = static_cast<osg::Node*>(m_osg_root);

osg::ArgumentParser arguments(&argc,argv);

osgViewer::Viewer viewer(arguments);
viewer.setSceneData(nodePtr);

/// create windows
viewer.realize();

osg::ref_ptr<osgGA::TrackballManipulator> trackBall = new osgGA::TrackballManipulator;
trackBall->setHomePosition(osg::Vec3f(xPos, -4000.f, -320.f),
osg::Vec3f(xPos, 0.f, -320.f),
osg::Vec3f(0.f, 0.f, 1.f));
viewer.setCameraManipulator( trackBall );


osg::ref_ptr<osgViewer::StatsHandler> stats = new osgViewer::StatsHandler();
viewer.addEventHandler(stats);

/// run until escape pressed
long frameCounter = 0;
long frameAtLastStatPrint = 0;
osg::Timer_t timeAtLastStatPrint = 0.f;
int numLogs = 0;
while (!viewer.done())
{
viewer.frame() ;
++frameCounter;
osg::Timer_t currentTime = osg::Timer::instance()->tick();
osg::Timer_t timeElapsedSinceLastStatUpdate = osg::Timer::instance()->delta_s(timeAtLastStatPrint, currentTime);
if(timeElapsedSinceLastStatUpdate > 5.f)
{
++numLogs;
int numFramesSinceLastStatUpdate = frameCounter - frameAtLastStatPrint;
float fps = ((float)numFramesSinceLastStatUpdate) / (float)timeElapsedSinceLastStatUpdate;
printf("==============%d. Updated FPS: %f====================\n", numLogs, fps);
frameAtLastStatPrint = frameCounter;
timeAtLastStatPrint = currentTime;
}
}

return 0;
}


[/code]

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=56357#56357





_______________________________________________
osg-users mailing list
osg-...@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Robert Osfield

unread,
Apr 17, 2014, 10:59:31 AM4/17/14
to OpenSceneGraph Users
Hi Balajee.R.C,

I would suspect a driver issue with it getting overwhelmed by the
amount of data and stops sync the CPU and GPUs efficiently.

Try other hardware and other drivers to see if you can see a pattern.

Robert.
Reply all
Reply to author
Forward
0 new messages