Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 78d96e4f8c..e41bdf6e9d 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -75,6 +75,7 @@ HRESULT WINAPI DllUnregisterServer(void) struct media_stream { IMFMediaType *current; + DWORD id; };
typedef struct source_reader @@ -644,6 +645,9 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri if (FAILED(hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(object->descriptor, i, &selected, &sd))) break;
+ if (FAILED(hr = IMFStreamDescriptor_GetStreamIdentifier(sd, &object->streams[i].id))) + WARN("Failed to get stream identifier, hr %#x.\n", hr); + hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &handler); IMFStreamDescriptor_Release(sd); if (FAILED(hr))
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/Makefile.in | 2 +- dlls/mfreadwrite/main.c | 142 ++++++++++++++++++++++++++++++++++- 2 files changed, 141 insertions(+), 3 deletions(-)
diff --git a/dlls/mfreadwrite/Makefile.in b/dlls/mfreadwrite/Makefile.in index edc7ebd07d..ce8a4d4602 100644 --- a/dlls/mfreadwrite/Makefile.in +++ b/dlls/mfreadwrite/Makefile.in @@ -1,6 +1,6 @@ MODULE = mfreadwrite.dll IMPORTLIB = mfreadwrite -IMPORTS = mfuuid uuid mfplat +IMPORTS = mfuuid uuid mfplat ole32
C_SRCS = \ main.c diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index e41bdf6e9d..e6ddce0a3c 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -74,6 +74,7 @@ HRESULT WINAPI DllUnregisterServer(void)
struct media_stream { + IMFMediaStream *stream; IMFMediaType *current; DWORD id; }; @@ -82,6 +83,7 @@ typedef struct source_reader { IMFSourceReader IMFSourceReader_iface; IMFAsyncCallback source_events_callback; + IMFAsyncCallback stream_events_callback; LONG refcount; IMFMediaSource *source; IMFPresentationDescriptor *descriptor; @@ -110,6 +112,11 @@ static struct source_reader *impl_from_source_callback_IMFAsyncCallback(IMFAsync return CONTAINING_RECORD(iface, struct source_reader, source_events_callback); }
+static struct source_reader *impl_from_stream_callback_IMFAsyncCallback(IMFAsyncCallback *iface) +{ + return CONTAINING_RECORD(iface, struct source_reader, stream_events_callback); +} + static inline struct sink_writer *impl_from_IMFSinkWriter(IMFSinkWriter *iface) { return CONTAINING_RECORD(iface, struct sink_writer, IMFSinkWriter_iface); @@ -151,6 +158,77 @@ static HRESULT WINAPI source_reader_source_events_callback_GetParameters(IMFAsyn return E_NOTIMPL; }
+static HRESULT source_reader_new_stream_handler(struct source_reader *reader, IMFMediaEvent *event) +{ + IMFStreamDescriptor *sd; + IMFMediaStream *stream; + PROPVARIANT value; + unsigned int i; + DWORD id = 0; + HRESULT hr; + + PropVariantInit(&value); + if (FAILED(hr = IMFMediaEvent_GetValue(event, &value))) + { + WARN("Failed to get event value, hr %#x.\n", hr); + return hr; + } + + if (value.vt != VT_UNKNOWN || !value.u.punkVal) + { + WARN("Unexpected value type %d.\n", value.vt); + PropVariantClear(&value); + return E_UNEXPECTED; + } + + hr = IUnknown_QueryInterface(value.u.punkVal, &IID_IMFMediaStream, (void **)&stream); + PropVariantClear(&value); + if (FAILED(hr)) + { + WARN("Unexpected object type.\n"); + return hr; + } + + TRACE("Got new stream %p.\n", stream); + + if (SUCCEEDED(hr = IMFMediaStream_GetStreamDescriptor(stream, &sd))) + { + hr = IMFStreamDescriptor_GetStreamIdentifier(sd, &id); + IMFStreamDescriptor_Release(sd); + } + + if (FAILED(hr)) + { + WARN("Unidentified stream %p, hr %#x.\n", stream, hr); + IMFMediaStream_Release(stream); + return hr; + } + + for (i = 0; i < reader->stream_count; ++i) + { + if (id == reader->streams[i].id) + { + if (!InterlockedCompareExchangePointer((void **)&reader->streams[i].stream, stream, NULL)) + { + IMFMediaStream_AddRef(reader->streams[i].stream); + if (FAILED(hr = IMFMediaStream_BeginGetEvent(stream, &reader->stream_events_callback, + (IUnknown *)stream))) + { + WARN("Failed to subscribe to stream events, hr %#x.\n", hr); + } + } + break; + } + } + + if (i == reader->stream_count) + WARN("Stream with id %#x was not present in presentation descriptor.\n", id); + + IMFMediaStream_Release(stream); + + return hr; +} + static HRESULT WINAPI source_reader_source_events_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) { struct source_reader *reader = impl_from_source_callback_IMFAsyncCallback(iface); @@ -170,10 +248,21 @@ static HRESULT WINAPI source_reader_source_events_callback_Invoke(IMFAsyncCallba
TRACE("Got event %u.\n", event_type);
+ switch (event_type) + { + case MENewStream: + hr = source_reader_new_stream_handler(reader, event); + break; + default: + ; + } + + if (FAILED(hr)) + WARN("Failed while handling %d event, hr %#x.\n", event_type, hr); + IMFMediaEvent_Release(event);
- IMFMediaSource_BeginGetEvent(source, &reader->source_events_callback, - (IUnknown *)source); + IMFMediaSource_BeginGetEvent(source, iface, (IUnknown *)source);
return S_OK; } @@ -187,6 +276,52 @@ static const IMFAsyncCallbackVtbl source_events_callback_vtbl = source_reader_source_events_callback_Invoke, };
+static ULONG WINAPI source_reader_stream_events_callback_AddRef(IMFAsyncCallback *iface) +{ + struct source_reader *reader = impl_from_stream_callback_IMFAsyncCallback(iface); + return IMFSourceReader_AddRef(&reader->IMFSourceReader_iface); +} + +static ULONG WINAPI source_reader_stream_events_callback_Release(IMFAsyncCallback *iface) +{ + struct source_reader *reader = impl_from_stream_callback_IMFAsyncCallback(iface); + return IMFSourceReader_Release(&reader->IMFSourceReader_iface); +} + +static HRESULT WINAPI source_reader_stream_events_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) +{ + MediaEventType event_type; + IMFMediaStream *stream; + IMFMediaEvent *event; + HRESULT hr; + + TRACE("%p, %p.\n", iface, result); + + stream = (IMFMediaStream *)IMFAsyncResult_GetStateNoAddRef(result); + + if (FAILED(hr = IMFMediaStream_EndGetEvent(stream, result, &event))) + return hr; + + IMFMediaEvent_GetType(event, &event_type); + + TRACE("Got event %u.\n", event_type); + + IMFMediaEvent_Release(event); + + IMFMediaStream_BeginGetEvent(stream, iface, (IUnknown *)stream); + + return S_OK; +} + +static const IMFAsyncCallbackVtbl stream_events_callback_vtbl = +{ + source_reader_source_events_callback_QueryInterface, + source_reader_stream_events_callback_AddRef, + source_reader_stream_events_callback_Release, + source_reader_source_events_callback_GetParameters, + source_reader_stream_events_callback_Invoke, +}; + static HRESULT WINAPI src_reader_QueryInterface(IMFSourceReader *iface, REFIID riid, void **out) { srcreader *This = impl_from_IMFSourceReader(iface); @@ -239,6 +374,8 @@ static ULONG WINAPI src_reader_Release(IMFSourceReader *iface)
for (i = 0; i < reader->stream_count; ++i) { + if (reader->streams[i].stream) + IMFMediaStream_Release(reader->streams[i].stream); if (reader->streams[i].current) IMFMediaType_Release(reader->streams[i].current); } @@ -614,6 +751,7 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri
object->IMFSourceReader_iface.lpVtbl = &srcreader_vtbl; object->source_events_callback.lpVtbl = &source_events_callback_vtbl; + object->stream_events_callback.lpVtbl = &stream_events_callback_vtbl; object->refcount = 1; object->source = source; IMFMediaSource_AddRef(object->source);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/tests/Makefile.in | 2 + dlls/mfreadwrite/tests/mfplat.c | 273 ++++++++++++++++++++++++++++- dlls/mfreadwrite/tests/resource.rc | 22 +++ dlls/mfreadwrite/tests/test.wav | Bin 0 -> 4488 bytes 4 files changed, 293 insertions(+), 4 deletions(-) create mode 100644 dlls/mfreadwrite/tests/resource.rc create mode 100644 dlls/mfreadwrite/tests/test.wav
diff --git a/dlls/mfreadwrite/tests/Makefile.in b/dlls/mfreadwrite/tests/Makefile.in index 5c906a138a..ae86fed95f 100644 --- a/dlls/mfreadwrite/tests/Makefile.in +++ b/dlls/mfreadwrite/tests/Makefile.in @@ -3,3 +3,5 @@ IMPORTS = ole32 mfplat mfreadwrite mfuuid
C_SRCS = \ mfplat.c + +RC_SRCS = resource.rc diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index c031ddc9bd..16fa8223bf 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -26,12 +26,19 @@ #include "winuser.h" #include "winreg.h"
+#include "initguid.h" +#include "ole2.h" + +DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + #undef INITGUID +#include "guiddef.h" #include "mfapi.h" #include "mfidl.h" #include "mferror.h" #include "mfreadwrite.h"
+#include "wine/heap.h" #include "wine/test.h"
static HRESULT (WINAPI *pMFCreateMFByteStreamOnStream)(IStream *stream, IMFByteStream **bytestream); @@ -45,10 +52,37 @@ static void init_functions(void) #undef X }
+static IMFByteStream *get_resource_stream(const char *name) +{ + IMFByteStream *bytestream; + IStream *stream; + DWORD written; + HRESULT hr; + HRSRC res; + void *ptr; + + res = FindResourceA(NULL, name, (const char *)RT_RCDATA); + ok(res != 0, "Resource %s wasn't found.\n", name); + + ptr = LockResource(LoadResource(GetModuleHandleA(NULL), res)); + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "Failed to create memory stream, hr %#x.\n", hr); + + hr = IStream_Write(stream, ptr, SizeofResource(GetModuleHandleA(NULL), res), &written); + ok(hr == S_OK, "Failed to write stream content, hr %#x.\n", hr); + + hr = pMFCreateMFByteStreamOnStream(stream, &bytestream); + ok(hr == S_OK, "Failed to create bytestream, hr %#x.\n", hr); + IStream_Release(stream); + + return bytestream; +} + static void test_MFCreateSourceReaderFromByteStream(void) { static const WCHAR audio[] = {'A','u','d','i','o',0}; - IMFSourceReader *source = NULL; + IMFSourceReader *reader = NULL; IMFAttributes *attributes; IMFByteStream *bytestream = NULL; IStream *stream = NULL; @@ -75,15 +109,15 @@ static void test_MFCreateSourceReaderFromByteStream(void) hr = pMFCreateMFByteStreamOnStream(stream, &bytestream); ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = MFCreateSourceReaderFromByteStream(bytestream, attributes, &source); + hr = MFCreateSourceReaderFromByteStream(bytestream, attributes, &reader); todo_wine ok(hr == S_OK || hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE, "got 0x%08x\n", hr);
IStream_Release(stream); IMFByteStream_Release(bytestream); IMFAttributes_Release(attributes); - if(source) - IMFSourceReader_Release(source); + if (reader) + IMFSourceReader_Release(reader); }
static void test_factory(void) @@ -106,6 +140,236 @@ static void test_factory(void) CoUninitialize(); }
+struct async_callback +{ + IMFSourceReaderCallback IMFSourceReaderCallback_iface; + LONG refcount; + HANDLE event; +}; + +static struct async_callback *impl_from_IMFSourceReaderCallback(IMFSourceReaderCallback *iface) +{ + return CONTAINING_RECORD(iface, struct async_callback, IMFSourceReaderCallback_iface); +} + +static HRESULT WINAPI async_callback_QueryInterface(IMFSourceReaderCallback *iface, REFIID riid, void **out) +{ + if (IsEqualIID(riid, &IID_IMFSourceReaderCallback) || + IsEqualIID(riid, &IID_IUnknown)) + { + *out = iface; + IMFSourceReaderCallback_AddRef(iface); + return S_OK; + } + + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI async_callback_AddRef(IMFSourceReaderCallback *iface) +{ + struct async_callback *callback = impl_from_IMFSourceReaderCallback(iface); + return InterlockedIncrement(&callback->refcount); +} + +static ULONG WINAPI async_callback_Release(IMFSourceReaderCallback *iface) +{ + struct async_callback *callback = impl_from_IMFSourceReaderCallback(iface); + ULONG refcount = InterlockedDecrement(&callback->refcount); + + if (!refcount) + { + heap_free(callback); + } + + return refcount; +} + +static HRESULT WINAPI async_callback_OnReadSample(IMFSourceReaderCallback *iface, HRESULT hr, DWORD stream_index, + DWORD stream_flags, LONGLONG timestamp, IMFSample *sample) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI async_callback_OnFlush(IMFSourceReaderCallback *iface, DWORD stream_index) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI async_callback_OnEvent(IMFSourceReaderCallback *iface, DWORD stream_index, IMFMediaEvent *event) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static const IMFSourceReaderCallbackVtbl async_callback_vtbl = +{ + async_callback_QueryInterface, + async_callback_AddRef, + async_callback_Release, + async_callback_OnReadSample, + async_callback_OnFlush, + async_callback_OnEvent, +}; + +static struct async_callback *create_async_callback(void) +{ + struct async_callback *callback; + + callback = heap_alloc(sizeof(*callback)); + callback->IMFSourceReaderCallback_iface.lpVtbl = &async_callback_vtbl; + callback->refcount = 1; + + return callback; +} + +static void test_source_reader(void) +{ + struct async_callback *callback; + IMFAttributes *attributes; + IMFMediaType *mediatype; + IMFSourceReader *reader; + IMFMediaSource *source; + IMFByteStream *stream; + BOOL selected; + HRESULT hr; + + if (!pMFCreateMFByteStreamOnStream) + return; + + stream = get_resource_stream("test.wav"); + + hr = MFCreateSourceReaderFromByteStream(stream, NULL, &reader); +todo_wine + ok(hr == S_OK, "Failed to create source reader, hr %#x.\n", hr); + + if (FAILED(hr)) + { + IMFByteStream_Release(stream); + return; + } + + /* Access underlying media source object. */ + hr = IMFSourceReader_GetServiceForStream(reader, MF_SOURCE_READER_MEDIASOURCE, &GUID_NULL, &IID_IMFMediaSource, + (void **)&source); + ok(hr == S_OK, "Failed to get media source interface, hr %#x.\n", hr); + IMFMediaSource_Release(source); + + /* Stream selection. */ + hr = IMFSourceReader_GetStreamSelection(reader, MF_SOURCE_READER_FIRST_VIDEO_STREAM, &selected); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFSourceReader_GetStreamSelection(reader, 100, &selected); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + selected = FALSE; + hr = IMFSourceReader_GetStreamSelection(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, &selected); + ok(hr == S_OK, "Failed to get stream selection, hr %#x.\n", hr); + ok(selected, "Unexpected selection.\n"); + + selected = FALSE; + hr = IMFSourceReader_GetStreamSelection(reader, 0, &selected); + ok(hr == S_OK, "Failed to get stream selection, hr %#x.\n", hr); + ok(selected, "Unexpected selection.\n"); + + hr = IMFSourceReader_SetStreamSelection(reader, MF_SOURCE_READER_FIRST_VIDEO_STREAM, TRUE); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFSourceReader_SetStreamSelection(reader, 100, TRUE); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFSourceReader_SetStreamSelection(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, FALSE); + ok(hr == S_OK, "Failed to deselect a stream, hr %#x.\n", hr); + + selected = TRUE; + hr = IMFSourceReader_GetStreamSelection(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, &selected); + ok(hr == S_OK, "Failed to get stream selection, hr %#x.\n", hr); + ok(!selected, "Unexpected selection.\n"); + + hr = IMFSourceReader_SetStreamSelection(reader, MF_SOURCE_READER_ALL_STREAMS, TRUE); + ok(hr == S_OK, "Failed to deselect a stream, hr %#x.\n", hr); + + selected = FALSE; + hr = IMFSourceReader_GetStreamSelection(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, &selected); + ok(hr == S_OK, "Failed to get stream selection, hr %#x.\n", hr); + ok(selected, "Unexpected selection.\n"); + + /* Native media type. */ + hr = IMFSourceReader_GetNativeMediaType(reader, MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, &mediatype); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFSourceReader_GetNativeMediaType(reader, 100, 0, &mediatype); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFSourceReader_GetNativeMediaType(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, &mediatype); + ok(hr == S_OK, "Failed to get native mediatype, hr %#x.\n", hr); + IMFMediaType_Release(mediatype); + + /* MF_SOURCE_READER_CURRENT_TYPE_INDEX is Win8+ */ + hr = IMFSourceReader_GetNativeMediaType(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, + MF_SOURCE_READER_CURRENT_TYPE_INDEX, &mediatype); + ok(hr == S_OK || broken(hr == MF_E_NO_MORE_TYPES), "Failed to get native mediatype, hr %#x.\n", hr); + if (SUCCEEDED(hr)) + IMFMediaType_Release(mediatype); + + hr = IMFSourceReader_GetNativeMediaType(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, 1, &mediatype); + ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr); + + /* Current media type. */ + hr = IMFSourceReader_GetCurrentMediaType(reader, MF_SOURCE_READER_FIRST_VIDEO_STREAM, &mediatype); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFSourceReader_GetCurrentMediaType(reader, 100, &mediatype); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFSourceReader_GetCurrentMediaType(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, &mediatype); + ok(hr == S_OK, "Failed to get current media type, hr %#x.\n", hr); + IMFMediaType_Release(mediatype); + + hr = IMFSourceReader_GetCurrentMediaType(reader, 0, &mediatype); + ok(hr == S_OK, "Failed to get current media type, hr %#x.\n", hr); + IMFMediaType_Release(mediatype); + + /* Flush. */ + hr = IMFSourceReader_Flush(reader, MF_SOURCE_READER_FIRST_VIDEO_STREAM); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFSourceReader_Flush(reader, 100); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + + hr = IMFSourceReader_Flush(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM); + ok(hr == S_OK, "Failed to flush stream, hr %#x.\n", hr); + + hr = IMFSourceReader_Flush(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM); + ok(hr == S_OK, "Failed to flush stream, hr %#x.\n", hr); + + hr = IMFSourceReader_Flush(reader, MF_SOURCE_READER_ALL_STREAMS); + ok(hr == S_OK, "Failed to flush all streams, hr %#x.\n", hr); + + IMFSourceReader_Release(reader); + + /* Async mode. */ + callback = create_async_callback(); + + hr = MFCreateAttributes(&attributes, 1); + ok(hr == S_OK, "Failed to create attributes object, hr %#x.\n", hr); + + hr = IMFAttributes_SetUnknown(attributes, &MF_SOURCE_READER_ASYNC_CALLBACK, + (IUnknown *)&callback->IMFSourceReaderCallback_iface); + ok(hr == S_OK, "Failed to set attribute value, hr %#x.\n", hr); + IMFSourceReaderCallback_Release(&callback->IMFSourceReaderCallback_iface); + + hr = MFCreateSourceReaderFromByteStream(stream, attributes, &reader); + ok(hr == S_OK, "Failed to create source reader, hr %#x.\n", hr); + IMFAttributes_Release(attributes); + + IMFSourceReader_Release(reader); + + IMFByteStream_Release(stream); +} + START_TEST(mfplat) { HRESULT hr; @@ -117,6 +381,7 @@ START_TEST(mfplat)
test_MFCreateSourceReaderFromByteStream(); test_factory(); + test_source_reader();
hr = MFShutdown(); ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); diff --git a/dlls/mfreadwrite/tests/resource.rc b/dlls/mfreadwrite/tests/resource.rc new file mode 100644 index 0000000000..f54212a8c8 --- /dev/null +++ b/dlls/mfreadwrite/tests/resource.rc @@ -0,0 +1,22 @@ +/* + * Copyright 2019 Nikolay Sivov for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "windef.h" + +/* @makedep: test.wav */ +test.wav RCDATA test.wav diff --git a/dlls/mfreadwrite/tests/test.wav b/dlls/mfreadwrite/tests/test.wav new file mode 100644 index 0000000000000000000000000000000000000000..51d23936196da1a0452c78713c8af819259d225e GIT binary patch literal 4488 zcmWIYbaQJEWMBw)40BD(Em06)U|?VbLYFlRV9dzC!QkT=93ll2_w;k~_Y8Im;RCXL z63fy|&GbwR^b8FQ8B!8U60LxyG&DA~w6?W(c6Imk^!D}jLqT6(Z%=nuXGeQmYjaa$ zeO*m;Rb_cuX-RQWQDFfL6c!d0mz0*3S5#Kl)YdmNHMg|2cYsVnGN`|=7h+OdYfE!u zLtSl6Rb>Ulq(Zn!AcH_ARa910*VfgKI%zbNM$^)0jvFnPMvKbP3T3p~9c`R|TVA8> dC3y36v{gCU_8#q_jCPtvyOyIJ@PQhp007ieqznK6
literal 0 HcmV?d00001
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index e6ddce0a3c..fd9062f648 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -839,23 +839,28 @@ failed: static HRESULT bytestream_get_url_hint(IMFByteStream *stream, WCHAR const **url) { static const UINT8 asfmagic[] = {0x30,0x26,0xb2,0x75,0x8e,0x66,0xcf,0x11,0xa6,0xd9,0x00,0xaa,0x00,0x62,0xce,0x6c}; + static const UINT8 wavmagic[] = { 'R', 'I', 'F', 'F',0x00,0x00,0x00,0x00, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' '}; + static const UINT8 wavmask[] = {0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; static const WCHAR asfW[] = {'.','a','s','f',0}; + static const WCHAR wavW[] = {'.','w','a','v',0}; static const struct stream_content_url_hint { const UINT8 *magic; UINT32 magic_len; const WCHAR *url; + const UINT8 *mask; } url_hints[] = { { asfmagic, sizeof(asfmagic), asfW }, + { wavmagic, sizeof(wavmagic), wavW, wavmask }, }; + UINT8 buffer[4 * sizeof(unsigned int)]; IMFAttributes *attributes; UINT32 length = 0; - UINT8 buffer[16]; + unsigned int i, j; DWORD caps = 0; QWORD position; - unsigned int i; HRESULT hr;
*url = NULL; @@ -888,6 +893,15 @@ static HRESULT bytestream_get_url_hint(IMFByteStream *stream, WCHAR const **url)
for (i = 0; i < ARRAY_SIZE(url_hints); ++i) { + if (url_hints[i].mask) + { + unsigned int *mask = (unsigned int *)url_hints[i].mask; + unsigned int *data = (unsigned int *)buffer; + + for (j = 0; j < sizeof(buffer) / sizeof(unsigned int); ++j) + data[j] &= mask[j]; + + } if (!memcmp(buffer, url_hints[i].magic, min(url_hints[i].magic_len, length))) { *url = url_hints[i].url;