MediaEngine audio playback on WinRT

扶醉桌前 提交于 2019-12-11 07:18:58

问题


I'm trying to add music to my game that runs on WinRT. The music should be in an encoded format (mp3, ogg, etc.) and should be streamable and be decoded by the hardware (for performance reasons).

I've looked through the samples, and found out that MediaEngine can do something like this (I hope).

However, I'm having problems making it work. I keep getting ComExceptions everytime I try to create IMFByteStream from IRandomAccessStream via MFCreateMFByteStreamOnStreamEx().

It might be that I'm not handling tasks correctly, since they are a new paradigm for me.

Here's some code (pretty similar to the sample I mentioned before):

void MyMedia::PlayMusic ()
{
    try
    {
        StorageFolder^ installedLocation = Windows::ApplicationModel::Package::Current->InstalledLocation;

        Concurrency::task<StorageFile^> m_pickFileTask = Concurrency::task<StorageFile^>(installedLocation->GetFileAsync("music.mp3"), m_tcs.get_token());

        SetURL(StringHelper::toString("music.mp3"));

        auto player = this;
        m_pickFileTask.then([&player](StorageFile^ fileHandle)
        {
            Concurrency::task<IRandomAccessStream^> fOpenStreamTask = Concurrency::task<IRandomAccessStream^> (fileHandle->OpenAsync(Windows::Storage::FileAccessMode::Read));
            fOpenStreamTask.then([&player](IRandomAccessStream^ streamHandle)
                {
                    try
                    {
                        player->SetBytestream(streamHandle);

                        if (player->m_spMediaEngine)
                        {
                            MEDIA::ThrowIfFailed(
                                player->m_spMediaEngine->Play()
                                );

                        }
                    } catch(Platform::Exception^)
                    {
                        MEDIA::ThrowIfFailed(E_UNEXPECTED);
                    }

                }
            );  
        }
        );

    } catch(Platform::Exception^ ex)
    {
        Printf("error: %s", ex->Message);
    }


}

void MyMedia::SetBytestream(IRandomAccessStream^ streamHandle)
{
    HRESULT hr = S_OK;
    ComPtr<IMFByteStream> spMFByteStream = nullptr; 

    //The following line always throws a ComException
    MEDIA::ThrowIfFailed(
        MFCreateMFByteStreamOnStreamEx((IUnknown*)streamHandle, &spMFByteStream)
        );

    MEDIA::ThrowIfFailed(
        m_spEngineEx->SetSourceFromByteStream(spMFByteStream.Get(), m_bstrURL)
        );  

    return;
}

Bonus: If you know a better solution to my audio needs, please leave a comment.


回答1:


I managed to fix this. There was two problems I found.

  • Media Foundation was not initialized

MFStartup(MF_VERSION); needs to be called before Media Foundation can be used. I added this code just before creating the media engine.

  • Referencing a pointer.

Line m_pickFileTask.then([&player](StorageFile^ fileHandle) should be m_pickFileTask.then([player](StorageFile^ fileHandle). This is already a pointer to the current class, and & provides the address of variable, so I was actually passing the pointer's pointer.



来源:https://stackoverflow.com/questions/11307746/mediaengine-audio-playback-on-winrt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!