食人魔:使用Boost异步获取渲染目标内容

时间:2018-08-20 13:57:43

标签: multithreading boost rendering ogre

Ogre版本: 1.9.0: 操作系统: Linux 4.8.0-58-通用#63〜16.04.1-Ubuntu x86_64

大家好,

我正在尝试为RViz(罗斯可视化)构建一个插件,以直接从使用Ogre渲染的窗口重新录制视频。如果我依次遍历所有打开的场景管理器并从渲染目标获取当前帧,则一切正常。录制完成后,从缓冲的图像生成视频。但是,当两个以上的窗口正在主动渲染内容时,帧速率会明显下降。请参见下面的代码。为了清楚起见,我省略了错误处理和其他不需要的代码行。每30毫秒调用一次 update()函数。

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="testCtrl">
    
<select style="width: 199px;margin-top: -9px;" id="ddlTypeCode" ng-model="selectedCountryCode" ng-change="locationChange(selectedCountryCode)" name="ddlTypeCode" class="form-control">
          <option  style="display:none;"></option>
         <option ng-repeat="Country in CountryList " value="{{Country}}"ng-selected="Country == 'India'">
                        {{Country}}
                    </option>
        

</div>

我尝试使用Boost库生成线程,以便异步捕获帧,但是返回的帧始终为黑色(或一些奇怪的像素混乱)。为此,我将每个活动场景管理器的grabAllFrames函数拆分为单独的函数,并将每个函数附加到一个线程。

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

我不知道这是什么问题。指向场景管理器的指针与顺序版本相同。视口相同。但是以某种方式 getTarget()不会返回任何有用的信息。当我使用

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

图像也是黑色的。因此,我认为问题出在 getTarget()函数之内。

我很感谢任何提示。如果有人对另一个多线程库感到幸运,我也欢迎其他解决方案。

谢谢

电车!

0 个答案:

没有答案