[PATCH 5/5] mfplat: Implement buffer collection for sample.

Nikolay Sivov nsivov at codeweavers.com
Tue Mar 5 01:49:42 CST 2019


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/mfplat/buffer.c         | 127 ++++++++++++++++++++++++++++++-----
 dlls/mfplat/main.c           |  28 --------
 dlls/mfplat/mediatype.c      |   1 -
 dlls/mfplat/mfplat_private.h |  29 ++++++++
 dlls/mfplat/queue.c          |   1 -
 dlls/mfplat/tests/mfplat.c   |  74 +++++++++++++++++++-
 6 files changed, 209 insertions(+), 51 deletions(-)

diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c
index f60c015c6c..833ec041a9 100644
--- a/dlls/mfplat/buffer.c
+++ b/dlls/mfplat/buffer.c
@@ -21,7 +21,6 @@
 #include "mfplat_private.h"
 
 #include "wine/debug.h"
-#include "wine/heap.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
 
@@ -39,6 +38,12 @@ struct sample
 {
     struct attributes attributes;
     IMFSample IMFSample_iface;
+
+    IMFMediaBuffer **buffers;
+    size_t buffer_count;
+    size_t capacity;
+    DWORD flags;
+    CRITICAL_SECTION cs;
 };
 
 static inline struct memory_buffer *impl_from_IMFMediaBuffer(IMFMediaBuffer *iface)
@@ -258,11 +263,16 @@ 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)
     {
+        for (i = 0; i < sample->buffer_count; ++i)
+            IMFMediaBuffer_Release(sample->buffers[i]);
+        DeleteCriticalSection(&sample->cs);
+        heap_free(sample->buffers);
         heap_free(sample);
     }
 
@@ -453,9 +463,15 @@ static HRESULT WINAPI sample_CopyAllItems(IMFSample *iface, IMFAttributes *dest)
 
 static HRESULT WINAPI sample_GetSampleFlags(IMFSample *iface, DWORD *flags)
 {
-    FIXME("%p, %p.\n", iface, flags);
+    struct sample *sample = impl_from_IMFSample(iface);
 
-    return E_NOTIMPL;
+    TRACE("%p, %p.\n", iface, flags);
+
+    EnterCriticalSection(&sample->cs);
+    *flags = sample->flags;
+    LeaveCriticalSection(&sample->cs);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI sample_SetSampleFlags(IMFSample *iface, DWORD flags)
@@ -495,19 +511,38 @@ static HRESULT WINAPI sample_SetSampleDuration(IMFSample *iface, LONGLONG durati
 
 static HRESULT WINAPI sample_GetBufferCount(IMFSample *iface, DWORD *count)
 {
-    FIXME("%p, %p.\n", iface, count);
+    struct sample *sample = impl_from_IMFSample(iface);
+
+    TRACE("%p, %p.\n", iface, count);
+
+    if (!count)
+        return E_INVALIDARG;
 
-    if (*count)
-        *count = 0;
+    EnterCriticalSection(&sample->cs);
+    *count = sample->buffer_count;
+    EnterCriticalSection(&sample->cs);
 
     return S_OK;
 }
 
 static HRESULT WINAPI sample_GetBufferByIndex(IMFSample *iface, DWORD index, IMFMediaBuffer **buffer)
 {
-    FIXME("%p, %u, %p.\n", iface, index, buffer);
+    struct sample *sample = impl_from_IMFSample(iface);
+    HRESULT hr = S_OK;
 
-    return E_NOTIMPL;
+    TRACE("%p, %u, %p.\n", iface, index, buffer);
+
+    EnterCriticalSection(&sample->cs);
+    if (index < sample->buffer_count)
+    {
+        *buffer = sample->buffers[index];
+        IMFMediaBuffer_AddRef(*buffer);
+    }
+    else
+        hr = E_INVALIDARG;
+    LeaveCriticalSection(&sample->cs);
+
+    return hr;
 }
 
 static HRESULT WINAPI sample_ConvertToContiguousBuffer(IMFSample *iface, IMFMediaBuffer **buffer)
@@ -519,30 +554,85 @@ static HRESULT WINAPI sample_ConvertToContiguousBuffer(IMFSample *iface, IMFMedi
 
 static HRESULT WINAPI sample_AddBuffer(IMFSample *iface, IMFMediaBuffer *buffer)
 {
-    FIXME("%p, %p.\n", iface, buffer);
+    struct sample *sample = impl_from_IMFSample(iface);
+    HRESULT hr = S_OK;
 
-    return E_NOTIMPL;
+    TRACE("%p, %p.\n", iface, buffer);
+
+    EnterCriticalSection(&sample->cs);
+    if (!mf_array_reserve((void **)&sample->buffers, &sample->capacity, sample->buffer_count + 1,
+            sizeof(*sample->buffers)))
+        hr = E_OUTOFMEMORY;
+    else
+    {
+        sample->buffers[sample->buffer_count++] = buffer;
+        IMFMediaBuffer_AddRef(buffer);
+    }
+    LeaveCriticalSection(&sample->cs);
+
+    return hr;
 }
 
 static HRESULT WINAPI sample_RemoveBufferByIndex(IMFSample *iface, DWORD index)
 {
-    FIXME("%p, %u.\n", iface, index);
+    struct sample *sample = impl_from_IMFSample(iface);
+    HRESULT hr = S_OK;
 
-    return E_NOTIMPL;
+    TRACE("%p, %u.\n", iface, index);
+
+    EnterCriticalSection(&sample->cs);
+    if (index < sample->buffer_count)
+    {
+        IMFMediaBuffer_Release(sample->buffers[index]);
+        if (index < sample->buffer_count - 1)
+        {
+            memmove(&sample->buffers[index], &sample->buffers[index+1],
+                    (sample->buffer_count - index - 1) * sizeof(*sample->buffers));
+        }
+        sample->buffer_count--;
+    }
+    else
+        hr = E_INVALIDARG;
+    LeaveCriticalSection(&sample->cs);
+
+    return hr;
 }
 
 static HRESULT WINAPI sample_RemoveAllBuffers(IMFSample *iface)
 {
-    FIXME("%p.\n", iface);
+    struct sample *sample = impl_from_IMFSample(iface);
+    size_t i;
 
-    return E_NOTIMPL;
+    TRACE("%p.\n", iface);
+
+    EnterCriticalSection(&sample->cs);
+    for (i = 0; i < sample->buffer_count; ++i)
+         IMFMediaBuffer_Release(sample->buffers[i]);
+    sample->buffer_count = 0;
+    LeaveCriticalSection(&sample->cs);
+
+    return S_OK;
 }
 
-static HRESULT WINAPI sample_GetTotalLength(IMFSample *iface, DWORD *length)
+static HRESULT WINAPI sample_GetTotalLength(IMFSample *iface, DWORD *total_length)
 {
-    FIXME("%p, %p.\n", iface, length);
+    struct sample *sample = impl_from_IMFSample(iface);
+    DWORD length;
+    size_t i;
 
-    return E_NOTIMPL;
+    TRACE("%p, %p.\n", iface, total_length);
+
+    *total_length = 0;
+
+    EnterCriticalSection(&sample->cs);
+    for (i = 0; i < sample->buffer_count; ++i)
+    {
+        if (SUCCEEDED(IMFMediaBuffer_GetCurrentLength(sample->buffers[i], &length)))
+            *total_length += length;
+    }
+    LeaveCriticalSection(&sample->cs);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI sample_CopyToBuffer(IMFSample *iface, IMFMediaBuffer *buffer)
@@ -612,12 +702,13 @@ HRESULT WINAPI MFCreateSample(IMFSample **sample)
 
     TRACE("%p.\n", sample);
 
-    object = heap_alloc(sizeof(*object));
+    object = heap_alloc_zero(sizeof(*object));
     if (!object)
         return E_OUTOFMEMORY;
 
     init_attribute_object(&object->attributes, 0);
     object->IMFSample_iface.lpVtbl = &samplevtbl;
+    InitializeCriticalSection(&object->cs);
 
     *sample = &object->IMFSample_iface;
 
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
index 787c40c6b6..2d7e02e473 100644
--- a/dlls/mfplat/main.c
+++ b/dlls/mfplat/main.c
@@ -29,7 +29,6 @@
 
 #include "initguid.h"
 
-#include "wine/heap.h"
 #include "wine/debug.h"
 #include "wine/unicode.h"
 #include "wine/list.h"
@@ -129,33 +128,6 @@ static BOOL GUIDFromString(LPCWSTR s, GUID *id)
     return FALSE;
 }
 
-static BOOL mf_array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
-{
-    size_t new_capacity, max_capacity;
-    void *new_elements;
-
-    if (count <= *capacity)
-        return TRUE;
-
-    max_capacity = ~(SIZE_T)0 / size;
-    if (count > max_capacity)
-        return FALSE;
-
-    new_capacity = max(4, *capacity);
-    while (new_capacity < count && new_capacity <= max_capacity / 2)
-        new_capacity *= 2;
-    if (new_capacity < count)
-        new_capacity = max_capacity;
-
-    if (!(new_elements = heap_realloc(*elements, new_capacity * size)))
-        return FALSE;
-
-    *elements = new_elements;
-    *capacity = new_capacity;
-
-    return TRUE;
-}
-
 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
 {
     switch (reason)
diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c
index 195ab38da5..7abbf31796 100644
--- a/dlls/mfplat/mediatype.c
+++ b/dlls/mfplat/mediatype.c
@@ -21,7 +21,6 @@
 #include "mfplat_private.h"
 
 #include "wine/debug.h"
-#include "wine/heap.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
 
diff --git a/dlls/mfplat/mfplat_private.h b/dlls/mfplat/mfplat_private.h
index e5b0647e63..72f8f684f6 100644
--- a/dlls/mfplat/mfplat_private.h
+++ b/dlls/mfplat/mfplat_private.h
@@ -20,6 +20,8 @@
 #include "mfidl.h"
 #include "mferror.h"
 
+#include "wine/heap.h"
+
 typedef struct attributes
 {
     IMFAttributes IMFAttributes_iface;
@@ -31,3 +33,30 @@ extern void init_attribute_object(mfattributes *object, UINT32 size) DECLSPEC_HI
 extern void init_system_queues(void) DECLSPEC_HIDDEN;
 extern void shutdown_system_queues(void) DECLSPEC_HIDDEN;
 extern BOOL is_platform_locked(void) DECLSPEC_HIDDEN;
+
+static inline BOOL mf_array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
+{
+    size_t new_capacity, max_capacity;
+    void *new_elements;
+
+    if (count <= *capacity)
+        return TRUE;
+
+    max_capacity = ~(SIZE_T)0 / size;
+    if (count > max_capacity)
+        return FALSE;
+
+    new_capacity = max(4, *capacity);
+    while (new_capacity < count && new_capacity <= max_capacity / 2)
+        new_capacity *= 2;
+    if (new_capacity < count)
+        new_capacity = max_capacity;
+
+    if (!(new_elements = heap_realloc(*elements, new_capacity * size)))
+        return FALSE;
+
+    *elements = new_elements;
+    *capacity = new_capacity;
+
+    return TRUE;
+}
diff --git a/dlls/mfplat/queue.c b/dlls/mfplat/queue.c
index 4d3322840c..1b9ef38a4e 100644
--- a/dlls/mfplat/queue.c
+++ b/dlls/mfplat/queue.c
@@ -21,7 +21,6 @@
 #define COBJMACROS
 
 #include "wine/debug.h"
-#include "wine/heap.h"
 #include "wine/list.h"
 
 #include "mfplat_private.h"
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 674bcf418e..19ec6ec6d1 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -714,19 +714,87 @@ static void test_system_memory_buffer(void)
     IMFMediaBuffer_Release(buffer);
 }
 
-static void test_MFSample(void)
+static void test_sample(void)
 {
+    IMFMediaBuffer *buffer, *buffer2;
+    DWORD count, flags, length;
     IMFSample *sample;
+    LONGLONG time;
     HRESULT hr;
-    UINT32 count;
 
     hr = MFCreateSample( &sample );
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
+    hr = IMFSample_GetBufferCount(sample, NULL);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
     hr = IMFSample_GetBufferCount(sample, &count);
     ok(hr == S_OK, "got 0x%08x\n", hr);
     ok(count == 0, "got %d\n", count);
 
+    hr = IMFSample_GetSampleFlags(sample, &flags);
+    ok(hr == S_OK, "Failed to get sample flags, hr %#x.\n", hr);
+    ok(!flags, "Unexpected flags %#x.\n", flags);
+
+    hr = IMFSample_GetSampleTime(sample, &time);
+todo_wine
+    ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFSample_GetSampleDuration(sample, &time);
+todo_wine
+    ok(hr == MF_E_NO_SAMPLE_DURATION, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFSample_GetBufferByIndex(sample, 0, &buffer);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFSample_RemoveBufferByIndex(sample, 0);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFSample_RemoveAllBuffers(sample);
+    ok(hr == S_OK, "Failed to remove all, hr %#x.\n", hr);
+
+    hr = IMFSample_GetTotalLength(sample, &length);
+    ok(hr == S_OK, "Failed to get total length, hr %#x.\n", hr);
+    ok(!length, "Unexpected total length %u.\n", length);
+
+    hr = MFCreateMemoryBuffer(16, &buffer);
+    ok(hr == S_OK, "Failed to create buffer, hr %#x.\n", hr);
+
+    hr = IMFSample_AddBuffer(sample, buffer);
+    ok(hr == S_OK, "Failed to add buffer, hr %#x.\n", hr);
+
+    hr = IMFSample_AddBuffer(sample, buffer);
+    ok(hr == S_OK, "Failed to add buffer, hr %#x.\n", hr);
+
+    hr = IMFSample_GetBufferCount(sample, &count);
+    ok(hr == S_OK, "Failed to get buffer count, hr %#x.\n", hr);
+    ok(count == 2, "Unexpected buffer count %u.\n", count);
+
+    hr = IMFSample_GetBufferByIndex(sample, 0, &buffer2);
+    ok(hr == S_OK, "Failed to get buffer, hr %#x.\n", hr);
+    ok(buffer2 == buffer, "Unexpected object.\n");
+    IMFMediaBuffer_Release(buffer2);
+
+    hr = IMFSample_GetTotalLength(sample, &length);
+    ok(hr == S_OK, "Failed to get total length, hr %#x.\n", hr);
+    ok(!length, "Unexpected total length %u.\n", length);
+
+    hr = IMFMediaBuffer_SetCurrentLength(buffer, 2);
+    ok(hr == S_OK, "Failed to set current length, hr %#x.\n", hr);
+
+    hr = IMFSample_GetTotalLength(sample, &length);
+    ok(hr == S_OK, "Failed to get total length, hr %#x.\n", hr);
+    ok(length == 4, "Unexpected total length %u.\n", length);
+
+    hr = IMFSample_RemoveBufferByIndex(sample, 1);
+    ok(hr == S_OK, "Failed to remove buffer, hr %#x.\n", hr);
+
+    hr = IMFSample_GetTotalLength(sample, &length);
+    ok(hr == S_OK, "Failed to get total length, hr %#x.\n", hr);
+    ok(length == 2, "Unexpected total length %u.\n", length);
+
+    IMFMediaBuffer_Release(buffer);
+
     IMFSample_Release(sample);
 }
 
@@ -1541,7 +1609,7 @@ START_TEST(mfplat)
     test_MFCreateMediaType();
     test_MFCreateMediaEvent();
     test_MFCreateAttributes();
-    test_MFSample();
+    test_sample();
     test_MFCreateFile();
     test_MFCreateMFByteStreamOnStream();
     test_system_memory_buffer();
-- 
2.20.1




More information about the wine-devel mailing list