編者:李國帥
qq:9611153 微信lgs9611153
時間:2012/05/03
若使用vmr9,測試了一下,需要使用無視窗模式,不能使用IVideoWindow接口,可以直接使用SetVideoPosition方法。
// VMR9 Headers
#include <d3d9.h>
#include <streams.h>
#include <strmif.h>
#include <control.h>
#include <evcode.h>
#include <vmr9.h>
public:
HRESULT InitializeWindowlessVMR(IBaseFilter **ppVmr9);
LONG SetZoomVideoWindow(RECT rcZoom);
LONG PaintVideoWindow(HDC hdc);
LONG ResetVideoWindow();
protected:
CComPtr<IBaseFilter> 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 <IVMRFilterConfig9> 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.top) 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.top)/(double)(m_rcClient.bottom-m_rcClient.top);
rcZoomVideo.top = (LONG)((rcZoom.top-m_rcClient.top) * HeightRate + m_rcVideo.top);
rcZoomVideo.bottom = (LONG)((rcZoom.bottom-m_rcClient.top) * HeightRate + m_rcVideo.top);
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;
}