Nikolay Sivov : mfplat: Implement ConvertToContiguousBuffer() for multiple buffers.

Alexandre Julliard julliard at winehq.org
Tue Mar 17 17:21:09 CDT 2020


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Tue Mar 17 17:10:29 2020 +0300

mfplat: Implement ConvertToContiguousBuffer() for multiple buffers.

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

---

 dlls/mfplat/buffer.c       | 110 ++++++++++++++++++++++++++++++++++++---------
 dlls/mfplat/tests/mfplat.c |  23 +++++++---
 2 files changed, 107 insertions(+), 26 deletions(-)

diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c
index 69633134f5..1727ff1e90 100644
--- a/dlls/mfplat/buffer.c
+++ b/dlls/mfplat/buffer.c
@@ -1136,9 +1136,78 @@ static HRESULT WINAPI sample_GetBufferByIndex(IMFSample *iface, DWORD index, IMF
     return hr;
 }
 
+static unsigned int 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 sample_copy_to_buffer(struct sample *sample, IMFMediaBuffer *buffer)
+{
+    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;
+
+    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);
+
+    return hr;
+}
+
 static HRESULT WINAPI sample_ConvertToContiguousBuffer(IMFSample *iface, IMFMediaBuffer **buffer)
 {
     struct sample *sample = impl_from_IMFSample(iface);
+    unsigned int total_length, i;
+    IMFMediaBuffer *dest_buffer;
     HRESULT hr = S_OK;
 
     TRACE("%p, %p.\n", iface, buffer);
@@ -1147,15 +1216,29 @@ static HRESULT WINAPI sample_ConvertToContiguousBuffer(IMFSample *iface, IMFMedi
 
     if (sample->buffer_count == 0)
         hr = E_UNEXPECTED;
-    else if (sample->buffer_count == 1)
+    else if (sample->buffer_count > 1)
     {
-        *buffer = sample->buffers[0];
-        IMFMediaBuffer_AddRef(*buffer);
+        total_length = sample_get_total_length(sample);
+        if (SUCCEEDED(hr = MFCreateMemoryBuffer(total_length, &dest_buffer)))
+        {
+            if (SUCCEEDED(hr = sample_copy_to_buffer(sample, dest_buffer)))
+            {
+                for (i = 0; i < sample->buffer_count; ++i)
+                    IMFMediaBuffer_Release(sample->buffers[i]);
+
+                sample->buffers[0] = dest_buffer;
+                IMFMediaBuffer_AddRef(sample->buffers[0]);
+
+                sample->buffer_count = 1;
+            }
+            IMFMediaBuffer_Release(dest_buffer);
+        }
     }
-    else
+
+    if (SUCCEEDED(hr))
     {
-        FIXME("Samples with multiple buffers are not supported.\n");
-        hr = E_NOTIMPL;
+        *buffer = sample->buffers[0];
+        IMFMediaBuffer_AddRef(*buffer);
     }
 
     LeaveCriticalSection(&sample->attributes.cs);
@@ -1225,21 +1308,6 @@ 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);
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 008aa05c30..21105f5ce5 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -1778,7 +1778,7 @@ static void test_system_memory_buffer(void)
 static void test_sample(void)
 {
     static const DWORD test_pattern = 0x22222222;
-    IMFMediaBuffer *buffer, *buffer2;
+    IMFMediaBuffer *buffer, *buffer2, *buffer3;
     DWORD count, flags, length;
     IMFAttributes *attributes;
     IMFSample *sample;
@@ -1998,9 +1998,15 @@ static void test_sample(void)
     ok(buffer2 == buffer, "Unexpected buffer instance.\n");
     IMFMediaBuffer_Release(buffer2);
 
+    hr = IMFMediaBuffer_SetCurrentLength(buffer, 3);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
     hr = MFCreateMemoryBuffer(16, &buffer2);
     ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr);
 
+    hr = IMFMediaBuffer_SetCurrentLength(buffer2, 4);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
     hr = IMFSample_AddBuffer(sample, buffer2);
     ok(hr == S_OK, "Failed to add buffer, hr %#x.\n", hr);
     IMFMediaBuffer_Release(buffer2);
@@ -2009,15 +2015,22 @@ static void test_sample(void)
     ok(hr == S_OK, "Failed to get buffer count, hr %#x.\n", hr);
     ok(count == 2, "Unexpected buffer count %u.\n", count);
 
-    hr = IMFSample_ConvertToContiguousBuffer(sample, &buffer2);
-todo_wine
+    hr = IMFSample_ConvertToContiguousBuffer(sample, &buffer3);
     ok(hr == S_OK, "Failed to convert, hr %#x.\n", hr);
+
+    hr = IMFMediaBuffer_GetMaxLength(buffer3, &length);
+    ok(hr == S_OK, "Failed to get maximum length, hr %#x.\n", hr);
+    ok(length == 7, "Unexpected length %u.\n", length);
+
+    hr = IMFMediaBuffer_GetCurrentLength(buffer3, &length);
+    ok(hr == S_OK, "Failed to get maximum length, hr %#x.\n", hr);
+    ok(length == 7, "Unexpected length %u.\n", length);
+
     if (SUCCEEDED(hr))
-        IMFMediaBuffer_Release(buffer2);
+        IMFMediaBuffer_Release(buffer3);
 
     hr = IMFSample_GetBufferCount(sample, &count);
     ok(hr == S_OK, "Failed to get buffer count, hr %#x.\n", hr);
-todo_wine
     ok(count == 1, "Unexpected buffer count %u.\n", count);
 
     IMFMediaBuffer_Release(buffer);




More information about the wine-cvs mailing list