这是一个大框架,目前c.1已经完成左边主线程视频流的设计,右边音频也已经完成,不过我还没有添加到c.1代码中。
之前c.0的代码思路是:1读取一视频帧,然后2映射贴图,最后3显示;在映射贴图(视频处理)中是采用双线程,加载到GPU进行计算,不过后来我测试了一下三个部分占用的时间比,1和3占比四分之一,2占比二分之一,这还是在加载到GPU计算的结果,所以导致最后播放帧率只有22左右,不满足30帧率的要求。
c.1的代码思路就如上图所示,一个线程预存视频帧,我测试过这个预存也就是读取每一帧到一个固定buff中的时间较短,所以等预存满了再和视频帧处理显示线程同步,这样相当于本来花在1 2 3上时间最终只花了2 3的时间,测得的帧率基本在30以上。
主要是增加了一下函数和一些地方的改动:
int LoadFrame(void*xx) {//预加载线程 while (1) { frame = cvQueryFrame(capture);//读取下一帧 if (!frame) break; if ((Mbuff1 + 1) % MaxLoadFrameBuffSize == Mbuff2) while (1) {//同步处理 满队列等待 //waitKey(Sleepms); if ((Mbuff1 + 1) % MaxLoadFrameBuffSize != Mbuff2) break; } cvarrToMat(frame).copyTo(Mbuff[Mbuff1]);//帧转换成MAT格式保存在Mbuff中 Mbuff1 = (Mbuff1 + 1) % MaxLoadFrameBuffSize;//入队 } return 0; } void MPop() {//出队列 picture_remap.rgbImg = Mbuff[Mbuff2]; if (Mbuff2 != Mbuff1) Mbuff2 = (Mbuff2 + 1) % MaxLoadFrameBuffSize; }
void SetupRC() { int i; glGenTextures(1, &cubeTexture); glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTexture); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); frame = cvQueryFrame(capture);// MatInit();// SDL_Delay(5000);// MPop();// remap6();// gltMakeCube(cubeBatch, 16.0f); skyBoxShader = gltLoadShaderPairWithAttributes("SkyBox.vp", "SkyBox.fp", 2, GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_NORMAL, "vNormal"); locMVPSkyBox = glGetUniformLocation(skyBoxShader, "mvpMatrix"); }
void CMainApplication::RunMainLoop() { bool bQuit = false; SDL_StartTextInput(); SDL_ShowCursor(SDL_DISABLE); // int ct = 0; DWORD start_time, end_time, q, p; start_time = GetTickCount(); // while (!bQuit) { //bQuit = HandleInput(); RenderFrame();//显示 MPop();//出队列 remap6();//贴图映射 if (++ct == 30) { ct = 0; end_time = GetTickCount(); printf("播放帧率 %f \n", 30000.0 / (end_time - start_time)); start_time = end_time; } } SDL_StopTextInput(); }
int main(int argc, char *argv[]) { capture = cvCreateFileCapture(VideoAddr); QueryPerformanceFrequency(&nFreq); picture_remap.rgbImg.setDefaultAllocator(cv::cuda::HostMem::getAllocator(cv::cuda::HostMem::AllocType::PAGE_LOCKED)); picture_remap.rgbImg.create(picture_remap.rgbImg.rows, picture_remap.rgbImg.cols, CV_8UC3); double rate = (double)cvGetCaptureProperty(capture, CV_CAP_PROP_FPS); printf("原始帧率 %f \n", rate); int frames = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT); thread = SDL_CreateThread(LoadFrame, "LoadFrame", &xx);//预加载线程 SDL_Delay(1000);//等加载线程至少加载一帧图片 MPop();//出队列
src[1].upload(picture_remap.rgbImg, src_stream[1]); CMainApplication *pMainApplication = new CMainApplication(argc, argv); if (!pMainApplication->BInit()) { pMainApplication->Shutdown(); return 1; } pMainApplication->RunMainLoop(); pMainApplication->Shutdown(); return 0; }