DirectShow Amcap工作finde,黑色屏幕与播放帽



我想将预览视频从图像传感器流式传输到我的电脑。稍后我想添加自定义过滤器。

首先,我使用Amcap来获得预览视频。它运行良好。然而,我希望我的项目是基于playcap(而不是像amcap那样复杂)。当我启动playcap时,它会检测到一个设备,但只显示一个黑屏。

我没有修改这两个例子中的代码。有人知道如何解决这个问题吗?也许有人能描述我如何向amcap添加自定义过滤器。Samplecgb部分在amcap中做什么?

谨致问候,afo

我将尝试提取创建下面的捕获图的步骤。这是一个复杂的过程,通常有多种方法可以完成大部分步骤,因此从现在起,你必须自己进行研究,并提出具体问题。

在下面的代码片段中,我将使用_com_ptr_t智能指针,它们是使用_COM_SMARTPTR_TYPEDEF(IGraphBuilder, __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);

之后,您需要将一个或多个输入源添加到图形中。您需要找到将图像传感器封装为视频捕获设备的过滤器,并将其添加到图形中。这将是一个多步骤的过程,可能会涉及到这样的事情:

枚举所有视频捕获设备:

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的pin的名称(并且它总是相同的)。以下是枚举引脚并选择第一个输出引脚的示例:

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);

这里有一个在图中插入自定义过滤器的例子。如果过滤器已经在系统中注册(它显示在GraphEdit的列表中),那么您只需要知道过滤器的类id。这是一个唯一标识过滤器的GUID,如果您还不知道,可以使用GraphEdit找到它(创建新图形,插入自定义过滤器,右键单击并查看属性,应该有过滤器的类id):

IBaseFilterPtr fCustomFilter;
fCustomFilter.CreateInstance(__uuidof(CLSID_OF_YOUR_CUSTOM_FILTER));
graph->AddFilter(fCustomFilter, L"Custom Filter Name");

然后,您可以使用与上述类似的管理器,为滤波器找到合适的输入引脚和合适的输出引脚,并根据您的需要进行连接。

最后,这是完全可选的,只对调试有用(所以不要在生产中使用),您可以向ROT注册图形,以便可以在GraphEdit(或GraphStudioNext等)等工具中研究最终图形。

AddToROT和RemoveFromRot:的MSDN示例代码

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

最新更新