Nikolay Sivov : mfplat: Implement CopyToBuffer().

Alexandre Julliard julliard at winehq.org
Tue Mar 10 16:24:58 CDT 2020


Module: wine
Branch: master
Commit: b50c7c799908b059085b5fec4e6bc90747de3e5a
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=b50c7c799908b059085b5fec4e6bc90747de3e5a

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Tue Mar 10 15:22:57 2020 +0300

mfplat: Implement CopyToBuffer().

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 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, &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 =
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);




More information about the wine-cvs mailing list