Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 87 ++++++++++++++++++++++++++++++++- dlls/mfreadwrite/tests/mfplat.c | 3 +- 2 files changed, 88 insertions(+), 2 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index df8f89a9d0..86a92b0e6a 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -74,6 +74,7 @@ HRESULT WINAPI DllUnregisterServer(void) typedef struct source_reader { IMFSourceReader IMFSourceReader_iface; + IMFAsyncCallback source_events_callback; LONG refcount; IMFMediaSource *source; IMFPresentationDescriptor *descriptor; @@ -90,11 +91,88 @@ static inline srcreader *impl_from_IMFSourceReader(IMFSourceReader *iface) return CONTAINING_RECORD(iface, srcreader, IMFSourceReader_iface); }
+static struct source_reader *impl_from_source_callback_IMFAsyncCallback(IMFAsyncCallback *iface) +{ + return CONTAINING_RECORD(iface, struct source_reader, source_events_callback); +} + static inline struct sink_writer *impl_from_IMFSinkWriter(IMFSinkWriter *iface) { return CONTAINING_RECORD(iface, struct sink_writer, IMFSinkWriter_iface); }
+static HRESULT WINAPI source_reader_source_events_callback_QueryInterface(IMFAsyncCallback *iface, + REFIID riid, void **obj) +{ + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualIID(riid, &IID_IMFAsyncCallback) || + IsEqualIID(riid, &IID_IUnknown)) + { + *obj = iface; + IMFAsyncCallback_AddRef(iface); + return S_OK; + } + + WARN("Unsupported %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI source_reader_source_events_callback_AddRef(IMFAsyncCallback *iface) +{ + struct source_reader *reader = impl_from_source_callback_IMFAsyncCallback(iface); + return IMFSourceReader_AddRef(&reader->IMFSourceReader_iface); +} + +static ULONG WINAPI source_reader_source_events_callback_Release(IMFAsyncCallback *iface) +{ + struct source_reader *reader = impl_from_source_callback_IMFAsyncCallback(iface); + return IMFSourceReader_Release(&reader->IMFSourceReader_iface); +} + +static HRESULT WINAPI source_reader_source_events_callback_GetParameters(IMFAsyncCallback *iface, + DWORD *flags, DWORD *queue) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI source_reader_source_events_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) +{ + struct source_reader *reader = impl_from_source_callback_IMFAsyncCallback(iface); + MediaEventType event_type; + IMFMediaSource *source; + IMFMediaEvent *event; + HRESULT hr; + + TRACE("%p, %p.\n", iface, result); + + source = (IMFMediaSource *)IMFAsyncResult_GetStateNoAddRef(result); + + if (FAILED(hr = IMFMediaSource_EndGetEvent(source, result, &event))) + return hr; + + IMFMediaEvent_GetType(event, &event_type); + + TRACE("Got event %u.\n", event_type); + + IMFMediaEvent_Release(event); + + IMFMediaSource_BeginGetEvent(source, &reader->source_events_callback, + (IUnknown *)source); + + return S_OK; +} + +static const IMFAsyncCallbackVtbl source_events_callback_vtbl = +{ + source_reader_source_events_callback_QueryInterface, + source_reader_source_events_callback_AddRef, + source_reader_source_events_callback_Release, + source_reader_source_events_callback_GetParameters, + source_reader_source_events_callback_Invoke, +}; + static HRESULT WINAPI src_reader_QueryInterface(IMFSourceReader *iface, REFIID riid, void **out) { srcreader *This = impl_from_IMFSourceReader(iface); @@ -273,11 +351,12 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri srcreader *object; HRESULT hr;
- object = heap_alloc(sizeof(*object)); + object = heap_alloc_zero(sizeof(*object)); if (!object) return E_OUTOFMEMORY;
object->IMFSourceReader_iface.lpVtbl = &srcreader_vtbl; + object->source_events_callback.lpVtbl = &source_events_callback_vtbl; object->refcount = 1; object->source = source; IMFMediaSource_AddRef(object->source); @@ -285,6 +364,12 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri if (FAILED(hr = IMFMediaSource_CreatePresentationDescriptor(object->source, &object->descriptor))) goto failed;
+ if (FAILED(hr = IMFMediaSource_BeginGetEvent(object->source, &object->source_events_callback, + (IUnknown *)object->source))) + { + goto failed; + } + hr = IMFSourceReader_QueryInterface(&object->IMFSourceReader_iface, riid, out);
failed: diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 609510d427..5f664b354c 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -48,7 +48,7 @@ static void init_functions(void) static void test_MFCreateSourceReaderFromByteStream(void) { static const WCHAR audio[] = {'A','u','d','i','o',0}; - IMFSourceReader *source; + IMFSourceReader *source = NULL; IMFAttributes *attributes; IMFByteStream *bytestream = NULL; IStream *stream = NULL; @@ -76,6 +76,7 @@ static void test_MFCreateSourceReaderFromByteStream(void) ok(hr == S_OK, "got 0x%08x\n", hr);
hr = MFCreateSourceReaderFromByteStream(bytestream, attributes, &source); +todo_wine ok(hr == S_OK || hr == MF_E_UNSUPPORTED_BYTESTREAM_TYPE, "got 0x%08x\n", hr);
if(stream)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 86a92b0e6a..eca607574f 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -214,6 +214,7 @@ static ULONG WINAPI src_reader_Release(IMFSourceReader *iface)
if (!refcount) { + IMFMediaSource_Shutdown(reader->source); if (reader->descriptor) IMFPresentationDescriptor_Release(reader->descriptor); IMFMediaSource_Release(reader->source);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index eca607574f..88482f7b96 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -317,8 +317,7 @@ static HRESULT WINAPI src_reader_GetPresentationAttribute(IMFSourceReader *iface } else { - FIXME("Unsupported source attribute %s.\n", debugstr_guid(guid)); - return E_NOTIMPL; + return IMFPresentationDescriptor_GetItem(reader->descriptor, guid, value); } break; default:
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 88482f7b96..3dac3e4877 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -25,7 +25,6 @@
#include "windef.h" #include "winbase.h" -#include "initguid.h" #include "ole2.h" #include "rpcproxy.h"
@@ -288,9 +287,39 @@ static HRESULT WINAPI src_reader_Flush(IMFSourceReader *iface, DWORD index) static HRESULT WINAPI src_reader_GetServiceForStream(IMFSourceReader *iface, DWORD index, REFGUID service, REFIID riid, void **object) { - srcreader *This = impl_from_IMFSourceReader(iface); - FIXME("%p, 0x%08x, %s, %s, %p\n", This, index, debugstr_guid(service), debugstr_guid(riid), object); - return E_NOTIMPL; + struct source_reader *reader = impl_from_IMFSourceReader(iface); + IUnknown *obj = NULL; + HRESULT hr; + + TRACE("%p, %#x, %s, %s, %p\n", iface, index, debugstr_guid(service), debugstr_guid(riid), object); + + switch (index) + { + case MF_SOURCE_READER_MEDIASOURCE: + obj = (IUnknown *)reader->source; + break; + default: + FIXME("Unsupported index %#x.\n", index); + return E_NOTIMPL; + } + + if (IsEqualGUID(service, &GUID_NULL)) + { + hr = IUnknown_QueryInterface(obj, riid, object); + } + else + { + IMFGetService *gs; + + hr = IUnknown_QueryInterface(obj, &IID_IMFGetService, (void **)&gs); + if (SUCCEEDED(hr)) + { + hr = IMFGetService_GetService(gs, service, riid, object); + IMFGetService_Release(gs); + } + } + + return hr; }
static HRESULT WINAPI src_reader_GetPresentationAttribute(IMFSourceReader *iface, DWORD index,
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 48 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 3dac3e4877..2d6b7a088b 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -30,6 +30,8 @@
#undef INITGUID #include <guiddef.h> +#include "mfapi.h" +#include "mferror.h" #include "mfidl.h" #include "mfreadwrite.h"
@@ -77,6 +79,8 @@ typedef struct source_reader LONG refcount; IMFMediaSource *source; IMFPresentationDescriptor *descriptor; + DWORD first_audio_stream_index; + DWORD first_video_stream_index; } srcreader;
struct sink_writer @@ -374,6 +378,40 @@ struct IMFSourceReaderVtbl srcreader_vtbl = src_reader_GetPresentationAttribute };
+static DWORD reader_get_first_stream_index(IMFPresentationDescriptor *descriptor, const GUID *major) +{ + unsigned int count, i; + BOOL selected; + HRESULT hr; + GUID guid; + + if (FAILED(IMFPresentationDescriptor_GetStreamDescriptorCount(descriptor, &count))) + return MF_SOURCE_READER_INVALID_STREAM_INDEX; + + for (i = 0; i < count; ++i) + { + IMFMediaTypeHandler *handler; + IMFStreamDescriptor *sd; + + if (SUCCEEDED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(descriptor, i, &selected, &sd))) + { + hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &handler); + IMFStreamDescriptor_Release(sd); + if (SUCCEEDED(hr)) + { + hr = IMFMediaTypeHandler_GetMajorType(handler, &guid); + IMFMediaTypeHandler_Release(handler); + if (SUCCEEDED(hr) && IsEqualGUID(&guid, major)) + { + return i; + } + } + } + } + + return MF_SOURCE_READER_INVALID_STREAM_INDEX; +} + static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttributes *attributes, REFIID riid, void **out) { @@ -393,6 +431,16 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri if (FAILED(hr = IMFMediaSource_CreatePresentationDescriptor(object->source, &object->descriptor))) goto failed;
+ /* At least one major type has to be set. */ + object->first_audio_stream_index = reader_get_first_stream_index(object->descriptor, &MFMediaType_Audio); + object->first_video_stream_index = reader_get_first_stream_index(object->descriptor, &MFMediaType_Video); + + if (object->first_audio_stream_index == MF_SOURCE_READER_INVALID_STREAM_INDEX && + object->first_video_stream_index == MF_SOURCE_READER_INVALID_STREAM_INDEX) + { + hr = MF_E_ATTRIBUTENOTFOUND; + } + if (FAILED(hr = IMFMediaSource_BeginGetEvent(object->source, &object->source_events_callback, (IUnknown *)object->source))) {
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com ---
v2: fix descriptor reference leak. Thanks, Józef.
dlls/mfreadwrite/main.c | 68 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 6 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 2d6b7a088b..14c9dfae9c 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -229,16 +229,72 @@ static ULONG WINAPI src_reader_Release(IMFSourceReader *iface)
static HRESULT WINAPI src_reader_GetStreamSelection(IMFSourceReader *iface, DWORD index, BOOL *selected) { - srcreader *This = impl_from_IMFSourceReader(iface); - FIXME("%p, 0x%08x, %p\n", This, index, selected); - return E_NOTIMPL; + struct source_reader *reader = impl_from_IMFSourceReader(iface); + IMFStreamDescriptor *sd; + + TRACE("%p, %#x, %p.\n", iface, index, selected); + + switch (index) + { + case MF_SOURCE_READER_FIRST_VIDEO_STREAM: + index = reader->first_video_stream_index; + break; + case MF_SOURCE_READER_FIRST_AUDIO_STREAM: + index = reader->first_audio_stream_index; + break; + default: + ; + } + + if (FAILED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(reader->descriptor, index, selected, &sd))) + return MF_E_INVALIDSTREAMNUMBER; + IMFStreamDescriptor_Release(sd); + + return S_OK; }
static HRESULT WINAPI src_reader_SetStreamSelection(IMFSourceReader *iface, DWORD index, BOOL selected) { - srcreader *This = impl_from_IMFSourceReader(iface); - FIXME("%p, 0x%08x, %d\n", This, index, selected); - return E_NOTIMPL; + struct source_reader *reader = impl_from_IMFSourceReader(iface); + unsigned int count; + HRESULT hr; + + TRACE("%p, %#x, %d.\n", iface, index, selected); + + switch (index) + { + case MF_SOURCE_READER_FIRST_VIDEO_STREAM: + index = reader->first_video_stream_index; + break; + case MF_SOURCE_READER_FIRST_AUDIO_STREAM: + index = reader->first_audio_stream_index; + break; + case MF_SOURCE_READER_ALL_STREAMS: + if (FAILED(hr = IMFPresentationDescriptor_GetStreamDescriptorCount(reader->descriptor, &count))) + return hr; + + for (index = 0; index < count; ++index) + { + if (selected) + IMFPresentationDescriptor_SelectStream(reader->descriptor, index); + else + IMFPresentationDescriptor_DeselectStream(reader->descriptor, index); + } + + return S_OK; + default: + ; + } + + if (selected) + hr = IMFPresentationDescriptor_SelectStream(reader->descriptor, index); + else + hr = IMFPresentationDescriptor_DeselectStream(reader->descriptor, index); + + if (FAILED(hr)) + return MF_E_INVALIDSTREAMNUMBER; + + return S_OK; }
static HRESULT WINAPI src_reader_GetNativeMediaType(IMFSourceReader *iface, DWORD index, DWORD typeindex,
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com ---
v2: fix handler reference leak. Thanks, Józef.
dlls/mfreadwrite/main.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 14c9dfae9c..cbaad1619a 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -297,12 +297,44 @@ static HRESULT WINAPI src_reader_SetStreamSelection(IMFSourceReader *iface, DWOR return S_OK; }
-static HRESULT WINAPI src_reader_GetNativeMediaType(IMFSourceReader *iface, DWORD index, DWORD typeindex, +static HRESULT WINAPI src_reader_GetNativeMediaType(IMFSourceReader *iface, DWORD index, DWORD type_index, IMFMediaType **type) { - srcreader *This = impl_from_IMFSourceReader(iface); - FIXME("%p, 0x%08x, %d, %p\n", This, index, typeindex, type); - return E_NOTIMPL; + struct source_reader *reader = impl_from_IMFSourceReader(iface); + IMFMediaTypeHandler *handler; + IMFStreamDescriptor *sd; + BOOL selected; + HRESULT hr; + + TRACE("%p, %#x, %#x, %p.\n", iface, index, type_index, type); + + switch (index) + { + case MF_SOURCE_READER_FIRST_VIDEO_STREAM: + index = reader->first_video_stream_index; + break; + case MF_SOURCE_READER_FIRST_AUDIO_STREAM: + index = reader->first_audio_stream_index; + break; + default: + ; + } + + if (FAILED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(reader->descriptor, index, &selected, &sd))) + return MF_E_INVALIDSTREAMNUMBER; + + hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &handler); + IMFStreamDescriptor_Release(sd); + if (FAILED(hr)) + return hr; + + if (type_index == MF_SOURCE_READER_CURRENT_TYPE_INDEX) + hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, type); + else + hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, type_index, type); + IMFMediaTypeHandler_Release(handler); + + return hr; }
static HRESULT WINAPI src_reader_GetCurrentMediaType(IMFSourceReader *iface, DWORD index, IMFMediaType **type)