Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 62 +++++++++++++++++++++++++++++++++ dlls/mfplat/mfplat.spec | 1 + dlls/mfplat/tests/mfplat.c | 70 ++++++++++++++++++++++++++++++++++++++ include/mfapi.h | 2 ++ 4 files changed, 135 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..65e9b66447 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,72 @@ 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 || broken(FAILED(hr)) /* Win8 */, "Unexpected hr %#x.\n", hr); + if (FAILED(hr)) + break; + + 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 +4709,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);