Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 2 -- dlls/mfplat/main.c | 1 - dlls/mfplat/mediatype.c | 2 -- dlls/mfplat/queue.c | 6 ------ dlls/mfplat/sample.c | 1 - 5 files changed, 12 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index f161bb29d80..e9990f85853 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -26,8 +26,6 @@ #include "d3d9.h" #include "evr.h"
-#include "wine/debug.h" - WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
#define ALIGN_SIZE(size, alignment) (((size) + (alignment)) & ~((alignment))) diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index e79f59d41dd..7e2527fc024 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -36,7 +36,6 @@ #include "d3d11.h" #include "uuids.h"
-#include "wine/debug.h" #include "wine/list.h"
#include "mfplat_private.h" diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c index 41dbda572d5..41758390289 100644 --- a/dlls/mfplat/mediatype.c +++ b/dlls/mfplat/mediatype.c @@ -25,8 +25,6 @@ #include "ks.h" #include "ksmedia.h"
-#include "wine/debug.h" - WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
DEFINE_MEDIATYPE_GUID(MFVideoFormat_IMC1, MAKEFOURCC('I','M','C','1')); diff --git a/dlls/mfplat/queue.c b/dlls/mfplat/queue.c index 8279929b46e..42bceb5811d 100644 --- a/dlls/mfplat/queue.c +++ b/dlls/mfplat/queue.c @@ -16,13 +16,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#include <stdarg.h> - #define COBJMACROS -#define NONAMELESSUNION - -#include "wine/debug.h" -#include "wine/list.h"
#include "mfplat_private.h" #include "rtworkq.h" diff --git a/dlls/mfplat/sample.c b/dlls/mfplat/sample.c index 04c68c87199..099db498f2d 100644 --- a/dlls/mfplat/sample.c +++ b/dlls/mfplat/sample.c @@ -25,7 +25,6 @@ #include "initguid.h" #include "dxva2api.h"
-#include "wine/debug.h" #include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/Makefile.in | 3 +- dlls/mfplat/main.c | 66 +++++++++++++++++++++++++++++++++-------- dlls/mfplat/mfplat.spec | 2 +- include/mfapi.h | 2 ++ 4 files changed, 58 insertions(+), 15 deletions(-)
diff --git a/dlls/mfplat/Makefile.in b/dlls/mfplat/Makefile.in index 79af7650de6..f4ef8e5649c 100644 --- a/dlls/mfplat/Makefile.in +++ b/dlls/mfplat/Makefile.in @@ -1,7 +1,8 @@ EXTRADEFS = -DWINE_NO_LONG_TYPES MODULE = mfplat.dll IMPORTLIB = mfplat -IMPORTS = advapi32 ole32 mfuuid propsys rtworkq +IMPORTS = advapi32 ole32 mfuuid propsys rtworkq kernelbase +DELAYIMPORTS = bcrypt
EXTRADLLFLAGS = -Wb,--prefer-native
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 7e2527fc024..7a1f10dac24 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -52,6 +52,9 @@ #include "initguid.h" #include "mfd3d12.h"
+#include "bcrypt.h" +#include "pathcch.h" + WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
struct local_handler @@ -4576,11 +4579,8 @@ static const IMFGetServiceVtbl bytestream_file_getservice_vtbl = bytestream_file_getservice_GetService, };
-/*********************************************************************** - * MFCreateFile (mfplat.@) - */ -HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags, - LPCWSTR url, IMFByteStream **bytestream) +static HRESULT create_file_bytestream(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags, + const WCHAR *path, BOOL is_tempfile, IMFByteStream **bytestream) { DWORD capabilities = MFBYTESTREAM_IS_SEEKABLE | MFBYTESTREAM_DOES_NOT_USE_NETWORK; DWORD filecreation_disposition = 0, fileaccessmode = 0, fileattributes = 0; @@ -4590,8 +4590,6 @@ HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE open HANDLE file; HRESULT hr;
- TRACE("%d, %d, %#x, %s, %p.\n", accessmode, openmode, flags, debugstr_w(url), bytestream); - switch (accessmode) { case MF_ACCESSMODE_READ: @@ -4630,12 +4628,12 @@ HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE open
if (flags & MF_FILEFLAGS_NOBUFFERING) fileattributes |= FILE_FLAG_NO_BUFFERING; + if (is_tempfile) + fileattributes |= FILE_FLAG_DELETE_ON_CLOSE;
/* Open HANDLE to file */ - file = CreateFileW(url, fileaccessmode, filesharemode, NULL, - filecreation_disposition, fileattributes, 0); - - if(file == INVALID_HANDLE_VALUE) + file = CreateFileW(path, fileaccessmode, filesharemode, NULL, filecreation_disposition, fileattributes, 0); + if (file == INVALID_HANDLE_VALUE) return HRESULT_FROM_WIN32(GetLastError());
if (!(object = calloc(1, sizeof(*object)))) @@ -4660,19 +4658,61 @@ HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE open object->capabilities = capabilities; object->hfile = file;
- if (GetFileTime(file, NULL, NULL, &writetime)) + if (!is_tempfile && GetFileTime(file, NULL, NULL, &writetime)) { IMFAttributes_SetBlob(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_LAST_MODIFIED_TIME, (const UINT8 *)&writetime, sizeof(writetime)); }
- IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME, url); + IMFAttributes_SetString(&object->attributes.IMFAttributes_iface, &MF_BYTESTREAM_ORIGIN_NAME, path);
*bytestream = &object->IMFByteStream_iface;
return S_OK; }
+/*********************************************************************** + * MFCreateFile (mfplat.@) + */ +HRESULT WINAPI MFCreateFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags, + const WCHAR *path, IMFByteStream **bytestream) +{ + TRACE("%d, %d, %#x, %s, %p.\n", accessmode, openmode, flags, debugstr_w(path), bytestream); + + return create_file_bytestream(accessmode, openmode, flags, path, FALSE, bytestream); +} + +/*********************************************************************** + * MFCreateTempFile (mfplat.@) + */ +HRESULT WINAPI MFCreateTempFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags, + IMFByteStream **bytestream) +{ + WCHAR name[24], tmppath[MAX_PATH], *path; + ULONG64 rnd; + size_t len; + HRESULT hr; + + TRACE("%d, %d, %#x, %p.\n", accessmode, openmode, flags, bytestream); + + BCryptGenRandom(NULL, (UCHAR *)&rnd, sizeof(rnd), BCRYPT_USE_SYSTEM_PREFERRED_RNG); + swprintf(name, ARRAY_SIZE(name), L"MFP%llX.TMP", rnd); + GetTempPathW(ARRAY_SIZE(tmppath), tmppath); + + len = wcslen(tmppath) + wcslen(name) + 2; + if (!(path = malloc(len * sizeof(*path)))) + return E_OUTOFMEMORY; + + wcscpy(path, tmppath); + PathCchAppend(path, len, name); + + hr = create_file_bytestream(accessmode, openmode, flags, path, TRUE, bytestream); + + free(path); + + return hr; +} + struct bytestream_wrapper { IMFByteStreamCacheControl IMFByteStreamCacheControl_iface; diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index 57f4e3c0d6c..5d177732fa8 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -71,7 +71,7 @@ @ stdcall MFCreateStreamDescriptor(long long ptr ptr) @ stdcall MFCreateSystemTimeSource(ptr) @ stub MFCreateSystemUnderlyingClock -@ stub MFCreateTempFile +@ stdcall MFCreateTempFile(long long long ptr) @ stdcall MFCreateTrackedSample(ptr) @ stdcall MFCreateTransformActivate(ptr) @ stub MFCreateURLFromPath diff --git a/include/mfapi.h b/include/mfapi.h index d4493501624..105613693c9 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -533,6 +533,8 @@ HRESULT WINAPI MFCreateMediaEvent(MediaEventType type, REFGUID extended_type, HR HRESULT WINAPI MFCreateMediaType(IMFMediaType **type); HRESULT WINAPI MFCreateMFVideoFormatFromMFMediaType(IMFMediaType *media_type, MFVIDEOFORMAT **video_format, UINT32 *size); HRESULT WINAPI MFCreateSample(IMFSample **sample); +HRESULT WINAPI MFCreateTempFile(MF_FILE_ACCESSMODE accessmode, MF_FILE_OPENMODE openmode, MF_FILE_FLAGS flags, + IMFByteStream **bytestream); HRESULT WINAPI MFCreateVideoMediaTypeFromSubtype(const GUID *subtype, IMFVideoMediaType **media_type); HRESULT WINAPI MFCreateVideoSampleAllocatorEx(REFIID riid, void **allocator); HRESULT WINAPI MFCreateMemoryBuffer(DWORD max_length, IMFMediaBuffer **buffer);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/main.c | 190 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 154 insertions(+), 36 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 7a1f10dac24..72dd0915447 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -6159,40 +6159,15 @@ static HRESULT resolver_create_registered_handler(HKEY hkey, REFIID riid, void * return hr; }
-static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHAR *url, DWORD flags, - IMFByteStreamHandler **handler) +static HRESULT resolver_create_bytestream_handler(IMFByteStream *stream, DWORD flags, const WCHAR *mime, + const WCHAR *extension, IMFByteStreamHandler **handler) { static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE }; - WCHAR *mimeW = NULL, *urlW = NULL; - IMFAttributes *attributes; - const WCHAR *url_ext; HRESULT hr = E_FAIL; unsigned int i, j; - UINT32 length;
*handler = NULL;
- /* MIME type */ - if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes))) - { - IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &mimeW, &length); - if (!url) - { - IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_ORIGIN_NAME, &urlW, &length); - url = urlW; - } - IMFAttributes_Release(attributes); - } - - /* Extension */ - url_ext = url ? wcsrchr(url, '.') : NULL; - - if (!url_ext && !mimeW) - { - CoTaskMemFree(urlW); - return MF_E_UNSUPPORTED_BYTESTREAM_TYPE; - } - if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS)) { struct local_handler *local_handler; @@ -6201,8 +6176,8 @@ static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHA
LIST_FOR_EACH_ENTRY(local_handler, &local_bytestream_handlers, struct local_handler, entry) { - if ((mimeW && !lstrcmpiW(mimeW, local_handler->u.bytestream.mime)) - || (url_ext && !lstrcmpiW(url_ext, local_handler->u.bytestream.extension))) + if ((mime && !lstrcmpiW(mime, local_handler->u.bytestream.mime)) + || (extension && !lstrcmpiW(extension, local_handler->u.bytestream.extension))) { if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFByteStreamHandler, (void **)handler))) @@ -6213,16 +6188,12 @@ static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHA LeaveCriticalSection(&local_handlers_section);
if (*handler) - { - CoTaskMemFree(mimeW); - CoTaskMemFree(urlW); return hr; - } }
for (i = 0, hr = E_FAIL; i < ARRAY_SIZE(hkey_roots); ++i) { - const WCHAR *namesW[2] = { mimeW, url_ext }; + const WCHAR *namesW[2] = { mime, extension }; HKEY hkey, hkey_handler;
if (RegOpenKeyW(hkey_roots[i], L"Software\Microsoft\Windows Media Foundation\ByteStreamHandlers", &hkey)) @@ -6249,14 +6220,161 @@ static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHA break; }
+ return hr; +} + +static HRESULT resolver_get_bytestream_url_hint(IMFByteStream *stream, WCHAR const **url) +{ + static const unsigned char asfmagic[] = {0x30,0x26,0xb2,0x75,0x8e,0x66,0xcf,0x11,0xa6,0xd9,0x00,0xaa,0x00,0x62,0xce,0x6c}; + static const unsigned char wavmagic[] = { 'R', 'I', 'F', 'F',0x00,0x00,0x00,0x00, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' '}; + static const unsigned char wavmask[] = {0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; + static const unsigned char isommagic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'i', 's', 'o', 'm',0x00,0x00,0x00,0x00}; + static const unsigned char mp4_magic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'M', 'S', 'N', 'V',0x00,0x00,0x00,0x00}; + static const unsigned char mp42magic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'm', 'p', '4', '2',0x00,0x00,0x00,0x00}; + static const unsigned char mp4vmagic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'M', '4', 'V', ' ',0x00,0x00,0x00,0x00}; + static const unsigned char mp4mask[] = {0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00}; + static const struct stream_content_url_hint + { + const unsigned char *magic; + const WCHAR *url; + const unsigned char *mask; + } + url_hints[] = + { + { asfmagic, L".asf" }, + { wavmagic, L".wav", wavmask }, + { isommagic, L".mp4", mp4mask }, + { mp42magic, L".mp4", mp4mask }, + { mp4_magic, L".mp4", mp4mask }, + { mp4vmagic, L".m4v", mp4mask }, + }; + unsigned char buffer[4 * sizeof(unsigned int)], pattern[4 * sizeof(unsigned int)]; + IMFAttributes *attributes; + DWORD length = 0, caps = 0; + unsigned int i, j; + QWORD position; + HRESULT hr; + + *url = NULL; + + if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes))) + { + UINT32 string_length = 0; + IMFAttributes_GetStringLength(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &string_length); + IMFAttributes_Release(attributes); + + if (string_length) + return S_OK; + } + + if (FAILED(hr = IMFByteStream_GetCapabilities(stream, &caps))) + return hr; + + if (!(caps & MFBYTESTREAM_IS_SEEKABLE)) + return MF_E_UNSUPPORTED_BYTESTREAM_TYPE; + + if (FAILED(hr = IMFByteStream_GetCurrentPosition(stream, &position))) + return hr; + + hr = IMFByteStream_Read(stream, buffer, sizeof(buffer), &length); + IMFByteStream_SetCurrentPosition(stream, position); if (FAILED(hr)) + return hr; + + if (length < sizeof(buffer)) + return S_OK; + + for (i = 0; i < ARRAY_SIZE(url_hints); ++i) + { + memcpy(pattern, buffer, sizeof(buffer)); + if (url_hints[i].mask) + { + unsigned int *mask = (unsigned int *)url_hints[i].mask; + unsigned int *data = (unsigned int *)pattern; + + for (j = 0; j < sizeof(buffer) / sizeof(unsigned int); ++j) + data[j] &= mask[j]; + + } + if (!memcmp(pattern, url_hints[i].magic, sizeof(pattern))) + { + *url = url_hints[i].url; + break; + } + } + + if (*url) + TRACE("Content type guessed as %s from %s.\n", debugstr_w(*url), debugstr_an((char *)buffer, length)); + else + WARN("Unrecognized content type %s.\n", debugstr_an((char *)buffer, length)); + + return S_OK; +} + +static HRESULT resolver_create_gstreamer_handler(IMFByteStreamHandler **handler) +{ + static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}}; + return CoCreateInstance(&CLSID_GStreamerByteStreamHandler, NULL, CLSCTX_INPROC_SERVER, &IID_IMFByteStreamHandler, (void **)handler); +} + +static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHAR *url, DWORD flags, + IMFByteStreamHandler **handler) +{ + WCHAR *mimeW = NULL, *urlW = NULL; + IMFAttributes *attributes; + const WCHAR *url_ext; + HRESULT hr = E_FAIL; + UINT32 length; + + *handler = NULL; + + /* MIME type */ + if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes))) { - static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}}; - hr = CoCreateInstance(&CLSID_GStreamerByteStreamHandler, NULL, CLSCTX_INPROC_SERVER, &IID_IMFByteStreamHandler, (void **)handler); + IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &mimeW, &length); + if (!url) + { + IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_ORIGIN_NAME, &urlW, &length); + url = urlW; + } + IMFAttributes_Release(attributes); + } + + /* Extension */ + url_ext = url ? wcsrchr(url, '.') : NULL; + + /* If content type was provided by the caller, it's tried first. Otherwise an attempt to deduce + content type from the content itself is made. + + TODO: wine specific fallback to predefined handler could be replaced by normally registering + this handler for all possible types. + */ + + if (url_ext || mimeW) + { + hr = resolver_create_bytestream_handler(stream, flags, mimeW, url_ext, handler); + + if (FAILED(hr)) + hr = resolver_create_gstreamer_handler(handler); }
CoTaskMemFree(mimeW); CoTaskMemFree(urlW); + + if (SUCCEEDED(hr)) + return hr; + + if (!(flags & MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE)) + return MF_E_UNSUPPORTED_BYTESTREAM_TYPE; + + if (FAILED(hr = resolver_get_bytestream_url_hint(stream, &url_ext))) + return hr; + + hr = resolver_create_bytestream_handler(stream, flags, NULL, url_ext, handler); + + if (FAILED(hr)) + hr = resolver_create_gstreamer_handler(handler); + return hr; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplay/player.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/dlls/mfplay/player.c b/dlls/mfplay/player.c index d7ec7085def..01438060dbd 100644 --- a/dlls/mfplay/player.c +++ b/dlls/mfplay/player.c @@ -1047,8 +1047,8 @@ static HRESULT media_player_create_item_from_url(struct media_player *player, { *ret = NULL;
- if (SUCCEEDED(hr = IMFSourceResolver_CreateObjectFromURL(player->resolver, url, MF_RESOLUTION_MEDIASOURCE, - player->propstore, &obj_type, &object))) + if (SUCCEEDED(hr = IMFSourceResolver_CreateObjectFromURL(player->resolver, url, MF_RESOLUTION_MEDIASOURCE + | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE, player->propstore, &obj_type, &object))) { hr = media_item_set_source(item, object); IUnknown_Release(object); @@ -1066,8 +1066,9 @@ static HRESULT media_player_create_item_from_url(struct media_player *player, { if (ret) *ret = NULL;
- hr = IMFSourceResolver_BeginCreateObjectFromURL(player->resolver, url, MF_RESOLUTION_MEDIASOURCE, - player->propstore, NULL, &player->resolver_callback, (IUnknown *)&item->IMFPMediaItem_iface); + hr = IMFSourceResolver_BeginCreateObjectFromURL(player->resolver, url, MF_RESOLUTION_MEDIASOURCE + | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE, player->propstore, NULL, + &player->resolver_callback, (IUnknown *)&item->IMFPMediaItem_iface);
IMFPMediaItem_Release(&item->IMFPMediaItem_iface); } @@ -1123,8 +1124,8 @@ static HRESULT media_player_create_item_from_object(struct media_player *player, if (sync) { if (stream) - hr = IMFSourceResolver_CreateObjectFromByteStream(player->resolver, stream, NULL, - MF_RESOLUTION_MEDIASOURCE, player->propstore, &obj_type, &object); + hr = IMFSourceResolver_CreateObjectFromByteStream(player->resolver, stream, NULL, MF_RESOLUTION_MEDIASOURCE + | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE, player->propstore, &obj_type, &object); else IUnknown_AddRef(object);
@@ -1145,8 +1146,9 @@ static HRESULT media_player_create_item_from_object(struct media_player *player, { if (stream) { - hr = IMFSourceResolver_BeginCreateObjectFromByteStream(player->resolver, stream, NULL, MF_RESOLUTION_MEDIASOURCE, - player->propstore, NULL, &player->resolver_callback, (IUnknown *)&item->IMFPMediaItem_iface); + hr = IMFSourceResolver_BeginCreateObjectFromByteStream(player->resolver, stream, NULL, MF_RESOLUTION_MEDIASOURCE + | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE, player->propstore, NULL, + &player->resolver_callback, (IUnknown *)&item->IMFPMediaItem_iface); } else {
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfmediaengine/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/mfmediaengine/main.c b/dlls/mfmediaengine/main.c index fb8b4b8e9ae..5bfb35efbac 100644 --- a/dlls/mfmediaengine/main.c +++ b/dlls/mfmediaengine/main.c @@ -1435,7 +1435,7 @@ static HRESULT media_engine_set_source(struct media_engine *engine, IMFByteStrea
if (url || bytestream) { - flags = MF_RESOLUTION_MEDIASOURCE; + flags = MF_RESOLUTION_MEDIASOURCE | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE; if (engine->flags & MF_MEDIA_ENGINE_DISABLE_LOCAL_PLUGINS) flags |= MF_RESOLUTION_DISABLE_LOCAL_PLUGINS;
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/reader.c | 97 +-------------------------------- dlls/mfreadwrite/tests/mfplat.c | 5 +- 2 files changed, 3 insertions(+), 99 deletions(-)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index 8ba00e86ff6..6d35a59f3a8 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -2390,94 +2390,6 @@ failed: return hr; }
-static HRESULT bytestream_get_url_hint(IMFByteStream *stream, WCHAR const **url) -{ - static const unsigned char asfmagic[] = {0x30,0x26,0xb2,0x75,0x8e,0x66,0xcf,0x11,0xa6,0xd9,0x00,0xaa,0x00,0x62,0xce,0x6c}; - static const unsigned char wavmagic[] = { 'R', 'I', 'F', 'F',0x00,0x00,0x00,0x00, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' '}; - static const unsigned char wavmask[] = {0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; - static const unsigned char isommagic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'i', 's', 'o', 'm',0x00,0x00,0x00,0x00}; - static const unsigned char mp4_magic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'M', 'S', 'N', 'V',0x00,0x00,0x00,0x00}; - static const unsigned char mp42magic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'm', 'p', '4', '2',0x00,0x00,0x00,0x00}; - static const unsigned char mp4vmagic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'M', '4', 'V', ' ',0x00,0x00,0x00,0x00}; - static const unsigned char mp4mask[] = {0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00}; - static const struct stream_content_url_hint - { - const unsigned char *magic; - const WCHAR *url; - const unsigned char *mask; - } - url_hints[] = - { - { asfmagic, L".asf" }, - { wavmagic, L".wav", wavmask }, - { isommagic, L".mp4", mp4mask }, - { mp42magic, L".mp4", mp4mask }, - { mp4_magic, L".mp4", mp4mask }, - { mp4vmagic, L".m4v", mp4mask }, - }; - unsigned char buffer[4 * sizeof(unsigned int)], pattern[4 * sizeof(unsigned int)]; - IMFAttributes *attributes; - DWORD length = 0, caps = 0; - unsigned int i, j; - QWORD position; - HRESULT hr; - - *url = NULL; - - if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes))) - { - UINT32 string_length = 0; - IMFAttributes_GetStringLength(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &string_length); - IMFAttributes_Release(attributes); - - if (string_length) - return S_OK; - } - - if (FAILED(hr = IMFByteStream_GetCapabilities(stream, &caps))) - return hr; - - if (!(caps & MFBYTESTREAM_IS_SEEKABLE)) - return S_OK; - - if (FAILED(hr = IMFByteStream_GetCurrentPosition(stream, &position))) - return hr; - - hr = IMFByteStream_Read(stream, buffer, sizeof(buffer), &length); - IMFByteStream_SetCurrentPosition(stream, position); - if (FAILED(hr)) - return hr; - - if (length < sizeof(buffer)) - return S_OK; - - for (i = 0; i < ARRAY_SIZE(url_hints); ++i) - { - memcpy(pattern, buffer, sizeof(buffer)); - if (url_hints[i].mask) - { - unsigned int *mask = (unsigned int *)url_hints[i].mask; - unsigned int *data = (unsigned int *)pattern; - - for (j = 0; j < sizeof(buffer) / sizeof(unsigned int); ++j) - data[j] &= mask[j]; - - } - if (!memcmp(pattern, url_hints[i].magic, sizeof(pattern))) - { - *url = url_hints[i].url; - break; - } - } - - if (*url) - TRACE("Stream type guessed as %s from %s.\n", debugstr_w(*url), debugstr_an((char *)buffer, length)); - else - WARN("Unrecognized content type %s.\n", debugstr_an((char *)buffer, length)); - - return S_OK; -} - static HRESULT create_source_reader_from_stream(IMFByteStream *stream, IMFAttributes *attributes, REFIID riid, void **out) { @@ -2485,13 +2397,8 @@ static HRESULT create_source_reader_from_stream(IMFByteStream *stream, IMFAttrib IMFSourceResolver *resolver; MF_OBJECT_TYPE obj_type; IMFMediaSource *source; - const WCHAR *url; HRESULT hr;
- /* If stream does not have content type set, try to guess from starting byte sequence. */ - if (FAILED(hr = bytestream_get_url_hint(stream, &url))) - return hr; - if (FAILED(hr = MFCreateSourceResolver(&resolver))) return hr;
@@ -2499,8 +2406,8 @@ static HRESULT create_source_reader_from_stream(IMFByteStream *stream, IMFAttrib IMFAttributes_GetUnknown(attributes, &MF_SOURCE_READER_MEDIASOURCE_CONFIG, &IID_IPropertyStore, (void **)&props);
- hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, url, MF_RESOLUTION_MEDIASOURCE, props, - &obj_type, (IUnknown **)&source); + hr = IMFSourceResolver_CreateObjectFromByteStream(resolver, stream, NULL, MF_RESOLUTION_MEDIASOURCE + | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE, props, &obj_type, (IUnknown **)&source); IMFSourceResolver_Release(resolver); if (props) IPropertyStore_Release(props); diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 7e724344168..f484925b28a 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -877,13 +877,10 @@ skip_read_sample:
refcount = get_refcount(attributes); hr = MFCreateSourceReaderFromByteStream(stream, attributes, &reader); -todo_wine { ok(hr == S_OK, "Failed to create source reader, hr %#x.\n", hr); ok(get_refcount(attributes) > refcount, "Unexpected refcount.\n"); -} IMFAttributes_Release(attributes); - if (hr == S_OK) - IMFSourceReader_Release(reader); + IMFSourceReader_Release(reader);
IMFByteStream_Release(stream); }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/mediatype.c | 68 +++++++++++++++++++++++++++++++++++--- dlls/mfplat/mfplat.spec | 2 +- dlls/mfplat/tests/mfplat.c | 48 +++++++++++++++++++++++++++ include/mfapi.h | 1 + 4 files changed, 113 insertions(+), 6 deletions(-)
diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c index 41758390289..b77db17189f 100644 --- a/dlls/mfplat/mediatype.c +++ b/dlls/mfplat/mediatype.c @@ -3215,15 +3215,15 @@ HRESULT WINAPI MFConvertColorInfoToDXVA(DWORD *dxva_info, const MFVIDEOFORMAT *f
struct frame_rate { - UINT64 rate; - UINT64 frame_time; + UINT64 key; + UINT64 value; };
static int __cdecl frame_rate_compare(const void *a, const void *b) { - const UINT64 *rate = a; + const UINT64 *key = a; const struct frame_rate *known_rate = b; - return *rate == known_rate->rate ? 0 : ( *rate < known_rate->rate ? 1 : -1 ); + return *key == known_rate->key ? 0 : ( *key < known_rate->key ? 1 : -1 ); }
/*********************************************************************** @@ -3252,7 +3252,7 @@ HRESULT WINAPI MFFrameRateToAverageTimePerFrame(UINT32 numerator, UINT32 denomin if ((entry = bsearch(&rate, known_rates, ARRAY_SIZE(known_rates), sizeof(*known_rates), frame_rate_compare))) { - *avgframetime = entry->frame_time; + *avgframetime = entry->value; } else *avgframetime = numerator ? denominator * (UINT64)10000000 / numerator : 0; @@ -3260,6 +3260,64 @@ HRESULT WINAPI MFFrameRateToAverageTimePerFrame(UINT32 numerator, UINT32 denomin return S_OK; }
+static unsigned int get_gcd(unsigned int a, unsigned int b) +{ + unsigned int m; + + while (b) + { + m = a % b; + a = b; + b = m; + } + + return a; +} + +/*********************************************************************** + * MFAverageTimePerFrameToFrameRate (mfplat.@) + */ +HRESULT WINAPI MFAverageTimePerFrameToFrameRate(UINT64 avgtime, UINT32 *numerator, UINT32 *denominator) +{ + static const struct frame_rate known_rates[] = + { +#define KNOWN_RATE(ft,n,d) { ft, ((UINT64)n << 32) | d } + KNOWN_RATE(417188, 24000, 1001), + KNOWN_RATE(416667, 24, 1), + KNOWN_RATE(400000, 25, 1), + KNOWN_RATE(333667, 30000, 1001), + KNOWN_RATE(333333, 30, 1), + KNOWN_RATE(200000, 50, 1), + KNOWN_RATE(166833, 60000, 1001), + KNOWN_RATE(166667, 60, 1), +#undef KNOWN_RATE + }; + const struct frame_rate *entry; + unsigned int gcd; + + TRACE("%s, %p, %p.\n", wine_dbgstr_longlong(avgtime), numerator, denominator); + + if ((entry = bsearch(&avgtime, known_rates, ARRAY_SIZE(known_rates), sizeof(*known_rates), + frame_rate_compare))) + { + *numerator = entry->value >> 32; + *denominator = entry->value; + } + else if (avgtime) + { + if (avgtime > 100000000) avgtime = 100000000; + gcd = get_gcd(10000000, avgtime); + *numerator = 10000000 / gcd; + *denominator = avgtime / gcd; + } + else + { + *numerator = *denominator = 0; + } + + return S_OK; +} + /*********************************************************************** * MFMapDXGIFormatToDX9Format (mfplat.@) */ diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index 5d177732fa8..31c80f596c2 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -20,7 +20,7 @@ @ stdcall MFAllocateWorkQueue(ptr) @ stdcall MFAllocateWorkQueueEx(long ptr) rtworkq.RtwqAllocateWorkQueue @ stub MFAppendCollection -@ stub MFAverageTimePerFrameToFrameRate +@ stdcall MFAverageTimePerFrameToFrameRate(int64 ptr ptr) @ stdcall MFBeginCreateFile(long long long wstr ptr ptr ptr) @ stub MFBeginGetHostByName @ stdcall MFBeginRegisterWorkQueueWithMMCSS(long wstr long ptr ptr) diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index f89a5202d80..c70d8a9ca81 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -6399,6 +6399,53 @@ static void test_MFFrameRateToAverageTimePerFrame(void) } }
+static void test_MFAverageTimePerFrameToFrameRate(void) +{ + static const struct frame_rate_test + { + unsigned int numerator; + unsigned int denominator; + UINT64 avgtime; + } frame_rate_tests[] = + { + { 60000, 1001, 166833 }, + { 30000, 1001, 333667 }, + { 24000, 1001, 417188 }, + { 60, 1, 166667 }, + { 30, 1, 333333 }, + { 50, 1, 200000 }, + { 25, 1, 400000 }, + { 24, 1, 416667 }, + + { 1000000, 25641, 256410 }, + { 10000000, 83333, 83333 }, + { 1, 10, 100000000 }, + { 1, 10, 100000001 }, + { 1, 10, 200000000 }, + { 1, 1, 10000000 }, + { 1, 2, 20000000 }, + { 5, 1, 2000000 }, + { 10, 1, 1000000 }, + }; + unsigned int i, numerator, denominator; + HRESULT hr; + + numerator = denominator = 1; + hr = MFAverageTimePerFrameToFrameRate(0, &numerator, &denominator); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!numerator && !denominator, "Unexpected output %u/%u.\n", numerator, denominator); + + for (i = 0; i < ARRAY_SIZE(frame_rate_tests); ++i) + { + numerator = denominator = 12345; + hr = MFAverageTimePerFrameToFrameRate(frame_rate_tests[i].avgtime, &numerator, &denominator); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(numerator == frame_rate_tests[i].numerator && denominator == frame_rate_tests[i].denominator, + "%u: unexpected %u/%u, expected %u/%u.\n", i, numerator, denominator, frame_rate_tests[i].numerator, + frame_rate_tests[i].denominator); + } +} + static void test_MFMapDXGIFormatToDX9Format(void) { static const struct format_pair @@ -7874,6 +7921,7 @@ START_TEST(mfplat) test_MFCreateDXSurfaceBuffer(); test_MFCreateTrackedSample(); test_MFFrameRateToAverageTimePerFrame(); + test_MFAverageTimePerFrameToFrameRate(); test_MFMapDXGIFormatToDX9Format(); test_d3d11_surface_buffer(); test_d3d12_surface_buffer(); diff --git a/include/mfapi.h b/include/mfapi.h index 105613693c9..b4e4d095bb4 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -500,6 +500,7 @@ HRESULT WINAPI MFAddPeriodicCallback(MFPERIODICCALLBACK callback, IUnknown *cont HRESULT WINAPI MFAllocateSerialWorkQueue(DWORD target_queue, DWORD *queue); HRESULT WINAPI MFAllocateWorkQueue(DWORD *queue); HRESULT WINAPI MFAllocateWorkQueueEx(MFASYNC_WORKQUEUE_TYPE queue_type, DWORD *queue); +HRESULT WINAPI MFAverageTimePerFrameToFrameRate(UINT64 avgtime, UINT32 *numerator, UINT32 *denominator); HRESULT WINAPI MFBeginCreateFile(MF_FILE_ACCESSMODE access_mode, MF_FILE_OPENMODE open_mode, MF_FILE_FLAGS flags, const WCHAR *path, IMFAsyncCallback *callback, IUnknown *state, IUnknown **cancel_cookie); HRESULT WINAPI MFBeginRegisterWorkQueueWithMMCSS(DWORD queue, const WCHAR *usage_class, DWORD taskid,