Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 81 +++++++++++++++++++++++++++++----- dlls/mfplat/tests/mfplat.c | 90 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 11 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index 8e54a538f6..07c2517788 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -771,22 +771,29 @@ static HRESULT WINAPI sample_RemoveAllBuffers(IMFSample *iface) return S_OK; }
-static HRESULT WINAPI sample_GetTotalLength(IMFSample *iface, DWORD *total_length) +static DWORD sample_get_total_length(struct sample *sample) { - struct sample *sample = impl_from_IMFSample(iface); - DWORD length; + DWORD total_length = 0, length; size_t i;
- TRACE("%p, %p.\n", iface, total_length); - - *total_length = 0; - - EnterCriticalSection(&sample->attributes.cs); for (i = 0; i < sample->buffer_count; ++i) { + length = 0; if (SUCCEEDED(IMFMediaBuffer_GetCurrentLength(sample->buffers[i], &length))) - *total_length += length; + total_length += length; } + + return total_length; +} + +static HRESULT WINAPI sample_GetTotalLength(IMFSample *iface, DWORD *total_length) +{ + struct sample *sample = impl_from_IMFSample(iface); + + TRACE("%p, %p.\n", iface, total_length); + + EnterCriticalSection(&sample->attributes.cs); + *total_length = sample_get_total_length(sample); LeaveCriticalSection(&sample->attributes.cs);
return S_OK; @@ -794,9 +801,61 @@ static HRESULT WINAPI sample_GetTotalLength(IMFSample *iface, DWORD *total_lengt
static HRESULT WINAPI sample_CopyToBuffer(IMFSample *iface, IMFMediaBuffer *buffer) { - FIXME("%p, %p.\n", iface, buffer); + struct sample *sample = impl_from_IMFSample(iface); + 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;
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, buffer); + + EnterCriticalSection(&sample->attributes.cs); + + 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, ¤t_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, ¤t_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); + + LeaveCriticalSection(&sample->attributes.cs); + + return hr; }
static const IMFSampleVtbl samplevtbl = diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 36fe9dc831..38713a4f44 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -1760,12 +1760,14 @@ static void test_system_memory_buffer(void)
static void test_sample(void) { + static const DWORD test_pattern = 0x22222222; IMFMediaBuffer *buffer, *buffer2; DWORD count, flags, length; IMFAttributes *attributes; IMFSample *sample; LONGLONG time; HRESULT hr; + BYTE *data;
hr = MFCreateSample( &sample ); ok(hr == S_OK, "got 0x%08x\n", hr); @@ -1868,6 +1870,94 @@ static void test_sample(void) IMFAttributes_Release(attributes); IMFSample_Release(sample);
+ /* CopyToBuffer() */ + hr = MFCreateSample(&sample); + ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr); + + hr = MFCreateMemoryBuffer(16, &buffer2); + ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr); + + /* Sample with no buffers. */ + hr = IMFMediaBuffer_SetCurrentLength(buffer2, 1); + ok(hr == S_OK, "Failed to set current length, hr %#x.\n", hr); + hr = IMFSample_CopyToBuffer(sample, buffer2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + hr = IMFMediaBuffer_GetCurrentLength(buffer2, &length); + ok(hr == S_OK, "Failed to get current length, hr %#x.\n", hr); + ok(!length, "Unexpected length %u.\n", length); + + /* Single buffer, larger destination. */ + hr = MFCreateMemoryBuffer(8, &buffer); + ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr); + + hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL); + ok(hr == S_OK, "Failed to lock buffer, hr %#x.\n", hr); + *(DWORD *)data = 0x11111111; + hr = IMFMediaBuffer_Unlock(buffer); + ok(hr == S_OK, "Failed to unlock, hr %#x.\n", hr); + hr = IMFMediaBuffer_SetCurrentLength(buffer, 4); + ok(hr == S_OK, "Failed to set current length, hr %#x.\n", hr); + + hr = IMFSample_AddBuffer(sample, buffer); + ok(hr == S_OK, "Failed to add buffer, hr %#x.\n", hr); + + /* Existing content is overwritten. */ + hr = IMFMediaBuffer_SetCurrentLength(buffer2, 8); + ok(hr == S_OK, "Failed to set length, hr %#x.\n", hr); + + hr = IMFSample_CopyToBuffer(sample, buffer2); + ok(hr == S_OK, "Failed to copy to buffer, hr %#x.\n", hr); + + hr = IMFMediaBuffer_GetCurrentLength(buffer2, &length); + ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr); + ok(length == 4, "Unexpected buffer length %u.\n", length); + + /* Multiple buffers, matching total size. */ + hr = IMFSample_AddBuffer(sample, buffer); + ok(hr == S_OK, "Failed to add buffer, hr %#x.\n", hr); + + hr = IMFSample_GetBufferCount(sample, &count); + ok(hr == S_OK, "Failed to get buffer count, hr %#x.\n", hr); + ok(count == 2, "Unexpected buffer count %u.\n", count); + + hr = IMFMediaBuffer_SetCurrentLength(buffer, 8); + ok(hr == S_OK, "Failed to set current length, hr %#x.\n", hr); + + hr = IMFSample_CopyToBuffer(sample, buffer2); + ok(hr == S_OK, "Failed to copy to buffer, hr %#x.\n", hr); + + hr = IMFMediaBuffer_GetCurrentLength(buffer2, &length); + ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr); + ok(length == 16, "Unexpected buffer length %u.\n", length); + + hr = IMFSample_AddBuffer(sample, buffer); + ok(hr == S_OK, "Failed to add buffer, hr %#x.\n", hr); + + hr = IMFMediaBuffer_SetCurrentLength(buffer2, 1); + ok(hr == S_OK, "Failed to set buffer length, hr %#x.\n", hr); + + hr = IMFMediaBuffer_Lock(buffer2, &data, NULL, NULL); + ok(hr == S_OK, "Failed to lock buffer, hr %#x.\n", hr); + *(DWORD *)data = test_pattern; + hr = IMFMediaBuffer_Unlock(buffer2); + ok(hr == S_OK, "Failed to unlock buffer, hr %#x.\n", hr); + + hr = IMFSample_CopyToBuffer(sample, buffer2); + ok(hr == MF_E_BUFFERTOOSMALL, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaBuffer_Lock(buffer2, &data, NULL, NULL); + ok(hr == S_OK, "Failed to lock buffer, hr %#x.\n", hr); + ok(!memcmp(data, &test_pattern, sizeof(test_pattern)), "Unexpected contents, %#x\n", *(DWORD *)data); + hr = IMFMediaBuffer_Unlock(buffer2); + ok(hr == S_OK, "Failed to unlock buffer, hr %#x.\n", hr); + + hr = IMFMediaBuffer_GetCurrentLength(buffer2, &length); + ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr); + ok(!length, "Unexpected buffer length %u.\n", length); + + IMFMediaBuffer_Release(buffer2); + IMFSample_Release(sample); + /* ConvertToContiguousBuffer() */ hr = MFCreateSample(&sample); ok(hr == S_OK, "Failed to create a sample, hr %#x.\n", hr);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/main.c | 22 ++++++++++-- dlls/mf/tests/mf.c | 88 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 105 insertions(+), 5 deletions(-)
diff --git a/dlls/mf/main.c b/dlls/mf/main.c index f38558f82e..f16e3e8aba 100644 --- a/dlls/mf/main.c +++ b/dlls/mf/main.c @@ -1342,9 +1342,27 @@ static ULONG WINAPI simple_type_handler_Release(IMFMediaTypeHandler *iface) static HRESULT WINAPI simple_type_handler_IsMediaTypeSupported(IMFMediaTypeHandler *iface, IMFMediaType *in_type, IMFMediaType **out_type) { - FIXME("%p, %p, %p.\n", iface, in_type, out_type); + struct simple_type_handler *handler = impl_from_IMFMediaTypeHandler(iface); + DWORD flags = 0; + HRESULT hr;
- return E_NOTIMPL; + TRACE("%p, %p, %p.\n", iface, in_type, out_type); + + if (out_type) + *out_type = NULL; + + EnterCriticalSection(&handler->cs); + if (!handler->media_type) + hr = MF_E_UNEXPECTED; + else + { + if (SUCCEEDED(hr = IMFMediaType_IsEqual(handler->media_type, in_type, &flags))) + hr = (flags & (MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES)) == + (MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES) ? S_OK : E_FAIL; + } + LeaveCriticalSection(&handler->cs); + + return hr; }
static HRESULT WINAPI simple_type_handler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count) diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 2dc5ad8f50..dcb20aff05 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2656,7 +2656,7 @@ static void test_evr(void)
static void test_MFCreateSimpleTypeHandler(void) { - IMFMediaType *media_type, *media_type2; + IMFMediaType *media_type, *media_type2, *media_type3; IMFMediaTypeHandler *handler; DWORD count; HRESULT hr; @@ -2668,6 +2668,9 @@ static void test_MFCreateSimpleTypeHandler(void) hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL); ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
+ hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL); + ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#x.\n", hr); + count = 0; hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count); ok(hr == S_OK, "Failed to get type count, hr %#x.\n", hr); @@ -2684,6 +2687,9 @@ static void test_MFCreateSimpleTypeHandler(void) hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
+ hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL); + ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#x.\n", hr); + hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type); ok(hr == S_OK, "Failed to set current type, hr %#x.\n", hr);
@@ -2692,6 +2698,15 @@ static void test_MFCreateSimpleTypeHandler(void) ok(media_type2 == media_type, "Unexpected type.\n"); IMFMediaType_Release(media_type2);
+ hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type2); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 1, &media_type2); ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
@@ -2700,11 +2715,78 @@ static void test_MFCreateSimpleTypeHandler(void) ok(media_type == media_type2, "Unexpected pointer.\n"); IMFMediaType_Release(media_type2);
- IMFMediaType_Release(media_type); - hr = IMFMediaTypeHandler_GetMajorType(handler, &guid); ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr);
+ hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_GetMajorType(handler, &guid); + ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr); + ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n"); + + hr = MFCreateMediaType(&media_type3); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, NULL); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + /* Different major types. */ + media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2); + ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + + hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + + /* Handler missing subtype. */ + hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2); + ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + + /* Different subtypes. */ + hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2); + ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + + /* Same major/subtype. */ + hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + + /* Set one more attribute. */ + hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)4 << 32 | 4); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type3, &media_type2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + + IMFMediaType_Release(media_type3); + IMFMediaType_Release(media_type); + hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL); ok(hr == S_OK, "Failed to set current type, hr %#x.\n", hr);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/mediatype.c | 39 +++++++++++- dlls/mfplat/tests/mfplat.c | 126 ++++++++++++++++++++++++++++++++++++- 2 files changed, 162 insertions(+), 3 deletions(-)
diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c index 6b67f5b33c..8378e24196 100644 --- a/dlls/mfplat/mediatype.c +++ b/dlls/mfplat/mediatype.c @@ -1038,12 +1038,47 @@ static ULONG WINAPI mediatype_handler_Release(IMFMediaTypeHandler *iface) return IMFStreamDescriptor_Release(&stream_desc->IMFStreamDescriptor_iface); }
+static BOOL stream_descriptor_is_mediatype_supported(IMFMediaType *media_type, IMFMediaType *candidate) +{ + DWORD flags = 0; + + if (FAILED(IMFMediaType_IsEqual(media_type, candidate, &flags))) + return FALSE; + + return (flags & (MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES)) == + (MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES); +} + static HRESULT WINAPI mediatype_handler_IsMediaTypeSupported(IMFMediaTypeHandler *iface, IMFMediaType *in_type, IMFMediaType **out_type) { - FIXME("%p, %p, %p.\n", iface, in_type, out_type); + struct stream_desc *stream_desc = impl_from_IMFMediaTypeHandler(iface); + BOOL supported = FALSE; + unsigned int i;
- return E_NOTIMPL; + TRACE("%p, %p, %p.\n", iface, in_type, out_type); + + if (!in_type) + return E_POINTER; + + if (out_type) + *out_type = NULL; + + EnterCriticalSection(&stream_desc->attributes.cs); + + supported = stream_desc->current_type && stream_descriptor_is_mediatype_supported(stream_desc->current_type, in_type); + if (!supported) + { + for (i = 0; i < stream_desc->media_types_count; ++i) + { + if ((supported = stream_descriptor_is_mediatype_supported(stream_desc->media_types[i], in_type))) + break; + } + } + + LeaveCriticalSection(&stream_desc->attributes.cs); + + return supported ? S_OK : MF_E_INVALIDMEDIATYPE; }
static HRESULT WINAPI mediatype_handler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count) diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 38713a4f44..97108e1478 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -3164,7 +3164,7 @@ static void test_MFInvokeCallback(void)
static void test_stream_descriptor(void) { - IMFMediaType *media_types[2], *media_type; + IMFMediaType *media_types[2], *media_type, *media_type2, *media_type3; IMFMediaTypeHandler *type_handler; IMFStreamDescriptor *stream_desc; GUID major_type; @@ -3217,12 +3217,36 @@ static void test_stream_descriptor(void) hr = IMFMediaTypeHandler_GetMediaTypeByIndex(type_handler, 2, &media_type); ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr);
+ /* IsMediaTypeSupported() */ + + hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, NULL, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, NULL, &media_type2); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
+ hr = MFCreateMediaType(&media_type3); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2); + ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + + hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type); ok(hr == S_OK, "Failed to set current type, hr %#x.\n", hr);
+ media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2); + ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + hr = IMFMediaTypeHandler_GetMajorType(type_handler, &major_type); ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr);
@@ -3233,11 +3257,111 @@ static void test_stream_descriptor(void) ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr); ok(IsEqualGUID(&major_type, &MFMediaType_Audio), "Unexpected major type.\n");
+ /* Mismatching major types. */ + hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); + ok(hr == S_OK, "Failed to set major type, hr %#x.\n", hr); + + media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type3, &media_type2); + ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + + /* Subtype missing. */ + hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type3, &media_type2); + ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + + hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type3, &media_type2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + + /* Mismatching subtype. */ + hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFAudioFormat_MP3); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type3, &media_type2); + ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, &count); ok(hr == S_OK, "Failed to get type count, hr %#x.\n", hr); ok(count == ARRAY_SIZE(media_types), "Unexpected type count.\n");
+ IMFMediaTypeHandler_Release(type_handler); + IMFStreamDescriptor_Release(stream_desc); + + /* IsMediaTypeSupported() for unset current type. */ + hr = MFCreateStreamDescriptor(123, ARRAY_SIZE(media_types), media_types, &stream_desc); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFStreamDescriptor_GetMediaTypeHandler(stream_desc, &type_handler); + ok(hr == S_OK, "Failed to get type handler, hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type3, NULL); + ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr); + + /* Initialize one from initial type set. */ + hr = IMFMediaType_CopyAllItems(media_type3, (IMFAttributes *)media_types[0]); + ok(hr == S_OK, "Failed to copy attributes, hr %#x.\n", hr); + + media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type3, &media_type2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + + hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); + ok(hr == S_OK, "Failed to copy attributes, hr %#x.\n", hr); + + media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type3, &media_type2); + ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + + hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFAudioFormat_MP3); + ok(hr == S_OK, "Failed to copy attributes, hr %#x.\n", hr); + + media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type3, &media_type2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + + /* Now set current type that's not compatible. */ + hr = IMFMediaType_SetGUID(media_type3, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); + ok(hr == S_OK, "Failed to copy attributes, hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(media_type3, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8); + ok(hr == S_OK, "Failed to copy attributes, hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type3); + ok(hr == S_OK, "Failed to set current type, hr %#x.\n", hr); + + media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type3, &media_type2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + + hr = IMFMediaType_CopyAllItems(media_types[0], (IMFAttributes *)media_type); + ok(hr == S_OK, "Failed to copy attributes, hr %#x.\n", hr); + + media_type2 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(type_handler, media_type, &media_type2); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!media_type2, "Unexpected pointer.\n"); + IMFMediaType_Release(media_type); + IMFMediaType_Release(media_type3);
IMFMediaTypeHandler_Release(type_handler);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=66844
Your paranoid android.
=== w1064v1809_ja (32 bit report) ===
mfplat: mfplat.c:2677: Test failed: Unexpected return value 0x102. mfplat.c:2028: Test failed: Failed to get event, hr 0xc00d3e85. mfplat.c:2031: Test failed: Failed to get event, hr 0xc00d3e85. mfplat.c:2034: Test failed: Failed to finalize GetEvent, hr 0xc00d3e85. mfplat.c:2037: Test failed: Unexpected result, hr 0xc00d3e85. 133c:mfplat: unhandled exception c0000005 at 00401AFB
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mf/mf.spec | 2 +- dlls/mf/tests/mf.c | 81 +++++++++++++++++++++++++++++++++++++++++++ dlls/mf/topology.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++ include/mfidl.idl | 1 + 4 files changed, 168 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/mf.spec b/dlls/mf/mf.spec index 1c3fc9c953..4b5b085d08 100644 --- a/dlls/mf/mf.spec +++ b/dlls/mf/mf.spec @@ -75,7 +75,7 @@ @ stdcall MFGetService(ptr ptr ptr ptr) @ stdcall MFGetSupportedMimeTypes(ptr) @ stdcall MFGetSupportedSchemes(ptr) -@ stub MFGetTopoNodeCurrentType +@ stdcall MFGetTopoNodeCurrentType(ptr long long ptr) @ stub MFReadSequencerSegmentOffset @ stub MFRequireProtectedEnvironment @ stdcall MFShutdownObject(ptr) diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index dcb20aff05..da533d05d3 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3103,6 +3103,86 @@ static void test_sample_copier(void) IMFTransform_Release(copier); }
+static void test_MFGetTopoNodeCurrentType(void) +{ + IMFMediaType *media_type, *media_type2; + IMFTopologyNode *node; + HRESULT hr; + + /* Tee node. */ + hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node); + ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr); + + hr = MFGetTopoNodeCurrentType(node, 0, TRUE, &media_type); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = MFCreateMediaType(&media_type2); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + /* Input type returned, if set. */ + hr = IMFTopologyNode_SetInputPrefType(node, 0, media_type2); + ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr); + + hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(media_type == media_type2, "Unexpected pointer.\n"); + IMFMediaType_Release(media_type); + + hr = IMFTopologyNode_SetInputPrefType(node, 0, NULL); + ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr); + + hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + /* Set second output. */ + hr = IMFTopologyNode_SetOutputPrefType(node, 1, media_type2); + ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr); + + hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type); + ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr); + + hr = IMFTopologyNode_SetOutputPrefType(node, 1, NULL); + ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr); + + /* Set first output. */ + hr = IMFTopologyNode_SetOutputPrefType(node, 0, media_type2); + ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr); + + hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(media_type == media_type2, "Unexpected pointer.\n"); + IMFMediaType_Release(media_type); + + hr = IMFTopologyNode_SetOutputPrefType(node, 0, NULL); + ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr); + + /* Set primary output. */ + hr = IMFTopologyNode_SetOutputPrefType(node, 1, media_type2); + ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr); + + hr = IMFTopologyNode_SetUINT32(node, &MF_TOPONODE_PRIMARYOUTPUT, 1); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = MFGetTopoNodeCurrentType(node, 0, FALSE, &media_type); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(media_type == media_type2, "Unexpected pointer.\n"); + IMFMediaType_Release(media_type); + + hr = MFGetTopoNodeCurrentType(node, 0, TRUE, &media_type); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(media_type == media_type2, "Unexpected pointer.\n"); + IMFMediaType_Release(media_type); + + IMFTopologyNode_Release(node); + IMFMediaType_Release(media_type2); +} + START_TEST(mf) { test_topology(); @@ -3121,4 +3201,5 @@ START_TEST(mf) test_MFGetSupportedMimeTypes(); test_MFGetSupportedSchemes(); test_sample_copier(); + test_MFGetTopoNodeCurrentType(); } diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c index db82816328..67afba6ba4 100644 --- a/dlls/mf/topology.c +++ b/dlls/mf/topology.c @@ -1786,6 +1786,91 @@ HRESULT WINAPI MFCreateTopologyNode(MF_TOPOLOGY_TYPE node_type, IMFTopologyNode return hr; }
+/*********************************************************************** + * MFGetTopoNodeCurrentType (mf.@) + */ +HRESULT WINAPI MFGetTopoNodeCurrentType(IMFTopologyNode *node, DWORD stream, BOOL output, IMFMediaType **type) +{ + IMFMediaTypeHandler *type_handler; + MF_TOPOLOGY_TYPE node_type; + IMFStreamSink *stream_sink; + IMFStreamDescriptor *sd; + IMFTransform *transform; + UINT32 primary_output; + IUnknown *object; + HRESULT hr; + + TRACE("%p, %u, %d, %p.\n", node, stream, output, type); + + if (FAILED(hr = IMFTopologyNode_GetNodeType(node, &node_type))) + return hr; + + switch (node_type) + { + case MF_TOPOLOGY_OUTPUT_NODE: + if (FAILED(hr = IMFTopologyNode_GetObject(node, &object))) + return hr; + + hr = IUnknown_QueryInterface(object, &IID_IMFStreamSink, (void **)&stream_sink); + IUnknown_Release(object); + if (SUCCEEDED(hr)) + { + hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &type_handler); + IMFStreamSink_Release(stream_sink); + + if (SUCCEEDED(hr)) + { + hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, type); + IMFMediaTypeHandler_Release(type_handler); + } + } + break; + case MF_TOPOLOGY_SOURCESTREAM_NODE: + if (FAILED(hr = IMFTopologyNode_GetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR, &IID_IMFStreamDescriptor, + (void **)&sd))) + { + return hr; + } + + hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &type_handler); + IMFStreamDescriptor_Release(sd); + if (SUCCEEDED(hr)) + { + hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, type); + IMFMediaTypeHandler_Release(type_handler); + } + break; + case MF_TOPOLOGY_TRANSFORM_NODE: + if (FAILED(hr = IMFTopologyNode_GetObject(node, &object))) + return hr; + + hr = IUnknown_QueryInterface(object, &IID_IMFTransform, (void **)&transform); + IUnknown_Release(object); + if (SUCCEEDED(hr)) + { + if (output) + hr = IMFTransform_GetOutputCurrentType(transform, stream, type); + else + hr = IMFTransform_GetInputCurrentType(transform, stream, type); + IMFTransform_Release(transform); + } + break; + case MF_TOPOLOGY_TEE_NODE: + if (SUCCEEDED(hr = IMFTopologyNode_GetInputPrefType(node, 0, type))) + break; + + if (FAILED(IMFTopologyNode_GetUINT32(node, &MF_TOPONODE_PRIMARYOUTPUT, &primary_output))) + primary_output = 0; + + hr = IMFTopologyNode_GetOutputPrefType(node, primary_output, type); + break; + default: + ; + } + + return hr; +} + static HRESULT WINAPI topology_loader_QueryInterface(IMFTopoLoader *iface, REFIID riid, void **out) { TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out); diff --git a/include/mfidl.idl b/include/mfidl.idl index cf04ec17ce..60337f8106 100644 --- a/include/mfidl.idl +++ b/include/mfidl.idl @@ -609,6 +609,7 @@ cpp_quote("HRESULT WINAPI MFGetSupportedMimeTypes(PROPVARIANT *array);") cpp_quote("HRESULT WINAPI MFGetSupportedSchemes(PROPVARIANT *array);") cpp_quote("HRESULT WINAPI MFGetService(IUnknown *object, REFGUID service, REFIID iid, void **obj);") cpp_quote("MFTIME WINAPI MFGetSystemTime(void);") +cpp_quote("HRESULT WINAPI MFGetTopoNodeCurrentType(IMFTopologyNode *node, DWORD stream, BOOL output, IMFMediaType **type);") cpp_quote("HRESULT WINAPI MFShutdownObject(IUnknown *object);")
typedef enum _MFMEDIASOURCE_CHARACTERISTICS
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=66845
Your paranoid android.
=== w1064v1809_zh_CN (32 bit report) ===
mf: mf.c:1007: Test failed: Unexpected return value 0x102. mf.c:931: Test failed: Failed to finalize GetEvent, hr 0xc00d3e85. 18f0:mf: unhandled exception c0000005 at 0040297F