是否将程序输出传递给DirectShow源筛选器以由Lync拾取

Pass program output to a DirectShow source filter to be picked up by Lync?

本文关键字:筛选 拾取 Lync DirectShow 程序 输出 是否      更新时间:2023-10-16

目标

总的来说,我想完成以下任务:

  1. 从程序实时生成一系列图像
  2. 将图像传递给DirectShow源筛选器,该筛选器已注册为捕获源
  3. 在类似Lync的程序中选择生成的"虚拟网络摄像头">

图像生成已经编写完成,必须利用现有的框架。我目前正在研究框架和DirectShow之间的接口。下面描述我当前用于传递图像的实现。

接口

COM接口在.idl文件中描述,生成的.c/.h文件包含在源过滤器中,并扩展到框架模块中。

附加的方法允许指定媒体格式以支持并基于图像生成速率调整参数。

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派生类(实现了用于传递图像的接口。假设缓冲区大小协商已经建立。

passImage((

STDMETHODIMP CVSourceStream::passImage(unsigned long size, BYTE **img) {
    memcpy_s(this->bufferedImg, size, *img, size);
    return S_OK;
}    

FillBuffer((

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的筛选器图实例与我的程序正在解压缩的图像共享数据的最干净的方式是什么?我看到过"进程间通信"被抛来抛去。虽然我不熟悉这个概念,但为了实现目标,我需要采取哪些步骤(管道、套接字、共享内存、注册表等(?

链接

MSDN论坛上也有类似的讨论

有人讨论了一个与我类似的问题,但没有足够的具体细节,我不想在旧的帖子上发帖。

关于堆栈溢出的类似问题。

事实上,这与我已经拥有的非常相似。然而,我需要运行一个新的应用程序,该应用程序可能会创建自己的过滤器图。

您必须在进程之间传递数据:Lync将始终在其进程中使用筛选器,而不询问从何处获取数据。由于它应该从外部进程获取数据,因此它必须处理进程间通信,并"以某种方式连接"到数据来源的远程进程。

你可以选择如何"以某种方式"准确地实现这一点。我更喜欢使用内存映射文件和事件/互斥进行同步。生产者进程生成数据并将其存储在MMF中,然后Lync进程内的消费者过滤器读取这些数据并作为生成的视频交付。