我试图用directshow编写一个C++应用程序,该应用程序可以将视频捕获保存到文件中。代码中的步骤如下: 1.创建捕获图形生成器2.创建系统设备枚举器3.创建系统设备枚举器--以获得捕获过滤器4.为视频捕获类别5创建枚举器.创建用于捕获视频的查询
附加代码
// gets the device filter
HRESULT getDeviceFilter(REFCLSID clsid, int order, IBaseFilter **pCap)
{
ICreateDevEnum *pDevEnum = NULL;
IEnumMoniker *pEnum = NULL;
// Create the System Device Enumerator.
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
reinterpret_cast<void**>(&pDevEnum));
if (SUCCEEDED(hr))
{
// Create an enumerator for the video capture category.
hr = pDevEnum->CreateClassEnumerator( clsid, &pEnum, 0);
}
IMoniker *pMoniker = NULL;
if (pEnum->Next(1, &pMoniker, NULL) == S_OK)
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)pCap);
return hr;
}
int main()
{
IGraphBuilder *pGraph = 0;
ICaptureGraphBuilder2 *pBuild = 0;
IBaseFilter *pCap = 0;
HRESULT hr = CoInitialize(NULL);
// Create the Capture Graph Builder.
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICaptureGraphBuilder2,
(void**)&pBuild );
ICreateDevEnum *pDevEnum = NULL;
IEnumMoniker *pEnum = NULL;
// Create the System Device Enumerator.
hr = CoCreateInstance(CLSID_SystemDeviceEnum,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum,
reinterpret_cast<void**>(&pDevEnum));
IBaseFilter *pMux = 0;
hr = pBuild->SetOutputFileName(&MEDIASUBTYPE_Avi, // Specifies AVI for the target file.
L"C:\\Example.avi", // File name.
&pMux, // Receives a pointer to the mux.
NULL); // (Optional) Receives a pointer to the file sink.
// gets the first device, VDM tv card
hr = getDeviceFilter(CLSID_VideoInputDeviceCategory, 0, &pCap);
hr = pBuild->RenderStream(&PIN_CATEGORY_CAPTURE, // Pin category.
&MEDIATYPE_Video, // Media type.
pCap, // Capture filter.
NULL, // Intermediate filter (optional).
pMux); // Mux or file sink filter.
// Release the mux filter.
pMux->Release();
IConfigAviMux *pConfigMux = NULL;
hr = pMux->QueryInterface(IID_IConfigAviMux, (void**)&pConfigMux);
if (SUCCEEDED(hr))
{
pConfigMux->SetMasterStream(1);
pConfigMux->Release();
}
return 0;
}然而,在调用RenderStream时,我得到了一个E_INVALIDARG错误
有什么建议吗?
谢谢
发布于 2012-12-06 12:39:07
看看本题。你好像错过了一些步骤。
首先,您没有在任何地方使用pGraph。您应该创建一个图形管理器,然后使用SetFilterGraph为图形生成器提供指向图形管理器的指针,从而初始化它。
// Create the Filter Graph Manager.
hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void**)&pGraph);
if (SUCCEEDED(hr))
{
// Initialize the Capture Graph Builder.
pBuild->SetFiltergraph(pGraph);
// ...
}其次,您使用的过滤器不是由图形管理器管理的。引用这里
在调用方法之前,必须将pSource、pIntermediate和pSink指定的所有筛选器添加到图中。
您必须将过滤器pCap和pMux添加到前面使用AddFilter创建的图形管理器中。在调用RenderStream之前,您应该这样做。这是因为RenderStream最终会调用管理器上的连接方法。
如果以上步骤不能解决您的问题,您还可以尝试其他几种方法。
设备过滤器。您正在使用CLSID_VideoInputDeviceCategory的第一个设备,但您确定这是正确的设备吗?网络摄像机等也属于这一类别。确保没有连接相同类别的其他设备,然后再试一次。
连接。每个设备都是不同的。它可能是你的设备不能直接连接到穆克斯。在这种情况下,我们必须找出原因,并确定是否需要连接额外的过滤器(如解码器)。GraphEdit是查找这些过滤器的一种非常快速的方法。
针类/媒体类型。根据我的经验,E_INVALIDARG是由RenderStream的前2个参数引起的90%的时间。尝试将引脚类别或媒体类型设置为NULL。
系统设备枚举器:正如您自己描述的那样,您要创建两次系统设备枚举器。这在我看来很奇怪,为什么不同时使用一种呢?
如果您的代码仍然不能工作,您应该向我提供更多的信息。当你使用GraphEdit时,你实现了你的目标吗?你的VDM电视卡过滤器看起来怎么样(插脚,媒体类型)?
https://stackoverflow.com/questions/13743076
复制相似问题