From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/qasf/asfreader.c | 114 +++++++++++++++++++++++++++++++++++- dlls/qasf/tests/asfreader.c | 3 - 2 files changed, 111 insertions(+), 6 deletions(-)
diff --git a/dlls/qasf/asfreader.c b/dlls/qasf/asfreader.c index c38943ec247..29a3f578e7c 100644 --- a/dlls/qasf/asfreader.c +++ b/dlls/qasf/asfreader.c @@ -27,6 +27,12 @@
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
+struct asf_stream +{ + struct strmbase_source source; + DWORD index; +}; + struct asf_reader { struct strmbase_filter filter; @@ -37,8 +43,36 @@ struct asf_reader
IWMReaderCallback *callback; IWMReader *reader; + + LONG stream_count; + struct asf_stream streams[16]; };
+static inline struct asf_stream *impl_from_strmbase_pin(struct strmbase_pin *iface) +{ + return CONTAINING_RECORD(iface, struct asf_stream, source.pin); +} + +static HRESULT source_query_interface(struct strmbase_pin *iface, REFIID iid, void **out) +{ + struct asf_stream *stream = impl_from_strmbase_pin(iface); + + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) + || IsEqualGUID(iid, &IID_IPin)) + *out = &stream->source.pin.IPin_iface; + else + { + *out = NULL; + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + static inline struct asf_reader *impl_from_strmbase_filter(struct strmbase_filter *iface) { return CONTAINING_RECORD(iface, struct asf_reader, filter); @@ -46,12 +80,29 @@ static inline struct asf_reader *impl_from_strmbase_filter(struct strmbase_filte
static struct strmbase_pin *asf_reader_get_pin(struct strmbase_filter *iface, unsigned int index) { - return NULL; + struct asf_reader *filter = impl_from_strmbase_filter(iface); + struct strmbase_pin *pin; + + TRACE("iface %p, index %u.\n", iface, index); + + if (index >= InterlockedOr(&filter->stream_count, 0)) pin = NULL; + else pin = &filter->streams[index].source.pin; + + return pin; }
static void asf_reader_destroy(struct strmbase_filter *iface) { struct asf_reader *filter = impl_from_strmbase_filter(iface); + struct strmbase_source *source; + + while (filter->stream_count--) + { + source = &filter->streams[filter->stream_count].source; + if (source->pin.peer) IPin_Disconnect(source->pin.peer); + IPin_Disconnect(&source->pin.IPin_iface); + strmbase_source_cleanup(source); + }
free(filter->file_name); FreeMediaType(&filter->media_type); @@ -83,6 +134,21 @@ static const struct strmbase_filter_ops filter_ops = .filter_query_interface = asf_reader_query_interface, };
+static HRESULT WINAPI asf_reader_DecideBufferSize(struct strmbase_source *iface, + IMemAllocator *allocator, ALLOCATOR_PROPERTIES *req_props) +{ + FIXME("iface %p, allocator %p, req_props %p stub!\n", iface, allocator, req_props); + return E_NOTIMPL; +} + +static const struct strmbase_source_ops source_ops = +{ + .base.pin_query_interface = source_query_interface, + .pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator, + .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection, + .pfnDecideBufferSize = asf_reader_DecideBufferSize, +}; + static inline struct asf_reader *impl_from_IFileSourceFilter(IFileSourceFilter *iface) { return CONTAINING_RECORD(iface, struct asf_reader, IFileSourceFilter_iface); @@ -232,9 +298,49 @@ static ULONG WINAPI reader_callback_Release(IWMReaderCallback *iface) static HRESULT WINAPI reader_callback_OnStatus(IWMReaderCallback *iface, WMT_STATUS status, HRESULT hr, WMT_ATTR_DATATYPE type, BYTE *value, void *context) { - FIXME("iface %p, status %d, hr %#lx, type %d, value %p, context %p stub!\n", + struct asf_reader *filter = impl_from_IWMReaderCallback(iface)->filter; + DWORD i, stream_count; + WCHAR name[MAX_PATH]; + + TRACE("iface %p, status %d, hr %#lx, type %d, value %p, context %p.\n", iface, status, hr, type, value, context); - return E_NOTIMPL; + + switch (status) + { + case WMT_OPENED: + if (FAILED(hr)) + { + WARN("Failed to open WMReader, hr %#lx\n", hr); + break; + } + if (FAILED(hr = IWMReader_GetOutputCount(filter->reader, &stream_count))) + { + WARN("Failed to get WMReader output count, hr %#lx\n", hr); + break; + } + if (stream_count > ARRAY_SIZE(filter->streams)) + { + FIXME("Found %lu streams, not supported!\n", stream_count); + stream_count = ARRAY_SIZE(filter->streams); + } + + for (i = 0; i < stream_count; ++i) + { + struct asf_stream *stream = filter->streams + i; + swprintf(name, ARRAY_SIZE(name), L"Raw Stream %u", stream->index); + strmbase_source_init(&stream->source, &filter->filter, name, &source_ops); + } + + InterlockedExchange(&filter->stream_count, stream_count); + BaseFilterImpl_IncrementPinVersion(&filter->filter); + break; + + default: + WARN("Ignoring status %#x\n", status); + break; + } + + return S_OK; }
static HRESULT WINAPI reader_callback_OnSample(IWMReaderCallback *iface, DWORD output, QWORD time, @@ -273,6 +379,7 @@ HRESULT asf_reader_create(IUnknown *outer, IUnknown **out) { struct asf_reader *object; HRESULT hr; + int i;
if (!(object = calloc(1, sizeof(*object)))) return E_OUTOFMEMORY; @@ -289,6 +396,7 @@ HRESULT asf_reader_create(IUnknown *outer, IUnknown **out) return hr; }
+ for (i = 0; i < ARRAY_SIZE(object->streams); ++i) object->streams[i].index = i; strmbase_filter_init(&object->filter, outer, &CLSID_WMAsfReader, &filter_ops); object->IFileSourceFilter_iface.lpVtbl = &file_source_vtbl;
diff --git a/dlls/qasf/tests/asfreader.c b/dlls/qasf/tests/asfreader.c index a2b56ee29de..b3e605f0c22 100644 --- a/dlls/qasf/tests/asfreader.c +++ b/dlls/qasf/tests/asfreader.c @@ -499,9 +499,7 @@ static void test_filesourcefilter(void) ok(hr == S_OK, "Got hr %#lx.\n", hr);
hr = IEnumPins_Next(enumpins, 1, pins, NULL); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); - if (hr != S_OK) goto skip_pins; check_pin(pins[0], filter, PINDIR_OUTPUT, L"Raw Video 0", L"Raw Video 0", video_mt, ARRAY_SIZE(video_mt)); IPin_Release(pins[0]);
@@ -511,7 +509,6 @@ static void test_filesourcefilter(void) IPin_Release(pins[0]);
hr = IEnumPins_Next(enumpins, 1, pins, NULL); -skip_pins: ok(hr == S_FALSE, "Got hr %#lx.\n", hr); IEnumPins_Release(enumpins);