4

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

这是我正在做的事情:

首先我抓住帧缓冲区

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 编码器。我已经在使用 zerolatency 预设。

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

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

如果没有更好的方法,至少这个问题可以帮助尝试这样做的人,像我一样做。

4

1 回答 1

2

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

但是,如果您真的想将视频编码提升到一个新的水平,您可以使用Nvidia Codec Library通过 CUDA 来完成。我最近问了同样的问题,所以可能会有所帮助。

于 2012-12-26T21:36:36.397 回答