天天看點

MFC+OpenGL顯示視訊流圖檔

由于想做一個應用軟體,把目前自己的算法應用出去,給給為研究者提供一丢丢便利,需要在MFC中顯示視訊流檔案。我嘗試了兩種方法:opencv+MFC;openGL+MFC;這兩種方法都可行。但是在使用opencv+MFC時,以為是設定雙緩沖處有點問題,導緻視訊流閃爍嚴重。(實際是讀取視訊的問題,修改後應該可行,後面改用opengl做了,也出現了這樣的問題,後來修改好了)。

1、首先需要加載一個Picture Control的控件;設定ID等

2、在CTrackingAppDlg.h(XXXDlg.h)中定義雙緩沖區:

HDC _hrenderDC; //DC
    HGLRC _hrenderRC; //RC
           

添加兩個初始化函數:

bool CTrackingAppDlg::SetWindowPixelFormat(HDC hDC)
{
    PIXELFORMATDESCRIPTOR pixelDesc;  

    pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);  

    pixelDesc.nVersion = ;  
    pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |PFD_DOUBLEBUFFER |PFD_TYPE_RGBA;

    pixelDesc.iPixelType = PFD_TYPE_RGBA;
    pixelDesc.cColorBits = ;
    pixelDesc.cRedBits = ;  
    pixelDesc.cRedShift = ;
    pixelDesc.cGreenBits = ;
    pixelDesc.cGreenShift = ;
    pixelDesc.cBlueBits = ;
    pixelDesc.cBlueShift = ;  
    pixelDesc.cAlphaBits = ;  
    pixelDesc.cAlphaShift = ;  
    pixelDesc.cAccumBits = ;  
    pixelDesc.cAccumRedBits = ;  
    pixelDesc.cAccumGreenBits = ;  
    pixelDesc.cAccumBlueBits = ;  
    pixelDesc.cAccumAlphaBits = ;  
    pixelDesc.cDepthBits = ;  
    pixelDesc.cStencilBits = ;  
    pixelDesc.cAuxBuffers = ;  
    pixelDesc.iLayerType = PFD_MAIN_PLANE;  
    pixelDesc.bReserved = ;  
    pixelDesc.dwLayerMask = ;  
    pixelDesc.dwVisibleMask = ;  
    pixelDesc.dwDamageMask = ;  

    _pixelFormat = ChoosePixelFormat(hDC,&pixelDesc);  

    if( _pixelFormat== ) // Choose default  
    {  
        _pixelFormat = ;  
        if(DescribePixelFormat(hDC,_pixelFormat,  sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==)  
        {  
            return false;  
        }  
    } 

    if(SetPixelFormat(hDC,_pixelFormat,&pixelDesc)==FALSE)  
    {   
        return false;  
    }  

    return true;  
}

BOOL CTrackingAppDlg::CreateViewGLContext(HDC hDC)  
{  
    _hrenderRC = wglCreateContext(hDC);  

    if(_hrenderRC==NULL)  
        return FALSE;  

    if(wglMakeCurrent(hDC,_hrenderRC)==FALSE)  
        return FALSE; 

    return TRUE;  
}  
           

3、在InitDialog函數中初始化;

//讀取Picture控件的大小;
    CRect picRect;
    CWnd *wnd = GetDlgItem(IDC_PIC_RAW);
    wnd->GetWindowRect(&picRect);
    //用于設定圖檔顯示的ViewPort視窗
    _app->getRawPictureView(i)->setViewPort(picRect.Width(),picRect.Height());
           

初始化并設定Opengl顯示屬性等:

_hrenderDC = ::GetDC(wnd->m_hWnd);
///////////////////////////////////////////Tian///////////////////////////
        if(SetWindowPixelFormat(_hrenderDC)==FALSE)  
            return ;  

        if(CreateViewGLContext(_hrenderDC)==FALSE)  
            return ;  

        glPolygonMode(GL_FRONT,GL_FILL);  
        glPolygonMode(GL_BACK,GL_FILL);  
        //////////////////////////////////////////////////////

        glEnable(GL_TEXTURE_2D);  
        glShadeModel(GL_SMOOTH);  
        //它負責把視景體截取的圖像按照怎樣的高和寬顯示到螢幕上。
        //glViewport(0,0,259,231);  
        glMatrixMode(GL_PROJECTION);  
        glLoadIdentity();  

        /*      gluPerspective(45,1,0.1,100.0);  
        glMatrixMode(GL_MODELVIEW);  
        glLoadIdentity(); */ 

        glShadeModel(GL_SMOOTH);       // Enable Smooth Shading  
        glClearColor(f, f, f, f);    // Black Background  
        glClearDepth(f);         // Depth Buffer Setup  
        glEnable(GL_DEPTH_TEST);       // Enables Depth Testing  
        glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do  

    glEnableClientState(GL_VERTEX_ARRAY);  
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);  
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);//緩存模式
    SetTimer(,,);//每隔10ms執行Ontimer函數一次,将Reshape放在Ontimer中可以動态更換圖檔   
           

5、OnTimer類:

void CTrackingAppDlg::OnTimer(UINT_PTR nIDEvent)
{

    //showImage(picView->getRawImage(),IDC_PIC_RAW);
    //showImage(picView->getBitImage(),IDC_PIC_BIT);
    wglMakeCurrent(_hrenderDC , _hrenderRC);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    if(_app)
    {
        for(int i=;i<;i++)
            _app->getRawPictureView(i)->reshape();
    }
    SwapBuffers(_hrenderDC);
    CDialogEx::OnTimer(nIDEvent);
}
           

初始化部分就這麼多,其他的與opengl使用相同。不懂的自己多補一點opengl相關基礎。

reshape函數如下:

void RawPicView::reshape()
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glOrtho( -, , -, , -,  );

//  glMatrixMode(GL_MODELVIEW);

    if(_ChannelId == )
        glViewport(,,_rectWight/-,_rectHight);
    else
        glViewport(_rectWight/+,,_rectWight/-,_rectHight);

    glLoadIdentity();
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

    if(!_initialized)
        initlize();

    glDisable(GL_LIGHTING);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, _textureId );

    if( !_valid )
        replaceTexture();

    glColor3f( , ,  );
    glBegin(GL_QUADS); // Drawing Using Triangles  
    ////////////////////////Tian//////////////////////////////////////////////
        glTexCoord2f( ,  );
        glVertex2f( -, f );

        glTexCoord2f( ,  );
        glVertex2f( -, -);    

        glTexCoord2f( ,  );
        glVertex2f( , -);

        glTexCoord2f( ,  );
        glVertex2f( ,  ); 

    //////////////////////////////////////////////////////////////////////////
    glEnd();

}
           

當然還是給個結果比較好:

效果如下:

MFC+OpenGL顯示視訊流圖檔