From: Charlotte Pabst <cpabst(a)codeweavers.com> --- dlls/mfsrcsnk/media_source.c | 96 ++++++++++++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 4 deletions(-) diff --git a/dlls/mfsrcsnk/media_source.c b/dlls/mfsrcsnk/media_source.c index 9ea4e5ecef1..0d5dd098db1 100644 --- a/dlls/mfsrcsnk/media_source.c +++ b/dlls/mfsrcsnk/media_source.c @@ -206,6 +206,72 @@ static HRESULT async_start_params_create(IMFPresentationDescriptor *descriptor, return S_OK; } +struct async_setrate_params +{ + IUnknown IUnknown_iface; + LONG refcount; + float rate; + BOOL thin; +}; + +static struct async_setrate_params *async_setrate_params_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct async_setrate_params, IUnknown_iface); +} + +static HRESULT WINAPI async_setrate_params_QueryInterface(IUnknown *iface, REFIID riid, void **obj) +{ + struct async_setrate_params *params = async_setrate_params_from_IUnknown(iface); + + if (IsEqualIID(riid, &IID_IUnknown)) + { + IUnknown_AddRef(¶ms->IUnknown_iface); + *obj = ¶ms->IUnknown_iface; + return S_OK; + } + + WARN("Unsupported interface %s\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI async_setrate_params_AddRef(IUnknown *iface) +{ + struct async_setrate_params *params = async_setrate_params_from_IUnknown(iface); + return InterlockedIncrement(¶ms->refcount); +} + +static ULONG WINAPI async_setrate_params_Release(IUnknown *iface) +{ + struct async_setrate_params *params = async_setrate_params_from_IUnknown(iface); + ULONG refcount = InterlockedDecrement(¶ms->refcount); + if (!refcount) free(params); + return refcount; +} + +static const IUnknownVtbl async_setrate_params_vtbl = +{ + async_setrate_params_QueryInterface, + async_setrate_params_AddRef, + async_setrate_params_Release, +}; + +static HRESULT async_setrate_params_create(float rate, BOOL thin, IUnknown **out) +{ + struct async_setrate_params *params; + + if (!(params = calloc(1, sizeof(*params)))) + return E_OUTOFMEMORY; + + params->IUnknown_iface.lpVtbl = &async_setrate_params_vtbl; + params->refcount = 1; + params->rate = rate; + params->thin = thin; + + *out = ¶ms->IUnknown_iface; + return S_OK; +} + struct media_stream { IMFMediaStream IMFMediaStream_iface; @@ -233,6 +299,7 @@ struct media_source IMFAsyncCallback async_stop_iface; IMFAsyncCallback async_pause_iface; IMFAsyncCallback async_read_iface; + IMFAsyncCallback async_setrate_iface; LONG refcount; CRITICAL_SECTION cs; @@ -1038,9 +1105,27 @@ static ULONG WINAPI media_source_IMFRateControl_Release(IMFRateControl *iface) return IMFMediaSource_Release(&source->IMFMediaSource_iface); } +static HRESULT media_source_async_setrate(struct media_source *source, IMFAsyncResult *result) +{ + struct async_setrate_params *params; + IUnknown *state; + + if (!(state = IMFAsyncResult_GetStateNoAddRef(result))) return E_INVALIDARG; + params = async_setrate_params_from_IUnknown(state); + + EnterCriticalSection(&source->cs); + source->rate = params->rate; + LeaveCriticalSection(&source->cs); + + return IMFMediaEventQueue_QueueEventParamVar(source->queue, MESourceRateChanged, &GUID_NULL, S_OK, NULL); +} + +DEFINE_MF_ASYNC_CALLBACK(media_source, async_setrate, IMFMediaSource_iface) + static HRESULT WINAPI media_source_IMFRateControl_SetRate(IMFRateControl *iface, BOOL thin, float rate) { struct media_source *source = media_source_from_IMFRateControl(iface); + IUnknown *params; HRESULT hr; FIXME("source %p, thin %d, rate %f, stub!\n", source, thin, rate); @@ -1053,11 +1138,13 @@ static HRESULT WINAPI media_source_IMFRateControl_SetRate(IMFRateControl *iface, if (FAILED(hr = IMFRateSupport_IsRateSupported(&source->IMFRateSupport_iface, thin, rate, NULL))) return hr; - EnterCriticalSection(&source->cs); - source->rate = rate; - LeaveCriticalSection(&source->cs); + if (FAILED(hr = async_setrate_params_create(rate, thin, ¶ms))) + return hr; - return IMFMediaEventQueue_QueueEventParamVar(source->queue, MESourceRateChanged, &GUID_NULL, S_OK, NULL); + hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, &source->async_setrate_iface, params); + IUnknown_Release(params); + + return hr; } static HRESULT WINAPI media_source_IMFRateControl_GetRate(IMFRateControl *iface, BOOL *thin, float *rate) @@ -1726,6 +1813,7 @@ static HRESULT media_source_create(const WCHAR *url, IMFByteStream *stream, IMFM source->async_stop_iface.lpVtbl = &media_source_async_stop_vtbl; source->async_pause_iface.lpVtbl = &media_source_async_pause_vtbl; source->async_read_iface.lpVtbl = &media_source_async_read_vtbl; + source->async_setrate_iface.lpVtbl = &media_source_async_setrate_vtbl; source->refcount = 1; if (FAILED(hr = MFCreateEventQueue(&source->queue))) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/8505