Screen capture to video with Directx9 / Directx11 and Microsoft Media Foundation

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: Screen capture to video with Directx9 / Directx11 and Microsoft Media Foundation

13 Jan 2020, 20:29

Testing right now. Intermedial report: looks good, while testing is in progress!
Still running the test. Almost 10 min. The only downside is how to stop it and retain a valid mp4 output!
Now I stopped it. It proved stable! You are amazing. As I predicted at stop mp4 was not playable although I "tried". Will modify the code tomorrow to stop at the end of recording session!
Good night!

P.s.: I tested similarly the script with "collimator and frame" and it crashes soon. The same I did with WebCam script and it was much more stable but ultimately it craches with: IMFMediaSource_Shutdown error: -1072873851
ErrorLevel: 0
.
Last edited by rommmcek on 13 Jan 2020, 20:46, edited 1 time in total.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Screen capture to video with Directx9 / Directx11 and Microsoft Media Foundation

13 Jan 2020, 20:44

I updated first post.
Now I think it should work OK.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Screen capture to video with Directx9 / Directx11 and Microsoft Media Foundation

13 Jan 2020, 21:58

Please link to script with "collimator and frame".
Post Your tested code for WebCam that gives such error.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Screen capture to video with Directx9 / Directx11 and Microsoft Media Foundation

14 Jan 2020, 04:29

Can You try this code - what error do You get?

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

;file := "test.mp4"
;video_bitrate := 2000000
;video_fps := 25
;duration := 25
 videodevice := "Lenovo EasyCamera"
 audiodevice := "Stereo Mix (Realtek High Definition Audio)"
 ;audiodevice := "Microphone (Realtek High Definition Audio)"
 ;audiodevice := "Stereo Mix (Realtek High Definition Audio)"
 ;hardware_encoder:= "Encoder MFT"
 ;hardware_encoder:= "GeForce MX 660M"
;IMFSourceReader_SetCurrentMediaType error: -1072875852
 ;ShowAllDevicesNames := true

file := "test.mp4"
FileDelete % file
video_bitrate := 2000000
duration := 1
; videodevice := "e2eSoft VCam"
; audiodevice := "CABLE Output (VB-Audio Virtual Cable)"
; ShowAllDevicesNames := true



setbatchlines -1
LOAD_DLL_Mf_Mfplat_Mfreadwrite()
MFStartup(version := 2, MFSTARTUP_FULL := 0)
if (ShowAllDevicesNames = "")
{
   VarSetCapacity(MFT_REGISTER_TYPE_INFO, 32, 0)
   DllCall("RtlMoveMemory", "ptr", &MFT_REGISTER_TYPE_INFO, "ptr", MF_GUID(GUID, "MFMediaType_Video"), "ptr", 16)
   DllCall("RtlMoveMemory", "ptr", &MFT_REGISTER_TYPE_INFO + 16, "ptr", MF_GUID(GUID, "MFVideoFormat_H264"), "ptr", 16)
   hardware_encoder := MFTEnumEx(MF_GUID(GUID, "MFT_CATEGORY_VIDEO_ENCODER"), MFT_ENUM_FLAG_HARDWARE := 0x04|MFT_ENUM_FLAG_SORTANDFILTER := 0x40, 0, &MFT_REGISTER_TYPE_INFO)
   ;msgbox % "hardware-encoder - " hardware_encoder
   if (hardware_encoder != "")
   {
      MFCreateAttributes(pMFAttributes, 4)
      IMFAttributes_SetUINT32(pMFAttributes, MF_GUID(GUID, "MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS"), true)
   }
   else
      MFCreateAttributes(pMFAttributes, 3)
   IMFAttributes_SetGUID(pMFAttributes, MF_GUID(GUID, "MF_TRANSCODE_CONTAINERTYPE"), MF_GUID(GUID1, "MFTranscodeContainerType_MPEG4"))
   IMFAttributes_SetUINT32(pMFAttributes, MF_GUID(GUID, "MF_SINK_WRITER_DISABLE_THROTTLING"), true)
   IMFAttributes_SetUINT32(pMFAttributes, MF_GUID(GUID, "MF_LOW_LATENCY"), true)
   MFCreateSinkWriterFromURL(file, 0, pMFAttributes, pSinkWriter)
   Release(pMFAttributes)
   pMFAttributes := ""
}

deviceError := WidthMax := HeightMax := FpsMax := BitrateMax := StreamNumberVideo := TypeNumberVideo := NUM_CHANNELSMax := BITS_PER_SAMPLEMax := SAMPLES_PER_SECONDMax := BYTES_PER_SECONDMax := StreamNumberAudio := TypeNumberAudio := VideoSources := AudioSources := ""
loop 2
{
   if (A_Index = 1)
      LookingSource := "video"
   else
      LookingSource := "audio"
   MFCreateAttributes(pMFAttributes%LookingSource%, 1)
   IMFAttributes_SetGUID(pMFAttributes%LookingSource%, MF_GUID(GUID, "MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE"), MF_GUID(GUID1, "MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_" SubStr(LookingSource, 1, 3) "CAP_GUID"))
   MFEnumDeviceSources(pMFAttributes%LookingSource%, pppSourceActivate, pcSourceActivate)
   Loop % pcSourceActivate
   {
      IMFActivate := NumGet(pppSourceActivate + (A_Index - 1)*A_PtrSize)
      devicename := IMFActivate_GetAllocatedString(IMFActivate, MF_GUID(GUID, "MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME"))
      if ShowAllDevicesNames
         %LookingSource%devicenames .= devicename "`n"
      else if (devicename = %LookingSource%device)
         IMFActivate_ActivateObject(IMFActivate, IMFMediaSource := "{279a808d-aec7-40c8-9c6b-a6b492c78a66}", MediaSource%LookingSource%)
      Release(IMFActivate)
      IMFActivate := ""
   }
   DllCall("ole32\CoTaskMemFree", "ptr", pppSourceActivate)
   Release(pMFAttributes%LookingSource%)
   pMFAttributes%LookingSource% := ""
   if ShowAllDevicesNames
   {
      if (%LookingSource%devicenames = "")
         %LookingSource%devicenames .= "None`n"
      %LookingSource%devicenames := LookingSource ":`n" %LookingSource%devicenames
      if (A_Index = 1)
         Continue
      msgbox % clipboard := videodevicenames "`n" audiodevicenames
      ExitApp
   }
   if (MediaSource%LookingSource% = "") or (deviceError != "")
   {
      if (MediaSource%LookingSource% = "")
         deviceError .= "Cannot find " LookingSource " device - """ %LookingSource%device """`n"
      if (A_Index = 1) and (audiodevice != "")
         Continue
      msgbox % deviceError
      ExitApp
   }
   if (A_Index = 1)
   {
      if (hardware_encoder != "")
      {
         MFCreateAttributes(pMFAttributes, 3)
         IMFAttributes_SetUINT32(pMFAttributes, MF_GUID(GUID, "MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS"), true)
      }
      else
         MFCreateAttributes(pMFAttributes, 2)
      IMFAttributes_SetUINT32(pMFAttributes, MF_GUID(GUID, "MF_LOW_LATENCY"), true)
      IMFAttributes_SetUINT32(pMFAttributes, MF_GUID(GUID, "MF_SOURCE_READER_DISCONNECT_MEDIASOURCE_ON_SHUTDOWN"), true)
   }
   MFCreateSourceReaderFromMediaSource(MediaSource%LookingSource%, pMFAttributes, SourceReader)
   loop
   {
      n := A_Index - 1
      if (IMFSourceReader_GetNativeMediaType(SourceReader, n, 0, ppMediaType) = "MF_E_INVALIDSTREAMNUMBER")
      {
         if (LookingSource = "video")
            VideoStreamCount := n
         break
      }
      Release(ppMediaType)
      ppMediaType := ""
      loop
      {
         k := A_Index - 1
         if (IMFSourceReader_GetNativeMediaType(SourceReader, n, k, ppMediaType) = "MF_E_NO_MORE_TYPES")
            break
         IMFAttributes_GetGUID(ppMediaType, MF_GUID(GUID, "MF_MT_MAJOR_TYPE"), pguidValue)
         if (LookingSource = "video") and (MemoryDifference(&pguidValue, MF_GUID(GUID, "MFMediaType_Video"), 16) = 0)
         {
            IMFAttributes_GetGUID(ppMediaType, MF_GUID(GUID, "MF_MT_SUBTYPE"), pguidValueSubType)
            VideoSources .= Format("0x{:x}", NumGet(pguidValueSubType, 0, "int")) "`n" 
            if (MemoryDifference(&pguidValueSubType, MF_GUID(GUID, "MFVideoFormat_I420"), 16) = 0) or (MemoryDifference(&pguidValueSubType, MF_GUID(GUID, "MFVideoFormat_IYUV"), 16) = 0) or (MemoryDifference(&pguidValueSubType, MF_GUID(GUID, "MFVideoFormat_NV12"), 16) = 0) or (MemoryDifference(&pguidValueSubType, MF_GUID(GUID, "MFVideoFormat_YUY2"), 16) = 0) or (MemoryDifference(&pguidValueSubType, MF_GUID(GUID, "MFVideoFormat_YV12"), 16) = 0) or (MemoryDifference(&pguidValueSubType, MF_GUID(GUID, "MFVideoFormat_RGB32"), 16) = 0) or (MemoryDifference(&pguidValueSubType, MF_GUID(GUID, "MFVideoFormat_RGB24"), 16) = 0)
            {
               IMFAttributes_GetUINT64(ppMediaType, MF_GUID(GUID, "MF_MT_FRAME_SIZE"), FRAME_SIZE)
               IMFAttributes_GetUINT64(ppMediaType, MF_GUID(GUID, "MF_MT_FRAME_RATE"), FRAME_RATE)
               if (IMFAttributes_GetUINT32(ppMediaType, MF_GUID(GUID, "MF_MT_AVG_BITRATE"), AVG_BITRATE) = "MF_E_ATTRIBUTENOTFOUND")
                  AVG_BITRATE := 0
               WidthCurrent := FRAME_SIZE >> 32
               HeightCurrent := 0xFFFFFFFF & FRAME_SIZE
               FpsCurrent := (FRAME_RATE>>32)/(0xFFFFFFFF & FRAME_RATE)
               BitrateCurrent := AVG_BITRATE
               if (WidthCurrent > WidthMax) or ((WidthCurrent = WidthMax) and (HeightCurrent > HeightMax)) or ((WidthCurrent = WidthMax) and (HeightCurrent = HeightMax) and (FpsCurrent > FpsMax)) or ((WidthCurrent = WidthMax) and (HeightCurrent = HeightMax) and (FpsCurrent = FpsMax) and (BitrateCurrent > BitrateMax))
               { 
                  WidthMax := WidthCurrent
                  HeightMax := HeightCurrent
                  FpsMax := FpsCurrent
                  BitrateMax := BitrateCurrent
                  StreamNumberVideo := n
                  TypeNumberVideo := k
               }
            }
         }
         if ((LookingSource = "audio") or (audiodevice = "")) and (MemoryDifference(&pguidValue, MF_GUID(GUID, "MFMediaType_Audio"), 16) = 0)
         {
            IMFAttributes_GetGUID(ppMediaType, MF_GUID(GUID, "MF_MT_SUBTYPE"), pguidValueSubType)
            AudioSources .= Format("0x{:x}", NumGet(pguidValueSubType, 0, "int")) "`n"
            if (MemoryDifference(&pguidValueSubType, MF_GUID(GUID, "MFAudioFormat_PCM"), 16) = 0) or (MemoryDifference(&pguidValueSubType, MF_GUID(GUID, "MFAudioFormat_Float"), 16) = 0)
            {
               if (IMFAttributes_GetUINT32(ppMediaType, MF_GUID(GUID, "MF_MT_AUDIO_AVG_BYTES_PER_SECOND"), BYTES_PER_SECOND) = "MF_E_ATTRIBUTENOTFOUND")
                  BYTES_PER_SECOND := 0
               if (IMFAttributes_GetUINT32(ppMediaType, MF_GUID(GUID, "MF_MT_AUDIO_BITS_PER_SAMPLE"), BITS_PER_SAMPLE) = "MF_E_ATTRIBUTENOTFOUND")
                  BITS_PER_SAMPLE := 0
               if (IMFAttributes_GetUINT32(ppMediaType, MF_GUID(GUID, "MF_MT_AUDIO_SAMPLES_PER_SECOND"), SAMPLES_PER_SECOND) = "MF_E_ATTRIBUTENOTFOUND")
                  SAMPLES_PER_SECOND := 0
               if (IMFAttributes_GetUINT32(ppMediaType, MF_GUID(GUID, "MF_MT_AUDIO_NUM_CHANNELS"), NUM_CHANNELS) = "MF_E_ATTRIBUTENOTFOUND")
                  NUM_CHANNELS := 0
               if ((NUM_CHANNELSMax < 2) and (NUM_CHANNELS > NUM_CHANNELSMax)) or ((NUM_CHANNELSMax = 2) and (NUM_CHANNELS = 6)) or ((NUM_CHANNELSMax > 2) and (NUM_CHANNELSMax != 6) and ((NUM_CHANNELS = 2) or (NUM_CHANNELS = 6))) or ((NUM_CHANNELS = NUM_CHANNELSMax) and (BITS_PER_SAMPLEMax != 16) and ((BITS_PER_SAMPLE = 16) or (BITS_PER_SAMPLE > BITS_PER_SAMPLEMax))) or ((NUM_CHANNELS = NUM_CHANNELSMax) and (BITS_PER_SAMPLE = BITS_PER_SAMPLEMax) and (SAMPLES_PER_SECONDMax != 44100) and (SAMPLES_PER_SECONDMax != 48000) and ((SAMPLES_PER_SECOND = 44100) or (SAMPLES_PER_SECOND > SAMPLES_PER_SECONDMax))) or ((SAMPLES_PER_SECONDMax != 48000) and (SAMPLES_PER_SECOND = 48000)) or ((NUM_CHANNELS = NUM_CHANNELSMax) and (BITS_PER_SAMPLE = BITS_PER_SAMPLEMax) and (SAMPLES_PER_SECOND = SAMPLES_PER_SECONDMax) and (BYTES_PER_SECOND > BYTES_PER_SECONDMax))
               { 
                  NUM_CHANNELSMax := NUM_CHANNELS
                  BITS_PER_SAMPLEMax := BITS_PER_SAMPLE
                  SAMPLES_PER_SECONDMax := SAMPLES_PER_SECOND
                  BYTES_PER_SECONDMax := BYTES_PER_SECOND
                  StreamNumberAudio := n
                  TypeNumberAudio := k
               }
            }
         }
         Release(ppMediaType)
         ppMediaType := ""
      }
   }
   if (audiodevice != "")
   {
      Release(SourceReader)
      SourceReader := ""
   }
   if (audiodevice = "") or (A_Index = 2)
   {
      if (StreamNumberVideo = "")
      {
         Sort, VideoSources, U
         msgbox % "Current VideoSources not supported:`n" VideoSources
         ExitApp
      }
      if (A_Index = 2)
      {
         if (StreamNumberAudio != "")
            StreamNumberAudio += VideoStreamCount
         else
         {
            Sort, AudioSources, U
            msgbox % "Current AudioSources not supported:`n" AudioSources
            ExitApp
         }
         MFCreateCollection(MFCollection)
         IMFCollection_AddElement(MFCollection, MediaSourceVideo)
         IMFCollection_AddElement(MFCollection, MediaSourceAudio)
         MFCreateAggregateSource(MFCollection, AggSource)
         Release(MFCollection)
         MFCollection := ""
         MFCreateSourceReaderFromMediaSource(AggSource, pMFAttributes, SourceReader)
      }
      IMFSourceReader_SetStreamSelection(SourceReader, MF_SOURCE_READER_ALL_STREAMS := 0xFFFFFFFE, false)
      IMFSourceReader_SetStreamSelection(SourceReader, StreamNumberVideo, true)
      if (StreamNumberAudio != "")
         IMFSourceReader_SetStreamSelection(SourceReader, StreamNumberAudio, true)
      IMFSourceReader_GetNativeMediaType(SourceReader, StreamNumberVideo, TypeNumberVideo, ppMediaType)
      IMFAttributes_GetGUID(ppMediaType, MF_GUID(GUID, "MF_MT_SUBTYPE"), pguidValue)
      IMFAttributes_GetUINT32(ppMediaType, MF_GUID(GUID, "MF_MT_INTERLACE_MODE"), INTERLACE_MODE)
      IMFAttributes_GetUINT64(ppMediaType, MF_GUID(GUID, "MF_MT_FRAME_SIZE"), FRAME_SIZE)
      IMFAttributes_GetUINT64(ppMediaType, MF_GUID(GUID, "MF_MT_FRAME_RATE"), FRAME_RATE)
      IMFAttributes_GetUINT64(ppMediaType, MF_GUID(GUID, "MF_MT_PIXEL_ASPECT_RATIO"), ASPECT_RATIO)
      Release(ppMediaType)
      Release(pMFAttributes)
      ppMediaType := pMFAttributes := ""
      if (audiodevice = "")
         break
   }
}

loop 2   ; 1 - input, 2 - output
{
   MFCreateMediaType(pMediaTypeVideo%A_Index%)
   IMFAttributes_SetGUID(pMediaTypeVideo%A_Index%, MF_GUID(GUID, "MF_MT_MAJOR_TYPE"), MF_GUID(GUID1, "MFMediaType_Video"))
   if (A_Index = 1)
      IMFAttributes_SetGUID(pMediaTypeVideo%A_Index%, MF_GUID(GUID, "MF_MT_SUBTYPE"), &pguidValue)
   else
   {
      IMFAttributes_SetGUID(pMediaTypeVideo%A_Index%, MF_GUID(GUID, "MF_MT_SUBTYPE"), MF_GUID(GUID1, "MFVideoFormat_H264"))
      IMFAttributes_SetUINT32(pMediaTypeVideo%A_Index%, MF_GUID(GUID, "MF_MT_AVG_BITRATE"), video_bitrate)
   }
   IMFAttributes_SetUINT32(pMediaTypeVideo%A_Index%, MF_GUID(GUID, "MF_MT_INTERLACE_MODE"), INTERLACE_MODE)
   IMFAttributes_SetUINT64(pMediaTypeVideo%A_Index%, MF_GUID(GUID, "MF_MT_FRAME_SIZE"), FRAME_SIZE)
   IMFAttributes_SetUINT64(pMediaTypeVideo%A_Index%, MF_GUID(GUID, "MF_MT_FRAME_RATE"), FRAME_RATE)
   IMFAttributes_SetUINT64(pMediaTypeVideo%A_Index%, MF_GUID(GUID, "MF_MT_PIXEL_ASPECT_RATIO"), ASPECT_RATIO)
}
IMFSinkWriter_AddStream(pSinkWriter, pMediaTypeVideo2, videoStreamIndex)
IMFSinkWriter_SetInputMediaType(pSinkWriter, videoStreamIndex, pMediaTypeVideo1, 0)
IMFSourceReader_SetCurrentMediaType(SourceReader, StreamNumberVideo, 0, pMediaTypeVideo1)
Release(pMediaTypeVideo1)
Release(pMediaTypeVideo2)
pMediaTypeVideo1 := pMediaTypeVideo2 := ""

if (StreamNumberAudio != "")
{
   if (NUM_CHANNELSMax = 0)
      NUM_CHANNELSMax := 1
   else if (NUM_CHANNELSMax > 2) and (NUM_CHANNELSMax < 6)
      NUM_CHANNELSMax := 2
   else if (NUM_CHANNELSMax > 6)
      NUM_CHANNELSMax := 6
   if (SAMPLES_PER_SECONDMax < 44100)
      SAMPLES_PER_SECONDMax := 44100
   else if (SAMPLES_PER_SECONDMax > 44100)
      SAMPLES_PER_SECONDMax := 48000
   loop 2   ; 1 - input, 2 - output
   {
      MFCreateMediaType(pMediaTypeAudio%A_Index%)
      IMFAttributes_SetGUID(pMediaTypeAudio%A_Index%, MF_GUID(GUID, "MF_MT_MAJOR_TYPE"), MF_GUID(GUID1, "MFMediaType_Audio"))
      if (A_Index = 1)
         IMFAttributes_SetGUID(pMediaTypeAudio%A_Index%, MF_GUID(GUID, "MF_MT_SUBTYPE"), MF_GUID(GUID1, "MFAudioFormat_PCM"))
      else
      {
         IMFAttributes_SetGUID(pMediaTypeAudio%A_Index%, MF_GUID(GUID, "MF_MT_SUBTYPE"), MF_GUID(GUID1, "MFAudioFormat_AAC"))
         IMFAttributes_SetUINT32(pMediaTypeAudio%A_Index%, MF_GUID(GUID, "MF_MT_AUDIO_AVG_BYTES_PER_SECOND"), 20000)
      }
      IMFAttributes_SetUINT32(pMediaTypeAudio%A_Index%, MF_GUID(GUID, "MF_MT_AUDIO_BITS_PER_SAMPLE"), 16)
      IMFAttributes_SetUINT32(pMediaTypeAudio%A_Index%, MF_GUID(GUID, "MF_MT_AUDIO_SAMPLES_PER_SECOND"), SAMPLES_PER_SECONDMax)
      IMFAttributes_SetUINT32(pMediaTypeAudio%A_Index%, MF_GUID(GUID, "MF_MT_AUDIO_NUM_CHANNELS"), NUM_CHANNELSMax)
   }
   IMFSinkWriter_AddStream(pSinkWriter, pMediaTypeAudio2, audioStreamIndex)
   IMFSinkWriter_SetInputMediaType(pSinkWriter, audioStreamIndex, pMediaTypeAudio1, 0)
   IMFSourceReader_SetCurrentMediaType(SourceReader, StreamNumberAudio, 0, pMediaTypeAudio1)
   Release(pMediaTypeAudio1)
   Release(pMediaTypeAudio2)
   pMediaTypeAudio1 := pMediaTypeAudio2 := ""
}
IMFSinkWriter_BeginWriting(pSinkWriter)

CaptureStart := start := ""
CaptureDuration := duration*1000
loop
{
   IMFSourceReader_ReadSample(SourceReader, MF_SOURCE_READER_ANY_STREAM := 0xFFFFFFFE, 0, ActualStreamIndex, StreamFlags, Timestamp, pSample)
   if (ActualStreamIndex = StreamNumberVideo)
      ActualStreamIndex := videoStreamIndex
   else
      ActualStreamIndex := audioStreamIndex
   if (CaptureStart = "") and (pSample != 0) and (ActualStreamIndex = videoStreamIndex)
   {
      CaptureStart := 1
      TimestampStart := Timestamp
      start := A_TickCount
   }
   if CaptureStart
   {
      if (pSample != 0)
      {
         if (gap%ActualStreamIndex% = 1)
         {
            IMFAttributes_SetUINT32(pSample, MF_GUID(GUID, "MFSampleExtension_Discontinuity"), true)
            gap%ActualStreamIndex% := ""
         }
         IMFSample_SetSampleTime(pSample, Timestamp - TimestampStart)
         IMFSinkWriter_WriteSample(pSinkWriter, ActualStreamIndex, pSample)
      }
      else if (StreamFlags & MF_SOURCE_READERF_STREAMTICK := 256)
      {
         IMFSinkWriter_SendStreamTick(pSinkWriter, ActualStreamIndex, Timestamp - TimestampStart)
         gap%ActualStreamIndex% := 1
      }
   }
   if (pSample != 0)
   {
      Release(pSample)
      pSample := ""
   }
   if ((A_TickCount - start) >= CaptureDuration)
      break
}
IMFSinkWriter_Finalize(pSinkWriter)
hr := DllCall(NumGet(NumGet(MediaSourceVideo+0)+12*A_PtrSize), "ptr", MediaSourceVideo)
if hr or ErrorLevel
   _Error("error" MediaSourceVideo "MediaSourceVideo error: " hr "`nErrorLevel: " ErrorLevel)
Release(MediaSourceVideo)
if (audiodevice != "")
{
   hr := DllCall(NumGet(NumGet(MediaSourceAudio+0)+12*A_PtrSize), "ptr", MediaSourceAudio)
   if hr or ErrorLevel
      _Error("error" MediaSourceAudio "MediaSourceAudio error: " hr "`nErrorLevel: " ErrorLevel)
   release(MediaSourceAudio)
   hr := DllCall(NumGet(NumGet(AggSource+0)+12*A_PtrSize), "ptr", AggSource)
   if hr or ErrorLevel
      _Error("error" AggSource "AggSource error: " hr "`nErrorLevel: " ErrorLevel)
   Release(AggSource)
   MediaSourceAudio := AggSource := ""
}
Release(SourceReader)
Release(pSinkWriter)
SourceReader := MediaSourceVideo := pSinkWriter := ""
MFShutdown()
;msgbox done

Reload
ExitApp
Esc::ExitApp


LOAD_DLL_Mf_Mfplat_Mfreadwrite()
{
   if !DllCall("GetModuleHandle","str","Mf")
      DllCall("LoadLibrary","Str", "Mf.dll", "ptr")
   if !DllCall("GetModuleHandle","str","Mfplat")
      DllCall("LoadLibrary","Str", "Mfplat.dll", "ptr")
   if !DllCall("GetModuleHandle","str","Mfreadwrite")
      DllCall("LoadLibrary","Str", "Mfreadwrite.dll", "ptr")
}

MFStartup(version, dwFlags)
{
   hr := DllCall("Mfplat.dll\MFStartup", "uint", version, "uint", dwFlags)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

MFShutdown()
{
   hr := DllCall("Mfplat.dll\MFShutdown")
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

MFTEnumEx(guidCategory, Flags, pInputType, pOutputType)
{
   if (A_PtrSize = 8)
      hr := DllCall("Mfplat\MFTEnumEx", "ptr", guidCategory, "uint", Flags, "ptr", pInputType, "ptr", pOutputType, "ptr*", pppMFTActivate, "uint*", pnumMFTActivate)
   else
      hr := DllCall("Mfplat\MFTEnumEx", "uint64", NumGet(guidCategory+0, 0, "uint64"), "uint64", NumGet(guidCategory+0, 8, "uint64"), "uint", Flags, "ptr", pInputType, "ptr", pOutputType, "ptr*", pppMFTActivate, "uint*", pnumMFTActivate)
   loop % pnumMFTActivate
   {
      IMFActivate := NumGet(pppMFTActivate + (A_Index - 1)*A_PtrSize)
      if (A_Index = 1)
         hardware_encoder := IMFActivate_GetAllocatedString(IMFActivate, MF_GUID(GUID, "MFT_FRIENDLY_NAME_Attribute"))
      Release(IMFActivate)
   }
   DllCall("ole32\CoTaskMemFree", "ptr", pppMFTActivate)
   return hardware_encoder
}

MFCreateSinkWriterFromURL(pwszOutputURL, pByteStream, pAttributes, ByRef ppSinkWriter)
{
   hr := DllCall("Mfreadwrite.dll\MFCreateSinkWriterFromURL", "str", pwszOutputURL, "ptr", pByteStream, "ptr", pAttributes, "ptr*", ppSinkWriter)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

MFCreateSourceReaderFromMediaSource(pMediaSource, pAttributes, ByRef ppSourceReader)
{
   hr := DllCall("Mfreadwrite.dll\MFCreateSourceReaderFromMediaSource", "ptr", pMediaSource, "ptr", pAttributes, "ptr*", ppSourceReader)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

MFCreateMediaType(ByRef ppMFType)
{
   hr := DllCall("Mfplat.dll\MFCreateMediaType", "ptr*", ppMFType)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

MFCreateAttributes(ByRef ppMFAttributes, cInitialSize)
{
   hr := DllCall("Mfplat.dll\MFCreateAttributes", "ptr*", ppMFAttributes, "uint", cInitialSize)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

MFCreateSample(ByRef ppIMFSample)
{
   hr := DllCall("Mfplat.dll\MFCreateSample", "ptr*", ppIMFSample)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

MFCreateMemoryBuffer(cbMaxLength, ByRef ppBuffer)
{
   hr := DllCall("Mfplat.dll\MFCreateMemoryBuffer", "uint", cbMaxLength, "ptr*", ppBuffer)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

MFCopyImage(pDest, lDestStride, pSrc, lSrcStride, dwWidthInBytes, dwLines)
{
   hr := DllCall("Mfplat.dll\MFCopyImage", "ptr", pDest, "int", lDestStride, "ptr", pSrc, "int", lSrcStride, "uint", dwWidthInBytes, "uint", dwLines)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

MFEnumDeviceSources(pAttributes, ByRef pppSourceActivate, ByRef pcSourceActivate)
{
   hr := DllCall("Mf.dll\MFEnumDeviceSources", "ptr", pAttributes, "ptr*", pppSourceActivate, "uint*", pcSourceActivate)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

MFCreateCollection(ByRef ppIMFCollection)
{
   hr := DllCall("Mfplat.dll\MFCreateCollection", "ptr*", ppIMFCollection)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

MFCreateAggregateSource(pSourceCollection, ByRef ppAggSource)
{
   hr := DllCall("Mf.dll\MFCreateAggregateSource", "ptr", pSourceCollection, "ptr*", ppAggSource)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFSourceReader_SetCurrentMediaType(this, dwStreamIndex, pdwReserved, pMediaType)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "uint", dwStreamIndex, "uint", pdwReserved, "ptr", pMediaType)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFSourceReader_SetStreamSelection(this, dwStreamIndex, fSelected)
{
   hr := DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint", dwStreamIndex, "int", fSelected)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFSourceReader_GetNativeMediaType(this, dwStreamIndex, dwMediaTypeIndex, ByRef ppMediaType)
{
   hr := DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "uint", dwStreamIndex, "uint", dwMediaTypeIndex, "ptr*", ppMediaType)
   if hr or ErrorLevel
   {
      if (hr&=0xFFFFFFFF) = 0xC00D36B3   ; MF_E_INVALIDSTREAMNUMBER
         return "MF_E_INVALIDSTREAMNUMBER"
      if (hr&=0xFFFFFFFF) = 0xC00D36B9   ; MF_E_NO_MORE_TYPES
         return "MF_E_NO_MORE_TYPES"
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   }
}

IMFSourceReader_ReadSample(this, dwStreamIndex, dwControlFlags, ByRef pdwActualStreamIndex, ByRef pdwStreamFlags, ByRef pllTimestamp, ByRef ppSample)
{
   hr := DllCall(NumGet(NumGet(this+0)+9*A_PtrSize), "ptr", this, "uint", dwStreamIndex, "uint", dwControlFlags, "uint*", pdwActualStreamIndex, "uint*", pdwStreamFlags, "int64*", pllTimestamp, "ptr*", ppSample)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFAttributes_GetGUID(this, guidKey, ByRef pguidValue)
{
   VarSetCapacity(pguidValue, 16, 0)
   hr := DllCall(NumGet(NumGet(this+0)+10*A_PtrSize), "ptr", this, "ptr", guidKey, "ptr", &pguidValue)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   return &pguidValue
}

IMFAttributes_GetUINT64(this, guidKey, ByRef punValue)
{
   hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "ptr", guidKey, "uint64*", punValue)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFAttributes_GetUINT32(this, guidKey, ByRef punValue)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", guidKey, "uint*", punValue)
   if hr or ErrorLevel
   {
      if (hr&=0xFFFFFFFF) = 0xC00D36E6   ; MF_E_ATTRIBUTENOTFOUND
         return "MF_E_ATTRIBUTENOTFOUND"
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   }
}

IMFAttributes_SetUINT32(this, guidKey, unValue)
{
   hr := DllCall(NumGet(NumGet(this+0)+21*A_PtrSize), "ptr", this, "ptr", guidKey, "uint", unValue)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFAttributes_SetUINT64(this, guidKey, unValue)
{
   hr := DllCall(NumGet(NumGet(this+0)+22*A_PtrSize), "ptr", this, "ptr", guidKey, "uint64", unValue)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFAttributes_SetGUID(this, guidKey, guidValue)
{
   hr := DllCall(NumGet(NumGet(this+0)+24*A_PtrSize), "ptr", this, "ptr", guidKey, "ptr", guidValue)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFActivate_GetAllocatedString(this, guidKey)
{
   hr := DllCall(NumGet(NumGet(this+0)+13*A_PtrSize), "ptr", this, "ptr", guidKey, "ptr*", ppwszValue, "uint*", pcchLength)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
   AllocatedString := StrGet(ppwszValue, pcchLength, "UTF-16")
   DllCall("ole32\CoTaskMemFree", "ptr", ppwszValue)
   return AllocatedString
}

IMFActivate_ActivateObject(this, riid, ByRef ppv)
{
   GUID(riid, riid)
   hr := DllCall(NumGet(NumGet(this+0)+33*A_PtrSize), "ptr", this, "ptr", &riid, "ptr*", ppv)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFSinkWriter_SendStreamTick(this, dwStreamIndex, llTimestamp)
{
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "uint", dwStreamIndex, "int64", llTimestamp)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFSinkWriter_AddStream(this, pMediaTypeOut, ByRef pdwStreamIndex)
{
   hr := DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "ptr", pMediaTypeOut, "ptr*", pdwStreamIndex)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFSinkWriter_SetInputMediaType(this, dwStreamIndex, pInputMediaType, pEncodingParameters)
{
   hr := DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this, "uint", dwStreamIndex, "ptr", pInputMediaType, "ptr", pEncodingParameters)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFSinkWriter_BeginWriting(this)
{
   hr := DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFSinkWriter_WriteSample(this, dwStreamIndex, pSample)
{
   hr := DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this, "uint", dwStreamIndex, "ptr", pSample)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFSinkWriter_Finalize(this)
{
   hr := DllCall(NumGet(NumGet(this+0)+11*A_PtrSize), "ptr", this)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFMediaBuffer_Lock(this, ByRef ppbBuffer, ByRef pcbMaxLength, ByRef pcbCurrentLength)
{
   hr := DllCall(NumGet(NumGet(this+0)+3*A_PtrSize), "ptr", this, "ptr*", ppbBuffer, "uint*", pcbMaxLength, "uint*", pcbCurrentLength)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFMediaBuffer_Unlock(this)
{
   hr := DllCall(NumGet(NumGet(this+0)+4*A_PtrSize), "ptr", this)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFMediaBuffer_SetCurrentLength(this, cbCurrentLength)
{
   hr := DllCall(NumGet(NumGet(this+0)+6*A_PtrSize), "ptr", this, "uint", cbCurrentLength)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFMediaSource_Shutdown(this)
{
   hr := DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), "ptr", this)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFSample_AddBuffer(this, pBuffer)
{
   hr := DllCall(NumGet(NumGet(this+0)+42*A_PtrSize), "ptr", this, "ptr", pBuffer)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFSample_SetSampleTime(this, hnsSampleTime)
{
   hr := DllCall(NumGet(NumGet(this+0)+36*A_PtrSize), "ptr", this, "int64", hnsSampleTime)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFSample_GetSampleDuration(this, ByRef phnsSampleDuration)
{
   hr := DllCall(NumGet(NumGet(this+0)+37*A_PtrSize), "ptr", this, "int64*", phnsSampleDuration)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFSample_SetSampleDuration(this, hnsSampleDuration)
{
   hr := DllCall(NumGet(NumGet(this+0)+38*A_PtrSize), "ptr", this, "int64", hnsSampleDuration)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

IMFCollection_AddElement(this, pUnkElement)
{
   hr := DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "ptr", pUnkElement)
   if hr or ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

MF_GUID(ByRef GUID, name)
{
   static init:=1, _:={}
   if init
   {
      init:=0
      _.MF_MT_MAJOR_TYPE := [0x48eba18e, 0xf8c9, 0x4687, 0xbf, 0x11, 0x0a, 0x74, 0xc9, 0xf9, 0x6a, 0x8f]
      _.MF_MT_SUBTYPE := [0xf7e34c9a, 0x42e8, 0x4714, 0xb7, 0x4b, 0xcb, 0x29, 0xd7, 0x2c, 0x35, 0xe5]
      _.MF_MT_AVG_BITRATE := [0x20332624, 0xfb0d, 0x4d9e, 0xbd, 0x0d, 0xcb, 0xf6, 0x78, 0x6c, 0x10, 0x2e]
      _.MF_MT_INTERLACE_MODE := [0xe2724bb8, 0xe676, 0x4806, 0xb4, 0xb2, 0xa8, 0xd6, 0xef, 0xb4, 0x4c, 0xcd]
      _.MF_MT_FRAME_SIZE := [0x1652c33d, 0xd6b2, 0x4012, 0xb8, 0x34, 0x72, 0x03, 0x08, 0x49, 0xa3, 0x7d]
      _.MF_MT_FRAME_RATE := [0xc459a2e8, 0x3d2c, 0x4e44, 0xb1, 0x32, 0xfe, 0xe5, 0x15, 0x6c, 0x7b, 0xb0]
      _.MF_MT_PIXEL_ASPECT_RATIO := [0xc6376a1e, 0x8d0a, 0x4027, 0xbe, 0x45, 0x6d, 0x9a, 0x0a, 0xd3, 0x9b, 0xb6]
      _.MF_MT_AUDIO_AVG_BYTES_PER_SECOND := [0x1aab75c8, 0xcfef, 0x451c, 0xab, 0x95, 0xac, 0x03, 0x4b, 0x8e, 0x17, 0x31]
      _.MF_MT_AUDIO_BLOCK_ALIGNMENT := [0x322de230, 0x9eeb, 0x43bd, 0xab, 0x7a, 0xff, 0x41, 0x22, 0x51, 0x54, 0x1d]
      _.MF_MT_AUDIO_SAMPLES_PER_SECOND := [0x5faeeae7, 0x0290, 0x4c31, 0x9e, 0x8a, 0xc5, 0x34, 0xf6, 0x8d, 0x9d, 0xba]
      _.MF_MT_AUDIO_BITS_PER_SAMPLE := [0xf2deb57f, 0x40fa, 0x4764, 0xaa, 0x33, 0xed, 0x4f, 0x2d, 0x1f, 0xf6, 0x69]
      _.MF_MT_AUDIO_NUM_CHANNELS := [0x37e48bf5, 0x645e, 0x4c5b, 0x89, 0xde, 0xad, 0xa9, 0xe2, 0x9b, 0x69, 0x6a]
      _.MFT_CATEGORY_VIDEO_ENCODER := [0xf79eac7d, 0xe545, 0x4387, 0xbd, 0xee, 0xd6, 0x47, 0xd7, 0xbd, 0xe4, 0x2a]
      _.MF_TRANSCODE_CONTAINERTYPE := [0x150ff23f, 0x4abc, 0x478b, 0xac, 0x4f, 0xe1, 0x91, 0x6f, 0xba, 0x1c, 0xca]
      _.MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS := [0xa634a91c, 0x822b, 0x41b9, 0xa4, 0x94, 0x4d, 0xe4, 0x64, 0x36, 0x12, 0xb0]
      _.MFTranscodeContainerType_MPEG4 := [0xdc6cd05d, 0xb9d0, 0x40ef, 0xbd, 0x35, 0xfa, 0x62, 0x2c, 0x1a, 0xb2, 0x8a]
      _.MFT_FRIENDLY_NAME_Attribute := [0x314ffbae, 0x5b41, 0x4c95, 0x9c, 0x19, 0x4e, 0x7d, 0x58, 0x6f, 0xac, 0xe3]
      _.MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME := [0x60d0e559, 0x52f8, 0x4fa2, 0xbb, 0xce, 0xac, 0xdb, 0x34, 0xa8, 0xec, 0x1]
      _.MF_SINK_WRITER_DISABLE_THROTTLING := [0x08b845d8, 0x2b74, 0x4afe, 0x9d, 0x53, 0xbe, 0x16, 0xd2, 0xd5, 0xae, 0x4f]
      _.MF_LOW_LATENCY := [0x9c27891a, 0xed7a, 0x40e1, 0x88, 0xe8, 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee]
      _.MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE := [0xc60ac5fe, 0x252a, 0x478f, 0xa0, 0xef, 0xbc, 0x8f, 0xa5, 0xf7, 0xca, 0xd3]
      _.MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID := [0x14dd9a1c, 0x7cff, 0x41be, 0xb1, 0xb9, 0xba, 0x1a, 0xc6, 0xec, 0xb5, 0x71]
      _.MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID := [0x8ac3587a, 0x4ae7, 0x42d8, 0x99, 0xe0, 0x0a, 0x60, 0x13, 0xee, 0xf9, 0x0f]
      _.MF_SOURCE_READER_DISCONNECT_MEDIASOURCE_ON_SHUTDOWN := [0x56b67165, 0x219e, 0x456d, 0xa2, 0x2e, 0x2d, 0x30, 0x04, 0xc7, 0xfe, 0x56]
      _.MFSampleExtension_Discontinuity := [0x9cdf01d9, 0xa0f0, 0x43ba, 0xb0, 0x77, 0xea, 0xa0, 0x6c, 0xbd, 0x72, 0x8a]
      _.MFMediaType_Video := [0x73646976, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71]
      _.MFMediaType_Audio := [0x73647561, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71]
      _.MFAudioFormat_AAC := [0x1610, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71]
      _.MFAudioFormat_Float := [0x0003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71]
      _.MFAudioFormat_PCM := [0x0001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71]
      _.MFVideoFormat_H264 := [0x34363248, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71]   ; FCC("H264") = 0x34363248
      _.MFVideoFormat_RGB32 := [0x00000016, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71]
      _.MFVideoFormat_ARGB32 := [0x00000015, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71]
      _.MFVideoFormat_I420 := [0x30323449, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71]
      _.MFVideoFormat_IYUV := [0x56555949, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71]
      _.MFVideoFormat_NV12 := [0x3231564E, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71]
      _.MFVideoFormat_YUY2 := [0x32595559, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71]
      _.MFVideoFormat_YV12 := [0x32315659, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71]
      _.MFVideoFormat_RGB24 := [0x00000014, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71]
   }
   if _.haskey(name)
   {
      p := _[name]
      VarSetCapacity(GUID,16)
      ,NumPut(p.1+(p.2<<32)+(p.3<<48),GUID,0,"int64")
      ,NumPut(p.4+(p.5<<8)+(p.6<<16)+(p.7<<24)+(p.8<<32)+(p.9<<40)+(p.10<<48)+(p.11<<56),GUID,8,"int64")
      return &GUID
   }
   else return name
}

GUID(ByRef GUID, sGUID)
{
    VarSetCapacity(GUID, 16, 0)
    return DllCall("ole32\CLSIDFromString", "WStr", sGUID, "Ptr", &GUID) >= 0 ? &GUID : ""
}

FCC(var)
{
   c := StrSplit(var)
   msgbox % clipboard := Format("{:#x}",((Asc(c[1])&255)+((Asc(c[2])&255)<<8)+((Asc(c[3])&255)<<16)+((Asc(c[4])&255)<<24)))
}

Release(this)
{
   DllCall(NumGet(NumGet(this+0)+2*A_PtrSize), "ptr", this)
   if ErrorLevel
      _Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}

MemoryDifference(ptr1, ptr2, num)
{
   return DllCall("msvcrt\memcmp", "ptr", ptr1, "ptr", ptr2, "int", num) 
}

_Error(val)
{
   msgbox % val
   ExitApp
}
This code
https://www.autohotkey.com/boards/viewtopic.php?p=306894#p306894
I fixed.
But I think it is better to use code from this topic, because it uses asynchronous mode to get audiosamples and therefore does not depend on video fps.
Last edited by malcev on 14 Jan 2020, 07:31, edited 1 time in total.
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: Screen capture to video with Directx9 / Directx11 and Microsoft Media Foundation

14 Jan 2020, 07:00

After ca. 5-15 cycles I get MediaSourceVideo error: -1072873851
ErrorLevel: 0
and crash.

To the link. Yeah, I know you evolved that code, but I didn't updated "my code" for two reasons: It proved reliable and it had slightly less CPU usage...
Edit: I believe higher CPU usage was due to rotation needed for me and previous code didn't worked with "my workaround" (commenting hardware_encoder := MFTEnumEx(…)). Now it works! And the code in this thread too! So Thank You for the umpteenth time!
Edit2: To the reload test: I modified the code so at the end of the recording cycle temp.mp4 was renamed and I could access it during the test besides exit was waiting to the end of the recording cycle too. There was always a correct playable video file as well during the test as after the test.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Screen capture to video with Directx9 / Directx11 and Microsoft Media Foundation

14 Jan 2020, 07:36

I updated this code
https://www.autohotkey.com/boards/viewtopic.php?p=309538#p309538
What it shows now?
If You uncomment ; Rotate := true will it not work to You in this code?
https://www.autohotkey.com/boards/viewtopic.php?p=309209#p309209
If You comment hardware_encoder := MFTEnumEx(…) then You will capture without hardware encoding - I think it will be not good.
But if You uncomment Rotate := true then You will try to use hardware encoder.
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: Screen capture to video with Directx9 / Directx11 and Microsoft Media Foundation

14 Jan 2020, 08:08

First link: The code proved stable! Congrats! During the test Output video was o.k. audio couldn't hear because of such short recording (1s) and starting new recording over and over again, but at the end of the test (ca 10min) there was a correct video and audio! For both mic and soundcard!
Second link: No, It woks as you designed it! I just tested "my workaround" which at some point of the development (in the other thread) didn't work.
You wrote:You will capture without hardware encoding - I think it will be not good.
What would happen? Worse video quality (I noticed sometimes, when recording was static, somehow blur pic from time to time)?
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Screen capture to video with Directx9 / Directx11 and Microsoft Media Foundation

14 Jan 2020, 09:21

If You use hardware GPU encoding you do not consume CPU.
And if You use hardware CPU encoding it should have better performance than using software encoding.
But there are a lot of options and tweaks with codecs and encoders which can give You the better quality result.
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Screen capture to video with Directx9 / Directx11 and Microsoft Media Foundation

21 Jan 2020, 14:25

Added support for audio capture in Windows 7 and fixed bugs with checkCoordinates function and exit from main loop.
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: Screen capture to video with Directx9 / Directx11 and Microsoft Media Foundation

25 Jan 2020, 14:41

Hi!
Didn't have access to Win7, but today I did.
It was short test. I get IMFSinkWriter_SetInputMediaType error: -1072875852
ErrorLevel: 0
, despite uncommented ShowAllAudioDevicesNames := true, so I couldn't procede any more.

I tried DirectX9 on Win10 too: Video o.k., audio not o.k. - it starts seemingly then it distorts and fades away in a half of a second.

P.s.: Currently I do not have Web Cam on Win7 to test the script on the other thread!
malcev
Posts: 1769
Joined: 12 Aug 2014, 12:37

Re: Screen capture to video with Directx9 / Directx11 and Microsoft Media Foundation

25 Jan 2020, 19:55

Hi!
What shows hardware encoder in Windows7?
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: Screen capture to video with Directx9 / Directx11 and Microsoft Media Foundation

25 Jan 2020, 21:19

See attachment.
Edit: My settings: file := "test.mp4"
video_bitrate := 2000000
video_fps := 25
duration := 5
capture_cursor := true
audiodevice := "Stereo Mix (Realtek High Definition Audio)" ; happens to be the same as on my Win10
; x1 := 100, x2 := 1000, y1 := 100, y2 := 500
; ShowAllAudioDevicesNames := true
; CaptureCoordinatesWithCPU := true
; Rotate := true
Attachments
test.zip
(997.25 KiB) Downloaded 215 times
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: Screen capture to video with Directx9 / Directx11 and Microsoft Media Foundation

25 Jan 2020, 23:29

Same settings.
Attachments
test2.zip
(1.03 MiB) Downloaded 228 times
User avatar
rommmcek
Posts: 1470
Joined: 15 Aug 2014, 15:18

Re: Screen capture to video with Directx9 / Directx11 and Microsoft Media Foundation

26 Jan 2020, 17:19

I should tell you before, but Win7 on wich I do testing is a bit out of date (see attached pic)!
Attachments
test3.zip
(1.1 MiB) Downloaded 231 times

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: Basi, nitsik and 156 guests