Поделиться через


Использование IAMVideoAccelerator в декодерах

[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует, чтобы новый код использовал MediaPlayer, IMFMediaEngine и аудио- и видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, использующий устаревшие API, чтобы по возможности использовать новые API.]

Интерфейс IAMVideoAccelerator позволяет выполнять универсальные операции с ускорением видео, включая Ускорение видео DirectX (VA). Для ускорения, отличного от DirectX VA, декодер и видеодрайвер должны соответствовать общему протоколу.

В этом разделе описывается общий порядок операций, которым должен следовать любой декодер при использовании этого интерфейса. Дополнительные сведения, относящиеся к декодерам на основе DirectX va, можно найти в статье Сопоставление ускорения видео DirectX с IAMVideoAccelerator.

Примечание

Этот интерфейс доступен в Windows 2000 и более поздних версиях.

 

Интерфейс IAMVideoAccelerator предоставляется на входной штырь микшера наложения или отрисовщика смешанного видео (VMR). Интерфейс IAMVideoAcceleratorNotify предоставляется в выходном контакте декодера. Последовательность событий для подключения контактов фильтра выглядит следующим образом:

  1. Диспетчер графа фильтра вызывает IPin::Connect в выходном контакте фильтра декодера. AM_MEDIA_TYPE является необязательным параметром.

    • AM_MEDIA_TYPE — это структура данных, описывающая тип носителя. Он содержит GUID основного типа (который в нашем случае должен быть MEDIATYPE_Video), подтип GUID (который в нашем случае должен быть GUID видео акселератора) и множество других вещей. Одна из них — guid типа формата, содержащий сведения о носителе, включая в нашем случае ширину и высоту несжатого видео, скорее всего, в структуре MPEG1VIDEOINFO, VIDEOINFOHEADER, MPEG2VIDEOINFO или VIDEOINFOHEADER2 .
    • Структура AM_MEDIA_TYPE , если она есть, указывает декодеру работать с использованием указанного типа носителя, который может быть "полностью указан" или "частично указан". Если значение "указано полностью", декодер обычно просто пытается работать с этим типом мультимедиа. Если параметр "частично указан", он попытается найти "полностью заданный" совместимый режим работы, который можно использовать для подключения способом, согласованным с типом носителя "частично заданный".
    • Обычно при попытке найти "полностью заданный" тип носителя, используемый для подключения, просто выполните список всех "полных" типов носителей, поддерживаемых выходной закреплением, который совместим с "частично заданным" типом мультимедиа, и попытаться подключиться к каждому из них до успешного выполнения. Обычно процесс будет аналогичным, если в вызове IPin::Connect не содержится AM_MEDIA_TYPE, но с выходным закреплением, требующим проверка всех типов мультимедиа.
  2. Если декодер хочет проверка, поддерживается ли определенный AM_MEDIA_TYPE (включая GUID видео акселератора) подчиненным входным контактом, он может вызвать IPin::QueryAccept этого контакта (с guid видео акселератора в качестве подтипа AM_MEDIA_TYPE) или просто попытаться подключиться к этому контакту, как описано в пункте 5 ниже.

  3. Если декодер не знает, какие GUID видео акселератора поддерживает подчиненный входной контакт, и не хочет предлагать только определенный GUID видео акселератора видео, вызвав IPin::QueryAccept подчиненного входного контакта, декодер может вызвать IAMVideoAccelerator::GetVideoAcceleratorGUIDs , чтобы получить список guidID видео акселератора, поддерживаемых закреплением.

  4. Для некоторых идентификаторов GUID видео акселератора декодер может вызывать IAMVideoAccelerator::GetUncompFormatsSupported для получения списка форматов пикселей DDPIXELFORMAT , которые можно использовать для отрисовки определенного GUID видео акселератора. Возвращаемый список следует рассматривать в порядке убывания предпочтения (т. е. с наиболее предпочтительным форматом).

  5. Декодер вызывает IPin::ReceiveConnection подчиненного входного контакта, передав ему AM_MEDIA_TYPE с соответствующим GUID видео акселератора в качестве подтипа типа мультимедиа. Это настраивает подключение для работы, включая создание несжатых выходных поверхностей (которые выделяются с использованием ширины и высоты, найденных в AM_MEDIA_TYPE, и количества поверхностей, которые необходимо выделить с помощью вызова, описанного ниже, и любых других сведений, доступных и желающих использовать для этой цели, таких как GUID видео акселератора). Если нижестоящий входной контакт отклоняет GUID видео акселератора или какой-либо другой аспект подключения, это может привести к сбою IPin::ReceiveConnection . Если IPin::ReceiveConnection завершается сбоем , это указывается в возвращенном HRESULT, и декодер может повторить вызов, например с помощью нового GUID видео акселератора в структуре AM_MEDIA_TYPE .

    • [!Примечание]

      Это еще один способ (и наиболее точный) для декодера определить, что поддерживается подчиненным контактом ввода— просто вызвать IPin::ReceiveConnection и попытаться подключиться, а затем проверить, была ли попытка подключения успешной.

       

    • Во время IPin::ReceiveConnection отрисовщик вызывает IAMVideoAcceleratorNotify::GetUncompSurfacesInfo, передав ему GUID видео акселератора и структуру AMVAUncompBufferInfo , чтобы определить, сколько несжатых поверхностей необходимо выделить. Декодер заполняет и возвращает структуру, содержащую минимальное и максимальное количество поверхностей, выделяемых для определенного типа, и структуру DDPIXELFORMAT , описывающую формат пикселей выделяемых поверхностей.

    • [!Примечание]

      В вызове IAMVideoAcceleratorNotify::GetUncompSurfacesInfo не передается ничего, кроме GUID видео акселератора.

       

  6. Отрисовщик вызывает IAMVideoAcceleratorNotify::SetUncompSurfacesInfo декодера, передавая декодеру фактическое количество выделенных поверхностей без сжатия.

  7. Отрисовщик вызывает IAMVideoAcceleratorNotify::GetCreateVideoAcceleratorData декодера , чтобы получить все данные, необходимые для инициализации видео акселератора.

  8. Декодер вызывает IAMVideoAccelerator::GetCompBufferInfo, передав ему GUID видео акселератора, структуру AMVAUncompDataInfo и количество типов сжатых буферов, чтобы получить в ответ набор структур данных AMVACompBufferInfo , соответствующих каждому типу буфера сжатых данных, используемого GUID видео ускорителя.

    • Структура AMVAUncompDataInfo содержит ширину и высоту декодированных несжатых данных (в пикселях) и DDPIXELFORMAT несжатого рисунка.
    • Возвращаемые структуры данных AMVACompBufferInfo содержат:
      • Количество сжатых буферов, необходимых для определенного типа.

      • Ширина и высота создаваемой поверхности (поля, которые могут иметь или не иметь реального значения).

        Примечание

        Операция выделения поверхности DirectDraw для сжатых буферов в настоящее время не предусматривает, чтобы ширина или высота этих поверхностей была больше или равна 2^15, хотя вызов выделения поверхности не может явно завершиться ошибкой, если это ограничение нарушено. Таким образом, драйвер может структурировать свои запросы на сжатые буферные памяти, чтобы избежать таких экстремальных размеров. Например, вместо того чтобы запрашивать буфер с width="1" и height="65536", драйвер должен запросить буфер width="1024" и height="64".

         

      • Общее количество байтов, используемых поверхностью.

      • Структура типа DDSCAPS2 , определяющая объект DirectDrawSurface, описывающая возможности создания поверхностей для хранения сжатых данных.

      • DDPIXELFORMAT, описывающий формат пикселей, используемый для создания поверхностей для хранения сжатых данных (поле, которое может иметь или не иметь никакого фактического значения).

Примечание

Вызовы отрисовщика некоторых методов интерфейса IAMVideoAcceleratorNotify декодера могут (и обычно будут происходить) внутри вызова декодера iPin::ReceiveConnection отрисовщика. В частности, это относится к следующим:

 

Примечание

Для поддержки динамических изменений формата декодер может также вызывать методЫ IPin::ReceiveConnection и другие описанные выше методы, пока фильтры подключены и запущены. Эта возможность предоставляется для поддержки динамических изменений формата (хотя и не в H.263, Приложение P, смысл , так как все наборы данных запускаются с нуля, и поэтому любая справочная информация о рисунке теряется).

 

Ниже приведено описание использования IAMVideoAccelerator во время операции после инициализации.

  1. Для каждой несжатой поверхности декодер вызывает IAMVideoAccelerator::BeginFrame , чтобы начать обработку для создания выходного изображения. При этом декодер отправляет структуру AMVABeginFrameInfo .

    • Структура AMVABeginFrameInfo содержит индекс для буфера назначения, указатель на некоторые данные для отправки вниз и указатель на место, где ускоритель может поместить некоторые данные для чтения декодером.

    • ПРИМЕЧАНИЕ 1. Ускоритель фактически не получает индекс буфера назначения, так как он преобразуется отрисовщиком перед переходом вниз.

    • ПРИМЕЧАНИЕ 2. IAMVideoAccelerator::BeginFrame можно вызывать несколько раз между вызовами IAMVideoAccelerator::EndFrame.

    • ПРИМЕЧАНИЕ 3. В операции интерфейса не предполагается, что IAMVideoAccelerator::BeginFrame и IAMVideoAccelerator::EndFrame должны вызываться для обработки каждого отдельного рисунка в битовом потоке.

      В интерфейсе IAMVideoAccelerator::BeginFrame создается связь в отрисовщике между индексом и несжатой поверхностью. Он также предоставляет средства для вызова определенной функции в драйвере устройства (с поддержкой средств передачи произвольных данных между декодером и драйвером устройства).

      (Однако в операции DirectX VA описано ниже требование, чтобы IAMVideoAccelerator::BeginFrame и IAMVideoAccelerator::EndFrame должны вызываться для обработки каждого отдельного изображения в битовом потоке.)

  2. Для отправки несжатых данных в ускоритель декодер вызывает:

    • IAMVideoAccelerator::QueryRenderStatus , чтобы определить, является ли буфер безопасным для чтения или записи в.
    • IAMVideoAccelerator::GetBuffer для блокировки и получения доступа к указанному буферу (если он ранее не вызывал этот метод для получения этого доступа). GetBuffer также можно использовать для получения копии содержимого последнего несжатого выходного рисунка, для которого был вызван IAMVideoAccelerator::BeginFrame , при условии, что IAMVideoAccelerator::EndFrame не был вызван для этого индекса целевого буфера. Если DDI возвращает состояние отрисовки DDERR_WASSTILLDRAWING для запрошенного буфера, в GetBuffer будет работать цикл спящего режима, пока это условие не будет снято. Чтобы вызвать GetBuffer, декодеру потребуются некоторые сведения из структуры данных AMVACompBufferInfo , полученной путем вызова IAMVideoAccelerator::GetCompBufferInfo.
    • IAMVideoAccelerator::Execute указывает, что данные в наборе сжатых буферов, как указано в массиве структур данных AMVABUFFERINFO , должны быть обработаны. В этом вызове драйверу передается код функции dwFunction. Указатель lpPrivateInputData также передается некоторым данным для отправки нисходящих данных, а указатель lpPrivateOutputData передается в место, где подчиненный процесс может поместить некоторые данные для чтения декодером.
    • IAMVideoAccelerator::ReleaseBuffer указывает, что декодер на данный момент завершил использование указанного буфера и больше не нуждается в заблокированном доступе к буферу. (Если декодер хочет продолжать использовать буфер, он может просто не вызывать IAMVideoAccelerator::ReleaseBufferer на данный момент, тем самым избегая необходимости вызывать IAMVideoAccelerator::GetBufferator, пока он действительно не намерен больше использовать буфер.) Декодер не должен записывать данные в буфер после вызова Execute , пока QueryRenderStatus не укажет, что буфер безопасен для записи.
  3. Чтобы завершить обработку выходных данных для буфера назначения, декодер вызывает IAMVideoAccelerator::EndFrame. Он может передавать некоторые произвольные данные ниже по этому вызову, и это, по сути, все, что происходит в результате этого вызова. Он не отправляет индекс буфера назначения в этом вызове, поэтому не может указать ускорителю, какой целевой буфер завершен, если это указание не содержится в произвольных передаваемых данных.

  4. Для отображения кадра декодер вызывает IAMVideoAccelerator::D isplayFrame с индексом отображаемого кадра и структурой IMediaSample , содержащей метки времени начала и остановки и соответствующие флаги, такие как dwTypeSpecificFlags в структуре AM_SAMPLE2_PROPERTIES и dwInterlaceFlags в структуре VIDEOINFOHEADER2 . Перед вызовом DisplayFrame декодер должен убедиться, что все операции распаковки, влияющие на содержимое кадра, завершены.

  5. Наконец, после завершения всей обработки декодер должен указывать на завершение всех оставшихся начатых выходных кадров путем вызова IAMVideoAccelerator::EndFrame и освобождения всех заблокированных буферов путем вызова IAMVideoAccelerator::ReleaseBufferer для каждого неизданного буфера.

Интерфейсы и спецификации декодера