控制捕获图

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

Filter Graph 管理器的 IMediaControl 接口具有运行、停止和暂停整个图形的方法。 但是,如果筛选器图具有捕获和预览流,则可能需要单独控制这两个流。 例如,你可能想要预览视频而不捕获它。 可以通过 ICaptureGraphBuilder2::ControlStream 方法执行此操作。

注意

捕获到高级系统格式 (ASF) 文件时,此方法不起作用。

 

控制捕获流

以下代码将视频捕获流设置为运行 4 秒,在图形运行后开始运行 1 秒:

// Control the video capture stream. 
REFERENCE_TIME rtStart = 10000000, rtStop = 50000000;
const WORD wStartCookie = 1, wStopCookie = 2;  // Arbitrary values.
hr = pBuild->ControlStream(
    &PIN_CATEGORY_CAPTURE, // Pin category.
    &MEDIATYPE_Video,      // Media type.
    pCap,                 // Capture filter.
    &rtStart, &rtStop,     // Start and stop times.
    wStartCookie, wStopCookie  // Values for the start and stop events.
);
pControl->Run();

第一个参数指定要控制的流,作为引脚类别 GUID。 第二个参数提供媒体类型。 第三个参数是指向捕获筛选器的指针。 若要控制图形中的所有捕获流,请将第二个和第三个参数设置为 NULL

接下来的两个参数定义流开始和停止的时间,相对于图形开始运行的时间。 调用 IMediaControl::Run 以运行图形。 在运行图形之前, ControlStream 方法不起作用。 如果图形已在运行,则设置将立即生效。

最后两个参数用于在流启动和停止时获取事件通知。 对于使用此方法控制的每个流,筛选器图将发送一对事件: 流启动时EC_STREAM_CONTROL_STARTED ,流停止时 EC_STREAM_CONTROL_STOPPEDwStartCookiewStopCookie 的值用作第二个事件参数。 因此,start 事件中的 lParam2 等于 wStartCookie,stop 事件中的 lParam2 等于 wStopCookie。 以下代码演示如何获取这些事件:

while (hr = pEvent->GetEvent(&evCode, &param1, &param2, 0), SUCCEEDED(hr))
{
    switch (evCode)
    {
    case EC_STREAM_CONTROL_STARTED: 
    // param2 == wStartCookie
    break;

    case EC_STREAM_CONTROL_STOPPED: 
    // param2 == wStopCookie
    break;
    
    } 
    pEvent->FreeEventParams(evCode, param1, param2);
}

ControlStream 方法为开始和停止时间定义了一些特殊值。

开始 停止
MAXLONGLONG 永远不要启动此流。 在图形停止之前不要停止。
NULL 在图形运行时立即启动。 立即停止。

 

例如,以下代码会立即停止捕获流:

pBuild->ControlStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pCap,
    0, 0,     // Start and stop times.
    wStartCookie, wStopCookie); 

尽管可以停止捕获流并在以后重新启动它,但这会在时间戳中造成一个间隔。 播放时,根据文件格式) ,视频会在间隔 (期间显示为停止。

控制预览流

若要控制预览引脚,请调用 ControlStream ,但将第一个参数设置为 PIN_CATEGORY_PREVIEW。 这与PIN_CATEGORY_CAPTURE一样,只不过不能使用引用时间指定开始和停止,因为预览帧没有时间戳。 因此,必须使用 NULL 或 MAXLONGLONG。 使用 NULL 启动预览流:

pBuild->ControlStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap,
    NULL,    // Start now.
    0,       // (Don't care.)
    wStartCookie, wStopCookie); 

使用 MAXLONGLONG 停止预览流:

pBuild->ControlStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pCap,
    0,               // (Don't care.)
    MAXLONGLONG,     // Stop now.
    wStartCookie, wStopCookie); 

预览流是来自捕获筛选器上的预览引脚还是来自 Smart Tee 筛选器并不重要。 ControlStream 方法可任一方式工作。

但是,对于视频端口固定,方法将失败。 在这种情况下,另一种方法是隐藏视频窗口。 查询 IVideoWindow 的图形,并使用 IVideoWindow::p ut_Visible 方法来显示或隐藏窗口。

// Hide the video window.
IVideoWindow *pVidWin = 0;
hr = pGraph->QueryInterface(IID_IVideoWindow, (void**)&pVidWin);
if (SUCCEEDED(hr))
{
    pVidWin->put_Visible(OAFALSE);
    pVidWin->Release();
}

此外,如果在运行图形之前使用值 OAFALSE 调用 IVideoWindow::p ut_AutoShow ,则视频呈现器筛选器会隐藏窗口,直到你指定其他方法。 默认情况下,运行图形时,视频呈现器会显示窗口。

有关流控制的备注

图钉的默认行为是在图形运行时提供样本。 例如,假设使用 PIN_CATEGORY_CAPTURE 调用 ControlStream ,但不使用 PIN_CATEGORY_PREVIEW。 运行图形时,预览流将立即运行,而捕获流将在 ControlStream 中指定的任何时间运行。

如果要捕获多个流并将其发送到复用筛选器(例如,如果要将音频和视频捕获到 AVI 文件),则应同时控制这两个流。 否则,复用筛选器可能会阻止等待一个流,因为它尝试交错两个流。 在运行图形之前,对所有捕获流设置相同的开始和停止时间:

pBuild->ControlStream(&PIN_CATEGORY_CAPTURE, 
    
NULL, NULL,       // All capture streams.
    &rtStart, rtStop, 
    wStartCookie, wStopCookie); 

在内部, ControlStream 方法使用 IAMStreamControl 接口,该接口在捕获筛选器的引脚上公开,Smart Tee 筛选器 ((如果存在) ),还可能使用复用筛选器。 可以直接使用此接口,而不是调用 ControlStream,尽管这样做没有特别的优势。

视频捕获