cpp_quote("#include <winapifamily.h>")

//*@@@+++@@@@******************************************************************
//
// 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>")

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

///////////////////////////////////////////////////////////////////////////////
//
// 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,

#if (WINVER >= _WIN32_WINNT_WINTHRESHOLD)
    /// <summary>
    ///     If set, the Protected Media Path will exist in process.
    ///     If hardware protection is not available, playing protected content
    ///     will fail.
    /// </summary>
    MFPMPSESSION_IN_PROCESS = 0x2,
#endif // (WINVER >= _WIN32_WINNT_WINTHRESHOLD) ")

}   MFPMPSESSION_CREATION_FLAGS;


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

cpp_quote("#if (NTDDI_VERSION >= NTDDI_WIN11_ZN) ")
/// <summary>
/// Use this service GUID to retrieve the IAcousticEchoCancellationControl interface through the capture MFMediaSource's
/// IMFGetService::GetService
/// </summary>
cpp_quote( "EXTERN_GUID( MF_ACOUSTIC_ECHO_CANCELLATION_CONTROL_SERVICE, 0x7f6c3b29, 0x2d12, 0x4f6f, 0xac, 0x5, 0xc1, 0xa8, 0x9b, 0x8d, 0x52, 0x88);" )

/// <summary>
/// Use this service GUID to retrieve the IAudioEffectsManager interface through the capture MFMediaSource's
/// IMFGetService::GetService
/// </summary>
cpp_quote( "EXTERN_GUID( MF_AUDIO_EFFECTS_MANAGER_SERVICE, 0x1f541943, 0xd5df, 0x455e, 0xa2, 0xe5, 0x7d, 0x64, 0xd3, 0xbb, 0xbd, 0xb5);" )
cpp_quote("#endif // (NTDDI_VERSION >= NTDDI_WIN11_ZN) ")


interface IMFTopology;



cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)")

interface IMFClock;
interface IMFPresentationTimeSource;



// WMV Source attributes

// MF_WVC1_PROG_SINGLE_SLICE_CONTENT
// Data type: UINT32
// This attribute is set to 1 if it is certain that all video frames in the WVC1 content use progressive and single slice encoding.  
// Media Source can set this attribute on the IMFMediaType for WVC1 streams 
// 67EC2559-0F2F-4420-A4DD-2F8EE7A5738B
cpp_quote( "EXTERN_GUID( MF_WVC1_PROG_SINGLE_SLICE_CONTENT, 0x67EC2559, 0x0F2F, 0x4420, 0xA4, 0xDD, 0x2F, 0x8E, 0xE7, 0xA5, 0x73, 0x8B);" )



// MPEG4 Source attributes

// MF_PROGRESSIVE_CODING_CONTENT
// Data type: UINT32
// This attribute is set to 1 if it is certain that all video frames in the content use progressive encoding.  
// The MP4 Media Source can set this attribute on the IMFMediaType for H.264 streams after examining the SPS available in the MP4 'moov' box.
// 8F020EEA-1508-471F-9DA6-507D7CFA40DB
cpp_quote( "EXTERN_GUID( MF_PROGRESSIVE_CODING_CONTENT, 0x8F020EEA, 0x1508, 0x471F, 0x9D, 0xA6, 0x50, 0x7D, 0x7C, 0xFA, 0x40, 0xDB);" )



// MF_NALU_LENGTH_SET
// Data type: UINT32
// MPEG-4 file format already has NALU length information available in the file container
// set the attribute of MF_NALU_LENGTH_SET on the media type MEDIASUBTYPE_H264
// indicate that NALU length information will be sent as a blob together with each compressed H.264 sample, 
// which is one picture per sample
cpp_quote( "EXTERN_GUID( MF_NALU_LENGTH_SET, 0xA7911D53, 0x12A4, 0x4965, 0xAE, 0x70, 0x6E, 0xAD, 0xD6, 0xFF, 0x05, 0x51);" )


// MF_NALU_LENGTH_INFORMATION
// Data type: BLOB
// if the media type of MEDIASUBTYPE_H264 has the attribute of MF_NALU_LENGTH_SET set
// each compressed sample from MPEG4 source shall have MF_NALU_LENGTH_INFORMATION set to indicate of the lengths of different NALUs 
// in the sample
cpp_quote( "EXTERN_GUID( MF_NALU_LENGTH_INFORMATION,  0x19124E7C, 0xAD4B, 0x465F, 0xBB, 0x18, 0x20, 0x18, 0x62, 0x87, 0xB6, 0xAF);" )


// MF_USER_DATA_PAYLOAD
// Data type: BLOB
// when the output sample has the attribute of MF_USER_DATA_PAYLOAD set
// user data payload comes together with the output sample 
// user data might contain close caption data, bar data etc
// user data is passed through without any decoding
//
cpp_quote( "EXTERN_GUID( MF_USER_DATA_PAYLOAD,  0xd1d4985d, 0xdc92, 0x457a, 0xb3, 0xa0, 0x65, 0x1a, 0x33, 0xa3, 0x10, 0x47);" )


//
// MPEG4 Sink attributes
//

// MF_MPEG4SINK_SPSPPS_PASSTHROUGH
// Data type: UINT32
// According to Mpeg4 spec, SPS and PPS of H.264 codec should appear in sample
// description box. Mpeg4 sink filters out the SPS and PPS NALU. This attribute
// disables the filtering. SPS and PPS apppear in elementary stream.
cpp_quote( "EXTERN_GUID( MF_MPEG4SINK_SPSPPS_PASSTHROUGH, 0x5601a134, 0x2005, 0x4ad2, 0xb3, 0x7d, 0x22, 0xa6, 0xc5, 0x54, 0xde, 0xb2);" )

// MF_MPEG4SINK_MOOV_BEFORE_MDAT
// Data type: UINT32
// The default behavior of mpeg4 media sink is 'moov' written after 'mdat' box
// By setting this attribute, file generated will have 'moov' written before 'mdat' box.
// The byte stream passed in must not be slow seek or remote for mpeg4 sink to use this attribute.
// Using this feature involves an additonal file copying/remuxing.
cpp_quote( "EXTERN_GUID( MF_MPEG4SINK_MOOV_BEFORE_MDAT, 0xf672e3ac, 0xe1e6, 0x4f10, 0xb5, 0xec, 0x5f, 0x3b, 0x30, 0x82, 0x88, 0x16);" )	

// MF_MPEG4SINK_MINIMUM_PROPERTIES_SIZE 
// {DCA1ED52-450E-4A22-8C62-4ED452F7A187} 
// Data type: UINT32 
// The default behavior of the mpeg4 media sink is to only use the smallest amount of storage 
// needed when writing the metadata properties to the MP4 file header. 
// When this attribute is specified, the media sink reserves the specified amount of storage 
// (in bytes) for metadata properties. If the metadata data properties are updated later, or 
// if new properties are added, the media sink will attempt to update the file in-place by 
// writing the properties into the previously reserved space. This avoids having to rewrite 
// the entire file to make room for the new properties. 
cpp_quote("EXTERN_GUID( MF_MPEG4SINK_MINIMUM_PROPERTIES_SIZE, 0xdca1ed52, 0x450e, 0x4a22, 0x8c, 0x62, 0x4e, 0xd4, 0x52, 0xf7, 0xa1, 0x87);")

// MF_MPEG4SINK_MIN_FRAGMENT_DURATION 
// Data type: UINT64 
// This attribute specifies the minimum duration in hns of each fragment which the MPEG4 sink produces when operating in fragmented mode. 
// If this attribute is set, the MF_MPEG4SINK_MAX_CODED_SEQUENCES_PER_FRAGMENT attribute is ignored. 
// 
cpp_quote("EXTERN_GUID(MF_MPEG4SINK_MIN_FRAGMENT_DURATION, 0xa30b570c, 0x8efd, 0x45e8, 0x94, 0xfe, 0x27, 0xc8, 0x4b, 0x5b, 0xdf, 0xf6);")

// MF_MPEG4SINK_MAX_CODED_SEQUENCES_PER_FRAGMENT 
// Data type: UINT32 
// This attribute specifies the maximum number of coded sequences which the MPEG4 sink will place in each fragment when operating in fragmented mode. 
// A coded sequence is a group of IMFSamples where the first IMFSample has the non-zero value for 
// the MFSampleExtension_CleanPoint attribute, followed by zero or more IMFSamples that have a zero 
// value, or no value, for the MFSampleExtension_CleanPoint attribute. 
// 
cpp_quote("EXTERN_GUID(MF_MPEG4SINK_MAX_CODED_SEQUENCES_PER_FRAGMENT, 0xfc1b3bd6, 0x692d, 0x4ce5, 0x92, 0x99, 0x73, 0x8a, 0xa5, 0x46, 0x3e, 0x9a);")

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

[
    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( "    _Outptr_ IMFMediaSession** ppMediaSession" )
cpp_quote( "    );" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region PC Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PC_APP)")

/// <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( "    _Outptr_ IMFMediaSession** ppMediaSession," )
cpp_quote( "    _Outptr_opt_ IMFActivate **ppEnablerActivate" )
cpp_quote( "    );" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PC_APP) */")
#pragma endregion

#pragma region Application or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)")

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

//
// 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

    MF_RESOLUTION_DISABLE_LOCAL_PLUGINS                       = 0x00000040,
        // This flag causes the source resolver to not attempt to use any locally registered scheme or bytestream handler plugins.

    MF_RESOLUTION_PLUGIN_CONTROL_POLICY_APPROVED_ONLY         = 0x00000080,
        // This flag causes the source resolver to use a local plugin control policy that only allows use of approved plugins.

    MF_RESOLUTION_PLUGIN_CONTROL_POLICY_WEB_ONLY              = 0x00000100,
        // This flag causes the source resolver to use a local plugin control policy that only allows use of web approved plugins.

    MF_RESOLUTION_PLUGIN_CONTROL_POLICY_WEB_ONLY_EDGEMODE     = 0x00000200,
        // This flag causes the source resolver to use a local plugin control policy that only allows use of edge mode web approved plugins.

    MF_RESOLUTION_ENABLE_STORE_PLUGINS                        = 0x00000400,
    // This flag allows the source resolver to use store-distributed bytestream handler plugins

    //
    // Access mode requested
    //
        //In what mode should the requested resource be open
    MF_RESOLUTION_READ              = 0x00010000,
    MF_RESOLUTION_WRITE             = 0x00020000
};
cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

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;

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)")

[
    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("_Outptr_")]  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("_Outptr_")]  IUnknown **ppObject
                );

    [local]
    HRESULT BeginCreateObjectFromURL(
                [in] LPCWSTR pwszURL,
                [in] DWORD dwFlags,
                [in] IPropertyStore *pProps,
                [out, annotation("_Outptr_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("_Outptr_")]  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("_Outptr_opt_")] IUnknown **ppIUnknownCancelCookie,
                [in] IMFAsyncCallback *pCallback,
                [in] IUnknown *punkState
                );

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


    [local]
    HRESULT EndCreateObjectFromByteStream(
                [in]   IMFAsyncResult *pResult,
                [out, annotation("_Out_")]  MF_OBJECT_TYPE *pObjectType,
                [out, annotation("_Outptr_")]  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 */     _Outptr_ IMFSourceResolver     **ppISourceResolver);" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_GAMES)")

cpp_quote( "STDAPI CreatePropertyStore( " )
cpp_quote( "        /* out */     _Outptr_ 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 }; ")

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

#pragma region Application or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)")

// 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("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

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

#pragma region Application or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)")

// 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 }; ")

// Type: VT_UINT32
// Sets the SBE mode.
// 0: default is to use the automatic stream mapping in the crossbar to the output
// 1: Crossbar output multiple streams mapped to the output
// 2: Crossbar mode where the application has to map the streams to the output (selection of the audio stream possible)
// {3FAE10BB-F859-4192-B562-1868D3DA3A02}
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_SBESourceMode = { { 0x3fae10bb, 0xf859, 0x4192, 0xb5, 0x62, 0x18, 0x68, 0xd3, 0xda, 0x3a, 0x02}, 0x01 }; ")

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

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

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

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

// Type: VT_UNKNOWN
// Defines an IMFAsyncCallback implementation that will create the a PMP session on behalf of the bytestream.
// {28bb4de2-26a2-4870-b720-d26bbeb14942}
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_PMP_Creation_Callback = { { 0x28bb4de2, 0x26a2, 0x4870, 0xb7, 0x20, 0xd2, 0x6b, 0xbe, 0xb1, 0x49, 0x42}, 0x01 }; ")

// Type: VT_BOOL
// When set and TRUE, specifies that the HTTP caching bytestream should use URLMon to download
// content.  By default, WinHTTP will be used.
// {eda8afdf-c171-417f-8d17-2e0918303292}, 1
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_HTTP_ByteStream_Enable_Urlmon = { { 0xeda8afdf, 0xc171, 0x417f, 0x8d, 0x17, 0x2e, 0x09, 0x18, 0x30, 0x32, 0x92}, 0x01 }; ")

// TYPE: VT_UI4
// When MFPKEY_HTTP_ByteStream_Enable_Urlmon is turned on, this value specifies the urlmon
// bind flags as defined in the BINDF enumeration.  The default value is BINDF_ASYNCHRONOUS | 
// BINDF_ASYNCSTORAGE | BINDF_NOWRITECACHE | BINDF_PULLDATA | BINDF_RESYNCHRONIZE
// {eda8afdf-c171-417f-8d17-2e0918303292}, 2
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_HTTP_ByteStream_Urlmon_Bind_Flags = { { 0xeda8afdf, 0xc171, 0x417f, 0x8d, 0x17, 0x2e, 0x09, 0x18, 0x30, 0x32, 0x92}, 0x02 }; ")

// TYPE: VT_VECTOR | VT_UI1
// When MFPKEY_HTTP_ByteStream_Enable_Urlmon is turned on, this value specifies the root security
// ID for urlmon.  By default, this value is null and no root security ID will be provided to
// urlmon.
// {eda8afdf-c171-417f-8d17-2e0918303292}, 3
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_HTTP_ByteStream_Urlmon_Security_Id = { { 0xeda8afdf, 0xc171, 0x417f, 0x8d, 0x17, 0x2e, 0x09, 0x18, 0x30, 0x32, 0x92}, 0x03 }; ")

// TYPE: VT_UNKNOWN
// When MFPKEY_HTTP_ByteStream_Enable_Urlmon is turned on, this value specifies an
// implementation of IWindowForBindingUI that can be used to obtain an HWND for urlmon
// UI.  By default, urlmon UI will be disabled.
// {eda8afdf-c171-417f-8d17-2e0918303292}, 4
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_HTTP_ByteStream_Urlmon_Window = { { 0xeda8afdf, 0xc171, 0x417f, 0x8d, 0x17, 0x2e, 0x09, 0x18, 0x30, 0x32, 0x92}, 0x04 }; ")

// TYPE: VT_UNKNOWN
// When MFPKEY_HTTP_ByteStream_Enable_Urlmon is turned on, this value specifies an
// implementation of IServiceProvider that can be used to obtain services for the
// urlmon protocol handler.
// {eda8afdf-c171-417f-8d17-2e0918303292}, 5
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_HTTP_ByteStream_Urlmon_Callback_QueryService = { { 0xeda8afdf, 0xc171, 0x417f, 0x8d, 0x17, 0x2e, 0x09, 0x18, 0x30, 0x32, 0x92}, 0x05 }; ")

// Type: VT_CLSID
// Set to the GUID that identifies the media protection system to use for the content.
// {636B271D-DDC7-49E9-A6C6-47385962E5BD}
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_MediaProtectionSystemId =  { { 0x636b271d, 0xddc7, 0x49e9, 0xa6, 0xc6, 0x47, 0x38, 0x59, 0x62, 0xe5, 0xbd}, 0x01 }; ")

// Type: VT_BLOB
// BLOB containing the context to use when initializing a media protection system's trusted input module.
// {636B271D-DDC7-49E9-A6C6-47385962E5BD}
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_MediaProtectionSystemContext =  { { 0x636b271d, 0xddc7, 0x49e9, 0xa6, 0xc6, 0x47, 0x38, 0x59, 0x62, 0xe5, 0xbd}, 0x02 }; ")

// Type: VT_UNKNOWN
// Set to an IPropertySet that defines the mapping from property system id to property system activation id.
// {636B271D-DDC7-49E9-A6C6-47385962E5BD}
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_MediaProtectionSystemIdMapping =  { { 0x636b271d, 0xddc7, 0x49e9, 0xa6, 0xc6, 0x47, 0x38, 0x59, 0x62, 0xe5, 0xbd}, 0x03 }; ")

// Type: VT_CLSID
// Set to the GUID that identifies the protection system in the container.
// {42AF3D7C-00CF-4a0f-81F0-ADF524A5A5B5}
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_MediaProtectionContainerGuid =  { { 0x42af3d7c, 0xcf, 0x4a0f, 0x81, 0xf0, 0xad, 0xf5, 0x24, 0xa5, 0xa5, 0xb5}, 0x1 }; ")

// Type: VT_UNKNOWN
// Set to an IPropertySet that defines a mapping from track type to IRandomAccessStream containing the DRM context
// {4454B092-D3DA-49b0-8452-6850C7DB764D}
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_MediaProtectionSystemContextsPerTrack =  { { 0x4454b092, 0xd3da, 0x49b0, 0x84, 0x52, 0x68, 0x50, 0xc7, 0xdb, 0x76, 0x4d }, 0x03 }; ")

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

// Type: VT_BOOL
// When set and TRUE, specifies that the URL is being downloaded to disk instead of being played.
// {817f11b7-a982-46ec-a449-ef58aed53ca8}
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_HTTP_ByteStream_Download_Mode = { { 0x817f11b7, 0xa982, 0x46ec, 0xa4, 0x49, 0xef, 0x58, 0xae, 0xd5, 0x3c, 0xa8 }, 0x01 }; ")

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


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

// TYPE: VT_UI4
// This property specifies how the HTTP Byte Stream should cache downloaded data.
// A value of 1 means that the downloaded data should be cached to disk.
// A value of 2 means that the downloaded data should be cached in memory.
// A value of 0 is the default, and means that the Byte Stream is free to choose the caching mode
// based on heuristics.
// {86a2403e-c78b-44d7-8bc8-ff7258117508}, 1
cpp_quote("EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_HTTP_ByteStream_Caching_Mode = { { 0x86a2403e, 0xc78b, 0x44d7, 0x8b, 0xc8, 0xff, 0x72, 0x58, 0x11, 0x75, 0x08}, 0x01 }; ")

// TYPE: VT_UI8
// This property specifies an upper limit on the amount of data, in bytes, that the
// HTTP Byte Stream caches on disk or in memory.
// The Byte Stream may choose a lower limit than the one specified.
// A value of 0 is the default, and means that the Byte Stream is free to limit the cache size
// based on heuristics.
// {86a2403e-c78b-44d7-8bc8-ff7258117508}, 2
cpp_quote("EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MFPKEY_HTTP_ByteStream_Cache_Limit = { { 0x86a2403e, 0xc78b, 0x44d7, 0x8b, 0xc8, 0xff, 0x72, 0x58, 0x11, 0x75, 0x08}, 0x02 }; ")

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


#pragma region Application or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)")


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

/// <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)

#if (WINVER >= _WIN32_WINNT_WIN8)
    /// <summary>
    ///     This bit should be set if the Media Source is not currently
    ///     using the network to receive the content.  Networking hardware
    ///     may enter a power saving state when this bit is set.
    /// </summary>
    MFMEDIASOURCE_DOES_NOT_USE_NETWORK = 0x80
#endif // (WINVER >= _WIN32_WINNT_WIN8)

}   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("_Outptr_")] 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 );
}

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

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


#pragma region Application or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)")

[
    object,
    uuid(3C9B2EB9-86D5-4514-A394-F56664F9F0D8),
]
interface IMFMediaSourceEx : IMFMediaSource
{
    HRESULT GetSourceAttributes(
        [out] IMFAttributes** ppAttributes
        );

    HRESULT GetStreamAttributes(
        [in]  DWORD dwStreamIdentifier,
        [out] IMFAttributes** ppAttributes
        );

    HRESULT SetD3DManager(
        [in]  IUnknown* pManager
        );
}

// MF_SOURCE_STREAM_SUPPORTS_HW_CONNECTION
// Data type: UINT32, treat as BOOL
// Indicates that the media source stream supports HW connection to downstream Hardware MFTs
// {A38253AA-6314-42fd-A3CE-BB27B6859946}
cpp_quote( "EXTERN_GUID( MF_SOURCE_STREAM_SUPPORTS_HW_CONNECTION, 0xa38253aa, 0x6314, 0x42fd, 0xa3, 0xce, 0xbb, 0x27, 0xb6, 0x85, 0x99, 0x46);" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

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

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
interface IMFPresentationClock;

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

#pragma region Application or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)")

[
    object,
    uuid(6ef2a662-47c0-4666-b13d-cbb717f2fa2c)
]
interface IMFClockConsumer : IUnknown
{
    HRESULT SetPresentationClock(
        [in] IMFPresentationClock* pPresentationClock
        );

    HRESULT GetPresentationClock(
        [out] IMFPresentationClock** ppPresentationClock
        );
}

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

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

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

#pragma region Application or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)")

[
    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(
        );
}


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

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

// MF_STREAM_SINK_SUPPORTS_HW_CONNECTION
// Data type: UINT32, treat as BOOL
// Indicates that the stream sink supports HW connection to upstream Hardware MFTs
// {9B465CBF-0597-4f9e-9F3C-B97EEEF90359}
cpp_quote( "EXTERN_GUID( MF_STREAM_SINK_SUPPORTS_HW_CONNECTION, 0x9b465cbf, 0x597, 0x4f9e, 0x9f, 0x3c, 0xb9, 0x7e, 0xee, 0xf9, 0x3, 0x59);" )

// MF_STREAM_SINK_SUPPORTS_ROTATION
// Data type: UINT32, treat as BOOL
// Indicates whether the stream sink supports video rotation
// {B3E96280-BD05-41a5-97AD-8A7FEE24B912} 
cpp_quote( "EXTERN_GUID( MF_STREAM_SINK_SUPPORTS_ROTATION, 0xb3e96280, 0xbd05, 0x41a5, 0x97, 0xad, 0x8a, 0x7f, 0xee, 0x24, 0xb9, 0x12);" )

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


//
// 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" )

/// <summary>
///     Flags to transfer video frame from sink
/// </summary>
typedef enum MF_TRANSFER_VIDEO_FRAME_FLAGS
{
    MF_TRANSFER_VIDEO_FRAME_DEFAULT     = 0,
    MF_TRANSFER_VIDEO_FRAME_STRETCH     = 1,
    MF_TRANSFER_VIDEO_FRAME_IGNORE_PAR  = 2,
} MF_TRANSFER_VIDEO_FRAME_FLAGS;

// MF_SINK_VIDEO_PTS
// Data type: UINT64
// This attribute is the prenstation time stamp of the video frame out of video sink in frame server mode.
//
cpp_quote( "EXTERN_GUID( MF_SINK_VIDEO_PTS,  0x2162bde7, 0x421e, 0x4b90, 0x9b, 0x33, 0xe5, 0x8f, 0xbf, 0x1d, 0x58, 0xb6);" )

// MF_SINK_VIDEO_NATIVE_WIDTH
// Data type: UINT32
// This attribute is the native width of the video frame out of video sink in frame server mode.
//
cpp_quote( "EXTERN_GUID( MF_SINK_VIDEO_NATIVE_WIDTH,  0xe6d6a707, 0x1505, 0x4747, 0x9b, 0x10, 0x72, 0xd2, 0xd1, 0x58, 0xcb, 0x3a);" )

// MF_SINK_VIDEO_NATIVE_HEIGHT
// Data type: UINT32
// This attribute is the native height of the video frame out of video sink in frame server mode.
//
cpp_quote( "EXTERN_GUID( MF_SINK_VIDEO_NATIVE_HEIGHT,  0xf0ca6705, 0x490c, 0x43e8, 0x94, 0x1c, 0xc0, 0xb3, 0x20, 0x6b, 0x9a, 0x65);" )

// MF_SINK_VIDEO_DISPLAY_ASPECT_RATIO_NUMERATOR
// Data type: UINT32
// This attribute is the display aspect ratio numerator of the video frame out of video sink in frame server mode.
//
cpp_quote( "EXTERN_GUID( MF_SINK_VIDEO_DISPLAY_ASPECT_RATIO_NUMERATOR,  0xd0f33b22, 0xb78a, 0x4879, 0xb4, 0x55, 0xf0, 0x3e, 0xf3, 0xfa, 0x82, 0xcd);" )


// MF_SINK_VIDEO_DISPLAY_ASPECT_RATIO_DENOMINATOR
// Data type: UINT32
// This attribute is the display aspect ratio denominator of the video frame out of video sink in frame server mode.
//
cpp_quote( "EXTERN_GUID( MF_SINK_VIDEO_DISPLAY_ASPECT_RATIO_DENOMINATOR,  0x6ea1eb97, 0x1fe0, 0x4f10, 0xa6, 0xe4, 0x1f, 0x4f, 0x66, 0x15, 0x64, 0xe0);" )


// MF_BD_MVC_PLANE_OFFSET_METADATA
// Data type: BLOB
// This attribute is the plane offset metadata defined by Blu-ray Disc MVC spec.
//
cpp_quote( "EXTERN_GUID( MF_BD_MVC_PLANE_OFFSET_METADATA,  0x62a654e4, 0xb76c, 0x4901, 0x98, 0x23, 0x2c, 0xb6, 0x15, 0xd4, 0x73, 0x18);" )


// MF_LUMA_KEY_ENABLE
// Data type: UINT32
// This attribute is a sample attribute to indicate that video render needs to apply luma key.
//
cpp_quote( "EXTERN_GUID( MF_LUMA_KEY_ENABLE, 0x7369820f, 0x76de, 0x43ca, 0x92, 0x84, 0x47, 0xb8, 0xf3, 0x7e, 0x06, 0x49);" )

// MF_LUMA_KEY_LOWER
// Data type: DOUBLE
// This attribute is a sample attribute to store lower limit of luma key.
//
cpp_quote( "EXTERN_GUID( MF_LUMA_KEY_LOWER,  0x93d7b8d5, 0x0b81, 0x4715, 0xae, 0xa0, 0x87, 0x25, 0x87, 0x16, 0x21, 0xe9);" )

// MF_LUMA_KEY_UPPER
// Data type: DOUBLE
// This attribute is a sample attribute to store upper limit of luma key.
//
cpp_quote( "EXTERN_GUID( MF_LUMA_KEY_UPPER,  0xd09f39bb, 0x4602, 0x4c31, 0xa7, 0x06, 0xa1, 0x21, 0x71, 0xa5, 0x11, 0x0a);" )

// MF_USER_EXTENDED_ATTRIBUTES
// Data type: IUNKNOWN
// This attribute is a sample attribute to store user specific sample attributes.
//
cpp_quote( "EXTERN_GUID( MF_USER_EXTENDED_ATTRIBUTES,  0xc02abac6, 0xfeb2, 0x4541, 0x92, 0x2f, 0x92, 0x0b, 0x43, 0x70, 0x27, 0x22);" )

// MF_INDEPENDENT_STILL_IMAGE
// Data type: UINT32
// This attribute is a sample attribute of decoded video frame to indicate that video processor should treat it
// as independent frame without referencing on past frames during deinterlacing.
//
cpp_quote( "EXTERN_GUID( MF_INDEPENDENT_STILL_IMAGE, 0xea12af41, 0x0710, 0x42c9, 0xa1, 0x27, 0xda, 0xa3, 0xe7, 0x84, 0x83, 0xa5);" )


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(3978AA1A-6D5B-4B7F-A340-90899189AE34),
    local
]
interface IMFVideoSampleAllocatorNotifyEx : IMFVideoSampleAllocatorNotify
{
    HRESULT NotifyPrune(IMFSample *);
};


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

    HRESULT GetFreeSampleCount(
        [out] LONG* plSamples);
};

[
    object,
    local,
    uuid(545b3a48-3283-4f62-866f-a62d8f598f9f),
    helpstring("IMFVideoSampleAllocatorEx Interface"),
    pointer_default(unique)
]
/// <summary>
///    The IMFVideoSampleAllocatorEx interface (used with DXGI buffer allocators)
/// </summary>
interface IMFVideoSampleAllocatorEx : IMFVideoSampleAllocator
{
    HRESULT InitializeSampleAllocatorEx(
        [annotation("_In_")]  DWORD cInitialSamples,
        [annotation("_In_")]  DWORD cMaximumSamples,
        [annotation("_In_opt_")]  IMFAttributes *pAttributes,
        [annotation("_In_")]  IMFMediaType *pMediaType
    );
};

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

[
    object,
    uuid(20bc074b-7a8d-4609-8c3b-64a0a3b5d7ce),
    pointer_default(unique)
]
/// <summary>
///    This interface is implemented by the Windows.Media.Core.MediaStreamSource runtime class.
/// </summary>
interface IMFDXGIDeviceManagerSource : IUnknown
{
    HRESULT GetManager(
        [out] IMFDXGIDeviceManager** ppManager);
}

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

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

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

typedef enum _MF_VIDEO_PROCESSOR_ROTATION
{
    ROTATION_NONE                = 0,
    ROTATION_NORMAL              = 1
} MF_VIDEO_PROCESSOR_ROTATION;

typedef enum _MF_VIDEO_PROCESSOR_MIRROR
{
    MIRROR_NONE                = 0,
    MIRROR_HORIZONTAL          = 1,
    MIRROR_VERTICAL            = 2
} MF_VIDEO_PROCESSOR_MIRROR;

[
    object,
    local,
    uuid(A3F675D5-6119-4f7f-A100-1D8B280F0EFB),
    helpstring("Configuration interface for Video Processors"),
    pointer_default(unique)
]
/// <summary>
///     Configuration interface for Video Processors
/// </summary>
interface IMFVideoProcessorControl : IUnknown
{
    HRESULT SetBorderColor( [in, annotation("_In_opt_")] MFARGB* pBorderColor );

    HRESULT SetSourceRectangle( [in, annotation("_In_opt_")] RECT* pSrcRect );

    HRESULT SetDestinationRectangle( [in, annotation("_In_opt_")] RECT* pDstRect );

    HRESULT SetMirror( [in, annotation("_In_")] MF_VIDEO_PROCESSOR_MIRROR eMirror );

    HRESULT SetRotation( [in, annotation("_In_")] MF_VIDEO_PROCESSOR_ROTATION eRotation );

    HRESULT SetConstrictionSize( [in, annotation("_In_opt_")] SIZE* pConstrictionSize );
};

cpp_quote("#if (WINVER >= _WIN32_WINNT_WINBLUE) ")
[
    object,
    local,
    uuid(BDE633D3-E1DC-4a7f-A693-BBAE399C4A20),
    pointer_default(unique)
]
/// <summary> 
///     Configuration interface for Video Processors (version 2) 
/// </summary> 
interface IMFVideoProcessorControl2 : IMFVideoProcessorControl
{
    /// <summary>
    ///     The SetRotationOverride method overrides the rotation operation 
    ///     performed in the video processor.
    /// </summary>
    /// <param name=uiRotation>
    ///     Rotation value in degrees.  Generally only values from
    ///     the MFVideoRotationFormat enum are supported.
    /// </param>
    HRESULT SetRotationOverride([in, annotation("_In_")] UINT uiRotation);

    /// <summary>
    ///     The EnableHardwareEffects method enables VideoProcessorBlt
    ///     implemented effects when using VideoProcessorBlt.
    /// </summary>
    /// <param name=fEnabled>
    ///     Whether effects should be enabled.
    /// </param>
    HRESULT EnableHardwareEffects([in, annotation("_In_")] BOOL fEnabled);

    /// <summary>
    ///     The GetSupportedHardwareEffects method returns the list of
    ///     supported effects in the currently configured video processor.
    /// </summary>
    /// <param name=puiSupport>
    ///     Bitwise OR of effect capabilities from D3D11_VIDEO_PROCESSOR_AUTO_STREAM_CAPS
    /// </param>
    HRESULT GetSupportedHardwareEffects([out, retval, annotation("_Out_")] UINT *puiSupport);
};

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

// Enum describing the packing for spherical video frames
typedef enum _MFVideoSphericalFormat {
    MFVideoSphericalFormat_Unsupported = 0,
    MFVideoSphericalFormat_Equirectangular = 1,
    MFVideoSphericalFormat_CubeMap = 2,
    MFVideoSphericalFormat_3DMesh = 3
} MFVideoSphericalFormat;

cpp_quote("#endif /* (WINVER >= _WIN32_WINNT_WIN10) */ ")

// TODO: NTDDI_WIN10_RS4
cpp_quote("#if (NTDDI_VERSION >= NTDDI_WIN10_RS3) ")

// MF_XVP_SAMPLE_LOCK_TIMEOUT 
// Data type: UINT32  
// Timeout value used for sample locking operations in XVP.  Value is in milliseconds. 
// The timeout applies to an IMFSample that uses a lock to protect access to the buffer.  
// For example, if the IMFSample references a shared D3D texture that is protected by 
// IDXGIKeyedMutex, then the timeout is used when trying to acquire the IDXGIKeyedMutex. 
// After failing to acquire the lock due to a timeout, XVP will return E_TIMEOUT from ProcessOutput. 
// {AA4DDB29-5134-4363-AC72-83EC4BC10426} 
cpp_quote("EXTERN_GUID( MF_XVP_SAMPLE_LOCK_TIMEOUT, 0xaa4ddb29, 0x5134, 0x4363, 0xac, 0x72, 0x83, 0xec, 0x4b, 0xc1, 0x4, 0x26);")

// This enumeration describes different types of  
// spherical projection modes used when projecting 
// from a stream representation to a 3D representation. 
typedef enum MFVideoSphericalProjectionMode
{
    // The current view should be projected onto a sphere in 3D space. 
    MFVideoSphericalProjectionMode_Spherical = 0,
    // The current view should be projected onto a flat surface. 
    MFVideoSphericalProjectionMode_Flat
} MFVideoSphericalProjectionMode;

[
    object,
    local,
    uuid(2424B3F2-EB23-40f1-91AA-74BDDEEA0883)
]
/// <summary>  
///     Configuration interface for Video Processors (version 3)  
/// </summary>  
interface IMFVideoProcessorControl3 : IMFVideoProcessorControl2
{
    /// <summary> 
    ///     For a given input type, returns the "natural output type" of the video. 
    ///     The natural type is defined as: 
    ///       * no scaling applied 
    ///       * no color conversions applied 
    ///     This accounts for any rotation / cropping / pixel aspect applied to the video. 
    /// </summary> 
    /// <param name=ppType> 
    ///     Returns a media type containing the natural output type. 
    /// </param> 
    HRESULT GetNaturalOutputType([out, annotation("_Outptr_")] IMFMediaType **ppType);

    // Sets spherical video processing properties 
    /// <summary> 
    ///     Enables spherical video rendering (360 video). 
    /// </summary> 
    /// <param name=fEnable> 
    ///     Whether rendering is enabled. 
    /// </param> 
    /// <param name=eFormat> 
    ///     The type of spherical video to render. 
    /// </param> 
    /// <param name=eProjectionMode> 
    ///     How the spherical video should be projected. 
    /// </param> 
    HRESULT EnableSphericalVideoProcessing(
        [in, annotation("_In_")] BOOL fEnable,
        [in, annotation("_In_")] MFVideoSphericalFormat eFormat,
        [in, annotation("_In_")] MFVideoSphericalProjectionMode eProjectionMode
    );

    // Sets spherical video processing properties 
    /// <summary> 
    ///     When rendering spherical video (360 video) this sets the view 
    ///     direction of the camera.  X,Y,Z,W are the components of the 
    ///     camera's view direction quaternion.  This quaternion can be  
    ///     left un-normalized, or normalized. 
    /// </summary> 
    /// <param name=X> 
    ///     X component of view direction quaternion. 
    /// </param> 
    /// <param name=Y> 
    ///     Y component of view direction quaternion. 
    /// </param> 
    /// <param name=Z> 
    ///     Z component of view direction quaternion. 
    /// </param> 
    /// <param name=W> 
    ///     W component of view direction quaternion. 
    /// </param> 
    /// <param name=fieldOfView> 
    ///     Field of view in degrees. 
    /// </param> 
    HRESULT SetSphericalVideoProperties(
        [in, annotation("_In_")] float X,
        [in, annotation("_In_")] float Y,
        [in, annotation("_In_")] float Z,
        [in, annotation("_In_")] float W,
        [in, annotation("_In_")] float fieldOfView
    );

    /// <summary> 
    ///     When the video processor is used as part of a renderer and the renderer 
    ///     has knowledge of the output device; the output device is passed to the video 
    ///     processor with SetOutputDevice. 
    /// </summary> 
    /// <param name=pOutputDevice> 
    ///     IUnknown of the output device.  This may be either a IDXGIOutput or  
    ///     Windows.Graphics.Display.IDisplayInformation depending on the renderer. 
    /// </param> 
    HRESULT SetOutputDevice([in, annotation("_In_")] IUnknown *pOutputDevice);
};

cpp_quote("#endif /* (NTDDI_VERSION >= NTDDI_WIN10_RS3) */ ")

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

cpp_quote("#if (NTDDI_VERSION >= NTDDI_WIN10_VB) ")

[
    object,
    local,
    uuid(604D33D7-CF23-41d5-8224-5BBBB1A87475)
]
/// <summary> 
/// Configuration interface for Video Renderer Effects 
/// </summary> 
interface IMFVideoRendererEffectControl : IUnknown
{
    /// <summary> 
    /// When the Renderer Effect requests a communication channel using the 
    /// MF_VIDEO_RENDERER_EFFECT_APP_SERVICE_NAME MFT attribute, this method will 
    /// be called asynchronously by the platform on successful establishment of the requested 
    /// communication channel. The Video Renderer Effect's App Service implements this 
    /// interface. 
    /// </summary> 
    /// <param name=pAppServiceConnection> 
    /// IUnknown of the app service connection object. 
    /// </param> 
    HRESULT OnAppServiceConnectionEstablished([in, annotation("_In_")] IUnknown* pAppServiceConnection);
};

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

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

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

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

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 );
};

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

//
// 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) ")

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

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;

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

// 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_ENABLE_XVP_FOR_PLAYBACK
// Data type: BOOL (UINT32)
// If set, topoloader will pull in video processor if necessary during non-transcode topology resolution.
// {1967731F-CD78-42fc-B026-0992A56E5693}
cpp_quote( "EXTERN_GUID(MF_TOPOLOGY_ENABLE_XVP_FOR_PLAYBACK, 0x1967731f, 0xcd78, 0x42fc, 0xb0, 0x26, 0x9, 0x92, 0xa5, 0x6e, 0x56, 0x93);" )

// 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);" )

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

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,

    /// <summary>
    ///     If hardware MFTs are available, the topoloader will insert
    ///     them.  If not, the connection will fail.
    /// </summary>
    MFTOPOLOGY_HWMODE_USE_ONLY_HARDWARE = 2,

} 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 /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

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

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

// MF_DISABLE_LOCALLY_REGISTERED_PLUGINS
// Data type: UINT32
// Set this attribute to TRUE to prevent the topoloader from inserting locally registered transforms.
// {66b16da9-add4-47e0-a16b-5af1fb483634}
cpp_quote( "EXTERN_GUID( MF_DISABLE_LOCALLY_REGISTERED_PLUGINS, 0x66b16da9, 0xadd4, 0x47e0, 0xa1, 0x6b, 0x5a, 0xf1, 0xfb, 0x48, 0x36, 0x34);" )

// MF_LOCAL_PLUGIN_CONTROL_POLICY
// Data type: UINT32
// Set this attribute to one of the MF_PLUGIN_CONTROL_POLICY values.
// This allows the app to specify a local policy that can be more restrictive than the
// process wide policy configured via IMFPluginControl.
// {d91b0085-c86d-4f81-8822-8c68e1d7fa04}
cpp_quote( "EXTERN_GUID( MF_LOCAL_PLUGIN_CONTROL_POLICY, 0xd91b0085, 0xc86d, 0x4f81, 0x88, 0x22, 0x8c, 0x68, 0xe1, 0xd7, 0xfa, 0x04);" )

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

#pragma region PC Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PC_APP)")

//
// Topology functions
//
cpp_quote( "STDAPI MFCreateTopology(" )
cpp_quote( "    _Outptr_ 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;

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PC_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

/// <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("_Outptr_")] 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("_Outptr_")] 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_WORKQUEUE_MMCSS_PRIORITY
// Data type: INT32 (aliased as UINT32)
// MMCSS TaskId to be used for the work queue serving this node
cpp_quote( "EXTERN_GUID( MF_TOPONODE_WORKQUEUE_MMCSS_PRIORITY, 0x5001f840, 0x2816, 0x48f4, 0x93, 0x64, 0xad, 0x1e, 0xf6, 0x61, 0xa1, 0x23);" )

// MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY
// Data type: INT32
// MMCSS TaskId to be used for the work queue serving this node
cpp_quote( "EXTERN_GUID( MF_TOPONODE_WORKQUEUE_ITEM_PRIORITY, 0xa1ff99be, 0x5e97, 0x4a53, 0xb4, 0x94, 0x56, 0x8c, 0x64, 0x2c, 0x0f, 0xf3);" )

// 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);" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

//
// Topology node functions
//

#pragma region PC Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PC_APP)")

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PC_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

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( "    _Outptr_ IMFMediaType** ppType);" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)")

[
    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( "    _Outptr_ 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>
cpp_quote("#if defined(_MSC_VER) && (_MSC_VER >= 1600)")
cpp_quote("#pragma warning(push)")
cpp_quote("#pragma warning(disable:4820) // Disable C4820: padding after data member")
cpp_quote("#endif")
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;
cpp_quote("#if defined(_MSC_VER) && (_MSC_VER >= 1600)")
cpp_quote("#pragma warning(pop)")
cpp_quote("#endif")


/// <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(
        );

}

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

#pragma region PC Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PC_APP)")

/// <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( "    _Outptr_ IMFPresentationClock** ppPresentationClock" )
cpp_quote( "    );" )

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PC_APP) */")
#pragma endregion

#pragma region Application or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)")

[
    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( "    _Outptr_ 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
        );

}

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

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

///////////////////////////////////////////////////////////////////////////////
//
// 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 );" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)")

// 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) ")

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

// MF_PD_ADAPTIVE_STREAMING
// Data type: UINT32 (treat as BOOL)
// {EA0D5D97-29F9-488B-AE6B-7D6B4136112B}
// Indicates on the presentation descriptor that the source content uses adaptive streaming.
// Pulling the content faster or slower than real time may cause bitrate switches.
cpp_quote("DEFINE_GUID( MF_PD_ADAPTIVE_STREAMING, 0xEA0D5D97, 0x29F9, 0x488B, 0xAE, 0x6B, 0x7D, 0x6B, 0x41, 0x36, 0x11, 0x2B);")

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

[
    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_reads_opt_( cStreamDescriptors ) IMFStreamDescriptor** apStreamDescriptors," )
cpp_quote( "    _Outptr_ IMFPresentationDescriptor** ppPresentationDescriptor" )
cpp_quote( "    );" )
cpp_quote("")

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

#pragma region Desktop or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_GAMES)")


//
// 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( "    _Outptr_result_bytebuffer_to_(*pcbData, *pcbData) BYTE ** ppbData);" )
cpp_quote("")

cpp_quote( "STDAPI MFDeserializePresentationDescriptor(" )
cpp_quote( "    _In_ DWORD cbData," )
cpp_quote( "    _In_reads_( cbData ) BYTE * pbData," )
cpp_quote( "    _Outptr_ IMFPresentationDescriptor ** ppPD);")
cpp_quote("")

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

#pragma region Application or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)")

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

// 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);" )

// MF_SD_SUPPORTS_PROTECTED_CODEC_SWITCH
// Data type: UINT32 (treat as BOOL)
// {8fb6b117-862e-4b31-8dab-5e0a434caef0}
// Indicates that the media processor can do a codec switch in response to MEStreamFormatChanged
// even if the content is protected.
cpp_quote("DEFINE_GUID( MF_SD_SUPPORTS_PROTECTED_CODEC_SWITCH, 0x8fb6b117, 0x862e, 0x4b31, 0x8d, 0xab, 0x5e, 0x0a, 0x43, 0x4c, 0xae, 0xf0);")

[
    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_reads_(cMediaTypes) IMFMediaType** apMediaTypes," )
cpp_quote( "    _Outptr_ 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("_Outptr_opt_result_maybenull_")] IMFMediaType** ppMediaType
        );

    [call_as(IsMediaTypeSupported)]
    HRESULT RemoteIsMediaTypeSupported(
        [in, size_is(cbData)] BYTE *pbData,
        [in] DWORD cbData,
        [out, size_is(, *pcbBestMatch)] BYTE ** ppbBestMatch,
        [out] DWORD * pcbBestMatch
        );

    HRESULT GetMediaTypeCount(
        [out] DWORD* pdwTypeCount
        );

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

    [call_as(GetMediaTypeByIndex)]
    HRESULT RemoteGetMediaTypeByIndex(
        [in] DWORD dwIndex,
        [out, size_is(, *pcbData)] BYTE ** ppbData,
        [out] DWORD * pcbData
        );

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

    [call_as(SetCurrentMediaType)]
    HRESULT RemoteSetCurrentMediaType(
        [in, size_is(cbData)] BYTE *pbData,
        [in] DWORD cbData
        );

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

    [call_as(GetCurrentMediaType)]
    HRESULT RemoteGetCurrentMediaType(
        [out, size_is(, *pcbData)] BYTE ** ppbData,
        [out] DWORD * pcbData
        );

    HRESULT GetMajorType(
       [out] GUID* pguidMajorType
       );
};

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

//
// 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( "    _Outptr_ 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 );" )

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

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);
};

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

//
// 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( "    _Outptr_ IMFMediaSink** ppSink" )
cpp_quote( "    );" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region PC Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PC_APP)")

/// <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( "    _Outptr_ IMFActivate ** ppActivate " )
cpp_quote( "    );" )


cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PC_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

//
// 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);" )

// MF_AUDIO_RENDERER_ATTRIBUTE_STREAM_CATEGORY
// Data type: UINT32
// This attribute allows the caller to pass in the audio stream category, to have an audio media sink use this category when creating the audio stream.
// See AudioSessionTypes.h for the list of valid audio stream categories that can be passed with this attribute.
// If no stream category is specified, a default stream category of 'Other' will be used.
cpp_quote( "EXTERN_GUID( MF_AUDIO_RENDERER_ATTRIBUTE_STREAM_CATEGORY, 0xa9770471, 0x92ec, 0x4df4, 0x94, 0xfe, 0x81, 0xc3, 0x6f, 0xc, 0x3a, 0x7a);" )

//
// 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( "    _Outptr_ 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( "    _Outptr_ 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( "    _Outptr_ 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( "    _Outptr_ IMFMediaSink** ppMediaSink " )
cpp_quote( "    );" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN8) ")
/// <summary>
///     Creates an AC-3 archive sink.  The AC-3 archive sink takes compressed AC-3
///     audio and writes it to an .ac3 file.
/// </summary>
/// <param name="pTargetByteStream">
///     Pointer to the byte stream that will be used to write the .ac3 file
/// </param>
/// <param name="ppMediaSink">
///     Receives a pointer to the IMFMediaSinkInterface.  The caller must release this interface.
/// </param>
cpp_quote( "STDAPI" )
cpp_quote( "MFCreateAC3MediaSink(" )
cpp_quote( "    _In_ IMFByteStream* pTargetByteStream, " )
cpp_quote( "    _In_ IMFMediaType* pAudioMediaType, " )
cpp_quote("     _Outptr_ IMFMediaSink** ppMediaSink " )
cpp_quote( "    );" )

/// <summary>
///     Creates an ADTS archive sink.  The ADTS archive sink takes compressed AAC
///     audio and writes it to an ADTS file.
/// </summary>
/// <param name="pTargetByteStream">
///     Pointer to the byte stream that will be used to write the ADTS file
/// </param>
/// <param name="ppMediaSink">
///     Receives a pointer to the IMFMediaSinkInterface.  The caller must release this interface.
/// </param>
cpp_quote( "STDAPI" )
cpp_quote( "MFCreateADTSMediaSink(" )
cpp_quote( "    _In_ IMFByteStream* pTargetByteStream, " )
cpp_quote( "    _In_ IMFMediaType* pAudioMediaType, " )
cpp_quote("     _Outptr_ IMFMediaSink** ppMediaSink " )
cpp_quote( "    );" )

/// <summary>
///     Creates a generic multiplexer sink. The sink queries for a MFT multiplexer that outputs
///     a stream of MFMediaType_Stream major type and the specified subtype and attributes; if found,
///     the sink then uses this MFT to multiplex the input streams.
/// </summary>
/// <param name="guidOutputSubType">
///     The subtype GUID of the output type of the MFT mux to be used by the sink.
/// </param>
/// <param name="pOutputAttributes">
///     Optional; can be null.
///     Pointer to the list of attributes that the MFT mux output type must support.
/// </param>
/// <param name="pOutputByteStream">
///     Optional; can be null.
///     Pointer to the byte stream that output data will be written to.
/// </param>
/// <param name="ppMuxSink">
///     Receives a pointer to the IMFMediaSink interface. The caller must release this interface.
/// </param>
/// <returns>
///     If the method succeeds and a MFT mux supporting the request output format is found, the return value is S_OK.
///     If a MFT for the requested output format could not be found or the method fails for some other reason,
///         the return value will be a failure code.
/// </returns>
cpp_quote( "STDAPI" )
cpp_quote( "MFCreateMuxSink(" )
cpp_quote( "    _In_ GUID guidOutputSubType, " )
cpp_quote( "    _In_opt_ IMFAttributes* pOutputAttributes, " )
cpp_quote( "    _In_opt_ IMFByteStream* pOutputByteStream, " )
cpp_quote( "    _Outptr_ IMFMediaSink** ppMuxSink " )
cpp_quote( "    );" )

/// <summary>
///     Creates a Fragmented MPEG4 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( "MFCreateFMPEG4MediaSink(" )
cpp_quote( "    _In_ IMFByteStream* pIByteStream, " )
cpp_quote( "    _In_opt_ IMFMediaType* pVideoMediaType, " )
cpp_quote( "    _In_opt_ IMFMediaType* pAudioMediaType, " )
cpp_quote( "    _Outptr_ IMFMediaSink** ppIMediaSink " )
cpp_quote( "    );" )

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

cpp_quote("#if (WINVER >= _WIN32_WINNT_WINBLUE) ")
/// <summary>
///     Creates an AVI Sink
/// </summary>
/// <param name="pIByteStream">
///     Pointer to the byte stream that will be used to write the AVI 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 IMFMediaSink Interface.  The caller must release this interface.
/// </param>
cpp_quote( "STDAPI" )
cpp_quote( "MFCreateAVIMediaSink(" )
cpp_quote( "    _In_ IMFByteStream* pIByteStream, " )
cpp_quote( "    _In_ IMFMediaType* pVideoMediaType, " )
cpp_quote( "    _In_opt_ IMFMediaType* pAudioMediaType, " )
cpp_quote( "    _Outptr_ IMFMediaSink** ppIMediaSink " )
cpp_quote( "    );" )

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

cpp_quote("#if (WINVER >= _WIN32_WINNT_WINBLUE) ")
/// <summary>
///     Creates an WAVE archive sink.  The WAVE archive sink takes
///     audio and writes it to an .wav file.
/// </summary>
/// <param name="pTargetByteStream">
///     Pointer to the byte stream that will be used to write the .wav file
/// </param>
/// <param name="ppMediaSink">
///     Receives a pointer to the IMFMediaSinkInterface.  The caller must release this interface.
/// </param>
cpp_quote( "STDAPI" )
cpp_quote( "MFCreateWAVEMediaSink(" )
cpp_quote( "    _In_ IMFByteStream* pTargetByteStream, " )
cpp_quote( "    _In_ IMFMediaType* pAudioMediaType, " )
cpp_quote("     _Outptr_ IMFMediaSink** ppMediaSink " )
cpp_quote( "    );" )

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

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

///////////////////////////////////////////////////////////////////////////////
//
// 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("_Outptr_")] 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( "    _Outptr_ IMFTopoLoader ** ppObj );" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

///////////////////////////////////////////////////////////////////////////////
//
// 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();
};

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

//
// Content Enabler Type GUIDs
//
#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")
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("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

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("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

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 ) ")

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

[
    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("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

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) ")

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

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


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("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

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) ")

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion


#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN8) ")
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
[
    object, 
    uuid(26AFEA53-D9ED-42B5-AB80-E64F9EE34779),
    local
]
/// <summary>
///     A Media Source container plugin implements this interface
///     in order to demux raw multimedia data into media samples
///     pertaining to one or more media streams.
/// </summary>
/// <remarks>
///     A Media Source container plugin is required to implement
///     this interface.
/// </remarks>
interface IMFSeekInfo : IUnknown{
    /// <summary>
    ///     For a given seek position, find the two nearest key frames
    /// </summary>
    /// <param name="pguidTimeFormat">
    ///     Pointer to a GUID that specifies the time format.
    ///     This can be GUID_NULL, in which case the time
    ///     format is in 100-nanosecond units.
    /// </param>
    /// <param name="pvarStartPosition">
    ///     Specifies the start position.  The units for this parameter
    ///     are indicated by the time format given in pguidTimeFormat.
    /// </param>
    /// <param name="pvarPreviousKeyFrame">
    ///     Receives previous key frame information. The units for this parameter
    ///     are indicated by the time format given in pguidTimeFormat.
    /// </param>
    /// <param name="pvarNextKeyFrame">
    ///     Receives next key frame information. The units for this parameter
    ///     are indicated by the time format given in pguidTimeFormat.
    /// </param>
    HRESULT GetNearestKeyFrames(
        [in, annotation("_In_")] const GUID *pguidTimeFormat,
        [in, annotation("_In_")] const PROPVARIANT *pvarStartPosition,
        [out, annotation("_Out_")] PROPVARIANT *pvarPreviousKeyFrame,
        [out, annotation("_Out_")] PROPVARIANT *pvarNextKeyFrame
        );
}
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN8) ")

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion


#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

//
// Use this GUID to get information to perform scrubbing efficiently
//
cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN8) ")
cpp_quote( "EXTERN_C const GUID MF_SCRUBBING_SERVICE;")
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN8) ")

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

[
    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);" )

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN8) ")
//
// Use this service GUID to retrieve IMFSimpleAudioVolume through
// IMFGetService::GetService. The retrieved interface will control capture volume.
//
cpp_quote( "EXTERN_GUID( MR_CAPTURE_POLICY_VOLUME_SERVICE, 0x24030acd, 0x107a, 0x4265, 0x97, 0x5c, 0x41, 0x4e, 0x33, 0xe6, 0x5f, 0x2a);" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN8) ")

[
    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("_Outptr_")] LPWSTR *pszName
                );
    HRESULT SetIconPath(
                [in] LPCWSTR pszPath
                );
    HRESULT GetIconPath(
                [out, annotation("_Outptr_")] 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_reads_bytes_(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( "    _Outptr_ 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_reads_bytes_(dwSampleSize)")] const BYTE * pSampleBuffer,
        [in] DWORD dwSampleSize,
        [in, annotation("_In_")] IMFAttributes* pAttributes
        );

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

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

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

[
   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);" )


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

[
   object,
   uuid(96bf961b-40fe-42f1-ba9d-320238b49700),
]
/// <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 IMFWorkQueueServicesEx : IMFWorkQueueServices
{
    /// <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 GetTopologyWorkQueueMMCSSPriority(
        [in] DWORD dwTopologyWorkQueueId,
        [out] LONG * plPriority );

    /// <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 BeginRegisterPlatformWorkQueueWithMMCSSEx(
        [in] DWORD dwPlatformWorkQueue,
        [in] LPCWSTR wszClass,
        [in] DWORD dwTaskId,
        [in] LONG lPriority,
        [in] IMFAsyncCallback * pCallback,
        [in] IUnknown * pState );

    [call_as(BeginRegisterPlatformWorkQueueWithMMCSSEx)]
    HRESULT RemoteBeginRegisterPlatformWorkQueueWithMMCSSEx(
        [in] DWORD dwPlatformWorkQueue,
        [in] LPCWSTR wszClass,
        [in] DWORD dwTaskId,
        [in] LONG lPriority,
        [in] IMFRemoteAsyncCallback * pCallback );

    /// <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 GetPlatformWorkQueueMMCSSPriority(
        [in] DWORD dwPlatformWorkQueueId,
        [out] LONG * plPriority );
};

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

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

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

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("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

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

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion


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

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

///////////////////////////////////////////////////////////////////////////////
[
    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( "    _Outptr_ IMFQualityManager **ppQualityManager );" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")
///////////////////////////////////////////////////////////////////////////////
//  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("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

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

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

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

[
    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 /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

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

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

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

[
   object,
   uuid(2347D60B-3FB5-480c-8803-8DF3ADCD3EF0),
   local
]
/// <summary>
///     Use IMFRealTimeClientEx instead
/// </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 branch about which work queue is being used through this
    ///     function.
    /// </summary>
    HRESULT SetWorkQueue(
        [in] DWORD dwWorkQueueId );
};

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

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

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

[
   object,
   uuid(03910848-AB16-4611-B100-17B88AE2F248)   
]
/// <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 IMFRealTimeClientEx : IUnknown
{
    /// <summary>
    ///     This method is called by MF when the RT operations start.
    ///     Implementation uses this data for enlisting threads in MMCSS
    /// </summary>
    HRESULT RegisterThreadsEx(
        [in, out] DWORD* pdwTaskIndex,
        [in] LPCWSTR wszClassName,
        [in] LONG lBasePriority );

    /// <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 branch about which work queue is being used through this
    ///     function.
    /// </summary>
    HRESULT SetWorkQueueEx(
        [in] DWORD dwMultithreadedWorkQueueId,
        [in] LONG lWorkItemBasePriority );
};

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

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

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

///////////////////////////////////////////////////////////////////////////////
//
// 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( "    _Outptr_ 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("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

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( "    _Outptr_ IMFMediaSource **ppAggSource" )
cpp_quote( "    );" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN7) ")

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

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

[
    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.
//
cpp_quote("#if defined(_MSC_VER) && (_MSC_VER >= 1600)")
cpp_quote("#pragma warning(push)")
cpp_quote("#pragma warning(disable:4820 4201) // Disable C4820: padding after data member, C4201: nonstandard extension used: nameless struct/union")
cpp_quote("#endif")
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;
cpp_quote("#if defined(_MSC_VER) && (_MSC_VER >= 1600)")
cpp_quote("#pragma warning(pop)")
cpp_quote("#endif")

[
    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
//
///////////////////////////////////////////////////////////////////////////////

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

/// <summary>
///     The MFBYTESTREAM_BUFFERING_PARAMS structure is for passing the buffering parameters to the byte stream.
/// </summary>
cpp_quote("#if defined(_MSC_VER) && (_MSC_VER >= 1600)")
cpp_quote("#pragma warning(push)")
cpp_quote("#pragma warning(disable:4820) // Disable C4820: padding after data member")
cpp_quote("#endif")

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

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;

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

cpp_quote("#if defined(_MSC_VER) && (_MSC_VER >= 1600)")
cpp_quote("#pragma warning(pop)")
cpp_quote("#endif")


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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

[
    object,
    uuid(6d66d782-1d4f-4db7-8c63-cb8c77f1ef5e),
]
/// <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] 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),
]
/// <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(64976BFA-FB61-4041-9069-8C9A5F659BEB),
]
/// <summary>
///     The IMFByteStreamTimeSeek interface allows time based seek in
///     byte stream.
/// </summary>
interface IMFByteStreamTimeSeek : IUnknown
{
    /// <summary>
    ///     Verifies if the Byte Stream supports time based seeking.
    /// </summary>
    /// <param name=pfTimeSeekIsSupported>
    ///     Pointer to the result of the operation, which will be TRUE if
    ///     the Byte Stream supports time based seeking, and FALSE otherwise.
    ///     This parameter is optional and the caller can use the HRESULT instead.
    /// </param>
    /// <returns>
    ///     <para> S_OK: Time based seeking is supported. </para>
    ///     <para> S_FALSE: Time based seeking is not supported. </para>
    /// </returns>
    HRESULT IsTimeSeekSupported(
        [out] BOOL* pfTimeSeekIsSupported
        );

    /// <summary>
    ///     Performs a time based seek in the Byte Stream.
    /// </summary>
    /// <param name=qwTimePosition>
    ///     Position to seek (in hundreds of nanoseconds).
    /// </param>
    HRESULT TimeSeek(
        [in] QWORD qwTimePosition
        );

    /// <summary>
    ///     Retrieves information provided by the remote server in response
    //       to a time based seek.
    //       This method normally cannot be invoked until after some data
    //       has been read from the byte stream, as invoking the TimeSeek
    //       method does not necessarily cause the request to be sent to the
    //       server immediately.
    /// </summary>
    /// <param name=pqwStartTime>
    ///     Position that the server seeked to (in hundreds of nanoseconds).
    /// </param>
    /// <param name=pqwStopTime>
    ///     Position that the server will stop at (in hundreds of nanoseconds), or 0 if unknown.
    /// </param>
    /// <param name=pqwDuration>
    ///     Total duration of file being downloaded (in hundreds of nanoseconds), or -1 if unknown.
    /// </param>
    HRESULT GetTimeSeekResult(
        [out] QWORD *pqwStartTime,
        [out] QWORD *pqwStopTime,
        [out] QWORD *pqwDuration
        );
};

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

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

typedef struct
{
    // The start offset, in bytes, of a range of cached data
    QWORD qwStartOffset;
    // The end offset, in bytes, of a range of cached data
    QWORD qwEndOffset;
} MF_BYTE_STREAM_CACHE_RANGE;

[
    object,
    uuid(71CE469C-F34B-49EA-A56B-2D2A10E51149),
]
/// <summary>
///     This interface is exposed by byte streams that transfer data from
///     a remote resource to a local cache in the background.  This interface
///     provides additional control over IMFByteStreamCacheControl2 over the
///     way the transfer happens.
/// </summary>
interface IMFByteStreamCacheControl2 : IMFByteStreamCacheControl
{
    /// <summary>
    ///     Returns a series of MF_BYTE_STREAM_CACHE_RANGE structures that
    ///     identify ranges of bytes in the cache.
    /// </summary>
    /// <param name="pcRanges">
    ///     Receives the number of ranges in the output array ppRanges.
    /// </param>
    /// <param name="ppRanges">
    ///     Recieves an array of MF_BYTE_STREAM_CACHE_RANGE structures with
    ///     *pcRanges elements.  Each MF_BYTE_STREAM_CACHE_RANGE structure
    ///     specifies a range of bytes stored in the byte stream's cache.
    ///     The caller must free *ppRanges with CoTaskMemFree.
    /// </param>
    HRESULT GetByteRanges(
        [out] DWORD* pcRanges,
        [out, size_is(,*pcRanges)] MF_BYTE_STREAM_CACHE_RANGE** ppRanges
        );
    
    /// <summary>
    ///     Limits the cache size to the specified number of bytes.
    /// </summary>
    /// <param name="qwBytes">
    ///     The maximum number of bytes to store in the cache, or ULONGLONG_MAX (QWORD_MAX)
    ///     for no limit.  The default value is no limit.
    /// </param>
    HRESULT SetCacheLimit(
        [in] QWORD qwBytes
        );

    /// <summary>
    ///     Queries whether the background transfer is active.  The background
    ///     transfer might be inactive if the cache has been filled (due to
    ///     SetCacheLimit) or if background transfer has benn stopped (due to
    ///     IMFByteStreamCacheControl::StopBackgroundTransfer).
    /// </summary>
    /// <param name="pfActive">
    ///     Receives TRUE if the background transfer is currently active, FALSE
    ///     if the background transfer is inactive
    /// </param>
    HRESULT IsBackgroundTransferActive(
        [out] BOOL* pfActive
        );
};

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

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

[
    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_reads_bytes_(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_reads_bytes_(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_writes_to_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_writes_to_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("_Outptr_")] 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("_Outptr_")] 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( "    _Outptr_ IMFNetCredentialCache ** ppCache);")


cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

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

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")


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

[
    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("_Outptr_result_bytebuffer_(*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("_Outptr_result_bytebuffer_(*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_reads_bytes_(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 );" )

//+-----------------------------------------------------------------------------
//
//  Interface:  IMFNetResourceFilter
//
//  Synopsis:   Callbacks for filtering and sending requests.
//
//------------------------------------------------------------------------------
[
    object,
    uuid(091878a3-bf11-4a5c-bc9f-33995b06ef2d),
    helpstring("IMFNetResourceFilter Interface"),
    pointer_default(unique),
    local
]
interface IMFNetResourceFilter : IUnknown
{
    HRESULT OnRedirect( 
        [in, annotation("_In_")] LPCWSTR pszUrl,
        [out, annotation("_Out_")] VARIANT_BOOL *pvbCancel
        );

    HRESULT OnSendingRequest( 
        [in, annotation("_In_")] LPCWSTR pszUrl
        );
};

cpp_quote("EXTERN_GUID( MFNETSOURCE_RESOURCE_FILTER, 0x815d0ff6, 0x265a, 0x4477, 0x9e, 0x46, 0x7b, 0x80, 0xad, 0x80, 0xb5, 0xfb);" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

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

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

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

[
    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_writes_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( "    _Outptr_ 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("_Outptr_")] 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;

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

/// <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 );" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

/// <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: Enable private download mode; cache will get cleared.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_ENABLE_PRIVATEMODE, 0x824779d8, 0xf18b, 0x4405, 0x8c, 0xf1, 0x46, 0x4f, 0xb5, 0xaa, 0x8f, 0x71 );" )

/// <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) ")

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN8) ")
/// <summary>
///  String that identifies the UPnP ConnectionManager Service instance.  The string is sent to DLNA server using the PeerManager.dlna.org HTTP/RTSP header.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_PEERMANAGER, 0x48b29adb, 0xfebf, 0x45ee, 0xa9, 0xbf, 0xef, 0xb8, 0x1c, 0x49, 0x2e, 0xfc );" )

/// <summary>
///  String that provides a friendly name for identification of the client.  The string is sent to DLNA servers using the FriendlyName.dlna.org HTTP/RTSP header.
/// </summary>
cpp_quote( "EXTERN_GUID( MFNETSOURCE_FRIENDLYNAME, 0x5b2a7757, 0xbc6b, 0x447e, 0xaa, 0x06, 0x0d, 0xda, 0x1c, 0x64, 0x6e, 0x2f );" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN8) ")

/// <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
//
///////////////////////////////////////////////////////////////////////////////

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

[
    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("_Outptr_opt_")] IUnknown **ppIUnknownCancelCookie,
                [in]  IMFAsyncCallback *pCallback,
                [in]  IUnknown *punkState
                );

    HRESULT EndCreateObject(
                [in]  IMFAsyncResult *pResult,
                [out, annotation("_Out_")] MF_OBJECT_TYPE *pObjectType,
                [out, annotation("_Outptr_")] 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("_Outptr_opt_")] IUnknown **ppIUnknownCancelCookie,
                [in]  IMFAsyncCallback *pCallback,
                [in]  IUnknown *punkState
                );

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

    HRESULT CancelObjectCreation(
                [in] IUnknown *pIUnknownCancelCookie
            );

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

/// <summary>
/// GUID passed to IMFGetService::GetService to retrieve a bytestream
/// service interface such as IMFByteStreamCacheControl2, IMFByteStreamBuffering, or IPropertyStore
/// from a Media Source.
/// </summary>
cpp_quote( "EXTERN_GUID( MF_BYTESTREAM_SERVICE, 0xab025e2b, 0x16d9, 0x4180, 0xa1, 0x27, 0xba, 0x6c, 0x70, 0x15, 0x61, 0x61 );" )

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

///////////////////////////////////////////////////////////////////////////////
//
// 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;

//
// ITA attributes
//

// MF_MEDIA_PROTECTION_MANAGER_PROPERTIES
// Data type: IUnknown
// If an ITA supports IMFAttributes and is being used in tandem with a session
// that has a media protection manager, the properties associated with the
// media protection manager (IPropertySet) will be passed via this attribute
// to the ITA.

cpp_quote("EXTERN_GUID( MF_MEDIA_PROTECTION_MANAGER_PROPERTIES, 0x38BD81A9, 0xACEA, 0x4C73, 0x89, 0xB2, 0x55, 0x32, 0xC0, 0xAE, 0xCA, 0x79 );")

[
    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("_Outptr_")] 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("_Outptr_")] 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("_Outptr_")] 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("_Outptr_")] 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_reads_opt_(nPolicy)")] IMFOutputPolicy ** ppPolicy,
                [in] DWORD nPolicy,
                [out, unique, size_is( ,*pcbTicket), annotation("_Outptr_opt_result_bytebuffer_(*pcbTicket)")] BYTE ** ppbTicket,
                [out, annotation("_Out_opt_")] DWORD * pcbTicket);
};

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

interface IMFOutputSchema;

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

[
    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("_Outptr_")] 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);" )
// The GUID 57cd5976-ce47-11d9-92db-000bdb28ff98 is reserved
cpp_quote( "EXTERN_GUID( MFCONNECTOR_MIRACAST, 0x57cd5977, 0xce47, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98);" )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_TRANSPORT_AGNOSTIC_DIGITAL_MODE_A, 0x57cd5978, 0xce47, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98); " )
cpp_quote( "EXTERN_GUID( MFCONNECTOR_TRANSPORT_AGNOSTIC_DIGITAL_MODE_B, 0x57cd5979, 0xce47, 0x11d9, 0x92, 0xdb, 0x00, 0x0b, 0xdb, 0x28, 0xff, 0x98); " )
cpp_quote( "" )


cpp_quote("#if (NTDDI_VERSION >= NTDDI_WIN10_VB) ")

// MF_POLICY_ID
// Data type: UINT32 (treat as BOOL)
// An identifier that can be set on an IMFOutputPolicy.
// The value can be recieved from the MEPolicySet media event. It is stored as a VT_UI4
// type payload in the MEPolicySet event.
// {B160C24D-C059-48F1-A901-9EE298A9A8C3}
cpp_quote( "EXTERN_C const DECLSPEC_SELECTANY GUID MF_POLICY_ID = { 0xb160c24d, 0xc059, 0x48f1, { 0xa9, 0x1, 0x9e, 0xe2, 0x98, 0xa9, 0xa8, 0xc3 } };" )

cpp_quote("#endif // (NTDDI_VERSION >= NTDDI_WIN10_VB) ")



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

[
    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_CONSTRICTVIDEO_NOOPM, 0xa580e8cd, 0xc247, 0x4957, 0xb9, 0x83, 0x3c, 0x2e, 0xeb, 0xd1, 0xff, 0x59);")
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( "EXTERN_GUID( MFPROTECTION_PROTECTED_SURFACE, 0x4f5d9566, 0xe742, 0x4a25, 0x8d, 0x1f, 0xd2, 0x87, 0xb5, 0xfa, 0x0a, 0xde);" )
cpp_quote( "EXTERN_GUID( MFPROTECTION_DISABLE_SCREEN_SCRAPE, 0xa21179a4, 0xb7cd, 0x40d8, 0x96, 0x14, 0x8e, 0xf2, 0x37, 0x1b, 0xa7, 0x8d);" )

//  36a59cbc-7401-4a8c-bc20-46a7c9e597f0
//  Protection of uncompressed video frames
//  0 - allow application access to frames
//  1 - allow application access to frames if application certificate provided
//  0xFFFFFFFF (default) no application access to uncompressed frames
cpp_quote( "EXTERN_GUID( MFPROTECTION_VIDEO_FRAMES, 0x36a59cbc, 0x7401, 0x4a8c, 0xbc, 0x20, 0x46, 0xa7, 0xc9, 0xe5, 0x97, 0xf0);" )

// GUID to specify hardware protected surface support
// {4EE7F0C1-9ED7-424F-B6BE-996B33528856}
cpp_quote("EXTERN_GUID(MFPROTECTION_HARDWARE, 0x4ee7f0c1, 0x9ed7, 0x424f, 0xb6, 0xbe, 0x99, 0x6b, 0x33, 0x52, 0x88, 0x56);")

// GUID to specify hdcp type enforcement
// {A4A585E8-ED60-442D-814D-DB4D4220A06D}
cpp_quote("EXTERN_GUID( MFPROTECTION_HDCP_WITH_TYPE_ENFORCEMENT, 0xa4a585e8, 0xed60, 0x442d, 0x81, 0x4d, 0xdb, 0x4d, 0x42, 0x20, 0xa0, 0x6d);")


//  Protection levels for MFPROTECTION_CGMSA
typedef enum _MF_OPM_CGMSA_PROTECTION_LEVEL
{
    MF_OPM_CGMSA_OFF                                           = 0x00,
    MF_OPM_CGMSA_COPY_FREELY                                   = 0x01,
    MF_OPM_CGMSA_COPY_NO_MORE                                  = 0x02,
    MF_OPM_CGMSA_COPY_ONE_GENERATION                           = 0x03,
    MF_OPM_CGMSA_COPY_NEVER                                    = 0x04,
    MF_OPM_CGMSA_REDISTRIBUTION_CONTROL_REQUIRED               = 0x08,
} MF_OPM_CGMSA_PROTECTION_LEVEL;

//  Protection levels for MFPROTECTION_ACP
typedef enum _MF_OPM_ACP_PROTECTION_LEVEL
{
    MF_OPM_ACP_OFF             = 0,
    MF_OPM_ACP_LEVEL_ONE       = 1,
    MF_OPM_ACP_LEVEL_TWO       = 2,
    MF_OPM_ACP_LEVEL_THREE     = 3,
    MF_OPM_ACP_FORCE_ULONG     = 0x7fffffff
} MF_OPM_ACP_PROTECTION_LEVEL;

//  Attribute that affects handling of protections - best effort
//  c8e06331-75f0-4ec1-8e77-17578f773b46
//  UINT32 interpreted as BOOL : TRUE - fail over if available, FALSE - no need to fail over
cpp_quote( "EXTERN_GUID( MFPROTECTIONATTRIBUTE_BEST_EFFORT, 0xc8e06331, 0x75f0, 0x4ec1, 0x8e, 0x77, 0x17, 0x57, 0x8f, 0x77, 0x3b, 0x46);" )
cpp_quote( "" )

//  Attribute that affects handling of protections - fail over to this if best effort fails
//  8536abc5-38f1-4151-9cce-f55d941229ac
//  UINT32 interpreted as BOOL
cpp_quote( "EXTERN_GUID( MFPROTECTIONATTRIBUTE_FAIL_OVER, 0x8536abc5, 0x38f1, 0x4151, 0x9c, 0xce, 0xf5, 0x5d, 0x94, 0x12, 0x29, 0xac);" )
cpp_quote( "" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN8) ")
#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

// GUID to sepecify AES DXVA encryption for DXVA decoders.
// {C873DE64-D8A5-49E6-88BB-FB963FD3D4CE}
cpp_quote( "EXTERN_GUID(MFPROTECTION_GRAPHICS_TRANSFER_AES_ENCRYPTION, 0xc873de64, 0xd8a5, 0x49e6, 0x88, 0xbb, 0xfb, 0x96, 0x3f, 0xd3, 0xd4, 0xce);" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

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

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

//
// 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 MFAudioConstriction enumeration
//              The MFAudioConstriction enumeration matches the EAudioConstriction enumeration
//              defined audioenginebaseapo.h
//
//  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( "" )

cpp_quote( "" )
cpp_quote( "typedef enum _MFAudioConstriction                                  " )
cpp_quote( "{                                                                  " )
cpp_quote( "    MFaudioConstrictionOff   = 0,                                  " )
cpp_quote( "    MFaudioConstriction48_16 = ( MFaudioConstrictionOff + 1 ) ,    " )
cpp_quote( "    MFaudioConstriction44_16 = ( MFaudioConstriction48_16 + 1 ) ,  " )
cpp_quote( "    MFaudioConstriction14_14 = ( MFaudioConstriction44_16 + 1 ) ,  " )
cpp_quote( "    MFaudioConstrictionMute  = ( MFaudioConstriction14_14 + 1 )    " )
cpp_quote( "} MFAudioConstriction;                                             " ) 
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) ")

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

[
    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("_Outptr_result_bytebuffer_(*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_reads_bytes_(cbSessionKey)")] BYTE *pbEncryptedSessionKey, [in] DWORD cbSessionKey );
};

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

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

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_AES128CTR          = 4,
} 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("_Outptr_result_bytebuffer_(*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
        );
}

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

[
    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("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ")
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

[
    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 /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

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

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

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

///////////////////////////////////////////////////////////////////////////////
//
// 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("_Outptr_")] void ** ppv);

    HRESULT GetRemoteHost(
        [in] REFIID riid,
        [out, iid_is(riid), annotation("_Outptr_")] 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);
};


// ef65a54d-0788-45b8-8b14-bc0f6a6b5137
cpp_quote( "EXTERN_GUID( CLSID_CreateMediaExtensionObject, 0xef65a54d, 0x0788, 0x45b8, 0x8b, 0x14, 0xbc, 0x0f, 0x6a, 0x6b, 0x51, 0x37);" )

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
[
    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( "    _Outptr_ 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( "    _Outptr_ IMFRemoteDesktopPlugin** ppPlugin );" )

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

//
// CreateNamedPropertyStore
//
cpp_quote( "EXTERN_C HRESULT STDAPICALLTYPE CreateNamedPropertyStore(" )
cpp_quote( "        _Outptr_ 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("_Outptr_") ] 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("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

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

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

////////////////////////////////////////////////////////////////////////////
//
// 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(_Outptr_ 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("_Outptr_result_maybenull_")] 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("_Outptr_result_maybenull_")] 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("_Outptr_result_maybenull_")] IMFAttributes** ppAttrs );
};

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion


#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

/////////////////////////////////////////////////////////////////////////////
// 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_FLAC
// represents MF built-in FLAC container
// {31344aa3-05a9-42b5-901b-8e9d4257f75e}
cpp_quote( "EXTERN_GUID( MFTranscodeContainerType_FLAC, 0x31344aa3, 0x05a9, 0x42b5, 0x90, 0x1b, 0x8e, 0x9d, 0x42, 0x57, 0xf7, 0x5e );" )

// 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 );" )

// MFTranscodeContainerType_AC3
// represents MF built-in AC3 container
// {132fd27d-0f02-43de-a301-38fbbbb3834e}
cpp_quote( "EXTERN_GUID( MFTranscodeContainerType_AC3, 0x6d8d91c3, 0x8c91, 0x4ed1, 0x87, 0x42, 0x8c, 0x34, 0x7d, 0x5b, 0x44, 0xd0 );" )

// MFTranscodeContainerType_ADTS
// represents MF built-in ADTS container
// {132fd27d-0f02-43de-a301-38fbbbb3834e}
cpp_quote( "EXTERN_GUID( MFTranscodeContainerType_ADTS, 0x132fd27d, 0x0f02, 0x43de, 0xa3, 0x01, 0x38, 0xfb, 0xbb, 0xb3, 0x83, 0x4e );" )

// MFTranscodeContainerType_MPEG2
// represents MF built-in mpeg2 container
// {bfc2dbf9-7bb4-4f8f-afde-e112c44ba882 }
cpp_quote( "EXTERN_GUID( MFTranscodeContainerType_MPEG2, 0xbfc2dbf9, 0x7bb4, 0x4f8f, 0xaf, 0xde, 0xe1, 0x12, 0xc4, 0x4b, 0xa8, 0x82 );" )

// MFTranscodeContainerType_WAVE
// represents MF built-in wave container
// {64c3453c-0f26-4741-be63-87bdf8bb935b}
cpp_quote( "EXTERN_GUID( MFTranscodeContainerType_WAVE, 0x64c3453c, 0x0f26, 0x4741, 0xbe, 0x63, 0x87, 0xbd, 0xf8, 0xbb, 0x93, 0x5b );" )

// MFTranscodeContainerType_AVI
// represents MF built-in avi container
// {7edfe8af-402f-4d76-a33c-619fd157d0f1 }
cpp_quote( "EXTERN_GUID( MFTranscodeContainerType_AVI, 0x7edfe8af, 0x402f, 0x4d76, 0xa3, 0x3c, 0x61, 0x9f, 0xd1, 0x57, 0xd0, 0xf1 );" )

cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN8) ")
// MFTranscodeContainerType_FMPEG4
// represents MF built-in Fragmented MPEG4 container
// {9BA876F1-419F-4b77-A1E0-35959D9D4004}
cpp_quote( "EXTERN_GUID( MFTranscodeContainerType_FMPEG4, 0x9ba876f1, 0x419f, 0x4b77, 0xa1, 0xe0, 0x35, 0x95, 0x9d, 0x9d, 0x40, 0x4 );" )
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WIN8) ")

// MFTranscodeContainerType_AMR
// represents MF built in AMR container
// {025D5AD3-621A-475B-964D-66B1C824F079}
cpp_quote( "EXTERN_GUID( MFTranscodeContainerType_AMR, 0x25d5ad3, 0x621a, 0x475b, 0x96, 0x4d, 0x66, 0xb1, 0xc8, 0x24, 0xf0, 0x79 );" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion


#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

// 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 );" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

typedef enum _MF_VIDEO_PROCESSOR_ALGORITHM_TYPE
{
    // default mode favors a balance of quality and speed
    MF_VIDEO_PROCESSOR_ALGORITHM_DEFAULT = 0,
 
    // the VP will always internally process in AYUV and use high quality filters
    MF_VIDEO_PROCESSOR_ALGORITHM_MRF_CRF_444   = 1
 
} MF_VIDEO_PROCESSOR_ALGORITHM_TYPE;

// MF_VIDEO_PROCESSOR_ALGORITHM
// Data type: UINT32(MF_VIDEO_PROCESSOR_ALGORITHM_TYPES, MF_VIDEO_PROCESSOR_ALGORITHM_DEFAULT(0) or MF_VIDEO_PROCESSOR_ALGORITHM_MRF_CRF_444(1))
// Must in sync with Windows.Media.Transcoding.MediaVideoProcessingAlgorithm
// {4A0A1E1F-272C-4fb6-9EB1-DB330CBC97CA}
cpp_quote( "EXTERN_GUID( MF_VIDEO_PROCESSOR_ALGORITHM, 0x4a0a1e1f, 0x272c, 0x4fb6, 0x9e, 0xb1, 0xdb, 0x33, 0xc, 0xbc, 0x97, 0xca);" )

// MF_XVP_DISABLE_FRC  
// Data type: UINT32 (treat as BOOL)  
// If this attribute is TRUE, the XVP will not perform frame rate conversion (FRC)
// This attribute should be set on the transform's attrbiute store prior to OnBeginStreaming().
// {2C0AFA19-7A97-4D5A-9EE8-16D4FC518D8C}
cpp_quote( "EXTERN_GUID( MF_XVP_DISABLE_FRC, 0x2c0afa19, 0x7a97, 0x4d5a, 0x9e, 0xe8, 0x16, 0xd4, 0xfc, 0x51, 0x8d, 0x8c );" )

// This should be enabled after _WIN32_WINNT is updated.   
//#if (_WIN32_WINNT >= _WIN32_WINNT_WINTHRESHOLD)  
cpp_quote("#if (WINVER >= _WIN32_WINNT_WINBLUE) ")

// MF_XVP_CALLER_ALLOCATES_OUTPUT
// Data type: UINT32 (treat as BOOL)  
// If this attribute is TRUE, XVP will expect caller allocated textures on output even in DX mode
//  when FALSE XVP will allocate output in DX mode (and will fail if provided output)
// {04A2CABC-0CAB-40b1-A1B9-75BC3658F000}
cpp_quote( "EXTERN_GUID( MF_XVP_CALLER_ALLOCATES_OUTPUT, 0x4a2cabc, 0xcab, 0x40b1, 0xa1, 0xb9, 0x75, 0xbc, 0x36, 0x58, 0xf0, 0x0 );" )

//#endif // (WINVER >= _WIN32_WINNT_WINTHRESHOLD)
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WINBLUE) ")

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

// This should be enabled after _WIN32_WINNT is updated.   
//#if (_WIN32_WINNT >= _WIN32_WINNT_WINTHRESHOLD)  
cpp_quote("#if (WINVER >= _WIN32_WINNT_WINBLUE) ")

cpp_quote("#if (WINVER < _WIN32_WINNT_WINTHRESHOLD) ")
// CLSID_VideoProcessorMFT
// Standard MF video processor component (a.k.a: XVP)
// {88753B26-5B24-49bd-B2E7-0C445C78C982}  
cpp_quote("EXTERN_GUID(CLSID_VideoProcessorMFT, 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82);")
cpp_quote("#endif // (WINVER < _WIN32_WINNT_WINTHRESHOLD) ")


//#endif // (WINVER >= _WIN32_WINNT_WINTHRESHOLD)
cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WINBLUE) ")

/////////////////////////////////////////////////////////////////////////////
/// <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( "    _Outptr_ 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
///     have 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( "    _Outptr_ IMFTopology** ppTranscodeTopo" )
cpp_quote( "    );" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

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

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

/////////////////////////////////////////////////////////////////////////////
/// <summary>
///     Creates a partial transcode topology. The partial topology has a
///     source object, encoder object and sink object. The encoder object and sink object
///     have been configured properly.
/// </summary>
/// <param name="pSrc">
///     A pointer to an IMFMediaSource object.
/// </param>
/// <param name="pOutputStream">
///     Specifies an output IMFByteStream object.
/// </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 MFCreateTranscodeTopologyFromByteStream(" )
cpp_quote( "    _In_ IMFMediaSource* pSrc," )
cpp_quote( "    _In_ IMFByteStream* pOutputStream," )
cpp_quote( "    _In_ IMFTranscodeProfile* pProfile," )
cpp_quote( "    _Out_ IMFTopology** ppTranscodeTopo" )
cpp_quote( "    );" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

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

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")


/////////////////////////////////////////////////////////////////////////////
/// <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( " _Outptr_ 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(" _Outptr_ 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);
}

///////////////////////////////////////////////////////////////////////////////
// IMFCapturePhotoConfirmationInterface
//
///////////////////////////////////////////////////////////////////////////////
[
    object,
    uuid(19f68549-ca8a-4706-a4ef-481dbc95e12c),
    local
]
interface IMFCapturePhotoConfirmation : IUnknown
{
    HRESULT SetPhotoConfirmationCallback(
    [in, annotation("_In_")] IMFAsyncCallback* pNotificationCallback);

    /// <summary>
    /// Sets the PhotoConfirmation pixel format
    /// </summary>   
    HRESULT SetPixelFormat(
        [in, annotation("_In_")] GUID subtype);

    /// <summary>
    /// Returns the PhotoConfirmation pixel format
    /// </summary>   
    HRESULT GetPixelFormat(
        [out, annotation("_Out_")] GUID* subtype);
};

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)")

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

[
    object,
    uuid(84d2054a-3aa1-4728-a3b0-440a418cf49c)
]
/// <summary>
///     IMFPMPHostApp supply the methods for creating object in the PMP process
/// </summary>
interface IMFPMPHostApp : IUnknown
{
   HRESULT LockProcess();
   HRESULT UnlockProcess();
   HRESULT ActivateClassById(
      [in] LPCWSTR id,
      [in, unique] IStream * pStream,
      [in] REFIID riid,
      [out, iid_is(riid)] void ** ppv);
}

[
    object,
    uuid(c004f646-be2c-48f3-93a2-a0983eba1108),
    local,
]
/// <summary>
///     IMFPMPClient is the interface implemented by components (usualy sources)
///     which need access to IMFPMPHost
/// </summary>
interface IMFPMPClientApp : IUnknown
{
    /// <summary>
    ///     Initialize the component with IMFPMPHost.
    /// </summary>
    HRESULT SetPMPHost(
        [in] IMFPMPHostApp * pPMPHost
        );
}

cpp_quote("#endif ")
cpp_quote("#if (WINVER >= _WIN32_WINNT_WINBLUE) ")

[
    object,
    uuid(380b9af9-a85b-4e78-a2af-ea5ce645c6b4),
    pointer_default(unique)
]
/// <summary>
///     MFMediaStreamSourceSampleRequest is implemented by the
///     Windows.Media.Core.MediaStreamSourceSampleRequest runtime class.
/// </summary>
interface IMFMediaStreamSourceSampleRequest : IUnknown
{
    HRESULT SetSample([in] IMFSample* value);
}

cpp_quote("#endif ")

[
    object,
    uuid(245BF8E9-0755-40f7-88A5-AE0F18D55E17),
    helpstring("IMFTrackedSample Interface"),
    local
]
/// <summary>
//  The IMFTrackedSample interface is used to notify allocators when their 
//  samples are no longer in use by other clients.
/// </summary>
interface IMFTrackedSample : IUnknown
{
    //-------------------------------------------------------------------------
    // Description:
    //
    //  This method sets the allocator on a sample. 
    //
    // Parameters:
    //
    //  pSampleAllocator - The sample allocator interface to be notified when all 
    //      clients have finished with a sample.
    //  punkState - Caller supplied state that will be furnished during the 
    //      Invoke call. This value will be addref'ed and it is therefore 
    //      recommended that the object passed be a pointer to the 
    //      object itself. This will guarantee that the 
    //      object does not disappear during the call.
    //
    // Return values:
    //
    //  S_OK - Successful completion.
    //  E_POINTER - An invalid pointer was passed.
    //
    // Remarks:
    //
    //  When the reference count
    //  on the sample reaches 1, indicating that only the owner (allocator)
    //  holds a reference, the owner will receive a callback. The allocator 
    //  interface will be subsequently NULL'ed out. This interface ensures that 
    //  the allocator does not get freed while it has samples outstanding.
    //
    HRESULT SetAllocator(
        [in, annotation("_In_")] IMFAsyncCallback* pSampleAllocator,
        [in, unique] IUnknown* pUnkState
        );
}

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


cpp_quote( "STDAPI MFCreateTrackedSample(" )
cpp_quote( "    _Outptr_ IMFTrackedSample** ppMFSample);" )


cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

#pragma region Desktop or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_GAMES)")

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

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

cpp_quote( "STDAPI MFCreateStreamOnMFByteStream(" ) 
cpp_quote( "    _In_ IMFByteStream* pByteStream," ) 
cpp_quote( "    _Outptr_ IStream** ppStream);" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

#pragma region Application Family
cpp_quote( "#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)" )

cpp_quote( "STDAPI MFCreateMFByteStreamOnStreamEx(" )
cpp_quote( "    _In_ IUnknown* punkStream," )
cpp_quote( "    _Outptr_ IMFByteStream** ppByteStream );" )


cpp_quote( "STDAPI MFCreateStreamOnMFByteStreamEx(" ) 
cpp_quote( "    _In_ IMFByteStream* pByteStream," ) 
cpp_quote( "    _In_ REFIID riid," )
cpp_quote( "    _Outptr_ void **ppv );" )

cpp_quote( "STDAPI MFCreateMediaTypeFromProperties(" )
cpp_quote( "    _In_ IUnknown* punkStream," )
cpp_quote( "    _Outptr_ IMFMediaType** ppMediaType );" )

cpp_quote( "STDAPI MFCreatePropertiesFromMediaType(" ) 
cpp_quote( "    _In_ IMFMediaType* pMediaType," ) 
cpp_quote( "    _In_ REFIID riid," )
cpp_quote( "    _Outptr_ void **ppv );" )

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

// {AB544072-C269-4EBC-A552-1C3B32BED5CA}
cpp_quote( "DEFINE_GUID(MF_WRAPPED_BUFFER_SERVICE, 0xab544072, 0xc269, 0x4ebc, 0xa5, 0x52, 0x1c, 0x3b, 0x32, 0xbe, 0xd5, 0xca);" )

// {31F52BF2-D03E-4048-80D0-9C1046D87C61}
cpp_quote( "EXTERN_GUID(MF_WRAPPED_SAMPLE_SERVICE, 0x31f52bf2, 0xd03e, 0x4048, 0x80, 0xd0, 0x9c, 0x10, 0x46, 0xd8, 0x7c, 0x61);" )

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

cpp_quote( "#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */" )
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

//  
// MF_WRAPPED_OBJECT - /* 2b182c4c-d6ac-49f4-8915-f71887db70cd */
// This service GUID should be used to get direct access to a wrapped object. 
// For example: When an IMFByteStream is wrapped into a IRandomAccessStream,
// the wrapped IMFByteStream can be retrieved from the IRandomAccessStream using this service.
//  
cpp_quote( "EXTERN_GUID( MF_WRAPPED_OBJECT, 0x2b182c4c, 0xd6ac, 0x49f4, 0x89, 0x15, 0xf7, 0x18, 0x87, 0xdb, 0x70, 0xcd);" )


/////////////////////////////////////////////////////////////////////////////
// Scheme and Bytestream handler CLSIDs

// {44CB442B-9DA9-49df-B3FD-023777B16E50}
cpp_quote( "EXTERN_GUID(CLSID_HttpSchemePlugin, 0x44cb442b, 0x9da9, 0x49df, 0xb3, 0xfd, 0x2, 0x37, 0x77, 0xb1, 0x6e, 0x50);" )

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

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote( "#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)" )

// {E9F4EBAB-D97B-463e-A2B1-C54EE3F9414D}
cpp_quote( "EXTERN_GUID(CLSID_NetSchemePlugin, 0xe9f4ebab, 0xd97b, 0x463e, 0xa2, 0xb1, 0xc5, 0x4e, 0xe3, 0xf9, 0x41, 0x4d);" )

cpp_quote( "#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */" )
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

//////////////////////////////////////////////////////////////////////////////
//
// 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( "    _Outptr_result_buffer_(*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( "    _Outptr_ 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( "    _Outptr_ 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);" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

// 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);" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

#pragma region Desktop Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)")

// MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_SYMBOLIC_LINK
// Data type: STRING
// Symbolic link for a audio capture source
cpp_quote( "EXTERN_GUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_SYMBOLIC_LINK, 0x98d24b5e, 0x5930, 0x4614, 0xb5, 0xa1, 0xf6, 0x0, 0xf9, 0x35, 0x5a, 0x78);" )

// 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);" )

// MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_PROVIDER_DEVICE_ID
// Data type: STRING
// Contains a device Id for a provider
cpp_quote( "EXTERN_GUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_PROVIDER_DEVICE_ID, 0x36689d42, 0xa06c, 0x40ae, 0x84, 0xcf, 0xf5, 0xa0, 0x34, 0x6, 0x7c, 0xc4);" )

// MF_DEVSOURCE_ATTRIBUTE_SOURCE_XADDRESS 
// {BCA0BE52-C327-44C7-9B7D-7FA8D9B5BCDA} 
// Data type: STRING 
// Contains a XADDRESS of KSCATEGORY_NETWORK_CAMERA that 
// can be obtained from the PKEY_PNPX_XAddrs from a KSCATEGORY_NETWORK_CAMERA 
// or Web Services on Devices (WSD) xaddrs parameter, currently only supports ONVIF cameras.
cpp_quote("EXTERN_GUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_XADDRESS, 0xbca0be52, 0xc327, 0x44c7, 0x9b, 0x7d, 0x7f, 0xa8, 0xd9, 0xb5, 0xbc, 0xda);")

// MF_DEVSOURCE_ATTRIBUTE_SOURCE_RTSP_URL 
// {9D7B40D2-3617-4043-93E3-8D6DA9BB3492} 
// Data type: STRING 
// Currently only RTSP urls are supported as an initialization parameter. 
cpp_quote("EXTERN_GUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_STREAM_URL, 0x9d7b40d2, 0x3617, 0x4043, 0x93, 0xe3, 0x8d, 0x6d, 0xa9, 0xbb, 0x34, 0x92);")

// MF_DEVSOURCE_ATTRIBUTE_SOURCE_USERNAME 
// {05D01ADD-949F-46EB-BC8E-8B0D2B32D79D} 
// Data type: STRING 
// Attribute contains a username to use for authentication. 
cpp_quote("EXTERN_GUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_USERNAME,0x5d01add, 0x949f, 0x46eb, 0xbc, 0x8e, 0x8b, 0xd, 0x2b, 0x32, 0xd7, 0x9d);")

// MF_DEVSOURCE_ATTRIBUTE_SOURCE_PASSWORD 
// {A0FD7E16-42D9-49DF-84C0-E82C5EAB8874} 
// Data type: STRING 
// Attribute contains a password to use for authentication. 
cpp_quote("EXTERN_GUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_PASSWORD, 0xa0fd7e16, 0x42d9, 0x49df, 0x84, 0xc0, 0xe8, 0x2c, 0x5e, 0xab, 0x88, 0x74);")


// {7A213AA7-866F-414A-8C1A-275C7283A395} 
// CLSID_FrameServerNetworkCameraSource 
// CLSID for KSCATEGORY_NETWORK_CAMERA Source that controls the MediaSource, 
// provides functionality to stream and control KSCATEGORY_NETWORK_CAMERA. 
// CLSID_FrameServerNetworkCameraSource is only supported using the Windows service FrameServer 
// and requires FrameServer for control and media flow, all other uses are not supported.
cpp_quote("EXTERN_GUID(CLSID_FrameServerNetworkCameraSource, 0x7a213aa7, 0x866f, 0x414a, 0x8c, 0x1a, 0x27, 0x5c, 0x72, 0x83, 0xa3, 0x95);")

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

//
// 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);")

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

//
// Device Stream Type GUIDs
//

// MF_DEVICESTREAM_IMAGE_STREAM
// Data type: UINT32
// this attribute will be set on a device stream when it supports still image capture
cpp_quote( "EXTERN_GUID( MF_DEVICESTREAM_IMAGE_STREAM, 0xa7ffb865, 0xe7b2, 0x43b0, 0x9f, 0x6f, 0x9a, 0xf2, 0xa0, 0xe5, 0xf, 0xc0);" )

// MF_DEVICESTREAM_INDEPENDENT_IMAGE_STREAM
// Data type: UINT32
// this attribute will be set on a device stream when it supports still image capture that is not dependent on a video stream
cpp_quote( "EXTERN_GUID( MF_DEVICESTREAM_INDEPENDENT_IMAGE_STREAM, 0x3eeec7e, 0xd605, 0x4576, 0x8b, 0x29, 0x65, 0x80, 0xb4, 0x90, 0xd7, 0xd3);" )

// MF_DEVICESTREAM_STREAM_ID
// Data type: UINT32
// this attribute is set to the stream's KS stream ID
cpp_quote( "EXTERN_GUID( MF_DEVICESTREAM_STREAM_ID, 0x11bd5120, 0xd124, 0x446b, 0x88, 0xe6, 0x17, 0x6, 0x2, 0x57, 0xff, 0xf9);" )

// {2939E7B8-A62E-4579-B674-D4073DFABBBA}
// MF_DEVICESTREAM_STREAM_CATEGORY
// Data type: GUID
// this attribute represents the GUID that identifies the stream category defined in ksmedia.h
cpp_quote( "EXTERN_GUID( MF_DEVICESTREAM_STREAM_CATEGORY, 0x2939e7b8, 0xa62e, 0x4579, 0xb6, 0x74, 0xd4, 0x7, 0x3d, 0xfa, 0xbb, 0xba);" )

// {1CB378E9-B279-41D4-AF97-34A243E68320}
// MF_DEVICESTREAM_FRAMESERVER_SHARED
// Data type: UINT32
// this attribute, when set on a stream, explicitly marks the stream as shared by the frame server.
cpp_quote( "EXTERN_GUID( MF_DEVICESTREAM_FRAMESERVER_SHARED, 0x1CB378E9, 0xB279, 0x41D4, 0xAF, 0x97, 0x34, 0xA2, 0x43, 0xE6, 0x83, 0x20);" )

//
// MF_DEVICESTREAM_TRANSFORM_STREAM_ID
// Data type: UINT32
// This attribute represents the stream's MFT stream id 
// {e63937b7-daaf-4d49-815f-d826f8ad31e7}
//
cpp_quote( "EXTERN_GUID( MF_DEVICESTREAM_TRANSFORM_STREAM_ID,  0xe63937b7, 0xdaaf, 0x4d49, 0x81, 0x5f, 0xd8, 0x26, 0xf8, 0xad, 0x31, 0xe7);" ) 

//
// MF_DEVICESTREAM_EXTENSION_PLUGIN_CLSID
// Data type: GUID
// This attribute represents device extension MFT's CLSID when it is indicated in the device registry key
// {048e6558-60c4-4173-bd5b-6a3ca2896aee}
//
cpp_quote( "EXTERN_GUID( MF_DEVICESTREAM_EXTENSION_PLUGIN_CLSID, 0x048e6558, 0x60c4, 0x4173, 0xbd, 0x5b, 0x6a, 0x3c, 0xa2, 0x89, 0x6a, 0xee);" ) 

//
// MF_DEVICEMFT_EXTENSION_PLUGIN_CLSID
// Data type: GUID
// This attribute represents device MFT's CLSID when it is indicated in the device registry key. This is loaded by device source
// {0844DBAE-34FA-48A0-A783-8E696FB1C9A8}
//

cpp_quote( "EXTERN_GUID( MF_DEVICEMFT_EXTENSION_PLUGIN_CLSID, 0x844dbae, 0x34fa, 0x48a0, 0xa7, 0x83, 0x8e, 0x69, 0x6f, 0xb1, 0xc9, 0xa8);" ) 

//
// MF_DEVICESTREAM_EXTENSION_PLUGIN_CONNECTION_POINT
// Data type: IUnknown
// This attribute represents filter KSControl pointer 
// {37f9375c-e664-4ea4-aae4-cb6d1daca1f4}
//
cpp_quote( "EXTERN_GUID( MF_DEVICESTREAM_EXTENSION_PLUGIN_CONNECTION_POINT,  0x37f9375c, 0xe664, 0x4ea4, 0xaa, 0xe4, 0xcb, 0x6d, 0x1d, 0xac, 0xa1, 0xf4);" ) 

// MF_DEVICESTREAM_TAKEPHOTO_TRIGGER
// Data Type: UINT32
// {1d180e34-538c-4fbb-a75a-859af7d261a6}
/// <summary>
///     Set this to non-zero will encapsulate dependent image pin take photo trigger in device source
/// </summary>
cpp_quote( "EXTERN_GUID( MF_DEVICESTREAM_TAKEPHOTO_TRIGGER, 0x1d180e34, 0x538c, 0x4fbb, 0xa7, 0x5a, 0x85, 0x9a, 0xf7, 0xd2, 0x61, 0xa6 );" )

// MF_DEVICESTREAM_MAX_FRAME_BUFFERS
// Data Type: UINT32
// {1684cebe-3175-4985-882c-0efd3e8ac11e}
/// <summary>
///     Specifies the maximum number of frames that the video capture source will buffer for this stream
/// </summary>
cpp_quote( "EXTERN_GUID( MF_DEVICESTREAM_MAX_FRAME_BUFFERS, 0x1684cebe, 0x3175, 0x4985, 0x88, 0x2c, 0x0e, 0xfd, 0x3e, 0x8a, 0xc1, 0x1e );" )


// MF_DEVICEMFT_CONNECTED_FILTER_KSCONTROL
// Data type: IUnknown
// {6A2C4FA6-D179-41CD-9523-822371EA40E5}
/// <summary>
///     Specifies the maximum number of frames that the video capture source will buffer for this stream
/// </summary>
cpp_quote("EXTERN_GUID( MF_DEVICEMFT_CONNECTED_FILTER_KSCONTROL, 0x6a2c4fa6, 0xd179, 0x41cd, 0x95, 0x23, 0x82, 0x23, 0x71, 0xea, 0x40, 0xe5);")

// MF_DEVICEMFT_CONNECTED_PIN_KSCONTROL
// Data type: IUnknown
// {E63310F7-B244-4EF8-9A7D-24C74E32EBD0}
/// <summary>
///     Specifies the maximum number of frames that the video capture source will buffer for this stream
/// </summary>
cpp_quote("EXTERN_GUID( MF_DEVICEMFT_CONNECTED_PIN_KSCONTROL, 0xe63310f7, 0xb244, 0x4ef8, 0x9a, 0x7d, 0x24, 0xc7, 0x4e, 0x32, 0xeb, 0xd0);")

//
// Device Thermal State related GUIDS
//

//MF_DEVICE_THERMAL_STATE_CHANGED
// Data Type: UINT32
// {70ccd0af-fc9f-4deb-a875-9fecd16c5bd4}
/// <summary>
///     Event that signals a thermal state change in the device and the value specifies the device thermal value in percentage.
/// </summary>
cpp_quote("EXTERN_GUID( MF_DEVICE_THERMAL_STATE_CHANGED, 0x70ccd0af, 0xfc9f, 0x4deb, 0xa8, 0x75, 0x9f, 0xec, 0xd1, 0x6c, 0x5b, 0xd4 );")


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


//
// 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);" )

// {4E251FA4-830F-4770-859A-4B8D99AA809B}   MFSampleExtension_Spatial_CameraViewTransform
// Type : Blob (Windows::Foundation::Numerics::Matrix)
// Stores Camera extrinsic transform.
cpp_quote("EXTERN_GUID(MFSampleExtension_Spatial_CameraViewTransform , 0x4e251fa4, 0x830f, 0x4770, 0x85, 0x9a, 0x4b, 0x8d, 0x99, 0xaa, 0x80, 0x9b);")

// {9D13C82F-2199-4E67-91CD-D1A4181F2534}   MFSampleExtension_Spatial_CameraCoordinateSystem
// Type : IUnknown (Windows::Perception::Spatial::SpatialCoordinateSystem)
// Stores coordinate system of captured frame
cpp_quote("EXTERN_GUID(MFSampleExtension_Spatial_CameraCoordinateSystem , 0x9d13c82f, 0x2199, 0x4e67, 0x91, 0xcd, 0xd1, 0xa4, 0x18, 0x1f, 0x25, 0x34);")

// {47F9FCB5-2A02-4F26-A477-792FDF95886A}   MFSampleExtension_Spatial_CameraProjectionTransform
// Type : Blob (Windows::Foundation::Numerics::Matrix4x4)
// Stores Camera projection transform
cpp_quote("EXTERN_GUID(MFSampleExtension_Spatial_CameraProjectionTransform , 0x47f9fcb5, 0x2a02, 0x4f26, 0xa4, 0x77, 0x79, 0x2f, 0xdf, 0x95, 0x88, 0x6a);")

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */")
#pragma endregion

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

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

interface IMFSignedLibrary;

[
    object,
    uuid(ef5dc845-f0d9-4ec9-b00c-cb5183d38434),
    local
]
interface IMFProtectedEnvironmentAccess : IUnknown
{
    HRESULT Call([annotation("_In_")] UINT32 inputLength, [annotation("_In_reads_bytes_(inputLength)")] const BYTE *input,
                 [annotation("_In_")] UINT32 outputLength, [annotation("_Out_writes_bytes_(outputLength)")] BYTE *output);
    HRESULT ReadGRL([annotation("_Out_")] UINT32 *outputLength, [annotation("_Outptr_result_bytebuffer_(*outputLength)")] BYTE **output);
}

[
    object,
    uuid(4a724bca-ff6a-4c07-8e0d-7a358421cf06),
    local
]
interface IMFSignedLibrary : IUnknown
{
    HRESULT GetProcedureAddress([annotation("_In_")] LPCSTR name, [annotation("_Outptr_")] PVOID *address);
}

[
    object,
    uuid(fff4af3a-1fc1-4ef9-a29b-d26c49e2f31a),
    local
]
interface IMFSystemId : IUnknown
{
    HRESULT GetData([annotation("_Out_")] UINT32 *size, [annotation("_Outptr_result_bytebuffer_(*size)")] BYTE **data);
    HRESULT Setup(UINT32 stage, 
                  UINT32 cbIn, [annotation("_In_reads_bytes_(cbIn)")] const BYTE *pbIn,
                  [annotation("_Out_")] UINT32 *pcbOut, [annotation("_Outptr_result_bytebuffer_(*pcbOut)")] BYTE **ppbOut);
                  
}

cpp_quote( "STDAPI MFCreateProtectedEnvironmentAccess( " )
cpp_quote( "    _Outptr_ IMFProtectedEnvironmentAccess**   ppAccess" )
cpp_quote( ");" )


cpp_quote( "STDAPI MFLoadSignedLibrary( " )
cpp_quote( "    _In_ LPCWSTR pszName," )
cpp_quote( "    _Outptr_ IMFSignedLibrary**   ppLib" )
cpp_quote( ");" )

cpp_quote( "STDAPI MFGetSystemId( " )
cpp_quote( "    _Outptr_ IMFSystemId** ppId" )
cpp_quote( ");" )


cpp_quote( "STDAPI MFGetLocalId( " )
cpp_quote( "    _In_reads_bytes_(size) const BYTE *verifier," )
cpp_quote( "    _In_ UINT32 size," )
cpp_quote( "    _Outptr_ LPWSTR *id" )
cpp_quote( ");" )

cpp_quote( "// {40871C59-AB40-471F-8DC3-1F259D862479}" )
cpp_quote( "DEFINE_GUID(CLSID_MPEG2ByteStreamPlugin, " )
cpp_quote( "0x40871c59, 0xab40, 0x471f, 0x8d, 0xc3, 0x1f, 0x25, 0x9d, 0x86, 0x24, 0x79);" )

/// <summary>
/// GUID passed to IMFGetService::GetService to retrieve an IMFMediaSource interface.
/// </summary>
cpp_quote( "// {f09992f7-9fba-4c4a-a37f-8c47b4e1dfe7}" )
cpp_quote( "EXTERN_GUID( MF_MEDIASOURCE_SERVICE, 0xf09992f7, 0x9fba, 0x4c4a, 0xa3, 0x7f, 0x8c, 0x47, 0xb4, 0xe1, 0xdf, 0xe7 );" )

/// <summary>
/// GUID passed to IMFGetService::GetService to retrieve an IMFMediaSource interface. 
/// Unlike with MF_MEDIASOURCE_SERVICE, the call to GetService() may block for a long time to display user-consent UI for instance.
/// </summary>
cpp_quote( "// {014A5031-2F05-4C6A-9F9C-7D0DC4EDA5F4}" )
cpp_quote( "EXTERN_GUID( MF_ACCESS_CONTROLLED_MEDIASOURCE_SERVICE, 0x14a5031, 0x2f05, 0x4c6a, 0x9f, 0x9c, 0x7d, 0xd, 0xc4, 0xed, 0xa5, 0xf4 );" )

typedef struct _MFCONTENTPROTECTIONDEVICE_INPUT_DATA
{
    /// <member name="HWProtectionFunctionID">
    /// Identifier of the function that needs to be executed. To be defined by protection system implementation.
    /// </member>
    DWORD HWProtectionFunctionID;

    /// <member name="PrivateDataByteCount">
    /// Contains the size of the private data reserved by the security processor implementation. Determined by calling IMFContentProtectionDevice::GetPrivateDataByteCount
    /// </member>
    DWORD PrivateDataByteCount;

    /// <member name="HWProtectionDataByteCount">
    /// Contains the size of the data for the protection system function to be executed.
    /// </member>
    DWORD HWProtectionDataByteCount;

    /// does not disturb 8-byte alignment
    DWORD Reserved;

    /// <member name="InputData">
    /// If PrivateDataByteCount is greater than 0, InputData[0] - InputData[PrivateDataSize - 1] is reserved for IHV use.
    /// InputData[PrivateDataByteCount] - InputData[HWProtectionDataByteCount + PrivateDataByteCount - 1] contains the input data for the protection system command. 
    /// The format and size of the DRM command is defined by the protection system specification.
    /// </member>
    BYTE InputData[4];
} MFCONTENTPROTECTIONDEVICE_INPUT_DATA;


typedef struct _MFCONTENTPROTECTIONDEVICE_OUTPUT_DATA
{
    /// <member name="PrivateDataByteCount">
    /// Contains the size of the private data reserved by the security processor implementation. Determined by calling IMFContentProtectionDevice::GetPrivateDataByteCount
    /// </member>
    DWORD PrivateDataByteCount;

    /// <member name="MaxHWProtectionDataByteCount">
    /// The maximum size of data that the IHV can return in the output buffer.
    /// </member>
    DWORD MaxHWProtectionDataByteCount;

    /// <member name="HWProtectionDataByteCount">
    /// Returns the size of the output data written by the IHV.
    /// </member>
    DWORD HWProtectionDataByteCount;

    /// <member name="Status">
    /// Returns the result of the protection system command.
    /// </member>
    HRESULT Status;

    /// <member name="TransportTimeInHundredsOfNanoseconds">
    /// Returns the number of 100 nanosecond units spent transporting the data. 
    /// </member>
    LONGLONG TransportTimeInHundredsOfNanoseconds;

    /// <member name="ExecutionTimeInHundredsOfNanoseconds">
    /// Returns the number of 100 nanosecond units spent executing the protection system command.
    /// </member>
    LONGLONG ExecutionTimeInHundredsOfNanoseconds;

    /// <member name="OutputData">
    /// If PrivateDataSize is greater than 0, OutputData[0] - OutputData[PrivateDataByteCount - 1] is reserved for IHV use.
    /// pbOutput[PrivateDataByteCount] - pbOutput[MaxHWProtectionDataByteCount + PrivateDataByteCount - 1] contains the region 
    /// into which the driver should return the output data from the protection system command.The format and size of the 
    /// command is defined by the protection system specification.
    /// </member>
    BYTE OutputData[4];
} MFCONTENTPROTECTIONDEVICE_OUTPUT_DATA;


///
/// System function IDs for the secure processor shall be in the range 0x04000000 to 0x04FFFFFF. This
/// effectively reserves a range of IDs that will not be used by a protection system implementation.
///
/// One structure per function ID shall be defined.
///
cpp_quote("#define MFCONTENTPROTECTIONDEVICE_FUNCTIONID_START 0x04000000")
cpp_quote("#define MFCONTENTPROTECTIONDEVICE_REALTIMECLIENT_DATA_FUNCTIONID MFCONTENTPROTECTIONDEVICE_FUNCTIONID_START")

///
/// <summary> 
///    Needed for advising the secure processor of the MMCSS parameters so that scheduling for
///    real time items can happen at the expected priority
/// </summary>
/// <member name="TaskIndex">
///    The MMCSS task identifier
/// </member>
/// <member name="ClassName">
///    The name of the MMCSS task
/// </member>
/// <member name="BasePriority">
///    The base priority of the thread
/// </member>
///
cpp_quote("typedef struct _MFCONTENTPROTECTIONDEVICE_REALTIMECLIENT_DATA {")
cpp_quote( "    DWORD TaskIndex;" )
cpp_quote( "    WCHAR ClassName[MAX_PATH];" )
cpp_quote( "    LONG BasePriority;" )
cpp_quote( "} MFCONTENTPROTECTIONDEVICE_REALTIMECLIENT_DATA;" )


/// <summary>
/// This interface allows a decryptor to communicate with the security processor implementing the hardware decryption for the given ProtectionSystemId.
/// </summary>
[
    object,
    uuid(E6257174-A060-4C9A-A088-3B1B471CAD28),
    local
]
interface IMFContentProtectionDevice : IUnknown
{
     /// Calls into the protection system ID implementation in the security processor.
     /// <param name=FunctionId>Identifier of the function that needs to be executed. To be defined by protection system ID implementation</param>
     /// <param name=InputBufferByteCount>Number of bytes of buffer InputBuffer including private data </param>
     /// <param name=InputBuffer>Pointer to the input data </param>
     /// <param name=OutputBufferByteCount>Pointer to a value that specifies the length of the data buffer OutputBuffer including private data, in bytes. 
     ///      When the function returns, this parameter contains the pointer to a value that specifies the length of the data written to the buffer, including the private bytes. </param>
     /// <param name=OutputBuffer>Pointer to the buffer where output data will be written </param>
     ///
     HRESULT InvokeFunction(
         [in, annotation("_In_")] DWORD FunctionId, 
         [in, annotation("_In_")] DWORD InputBufferByteCount, 
         [in, size_is(InputBufferByteCount), annotation("_In_reads_bytes_(InputBufferByteCount)")] const BYTE *InputBuffer,
         [in, out, annotation("_Inout_")] DWORD *OutputBufferByteCount, 
         [out, size_is(*OutputBufferByteCount), annotation("_Out_writes_bytes_(*OutputBufferByteCount)")] BYTE *OutputBuffer);
     
     /// Gets the required number of bytes that need to be prepended to 
     /// input and output buffers when calling the security processor (see InvokeFunction above).
     /// This way the MFT decryptor is able to allocate the total amount of bytes and copies can 
     /// be avoided when moving the data to the security processor.
     /// <param name=PrivateInputByteCount> Required number of bytes that need to be prepended to 
     ///      the content protection system input buffer</param>
     /// <param name=PrivateOutputByteCount> Required number of bytes that need to be prepended to 
     ///      the content protection system output buffer</param>     
     HRESULT GetPrivateDataByteCount(
         [out, annotation("_Out_")] DWORD *PrivateInputByteCount,
         [out, annotation("_Out_")] DWORD *PrivateOutputByteCount);
}

/// <summary>
/// This API creates an IMFContentProtectionDevice interface for the given ProtectionSystemId.
/// </summary>
cpp_quote( "STDAPI MFCreateContentProtectionDevice( " )
cpp_quote( "   _In_ REFGUID ProtectionSystemId, " )
cpp_quote( "   _Outptr_ IMFContentProtectionDevice **ContentProtectionDevice); " )

/// <summary>
/// This API checks whether there's support for a hardware security processor for the given MediaProtectionSystemId.
/// </summary>
cpp_quote("STDAPI MFIsContentProtectionDeviceSupported( ")
cpp_quote("   _In_ REFGUID ProtectionSystemId, ")
cpp_quote("   _Out_ BOOL *isSupported); ")

/// <summary>
/// This interface allows a decryptor to perform hardware key management and hardware sample decryption.
/// </summary>
[
    object,
    uuid(7EC4B1BD-43FB-4763-85D2-64FCB5C5F4CB),
    local
]
interface IMFContentDecryptorContext : IUnknown
{
    /// Allows the display driver to return IHV specific information used when initializing a new hardware key.
    /// <param name=InputPrivateDataByteCount>Number of bytes of buffer InputPrivateData </param>
    /// <param name=InputPrivateData>The contents of this parameter is defined by the implementation of 
    ///     the protection system implementation running in the security processor. It may contain data about license or stream properties</param>
    /// <param name=OutputPrivateData>The return data is also defined by the protection system implementation 
    ///     running in the security processor. It may contain data associated with the underlying hardware key</param>
    HRESULT InitializeHardwareKey(
        [in, annotation("_In_")] UINT InputPrivateDataByteCount,
        [in, annotation("_In_reads_opt_(InputPrivateDataByteCount)")] const void *InputPrivateData,
        [out, annotation("_Out_")] UINT64 *OutputPrivateData);
}

//
// Use this GUID to retrieve ID3D11DecryptContext from components providing that service.
//
cpp_quote( "EXTERN_GUID( MF_CONTENT_DECRYPTOR_SERVICE, 0x68a72927, 0xfc7b, 0x44ee, 0x85, 0xf4, 0x7c, 0x51, 0xbd, 0x55, 0xa6, 0x59);" )

//
// Use this GUID to retrieve IMFRealTimeClientEx from components providing that service.
//
cpp_quote("EXTERN_GUID( MF_CONTENT_PROTECTION_DEVICE_SERVICE, 0xff58436f, 0x76a0, 0x41fe, 0xb5, 0x66, 0x10, 0xcc, 0x53, 0x96, 0x2e, 0xdd);")

/// <summary>
/// This API creates an IMFContentDecryptorContext interface for the given ProtectionSystemId.
/// </summary>
cpp_quote( "STDAPI MFCreateContentDecryptorContext( " )
cpp_quote( "   _In_ REFGUID guidMediaProtectionSystemId, " )
cpp_quote( "   _In_opt_ IMFDXGIDeviceManager *pD3DManager, " )
cpp_quote( "   _In_ IMFContentProtectionDevice *pContentProtectionDevice, " )
cpp_quote( "   _Outptr_ IMFContentDecryptorContext **ppContentDecryptorContext); " )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion

#pragma region Application Family
cpp_quote("#if (WINVER >= _WIN32_WINNT_WINTHRESHOLD) ")

cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

// MF_SD_AUDIO_ENCODER_DELAY
// Data type: UINT32 8e85422c-73de-403f-9a35-550ad6e8b951
cpp_quote("EXTERN_GUID( MF_SD_AUDIO_ENCODER_DELAY,   0x8e85422c, 0x73de, 0x403f, 0x9a, 0x35, 0x55, 0x0a, 0xd6, 0xe8, 0xb9, 0x51 );")

// MF_SD_AUDIO_ENCODER_PADDING
// Data type: UINT32 

cpp_quote("EXTERN_GUID( MF_SD_AUDIO_ENCODER_PADDING, 0x529c7f2c, 0xac4b, 0x4e3f, 0xbf, 0xc3, 0x09, 0x02, 0x19, 0x49, 0x82, 0xcb );")

// CLSID_MSH264DecoderMFT
// H.264 decoder MFT
// {62CE7E72-4C71-4d20-B15D-452831A87D9D}
cpp_quote("EXTERN_GUID(CLSID_MSH264DecoderMFT, 0x62CE7E72, 0x4C71, 0x4d20, 0xB1, 0x5D, 0x45, 0x28, 0x31, 0xA8, 0x7D, 0x9D);")

// CLSID_MSH264EncoderMFT
// H.264 encoder MFT
// {6ca50344-051a-4ded-9779-a43305165e35}
cpp_quote("EXTERN_GUID(CLSID_MSH264EncoderMFT, 0x6ca50344, 0x051a, 0x4ded, 0x97, 0x79, 0xa4, 0x33, 0x05, 0x16, 0x5e, 0x35);")

// CLSID_MSDDPlusDecMFT
// DDPlus decoder MFT
// {177C0AFE-900B-48d4-9E4C-57ADD250B3D4}
cpp_quote("EXTERN_GUID(CLSID_MSDDPlusDecMFT, 0x177C0AFE, 0x900B, 0x48d4, 0x9E, 0x4C, 0x57, 0xAD, 0xD2, 0x50, 0xB3, 0xD4);")

// CLSID_MP3DecMediaObject
// MP3 DMO
// {bbeea841-0a63-4f52-a7ab-a9b3a84ed38a}
cpp_quote("EXTERN_GUID(CLSID_MP3DecMediaObject, 0xbbeea841, 0x0a63, 0x4f52, 0xa7, 0xab, 0xa9, 0xb3, 0xa8, 0x4e, 0xd3, 0x8a);")

// CLSID_MSAACDecMFT
// AAC decoder MFT
// {32d186a7-218f-4c75-8876-dd77273a8999}
cpp_quote("EXTERN_GUID(CLSID_MSAACDecMFT, 0x32d186a7, 0x218f, 0x4c75, 0x88, 0x76, 0xdd, 0x77, 0x27, 0x3a, 0x89, 0x99);")

// CLSID_MSH265DecoderMFT
// H.265 decoder MFT
// {420A51A3-D605-430C-B4FC-45274FA6C562}
cpp_quote("EXTERN_GUID(CLSID_MSH265DecoderMFT, 0x420A51A3, 0xD605, 0x430C, 0xB4, 0xFC, 0x45, 0x27, 0x4F, 0xA6, 0xC5, 0x62);")

// CLSID_WMVDecoderMFT
// WMV decoder MFT
// {82d353df-90bd-4382-8bc2-3f6192b76e34}
cpp_quote("EXTERN_GUID(CLSID_WMVDecoderMFT, 0x82d353df, 0x90bd, 0x4382, 0x8b, 0xc2, 0x3f, 0x61, 0x92, 0xb7, 0x6e, 0x34);")

// CLSID_WMADecMediaObject
// WMA decoder DMO
// {2eeb4adf-4578-4d10-bca7-bb955f56320a}
cpp_quote("EXTERN_GUID(CLSID_WMADecMediaObject, 0x2eeb4adf, 0x4578, 0x4d10, 0xbc, 0xa7, 0xbb, 0x95, 0x5f, 0x56, 0x32, 0x0a);")

// CLSID_MSMPEGAudDecMFT
// MPEG audio decoder MFT
// {70707B39-B2CA-4015-ABEA-F8447D22D88B}
cpp_quote("EXTERN_GUID(CLSID_MSMPEGAudDecMFT, 0x70707B39, 0xB2CA, 0x4015, 0xAB, 0xEA, 0xF8, 0x44, 0x7D, 0x22, 0xD8, 0x8B);")

// CLSID_MSMPEGDecoderMFT
// MPEG decoder MFT
// {2D709E52-123F-49b5-9CBC-9AF5CDE28FB9}
cpp_quote("EXTERN_GUID(CLSID_MSMPEGDecoderMFT, 0x2D709E52, 0x123F, 0x49b5, 0x9C, 0xBC, 0x9A, 0xF5, 0xCD, 0xE2, 0x8F, 0xB9);")

// CLSID_AudioResamplerMediaObject
// Audio Resampler DMO
// {f447b69e-1884-4a7e-8055-346f74d6edb3}
cpp_quote("EXTERN_GUID(CLSID_AudioResamplerMediaObject, 0xf447b69e, 0x1884, 0x4a7e, 0x80, 0x55, 0x34, 0x6f, 0x74, 0xd6, 0xed, 0xb3);")

// CLSID_MSVPxDecoder
// VP8/VP9 decoder MFT
// {E3AAF548-C9A4-4C6E-234D-5ADA374B0000}
cpp_quote("EXTERN_GUID(CLSID_MSVPxDecoder, 0xE3AAF548, 0xC9A4, 0x4C6E, 0x23, 0x4D, 0x5A, 0xDA, 0x37, 0x4B, 0x00, 0x00);")

// CLSID_MSOpusDecoder
// Opus decoder MFT
// {63e17c10-2d43-4c42-8fe3-8d8b63e46a6a}
cpp_quote("EXTERN_GUID(CLSID_MSOpusDecoder, 0x63e17c10, 0x2d43, 0x4c42, 0x8f, 0xe3, 0x8d, 0x8b, 0x63, 0xe4, 0x6a, 0x6a);")

// CLSID_VideoProcessorMFT
// Standard MF video processor component (a.k.a: XVP)
// {88753B26-5B24-49bd-B2E7-0C445C78C982}  
cpp_quote( "EXTERN_GUID(CLSID_VideoProcessorMFT, 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82);" )

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")

cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WINTHRESHOLD) ")
#pragma endregion

#pragma region EME2 helper types
cpp_quote("#if (WINVER >= _WIN32_WINNT_WINTHRESHOLD) ")
// Some of the EME 2 types are common between internally used interfaces and public interfaces.
// Having them here so both can use them
typedef enum MF_MEDIAKEYSESSION_TYPE
{
    MF_MEDIAKEYSESSION_TYPE_TEMPORARY,
    MF_MEDIAKEYSESSION_TYPE_PERSISTENT_LICENSE,
    MF_MEDIAKEYSESSION_TYPE_PERSISTENT_RELEASE_MESSAGE,
    MF_MEDIAKEYSESSION_TYPE_PERSISTENT_USAGE_RECORD
} MF_MEDIAKEYSESSION_TYPE;

typedef enum MF_MEDIAKEY_STATUS
{
    MF_MEDIAKEY_STATUS_USABLE,
    MF_MEDIAKEY_STATUS_EXPIRED,
    MF_MEDIAKEY_STATUS_OUTPUT_DOWNSCALED,
    MF_MEDIAKEY_STATUS_OUTPUT_NOT_ALLOWED,
    MF_MEDIAKEY_STATUS_STATUS_PENDING,
    MF_MEDIAKEY_STATUS_INTERNAL_ERROR,
    MF_MEDIAKEY_STATUS_RELEASED,
    MF_MEDIAKEY_STATUS_OUTPUT_RESTRICTED
} MF_MEDIAKEY_STATUS;

//+-----------------------------------------------------------------------------
//
//  Enumeration:  MFMediaKeyStatus
//
//  Synopsis:   Defines output parameter for IMFMediaKeySession2.get_KeyStatuses
//
//------------------------------------------------------------------------------
typedef struct MFMediaKeyStatus
{
    BYTE *pbKeyId;
    UINT  cbKeyId;
    MF_MEDIAKEY_STATUS eMediaKeyStatus;
} MFMediaKeyStatus;

//+-----------------------------------------------------------------------------
//
//  Enumeration:  MF_MEDIAKEYSESSION_MESSAGETYPE
//
//  Synopsis:   Defines message type for IMFMediaKeySessionNotify2 KeyMessage event
//
//------------------------------------------------------------------------------
typedef enum MF_MEDIAKEYSESSION_MESSAGETYPE
{
    MF_MEDIAKEYSESSION_MESSAGETYPE_LICENSE_REQUEST = 0,
    MF_MEDIAKEYSESSION_MESSAGETYPE_LICENSE_RENEWAL = 1,
    MF_MEDIAKEYSESSION_MESSAGETYPE_LICENSE_RELEASE = 2,
    MF_MEDIAKEYSESSION_MESSAGETYPE_INDIVIDUALIZATION_REQUEST = 3
} MF_MEDIAKEYSESSION_MESSAGETYPE;

// <summary>
// This enum maps to the W3C cross origin settings (CORS) attribute used by the HTML5 media element: 
//  * Omitted Attribute -- No CORS state.
//  * Anonymous -- Requests for the element will have their mode set to "cors" and their credentials mode set to "same-origin".
//  * Use Credentials -- Requests for the element will have their mode set to "cors" and their credentials mode set to "include".
// </summary>
typedef enum _MF_CROSS_ORIGIN_POLICY
{
    MF_CROSS_ORIGIN_POLICY_NONE = 0,
    MF_CROSS_ORIGIN_POLICY_ANONYMOUS = 1,
    MF_CROSS_ORIGIN_POLICY_USE_CREDENTIALS = 2,
} MF_CROSS_ORIGIN_POLICY;

// <summary>
// This interface is implemented by clients that want to enforce a cross origin policy for HTML5 media downloads.
// The Media Foundation network code uses these client callbacks to implement and enforce cross origin downloads.
//  * GetCrossOriginPolicy() returns the client's current cross origin policy to apply to the download session.
//  * GetSourceOrigin() returns the W3C origin of the HTML5 media element.  Use CoTaskMemFree to free the string.
//  * IsSameOrigin() returns true when the specified URL has the same origin as the HTML5 media element.
// </summary>
[
    object,
    uuid(bc2b7d44-a72d-49d5-8376-1480dee58b22),
    helpstring("IMFNetCrossOriginSupport Interface"),
    pointer_default(unique),
    local
]
interface IMFNetCrossOriginSupport : IUnknown
{
    HRESULT GetCrossOriginPolicy(
        [out, annotation("_Out_")] MF_CROSS_ORIGIN_POLICY* pPolicy
        );

    HRESULT GetSourceOrigin(
        [out, annotation("_Out_")] LPWSTR* wszSourceOrigin
        );

    HRESULT IsSameOrigin(
        [in] LPCWSTR wszURL,
        [out, annotation("_Out_")] BOOL* pfIsSameOrigin
        );
};

// <summary>
// The property ID for the IMFNetCrossOriginSupport callback object in a source resolver's IPropertyStore.
// Can be a member of the MF_MEDIA_ENGINE_SOURCE_RESOLVER_CONFIG_STORE's IPropertyStore.  Can also belong to the 
// IPropertyStore passed to IMFSchemeHandler::BeginCreateObject().
// </summary>
cpp_quote("EXTERN_GUID(MFNETSOURCE_CROSS_ORIGIN_SUPPORT, 0x9842207c, 0xb02c, 0x4271, 0xa2, 0xfc, 0x72, 0xe4, 0x93, 0x8, 0xe5, 0xc2);")

// <summary>
// This interface is implemented by clients to provide HTTP based download functionality to Media Foundation.
// </summary>
[
    object,
    uuid(F779FDDF-26E7-4270-8A8B-B983D1859DE0),
    local
]
interface IMFHttpDownloadRequest : IUnknown
{
    HRESULT AddHeader(
        [in, annotation("_In_")] LPCWSTR szHeader
    );

    HRESULT BeginSendRequest(
        [in, size_is(cbPayload), annotation("_In_reads_opt_(cbPayload)")] const BYTE* pbPayload,
        [in, annotation("_In_")] ULONG cbPayload,
        [in, annotation("_In_")] IMFAsyncCallback* pCallback,
        [in, annotation("_In_opt_")] IUnknown* punkState
    );

    HRESULT EndSendRequest(
        [in, annotation("_In_")] IMFAsyncResult* pResult
    );

    HRESULT BeginReceiveResponse(
        [in, annotation("_In_")] IMFAsyncCallback* pCallback,
        [in, annotation("_In_opt_")] IUnknown* punkState
    );

    HRESULT EndReceiveResponse(
        [in, annotation("_In_")] IMFAsyncResult* pResult
    );

    HRESULT BeginReadPayload(
        [out, size_is(cb), annotation("_Out_writes_(cb)")] BYTE* pb,
        [in, annotation("_In_")] ULONG cb,
        [in, annotation("_In_")] IMFAsyncCallback* pCallback,
        [in, annotation("_In_opt_")] IUnknown* punkState
    );

    HRESULT EndReadPayload(
        [in, annotation("_In_")] IMFAsyncResult* pResult,
        [out, annotation("_Out_")] QWORD* pqwOffset,
        [out, annotation("_Out_")] ULONG* pcbRead
    );

    HRESULT QueryHeader(
        [in, annotation("_In_")] LPCWSTR szHeaderName,
        [in, annotation("_In_")] DWORD dwIndex,
        [out, annotation("_Outptr_")] LPWSTR* ppszHeaderValue
    );

    HRESULT GetURL(
        [out, annotation("_Outptr_")] LPWSTR* ppszURL
    );

    HRESULT HasNullSourceOrigin(
        [out, annotation("_Out_")] BOOL* pfNullSourceOrigin
    );

    HRESULT GetTimeSeekResult(
        [out, annotation("_Out_")] QWORD* pqwStartTime,
        [out, annotation("_Out_")] QWORD* pqwStopTime,
        [out, annotation("_Out_")] QWORD* pqwDuration
    );

    HRESULT GetHttpStatus(
        [out, annotation("_Out_")] DWORD* pdwHttpStatus
    );

    HRESULT GetAtEndOfPayload(
        [out, annotation("_Out_")] BOOL* pfAtEndOfPayload
    );

    HRESULT GetTotalLength(
        [out, annotation("_Out_")] QWORD* pqwTotalLength
    );

    HRESULT GetRangeEndOffset(
        [out, annotation("_Out_")] QWORD* pqwRangeEnd
    );

    HRESULT Close();
};

// <summary>
// This interface is implemented by clients to provide an IMFHttpDownloadRequest implementation to Media Foundation.
// </summary>
[
    object,
    uuid(71FA9A2C-53CE-4662-A132-1A7E8CBF62DB),
    local
]
interface IMFHttpDownloadSession : IUnknown
{
    HRESULT SetServer(
        [in, annotation("_In_")] LPCWSTR szServerName,
        [in, annotation("_In_")] DWORD nPort
    );

    HRESULT CreateRequest(
        [in, annotation("_In_")] LPCWSTR szObjectName,
        [in, annotation("_In_")] BOOL fBypassProxyCache,
        [in, annotation("_In_")] BOOL fSecure,
        [in, annotation("_In_opt_")] LPCWSTR szVerb,
        [in, annotation("_In_opt_")] LPCWSTR szReferrer,
        [out, annotation("_COM_Outptr_")] IMFHttpDownloadRequest** ppRequest
    );

    HRESULT Close();
};

// <summary>
// This interface is implemented by clients that want to provide their own IMFHttpDownloadSession implementation.
// Media Foundation uses this interface to create an IMFHttpDownloadSession for downloading media.
// </summary>
[
    object,
    uuid(1B4CF4B9-3A16-4115-839D-03CC5C99DF01),
    local
]
interface IMFHttpDownloadSessionProvider : IUnknown
{
    HRESULT CreateHttpDownloadSession(
        [in, annotation("_In_")] LPCWSTR wszScheme,
        [out, annotation("_COM_Outptr_")] IMFHttpDownloadSession** ppDownloadSession
    );
};

// <summary>
// The property ID for the IMFHttpDownloadSessionProvider object in a source resolver's IPropertyStore.
// </summary>
cpp_quote("EXTERN_GUID(MFNETSOURCE_HTTP_DOWNLOAD_SESSION_PROVIDER, 0x7d55081e, 0x307d, 0x4d6d, 0xa6, 0x63, 0xa9, 0x3b, 0xe9, 0x7c, 0x4b, 0x5c);")

cpp_quote("#endif // (WINVER >= _WIN32_WINNT_WINTHRESHOLD) ")
#pragma endregion


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

typedef enum MF_MEDIASOURCE_STATUS_INFO
{
    MF_MEDIASOURCE_STATUS_INFO_FULLYSUPPORTED = 0,
    MF_MEDIASOURCE_STATUS_INFO_UNKNOWN = 1
} MF_MEDIASOURCE_STATUS_INFO;

// MF_SD_MEDIASOURCE_STATUS
// Type: MF_MEDIASOURCE_STATUS_INFO
// {1913678B-FC0F-44DA-8F43-1BA3B526F4AE}
cpp_quote("EXTERN_GUID(MF_SD_MEDIASOURCE_STATUS, 0x1913678b, 0xfc0f, 0x44da, 0x8f, 0x43, 0x1b, 0xa3, 0xb5, 0x26, 0xf4, 0xae);")

// Struct describing the view direction for spherical video
typedef struct _MF_VIDEO_SPHERICAL_VIEWDIRECTION
{
    int iHeading;           // Range: -180 to 180
    int iPitch;             // Range: -180 to 180
    int iRoll;              // Range: -180 to 180
} MF_VIDEO_SPHERICAL_VIEWDIRECTION;

cpp_quote("#define MF_UNKNOWN_DURATION 0")

// MF_SD_VIDEO_SPHERICAL
// Type: UINT32 (treat as BOOL)
// {A51DA449-3FDC-478C-BCB5-30BE76595F55}
cpp_quote("EXTERN_GUID(MF_SD_VIDEO_SPHERICAL, 0xa51da449, 0x3fdc, 0x478c, 0xbc, 0xb5, 0x30, 0xbe, 0x76, 0x59, 0x5f, 0x55);")

// MF_SD_VIDEO_SPHERICAL_FORMAT
// Type: MFVideoSphericalFormat
// {4A8FC407-6EA1-46C8-B567-6971D4A139C3}
cpp_quote("EXTERN_GUID(MF_SD_VIDEO_SPHERICAL_FORMAT, 0x4a8fc407, 0x6ea1, 0x46c8, 0xb5, 0x67, 0x69, 0x71, 0xd4, 0xa1, 0x39, 0xc3);")

// MF_SD_VIDEO_SPHERICAL_INITIAL_VIEWDIRECTION
// Type: MF_VIDEO_SPHERICAL_VIEWDIRECTION
// {11D25A49-BB62-467F-9DB1-C17165716C49}
cpp_quote("EXTERN_GUID(MF_SD_VIDEO_SPHERICAL_INITIAL_VIEWDIRECTION, 0x11d25a49, 0xbb62, 0x467f, 0x9d, 0xb1, 0xc1, 0x71, 0x65, 0x71, 0x6c, 0x49);")

// MF_MEDIASOURCE_EXPOSE_ALL_STREAMS
// Type: bool
// {E7F250B8-8FD9-4A09-B6C1-6A315C7C720E}
cpp_quote("EXTERN_GUID(MF_MEDIASOURCE_EXPOSE_ALL_STREAMS, 0xe7f250b8, 0x8fd9, 0x4a09, 0xb6, 0xc1, 0x6a, 0x31, 0x5c, 0x7c, 0x72, 0xe);")

[
    object,
    uuid(FBB03414-D13B-4786-8319-5AC51FC0A136),
    local
]
interface IMFMediaSource2 : IMFMediaSourceEx
{

    HRESULT SetMediaType(
        [in, annotation("_In_")] DWORD dwStreamID,
        [in, annotation("_In_")] IMFMediaType *pMediaType
        );
};

[
    object,
    uuid(C5BC37D6-75C7-46A1-A132-81B5F723C20F),
    local
]
interface IMFMediaStream2 : IMFMediaStream
{
    HRESULT SetStreamState(
        [in, annotation("_In_")] MF_STREAM_STATE value
        );
    HRESULT GetStreamState(
        [out, annotation("_Out_")] MF_STREAM_STATE* value
        );
};


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

//  TODO_WIN32_WINNT_REDSTONE
cpp_quote("#if (WINVER >= _WIN32_WINNT_WINTHRESHOLD) ")

#pragma region Application or Games Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)")

// {616DE972-83AD-4950-8170-630D19CBE307}
// MF_ST_MEDIASOURCE_COLLECTION
// Data type:  IUnknown
// This attribute stores the IUnknown of the IMFCollection which contains the
// IMFMediaSourceEx corresponding to the sources available to the ST.
cpp_quote("EXTERN_GUID(MF_ST_MEDIASOURCE_COLLECTION, 0x616DE972, 0x83AD, 0x4950, 0x81, 0x70, 0x63, 0x0D, 0x19, 0xCB, 0xE3, 0x07);")

// {46783CCA-3DF5-4923-A9EF-36B7223EDDE0}
// MF_DEVICESTREAM_FILTER_KSCONTROL
// Data type:  IUnknown
// This attribute stores the IUnknown of the IKsControl corresponding to the source filter.
cpp_quote("EXTERN_GUID(MF_DEVICESTREAM_FILTER_KSCONTROL, 0x46783CCA, 0x3DF5, 0x4923, 0xA9, 0xEF, 0x36, 0xB7, 0x22, 0x3E, 0xDD, 0xE0);")

// {EF3EF9A7-87F2-48CA-BE02-674878918E98}
// MF_DEVICESTREAM_PIN_KSCONTROL
// Data type:  IUnknown
// This attribute stores the IUnknown of the IKsControl corresponding to the source pin.
cpp_quote("EXTERN_GUID(MF_DEVICESTREAM_PIN_KSCONTROL, 0xEF3EF9A7, 0x87F2, 0x48CA, 0xBE, 0x02, 0x67, 0x48, 0x78, 0x91, 0x8E, 0x98);")

// {2F8CB617-361B-434F-85EA-99A03E1CE4E0}
// MF_DEVICESTREAM_SOURCE_ATTRIBUTES
// Data type:  IUnknown
// This attribute stores the IUnknown of the IMFAttributes corresponding to the source attributes
cpp_quote("EXTERN_GUID(MF_DEVICESTREAM_SOURCE_ATTRIBUTES, 0x2F8CB617, 0x361B, 0x434F, 0x85, 0xEA, 0x99, 0xA0, 0x3E, 0x1C, 0xE4, 0xE0);")

// {F402567B-4D91-4179-96D1-74C8480C2034}
// MF_DEVICESTREAM_FRAMESERVER_HIDDEN
// Data type: UINT32
// this attribute, when set on a stream, marks the stream as being 
// hidden from the client.
cpp_quote( "EXTERN_GUID( MF_DEVICESTREAM_FRAMESERVER_HIDDEN, 0xF402567B, 0x4D91, 0x4179, 0x96, 0xD1, 0x74, 0xC8, 0x48, 0x0C, 0x20, 0x34);" )

// {6770BD39-EF82-44EE-A49B-934BEB24AEF7}
// MF_STF_VERSION_INFO
// Data type: Unicode String
// Represents the version information provided by IHV/OEMs for the 
// Sensor Transform Factory.  This data must be treated as an 
// opaque data by the pipeline.
cpp_quote( "EXTERN_GUID( MF_STF_VERSION_INFO, 0x6770BD39, 0xEF82, 0x44EE, 0xA4, 0x9B, 0x93, 0x4B, 0xEB, 0x24, 0xAE, 0xF7);" )

// {31A165D5-DF67-4095-8E44-8868FC20DBFD}
// MF_STF_VERSION_DATE
// Data type: UINT64
// FILETIME representing the date/time stamp of the Sensor Transform Factory.
cpp_quote( "EXTERN_GUID( MF_STF_VERSION_DATE, 0x31A165D5, 0xDF67, 0x4095, 0x8E, 0x44, 0x88, 0x68, 0xFC, 0x20, 0xDB, 0xFD);" )

// {6D8B957E-7CF6-43F4-AF56-9C0E1E4FCBE1}
// MF_DEVICESTREAM_REQUIRED_CAPABILITIES
// Data type: Unicode String
// Semi-colon delimited capability string(s), which denotes the 
// required capabilities of a specific stream.
// The available list of capabilities can be obtained from 
// https://msdn.microsoft.com/en-us/library/windows/apps/br211430
cpp_quote( "EXTERN_GUID( MF_DEVICESTREAM_REQUIRED_CAPABILITIES, 0x6D8B957E, 0x7CF6, 0x43F4, 0xAF, 0x56, 0x9C, 0x0E, 0x1E, 0x4F, 0xCB, 0xE1);" )

// {331AE85D-C0D3-49BA-83BA-82A12D63CDD6}
// MF_DEVICESTREAM_REQUIRED_SDDL
// Data type: Unicode String
// To specify more fine grain access rights for a given Sensor
// Transform stream, the Sensor Transform can specify SDDL on
// the stream.
cpp_quote( "EXTERN_GUID( MF_DEVICESTREAM_REQUIRED_SDDL, 0x331AE85D, 0xC0D3, 0x49BA, 0x83, 0xBA, 0x82, 0xA1, 0x2D, 0x63, 0xCD, 0xD6);" )

// MF_DEVICEMFT_SENSORPROFILE_COLLECTION
// Data type: IUnknown
// IMFSensorProfileCollection interface that SGT Factory can provide to indicate new
// profiles available to the SG generation.
cpp_quote("EXTERN_GUID(MF_DEVICEMFT_SENSORPROFILE_COLLECTION, 0x36EBDC44, 0xB12C, 0x441B, 0x89, 0xF4, 0x08, 0xB2, 0xF4, 0x1A, 0x9C, 0xFC );")

// MF_DEVICESTREAM_SENSORSTREAM_ID
// Data type: UINT32
// When device streams are marked as hidden due to new profile logic, we still need to
// match the device stream to the sensor stream.  The sensor group contains all the
// streams, including the hidden ones.  The device stream IDs get translated based on
// what is hidden and what is not hidden, so we need to add an attribute to the device
// stream showing the "original" sensor stream ID.  We want to avoid overloading the
// device stream ID since that may be used by multiple components in the pipeline.
cpp_quote("EXTERN_GUID(MF_DEVICESTREAM_SENSORSTREAM_ID, 0xE35B9FE4, 0x0659, 0x4CAD, 0xBB, 0x51, 0x33, 0x16, 0x0B, 0xE7, 0xE4, 0x13 );")

typedef enum
{
    MFSensorDeviceType_Unknown = 0,
    MFSensorDeviceType_Device,
    MFSensorDeviceType_MediaSource,
    MFSensorDeviceType_FrameProvider,
    MFSensorDeviceType_SensorTransform
} MFSensorDeviceType;

typedef enum
{
    MFSensorStreamType_Unknown = 0,
    MFSensorStreamType_Input,
    MFSensorStreamType_Output
} MFSensorStreamType;

typedef enum
{
    MFSensorDeviceMode_Controller = 0,
    MFSensorDeviceMode_Shared
} MFSensorDeviceMode;

[
    object,
    uuid(FB9F48F2-2A18-4E28-9730-786F30F04DC4),
    helpstring("IMFSensorDevice Interface"),
    local
]
interface IMFSensorDevice : IUnknown
{
    HRESULT GetDeviceId(
        [out, annotation("_Out_")] ULONGLONG* pDeviceId
        );

    HRESULT GetDeviceType(
        [out, annotation("_Out_")] MFSensorDeviceType* pType
        );

    HRESULT GetFlags(
        [out, annotation("_Out_")] ULONGLONG* pFlags
        );

    HRESULT GetSymbolicLink(
        [out, size_is(cchSymbolicLink), annotation("_Out_writes_z_(cchSymbolicLink)")] LPWSTR SymbolicLink,
        [in, annotation("_In_")] LONG cchSymbolicLink,
        [out, annotation("_Out_")] LONG* pcchWritten
        );

    HRESULT GetDeviceAttributes(
        [out, annotation("_COM_Outptr_result_maybenull_")] IMFAttributes **ppAttributes
        );

    HRESULT GetStreamAttributesCount(
        [in, annotation("_In_")] MFSensorStreamType eType,
        [out, annotation("_Out_")] DWORD *pdwCount
        );

    HRESULT GetStreamAttributes(
        [in, annotation("_In_")] MFSensorStreamType eType,
        [in, annotation("_In_")] DWORD dwIndex,
        [out, annotation("_COM_Outptr_")] IMFAttributes **ppAttributes
        );

    HRESULT SetSensorDeviceMode(
        [in, annotation("_In_")] MFSensorDeviceMode eMode
        );

    HRESULT GetSensorDeviceMode(
        [out, annotation("_Out_")] MFSensorDeviceMode* peMode
        );
};

[
    object,
    uuid(4110243A-9757-461F-89F1-F22345BCAB4E),
    helpstring("IMFSensorGroup Interface"),
    local
]
interface IMFSensorGroup : IUnknown
{
    HRESULT GetSymbolicLink(
        [out, size_is(cchSymbolicLink), annotation("_Out_writes_z_(cchSymbolicLink)")] LPWSTR SymbolicLink,
        [in, annotation("_In_")] LONG cchSymbolicLink,
        [out, annotation("_Out_")] LONG* pcchWritten
        );

    HRESULT GetFlags(
        [out, annotation("_Out_")] ULONGLONG* pFlags
        );

    HRESULT GetSensorGroupAttributes(
        [out, annotation("_COM_Outptr_result_maybenull_")] IMFAttributes **ppAttributes
        );

    HRESULT GetSensorDeviceCount(
        [out, annotation("_Out_")] DWORD *pdwCount
        );

    HRESULT GetSensorDevice(
        [in, annotation("_In_")] DWORD dwIndex, 
        [out, annotation("_COM_Outptr_")] IMFSensorDevice **ppDevice
        );

    HRESULT SetDefaultSensorDeviceIndex(
        [in, annotation("_In_")] DWORD dwIndex
        );

    HRESULT GetDefaultSensorDeviceIndex(
        [out, annotation("_Out_")] DWORD* pdwIndex
        );

    HRESULT CreateMediaSource(
        [out, annotation("_COM_Outptr_")] IMFMediaSource **ppSource
        );
};

[
    object,
    uuid(E9A42171-C56E-498A-8B39-EDA5A070B7FC),
    helpstring("IMFSensorStream Interface"),
    local
]
interface IMFSensorStream : IMFAttributes
{
    HRESULT GetMediaTypeCount(
        [out, annotation("_Out_")] DWORD* pdwCount
        );

    HRESULT GetMediaType(
        [in, annotation("_In_")] DWORD dwIndex,
        [out, annotation("_COM_Outptr_")] IMFMediaType** ppMediaType
        );

    HRESULT CloneSensorStream(
        [out, annotation("_COM_Outptr_")] IMFSensorStream** ppStream
        );
};

[
    object,
    uuid(EED9C2EE-66B4-4F18-A697-AC7D3960215C),
    helpstring("IMFSensorTransformFactory Interface"),
    local

]
interface IMFSensorTransformFactory : IUnknown
{
    HRESULT GetFactoryAttributes(
        [out, annotation("_COM_Outptr_")] IMFAttributes** ppAttributes
        );

    HRESULT InitializeFactory(
        [in, annotation("_In_")] DWORD dwMaxTransformCount,
        [in, annotation("_In_")] IMFCollection* pSensorDevices,
        [in, annotation("_In_opt_")] IMFAttributes* pAttributes
        );

    HRESULT GetTransformCount(
        [out, annotation("_Out_")] DWORD* pdwCount
        );

    HRESULT GetTransformInformation(
        [in, annotation("_In_")] DWORD TransformIndex,
        [out, annotation("_Out_")] GUID* pguidTransformId,
        [out, annotation("_COM_Outptr_result_maybenull_")] IMFAttributes** ppAttributes,
        [out, annotation("_COM_Outptr_")] IMFCollection** ppStreamInformation
        );

    HRESULT CreateTransform(
        [in, annotation("_In_")] REFGUID guidSensorTransformID,
        [in, annotation("_In_opt_")] IMFAttributes* pAttributes,
        [out, annotation("_COM_Outptr_")] IMFDeviceTransform** ppDeviceMFT
        );
};

cpp_quote("STDAPI")
cpp_quote("MFCreateSensorGroup(")
cpp_quote("    _In_z_ LPCWSTR SensorGroupSymbolicLink,")
cpp_quote("    _COM_Outptr_ IMFSensorGroup** ppSensorGroup")
cpp_quote("    );")
cpp_quote("")
cpp_quote("STDAPI")
cpp_quote("MFCreateSensorStream(")
cpp_quote("    _In_ DWORD StreamId,")
cpp_quote("    _In_opt_ IMFAttributes* pAttributes,")
cpp_quote("    _In_ IMFCollection* pMediaTypeCollection,")
cpp_quote("    _COM_Outptr_ IMFSensorStream** ppStream")
cpp_quote("    );")
cpp_quote("")

typedef struct
{
    GUID    Type;
    UINT32  Index;
    UINT32  Unused;
} SENSORPROFILEID;

[
    object,
    uuid(22F765D1-8DAB-4107-846D-56BAF72215E7),
    helpstring("IMFSensorProfile Interface"),
    local
]
interface IMFSensorProfile : IUnknown
{
    HRESULT GetProfileId(
        [out, annotation("_Out_")] SENSORPROFILEID* pId
        );

    HRESULT AddProfileFilter(
        [in, annotation("_In_")] UINT32 StreamId, 
        [in, annotation("_In_z_")] LPCWSTR wzFilterSetString
        );

    HRESULT IsMediaTypeSupported(
        [in, annotation("_In_")] UINT32 StreamId, 
        [in, annotation("_In_")] IMFMediaType* pMediaType, 
        [out, annotation("_Out_")] BOOL* pfSupported
        );

    HRESULT AddBlockedControl(
        [in, annotation("_In_z_")] LPCWSTR wzBlockedControl
        );
};

[
    object,
    uuid(C95EA55B-0187-48BE-9353-8D2507662351),
    helpstring("IMFSensorProfileCollection Interface"),
    local
]
interface IMFSensorProfileCollection : IUnknown
{
    DWORD GetProfileCount(
        );

    HRESULT GetProfile(
        [in, annotation("_In_")] DWORD Index,
        [out, annotation("_COM_Outptr_")] IMFSensorProfile** ppProfile
        );

    HRESULT AddProfile(
        [in, annotation("_In_")] IMFSensorProfile* pProfile
        );

    HRESULT FindProfile(
        [in, annotation("_In_")] SENSORPROFILEID* ProfileId, 
        [out, annotation("_COM_Outptr_")] IMFSensorProfile** ppProfile
        );

    void RemoveProfileByIndex(
        [in, annotation("_In_")] DWORD Index
        );

    void RemoveProfile(
        [in, annotation("_In_")] SENSORPROFILEID* ProfileId
        );
};

cpp_quote("STDAPI")
cpp_quote("MFCreateSensorProfile(")
cpp_quote("    _In_ REFGUID ProfileType,")
cpp_quote("    _In_ UINT32 ProfileIndex,")
cpp_quote("    _In_opt_z_ LPCWSTR Constraints,")
cpp_quote("    _COM_Outptr_ IMFSensorProfile** ppProfile")
cpp_quote("    );")

cpp_quote("STDAPI")
cpp_quote("MFCreateSensorProfileCollection(")
cpp_quote("    _COM_Outptr_ IMFSensorProfileCollection** ppSensorProfile")
cpp_quote("    );")


cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */")
#pragma endregion

[
    object,
    uuid(39DC7F4A-B141-4719-813C-A7F46162A2B8),
    helpstring("IMFSensorProcessActivity Interface"),
    local
]
interface IMFSensorProcessActivity : IUnknown
{
    HRESULT GetProcessId(
        [out, annotation("_Out_")] ULONG* pPID
        );

    HRESULT GetStreamingState(
        [out, annotation("_Out_")] BOOL* pfStreaming
        );

    HRESULT GetStreamingMode(
        [out, annotation("_Out_")] MFSensorDeviceMode* pMode
        );

    HRESULT GetReportTime (
        [out, annotation("_Out_")] FILETIME* pft
        );
};

[
    object,
    uuid(3E8C4BE1-A8C2-4528-90DE-2851BDE5FEAD),
    helpstring("IMFSensorActivityReport  Interface"),
    local
]
interface IMFSensorActivityReport  : IUnknown
{
    HRESULT GetFriendlyName(
        [out, size_is(cchFriendlyName), annotation("_Out_writes_z_(cchFriendlyName)")] LPWSTR FriendlyName,
        [in, annotation("_In_")] ULONG cchFriendlyName,
        [out, annotation("_Out_")] ULONG* pcchWritten
        );

    HRESULT GetSymbolicLink(
        [out, size_is(cchSymbolicLink), annotation("_Out_writes_z_(cchSymbolicLink)")] LPWSTR SymbolicLink,
        [in, annotation("_In_")] ULONG cchSymbolicLink,
        [out, annotation("_Out_")] ULONG* pcchWritten
        );

    HRESULT GetProcessCount(
        [out, annotation("_Out_")] ULONG* pcCount
        );

    HRESULT GetProcessActivity(
        [in, annotation("_In_")] ULONG Index,
        [out, annotation("_COM_Outptr_")] IMFSensorProcessActivity** ppProcessActivity
        );
};

[
    object,
    uuid(683F7A5E-4A19-43CD-B1A9-DBF4AB3F7777),
    helpstring("IMFSensorActivitiesReport Interface"),
    local
]
interface IMFSensorActivitiesReport : IUnknown
{
    HRESULT GetCount(
        [out, annotation("_Out_")] ULONG* pcCount
        );

    HRESULT GetActivityReport(
        [in, annotation("_In_")] ULONG Index,
        [out, annotation("_COM_Outptr_")] IMFSensorActivityReport** sensorActivityReport
        );

    HRESULT GetActivityReportByDeviceName(
        [in, annotation("_In_z_")] LPCWSTR SymbolicName,
        [out, annotation("_COM_Outptr_")] IMFSensorActivityReport** sensorActivityReport
        );
};

[
    object,
    uuid(DE5072EE-DBE3-46DC-8A87-B6F631194751),
    helpstring("IMFSensorActivitiesReportCallback Interface"),
    local
]
interface IMFSensorActivitiesReportCallback : IUnknown
{
    HRESULT OnActivitiesReport(
        [in, annotation("_In_")] IMFSensorActivitiesReport* sensorActivitiesReport
        );
};

[
    object,
    uuid(D0CEF145-B3F4-4340-A2E5-7A5080CA05CB),
    helpstring("IMFSensorActivityMonitor Interface"),
    local
]
interface IMFSensorActivityMonitor : IUnknown
{
    HRESULT Start(
        );

    HRESULT Stop(
        );
};

cpp_quote("")
cpp_quote("STDAPI")
cpp_quote("MFCreateSensorActivityMonitor(")
cpp_quote("    _In_ IMFSensorActivitiesReportCallback* pCallback,")
cpp_quote("    _COM_Outptr_ IMFSensorActivityMonitor** ppActivityMonitor")
cpp_quote("    );")


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

#pragma region Application Family
cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)")

// Focal lengths and principal points to be used together with 
// distortion model coefficients to create complete parameter set
// for distortion model.
typedef struct _MFCameraIntrinsic_CameraModel
{
    FLOAT FocalLength_x;
    FLOAT FocalLength_y;
    FLOAT PrincipalPoint_x;
    FLOAT PrincipalPoint_y;
} MFCameraIntrinsic_CameraModel;

// Coefficients for radial lens distortion model with 6 radial
// and 2 tangential parameters
typedef struct _MFCameraIntrinsic_DistortionModel6KT
{
    FLOAT Radial_k1;
    FLOAT Radial_k2;
    FLOAT Radial_k3;
    FLOAT Radial_k4;
    FLOAT Radial_k5;
    FLOAT Radial_k6;
    FLOAT Tangential_p1;
    FLOAT Tangential_p2;
} MFCameraIntrinsic_DistortionModel6KT;

// Coefficients for ArcTan or F-Theta lens distortion model.
// This is equidistant fish-eye lens model
typedef struct _MFCameraIntrinsic_DistortionModelArcTan
{
    FLOAT Radial_k0;
    FLOAT DistortionCenter_x; // center of distortion in Z=1 plane, x
    FLOAT DistortionCenter_y; // center of distortion in Z=1 plane, y
    FLOAT Tangential_x;
    FLOAT Tangential_y;
} MFCameraIntrinsic_DistortionModelArcTan;

typedef enum _MFCameraIntrinsic_DistortionModelType {
    MFCameraIntrinsic_DistortionModelType_6KT = 0,
    MFCameraIntrinsic_DistortionModelType_ArcTan
} MFCameraIntrinsic_DistortionModelType;

typedef struct _MFExtendedCameraIntrinsic_IntrinsicModel
{
    // Pixel size of the frame
    UINT32 Width;
    UINT32 Height;

    // Identifier for camera's that provide two or more frames as one combined frame
    // E.g., 360-cameras typically contains two physical camera sensors but provides single stream of samples where one sample contains
    // two frames, one from each sensor. This field is used to identify those individual frames starting from top-left with id 0.
    //
    // Example of 2x1 combined frames and their identification: [0][1]
    UINT32 SplitFrameId;

    // Pinhole camera model parameters
    MFCameraIntrinsic_CameraModel CameraModel;
} MFExtendedCameraIntrinsic_IntrinsicModel;

[
    object,
    uuid(5C595E64-4630-4231-855A-12842F733245),
    local
]
interface IMFExtendedCameraIntrinsicModel : IUnknown
{
    HRESULT GetModel(
        [out, annotation("_Out_")] MFExtendedCameraIntrinsic_IntrinsicModel* pIntrinsicModel
        );
    
    HRESULT SetModel(
        [in, annotation("_In_")] const MFExtendedCameraIntrinsic_IntrinsicModel* pIntrinsicModel
        );

    HRESULT GetDistortionModelType(
        [out, annotation("_Out_")] MFCameraIntrinsic_DistortionModelType* pDistortionModelType
        );
};

[
    object,
    uuid(74C2653B-5F55-4EB1-9F0F-18B8F68B7D3D),
    local
]
interface IMFExtendedCameraIntrinsicsDistortionModel6KT : IUnknown
{
    HRESULT GetDistortionModel(
        [out, annotation("_Out_")] MFCameraIntrinsic_DistortionModel6KT* pDistortionModel
        );

    HRESULT SetDistortionModel(
        [in, annotation("_In_")] const MFCameraIntrinsic_DistortionModel6KT* pDistortionModel
        );
};

[
    object,
    uuid(812D5F95-B572-45DC-BAFC-AE24199DDDA8),
    local
]
interface IMFExtendedCameraIntrinsicsDistortionModelArcTan : IUnknown
{
    HRESULT GetDistortionModel(
        [out, annotation("_Out_")] MFCameraIntrinsic_DistortionModelArcTan* pDistortionModel
        );

    HRESULT SetDistortionModel(
        [in, annotation("_In_")] const MFCameraIntrinsic_DistortionModelArcTan* pDistortionModel
        );
};

[
    object,
    uuid(687F6DAC-6987-4750-A16A-734D1E7A10FE),
    local
]
interface IMFExtendedCameraIntrinsics : IUnknown
{
    // Initialize from buffer will clear any existing models in underlying data store
    HRESULT InitializeFromBuffer(
        [in, size_is(dwBufferSize), annotation("_In_reads_bytes_(dwBufferSize)")] BYTE* pbBuffer,
        [in] DWORD dwBufferSize
        );

    HRESULT GetBufferSize(
        [out, annotation("_Out_")] DWORD* pdwBufferSize
        );

    HRESULT SerializeToBuffer(
        [out, annotation("_Out_writes_bytes_to_(*pdwBufferSize, *pdwBufferSize)")] BYTE* pbBuffer,
        [out, annotation("_Inout_")] DWORD* pdwBufferSize
        );

    HRESULT GetIntrinsicModelCount(
        [out, annotation("_Out_")] DWORD* pdwCount
        );
    
    HRESULT GetIntrinsicModelByIndex(
        [in] DWORD dwIndex,
        [out, annotation("_COM_Outptr_")] IMFExtendedCameraIntrinsicModel** ppIntrinsicModel
        );

    HRESULT AddIntrinsicModel(
        [in, annotation("_In_")] IMFExtendedCameraIntrinsicModel* pIntrinsicModel
        );

};

// MFStreamExtension_ExtendedCameraIntrinsics 
// {AA74B3DF-9A2C-48D6-8393-5BD1C1A81E6E}
// Value type: Blob
// Stores camera intrinsics data on stream attribute store
cpp_quote("DEFINE_GUID(MFStreamExtension_ExtendedCameraIntrinsics,")
cpp_quote("    0xaa74b3df, 0x9a2c, 0x48d6, 0x83, 0x93, 0x5b, 0xd1, 0xc1, 0xa8, 0x1e, 0x6e);")

// MFSampleExtension_ExtendedCameraIntrinsics 
// {560BC4A5-4DE0-4113-9CDC-832DB9740F3D}
// Value type: Blob
// Stores camera intrinsics data on the sample's (a.k.a frame) attribute store
cpp_quote("DEFINE_GUID(MFSampleExtension_ExtendedCameraIntrinsics,")
cpp_quote("    0x560bc4a5, 0x4de0, 0x4113, 0x9c, 0xdc, 0x83, 0x2d, 0xb9, 0x74, 0xf, 0x3d);")

cpp_quote("#if (NTDDI_VERSION >= NTDDI_WIN10_RS5) ")

cpp_quote("STDAPI")
cpp_quote("MFCreateExtendedCameraIntrinsics(")
cpp_quote("    _COM_Outptr_ IMFExtendedCameraIntrinsics** ppExtendedCameraIntrinsics")
cpp_quote("    );")

cpp_quote("STDAPI")
cpp_quote("MFCreateExtendedCameraIntrinsicModel(")
cpp_quote("    const MFCameraIntrinsic_DistortionModelType distortionModelType,")
cpp_quote("    _COM_Outptr_ IMFExtendedCameraIntrinsicModel** ppExtendedCameraIntrinsicModel")
cpp_quote("    );")

cpp_quote("#endif // (NTDDI_VERSION >= NTDDI_WIN10_RS5) ")

cpp_quote("#if (NTDDI_VERSION >= NTDDI_WIN10_VB) ")


///////////////////////////////////////////////////////////////////////////////
//
// IMFExtendedCameraControl Interface
//
///////////////////////////////////////////////////////////////////////////////
[
    object,
    uuid(38E33520-FCA1-4845-A27A-68B7C6AB3789),
    helpstring("IMFExtendedCameraControl Interface"),
    local
]
/// <summary>
/// This interface is used to configure the camera's extended properties.
/// </summary>
interface IMFExtendedCameraControl : IUnknown
{
    /// <summary>
    /// Queries for property capabilities.
    /// </summary>
    /// <return>
    /// ULONGLONG mapping to property capabilities (KSCAMERA_EXTENDEDPROP_*) defined in ksmedia.h
    /// </return>
    ULONGLONG GetCapabilities();

    /// <summary>
    /// Sets the property flags.
    /// </summary>  
    /// <param name="ulFlags">
    /// ULONGLONG mapping to property flags (KSCAMERA_EXTENDEDPROP_*) defined in ksmedia.h
    /// </param>
    HRESULT SetFlags([in, annotation("_In_")] ULONGLONG ulFlags);

    /// <summary>
    /// Queries for property flags.
    /// </summary>
    /// <return>
    /// ULONGLONG mapping to property flags (KSCAMERA_EXTENDEDPROP_*) defined in ksmedia.h
    /// </return>
    ULONGLONG GetFlags();

    /// <summary>
    /// Locks the internal payload buffer for query/changes.
    /// </summary>  
    /// <param name="ppPayload">
    /// BYTE pointer to the buffer containing the raw payload.
    /// Caller should not free the buffer but instead call UnlockPayload
    /// </param>
    /// <param name="pulPayload">
    /// Size of the payload.
    /// </param>
    HRESULT LockPayload([out, annotation("_Outptr_result_buffer_(*pulPayload)")] BYTE** ppPayload, [out, annotation("_Out_")] ULONG* pulPayload);

    /// <summary>
    /// Unlocks the raw payload contained in this control.
    /// </summary>  
    HRESULT UnlockPayload();

    /// <summary>
    /// Commits the configured control settings to the camera driver.
    /// </summary>
    HRESULT CommitSettings();
};


///////////////////////////////////////////////////////////////////////////////
//
// IMFExtendedCameraController Interface
//
///////////////////////////////////////////////////////////////////////////////
[
    object,
    uuid(B91EBFEE-CA03-4AF4-8A82-A31752F4A0FC),
    helpstring("IMFExtendedCameraController Interface"),
    local
]
/// <summary>
/// This interface is used to configure the camera's extended properties.
/// </summary>
interface IMFExtendedCameraController : IUnknown
{
    /// <summary>
    /// Allows an app to get the current camera's extended property controls
    /// </summary>
    /// <param name = "dwStreamIndex">
    /// Indicates stream index to use for this property.
    /// MF_CAPTURE_ENGINE_MEDIASOURCE indicates a filter level property.
    /// </param>
    /// <param name = "ulPropertyId">
    /// ID index for identifying the property within KSPROPERTYSETID_ExtendedCameraControl.
    /// </param>
    /// <param name = "ppControl">
    /// IMFExtendedCameraControl pointer, representing the control.
    /// </param>
    HRESULT GetExtendedCameraControl(
        [in, annotation("_In_")] DWORD dwStreamIndex,
        [in, annotation("_In_")] ULONG ulPropertyId,
        [out, annotation("_COM_Outptr_")] IMFExtendedCameraControl** ppControl);
};


[
    object,
    uuid(F25362EA-2C0E-447F-81E2-755914CDC0C3),
    helpstring("IMFRelativePanelReport Interface"),
    local
]
/// <summary>
/// This interface is used to retrieve the relative panel current value.
/// </summary>
interface IMFRelativePanelReport : IUnknown
{
    /// <summary>
    /// Allows an app to get the current relative panel value
    /// </summary>
    /// <param name = "panel"> 
    /// Indicates the panel associated with the camera's relative facing to the displayRegion, using a 
    /// value from the ACPI_PLD_PANEL enumeration. Only the enumeration values of AcpiPldPanelFront, 
    /// AcpiPldPanelBack, and AcpiPldPanelUnknown are expected. 
    /// </param>
    HRESULT GetRelativePanel(
        [out, annotation("_Out_")] ULONG* panel
    );
};

[
    object,
    uuid(421AF7F6-573E-4AD0-8FDA-2E57CEDB18C6),
    helpstring("IMFRelativePanelWatcher Interface"),
    local
]
/// <summary>
/// This interface is used to control a IMFAsyncCallback, with an IMFAsyncResult to retrieve a report of its value.
/// </summary>
interface IMFRelativePanelWatcher : IMFShutdown
{
    HRESULT BeginGetReport([in, annotation("_In_")] IMFAsyncCallback* pCallback, [in, annotation("_In_opt_")] IUnknown* pState);

    HRESULT EndGetReport([in, annotation("_In_")] IMFAsyncResult* pResult, [out, annotation("_COM_Outptr_")] IMFRelativePanelReport** ppRelativePanelReport);

    /// <summary>
    /// Allows an app to retrieve the report of the current relative panel value
    /// </summary>
    /// <param name = "ppRelativePanelReport">
    /// IMFRelativePanelReport pointer, representing the panel value.
    /// </param>
    HRESULT GetReport(
        [out, annotation("_COM_Outptr_")] IMFRelativePanelReport** ppRelativePanelReport
        );
};

/// <summary>
/// Allows an app to create a Relative Panel Watcher
/// </summary>
/// <param name = "videoDeviceId">
/// string symbolic link name of the video capture device
/// </param>
/// <param name = "displayMonitorDeviceId">
/// string symbolic link name of the display monitor device
/// </param>
/// <param name = "ppRelativePanelWatcher"
/// IMFRelativePanelWatcher pointer, representing the watcher
/// </param>
cpp_quote("")
cpp_quote("STDAPI")
cpp_quote("MFCreateRelativePanelWatcher(")
cpp_quote("    _In_ PCWSTR videoDeviceId,")
cpp_quote("    _In_ PCWSTR displayMonitorDeviceId,")
cpp_quote("    _COM_Outptr_ IMFRelativePanelWatcher** ppRelativePanelWatcher")
cpp_quote("    );")

[
    object,
    local,
    uuid(725B77C7-CA9F-4FE5-9D72-9946BF9B3C70),
    helpstring("IMFVideoCaptureSampleAllocator Interface"),
    pointer_default(unique)
]
/// <summary>
/// The IMFVideoCaptureSampleAllocator interface is a specialized
/// sample allocator for video capture devices.
/// </summary>
interface IMFVideoCaptureSampleAllocator : IMFVideoSampleAllocator
{
    /// <param name="cbSampleSize">
    /// Sample size in bytes.
    /// The actual sample size used by the allocator is the maximum of
    /// the size required by pMediaType and cbSampleSize.
    /// </param>
    /// <param name="cbCaptureMetadataSize">
    /// Capture metadata size in bytes. Applies only to callers that want to
    /// to include additional metadata with the captured frames. The metadata size
    /// should include the size of a KSCAMERA_METADATA_ITEMHEADER in addition to
    /// the size of the metadata payload itself.
    /// </param>
    /// <param name="cbAlignment">
    /// Buffer alignment size in bytes.
    /// The default and minimum alignment size is 4KB. Custom alignment sizes
    /// less than 4KB will be treated as 4KB.
    /// </param>
    /// <param name="cMinimumSamples">
    /// Minimum number of pre-allocated samples.
    /// This method will fail if the allocator cannot pre-allocate the specified
    /// minimum number of samples.
    /// </param>
    /// <param name="pAttributes">
    /// Optional parameter. An IMFAttributes store with additional configuration
    /// attributes for the sample allocator. The attributes that are accepted
    /// are the same as for IMFVideoSampleAllocatorEx::InitializeSampleAllocatorEx.
    /// (See online documentation for that API for more details.)
    /// </param>
    /// <param name="pMediaType">
    /// The IMFMediaType for which samples will be allocator. The sample
    /// allocator uses this parameter to calculate the minimum required size
    /// for the media samples.
    /// </param>
    HRESULT InitializeCaptureSampleAllocator(
        [in, annotation("_In_")] DWORD cbSampleSize,
        [in, annotation("_In_")] DWORD cbCaptureMetadataSize,
        [in, annotation("_In_")] DWORD cbAlignment,
        [in, annotation("_In_")] DWORD cMinimumSamples,
        [in, annotation("_In_opt_")] IMFAttributes *pAttributes,
        [in, annotation("_In_")] IMFMediaType *pMediaType
    );
};

/// <summary>
///     The enumeration type defines video capture sample allocator mode
/// </summary>
typedef enum MFSampleAllocatorUsage
{
    MFSampleAllocatorUsage_UsesProvidedAllocator = 0,
    MFSampleAllocatorUsage_UsesCustomAllocator,
    MFSampleAllocatorUsage_DoesNotAllocate
} MFSampleAllocatorUsage;

[
    object,
    uuid(DA62B958-3A38-4A97-BD27-149C640C0771),
    helpstring("IMFSampleAllocatorControl Interface"),
    local
]
/// <summary>
/// An enumeration that specifies how an object that implements
/// IMFSampleAllocatorControl uses a sample allocator.
/// </summary>
interface IMFSampleAllocatorControl : IUnknown
{
    /// <summary>
    /// Sets the default sample allocator to use for the specified output stream.
    /// When this allocator is in use, the sample allocator usage value is
    /// MFSampleAllocatorUsage_UsesProvidedAllocator.
    /// </summary>
    /// <param name="dwOutputStreamID">
    /// The ID of the output stream that the pAllocator parameter applies to.
    /// </param>
    /// <param name="pAllocator">
    /// Provides a sample allocator to use for the specified output stream. The
    /// allocator must support one of the MF allocator interfaces, such as,
    /// IMFVideoCaptureSampleAllocator or IMFVideoSampleAllocatorEx.
    /// </param>
    HRESULT SetDefaultAllocator(
        [in, annotation("_In_")] DWORD dwOutputStreamID,
        [in, annotation("_In_")] IUnknown *pAllocator
    );

    /// <summary>
    /// Retrieves the sample allocator usage for the specified output stream.
    /// </summary>
    /// <param name="dwOutputStreamID">
    /// The ID of the output stream whose sample allocator usage is requested.
    /// </param>
    /// <param name="pdwInputStreamID">
    /// If the allocator usage is MFSampleAllocatorUsage_DoesNotAllocate,
    /// then this output parameter is set to the ID of the input stream that
    /// the output samples are coming from.
    /// For all other allocator usage values, this parameter shall be ignored.
    /// </param>
    /// <param name="peUsage">
    /// The sample allocator usage of the specified output stream.
    /// </param>
    HRESULT GetAllocatorUsage(
        [in, annotation("_In_")] DWORD dwOutputStreamID,
        [out, annotation("_Out_")] DWORD* pdwInputStreamID,
        [out, annotation("_Out_")] MFSampleAllocatorUsage* peUsage
    );
};

cpp_quote("#endif // (NTDDI_VERSION >= NTDDI_WIN10_VB) ")

cpp_quote("#if (NTDDI_VERSION >= NTDDI_WIN10_CO) ")


/// <summary>
/// This enum defines the possible occlusion states for a camera
/// </summary>
[v1_enum]
typedef enum MFCameraOcclusionState
{
    MFCameraOcclusionState_Open                         = 0x0,
    MFCameraOcclusionState_OccludedByLid                = 0x1,
    MFCameraOcclusionState_OccludedByCameraHardware     = 0x2,
} MFCameraOcclusionState;
cpp_quote("DEFINE_ENUM_FLAG_OPERATORS(MFCameraOcclusionState)")

/// <summary>
/// This interface is an input parameter for OnOcclusionStateReport callback function
/// adn is used to get the most recent camera occlusion state for the camera under monitoring.
/// </summary>
[
    object,
    uuid(1640B2CF-74DA-4462-A43B-B76D3BDC1434),
    helpstring("IMFCameraOcclusionStateReport Interface"),
    local
]
interface IMFCameraOcclusionStateReport : IUnknown
{
    /// <summary>
    /// This function will get the most recent occlusion state for the camera that's being monitored.
    /// </summary>
    /// <param name = "occlusionState">
    /// Numeric value that represents one or more MFCameraOcclusionState values.
    /// </param>
    HRESULT GetOcclusionState(
            [out, annotation("_Out_ ")] DWORD* occlusionState
    );
};

/// <summary>
/// This callback interface is required to be implemented by the client that creates
/// an IMFCameraOcclusionStateMonitor object.
/// </summary>
[
    object,
    uuid(6E5841C7-3889-4019-9035-783FB19B5948),
    helpstring("IMFCameraOcclusionStateReportCallback Interface"),
    local
]
interface IMFCameraOcclusionStateReportCallback : IUnknown
{
    /// <summary>
    /// This function will be called when the monitor detects that the occlusion state has changed.
    /// </summary>
    /// <param name = "occlusionStateReport">
    /// Pointer to the IMFCameraOcclusionStateReport interface that is used to get the most recent state.
    /// </param>
    HRESULT OnOcclusionStateReport(
        [in, annotation("_In_")] IMFCameraOcclusionStateReport* occlusionStateReport
    );
};

/// <summary>
/// This interface represents the main camera occlusion state monitor object.
/// </summary>
[
    object,
    uuid(CC692F46-C697-47E2-A72D-7B064617749B),
    helpstring("IMFCameraOcclusionStateMonitor Interface"),
    local
]
interface IMFCameraOcclusionStateMonitor : IUnknown
{
    /// <summary>
    /// This function will start the monitor and will immediately cause 
    /// OnOcclusionStateReport callback funtion to be called with the current state information.
    /// </summary>
    HRESULT Start(
    );

    /// <summary>
    /// This function will stop the monitor.
    /// </summary>
    HRESULT Stop(
    );

    /// <summary>
    /// This function will return supported camera occlusion states, the return value
    /// is combination MFCameraOcclusionState flags. MFCameraOcclusionState_Open is always supported.
    /// </summary>
    DWORD GetSupportedStates(
    );
}

/// <summary>
/// Allows app to create Camera Occlusion State Monitor for the given camera device.
/// The symbolicLink should be from the camera that is already activated, otherwise 
/// the state information is not guaranteed to be correct.
/// </summary>
/// <param name = "symbolicLink">
/// String symbolic link name of the video capture device that is active.
/// </param>
/// <param name = "callback">
/// Pointer to an object that implements the callback interface.
/// </param>
/// <param name = "occlusionStateMonitor">
/// Specifies a pointer to a variable where theIMFCameraOcclusionStateMonitor object
/// will be stored.
/// </param>
cpp_quote("")
cpp_quote("STDAPI")
cpp_quote("MFCreateCameraOcclusionStateMonitor(")
cpp_quote("    _In_z_ LPCWSTR symbolicLink,")
cpp_quote("    _In_ IMFCameraOcclusionStateReportCallback* callback,")
cpp_quote("    _COM_Outptr_ IMFCameraOcclusionStateMonitor** occlusionStateMonitor")
cpp_quote("    );")

cpp_quote("#endif // (NTDDI_VERSION >= NTDDI_WIN10_CO) ")

cpp_quote("#if (NTDDI_VERSION >= NTDDI_WIN10_NI) ")

// {94DD0C30-28C7-4EFB-9D6B-812300FB0C7F}
// KSPROPERTYSETID_ANYCAMERACONTROL
// This represents that a control is contained in a custom property set
cpp_quote("EXTERN_GUID(KSPROPERTYSETID_ANYCAMERACONTROL, 0x94dd0c30, 0x28c7, 0x4efb, 0x9d, 0x6b, 0x81, 0x23, 0x0, 0xfb, 0xc, 0x7f);")

/// <summary>
/// This interface represents the callback mechanism for the camera control monitor object. 
/// A client passes an implmented instance of this interface when creating a monitor
/// </summary>
[
    object,
    uuid(E8F2540D-558A-4449-8B64-4863467A9FE8),
    helpstring("IMFCameraControlNotify Interface"),
    local
]
interface IMFCameraControlNotify : IUnknown
{
    /// <summary>
    /// This method represents the notification callback for changes to controls. 
    /// </summary>
    /// <param name = "controlSet">
    /// If provided controlSet GUID is MF_CAMERACONTROL_PROPSET_CUSTOM, then the callback was invoked by a 
    /// subscription for a change to a control outside the supported Property Sets
    /// </param>
    /// <param name = "id">
    /// This is the id of the control in its set.
    /// </param>
    void OnChange(
        [in, annotation("_In_")] REFGUID controlSet,
        [in, annotation("_In_")] UINT32 id);

    /// <summary>
    /// This method notifies client if an unrecoverable error occurs within the monitor.
    /// After call returns to monitor, it will cleanup and remove reference to IMFCameraControlNotify
    /// There is not a need to call IMFCameraControlMonitor::Shutdown after receiving an OnError
    /// </summary>
    /// <param name = "hrStatus">
    /// The internal error code. 
    /// If E_OUTOFMEMORY, then there were not enough resources available for the monitor to function properly
    /// If MF_INVALID_STATE_ERR, then there has been some corruption of memory states.
    /// </param>
    void OnError(
        [in, annotation("_In_")] HRESULT hrStatus);
}

/// <summary>
/// This interface represents the main camera control monitor object.
/// </summary>
[
    object,
    uuid(4D46F2C9-28BA-4970-8C7B-1F0C9D80AF69),
    helpstring("IMFCameraControlMonitor Interface"),
    local
]
interface IMFCameraControlMonitor : IUnknown
{
    /// <summary>
    /// This function will start the monitor. The monitor will call OnChange on Subscriptions linked to changed controls
    /// If called when Monitor is already started or has shutdown, method will return error MF_E_INVALIDREQUEST
    /// </summary>
    HRESULT Start(
    );

    /// <summary>
    /// This function will stop the monitor. A client can stop the monitor to pause notifications.
    /// In Stopped state, client can Add/Remove Control Subscriptions.
    /// If called when Monitor is already stopped or has shutdown, method will return error MF_E_INVALIDREQUEST
    /// </summary>
    HRESULT Stop(
    );

    /// <summary>
    /// This function will add to the list of controls for which the client wants to be notified
    /// If the provided controlSet is MF_CAMERACONTROL_PROPSET_CUSTOM, then the monitor's callback will be called for the change of "Any Control"
    /// If called when Monitor is in Start or Shutdown state, method will return error MF_E_INVALIDREQUEST
    /// If controlSet is not MF_CAMERACONTROL_PROPSET_CUSTOM, PROPSETID_VIDCAP_VIDEOPROCAMP, PROPSETID_VIDCAP_CAMERACONTROL or
    /// KSPROPERTYSETID_ExtendedCameraControl then method will return with error E_INVALIDARG
    /// </summary>
    HRESULT AddControlSubscription(
        [in, annotation("_In_")] GUID controlSet,
        [in, annotation("_In_")] UINT32 id
    );

    /// <summary>
    /// This function will remove the subscription for this control from the monitor
    /// If the provided controlSet is MF_CAMERACONTROL_PROPSET_CUSTOM, then the subscription for "Any Control" change will be removed
    /// If called when Monitor is in Start or Shutdown state, method will return with error MF_E_INVALIDREQUEST
    /// If provided control description does not match a current subscription, method will return with error MF_E_NOT_FOUND
    /// </summary>
    HRESULT RemoveControlSubscription(
        [in, annotation("_In_")] GUID controlSet,
        [in, annotation("_In_")] UINT32 id
    );

    /// This function will cleanup and shutdown the monitor.
    /// It is acceptable to call Shutdown even if monitor is not in stop state 
    /// After Shutdown, a client cannot call on the Monitor to Add/Remove Control Subscriptions or Start/Stop notifications    
    /// </summary>
    void Shutdown();
}

/// <summary>
/// Allows app to create CameraControlMonitor.
/// If provided symbolic link name does not match a camera device, then method will return E_INVALIDARG
/// </summary>
/// <param name = "symbolicLink">
/// String symbolic link name of the video capture device that is active.
/// </param>
/// <param name = "callback">
/// Pointer to an object that implements the callback interface.
/// </param>
/// <param name = "ppCameraControlMonitor">
/// Specifies a pointer to a variable where the IMFCameraControlMonitor object
/// will be stored.
/// </param>
cpp_quote("")
cpp_quote("STDAPI")
cpp_quote("MFCreateCameraControlMonitor(")
cpp_quote("    _In_z_ LPCWSTR symbolicLink,")
cpp_quote("    _In_ IMFCameraControlNotify* callback,")
cpp_quote("    _COM_Outptr_ IMFCameraControlMonitor ** ppCameraControlMonitor")
cpp_quote("    );")

typedef enum
{
    MF_CAMERA_CONTROL_CONFIGURATION_TYPE_PRESTART = 0,
    MF_CAMERA_CONTROL_CONFIGURATION_TYPE_POSTSTART,
} MF_CAMERA_CONTROL_CONFIGURATION_TYPE;

typedef struct
{
    LONG    minValue;
    LONG    maxValue;
    LONG    stepValue;
    LONG    defaultValue;
} MF_CAMERA_CONTROL_RANGE_INFO;

[
    object,
    uuid(75510662-B034-48F4-88A7-8DE61DAA4AF9),
    helpstring("IMFCameraControlDefaults Interface"),
    local
]
interface IMFCameraControlDefaults : IUnknown
{
    /// <summary>
    /// Gets the configuration type (pre-start or post-start).  Some 
    /// camera level controls can only be set after the camera has
    /// started (such as focus/brightness/whitebalance) since the 
    /// controls require frame data for the parameters to converge. 
    /// While still other types of controls can only be configured 
    /// when the camera is not in a running state (such as HDR 
    /// support) since it requires a re-programming of the camera 
    /// mode.
    /// 
    /// Whether a well known control is pre or post start is 
    /// specified in the DDI specification of the control. 
    /// (NOTE:  If the DDI specification does not explicitly 
    /// indicate the control is a pre-start control, caller must 
    /// assume the control is post-start).  
    /// </summary>
    MF_CAMERA_CONTROL_CONFIGURATION_TYPE GetType(
        );

    /// <summary>
    /// The legacy PROPSETID_VIDCAP_VIDEOPROCAMP and 
    /// PROPSETID_VIDCAP_CAMERACONTROL control sets provide a 
    /// min/max/step/default value which bounds the acceptable range 
    /// of values that can be configured. 
    ///  
    /// For other controls, the caller is responsible for knowing 
    /// whether the underlying control supports the basic range 
    /// information.  Calling into this method for a control that 
    /// does not support basic range will return MF_E_NOT_FOUND. 
    /// </summary>
    HRESULT GetRangeInfo(
        [out, annotation("_Out_")] MF_CAMERA_CONTROL_RANGE_INFO* rangeInfo
        );

    /// <summary>
    /// Because the camera control schema and optional data payload 
    /// schema can be arbitrary (the only constraint is that all 
    /// control schema must have KSPROPERTY as the first structure 
    /// in the binary format), this method provides the caller a way 
    /// to modify the contents of the control and data payload 
    /// directly. 
    ///  
    /// UnlockControlData must be called before the collection this 
    /// control is contained in is sent to 
    /// IMFCameraConfigurationManager::SaveDefaults() method. 
    /// </summary>
    HRESULT LockControlData(
        [out, annotation("_Outptr_result_bytebuffer_(*controlSize)")] void** control, 
        [out, annotation("_Out_")] ULONG* controlSize, 
        [out, annotation("_Outptr_opt_result_bytebuffer_(*dataSize)")] void** data, 
        [out, annotation("_Out_opt_")] ULONG* dataSize
        );

    /// <summary>
    /// Once UnlockControlData is called, the caller must not attempt to 
    /// modify the buffer pointer returned from LockControlData.  Doing 
    /// so will result in undefined behavior. 
    /// </summary>
    HRESULT UnlockControlData(
        );
};

[
    object,
    uuid(92D43D0F-54A8-4BAE-96DA-356D259A5C26),
    helpstring("IMFCameraControlDefaultsCollection Interface"),
    local
]
interface IMFCameraControlDefaultsCollection : IMFAttributes
{
    /// <summary>
    /// Return the number of controls currently in the collection.
    /// </summary>
    ULONG   GetControlCount(
        );

    /// <summary>
    /// Return the control based on the 0 based index provided.  The
    /// index provided must be -1 of the control count. 
    /// </summary>
    HRESULT GetControl(
        [in, annotation("_In_")] ULONG index,
        [out, annotation("_COM_Outptr_")] IMFCameraControlDefaults** configuration
        );

    /// <summary>
    /// Add a new extended camera control to the collection.  The 
    /// controlId provided must be an id in the 
    /// KSPROPERTYSETID_ExtendedCameraControl property set. 
    ///  
    /// The streamId is only used when the underlying camera control 
    /// is a pin level control, otherwise this value is ignored. 
    ///  
    /// Depending on the control, the data payload size/schema may 
    /// vary.  The dataSize must be valid for the control payload 
    /// schema so the control can reserve the buffer required. 
    /// </summary>
    HRESULT GetOrAddExtendedControl(
        [in, annotation("_In_")] MF_CAMERA_CONTROL_CONFIGURATION_TYPE configType,
        [in, annotation("_In_")] ULONG constrolId,
        [in, annotation("_In_")] DWORD streamId,
        [in, annotation("_In_")] ULONG dataSize,
        [out, annotation("_COM_Outptr_")] IMFCameraControlDefaults** defaults
        );

    /// <summary>
    /// For custom controls, controlSet/controlId are based on the 
    /// custom control DDI published by the camera driver vendor. 
    /// Similarly, the controlSize and dataSize are based on the DDI 
    /// published by the vendor. 
    ///  
    /// NOTE:  controlSize must be >= sizeof(KSPROPERTY) even for 
    /// custom controls. 
    /// </summary>
    HRESULT GetOrAddControl(
        [in, annotation("_In_")] MF_CAMERA_CONTROL_CONFIGURATION_TYPE configType,
        [in, annotation("_In_")] REFGUID controlSet,
        [in, annotation("_In_")] ULONG constrolId,
        [in, annotation("_In_")] ULONG controlSize,
        [in, annotation("_In_")] ULONG dataSize,
        [out, annotation("_COM_Outptr_")] IMFCameraControlDefaults** defaults
        );

    /// <summary>
    /// Removes a control based on the set/id.
    /// </summary>
    HRESULT RemoveControl(
        [in, annotation("_In_")] REFGUID controlSet,
        [in, annotation("_In_")] ULONG constrolId
        );

    /// <summary>
    /// Removes all controls in the collection. 
    /// </summary>
    HRESULT RemoveAllControls();
};

/// CLSID_CameraConfigurationManager
///  
/// Data type: GUID CLSID for creating the 
/// IMFCameraConfigurationManager. 
///  
/// {6C92B540-5854-4A17-92B6-AC89C96E9683}
cpp_quote( "EXTERN_GUID(CLSID_CameraConfigurationManager, 0x6C92B540, 0x5854, 0x4A17,0x92, 0xB6, 0xAC, 0x89, 0xC9, 0x6E, 0x96, 0x83);" )

[
    object,
    uuid(A624F617-4704-4206-8A6D-EBDA4A093985),
    helpstring("IMFCameraConfigurationManager Interface"),
    local
]
interface IMFCameraConfigurationManager : IUnknown
{
    /// Loads the camera control defaults as specified by the 
    /// MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK in 
    /// the cameraAttributes parameter. 
    /// If there are no default controls specified, the resulting 
    /// collection will be empty (GetControlCount returns 0) 
    ///  
    /// NOTE: If the
    /// MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK is 
    /// not set, this method will return MF_E_ATTRIBUTENOTFOUND. 
    HRESULT LoadDefaults(
        [in, annotation("_In_")] IMFAttributes* cameraAttributes, 
        [out, annotation("_COM_Outptr_")] IMFCameraControlDefaultsCollection** configurations
        );

    /// Save the collection of camera control defaults.  The 
    /// information will be stored on the camera defined by the 
    /// MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK when 
    /// the collection was loaded.  Saving an empty collection will 
    /// result in all the existing control defaults being cleared. 
    HRESULT SaveDefaults(
        [in, annotation("_In_")] IMFCameraControlDefaultsCollection* configurations
        );

    /// Shutdown the configuration manager.  Subsequent calls to 
    /// LoadDefaults/SaveDefaults after the 
    /// IMFCameraConfigurationManager is shutdown will result in 
    /// MF_E_SHUTDOWN error. 
    void Shutdown(
        );
};

cpp_quote("#endif // (NTDDI_VERSION >= NTDDI_WIN10_NI) ")

cpp_quote("#if (NTDDI_VERSION >= NTDDI_WIN11_ZN) ")

typedef struct
{
    DWORD       sizeInBytes;           // Size in bytes to next DetectedFaceBound
    float       normalizedXPosition;   // Normalized between 0.0 - 1.0
    float       normalizedYPosition;   // Normalized between 0.0 - 1.0
    float       normalizedWidth;       // Normalized between 0.0 - 1.0
    float       normalizedHeight;      // Normalized between 0.0 - 1.0
    LONG        confidenceValue;       // Normalized between 0 - 100
    ULONGLONG   flags;
} DetectedFaceBound;

[
    object,
    uuid(0BFD1ADE-0421-4909-ACB7-7A7125416881),
    helpstring("IMFFaceDetectionTransformCallback"),
    local
]
interface IMFFaceDetectionTransformCallback  : IUnknown
{
    void OnFaceDetectionResult(
        [in, annotation("_In_")] ULONG countOfBounds,
        [in, annotation("_In_reads_(countOfBounds)")] DetectedFaceBound* detectedFaceBounds
        );
};

[
    object,
    uuid(DDD59578-D0E7-46E2-BE8C-1CE76AD147C0),
    helpstring("IMFFaceDetectionTransform"),
    local
]
interface IMFFaceDetectionTransform  : IUnknown
{
    HRESULT SetDetectionCallback(
        [in, annotation("_In_")] IMFFaceDetectionTransformCallback* callback,
        [out, annotation("_Out_")] void** callbackToken
        );

    HRESULT ClearDetectionCallback(
        [in, annotation("_In_")] void* callbackToken
        );
};

/// CLSID_FaceDetectionMFT  
///   
/// Data type: GUID CLSID for creating Face Detection  
/// IMFTransform.  Also implements the IMFFaceDetectionTransform  
/// interface.  
///   
/// {C1E565E2-F2DE-4537-9612-2F30A160EB5C} 
cpp_quote("EXTERN_GUID(CLSID_FaceDetectionMFT,  0xc1e565e2, 0xf2de, 0x4537, 0x96, 0x12, 0x2f, 0x30, 0xa1, 0x60, 0xeb, 0x5c);") 

/// CLSID_FrameServerClassFactory 
///  
/// Data type: GUID CLSID for creating the 
/// IMFActivate from the Frame Server.
///
/// NOTE:  This CLSID may only be CoCreated from
/// Frame Server service process.  Any attempts to
/// instantiate this CLSID from a non-Frame Server
/// service process will fail with access denied.
///
/// It is recommended that applications use 
/// MFCreateDeviceSource or MFEnumDeviceSources to
/// create an IMFMediaSource for the camera.
///  
/// {9A93092C-9CDC-49B8-8349-CBCF3145FE0A}
cpp_quote( "EXTERN_GUID(CLSID_FrameServerClassFactory, 0x9A93092C, 0x9CDC, 0x49B8, 0x83, 0x49, 0xCB, 0xCF, 0x31, 0x45, 0xFE, 0x0A);")

/// MF_CAMERASOURCE_PROVIDE_SELECTED_PROFILE_ON_START 
///   
/// Data type: UINT32 - Set to non-zero to have pipeline provide 
/// the selected camera profile on the first stream start 
/// on the source. Setting the value to 0 will be treatd as if 
/// the attribute was not set: the selected profile is sent during 
/// client initialization.  Multiple clients may initialize the 
/// same source so the selected profile may be issued independent 
/// of the start operation. 
/// 
/// Setting this attribute enables an optimization 
/// (reducing the number of profile changes), but the KsEvent 
/// and KsProperty methods handling  still need to handle the case where 
/// the optimization is not available. If the new 
/// PROFILE_ON_START property is honored, then the KsEvent and 
/// KsProperty methods are called less often, avoiding 
/// unnecessary profile changes. 
///  
/// {A9B46058-82F2-4E5C-BF6E-25B4B09F22ED}
cpp_quote( "EXTERN_GUID(MF_CAMERASOURCE_PROVIDE_SELECTED_PROFILE_ON_START, 0xA9B46058, 0x82F2, 0x4E5C, 0xBF, 0x6E, 0x25, 0xB4, 0xB0, 0x9F, 0x22, 0xED);")

/// MF_DEVSOURCE_ATTRIBUTE_FRAMESERVER_SHARE_MODE 
///  
/// Attribute used during MFCreateDeviceSource or 
/// IMFActivate::ActivateObject to create an instance of 
/// IMFMediaSource in shared mode. 
///  
/// Shared mode allows multiple shared mode applications to 
/// stream from the same camera without the ability to change 
/// the extended camera controls nor change media types. 
///  
/// Data type: UINT32 
///  
/// 0 or not set - Default non-shared mdoe instance. 
///  
/// 1 - Shared mode instance. 
///  
/// {44d1a9bc-2999-4238-ae43-0730ceb2ab1b}
cpp_quote("EXTERN_GUID(MF_DEVSOURCE_ATTRIBUTE_FRAMESERVER_SHARE_MODE, 0x44d1a9bc, 0x2999, 0x4238, 0xae, 0x43, 0x07, 0x30, 0xce, 0xb2, 0xab, 0x1b);")

cpp_quote("#endif // (NTDDI_VERSION >= NTDDI_WIN11_ZN) ")

cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */")
#pragma endregion // Application Family
