mfplat: Implement buffer collection for sample.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7343fc9e69
commit
851113b06f
|
@ -21,7 +21,6 @@
|
||||||
#include "mfplat_private.h"
|
#include "mfplat_private.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
#include "wine/heap.h"
|
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
||||||
|
|
||||||
|
@ -39,6 +38,12 @@ struct sample
|
||||||
{
|
{
|
||||||
struct attributes attributes;
|
struct attributes attributes;
|
||||||
IMFSample IMFSample_iface;
|
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)
|
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);
|
struct sample *sample = impl_from_IMFSample(iface);
|
||||||
ULONG refcount = InterlockedDecrement(&sample->attributes.ref);
|
ULONG refcount = InterlockedDecrement(&sample->attributes.ref);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
TRACE("%p, refcount %u.\n", iface, refcount);
|
TRACE("%p, refcount %u.\n", iface, refcount);
|
||||||
|
|
||||||
if (!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);
|
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)
|
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)
|
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)
|
static HRESULT WINAPI sample_GetBufferCount(IMFSample *iface, DWORD *count)
|
||||||
{
|
{
|
||||||
FIXME("%p, %p.\n", iface, count);
|
struct sample *sample = impl_from_IMFSample(iface);
|
||||||
|
|
||||||
if (*count)
|
TRACE("%p, %p.\n", iface, count);
|
||||||
*count = 0;
|
|
||||||
|
if (!count)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
EnterCriticalSection(&sample->cs);
|
||||||
|
*count = sample->buffer_count;
|
||||||
|
EnterCriticalSection(&sample->cs);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI sample_GetBufferByIndex(IMFSample *iface, DWORD index, IMFMediaBuffer **buffer)
|
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)
|
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)
|
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)
|
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)
|
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)
|
static HRESULT WINAPI sample_CopyToBuffer(IMFSample *iface, IMFMediaBuffer *buffer)
|
||||||
|
@ -612,12 +702,13 @@ HRESULT WINAPI MFCreateSample(IMFSample **sample)
|
||||||
|
|
||||||
TRACE("%p.\n", sample);
|
TRACE("%p.\n", sample);
|
||||||
|
|
||||||
object = heap_alloc(sizeof(*object));
|
object = heap_alloc_zero(sizeof(*object));
|
||||||
if (!object)
|
if (!object)
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
init_attribute_object(&object->attributes, 0);
|
init_attribute_object(&object->attributes, 0);
|
||||||
object->IMFSample_iface.lpVtbl = &samplevtbl;
|
object->IMFSample_iface.lpVtbl = &samplevtbl;
|
||||||
|
InitializeCriticalSection(&object->cs);
|
||||||
|
|
||||||
*sample = &object->IMFSample_iface;
|
*sample = &object->IMFSample_iface;
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
|
|
||||||
#include "initguid.h"
|
#include "initguid.h"
|
||||||
|
|
||||||
#include "wine/heap.h"
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
#include "wine/list.h"
|
#include "wine/list.h"
|
||||||
|
@ -129,33 +128,6 @@ static BOOL GUIDFromString(LPCWSTR s, GUID *id)
|
||||||
return FALSE;
|
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)
|
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
|
||||||
{
|
{
|
||||||
switch (reason)
|
switch (reason)
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include "mfplat_private.h"
|
#include "mfplat_private.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
#include "wine/heap.h"
|
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include "mfidl.h"
|
#include "mfidl.h"
|
||||||
#include "mferror.h"
|
#include "mferror.h"
|
||||||
|
|
||||||
|
#include "wine/heap.h"
|
||||||
|
|
||||||
typedef struct attributes
|
typedef struct attributes
|
||||||
{
|
{
|
||||||
IMFAttributes IMFAttributes_iface;
|
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 init_system_queues(void) DECLSPEC_HIDDEN;
|
||||||
extern void shutdown_system_queues(void) DECLSPEC_HIDDEN;
|
extern void shutdown_system_queues(void) DECLSPEC_HIDDEN;
|
||||||
extern BOOL is_platform_locked(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;
|
||||||
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#define COBJMACROS
|
#define COBJMACROS
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
#include "wine/heap.h"
|
|
||||||
#include "wine/list.h"
|
#include "wine/list.h"
|
||||||
|
|
||||||
#include "mfplat_private.h"
|
#include "mfplat_private.h"
|
||||||
|
|
|
@ -714,19 +714,87 @@ static void test_system_memory_buffer(void)
|
||||||
IMFMediaBuffer_Release(buffer);
|
IMFMediaBuffer_Release(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_MFSample(void)
|
static void test_sample(void)
|
||||||
{
|
{
|
||||||
|
IMFMediaBuffer *buffer, *buffer2;
|
||||||
|
DWORD count, flags, length;
|
||||||
IMFSample *sample;
|
IMFSample *sample;
|
||||||
|
LONGLONG time;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
UINT32 count;
|
|
||||||
|
|
||||||
hr = MFCreateSample( &sample );
|
hr = MFCreateSample( &sample );
|
||||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
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);
|
hr = IMFSample_GetBufferCount(sample, &count);
|
||||||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||||
ok(count == 0, "got %d\n", count);
|
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);
|
IMFSample_Release(sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1541,7 +1609,7 @@ START_TEST(mfplat)
|
||||||
test_MFCreateMediaType();
|
test_MFCreateMediaType();
|
||||||
test_MFCreateMediaEvent();
|
test_MFCreateMediaEvent();
|
||||||
test_MFCreateAttributes();
|
test_MFCreateAttributes();
|
||||||
test_MFSample();
|
test_sample();
|
||||||
test_MFCreateFile();
|
test_MFCreateFile();
|
||||||
test_MFCreateMFByteStreamOnStream();
|
test_MFCreateMFByteStreamOnStream();
|
||||||
test_system_memory_buffer();
|
test_system_memory_buffer();
|
||||||
|
|
Loading…
Reference in New Issue