我正在開發一個系統,該系統會在呈現完成後立即從服務器中完成的3D圖形向客戶端發送壓縮視頻。 我已經有代碼的工作,但我覺得它可能會更快(而且它已經在系統中的瓶頸)使用opengl和x264更快地編碼實時3D圖形
下面是我在做什麼:
首先我搶的framebuffer
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
然後我翻轉framebuffer,因爲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並且僅在將其複製到系統內存之後纔會很好,並且希望有一種方法可以在不需要翻轉的情況下進行顏色轉換。
如果沒有更好的方法,至少這個問題可能會幫助有人試圖做到這一點,做到這一點,就像我做的一樣。使用PBOs.Here是example它加速UPS採用2個公益組織,其異步工作的閱讀,而不使管線停滯像readPixels使用directly.In我的應用我得到了80%的性能提升時不切換時
有幾件事情可以使這個「更快」。你確實可以將一些計算任務卸載到GPU上,但是如果你的GPU已經成爲瓶頸,那對你來說無能爲力。你也可以通過使用PBO來改進這個代碼,所以你不會阻塞GPU管道。在這種情況下更快是相對的。先測量究竟是什麼問題。 – KillianDS
另外,你只是想在這裏做屏幕抓取,或者你可以把東西呈現給FBO嗎?它對於優化你可以做的事情有很大的影響。我已經完成了這件事,可能會非常棘手。 – KillianDS
對不起。通過讀像素將幀緩衝區複製到內存,整個翻轉和轉換都是瓶頸。複製後,所有內容都在主內存和CPU中完成。 我正在渲染到服務器中的屏幕,然後捕獲它。這可能很愚蠢,如果通過使用FBO,我可以避免進入顯示器並同時提高性能,那將會很棒。 我不熟悉幀緩衝區對象,但我可以肯定地給他們一個嘗試。我想我可以修改應用程序,而不是呈現到後臺緩衝區呈現給FBO。那有意義嗎? – cloudraven