Поддержка декодирования видео Direct3D 11 в Media Foundation

В этом разделе описывается, как поддерживать Microsoft Direct3D 11 в декоде Microsoft Media Foundation. В частности, он описывает взаимодействие между декодером и отрисовщиком видео. В этом разделе не описывается реализация операций декодирования.

Обзор

В оставшейся части этого раздела используются следующие термины:

  • Декодирования программного обеспечения. Декодирования программного обеспечения — это преобразование Media Foundation (MFT), которое получает сжатые примеры видео и выводит несжатые видеокадры.
  • Устройство декодировщика. Устройство декодировщика — это ускоритель видео и реализуется графическим драйвером. Устройство декодировщика выполняет операции ускорения декодирования.
  • Воронка продаж. Конвейер размещает декодирования программного обеспечения и предоставляет буферы в декодатор программного обеспечения и из нее. В зависимости от приложения конвейер может быть сеансом мультимедиа, средством чтения источника или кодом приложения, который напрямую вызывается в MFT.

Чтобы выполнить декодирование с помощью Direct3D 11, декодирования программного обеспечения должен иметь указатель на устройство Direct3D 11. Устройство Direct3D 11 создается внешне для декодирования программного обеспечения. В сценарии сеанса мультимедиа средство отрисовки видео создает устройство Direct3D 11. В сценарии чтения источника обычно приложение создает устройство Direct3D 11.

Диспетчер устройств DXGI используется для совместного использования Direct3D 11 между компонентами. Диспетчер устройств DXGI предоставляет интерфейс IMFDXGIDeviceManager. Конвейер задает указатель МВФDXGIDeviceManager на декодирования программного обеспечения, отправив сообщение MFT_MESSAGE_SET_D3D_MANAGER.

На следующей схеме показана связь между декодером программного обеспечения, Direct3D 11 и конвейером.

a diagram that shows the software decoder and the dxgi device manager.

Ниже приведены основные шаги, которые должен выполнять декодирования программного обеспечения для поддержки Direct3D 11 в Media Foundation:

  1. Откройте дескриптор устройства Direct3D 11.
  2. Найдите конфигурацию декодера.
  3. Выделите несжатые буферы.
  4. Декодирование кадров.

Эти шаги подробно описаны в оставшейся части этого раздела.

Открытие дескриптора устройства

Декодирования MFT использует диспетчер устройств DXGI для получения дескриптора на устройство Direct3D 11. Чтобы открыть дескриптор устройства, выполните следующие действия.

  1. Декодирования MFT должен предоставлять атрибут MF_SA_D3D11_AWARE со значением TRUE.
  2. Загрузчик топологии запрашивает этот атрибут путем вызова IMFTransform::GetAttributes. Значение TRUE указывает, что MFT поддерживает Direct3D 11.
  3. Загрузчик топологии вызывает МВФTransform::P rocessMessage с сообщением MFT_MESSAGE_SET_D3D_MANAGER. Параметр ulParam — это указатель IUnknown на диспетчер устройств DXGI. Запросите этот указатель для интерфейса МВФDXGIDeviceManager.
  4. ВызовИТЕ МВФDXGIDeviceManager::OpenDeviceHandle , чтобы получить дескриптор устройства Direct3D 11.
  5. Чтобы получить указатель на устройство Direct3D 11, вызовите МВФDXGIDeviceManager::GetVideoService. Передайте дескриптор устройства и значение IID_ID3D11Device. Метод возвращает указатель на интерфейс ID3D11Device.
  6. Чтобы получить указатель на акселератор видео, снова вызовите МВФDXGIDeviceManager::GetVideoService . На этот раз передайте дескриптор устройства и значение IID_ID3D11VideoDevice. Метод возвращает указатель на интерфейс ID3D11VideoDevice.
  7. Вызов ID3D11Device::GetImmediateContext для получения указателя ID3D11DeviceContext.
  8. Вызов QueryInterface на идентификаторе ID3D11DeviceContext, чтобы получить указатель ID3D11VideoContext.
  9. Рекомендуется использовать защиту нескольких потоков в контексте устройства, чтобы предотвратить проблемы взаимоблокировки, которые иногда могут возникать при вызове ID3D11VideoContext::GetDecoderBuffer или ID3D11VideoContext::ReleaseDecoderBuffer. Чтобы задать защиту с несколькими потоками, сначала вызовите QueryInterface в ID3D11Device, чтобы получить указатель id3D10Multithread. Затем вызовите ID3D10Multithread::SetMultithreadProtected, передавая значение true для bMTProtect.

Поиск конфигурации декодера

Чтобы выполнить декодирование, декодировщик программного обеспечения должен найти совместимую конфигурацию, поддерживаемую устройством декодировщика, включая формат целевого объекта отрисовки. Этот шаг выполняется внутри метода МВФTransform::SetInputType , как показано ниже.

  1. Проверьте тип входного носителя. Если тип отклонен, пропустите оставшиеся шаги и верните код ошибки.
  2. Вызов ID3D11VideoDevice::GetVideoDecoderProfileCount , чтобы получить количество поддерживаемых профилей.
  3. Вызовите ID3D11VideoDevice::GetVideoDecoderProfile , чтобы перечислить профили и получить идентификаторы GUID профиля.
  4. Найдите GUID профиля, соответствующий формату видео и возможностям декодера программного обеспечения. Например, декодатор MPEG-2 будет искать D3D11_DECODER_PROFILE_MPEG2_MOCOMP,D3D11_DECODER_PROFILE_MPEG2_IDCT и D3D11_DECODER_PROFILE_MPEG2_VLD.
  5. Если найден подходящий guid декодировщика, проверка выходной формат путем вызова метода ID3D11VideoDevice::CheckVideoDecoderFormat. Передайте идентификатор GUID декодера и значение DXGI_FORMAT , указывающее формат целевого объекта отрисовки.
  6. Затем найдите подходящую конфигурацию для декодера.
    1. Вызов ID3D11VideoDevice::GetVideoDecoderConfigCount , чтобы получить количество конфигураций декодировщика. Передайте один и тот же GUID устройства декодировщика, а также структуру D3D11_VIDEO_DECODER_DESC , описывающую предлагаемый формат целевого объекта отрисовки.
    2. Вызовите ID3D11VideoDevice::GetVideoDecoderConfig , чтобы перечислить конфигурации декодировщика.

В методе IMFTransform::GetOutputAvailableType возвращает несжатый формат видео на основе предлагаемого формата целевого объекта отрисовки.

В методе IMFTransform::SetOutputType проверка тип мультимедиа для целевого формата отрисовки.

Резервное копирование в декодирование программного обеспечения

MFT может быть не удается найти конфигурацию. Например, графический драйвер может не поддерживать правильные возможности. В этом случае MFT должен вернуться к декодированию программного обеспечения, как показано ниже.

  1. Методы SetInputType и SetOutputType должны возвращать MF_E_UNSUPPORTED_D3D_TYPE.
  2. В ответ загрузчик топологии отправит сообщение MFT_MESSAGE_SET_D3D_MANAGER со значением NULL для параметра ulParam .
  3. MFT освобождает указатель на интерфейс МВФDXGIDeviceManager.
  4. Загрузчик топологии перенацеливает тип носителя.

На этом этапе MFT может использовать декодирование программного обеспечения.

Выделение несжатых буферов

Декодировщик отвечает за выделение текстур Direct3D 11 для использования в качестве несжатых буферов видео. Атрибут MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT в атрибутах потока вывода (см. МВФТрансформ::GetOutputStreamAttributes) используется для определения количества поверхностей декодировщика, которые следует выделить для отрисовщика видео, используемого для деинтерлакирования. Декодатор должен использовать это значение, ограничивающее его для некоторых разумных верхних и нижних пределов, например 3-32. Для прогрессивного содержимого см . MF_SA_MINIMUM_OUTPUT_SAMPLE_COUNT_PROGRESSIVE.

В методе IMFTransform::GetOutputStreamInfo задайте флаг MFT_OUTPUT_STREAM_PROVIDES_SAMPLES в структуре MFT_OUTPUT_STREAM_INFO. Этот флаг уведомляет сеанс мультимедиа о том, что MFT выделяет собственные выходные образцы. Чтобы выделить выходные примеры, MFT выполняет следующие действия:

  1. Создайте массив текстур 2D путем вызова ID3D11Device::CreateTexture2D. В структуре D3D11_TEXTURE2D_DESC задайте arraySize равным количеству поверхностей, необходимых декодировщику. В том числе:

    • Поверхности для эталонных кадров.
    • Поверхности для деинтерлакирования (три поверхности).
    • Поверхности, необходимые декодировщику для буферизации.

    Флаги привязки (BindFlags) должны включать флаг D3D11_BIND_DECODER и все флаги привязки, заданные через атрибут MF_SA_D3D11_BINDFLAGS в атрибутах выходного потока.

  2. Для каждой поверхности в массиве текстур вызовите ID3D11VideoDevice::CreateVideoDecoderOutputView , чтобы создать представление вывода декодировщика видео. Во время декодирования эти выходные представления будут переданы методу ID3D11VideoContext::D ecoderBeginFrame .

  3. Для каждой поверхности в массиве текстур создайте образец носителя следующим образом:

    1. Создайте буфер мультимедиа DXGI, вызвав функцию MFCreateDXGISurfaceBuffer. Передайте указатель ID3D11Texture2D и смещение для каждого элемента в массиве текстур. Функция возвращает указатель МВФMediaBuffer.
    2. Создайте пустой образец носителя, вызвав функцию MFCreateVideoSampleFromSurface. Задайте для параметра pUnkSurface значение NULL. Функция возвращает указатель МВФSample.
    3. Вызов IMFSample::AddBuffer , чтобы добавить буфер мультимедиа в пример.

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

Декодирования

Чтобы создать устройство декодировщика, вызовите ID3D11VideoDevice::CreateVideoDecoder. Метод возвращает указатель на интерфейс ID3D11VideoDecoder. Декодирование должно происходить внутри метода IMFTransform::P rocessOutput. В каждом кадре вызовите МВФDXGIDeviceManager::TestDevice для проверки доступности DXGI. Если устройство изменилось, декодирования программного обеспечения должен повторно создать устройство декодировщика, как показано ниже.

  1. Закройте дескриптор устройства, вызвав IMFDXGIDeviceManager::CloseDeviceHandle.
  2. Выпустите все ресурсы, связанные с предыдущим устройством Direct3D 11, включая интерфейсы ID3D11VideoDecoder, ID3D11VideoContext, ID3D11Texture2D и ID3D11VideoDecoderOutputView.
  3. Откройте новый дескриптор устройства.
  4. Согласование новой конфигурации декодировщика, как описано ранее в разделе "Поиск конфигурации декодера". Этот шаг необходим, так как возможности устройства могли измениться.
  5. Создайте новое устройство декодировщика.

Если дескриптор устройства действителен, процесс декодирования работает следующим образом:

  1. Получите доступную поверхность, которая в настоящее время не используется. Изначально все поверхности доступны.
  2. Запрос примера мультимедиа для интерфейса IMFTrackedSample.
  3. Вызов МВФTrackedSample::SetAllocator и укажите указатель на интерфейс МВФAsyncCallback. (Декодировщик программного обеспечения должен реализовать этот интерфейс.) Когда средство отрисовки видео освобождает пример, обратный вызов будет вызван. Используйте этот обратный вызов, чтобы отслеживать, какие примеры доступны в настоящее время и которые используются.
  4. Вызов ID3D11VideoContext::D ecoderBeginFrame. Передайте указатель на интерфейс ID3D11VideoDecoder для устройства декодера и интерфейса ID3D11VideoDecoderOutputView для представления выходных данных.
  5. Выполните одно или несколько раз:
    1. Вызовите ID3D11VideoContext::GetDecoderBuffer , чтобы получить буфер.
    2. Заполните буфер.
    3. Вызов ID3D11VideoContext::ReleaseDecoderBuffer.
    4. Вызов ID3D11VideoContext::SubmitDecoderBuffer. Этот метод указывает устройству декодировщика выполнять операции декодирования кадра.
  6. Вызов ID3D11VideoContext::D ecoderEndFrame , чтобы сигнализировать о завершении декодирования текущего кадра.

Direct3D 11 использует те же структуры данных, что и DXVA 2.0 для декодирования операций. Для исходного набора профилей DXVA (для H.261, H.263 и MPEG-2) эти структуры данных описаны в спецификации DXVA 1.0.

В каждой паре вызовов DecoderBeginFrame и SubmitDecoderBuffer можно вызывать GetDecoderBuffer несколько раз, но только один раз для каждого типа буфера. Если вы используете один и тот же тип буфера дважды без вызова SubmitDecoderBuffer, вы перезаписываете данные в буфере.

API видео Direct3D 11

Ускорение видео DirectX 2.0