[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