Поддержка DXVA 2.0 в Media Foundation
В этом разделе описывается поддержка 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::P rocessMessage с сообщением MFT_MESSAGE_SET_D3D_MANAGER . Параметр ulParam является указателем IUnknown на диспетчер устройств Direct3D видео отрисовщика. Запросите этот указатель для интерфейса IDirect3DDeviceManager9 .
- Вызовите IDirect3DDeviceManager9::OpenDeviceHandle , чтобы получить дескриптор устройства Direct3D отрисовщика.
- Вызовите IDirect3DDeviceManager9::GetVideoService и передайте дескриптор устройства. Этот метод возвращает указатель на интерфейс IDirectXVideoDecoderService .
- Кэшируйте указатели и дескриптор устройства.
Поиск конфигурации декодера
MFT должен найти совместимую конфигурацию для устройства декодера DXVA. После проверки типа входных данных выполните следующие действия в методе IMFTransform::SetInputType :
Вызовите IDirectXVideoDecoderService::GetDecoderDeviceGuids. Этот метод возвращает массив идентификаторов GUID устройства декодера.
Циклически просматривайте массив GUID декодера, чтобы найти те, которые поддерживает декодер. Например, для декодера 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 должен освободить указатель на интерфейс IDirect3DeviceManager9 . Затем загрузчик топологии пересматривает тип носителя, а 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), чтобы отслеживать, какие примеры доступны в настоящее время, а какие используются.
Связанные темы