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
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org