mfplat: Implement CopyToBuffer().

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Nikolay Sivov 2020-03-10 15:22:57 +03:00 committed by Alexandre Julliard
parent 68da7ea97d
commit b50c7c7999
2 changed files with 160 additions and 11 deletions

View File

@ -771,22 +771,29 @@ static HRESULT WINAPI sample_RemoveAllBuffers(IMFSample *iface)
return S_OK;
}
static DWORD sample_get_total_length(struct sample *sample)
{
DWORD total_length = 0, length;
size_t i;
for (i = 0; i < sample->buffer_count; ++i)
{
length = 0;
if (SUCCEEDED(IMFMediaBuffer_GetCurrentLength(sample->buffers[i], &length)))
total_length += length;
}
return total_length;
}
static HRESULT WINAPI sample_GetTotalLength(IMFSample *iface, DWORD *total_length)
{
struct sample *sample = impl_from_IMFSample(iface);
DWORD 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)
{
if (SUCCEEDED(IMFMediaBuffer_GetCurrentLength(sample->buffers[i], &length)))
*total_length += length;
}
*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, &current_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, &current_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 =

View File

@ -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);