-- v3: qasf: Implement ASF Reader filter pin DecideBufferSize. qasf: Implement ASF Reader filter pin_query_accept. winegstreamer: Implement IWMOutputMediaProps_SetMediaType. qasf: Implement ASF Reader filter pin_get_media_type.
From: Rémi Bernon rbernon@codeweavers.com
And name pins accordingly.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/qasf/asfreader.c | 57 ++++++++++++++++++++++++++++++++++++- dlls/qasf/tests/asfreader.c | 4 +-- 2 files changed, 57 insertions(+), 4 deletions(-)
diff --git a/dlls/qasf/asfreader.c b/dlls/qasf/asfreader.c index 13b6e2d7bbe..98b506b66e6 100644 --- a/dlls/qasf/asfreader.c +++ b/dlls/qasf/asfreader.c @@ -48,6 +48,51 @@ struct asf_reader 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 inline struct asf_reader *asf_reader_from_asf_stream(struct asf_stream *stream) +{ + return CONTAINING_RECORD(stream, struct asf_reader, streams[stream->index]); +} + +static HRESULT asf_stream_get_media_type(struct strmbase_pin *iface, unsigned int index, AM_MEDIA_TYPE *media_type) +{ + struct asf_stream *stream = impl_from_strmbase_pin(iface); + struct asf_reader *filter = asf_reader_from_asf_stream(stream); + IWMOutputMediaProps *props; + AM_MEDIA_TYPE *mt; + DWORD size; + HRESULT hr; + + TRACE("iface %p, index %u, media_type %p.\n", iface, index, media_type); + + if (FAILED(IWMReader_GetOutputFormat(filter->reader, stream->index, index, &props))) + return VFW_S_NO_MORE_ITEMS; + + if (FAILED(hr = IWMOutputMediaProps_GetMediaType(props, NULL, &size))) + { + IWMOutputMediaProps_Release(props); + return hr; + } + + if (!(mt = malloc(size))) + { + IWMOutputMediaProps_Release(props); + return E_OUTOFMEMORY; + } + + hr = IWMOutputMediaProps_GetMediaType(props, (WM_MEDIA_TYPE *)mt, &size); + if (SUCCEEDED(hr)) + hr = CopyMediaType(media_type, mt); + free(mt); + + IWMOutputMediaProps_Release(props); + return hr; +} + static inline struct asf_reader *impl_from_strmbase_filter(struct strmbase_filter *iface) { return CONTAINING_RECORD(iface, struct asf_reader, filter); @@ -120,6 +165,7 @@ static HRESULT WINAPI asf_reader_DecideBufferSize(struct strmbase_source *iface,
static const struct strmbase_source_ops source_ops = { + .base.pin_get_media_type = asf_stream_get_media_type, .pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator, .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection, .pfnDecideBufferSize = asf_reader_DecideBufferSize, @@ -275,6 +321,7 @@ static HRESULT WINAPI reader_callback_OnStatus(IWMReaderCallback *iface, WMT_STA WMT_ATTR_DATATYPE type, BYTE *value, void *context) { struct asf_reader *filter = impl_from_IWMReaderCallback(iface)->filter; + AM_MEDIA_TYPE stream_media_type = {0}; DWORD i, stream_count; WCHAR name[MAX_PATH];
@@ -304,7 +351,15 @@ static HRESULT WINAPI reader_callback_OnStatus(IWMReaderCallback *iface, WMT_STA 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); + + if (FAILED(hr = asf_stream_get_media_type(&stream->source.pin, 0, &stream_media_type))) + WARN("Failed to get stream media type, hr %#lx.\n", hr); + if (IsEqualGUID(&stream_media_type.majortype, &MEDIATYPE_Video)) + swprintf(name, ARRAY_SIZE(name), L"Raw Video %u", stream->index); + else + swprintf(name, ARRAY_SIZE(name), L"Raw Audio %u", stream->index); + FreeMediaType(&stream_media_type); + strmbase_source_init(&stream->source, &filter->filter, name, &source_ops); } filter->stream_count = stream_count; diff --git a/dlls/qasf/tests/asfreader.c b/dlls/qasf/tests/asfreader.c index 494d0384ac8..ed78a856003 100644 --- a/dlls/qasf/tests/asfreader.c +++ b/dlls/qasf/tests/asfreader.c @@ -231,13 +231,11 @@ static void check_pin(IPin *pin, IBaseFilter *expect_filter, PIN_DIRECTION expec ok(hr == S_OK, "Got hr %#lx.\n", hr); ok(info.pFilter == expect_filter, "Got filter %p.\n", info.pFilter); ok(info.dir == expect_dir, "Got dir %#x.\n", info.dir); - todo_wine ok(!wcscmp(info.achName, expect_name), "Got name %s.\n", debugstr_w(info.achName)); IBaseFilter_Release(info.pFilter);
hr = IPin_QueryId(pin, &id); ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(!wcscmp(id, expect_id), "Got id %s.\n", debugstr_w(id)); CoTaskMemFree(id);
@@ -253,7 +251,7 @@ static void check_pin(IPin *pin, IBaseFilter *expect_filter, PIN_DIRECTION expec FreeMediaType(mt); CoTaskMemFree(mt); } - todo_wine + todo_wine_if(IsEqualGUID(&expect_mt[0].majortype, &MEDIATYPE_Video)) ok(i == expect_mt_count, "Got %u types.\n", i); ok(hr == S_FALSE, "Got hr %#lx.\n", hr); IEnumMediaTypes_Release(enum_mt);
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winegstreamer/wm_reader.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c index 03adea8a318..a235f2d15c6 100644 --- a/dlls/winegstreamer/wm_reader.c +++ b/dlls/winegstreamer/wm_reader.c @@ -116,8 +116,12 @@ static HRESULT WINAPI output_props_GetMediaType(IWMOutputMediaProps *iface, WM_M
static HRESULT WINAPI output_props_SetMediaType(IWMOutputMediaProps *iface, WM_MEDIA_TYPE *mt) { - FIXME("iface %p, mt %p, stub!\n", iface, mt); - return E_NOTIMPL; + const struct output_props *props = impl_from_IWMOutputMediaProps(iface); + + TRACE("iface %p, mt %p.\n", iface, mt); + + FreeMediaType((AM_MEDIA_TYPE *)&props->mt); + return CopyMediaType((AM_MEDIA_TYPE *)&props->mt, (AM_MEDIA_TYPE *)mt); }
static HRESULT WINAPI output_props_GetStreamGroupName(IWMOutputMediaProps *iface, WCHAR *name, WORD *len)
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/qasf/asfreader.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
diff --git a/dlls/qasf/asfreader.c b/dlls/qasf/asfreader.c index 98b506b66e6..33d94402aaf 100644 --- a/dlls/qasf/asfreader.c +++ b/dlls/qasf/asfreader.c @@ -93,6 +93,27 @@ static HRESULT asf_stream_get_media_type(struct strmbase_pin *iface, unsigned in return hr; }
+static HRESULT asf_stream_query_accept(struct strmbase_pin *iface, const AM_MEDIA_TYPE *media_type) +{ + struct asf_stream *stream = impl_from_strmbase_pin(iface); + struct asf_reader *filter = asf_reader_from_asf_stream(stream); + IWMOutputMediaProps *props; + HRESULT hr; + + TRACE("iface %p, media_type %p.\n", iface, media_type); + strmbase_dump_media_type(media_type); + + if (FAILED(IWMReader_GetOutputFormat(filter->reader, stream->index, 0, &props))) + return VFW_S_NO_MORE_ITEMS; + + hr = IWMOutputMediaProps_SetMediaType(props, (WM_MEDIA_TYPE *)media_type); + if (SUCCEEDED(hr)) + hr = IWMReader_SetOutputProps(filter->reader, stream->index, props); + + IWMOutputMediaProps_Release(props); + return hr; +} + static inline struct asf_reader *impl_from_strmbase_filter(struct strmbase_filter *iface) { return CONTAINING_RECORD(iface, struct asf_reader, filter); @@ -166,6 +187,7 @@ static HRESULT WINAPI asf_reader_DecideBufferSize(struct strmbase_source *iface, static const struct strmbase_source_ops source_ops = { .base.pin_get_media_type = asf_stream_get_media_type, + .base.pin_query_accept = asf_stream_query_accept, .pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator, .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection, .pfnDecideBufferSize = asf_reader_DecideBufferSize,
On 5/27/22 09:46, Rémi Bernon wrote:
+static HRESULT asf_stream_query_accept(struct strmbase_pin *iface, const AM_MEDIA_TYPE *media_type) +{
- struct asf_stream *stream = impl_from_strmbase_pin(iface);
- struct asf_reader *filter = asf_reader_from_asf_stream(stream);
- IWMOutputMediaProps *props;
- HRESULT hr;
- TRACE("iface %p, media_type %p.\n", iface, media_type);
- strmbase_dump_media_type(media_type);
- if (FAILED(IWMReader_GetOutputFormat(filter->reader, stream->index, 0, &props)))
return VFW_S_NO_MORE_ITEMS;
- hr = IWMOutputMediaProps_SetMediaType(props, (WM_MEDIA_TYPE *)media_type);
- if (SUCCEEDED(hr))
hr = IWMReader_SetOutputProps(filter->reader, stream->index, props);
- IWMOutputMediaProps_Release(props);
- return hr;
+}
This seems wrong; QueryAccept() isn't supposed to modify any state, and it can be called at any time.
Given that there's apparently no WM interface for this functionality I suspect that we'll have to implement it manually (after writing tests to find out what the correct functionality even is), if it's worth implementing. Which it may not be—calling QueryAccept() on the source pin isn't part of the usual connection process, and our fallback implementation returns S_OK anyway.
From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/qasf/asfreader.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/dlls/qasf/asfreader.c b/dlls/qasf/asfreader.c index 33d94402aaf..939a1848b85 100644 --- a/dlls/qasf/asfreader.c +++ b/dlls/qasf/asfreader.c @@ -180,8 +180,29 @@ static const struct strmbase_filter_ops filter_ops = 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; + struct asf_stream *stream = impl_from_strmbase_pin(&iface->pin); + unsigned int buffer_size = 16384; + ALLOCATOR_PROPERTIES ret_props; + + TRACE("iface %p, allocator %p, req_props %p.\n", iface, allocator, req_props); + + if (IsEqualGUID(&stream->source.pin.mt.formattype, &FORMAT_VideoInfo)) + { + VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)stream->source.pin.mt.pbFormat; + buffer_size = format->bmiHeader.biSizeImage; + } + else if (IsEqualGUID(&stream->source.pin.mt.formattype, &FORMAT_WaveFormatEx) + && (IsEqualGUID(&stream->source.pin.mt.subtype, &MEDIASUBTYPE_PCM) + || IsEqualGUID(&stream->source.pin.mt.subtype, &MEDIASUBTYPE_IEEE_FLOAT))) + { + WAVEFORMATEX *format = (WAVEFORMATEX *)stream->source.pin.mt.pbFormat; + buffer_size = format->nAvgBytesPerSec; + } + + req_props->cBuffers = max(req_props->cBuffers, 1); + req_props->cbBuffer = max(req_props->cbBuffer, buffer_size); + req_props->cbAlign = max(req_props->cbAlign, 1); + return IMemAllocator_SetProperties(allocator, req_props, &ret_props); }
static const struct strmbase_source_ops source_ops =
v3: Use `malloc` / `free` for the `WM_MEDIA_TYPE` buffer, `DeleteMediaType` would otherwise try to free invalid `pbFormat` pointer.