控制捕获图
[与此页面关联的功能 DirectShow 是旧版功能。 它已被 MediaPlayer、 IMFMediaEngine 和 Media Foundation 中的音频/视频捕获所取代。 这些功能已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能在 Media Foundation 中使用 MediaPlayer、 IMFMediaEngine 和 音频/视频捕获 ,而不是 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_STOPPED 。 wStartCookie 和 wStopCookie 的值用作第二个事件参数。 因此,start 事件中的 lParam2 等于 wStartCookie,stop 事件中的 lParam2 等于 wStopCookie。 以下代码演示如何获取这些事件:
while (hr = pEvent->GetEvent(&evCode, ¶m1, ¶m2, 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,尽管这样做没有特别的优势。
相关主题