使用opengl和x264快速编码实时三维图形



我正在开发一个系统,该系统在渲染后立即从服务器中完成的三维图形向客户端发送压缩视频。我已经有了代码,但我觉得它可能会更快(而且它已经是系统中的一个瓶颈)

以下是我正在做的事情:

首先我获取帧缓冲区

glReadBuffer( GL_FRONT );
glReadPixels( 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer ); 

然后我翻转帧缓冲区,因为swsScale(我用于颜色空间转换)有一个奇怪的错误,在转换时会垂直翻转图像。我提前翻转了,没什么特别的。

void VerticalFlip(int width, int height, byte* pixelData, int bitsPerPixel)
{
byte* temp = new byte[width*bitsPerPixel];
height--; //remember height array ends at height-1

for (int y = 0; y < (height+1)/2; y++) 
{
memcpy(temp,&pixelData[y*width*bitsPerPixel],width*bitsPerPixel);
memcpy(&pixelData[y*width*bitsPerPixel],&pixelData[(height-y)*width*bitsPerPixel],width*bitsPerPixel);
memcpy(&pixelData[(height-y)*width*bitsPerPixel],temp,width*bitsPerPixel);
}
delete[] temp;
}

然后我将其转换为YUV420p

convertCtx = sws_getContext(width, height, PIX_FMT_RGB24, width, height, PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL);
uint8_t *src[3]= {buffer, NULL, NULL}; 
sws_scale(convertCtx, src, &srcstride, 0, height, pic_in.img.plane, pic_in.img.i_stride);

然后我几乎只调用x264编码器。我已经在使用零延迟预设。

int frame_size = x264_encoder_encode(_encoder, &nals, &i_nals, _inputPicture, &pic_out);

我的猜测是应该有一个更快的方法来做到这一点。捕获帧并将其转换为YUV420p。最好在GPU中将其转换为YUV420p,然后将其复制到系统内存中,希望有一种方法可以在不需要翻转的情况下进行颜色转换。

如果没有更好的方法,至少这个问题可能会帮助那些试图做到这一点的人,以我以前的方式来做。

首先,使用PBO使用异步纹理读取。下面是一个例子。它通过使用两个PBO来加快读取速度,这两个PBOs异步工作,而不会像readPixels直接使用时那样停滞管道。在我的应用程序中,当切换到PBO时,我的性能提高了80%。此外,在某些GPU上,glGetTexImage()的工作速度比glReadPixels()快,所以请尝试一下。

但如果你真的想把视频编码提升到一个新的水平,你可以使用Nvidia编解码器库通过CUDA来完成。我最近问了同样的问题,所以这会很有帮助。

最新更新