From: Brendan McGrath <bmcgrath@codeweavers.com> --- dlls/mf/sar.c | 43 ++++++++++++++++++++++++++++++++++++++----- dlls/mf/tests/mf.c | 1 - 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index 0ad8b195a0e..470db80d0f6 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 @@ -2047,20 +2048,23 @@ static HRESULT WINAPI audio_renderer_render_callback_GetParameters(IMFAsyncCallb static void audio_renderer_render(struct audio_renderer *renderer, IMFAsyncResult *result) { - unsigned int src_frames, dst_frames, max_frames, pad_frames; + unsigned int src_frames, dst_frames, max_frames, pad_frames, silent_frames; struct queued_object *obj, *obj2; + LONGLONG pts, clock_time; BOOL keep_sample = FALSE; IMFMediaBuffer *buffer; UINT64 position; BYTE *dst, *src; DWORD src_len; - LONGLONG pts; HRESULT hr; LIST_FOR_EACH_ENTRY_SAFE(obj, obj2, &renderer->queue, struct queued_object, entry) { 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); } @@ -2082,12 +2086,29 @@ static void audio_renderer_render(struct audio_renderer *renderer, IMFAsyncResul IAudioClock_GetPosition(renderer->audio_clock, &position, NULL); position += pad_frames * renderer->audio_clock_frequency / renderer->sample_rate; + if (renderer->flags & SAR_ADDING_SILENCE) + { + clock_time = renderer->pts + (INT64)(position - renderer->position) * MFCLOCK_FREQUENCY_HNS / (INT64)renderer->audio_clock_frequency; + if (clock_time < pts) + { + silent_frames = (pts - clock_time) * renderer->sample_rate / MFCLOCK_FREQUENCY_HNS; + silent_frames = min(silent_frames, max_frames); + if (silent_frames && SUCCEEDED(hr = IAudioRenderClient_GetBuffer(renderer->audio_render_client, silent_frames, &dst))) + { + IAudioRenderClient_ReleaseBuffer(renderer->audio_render_client, silent_frames, AUDCLNT_BUFFERFLAGS_SILENT); + max_frames -= silent_frames; + position += silent_frames * renderer->audio_clock_frequency / renderer->sample_rate; + } + } + } + src_frames -= obj->u.sample.frame_offset; dst_frames = min(src_frames, max_frames); hr = S_OK; 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 +2141,22 @@ 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 && + 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); + } } 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