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 を使用して非同期テクスチャ読み取りを使用します。これは、readPixels を直接使用した場合のように、パイプラインを停止させることなく非同期で動作する 2 つの PBO を使用して読み取りを高速化するです。私のアプリでは、PBO に切り替えると 80% のパフォーマンス向上が得られました。さらに、一部の GPU では glGetTexImage() が glReadPixels() よりも高速に動作するため、試してみてください。

しかし、本当にビデオ エンコーディングを次のレベルに引き上げたい場合は、Nvidia Codec Libraryを使用して CUDA 経由で行うことができます。最近同じ質問をしたので、これは役に立ちます。

于 2012-12-26T21:36:36.397 に答える