audio - IMFMediaPlayer 在 SetSourceFromByteStream 期间挂起

标签 audio windows-runtime ms-media-foundation

背景:我正在为 Win8 编写一个 Metro 风格的应用程序。我需要能够播放音乐文件。由于质量和空间要求,我们使用编码音频 (mp3/ogg)。

我正在使用 XAudio2 播放音效(.wav 文件),但由于我想不出用它播放编码音频的方法,我决定使用 Media Foundation(IMFMediaPlayer 接口(interface))播放音乐文件。

我下载了 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 的更好方法,请告诉我)

最佳答案

无法弄清楚为什么会发生这种情况,但我设法编写了一个工作循环:
IMFSourceReader可用于解码 MP3 并将字节输入 XAudio2SourceVoice .
XAudio2 audio stream effect sample包含如何做到这一点的好例子。

关于audio - IMFMediaPlayer 在 SetSourceFromByteStream 期间挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11581384/

相关文章:

android - Android:找不到声音文件

c# - 拉伸(stretch) WrapGrid 项目宽度

windows - MFPCreateMediaPlayer 调用时出错

windows - 如何让自定义视频媒体/流接收器在媒体基础中请求 RGB32 帧?

swift - 线程1:播放声音时,EXC_BAD_ACCESS(代码= 1,地址= 0x48)

audio - Julia 中用于音频处理的实时 STFT 和 ISTFT

c# - 如何连接到 Windows 8.1 上的 Azure Blob 存储?

windows-8 - 为什么我无法访问 System.IO 命名空间中的isolatedStorage?

c++ - Windows Media Foundation MFT缓冲和视频质量问题(颜色丢失,而不是平滑的曲线,尤其是文本)

jquery - 让音频在移动 Safari 中播放?