Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/sar.c | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index f883163bde5..d5dc0b4f382 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -38,6 +38,11 @@ enum stream_state STREAM_STATE_PAUSED, };
+enum audio_renderer_flags +{ + SAR_SHUT_DOWN = 0x1, +}; + struct audio_renderer { IMFMediaSink IMFMediaSink_iface; @@ -62,7 +67,7 @@ struct audio_renderer ISimpleAudioVolume *audio_volume; HANDLE buffer_ready_event; enum stream_state state; - BOOL is_shut_down; + unsigned int flags; CRITICAL_SECTION cs; };
@@ -212,7 +217,7 @@ static HRESULT WINAPI audio_renderer_sink_GetCharacteristics(IMFMediaSink *iface
TRACE("%p, %p.\n", iface, flags);
- if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_SHUTDOWN;
*flags = MEDIASINK_FIXED_STREAMS | MEDIASINK_CAN_PREROLL; @@ -227,7 +232,7 @@ static HRESULT WINAPI audio_renderer_sink_AddStreamSink(IMFMediaSink *iface, DWO
TRACE("%p, %#x, %p, %p.\n", iface, stream_sink_id, media_type, stream_sink);
- return renderer->is_shut_down ? MF_E_SHUTDOWN : MF_E_STREAMSINKS_FIXED; + return renderer->flags & SAR_SHUT_DOWN ? MF_E_SHUTDOWN : MF_E_STREAMSINKS_FIXED; }
static HRESULT WINAPI audio_renderer_sink_RemoveStreamSink(IMFMediaSink *iface, DWORD stream_sink_id) @@ -236,7 +241,7 @@ static HRESULT WINAPI audio_renderer_sink_RemoveStreamSink(IMFMediaSink *iface,
TRACE("%p, %#x.\n", iface, stream_sink_id);
- return renderer->is_shut_down ? MF_E_SHUTDOWN : MF_E_STREAMSINKS_FIXED; + return renderer->flags & SAR_SHUT_DOWN ? MF_E_SHUTDOWN : MF_E_STREAMSINKS_FIXED; }
static HRESULT WINAPI audio_renderer_sink_GetStreamSinkCount(IMFMediaSink *iface, DWORD *count) @@ -248,7 +253,7 @@ static HRESULT WINAPI audio_renderer_sink_GetStreamSinkCount(IMFMediaSink *iface if (!count) return E_POINTER;
- if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_SHUTDOWN;
*count = 1; @@ -264,12 +269,9 @@ static HRESULT WINAPI audio_renderer_sink_GetStreamSinkByIndex(IMFMediaSink *ifa
TRACE("%p, %u, %p.\n", iface, index, stream);
- if (renderer->is_shut_down) - return MF_E_SHUTDOWN; - EnterCriticalSection(&renderer->cs);
- if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) hr = MF_E_SHUTDOWN; else if (index > 0) hr = MF_E_INVALIDINDEX; @@ -294,7 +296,7 @@ static HRESULT WINAPI audio_renderer_sink_GetStreamSinkById(IMFMediaSink *iface,
EnterCriticalSection(&renderer->cs);
- if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) hr = MF_E_SHUTDOWN; else if (stream_sink_id > 0) hr = MF_E_INVALIDSTREAMNUMBER; @@ -333,7 +335,7 @@ static HRESULT WINAPI audio_renderer_sink_SetPresentationClock(IMFMediaSink *ifa
EnterCriticalSection(&renderer->cs);
- if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) hr = MF_E_SHUTDOWN; else audio_renderer_set_presentation_clock(renderer, clock); @@ -355,7 +357,7 @@ static HRESULT WINAPI audio_renderer_sink_GetPresentationClock(IMFMediaSink *ifa
EnterCriticalSection(&renderer->cs);
- if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) hr = MF_E_SHUTDOWN; else if (renderer->clock) { @@ -376,11 +378,11 @@ static HRESULT WINAPI audio_renderer_sink_Shutdown(IMFMediaSink *iface)
TRACE("%p.\n", iface);
- if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_SHUTDOWN;
EnterCriticalSection(&renderer->cs); - renderer->is_shut_down = TRUE; + renderer->flags |= SAR_SHUT_DOWN; IMFMediaEventQueue_Shutdown(renderer->event_queue); IMFMediaEventQueue_Shutdown(renderer->stream_event_queue); audio_renderer_set_presentation_clock(renderer, NULL); @@ -437,7 +439,7 @@ static HRESULT WINAPI audio_renderer_preroll_NotifyPreroll(IMFMediaSinkPreroll *
TRACE("%p, %s.\n", iface, debugstr_time(start_time));
- if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_SHUTDOWN;
audio_renderer_preroll(renderer); @@ -1145,7 +1147,7 @@ static HRESULT WINAPI audio_renderer_stream_GetEvent(IMFStreamSink *iface, DWORD
TRACE("%p, %#x, %p.\n", iface, flags, event);
- if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_STREAMSINK_REMOVED;
return IMFMediaEventQueue_GetEvent(renderer->stream_event_queue, flags, event); @@ -1158,7 +1160,7 @@ static HRESULT WINAPI audio_renderer_stream_BeginGetEvent(IMFStreamSink *iface,
TRACE("%p, %p, %p.\n", iface, callback, state);
- if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_STREAMSINK_REMOVED;
return IMFMediaEventQueue_BeginGetEvent(renderer->stream_event_queue, callback, state); @@ -1171,7 +1173,7 @@ static HRESULT WINAPI audio_renderer_stream_EndGetEvent(IMFStreamSink *iface, IM
TRACE("%p, %p, %p.\n", iface, result, event);
- if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_STREAMSINK_REMOVED;
return IMFMediaEventQueue_EndGetEvent(renderer->stream_event_queue, result, event); @@ -1184,7 +1186,7 @@ static HRESULT WINAPI audio_renderer_stream_QueueEvent(IMFStreamSink *iface, Med
TRACE("%p, %u, %s, %#x, %p.\n", iface, event_type, debugstr_guid(ext_type), hr, value);
- if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_STREAMSINK_REMOVED;
return IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, event_type, ext_type, hr, value); @@ -1196,7 +1198,7 @@ static HRESULT WINAPI audio_renderer_stream_GetMediaSink(IMFStreamSink *iface, I
TRACE("%p, %p.\n", iface, sink);
- if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_STREAMSINK_REMOVED;
*sink = &renderer->IMFMediaSink_iface; @@ -1211,7 +1213,7 @@ static HRESULT WINAPI audio_renderer_stream_GetIdentifier(IMFStreamSink *iface,
TRACE("%p, %p.\n", iface, identifier);
- if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_STREAMSINK_REMOVED;
*identifier = 0; @@ -1228,7 +1230,7 @@ static HRESULT WINAPI audio_renderer_stream_GetMediaTypeHandler(IMFStreamSink *i if (!handler) return E_POINTER;
- if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_STREAMSINK_REMOVED;
*handler = &renderer->IMFMediaTypeHandler_iface; @@ -1462,7 +1464,7 @@ static HRESULT WINAPI audio_renderer_stream_type_handler_GetMajorType(IMFMediaTy if (!type) return E_POINTER;
- if (renderer->is_shut_down) + if (renderer->flags & SAR_SHUT_DOWN) return MF_E_STREAMSINK_REMOVED;
memcpy(type, &MFMediaType_Audio, sizeof(*type));
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/sar.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index d5dc0b4f382..66fdf471ade 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -41,6 +41,7 @@ enum stream_state enum audio_renderer_flags { SAR_SHUT_DOWN = 0x1, + SAR_PREROLLED = 0x2, };
struct audio_renderer @@ -179,6 +180,7 @@ static void audio_renderer_release_audio_client(struct audio_renderer *renderer) if (renderer->audio_volume) ISimpleAudioVolume_Release(renderer->audio_volume); renderer->audio_volume = NULL; + renderer->flags &= ~SAR_PREROLLED; }
static ULONG WINAPI audio_renderer_sink_Release(IMFMediaSink *iface) @@ -409,10 +411,14 @@ static const IMFMediaSinkVtbl audio_renderer_sink_vtbl =
static void audio_renderer_preroll(struct audio_renderer *renderer) { - int i; + unsigned int i; + + if (renderer->flags & SAR_PREROLLED) + return;
for (i = 0; i < 2; ++i) IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL); + renderer->flags |= SAR_PREROLLED; }
static HRESULT WINAPI audio_renderer_preroll_QueryInterface(IMFMediaSinkPreroll *iface, REFIID riid, void **obj) @@ -586,6 +592,7 @@ static HRESULT WINAPI audio_renderer_clock_sink_OnClockStop(IMFClockStateSink *i else WARN("Failed to stop audio client, hr %#x.\n", hr); renderer->state = STREAM_STATE_STOPPED; + renderer->flags &= ~SAR_PREROLLED; } } else
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/sar.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index 66fdf471ade..5f035a801ce 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -567,6 +567,8 @@ static HRESULT WINAPI audio_renderer_clock_sink_OnClockStart(IMFClockStateSink * hr = MF_E_NOT_INITIALIZED;
IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkStarted, &GUID_NULL, hr, NULL); + if (SUCCEEDED(hr)) + audio_renderer_preroll(renderer); LeaveCriticalSection(&renderer->cs);
return hr;
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/sar.c | 268 +++++++++++++++++++++++++++++++++++++++++++++++- include/mfapi.h | 1 + 2 files changed, 264 insertions(+), 5 deletions(-)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index 5f035a801ce..080db35e5a3 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -28,6 +28,7 @@
#include "wine/debug.h" #include "wine/heap.h" +#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
@@ -42,6 +43,32 @@ enum audio_renderer_flags { SAR_SHUT_DOWN = 0x1, SAR_PREROLLED = 0x2, + SAR_SAMPLE_REQUESTED = 0x4, +}; + +enum queued_object_type +{ + OBJECT_TYPE_SAMPLE, + OBJECT_TYPE_MARKER, +}; + +struct queued_object +{ + struct list entry; + enum queued_object_type type; + union + { + struct + { + IMFSample *sample; + unsigned int frame_offset; + } sample; + struct + { + MFSTREAMSINK_MARKER_TYPE type; + PROPVARIANT context; + } marker; + } u; };
struct audio_renderer @@ -56,6 +83,7 @@ struct audio_renderer IMFSimpleAudioVolume IMFSimpleAudioVolume_iface; IMFAudioStreamVolume IMFAudioStreamVolume_iface; IMFAudioPolicy IMFAudioPolicy_iface; + IMFAsyncCallback render_callback; LONG refcount; IMFMediaEventQueue *event_queue; IMFMediaEventQueue *stream_event_queue; @@ -64,14 +92,34 @@ struct audio_renderer IMFMediaType *current_media_type; IMMDevice *device; IAudioClient *audio_client; + IAudioRenderClient *audio_render_client; IAudioStreamVolume *stream_volume; ISimpleAudioVolume *audio_volume; HANDLE buffer_ready_event; + MFWORKITEM_KEY buffer_ready_key; + unsigned int frame_size; + struct list queue; enum stream_state state; unsigned int flags; CRITICAL_SECTION cs; };
+static void release_pending_object(struct queued_object *object) +{ + list_remove(&object->entry); + switch (object->type) + { + case OBJECT_TYPE_SAMPLE: + if (object->u.sample.sample) + IMFSample_Release(object->u.sample.sample); + break; + case OBJECT_TYPE_MARKER: + PropVariantClear(&object->u.marker.context); + break; + } + heap_free(object); +} + static struct audio_renderer *impl_from_IMFMediaSink(IMFMediaSink *iface) { return CONTAINING_RECORD(iface, struct audio_renderer, IMFMediaSink_iface); @@ -122,6 +170,11 @@ static struct audio_renderer *impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler return CONTAINING_RECORD(iface, struct audio_renderer, IMFMediaTypeHandler_iface); }
+static struct audio_renderer *impl_from_render_callback_IMFAsyncCallback(IMFAsyncCallback *iface) +{ + return CONTAINING_RECORD(iface, struct audio_renderer, render_callback); +} + static HRESULT WINAPI audio_renderer_sink_QueryInterface(IMFMediaSink *iface, REFIID riid, void **obj) { struct audio_renderer *renderer = impl_from_IMFMediaSink(iface); @@ -174,6 +227,9 @@ static void audio_renderer_release_audio_client(struct audio_renderer *renderer) if (renderer->audio_client) IAudioClient_Release(renderer->audio_client); renderer->audio_client = NULL; + if (renderer->audio_render_client) + IAudioRenderClient_Release(renderer->audio_render_client); + renderer->audio_render_client = NULL; if (renderer->stream_volume) IAudioStreamVolume_Release(renderer->stream_volume); renderer->stream_volume = NULL; @@ -187,6 +243,7 @@ static ULONG WINAPI audio_renderer_sink_Release(IMFMediaSink *iface) { struct audio_renderer *renderer = impl_from_IMFMediaSink(iface); ULONG refcount = InterlockedDecrement(&renderer->refcount); + struct queued_object *obj, *obj2;
TRACE("%p, refcount %u.\n", iface, refcount);
@@ -204,8 +261,12 @@ static ULONG WINAPI audio_renderer_sink_Release(IMFMediaSink *iface) IMFMediaType_Release(renderer->media_type); if (renderer->current_media_type) IMFMediaType_Release(renderer->current_media_type); - CloseHandle(renderer->buffer_ready_event); audio_renderer_release_audio_client(renderer); + CloseHandle(renderer->buffer_ready_event); + LIST_FOR_EACH_ENTRY_SAFE(obj, obj2, &renderer->queue, struct queued_object, entry) + { + release_pending_object(obj); + } DeleteCriticalSection(&renderer->cs); heap_free(renderer); } @@ -1248,19 +1309,82 @@ static HRESULT WINAPI audio_renderer_stream_GetMediaTypeHandler(IMFStreamSink *i return S_OK; }
+static HRESULT stream_queue_sample(struct audio_renderer *renderer, IMFSample *sample) +{ + struct queued_object *object; + + if (!(object = heap_alloc_zero(sizeof(*object)))) + return E_OUTOFMEMORY; + + object->type = OBJECT_TYPE_SAMPLE; + object->u.sample.sample = sample; + IMFSample_AddRef(object->u.sample.sample); + + list_add_tail(&renderer->queue, &object->entry); + + return S_OK; +} + static HRESULT WINAPI audio_renderer_stream_ProcessSample(IMFStreamSink *iface, IMFSample *sample) { - FIXME("%p, %p.\n", iface, sample); + struct audio_renderer *renderer = impl_from_IMFStreamSink(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, sample); + + if (!sample) + return E_POINTER; + + if (renderer->flags & SAR_SHUT_DOWN) + 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; + LeaveCriticalSection(&renderer->cs); + + return hr; +} + +static HRESULT stream_place_marker(struct audio_renderer *renderer, MFSTREAMSINK_MARKER_TYPE marker_type, + const PROPVARIANT *context_value) +{ + struct queued_object *marker; + HRESULT hr = S_OK; + + if (!(marker = heap_alloc_zero(sizeof(*marker)))) + return E_OUTOFMEMORY; + + marker->type = OBJECT_TYPE_MARKER; + marker->u.marker.type = marker_type; + PropVariantInit(&marker->u.marker.context); + if (context_value) + hr = PropVariantCopy(&marker->u.marker.context, context_value); + if (SUCCEEDED(hr)) + list_add_tail(&renderer->queue, &marker->entry); + else + release_pending_object(marker); + + return hr; }
static HRESULT WINAPI audio_renderer_stream_PlaceMarker(IMFStreamSink *iface, MFSTREAMSINK_MARKER_TYPE marker_type, const PROPVARIANT *marker_value, const PROPVARIANT *context_value) { - FIXME("%p, %d, %p, %p.\n", iface, marker_type, marker_value, context_value); + struct audio_renderer *renderer = impl_from_IMFStreamSink(iface); + HRESULT hr;
- return E_NOTIMPL; + TRACE("%p, %d, %p, %p.\n", iface, marker_type, marker_value, context_value); + + if (renderer->flags & SAR_SHUT_DOWN) + return MF_E_STREAMSINK_REMOVED; + + EnterCriticalSection(&renderer->cs); + hr = stream_place_marker(renderer, marker_type, context_value); + LeaveCriticalSection(&renderer->cs); + + return hr; }
static HRESULT WINAPI audio_renderer_stream_Flush(IMFStreamSink *iface) @@ -1350,6 +1474,7 @@ static HRESULT WINAPI audio_renderer_stream_type_handler_GetMediaTypeByIndex(IMF
static HRESULT audio_renderer_create_audio_client(struct audio_renderer *renderer) { + IMFAsyncResult *result; WAVEFORMATEX *wfx; HRESULT hr;
@@ -1372,6 +1497,8 @@ static HRESULT audio_renderer_create_audio_client(struct audio_renderer *rendere return hr; }
+ renderer->frame_size = wfx->wBitsPerSample * wfx->nChannels / 8; + hr = IAudioClient_Initialize(renderer->audio_client, AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 1000000, 0, wfx, NULL); CoTaskMemFree(wfx); @@ -1394,12 +1521,26 @@ static HRESULT audio_renderer_create_audio_client(struct audio_renderer *rendere return hr; }
+ if (FAILED(hr = IAudioClient_GetService(renderer->audio_client, &IID_IAudioRenderClient, + (void **)&renderer->audio_render_client))) + { + WARN("Failed to get audio render client, hr %#x.\n", hr); + return hr; + } + if (FAILED(hr = IAudioClient_SetEventHandle(renderer->audio_client, renderer->buffer_ready_event))) { WARN("Failed to set event handle, 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))) + WARN("Failed to submit wait item, hr %#x.\n", hr); + IMFAsyncResult_Release(result); + } + return hr; }
@@ -1532,6 +1673,121 @@ static HRESULT audio_renderer_collect_supported_types(struct audio_renderer *ren return hr; }
+static HRESULT WINAPI audio_renderer_render_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj) +{ + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IMFAsyncCallback) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IMFAsyncCallback_AddRef(iface); + return S_OK; + } + + WARN("Unsupported interface %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI audio_renderer_render_callback_AddRef(IMFAsyncCallback *iface) +{ + struct audio_renderer *renderer = impl_from_render_callback_IMFAsyncCallback(iface); + return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface); +} + +static ULONG WINAPI audio_renderer_render_callback_Release(IMFAsyncCallback *iface) +{ + struct audio_renderer *renderer = impl_from_render_callback_IMFAsyncCallback(iface); + return IMFMediaSink_Release(&renderer->IMFMediaSink_iface); +} + +static HRESULT WINAPI audio_renderer_render_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI audio_renderer_render_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) +{ + struct audio_renderer *renderer = impl_from_render_callback_IMFAsyncCallback(iface); + unsigned int src_frames, dst_frames, max_frames, src_len; + struct queued_object *obj, *obj2; + BOOL keep_sample = FALSE; + IMFMediaBuffer *buffer; + BYTE *dst, *src; + HRESULT hr; + + EnterCriticalSection(&renderer->cs); + + LIST_FOR_EACH_ENTRY_SAFE(obj, obj2, &renderer->queue, struct queued_object, entry) + { + if (obj->type == OBJECT_TYPE_MARKER) + { + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkMarker, + &GUID_NULL, S_OK, &obj->u.marker.context); + } + else if (obj->type == OBJECT_TYPE_SAMPLE) + { + if (SUCCEEDED(IMFSample_ConvertToContiguousBuffer(obj->u.sample.sample, &buffer))) + { + if (SUCCEEDED(IMFMediaBuffer_Lock(buffer, &src, NULL, &src_len))) + { + if ((src_frames = src_len / renderer->frame_size)) + { + if (SUCCEEDED(IAudioClient_GetBufferSize(renderer->audio_client, &max_frames))) + { + src_frames -= obj->u.sample.frame_offset; + dst_frames = min(src_frames, max_frames); + + if (SUCCEEDED(hr = IAudioRenderClient_GetBuffer(renderer->audio_render_client, dst_frames, &dst))) + { + memcpy(dst, src + obj->u.sample.frame_offset * renderer->frame_size, + dst_frames * renderer->frame_size); + + IAudioRenderClient_ReleaseBuffer(renderer->audio_render_client, dst_frames, 0); + + obj->u.sample.frame_offset += dst_frames; + } + + keep_sample = FAILED(hr) || src_frames > max_frames; + } + } + IMFMediaBuffer_Unlock(buffer); + } + IMFMediaBuffer_Release(buffer); + } + } + + if (keep_sample) + break; + + list_remove(&obj->entry); + release_pending_object(obj); + } + + if (list_empty(&renderer->queue) && !(renderer->flags & SAR_SAMPLE_REQUESTED)) + { + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkRequestSample, &GUID_NULL, S_OK, NULL); + renderer->flags |= SAR_SAMPLE_REQUESTED; + } + + if (FAILED(hr = MFPutWaitingWorkItem(renderer->buffer_ready_event, 0, result, &renderer->buffer_ready_key))) + WARN("Failed to submit wait item, hr %#x.\n", hr); + + LeaveCriticalSection(&renderer->cs); + + return S_OK; +} + +static const IMFAsyncCallbackVtbl audio_renderer_render_callback_vtbl = +{ + audio_renderer_render_callback_QueryInterface, + audio_renderer_render_callback_AddRef, + audio_renderer_render_callback_Release, + audio_renderer_render_callback_GetParameters, + audio_renderer_render_callback_Invoke, +}; + static HRESULT sar_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj) { struct audio_renderer *renderer; @@ -1552,9 +1808,11 @@ static HRESULT sar_create_object(IMFAttributes *attributes, void *user_context, renderer->IMFSimpleAudioVolume_iface.lpVtbl = &audio_renderer_simple_volume_vtbl; renderer->IMFAudioStreamVolume_iface.lpVtbl = &audio_renderer_stream_volume_vtbl; renderer->IMFAudioPolicy_iface.lpVtbl = &audio_renderer_policy_vtbl; + renderer->render_callback.lpVtbl = &audio_renderer_render_callback_vtbl; renderer->refcount = 1; InitializeCriticalSection(&renderer->cs); renderer->buffer_ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); + list_init(&renderer->queue);
if (FAILED(hr = MFCreateEventQueue(&renderer->event_queue))) goto failed; diff --git a/include/mfapi.h b/include/mfapi.h index c8ae665b10b..05ada65b9db 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -535,6 +535,7 @@ HRESULT WINAPI MFInitAttributesFromBlob(IMFAttributes *attributes, const UINT8 * HRESULT WINAPI MFInitMediaTypeFromWaveFormatEx(IMFMediaType *mediatype, const WAVEFORMATEX *format, UINT32 size); HRESULT WINAPI MFInvokeCallback(IMFAsyncResult *result); HRESULT WINAPI MFLockPlatform(void); +HRESULT WINAPI MFPutWaitingWorkItem(HANDLE event, LONG priority, IMFAsyncResult *result, MFWORKITEM_KEY *key); HRESULT WINAPI MFPutWorkItem(DWORD queue, IMFAsyncCallback *callback, IUnknown *state); HRESULT WINAPI MFPutWorkItem2(DWORD queue, LONG priority, IMFAsyncCallback *callback, IUnknown *state); HRESULT WINAPI MFPutWorkItemEx(DWORD queue, IMFAsyncResult *result);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=71668
Your paranoid android.
=== debiant (32 bit report) ===
mf: mf.c:3074: Test failed: Failed to activate, hr 0x8889000a. mf.c:3077: Test failed: Failed to activate, hr 0x8889000a. mf.c:3082: Test failed: Failed to get sink flags, hr 0xc00d3e85.
=== debiant (32 bit Chinese:China report) ===
mf: mf.c:3074: Test failed: Failed to activate, hr 0x8889000a. mf.c:3077: Test failed: Failed to activate, hr 0x8889000a. mf.c:3082: Test failed: Failed to get sink flags, hr 0xc00d3e85.
=== debiant (32 bit WoW report) ===
mf: mf.c:3074: Test failed: Failed to activate, hr 0x8889000a. mf.c:3077: Test failed: Failed to activate, hr 0x8889000a. mf.c:3082: Test failed: Failed to get sink flags, hr 0xc00d3e85.
=== debiant (64 bit WoW report) ===
mf: mf.c:3074: Test failed: Failed to activate, hr 0x8889000a. mf.c:3077: Test failed: Failed to activate, hr 0x8889000a. mf.c:3082: Test failed: Failed to get sink flags, hr 0xc00d3e85.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/sar.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index 080db35e5a3..d53ccdd51ec 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -1389,9 +1389,30 @@ static HRESULT WINAPI audio_renderer_stream_PlaceMarker(IMFStreamSink *iface, MF
static HRESULT WINAPI audio_renderer_stream_Flush(IMFStreamSink *iface) { - FIXME("%p.\n", iface); + struct audio_renderer *renderer = impl_from_IMFStreamSink(iface); + struct queued_object *obj, *obj2; + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p.\n", iface); + + EnterCriticalSection(&renderer->cs); + if (renderer->flags & SAR_SHUT_DOWN) + hr = MF_E_STREAMSINK_REMOVED; + else + { + LIST_FOR_EACH_ENTRY_SAFE(obj, obj2, &renderer->queue, struct queued_object, entry) + { + if (obj->type == OBJECT_TYPE_MARKER) + { + IMFMediaEventQueue_QueueEventParamVar(renderer->stream_event_queue, MEStreamSinkMarker, + &GUID_NULL, S_OK, &obj->u.marker.context); + } + release_pending_object(obj); + } + } + LeaveCriticalSection(&renderer->cs); + + return hr; }
static const IMFStreamSinkVtbl audio_renderer_stream_vtbl =
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=71669
Your paranoid android.
=== debiant (32 bit report) ===
mf: mf.c:3074: Test failed: Failed to activate, hr 0x8889000a. mf.c:3077: Test failed: Failed to activate, hr 0x8889000a. mf.c:3082: Test failed: Failed to get sink flags, hr 0xc00d3e85.
=== debiant (32 bit Chinese:China report) ===
mf: mf.c:3074: Test failed: Failed to activate, hr 0x8889000a. mf.c:3077: Test failed: Failed to activate, hr 0x8889000a. mf.c:3082: Test failed: Failed to get sink flags, hr 0xc00d3e85.
=== debiant (32 bit WoW report) ===
mf: mf.c:3074: Test failed: Failed to activate, hr 0x8889000a. mf.c:3077: Test failed: Failed to activate, hr 0x8889000a. mf.c:3082: Test failed: Failed to get sink flags, hr 0xc00d3e85.
=== debiant (64 bit WoW report) ===
mf: mf.c:3074: Test failed: Failed to activate, hr 0x8889000a. mf.c:3077: Test failed: Failed to activate, hr 0x8889000a. mf.c:3082: Test failed: Failed to get sink flags, hr 0xc00d3e85.