Jump to content

Recommended Posts

Posted (edited)

This is a spin off the thread from here.

I've moved this out of the collab space so I don't feel guilty about making sweeping changes when the mood hits me.  But I'm still more than happy for this to be a community project at heart.

Just a quick comment about the code: for this API, it looks like we need to construct some objects internally, which is a bit of a learning curve - but hopefully this example will provide a bit of background as to whats happening there...

anyway this is where I've left things for tonight:

#AutoIt3Wrapper_UseX64=N ;test both x86/x64

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

Opt("MustDeclareVars", True)

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

#Region Constants

;~ Global Const $S_OK = 0 ;already decalred via winapi.au3
Global Const $S_FALSE = 1
;~ Global Const $E_NOINTERFACE = 0x80004002 ;already decalred via winapi.au3

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

Global Const $sCLSID_MFMediaEngineClassFactory = "{B44392DA-499B-446b-A4CB-005FEAD0E6D5}"


;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

; _MF_ATTRIBUTE_TYPE
Global Enum $MF_ATTRIBUTE_UINT32 = $VT_UI4, _
        $MF_ATTRIBUTE_UINT64 = $VT_UI8, _
        $MF_ATTRIBUTE_DOUBLE = $VT_R8, _
        $MF_ATTRIBUTE_GUID = $VT_CLSID, _
        $MF_ATTRIBUTE_STRING = $VT_LPWSTR, _
        $MF_ATTRIBUTE_BLOB = BitOR($VT_VECTOR, $VT_UI1), _
        $MF_ATTRIBUTE_IUNKNOWN = $VT_UNKNOWN

; MF_MEDIA_ENGINE_NETWORK
Global Enum $MF_MEDIA_ENGINE_NETWORK_EMPTY, _
        $MF_MEDIA_ENGINE_NETWORK_IDLE, _
        $MF_MEDIA_ENGINE_NETWORK_LOADING, _
        $MF_MEDIA_ENGINE_NETWORK_NO_SOURCE

; MF_MEDIA_ENGINE_ERR
Global Enum $MF_MEDIA_ENGINE_ERR_NOERROR, _
        $MF_MEDIA_ENGINE_ERR_ABORTED, _
        $MF_MEDIA_ENGINE_ERR_NETWORK, _
        $MF_MEDIA_ENGINE_ERR_DECODE, _
        $MF_MEDIA_ENGINE_ERR_SRC_NOT_SUPPORTED, _
        $MF_MEDIA_ENGINE_ERR_ENCRYPTED

; MF_MEDIA_ENGINE_PRELOAD
Global Enum $MF_MEDIA_ENGINE_PRELOAD_MISSING, _
        $MF_MEDIA_ENGINE_PRELOAD_EMPTY, _
        $MF_MEDIA_ENGINE_PRELOAD_NONE, _
        $MF_MEDIA_ENGINE_PRELOAD_METADATA, _
        $MF_MEDIA_ENGINE_PRELOAD_AUTOMATIC

; MF_MEDIA_ENGINE_CANPLAY
Global Enum $MF_MEDIA_ENGINE_CANPLAY_NOT_SUPPORTED, _
        $MF_MEDIA_ENGINE_CANPLAY_MAYBE, _
        $MF_MEDIA_ENGINE_CANPLAY_PROBABLY

; MF_MEDIA_ENGINE_CREATEFLAGS
Global Enum $MF_MEDIA_ENGINE_AUDIOONLY = 0x1, _
        $MF_MEDIA_ENGINE_WAITFORSTABLE_STATE = 0x2, _
        $MF_MEDIA_ENGINE_FORCEMUTE = 0x4, _
        $MF_MEDIA_ENGINE_REAL_TIME_MODE = 0x8, _
        $MF_MEDIA_ENGINE_DISABLE_LOCAL_PLUGINS = 0x10, _
        $MF_MEDIA_ENGINE_CREATEFLAGS_MASK = 0x1f

; MF_MEDIA_ENGINE_EVENT
Global Enum $MF_MEDIA_ENGINE_EVENT_LOADSTART = 1, _
        $MF_MEDIA_ENGINE_EVENT_PROGRESS = 2, _
        $MF_MEDIA_ENGINE_EVENT_SUSPEND = 3, _
        $MF_MEDIA_ENGINE_EVENT_ABORT = 4, _
        $MF_MEDIA_ENGINE_EVENT_ERROR = 5, _
        $MF_MEDIA_ENGINE_EVENT_EMPTIED = 6, _
        $MF_MEDIA_ENGINE_EVENT_STALLED = 7, _
        $MF_MEDIA_ENGINE_EVENT_PLAY = 8, _
        $MF_MEDIA_ENGINE_EVENT_PAUSE = 9, _
        $MF_MEDIA_ENGINE_EVENT_LOADEDMETADATA = 10, _
        $MF_MEDIA_ENGINE_EVENT_LOADEDDATA = 11, _
        $MF_MEDIA_ENGINE_EVENT_WAITING = 12, _
        $MF_MEDIA_ENGINE_EVENT_PLAYING = 13, _
        $MF_MEDIA_ENGINE_EVENT_CANPLAY = 14, _
        $MF_MEDIA_ENGINE_EVENT_CANPLAYTHROUGH = 15, _
        $MF_MEDIA_ENGINE_EVENT_SEEKING = 16, _
        $MF_MEDIA_ENGINE_EVENT_SEEKED = 17, _
        $MF_MEDIA_ENGINE_EVENT_TIMEUPDATE = 18, _
        $MF_MEDIA_ENGINE_EVENT_ENDED = 19, _
        $MF_MEDIA_ENGINE_EVENT_RATECHANGE = 20, _
        $MF_MEDIA_ENGINE_EVENT_DURATIONCHANGE = 21, _
        $MF_MEDIA_ENGINE_EVENT_VOLUMECHANGE = 22, _
        $MF_MEDIA_ENGINE_EVENT_FORMATCHANGE = 1000, _
        $MF_MEDIA_ENGINE_EVENT_PURGEQUEUEDEVENTS = 1001, _
        $MF_MEDIA_ENGINE_EVENT_TIMELINE_MARKER = 1002, _
        $MF_MEDIA_ENGINE_EVENT_BALANCECHANGE = 1003, _
        $MF_MEDIA_ENGINE_EVENT_DOWNLOADCOMPLETE = 1004, _
        $MF_MEDIA_ENGINE_EVENT_BUFFERINGSTARTED = 1005, _
        $MF_MEDIA_ENGINE_EVENT_BUFFERINGENDED = 1006, _
        $MF_MEDIA_ENGINE_EVENT_FRAMESTEPCOMPLETED = 1007, _
        $MF_MEDIA_ENGINE_EVENT_NOTIFYSTABLESTATE = 1008, _
        $MF_MEDIA_ENGINE_EVENT_FIRSTFRAMEREADY = 1009, _
        $MF_MEDIA_ENGINE_EVENT_TRACKSCHANGE = 1010, _
        $MF_MEDIA_ENGINE_EVENT_OPMINFO = 1011, _
        $MF_MEDIA_ENGINE_EVENT_RESOURCELOST = 1012, _
        $MF_MEDIA_ENGINE_EVENT_DELAYLOADEVENT_CHANGED = 1013, _
        $MF_MEDIA_ENGINE_EVENT_STREAMRENDERINGERROR = 1014, _
        $MF_MEDIA_ENGINE_EVENT_SUPPORTEDRATES_CHANGED = 1015, _
        $MF_MEDIA_ENGINE_EVENT_AUDIOENDPOINTCHANGE = 1016

; MF_MEDIA_ENGINE_READY
Global Enum $MF_MEDIA_ENGINE_READY_HAVE_NOTHING, _
        $MF_MEDIA_ENGINE_READY_HAVE_METADATA, _
        $MF_MEDIA_ENGINE_READY_HAVE_CURRENT_DATA, _
        $MF_MEDIA_ENGINE_READY_HAVE_FUTURE_DATA, _
        $MF_MEDIA_ENGINE_READY_HAVE_ENOUGH_DATA

; MF_MEDIA_ENGINE_STATISTIC
Global Enum $MF_MEDIA_ENGINE_STATISTIC_FRAMES_RENDERED, _
        $MF_MEDIA_ENGINE_STATISTIC_FRAMES_DROPPED, _
        $MF_MEDIA_ENGINE_STATISTIC_BYTES_DOWNLOADED, _
        $MF_MEDIA_ENGINE_STATISTIC_BUFFER_PROGRESS, _
        $MF_MEDIA_ENGINE_STATISTIC_FRAMES_PER_SECOND, _
        $MF_MEDIA_ENGINE_STATISTIC_PLAYBACK_JITTER, _
        $MF_MEDIA_ENGINE_STATISTIC_FRAMES_CORRUPTED, _
        $MF_MEDIA_ENGINE_STATISTIC_TOTAL_FRAME_DELAY

; MF_MEDIA_ENGINE_S3D_PACKING_MODE
Global Enum $MF_MEDIA_ENGINE_S3D_PACKING_MODE_NONE, _
        $MF_MEDIA_ENGINE_S3D_PACKING_MODE_SIDE_BY_SIDE, _
        $MF_MEDIA_ENGINE_S3D_PACKING_MODE_TOP_BOTTOM

; MF_MEDIA_ENGINE_SEEK_MODE
Global Enum $MF_MEDIA_ENGINE_SEEK_MODE_NORMAL, _
        $MF_MEDIA_ENGINE_SEEK_MODE_APPROXIMATE

#EndRegion

#Region Interfaces

Global Const $sIID_IUnknown = "{00000000-0000-0000-C000-000000000046}"
Global Const $sIID_IMFMediaError = "{fc0e10d2-ab2a-4501-a951-06bb1075184c}"
Global Const $sIID_IMFMediaEngineSrcElements = "{7a5e5354-b114-4c72-b991-3131d75032ea}"
Global Const $sIID_IMFMediaTimeRange = "{db71a2fc-078a-414e-9df9-8c2531b0aa6c}"
Global Const $sIID_IMFMediaEngine = "{98a1b0bb-03eb-4935-ae7c-93c1fa0e1c93}"
Global Const $sIID_IMFMediaEngineEx = "{83015ead-b1e6-40d0-a98a-37145ffe1ad1}"
Global Const $sIID_IMFMediaEngineClassFactory = "{4d645ace-26aa-4688-9be1-df3516990b93}"
Global Const $sIID_IMFMediaEngineNotify = "{fee7c112-e776-42b5-9bbf-0048524e2bd5}"
Global Const $sIID_IMFMediaEngineAudioEndpointId = "{7a3bac98-0e76-49fb-8c20-8a86fd98eaf2}"
Global Const $sIID_IMFMediaEngineExtension = "{2f69d622-20b5-41e9-afdf-89ced1dda04e}"

Global Const $IID_IUnknown = _WinAPI_GUIDFromString($sIID_IUnknown)
Global Const $IID_IMFMediaEngineNotify = _WinAPI_GUIDFromString($sIID_IMFMediaEngineNotify)
Global Const $IID_IMFMediaEngineSrcElements = _WinAPI_GUIDFromString($sIID_IMFMediaEngineSrcElements)

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_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_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 $tag_IMFMediaEngine = _
        "GetError hresult(ptr*);" & _
        "SetErrorCode hresult(long);" & _
        "SetSourceElements hresult(ptr);" & _
        "SetSource hresult(ptr);" & _
        "GetCurrentSource hresult(ptr*);" & _
        "GetNetworkState short();" & _
        "GetPreload long();" & _
        "SetPreload hresult(long);" & _
        "GetBuffered hresult(ptr*);" & _
        "Load hresult();" & _
        "CanPlayType hresult(ptr; long*);" & _
        "GetReadyState short();" & _
        "IsSeeking bool();" & _
        "GetCurrentTime double();" & _
        "SetCurrentTime hresult(double);" & _
        "GetStartTime double();" & _
        "GetDuration double();" & _
        "IsPaused bool();" & _
        "GetDefaultPlaybackRate double();" & _
        "SetDefaultPlaybackRate hresult(double);" & _
        "GetPlaybackRate double();" & _
        "SetPlaybackRate hresult(double);" & _
        "GetPlayed hresult(ptr*);" & _
        "GetSeekable hresult(ptr*);" & _
        "IsEnded bool();" & _
        "GetAutoPlay bool();" & _
        "SetAutoPlay hresult(bool);" & _
        "GetLoop bool();" & _
        "SetLoop hresult(bool);" & _
        "Play hresult();" & _
        "Pause hresult();" & _
        "GetMuted bool();" & _
        "SetMuted hresult(bool);" & _
        "GetVolume double();" & _
        "SetVolume hresult(double);" & _
        "HasVideo bool();" & _
        "HasAudio bool();" & _
        "GetNativeVideoSize hresult(uint*; uint*);" & _
        "GetVideoAspectRatio hresult(uint*; uint*);" & _
        "Shutdown hresult();" & _
        "TransferVideoFrame hresult(ptr; struct*; struct*; ulong*);" & _
        "OnVideoStreamTick hresult(int64*);"

Global Const $tag_IMFMediaEngineAudioEndpointId = _
        "SetAudioEndpointId hresult(wstr);" & _
        "GetAudioEndpointId hresult(wstr*);"

Global Const $tag_IMFMediaEngineClassFactory = _
        "CreateInstance hresult(uint; ptr; ptr*);" & _
        "CreateTimeRange hresult(ptr*);" & _
        "CreateError hresult(ptr*);"

Global Const $tag_IMFMediaEngineClassFactory2 = _
        "CreateMediaKeys2 hresult(ptr; ptr; ptr; ptr*);"

Global Const $tag_IMFMediaEngineClassFactory3 = _
        "CreateMediaKeySystemAccess hresult(ptr; ptr*; uint; ptr*);"

Global Const $tag_IMFMediaEngineClassFactory4 = _
        "CreateContentDecryptionModuleFactory hresult(wstr; struct*; ptr*);"

Global Const $tag_IMFMediaEngineClassFactoryEx = _
        $tag_IMFMediaEngineClassFactory & _
        "CreateMediaSourceExtension hresult(uint; ptr; ptr*);" & _
        "CreateMediaKeys hresult(ptr; ptr; ptr*);" & _
        "IsTypeSupported hresult(ptr; ptr; bool*);"


Global Const $tag_IMFMediaEngineEMENotify = _
        "Encrypted none(struct*; uint; ptr);" & _
        "WaitingForKey none();"

Global Const $tag_IMFMediaEngineEME = _
        "Keys hresult(ptr*);" & _
        "SetMediaKeys hresult(ptr);"

Global Const $tag_IMFMediaEngineEx = _
        $tag_IMFMediaEngine & _
        "SetSourceFromByteStream hresult(ptr; ptr);" & _
        "GetStatistics hresult(long; struct*);" & _
        "UpdateVideoStream hresult(struct*; struct*; ulong*);" & _
        "GetBalance double();" & _
        "SetBalance hresult(double);" & _
        "IsPlaybackRateSupported bool(double);" & _
        "FrameStep hresult(bool);" & _
        "GetResourceCharacteristics hresult(uint*);" & _
        "GetPresentationAttribute hresult(struct*; struct*);" & _
        "GetNumberOfStreams hresult(uint*);" & _
        "GetStreamAttribute hresult(uint; struct*; struct*);" & _
        "GetStreamSelection hresult(uint; bool*);" & _
        "SetStreamSelection hresult(uint; bool);" & _
        "ApplyStreamSelections hresult();" & _
        "IsProtected hresult(bool*);" & _
        "InsertVideoEffect hresult(ptr; bool);" & _
        "InsertAudioEffect hresult(ptr; bool);" & _
        "RemoveAllEffects hresult();" & _
        "SetTimelineMarkerTimer hresult(double);" & _
        "GetTimelineMarkerTimer hresult(double*);" & _
        "CancelTimelineMarkerTimer hresult();" & _
        "IsStereo3D bool();" & _
        "GetStereo3DFramePackingMode hresult(long*);" & _
        "SetStereo3DFramePackingMode hresult(long);" & _
        "GetStereo3DRenderMode hresult(long*);" & _
        "SetStereo3DRenderMode hresult(long);" & _
        "EnableWindowlessSwapchainMode hresult(bool);" & _
        "GetVideoSwapchainHandle hresult(handle*);" & _
        "EnableHorizontalMirrorMode hresult(bool);" & _
        "GetAudioStreamCategory hresult(uint*);" & _
        "SetAudioStreamCategory hresult(uint);" & _
        "GetAudioEndpointRole hresult(uint*);" & _
        "SetAudioEndpointRole hresult(uint);" & _
        "GetRealTimeMode hresult(bool*);" & _
        "SetRealTimeMode hresult(bool);" & _
        "SetCurrentTimeEx hresult(double; long);" & _
        "EnableTimeUpdateTimer hresult(bool);"

Global Const $tag_IMFMediaEngineExtension = _
        "CanPlayType hresult(bool; ptr; long*);" & _
        "BeginCreateObject hresult(ptr; ptr; long; ptr*; ptr; ptr);" & _
        "CancelObjectCreation hresult(ptr);" & _
        "EndCreateObject hresult(ptr; ptr*);"

Global Const $tag_IMFMediaEngineNeedKeyNotify = _
        "NeedKey none(struct*; uint);"

Global Const $tag_IMFMediaEngineNotify = _
        "EventNotify hresult(uint; ulong_ptr; uint);"

Global Const $tag_IMFMediaEngineOPMInfo = _
        "GetOPMInfo hresult(long*; bool*);"

Global Const $tag_IMFMediaEngineProtectedContent = _
        "ShareResources hresult(ptr);" & _
        "GetRequiredProtections hresult(uint*);" & _
        "SetOPMWindow hresult(hwnd);" & _
        "TransferVideoFrame hresult(ptr; struct*; struct*; ulong*; uint*);" & _
        "SetContentProtectionManager hresult(ptr);" & _
        "SetApplicationCertificate hresult(struct*; uint);"

Global Const $tag_IMFMediaEngineSrcElements = _
        "GetLength uint();" & _
        "GetURL hresult(uint; ptr*);" & _
        "GetType hresult(uint; ptr*);" & _
        "GetMedia hresult(uint; ptr*);" & _
        "AddElement hresult(ptr; ptr; ptr);" & _
        "RemoveAllElements hresult();"

Global Const $tag_IMFMediaEngineSrcElementsEx = _
        $tag_IMFMediaEngineSrcElements & _
        "AddElementEx hresult(ptr; ptr; ptr; ptr);" & _
        "GetKeySystem hresult(uint; ptr*);"

Global Const $tag_IMFMediaEngineSupportsSourceTransfer = _
        "ShouldTransferSource hresult(bool*);" & _
        "DetachMediaSource hresult(ptr*; ptr*; ptr*);" & _
        "AttachMediaSource hresult(ptr; ptr; ptr);"

Global Const $tag_IMFMediaEngineTransferSource = _
        "TransferSourceToMediaEngine hresult(ptr);"

Global Const $tag_IMFMediaEngineWebSupport = _
        "ShouldDelayTheLoadEvent bool();" & _
        "ConnectWebAudio hresult(uint; ptr*);" & _
        "DisconnectWebAudio hresult();"

Global Const $tag_IMFMediaError = _
        "GetErrorCode short();" & _
        "GetExtendedErrorCode hresult();" & _
        "SetErrorCode hresult(long);" & _
        "SetExtendedErrorCode hresult(hresult);"

#EndRegion

#Region Properties etc

Global Const $MF_MEDIA_ENGINE_AUDIO_CATEGORY = __COM_CreateGUID("{c8d4c51d-350e-41f2-ba46-faebbb0857f6}")
Global Const $MF_MEDIA_ENGINE_AUDIO_ENDPOINT_ROLE = __COM_CreateGUID("{d2cb93d1-116a-44f2-9385-f7d0fda2fb46}")
Global Const $MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE = __COM_CreateGUID("{4e0212e2-e18f-41e1-95e5-c0e7e9235bc3}")
Global Const $MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE9 = __COM_CreateGUID("{052c2d39-40c0-4188-ab86-f828273b7522}")
Global Const $MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE10 = __COM_CreateGUID("{11a47afd-6589-4124-b312-6158ec517fc3}")
Global Const $MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE11 = __COM_CreateGUID("{1cf1315f-ce3f-4035-9391-16142f775189}")
Global Const $MF_MEDIA_ENGINE_BROWSER_COMPATIBILITY_MODE_IE_EDGE = __COM_CreateGUID("{a6f3e465-3aca-442c-a3f0-ad6ddad839ae}")
Global Const $MF_MEDIA_ENGINE_CALLBACK = __COM_CreateGUID("{c60381b8-83a4-41f8-a3d0-de05076849a9}")
Global Const $MF_MEDIA_ENGINE_COMPATIBILITY_MODE = __COM_CreateGUID("{3ef26ad4-dc54-45de-b9af-76c8c66bfa8e}")
Global Const $MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WIN10 = __COM_CreateGUID("{5b25e089-6ca7-4139-a2cb-fcaab39552a3}")
Global Const $MF_MEDIA_ENGINE_COMPATIBILITY_MODE_WWA_EDGE = __COM_CreateGUID("{15b29098-9f01-4e4d-b65a-c06c6c89da2a}")
Global Const $MF_MEDIA_ENGINE_CONTENT_PROTECTION_FLAGS = __COM_CreateGUID("{e0350223-5aaf-4d76-a7c3-06de70894db4}")
Global Const $MF_MEDIA_ENGINE_CONTENT_PROTECTION_MANAGER = __COM_CreateGUID("{fdd6dfaa-bd85-4af3-9e0f-a01d539d876a}")
Global Const $MF_MEDIA_ENGINE_CONTINUE_ON_CODEC_ERROR = __COM_CreateGUID("{dbcdb7f9-48e4-4295-b70d-d518234eeb38}")
Global Const $MF_MEDIA_ENGINE_COREWINDOW = __COM_CreateGUID("{fccae4dc-0b7f-41c2-9f96-4659948acddc}")
Global Const $MF_MEDIA_ENGINE_DXGI_MANAGER = __COM_CreateGUID("{065702da-1094-486d-8617-ee7cc4ee4648}")
Global Const $MF_MEDIA_ENGINE_EME_CALLBACK = __COM_CreateGUID("{494553a7-a481-4cb7-bec5-380903513731}")
Global Const $MF_MEDIA_ENGINE_EXTENSION = __COM_CreateGUID("{3109fd46-060d-4b62-8dcf-faff811318d2}")
Global Const $MF_MEDIA_ENGINE_MEDIA_PLAYER_MODE = __COM_CreateGUID("{3ddd8d45-5aa1-4112-82e5-36f6a2197e6e}")
Global Const $MF_MEDIA_ENGINE_NEEDKEY_CALLBACK = __COM_CreateGUID("{7ea80843-b6e4-432c-8ea4-7848ffe4220e}")
Global Const $MF_MEDIA_ENGINE_OPM_HWND = __COM_CreateGUID("{a0be8ee7-0572-4f2c-a801-2a151bd3e726}")
Global Const $MF_MEDIA_ENGINE_PLAYBACK_HWND = __COM_CreateGUID("{d988879b-67c9-4d92-baa7-6eadd446039d}")
Global Const $MF_MEDIA_ENGINE_PLAYBACK_VISUAL = __COM_CreateGUID("{6debd26f-6ab9-4d7e-b0ee-c61a73ffad15}")
Global Const $MF_MEDIA_ENGINE_SOURCE_RESOLVER_CONFIG_STORE = __COM_CreateGUID("{0ac0c497-b3c4-48c9-9cde-bb8ca2442ca3}")
Global Const $MF_MEDIA_ENGINE_STREAM_CONTAINS_ALPHA_CHANNEL = __COM_CreateGUID("{5cbfaf44-d2b2-4cfb-80a7-d429c74c789d}")
Global Const $MF_MEDIA_ENGINE_SYNCHRONOUS_CLOSE = __COM_CreateGUID("{c3c2e12f-7e0e-4e43-b91c-dc992ccdfa5e}")
Global Const $MF_MEDIA_ENGINE_TELEMETRY_APPLICATION_ID = __COM_CreateGUID("{1e7b273b-a7e4-402a-8f51-c48e88a2cabc}")
Global Const $MF_MEDIA_ENGINE_TRACK_ID = __COM_CreateGUID("{65bea312-4043-4815-8eab-44dce2ef8f2a}")
Global Const $MF_MEDIA_ENGINE_VIDEO_OUTPUT_FORMAT = __COM_CreateGUID("{5066893c-8cf9-42bc-8b8a-472212e52726}")

#EndRegion

#Region Internal Objects

;;;;;;;;;;;;;;;;;;;;;;;; IUnknown Methods ;;;;;;;;;;;;;;;;;;;;;;

Func IUnknown_QueryInterface($pThis, $pTestIID, $ppObj)
    ;We only support 1 vTab per Object ATM.
    Local $hResult = $S_OK
    Local $tRetObj, $tThis
    Local $tTestIID = DllStructCreate("byte dIID[16]", $pTestIID)
    Local $tIIDList, $tSupIID

    If Not $ppObj Then
        $hResult = $E_POINTER
    Else
        $tRetObj = DllStructCreate("ptr pObj", $ppObj)
        $tThis = DllStructCreate("ptr pVTab;ptr iRefCnt;ptr pIIDList", $pThis)
        $tIIDList = DllStructCreate("int iIfaceCnt", $tThis.pIIDList)
        $tIIDList = DllStructCreate(StringFormat("align 4; int iIfaceCnt;ptr pIID[%d]", $tIIDList.iIfaceCnt), $tThis.pIIDList)
        For $i = 1 To $tIIDList.iIfaceCnt
            $tSupIID = DllStructCreate("byte dIID[16]", $tIIDList.pIID(($i)))
            If $tTestIID.dIID = $tSupIID.dIID Then
                $tRetObj.pObj = $pThis
                IUnknown_AddRef($pThis)
                ExitLoop
            EndIf
        Next

        If $i > $tIIDList.iIfaceCnt Then
            $tRetObj.pObj = 0
            $hResult = $E_NOINTERFACE
        EndIf
    EndIf

    Return $hResult
EndFunc

Func IUnknown_AddRef($pThis)
    Local $tThis = DllStructCreate("ptr pVTab;int iRefCnt", $pThis)
    $tThis.iRefCnt += 1
    Return $tThis.iRefCnt
EndFunc

Func IUnknown_Release($pThis)
    Local $tThis = DllStructCreate("ptr pVTab;int iRefCnt", $pThis)
    $tThis.iRefCnt -= 1
    Return $tThis.iRefCnt
EndFunc

Local $tIUnknown_QueryInterface = DllCallbackRegister("IUnknown_QueryInterface", "long", "ptr;ptr;ptr")
Local $tIUnknown_AddRef = DllCallbackRegister("IUnknown_AddRef", "long", "ptr")
Local $tIUnknown_Release = DllCallbackRegister("IUnknown_Release", "long", "ptr")


;;;;;;;;;;;;;;;;;;;;;;;; IMFMediaEngineNotify ;;;;;;;;;;;;;;;;;;;;;;

; IMFMediaEngineNotify::EventNotify is defined further down...
Local $tIMFMediaEngineNotify_EventNotify = DllCallbackRegister("IMFEventNotiy_EventNotify", "long", "ptr;dword;dword_ptr;dword")

;Create the IMFMediaEngineNotify vtable.
Local $tIMFMediaEngineNotify_Vtab = DllStructCreate("ptr pFunc[4]")
$tIMFMediaEngineNotify_Vtab.pFunc(1) = DllCallbackGetPtr($tIUnknown_QueryInterface)
$tIMFMediaEngineNotify_Vtab.pFunc(2) = DllCallbackGetPtr($tIUnknown_AddRef)
$tIMFMediaEngineNotify_Vtab.pFunc(3) = DllCallbackGetPtr($tIUnknown_Release)
$tIMFMediaEngineNotify_Vtab.pFunc(4) = DllCallbackGetPtr($tIMFMediaEngineNotify_EventNotify)

;Supported IID list for IUnkown::QueryInterface
Local $tEventNotify_IIDList = DllStructCreate("align 4;int iCount;ptr pIID[2];")
$tEventNotify_IIDList.iCount = 2
$tEventNotify_IIDList.pIID(1) = DllStructGetPtr($IID_IUnknown)
$tEventNotify_IIDList.pIID(2) = DllStructGetPtr($IID_IMFMediaEngineNotify)

;Required object layout for our implementation of IUnknown - might need to rethink layout to supporting different interfaces.
Local $tIMFMediaEngineNotify = DllStructCreate("ptr pVTab;int iRefCnt;ptr pIIDList;")
$tIMFMediaEngineNotify.pVtab = DllStructGetPtr($tIMFMediaEngineNotify_Vtab)
$tIMFMediaEngineNotify.pIIDList = DllStructGetPtr($tEventNotify_IIDList)

;Initailise the object.
Local $pIMFMediaEngineNotify = DllStructGetPtr($tIMFMediaEngineNotify)
IUnknown_AddRef($pIMFMediaEngineNotify)


;;;;;;;;;;;;;;;;;;;;;;;; IMFMediaEngineSrcElements ;;;;;;;;;;;;;;;;;;;;;;
;Might not need this after all!!!
; This is essetially an array of bstr - so might be able to write these funcs.
; if we have to manually code a bunch of objects, this could become unamanageable!

;~ Local $tIMFMediaEngineSrcElements_GetLength = DllCallbackRegister("IMFMediaEngineSrcElements_GetLength", "uint", "ptr")
;~ Local $tIMFMediaEngineSrcElements_GetUrl = DllCallbackRegister("IMFMediaEngineSrcElements_GetUrl", "long", "ptr; uint; ptr")
;~ Local $tIMFMediaEngineSrcElements_GetType = DllCallbackRegister("IMFMediaEngineSrcElements_GetType", "long", "ptr; uint; ptr")
;~ Local $tIMFMediaEngineSrcElements_GetMedia = DllCallbackRegister("IMFMediaEngineSrcElements_GetMedia", "long", "ptr; uint; ptr")
;~ Local $tIMFMediaEngineSrcElements_AddElement = DllCallbackRegister("IMFMediaEngineSrcElements_AddElement", "long", "ptr; ptr; ptr; ptr")
;~ Local $tIMFMediaEngineSrcElements_RemoveAllElements = DllCallbackRegister("IMFMediaEngineSrcElements_RemoveAllElements", "long", "ptr")

Local $tIMFMediaEngineSrcElements_Vtab = DllStructCreate("ptr pFunc[9]")
$tIMFMediaEngineSrcElements_Vtab(1) = DllCallbackGetPtr($tIUnknown_QueryInterface)
$tIMFMediaEngineSrcElements_Vtab(2) = DllCallbackGetPtr($tIUnknown_AddRef)
$tIMFMediaEngineSrcElements_Vtab(3) = DllCallbackGetPtr($tIUnknown_Release)
;~ $tIMFMediaEngineSrcElements_Vtab(4) = DllCallbackGetPtr($tIMFMediaEngineSrcElements_GetLength)
;~ $tIMFMediaEngineSrcElements_Vtab(5) = DllCallbackGetPtr($tIMFMediaEngineSrcElements_GetUrl)
;~ $tIMFMediaEngineSrcElements_Vtab(6) = DllCallbackGetPtr($tIMFMediaEngineSrcElements_GetType)
;~ $tIMFMediaEngineSrcElements_Vtab(7) = DllCallbackGetPtr($tIMFMediaEngineSrcElements_GetMedia)
;~ $tIMFMediaEngineSrcElements_Vtab(8) = DllCallbackGetPtr($tIMFMediaEngineSrcElements_AddElement)
;~ $tIMFMediaEngineSrcElements_Vtab(9) = DllCallbackGetPtr($tIMFMediaEngineSrcElements_RemoveAllElements)

Local $tIMFMediaEngineSrcElements_IIDList = DllStructCreate("align 4;int iCount;ptr pIID[2];")
$tIMFMediaEngineSrcElements_IIDList.iCount = 2
$tIMFMediaEngineSrcElements_IIDList.pIID(1) = DllStructGetPtr($IID_IUnknown)
$tIMFMediaEngineSrcElements_IIDList.pIID(2) = DllStructGetPtr($IID_IMFMediaEngineSrcElements)

Local $tIMFMediaEngineSrcElements = DllStructCreate("ptr pVTab;int iRefCnt;ptr pIIDList;int iSrcElCnt;ptr pSrcElList")
$tIMFMediaEngineSrcElements.pVtab = DllStructGetPtr($tIMFMediaEngineSrcElements_Vtab)
$tIMFMediaEngineSrcElements.pIIDList = DllStructGetPtr($tIMFMediaEngineSrcElements_IIDList)

;Initailise the object.
Local $pIMFMediaEngineSrcElements = DllStructGetPtr($tIMFMediaEngineSrcElements)
IUnknown_AddRef($pIMFMediaEngineSrcElements)


#EndRegion

Local $hWnd = GUICreate("Media Engine", 800, 600, -1, -1, $WS_OVERLAPPEDWINDOW)
_MF_Startup()

;Create the callback obj
Local $oIMFMediaEngineNotify = ObjCreateInterface($pIMFMediaEngineNotify, $sIID_IMFMediaEngineNotify, $tag_IMFMediaEngineNotify)
ConsoleWrite(StringFormat("(%d,0) IsObj($oIMFMediaEngineNotify) = %s", @ScriptLineNumber, IsObj($oIMFMediaEngineNotify)) & @CRLF & @CRLF)

;Test our object!!
;~ ConsoleWrite("QueryInterface Test:" & @CRLF)
;~ Local $pIUnknown, $tGUID = _WinAPI_GUIDFromString($sIID_IUnknown)
;~ $oIMFMediaEngineNotify.QueryInterface(DllStructGetPtr($tGUID), $pIUnknown)
;~ ConsoleWrite(StringFormat("$pIUnknown = %s", Ptr($pIUnknown)) & @CRLF)
;~ Local $oIUnknown = ObjCreateInterface($pIUnknown, $sIID_IUnknown, "")
;~ ConsoleWrite("RefCnt = " & $oIUnknown.Release() & ", .Release()" & @CRLF & @CRLF)

;Create Media  Engine Factory -
Local $oIMFEngineClassFact = ObjCreateInterface($sCLSID_MFMediaEngineClassFactory, $sIID_IMFMediaEngineClassFactory, $tag_IMFMediaEngineClassFactory)

;Create attrib store for - basically config for factory
Local $pAttributes = _MF_CreateAttributes(1)
Local $oAttributes = ObjCreateInterface($pAttributes, $sIID_IMFAttributes, $tag_IMFAttributes)

;https://learn.microsoft.com/en-us/windows/win32/api/mfmediaengine/nf-mfmediaengine-imfmediaengineclassfactory-createinstance

;Set the callback func. Required!!
Local $tVtIUnknown = DllStructCreate("align 2;ushort vt;word Pad[3];ptr IUnknown;")
$tVtIUnknown.vt = $MF_ATTRIBUTE_IUNKNOWN
$tVtIUnknown.IUnknown = $pIMFMediaEngineNotify
$oAttributes.SetItem($MF_MEDIA_ENGINE_CALLBACK, $tVtIUnknown)

; We need to tell the engine to use its renderer by setting a render target!
Local $tVtHwnd = DllStructCreate("align 2;ushort vt;word Pad[3];uint64 hwnd;")
$tVtHwnd.vt = $MF_ATTRIBUTE_UINT64
$tVtHwnd.hwnd = $hWnd
$oAttributes.SetItem($MF_MEDIA_ENGINE_PLAYBACK_HWND, $tVtHwnd)

Local $pMFEngine

;$oIMFEngine must be global for the event handler.
;(The ptr for $oIMFEngine not passed to the callback as far as I can see)
Global $oIMFEngine

;Create the Engine
Local $hResult = $oIMFEngineClassFact.CreateInstance(0, $pAttributes, $pMFEngine) ;MF_E_ATTRIBUTENOTFOUND = C00D36E6
ConsoleWrite(StringFormat("(%d,0) Fact.CreateInstance(), hr = 0x%08x", @ScriptLineNumber, $hResult) & @CRLF)
$oIMFEngine = ObjCreateInterface($pMFEngine, $sIID_IMFMediaEngine, $tag_IMFMediaEngine)
ConsoleWrite(StringFormat("(%d,0) IMFEngine Created = %s", @ScriptLineNumber, (IsObj($oIMFEngine) = 1)) & @CRLF)

;Next step for sorting out the media source. - Maybe not required after all
;~ Local $tGUID = _WinAPI_GUIDFromString($sIID_IMFMediaEngineSrcElements)
;~ Local $oIMFMediaEngineSrcElements = ObjCreateInterface($pMFEngine, $sIID_IMFMediaEngineSrcElements, $tag_IMFMediaEngineSrcElements)
;~ ConsoleWrite(StringFormat("(%d,0) $oIMFMediaEngineSrcElements Created = %s", @ScriptLineNumber, (IsObj($oIMFMediaEngineSrcElements) = 1)) & @CRLF)

;Testing!!!
ConsoleWrite("Test a few notifications...." & @CRLF)
$oIMFEngine.SetMuted(True)
$oIMFEngine.SetMuted(False)
Local $sSource = _WinAPI_SysAllocString($sTestFile)
$hResult = $oIMFEngine.SetSource($sSource)
ConsoleWrite(StringFormat("(%d,0) %s hresult = 0x%08X", @ScriptLineNumber, "$oIMFEngine.SetSource", $hResult) & @CRLF)
$oIMFEngine.Load()
ConsoleWrite(StringFormat("(%d,0) %s hresult = 0x%08X", @ScriptLineNumber, "$oIMFEngine.Load", $hResult) & @CRLF)
$oIMFEngine.Play()
ConsoleWrite(StringFormat("(%d,0) %s hresult = 0x%08X", @ScriptLineNumber, "$oIMFEngine.Play", $hResult) & @CRLF)

GUISetState()

;~ ;Test thread pause.. Anti-crash caused via notifications test! -- In uncommenented you will need to kill script with task manager. 
;~ Local $aCall = DllCall("kernel32.dll", "dword", "GetCurrentThreadId")
;~ Local $iThreadID = $aCall[0]
;~ $aCall = DllCall("kernel32.dll", "ptr", "OpenThread", "dword", 0x001F03FF, "int", 0, "dword", $iThreadID)
;~ Local $hThread = $aCall[0]
;~ DllCall("kernel32.dll", "dword", "SuspendThread", "ptr", $hThread)

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

$oIMFEngine.Shutdown()
_MF_Shutdown()

#Region Event Handler

Func IMFEventNotiy_EventNotify($pThis, $iEvent, $iParam1, $iParam2)
;~  Return
    Switch $iEvent

        Case $MF_MEDIA_ENGINE_EVENT_EMPTIED
            ConsoleWrite(StringFormat("Event: %-4d > %s",  $iEvent, "Emptied") & @CRLF)

        Case $MF_MEDIA_ENGINE_EVENT_PLAY
            ConsoleWrite(StringFormat("Event: %-4d > %s",  $iEvent, "Play") & @CRLF)

        Case $MF_MEDIA_ENGINE_EVENT_WAITING
            ConsoleWrite(StringFormat("Event: %-4d > %s",  $iEvent, "Waiting") & @CRLF)

        Case $MF_MEDIA_ENGINE_EVENT_PLAYING
            ConsoleWrite(StringFormat("Event: %-4d > %s",  $iEvent, "Playing") & @CRLF)

        Case $MF_MEDIA_ENGINE_EVENT_TIMEUPDATE
             ConsoleWrite(StringFormat("Event: %-4d > %s",  $iEvent, "Time Update") & @CRLF)

        Case $MF_MEDIA_ENGINE_EVENT_CANPLAY
            ConsoleWrite(StringFormat("Event: %-4d > %s",  $iEvent, "CanPlay") & @CRLF)

        Case $MF_MEDIA_ENGINE_EVENT_VOLUMECHANGE
            ConsoleWrite(StringFormat("Event: %-4d >, %s, Vol: %f, Muted: %s",  $iEvent, "Volume Change", $oIMFEngine.GetVolume(), $oIMFEngine.GetMuted()) & @CRLF)

        Case $MF_MEDIA_ENGINE_EVENT_PURGEQUEUEDEVENTS
            ConsoleWrite(StringFormat("Event: %-4d > %s",  $iEvent, "Purge Queued Events") & @CRLF)

        Case Else
            ConsoleWrite(StringFormat("Event: %-4d > P1: %d, P2 %d",  $iEvent, $iParam1, $iParam2) & @CRLF)

    EndSwitch
EndFunc

#EndRegion

#Region Funcs

; replace 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 GUID[16]", DllStructGetPtr($tGUID1))
    Local $tBuff2 = DllStructCreate("byte GUID[16]", DllStructGetPtr($tGUID2))
    ConsoleWrite($tBuff1.GUID & @CRLF)
    ConsoleWrite($tBuff2.GUID & @CRLF)

    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

Func _MF_CreateAttributes($iInitialSize = 0)
    Local $aCall = DllCall("mfplat.dll", "long", "MFCreateAttributes", "ptr*", 0, "uint", $iInitialSize)
    If @error Then Return SetError(__COM_GetDllError(), 0, 0)
    Return SetError($aCall[0], 0, $aCall[1])
EndFunc


Func _WinAPI_SysAllocString($sString)
  Local $aCall = DllCall("OleAut32.dll", "handle", "SysAllocString", "wstr", $sString)
  If @error Then Return SetError(__COM_GetDllError(), 0, 0)
  Return $aCall[0]
EndFunc   ;==>_WinAPI_SysAllocString

#EndRegion Funcs
Edited by MattyD
Posted

Replacing :

Func _WinAPI_SysAllocString($sString)
    Local $aCall = DllCall("mfplat.dll", "handle", "OleAut32.dll", "wchar", $sString)
    If @error Then Return SetError(__COM_GetDllError(), 0, 0)
    Return $aCall[0]
EndFunc

with

Func _WinAPI_SysAllocString($sString)
  Local $aCall = DllCall("OleAut32.dll", "handle", "SysAllocString", "wstr", $sString)
  If @error Then Return SetError(__COM_GetDllError(), 0, 0)
  Return $aCall[0]
EndFunc   ;==>_WinAPI_SysAllocString

And removing the , $oIMFEngine.CanPlay() in event handler proc.

Now starts correctly.  But after a few events the script crashes.  However from time to time, the event handler stops receiving messages and the video runs normally.  In this particular case, you cannot stop the script with the close button.  You need to interrupt it with task manager.

Posted (edited)

OK thanks! -That's amazing,, I've added those changes in Post #1.

yeah the event proc issue's likely going to be a painful one, if its the normal issue we see with callbacks in AutoIt. 

I remember once solving this by having the script pause its own thread. I found it stopped executing at that point, but the event proc continued to work as per normal.
So the "paused" script handled notifications in the background then passed anything it received to a second script via some IPC. 

As a test, you can pop this after GuiSetState().

Local $aCall = DllCall("kernel32.dll", "dword", "GetCurrentThreadId")
Local $iThreadID = $aCall[0]
$aCall = DllCall("kernel32.dll", "ptr", "OpenThread", "dword", 0x001F03FF, "int", 0, "dword", $iThreadID)
Local $hThread = $aCall[0]
DllCall("kernel32.dll", "dword", "SuspendThread", "ptr", $hThread)

You should see the notifications happily running. Just be prepared - the window will stop responding and you'll manually need to kill the process.  But you should hopefully be able to run the video through.

Edited by MattyD
Posted

Yep, it does work, the same way you could do :

SleepEx(300000, True)

Func SleepEx($nMilliseconds, $bAlertable = 0)
  Local $aRet = DllCall('kernel32.dll', 'dword', 'SleepEx', 'dword', $nMilliseconds, 'bool', $bAlertable)
  If @error Then Return SetError(@error, @extended, 0)
  Return $aRet[0]
EndFunc   ;==>_SleepEx

Video is playing normally for the duration of the sleepex

Posted

hmm you can use mediaEngine as a frameserver. So it might be worth seeing if we can get another process to do the rendering.

Its convoluted, but might be worth a look if there's no better ideas?

Posted (edited)

I came to the same conclusion.  It is quite clear that the rendering is performed into another thread.  Since AutoIt is not built to manage multiple threads, it just crashes or gets completely lost.  Try this a few times and you will receive all very weird messages :

Local $hEvent = _WinAPI_CreateEvent(0, True, False), $iRet
While True
  $iRet = _WinAPI_WaitForSingleObjectEx($hEvent, 1000, True)
  ConsoleWrite($iRet & @CRLF)
WEnd

Func _WinAPI_WaitForSingleObjectEx($hEvent, $nMilliseconds, $bAlertable = 0)
  Local $aRet = DllCall('kernel32.dll', 'dword', 'WaitForSingleObjectEx', 'handle', $hEvent, 'dword', $nMilliseconds, 'bool', $bAlertable)
  If @error Then Return SetError(@error, @extended, 0)
  Return $aRet[0]
EndFunc   ;==>_WinAPI_WaitForSingleObjectEx

 

Edited by Nine
Posted (edited)

I first ran your script in your first post with lines 674 through 679 commented. The playback started fine, but the video frames did not seem to move forward and the script stopped after about 5 seconds. I then ran your script with those lines uncommented. Aside from having to use Task Manager to exit the program, the 4k video file played smoothly without any stuttering. Congratulations!

Edited by CYCho
Posted

Nice work.

It crashes for x64 just after displaying GUI :

(609,0) IsObj($oIMFMediaEngineNotify) = 1

(648,0) Fact.CreateInstance(), hr = 0x00000000
(650,0) IMFEngine Created = True
Test a few notifications....
Event: 22   >, Volume Change, Vol: 1.000000, Muted: True
Event: 22   >, Volume Change, Vol: 1.000000, Muted: False
Event: 1001 > Purge Queued Events
Event: 1    > P1: 0, P2 0
(663,0) $oIMFEngine.SetSource hresult = 0x00000000
Event: 1001 > Purge Queued Events
Event: 4    > P1: 0, P2 0
Event: 6    > Emptied
Event: 1    > P1: 0, P2 0
(665,0) $oIMFEngine.Load hresult = 0x00000000
Event: 8    > Play
Event: 12   > Waiting
(667,0) $oIMFEngine.Play hresult = 0x00000000
Event: 21   > P1: 0, P2 0
Event: 10   > P1: 0, P2 0
Event: 11   > P1: 0, P2 0
Event: 14   > CanPlay
Event: 15   > P1: 0, P2 0
Event: 18   > Time Update
Event: 1000 > P1: 0, P2 0
Event: 1009 > P1: 0, P2 0
Event: 18   > Time Update
Event: 18   > Time Update
Event: 13   > Playing
Event: 18   > Time Update
!>09:52:06 AutoIt3.exe ended.rc:-1073741819

-1073741819 / 0xC0000005: An Access Violation is a type of Exception caused when an application Reads, Writes or Executes an invalid Memory Address.

x86:

it starts but get frozen after 1 sec and crashes with same error as for x64.

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Posted (edited)

Thanks guys.

I've found if you spin up a MsgBox() and just keep it open, the whole window doesn't lock up.  I don't suppose we can block execution in the same way, but without the dialog? 

If we can achieve this, we might be able to embed the video into a window owned by a child process using $WS_CHILD. Sleeping/Suspending the thread locks up both windows.

Edited by MattyD
Posted

Good find.  I was trying to use one of my IPC to connect both running processes.  Even with the MsgBox I am having a hard time to send messages to rendering process.  However the Main process can receive quite nicely messages from the rendering process.  Along the way I made a small UDF to create interface object, based on our discussion and from a post I saw from trancexx.  I also included it in the script.

I'll let you decide what you want to do with this version 2 of the engine.

 

MediaEngine.zip

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