解码器如何使用 IAMVideoAccelerator

[与此页面关联的功能 DirectShow 是旧版功能。 它已被 MediaPlayerIMFMediaEngineMedia Foundation 中的音频/视频捕获所取代。 这些功能已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能在 Media Foundation 中使用 MediaPlayerIMFMediaEngine音频/视频捕获 ,而不是 DirectShow。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]

IAMVideoAccelerator 接口支持常规视频加速操作,包括 DirectX 视频加速 (VA) 。 对于非 DirectX VA 加速,解码器和视频驱动程序必须都遵循通用协议。

本部分介绍使用此接口时,任何解码器应遵循的一般操作顺序。 有关基于 DirectX VA 的解码器的详细信息,请参阅 将 DirectX 视频加速映射到 IAMVideoAccelerator

注意

此接口在 Windows 2000 及更高版本中可用。

 

IAMVideoAccelerator 接口在覆盖混音器或视频混合呈现器 (VMR) 的输入引脚上公开。 IAMVideoAcceleratorNotify 接口在解码器的输出引脚上公开。 连接筛选器引脚的事件序列如下所示:

  1. Filter Graph 管理器在解码器筛选器的输出引脚上调用 IPin::Connect AM_MEDIA_TYPE是可选参数。

    • AM_MEDIA_TYPE 是描述一种媒体类型的数据结构。 它包含主要类型 GUID (在本例中应MEDIATYPE_Video) 、子类型 GUID (在本例中应是视频加速器 GUID) 以及其他各种内容。 其中之一是包含媒体相关信息的格式类型 GUID,包括未压缩视频图片的宽度和高度,最有可能在 MPEG1VIDEOINFOVIDEOINFOHEADERMPEG2VIDEOINFOVIDEOINFOHEADER2 结构中
    • AM_MEDIA_TYPE结构(如果存在)指示解码器使用指定的媒体类型(可以是“完全指定”或“部分指定”)进行操作。 如果“完全指定”,解码器通常只是尝试使用该媒体类型进行操作。 如果“部分指定”,它将尝试查找“完全指定”兼容的操作模式,可以使用该模式以与“部分指定”媒体类型一致的方式进行连接。
    • 尝试查找用于连接的“完全指定”媒体类型的常规方式是,只需运行输出引脚支持的与“部分指定”媒体类型兼容的每个“完全指定”媒体类型的列表,并尝试与每个媒体类型连接,直到成功。 如果 IPin::Connect 调用中不包含任何AM_MEDIA_TYPE,但输出引脚需要检查其所有媒体类型,则此过程通常类似。
  2. 如果解码器想要检查下游输入引脚是否支持特定AM_MEDIA_TYPE (包括视频加速器 GUID) ,则可以调用该引脚的 IPin::QueryAccept (,并将视频加速器 GUID 用作AM_MEDIA_TYPE) 的子类型,也可以直接尝试连接到该引脚,如以下第 5 项所述。

  3. 如果解码器不知道下游输入引脚支持哪些视频加速器 GUID,并且不希望通过调用下游输入引脚的 IPin::QueryAccept 来仅建议某个特定的候选视频加速器 GUID,则解码器可以调用 IAMVideoAccelerator::GetVideoAcceleratorGUID 以获取该引脚支持的视频加速器 GUID 的列表。

  4. 对于某些特定的视频加速器 GUID,解码器可以调用下游输入引脚的 IAMVideoAccelerator::GetUncompFormatsSupported 以获取可用于呈现特定视频加速器 GUID 的 DDPIXELFORMAT 像素格式的列表。 应将返回的列表视为按优先顺序递减 (,即首先列出首选格式) 。

  5. 解码器调用下游输入引脚的 IPin::ReceiveConnection,向其传递 一个AM_MEDIA_TYPE ,其中正确的视频加速器 GUID 作为媒体类型的子类型。 这会为操作设置连接,包括创建未压缩的输出图面 (使用 在 AM_MEDIA_TYPE 中找到的宽度和高度进行分配,以及通过下述调用找到的要分配的图面数,以及视频加速器具有和希望用于该目的的任何其他信息,例如视频加速器 GUID 本身) 。 如果下游输入引脚拒绝视频加速器 GUID 或连接的其他某个方面,这可能会导致 IPin::ReceiveConnection 失败。 如果 IPin::ReceiveConnection 失败,则会在返回的 HRESULT 中指示这一点,解码器可以尝试再次进行调用,例如,在 AM_MEDIA_TYPE 结构中使用新的视频加速器 GUID。

  6. 呈现器调用解码器的 IAMVideoAcceleratorNotify::SetUncompSurfacesInfo,将分配的实际未压缩表面数传递给解码器。

  7. 呈现器调用解码器的 IAMVideoAcceleratorNotify::GetCreateVideoAcceleratorData ,以获取初始化视频加速器所需的任何数据。

  8. 解码器调用 IAMVideoAccelerator::GetCompBufferInfo,向其传递视频加速器 GUID、 AMVAUncompDataInfo 结构和压缩缓冲区类型的数量,以获取返回一组 AMVACompBufferInfo 数据结构,其中一个结构对应于视频加速器 GUID 所使用的每种类型的压缩数据缓冲区。

    • AMVAUncompDataInfo 结构包含解码的未压缩数据 (的宽度和高度(以像素) )和未压缩图片的 DDPIXELFORMAT。
    • 每个返回的 AMVACompBufferInfo 数据结构都包含:
      • 特定类型所需的压缩缓冲区数。

      • 要创建的图面的宽度和高度 (字段,这些字段可能具有或可能没有任何实际含义) 。

        注意

        压缩缓冲区的 DirectDraw surface 分配操作当前未规定这些图面的宽度或高度大于或等于 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 结构。

  2. 若要将未压缩的数据发送到加速器,解码器会调用:

  3. 若要完成目标缓冲区的输出处理,解码器调用 IAMVideoAccelerator::EndFrame。 它可以通过此调用向下游传递一些任意数据,这基本上就是此调用所导致的一切。 它不会在此调用中发送目标缓冲区索引,因此它无法向加速器准确指示已完成的目标缓冲区,除非此指示包含在传递的任意数据中。

  4. 为了显示帧,解码器调用 IAMVideoAccelerator::D isplayFrame,其中包含要显示的帧的索引,以及包含开始和停止时间戳和相关标志(如 AM_SAMPLE2_PROPERTIES 结构中的 dwTypeSpecificFlags)和 VIDEOINFOHEADER2 结构中的 dwInterlaceFlagsIMediaSample 结构。 解码器必须在调用 DisplayFrame 之前验证影响帧内容的所有解压缩操作是否已完成。

  5. 最后,解码器应在完成所有处理后,通过调用 IAMVideoAccelerator::EndFrame 来指示完成所有剩余的开始输出帧,并通过为每个未发布的缓冲区调用 IAMVideoAccelerator::ReleaseBuffer 释放其所有锁定的缓冲区。

解码器接口和规范