Win10屏幕录制 (DirectX 11+DXGI)
; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=71533
#NoEnv
SetBatchLines -1
SetWorkingDir %A_ScriptDir%
file := "test.mp4"
video_bitrate := 2000000 ; 视频比特率
video_fps := 25 ; 视频FPS
duration := 5 ; 录制时长(秒)
capture_cursor := true ; 录制时包含光标
; audiodevice := "CABLE Output (VB-Audio Virtual Cable)" ; 虚拟内录声卡:https://vb-audio.com/Cable/
audiodevice := "麦克风 (Realtek High Definition Audio)" ; 不想录制声音可以删除此行
; audiodevice := "PC扬声器 (Realtek High Definition Audio)"
audioDelay := 80 ; 音频延迟
; x1 := 100, x2 := 1000, y1 := 100, y2 := 500 ; 设置录像屏幕坐标
; ShowAllAudioDevicesNames := true ; 显示当前电脑的音频设备名
; CaptureCoordinatesWithCPU := true ; 使用 CPU 捕获坐标
; Rotate := true ; 旋转
; UseSoftwareEncoding := true ; 使用软件编码
Global pSinkWriter, SourceReader, audioStreamIndex, Flush, IMFSourceReaderCallback
IDXGIFactory := CreateDXGIFactory()
if !IDXGIFactory {
MsgBox, 16, Error, Create IDXGIFactory failed.
ExitApp
}
Loop {
IDXGIFactory_EnumAdapters(IDXGIFactory, A_Index-1, IDXGIAdapter)
Loop {
hr := IDXGIAdapter_EnumOutputs(IDXGIAdapter, A_Index-1, IDXGIOutput)
if (hr = "DXGI_ERROR_NOT_FOUND")
break
VarSetCapacity(DXGI_OUTPUT_DESC, 88+A_PtrSize, 0)
, IDXGIOutput_GetDesc(IDXGIOutput, &DXGI_OUTPUT_DESC)
, Width := NumGet(DXGI_OUTPUT_DESC, 72, "int")
, Height := NumGet(DXGI_OUTPUT_DESC, 76, "int")
, AttachedToDesktop := NumGet(DXGI_OUTPUT_DESC, 80, "int")
if (AttachedToDesktop = 1)
break 2
}
}
if (AttachedToDesktop != 1) {
MsgBox, 16, 报错, 没有适配器连接到桌面
ExitApp
}
D3D11CreateDevice(IDXGIAdapter, D3D_DRIVER_TYPE_UNKNOWN := 0, 0, 0, 0, 0, D3D11_SDK_VERSION := 7, d3d_device, 0, d3d_context)
, IDXGIOutput1 := IDXGIOutput1_Query(IDXGIOutput)
, IDXGIOutput1_DuplicateOutput(IDXGIOutput1, d3d_device, Duplication)
, VarSetCapacity(DXGI_OUTDUPL_DESC, 36, 0)
, IDXGIOutputDuplication_GetDesc(Duplication, &DXGI_OUTDUPL_DESC)
, DesktopImageInSystemMemory := NumGet(DXGI_OUTDUPL_DESC, 32, "uint")
Sleep 50 ; 据我了解-需要一些睡眠才能成功连接到 IDXGIOutputDuplication 接口
VarSetCapacity(D3D11_TEXTURE2D_DESC, 44, 0)
, NumPut(width, D3D11_TEXTURE2D_DESC, 0, "uint") ; Width 宽度
, NumPut(height, D3D11_TEXTURE2D_DESC, 4, "uint") ; Height 高度
, NumPut(1, D3D11_TEXTURE2D_DESC, 8, "uint") ; MipLevels 级别
, NumPut(1, D3D11_TEXTURE2D_DESC, 12, "uint") ; ArraySize 数组大小
, NumPut(DXGI_FORMAT_B8G8R8A8_UNORM := 87, D3D11_TEXTURE2D_DESC, 16, "uint") ; Format 格式
, NumPut(1, D3D11_TEXTURE2D_DESC, 20, "uint") ; SampleDescCount 采样率
, NumPut(0, D3D11_TEXTURE2D_DESC, 24, "uint") ; SampleDescQuality 采样质量
, NumPut(D3D11_USAGE_STAGING := 3, D3D11_TEXTURE2D_DESC, 28, "uint") ; Usage 用法
, NumPut(0, D3D11_TEXTURE2D_DESC, 32, "uint") ; BindFlags 绑定标志
, NumPut(D3D11_CPU_ACCESS_READ := 0x20000 | D3D11_CPU_ACCESS_WRITE := 0x10000, D3D11_TEXTURE2D_DESC, 36, "uint") ; CPUAccessFlags CPU访问标志
, NumPut(0, D3D11_TEXTURE2D_DESC, 40, "uint") ; MiscFlags 杂项标志
, ID3D11Device_CreateTexture2D(d3d_device, &D3D11_TEXTURE2D_DESC, 0, staging_tex)
if (capture_cursor = true)
VarSetCapacity(D3D11_TEXTURE2D_DESC, 44, 0)
, NumPut(width, D3D11_TEXTURE2D_DESC, 0, "uint") ; Width 宽度
, NumPut(height, D3D11_TEXTURE2D_DESC, 4, "uint") ; Height 高度
, NumPut(1, D3D11_TEXTURE2D_DESC, 8, "uint") ; MipLevels 级别
, NumPut(1, D3D11_TEXTURE2D_DESC, 12, "uint") ; ArraySize 数组大小
, NumPut(DXGI_FORMAT_B8G8R8A8_UNORM := 87, D3D11_TEXTURE2D_DESC, 16, "uint") ; Format 格式
, NumPut(1, D3D11_TEXTURE2D_DESC, 20, "uint") ; SampleDescCount 采样率
, NumPut(0, D3D11_TEXTURE2D_DESC, 24, "uint") ; SampleDescQuality 采样质量
, NumPut(D3D11_USAGE_DEFAULT := 0, D3D11_TEXTURE2D_DESC, 28, "uint") ; Usage 用法
, NumPut(D3D11_BIND_RENDER_TARGET := 0x20, D3D11_TEXTURE2D_DESC, 32, "uint") ; BindFlags 绑定标志
, NumPut(0, D3D11_TEXTURE2D_DESC, 36, "uint") ; CPUAccessFlags CPU访问标志
, NumPut(D3D11_RESOURCE_MISC_GDI_COMPATIBLE := 0x200, D3D11_TEXTURE2D_DESC, 40, "uint") ; MiscFlags 杂项标志
, ID3D11Device_CreateTexture2D(d3d_device, &D3D11_TEXTURE2D_DESC, 0, gdi_tex)
LOAD_DLL_Mf_Mfplat_Mfreadwrite()
, MFStartup(version := 2, MFSTARTUP_FULL := 0)
if (ShowAllAudioDevicesNames != 1) {
if (UseSoftwareEncoding != 1)
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)
if (x1 != "")
checkCoordinates(x1, x2, y1, y2, hardware_encoder)
, width := x2-x1
, height := y2-y1
, VarSetCapacity(D3D11_BOX, 24, 0)
, NumPut(x1, D3D11_BOX, 0, "uint") ; left
, NumPut(y1, D3D11_BOX, 4, "uint") ; top
, NumPut(0, D3D11_BOX, 8, "uint") ; front
, NumPut(x2, D3D11_BOX, 12, "uint") ; right
, NumPut(y2, D3D11_BOX, 16, "uint") ; bottom
, NumPut(1, D3D11_BOX, 20, "uint") ; back
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 := ""
Loop 2 { ; 1 - input 输入, 2 - output 输出
MFCreateMediaType(pMediaType%A_Index%)
, IMFAttributes_SetGUID(pMediaType%A_Index%, MF_GUID(GUID, "MF_MT_MAJOR_TYPE"), MF_GUID(GUID1, "MFMediaType_Video"))
if (A_Index = 1) {
if !InStr(hardware_encoder, "NVIDIA") or ((x1 != "") and (CaptureCoordinatesWithCPU = true))
IMFAttributes_SetGUID(pMediaType%A_Index%, MF_GUID(GUID, "MF_MT_SUBTYPE"), MF_GUID(GUID1, "MFVideoFormat_RGB32"))
else
IMFAttributes_SetGUID(pMediaType%A_Index%, MF_GUID(GUID, "MF_MT_SUBTYPE"), MF_GUID(GUID1, "MFVideoFormat_ARGB32"))
} else
IMFAttributes_SetGUID(pMediaType%A_Index%, MF_GUID(GUID, "MF_MT_SUBTYPE"), MF_GUID(GUID1, "MFVideoFormat_H264"))
, IMFAttributes_SetUINT32(pMediaType%A_Index%, MF_GUID(GUID, "MF_MT_AVG_BITRATE"), video_bitrate)
IMFAttributes_SetUINT32(pMediaType%A_Index%, MF_GUID(GUID, "MF_MT_INTERLACE_MODE"), MFVideoInterlace_Progressive := 2)
, IMFAttributes_SetUINT64(pMediaType%A_Index%, MF_GUID(GUID, "MF_MT_FRAME_SIZE"), (width<<32)|height)
, IMFAttributes_SetUINT64(pMediaType%A_Index%, MF_GUID(GUID, "MF_MT_FRAME_RATE"), (video_fps<<32)|1)
, IMFAttributes_SetUINT64(pMediaType%A_Index%, MF_GUID(GUID, "MF_MT_PIXEL_ASPECT_RATIO"), (1<<32)|1)
}
IMFSinkWriter_AddStream(pSinkWriter, pMediaType2, videoStreamIndex)
, IMFSinkWriter_SetInputMediaType(pSinkWriter, videoStreamIndex, pMediaType1, 0)
, Release(pMediaType1)
, Release(pMediaType2)
, pMediaType1 := pMediaType2 := ""
}
if (audiodevice != "") or (ShowAllAudioDevicesNames = 1) {
NUM_CHANNELSMax := BITS_PER_SAMPLEMax := SAMPLES_PER_SECONDMax := BYTES_PER_SECONDMax := StreamNumberAudio := TypeNumberAudio := AudioSources := ""
, audiobasedevice := audiodevice
, IMFSourceReaderCallback := IMFSourceReaderCallback_new()
, MFCreateAttributes(pMFAttributes, 1)
, IMFAttributes_SetGUID(pMFAttributes, MF_GUID(GUID, "MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE"), MF_GUID(GUID1, "MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID"))
, MFEnumDeviceSources(pMFAttributes, 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 (ShowAllAudioDevicesNames = 1) {
basedevicename := devicename
Loop {
if !InStr(Audiodevicenames, """" devicename """`r`n")
break
devicename := basedevicename "[" A_Index+1 "]"
}
Audiodevicenames .= """" devicename """`r`n"
} else {
if RegexMatch(audiodevice, "\[(\d)]$", match) and (devicename = RegexReplace(audiodevice, "\[\d]$")) {
match1--
if (match1 = 0)
audiodevice := devicename
else
audiodevice := devicename "[" match1 "]"
}
if (devicename = audiodevice) and (MediaSourceAudio = "")
IMFActivate_ActivateObject(IMFActivate, IMFMediaSource := "{279a808d-aec7-40c8-9c6b-a6b492c78a66}", MediaSourceAudio)
}
Release(IMFActivate)
, IMFActivate := ""
}
DllCall("ole32\CoTaskMemFree", "ptr", pppSourceActivate)
, Release(pMFAttributes)
, pMFAttributes := ""
if (ShowAllAudioDevicesNames = 1) {
if (Audiodevicenames = "")
Audiodevicenames .= "None"
MsgBox 0x40, 音频设备名已存入剪贴板, % "Audio:`r`n" clipboard := Audiodevicenames
ExitApp
}
if (MediaSourceAudio = "") {
MsgBox 0x10, 请匹配你电脑对应的音频设备, % "找不到音频设备 - """ audiobasedevice """"
ExitApp
}
MFCreateAttributes(pMFAttributes, 1)
, IMFAttributes_SetUnknown(pMFAttributes, MF_GUID(GUID, "MF_SOURCE_READER_ASYNC_CALLBACK"), IMFSourceReaderCallback)
, MFCreateSourceReaderFromMediaSource(MediaSourceAudio, pMFAttributes, SourceReader)
Loop {
n := A_Index - 1
if (IMFSourceReader_GetNativeMediaType(SourceReader, n, 0, ppMediaType) = "MF_E_INVALIDSTREAMNUMBER")
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 (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 (StreamNumberAudio = "") {
Sort, AudioSources, U
MsgBox % "不支持当前的音频源:`n" AudioSources
ExitApp
}
IMFSourceReader_SetStreamSelection(SourceReader, MF_SOURCE_READER_ALL_STREAMS := 0xFFFFFFFE, false)
, IMFSourceReader_SetStreamSelection(SourceReader, StreamNumberAudio, true)
, Release(pMFAttributes)
, pMFAttributes := ""
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)
, video_frame_duration := 10000000/video_fps
, video_frame_count := duration*video_fps
, cbWidth := 4 * width
, cbBuffer := cbWidth * height
, rtStart := 0
, fps := 1000/video_fps
, CaptureDuration := duration*1000 - 2*fps
, VarSetCapacity(TIMECAPS, 8, 0)
, DllCall("winmm\timeGetDevCaps", "ptr", &TIMECAPS, "uint", 8)
, uPeriod := NumGet(TIMECAPS, 0, "uint")
, DllCall("Winmm\timeBeginPeriod", "uint", uPeriod)
MsgBox % "硬件编码器 - " ((hardware_encoder != "") ? hardware_encoder : "none")
Loop {
if (A_Index != 1) {
DllCall("QueryPerformanceCounter", "int64*", ATickCount)
, sleepDuration := fps*(A_Index-1) - (ATickCount - start)*1000/freq
, SleepEnd := ATickCount + sleepDuration*freq/1000
sleep % sleepDuration - 15
DllCall("QueryPerformanceCounter", "int64*", ATickCount)
if (ATickCount < SleepEnd)
DllCall("Sleep", "uint", (SleepEnd - ATickCount)*1000/freq)
}
VarSetCapacity(DXGI_OUTDUPL_FRAME_INFO, 48, 0)
if (A_Index = 1)
AcquireNextFrame := IDXGIOutputDuplication_AcquireNextFrame(Duplication, -1, &DXGI_OUTDUPL_FRAME_INFO, desktop_resource)
else
AcquireNextFrame := IDXGIOutputDuplication_AcquireNextFrame(Duplication, 0, &DXGI_OUTDUPL_FRAME_INFO, desktop_resource)
if (AcquireNextFrame != "DXGI_ERROR_WAIT_TIMEOUT") {
if (A_Index = 1) {
if (audiodevice != "") {
IMFSourceReader_ReadSample(SourceReader, MF_SOURCE_READER_ANY_STREAM := 0xFFFFFFFE, 0, 0, 0, 0, 0)
if (audioDelay > 0)
DllCall("Sleep", "uint", audioDelay)
}
DllCall("QueryPerformanceCounter", "int64*", start)
, DllCall("QueryPerformanceFrequency", "int64*", freq)
} else
Release(pSample)
, Release(pBuffer)
, pSample := pBuffer := ""
tex := ID3D11Texture2D_Query(desktop_resource)
if (capture_cursor = true)
VarSetCapacity(CURSORINFO, cbSize := 16 + A_PtrSize, 0)
, NumPut(cbSize, CURSORINFO, 0, "uint")
if (capture_cursor = true) and DllCall("GetCursorInfo", "ptr", &CURSORINFO) and (NumGet(CURSORINFO, 4, "uint") = 1) ; CURSOR_SHOWING 光标显示
{
hCursor := NumGet(CURSORINFO, 8)
, xCursor := NumGet(CURSORINFO, 8 + A_PtrSize, "int")
, yCursor := NumGet(CURSORINFO, 12 + A_PtrSize, "int")
, VarSetCapacity(ICONINFO, 8 + A_PtrSize*3, 0)
, DllCall("GetIconInfo", "ptr", hCursor, "ptr", &ICONINFO)
, xHotspot := NumGet(ICONINFO, 4, "uint")
, yHotspot := NumGet(ICONINFO, 8, "uint")
, hbmMask := NumGet(ICONINFO, 8 + A_PtrSize)
, hbmColor := NumGet(ICONINFO, 8 + A_PtrSize*2)
, ID3D11DeviceContext_CopyResource(d3d_context, gdi_tex, tex)
, gdi_Surface := IDXGISurface1_Query(gdi_tex)
, IDXGISurface1_GetDC(gdi_Surface, 0, hdc)
, DllCall("DrawIconEx", "ptr", hdc, "int", xCursor - xHotspot, "int", yCursor - yHotspot, "ptr", hCursor, "int", 0, "int", 0, "uint", 0, "ptr", 0, "uint", DI_NORMAL := 0x0003 | DI_DEFAULTSIZE := 0x0008)
if hbmMask
DllCall("DeleteObject", "ptr", hbmMask)
if hbmColor
DllCall("DeleteObject", "ptr", hbmColor)
hbmMask := hbmColor := ""
, IDXGISurface1_ReleaseDC(gdi_Surface, 0)
if (x1 = "")
ID3D11DeviceContext_CopyResource(d3d_context, staging_tex, gdi_tex)
else
ID3D11DeviceContext_CopySubresourceRegion(d3d_context, staging_tex, 0, 0, 0, 0, gdi_tex, 0, &D3D11_BOX) ; set region
ObjRelease(gdi_Surface)
, gdi_Surface := ""
} else {
if (x1 = "")
ID3D11DeviceContext_CopyResource(d3d_context, staging_tex, tex)
else
ID3D11DeviceContext_CopySubresourceRegion(d3d_context, staging_tex, 0, 0, 0, 0, tex, 0, &D3D11_BOX) ; set region 设置区域
}
VarSetCapacity(D3D11_MAPPED_SUBRESOURCE, 8+A_PtrSize, 0)
, ID3D11DeviceContext_Map(d3d_context, staging_tex, 0, D3D11_MAP_READ := 1, 0, &D3D11_MAPPED_SUBRESOURCE)
, pBits := NumGet(D3D11_MAPPED_SUBRESOURCE, 0, "ptr")
, pitch := NumGet(D3D11_MAPPED_SUBRESOURCE, A_PtrSize, "uint")
, MFCreateMemoryBuffer(cbBuffer, pBuffer)
, IMFMediaBuffer_Lock(pBuffer, pData, 0, 0)
if !InStr(hardware_encoder, "NVIDIA") or ((x1 != "") and (CaptureCoordinatesWithCPU = true)) or (Rotate = true)
MFCopyImage(pData, cbWidth, pBits+(height-1)*pitch, pitch*-1, cbWidth, height)
else
MFCopyImage(pData, cbWidth, pBits, pitch, cbWidth, height)
IMFMediaBuffer_Unlock(pBuffer)
, IMFMediaBuffer_SetCurrentLength(pBuffer, cbBuffer)
, MFCreateSample(pSample)
, IMFSample_AddBuffer(pSample, pBuffer)
}
IMFSample_SetSampleTime(pSample, rtStart)
, IMFSample_SetSampleDuration(pSample, video_frame_duration)
, IMFSinkWriter_WriteSample(pSinkWriter, streamIndex, pSample)
if (AcquireNextFrame != "DXGI_ERROR_WAIT_TIMEOUT")
ID3D11DeviceContext_Unmap(d3d_context, staging_tex, 0)
, ObjRelease(tex)
, Release(desktop_resource)
, tex := desktop_resource := ""
, IDXGIOutputDuplication_ReleaseFrame(duplication)
if ((ATickCount - start)/freq*1000 >= CaptureDuration) {
video_frame_countReal := A_Index
if (audiodevice != "") {
flush := 1
Loop {
if (flush = "")
break
sleep 50
}
}
break
}
rtStart += video_frame_duration
}
IMFSinkWriter_Finalize(pSinkWriter)
, DllCall("Winmm\timeEndPeriod", "uint", uPeriod)
if audiodevice
Release(MediaSourceAudio), MediaSourceAudio := ""
Release(pSample)
, Release(pBuffer)
, Release(pSinkWriter)
, Release(staging_tex)
, Release(d3d_device)
, Release(d3d_context)
, Release(duplication)
, Release(IDXGIAdapter)
, Release(IDXGIOutput)
, ObjRelease(IDXGIOutput1)
, Release(IDXGIFactory)
if (capture_cursor = true)
Release(gdi_tex), gdi_tex := ""
pSample := pBuffer := pSinkWriter := staging_tex := d3d_device := d3d_context := duplication := IDXGIAdapter := IDXGIOutput := IDXGIOutput1 := IDXGIFactory := ""
, MFShutdown()
MsgBox % "录制完毕`n`n" video_frame_countReal " 捕获`n" video_frame_count-video_frame_countReal " 丢帧"
ExitApp
; ======================== 以下是函数库 ========================
CreateDXGIFactory() {
if !DllCall("GetModuleHandle","str","DXGI")
DllCall("LoadLibrary","str","DXGI")
if !DllCall("GetModuleHandle","str","D3D11")
DllCall("LoadLibrary","str","D3D11")
GUID(riid, "{7b7166ec-21c7-44ae-b21a-c9ae321ae369}")
, hr := DllCall("DXGI\CreateDXGIFactory1", "ptr", &riid, "ptr*", ppFactory)
if hr or ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
return ppFactory
}
IDXGIFactory_EnumAdapters(this, Adapter, ByRef ppAdapter) {
hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "uint", Adapter, "ptr*", ppAdapter)
if hr or ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
IDXGIAdapter_EnumOutputs(this, Output, ByRef ppOutput) {
hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "uint", Output, "ptr*", ppOutput)
if hr or ErrorLevel
{
if !ErrorLevel {
if (hr&=0xFFFFFFFF) = 0x887A0002 ; DXGI_ERROR_NOT_FOUND
return "DXGI_ERROR_NOT_FOUND"
}
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
}
IDXGIAdapter_GetDesc(this, pDesc) {
hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "ptr", pDesc)
if hr or ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
IDXGIOutput_GetDesc(this, pDesc) {
hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", pDesc)
if hr or ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
IDXGIOutputDuplication_GetDesc(this, pDesc) {
DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), "ptr", this, "ptr", pDesc)
if ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
IDXGIOutputDuplication_AcquireNextFrame(this, TimeoutInMilliseconds, pFrameInfo, ByRef ppDesktopResource) {
hr := DllCall(NumGet(NumGet(this+0)+8*A_PtrSize), "ptr", this, "uint", TimeoutInMilliseconds, "ptr", pFrameInfo, "ptr*", ppDesktopResource)
if hr or ErrorLevel
{
if !ErrorLevel {
if (hr&=0xFFFFFFFF) = 0x887A0027 ; DXGI_ERROR_WAIT_TIMEOUT
return "DXGI_ERROR_WAIT_TIMEOUT"
}
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
}
D3D11CreateDevice(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, ByRef ppDevice, ByRef pFeatureLevel, ByRef ppImmediateContext) {
hr := DllCall("D3D11\D3D11CreateDevice", "ptr", pAdapter, "int", DriverType, "ptr", Software, "uint", Flags, "ptr", pFeatureLevels, "uint", FeatureLevels, "uint", SDKVersion, "ptr*", ppDevice, "ptr*", pFeatureLevel, "ptr*", ppImmediateContext)
if hr or ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
ID3D11Device_CreateTexture2D(this, pDesc, pInitialData, ByRef ppTexture2D) {
hr := DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), "ptr", this, "ptr", pDesc, "ptr", pInitialData, "ptr*", ppTexture2D)
if hr or ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
IDXGIOutputDuplication_MapDesktopSurface(this, pLockedRect) {
hr := DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), "ptr", this, "ptr", pLockedRect)
if hr or ErrorLevel
{
if !ErrorLevel {
if (hr&=0xFFFFFFFF) = 0x887A0004 ; DXGI_ERROR_UNSUPPORTED
return "DXGI_ERROR_UNSUPPORTED"
}
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
}
IDXGIOutputDuplication_UnMapDesktopSurface(this) {
hr := DllCall(NumGet(NumGet(this+0)+13*A_PtrSize), "ptr", this)
if hr or ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
IDXGIOutputDuplication_ReleaseFrame(this) {
hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this)
if hr or ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
IDXGIOutput1_DuplicateOutput(this, pDevice, ByRef ppOutputDuplication) {
hr := DllCall(NumGet(NumGet(this+0)+22*A_PtrSize), "ptr", this, "ptr", pDevice, "ptr*", ppOutputDuplication)
if hr or ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
IDXGISurface1_GetDC(this, Discard, ByRef phdc) {
hr := DllCall(NumGet(NumGet(this+0)+11*A_PtrSize), "ptr", this, "int", Discard, "ptr*", phdc)
if hr or ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
IDXGISurface1_ReleaseDC(this, pDirtyRect) {
hr := DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), "ptr", this, "ptr", pDirtyRect)
if hr or ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
IDXGIOutput1_Query(IDXGIOutput) {
hr := ComObjQuery(IDXGIOutput, "{00cddea8-939b-4b83-a340-a685226666cc}")
if !hr or ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
return hr
}
ID3D11Texture2D_Query(desktop_resource) {
hr := ComObjQuery(desktop_resource, "{6f15aaf2-d208-4e89-9ab4-489535d34f9c}")
if !hr or ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
return hr
}
IDXGISurface1_Query(Texture2D) {
hr := ComObjQuery(Texture2D, "{4AE63092-6327-4c1b-80AE-BFE12EA32B86}")
if !hr or ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
return hr
}
ID3D11DeviceContext_CopyResource(this, pDstResource, pSrcResource) {
hr := DllCall(NumGet(NumGet(this+0)+47*A_PtrSize), "ptr", this, "ptr", pDstResource, "ptr", pSrcResource)
if ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
ID3D11DeviceContext_CopySubresourceRegion(this, pDstResource, DstSubresource, DstX, DstY, DstZ, pSrcResource, SrcSubresource, pSrcBox) {
hr := DllCall(NumGet(NumGet(this+0)+46*A_PtrSize), "ptr", this, "ptr", pDstResource, "uint", DstSubresource, "uint", DstX, "uint", DstY, "uint", DstZ, "ptr", pSrcResource, "uint", SrcSubresource, "ptr", pSrcBox)
if ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
ID3D11DeviceContext_Map(this, pResource, Subresource, MapType, MapFlags, pMappedResource) {
hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), "ptr", this, "ptr", pResource, "uint", Subresource, "uint", MapType, "uint", MapFlags, "ptr", pMappedResource)
if hr or ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
ID3D11DeviceContext_Unmap(this, pResource, Subresource) {
hr := DllCall(NumGet(NumGet(this+0)+15*A_PtrSize), "ptr", this, "ptr", pResource, "uint", Subresource)
if ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
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 !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, pdwActualStreamIndex, pdwStreamFlags, pllTimestamp, ppSample) {
hr := DllCall(NumGet(NumGet(this+0)+9*A_PtrSize), "ptr", this, "uint", dwStreamIndex, "uint", dwControlFlags, "uint", pdwActualStreamIndex, "uint", pdwStreamFlags, "int", pllTimestamp, "ptr", ppSample)
if hr or ErrorLevel
_Error(A_ThisFunc " error: " hr "`nErrorLevel: " ErrorLevel)
}
IMFSourceReader_Flush(this, dwStreamIndex) {
hr := DllCall(NumGet(NumGet(this+0)+10*A_PtrSize), "ptr", this, "uint", dwStreamIndex)
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 !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)
}
IMFAttributes_SetUnknown(this, guidKey, pUnknown) {
hr := DllCall(NumGet(NumGet(this+0)+27*A_PtrSize), "ptr", this, "ptr", guidKey, "ptr", pUnknown)
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]
_.MF_SOURCE_READER_ASYNC_CALLBACK := [0x1e3dbeac, 0xbb43, 0x4c35, 0xb5, 0x07, 0xcd, 0x64, 0x44, 0x64, 0xc9, 0x65]
_.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
}
checkCoordinates(ByRef start1, ByRef end1, ByRef start2, ByRef end2, hardware_encoder:="") {
if !InStr(hardware_encoder, "NVIDIA") or ((x1 != "") and (CaptureCoordinatesWithCPU = true))
min1 := min2 := 33
else
min1 := 33, min2 := 17
max1 := A_ScreenWidth, max2 := A_ScreenHeight
Loop 2 {
if (end%A_Index% - start%A_Index% < min%A_Index%)
end%A_Index% := start%A_Index% + min%A_Index%
if (!InStr(hardware_encoder, "NVIDIA") or ((x1 != "") and (CaptureCoordinatesWithCPU = true))) and (mod(end%A_Index% - start%A_Index%, 2) != 0)
end%A_Index%++
if (end%A_Index% > max%A_Index%)
start%A_Index% += max%A_Index%-end%A_Index%
, end%A_Index% := max%A_Index%
}
}
IMFSourceReaderCallback_new() {
static VTBL := [ "QueryInterface"
, "AddRef"
, "Release"
, "OnReadSample" A_PtrSize
, "OnFlush"
, "OnEvent" ]
, heapSize := A_PtrSize*10
, heapOffset := A_PtrSize*9
, flags := (HEAP_GENERATE_EXCEPTIONS := 0x4) | (HEAP_NO_SERIALIZE := 0x1)
, HEAP_ZERO_MEMORY := 0x8
hHeap := DllCall("HeapCreate", "UInt", flags, "Ptr", 0, "Ptr", 0, "Ptr")
, addr := IMFSourceReaderCallback := DllCall("HeapAlloc", "Ptr", hHeap, "UInt", HEAP_ZERO_MEMORY, "Ptr", heapSize, "Ptr")
, addr := NumPut(addr + A_PtrSize, addr + 0)
for k, v in VTBL
addr := NumPut( RegisterSyncCallback("IMFSourceReaderCallback_" . v), addr + 0 )
NumPut(hHeap, IMFSourceReaderCallback + heapOffset)
Return IMFSourceReaderCallback
}
IMFSourceReaderCallback_QueryInterface(this, riid, ppvObject) {
static IID_IUnknown, IID_IMFSourceReaderCallback
if (!VarSetCapacity(IID_IUnknown)) {
VarSetCapacity(IID_IUnknown, 16), VarSetCapacity(IID_IMFSourceReaderCallback, 16)
, DllCall("ole32\CLSIDFromString", "WStr", "{00000000-0000-0000-C000-000000000046}", "Ptr", &IID_IUnknown)
, DllCall("ole32\CLSIDFromString", "WStr", "{deec8d99-fa1d-4d82-84c2-2c8969944867}", "Ptr", &IID_IMFSourceReaderCallback)
}
if (DllCall("ole32\IsEqualGUID", "Ptr", riid, "Ptr", &IID_IMFSourceReaderCallback) || DllCall("ole32\IsEqualGUID", "Ptr", riid, "Ptr", &IID_IUnknown)) {
NumPut(this, ppvObject+0, "Ptr")
, IMFSourceReaderCallback_AddRef(this)
return 0 ; S_OK
}
NumPut(0, ppvObject+0, "Ptr")
return 0x80004002 ; E_NOINTERFACE
}
IMFSourceReaderCallback_AddRef(this) {
static refOffset := A_PtrSize*8
NumPut(refCount := NumGet(this + refOffset, "UInt") + 1, this + refOffset, "UInt")
Return refCount
}
IMFSourceReaderCallback_Release(this) {
static refOffset := A_PtrSize*8
, heapOffset := A_PtrSize*9
NumPut(refCount := NumGet(this + refOffset, "UInt") - 1, this + refOffset, "UInt")
if (refCount = 0)
hHeap := NumGet(this + heapOffset)
, DllCall("HeapDestroy", "Ptr", hHeap)
Return refCount
}
/*
RegisterSyncCallback
A replacement for RegisterCallback for use with APIs that will call
the callback on the wrong thread. Synchronizes with the script's main
thread via a window message.
This version tries to emulate RegisterCallback as much as possible
without using RegisterCallback, so shares most of its limitations,
and some enhancements that could be made are not.
Other differences from v1 RegisterCallback:
- Variadic mode can't be emulated exactly, so is not supported.
- A_EventInfo can't be set in v1, so is not supported.
- Fast mode is not supported (the option is ignored).
- ByRef parameters are allowed (but ByRef is ignored).
- Throws instead of returning "" on failure.
*/
RegisterSyncCallback(FunctionName, Options:="", ParamCount:="") {
if !(fn := Func(FunctionName)) || fn.IsBuiltIn
throw Exception("Bad function", -1, FunctionName)
if (ParamCount == "")
ParamCount := fn.MinParams
if (ParamCount > fn.MaxParams && !fn.IsVariadic || ParamCount+0 < fn.MinParams)
throw Exception("Bad param count", -1, ParamCount)
static sHwnd := 0, sMsg, sSendMessageW
if !sHwnd {
Gui RegisterSyncCallback: +Parent%A_ScriptHwnd% +hwndsHwnd
OnMessage(sMsg := 0x8000, Func("RegisterSyncCallback_Msg"))
, sSendMessageW := DllCall("GetProcAddress", "ptr", DllCall("GetModuleHandle", "str", "user32.dll", "ptr"), "astr", "SendMessageW", "ptr")
}
if !(pcb := DllCall("GlobalAlloc", "uint", 0, "ptr", 96, "ptr"))
throw
DllCall("VirtualProtect", "ptr", pcb, "ptr", 96, "uint", 0x40, "uint*", 0)
, p := pcb
if (A_PtrSize = 8) {
/*
48 89 4c 24 08 ; mov [rsp+8], rcx
48 89 54'24 10 ; mov [rsp+16], rdx
4c 89 44 24 18 ; mov [rsp+24], r8
4c'89 4c 24 20 ; mov [rsp+32], r9
48 83 ec 28' ; sub rsp, 40
4c 8d 44 24 30 ; lea r8, [rsp+48] (arg 3, ¶ms)
49 b9 .. ; mov r9, .. (arg 4, operand to follow)
*/
p := NumPut(0x54894808244c8948, p+0)
, p := NumPut(0x4c182444894c1024, p+0)
, p := NumPut(0x28ec834820244c89, p+0)
, p := NumPut( 0xb9493024448d4c, p+0) - 1
, lParamPtr := p, p += 8
, p := NumPut(0xba, p+0, "char") ; mov edx, nmsg
, p := NumPut(sMsg, p+0, "int")
, p := NumPut(0xb9, p+0, "char") ; mov ecx, hwnd
, p := NumPut(sHwnd, p+0, "int")
, p := NumPut(0xb848, p+0, "short") ; mov rax, SendMessageW
, p := NumPut(sSendMessageW, p+0)
/*
ff d0 ; call rax
48 83 c4 28 ; add rsp, 40
c3 ; ret
*/
, p := NumPut(0x00c328c48348d0ff, p+0)
} else ; (A_PtrSize = 4)
p := NumPut(0x68, p+0, "char") ; push ... (lParam data)
, lParamPtr := p, p += 4
, p := NumPut(0x0824448d, p+0, "int") ; lea eax, [esp+8]
, p := NumPut(0x50, p+0, "char") ; push eax
, p := NumPut(0x68, p+0, "char") ; push nmsg
, p := NumPut(sMsg, p+0, "int")
, p := NumPut(0x68, p+0, "char") ; push hwnd
, p := NumPut(sHwnd, p+0, "int")
, p := NumPut(0xb8, p+0, "char") ; mov eax, &SendMessageW
, p := NumPut(sSendMessageW, p+0, "int")
, p := NumPut(0xd0ff, p+0, "short") ; call eax
, p := NumPut(0xc2, p+0, "char") ; ret argsize
, p := NumPut((InStr(Options, "C") ? 0 : ParamCount*4), p+0, "short")
NumPut(p, lParamPtr+0) ; To be passed as lParam.
, p := NumPut(&fn, p+0)
, p := NumPut(ParamCount, p+0, "int")
return pcb
}
RegisterSyncCallback_Msg(wParam, lParam) {
if (A_Gui != "RegisterSyncCallback")
return
fn := Object(NumGet(lParam + 0))
, paramCount := NumGet(lParam + A_PtrSize, "int")
, params := []
Loop % paramCount
params.Push(NumGet(wParam + A_PtrSize * (A_Index-1)))
return %fn%(params*)
}
IMFSourceReaderCallback_OnReadSample4(this_, hrStatus, dwStreamIndex, dwStreamFlags, llTimestamp, llTimestamp1, pSample) {
Static audioStart, gapAudio
critical
if hrStatus
_Error(A_ThisFunc " error: " hrStatus "`nErrorLevel: " ErrorLevel)
llTimestamp |= (llTimestamp1 << 32)
if (pSample != 0) {
if (gapAudio = 1)
IMFAttributes_SetUINT32(pSample, MF_GUID(GUID, "MFSampleExtension_Discontinuity"), true)
, gapAudio := ""
if (audioStart = "")
audioStart := llTimestamp
IMFSample_SetSampleTime(pSample, llTimestamp - audioStart)
, IMFSinkWriter_WriteSample(pSinkWriter, audioStreamIndex, pSample)
}
else if (dwStreamFlags & MF_SOURCE_READERF_STREAMTICK := 256) and (audioStart != "")
IMFSinkWriter_SendStreamTick(pSinkWriter, audioStreamIndex, llTimestamp - audioStart)
, gapAudio := 1
if (flush = "")
IMFSourceReader_ReadSample(SourceReader, MF_SOURCE_READER_ANY_STREAM := 0xFFFFFFFE, 0, 0, 0, 0, 0)
else
Release(IMFSourceReaderCallback)
, Release(SourceReader)
, SourceReader := IMFSourceReaderCallback := flush := audioStart := gapAudio := ""
return
}
IMFSourceReaderCallback_OnReadSample8(this_, hrStatus, dwStreamIndex, dwStreamFlags, llTimestamp, pSample) {
Static audioStart, gapAudio
critical
if hrStatus
_Error(A_ThisFunc " error: " hrStatus "`nErrorLevel: " ErrorLevel)
if (pSample != 0) {
if (gapAudio = 1)
IMFAttributes_SetUINT32(pSample, MF_GUID(GUID, "MFSampleExtension_Discontinuity"), true)
, gapAudio := ""
if (audioStart = "")
audioStart := llTimestamp
IMFSample_SetSampleTime(pSample, llTimestamp - audioStart)
, IMFSinkWriter_WriteSample(pSinkWriter, audioStreamIndex, pSample)
} else if (dwStreamFlags & MF_SOURCE_READERF_STREAMTICK := 256) and (audioStart != "") {
IMFSinkWriter_SendStreamTick(pSinkWriter, audioStreamIndex, llTimestamp - audioStart)
gapAudio := 1
}
if (flush = "")
IMFSourceReader_ReadSample(SourceReader, MF_SOURCE_READER_ANY_STREAM := 0xFFFFFFFE, 0, 0, 0, 0, 0)
else {
Release(IMFSourceReaderCallback)
, Release(SourceReader)
, SourceReader := IMFSourceReaderCallback := flush := audioStart := gapAudio := ""
}
return
}
IMFSourceReaderCallback_OnFlush(this_, dwStreamIndex) {
return
}
IMFSourceReaderCallback_OnEvent(this_) {
return
}
声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。

评论(0)