문제

저는 렌더링되는 즉시 서버에서 수행되는 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 인코더를 호출합니다.이미 제로 레이턴시 사전 설정을 사용하고 있습니다.

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

내 생각에는 이 작업을 수행하는 더 빠른 방법이 있어야 한다는 것입니다.프레임을 캡처하여 YUV420p로 변환합니다.GPU에서 YUV420p로 변환한 후 시스템 메모리에 복사하는 것이 좋을 것입니다. 뒤집을 필요 없이 색상 변환을 수행할 수 있는 방법이 있기를 바랍니다.

더 좋은 방법이 없다면, 적어도 이 질문은 제가 했던 것과 같은 방식으로 이 일을 하려는 누군가에게 도움이 될 수 있습니다.

도움이 되었습니까?

해결책

먼저 PBO를 사용하여 비동기 텍스처 읽기를 사용합니다.여기는 다음과 같습니다. readPixels가 직접 사용될 때처럼 파이프라인을 지연시키지 않고 비동기적으로 작동하는 2개의 PBO를 사용하여 읽기 속도를 높입니다. 내 앱에서 PBO로 전환하면 성능이 80% 향상되었습니다.또한 일부 GPU에서는 glGetTexImage()가 glReadPixels()보다 빠르게 작동하므로 시도해 보십시오.

하지만 정말로 비디오 인코딩을 다음 단계로 끌어올리고 싶다면 다음을 사용하여 CUDA를 통해 수행할 수 있습니다. 엔비디아 코덱 라이브러리.최근에도 같은 질문을 해서 이것 도움이 될 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top