生成重新压缩Graph

AVI 文件重新压缩的典型筛选器图如下所示:

avi recompression graph

AVI 拆分器筛选器文件源 (异步) 筛选器中提取数据,并将其分析为视频和音频流。 视频解压缩器解码压缩的视频,其中由视频压缩器重新压缩。 解压缩器的选择取决于源文件;智能连接会自动处理它。 应用程序必须通过向用户显示列表来选择压缩器。 (请参阅 选择压缩筛选器.)

压缩的视频随后转到 AVI 复用筛选器。 此示例中的音频流未压缩,因此它直接从 AVI 拆分器传输到 AVI 复用器。 AVI Mux 将两个流交错, 文件编写器筛选器 会将输出写入磁盘。 请注意,即使原始文件没有音频流,也需要 AVI 复用。

生成此筛选器图的最简单方法是使用 Capture Graph Builder,这是用于生成捕获图和其他自定义筛选器图的DirectShow组件。

通过调用 CoCreateInstance 创建捕获Graph生成器来"开始"菜单:

ICaptureGraphBuilder2 *pBuild = NULL;
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, 
                        NULL, CLSCTX_INPROC_SERVER,
    IID_ICaptureGraphBuilder2, (void **)&pBuild);

然后使用捕获Graph生成器生成筛选器图:

  1. 生成图形的呈现部分,其中包括 AVI 复用器筛选器和 文件编写器
  2. 将源筛选器和压缩筛选器添加到图形。
  3. 连接源筛选器到 MUX 筛选器。 捕获图形生成器插入分析源文件所需的任何拆分器和解码器筛选器。 它还可以通过压缩筛选器路由视频和音频流。

以下各节介绍了每个步骤。

生成呈现部分

若要生成图形的呈现部分,请调用 ICaptureGraphBuilder2::SetOutputFileName 方法。 此方法采用输入参数,这些参数指定输出的媒体子类型以及输出文件的名称。 它返回指向 MUX 筛选器和文件编写器的指针。 下一阶段图形生成需要 MUX 筛选器。 此示例不需要指向文件编写器的指针,以便参数可以为 NULL

IBaseFilter *pMux = NULL;
hr = pBuild->SetOutputFileName(
        &MEDIASUBTYPE_Avi, // File type. 
        wszOutputFile,     // File name, as a wide-character string.
        &pMux,             // Receives a pointer to the multiplexer.
        NULL);             // Receives a pointer to the file writer. 

方法返回时,MUX 筛选器具有未完成的引用计数,因此请务必稍后释放指针。

下图显示了此时的筛选器图。

rendering section of the filter graph

MUX 筛选器公开两个接口,用于控制 AVI 格式:

添加源和压缩筛选器

下一步是将源筛选器和压缩筛选器添加到筛选器图。 调用 SetOutputFileName 时,Capture Graph Builder 会自动创建筛选器Graph管理器的实例。 通过调用 ICaptureGraphBuilder2::GetFiltergraph 方法获取指向它的指针:

IGraphBuilder *pGraph = NULL;
hr = pBuild->GetFiltergraph(&pGraph);

现在调用 IGraphBuilder::AddSourceFilter 方法添加异步文件源筛选器,并使用 IFilterGraph::AddFilter 方法添加视频压缩器:

IBaseFilter *pSrc = NULL;
hr = pGraph->AddSourceFilter(wszInputFile, L"Source Filter", &pSrc);
hr = pGraph->AddFilter(pVComp, L"Compressor");

此时,源筛选器和压缩筛选器未连接到图中的其他任何内容,如下图所示:

filter graph with source and compression filters

将源连接 Mux

最后一步是通过视频压缩器将源筛选器连接到 AVI Mux 筛选器。 使用 ICaptureGraphBuilder2::RenderStream 方法,该方法通过压缩筛选器(可选)将源筛选器上的输出引脚连接到指定的接收器筛选器。

前两个参数通过指定引脚类别和媒体类型来指定要连接的源筛选器的引脚。 异步文件源筛选器只有一个输出引脚,因此这些参数应为 NULL。 接下来的三个参数指定源筛选器、压缩筛选器 ((如果有) )和 Mux 筛选器。

下面的代码示例通过视频压缩器呈现视频流:

hr = pBuild->RenderStream(
        NULL,       // Output pin category
        NULL,       // Media type
        pSrc,       // Source filter
        pVComp,     // Compression filter
        pMux);      // Sink filter (the AVI Mux)

下图显示了到目前为止的筛选器图。

rendered video stream

假设源文件具有音频流, 则 AVI 拆分器 筛选器已为音频创建输出引脚。 若要连接此引脚,请再次调用 RenderStream:

hr = pBuild->RenderStream(NULL, NULL, pSrc, NULL, pMux);

此处未指定压缩筛选器。 源筛选器的输出引脚已连接,因此 RenderStream 方法在拆分器筛选器上搜索未连接的输出引脚。 它查找音频引脚,并将其直接连接到 MUX 筛选器。 如果源文件没有音频流,则对 RenderStream 的第二次调用将失败。 这是预期行为。 图形在对 RenderStream 的第一次调用后完成,因此第二次调用中的失败是无害的。

在此示例中,两个 RenderStream 调用的顺序非常重要。 由于第二次调用未指定压缩器,因此它将从 AVI 拆分器连接任何未连接的引脚。 如果在另一个呼叫之前进行此调用,则它可能会将视频流连接到 AVI Mux,而无需视频压缩器。 因此,必须使用压缩筛选器) 进行更具体的调用 (。

前面的讨论假定源文件是 AVI 文件。 但是,此方法也适用于其他文件类型,例如 MPEG 文件。 生成的筛选器图将略有不同。

重新压缩 AVI 文件