-- v2: mfreadwrite/tests: Test source reader transforms with MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING. mfreadwrite/tests: Test source reader transforms with MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING. mfreadwrite/tests: Test source reader exposed transforms and types. mfreadwrite/tests: Initialize test source stream types from descriptors.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/tests/mfplat.c | 179 ++++++++++++++++++++++---------- 1 file changed, 126 insertions(+), 53 deletions(-)
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index c3544a31ac6..a93b49a64a6 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -38,11 +38,47 @@ DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); #include "mfidl.h" #include "mferror.h" #include "mfreadwrite.h" +#include "propvarutil.h" #include "d3d9.h" #include "dxva2api.h"
#include "wine/test.h"
+struct attribute_desc +{ + const GUID *key; + const char *name; + PROPVARIANT value; + BOOL ratio; + BOOL required; + BOOL todo; + BOOL todo_value; +}; + +#define ATTR_GUID(k, g, ...) {.key = &k, .name = #k, {.vt = VT_CLSID, .puuid = (GUID *)&g}, __VA_ARGS__ } +#define ATTR_UINT32(k, v, ...) {.key = &k, .name = #k, {.vt = VT_UI4, .ulVal = v}, __VA_ARGS__ } +#define ATTR_BLOB(k, p, n, ...) {.key = &k, .name = #k, {.vt = VT_VECTOR | VT_UI1, .caub = {.pElems = (void *)p, .cElems = n}}, __VA_ARGS__ } +#define ATTR_RATIO(k, n, d, ...) {.key = &k, .name = #k, {.vt = VT_UI8, .uhVal = {.HighPart = n, .LowPart = d}}, .ratio = TRUE, __VA_ARGS__ } +#define ATTR_UINT64(k, v, ...) {.key = &k, .name = #k, {.vt = VT_UI8, .uhVal = {.QuadPart = v}}, __VA_ARGS__ } + +#define init_media_type(a, b, c) init_attributes_(__FILE__, __LINE__, (IMFAttributes *)a, b, c) +#define init_attributes(a, b, c) init_attributes_(__FILE__, __LINE__, a, b, c) +static void init_attributes_(const char *file, int line, IMFAttributes *attributes, + const struct attribute_desc *desc, ULONG limit) +{ + HRESULT hr; + ULONG i; + + hr = IMFAttributes_DeleteAllItems(attributes); + ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + for (i = 0; i < limit && desc[i].key; ++i) + { + hr = IMFAttributes_SetItem(attributes, desc[i].key, &desc[i].value); + ok_(file, line)(hr == S_OK, "SetItem %s returned %#lx\n", debugstr_a(desc[i].name), hr); + } +} + static ULONG get_refcount(void *iface) { IUnknown *unknown = iface; @@ -357,48 +393,10 @@ static HRESULT WINAPI test_source_GetCharacteristics(IMFMediaSource *iface, DWOR static HRESULT WINAPI test_source_CreatePresentationDescriptor(IMFMediaSource *iface, IMFPresentationDescriptor **pd) { struct test_source *source = impl_from_IMFMediaSource(iface); - IMFStreamDescriptor *sds[ARRAY_SIZE(source->streams)]; - IMFMediaType *media_type; HRESULT hr = S_OK; - int i;
- EnterCriticalSection(&source->cs); - - if (source->pd) - { - *pd = source->pd; - IMFPresentationDescriptor_AddRef(*pd); - } - else - { - for (i = 0; i < source->stream_count; ++i) - { - hr = MFCreateMediaType(&media_type); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - - hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, 32); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - - hr = MFCreateStreamDescriptor(i, 1, &media_type, &sds[i]); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - - IMFMediaType_Release(media_type); - } - - hr = MFCreatePresentationDescriptor(source->stream_count, sds, &source->pd); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - for (i = 0; i < source->stream_count; ++i) - IMFStreamDescriptor_Release(sds[i]); - - *pd = source->pd; - IMFPresentationDescriptor_AddRef(*pd); - } - - LeaveCriticalSection(&source->cs); + *pd = source->pd; + IMFPresentationDescriptor_AddRef(*pd);
return hr; } @@ -522,17 +520,22 @@ static struct test_media_stream *create_test_stream(DWORD stream_index, IMFMedia return stream; }
-static IMFMediaSource *create_test_source(int stream_count) +static IMFMediaSource *create_test_source(IMFStreamDescriptor **streams, UINT stream_count) { struct test_source *source; + HRESULT hr; int i;
source = calloc(1, sizeof(*source)); source->IMFMediaSource_iface.lpVtbl = &test_source_vtbl; source->refcount = 1; source->stream_count = stream_count; - MFCreateEventQueue(&source->event_queue); + hr = MFCreatePresentationDescriptor(stream_count, streams, &source->pd); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = MFCreateEventQueue(&source->event_queue); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); InitializeCriticalSection(&source->cs); + for (i = 0; i < source->stream_count; ++i) source->streams[i] = create_test_stream(i, &source->IMFMediaSource_iface);
@@ -1028,7 +1031,15 @@ static void test_source_reader(const char *filename, bool video) static void test_source_reader_from_media_source(void) { static const DWORD expected_sample_order[10] = {0, 0, 1, 1, 0, 0, 0, 0, 1, 0}; + static const struct attribute_desc audio_stream_type_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM), + ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32), + {0}, + };
+ IMFStreamDescriptor *audio_streams[3]; struct async_callback *callback; IMFSourceReader *reader; IMFMediaSource *source; @@ -1043,7 +1054,18 @@ static void test_source_reader_from_media_source(void) int i; PROPVARIANT pos;
- source = create_test_source(3); + for (i = 0; i < ARRAY_SIZE(audio_streams); i++) + { + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(media_type, audio_stream_type_desc, -1); + + hr = MFCreateStreamDescriptor(i, 1, &media_type, &audio_streams[i]); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + } + + source = create_test_source(audio_streams, 3); ok(!!source, "Failed to create test source.\n");
hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader); @@ -1122,7 +1144,7 @@ static void test_source_reader_from_media_source(void) IMFSourceReader_Release(reader); IMFMediaSource_Release(source);
- source = create_test_source(1); + source = create_test_source(audio_streams, 1); ok(!!source, "Failed to create test source.\n");
hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader); @@ -1159,7 +1181,7 @@ static void test_source_reader_from_media_source(void) IMFMediaSource_Release(source);
/* Request from stream 0. */ - source = create_test_source(3); + source = create_test_source(audio_streams, 3); ok(!!source, "Failed to create test source.\n");
hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader); @@ -1193,7 +1215,7 @@ static void test_source_reader_from_media_source(void) IMFMediaSource_Release(source);
/* Request a non-native bit depth. */ - source = create_test_source(1); + source = create_test_source(audio_streams, 1); ok(!!source, "Failed to create test source.\n");
hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader); @@ -1241,7 +1263,7 @@ static void test_source_reader_from_media_source(void) IMFMediaSource_Release(source);
/* Async mode. */ - source = create_test_source(3); + source = create_test_source(audio_streams, 3); ok(!!source, "Failed to create test source.\n");
callback = create_async_callback(); @@ -1286,7 +1308,7 @@ static void test_source_reader_from_media_source(void) IMFMediaSource_Release(source);
/* RequestSample failure. */ - source = create_test_source(3); + source = create_test_source(audio_streams, 3); ok(!!source, "Failed to create test source.\n");
fail_request_sample = TRUE; @@ -1329,7 +1351,7 @@ static void test_source_reader_from_media_source(void) fail_request_sample = FALSE;
/* MF_SOURCE_READER_ANY_STREAM with streams of different sample sizes */ - source = create_test_source(2); + source = create_test_source(audio_streams, 2); ok(!!source, "Failed to create test source.\n");
test_source = impl_from_IMFMediaSource(source); @@ -1359,19 +1381,32 @@ static void test_source_reader_from_media_source(void)
IMFSourceReader_Release(reader); IMFMediaSource_Release(source); + + for (i = 0; i < ARRAY_SIZE(audio_streams); i++) + IMFStreamDescriptor_Release(audio_streams[i]); }
static void test_reader_d3d9(void) { + static const struct attribute_desc audio_stream_type_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM), + ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32), + {0}, + }; + + IMFStreamDescriptor *audio_streams[3]; IDirect3DDeviceManager9 *d3d9_manager; IDirect3DDevice9 *d3d9_device; IMFAttributes *attributes; + IMFMediaType *media_type; IMFSourceReader *reader; IMFMediaSource *source; IDirect3D9 *d3d9; HWND window; HRESULT hr; - UINT token; + UINT i, token; ULONG refcount;
d3d9 = Direct3DCreate9(D3D_SDK_VERSION); @@ -1387,13 +1422,24 @@ static void test_reader_d3d9(void) goto done; }
+ for (i = 0; i < ARRAY_SIZE(audio_streams); i++) + { + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(media_type, audio_stream_type_desc, -1); + + hr = MFCreateStreamDescriptor(i, 1, &media_type, &audio_streams[i]); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + } + hr = DXVA2CreateDirect3DDeviceManager9(&token, &d3d9_manager); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IDirect3DDeviceManager9_ResetDevice(d3d9_manager, d3d9_device, token); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- source = create_test_source(3); + source = create_test_source(audio_streams, 3); ok(!!source, "Failed to create test source.\n");
hr = MFCreateAttributes(&attributes, 1); @@ -1409,11 +1455,13 @@ static void test_reader_d3d9(void)
IMFSourceReader_Release(reader);
+ for (i = 0; i < ARRAY_SIZE(audio_streams); i++) + IMFStreamDescriptor_Release(audio_streams[i]); + refcount = IDirect3DDeviceManager9_Release(d3d9_manager); ok(!refcount, "Unexpected refcount %lu.\n", refcount);
IDirect3DDevice9_Release(d3d9_device); - done: IDirect3D9_Release(d3d9); DestroyWindow(window); @@ -1511,12 +1559,34 @@ static void test_sink_writer_mp4(void)
static void test_interfaces(void) { + static const struct attribute_desc audio_stream_type_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM), + ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32), + {0}, + }; + + IMFStreamDescriptor *audio_streams[1]; + IMFMediaType *media_type; IMFSourceReader *reader; IMFMediaSource *source; IUnknown *unk; HRESULT hr; + UINT i; + + for (i = 0; i < ARRAY_SIZE(audio_streams); i++) + { + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(media_type, audio_stream_type_desc, -1);
- source = create_test_source(1); + hr = MFCreateStreamDescriptor(i, 1, &media_type, &audio_streams[i]); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + } + + source = create_test_source(audio_streams, 1); ok(!!source, "Failed to create test source.\n");
hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader); @@ -1529,6 +1599,9 @@ static void test_interfaces(void)
IMFSourceReader_Release(reader); IMFMediaSource_Release(source); + + for (i = 0; i < ARRAY_SIZE(audio_streams); i++) + IMFStreamDescriptor_Release(audio_streams[i]); }
START_TEST(mfplat)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/tests/Makefile.in | 2 +- dlls/mfreadwrite/tests/mfplat.c | 385 +++++++++++++++++++++++++++++ 2 files changed, 386 insertions(+), 1 deletion(-)
diff --git a/dlls/mfreadwrite/tests/Makefile.in b/dlls/mfreadwrite/tests/Makefile.in index 90bac9e0896..cada1bf22ff 100644 --- a/dlls/mfreadwrite/tests/Makefile.in +++ b/dlls/mfreadwrite/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = mfreadwrite.dll -IMPORTS = ole32 user32 d3d9 dxva2 mfplat mfreadwrite mfuuid +IMPORTS = ole32 user32 d3d9 dxva2 mfplat mfreadwrite mfuuid propsys
SOURCES = \ mfplat.c \ diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index a93b49a64a6..04c077dd027 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -61,6 +61,53 @@ struct attribute_desc #define ATTR_RATIO(k, n, d, ...) {.key = &k, .name = #k, {.vt = VT_UI8, .uhVal = {.HighPart = n, .LowPart = d}}, .ratio = TRUE, __VA_ARGS__ } #define ATTR_UINT64(k, v, ...) {.key = &k, .name = #k, {.vt = VT_UI8, .uhVal = {.QuadPart = v}}, __VA_ARGS__ }
+#define check_media_type(a, b, c) check_attributes_(__FILE__, __LINE__, (IMFAttributes *)a, b, c) +#define check_attributes(a, b, c) check_attributes_(__FILE__, __LINE__, a, b, c) +void check_attributes_(const char *file, int line, IMFAttributes *attributes, + const struct attribute_desc *desc, ULONG limit) +{ + char buffer[1024], *buf = buffer; + PROPVARIANT value; + int i, j, ret; + HRESULT hr; + + for (i = 0; i < limit && desc[i].key; ++i) + { + hr = IMFAttributes_GetItem(attributes, desc[i].key, &value); + todo_wine_if(desc[i].todo) + ok_(file, line)(hr == S_OK, "%s missing, hr %#lx\n", debugstr_a(desc[i].name), hr); + if (hr != S_OK) continue; + + switch (value.vt) + { + default: sprintf(buffer, "??"); break; + case VT_CLSID: sprintf(buffer, "%s", debugstr_guid(value.puuid)); break; + case VT_UI4: sprintf(buffer, "%lu", value.ulVal); break; + case VT_UI8: + if (desc[i].ratio) + sprintf(buffer, "%lu:%lu", value.uhVal.HighPart, value.uhVal.LowPart); + else + sprintf(buffer, "%I64u", value.uhVal.QuadPart); + break; + case VT_VECTOR | VT_UI1: + buf += sprintf(buf, "size %lu, data {", value.caub.cElems); + for (j = 0; j < 128 && j < value.caub.cElems; ++j) + buf += sprintf(buf, "0x%02x,", value.caub.pElems[j]); + if (value.caub.cElems > 128) + buf += sprintf(buf, "...}"); + else + buf += sprintf(buf - (j ? 1 : 0), "}"); + break; + } + + ret = PropVariantCompareEx(&value, &desc[i].value, 0, 0); + todo_wine_if(desc[i].todo_value) + ok_(file, line)(ret == 0, "%s mismatch, type %u, value %s\n", + debugstr_a(desc[i].name), value.vt, buffer); + PropVariantClear(&value); + } +} + #define init_media_type(a, b, c) init_attributes_(__FILE__, __LINE__, (IMFAttributes *)a, b, c) #define init_attributes(a, b, c) init_attributes_(__FILE__, __LINE__, a, b, c) static void init_attributes_(const char *file, int line, IMFAttributes *attributes, @@ -1604,6 +1651,343 @@ static void test_interfaces(void) IMFStreamDescriptor_Release(audio_streams[i]); }
+static void test_source_reader_transforms(void) +{ + static const struct attribute_desc h264_stream_type_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264), + ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), + {0}, + }; + static const struct attribute_desc nv12_stream_type_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), + ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), + {0}, + }; + static const struct attribute_desc nv12_expect_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), + ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), + ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001), + ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1), + ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), + ATTR_UINT32(MF_MT_AVG_BIT_ERROR_RATE, 0, .todo = TRUE), + ATTR_UINT32(MF_MT_COMPRESSED, 0, .todo = TRUE), + ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 96), + ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), + ATTR_UINT32(MF_MT_INTERLACE_MODE, 7), + ATTR_UINT32(MF_MT_SAMPLE_SIZE, 13824), + ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), + {0}, + }; + static const struct attribute_desc yuy2_stream_type_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), + ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), + {0}, + }; + static const struct attribute_desc yuy2_expect_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), + ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), + ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001), + ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1), + ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), + ATTR_UINT32(MF_MT_AVG_BIT_ERROR_RATE, 0, .todo = TRUE), + ATTR_UINT32(MF_MT_COMPRESSED, 0, .todo = TRUE), + ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 192), + ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), + ATTR_UINT32(MF_MT_INTERLACE_MODE, 7), + ATTR_UINT32(MF_MT_SAMPLE_SIZE, 18432), + ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), + {0}, + }; + static const struct attribute_desc rgb32_stream_type_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), + ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), + {0}, + }; + IMFStreamDescriptor *video_stream; + IMFSourceReaderEx *reader_ex; + IMFMediaType *media_type; + IMFSourceReader *reader; + IMFTransform *transform; + IMFMediaSource *source; + GUID category; + HRESULT hr; + + /* test source reader with a RGB32 source */ + + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(media_type, rgb32_stream_type_desc, -1); + hr = MFCreateStreamDescriptor(0, 1, &media_type, &video_stream); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + + source = create_test_source(&video_stream, 1); + ok(!!source, "Failed to create test source.\n"); + + hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFSourceReader_SetStreamSelection(reader, 0, TRUE); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + /* skip tests on Win7 which misses IMFSourceReaderEx and has uninteresting media types differences */ + hr = IMFSourceReader_QueryInterface(reader, &IID_IMFSourceReaderEx, (void **)&reader_ex); + ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Win7 */, "Unexpected hr %#lx.\n", hr); + if (broken(hr == E_NOINTERFACE)) + { + win_skip("missing IMFSourceReaderEx interface, skipping tests on Win7\n"); + goto skip_tests; + } + IMFSourceReaderEx_Release(reader_ex); + + hr = IMFSourceReader_GetNativeMediaType(reader, 0, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, rgb32_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, rgb32_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + /* only one stream type and only one stream */ + hr = IMFSourceReader_GetNativeMediaType(reader, 0, 1, &media_type); + ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr); + hr = IMFSourceReader_GetNativeMediaType(reader, 1, 0, &media_type); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr); + hr = IMFSourceReader_GetCurrentMediaType(reader, 1, &media_type); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr); + + /* cannot request encoding to compressed media type */ + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(media_type, h264_stream_type_desc, -1); + hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); + ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + + /* SetCurrentMediaType needs major type and subtype */ + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + init_media_type(media_type, nv12_stream_type_desc, 1); + hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); + todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + + /* RGB32 -> NV12 conversion */ + init_media_type(media_type, nv12_stream_type_desc, -1); + hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); + ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, rgb32_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetServiceForStream(reader, 0, &GUID_NULL, &IID_IMFTransform, (void **)&transform); + ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr); + + IMFSourceReader_Release(reader); + IMFMediaSource_Release(source); + IMFStreamDescriptor_Release(video_stream); + + + /* test source reader with a NV12 source */ + + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(media_type, nv12_stream_type_desc, -1); + hr = MFCreateStreamDescriptor(0, 1, &media_type, &video_stream); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + + source = create_test_source(&video_stream, 1); + ok(!!source, "Failed to create test source.\n"); + + hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFSourceReader_SetStreamSelection(reader, 0, TRUE); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFSourceReader_GetNativeMediaType(reader, 0, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, nv12_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, nv12_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + /* NV12 -> RGB32 conversion */ + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(media_type, rgb32_stream_type_desc, -1); + hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); + ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetServiceForStream(reader, 0, &GUID_NULL, &IID_IMFTransform, (void **)&transform); + ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr); + + /* NV12 -> YUY2 conversion */ + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(media_type, yuy2_stream_type_desc, -1); + hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); + ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, nv12_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetServiceForStream(reader, 0, &GUID_NULL, &IID_IMFTransform, (void **)&transform); + ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr); + + IMFSourceReader_Release(reader); + IMFMediaSource_Release(source); + IMFStreamDescriptor_Release(video_stream); + + + /* test source reader with a H264 source */ + + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(media_type, h264_stream_type_desc, -1); + hr = MFCreateStreamDescriptor(0, 1, &media_type, &video_stream); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + + source = create_test_source(&video_stream, 1); + ok(!!source, "Failed to create test source.\n"); + + hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFSourceReader_SetStreamSelection(reader, 0, TRUE); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFSourceReader_GetNativeMediaType(reader, 0, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, h264_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, h264_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + /* when H264 output is used, there's no decoder transform */ + hr = IMFSourceReader_GetServiceForStream(reader, 0, &GUID_NULL, &IID_IMFTransform, (void **)&transform); + ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr); + + /* H264 -> RGB32 conversion */ + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(media_type, rgb32_stream_type_desc, -1); + hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); + todo_wine ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + + /* H264 -> NV12 conversion */ + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(media_type, nv12_stream_type_desc, 2); /* doesn't need the frame size */ + hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, nv12_expect_desc, -1); + IMFMediaType_Release(media_type); + + /* the H264 decoder transform can now be accessed */ + hr = IMFSourceReader_GetServiceForStream(reader, 0, &GUID_NULL, &IID_IMFTransform, (void **)&transform); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, h264_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, nv12_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + IMFTransform_Release(transform); + + /* YUY2 output works too */ + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(media_type, yuy2_stream_type_desc, 2); /* doesn't need the frame size */ + hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, yuy2_expect_desc, -1); + IMFMediaType_Release(media_type); + + /* decoder transform is also available through the IMFSourceReaderEx interface */ + hr = IMFSourceReader_QueryInterface(reader, &IID_IMFSourceReaderEx, (void **)&reader_ex); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 0, &category, &transform); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, h264_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, yuy2_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + /* changing the transform media type doesn't change the reader output type */ + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(media_type, nv12_stream_type_desc, -1); + hr = IMFTransform_SetOutputType(transform, 0, media_type, 0); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, yuy2_expect_desc, -1); + IMFMediaType_Release(media_type); + + IMFTransform_Release(transform); + } + + hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 1, &category, &transform); + todo_wine ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#lx.\n", hr); + IMFSourceReaderEx_Release(reader_ex); + +skip_tests: + IMFSourceReader_Release(reader); + IMFMediaSource_Release(source); + IMFStreamDescriptor_Release(video_stream); +} + START_TEST(mfplat) { HRESULT hr; @@ -1618,6 +2002,7 @@ START_TEST(mfplat) test_source_reader("test.wav", false); test_source_reader("test.mp4", true); test_source_reader_from_media_source(); + test_source_reader_transforms(); test_reader_d3d9(); test_sink_writer_create(); test_sink_writer_mp4();
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/tests/mfplat.c | 202 +++++++++++++++++++++++++++----- 1 file changed, 173 insertions(+), 29 deletions(-)
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index aa333b67065..08e19589ad1 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -1651,7 +1651,7 @@ static void test_interfaces(void) IMFStreamDescriptor_Release(audio_streams[i]); }
-static void test_source_reader_transforms(BOOL enable_processing) +static void test_source_reader_transforms(BOOL enable_processing, BOOL enable_advanced) { static const struct attribute_desc h264_stream_type_desc[] = { @@ -1684,6 +1684,16 @@ static void test_source_reader_transforms(BOOL enable_processing) ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), {0}, }; + static const struct attribute_desc nv12_expect_advanced_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .todo_value = TRUE), + ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), + ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1, .todo = TRUE), + ATTR_UINT32(MF_MT_COMPRESSED, 0, .todo = TRUE), + ATTR_UINT32(MF_MT_INTERLACE_MODE, 2, .todo = TRUE), + {0}, + }; static const struct attribute_desc yuy2_stream_type_desc[] = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), @@ -1708,6 +1718,16 @@ static void test_source_reader_transforms(BOOL enable_processing) ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), {0}, }; + static const struct attribute_desc yuy2_expect_advanced_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2, .todo_value = TRUE), + ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), + ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1, .todo = TRUE), + ATTR_UINT32(MF_MT_COMPRESSED, 0, .todo = TRUE), + ATTR_UINT32(MF_MT_INTERLACE_MODE, 2, .todo = TRUE), + {0}, + }; static const struct attribute_desc rgb32_stream_type_desc[] = { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), @@ -1726,6 +1746,15 @@ static void test_source_reader_transforms(BOOL enable_processing) ATTR_UINT32(MF_MT_SAMPLE_SIZE, 36864, .todo = TRUE), {0}, }; + static const struct attribute_desc rgb32_expect_advanced_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .todo_value = TRUE), + ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), + ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1, .todo = TRUE), + ATTR_UINT32(MF_MT_COMPRESSED, 0, .todo = TRUE), + ATTR_UINT32(MF_MT_INTERLACE_MODE, 2, .todo = TRUE), + }; IMFStreamDescriptor *video_stream; IMFSourceReaderEx *reader_ex; IMFAttributes *attributes; @@ -1736,12 +1765,14 @@ static void test_source_reader_transforms(BOOL enable_processing) GUID category; HRESULT hr;
- winetest_push_context("vp %u", enable_processing); + winetest_push_context("vp %u adv %u", enable_processing, enable_advanced);
hr = MFCreateAttributes(&attributes, 1); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFAttributes_SetUINT32(attributes, &MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, enable_processing); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFAttributes_SetUINT32(attributes, &MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, enable_advanced); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
/* test source reader with a RGB32 source */
@@ -1805,19 +1836,43 @@ static void test_source_reader_transforms(BOOL enable_processing) hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
- /* RGB32 -> NV12 conversion */ - init_media_type(media_type, nv12_stream_type_desc, -1); + /* RGB32 -> NV12 conversion with MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING */ + init_media_type(media_type, nv12_stream_type_desc, 2); /* doesn't need the frame size */ hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); - ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#lx.\n", hr); + if (enable_advanced) + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + else + ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#lx.\n", hr); IMFMediaType_Release(media_type);
hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - check_media_type(media_type, rgb32_stream_type_desc, -1); + if (enable_advanced) + check_media_type(media_type, nv12_expect_advanced_desc, -1); + else + check_media_type(media_type, rgb32_stream_type_desc, -1); IMFMediaType_Release(media_type);
+ /* video processor is accessible with MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING */ hr = IMFSourceReader_GetServiceForStream(reader, 0, &GUID_NULL, &IID_IMFTransform, (void **)&transform); - ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr); + if (!enable_advanced) + ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr); + else + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, rgb32_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, nv12_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + IMFTransform_Release(transform); + }
IMFSourceReader_Release(reader); IMFMediaSource_Release(source); @@ -1851,12 +1906,12 @@ static void test_source_reader_transforms(BOOL enable_processing) check_media_type(media_type, nv12_stream_type_desc, -1); IMFMediaType_Release(media_type);
- /* NV12 -> RGB32 conversion with MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING */ + /* NV12 -> RGB32 conversion with MF_SOURCE_READER_ENABLE_(ADVANCED_)VIDEO_PROCESSING */ hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); init_media_type(media_type, rgb32_stream_type_desc, 2); /* doesn't need the frame size */ hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); - if (enable_processing) + if (enable_processing || enable_advanced) todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); else ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#lx.\n", hr); @@ -1864,40 +1919,99 @@ static void test_source_reader_transforms(BOOL enable_processing)
hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (enable_processing) + if (enable_advanced) + check_media_type(media_type, rgb32_expect_advanced_desc, -1); + else if (enable_processing) check_media_type(media_type, rgb32_expect_desc, -1); else check_media_type(media_type, nv12_stream_type_desc, -1); IMFMediaType_Release(media_type);
+ /* convert transform is only exposed with MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING */ hr = IMFSourceReader_GetServiceForStream(reader, 0, &GUID_NULL, &IID_IMFTransform, (void **)&transform); - ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr); + if (!enable_advanced) + ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr); + else + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, nv12_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, rgb32_stream_type_desc, -1); + IMFMediaType_Release(media_type);
- /* NV12 -> YUY2 conversion */ + IMFTransform_Release(transform); + } + + /* NV12 -> YUY2 conversion with MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING */ hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - init_media_type(media_type, yuy2_stream_type_desc, -1); + init_media_type(media_type, yuy2_stream_type_desc, 2); /* doesn't need the frame size */ hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); - ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#lx.\n", hr); + if (enable_advanced) + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + else + ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#lx.\n", hr); IMFMediaType_Release(media_type);
hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (enable_processing) + if (enable_advanced) + check_media_type(media_type, yuy2_expect_advanced_desc, -1); + else if (enable_processing) check_media_type(media_type, rgb32_expect_desc, -1); else check_media_type(media_type, nv12_stream_type_desc, -1); IMFMediaType_Release(media_type);
- /* even though we are now converting to RGB32 the converter transform is not exposed */ + /* convert transform is only exposed with MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING */ hr = IMFSourceReader_GetServiceForStream(reader, 0, &GUID_NULL, &IID_IMFTransform, (void **)&transform); - ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr); + if (!enable_advanced) + ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr); + else + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, nv12_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, yuy2_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + IMFTransform_Release(transform); + }
- /* not even through the IMFSourceReaderEx interface */ hr = IMFSourceReader_QueryInterface(reader, &IID_IMFSourceReaderEx, (void **)&reader_ex); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 0, &category, &transform); - todo_wine ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#lx.\n", hr); + if (!enable_advanced) + todo_wine ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#lx.\n", hr); + else + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, nv12_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, yuy2_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + IMFTransform_Release(transform); + } + hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 1, &category, &transform); todo_wine ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#lx.\n", hr); IMFSourceReaderEx_Release(reader_ex); @@ -1938,12 +2052,12 @@ static void test_source_reader_transforms(BOOL enable_processing) hr = IMFSourceReader_GetServiceForStream(reader, 0, &GUID_NULL, &IID_IMFTransform, (void **)&transform); ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr);
- /* H264 -> RGB32 conversion with MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING */ + /* H264 -> RGB32 conversion with MF_SOURCE_READER_ENABLE_(ADVANCED_)VIDEO_PROCESSING */ hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); init_media_type(media_type, rgb32_stream_type_desc, 2); /* doesn't need the frame size */ hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); - if (enable_processing) + if (enable_processing || enable_advanced) todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); else todo_wine ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr); @@ -1951,15 +2065,17 @@ static void test_source_reader_transforms(BOOL enable_processing)
hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (enable_processing) + if (enable_advanced) + check_media_type(media_type, rgb32_expect_advanced_desc, -1); + else if (enable_processing) check_media_type(media_type, rgb32_expect_desc, -1); else check_media_type(media_type, h264_stream_type_desc, -1); IMFMediaType_Release(media_type);
- /* H264 decoder transform is exposed with MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING */ + /* the exposed transform is the H264 decoder or the converter with MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING */ hr = IMFSourceReader_GetServiceForStream(reader, 0, &GUID_NULL, &IID_IMFTransform, (void **)&transform); - if (!enable_processing) + if (!enable_processing && !enable_advanced) ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr); else todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -1967,13 +2083,19 @@ static void test_source_reader_transforms(BOOL enable_processing) { hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - check_media_type(media_type, h264_stream_type_desc, -1); + if (enable_advanced) + check_media_type(media_type, nv12_stream_type_desc, -1); + else + check_media_type(media_type, h264_stream_type_desc, -1); IMFMediaType_Release(media_type);
/* with NV12 output */ hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - check_media_type(media_type, nv12_stream_type_desc, -1); + if (enable_advanced) + check_media_type(media_type, rgb32_stream_type_desc, -1); + else + check_media_type(media_type, nv12_stream_type_desc, -1); IMFMediaType_Release(media_type);
IMFTransform_Release(transform); @@ -1983,7 +2105,7 @@ static void test_source_reader_transforms(BOOL enable_processing) hr = IMFSourceReader_QueryInterface(reader, &IID_IMFSourceReaderEx, (void **)&reader_ex); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 0, &category, &transform); - if (!enable_processing) + if (!enable_processing && !enable_advanced) todo_wine ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#lx.\n", hr); else todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -2002,7 +2124,28 @@ static void test_source_reader_transforms(BOOL enable_processing) IMFTransform_Release(transform); }
+ /* the video processor can be accessed at index 1 with MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING */ hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 1, &category, &transform); + if (!enable_advanced) + todo_wine ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#lx.\n", hr); + else + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, nv12_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, rgb32_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + IMFTransform_Release(transform); + } + + hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 2, &category, &transform); todo_wine ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#lx.\n", hr); IMFSourceReaderEx_Release(reader_ex);
@@ -2109,8 +2252,9 @@ START_TEST(mfplat) test_source_reader("test.wav", false); test_source_reader("test.mp4", true); test_source_reader_from_media_source(); - test_source_reader_transforms(FALSE); - test_source_reader_transforms(TRUE); + test_source_reader_transforms(FALSE, FALSE); + test_source_reader_transforms(TRUE, FALSE); + test_source_reader_transforms(FALSE, TRUE); test_reader_d3d9(); test_sink_writer_create(); test_sink_writer_mp4();
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/tests/mfplat.c | 134 ++++++++++++++++++++++++++++---- 1 file changed, 121 insertions(+), 13 deletions(-)
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 04c077dd027..aa333b67065 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -1651,7 +1651,7 @@ static void test_interfaces(void) IMFStreamDescriptor_Release(audio_streams[i]); }
-static void test_source_reader_transforms(void) +static void test_source_reader_transforms(BOOL enable_processing) { static const struct attribute_desc h264_stream_type_desc[] = { @@ -1715,8 +1715,20 @@ static void test_source_reader_transforms(void) ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), {0}, }; + static const struct attribute_desc rgb32_expect_desc[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .todo_value = TRUE), + ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96), + ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1, .todo = TRUE), + ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 384, .todo = TRUE), + ATTR_UINT32(MF_MT_INTERLACE_MODE, 2, .todo = TRUE), + ATTR_UINT32(MF_MT_SAMPLE_SIZE, 36864, .todo = TRUE), + {0}, + }; IMFStreamDescriptor *video_stream; IMFSourceReaderEx *reader_ex; + IMFAttributes *attributes; IMFMediaType *media_type; IMFSourceReader *reader; IMFTransform *transform; @@ -1724,6 +1736,13 @@ static void test_source_reader_transforms(void) GUID category; HRESULT hr;
+ winetest_push_context("vp %u", enable_processing); + + hr = MFCreateAttributes(&attributes, 1); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFAttributes_SetUINT32(attributes, &MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, enable_processing); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + /* test source reader with a RGB32 source */
hr = MFCreateMediaType(&media_type); @@ -1736,7 +1755,7 @@ static void test_source_reader_transforms(void) source = create_test_source(&video_stream, 1); ok(!!source, "Failed to create test source.\n");
- hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader); + hr = MFCreateSourceReaderFromMediaSource(source, attributes, &reader); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFSourceReader_SetStreamSelection(reader, 0, TRUE); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -1817,7 +1836,7 @@ static void test_source_reader_transforms(void) source = create_test_source(&video_stream, 1); ok(!!source, "Failed to create test source.\n");
- hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader); + hr = MFCreateSourceReaderFromMediaSource(source, attributes, &reader); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFSourceReader_SetStreamSelection(reader, 0, TRUE); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -1832,12 +1851,23 @@ static void test_source_reader_transforms(void) check_media_type(media_type, nv12_stream_type_desc, -1); IMFMediaType_Release(media_type);
- /* NV12 -> RGB32 conversion */ + /* NV12 -> RGB32 conversion with MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING */ hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - init_media_type(media_type, rgb32_stream_type_desc, -1); + init_media_type(media_type, rgb32_stream_type_desc, 2); /* doesn't need the frame size */ hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); - ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#lx.\n", hr); + if (enable_processing) + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + else + ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (enable_processing) + check_media_type(media_type, rgb32_expect_desc, -1); + else + check_media_type(media_type, nv12_stream_type_desc, -1); IMFMediaType_Release(media_type);
hr = IMFSourceReader_GetServiceForStream(reader, 0, &GUID_NULL, &IID_IMFTransform, (void **)&transform); @@ -1853,12 +1883,25 @@ static void test_source_reader_transforms(void)
hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - check_media_type(media_type, nv12_stream_type_desc, -1); + if (enable_processing) + check_media_type(media_type, rgb32_expect_desc, -1); + else + check_media_type(media_type, nv12_stream_type_desc, -1); IMFMediaType_Release(media_type);
+ /* even though we are now converting to RGB32 the converter transform is not exposed */ hr = IMFSourceReader_GetServiceForStream(reader, 0, &GUID_NULL, &IID_IMFTransform, (void **)&transform); ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr);
+ /* not even through the IMFSourceReaderEx interface */ + hr = IMFSourceReader_QueryInterface(reader, &IID_IMFSourceReaderEx, (void **)&reader_ex); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 0, &category, &transform); + todo_wine ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#lx.\n", hr); + hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 1, &category, &transform); + todo_wine ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#lx.\n", hr); + IMFSourceReaderEx_Release(reader_ex); + IMFSourceReader_Release(reader); IMFMediaSource_Release(source); IMFStreamDescriptor_Release(video_stream); @@ -1876,7 +1919,7 @@ static void test_source_reader_transforms(void) source = create_test_source(&video_stream, 1); ok(!!source, "Failed to create test source.\n");
- hr = MFCreateSourceReaderFromMediaSource(source, NULL, &reader); + hr = MFCreateSourceReaderFromMediaSource(source, attributes, &reader); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFSourceReader_SetStreamSelection(reader, 0, TRUE); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -1895,14 +1938,74 @@ static void test_source_reader_transforms(void) hr = IMFSourceReader_GetServiceForStream(reader, 0, &GUID_NULL, &IID_IMFTransform, (void **)&transform); ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr);
- /* H264 -> RGB32 conversion */ + /* H264 -> RGB32 conversion with MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING */ hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - init_media_type(media_type, rgb32_stream_type_desc, -1); + init_media_type(media_type, rgb32_stream_type_desc, 2); /* doesn't need the frame size */ hr = IMFSourceReader_SetCurrentMediaType(reader, 0, NULL, media_type); - todo_wine ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr); + if (enable_processing) + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + else + todo_wine ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(media_type); + + hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (enable_processing) + check_media_type(media_type, rgb32_expect_desc, -1); + else + check_media_type(media_type, h264_stream_type_desc, -1); IMFMediaType_Release(media_type);
+ /* H264 decoder transform is exposed with MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING */ + hr = IMFSourceReader_GetServiceForStream(reader, 0, &GUID_NULL, &IID_IMFTransform, (void **)&transform); + if (!enable_processing) + ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr); + else + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, h264_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + /* with NV12 output */ + hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, nv12_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + IMFTransform_Release(transform); + } + + /* H264 decoder transform is also available through the IMFSourceReaderEx interface */ + hr = IMFSourceReader_QueryInterface(reader, &IID_IMFSourceReaderEx, (void **)&reader_ex); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 0, &category, &transform); + if (!enable_processing) + todo_wine ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#lx.\n", hr); + else + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (hr == S_OK) + { + hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, h264_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_media_type(media_type, nv12_stream_type_desc, -1); + IMFMediaType_Release(media_type); + + IMFTransform_Release(transform); + } + + hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 1, &category, &transform); + todo_wine ok(hr == MF_E_INVALIDINDEX, "Unexpected hr %#lx.\n", hr); + IMFSourceReaderEx_Release(reader_ex); + /* H264 -> NV12 conversion */ hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -1945,7 +2048,7 @@ static void test_source_reader_transforms(void) check_media_type(media_type, yuy2_expect_desc, -1); IMFMediaType_Release(media_type);
- /* decoder transform is also available through the IMFSourceReaderEx interface */ + /* H264 decoder transform is also available through the IMFSourceReaderEx interface */ hr = IMFSourceReader_QueryInterface(reader, &IID_IMFSourceReaderEx, (void **)&reader_ex); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFSourceReaderEx_GetTransformForStream(reader_ex, 0, 0, &category, &transform); @@ -1986,6 +2089,10 @@ skip_tests: IMFSourceReader_Release(reader); IMFMediaSource_Release(source); IMFStreamDescriptor_Release(video_stream); + + IMFAttributes_Release(attributes); + + winetest_pop_context(); }
START_TEST(mfplat) @@ -2002,7 +2109,8 @@ START_TEST(mfplat) test_source_reader("test.wav", false); test_source_reader("test.mp4", true); test_source_reader_from_media_source(); - test_source_reader_transforms(); + test_source_reader_transforms(FALSE); + test_source_reader_transforms(TRUE); test_reader_d3d9(); test_sink_writer_create(); test_sink_writer_mp4();
Skipping the tests on Win7 instead to keep them simple.
Anything I should do here? This is just tests but then I have some code to better implement the source reader pipelines and support decoder, converters and arbitrary transforms that applications can add.
This merge request was approved by Nikolay Sivov.