2013-12-10 15 views
7

FFMPEG (ayrı bir iş parçacığında) kullanarak video dosyasını çözen ve bu dokuyu başka bir PBO kullanarak oluşturan bir uygulamaya sahibim. Tüm PBO do-Hickey aşağıdaki fonksiyonu olur:Birden çok Piksel Tamponu Nesnesi kullanarak Video Texture güncellenirken kesinti

kod çözme thread
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; 
} 

, ben sadece _currentBuffer güncelleme ve true _isDirty bayrağını ayarlayın. Bu işlev render iş parçacığında çağrılır.

Tek bir PBO kullandığımda, yani yukarıdaki kodda _numPbos = 1 olduğunda, oluşturma herhangi bir kesiklik olmadan düzgün çalışır. Bununla birlikte, birden fazla PBO kullandığımda, videoda görünür bir kekem var. _numPbos = 2 here ile 5 video görüntüleyen bir örnek bulabilirsiniz. Kullandığım daha fazla sayıda PBO'lar, daha da kötüsü olur.

Teorik olarak, güncelleştirdiğim arabellek ve arabellek için kullanıyorumdan daha farklı olan arabellek farklıdır, bu nedenle bu tür bir aksaklık olmamalıdır. Oluşturma performansını artırmak için çift/üçlü tamponlamayı kullanmak istiyorum.

Neyin yanlış gidebileceği konusunda bazı ipuçları/ipuçları arıyorum.

cevap

1

Ben senin sorunun ise, bilmiyorum, ama bu çağrı sonrasında: Sen

glBindTexture 

aradığınız Ama hala endeksi _currentPboIndex de tampon ile faaliyet

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

.

Benim kod

, iki indeksleri var - Ben güncelleme boru hattı daha

index = 0; 
nextIndex = 1; 

set init olarak endeks ve nextIndex

şu şekildedir:

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

Hayır, bu değildi Sorun. GlUnmapBuffer çağrılması, arabellek nesnesinin artık geçerli olmadığı anlamına gelmez. Sadece sürücünün arabayı GPU belleğinde hareket ettirmesine izin verir. İstemci alanında yalnızca eşlemesi geçersiz kılınacaktır. – balajeerc

İlgili konular