2013-12-10 3 views
7

私は別のスレッドでFFMPEGを使用してビデオファイルをデコードし、別のスレッドでPBOを使用してこのテクスチャをレンダリングするアプリケーションを持っています。すべてのPBO行う-キスマークは次の関数で起こる:デコードスレッドで複数のピクセルバッファオブジェクトを使用してビデオテクスチャを更新するときのスタッター

void DynamicTexture::update() 
{ 
    if(!_isDirty) 
    { 
     return; 
    } 

    /// \todo Check to make sure that PBOs are supported 
    if(_usePbo) 
    { 
     // In multi PBO mode, we keep swapping between the PBOs 
     // We use one PBO to actually set the texture data that we will upload 
     // and the other we use to update/modify. Once modification is complete, 
     // we simply swap buffers 

     // Unmap the PBO that was updated last so that it can be released for rendering 

     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _pboIds[_currentPboIndex]); 
     glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); 
     Util::GLErrorAssert(); 

     // bind the texture 
     glBindTexture(GL_TEXTURE_2D, _textureId); 
     Util::GLErrorAssert(); 

     // copy pixels from PBO to texture object 
     // Use offset instead of pointer. 
     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _width, _height, 
         (_channelCount==4)?GL_RGBA:GL_RGB, 
         GL_UNSIGNED_BYTE, 0); 
     Util::GLErrorAssert(); 

     // Now swap the pbo index 
     _currentPboIndex = (++_currentPboIndex) % _numPbos; 

     // bind PBO to update pixel values 
     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _pboIds[_currentPboIndex]); 
     Util::GLErrorAssert(); 

     // map the next buffer object into client's memory 
     // Note that glMapBuffer() causes sync issue. 
     // If GPU is working with this buffer, glMapBuffer() will wait(stall) 
     // for GPU to finish its job 
     GLubyte* ptr = (GLubyte*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); 
     Util::GLErrorAssert(); 
     if(ptr) 
     { 
      // update data directly on the mapped buffer 
      _currentBuffer = ptr; 
      Util::GLErrorAssert(); 
     } 
     else 
     { 
      printf("Unable to map PBO!"); 
      assert(false); 
     } 

     // It is good idea to release PBOs with ID 0 after use. 
     // Once bound with 0, all pixel operations behave normal ways. 
     glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 
     Util::GLErrorAssert(); 

     // If a callback was registered, call it 
     if(_renderCallback) 
     { 
      (*_renderCallback)(this); 
     } 
    } 
    else 
    { 
     glBindTexture(GL_TEXTURE_2D, _textureId); 
     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 
         _width, _height, (_channelCount==4)?GL_RGBA:GL_RGB, 
         GL_UNSIGNED_BYTE, 
         &(_buffer[0]) 
         ); 
     Util::GLErrorAssert(); 
    } 

    // Reset the dirty flag after updating 
    _isDirty = false; 
} 

、私は単に_currentBufferを更新し、trueに_isDirtyフラグを設定します。この関数は、レンダリングスレッドで呼び出されます。

単一のPBOを使用する場合、つまり上記のコードで_numPbos = 1の場合、レンダリングはスタッターなしで正常に動作します。しかし、複数のPBOを使用すると、ビデオに目障りな吃音があります。 _numPbos = 2 hereで5つのビデオをレンダリングしている私のサンプルを見つけることができます。私が使用するPBOの数が多いほど、スタッターが悪くなります。

理論的には、私が更新しているバッファと、私がレンダリングに使用しているバッファよりもバッファが異なっているので、この種のグリッチはないはずです。レンダリングのパフォーマンスを向上させるために、ダブル/トリプルバッファリングを使用したいと思います。

私は何が間違っている可能性があるかについてのいくつかのポインタ/ヒントを探しています。

答えて

1

私はそれがあなたの問題であれば、知らない、しかし、あなたがこれを呼び出した後:

glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _pboIds[_currentPboIndex]); 
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); 
Util::GLErrorAssert(); 

あなたは

glBindTexture 

を呼んでいる。しかし、あなたはまだインデックス_currentPboIndexで緩衝液を用いて動作しています。

私のコードで

、私は2つのインデックスがある - 私は私の更新パイプラインより

index = 0; 
nextIndex = 1; 

を設定INITでインデックスとnextIndex

はこのようなものです:

index = (index + 1) % 2; 
nextIndex = (nextIndex + 1) % 2; 

uint32 textureSize = sizeof(RGB) * width * height; 


GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo[nextIndex])); 
GL_CHECK(glBufferData(GL_PIXEL_UNPACK_BUFFER, textureSize, 0, GL_STREAM_DRAW_ARB)); 
GL_CHECK(gpuDataPtr = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, textureSize, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)); 

//update data gpuDataPtr 

GL_CHECK(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER_ARB)); 

//bind texture 

GL_CHECK(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER, pbo[index])); 

GL_CHECK(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 
      width, height, glFormat, GL_UNSIGNED_BYTE, 0)); 

GL_CHECK(glBindBufferARB(type, 0)); 
+0

はありません、それは「wasn問題はありません。 glUnmapBufferを呼び出すことは、バッファオブジェクトがもはや有効ではないことを意味するものではありません。これは単に、ドライバがGPUメモリ内のバッファを移動させるだけです。無効にされるクライアント空間内でのそのマッピングだけです。 – balajeerc

関連する問題