将视频捕获到 AVI 文件

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

下图显示了将视频捕获到 AVI 文件的最简单图形。

avi 视频捕获图

AVI 复用器筛选器从捕获引脚获取视频流,并将其打包到 AVI 流中。 音频流也可以连接到 AVI 复用器筛选器,在这种情况下,复用器将交错两个流。 文件编写器筛选器将 AVI 流写入磁盘。

若要生成图形,请首先调用 ICaptureGraphBuilder2::SetOutputFileName 方法,如下所示:

IBaseFilter *pMux;
hr = pBuild->SetOutputFileName(
    &MEDIASUBTYPE_Avi,  // Specifies AVI for the target file.
    L"C:\\Example.avi", // File name.
    &pMux,              // Receives a pointer to the mux.
    NULL);              // (Optional) Receives a pointer to the file sink.

第一个参数指定文件类型 - 在本例中为 AVI。 第二个参数提供文件名。 对于 AVI,SetOutputFileName 方法共同创建 AVI Mux 筛选器和文件编写器筛选器,并将其添加到图形中。 它还通过调用 IFileSinkFilter::SetFileName 方法在文件编写器筛选器上设置文件名,并连接这两个筛选器。 方法返回指向第三个参数中的 AVI 复用函数的指针。 (可选)它会返回指向第四个参数中的 IFileSinkFilter 接口的指针。 如果不需要此接口,可以将此参数设置为 NULL,如上一示例所示。

接下来,调用 ICaptureGraphBuilder2::RenderStream 方法,将捕获筛选器连接到 AVI 复用器,如下所示:

hr = pBuild->RenderStream(
    &PIN_CATEGORY_CAPTURE, // Pin category.
    &MEDIATYPE_Video,      // Media type.
    pCap,                  // Capture filter.
    NULL,                  // Intermediate filter (optional).
    pMux);                 // Mux or file sink filter.

// Release the mux filter.
pMux->Release();

第一个参数提供引脚类别,这是捕获PIN_CATEGORY_CAPTURE。 第二个参数提供媒体类型。 第三个参数是指向捕获筛选器的 IBaseFilter 接口的指针。 第四个参数是可选的:它允许在将视频流传递到复用筛选器之前,通过中间筛选器(如编码器)路由视频流。 否则,请将此参数设置为 NULL,如上一示例所示。 第五个参数是指向复用筛选器的指针。 此指针是通过调用 SetOutputFileName 方法获取的。

若要捕获音频,请使用媒体类型MEDIATYPE_Audio调用 RenderStream。 如果要从两个不同的设备捕获音频和视频,最好将音频流设置为主流。 这有助于防止两个流之间的偏移,因为 AVI 复用器筛选器调整视频流的播放速率以匹配音频流。 若要设置主流,请在 AVI Mux 筛选器上调用 IConfigAviMux::SetMasterStream 方法:

IConfigAviMux *pConfigMux = NULL;
hr = pMux->QueryInterface(IID_IConfigAviMux, (void**)&pConfigMux);
if (SUCCEEDED(hr))
{
    pConfigMux->SetMasterStream(1);
    pConfigMux->Release();
}

SetMasterStream 的参数是流号,由调用 RenderStream 的顺序决定。 例如,如果首先为视频调用 RenderStream,然后为音频调用 RenderStream,则视频为流 0,音频为流 1。

还可以通过调用 IConfigInterleaving::p ut_Mode 方法来设置 AVI Mux 筛选器如何交错音频和视频流。

IConfigInterleaving *pInterleave = NULL;
hr = pMux->QueryInterface(IID_IConfigInterleaving, (void**)&pInterleave);
if (SUCCEEDED(hr))
{
    pInterleave->put_Mode(INTERLEAVE_CAPTURE);
    pInterleave->Release();
}

使用 INTERLEAVE_CAPTURE 标志时,AVI 复用器以适合视频捕获的速率执行交错。 还可以使用 INTERLEAVE_NONE,这意味着没有交错 - AVI 复用器只需按照数据到达的顺序写入数据。 INTERLEAVE_FULL标志表示 AVI Mux 执行完全交错;但是,此模式不太适合视频捕获,因为它需要最多的被听到。

对视频流进行编码

可以通过在捕获筛选器和 AVI 复用器筛选器之间插入编码器筛选器来对视频流进行编码。 使用 系统设备枚举器筛选器映射器 选择编码器筛选器。 (有关详细信息,请参阅 枚举设备和筛选器。)

将编码器筛选器指定为 RenderStream 的第四个参数,在以下示例中以粗体显示:

IBaseFilter *pEncoder;
/* Create the encoder filter (not shown). */
// Add it to the filter graph.
pGraph->AddFilter(pEncoder, L"Encoder");

/* Call SetOutputFileName as shown previously. */

// Render the stream.
hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, 
    pCap, 
pEncoder, pMux);
pEncoder->Release();

编码器筛选器可能支持 IAMVideoCompression 或其他用于设置编码参数的接口。 有关可能接口的列表,请参阅 文件编码和解码接口

将视频捕获到文件