c++ - Directshow - 无法使用 SetMode 设置静止引脚
问题描述
我正在尝试使用 directshow(相机制造商建议使用的框架)从相机的静止引脚获取图像。
我一直在关注https://docs.microsoft.com/en-gb/windows/desktop/DirectShow/capturing-an-image-from-a-still-image-pin上的 DirectShow MS 文档,虽然我可以找到使用 ICaptureGraphBuilder2::FindPin 方法的静止引脚并已使用 graphedit 应用程序确认该引脚存在于相机上,我在使用 IAMVideoControl::SetMode 方法更改引脚时遇到了障碍。
我正在使用的代码如下:
HRESULT hr = CoInitializeEx(NULL, COINIT::COINIT_MULTITHREADED);
if (FAILED(hr))
Console::WriteLine("Initialise Failed");
else
Console::WriteLine("Initialise Success");
//Initalise graph builder
ICaptureGraphBuilder2 *pBuild;
IGraphBuilder *pGraph;
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&pBuild);
if (FAILED(hr))
Console::WriteLine("Graph builder failed");
else
Console::WriteLine("Graph builder success");
//Create filter graph
hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void**)&pGraph);
if (SUCCEEDED(hr))
{
pBuild->SetFiltergraph(pGraph);
Console::WriteLine("Set filter graph success");
}
else
{
pBuild->Release();
Console::WriteLine("Set filter graph failed");
}
// Create the System Device Enumerator.
ICreateDevEnum *pDevEnum;
IEnumMoniker *pDevicesInfo;
HRESULT hr2 = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
if (SUCCEEDED(hr2))
{
Console::WriteLine("Device enum builder success");
// Create an enumerator for the video category.
hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pDevicesInfo, 0);
if (hr == S_FALSE)
Console::WriteLine("Retrieve video input devices failed");
else
Console::WriteLine("Retrieve video input devices success");
pDevEnum->Release();
}
//loop over video devices and find see3cam_130
IMoniker *pMoniker = NULL;
while (pDevicesInfo->Next(1, &pMoniker, NULL) == S_OK)
{
IPropertyBag *pPropBag;
HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
if (FAILED(hr))
{
pMoniker->Release();
continue;
}
VARIANT var;
VariantInit(&var);
// Get description or friendly name.
hr = pPropBag->Read(L"FriendlyName", &var, 0);
if (SUCCEEDED(hr))
{
Console::WriteLine("Found video device");
//If correct device, break loop
if (0 == wcscmp(var.bstrVal, L"See3CAM_130"))
{
Console::WriteLine("See3CAM_130");
break;
}
else
{
Console::WriteLine("Comparison failed");
}
printf("%S\n", var.bstrVal);
VariantClear(&var);
}
else
{
Console::WriteLine("Vid Device failed");
}
}
//Create filter for device
IBaseFilter *pCap = NULL;
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
if (SUCCEEDED(hr))
{
Console::WriteLine("Filter created");
hr = pGraph->AddFilter(pCap, L"Capture Filter");
if (SUCCEEDED(hr))
{
Console::WriteLine("Capture filter added to filter graph");
}
else
{
Console::WriteLine("Capture filter NOT added to filter graph");
}
}
else
Console::WriteLine("Filter failed");
//Render capture pin first before attempting to set still pin (setting still pin fails with ot without this step)
hr = pBuild->RenderStream(
&PIN_CATEGORY_CAPTURE, // Pin category.
&MEDIATYPE_Video, // Media type.
pCap, // Capture filter.
NULL, // Intermediate filter (optional).
NULL); // Mux or file sink filter.
if (SUCCEEDED(hr))
Console::WriteLine("Stream Render success");
else
Console::WriteLine("Stream Render failed");
//Create a control to run graph
IMediaControl *pControl;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
if (FAILED(hr))
Console::WriteLine("Graph initalised - Failed");
else
Console::WriteLine("Graph initalised - Success");
// Run the graph.
while (1)
{
hr = pControl->Run();
if (FAILED(hr))
Console::WriteLine("Graph run - Failed");
else
{
Console::WriteLine("Graph run - Success");
break;
}
}
//Find the still pin
IAMVideoControl *pAMVidControl = NULL;
hr = pCap->QueryInterface(IID_IAMVideoControl, (void**)&pAMVidControl);
if (SUCCEEDED(hr))
{
Console::WriteLine("Video Control Initialised - Success");
IPin *pPin = NULL;
hr = pBuild->FindPin(
pCap, // Filter.
PINDIR_OUTPUT, // Look for an output pin.
&PIN_CATEGORY_STILL, // Pin category.
NULL, // Media type (don't care).
FALSE, // Pin must be unconnected.
0, // Get the 0'th pin.
&pPin // Receives a pointer to thepin.
);
if (SUCCEEDED(hr))
{
Console::WriteLine("Find pin - Success");
hr = pAMVidControl->SetMode(pPin, VideoControlFlag_Trigger);
if (FAILED(hr))
Console::WriteLine("Pin Mode Set - Failed");
else
Console::WriteLine("Pin Mode Set - Success");
pPin->Release();
}
else
Console::WriteLine("Find pin - Failed");
}
else
Console::WriteLine("Video Control Initialised - Failed");
一切都成功了,直到我尝试使用 SetMode 方法并且我不知道为什么......
我仍然是一名初级开发人员,并且在 c++ 方面缺乏经验,所以我怀疑我在某个地方错过了一步。我考虑过使用 directshow.net 包装器,但我不想浪费我花在这一步上的时间。
关于为什么 IAMVideoControl::SetMode 方法在我的代码中失败的任何提示?
注意:HResult 错误为 ERROR_GEN_FAILURE(可能用于表示设备已停止响应(挂起)或设备发生一般故障。设备可能需要手动重置。)
解决方案
我看到您查询,您必须做很多工作才能捕获静止帧。
枚举静止引脚后,您应该连接采样采集器并将空渲染到相机静止引脚。
构建并运行图形后,您应该触发静止模式,并且帧将在抓取器中接收。
然后你可以随心所欲地使用框架。
推荐阅读
- java - firebase 数据库的平均评分
- apache - 即使使用超级配置,Prestashop 在 Amazon AWS + RDS 中也不稳定
- python - Docker 让 Selenium 运行
- javascript - 利用 dom to image 将图像复制到剪贴板
- reactjs - 如何在 ReactJS 中独立删除动态添加的输入字段
- gis - 你如何让海龟只跟随我从加载到 netlogo 的 shapefile 创建的绿色补丁?
- javascript - 从字符串中获取回文长度
- c# - TempData 在 Web 场中失败
- google-sheets - 如何使嵌入的 Google 文档正确显示自定义字体
- python - 用 Python 读/写循环文本文件