Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 10 ++++++++-- dlls/mfreadwrite/tests/mfplat.c | 6 +++++- 2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 7625669ddb..d80e450c85 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -463,6 +463,7 @@ static HRESULT WINAPI src_reader_GetNativeMediaType(IMFSourceReader *iface, DWOR struct source_reader *reader = impl_from_IMFSourceReader(iface); IMFMediaTypeHandler *handler; IMFStreamDescriptor *sd; + IMFMediaType *src_type; BOOL selected; HRESULT hr;
@@ -489,11 +490,16 @@ static HRESULT WINAPI src_reader_GetNativeMediaType(IMFSourceReader *iface, DWOR return hr;
if (type_index == MF_SOURCE_READER_CURRENT_TYPE_INDEX) - hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, type); + hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &src_type); else - hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, type_index, type); + hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, type_index, &src_type); IMFMediaTypeHandler_Release(handler);
+ if (SUCCEEDED(hr = MFCreateMediaType(type))) + hr = IMFMediaType_CopyAllItems(src_type, (IMFAttributes *)*type); + + IMFMediaType_Release(src_type); + return hr; }
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 074c403e49..188e6889fe 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -186,9 +186,9 @@ static struct async_callback *create_async_callback(void)
static void test_source_reader(void) { + IMFMediaType *mediatype, *mediatype2; struct async_callback *callback; IMFAttributes *attributes; - IMFMediaType *mediatype; IMFSourceReader *reader; IMFMediaSource *source; IMFByteStream *stream; @@ -267,6 +267,10 @@ todo_wine
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); + hr = IMFSourceReader_GetNativeMediaType(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, &mediatype2); + ok(hr == S_OK, "Failed to get native mediatype, hr %#x.\n", hr); + ok(mediatype != mediatype2, "Unexpected media type instance.\n"); + IMFMediaType_Release(mediatype2); IMFMediaType_Release(mediatype);
/* MF_SOURCE_READER_CURRENT_TYPE_INDEX is Win8+ */
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 51 ++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 19 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index d80e450c85..bb9ad0fbfa 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -122,6 +122,36 @@ static inline struct sink_writer *impl_from_IMFSinkWriter(IMFSinkWriter *iface) return CONTAINING_RECORD(iface, struct sink_writer, IMFSinkWriter_iface); }
+static HRESULT media_event_get_object(IMFMediaEvent *event, REFIID riid, void **obj) +{ + PROPVARIANT value; + 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, riid, obj); + PropVariantClear(&value); + if (FAILED(hr)) + { + WARN("Unexpected object type.\n"); + return hr; + } + + return hr; +} + static HRESULT WINAPI source_reader_source_events_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj) { @@ -162,30 +192,13 @@ static HRESULT source_reader_new_stream_handler(struct source_reader *reader, IM { IMFStreamDescriptor *sd; IMFMediaStream *stream; - PROPVARIANT value; unsigned int i; DWORD id = 0; HRESULT hr;
- PropVariantInit(&value); - if (FAILED(hr = IMFMediaEvent_GetValue(event, &value))) + if (FAILED(hr = media_event_get_object(event, &IID_IMFMediaStream, (void **)&stream))) { - 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"); + WARN("Failed to get stream object, hr %#x.\n", hr); return hr; }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index bb9ad0fbfa..84db9aa600 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -152,6 +152,20 @@ static HRESULT media_event_get_object(IMFMediaEvent *event, REFIID riid, void ** return hr; }
+static HRESULT media_stream_get_id(IMFMediaStream *stream, DWORD *id) +{ + IMFStreamDescriptor *sd; + HRESULT hr; + + if (SUCCEEDED(hr = IMFMediaStream_GetStreamDescriptor(stream, &sd))) + { + hr = IMFStreamDescriptor_GetStreamIdentifier(sd, id); + IMFStreamDescriptor_Release(sd); + } + + return hr; +} + static HRESULT WINAPI source_reader_source_events_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj) { @@ -190,7 +204,6 @@ static HRESULT WINAPI source_reader_source_events_callback_GetParameters(IMFAsyn
static HRESULT source_reader_new_stream_handler(struct source_reader *reader, IMFMediaEvent *event) { - IMFStreamDescriptor *sd; IMFMediaStream *stream; unsigned int i; DWORD id = 0; @@ -204,13 +217,7 @@ static HRESULT source_reader_new_stream_handler(struct source_reader *reader, IM
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)) + if (FAILED(hr = media_stream_get_id(stream, &id))) { WARN("Unidentified stream %p, hr %#x.\n", stream, hr); IMFMediaStream_Release(stream);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/main.c | 99 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 95 insertions(+), 4 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 84db9aa600..43dfd4e9ed 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -37,6 +37,7 @@
#include "wine/debug.h" #include "wine/heap.h" +#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
@@ -72,11 +73,19 @@ HRESULT WINAPI DllUnregisterServer(void) return __wine_unregister_resources( mfinstance ); }
+struct sample +{ + struct list entry; + IMFSample *sample; +}; + struct media_stream { IMFMediaStream *stream; IMFMediaType *current; DWORD id; + CRITICAL_SECTION cs; + struct list samples; };
typedef struct source_reader @@ -308,8 +317,64 @@ static ULONG WINAPI source_reader_stream_events_callback_Release(IMFAsyncCallbac return IMFSourceReader_Release(&reader->IMFSourceReader_iface); }
+static HRESULT source_reader_media_sample_handler(struct source_reader *reader, IMFMediaStream *stream, + IMFMediaEvent *event) +{ + IMFSample *sample; + unsigned int i; + DWORD id = 0; + HRESULT hr; + + TRACE("Got new sample for stream %p.\n", stream); + + if (FAILED(hr = media_event_get_object(event, &IID_IMFSample, (void **)&sample))) + { + WARN("Failed to get sample object, hr %#x.\n", hr); + return hr; + } + + if (FAILED(hr = media_stream_get_id(stream, &id))) + { + WARN("Unidentified stream %p, hr %#x.\n", stream, hr); + IMFSample_Release(sample); + return hr; + } + + for (i = 0; i < reader->stream_count; ++i) + { + if (id == reader->streams[i].id) + { + struct sample *pending_sample; + + if (!(pending_sample = heap_alloc(sizeof(*pending_sample)))) + { + hr = E_OUTOFMEMORY; + goto failed; + } + + pending_sample->sample = sample; + IMFSample_AddRef(pending_sample->sample); + + EnterCriticalSection(&reader->streams[i].cs); + list_add_tail(&reader->streams[i].samples, &pending_sample->entry); + LeaveCriticalSection(&reader->streams[i].cs); + + break; + } + } + + if (i == reader->stream_count) + WARN("Stream with id %#x was not present in presentation descriptor.\n", id); + +failed: + IMFSample_Release(sample); + + return hr; +} + static HRESULT WINAPI source_reader_stream_events_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) { + struct source_reader *reader = impl_from_stream_callback_IMFAsyncCallback(iface); MediaEventType event_type; IMFMediaStream *stream; IMFMediaEvent *event; @@ -326,6 +391,18 @@ static HRESULT WINAPI source_reader_stream_events_callback_Invoke(IMFAsyncCallba
TRACE("Got event %u.\n", event_type);
+ switch (event_type) + { + case MEMediaSample: + hr = source_reader_media_sample_handler(reader, stream, event); + break; + default: + ; + } + + if (FAILED(hr)) + WARN("Failed while handling %d event, hr %#x.\n", event_type, hr); + IMFMediaEvent_Release(event);
IMFMediaStream_BeginGetEvent(stream, iface, (IUnknown *)stream); @@ -394,10 +471,21 @@ 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); + struct media_stream *stream = &reader->streams[i]; + struct sample *ptr, *next; + + if (stream->stream) + IMFMediaStream_Release(stream->stream); + if (stream->current) + IMFMediaType_Release(stream->current); + DeleteCriticalSection(&stream->cs); + + LIST_FOR_EACH_ENTRY_SAFE(ptr, next, &stream->samples, struct sample, entry) + { + IMFSample_Release(ptr->sample); + list_remove(&ptr->entry); + heap_free(ptr); + } } heap_free(reader->streams); DeleteCriticalSection(&reader->cs); @@ -832,6 +920,9 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri IMFMediaType_Release(src_type); if (FAILED(hr)) break; + + InitializeCriticalSection(&object->streams[i].cs); + list_init(&object->streams[i].samples); }
if (FAILED(hr))
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfreadwrite/tests/mfplat.c | 59 +++++++++++++++++++++++++++++++++ include/mfreadwrite.idl | 21 +++++++----- 2 files changed, 72 insertions(+), 8 deletions(-)
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 188e6889fe..29e8e08eb7 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -187,11 +187,14 @@ static struct async_callback *create_async_callback(void) static void test_source_reader(void) { IMFMediaType *mediatype, *mediatype2; + DWORD stream_flags, actual_index; struct async_callback *callback; IMFAttributes *attributes; IMFSourceReader *reader; IMFMediaSource *source; IMFByteStream *stream; + LONGLONG timestamp; + IMFSample *sample; BOOL selected; HRESULT hr;
@@ -298,6 +301,62 @@ todo_wine ok(hr == S_OK, "Failed to get current media type, hr %#x.\n", hr); IMFMediaType_Release(mediatype);
+ hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, &actual_index, &stream_flags, + ×tamp, &sample); + ok(hr == S_OK, "Failed to get a sample, hr %#x.\n", hr); + ok(actual_index == 0, "Unexpected stream index %u\n", actual_index); + ok(!stream_flags, "Unexpected stream flags %#x.\n", stream_flags); + IMFSample_Release(sample); + + /* There is no video stream. */ + hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, &actual_index, &stream_flags, + ×tamp, &sample); + ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); + ok(actual_index == MF_SOURCE_READER_FIRST_VIDEO_STREAM, "Unexpected stream index %u\n", actual_index); + ok(stream_flags == MF_SOURCE_READERF_ERROR, "Unexpected stream flags %#x.\n", stream_flags); + + hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, &actual_index, &stream_flags, + ×tamp, &sample); + ok(hr == S_OK, "Failed to get a sample, hr %#x.\n", hr); + ok(actual_index == 0, "Unexpected stream index %u\n", actual_index); + ok(stream_flags == MF_SOURCE_READERF_ENDOFSTREAM, "Unexpected stream flags %#x.\n", stream_flags); + ok(!sample, "Unexpected sample object.\n"); + + hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, MF_SOURCE_READER_CONTROLF_DRAIN, + &actual_index, &stream_flags, ×tamp, &sample); + ok(hr == S_OK, "Failed to get a sample, hr %#x.\n", hr); + ok(actual_index == 0, "Unexpected stream index %u\n", actual_index); + ok(stream_flags == MF_SOURCE_READERF_ENDOFSTREAM, "Unexpected stream flags %#x.\n", stream_flags); + ok(!sample, "Unexpected sample object.\n"); + + hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, MF_SOURCE_READER_CONTROLF_DRAIN, + &actual_index, &stream_flags, ×tamp, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, MF_SOURCE_READER_CONTROLF_DRAIN, + &actual_index, NULL, ×tamp, &sample); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, MF_SOURCE_READER_CONTROLF_DRAIN, + NULL, &stream_flags, ×tamp, &sample); + ok(hr == S_OK, "Failed to get a sample, hr %#x.\n", hr); + ok(stream_flags == MF_SOURCE_READERF_ENDOFSTREAM, "Unexpected stream flags %#x.\n", stream_flags); + ok(!sample, "Unexpected sample object.\n"); + + hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, MF_SOURCE_READER_CONTROLF_DRAIN, + &actual_index, &stream_flags, NULL, &sample); + ok(hr == S_OK, "Failed to get a sample, hr %#x.\n", hr); + ok(actual_index == 0, "Unexpected stream index %u\n", actual_index); + ok(stream_flags == MF_SOURCE_READERF_ENDOFSTREAM, "Unexpected stream flags %#x.\n", stream_flags); + ok(!sample, "Unexpected sample object.\n"); + + hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_ANY_STREAM, MF_SOURCE_READER_CONTROLF_DRAIN, + &actual_index, &stream_flags, NULL, &sample); + ok(hr == S_OK, "Failed to get a sample, hr %#x.\n", hr); + ok(actual_index == 0, "Unexpected stream index %u\n", actual_index); + ok(stream_flags == MF_SOURCE_READERF_ENDOFSTREAM, "Unexpected stream flags %#x.\n", stream_flags); + ok(!sample, "Unexpected sample object.\n"); + /* Flush. */ hr = IMFSourceReader_Flush(reader, MF_SOURCE_READER_FIRST_VIDEO_STREAM); ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr); diff --git a/include/mfreadwrite.idl b/include/mfreadwrite.idl index 0eea43b08b..ed09b74aae 100644 --- a/include/mfreadwrite.idl +++ b/include/mfreadwrite.idl @@ -19,6 +19,11 @@ import "mfobjects.idl"; import "mftransform.idl";
+typedef [v1_enum] enum MF_SOURCE_READER_CONTROL_FLAG +{ + MF_SOURCE_READER_CONTROLF_DRAIN = 0x00000001, +} MF_SOURCE_READER_CONTROL_FLAG; + enum { MF_SOURCE_READER_INVALID_STREAM_INDEX = 0xffffffff, @@ -30,15 +35,15 @@ enum MF_SOURCE_READER_CURRENT_TYPE_INDEX = 0xffffffff };
-typedef enum MF_SOURCE_READER_FLAG +typedef [v1_enum] enum MF_SOURCE_READER_FLAG { - MF_SOURCE_READERF_ERROR = 0x001, - MF_SOURCE_READERF_ENDOFSTREAM = 0x002, - MF_SOURCE_READERF_NEWSTREAM = 0x004, - MF_SOURCE_READERF_NATIVEMEDIATYPECHANGED = 0x010, - MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED = 0x020, - MF_SOURCE_READERF_STREAMTICK = 0x100, - MF_SOURCE_READERF_ALLEFFECTSREMOVED = 0x200 + MF_SOURCE_READERF_ERROR = 0x00000001, + MF_SOURCE_READERF_ENDOFSTREAM = 0x00000002, + MF_SOURCE_READERF_NEWSTREAM = 0x00000004, + MF_SOURCE_READERF_NATIVEMEDIATYPECHANGED = 0x00000010, + MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED = 0x00000020, + MF_SOURCE_READERF_STREAMTICK = 0x00000100, + MF_SOURCE_READERF_ALLEFFECTSREMOVED = 0x00000200, } MF_SOURCE_READER_FLAG;
typedef struct _MF_SINK_WRITER_STATISTICS