DXVA 视频处理

DXVA 视频处理封装了用于处理未压缩视频图像的图形硬件的功能。 视频处理服务包括反交错和视频混合。

本主题包含以下各节:

概述

图形硬件可以使用图形处理单元 (GPU) 来处理未压缩的视频图像。 视频处理设备是封装这些功能的软件组件。 应用程序可以使用视频处理设备来执行诸如以下功能:

  • 反交错和反转电视
  • 将视频子流混合到主视频图像上
  • 颜色调整 (ProcAmp) 和图像筛选
  • 图像缩放
  • 颜色空间转换
  • alpha 值混合处理

下图显示了视频处理管道中的阶段。 该图并不表示实际执行情况。 例如,图形驱动程序可以将多个阶段合并到单个操作中。 所有这些操作都可以在对视频处理设备的单个调用中执行。 驱动程序可能不支持此处显示的一些阶段,例如噪音和详细信息筛选。

diagram showing the stages of dxva video processing.

视频处理管道的输入始终包含视频流,其中包含主图像数据。 主视频流决定输出视频的帧频。 输出视频的每个帧都相对于主要视频流的输入数据进行计算。 主流中的像素始终不透明,没有每像素 alpha 数据。 主视频流可以是渐进式或交错的。

视频处理管道可选择接收多达 15 个视频子流。 子流包含辅助图像数据,例如隐藏式字幕或 DVD 子图片。 这些图像通过主视频流显示,通常不会自行显示。 子流图片可以包含每像素 alpha 数据,并且始终是渐进式帧。 视频处理设备将子流图像与主视频流中的当前反交错帧进行 alpha 混合。

在本主题的其余部分,术语图片用于视频处理设备的输入数据。 图片可能包含渐进式框架、单个字段或两个交错字段。 输出始终是无交错的帧。

视频驱动程序可以实现多个视频处理设备,以提供不同的视频处理功能集。 设备由 GUID 标识。 以下 GUID 是预定义的:

  • DXVA2_VideoProcBobDevice。 此设备执行 bob 取消交错。
  • DXVA2_VideoProcProgressiveDevice。 如果视频仅包含渐进式帧,且没有交错帧,则使用此设备。 (一些视频内容包含渐进式和交错帧的组合。渐进式设备不能用于此类“混合”视频内容,因为交错帧需要反交错步骤。)

支持 DXVA 视频处理的每个图形驱动程序必须至少实现这两台设备。 图形驱动程序还可以提供其他设备,这些设备由特定于驱动程序的 GUID 标识。 例如,驱动程序可能实现专有的反交错算法,该算法可生成比 bob 反交错更好的输出质量。 某些反交错算法可能需要从主流中向前或向后引用图片。 如果是这样,调用方必须按照正确的顺序将这些图片提供给驱动程序,如本节稍后所述。

还提供了参考软件设备。 软件设备针对质量而不是速度进行优化,可能不足以进行实时视频处理。 引用软件设备使用 GUID 值 DXVA2_VideoProcSoftwareDevice。

创建视频处理设备

在使用 DXVA 视频处理之前,应用程序必须创建视频处理设备。 以下是有关步骤的简要概述,本节其余部分将对这些步骤进行更详细的解释:

  1. 获取指向 IDirectXVideoProcessorService 接口的指针。
  2. 为主要视频流创建视频格式的说明。 使用此说明获取支持视频格式的视频处理设备的列表。 设备由 GUID 标识。
  3. 对于特定设备,获取设备支持的渲染-目标格式列表。 格式作为 D3DFORMAT值列表返回。 如果计划混合子流,还需获取支持的子流格式列表。
  4. 查询每个设备的功能。
  5. 创建视频处理设备。

有时可以省略其中一些步骤。 例如,你可以尝试使用首选格式创建视频处理设备,而不是获取渲染-目标格式的列表,并查看它是否成功。 常见的格式(如 D3DFMT_X8R8G8B8)可能会成功。

本部分的其余部分详细介绍了这些步骤。

获取 IDirectXVideoProcessorService 指针

从 Direct3D 设备获取 IDirectXVideoProcessorService 接口。 可通过两种方法获取指向此接口的指针:

如果有指向 Direct3D 设备的指针,可以通过调用 DXVA2CreateVideoService 函数来获取 IDirectXVideoProcessorService 指针。 传入指向设备的 IDirect3DDevice9 接口的指针,并为 riid 参数指定 IID_IDirectXVideoProcessorService,如以下代码所示:

    // Create the DXVA-2 Video Processor service.
    hr = DXVA2CreateVideoService(g_pD3DD9, IID_PPV_ARGS(&g_pDXVAVPS));

在某些情况下,一个对象会创建 Direct3D 设备,然后通过 Direct3D 设备管理器与其他对象共享它。 在这种情况下,可以在设备管理器上调用 IDirect3DDeviceManager9::GetVideoService 以获取 IDirectXVideoProcessorService 指针,如以下代码所示:

HRESULT GetVideoProcessorService(
    IDirect3DDeviceManager9 *pDeviceManager,
    IDirectXVideoProcessorService **ppVPService
    )
{
    *ppVPService = NULL;

    HANDLE hDevice;

    HRESULT hr = pDeviceManager->OpenDeviceHandle(&hDevice);
    if (SUCCEEDED(hr))
    {
        // Get the video processor service 
        HRESULT hr2 = pDeviceManager->GetVideoService(
            hDevice, 
            IID_PPV_ARGS(ppVPService)
            );

        // Close the device handle.
        hr = pDeviceManager->CloseDeviceHandle(hDevice);

        if (FAILED(hr2))
        {
            hr = hr2;
        }
    }

    if (FAILED(hr))
    {
        SafeRelease(ppVPService);
    }

    return hr;
}

枚举视频处理设备

若要获取视频处理设备的列表,请使用主视频流的格式填写 DXVA2_VideoDesc 结构,并将此结构传递给 IDirectXVideoProcessorService::GetVideoProcessorDeviceGuids 方法。 该方法返回一个 GUID 数组,每个可与该视频格式一起使用的视频处理设备都有一个 GUID。

请考虑应用程序,它使用 BT.709 对 YUV 颜色的定义,以每秒 29.97 帧的帧速率渲染 YUY2 格式的视频流。 假设视频内容完全由渐进式帧组成。 以下代码片段演示如何填写格式说明并获取设备 GUID:

    // Initialize the video descriptor.

    g_VideoDesc.SampleWidth                         = VIDEO_MAIN_WIDTH;
    g_VideoDesc.SampleHeight                        = VIDEO_MAIN_HEIGHT;
    g_VideoDesc.SampleFormat.VideoChromaSubsampling = DXVA2_VideoChromaSubsampling_MPEG2;
    g_VideoDesc.SampleFormat.NominalRange           = DXVA2_NominalRange_16_235;
    g_VideoDesc.SampleFormat.VideoTransferMatrix    = EX_COLOR_INFO[g_ExColorInfo][0];
    g_VideoDesc.SampleFormat.VideoLighting          = DXVA2_VideoLighting_dim;
    g_VideoDesc.SampleFormat.VideoPrimaries         = DXVA2_VideoPrimaries_BT709;
    g_VideoDesc.SampleFormat.VideoTransferFunction  = DXVA2_VideoTransFunc_709;
    g_VideoDesc.SampleFormat.SampleFormat           = DXVA2_SampleProgressiveFrame;
    g_VideoDesc.Format                              = VIDEO_MAIN_FORMAT;
    g_VideoDesc.InputSampleFreq.Numerator           = VIDEO_FPS;
    g_VideoDesc.InputSampleFreq.Denominator         = 1;
    g_VideoDesc.OutputFrameFreq.Numerator           = VIDEO_FPS;
    g_VideoDesc.OutputFrameFreq.Denominator         = 1;

    // Query the video processor GUID.

    UINT count;
    GUID* guids = NULL;

    hr = g_pDXVAVPS->GetVideoProcessorDeviceGuids(&g_VideoDesc, &count, &guids);

此示例的代码取自 DXVA2_VideoProc SDK 示例。

此示例中的 pGuids 数组由 GetVideoProcessorDeviceGuids 方法分配,因此应用程序必须通过调用 CoTaskMemFree 释放该数组。 可以使用此方法返回的任何设备 GUID 执行其余步骤。

枚举渲染-目标格式

若要获取设备支持的渲染-目标格式列表,请将设备 GUID 和DXVA2_VideoDesc结构传递给 IDirectXVideoProcessorService::GetVideoProcessorRenderTargets 方法,如以下代码所示:

    // Query the supported render-target formats.

    UINT i, count;
    D3DFORMAT* formats = NULL;

    HRESULT hr = g_pDXVAVPS->GetVideoProcessorRenderTargets(
        guid, &g_VideoDesc, &count, &formats);

    if (FAILED(hr))
    {
        DBGMSG((L"GetVideoProcessorRenderTargets failed: 0x%x.\n", hr));
        return FALSE;
    }

    for (i = 0; i < count; i++)
    {
        if (formats[i] == VIDEO_RENDER_TARGET_FORMAT)
        {
            break;
        }
    }

    CoTaskMemFree(formats);

    if (i >= count)
    {
        DBGMSG((L"The device does not support the render-target format.\n"));
        return FALSE;
    }

该方法返回 D3DFORMAT 值的数组。 在此示例中,输入类型为 YUY2,典型的格式列表可能是 D3DFMT_X8R8G8B8(32 位 RGB)和 D3DMFT_YUY2(输入格式)。 但是,确切列表将取决于驱动程序。

子流的可用格式列表可能因渲染-目标格式和输入格式而异。 若要获取子流格式的列表,请将设备 GUID、格式结构和渲染-目标格式传递给 IDirectXVideoProcessorService::GetVideoProcessorSubStreamFormats 方法,如以下代码所示:

    // Query the supported substream formats.

    formats = NULL;

    hr = g_pDXVAVPS->GetVideoProcessorSubStreamFormats(
        guid, &g_VideoDesc, VIDEO_RENDER_TARGET_FORMAT, &count, &formats);

    if (FAILED(hr))
    {
        DBGMSG((L"GetVideoProcessorSubStreamFormats failed: 0x%x.\n", hr));
        return FALSE;
    }

    for (i = 0; i < count; i++)
    {
        if (formats[i] == VIDEO_SUB_FORMAT)
        {
            break;
        }
    }

    CoTaskMemFree(formats);

    if (i >= count)
    {
        DBGMSG((L"The device does not support the substream format.\n"));
        return FALSE;
    }

该方法返回 D3DFORMAT 值的数组。 典型的子流格式为 AYUV 和 AI44。

查询设备功能

若要获取特定设备的功能,请将设备 GUID、格式结构和渲染-目标格式传递给 IDirectXVideoProcessorService::GetVideoProcessorCaps 方法。 该方法使用设备功能填充 DXVA2_VideoProcessorCaps 结构。

    // Query video processor capabilities.

    hr = g_pDXVAVPS->GetVideoProcessorCaps(
        guid, &g_VideoDesc, VIDEO_RENDER_TARGET_FORMAT, &g_VPCaps);

    if (FAILED(hr))
    {
        DBGMSG((L"GetVideoProcessorCaps failed: 0x%x.\n", hr));
        return FALSE;
    }

创建设备

若要创建视频处理设备,请调用 IDirectXVideoProcessorService::CreateVideoProcessor。 此方法的输入是设备 GUID、格式说明、渲染-目标格式以及计划混合的最大子流数。 该方法返回指向 IDirectXVideoProcessor 接口的指针,该接口表示视频处理设备。

    // Finally create a video processor device.

    hr = g_pDXVAVPS->CreateVideoProcessor(
        guid,
        &g_VideoDesc,
        VIDEO_RENDER_TARGET_FORMAT,
        SUB_STREAM_COUNT,
        &g_pDXVAVPD
        );

视频进程位块传送

主要视频处理操作是视频处理位块传送。 (位块传送是将两个或多个位图合并成单个位图的任何操作。视频处理位块传送结合了输入图片以创建输出帧。)若要执行视频处理位块传送,请调用 IDirectXVideoProcessor::VideoProcessBlt。 此方法将一组视频示例传递给视频处理设备。 作为响应,视频处理设备处理输入图片并生成一个输出帧。 处理可以包括反交错、颜色空间转换和子流混合。 输出将写入调用方提供的目标图面。

VideoProcessBlt 方法采用以下参数:

  • pRT 指向 IDirect3DSurface9 渲染目标表面,该表面将接收处理后的视频帧。
  • pBltParams 指向一个 DXVA2_VideoProcessBltParams 结构,该结构指定位块传送的参数。
  • pSamplesDXVA2_VideoSample 结构的数组的地址。 这些结构包含位块传送的输入示例。
  • NumSamples 提供 pSamples 数组的大小。
  • Reserved 参数是保留的,应设置为 NULL

pSamples 数组中,调用方必须提供以下输入示例:

  • 主视频流的当前图片。
  • 前向和后向参考图像(如果反交错算法需要)。
  • 零个或多个子流图片,最多 15 个子流。

驱动程序预期此数组按特定顺序排列,如输入示例顺序中所述。

位块传送参数

DXVA2_VideoProcessBltParams 结构包含位图传送的常规参数。 最重要的参数存储在结构的以下成员中:

  • TargetFrame 是输出帧的呈现时间。 对于渐进式内容,此时间必须等于主要视频流中当前帧的开始时间。 该时间在输入示例的 DXVA2_VideoSample 结构的 Start 成员中指定。

    对于交错内容,具有两个交错字段的帧生成两个无交错输出帧。 在第一个输出帧中,演示时间必须与主视频流中当前图片的开始时间相等,就像渐进式内容一样。 在第二个输出帧中,开始时间必须等于当前图片在主视频流的开始时间与流中下一张图片的开始时间之间的中点。 例如,如果输入视频是每秒 25 帧(每秒 50 个字段),则输出帧将具有下表中显示的时间戳。 时间戳以 100 纳秒为单位显示。

    输入图片 TargetFrame (1) TargetFrame (2)
    0 0 200000
    400000 0 600000
    800000 800000 1000000
    1200000 1200000 1400000

     

    如果交错内容包含单个字段而不是交错字段,则输出时间始终与输入时间匹配,就像渐进式内容一样。

  • TargetRect 定义目标图面中的矩形区域。 位块传送会将输出写入此区域。 具体而言,将修改 TargetRect 中的每个像素,并且不会修改 TargetRect 以外的任何像素。 目标矩形定义所有输入视频流的边框。 通过 IDirectXVideoProcessor::VideoProcessBltpSamples 参数控制该矩形内的单个流的位置。

  • BackgroundColor 提供任何显示视频图像的位置的背景颜色。 例如,当 16 x 9 视频图像显示在 4 x 3 区域(信箱)中时,装箱区域将显示背景色。 背景色仅适用于目标矩形 (TargetRect)。 TargetRect 之外的任何像素都不会修改。

  • DestFormat 描述了输出视频的颜色空间,例如,是使用 ITU-R BT.709 还是 BT.601 颜色。 此信息可能会影响图像的显示方式。 有关详细信息,请参阅扩展颜色信息

DXVA2_VideoProcessBltParams 结构的参考页上介绍了其他参数。

输入示例

IDirectXVideoProcessor::VideoProcessBltpSamples 参数指向 DXVA2_VideoSample 结构的数组。 其中每个结构都包含有关一个输入示例的信息,以及指向包含示例的 Direct3D 图面的指针。 每个样本都是以下之一:

  • 主视频流的当前图片。
  • 主码流中的前向或后向参考图像,用于去交错。
  • 子流图片。

稍后将在“输入示例顺序”部分介绍示例必须出现在数组中的确切顺序。

最多可以提供 15 个子流图片,尽管大多数视频应用程序最多只需要一个子流。 每个对 VideoProcessBlt 的调用都可以更改子流的数量。 子流图片通过设置 DXVA2_VideoSample 结构的 SampleFormat.SampleFormat 成员等于 DXVA2_SampleSubStream 来指示。 对于主视频流,此成员描述输入视频的交错。 有关详细信息,请参阅 DXVA2_SampleFormat 枚举。

对于主要视频流,DXVA2_VideoSample 结构的开始结束成员提供输入示例的开始和结束时间。 对于子流图片,请将这些值设置为零,因为呈现时间始终从主流计算。 应用程序负责跟踪何时应显示每个子流图片并在适当时间将其提交到 VideoProcessBlt

两个矩形定义源视频如何为每个流定位:

  • DXVA2_VideoSample 结构的 SrcRect 成员指定源矩形,源图片的矩形区域将显示在复合输出帧中。 若要裁剪图片,请将此值设置为小于帧大小的值。 否则,将其设置为等于帧大小。
  • 同一结构的 DstRect 成员指定目标矩形,即目标图面的矩形区域,其中将显示视频帧。

驱动程序将源矩形中的像素点以位块传送的方式输入目标矩形。 这两个矩形可以具有不同的大小或纵横比;驱动程序会根据需要缩放映像。 此外,每个输入流都可以使用不同的缩放因子。 事实上,为了在输出帧中生成正确的宽高比,可能有必要缩放。 驱动程序不考虑源的像素纵横比,因此,如果源图像使用非平方像素,则由应用程序来计算正确的目标矩形。

首选子流格式为 AYUV 和 AI44。 后者是具有 16 种颜色的托盘格式。 调色板条目在 DXVA2_VideoSample 结构的 Pal 成员中指定。 (如果源视频格式最初表示为媒体基础媒体类型,则调色板条目存储在 MF_MT_PALETTE 属性中。)对于非托盘化格式,将此数组清除为零。

图像构成

每个位块传送操作由以下三个矩形定义:

  • 目标矩形 (TargetRect) 定义目标图面中将显示输出的区域。 输出图像被剪裁到此矩形。
  • 每个流的目标矩形 (DstRect) 定义输入流出现在复合图像中的位置。
  • 每个流的矩形 (SrcRect) 定义源图像的哪个部分会出现。

目标矩形和目标矩形相对于目标图面指定。 源矩形相对于源图像指定。 所有矩形都以像素为单位指定。

diagram showing source, destination, and target rectangles

视频处理设备 alpha 使用以下任何 alpha 数据源混合输入图片:

  • 子流中的每像素 alpha 数据。
  • DXVA2_VideoSample 结构的 PlanarAlpha 成员中指定的每个视频流的平面 alpha 值。
  • 复合图像的平面 alpha 值,在 DXVA2_VideoProcessBltParams 结构的 Alpha 成员中指定。 此值用于将整个复合图像与背景色混合。

本部分提供了一系列示例,演示视频处理设备如何创建输出图像。

示例 1:装箱

此示例演示如何将目标矩形设置为小于目标矩形来装箱源图像。 本示例中的主要视频流是 720 × 480 图像,旨在以 16:9 纵横比显示。 目标图面为 640 × 480 像素(4:3 纵横比)。 若要实现正确的纵横比,目标矩形必须为 640 × 360。 为简单起见,此示例不包含子流。 下图显示了源矩形和目标矩形。

diagram showing letterboxing.

上图显示了以下矩形:

  • 目标矩形:{ 0, 0, 640, 480 }

  • 主要视频:

    • 源矩形: { 0, 0, 720, 480 }
    • 目标矩形: { 0, 60, 640, 420 }

驱动程序将对视频进行去交错处理,将无交帧缩小到 640 × 360,并将帧以位块传送方式传入目标矩形。 目标矩形大于目标位置的矩形,因此驱动程序将使用背景色填充框架上方和下方的水平条。 背景色在 DXVA2_VideoProcessBltParams 结构中指定。

示例 2:拉伸子流图像

子流图片可以扩展到主要视频图片之外。 例如,在 DVD 视频中,主视频流可以具有 4:3 纵横比,而子流为 16:9。 在此示例中,两个视频流具有相同的源尺寸 (720 × 480),但子流旨在以 16:9 纵横比显示。 为了实现此纵横比,子流图像会水平拉伸。 下图显示了源矩形和目标矩形。

diagram showing substream image stretching.

上图显示了以下矩形:

  • 目标矩形:{ 0, 0, 854, 480 }

  • 主要视频:

    • 源矩形:{ 0, 0, 720, 480 }
    • 目标矩形:{ 0, 107, 474, 480 }
  • 子流:

    • 源矩形:{ 0, 0, 720, 480 }
    • 目标矩形:{ 0, 0, 854, 480 }

这些值保留图像高度,并水平缩放两个图像。 在两个图像出现的区域中,它们是 alpha 混合的。 当子流图像超出主视频时,子流将与背景色进行 alpha 混合。 这种 alpha 混合法使图表右侧的颜色发生了变化。

示例 3:不匹配的流高度

在上一示例中,子流和主流的高度相同。 流也可以具有不匹配的高度,如此示例所示。 在本例中,目标矩形内未出现视频的区域使用背景色-黑色绘制。 下图显示了源矩形和目标矩形。

diagram showing mismatched stream heights,

上图显示了以下矩形:

  • 目标矩形:{ 0, 0, 150, 85 }
  • 主要视频:
    • 源矩形:{ 0, 0, 150, 50 }
    • 目标矩形:{ 0, 17, 150, 67 }
  • 子流:
    • 源矩形:{ 0, 0, 100, 85 }
    • 目标矩形:{ 25, 0, 125, 85 }

示例 4:目标矩形小于目标图面

此示例显示了目标矩形小于目标图面的情况。

diagram showing a blit to a destination rectangle.

上图显示了以下矩形:

  • 目标图面: { 0, 0, 300, 200 }
  • 目标矩形:{ 0, 0, 150, 85 }
  • 主要视频:
    • 源矩形:{ 0, 0, 150, 50 }
    • 目标矩形:{ 0, 17, 150, 67 }
  • 子流:
    • 源矩形:{ 0, 0, 100, 85 }
    • 目标矩形:{ 25, 0, 125, 85 }

目标矩形外的像素不会被修改,因此背景色只会出现在目标矩形内。 虚线区域表示不受位块传送影响的目标表面部分。

示例 5:源矩形

如果指定小于源图片的源矩形,驱动程序将只对该部分图像进行位块传送处理。 在此示例中,源矩形指定主视频流的右下象限和子流的左下象限(由关系图中的哈希标记指示)。 目标矩形的大小与源矩形相同,因此不会拉伸视频。 下图显示了源矩形和目标矩形。

diagram showing a blit from two source rectangles.

上图显示了以下矩形:

  • 目标矩形:{ 0, 0, 720, 576 }
  • 主要视频:
    • 源图面大小:{ 0, 0, 720, 480 }
    • 源矩形:{ 360, 240, 720, 480 }
    • 目标矩形:{ 0, 0, 360, 240 }
  • 子流:
    • 源图面大小:{ 0, 0, 640, 576 }
    • 源矩形:{ 0, 288, 320, 576 }
    • 目标矩形:{ 400, 0, 720, 288 }

示例 6:与目标矩形相交

此示例类似于上一个示例,但目标矩形相交。 图面尺寸与上一示例中相同,但源矩形和目标矩形不同。 同样,视频被裁剪,但未拉伸。 下图显示了源矩形和目标矩形。

diagram showing intersecting destination rectangles.

上图显示了以下矩形:

  • 目标矩形:{ 0, 0, 720, 576 }
  • 主要视频:
    • 源图面大小:{ 0, 0, 720, 480 }
    • 源矩形:{ 260, 92, 720, 480 }
    • 目标矩形:{ 0, 0, 460, 388 }
  • 子流:
    • 源图面大小:{ 0, 0, 640, 576 }
    • 源矩形:{ 0, 0, 460, 388 }
    • 目标矩形:{ 260, 188, 720, 576 }

示例 7:拉伸和裁剪视频

在此示例中,视频被拉伸和裁剪。 每个流中的 180 × 120 区域被拉伸,以覆盖目标矩形中的 360 × 240 区域。

diagram showing stretching and cropping.

上图显示了以下矩形:

  • 目标矩形:{ 0, 0, 720, 480 }
  • 主要视频:
    • 源图面大小:{ 0, 0, 360, 240 }
    • 源矩形:{ 180, 120, 360, 240 }
    • 目标矩形:{ 0, 0, 360, 240 }
  • 子流:
    • 源图面大小:{ 0, 0, 360, 240 }
    • 源矩形:{ 0, 0, 180, 120 }
    • 目标矩形:{ 360, 240, 720, 480 }

输入示例顺序

VideoProcessBlt 方法的 pSamples 参数是指向输入样本数组的指针。 主要视频流中的示例首先出现,后跟 Z 顺序的子流图片。 示例必须按以下顺序放入数组中:

  • 主要视频流的示例首先以时态顺序显示在数组中。 根据反交错模式的不同,驱动程序可能需要从主要视频流中获取一个或多个参考采样。 DXVA2_VideoProcessorCaps 结构的 NumForwardRefSamplesNumBackwardRefSamples 成员指定需要多少个向前和向后引用样本。 调用方必须提供这些参考示例,即使视频内容是渐进式的,并且不需要反交错。 (当向反交错设备提供渐进式帧时,例如,当源包含交错帧和渐进帧的混合时,可能会出现这种情况。)
  • 在主视频流的样本之后,数组最多可以包含 15 个子流样本,按 Z 顺序排列,从下到上。 子流始终是渐进式的,不需要参考图片。

随时,主视频流可以在交错和渐进式内容之间切换,子流的数量可能会更改。

DXVA2_VideoSample 结构的 SampleFormat.SampleFormat 成员指示图片的类型。 对于子流图片,请将此值设置为 DXVA2_SampleSubStream。 对于渐进式图片,该值为 DXVA2_SampleProgressiveFrame。 对于交错图片,该值取决于字段布局。

如果驱动程序需要前向和向后引用示例,则视频序列开始时可能无法使用完整数量的样本。 在这种情况下,请在 pSamples 数组中包含它们的条目,但会将缺失的样本标记为具有类型 DXVA2_SampleUnknown。

DXVA2_VideoSample 结构的开始结束成员为每个样本提供临时位置。 这些值仅用于主要视频流中的示例。 对于子流图片,请将这两个成员设置为零。

以下示例可能有助于阐明这些要求。

示例 1

如果没有子流,并且取消交错算法不需要引用样本(NumForwardRefSamplesNumBackwardRefSamples 均为零),则会出现最简单的情况。 Bob 取消交错是此类算法的一个示例。 在这种情况下,pSamples 数组应包含单个输入图面,如下表所示。

索引 图面类型 时态位置
pSamples[0] 交错图片。 T

 

假定时间值 T 是当前视频帧的开始时间。

示例 2

在此示例中,应用程序将两个子流与主流混合。 反交错算法不需要引用示例。 下表显示了如何在 pSamples 数组中排列这些示例。

Index 图面类型 时态位置 Z 顺序
pSamples[0] 交错图片 T 0
pSamples[1] 子流 0 1
pSamples[2] 子流 0 2

 

示例 3

现在假设反交错算法需要一个向后引用样本和一个向前引用样本。 此外,还提供了两张子流图片,总共有五个图面。 下表显示了正确的排序。

Index 图面类型 时态位置 Z 顺序
pSamples[0] 交错图片(参考) T −1 不适用
pSamples[1] 交错图片 T 0
pSamples[2] 交错图片(参考) T +1 不适用
pSamples[3] 子流 0 1
pSamples[4] 子流 0 2

 

时间 T -1 是当前帧前一帧的开始时间,T+1 是下一帧的开始时间。

如果视频流切换到渐进式内容(使用相同的反交错模式),则应用程序必须提供相同数量的示例,如下表所示。

Index 图面类型 时态位置 Z 顺序
pSamples[0] 渐进式图片(参考) T −1 不适用
pSamples[1] 渐进式图片 T 0
pSamples[2] 渐进式图片(参考) T +1 不适用
pSamples[3] 子流 0 1
pSamples[4] 子流 0 2

 

示例 4

在视频序列开始时,前向引用示例可能不可用。 发生这种情况时,缺少样本的条目包含在 pSamples 数组中,示例类型为 DXVA2_SampleUnknown。

假设反交错模式需要一个向前引用和一个向后引用示例,则对 VideoProcessBlt 的前三个调用将具有以下三个表中所示的输入序列。

Index 图面类型 时态位置
pSamples[0] 未知 0
pSamples[1] 未知 0
pSamples[2] 交错图片(参考) T +1

 

Index 图面类型 时态位置
pSamples[0] 未知 0
pSamples[1] 交错图片 T
pSamples[2] 交错图片(参考) T +1

 

索引 图面类型 时态位置
pSamples[0] 交错图片 T −1
pSamples[1] 交错图片 T
pSamples[2] 交错图片(参考) T +1

 

DirectX 视频加速 2.0

DXVA2_VideoProc 示例