背景:我正在为Win8编写一个地铁风格的应用程序。我需要能够播放音乐文件。由于质量和空间要求,我们使用编码音频(mp3 / ogg)。
我正在使用XAudio2播放声音效果(.wav文件),但由于我无法想出用它播放编码音频的方法,我决定用Media Foundation(IMFMediaPlayer界面)播放音乐文件。
我下载了metro应用示例,发现Media Engine Native C ++视频播放示例最接近我的需要。
现在我的应用程序有MediaPlayer播放音乐,我遇到了一个问题。如果运行应用程序的设备足够慢,MediaPlayer会挂起。当我在我的设备上运行应用程序的发布版本时,它很好,我可以听到音乐很好。但是当我连接调试器或在较慢的设备上运行时,它会在我为MediaPlayer设置字节流时挂起。
以下是一些代码,您会发现它与样本非常相似:
StorageFolder^ installedLocation = Windows::ApplicationModel::Package::Current->InstalledLocation;
m_pickFileTask = Concurrency::task<StorageFile^>(installedLocation->GetFileAsync(filename)), m_tcs.get_token());
auto player = this;
m_pickFileTask.then([player](StorageFile^ fileHandle)
{
player->SetURL(fileHandle->Path);
Concurrency::task<IRandomAccessStream^> fOpenStreamTask = Concurrency::task<IRandomAccessStream^> (fileHandle->OpenAsync(Windows::Storage::FileAccessMode::Read));
fOpenStreamTask.then([player](IRandomAccessStream^ streamHandle)
{
MEDIA::ThrowIfFailed(
player->m_spMediaEngine->Pause()
);
MEDIA::GetMediaError(player->m_spMediaEngine);
player->SetBytestream(streamHandle);
if (player->m_spMediaEngine)
{
MEDIA::ThrowIfFailed(
player->m_spEngineEx->Play()
);
MEDIA::GetMediaError(player->m_spMediaEngine);
}
}
);
}
);
这是SetBytestream方法:
SetBytestream(IRandomAccessStream^ streamHandle)
{
if(m_spMFByteStream != nullptr)
{
m_spMFByteStream->Close();
m_spMFByteStream = nullptr;
}
MEDIA::ThrowIfFailed(
MFCreateMFByteStreamOnStreamEx((IUnknown*)streamHandle, &m_spMFByteStream)
);
MEDIA::ThrowIfFailed(
m_spEngineEx->SetSourceFromByteStream(m_spMFByteStream.Get(), m_bstrURL)
);
MEDIA::GetMediaError(m_spEngineEx);
return;
}
它挂起的行是:
m_spEngineEx->SetSourceFromByteStream(m_spMFByteStream.Get(), m_bstrURL)
当我调试应用程序时,我可以按暂停并查看堆栈。嗯,不是很多,但至少我可以看到它无限期地
ntdll.dll!77b7f4dc()
为什么我的应用会以这种方式挂起的任何想法?
(可选:如果你知道在c ++ metro风格的应用程序中播放mp3 / ogg更好的方法,请告诉我)
答案 0 :(得分:0)
无法弄清楚为什么会发生这种情况,但我设法编写了一份工作代码:
IMFSourceReader
可用于解码MP3并将字节输入XAudio2SourceVoice
。
XAudio2 audio stream effect sample
包含了如何执行此操作的好示例。