[PATCH 1/5] mfplat: Implement sample tracking.

Nikolay Sivov nsivov at codeweavers.com
Mon Jul 6 10:08:25 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at 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




More information about the wine-devel mailing list