//*@@@+++@@@@******************************************************************
//
// Microsoft Windows Media Foundation
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//*@@@---@@@@******************************************************************
//

import "mfobjects.idl";
import "mftransform.idl";

//
// Include this for MAX_PATH
//
cpp_quote("#include <windef.h>")

///////////////////////////////////////////////////////////////////////////////
//
// Media Foundation basic control-layer interfaces
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

/// <summary>
///     The enumeration type defines several ways by which SetTopology can be
///     called on a media session.
/// </summary>
/// <remarks>
///     The flags are neither exclusive nor mandatory. If none of the following
///     flags is set, it means the topology will be resolved at first and then
///     queued, and it will be used sequentially when the previous presentation
///     is done.
/// </remarks>
typedef enum MFSESSION_SETTOPOLOGY_FLAGS
{
    /// <summary>
    ///     Media session should end the current presentation and use
    ///     this topology immediately
    /// </summary>
    MFSESSION_SETTOPOLOGY_IMMEDIATE = 0x1,

    /// <summary>
    ///     Media session does not need to resolve the topology.
    /// </summary>
    MFSESSION_SETTOPOLOGY_NORESOLUTION = 0x2,

#if (WINVER >= _WIN32_WINNT_WIN7)
    /// <summary>
    ///     Media session should end the current presentation and remove
    ///     it from the session.
    /// </summary>
    MFSESSION_SETTOPOLOGY_CLEAR_CURRENT = 0x4
#endif

}   MFSESSION_SETTOPOLOGY_FLAGS;

/// <summary>
///     Flags for use with IMFMediaSession::GetFullTopology
/// </summary>
typedef enum MFSESSION_GETFULLTOPOLOGY_FLAGS
{
    /// <summary>
    ///     Media Session should return the topology it is currently
    ///     playing.
    /// </summary>
    MFSESSION_GETFULLTOPOLOGY_CURRENT = 0x1

}   MFSESSION_GETFULLTOPOLOGY_FLAGS;

/// <summary>
///     Flags for use with MFCreatePMPMediaSession
/// </summary>
typedef enum MFPMPSESSION_CREATION_FLAGS
{
    /// <summary>
    ///     If set, the Protected Media Path will exist in an unprotected
    ///     process.
    ///     This is for applications that wish to play clear content in a
    ///     separate (unprotected) process.
    ///     If not set, the Protected Media Path will exist in a protected
    ///     process, and both protected and clear content will play in
    ///     this process.
    /// </summary>
    MFPMPSESSION_UNPROTECTED_PROCESS = 0x1

}   MFPMPSESSION_CREATION_FLAGS;

/// <summary>
///     ID for topology node.
/// </summary>
typedef unsigned __int64 TOPOID;

interface IMFTopology;
interface IMFClock;
interface IMFPresentationTimeSource;

[
    object,
    uuid(90377834-21D0-4dee-8214-BA2E3E6C1127),
]
/// <summary>
///     IMFMediaSession is the control-level abstraction used by applications
///     working with the Media Foundation pipeline.
///     This is the main interface used by the application for both
///     unprotected and protected content.
///     For unprotected content, the application instantiates a Media Session
///     in its own process using MFCreateMediaSession.
///     For protected content, the application instantiates a PMP Media Session
///     in its own process using MFCreatePMPMediaSession.  The PMP Media Session
///     implements IMFMediaSession, which the application uses to control
///     the session.
/// </summary>
interface IMFMediaSession : IMFMediaEventGenerator
{
    /// <summary>
    ///     SetTopology is used to specify the topology to be used by
    ///     the Media Session.  The topology specifies the Media Source,
    ///     Media Transforms, and Media Sinks to be used.
    ///     This is an asynchronous call.
    /// </summary>
    /// <param name="dwSetTopologyFlags">
    ///     Bitflags that can be a combination of the following:
    ///     MFSESSION_SETTOPOLOGY_IMMEDIATE:
    ///         If set, the currently-playing topology will be ended
    ///         and this topology will be set immediately.
    ///         This is different from the default behavior, in which
    ///         the currently-playing topology is allowed to reach the
    ///         end of its presentation before this operation is carried out.
    ///     MFSESSION_SETTOPOLOGY_NORESOLUTION:
    ///         This flag should be set if pTopology is a fully-specified
    ///         topology.
    ///         This is different from the default behavior, in which
    ///         pTopology is assumed to be only partially specified,
    ///         in which case the Media Session will attempt to resolve
    ///         the topology using the Topology Loader.
    /// </param>
    /// <param name="pTopology">
    ///     Specifies a pointer to a topology.
    ///     Unless the MFSESSION_SETTOPOLOGY_NORESOLUTION bit is set in
    ///     dwFlags, this is assumed to be a partial topology.  A partial
    ///     topology is one in which not all nodes are specified; for
    ///     instance, an application may specify a topology that has only
    ///     source and output nodes specified, and the Media Session will
    ///     supply the other necessary nodes (decoders, etc) during the
    ///     topology loading step.
    /// </param>
    /// <remarks>
    ///     Upon completion of this asynchronous operation, the Media Session
    ///     will send the MESessionTopologySet event.
    ///</remarks>
    HRESULT SetTopology(
        [in] DWORD dwSetTopologyFlags,
        [in] IMFTopology* pTopology
        );

    /// <summary>
    ///     ClearTopologies will asynchronously clear all pending topologies
    ///     for this Media Session
    /// </summary>
    /// <remarks>
    ///     Upon completion of this asynchronous operation, the Media Session
    ///     will send the MEClearQueuedPresentations event.
    /// </remarks>
    HRESULT ClearTopologies( void );

    /// <summary>
    ///     Start starts the processing of media samples and starts the
    ///     Presentation Clock.
    /// </summary>
    /// <param name="pguidTimeFormat">
    ///     Specifies the time format that should be used to interpret
    ///     the pvarStartPosition parameter.
    ///     Can be NULL, in which case, pvarStartPosition will be in terms
    ///     of MFTIME.
    ///     Support for other time formats depends on the Media Source
    ///     being used.
    /// </param>
    /// <param name="pvarStartPosition">
    ///     Specifies where to start playback.
    ///     This value is interpreted according to the value of pguidTimeFormat.
    ///     If pguidTimeFormat is NULL or *pguidTimeFormat is GUID_NULL, then
    ///     pvarStartPosition should either be of type VT_I8, with its value
    ///     specifying a time offset in MFTIME units; or it can be VT_EMPTY
    ///     to specify that the Media Session should start at the current
    ///     position.
    /// </param>
    /// <remarks>
    ///     Upon completion of this asynchronous operation, the Media Session
    ///     will send the MESessionStarted event.
    /// </remarks>
    HRESULT Start(
        [in, unique] const GUID *pguidTimeFormat,
        [in, unique] const PROPVARIANT *pvarStartPosition
        );

    /// <summary>
    ///     Pause pauses the processing of media samples and pauses the
    ///     Presentation Clock.
    /// </summary>
    /// <remarks>
    ///     Upon completion of this asynchronous operation, the Media Session
    ///     will send the MESessionPaused event.
    /// </remarks>
    HRESULT Pause( void );

    /// <summary>
    ///     Stop stops the processing of media samples and stops the
    ///     Presentation Clock.
    /// </summary>
    /// <remarks>
    ///     Upon completion of this asynchronous operation, the Media Session
    ///     will send the MESessionStopped event.
    /// </remarks>
    HRESULT Stop( void );

    /// <summary>
    ///     The Close methods closes and releases all resources being
    ///     used by the Media Session.
    ///     The application should call this method after it is done
    ///     using the Media Session to ensure that all of the final
    ///     operations take place.
    /// </summary>
    /// <remarks>
    ///     Upon completion of this asynchronous operation, the Media Session
    ///     will send the MESessionClosed event.
    /// </remarks>
    HRESULT Close( void );

    /// <summary>
    ///     The Shutdown method causes all the resources used by the
    ///     Media Session to be properly shutdown and released.
    ///     The application must call this method after it is done using
    ///     the Media Session to avoid memory leaks.
    /// </summary>
    HRESULT Shutdown( void );

    /// <summary>
    ///     The GetClock method gives the application access to the
    ///     Presentation Clock used for this session.
    ///     This clock is useful for displaying presentation time in
    ///     the application
    /// </summary>
    /// <param name="ppClock">
    ///     Pointer to a variable that will receive a pointer to the
    ///     clock for this presentation.
    /// </param>
    /// <remarks>
    ///     *ppClock will be a Presentation Clock.
    ///     Although it will QueryInterface for IMFPresentationClock, the
    ///     application should not control the state of the presentation
    ///     clock directly; instead, the application should always use
    ///     the transport-control methods (Start, Stop, Pause) on
    ///     IMFMediaSession.
    /// </remarks>
    HRESULT GetClock(
        [out] IMFClock** ppClock
        );

    /// <summary>
    ///     The GetSessionCapabilities method returns a DWORD that can reflect the capabilities of the
    ///     current media session.
    /// </summary>
    /// <param name="pdwCaps">
    ///     Specifies a pointer to a variable where the DWORD will be stored.
    /// </param>
    /// <return>
    ///     If the method succeeds, it returns S_OK. If it fails, it returns an error code.
    /// </return>
    /// <remarks>
    ///     The capabilities DWORD is a bitwise combination of the
    ///     MFSESSIONCAP_xxx flags
    /// </remarks>
    HRESULT GetSessionCapabilities(
        [out] DWORD *pdwCaps
        );

    /// <summary>
    ///     The application can use this method to retrieve fully-specified
    ///     (i.e. loaded) topologies from the Media Session.
    /// </summary>
    /// <param name="dwGetFullTopologyFlags">
    ///     Bitflag combination of the MFSESSION_GETFULLTOPOLOGY_FLAGS:
    ///     MFSESSION_GETFULLTOPOLOGY_CURRENT:
    ///         If this bit is set, then the TopoId parameter will be ignored,
    ///         and the Media Session will return the full topology for the
    ///         presentation it is currently playing.
    /// </param>
    /// <param name="TopoId">
    ///     Identifier of the topology to retrieve.
    ///     Ignored if the MFSESSION_GETFULLTOPOLOGY_CURRENT bit is set
    ///     in dwGetFullTopologyFlags.
    /// </param>
    /// <param name="ppFullTopology">
    ///     Pointer to a variable in which the full topology is returned.
    /// </param>
    /// <remarks>
    ///     If the TopoId parameter is used, the Media Session will only be
    ///     able to provide full topologies for the currently-playing
    ///     presentation and for all topologies that have been queued on
    ///     the Media Session.  This method cannot be used for retrieving
    ///     topologies that have ended.
    /// </remarks>
    HRESULT GetFullTopology(
        [in] DWORD dwGetFullTopologyFlags,
        [in] TOPOID TopoId,
        [out] IMFTopology** ppFullTopology
        );
}


//
// MFCreateMediaSession attributes
//

// MF_SESSION_TOPOLOADER
// Data type: GUID
// If the MF_SESSION_TOPOLOADER is set, this value is used to CoCreate topoloader
cpp_quote( "EXTERN_GUID( MF_SESSION_TOPOLOADER, 0x1e83d482, 0x1f1c, 0x4571, 0x84, 0x5, 0x88, 0xf4, 0xb2, 0x18, 0x1f, 0x71);" )

// MF_SESSION_GLOBAL_TIME
// Data type: UINT32
// If set to a nonzero value, then the Media Session expects all topologies
// it receives to have the MF_TOPOLOGY_PROJECTSTART and MF_TOPOLOGY_PROJECTSTOP
// attributes set to valid values that are relative to the beginning of the
// entire timeline.
cpp_quote( "EXTERN_GUID( MF_SESSION_GLOBAL_TIME, 0x1e83d482, 0x1f1c, 0x4571, 0x84, 0x5, 0x88, 0xf4, 0xb2, 0x18, 0x1f, 0x72);" )

// MF_SESSION_QUALITY_MANAGER
// Data type: GUID
// The Media Foundation default Quality Manager(QM) implementation will
// be playback specific. Third party applications can pass in their own custom
// QM. They can do this by passing a GUID for the QM in the
// MFCreateMediaSession/MFCreatePMPMediaSession call. The third party QM will
// be CoCreated. A GUID to the QM will be specified as an attribute,
// MF_SESSION_QUALITY_MANAGER, in the configuration passed to these functions.
// To get rid of the Quality Manager altogether an application can pass in
// GUID_NULL for the MF_SESSION_QUALITY_MANAGER configuration attribute.
// {EF8436C7-2512-4abd-AC73-20C8186D2B7F}
cpp_quote( "EXTERN_GUID( MF_SESSION_QUALITY_MANAGER, 0x1e83d482, 0x1f1c, 0x4571, 0x84, 0x5, 0x88, 0xf4, 0xb2, 0x18, 0x1f, 0x73);" )


//
// MFCreatePMPMediaSession attributes
//

// MF_SESSION_CONTENT_PROTECTION_MANAGER
// Data type: IUNKNOWN
// The application supplies an object implementing IMFContentProtectionManager
// which can handle operations related to protected content (such as license
// {AFE5B29D-50FA-46e8-B9BE-0C0C3CE4B3A5}
// acquisition)
cpp_quote( "EXTERN_GUID( MF_SESSION_CONTENT_PROTECTION_MANAGER, 0x1e83d482, 0x1f1c, 0x4571, 0x84, 0x5, 0x88, 0xf4, 0xb2, 0x18, 0x1f, 0x74);" )

// MF_SESSION_SERVER_CONTEXT
// Data type: IUNKNOWN
// Application can set MF_SESSION_SERVER_CONTEXT property if it wants to
// share PMP process among more then one session.
// To do this, application has to request MF_PMP_SERVER_CONTEXT service
// from first mediasession and store it in the configuration for the
// second session
cpp_quote( "EXTERN_GUID( MF_SESSION_SERVER_CONTEXT, 0xafe5b291, 0x50fa, 0x46e8, 0xb9, 0xbe, 0xc, 0xc, 0x3c, 0xe4, 0xb3, 0xa5);" )


// MF_SESSION_REMOTE_SOURCE_MODE
// Data type: UINT32
// Application can set MF_SESSION_REMOTE_SOURCE_MODE property to indicate that source is already running in remote
// process and PMPSession does not have to remote it
cpp_quote( "EXTERN_GUID( MF_SESSION_REMOTE_SOURCE_MODE, 0xf4033ef4, 0x9bb3, 0x4378, 0x94, 0x1f, 0x85, 0xa0, 0x85, 0x6b, 0xc2, 0x44);"  )

// MF_SESSION_APPROX_EVENT_OCCURRENCE_TIME
// Data type: UINT64
// Some events fired by the media session will have this attribute attached. This attribute represents
// the approximate time of the presentation clock at the time the event occured. This is useful for scenarios where
// the presentation clock may be reset when the consumer receives the event (i.e. MESessionStopped).
cpp_quote( "EXTERN_GUID( MF_SESSION_APPROX_EVENT_OCCURRENCE_TIME, 0x190e852f, 0x6238, 0x42d1, 0xb5, 0xaf, 0x69, 0xea, 0x33, 0x8e, 0xf8, 0x50);" )

//
// Media Session constants
//

// MF_PMP_SERVER_CONTEXT
// An application wishing to share the same PMP process among multiple
// Media Sessions should obtain the PMP Server Context service from the first
// Media Session using this service GUID and store this as the
// MF_SESSION_SERVER_CONTEXT attribute in the second Media Session's
// configuration attributes.
cpp_quote( "EXTERN_GUID( MF_PMP_SERVER_CONTEXT, 0x2f00c910, 0xd2cf, 0x4278, 0x8b, 0x6a, 0xd0, 0x77, 0xfa, 0xc3, 0xa2, 0x5f);"  )

//
// Media Session functions
//

/// <summary>
///     Creates a Media Processing Session.  Applications that do not plan
///     to play protected content can create the Media Session this way.
/// </summary>
/// <param name="pConfiguration">
///     Specifies a pointer to an IMFAttributes object.
/// </param>
/// <param name="ppMediaSession">
///     Specifies a pointer to a variable where the media session object
///     will be stored.
/// </param>
cpp_quote( "STDAPI MFCreateMediaSession(" )
cpp_quote( "    IMFAttributes* pConfiguration," )
cpp_quote( "    __out IMFMediaSession** ppMediaSession" )
cpp_quote( "    );" )

/// <summary>
///     Creates a PMP (Protected Media Path) Media Session
/// </summary>
/// <param name="dwCreationFlags">
///     Bitflags containing a combination of the bits specified
///     by MFPMPSESSION_CREATION_FLAGS.
///     See MFPMPSESSION_CREATION_FLAGS for details.
/// </param>
/// <param name="pConfiguration">
///     Specifies a pointer to an IMFAttributes object.
///     Applications can set the following attributes:
///         MF_SESSION_CONTENT_PROTECTION_MANAGER
///             This is a pointer to an application-implemented
///             IMFContentProtectionManager to handle protected content
///             operations.
///             See IMFContentProtectionManager for details.
/// </param>
/// <param name="ppMediaSession">
///     Specifies a pointer to a variable where the PMP Media Session object
///     will be stored
/// </param>

cpp_quote( "STDAPI MFCreatePMPMediaSession(" )
cpp_quote( "    DWORD dwCreationFlags," )
cpp_quote( "    IMFAttributes *pConfiguration," )
cpp_quote( "    __out IMFMediaSession** ppMediaSession," )
cpp_quote( "    __out_opt IMFActivate **ppEnablerActivate" )
cpp_quote( "    );" )


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

//
// Resolution will return one of the following source types
//
typedef enum MF_OBJECT_TYPE
{
    MF_OBJECT_MEDIASOURCE,
    MF_OBJECT_BYTESTREAM,
    MF_OBJECT_INVALID
} MF_OBJECT_TYPE;

enum
{
    //
    // Object type requested
    //
    MF_RESOLUTION_MEDIASOURCE       = 0x00000001,  // Attempt to return a MediaSource object
    MF_RESOLUTION_BYTESTREAM        = 0x00000002,  // Attempt to return a ByteStream object (not currently supported)

    //
    // Advanced resolution
    //
    MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE   = 0x00000010,
        // Enumerates though all handlers, if the default handler for the extension fails. For example,
        // suppose we have a WMV file with the extension ".MP3".  If you do not specify this flag, then the
        // resolver will only try to invoke the MP3 handler on the file and it will fail since it is not an mp3 file.
        // If this flag is specified, then after the failure, it will enumerate through all it's known handlers to
        // see if any of them will accept the file
        // NOTE: This flag is mutually exclusive with the MF_RESOLUTION_KEEP_BYTE_STREAM_ALIVE_ON_FAIL flag

    MF_RESOLUTION_KEEP_BYTE_STREAM_ALIVE_ON_FAIL              = 0x00000020,
        // This flag allows the bytestream that the resolver creates during resolution to be cached (kept alive) on failure
        // so it can be used on the subsequent call.  By specifying this flag, the caller agrees to attempt resolution
        // again if the resolution fails.  For example, suppose we are trying to play back a network URL that points to a
        // file with extension ".MP3" and resolution fails because the file is really a misnamed WMV file.  If this
        // flag is specified for the first resolution, then the network byte stream is cached (kept alive) by the resolver.
        // On the subsequent resolution, the user would specify the MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE
        // flag to allow handler enumeration.  By using the MF_RESOLUTION_KEEP_BYTE_STREAM_ALIVE_ON_FAIL, the networked URL
        // is accessed once even though resolution is done twice.  In this manner, the web server logs depict a more
        // accurate access count.
        // NOTE: This flag is mutually exclusive with the MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE flag

    //
    // Access mode requested
    //
        //In what mode should the requested resource be open
    MF_RESOLUTION_READ              = 0x00010000,
    MF_RESOLUTION_WRITE             = 0x00020000
};

typedef enum _MF_CONNECT_METHOD
{
    MF_CONNECT_DIRECT              = 0x00000000,
    MF_CONNECT_ALLOW_CONVERTER     = 0x00000001,
    MF_CONNECT_ALLOW_DECODER       = 0x00000003,

    //
    // If MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES is set, the topoloader
    // tries to fully resolve each output type, by inserting decoders/converters, etc. The
    // next type in the list of output types is tried only if every attempt to resolve the current
    // one failed.
    // Currently this flag is only used in conjunction with the MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES flag.
    // And as such it should be set only on a SourceStream topo node. If this flag is set on any other node, it is
    // a no-op.
    //
    MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES  = 0x00000004,
    MF_CONNECT_AS_OPTIONAL         = 0x00010000,
    MF_CONNECT_AS_OPTIONAL_BRANCH  = 0x00020000,
} MF_CONNECT_METHOD;

typedef enum _MF_TOPOLOGY_RESOLUTION_STATUS_FLAGS
{
    MF_TOPOLOGY_RESOLUTION_SUCCEEDED            = 0x00000000,
    MF_OPTIONAL_NODE_REJECTED_MEDIA_TYPE        = 0x00000001,
    MF_OPTIONAL_NODE_REJECTED_PROTECTED_PROCESS = 0x00000002,
} MF_TOPOLOGY_RESOLUTION_STATUS_FLAGS;


interface IMFByteStream;

[
    object,
    uuid(FBE5A32D-A497-4b61-BB85-97B1A848A6E3),
]
/// <summary>
///     The Media Foundation Source Resolver can be used to resolve an
///     URL or an IMFByteStream object into the correct Media Source
///     for reading this content.
///     Whenever an IPropertyStore * input param appears, this parameter
///     is to contain any configuration attributes that will be needed
///     in creating this Media Source.
/// </summary>
interface IMFSourceResolver : IUnknown
{
    [local]
    HRESULT CreateObjectFromURL(
                [in] LPCWSTR pwszURL,
                [in] DWORD dwFlags,
                [in] IPropertyStore *pProps,
                [out, annotation("__out")]  MF_OBJECT_TYPE *pObjectType,
                [out, annotation("__out")]  IUnknown **ppObject
                );

    [local]
    HRESULT CreateObjectFromByteStream(
                [in] IMFByteStream* pByteStream,
                [in] LPCWSTR pwszURL,
                [in] DWORD dwFlags,
                [in] IPropertyStore *pProps,
                [out, annotation("__out")]  MF_OBJECT_TYPE *pObjectType,
                [out, annotation("__out")]  IUnknown **ppObject
                );

    [local]
    HRESULT BeginCreateObjectFromURL(
                [in] LPCWSTR pwszURL,
                [in] DWORD dwFlags,
                [in] IPropertyStore *pProps,
                [out, annotation("__out_opt")] IUnknown **ppIUnknownCancelCookie,
                [in] IMFAsyncCallback *pCallback,
                [in] IUnknown *punkState
                );

    [call_as(BeginCreateObjectFromURL)]
    HRESULT RemoteBeginCreateObjectFromURL(
                [in, string] LPCWSTR pwszURL,
                [in] DWORD dwFlags,
                [in] IPropertyStore *pProps,
                [in] IMFRemoteAsyncCallback *pCallback
                );

    [local]
    HRESULT EndCreateObjectFromURL(
                [in]   IMFAsyncResult *pResult,
                [out, annotation("__out")]  MF_OBJECT_TYPE *pObjectType,
                [out, annotation("__out")]  IUnknown **ppObject
                );

    [call_as(EndCreateObjectFromURL)]
    HRESULT RemoteEndCreateObjectFromURL(
                [in]   IUnknown *pResult,
                [out]  MF_OBJECT_TYPE *pObjectType,
                [out]  IUnknown **ppObject
                );

    [local]
    HRESULT BeginCreateObjectFromByteStream(
                [in] IMFByteStream* pByteStream,
                [in] LPCWSTR pwszURL,
                [in] DWORD dwFlags,
                [in] IPropertyStore *pProps,
                [out, annotation("__out_opt")] IUnknown **ppIUnknownCancelCookie,
                [in] IMFAsyncCallback *pCallback,
                [in] IUnknown *punkState
                );

    [call_as(BeginCreateObjectFromByteStream)]
    HRESULT RemoteBeginCreateObjectFromByteStream(
        [in] IMFByteStream* pByteStream,
        [in] LPCWSTR pwszURL,
        [in] DWORD dwFlags,
        [in] IPropertyStore *pProps,
        [in] IMFRemoteAsyncCallback *pCallback
        );


    [local]
    HRESULT EndCreateObjectFromByteStream(
                [in]   IMFAsyncResult *pResult,
                [out, annotation("__out")]  MF_OBJECT_TYPE *pObjectType,
                [out, annotation("__out")]  IUnknown **ppObject
                );

    [call_as(EndCreateObjectFromByteStream)]
    HRESULT RemoteEndCreateObjectFromByteStream(
                [in]   IUnknown *pResult,
                [out]  MF_OBJECT_TYPE *pObjectType,
                [out]  IUnknown **ppObject
                );

    [local]
    HRESULT CancelObjectCreation(
                [in] IUnknown *pIUnknownCancelCookie
                );
}

cpp_quote( "STDAPI MFCreateSourceResolver( "                )
cpp_quote( "        /* out */     __out IMFSourceResolver     **ppISourceResolver);" )

cpp_quote( "STDAPI CreatePropertyStore( " )
cpp_quote( "        /* out */     __out IPropertyStore        **ppStore);" )


/// <summary>
///     Returns the currently registered MF schemes
/// </summary>
/// <param name="pPropVarSchemeArray">
///     Pointer to a PROPVARIANT that will receive the array (VT_VECTOR)
///     of VT_LPWSTRs that contains the currently registered MF schemes
/// </param>
/// <remarks>
///     Before calling this function, PropVariantInit() should be called
///     on the PROPVARIANT argument.
///     The user of this function is responsible for calling PropVariantClear()
///     on the PROPVARIANT to ensure that the array of strings is deallocated.
/// </remarks>
cpp_quote( "STDAPI MFGetSupportedSchemes(                      ")
cpp_quote( "       __out PROPVARIANT* pPropVarSchemeArray  );  ")

/// <summary>
///     Returns the currently registered MIME types supported by MF Byte Streams
/// </summary>
/// <param name="pPropVarMimeTypeArray">
///     Pointer to a PROPVARIANT that will receive the array (VT_VECTOR)
///     of VT_LPWSTRs that contains the currently registered MIME types
/// </param>
/// <remarks>
///     Before calling this function, PropVariantInit() should be called
///     on the PROPVARIANT argument.
///     The user of this function is responsible for calling PropVariantClear()
///     on the PROPVARIANT to ensure that the array of strings is deallocated.
/// </remarks>
cpp_quote( "STDAPI MFGetSupportedMimeTypes(                      ")
cpp_quote( "       __out PROPVARIANT* pPropVarMimeTypeArray  );  ")


//
// Properties for the configuration property store in the Source Resolver
// creation methods
//

// Type: VT_UNKNOWN
// The application can pass in an object implementing IMFSourceOpenMonitor
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_SourceOpenMonitor = { { 0x074d4637, 0xb5ae, 0x465d, 0xaf, 0x17, 0x1a, 0x53, 0x8d, 0x28, 0x59, 0xdd}, 0x02 }; ")

// Type: VT_BOOL
// When this is set to VARIANT_TRUE, if an ASF Media Source is created,
// it will perform all seek operations approximately (and more quickly)
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_ASFMediaSource_ApproxSeek = { { 0xb4cd270f, 0x244d, 0x4969, 0xbb, 0x92, 0x3f, 0x0f, 0xb8, 0x31, 0x6f, 0x10}, 0x01 }; ")

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
// Type: VT_BOOL
// When this is set to VARIANT_TRUE, if an ASF Media Source is created,
// it will perform iterative seek if there is  no index
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_ASFMediaSource_IterativeSeekIfNoIndex = { { 0x170b65dc, 0x4a4e, 0x407a, 0xac, 0x22, 0x57, 0x7f, 0x50, 0xe4, 0xa3, 0x7c }, 0x01 }; ")

// Type: VT_UINT32
// Only valid when MFPKEY_ASFMediaSource_IterativeSeekIfNoIndex is set to TRUE
// The count is any integer [1, 10]
// If this value is not set, the default value 5 is used.
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_ASFMediaSource_IterativeSeek_Max_Count = { { 0x170b65dc, 0x4a4e, 0x407a, 0xac, 0x22, 0x57, 0x7f, 0x50, 0xe4, 0xa3, 0x7c }, 0x02 }; ")

// Type: VT_UINT32
// Only valid when MFPKEY_ASFMediaSource_IterativeSeekIfNoIndex is set to TRUE
// the tolerance zone is the difference that allowed between the real seek time and preferred seek time.
// Keyframe distance is recommended to use.
// If this value is not set, the default value 8000 millisecond is used.
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_ASFMediaSource_IterativeSeek_Tolerance_In_MilliSecond = { { 0x170b65dc, 0x4a4e, 0x407a, 0xac, 0x22, 0x57, 0x7f, 0x50, 0xe4, 0xa3, 0x7c }, 0x03 }; ")

//
// DLNA Profile ID - needed for media sharing.
//
// {CFA31B45-525D-4998-BB44-3F7D81542FA4}
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_Content_DLNA_Profile_ID = { { 0xcfa31b45, 0x525d, 0x4998, 0xbb, 0x44, 0x3f, 0x7d, 0x81, 0x54, 0x2f, 0xa4 }, 0x01 }; ")

// Type: VT_BOOL
// When this is set to VARIANT_TRUE, the media source is requested to disable any read-ahead.
// This can be a useful performance optimization to limit disk read when a media source will 
// only be instantiated for limited tasks, such as reading video thumbnail data.
// Not all sources will support this feature.
// {26366C14-C5BF-4c76-887B-9F1754DB5F09}
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_MediaSource_DisableReadAhead = { { 0x26366c14, 0xc5bf, 0x4c76, 0x88, 0x7b, 0x9f, 0x17, 0x54, 0xdb, 0x5f, 0x9}, 0x01 }; ")

cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

/// <summary>
///     Bitflags returned by IMFMediaSource::GetCharacteristics
/// </summary>
typedef enum _MFMEDIASOURCE_CHARACTERISTICS
{
    /// <summary>
    ///     This bit should be set if the Media Source is sourcing a live
    ///     presentation
    /// <summary>
    MFMEDIASOURCE_IS_LIVE           = 0x1,

    /// <summary>
    ///     This bit should be set if the Media Source supports seeking
    /// </summary>
    MFMEDIASOURCE_CAN_SEEK          = 0x2,

    /// <summary>
    ///     This bit should be set if the Media Source supports pausing
    /// </summary>
    MFMEDIASOURCE_CAN_PAUSE         = 0x4,

    /// <summary>
    ///     This bit should be set if the Media Source downloads content
    ///     and seeking outside the downloaded area is slow.
    /// </summary>
    MFMEDIASOURCE_HAS_SLOW_SEEK    = 0x8,

#if (WINVER >= _WIN32_WINNT_WIN7)
    /// <summary>
    ///     This bit should be set if the Media Source may change presentation
    ///     information during playback, such as network sources.
    /// </summary>
    MFMEDIASOURCE_HAS_MULTIPLE_PRESENTATIONS    = 0x10,

    /// <summary>
    ///     This bit should be set if the Media Source can skip to the next
    ///     playlist entry
    /// </summary>
    MFMEDIASOURCE_CAN_SKIPFORWARD    = 0x20,

    /// <summary>
    ///     This bit should be set if the Media Source can skip to the previous
    ///     playlist entry
    /// </summary>
    MFMEDIASOURCE_CAN_SKIPBACKWARD    = 0x40
#endif // (WINVER >= _WIN32_WINNT_WIN7)

}   MFMEDIASOURCE_CHARACTERISTICS;

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
/// <summary>
///     MF_TIME_FORMAT_ENTRY_RELATIVE can be used as the pguidTimeFormat
///     argument to IMFMediaSession::Start and IMFMediaSource::Start to
///     indicate that playback should start at a given offset relative to
///     current play list entry.The associated PROPVARIANT should be of type 
///     VT_I4, indicated the entry offset from current entry.
/// </summary>
cpp_quote( "EXTERN_GUID( MF_TIME_FORMAT_ENTRY_RELATIVE, 0x4399f178, 0x46d3, 0x4504, 0xaf, 0xda, 0x20, 0xd3, 0x2e, 0x9b, 0xa3, 0x60 );" )

cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

interface IMFPresentationDescriptor;
interface IMFStreamDescriptor;

[
    object,
    uuid(279a808d-aec7-40c8-9c6b-a6b492c78a66),
]
/// <summary>
///     IMFMediaSource is the interface implemented by Media Sources in
///     the MF pipeline
/// </summary>
interface IMFMediaSource : IMFMediaEventGenerator
{
    /// <summary>
    ///     Returns the characteristics of this Media Source
    /// </summary>
    /// <param name="pdwCharacteristics">
    ///     Pointer to a variable in which the characteristics will be stored.
    ///     *pdwCharacteristics will be a combination of the bitflags
    ///     in the MFMEDIASOURCE_CHARACTERISTICS enumerated type.
    /// </param>
    /// <remarks>
    ///     Characteristics may change throughout the life of the Media Source
    /// </remarks>
    HRESULT GetCharacteristics(
        [out] DWORD* pdwCharacteristics);

    /// <summary>
    ///     Obtains a Presentation Descriptor describing the presentation
    ///     being sourced by the Media Source.
    /// </summary>
    /// <param name="ppPresentationDescriptor">
    ///     Pointer to a variable in which a pointer to the Presentation
    ///     Descriptor for this presentation will be stored.
    /// </param>
    /// <remarks>
    ///     When this call is being made to a Media Source in a remote
    ///     process, this call will be proxied via
    ///     RemoteCreatePresentationDescriptor.
    ///     In this case, a local copy of the Presentation Descriptor
    ///     will be returned.
    /// </remarks>
    [local]
    HRESULT CreatePresentationDescriptor(
        [out, annotation("__out")] IMFPresentationDescriptor** ppPresentationDescriptor);

    /// <summary>
    ///     This method is used to proxy CreatePresentationDescriptor calls
    ///     to a Media Source in a remote process.
    ///     Media Sources do not need to implement this method.
    /// </summary>
    /// <remarks>
    ///     This call will result in a call to
    ///     IMFMediaSource::CreatePresentationDescriptor on the remote
    ///     Media Source
    /// </remarks>
    [call_as(CreatePresentationDescriptor)]
    HRESULT RemoteCreatePresentationDescriptor(
        [out] DWORD * pcbPD,
        [out, size_is(, *pcbPD)] BYTE ** pbPD,
        [out] IMFPresentationDescriptor ** ppRemotePD);

    /// <summary>
    ///     Starts the presentation on this Media Source
    /// </summary>
    /// <param name="pPresentationDescriptor">
    ///     The caller can obtain this Presentation Descriptor from
    ///     CreatePresentationDescriptor.
    ///     The application can use this Presentation Descriptor to indicate
    ///     which streams to select, by means of the IMFPresentationDescriptor
    ///     methods
    /// </param>
    /// <param name="pguidTimeFormat">
    ///     Specifies the time format that should be used to interpret
    ///     the pvarStartPosition parameter.
    ///     Can be NULL, in which case, pvarStartPosition will be in terms
    ///     of MFTIME.
    ///     Support for other time formats varies across Media Source
    ///     implementations.
    /// </param>
    /// <param name="pvarStartPosition">
    ///     Specifies where to start playback.
    ///     This value is interpreted according to the value of pguidTimeFormat.
    ///     If pguidTimeFormat is NULL or *pguidTimeFormat is GUID_NULL, then
    ///     pvarStartPosition should either be of type VT_I8, with its value
    ///     specifying a time offset in MFTIME units; or it can be VT_EMPTY
    ///     to specify that the Media Session should start at the current
    ///     position.
    /// </param>
    HRESULT Start(
        [in] IMFPresentationDescriptor* pPresentationDescriptor,
        [in, unique] const GUID* pguidTimeFormat,
        [in, unique] const PROPVARIANT* pvarStartPosition);

    /// <summary>
    ///     Stops the presentation on this Media Source
    /// </summary>
    /// <remarks>
    ///     If Start() is subsequently called with a NULL or VT_EMPTY
    ///     pvarStartPosition, playback will begin at the beginning of the
    ///     presentation.
    /// </remarks>
    HRESULT Stop( void );

    /// <summary>
    ///     Pauses the presentation on this Media Source
    /// </summary>
    /// <remarks>
    ///     Not all Media Sources support pausing.
    ///     Media Sources that support pausing should set the
    ///     MFMEDIASOURCE_CAN_PAUSE characteristic in GetCharateristics.
    ///     Those that do not support it may fail this call.
    ///     If the Media Session supports pausing, then if Start()
    ///     is subsequently called with a NULL or VT_EMPTY pvarStartPosition,
    ///     then playback will resume from its current position
    /// </remarks>
    HRESULT Pause( void );

    /// <summary>
    ///     Shuts down the Media Source and releases all resources.
    /// </summary>
    /// <remarks>
    ///     If the application created the Media Source -- whether manually
    ///     or via IMFSourceResolver -- the application is responsible for
    ///     calling Shutdown on the Media Source in order to avoid memory
    ///     or resource leaks
    /// </remarks>
    HRESULT Shutdown( void );
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
[
    object,
    uuid(D182108F-4EC6-443f-AA42-A71106EC825F),
]
interface IMFMediaStream : IMFMediaEventGenerator
{
    HRESULT GetMediaSource(
        [out] IMFMediaSource** ppMediaSource
        );

    HRESULT GetStreamDescriptor(
        [out] IMFStreamDescriptor** ppStreamDescriptor
        );

    [local]
    HRESULT RequestSample(
        [in] IUnknown* pToken
        );

    [call_as(RequestSample)]
    HRESULT RemoteRequestSample(
        );
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

//
// Sink characteristics
//
cpp_quote( "#define MEDIASINK_FIXED_STREAMS         0x00000001" )
cpp_quote( "#define MEDIASINK_CANNOT_MATCH_CLOCK    0x00000002" )
cpp_quote( "#define MEDIASINK_RATELESS              0x00000004" )
cpp_quote( "#define MEDIASINK_CLOCK_REQUIRED        0x00000008" )
cpp_quote( "#define MEDIASINK_CAN_PREROLL           0x00000010" )

/// <summary>
/// MediaSink should expose cap if it requires mediatype to be set on the reference stream in order to connect other streams
/// Topoloader will use this flag to set mediatype during topology resolution
/// </summary>
cpp_quote( "#define MEDIASINK_REQUIRE_REFERENCE_MEDIATYPE 0x00000020" )


interface IMFPresentationClock;
interface IMFStreamSink;

[
    object,
    uuid(6ef2a660-47c0-4666-b13d-cbb717f2fa2c)
]
/// <summary>
/// The IMFMediaSink interface is the base interface for all
/// Media Foundation sinks (for both encoding and rendering).
/// While Stream Sinks handle the actual processing of data on
/// each stream, the Media Sink is responsible for managing the
/// sink end of the presentation as a whole.
/// </summary>
interface IMFMediaSink : IUnknown
{
    /// <summary>
    ///     The GetCharacteristics method allows the caller to
    ///     retrieve the characteristics for this Media Sink.
    /// </summary>
    /// <param name="pdwCharacteristics">
    ///     Pointer to a variable where the Media Sink characteristics
    ///     flags will be returned.  Should not be NULL.
    /// </param>
    /// <remarks>
    ///     The characteristics can be a combination of zero or
    ///     more of the following flags:
    ///     <para>
    ///         MEDIASINK_FIXED_STREAMS:
    ///             This flag indicates that AddStreamSink and
    ///             RemoveStreamSink are not supported, since the
    ///             Media Sink creates and maintains a fixed set
    ///             of StreamSinks.
    ///     </para>
    ///     <para>
    ///         MEDIASINK_CANNOT_MATCH_CLOCK:
    ///             This flag indicates that this Media Sink cannot
    ///             match to an outside Presentation Time Source.
    ///             If this flag is set, then calling SetPresentationClock
    ///             on this Media Sink with a Presentation Clock that is
    ///             using a Time Source other than the one provided by
    ///             this Media Sink will have suboptimal results.
    ///             This flag should be used sparingly, since it restricts
    ///             the scenarios in which this Media Sink can be used.
    ///     </para>
    ///     <para>
    ///         MEDIASINK_RATELESS:
    ///             This flag indicates that the Media Sink is "rateless".
    ///             This means that the Media Sink simply operates as quickly
    ///             as possible and does not make any attempt to operate in
    ///             real time or to sync to a presentation clock.
    ///             Most archiving sinks are rateless.
    ///             See the MF Timing Model design doc for more details on how
    ///             rateless sinks are handled.
    ///     </para>
    ///     <para>
    ///         MEDIASINK_CLOCK_REQUIRED:
    ///             This flag indicates that the Media Sink requires a
    ///             Presentation Clock to be set via
    ///             IMFMediaSink::SetPresentationClock in order for the
    ///             sink to operate correctly.
    ///             Video renderers that depend on a presentation clock
    ///             for scheduling when to display their frames should
    ///             set this flag.
    ///     </para>
    /// </remarks>
    HRESULT GetCharacteristics(
        [out] DWORD* pdwCharacteristics
        );

    /// <summary>
    ///     The AddStreamSink method provides a way to add a Stream Sink
    ///     supporting the given Media Type.
    /// </summary>
    /// <param name="dwStreamSinkIdentifier">
    ///     Identifier of the stream sink to support pMediaType.
    ///     This must be an identifier that is not currently in use.
    /// </param>
    /// <param name="pMediaType">
    ///     Pointer to the Media Type to support.
    ///     This can point to a valid media type, or it can be NULL
    ///     to signify that media type negotiation will happen later.
    /// </param>
    /// <param name="ppStreamSink">
    ///     Pointer to a variable in which the pointer to the new
    ///     Stream Sink is returned.  Should not be NULL.
    /// </param>
    /// <returns>
    ///     <para>
    ///         MF_E_MEDIASINK_FIXED_STREAMS:
    ///             This Media Sink has a fixed set of Stream Sinks,
    ///             and therefore AddStreamSink and RemoveStreamSink are not
    ///             supported.
    ///     </para>
    ///     <para>
    ///         MF_E_STREAMSINK_EXISTS:
    ///             A Stream Sink with identifier dwStreamSinkIdentifier
    ///             already exists.
    ///     </para>
    /// </returns>
    /// <remarks>
    ///     Media Sinks that set MEDIASINK_FIXED_STREAMS in GetCharacteristics
    ///     will fail this call.
    /// </remarks>
    HRESULT AddStreamSink(
        [in] DWORD dwStreamSinkIdentifier,
        [in] IMFMediaType* pMediaType,
        [out] IMFStreamSink** ppStreamSink
        );

    /// <summary>
    ///     The RemoveStreamSink method signals to the Media Sink that
    ///     the Stream Sink with the given identifier will no longer be
    ///     used and should no longer be enumerated.
    /// </summary>
    /// <param name="dwStreamSinkIdentifier">
    ///     Identifier of the Stream Sink to remove.
    /// </param>
    /// <returns>
    ///     <para>
    ///         MF_E_MEDIASINK_FIXED_STREAMS:
    ///             This Media Sink has a fixed set of Stream Sinks,
    ///             and therefore AddStreamSink and RemoveStreamSink are not
    ///             supported.
    ///     </para>
    ///     <para>
    ///         MF_E_INVALIDSTREAMNUMBER:
    ///             There is no Stream Sink with identifier dwStreamSinkIdentifier.
    ///     </para>
    ///     <para>
    ///         MF_E_STREAM_REMOVED:
    ///             This Stream Sink has already been removed
    ///     </para>
    /// </returns>
    /// <remarks>
    ///     Media Sinks that set MEDIASINK_FIXED_STREAMS in GetCharacteristics
    ///     will fail this call.
    ///     This Stream Sink will no longer be enumerated by
    ///     GetStreamSinkByIndex or by GetStreamSinkById.
    ///     This same identifier can be used to create a new Stream Sink
    ///     via AddStreamSink.
    /// </remarks>
    HRESULT RemoveStreamSink(
        [in] DWORD dwStreamSinkIdentifier
        );

    /// <summary>
    ///     The GetStreamSinkCount method allows the user to
    ///     retrieve the number of Stream Sinks associated with
    ///     this Media Sink.
    /// </summary>
    /// <param name="pcStreamSinkCount">
    ///     Pointer to a variable in which the number of Stream Sinks
    ///     associated with this Media Sink will be returned.
    ///     Should not be NULL.
    /// </param>
    HRESULT GetStreamSinkCount(
        [out] DWORD* pcStreamSinkCount
        );

    /// <summary>
    ///     The GetStreamSinkByIndex method allows the user to
    ///     retrieve a pointer to a Stream Sink associated with
    ///     this Media Sink given its index among the Media Sink's
    ///     Stream Sinks.
    /// </summary>
    /// <param name="dwIndex">
    ///     0-based index into the Media Sink's Stream Sinks.
    /// </param>
    /// <param name="ppStreamSink">
    ///     Pointer to a variable that in which the pointer to
    ///     the requested Stream Sink will be returned.  Should not be NULL.
    /// </param>
    /// <remarks>
    ///     Note that enumeration is not a thread-safe operation,
    ///     since Stream Sinks can be added or removed between
    ///     calls to this method.
    /// </remarks>
    HRESULT GetStreamSinkByIndex(
        [in] DWORD dwIndex,
        [out] IMFStreamSink** ppStreamSink
        );

    /// <summary>
    ///     The GetStreamSinkById method allows the user to retrieve
    ///     a pointer to a Stream Sink associated with this Media Sink
    ///     given its Stream Sink identifier.
    /// </summary>
    /// <param name="dwStreamSinkIdentifier">
    ///     The Stream Sink identifier for the desired Stream Sink.
    /// </param>
    /// <param name="ppStreamSink">
    ///     Pointer to a variable in which the pointer to the requested
    ///     Stream Sink will be returned.  Should not be NULL.
    /// </param>
    /// <returns>
    ///     <para>
    ///         MF_E_INVALIDSTREAMNUMBER:
    ///             There is no Stream Sink with the given identifier.
    ///     </para>
    /// </returns>
    HRESULT GetStreamSinkById(
        [in] DWORD dwStreamSinkIdentifier,
        [out] IMFStreamSink** ppStreamSink
        );

    /// <summary>
    ///     The SetPresentationClock method allows the user to set a
    ///     Presentation Clock on the Media Sink that will control
    ///     how it sinks data
    /// </summary>
    /// <param name="pPresentationClock">
    ///     A pointer to the Presentation Clock that the user chooses
    ///     to control the sinking behavior.  Can be NULL.
    /// </param>
    /// <remarks>
    ///     <para>
    ///         A NULL value indicates that the Media Sink is being removed
    ///         from the presentation.  The Media Sink should call
    ///         IMFPresentationClock::RemoveClockStateSink to stop listening
    ///         for notifications from its former Presentation Clock.
    ///     </para>
    ///     <para>
    ///         pPresentationClock must have already had a valid
    ///         Presentation Time Source set.
    ///         Implementations must handle this call.
    ///     </para>
    ///     <para>
    ///         If this Media Sink is a Presentation Time Source, the Presentation
    ///         Clock may or may not be using this Media Sink as the Presentation
    ///         Time Source.
    ///         If SetPresentationClock has been called, the Media Sink should
    ///         pay attention to the time on that Presentation Clock's Time Source
    ///         and not fall behind, even if a Presentation Time Source other
    ///         than this Media Sink is being used by the Presentation Clock.
    ///         The exception is rateless sinks, which
    ///         will ignore the clock.  If a Media Sink cannot do this,
    ///         then the MEDIASINK_CANNOT_MATCH_CLOCK flag should be set from
    ///         GetCharacteristics.  In this case, SetPresentationClock
    ///         should still succeed, but the results may be suboptimal
    ///         if this sink's failure to allocate samples quickly enough holds
    ///         up the entire pipeline.
    ///     </para>
    ///     <para>
    ///         The Media Sink is expected to call AddClockStateSink
    ///         on this Presentation Clock to register itself
    ///         for clock state change notifications.
    ///         The Media Sink is expected to call RemoveClockStateSink
    ///         to deregister itself when a new Presentation Clock is
    ///         set via SetPresentationClock, or upon shutdown of the
    ///         Media Sink.
    ///     </para>
    /// </remarks>
    HRESULT SetPresentationClock(
        [in] IMFPresentationClock* pPresentationClock
        );

    /// <summary>
    ///     The GetPresentationClock method allows the user to
    ///     retrieve the last Presentation Clock that was set
    ///     on the Media Sink.
    /// </summary>
    /// <param name="ppPresentationClock">
    ///     A pointer to a variable in which a pointer to the last
    ///     Presentation Clock set on this Media Sink is returned.
    ///     Should not be NULL.
    /// </param>
    /// <returns>
    ///     <para>
    ///         MF_E_NO_CLOCK:
    ///             No clock was ever set.
    ///     </para>
    /// </returns>
    HRESULT GetPresentationClock(
        [out] IMFPresentationClock** ppPresentationClock
        );

    /// <summary>
    ///     The Shutdown method causes all the resources used by the
    ///     Media Sink to be properly shutdown and released.
    ///     The Media Sink should be shut down when the caller is done with
    ///     it to prevent memory leaks
    /// </summary>
    /// <remarks>
    ///     Upon successful completion of this call, all
    ///     methods on the Media Sink will return MF_E_SHUTDOWN when called.
    ///     The exception is the IMFMediaEventGenerator calls
    ///     which are still allowed.
    /// </remarks>
    HRESULT Shutdown();
}


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

/// <summary>
/// Marker types for use with IMFStreamSink::PlaceMarker.
/// </summary>
typedef enum _MFSTREAMSINK_MARKER_TYPE
{
    /// <member name="MFSTREAMSINK_MARKER_DEFAULT">
    ///     This indicates that this marker is not meant to convey
    ///     any special information to the Stream Sink and is just
    ///     for the caller's use.
    /// </member>
    MFSTREAMSINK_MARKER_DEFAULT,

    /// <member name="MFSTREAMSINK_MARKER_ENDOFSEGMENT">
    ///     This is an informational marker sent to the Stream Sink
    ///     when the end of a particular segment (topology) for this stream has been
    ///     hit.
    ///     Receiving this marker is an indication that there may be
    ///     a gap in this stream until the next segment starts; however,
    ///     samples for the next segment may follow immediately.
    /// </member>
    MFSTREAMSINK_MARKER_ENDOFSEGMENT,

    /// <member name="MFSTREAMSINK_MARKER_TICK">
    ///     This is a hint to the Stream Sink that there is a gap
    ///     in the sample times.  The marker value associated with
    ///     this marker will be a VT_I8 100ns value indicating
    ///     the next possible sample time for this Stream Sink.
    ///     The Stream Sink can ignore this marker, but some Stream
    ///     Sinks will want to inspect these markers for optimal behavior.
    /// </member>
    MFSTREAMSINK_MARKER_TICK,

    /// <member name="MFSTREAMSINK_MARKER_EVENT">
    ///     The pvarMarkerValue argument to PlaceMarker will be a
    ///     VT_UNKNOWN containing an IMFMediaEvent.  This event
    ///     should be processed by the Stream Sink if the Stream Sink
    ///     recognizes it; otherwise, it should just send the marker
    ///     back.
    /// </member>
    MFSTREAMSINK_MARKER_EVENT,

}   MFSTREAMSINK_MARKER_TYPE;

interface IMFMediaTypeHandler;

[
    object,
    uuid(0A97B3CF-8E7C-4a3d-8F8C-0C843DC247FB),
]
/// <summary>
/// The IMFStreamSink interface is the base interface for all
/// Media Foundation stream-based sinks (for both encoding
/// and rendering).
/// </summary>
interface IMFStreamSink : IMFMediaEventGenerator
{
    /// <summary>
    ///     The GetMediaSink method allows the caller to retrieve
    ///     a pointer to the Media Sink to which this stream belongs.
    /// </summary>
    /// <param name=ppMediaSink>
    ///     Pointer to a variable where the pointer to the Media Sink
    ///     for this stream will be returned.  Should not be NULL.
    /// </param>
    /// <returns>
    ///     <para>
    ///         MF_E_STREAM_REMOVED:
    ///             This Stream Sink has been removed and is no longer usable.
    ///     </para>
    /// </returns>
    /// <remarks>
    ///     <para>
    ///         All Stream Sink objects should be associated with exactly
    ///         one Media Sink.  Media Sinks can contain more than one Stream Sink.
    ///     </para>
    ///     <para>
    ///         This call should return a pointer to a valid Media Sink
    ///         object, regardless of the state the Stream Sink was in when the
    ///         call was made.
    ///     </para>
    /// </remarks>
    HRESULT GetMediaSink(
        [out] IMFMediaSink** ppMediaSink
        );

    /// <summary>
    ///     The GetIdentifier method allows the caller to retrieve the
    ///     unique identifier for this stream.
    /// </summary>
    /// <param name=pdwIdentifier>
    ///     Pointer to a variable where the stream identifier will be returned.
    ///     Should not be NULL.
    /// </param>
    /// <returns>
    ///     <para>
    ///         MF_E_STREAM_REMOVED:
    ///             This Stream Sink has been removed and is no longer usable.
    ///     </para>
    /// </returns>
    /// <remarks>
    ///     <para>
    ///         This call should return a Stream Sink identifier that is unique
    ///         within this Media Sink.  It should do so regardless of the state
    ///         of the Stream Sink.
    ///     </para>
    ///     <para>
    ///         If the Stream Sink was created via IMFMediaSink::AddStreamSink,
    ///         then this identifier will be the identifier with which the Stream
    ///         Sink was created; otherwise, this identifier gets assigned by the
    ///         Media Sink itself.  For certain implementations, this identifier
    ///         has a meaning (for instance, in an ASF encoding sink, it would be
    ///         the ASF stream number); for other implementations it is simply an
    ///         identifier.
    ///     </para>
    /// </remarks>
    HRESULT GetIdentifier(
        [out] DWORD* pdwIdentifier
        );

    /// <summary>
    ///     The GetMediaTypeHandler method allows the caller to retrieve
    ///     the Media Type Handler for this stream, which will in turn
    ///     allow the user to see which media types are supported and to
    ///     choose a media type.
    /// </summary>
    /// <param name=ppMediaTypeHandler>
    ///     Pointer to a variable where the pointer to the stream's Media
    ///     Type Handler will be returned.  Should not be NULL.
    /// </param>
    /// <remarks>
    ///     This method should return a valid Media Type Handler, regardless
    ///     of the state the Stream Sink is in (except, of course, if the
    ///     Stream Sink has been removed from its Media Sink, in which case
    ///     MF_E_STREAMSINK_REMOVED will be returned).  If no media types
    ///     are currently supported, then the correct behavior is to return
    ///     a Media Type Handler that simply fails the
    ///     IMFMediaTypeHandler::GetCurrentMediaType and indicates from
    ///     IMFMedaTypeHandler::IsMediaTypeSupported that no media types
    ///     are supported.
    /// </remarks>
    HRESULT GetMediaTypeHandler(
        [out] IMFMediaTypeHandler** ppHandler
        );

    /// <summary>
    ///     The ProcessSample method provides a way for the user to send
    ///     samples into the Stream Sink to be either written or rendered.
    /// </summary>
    /// <param name=pSample>
    ///     Pointer to an object implementing IMFSample that contains the
    ///     sample to be written or rendered.
    /// </param>
    /// <returns>
    ///     <para>
    ///         MF_E_STREAM_REMOVED:
    ///             This Stream Sink has been removed and is no longer usable.
    ///     </para>
    ///     <para>
    ///         MF_E_INVALIDREQUEST:
    ///             This Stream Sink is either in the paused or stopped state
    ///             and cannot handle the sample.
    ///     </para>
    ///     <para>
    ///         MF_E_NO_TIMESTAMP:
    ///             pSample is missing a timestamp, and this Stream Sink
    ///             requires timestamps
    ///     </para>
    /// </returns>
    /// <remarks>
    ///     Please see Media Sink design spec for info on how ProcessSample works.
    /// </remarks>
    HRESULT ProcessSample(
        [in] IMFSample* pSample
        );

    /// <summary>
    ///     The PlaceMarker method indicates to the Stream Sink that
    ///     it should send an MEStreamSinkMarker event once it has
    ///     finished processing all samples that were passed in before
    ///     this call was made.
    /// </summary>
    /// <param name=eMarkerType>
    ///     Indicates type of marker
    /// </param>
    /// <param name=pvarMarkerValue>
    ///     This is an additional piece of data that may be useful,
    ///     depending on the value of eMarkerType.
    ///     For instance, if dwFlags is STREAMSINK_MARKER_TICK,
    ///     then this is a VT_I8 containing the next possible sample time,
    ///     in 100ns units.  May be NULL.
    /// </param>
    /// <param name=pvarContextValue>
    ///     This is an optional piece of context data that will be
    ////    returned to the caller as the value attached to the
    ////    MEStreamSinkMarker event.
    ////    This value is purely for the caller's use.
    ////    The Stream Sink should make its own copy of this PROPVARIANT.
    ////    May be NULL.
    /// </param>
    /// <returns>
    ///     <para>
    ///         MF_E_STREAM_REMOVED:
    ///             This Stream Sink has been removed and is no longer usable.
    ///     </para>
    /// </returns>
    /// <remarks>
    ///     Callers should call PlaceMarker with type STREAMSINK_MARKER_ENDOFSEGMENT
    ///     when they are done passing data to this Stream Sink.
    ///     All of the data waiting in the Stream Sink at the time of
    ///     PlaceMarker will still get handled, even if the type is
    ///     is STREAMSINK_MARKER_ENDOFSEGMENT..
    ///     This call should succeed and queue the MEStreamSinkMarker
    ///     event even while the Stream Sink is in a stopped or paused state
    ///     Even if Flush is called on the Stream Sink after a
    ///     PlaceMarker call but before the Stream Sink sends out the
    ///     MEStreamSinkMarker event, then the MEStreamSinkMarker event
    ///     should nevertheless get sent.
    ///     If the marker is of the STREAMSINK_MARKER_ENDOFSEGMENT
    ///     or STREAMSINK_MARKER_TICK types, then this call will likely affect
    ///     the behavior of the Stream Sink in some way.
    ///     If STREAMSINK_MARKER_DEFAULT is the type, then the Stream Sink's
    ///     processing of samples should not be affected.
    /// </remarks>
    HRESULT PlaceMarker(
        [in] MFSTREAMSINK_MARKER_TYPE eMarkerType,
        [in] const PROPVARIANT *pvarMarkerValue,
        [in] const PROPVARIANT *pvarContextValue );

    /// <summary>
    ///     The Flush method signals to the Stream Sink that it should
    ///     drop all data that has come into ProcessSample but has not
    ///     yet been processed.
    /// </summary>
    /// <returns>
    ///     <para>
    ///         MF_E_STREAM_REMOVED:
    ///             This Stream Sink has been removed and is no longer usable.
    ///     </para>
    /// </returns>
    /// <remarks>
    ///     None of the data waiting in the Stream Sink at the time
    ///     of Flush will get handled.
    ///     The call will return once all of the waiting data has been
    ///     successfully dropped.
    ///     Flush does not change the running state of the Stream Sink
    ///     (i.e. started, stopped, pause).
    ///     Since queued data gets dropped at the Flush call,
    ///     the result will be a glitch in the data.
    ///     Flush does not drop any pending events on the Stream Sink's
    ///     Media Event Generator.  Those events will still get delivered;
    ///     however, they will contain the error code MF_E_STREAMSINK_FLUSHED
    ///     in their status HRESULTs, which will indicate that they were
    ///     generated after a Flush.
    /// </remarks>
    HRESULT Flush();
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////


[
    object,
    uuid(86cbc910-e533-4751-8e3b-f19b5b806a03),
    local
]
interface IMFVideoSampleAllocator : IUnknown
{
    HRESULT SetDirectXManager(
        [in, unique] IUnknown* pManager);

    HRESULT UninitializeSampleAllocator();

    HRESULT InitializeSampleAllocator(
        [in] DWORD cRequestedFrames,
        [in] IMFMediaType* pMediaType);

    HRESULT AllocateSample(
        [out] IMFSample** ppSample);
};


cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
[
    object,
    uuid(A792CDBE-C374-4e89-8335-278E7B9956A4),
    local
]
interface IMFVideoSampleAllocatorNotify : IUnknown
{
    HRESULT NotifyRelease();
};

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
[
    object,
    uuid(992388B4-3372-4f67-8B6F-C84C071F4751),
    local
]
interface IMFVideoSampleAllocatorCallback : IUnknown
{
    HRESULT SetCallback(
        [in, unique] IMFVideoSampleAllocatorNotify* pNotify);

    HRESULT GetFreeSampleCount(
        [out] LONG* plSamples);
};
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")


//////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

interface IMFTopologyNode;

/// <summary>
/// IMFTopology is provided to configure topology. The application or other MF components can create
/// the topology object via MFCreateTopology and then use the interface to configure the partial topology.
/// </summary>
[
    object,
    uuid(83CF873A-F6DA-4bc8-823F-BACFD55DC433),
]
interface IMFTopology : IMFAttributes
{
    /// <summary>
    /// It returns the identifier for the whole topology.
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <param name="pID">Pointer to a variable where the identifier of the topology is returned</param>
    /// <returns>
    /// If the method succeeds, the return value is S_OK.
    /// If the method fails, the return value will be some failure code.
    /// </returns>
    HRESULT GetTopologyID( [out] TOPOID* pID );


    /// <summary>
    /// Add a node to the topology
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <param name="pNode">The pointer to the topology node to be added</param>
    /// <returns>
    /// If the method succeeds, the return value is S_OK.
    /// If the method fails, the return value will be some failure code.
    /// </returns>
    [local]
    HRESULT AddNode( [in] IMFTopologyNode* pNode );

    /// <summary>
    /// Remove a node from the topology
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <param name="pNode">the pointer to the topology node to be removed</param>
    /// <returns>
    /// If the method succeeds, the return value is S_OK.
    /// If the method fails, the return value will be some failure code.
    /// </returns>
    [local]
    HRESULT RemoveNode( [in] IMFTopologyNode* pNode );

    /// <summary>
    /// Return the count of nodes in the topology
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <param name="pwNodes">The pointer of a WORD variable where the node count will be returned.</param>
    /// <returns>
    /// If the method succeeds, the return value is S_OK.
    /// If the method fails, the return value will be some failure code.
    /// </returns>
    HRESULT GetNodeCount( [out] WORD* pwNodes );

    /// <summary>
    /// Retreives the node at position wIndex
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <param name="wIndex">the index of the node to return</param>
    /// <param name="ppNode">the node to return</param>
    /// <returns>
    /// If the method succeeds, the return value is S_OK.
    /// If the method fails, the return value will be some failure code.
    /// </returns>
    HRESULT GetNode( [in] WORD wIndex,
                     [out] IMFTopologyNode** ppNode );


    /// <summary>
    /// Removes all nodes
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <returns>
    /// If the method succeeds, the return value is S_OK.
    /// If the method fails, the return value will be some failure code.
    /// </returns>
    [local]
    HRESULT Clear( void );

    /// <summary>
    /// Makes the current topology a copy of the topology passed in as pTopology
    /// </summary>
    /// <remarks>
    /// It simplies calls IMFTopologyNode::CloneFrom on each topology node in the topology
    /// </remarks>
    /// <param name="pTopology">The topology to clone from</param>
    /// <returns>
    /// If the method succeeds, the return value is S_OK.
    /// If the method fails, the return value will be some failure code.
    /// </returns>
    HRESULT CloneFrom( [in] IMFTopology* pTopology );

    /// <summary>
    /// Finds topology node by ID
    /// </summary>
    /// <returns>
    ///     <para>
    ///         MF_E_NOT_FOUND:
    ///             No node with the specific node ID exist in the topology.
    ///     </para>
    /// </returns>
    HRESULT GetNodeByID(
                [in] TOPOID qwTopoNodeID,
                [out] IMFTopologyNode **ppNode );

    /// <summary>
    ///     Used by MF components or application to discover all the source
    ///     nodes in current topology.
    ///     This is a helper function to save caller from having to enumerate
    ///     through the whole topology.
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <param name="ppCollection">
    ///     The collection of the topology source nodes
    /// </param>
    /// <returns>
    ///     If the method succeeds, the return value is S_OK.
    ///     If the method fails, the return value will be some failure code.
    /// </returns>
    HRESULT GetSourceNodeCollection(
        [out] IMFCollection** ppCollection );

    /// <summary>
    ///     Used by MF components or application to discover all the output
    ///     nodes.
    ///     This is a helper function to save caller from having to enumerate
    ///     through the whole topology.
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <param name="ppCollection">
    ///     The collection of the topology output nodes
    /// </param>
    /// <returns>
    ///     If the method succeeds, the return value is S_OK.
    ///     If the method fails, the return value will be some failure code.
    /// </returns>
    HRESULT GetOutputNodeCollection(
        [out] IMFCollection** ppCollection );
};

//
// Topology attributes
//

// MF_TOPOLOGY_PROJECTSTART
// Data type: UINT64
// Indicates when in the timeline this topology is to start.
// This is given as an MFTIME value relative to the beginning of the entire
// sequence (i.e. global time).
// This attribute is required to be present if the Media Session has been
// configured with a nonzero value for MF_SESSION_GLOBAL_TIME.
// If this topology follows another topology in a sequence, this value must
// equal the MF_TOPOLOGY_PROJECTSTOP value of the previous topology.
cpp_quote( "EXTERN_GUID( MF_TOPOLOGY_PROJECTSTART, 0x7ed3f802, 0x86bb, 0x4b3f, 0xb7, 0xe4, 0x7c, 0xb4, 0x3a, 0xfd, 0x4b, 0x80);" )

// MF_TOPOLOGY_PROJECTSTOP
// Data type: UINT64
// Indicates when in the timeline this topology is to stop.
// This is given as an MFTIME value relative to the beginning of the entire
// sequence (i.e. global time).
// This attribute is required to be present if the Media Session has been
// configured with a nonzero value for MF_SESSION_GLOBAL_TIME.
cpp_quote( "EXTERN_GUID( MF_TOPOLOGY_PROJECTSTOP, 0x7ed3f803, 0x86bb, 0x4b3f, 0xb7, 0xe4, 0x7c, 0xb4, 0x3a, 0xfd, 0x4b, 0x80);" )

// MF_TOPOLOGY_NO_MARKIN_MARKOUT
// Data type: UINT32
// If present and set to a nonzero value, the Media Foundation pipeline will
// not attempt to trim the stream data to any particular markin or markout
// values.
// The default behavior of the Media Foundation pipeline is to trim stream
// data at some topology node; the node at which the trimming will occur
// is determined either by the Topology Loader or the application.
// See the MF_TOPONODE_MARKIN/MARKOUT_HERE attributes for more details
cpp_quote( "EXTERN_GUID( MF_TOPOLOGY_NO_MARKIN_MARKOUT, 0x7ed3f804, 0x86bb, 0x4b3f, 0xb7, 0xe4, 0x7c, 0xb4, 0x3a, 0xfd, 0x4b, 0x80);" )

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
typedef enum MFTOPOLOGY_DXVA_MODE
{
    /// <summary>
    ///     Default DXVA handling for MF v1.  The D3DManager will be set on
    ///     decoders inserted by the topoloader only.
    /// </summary>
    MFTOPOLOGY_DXVA_DEFAULT = 0,

    /// <summary>
    ///     No DXVA.  No transforms will get the D3DManager.  This allows
    ///     software processing even on DXVA-enabled machines
    /// </summary>
    MFTOPOLOGY_DXVA_NONE = 1,

    /// <summary>
    ///     Full DXVA.  The D3DManager will be set on any chain of D3D-aware
    ///     nodes upstream from a D3D-aware renderer.
    MFTOPOLOGY_DXVA_FULL = 2,

}   MFTOPOLOGY_DXVA_MODE;

// MF_TOPOLOGY_DXVA_MODE
// Data type: UINT32
// Sets the DXVA mode for the topoloader, with possible options defined in
// the MFTOPOLOGY_DXVA_MODE enumeration.
// The default behavior of the Media Foundation pipeline is to enable DXVA
// at the decoder if possible and drop optional MFTs that are not D3D-aware.
cpp_quote( "EXTERN_GUID(MF_TOPOLOGY_DXVA_MODE, 0x1e8d34f6, 0xf5ab, 0x4e23, 0xbb, 0x88, 0x87, 0x4a, 0xa3, 0xa1, 0xa7, 0x4d);" )

// MF_TOPOLOGY_STATIC_PLAYBACK_OPTIMIZATIONS
// Data type: UINT32
// Enables statically optimizing the playback pipeline using WinSAT data and user power scheme preferences.
// The default behavior of the Media Foundation pipeline is not to enable this feature.
cpp_quote( "EXTERN_GUID(MF_TOPOLOGY_STATIC_PLAYBACK_OPTIMIZATIONS, 0xb86cac42, 0x41a6, 0x4b79, 0x89, 0x7a, 0x1a, 0xb0, 0xe5, 0x2b, 0x4a, 0x1b);" )

// MF_TOPOLOGY_PLAYBACK_MAX_DIMS
// Data type: UINT64 (UINT32 width /UINT32 height)
// Specifies the output window size.  A missing attribute or a value of 0 indicates to use the desktop resolution.
//
cpp_quote( "EXTERN_GUID(MF_TOPOLOGY_PLAYBACK_MAX_DIMS,  0x5715cf19, 0x5768, 0x44aa, 0xad, 0x6e, 0x87, 0x21, 0xf1, 0xb0, 0xf9, 0xbb);" )

typedef enum MFTOPOLOGY_HARDWARE_MODE
{
    /// <summary>
    ///     Default hardware handling for MF v1.  Hardware MFTs will
    ///     not be inserted.
    /// </summary>
    MFTOPOLOGY_HWMODE_SOFTWARE_ONLY = 0,

    /// <summary>
    ///     If hardware MFTs are available, the topoloader will insert
    ///     them.  If not, the topoloader will fall back to a software
    ///     MFT to perform the task.
    /// </summary>
    MFTOPOLOGY_HWMODE_USE_HARDWARE = 1,

} MFTOPOLOGY_HARDWARE_MODE;

// MF_TOPOLOGY_HARDWARE_MODE
// Data type: UINT32
// Sets the hardware mode for the topoloader, with possible options defined in
// the MFTOPOLOGY_HARDWARE_MODE enumeration.
// The deffault behavior of the Media Foundation pipeline is to insert only
// software transforms
cpp_quote( "EXTERN_GUID(MF_TOPOLOGY_HARDWARE_MODE, 0xd2d362fd, 0x4e4f, 0x4191, 0xa5, 0x79, 0xc6, 0x18, 0xb6, 0x67, 0x6, 0xaf);" )

// MF_TOPOLOGY_PLAYBACK_FRAMERATE
// Data type: UINT32 (UINT32 numerator /UINT32 denominator)
// Specifies the monitor refresh rate
//
cpp_quote( "EXTERN_GUID(MF_TOPOLOGY_PLAYBACK_FRAMERATE, 0xc164737a, 0xc2b1, 0x4553, 0x83, 0xbb, 0x5a, 0x52, 0x60, 0x72, 0x44, 0x8f);" )

// MF_TOPOLOGY_DYNAMIC_CHANGE_NOT_ALLOWED
// Data type: BOOL (UINT32)
// Set this attribute on a topology if the topology is not allowed to change
// to re-negotiate the new media type between the nodes
// when format change happens, for example, by inserting a new video resizer or audio resampler.
// {D529950B-D484-4527-A9CD-B1909532B5B0}
cpp_quote( "EXTERN_GUID(MF_TOPOLOGY_DYNAMIC_CHANGE_NOT_ALLOWED, 0xd529950b, 0xd484, 0x4527, 0xa9, 0xcd, 0xb1, 0x90, 0x95, 0x32, 0xb5, 0xb0);" )

// MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES
// Data type: BOOL (UINT32)
// The topoloader will typically use the source's current type as-is.  To allow the topoloader to enumerate all of the
// source types from a multiple format source, set this attribute to 1.
cpp_quote( "EXTERN_GUID(MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES, 0x6248c36d, 0x5d0b, 0x4f40, 0xa0, 0xbb, 0xb0, 0xb3, 0x05, 0xf7, 0x76, 0x98);" )

// MF_TOPOLOGY_START_TIME_ON_PRESENTATION_SWITCH
// Data type: UINT64
// Indicates the start time that should be used on the topology during a presentation
// switch.
// This is given as an MFTIME value in HNS units
// {C8CC113F-7951-4548-AAD6-9ED6202E62B3}
cpp_quote( "EXTERN_GUID( MF_TOPOLOGY_START_TIME_ON_PRESENTATION_SWITCH, 0xc8cc113f, 0x7951, 0x4548, 0xaa, 0xd6, 0x9e, 0xd6, 0x20, 0x2e, 0x62, 0xb3);" )

cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

//
// Topology functions
//
cpp_quote( "STDAPI MFCreateTopology(" )
cpp_quote( "    __out IMFTopology ** ppTopo );" )


//////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////


/// <summary>
///     Topology node types
/// </summary>
typedef enum MF_TOPOLOGY_TYPE
{
    /// <member name="MF_TOPOLOGY_OUTPUT_NODE">
    ///     It represents the output topolgy node. The object contained in the output node could be a media sink object or an sink activator object.
    /// </member>
    MF_TOPOLOGY_OUTPUT_NODE,

    /// <member name="MF_TOPOLOGY_SOURCESTREAM_NODE">
    ///     It represents the source topology node. The node of this type implements IMFSourceStreamTopologyNode.
    /// </member>
    MF_TOPOLOGY_SOURCESTREAM_NODE,

    /// <member name="MF_TOPOLOGY_TRANSFORM_NODE">
    ///     It represents a media foundation transform object. The node of this type contains an IMFTransform object.
    /// </member>
    MF_TOPOLOGY_TRANSFORM_NODE,

    /// <member name="MF_TOPOLOGY_TEE_NODE">
    ///     represents a TEE node. It doesn't hold any real object. The node will be useful in scenarios like preview & archive.
    /// </member>
    MF_TOPOLOGY_TEE_NODE,

    MF_TOPOLOGY_MAX = 0xffffffff
} MF_TOPOLOGY_TYPE;

/// <summary>
/// IMFTopologyNode interface.
/// Methods for configuring topology nodes
/// </summary>
[
    object,
    uuid(83CF873A-F6DA-4bc8-823F-BACFD55DC430),
]
interface IMFTopologyNode : IMFAttributes
{
    /// <summary>
    /// Allows the application to set the object pointer.
    /// </summary>
    /// <remarks>
    ///
    /// Set the object associated with the node;
    ///
    /// For MF_TOPOLOGY_TRANSFORM_NODE node, the object needs to implement IMFTransform or IMFActivate
    /// For MF_TOPOLOGY_OUTPUT_NODE node, the object needs to implement IMFStreamSink or IMFActivate.
    ///
    /// </remarks>
    /// <param name="pObject">The pointer to the object that will be associated with the node</param>
    /// <returns>
    /// If the method succeeds, the return value is S_OK.
    /// If the method fails, the return value will be some failure code.
    /// </returns>
    HRESULT SetObject( [in] IUnknown* pObject );

    /// <summary>
    /// Allows the application to get the object pointer.
    /// </summary>
    /// <remarks>
    ///
    /// Get the object associated with the node;
    ///
    /// For MF_TOPOLOGY_TRANSFORM_NODE node, it returns the IMFTransform object. With PMP process is involved, the object we give out is a proxy of the actual object.
    /// For MF_TOPOLOGY_OUTPUT_NODE node, the object it returns the object implements IMFStreamSink or IMFActivate.
    ///
    /// </remarks>
    /// <param name="ppObject">The pointer to the object that is associated with the topology node</param>
    /// <returns>
    /// If the method succeeds, the return value is S_OK.
    /// If the method fails, the return value will be some failure code.
    /// </returns>
    HRESULT GetObject( [out] IUnknown** ppObject );


    /// <summary>
    /// Returns the node type
    /// </summary>
    /// <remarks>
    ///
    /// </remarks>
    /// <param name="pType">pointer to a variable where the node type is returned. See MF_TOPOLOGY_TYPE for a list of topolgy node types</param>
    /// <returns>
    /// If the method succeeds, the return value is S_OK.
    /// If the method fails, the return value will be some failure code.
    /// </returns>
    HRESULT GetNodeType( [out] MF_TOPOLOGY_TYPE* pType );


    /// <summary>
    /// Return the unique identifier for the node.
    /// </summary>
    /// <remarks>
    /// This ID is set when the topology node is created,
    /// and stays the same no matter what object is set in the node’s SetObject.
    /// This unique ID is used by the Topoloader find a node in the previous full topology for object reuse.
    /// </remarks>
    /// <param name="pID">pointer to a variable where TOPOID is returned</param>
    /// <returns>
    /// If the method succeeds, the return value is S_OK.
    /// If the method fails, the return value will be some failure code.
    /// </returns>
    HRESULT GetTopoNodeID( [out] TOPOID* pID );

    /// Sets the unique identifier for the node.
    /// </summary>
    HRESULT SetTopoNodeID( [in] TOPOID ullTopoID );


    /// <summary>
    /// Return the number of inputs currently available on this topology node.
    /// This might not be the same as the number of input connection of this topology node.
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <param name="pcInputs">pointer to a variable where the input count is returned</param>
    /// <returns>
    /// If the method succeeds, the return value is S_OK.
    /// If the method fails, the return value will be some failure code.
    /// </returns>
    HRESULT GetInputCount( [out] DWORD* pcInputs );


    /// <summary>
    /// Return the number of outputs currently available on this topology node.
    /// This might not be the same as the number of output connection of this topology node.
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <param name="pcOutputs">pointer to a  variable where the output count is returned</param>
    /// <returns>
    /// If the method succeeds, the return value is S_OK.
    /// If the method fails, the return value will be some failure code.
    /// </returns>
    HRESULT GetOutputCount( [out] DWORD* pcOutputs );


    /// <summary>
    /// Move to topology interface
    /// Connect this node's output to another node's input.
    /// If this output node stream is already connected, it is unlinked first.
    /// </summary>
    /// <param name="dwOutputIndex">
    ///     The 0-based index of the output to connect
    /// </param>
    /// <param name="pDownstreamNode">
    ///     The downstream node to which to connect
    /// </param>
    /// <param name="dwInputIndexOnDownstreamNode">
    ///     The 0-based index of the input to which to connect on
    ///     pDownstreamNode
    /// </param>
    /// <remarks>
    ///     Input/output index values are meant to be sequential 0-based values.
    ///     If a new value dwIndex is used, then new input/output connections
    ///     are created for that node so that connections 0 through dwIndex
    ///     will exist.
    /// </remarks>
    /// <returns>
    /// </returns>
    [local]
    HRESULT ConnectOutput( [in] DWORD dwOutputIndex,
                           [in] IMFTopologyNode* pDownstreamNode,
                           [in] DWORD dwInputIndexOnDownstreamNode );


    /// <summary>
    /// Disconnects this node's output from another node's input.
    /// </summary>
    [local]
    HRESULT DisconnectOutput( [in] DWORD dwOutputIndex );


    /// <summary>
    ///     Query what node is connected to the given input of this node.
    /// </summary>
    /// <remarks>
    ///     Source stream nodes have no inputs and will fail this call.
    /// </remarks>
    /// <param name="dwInputIndex">
    ///     The 0-based index of the input connection to query
    /// </param>
    /// <param name="ppUpstreamNode">
    ///     Pointer to a variable that will receive the IMFTopologyNode *
    ///     that is connected to this input, if any
    /// </param>
    /// <param name="pdwOutputIndexOnUpstreamNode">
    ///     Pointer to a variable that will receive the 0-based index
    ///     of the output connection on *ppUpstreamNode, if it exists.
    /// </param>
    HRESULT GetInput( [in] DWORD dwInputIndex,
                      [out] IMFTopologyNode** ppUpstreamNode,
                      [out] DWORD* pdwOutputIndexOnUpstreamNode );


    /// <summary>
    ///     Query what node is connected to the given output of this node.
    /// </summary>
    /// <remarks>
    ///     Output nodes have no outputs and will fail this call
    /// </remarks>
    /// <param name="dwOutputIndex">
    ///     The 0-based index of the output connection to query
    /// </param>
    /// <param name="ppDownstreamNode">
    ///     Pointer to a variable that will receive the IMFTopologyNode *
    ///     that is connected to this output, if any
    /// </param>
    /// <param name="pdwInputIndexOnDownstreamNode">
    ///     Pointer to a variable that will receive the 0-based index
    ///     of the input connection on *ppDownstreamNode, if it exists.
    /// </param>
    HRESULT GetOutput( [in] DWORD dwOutputIndex,
                       [out] IMFTopologyNode** ppDownstreamNode,
                       [out] DWORD* pdwInputIndexOnDownstreamNode );


    /// <summary>
    ///     Set the output preferred type
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <param name="dwOutputIndex">
    ///     0-based output index.
    /// </param>
    /// <param name="pType">
    ///     Media type to set
    /// </param>
    /// <returns>
    ///     Input/output index values are meant to be sequential 0-based values.
    ///     If a new value dwIndex is used, then new input/output connections
    ///     are created for that node so that connections 0 through dwIndex
    ///     will exist.
    /// </returns>
    [local]
    HRESULT SetOutputPrefType( [in] DWORD dwOutputIndex,
                               [in] IMFMediaType* pType );


    /// <summary>
    ///     Get the output preferred type
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <param name="dwOutputIndex">
    ///     0-based output index
    /// </param>
    /// <param name="ppType">
    ///     Pointer to IMFMediaType* where the media type is returned
    /// </param>
    /// <returns>
    ///     If the index is out of range, we will return E_INVALIDARG.
    /// </returns>
    [local] HRESULT GetOutputPrefType(
                                [in] DWORD dwOutputIndex,
                                [out, annotation("__out")] IMFMediaType** ppType );

    [call_as(GetOutputPrefType)] HRESULT RemoteGetOutputPrefType(
                                [in] DWORD dwOutputIndex,
                                [out] DWORD * pcbData,
                                [out, size_is(, *pcbData)] BYTE ** ppbData);

    /// <summary>
    ///     Set the input preferred type
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <param name="dwInputIndex">
    ///     0-based input index
    /// </param>
    /// <param name="pType">
    ///     Specifies the media type to set
    /// </param>
    /// <returns>
    /// <returns>
    ///     Input/output index values are meant to be sequential 0-based values.
    ///     If a new value dwIndex is used, then new input/output connections
    ///     are created for that node so that connections 0 through dwIndex
    ///     will exist.
    /// </returns>
    [local]
    HRESULT SetInputPrefType( [in] DWORD dwInputIndex,
                              [in] IMFMediaType* pType );


    /// <summary>
    ///     Get the input preferred type
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <param name="dwInputIndex">
    ///     0-based input index
    /// </param>
    /// <param name="ppType">
    ///     Pointer to a variable where the media type is returned
    /// </param>
    /// <returns>
    /// If the index is out of range, we will return E_INVALIDARG.
    /// </returns>
    [local]
    HRESULT GetInputPrefType( [in] DWORD dwInputIndex,
                              [out, annotation("__out")] IMFMediaType** ppType );

    [call_as(GetInputPrefType)] HRESULT RemoteGetInputPrefType(
                                [in] DWORD dwInputIndex,
                                [out] DWORD * pcbData,
                                [out, size_is(, *pcbData)] BYTE ** ppbData);


    /// Makes current node a copy of the node that is passed in as input
    /// </summary>
    /// <remarks>
    /// The two nodes will share the same topology node id and underlying object pointer
    /// </remarks>
    /// <param name="pNode">the input node to clone from</param>
    /// <returns>
    /// If the method succeeds, the return value is S_OK.
    /// If the method fails, the return value will be some failure code.
    /// </returns>
    HRESULT CloneFrom( [in] IMFTopologyNode* pNode );

};

//
// Topology node attributes
//

//
// general node attributes (0x494bbcea, 0xb031, 0x4e38, 0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc)
//

/// <summary>
///     Enumerated type to define when the transform at a transform node
///     is supposed to be flushed.
///     These are the possible values for the MF_TOPONODE_FLUSH attribute.
/// </summary>
typedef enum _MF_TOPONODE_FLUSH_MODE
{
    /// <member name="MF_TOPONODE_FLUSH_ALWAYS">
    ///     Transform is to be flushed for all types of stream changes
    ///     (e.g. seeks, new segment, etc.)
    /// </member>
    MF_TOPONODE_FLUSH_ALWAYS,

    /// <member name="MF_TOPONODE_FLUSH_SEEK">
    ///     Transform is to be flushed only when the stream is seeked
    /// </member>
    MF_TOPONODE_FLUSH_SEEK,

    /// <member name="MF_TOPONODE_FLUSH_NEVER">
    ///     Transform is never to be flushed (except when we are completely done
    ///     with it)
    /// </member>
    MF_TOPONODE_FLUSH_NEVER,

} MF_TOPONODE_FLUSH_MODE;


// MF_TOPONODE_FLUSH
// Data type: UINT32
// For transform nodes, indicates under what circumstances the transform
// will be flushed at a stream change.
// If not set, then the behavior is MF_TOPONODE_FLUSH_ALWAYS.
// Value should be one of the MF_TOPONODE_FLUSH_MODE values defined.
cpp_quote( "EXTERN_GUID( MF_TOPONODE_FLUSH, 0x494bbce8, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

/// <summary>
///     Enumerated type to define when the transform at a transform node
///     is supposed to be drained.
///     These are the possible values for the MF_TOPONODE_DRAIN attribute.
/// </summary>
typedef enum _MF_TOPONODE_DRAIN_MODE
{
    /// <member name="MF_TOPONODE_DRAIN_DEFAULT">
    ///     Default draining behavior is to be applied:
    ///         At EndOfStream: drain
    ///         At a markout: do not drain
    /// </member>
    MF_TOPONODE_DRAIN_DEFAULT,

    /// <member name="MF_TOPONODE_DRAIN_ALWAYS">
    ///     Transform is to be drained whenever a topology ends
    /// </member>
    MF_TOPONODE_DRAIN_ALWAYS,

    /// <member name="MF_TOPONODE_DRAIN_NEVER">
    ///     Transform is never to be drained
    /// </member>
    MF_TOPONODE_DRAIN_NEVER,

} MF_TOPONODE_DRAIN_MODE;


// MF_TOPONODE_DRAIN
// Data type: UINT32
// For transform nodes, indicates whether or not to drain the transform
// at the end of topologies.
// If not set, then the behavior is as described for MF_TOPONODE_DRAIN_DEFAULT.
// Value should be one of the MF_TOPONODE_DRAIN_MODE values defined.
cpp_quote( "EXTERN_GUID( MF_TOPONODE_DRAIN, 0x494bbce9, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

// MF_TOPONODE_D3DAWARE
// Data type: UINT32
// If nonzero, indicates that node is D3D aware and mediaproc should not
// use default D3D logic
cpp_quote( "EXTERN_GUID( MF_TOPONODE_D3DAWARE, 0x494bbced, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

// MF_TOPOLOGY_RESOLUTION_STATUS_FLAGS
// Data type: UINT32
// After topology resolution this value can be bitwise of MF_TOPOLOGY_RESOLUTION_STATUS_FLAGS
cpp_quote( "EXTERN_GUID( MF_TOPOLOGY_RESOLUTION_STATUS, 0x494bbcde, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

// MF_TOPONODE_ERRORCODE
// Data type: UINT32
// Stores the error code from connection failures
cpp_quote( "EXTERN_GUID( MF_TOPONODE_ERRORCODE, 0x494bbcee, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

// MF_TOPONODE_CONNECT_METHOD
// Data type: UINT32
// The value should be bitwise of MF_CONNECT_METHOD, describing the connect
// method topoloader should try to use for this node
cpp_quote( "EXTERN_GUID( MF_TOPONODE_CONNECT_METHOD, 0x494bbcf1, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

// MF_TOPONODE_LOCKED
// Data type: UINT32
// When value is nonzero, indicates that the media type should not be changed,
// since the node is in use
cpp_quote( "EXTERN_GUID( MF_TOPONODE_LOCKED, 0x494bbcf7, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

// MF_TOPONODE_WORKQUEUE_ID
// Data type: UINT32
// Work queue to use for this node
cpp_quote( "EXTERN_GUID( MF_TOPONODE_WORKQUEUE_ID, 0x494bbcf8, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

// MF_TOPONODE_WORKQUEUE_MMCSS_CLASS
// Data type: STRING
// MMCSS class to be used for the work queue serving this node
cpp_quote( "EXTERN_GUID( MF_TOPONODE_WORKQUEUE_MMCSS_CLASS, 0x494bbcf9, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

// MF_TOPONODE_DECRYPTOR
// Data type: UINT32
// If nonzero, indicates that the node's object is a decryptor
cpp_quote( "EXTERN_GUID( MF_TOPONODE_DECRYPTOR, 0x494bbcfa, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

// MF_TOPONODE_DECRYPTOR
// Data type: BLOB of UINT32
// Contains array of output indexes which should be marked as discardable
cpp_quote( "EXTERN_GUID( MF_TOPONODE_DISCARDABLE, 0x494bbcfb, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

// MF_TOPONODE_ERROR_MAJORTYPE
// Data type: GUID
// Only set when certain errors occur.
// If present, indicates the media type's major type.
// Currently, this will only be set when topology resolution fails
// due to missing codec.
cpp_quote( "EXTERN_GUID( MF_TOPONODE_ERROR_MAJORTYPE, 0x494bbcfd, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

// MF_TOPONODE_ERROR_SUBTYPE
// Data type: GUID
// Only set when certain errors occur.
// If present, indicates the media type's sub type.
// Currently, this will only be set when topology resolution fails
// due to missing codec.
cpp_quote( "EXTERN_GUID( MF_TOPONODE_ERROR_SUBTYPE, 0x494bbcfe, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

// MF_TOPONODE_WORKQUEUE_MMCSS_TASKID
// Data type: UINT32
// MMCSS TaskId to be used for the work queue serving this node
cpp_quote( "EXTERN_GUID( MF_TOPONODE_WORKQUEUE_MMCSS_TASKID, 0x494bbcff, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

// MF_TOPONODE_MARKIN_HERE
// Data type: UINT32
// If nonzero, the Media Foundation pipeline will apply markin at this
// node.
// For resolved topologies, it is recommended that exactly one node in
// every path from a source node to an output node have this attribute
// set to a nonzero value.
// If this attribute is not present for some path, then markin will
// not occur at all on that path.
// Media Foundation's Topology Loader handles setting this attribute at
// the appropriate node.
// Note that Media Foundation does not support doing markin and markout
// at different nodes
cpp_quote( "EXTERN_GUID( MF_TOPONODE_MARKIN_HERE, 0x494bbd00, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

// MF_TOPONODE_MARKOUT_HERE
// Data type: UINT32
// If nonzero, the Media Foundation pipeline will apply markin at this
// node.
// For resolved topologies, it is recommended that exactly one node in
// every path from a source node to an output node have this attribute
// set to a nonzero value.
// If this attribute is not present for some path, then markout will
// not occur at all on that path.
// Media Foundation's Topology Loader handles setting this attribute at
// the appropriate node.
// Note that Media Foundation does not support doing markin and markout
// at different nodes
cpp_quote( "EXTERN_GUID( MF_TOPONODE_MARKOUT_HERE, 0x494bbd01, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

// MF_TOPONODE_DECODER
// Data type: UINT32
// If nonzero, indicates that the node's object is a decoder
cpp_quote( "EXTERN_GUID( MF_TOPONODE_DECODER, 0x494bbd02, 0xb031,  0x4e38,  0x97, 0xc4, 0xd5, 0x42, 0x2d, 0xd6, 0x18, 0xdc);" )

//
// source node attributes (0x835c58ea, 0xe075, 0x4bc7, 0xbc, 0xba, 0x4d, 0xe0, 0x00, 0xdf, 0x9a, 0xe6)
//

// MF_TOPONODE_MEDIASTART
// Data type: UINT64
// Indicates the start time for this segment relative to the original media.
// If not set, assumed to be whatever the current position is in that media.
cpp_quote( "EXTERN_GUID( MF_TOPONODE_MEDIASTART, 0x835c58ea, 0xe075, 0x4bc7, 0xbc, 0xba, 0x4d, 0xe0, 0x00, 0xdf, 0x9a, 0xe6);" )

// MF_TOPONODE_MEDIASTOP
// Data type: UINT64
// Indicates the stop time for this segment relative to the original media.
// If not set, segment will include the rest of this media
cpp_quote( "EXTERN_GUID( MF_TOPONODE_MEDIASTOP, 0x835c58eb, 0xe075, 0x4bc7, 0xbc, 0xba, 0x4d, 0xe0, 0x00, 0xdf, 0x9a, 0xe6);" )

// MF_TOPONODE_SOURCE
// Data type: IUNKNOWN
// Pointer to the IMFMediaSource associated with this node
cpp_quote( "EXTERN_GUID( MF_TOPONODE_SOURCE, 0x835c58ec, 0xe075, 0x4bc7, 0xbc, 0xba, 0x4d, 0xe0, 0x00, 0xdf, 0x9a, 0xe6);" )

// MF_TOPONODE_PRESENTATION_DESCRIPTOR
// Data type: IUNKNOWN
// Pointer to the IMFPresentationDescriptor for the Media Source
// associated with this node
cpp_quote( "EXTERN_GUID( MF_TOPONODE_PRESENTATION_DESCRIPTOR, 0x835c58ed, 0xe075, 0x4bc7, 0xbc, 0xba, 0x4d, 0xe0, 0x00, 0xdf, 0x9a, 0xe6);" )

// MF_TOPONODE_STREAM_DESCRIPTOR
// Data type: IUNKNOWN
// Pointer to the IMFStreamDescriptor from the Presentation Desciptor of
// the Media Source associated with this node
cpp_quote( "EXTERN_GUID( MF_TOPONODE_STREAM_DESCRIPTOR, 0x835c58ee, 0xe075, 0x4bc7, 0xbc, 0xba, 0x4d, 0xe0, 0x00, 0xdf, 0x9a, 0xe6);" )

// MF_TOPONODE_SEQUENCE_ELEMENTID
// Data type: UINT32
// Media Sources that provide topologies should set this on source nodes
// to indicate which element this topology belongs to.
// Two topologies that have the same value for this attribute on their
// source nodes are really the "same" segment (i.e. time will be continuous
// on all nodes between them).
// In the MF Sequencer Source, this corresponds to the MFSequencerElementId
// associated with the topology.
cpp_quote( "EXTERN_GUID( MF_TOPONODE_SEQUENCE_ELEMENTID, 0x835c58ef, 0xe075, 0x4bc7, 0xbc, 0xba, 0x4d, 0xe0, 0x00, 0xdf, 0x9a, 0xe6);" )

//
// transform node attributes (0x88DCC0C9, 0x293E, 0x4e8b, 0x9A, 0xEB, 0x0A, 0xD6, 0x4C, 0xC0, 0x16, 0xB0)
//

// MF_TOPONODE_TRANSFORM_OBJECTID
// Data type: GUID
// CLSID of the transform for this node
cpp_quote( "EXTERN_GUID( MF_TOPONODE_TRANSFORM_OBJECTID, 0x88dcc0c9, 0x293e, 0x4e8b, 0x9a, 0xeb, 0xa, 0xd6, 0x4c, 0xc0, 0x16, 0xb0);" )

//
// output node attributes (0x14932f9b, 0x9087, 0x4bb4, 0x84, 0x12, 0x51, 0x67, 0x14, 0x5c, 0xbe, 0x04)
//

// MF_TOPONODE_STREAMID
// Data type: UINT32
// Indicates Stream Sink ID of the Stream Sink associated with this node
cpp_quote( "EXTERN_GUID( MF_TOPONODE_STREAMID, 0x14932f9b, 0x9087, 0x4bb4, 0x84, 0x12, 0x51, 0x67, 0x14, 0x5c, 0xbe, 0x04);" )

// MF_TOPONODE_NOSHUTDOWN_ON_REMOVE
// Data type: UINT32
// If nonzero, indicates that the Media Session should not shut down the
// Media Sink associated with this node when the Media Sink no longer appears
// in the topology.  By default, the Media Session will shut this sink down.
cpp_quote( "EXTERN_GUID( MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, 0x14932f9c, 0x9087, 0x4bb4, 0x84, 0x12, 0x51, 0x67, 0x14, 0x5c, 0xbe, 0x04);" )

// MF_TOPONODE_RATELESS
// Data type: UINT32
// If nonzero, indicates that the Media Sink associated with this node is
// rateless.  In this case, the Media Sink will be treated as a rateless sink,
// regardless of whether or not it sets the MEDIASINK_RATELESS characteristic
// If not set, Media Sink is assumed not to be rateless.
cpp_quote( "EXTERN_GUID( MF_TOPONODE_RATELESS, 0x14932f9d, 0x9087, 0x4bb4, 0x84, 0x12, 0x51, 0x67, 0x14, 0x5c, 0xbe, 0x04);" )

// MF_TOPONODE_DISABLE_PREROLL
// Data type: UINT32
// If nonzero, indicates that this output should not be prerolled, regardless
// of whether the associated Media Sink supports prerolling.
cpp_quote( "EXTERN_GUID( MF_TOPONODE_DISABLE_PREROLL, 0x14932f9e, 0x9087, 0x4bb4, 0x84, 0x12, 0x51, 0x67, 0x14, 0x5c, 0xbe, 0x04);" )

//
// tee node attributes (0x6304ef99, 0x16b2, 0x4ebe, 0x9d, 0x67, 0xe4, 0xc5, 0x39, 0xb3, 0xa2, 0x59)
//

// MF_TOPONODE_PRIMARYOUTPUT
// Data type: UINT32
// 0-based output connection index.  Indicates which output is the "primary
// output", which indicates which of the output streams the pipeline
// should wait to get a request on before it can process the request
// from the remaining outputs.
cpp_quote( "EXTERN_GUID( MF_TOPONODE_PRIMARYOUTPUT, 0x6304ef99, 0x16b2, 0x4ebe, 0x9d, 0x67, 0xe4, 0xc5, 0x39, 0xb3, 0xa2, 0x59);" )


//
// Topology node functions
//

cpp_quote( "STDAPI MFCreateTopologyNode(" )
cpp_quote( "    MF_TOPOLOGY_TYPE NodeType," )
cpp_quote( "    __out IMFTopologyNode ** ppNode );" )

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
/// <summary>
/// Gets the current media type set on a given input or output on the given topology node
/// </summary>
/// <param name="pNode">the input node to get the type from</param>
/// <param name="dwStreamIndex">the stream index of the stream to get the type from</param>
/// <param name="fOutput">TRUE to get an output stream type; FALSE for an input stream</param>
/// <param name="ppType">receives the media type from the node</param>
/// <returns>
/// If the method succeeds, the return value is S_OK.
/// If the method fails, the return value will be some failure code.
/// </returns>
cpp_quote( "STDAPI MFGetTopoNodeCurrentType(" )
cpp_quote( "    IMFTopologyNode* pNode," )
cpp_quote( "    DWORD dwStreamIndex," )
cpp_quote( "    BOOL fOutput," )
cpp_quote( "    __deref_out IMFMediaType** ppType);" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

//////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(fa993888-4383-415a-a930-dd472a8cf6f7)
]
/// <summary>
///     Queries an object for a specified service interface.
///     A service is an interface that is exposed by one object but might be
///     implemented by another object. The GetService method is equivalent
///     to QueryInterface, with the following difference: when QueryInterface
///     retrieves a pointer to an interface, it is guaranteed that you can query
///     the returned interface and get back the original interface. The
///     GetService method does not make this guarantee, because the retrieved
///     interface might be implemented by a separate object.
/// </summary>
interface IMFGetService : IUnknown
{
    /// <summary>
    ///     Retrieves a service interface.
    /// </summary>
    /// <param name="guidService">
    ///     The service identifier (SID) of the service.
    /// </param>
    /// <param name="riid">
    ///     The interface identifier (IID) of the interface being requested.
    /// </param>
    /// <param name="ppvObject">
    ///     Receives the interface pointer. The caller must release the interface.
    /// </param>
    ///  <returns>
    ///     If the method succeeds it returns S_OK. If the component does not
    ///     support the service it returns MF_E_UNSUPPORTED_SERVICE.
    ///  </returns>
    ///  <remarks>
    ///     Objects which implement IMFGetService should check to see that the
    ///     REFIID is requested for the right service GUID.
    ///  </remarks>
    HRESULT GetService(
        [in] REFGUID guidService,
        [in] REFIID riid,
        [out, iid_is(riid)] LPVOID* ppvObject
        );

}

cpp_quote( "STDAPI MFGetService(" )
cpp_quote( "    IUnknown* punkObject," )
cpp_quote( "    REFGUID guidService," )
cpp_quote( "    REFIID riid," )
cpp_quote( "    __out LPVOID* ppvObject" )
cpp_quote( "    );" )


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

/// <summary>
///     MFTIME is the type used to describe time in Media Foundation.
///     It is in 100ns units.
/// </summary>
typedef LONGLONG  MFTIME;

/// <summary>
///     Bit flags for the clock characteristics returned by
///     IMFClock::GetClockCharacteristics
/// </summary>
typedef enum _MFCLOCK_CHARACTERISTICS_FLAGS
{
    /// <member name="MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ">
    ///     If set, clock times given in IMFClock::GetCorrelatedTime
    ///     are in standard MFTIME (100ns) units.
    ///     The dwClockFrequency member of the MFCLOCK_PROPERTIES structure
    ///     returned from IMFClock::GetProperties must be set to
    ///     MFCLOCK_FREQUENCY_HNS in this case.
    /// </member>
    MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ    = 0x2,

    /// <member name="MFCLOCK_CHARACTERISTICS_FLAG_ALWAYS_RUNNING">
    ///     If set, the clock will always be in the MFCLOCK_STATE_RUNNING
    ///     state.
    /// </member>
    MFCLOCK_CHARACTERISTICS_FLAG_ALWAYS_RUNNING     = 0x4,

    /// <member name="MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK">
    ///     If set, then this clock is running according to system time.
    ///     Therefore, the clock time returned from
    ///     IMFClock::GetCorrelation can be used without any further
    ///     calculations.
    /// </member>
    MFCLOCK_CHARACTERISTICS_FLAG_IS_SYSTEM_CLOCK    = 0x8

}   MFCLOCK_CHARACTERISTICS_FLAGS;

/// <summary>
///     Enumerated type describing the state of a clock.
///     Obtained from IMFClock::GetState.
/// </summary>
typedef enum _MFCLOCK_STATE
{
    /// <member name="MFCLOCK_STATE_INVALID">
    ///     Clock is currently invalid.
    ///     If the clock uses an underlying device, this could mean that
    ///     there is no device.
    /// </member>
    MFCLOCK_STATE_INVALID,

    /// <member name="MFCLOCK_STATE_RUNNING">
    ///     Clock is currently running (started).
    /// </member>
    MFCLOCK_STATE_RUNNING,

    /// <member name="MFCLOCK_STATE_STOPPED">
    ///     Clock is currently stopped and reporting a time of 0.
    /// </member>
    MFCLOCK_STATE_STOPPED,

    /// <member name="MFCLOCK_STATE_PAUSED">
    ///     Clock is currently paused, and the time it reports is frozen.
    /// </member>
    MFCLOCK_STATE_PAUSED

}   MFCLOCK_STATE;

/// <summary>
///     Bit flags for the dwClockFlags member of MFCLOCK_PROPERTIES
/// </summary>
typedef enum _MFCLOCK_RELATIONAL_FLAGS
{
    /// <member name="MFCLOCK_RELATIONAL_FLAG_JITTER_NEVER_AHEAD">
    ///     If set, this bit indicates that jitter values are always negative.
    ///     That is, the clock time returned by IMFClock::GetCorrelatedTime()
    ///     will never jitter to times ahead; only to times behind.
    /// </member>
    MFCLOCK_RELATIONAL_FLAG_JITTER_NEVER_AHEAD = 0x1

}   MFCLOCK_RELATIONAL_FLAGS;

/// <summary>
///     Properties structure describing how the clock retrieves and reports
///     time.
///     Obtained from IMFClock::GetProperties
/// </summary>
typedef struct _MFCLOCK_PROPERTIES
{
    /// <member name="qwCorrelationRate">
    ///     The nominal rate at which the clock is correlated to MF system time.
    ///     A value of 0 means that the correlation is made during the
    ///     IMFClock::GetCorrelatedTime call.
    /// </member>
    unsigned __int64 qwCorrelationRate;

    /// <member name="guidClockId">
    ///     Uniquely identifies the clocking device (source crystal).
    ///     If two clocks have the same guidClockId, then they are based
    ///     on the same clocking device.
    ///     A value of GUID_NULL indicates that this clock is not similar
    ///     to any other clock.
    /// </member>
    GUID        guidClockId;

    /// <member name="dwClockFlags">
    ///     Bit flags describing this clock.
    ///     See enumerated type MFCLOCK_RELATIONAL_FLAGS.
    /// </member>
    DWORD       dwClockFlags;

    /// <member name="qwClockFrequency">
    ///     Fixed frequency in Hz at which the clock operates.
    ///     A value of MFCLOCK_FREQUENCY_HNS means that the clock has
    ///     a frequency of 10MHz, which is standard MFTIME units (100ns).
    ///     If the bit flag MFCLOCK_CHARACTERISTICS_FLAG_FREQUENCY_10MHZ
    ///     is set in the characteristics returned by
    ///     IMFClock::GetClockCharacteristics, then this value must be equal
    ///     to MFCLOCK_FREQUENCY_HNS.
    /// </member>
    unsigned __int64 qwClockFrequency;

    /// <member name="dwClockTolerance">
    ///     Amount of inaccuracy in parts-per-billion that may be present
    ///     on the clock.
    ///     Implementations that do not know the clock tolerance should
    ///     set this value to MFCLOCK_TOLERANCE_UNKNOWN, which is the
    ///     value typical in crystal specifications.
    /// </member>
    DWORD       dwClockTolerance;

    /// <member name="dwClockJitter">
    ///     Amount of jitter in 100ns units that may be present on this
    ///     clock due to sampling (this does not include the inaccuracies
    ///     accounted for in dwClockTolerance).
    ///     For single-device clocks, this is the inverse of frequency.
    ///     For frequencies greater than or equal to 10MHz on single-device
    ///     clocks, this value should be 1.
    ///     When this clock belongs to a capture device that is not directly
    ///     timestamping the incoming data, the correlation cannot be made
    ///     until the driver's interrupt service routine runs.
    ///     If this is the case,
    ///     then these values should be included in the expected jitter:
    ///     <para>
    ///         MFCLOCK_JITTER_ISR:
    ///             Jitter due to timestamping during
    ///             the device driver's interrupt service routine.
    ///     </para>
    ///     <para>
    ///         MFCLOCK_JITTER_DPC:
    ///             Jitter due to timestampind during
    ///             the device driver's deferred procedure call processing.
    ///     </para>
    ///     <para>
    ///         MFCLOCK_JITTER_PASSIVE:
    ///             Jitter due to dropping to
    ///             passive level (normal thread execution) before timestamping.
    ///     </para>
    /// </member>
    DWORD       dwClockJitter;

}   MFCLOCK_PROPERTIES;

/// <summary>
///     Constants used in MFCLOCK_PROPERTIES fields.
///     See CMFCLOCK_PROPERTIES comments.
/// </summary>
cpp_quote( "#define MFCLOCK_FREQUENCY_HNS       10000000" )
cpp_quote( "#define MFCLOCK_TOLERANCE_UNKNOWN   50000" )
cpp_quote( "#define MFCLOCK_JITTER_ISR          1000" )
cpp_quote( "#define MFCLOCK_JITTER_DPC          4000" )
cpp_quote( "#define MFCLOCK_JITTER_PASSIVE      10000" )


[
    object,
    uuid(2eb1e945-18b8-4139-9b1a-d5d584818530),
]
/// <summary>
///     IMFClock is the basic interface for any object providing a time.
/// </summary>
interface IMFClock : IUnknown
{
    /// <summary>
    ///     Gets the characteristics of this clock.
    /// </summary>
    /// <param name="pdwCharacteristics">
    ///     Pointer to a variable that will receive the
    ///     MFCLOCK_CHARACTERISTICS_FLAGS bit flags.
    /// </param>
    HRESULT GetClockCharacteristics(
        [out] DWORD *pdwCharacteristics );

    /// <summary>
    ///     Gets the last known clock time, as correlated to MF system time
    ///     (QueryPerformanceCounter time).
    /// </summary>
    /// <param name="dwReserved">
    ///     Reserved: Must be 0.
    /// </param>
    /// <param name="pllClockTime">
    ///     Pointer to a variable that will be set to the clock time,
    ///     in clock's frequency units, at the last
    ///     correlation to system time.
    /// </param>
    /// <param name="phnsSystemTime">
    ///     Pointer to a variable that will be set to the system time
    ///     in 100ns units at which the clock was at *pllClockTime.
    /// </param>
    /// <remarks>
    ///     Clock providers should make this correlation as accurate
    ///     as possible by raising the driver to the highest IRQL
    ///     level to sample device time and system time.
    /// </remarks>
    HRESULT GetCorrelatedTime(
        [in] DWORD dwReserved,
        [out] LONGLONG *pllClockTime,
        [out] MFTIME *phnsSystemTime );

    /// <summary>
    ///     IMFClock::GetContinuityKey is not used in this version of
    ///     Media Foundation.  Clocks must return 0 in *pdwContinuityKey.
    /// </summary>
    HRESULT GetContinuityKey(
        [out] DWORD *pdwContinuityKey );

    /// <summary>
    ///     Gets the current state of the clock.
    /// </summary>
    /// <param name="dwReserved">
    ///     Reserved: Must be 0.
    /// </param>
    /// <param name="peClockState">
    ///     Pointer to a variable that will receive the current state
    ///     of the clock.
    /// </param>
    HRESULT GetState(
        [in] DWORD dwReserved,
        [out] MFCLOCK_STATE *peClockState );

    /// <summary>
    ///     Retrieves advanced properties of the clock.
    /// </summary>
    /// <param name="pClockProperties">
    ///     Pointer to an MFCLOCK_PROPERTIES that will be filled in
    ///     with the advanced properties of this clock.
    /// </param>
    /// <remark>
    ///     Please see comments for MFCLOCK_PROPERTIES structure to see
    ///     what information can be obtained through the properties.
    /// </remark>
    HRESULT GetProperties(
        [out] MFCLOCK_PROPERTIES *pClockProperties );
};

/// <summary>
///     Retrieves the current MF system time
/// </summary>
/// <returns>
///     Return value is the current MF system time in 100ns units
/// </returns>
cpp_quote( "STDAPI_(MFTIME) " )
cpp_quote( "MFGetSystemTime(" )
cpp_quote( "    );" )

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////


/// <summary>
///     PRESENTATION_CURRENT_POSITION generally means "now".
///     For example, when used as the clock time in a Start call, it means to
///     start at the current position without seeking.
/// </summary>
cpp_quote( "#define PRESENTATION_CURRENT_POSITION   0x7fffffffffffffff" )

interface IMFClockStateSink;
interface IMFPresentationTimeSource;

[
    object,
    uuid(868CE85C-8EA9-4f55-AB82-B009A910A805),
]
/// <summary>
///     IMFPresentationClock is implemented by the Presentation Clock.
///     The caller can specify the Presentation Time Source from which
///     this clock is to read time.
///     There are also methods to control the state of the clock, as
///     well as methods for subscribing and unsubscribing to clock state
///     change notifications.
///     Timers can be set on the Presentation Clock by QIing for
///     IMFTimer.
///     The rate of the Presentation Clock can be set and queried by
///     QIing the Presentation Clock for IMFRateControl.
/// </summary>
interface IMFPresentationClock : IMFClock
{
    /// <summary>
    ///     Sets the Presentation Time Source from which this Presentation
    ///     Clock will read its time.
    /// </summary>
    /// <param name="pTimeSource">
    ///     Pointer to a Presentation Time Source to be used by this
    ///     Presentation Clock.
    /// </param>
    /// <remarks>
    ///     <para>
    ///         pTimeSource must QI for IMFClock.  All time queries on the
    ///         Presentation Clock are forwarded to the Presentation Time
    ///         Source.
    ///     </para>
    ///     <para>
    ///         A Presentation Time Source must be set in order for
    ///         the Presentation Clock to operate.
    ///     </para>
    ///     <para>
    ///         Note that the Presentation Clock will subscribe pTimeSource
    ///         as a Clock State Sink so that pTimeSource will receive
    ///         state change notifications.  The Presentation Time Source
    ///         will receive these notifications synchronously as the clock
    ///         state change is happening; this is not necessarily true
    ///         for other Clock State Sinks.
    ///     </para>
    /// </remarks>
    HRESULT SetTimeSource(
        [in] IMFPresentationTimeSource* pTimeSource
        );

    /// <summary>
    ///     Gets the Presentation Time Source currently in use by this
    ///     Presentation Clock
    /// </summary>
    /// <param name="ppTimeSource>
    ///     Pointer to a variable that will receive a pointer to the current
    ///     Presentation Time Source
    /// </param>
    HRESULT GetTimeSource(
        [out] IMFPresentationTimeSource** ppTimeSource
        );

/// <summary>
///     GetTime is a helper that retrieves the latest clock time
///     in 100ns units for Presentation Clocks with simple Presentation
///     Time Sources.
/// </summary>
/// <param name="phnsClockTime">
///     Pointer to a variable that will receive the latest clock time
/// </param>
/// <returns>
///     <para>
///         MF_E_CLOCK_NOT_SIMPLE:
///             MFGetClockTime cannot read the time on the clock because
///             the clock uses more advanced features.  See remarks
///             for what kinds of clocks are handled by GetTime.
///             If this error code is returned, then time should be obtained
///             via IMFClock::GetCorrelatedTime() instead.
///     </para>
/// </returns>
/// <remarks>
///     <para>
///         GetTime handles only "simple" clocks.  That is, clocks
///         must have a frequency of 10MHz.  For more advanced clocks,
///         IMFClock::GetCorrelatedTime() should be used.
///     </para>
///     <para>
///         GetTime makes no attempt to smooth out jitter or
///         otherwise account for any inaccuracies in the clock time.
///         It simply estimates the current clock time based on the system
///         time in the latest correlation (as given by
///         IMFClock::GetCorrelatedTime) and the system time now.
///         Callers wishing to get better information about the clock time
///         should use IMFClock::GetCorrelatedTime along with the properties
///         returned by IMFClock::GetProperties.
///     </para>
/// </remarks>
    HRESULT GetTime(
        [out] MFTIME *phnsClockTime
        );

    /// <summary>
    ///     Subscribes an object to receive clock state change notifications
    /// </summary>
    /// <param name="pStateSink">
    ///     Pointer to the Clock State Sink to be subscribed.
    /// </param>
    /// <remarks>
    ///     <para>
    ///         The Clock State Sink will be asynchronously notified of
    ///         the current state of the Presentation Clock after it is
    ///         added.
    ///     </para>
    ///     <para>
    ///         See comments on IMFClockStateSink::OnClockStart for
    ///         more info on how Clock State Sinks are notified of state
    ///         changes.
    ///     </para>
    /// </remarks>
    HRESULT AddClockStateSink(
        [in] IMFClockStateSink* pStateSink
        );

    /// <summary>
    ///     Unsubscribes an object from receiving clock state change
    ///     notifications.
    /// </summary>
    /// <param name="pStateSink">
    ///     Pointer to the Clock State Sink to be unsubscribed.
    /// </param>
    HRESULT RemoveClockStateSink(
        [in] IMFClockStateSink* pStateSink
        );

    /// <summary>
    ///     Starts the Presentation Clock so that it starts running from the
    ///     specified clock offset.
    /// </summary>
    /// <param name="llClockStartOffset">
    ///     Clock time from which the clock should start running.
    ///     ullClockStartOffset is given in the units of the clock's frequency.
    ///     Please see comments on the MF_CLOCK_PROPERTIES structure returned
    ///     from IMFClock::GetProperties.
    ///     A value of PRESENTATION_CURRENT_POSITION indicates that the
    ///     clock should start running from wherever it is right now;
    ///     this value is used to resume from the paused state.
    /// </param>
    /// <remarks>
    ///     <para>
    ///         The Presentation Clock will synchronously call OnClockStart on
    ///         the Presentation Time Source and will proceed with the state
    ///         change only if that call succeeds.  All other subscribed Clock
    ///         State Sinks will be notified of the state change asynchronously.
    ///     </para>
    /// </remarks>
    HRESULT Start(
        [in] LONGLONG llClockStartOffset
        );

    /// <summary>
    ///     Stops the Presentation Clock.
    /// </summary>
    /// <remarks>
    ///     <para>
    ///         The Presentation Clock will synchronously call OnClockStop on
    ///         the Presentation Time Source and will proceed with the state
    ///         change only if that call succeeds.  All other subscribed Clock
    ///         State Sinks will be notified of the state change asynchronously.
    ///     </para>
    /// </remarks>
    HRESULT Stop(
        );

    /// <summary>
    ///     Pauses the Presentation Clock.
    /// </summary>
    /// <remarks>
    ///     <para>
    ///         The Presentation Clock will synchronously call OnClockPause on
    ///         the Presentation Time Source and will proceed with the state
    ///         change only if that call succeeds.  All other subscribed Clock
    ///         State Sinks will be notified of the state change asynchronously.
    ///     </para>
    /// </remarks>
    HRESULT Pause(
        );

}

/// <summary>
///     Creates a Presentation Clock object
/// </summary>
/// <param name="ppPresentationClock">
///     Pointer to a variable that will receive a pointer to the Presentation
///     Clock
/// </param>
/// <remarks>
///     *ppPresentationClock must be given a valid Presentation Time Source
///     before it will work.
/// </remarks>
cpp_quote( "STDAPI MFCreatePresentationClock(" )
cpp_quote( "    __out IMFPresentationClock** ppPresentationClock" )
cpp_quote( "    );" )

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(7FF12CCE-F76F-41c2-863B-1666C8E5E139),
]
/// <summary>
///     IMFPresentationTimeSource is the interface that an object implements
///     in order to be able to provide presentation time to the Presentation
///     Clock.  Objects implementing IMFPresentationTimeSource must QI
///     for IMFClock and IMFClockStateSink.
/// </summary>
interface IMFPresentationTimeSource : IMFClock
{
    /// <summary>
    ///     GetUnderlyingClock gets the always-running clock that drives
    ///     this Presentation Time Source
    /// </summary>
    /// <param name="ppClock">
    ///     Pointer to a variable that will receive a pointer to the
    ///     underlying clock for this Presentation Time Source
    /// </param>
    /// <returns>
    ///     <para>
    ///         MF_E_NO_CLOCK:
    ///             There is no underlying clock
    ///     </para>
    /// </returns>
    /// <remarks>
    ///     <para>
    ///         The underlying clock is useful to components in the
    ///         pipeline that want to make decisions based on the speed
    ///         at which the Presentation Clock will run, and they want
    ///         to observe that speed even when the Presentation Clock is
    ///         stopped or paused.  (For example, some Media Sources
    ///         implement IMFPresentationClockClient for this purpose).
    ///     </para>
    ///     <para>
    ///         The underlying clock is required to be always running,
    ///         regardless of the state (started/stopped/paused) of the
    ///         Presentation Time Source.  That is, the underlying clock
    ///         must set the bit MFCLOCK_CHARACTERISTICS_FLAG_ALWAYS_RUNNING
    ///         in IMFClock::GetClockCharacteristics, even though this
    ///         Presentation Time Source will not set that bit.
    ///     </para>
    ///     <para>
    ///         Returning an underlying clock is optional.  If there is
    ///         no such clock, implementations will return MF_E_NO_CLOCK.
    ///     </para>
    /// </remarks>
    HRESULT GetUnderlyingClock(
        [out] IMFClock** ppClock
        );
}

/// <summary>
///     Creates a Presentation Time Source that returns system time
/// </summary>
/// <param name="ppSystemTimeSource">
///     Pointer to a variable that will receive a pointer to a
///     Presentation Time Source based on system time
/// </param>
cpp_quote( "STDAPI" )
cpp_quote( "MFCreateSystemTimeSource(" )
cpp_quote( "    __out IMFPresentationTimeSource** ppSystemTimeSource" )
cpp_quote( "    );" )



///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(F6696E82-74F7-4f3d-A178-8A5E09C3659F),
]
/// <summary>
///     The IMFClockStateSink interface is implemented by any object
///     that wishes to subscribe to clock state notifications from a
///     Presentation Clock.
///     In particular, all Presentation Time Sources are Clock State Sinks.
/// </summary>
interface IMFClockStateSink : IUnknown
{
    /// <summary>
    ///     OnClockStart is called when the Presentation Clock has been started
    /// </summary>
    /// <param name="hnsSystemTime">
    ///     The MF system time, given in 100ns units, at which the clock
    ///     started running.
    /// </param>
    /// <param name="llClockStartOffset">
    ///     Clock time, given in the clock's frequency units, from which
    ///     the clock started running.
    /// </param>
    /// <remarks>
    ///     <para>
    ///         If the Clock State Sink is the Presentation Time Source
    ///         currently being used by the Presentation Clock, then
    ///         the Presentation Clock makes these state change notification
    ///         calls synchronously from the IMFPresentationClock::Start,
    ///         Stop, and Pause calls.  In this case, any failure code
    ///         returned from this method will result in an error being
    ///         returned to the caller of the Presentation Clock, and the state
    ///         change will not take place.
    ///     </para>
    ///     <para>
    ///         If the Clock State Sink is not the Presentation Time Source
    ///         currently in use, then these state change notification calls
    ///         are made asynchronously after the fact.  Error codes returned
    ///         are ignored.
    ///     </para>
    ///     <para>
    ///         hnsSystemTime should be in the very recent past.
    ///     </para>
    /// </remarks>
    HRESULT OnClockStart(
        [in] MFTIME hnsSystemTime,
        [in] LONGLONG llClockStartOffset
        );

    /// <summary>
    ///     OnClockStop is called when the Presentation Clock has been stopped
    /// </summary>
    /// <param name="hnsSystemTime">
    ///     The MF system time, given in 100ns units, at which the clock
    ///    stopped.
    /// </param>
    /// <remarks>
    ///     <para>
    ///         If the Clock State Sink is the Presentation Time Source
    ///         currently being used by the Presentation Clock, then
    ///         the Presentation Clock makes these state change notification
    ///         calls synchronously from the IMFPresentationClock::Start,
    ///         Stop, and Pause calls.  In this case, any failure code
    ///         returned from this method will result in an error being
    ///         returned to the caller of the Presentation Clock, and the state
    ///         change will not take place.
    ///     </para>
    ///     <para>
    ///         If the Clock State Sink is not the Presentation Time Source
    ///         currently in use, then these state change notification calls
    ///         are made asynchronously after the fact.  Error codes returned
    ///         are ignored.
    ///     </para>
    ///     <para>
    ///         hnsSystemTime should be in the very recent past.
    ///     </para>
    /// </remarks>
    HRESULT OnClockStop(
        [in] MFTIME hnsSystemTime
        );

    /// <summary>
    ///     OnClockPause is called when the Presentation Clock has been paused
    /// </summary>
    /// <param name="hnsSystemTime">
    ///     The MF system time, given in 100ns units, at which the clock
    ///    paused.
    /// </param>
    /// <remarks>
    ///     <para>
    ///         If the Clock State Sink is the Presentation Time Source
    ///         currently being used by the Presentation Clock, then
    ///         the Presentation Clock makes these state change notification
    ///         calls synchronously from the IMFPresentationClock::Start,
    ///         Stop, and Pause calls.  In this case, any failure code
    ///         returned from this method will result in an error being
    ///         returned to the caller of the Presentation Clock, and the state
    ///         change will not take place.
    ///     </para>
    ///     <para>
    ///         If the Clock State Sink is not the Presentation Time Source
    ///         currently in use, then these state change notification calls
    ///         are made asynchronously after the fact.  Error codes returned
    ///         are ignored.
    ///     </para>
    ///     <para>
    ///         hnsSystemTime should be in the very recent past.
    ///     </para>
    /// </remarks>
    HRESULT OnClockPause(
        [in] MFTIME hnsSystemTime
        );

    /// <summary>
    ///     OnClockRestart is called when the Presentation Clock has been
    ///     restarted from the paused state.
    /// </summary>
    /// <param name="hnsSystemTime">
    ///     The MF system time, given in 100ns units, at which the clock
    ///     restarted.
    /// </param>
    /// <remarks>
    ///     <para>
    ///         If the Clock State Sink is the Presentation Time Source
    ///         currently being used by the Presentation Clock, then
    ///         the Presentation Clock makes these state change notification
    ///         calls synchronously from the IMFPresentationClock::Start,
    ///         Stop, and Pause calls.  In this case, any failure code
    ///         returned from this method will result in an error being
    ///         returned to the caller of the Presentation Clock, and the state
    ///         change will not take place.
    ///     </para>
    ///     <para>
    ///         If the Clock State Sink is not the Presentation Time Source
    ///         currently in use, then these state change notification calls
    ///         are made asynchronously after the fact.  Error codes returned
    ///         are ignored.
    ///     </para>
    ///     <para>
    ///         hnsSystemTime should be in the very recent past.
    ///     </para>
    /// </remarks>
    HRESULT OnClockRestart(
        [in] MFTIME hnsSystemTime
        );


    /// <summary>
    ///     OnClockSetRate is called when the rate has been changed on the
    ///     PresentationClock.
    /// </summary>
    /// <param name="hnsSystemTime">
    ///     The MF system time, given in 100ns units, at which the clock
    ///     changed rates.
    /// </param>
    /// <param name="flRate>
    ///     The new rate
    /// </param>
    /// <remarks>
    ///     <para>
    ///         If the Clock State Sink is the Presentation Time Source
    ///         currently being used by the Presentation Clock, then
    ///         the Presentation Clock makes these rate change notification
    ///         calls synchronously from the IMFRateControl::SetRate call
    ///         on the Presentation Clock.  In this case, any failure code
    ///         returned from this method will result in an error being
    ///         returned to the caller of the Presentation Clock, and the rate
    ///         change will not take place.
    ///     </para>
    ///     <para>
    ///         If the Clock State Sink is not the Presentation Time Source
    ///         currently in use, then these rate change notification calls
    ///         are made asynchronously after the fact.  Error codes returned
    ///         are ignored.
    ///     </para>
    /// </remarks>
    HRESULT OnClockSetRate(
        [in] MFTIME hnsSystemTime,
        [in] float flRate
        );

}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
// Media Foundation presentation primitives
//
///////////////////////////////////////////////////////////////////////////////

// MF_PD_PMPHOST_CONTEXT
// Data type: IUnknown
// Used by PMPHost to store app PD in the remote PD
// {6C990D31-BB8E-477a-8598-0D5D96FCD88A}
cpp_quote( "EXTERN_GUID( MF_PD_PMPHOST_CONTEXT, 0x6c990d31, 0xbb8e, 0x477a, 0x85, 0x98, 0xd, 0x5d, 0x96, 0xfc, 0xd8, 0x8a );" )

// MF_PD_APP_CONTEXT
// Data type: IUnknown
// Used by IMFMediaSource proxy code to store remote PD in the AppSource PD
// {6C990D32-BB8E-477a-8598-0D5D96FCD88A}
cpp_quote( "EXTERN_GUID( MF_PD_APP_CONTEXT, 0x6c990d32, 0xbb8e, 0x477a, 0x85, 0x98, 0xd, 0x5d, 0x96, 0xfc, 0xd8, 0x8a );" )

// MF_PD_DURATION
// Data type: int64
// Duration in 100ns units of the presentation.  This attribute is optional.
// {6C990D33-BB8E-477a-8598-0D5D96FCD88A}
cpp_quote( "EXTERN_GUID( MF_PD_DURATION, 0x6c990d33, 0xbb8e, 0x477a, 0x85, 0x98, 0xd, 0x5d, 0x96, 0xfc, 0xd8, 0x8a );" )

// MF_PD_TOTAL_FILE_SIZE
// Data type: UINT64
// Total file size in bytes of the presentation.  This attributes is optional.
// {6C990D34-BB8E-477a-8598-0D5D96FCD88A}
cpp_quote( "EXTERN_GUID( MF_PD_TOTAL_FILE_SIZE, 0x6c990d34, 0xbb8e, 0x477a, 0x85, 0x98, 0xd, 0x5d, 0x96, 0xfc, 0xd8, 0x8a );" )

// MF_PD_AUDIO_ENCODING_BITRATE
// Data type: UINT32
// Encoding bitrate for audio in this presentation.
// This attributes is optional and is absent for formats such as ASF that have
// more complex bitrate reporting.
// {6C990D35-BB8E-477a-8598-0D5D96FCD88A}
cpp_quote( "EXTERN_GUID( MF_PD_AUDIO_ENCODING_BITRATE, 0x6c990d35, 0xbb8e, 0x477a, 0x85, 0x98, 0xd, 0x5d, 0x96, 0xfc, 0xd8, 0x8a );" )

// MF_PD_VIDEO_ENCODING_BITRATE
// Data type: UINT32
// Encoding bitrate for video in this presentation.
// This attributes is optional and is absent for formats such as ASF that have
// more complex bitrate reporting.
// {6C990D36-BB8E-477a-8598-0D5D96FCD88A}
cpp_quote( "EXTERN_GUID( MF_PD_VIDEO_ENCODING_BITRATE, 0x6c990d36, 0xbb8e, 0x477a, 0x85, 0x98, 0xd, 0x5d, 0x96, 0xfc, 0xd8, 0x8a );" )

// MF_PD_MIME_TYPE
// Data type: string
// Used by IMFMediaSource to store the mime type of the content opened by the source.
// {6C990D37-BB8E-477a-8598-0D5D96FCD88A}
cpp_quote( "EXTERN_GUID( MF_PD_MIME_TYPE, 0x6c990d37, 0xbb8e, 0x477a, 0x85, 0x98, 0xd, 0x5d, 0x96, 0xfc, 0xd8, 0x8a );" )

// MF_PD_LAST_MODIFIED_TIME
// Type: BLOB
// The format of this blob is given by the FILETIME structure.
// It specifies the time the presentation was last modified.  This attribute is optional.
// {6C990D38-BB8E-477a-8598-0D5D96FCD88A}
cpp_quote( "EXTERN_GUID(MF_PD_LAST_MODIFIED_TIME, 0x6c990d38, 0xbb8e, 0x477a, 0x85, 0x98, 0xd, 0x5d, 0x96, 0xfc, 0xd8, 0x8a );" )

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
// MF_PD_PLAYBACK_ELEMENT_ID
// Type: UINT32
// This attribute may be present on the IMFPresentationDescriptor *
// accompanying an MENewPresentation event.  Please see comments on
// MENewPresentation for an explanation of this attribute.
// {6C990D39-BB8E-477a-8598-0D5D96FCD88A}
cpp_quote( "EXTERN_GUID(MF_PD_PLAYBACK_ELEMENT_ID, 0x6c990d39, 0xbb8e, 0x477a, 0x85, 0x98, 0xd, 0x5d, 0x96, 0xfc, 0xd8, 0x8a );" )

// MF_PD_PREFERRED_LANGUAGE
// Data type: string
// Used by application to set preferred language( RFC1766) to sources ( such as network sources ). This attribute is optional.
// {6C990D3A-BB8E-477a-8598-0D5D96FCD88A}
cpp_quote( "EXTERN_GUID( MF_PD_PREFERRED_LANGUAGE, 0x6c990d3A, 0xbb8e, 0x477a, 0x85, 0x98, 0xd, 0x5d, 0x96, 0xfc, 0xd8, 0x8a );" )

// MF_PD_PLAYBACK_BOUNDARY_TIME
// Type: UINT64
// This attribute may be present on the IMFPresentationDescriptor *
// accompanying an MENewPresentation event.  Please see comments on
// MENewPresentation for an explanation of this attribute.
// {6C990D3B-BB8E-477a-8598-0D5D96FCD88A}
cpp_quote( "EXTERN_GUID(MF_PD_PLAYBACK_BOUNDARY_TIME, 0x6c990d3b, 0xbb8e, 0x477a, 0x85, 0x98, 0xd, 0x5d, 0x96, 0xfc, 0xd8, 0x8a );" )

// MF_PD_AUDIO_ISVARIABLEBITRATE
// Type: UINT32 (boolean)
// Used by media source to indicate the audio stream(s) in this presentation are variable bitrate.  This attribute is optional.
// {33026ee0-e387-4582-ae0a-34a2ad3baa18}
cpp_quote( "EXTERN_GUID( MF_PD_AUDIO_ISVARIABLEBITRATE, 0x33026ee0, 0xe387, 0x4582, 0xae, 0x0a, 0x34, 0xa2, 0xad, 0x3b, 0xaa, 0x18 );" )

cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")


[
    object,
    uuid(03cb2711-24d7-4db6-a17f-f3a7a479a536),
]
interface IMFPresentationDescriptor : IMFAttributes
{
    HRESULT GetStreamDescriptorCount(
        [out] DWORD* pdwDescriptorCount
        );

    HRESULT GetStreamDescriptorByIndex(
        [in] DWORD dwIndex,
        [out] BOOL* pfSelected,
        [out] IMFStreamDescriptor** ppDescriptor
        );

    HRESULT SelectStream(
        [in] DWORD dwDescriptorIndex
        );

    HRESULT DeselectStream(
        [in] DWORD dwDescriptorIndex
        );

    HRESULT Clone(
        [out] IMFPresentationDescriptor** ppPresentationDescriptor
        );
}

//
// Instantiates the Media Foundation-provided implementation of
// IMFPresentationDescriptor.
// The IMFStreamDescriptors in the apStreamDescriptors array should be the
// MF implementations.
//
cpp_quote( "STDAPI MFCreatePresentationDescriptor(" )
cpp_quote( "    DWORD cStreamDescriptors," )
cpp_quote( "    __in_ecount_opt( cStreamDescriptors ) IMFStreamDescriptor** apStreamDescriptors," )
cpp_quote( "    __deref_out IMFPresentationDescriptor** ppPresentationDescriptor" )
cpp_quote( "    );" )
cpp_quote("")

//
// Given an IMFPresentationDescriptor, determines whether this presentation
// requires that it be played in the Media Foundation Protected Environment.
//
cpp_quote("STDAPI MFRequireProtectedEnvironment(")
cpp_quote("     __in IMFPresentationDescriptor* pPresentationDescriptor")
cpp_quote("     );")
cpp_quote("")

//
// Functions to serialize and deserialize a Presentation Descriptor
//
cpp_quote( "STDAPI MFSerializePresentationDescriptor(" )
cpp_quote( "    __in IMFPresentationDescriptor * pPD,")
cpp_quote( "    __out DWORD * pcbData," )
cpp_quote( "    __deref_out_bcount_full(*pcbData) BYTE ** ppbData);" )
cpp_quote("")

cpp_quote( "STDAPI MFDeserializePresentationDescriptor(" )
cpp_quote( "    __in DWORD cbData," )
cpp_quote( "    __in_ecount( cbData ) BYTE * pbData," )
cpp_quote( "    __deref_out IMFPresentationDescriptor ** ppPD);")
cpp_quote("")



///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

// MF_SD_LANGUAGE
// Type: LPWSTR
// {00AF2180-BDC2-423c-ABCA-F503593BC121}
cpp_quote( "EXTERN_GUID(MF_SD_LANGUAGE, 0xaf2180, 0xbdc2, 0x423c, 0xab, 0xca, 0xf5, 0x3, 0x59, 0x3b, 0xc1, 0x21);" )

// MF_SD_PROTECTED
// Data type: UINT32
// Indicates if stream is protected
// {00AF2181-BDC2-423c-ABCA-F503593BC121}
cpp_quote( "EXTERN_GUID(MF_SD_PROTECTED, 0xaf2181, 0xbdc2, 0x423c, 0xab, 0xca, 0xf5, 0x3, 0x59, 0x3b, 0xc1, 0x21);" )

// MF_SD_STREAM_NAME
// Type: LPWSTR
// Stores the stream name (if available) for the stream
// {4F1B099D-D314-41e5-A781-7FEFAA4C501F}
cpp_quote( "EXTERN_GUID(MF_SD_STREAM_NAME, 0x4f1b099d, 0xd314, 0x41e5, 0xa7, 0x81, 0x7f, 0xef, 0xaa, 0x4c, 0x50, 0x1f);" )

// MF_SD_MUTUALLY_EXCLUSIVE
// Type: UINT32
// Indicates that the stream is mutually exclusive with respect to all other streams of this type
// {023EF79C-388D-487f-AC17-696CD6E3C6F5}
cpp_quote( "EXTERN_GUID(MF_SD_MUTUALLY_EXCLUSIVE, 0x23ef79c, 0x388d, 0x487f, 0xac, 0x17, 0x69, 0x6c, 0xd6, 0xe3, 0xc6, 0xf5);" )


[
    object,
    uuid(56c03d9c-9dbb-45f5-ab4b-d80f47c05938),
]
interface IMFStreamDescriptor : IMFAttributes
{
    HRESULT GetStreamIdentifier(
        [out] DWORD* pdwStreamIdentifier
        );

    HRESULT GetMediaTypeHandler(
        [out] IMFMediaTypeHandler** ppMediaTypeHandler
        );

}

//
// Instantiates the Media Foundation-provided implementations of
// IMFStreamDescriptor
//
cpp_quote( "STDAPI MFCreateStreamDescriptor(" )
cpp_quote( "    DWORD dwStreamIdentifier," )
cpp_quote( "    DWORD cMediaTypes," )
cpp_quote( "    __in_ecount(cMediaTypes) IMFMediaType** apMediaTypes," )
cpp_quote( "    __out IMFStreamDescriptor** ppDescriptor" )
cpp_quote( "    );" )
cpp_quote( "" )

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(e93dcf6c-4b07-4e1e-8123-aa16ed6eadf5),
]
/// <summary>
///     IMFMediaTypeHandler is the interface used by some Media Foundation
///     components for media type enumeration and negotiation
/// </summary>
interface IMFMediaTypeHandler : IUnknown
{
    [local]
    HRESULT IsMediaTypeSupported(
        [in] IMFMediaType* pMediaType,
        [out, annotation("__out")] IMFMediaType** ppMediaType
        );

    [local]
    HRESULT GetMediaTypeCount(
        [out, annotation("__out")] DWORD* pdwTypeCount
        );

    [local]
    HRESULT GetMediaTypeByIndex(
        [in] DWORD dwIndex,
        [out, annotation("__out")] IMFMediaType** ppType
        );

    [local]
    HRESULT SetCurrentMediaType(
        [in] IMFMediaType* pMediaType
        );

    [local]
    HRESULT GetCurrentMediaType(
        [out, annotation("__out")] IMFMediaType** ppMediaType
        );

midl_pragma warning (disable: 2495)
    [call_as(GetCurrentMediaType)]
    HRESULT RemoteGetCurrentMediaType(
        [out, annotation("__out"), size_is(, *pcbData)] BYTE ** ppbData,
        [out] DWORD * pcbData
        );
midl_pragma warning (default: 2495)

midl_pragma warning (disable: 2495)
    HRESULT GetMajorType(
       [out, annotation("__out")] GUID* pguidMajorType
       );
midl_pragma warning (default: 2495)
};

//
// Instantiates a simple Media Type Handler object that manages a single media
// type.  To use this object, initialize it with a media type via
// IMFMediaTypeHandler::SetCurrentMediaType.
//
cpp_quote( "STDAPI MFCreateSimpleTypeHandler(" )
cpp_quote( "    __out IMFMediaTypeHandler ** ppHandler );" )

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

typedef enum MFTIMER_FLAGS
{
    /// <summary>
    ///     Indicates that time passed to SetTimer function is relative to the
    ///     current time
    /// </summary>
    MFTIMER_RELATIVE = 0x00000001,
} MFTIMER_FLAGS;


[
    object,
    uuid(e56e4cbd-8f70-49d8-a0f8-edb3d6ab9bf2),
    local
]
/// <summary>
///     IMFTimer is implemented by clocks that provide timer functionality
/// </summary>
interface IMFTimer : IUnknown
{
    /// <summary>
    ///     SetTimer sets a timer that will cause the callback
    ///     function to be called at the specified clock time.
    /// </summary>
    /// <param name="dwFlags">
    ///     Combination of MFTIMER_FLAGS flags.
    /// </param>
    /// <param name="llClockTime">
    ///     Clock time at which the timer should fire.
    ///     Given in the clock's frequency units.
    /// <param>
    /// <param name="pCallback">
    ///     Callback that will be invoked when the timer fires.
    /// </param>
    /// <param name="punkState">
    ///     Caller-defined state object that will be passed to
    ///     pCallback->Invoke when the timer fires.  Optional.
    /// </param>
    /// <param name="ppunkKey">
    ///     Pointer to a variable that will receive a key that can be
    ///     used to cancel the timer.
    /// </param>
    HRESULT SetTimer(
        [in] DWORD dwFlags,
        [in] LONGLONG llClockTime,
        [in] IMFAsyncCallback* pCallback,
        [in] IUnknown* punkState,
        [out] IUnknown** ppunkKey
        );

    /// <summary>
    ///     Cancels a previously-set timer
    /// </summary>
    /// <param name="punkKey">
    ///     The key associated with the timer.
    ///     This key was returned from IMFTimer::SetTimer.
    /// </param>
    /// <returns>
    ///     <para>
    ///         MF_E_CLOCK_INVALID_TIMER_KEY:
    ///             punkKey does not correspond to any timer that can
    ///             currently be canceled.
    ///     </para>
    /// </returns>
    /// <remarks>
    ///     If CancelTimer succeeds, the callback will not be invoked
    ///     for that timer.
    /// </remarks>
    HRESULT CancelTimer(
        [in] IUnknown* punkKey
        );
}

//////////////////////////////////////  Activate guids ////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Following attributes are used by WMP to pass custom video mixer/presenter
cpp_quote( "EXTERN_GUID( MF_ACTIVATE_CUSTOM_VIDEO_MIXER_CLSID,          0xba491360, 0xbe50, 0x451e, 0x95, 0xab, 0x6d, 0x4a, 0xcc, 0xc7, 0xda, 0xd8 );" )
cpp_quote( "EXTERN_GUID( MF_ACTIVATE_CUSTOM_VIDEO_MIXER_ACTIVATE,       0xba491361, 0xbe50, 0x451e, 0x95, 0xab, 0x6d, 0x4a, 0xcc, 0xc7, 0xda, 0xd8 );" )
cpp_quote( "EXTERN_GUID( MF_ACTIVATE_CUSTOM_VIDEO_MIXER_FLAGS,          0xba491362, 0xbe50, 0x451e, 0x95, 0xab, 0x6d, 0x4a, 0xcc, 0xc7, 0xda, 0xd8 );" )
cpp_quote( "EXTERN_GUID( MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_CLSID,      0xba491364, 0xbe50, 0x451e, 0x95, 0xab, 0x6d, 0x4a, 0xcc, 0xc7, 0xda, 0xd8 );" )
cpp_quote( "EXTERN_GUID( MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE,   0xba491365, 0xbe50, 0x451e, 0x95, 0xab, 0x6d, 0x4a, 0xcc, 0xc7, 0xda, 0xd8 );" )
cpp_quote( "EXTERN_GUID( MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS,      0xba491366, 0xbe50, 0x451e, 0x95, 0xab, 0x6d, 0x4a, 0xcc, 0xc7, 0xda, 0xd8 );" )

enum
{
    //
    // Custom mixer flags
    //
    MF_ACTIVATE_CUSTOM_MIXER_ALLOWFAIL         = 0x00000001,  // Failure to create custom mixer will not fail the pipeline
};

enum
{
    //
    // Custom presenter flags
    //
    MF_ACTIVATE_CUSTOM_PRESENTER_ALLOWFAIL     = 0x00000001,  // Failure to create custom presenter will not fail the pipeline
};

/// <summary>
/// MF_ACTIVATE_MFT_LOCKED indicates that MFT which pointed by this activate is locked. Topoloader cannot change the mediatypes for this MFT
/// Topoloader sets this attribute after it uses activate during first topology resolution
/// </summary>
cpp_quote( "EXTERN_GUID( MF_ACTIVATE_MFT_LOCKED,  0xc1f6093c, 0x7f65, 0x4fbd, 0x9e, 0x39, 0x5f, 0xae, 0xc3, 0xc4, 0xfb, 0xd7 );" )

/// <summary>
/// MF_ACTIVATE_VIDEO_WINDOW - UINT64
/// Contains HWND for video activate
/// </summary>
cpp_quote( "EXTERN_GUID( MF_ACTIVATE_VIDEO_WINDOW, 0x9a2dbbdd, 0xf57e, 0x4162, 0x82, 0xb9, 0x68, 0x31, 0x37, 0x76, 0x82, 0xd3 );" )

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

typedef enum _MFSHUTDOWN_STATUS
{
    MFSHUTDOWN_INITIATED,
    MFSHUTDOWN_COMPLETED,
} MFSHUTDOWN_STATUS;

[
    object,
    uuid(97ec2ea4-0e42-4937-97ac-9d6d328824e1),
]
/// <summary>
///     Many Media Foundation components need to be shut down upon exit to break
///     circular references and avoid memory leaks.  For any object that
///     implements an interface with a method called Shutdown(), this method
///     should be called at shutdown time.
///     However, some Media Foundation components instead need to be QIed
///     for IMFShutdown and shut down through this interface.
///     The easiest way to do this is to call MFShutdownObject on the object.
///     Most notably, applications should try to QI for IMFShutdown on
///     any objects implementing the following interfaces:
///         IMFPresentationClock
///         IMFActivate
///         IMFContentEnabler
///         IMFInputTrustAuthority
///         IMFTransform (for asynchronous MFTs)
/// </summary>
interface IMFShutdown : IUnknown
{
    HRESULT Shutdown();

    HRESULT GetShutdownStatus(
        [out] MFSHUTDOWN_STATUS * pStatus);
};

//
// MFShutdownObject can be used on any MF object that inherits or may inherit
// from IMFShutdown.
// If the object inherits from IMFShutdown, then IMFShutdown::Shutdown is
// called.  Regardless, this function will return success.
cpp_quote( "STDAPI " )
cpp_quote( "MFShutdownObject(")
cpp_quote( "    IUnknown * pUnk );")


///////////////////////////////////////////////////////////////////////////////
//
// Media Foundation playback sink creation functions
//
///////////////////////////////////////////////////////////////////////////////


cpp_quote( "STDAPI" )
cpp_quote( "MFCreateAudioRenderer(" )
cpp_quote( "    IMFAttributes* pAudioAttributes," )
cpp_quote( "    __out IMFMediaSink** ppSink" )
cpp_quote( "    );" )

/// <summary>
///     Creates an Audio Renderer Media Sink Activate
/// </summary>
/// </param>
/// <param name="ppIActivate">
///     Returns pointer to an Audio Renderer Media Sink Activate
/// </param>
cpp_quote( "STDAPI" )
cpp_quote( "MFCreateAudioRendererActivate( " )
cpp_quote( "    __out IMFActivate ** ppActivate " )
cpp_quote( "    );" )

//
// Attributes for use with MFCreateAudioRenderer (0xede4b5e0, 0xf805, 0x4d6c, 0x99, 0xb3, 0xdb, 0x01, 0xbf, 0x95, 0xdf, 0xab)
//

// MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS
// Data type: UINT32
// Audio renderer flags attribute. See below for defined flags.
cpp_quote( "EXTERN_GUID( MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS, 0xede4b5e0, 0xf805, 0x4d6c, 0x99, 0xb3, 0xdb, 0x01, 0xbf, 0x95, 0xdf, 0xab);" )

//
//     Flags for the MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS attribute:
//
//     MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS_CROSSPROCESS - If this attribute bit is set, the audio renderer will treat a MF_AUDIO_RENDERER_ATTRIBUTE_SESSION_ID
//     set on it as a cross-process session, allowing audio renderers in multiple processes to share the audio session and associated volume and policy control. Otherwise, audio
//     sessions will always stay local to audio renderers in the current process.
//
cpp_quote("#define    MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS_CROSSPROCESS          0x00000001")

//
//     MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS_NOPERSIST - If this attribute bit is set, audio engine is not going to persist properties for audio session.
//
cpp_quote("#define    MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS_NOPERSIST          0x00000002")

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
//
//     MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS_DONT_ALLOW_FORMAT_CHANGES - **New for Win7**
//     In order to handle dynamic audio device changes without requiring the application to listen for device change events and swap renderers 
//     dynamically (and deal with any clocking issues that stem from that) the audio renderer sink was enhanced to support format changes
//     when generated by an audio device change (in-band formats changes are handled by the MF pipeline, which can dynamically insert a resampler). 
//     This attribute can be used to disable these enhancements and prevent the SAR from allowing its media type to be changed in this 
//     situations. In those cases it will send the necessary events on dynamic device changes to allow the app to handle the device changes 
//     itself.
//
cpp_quote("#define    MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS_DONT_ALLOW_FORMAT_CHANGES          0x00000004")
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

// MF_AUDIO_RENDERER_ATTRIBUTE_SESSION_ID
// Data type: GUID
// This attribute allows the caller to specify an audio session ID for audio media sink. If this is not specified, the sink will use the application's default audio session.
cpp_quote( "EXTERN_GUID( MF_AUDIO_RENDERER_ATTRIBUTE_SESSION_ID, 0xede4b5e3, 0xf805, 0x4d6c, 0x99, 0xb3, 0xdb, 0x01, 0xbf, 0x95, 0xdf, 0xab);" )

// MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID
// Data type: STRING
// This attribute allows the caller to pass in an audio endpoint id (obtained by calling IMMDevice::GetId on a device enumerated from IMMDeviceEnumerator - see MDeviceAPI.idl)
// for creation of an audio renderer media sink on that device endpoint.
// If this attribute is set, the MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE must not be set. Otherwise, a failure will result on audio media sink creation.
// If neither this attribute nor the MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE attribute is set, the default eConsole audio endpoint will be used.
cpp_quote( "EXTERN_GUID( MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID, 0xb10aaec3, 0xef71, 0x4cc3, 0xb8, 0x73, 0x5, 0xa9, 0xa0, 0x8b, 0x9f, 0x8e);" )

// MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE
// Data type: UINT32
// This attribute allows the caller to pass in an audio endpoint "role", to have an audio media sink created using the default device for the supplied role.
// See the MultimediaDevice documentation (MMDeviceAPI.idl) for the list of list of audio endpoint roles that can be passed with this attribute.
// If this attribute is set, the MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID must not be set. Otherwise, a failure will result on audio media sink creation.
// If neither this attribute nor the MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID attribute is set, the default eConsole audio endpoint will be used.
cpp_quote( "EXTERN_GUID( MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE, 0x6ba644ff, 0x27c5, 0x4d02, 0x98, 0x87, 0xc2, 0x86, 0x19, 0xfd, 0xb9, 0x1b);" )

//
// Attributes for use with MFCreateAudioRenderer
//

/// <summary>
///     Creates a Video Renderer Media Sink Activate
/// </summary>
/// <param name="hwndVideo">
///     The HWND within which the video will play
/// </param>
/// <param name="ppIActivate">
///     Returns pointer to a Video Renderer Media Sink Activate
/// </param>
cpp_quote( "STDAPI" )
cpp_quote( "MFCreateVideoRendererActivate(" )
cpp_quote( "    __in HWND hwndVideo, " )
cpp_quote( "    __out IMFActivate ** ppActivate " )
cpp_quote( "    );" )

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
/// <summary>
///     Creates a MPEG4 Archive Sink
/// </summary>
/// <param name="pIByteStream">
///     Pointer to the byte stream that will be used to write the MPEG4 file
/// </param>
/// <param name="pVideoMediaType">
///     Pointer to the media type of the video input stream
/// </param>
/// <param name="pAudioMediaType">
///     Pointer to the media type of the audio input stream
/// </param>
/// <param name="ppIMediaSink">
///     Receives a pointer to the IMFMediaSinkInterface.  The caller must release this interface.
/// </param>
cpp_quote( "STDAPI" )
cpp_quote( "MFCreateMPEG4MediaSink(" )
cpp_quote( "    __in IMFByteStream* pIByteStream, " )
cpp_quote( "    __in_opt IMFMediaType* pVideoMediaType, " )
cpp_quote( "    __in_opt IMFMediaType* pAudioMediaType, " )
cpp_quote( "    __out IMFMediaSink** ppIMediaSink " )
cpp_quote( "    );" )

/// <summary>
///     Creates a 3GP Archive Sink
/// </summary>
/// <param name="pIByteStream">
///     Pointer to the byte stream that will be used to write the 3GP file
/// </param>
/// <param name="pVideoMediaType">
///     Pointer to the media type of the video input stream
/// </param>
/// <param name="pAudioMediaType">
///     Pointer to the media type of the audio input stream
/// </param>
/// <param name="ppIMediaSink">
///     Receives a pointer to the IMFMediaSinkInterface.  The caller must release this interface.
/// </param>
cpp_quote( "STDAPI" )
cpp_quote( "MFCreate3GPMediaSink(" )
cpp_quote( "    __in IMFByteStream* pIByteStream, " )
cpp_quote( "    __in_opt IMFMediaType* pVideoMediaType, " )
cpp_quote( "    __in_opt IMFMediaType* pAudioMediaType, " )
cpp_quote( "    __out IMFMediaSink** ppIMediaSink " )
cpp_quote( "    );" )

/// <summary>
///     Creates a MP3 archive sink.  The MP3 archive sink takes metadata and compressed MP3
///     audio and writes it to an MP3 file with ID3 headers.
/// </summary>
/// <param name="pTargetByteStream">
///     Pointer to the byte stream that will be used to write the MP3 file
/// </param>
/// <param name="ppMediaSink">
///     Receives a pointer to the IMFMediaSinkInterface.  The caller must release this interface.
/// </param>
cpp_quote( "STDAPI" )
cpp_quote( "MFCreateMP3MediaSink(" )
cpp_quote( "    __in IMFByteStream* pTargetByteStream, " )
cpp_quote("     __deref_out IMFMediaSink** ppMediaSink " )
cpp_quote( "    );" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
// Media Foundation topology-related interfaces
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

/// <summary>
///     IMFTopoLoader interface.
///     Unless the MFSESSION_SETTOPOLOGY_NORESOLUTION flag is set when
///     IMFMediaSession::SetTopology is called, the Media Session takes
///     care of topology resolution.
///     However, applications that wish to do topology resolution outside
///     the Media Session can call MFCreateTopoLoader to create the topoloader
///     object.  They can then use this interface to resolve a partial
///     topology to afull topology, which can be set on the Media Session with
///     the flag MFSESSION_SETTOPOLOGY_NORESOLUTION.
/// </summary>
[
    object,
    uuid(DE9A6157-F660-4643-B56A-DF9F7998C7CD),
    local
]
interface IMFTopoLoader : IUnknown
{
    /// <summary>
    ///     Given the input partial topology, the method will turn it into a
    ///     fully loaded topology.
    /// </summary>
    /// <remarks>
    ///     Topoloader will find all the intermediate transforms needed to
    ///     provide a fully specified topology of sources, transforms,
    ///     and sinks.
    ///     Sets all the input and output media types on all the objects
    ///     in the topology.
    ///     If this method returns successfully, the output topology is
    ///     ready for processing by the media processor.
    ///     The third parameter pCurrentTopo can be NULL or a pointer to
    ///     the preceding topology.
    /// </remarks>
    /// <param name="pInputTopo">
    ///     The pointer to the partial topology to be resolved.
    /// </param>
    /// <param name="ppOutputTopo">
    ///     The pointer to a IMFTopology pointer where the full topology
    ///     is returned
    /// </param>
    /// <param name="pCurrentTopo">
    ///     The pointer to the previous full topology for object caching.
    ///     May be NULL.
    ///     The topoloader will use this full topology as reference and
    ///     pull the topology node objects from it into the new
    ///     full topology it creates.
    ///     Once Load completes successfully, pCurrentTopo should be discarded.
    /// </param>
    /// <returns>
    ///     If the method succeeds, the return value is S_OK.
    ///     If the method fails, the return value will be some failure code.
    /// </returns>
    HRESULT Load(
                [in] IMFTopology * pInputTopo,
                [out, annotation("__out")] IMFTopology ** ppOutputTopo,
                [in] IMFTopology* pCurrentTopo);
};

/// <summary>
///     Creates an IMFTopologyLoader object
/// </summary>
/// <param name="ppObj">
///     Pointer to an IMFTopoLoader pointer where the Topology Loader object
///     will be returned
/// </param>
cpp_quote( "STDAPI MFCreateTopoLoader(" )
cpp_quote( "    __out IMFTopoLoader ** ppObj );" )



///////////////////////////////////////////////////////////////////////////////
//
// Media Foundation protected playback interfaces
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid( ACF92459-6A61-42bd-B57C-B43E51203CB0 ),
    helpstring( "IMFContentProtectionManager Interface"),
    pointer_default(unique)
]
/// <summary>
///     IMFContentProtectionManager is the interface that an application is called
///     back on if a PMP component wants to perform some steps with the application’s
///     help/consent, like license acquisition or individualization.
///     <para>
///         The application should implement this callback and set the callback pointer in
///         the configuration property store that it passes into the PMP Session as part
///         of the MFCreatePMPMediaSession method. If the application does not set a
///         callback pointer then certain operations like license acquisition that require
///         application help will fail.
///     </para>
///     <para>
///         The PMP marshals calls from within the Protected Environment to the application.
///     </para>
///     <para>
///         Typically, this interface will be invoked during the SetTopology operation, before
///         MESessionTopologySet is fired by the session. The application should be prepared to receive
///         multiple content enablers during this time. Content Enablers may also be fired outside
///         of the SetTopology operation, but those scenarios are not as common, and typically
///         involve just a single content enabler, so the application should not need special
///         UI to handle multiple enablers outside of the SetTopology operation.
///     </para>
/// </summary>
interface IMFContentProtectionManager: IUnknown
{
    /// <summary>
    ///     BeginEnableContent requests the application to perform a specific step to
    ///     acquire rights to the content. The application should not block in this method.
    ///     It should do any time-consuming operations asynchronously on its own thread and
    ///     when done notify the PMP via the pCallback parameter passed into this method.
    /// </summary>
    /// <param name="pEnablerActivate">
    ///     [in]  An IMFActivate to a Content Enabler object. The methods of this object provide
    ///     the various options available to the application to perform what is necessary to
    ///     finish this step of acquiring rights to the content.
    /// </param>
    /// <param name="pTopo">
    ///     [in]  A pointer to the topology that caused this content enabler
    ///     to be fired. Note that in some cases, there is no relevant
    ///     topology, and this parameter will be NULL.
    /// </param>
    /// <param name="pCallback">
    ///     [in]  A callback pointer into the PMP. When the application is done with its
    ///     asynchronous processing it should call pCallback->Invoke.
    /// </param>
    /// <param name="punkState">
    ///     [in]  A context object that the application should pass back into pCallback->Invoke.
    /// </param>
    /// <returns>
    ///     The return value is S_OK on success, and an error code otherwise.
    /// </returns>
    /// <remarks>
    ///     If the application returns a success code from BeginEnableContent, then it must
    ///     call pCallback->Invoke. If it returns an error code from BeginEnableContent, then
    ///     it must not call pCallback->Invoke.
    ///</remarks>
    [local]
    HRESULT BeginEnableContent(
        [in] IMFActivate *pEnablerActivate,
        [in] IMFTopology *pTopo,
        [in] IMFAsyncCallback *pCallback,
        [in] IUnknown *punkState
        );

    [call_as(BeginEnableContent)]
    HRESULT RemoteBeginEnableContent(
        [in] REFCLSID clsidType,
        [in, size_is(cbData)] BYTE *pbData,
        [in] DWORD cbData,
        [in] IMFRemoteAsyncCallback *pCallback
        );

    /// <summary>
    ///     After the application notifies the PMP (via pCallback->Invoke) that it is done with
    ///     all asynchronous processing following BeginEnableContent, PMP calls EndEnableContent
    ///     on the application to fetch the result code of that processing.
    /// </summary>
    /// <param name="pResult">
    ///     [in]  This is the same pointer that the application passed into pCallback->Invoke,
    ///     where pCallback is what was passed into BeginEnableContent.
    /// </param>
    /// <returns>
    ///     The application should return the success code or error code of the asynchronous
    ///     processing that followed the BeginEnableContent call.
    /// </returns>
    /// <remarks>
    ///     This method is called synchronously from the callback passed in to
    ///     BeginEnableContent. Thus, this method will be called on the application's
    ///     thread, and should not block.
    ///</remarks>
    [local]
    HRESULT EndEnableContent(
        [in] IMFAsyncResult *pResult
        );

    [call_as(EndEnableContent)]
    HRESULT RemoteEndEnableContent(
        [in] IUnknown *pResult
        );
};

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

typedef enum
{
    MF_LICENSE_URL_UNTRUSTED,
    MF_LICENSE_URL_TRUSTED,
    MF_LICENSE_URL_TAMPERED,
}   MF_URL_TRUST_STATUS;

[
    object,
    uuid( D3C4EF59-49CE-4381-9071-D5BCD044C770 ),
    helpstring( "IMFContentEnabler Interface"),
    pointer_default(unique)
]
/// <summary>
///     The IMFContentEnabler interface encapsulates all of the options available
///     to the application to perform one step along the way to acquire rights to
///     the content.
///     <para>
///         For instance, if the application wants to play WMDRM content, the steps
///         required may be to first individualize the machine and then acquire a license.
///     </para>
///     <para>
///     -   For individualization, the platform creates a Content Enabler object and
///         passes it to the application as part of a platform callback. The application
///         can then put up UI if required, get user consent if required, and finally
///         call the methods of the Content Enabler to perform individualization. The
///         AutomaticEnable method of the Content Enabler performs the individualization.
///     -   The same process is repeated for license acquisition. In this case as well
///         the platform creates (a different implementation of) the Content Enabler object.
///         The AutomaticEnable method of this Content Enabler fetches a license.
///     </para>
///     <para>
///         Abstracting these operations through the IMFContentEnabler interface allows an
///         application to write common code to deal with the various steps of acquiring
///         rights. This also makes it possible for a variety of current and future content
///         protection systems to automatically be plugged in under the application as long
///         as their requirements can be abstracted within this interface.
///     </para>
/// </summary>
interface IMFContentEnabler : IUnknown
{
    /// <summary>
    ///     GetEnableType returns the type of operation that needs to be done to acquire
    ///     rights to the content. For the types that the application is aware of, it can
    ///     put up friendly strings in its UI.
    /// </summary>
    /// <param name="pType">
    ///     [out]  GUID representing the type of operation requested.
    /// </param>
    /// <returns>
    ///     If the method succeeds, it returns S_OK. Otherwise it returns a failure code.
    /// </returns>
    HRESULT GetEnableType(
        [out] GUID *pType );

    /// <summary>
    ///     If the operation requested can be achieved by the application opening a certain
    ///     URL in the browser then GetEnableURL returns that URL. For instance, for license
    ///     acquisition an application might prefer to navigate to the URL itself.
    ///     <para>
    ///         The application is expected to do an HTTP POST request to this URL.
    ///     </para>
    /// </summary>
    /// <param name="pwszURL">
    ///     [out]  Pointer to a WCHAR array allocated by the caller. The Content Enabler
    ///     object fills in the URL to navigate to if the length of the array, indicated by
    ///     the pcchURL parameter, is sufficient.
    /// </param>
    /// <param name="pcchURL">
    ///     [in, out]  Pointer to a DWORD. The caller should initialize it to the size of the
    ///     array, in WCHARs, that pwszURL points to. The Content Enabler overwrites it with
    ///     the length of the URL in WCHARs excluding the terminating NULL.
    /// </param>
    /// <param name="pTrustStatus">
    ///     [out]  An enum that tells the application whether the URL is from a trusted source.
    ///     See MF_URL_TRUST_STATUS for details.
    /// </param>
    /// <returns>
    ///     If there is an URL to return and the method succeeds, it returns S_OK. Otherwise it
    ///     returns a failure code.
    /// </returns>
    /// <remarks>
    ///     The application needs to call this method twice - once with a NULL pwszURL in order
    ///     to get the length of the WCHAR array to allocate, and the second time with the
    ///     allocated array and its size.
    ///     <para>
    ///         The GetEnableURL call must be accompanied by a GetEnableData call. Typically the
    ///         application will also call MonitorEnable subsequently.
    ///     </para>
    ///</remarks>
    HRESULT GetEnableURL(
        [out, size_is(, *pcchURL)] LPWSTR * ppwszURL,
        [out] DWORD *pcchURL,
        [in, out, unique] MF_URL_TRUST_STATUS *pTrustStatus );

    /// <summary>
    ///     GetEnableData returns the data that needs to accompany the HTTP POST request in case
    ///     the application chooses to navigate to the URL returned by GetEnableURL.
    /// </summary>
    /// <param name="pbData">
    ///     [out]  Pointer to a BYTE array allocated by GetEnableData that contains the HTTP POST data.
    /// </param>
    /// <param name="pcbData">
    ///     [out]  Pointer to a DWORD. The Content Enabler overwrites this with the
    ///     length of the POST data in BYTEs.
    /// </param>
    /// <returns>
    ///     If there is POST data to return and the method succeeds, it returns S_OK. Otherwise
    ///     it returns a failure code.
    /// </returns>
    /// <remarks>
    ///</remarks>
    HRESULT GetEnableData(
        [out, size_is(, *pcbData)] BYTE ** ppbData,
        [out] DWORD *pcbData );

    /// <summary>
    ///     The IsAutomaticSupported method indicates whether the Content Enabler can do all of the
    ///     requested steps on its own. For WMDRM license acquisition for instance, the Content
    ///     Enabler is able to navigate to the license acquisition URL on its own and download
    ///     the license.
    /// </summary>
    /// <param name="pfAutomatic">
    ///     [in]  Pointer to a BOOL. The Content Enabler sets the BOOL to TRUE if it can do the
    ///     required operation on its own. It sets the BOOL to FALSE if it needs the application
    ///     to do the required operation by calling GetEnableURL and navigating to it.
    /// </param>
    /// <returns>
    ///     If the method succeeds it returns S_OK, otherwise it returns a failure code.
    /// </returns>
    /// <remarks>
    ///</remarks>
    HRESULT IsAutomaticSupported(
        [out] BOOL *pfAutomatic );

    /// <summary>
    ///     Through AutomaticEnable the application instructs the Content Enabler to perform the
    ///     required operation on its own. MF ONLY: When the operation completes the Content Enabler
    ///     queues up a MEEnablerCompleted event onto its IMFMediaEventGenerator interface.
    /// </summary>
    /// <returns>
    ///     If the method succeeds it returns S_OK, otherwise it returns a failure code.
    /// </returns>
    /// <remarks>
    ///</remarks>
    HRESULT AutomaticEnable();

    /// <summary>
    ///     MF ONLY: In case the application chooses to call GetEnableURL and navigate itself, the
    ///     application is expected to do so through a web browser or web browser control.
    ///     From that point the rest of the operation proceeds without the application’s
    ///     involvement. If the application wants to be notified when the operation completes,
    ///     then it should call MonitorEnable. In this case the Content Enabler queues up a
    ///     MEEnablerCompleted event onto its IMFMediaEventGenerator interface, just like in
    ///     the SilentEnable case.
    /// </summary>
    /// <returns>
    ///     If the method succeeds it returns S_OK, otherwise it returns a failure code.
    /// </returns>
    /// <remarks>
    ///</remarks>
    HRESULT MonitorEnable();

    /// <summary>
    ///     The application can call Cancel to cancel a pending SilentEnable or MonitorEnable.
    ///     MF ONLY: In response the Content Enabler queues up a MEEnablerCompleted event immediately
    ///     with an error code of E_CANCEL.
    /// </summary>
    /// <returns>
    ///     If the method succeeds it returns S_OK, otherwise it returns a failure code.
    /// </returns>
    /// <remarks>
    ///</remarks>
    HRESULT Cancel();
};

//
// Content Enabler Type GUIDs
//
cpp_quote( "" )
cpp_quote( "EXTERN_GUID( MFENABLETYPE_WMDRMV1_LicenseAcquisition, 0x4ff6eeaf, 0xb43, 0x4797, 0x9b, 0x85, 0xab, 0xf3, 0x18, 0x15, 0xe7, 0xb0);" )
cpp_quote( "EXTERN_GUID( MFENABLETYPE_WMDRMV7_LicenseAcquisition, 0x3306df, 0x4a06, 0x4884,0xa0, 0x97, 0xef, 0x6d, 0x22, 0xec, 0x84, 0xa3);" )
cpp_quote( "EXTERN_GUID( MFENABLETYPE_WMDRMV7_Individualization, 0xacd2c84a, 0xb303, 0x4f65, 0xbc, 0x2c, 0x2c, 0x84, 0x8d, 0x1, 0xa9, 0x89);" )
cpp_quote( "EXTERN_GUID( MFENABLETYPE_MF_UpdateRevocationInformation, 0xe558b0b5, 0xb3c4, 0x44a0, 0x92, 0x4c, 0x50, 0xd1, 0x78, 0x93, 0x23, 0x85);" )
cpp_quote( "EXTERN_GUID( MFENABLETYPE_MF_UpdateUntrustedComponent, 0x9879f3d6, 0xcee2, 0x48e6, 0xb5, 0x73, 0x97, 0x67, 0xab, 0x17, 0x2f, 0x16);" )
cpp_quote( "EXTERN_GUID( MFENABLETYPE_MF_RebootRequired, 0x6d4d3d4b, 0x0ece, 0x4652, 0x8b, 0x3a, 0xf2, 0xd2, 0x42, 0x60, 0xd8, 0x87);" )

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

cpp_quote( "// ")
cpp_quote( "// Structs that contain information about revoked or unsigned binaries, ")
cpp_quote( "// returned by the IMFContentEnabler::GetEnableData() method of  ")
cpp_quote( "// the Revocation content enabler ")
cpp_quote( "// ")

cpp_quote( "#ifndef MFRR_INFO_VERSION" )
cpp_quote( "#define MFRR_INFO_VERSION 0" )
cpp_quote( "#endif" )


cpp_quote( "// ")
cpp_quote( "// The values for MFRR_COMPONENT_HASH_INFO.ulReason ")
cpp_quote( "// ")

cpp_quote( "#define MF_USER_MODE_COMPONENT_LOAD        0x00000001")
cpp_quote( "#define MF_KERNEL_MODE_COMPONENT_LOAD      0x00000002")
cpp_quote( "#define MF_GRL_LOAD_FAILED                 0x00000010")
cpp_quote( "#define MF_INVALID_GRL_SIGNATURE           0x00000020")
cpp_quote( "#define MF_GRL_ABSENT                      0x00001000")
cpp_quote( "#define MF_COMPONENT_REVOKED               0x00002000")
cpp_quote( "#define MF_COMPONENT_INVALID_EKU           0x00004000")
cpp_quote( "#define MF_COMPONENT_CERT_REVOKED          0x00008000")
cpp_quote( "#define MF_COMPONENT_INVALID_ROOT          0x00010000")
cpp_quote( "#define MF_COMPONENT_HS_CERT_REVOKED       0x00020000")
cpp_quote( "#define MF_COMPONENT_LS_CERT_REVOKED       0x00040000")
cpp_quote( "#define MF_BOOT_DRIVER_VERIFICATION_FAILED 0x00100000")
cpp_quote( "#define MF_TEST_SIGNED_COMPONENT_LOADING   0x01000000")
cpp_quote( "#define MF_MINCRYPT_FAILURE                0x10000000")

cpp_quote( "// ")
cpp_quote( "// STR_HASH_LEN: Number of characters required to represent a SHA-1 hash  ")
cpp_quote( "// (RTL_MAX_HASH_LEN_V1) as a string of the form \"0x5a3b53463b672a4f...\" ")
cpp_quote( "// Each byte of a SHA-1 hash takes two characters to represent, and ")
cpp_quote( "// we add in two leading characters \"0x\" as well as the NULL terminator ")
cpp_quote( "// ")

cpp_quote( "#define SHA_HASH_LEN   20 ")

cpp_quote( "#define STR_HASH_LEN   (SHA_HASH_LEN*2 + 3) ")

cpp_quote( "typedef struct _MFRR_COMPONENT_HASH_INFO ")
cpp_quote( "{ ")
cpp_quote( "    // Reason for failure (revoked or unsigned or badly signed).   ")
cpp_quote( "    DWORD ulReason; ")
cpp_quote( " ")
cpp_quote( "    // Header hash of the component ")
cpp_quote( "    WCHAR rgHeaderHash[STR_HASH_LEN];  ")
cpp_quote( " ")
cpp_quote( "    // Hash of public key if one of the certificates  ")
cpp_quote( "    // in the signing certificate chain is revoked ")
cpp_quote( "    WCHAR rgPublicKeyHash[STR_HASH_LEN];  ")
cpp_quote( " ")
cpp_quote( "    // Component name (full path name) ")
cpp_quote( "    WCHAR wszName[MAX_PATH];     ")
cpp_quote( " ")
cpp_quote( "}   MFRR_COMPONENT_HASH_INFO, *PMFRR_COMPONENT_HASH_INFO; ")


cpp_quote( "typedef struct _MFRR_COMPONENTS ")
cpp_quote( "{ ")
cpp_quote( " ")
cpp_quote( "    // Version number  ")
cpp_quote( "    DWORD dwRRInfoVersion; ")
cpp_quote( " ")
cpp_quote( "    // Number of components in list ")
cpp_quote( "    DWORD dwRRComponents; ")
cpp_quote( " ")
cpp_quote( "    // points to the end of this structure that has  ")
cpp_quote( "    // allocated memory for the array of component info structures ")
cpp_quote( "    PMFRR_COMPONENT_HASH_INFO pRRComponents;  ")
cpp_quote( " ")
cpp_quote( "}   MFRR_COMPONENTS, *PMFRR_COMPONENTS; ")


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
// Media Foundation advanced playback interfaces
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

//
// Structure used in flattening WM_PICTURE data
// This is the format of the blob in an ASF file, and what will be returned
// from a call to IMFMetadata::GetProperty( ).  It is always byte
// aligned since it is part of a file format.  Full binary layout of the blob
// is ASF_FLAT_PICTURE followed by null-terminated UNICODE string denoting MIME
// type, null-terminated UNICODE string description, and pointer to image
// bytes.
//
cpp_quote( "#pragma pack ( push ) ")
cpp_quote( "#pragma pack ( 1 ) ")
cpp_quote( "typedef struct _ASFFlatPicture ")
cpp_quote( "{ ")
cpp_quote( "    // ")
cpp_quote( "    // Direct mapped fields ")
cpp_quote( "    // ")
cpp_quote( "    BYTE bPictureType; ")
cpp_quote( "    DWORD dwDataLen; ")
cpp_quote( "}   ASF_FLAT_PICTURE; ")
cpp_quote( "#pragma pack ( pop ) ")


//
// Structure used in flattening WM_SYNCHRONISED_LYRICS data
// This is the format of the blob in an ASF file, and what will be returned
// from a call to IMFMetadata::GetProperty( ).  It is always byte aligned
// since it is part of a file format.  Full binary layout of the blob is
// FLAT_SYNCHRONIZED_LYRICS followed by null-terminated UNICODE string content
// description, followed by BYTE pointer to lyrics.  Lyrics themselves are
// defined as array, null-terminated UNICODE string followed by DWORD timestamp
// (units specified by bTimeStampFormat value).
//
cpp_quote( "#pragma pack ( push ) ")
cpp_quote( "#pragma pack ( 1 ) ")
cpp_quote( "typedef struct _ASFFlatSynchronisedLyrics ")
cpp_quote( "{ ")
cpp_quote( "    // ")
cpp_quote( "    // Direct mapped fields ")
cpp_quote( "    // ")
cpp_quote( "    BYTE bTimeStampFormat; ")
cpp_quote( "    BYTE bContentType; ")
cpp_quote( "    DWORD dwLyricsLen; ")
cpp_quote( "}   ASF_FLAT_SYNCHRONISED_LYRICS; ")
cpp_quote( "#pragma pack ( pop ) ")

[
    object,
    uuid(F88CFB8C-EF16-4991-B450-CB8C69E51704),
]
/// <summary>
///     <para>
///     The IMFMetadata interface is the method by which MF-aware applications
///     access file metadata from media sources.
///     </para>
/// </summary>
interface IMFMetadata : IUnknown
{
    /// <summary>
    ///     Sets the language context in which values are to be returned.
    /// </summary>
    /// <param name="pwszRFC1766">
    ///     Language ID, specified per RFC 1766.
    /// </param>
    HRESULT SetLanguage(
                [in] LPCWSTR pwszRFC1766
                );

    /// <summary>
    ///     Retrieves the current language context.
    /// </summary>
    /// <param name="pwszRFC1766">
    ///     Language ID, specified per RFC 1766. Must be deallocated using CoTaskMemFree(...)
    /// </param>
    HRESULT GetLanguage(
                [out] LPWSTR * ppwszRFC1766
                );

    /// <summary>
    ///     Retrieves a list of all available languages in this metadata set.
    /// </summary>
    /// <param name="ppvLanguages">
    ///     Returns a list of language IDs, per RFC1766, in a PROPVARIANT specified as type
    ///     VT_VECTOR | VT_LPWSTR.
    /// </PARAM>
    HRESULT GetAllLanguages(
                [out] PROPVARIANT * ppvLanguages
                );

    /// <summary>
    ///     Set given property to the given value.  For property type, consult schema
    ///     documentation.
    /// </summary>
    /// <param name="pwszName">
    ///     The name of the property.
    /// </param>
    /// <param name="ppvValue">
    ///     Value to set.
    /// </param>
    /// <remarks>
    /// <para>
    ///     If the value is recognized, the type of the PROPVARIANT will be enforced.
    /// </para>
    /// <para>
    ///     If the value is NOT recognized, but exists in the current propery set,
    ///     SetProperty will enforce agreement between the type of the existing value
    ///     and the type of the new value.
    /// </para>
    /// <para>
    ///     If the value is NOT recognized and does NOT exist in the current property
    ///     set, SetProperty will successfully set the property regardless of type.
    /// </para>
    /// </remarks>
    HRESULT SetProperty(
                [in] LPCWSTR pwszName,
                [in] const PROPVARIANT * ppvValue
                );

    /// <summary>
    ///     Retrieve value corresponding to the specified name.
    /// </summary>
    /// <param name="pwszName">
    ///     The name of the property.
    /// </param>
    /// <param name="ppvValue">
    ///     Value to retrieve.
    /// </param>
    /// <remarks>
    ///     For predefined values, type will be as specified in schema documentation.
    ///     For unknown values, type will be as specified when set, or in the case of
    ///     unknown file metadata values, will default to string.
    /// </remarks>
    HRESULT GetProperty(
                [in] LPCWSTR pwszName,
                [out] PROPVARIANT * ppvValue
                );

    /// <summary>
    ///     Remove specified property from a set.
    /// </summary>
    /// <param name="pwszName">
    ///     Name of the property to remove.
    /// </param>
    /// <remarks>
    ///     Some properties may be considered read-only.  An attempt to delete a
    ///     read-only property will result in an error.  An attempt to delete a
    ///     property which is not part of the set will succeed with status code
    ///     S_FALSE.
    /// </remarks>
    HRESULT DeleteProperty(
                [in] LPCWSTR pwszName
                );

    /// <summary>
    ///     Retrieve the names of all properties in the given set.
    /// </summary>
    /// <param name="ppvNames">
    ///     Array of VT_LPWSTR property names.
    /// </param>
    /// <remarks>
    ///     Note that the list will be returned as type VT_VECTOR | VT_LPWSTR,
    ///     i.e. a simple array, NOT in a SAFEARRAY type.
    /// </remarks>
    HRESULT GetAllPropertyNames(
                [out] PROPVARIANT * ppvNames
                );
};

[
    object,
    uuid(56181D2D-E221-4adb-B1C8-3CEE6A53F76F)
]
/// <summary>
///     IMFMetadataProvider is used to obtain a IMFMetadata interface
///     associated with a particular IMFPresentationDescriptor
/// </summary>
interface IMFMetadataProvider : IUnknown
{
    /// <summary>
    ///     Returns a IMFMetadata interface
    /// </summary>
    /// <param name="pPresentationDescriptor">
    ///     Pointer to the IMFPresentationDescriptor for which the
    ///     IMFMetadata is desired.
    /// </param>
    /// <param name="dwStreamIdentifier">
    ///     If set to 0, the function returns the IMFMetadata of the whole
    ///     presentation. If dwStreamIdentifier is set to a non-zero value,
    ///     the function returns a IMFMetadata belonging to the stream
    ///    identified by dwStreamIdentifier.
    /// </param>
    /// <param name="dwFlags">
    ///     Reserved for future use.  Must be set to zero.
    /// </param>
    /// <param name="ppMFMetadata">
    ///     Pointer to a variable that will be set to a pointer to the IMFMetadata interface.
    /// </param>
    /// <returns>
    ///     <para>
    ///         MF_E_PROPERTY_NOT_FOUND:
    ///         An IMFMetadata interface is not available for the requested
    ///         IMFPresentationDescriptor and/or stream identifier.
    ///     </para>
    /// </returns>
    /// <remarks>
    ///     <para>
    ///         An IMFMetadata interface may not always be available for a
    ///         certain IMFPresentationDescriptor and/or stream identifier.
    ///     </para>
    /// </remarks>
    HRESULT GetMFMetadata(
        [in] IMFPresentationDescriptor *pPresentationDescriptor,
        [in] DWORD dwStreamIdentifier,
        [in] DWORD dwFlags,
        [out] IMFMetadata **ppMFMetadata
        );
}

//
// Use this GUID to retrieve IMFMetadataProvider from components providing
// that service.
//
cpp_quote( "EXTERN_GUID( MF_METADATA_PROVIDER_SERVICE, 0xdb214084, 0x58a4, 0x4d2e, 0xb8, 0x4f, 0x6f, 0x75, 0x5b, 0x2f, 0x7a, 0xd);" )

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
//
// Use this GUID for "new" metadata service, i.e. IPropertyStore.  Use of
// IMFMetadataProvider is deprecated for general metadata use, and doesn't
// support writing.
//
cpp_quote( "EXTERN_GUID( MF_PROPERTY_HANDLER_SERVICE, 0xa3face02, 0x32b8, 0x41dd, 0x90, 0xe7, 0x5f, 0xef, 0x7c, 0x89, 0x91, 0xb5);" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////


typedef enum _MFRATE_DIRECTION
{
    //
    // Indicates forward playback
    //
    MFRATE_FORWARD,

    //
    // Indicates reverse playback
    //
    MFRATE_REVERSE

}   MFRATE_DIRECTION;

[
    object,
    uuid(0a9ccdbc-d797-4563-9667-94ec5d79292d),
    pointer_default(unique)
]
/// <summary>
///     IMFRateSupport is used to query a component for what
///     rates it supports.
///     This interface is obtained from the component via
///     IMFGetService::GetService using the MF_RATE_CONTROL_SERVICE
///     service GUID.
///     The Media Session provides IMFRateSupport.
///     Media Sources, Transforms, and Media Sinks may provide IMFRateSupport.
///     Those that do not are assumed to support any positive rate but
///     not zero or negative rates.
/// </summary>
interface IMFRateSupport : IUnknown
{
    /// <summary>
    ///     Gets the slowest rate at which playback can happen
    /// </summary>
    /// <param name="eDirection">
    ///     Indicates playback direction for this query.
    ///     If MFRATE_FORWARD, then *pflRate will be set to the slowest
    ///     positive rate supported.
    ///     If MFRATE_REVERSE, then *pflRate will be set to the slowest
    ///     negative rate (by absolute value) supported.
    /// </param>
    /// <param name="fThin">
    ///     If TRUE, then *pflRate will be set to the slowest rate at
    ///     which thinning will occur.
    /// </param>
    /// <param name="pflRate">
    ///     Pointer to a variable to receive the slowest rate supported.
    /// </param>
    /// <returns>
    ///     <para>
    ///         MF_E_REVERSE_UNSUPPORTED
    ///         Returned by components that do not support reverse
    ///         playback when fForwardPlayback is FALSE.
    ///     </para>
    ///     <para>
    ///         MF_E_THINNING_UNSUPPORTED
    ///         Returned by components that cannot thin streams or handle
    ///         thinned streams when fThin is TRUE.
    ///     </para>
    /// </returns>
    /// <remarks>
    ///     <para>
    ///         If 0 is returned in *pflRate, that does not guarantee that
    ///         rate 0 is supported; the caller must do a separate
    ///         IsRateSupported query to determine that.
    ///         Otherwise, *pflRate can be assumed to be supported.
    ///     </para>
    ///     <para>
    ///         "Thinning" is defined in a format-specific manner.
    ///         For some formats (such as ASF), thinning will mean dropping
    ///         all frames that are not I-frames.
    ///         If the component produces stream data (like a Media Source
    ///         or a demultiplexer), it should pay attention
    ///         to the fThin argument and return MF_E_THINNING_UNSUPPORTED
    ///         if it cannot thin the stream.
    ///         If the component processes or receives a stream (like
    ///         most transforms or Media Sinks), it may ignore this
    ///         parameter if it does not care whether the stream is thinned.
    ///         In the Media Session's implementation of rate support,
    ///         if the transforms do not explicitly support reverse playback,
    ///         the Media Session will attempt to do reverse playback in
    ///         thinned mode (but will not do so unthinned).
    ///         Therefore, most applications will set fThin to TRUE
    ///         when using the Media Session for reverse playback.
    ///     </para>
    /// </remarks>
    HRESULT GetSlowestRate(
        [in]  MFRATE_DIRECTION eDirection,
        [in]  BOOL fThin,
        [out] float* pflRate
        );

    /// <summary>
    ///     Gets the fastest rate at which playback can happen
    /// </summary>
    /// <param name="eDirection">
    ///     Indicates playback direction for this query.
    ///     If MFRATE_FORWARD, then *pflRate will be set to the fastest
    ///     positive rate supported.
    ///     If MFRATE_REVERSE, then *pflRate will be set to the fastest
    ///     negative rate (by absolute value) supported.
    /// </param>
    /// <param name="fThin">
    ///     If TRUE, then *pflRate will be set to the fastest rate at
    ///     which thinning will occur.
    /// </param>
    /// <param name="pflRate">
    ///     Pointer to a variable to receive the fastest rate supported.
    /// </param>
    /// <returns>
    ///     <para>
    ///         MF_E_REVERSE_UNSUPPORTED
    ///         Returned by components that do not support reverse
    ///         playback when fForwardPlayback is FALSE.
    ///     </para>
    ///     <para>
    ///         MF_E_THINNING_UNSUPPORTED
    ///         Returned by components that cannot thin streams or handle
    ///         thinned streams when fThin is TRUE.
    ///     </para>
    /// </returns>
    /// <remarks>
    ///     <para>
    ///         If 0 is returned in *pflRate, that does not guarantee that
    ///         rate 0 is supported; the caller must do a separate
    ///         IsRateSupported query to determine that.
    ///         Otherwise, *pflRate can be assumed to be supported.
    ///     </para>
    ///     <para>
    ///         "Thinning" is defined in a format-specific manner.
    ///         For some formats (such as ASF), thinning will mean dropping
    ///         all frames that are not I-frames.
    ///         If the component produces stream data (like a Media Source
    ///         or a demultiplexer), it should pay attention
    ///         to the fThin argument and return MF_E_THINNING_UNSUPPORTED
    ///         if it cannot thin the stream.
    ///         If the component processes or receives a stream (like
    ///         most transforms or Media Sinks), it may ignore this
    ///         parameter if it does not care whether the stream is thinned.
    ///         In the Media Session's implementation of rate support,
    ///         if the transforms do not explicitly support reverse playback,
    ///         the Media Session will attempt to do reverse playback in
    ///         thinned mode (but will not do so unthinned).
    ///         Therefore, most applications will set fThin to TRUE
    ///         when using the Media Session for reverse playback.
    ///     </para>
    /// </remarks>
    HRESULT GetFastestRate(
        [in]  MFRATE_DIRECTION eDirection,
        [in]  BOOL fThin,
        [out] float* pflRate
        );

    /// <summary>
    ///     Queries whether a rate is supported by the component.
    /// </summary>
    /// <param name="fThin">
    ///     If TRUE, then the query concerns support of a thinned stream
    ///     at the flRate.
    ///     If FALSE, then the query concerns an unthinned stream.
    /// </param>
    /// <param name="flRate">
    ///     Rate for which support is being queried
    /// </param>
    /// <param name="pflNearestSupportedRate">
    ///     Optional; may be NULL.
    ///     If non-NULL and flRate is unsupported, the value returned
    ///     should be the nearest rate that is supported (in the same direction
    ///     of flRate) given the value specified for fThin.
    ///     (In the success case, it will be set to flRate.)
    ///     This return value is useful for components that support
    ///     several discrete rates.
    ///     If there are supported rates on either side of flRate,
    ///     then whichever is closer to flRate is the one that is returned.
    /// </param>
    /// <returns>
    ///     <para>
    ///         MF_E_UNSUPPORTED_RATE:
    ///         Rate is not supported
    ///     </para>
    ///     <para>
    ///         MF_E_REVERSE_UNSUPPORTED
    ///         Returned by components that do not support reverse
    ///         playback when fForwardPlayback is FALSE.
    ///     </para>
    ///     <para>
    ///         MF_E_THINNING_UNSUPPORTED
    ///         Returned by components that cannot thin streams or handle
    ///         thinned streams when fThin is TRUE.
    ///     </para>
    /// </returns>
    /// <remarks>
    ///     <para>
    ///         The Media Foundation pipeline will pay attention to the
    ///         value returned in pflNearestSupportedRate for Media Sources
    ///         only; this value will be ignored coming from Transforms
    ///         or Media Sinks.
    ///     </para>
    ///     <para>
    ///         "Thinning" is defined in a format-specific manner.
    ///         For some formats (such as ASF), thinning will mean dropping
    ///         all frames that are not I-frames.
    ///         If the component produces stream data (like a Media Source
    ///         or a demultiplexer), it should pay attention
    ///         to the fThin argument and return MF_E_THINNING_UNSUPPORTED
    ///         if it cannot thin the stream.
    ///         If the component processes or receives a stream (like
    ///         most transforms or Media Sinks), it may ignore this
    ///         parameter if it does not care whether the stream is thinned.
    ///         In the Media Session's implementation of rate support,
    ///         if the transforms do not explicitly support reverse playback,
    ///         the Media Session will attempt to do reverse playback in
    ///         thinned mode (but will not do so unthinned).
    ///         Therefore, most applications will set fThin to TRUE
    ///         when using the Media Session for reverse playback.
    ///     </para>
    /// </remarks>
    HRESULT IsRateSupported(
        [in]  BOOL fThin,
        [in]  float flRate,
        [in, out, unique] float *pflNearestSupportedRate
        );

};

//
// This service GUID should be passed to the component's implementation
// of IMFGetService::GetService to obtain the IMFRateSupport and
// IMFRateControl services
//
cpp_quote( "EXTERN_GUID( MF_RATE_CONTROL_SERVICE, 0x866fa297, 0xb802, 0x4bf8, 0x9d, 0xc9, 0x5e, 0x3b, 0x6a, 0x9f, 0x53, 0xc9);" )


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(88ddcd21-03c3-4275-91ed-55ee3929328f),
    pointer_default(unique)
]
/// <summary>
///     IMFRateControl is used to notify components of a rate change.
///     This interface is obtained from the component via
///     IMFGetService::GetService using the MF_RATE_CONTROL_SERVICE
///     service GUID.
///     The Media Session provides IMFRateControl.
///     Media Sources and Transforms may provide IMFRateControl.
///     If they do, they will be notified of rate changes.
///     Media Sinks should not provide IMFRateControl; instead, they
///     will be notified of rate changes via IMFClockStateSink::OnClockSetRate.
/// </summary>
interface IMFRateControl : IUnknown
{
    /// <summary>
    ///     Sets the rate on the component.
    /// </summary>
    /// <param name="fThin">
    ///     A value of TRUE means that the stream will be thinned.
    ///     For Media Sources and demultiplexers, this is an indication
    ///     that the component should thin the stream.
    ///     For downstream Transforms, this is an indication that
    ///     the stream will be thinned.
    ///     A value of FALSE means that the stream is not to be thinned.
    /// <param name="flRate">
    ///     New rate
    /// </param>
    /// <returns>
    ///     <para>
    ///         MF_E_UNSUPPORTED_RATE_TRANSITION:
    ///         The component cannot transition from the current rate
    ///         to flRate while in the playing state.
    ///     </para>
    ///     <para>
    ///         MF_E_UNSUPPORTED_RATE:
    ///         flRate is not supported
    ///     </para>
    ///     <para>
    ///         MF_E_REVERSE_UNSUPPORTED:
    ///         Reverse rates are unsupported
    ///     </para>
    ///     <para>
    ///         MF_E_THINNING_UNSUPPORTED
    ///         Returned by components that cannot thin streams or handle
    ///         thinned streams when fThin is TRUE.
    ///     </para>
    /// </returns>
    /// <remarks>
    ///     <para>
    ///         SetRate may fail with MF_E_UNSUPPORTED_RATE even though
    ///         a previous call to IMFRateSupport::IsRateSupported
    ///         succeeded for that rate.  This is because components
    ///         can dynamically change which rates are supported.
    ///     </para>
    ///     <para>
    ///         SetRate is an asynchronous call for the Media Session
    ///         and Media Sources.
    ///         How the rate change is completed depends on the component:
    ///         <para>
    ///             The Media Session will send MESessionRateChanged.
    ///         </para>
    ///         <para>
    ///             Media Sources will send MESourceRateChanged.
    ///         </para>
    ///         <para>
    ///             The Presentation Clock will notify all subscribed
    ///             clock state sinks via IMFClockStateSinks::OnClockSetRate,
    ///             and the Stream Sinks should send the
    ///             MEStreamSinkRateChanged event.
    ///         </para>
    ///     </para>
    ///     <para>
    ///         If SetRate is called on an object that is in the running state,
    ///         the rate change should proceed as soon as possible.
    ///         If SetRate is called on an object that is in a non-running
    ///         state, the new rate should be used next time the component
    ///         enters the running state.
    ///     </para>
    ///     <para>
    ///         "Thinning" is defined in a format-specific manner.
    ///         For some formats (such as ASF), thinning will mean dropping
    ///         all frames that are not I-frames.
    ///         If the component produces stream data (like a Media Source
    ///         or a demultiplexer), it should pay attention
    ///         to the fThin argument and return MF_E_THINNING_UNSUPPORTED
    ///         if it cannot thin the stream.
    ///         If the component processes or receives a stream (like
    ///         most transforms or Media Sinks), it may ignore this
    ///         parameter if it does not care whether the stream is thinned.
    ///         In the Media Session's implementation of rate support,
    ///         if the transforms do not explicitly support reverse playback,
    ///         the Media Session will attempt to do reverse playback in
    ///         thinned mode (but will not do so unthinned).
    ///         Therefore, most applications will set fThin to TRUE
    ///         when using the Media Session for reverse playback.
    ///     </para>
    /// </remarks>
    HRESULT SetRate(
        [in]    BOOL fThin,
        [in]    float flRate
        );

    /// <summary>
    ///     Queries the component's current rate
    /// </summary>
    /// <param name="pfThin">
    ///     Optional; may be NULL.
    ///     Pointer to a variable whose value will indicate whether
    ///     the stream is being thinned.
    ///     Implementations that do not understand thinning should set
    ///     this value to FALSE.
    /// </param>
    /// <param name="pflRate">
    ///     Pointer to a variable to receive the current rate
    /// </param>
    HRESULT GetRate(
        [in, out, unique]   BOOL *pfThin,
        [in, out, unique]   float *pflRate
        );
};

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
[
    object,
    uuid(ab9d8661-f7e8-4ef4-9861-89f334f94e74),
    local
]
/// <summary>
///     IMFTimecodeTranslate interface is used to convert SMPTE timecodes to and from hundered nanoseconds units.
/// </summary>
interface IMFTimecodeTranslate : IUnknown
{
    /// <summary>
    ///     Converts SMPTE Timecode to hunderd nanoseconds
    /// </summary>
    HRESULT BeginConvertTimecodeToHNS(
        [in] const PROPVARIANT *pPropVarTimecode,
        [in] IMFAsyncCallback *pCallback,
        [in] IUnknown *punkState
        );

    HRESULT EndConvertTimecodeToHNS(
        [in] IMFAsyncResult *pResult,
        [out] MFTIME *phnsTime
        );

    HRESULT BeginConvertHNSToTimecode(
        [in] MFTIME hnsTime,
        [in] IMFAsyncCallback *pCallback,
        [in] IUnknown *punkState
        );

    HRESULT EndConvertHNSToTimecode(
        [in] IMFAsyncResult *pResult,
        [out] PROPVARIANT *pPropVarTimecode
        );
};

//
// This service GUID should be passed to the component's implementation
// of IMFGetService::GetService to obtain the IMFTimecodeTranslate service
//
cpp_quote( "EXTERN_GUID( MF_TIMECODE_SERVICE, 0xa0d502a7, 0x0eb3, 0x4885, 0xb1, 0xb9, 0x9f, 0xeb, 0x0d, 0x08, 0x34, 0x54 );" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(089EDF13-CF71-4338-8D13-9E569DBDC319)
]
/// <summary>
///     This interface is used to set the application's session audio volume through Media Foundation.
///     It can be obtained via IMFGetService.
/// </summary>
interface IMFSimpleAudioVolume : IUnknown
{
    HRESULT SetMasterVolume(
        [in] float fLevel
        );

    HRESULT GetMasterVolume(
        [out] float *pfLevel
        );

    HRESULT SetMute(
        [in] const BOOL bMute
        );

    HRESULT GetMute(
        [out] BOOL *pbMute
        );
}
//
// Use this service GUID to retrieve IMFSimpleAudioVolume through
// IMFGetService::GetService
//
cpp_quote( "EXTERN_GUID( MR_POLICY_VOLUME_SERVICE, 0x1abaa2ac, 0x9d3b, 0x47c6, 0xab, 0x48, 0xc5, 0x95, 0x6, 0xde, 0x78, 0x4d);" )

[
    object,
    uuid(76B1BBDB-4EC8-4f36-B106-70A9316DF593)
]
/// <summary>
///     This interface is used to set the stream audio volume through Media Foundation.
///     The IMFSimpleAudioVolume is the recommended way for Media Foundation applications
///     to control audio volume; however, this volume interface is provided for special cases
///     where an application needs to control the volume of an individual audio stream without
///     affecting the overall application volume.
///     It is implemented on the Streaming Audio Renderer sink (SAR) and is obtained via IMFGetService.
/// </summary>
interface IMFAudioStreamVolume : IUnknown
{
    HRESULT GetChannelCount(
        [out] UINT32 *pdwCount
        );

    HRESULT SetChannelVolume(
        [in] UINT32 dwIndex,
        [in] const float fLevel
        );

    HRESULT GetChannelVolume(
        [in] UINT32 dwIndex,
        [out] float *pfLevel
        );

    HRESULT SetAllVolumes(
        [in] UINT32 dwCount,
        [in, size_is(dwCount)] const float *pfVolumes
        );

    HRESULT GetAllVolumes(
        [in] UINT32 dwCount,
        [out, size_is(dwCount)] float *pfVolumes
        );
}
//
// Use this service GUID to retrieve IMFAudioStreamVolume through
// IMFGetService::GetService
//
cpp_quote( "EXTERN_GUID( MR_STREAM_VOLUME_SERVICE, 0xf8b5fa2f, 0x32ef, 0x46f5, 0xb1, 0x72, 0x13, 0x21, 0x21, 0x2f, 0xb2, 0xc4);" )

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(a0638c2b-6465-4395-9ae7-a321a9fd2856),
    local
]
/// <summary>
///     This interface is used to set the audio policy through Media Foundation.
///     It can be obtained via IMFGetService.
/// </summary>
interface IMFAudioPolicy : IUnknown
{
    HRESULT SetGroupingParam(
                [in] REFGUID rguidClass
                );
    HRESULT GetGroupingParam(
                [out, annotation("__out")] GUID *pguidClass
                );
    HRESULT SetDisplayName(
                [in] LPCWSTR pszName
                );
    HRESULT GetDisplayName(
                [out, annotation("__deref_out")] LPWSTR *pszName
                );
    HRESULT SetIconPath(
                [in] LPCWSTR pszPath
                );
    HRESULT GetIconPath(
                [out, annotation("__deref_out")] LPWSTR *pszPath
                );
};

//
// Use this service GUID to retrieve IMFAudioPolicy through
// IMFGetService::GetService
//
cpp_quote( "EXTERN_GUID( MR_AUDIO_POLICY_SERVICE, 0x911fd737, 0x6775, 0x4ab0, 0xa6, 0x14, 0x29, 0x78, 0x62, 0xfd, 0xac, 0x88);" )

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
[
    object,
    uuid(8C7B80BF-EE42-4b59-B1DF-55668E1BDCA8),
    local
]
interface IMFSampleGrabberSinkCallback : IMFClockStateSink
{
    //
    // Presentation Clock Setting
    //
    HRESULT OnSetPresentationClock(
        [in] IMFPresentationClock* pPresentationClock
        );

    //
    // Process Sample
    //
    HRESULT OnProcessSample(
        [in] REFGUID guidMajorMediaType,
        [in] DWORD dwSampleFlags,
        [in] LONGLONG llSampleTime,
        [in] LONGLONG llSampleDuration,
        [in, annotation("__in_bcount(dwSampleSize)")] const BYTE * pSampleBuffer,
        [in] DWORD dwSampleSize
        );

    //
    // Shutdown
    //
    HRESULT OnShutdown();
}

cpp_quote( "STDAPI" )
cpp_quote( "MFCreateSampleGrabberSinkActivate(" )
cpp_quote( "    IMFMediaType *pIMFMediaType,")
cpp_quote( "    IMFSampleGrabberSinkCallback* pIMFSampleGrabberSinkCallback," )
cpp_quote( "    __out IMFActivate** ppIActivate" )
cpp_quote( "    );" )

//
// Sample Grabber Sink Activate Attributes
//
// MF_SAMPLEGRABBERSINK_SAMPLE_TIME_OFFSET
// Data type: UINT64
// The MF_SAMPLEGRABBERSINK_SAMPLE_TIME_OFFSET value will be subtracted from the sample time when the Sample Grabber Sink
// is deciding when to present the sample (via the Sample Grabber Sink Callback.)  The Sample Grabber Sink will not modify
// the original time stamp in the sample. This attribute is used to have the Sample Grabber Sink send samples before the
// presentation clock has reached the sample time.
// The units of this attribute are in 100 NS (MFTime).
// If this attribute is not present, a value of 0 is used.
cpp_quote( "EXTERN_GUID( MF_SAMPLEGRABBERSINK_SAMPLE_TIME_OFFSET, 0x62e3d776, 0x8100, 0x4e03, 0xa6, 0xe8, 0xbd, 0x38, 0x57, 0xac, 0x9c, 0x47);" )

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
// MF_SAMPLEGRABBERSINK_IGNORE_CLOCK
// Data type: BOOL (UINT32)
// Typically, the sample grabber sink will push out samples based upon the current presentation time.  This can result
// in delays for clients that do not need sample output to be synchronized with the presentation clock.  To ignore
// the clock and have the sample grabber sink push out samples as fast as possible, set this attribute to 1.
cpp_quote( "EXTERN_GUID( MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, 0x0efda2c0, 0x2b69, 0x4e2e, 0xab, 0x8d, 0x46, 0xdc, 0xbf, 0xf7, 0xd2, 0x5d);" )

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
[
    object,
    uuid(ca86aa50-c46e-429e-ab27-16d6ac6844cb),
    local
]
/// <summary>
///     The IMFSampleGrabberSinkCallback2 is used by the MF SampleGrabberSink to deliver samples to the implementer of this interface.
/// </summary>
/// <remarks>
///     Since this interface inherits from IMFSampleGrabberSinkCallback, the SampleGrabberSink (SGS) will attempt to QI for the IMFSampleGrabberSinkCallback2 interface.
///     If it finds the IMFSampleGrabberSinkCallback2 interface, then the SGS will ONLY deliver samples via the IMFSampleGrabberSinkCallback2::OnProcessSampleEx(...) method
///     and never use the IMFSampleGrabberSinkCallback::OnProcessSample(...) method.  However, if the callback object used to create the SGS only implements the
///     IMFSampleGrabberSinkCallback interface, then the SGS will naturally use the IMFSampleGrabberSinkCallback::OnProcessSample(...) to deliver the samples.
/// </remarks>
interface IMFSampleGrabberSinkCallback2 : IMFSampleGrabberSinkCallback
{
    /// <summary>
    ///     The OnProcessSampleEx method is called by the SampleGrabberSink to deliver samples.
    /// </summary>
    /// <param name=guidMajorMediaType>
    ///     The major GUID type of the sample being delivered
    /// </param>
    /// <param name=dwSampleFlags>
    ///     The sample flags of the sample being delivered
    /// </param>
    /// <param name=llSampleTime>
    ///     The timestamp in HNS units of the sample being delivered
    /// </param>
    /// <param name=llSampleDuration>
    ///     The duration in HNS units of the sample being delivered
    /// </param>
    /// <param name=pSampleBuffer>
    ///     A byte pointer to the sample data
    /// </param>
    /// <param name=dwSampleSize>
    ///     The size in bytes of the data pointed to by the pSampleBuffer argument.
    /// </param>
    /// <param name=pAttributes>
    ///     IMFAttributes pointer that allows the retrieval of the sample attributes
    /// </param>
    HRESULT OnProcessSampleEx(
        [in] REFGUID guidMajorMediaType,
        [in] DWORD dwSampleFlags,
        [in] LONGLONG llSampleTime,
        [in] LONGLONG llSampleDuration,
        [in, annotation("__in_bcount(dwSampleSize)")] const BYTE * pSampleBuffer,
        [in] DWORD dwSampleSize,
        [in, annotation("__in")] IMFAttributes* pAttributes
        );

}
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////


cpp_quote( "EXTERN_GUID( MF_QUALITY_SERVICES, 0xb7e2be11, 0x2f96, 0x4640, 0xb5, 0x2c, 0x28, 0x23, 0x65, 0xbd, 0xf1, 0x6c);" )


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
   object,
   uuid(35FE1BB8-A3A9-40fe-BBEC-EB569C9CCCA3),
]
/// <summary>
///     The IMFWorkQueueServices can be obtained from the session by querying
///     for the MF_WORKQUEUE_SERVICES service
/// </summary>
/// <remarks>
///     This interface allows applications to control
///     both platform and topology workqueues
/// </remarks>
interface IMFWorkQueueServices : IUnknown
{
    /// <summary>
    ///     The BeginRegisterTopologyWorkQueuesWithMMCSS method parses
    ///     the topology nodes and registers the assigned workqueues
    ///     with the appropriate MMCSS classes
    /// </summary>
    /// <param name=pCallback>
    ///     Standard callback used for async operations in MF
    /// </param>
    /// <param name=pState>
    ///     Standard state used for async operations in MF
    /// </param>
    [local]
    HRESULT BeginRegisterTopologyWorkQueuesWithMMCSS(
        [in] IMFAsyncCallback * pCallback,
        [in] IUnknown * pState );

    [call_as(BeginRegisterTopologyWorkQueuesWithMMCSS)]
    HRESULT RemoteBeginRegisterTopologyWorkQueuesWithMMCSS(
        [in] IMFRemoteAsyncCallback * pCallback );

    /// <summary>
    ///     The EndRegisterTopologyWorkQueuesWithMMCSS method is called
    ///     by the application when all the WorkQueues of the current topology
    ///     have been registered with MMCSS
    /// </summary>
    /// <param name=pResult>
    ///     Standard result passed to end MF async operations
    /// </param>
    [local]
    HRESULT EndRegisterTopologyWorkQueuesWithMMCSS(
        [in] IMFAsyncResult * pResult );

    [call_as(EndRegisterTopologyWorkQueuesWithMMCSS)]
    HRESULT RemoteEndRegisterTopologyWorkQueuesWithMMCSS(
        [in] IUnknown * pResult );


    /// <summary>
    ///     The BeginUnregisterTopologyWorkQueuesWithMMCSS method unregisters
    ///     the assigned workqueues from MMCSS
    /// </summary>
    /// <param name=pCallback>
    ///     Standard callback used for async operations in MF
    /// </param>
    /// <param name=pState>
    ///     Standard state used for async operations in MF
    /// </param>
    [local]
    HRESULT BeginUnregisterTopologyWorkQueuesWithMMCSS(
        [in] IMFAsyncCallback * pCallback,
        [in] IUnknown * pState );

    [call_as(BeginUnregisterTopologyWorkQueuesWithMMCSS)]
    HRESULT RemoteBeginUnregisterTopologyWorkQueuesWithMMCSS(
        [in] IMFRemoteAsyncCallback * pCallback );


    /// <summary>
    ///     The EndUnregisterTopologyWorkQueuesWithMMCSS method is called
    ///     by the application when all the WorkQueues of the current topology
    ///     have been unregistered from MMCSS
    /// </summary>
    /// <param name=pResult>
    ///     Standard result passed to end MF async operations
    /// </param>
    [local]
    HRESULT EndUnregisterTopologyWorkQueuesWithMMCSS(
        [in] IMFAsyncResult * pResult );

    [call_as(EndUnregisterTopologyWorkQueuesWithMMCSS)]
    HRESULT RemoteEndUnregisterTopologyWorkQueuesWithMMCSS(
        [in] IUnknown * pResult );

    /// <summary>
    ///     Retrieves the MMCSS class string associated with
    ///     the given topology workqueue
    /// </summary>
    /// <param name=dwTopologyWorkQueueId>
    ///     Topology workqueue id for which the info will be returned
    /// </param>
    /// <param name=pwszClass>
    ///     Pointer to an array of WCHARs allocated by the caller
    /// </param>
    /// <param name=pcchClass>
    ///     Size, in number of characters, of the pwszClass array
    /// </param>
    HRESULT GetTopologyWorkQueueMMCSSClass(
        [in] DWORD dwTopologyWorkQueueId,
        [out, size_is( *pcchClass )] LPWSTR pwszClass,
        [in, out] DWORD * pcchClass );

    /// <summary>
    ///     Retrieves the MMCSS class string associated with
    ///     the given topology workqueue
    /// </summary>
    /// <param name=dwTopologyWorkQueueId>
    ///     Topology workqueue id for which the info will be returned
    /// </param>
    /// <param name=pdwTaskId>
    ///     Pointer to a buffer allocated by the caller
    ///     The workqueue's MMCSS task id will be filled in
    /// </param>
    HRESULT GetTopologyWorkQueueMMCSSTaskId(
        [in] DWORD dwTopologyWorkQueueId,
        [out] DWORD * pdwTaskId );

    /// <summary>
    ///     The BeginRegisterPlatformWorkQueueWithMMCSS method registers
    ///     the specified platform workqueue with MMCSS using the specified
    ///     class and taskId
    /// </summary>
    /// <param name=dwPlatformWorkQueue>
    ///     The id of one of the standard platform workqueues
    /// </param>
    /// <param name=wszClass>
    ///     The MMCSS class which the workqueue should be registered with
    /// </param>
    /// <param name=dwTaskId>
    ///     The task id which the workqueue should be registered to
    ///     If dwTaskId is 0, new MMCSS bucket will be created
    /// </param>
    /// <param name=pCallback>
    ///     Standard callback used for async operations in MF
    /// </param>
    /// <param name=pState>
    ///     Standard state used for async operations in MF
    /// </param>
    [local]
    HRESULT BeginRegisterPlatformWorkQueueWithMMCSS(
        [in] DWORD dwPlatformWorkQueue,
        [in] LPCWSTR wszClass,
        [in] DWORD dwTaskId,
        [in] IMFAsyncCallback * pCallback,
        [in] IUnknown * pState );

    [call_as(BeginRegisterPlatformWorkQueueWithMMCSS)]
    HRESULT RemoteBeginRegisterPlatformWorkQueueWithMMCSS(
        [in] DWORD dwPlatformWorkQueue,
        [in] LPCWSTR wszClass,
        [in] DWORD dwTaskId,
        [in] IMFRemoteAsyncCallback * pCallback );

    /// <summary>
    ///     The EndRegisterPlatformWorkQueueWithMMCSS method should be called
    ///     by the application when the platform workqueue has been registered with MMCSS
    /// </summary>
    /// <param name=pResult>
    ///     Standard result passed to end MF async operations
    /// </param>
    /// <param name=pdwTaskId>
    ///     This buffer will be filled with the TaskId of the specified workqueue
    /// </param>
    [local]
    HRESULT EndRegisterPlatformWorkQueueWithMMCSS(
        [in] IMFAsyncResult * pResult,
        [out, annotation("__out")] DWORD* pdwTaskId );

    [call_as(EndRegisterPlatformWorkQueueWithMMCSS)]
    HRESULT RemoteEndRegisterPlatformWorkQueueWithMMCSS(
        [in] IUnknown * pResult,
        [out] DWORD* pdwTaskId );

    /// <summary>
    ///     The BeginUnregisterPlatformWorkQueueWithMMCSS method unregisters
    ///     the specified platform workqueue from MMCSS
    /// </summary>
    /// <param name=dwPlatformWorkQueue>
    ///     The id of one of the standard platform workqueues
    /// </param>
    /// <param name=pCallback>
    ///     Standard callback used for async operations in MF
    /// </param>
    /// <param name=pState>
    ///     Standard state used for async operations in MF
    /// </param>
    [local]
    HRESULT BeginUnregisterPlatformWorkQueueWithMMCSS(
        [in] DWORD dwPlatformWorkQueue,
        [in] IMFAsyncCallback * pCallback,
        [in] IUnknown * pState );

    [call_as(BeginUnregisterPlatformWorkQueueWithMMCSS)]
    HRESULT RemoteBeginUnregisterPlatformWorkQueueWithMMCSS(
        [in] DWORD dwPlatformWorkQueue,
        [in] IMFRemoteAsyncCallback * pCallback );

    /// <summary>
    ///     The EndUnregisterPlatformWorkQueueWithMMCSS method should be called
    ///     by the application when the platform workqueue has been unregistered from MMCSS
    /// </summary>
    /// <param name=pResult>
    ///     Standard result passed to end MF async operations
    /// </param>
    [local]
    HRESULT EndUnregisterPlatformWorkQueueWithMMCSS(
        [in] IMFAsyncResult * pResult );

    [call_as(EndUnregisterPlatformWorkQueueWithMMCSS)]
    HRESULT RemoteEndUnregisterPlatformWorkQueueWithMMCSS(
        [in] IUnknown * pResult );

    /// <summary>
    ///     Retrieves the MMCSS class string associated with
    ///     the given platform workqueue
    /// </summary>
    /// <param name=dwPlatformWorkQueueId>
    ///     Topology workqueue id for which the info will be returned
    /// </param>
    /// <param name=pwszClass>
    ///     Pointer to an array of WCHARs allocated by the caller
    /// </param>
    /// <param name=pcchClass>
    ///     Size, in number of characters, of the pwszClass array
    /// </param>
    HRESULT GetPlaftormWorkQueueMMCSSClass(
        [in] DWORD dwPlatformWorkQueueId,
        [out, size_is( *pcchClass )] LPWSTR pwszClass,
        [in, out] DWORD * pcchClass );

    /// <summary>
    ///     Retrieves the MMCSS class string associated with
    ///     the given platform workqueue
    /// </summary>
    /// <param name=dwPlatformWorkQueueId>
    ///     Topology workqueue id for which the info will be returned
    /// </param>
    /// <param name=pdwTaskId>
    ///     Pointer to a buffer allocated by the caller
    ///     The workqueue's MMCSS task id will be filled in
    /// </param>
    HRESULT GetPlatformWorkQueueMMCSSTaskId(
        [in] DWORD dwPlatformWorkQueueId,
        [out] DWORD * pdwTaskId );
};

// {8e37d489-41e0-413a-9068-287c886d8dda}
cpp_quote( "EXTERN_GUID( MF_WORKQUEUE_SERVICES, 0x8e37d489, 0x41e0, 0x413a, 0x90, 0x68, 0x28, 0x7c, 0x88, 0x6d, 0x8d, 0xda);" )


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
// Media Foundation Quality Management
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

typedef enum _MF_QUALITY_DROP_MODE
{
    MF_DROP_MODE_NONE = 0x0,
    MF_DROP_MODE_1 = 0x1,
    MF_DROP_MODE_2 = 0x2,
    MF_DROP_MODE_3 = 0x3,
    MF_DROP_MODE_4 = 0x4,
    MF_DROP_MODE_5 = 0x5,
    MF_NUM_DROP_MODES = 0x6 // Helper value, indicates the # of drop modes supported.
} MF_QUALITY_DROP_MODE;


typedef enum _MF_QUALITY_LEVEL
{
    MF_QUALITY_NORMAL = 0x0,
    MF_QUALITY_NORMAL_MINUS_1 = 0x1,
    MF_QUALITY_NORMAL_MINUS_2 = 0x2,
    MF_QUALITY_NORMAL_MINUS_3 = 0x3,
    MF_QUALITY_NORMAL_MINUS_4 = 0x4,
    MF_QUALITY_NORMAL_MINUS_5 = 0x5,
    MF_NUM_QUALITY_LEVELS = 0x6 // Helper value, indicates the # of quality levels supported.
} MF_QUALITY_LEVEL;

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")

typedef enum _MF_QUALITY_ADVISE_FLAGS
{
    MF_QUALITY_CANNOT_KEEP_UP = 0x1,
} MF_QUALITY_ADVISE_FLAGS;

cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")


///////////////////////////////////////////////////////////////////////////////
[
    object,
    uuid(8D009D86-5B9F-4115-B1FC-9F80D52AB8AB),
    local
]
/// <summary>
///     Generic interface which 3rd party quality managers will need to
///     support. They will get a topology and a clock.
/// </summary>
interface IMFQualityManager : IUnknown
{

    /// <summary>
    ///     The NotifyTopology method is called by the media processor to
    //      pass to the QM the topology that its about to use.
    /// </summary>
    /// <param name="pTopology">
    ///     Pointer to the topology about to be used by Media Processor.
    ///     Pass in NULL to inform the quality manager to release
    ///     references to the topology.
    /// </param>
    HRESULT NotifyTopology( [in] IMFTopology * pTopology );

    /// <summary>
    ///     The NotifyPresentationClock method is called by the
    ///     media processor to pass QM the presentation clock for the
    ///     current presentation.
    /// </summary>
    /// <param name="pClock">
    ///     Pointer to the clock that will be used for the current
    ///     presentation. Pass in NULL to inform the quality manager
    ///     to release references to the clock.
    /// </param>
    /// <remarks>
    ///     The quality manager may subscribe to the clock to be informed
    ///     of state changes, as well as the direction of playback
    ///     (forward or reverse) and the rate.
    /// </remarks>
    HRESULT NotifyPresentationClock( [in] IMFPresentationClock * pClock );

    /// <summary>
    ///     The NotifyProcessInput method is called when the media proc is
    ///     about to deliver a sample to a component
    /// </summary>
    /// <param name=pNode>
    ///     Pointer to the node media processor is about to deliver data to.
    /// </param>
    /// <param name=lInputIndex>
    ///     The index of the input on the node data is being fed to.
    /// </param>
    /// <param name=pSample>
    ///     Pointer to the sample about to be fed into the topology node.
    /// </param>
    /// <remarks>
    ///     This method is called for every sample passing through every
    ///     component.  To avoid increasing the steady state latency too much,
    ///     it needs to be as quick as possible.
    /// </remarks>
    HRESULT NotifyProcessInput(
        [in] IMFTopologyNode * pNode,
        [in] long lInputIndex,
        [in] IMFSample * pSample
        );

    /// <summary>
    ///     The NotifyProcessOutput method is called when the media proc
    ///     receives a sample from a component
    /// </summary>
    /// <param name=pNode>
    ///     Pointer to the node the media processor has received data from.
    /// </param>
    /// <param name=lOutputIndex>
    ///     The index of the output on the node data was produced from.
    /// </param>
    /// <param name=pSample>
    ///     Pointer to the sample that was produced by the topology node.
    /// </param>
    /// <remarks>
    ///     This method is called for every sample passing through every
    ///     component.  To avoid increasing the steady state latency too much,
    ///     it needs to be as quick as possible.
    /// </remarks>
    HRESULT NotifyProcessOutput(
        [in] IMFTopologyNode * pNode,
        [in] long lOutputIndex,
        [in] IMFSample * pSample
        );

    /// <summary>
    ///     This callback is made to the Quality manager by the pipeline in
    ///     response to the MEQualityNotify event.
    /// </summary>
    /// <param name=pObject>
    ///     Pointer to the Object from which the notification is coming in.
    ///     This is not the topo node. In case of MFTs this will be the MFT
    ///     specifed on the toponode. In the case of sinks this will be the
    ///     Media sink object itself.
    /// </param>
    /// <param name=pEvent>
    ///     The event pointer.
    /// </param>
    /// <remarks>
    ///     See data on the MEQualityNotify
    /// </remarks>
    HRESULT NotifyQualityEvent(
        [in] IUnknown * pObject,
        [in] IMFMediaEvent *pEvent );

    /// <summary>
    ///     Called when the session is being shutdown
    /// </summary>
    /// <remarks>
    ///     Releases references on pipeline components.
    /// </remarks>
    HRESULT Shutdown();
};

///////////////////////////////////////////////////////////////////////////////
/// <summary>
///     Creates the default MF Quality Manager.
/// </summary>
/// <param name="ppQualityManager">
///     A pointer to receive the MF Quality Manager.
/// </param>
/// <remarks>
///     A 3rd party can create the default MF Quality Manager using
///     this function. It could be used to sub-class its functionality.
/// </remarks>
cpp_quote( "STDAPI MFCreateStandardQualityManager(" )
cpp_quote( "    __out IMFQualityManager **ppQualityManager );" )

///////////////////////////////////////////////////////////////////////////////
//  GUIDs to go with MEQualityNotify
//
// {F6B44AF8-604D-46fe-A95D-45479B10C9BC}
cpp_quote( "EXTERN_GUID( MF_QUALITY_NOTIFY_PROCESSING_LATENCY, 0xf6b44af8, 0x604d, 0x46fe, 0xa9, 0x5d, 0x45, 0x47, 0x9b, 0x10, 0xc9, 0xbc );" )

// {30D15206-ED2A-4760-BE17-EB4A9F12295C}
cpp_quote( "EXTERN_GUID( MF_QUALITY_NOTIFY_SAMPLE_LAG, 0x30d15206, 0xed2a, 0x4760, 0xbe, 0x17, 0xeb, 0x4a, 0x9f, 0x12, 0x29, 0x5c );" )


///////////////////////////////////////////////////////////////////////////////
[
    object,
    uuid(EC15E2E9-E36B-4f7c-8758-77D452EF4CE7)
]
/// <summary>
///     Implemented by a component which can respond to quality adjustment requests from the Quality Manager.
/// </summary>
interface IMFQualityAdvise: IUnknown
{
    /// <param name="eDropMode">
    ///     The Quality Manager can request the component to go into a
    ///     particular drop mode. The component can define what it wants to do
    ///     for each drop level. See remarks section for some examples. MF
    ///     defines 6 drop modes: MF_DROP_MODE_NONE, MF_DROP_MODE_1,
    ///     MF_DROP_MODE_2, ... MF_DROP_MODE_5
    /// </param>
    /// <remarks>
    ///     As an example, consider a video decoder which supports 3 drop modes.
    ///     For example, if the content has 3 B-frames between each pair of
    ///     P-frames, the decoder might decide the following 3 drop modes:
    ///     -- Drop 1 B-frame for every 2 B-frames
    ///     -- Drop every alternate B-frame
    ///     -- Drop P-frames and go to key frame only mode
    ///
    ///     If the quality of playback is not improving over time the Quality Manager
    ///     might make the following calls to this video decoder:
    ///     -- SetDropMode( MF_DROP_MODE_NONE ). The decoder returns S_OK
    ///         and knows that it should decode all samples.
    ///     -- SetDropMode( MF_DROP_MODE_1 ). The decoder returns S_OK and
    ///         starts dropping 1 B-frame for every 2 B-frames.
    ///     -- SetDropMode( MF_DROP_MODE_2 ). The decoder returns S_OK and
    ///         starts dropping every alternate B-frame
    ///     -- SetDropMode( MF_DROP_MODE_3).
    ///     -- SetDropMode( MF_DROP_MODE_4). The decoder returns
    ///         MF_E_NO_MORE_DROP_MODES and start dropping P-frames. The
    ///         special return code tells the Quality Manager that there the
    ///         maximum drop mode is reached. The Quality Manager will not call
    ///         SetDropMode( MF_DROP_MODE_4) on this component.
    /// </remarks>
    ///  <returns>
    ///     If the method succeeds it returns S_OK. If the component has
    ///     reached its highest level of drop mode it should return
    ///     MF_E_NO_MORE_DROP_MODES. This indicates to the Quality Manager
    ///     that it cannot request any more drop modes from this component.
    ///  </returns>
    HRESULT SetDropMode(
            [in] MF_QUALITY_DROP_MODE eDropMode );

    /// <param name="eQualityLevel">
    ///     The Quality Manager can request the component to reduce its output
    ///     to a particular quality level. The component can define what it wants
    ///     to do for each quality level. See remarks section for some examples.
    ///     MF defines 6 quality levels: MF_QUALITY_NORMAL,
    ///     MF_QUALITY_NORMAL_MINUS_1, MF_QUALITY_NORMAL_MINUS_2,
    ///     ... MF_QUALITY_NORMAL_MINUS_5.
    /// </param>
    /// <remarks>
    ///     As an example, consider a video decoder which has 4 steps in
    ///     post-processing of the decoded video. This decoder can drop these
    ///     post-processing steps to produce frames faster even though they are
    ///     at a lower quality.
    ///     If the quality of playback is not improving over time the QM might
    ///     make the following calls to this video decoder:
    ///     -- SetQualityLevel(MF_QUALITY_NORMAL). The decoder returns S_OK
    ///         and knows that it should use all the normal post processing steps.
    ///     -- SetQualityLevel (MF_QUALITY_NORMAL_MINUS_1). The decoder
    ///         returns S_OK and stops doing one of the post-processing steps.
    ///     -- SetQualityLevel (MF_QUALITY_NORMAL_MINUS_2). The decoder
    ///         returns S_OK and stops doing one of the post-processing steps.
    ///     -- ...
    ///     -- SetQualityLevel (MF_QUALITY_NORMAL_MINUS_4). The decoder
    ///         returns S_OK and stops doing one of the post-processing steps.
    ///     -- SetQualityLevel( MF_QUALITY_NORMAL_MINUS_5). The decoder returns
    ///         MF_E_NO_MORE_QUALITY_LEVELS. The special return code tells the
    ///         Quality Manager that the minimum level of quality has been
    ///         reached. The Quality Manager will not call
    ///         SetQualityLevel (MF_QUALITY_NORMAL_MINUS_5) on this component.
    /// </remarks>
    ///  <returns>
    ///     If the method succeeds it returns S_OK. If the component has
    ///     reached its lowest level of quality  it should return
    ///     MF_E_NO_MORE_QUALITY_LEVELS. This indicates to the
    ///     Quality Manager that it cannot request any more quality levels
    ///     below the currently requested level.
    ///  </returns>
    HRESULT SetQualityLevel(
            [in] MF_QUALITY_LEVEL eQualityLevel );

    /// <param name="peDropMode">
    ///     The current Drop mode is returned by the component.
    /// </param>
midl_pragma warning (disable: 2495)
    HRESULT GetDropMode(
            [out, annotation("__out")] MF_QUALITY_DROP_MODE *peDropMode );
midl_pragma warning (default: 2495)

    /// <param name="peQualityLevel">
    ///     The current quality level is returned by the component.
    /// </param>
midl_pragma warning (disable: 2495)
    HRESULT GetQualityLevel(
            [out, annotation("__out")] MF_QUALITY_LEVEL *peQualityLevel );
midl_pragma warning (default: 2495)

    /// <param name="hnsAmountToDrop">
    ///     The component should drop samples covering the time interval
    ///     hnsDropTime.
    /// </param>
    /// <remarks>
    ///     This is to get A/V back in sync once we are already out of sync.
    ///     If video is already late by 30 ms, adjusting the quality on the
    ///     video will not help. The quality will go down but that does not
    ///     mean rendering will catch up. In such a scenario we will ask the
    ///     EVR to DropTime( 30 ms ), indicating that it should drop 30 ms
    ///     of data to quickly catch up. This functionality might not make
    ///     sense for the decoder, the decoder can just return an error
    ///     from this call.
    ///
    ///     If DropTime is called multiple times, the hnsAmountToDrop value is
    ///     absolute. The renderer should not add/aggregate the
    ///     hnsAmountToDrop value from subsequent calls.
    ///
    ///	    The caller can give a DropTime value of zero to ask the component
    ///	    to come out of its DropTime mode.
    /// </remarks>
    ///  <returns>
    ///     S_OK on success. MF_E_DROPTIME_NOT_SUPPORTED if the
    ///     component does not support drop time.
    ///  </returns>
    HRESULT DropTime(
            [in] LONGLONG hnsAmountToDrop );
};

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")

///////////////////////////////////////////////////////////////////////////////
[
    object,
    uuid(F3706F0D-8EA2-4886-8000-7155E9EC2EAE)
]
/// <summary>
///     Implemented by a component which can respond to quality notifications from the Quality Manager
///     and wants to manage its quality parameters itself
/// </summary>
interface IMFQualityAdvise2: IMFQualityAdvise
{
    /// <summary>
    ///     This callback is made to the component by the Quality manager in
    ///     response to the MEQualityNotify event from the sink.
    /// </summary>
    /// <param name=pEvent>
    ///     The event pointer.
    /// </param>
    /// <param name=pdwFlags>
    ///     Flags specifying the state of the component.
    ///     See the enumeration MF_QUALITY_ADVISE_FLAGS.
    /// </param>
    /// <remarks>
    ///     See data on the MEQualityNotify
    /// </remarks>
    HRESULT NotifyQualityEvent(
        [in]  IMFMediaEvent *pEvent,
        [out] DWORD *pdwFlags);
};

///////////////////////////////////////////////////////////////////////////////
[
    object,
    uuid(dfcd8e4d-30b5-4567-acaa-8eb5b7853dc9)
]
/// <summary>
///     Reports back the maximum drop and minimum quality levels
/// </summary>
interface IMFQualityAdviseLimits: IUnknown
{
    /// <param name="peDropMode">
    ///     The current Drop mode is returned by the component.
    /// </param>
midl_pragma warning (disable: 2495)
    HRESULT GetMaximumDropMode(
            [out, annotation("__out")] MF_QUALITY_DROP_MODE *peDropMode );
midl_pragma warning (default: 2495)

    /// <param name="peQualityLevel">
    ///     The current quality level is returned by the component.
    /// </param>
midl_pragma warning (disable: 2495)
    HRESULT GetMinimumQualityLevel(
            [out, annotation("__out")] MF_QUALITY_LEVEL *peQualityLevel );
midl_pragma warning (default: 2495)
};
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

///////////////////////////////////////////////////////////////////////////////

[
   object,
   uuid(2347D60B-3FB5-480c-8803-8DF3ADCD3EF0),
   local
]
/// <summary>
///     Implemented by components who spin off new threads and need to enlist
///     these threads in MMCSS in the same group with the rest of MF threads.
/// </summary>
interface IMFRealTimeClient : IUnknown
{
    /// <summary>
    ///     This method is called by MF when the RT operations start.
    ///     Implementation uses this data for enlisting threads in MMCSS
    /// </summary>
    HRESULT RegisterThreads(
        [in] DWORD dwTaskIndex,
        [in] LPCWSTR wszClass );

    /// <summary>
    ///     This method is called by MF when the RT operations end
    ///     Implementation can deregister the threads now
    /// </summary>
    HRESULT UnregisterThreads( );

    /// <summary>
    ///     The application can ask the pipeline to run different branches of the topology
    ///     on different work queues. When the pipeline is using private workqueues it will
    ///     notify components on that brach about which work queue is being used through this
    ///     function.
    /// </summary>
    HRESULT SetWorkQueue(
        [in] DWORD dwWorkQueueId );
};


///////////////////////////////////////////////////////////////////////////////
//
// Media Foundation sequence playback interfaces
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

typedef DWORD MFSequencerElementId;
const DWORD MFSEQUENCER_INVALID_ELEMENT_ID = 0xffffffff;

typedef enum _MFSequencerTopologyFlags
{
    SequencerTopologyFlags_Last = 0x00000001,
} MFSequencerTopologyFlags;

[
    object,
    uuid(197CD219-19CB-4de1-A64C-ACF2EDCBE59E),
    local
]
/// <summary>
///     IMFSequencerSource allows the caller to queue multiple topologies for
///     rendering.
/// </summary>
interface IMFSequencerSource : IUnknown
{
    /// <summary>
    ///     AppendTopology adds a topology to the end of the queue of
    ///     topologies.
    /// </summary>
    /// <param name="pTopology">
    ///     Pointer to the topology to be queued. This pointer can be NULL.
    /// </param>
    /// <param name="dwFlags">
    ///     Combination of MFSequencerTopologyFlags.
    /// </param>
    /// <param name="pdwId">
    ///     Pointer to a variable to receive the sequencer element ID
    ///     that the sequencer assigns to this topology
    /// </param>
    /// <remarks>
    ///     Topologies are played by the sequencer in the order in which
    ///     they are queued up.
    ///     The application indicates that no more topologies will be queued
    ///     either by setting the SequencerTopologyFlags_Last flag or
    ///     by calling AppendTopology with a NULL pTopology.
    ///     It is important to tell the sequencer that there are no more
    ///     topologies coming. It uses this information to end playback
    ///     in the pipeline.  If the application does not indicate when
    ///     there are no more topologies to be queued, the sequencer will
    ///     wait for a new topology to be queued up even if it has finished
    ///     playing everything it currently has.
    /// </remarks>
    HRESULT AppendTopology(
                [in] IMFTopology *pTopology,
                [in] DWORD dwFlags,
                [out, annotation("__out")] MFSequencerElementId *pdwId );

    /// <summary>
    ///     Deletes topology by ID.
    /// </summary>
    /// <param name="dwId">
    ///     Sequencer element ID of the topology to delete
    /// </param>
    HRESULT DeleteTopology(
                [in] MFSequencerElementId dwId);

    /// <summary>
    ///     GetPresentationContext maps a Presentation Descriptor to
    ///     its associated sequencer element ID and topology.
    /// </summary>
    /// <param name="pPD>
    ///     Pointer to the Presentation Descriptor to map
    /// </param>
    /// <param name="pId">
    ///     Pointer to a variable that will receive the sequencer element
    ///     ID associated with pPD.
    /// </param>
    /// <param name="ppTopology">
    ///     Topology associated with this sequencer element
    ///     The return value can be NULL if sequencer has already switched to the next presentation
    /// </param>
    ///  <returns>
    ///     <para> S_OK: On success</para>
    ///     <para>
    ///         MF_S_SEQUENCER_CONTEXT_CANCELED : For a topology which was cancelled.
    ///         A cancelled topology is one which was prerolled but was then discarded because
    ///         of a change in the order of playback. When a topology is cancelled the user will
    ///         get events from the session when the topology is set, started, ended, etc. but the
    ///         topology will not process any data.
    ///     </para>
    ///  </returns>
    ///
    HRESULT GetPresentationContext(
                [in] IMFPresentationDescriptor* pPD,
                [out, optional, annotation("__out_opt")] MFSequencerElementId *pId,
                [out, optional, annotation("__out_opt")] IMFTopology **ppTopology );


    /// <summary>
    ///     UpdateTopology updates a topology in the queue
    /// </summary>
    /// <param name="dwId">
    ///     Sequencer element ID for this topology
    /// </param>
    /// <param name="pTopology">
    ///     Updated topology for this sequencer element.
    ///     Ignored unless SequencerTopologyMask_Topology is set in dwMask
    /// </param>
    HRESULT UpdateTopology(
                [in] MFSequencerElementId dwId,
                [in] IMFTopology *pTopology);

    /// <summary>
    ///     UpdateTopologyFlags updates a topology in the queue
    /// </summary>
    /// <param name="dwId">
    ///     Sequencer element ID for this topology
    /// </param>
    /// <param name="dwFlags">
    ///     Bitflags defined by MFSequencerTopologyFlags.
    ///     Ignored unless SequencerTopologyMask_Flags is set in dwMask
    /// </param>
    HRESULT UpdateTopologyFlags(
                [in] MFSequencerElementId dwId,
                [in] DWORD dwFlags);

};

//
// Sequencer constants
//

//
// MF_TIME_FORMAT_SEGMENT_OFFSET can be used as the pguidTimeFormat argument
// to IMFMediaSession::Start and IMFMediaSource::Start to indicate that
// playback should start at a given offset relative to a sequencer element.
// The associated PROPVARIANT can be created by calling
// MFCreateSequencerSegmentOffset.
//
cpp_quote( "EXTERN_GUID( MF_TIME_FORMAT_SEGMENT_OFFSET, 0xc8b8be77, 0x869c, 0x431d, 0x81, 0x2e, 0x16, 0x96, 0x93, 0xf6, 0x5a, 0x39 );" )

//
// Sequencer functions
//

/// <summary>
///     Creates a Sequencer Source
/// </summary>
/// <param name="pReserved">
///     MUST be NULL
/// </param>
/// <param name="pCallback">
///     Pointer to the callback interface. Can be NULL.
/// </param>
/// <param name="ppSequencer">
///     Returns pointer to a Sequencer.
/// </param>
cpp_quote( "STDAPI MFCreateSequencerSource(" )
cpp_quote( "    IUnknown *pReserved," )
cpp_quote( "    __out IMFSequencerSource **ppSequencerSource" )
cpp_quote( "    );" )

/// <summary>
///     Creates a start point for use in IMFMediaSession::Start and
///     IMFMediaSource::Start calls when the time format is
///     MF_TIME_FORMAT_SEGMENT_OFFSET
/// </summary>
/// <param name="dwId">
///     Sequencer element ID of the element in which to start
/// </param>
/// <param name="hnsOffset">
///     Time offset within the specified sequencer element
/// </param>
/// <param name="pvarSegmentOffset">
///     Pointer to receive the PROPVARIANT that should be used with Start()
///     calls
/// </param>
cpp_quote( "STDAPI MFCreateSequencerSegmentOffset(" )
cpp_quote( "    MFSequencerElementId dwId," )
cpp_quote( "    MFTIME hnsOffset," )
cpp_quote( "    __out PROPVARIANT *pvarSegmentOffset" )
cpp_quote( "    );" )

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
/// <summary>
///     Creates an aggregated IMFMediaSource from a list of input media sources
/// </summary>
/// <param name="pSourceCollection">
///     The collection of media sources to be aggregated. MUST be non-NULL.
/// </param>
/// <param name="ppAggSource">
///     Returns a pointer to the aggregated media source.
/// </param>
cpp_quote( "STDAPI MFCreateAggregateSource(" )
cpp_quote( "    __in IMFCollection *pSourceCollection," )
cpp_quote( "    __deref_out IMFMediaSource **ppAggSource" )
cpp_quote( "    );" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(0E1D6009-C9F3-442d-8C51-A42D2D49452F),
]
/// <summary>
///     IMFMediaSourceTopologyProvider is implemented by sequencer sources.
/// </summary>
interface IMFMediaSourceTopologyProvider : IUnknown
{
    /// <summary>
    ///     Maps an IMFPresentationDescriptor to an IMFTopology for
    ///     this Media Source
    /// </summary>
    /// <param name="pPresentationDescriptor">
    ///     Presentation Descriptor for which to obtain the topology.
    ///     This is generally obtained by obtaining the IMFMediaSource
    ///     interface pointer for this source and calling
    ///     IMFMediaSource::CreatePresentationDescriptor
    /// </param>
    /// <param name="ppTopology">
    ///     Pointer to a variable that will receive the IMFTopology
    ///     corresponding to pPresentationDescriptor.
    ///     The application should use this topology when it calls
    ///     IMFMediaSession::SetTopology.
    /// </param>
    HRESULT GetMediaSourceTopology(
        [in]  IMFPresentationDescriptor* pPresentationDescriptor,
        [out] IMFTopology** ppTopology
        );
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(0E1D600a-C9F3-442d-8C51-A42D2D49452F),
]
/// <summary>
///     IMFMediaSourcePresentationProvider is provided by sequencer sources
///     and is obtained via IMFGetService::GetService
/// </summary>
interface IMFMediaSourcePresentationProvider : IUnknown
{
    /// <summary>
    ///     The Media Foundation pipeline calls this method to notify the
    ///     Media Source that this presentation has hit its markout
    ///     (or markin, for reverse playback).
    ///     This is needed in the case of markout (markin for reverse)
    ///     because the Media Source may not know exactly where it should
    ///     end this segment to hit the specified markout.
    /// </summary>
    /// <param name="pPresentationDescriptor">
    ///     Presentation Descriptor for the presentation whose end we
    ///     have reached
    /// </param>

    HRESULT ForceEndOfPresentation(
        [in]  IMFPresentationDescriptor* pPresentationDescriptor
        );
}

//
// MF_SOURCE_PRESENTATION_PROVIDER_SERVICE is the service GUID for
// obtaining IMFMediaSourcePresentationProvider
//
cpp_quote( "EXTERN_GUID( MF_SOURCE_PRESENTATION_PROVIDER_SERVICE, 0xe002aadc, 0xf4af, 0x4ee5, 0x98, 0x47, 0x05, 0x3e, 0xdf, 0x84, 0x04, 0x26 );" )


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

//
// This structure is used in IMFTopologyNodeAttributeEditor::UpdateNodeAttributes.
// NodeId indicate which node's attributes to update.
//
typedef struct _MFTOPONODE_ATTRIBUTE_UPDATE
{
    TOPOID NodeId;
    GUID guidAttributeKey;
    MF_ATTRIBUTE_TYPE attrType;

    [switch_is(attrType)] [switch_type(DWORD)] union
    {
        [case(MF_ATTRIBUTE_UINT32)]

            UINT32 u32;

        [case(MF_ATTRIBUTE_UINT64)]

            UINT64 u64;

        [case(MF_ATTRIBUTE_DOUBLE)]

            double d;

        [default]
            ;
    } ;
} MFTOPONODE_ATTRIBUTE_UPDATE;

[
    object,
    uuid(676aa6dd-238a-410d-bb99-65668d01605a),
]
/// <summary>
///     IMFTopologyNodeAttributeEditor interface is exposed by pipeline to allow application to change
///     properties on the toponode objects during playback.
///     In the current implementation, the only supported property is MF_TOPONODE_MEDIASTOP.
///     Pipeline will ignore all other properties
/// </summary>
interface IMFTopologyNodeAttributeEditor : IUnknown
{
    /// <summary>
    ///     UpdateNodeAttributes makes one or more updates to
    ///     the attributes on various nodes in the topology
    /// </summary>
    /// <param name="TopoId">
    ///     Topology ID of the topology whose nodes' attributes
    ///     will be updated
    /// </param>
    /// <param name="cUpdates">
    ///     Number of elements in the array pUpdates
    /// </param>
    /// <param name="pUpdates">
    ///     Array of size cUpdates of MFSEQUENCER_NODE_ATTRIBUTE_UPDATE structures.
    ///     Each element indicates the node and the attribute to update.
    ///     IMFAttributes::SetItem will be called using guidAttributeKey
    ///     and the PROPVARIANT supplied
    /// </param>
    HRESULT UpdateNodeAttributes(
                [in] TOPOID TopoId,
                [in] DWORD cUpdates,
                [in, size_is(cUpdates)] MFTOPONODE_ATTRIBUTE_UPDATE * pUpdates);
};

//
// MF_TOPONODE_ATTRIBUTE_EDITOR_SERVICE is the service GUID for
// obtaining IMFTopologyNodeAttributeEditor
//
cpp_quote( "EXTERN_GUID( MF_TOPONODE_ATTRIBUTE_EDITOR_SERVICE, 0x65656e1a, 0x077f, 0x4472, 0x83, 0xef, 0x31, 0x6f, 0x11, 0xd5, 0x08, 0x7a );" )


///////////////////////////////////////////////////////////////////////////////
//
// Media Foundation network playback interfaces
//
///////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

typedef [public] struct _MF_LEAKY_BUCKET_PAIR
{
    DWORD dwBitrate;
    DWORD msBufferWindow;
}
MF_LEAKY_BUCKET_PAIR;

/// <summary>
///     The MFBYTESTREAM_BUFFERING_PARAMS structure is for passing the buffering parameters to the byte stream.
/// </summary>
typedef [public] struct _MFBYTESTREAM_BUFFERING_PARAMS
{
    /// <member name="cbTotalFileSize">
    ///     Total number of bytes in file, or -1 if unknown
    ///     Type: QWORD.
    /// </member>
    QWORD cbTotalFileSize;
    /// <member name="cbPlayableDataSize">
    ///     Number of bytes in Data Object, or -1 if unknown or N/A
    ///     Type: QWORD.
    /// </member>
    QWORD cbPlayableDataSize;
    /// <member name="prgBuckets">
    ///     Array of leaky buckets for various bitrates
    ///     Type: MF_LEAKY_BUCKET_PAIR.
    /// </member>
    MF_LEAKY_BUCKET_PAIR *prgBuckets;
    /// <member name="cBuckets">
    ///     Number of leaky buckets in array
    ///     Type: DWORD.
    /// </member>
    DWORD cBuckets;
    /// <member name="qwNetBufferingTime">
    ///     Network buffering time to add to any leaky bucket parameters, in 100ns
    ///     Type: QWORD.
    /// </member>
    QWORD qwNetBufferingTime;
    /// <member name="qwPlayDuration">
    ///     Seek requires downloading the data starting from the Key frame
    ///     This specifies the time duration,in 100ns, between the previous key frame
    ///     poistion and the seek point.
    ///     Type: QWORD.
    /// </member>
    QWORD qwExtraBufferingTimeDuringSeek;
    /// <member name="qwPlayDuration">
    ///     Duration of playable portion of file in 100ns, or 0 if unknown
    ///     Type: QWORD.
    /// </member>
    QWORD qwPlayDuration;
    /// <member name="dRate">
    ///     The rate of the playback
    ///     Type: FLOAT.
    /// </member>
    float dRate;
}
MFBYTESTREAM_BUFFERING_PARAMS;


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(6d66d782-1d4f-4db7-8c63-cb8c77f1ef5e),
    local
]
/// <summary>
///     The IMFByteStreamBuffering interface is for controlling the buffer on the byte stream
/// </summary>
interface IMFByteStreamBuffering : IUnknown
{
/// <summary>
///     The SetBufferingParams method is for setting the buffering parameters.
/// </summary>
/// <param name=pParams>
///     The input MFBYTESTREAM_BUFFERING_PARAMS.
/// </param>
    HRESULT SetBufferingParams(
        [in, annotation("__in")] MFBYTESTREAM_BUFFERING_PARAMS *pParams
        );

/// <summary>
///     The EnableBuffering method is for enabling/disabling the buffering on the byte stream
/// </summary>
/// <param name=fEnable>
///     BOOL flag indicating enable or disable the buffering.
/// </param>
    HRESULT EnableBuffering(
        [in] BOOL fEnable
        );

/// <summary>
///     If the byte stream is currently buffering, invoking this method will cause a MEBufferingStopped
///     event to be sent immediately, without waiting for the necessary data to be buffered.
///     Invoking this method while the byte stream is not buffering has no effect.
/// </summary>
    HRESULT StopBuffering();
};


//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(F5042EA4-7A96-4a75-AA7B-2BE1EF7F88D5),
    local
]
/// <summary>
///     This interface is exposed by byte streams that transfer data from
///     a remote resource to a local cache in the background. It allows the
///     application to have some control over the way the transfer happens.
/// </summary>
interface IMFByteStreamCacheControl : IUnknown
{
    /// <summary>
    ///     Instructs the byte stream to stop the background transfer to cache.
    ///     The byte stream resumes the transfer the next time the application
    ///     reads data.  The transfer is also resumed if buffering is enabled
    ///     using IMFByteStreamBuffering::EnableBuffering.
    /// </summary>
    HRESULT StopBackgroundTransfer();
};


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(5b87ef6a-7ed8-434f-ba0e-184fac1628d1),
    local
]
/// <summary>
///     The IMFNetCredential interface is used to set and retrieve the username
///     and password for authentication purposes.
/// </summary>
interface IMFNetCredential : IUnknown
{
/// <summary>
///  SetUser sets the user name of the credential.
/// <param name="pbData">
///  Pointer to a buffer containing a UNICODE string with the user name. The
///  object will make an encrypted copy of this data. If the data is already
///  encrypted, the application must set fDataIsEncrypted to TRUE. To encrypt
///  the data the application must use the CryptProtectData function from the
///  Platform SDK.
/// </param>
/// <param name="cbData">
///  Size, in bytes, of the data pointed by pbData. If the data is an
///  unencrypted string, this value must include the null terminator
///  of the string.
/// </param>
/// <param name="fEncrypted">
///  Boolean value that specifies if the data is already encrypted.
/// </param>
    HRESULT SetUser(
        [in, size_is(cbData), annotation("__in_bcount(cbData)")] BYTE * pbData,
        [in] DWORD cbData,
        [in] BOOL fDataIsEncrypted );


/// <summary>
///  SetPassword sets the password of the credential.
/// <param name="pbData">
///  Pointer to a buffer containing a UNICODE string with the password. The
///  object will make an encrypted copy of this data. If the data is already
///  encrypted, the application must set fDataIsEncrypted to TRUE. To encrypt
///  the data the application must use the CryptProtectData function from the
///  Platform SDK.
/// </param>
/// <param name="cbData">
///  Size, in bytes, of the data pointed by pbData. If the data is an
///  unencrypted string, this value must include the null terminator
///  of the string.
/// </param>
/// <param name="fEncrypted">
///  Boolean value that specifies if the data is already encrypted.
/// </param>
HRESULT SetPassword(
        [in, size_is(cbData), annotation("__in_bcount(cbData)")] BYTE * pbData,
        [in] DWORD cbData,
        [in] BOOL fDataIsEncrypted );

/// <summary>
///  GetUser retrieves the user name of this credential.
/// </summary>
/// <param name="pbData">
///  Pointer to the buffer that will receive the user name. If the application
///  sets the fEncryptData parameter to TRUE, the function will return the data
///  unencrypted as a UNICODE string format. If the application sets the
///  sets the fEncryptData parameter to FALSE, the function will return the data
///  encrypted. To unencrypt the data the application will have to use the
///  CryptUnprotectData function from the Platform SDK.
/// </param>
/// <param name="pcbData">
///  Pointer to a DWORD value that contains the size of the data buffer. Upon input,
///  the value contains the maximum size of the buffer. Upon return, the value contains
///  the number of bytes needed to hold the data, including the null terminator if the
///  data is returned unencrypted.
/// </param>
/// <param name="fEncryptData">
///  If this value is TRUE, the function will return the data encrypted, otherwise
///  it'll return the data unencrypted.
/// </param>
    HRESULT GetUser(
                [out, size_is(*pcbData), annotation("__out_ecount_part_opt(*pcbData,*pcbData)")] BYTE * pbData,
                [in, out, annotation("__inout")] DWORD * pcbData,
                [in] BOOL fEncryptData );


/// <summary>
///  GetPassword retrieves the user name of this credential.
/// </summary>
/// <param name="pbData">
///  Pointer to the buffer that will receive the password. If the application
///  sets the fEncryptData parameter to TRUE, the function will return the data
///  unencrypted as a UNICODE string format. If the application sets the
///  sets the fEncryptData parameter to FALSE, the function will return the data
///  encrypted. To unencrypt the data the application will have to use the
///  CryptUnprotectData function from the Platform SDK.
/// </param>
/// <param name="pcbData">
///  Pointer to a DWORD value that contains the size of the data buffer. Upon input,
///  the value contains the maximum size of the buffer. Upon return, the value contains
///  the number of bytes needed to hold the data, including the null terminator if the
///  data is returned unencrypted.
/// </param>
/// <param name="fEncryptData">
///  If this value is TRUE, the function will return the data encrypted, otherwise
///  it'll return the data unencrypted.
/// </param>
    HRESULT GetPassword(
                [out, size_is(*pcbData), annotation("__out_ecount_part_opt(*pcbData,*pcbData)")] BYTE * pbData,
                [in, out, annotation("__inout")] DWORD * pcbData,
                [in] BOOL fEncryptData );

/// <summary> LoggedOnUser returns TRUE if logged on credentials should be used. </summary>
    HRESULT LoggedOnUser( [out, annotation("__out")] BOOL *pfLoggedOnUser );
};


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(5b87ef6b-7ed8-434f-ba0e-184fac1628d1),
    local
]
/// <summary>
///     The IMFNetCredentialManager interface is used by MF to get user credentials.
///     The application can provide an object exposing this interface in the
///     MFNETSOURCE_CREDENTIAL_MANAGER property of the property store that is
///     passed to IMFSourceResolver or IMFSchemeHandler. If an object is not provided,
///     MF will not handle network authentication requests.
/// </summary>
interface IMFNetCredentialManager : IUnknown
{
/// <summary>
///     The MFNetCredentialManagerGetParam structure is for passing the authentication information to the credential manager .
/// </summary>
    typedef struct _MFNetCredentialManagerGetParam
    {
    /// <member name="hrOp">
    ///     The response code of the authenticaion challenge.
    ///     Examples are: NS_E_PROXY_ACCESSDENIED, E_ACCESSDENIED, etc.
    ///     Type: HRESULT.
    /// </member>
        HRESULT hrOp;

    /// <member name="fAllowLoggedOnUser">
    ///     Specify if currently logged on user's credential should be used as the default credential.
    ///     Type: BOOL.
    /// </member>
        BOOL fAllowLoggedOnUser;

    /// <member name="fClearTextPackage">
    ///     When set this flag indicates that the authentication package will send the credentials
    ///     unencrypted over the network.
    /// </member>
        BOOL fClearTextPackage;

    /// <member name="pszUrl">
    ///     The original URL for which authentication is required.
    ///     Type: String.
    /// </member>
        LPCWSTR pszUrl;

    /// <member name="pszSite">
    ///     The name of the site or proxy that required authentication.
    ///     Type: String.
    /// </member>
        LPCWSTR pszSite;

    /// <member name="pszRealm">
    ///     The Realm for the authentication.
    ///     Type: String.
    /// </member>
        LPCWSTR pszRealm;

    /// <member name="pszPackage">
    ///     The name of the authentication package. For example, "Digest" or "MBS_BASIC".
    ///     Type: String.
    /// </member>
        LPCWSTR pszPackage;

    /// <member name="nRetries">
    ///     The number of times that the credential manager should retry after authentication failed.
    ///     Type: LONG.
    /// </member>
        LONG nRetries;

    } MFNetCredentialManagerGetParam;

/// <summary> BeginGetCredentials is the start of the asynchronous call to get the credential. </summary>
/// <param name="pParam">
///   Pointer to the MFNetCredentialManagerGetParam parameter.
/// </param>
/// <param name="pCallback">
///   The callback when the operation is completed.
/// </param>
/// <param name="pState">
///   The state from the caller that should be returned in the callback.
/// </param>
    HRESULT BeginGetCredentials(
                [in] MFNetCredentialManagerGetParam * pParam,
                [in] IMFAsyncCallback * pCallback,
                [in] IUnknown * pState );

/// <summary> EndGetCredentials is the end of the asynchronous call to get the credential. </summary>
/// <param name="pResult">
///   The state of the operation from the callback.
/// </param>
/// <param name="ppCred">
///   Pointer to the IMFNetCredential* interface for getting the credentials.
/// </param>
    HRESULT EndGetCredentials(
                [in] IMFAsyncResult * pResult,
                [out, annotation("__out")] IMFNetCredential ** ppCred
                );

/// <summary> SetGood is called by MF to notify whether the credential succeeded authentication.</summary>
/// <param name="pCred">
///   The credential used in the authentication.
/// </param>
/// <param name="fGood">
///   Notify whether the credential provided succeeded the authentication.
/// </param>
    HRESULT SetGood(
                [in] IMFNetCredential * pCred,
                [in] BOOL fGood );
};


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(5b87ef6c-7ed8-434f-ba0e-184fac1628d1),
    local
]
/// <summary>
///     The IMFNetCredentialCache is for retrieving the credentials from the credential cache.
///     An application that implements a Credential Manager (see IMFNetCredentialManager)
///     can use MF's Credential Cache to cache credentials. To create a Credential Cache the
///     application calls MFCreateCredentialCache.
/// </summary>
interface IMFNetCredentialCache : IUnknown
{
    typedef enum _MFNetCredentialRequirements
    {
    /// <member name="REQUIRE_PROMPT">
    ///     Specify that the credential manager needs to prompt
    ///     the user to provide the credentials.
    ///     Type: DWORD.
    /// </member>
        REQUIRE_PROMPT = 0x00000001,

#if (WINVER >= _WIN32_WINNT_WIN7)
    /// <member name="REQUIRE_SAVE_SELECTED">
    ///     Specify that the credential manager needs to prompt
    ///     the user with the option to save credentials selected.
    ///     This happens when the credentials were saved already,
    ///     therefore the user does not need to reselect the option.
    /// </member>
        REQUIRE_SAVE_SELECTED = 0x00000002,
#endif // (WINVER >= _WIN32_WINNT_WIN7)

    } MFNetCredentialRequirements;

    /// <summary>
    ///     The MFNetCredentialOptions is the enumerate of
    ///     the options for the credential cache.
    /// </summary>
    typedef enum _MFNetCredentialOptions
    {
        /// <member name="MFNET_CREDENTIAL_SAVE">
        ///     Specify that the Credential Cache may save the
        ///     credentials in a persistent storage to be used
        ///     the next time it gets instantiated by the
        ///     application.
        ///     Type: DWORD.
        /// </member>
        MFNET_CREDENTIAL_SAVE = 0x00000001,

        /// <member name="MFNET_CREDENTIAL_DONT_CACHE">
        ///     Specify that the Credential Cache must not cache
        ///     the credentials in memory. If this flag
        ///     is set, then MFNET_CREDENTIAL_SAVE must not be used.
        ///     Type: DWORD.
        /// </member>
        MFNET_CREDENTIAL_DONT_CACHE = 0x00000002,

        /// <member name="MFNET_CREDENTIAL_ALLOW_CLEAR_TEXT">
        ///     Specify the user allowed the credentials to be sent over
        ///     the network unencrypted.
        ///     Type: DWORD.
        /// </member>
        MFNET_CREDENTIAL_ALLOW_CLEAR_TEXT = 0x00000004,

    } MFNetCredentialOptions;


    /// <summary>
    ///     Authentication flags.
    /// </summary>
    typedef enum _MFNetAuthenticationFlags
    {
        /// <member name="MFNET_AUTHENTICATION_PROXY">
        ///     Specify that the credentials will be used to authenticate with a proxy.
        ///     Type: DWORD.
        /// </member>
        MFNET_AUTHENTICATION_PROXY = 0x00000001,

        /// <member name="MFNET_AUTHENTICATION_CLEAR_TEXT">
        ///     Specify that the credentials will be sent over the network unencrypted.
        ///     Type: DWORD.
        /// </member>
        MFNET_AUTHENTICATION_CLEAR_TEXT = 0x00000002,

        /// <member name="MFNET_AUTHENTICATION_LOGGED_ON_USER">
        ///     Requires a credential for the logged on user.
        ///     Type: DWORD.
        /// </member>
        MFNET_AUTHENTICATION_LOGGED_ON_USER = 0x00000004,

    } MFNetAuthenticationFlags;


/// <summary>
///     The GetCredential returns a credential object for a specific URL.
/// </summary>
/// <param name="pszUrl">
///   The URL for which the credential is needed.
/// </param>
/// <param name="pszRealm">
///   The Realm for the authentication.
/// </param>
/// <param name="dwAuthenticationFlags">
///   Authenticaiton flags as defined in MFNetAuthenticationFlags.
/// </param>
/// <param name="ppCred">
///   Pointer to get the credential.
/// </param>
/// <param name="pdwRequirementsFlags">
///   Pointer to get the requirement flags, as defined in MFNetCredentialRequirements.
/// </param>

    HRESULT GetCredential(
                [in] LPCWSTR pszUrl,
                [in] LPCWSTR pszRealm,
                [in] DWORD dwAuthenticationFlags,
                [out, annotation("__out")] IMFNetCredential ** ppCred,
                [out, annotation("__out")] DWORD * pdwRequirementsFlags );

/// <summary> SetGood is called by the Credential Manager to notify whether the credential provided succeeded the authentication.</summary>
/// <param name="pCred">
///   The credential used in the authentication.
/// </param>
/// <param name="fGood">
///   Notify whether the credential provided succeeded the authentication.
/// </param>

    HRESULT SetGood(
                [in] IMFNetCredential * pCred,
                [in] BOOL fGood );

/// <summary>
///     SetUserOptions is called by the Credential Manager to set user options for the credential.
/// </summary>
/// <param name="pCred">
///   The credential being referred to.
/// </param>
/// <param name="dwOptionsFlags">
///   User flags as defined in MFNetCredentialOptions.
/// </param>

    HRESULT SetUserOptions(
                [in] IMFNetCredential * pCred,
                [in] DWORD dwOptionsFlags );
};

/// <summary>
///     MFCreateCredentialCache creates MF's default Credential Cache.
///     An application that implements a Credential Manager (see IMFNetCredentialManager)
///     should use the default Credential Cache to persist credentials.
/// </summary>
cpp_quote( "STDAPI ")
cpp_quote( "MFCreateCredentialCache(")
cpp_quote( "    __out IMFNetCredentialCache ** ppCache);")


cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(61f7d887-1230-4a8b-aeba-8ad434d1a64d),
    local
]
/// <summary>
///     The IMFSSLCertificateManager interface is used by MF to retrieve a
///     client SSL certificate in case HTTPS is used and the server requests
///     a client-side certificate.  The interface can also be used to allow the application
///     to validate the server’s SSL certificate.
///     The application can provide an object exposing this interface in the
///     MFNETSOURCE_SSLCERTIFICATE_MANAGER property of the property store that is
///     passed to IMFSourceResolver or IMFSchemeHandler. If an object is not provided,
///     MF will be unable to use HTTPS if the server requests a client-side certificate.
/// </summary>
interface IMFSSLCertificateManager : IUnknown
{
/// <summary> GetClientCertificate is used to get the client’s SSL certificate using a synchronous call </summary>
/// <param name="pszURL">
///   The URL used when sending a request to the server, and for which a client-side SSL certificate is now required.
/// </param>
/// <param name="ppbData">
///  Pointer to a pointer which, on successful return, will point to the certificate.
///   The certificate  is stored in a buffer which must be allocated using CoTaskMemAlloc,
///   and the caller must free the memory pointed to by *ppbData using CoTaskMemFree.
/// </param>
/// <param name="pcbData">
///  Pointer to a DWORD value that contains the size of the data buffer. Upon
///  input, the value contains the maximum size of the buffer. Upon return, the
///  value contains the number of bytes needed to hold the data.
/// </param>
    HRESULT GetClientCertificate(
                [in] LPCWSTR pszURL,
                [out, size_is(, *pcbData), annotation("__deref_out_bcount(*pcbData)")] BYTE **ppbData,
                [out, annotation("__out")] DWORD * pcbData );

/// <summary> BeginGetClientCertificate is the start of the asynchronous call to get the client’s SSL certificate. </summary>
/// <param name="pszURL">
///   The URL used when sending a request to the server, and for which a client-side SSL certificate is now required.
/// </param>
/// <param name="pCallback">
///   The callback when the operation is completed.
/// </param>
/// <param name="pState">
///   The state from the caller that should be returned in the callback.
/// </param>
    HRESULT BeginGetClientCertificate(
                [in] LPCWSTR pszURL,
                [in] IMFAsyncCallback * pCallback,
                [in] IUnknown * pState );

/// <summary> EndGetClientCertificate is the end of the asynchronous call to get the client’s SSL certificate. </summary>
/// <param name="pResult">
///   The state of the operation from the callback.
/// </param>
/// <param name="ppbData">
///  Pointer to a pointer which, on successful return, will point to the certificate.  The certificate is
///  stored in a buffer which must be allocated using CoTaskMemAlloc, and the caller must free the memory
///  pointed to by *ppbData using CoTaskMemFree.
/// </param>
/// <param name="pcbData">
///  Pointer to a DWORD value that contains the size of the data buffer. Upon
///  input, the value contains the maximum size of the buffer. Upon return, the
///  value contains the number of bytes needed to hold the data.
/// </param>
    HRESULT EndGetClientCertificate(
                [in] IMFAsyncResult * pResult,
                [out, size_is(, *pcbData), annotation("__deref_out_bcount(*pcbData)")] BYTE **ppbData,
                [out, annotation("__out")] DWORD * pcbData );

/// <summary> GetCertificatePolicy is called by MF to determine if the server’s SSL certificate should be verified
///  automatically or if IMFSSLCertificateManager should be used to verify the server’s certificate.
/// </summary>
/// <param name="pszURL">
///   The URL which will be sent to the server.
/// </param>
/// <param name=" pfOverrideAutomaticCheck">
///   Set to TRUE if IMFSSLCertificateManager::OnServerCertificate should be used to verify the server’s certificate.
///   Set to FALSE to verify the server’s certificate using the certificates in the Windows certificate store.
/// </param>
/// <param name=" pfClientCertificateAvailable">
///   Set to TRUE if SSL certificate for the client is available upfront. In this case, the client certificate will
///   be supplied with a synchronous call to GetClientCertificate. Set to FALSE to verify the server’s certificate
///   using the certificates in the Windows certificate store. In this case client`s SSL certificate will be obtained
///   with an asynchronous call to BeginGetClientCertificate.
/// </param>
    HRESULT GetCertificatePolicy(
                [in] LPCWSTR pszURL,
                [out] BOOL *pfOverrideAutomaticCheck,
                [out] BOOL *pfClientCertificateAvailable );

/// <summary>
///  OnServerCertificate is invoked by MF when the server’s SSL certificate has been received, and is used for checking
///  if the certificate is accepted.
/// <param name="pszURL">
///   The URL used when sending a request to the server, and for which a server-side SSL certificate has now been received.
/// </param>
/// <param name="pbData">
///  Pointer to a buffer containing the server’s SSL certificate.
/// </param>
/// <param name="cbData">
///  Size, in bytes, of the data pointed by pbData.
/// </param>
/// <param name="pfGood">
///  Boolean value which, if set to TRUE, indicates that the server’s SSL certificate has been accepted and that the
///  connection can proceed.  If set to FALSE, the certificate is rejected and the connection will be closed.
/// </param>
HRESULT OnServerCertificate(
        [in] LPCWSTR pszURL,
        [in, size_is(cbData), annotation("__in_bcount(cbData)")] BYTE * pbData,
        [in] DWORD cbData,
        [out] BOOL *pfIsGood );
};

/// <summary>
/// Netsource configuration property: The SSL credential manager.
/// Application provided credential manager is stored in the config
/// property store using this ID.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_SSLCERTIFICATE_MANAGER, 0x55e6cb27, 0xe69b, 0x4267, 0x94, 0x0c, 0x2d, 0x7e, 0xc5, 0xbb, 0x8a, 0x0f );" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(059054B3-027C-494C-A27D-9113291CF87F),
]
/// <summary>
///     The application can provide an object exposing the IMFSourceOpenMonitor
///     interface to receive notifications on the progress of an asynchronous
///     open operation. The application provides the object in the
///     MFPKEY_SourceOpenMonitor property of the property store that
///     is passed to IMFSourceResolver or IMFSchemeHandler.
/// </summary>
interface IMFSourceOpenMonitor : IUnknown
{
    /// <summary>
    ///     Called by the Network Media Source to indicate the progress of
    ///     the asynchronous open operation.
    /// </summary>
    /// <param name=pEvent>
    ///     The status of the open operation. It can be MEConnectStart or
    ///     MEConnectEnd.
    /// </param>
    ///
    HRESULT OnSourceEvent(
        [in] IMFMediaEvent *pEvent
        );
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(e9cd0383-a268-4bb4-82de-658d53574d41),
    local
]
/// <summary>
///     The IMFNetProxyLocator interface is used to determine the proxy to
///     use for connecting to a server.
/// </summary>
interface IMFNetProxyLocator : IUnknown
{
    ///  <summary>
    ///     Initializes the ProxyLocator object. Once the ProxyLocator
    ///     object has been initialized, the client has to call FindNextProxy to
    ///     retrieve the information about the first proxy.
    ///  </summary>
    ///  <param name=pszHost>The hostname of the destination server.</param>
    ///  <param name=pszUrl>The destination url.</param>
    ///  <param name=fReserved>This parameter is reserved and should be set to FALSE.</param>
    ///
    HRESULT FindFirstProxy(
                [in] LPCWSTR pszHost,
                [in] LPCWSTR pszUrl,
                [in] BOOL fReserved );

    ///  <summary>
    ///     Continues the proxy enumeration from a previous call to FindNextProxy or
    ///     FindFirstProxy.
    ///  </summary>
    ///  <returns>
    ///     <para> S_OK: a new proxy has been located.</para>
    ///     <para> S_FALSE: no more proxies can be found.</para>
    ///  </returns>
    ///
    HRESULT FindNextProxy();

    ///  <summary>
    ///     RegisterProxyResult is called by the client to record the success
    ///     or failure of using the current proxy.
    ///  </summary>
    ///  <param name=hrOp>The result of using the current proxy for connection.</param>
    HRESULT RegisterProxyResult(
                [in] HRESULT hrOp );

    ///  <summary>Retrieve the current proxy information including hostname and port.</summary>
    ///  <param name=pszStr>The proxy hostname and port.</param>
    ///  <param name=pcchStr>The count of unicode characters in pszStr.</param>
    HRESULT GetCurrentProxy(
                [out, size_is( *pcchStr ), annotation("__out_ecount_opt(*pcchStr)") ] LPWSTR pszStr,
                [in, out] DWORD * pcchStr );

    ///  <summary>Creates a new instance of the ProxyLocator.</summary>
    ///  <param name=ppProxyLocator>The new ProxyLocator created.</param>
    HRESULT Clone(
                [out] IMFNetProxyLocator ** ppProxyLocator);
}


/// <summary>
///     Creates a default proxy locator.
/// </summary>
/// <param name=pszProtocol>The name of the protocol.</param>
/// <param name=pProxyConfig>
///     Property store that contains the proxy configuration.
///     See property keys MFNETSOURCE_PROXYHOSTNAME through MFNETSOURCE_PROXYRERUNAUTODETECTION.
/// </param>
/// <param name=ppProxyLocator>Pointer to receive the ProxyLocator object.</param>
cpp_quote( "STDAPI MFCreateProxyLocator(")
cpp_quote( "    LPCWSTR pszProtocol," )
cpp_quote( "    IPropertyStore* pProxyConfig, " )
cpp_quote( "    __out IMFNetProxyLocator** ppProxyLocator );" )



///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(e9cd0384-a268-4bb4-82de-658d53574d41),
    local
]
///<summary>
///     IMFNetProxyLocatorFactory interface is used to create the
///     IMFNetProxyLocator interface which determines the proxy to use.
///     The application can provide an object exposing this interface
///     in the MFNETSOURCE_PROXYLOCATORFACTORY property of the property store
///     that is passed to IMFSourceResolver or IMFSchemeHandler.
///     If the object is not provided, MF will use the default ProxyLocatorFactory.
///</summary>
interface IMFNetProxyLocatorFactory : IUnknown
{
    /// <summary>
    ///     CreateProxyLocator is called to create a ProxyLocator
    ///     object for a given protocol.
    /// </summary>
    /// <param name="pszProtocol">
    ///     The protocol name, such as "rtsp" and "http".
    /// </param>
    /// <param name="ppProxyLocator">
    ///     The IMFNetProxyLocator interface of the ProxyLocator object.
    /// </param>
    HRESULT CreateProxyLocator(
                [in] LPCWSTR pszProtocol,
                [out, annotation("__out")] IMFNetProxyLocator ** ppProxyLocator);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(e9931663-80bf-4c6e-98af-5dcf58747d1f),
    local
]
///<summary>
///     IMFSaveJob interface is a service interface that can be used to persist
///     content to a ByteStream object provided by the application. The application
///     uses the MFNET_SAVEJOB_SERVICE GUID to retrieve this service.
///     Currently only the HTTP ByteStream object provides it.
///</summary>
interface IMFSaveJob : IUnknown
{
    ///  <summary>
    ///     Starts an asynchronous operation that will persist the content
    ///     of the object to a ByteStream given by the application.
    ///  </summary>
    ///  <param name=pStream>The ByteStream in which the service will persist the content.</param>
    ///  <param name=pCallback>The callback when the operation is completed.</param>
    ///  <param name=pState>The state from the caller that should be returned in the callback.</param>
    HRESULT BeginSave(
        [in] IMFByteStream * pStream,
        [in] IMFAsyncCallback * pCallback,
        [in] IUnknown * pState );

    ///<summary>
    ///     Completes the operation started by BeginSave.
    ///</summary>
    ///<param name=pResult>
    ///     The state of the operation from the callback.
    ///</param>
    HRESULT EndSave(
        [in] IMFAsyncResult * pResult );

    ///  <summary>Cancels the operation started by BeginSave.</summary>
    HRESULT CancelSave( );

    ///  <summary>Retrieves the percentage of content that has been persisted</summary>
    ///  <param name=pdwPercentComplete>The percentage of completion.</param>
    HRESULT GetProgress(
        [out, annotation("__out")] DWORD *pdwPercentComplete );
};

/// <summary>
/// GUID passed to IMFGetService::GetService to retrieve the IMFSaveJob interface.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNET_SAVEJOB_SERVICE, 0xb85a587f, 0x3d02, 0x4e52, 0x95, 0x65, 0x55, 0xd3, 0xec, 0x1e, 0x7f, 0xf7 );" )


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

/// <summary>
///     The type of control protocol used by the Media Source.
///     See MFNETSOURCE_PROTOCOL_ID.
/// </summary>
typedef enum _MFNETSOURCE_PROTOCOL_TYPE
{
    /// <member name="MFNETSOURCE_UNDEFINED">
    ///     The protocol type has not yet been determined.
    /// </member>
    MFNETSOURCE_UNDEFINED = 0x0,

    /// <member name="MFNETSOURCE_HTTP">
    ///     The protocol type is HTTP. This includes HTTPv9, WMSP and HTTP download.
    /// </member>
    MFNETSOURCE_HTTP = 0x1,

    /// <member name="MFNETSOURCE_RTSP">
    ///     The protocol type is RTSP.
    /// </member>
    MFNETSOURCE_RTSP = 0x2,

    /// <member name="MFNETSOURCE_FILE">
    ///     The content is read from a file. The file may be local or on a remote share.
    /// </member>
    MFNETSOURCE_FILE = 0x3,

    /// <member name="MFNETSOURCE_MULTICAST">
    ///     The protocol type is multicast.
    /// </member>
    MFNETSOURCE_MULTICAST = 0x4,

} MFNETSOURCE_PROTOCOL_TYPE;


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(7BE19E73-C9BF-468a-AC5A-A5E8653BEC87),
    local
]
///<summary>
///     Used to query and set the configuration
///     of the Net Scheme plugin.
///</summary>
interface IMFNetSchemeHandlerConfig : IUnknown
{
    /// <summary>
    ///     Method that retrieves the number of protocols
    ///     supported by this Net Scheme plugin.
    /// </summary>
    /// <param name=pcProtocols>
    ///     Pointer used to return the number of protocols.
    /// </param>
    HRESULT GetNumberOfSupportedProtocols(
            [out, annotation("__out")] ULONG* pcProtocols );

    /// <summary>
    ///     This method gets the protocol type for
    ///     a given protocol index.
    /// </summary>
    /// <param name=nProtocolIndex>
    ///     Protocol index. It is a value between 0 and
    ///     the value returned by GetNumberOfSupportedProtocols,
    ///     exclusively.
    /// </param>
    HRESULT GetSupportedProtocolType(
            [in] ULONG nProtocolIndex,
            [out, annotation("__out")] MFNETSOURCE_PROTOCOL_TYPE* pnProtocolType );

    /// <summary>
    ///     Forces the Network scheme plugin to clean up the protocol
    ///     rollover settings and use the default rollover behavior.
    ///     NOTE: This method is not implemented in this version of MF,
    ///     and it always returns S_OK.
    /// </summary>
    HRESULT ResetProtocolRolloverSettings();
};


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

cpp_quote( "STDAPI MFCreateNetSchemePlugin(" )
cpp_quote( "    REFIID riid, " )
cpp_quote( "    LPVOID *ppvHandler );" )

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

/// <summary>
///     The type of transport used in streaming or download.
///     See MFNETSOURCE_TRANSPORT_ID.
/// </summary>
typedef enum _MFNETSOURCE_TRANSPORT_TYPE
{
    /// <member name="MFNETSOURCE_UDP">
    ///     The data transport used is UDP.
    /// </member>
    MFNETSOURCE_UDP,

    /// <member name="MFNETSOURCE_TCP">
    ///     The data transport used is TCP.
    /// </member>
    MFNETSOURCE_TCP,
} MFNETSOURCE_TRANSPORT_TYPE;


/// <summary>
///     The status of cache for a media file or entry.
///     See MFNETSOURCE_CACHE_STATE_ID.
/// </summary>
typedef enum _MFNETSOURCE_CACHE_STATE
{
    /// <member name="MFNETSOURCE_CACHE_UNAVAILABLE">
    ///     The cache for a file or entry does not exist.
    /// </member>
    MFNETSOURCE_CACHE_UNAVAILABLE,

    /// <member name=" MFNETSOURCE_CACHE_ACTIVE_WRITING">
    ///     The cache for a file or entry is growing.
    /// </member>
    MFNETSOURCE_CACHE_ACTIVE_WRITING,

    /// <member name="MFNETSOURCE_CACHE_ACTIVE_COMPLETE">
    ///     The cache for a file or entry is completed.
    /// </member>
    MFNETSOURCE_CACHE_ACTIVE_COMPLETE,
} MFNETSOURCE_CACHE_STATE;


/// <summary>
///     The property IDs of the statistics that are supported by
///     Network Media Sources and Byte Streams. To retrieve the
///     statistics the application uses IMFGetService::GetService with
///     the MFNETSOURCE_STATISTICS_SERVICE service GUID and a
///     IID_IPropertyStore RIID. Then the application can use the returned
///     IPropertyStore interface to read the object's statistics with
///     the following pids and the MFNETSOURCE_STATISTICS
///     fmtid.
/// </summary>
typedef enum _MFNETSOURCE_STATISTICS_IDS
{
    /// <member name="MFNETSOURCE_RECVPACKETS_ID">
    ///     The number of packets received.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_RECVPACKETS_ID = 0,

    /// <member name="MFNETSOURCE_LOSTPACKETS_ID">
    ///     The number of packets lost.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_LOSTPACKETS_ID,

    /// <member name="MFNETSOURCE_RESENDSREQUESTED_ID">
    ///     The number of packets resend requested.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_RESENDSREQUESTED_ID,

    /// <member name="MFNETSOURCE_RESENDSRECEIVED_ID">
    ///     The number of packets resend received.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_RESENDSRECEIVED_ID,

    /// <member name="MFNETSOURCE_RECOVEREDBYECCPACKETS_ID">
    ///     The total  of packets recovered by error correction (ECC).
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_RECOVEREDBYECCPACKETS_ID,

    /// <member name="MFNETSOURCE_RECOVEREDBYRTXPACKETS_ID">
    ///     The total number of packets recovered by retransmission (RTX).
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_RECOVEREDBYRTXPACKETS_ID,

    /// <member name="MFNETSOURCE_OUTPACKETS_ID">
    ///     The total number of packets returned to user.
    ///     This includes recovered packets.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_OUTPACKETS_ID,

    /// <member name="MFNETSOURCE_RECVRATE_ID">
    ///     The 10 second average receive rate.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_RECVRATE_ID,

    /// <member name="MFNETSOURCE_AVGBANDWIDTHBPS_ID">
    ///     The average bandwidth of the clip.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_AVGBANDWIDTHBPS_ID,

    /// <member name="MFNETSOURCE_BYTESRECEIVED_ID">
    ///     The total number of bytes received.
    ///     Type: QWORD.
    /// </member>
    MFNETSOURCE_BYTESRECEIVED_ID,

    /// <member name="MFNETSOURCE_PROTOCOL_ID">
    ///     The type of control protocol used to receive the data.
    ///     Valid values are defined in MFNETSOURCE_PROTOCOL_TYPE.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_PROTOCOL_ID,

    /// <member name="MFNETSOURCE_TRANSPORT_ID">
    ///     The type of transport used to receive the data.
    ///     Valid values are defined in MFNETSOURCE_TRANSPORT_TYPE.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_TRANSPORT_ID,

    /// <member name="MFNETSOURCE_CACHE_STATE_ID">
    ///     The status of cache for a media file or entry.
    ///     Valid values are defined in MFNETSOURCE_CACHE_STATE.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_CACHE_STATE_ID,

    /// <member name="MFNETSOURCE_LINKBANDWIDTH_ID">
    ///     Current link bandwidth in bits per second.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_LINKBANDWIDTH_ID,

    /// <member name="MFNETSOURCE_CONTENTBITRATE_ID">
    ///     Current content bitrate.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_CONTENTBITRATE_ID,

    /// <member name="MFNETSOURCE_SPEEDFACTOR_ID">
    ///     The negotiated speed factor used in data transmission, multiplied by 1000.
    ///     The sender sends data in the speed of speed factor * content bitrate.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_SPEEDFACTOR_ID,

    /// <member name="MFNETSOURCE_BUFFERSIZE_ID">
    ///     The playout buffer size in milliseconds.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_BUFFERSIZE_ID,

    /// <member name="MFNETSOURCE_BUFFERPROGRESS_ID">
    ///     The percentage of playout buffer filled up during buffering.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_BUFFERPROGRESS_ID,

    /// <member name="MFNETSOURCE_LASTBWSWITCHTS_ID">
    ///     Tickcount of last bandwidth switch.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_LASTBWSWITCHTS_ID,

    /// <member name="MFNETSOURCE_SEEKRANGESTART_ID">
    ///     Start of seekable range in nanoseconds.
    ///     Type: QWORD.
    /// </member>
    MFNETSOURCE_SEEKRANGESTART_ID,

    /// <member name="MFNETSOURCE_SEEKRANGEEND_ID">
    ///     End of seekable range in nanoseconds.
    ///     Type: QWORD.
    /// </member>
    MFNETSOURCE_SEEKRANGEEND_ID,

    /// <member name="MFNETSOURCE_BUFFERINGCOUNT_ID">
    ///     Number of times buffering happened (including the initial buffering).
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_BUFFERINGCOUNT_ID,

    /// <member name="MFNETSOURCE_INCORRECTLYSIGNEDPACKETS_ID">
    ///     Number of packets that had incorrect signature.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_INCORRECTLYSIGNEDPACKETS_ID,

    /// <member name="MFNETSOURCE_SIGNEDSESSION_ID">
    ///     Whether this is a signed session.
    ///     Type: BOOLEAN.
    /// </member>
    MFNETSOURCE_SIGNEDSESSION_ID,

    /// <member name="MFNETSOURCE_MAXBITRATE_ID">
    ///     Current content maximum bitrate.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_MAXBITRATE_ID,

    /// <member name="MFNETSOURCE_RECEPTION_QUALITY_ID">
    ///     Reception quality.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_RECEPTION_QUALITY_ID,

    /// <member name="MFNETSOURCE_RECOVEREDPACKETS_ID">
    ///     The total number of packets recovered.
    ///     Type: DWORD.
    /// </member>
    MFNETSOURCE_RECOVEREDPACKETS_ID,

    /// <member name="MFNETSOURCE_VBR_ID">
    ///     Whether this is VBR content.
    ///     Type: BOOLEAN.
    /// </member>
    MFNETSOURCE_VBR_ID,

    /// <member name="MFNETSOURCE_DOWNLOADPROGRESS_ID">
    ///     The percentage of the content that has been downloaded so far.
    ///     Type: BOOLEAN.
    /// </member>
    MFNETSOURCE_DOWNLOADPROGRESS_ID,

#if (WINVER >= _WIN32_WINNT_WIN7)
    /// <member name="MFNETSOURCE_UNPREDEFINEDPROTOCOLNAME_ID">
    ///     The name of protocol when MFNETSOURCE_PROTOCOL_ID is MFNETSOURCE_UNDEFINED.
    ///     Data type: STRING
    /// </member>
    MFNETSOURCE_UNPREDEFINEDPROTOCOLNAME_ID,
#endif // (WINVER >= _WIN32_WINNT_WIN7)

} MFNETSOURCE_STATISTICS_IDS;

/// <summary>
/// GUID passed to IMFGetService::GetService to retrieve a statistics
/// service interface such as IMFStatisticsSite or IMFPropertyStore
/// from a Network Media Source or Byte Stream.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_STATISTICS_SERVICE, 0x3cb1f275, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
/// The fmtid of the PROPERTYKEY used to retrieve statistics from
/// Network Media Sources and Byte Streams. It is used with
/// the property IDs defined in MFNETSOURCE_STATISTICS_IDS.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_STATISTICS, 0x3cb1f274, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
/// Netsource configuration property: startup buffering time in seconds.
/// Default: 5 seconds.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_BUFFERINGTIME, 0x3cb1f276, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
/// Netsource configuration property: acceleration duration in milliseconds.
/// Default: 10000 ms.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_ACCELERATEDSTREAMINGDURATION, 0x3cb1f277, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
/// Netsource configuration property: UDP stream acceleration duration in milliseconds.
/// UDP stream should not accelerate more than the server's UDP resend buffer size.
/// Default: 8000 ms.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_MAXUDPACCELERATEDSTREAMINGDURATION, 0x4aab2879, 0xbbe1, 0x4994, 0x9f, 0xf0, 0x54, 0x95, 0xbd, 0x25, 0x1, 0x29 );" )

/// <summary>
/// Netsource configuration property: Maximun memory buffered samples in milliseconds.
/// The net source should not buffer more than this limit worth of data in memory.
/// Default: 40000 ms.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_MAXBUFFERTIMEMS, 0x408b24e6, 0x4038, 0x4401, 0xb5, 0xb2, 0xfe, 0x70, 0x1a, 0x9e, 0xbf, 0x10 );" )

/// <summary>
/// Netsource configuration property: link bandwidth.
/// This can be set by the application or detected by link bandwidth tests such as packetpair.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_CONNECTIONBANDWIDTH, 0x3cb1f278, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
/// Netsource configuration property: enable or disable caching of content.
/// Default is enable.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_CACHEENABLED, 0x3cb1f279, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
/// Netsource configuration property: number of times the client will try to reconnect
/// to the server and resume streaming if the connection was broken due to temporary
/// network outage.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_AUTORECONNECTLIMIT, 0x3cb1f27a, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
/// Netsource configuration property: enable or disable UDP resend in case of packet loss.
/// Default is enable.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_RESENDSENABLED, 0x3cb1f27b, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
/// Netsource configuration property: enable or disable stream switching for MBR files.
/// Default is enable.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_THINNINGENABLED, 0x3cb1f27c, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
/// Netsource configuration property: The control protocol used.
/// This property is read-only. Valid values are in MFNETSOURCE_PROTOCOL_TYPE.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_PROTOCOL, 0x3cb1f27d, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
/// Netsource configuration property: The transport protocol used.
/// This property is read-only. Valid values are in MFNETSOURCE_TRANSPORT_TYPE.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_TRANSPORT, 0x3cb1f27e, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
/// <summary>
/// Netsource configuration property: enable or disable preview mode.
/// Default is disabled.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_PREVIEWMODEENABLED, 0x3cb1f27f, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

/// <summary>
/// Netsource configuration property: The credential manager.
/// Application provided credential manager is stored in the config
/// property store using this ID.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_CREDENTIAL_MANAGER, 0x3cb1f280, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
/// This is a read-only property used to retrieve from netsource
/// the packetpair and runtime bandwidth detected.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_PPBANDWIDTH, 0x3cb1f281, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
/// This is a read-only property used to retrieve from netsource
/// the number of auto-reconnect attemps.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_AUTORECONNECTPROGRESS, 0x3cb1f282, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  ID of the property that the application uses to set the Proxy Locator Factory
///  (IMFNetProxyLocatorFactory) that will be used by the netsource to enumerate proxies.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_PROXYLOCATORFACTORY, 0x3cb1f283, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  ID of application specified value used as part of cs(User-Agent) field in logging message.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_BROWSERUSERAGENT, 0x3cb1f28b, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  ID of application specified value of cs(Referer) field in logging message.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_BROWSERWEBPAGE, 0x3cb1f28c, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  ID of application specified value of c-playerversion field in logging message.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_PLAYERVERSION, 0x3cb1f28d, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  ID of application specified value of c-playerid field in logging message.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_PLAYERID, 0x3cb1f28e, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  ID of application specified the value of c-hostexe field in logging message.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_HOSTEXE, 0x3cb1f28f, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  ID of application specified value of c-hostexever in logging message.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_HOSTVERSION, 0x3cb1f291, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  ID of application specified value used as part of cs(User-Agent) field in logging message.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_PLAYERUSERAGENT, 0x3cb1f292, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
/// <summary>
///  GUID that uniquely identifies the client to the server. If not set, or set as GUID_NULL, MF will generate a new
///  anonymous GUID per session that ensures the user's privacy.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_CLIENTGUID, 0x60a2c4a6, 0xf197, 0x4c14, 0xa5, 0xbf, 0x88, 0x83, 0xd, 0x24, 0x58, 0xaf );" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

/// <summary>
///  ID of application specified array of urls that netsource should send logging messages to
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_LOGURL, 0x3cb1f293, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  Netsource configuration property: Enable or disable UDP based data protocol.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_ENABLE_UDP, 0x3cb1f294, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  Netsource configuration property: Enable or disable TCP based data protocol.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_ENABLE_TCP, 0x3cb1f295, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  Netsource configuration property: Enable or disable MSB multicast protocol.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_ENABLE_MSB, 0x3cb1f296, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  Netsource configuration property: Enable or disable RTSP control protocol.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_ENABLE_RTSP, 0x3cb1f298, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  Netsource configuration property: Enable or disable HTTP control protocol.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_ENABLE_HTTP, 0x3cb1f299, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  Netsource configuration property: Enable or disable all streaming protocols.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_ENABLE_STREAMING, 0x3cb1f29c, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  Netsource configuration property: Enable or disable all download protocols.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_ENABLE_DOWNLOAD, 0x3cb1f29d, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  Netsource configuration property: Range of valid UDP ports that can be used to receive streaming content.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_UDP_PORT_RANGE, 0x3cb1f29a, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  This is the ID of a read-only property used to retrieve from netsource
///  the proxy host and port used in the connection.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_PROXYINFO, 0x3cb1f29b, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  Network byte stream read-only property: Array of bytes that contains
///  the representation of the DRM License associated with this byte stream.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_DRMNET_LICENSE_REPRESENTATION, 0x47eae1bd, 0xbdfe, 0x42e2, 0x82, 0xf3, 0x54, 0xa4, 0x8c, 0x17, 0x96, 0x2d );" )

/// <summary>
///  Property passed in a property store to MFCreateProxyLocator in order to
///  instantiate a default proxy locator. Look for MFNET_PROXYSETTINGS
///  for a list of the values that this property can have.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_PROXYSETTINGS, 0x3cb1f287, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  Property passed in a property store to MFCreateProxyLocator in order to
///  instantiate a default proxy locator. It defines the name of the proxy
///  host to be used with the manual proxy setting.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_PROXYHOSTNAME, 0x3cb1f284, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  Property passed in a property store to MFCreateProxyLocator in order to
///  instantiate a default proxy locator. It defines the default proxy port
///  to be used.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_PROXYPORT, 0x3cb1f288, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  Property passed in a property store to MFCreateProxyLocator in order to
///  instantiate a default proxy locator. It defines the list of addresses
///  that do not needed to be accessed through the proxy server. Entries in the
///  list can be separated by semicolons (;).
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_PROXYEXCEPTIONLIST, 0x3cb1f285, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  Property passed in a property store to MFCreateProxyLocator in order to
///  instantiate a default proxy locator. If this property is set to a value
///  different than zero, the proxy locator will bypass the proxy server for
///  local addresses.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_PROXYBYPASSFORLOCAL, 0x3cb1f286, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

/// <summary>
///  Property passed in a property store to MFCreateProxyLocator in order to
///  instantiate a default proxy locator. If this property is set to a value
///  different than zero, the proxy locator will force proxy detection when
///  enumerating proxies.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_PROXYRERUNAUTODETECTION, 0x3cb1f289, 0x0505, 0x4c5d, 0xae, 0x71, 0x0a, 0x55, 0x63, 0x44, 0xef, 0xa1 );" )

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
/// <summary>
///  The string sent in the Accept-Language header.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_STREAM_LANGUAGE, 0x9ab44318, 0xf7cd, 0x4f2d, 0x8d, 0x6d, 0xfa, 0x35, 0xb4, 0x92, 0xce, 0xcb );" )

/// <summary>
///  Array of strings with the parameters to send to the log server.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_LOGPARAMS, 0x64936ae8, 0x9418, 0x453a, 0x8c, 0xda, 0x3e, 0xa, 0x66, 0x8b, 0x35, 0x3b );" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")


/// <summary>
///     Options that can be used with MFNETSOURCE_PROXYSETTINGS.
/// </summary>
typedef enum _MFNET_PROXYSETTINGS
{
    /// <summary>
    ///     This option sets the proxy locator to bypass all addresses.
    /// </summary>
    MFNET_PROXYSETTING_NONE = 0,

    /// <summary>
    ///     This options sets the proxy locator to use manual settings.
    /// </summary>
    MFNET_PROXYSETTING_MANUAL = 1,

    /// <summary>
    ///     This options sets the proxy locator to use proxy auto-discovery.
    /// </summary>
    MFNET_PROXYSETTING_AUTO = 2,

    /// <summary>
    ///     This options sets the proxy locator to use the internet browser
    ///     proxy settings.
    /// </summary>
    MFNET_PROXYSETTING_BROWSER = 3
}
MFNET_PROXYSETTINGS;


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
// Media Foundation source resolution interfaces
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(6D4C7B74-52A0-4bb7-B0DB-55F29F47A668),
    local
]
/// <summary>
///     A scheme handler is typically associated with one or more schemes
///     (e.g. file:// or http://) and is able to create an object (generally
///     an IMFByteStream) capable of reading from that URL.
/// </summary>
interface IMFSchemeHandler : IUnknown
{
    HRESULT BeginCreateObject(
                [in]  LPCWSTR pwszURL,
                [in]  DWORD dwFlags,
                [in]  IPropertyStore *pProps,
                [out, annotation("__out_opt")] IUnknown **ppIUnknownCancelCookie,
                [in]  IMFAsyncCallback *pCallback,
                [in]  IUnknown *punkState
                );

    HRESULT EndCreateObject(
                [in]  IMFAsyncResult *pResult,
                [out, annotation("__out")] MF_OBJECT_TYPE *pObjectType,
                [out, annotation("__out")] IUnknown **ppObject
                );

    HRESULT CancelObjectCreation(
                [in] IUnknown *pIUnknownCancelCookie
                );
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
// {A6E1F733-3001-4915-8150-1558A2180EC8}
cpp_quote( "EXTERN_GUID(MF_BYTESTREAMHANDLER_ACCEPTS_SHARE_WRITE, 0xa6e1f733, 0x3001, 0x4915, 0x81, 0x50, 0x15, 0x58, 0xa2, 0x18, 0xe, 0xc8);" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")


[
    object,
    uuid(BB420AA4-765B-4a1f-91FE-D6A8A143924C),
    local
]
/// <summary>
///     A byte stream handler is typically associated with one or more formats
///     (e.g. WMV or MP3) and is able to create an object (generally an
///     IMFMediaSource) capable of reading that format.
/// </summary>
interface IMFByteStreamHandler : IUnknown
{
    HRESULT BeginCreateObject(
                [in]  IMFByteStream *pByteStream,
                [in]  LPCWSTR pwszURL,
                [in]  DWORD dwFlags,
                [in]  IPropertyStore *pProps,
                [out, annotation("__out_opt")] IUnknown **ppIUnknownCancelCookie,
                [in]  IMFAsyncCallback *pCallback,
                [in]  IUnknown *punkState
                );

    HRESULT EndCreateObject(
                [in]  IMFAsyncResult *pResult,
                [out, annotation("__out")] MF_OBJECT_TYPE *pObjectType,
                [out, annotation("__out")] IUnknown **ppObject
                );

    HRESULT CancelObjectCreation(
                [in] IUnknown *pIUnknownCancelCookie
            );

    HRESULT GetMaxNumberOfBytesRequiredForResolution(
                [out, annotation("__out")] QWORD *pqwBytes
                );
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
// Media Foundation Protected Media Path component interfaces
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid( 542612C4-A1B8-4632-B521-DE11EA64A0B0 ),
    helpstring( "IMFTrustedInput Interface")
]
/// <summary>
///     A component that exposes Input Trust Authorities implements
///     IMFTrustedInput.
///     This interface provides a common way for the components to expose
///     ITAs on each of its streams.
///     In addition to the methods inherited from IUnknown, IMFTrustedInput also
///     exposes the following methods.
/// </summary>
interface IMFTrustedInput : IUnknown
{
    /// <summary>
    ///     The GetInputTrustAuthority method returns an Input Trust Authority
    ///     for the specified presentation and stream.
    /// </summary>
    /// <param name="dwStreamID">
    ///     [in]  The stream ID for which the ITA is being requested.
    /// </param>
    /// <param name="riid">
    ///     [in]  The interface ID that is requested from the ITA.
    /// </param>
    /// <param name="ppv">
    ///     [out]  A pointer to the requested interface of an ITA.
    /// </param>
    /// <returns>
    ///     If the method succeeds, it returns S_OK.
    ///     Otherwise it returns a failure code.
    ///     If the decrypter does not support the requested interface,
    ///     the failure code is E_NOINTERFACE.
    /// </returns>
    /// <remarks>
    ///     The only value of riid currently passed in by MF is
    ///     IID_IMFInputTrustAuthority.
    ///     We are using custom marshalling for cross-process remoting
    ///</remarks>
    HRESULT GetInputTrustAuthority(
        [in] DWORD dwStreamID,
        [in] REFIID riid,
        [out, iid_is(riid)] IUnknown** ppunkObject
        );
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

typedef enum _MFPOLICYMANAGER_ACTION
{
    PEACTION_NO = 0,
    PEACTION_PLAY = 1,
    PEACTION_COPY = 2,
    PEACTION_EXPORT = 3,
    PEACTION_EXTRACT = 4,
    PEACTION_RESERVED1 = 5,
    PEACTION_RESERVED2 = 6,
    PEACTION_RESERVED3 = 7,
    PEACTION_LAST = 7
} MFPOLICYMANAGER_ACTION;

typedef struct _MFINPUTTRUSTAUTHORITY_ACTION
{
    // action performed by the OTA
    MFPOLICYMANAGER_ACTION Action;

    // pointer to ticket object provided by the OTA
    BYTE * pbTicket;

    // size of the ticket object
    DWORD cbTicket;
} MFINPUTTRUSTAUTHORITY_ACCESS_ACTION;


/// <summary>
///   Contains parameters for BindAccess / UpdateAccess operation
///   PolicyEngine has to do following operations in order to call BindAccess
///   - go through the list OTAs which are receiving data from the ITA
///   - call OTA::SetPolicy passing PolicyObject from the ITA
///   - get Ticket object (Ticket can be returned from OTA::SetPolicy call or as part of MESetPolicy event)
///       * OTA can return NULL if it does not support tickets
///   - put action / ticket to rgOutputActions array
///   - sign structure. append signature at the end of the structure
/// </summary>
typedef struct _MFINPUTTRUSTAUTHORITY_ACCESS_PARAMS
{
    // sizeof of structure
    DWORD dwSize;

    // version. should be 0
    DWORD dwVer;

    // offset and size of signature blob
    DWORD cbSignatureOffset;
    DWORD cbSignatureSize;

    // offset and size of extension blob
    DWORD cbExtensionOffset;
    DWORD cbExtensionSize;

    // number of elements in rgOutputActions array
    DWORD cActions;

    // array of MFINPUTTRUSTAUTHORITY_ACCESS_ACTION structure
    // one structure per OTA / per action;
    MFINPUTTRUSTAUTHORITY_ACCESS_ACTION rgOutputActions[1];

} MFINPUTTRUSTAUTHORITY_ACCESS_PARAMS;

interface IMFOutputPolicy;

[
    object,
    uuid( D19F8E98-B126-4446-890C-5DCB7AD71453 ),
    helpstring( "IMFInputTrustAuthority Interface"),
]
/// <summary>
///     Input Trust Authorities implement IMFInputTrustAuthority. This
///     interface provides a common way for the rest of the PMP components
///     to talk to various input protection systems. In addition to the methods
///     inherited from IUnknown, IMFInputTrustAuthority also exposes the
//      following methods.
/// </summary>
interface IMFInputTrustAuthority : IUnknown
{
    /// <summary>
    ///     The GetDecrypter method returns a decrypter transform.
    ///     <para>
    ///         Usually protected content is encrypted when it is stored
    ///         or transmitted.
    ///         After it enters the Media Path via a media source or transform,     ///         it typically needs to be decrypted first as the majority
    ///         of components in the Media Path can process
    ///         clear content only. The decrypter transform does this.
    ///     </para>
    ///     <para>
    ///         The PMP inserts the decrypter as the first node in the
    ///         topology right after the node corresponding to the ITA.
    ///         For every protected stream of the ITA node object there
    ///         is a separate instance of the ITA and decrypter.
    ///         However since the ITA node object hands out
    ///         all ITA instances (via ITA Creator) it can arrange for the
    ///         ITAs to be light objects that point to a common underlying
    ///         object. For instance, the ASF media source does this
    ///         for the WMDRM ITAs it hands out for its streams.
    ///     </para>
    /// </summary>
    /// <param name="riid">
    ///     [in]  The interface ID that is requested from the decrypter
    ///     transform.
    /// </param>
    /// <param name="ppv">
    ///     [out]  A pointer to the requested interface of a decrypter
    ///     transform.
    /// </param>
    /// <returns>
    ///     If the method succeeds, it returns S_OK.
    ///     Otherwise it returns a failure code.
    ///     If the decrypter does not support the requested interface,
    ///     the failure code is E_NOINTERFACE.
    /// </returns>
    /// <remarks>
    ///     The only value of riid currently passed in by the MF Policy Engine
    ///     is IID_IMFTransform.
    ///     <para>
    ///         It is recommended that on creation the decrypter transform
    ///         should be in a "disabled" state i.e. the ProcessOutput method
    ///         should fail. After the ITA verifies that it is running inside
    ///         the PMP,
    ///         it should enable the decrypter.
    ///         It can do this through a private interface, since
    ///         the decrypter is handed out by the ITA.
    ///         Having the decrypter disabled by default
    ///         prevents the decrypter from being used outside the PMP.
    ///     </para>
    ///     <para>
    ///         The ITA node object and ITA together should ensure that the
    ///         decrypter transform that they hand out can accept the media
    ///         type(s) possible for the corresponding input stream.
    ///     </para>
    ///</remarks>
    [local]
    HRESULT GetDecrypter(
        [in] REFIID riid,
        [out, iid_is(riid), annotation("__out")] void ** ppv );


    /// <summary>
    ///     Through the RequestAccess method the Policy Engine tells the ITA
    ///     about the actions that will be performed with that stream.
    ///     <para>
    ///         At this point the ITA should do whatever work it needs to
    ///         verify a user’s right to do those actions, check licenses etc.
    ///     </para>
    ///     <para>
    ///         This method may be called multiple times, once for every
    ///         output that this stream goes to.
    ///         The actions in each call may be different.
    ///     </para>
    ///     <para>
    ///         Sometimes even if the user currently does not have the
    ///         requested right, the ITA may be able to get the user that
    ///         right by performing some additional steps, but
    ///         user consent would be required before performing those steps.
    ///         An example is license acquisition or individualization.
    ///         In such a case the ITA should pass back
    ///         an IMFActivate to a ContentEnabler object through
    ///         ppContentEnablerActivate. The ContentEnabler
    ///         implementation should be provided by the ITA and its
    ///         methods should completely encapsulate the additional steps to
    ///         be done. The Policy Engine will pass this to
    ///         the application, let the application Activate and call the
    ///         ContentEnabler methods after getting the user’s consent.
    ///         Once that completes, the Policy Engine will call RequestAccess
    ///         once again on the ITA.
    ///     </para>
    /// </summary>
    /// <param name="Action">
    ///     [in]  An enum that says how the data from this stream is going
    ///           to be used.
    /// </param>
    /// <param name="ppContentEnablerActivate">
    ///     [out]  An optional IMFActivate to a ContentEnabler object.
    /// </param>
    /// <returns>
    ///     If this verification succeeds, the ITA should return S_OK
    ///     and pass back NULL in the optional ppContentEnablerActivate
    ///     parameter.
    ///     <para>
    ///         If the verification results in a definite no,
    ///         the ITA should return MF_E_NO_RIGHTS
    ///         and pass back NULL in the optional ppContentEnablerActivate
    ///         parameter.
    ///     </para>
    ///     <para>
    ///         If the verification needs additional steps to be performed
    ///         with user consent, the ITA should return MF_E_NEEDS_ENABLING
    ///         and pass back an IMFActivate to a ContentEnabler
    ///         pointer in the ppContentEnablerActivate parameter.
    ///     </para>
    /// </returns>
    /// <remarks>
    ///     Through RequestAccess the Policy Engine tells the ITA to only
    ///     prepare for an action.
    ///     The ITA should not assume that the action will definitely happen.
    ///     For instance there might be a failure in one of the later steps
    ///     before even a single media sample is pulled out of the input.
    ///     When the action is definitely about to happen the Policy
    ///     Engine calls BindAccess.
    ///</remarks>
    [local]
    HRESULT RequestAccess(
        [in] MFPOLICYMANAGER_ACTION Action,
        [out, annotation("__out")] IMFActivate **ppContentEnablerActivate );

    /// <summary>
    ///     The GetPolicy method returns the policy that dictates which output
    ///     protection systems to allow for the given stream and the
    ///     configuration data for each protection system.
    /// </summary>
    /// <param name="Action">
    ///     [in]  An enum that says how the data from this stream is going
    ///           to be used. The policy returned is typically a function of
    ///           the action being performed on that
    ///     stream.
    /// </param>
    /// <param name="ppPolicy">
    ///     [out]  An IMFOutputPolicy object for that stream for that action.
    ///            See IMFOutputPolicy for details.
    /// </param>
    /// <returns>
    ///     The ITA should return S_OK on success and an appropriate error code
    ///     on failure.
    /// </returns>
    /// <remarks>
    ///</remarks>
    [local]
    HRESULT GetPolicy(
        [in] MFPOLICYMANAGER_ACTION Action,
        [out, annotation("__out")] IMFOutputPolicy ** ppPolicy);

    /// <summary>
    ///     Through the BindAccess method the Policy Engine informs the
    ///     ITA that the action requested is definitely happening.
    ///     This allows the ITA to change any internal state.
    ///     For instance a WMDRM ITA might update the playcount remaining
    ///     for that piece of content.
    ///     <para>
    ///         The action passed in through BindAccess must be the same
    ///         as the one passed in earlier through RequestAccess.
    ///     </para>
    /// </summary>
    /// <param name="pParam">
    ///     [in]  pointer to the structure which contains parameters for BIND operation.
    /// </param>
    /// <returns>
    ///     If the ITA approves of the action it should return S_OK.
    ///     Otherwise it should return a failure code.
    /// </returns>
    /// <remarks>
    /// </remarks>
    [local]
    HRESULT BindAccess(
        [in, annotation("__in")] MFINPUTTRUSTAUTHORITY_ACCESS_PARAMS * pParam);

    /// <summary>
    ///     Through the UpdateAccess method the Policy Engine informs
    ///     the ITA of any changes in the pipeline that affect the
    ///     cActionCount value passed in the preceding BindAccess call for
    ///     this action.
    ///     This allows the ITA to change any internal state.
    ///     For instance a WMDRM ITA might update the copycount remaining
    ///     for that piece of content.
    /// </summary>
    /// <param name="pParam">
    ///     [in]  pointer to the structure which contains parameters for BIND operation.
    /// </param>
    /// <returns>
    ///     If the ITA approves of the action it should return S_OK.
    ///     Otherwise it should return a failure code.
    /// </returns>
    /// <remarks>
    /// </remarks>
    [local]
    HRESULT UpdateAccess(
        [in, annotation("__in")] MFINPUTTRUSTAUTHORITY_ACCESS_PARAMS * pParam);

    /// <summary>
    ///     The Reset method tells the ITA to return to the initial state.
    ///     Any decrypter it handed out should be disabled at this point.
    /// </summary>
    /// <returns>
    ///     If the ITA can reset successfully it should return an S_OK,
    ///     otherwise it should return an error code.
    /// </returns>
    /// <remarks>
    ///     The Policy Engine currently ignores the return code from this
    ///     method.
    ///</remarks>
    HRESULT Reset();
}


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

interface IMFOutputTrustAuthority;

[
    object,
    uuid( D19F8E95-B126-4446-890C-5DCB7AD71453 ),
    helpstring( "IMFTrustedOutput Interface"),
    pointer_default(unique),
    local
]
/// <summary>
///     Media sinks and transforms that are designed to work with the PMP
///     and send protected content outside the MF pipeline must implement
///     IMFTrustedOutput. Through this interface the Policy Engine negotiates
///     which type of content protection the output should apply.
/// </summary>
interface IMFTrustedOutput : IUnknown
{
    /// <summary>
    ///     GetOutputTrustAuthorityCount returns the number of Output Trust
    ///     Authorities being exposed by this output. A trusted output
    ///     can expose one or more OTAs, each of which reports a single action.
    /// </summary>
    /// <param name="pcOutputTrustAuthorities">
    ///     [out]  The number of Output Trust Authorities exposed by this
    ///     output.
    /// </param>
    /// <returns>
    ///     The return value is S_OK on success, and an error code otherwise.
    /// </returns>
    HRESULT GetOutputTrustAuthorityCount(
                [out, annotation("__out")] DWORD * pcOutputTrustAuthorities);

    /// <summary>
    ///     GetOutputTrustAuthorityByIndex returns the Trust Authority for
    ///     the output at
    ///     the specified index, which exposes an action being executed by this
    ///     output, and implements the content protection systems supported for
    ///     that action.
    /// </summary>
    /// <param name="dwIndex">
    ///     [in]  The index for the requested Trust Authority pointer.
    /// </param>
    /// <param name="ppauthority">
    ///     [out]  The output returns the Output Trust Authority pointer
    ///     through this.
    /// </param>
    /// <returns>
    ///     The return value is S_OK on success, and an error code otherwise.
    /// </returns>
    HRESULT GetOutputTrustAuthorityByIndex(
                [in] DWORD dwIndex,
                [out, annotation("__out")] IMFOutputTrustAuthority ** ppauthority);

    /// <summary>
    ///     IsFinal returns whether the trusted output is to be considered a
    ///     policy sink, or whether policy needs to be enforced further
    ///     downstream of this trusted output.
    /// </summary>
    /// <param name="pfIsFinal">
    ///     [out]  The value returned indicates whether this is a final output
    ///     which acts as a policy sink.
    /// </param>
    /// <returns>
    ///     The return value is S_OK on success, and an error code otherwise.
    /// </returns>
    /// <remarks>
    ///     A trusted output is generally considered final if it ensures that
    ///     it either does not give out any of the media content it receives,
    ///     or any part of the content that it gives out is protected by
    ///     its own proprietary methods (e.g. encryption) or sufficiently
    ///     devalued so as to not require protection.
    ///</remarks>
    HRESULT IsFinal(
                [out, annotation("__out")] BOOL *pfIsFinal );
};


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid( D19F8E94-B126-4446-890C-5DCB7AD71453 ),
    helpstring( "IMFOutputTrustAuthority Interface"),
    pointer_default(unique),
    local
]
/// <summary>
///     The Output Trust Authority encapsulates the functionality of one or
///     more specific content protection systems that a trusted output supports.
///     Every output must provide an IMFOutputTrustAuthority (OTA)
///     implementation for each virtual output it encapsulates.
///     It may do this through one OTA object if those outputs have the same
///     action or multiple OTAs if they are different actions.
/// </summary>
interface IMFOutputTrustAuthority : IUnknown
{
    /// <summary>
    ///     GetAction returns what the output trust authority does with the
    ///     content.
    /// </summary>
    /// <param name="pAction">
    ///     [in]  A pointer to an MFPOLICYMANAGER_ACTION enum.
    ///     The output fills in the enum value that comes closest to
    ///     describing what the output does with the content.
    /// </param>
    /// <returns>
    ///     The return value is S_OK on success, and an error code otherwise.
    /// </returns>
    HRESULT GetAction(
                [out, annotation("__out")] MFPOLICYMANAGER_ACTION * pAction);

    /// <summary>
    ///     Through SetPolicy the Policy Engine passes the output the
    ///     Policy Objects provided by the ITAs, which specify which
    ///     content protections to apply to the content.
    ///     Content from multiple Input TAs may be given to the same
    ///     output, so SetPolicy takes an array of Policy Objects
    /// </summary>
    /// <param name="ppPolicy">
    ///     [in]  An array of Policy Objects, each packaged as an
    ///     IMFOutputPolicy.
    ///     Each Policy Object negotiates policy with the OTA and specifies the
    ///     content protection systems to apply to all content received by the
    ///     output henceforth.
    /// </param>
    /// <returns>
    ///     The return value is S_OK if the output supports the specified
    ///     content protection systems.
    ////    Otherwise the return value is an error code.
    /// </returns>
    HRESULT SetPolicy(
                [in, annotation("__in_ecount_opt(nPolicy)")] IMFOutputPolicy ** ppPolicy,
                [in] DWORD nPolicy,
                [out, unique, size_is( ,*pcbTicket), annotation("__deref_opt_out_bcount(*pcbTicket)")] BYTE ** ppbTicket,
                [out, annotation("__out_opt")] DWORD * pcbTicket);
};


////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid( 7F00F10A-DAED-41AF-AB26-5FDFA4DFBA3C ),
    helpstring( "IMFOutputPolicy Interface"),
    pointer_default(unique),
    local
]
/// <summary>
///     The IMFOutputPolicy interface allows OTAs to query for the
///     protection systems they are required to enforce on each of their
///     outputs for the current content
/// </summary>
interface IMFOutputPolicy : IMFAttributes
{
    /// <summary>
    ///     GenerateRequiredSchemas takes in the specifics of the output type
    ///     and the list of protection systems supported by the output.
    ///     It returns either an error code or an IMFOutputSchemaCollection
    ///     pointer indicating a subset of the output's supported protection
    ///     schemas that need to be enforced, along with configuration
    ///     data for each protection schema that needs to be enforced.
    /// </summary>
    /// <param name="dwAttributes">
    ///     [in]  A bitfield that indicates the attributes of an output
    ///           that this OTA represents and of the media going over this
    ///           output.
    /// </param>
    /// <param name="guidOutputID">
    ///     [in]  A GUID that indicates a specific media output connector or
    ///     family of connectors that this OTA represents.
    ///     For instance, for an analog video output, this tells the
    ///     Policy Object whether this is a Component, Composite, S-Video or
    ///     VGA output.
    ///     For a digital audio output, this tells the Policy Object whether
    ///     this is a S/PDIF or HDMI output.
    /// </param>
    /// <param name="rgGuidProtectionSchemasSupported">
    ///     [in]  An array of GUIDs that indicates the output protection
    ///           schemas this OTA supports.
    ///           This is used by the Policy Object to determine whether
    ///           this output supports enough protection
    ///           to meet the security bar of the content this policy is for
    /// </param>
    /// <param name="cProtectionSchemasSupported">
    ///     [in]  A DWORD that indicates the number of GUIDs passed in the
    ///           rgGuidProtectionSchemasSupported parameter.
    /// </param>
    /// <param name="ppRequiredProtectionSchemas">
    ///     [out]  A pointer to an IMFOutputSchemaCollection that will store
    ///            the collection of IMFOutputSchema's to indicate the
    ///            protection schemas this OTA is required to enforce on
    ///            the specified output
    /// </param>
    /// <returns>
    ///     The return value is S_OK on success, and an error code otherwise.
    /// </returns>
    HRESULT GenerateRequiredSchemas(
        [in] DWORD dwAttributes,
        [in] GUID guidOutputSubType,
        [in] GUID *rgGuidProtectionSchemasSupported,
        [in] DWORD cProtectionSchemasSupported,
        [out, annotation("__out")] IMFCollection **ppRequiredProtectionSchemas );

    /// <summary>
    ///     GetOriginatorID returns a GUID identifying the ITA originator
    ///     of this Policy Object.
    ///     The OriginatorID of an ITA should be the same for all of the
    ///     Policy Objects and Output Schemas it gives out, as well as those
    ///     given out by its topology component for dynamic policy changes.
    ///     However, it should be unique from all the other ITAs that could
    ///     give Policy Objects and Output Schemas to an OTA.
    /// </summary>
    /// <param name="pguidOriginatorID">
    ///     [out]  A pointer to a GUID that will store the ID of the
    ////           originator of this Policy Object.
    ///            The Originator ID allows the OTA to distinguish
    ///            Policy Objects coming from different ITAs, so it can
    ///            know which one to update during dynamic policy changes
    /// </param>
    /// <returns>
    ///     The return value is S_OK on success, and an error code otherwise.
    /// </returns>
    HRESULT GetOriginatorID(
        [out, annotation("__out")] GUID *pguidOriginatorID );

    /// <summary>
    ///     GetMinimumGRLVersion returns a DWORD indicating the minimum version
    ///     of the Global Revocation List that needs to be enforced by the
    ///     Protected Environment to process the content that this
    ///     policy applies to.
    /// </summary>
    /// <param name="pdwMinimumGRLVersion">
    ///     [out]  A pointer to a DWORD that will store the minimum version
    ///            of the GRL required for the content associated with this
    ///            Policy Object.
    /// </param>
    /// <returns>
    ///     The return value is S_OK on success, and an error code otherwise.
    /// </returns>
    /// <remarks>
    ///     In MF v1, we do not support dynamic changes to a content's
    ///     security level requirements within a single presentation.
    ///     The content security level is checked before content streaming
    ///     begins, and is assumed to remain constant for the duration of
    ///     that presentation.
    ///     If content exposes a new Policy Object via dynamic policy changes,
    ///     any changes to the SL value will not be handled.
    ///</remarks>
    HRESULT GetMinimumGRLVersion(
        [out, annotation("__out")] DWORD *pdwMinimumGRLVersion );
};

//
// Output attributes (bit masks for fields)
//
cpp_quote( "#define MFOUTPUTATTRIBUTE_DIGITAL               ((DWORD) 0x00000001)" )
cpp_quote( "#define MFOUTPUTATTRIBUTE_NONSTANDARDIMPLEMENTATION ((DWORD) 0x00000002)" )
cpp_quote( "#define MFOUTPUTATTRIBUTE_VIDEO                 ((DWORD) 0x00000004)" )
cpp_quote( "#define MFOUTPUTATTRIBUTE_COMPRESSED            ((DWORD) 0x00000008)" )
cpp_quote( "#define MFOUTPUTATTRIBUTE_SOFTWARE              ((DWORD) 0x00000010)" )
cpp_quote( "#define MFOUTPUTATTRIBUTE_BUS                   ((DWORD) 0x00000020)" )
cpp_quote( "#define MFOUTPUTATTRIBUTE_BUSIMPLEMENTATION     ((DWORD) 0x0000FF00)" )



cpp_quote( "EXTERN_GUID( MFCONNECTOR_SPDIF, 0xb94a712, 0xad3e, 0x4cee, 0x83, 0xce, 0xce, 0x32, 0xe3, 0xdb, 0x65, 0x22);" )




//
// Bus Connector GUIDs
// NOTE: All 128 GUIDs ac3aefXX-ce43-11d9-92db-000bdb28ff98 for XX=5c-db
// have been reserved for connector GUIDs for buses. This reserved range
// shall be used when defining new bus connectors
//
cpp_quote( "" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_UNKNOWN, 0xac3aef5c, 0xce43, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_PCI,  0xac3aef5d, 0xce43, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_PCIX, 0xac3aef5e, 0xce43, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_PCI_Express, 0xac3aef5f, 0xce43, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_AGP, 0xac3aef60, 0xce43, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "" )

//
// Output Connector GUIDs
// NOTE: All 128 GUIDs 57cd59XX-ce47-11d9-92db-000bdb28ff98 for XX=68-e7
// have been reserved for connector GUIDs for outputs. This reserved range
// shall be used when defining new output connectors.
// The value of the GUID needs to be in the same order as defined in COPP_ConnectorType.
//
cpp_quote( "" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_VGA, 0x57cd5968, 0xce47, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_SVIDEO, 0x57cd5969, 0xce47, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_COMPOSITE, 0x57cd596a, 0xce47, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_COMPONENT, 0x57cd596b, 0xce47, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_DVI, 0x57cd596c, 0xce47, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_HDMI, 0x57cd596d, 0xce47, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_LVDS, 0x57cd596e, 0xce47, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
// The GUID 57cd596f-ce47-11d9-92db-000bdb28ff98 is reserved for TMDS
cpp_quote( "EXTERN_GUID( MFCONNECTOR_D_JPN, 0x57cd5970, 0xce47, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_SDI, 0x57cd5971, 0xce47, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_DISPLAYPORT_EXTERNAL, 0x57cd5972, 0xce47, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_DISPLAYPORT_EMBEDDED, 0x57cd5973, 0xce47, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_UDI_EXTERNAL, 0x57cd5974, 0xce47, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_UDI_EMBEDDED, 0x57cd5975, 0xce47, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )

cpp_quote( "" )




///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid( 7BE0FC5B-ABD9-44FB-A5C8-F50136E71599 ),
    helpstring( "IMFOutputSchema Interface"),
    pointer_default(unique),
    local
]
/// <summary>
///     The IMFOutputSchema interface encapsulates information for a single
///     output protection system and its corresponding configuration data.
///     IMFAttributes is used to store configuration data beyond the default DWORD
/// </summary>
interface IMFOutputSchema : IMFAttributes
{
    /// <summary>
    ///     GetSchemaType returns the GUID for the output protection system specified
    ///     by this IMFOutputSchema.
    /// </summary>
    /// <param name="guidSchemaType">
    ///     [out]  A GUID representing a specific output protection system.
    /// </param>
    /// <returns>
    ///     The return value is S_OK on success, and an error code otherwise.
    /// </returns>
    HRESULT GetSchemaType(
        [out, annotation("__out")] GUID *pguidSchemaType);

    /// <summary>
    ///     GetConfigurationData provides OTAs easy access to policy configuration data
    ///     if that data does not need more than a DWORD of space (this is true for many
    ///     of our OTAs right now.
    /// </summary>
    /// <param name="pdwVal">
    ///     [out]  A pointer to a DWORD that will store the basic configuration data
    ///     for the protection scheme specified by this IMFOutputSchema. The semantics
    ///     of the DWORD vary across protection schemes.
    /// </param>
    /// <returns>
    ///     The return value is S_OK on success, and an error code otherwise.
    /// </returns>
    HRESULT GetConfigurationData(
        [out, annotation("__out")] DWORD *pdwVal);

    /// <summary>
    ///     GetOriginatorID returns a GUID identifying the ITA originator of this Output Schema.
    ///     The OriginatorID of an ITA should be the same for all of the Policy Objects and Output Schemas
    ///     it gives out, as well as those given out by its topology component for dynamic policy changes.
    ///     However, it should be unique from all the other ITAs that could give Policy Objects and
    ///     Output Schemas to an OTA.
    /// </summary>
    /// <param name="pguidOriginatorID">
    ///     [out]  A pointer to a GUID that will store the ID of the originator of this Output
    ///     Schema. The Originator ID allows the OTA to distinguish Output Schemas coming from
    ///     different ITAs, so it can know which one to update during content protection messages
    /// </param>
    /// <returns>
    ///     The return value is S_OK on success, and an error code otherwise.
    /// </returns>
    HRESULT GetOriginatorID(
        [out, annotation("__out")] GUID *pguidOriginatorID );

};

//
// Protection Scheme GUIDs
//
cpp_quote( "" )
cpp_quote( "EXTERN_GUID( MFPROTECTION_DISABLE, 0x8cc6d81b, 0xfec6, 0x4d8f, 0x96, 0x4b, 0xcf, 0xba, 0x0b, 0x0d, 0xad, 0x0d);" )
cpp_quote( "EXTERN_GUID( MFPROTECTION_CONSTRICTVIDEO, 0x193370ce, 0xc5e4, 0x4c3a, 0x8a, 0x66, 0x69, 0x59, 0xb4, 0xda, 0x44, 0x42);" )
cpp_quote( "EXTERN_GUID( MFPROTECTION_CONSTRICTAUDIO, 0xffc99b44, 0xdf48, 0x4e16, 0x8e, 0x66, 0x09, 0x68, 0x92, 0xc1, 0x57, 0x8a);" )
cpp_quote( "EXTERN_GUID( MFPROTECTION_TRUSTEDAUDIODRIVERS, 0x65bdf3d2, 0x0168, 0x4816, 0xa5, 0x33, 0x55, 0xd4, 0x7b, 0x02, 0x71, 0x01);" )
cpp_quote( "EXTERN_GUID( MFPROTECTION_HDCP, 0xAE7CC03D, 0xC828, 0x4021, 0xac, 0xb7, 0xd5, 0x78, 0xd2, 0x7a, 0xaf, 0x13);" )
cpp_quote( "EXTERN_GUID( MFPROTECTION_CGMSA, 0xE57E69E9, 0x226B, 0x4d31, 0xB4, 0xE3, 0xD3, 0xDB, 0x00, 0x87, 0x36, 0xDD);" )
cpp_quote( "EXTERN_GUID( MFPROTECTION_ACP, 0xc3fd11c6, 0xf8b7, 0x4d20, 0xb0, 0x08, 0x1d, 0xb1, 0x7d, 0x61, 0xf2, 0xda);" )
cpp_quote( "EXTERN_GUID( MFPROTECTION_WMDRMOTA, 0xa267a6a1, 0x362e, 0x47d0, 0x88, 0x05, 0x46, 0x28, 0x59, 0x8a, 0x23, 0xe4);" )
cpp_quote( "EXTERN_GUID( MFPROTECTION_FFT, 0x462a56b2, 0x2866, 0x4bb6, 0x98, 0x0d, 0x6d, 0x8d, 0x9e, 0xdb, 0x1a, 0x8c);" )
cpp_quote( "" )

//
// Protection schema attribute GUIDs
//
cpp_quote( "" )
cpp_quote( "EXTERN_GUID( MFPROTECTIONATTRIBUTE_CONSTRICTVIDEO_IMAGESIZE, 0x8476fc, 0x4b58, 0x4d80, 0xa7, 0x90, 0xe7, 0x29, 0x76, 0x73, 0x16, 0x1d);" )
cpp_quote( "EXTERN_GUID( MFPROTECTIONATTRIBUTE_HDCP_SRM, 0x6f302107, 0x3477, 0x4468, 0x8a, 0x8, 0xee, 0xf9, 0xdb, 0x10, 0xe2, 0xf);" )
cpp_quote( "" )

//
// MFPROTECTION_DISABLE schema data
//
//  Schema data is a 32 bit value defined as follows:
//
//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
//  +-------------------------------------------------------------+-+
//  |                         Reserved                            |S|
//  +-------------------------------------------------------------+-+
//
//  where
//
//      Reserved - must be zero
//
//      S - Status
//          0 = off, i.e. do not disable
//          1 = on, i.e. disable
//
//  The MAKE macro is useful to ITA policy objects for building the DWORD
//  schema data. Note it does not validate the parameters.
//
//  The EXTRACT macros are normally useful only to implementors of this type of
//  protection for breaking out parameters from the DWORD schema data.
//  Extracting the Reserved data is useful only to verify that it is zero.
//
cpp_quote( "" )
cpp_quote( "#define MAKE_MFPROTECTIONDATA_DISABLE(Disable)  \\" )
cpp_quote( "    ((DWORD)(Disable ? 0x00000001 : 0))" )
cpp_quote( "" )
cpp_quote( "#define EXTRACT_MFPROTECTIONDATA_DISABLE_ON(Data) \\" )
cpp_quote( "    (0 != ((Data) & 0x00000001))"  )
cpp_quote( "" )
cpp_quote( "#define EXTRACT_MFPROTECTIONDATA_DISABLE_RESERVED(Data) \\" )
cpp_quote( "    (((DWORD)((Data) & 0xFFFFFFFE)) >> 1)" )
cpp_quote( "" )

//
// MFPROTECTION_CONSTRICTAUDIO schema data
//
//  Schema data is a 32 bit value defined as follows:
//
//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
//  +-----------------------------------------------+---------------+
//  |                   Reserved                    |     Level     |
//  +-----------------------------------------------+---------------+
//
//  where
//
//      Reserved - must be zero
//
//      Level - the constriction level. Values defined by the
//          EAudioConstriction enumeration.
//
//  The MAKE macro is useful to ITA policy objects for building the DWORD
//  schema data. Note it does not validate the parameters.
//
//  The EXTRACT macros are normally useful only to implementors of this type of
//  protection for breaking out parameters from the DWORD schema data.
//  Extracting the Reserved data is useful only to verify that it is zero.
//
cpp_quote( "" )
cpp_quote( "#define MAKE_MFPROTECTIONDATA_CONSTRICTAUDIO(Level) \\" )
cpp_quote( "    ((DWORD)(Level))" )
cpp_quote( "" )
cpp_quote( "#define EXTRACT_MFPROTECTIONDATA_CONSTRICTAUDIO_LEVEL(Data) \\" )
cpp_quote( "    ((DWORD)((Data) & 0x000000FF))" )
cpp_quote( "" )
cpp_quote( "#define EXTRACT_MFPROTECTIONDATA_CONSTRICTAUDIO_RESERVED(Data) \\" )
cpp_quote( "    (((DWORD)((Data) & 0xFFFFFF00)) >> 8)" )
cpp_quote( "" )

//
// MFPROTECTION_TRUSTEDAUDIODRIVERS schema data
//
//  Schema data is a 32 bit value defined as follows:
//
//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
//  +---------------------------+-+-+-------------------------------+
//  |         Reserved        |N|T|D|         DrmLevel              |
//  +---------------------------+-+-+-------------------------------+
//
//  where
//
//      Reserved - must be zero
//
//      N - CopyOk
//
//      T - allow test certificates
//
//      D - digital output disable
//
//      DrmLevel - the minimim allowed DrmLevel attribute for the audio drivers
//
//  The MAKE macro is useful to ITA policy objects for building the DWORD
//  schema data. Note it does not validate the parameters.
//
//  The EXTRACT macros are normally useful only to implementors of this type of
//  protection for breaking out parameters from the DWORD schema data.
//  Extracting the Reserved data is useful only to verify that it is zero.
//
cpp_quote( "" )
cpp_quote( "#define MAKE_MFPROTECTIONDATA_TRUSTEDAUDIODRIVERS(TestCertificateEnable, DigitalOutputDisable, DrmLevel) \\" )
cpp_quote( "    (((DWORD)((TestCertificateEnable) ? 0x00020000 : 0)) | \\" )
cpp_quote( "     ((DWORD)((DigitalOutputDisable) ? 0x00010000 : 0)) | \\" )
cpp_quote( "     ((DWORD)(DrmLevel)))" )
cpp_quote( "" )
cpp_quote( "" )
cpp_quote( "#if (WINVER >= _WIN32_WINNT_WIN7) ")
cpp_quote( "#define MAKE_MFPROTECTIONDATA_TRUSTEDAUDIODRIVERS2(TestCertificateEnable, DigitalOutputDisable, CopyOK, DrmLevel) \\" )
cpp_quote( "    (((DWORD)((TestCertificateEnable) ? 0x00020000 : 0)) | \\" )
cpp_quote( "     ((DWORD)((DigitalOutputDisable) ? 0x00010000 : 0)) | \\" )
cpp_quote( "     ((DWORD)((CopyOK) ? 0x00040000 : 0)) | \\" )
cpp_quote( "     ((DWORD)(DrmLevel)))" )
cpp_quote( "" )
cpp_quote( "#endif // (WINVER >= _WIN32_WINNT_WIN7) ")
cpp_quote( "#define EXTRACT_MFPROTECTIONDATA_TRUSTEDAUDIODRIVERS_DRMLEVEL(Data) \\" )
cpp_quote( "    ((DWORD)((Data) & 0x0000FFFF))" )
cpp_quote( "" )
cpp_quote( "#define EXTRACT_MFPROTECTIONDATA_TRUSTEDAUDIODRIVERS_DIGITALOUTPUTDISABLE(Data) \\" )
cpp_quote( "    (0 != ((Data) & 0x00010000))"  )
cpp_quote( "" )
cpp_quote( "#define EXTRACT_MFPROTECTIONDATA_TRUSTEDAUDIODRIVERS_TESTCERTIFICATEENABLE(Data) \\" )
cpp_quote( "    (0 != ((Data) & 0x00020000))"  )
cpp_quote( "" )
cpp_quote( "#if (WINVER >= _WIN32_WINNT_WIN7) ")
cpp_quote( "#define EXTRACT_MFPROTECTIONDATA_TRUSTEDAUDIODRIVERS_COPYOK(Data) \\" )
cpp_quote( "    (0 != ((Data) & 0x00040000))"  )
cpp_quote( "" )
cpp_quote( "#define EXTRACT_MFPROTECTIONDATA_TRUSTEDAUDIODRIVERS_RESERVED(Data) \\" )
cpp_quote( "    (((DWORD)((Data) & 0xFFF80000)) >> 19)" )
cpp_quote( "" )
cpp_quote( "#else ")
cpp_quote( "#define EXTRACT_MFPROTECTIONDATA_TRUSTEDAUDIODRIVERS_RESERVED(Data) \\" )
cpp_quote( "    (((DWORD)((Data) & 0xFFF80000)) >> 18)" )
cpp_quote( "" )
cpp_quote( "#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////




[
    object,
    uuid( d0ae555d-3b12-4d97-b060-0990bc5aeb67 ),
    local
]
/// <summary>
///     IMFSecureChannel is the base level interfaced used for initializing
///     a one-way secure channel between a host and a client. The client
///     implements the IMFSecureChannel interface, which the host calls methods
///     on to setup the channel.
/// </summary>
interface IMFSecureChannel : IUnknown
{
    /// <summary>
    ///     GetCertificate should return the client's secure channel
    ///     certificate.
    /// </summary>
    /// <param name="ppCoTaskMemCert">
    ///     ppCoTaskMemCert receives a pointer to a chunk of memory containing
    ///     the secure channel certificate. This memory should be allocated
    ///     by the callee using CoTaskMemAlloc, and must be freed by the caller
    ///     using CoTaskMemFree.
    /// </param>
    /// <param name="pcbCert">
    ///     pcbCert receives the length of the buffer returned by the
    ///     ppCoTaskMemCert parameter.
    /// </param>
    HRESULT GetCertificate( [out, annotation("__deref_out_bcount(*pcbCert)")] BYTE **ppCert, [out, annotation("__out")] DWORD* pcbCert );

    /// <summary>
    ///     SetupSession passes the encrypted session key to the callee. The
    ///     callee should decrypt this key and use it as the session key for
    ///     the secure channel connection.
    /// </summary>
    /// <param name="pbEncryptedSessionKey">
    ///     Contains a pointer to a chunk of memory containing the encrypted
    ///     session key.
    /// </param>
    /// <param name="cbSessionKey">
    ///     Contains the length of the memory buffer pointed to by the
    ///     pbEncryptedSessionKey parameter.
    /// </param>
    HRESULT SetupSession( [in, annotation("__in_bcount(cbSessionKey)")] BYTE *pbEncryptedSessionKey, [in] DWORD cbSessionKey );
};

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

typedef enum SAMPLE_PROTECTION_VERSION
{
    SAMPLE_PROTECTION_VERSION_NO                 = 0,
    SAMPLE_PROTECTION_VERSION_BASIC_LOKI         = 1,
    SAMPLE_PROTECTION_VERSION_SCATTER            = 2,
    SAMPLE_PROTECTION_VERSION_RC4                = 3
} SAMPLE_PROTECTION_VERSION;

cpp_quote( "EXTERN_GUID( MF_SampleProtectionSalt, 0x5403deee, 0xb9ee, 0x438f, 0xaa, 0x83, 0x38, 0x4, 0x99, 0x7e, 0x56, 0x9d);" )

[
    object,
    uuid( 8e36395f-c7b9-43c4-a54d-512b4af63c95 ),
    local
]
interface IMFSampleProtection : IUnknown
{
    /// <summary>
    ///     GetInputProtectionVersion returns the version of sample protection implemented by
    ///     the component on the input.
    /// </summary>
    /// <param name="pdwVersion">
    ///     pdwVersion receives a DWORD containing the version number.
    /// </param>
    HRESULT GetInputProtectionVersion( [out, annotation("__out")] DWORD *pdwVersion );

    /// <summary>
    ///     GetOutputProtectionVersion returns the version of sample protection implemented by
    ///     the component on the input.
    /// </summary>
    /// <param name="pdwVersion">
    ///     pdwVersion receives a DWORD containing the version number.
    /// </param>
    HRESULT GetOutputProtectionVersion( [out, annotation("__out")] DWORD *pdwVersion );

    /// <summary>
    ///     GetProtectionCertificate only needs to be implemented for a
    ///     downstream component providing sample protection for certain
    ///     version numbers of sample protection. It returns the sample
    ///     protection certificate of that component.
    ///     Components which do not need to implement the certificate
    ///     functionality should simply return E_NOTIMPL.
    /// </summary>
    /// <param name="dwVersion">
    ///     Contains the version number of the sample protection scheme for
    ///     which to receive the sample protection certificate.
    /// </param>
    /// <param name="ppMemCert">
    ///     Receives a pointer to a memory buffer containing the sample
    ///     protection certificate. This memory should be allocated by the
    ///     callee using CoTaskMemAlloc and freed by the caller using
    ///     CoTaskMemFree.
    /// </param>
    /// <param name="pcbCert">
    ///     Receives the length of the memory buffer returned in the
    ///     ppCoTaskMemCert parameter.
    /// </param>
    HRESULT GetProtectionCertificate( [in] DWORD dwVersion,
                                      [out, annotation("__deref_out_bcount(*pcbCert)")] BYTE **ppCert,
                                      [out, annotation("__out")] DWORD *pcbCert );

    /// <summary>
    ///     InitOutputProtection is implemented by an upstream component
    ///     providing sample protection functionality. It receives a version
    ///     number for the sample protection scheme to use, and returns
    ///     initialization information specific to that sample protection
    ///     scheme.
    ///     The component should return a failure code if the specified version
    ///     of sample protection is not supported.
    ///     A downstream component should return E_NOTIMPL for this method.
    /// </summary>
    /// <param name="dwVersion">
    ///     Specifies the version number of sample protection to be used.
    /// </param>
    /// <param name="dwOutputId">
    ///     Specifies the ID of the output (output ID for IMFTransform)
    /// </param>
    /// <param name="pbCert">
    ///     Pointer to certificate blob provided by the downstream component
    /// </param>
    /// <param name="pbCert">
    ///     Size to certificate blob provided by the downstream component
    /// </param>
    /// <param name="ppbSeed">
    ///     Receives the initialization information for downstream component.
    ///     This information should be deallocated by the caller using the
    ///     CoTaskMemFree method.
    /// </param>
    /// <param name="pcbSeed">
    ///     Receives the size of initialization information.
    /// </param>
    HRESULT InitOutputProtection( [in] DWORD dwVersion,
                                  [in] DWORD dwOutputId,
                                  [in] BYTE * pbCert,
                                  [in] DWORD cbCert,
                                  [out] BYTE ** ppbSeed,
                                  [out] DWORD * pcbSeed );

    /// <summary>
    ///     InitInputProtection is implemented by a downstream component
    ///     providing sample protection functionality. It takes a version
    ///     number of sample protection, along with initialization information
    ///     specific to that sample protection scheme.
    ///     The method should return a failure code in the event that the
    ///     component does not support the specified version of sample
    ///     protection.
    ///     An upstream component should return E_NOTIMPL for this method.
    /// </summary>
    /// <param name="dwVersion">
    ///     Specifies the version number of sample protection to be used.
    /// </param>
    /// <param name="dwInputId">
    ///     Specifies the ID of the input (input ID for IMFTransform or stream ID for IMFMediaSink)
    /// </param>
    /// <param name="pbSeed">
    ///     Specifies the initialization information provided by the upstream node.
    ///     The callee should copy this information if it is needed outside the
    ///     scope of this call.
    /// </param>
    /// <param name="cbSeed">
    ///     Specifies the size of initialization information contained in a
    ///     pbSeed.
    /// </param>
    HRESULT InitInputProtection( [in] DWORD dwVersion,
                                [in] DWORD dwInputId,
                                [in] BYTE * pbSeed,
                                [in] DWORD cbSeed );
};

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////
//
// Media Foundation Media Source/Sink: interfaces for advanced implementations
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(5dfd4b2a-7674-4110-a4e6-8a68fd5f3688)
]
///
/// <summary>
///     IMFMediaSinkPreroll is optionally implemented by Media Sinks
///     that are able to preroll.  Prerolling helps avoid glitches
///     upon startup.
/// </summary>
interface IMFMediaSinkPreroll : IUnknown
{
    /// <summary>
    ///
    /// </summary>
    /// <param name="hnsUpcomingStartTime">
    ///     An MFTIME indicating what the start time for IMFClock::Start call
    /// </param>
    /// <remarks>
    ///     <para>
    ///         For all IMFStreamSink::ProcessSample calls received
    ///         between this call and the IMFClockStateSink::OnClockStart call,
    ///         any necessary work should be done on the sample to prepare it
    ///         to be processed, but the sample should not be rendered until
    ///         OnClockStart is received.
    ///     </para>
    /// </remarks>
    HRESULT NotifyPreroll(
        [in] MFTIME hnsUpcomingStartTime
        );
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(EAECB74A-9A50-42ce-9541-6A7F57AA4AD7),
    local
]
/// <summary>
///     IMFFinalizableMediaSink is optionally supported by Media Sinks
///     that finish its time-consuming tasks before shutdown.
/// </summary>
interface IMFFinalizableMediaSink : IMFMediaSink
{
    ///
    /// <summary>
    ///     BeginFinalize tells the Media Sink to asynchronously
    ///     take any steps it needs to finish its tasks.
    /// </summary>
    /// <param name="pCallback">
    ///     Pointer to an Asynchronous Callback object.
    ///     Should not be NULL.
    /// </param>
    /// <param name="punkState">
    ///     Pointer to user-defined state that will be returned with the
    ///     sample in the call to pCallback->Invoke.
    /// </param>
    /// <remarks>
    ///     <para>
    ///         Many archive Media Sinks have steps they need to do at
    ///         the end of archiving to finish up the file, such as updating
    ///         the header (for some formats) or flushing all pending writes
    ///         to disk.  In some cases, this may include expensive operations
    ///         (such as indexing the content).
    ///         this is an asynchronous way to do this.
    ///     </para>
    ///     <para>
    ///         Making this call is optional
    ///     </para>
    /// </remarks>
    HRESULT BeginFinalize(
        [in] IMFAsyncCallback* pCallback,
        [in] IUnknown* punkState
        );

    /// <summary>
    ///     EndFinalize should be called when the async callback
    ///     given to BeginFinalize is invoked.
    /// </summary>
    /// <param name="pResult">
    ///     Pointer to the Asynchronous Result which was passed into the
    ///     IMFAsyncCallbackInvoke on the user's Asynchronous Callback object.
    ///     Should not be NULL.
    /// </param>
    HRESULT EndFinalize(
        [in] IMFAsyncResult* pResult
        );
}

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(9db7aa41-3cc5-40d4-8509-555804ad34cc)
]
/// <summary>
///     IMFStreamingSinkConfig is optionally supported by Media Sinks.
///     The interface is used for passing configuration information to
///     Media Sinks that are used for streaming.
/// </summary>
interface IMFStreamingSinkConfig : IUnknown
{
    /// <summary>
    ///     StartStreaming should be called before the Media Session
    ///     is started.
    /// </summary>
    /// <param name="fSeekOffsetIsByteOffset">
    ///     If TRUE, qwSeekOffset is the byte position specified by the
    ///     streaming media client.  If FALSE, qwSeekOffset is the time
    ///     position, in hundreds of nanoseconds, which was specified by
    ///     the streaming media client.
    /// </param>
    /// <param name="qwSeekOffset">
    ///     Either a byte offset or a time offset, depending on the value
    ///     of fSeekOffsetIsByteOffset.  Time offsets are specified in
    ///     hundreds of nanoseconds.
    /// </param>
    HRESULT StartStreaming(
        [in] BOOL fSeekOffsetIsByteOffset,
        [in] QWORD qwSeekOffset
        );
};
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
// Media Foundation playback quality
//
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//
// Media Foundation interfaces for use with advanced content protection
// scenarios
//
///////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

/// <summary>
/// when pipeline runs source in the remote process, pipeline creates a special proxy objects in the application
/// process for source and sequencer. All proxy objects should implement the IMFRemoteProxy interface in order for
/// pipeline to access remote object and proxy host.
/// </summary>
[
    object,
    uuid( 994e23ad-1cc2-493c-b9fa-46f1cb040fa4 ),
    local,
]
interface IMFRemoteProxy : IUnknown
{
    HRESULT GetRemoteObject(
        [in] REFIID riid,
        [out, iid_is(riid), annotation("__out")] void ** ppv);

    HRESULT GetRemoteHost(
        [in] REFIID riid,
        [out, iid_is(riid), annotation("__out")] void ** ppv);
}

// Component should expose MF_REMOTE_PROXY service if it works as a proxy for remote component
cpp_quote( "EXTERN_GUID( MF_REMOTE_PROXY, 0x2f00c90e, 0xd2cf, 0x4278, 0x8b, 0x6a, 0xd0, 0x77, 0xfa, 0xc3, 0xa2, 0x5f);" )



///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
[
    object,
    uuid(09EF5BE3-C8A7-469e-8B70-73BF25BB193F),
    local
]
/// <summary>
///     Provide a way for activate to marshal interface across process.
///     If the activate can't be created in the remote process, the platform will know how to unmarshal the interface for the activate
/// </summary>
interface IMFObjectReferenceStream : IUnknown
{

    HRESULT SaveReference(
                   [in] REFIID riid,
                   [in] IUnknown * pUnk);

    HRESULT LoadReference(
                   [in] REFIID riid,
                   [out] void ** ppv);
};



///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
[
    object,
    uuid(F70CA1A9-FDC7-4782-B994-ADFFB1C98606),
]
/// <summary>
///     IMFPMPHost supply the methods for creating object in the PMP process
/// </summary>
interface IMFPMPHost: IUnknown
{
    /// <summary>
    ///     Locks process from shutdown. If lock count is not 0, process will wait for 3 sec before terminating after shutdown
    /// </summary>
    HRESULT LockProcess();

    /// <summary>
    ///     Unlocks process from shutdown
    /// </summary>
    HRESULT UnlockProcess();

    /// <summary>
    ///     Creates object in pmp process by clsid
    /// </summary>
    /// <param name="pStream">
    ///     Optional pointer to serialized object.
    ///     If pointer is provided, pmp host will QI object for IPersistStream interface and call IPersistStream::Load
    /// </param>
    [local]
    HRESULT CreateObjectByCLSID(
                        [in] REFCLSID clsid,
                        [in, unique] IStream * pStream,
                        [in] REFIID riid,
                        [out, iid_is(riid)] void ** ppv);

    [call_as(CreateObjectByCLSID)]
    HRESULT RemoteCreateObjectByCLSID(
                        [in] REFCLSID clsid,
                        [in, unique, size_is(cbData)] BYTE * pbData,
                        [in] DWORD cbData,
                        [in] REFIID riid,
                        [out, iid_is(riid)] void ** ppv);
}

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
//
// MF_PMP_SERVICE is the service GUID for
// obtaining IMFPMPHost
//

cpp_quote( "EXTERN_C const GUID MF_PMP_SERVICE;" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

[
    object,
    uuid(6C4E655D-EAD8-4421-B6B9-54DCDBBDF820),
    local,
]
/// <summary>
///     IMFPMPClient is the interface implemented by components (usualy sources)
///     which need access to IMFPMPHost
/// </summary>
interface IMFPMPClient: IUnknown
{
    /// <summary>
    ///     Initialize the component with IMFPMPHost.
    /// </summary>
    HRESULT SetPMPHost(
        [in] IMFPMPHost * pPMPHost
        );
}

[
    object,
    uuid( 994e23af-1cc2-493c-b9fa-46f1cb040fa4 ),
]
/// <summary>
///     The IMFPMPServer interface is an internal interface used to communicate between PMPSession and  PMPHost objects
///     It provides methods to create and setup objects in PMP process.
/// </summary>
interface IMFPMPServer : IUnknown
{
    /// <summary>
    ///     Locks process from shutdown. If lock count is not 0, process will wait for 3 sec before terminating after shutdown
    /// </summary>
    HRESULT LockProcess();

    /// <summary>
    ///     Unlocks process from shutdown
    /// </summary>
    HRESULT UnlockProcess();

    /// <summary>
    ///     Creates object in the PMP process.
    /// </summary>
    HRESULT CreateObjectByCLSID(
                [in] REFCLSID clsid,
                [in] REFIID riid,
                [out, iid_is(riid)] void ** ppObject);
};

cpp_quote( "STDAPI MFCreatePMPServer(" )
cpp_quote( "    DWORD dwCreationFlags," )
cpp_quote( "    __out IMFPMPServer** ppPMPServer" )
cpp_quote( "    );" )

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid( 1cde6309-cae0-4940-907e-c1ec9c3d1d4a ),
    local,
]
/// <summary>
///     The IMFRemoteDesktopPlugin interface is expose by remote desktop plugin
///     Application should create remote desktop plugin and call it for every partial topology
/// </summary>
interface IMFRemoteDesktopPlugin : IUnknown
{
    /// <summary>
    ///     Called by application to update topology
    /// </summary>
    HRESULT UpdateTopology(
        [in, out] IMFTopology * pTopology);
}


/// <summary>
/// Creates party remote manager
/// </summary>
cpp_quote( "STDAPI MFCreateRemoteDesktopPlugin(")
cpp_quote( "    __out IMFRemoteDesktopPlugin** ppPlugin );" )

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

//
// CreateNamedPropertyStore
//
cpp_quote( "EXTERN_C HRESULT STDAPICALLTYPE CreateNamedPropertyStore(" )
cpp_quote( "        __out INamedPropertyStore **ppStore" )
cpp_quote( "        );" )
cpp_quote( "" )


//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

//
// SAMI interfaces and GUIDS
//

/// <summary>
///     Used to retrieve and set SAMI styles on the MF SAMI Media Source.
/// </summary>
[
    object,
    uuid(A7E025DD-5303-4a62-89D6-E747E1EFAC73),
    local
]
interface IMFSAMIStyle: IUnknown
{
    /// <summary>
    ///     Gets the total number of styles
    /// </summary>
    HRESULT GetStyleCount( [out, annotation("__out")]           DWORD * pdwCount );

    /// <summary>
    ///     Gets all of the styles as a string array in a PROPVARIANT.
    ///     The caller must properly clear the PROPVARIANT to avoid memory leaks.
    /// </summary>
    HRESULT GetStyles( [out, annotation("__out")]               PROPVARIANT* pPropVarStyleArray );

    /// <summary>
    ///     Sets the current selected style to the provided style.
    /// </summary>
    HRESULT SetSelectedStyle( [in, annotation("__in")]          LPCWSTR pwszStyle );

    /// <summary>
    ///     Gets the currently selected style.
    ///     The returned string must be deallocated using CoTaskMemFree().
    /// </summary>
    HRESULT GetSelectedStyle( [out, annotation("__deref_out") ] LPWSTR * ppwszStyle );
}

// MF_SAMI_SERVICE
// This is the "service" GUID that is used to obtain the IMFSAMIStyle interface from the
// MF SAMI source from via a GetService() call from another component. (e.g., The Media Session )
// {49A89AE7-B4D9-4ef2-AA5C-F65A3E05AE4E}
//
cpp_quote( "EXTERN_GUID( MF_SAMI_SERVICE, 0x49a89ae7, 0xb4d9, 0x4ef2, 0xaa, 0x5c, 0xf6, 0x5a, 0x3e, 0x5, 0xae, 0x4e );" )

//
// MF_PD_SAMI_STYLELIST
// Data type: BLOB
// This "Presentation Descriptor Style List" attribute contains the friendly name of the supported styles
// of the currently opened file.  This attribute is present on the Presentation Descriptor that the MF SAMI source provides.
// The form of the blob is as follows:
//
//      [ DWORD: number of style strings ]
//      [ DWORD: number of bytes in string #1 including NULL char ]
//      [ wide string #1 including NULL char ]
//      [ DWORD: number of bytes in string #2 including NULL char ]
//      [ wide string #2 including NULL char ]
//      [ DWORD: number of bytes in string #3 including NULL char ]
//      [ wide string #3 including NULL char ]
//
// {E0B73C7F-486D-484e-9872-4DE5192A7BF8}
cpp_quote( "EXTERN_GUID( MF_PD_SAMI_STYLELIST, 0xe0b73c7f, 0x486d, 0x484e, 0x98, 0x72, 0x4d, 0xe5, 0x19, 0x2a, 0x7b, 0xf8 );" )

//
// MF_SD_SAMI_LANGUAGE
// Data Type: LPWSTR
// This attribute contains the SAMI language name defined for the stream.
// This attribute is present in the Stream Descriptors returned from the MF SAMI Source.
// The SAMI language name is specified in the SAMI file.
// {36FCB98A-6CD0-44cb-ACB9-A8F5600DD0BB}
//
cpp_quote( "EXTERN_GUID( MF_SD_SAMI_LANGUAGE, 0x36fcb98a, 0x6cd0, 0x44cb, 0xac, 0xb9, 0xa8, 0xf5, 0x60, 0xd, 0xd0, 0xbb );" )


cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
////////////////////////////////////////////////////////////////////////////
//
// TRANSFORM FUNCTIONS
//

/// <summary>
///     Creates a sample copier MFT.  This MFT is typically used to copy non-D3D
///     samples into D3D samples provided by the EVR.
/// </summary>
/// <param name="ppCopierMFT">
///     Specifies a pointer to a variable where the sample copier transform
///     will be stored.
/// </param>
cpp_quote("STDAPI MFCreateSampleCopierMFT(__deref_out IMFTransform** ppCopierMFT);")

//////////////////////////////////////////////////////////////////////////////
//
// Transcode APIs
//
/////////////////////////////////////////////////////////////////////////////
[
    object,
    uuid(4ADFDBA3-7AB0-4953-A62B-461E7FF3DA1E),
    local
]
/// <summary>
///     IMFTranscodeProfile is for setting transcode configurations
/// 	that user perfers for the transcoded output media file.
/// </summary>
interface IMFTranscodeProfile : IUnknown
{
    /// <summary>
    ///     SetAudioAttributes is used to specify the audio stream settings.
    ///     These attributes are the ones defined by MF audio media type.
    /// </summary>
    /// <param name="pAttrs">
    ///     A pointer to an IMFAttributes object having the audio stream settings.
    /// </param>
    HRESULT SetAudioAttributes( [in, annotation("__in_opt")] IMFAttributes* pAttrs );

    /// <summary>
    ///     GetAudioAttributes is used to get the audio stream settings.
    /// </summary>
    /// <param name="ppAttrs">
    ///     Specifies a pointer to a variable where IMFAttributes object stored.
    ///     If no audio attributes have been set,
    ///     GetAudioAttributes expected to succeed and return NULL.
    /// </param>
    HRESULT GetAudioAttributes( [out, annotation("__deref_out_opt")] IMFAttributes** ppAttrs );

    /// <summary>
    ///     SetVideoAttributes is used to specify the video stream settings.
    ///     These attributes are the ones defined by MF video media type.
    /// </summary>
    /// <param name="pAttrs">
    ///     A pointer to an IMFAttributes object having the video stream settings.
    ///     If no video attributes have been set,
    ///     GetVideoAttributes expected to succeed and return NULL.
    /// </param>
    HRESULT SetVideoAttributes( [in, annotation("__in_opt")] IMFAttributes* pAttrs );

    /// <summary>
    ///     GetVideoAttributes is used to get the video stream settings.
    /// </summary>
    /// <param name="ppAttrs">
    ///     Specifies a pointer to a variable where IMFAttributes object stored.
    /// </param>
    HRESULT GetVideoAttributes( [out, annotation("__deref_out_opt")] IMFAttributes** ppAttrs );

    /// <summary>
    ///     SetContainerAttributes is used to specify the container settings.
    ///     These attributes are defined by transcode APIs.
    /// </summary>
    /// <param name="pAttrs">
    ///     A pointer to an IMFAttributes object having the container settings.
    /// </param>
    HRESULT SetContainerAttributes( [in, annotation("__in_opt")] IMFAttributes* pAttrs );

    /// <summary>
    ///     GetContainerAttributes is used to get the container settings.
    /// </summary>
    /// <param name="ppAttrs">
    ///     Specifies a pointer to a variable where IMFAttributes object stored.
    ///     If no container attributes have been set,
    ///     GetContainerAttributes expected to succeed and return NULL.
    /// </param>
    HRESULT GetContainerAttributes( [out, annotation("__deref_out_opt")] IMFAttributes** ppAttrs );
};

/////////////////////////////////////////////////////////////////////////////
// Transcode attribute guids

//
// Container attrributes
// They include
// 1. The following attributes
// 2. MFT_FIELDOFUSE_UNLOCK_Attribute
//

// MF_TRANSCODE_CONTAINERTYPE
// DataType: GUID(one of the transcode supported container types)
// Only support the pre-defined container attributes
// {150FF23F-4ABC-478b-AC4F-E1916FBA1CCA}
cpp_quote( "EXTERN_GUID( MF_TRANSCODE_CONTAINERTYPE, 0x150ff23f, 0x4abc, 0x478b, 0xac, 0x4f, 0xe1, 0x91, 0x6f, 0xba, 0x1c, 0xca );" )

// MFTranscodeContainerType_ASF
// represents MF built-in ASF container
// {430F6F6E-B6BF-4fc1-A0BD-9EE46EEE2AFB}
cpp_quote( "EXTERN_GUID( MFTranscodeContainerType_ASF, 0x430f6f6e, 0xb6bf, 0x4fc1, 0xa0, 0xbd, 0x9e, 0xe4, 0x6e, 0xee, 0x2a, 0xfb );" )

// MFTranscodeContainerType_MPEG4
// represents MF built-in MPEG4 container
// {DC6CD05D-B9D0-40ef-BD35-FA622C1AB28A}
cpp_quote( "EXTERN_GUID( MFTranscodeContainerType_MPEG4, 0xdc6cd05d, 0xb9d0, 0x40ef, 0xbd, 0x35, 0xfa, 0x62, 0x2c, 0x1a, 0xb2, 0x8a );" )

// MFTranscodeContainerType_MP3
// represents MF built-in MP3 container
// {E438B912-83F1-4de6-9E3A-9FFBC6DD24D1}
cpp_quote( "EXTERN_GUID( MFTranscodeContainerType_MP3, 0xe438b912, 0x83f1, 0x4de6, 0x9e, 0x3a, 0x9f, 0xfb, 0xc6, 0xdd, 0x24, 0xd1 );" )

// MFTranscodeContainerType_3GP
// represents MF built-in 3GP container
// {34c50167-4472-4f34-9ea0-c49fbacf037d }
cpp_quote( "EXTERN_GUID( MFTranscodeContainerType_3GP, 0x34c50167, 0x4472, 0x4f34, 0x9e, 0xa0, 0xc4, 0x9f, 0xba, 0xcf, 0x03, 0x7d );" )

// MF_TRANSCODE_SKIP_METADATA_TRANSFER
// DataType: UINT32(0:auto transfer, 1:don't transfer)
// {4E4469EF-B571-4959-8F83-3DCFBA33A393}
cpp_quote( "EXTERN_GUID( MF_TRANSCODE_SKIP_METADATA_TRANSFER, 0x4e4469ef, 0xb571, 0x4959, 0x8f, 0x83, 0x3d, 0xcf, 0xba, 0x33, 0xa3, 0x93 );" )

// MF_TRANSCODE_TOPOLOGYMODE
// DataType: UINT32(By default, software-only with a encoder MFT)
// {3E3DF610-394A-40b2-9DEA-3BAB650BEBF2}
cpp_quote( "EXTERN_GUID( MF_TRANSCODE_TOPOLOGYMODE, 0x3e3df610, 0x394a, 0x40b2, 0x9d, 0xea, 0x3b, 0xab, 0x65, 0xb, 0xeb, 0xf2 );" )

typedef enum _MF_TRANSCODE_TOPOLOGYMODE_FLAGS
{
    // Only software MFTs inserted into a trancode topology, by default
    MF_TRANSCODE_TOPOLOGYMODE_SOFTWARE_ONLY  = 0,
    // Allow hardware MFTs inserted into a trancode topology
    MF_TRANSCODE_TOPOLOGYMODE_HARDWARE_ALLOWED  = 1

    // Reserved for future use   
} MF_TRANSCODE_TOPOLOGYMODE_FLAGS;

// MF_TRANSCODE_ADJUST_PROFILE
// DataType: UINT32
// {3E3DF610-394A-40b2-9DEA-3BAB650BEBF2}
cpp_quote( "EXTERN_GUID( MF_TRANSCODE_ADJUST_PROFILE, 0x9c37c21b, 0x60f, 0x487c, 0xa6, 0x90, 0x80, 0xd7, 0xf5, 0xd, 0x1c, 0x72 );" )

typedef enum _MF_TRANSCODE_ADJUST_PROFILE_FLAGS
{
    // Only adjust the frame rate/interlace mode if needed, by default
    MF_TRANSCODE_ADJUST_PROFILE_DEFAULT = 0,
    // Fill the missing media type attributes by the source media type. It does not overwrite the already set stream-level attributes. 
    MF_TRANSCODE_ADJUST_PROFILE_USE_SOURCE_ATTRIBUTES = 1

    //  Reserved for future use
} MF_TRANSCODE_ADJUST_PROFILE_FLAGS;

//
// Audio/video stream attributes
// They include
// 1. Audio/video MT attributes(refer to mfapi.h for all the MT attributes)
// 2. Audio/video encoder specific properties, some of them got from codecapi.h
//

// MF_TRANSCODE_ENCODINGPROFILE
// DataType: LPCWSTR(one of the device conformance profile strings got from the device capability)
// This attribute is only used if the transcoded file is targeted for a WM-capable device
// For video,
//  - "AP" advanced profile
//  - "MP" main profile
//  - "SP" simple profile
// {6947787C-F508-4ea9-B1E9-A1FE3A49FBC9}
cpp_quote( "EXTERN_GUID( MF_TRANSCODE_ENCODINGPROFILE, 0x6947787c, 0xf508, 0x4ea9, 0xb1, 0xe9, 0xa1, 0xfe, 0x3a, 0x49, 0xfb, 0xc9 );" )

// MF_TRANSCODE_QUALITYVSSPEED
// DataType: UINT32 (from 0~100, 0=lowest quality, highest speed, 100=highest quality, lowest speed)
// Same guid as STATIC_CODECAPI_AVEncCommonQualityVsSpeed
cpp_quote( "EXTERN_GUID( MF_TRANSCODE_QUALITYVSSPEED, 0x98332df8, 0x03cd, 0x476b, 0x89, 0xfa, 0x3f, 0x9e, 0x44, 0x2d, 0xec, 0x9f );" )

// MF_TRANSCODE_DONOT_INSERT_ENCODER
// DataType: UINT32(0:insert encoder in the partial topology, 1:don't insert encoder in the partial topology)
// By default, encoder is inserted.
// {F45AA7CE-AB24-4012-A11B-DC8220201410}
cpp_quote( "EXTERN_GUID( MF_TRANSCODE_DONOT_INSERT_ENCODER, 0xf45aa7ce, 0xab24, 0x4012, 0xa1, 0x1b, 0xdc, 0x82, 0x20, 0x20, 0x14, 0x10 );" )

/////////////////////////////////////////////////////////////////////////////
/// <summary>
///     Creates a transcode profile to store user perfers audio and video settings.
/// </summary>
/// <param name="ppTranscodeProfile">
///     Specifies a pointer to a variable where the transcode profile
///     will be stored.
/// </param>
cpp_quote( "STDAPI MFCreateTranscodeProfile(" )
cpp_quote( "    __out IMFTranscodeProfile** ppTranscodeProfile" )
cpp_quote( "    );" )

/////////////////////////////////////////////////////////////////////////////
/// <summary>
///     Creates a partial transcode topology. The partial topology has a
///     source object, encoder object and sink object. The encoder object and sink object
//	has been configured properly.
/// </summary>
/// <param name="pSrc">
///     A pointer to an IMFMediaSource object.
/// </param>
/// <param name="pwszOutputFilePath">
///     Specifies a output file path.
/// </param>
/// <param name="pProfile">
///     Specifies a pointer to an IMFTranscodeProfile object.
///     It has the user preferred output configurations.
/// </param>
/// <param name="ppTranscodeTopo">
///     Specifies a pointer to a variable where the partial transcode topology
///     will be stored.
/// </param>
cpp_quote( "STDAPI MFCreateTranscodeTopology(" )
cpp_quote( "    __in IMFMediaSource* pSrc," )
cpp_quote( "    __in LPCWSTR pwszOutputFilePath," )
cpp_quote( "    __in IMFTranscodeProfile* pProfile," )
cpp_quote( "    __out IMFTopology** ppTranscodeTopo" )
cpp_quote( "    );" )

/////////////////////////////////////////////////////////////////////////////
/// <summary>
///     Get the available output types from an audio encoder.
/// </summary>
/// <param name="guidSubType">
///     Specifies the sub type of the preferred media type
/// </param>
/// <param name="dwMFTFlags">
///     Specifies which category the preferred audio encoder is, for example, HW or SW.
/// </param>
/// <param name="pCodecConfig">
///     Specifies the specific encoder configurations, which needs to be set before getting the preferred output media types.
/// </param>
/// <param name="ppAvailableTypes">
///     Specifies a pointer to a variable to a list of the available output types.
/// </param>
cpp_quote( "STDAPI MFTranscodeGetAudioOutputAvailableTypes(" )
cpp_quote( " __in REFGUID guidSubType," )
cpp_quote( " __in DWORD dwMFTFlags," )
cpp_quote( " __in_opt IMFAttributes* pCodecConfig, ")
cpp_quote( " __out IMFCollection** ppAvailableTypes );" )

//////////////////////////////////////////////////////////////////////////////
typedef struct _MF_TRANSCODE_SINK_INFO {
    DWORD dwVideoStreamID;
    IMFMediaType* pVideoMediaType;
    DWORD dwAudioStreamID;
    IMFMediaType* pAudioMediaType;
} MF_TRANSCODE_SINK_INFO;

[
    object,
    uuid(8CFFCD2E-5A03-4a3a-AFF7-EDCD107C620E),
    local
]
interface IMFTranscodeSinkInfoProvider : IUnknown
{
    HRESULT SetOutputFile( [in, annotation("__in")] LPCWSTR pwszFileName );
    HRESULT SetOutputByteStream( [in, annotation("__in")] IMFActivate* pByteStreamActivate );
    HRESULT SetProfile( [in, annotation("__in")] IMFTranscodeProfile* pProfile );
    HRESULT GetSinkInfo( [out, annotation("__out")] MF_TRANSCODE_SINK_INFO* pSinkInfo );
};

//////////////////////////////////////////////////////////////////////////////
///
/// <summary>
///     Create a generic transcode sink activate for out-of-proc topology
/// </summary>
/// <param name="ppActivate">
///    Receive pointer for a transcode sink activate.
/// </param>
cpp_quote(" STDAPI MFCreateTranscodeSinkActivate( ")
cpp_quote(" __out IMFActivate** ppActivate ); ")

//////////////////////////////////////////////////////////////////////////////
//
// Field-of-use API
//
/////////////////////////////////////////////////////////////////////////////

[
    object,
    uuid(508E71D3-EC66-4fc3-8775-B4B9ED6BA847),
]
/// <summary>
///     IMFFieldOfUseMFTUnlock manages the unlocking process on behalf of the application
/// </summary>
/// <remarks>
///     Restricted MFTs need to be unlocked at creation time, otherwise both the type negociation
///     and data processing will fail with error codes MF_E_UNAUTHORIZED.
/// </remarks>
interface IMFFieldOfUseMFTUnlock :  IUnknown
{
    /// <summary>
    ///     Unlock manages the unlocking process on behalf of the application.
    /// </summary>
    /// <param name="pUnkMFT">
    ///     Points to the IUnknown interface of the MFT to unlock.
    /// </param>
    /// <returns>
    ///     The return value is S_OK if the MFT has been successfully unlocked, and an error code otherwise.
    /// </returns>
    HRESULT Unlock(
        [in] IUnknown *pUnkMFT
    );
}

typedef struct _MFT_REGISTRATION_INFO
{
    CLSID clsid;
    GUID guidCategory;
    UINT32 uiFlags;
    LPCWSTR pszName;
    DWORD cInTypes;
    [size_is(cInTypes)] MFT_REGISTER_TYPE_INFO* pInTypes;
    DWORD cOutTypes;
    [size_is(cOutTypes)] MFT_REGISTER_TYPE_INFO* pOutTypes;
} MFT_REGISTRATION_INFO;

/* ddf5cf9c-4506-45aa-abf0-6d5d94dd1b4a */
cpp_quote( "EXTERN_GUID(MF_LOCAL_MFT_REGISTRATION_SERVICE, 0xddf5cf9c, 0x4506, 0x45aa, 0xab, 0xf0, 0x6d, 0x5d, 0x94, 0xdd, 0x1b, 0x4a);" )

[
    object,
    uuid(149c4d73-b4be-4f8d-8b87-079e926b6add),
]
/// <summary>
///     IMFLocalMFTRegistration is a service interface exposed by the session.  Using this
///     service, applications can register an MFT locally for its own use.  If the session
///     is running cross-process, the registration will be remoted into the remote process.
/// </summary>
interface IMFLocalMFTRegistration : IUnknown
{
    /// <summary>
    ///     Call RegisterMFTs to locally register a set of MFTs defined by an array
    ///     of MFT_REGISTRATION_INFO structures.
    /// </summary>
    /// <param name="pMFTs">
    ///     Points to an array of MFT_REGISTRATION_INFO structures.  The MFTs defined
    ///     by these structures will be registered locally.
    /// </param>
    /// <param name="cMFTs">
    ///     Defines how many MFT_REGISTRATION_INFO structures are pointed to by pMFTs.
    /// </param>
    ///  <returns>
    ///     S_OK on sucessful registration.  An error code may be returned if there is
    ///     a problem remoting the registrations into the remote process.
    ///  </returns>
    HRESULT RegisterMFTs([in, size_is(cMFTs)] MFT_REGISTRATION_INFO* pMFTs, DWORD cMFTs);
}

/////////////////////////////////////////////////////////////////////////////

cpp_quote( "STDAPI MFCreateMFByteStreamOnStream(" )
cpp_quote( "    IStream*        pStream," )
cpp_quote( "    __out IMFByteStream** ppByteStream);" )

/////////////////////////////////////////////////////////////////////////////
// Scheme and Bytestream handler CLSIDs
// {9EC4B4F9-3029-45ad-947B-344DE2A249E2}
cpp_quote( "EXTERN_GUID(CLSID_UrlmonSchemePlugin, 0x9ec4b4f9, 0x3029, 0x45ad, 0x94, 0x7b, 0x34, 0x4d, 0xe2, 0xa2, 0x49, 0xe2);" )

//////////////////////////////////////////////////////////////////////////////
//
// Capture (device) source APIs
//
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////

/// <summary>
///     Enumerates Media Foundation Capture Sources
/// </summary>
/// <param name="pAttributes">
///     Attribute store for enumeration (containing source type GUID, etc)
/// </param>
/// <param name="pppSourceActivate">
///     Array of IMFActivate pointers
///     Each pointer must be released and the array freed with CoTaskMemFree
/// </param>
/// <param name="pcSourceActivate">
///     Number of pointers in the pppSourceActivate array
/// </param>
cpp_quote( "STDAPI MFEnumDeviceSources(" )
cpp_quote( "    __in                IMFAttributes*                      pAttributes," )
cpp_quote( "    __deref_out_ecount(*pcSourceActivate) IMFActivate***    pppSourceActivate," )
cpp_quote( "    __out               UINT32*                             pcSourceActivate" )
cpp_quote( ");" )

/////////////////////////////////////////////////////////////////////////////

/// <summary>
///     Creates a Media Foundation Device Source
/// </summary>
/// <param name="pAttributes">
///     Device Source creation attributes
/// </param>
/// <param name="ppSource">
///     Returns pointer to a Device Source
/// </param>
cpp_quote( "STDAPI MFCreateDeviceSource(" )
cpp_quote( "    __in  IMFAttributes*   pAttributes," )
cpp_quote( "    __out IMFMediaSource** ppSource" )
cpp_quote( ");" )

/////////////////////////////////////////////////////////////////////////////

/// <summary>
///     Creates a Media Foundation Device Source Activate
/// </summary>
/// <param name="pAttributes">
///     Device Source creation attributes
/// </param>
/// <param name="ppActivate">
///     Returns pointer to a Device Source Activate
/// </param>
cpp_quote( "STDAPI MFCreateDeviceSourceActivate( " )
cpp_quote( "    __in  IMFAttributes*   pAttributes," )
cpp_quote( "    __out IMFActivate**   ppActivate" )
cpp_quote( ");" )

/////////////////////////////////////////////////////////////////////////////

//
// Capture source attributes
//

// MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE
// Data type: GUID
// Media Source type GUID (e.g. MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID )
cpp_quote( "EXTERN_GUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, 0xc60ac5fe, 0x252a, 0x478f, 0xa0, 0xef, 0xbc, 0x8f, 0xa5, 0xf7, 0xca, 0xd3);" )

// MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_HW_SOURCE
// Data type: UINT32
// If this attribute is TRUE, this is a hardware capture source, otherwise it's a software source
cpp_quote( "EXTERN_GUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_HW_SOURCE, 0xde7046ba, 0x54d6, 0x4487, 0xa2, 0xa4, 0xec, 0x7c, 0xd, 0x1b, 0xd1, 0x63);" )

// MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME
// Data type: STRING
// Friendly name of the video capture device
cpp_quote( "EXTERN_GUID( MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, 0x60d0e559, 0x52f8, 0x4fa2, 0xbb, 0xce, 0xac, 0xdb, 0x34, 0xa8, 0xec, 0x1);" )

// MF_DEVSOURCE_ATTRIBUTE_MEDIA_TYPE
// Data type: BLOB
// Blob consisting of one MAJOR_TYPE GUID\MINOR_TYPE GUID pair
cpp_quote( "EXTERN_GUID( MF_DEVSOURCE_ATTRIBUTE_MEDIA_TYPE, 0x56a819ca, 0xc78, 0x4de4, 0xa0, 0xa7, 0x3d, 0xda, 0xba, 0xf, 0x24, 0xd4);" )

// MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_CATEGORY
// Data type: GUID
// Capture source category (e.g. CLSID_VideoInputDeviceCategory)
cpp_quote( "EXTERN_GUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_CATEGORY, 0x77f0ae69, 0xc3bd, 0x4509, 0x94, 0x1d, 0x46, 0x7e, 0x4d, 0x24, 0x89, 0x9e);" )

// MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK
// Data type: STRING
// Symbolic link for creating a video capture source
cpp_quote( "EXTERN_GUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, 0x58f0aad8, 0x22bf, 0x4f8a, 0xbb, 0x3d, 0xd2, 0xc4, 0x97, 0x8c, 0x6e, 0x2f);" )

// MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_MAX_BUFFERS
// Data type: UINT32
// Maximum # of sample that the video capture source will buffer
// {7DD9B730-4F2D-41d5-8F95-0CC9A912BA26}
cpp_quote( "EXTERN_GUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_MAX_BUFFERS, 0x7dd9b730, 0x4f2d, 0x41d5, 0x8f, 0x95, 0xc, 0xc9, 0xa9, 0x12, 0xba, 0x26);" )

// MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID
// Data type: STRING
// Device endpoint ID for creating an audio capture source
cpp_quote( "EXTERN_GUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ENDPOINT_ID, 0x30da9258, 0xfeb9, 0x47a7, 0xa4, 0x53, 0x76, 0x3a, 0x7a, 0x8e, 0x1c, 0x5f);" )

// MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ROLE
// Data type: UINT32
// Device role (ERole) for creating an audio capture source
cpp_quote( "EXTERN_GUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_ROLE, 0xbc9d118e, 0x8c67, 0x4a18, 0x85, 0xd4, 0x12, 0xd3, 0x0, 0x40, 0x5, 0x52);" )

/////////////////////////////////////////////////////////////////////////////

//
// Device Source Type GUIDs
//

// {14DD9A1C-7CFF-41be-B1B9-BA1AC6ECB571}...MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID
cpp_quote( "EXTERN_GUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID, 0x14dd9a1c, 0x7cff, 0x41be, 0xb1, 0xb9, 0xba, 0x1a, 0xc6, 0xec, 0xb5, 0x71);")

// {8AC3587A-4AE7-42D8-99E0-0A6013EEF90F}...MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
cpp_quote( "EXTERN_GUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID, 0x8ac3587a, 0x4ae7, 0x42d8, 0x99, 0xe0, 0x0a, 0x60, 0x13, 0xee, 0xf9, 0x0f);")

/////////////////////////////////////////////////////////////////////////////

//
// MFSample DevSource-specific attribute GUIDs
//

// {8F3E35E7-2DCD-4887-8622-2A58BAA652B0}   MFSampleExtension_DeviceTimestamp
// Type: UINT64
// Stores the original device timestamp prior to QPC correlation and conversion to stream time.
cpp_quote( "EXTERN_GUID(MFSampleExtension_DeviceTimestamp, 0x8f3e35e7, 0x2dcd, 0x4887, 0x86, 0x22, 0x2a, 0x58, 0xba, 0xa6, 0x52, 0xb0);" )

cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

