Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 21 +++++++- dlls/mfplat/mediatype.c | 2 + dlls/mfplat/tests/mfplat.c | 99 ++++++++++++++++++++++++++++++-------- 3 files changed, 102 insertions(+), 20 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index 05e1ce5fd6..64ec436a1e 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -546,6 +546,7 @@ static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, BOOL bo { unsigned int bpp, max_length, plane_size; struct memory_buffer *object; + unsigned int row_alignment; GUID subtype; BOOL is_yuv; HRESULT hr; @@ -572,10 +573,28 @@ static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, BOOL bo if (!object) return E_OUTOFMEMORY;
- pitch = ALIGN_SIZE(width * bpp, MF_64_BYTE_ALIGNMENT); + switch (fourcc) + { + case MAKEFOURCC('I','M','C','1'): + case MAKEFOURCC('I','M','C','2'): + case MAKEFOURCC('I','M','C','3'): + case MAKEFOURCC('I','M','C','4'): + case MAKEFOURCC('Y','V','1','2'): + row_alignment = MF_128_BYTE_ALIGNMENT; + break; + default: + row_alignment = MF_64_BYTE_ALIGNMENT; + } + + pitch = ALIGN_SIZE(width * bpp, row_alignment);
switch (fourcc) { + case MAKEFOURCC('I','M','C','1'): + case MAKEFOURCC('I','M','C','3'): + max_length = pitch * height * 2; + plane_size *= 2; + break; case MAKEFOURCC('N','V','1','2'): max_length = pitch * height * 3 / 2; break; diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c index 142ee69cf6..8c4716e5e1 100644 --- a/dlls/mfplat/mediatype.c +++ b/dlls/mfplat/mediatype.c @@ -1799,6 +1799,8 @@ static const struct uncompressed_video_format video_formats[] = { &MFVideoFormat_NV12, 1, 0, 0, 1 }, { &MFVideoFormat_D16, 2, 3, 0, 0 }, { &MFVideoFormat_L16, 2, 3, 0, 0 }, + { &MFVideoFormat_UYVY, 2, 0, 0, 1 }, + { &MFVideoFormat_YUY2, 2, 0, 0, 1 }, { &MFVideoFormat_YV12, 1, 0, 0, 1 }, { &MFVideoFormat_A16B16G16R16F, 8, 3, 1, 0 }, }; diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index c5ed883dfa..4cb5499f7c 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -3475,6 +3475,14 @@ static void test_MFCalculateImageSize(void) { &MFVideoFormat_YV12, 2, 1, 3 }, { &MFVideoFormat_YV12, 1, 2, 6, 3 }, { &MFVideoFormat_YV12, 4, 3, 18 }, + + { &MFVideoFormat_YUY2, 2, 1, 4 }, + { &MFVideoFormat_YUY2, 4, 3, 24 }, + { &MFVideoFormat_YUY2, 128, 128, 32768 }, + + { &MFVideoFormat_UYVY, 2, 1, 4 }, + { &MFVideoFormat_UYVY, 4, 3, 24 }, + { &MFVideoFormat_UYVY, 128, 128, 32768 }, }; unsigned int i; UINT32 size; @@ -3490,23 +3498,22 @@ static void test_MFCalculateImageSize(void)
for (i = 0; i < ARRAY_SIZE(image_size_tests); ++i) { + const struct image_size_test *ptr = &image_size_tests[i]; + /* Those are supported since Win10. */ - BOOL is_broken = IsEqualGUID(image_size_tests[i].subtype, &MFVideoFormat_A16B16G16R16F) || - IsEqualGUID(image_size_tests[i].subtype, &MFVideoFormat_A2R10G10B10); + BOOL is_broken = IsEqualGUID(ptr->subtype, &MFVideoFormat_A16B16G16R16F) || + IsEqualGUID(ptr->subtype, &MFVideoFormat_A2R10G10B10);
- hr = MFCalculateImageSize(image_size_tests[i].subtype, image_size_tests[i].width, - image_size_tests[i].height, &size); + hr = MFCalculateImageSize(ptr->subtype, ptr->width, ptr->height, &size); ok(hr == S_OK || (is_broken && hr == E_INVALIDARG), "%u: failed to calculate image size, hr %#x.\n", i, hr); - ok(size == image_size_tests[i].size, "%u: unexpected image size %u, expected %u.\n", i, size, - image_size_tests[i].size); + ok(size == ptr->size, "%u: unexpected image size %u, expected %u. Size %u x %u, format %s.\n", i, size, ptr->size, + ptr->width, ptr->height, wine_dbgstr_an((char *)&ptr->subtype->Data1, 4));
if (pMFGetPlaneSize) { - unsigned int plane_size = image_size_tests[i].plane_size ? image_size_tests[i].plane_size : - image_size_tests[i].size; + unsigned int plane_size = ptr->plane_size ? ptr->plane_size : ptr->size;
- hr = pMFGetPlaneSize(image_size_tests[i].subtype->Data1, image_size_tests[i].width, image_size_tests[i].height, - &size); + hr = pMFGetPlaneSize(ptr->subtype->Data1, ptr->width, ptr->height, &size); ok(hr == S_OK, "%u: failed to get plane size, hr %#x.\n", i, hr); ok(size == plane_size, "%u: unexpected plane size %u, expected %u.\n", i, size, plane_size); } @@ -4635,16 +4642,51 @@ static void test_MFCreate2DMediaBuffer(void) unsigned int height; unsigned int fourcc; unsigned int contiguous_length; + int pitch; + unsigned int plane_multiplier; } _2d_buffer_tests[] = { - { 2, 2, MAKEFOURCC('N','V','1','2'), 6 }, - { 4, 2, MAKEFOURCC('N','V','1','2'), 12 }, - { 2, 4, MAKEFOURCC('N','V','1','2'), 12 }, - { 1, 3, MAKEFOURCC('N','V','1','2'), 4 }, - - { 2, 4, D3DFMT_A8R8G8B8, 32 }, - { 1, 4, D3DFMT_A8R8G8B8, 16 }, - { 4, 1, D3DFMT_A8R8G8B8, 16 }, + { 2, 2, MAKEFOURCC('N','V','1','2'), 6, 64 }, + { 4, 2, MAKEFOURCC('N','V','1','2'), 12, 64 }, + { 2, 4, MAKEFOURCC('N','V','1','2'), 12, 64 }, + { 1, 3, MAKEFOURCC('N','V','1','2'), 4, 64 }, + + { 2, 2, MAKEFOURCC('I','M','C','2'), 6, 128 }, + { 4, 2, MAKEFOURCC('I','M','C','2'), 12, 128 }, + { 2, 4, MAKEFOURCC('I','M','C','2'), 12, 128 }, + { 2, 2, MAKEFOURCC('I','M','C','4'), 6, 128 }, + { 4, 2, MAKEFOURCC('I','M','C','4'), 12, 128 }, + { 2, 4, MAKEFOURCC('I','M','C','4'), 12, 128 }, + + { 4, 2, MAKEFOURCC('I','M','C','1'), 32, 128, 2 }, + { 4, 4, MAKEFOURCC('I','M','C','1'), 64, 128, 2 }, + { 4, 16, MAKEFOURCC('I','M','C','1'), 256, 128, 2 }, + { 4, 20, MAKEFOURCC('I','M','C','1'), 320, 128, 2 }, + + { 4, 2, MAKEFOURCC('I','M','C','3'), 32, 128, 2 }, + { 4, 4, MAKEFOURCC('I','M','C','3'), 64, 128, 2 }, + { 4, 16, MAKEFOURCC('I','M','C','3'), 256, 128, 2 }, + { 4, 20, MAKEFOURCC('I','M','C','3'), 320, 128, 2 }, + + { 4, 2, MAKEFOURCC('Y','V','1','2'), 12, 128 }, + { 4, 4, MAKEFOURCC('Y','V','1','2'), 24, 128 }, + { 4, 16, MAKEFOURCC('Y','V','1','2'), 96, 128 }, + + { 4, 2, MAKEFOURCC('A','Y','U','V'), 32, 64 }, + { 4, 4, MAKEFOURCC('A','Y','U','V'), 64, 64 }, + { 4, 16, MAKEFOURCC('A','Y','U','V'), 256, 64 }, + + { 4, 2, MAKEFOURCC('Y','U','Y','2'), 16, 64 }, + { 4, 4, MAKEFOURCC('Y','U','Y','2'), 32, 64 }, + { 4, 16, MAKEFOURCC('Y','U','Y','2'), 128, 64 }, + + { 4, 2, MAKEFOURCC('U','Y','V','Y'), 16, 64 }, + { 4, 4, MAKEFOURCC('U','Y','V','Y'), 32, 64 }, + { 4, 16, MAKEFOURCC('U','Y','V','Y'), 128, 64 }, + + { 2, 4, D3DFMT_A8R8G8B8, 32, 64 }, + { 1, 4, D3DFMT_A8R8G8B8, 16, 64 }, + { 4, 1, D3DFMT_A8R8G8B8, 16, 64 }, }; unsigned int max_length, length, length2; BYTE *buffer_start, *data, *data2; @@ -4838,9 +4880,28 @@ static void test_MFCreate2DMediaBuffer(void) ok(length == ptr->contiguous_length, "%d: unexpected contiguous length %u for %u x %u, format %s.\n", i, length, ptr->width, ptr->height, wine_dbgstr_an((char *)&ptr->fourcc, 4));
+ hr = IMFMediaBuffer_Lock(buffer, &data, &length2, NULL); + ok(hr == S_OK, "Failed to lock buffer, hr %#x.\n", hr); + ok(length == ptr->contiguous_length, "%d: unexpected linear buffer length %u for %u x %u, format %s.\n", + i, length2, ptr->width, ptr->height, wine_dbgstr_an((char *)&ptr->fourcc, 4)); + + hr = IMFMediaBuffer_Unlock(buffer); + ok(hr == S_OK, "Failed to unlock buffer, hr %#x.\n", hr); + hr = pMFGetPlaneSize(ptr->fourcc, ptr->width, ptr->height, &length2); ok(hr == S_OK, "Failed to get plane size, hr %#x.\n", hr); - ok(length2 == length, "%d: contiguous length %u does not match plane size %u.\n", i, length, length2); + if (ptr->plane_multiplier) + length2 *= ptr->plane_multiplier; + ok(length2 == length, "%d: contiguous length %u does not match plane size %u, %u x %u, format %s.\n", i, length, + length2, ptr->width, ptr->height, wine_dbgstr_an((char *)&ptr->fourcc, 4)); + + hr = IMF2DBuffer_Lock2D(_2dbuffer, &data, &pitch); + ok(hr == S_OK, "Failed to lock buffer, hr %#x.\n", hr); + hr = IMF2DBuffer_Unlock2D(_2dbuffer); + ok(hr == S_OK, "Failed to unlock buffer, hr %#x.\n", hr); + + ok(pitch == ptr->pitch, "%d: unexpected pitch %d, expected %d, %u x %u, format %s.\n", i, pitch, ptr->pitch, + ptr->width, ptr->height, wine_dbgstr_an((char *)&ptr->fourcc, 4));
ret = TRUE; hr = IMF2DBuffer_IsContiguousFormat(_2dbuffer, &ret);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/tests/mfplat.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 4cb5499f7c..8e9bf8102a 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -2066,7 +2066,7 @@ static HRESULT WINAPI testcallback_Invoke(IMFAsyncCallback *iface, IMFAsyncResul state = IMFAsyncResult_GetStateNoAddRef(result); if (state && SUCCEEDED(IUnknown_QueryInterface(state, &IID_IMFMediaEventQueue, (void **)&queue))) { - IMFMediaEvent *event; + IMFMediaEvent *event = NULL, *event2;
if (is_win8_plus) { @@ -2079,10 +2079,11 @@ static HRESULT WINAPI testcallback_Invoke(IMFAsyncCallback *iface, IMFAsyncResul hr = IMFMediaEventQueue_EndGetEvent(queue, result, &event); ok(hr == S_OK, "Failed to finalize GetEvent, hr %#x.\n", hr);
- hr = IMFMediaEventQueue_EndGetEvent(queue, result, &event); + hr = IMFMediaEventQueue_EndGetEvent(queue, result, &event2); ok(hr == E_FAIL, "Unexpected result, hr %#x.\n", hr);
- IMFMediaEvent_Release(event); + if (event) + IMFMediaEvent_Release(event); }
hr = IMFAsyncResult_GetObject(result, &obj); @@ -2719,7 +2720,7 @@ static void test_event_queue(void) hr = IMFMediaEventQueue_QueueEvent(queue, event); ok(hr == S_OK, "Failed to queue event, hr %#x.\n", hr);
- ret = WaitForSingleObject(callback.event, 100); + ret = WaitForSingleObject(callback.event, 500); ok(ret == WAIT_OBJECT_0, "Unexpected return value %#x.\n", ret);
CloseHandle(callback.event);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 2 +- dlls/mfplat/main.c | 2 +- dlls/mfplat/mediatype.c | 5 ++--- dlls/mfplat/mfplat_private.h | 37 ++++++++++++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 5 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index 64ec436a1e..71bae4c42f 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -642,7 +642,7 @@ HRESULT WINAPI MFCreateAlignedMemoryBuffer(DWORD max_length, DWORD alignment, IM
HRESULT WINAPI MFCreate2DMediaBuffer(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up, IMFMediaBuffer **buffer) { - TRACE("%u, %u, %#x, %d, %p.\n", width, height, fourcc, bottom_up, buffer); + TRACE("%u, %u, %s, %d, %p.\n", width, height, debugstr_fourcc(fourcc), bottom_up, buffer);
return create_2d_buffer(width, height, fourcc, bottom_up, buffer); } diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index a5c954161d..ffe9e36d15 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -1510,7 +1510,7 @@ HRESULT WINAPI MFShutdown(void) */ HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines) { - TRACE("(%p, %d, %p, %d, %u, %u)\n", dest, deststride, src, srcstride, width, lines); + TRACE("%p, %d, %p, %d, %u, %u.\n", dest, deststride, src, srcstride, width, lines);
while (lines--) { diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c index 8c4716e5e1..77753cc499 100644 --- a/dlls/mfplat/mediatype.c +++ b/dlls/mfplat/mediatype.c @@ -19,7 +19,6 @@ #define COBJMACROS
#include "mfplat_private.h" -#include "d3d9types.h"
#include "initguid.h" #include "ks.h" @@ -1837,7 +1836,7 @@ HRESULT WINAPI MFGetStrideForBitmapInfoHeader(DWORD fourcc, DWORD width, LONG *s struct uncompressed_video_format *format; GUID subtype;
- TRACE("%#x, %u, %p.\n", fourcc, width, stride); + TRACE("%s, %u, %p.\n", debugstr_fourcc(fourcc), width, stride);
memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype)); subtype.Data1 = fourcc; @@ -1902,7 +1901,7 @@ HRESULT WINAPI MFGetPlaneSize(DWORD fourcc, DWORD width, DWORD height, DWORD *si unsigned int stride; GUID subtype;
- TRACE("%#x, %u, %u, %p.\n", fourcc, width, height, size); + TRACE("%s, %u, %u, %p.\n", debugstr_fourcc(fourcc), width, height, size);
memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype)); subtype.Data1 = fourcc; diff --git a/dlls/mfplat/mfplat_private.h b/dlls/mfplat/mfplat_private.h index 0c374f116b..15d81a65b9 100644 --- a/dlls/mfplat/mfplat_private.h +++ b/dlls/mfplat/mfplat_private.h @@ -23,6 +23,7 @@ #include "mfapi.h" #include "mfidl.h" #include "mferror.h" +#include "d3d9types.h"
#include "wine/heap.h" #include "wine/debug.h" @@ -145,3 +146,39 @@ static inline const char *debugstr_propvar(const PROPVARIANT *v) return wine_dbg_sprintf("%p {vt %#x}", v, v->vt); } } + +static inline const char *debugstr_fourcc(DWORD format) +{ + static const struct format_name + { + unsigned int format; + const char *name; + } formats[] = + { + { D3DFMT_R8G8B8, "R8G8B8" }, + { D3DFMT_A8R8G8B8, "A8R8G8B8" }, + { D3DFMT_X8R8G8B8, "X8R8G8B8" }, + { D3DFMT_R5G6B5, "R5G6B5" }, + { D3DFMT_X1R5G5B5, "X1R5G6B5" }, + { D3DFMT_A2B10G10R10, "A2B10G10R10" }, + { D3DFMT_P8, "P8" }, + { D3DFMT_L8, "L8" }, + { D3DFMT_D16, "D16" }, + { D3DFMT_L16, "L16" }, + { D3DFMT_A16B16G16R16F, "A16B16G16R16F" }, + }; + int i; + + if ((format & 0xff) == format) + { + for (i = 0; i < ARRAY_SIZE(formats); ++i) + { + if (formats[i].format == format) + return wine_dbg_sprintf("%s", wine_dbgstr_an(formats[i].name, -1)); + } + + return wine_dbg_sprintf("%#x", format); + } + + return wine_dbgstr_an((char *)&format, 4); +}
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/session.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 69d1fdf569..2204149dca 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -2613,6 +2613,14 @@ static HRESULT WINAPI session_events_callback_Invoke(IMFAsyncCallback *iface, IM session_deliver_sample(session, (IMFMediaStream *)event_source, &value); LeaveCriticalSection(&session->cs);
+ break; + case MEAudioSessionGroupingParamChanged: + case MEAudioSessionIconChanged: + case MEAudioSessionNameChanged: + case MEAudioSessionVolumeChanged: + + IMFMediaEventQueue_QueueEvent(session->event_queue, event); + break; case MEAudioSessionDeviceRemoved: case MEAudioSessionDisconnected:
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/session.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 2204149dca..db1e5e4fe5 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -164,7 +164,7 @@ struct topo_node enum presentation_flags { SESSION_FLAG_SOURCES_SUBSCRIBED = 0x1, - SESSION_FLAG_SINKS_SUBSCRIBED = 0x2, + SESSION_FLAG_PRESENTATION_CLOCK_SET = 0x2, SESSION_FLAG_FINALIZE_SINKS = 0x4, };
@@ -1911,9 +1911,21 @@ static enum object_state session_get_object_state_for_event(MediaEventType event } }
+static void session_set_consumed_clock(IUnknown *object, IMFPresentationClock *clock) +{ + IMFClockConsumer *consumer; + + if (SUCCEEDED(IUnknown_QueryInterface(object, &IID_IMFClockConsumer, (void **)&consumer))) + { + IMFClockConsumer_SetPresentationClock(consumer, clock); + IMFClockConsumer_Release(consumer); + } +} + static HRESULT session_start_clock(struct media_session *session) { IMFPresentationTimeSource *time_source = NULL; + struct media_source *source; LONGLONG start_offset = 0; struct media_sink *sink; struct topo_node *node; @@ -1925,8 +1937,9 @@ static HRESULT session_start_clock(struct media_session *session) IMFTransform_ProcessMessage(node->object.transform, MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0); }
- if (!(session->presentation.flags & SESSION_FLAG_SINKS_SUBSCRIBED)) + if (!(session->presentation.flags & SESSION_FLAG_PRESENTATION_CLOCK_SET)) { + /* Attempt to get time source from the sinks. */ LIST_FOR_EACH_ENTRY(sink, &session->presentation.sinks, struct media_sink, entry) { if (SUCCEEDED(IMFMediaSink_QueryInterface(sink->sink, &IID_IMFPresentationTimeSource, @@ -1957,6 +1970,12 @@ static HRESULT session_start_clock(struct media_session *session) } }
+ /* Set clock for all topology nodes. */ + LIST_FOR_EACH_ENTRY(source, &session->presentation.sources, struct media_source, entry) + { + session_set_consumed_clock((IUnknown *)source->source, session->clock); + } + LIST_FOR_EACH_ENTRY(sink, &session->presentation.sinks, struct media_sink, entry) { if (sink->event_generator && FAILED(hr = IMFMediaEventGenerator_BeginGetEvent(sink->event_generator, @@ -1969,7 +1988,15 @@ static HRESULT session_start_clock(struct media_session *session) WARN("Failed to set presentation clock for the sink, hr %#x.\n", hr); }
- session->presentation.flags |= SESSION_FLAG_SINKS_SUBSCRIBED; + LIST_FOR_EACH_ENTRY(node, &session->presentation.nodes, struct topo_node, entry) + { + if (node->type != MF_TOPOLOGY_TRANSFORM_NODE) + continue; + + session_set_consumed_clock(node->object.object, session->clock); + } + + session->presentation.flags |= SESSION_FLAG_PRESENTATION_CLOCK_SET; }
if (IsEqualGUID(&session->presentation.time_format, &GUID_NULL))