VMR9实现放大缩小

网友投稿 710 2022-11-16

VMR9实现放大缩小

VMR9实现放大缩小

​​编者:李国帅​​

​​时间:2012/05/03  ​​

若使用vmr9,测试了一下,需要使用无窗口模式,不能使用IVideoWindow接口,可以直接使用SetVideoPosition方法

// VMR9 Headers#include #include #include #include #include #include public: HRESULT InitializeWindowlessVMR(IBaseFilter **ppVmr9); LONG SetZoomVideoWindow(RECT rcZoom); LONG PaintVideoWindow(HDC hdc); LONG ResetVideoWindow();protected: CComPtr m_pVmr9; IVMRWindowlessControl9 *m_pWC; RECT m_rcClient;//播放区域 RECT m_rcVideo;//播放区域//CGraphBase::CGraphBase(CWindow* pParent) m_pVmr9 = NULL; m_pWC = NULL; memset(&m_rcVideo,0,sizeof(RECT)); memset(&m_rcClient,0,sizeof(RECT));//CGraphBase::~CGraphBase(void) SafeRelease(m_pWC); SafeRelease(m_pVmr9);//CreatePlayer() // Create the Video Mixing Renderer and add it to the graph HRESULT hrVmr = InitializeWindowlessVMR(&m_pVmr9); _assert(SUCCEEDED(hrVmr) && m_pVmr9 != NULL); hr |= ConnectFilters(mGraph, pIDecoderFilter,m_pVmr9);HRESULT CGraphBase::InitializeWindowlessVMR( IBaseFilter **ppVmr9 ){ if (!ppVmr9) return E_POINTER; *ppVmr9 = NULL; IBaseFilter* pVmr = NULL; // Create the VMR and add it to the filter graph. HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr); if (SUCCEEDED(hr)) { hr = mGraph->AddFilter(pVmr, L"Video Mixing Renderer 9"); if (SUCCEEDED(hr)) { // Set the rendering mode and number of streams CComPtr pConfig; pVmr->QueryInterface(IID_IVMRFilterConfig9, (void**)&pConfig); pConfig->SetRenderingMode(VMR9Mode_Windowless); hr = pVmr->QueryInterface(IID_IVMRWindowlessControl9, (void**)&m_pWC); if( SUCCEEDED(hr)) { hr = m_pWC->SetVideoClippingWindow(m_pParent->m_hWnd); hr = m_pWC->SetBorderColor(RGB(0,0,0)); }#ifndef BILINEAR_FILTERING // Request point filtering (instead of bilinear filtering) // to improve the text quality. In general, if you are // not scaling the app Image, you should use point filtering. // This is very important if you are doing source color keying. IVMRMixerControl9 *pMix; hr = pVmr->QueryInterface(IID_IVMRMixerControl9, (void**)&pMix); if( SUCCEEDED(hr)) { DWORD dwPrefs=0; hr = pMix->GetMixingPrefs(&dwPrefs); if (SUCCEEDED(hr)) { dwPrefs |= MixerPref_PointFiltering; dwPrefs &= ~(MixerPref_BiLinearFiltering); hr = pMix->SetMixingPrefs(dwPrefs); } pMix->Release(); }#endif } else { //Msg(TEXT("Failed to add VMR to graph! hr=0x%x\r\n"), hr); } // Don't release the pVmr interface because we are copying it into the caller's ppVmr9 pointer *ppVmr9 = pVmr; } else { //Msg(TEXT("Failed to create VMR! hr=0x%x\r\n"), hr); } return hr;}LONG CGraphBase::SetZoomVideoWindow(RECT rcZoom){ if (m_pWC == NULL) return 0; // Track the movement of the container window and resize as needed GetClientRect(m_pParent->m_hWnd, &m_rcClient);// Get the window client area. //SetRect(&m_rcClient, 0, 0, m_rcClient.right/2, m_rcClient.bottom/2); // Set the destination rectangle. if(m_rcClient.right<=m_rcClient.left || m_rcClient.bottom<=m_rcClient-) return FALSE; ATLASSERT(rcZoom.right>0 && rcZoom.bottom>0);//代表不缩放 if(rcZoom.right<=0 || rcZoom.bottom<=0) return FALSE;// long lWidth, lHeight; HRESULT hr = m_pWC->GetNativeVideoSize(&lWidth, &lHeight, NULL, NULL); if (!SUCCEEDED(hr))return FALSE; if ((lWidth == 0) && (lHeight == 0))return FALSE; if (m_rcVideo.bottom == 0 || m_rcVideo.right == 0) { SetRect(&m_rcVideo, 0, 0, lWidth, lHeight);//原始状态// Set the source rectangle. //SetRect(&rcSrc, 0, 0, lWidth/2, lHeight/2);//测试 } RECT rcZoomVideo;//设备上放大的区域 memset(&rcZoomVideo,0,sizeof(RECT)); double WidthRate = (double)(m_rcVideo.right-m_rcVideo.left) /(double)(m_rcClient.right-m_rcClient.left); rcZoomVideo.left = (LONG)((rcZoom.left-m_rcClient.left) * WidthRate + m_rcVideo.left); rcZoomVideo.right = (LONG)((rcZoom.right-m_rcClient.left) * WidthRate + m_rcVideo.left); double HeightRate = (double)(m_rcVideo.bottom-m_rcVideo-)/(double)(m_rcClient.bottom-m_rcClient-); rcZoomVideo- = (LONG)((rcZoom--m_rcClient-) * HeightRate + m_rcVideo-); rcZoomVideo.bottom = (LONG)((rcZoom.bottom-m_rcClient-) * HeightRate + m_rcVideo-); CopyRect(&m_rcVideo,&rcZoomVideo); HRESULT hr = m_pWC->SetVideoPosition(&m_rcVideo, &m_rcClient); // Set the video position. if (FAILED(hr)) { //Msg(TEXT("SetVideoPosition FAILED! hr=0x%x\r\n"), hr); } return hr;}LONG CGraphBase::PaintVideoWindow( HDC hdc ){ if (m_pWC == NULL) return 0; RECT rcClient; GetClientRect(*m_pParent, &rcClient); // Find the region where the application can paint by subtracting // the video destination rectangle from the client area. // (Assume that g_rcDest was calculated previously.) HRGN rgnClient = CreateRectRgnIndirect(&rcClient); HRGN rgnVideo = CreateRectRgnIndirect(&m_rcClient); CombineRgn(rgnClient, rgnClient, rgnVideo, RGN_DIFF); // Paint on window. HBRUSH hbr = GetSysColorBrush(COLOR_BTNFACE); FillRgn(hdc, rgnClient, hbr); // Clean up. DeleteObject(hbr); DeleteObject(rgnClient); DeleteObject(rgnVideo); // Request the VMR to paint the video. HRESULT hr = m_pWC->RepaintVideo(*m_pParent, hdc); if (SUCCEEDED(hr))return 1; return 0;}LONG CGraphBase::ResetVideoWindow(){ if (m_pWC == NULL) return 0; long lWidth, lHeight; HRESULT hr = m_pWC->GetNativeVideoSize(&lWidth, &lHeight, NULL, NULL); if (!SUCCEEDED(hr))return 0; if ((lWidth == 0) && (lHeight == 0))return 0; SetRect(&m_rcVideo, 0, 0, lWidth, lHeight);//原始状态 m_pWC->SetVideoPosition(&m_rcVideo, &m_rcClient); // Set the video position. return 1;}

刷新函数:

因为使用vmr的无窗口模式,播放区域自己就是控件窗口,所以不需要专门的设置窗口大小,也不需要在窗口graph之后和onsize的时候重新设置。

刷新一下即可。

LRESULT CxxPlayer::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){ // reset video window if(m_hWnd==NULL || !::IsWindow(m_hWnd))return S_OK; RECT rect; GetClientRect(&rect); if(m_pCurGraph!=NULL) { ShowWindow(SW_HIDE); m_pCurGraph->SetDisplayRect(m_hWnd,&rect);//不需要 m_pCurGraph->SetZoomVideoWindow(m_rcZoom); ShowWindow(SW_SHOW); } return 0;}BOOL CGraphBase::SetDisplayRect(HWND inWindow,LPRECT pRect){ CheckPointer(m_pWC, FALSE); m_pWC->SetVideoClippingWindow(inWindow); if (pRect != NULL) { SetWindowPos(inWindow,HWND_TOPMOST,pRect->left,pRect->top,pRect->right,pRect->bottom,SWP_SHOWWINDOW); } // Restore the video window m_pWC->RepaintVideo(inWindow,m_pParent->GetDC()); return TRUE;}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SQL查询笔记
下一篇:【夯实Redis】如何保证数据库与缓存双写一致性?        跟着大宇学Redis--------目录帖
相关文章

 发表评论

暂时没有评论,来抢沙发吧~