Module: wine Branch: master Commit: 181b609f565125a5774f7cf852d81286697c9b12 URL: https://gitlab.winehq.org/wine/wine/-/commit/181b609f565125a5774f7cf852d8128...
Author: Ziqing Hui zhui@codeweavers.com Date: Wed Apr 17 17:04:48 2024 +0800
winegstreamer/video_decoder: Support aggregation.
---
dlls/winegstreamer/video_decoder.c | 134 +++++++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 51 deletions(-)
diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index 065f2608ef8..4824e317174 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -45,7 +45,9 @@ static const GUID *const video_decoder_output_types[] =
struct video_decoder { + IUnknown IUnknown_inner; IMFTransform IMFTransform_iface; + IUnknown *outer; LONG refcount;
IMFAttributes *attributes; @@ -73,6 +75,79 @@ struct video_decoder IMFMediaBuffer *temp_buffer; };
+static inline struct video_decoder *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct video_decoder, IUnknown_inner); +} + +static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void **out) +{ + struct video_decoder *decoder = impl_from_IUnknown(iface); + + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown)) + *out = &decoder->IUnknown_inner; + else if (IsEqualGUID(iid, &IID_IMFTransform)) + *out = &decoder->IMFTransform_iface; + else + { + *out = NULL; + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static ULONG WINAPI unknown_AddRef(IUnknown *iface) +{ + struct video_decoder *decoder = impl_from_IUnknown(iface); + ULONG refcount = InterlockedIncrement(&decoder->refcount); + + TRACE("iface %p increasing refcount to %lu.\n", decoder, refcount); + + return refcount; +} + +static ULONG WINAPI unknown_Release(IUnknown *iface) +{ + struct video_decoder *decoder = impl_from_IUnknown(iface); + ULONG refcount = InterlockedDecrement(&decoder->refcount); + + TRACE("iface %p decreasing refcount to %lu.\n", decoder, refcount); + + if (!refcount) + { + IMFTransform_Release(decoder->copier); + IMFVideoSampleAllocatorEx_Release(decoder->allocator); + if (decoder->temp_buffer) + IMFMediaBuffer_Release(decoder->temp_buffer); + if (decoder->wg_transform) + wg_transform_destroy(decoder->wg_transform); + if (decoder->input_type) + IMFMediaType_Release(decoder->input_type); + if (decoder->output_type) + IMFMediaType_Release(decoder->output_type); + if (decoder->output_attributes) + IMFAttributes_Release(decoder->output_attributes); + if (decoder->attributes) + IMFAttributes_Release(decoder->attributes); + wg_sample_queue_destroy(decoder->wg_sample_queue); + free(decoder); + } + + return refcount; +} + +static const IUnknownVtbl unknown_vtbl = +{ + unknown_QueryInterface, + unknown_AddRef, + unknown_Release, +}; + static struct video_decoder *impl_from_IMFTransform(IMFTransform *iface) { return CONTAINING_RECORD(iface, struct video_decoder, IMFTransform_iface); @@ -230,62 +305,17 @@ static void uninit_allocator(struct video_decoder *decoder)
static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out) { - struct video_decoder *decoder = impl_from_IMFTransform(iface); - - TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); - - if (IsEqualGUID(iid, &IID_IUnknown) || - IsEqualGUID(iid, &IID_IMFTransform)) - *out = &decoder->IMFTransform_iface; - else - { - *out = NULL; - WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); - return E_NOINTERFACE; - } - - IUnknown_AddRef((IUnknown *)*out); - return S_OK; + return IUnknown_QueryInterface(impl_from_IMFTransform(iface)->outer, iid, out); }
static ULONG WINAPI transform_AddRef(IMFTransform *iface) { - struct video_decoder *decoder = impl_from_IMFTransform(iface); - ULONG refcount = InterlockedIncrement(&decoder->refcount); - - TRACE("iface %p increasing refcount to %lu.\n", decoder, refcount); - - return refcount; + return IUnknown_AddRef(impl_from_IMFTransform(iface)->outer); }
static ULONG WINAPI transform_Release(IMFTransform *iface) { - struct video_decoder *decoder = impl_from_IMFTransform(iface); - ULONG refcount = InterlockedDecrement(&decoder->refcount); - - TRACE("iface %p decreasing refcount to %lu.\n", decoder, refcount); - - if (!refcount) - { - IMFTransform_Release(decoder->copier); - IMFVideoSampleAllocatorEx_Release(decoder->allocator); - if (decoder->temp_buffer) - IMFMediaBuffer_Release(decoder->temp_buffer); - if (decoder->wg_transform) - wg_transform_destroy(decoder->wg_transform); - if (decoder->input_type) - IMFMediaType_Release(decoder->input_type); - if (decoder->output_type) - IMFMediaType_Release(decoder->output_type); - if (decoder->output_attributes) - IMFAttributes_Release(decoder->output_attributes); - if (decoder->attributes) - IMFAttributes_Release(decoder->attributes); - wg_sample_queue_destroy(decoder->wg_sample_queue); - free(decoder); - } - - return refcount; + return IUnknown_Release(impl_from_IMFTransform(iface)->outer); }
static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, @@ -810,7 +840,7 @@ static const IMFTransformVtbl transform_vtbl = };
static HRESULT video_decoder_create_with_types(const GUID *const *input_types, UINT input_type_count, - const GUID *const *output_types, UINT output_type_count, IMFTransform **ret) + const GUID *const *output_types, UINT output_type_count, IUnknown *outer, IMFTransform **ret) { struct video_decoder *decoder; HRESULT hr; @@ -818,8 +848,10 @@ static HRESULT video_decoder_create_with_types(const GUID *const *input_types, U if (!(decoder = calloc(1, sizeof(*decoder)))) return E_OUTOFMEMORY;
+ decoder->IUnknown_inner.lpVtbl = &unknown_vtbl; decoder->IMFTransform_iface.lpVtbl = &transform_vtbl; decoder->refcount = 1; + decoder->outer = outer ? outer : &decoder->IUnknown_inner;
decoder->input_type_count = input_type_count; decoder->input_types = input_types; @@ -903,7 +935,7 @@ HRESULT h264_decoder_create(REFIID riid, void **out) wg_transform_destroy(transform);
if (FAILED(hr = video_decoder_create_with_types(h264_decoder_input_types, ARRAY_SIZE(h264_decoder_input_types), - video_decoder_output_types, ARRAY_SIZE(video_decoder_output_types), &iface))) + video_decoder_output_types, ARRAY_SIZE(video_decoder_output_types), NULL, &iface))) return hr; decoder = impl_from_IMFTransform(iface);
@@ -953,5 +985,5 @@ HRESULT WINAPI winegstreamer_create_video_decoder(IMFTransform **out) return E_FAIL;
return video_decoder_create_with_types(iv50_decoder_input_types, ARRAY_SIZE(iv50_decoder_input_types), - iv50_decoder_output_types, ARRAY_SIZE(iv50_decoder_output_types), out); + iv50_decoder_output_types, ARRAY_SIZE(iv50_decoder_output_types), NULL, out); }