@@ -6112,40 +6112,15 @@ static HRESULT resolver_create_registered_handler(HKEY hkey, REFIID riid, void *
6112
6112
return hr ;
6113
6113
}
6114
6114
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 )
6117
6117
{
6118
6118
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 ;
6122
6119
HRESULT hr = E_FAIL ;
6123
6120
unsigned int i , j ;
6124
- UINT32 length ;
6125
6121
6126
6122
* handler = NULL ;
6127
6123
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
-
6149
6124
if (!(flags & MF_RESOLUTION_DISABLE_LOCAL_PLUGINS ))
6150
6125
{
6151
6126
struct local_handler * local_handler ;
@@ -6154,8 +6129,8 @@ static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHA
6154
6129
6155
6130
LIST_FOR_EACH_ENTRY (local_handler , & local_bytestream_handlers , struct local_handler , entry )
6156
6131
{
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 )))
6159
6134
{
6160
6135
if (SUCCEEDED (hr = IMFActivate_ActivateObject (local_handler -> activate , & IID_IMFByteStreamHandler ,
6161
6136
(void * * )handler )))
@@ -6166,16 +6141,12 @@ static HRESULT resolver_get_bytestream_handler(IMFByteStream *stream, const WCHA
6166
6141
LeaveCriticalSection (& local_handlers_section );
6167
6142
6168
6143
if (* handler )
6169
- {
6170
- CoTaskMemFree (mimeW );
6171
- CoTaskMemFree (urlW );
6172
6144
return hr ;
6173
- }
6174
6145
}
6175
6146
6176
6147
for (i = 0 , hr = E_FAIL ; i < ARRAY_SIZE (hkey_roots ); ++ i )
6177
6148
{
6178
- const WCHAR * namesW [2 ] = { mimeW , url_ext };
6149
+ const WCHAR * namesW [2 ] = { mime , extension };
6179
6150
HKEY hkey , hkey_handler ;
6180
6151
6181
6152
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
6202
6173
break ;
6203
6174
}
6204
6175
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 );
6205
6234
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 )))
6206
6286
{
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 );
6209
6312
}
6210
6313
6211
6314
CoTaskMemFree (mimeW );
6212
6315
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
+
6213
6331
return hr ;
6214
6332
}
6215
6333
0 commit comments