From: Charlotte Pabst <cpabst(a)codeweavers.com> --- dlls/mfsrcsnk/media_source.c | 152 +++++++++++++++++++++++------------ 1 file changed, 100 insertions(+), 52 deletions(-) diff --git a/dlls/mfsrcsnk/media_source.c b/dlls/mfsrcsnk/media_source.c index 9ea4e5ecef1..d31be5c3734 100644 --- a/dlls/mfsrcsnk/media_source.c +++ b/dlls/mfsrcsnk/media_source.c @@ -26,6 +26,49 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat); +#define DEFINE_MF_ASYNC_PARAMS(type) \ + static struct type *type ## _from_IUnknown(IUnknown *iface) \ + { \ + return CONTAINING_RECORD(iface, struct type, IUnknown_iface); \ + } \ + static HRESULT WINAPI type ## _QueryInterface(IUnknown *iface, REFIID iid, void **out) \ + { \ + if (IsEqualIID(iid, &IID_IUnknown)) \ + { \ + IUnknown_AddRef(iface); \ + *out = iface; \ + return S_OK; \ + } \ + *out = NULL; \ + return E_NOINTERFACE; \ + } \ + static ULONG WINAPI type ## _AddRef(IUnknown *iface) \ + { \ + struct type *object = type ## _from_IUnknown(iface); \ + return InterlockedIncrement(&object->refcount); \ + } \ + static ULONG WINAPI type ## _Release(IUnknown *iface) \ + { \ + struct type *object = type ## _from_IUnknown(iface); \ + ULONG ref = InterlockedDecrement(&object->refcount); \ + if (!ref) type ## _ ## destroy(object); \ + return ref; \ + } \ + static const IUnknownVtbl type ## _vtbl = \ + { \ + type ## _QueryInterface, \ + type ## _AddRef, \ + type ## _Release, \ + }; \ + static struct type *type ## _alloc(void) \ + { \ + struct type *object; \ + if (!(object = calloc(1, sizeof(*object)))) return NULL; \ + object->IUnknown_iface.lpVtbl = &type ## _vtbl; \ + object->refcount = 1; \ + return object; \ + } + #define DEFINE_MF_ASYNC_CALLBACK_(type, name, impl_from, pfx, mem, expr) \ static struct type *impl_from(IMFAsyncCallback *iface) \ { \ @@ -137,70 +180,52 @@ struct async_start_params PROPVARIANT position; }; -static struct async_start_params *async_start_params_from_IUnknown(IUnknown *iface) -{ - return CONTAINING_RECORD(iface, struct async_start_params, IUnknown_iface); -} - -static HRESULT WINAPI async_start_params_QueryInterface(IUnknown *iface, REFIID riid, void **obj) +static void async_start_params_destroy(struct async_start_params *params) { - struct async_start_params *params = async_start_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; + IMFPresentationDescriptor_Release(params->descriptor); + PropVariantClear(¶ms->position); + free(params); } -static ULONG WINAPI async_start_params_AddRef(IUnknown *iface) -{ - struct async_start_params *params = async_start_params_from_IUnknown(iface); - return InterlockedIncrement(¶ms->refcount); -} +DEFINE_MF_ASYNC_PARAMS(async_start_params); -static ULONG WINAPI async_start_params_Release(IUnknown *iface) +static HRESULT async_start_params_create(IMFPresentationDescriptor *descriptor, const GUID *time_format, + const PROPVARIANT *position, IUnknown **out) { - struct async_start_params *params = async_start_params_from_IUnknown(iface); - ULONG refcount = InterlockedDecrement(¶ms->refcount); + struct async_start_params *params; - if (!refcount) - { - IMFPresentationDescriptor_Release(params->descriptor); - PropVariantClear(¶ms->position); - free(params); - } + if (!(params = async_start_params_alloc())) return E_OUTOFMEMORY; + params->descriptor = descriptor; + IMFPresentationDescriptor_AddRef(descriptor); + params->format = *time_format; + PropVariantCopy(¶ms->position, position); - return refcount; + *out = ¶ms->IUnknown_iface; + return S_OK; } -static const IUnknownVtbl async_start_params_vtbl = +struct async_set_rate_params { - async_start_params_QueryInterface, - async_start_params_AddRef, - async_start_params_Release, + IUnknown IUnknown_iface; + LONG refcount; + float rate; + BOOL thin; }; -static HRESULT async_start_params_create(IMFPresentationDescriptor *descriptor, const GUID *time_format, - const PROPVARIANT *position, IUnknown **out) +static void async_set_rate_params_destroy(struct async_set_rate_params *params) { - struct async_start_params *params; + free(params); +} - if (!(params = calloc(1, sizeof(*params)))) - return E_OUTOFMEMORY; +DEFINE_MF_ASYNC_PARAMS(async_set_rate_params); - params->IUnknown_iface.lpVtbl = &async_start_params_vtbl; - params->refcount = 1; +static HRESULT async_set_rate_params_create(float rate, BOOL thin, IUnknown **out) +{ + struct async_set_rate_params *params; - params->descriptor = descriptor; - IMFPresentationDescriptor_AddRef(descriptor); - params->format = *time_format; - PropVariantCopy(¶ms->position, position); + if (!(params = async_set_rate_params_alloc())) return E_OUTOFMEMORY; + params->rate = rate; + params->thin = thin; *out = ¶ms->IUnknown_iface; return S_OK; @@ -233,6 +258,7 @@ struct media_source IMFAsyncCallback async_stop_iface; IMFAsyncCallback async_pause_iface; IMFAsyncCallback async_read_iface; + IMFAsyncCallback async_set_rate_iface; LONG refcount; CRITICAL_SECTION cs; @@ -1038,9 +1064,28 @@ static ULONG WINAPI media_source_IMFRateControl_Release(IMFRateControl *iface) return IMFMediaSource_Release(&source->IMFMediaSource_iface); } +static HRESULT media_source_async_set_rate(struct media_source *source, IMFAsyncResult *result) +{ + struct async_set_rate_params *params; + IUnknown *state; + + if (!(state = IMFAsyncResult_GetStateNoAddRef(result))) return E_INVALIDARG; + params = async_set_rate_params_from_IUnknown(state); + + EnterCriticalSection(&source->cs); + source->rate = params->rate; + LeaveCriticalSection(&source->cs); + + queue_media_event_value(source->queue, MESourceRateChanged, NULL); + return S_OK; +} + +DEFINE_MF_ASYNC_CALLBACK(media_source, async_set_rate, 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 +1098,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_set_rate_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_set_rate_iface, params); + IUnknown_Release(params); + + return hr; } static HRESULT WINAPI media_source_IMFRateControl_GetRate(IMFRateControl *iface, BOOL *thin, float *rate) @@ -1726,6 +1773,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_set_rate_iface.lpVtbl = &media_source_async_set_rate_vtbl; source->refcount = 1; if (FAILED(hr = MFCreateEventQueue(&source->queue))) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9693