Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/mfplat/buffer.c | 81 +++++++++++++++++++++++++++++-----
dlls/mfplat/tests/mfplat.c | 90 ++++++++++++++++++++++++++++++++++++++
2 files changed, 160 insertions(+), 11 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c
index 8e54a538f6..07c2517788 100644
--- a/dlls/mfplat/buffer.c
+++ b/dlls/mfplat/buffer.c
@@ -771,22 +771,29 @@ static HRESULT WINAPI sample_RemoveAllBuffers(IMFSample *iface)
return S_OK;
}
-static HRESULT WINAPI sample_GetTotalLength(IMFSample *iface, DWORD *total_length)
+static DWORD sample_get_total_length(struct sample *sample)
{
- struct sample *sample = impl_from_IMFSample(iface);
- DWORD length;
+ DWORD total_length = 0, length;
size_t i;
- TRACE("%p, %p.\n", iface, total_length);
-
- *total_length = 0;
-
- EnterCriticalSection(&sample->attributes.cs);
for (i = 0; i < sample->buffer_count; ++i)
{
+ length = 0;
if (SUCCEEDED(IMFMediaBuffer_GetCurrentLength(sample->buffers[i], &length)))
- *total_length += length;
+ total_length += length;
}
+
+ return total_length;
+}
+
+static HRESULT WINAPI sample_GetTotalLength(IMFSample *iface, DWORD *total_length)
+{
+ struct sample *sample = impl_from_IMFSample(iface);
+
+ TRACE("%p, %p.\n", iface, total_length);
+
+ EnterCriticalSection(&sample->attributes.cs);
+ *total_length = sample_get_total_length(sample);
LeaveCriticalSection(&sample->attributes.cs);
return S_OK;
@@ -794,9 +801,61 @@ static HRESULT WINAPI sample_GetTotalLength(IMFSample *iface, DWORD *total_lengt
static HRESULT WINAPI sample_CopyToBuffer(IMFSample *iface, IMFMediaBuffer *buffer)
{
- FIXME("%p, %p.\n", iface, buffer);
+ struct sample *sample = impl_from_IMFSample(iface);
+ DWORD total_length, dst_length, dst_current_length, src_max_length, current_length;
+ BYTE *src_ptr, *dst_ptr;
+ BOOL locked;
+ HRESULT hr;
+ size_t i;
- return E_NOTIMPL;
+ TRACE("%p, %p.\n", iface, buffer);
+
+ EnterCriticalSection(&sample->attributes.cs);
+
+ total_length = sample_get_total_length(sample);
+ dst_current_length = 0;
+
+ dst_ptr = NULL;
+ dst_length = current_length = 0;
+ locked = SUCCEEDED(hr = IMFMediaBuffer_Lock(buffer, &dst_ptr, &dst_length, ¤t_length));
+ if (locked)
+ {
+ if (dst_length < total_length)
+ hr = MF_E_BUFFERTOOSMALL;
+ else if (dst_ptr)
+ {
+ for (i = 0; i < sample->buffer_count && SUCCEEDED(hr); ++i)
+ {
+ src_ptr = NULL;
+ src_max_length = current_length = 0;
+ if (SUCCEEDED(hr = IMFMediaBuffer_Lock(sample->buffers[i], &src_ptr, &src_max_length, ¤t_length)))
+ {
+ if (src_ptr)
+ {
+ if (current_length > dst_length)
+ hr = MF_E_BUFFERTOOSMALL;
+ else if (current_length)
+ {
+ memcpy(dst_ptr, src_ptr, current_length);
+ dst_length -= current_length;
+ dst_current_length += current_length;
+ dst_ptr += current_length;
+ }
+ }
+ IMFMediaBuffer_Unlock(sample->buffers[i]);
+ }
+ }
+ }
+ }
+
+ IMFMediaBuffer_SetCurrentLength(buffer, dst_current_length);
+
+ if (locked)
+ IMFMediaBuffer_Unlock(buffer);
+
+ LeaveCriticalSection(&sample->attributes.cs);
+
+ return hr;
}
static const IMFSampleVtbl samplevtbl =
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 36fe9dc831..38713a4f44 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -1760,12 +1760,14 @@ static void test_system_memory_buffer(void)
static void test_sample(void)
{
+ static const DWORD test_pattern = 0x22222222;
IMFMediaBuffer *buffer, *buffer2;
DWORD count, flags, length;
IMFAttributes *attributes;
IMFSample *sample;
LONGLONG time;
HRESULT hr;
+ BYTE *data;
hr = MFCreateSample( &sample );
ok(hr == S_OK, "got 0x%08x\n", hr);
@@ -1868,6 +1870,94 @@ static void test_sample(void)
IMFAttributes_Release(attributes);
IMFSample_Release(sample);
+ /* CopyToBuffer() */
+ hr = MFCreateSample(&sample);
+ ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr);
+
+ hr = MFCreateMemoryBuffer(16, &buffer2);
+ ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr);
+
+ /* Sample with no buffers. */
+ hr = IMFMediaBuffer_SetCurrentLength(buffer2, 1);
+ ok(hr == S_OK, "Failed to set current length, hr %#x.\n", hr);
+ hr = IMFSample_CopyToBuffer(sample, buffer2);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = IMFMediaBuffer_GetCurrentLength(buffer2, &length);
+ ok(hr == S_OK, "Failed to get current length, hr %#x.\n", hr);
+ ok(!length, "Unexpected length %u.\n", length);
+
+ /* Single buffer, larger destination. */
+ hr = MFCreateMemoryBuffer(8, &buffer);
+ ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr);
+
+ hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL);
+ ok(hr == S_OK, "Failed to lock buffer, hr %#x.\n", hr);
+ *(DWORD *)data = 0x11111111;
+ hr = IMFMediaBuffer_Unlock(buffer);
+ ok(hr == S_OK, "Failed to unlock, hr %#x.\n", hr);
+ hr = IMFMediaBuffer_SetCurrentLength(buffer, 4);
+ ok(hr == S_OK, "Failed to set current length, hr %#x.\n", hr);
+
+ hr = IMFSample_AddBuffer(sample, buffer);
+ ok(hr == S_OK, "Failed to add buffer, hr %#x.\n", hr);
+
+ /* Existing content is overwritten. */
+ hr = IMFMediaBuffer_SetCurrentLength(buffer2, 8);
+ ok(hr == S_OK, "Failed to set length, hr %#x.\n", hr);
+
+ hr = IMFSample_CopyToBuffer(sample, buffer2);
+ ok(hr == S_OK, "Failed to copy to buffer, hr %#x.\n", hr);
+
+ hr = IMFMediaBuffer_GetCurrentLength(buffer2, &length);
+ ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr);
+ ok(length == 4, "Unexpected buffer length %u.\n", length);
+
+ /* Multiple buffers, matching total size. */
+ 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 = IMFMediaBuffer_SetCurrentLength(buffer, 8);
+ ok(hr == S_OK, "Failed to set current length, hr %#x.\n", hr);
+
+ hr = IMFSample_CopyToBuffer(sample, buffer2);
+ ok(hr == S_OK, "Failed to copy to buffer, hr %#x.\n", hr);
+
+ hr = IMFMediaBuffer_GetCurrentLength(buffer2, &length);
+ ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr);
+ ok(length == 16, "Unexpected buffer length %u.\n", length);
+
+ hr = IMFSample_AddBuffer(sample, buffer);
+ ok(hr == S_OK, "Failed to add buffer, hr %#x.\n", hr);
+
+ hr = IMFMediaBuffer_SetCurrentLength(buffer2, 1);
+ ok(hr == S_OK, "Failed to set buffer length, hr %#x.\n", hr);
+
+ hr = IMFMediaBuffer_Lock(buffer2, &data, NULL, NULL);
+ ok(hr == S_OK, "Failed to lock buffer, hr %#x.\n", hr);
+ *(DWORD *)data = test_pattern;
+ hr = IMFMediaBuffer_Unlock(buffer2);
+ ok(hr == S_OK, "Failed to unlock buffer, hr %#x.\n", hr);
+
+ hr = IMFSample_CopyToBuffer(sample, buffer2);
+ ok(hr == MF_E_BUFFERTOOSMALL, "Unexpected hr %#x.\n", hr);
+
+ hr = IMFMediaBuffer_Lock(buffer2, &data, NULL, NULL);
+ ok(hr == S_OK, "Failed to lock buffer, hr %#x.\n", hr);
+ ok(!memcmp(data, &test_pattern, sizeof(test_pattern)), "Unexpected contents, %#x\n", *(DWORD *)data);
+ hr = IMFMediaBuffer_Unlock(buffer2);
+ ok(hr == S_OK, "Failed to unlock buffer, hr %#x.\n", hr);
+
+ hr = IMFMediaBuffer_GetCurrentLength(buffer2, &length);
+ ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr);
+ ok(!length, "Unexpected buffer length %u.\n", length);
+
+ IMFMediaBuffer_Release(buffer2);
+ IMFSample_Release(sample);
+
/* ConvertToContiguousBuffer() */
hr = MFCreateSample(&sample);
ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr);
--
2.25.1