Skip to content

Commit ec71b52

Browse files
nsivovivyl
authored andcommitted
mfplat: Better handle source resolution when content type is not specified for the stream.
Signed-off-by: Nikolay Sivov <[email protected]> Signed-off-by: Alexandre Julliard <[email protected]> (cherry picked from commit 3a8bdf8)
1 parent 1b48a3e commit ec71b52

File tree

1 file changed

+154
-36
lines changed

1 file changed

+154
-36
lines changed

dlls/mfplat/main.c

Lines changed: 154 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6112,40 +6112,15 @@ static HRESULT resolver_create_registered_handler(HKEY hkey, REFIID riid, void *
61126112
return hr;
61136113
}
61146114

6115-
static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHAR *url, DWORD flags,
6116-
IMFByteStreamHandler **handler)
6115+
static HRESULT resolver_create_bytestream_handler(IMFByteStream *stream, DWORD flags, const WCHAR *mime,
6116+
const WCHAR *extension, IMFByteStreamHandler **handler)
61176117
{
61186118
static const HKEY hkey_roots[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE };
6119-
WCHAR *mimeW = NULL, *urlW = NULL;
6120-
IMFAttributes *attributes;
6121-
const WCHAR *url_ext;
61226119
HRESULT hr = E_FAIL;
61236120
unsigned int i, j;
6124-
UINT32 length;
61256121

61266122
*handler = NULL;
61276123

6128-
/* MIME type */
6129-
if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes)))
6130-
{
6131-
IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &mimeW, &length);
6132-
if (!url)
6133-
{
6134-
IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_ORIGIN_NAME, &urlW, &length);
6135-
url = urlW;
6136-
}
6137-
IMFAttributes_Release(attributes);
6138-
}
6139-
6140-
/* Extension */
6141-
url_ext = url ? wcsrchr(url, '.') : NULL;
6142-
6143-
if (!url_ext && !mimeW)
6144-
{
6145-
CoTaskMemFree(urlW);
6146-
return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6147-
}
6148-
61496124
if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS))
61506125
{
61516126
struct local_handler *local_handler;
@@ -6154,8 +6129,8 @@ static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHA
61546129

61556130
LIST_FOR_EACH_ENTRY(local_handler, &local_bytestream_handlers, struct local_handler, entry)
61566131
{
6157-
if ((mimeW && !lstrcmpiW(mimeW, local_handler->u.bytestream.mime))
6158-
|| (url_ext && !lstrcmpiW(url_ext, local_handler->u.bytestream.extension)))
6132+
if ((mime && !lstrcmpiW(mime, local_handler->u.bytestream.mime))
6133+
|| (extension && !lstrcmpiW(extension, local_handler->u.bytestream.extension)))
61596134
{
61606135
if (SUCCEEDED(hr = IMFActivate_ActivateObject(local_handler->activate, &IID_IMFByteStreamHandler,
61616136
(void **)handler)))
@@ -6166,16 +6141,12 @@ static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHA
61666141
LeaveCriticalSection(&local_handlers_section);
61676142

61686143
if (*handler)
6169-
{
6170-
CoTaskMemFree(mimeW);
6171-
CoTaskMemFree(urlW);
61726144
return hr;
6173-
}
61746145
}
61756146

61766147
for (i = 0, hr = E_FAIL; i < ARRAY_SIZE(hkey_roots); ++i)
61776148
{
6178-
const WCHAR *namesW[2] = { mimeW, url_ext };
6149+
const WCHAR *namesW[2] = { mime, extension };
61796150
HKEY hkey, hkey_handler;
61806151

61816152
if (RegOpenKeyW(hkey_roots[i], L"Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers", &hkey))
@@ -6202,14 +6173,161 @@ static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHA
62026173
break;
62036174
}
62046175

6176+
return hr;
6177+
}
6178+
6179+
static HRESULT resolver_get_bytestream_url_hint(IMFByteStream *stream, WCHAR const **url)
6180+
{
6181+
static const unsigned char asfmagic[] = {0x30,0x26,0xb2,0x75,0x8e,0x66,0xcf,0x11,0xa6,0xd9,0x00,0xaa,0x00,0x62,0xce,0x6c};
6182+
static const unsigned char wavmagic[] = { 'R', 'I', 'F', 'F',0x00,0x00,0x00,0x00, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' '};
6183+
static const unsigned char wavmask[] = {0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
6184+
static const unsigned char isommagic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'i', 's', 'o', 'm',0x00,0x00,0x00,0x00};
6185+
static const unsigned char mp4_magic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'M', 'S', 'N', 'V',0x00,0x00,0x00,0x00};
6186+
static const unsigned char mp42magic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'm', 'p', '4', '2',0x00,0x00,0x00,0x00};
6187+
static const unsigned char mp4vmagic[] = {0x00,0x00,0x00,0x00, 'f', 't', 'y', 'p', 'M', '4', 'V', ' ',0x00,0x00,0x00,0x00};
6188+
static const unsigned char mp4mask[] = {0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00};
6189+
static const struct stream_content_url_hint
6190+
{
6191+
const unsigned char *magic;
6192+
const WCHAR *url;
6193+
const unsigned char *mask;
6194+
}
6195+
url_hints[] =
6196+
{
6197+
{ asfmagic, L".asf" },
6198+
{ wavmagic, L".wav", wavmask },
6199+
{ isommagic, L".mp4", mp4mask },
6200+
{ mp42magic, L".mp4", mp4mask },
6201+
{ mp4_magic, L".mp4", mp4mask },
6202+
{ mp4vmagic, L".m4v", mp4mask },
6203+
};
6204+
unsigned char buffer[4 * sizeof(unsigned int)], pattern[4 * sizeof(unsigned int)];
6205+
IMFAttributes *attributes;
6206+
DWORD length = 0, caps = 0;
6207+
unsigned int i, j;
6208+
QWORD position;
6209+
HRESULT hr;
6210+
6211+
*url = NULL;
6212+
6213+
if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes)))
6214+
{
6215+
UINT32 string_length = 0;
6216+
IMFAttributes_GetStringLength(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &string_length);
6217+
IMFAttributes_Release(attributes);
6218+
6219+
if (string_length)
6220+
return S_OK;
6221+
}
6222+
6223+
if (FAILED(hr = IMFByteStream_GetCapabilities(stream, &caps)))
6224+
return hr;
6225+
6226+
if (!(caps & MFBYTESTREAM_IS_SEEKABLE))
6227+
return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6228+
6229+
if (FAILED(hr = IMFByteStream_GetCurrentPosition(stream, &position)))
6230+
return hr;
6231+
6232+
hr = IMFByteStream_Read(stream, buffer, sizeof(buffer), &length);
6233+
IMFByteStream_SetCurrentPosition(stream, position);
62056234
if (FAILED(hr))
6235+
return hr;
6236+
6237+
if (length < sizeof(buffer))
6238+
return S_OK;
6239+
6240+
for (i = 0; i < ARRAY_SIZE(url_hints); ++i)
6241+
{
6242+
memcpy(pattern, buffer, sizeof(buffer));
6243+
if (url_hints[i].mask)
6244+
{
6245+
unsigned int *mask = (unsigned int *)url_hints[i].mask;
6246+
unsigned int *data = (unsigned int *)pattern;
6247+
6248+
for (j = 0; j < sizeof(buffer) / sizeof(unsigned int); ++j)
6249+
data[j] &= mask[j];
6250+
6251+
}
6252+
if (!memcmp(pattern, url_hints[i].magic, sizeof(pattern)))
6253+
{
6254+
*url = url_hints[i].url;
6255+
break;
6256+
}
6257+
}
6258+
6259+
if (*url)
6260+
TRACE("Content type guessed as %s from %s.\n", debugstr_w(*url), debugstr_an((char *)buffer, length));
6261+
else
6262+
WARN("Unrecognized content type %s.\n", debugstr_an((char *)buffer, length));
6263+
6264+
return S_OK;
6265+
}
6266+
6267+
static HRESULT resolver_create_gstreamer_handler(IMFByteStreamHandler **handler)
6268+
{
6269+
static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}};
6270+
return CoCreateInstance(&CLSID_GStreamerByteStreamHandler, NULL, CLSCTX_INPROC_SERVER, &IID_IMFByteStreamHandler, (void **)handler);
6271+
}
6272+
6273+
static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHAR *url, DWORD flags,
6274+
IMFByteStreamHandler **handler)
6275+
{
6276+
WCHAR *mimeW = NULL, *urlW = NULL;
6277+
IMFAttributes *attributes;
6278+
const WCHAR *url_ext;
6279+
HRESULT hr = E_FAIL;
6280+
UINT32 length;
6281+
6282+
*handler = NULL;
6283+
6284+
/* MIME type */
6285+
if (SUCCEEDED(IMFByteStream_QueryInterface(stream, &IID_IMFAttributes, (void **)&attributes)))
62066286
{
6207-
static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}};
6208-
hr = CoCreateInstance(&CLSID_GStreamerByteStreamHandler, NULL, CLSCTX_INPROC_SERVER, &IID_IMFByteStreamHandler, (void **)handler);
6287+
IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_CONTENT_TYPE, &mimeW, &length);
6288+
if (!url)
6289+
{
6290+
IMFAttributes_GetAllocatedString(attributes, &MF_BYTESTREAM_ORIGIN_NAME, &urlW, &length);
6291+
url = urlW;
6292+
}
6293+
IMFAttributes_Release(attributes);
6294+
}
6295+
6296+
/* Extension */
6297+
url_ext = url ? wcsrchr(url, '.') : NULL;
6298+
6299+
/* If content type was provided by the caller, it's tried first. Otherwise an attempt to deduce
6300+
content type from the content itself is made.
6301+
6302+
TODO: wine specific fallback to predefined handler could be replaced by normally registering
6303+
this handler for all possible types.
6304+
*/
6305+
6306+
if (url_ext || mimeW)
6307+
{
6308+
hr = resolver_create_bytestream_handler(stream, flags, mimeW, url_ext, handler);
6309+
6310+
if (FAILED(hr))
6311+
hr = resolver_create_gstreamer_handler(handler);
62096312
}
62106313

62116314
CoTaskMemFree(mimeW);
62126315
CoTaskMemFree(urlW);
6316+
6317+
if (SUCCEEDED(hr))
6318+
return hr;
6319+
6320+
if (!(flags & MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE))
6321+
return MF_E_UNSUPPORTED_BYTESTREAM_TYPE;
6322+
6323+
if (FAILED(hr = resolver_get_bytestream_url_hint(stream, &url_ext)))
6324+
return hr;
6325+
6326+
hr = resolver_create_bytestream_handler(stream, flags, NULL, url_ext, handler);
6327+
6328+
if (FAILED(hr))
6329+
hr = resolver_create_gstreamer_handler(handler);
6330+
62136331
return hr;
62146332
}
62156333

0 commit comments

Comments
 (0)