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)