很久没写日志了,很久没写代码了! 首先在.h中定义变量:
要在.cpp中构造函数中初始化NULL,在析构函数或者反初始化函数中Release变量,这里略过! 其次,添加函数SetVideoSize: void Cxxx::SetVideoSize(long lWidth,long lHeight) { m_nWidth = lWidth; m_nHeight = lHeight; if(m_pD3D != NULL) { m_pD3D->Release(); m_pD3D = NULL; } if(m_pd3dDevice != NULL) { m_pd3dDevice->Release(); m_pd3dDevice = NULL; } if(m_pd3dSurface != NULL) { m_pd3dSurface->Release(); m_pd3dSurface = NULL; } m_pD3D = Direct3DCreate9( D3D_SDK_VERSION ); if( m_pD3D == NULL ) return; D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof(d3dpp) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; double dbAspect = (double)lWidth / lHeight; CRect rtClient; m_PresentWnd.GetClientRect(&rtClient); m_rtViewport = rtClient; if(rtClient.Width() > rtClient.Height() * dbAspect) { //width lager than height,adjust the width int nValidW(static_cast<int>(rtClient.Height() * dbAspect)); int nLost(rtClient.Width() - nValidW); m_rtViewport.left += nLost / 2; m_rtViewport.right = m_rtViewport.left + nValidW; } else { //height lager than width,adjust the height int nValidH(static_cast<int>(rtClient.Width() / dbAspect)); int nLost(rtClient.Height() - nValidH); m_rtViewport.top += nLost / 2; m_rtViewport.bottom = m_rtViewport.top + nValidH; } if( FAILED( m_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_PresentWnd.GetSafeHwnd(), D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &m_pd3dDevice ) ) ) return; if( FAILED(m_pd3dDevice->CreateOffscreenPlainSurface( lWidth,lHeight, (D3DFORMAT)MAKEFOURCC('Y', 'V', '1', '2'), D3DPOOL_DEFAULT, &m_pd3dSurface, NULL))) return; } 其中,m_PresentWnd为定义显示区域的窗口对象。 再次添加SetYUVbuffer函数用于设置显示数据(这里只表达了显示YV12的数据格式): void Cxxx::SetYUVbuffer(LPBYTE pBuffer,long lLen) { if(m_pd3dSurface == NULL)return; D3DLOCKED_RECT d3d_rect; if( FAILED(m_pd3dSurface->LockRect(&d3d_rect,NULL,D3DLOCK_DONOTWAIT))) return ; const int w = m_nWidth,h = m_nHeight; BYTE * const p = (BYTE *)d3d_rect.pBits; const int stride = d3d_rect.Pitch; int i = 0; for(i = 0;i < h;i ++) { memcpy(p + i * stride,pBuffer + i * w, w); } for(i = 0;i < h/2;i ++) { memcpy(p + stride * h + i * stride / 2,pBuffer + w * h + w * h / 4 + i * w / 2, w / 2); } for(i = 0;i < h/2;i ++) { memcpy(p + stride * h + stride * h / 4 + i * stride / 2,pBuffer + w * h + i * w / 2, w / 2); } if( FAILED(m_pd3dSurface->UnlockRect())) { return ; } DrawImage(); } 注意:这里的函数参数pBuffer中所传递的YV12数据,其Pitch等于Width,并且YUV数据一次排列,无Padding数据。 最后添加函数DrawImage函数将图像显示出来: void Cxxx::DrawImage() { if (m_pd3dDevice != NULL) { m_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 ); m_pd3dDevice->BeginScene(); IDirect3DSurface9 * pBackBuffer = NULL; m_pd3dDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&pBackBuffer); m_pd3dDevice->StretchRect(m_pd3dSurface,NULL,pBackBuffer,&m_rtViewport,D3DTEXF_LINEAR); m_pd3dDevice->EndScene(); m_pd3dDevice->Present( NULL, NULL, NULL, NULL ); } } 至此,函数编码结束。 调用过程: 当图像画幅改变时,首先调用SerVideoSize设置新的图像画幅; 然后就定时的调用SetYUVBuffer来输入视频数据即可。 |
|
来自: SamBookshelf > 《DirectX》