[PATCH 1/9] mfplat: Implement MFCreateMediaBufferFromMediaType() for audio types.

Nikolay Sivov nsivov at codeweavers.com
Fri Mar 13 07:34:30 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/mfplat/buffer.c       | 62 ++++++++++++++++++++++++++++++++++
 dlls/mfplat/mfplat.spec    |  1 +
 dlls/mfplat/tests/mfplat.c | 68 ++++++++++++++++++++++++++++++++++++++
 include/mfapi.h            |  2 ++
 4 files changed, 133 insertions(+)

diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c
index 590288e344..b1d353a59b 100644
--- a/dlls/mfplat/buffer.c
+++ b/dlls/mfplat/buffer.c
@@ -448,6 +448,68 @@ HRESULT WINAPI MFCreate2DMediaBuffer(DWORD width, DWORD height, DWORD fourcc, BO
     return create_2d_buffer(width, height, fourcc, buffer);
 }
 
+static unsigned int buffer_get_aligned_length(unsigned int length, unsigned int alignment)
+{
+    length = (length + alignment) / alignment;
+    length *= alignment;
+
+    return length;
+}
+
+HRESULT WINAPI MFCreateMediaBufferFromMediaType(IMFMediaType *media_type, LONGLONG duration, DWORD min_length,
+        DWORD alignment, IMFMediaBuffer **buffer)
+{
+    UINT32 length = 0, block_alignment;
+    LONGLONG avg_length;
+    HRESULT hr;
+    GUID major;
+
+    TRACE("%p, %s, %u, %u, %p.\n", media_type, wine_dbgstr_longlong(duration), min_length, alignment, buffer);
+
+    if (!media_type)
+        return E_INVALIDARG;
+
+    if (FAILED(hr = IMFMediaType_GetMajorType(media_type, &major)))
+        return hr;
+
+    if (IsEqualGUID(&major, &MFMediaType_Audio))
+    {
+        block_alignment = 0;
+        if (FAILED(IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_alignment)))
+            WARN("Block alignment was not specified.\n");
+
+        if (block_alignment)
+        {
+            avg_length = 0;
+
+            if (duration)
+            {
+                length = 0;
+                if (SUCCEEDED(IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &length)))
+                {
+                    /* 100 ns -> 1 s */
+                    avg_length = length * duration / (10 * 1000 * 1000);
+                }
+            }
+
+            alignment = max(16, alignment);
+
+            length = buffer_get_aligned_length(avg_length + 1, alignment);
+            length = buffer_get_aligned_length(length, block_alignment);
+        }
+        else
+            length = 0;
+
+        length = max(length, min_length);
+
+        return create_1d_buffer(length, MF_1_BYTE_ALIGNMENT, buffer);
+    }
+    else
+        FIXME("Major type %s is not supported.\n", debugstr_guid(&major));
+
+    return E_NOTIMPL;
+}
+
 static HRESULT WINAPI sample_QueryInterface(IMFSample *iface, REFIID riid, void **out)
 {
     TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec
index 2fb6388a31..9f08d1aff2 100644
--- a/dlls/mfplat/mfplat.spec
+++ b/dlls/mfplat/mfplat.spec
@@ -52,6 +52,7 @@
 @ stdcall MFCreateMFByteStreamOnStreamEx(ptr ptr)
 @ stdcall MFCreateMFByteStreamWrapper(ptr ptr)
 @ stub MFCreateMFVideoFormatFromMFMediaType
+@ stdcall MFCreateMediaBufferFromMediaType(ptr int64 long long ptr)
 @ stub MFCreateMediaBufferWrapper
 @ stdcall MFCreateMediaEvent(long ptr long ptr ptr)
 @ stdcall MFCreateMediaType(ptr)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 31194db77f..7134c62a79 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -95,6 +95,8 @@ static HRESULT (WINAPI *pMFGetPlaneSize)(DWORD format, DWORD width, DWORD height
 static HRESULT (WINAPI *pMFGetStrideForBitmapInfoHeader)(DWORD format, DWORD width, LONG *stride);
 static HRESULT (WINAPI *pMFCreate2DMediaBuffer)(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up,
         IMFMediaBuffer **buffer);
+static HRESULT (WINAPI *pMFCreateMediaBufferFromMediaType)(IMFMediaType *media_type, LONGLONG duration, DWORD min_length,
+        DWORD min_alignment, IMFMediaBuffer **buffer);
 
 static const WCHAR fileschemeW[] = L"file://";
 
@@ -665,6 +667,7 @@ static void init_functions(void)
     X(MFCreate2DMediaBuffer);
     X(MFCreateDXGIDeviceManager);
     X(MFCreateSourceResolver);
+    X(MFCreateMediaBufferFromMediaType);
     X(MFCreateMFByteStreamOnStream);
     X(MFCreateTransformActivate);
     X(MFGetPlaneSize);
@@ -4587,6 +4590,70 @@ static void test_MFCreate2DMediaBuffer(void)
     IMFMediaBuffer_Release(buffer);
 }
 
+static void test_MFCreateMediaBufferFromMediaType(void)
+{
+    static struct audio_buffer_test
+    {
+        unsigned int duration;
+        unsigned int min_length;
+        unsigned int min_alignment;
+        unsigned int block_alignment;
+        unsigned int bytes_per_second;
+        unsigned int buffer_length;
+    } audio_tests[] =
+    {
+        { 0,  0,  0,  4,  0, 20 },
+        { 0, 16,  0,  4,  0, 20 },
+        { 0,  0, 32,  4,  0, 36 },
+        { 0, 64, 32,  4,  0, 64 },
+        { 1,  0,  0,  4, 16, 36 },
+        { 2,  0,  0,  4, 16, 52 },
+    };
+    IMFMediaBuffer *buffer;
+    UINT32 length;
+    HRESULT hr;
+    IMFMediaType *media_type;
+    unsigned int i;
+
+    if (!pMFCreateMediaBufferFromMediaType)
+    {
+        win_skip("MFCreateMediaBufferFromMediaType() is not available.\n");
+        return;
+    }
+
+    hr = pMFCreateMediaBufferFromMediaType(NULL, 0, 0, 0, &buffer);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = MFCreateMediaType(&media_type);
+    ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
+
+    hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
+    ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
+
+    for (i = 0; i < ARRAY_SIZE(audio_tests); ++i)
+    {
+        const struct audio_buffer_test *ptr = &audio_tests[i];
+
+        hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, ptr->block_alignment);
+        ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
+
+        hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, ptr->bytes_per_second);
+        ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
+
+        hr = pMFCreateMediaBufferFromMediaType(media_type, ptr->duration * 10000000, ptr->min_length,
+                ptr->min_alignment, &buffer);
+        ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+        hr = IMFMediaBuffer_GetMaxLength(buffer, &length);
+        ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr);
+        ok(ptr->buffer_length == length, "%d: unexpected buffer length %u, expected %u.\n", i, length, ptr->buffer_length);
+
+        IMFMediaBuffer_Release(buffer);
+    }
+
+    IMFMediaType_Release(media_type);
+}
+
 START_TEST(mfplat)
 {
     char **argv;
@@ -4640,6 +4707,7 @@ START_TEST(mfplat)
     test_queue_com();
     test_MFGetStrideForBitmapInfoHeader();
     test_MFCreate2DMediaBuffer();
+    test_MFCreateMediaBufferFromMediaType();
 
     CoUninitialize();
 }
diff --git a/include/mfapi.h b/include/mfapi.h
index 9f4db44d1e..9c22b6bfd8 100644
--- a/include/mfapi.h
+++ b/include/mfapi.h
@@ -411,6 +411,8 @@ HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **man
 HRESULT WINAPI MFCreateEventQueue(IMFMediaEventQueue **queue);
 HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags,
                             LPCWSTR url, IMFByteStream **bytestream);
+HRESULT WINAPI MFCreateMediaBufferFromMediaType(IMFMediaType *media_type, LONGLONG duration, DWORD min_length,
+        DWORD min_alignment, IMFMediaBuffer **buffer);
 HRESULT WINAPI MFCreateMediaEvent(MediaEventType type, REFGUID extended_type, HRESULT status,
                                   const PROPVARIANT *value, IMFMediaEvent **event);
 HRESULT WINAPI MFCreateMediaType(IMFMediaType **type);
-- 
2.25.1




More information about the wine-devel mailing list