Penceresiz Modu Kullanma
[Bu sayfayla ilişkilendirilmiş DirectShowözelliği, eski bir özelliktir.] Yerine MediaPlayer, IMFMediaEngineve Media Foundation 'de Ses/Video Yakalamaalmıştır. Bu özellikler Windows 10 ve Windows 11 için iyileştirilmiştir. Microsoft, mümkün olduğunda, yeni kodun MediaPlayer, IMFMediaEngine ve Audio/Video Capture in Media Foundation kullanmasını, DirectShowyerine kesinlikle önerir. Microsoft, mümkünse yeni API'leri kullanmak için eski API'leri kullanan mevcut kodun yeniden yazılmasını önerir.]
Hem Video Mixing Renderer Filter 7 (VMR-7) hem de Video Mixing Renderer Filter 9 (VMR-9), IVideoWindow arabirimi üzerinde önemli bir gelişmeyi temsil eden penceresiz modu destekler. Bu konu başlığında penceresiz mod ile pencereli mod arasındaki farklar ve penceresiz modun nasıl kullanılacağı açıklanmaktadır.
Mevcut uygulamalarla geriye dönük olarak uyumlu kalmak için VMR varsayılan olarak pencereli moda geçer. Pencereli modda, işleyici videoyu görüntülemek için kendi penceresini oluşturur. Uygulama genellikle video penceresini uygulama penceresinin alt öğesi olacak şekilde ayarlar. Ancak ayrı bir video penceresinin varlığı bazı sorunlara neden olur:
- En önemlisi, iş parçacıkları arasında pencere iletileri gönderilirse kilitlenme olasılığı vardır.
- Filtre Grafı Yöneticisi'nin WM_PAINT gibi belirli pencere iletilerini Video oluşturucuya iletmesi gerekir. Uygulama, Filter Graph Manager'ın doğru iç durumu koruması için Filter Graph Manager'ın IVideoWindow (Video Oluşturucu'nun değil) uygulamasını kullanmalıdır.
- Video penceresinden fare veya klavye olaylarını almak için, uygulamanın birileti boşaltması ayarlaması gerekir ve bu da video penceresinin bu iletileri uygulamaya iletmesine neden olur.
- Kırpma sorunlarını önlemek için, video penceresinin uygun pencere stillerine sahip olması gerekir.
Penceresiz mod, video dikdörtgenini kırpmak için DirectDraw kullanarak VMR'nin doğrudan uygulama penceresinin istemci alanına çizilmesiyle bu sorunları önler. Penceresiz mod kilitlenme olasılığını önemli ölçüde azaltır. Ayrıca, uygulamanın sahip penceresini veya pencere stillerini ayarlaması gerekmez. Aslında, VMR penceresiz moddayken, artık gerekmeyen IVideoWindow arabirimini bile kullanıma sunmaz.
Penceresiz modu kullanmak için VMR'yi açıkça yapılandırmanız gerekir. Ancak, bunun pencereli moddan daha esnek ve kullanımı daha kolay olduğunu göreceksiniz.
VMR-7 filtresi ve VMR-9 filtresi farklı arabirimleri kullanıma sunar, ancak adımlar her birine eşdeğerdir.
VMR'yi Penceresiz Mod için yapılandırma
VMR'nin varsayılan davranışını geçersiz kılmak için, filtre grafiğini oluşturmadan önce VMR'yi yapılandırın:
VMR-7
- Filtre Grafı Yöneticisi'ni oluşturun.
- VMR-7'yi oluşturun ve filtre grafiğine ekleyin.
- VMR-7 üzerinde VMRMode_Windowless bayrağıyla IVMRFilterConfig::SetRenderingMode çağırın.
- IVMRWindowlessControl arabirimi için VMR-7'yi sorgulayabilirsiniz.
- VMR-7 üzerinde IVMRWindowlessControl::SetVideoClippingWindow çağırın. Videonun gösterilmesi gereken pencere tutamacını belirtin.
VMR-9
- Filtre Grafı Yöneticisi'ni oluşturun.
- VMR-9'u oluşturun ve filtre grafiğine ekleyin.
- IVMRFilterConfig9::SetRenderingMode çağrısını, VMR9Mode_Windowless bayrağıyla VMR-9 üzerinde yapın.
- IVMRWindowlessControl9 arabirimi için VMR-9'ı sorgulayabilirsiniz.
- VMR-9 üzerinde IVMRWindowlessControl9::SetVideoClippingWindow çağırın. Videonun gösterilmesi gereken pencere tutamacını belirtin.
Şimdi IGraphBuilder::RenderFile veya diğer graf oluşturma yöntemlerini çağırarak filtre grafiğinin geri kalanını oluşturun. Filtre Grafı Yöneticisi, grafiğe eklediğiniz VMR örneğini otomatik olarak kullanır. (Bunun neden olduğu hakkında ayrıntılı bilgi için bkz. Intelligent Connect.)
Aşağıdaki kod, VMR-7'yi oluşturan, grafiğe ekleyen ve penceresiz modu ayarlayan bir yardımcı işlevi gösterir.
HRESULT InitWindowlessVMR(
HWND hwndApp, // Window to hold the video.
IGraphBuilder* pGraph, // Pointer to the Filter Graph Manager.
IVMRWindowlessControl** ppWc // Receives a pointer to the VMR.
)
{
if (!pGraph || !ppWc)
{
return E_POINTER;
}
IBaseFilter* pVmr = NULL;
IVMRWindowlessControl* pWc = NULL;
// Create the VMR.
HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL,
CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr);
if (FAILED(hr))
{
return hr;
}
// Add the VMR to the filter graph.
hr = pGraph->AddFilter(pVmr, L"Video Mixing Renderer");
if (FAILED(hr))
{
pVmr->Release();
return hr;
}
// Set the rendering mode.
IVMRFilterConfig* pConfig;
hr = pVmr->QueryInterface(IID_IVMRFilterConfig, (void**)&pConfig);
if (SUCCEEDED(hr))
{
hr = pConfig->SetRenderingMode(VMRMode_Windowless);
pConfig->Release();
}
if (SUCCEEDED(hr))
{
// Set the window.
hr = pVmr->QueryInterface(IID_IVMRWindowlessControl, (void**)&pWc);
if( SUCCEEDED(hr))
{
hr = pWc->SetVideoClippingWindow(hwndApp);
if (SUCCEEDED(hr))
{
*ppWc = pWc; // Return this as an AddRef'd pointer.
}
else
{
// An error occurred, so release the interface.
pWc->Release();
}
}
}
pVmr->Release();
return hr;
}
Bu işlev, yalnızca bir video akışının görüntülendiğini ve video üzerinde statik bir bit eşlemin karıştırılmadığını varsayar. Ayrıntılar için bkz. VMR Penceresiz Modu . Bu işlevi şu şekilde çağırabilirsiniz:
IVMRWindowlessControl *pWc = NULL;
hr = InitWindowlessVMR(hwnd, pGraph, &g_pWc);
if (SUCCEEDED(hr))
{
// Build the graph. For example:
pGraph->RenderFile(wszMyFileName, 0);
// Release the VMR interface when you are done.
pWc->Release();
}
Videoyu Konumlandırma
VMR'yi yapılandırdıktan sonra, sonraki adım videonun konumunu ayarlamaktır. dikkate alınması gereken iki dikdörtgen vardır: kaynak dikdörtgen ve hedef dikdörtgen. Kaynak dikdörtgen, videonun hangi bölümünün görüntüleneceğini tanımlar. Hedef dikdörtgen, pencerenin istemci alanında videoyu içerecek bölgeyi belirtir. VMR, video görüntüsünü kaynak dikdörtgene kırpır ve kırpılan görüntüyü hedef dikdörtgene sığacak şekilde genişletir.
VMR-7
- her iki dikdörtgeni de belirtmek için IVMRWindowlessControl::SetVideoPosition yöntemini çağırın.
- Kaynak dikdörtgen, yerel video boyutuna eşit veya ondan küçük olmalıdır; yerel video boyutunu almak için IVMRWindowlessControl::GetNativeVideoSize yöntemini kullanabilirsiniz.
VMR-9
- her iki dikdörtgeni de belirtmek için IVMRWindowlessControl9::SetVideoPosition yöntemini çağırın.
- Kaynak dikdörtgen, yerel video boyutuna eşit veya ondan küçük olmalıdır; yerel video boyutunu almak için IVMRWindowlessControl9::GetNativeVideoSize yöntemini kullanabilirsiniz.
Örneğin, aşağıdaki kod VMR-7 için kaynak ve hedef dikdörtgenleri ayarlar. Kaynak dikdörtgeni video görüntüsünün tamamına, hedef dikdörtgeni ise tüm pencere istemci alanına eşit olarak ayarlar:
// Find the native video size.
long lWidth, lHeight;
HRESULT hr = g_pWc->GetNativeVideoSize(&lWidth, &lHeight, NULL, NULL);
if (SUCCEEDED(hr))
{
RECT rcSrc, rcDest;
// Set the source rectangle.
SetRect(&rcSrc, 0, 0, lWidth, lHeight);
// Get the window client area.
GetClientRect(hwnd, &rcDest);
// Set the destination rectangle.
SetRect(&rcDest, 0, 0, rcDest.right, rcDest.bottom);
// Set the video position.
hr = g_pWc->SetVideoPosition(&rcSrc, &rcDest);
}
Müşteri alanının daha küçük bir bölümünü kaplaması için video boyutunu değiştirmek istiyorsanız, rcDest parametresini değiştirin. Video görüntüsünü kırpmak istiyorsanız rcSrc parametresini değiştirin.
Pencere Mesajlarını Yönetme
VMR'nin kendi penceresi olmadığından, videoyu yeniden boyaması veya yeniden boyutlandırması gerekiyorsa bu durum bildirilmelidir. Listelenen VMR yöntemlerini çağırarak aşağıdaki pencere iletilerine yanıt verin.
VMR-7
- WM_PAINT. IVMRWindowlessControl::RepaintVideoçağrısı. Bu yöntem, VMR-7'nin en son video çerçevesini yeniden boyamasına neden olur.
- WM_DISPLAYCHANGE: IVMRWindowlessControl::DisplayModeChangedçağrısını gerçekleştirin. Bu yöntem, VMR-7'ye videonun yeni çözünürlükte veya renk derinliğinde gösterilmesi gerektiğini bildirir.
- WM_SIZE veya WM_WINDOWPOSCHANGED: Videonun konumunu yeniden hesaplayın ve gerekirse konumu güncelleştirmek için IVMRWindowlessControl::SetVideoPositionçağırın.
VMR-9
- WM_PAINT. IVMRWindowlessControl9::RepaintVideoçağrısı. Bu yöntem, VMR-9'un en son video çerçevesini yeniden boyamasına neden olur.
- WM_DISPLAYCHANGE: IVMRWindowlessControl9::DisplayModeChangedçağrısı gerçekleştirin. Bu yöntem, VMR-9'a videonun yeni çözünürlükte veya renk derinliğinde gösterilmesi gerektiğini bildirir.
- WM_SIZE veya WM_WINDOWPOSCHANGED: Videonun konumunu yeniden hesaplayın ve gerekirse konumu güncelleştirmek için IVMRWindowlessControl9::SetVideoPositionçağırın.
Not
WM_WINDOWPOSCHANGED iletisinin varsayılan işleyicisi bir WM_SIZE iletisi gönderir. Ancak uygulamanız WM_WINDOWPOSCHANGED kesiyorsa ve DefWindowProc'a geçirmezse, WM_SIZE işleyicinize ek olarak WM_WINDOWPOSCHANGED işleyicinizde SetVideoPosition çağırmalısınız.
Aşağıdaki örnekte bir WM_PAINT ileti işleyicisi gösterilmektedir. İstemci dikdörtgeninden video dikdörtgeni çıkarıldıktan sonra tanımlanan bir bölgeyi boyar. Video dikdörtgenine çizim yapmayınız, çünkü VMR üzerine boyadığında titremeye neden olabilir. Aynı nedenle, pencere sınıfınızda bir arka plan fırçası ayarlamayın.
void OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
HDC hdc;
RECT rcClient;
GetClientRect(hwnd, &rcClient);
hdc = BeginPaint(hwnd, &ps);
if (g_pWc != NULL)
{
// 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(&g_rcDest);
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 = g_pWc->RepaintVideo(hwnd, hdc);
}
else // There is no video, so paint the whole client area.
{
FillRect(hdc, &rc2, (HBRUSH)(COLOR_BTNFACE + 1));
}
EndPaint(hwnd, &ps);
}
WM_PAINT iletileri yanıtlamanız gerekse de, videoyu güncelleştirmek için WM_PAINT iletiler arasında yapmanız gereken bir şey yoktur. Bu örnekte gösterildiği gibi penceresiz mod, video görüntüsünü yalnızca pencerede kendi kendine çizim bölgesi olarak ele almanızı sağlar.
İlgili konular