Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом разделе описывается, как поддерживать DirectX Video Acceleration (DXVA) 2.0 в преобразовании Media Foundation (MFT) с помощью Microsoft Direct3D 9. В частности, он описывает взаимодействие между декодером и отрисовщиком видео, которое опосредуется загрузчиком топологии. В этом разделе не описывается, как реализовать декодирование DXVA.
В оставшейся части этой темы термин декодировщика относится к декодировщику MFT, который получает сжатое видео и выводит несжатое видео. Термин декодер устройства относится к аппаратному ускорителю видео, реализованному графическим драйвером.
Совет
Сведения о декодировании видео в Microsoft Direct3D 11 см. в поддержке декодирования видео Direct3D 11 в Media Foundation.
Заметка
Приложения Магазина Windows должны использовать Direct3D 11.
Ниже приведены основные шаги, которые декодеры должны выполнять для поддержки DXVA 2.0 в Media Foundation.
- Откройте хэндл к устройству Direct3D 9.
- Найдите конфигурацию декодировщика DXVA.
- Выделите несжатые буферы.
- Декодирование кадров.
Эти шаги подробно описаны в оставшейся части этого раздела.
Открытие дескриптора устройства Direct3D
MFT использует диспетчер устройств Microsoft Direct3D для получения дескриптора устройства Direct3D 9. Чтобы открыть дескриптор устройства, выполните следующие действия.
- Предоставить атрибут MF_SA_D3D_AWARE со значением TRUE. Загрузчик топологии запрашивает этот атрибут, вызывая IMFTransform::GetAttributes. Когда атрибут установлен в значение TRUE, это уведомляет загрузчик топологии о том, что MFT поддерживает DXVA.
- Когда начинается согласование формата, загрузчик топологии вызывает IMFTransform::ProcessMessage с сообщением MFT_MESSAGE_SET_D3D_MANAGER. Параметр ulParam является указателем IUnknown на диспетчер устройств Direct3D отрисовщика видео. Запросите этот указатель на интерфейс IDirect3DDeviceManager9.
- Вызовите IDirect3DDeviceManager9::OpenDeviceHandle, чтобы получить дескриптор устройства Direct3D, используемого отрисовщиком.
- Вызовите IDirect3DDeviceManager9::GetVideoService и передайте дескриптор устройства. Этот метод возвращает указатель на интерфейс IDirectXVideoDecoderService.
- Кэшируйте указатели и дескриптор устройства.
Поиск конфигурации декодера
MFT должен найти совместимую конфигурацию для устройства декодирования DXVA. Выполните следующие действия в методе IMFTransform::SetInputType после проверки входного типа:
Выполнен вызов IDirectXVideoDecoderService::GetDecoderDeviceGuids. Этот метод возвращает массив графических идентификаторов устройств декодировщика.
Прокрутите массив графических идентификаторов декодировщика, чтобы найти те, которые поддерживает декодировщик. Например, для декодера MPEG-2 вы будете искать DXVA2_ModeMPEG2_MOCOMP, DXVA2_ModeMPEG2_IDCTили DXVA2_ModeMPEG2_VLD.
Когда вы найдете GUID устройства-декодировщика, передайте этот GUID в метод IDirectXVideoDecoderService::GetDecoderRenderTargets. Этот метод возвращает массив форматов целевой отрисовки, указанные как D3DFORMAT значения.
Пройдите по целевым форматам отрисовки и найдите формат, поддерживаемый декодером.
Вызов функции IDirectXVideoDecoderService::GetDecoderConfigurations. Передайте один и тот же GUID устройства декодировщика, а также структуру DXVA2_VideoDesc, описывающую предлагаемый формат выходных данных. Метод возвращает массив DXVA2_ConfigPictureDecode структур. Каждая структура описывает одну возможную конфигурацию для устройства декодера. Найдите конфигурацию, которую поддерживает декодировщик.
Сохраните целевой формат и конфигурацию отрисовки.
В методе IMFTransform::GetOutputAvailableType возвращает несжатый формат видео на основе предлагаемого целевого формата отрисовки.
В методе IMFTransform::SetOutputType проверьте тип носителя на соответствие целевому формату отрисовки.
Переход на программное декодирование
Если MFT не может найти конфигурацию DXVA (например, если графический драйвер не имеет правильных возможностей), он должен вернуть код ошибки MF_E_UNSUPPORTED_D3D_TYPE из методов SetInputType и SetOutputType. Загрузчик топологии будет отвечать, отправив сообщение MFT_MESSAGE_SET_D3D_MANAGER со значением NULL для параметра ulParam. MFT необходимо освободить указатель на интерфейс IDirect3DDeviceManager9. Затем модуль загрузки топологии пересогласует тип носителя, и MFT может использовать программное декодирование.
Выделение несжатых буферов
В DXVA 2.0 декодатор отвечает за выделение поверхностей Direct3D для использования в качестве несжатых буферов видео. Декодатор должен выделить 3 поверхности для EVR, используемых для деинтерлакирования. Это число установлено, поскольку Media Foundation не предоставляет способ, чтобы EVR указал, сколько поверхностей требуется графическому драйверу для деинтерлейсинга. Для любого драйвера должно быть достаточно трех поверхностей.
В методе IMFTransform::GetOutputStreamInfo задайте флаг MFT_OUTPUT_STREAM_PROVIDES_SAMPLES в структуре MFT_OUTPUT_STREAM_INFO. Этот флаг уведомляет сеанс мультимедиа о том, что MFT выделяет собственные выходные образцы.
Чтобы создать поверхности, вызовите IDirectXVideoAccelerationService::CreateSurface. (Интерфейс IDirectXVideoDecoderService наследует этот метод от IDirectXVideoAccelerationService.) Это можно сделать в SetInputTypeпосле поиска целевого формата отрисовки.
Для каждой поверхности вызовите MFCreateVideoSampleFromSurface, чтобы создать образец носителя для хранения поверхности. Метод возвращает указатель на интерфейс IMFSample.
Расшифровка
Чтобы создать устройство декодирования, вызовите IDirectXVideoDecoderService::CreateVideoDecoder. Метод возвращает указатель на интерфейс IDirectXVideoDecoder декодирующего устройства.
Декодирование должно происходить внутри метода IMFTransform::P rocessOutput. В каждом кадре вызовите IDirect3DDeviceManager9::TestDevice для тестирования идентификатора устройства. Если устройство изменилось, метод возвращает DXVA2_E_NEW_VIDEO_DEVICE. В этом случае сделайте следующее:
- Закройте дескриптор устройства, вызвав IDirect3DDeviceManager9::CloseDeviceHandle.
- Отпустите указатели IDirectXVideoDecoderService и IDirectXVideoDecoder .
- Откройте новый дескриптор устройства.
- Согласование новой конфигурации декодировщика, как описано в разделе "Поиск конфигурации декодера" на этой странице.
- Создайте новое устройство декодировщика.
Если дескриптор устройства действителен, процесс декодирования работает следующим образом:
- Возьмите доступную поверхность, которая в настоящее время не используется. (Изначально все поверхности доступны.)
- Запрос примера мультимедиа для интерфейса IMFTrackedSample.
- Вызовите IMFTrackedSample::SetAllocator, а также предоставьте указатель на интерфейс IMFAsyncCallback, который реализован декодером. Когда средство отображения видео освобождает семпл, будет вызван обработчик обратного вызова декодера.
- Вызов IDirectXVideoDecoder::BeginFrame.
- Выполните одно или несколько раз:
- Вызовите IDirectXVideoDecoder::GetBuffer, чтобы получить буфер декодера DXVA.
- Заполните буфер.
- Вызов IDirectXVideoDecoder::ReleaseBuffer.
- Вызовите IDirectXVideoDecoder::Execute для выполнения операций декодирования кадра.
DXVA 2.0 использует те же структуры данных, что и DXVA 1.0 для декодирования операций. Для исходного набора профилей DXVA (для H.261, H.263 и MPEG-2) эти структуры данных описаны в спецификации DXVA 1.0.
В каждой паре вызовов BeginFrame/ Execute можно вызывать GetBuffer несколько раз, но только один раз для каждого типа буфера DXVA. При двойном вызове с одинаковым типом буфера вы перезаписываете данные.
Используйте обратный вызов из метода SetAllocator (шаг 3), чтобы отслеживать, какие образцы доступны в настоящий момент и какие используются.
Связанные разделы