Воспроизведение звука MediaEngine на WinRT

Я пытаюсь добавить музыку в свою игру, работающую на WinRT. Музыка должна быть в закодированном формате (mp3, ogg и т. д.), должна поддерживать потоковую передачу и декодироваться аппаратно (по соображениям производительности).

Я просмотрел примеры и обнаружил, что MediaEngine может сделать что-то подобное (надеюсь).

Однако у меня проблемы с его работой. Я продолжаю получать ComExceptions каждый раз, когда пытаюсь создать IMFByteStream из IRandomAccessStream через MFCreateMFByteStreamOnStreamEx().

Возможно, я неправильно справляюсь с задачами, так как они для меня новая парадигма.

Вот некоторый код (очень похожий на пример, который я упоминал ранее):

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;
}

Бонус: если вы знаете лучшее решение для моих аудио потребностей, пожалуйста, оставьте комментарий.


person Habba    schedule 03.07.2012    source источник
comment
Что касается аппаратного декодирования: это зависит от аппаратного обеспечения (см. blogs.msdn.com/b/b8/archive/2012/06/08/ для более полного обзора)   -  person Sascha    schedule 03.07.2012
comment
Спасибо за ссылку. Я рассчитываю на то, что все основные портативные устройства смогут это сделать. Или же они не являются жизнеспособными игровыми платформами.   -  person Habba    schedule 03.07.2012


Ответы (1)


Мне удалось это исправить. Было две проблемы, которые я обнаружил.

  • Медиафонд не был инициализирован

MFStartup(MF_VERSION); необходимо вызвать, прежде чем можно будет использовать Media Foundation. Я добавил этот код непосредственно перед созданием медиадвижка.

  • Ссылка на указатель.

Строка m_pickFileTask.then([&player](StorageFile^ fileHandle) должна быть m_pickFileTask.then([player](StorageFile^ fileHandle). This уже является указателем на текущий класс, а & предоставляет адрес переменной, поэтому я фактически передавал указатель указателя.

person Habba    schedule 03.07.2012