2017-07-19 92 views
0

我現在正在爬行Windows Media Foundation的陡峭學習曲線,我正在關注兩個非常相似的代碼示例以幫助我理解該技術。即使兩個媒體會話都使用一個非常簡單的「播放」程序來播放文件中的視頻,但仍有一些重要的細微差別。其中MF Play示例代碼在Media Foundation中顯示正確的COM技術?

第一個樣品是微軟的MF播放位於:

https://msdn.microsoft.com/en-us/library/windows/desktop/dd979592(v=vs.85).aspx

它不會初始化COM和不執行任何關鍵部分鎖但它播放視頻非常好。缺乏使用COM會限制它以其他方式使用,例如處理多個視頻流以通過多線程分離窗口?由於此代碼在線,因此我可能會天真地認爲此代碼更新。

第二個示例來自「開發微軟媒體基礎應用程序 - 安東波林格」一書。我下載的示例代碼從這裏: https://www.microsoftpressstore.com/content/images/9780735656598/downloads/9780735656598_files.zip

在第3章的文件夾此播放程序稍微複雜,由於使用這些COM初始化函數:

// initialize COM 
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 
... 
// uninitialize COM 
CoUninitialize(); 

它還使用了幾個關鍵部分鎖使用:

CComCritSecLock<CComAutoCriticalSection> lock(m_critSec); 

但鬼使神差沒有相應的解鎖()。那麼有人可以解釋這兩個代碼示例之間的這些潛在的重要差異,以及我應該使用哪些?我擔心,如果我不使用COM方法,那麼當我嘗試將多個視頻流到多個窗口時,我可能會遇到問題,或者更糟糕的是,我可能會遇到可靠性問題。

在附註中,Polinger代碼有效,但在播放視頻時無法處理窗口大小調整。我試圖以類似於MS代碼不使用窗口大小調整事件之後,這段代碼的方式添加代碼:

m_pVideoDisplay->SetVideoPosition(NULL, &rcDest) 

使用這只是導致程序凍結。

任何幫助將不勝感激!

回答

1

關於「它不初始化COM」 - 你沒有看到它的所有代碼 - 研究Media Session Playback Example - 你可以在player.cpp中找到調用MFStartup - MediaFoundation(MF)就足夠了。我讀過Polinger書,並在代碼中調用了一些COM線程模型敏感函數 - 例如DirectX。但是,從我的經驗看來,MF從MFStartup呼叫的上下文中調用CoInitialize。此外,在波林格的代碼中,有一個叫做Apartment thread model的公司:hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);,但是MF支持Multithreaded模型的執行 - 它對它不敏感。

關於「但神祕的是沒有相應的解鎖()」。 - CComCritSecLock是段鎖的面向對象包裝器,unlocks()CComCritSecLock - ~CComCritSecLock()的析構器中被調用。

關於調整 - m_pVideoDisplay->SetVideoPosition(NULL, &rcDest) - 它看起來像rcDest有錯誤的值 - 根據 IMFVideoDisplayControl::SetVideoPosition method

The destination rectangle defines a rectangle within the clipping window where the video appears. It is specified in pixels, relative to the client area of the window. To fill the entire window, set the destination rectangle to {0, 0, width, height},

我可以告訴研究CodeProject網站我的項目:NativeMediaFoundationPlayer:WPFMediaFoundationPlayer

的問候, Evgeny Pereguda

+0

謝謝您的回覆和鏈接!尤其是清理析構函數如何解鎖。現在不是這樣的謎。 –

1

該示例不正確地省略了COM初始化,這是不正確的。它應該通常稱爲CoInitialize [Ex]。您可以檢查Media Foundation的Windows SDK 7.x示例,並且示例顯示正確的初始化。例如this就是Transcode樣本。

正如Evgeny提到的,CComCritSecLockCComAutoCriticalSection是衆所周知的ATL類,它們可以幫助您自動解鎖關鍵部分。

使用這個類來鎖定和解鎖對象以更安全的方式比與CComCriticalSection類或CComAutoCriticalSection類。

+0

謝謝你的澄清!我沒有研究過MFPlayer2,因爲它使用了已棄用的IMFPMediaPlayer API,但是我會看看它是如何使用COM鎖定技術的。 –

+0

即使MFPlayer2可能使用了不贊成使用的(不好的例子,那就是),但是COM規則同樣適用。 –

0

對於其他人誰可能是工作我在OP中提到的該Polinger代碼示例中,我能夠做這個成功添加窗口大小調整到Polinger例如:

在winmain.cpp文件的WndProc回調函數,我說:

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
... 
    case WM_SIZE: 
     OnResize(LOWORD(lParam), HIWORD(lParam)); 
     break; 

那麼這個功能添加到winmain.cpp文件:

// Handler for WM_SIZE messages. 
void OnResize(WORD width, WORD height) 
{ 
    if (g_pPlayer) 
    { 
     g_pPlayer->ResizeVideo(width, height); 
    } 
} 

然後將此功能添加到Player.cpp文件中:

HRESULT CPlayer::ResizeVideo(WORD width, WORD height) 
{ 
    HRESULT hr = S_OK; 

    CComCritSecLock<CComAutoCriticalSection> lock(m_critSec); 

    if (m_pVideoDisplay) 
    { 
     // Set the destination rectangle. 
     RECT rcDest = { 0, 0, width, height }; 
     hr = m_pVideoDisplay->SetVideoPosition(NULL, &rcDest); 
    } 

    return hr; 
}