目标
总的来说,我想完成以下任务:
- 通过程序实时生成一系列图像
- 将图像传递给注册为捕获源的 DirectShow 源过滤器
- 在 Lync 等程序中选择生成的“虚拟网络摄像头”
图像生成已经编写完成,必须利用现有框架。我目前正在研究框架和 DirectShow 之间的接口(interface)。我当前传递图像的实现如下所述。
接口(interface)
COM接口(interface)在.idl
文件中描述,生成的.c
/.h
文件包含在source filter中并且,通过扩展,框架模块。
其他方法允许指定媒体格式以支持并根据图像生成速率调整参数。
passImage
方法传递指向生成的图像缓冲区的指针和缓冲区的大小。当接收到要传递的新数据时,框架接收器模块会调用它。
MyInterface.idl
[
object,
uuid("46B4BD3C-CD67-4158-BB83-89EA95306A4D"),
] interface IExtLiveSrc : IUnknown
{
...
HRESULT passImage
(
[in] unsigned long size,
[in, size_is(size)] BYTE **img
);
};
DirectShow 源过滤器
源过滤器作为两个类和一个关联的 CLSID 实现,它们作为 DLL 导出并使用 regsvr32
注册。 DLLRegisterServer
方法被适本地实现以在 CLSID_VideoInputDeviceCategory
下注册 COM 对象。
MyFilter.h
class CVSource : public CSource {
static CUnknown *WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT *phr);
STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
// private constructor
}
class CVSourceStream : public CSourceStream
, public virtual IKsPropertySet
, public virtual IAMStreamConfig
, public virtual IExtLiveSrc
{
// constructor, IUnknown, IKsPropertySet, IAMStreamConfig methods
...
HRESULT FillBuffer(IMediaSample *pms);
STDMETHODIMP passImage(unsigned long size, BYTE **img);
}
注意:pin(CSourceStream
-派生类)实现了用于传递图像的接口(interface)。假设缓冲区大小协商已经建立。
passImage()
STDMETHODIMP CVSourceStream::passImage(unsigned long size, BYTE **img) {
memcpy_s(this->bufferedImg, size, *img, size);
return S_OK;
}
填充缓冲区()
HRESULT CVSourceStream::FillBuffer(IMediaSample *pms) {
// Set timestamp on IMediaSample instance
...
BYTE *pData;
pms->GetPointer(&pData);
long lDataLen = pms->GetSize();
memcpy_s(pData, lDataLen, this->bufferedImg, lDataLen);
return S_OK;
}
问题
暂时忽略锁定和同步(我知道 FillBuffer()
应该阻塞直到数据可用),我做了以下观察。
- 将生成的缓冲区测试序列直接添加到
FillBuffer()
会导致 Lync 正确显示它们。 - 当运行我的程序时,
passImage()
行为正确并且缓冲区实例变量接收到正确的数据。然而,FillBuffer()
在调试时似乎从未被调用。
根据我所做的研究,我的问题似乎是两个不同的进程(我的框架程序和 Lync)由于创建而没有在源过滤器 DLL 中共享相同的数据过滤器图的两个独立实例。
Lync 的过滤器图实例与我的程序正在存储的图像共享数据的最简洁方法是什么?我已经看到了“进程间通信”。尽管我不熟悉这个概念,但为了实现我的目标(管道、套接字、共享内存、注册表等)我需要采取哪些明确的步骤列表?
链接
A similar discussion on the MSDN forums.
有人讨论了与我所拥有的类似的问题,但没有足够具体的细节,我不想在旧线程上发帖。
A similar question on stack overflow.
这实际上与我已有的非常相似。但是,我需要运行一个可能会创建自己的过滤器图的新应用程序。
最佳答案
您必须在进程之间传递数据:Lync 将始终在其进程中使用筛选器,而不询问从何处获取数据。并且由于它应该从外部进程获取数据,因此它必须处理进程间通信并“以某种方式连接”到数据来自的远程进程。
有一些选项可以让你“以某种方式”准确地实现这个。我更喜欢使用内存映射文件和事件/互斥锁进行同步。生产者进程生成数据并将它们存储在 MMF 中,然后 Lync 进程中的消费者过滤器读取这些数据并作为生成的视频提供。
关于c++ - 将程序输出传递给 DirectShow 源过滤器以供 Lync 获取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31306215/