C++ DirectShow Amcap工作于finde,带playcap的黑屏
我想将预览视频从图像传感器传输到电脑。 稍后我想添加自定义过滤器 首先,我使用Amcap获取预览视频。它很好用。 然而,我希望我的项目是基于playcap(没有amcap那么复杂)。 当我启动playcap时,它会检测到一个设备,但只显示一个黑屏 两个示例中的代码我都没有修改。 有人知道如何解决这个问题吗? 或者,是否有人可以描述我如何向amcap添加自定义过滤器。 Samplecgb部件在amcap中做什么 国王问候,C++ DirectShow Amcap工作于finde,带playcap的黑屏,c++,directshow,C++,Directshow,我想将预览视频从图像传感器传输到电脑。 稍后我想添加自定义过滤器 首先,我使用Amcap获取预览视频。它很好用。 然而,我希望我的项目是基于playcap(没有amcap那么复杂)。 当我启动playcap时,它会检测到一个设备,但只显示一个黑屏 两个示例中的代码我都没有修改。 有人知道如何解决这个问题吗? 或者,是否有人可以描述我如何向amcap添加自定义过滤器。 Samplecgb部件在amcap中做什么 国王问候, afo我将尝试提取以下创建捕获图的步骤。这是一个复杂的过程,通常有多种方法
afo我将尝试提取以下创建捕获图的步骤。这是一个复杂的过程,通常有多种方法来完成大部分步骤,所以从现在开始,你必须做自己的研究,并提出具体的问题 在下面的代码片段中,我将使用
\u COM\u SMARTPTR\u TYPEDEF(IGraphBuilder,\uu uuidof(IGraphBuilder))
宏定义这些代码片段。因此,请定义IGraphBuilderPtr
,您可以这样做:
_COM_SMARTPTR_TYPEDEF(IGraphBuilder, __uuidof(IGraphBuilder))
// which defines IGraphBuilderPtr
您始终需要有一个图表,以便第一步非常通用:
IGraphBuilderPtr graph;
graph.CreateInstance(CLSID_FilterGraph);
然后,如果您正在构建捕获图,则很可能需要使用以下界面:
ICaptureGraphBuilder2Ptr cg;
cg.CreateInstance(CLSID_CaptureGraphBuilder2);
cg->SetFiltergraph(graph);
之后,您需要将一个或多个输入源添加到图形中。您需要找到将图像传感器包装为视频捕获设备的过滤器,并将其添加到图表中。
这将是一个多步骤的过程,可能涉及到如下操作:
_COM_SMARTPTR_TYPEDEF(IGraphBuilder, __uuidof(IGraphBuilder))
// which defines IGraphBuilderPtr
枚举所有视频捕获设备:
IBaseFilterPtr fVideoInput; // will hold the video input source
ICreateDevEnumPtr pCreate(CLSID_SystemDeviceEnum);
IEnumMonikerPtr pEnum;
HRESULT hr = pCreate->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
&pEnum,
0);
if (hr == S_OK)
{
IMonikerPtr pMon;
while (pEnum->Next(1, &pMon, NULL) == S_OK)
{
// inspect the moniker of each devices to determine if it's the one you're after
// if it's the right device, then..
HRESULT hr = mon->BindToObject(NULL,
NULL,
__uuidof(IBaseFilter),
(void**)&fVideoInput);
}
}
一旦你有了视频输入过滤器的接口,你就必须枚举它的管脚并找到正确的输出管脚来连接图的其余部分。这可以简单到枚举所有管脚并选择第一个输出管脚(如果只有一个),或者枚举所有管脚并查询每个输出管脚的媒体类型并以这种方式选择正确的管脚,或者,如果您知道管脚的名称(并且始终相同),则调用FindPin。下面是枚举管脚并选择第一个输出管脚的示例:
IEnumPinsPtr pEnum;
fVideoInput->EnumPins(&pEnum);
IPinPtr pin;
while (pEnum->Next(1, &pin, NULL) == S_OK)
{
PIN_DIRECTION dir;
pin->QueryDirection(&dir);
if (dir == PINDIR_OUTPUT)
{
// this is the first output pin
break;
}
}
获得输出管脚后,可以插入另一个过滤器,找到合适的管脚(与上面类似,但查找输入管脚),然后使用以下方法直接连接两个管脚:
// assuming pinOut is an output pin
// and pinIn is an input pin, this method will try to connect them
HRESULT hr = graph->Connect(pinOut, pinIn);
或者,您可以尝试简单地渲染pin:
hr = graph->Render(pinOut);
下面是在图中插入自定义过滤器的示例。如果过滤器已经在系统中注册(它显示在GraphiEdit的列表中),那么您只需要知道过滤器的类id。这是唯一标识筛选器的GUID,如果您还不知道它,可以使用GraphiEdit找到它(创建新图形,插入自定义筛选器,右键单击并查看属性,应该有筛选器的类id):
然后,您可以按照上述类似的方式进行操作,为过滤器找到合适的输入引脚和合适的输出引脚,并根据需要连接它们
最后,这是完全可选的,并且仅对调试有用(因此不要在生产中使用),您可以使用ROT注册图形,以便可以在GraphEdit(或GraphStudionText或类似工具)等工具中研究最终图形
示例代码取自:
你试过在GraphiEdit中创建一个过滤图吗?是的,我试过这个。如果您成功使用GraphiEdit,那么您应该能够在应用程序中简单地重新创建相同的图形。由于playcap是一个非常简单的应用程序,因此它选择的管脚和graphbuilder在图形中插入的过滤器之间可能不兼容。请描述实现包含自定义源、自定义过滤器和渲染过滤器的图形的主要步骤。我必须先注册过滤器吗?自定义过滤器是指您希望自己开发的过滤器,还是其他人编写的已经存在的过滤器?如果您编写了自己的过滤器,但它不是项目的一部分,或者您使用了其他人尚未注册的过滤器,那么您必须注册它。但是,如果您使用的过滤器已经显示在GraphiEdit中,则不必注册它。
DWORD dwRegistration = 0;
HRESULT hr = AddToRot(graph, &dwRegistration);
// hold on to dwRegistration, and use it later when you tear down the graph
// to unregister it using the RemoveFromRot(&dwRegister) method