Broadly, I want to accomplish the following:
The image generation is already written and must leverage an existing framework. I am currently working on the interface between the framework and DirectShow. My current implementation for passing the images is described below.
A COM interface is described in an .idl
file, and the generated .c
/.h
files are included in the source filter and, by extension, the framework module.
Additional methods allow for specifying a media format to support and tuning parameters based on the rate of image generation.
The passImage
method passes a pointer to a generated image buffer and the size of the buffer. This is called by a framework sink module when it receives new data to pass.
MyInterface.idl
[
object,
uuid("46B4BD3C-CD67-4158-BB83-89EA95306A4D"),
] interface IExtLiveSrc : IUnknown
{
...
HRESULT passImage
(
[in] unsigned long size,
[in, size_is(size)] BYTE **img
);
};
The source filter is implemented as two classes and an associated CLSID that are exported as a DLL and registered using regsvr32
. The DLLRegisterServer
method is implemented appropriately to register the COM object under CLSID_VideoInputDeviceCategory
.
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);
}
Note: the pin (CSourceStream
-derived class) implements the interface used to pass images. Assume that buffer size negotiation has already been established.
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;
}
Ignoring locking and synchronization for the moment (I know that FillBuffer()
should block until data is available), I've made the following observations.
FillBuffer()
leads to Lync correctly displaying them.passImage()
behaves correctly and the buffer instance variable receives the correct data. However, FillBuffer()
never seems to be called when debugging.Based on research I've done, it appears my issue is that the two different processes (my framework program and Lync) don't share the same data in the source filter DLL due to creating two separate instances of the filter graph.
What is the cleanest way for Lync's instance of the filter graph to share data with the images my program is despositing? I've seen "inter-process communication" tossed around. Though I'm not familiar with the concept, what would be a clear list of steps I would need to take towards my goal (pipes, sockets, shared memory, registry, etc.)?
A similar discussion on the MSDN forums.
There's discussion of a similar problem to what I have but not enough concrete details, and I don't want to post on an old thread.
A similar question on stack overflow.
This is actually quite similar to what I already have. However, I need to run a new application that presumably creates its own filter graph.
You have to pass data between processes: Lync will always use the filter in its process, without asking where it takes data from. And since it is supposed to take data from external process, it has to deal with interprocess communication and "somehow connect" to remote process where the data comes from.
There are options how you can implement this "somehow" exactly. I would prefer using memory mapped files and events/mutexes for synchronization. Producer process generates data and stores them in MMF, then consumer filter inside Lync processes reads this and delivers as generated video.