我现在正在爬上Windows Media Foundation陡峭的学习曲线,我正专注于两个非常相似的代码示例,以帮助我理解这项技术。尽管两者都使用媒体会话来播放一个非常简单的播放文件视频的“播放”节目,但是存在重要的细微差别。
第一个样本是微软的MF Play,位于:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd979592(v=vs.85).aspx
它没有初始化COM,也没有执行任何关键部分锁定,但它播放视频非常好。缺少使用COM是否会限制它在其他方面的使用,例如在处理多个视频流以通过多线程分离窗口时?由于此代码在线,我可能天真地假设此代码更新。
第二个样本来自“开发Microsoft Media Foundation Applications - 作者:Anton Polinger”一书。我从这里下载了示例代码: https://www.microsoftpressstore.com/content/images/9780735656598/downloads/9780735656598_files.zip
由于使用了这些COM初始化函数,第3章文件夹中的Play程序稍微复杂一些:
// initialize COM
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
...
// uninitialize COM
CoUninitialize();
它还使用以下几个关键部分锁:
CComCritSecLock<CComAutoCriticalSection> lock(m_critSec);
但神秘的是没有相应的解锁()。那么有人可以解释这两个代码示例之间潜在的重要差异以及我应该使用哪些代码示例?我担心如果我不使用COM方法,我可能会在以后尝试将多个视频流式传输到多个窗口时遇到问题,或者更糟糕的是我可能遇到可靠性问题。
另一方面,Polinger代码有效,但在播放视频时无法处理窗口大小调整。我尝试在窗口调整大小事件后使用此代码添加类似于MS代码的代码:
m_pVideoDisplay->SetVideoPosition(NULL, &rcDest)
使用它只会导致程序冻结。
非常感谢任何帮助!
答案 0 :(得分:1)
关于&#34;它没有初始化COM&#34; - 你没有看到它的所有代码 - 研究Media Session Playback Example - 你会在player.cpp中找到调用MFStartup
- 这对MediaFoundation(MF)来说已经足够了。我读过Polinger的书,在代码中它调用了一些COM线程模型敏感函数 - 例如,DirectX。但是,根据我的经验,看起来MF从MFStartup
调用的上下文调用CoInitialize。更重要的是,在Polinger的书代码中,有一个叫公主线程模型:hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
,但MF支持从多线程模型执行 - 它对它不敏感。
关于&#34;但神秘的是没有相应的解锁()。&#34; - 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
答案 1 :(得分:1)
示例不准确地省略了COM初始化,这是不正确的。应该以通常的方式调用CoInitialize [Ex]。您可以检查Media Foundation的Windows SDK 7.x示例,并且示例显示正确的初始化。例如,this是Transcode
样本的执行方式。
正如Evgeny所提到的,CComCritSecLock
和CComAutoCriticalSection
是众所周知的,并且记录了ATL类,它们可以帮助您自动解锁关键部分。
使用此类以比
CComCriticalSection
班级或CComAutoCriticalSection
班级更安全的方式锁定和解锁对象。
答案 2 :(得分: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;
}