Operating System: : Linux 4.8.0-58-generic #63~16.04.1-Ubuntu x86_64.:
Hi everyone,
I'm trying to build a plugin for RViz (Ros Visualization) to recored videos directly from the windows being rendered using Ogre. If I sequentially loop over all opened scene managers and grab the current frame from the render target, everything works fine. The video is generated from the buffered images after recording is done. Yet, the frame rate drops noticeably when more than two windows are actively rendering content. See code below. I left out error handling and other unneeded lines of code for clarity.
Code: Select all
void VideoRecorderDisplay::update()
{
if (m_recording)
{
grabAllFrames();
}
}
void VideoRecorderDisplay::grabAllFrames()
{
// TODO: start thread for each manager and parallelize
const size_t sceneManagerSize = m_sceneManagers.size();
for(size_t i = 0; i < sceneManagerSize; i++)
{
Ogre::Viewport* viewPort = m_sceneManagers[i]->getCurrentViewport();
if(viewPort != nullptr)
{
Ogre::Image ogreImage = getOgreImageFromRenderTarget(viewPort->getTarget());
m_ogreImageList.push_back(ogreImage);
}
}
}
Ogre::Image VideoRecorderDisplay::getOgreImageFromRenderTarget(Ogre::RenderTarget* const renderTarget)
{
try
{
// create PixelBox and get data from target
Ogre::PixelFormat pf = renderTarget->suggestPixelFormat();
const uint32_t targetWidth = renderTarget->getWidth();
const uint32_t targetHeight = renderTarget->getHeight();
const size_t boxSize = targetWidth * targetHeight * Ogre::PixelUtil::getNumElemBytes(pf);
unsigned char* ogrePixelData = new unsigned char[boxSize];
Ogre::PixelBox pixelBox(targetWidth, targetHeight, 1, pf, ogrePixelData);
renderTarget->copyContentsToMemory(pixelBox);
// load data into Ogre::Image
Ogre::Image ogreImage = Ogre::Image().loadDynamicImage(ogrePixelData, targetWidth, targetHeight, 1, pf);
return ogreImage;
}
}
Code: Select all
static boost::shared_ptr<boost::thread> grabberThread0;
static boost::shared_ptr<boost::thread> grabberThread1;
static boost::shared_ptr<boost::thread> grabberThread2;
static boost::shared_ptr<boost::thread> grabberThread3;
void VideoRecorderDisplay::update()
{
if (m_recording)
{
grabberThread0 = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&VideoRecorderDisplay::grabAllFramesParallelized, this, m_sceneManagers[0], boost::ref(m_dataListPerThread[0]))));
grabberThread1 = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&VideoRecorderDisplay::grabAllFramesParallelized, this, m_sceneManagers[1], boost::ref(m_dataListPerThread[1]))));
grabberThread2 = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&VideoRecorderDisplay::grabAllFramesParallelized, this, m_sceneManagers[2], boost::ref(m_dataListPerThread[2]))));
grabberThread3 = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&VideoRecorderDisplay::grabAllFramesParallelized, this, m_sceneManagers[3], boost::ref(m_dataListPerThread[3]))));
grabberThread0->join();
grabberThread1->join();
grabberThread2->join();
grabberThread3->join();
}
}
void VideoRecorderDisplay::grabAllFramesParallelized(Ogre::SceneManager* scnMngr, std::vector<Ogre::Image> dataList)
{
Ogre::Viewport* viewPort = scnMngr->getCurrentViewport();
if(viewPort != nullptr)
{
Ogre::Image ogreImage = getOgreImageFromRenderTarget(viewPort->getTarget());
dataList.push_back(ogreImage);
}
}
Code: Select all
viewPort->getTarget()->writeContentsToFile("test.bmp")
I'm grateful for any hint. If somebody had luck with another multithreading library, I'm also open for other solutions.
Thanks,
Trammy!