#winapi #directx-11 #ms-media-foundation #directx-12
#winapi #directx-11 #ms-media-foundation #directx-12
Вопрос:
Я использую примерный класс MediaEnginePlayer DirectX от Microsoft, определенный здесь и описанный здесь в настольном приложении Win32 в Windows 10.
После вызова setSource() для аудиофайла, подобного этому:
mePlayer->SetSource(L"c:\auddio.opus");
он автоматически начинает воспроизведение, потому что класс вызывает Play() после получения MF_MEDIA_ENGINE_EVENT_CANPLAY
события здесь.
Но если задано видео:
mePlayer->SetSource(L"c:\video.mp4"); //Won't play
он не воспроизводится. Чтобы запустить воспроизведение видео, мне нужно явно вызвать Play() либо до, либо после вызова setSource() .
//This will play
mePlayer->SetSource(L"c:\video.mp4");
mePlayer->Play();
//And even this will play
mePlayer->Play();
mePlayer->SetSource(L"c:\video.mp4");
Но я не понимаю, почему это так. Вот пример, демонстрирующий проблему: https://www.mediafire.com/file/6b61sxoou94d60r/Test.zip/file
Кто-нибудь может объяснить это поведение?
Комментарии:
1. Протестировал этот образец с разными видеофайлами, и он работает для меня без
mePlayer->Play()
дополнительного вызова. Убедитесь, что вы добавили свой видеофайл в папку ресурсов проекта и установили для его свойств значения «Содержимое: да» и «Тип элемента: Медиа». Вы получитеMF_MEDIA_ENGINE_EVENT_LOADEDMETADATA
, а затемMF_MEDIA_ENGINE_EVENT_CANPLAY
, после этого, начнется воспроизведение видео.2. Я также могу заставить образец работать. Но класс не выполняет то же самое для меня вне образца, и я не понимаю, почему. События, о которых вы упоминаете, срабатывают. Метод Play() вызывается после
MF_MEDIA_ENGINE_EVENT_CANPLAY
без ошибок. Я также получаюMF_MEDIA_ENGINE_EVENT_TIMEUPDATE
события. Однако без моего явного вызова Play()GetCurrentTime()
всегда сообщает ноль.3. Не могли бы вы показать мини-, полный и воспроизводимый образец?
4. Я не уверен, как его загрузить. Может быть, я смогу создать небольшую программу win32, которую я мог бы вставить сюда завтра, в которую можно было бы поместить класс. На самом деле вам не нужно отображать видео для его тестирования. Если он воспроизводится, вы услышите звук.
5. Может быть, вы можете поделиться им в Github.
Ответ №1:
Я могу воспроизвести эту проблему, используя ваш пример кода.
Вызов MediaEnginePlayer::Play()
при получении MF_MEDIA_ENGINE_EVENT_LOADEDMETADATA
решает эту проблему для меня. Вы можете попробовать.
О том, почему вызов MediaEnginePlayer::Play()
при получении MF_MEDIA_ENGINE_EVENT_CANPLAY
не работает, мне нужно провести дополнительное расследование.
Комментарии:
1. Он также воспроизводится для меня, если после вызова вызывается функция Play()
MF_MEDIA_ENGINE_EVENT_LOADEDMETADATA
, что действительно интересно, поскольку я считаю, что это происходит раньшеMF_MEDIA_ENGINE_EVENT_CANPLAY
и не гарантирует, что было загружено достаточно данных для успешного начала воспроизведения. Загадочно, как исходный образец может работать. Возможно, возникает какая-то странная асинхронная проблема? Спасибо, что посмотрели на это.2. @cecil Если вы закомментируете строки кода
MediaEnginePlayer::TransferFrame()
в примере UWP, воспроизводится та же проблема. Но если вы изменитеPlay()
сMF_MEDIA_ENGINE_EVENT_CANPLAY
наMF_MEDIA_ENGINE_EVENT_LOADEDMETADATA
, это сработает. В вашем примере кода Win32 CMediaEnginePlayer::TransferFrame()
никогда не выполняется. Таким образом, мы можем подтвердить, что эта проблема согласуется между Win32 C и UWP-приложением.3. Это отличное наблюдение. Я думаю, что именно это призвание
IMFMediaEngine::OnVideoStreamTick()
заставляет его работать и прогрессировать при воспроизведении. Вы можете закомментировать все остальное,MediaEnginePlayer::TransferFrame()
и оно будет воспроизводиться. Возможно, этот вызов является требованием воспроизведения видео. Мне все еще странно, что один вызовMediaEnginePlayer::Play()
в определенное время все равно приводит к его воспроизведению.4. Согласно MSDN :
MF_MEDIA_ENGINE_EVENT_CANPLAY
означает, что воспроизведение может начаться, но медиа-движку может потребоваться остановка для буферизации большего количества данных. Таким образом, исходя из понимания документа, он может быть не в состоянии воспроизводиться из-за буферизации данных. После тестирования, я думаю, вы можете использоватьMF_MEDIA_ENGINE_EVENT_LOADEDDATA
флаг, в документе говорится: Медиа-движок загрузил достаточно данных для отображения некоторого контента (например, видеокадра). И у меня это работает нормально.