How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 5: In-Place Processing)

Previously on the topic:

Due to the nature of the brightness and constract correction processing, it would make sense to combine and simplify processing to apply correction “in-place”, that is without copying data from input to output buffer, but instead processing the same buffer before it is passed further downstream.

DMO API offers additional optional IMediaObjectInPlace interface to be implemented on the DMO which the hosting object might prefer to regular IMediaObject.

The interface itself is simple with basically the only Process method to actually handle the processing:

// IMediaObjectInPlace
	STDMETHOD(Process)(ULONG nSize, BYTE* pnData, REFERENCE_TIME nStartTime, DWORD nFlags)
	STDMETHOD(Clone)(IMediaObjectInPlace** ppMediaObject)
	STDMETHOD(GetLatency)(REFERENCE_TIME* pnLatencyTime)

Still the interest in in-place processing in DMO is more abstract because current DMO Wrapper Filter implementation does not take advantage of in-place processing and chooses to always work through IMediaObject.

However if the object is hosted directly, in-place processing might make sense and be important.

To support in-place processing in the DMO it is required to inherit from interface and add it to the COM map:

class ATL_NO_VTABLE CBrightnessContrastObject :
	public CComObjectRootEx<CComMultiThreadModel>,
	...
	public IMediaObjectInPlace
...
BEGIN_COM_MAP(CBrightnessContrastObject)
	...
	COM_INTERFACE_ENTRY(IMediaObjectInPlace)
END_COM_MAP()

And implement the IMediaObjectInPlace methods, of which IMediaObjectInPlace::Process is the essential.

Source code: DmoBrightnessContrastSample.05.zip (note that Release build binary is included)

4 Replies to “How To: Implement DirectShow Filter using DirectX Media Object DMO (Part 5: In-Place Processing)”

  1. Guest: I wanted to try your code for implementing DirectShow filters using DMOs but found an unresolved reference to AtlSetPerUserRegistration. I cannot seem to find out anything about this ATL function.

    It appeared in Visual Studio 2008, just comment it out.

    Guest: I am still using VS 2005, but I figured that at least there should be some docs on it at MS. Found nothing. I will try commenting it out.

    Yes, it is an undocumented [yet] feature but generated by default project wizard.

    I am pretty sure Microsoft will document it soon and it will be quite useful: it will allow registration of COM classes from under non-admin account. However it might be still not useful enough for DMOs because they will need additional entries under HKEY_CLASSES_ROOT for which there will still be insufficient permissions.

    See also: ATL and Visual Studio C++.NET 2008 Goodies

  2. Guest: I’m trying to create a DMO filter to DirectShow using your great article as reference. I would like to know if it’s possible to debug the filter. I set some breakpoints on code and set GraphEditor as executable, but when debug in visual studio the breakpoints are disabled and says: “The breakpoint will not currently be hit. No symbols have been loaded for this document.” Maybe you could give me some hint about this :). Thank you!

    You’re doing it the right way. Start GraphEdit and make it load your DLL. The possible problems on this way are:

    • You are using wrong debugger engine, you need to use “Native” debugger. It may be set to “Auto” and it’s loading a different one, e.g. managed
    • It shows a warning because it does not have symbols for GraphEdt.exe, but as soon as the process loads your DLL it will be able to stop at breakpoints
    • You’re building your DLL without debug information, esp. in Release configuration, and the debugger just does not have information about where to pub the breakpoint in the right place
    • You’re confusing somewhere 32 and 64-bit versions of binaries, e.g. you build 64-bit and start 32-bit GraphEdit
  3. (…continued)

    Guest: Thanks for your help. I have tested every point you tell me and all of them are fine. Debugger engine is set to “Auto”, I’m building a 32-bit version DLL and I try to test the debug version. Maybe the problem could be the folder where the DLL is exported? The DLL file is generated in debug folder inside the project folder, I try to generated DLL in GraphEditor folder but doesn’t works. When you say “Start GraphEdit and
    make it load your DLL” you mean I must load explicit the DLL from GraphEditor? I don’t do anything, when compile the solution, the DLL is registed automatically and when GraphEditor starts, DLL appear in “Insert Filter” window.

    There is nothing wrong in your description, it is how it is going to work. You build your own DLL but you start GraphEdit, a different application, right? At this point why would your source contain a single line you can break at? No, it does not.

    It’s only when you insert your filter in the GraphEdit instance, it would load your DLL and debugger will see this and enable all breakpoints. This is where it starts working from. If it does not, make sure it opens right DLL. For example, you should be unable to rename or delete the DLL file at this time as it should be in use by GraphEdit.

    See also in TMH’s FAQ: Can I debug my filter in GraphEdit or another application?

    Guest: You were right, there is nothing wrong in the application. I didn’t insert the filter in the GraphEdt, I supposed that at least GetFriendlyName() could be called when “insert filter” dialog was open.

    When you register filter, some information is written into system registry. Then applications like GraphEdit read this information without instantiating a filter.

  4. Blog reader question:

    But I have problem DMO register for 64bit system.

    I want to make DMO filter whose input is YUY2 and output is RGB24 or RGB48.

    […]

    When I build the project, there is error.

    1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.CppCommon.targets(1749,5): warning MSB3075: The command “regsvr32 /s “Debug\DmoBrightnessContrastSample.dll”” exited with code 5. Please verify that you have sufficient rights to run this command.

    1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.CppCommon.targets(1761,5): error MSB8011: Failed to register output. Please try enabling Per-user Redirection or register the component from a command prompt with elevated permissions.

    So I ran command prompt as Administrator and run regsvr32 DmoBrightnessContrastSample.dll. Still GraphEdit does not showing this DMO. And I also run c:\windows\syswow64\regsvr32 DmoBrightnessContrastSample.dll, because I heard that this is for 32-bit. And some registry keys are registered only for 64-bit. So I copied to 32bit…

    [HKEY_CLASSES_ROOT\Wow6432Node\DirectShow\MediaObjects\334be85b-9de4-4405-8eee-9cbb2650f83d]

    [HKEY_CLASSES_ROOT\Wow6432Node\DirectShow\MediaObjects\Categories\d990ee14-776c-4723-be46-3da2f56f10b9\334be85b-9de4-4405-8eee-9cbb2650f83d]

    è

    [HKEY_CLASSES_ROOT\DirectShow\MediaObjects\334be85b-9de4-4405-8eee-9cbb2650f83d]

    [HKEY_CLASSES_ROOT\DirectShow\MediaObjects\Categories\d990ee14-776c-4723-be46-3da2f56f10b9\334be85b-9de4-4405-8eee-9cbb2650f83d]

    Now I can see “Alax.Info BrightnessContrast Sample” under DMO Video Effects in GraphEdit, but when I try to insert this filter, there is error message again.

    – the filter could not be created. Resources used by this filter may already be in use.
    – Class not registered (0x80040154)

    So…. I wonder what should I do more.

    You should regsvr32 using administrator privileges – you already found it out.

    32 and 64 bit versions run independently. You should build both, regsvr32 both and then they will both be available to 32/64 bit GraphEdit and applications.

    32-bit apps will see 32-bit DMO registration and will use it regardless of 64-bit version registration/availability and vice versa.

Leave a Reply