diff options
| author | 2025-02-19 13:40:38 -0500 | |
|---|---|---|
| committer | 2025-02-19 13:40:38 -0500 | |
| commit | 2bee71a7e032c0972418e324bb1d7e6b02330b18 (patch) | |
| tree | fa5819e9d9efe75cbc6f50d462dd0eb6bd19b6a2 /subprojects/packagefiles | |
| parent | b36f022defd8d4ec5a8c29578bb583bea05dfbb6 (diff) | |
| download | camu-2bee71a7e032c0972418e324bb1d7e6b02330b18.tar.gz camu-2bee71a7e032c0972418e324bb1d7e6b02330b18.tar.bz2 camu-2bee71a7e032c0972418e324bb1d7e6b02330b18.zip | |
Server resource unload, many tweaks and fixes
- Initial liana client preferences.
- Hook up libplacebo dx11 backend.
- Make usage of FFmpeg hardware decoding api make some sense.
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'subprojects/packagefiles')
6 files changed, 371 insertions, 32 deletions
diff --git a/subprojects/packagefiles/ffmpeg/meson.build b/subprojects/packagefiles/ffmpeg/meson.build index 33dbd30..05940c4 100644 --- a/subprojects/packagefiles/ffmpeg/meson.build +++ b/subprojects/packagefiles/ffmpeg/meson.build @@ -1,11 +1,14 @@ project('ffmpeg', 'c', version: '7.1', meson_version: '>=0.57.0') +ffmpeg_version_string = meson.project_version() + compiler = meson.get_compiler('c') cpu = target_machine.cpu_family() is_64bit = (cpu == 'x86_64' or cpu == 'aarch64') is_debug = get_option('buildtype').startswith('debug') is_minsize = get_option('buildtype') == 'minsize' +is_linux = host_machine.system() == 'linux' is_windows = host_machine.system() == 'windows' is_msvc = compiler.get_id() == 'msvc' or compiler.get_id() == 'clang-cl' is_mingw = is_windows and not is_msvc @@ -45,6 +48,7 @@ endif decoders = 'flac,mp3,mp3float,aac,opus,vorbis,alac,mjpeg,jpeg2000,gif,h264,hevc,av1,vp9,vp8' decoders += ',pcm_f32be,pcm_s32be,pcm_s32le,pcm_s32le_planar,pcm_f32le,pcm_s24be,pcm_s24le,pcm_s16be,pcm_s16be_planar,pcm_s16le,pcm_s16le_planar' +decoders += ',dca' #decoders += ',pcm_dvd,mpegvideo,mpeg2video' #decoders += ',ass,srt' @@ -53,6 +57,7 @@ demuxers = 'flac,mp3,aac,wav,image2,mjpeg,image2pipe,image_jpeg_pipe,gif,matrosk #demuxers += ',ass,srt' parsers = 'aac,opus,mjpeg,jpeg2000,gif,h264,hevc,av1,vp9,vp8' +parsers += ',dca' #parsers += ',mpegaudio,mpegvideo,dvd_nav' extra_options += ['--enable-zlib'] @@ -63,16 +68,24 @@ parsers += ',png' bsfs = 'extract_extradata,mp3_header_decompress' hwaccels = '' -if is_windows and get_option('sink-use-vulkan') +if get_option('sink-use-vulkan') extra_options += ['--enable-vulkan'] hwaccels += 'h264_vulkan,hevc_vulkan,av1_vulkan' - #extra_options += ['--enable-d3d11va', '--enable-d3d12va', '--enable-dxva2'] - #hwaccels += 'h264_dxva2,' +elif is_windows + extra_options += ['--enable-d3d11va'] + #extra_options += ['--enable-d3d11va', '--enable-dxva2'] + hwaccels += 'h264_d3d11va,hevc_d3d11va,av1_d3d11va,vp9_d3d11va' + hwaccels += ',h264_d3d11va2,hevc_d3d11va2,av1_d3d11va2,vp9_d3d11va2' + #hwaccels += ',h264_dxva2,hevc_dxva2,av1_dxva2,vp9_dxva2' elif is_android extra_options += ['--enable-jni', '--enable-mediacodec'] decoders += ',h264_mediacodec,hevc_mediacodec,av1_mediacodec' -else - extra_options += ['--disable-vulkan', '--disable-vdpau', '--disable-vaapi'] +elif is_linux + extra_options += ['--enable-vaapi'] +endif + +if hwaccels != '' + extra_options += ['--enable-hwaccel=' + hwaccels] endif protocols = 'file,cache' @@ -121,6 +134,7 @@ proj = ext_proj.add_project('configure', '--enable-avutil', '--enable-avformat', '--enable-avcodec', + '--enable-avdevice', '--enable-swresample', '--enable-swscale', '--disable-indevs', @@ -129,9 +143,8 @@ proj = ext_proj.add_project('configure', '--enable-decoder=' + decoders, '--enable-parser=' + parsers, '--enable-bsf=' + bsfs, - '--enable-hwaccel=' + hwaccels, '--enable-protocol=' + protocols, - extra_options, + extra_options ], cross_configure_options: ['--enable-cross-compile'], verbose: true) @@ -139,6 +152,7 @@ proj = ext_proj.add_project('configure', avutil = proj.dependency('avutil') avformat = proj.dependency('avformat') avcodec = proj.dependency('avcodec') +avdevice = proj.dependency('avdevice') swresample = proj.dependency('swresample') swscale = proj.dependency('swscale') -ffmpeg_inc_dep = declare_dependency(include_directories: include_directories('.', 'build/')) +ffmpeg_include = declare_dependency(include_directories: include_directories('.', 'build/')) diff --git a/subprojects/packagefiles/miniaudio/miniaudio_pulse_flush.diff b/subprojects/packagefiles/miniaudio/miniaudio_pulse_flush.diff index 41ea436..293ba94 100644 --- a/subprojects/packagefiles/miniaudio/miniaudio_pulse_flush.diff +++ b/subprojects/packagefiles/miniaudio/miniaudio_pulse_flush.diff @@ -1,26 +1,3 @@ -diff --git a/extras/miniaudio_split/miniaudio.c b/extras/miniaudio_split/miniaudio.c -index bb97e1f..43bf4f1 100644 ---- a/extras/miniaudio_split/miniaudio.c -+++ b/extras/miniaudio_split/miniaudio.c -@@ -4763,7 +4763,7 @@ static void ma_thread_wait__posix(ma_thread* pThread) - static ma_result ma_mutex_init__posix(ma_mutex* pMutex) - { - int result; -- -+ - if (pMutex == NULL) { - return MA_INVALID_ARGS; - } -@@ -19374,7 +19374,8 @@ static ma_result ma_device_stop__pulse(ma_device* pDevice) - happens, draining never completes and we get stuck here. For now I'm disabling draining of - the device so we don't just freeze the application. - */ -- #if 0 -+ #if 1 -+ ma_bool32 wasSuccessful = MA_FALSE; - ma_pa_operation* pOP = ((ma_pa_stream_drain_proc)pDevice->pContext->pulse.pa_stream_drain)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, ma_pulse_operation_complete_callback, &wasSuccessful); - ma_wait_for_operation_and_unref__pulse(pDevice->pContext, pDevice->pulse.pMainLoop, pOP); - #endif diff --git a/miniaudio.h b/miniaudio.h index a5673ac..cf73a54 100644 --- a/miniaudio.h @@ -29,7 +6,7 @@ index a5673ac..cf73a54 100644 static ma_result ma_mutex_init__posix(ma_mutex* pMutex) { int result; -- +- + if (pMutex == NULL) { return MA_INVALID_ARGS; diff --git a/subprojects/packagefiles/miniaudio/miniaudio_wasapi_clock_service.diff b/subprojects/packagefiles/miniaudio/miniaudio_wasapi_clock_service.diff new file mode 100644 index 0000000..4398e31 --- /dev/null +++ b/subprojects/packagefiles/miniaudio/miniaudio_wasapi_clock_service.diff @@ -0,0 +1,151 @@ +diff --git a/miniaudio.h b/miniaudio.h +index 3879cd3..58a16a6 100644 +--- a/miniaudio.h ++++ b/miniaudio.h +@@ -7312,6 +7312,7 @@ typedef struct + ma_device_type deviceType; + void* pAudioClient; + void** ppAudioClientService; ++ void** ppAudioClock; + ma_result* pResult; /* The result from creating the audio client service. */ + } createAudioClient; + struct +@@ -7821,6 +7822,7 @@ struct ma_device + /*IAudioClient**/ ma_ptr pAudioClientCapture; + /*IAudioRenderClient**/ ma_ptr pRenderClient; + /*IAudioCaptureClient**/ ma_ptr pCaptureClient; ++ /*IAudioClock**/ ma_ptr pAudioClock; + /*IMMDeviceEnumerator**/ ma_ptr pDeviceEnumerator; /* Used for IMMNotificationClient notifications. Required for detecting default device changes. */ + ma_IMMNotificationClient notificationClient; + /*HANDLE*/ ma_handle hEventPlayback; /* Auto reset. Initialized to signaled. */ +@@ -20305,6 +20307,8 @@ static const IID MA_IID_IAudioClient2 = {0x726778CD, + static const IID MA_IID_IAudioClient3 = {0x7ED4EE07, 0x8E67, 0x4CD4, {0x8C, 0x1A, 0x2B, 0x7A, 0x59, 0x87, 0xAD, 0x42}}; /* 7ED4EE07-8E67-4CD4-8C1A-2B7A5987AD42 = __uuidof(IAudioClient3) */ + static const IID MA_IID_IAudioRenderClient = {0xF294ACFC, 0x3146, 0x4483, {0xA7, 0xBF, 0xAD, 0xDC, 0xA7, 0xC2, 0x60, 0xE2}}; /* F294ACFC-3146-4483-A7BF-ADDCA7C260E2 = __uuidof(IAudioRenderClient) */ + static const IID MA_IID_IAudioCaptureClient = {0xC8ADBD64, 0xE71E, 0x48A0, {0xA4, 0xDE, 0x18, 0x5C, 0x39, 0x5C, 0xD3, 0x17}}; /* C8ADBD64-E71E-48A0-A4DE-185C395CD317 = __uuidof(IAudioCaptureClient) */ ++static const IID MA_IID_IAudioClock = {0xCD63314F, 0x3FBA, 0x4a1b, {0x81, 0x2C, 0xEF, 0x96, 0x35, 0x87, 0x28, 0xE7}}; /* CD63314F-3FBA-4a1b-812C-EF96358728E7 = _uuidof(IAudioClock) */ ++static const IID MA_IID_IAudioClock2 = {0x6f49ff73, 0x6727, 0x49ac, {0xa0, 0x08, 0xd9, 0x8c, 0xf5, 0xe7, 0x00, 0x48}}; /* 6f49ff73-6727-49ac-a008-d98cf5e70048 = __uuidof(IAudioClock2) */ + static const IID MA_IID_IMMNotificationClient = {0x7991EEC9, 0x7E89, 0x4D85, {0x83, 0x90, 0x6C, 0x70, 0x3C, 0xEC, 0x60, 0xC0}}; /* 7991EEC9-7E89-4D85-8390-6C703CEC60C0 = __uuidof(IMMNotificationClient) */ + #if !defined(MA_WIN32_DESKTOP) && !defined(MA_WIN32_GDK) + static const IID MA_IID_DEVINTERFACE_AUDIO_RENDER = {0xE6327CAD, 0xDCEC, 0x4949, {0xAE, 0x8A, 0x99, 0x1E, 0x97, 0x6A, 0x79, 0xD2}}; /* E6327CAD-DCEC-4949-AE8A-991E976A79D2 */ +@@ -20334,6 +20338,7 @@ typedef struct ma_IAudioClient2 ma_IAudioClient2; + typedef struct ma_IAudioClient3 ma_IAudioClient3; + typedef struct ma_IAudioRenderClient ma_IAudioRenderClient; + typedef struct ma_IAudioCaptureClient ma_IAudioCaptureClient; ++typedef struct ma_IAudioClock ma_IAudioClock; + + typedef ma_int64 MA_REFERENCE_TIME; + +@@ -20745,6 +20750,28 @@ static MA_INLINE HRESULT ma_IAudioCaptureClient_GetBuffer(ma_IAudioCaptureClient + static MA_INLINE HRESULT ma_IAudioCaptureClient_ReleaseBuffer(ma_IAudioCaptureClient* pThis, ma_uint32 numFramesRead) { return pThis->lpVtbl->ReleaseBuffer(pThis, numFramesRead); } + static MA_INLINE HRESULT ma_IAudioCaptureClient_GetNextPacketSize(ma_IAudioCaptureClient* pThis, ma_uint32* pNumFramesInNextPacket) { return pThis->lpVtbl->GetNextPacketSize(pThis, pNumFramesInNextPacket); } + ++ ++/* IAudioClock */ ++typedef struct ++{ ++ /* IUnknown */ ++ HRESULT (STDMETHODCALLTYPE * QueryInterface)(ma_IAudioCaptureClient* pThis, const IID* const riid, void** ppObject); ++ ULONG (STDMETHODCALLTYPE * AddRef) (ma_IAudioCaptureClient* pThis); ++ ULONG (STDMETHODCALLTYPE * Release) (ma_IAudioCaptureClient* pThis); ++ ++ /* IAudioClock */ ++ HRESULT (STDMETHODCALLTYPE * GetFrequency)(ma_IAudioClock* pThis, ma_uint64* pu64Frequency); ++ HRESULT (STDMETHODCALLTYPE * GetPosition)(ma_IAudioClock* pThis, ma_uint64* pu64Position, ma_uint64* pu64QPCPosition); ++ HRESULT (STDMETHODCALLTYPE * GetCharacteristics)(ma_IAudioClock* pThis, DWORD* pdwCharacteristics); ++} ma_IAudioClockVtbl; ++struct ma_IAudioClock ++{ ++ ma_IAudioClockVtbl* lpVtbl; ++}; ++static MA_INLINE HRESULT ma_IAudioClock_GetFrequency(ma_IAudioClock* pThis, ma_uint64* pu64Frequency) { return pThis->lpVtbl->GetFrequency(pThis, pu64Frequency); } ++static MA_INLINE HRESULT ma_IAudioClock_GetPosition(ma_IAudioClock* pThis, ma_uint64* pu64Position, ma_uint64* pu64QPCPosition) { return pThis->lpVtbl->GetPosition(pThis, pu64Position, pu64QPCPosition); } ++static MA_INLINE HRESULT ma_IAudioClock_GetCharacteristics(ma_IAudioClock* pThis, DWORD* pdwCharacteristics) { return pThis->lpVtbl->GetCharacteristics(pThis, pdwCharacteristics); } ++ + #if defined(MA_WIN32_UWP) + /* mmdevapi Functions */ + typedef HRESULT (WINAPI * MA_PFN_ActivateAudioInterfaceAsync)(const wchar_t* deviceInterfacePath, const IID* riid, MA_PROPVARIANT* activationParams, ma_IActivateAudioInterfaceCompletionHandler* completionHandler, ma_IActivateAudioInterfaceAsyncOperation** activationOperation); +@@ -21248,6 +21275,7 @@ static ma_thread_result MA_THREADCALL ma_context_command_thread__wasapi(void* pU + } else { + *cmd.data.createAudioClient.pResult = ma_result_from_HRESULT(ma_IAudioClient_GetService((ma_IAudioClient*)cmd.data.createAudioClient.pAudioClient, &MA_IID_IAudioCaptureClient, cmd.data.createAudioClient.ppAudioClientService)); + } ++ ma_IAudioClient_GetService((ma_IAudioClient*)cmd.data.createAudioClient.pAudioClient, &MA_IID_IAudioClock, cmd.data.createAudioClient.ppAudioClock); + } break; + + case MA_CONTEXT_COMMAND_RELEASE_IAUDIOCLIENT__WASAPI: +@@ -21286,7 +21314,7 @@ static ma_thread_result MA_THREADCALL ma_context_command_thread__wasapi(void* pU + return (ma_thread_result)0; + } + +-static ma_result ma_device_create_IAudioClient_service__wasapi(ma_context* pContext, ma_device_type deviceType, ma_IAudioClient* pAudioClient, void** ppAudioClientService) ++static ma_result ma_device_create_IAudioClient_service__wasapi(ma_context* pContext, ma_device_type deviceType, ma_IAudioClient* pAudioClient, void** ppAudioClientService, void **ppAudioClock) + { + ma_result result; + ma_result cmdResult; +@@ -21294,6 +21322,7 @@ static ma_result ma_device_create_IAudioClient_service__wasapi(ma_context* pCont + cmd.data.createAudioClient.deviceType = deviceType; + cmd.data.createAudioClient.pAudioClient = (void*)pAudioClient; + cmd.data.createAudioClient.ppAudioClientService = ppAudioClientService; ++ cmd.data.createAudioClient.ppAudioClock = ppAudioClock; + cmd.data.createAudioClient.pResult = &cmdResult; /* Declared locally, but won't be dereferenced after this function returns since execution of the command will wait here. */ + + result = ma_context_post_command__wasapi(pContext, &cmd); /* This will not return until the command has actually been run. */ +@@ -22121,6 +22150,7 @@ typedef struct + ma_IAudioClient* pAudioClient; + ma_IAudioRenderClient* pRenderClient; + ma_IAudioCaptureClient* pCaptureClient; ++ ma_IAudioClock* pAudioClock; + ma_format formatOut; + ma_uint32 channelsOut; + ma_uint32 sampleRateOut; +@@ -22160,6 +22190,7 @@ static ma_result ma_device_init_internal__wasapi(ma_context* pContext, ma_device + pData->pAudioClient = NULL; + pData->pRenderClient = NULL; + pData->pCaptureClient = NULL; ++ pData->pAudioClock = NULL; + + streamFlags = MA_AUDCLNT_STREAMFLAGS_EVENTCALLBACK; + if (!pData->noAutoConvertSRC && pData->sampleRateIn != 0 && pData->shareMode != ma_share_mode_exclusive) { /* <-- Exclusive streams must use the native sample rate. */ +@@ -22530,9 +22561,9 @@ static ma_result ma_device_init_internal__wasapi(ma_context* pContext, ma_device + + + if (deviceType == ma_device_type_playback) { +- result = ma_device_create_IAudioClient_service__wasapi(pContext, deviceType, (ma_IAudioClient*)pData->pAudioClient, (void**)&pData->pRenderClient); ++ result = ma_device_create_IAudioClient_service__wasapi(pContext, deviceType, (ma_IAudioClient*)pData->pAudioClient, (void**)&pData->pRenderClient, (void**)&pData->pAudioClock); + } else { +- result = ma_device_create_IAudioClient_service__wasapi(pContext, deviceType, (ma_IAudioClient*)pData->pAudioClient, (void**)&pData->pCaptureClient); ++ result = ma_device_create_IAudioClient_service__wasapi(pContext, deviceType, (ma_IAudioClient*)pData->pAudioClient, (void**)&pData->pCaptureClient, (void**)&pData->pAudioClock); + } + + /*if (FAILED(hr)) {*/ +@@ -22693,6 +22724,7 @@ static ma_result ma_device_reinit__wasapi(ma_device* pDevice, ma_device_type dev + if (deviceType == ma_device_type_capture || deviceType == ma_device_type_loopback) { + pDevice->wasapi.pAudioClientCapture = data.pAudioClient; + pDevice->wasapi.pCaptureClient = data.pCaptureClient; ++ pDevice->wasapi.pAudioClock = data.pAudioClock; + + pDevice->capture.internalFormat = data.formatOut; + pDevice->capture.internalChannels = data.channelsOut; +@@ -22714,6 +22746,7 @@ static ma_result ma_device_reinit__wasapi(ma_device* pDevice, ma_device_type dev + if (deviceType == ma_device_type_playback) { + pDevice->wasapi.pAudioClientPlayback = data.pAudioClient; + pDevice->wasapi.pRenderClient = data.pRenderClient; ++ pDevice->wasapi.pAudioClock = data.pAudioClock; + + pDevice->playback.internalFormat = data.formatOut; + pDevice->playback.internalChannels = data.channelsOut; +@@ -22783,6 +22816,7 @@ static ma_result ma_device_init__wasapi(ma_device* pDevice, const ma_device_conf + + pDevice->wasapi.pAudioClientCapture = data.pAudioClient; + pDevice->wasapi.pCaptureClient = data.pCaptureClient; ++ pDevice->wasapi.pAudioClock = data.pAudioClock; + pDevice->wasapi.originalPeriodSizeInMilliseconds = pDescriptorCapture->periodSizeInMilliseconds; + pDevice->wasapi.originalPeriodSizeInFrames = pDescriptorCapture->periodSizeInFrames; + pDevice->wasapi.originalPeriods = pDescriptorCapture->periodCount; +@@ -22862,6 +22896,7 @@ static ma_result ma_device_init__wasapi(ma_device* pDevice, const ma_device_conf + + pDevice->wasapi.pAudioClientPlayback = data.pAudioClient; + pDevice->wasapi.pRenderClient = data.pRenderClient; ++ pDevice->wasapi.pAudioClock = data.pAudioClock; + pDevice->wasapi.originalPeriodSizeInMilliseconds = pDescriptorPlayback->periodSizeInMilliseconds; + pDevice->wasapi.originalPeriodSizeInFrames = pDescriptorPlayback->periodSizeInFrames; + pDevice->wasapi.originalPeriods = pDescriptorPlayback->periodCount; diff --git a/subprojects/packagefiles/miniaudio/miniaudio_wasapi_drain.diff b/subprojects/packagefiles/miniaudio/miniaudio_wasapi_drain.diff new file mode 100644 index 0000000..eb6bd24 --- /dev/null +++ b/subprojects/packagefiles/miniaudio/miniaudio_wasapi_drain.diff @@ -0,0 +1,44 @@ +commit 7ead713f6b67c0247e248de3709cc383da19bdea +Author: Andrew Opalach <andrew@akon.city> +Date: Sun Feb 2 15:24:33 2025 -0500 + + WASAPI: Fix drain on device stop + +diff --git a/miniaudio.h b/miniaudio.h +index fced0d2..22b0e4f 100644 +--- a/miniaudio.h ++++ b/miniaudio.h +@@ -23133,13 +23133,12 @@ static ma_result ma_device_stop__wasapi_nolock(ma_device* pDevice) + */ + if (ma_atomic_bool32_get(&pDevice->wasapi.isStartedPlayback)) { + /* We need to make sure we put a timeout here or else we'll risk getting stuck in a deadlock in some cases. */ +- DWORD waitTime = pDevice->wasapi.actualBufferSizeInFramesPlayback / pDevice->playback.internalSampleRate; ++ DWORD waitTime = pDevice->wasapi.actualBufferSizeInFramesPlayback / (pDevice->playback.internalSampleRate / 1000); + + if (pDevice->playback.shareMode == ma_share_mode_exclusive) { + WaitForSingleObject((HANDLE)pDevice->wasapi.hEventPlayback, waitTime); +- } +- else { +- ma_uint32 prevFramesAvaialablePlayback = (ma_uint32)-1; ++ } else { ++ ma_uint32 prevFramesAvailablePlayback = (ma_uint32)-1; + ma_uint32 framesAvailablePlayback; + for (;;) { + result = ma_device__get_available_frames__wasapi(pDevice, (ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback, &framesAvailablePlayback); +@@ -23155,13 +23154,13 @@ static ma_result ma_device_stop__wasapi_nolock(ma_device* pDevice) + Just a safety check to avoid an infinite loop. If this iteration results in a situation where the number of available frames + has not changed, get out of the loop. I don't think this should ever happen, but I think it's nice to have just in case. + */ +- if (framesAvailablePlayback == prevFramesAvaialablePlayback) { ++ if (framesAvailablePlayback == prevFramesAvailablePlayback) { + break; + } +- prevFramesAvaialablePlayback = framesAvailablePlayback; ++ prevFramesAvailablePlayback = framesAvailablePlayback; + +- WaitForSingleObject((HANDLE)pDevice->wasapi.hEventPlayback, waitTime * 1000); + ResetEvent((HANDLE)pDevice->wasapi.hEventPlayback); /* Manual reset. */ ++ WaitForSingleObject((HANDLE)pDevice->wasapi.hEventPlayback, waitTime); + } + } + } diff --git a/subprojects/packagefiles/miniaudio/miniaudio_wasapi_exclusive_testing.diff b/subprojects/packagefiles/miniaudio/miniaudio_wasapi_exclusive_testing.diff new file mode 100644 index 0000000..994a750 --- /dev/null +++ b/subprojects/packagefiles/miniaudio/miniaudio_wasapi_exclusive_testing.diff @@ -0,0 +1,83 @@ +diff --git a/miniaudio.h b/miniaudio.h +index 22b0e4f..49ecd9a 100644 +--- a/miniaudio.h ++++ b/miniaudio.h +@@ -23061,6 +23061,26 @@ static ma_result ma_device_start__wasapi_nolock(ma_device* pDevice) + } + + if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) { ++ ma_uint32 bufferSizeInFrames; ++ if (pDevice->playback.shareMode == ma_share_mode_exclusive) { ++ bufferSizeInFrames = pDevice->wasapi.actualBufferSizeInFramesPlayback; ++ } else { ++ bufferSizeInFrames = pDevice->wasapi.periodSizeInFramesPlayback; ++ } ++ hr = ma_IAudioRenderClient_GetBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, bufferSizeInFrames, (BYTE**)&pDevice->wasapi.pMappedBufferPlayback); ++ if (FAILED(hr)) { ++ return ma_result_from_HRESULT(hr); ++ } ++ pDevice->wasapi.mappedBufferPlaybackCap = bufferSizeInFrames; ++ pDevice->wasapi.mappedBufferPlaybackLen = 0; ++ ++ ma_device__read_frames_from_client(pDevice, bufferSizeInFrames, pDevice->wasapi.pMappedBufferPlayback); ++ ++ ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, pDevice->wasapi.mappedBufferPlaybackCap, 0); ++ pDevice->wasapi.pMappedBufferPlayback = NULL; ++ pDevice->wasapi.mappedBufferPlaybackCap = 0; ++ pDevice->wasapi.mappedBufferPlaybackLen = 0; ++ + hr = ma_IAudioClient_Start((ma_IAudioClient*)pDevice->wasapi.pAudioClientPlayback); + if (FAILED(hr)) { + ma_log_postf(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal playback device. HRESULT = %d.", (int)hr); +@@ -23136,6 +23156,7 @@ static ma_result ma_device_stop__wasapi_nolock(ma_device* pDevice) + DWORD waitTime = pDevice->wasapi.actualBufferSizeInFramesPlayback / (pDevice->playback.internalSampleRate / 1000); + + if (pDevice->playback.shareMode == ma_share_mode_exclusive) { ++ ResetEvent((HANDLE)pDevice->wasapi.hEventPlayback); + WaitForSingleObject((HANDLE)pDevice->wasapi.hEventPlayback, waitTime); + } else { + ma_uint32 prevFramesAvailablePlayback = (ma_uint32)-1; +@@ -23415,7 +23436,23 @@ static ma_result ma_device_write__wasapi(ma_device* pDevice, const void* pFrames + ma_uint32 totalFramesProcessed = 0; + + /* Keep writing to the device until it's stopped or we've consumed all of our input. */ +- while (ma_device_get_state(pDevice) == ma_device_state_started && totalFramesProcessed < frameCount) { ++ while (totalFramesProcessed < frameCount) { ++ if (pDevice->playback.shareMode == ma_share_mode_exclusive && pDevice->wasapi.pMappedBufferPlayback == NULL) { ++ /* ++ In exclusive mode we need to wait here. Exclusive mode is weird because GetBuffer() never ++ seems to return AUDCLNT_E_BUFFER_TOO_LARGE, which is what we normally use to determine ++ whether or not we need to wait for more data. ++ */ ++ if (WaitForSingleObject((HANDLE)pDevice->wasapi.hEventPlayback, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) { ++ result = MA_ERROR; ++ break; /* Wait failed. Probably timed out. */ ++ } ++ } ++ ++ if (ma_device_get_state(pDevice) != ma_device_state_started) { ++ break; ++ } ++ + ma_uint32 framesRemaining = frameCount - totalFramesProcessed; + + /* +@@ -23448,18 +23485,6 @@ static ma_result ma_device_write__wasapi(ma_device* pDevice, const void* pFrames + pDevice->wasapi.pMappedBufferPlayback = NULL; + pDevice->wasapi.mappedBufferPlaybackCap = 0; + pDevice->wasapi.mappedBufferPlaybackLen = 0; +- +- /* +- In exclusive mode we need to wait here. Exclusive mode is weird because GetBuffer() never +- seems to return AUDCLNT_E_BUFFER_TOO_LARGE, which is what we normally use to determine +- whether or not we need to wait for more data. +- */ +- if (pDevice->playback.shareMode == ma_share_mode_exclusive) { +- if (WaitForSingleObject((HANDLE)pDevice->wasapi.hEventPlayback, MA_WASAPI_WAIT_TIMEOUT_MILLISECONDS) != WAIT_OBJECT_0) { +- result = MA_ERROR; +- break; /* Wait failed. Probably timed out. */ +- } +- } + } + } else { + /* We don't have a mapped data buffer so we'll need to get one. */ diff --git a/subprojects/packagefiles/miniaudio/miniaudio_wasapi_release.diff b/subprojects/packagefiles/miniaudio/miniaudio_wasapi_release.diff new file mode 100644 index 0000000..15bc2e0 --- /dev/null +++ b/subprojects/packagefiles/miniaudio/miniaudio_wasapi_release.diff @@ -0,0 +1,70 @@ +commit 90f8315432c85b3efdde3a808c3fd890fe4a0064 +Author: Andrew Opalach <andrew@akon.city> +Date: Mon Feb 3 13:58:49 2025 -0500 + + WASAPI: Release mapped buffer before stopping device + +diff --git a/miniaudio.h b/miniaudio.h +index 22b0e4f..2d94253 100644 +--- a/miniaudio.h ++++ b/miniaudio.h +@@ -23102,6 +23102,14 @@ static ma_result ma_device_stop__wasapi_nolock(ma_device* pDevice) + } + + if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) { ++ /* If we have a mapped buffer we need to release it. */ ++ if (pDevice->wasapi.pMappedBufferCapture != NULL) { ++ ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, pDevice->wasapi.mappedBufferCaptureCap); ++ pDevice->wasapi.pMappedBufferCapture = NULL; ++ pDevice->wasapi.mappedBufferCaptureCap = 0; ++ pDevice->wasapi.mappedBufferCaptureLen = 0; ++ } ++ + hr = ma_IAudioClient_Stop((ma_IAudioClient*)pDevice->wasapi.pAudioClientCapture); + if (FAILED(hr)) { + ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to stop internal capture device."); +@@ -23115,18 +23123,22 @@ static ma_result ma_device_stop__wasapi_nolock(ma_device* pDevice) + return ma_result_from_HRESULT(hr); + } + +- /* If we have a mapped buffer we need to release it. */ +- if (pDevice->wasapi.pMappedBufferCapture != NULL) { +- ma_IAudioCaptureClient_ReleaseBuffer((ma_IAudioCaptureClient*)pDevice->wasapi.pCaptureClient, pDevice->wasapi.mappedBufferCaptureCap); +- pDevice->wasapi.pMappedBufferCapture = NULL; +- pDevice->wasapi.mappedBufferCaptureCap = 0; +- pDevice->wasapi.mappedBufferCaptureLen = 0; +- } +- + ma_atomic_bool32_set(&pDevice->wasapi.isStartedCapture, MA_FALSE); + } + + if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) { ++ if (pDevice->wasapi.pMappedBufferPlayback != NULL) { ++ ma_silence_pcm_frames( ++ ma_offset_pcm_frames_ptr(pDevice->wasapi.pMappedBufferPlayback, pDevice->wasapi.mappedBufferPlaybackLen, pDevice->playback.internalFormat, pDevice->playback.internalChannels), ++ pDevice->wasapi.mappedBufferPlaybackCap - pDevice->wasapi.mappedBufferPlaybackLen, ++ pDevice->playback.internalFormat, pDevice->playback.internalChannels ++ ); ++ ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, pDevice->wasapi.mappedBufferPlaybackCap, 0); ++ pDevice->wasapi.pMappedBufferPlayback = NULL; ++ pDevice->wasapi.mappedBufferPlaybackCap = 0; ++ pDevice->wasapi.mappedBufferPlaybackLen = 0; ++ } ++ + /* + The buffer needs to be drained before stopping the device. Not doing this will result in the last few frames not getting output to + the speakers. This is a problem for very short sounds because it'll result in a significant portion of it not getting played. +@@ -23178,13 +23190,6 @@ static ma_result ma_device_stop__wasapi_nolock(ma_device* pDevice) + return ma_result_from_HRESULT(hr); + } + +- if (pDevice->wasapi.pMappedBufferPlayback != NULL) { +- ma_IAudioRenderClient_ReleaseBuffer((ma_IAudioRenderClient*)pDevice->wasapi.pRenderClient, pDevice->wasapi.mappedBufferPlaybackCap, 0); +- pDevice->wasapi.pMappedBufferPlayback = NULL; +- pDevice->wasapi.mappedBufferPlaybackCap = 0; +- pDevice->wasapi.mappedBufferPlaybackLen = 0; +- } +- + ma_atomic_bool32_set(&pDevice->wasapi.isStartedPlayback, MA_FALSE); + } + |