Jump to content

Recommended Posts

Posted (edited)

I think it would kind of interesting to put our knowledge (and time) to construct something solid around this foundation.  It was mentioned in this thread and I believe that it is something worth investing to.

https://learn.microsoft.com/en-us/windows/win32/medfound/microsoft-media-foundation-sdk

Here a working take on playback.

#include <StructureConstants.au3>
#include <GUIConstants.au3>
#include <Array.au3>

Opt("MustDeclareVars", True)

Global Const $MF_VERSION = 0x00020070
Global Enum $MFSTARTUP_FULL, $MFSTARTUP_LITE
Local $aCall, $iHresult

$aCall = DllCall("Mfplat.dll", "long", "MFStartup", "long", $MF_VERSION, "long", $MFSTARTUP_FULL)

$aCall = DllCall("Mf.dll", "long", "MFCreateMediaSession", "ptr", 0, "ptr*", 0)
Local $pIMFMediaSession = $aCall[2]

Global Const $sIID_IMFMediaEventGenerator = "(2cd0bd52-bcd5-4b89-b62c-eadc0c031e7d)"
Global Const $tag_IMFMediaEventGenerator = _
    "GetEvent hresult(long; ptr*);" & _
    "BeginGetEvent hresult(ptr; ptr);" & _
    "EndGetEvent hresult(ptr; ptr*);" & _
    "QueueEvent hresult(uint; struct*; hresult; struct*);"

Global Const $sIID_IMFMediaSession = "{90377834-21d0-4dee-8214-ba2e3e6c1127}"
Global Const $tag_IMFMediaSession = $tag_IMFMediaEventGenerator & _
    "SetTopology hresult(uint; ptr);" & _
    "ClearTopologies hresult();" & _
    "Start hresult(struct*; struct*);" & _
    "Pause hresult();" & _
    "Stop hresult();" & _
    "Close hresult();" & _
    "Shutdown hresult();" & _
    "GetClock hresult(ptr*);" & _
    "GetSessionCapabilities hresult(uint*);" & _
    "GetFullTopology hresult(uint; uint64; ptr*);"

Local $oIMFMediaSession = ObjCreateInterface($pIMFMediaSession, $sIID_IMFMediaSession, $tag_IMFMediaSession)
ConsoleWrite("oIMFMediaSession " & IsObj($oIMFMediaSession) & @CRLF)

$aCall = DllCall("Mfplat.dll", "long", "MFCreateSourceResolver", "ptr*", 0)
Local $pIMFSourceResolver = $aCall[1]
Global Const $sIID_IMFSourceResolver = "{fbe5a32d-a497-4b61-bb85-97b1a848a6e3}"
Global Const $tag_IMFSourceResolver = _
    "CreateObjectFromURL hresult(wstr; uint; ptr; long*; ptr*);" & _
    "CreateObjectFromByteStream hresult(ptr; wstr; uint; ptr; long*; ptr*);" & _
    "BeginCreateObjectFromURL hresult(wstr; uint; ptr; ptr*; ptr; ptr);" & _
    "EndCreateObjectFromURL hresult(ptr; long*; ptr*);" & _
    "BeginCreateObjectFromByteStream hresult(ptr; wstr; uint; ptr; ptr*; ptr; ptr);" & _
    "EndCreateObjectFromByteStream hresult(ptr; long*; ptr*);" & _
    "CancelObjectCreation hresult(ptr);"

Local $oIMFSourceResolver = ObjCreateInterface($pIMFSourceResolver, $sIID_IMFSourceResolver, $tag_IMFSourceResolver)
ConsoleWrite("oIMFSourceResolver " & IsObj($oIMFSourceResolver) & @CRLF)

Global Const $MF_RESOLUTION_MEDIASOURCE = 1
Global Enum $MF_OBJECT_MEDIASOURCE, $MF_OBJECT_BYTESTREAM, $MF_OBJECT_INVALID
Local $iObjType, $pMediaSource

Local $hResult = $oIMFSourceResolver.CreateObjectFromURL(@ScriptDir & "\Relax.mp4", $MF_RESOLUTION_MEDIASOURCE, 0, $iObjType, $pMediaSource)

Global Const $sIID_IMFMediaSource = "{279a808d-aec7-40c8-9c6b-a6b492c78a66}"
Global Const $tag_IMFMediaSource = $tag_IMFMediaEventGenerator & _
    "GetCharacteristics hresult(uint*);" & _
    "CreatePresentationDescriptor hresult(ptr*);" & _
    "Start hresult(ptr; struct*; struct*);" & _
    "Stop hresult();" & _
    "Pause hresult();" & _
    "Shutdown hresult();"
Local $oIMFMediaSource = ObjCreateInterface($pMediaSource, $sIID_IMFMediaSource, $tag_IMFMediaSource)
ConsoleWrite("oIMFMediaSource " & IsObj($oIMFMediaSource) & @CRLF)
Local $pIMFPresentationDescriptor
$oIMFMediaSource.CreatePresentationDescriptor($pIMFPresentationDescriptor)

Global Const $sIID_IMFAttributes = "(2cd2d921-c447-44a7-a13c-4adabfc247e3)"
Global Const $tag_IMFAttributes = _
    "GetItem hresult(struct*; struct*);" & _
    "GetItemType hresult(struct*; long*);" & _
    "CompareItem hresult(struct*; struct*; bool*);" & _
    "Compare hresult(ptr; long; bool*);" & _
    "GetUINT32 hresult(struct*; uint*);" & _
    "GetUINT64 hresult(struct*; uint64*);" & _
    "GetDouble hresult(struct*; double*);" & _
    "GetGUID hresult(struct*; struct*);" & _
    "GetStringLength hresult(struct*; uint*);" & _
    "GetString hresult(struct*; wstr; uint; uint*);" & _
    "GetAllocatedString hresult(struct*; wstr*; uint*);" & _
    "GetBlobSize hresult(struct*; uint*);" & _
    "GetBlob hresult(struct*; struct*; uint; uint*);" & _
    "GetAllocatedBlob hresult(struct*; ptr*; uint*);" & _
    "GetUnknown hresult(struct*; struct*; ptr*);" & _
    "SetItem hresult(struct*; struct*);" & _
    "DeleteItem hresult(struct*);" & _
    "DeleteAllItems hresult();" & _
    "SetUINT32 hresult(struct*; uint);" & _
    "SetUINT64 hresult(struct*; uint64);" & _
    "SetDouble hresult(struct*; double);" & _
    "SetGUID hresult(struct*; struct*);" & _
    "SetString hresult(struct*; wstr);" & _
    "SetBlob hresult(struct*; struct*; uint);" & _
    "SetUnknown hresult(struct*; ptr);" & _
    "LockStore hresult();" & _
    "UnlockStore hresult();" & _
    "GetCount hresult(uint*);" & _
    "GetItemByIndex hresult(uint; struct*; struct*);" & _
    "CopyAllItems hresult(ptr);"

Global Const $sIID_IMFPresentationDescriptor = "{03cb2711-24d7-4db6-a17f-f3a7a479a536}"
Global Const $tag_IMFPresentationDescriptor = $tag_IMFAttributes & _
    "GetStreamDescriptorCount hresult(uint*);" & _
    "GetStreamDescriptorByIndex hresult(uint; bool*; ptr*);" & _
    "SelectStream hresult(uint);" & _
    "DeselectStream hresult(uint);" & _
    "Clone hresult(ptr*);"

Local $oIMFPresentationDescriptor = ObjCreateInterface($pIMFPresentationDescriptor, $sIID_IMFPresentationDescriptor, $tag_IMFPresentationDescriptor)
ConsoleWrite("oIMFPresentationDescriptor " & IsObj($oIMFPresentationDescriptor) & @CRLF)

; CreatePlaybackTopology

Local $hWnd = GUICreate("Basic Playback", 800, 600, -1, -1, $WS_OVERLAPPEDWINDOW)
; register msg

Global Const $sIID_IMFTopology = "{83cf873a-f6da-4bc8-823f-bacfd55dc433}"
Global Const $tag_IMFTopology = $tag_IMFAttributes & _
  "GetTopologyID hresult();" & _
  "AddNode hresult(ptr);" & _
  "RemoveNode hresult();" & _
  "GetNodeCount hresult();" & _
  "GetNode hresult();" & _
  "Clear hresult();" & _
  "CloneFrom hresult();" & _
  "GetNodeByID hresult();" & _
  "GetSourceNodeCollection hresult();" & _
  "GetOutputNodeCollection hresult();"

$aCall = DllCall("Mf.dll", "long", "MFCreateTopology", "ptr*", 0)
Local $pIMFTopology = $aCall[1]
Local $oIMFTopology = ObjCreateInterface($pIMFTopology, $sIID_IMFTopology, $tag_IMFTopology)
ConsoleWrite("oIMFTopology " & IsObj($oIMFTopology) & @CRLF)

Local $iCount, $bSelect, $pIMFStreamDescriptor, $oIMFStreamDescriptor
$oIMFPresentationDescriptor.GetStreamDescriptorCount($iCount)
Global Enum $MF_TOPOLOGY_OUTPUT_NODE, $MF_TOPOLOGY_SOURCESTREAM_NODE, $MF_TOPOLOGY_TRANSFORM_NODE, $MF_TOPOLOGY_TEE_NODE, $MF_TOPOLOGY_MAX = 0xFFFFFFFF
Global Const $sIID_IMFTopologyNode = "{83cf873a-f6da-4bc8-823f-bacfd55dc430}"
Global Const $tag_IMFTopologyNode = $tag_IMFAttributes & _
  "SetObject hresult(ptr);" & _
  "GetObject hresult();" & _
  "GetNodeType hresult();" & _
  "GetTopoNodeID hresult();" & _
  "SetTopoNodeID hresult();" & _
  "GetInputCount hresult();" & _
  "GetOutputCount hresult();" & _
  "ConnectOutput hresult(dword;ptr;dword);" & _
  "DisconnectOutput hresult();" & _
  "GetInput hresult();" & _
  "GetOutput hresult();" & _
  "SetOutputPrefType hresult();" & _
  "GetOutputPrefType hresult();" & _
  "SetInputPrefType hresult();" & _
  "GetInputPrefType hresult();" & _
  "CloneFrom hresult();"
Global Const $MF_TOPONODE_SOURCE = __COM_CreateGUID("{835c58ec-e075-4bc7-bcba-4de000df9ae6}")
Global Const $MF_TOPONODE_PRESENTATION_DESCRIPTOR = __COM_CreateGUID("{835c58ed-e075-4bc7-bcba-4de000df9ae6}")
Global Const $MF_TOPONODE_STREAM_DESCRIPTOR = __COM_CreateGUID("{835c58ee-e075-4bc7-bcba-4de000df9ae6}")
Global Const $MFMediaType_Audio = __COM_CreateGUID("{73647561-0000-0010-8000-00aa00389b71}")
Global Const $MFMediaType_Video = __COM_CreateGUID("{73646976-0000-0010-8000-00aa00389b71}")
Global Const $MF_TOPONODE_NOSHUTDOWN_ON_REMOVE = __COM_CreateGUID("{14932f9c-9087-4bb4-8412-5167145cbe04}")
Global Const $MF_TOPONODE_STREAMID = __COM_CreateGUID("{14932f9b-9087-4bb4-8412-5167145cbe04}")

Global Const $sIID_IMFStreamDescriptor = "{56c03d9c-9dbb-45f5-ab4b-d80f47c05938}"
Global Const $tag_IMFStreamDescriptor = $tag_IMFAttributes & _
  "GetStreamIdentifier hresult(ptr*);" & _
  "GetMediaTypeHandler hresult(ptr*);"

Global Const $sIID_IMFMediaTypeHandler = "{e93dcf6c-4b07-4e1e-8123-aa16ed6eadf5}"
Global Const $tag_IMFMediaTypeHandler = _
  "IsMediaTypeSupported hresult();" & _
  "GetMediaTypeCount hresult();" & _
  "GetMediaTypeByIndex hresult();" & _
  "SetCurrentMediaType hresult();" & _
  "GetCurrentMediaType hresult();" & _
  "GetMajorType hresult(struct*);"

Local $pSourceNode, $oSourceNode, $pIMFMediaTypeHandler, $oIMFMediaTypeHandler, $pIMFActivate
Local $pOutputNode, $oOutputNode, $tGUID = DllStructCreate($tagGUID)

For $i = 0 To $iCount - 1
  $oIMFPresentationDescriptor.GetStreamDescriptorByIndex($i, $bSelect, $pIMFStreamDescriptor)
  $oIMFStreamDescriptor = ObjCreateInterface($pIMFStreamDescriptor, $sIID_IMFStreamDescriptor, $tag_IMFStreamDescriptor)
  ConsoleWrite("oIMFStreamDescriptor " & IsObj($oIMFStreamDescriptor) & @CRLF)
  If $bSelect Then
    ; Add a source node for this stream.
    $aCall = DllCall("Mf.dll", "long", "MFCreateTopologyNode", "dword", $MF_TOPOLOGY_SOURCESTREAM_NODE, "ptr*", 0)
    $pSourceNode = $aCall[2]
    $oSourceNode = ObjCreateInterface($pSourceNode, $sIID_IMFTopologyNode, $tag_IMFTopologyNode)
    ConsoleWrite("oSourceNode " & IsObj($oSourceNode) & @CRLF)
    $oSourceNode.SetUnknown($MF_TOPONODE_SOURCE, $pMediaSource)
    $oSourceNode.SetUnknown($MF_TOPONODE_PRESENTATION_DESCRIPTOR, $pIMFPresentationDescriptor)
    $oSourceNode.SetUnknown($MF_TOPONODE_STREAM_DESCRIPTOR, $pIMFStreamDescriptor)
    $oIMFTopology.AddNode($pSourceNode)

    ; Create the output node for the renderer.

    $oIMFStreamDescriptor.GetMediaTypeHandler($pIMFMediaTypeHandler)
    $oIMFMediaTypeHandler = ObjCreateInterface($pIMFMediaTypeHandler, $sIID_IMFMediaTypeHandler, $tag_IMFMediaTypeHandler)
    ConsoleWrite("oIMFMediaTypeHandler " & IsObj($oIMFMediaTypeHandler) & @CRLF)
    $oIMFMediaTypeHandler.GetMajorType($tGUID)
    If __COM_ReadGUIDAt(DllStructGetPtr($tGUID)) =  __COM_ReadGUIDAt(DllStructGetPtr($MFMediaType_Audio)) Then
      ConsoleWrite("=== audio ===" & @CRLF)
      $aCall = DllCall("Mf.dll", "long", "MFCreateAudioRendererActivate", "ptr*", 0)
      $pIMFActivate = $aCall[1]
    ElseIf __COM_ReadGUIDAt(DllStructGetPtr($tGUID)) =  __COM_ReadGUIDAt(DllStructGetPtr($MFMediaType_Video)) Then
      ConsoleWrite("=== video ===" & @CRLF)
      $aCall = DllCall("Mf.dll", "long", "MFCreateVideoRendererActivate", "hwnd", $hWnd, "ptr*", 0)
      $pIMFActivate = $aCall[2]
    EndIf

    $aCall = DllCall("Mf.dll", "long", "MFCreateTopologyNode", "dword", $MF_TOPOLOGY_OUTPUT_NODE, "ptr*", 0)
    $pOutputNode = $aCall[2]
    $oOutputNode = ObjCreateInterface($pOutputNode, $sIID_IMFTopologyNode, $tag_IMFTopologyNode)
    ConsoleWrite("oOutputNode " & IsObj($oOutputNode) & @CRLF)
    $oOutputNode.SetObject($pIMFActivate)
    $oIMFTopology.AddNode($pOutputNode)
    $oOutputNode.SetUINT32($MF_TOPONODE_STREAMID, 0)
    $oOutputNode.SetUINT32($MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, True)

    ; Connect the source node to the output node.
    $iHresult = $oSourceNode.ConnectOutput(0, $pOutputNode, 0)
    ConsoleWrite("SourceNode.ConnectOutput " & $iHresult & @CRLF)
  EndIf
Next

GUISetState(@SW_SHOW, $hWnd)

$iHresult = $oIMFMediaSession.SetTopology(0, $pIMFTopology)
ConsoleWrite("IMFMediaSession.SetTopology " & $iHresult & @CRLF)
$tGUID = __COM_CreateGUID()
Local $tVtPropEmpty = DllStructCreate("align 2;ushort vt;word Pad[3]")
DllStructSetData($tVtPropEmpty, "vt", 0)
$iHResult = $oIMFMediaSession.Start($tGUID, $tVtPropEmpty)

While True
  Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE
      ExitLoop
  EndSwitch
WEnd

$iHresult = $oIMFMediaSession.Close()
ConsoleWrite("IMFMediaSession.Close " & $iHresult & @CRLF)
Sleep(1000)

$iHresult = $oIMFMediaSource.Shutdown()
ConsoleWrite("IMFMediaSource.Shutdown " & $iHresult & @CRLF)
$iHresult = $oIMFMediaSession.Shutdown()
ConsoleWrite("IMFMediaSession.Shutdown " & $iHresult & @CRLF)
$aCall = DllCall("Mfplat.dll", "long", "MFShutdown")

; ===============================================================

Func __COM_CreateGUID($sGUID = "{00000000-0000-0000-0000-000000000000}", $pAddress = 0)
  Local $tGUID = ($pAddress And IsPtr($pAddress)) ? DllStructCreate($tagGUID, $pAddress) : DllStructCreate($tagGUID)
  Local $aGUID = StringSplit(StringRegExpReplace($sGUID, "[{}]", ""), "-", 2)
  If UBound($aGUID) <> 5 Then Return SetError(1, 0, False)
  DllStructSetData($tGUID, 1, Dec($aGUID[0]))
  DllStructSetData($tGUID, 2, Dec($aGUID[1]))
  DllStructSetData($tGUID, 3, Dec($aGUID[2]))
  DllStructSetData($tGUID, 4, Binary("0x" & $aGUID[3] & $aGUID[4]))
  Return $tGUID
EndFunc   ;==>__COM_CreateGUID

Func __COM_ReadGUIDAt($pGUID)
  Local $tGUID, $sGUID
  If (Not $pGUID) Or (Not IsPtr($pGUID)) Then Return SetError(1, 0, "")
  $tGUID = DllStructCreate($tagGUID, $pGUID)
  $sGUID = StringFormat("{%s-%s-%s-%s-%s}", _
      Hex(DllStructGetData($tGUID, 1), 8), _
      Hex(DllStructGetData($tGUID, 2), 4), _
      Hex(DllStructGetData($tGUID, 3), 4), _
      StringMid(DllStructGetData($tGUID, 4), 3, 4), _
      StringMid(DllStructGetData($tGUID, 4), 7, 12))
  Return $sGUID
EndFunc   ;==>__COM_ReadGUIDAt

ps. it is very linear, but later code is structured as it should be (see solution).

Edited by Nine
Posted (edited)

A few interfaces for you sir! -

These were semi-generated from the rust v-table documentation... I'll start working though them in the coming days.

Global Const $sIID_IMFAttributes = "(2cd2d921-c447-44a7-a13c-4adabfc247e3)"
Global Const $tag_IMFAttributes = _
        "GetItem hresult(struct*; struct*);" & _
        "GetItemType hresult(struct*; long*);" & _
        "CompareItem hresult(struct*; struct*; bool*);" & _
        "Compare hresult(ptr; long; bool*);" & _
        "GetUINT32 hresult(struct*; uint*);" & _
        "GetUINT64 hresult(struct*; uint64*);" & _
        "GetDouble hresult(struct*; double*);" & _
        "GetGUID hresult(struct*; struct*);" & _
        "GetStringLength hresult(struct*; uint*);" & _
        "GetString hresult(struct*; wstr; uint; uint*);" & _
        "GetAllocatedString hresult(struct*; wstr*; uint*);" & _
        "GetBlobSize hresult(struct*; uint*);" & _
        "GetBlob hresult(struct*; struct*; uint; uint*);" & _
        "GetAllocatedBlob hresult(struct*; ptr*; uint*);" & _
        "GetUnknown hresult(struct*; struct*; ptr*);" & _
        "SetItem hresult(struct*; struct*);" & _
        "DeleteItem hresult(struct*);" & _
        "DeleteAllItems hresult();" & _
        "SetUINT32 hresult(struct*; uint);" & _
        "SetUINT64 hresult(struct*; uint64);" & _
        "SetDouble hresult(struct*; double);" & _
        "SetGUID hresult(struct*; struct*);" & _
        "SetString hresult(struct*; wstr);" & _
        "SetBlob hresult(struct*; struct*; uint);" & _
        "SetUnknown hresult(struct*; ptr);" & _
        "LockStore hresult();" & _
        "UnlockStore hresult();" & _
        "GetCount hresult(uint*);" & _
        "GetItemByIndex hresult(uint; struct*; struct*);" & _
        "CopyAllItems hresult(ptr);"

Global Const $sIID_IMFMediaEventGenerator = "(2cd0bd52-bcd5-4b89-b62c-eadc0c031e7d)"
Global Const $tag_IMFMediaEventGenerator = _
        "GetEvent hresult(long; ptr*);" & _
        "BeginGetEvent hresult(ptr; ptr);" & _
        "EndGetEvent hresult(ptr; ptr*);" & _
        "QueueEvent hresult(uint; struct*; hresult; struct*);"

Global Const $sIID_IMFMediaSession = "{90377834-21D0-4dee-8214-BA2E3E6C1127}"
Global Const $tag_IMFMediaSession = $tag_IMFMediaEventGenerator & _
        "SetTopology hresult(uint; ptr);" & _
        "ClearTopologies hresult();" & _
        "Start hresult(struct*; struct*);" & _
        "Pause hresult();" & _
        "Stop hresult();" & _
        "Close hresult();" & _
        "Shutdown hresult();" & _
        "GetClock hresult(ptr*);" & _
        "GetSessionCapabilities hresult(uint*);" & _
        "GetFullTopology hresult(uint; uint64; ptr*);"

Global Const $sIID_IMFMediaSource = "{279a808d-aec7-40c8-9c6b-a6b492c78a66}"
Global Const $tag_IMFMediaSource = $tag_IMFMediaEventGenerator & _
        "GetCharacteristics hresult(uint*);" & _
        "CreatePresentationDescriptor hresult(ptr*);" & _
        "Start hresult(ptr; struct*; struct*);" & _
        "Stop hresult();" & _
        "Pause hresult();" & _
        "Shutdown hresult();"

Global Const $sIID_IMFSourceResolver = "{FBE5A32D-A497-4b61-BB85-97B1A848A6E3}"
Global Const $tag_IMFSourceResolver = _
        "CreateObjectFromURL hresult(wstr; uint; ptr; long*; ptr*);" & _
        "CreateObjectFromByteStream hresult(ptr; wstr; uint; ptr; long*; ptr*);" & _
        "BeginCreateObjectFromURL hresult(wstr; uint; ptr; ptr*; ptr; ptr);" & _
        "EndCreateObjectFromURL hresult(ptr; long*; ptr*);" & _
        "BeginCreateObjectFromByteStream hresult(ptr; wstr; uint; ptr; ptr*; ptr; ptr);" & _
        "EndCreateObjectFromByteStream hresult(ptr; long*; ptr*);" & _
        "CancelObjectCreation hresult(ptr);"

Global Const $sIID_IMFPresentationDescriptor = "{03cb2711-24d7-4db6-a17f-f3a7a479a536}"
Global Const $tag_IMFPresentationDescriptor = _
        $tag_IMFAttributes & _
        "GetStreamDescriptorCount hresult(uint*);" & _
        "GetStreamDescriptorByIndex hresult(uint; bool*; ptr*);" & _
        "SelectStream hresult(uint);" & _
        "DeselectStream hresult(uint);" & _
        "Clone hresult(ptr*);"

And a couple funcs that I use to create and read guids.

Func __COM_CreateGUID($sGUID = "{00000000-0000-0000-0000-000000000000}", $pAddress = 0)
    Local $tGUID = ($pAddress And IsPtr($pAddress)) ? DllStructCreate($tagGUID, $pAddress) : DllStructCreate($tagGUID)
    Local $aGUID = StringSplit(StringRegExpReplace($sGUID, "[{}]", ""), "-", 2)
    If UBound($aGUID) <> 5 Then Return SetError($ERROR_INVALID_PARAMETER, 0, False)
    DllStructSetData($tGUID, 1, Dec($aGUID[0]))
    DllStructSetData($tGUID, 2, Dec($aGUID[1]))
    DllStructSetData($tGUID, 3, Dec($aGUID[2]))
    DllStructSetData($tGUID, 4, Binary("0x" & $aGUID[3] & $aGUID[4]))
    Return $tGUID
EndFunc   ;==>__COM_CreateGUID

Func __COM_ReadGUIDAt($pGUID)
    Local $tGUID, $sGUID
    If (Not $pGUID) Or (Not IsPtr($pGUID)) Then Return SetError($ERROR_INVALID_PARAMETER, 0, "")
    $tGUID = DllStructCreate($tagGUID, $pGUID)
    $sGUID = StringFormat("{%s-%s-%s-%s-%s}", _
            Hex(DllStructGetData($tGUID, 1), 8), _
            Hex(DllStructGetData($tGUID, 2), 4), _
            Hex(DllStructGetData($tGUID, 3), 4), _
            StringMid(DllStructGetData($tGUID, 4), 3, 4), _
            StringMid(DllStructGetData($tGUID, 4), 7, 12))
    Return $sGUID
EndFunc   ;==>__COM_ReadGUIDAt
Edited by MattyD
Posted (edited)

Here's a bunch more definitions from the mf*.idl files - they might not all be relevant and some might be missing (derived GUIDs with DEFINE_MEDIATYPE_GUID for e.g.), but I figure its probably a good starting point for copy/paste or something :)

The enum file only contains things that were declared as enums in the idls. So no straight up constants are in that file..

 Edit 11th April: Added IIDs List - I'll continue to add/update resources in this post.

MF_Enums.au3 MF_GUIDS.au3 MF_IIDs.au3

Edited by MattyD
Posted (edited)

Ok got the topology working I think...

Edit: skipped the IMFMediaEventGenerator step and went straight to playback!

#AutoIt3Wrapper_UseX64=N ;test both x86/x64

#include <APIErrorsConstants.au3>
#include <StructureConstants.au3>
#include <GUIConstants.au3>
#include <Array.au3>

Opt("MustDeclareVars", True)

Local $sTestFile =  "c:\users\matt\Desktop\test.mp4"

#Region Constants

Global Const $S_OK = 0
Global Const $S_FALSE = 1

Global Const $MF_VERSION = 0x00020070 ; 0x00010070 is needed for pre-Win7.
Global Enum $MFSTARTUP_FULL, $MFSTARTUP_LITE, $MFSTARTUP_NOSOCKET = $MFSTARTUP_LITE

Global Const $MF_RESOLUTION_MEDIASOURCE = 1
Global Enum $MF_OBJECT_MEDIASOURCE, $MF_OBJECT_BYTESTREAM, $MF_OBJECT_INVALID

; MF_TOPOLOGY_TYPE
Global Enum $MF_TOPOLOGY_OUTPUT_NODE, _
        $MF_TOPOLOGY_SOURCESTREAM_NODE, _
        $MF_TOPOLOGY_TRANSFORM_NODE, _
        $MF_TOPOLOGY_TEE_NODE, _
        $MF_TOPOLOGY_MAX = 0xffffffff

; MFSESSION_SETTOPOLOGY_FLAGS
Global Enum $MFSESSION_SETTOPOLOGY_IMMEDIATE = 0x1, _
        $MFSESSION_SETTOPOLOGY_NORESOLUTION = 0x2, _
        $MFSESSION_SETTOPOLOGY_CLEAR_CURRENT = 0x4

Global Enum $VT_EMPTY = 0, _
        $VT_NULL = 1, _
        $VT_I2 = 2, _
        $VT_I4 = 3, _
        $VT_R4 = 4, _
        $VT_R8 = 5, _
        $VT_CY = 6, _
        $VT_DATE = 7, _
        $VT_BSTR = 8, _
        $VT_DISPATCH = 9, _
        $VT_ERROR = 10, _
        $VT_BOOL = 11, _
        $VT_VARIANT = 12, _
        $VT_UNKNOWN = 13, _
        $VT_DECIMAL = 14, _
        $VT_I1 = 16, _
        $VT_UI1 = 17, _
        $VT_UI2 = 18, _
        $VT_UI4 = 19, _
        $VT_I8 = 20, _
        $VT_UI8 = 21, _
        $VT_INT = 22, _
        $VT_UINT = 23, _
        $VT_VOID = 24, _
        $VT_HRESULT = 25, _
        $VT_PTR = 26, _
        $VT_SAFEARRAY = 27, _
        $VT_CARRAY = 28, _
        $VT_USERDEFINED = 29, _
        $VT_LPSTR = 30, _
        $VT_LPWSTR = 31, _
        $VT_RECORD = 36, _
        $VT_INT_PTR = 37, _
        $VT_UINT_PTR = 38, _
        $VT_FILETIME = 64, _
        $VT_BLOB = 65, _
        $VT_STREAM = 66, _
        $VT_STORAGE = 67, _
        $VT_STREAMED_OBJECT = 68, _
        $VT_STORED_OBJECT = 69, _
        $VT_BLOB_OBJECT = 70, _
        $VT_CF = 71, _
        $VT_CLSID = 72, _
        $VT_VERSIONED_STREAM = 73, _
        $VT_BSTR_BLOB = 0xfff, _
        $VT_VECTOR = 0x1000, _
        $VT_ARRAY = 0x2000, _
        $VT_BYREF = 0x4000, _
        $VT_RESERVED = 0x8000, _
        $VT_ILLEGAL = 0xffff, _
        $VT_ILLEGALMASKED = 0xfff, _
        $VT_TYPEMASK = 0xfff

#EndRegion

#Region Interface Defs

Global Const $sIID_IMFAttributes = "(2cd2d921-c447-44a7-a13c-4adabfc247e3)"
Global Const $tag_IMFAttributes = _
        "GetItem hresult(struct*; struct*);" & _
        "GetItemType hresult(struct*; long*);" & _
        "CompareItem hresult(struct*; struct*; bool*);" & _
        "Compare hresult(ptr; long; bool*);" & _
        "GetUINT32 hresult(struct*; uint*);" & _
        "GetUINT64 hresult(struct*; uint64*);" & _
        "GetDouble hresult(struct*; double*);" & _
        "GetGUID hresult(struct*; struct*);" & _
        "GetStringLength hresult(struct*; uint*);" & _
        "GetString hresult(struct*; wstr; uint; uint*);" & _
        "GetAllocatedString hresult(struct*; wstr*; uint*);" & _
        "GetBlobSize hresult(struct*; uint*);" & _
        "GetBlob hresult(struct*; struct*; uint; uint*);" & _
        "GetAllocatedBlob hresult(struct*; ptr*; uint*);" & _
        "GetUnknown hresult(struct*; struct*; ptr*);" & _
        "SetItem hresult(struct*; struct*);" & _
        "DeleteItem hresult(struct*);" & _
        "DeleteAllItems hresult();" & _
        "SetUINT32 hresult(struct*; uint);" & _
        "SetUINT64 hresult(struct*; uint64);" & _
        "SetDouble hresult(struct*; double);" & _
        "SetGUID hresult(struct*; struct*);" & _
        "SetString hresult(struct*; wstr);" & _
        "SetBlob hresult(struct*; struct*; uint);" & _
        "SetUnknown hresult(struct*; ptr);" & _
        "LockStore hresult();" & _
        "UnlockStore hresult();" & _
        "GetCount hresult(uint*);" & _
        "GetItemByIndex hresult(uint; struct*; struct*);" & _
        "CopyAllItems hresult(ptr);"

Global Const $sIID_IMFMediaEventGenerator = "(2cd0bd52-bcd5-4b89-b62c-eadc0c031e7d)"
Global Const $tag_IMFMediaEventGenerator = _
        "GetEvent hresult(long; ptr*);" & _
        "BeginGetEvent hresult(ptr; ptr);" & _
        "EndGetEvent hresult(ptr; ptr*);" & _
        "QueueEvent hresult(uint; struct*; hresult; struct*);"

Global Const $sIID_IMFMediaSession = "{90377834-21D0-4dee-8214-BA2E3E6C1127}"
Global Const $tag_IMFMediaSession = $tag_IMFMediaEventGenerator & _
        "SetTopology hresult(uint; ptr);" & _
        "ClearTopologies hresult();" & _
        "Start hresult(struct*; struct*);" & _
        "Pause hresult();" & _
        "Stop hresult();" & _
        "Close hresult();" & _
        "Shutdown hresult();" & _
        "GetClock hresult(ptr*);" & _
        "GetSessionCapabilities hresult(uint*);" & _
        "GetFullTopology hresult(uint; uint64; ptr*);"

Global Const $sIID_IMFMediaSource = "{279a808d-aec7-40c8-9c6b-a6b492c78a66}"
Global Const $tag_IMFMediaSource = $tag_IMFMediaEventGenerator & _
        "GetCharacteristics hresult(uint*);" & _
        "CreatePresentationDescriptor hresult(ptr*);" & _
        "Start hresult(ptr; struct*; struct*);" & _
        "Stop hresult();" & _
        "Pause hresult();" & _
        "Shutdown hresult();"

Global Const $sIID_IMFSourceResolver = "{FBE5A32D-A497-4b61-BB85-97B1A848A6E3}"
Global Const $tag_IMFSourceResolver = _
        "CreateObjectFromURL hresult(wstr; uint; ptr; long*; ptr*);" & _
        "CreateObjectFromByteStream hresult(ptr; wstr; uint; ptr; long*; ptr*);" & _
        "BeginCreateObjectFromURL hresult(wstr; uint; ptr; ptr*; ptr; ptr);" & _
        "EndCreateObjectFromURL hresult(ptr; long*; ptr*);" & _
        "BeginCreateObjectFromByteStream hresult(ptr; wstr; uint; ptr; ptr*; ptr; ptr);" & _
        "EndCreateObjectFromByteStream hresult(ptr; long*; ptr*);" & _
        "CancelObjectCreation hresult(ptr);"

Global Const $sIID_IMFPresentationDescriptor = "{03cb2711-24d7-4db6-a17f-f3a7a479a536}"
Global Const $tag_IMFPresentationDescriptor = $tag_IMFAttributes & _
        "GetStreamDescriptorCount hresult(uint*);" & _
        "GetStreamDescriptorByIndex hresult(uint; bool*; ptr*);" & _
        "SelectStream hresult(uint);" & _
        "DeselectStream hresult(uint);" & _
        "Clone hresult(ptr*);"

Global Const $sIID_IMFTopologyNode = "{83cf873a-f6da-4bc8-823f-bacfd55dc430}"
Global Const $tag_IMFTopologyNode = $tag_IMFAttributes & _
        "SetObject hresult(ptr);" & _
        "GetObject hresult(ptr*);" & _
        "GetNodeType hresult(long*);" & _
        "GetTopoNodeID hresult(uint64*);" & _
        "SetTopoNodeID hresult(uint64);" & _
        "GetInputCount hresult(uint*);" & _
        "GetOutputCount hresult(uint*);" & _
        "ConnectOutput hresult(uint; ptr; uint);" & _
        "DisconnectOutput hresult(uint);" & _
        "GetInput hresult(uint; ptr*; uint*);" & _
        "GetOutput hresult(uint; ptr*; uint*);" & _
        "SetOutputPrefType hresult(uint; ptr);" & _
        "GetOutputPrefType hresult(uint; ptr*);" & _
        "SetInputPrefType hresult(uint; ptr);" & _
        "GetInputPrefType hresult(uint; ptr*);" & _
        "CloneFrom hresult(ptr);"

Global Const $sIID_IMFTopology = "{83cf873a-f6da-4bc8-823f-bacfd55dc433}"
Global Const $tag_IMFTopology = $tag_IMFAttributes & _
        "GetTopologyID hresult(uint64*);" & _
        "AddNode hresult(ptr);" & _
        "RemoveNode hresult(ptr);" & _
        "GetNodeCount hresult(short*);" & _
        "GetNode hresult(short; ptr*);" & _
        "Clear hresult();" & _
        "CloneFrom hresult(ptr);" & _
        "GetNodeByID hresult(uint64; ptr*);" & _
        "GetSourceNodeCollection hresult(ptr*);" & _
        "GetOutputNodeCollection hresult(ptr*);"

Global Const $sIID_IMFStreamDescriptor = "{56c03d9c-9dbb-45f5-ab4b-d80f47c05938}"
Global Const $tag_IMFStreamDescriptor = $tag_IMFAttributes & _
        "GetStreamIdentifier hresult(uint*);" & _
        "GetMediaTypeHandler hresult(ptr*);"

Global Const $sIID_IMFMediaTypeHandler = "{e93dcf6c-4b07-4e1e-8123-aa16ed6eadf5}"
Global Const $tag_IMFMediaTypeHandler = _
        "IsMediaTypeSupported hresult(ptr; ptr*);" & _
        "GetMediaTypeCount hresult(uint*);" & _
        "GetMediaTypeByIndex hresult(uint; ptr*);" & _
        "SetCurrentMediaType hresult(ptr);" & _
        "GetCurrentMediaType hresult(ptr*);" & _
        "GetMajorType hresult(struct*);"

#EndRegion

#Region GUIDs

Global Const $MF_TOPONODE_ERRORCODE = __COM_CreateGUID("{494bbcee-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_CONNECT_METHOD = __COM_CreateGUID("{494bbcf1-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_LOCKED = __COM_CreateGUID("{494bbcf7-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_WORKQUEUE_ID = __COM_CreateGUID("{494bbcf8-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_WORKQUEUE_MMCSS_CLASS = __COM_CreateGUID("{494bbcf9-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_DECRYPTOR = __COM_CreateGUID("{494bbcfa-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_DISCARDABLE = __COM_CreateGUID("{494bbcfb-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_ERROR_MAJORTYPE = __COM_CreateGUID("{494bbcfd-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_ERROR_SUBTYPE = __COM_CreateGUID("{494bbcfe-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_WORKQUEUE_MMCSS_TASKID = __COM_CreateGUID("{494bbcff-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_MARKIN_HERE = __COM_CreateGUID("{494bbd00-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_MARKOUT_HERE = __COM_CreateGUID("{494bbd01-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_DECODER = __COM_CreateGUID("{494bbd02-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_MEDIASTART = __COM_CreateGUID("{835c58ea-e075-4bc7-bcba-4de000df9ae6}")
Global Const $MF_TOPONODE_MEDIASTOP = __COM_CreateGUID("{835c58eb-e075-4bc7-bcba-4de000df9ae6}")
Global Const $MF_TOPONODE_SOURCE = __COM_CreateGUID("{835c58ec-e075-4bc7-bcba-4de000df9ae6}")
Global Const $MF_TOPONODE_PRESENTATION_DESCRIPTOR = __COM_CreateGUID("{835c58ed-e075-4bc7-bcba-4de000df9ae6}")
Global Const $MF_TOPONODE_STREAM_DESCRIPTOR = __COM_CreateGUID("{835c58ee-e075-4bc7-bcba-4de000df9ae6}")
Global Const $MF_TOPONODE_SEQUENCE_ELEMENTID = __COM_CreateGUID("{835c58ef-e075-4bc7-bcba-4de000df9ae6}")
Global Const $MF_TOPONODE_TRANSFORM_OBJECTID = __COM_CreateGUID("{88dcc0c9-293e-4e8b-9aeb-0ad64cc016b0}")
Global Const $MF_TOPONODE_STREAMID = __COM_CreateGUID("{14932f9b-9087-4bb4-8412-5167145cbe04}")
Global Const $MF_TOPONODE_NOSHUTDOWN_ON_REMOVE = __COM_CreateGUID("{14932f9c-9087-4bb4-8412-5167145cbe04}")
Global Const $MF_TOPONODE_RATELESS = __COM_CreateGUID("{14932f9d-9087-4bb4-8412-5167145cbe04}")
Global Const $MF_TOPONODE_DISABLE_PREROLL = __COM_CreateGUID("{14932f9e-9087-4bb4-8412-5167145cbe04}")
Global Const $MF_TOPONODE_PRIMARYOUTPUT = __COM_CreateGUID("{6304ef99-16b2-4ebe-9d67-e4c539b3a259}")

Global Const $MFMediaType_Audio = __COM_CreateGUID("{73647561-0000-0010-8000-00aa00389b71}")
Global Const $MFMediaType_Binary = __COM_CreateGUID("{72178c25-e45b-11d5-bc2a-00b0d0f3f4ab}")
Global Const $MFMediaType_Default = __COM_CreateGUID("{81a412e6-8103-4b06-857f-1862781024ac}")
Global Const $MFMediaType_FileTransfer = __COM_CreateGUID("{72178c26-e45b-11d5-bc2a-00b0d0f3f4ab}")
Global Const $MFMediaType_HTML = __COM_CreateGUID("{72178c24-e45b-11d5-bc2a-00b0d0f3f4ab}")
Global Const $MFMediaType_Image = __COM_CreateGUID("{72178c23-e45b-11d5-bc2a-00b0d0f3f4ab}")
Global Const $MFMediaType_MultiplexedFrames = __COM_CreateGUID("{6ea542b0-281f-4231-a464-fe2f5022501c}")
Global Const $MFMediaType_Perception = __COM_CreateGUID("{597ff6f9-6ea2-4670-85b4-ea84073fe940}")
Global Const $MFMediaType_Protected = __COM_CreateGUID("{7b4b6fe6-9d04-4494-be14-7e0bd076c8e4}")
Global Const $MFMediaType_SAMI = __COM_CreateGUID("{e69669a0-3dcd-40cb-9e2e-3708387c0616}")
Global Const $MFMediaType_Script = __COM_CreateGUID("{72178c22-e45b-11d5-bc2a-00b0d0f3f4ab}")
Global Const $MFMediaType_Stream = __COM_CreateGUID("{e436eb83-524f-11ce-9f53-0020af0ba770}")
Global Const $MFMediaType_Subtitle = __COM_CreateGUID("{a6d13581-ed50-4e65-ae08-26065576aacc}")
Global Const $MFMediaType_Video = __COM_CreateGUID("{73646976-0000-0010-8000-00aa00389b71}")

#Region

Local $hResult
Local $hWnd = GUICreate("Basic Playback", 800, 600, -1, -1, $WS_OVERLAPPEDWINDOW)

_MF_Startup()

;Start Session
ConsoleWrite(StringFormat("(%d,0) Start Session", @ScriptLineNumber) & @CRLF)
Local $pIMFMediaSession = _MF_CreateMediaSession()
Local $oIMFMediaSession = ObjCreateInterface($pIMFMediaSession, $sIID_IMFMediaSession, $tag_IMFMediaSession)
ConsoleWrite(StringFormat("(%d,0) $oIMFMediaSession = %s\r\n", @ScriptLineNumber, IsObj($oIMFMediaSession)) & @CRLF)

;Create the media source (using source resolver).
ConsoleWrite(StringFormat("(%d,0) Load Source", @ScriptLineNumber) & @CRLF)
Local $pIMFSourceResolver = _MF_CreateSourceResolver()
Local $oIMFSourceResolver = ObjCreateInterface($pIMFSourceResolver, $sIID_IMFSourceResolver, $tag_IMFSourceResolver)
Local $iObjType, $pMediaSource ;OUT Params
$hResult = $oIMFSourceResolver.CreateObjectFromURL($sTestFile, $MF_RESOLUTION_MEDIASOURCE, 0, $iObjType, $pMediaSource)
Local $oIMFMediaSource = ObjCreateInterface($pMediaSource, $sIID_IMFMediaSource, $tag_IMFMediaSource)

;Get the media source's presentation descriptor.
Local $pIMFPresentationDescriptor
$hResult = $oIMFMediaSource.CreatePresentationDescriptor($pIMFPresentationDescriptor)
Local $oIMFPresentationDescriptor = ObjCreateInterface($pIMFPresentationDescriptor, $sIID_IMFPresentationDescriptor, $tag_IMFPresentationDescriptor)
ConsoleWrite(StringFormat("(%d,0) $oIMFPresentationDescriptor = %s\r\n", @ScriptLineNumber, IsObj($oIMFPresentationDescriptor)) & @CRLF)

; Create an empty topology.
ConsoleWrite(StringFormat("(%d, 0) Create playback topology", @ScriptLineNumber) & @CRLF)
Local $pIMFTopology = _MF_CreateTopology()
Local $oIMFTopology = ObjCreateInterface($pIMFTopology, $sIID_IMFTopology, $tag_IMFTopology)

; Use the presentation descriptor to enumerate the stream descriptors.
Local $iCount
$hResult = $oIMFPresentationDescriptor.GetStreamDescriptorCount($iCount)
ConsoleWrite(StringFormat("(%d,0) Steam Count in media: %d", @ScriptLineNumber, $iCount) & @CRLF)

Local $pIMFStreamDescriptor, $oIMFStreamDescriptor, $bSelect
Local $pSourceNode, $oSourceNode
Local $pOutputNode, $oOutputNode
Local $pIMFMediaTypeHandler, $oIMFMediaTypeHandler
Local $tGUID = __COM_CreateGUID()
Local $pIMFActivate

;For each stream descriptor:
For $i = 0 To $iCount - 1
    ConsoleWrite(StringFormat("\r\n(%d,0) Stream: %d", @ScriptLineNumber, $i) & @CRLF)
    $hResult = $oIMFPresentationDescriptor.GetStreamDescriptorByIndex($i, $bSelect, $pIMFStreamDescriptor)
    $oIMFStreamDescriptor = ObjCreateInterface($pIMFStreamDescriptor, $sIID_IMFStreamDescriptor, $tag_IMFStreamDescriptor)

;~ Get the stream's major media type, such as audio or video.
;~     Check if the stream is currently selected. (Optionally, you can select or deselect a stream, based on the media type.)
;~     If the stream is selected, create an activation object for the media sink, based on the stream's media type.
;~     Add a source node for the stream and an output node for the media sink.
;~     Connect the source node to the output node.

    If $bSelect Then

        $hResult = $oIMFStreamDescriptor.GetMediaTypeHandler($pIMFMediaTypeHandler)
        $oIMFMediaTypeHandler = ObjCreateInterface($pIMFMediaTypeHandler, $sIID_IMFMediaTypeHandler, $tag_IMFMediaTypeHandler)
        $oIMFMediaTypeHandler.GetMajorType($tGUID)

        Select
            Case __COM_CompareGUIDs($tGUID, $MFMediaType_Audio)
                ConsoleWrite(StringFormat("(%d,0) Stream type Audio", @ScriptLineNumber) & @CRLF)
                $pIMFActivate = _MF_CreateAudioRendererActivate()
            Case __COM_CompareGUIDs($tGUID, $MFMediaType_Video)
                ConsoleWrite(StringFormat("(%d,0) Steam Type Video", @ScriptLineNumber) & @CRLF)
                $pIMFActivate = _MF_CreateVideoRendererActivate($hWnd)
            Case Else
                ConsoleWrite(StringFormat("(%d,0) Steam Type: %s", @ScriptLineNumber, __COM_ReadGUIDAt(DllStructGetPtr($tGUID))) & @CRLF)
                ContinueLoop
        EndSelect

        ; Add a source node for this stream. - If Not $hResult Then ... is just for testing. if any thrown an error it will be written to the console.
        $pSourceNode = _MF_CreateTopologyNode($MF_TOPOLOGY_SOURCESTREAM_NODE)
        $oSourceNode = ObjCreateInterface($pSourceNode, $sIID_IMFTopologyNode, $tag_IMFTopologyNode)
        $hResult = $oSourceNode.SetUnknown($MF_TOPONODE_SOURCE, $pMediaSource)
        If Not $hResult Then $hResult = $oSourceNode.SetUnknown($MF_TOPONODE_PRESENTATION_DESCRIPTOR, $pIMFPresentationDescriptor)
        If Not $hResult Then $hResult = $oSourceNode.SetUnknown($MF_TOPONODE_STREAM_DESCRIPTOR, $pIMFStreamDescriptor)
        If Not $hResult Then $hResult = $oIMFTopology.AddNode($pSourceNode)
        ConsoleWrite(StringFormat("(%d,0) Add SrcNode for strm %d, hr = 0x%08x", @ScriptLineNumber, $i, $hResult) & @CRLF)

        ; Create the output node for the renderer.
        $pOutputNode = _MF_CreateTopologyNode($MF_TOPOLOGY_OUTPUT_NODE)
        $oOutputNode = ObjCreateInterface($pOutputNode, $sIID_IMFTopologyNode, $tag_IMFTopologyNode)
        $hResult = $oOutputNode.SetObject($pIMFActivate)
        If Not $hResult Then $hResult = $oIMFTopology.AddNode($pOutputNode)
        If Not $hResult Then $hResult = $oOutputNode.SetUINT32($MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, True)
        ;~      If Not $hResult Then $hResult = $oOutputNode.SetUINT32($MF_TOPONODE_STREAMID, 0)
        ConsoleWrite(StringFormat("(%d,0) Add OutputNode for strm %d, hr = 0x%08x", @ScriptLineNumber, $i, $hResult) & @CRLF)

        ; Connect the source node to the output node.
        $hResult = $oSourceNode.ConnectOutput(0, $pOutputNode, 0)
        ConsoleWrite(StringFormat("(%d,0) Connect Nodes, hr = 0x%08x", @ScriptLineNumber, $hResult) & @CRLF)
  EndIf
Next
$hResult = $oIMFMediaSession.SetTopology($MFSESSION_SETTOPOLOGY_IMMEDIATE, $pIMFTopology) ;MF_E_TOPO_MISSING_SOURCE = C00D521A
ConsoleWrite(StringFormat("\r\n(%d,0) Set Toplology, hr = 0x%08x\r\n", @ScriptLineNumber, $hResult) & @CRLF)

GUISetState(@SW_SHOW, $hWnd)
$tGUID = __COM_CreateGUID()
Local $tVtPropEmpty = DllStructCreate("align 2;ushort vt;word Pad[3]")
DllStructSetData($tVtPropEmpty, "vt", $VT_EMPTY)
$hResult = $oIMFMediaSession.Start($tGUID, $tVtPropEmpty)
ConsoleWrite(StringFormat("(%d,0) Start, hr = 0x%08x", @ScriptLineNumber, $hResult) & @CRLF)

While True
  Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE
      ExitLoop
  EndSwitch
WEnd

$hResult = $oIMFMediaSession.Close()
Sleep(1000)

$hResult = $oIMFMediaSource.Shutdown()
$hResult = $oIMFMediaSession.Shutdown()
_MF_Shutdown()

; ===============================================================

Func __COM_CreateGUID($sGUID = "{00000000-0000-0000-0000-000000000000}", $pAddress = 0)
  Local $tGUID = ($pAddress And IsPtr($pAddress)) ? DllStructCreate($tagGUID, $pAddress) : DllStructCreate($tagGUID)
  Local $aGUID = StringSplit(StringRegExpReplace($sGUID, "[{}]", ""), "-", 2)
  If UBound($aGUID) <> 5 Then Return SetError($ERROR_INVALID_PARAMETER, 0, False)
  DllStructSetData($tGUID, 1, Dec($aGUID[0]))
  DllStructSetData($tGUID, 2, Dec($aGUID[1]))
  DllStructSetData($tGUID, 3, Dec($aGUID[2]))
  DllStructSetData($tGUID, 4, Binary("0x" & $aGUID[3] & $aGUID[4]))
  Return $tGUID
EndFunc   ;==>__COM_CreateGUID

Func __COM_ReadGUIDAt($pGUID)
  Local $tGUID, $sGUID
  If (Not $pGUID) Or (Not IsPtr($pGUID)) Then Return SetError($ERROR_INVALID_PARAMETER, 0, "")
  $tGUID = DllStructCreate($tagGUID, $pGUID)
  $sGUID = StringFormat("{%s-%s-%s-%s-%s}", _
      Hex(DllStructGetData($tGUID, 1), 8), _
      Hex(DllStructGetData($tGUID, 2), 4), _
      Hex(DllStructGetData($tGUID, 3), 4), _
      StringMid(DllStructGetData($tGUID, 4), 3, 4), _
      StringMid(DllStructGetData($tGUID, 4), 7, 12))
  Return $sGUID
EndFunc   ;==>__COM_ReadGUIDAt


Func __COM_CompareGUIDs($tGUID1, $tGUID2)
    If DllStructGetSize($tGUID1) < 16 Then Return SetError($ERROR_INVALID_PARAMETER, 0, False)
    If DllStructGetSize($tGUID2) < 16 Then Return SetError($ERROR_INVALID_PARAMETER, 0, False)
    Local $tBuff1 = DllStructCreate("byte[16]", DllStructGetPtr($tGUID1))
    Local $tBuff2 = DllStructCreate("byte[16]", DllStructGetPtr($tGUID2))
    Return DllStructGetData($tBuff1, 1) =  DllStructGetData($tBuff2, 1)
EndFunc

;Wrapped funcs generally populate @error with hresult.
;So this ensures we have sensible errors if DllCall() fails..
Func __COM_GetDllError($iError = @error)
    Switch $iError
        Case 0
            $iError = $ERROR_SUCCESS
        Case 1
            $iError = $ERROR_DLL_INIT_FAILED
        Case Else
            $iError = $ERROR_INVALID_PARAMETER
    EndSwitch
    Return $iError
EndFunc

Func _MF_CreateMediaSession($pConfig = 0)
    Local $aCall = DllCall("mf.dll", "long", "MFCreateMediaSession", "ptr", $pConfig, "ptr*", 0)
    If @error Then Return SetError(__COM_GetDllError(), 0, 0)
    Return SetError($aCall[0], 0, $aCall[2])
EndFunc

Func _MF_CreateTopology()
    Local $aCall = DllCall("mf.dll", "long", "MFCreateTopology", "ptr*", 0)
    If @error Then Return SetError(__COM_GetDllError(), 0, 0)
    Return SetError($aCall[0], 0, $aCall[1])
EndFunc

Func _MF_CreateTopologyNode($iNodeType)
    Local $aCall = DllCall("mf.dll", "long", "MFCreateTopologyNode", "long", $iNodeType, "ptr*", 0)
    If @error Then Return SetError(__COM_GetDllError(), 0, 0)
    Return SetError($aCall[0], 0, $aCall[2])
EndFunc

Func _MF_CreateAudioRendererActivate()
    Local $aCall = DllCall("mf.dll", "long", "MFCreateAudioRendererActivate", "ptr*", 0)
    If @error Then Return SetError(__COM_GetDllError(), 0, 0)
    Return SetError($aCall[0], 0, $aCall[1])
EndFunc

Func _MF_CreateVideoRendererActivate($hVideo)
    Local $aCall = DllCall("mf.dll", "long", "MFCreateVideoRendererActivate", "hwnd", $hVideo, "ptr*", 0)
    If @error Then Return SetError(__COM_GetDllError(), 0, 0)
    Return SetError($aCall[0], 0, $aCall[2])
EndFunc

Func _MF_Startup($iFlags = $MFSTARTUP_NOSOCKET)
    Local $aCall = DllCall("mfplat.dll", "long", "MFStartup", "ulong", $MF_VERSION, "dword", $iFlags)
    If @error Then Return SetError(__COM_GetDllError(), 0, False)
    Return SetError($aCall[0], 0, $aCall[0] = $S_OK)
EndFunc

Func _MF_Shutdown()
    Local $aCall = DllCall("mfplat.dll", "long", "MFShutdown")
    If @error Then Return SetError(__COM_GetDllError(), 0, False)
    Return SetError($aCall[0], 0, $aCall[0] = $S_OK)
EndFunc

Func _MF_CreateSourceResolver()
    Local $aCall = DllCall("mfplat.dll", "long", "MFCreateSourceResolver", "ptr*", 0)
    If @error Then Return SetError(__COM_GetDllError(), 0, False)
    Return SetError($aCall[0], 0, $aCall[1])
EndFunc
Edited by MattyD
Posted

Downloaded a 4k sample video and played, then an 8k sample video but that did not play.
Could y'all take that resolution in consideration while coding this ( not that I have or use 8k ), if descriptors, or what not ( no clue how any of this works ) that could be needed for such, be included ?. The CPU did not show to be going up as it does when something is playing and may very well be the DLLs that are unable to do the playback.
Other than that "discovery" of mine ( as a curiosity more than anything ), nice. Very nice :) 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Posted

Hey Nine, yeah, the shuffling stuff around was more me catching up to you - i.e. following and figuring out what was supposed to happen.

but looking back at it - this bit seems to be problematic.

$tGUID = __COM_CreateGUID($blah, DllStructGetPtr($tGUID))

I'd say we're releasing memory of the "old" struct when we reassign $tGUID. But we're never actually allocating memory for the "new" struct at the old position because we're specifying a ptr in DllStructCreate,

also a small gremlin. this was being created as $MF_TOPOLOGY_SOURCESTREAM_NODE.

$aCall = DllCall("Mf.dll", "long", "MFCreateTopologyNode", "dword", $MF_TOPOLOGY_OUTPUT_NODE, "ptr*", 0)
 $pOutputNode = $aCall[2]
 $oOutputNode = ObjCreateInterface($pOutputNode, $sIID_IMFTopologyNode, $tag_IMFTopologyNode)

@argumentum - as my niece would say, "you get what you get and you don't get upset" :P. Sorry, I don't have an answer for you at this stage mate, but will let you know if we come across anything!

  • Solution
Posted (edited)

Press space to play/pause in this next example... 

We also get notified when the pause button becomes available/unavailable, so that mechanism should allow us to create basic transport controls easily enough.

Sorry, I've kinda hijacked this thread nine. I'm just playing around a bit now - let me know if you'd like me to focus on anything specific.
Next I was going to see if we can get the video to grow/shrink when sizing the window.

#AutoIt3Wrapper_UseX64=Y ;test both x86/x64

#include <APIErrorsConstants.au3>
#include <StructureConstants.au3>
#include <GUIConstants.au3>
#include <Array.au3>

Opt("MustDeclareVars", True)

Local $sTestFile = @ScriptDir & "\relax.mp4"

#Region Constants

Global Const $S_OK = 0
Global Const $S_FALSE = 1

Global Const $MF_VERSION = 0x00020070 ; 0x00010070 is needed for pre-Win7.
Global Enum $MFSTARTUP_FULL, $MFSTARTUP_LITE, $MFSTARTUP_NOSOCKET = $MFSTARTUP_LITE

Global Const $MF_RESOLUTION_MEDIASOURCE = 1
Global Enum $MF_OBJECT_MEDIASOURCE, $MF_OBJECT_BYTESTREAM, $MF_OBJECT_INVALID

; MF_TOPOLOGY_TYPE
Global Enum $MF_TOPOLOGY_OUTPUT_NODE, _
        $MF_TOPOLOGY_SOURCESTREAM_NODE, _
        $MF_TOPOLOGY_TRANSFORM_NODE, _
        $MF_TOPOLOGY_TEE_NODE, _
        $MF_TOPOLOGY_MAX = 0xffffffff

; MFSESSION_SETTOPOLOGY_FLAGS
Global Enum $MFSESSION_SETTOPOLOGY_IMMEDIATE = 0x1, _
        $MFSESSION_SETTOPOLOGY_NORESOLUTION = 0x2, _
        $MFSESSION_SETTOPOLOGY_CLEAR_CURRENT = 0x4

; _MFCLOCK_STATE
Global Enum $MFCLOCK_STATE_INVALID, _
        $MFCLOCK_STATE_RUNNING, _
        $MFCLOCK_STATE_STOPPED, _
        $MFCLOCK_STATE_PAUSED

Global Const $MF_EVENT_FLAG_NO_WAIT = 0x00000001

;VARTYPE
Global Enum $VT_EMPTY = 0, _
        $VT_NULL = 1, _
        $VT_I2 = 2, _
        $VT_I4 = 3, _
        $VT_R4 = 4, _
        $VT_R8 = 5, _
        $VT_CY = 6, _
        $VT_DATE = 7, _
        $VT_BSTR = 8, _
        $VT_DISPATCH = 9, _
        $VT_ERROR = 10, _
        $VT_BOOL = 11, _
        $VT_VARIANT = 12, _
        $VT_UNKNOWN = 13, _
        $VT_DECIMAL = 14, _
        $VT_I1 = 16, _
        $VT_UI1 = 17, _
        $VT_UI2 = 18, _
        $VT_UI4 = 19, _
        $VT_I8 = 20, _
        $VT_UI8 = 21, _
        $VT_INT = 22, _
        $VT_UINT = 23, _
        $VT_VOID = 24, _
        $VT_HRESULT = 25, _
        $VT_PTR = 26, _
        $VT_SAFEARRAY = 27, _
        $VT_CARRAY = 28, _
        $VT_USERDEFINED = 29, _
        $VT_LPSTR = 30, _
        $VT_LPWSTR = 31, _
        $VT_RECORD = 36, _
        $VT_INT_PTR = 37, _
        $VT_UINT_PTR = 38, _
        $VT_FILETIME = 64, _
        $VT_BLOB = 65, _
        $VT_STREAM = 66, _
        $VT_STORAGE = 67, _
        $VT_STREAMED_OBJECT = 68, _
        $VT_STORED_OBJECT = 69, _
        $VT_BLOB_OBJECT = 70, _
        $VT_CF = 71, _
        $VT_CLSID = 72, _
        $VT_VERSIONED_STREAM = 73, _
        $VT_BSTR_BLOB = 0xfff, _
        $VT_VECTOR = 0x1000, _
        $VT_ARRAY = 0x2000, _
        $VT_BYREF = 0x4000, _
        $VT_RESERVED = 0x8000, _
        $VT_ILLEGAL = 0xffff, _
        $VT_ILLEGALMASKED = 0xfff, _
        $VT_TYPEMASK = 0xfff

;IMediaEvent Codes
Global Enum $MEUnknown = 0, _
        $MEError = 1, _
        $MEExtendedType = 2, _
        $MENonFatalError = 3, _
        $MEGenericV1Anchor = $MENonFatalError, _
        $MESessionUnknown = 100, _
        $MESessionTopologySet = 101, _
        $MESessionTopologiesCleared = 102, _
        $MESessionStarted = 103, _
        $MESessionPaused = 104, _
        $MESessionStopped = 105, _
        $MESessionClosed = 106, _
        $MESessionEnded = 107, _
        $MESessionRateChanged = 108, _
        $MESessionScrubSampleComplete = 109, _
        $MESessionCapabilitiesChanged = 110, _
        $MESessionTopologyStatus = 111, _
        $MESessionNotifyPresentationTime = 112, _
        $MENewPresentation = 113, _
        $MELicenseAcquisitionStart = 114, _
        $MELicenseAcquisitionCompleted = 115, _
        $MEIndividualizationStart = 116, _
        $MEIndividualizationCompleted = 117, _
        $MEEnablerProgress = 118, _
        $MEEnablerCompleted = 119, _
        $MEPolicyError = 120, _
        $MEPolicyReport = 121, _
        $MEBufferingStarted = 122, _
        $MEBufferingStopped = 123, _
        $MEConnectStart = 124, _
        $MEConnectEnd = 125, _
        $MEReconnectStart = 126, _
        $MEReconnectEnd = 127, _
        $MERendererEvent = 128, _
        $MESessionStreamSinkFormatChanged = 129, _
        $MESessionV1Anchor = $MESessionStreamSinkFormatChanged, _
        $MESourceUnknown = 200, _
        $MESourceStarted = 201, _
        $MEStreamStarted = 202, _
        $MESourceSeeked = 203, _
        $MEStreamSeeked = 204, _
        $MENewStream = 205, _
        $MEUpdatedStream = 206, _
        $MESourceStopped = 207, _
        $MEStreamStopped = 208, _
        $MESourcePaused = 209, _
        $MEStreamPaused = 210, _
        $MEEndOfPresentation = 211, _
        $MEEndOfStream = 212, _
        $MEMediaSample = 213, _
        $MEStreamTick = 214, _
        $MEStreamThinMode = 215, _
        $MEStreamFormatChanged = 216, _
        $MESourceRateChanged = 217, _
        $MEEndOfPresentationSegment = 218, _
        $MESourceCharacteristicsChanged = 219, _
        $MESourceRateChangeRequested = 220, _
        $MESourceMetadataChanged = 221, _
        $MESequencerSourceTopologyUpdated = 222, _
        $MESourceV1Anchor = $MESequencerSourceTopologyUpdated, _
        $MESinkUnknown = 300, _
        $MEStreamSinkStarted = 301, _
        $MEStreamSinkStopped = 302, _
        $MEStreamSinkPaused = 303, _
        $MEStreamSinkRateChanged = 304, _
        $MEStreamSinkRequestSample = 305, _
        $MEStreamSinkMarker = 306, _
        $MEStreamSinkPrerolled = 307, _
        $MEStreamSinkScrubSampleComplete = 308, _
        $MEStreamSinkFormatChanged = 309, _
        $MEStreamSinkDeviceChanged = 310, _
        $MEQualityNotify = 311, _
        $MESinkInvalidated = 312, _
        $MEAudioSessionNameChanged = 313, _
        $MEAudioSessionVolumeChanged = 314, _
        $MEAudioSessionDeviceRemoved = 315, _
        $MEAudioSessionServerShutdown = 316, _
        $MEAudioSessionGroupingParamChanged = 317, _
        $MEAudioSessionIconChanged = 318, _
        $MEAudioSessionFormatChanged = 319, _
        $MEAudioSessionDisconnected = 320, _
        $MEAudioSessionExclusiveModeOverride = 321, _
        $MESinkV1Anchor = $MEAudioSessionExclusiveModeOverride, _
        $METrustUnknown = 400, _
        $MEPolicyChanged = 401, _
        $MEContentProtectionMessage = 402, _
        $MEPolicySet = 403, _
        $METrustV1Anchor = $MEPolicySet, _
        $MEWMDRMLicenseBackupCompleted = 500, _
        $MEWMDRMLicenseBackupProgress = 501, _
        $MEWMDRMLicenseRestoreCompleted = 502, _
        $MEWMDRMLicenseRestoreProgress = 503, _
        $MEWMDRMLicenseAcquisitionCompleted = 506, _
        $MEWMDRMIndividualizationCompleted = 508, _
        $MEWMDRMIndividualizationProgress = 513, _
        $MEWMDRMProximityCompleted = 514, _
        $MEWMDRMLicenseStoreCleaned = 515, _
        $MEWMDRMRevocationDownloadCompleted = 516, _
        $MEWMDRMV1Anchor = $MEWMDRMRevocationDownloadCompleted, _
        $MEReservedMax = 10000


Global Const $MFSESSIONCAP_START = 0x00000001
Global Const $MFSESSIONCAP_SEEK = 0x00000002
Global Const $MFSESSIONCAP_PAUSE = 0x00000004
Global Const $MFSESSIONCAP_RATE_FORWARD = 0x00000010
Global Const $MFSESSIONCAP_RATE_REVERSE = 0x00000020


#EndRegion Constants

#Region Interface Defs

Global Const $sIID_IMFAttributes = "{2cd2d921-c447-44a7-a13c-4adabfc247e3}"
Global Const $tag_IMFAttributes = _
        "GetItem hresult(struct*; struct*);" & _
        "GetItemType hresult(struct*; long*);" & _
        "CompareItem hresult(struct*; struct*; bool*);" & _
        "Compare hresult(ptr; long; bool*);" & _
        "GetUINT32 hresult(struct*; uint*);" & _
        "GetUINT64 hresult(struct*; uint64*);" & _
        "GetDouble hresult(struct*; double*);" & _
        "GetGUID hresult(struct*; struct*);" & _
        "GetStringLength hresult(struct*; uint*);" & _
        "GetString hresult(struct*; wstr; uint; uint*);" & _
        "GetAllocatedString hresult(struct*; wstr*; uint*);" & _
        "GetBlobSize hresult(struct*; uint*);" & _
        "GetBlob hresult(struct*; struct*; uint; uint*);" & _
        "GetAllocatedBlob hresult(struct*; ptr*; uint*);" & _
        "GetUnknown hresult(struct*; struct*; ptr*);" & _
        "SetItem hresult(struct*; struct*);" & _
        "DeleteItem hresult(struct*);" & _
        "DeleteAllItems hresult();" & _
        "SetUINT32 hresult(struct*; uint);" & _
        "SetUINT64 hresult(struct*; uint64);" & _
        "SetDouble hresult(struct*; double);" & _
        "SetGUID hresult(struct*; struct*);" & _
        "SetString hresult(struct*; wstr);" & _
        "SetBlob hresult(struct*; struct*; uint);" & _
        "SetUnknown hresult(struct*; ptr);" & _
        "LockStore hresult();" & _
        "UnlockStore hresult();" & _
        "GetCount hresult(uint*);" & _
        "GetItemByIndex hresult(uint; struct*; struct*);" & _
        "CopyAllItems hresult(ptr);"

Global Const $tag_IMFClock = _
        "GetClockCharacteristics hresult(uint*);" & _
        "GetCorrelatedTime hresult(uint; int64*; int64*);" & _
        "GetContinuityKey hresult(uint*);" & _
        "GetState hresult(uint; long*);" & _
        "GetProperties hresult(struct*);"

Global Const $sIID_IMFPresentationClock = "{868CE85C-8EA9-4f55-AB82-B009A910A805}"
Global Const $tag_IMFPresentationClock = _
        $tag_IMFClock & _
        "SetTimeSource hresult(ptr);" & _
        "GetTimeSource hresult(ptr*);" & _
        "GetTime hresult(int64*);" & _
        "AddClockStateSink hresult(ptr);" & _
        "RemoveClockStateSink hresult(ptr);" & _
        "Start hresult(int64);" & _
        "Stop hresult();" & _
        "Pause hresult();"

Global Const $sIID_IMFActivate = "{7FEE9E9A-4A89-47a6-899C-B6A53A70FB67}"
Global Const $tag_IMFActivate = $tag_IMFAttributes & _
        "ActivateObject hresult(struct*; ptr*);" & _
        "ShutdownObject hresult();" & _
        "DetachObject hresult();"

Global Const $sIID_IMFMediaEvent = "{DF598932-F10C-4E39-BBA2-C308F101DAA3}"
Global Const $tag_IMFMediaEvent = $tag_IMFAttributes & _
        "GetType hresult(uint*);" & _
        "GetExtendedType hresult(struct*);" & _
        "GetStatus hresult([*mut HRESULT]);" & _
        "GetValue hresult(struct*);"

Global Const $sIID_IMFMediaEventGenerator = "{2cd0bd52-bcd5-4b89-b62c-eadc0c031e7d}"
Global Const $tag_IMFMediaEventGenerator = _
        "GetEvent hresult(long; ptr*);" & _
        "BeginGetEvent hresult(ptr; ptr);" & _
        "EndGetEvent hresult(ptr; ptr*);" & _
        "QueueEvent hresult(uint; struct*; hresult; struct*);"

Global Const $sIID_IMFMediaSession = "{90377834-21D0-4dee-8214-BA2E3E6C1127}"
Global Const $tag_IMFMediaSession = $tag_IMFMediaEventGenerator & _
        "SetTopology hresult(uint; ptr);" & _
        "ClearTopologies hresult();" & _
        "Start hresult(struct*; struct*);" & _
        "Pause hresult();" & _
        "Stop hresult();" & _
        "Close hresult();" & _
        "Shutdown hresult();" & _
        "GetClock hresult(ptr*);" & _
        "GetSessionCapabilities hresult(uint*);" & _
        "GetFullTopology hresult(uint; uint64; ptr*);"

Global Const $sIID_IMFMediaSource = "{279a808d-aec7-40c8-9c6b-a6b492c78a66}"
Global Const $tag_IMFMediaSource = $tag_IMFMediaEventGenerator & _
        "GetCharacteristics hresult(uint*);" & _
        "CreatePresentationDescriptor hresult(ptr*);" & _
        "Start hresult(ptr; struct*; struct*);" & _
        "Stop hresult();" & _
        "Pause hresult();" & _
        "Shutdown hresult();"

Global Const $sIID_IMFSourceResolver = "{FBE5A32D-A497-4b61-BB85-97B1A848A6E3}"
Global Const $tag_IMFSourceResolver = _
        "CreateObjectFromURL hresult(wstr; uint; ptr; long*; ptr*);" & _
        "CreateObjectFromByteStream hresult(ptr; wstr; uint; ptr; long*; ptr*);" & _
        "BeginCreateObjectFromURL hresult(wstr; uint; ptr; ptr*; ptr; ptr);" & _
        "EndCreateObjectFromURL hresult(ptr; long*; ptr*);" & _
        "BeginCreateObjectFromByteStream hresult(ptr; wstr; uint; ptr; ptr*; ptr; ptr);" & _
        "EndCreateObjectFromByteStream hresult(ptr; long*; ptr*);" & _
        "CancelObjectCreation hresult(ptr);"

Global Const $sIID_IMFPresentationDescriptor = "{03cb2711-24d7-4db6-a17f-f3a7a479a536}"
Global Const $tag_IMFPresentationDescriptor = $tag_IMFAttributes & _
        "GetStreamDescriptorCount hresult(uint*);" & _
        "GetStreamDescriptorByIndex hresult(uint; bool*; ptr*);" & _
        "SelectStream hresult(uint);" & _
        "DeselectStream hresult(uint);" & _
        "Clone hresult(ptr*);"

Global Const $sIID_IMFTopologyNode = "{83cf873a-f6da-4bc8-823f-bacfd55dc430}"
Global Const $tag_IMFTopologyNode = $tag_IMFAttributes & _
        "SetObject hresult(ptr);" & _
        "GetObject hresult(ptr*);" & _
        "GetNodeType hresult(long*);" & _
        "GetTopoNodeID hresult(uint64*);" & _
        "SetTopoNodeID hresult(uint64);" & _
        "GetInputCount hresult(uint*);" & _
        "GetOutputCount hresult(uint*);" & _
        "ConnectOutput hresult(uint; ptr; uint);" & _
        "DisconnectOutput hresult(uint);" & _
        "GetInput hresult(uint; ptr*; uint*);" & _
        "GetOutput hresult(uint; ptr*; uint*);" & _
        "SetOutputPrefType hresult(uint; ptr);" & _
        "GetOutputPrefType hresult(uint; ptr*);" & _
        "SetInputPrefType hresult(uint; ptr);" & _
        "GetInputPrefType hresult(uint; ptr*);" & _
        "CloneFrom hresult(ptr);"

Global Const $sIID_IMFTopology = "{83cf873a-f6da-4bc8-823f-bacfd55dc433}"
Global Const $tag_IMFTopology = $tag_IMFAttributes & _
        "GetTopologyID hresult(uint64*);" & _
        "AddNode hresult(ptr);" & _
        "RemoveNode hresult(ptr);" & _
        "GetNodeCount hresult(short*);" & _
        "GetNode hresult(short; ptr*);" & _
        "Clear hresult();" & _
        "CloneFrom hresult(ptr);" & _
        "GetNodeByID hresult(uint64; ptr*);" & _
        "GetSourceNodeCollection hresult(ptr*);" & _
        "GetOutputNodeCollection hresult(ptr*);"

Global Const $sIID_IMFStreamDescriptor = "{56c03d9c-9dbb-45f5-ab4b-d80f47c05938}"
Global Const $tag_IMFStreamDescriptor = $tag_IMFAttributes & _
        "GetStreamIdentifier hresult(uint*);" & _
        "GetMediaTypeHandler hresult(ptr*);"

Global Const $sIID_IMFMediaTypeHandler = "{e93dcf6c-4b07-4e1e-8123-aa16ed6eadf5}"
Global Const $tag_IMFMediaTypeHandler = _
        "IsMediaTypeSupported hresult(ptr; ptr*);" & _
        "GetMediaTypeCount hresult(uint*);" & _
        "GetMediaTypeByIndex hresult(uint; ptr*);" & _
        "SetCurrentMediaType hresult(ptr);" & _
        "GetCurrentMediaType hresult(ptr*);" & _
        "GetMajorType hresult(struct*);"

#EndRegion Interface Defs

#Region GUIDs

Global Const $MF_TOPONODE_ERRORCODE = __COM_CreateGUID("{494bbcee-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_CONNECT_METHOD = __COM_CreateGUID("{494bbcf1-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_LOCKED = __COM_CreateGUID("{494bbcf7-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_WORKQUEUE_ID = __COM_CreateGUID("{494bbcf8-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_WORKQUEUE_MMCSS_CLASS = __COM_CreateGUID("{494bbcf9-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_DECRYPTOR = __COM_CreateGUID("{494bbcfa-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_DISCARDABLE = __COM_CreateGUID("{494bbcfb-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_ERROR_MAJORTYPE = __COM_CreateGUID("{494bbcfd-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_ERROR_SUBTYPE = __COM_CreateGUID("{494bbcfe-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_WORKQUEUE_MMCSS_TASKID = __COM_CreateGUID("{494bbcff-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_MARKIN_HERE = __COM_CreateGUID("{494bbd00-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_MARKOUT_HERE = __COM_CreateGUID("{494bbd01-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_DECODER = __COM_CreateGUID("{494bbd02-b031-4e38-97c4-d5422dd618dc}")
Global Const $MF_TOPONODE_MEDIASTART = __COM_CreateGUID("{835c58ea-e075-4bc7-bcba-4de000df9ae6}")
Global Const $MF_TOPONODE_MEDIASTOP = __COM_CreateGUID("{835c58eb-e075-4bc7-bcba-4de000df9ae6}")
Global Const $MF_TOPONODE_SOURCE = __COM_CreateGUID("{835c58ec-e075-4bc7-bcba-4de000df9ae6}")
Global Const $MF_TOPONODE_PRESENTATION_DESCRIPTOR = __COM_CreateGUID("{835c58ed-e075-4bc7-bcba-4de000df9ae6}")
Global Const $MF_TOPONODE_STREAM_DESCRIPTOR = __COM_CreateGUID("{835c58ee-e075-4bc7-bcba-4de000df9ae6}")
Global Const $MF_TOPONODE_SEQUENCE_ELEMENTID = __COM_CreateGUID("{835c58ef-e075-4bc7-bcba-4de000df9ae6}")
Global Const $MF_TOPONODE_TRANSFORM_OBJECTID = __COM_CreateGUID("{88dcc0c9-293e-4e8b-9aeb-0ad64cc016b0}")
Global Const $MF_TOPONODE_STREAMID = __COM_CreateGUID("{14932f9b-9087-4bb4-8412-5167145cbe04}")
Global Const $MF_TOPONODE_NOSHUTDOWN_ON_REMOVE = __COM_CreateGUID("{14932f9c-9087-4bb4-8412-5167145cbe04}")
Global Const $MF_TOPONODE_RATELESS = __COM_CreateGUID("{14932f9d-9087-4bb4-8412-5167145cbe04}")
Global Const $MF_TOPONODE_DISABLE_PREROLL = __COM_CreateGUID("{14932f9e-9087-4bb4-8412-5167145cbe04}")
Global Const $MF_TOPONODE_PRIMARYOUTPUT = __COM_CreateGUID("{6304ef99-16b2-4ebe-9d67-e4c539b3a259}")

Global Const $MFMediaType_Audio = __COM_CreateGUID("{73647561-0000-0010-8000-00aa00389b71}")
Global Const $MFMediaType_Binary = __COM_CreateGUID("{72178c25-e45b-11d5-bc2a-00b0d0f3f4ab}")
Global Const $MFMediaType_Default = __COM_CreateGUID("{81a412e6-8103-4b06-857f-1862781024ac}")
Global Const $MFMediaType_FileTransfer = __COM_CreateGUID("{72178c26-e45b-11d5-bc2a-00b0d0f3f4ab}")
Global Const $MFMediaType_HTML = __COM_CreateGUID("{72178c24-e45b-11d5-bc2a-00b0d0f3f4ab}")
Global Const $MFMediaType_Image = __COM_CreateGUID("{72178c23-e45b-11d5-bc2a-00b0d0f3f4ab}")
Global Const $MFMediaType_MultiplexedFrames = __COM_CreateGUID("{6ea542b0-281f-4231-a464-fe2f5022501c}")
Global Const $MFMediaType_Perception = __COM_CreateGUID("{597ff6f9-6ea2-4670-85b4-ea84073fe940}")
Global Const $MFMediaType_Protected = __COM_CreateGUID("{7b4b6fe6-9d04-4494-be14-7e0bd076c8e4}")
Global Const $MFMediaType_SAMI = __COM_CreateGUID("{e69669a0-3dcd-40cb-9e2e-3708387c0616}")
Global Const $MFMediaType_Script = __COM_CreateGUID("{72178c22-e45b-11d5-bc2a-00b0d0f3f4ab}")
Global Const $MFMediaType_Stream = __COM_CreateGUID("{e436eb83-524f-11ce-9f53-0020af0ba770}")
Global Const $MFMediaType_Subtitle = __COM_CreateGUID("{a6d13581-ed50-4e65-ae08-26065576aacc}")
Global Const $MFMediaType_Video = __COM_CreateGUID("{73646976-0000-0010-8000-00aa00389b71}")

Global Const $MF_EVENT_DO_THINNING = __COM_CreateGUID("{321ea6fb-dad9-46e4-b31d-d2eae7090e30}")
Global Const $MF_EVENT_MFT_CONTEXT = __COM_CreateGUID("{b7cd31f1-899e-4b41-80c9-26a896d32977}")
Global Const $MF_EVENT_MFT_INPUT_STREAM_ID = __COM_CreateGUID("{f29c2cca-7ae6-42d2-b284-bf837cc874e2}")
Global Const $MF_EVENT_PRESENTATION_TIME_OFFSET = __COM_CreateGUID("{5ad914d1-9b45-4a8d-a2c0-81d1e50bfb07}")
Global Const $MF_EVENT_SCRUBSAMPLE_TIME = __COM_CreateGUID("{9ac712b3-dcb8-44d5-8d0c-37455a2782e3}")
Global Const $MF_EVENT_SESSIONCAPS = __COM_CreateGUID("{7e5ebcd0-11b8-4abe-afad-10f6599a7f42}")
Global Const $MF_EVENT_SESSIONCAPS_DELTA = __COM_CreateGUID("{7e5ebcd1-11b8-4abe-afad-10f6599a7f42}")
Global Const $MF_EVENT_SOURCE_ACTUAL_START = __COM_CreateGUID("{a8cc55a9-6b31-419f-845d-ffb351a2434b}")
Global Const $MF_EVENT_SOURCE_CHARACTERISTICS = __COM_CreateGUID("{47db8490-8b22-4f52-afda-9ce1b2d3cfa8}")
Global Const $MF_EVENT_SOURCE_CHARACTERISTICS_OLD = __COM_CreateGUID("{47db8491-8b22-4f52-afda-9ce1b2d3cfa8}")
Global Const $MF_EVENT_SOURCE_FAKE_START = __COM_CreateGUID("{a8cc55a7-6b31-419f-845d-ffb351a2434b}")
Global Const $MF_EVENT_SOURCE_PROJECTSTART = __COM_CreateGUID("{a8cc55a8-6b31-419f-845d-ffb351a2434b}")
Global Const $MF_EVENT_SOURCE_TOPOLOGY_CANCELED = __COM_CreateGUID("{db62f650-9a5e-4704-acf3-563bc6a73364}")
Global Const $MF_EVENT_START_PRESENTATION_TIME = __COM_CreateGUID("{5ad914d0-9b45-4a8d-a2c0-81d1e50bfb07}")
Global Const $MF_EVENT_START_PRESENTATION_TIME_AT_OUTPUT = __COM_CreateGUID("{5ad914d2-9b45-4a8d-a2c0-81d1e50bfb07}")
Global Const $MF_EVENT_STREAM_METADATA_CONTENT_KEYIDS = __COM_CreateGUID("{5063449d-cc29-4fc6-a75a-d247b35af85c}")
Global Const $MF_EVENT_STREAM_METADATA_KEYDATA = __COM_CreateGUID("{cd59a4a1-4a3b-4bbd-8665-72a40fbea776}")
Global Const $MF_EVENT_STREAM_METADATA_SYSTEMID = __COM_CreateGUID("{1ea2ef64-ba16-4a36-8719-fe7560ba32ad}")
Global Const $MF_EVENT_TOPOLOGY_STATUS = __COM_CreateGUID("{30c5018d-9a53-454b-ad9e-6d5f8fa7c43b}")
Global Const $MF_EVENT_OUTPUT_NODE = __COM_CreateGUID("{830f1a8b-c060-46dd-a801-1c95dec9b107}")

#EndRegion GUIDs

#Region

Local $hResult
Local $hWnd = GUICreate("Basic Playback", 800, 600, -1, -1, $WS_OVERLAPPEDWINDOW)

_MF_Startup()

;Start Session
ConsoleWrite(StringFormat("(%d,0) Start Session", @ScriptLineNumber) & @CRLF)
Local $pIMFMediaSession = _MF_CreateMediaSession()
Local $oIMFMediaSession = ObjCreateInterface($pIMFMediaSession, $sIID_IMFMediaSession, $tag_IMFMediaSession)
ConsoleWrite(StringFormat("(%d,0) $oIMFMediaSession = %s\r\n", @ScriptLineNumber, IsObj($oIMFMediaSession)) & @CRLF)

;Create the media source (using source resolver).
ConsoleWrite(StringFormat("(%d,0) Load Source", @ScriptLineNumber) & @CRLF)
Local $pIMFSourceResolver = _MF_CreateSourceResolver()
Local $oIMFSourceResolver = ObjCreateInterface($pIMFSourceResolver, $sIID_IMFSourceResolver, $tag_IMFSourceResolver)
Local $iObjType, $pMediaSource ;OUT Params
$hResult = $oIMFSourceResolver.CreateObjectFromURL($sTestFile, $MF_RESOLUTION_MEDIASOURCE, 0, $iObjType, $pMediaSource)
Local $oIMFMediaSource = ObjCreateInterface($pMediaSource, $sIID_IMFMediaSource, $tag_IMFMediaSource)

;Get the media source's presentation descriptor.
Local $pIMFPresentationDescriptor
$hResult = $oIMFMediaSource.CreatePresentationDescriptor($pIMFPresentationDescriptor)
Local $oIMFPresentationDescriptor = ObjCreateInterface($pIMFPresentationDescriptor, $sIID_IMFPresentationDescriptor, $tag_IMFPresentationDescriptor)
ConsoleWrite(StringFormat("(%d,0) $oIMFPresentationDescriptor = %s\r\n", @ScriptLineNumber, IsObj($oIMFPresentationDescriptor)) & @CRLF)

; Create an empty topology.
ConsoleWrite(StringFormat("(%d,0) Create playback topology", @ScriptLineNumber) & @CRLF)
Local $pIMFTopology = _MF_CreateTopology()
Local $oIMFTopology = ObjCreateInterface($pIMFTopology, $sIID_IMFTopology, $tag_IMFTopology)

; Use the presentation descriptor to enumerate the stream descriptors.
Local $iCount
$hResult = $oIMFPresentationDescriptor.GetStreamDescriptorCount($iCount)
ConsoleWrite(StringFormat("(%d,0) Steam Count in media: %d", @ScriptLineNumber, $iCount) & @CRLF)

Local $pIMFStreamDescriptor, $oIMFStreamDescriptor, $bSelect
Local $pSourceNode, $oSourceNode
Local $pOutputNode, $oOutputNode
Local $pIMFMediaTypeHandler, $oIMFMediaTypeHandler
Local $tGUID = __COM_CreateGUID()
Local $pIMFActivate, $oIMFActivate

;For each stream descriptor:
For $i = 0 To $iCount - 1
    ConsoleWrite(StringFormat("\r\n(%d,0) Stream: %d", @ScriptLineNumber, $i) & @CRLF)
    $hResult = $oIMFPresentationDescriptor.GetStreamDescriptorByIndex($i, $bSelect, $pIMFStreamDescriptor)
    $oIMFStreamDescriptor = ObjCreateInterface($pIMFStreamDescriptor, $sIID_IMFStreamDescriptor, $tag_IMFStreamDescriptor)

;~ Get the stream's major media type, such as audio or video.
;~     Check if the stream is currently selected. (Optionally, you can select or deselect a stream, based on the media type.)
;~     If the stream is selected, create an activation object for the media sink, based on the stream's media type.
;~     Add a source node for the stream and an output node for the media sink.
;~     Connect the source node to the output node.

    If $bSelect Then

        $hResult = $oIMFStreamDescriptor.GetMediaTypeHandler($pIMFMediaTypeHandler)
        $oIMFMediaTypeHandler = ObjCreateInterface($pIMFMediaTypeHandler, $sIID_IMFMediaTypeHandler, $tag_IMFMediaTypeHandler)
        $oIMFMediaTypeHandler.GetMajorType($tGUID)

        Select
            Case __COM_CompareGUIDs($tGUID, $MFMediaType_Audio)
                ConsoleWrite(StringFormat("(%d,0) Stream type Audio", @ScriptLineNumber) & @CRLF)
                $pIMFActivate = _MF_CreateAudioRendererActivate()
            Case __COM_CompareGUIDs($tGUID, $MFMediaType_Video)
                ConsoleWrite(StringFormat("(%d,0) Steam Type Video", @ScriptLineNumber) & @CRLF)
                $pIMFActivate = _MF_CreateVideoRendererActivate($hWnd)
            Case Else
                ConsoleWrite(StringFormat("(%d,0) Steam Type: %s", @ScriptLineNumber, __COM_ReadGUIDAt(DllStructGetPtr($tGUID))) & @CRLF)
                ContinueLoop
        EndSelect

        ; Add a source node for this stream. - If Not $hResult Then ... is just for testing. if any thrown an error it will be written to the console.
        $pSourceNode = _MF_CreateTopologyNode($MF_TOPOLOGY_SOURCESTREAM_NODE)
        $oSourceNode = ObjCreateInterface($pSourceNode, $sIID_IMFTopologyNode, $tag_IMFTopologyNode)
        $hResult = $oSourceNode.SetUnknown($MF_TOPONODE_SOURCE, $pMediaSource)
        If Not $hResult Then $hResult = $oSourceNode.SetUnknown($MF_TOPONODE_PRESENTATION_DESCRIPTOR, $pIMFPresentationDescriptor)
        If Not $hResult Then $hResult = $oSourceNode.SetUnknown($MF_TOPONODE_STREAM_DESCRIPTOR, $pIMFStreamDescriptor)
        If Not $hResult Then $hResult = $oIMFTopology.AddNode($pSourceNode)
        ConsoleWrite(StringFormat("(%d,0) Add SrcNode for strm %d, hr = 0x%08x", @ScriptLineNumber, $i, $hResult) & @CRLF)

        ; Create the output node for the renderer.
        $pOutputNode = _MF_CreateTopologyNode($MF_TOPOLOGY_OUTPUT_NODE)
        $oOutputNode = ObjCreateInterface($pOutputNode, $sIID_IMFTopologyNode, $tag_IMFTopologyNode)
        $hResult = $oOutputNode.SetObject($pIMFActivate)
        If Not $hResult Then $hResult = $oIMFTopology.AddNode($pOutputNode)
        If Not $hResult Then $hResult = $oOutputNode.SetUINT32($MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, True)
        ConsoleWrite(StringFormat("(%d,0) Add OutputNode for strm %d, hr = 0x%08x", @ScriptLineNumber, $i, $hResult) & @CRLF)

        ; Connect the source node to the output node.
        $hResult = $oSourceNode.ConnectOutput(0, $pOutputNode, 0)
        ConsoleWrite(StringFormat("(%d,0) Connect Nodes, hr = 0x%08x", @ScriptLineNumber, $hResult) & @CRLF)

    EndIf
Next

$hResult = $oIMFMediaSession.SetTopology($MFSESSION_SETTOPOLOGY_IMMEDIATE, $pIMFTopology) ;MF_E_TOPO_MISSING_SOURCE = C00D521A
ConsoleWrite(StringFormat("\r\n(%d,0) Set Toplology, hr = 0x%08x\r\n", @ScriptLineNumber, $hResult) & @CRLF)
;~ $oIMFTopology.Release()


GUISetState(@SW_SHOW, $hWnd)
$tGUID = __COM_CreateGUID()
Local $tVtPropEmpty = DllStructCreate("align 2;ushort vt;word Pad[3]")
DllStructSetData($tVtPropEmpty, "vt", $VT_EMPTY)
$hResult = $oIMFMediaSession.Start($tGUID, $tVtPropEmpty)
ConsoleWrite(StringFormat("(%d,0) Start, hr = 0x%08x", @ScriptLineNumber, $hResult) & @CRLF)

Local $iSessCaps, $iSessCapsDelta

Local $pEvent, $oEvent, $iEvtType
Local $hTimer = TimerInit()
Local $iTime, $iHour, $iMin, $iSec
Local $pClock, $oClock, $iClockState
$oIMFMediaSession.GetClock($pClock)
$oClock = ObjCreateInterface($pClock, $sIID_IMFPresentationClock, $tag_IMFPresentationClock)

Local $idPlayPause = GUICtrlCreateDummy()
Local $aAccelKeys[1][2] = [[" ", $idPlayPause]]
GUISetAccelerators($aAccelKeys)


While True
    $hResult = $oIMFMediaSession.GetEvent($MF_EVENT_FLAG_NO_WAIT, $pEvent)
    If $hResult = $S_OK Then
        $oEvent = ObjCreateInterface($pEvent, $sIID_IMFMediaEvent, $tag_IMFMediaEvent)
        $oEvent.GetType($iEvtType)

        Switch $iEvtType
            Case $MESessionStarted
                ConsoleWrite(StringFormat("(%d,0) Event Type: %d, %s", @ScriptLineNumber, $iEvtType, "Session Started.") & @CRLF)

            Case $MESessionPaused
                ConsoleWrite(StringFormat("(%d,0) Event Type: %d, %s", @ScriptLineNumber, $iEvtType, "Session Paused.") & @CRLF)

            Case $MESessionCapabilitiesChanged
                ConsoleWrite(StringFormat("(%d,0) Event Type: %d, %s", @ScriptLineNumber, $iEvtType, "Capabilities Changed.") & @CRLF)
                $oEvent.GetUINT32($MF_EVENT_SESSIONCAPS, $iSessCaps)
                $oEvent.GetUINT32($MF_EVENT_SESSIONCAPS_DELTA, $iSessCapsDelta)
                ConsoleWrite(StringFormat("(%d,0) Caps: %08x CapsDelta: %08x", @ScriptLineNumber, $iSessCaps, $iSessCapsDelta) & @CRLF)

                If BitAND($iSessCapsDelta, $MFSESSIONCAP_START) Then _
                        ConsoleWrite(StringFormat("(%d,0) Can Start = %s\r\n", @ScriptLineNumber, _
                        BitAND($iSessCaps, $MFSESSIONCAP_START) = $MFSESSIONCAP_START))

                If BitAND($iSessCapsDelta, $MFSESSIONCAP_SEEK) Then _
                        ConsoleWrite(StringFormat("(%d,0) Can Seek = %s\r\n", @ScriptLineNumber, _
                        BitAND($iSessCaps, $MFSESSIONCAP_SEEK) = $MFSESSIONCAP_SEEK))

                If BitAND($iSessCapsDelta, $MFSESSIONCAP_PAUSE) Then _
                        ConsoleWrite(StringFormat("(%d,0) Can Pause = %s\r\n", @ScriptLineNumber, _
                        BitAND($iSessCaps, $MFSESSIONCAP_PAUSE) = $MFSESSIONCAP_PAUSE))

                If BitAND($iSessCapsDelta, $MFSESSIONCAP_RATE_FORWARD) Then _
                        ConsoleWrite(StringFormat("(%d,0) Can Forward = %s\r\n", @ScriptLineNumber, _
                        BitAND($iSessCaps, $MFSESSIONCAP_RATE_FORWARD) = $MFSESSIONCAP_RATE_FORWARD))

                If BitAND($iSessCapsDelta, $MFSESSIONCAP_RATE_REVERSE) Then _
                        ConsoleWrite(StringFormat("(%d,0) Can Reverse = %s\r\n", @ScriptLineNumber, _
                        BitAND($iSessCaps, $MFSESSIONCAP_RATE_REVERSE) = $MFSESSIONCAP_RATE_REVERSE))


            Case Else
                ConsoleWrite(StringFormat("(%d,0) Event Type: %d", @ScriptLineNumber, $iEvtType) & @CRLF)
        EndSwitch
    EndIf

    If TimerDiff($hTimer) >= 1000 Then ; Ticker
        $oClock.GetState(0, $iClockState)
        $oClock.GetTime($iTime) ;seconds (100 ns units.)

        $iSec = Mod(Round($iTime / 10000000), 60)
        $iMin = Mod(Floor($iTime / 600000000), 60)
        $iHour = Floor($iTime / 36000000000)
        If $iClockState =  $MFCLOCK_STATE_RUNNING Then ConsoleWrite(StringFormat("> Clock: %d:%02d:%02d", $iHour, $iMin, $iSec) & @CRLF)

        $hTimer = TimerInit()
    EndIf

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop

        Case $idPlayPause
            $oClock.GetState(0, $iClockState)
            Switch $iClockState

                Case $MFCLOCK_STATE_PAUSED
                    $oIMFMediaSession.Start($tGUID, $tVtPropEmpty)

                Case $MFCLOCK_STATE_RUNNING
                    $oIMFMediaSession.Pause()
            EndSwitch

    EndSwitch
WEnd

ConsoleWrite(StringFormat("\r\n(%d,0) Shutdown, hr = 0x%08x", @ScriptLineNumber, $hResult) & @CRLF)
$hResult = $oIMFMediaSession.Close()
$hResult = $oIMFMediaSource.Shutdown()
$hResult = $oIMFMediaSession.Shutdown()
_MF_Shutdown()

#EndRegion


#Region Funcs

;Might replace this func with  _WinAPI_GUIDFromString()
Func __COM_CreateGUID($sGUID = "{00000000-0000-0000-0000-000000000000}", $pAddress = 0)
    Local $tGUID = ($pAddress And IsPtr($pAddress)) ? DllStructCreate($tagGUID, $pAddress) : DllStructCreate($tagGUID)
    Local $aGUID = StringSplit(StringRegExpReplace($sGUID, "[{}]", ""), "-", 2)
    If UBound($aGUID) <> 5 Then Return SetError($ERROR_INVALID_PARAMETER, 0, False)
    DllStructSetData($tGUID, 1, Dec($aGUID[0]))
    DllStructSetData($tGUID, 2, Dec($aGUID[1]))
    DllStructSetData($tGUID, 3, Dec($aGUID[2]))
    DllStructSetData($tGUID, 4, Binary("0x" & $aGUID[3] & $aGUID[4]))
    Return $tGUID
EndFunc   ;==>__COM_CreateGUID

Func __COM_ReadGUIDAt($pGUID)
    Local $tGUID, $sGUID
    If (Not $pGUID) Or (Not IsPtr($pGUID)) Then Return SetError($ERROR_INVALID_PARAMETER, 0, "")
    $tGUID = DllStructCreate($tagGUID, $pGUID)
    $sGUID = StringFormat("{%s-%s-%s-%s-%s}", _
            Hex(DllStructGetData($tGUID, 1), 8), _
            Hex(DllStructGetData($tGUID, 2), 4), _
            Hex(DllStructGetData($tGUID, 3), 4), _
            StringMid(DllStructGetData($tGUID, 4), 3, 4), _
            StringMid(DllStructGetData($tGUID, 4), 7, 12))
    Return $sGUID
EndFunc   ;==>__COM_ReadGUIDAt

Func __COM_CompareGUIDs($tGUID1, $tGUID2)
    If DllStructGetSize($tGUID1) < 16 Then Return SetError($ERROR_INVALID_PARAMETER, 0, False)
    If DllStructGetSize($tGUID2) < 16 Then Return SetError($ERROR_INVALID_PARAMETER, 0, False)
    Local $tBuff1 = DllStructCreate("byte[16]", DllStructGetPtr($tGUID1))
    Local $tBuff2 = DllStructCreate("byte[16]", DllStructGetPtr($tGUID2))
    Return DllStructGetData($tBuff1, 1) = DllStructGetData($tBuff2, 1)
EndFunc   ;==>__COM_CompareGUIDs

;Wrapped funcs generally populate @error with hresult.
;So this ensures we have sensible errors if DllCall() fails..
Func __COM_GetDllError($iError = @error)
    Switch $iError
        Case 0
            $iError = $ERROR_SUCCESS
        Case 1
            $iError = $ERROR_DLL_INIT_FAILED
        Case Else
            $iError = $ERROR_INVALID_PARAMETER
    EndSwitch
    Return $iError
EndFunc   ;==>__COM_GetDllError

Func _MF_CreateMediaSession($pConfig = 0)
    Local $aCall = DllCall("mf.dll", "long", "MFCreateMediaSession", "ptr", $pConfig, "ptr*", 0)
    If @error Then Return SetError(__COM_GetDllError(), 0, 0)
    Return SetError($aCall[0], 0, $aCall[2])
EndFunc   ;==>_MF_CreateMediaSession

Func _MF_CreateTopology()
    Local $aCall = DllCall("mf.dll", "long", "MFCreateTopology", "ptr*", 0)
    If @error Then Return SetError(__COM_GetDllError(), 0, 0)
    Return SetError($aCall[0], 0, $aCall[1])
EndFunc   ;==>_MF_CreateTopology

Func _MF_CreateTopologyNode($iNodeType)
    Local $aCall = DllCall("mf.dll", "long", "MFCreateTopologyNode", "long", $iNodeType, "ptr*", 0)
    If @error Then Return SetError(__COM_GetDllError(), 0, 0)
    Return SetError($aCall[0], 0, $aCall[2])
EndFunc   ;==>_MF_CreateTopologyNode

Func _MF_CreateAudioRendererActivate()
    Local $aCall = DllCall("mf.dll", "long", "MFCreateAudioRendererActivate", "ptr*", 0)
    If @error Then Return SetError(__COM_GetDllError(), 0, 0)
    Return SetError($aCall[0], 0, $aCall[1])
EndFunc   ;==>_MF_CreateAudioRendererActivate

Func _MF_CreateVideoRendererActivate($hVideo)
    Local $aCall = DllCall("mf.dll", "long", "MFCreateVideoRendererActivate", "hwnd", $hVideo, "ptr*", 0)
    If @error Then Return SetError(__COM_GetDllError(), 0, 0)
    Return SetError($aCall[0], 0, $aCall[2])
EndFunc   ;==>_MF_CreateVideoRendererActivate

Func _MF_Startup($iFlags = $MFSTARTUP_NOSOCKET)
    Local $aCall = DllCall("mfplat.dll", "long", "MFStartup", "ulong", $MF_VERSION, "dword", $iFlags)
    If @error Then Return SetError(__COM_GetDllError(), 0, False)
    Return SetError($aCall[0], 0, $aCall[0] = $S_OK)
EndFunc   ;==>_MF_Startup

Func _MF_Shutdown()
    Local $aCall = DllCall("mfplat.dll", "long", "MFShutdown")
    If @error Then Return SetError(__COM_GetDllError(), 0, False)
    Return SetError($aCall[0], 0, $aCall[0] = $S_OK)
EndFunc   ;==>_MF_Shutdown

Func _MF_CreateSourceResolver()
    Local $aCall = DllCall("mfplat.dll", "long", "MFCreateSourceResolver", "ptr*", 0)
    If @error Then Return SetError(__COM_GetDllError(), 0, False)
    Return SetError($aCall[0], 0, $aCall[1])
EndFunc   ;==>_MF_CreateSourceResolver

#EndRegion Funcs
Edited by MattyD
Posted
17 hours ago, MattyD said:

this bit seems to be problematic ....

also a small gremlin

Thanks for help.  Modifying accordingly made my code works.  Learning is a fascinating thing.

8 hours ago, MattyD said:

Sorry, I've kinda hijacked this thread nine

Don't be.   This is why I created in the collaboration section.  It was fun playing with this foundation.  I am very happy with the result of this thread.  Good work on it.

I will update my OP code but refer to your last script as the solution.

Next, I will take a look at the capture part of the foundation.  If I come up with something I'll post here also.  See ya around :)

Posted

@Nine and @MattyD, Thank you for your work on the Media Foundation. I'm sorry I can't help you, but I really hope you're successful. The new Media Player that comes with Windows 11 plays a 4k video file just fine. But when I play it with Windows Media Player Legacy, the audio is fine, but the video often stutters. The result of my test of your preliminary code is similar to Windows Media Player Legacy, and I hope you will address this issue as the project progresses.

Posted

Ok, that's good to know. 

I was doing some more reading last night, and it seems this example uses a legacy component for the renderer - the EVR (Enhanced Video Renderer) .
Apparently we're now supposed to use IMediaEngine, which exposes a Simple Video Renderer (SVR).  So that seems to be a whole different thing. God knows why MS is so intent on reinventing the wheel with these apis! https://learn.microsoft.com/en-us/windows/win32/medfound/enhanced-video-renderer

I'll leave it up to @Nine as to the scope of this thread. Considering we sortof have something working here with MediaSession- maybe we should start a new thread for MediaEngine. No doubt Nine will have something to share around media capture at some point too!

Posted

I think it is best for you to start a new thread.  Knowing that it is a legacy engine, not sure I will continue in this path.  Unless someone wants to add content to the current state of the code, I would consider the thread closed.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...