From: R��mi Bernon rbernon@codeweavers.com
--- dlls/qasf/asfreader.c | 49 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 7 deletions(-)
diff --git a/dlls/qasf/asfreader.c b/dlls/qasf/asfreader.c index 43a7a3534a8..f8114cdda26 100644 --- a/dlls/qasf/asfreader.c +++ b/dlls/qasf/asfreader.c @@ -41,6 +41,9 @@ struct asf_reader AM_MEDIA_TYPE media_type; WCHAR *file_name;
+ WMT_STATUS status; + CONDITION_VARIABLE status_cv; + IWMReaderCallback *callback; IWMReader *reader;
@@ -188,11 +191,27 @@ static HRESULT asf_reader_query_interface(struct strmbase_filter *iface, REFIID return E_NOINTERFACE; }
+static HRESULT asf_reader_wait_state(struct strmbase_filter *iface, DWORD timeout) +{ + struct asf_reader *filter = impl_from_strmbase_filter(iface); + DWORD time = GetTickCount(), end_time = time + timeout; + + while (filter->status == -1 && end_time - time <= timeout) + { + if (!SleepConditionVariableCS(&filter->status_cv, &filter->filter.filter_cs, end_time - time)) + break; + time = GetTickCount(); + } + + return filter->status == -1 ? VFW_S_STATE_INTERMEDIATE : S_OK; +} + static const struct strmbase_filter_ops filter_ops = { .filter_get_pin = asf_reader_get_pin, .filter_destroy = asf_reader_destroy, .filter_query_interface = asf_reader_query_interface, + .filter_wait_state = asf_reader_wait_state, };
static HRESULT WINAPI asf_reader_DecideBufferSize(struct strmbase_source *iface, @@ -269,17 +288,29 @@ static HRESULT WINAPI file_source_Load(IFileSourceFilter *iface, LPCOLESTR file_ if (!file_name) return E_POINTER;
- if (filter->file_name) - return E_FAIL; + EnterCriticalSection(&filter->filter.filter_cs);
- if (!(filter->file_name = wcsdup(file_name))) - return E_OUTOFMEMORY; + if (filter->file_name || !(filter->file_name = wcsdup(file_name))) + { + LeaveCriticalSection(&filter->filter.filter_cs); + return E_FAIL; + }
- if (media_type) - CopyMediaType(&filter->media_type, media_type); + if (media_type && FAILED(hr = CopyMediaType(&filter->media_type, media_type))) + { + LeaveCriticalSection(&filter->filter.filter_cs); + return hr; + }
if (FAILED(hr = IWMReader_Open(filter->reader, filter->file_name, filter->callback, NULL))) WARN("Failed to open WM reader, hr %#lx.\n", hr); + else + { + filter->status = -1; + asf_reader_wait_state(&filter->filter, INFINITE); + } + + LeaveCriticalSection(&filter->filter.filter_cs);
return S_OK; } @@ -424,9 +455,13 @@ static HRESULT WINAPI reader_callback_OnStatus(IWMReaderCallback *iface, WMT_STA strmbase_source_init(&stream->source, &filter->filter, name, &source_ops); } filter->stream_count = stream_count; - LeaveCriticalSection(&filter->filter.filter_cs); + + filter->status = WMT_OPENED; + WakeConditionVariable(&filter->status_cv);
BaseFilterImpl_IncrementPinVersion(&filter->filter); + + LeaveCriticalSection(&filter->filter.filter_cs); break;
default:
On 8/10/22 07:28, Rémi Bernon wrote:
+static HRESULT asf_reader_wait_state(struct strmbase_filter *iface, DWORD timeout) +{
- struct asf_reader *filter = impl_from_strmbase_filter(iface);
- DWORD time = GetTickCount(), end_time = time + timeout;
- while (filter->status == -1 && end_time - time <= timeout)
- {
if (!SleepConditionVariableCS(&filter->status_cv, &filter->filter.filter_cs, end_time - time))
break;
time = GetTickCount();
- }
- return filter->status == -1 ? VFW_S_STATE_INTERMEDIATE : S_OK;
+}
- static const struct strmbase_filter_ops filter_ops = { .filter_get_pin = asf_reader_get_pin, .filter_destroy = asf_reader_destroy, .filter_query_interface = asf_reader_query_interface,
- .filter_wait_state = asf_reader_wait_state, };
filter_wait_state() should not return VFW_S_STATE_INTERMEDIATE unless we are transitioning to another state asynchronously. IFileSourceFilter::Load() isn't a state transition, and it completes synchronously anyway.
(Note that in general we probably shouldn't be doing asynchronous state transitions from anything but a renderer, unless the tests say otherwise.)
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/qasf/asfreader.c | 48 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+)
diff --git a/dlls/qasf/asfreader.c b/dlls/qasf/asfreader.c index f8114cdda26..86f3c42454d 100644 --- a/dlls/qasf/asfreader.c +++ b/dlls/qasf/asfreader.c @@ -206,12 +206,60 @@ static HRESULT asf_reader_wait_state(struct strmbase_filter *iface, DWORD timeou return filter->status == -1 ? VFW_S_STATE_INTERMEDIATE : S_OK; }
+static HRESULT asf_reader_init_stream(struct strmbase_filter *iface) +{ + struct asf_reader *filter = impl_from_strmbase_filter(iface); + HRESULT hr; + int i; + + TRACE("iface %p\n", iface); + + for (i = 0; i < filter->stream_count; ++i) + { + struct asf_stream *stream = filter->streams + i; + + if (!stream->source.pin.peer) + continue; + + hr = IMemAllocator_Commit(stream->source.pAllocator); + if (FAILED(hr)) + { + WARN("Failed to commit stream %u allocator, hr %#lx\n", i, hr); + return hr; + } + } + + return S_OK; +} + +static HRESULT asf_reader_cleanup_stream(struct strmbase_filter *iface) +{ + struct asf_reader *filter = impl_from_strmbase_filter(iface); + int i; + + TRACE("iface %p\n", iface); + + for (i = 0; i < filter->stream_count; ++i) + { + struct asf_stream *stream = filter->streams + i; + + if (!stream->source.pin.peer) + continue; + + IMemAllocator_Decommit(stream->source.pAllocator); + } + + return S_OK; +} + static const struct strmbase_filter_ops filter_ops = { .filter_get_pin = asf_reader_get_pin, .filter_destroy = asf_reader_destroy, .filter_query_interface = asf_reader_query_interface, .filter_wait_state = asf_reader_wait_state, + .filter_init_stream = asf_reader_init_stream, + .filter_cleanup_stream = asf_reader_cleanup_stream, };
static HRESULT WINAPI asf_reader_DecideBufferSize(struct strmbase_source *iface,
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/qasf/asfreader.c | 65 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-)
diff --git a/dlls/qasf/asfreader.c b/dlls/qasf/asfreader.c index 86f3c42454d..cbb63e4a226 100644 --- a/dlls/qasf/asfreader.c +++ b/dlls/qasf/asfreader.c @@ -227,18 +227,41 @@ static HRESULT asf_reader_init_stream(struct strmbase_filter *iface) WARN("Failed to commit stream %u allocator, hr %#lx\n", i, hr); return hr; } + + hr = IPin_NewSegment(stream->source.pin.peer, 0, 0, 1); + if (FAILED(hr)) + { + WARN("Failed to start stream %u new segment, hr %#lx\n", i, hr); + return hr; + } }
- return S_OK; + filter->status = -1; + if (FAILED(hr = IWMReader_Start(filter->reader, 0, 0, 1, NULL))) + { + WARN("Failed to start WMReader %p, hr %#lx\n", filter->reader, hr); + filter->status = WMT_ERROR; + } + + return hr; }
static HRESULT asf_reader_cleanup_stream(struct strmbase_filter *iface) { struct asf_reader *filter = impl_from_strmbase_filter(iface); + HRESULT hr; int i;
TRACE("iface %p\n", iface);
+ filter->status = -1; + if (FAILED(hr = IWMReader_Stop(filter->reader))) + { + WARN("Failed to stop WMReader %p, hr %#lx\n", filter->reader, hr); + filter->status = WMT_ERROR; + return hr; + } + for (i = 0; i < filter->stream_count; ++i) { struct asf_stream *stream = filter->streams + i; @@ -512,6 +535,46 @@ static HRESULT WINAPI reader_callback_OnStatus(IWMReaderCallback *iface, WMT_STA LeaveCriticalSection(&filter->filter.filter_cs); break;
+ case WMT_END_OF_STREAMING: + EnterCriticalSection(&filter->filter.filter_cs); + for (i = 0; i < filter->stream_count; ++i) + { + struct asf_stream *stream = filter->streams + i; + + if (!stream->source.pin.peer) + continue; + + IPin_EndOfStream(stream->source.pin.peer); + } + LeaveCriticalSection(&filter->filter.filter_cs); + break; + + case WMT_STARTED: + if (FAILED(hr)) + { + ERR("Failed to start WMReader, hr %#lx.\n", hr); + break; + } + + EnterCriticalSection(&filter->filter.filter_cs); + filter->status = WMT_STARTED; + LeaveCriticalSection(&filter->filter.filter_cs); + WakeConditionVariable(&filter->status_cv); + break; + + case WMT_STOPPED: + if (FAILED(hr)) + { + ERR("Failed to stop WMReader, hr %#lx.\n", hr); + break; + } + + EnterCriticalSection(&filter->filter.filter_cs); + filter->status = WMT_STOPPED; + LeaveCriticalSection(&filter->filter.filter_cs); + WakeConditionVariable(&filter->status_cv); + break; + default: WARN("Ignoring status %#x.\n", status); break;
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/qasf/asfreader.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/dlls/qasf/asfreader.c b/dlls/qasf/asfreader.c index cbb63e4a226..dd8e8b282b3 100644 --- a/dlls/qasf/asfreader.c +++ b/dlls/qasf/asfreader.c @@ -217,6 +217,7 @@ static HRESULT asf_reader_init_stream(struct strmbase_filter *iface) for (i = 0; i < filter->stream_count; ++i) { struct asf_stream *stream = filter->streams + i; + IWMOutputMediaProps *props;
if (!stream->source.pin.peer) continue; @@ -228,6 +229,23 @@ static HRESULT asf_reader_init_stream(struct strmbase_filter *iface) return hr; }
+ hr = IWMReader_GetOutputFormat(filter->reader, stream->index, 0, &props); + if (FAILED(hr)) + { + WARN("Failed to get stream %u output format, hr %#lx\n", i, hr); + return hr; + } + + hr = IWMOutputMediaProps_SetMediaType(props, (WM_MEDIA_TYPE *)&stream->source.pin.mt); + if (SUCCEEDED(hr)) + hr = IWMReader_SetOutputProps(filter->reader, stream->index, props); + IWMOutputMediaProps_Release(props); + if (FAILED(hr)) + { + WARN("Failed to set stream %u output format, hr %#lx\n", i, hr); + return hr; + } + hr = IPin_NewSegment(stream->source.pin.peer, 0, 0, 1); if (FAILED(hr)) {
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/qasf/asfreader.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-)
diff --git a/dlls/qasf/asfreader.c b/dlls/qasf/asfreader.c index dd8e8b282b3..4edc487800b 100644 --- a/dlls/qasf/asfreader.c +++ b/dlls/qasf/asfreader.c @@ -209,16 +209,25 @@ static HRESULT asf_reader_wait_state(struct strmbase_filter *iface, DWORD timeou static HRESULT asf_reader_init_stream(struct strmbase_filter *iface) { struct asf_reader *filter = impl_from_strmbase_filter(iface); + WMT_STREAM_SELECTION selections[ARRAY_SIZE(filter->streams)]; + WORD stream_numbers[ARRAY_SIZE(filter->streams)]; + IWMReaderAdvanced *reader_advanced; HRESULT hr; int i;
TRACE("iface %p\n", iface);
+ if (FAILED(hr = IWMReader_QueryInterface(filter->reader, &IID_IWMReaderAdvanced, (void **)&reader_advanced))) + return hr; + for (i = 0; i < filter->stream_count; ++i) { struct asf_stream *stream = filter->streams + i; IWMOutputMediaProps *props;
+ stream_numbers[i] = i + 1; + selections[i] = WMT_OFF; + if (!stream->source.pin.peer) continue;
@@ -226,14 +235,14 @@ static HRESULT asf_reader_init_stream(struct strmbase_filter *iface) if (FAILED(hr)) { WARN("Failed to commit stream %u allocator, hr %#lx\n", i, hr); - return hr; + break; }
hr = IWMReader_GetOutputFormat(filter->reader, stream->index, 0, &props); if (FAILED(hr)) { WARN("Failed to get stream %u output format, hr %#lx\n", i, hr); - return hr; + break; }
hr = IWMOutputMediaProps_SetMediaType(props, (WM_MEDIA_TYPE *)&stream->source.pin.mt); @@ -243,17 +252,28 @@ static HRESULT asf_reader_init_stream(struct strmbase_filter *iface) if (FAILED(hr)) { WARN("Failed to set stream %u output format, hr %#lx\n", i, hr); - return hr; + break; }
hr = IPin_NewSegment(stream->source.pin.peer, 0, 0, 1); if (FAILED(hr)) { WARN("Failed to start stream %u new segment, hr %#lx\n", i, hr); - return hr; + break; } + + selections[i] = WMT_ON; }
+ if (SUCCEEDED(hr) && FAILED(hr = IWMReaderAdvanced_SetStreamsSelected(reader_advanced, + filter->stream_count, stream_numbers, selections))) + WARN("Failed to set reader %p stream selection, hr %#lx\n", filter->reader, hr); + + IWMReaderAdvanced_Release(reader_advanced); + + if (FAILED(hr)) + return hr; + filter->status = -1; if (FAILED(hr = IWMReader_Start(filter->reader, 0, 0, 1, NULL))) {