There are basically three cases for Macrovision support. The easiest case is when your analog capture hardware does MPEG compression. The Macrovision support is, then, implemented by setting the copy protection bits directly in the MPEG headers. This self-contained solution is the one Microsoft strongly recommends, and they imply in some places that they ONLY support analog solutions with onboard MPEG compression, but it's a painful fact of life that only a few of the analog TV capture boards do so.
The other two cases involve software MPEG codecs. One such case is when you have your own MPEG encoder, or at least have a close relationship with a decoder vendor. In that case, one possible solution is to implement some private communication scheme between the capture driver and the MPEG encoder, possibly involving special bits in the frame headers, that pass the detection status downstream. The MPEG encoder can then use that information to embed the copy protection state in the MPEG headers, as before.
The final case is the one we found ourselves in: a capture driver using relatively off-the-shelf MPEG encoders (like Main Concept). In this case, there is no private communcation scheme, and it hardly benefits the vendors to implement something specifically for one vendor. So, it's up to the driver.
The mechanism for implementing Macrovision in this third case is to broadcast a property setting to all filters in the current graph. The real target is Microsoft's "XDS Encoder". Now, if the XDS Encoder was smart, it would poll the capture driver to find out the Macrovision status. Unfortunately, it isn't smart. It just exposes the property and waits for someone, somewhere, to send it an update. Further, the IKsPropertySet interface is not one of the ones that IFilterGraph aggregates, so the only way to send the property is to enumerate the graph.
Unfortunately, that enumeration can only be done from user mode. Most AVStream capture graphs are kernel-mode only. That represents a problem. The trick here is to use a concept called a "ksproxy plugin". We have our capture driver expose a kernel streaming property set that no one has ever heard of. We use the registry's MediaInterfaces key to essentially say "the property GUID XXX needs help from the user-mode COM object YYY". When ksproxy goes to expose our kernel capture filter to DirectShow, it finds the unknown property set, notices that there is a user-mode plugin helper, and loads the helper.
Once ksproxy loads us, we can participate in the graph all we want. We are given a pointer to ksproxy, which implements IBaseFilter. From that, we can fetch its FILTERINFO, which contains a pointer to the filter graph manager. From there, it's easy; the enumeration and broadcast code is all in the ActiveX Video Control document above.
The implementation is not rocket science, but the key is having someone point you in the right direction. Hopefully, this will save you the multiple months we wasted trying to find a way to advertise our Macrovision detection.