C++ 虚拟网络摄像头驱动程序

C++ 虚拟网络摄像头驱动程序,c++,webcam,directshow,device-driver,wdk,C++,Webcam,Directshow,Device Driver,Wdk,我想开发一个虚拟网络摄像头驱动程序,从用户模式,我会传递图像到它,它将显示为网络摄像头输出 我不想使用DirectX过滤器和CSourceStream等,因为它们不适用于某些不使用DirectX捕获网络摄像头图像的程序 我必须写一个内核模式的设备驱动程序 有什么想法吗?我尝试了DDK样本中的testcap,但它不处理用户模式下的图像,也不获取任何输入,只在网络摄像头中显示7种颜色 任何帮助都将不胜感激。 谢谢 谢谢大家! 我在这里尝试了以下代码: (查找捕获源筛选器) 当我在雅虎、MSN上编译

我想开发一个虚拟网络摄像头驱动程序,从用户模式,我会传递图像到它,它将显示为网络摄像头输出

我不想使用DirectX过滤器和CSourceStream等,因为它们不适用于某些不使用DirectX捕获网络摄像头图像的程序

我必须写一个内核模式的设备驱动程序

有什么想法吗?我尝试了DDK样本中的testcap,但它不处理用户模式下的图像,也不获取任何输入,只在网络摄像头中显示7种颜色

任何帮助都将不胜感激。 谢谢


谢谢大家!

我在这里尝试了以下代码: (查找捕获源筛选器)

当我在雅虎、MSN上编译它时,它运行得很好,但它崩溃了AIM、Internet Explorer Flash摄像头、Firefox Flash摄像头和Skype。。。经过8次呼叫后,我在QueryInterface中找到了crash,我用了很多技巧跟踪它

现在我知道了,它在第8次呼叫时崩溃了 HRESULT CVCamStream::QueryInterface(refid-riid,void**ppv)

第八次呼叫,当它到达最后一次,我的意思是: 返回CSourceStream::QueryInterface(riid,ppv)

在第17行的Filters.cpp中

为什么你认为我会崩溃


感谢大家指导我找到正确的解决方案,即DirectShow,而不是驱动程序

您无法决定其他程序如何调用您的驱动程序。大多数程序将使用DirectShow。有些人会使用win3.x技术VFW。许多新的程序,包括Windows XP的扫描仪和照相机向导,可能会通过WIA界面调用您。如果您不想实现所有这些,您需要通过WDM并让vfwwdm32.dll为您提供一个VFW接口,或者编写您自己的VFW驱动程序。

Microsoft有几个API提供对图像数据的访问

  • Twain:用于从扫描仪等捕获单个图像
  • WIA:这似乎已经退化为一个单一的图像编解码器库
  • VfW:一个非常古老的(Win16)API,它实际上只适用于视频文件编码/解码,但支持一些视频采集
  • DirectShow:以前是DirectX SDK的一部分,现在是平台SDK的一部分。这是当前(通用)流媒体解决方案的最佳选择
  • Windows Media/Media Foundation:这似乎更适合于视频播放/重新编码
  • 特定于制造商的库:Pylon/Halcon/Imaging Control/
DirectShow特定于:

要在windows下创建图像采集设备,您必须提供实现streamclasses接口(或更新的Avstream)的设备(驱动程序),或者必须编写必须添加到VideoInputCategory枚举器的usermode COM对象

Avstream样本为真正的图像采集设备提供了一切。真正缺少的只是实际设备的较低层

如果你能设计一个设备,你应该创建一个兼容DCAM或UVC的设备。两者都有windows提供的内置驱动程序


如何编写软件源设备:

您必须创建一个DirectShow筛选器,该筛选器至少提供一个输出引脚,并将其注册到VideoInputCategory下。某些应用程序可能需要从捕获应用程序获得多个接口,但这些接口取决于应用程序本身。用于尝试过滤器的简单应用程序是PlattformSDK中提供的GraphEdit和AMCap

一些代码:

#include <InitGuid.h>
#include <streams.h>


const AMOVIESETUP_MEDIATYPE s_VideoPinType =
{
    &MEDIATYPE_Video,   // Major type
    &MEDIATYPE_NULL     // Minor type
};

const AMOVIESETUP_PIN s_VideoOutputPin =
{
    L"Output",              // Pin string name
    FALSE,                  // Is it rendered
    TRUE,                   // Is it an output
    FALSE,                  // Can we have none
    FALSE,                  // Can we have many
    &CLSID_NULL,            // Connects to filter
    NULL,                   // Connects to pin
    1,                      // Number of types
    &s_VideoPinType         // Pin details
};

const AMOVIESETUP_FILTER s_Filter =
{
    &CLSID_MyFilter,        // Filter CLSID
    L"bla",         // String name
    MERIT_DO_NOT_USE,               // Filter merit
    1,                              // Number pins
    &s_VideoOutputPin               // Pin details
};

    REGFILTER2 rf2;
    rf2.dwVersion = 1;
    rf2.dwMerit = MERIT_DO_NOT_USE;
    rf2.cPins = 1;
    rf2.rgPins = s_Filter.lpPin;

    HRESULT hr = pFilterMapper->RegisterFilter( CLSID_MyFilter, _FriendlyName.c_str(), 0, 
        &CLSID_VideoInputDeviceCategory, _InstanceID.c_str(), &rf2 );
    if( FAILED( hr ) )
    {
        return false;
    }

    std::wstring inputCat = GUIDToWString( CLSID_VideoInputDeviceCategory );
    std::wstring regPath = L"CLSID\\" + inputCat + L"\\Instance";
    win32_utils::CRegKey hKeyInstancesDir;
    LONG rval = openKey( HKEY_CLASSES_ROOT, regPath, KEY_WRITE, hKeyInstancesDir );
    if( rval == ERROR_SUCCESS )
    {
        win32_utils::CRegKey hKeyInstance;
        rval = createKey( hKeyInstancesDir, _InstanceID, KEY_WRITE, hKeyInstance );

        ....
#包括
#包括
const AMOVIESETUP_MEDIATYPE s_VideoPinType=
{
&MEDIATYPE_视频,//主要类型
&MEDIATYPE\u NULL//次要类型
};
常数AMOVIESETUP_引脚s_视频输出引脚=
{
L“Output”//Pin字符串名称
FALSE,//是否已渲染
TRUE,//这是一个输出吗
错,//我们能一个也没有吗
错,//我们能有很多吗
&CLSID_NULL,//连接到筛选器
NULL,//连接到pin
1,//类型数
&s\u VideoPinType//Pin详细信息
};
常数AMOVIESETUP_过滤器s_过滤器=
{
&CLSID\u MyFilter,//过滤器CLSID
L“bla”,//字符串名称
优点\u不使用,//筛选优点
1,//管脚编号
&s\u VideoOutputPin//Pin详细信息
};
regfilter2rf2;
rf2.dwVersion=1;
rf2.dwMerit=优点不使用;
rf2.cPins=1;
rf2.rgPins=s_Filter.lpPin;
HRESULT hr=pFilterMapper->RegisterFilter(CLSID\u MyFilter,\u FriendlyName.c\u str(),0,
&CLSID_VideoInputDeviceCategory,_InstanceID.c_str(),&rf2);
如果(失败(小时))
{
返回false;
}
std::wstring inputCat=GUIDToWString(CLSID\u VideoInputDeviceCategory);
std::wstring regPath=L“CLSID\\\”+inputCat+L“\\Instance”;
win32_utils::CRegKey hKeyInstancesDir;
LONG rval=openKey(HKEY_类_根、regPath、KEY_写、hKeyInstancesDir);
如果(rval==错误\成功)
{
win32_utils::CRegKey hKeyInstance;
rval=createKey(hKeyInstancesDir,_InstanceID,KEY_WRITE,hKeyInstance);
....

_InstanceID是为这个“虚拟设备”条目创建的GUID。

你是指WDK而不是DDK,对吗?另外,为了更好地了解你在寻找什么,我在示例中找不到testcap。再一次,不要尝试编写驱动程序,因为驱动程序往往非常大。我将尝试查看我的代码以注册软件ware设备,并在此处显示。如果您真的必须使用windows驱动程序,请参阅,以获取有关如何与设备驱动程序通信的说明。祝您好运。如果您只是想避免一些崩溃,我在此处对这些内容进行了一点改进:(当然不是内核模式的摄像头,但可能有用)干杯!有关从C#内部执行此操作的相关文章,请回答