Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/mfplat/buffer.c | 131 ++++++++++++++++++++++++++++++++++++++++---
1 file changed, 122 insertions(+), 9 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c
index 67c60663b33..a3311bc10f1 100644
--- a/dlls/mfplat/buffer.c
+++ b/dlls/mfplat/buffer.c
@@ -19,6 +19,7 @@
#define COBJMACROS
#include "mfplat_private.h"
+#include "rtworkq.h"
#include "wine/debug.h"
@@ -71,6 +72,10 @@ struct sample
DWORD prop_flags;
LONGLONG duration;
LONGLONG timestamp;
+
+ /* Tracked sample functionality. */
+ IRtwqAsyncResult *tracked_result;
+ LONG tracked_refcount;
};
static inline struct memory_buffer *impl_from_IMFMediaBuffer(IMFMediaBuffer *iface)
@@ -752,22 +757,53 @@ static ULONG WINAPI sample_AddRef(IMFSample *iface)
return refcount;
}
+static void release_sample_object(struct sample *sample)
+{
+ size_t i;
+
+ for (i = 0; i < sample->buffer_count; ++i)
+ IMFMediaBuffer_Release(sample->buffers[i]);
+ clear_attributes_object(&sample->attributes);
+ heap_free(sample->buffers);
+ heap_free(sample);
+}
+
static ULONG WINAPI sample_Release(IMFSample *iface)
{
struct sample *sample = impl_from_IMFSample(iface);
ULONG refcount = InterlockedDecrement(&sample->attributes.ref);
- size_t i;
TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount)
+ release_sample_object(sample);
+
+ return refcount;
+}
+
+static ULONG WINAPI sample_tracked_Release(IMFSample *iface)
+{
+ struct sample *sample = impl_from_IMFSample(iface);
+ ULONG refcount;
+ HRESULT hr;
+
+ EnterCriticalSection(&sample->attributes.cs);
+ refcount = InterlockedDecrement(&sample->attributes.ref);
+ if (sample->tracked_result && sample->tracked_refcount == refcount)
{
- for (i = 0; i < sample->buffer_count; ++i)
- IMFMediaBuffer_Release(sample->buffers[i]);
- clear_attributes_object(&sample->attributes);
- heap_free(sample->buffers);
- heap_free(sample);
+ /* Call could fail if queue system is not initialized, it's not critical. */
+ if (FAILED(hr = RtwqInvokeCallback(sample->tracked_result)))
+ WARN("Failed to invoke tracking callback, hr %#x.\n", hr);
+ IRtwqAsyncResult_Release(sample->tracked_result);
+ sample->tracked_result = NULL;
+ sample->tracked_refcount = 0;
}
+ LeaveCriticalSection(&sample->attributes.cs);
+
+ TRACE("%p, refcount %u.\n", iface, refcount);
+
+ if (!refcount)
+ release_sample_object(sample);
return refcount;
}
@@ -1484,9 +1520,34 @@ static ULONG WINAPI tracked_sample_Release(IMFTrackedSample *iface)
static HRESULT WINAPI tracked_sample_SetAllocator(IMFTrackedSample *iface,
IMFAsyncCallback *sample_allocator, IUnknown *state)
{
- FIXME("%p, %p, %p.\n", iface, sample_allocator, state);
+ struct sample *sample = impl_from_IMFTrackedSample(iface);
+ HRESULT hr = S_OK;
- return E_NOTIMPL;
+ TRACE("%p, %p, %p.\n", iface, sample_allocator, state);
+
+ EnterCriticalSection(&sample->attributes.cs);
+
+ if (sample->tracked_result)
+ hr = MF_E_NOTACCEPTING;
+ else
+ {
+ if (SUCCEEDED(hr = RtwqCreateAsyncResult((IUnknown *)iface, (IRtwqAsyncCallback *)sample_allocator,
+ state, &sample->tracked_result)))
+ {
+ /* Account for additional refcount brought by 'state' object. This threshold is used
+ on Release() to invoke tracker callback. */
+ sample->tracked_refcount = 1;
+ if (state == (IUnknown *)&sample->IMFTrackedSample_iface ||
+ state == (IUnknown *)&sample->IMFSample_iface)
+ {
+ ++sample->tracked_refcount;
+ }
+ }
+ }
+
+ LeaveCriticalSection(&sample->attributes.cs);
+
+ return hr;
}
static const IMFTrackedSampleVtbl tracked_sample_vtbl =
@@ -1497,6 +1558,58 @@ static const IMFTrackedSampleVtbl tracked_sample_vtbl =
tracked_sample_SetAllocator,
};
+static const IMFSampleVtbl sample_tracked_vtbl =
+{
+ sample_QueryInterface,
+ sample_AddRef,
+ sample_tracked_Release,
+ sample_GetItem,
+ sample_GetItemType,
+ sample_CompareItem,
+ sample_Compare,
+ sample_GetUINT32,
+ sample_GetUINT64,
+ sample_GetDouble,
+ sample_GetGUID,
+ sample_GetStringLength,
+ sample_GetString,
+ sample_GetAllocatedString,
+ sample_GetBlobSize,
+ sample_GetBlob,
+ sample_GetAllocatedBlob,
+ sample_GetUnknown,
+ sample_SetItem,
+ sample_DeleteItem,
+ sample_DeleteAllItems,
+ sample_SetUINT32,
+ sample_SetUINT64,
+ sample_SetDouble,
+ sample_SetGUID,
+ sample_SetString,
+ sample_SetBlob,
+ sample_SetUnknown,
+ sample_LockStore,
+ sample_UnlockStore,
+ sample_GetCount,
+ sample_GetItemByIndex,
+ sample_CopyAllItems,
+ sample_GetSampleFlags,
+ sample_SetSampleFlags,
+ sample_GetSampleTime,
+ sample_SetSampleTime,
+ sample_GetSampleDuration,
+ sample_SetSampleDuration,
+ sample_GetBufferCount,
+ sample_GetBufferByIndex,
+ sample_ConvertToContiguousBuffer,
+ sample_AddBuffer,
+ sample_RemoveBufferByIndex,
+ sample_RemoveAllBuffers,
+ sample_GetTotalLength,
+ sample_CopyToBuffer,
+};
+
+
/***********************************************************************
* MFCreateSample (mfplat.@)
*/
@@ -1546,7 +1659,7 @@ HRESULT WINAPI MFCreateTrackedSample(IMFTrackedSample **sample)
return hr;
}
- object->IMFSample_iface.lpVtbl = &samplevtbl;
+ object->IMFSample_iface.lpVtbl = &sample_tracked_vtbl;
object->IMFTrackedSample_iface.lpVtbl = &tracked_sample_vtbl;
*sample = &object->IMFTrackedSample_iface;
--
2.27.0