You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
Sample implementations of different Microsoft Media Foundation components
Notifications You must be signed in to change notification settings
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Go to fileAn architectural overview of the Media Foundation Architecture:
Two different programming models:
See github projects:
https://github.com/joekickass/media-foundation-samples
As usual when it comes to creating components that should fit into a complex framework (e.g. MF) there are some plumbing involved. With plumbing I mean all the bulk code that has to be written to hande the packaging of the component as well as to fulfill interfaces that allows the component to be loaded by the framework. In the case of MF , below is a short list:
In most situations, it is recommended to use C++/CX to interact with the Windows Runtime. But in the case of hybrid components that implement both COM and Windows Runtime interfaces, such as Media Foundation objects, this is not possible. C++/CX can only create Windows Runtime objects. So, for hybrid objects it is recommended that you use WRL to interact with the Windows Runtime. Be aware that Windows Runtime C++ Template Library has limited support for implementing COM interfaces.
An MF extension is usually implemented as a DLL. The following few steps are a common procedure:
EXPORTS DllGetActivationFactory PRIVATE DllCanUnloadNow PRIVATE DllGetClassObject PRIVATE
Note: The *.def file needs to be referenced in project settings under:
Setting | Value |
---|---|
Linker -> Input -> Definition File | mydefinitionfile.def |
#include "pch.h" // pch.h should include using namespace Microsoft::WRL; BOOL APIENTRY DllMain(HMODULE hInstance, DWORD ul_reason_for_call, LPVOID) < switch (ul_reason_for_call) < case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hInstance); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; > return TRUE; > HRESULT WINAPI DllGetActivationFactory(HSTRING activatibleClassId, IActivationFactory** factory) < return Module::GetModule().GetActivationFactory(activatibleClassId, factory); > HRESULT WINAPI DllCanUnloadNow() < return Module::GetModule().Terminate() ? S_OK : S_FALSE; > STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID FAR* ppv) < return Module::GetModule().GetClassObject(rclsid, riid, ppv); >
More info on DLLs and linking can be found on http://www.tenouk.com/ModuleBB.html
The Microsoft Interface Description Language is used to describe the interface exposed through the windows runtime. The following MSDN project template summarizes the steps needed to do this:
In addition to this, the MIDLRT compiler needs to be set up to generate a .winmd file for the DLL. Without it the library won't be exposed throught the Windows Runtime and thus cannot be used as a reference in managed code. More info:
An example *.idl file for a custom MFT:
import "Windows.Media.idl"; #include sdkddkver.h> namespace Transform < [version(NTDDI_WIN8)] runtimeclass Effect < [default] interface Windows.Media.IMediaExtension; > >
Right clicking on the idl file and selecting Properties is a shortcut to the project properties for MIDL. To genereate a .winmd file, add the following settings.
Setting | Value |
---|---|
MIDL -> General -> Enable Windows Runtime | Yes (/winrt) |
MIDL -> Output -> Metadata File | $(OutDir)%(RootNamespace).winmd |
MIDL -> Output -> Header File | %(RootNamespace)_h.h |
Note that the generated .winmd file needs to be modified in order to work properly. See StackOverflow for more info:
This means adding the following build step under project settings:
Setting | Value |
---|---|
Custom Build Step -> General -> Command Line | mdmerge -v -i "$(OutDir)." -o "$(OutDir)Output" -partial -metadata_dir "$(WindowsSDK_MetadataPath)" && copy /y "$(OutDir)Output*" "$(OutDir)" |
Custom Build Step -> General -> Output | $(OutDir)%(RootNamespace).winmd |
Custom Build Step -> General -> Execute After | Midl |
Finally, the generated header file (_%(RootNamespace)h.h) needs to be referenced in the class definition file (*.cpp) as shown in the generic example below. Notice the InspectableClass using a string definition from the header, and the ActivatableClass section.
#include "pch.h" #include "RootNamespace_h.h" #include wrl.h> using namespace Microsoft::WRL; using namespace Windows::Foundation; namespace ABI < namespace RootNamespace < class WinRTClass: public RuntimeClass < InspectableClass(RuntimeClass_RootNamespace_ClassName, BaseTrust) public: WinRTClass()<> >; ActivatableClass(WinRTClass); > >
A few libraries need to be referenced when creating an Effect MFT:
Add them to Linker -> Input -> Additional Dependencies.
In managed code (e.g. the C# application where the MFT library is referenced), the class needs to be activated using the following section added to the Package.appxmanifest file:
Extensions> Extension Category="windows.activatableClass.inProcessServer"> InProcessServer> Path>EffectTransform.dllPath> ActivatableClass ActivatableClassId="EffectTransform.Effect" ThreadingModel="both" /> InProcessServer> Extension> Extensions>
MF is a free-threaded system, which means that COM interface methods can be invoked from arbitrary threads. Therefore, when calling CoInitializeEx(), you must initialize COM with the apartment-threaded object concurrency by passing in the COINIT_APARTMENTTHREADED parameter. Your objects might also need to use synchronization primitives, such as locks, to control access to internal variables by concurrently running threads.