Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 151 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 145 insertions(+), 6 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 06be27daa3..c57dd10fd5 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -1908,6 +1908,7 @@ static const IMFMediaSourceVtbl mfsourcevtbl = enum resolved_object_origin { OBJECT_FROM_BYTESTREAM, + OBJECT_FROM_URL, };
struct resolver_queued_result @@ -1937,6 +1938,7 @@ typedef struct source_resolver IMFSourceResolver IMFSourceResolver_iface; LONG refcount; IMFAsyncCallback stream_callback; + IMFAsyncCallback url_callback; CRITICAL_SECTION cs; struct list pending; } mfsourceresolver; @@ -1951,6 +1953,11 @@ static struct source_resolver *impl_from_stream_IMFAsyncCallback(IMFAsyncCallbac return CONTAINING_RECORD(iface, struct source_resolver, stream_callback); }
+static struct source_resolver *impl_from_url_IMFAsyncCallback(IMFAsyncCallback *iface) +{ + return CONTAINING_RECORD(iface, struct source_resolver, url_callback); +} + static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enum resolved_object_origin origin, IMFAsyncResult *result) { @@ -1960,6 +1967,7 @@ static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enu { IUnknown *handler; IMFByteStreamHandler *stream_handler; + IMFSchemeHandler *scheme_handler; } handler;
queued_result = heap_alloc(sizeof(*queued_result)); @@ -1972,6 +1980,10 @@ static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enu queued_result->hr = IMFByteStreamHandler_EndCreateObject(handler.stream_handler, result, &queued_result->obj_type, &queued_result->object); break; + case OBJECT_FROM_URL: + queued_result->hr = IMFSchemeHandler_EndCreateObject(handler.scheme_handler, result, &queued_result->obj_type, + &queued_result->object); + break; default: queued_result->hr = E_FAIL; } @@ -2132,6 +2144,34 @@ static const IMFAsyncCallbackVtbl source_resolver_callback_stream_vtbl = source_resolver_callback_stream_Invoke, };
+static ULONG WINAPI source_resolver_callback_url_AddRef(IMFAsyncCallback *iface) +{ + struct source_resolver *resolver = impl_from_url_IMFAsyncCallback(iface); + return IMFSourceResolver_AddRef(&resolver->IMFSourceResolver_iface); +} + +static ULONG WINAPI source_resolver_callback_url_Release(IMFAsyncCallback *iface) +{ + struct source_resolver *resolver = impl_from_url_IMFAsyncCallback(iface); + return IMFSourceResolver_Release(&resolver->IMFSourceResolver_iface); +} + +static HRESULT WINAPI source_resolver_callback_url_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) +{ + struct source_resolver *resolver = impl_from_url_IMFAsyncCallback(iface); + + return resolver_handler_end_create(resolver, OBJECT_FROM_URL, result); +} + +static const IMFAsyncCallbackVtbl source_resolver_callback_url_vtbl = +{ + source_resolver_callback_QueryInterface, + source_resolver_callback_url_AddRef, + source_resolver_callback_url_Release, + source_resolver_callback_GetParameters, + source_resolver_callback_url_Invoke, +}; + static HRESULT resolver_create_registered_handler(HKEY hkey, REFIID riid, void **handler) { unsigned int j = 0, name_length, type; @@ -2223,6 +2263,73 @@ static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHA return hr; }
+static HRESULT resolver_get_scheme_handler(const WCHAR *url, DWORD flags, IMFSchemeHandler **handler) +{ + static const char schemehandlerspath[] = "Software\Microsoft\Windows Media Foundation\SchemeHandlers"; + static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE }; + const WCHAR *ptr = url; + unsigned int len, i; + WCHAR *scheme; + HRESULT hr; + + /* RFC 3986: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */ + while (*ptr) + { + WCHAR ch = tolowerW(*ptr); + + if (*ptr == '*' && ptr == url) + { + ptr++; + break; + } + else if (!(*ptr >= '0' && *ptr <= '9') && + !(ch >= 'a' && ch <= 'z') && + *ptr != '+' && *ptr != '-' && *ptr != '.') + { + break; + } + + ptr++; + } + + /* Schemes must end with a ':' */ + if (ptr == url || *ptr != ':') + return MF_E_UNSUPPORTED_SCHEME; + + len = ptr - url; + scheme = heap_alloc((len + 1) * sizeof(WCHAR)); + if (!scheme) + return E_OUTOFMEMORY; + + memcpy(scheme, url, len * sizeof(WCHAR)); + scheme[len] = 0; + + /* FIXME: check local handlers first */ + + for (i = 0, hr = E_FAIL; i < ARRAY_SIZE(hkey_roots); ++i) + { + HKEY hkey, hkey_handler; + + if (RegOpenKeyA(hkey_roots[i], schemehandlerspath, &hkey)) + continue; + + if (!RegOpenKeyW(hkey, scheme, &hkey_handler)) + { + hr = resolver_create_registered_handler(hkey_handler, &IID_IMFSchemeHandler, (void **)handler); + RegCloseKey(hkey_handler); + } + + RegCloseKey(hkey); + + if (SUCCEEDED(hr)) + break; + } + + heap_free(scheme); + + return hr; +} + static HRESULT resolver_end_create_object(struct source_resolver *resolver, enum resolved_object_origin origin, IMFAsyncResult *result, MF_OBJECT_TYPE *obj_type, IUnknown **out) { @@ -2318,14 +2425,45 @@ static ULONG WINAPI source_resolver_Release(IMFSourceResolver *iface) return refcount; }
-static HRESULT WINAPI mfsourceresolver_CreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url, - DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object) +static HRESULT WINAPI source_resolver_CreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url, + DWORD flags, IPropertyStore *props, MF_OBJECT_TYPE *obj_type, IUnknown **object) { - mfsourceresolver *This = impl_from_IMFSourceResolver(iface); + struct source_resolver *resolver = impl_from_IMFSourceResolver(iface); + IMFSchemeHandler *handler; + IMFAsyncResult *result; + MFASYNCRESULT *data; + HRESULT hr;
- FIXME("(%p)->(%s, %#x, %p, %p, %p): stub\n", This, debugstr_w(url), flags, props, obj_type, object); + TRACE("%p, %s, %#x, %p, %p, %p\n", iface, debugstr_w(url), flags, props, obj_type, object);
- return E_NOTIMPL; + if (!url || !obj_type || !object) + return E_POINTER; + + if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler))) + return hr; + + hr = MFCreateAsyncResult((IUnknown *)handler, NULL, NULL, &result); + IMFSchemeHandler_Release(handler); + if (FAILED(hr)) + return hr; + + data = (MFASYNCRESULT *)result; + data->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + + hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, NULL, &resolver->stream_callback, + (IUnknown *)result); + if (FAILED(hr)) + { + IMFAsyncResult_Release(result); + return hr; + } + + WaitForSingleObject(data->hEvent, INFINITE); + + hr = resolver_end_create_object(resolver, OBJECT_FROM_URL, result, obj_type, object); + IMFAsyncResult_Release(result); + + return hr; }
static HRESULT WINAPI source_resolver_CreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream, @@ -2484,7 +2622,7 @@ static const IMFSourceResolverVtbl mfsourceresolvervtbl = source_resolver_QueryInterface, source_resolver_AddRef, source_resolver_Release, - mfsourceresolver_CreateObjectFromURL, + source_resolver_CreateObjectFromURL, source_resolver_CreateObjectFromByteStream, mfsourceresolver_BeginCreateObjectFromURL, mfsourceresolver_EndCreateObjectFromURL, @@ -2511,6 +2649,7 @@ HRESULT WINAPI MFCreateSourceResolver(IMFSourceResolver **resolver)
object->IMFSourceResolver_iface.lpVtbl = &mfsourceresolvervtbl; object->stream_callback.lpVtbl = &source_resolver_callback_stream_vtbl; + object->url_callback.lpVtbl = &source_resolver_callback_url_vtbl; object->refcount = 1; list_init(&object->pending); InitializeCriticalSection(&object->cs);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 60 +++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 17 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index c57dd10fd5..f12666f053 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -1928,6 +1928,7 @@ struct resolver_cancel_object { IUnknown *handler; IMFByteStreamHandler *stream_handler; + IMFSchemeHandler *scheme_handler; } u; IUnknown *cancel_cookie; enum resolved_object_origin origin; @@ -1977,12 +1978,12 @@ static HRESULT resolver_handler_end_create(struct source_resolver *resolver, enu switch (origin) { case OBJECT_FROM_BYTESTREAM: - queued_result->hr = IMFByteStreamHandler_EndCreateObject(handler.stream_handler, result, &queued_result->obj_type, - &queued_result->object); + queued_result->hr = IMFByteStreamHandler_EndCreateObject(handler.stream_handler, result, + &queued_result->obj_type, &queued_result->object); break; case OBJECT_FROM_URL: - queued_result->hr = IMFSchemeHandler_EndCreateObject(handler.scheme_handler, result, &queued_result->obj_type, - &queued_result->object); + queued_result->hr = IMFSchemeHandler_EndCreateObject(handler.scheme_handler, result, + &queued_result->obj_type, &queued_result->object); break; default: queued_result->hr = E_FAIL; @@ -2528,25 +2529,47 @@ fallback: return E_NOTIMPL; }
-static HRESULT WINAPI mfsourceresolver_BeginCreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url, - DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *unk_state) +static HRESULT WINAPI source_resolver_BeginCreateObjectFromURL(IMFSourceResolver *iface, const WCHAR *url, + DWORD flags, IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state) { - mfsourceresolver *This = impl_from_IMFSourceResolver(iface); + struct source_resolver *resolver = impl_from_IMFSourceResolver(iface); + IMFSchemeHandler *handler; + IUnknown *inner_cookie = NULL; + IMFAsyncResult *result; + HRESULT hr;
- FIXME("(%p)->(%s, %#x, %p, %p, %p, %p): stub\n", This, debugstr_w(url), flags, props, cancel_cookie, - callback, unk_state); + TRACE("%p, %s, %#x, %p, %p, %p, %p.\n", iface, debugstr_w(url), flags, props, cancel_cookie, callback, state);
- return E_NOTIMPL; + if (FAILED(hr = resolver_get_scheme_handler(url, flags, &handler))) + return hr; + + if (cancel_cookie) + *cancel_cookie = NULL; + + hr = MFCreateAsyncResult((IUnknown *)handler, callback, state, &result); + IMFSchemeHandler_Release(handler); + if (FAILED(hr)) + return hr; + + hr = IMFSchemeHandler_BeginCreateObject(handler, url, flags, props, cancel_cookie ? &inner_cookie : NULL, + &resolver->url_callback, (IUnknown *)result); + + if (SUCCEEDED(hr) && inner_cookie) + resolver_create_cancel_object((IUnknown *)handler, OBJECT_FROM_URL, inner_cookie, cancel_cookie); + + IMFAsyncResult_Release(result); + + return hr; }
-static HRESULT WINAPI mfsourceresolver_EndCreateObjectFromURL(IMFSourceResolver *iface, IMFAsyncResult *result, - MF_OBJECT_TYPE *obj_type, IUnknown **object) +static HRESULT WINAPI source_resolver_EndCreateObjectFromURL(IMFSourceResolver *iface, IMFAsyncResult *result, + MF_OBJECT_TYPE *obj_type, IUnknown **object) { - mfsourceresolver *This = impl_from_IMFSourceResolver(iface); + struct source_resolver *resolver = impl_from_IMFSourceResolver(iface);
- FIXME("(%p)->(%p, %p, %p): stub\n", This, result, obj_type, object); + TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
- return E_NOTIMPL; + return resolver_end_create_object(resolver, OBJECT_FROM_URL, result, obj_type, object); }
static HRESULT WINAPI source_resolver_BeginCreateObjectFromByteStream(IMFSourceResolver *iface, IMFByteStream *stream, @@ -2610,6 +2633,9 @@ static HRESULT WINAPI source_resolver_CancelObjectCreation(IMFSourceResolver *if case OBJECT_FROM_BYTESTREAM: hr = IMFByteStreamHandler_CancelObjectCreation(object->u.stream_handler, object->cancel_cookie); break; + case OBJECT_FROM_URL: + hr = IMFSchemeHandler_CancelObjectCreation(object->u.scheme_handler, object->cancel_cookie); + break; default: hr = E_UNEXPECTED; } @@ -2624,8 +2650,8 @@ static const IMFSourceResolverVtbl mfsourceresolvervtbl = source_resolver_Release, source_resolver_CreateObjectFromURL, source_resolver_CreateObjectFromByteStream, - mfsourceresolver_BeginCreateObjectFromURL, - mfsourceresolver_EndCreateObjectFromURL, + source_resolver_BeginCreateObjectFromURL, + source_resolver_EndCreateObjectFromURL, source_resolver_BeginCreateObjectFromByteStream, source_resolver_EndCreateObjectFromByteStream, source_resolver_CancelObjectCreation,
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/mediatype.c | 101 ++++++++++++++++++++++++++++++++++++- dlls/mfplat/tests/mfplat.c | 89 ++++++++++++++++++++++++++++++-- include/mfapi.h | 3 ++ 3 files changed, 188 insertions(+), 5 deletions(-)
diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c index 974ab3aba3..27ca405175 100644 --- a/dlls/mfplat/mediatype.c +++ b/dlls/mfplat/mediatype.c @@ -332,9 +332,106 @@ static HRESULT WINAPI mediatype_IsCompressedFormat(IMFMediaType *iface, BOOL *co
static HRESULT WINAPI mediatype_IsEqual(IMFMediaType *iface, IMFMediaType *type, DWORD *flags) { - FIXME("%p, %p, %p.\n", iface, type, flags); + const DWORD full_equality_flags = MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES | + MF_MEDIATYPE_EQUAL_FORMAT_DATA | MF_MEDIATYPE_EQUAL_FORMAT_USER_DATA; + struct media_type *media_type = impl_from_IMFMediaType(iface); + struct comparand + { + IMFAttributes *type; + PROPVARIANT value; + UINT32 count; + GUID guid; + HRESULT hr; + } left, right, swp; + unsigned int i; + BOOL result;
- return E_NOTIMPL; + TRACE("%p, %p, %p.\n", iface, type, flags); + + *flags = 0; + + left.type = &media_type->attributes.IMFAttributes_iface; + right.type = (IMFAttributes *)type; + + if (FAILED(IMFAttributes_GetGUID(left.type, &MF_MT_MAJOR_TYPE, &left.guid))) + return E_INVALIDARG; + + if (FAILED(IMFAttributes_GetGUID(right.type, &MF_MT_MAJOR_TYPE, &right.guid))) + return E_INVALIDARG; + + if (IsEqualGUID(&left.guid, &right.guid)) + *flags |= MF_MEDIATYPE_EQUAL_MAJOR_TYPES; + + /* Subtypes equal or both missing. */ + left.hr = IMFAttributes_GetGUID(left.type, &MF_MT_SUBTYPE, &left.guid); + right.hr = IMFAttributes_GetGUID(right.type, &MF_MT_SUBTYPE, &right.guid); + + if ((SUCCEEDED(left.hr) && SUCCEEDED(right.hr) && IsEqualGUID(&left.guid, &right.guid)) || + (FAILED(left.hr) && FAILED(right.hr))) + { + *flags |= MF_MEDIATYPE_EQUAL_FORMAT_TYPES; + } + + /* Format data */ + IMFAttributes_GetCount(left.type, &left.count); + IMFAttributes_GetCount(right.type, &right.count); + + if (right.count < left.count) + { + swp = left; + left = right; + right = swp; + } + + *flags |= MF_MEDIATYPE_EQUAL_FORMAT_DATA; + + for (i = 0; i < left.count; ++i) + { + PROPVARIANT value; + GUID key; + + if (SUCCEEDED(IMFAttributes_GetItemByIndex(left.type, i, &key, &value))) + { + if (IsEqualGUID(&key, &MF_MT_USER_DATA) || + IsEqualGUID(&key, &MF_MT_FRAME_RATE_RANGE_MIN) || + IsEqualGUID(&key, &MF_MT_FRAME_RATE_RANGE_MAX)) + { + PropVariantClear(&value); + continue; + } + + result = FALSE; + IMFAttributes_CompareItem(right.type, &key, &value, &result); + PropVariantClear(&value); + if (!result) + { + *flags &= ~MF_MEDIATYPE_EQUAL_FORMAT_DATA; + break; + } + } + } + + /* User data */ + PropVariantInit(&left.value); + left.hr = IMFAttributes_GetItem(left.type, &MF_MT_USER_DATA, &left.value); + PropVariantInit(&right.value); + right.hr = IMFAttributes_GetItem(right.type, &MF_MT_USER_DATA, &right.value); + + if (SUCCEEDED(left.hr) && SUCCEEDED(left.hr)) + { + result = FALSE; + IMFAttributes_CompareItem(left.type, &MF_MT_USER_DATA, &left.value, &result); + } + else if (FAILED(left.hr) && FAILED(left.hr)) + result = TRUE; + + PropVariantClear(&left.value); + PropVariantClear(&right.value); + + if (result) + *flags |= MF_MEDIATYPE_EQUAL_FORMAT_USER_DATA; + + return *flags == full_equality_flags ? S_OK : S_FALSE; }
static HRESULT WINAPI mediatype_GetRepresentation(IMFMediaType *iface, GUID guid, void **representation) diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 3fa729b50e..ca00ac17d9 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -328,10 +328,13 @@ static void init_functions(void) is_win8_plus = pMFPutWaitingWorkItem != NULL; }
-static void test_MFCreateMediaType(void) +static void test_media_type(void) { + IMFMediaType *mediatype, *mediatype2; + BOOL compressed; + DWORD flags; HRESULT hr; - IMFMediaType *mediatype; + GUID guid;
if(0) { @@ -343,9 +346,89 @@ if(0) hr = MFCreateMediaType(&mediatype); ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = IMFMediaType_GetMajorType(mediatype, &guid); +todo_wine + ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr); + + compressed = FALSE; + hr = IMFMediaType_IsCompressedFormat(mediatype, &compressed); +todo_wine + ok(hr == S_OK, "Failed to get media type property, hr %#x.\n", hr); + ok(compressed, "Unexpected value %d.\n", compressed); + + hr = IMFMediaType_SetUINT32(mediatype, &MF_MT_ALL_SAMPLES_INDEPENDENT, 0); +todo_wine + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + compressed = FALSE; + hr = IMFMediaType_IsCompressedFormat(mediatype, &compressed); +todo_wine + ok(hr == S_OK, "Failed to get media type property, hr %#x.\n", hr); + ok(compressed, "Unexpected value %d.\n", compressed); + + hr = IMFMediaType_SetUINT32(mediatype, &MF_MT_ALL_SAMPLES_INDEPENDENT, 1); +todo_wine + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + compressed = TRUE; + hr = IMFMediaType_IsCompressedFormat(mediatype, &compressed); +todo_wine { + ok(hr == S_OK, "Failed to get media type property, hr %#x.\n", hr); + ok(!compressed, "Unexpected value %d.\n", compressed); +} hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = IMFMediaType_GetMajorType(mediatype, &guid); +todo_wine { + ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr); + ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n"); +} + /* IsEqual() */ + hr = MFCreateMediaType(&mediatype2); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + flags = 0xdeadbeef; + hr = IMFMediaType_IsEqual(mediatype, mediatype2, &flags); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + ok(flags == 0, "Unexpected flags %#x.\n", flags); + + /* Different major types. */ + hr = IMFMediaType_SetGUID(mediatype2, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); +todo_wine + ok(hr == S_OK, "Failed to set major type, hr %#x.\n", hr); + + flags = 0; + hr = IMFMediaType_IsEqual(mediatype, mediatype2, &flags); +todo_wine { + ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr); + ok(flags == (MF_MEDIATYPE_EQUAL_FORMAT_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_USER_DATA), + "Unexpected flags %#x.\n", flags); +} + /* Same major types, different subtypes. */ + hr = IMFMediaType_SetGUID(mediatype2, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); +todo_wine + ok(hr == S_OK, "Failed to set major type, hr %#x.\n", hr); + + flags = 0; + hr = IMFMediaType_IsEqual(mediatype, mediatype2, &flags); +todo_wine { + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(flags == (MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_DATA + | MF_MEDIATYPE_EQUAL_FORMAT_USER_DATA), "Unexpected flags %#x.\n", flags); +} + hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32); +todo_wine + ok(hr == S_OK, "Failed to set subtype, hr %#x.\n", hr); + + flags = 0; + hr = IMFMediaType_IsEqual(mediatype, mediatype2, &flags); +todo_wine { + ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr); + ok(flags == (MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_DATA | MF_MEDIATYPE_EQUAL_FORMAT_USER_DATA), + "Unexpected flags %#x.\n", flags); +} + IMFMediaType_Release(mediatype2); IMFMediaType_Release(mediatype); }
@@ -1766,7 +1849,7 @@ START_TEST(mfplat)
test_startup(); test_register(); - test_MFCreateMediaType(); + test_media_type(); test_MFCreateMediaEvent(); test_MFCreateAttributes(); test_sample(); diff --git a/include/mfapi.h b/include/mfapi.h index 2ad9f25062..fd5fbebc58 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -88,6 +88,9 @@ DEFINE_GUID(MF_MT_MAJOR_TYPE, 0x48eba18e, 0xf8c9, 0x4687, 0xbf, 0x1 DEFINE_GUID(MF_MT_PIXEL_ASPECT_RATIO, 0xc6376a1e, 0x8d0a, 0x4027, 0xbe, 0x45, 0x6d, 0x9a, 0x0a, 0xd3, 0x9b, 0xb6); DEFINE_GUID(MF_MT_SUBTYPE, 0xf7e34c9a, 0x42e8, 0x4714, 0xb7, 0x4b, 0xcb, 0x29, 0xd7, 0x2c, 0x35, 0xe5); DEFINE_GUID(MF_MT_ALL_SAMPLES_INDEPENDENT, 0xc9173739, 0x5e56, 0x461c, 0xb7, 0x13, 0x46, 0xfb, 0x99, 0x5c, 0xb9, 0x5f); +DEFINE_GUID(MF_MT_USER_DATA, 0xb6bc765f, 0x4c3b, 0x40a4, 0xbd, 0x51, 0x25, 0x35, 0xb6, 0x6f, 0xe0, 0x9d); +DEFINE_GUID(MF_MT_FRAME_RATE_RANGE_MIN, 0xd2e7558c, 0xdc1f, 0x403f, 0x9a, 0x72, 0xd2, 0x8b, 0xb1, 0xeb, 0x3b, 0x5e); +DEFINE_GUID(MF_MT_FRAME_RATE_RANGE_MAX, 0xe3371d41, 0xb4cf, 0x4a05, 0xbd, 0x4e, 0x20, 0xb8, 0x8b, 0xb2, 0xc4, 0xd6);
DEFINE_GUID(MFT_CATEGORY_VIDEO_DECODER, 0xd6c02d4b, 0x6833, 0x45b4, 0x97, 0x1a, 0x05, 0xa4, 0xb0, 0x4b, 0xab, 0x91); DEFINE_GUID(MFT_CATEGORY_VIDEO_ENCODER, 0xf79eac7d, 0xe545, 0x4387, 0xbd, 0xee, 0xd6, 0x47, 0xd7, 0xbd, 0xe4, 0x2a);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/Makefile.in | 2 +- dlls/mfreadwrite/main.c | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/dlls/mfreadwrite/Makefile.in b/dlls/mfreadwrite/Makefile.in index afefdb5cc6..edc7ebd07d 100644 --- a/dlls/mfreadwrite/Makefile.in +++ b/dlls/mfreadwrite/Makefile.in @@ -1,6 +1,6 @@ MODULE = mfreadwrite.dll IMPORTLIB = mfreadwrite -IMPORTS = mfuuid uuid +IMPORTS = mfuuid uuid mfplat
C_SRCS = \ main.c diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 098100df91..bcf79a8fbd 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -254,9 +254,23 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri static HRESULT create_source_reader_from_stream(IMFByteStream *stream, IMFAttributes *attributes, REFIID riid, void **out) { - /* FIXME: resolve bytestream to media source */ + IMFSourceResolver *resolver; + MF_OBJECT_TYPE obj_type; + IMFMediaSource *source; + HRESULT hr; + + if (FAILED(hr = MFCreateSourceResolver(&resolver))) + return hr;
- return create_source_reader_from_source(NULL, attributes, riid, out); + hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, NULL, MF_RESOLUTION_MEDIASOURCE, NULL, + &obj_type, (IUnknown **)&source); + IMFSourceResolver_Release(resolver); + if (FAILED(hr)) + return hr; + + hr = create_source_reader_from_source(source, attributes, riid, out); + IMFMediaSource_Release(source); + return hr; }
static HRESULT WINAPI sink_writer_QueryInterface(IMFSinkWriter *iface, REFIID riid, void **out)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 60 ++++++++++++++++++++++++++++++- dlls/mfreadwrite/mfreadwrite.spec | 2 +- include/mfreadwrite.idl | 1 + 3 files changed, 61 insertions(+), 2 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index bcf79a8fbd..88903ceddf 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -273,6 +273,47 @@ static HRESULT create_source_reader_from_stream(IMFByteStream *stream, IMFAttrib return hr; }
+static HRESULT create_source_reader_from_url(const WCHAR *url, IMFAttributes *attributes, REFIID riid, void **out) +{ + IMFSourceResolver *resolver; + IUnknown *object = NULL; + MF_OBJECT_TYPE obj_type; + IMFMediaSource *source; + HRESULT hr; + + if (FAILED(hr = MFCreateSourceResolver(&resolver))) + return hr; + + hr = IMFSourceResolver_CreateObjectFromURL(resolver, url, MF_RESOLUTION_MEDIASOURCE, NULL, &obj_type, + (IUnknown **)&object); + if (SUCCEEDED(hr)) + { + switch (obj_type) + { + case MF_OBJECT_BYTESTREAM: + hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, (IMFByteStream *)object, NULL, + MF_RESOLUTION_MEDIASOURCE, NULL, &obj_type, (IUnknown **)&source); + break; + case MF_OBJECT_MEDIASOURCE: + source = (IMFMediaSource *)object; + IMFMediaSource_AddRef(source); + break; + default: + WARN("Unknown object type %d.\n", obj_type); + hr = E_UNEXPECTED; + } + IUnknown_Release(object); + } + + IMFSourceResolver_Release(resolver); + if (FAILED(hr)) + return hr; + + hr = create_source_reader_from_source(source, attributes, riid, out); + IMFMediaSource_Release(source); + return hr; +} + static HRESULT WINAPI sink_writer_QueryInterface(IMFSinkWriter *iface, REFIID riid, void **out) { TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out); @@ -480,6 +521,16 @@ HRESULT WINAPI MFCreateSourceReaderFromMediaSource(IMFMediaSource *source, IMFAt return create_source_reader_from_source(source, attributes, &IID_IMFSourceReader, (void **)reader); }
+/*********************************************************************** + * MFCreateSourceReaderFromURL (mfreadwrite.@) + */ +HRESULT WINAPI MFCreateSourceReaderFromURL(const WCHAR *url, IMFAttributes *attributes, IMFSourceReader **reader) +{ + TRACE("%s, %p, %p.\n", debugstr_w(url), attributes, reader); + + return create_source_reader_from_url(url, attributes, &IID_IMFSourceReader, (void **)reader); +} + static HRESULT WINAPI readwrite_factory_QueryInterface(IMFReadWriteClassFactory *iface, REFIID riid, void **out) { if (IsEqualIID(riid, &IID_IMFReadWriteClassFactory) || @@ -508,7 +559,14 @@ static ULONG WINAPI readwrite_factory_Release(IMFReadWriteClassFactory *iface) static HRESULT WINAPI readwrite_factory_CreateInstanceFromURL(IMFReadWriteClassFactory *iface, REFCLSID clsid, const WCHAR *url, IMFAttributes *attributes, REFIID riid, void **out) { - FIXME("%s, %s, %p, %s, %p.\n", debugstr_guid(clsid), debugstr_w(url), attributes, debugstr_guid(riid), out); + TRACE("%s, %s, %p, %s, %p.\n", debugstr_guid(clsid), debugstr_w(url), attributes, debugstr_guid(riid), out); + + if (IsEqualGUID(clsid, &CLSID_MFSourceReader)) + { + return create_source_reader_from_url(url, attributes, &IID_IMFSourceReader, out); + } + + FIXME("Unsupported %s.\n", debugstr_guid(clsid));
return E_NOTIMPL; } diff --git a/dlls/mfreadwrite/mfreadwrite.spec b/dlls/mfreadwrite/mfreadwrite.spec index d8ed6942eb..3a215a9cc6 100644 --- a/dlls/mfreadwrite/mfreadwrite.spec +++ b/dlls/mfreadwrite/mfreadwrite.spec @@ -6,4 +6,4 @@ @ stub MFCreateSinkWriterFromURL @ stdcall MFCreateSourceReaderFromByteStream(ptr ptr ptr) @ stdcall MFCreateSourceReaderFromMediaSource(ptr ptr ptr) -@ stub MFCreateSourceReaderFromURL +@ stdcall MFCreateSourceReaderFromURL(wstr ptr ptr) diff --git a/include/mfreadwrite.idl b/include/mfreadwrite.idl index 82f67d499c..264712778f 100644 --- a/include/mfreadwrite.idl +++ b/include/mfreadwrite.idl @@ -151,3 +151,4 @@ cpp_quote( "HRESULT WINAPI MFCreateSourceReaderFromByteStream(IMFByteStream *str cpp_quote( " IMFSourceReader **reader);" ) cpp_quote( "HRESULT WINAPI MFCreateSourceReaderFromMediaSource(IMFMediaSource *source, IMFAttributes *attributes," ) cpp_quote( " IMFSourceReader **reader);" ) +cpp_quote( "HRESULT WINAPI MFCreateSourceReaderFromURL(const WCHAR *url, IMFAttributes *attributes, IMFSourceReader **reader);" )