2017-07-19 89 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; 
}