[PATCH v3 0/1] MR10369: mf: Handle ENDOFSEGMENT marker in SAR.
Windows renders silence once the ENDOFSEGMENT marker is received. This allows the presentation time source to continue counting up at the end of an audio stream. This is required when the PTS of the last video sample is greater than the PTS of the last audio sample. -- v3: mf: Handle ENDOFSEGMENT marker in SAR. https://gitlab.winehq.org/wine/wine/-/merge_requests/10369
From: Brendan McGrath <bmcgrath@codeweavers.com> --- dlls/mf/sar.c | 32 +++++++++++++++++++++++++++++--- dlls/mf/tests/mf.c | 1 - 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index 0ad8b195a0e..5b84168ba46 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -37,6 +37,7 @@ enum audio_renderer_flags SAR_SAMPLE_REQUESTED = 0x4, SAR_SEEKING = 0x8, SAR_REPORT_SEEK_TIME = 0x10, + SAR_ADDING_SILENCE = 0x20, }; enum queued_object_type @@ -2045,6 +2046,21 @@ static HRESULT WINAPI audio_renderer_render_callback_GetParameters(IMFAsyncCallb return E_NOTIMPL; } +/* Fills the rest of the audio client buffer with silence */ +static void audio_renderer_render_silence(struct audio_renderer *renderer) +{ + unsigned int max_frames, pad_frames; + BYTE *dst; + + if (SUCCEEDED(IAudioClient_GetBufferSize(renderer->audio_client, &max_frames)) && + SUCCEEDED(IAudioClient_GetCurrentPadding(renderer->audio_client, &pad_frames)) && + (max_frames -= pad_frames) && + SUCCEEDED(IAudioRenderClient_GetBuffer(renderer->audio_render_client, max_frames, &dst))) + { + IAudioRenderClient_ReleaseBuffer(renderer->audio_render_client, max_frames, AUDCLNT_BUFFERFLAGS_SILENT); + } +} + static void audio_renderer_render(struct audio_renderer *renderer, IMFAsyncResult *result) { unsigned int src_frames, dst_frames, max_frames, pad_frames; @@ -2061,6 +2077,9 @@ static void audio_renderer_render(struct audio_renderer *renderer, IMFAsyncResul { if (obj->type == OBJECT_TYPE_MARKER) { + if (obj->u.marker.type == MFSTREAMSINK_MARKER_ENDOFSEGMENT) + renderer->flags |= SAR_ADDING_SILENCE; + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkMarker, &GUID_NULL, S_OK, &obj->u.marker.context); } @@ -2088,6 +2107,7 @@ static void audio_renderer_render(struct audio_renderer *renderer, IMFAsyncResul if (dst_frames && SUCCEEDED(hr = IAudioRenderClient_GetBuffer(renderer->audio_render_client, dst_frames, &dst))) { + renderer->flags &= ~SAR_ADDING_SILENCE; memcpy(dst, src + obj->u.sample.frame_offset * renderer->frame_size, dst_frames * renderer->frame_size); @@ -2120,10 +2140,16 @@ static void audio_renderer_render(struct audio_renderer *renderer, IMFAsyncResul release_pending_object(obj); } - if (list_empty(&renderer->queue) && !(renderer->flags & SAR_SAMPLE_REQUESTED)) + if (list_empty(&renderer->queue)) { - IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL); - renderer->flags |= SAR_SAMPLE_REQUESTED; + if (!(renderer->flags & SAR_SAMPLE_REQUESTED)) + { + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL); + renderer->flags |= SAR_SAMPLE_REQUESTED; + } + + if (renderer->flags & SAR_ADDING_SILENCE) + audio_renderer_render_silence(renderer); } if (FAILED(hr = MFPutWaitingWorkItem(renderer->buffer_ready_event, 0, result, &renderer->buffer_ready_key))) diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index fbf82f2ad2f..7aca38c7fd2 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -7346,7 +7346,6 @@ if (time_source) } /* Time is now greater than 300000 as, due to the ENDOFSEGMENT marker, SAR will now insert silence and continue the timer */ - todo_wine ok(time > 300000, "Unexpected time %I64d.\n", time); /* No new samples are requested after the marker */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10369
v3: - move code that fills the audio client buffer with silence to a helper function -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10369#note_132866
On Thu Mar 19 13:21:26 2026 +0000, Nikolay Sivov wrote:
Please move this to a helper, for readability sake. OK, that's done
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10369#note_132867
Nikolay Sivov (@nsivov) commented about dlls/mf/sar.c:
return E_NOTIMPL; }
+/* Fills the rest of the audio client buffer with silence */ +static void audio_renderer_render_silence(struct audio_renderer *renderer) +{ + unsigned int max_frames, pad_frames; + BYTE *dst; + + if (SUCCEEDED(IAudioClient_GetBufferSize(renderer->audio_client, &max_frames)) && + SUCCEEDED(IAudioClient_GetCurrentPadding(renderer->audio_client, &pad_frames)) && + (max_frames -= pad_frames) && + SUCCEEDED(IAudioRenderClient_GetBuffer(renderer->audio_render_client, max_frames, &dst))) + { + IAudioRenderClient_ReleaseBuffer(renderer->audio_render_client, max_frames, AUDCLNT_BUFFERFLAGS_SILENT); + }
By improving readability I meant also not packing all functions calls in a single statement, same as the rest of this file does it. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10369#note_132868
participants (3)
-
Brendan McGrath -
Brendan McGrath (@redmcg) -
Nikolay Sivov (@nsivov)