Shehryar / ms-media-foundation-samples

Sample implementations of different Microsoft Media Foundation components

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

media-foundation-samples

Sample implementations of different Microsoft Media Foundation components

References

Core MF concepts

An architectural overview of the Media Foundation Architecture:

Media Foundation Architecture

Two different programming models:

Examples

See github projects:

https://github.com/joekickass/media-foundation-samples

Plumbing

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:

  • WRL
  • DLLs, linking and exporting
  • MIDL and MIDLRT

Windows Runtime Template Language (WRL)

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.

DLLs, linking and exporting

An MF extension is usually implemented as a DLL. The following few steps are a common procedure:

  1. Create a Win (Phone) 8.x DLL project

  2. Add a definition file (*.def) that defines all exported functions of the shared library (the export list)

    *.def:

    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
  3. dllmain.cpp defines the entry point of the DLL; DllMain(). Let it also implement the exported functions using some WRL magic:

    dllmain.cpp:

    #include "pch.h" // pch.h should include <wrl/module.h>
    
    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<InProc>::GetModule().GetActivationFactory(activatibleClassId, factory);
    }
    
    HRESULT WINAPI DllCanUnloadNow()
    {
        return Module<InProc>::GetModule().Terminate() ? S_OK : S_FALSE;
    }
    
    STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID FAR* ppv)
    {
        return Module<InProc>::GetModule().GetClassObject(rclsid, riid, ppv);
    }

More info on DLLs and linking can be found on http://www.tenouk.com/ModuleBB.html

MIDL and MIDLRT

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:

http://msdn.microsoft.com/en-us/library/vstudio/hh973463.aspx

  1. An .idl file that declares the MIDL attributes for a basic interface and its class implementation
  2. A .cpp file that defines the class implementation.
  3. A file that defines the library exports DllMain(), DllCanUnloadNow(), DllGetActivationFactory(), and DllGetClassObject().

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:

[http://msdn.microsoft.com/en-us/library/windows/desktop/hh869900(v=vs.85).aspx](http://msdn.microsoft.com/en-us/library/windows/desktop/hh869900(v=vs.85\).aspx)

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:

http://stackoverflow.com/questions/14653250/how-to-declare-interface-that-inherits-from-iclosable-idisposable

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<IWinRTClass>
        {
            InspectableClass(RuntimeClass_RootNamespace_ClassName, BaseTrust)

        public:
            WinRTClass(){}
        };

        ActivatableClass(WinRTClass);
    }
}

MFTs

A few libraries need to be referenced when creating an Effect MFT:

  • mf.lib
  • mfuuid.lib
  • mfplat.lib

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.dll</Path>
      <ActivatableClass ActivatableClassId="EffectTransform.Effect" ThreadingModel="both" />
    </InProcessServer>
  </Extension>
</Extensions>

Threading

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.

See also [http://msdn.microsoft.com/en-us/library/windows/desktop/ee892371(v=vs.85).aspx](http://msdn.microsoft.com/en-us/library/windows/desktop/ee892371(v=vs.85\).aspx)

About

Sample implementations of different Microsoft Media Foundation components

License:Apache License 2.0