Module: wine
Branch: master
Commit: adffa11609093c3c21cf43970bbecda1b2c43eb1
URL: https://source.winehq.org/git/wine.git/?a=commit;h=adffa11609093c3c21cf4397…
Author: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Date: Mon Jun 28 11:06:44 2021 +0200
mf/sar: Allow requesting more than a sample per period.
The IAudioClient implementation from both Windows and winepulse.drv
never sets the event more than once per period, which is usually
around 10 ms long. Some codecs produce audio samples shorter than
10 ms, so it is critical that the SAR is able to process more than
a sample per period.
This is not currently the case: a new sample is requested only in
audio_renderer_render, which is executed (at most) once per period.
This results in the SAR not being able to keep up with the audio
client, and eventually underrunning.
With this patch the SAR keeps a count of how many frames are
currently queued, and a new sample is immediately requested if
the internal queue has less than a buffer worth of frames.
This patch fixes audio stuttering problems in the logo videos
of Borderlands 3, Deep Rock Galactic and Mutant Year Zero.
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
---
dlls/mf/sar.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c
index eba822ae0fe..e35531acb71 100644
--- a/dlls/mf/sar.c
+++ b/dlls/mf/sar.c
@@ -101,6 +101,8 @@ struct audio_renderer
HANDLE buffer_ready_event;
MFWORKITEM_KEY buffer_ready_key;
unsigned int frame_size;
+ unsigned int queued_frames;
+ unsigned int max_frames;
struct list queue;
enum stream_state state;
unsigned int flags;
@@ -234,6 +236,7 @@ static void audio_renderer_release_audio_client(struct audio_renderer *renderer)
{
release_pending_object(obj);
}
+ renderer->queued_frames = 0;
renderer->buffer_ready_key = 0;
if (renderer->audio_client)
{
@@ -1330,6 +1333,13 @@ static HRESULT WINAPI audio_renderer_stream_GetMediaTypeHandler(IMFStreamSink *i
static HRESULT stream_queue_sample(struct audio_renderer *renderer, IMFSample *sample)
{
struct queued_object *object;
+ DWORD sample_len, sample_frames;
+ HRESULT hr;
+
+ if (FAILED(hr = IMFSample_GetTotalLength(sample, &sample_len)))
+ return hr;
+
+ sample_frames = sample_len / renderer->frame_size;
if (!(object = calloc(1, sizeof(*object))))
return E_OUTOFMEMORY;
@@ -1339,6 +1349,7 @@ static HRESULT stream_queue_sample(struct audio_renderer *renderer, IMFSample *s
IMFSample_AddRef(object->u.sample.sample);
list_add_tail(&renderer->queue, &object->entry);
+ renderer->queued_frames += sample_frames;
return S_OK;
}
@@ -1357,9 +1368,17 @@ static HRESULT WINAPI audio_renderer_stream_ProcessSample(IMFStreamSink *iface,
return MF_E_STREAMSINK_REMOVED;
EnterCriticalSection(&renderer->cs);
+
if (renderer->state == STREAM_STATE_RUNNING)
hr = stream_queue_sample(renderer, sample);
renderer->flags &= ~SAR_SAMPLE_REQUESTED;
+
+ if (renderer->queued_frames < renderer->max_frames && renderer->state == STREAM_STATE_RUNNING)
+ {
+ IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL);
+ renderer->flags |= SAR_SAMPLE_REQUESTED;
+ }
+
LeaveCriticalSection(&renderer->cs);
return hr;
@@ -1428,6 +1447,7 @@ static HRESULT WINAPI audio_renderer_stream_Flush(IMFStreamSink *iface)
release_pending_object(obj);
}
}
+ renderer->queued_frames = 0;
LeaveCriticalSection(&renderer->cs);
return hr;
@@ -1576,6 +1596,12 @@ static HRESULT audio_renderer_create_audio_client(struct audio_renderer *rendere
return hr;
}
+ if (FAILED(hr = IAudioClient_GetBufferSize(renderer->audio_client, &renderer->max_frames)))
+ {
+ WARN("Failed to get buffer size, hr %#x.\n", hr);
+ return hr;
+ }
+
if (SUCCEEDED(hr = MFCreateAsyncResult(NULL, &renderer->render_callback, NULL, &result)))
{
if (FAILED(hr = MFPutWaitingWorkItem(renderer->buffer_ready_event, 0, result, &renderer->buffer_ready_key)))
@@ -1789,6 +1815,7 @@ static void audio_renderer_render(struct audio_renderer *renderer, IMFAsyncResul
IAudioRenderClient_ReleaseBuffer(renderer->audio_render_client, dst_frames, 0);
obj->u.sample.frame_offset += dst_frames;
+ renderer->queued_frames -= dst_frames;
}
keep_sample = FAILED(hr) || src_frames > max_frames;
Module: wine
Branch: master
Commit: a9db6c050d6e98924b0cbc7fe08ff8d22ac0051e
URL: https://source.winehq.org/git/wine.git/?a=commit;h=a9db6c050d6e98924b0cbc7f…
Author: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Date: Fri Jul 2 17:33:06 2021 +0200
winegstreamer: Set MF_MT_ALL_SAMPLES_INDEPENDENT for audio types.
The stricter checks imposed by commit
ac39b313b618ab8d1613302c3604ba505afff0df, while being valid in general,
require that media source attaches to media types the attributes that
application can request.
This patch exposes the MF_MT_ALL_SAMPLES_INDEPENDENT attribute to audio
streams (similarly to what is already done for video streams), which is
for example requested by The Medium.
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
---
dlls/winegstreamer/mfplat.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index dfa448afcfe..dcbd03137ba 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -568,6 +568,7 @@ static IMFMediaType *mf_media_type_from_wg_format_audio(const struct wg_format *
IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, format->u.audio.rate);
IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, format->u.audio.channels);
IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, format->u.audio.channel_mask);
+ IMFMediaType_SetUINT32(type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
return type;
}