[PATCH 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. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10369
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
participants (2)
-
Brendan McGrath -
Brendan McGrath (@redmcg)